Skip to content

Commit

Permalink
1.4.0
Browse files Browse the repository at this point in the history
Improved managers and added the possibility to have data stored and be loaded in for certain managers
  • Loading branch information
App24 committed Apr 24, 2023
1 parent 6c28792 commit b32a3b7
Show file tree
Hide file tree
Showing 16 changed files with 342 additions and 153 deletions.
19 changes: 2 additions & 17 deletions Assets/RicUtils/Editor/ContextMenus/CreateEditorContextMenu.cs
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ public static void Create()
var mono = obj as MonoScript;
var @class = mono.GetClass();
if (@class.IsSubclassOf(typeof(GenericScriptableObject))) scriptableObject = @class.Name;
else if (IsSubclassOfRawGeneric(typeof(AvailableScriptableObject<>), @class)) availableScriptableObject = @class.Name;
else if (RicUtilities.IsSubclassOfRawGeneric(typeof(AvailableScriptableObject<>), @class)) availableScriptableObject = @class.Name;
}

string className = $"{scriptableObject}EditorWindow";
Expand Down Expand Up @@ -54,26 +54,11 @@ public static bool IsValid()
var @class = mono.GetClass();
if (mono.GetClass() == null) continue;
if (@class.IsSubclassOf(typeof(GenericScriptableObject))) hasGenericScriptableObject = true;
else if (IsSubclassOfRawGeneric(typeof(AvailableScriptableObject<>), @class)) hasAvailableScriptableObject = true;
else if (RicUtilities.IsSubclassOfRawGeneric(typeof(AvailableScriptableObject<>), @class)) hasAvailableScriptableObject = true;
}

return hasGenericScriptableObject && hasAvailableScriptableObject;
}

// https://stackoverflow.com/questions/457676/check-if-a-class-is-derived-from-a-generic-class
private static bool IsSubclassOfRawGeneric(System.Type generic, System.Type toCheck)
{
while (toCheck != null && toCheck != typeof(object))
{
var cur = toCheck.IsGenericType ? toCheck.GetGenericTypeDefinition() : toCheck;
if (generic == cur)
{
return true;
}
toCheck = toCheck.BaseType;
}
return false;
}
}

internal class DoCreateEditorAsset : DoCreateScriptAsset
Expand Down
2 changes: 2 additions & 0 deletions Assets/RicUtils/Editor/CreateAvailableScriptableObjects.cs
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,8 @@ public static void CreateAvailableScripts()
{
foreach (var keyValuePair in ToolUtilities.GetScriptableEditors())
{
if (!keyValuePair.IsValid()) continue;
if (keyValuePair.AvailableScriptableObjectType == null) continue;
var path = RicUtilities.GetAvailableScriptableObjectPath(keyValuePair.AvailableScriptableObjectType);
RicUtilities.CreateAssetFolder(path);

Expand Down
2 changes: 1 addition & 1 deletion Assets/RicUtils/Editor/RicUtils_EditorSettings.cs
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ public class RicUtils_EditorSettings : ScriptableObject

public static string version
{
get { return "1.3.0"; }
get { return "1.4.0"; }
}

public static ScriptableEditor[] scriptableEditors
Expand Down
5 changes: 5 additions & 0 deletions Assets/RicUtils/Editor/ScriptableEditor.cs
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,11 @@ public class ScriptableEditor

public System.Type AvailableScriptableObjectType => availableScriptableObjectType;

public bool IsValid()
{
return (CustomScriptableObjectType != null);
}

public bool IsSameKeyType(System.Type type)
{
if (type == null || CustomScriptableObjectType == null) return false;
Expand Down
134 changes: 41 additions & 93 deletions Assets/RicUtils/Editor/Tools/RicUtils_SettingsEditor.cs
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
using RicUtils.Managers;
using System.Collections;
using System.Collections.Generic;
using UnityEditor;
using UnityEditor.VersionControl;
using UnityEditorInternal;
using UnityEngine;

Expand Down Expand Up @@ -95,6 +97,16 @@ private void OnEnable()
EditorGUI.LabelField(rect, Styles.scriptableEditorsListLabel);
};

m_singletonManagersList.elementHeightCallback = index =>
{
var manager = settings.m_singletonManagers[index].manager.Type;
if (RicUtilities.IsSubclassOfRawGeneric(typeof(DataGenericManager<,>), manager))
{
return 42;
}
return 21;
};

m_singletonManagersList.drawElementCallback = (rect, index, isActive, isFocused) =>
{
var element = m_singletonManagersList.serializedProperty.GetArrayElementAtIndex(index);
Expand All @@ -105,6 +117,35 @@ private void OnEnable()
EditorGUI.LabelField(new Rect(rect.x, rect.y, labelWidth, EditorGUIUtility.singleLineHeight), "Manager");
//rect.x += 110;
EditorGUI.PropertyField(new Rect(rect.x + labelWidth, rect.y, width, EditorGUIUtility.singleLineHeight), element.FindPropertyRelative("manager"), GUIContent.none);

var manager = settings.m_singletonManagers[index].manager.Type;
if (RicUtilities.IsSubclassOfRawGeneric(typeof(DataGenericManager<,>), manager))
{
rect.y += EditorGUIUtility.singleLineHeight + 2;
EditorGUI.LabelField(new Rect(rect.x, rect.y, labelWidth, EditorGUIUtility.singleLineHeight), "Data");
GUI.enabled = settings.m_singletonManagers[index].data == null;
if (settings.m_singletonManagers[index].data == null)
{
if (GUI.Button(new Rect(rect.x + labelWidth, rect.y, width, EditorGUIUtility.singleLineHeight), "Create"))
{
RicUtilities.CreateAssetFolder("Assets/ScriptableObject/Managers Data");

var data = ScriptableObject.CreateInstance(manager.BaseType.GenericTypeArguments[1]);
if (!AssetDatabase.Contains(data))
AssetDatabase.CreateAsset(data, $"Assets/ScriptableObject/Managers Data/{manager.Name}_data.asset");

settings.m_singletonManagers[index].data = data as DataManagerScriptableObject;

EditorUtility.SetDirty(settings);
AssetDatabase.SaveAssets();
}
}
else
{
EditorGUI.PropertyField(new Rect(rect.x + labelWidth, rect.y, width, EditorGUIUtility.singleLineHeight), element.FindPropertyRelative("data"), GUIContent.none);
}
GUI.enabled = true;
}
};

m_singletonManagersList.drawHeaderCallback = rect =>
Expand Down Expand Up @@ -166,97 +207,4 @@ private void OnGUI()
}
}
}
/*[CustomEditor(typeof(RicUtils_Settings))]
public class RicUtils_SettingsEditor : UnityEditor.Editor
{
internal class Styles
{
public static readonly GUIContent scriptableEditorsLabel = new GUIContent("Scriptable Editors");
public static readonly GUIContent scriptableEditorsListLabel = new GUIContent("Scriptable Editors List");
public static readonly GUIContent scriptableEditorsAddButtonLabel = new GUIContent("Add Scriptable Editor");
}
private ReorderableList m_List;
private const string k_UndoRedo = "UndoRedoPerformed";
private const string SCRIPTABLE_EDITORS_PATH = "Assets/RicUtils/Editor/Resources/ScriptableEditors";
public void OnEnable()
{
if (target == null)
return;
m_List = new ReorderableList(serializedObject, serializedObject.FindProperty("m_scriptableEditors"), false, true, true, true);
m_List.drawElementCallback = (rect, index, isActive, isFocused) =>
{
var element = m_List.serializedProperty.GetArrayElementAtIndex(index);
rect.y += 2;
float width = 130;
EditorGUI.PropertyField(new Rect(rect.x, rect.y, width, EditorGUIUtility.singleLineHeight), element.FindPropertyRelative("customScriptableObjectType"), GUIContent.none);
EditorGUI.PropertyField(new Rect(rect.x + width + 5, rect.y, width, EditorGUIUtility.singleLineHeight), element.FindPropertyRelative("editorType"), GUIContent.none);
EditorGUI.PropertyField(new Rect(rect.x + ((width + 5) * 2), rect.y, width, EditorGUIUtility.singleLineHeight), element.FindPropertyRelative("availableScriptableObjectType"), GUIContent.none);
/*var temp = element.objectReferenceValue as ScriptableEditor;
if (!temp)
{
EditorGUI.PropertyField(new Rect(rect.x, rect.y, rect.width, EditorGUIUtility.singleLineHeight), element, GUIContent.none);
return;
}
if (temp.serializedObject == null) temp.serializedObject = new SerializedObject(temp);
EditorGUI.PropertyField(new Rect(rect.x, rect.y, width, EditorGUIUtility.singleLineHeight), temp.serializedObject.FindProperty("customScriptableObjectType"), GUIContent.none);
EditorGUI.PropertyField(new Rect(rect.x + width + 5, rect.y, width, EditorGUIUtility.singleLineHeight), temp.serializedObject.FindProperty("editorType"), GUIContent.none);
EditorGUI.PropertyField(new Rect(rect.x + ((width + 5) * 2), rect.y, width, EditorGUIUtility.singleLineHeight), temp.serializedObject.FindProperty("availableScriptableObjectType"), GUIContent.none);
EditorGUI.PropertyField(new Rect(rect.x + ((width + 8) * 3), rect.y, 6, EditorGUIUtility.singleLineHeight), element, GUIContent.none);
temp.serializedObject.ApplyModifiedProperties();
};
m_List.drawHeaderCallback = rect =>
{
EditorGUI.LabelField(rect, Styles.scriptableEditorsListLabel);
};
}
public override void OnInspectorGUI()
{
serializedObject.Update();
string evt_cmd = Event.current.commandName;
float labelWidth = EditorGUIUtility.labelWidth;
float fieldWidth = EditorGUIUtility.fieldWidth;
EditorGUI.indentLevel = 0;
EditorGUILayout.BeginVertical(EditorStyles.helpBox);
GUILayout.Label(Styles.scriptableEditorsLabel, EditorStyles.boldLabel);
m_List.DoLayoutList();
EditorGUI.indentLevel = 0;
EditorGUILayout.Space();
EditorGUILayout.EndVertical();
/*EditorGUILayout.BeginVertical(EditorStyles.helpBox);
if (GUILayout.Button(Styles.scriptableEditorsAddButtonLabel))
{
var old = new List<ScriptableEditor>((target as RicUtils_Settings).m_scriptableEditors);
old.Add(new ScriptableEditor());
(target as RicUtils_Settings).m_scriptableEditors = old.ToArray();
AssetDatabase.SaveAssets();
}
EditorGUILayout.EndVertical();
if (serializedObject.ApplyModifiedProperties() || evt_cmd == k_UndoRedo)
{
EditorUtility.SetDirty(target);
//TMPro_EventManager.ON_TMP_SETTINGS_CHANGED();
}
}
}*/
}
13 changes: 2 additions & 11 deletions Assets/RicUtils/Runtime/Managers/DataGenericManager.cs
Original file line number Diff line number Diff line change
Expand Up @@ -4,17 +4,8 @@

namespace RicUtils.Managers
{
public abstract class DataGenericManager<T> : GenericManager<T> where T : DataGenericManager<T>
public abstract class DataGenericManager<T, D> : SingletonGenericManager<T> where T : DataGenericManager<T, D> where D : DataManagerScriptableObject
{
protected virtual bool DontDestroyGameObjectOnLoad => true;
protected override bool DestroyIfFound => DontDestroyGameObjectOnLoad;

private void Awake()
{
SetInstance();
if (DontDestroyGameObjectOnLoad)
DontDestroyOnLoad(gameObject);
OnCreation();
}
public D data;
}
}

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

21 changes: 6 additions & 15 deletions Assets/RicUtils/Runtime/Managers/GenericManager.cs
Original file line number Diff line number Diff line change
Expand Up @@ -12,29 +12,20 @@ public abstract class GenericManager<T> : MonoBehaviour where T : GenericManager

protected virtual bool DestroyIfFound => true;

internal static void CreateManager()
protected virtual void Awake()
{
var gameObject = new GameObject();
gameObject.name = $"{typeof(T)} Manager";
var comp = gameObject.AddComponent<T>();
comp.SetInstance();
DontDestroyOnLoad(gameObject);
comp.OnCreation();
SetInstance();
}

protected virtual void OnCreation()
protected bool SetInstance()
{

}

protected void SetInstance()
{
if (_instance != null && DestroyIfFound)
if (_instance != null && DestroyIfFound && _instance != this)
{
Destroy(this);
return;
return false;
}
_instance = this as T;
return true;
}
}
}
16 changes: 13 additions & 3 deletions Assets/RicUtils/Runtime/Managers/SingletonCreation.cs
Original file line number Diff line number Diff line change
Expand Up @@ -10,11 +10,21 @@ public static class SingletonCreation
[RuntimeInitializeOnLoadMethod(RuntimeInitializeLoadType.BeforeSceneLoad)]
private static void OnLoad()
{
foreach (var manager in RicUtils_Settings.singletonManagers)
foreach (var singletonManager in RicUtils_Settings.singletonManagers)
{
var type = manager.manager.Type;
var type = singletonManager.manager.Type;
if (type == null)
{
Debug.LogWarning($"Could not find type: {singletonManager.manager.TypeNameAndAssembly}");
continue;
}
var method = type.GetMethod("CreateManager", BindingFlags.Static | BindingFlags.NonPublic | BindingFlags.InvokeMethod | BindingFlags.FlattenHierarchy);
method.Invoke(null, new object[] { });
var manager = method.Invoke(null, new object[] { });
if (RicUtilities.IsSubclassOfRawGeneric(typeof(DataGenericManager<,>), type))
{
type.GetField("data", BindingFlags.Public | BindingFlags.Instance | BindingFlags.NonPublic | BindingFlags.FlattenHierarchy).SetValue(manager, singletonManager.data);
}
type.GetMethod("OnCreation", BindingFlags.Public | BindingFlags.Instance | BindingFlags.NonPublic | BindingFlags.InvokeMethod | BindingFlags.FlattenHierarchy).Invoke(manager, new object[] { });
}
}
}
Expand Down
26 changes: 26 additions & 0 deletions Assets/RicUtils/Runtime/Managers/SingletonGenericManager.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

namespace RicUtils.Managers
{
public abstract class SingletonGenericManager<T> : GenericManager<T> where T : SingletonGenericManager<T>
{
internal static T CreateManager()
{
var gameObject = new GameObject();
gameObject.name = $"{typeof(T)} Manager";
var comp = gameObject.AddComponent<T>();
if (comp.SetInstance())
{
DontDestroyOnLoad(gameObject);
}
return comp;
}

protected virtual void OnCreation()
{

}
}
}
11 changes: 11 additions & 0 deletions Assets/RicUtils/Runtime/Managers/SingletonGenericManager.cs.meta

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

15 changes: 15 additions & 0 deletions Assets/RicUtils/Runtime/RicUtilities.cs
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,21 @@ public static string ToFriendlyCase(this string PascalString)
return Regex.Replace(PascalString, "(?!^)([A-Z])", " $1");
}

// https://stackoverflow.com/questions/457676/check-if-a-class-is-derived-from-a-generic-class
public static bool IsSubclassOfRawGeneric(System.Type generic, System.Type toCheck)
{
while (toCheck != null && toCheck != typeof(object))
{
var cur = toCheck.IsGenericType ? toCheck.GetGenericTypeDefinition() : toCheck;
if (generic == cur)
{
return true;
}
toCheck = toCheck.BaseType;
}
return false;
}

#if UNITY_EDITOR
public static void CreateAssetFolder(string folderPath)
{
Expand Down
4 changes: 3 additions & 1 deletion Assets/RicUtils/Runtime/SingletonManager.cs
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,9 @@ namespace RicUtils
[System.Serializable]
public class SingletonManager
{
[Inherits(typeof(GenericManager<>), ShortName = true, AllowAbstract = false, IncludeBaseType = false, ShowAllTypes = true)]
[Inherits(typeof(SingletonGenericManager<>), ShortName = true, AllowAbstract = false, IncludeBaseType = false, ShowAllTypes = true)]
public TypeReference manager;

public DataManagerScriptableObject data;
}
}
2 changes: 1 addition & 1 deletion Assets/RicUtils/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "io.github.app24.ricutils",
"version": "1.3.0",
"version": "1.4.0",
"displayName": "RicUtils",
"dependencies": {
"com.solidalloy.type-references": "2.16.0"
Expand Down
Loading

0 comments on commit b32a3b7

Please sign in to comment.