// Copyright (c) 2025 EFramework Innovation. All rights reserved.
// Use of this source code is governed by a MIT-style
// license that can be found in the LICENSE file.
using UnityEngine;
using EFramework.Unity.Utility;
namespace EFramework.Unity.Asset
{
public partial class XAsset
{
///
/// XAsset.Preferences 提供了运行时的首选项管理,用于控制运行模式、调试选项和资源路径等配置项。
///
///
///
/// 功能特性
/// - 运行模式配置:支持 AssetBundle 和 Resources 模式切换
/// - 调试选项管理:支持调试模式和模拟模式的切换
/// - 资源路径配置:支持配置内置、本地和远端资源路径
/// - 可视化配置界面:在 Unity 编辑器中提供直观的设置面板
///
/// 使用手册
/// | 配置项 | 配置键 | 默认值 | 功能说明 |
/// |--------|--------|--------|----------|
/// | Bundle 模式 | `Asset/BundleMode` | `true` | 控制是否启用 AssetBundle 模式,启用后将从打包的资源文件加载资源 |
/// | 引用计数模式 | `Asset/ReferMode` | `true` | 控制是否启用引用计数模式,启用后会自动跟踪资源引用,确保资源正确释放 |
/// | 调试模式 | `Asset/DebugMode` | `false` | 控制是否启用调试模式,启用后会输出详细的资源加载和释放日志 |
/// | 模拟模式 | `Asset/SimulateMode@Editor` | `false` | 控制是否启用模拟模式,仅在编辑器中可用,模拟 AssetBundle 的资源加载行为 |
/// | 文件偏移 | `Asset/OffsetFactor` | `4` | 设置资源包的头部偏移算子,用于进行简单的 AssetBundle 资源加密 |
/// | 内置资源路径 | `Asset/AssetUri` | `Patch@Assets.zip` | 设置资源包的内置路径,用于打包时的处理 |
/// | 本地资源路径 | `Asset/LocalUri` | `Assets` | 设置资源包的本地路径,用于运行时的加载 |
/// | 远端资源路径 | `Asset/RemoteUri` | `Builds/Patch/${Environment.Author}/${Environment.Version}/${Environment.Platform}/Assets` | 设置资源包的远端路径,用于运行时的下载 |
///
/// 更多信息请参考模块文档。
///
public partial class Preferences : ScriptableObject, XPrefs.IEditor
{
///
/// BundleMode 是 Bundle 模式开关的配置键。
/// 启用后将从打包的资源文件加载资源,否则使用Resources加载。
///
public const string BundleMode = "XAsset/BundleMode";
///
/// BundleModeDefault 是 Bundle 模式的默认值,默认开启以支持资源打包加载。
///
public const bool BundleModeDefault = true;
///
/// ReferMode 是引用计数模式的配置键。
/// 启用后会自动跟踪资源引用,确保资源正确释放。
///
public const string ReferMode = "XAsset/ReferMode";
///
/// ReferModeDefault 是引用计数模式的默认值,默认开启以防止资源泄漏
///
public const bool ReferModeDefault = true;
///
/// DebugMode 是调试模式的配置键。
/// 启用后会输出详细的资源加载和释放日志。
///
public const string DebugMode = "XAsset/DebugMode";
///
/// SimulateMode 是编辑器模拟模式的配置键。
/// 在编辑器中可以模拟Bundle模式的资源加载,方便测试。
///
public const string SimulateMode = "XAsset/SimulateMode@Editor";
///
/// OffsetFactor 是 Bundle 文件偏移的配置键。
///
public const string OffsetFactor = "XAsset/OffsetFactor";
///
/// OffsetFactorDefault 是 Bundle 文件偏移的默认值。
///
public const int OffsetFactorDefault = 4;
///
/// AssetUri 是资源包文件名的配置键。
/// 用于指定打包后的资源文件名称。
///
public const string AssetUri = "XAsset/AssetUri";
///
/// AssetUriDefault 是资源包的默认文件名。
///
public const string AssetUriDefault = "Patch@Assets.zip";
///
/// LocalUri 是本地资源路径的配置键,指定资源文件在本地存储的相对路径。
///
public const string LocalUri = "XAsset/LocalUri";
///
/// LocalUriDefault 是本地资源的默认存储路径。
///
public const string LocalUriDefault = "Assets";
///
/// RemoteUri 是远程资源地址的配置键,用于指定资源更新的远程服务器地址。
///
public const string RemoteUri = "XAsset/RemoteUri";
///
/// RemoteUriDefault 是远程资源的默认下载地址,支持变量求值。
///
public const string RemoteUriDefault = "Builds/Patch/${Environment.Author}/${Environment.Version}/${Environment.Platform}/Assets";
public virtual string Section => "XAsset";
public virtual string Tooltip => "Preferences of XAsset.";
public virtual bool Foldable => true;
public virtual int Priority => 100;
[SerializeField] protected bool foldout;
public virtual void OnActivate(string searchContext, UnityEngine.UIElements.VisualElement rootElement, XPrefs.IBase context) { }
public virtual void OnVisualize(string searchContext, XPrefs.IBase context)
{
#if UNITY_EDITOR
var bundleMode = context.GetBool(BundleMode, BundleModeDefault);
UnityEditor.EditorGUILayout.BeginVertical(UnityEditor.EditorStyles.helpBox);
UnityEditor.EditorGUILayout.BeginHorizontal();
GUILayout.Label(new GUIContent("Bundle", "Switch to AssetBundle/Resources Mode."), GUILayout.Width(60));
bundleMode = UnityEditor.EditorGUILayout.Toggle(bundleMode);
context.Set(BundleMode, bundleMode);
var ocolor = GUI.color;
if (!bundleMode) GUI.color = Color.gray;
GUILayout.Label(new GUIContent("Refer", "Auto Manage References."), GUILayout.Width(60));
var referMode = UnityEditor.EditorGUILayout.Toggle(context.GetBool(ReferMode, ReferModeDefault));
if (bundleMode) context.Set(ReferMode, referMode);
UnityEditor.EditorGUILayout.EndHorizontal();
UnityEditor.EditorGUILayout.BeginHorizontal();
GUILayout.Label(new GUIContent("Debug", "Switch to Debug/Release Mode."), GUILayout.Width(60));
var debugMode = UnityEditor.EditorGUILayout.Toggle(context.GetBool(DebugMode));
if (bundleMode) context.Set(DebugMode, debugMode);
GUILayout.Label(new GUIContent("Simulate", "Simulate to Load AssetBundle."), GUILayout.Width(60));
var simulateMode = UnityEditor.EditorGUILayout.Toggle(context.GetBool(SimulateMode));
if (bundleMode) context.Set(SimulateMode, simulateMode);
UnityEditor.EditorGUILayout.EndHorizontal();
UnityEditor.EditorGUILayout.BeginHorizontal();
GUILayout.Label(new GUIContent("Offset", "Asset Bundle Offset Factor."), GUILayout.Width(60));
var offsetFactor = UnityEditor.EditorGUILayout.IntField(context.GetInt(OffsetFactor, OffsetFactorDefault));
if (bundleMode) context.Set(OffsetFactor, offsetFactor);
UnityEditor.EditorGUILayout.EndHorizontal();
UnityEditor.EditorGUILayout.BeginHorizontal();
GUILayout.Label(new GUIContent("Asset", "Asset Uri of Assets."), GUILayout.Width(60));
var assetFile = UnityEditor.EditorGUILayout.TextField("", context.GetString(AssetUri, AssetUriDefault));
if (bundleMode) context.Set(AssetUri, assetFile);
UnityEditor.EditorGUILayout.EndHorizontal();
UnityEditor.EditorGUILayout.BeginHorizontal();
GUILayout.Label(new GUIContent("Local", "Local Uri of Assets."), GUILayout.Width(60));
var localPath = UnityEditor.EditorGUILayout.TextField("", context.GetString(LocalUri, LocalUriDefault));
if (bundleMode) context.Set(LocalUri, localPath);
UnityEditor.EditorGUILayout.EndHorizontal();
UnityEditor.EditorGUILayout.BeginHorizontal();
GUILayout.Label(new GUIContent("Remote", "Remote Uri of Assets."), GUILayout.Width(60));
var remoteUri = UnityEditor.EditorGUILayout.TextField("", context.GetString(RemoteUri, RemoteUriDefault));
if (bundleMode) context.Set(RemoteUri, remoteUri);
UnityEditor.EditorGUILayout.EndHorizontal();
GUI.color = ocolor;
UnityEditor.EditorGUILayout.EndVertical();
#endif
}
public virtual void OnDeactivate(XPrefs.IBase context) { }
public virtual bool OnSave(XPrefs.IBase context) { return true; }
public virtual bool OnApply(XPrefs.IBase context) { return true; }
public virtual bool OnBuild(XPrefs.IBase context) { return true; }
}
}
}