220 lines
6.8 KiB
C#
220 lines
6.8 KiB
C#
using System;
|
|
using System.Linq;
|
|
using System.Reflection;
|
|
using UnityEngine;
|
|
using Object = UnityEngine.Object;
|
|
#if UNITY_EDITOR
|
|
using UnityEditor;
|
|
using UnityEditor.Build;
|
|
using UnityEditor.Build.Reporting;
|
|
#endif
|
|
|
|
namespace Coffee.UIParticleInternal
|
|
{
|
|
public abstract class PreloadedProjectSettings : ScriptableObject
|
|
#if UNITY_EDITOR
|
|
{
|
|
private class PreprocessBuildWithReport : IPreprocessBuildWithReport
|
|
{
|
|
int IOrderedCallback.callbackOrder => 0;
|
|
|
|
void IPreprocessBuildWithReport.OnPreprocessBuild(BuildReport report)
|
|
{
|
|
Initialize();
|
|
}
|
|
}
|
|
|
|
[InitializeOnLoadMethod]
|
|
[InitializeOnEnterPlayMode]
|
|
private static void Initialize()
|
|
{
|
|
const BindingFlags flags = BindingFlags.Public | BindingFlags.Static | BindingFlags.FlattenHierarchy;
|
|
foreach (var t in TypeCache.GetTypesDerivedFrom(typeof(PreloadedProjectSettings<>)))
|
|
{
|
|
var defaultSettings = GetDefaultSettings(t);
|
|
if (!defaultSettings)
|
|
{
|
|
// When create a new instance, automatically set it as default settings.
|
|
defaultSettings = t.GetProperty("instance", flags)
|
|
?.GetValue(null, null) as PreloadedProjectSettings;
|
|
}
|
|
else if (GetPreloadedSettings(t).Length != 1)
|
|
{
|
|
SetDefaultSettings(defaultSettings);
|
|
}
|
|
}
|
|
|
|
EditorApplication.QueuePlayerLoopUpdate();
|
|
}
|
|
|
|
protected static string GetDefaultName(Type type, bool nicify)
|
|
{
|
|
var typeName = type.Name.Replace("ProjectSettings", "");
|
|
return nicify
|
|
? ObjectNames.NicifyVariableName(typeName)
|
|
: typeName;
|
|
}
|
|
|
|
private static Object[] GetPreloadedSettings(Type type)
|
|
{
|
|
return PlayerSettings.GetPreloadedAssets()
|
|
.Where(x => x && x.GetType() == type)
|
|
.ToArray();
|
|
}
|
|
|
|
protected static PreloadedProjectSettings GetDefaultSettings(Type type)
|
|
{
|
|
return GetPreloadedSettings(type).FirstOrDefault() as PreloadedProjectSettings
|
|
?? AssetDatabase.FindAssets($"t:{nameof(PreloadedProjectSettings)}")
|
|
.Select(AssetDatabase.GUIDToAssetPath)
|
|
.Select(AssetDatabase.LoadAssetAtPath<PreloadedProjectSettings>)
|
|
.FirstOrDefault(x => x && x.GetType() == type);
|
|
}
|
|
|
|
protected static void SetDefaultSettings(PreloadedProjectSettings asset)
|
|
{
|
|
if (!asset) return;
|
|
var type = asset.GetType();
|
|
if (string.IsNullOrEmpty(AssetDatabase.GetAssetPath(asset)))
|
|
{
|
|
if (!AssetDatabase.IsValidFolder("Assets/ProjectSettings"))
|
|
{
|
|
AssetDatabase.CreateFolder("Assets", "ProjectSettings");
|
|
}
|
|
|
|
var assetPath = $"Assets/ProjectSettings/{GetDefaultName(type, false)}.asset";
|
|
assetPath = AssetDatabase.GenerateUniqueAssetPath(assetPath);
|
|
AssetDatabase.CreateAsset(asset, assetPath);
|
|
}
|
|
|
|
var preloadedAssets = PlayerSettings.GetPreloadedAssets();
|
|
var projectSettings = GetPreloadedSettings(type);
|
|
PlayerSettings.SetPreloadedAssets(preloadedAssets
|
|
.Where(x => x)
|
|
.Except(projectSettings.Except(new[] { asset }))
|
|
.Append(asset)
|
|
.Distinct()
|
|
.ToArray());
|
|
|
|
AssetDatabase.Refresh();
|
|
}
|
|
}
|
|
#else
|
|
{
|
|
}
|
|
#endif
|
|
|
|
public abstract class PreloadedProjectSettings<T> : PreloadedProjectSettings
|
|
where T : PreloadedProjectSettings<T>
|
|
{
|
|
private static T s_Instance;
|
|
|
|
#if UNITY_EDITOR
|
|
private string _jsonText;
|
|
|
|
public static T instance
|
|
{
|
|
get
|
|
{
|
|
if (s_Instance) return s_Instance;
|
|
|
|
s_Instance = GetDefaultSettings(typeof(T)) as T;
|
|
if (s_Instance) return s_Instance;
|
|
|
|
s_Instance = CreateInstance<T>();
|
|
if (!s_Instance)
|
|
{
|
|
s_Instance = null;
|
|
return s_Instance;
|
|
}
|
|
|
|
SetDefaultSettings(s_Instance);
|
|
return s_Instance;
|
|
}
|
|
}
|
|
|
|
private void OnPlayModeStateChanged(PlayModeStateChange state)
|
|
{
|
|
switch (state)
|
|
{
|
|
case PlayModeStateChange.ExitingEditMode:
|
|
_jsonText = EditorJsonUtility.ToJson(this);
|
|
break;
|
|
case PlayModeStateChange.ExitingPlayMode:
|
|
if (_jsonText != null)
|
|
{
|
|
EditorJsonUtility.FromJsonOverwrite(_jsonText, this);
|
|
_jsonText = null;
|
|
}
|
|
|
|
break;
|
|
}
|
|
}
|
|
#else
|
|
public static T instance => s_Instance ? s_Instance : s_Instance = CreateInstance<T>();
|
|
#endif
|
|
|
|
/// <summary>
|
|
/// This function is called when the object becomes enabled and active.
|
|
/// </summary>
|
|
protected virtual void OnEnable()
|
|
{
|
|
#if UNITY_EDITOR
|
|
var isDefaultSettings = !s_Instance || s_Instance == this || GetDefaultSettings(typeof(T)) == this;
|
|
if (!isDefaultSettings)
|
|
{
|
|
DestroyImmediate(this, true);
|
|
return;
|
|
}
|
|
|
|
EditorApplication.playModeStateChanged += OnPlayModeStateChanged;
|
|
#endif
|
|
|
|
if (s_Instance) return;
|
|
s_Instance = this as T;
|
|
}
|
|
|
|
/// <summary>
|
|
/// This function is called when the behaviour becomes disabled.
|
|
/// </summary>
|
|
protected virtual void OnDisable()
|
|
{
|
|
#if UNITY_EDITOR
|
|
EditorApplication.playModeStateChanged -= OnPlayModeStateChanged;
|
|
#endif
|
|
if (s_Instance != this) return;
|
|
|
|
s_Instance = null;
|
|
}
|
|
|
|
#if UNITY_EDITOR
|
|
protected sealed class PreloadedProjectSettingsProvider : SettingsProvider
|
|
{
|
|
private Editor _editor;
|
|
private PreloadedProjectSettings<T> _target;
|
|
|
|
public PreloadedProjectSettingsProvider(string path) : base(path, SettingsScope.Project)
|
|
{
|
|
}
|
|
|
|
public override void OnGUI(string searchContext)
|
|
{
|
|
if (!_target)
|
|
{
|
|
if (_editor)
|
|
{
|
|
DestroyImmediate(_editor);
|
|
_editor = null;
|
|
}
|
|
|
|
_target = instance;
|
|
_editor = Editor.CreateEditor(_target);
|
|
}
|
|
|
|
_editor.OnInspectorGUI();
|
|
}
|
|
}
|
|
#endif
|
|
}
|
|
}
|