diff --git a/Assets/Labrys/Editor/FeatureEditor/FeatureEditorWindow.cs b/Assets/Labrys/Editor/FeatureEditor/FeatureEditorWindow.cs index 99a758d..82837cc 100644 --- a/Assets/Labrys/Editor/FeatureEditor/FeatureEditorWindow.cs +++ b/Assets/Labrys/Editor/FeatureEditor/FeatureEditorWindow.cs @@ -22,7 +22,7 @@ public static FeatureEditorWindow GetInstance() return instance; } - [MenuItem("Window/Labrys Feature Editor")] + [MenuItem("Window/Labrys/Feature Editor")] private static FeatureEditorWindow OpenWindow() { FeatureEditorWindow window = GetWindow(); diff --git a/Assets/Labrys/Editor/FeatureLibraryInspector.cs b/Assets/Labrys/Editor/FeatureLibraryInspector.cs new file mode 100644 index 0000000..32135e3 --- /dev/null +++ b/Assets/Labrys/Editor/FeatureLibraryInspector.cs @@ -0,0 +1,51 @@ +using UnityEngine; +using UnityEditor; +using UnityEditor.AnimatedValues; + +namespace Labrys.Editor +{ + [CustomEditor(typeof(FeatureLibrary))] + public class FeatureLibraryInspector : UnityEditor.Editor + { + private AnimBool fadeGroupVal = new AnimBool(false); + + public void OnEnable() + { + fadeGroupVal.valueChanged.AddListener(Repaint); + } + + public override void OnInspectorGUI() + { + serializedObject.UpdateIfRequiredOrScript(); + FeatureLibrary library = (FeatureLibrary)serializedObject.targetObject; + + EditorGUILayout.SelectableLabel(library.TargetDirectory); + + if (GUILayout.Button("Refresh")) + { + Undo.RegisterCompleteObjectUndo(library, "Feature Library Refresh"); + library.Refresh(); + EditorUtility.SetDirty(library); + } + + GUILayout.Space(25); + if (GUILayout.Button(fadeGroupVal.value ? "Hide contents" : "Show contents")) + fadeGroupVal.target = !fadeGroupVal.value; + if (EditorGUILayout.BeginFadeGroup(fadeGroupVal.faded)) + { + foreach (FeatureLibrary.Entry entry in library) + { + EditorGUILayout.BeginHorizontal(); + Debug.Log($"{entry.FaID}: {entry.Name}"); + EditorGUILayout.SelectableLabel($"{entry.FaID}: {entry.Name}", GUILayout.Height(20)); + if (GUILayout.Button("-->")) + { + ProjectWindowUtil.ShowCreatedAsset(entry.Feature); + } + EditorGUILayout.EndHorizontal(); + } + } + EditorGUILayout.EndFadeGroup(); + } + } +} \ No newline at end of file diff --git a/Assets/Labrys/Editor/FeatureLibraryInspector.cs.meta b/Assets/Labrys/Editor/FeatureLibraryInspector.cs.meta new file mode 100644 index 0000000..ddbbd38 --- /dev/null +++ b/Assets/Labrys/Editor/FeatureLibraryInspector.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: c9c61dcb6aa00284a8a5e4bb17abb6b6 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Labrys/FeatureEditor/TestFeature.asset b/Assets/Labrys/FeatureEditor/TestFeature.asset deleted file mode 100644 index 8e5a132..0000000 --- a/Assets/Labrys/FeatureEditor/TestFeature.asset +++ /dev/null @@ -1,132 +0,0 @@ -%YAML 1.1 -%TAG !u! tag:unity3d.com,2011: ---- !u!114 &11400000 -MonoBehaviour: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 0} - m_Enabled: 1 - m_EditorHideFlags: 0 - m_Script: {fileID: 11500000, guid: f132721a9c505654498a40770d09b4af, type: 3} - m_Name: TestFeature - m_EditorClassIdentifier: - sectionPositions: - - {x: -2, y: -2} - - {x: -2, y: 0} - - {x: -2, y: 2} - - {x: 0, y: 2} - - {x: 2, y: 2} - - {x: 2, y: 0} - - {x: 2, y: -2} - - {x: 0, y: -2} - sectionData: - - variant: Regular - fields: - - k__BackingField: hasChest - k__BackingField: false - - variant: Regular - fields: - - k__BackingField: hasChest - k__BackingField: false - - variant: Regular - fields: - - k__BackingField: hasChest - k__BackingField: false - - variant: Regular - fields: - - k__BackingField: hasChest - k__BackingField: false - - variant: Regular - fields: - - k__BackingField: hasChest - k__BackingField: false - - variant: Regular - fields: - - k__BackingField: hasChest - k__BackingField: false - - variant: ChestRoom - fields: - - k__BackingField: hasChest - k__BackingField: true - - variant: Regular - fields: - - k__BackingField: hasChest - k__BackingField: false - linkPositions: - - {x: -1, y: -2} - - {x: -2, y: -1} - - {x: -3, y: -2} - - {x: -2, y: -3} - - {x: -1, y: 0} - - {x: -2, y: 1} - - {x: -3, y: 0} - - {x: -1, y: 2} - - {x: -2, y: 3} - - {x: -3, y: 2} - - {x: 1, y: 2} - - {x: 0, y: 3} - - {x: 0, y: 1} - - {x: 3, y: 2} - - {x: 2, y: 3} - - {x: 2, y: 1} - - {x: 3, y: 0} - - {x: 1, y: 0} - - {x: 2, y: -1} - - {x: 3, y: -2} - - {x: 1, y: -2} - - {x: 2, y: -3} - - {x: 0, y: -1} - - {x: 0, y: -3} - linkData: - - open: 1 - external: 0 - - open: 1 - external: 0 - - open: 1 - external: 1 - - open: 1 - external: 1 - - open: 1 - external: 1 - - open: 1 - external: 0 - - open: 1 - external: 1 - - open: 1 - external: 0 - - open: 1 - external: 1 - - open: 1 - external: 1 - - open: 1 - external: 0 - - open: 1 - external: 1 - - open: 1 - external: 1 - - open: 1 - external: 1 - - open: 1 - external: 1 - - open: 1 - external: 0 - - open: 1 - external: 1 - - open: 1 - external: 1 - - open: 1 - external: 0 - - open: 1 - external: 1 - - open: 1 - external: 0 - - open: 1 - external: 1 - - open: 1 - external: 1 - - open: 1 - external: 1 - selectionPositions: - - {x: 2, y: -2} diff --git a/Assets/Labrys/FeatureEditor/TestFeature.asset.meta b/Assets/Labrys/FeatureEditor/TestFeature.asset.meta deleted file mode 100644 index 46a13d3..0000000 --- a/Assets/Labrys/FeatureEditor/TestFeature.asset.meta +++ /dev/null @@ -1,8 +0,0 @@ -fileFormatVersion: 2 -guid: 3c9906764ccf06948a8aab32a03352b4 -NativeFormatImporter: - externalObjects: {} - mainObjectFileID: 11400000 - userData: - assetBundleName: - assetBundleVariant: diff --git a/Assets/Labrys/FeatureLibrary.cs b/Assets/Labrys/FeatureLibrary.cs new file mode 100644 index 0000000..bf0b0f4 --- /dev/null +++ b/Assets/Labrys/FeatureLibrary.cs @@ -0,0 +1,195 @@ +using Labrys.FeatureEditor; +using System; +using System.Collections; +using System.Collections.Generic; +using System.IO; +#if UNITY_EDITOR +using UnityEditor; +#endif +using UnityEngine; + +namespace Labrys +{ + public class FeatureLibrary : ScriptableObject, IEnumerable, ISerializationCallbackReceiver, ICloneable + { + [field: SerializeField] + public string TargetDirectory { get; private set; } + + private Dictionary nameToFAID; + private FeatureAsset[] features; + + public int Count => features.Length; + + public FeatureAsset this[ushort faid] => Contains(faid) ? features[faid] : null; + + public FeatureAsset this[string name] + { + get => this[GetId(name)]; + private set => Add(name, value); + } + +#if UNITY_EDITOR + [MenuItem("Assets/Create/Labrys/Feature Library")] + private static void Create() + { + string saveDir = AssetDatabase.GetAssetPath(Selection.activeInstanceID); + if (!File.GetAttributes(saveDir).HasFlag(FileAttributes.Directory)) + saveDir = saveDir.Replace(Path.GetFileName(saveDir), ""); + + string loadPath = $"Assets{EditorUtility.OpenFolderPanel("Select target Feature folder", saveDir, "").Replace(Application.dataPath, "")}"; + string savePath = $"{saveDir}/NewFeatureLibrary.asset"; + + FeatureLibrary library = CreateInstance(); + library.TargetDirectory = loadPath; + library.Refresh(); + + ProjectWindowUtil.CreateAsset(library, savePath); + } + + public void Refresh() + { + string[] assetGUIDs = AssetDatabase.FindAssets($"t:{nameof(FeatureAsset)}", new string[] { TargetDirectory }); + nameToFAID = new Dictionary(); + features = new FeatureAsset[assetGUIDs.Length]; + + foreach (string guid in assetGUIDs) + { + string path = AssetDatabase.GUIDToAssetPath(guid); + Add(path.Replace(TargetDirectory, "").Replace(".asset", "").TrimStart('/'), + AssetDatabase.LoadAssetAtPath(path)); + } + } +#endif + private FeatureLibrary() + { + nameToFAID = new Dictionary(); + features = new FeatureAsset[0]; + } + + private bool Add(string name, FeatureAsset feature) + { + if (name == null || feature == null) + return false; + + features[nameToFAID.Count] = feature; + nameToFAID.Add(name, (ushort)nameToFAID.Count); + + return true; + } + + public FeatureAsset GetFeature(string name) => this[name]; + + public FeatureAsset GetFeature(ushort faid) => this[faid]; + + public bool Contains(string name) => nameToFAID.ContainsKey(name); + + public bool Contains(ushort faid) => 0 <= faid && faid < features.Length; + + public ushort GetId(string name) + { + if (nameToFAID.TryGetValue(name, out ushort faid)) + { + return faid; + } + throw new ArgumentException($"Unknown name: {name}."); + } + + public IEnumerator GetEnumerator() + { + if (nameToFAID == null) + yield break; + + foreach(KeyValuePair entry in nameToFAID) + { + yield return new Entry(entry.Value, entry.Key, this[entry.Value]); + } + } + + IEnumerator IEnumerable.GetEnumerator() + { + return GetEnumerator(); + } + + public object Clone() + { + FeatureLibrary clone = CreateInstance(); + + clone.TargetDirectory = TargetDirectory; + + clone.features = new FeatureAsset[features.Length]; + Array.Copy(features, clone.features, features.Length); + + clone.nameToFAID = new Dictionary(); + foreach(KeyValuePair pair in nameToFAID) + { + clone.nameToFAID.Add(pair.Key, pair.Value); + } + + return clone; + } + + public override string ToString() + { + string str = ""; + + foreach(Entry e in this) + { + str += $"{{faid: {e.FaID}, name: {e.Name}, feature: {e.Feature.ToString()}}}\n"; + } + + return $"TargetDirectory: {TargetDirectory}, Contents: [\n{str}\n]"; + } + + public struct Entry + { + public ushort FaID { get; } + public string Name { get; } + public FeatureAsset Feature { get; } + + public Entry(ushort faid, string name, FeatureAsset feature) + { + FaID = faid; + Name = name; + Feature = feature; + } + } + + #region SERIALIZATION + [SerializeField] + private List serializedNames; + [SerializeField] + private List serializedFeatures; + + public void OnBeforeSerialize() + { + if (nameToFAID == null || features == null) + return; + + serializedNames = new List(); + serializedFeatures = new List(); + foreach(KeyValuePair pair in nameToFAID) + { + serializedNames.Add(pair.Key); + serializedFeatures.Add(features[pair.Value]); + } + } + + public void OnAfterDeserialize() + { + if (serializedNames == null + || serializedFeatures == null + || serializedNames.Count != serializedFeatures.Count) + return; + + nameToFAID = new Dictionary(); + features = new FeatureAsset[serializedFeatures.Count]; + for (int i = 0; i < serializedNames.Count; i++) + { + Add(serializedNames[i], serializedFeatures[i]); + } + serializedNames = null; + serializedFeatures = null; + } + #endregion + } +} \ No newline at end of file diff --git a/Assets/Labrys/FeatureLibrary.cs.meta b/Assets/Labrys/FeatureLibrary.cs.meta new file mode 100644 index 0000000..3e5e9a7 --- /dev/null +++ b/Assets/Labrys/FeatureLibrary.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 56cac0c8c64b38c47bc5fc13147ebc83 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Test.asset b/Assets/Test.asset deleted file mode 100644 index 3eff857..0000000 --- a/Assets/Test.asset +++ /dev/null @@ -1,14 +0,0 @@ -%YAML 1.1 -%TAG !u! tag:unity3d.com,2011: ---- !u!114 &11400000 -MonoBehaviour: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 0} - m_Enabled: 1 - m_EditorHideFlags: 0 - m_Script: {fileID: 11500000, guid: 2304350bd412e4faba5b8135efded78c, type: 3} - m_Name: Test - m_EditorClassIdentifier: diff --git a/Assets/Test.asset.meta b/Assets/Test.asset.meta deleted file mode 100644 index 51d7d23..0000000 --- a/Assets/Test.asset.meta +++ /dev/null @@ -1,8 +0,0 @@ -fileFormatVersion: 2 -guid: 48d69f246df4a4ed2845ad8e6cff9387 -NativeFormatImporter: - externalObjects: {} - mainObjectFileID: 11400000 - userData: - assetBundleName: - assetBundleVariant: