diff --git a/Assets/Editor/Editor Windows/ConfigTypeSelectionPopup.cs b/Assets/Editor/Editor Windows/ConfigTypeSelectionPopup.cs new file mode 100644 index 0000000..09f4707 --- /dev/null +++ b/Assets/Editor/Editor Windows/ConfigTypeSelectionPopup.cs @@ -0,0 +1,63 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using UnityEditor; +using UnityEngine; + +namespace ScriptableObjectManager +{ + + // Custom Popup Window for Config Type Selection + internal class ConfigTypeSelectionPopup : PopupWindowContent + { + private readonly List SelectedTypes; + private readonly List AvailableTypes; + private readonly Action OnSelectionChanged; + private Vector2 ScrollPos = new(); + + public ConfigTypeSelectionPopup(List selectedTypes, Action onSelectionChanged, List availableTypes) + { + this.SelectedTypes = selectedTypes; + this.OnSelectionChanged = onSelectionChanged; + this.AvailableTypes = availableTypes; + } + + public override Vector2 GetWindowSize() + { + return new Vector2(200, 400); // Define the dimensions of the popup window + } + + public override void OnGUI(Rect rect) + { + GUILayout.Label("Select Config Types", EditorStyles.boldLabel); + + if (AvailableTypes.Count > 0) + { + ScrollPos = EditorGUILayout.BeginScrollView(ScrollPos); + + // Display each available type with a toggle to enable or disable it + foreach (var type in AvailableTypes) + { + bool isSelected = SelectedTypes.Contains(type); + bool toggle = EditorGUILayout.Toggle(type.Name, isSelected); + + if (toggle && !isSelected) + { + SelectedTypes.Add(type); // Add the type to the selection list + OnSelectionChanged.Invoke(); + ScriptableObjectEditorWindow.BasicFilters = SelectedTypes.Select(t => t.Name).ToArray(); + } + else if (!toggle && isSelected) + { + SelectedTypes.Remove(type); // Remove the type from the selection list + OnSelectionChanged.Invoke(); + ScriptableObjectEditorWindow.BasicFilters = SelectedTypes.Select(t => t.Name).ToArray(); + } + } + // Close the scrollable area within the popup + EditorGUILayout.EndScrollView(); + } + } + } + +} diff --git a/Assets/Editor/Editor Windows/ConfigTypeSelectionPopup.cs.meta b/Assets/Editor/Editor Windows/ConfigTypeSelectionPopup.cs.meta new file mode 100644 index 0000000..06bb933 --- /dev/null +++ b/Assets/Editor/Editor Windows/ConfigTypeSelectionPopup.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 4b7d03e7a1e149747ba47b250170c625 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Editor/Editor Windows/Icons/check.png b/Assets/Editor/Editor Windows/Icons/check.png new file mode 100644 index 0000000..7fdd200 Binary files /dev/null and b/Assets/Editor/Editor Windows/Icons/check.png differ diff --git a/Assets/Editor/Editor Windows/Icons/check.png.meta b/Assets/Editor/Editor Windows/Icons/check.png.meta new file mode 100644 index 0000000..f98b568 --- /dev/null +++ b/Assets/Editor/Editor Windows/Icons/check.png.meta @@ -0,0 +1,127 @@ +fileFormatVersion: 2 +guid: 0b1630592316867468f0cd45b7397c03 +TextureImporter: + internalIDToNameTable: [] + externalObjects: {} + serializedVersion: 13 + mipmaps: + mipMapMode: 0 + enableMipMap: 0 + sRGBTexture: 1 + linearTexture: 0 + fadeOut: 0 + borderMipMap: 0 + mipMapsPreserveCoverage: 0 + alphaTestReferenceValue: 0.5 + mipMapFadeDistanceStart: 1 + mipMapFadeDistanceEnd: 3 + bumpmap: + convertToNormalMap: 0 + externalNormalMap: 0 + heightScale: 0.25 + normalMapFilter: 0 + flipGreenChannel: 0 + isReadable: 0 + streamingMipmaps: 0 + streamingMipmapsPriority: 0 + vTOnly: 0 + ignoreMipmapLimit: 0 + grayScaleToAlpha: 0 + generateCubemap: 6 + cubemapConvolution: 0 + seamlessCubemap: 0 + textureFormat: 1 + maxTextureSize: 2048 + textureSettings: + serializedVersion: 2 + filterMode: 1 + aniso: 1 + mipBias: 0 + wrapU: 1 + wrapV: 1 + wrapW: 0 + nPOTScale: 0 + lightmap: 0 + compressionQuality: 50 + spriteMode: 1 + spriteExtrude: 1 + spriteMeshType: 1 + alignment: 0 + spritePivot: {x: 0.5, y: 0.5} + spritePixelsToUnits: 100 + spriteBorder: {x: 0, y: 0, z: 0, w: 0} + spriteGenerateFallbackPhysicsShape: 1 + alphaUsage: 1 + alphaIsTransparency: 1 + spriteTessellationDetail: -1 + textureType: 8 + textureShape: 1 + singleChannelComponent: 0 + flipbookRows: 1 + flipbookColumns: 1 + maxTextureSizeSet: 0 + compressionQualitySet: 0 + textureFormatSet: 0 + ignorePngGamma: 0 + applyGammaDecoding: 0 + swizzle: 50462976 + cookieLightType: 0 + platformSettings: + - serializedVersion: 3 + buildTarget: DefaultTexturePlatform + maxTextureSize: 2048 + resizeAlgorithm: 0 + textureFormat: -1 + textureCompression: 1 + compressionQuality: 50 + crunchedCompression: 0 + allowsAlphaSplitting: 0 + overridden: 0 + ignorePlatformSupport: 0 + androidETC2FallbackOverride: 0 + forceMaximumCompressionQuality_BC6H_BC7: 0 + - serializedVersion: 3 + buildTarget: Standalone + maxTextureSize: 2048 + resizeAlgorithm: 0 + textureFormat: -1 + textureCompression: 1 + compressionQuality: 50 + crunchedCompression: 0 + allowsAlphaSplitting: 0 + overridden: 0 + ignorePlatformSupport: 0 + androidETC2FallbackOverride: 0 + forceMaximumCompressionQuality_BC6H_BC7: 0 + - serializedVersion: 3 + buildTarget: Android + maxTextureSize: 2048 + resizeAlgorithm: 0 + textureFormat: -1 + textureCompression: 1 + compressionQuality: 50 + crunchedCompression: 0 + allowsAlphaSplitting: 0 + overridden: 0 + ignorePlatformSupport: 0 + androidETC2FallbackOverride: 0 + forceMaximumCompressionQuality_BC6H_BC7: 0 + spriteSheet: + serializedVersion: 2 + sprites: [] + outline: [] + physicsShape: [] + bones: [] + spriteID: 5e97eb03825dee720800000000000000 + internalID: 0 + vertices: [] + indices: + edges: [] + weights: [] + secondaryTextures: [] + nameFileIdTable: {} + mipmapLimitGroupName: + pSDRemoveMatte: 0 + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Editor/Editor Windows/Icons/options.png b/Assets/Editor/Editor Windows/Icons/options.png new file mode 100644 index 0000000..c9ea295 Binary files /dev/null and b/Assets/Editor/Editor Windows/Icons/options.png differ diff --git a/Assets/Editor/Editor Windows/Icons/options.png.meta b/Assets/Editor/Editor Windows/Icons/options.png.meta new file mode 100644 index 0000000..e18bbb6 --- /dev/null +++ b/Assets/Editor/Editor Windows/Icons/options.png.meta @@ -0,0 +1,127 @@ +fileFormatVersion: 2 +guid: 788dc88cfd779234395738446dd2eade +TextureImporter: + internalIDToNameTable: [] + externalObjects: {} + serializedVersion: 13 + mipmaps: + mipMapMode: 0 + enableMipMap: 0 + sRGBTexture: 1 + linearTexture: 0 + fadeOut: 0 + borderMipMap: 0 + mipMapsPreserveCoverage: 0 + alphaTestReferenceValue: 0.5 + mipMapFadeDistanceStart: 1 + mipMapFadeDistanceEnd: 3 + bumpmap: + convertToNormalMap: 0 + externalNormalMap: 0 + heightScale: 0.25 + normalMapFilter: 0 + flipGreenChannel: 0 + isReadable: 0 + streamingMipmaps: 0 + streamingMipmapsPriority: 0 + vTOnly: 0 + ignoreMipmapLimit: 0 + grayScaleToAlpha: 0 + generateCubemap: 6 + cubemapConvolution: 0 + seamlessCubemap: 0 + textureFormat: 1 + maxTextureSize: 2048 + textureSettings: + serializedVersion: 2 + filterMode: 1 + aniso: 1 + mipBias: 0 + wrapU: 1 + wrapV: 1 + wrapW: 0 + nPOTScale: 0 + lightmap: 0 + compressionQuality: 50 + spriteMode: 1 + spriteExtrude: 1 + spriteMeshType: 1 + alignment: 0 + spritePivot: {x: 0.5, y: 0.5} + spritePixelsToUnits: 100 + spriteBorder: {x: 0, y: 0, z: 0, w: 0} + spriteGenerateFallbackPhysicsShape: 1 + alphaUsage: 1 + alphaIsTransparency: 1 + spriteTessellationDetail: -1 + textureType: 8 + textureShape: 1 + singleChannelComponent: 0 + flipbookRows: 1 + flipbookColumns: 1 + maxTextureSizeSet: 0 + compressionQualitySet: 0 + textureFormatSet: 0 + ignorePngGamma: 0 + applyGammaDecoding: 0 + swizzle: 50462976 + cookieLightType: 0 + platformSettings: + - serializedVersion: 3 + buildTarget: DefaultTexturePlatform + maxTextureSize: 2048 + resizeAlgorithm: 0 + textureFormat: -1 + textureCompression: 1 + compressionQuality: 50 + crunchedCompression: 0 + allowsAlphaSplitting: 0 + overridden: 0 + ignorePlatformSupport: 0 + androidETC2FallbackOverride: 0 + forceMaximumCompressionQuality_BC6H_BC7: 0 + - serializedVersion: 3 + buildTarget: Standalone + maxTextureSize: 2048 + resizeAlgorithm: 0 + textureFormat: -1 + textureCompression: 1 + compressionQuality: 50 + crunchedCompression: 0 + allowsAlphaSplitting: 0 + overridden: 0 + ignorePlatformSupport: 0 + androidETC2FallbackOverride: 0 + forceMaximumCompressionQuality_BC6H_BC7: 0 + - serializedVersion: 3 + buildTarget: Android + maxTextureSize: 2048 + resizeAlgorithm: 0 + textureFormat: -1 + textureCompression: 1 + compressionQuality: 50 + crunchedCompression: 0 + allowsAlphaSplitting: 0 + overridden: 0 + ignorePlatformSupport: 0 + androidETC2FallbackOverride: 0 + forceMaximumCompressionQuality_BC6H_BC7: 0 + spriteSheet: + serializedVersion: 2 + sprites: [] + outline: [] + physicsShape: [] + bones: [] + spriteID: 5e97eb03825dee720800000000000000 + internalID: 0 + vertices: [] + indices: + edges: [] + weights: [] + secondaryTextures: [] + nameFileIdTable: {} + mipmapLimitGroupName: + pSDRemoveMatte: 0 + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Editor/Editor Windows/ScriptableObjectEditorWindow.cs b/Assets/Editor/Editor Windows/ScriptableObjectEditorWindow.cs index dedfc87..4ad3513 100644 --- a/Assets/Editor/Editor Windows/ScriptableObjectEditorWindow.cs +++ b/Assets/Editor/Editor Windows/ScriptableObjectEditorWindow.cs @@ -4,686 +4,785 @@ using System; using System.Linq; -public class ScriptableObjectEditorWindow : EditorWindow +namespace ScriptableObjectManager { - //prefs: - public const string BASIC_FILTERS_PREF = "basic_filters"; - public const string PROPERTY_SPACE_PREF = "property_space"; - public const string TABLE_ORIENTATION_PREF = "table_orientation"; - private const char SEPARATOR = '|'; // Filtrelerde kullanılmayacak özel bir karakter - public static string[] BasicFilters + public class ScriptableObjectEditorWindow : EditorWindow { - get - { - string savedFilters = EditorPrefs.GetString(BASIC_FILTERS_PREF, ""); - return string.IsNullOrEmpty(savedFilters) - ? new string[0] - : savedFilters.Split(new[] { SEPARATOR }, StringSplitOptions.RemoveEmptyEntries); - } - set - { - string filtersString = string.Join(SEPARATOR.ToString(), value); - EditorPrefs.SetString(BASIC_FILTERS_PREF, filtersString); - } - } + //prefs: + public const string BASIC_FILTERS_PREF = "basic_filters"; + public const string PROPERTY_SPACE_PREF = "property_space"; + public const string TABLE_ORIENTATION_PREF = "table_orientation"; + private const char SEPARATOR = '|'; // Filtrelerde kullanılmayacak özel bir karakter - // layout: - private readonly float PropertyMinWidth = 40; - private float PropertySpace = 5; - private Vector2 ScrollPosMain = new(); - private readonly GUILayoutOption[] GUIL_StandartOptions = new GUILayoutOption[] { GUILayout.MinWidth(100), GUILayout.ExpandWidth(true) }; - private readonly GUILayoutOption[] GUIL_DefaultOptions = new GUILayoutOption[] { GUILayout.MinWidth(150), GUILayout.ExpandWidth(true) }; - private bool OrientationVertical = true; // Determines the orientation of the layout (true: vertical. false: horizontal) - // data: - private List> groupedConfigs; // Stores ScriptableObjects grouped by their class types in nested lists - private List selectedTypes = new(); // Tracks which ScriptableObject types are currently selected for display - private List availableTypes = new(); // Holds all unique ScriptableObject types found in the project - - // textures: - private Texture2D spaceIcon; - private Texture2D orientationIcon; - private Texture2D deleteConfigIcon; - private Texture2D addConfigIcon; - private Texture2D refreshIcon; - private Texture2D filtersIcon; - - // Buttons Styles: - GUIContent spaceButton; - GUIContent orientationButton; - GUIContent refreshButton; - GUIContent filtersButton; - // create config button styles: - GUIContent AddConfigButton; - GUILayoutOption[] AddConfigButtonOptions; - GUIStyle buttonStyle; - // delete config button styles: - GUIContent deleteConfigButton; - GUILayoutOption[] deleteConfigButtonOptions; - - // label styles: - GUIStyle centeredLabelStyle; - - // window: - [MenuItem("Window/Game Config Editor")] - public static void ShowWindow() - { - GetWindow("Game Config Editor"); - } - - private void OnEnable() - { - // Load the saved property space from EditorPrefs - float propSpace = EditorPrefs.GetFloat(PROPERTY_SPACE_PREF, -2); - if (propSpace == -2) + public static string[] BasicFilters { - // If no space is set, use the default value - PropertySpace = -1; - EditorPrefs.SetFloat(PROPERTY_SPACE_PREF, PropertySpace); + get + { + string savedFilters = EditorPrefs.GetString(BASIC_FILTERS_PREF, ""); + return string.IsNullOrEmpty(savedFilters) + ? new string[0] + : savedFilters.Split(new[] { SEPARATOR }, StringSplitOptions.RemoveEmptyEntries); + } + set + { + string filtersString = string.Join(SEPARATOR.ToString(), value); + EditorPrefs.SetString(BASIC_FILTERS_PREF, filtersString); + } } - else PropertySpace = propSpace; - - // Load the saved table orientation from EditorPrefs - OrientationVertical = EditorPrefs.GetBool(TABLE_ORIENTATION_PREF, true); - // Initialize the editor by discovering available types and organizing ScriptableObjects accordingly - LoadAvailableTypes(); - GroupScriptableObjectsByType(); + // layout: + private readonly float PropertyMinWidth = 40; + private float PropertySpace = 5; + private Vector2 ScrollPosMain = new(); + private readonly GUILayoutOption[] GUIL_StandartOptions = new GUILayoutOption[] { GUILayout.MinWidth(100), GUILayout.ExpandWidth(true) }; + private readonly GUILayoutOption[] GUIL_DefaultOptions = new GUILayoutOption[] { GUILayout.MinWidth(150), GUILayout.ExpandWidth(true) }; + private bool OrientationVertical = true; // Determines the orientation of the layout (true: vertical. false: horizontal) + // data: + private List> groupedConfigs; // Stores ScriptableObjects grouped by their class types in nested lists + private List selectedTypes = new(); // Tracks which ScriptableObject types are currently selected for display + private List availableTypes = new(); // Holds all unique ScriptableObject types found in the project + + // rename operation: + bool isRenaming = false; + bool FinishRenaming = false; + ScriptableObject ObjectToRename = null; + string renameText = ""; + + // textures: + private Texture2D spaceIcon; + private Texture2D orientationIcon; + private Texture2D ConfigOptionsIcon; + private Texture2D addConfigIcon; + private Texture2D refreshIcon; + private Texture2D filtersIcon; + private Texture2D checkIcon; + + // Buttons Styles: + GUIContent spaceButton; + GUIContent orientationButton; + GUIContent refreshButton; + GUIContent filtersButton; + GUIContent checkButton; + // create config button styles: + GUIContent AddConfigButton; + GUILayoutOption[] AddConfigButtonOptions; + GUIStyle buttonStyle; + // delete config button styles: + GUIContent ConfigOptionsButton; + GUILayoutOption[] ConfigOptionsButtonOptions; + + // label styles: + GUIStyle centeredLabelStyle; + + // window: + [MenuItem("Window/Game Config Editor")] + public static void ShowWindow() + { + GetWindow("Game Config Editor"); + } + + private void OnEnable() + { + // Load the saved property space from EditorPrefs + float propSpace = EditorPrefs.GetFloat(PROPERTY_SPACE_PREF, -2); + if (propSpace == -2) + { + // If no space is set, use the default value + PropertySpace = -1; + EditorPrefs.SetFloat(PROPERTY_SPACE_PREF, PropertySpace); + } + else PropertySpace = propSpace; - // Load icons for UI buttons - LoadIcons(); + // Load the saved table orientation from EditorPrefs + OrientationVertical = EditorPrefs.GetBool(TABLE_ORIENTATION_PREF, true); - // setup styles - SetupButtonStyles(); - } - - /// - /// Sets up the GUI buttons with their respective icons and tooltips. - /// - private void SetupButtonStyles() - { - // GUI content for space button - if (spaceIcon != null) - { - spaceButton = new GUIContent(spaceIcon, "change space between parameters"); - } - else - { - spaceButton = new GUIContent("space", "change space between parameters"); - } + // Initialize the editor by discovering available types and organizing ScriptableObjects accordingly + LoadAvailableTypes(); + GroupScriptableObjectsByType(); - // GUI content for orientation button - if (orientationIcon != null) - { - orientationButton = new GUIContent(orientationIcon, "change the table orientation"); - } - else - { - orientationButton = new GUIContent("rotate", "change the table orientation"); - } + // Load icons for UI buttons + LoadIcons(); - // GUI content for refresh button - if (refreshIcon != null) - { - refreshButton = new GUIContent(refreshIcon, "refresh"); - } - else - { - refreshButton = new GUIContent("refresh", "refresh"); + // setup styles + SetupButtonStyles(); } - // GUI content for filters button - if (filtersIcon != null) - { - filtersButton = new GUIContent(filtersIcon, "filters"); - } - else + /// + /// Sets up the GUI buttons with their respective icons and tooltips. + /// + private void SetupButtonStyles() { - filtersButton = new GUIContent("filters", "filters"); - } + // GUI content for space button + if (spaceIcon != null) + { + spaceButton = new GUIContent(spaceIcon, "change space between parameters"); + } + else + { + spaceButton = new GUIContent("space", "change space between parameters"); + } - // 'create config' button styles - if (addConfigIcon != null) - { - AddConfigButton = new GUIContent(addConfigIcon, "create new config"); - AddConfigButtonOptions = new GUILayoutOption[] { GUILayout.Height(20), GUILayout.Width(20) }; - } - else - { - AddConfigButton = new GUIContent("Add new", "create new config"); - AddConfigButtonOptions = new GUILayoutOption[] { GUILayout.Width(65) }; - } + // GUI content for orientation button + if (orientationIcon != null) + { + orientationButton = new GUIContent(orientationIcon, "change the table orientation"); + } + else + { + orientationButton = new GUIContent("rotate", "change the table orientation"); + } - // 'delete config' button styles - if (deleteConfigIcon != null) - { - deleteConfigButton = new GUIContent(deleteConfigIcon, "delete config permanently"); - deleteConfigButtonOptions = new GUILayoutOption[] { GUILayout.Height(20), GUILayout.Width(20) }; - } - else - { - deleteConfigButton = new GUIContent("del", "delete config permanently"); - deleteConfigButtonOptions = new GUILayoutOption[] { GUILayout.Width(30) }; - } - } + // GUI content for refresh button + if (refreshIcon != null) + { + refreshButton = new GUIContent(refreshIcon, "refresh"); + } + else + { + refreshButton = new GUIContent("refresh", "refresh"); + } - private void OnGUI() - { - EditorGUILayout.BeginHorizontal(); + // GUI content for filters button + if (filtersIcon != null) + { + filtersButton = new GUIContent(filtersIcon, "filters"); + } + else + { + filtersButton = new GUIContent("filters", "filters"); + } + // GUI content for check button + if (checkIcon != null) + { + checkButton = new GUIContent(checkIcon, "check"); + } + else + { + checkButton = new GUIContent("ok", "check"); + } - // A button to set space between properties - if (GUILayout.Button(spaceButton, GUILayout.Width(50))) - { - SetSpace(); - } + // 'create config' button styles + if (addConfigIcon != null) + { + AddConfigButton = new GUIContent(addConfigIcon, "create new config"); + AddConfigButtonOptions = new GUILayoutOption[] { GUILayout.Height(20), GUILayout.Width(20) }; + } + else + { + AddConfigButton = new GUIContent("Add new", "create new config"); + AddConfigButtonOptions = new GUILayoutOption[] { GUILayout.Width(65) }; + } - // A button to change the orientation of the table - if (GUILayout.Button(orientationButton, GUILayout.Width(50))) - { - if (OrientationVertical) + // 'Config Options' button styles + if (ConfigOptionsIcon != null) { - OrientationVertical = false; - EditorPrefs.SetBool(TABLE_ORIENTATION_PREF, OrientationVertical); + ConfigOptionsButton = new GUIContent(ConfigOptionsIcon, "Options"); + ConfigOptionsButtonOptions = new GUILayoutOption[] { GUILayout.Height(20), GUILayout.Width(20) }; } else { - OrientationVertical = true; - EditorPrefs.SetBool(TABLE_ORIENTATION_PREF, OrientationVertical); + ConfigOptionsButton = new GUIContent("opt", "Options"); + ConfigOptionsButtonOptions = new GUILayoutOption[] { GUILayout.Width(30) }; } } - EditorGUILayout.Space(); - - // A button to refresh the list of ScriptableObjects - if (GUILayout.Button(refreshButton, GUILayout.Width(50))) + private void OnGUI() { - RefreshAll(); - } + EditorGUILayout.BeginHorizontal(); - // Display a popup window at the mouse position for basic filters - if (GUILayout.Button(filtersButton, GUILayout.Width(50))) - { - Vector2 mousePosition = Event.current.mousePosition; - PopupWindow.Show(new Rect(mousePosition.x, mousePosition.y + 20, 0, 0), new ConfigTypeSelectionPopup(selectedTypes, GroupScriptableObjectsByType, availableTypes)); - } - EditorGUILayout.EndHorizontal(); + // A button to set space between properties + if (GUILayout.Button(spaceButton, GUILayout.Width(50))) + { + SetSpace(); + } + + // A button to change the orientation of the table + if (GUILayout.Button(orientationButton, GUILayout.Width(50))) + { + if (OrientationVertical) + { + OrientationVertical = false; + EditorPrefs.SetBool(TABLE_ORIENTATION_PREF, OrientationVertical); + } + else + { + OrientationVertical = true; + EditorPrefs.SetBool(TABLE_ORIENTATION_PREF, OrientationVertical); + } + } - EditorGUILayout.Space(5); + EditorGUILayout.Space(); - // if there is no SO loaded or selected from filters show a message - if (selectedTypes == null || selectedTypes.Count == 0 || groupedConfigs == null || groupedConfigs.Count == 0) - { - EditorGUILayout.LabelField("[No Config Selected]", EditorStyles.boldLabel); - return; - } + // A button to refresh the list of ScriptableObjects + if (GUILayout.Button(refreshButton, GUILayout.Width(50))) + { + RefreshAll(); + } - // show configs - ScrollPosMain = EditorGUILayout.BeginScrollView(ScrollPosMain); - if (groupedConfigs.Count != 0) - { - foreach (var configGroup in groupedConfigs) + // Display a popup window at the mouse position for basic filters + if (GUILayout.Button(filtersButton, GUILayout.Width(50))) { - // Only display groups that match the selected types or if no specific types are filtered - if (selectedTypes.Count == 0 || !selectedTypes.Contains(configGroup[0].GetType())) - continue; + Vector2 mousePosition = Event.current.mousePosition; + PopupWindow.Show(new Rect(mousePosition.x, mousePosition.y + 20, 0, 0), new ConfigTypeSelectionPopup(selectedTypes, GroupScriptableObjectsByType, availableTypes)); + } + EditorGUILayout.EndHorizontal(); - GUILayout.Space(20); + EditorGUILayout.Space(5); - EditorGUILayout.BeginHorizontal(); + // if there is no SO loaded or selected from filters show a message + if (selectedTypes == null || selectedTypes.Count == 0 || groupedConfigs == null || groupedConfigs.Count == 0) + { + EditorGUILayout.LabelField("[No Config Selected]", EditorStyles.boldLabel); + return; + } - // 'create config' button styles - if (addConfigIcon != null) + // show configs + ScrollPosMain = EditorGUILayout.BeginScrollView(ScrollPosMain); + if (groupedConfigs.Count != 0) + { + foreach (var configGroup in groupedConfigs) { - buttonStyle = new GUIStyle(GUI.skin.button); - buttonStyle.padding = new RectOffset(2, 2, 2, 2); - buttonStyle.imagePosition = ImagePosition.ImageOnly; - } + // Only display groups that match the selected types or if no specific types are filtered + if (selectedTypes.Count == 0 || !selectedTypes.Contains(configGroup[0].GetType())) + continue; - // create config button: - if (GUILayout.Button(AddConfigButton, buttonStyle, AddConfigButtonOptions)) - { - AddNewSO(configGroup[0].GetType()); - } + GUILayout.Space(20); - // show name of the ScriptableObject type - centeredLabelStyle = new GUIStyle(EditorStyles.boldLabel); - centeredLabelStyle.fontSize = 16; - GUILayout.Label(configGroup[0].GetType().Name, centeredLabelStyle); + EditorGUILayout.BeginHorizontal(); - EditorGUILayout.EndHorizontal(); + // 'create config' button styles + if (addConfigIcon != null) + { + buttonStyle = new GUIStyle(GUI.skin.button); + buttonStyle.padding = new RectOffset(2, 2, 2, 2); + buttonStyle.imagePosition = ImagePosition.ImageOnly; + } - // table: - if (OrientationVertical) - { - EditorGUILayout.BeginHorizontal(); - PutPropertiesForObject_V(configGroup); - EditorGUILayout.EndHorizontal(); - } - else - { - EditorGUILayout.BeginVertical("box"); - PutPropertiesForObject_H(configGroup); - EditorGUILayout.EndVertical(); + // create config button: + if (GUILayout.Button(AddConfigButton, buttonStyle, AddConfigButtonOptions)) + { + AddNewSO(configGroup[0].GetType()); + } + + // show name of the ScriptableObject type + centeredLabelStyle = new GUIStyle(EditorStyles.boldLabel); + centeredLabelStyle.fontSize = 16; + GUILayout.Label(configGroup[0].GetType().Name, centeredLabelStyle); + + EditorGUILayout.EndHorizontal(); + + // table: + if (OrientationVertical) + { + EditorGUILayout.BeginHorizontal(); + PutPropertiesForObject_V(configGroup); + EditorGUILayout.EndHorizontal(); + } + else + { + EditorGUILayout.BeginVertical("box"); + PutPropertiesForObject_H(configGroup); + EditorGUILayout.EndVertical(); + } } } + EditorGUILayout.EndScrollView(); } - EditorGUILayout.EndScrollView(); - } - private void SetSpace() - { - float propSpace = EditorPrefs.GetFloat(PROPERTY_SPACE_PREF, -2); - if (propSpace == -2) - { - // If no space is set, use the default value - PropertySpace = -1; - EditorPrefs.SetFloat(PROPERTY_SPACE_PREF, PropertySpace); - } - else + private void SetSpace() { - // If space is already set, increase it by 1 - PropertySpace += 1; + float propSpace = EditorPrefs.GetFloat(PROPERTY_SPACE_PREF, -2); + if (propSpace == -2) + { + // If no space is set, use the default value + PropertySpace = -1; + EditorPrefs.SetFloat(PROPERTY_SPACE_PREF, PropertySpace); + } + else + { + // If space is already set, increase it by 1 + PropertySpace += 1; - // If the space exceeds 5, reset it to 0 - if (PropertySpace > 5) PropertySpace = -1; + // If the space exceeds 5, reset it to 0 + if (PropertySpace > 5) PropertySpace = -1; - // Save the new space value - EditorPrefs.SetFloat(PROPERTY_SPACE_PREF, PropertySpace); + // Save the new space value + EditorPrefs.SetFloat(PROPERTY_SPACE_PREF, PropertySpace); - Debug.Log("Property Space: " + PropertySpace); + Debug.Log("Property Space: " + PropertySpace); + } } - } - - private void RefreshAll() - { - LoadAvailableTypes(); - GroupScriptableObjectsByType(); - } - void AddNewSO(Type type) - { - // Create a new instance of the selected ScriptableObject type - ScriptableObject newConfig = ScriptableObject.CreateInstance(type); - - // Save file panel that works within the project (Assets/) - string path = EditorUtility.SaveFilePanelInProject( - "Save Config", - type.Name + ".asset", - "asset", - "Please enter a file name to save the ScriptableObject.", - "Assets/Resources/ScriptableObjects" - ); - - if (!string.IsNullOrEmpty(path)) + private void RefreshAll() { - AssetDatabase.CreateAsset(newConfig, path); - AssetDatabase.SaveAssets(); - AssetDatabase.Refresh(); + LoadAvailableTypes(); + GroupScriptableObjectsByType(); } - RefreshAll(); - } - private void LoadIcons() - { - spaceIcon = AssetDatabase.LoadAssetAtPath("Assets/Editor/Editor Windows/Icons/space.png"); - orientationIcon = AssetDatabase.LoadAssetAtPath("Assets/Editor/Editor Windows/Icons/orientation.png"); - deleteConfigIcon = AssetDatabase.LoadAssetAtPath("Assets/Editor/Editor Windows/Icons/delete.png"); - addConfigIcon = AssetDatabase.LoadAssetAtPath("Assets/Editor/Editor Windows/Icons/add file.png"); - refreshIcon = AssetDatabase.LoadAssetAtPath("Assets/Editor/Editor Windows/Icons/refresh.png"); - filtersIcon = AssetDatabase.LoadAssetAtPath("Assets/Editor/Editor Windows/Icons/filter.png"); - - if (spaceIcon == null) - { - Debug.LogError("space Icon not found in: Assets/Editor/Editor Windows/Icons/space.png"); - } - if (orientationIcon == null) + void AddNewSO(Type type) { - Debug.LogError("orientation Icon not found in: Assets/Editor/Editor Windows/Icons/orientation.png"); - } - if(deleteConfigIcon == null) - { - Debug.LogError("deleteConfig Icon not found in: Assets/Editor/Editor Windows/Icons/delete.png"); - } - if (addConfigIcon == null) - { - Debug.LogError("addConfig Icon not found in: Assets/Editor/Editor Windows/Icons/add file.png"); - } - if (refreshIcon == null) - { - Debug.LogError("refresh Icon not found in: Assets/Editor/Editor Windows/Icons/refresh.png"); - } - if (filtersIcon == null) - { - Debug.LogError("filters Icon not found in: Assets/Editor/Editor Windows/Icons/filter.png"); - } - } + // Create a new instance of the selected ScriptableObject type + ScriptableObject newConfig = ScriptableObject.CreateInstance(type); - private void LoadAvailableTypes() - { - selectedTypes.Clear(); - // Scan the "ScriptableObjects" folder to find all unique ScriptableObject types - availableTypes = Resources.LoadAll("ScriptableObjects").Select(t => t.GetType()).Distinct().ToList(); - foreach (var filter in BasicFilters) - { - if (string.IsNullOrEmpty(filter)) - continue; - // Add any additional types specified in the basic filters - var type = availableTypes.FirstOrDefault(t => t.Name == filter); - if (type != null) + // Save file panel that works within the project (Assets/) + string path = EditorUtility.SaveFilePanelInProject( + "Save Config", + type.Name + ".asset", + "asset", + "Please enter a file name to save the ScriptableObject.", + "Assets/Resources/ScriptableObjects" + ); + + if (!string.IsNullOrEmpty(path)) { - selectedTypes.Add(type); + AssetDatabase.CreateAsset(newConfig, path); + AssetDatabase.SaveAssets(); + AssetDatabase.Refresh(); } + RefreshAll(); } - } - private void GroupScriptableObjectsByType() - { - // Fetch all ScriptableObjects from a designated folder and organize them into groups based on their class types - var configs = Resources.LoadAll("").ToList(); - - groupedConfigs = configs - .GroupBy(c => c.GetType()) - .Where(g => selectedTypes.Count == 0 || selectedTypes.Contains(g.Key)) // Only include groups matching the current type filter - .Select(g => g.ToList()) // Convert each group into a list of ScriptableObjects - .ToList(); - } + private void LoadIcons() + { + spaceIcon = AssetDatabase.LoadAssetAtPath("Assets/Editor/Editor Windows/Icons/space.png"); + orientationIcon = AssetDatabase.LoadAssetAtPath("Assets/Editor/Editor Windows/Icons/orientation.png"); + ConfigOptionsIcon = AssetDatabase.LoadAssetAtPath("Assets/Editor/Editor Windows/Icons/options.png"); + addConfigIcon = AssetDatabase.LoadAssetAtPath("Assets/Editor/Editor Windows/Icons/add file.png"); + refreshIcon = AssetDatabase.LoadAssetAtPath("Assets/Editor/Editor Windows/Icons/refresh.png"); + filtersIcon = AssetDatabase.LoadAssetAtPath("Assets/Editor/Editor Windows/Icons/filter.png"); + checkIcon = AssetDatabase.LoadAssetAtPath("Assets/Editor/Editor Windows/Icons/check.png"); + if (spaceIcon == null) + { + Debug.LogError("space Icon not found in: Assets/Editor/Editor Windows/Icons/space.png"); + } + if (orientationIcon == null) + { + Debug.LogError("orientation Icon not found in: Assets/Editor/Editor Windows/Icons/orientation.png"); + } + if (ConfigOptionsIcon == null) + { + Debug.LogError("ConfigOptions Icon not found in: Assets/Editor/Editor Windows/Icons/options.png"); + } + if (addConfigIcon == null) + { + Debug.LogError("addConfig Icon not found in: Assets/Editor/Editor Windows/Icons/add file.png"); + } + if (refreshIcon == null) + { + Debug.LogError("refresh Icon not found in: Assets/Editor/Editor Windows/Icons/refresh.png"); + } + if (filtersIcon == null) + { + Debug.LogError("filters Icon not found in: Assets/Editor/Editor Windows/Icons/filter.png"); + } + if (checkIcon == null) + { + Debug.LogError("check Icon not found in: Assets/Editor/Editor Windows/Icons/check.png"); + } + } - /// - /// create a vertival table for the properties of the object - /// - private void PutPropertiesForObject_V(List Configs) where T : ScriptableObject - { - try + private void LoadAvailableTypes() { - EditorGUILayout.BeginVertical("box", GUILayout.Width(170)); - try + selectedTypes.Clear(); + // Scan the "ScriptableObjects" folder to find all unique ScriptableObject types + availableTypes = Resources.LoadAll("ScriptableObjects").Select(t => t.GetType()).Distinct().ToList(); + foreach (var filter in BasicFilters) { - // An empty label to align property names properly in the UI - EditorGUILayout.LabelField("", GUILayout.MinWidth(PropertyMinWidth)); - - // Iterate through the properties of the first ScriptableObject to display their names - SerializedObject serializedObject = new(Configs[0]); - SerializedProperty property = serializedObject.GetIterator(); - - bool ShouldNext = property.NextVisible(true); - while (ShouldNext) + if (string.IsNullOrEmpty(filter)) + continue; + // Add any additional types specified in the basic filters + var type = availableTypes.FirstOrDefault(t => t.Name == filter); + if (type != null) { - if (property.propertyType != SerializedPropertyType.ArraySize && property.name != "m_Script" && property.name != "data") // Exclude internal Unity fields and arrays - { - // Show the name of each property as a label - EditorGUILayout.LabelField(property.name, GUIL_StandartOptions); - // if any property is bigger than expected this will calculate extra space needed (ex: array properties can expand) - if (property.isExpanded) - GUILayout.Space(CalculatePropertyHeight(Configs, property) - EditorGUIUtility.singleLineHeight); - GUILayout.Space(PropertySpace); - } - ShouldNext = property.NextVisible(false); // Move to the next property, skipping nested children + selectedTypes.Add(type); } } - catch - { - // If an error occurs, refresh the type list and regroup the objects - LoadAvailableTypes(); - GroupScriptableObjectsByType(); - } - EditorGUILayout.EndVertical(); + } - if (Configs.Count == 0) - return; // Exit if there are no configurations to display + private void GroupScriptableObjectsByType() + { + // Fetch all ScriptableObjects from a designated folder and organize them into groups based on their class types + var configs = Resources.LoadAll("").ToList(); + + groupedConfigs = configs + .GroupBy(c => c.GetType()) + .Where(g => selectedTypes.Count == 0 || selectedTypes.Contains(g.Key)) // Only include groups matching the current type filter + .Select(g => g.ToList()) // Convert each group into a list of ScriptableObjects + .ToList(); + } - foreach (var Config in Configs) + + /// + /// create a vertival table for the properties of the object + /// + private void PutPropertiesForObject_V(List Configs) where T : ScriptableObject + { + try { - EditorGUILayout.BeginVertical("box"); + EditorGUILayout.BeginVertical("box", GUILayout.Width(170)); try { - // Retrieve and display the asset's file name without its extension - string filePath = AssetDatabase.GetAssetPath(Config); - string fileName = System.IO.Path.GetFileNameWithoutExtension(filePath); - if (fileName == "") throw new System.Exception(); - - // Display the file name and a delete button for the asset - EditorGUILayout.BeginHorizontal(); - GUIContent propertyContent = new GUIContent(fileName, fileName); - EditorGUILayout.LabelField(propertyContent, EditorStyles.miniBoldLabel, GUILayout.MinWidth(PropertyMinWidth)); - DeleteButton(Config); - EditorGUILayout.EndHorizontal(); + // An empty label to align property names properly in the UI + EditorGUILayout.LabelField("", GUILayout.MinWidth(PropertyMinWidth)); - SerializedObject serializedObject = new(Config); + // Iterate through the properties of the first ScriptableObject to display their names + SerializedObject serializedObject = new(Configs[0]); SerializedProperty property = serializedObject.GetIterator(); - // Iterate through all properties to create editable fields based on their types bool ShouldNext = property.NextVisible(true); while (ShouldNext) { - if (property.propertyType != SerializedPropertyType.ArraySize && property.name != "m_Script" && property.name != "data") // Skip unwanted properties + if (property.propertyType != SerializedPropertyType.ArraySize && property.name != "m_Script" && property.name != "data") // Exclude internal Unity fields and arrays { - EditorGUILayout.PropertyField(property, GUIContent.none, true, GUIL_DefaultOptions); + // Show the name of each property as a label + EditorGUILayout.LabelField(property.name, GUIL_StandartOptions); + // if any property is bigger than expected this will calculate extra space needed (ex: array properties can expand) if (property.isExpanded) - { - float extraSpace = CalculatePropertyHeight(Configs, property); - extraSpace -= EditorGUI.GetPropertyHeight(property); - GUILayout.Space(extraSpace); - } + GUILayout.Space(CalculatePropertyHeight(Configs, property) - EditorGUIUtility.singleLineHeight); GUILayout.Space(PropertySpace); - serializedObject.ApplyModifiedProperties(); } - ShouldNext = property.NextVisible(false); // Advance to the next property, excluding nested fields + ShouldNext = property.NextVisible(false); // Move to the next property, skipping nested children } - property.Reset(); } catch { - // Handle errors by refreshing the type list and regrouping + // If an error occurs, refresh the type list and regroup the objects LoadAvailableTypes(); GroupScriptableObjectsByType(); } EditorGUILayout.EndVertical(); - } - } - catch - { - // Catch any top-level errors and reset the data - LoadAvailableTypes(); - GroupScriptableObjectsByType(); - } - } + if (Configs.Count == 0) + return; // Exit if there are no configurations to display - private void DeleteButton(T Config) where T : ScriptableObject - { - - GUIStyle buttonStyle = new GUIStyle(GUI.skin.button); + foreach (var Config in Configs) + { + EditorGUILayout.BeginVertical("box"); + try + { + // Retrieve and display the asset's file name without its extension + string filePath = AssetDatabase.GetAssetPath(Config); + string fileName = System.IO.Path.GetFileNameWithoutExtension(filePath); + if (fileName == "") throw new System.Exception(); - if (deleteConfigIcon != null) - { - buttonStyle.padding = new RectOffset(2, 2, 2, 2); - buttonStyle.imagePosition = ImagePosition.ImageOnly; - } + // Display the file name and a delete button for the asset + EditorGUILayout.BeginHorizontal(); + GUIContent propertyContent = new GUIContent(fileName, fileName); - if (GUILayout.Button(deleteConfigButton, buttonStyle, deleteConfigButtonOptions)) - { - // Delete the selected ScriptableObject asset - DeleteConfig(Config); - } - } + Rect elementRect = GUILayoutUtility.GetRect(120, 18); + if (isRenaming && ObjectToRename != null && ObjectToRename == Config) + { + GUI.SetNextControlName("RenameField"); - /// - /// create a Horizontal (parameters will be horizontal) table for the properties of the object - /// - private void PutPropertiesForObject_H(List Configs) where T : ScriptableObject - { - try - { - // property names on horizontal line: - EditorGUILayout.BeginHorizontal(); - try - { - // An empty label to align property names properly in the UI - EditorGUILayout.LabelField("", GUILayout.Width(152)); + // Display a text field for renaming the asset.if renameText is empty, show the file name until the user types something + renameText = EditorGUI.TextField(elementRect, renameText == "" ? fileName : renameText); - // Iterate through the properties of the first ScriptableObject to display their names - SerializedObject serializedObject = new(Configs[0]); - SerializedProperty property = serializedObject.GetIterator(); + Event e = Event.current; - bool ShouldNext = property.NextVisible(true); - while (ShouldNext) - { - if (property.propertyType != SerializedPropertyType.ArraySize && property.name != "m_Script" && property.name != "data") // Exclude internal Unity fields and arrays + // textfield + confirm button (for mouse event it must also contain the button area) + elementRect.width += 25; + if (isRenaming && e.type == EventType.MouseDown && !elementRect.Contains(e.mousePosition)) + { + isRenaming = false; + GUI.FocusControl(null); + e.Use(); + } + + if (FinishRenaming || Event.current.keyCode == KeyCode.Return || Event.current.keyCode == KeyCode.KeypadEnter) + { + AssetDatabase.RenameAsset(filePath, renameText); + AssetDatabase.SaveAssets(); + isRenaming = false; + FinishRenaming = false; + renameText = ""; + ObjectToRename = null; + GUI.FocusControl(null); + } + else if (Event.current.keyCode == KeyCode.Escape) + { + renameText = ""; + isRenaming = false; + ObjectToRename = null; + GUI.FocusControl(null); + } + + EditorGUI.FocusTextInControl("RenameField"); + } + else + { + EditorGUI.LabelField(elementRect, propertyContent, EditorStyles.miniBoldLabel); + } + + OptionsButton(Config); + EditorGUILayout.EndHorizontal(); + + SerializedObject serializedObject = new(Config); + SerializedProperty property = serializedObject.GetIterator(); + + // Iterate through all properties to create editable fields based on their types + bool ShouldNext = property.NextVisible(true); + while (ShouldNext) + { + if (property.propertyType != SerializedPropertyType.ArraySize && property.name != "m_Script" && property.name != "data") // Skip unwanted properties + { + EditorGUILayout.PropertyField(property, GUIContent.none, true, GUIL_DefaultOptions); + if (property.isExpanded) + { + float extraSpace = CalculatePropertyHeight(Configs, property); + extraSpace -= EditorGUI.GetPropertyHeight(property); + GUILayout.Space(extraSpace); + } + GUILayout.Space(PropertySpace); + serializedObject.ApplyModifiedProperties(); + } + ShouldNext = property.NextVisible(false); // Advance to the next property, excluding nested fields + } + property.Reset(); + } + catch { - // Show the name of each property as a label - EditorGUILayout.LabelField(property.name, GUIL_StandartOptions); + // Handle errors by refreshing the type list and regrouping + LoadAvailableTypes(); + GroupScriptableObjectsByType(); } - ShouldNext = property.NextVisible(false); // Move to the next property, skipping nested children + EditorGUILayout.EndVertical(); } + } catch { - // If an error occurs, refresh the type list and regroup the objects + // Catch any top-level errors and reset the data LoadAvailableTypes(); GroupScriptableObjectsByType(); } - EditorGUILayout.EndHorizontal(); + } - // Exit if there are no configurations to display - if (Configs.Count == 0) - return; + private void OptionsButton(T Config) where T : ScriptableObject + { + + GUIStyle buttonStyle = new GUIStyle(GUI.skin.button); - // Iterate through each ScriptableObject in the list - foreach (var Config in Configs) + if (ConfigOptionsIcon != null) { - EditorGUILayout.BeginHorizontal(); - try + buttonStyle.padding = new RectOffset(2, 2, 2, 2); + buttonStyle.margin = new RectOffset(0, 0, 0, 0); + buttonStyle.imagePosition = ImagePosition.ImageOnly; + } + + if (isRenaming && ObjectToRename != null && ObjectToRename == Config) + { + if (GUILayout.Button(checkIcon, buttonStyle, ConfigOptionsButtonOptions)) { - // Retrieve and display the asset's file name without its extension - string filePath = AssetDatabase.GetAssetPath(Config); - string fileName = System.IO.Path.GetFileNameWithoutExtension(filePath); - if (fileName == "") throw new System.Exception(); + FinishRenaming = true; + } + } + else + { + if (GUILayout.Button(ConfigOptionsButton, buttonStyle, ConfigOptionsButtonOptions)) + { + ShowOptionsMenu(Config); + } + } + } + + private void ShowOptionsMenu(T Config) where T : ScriptableObject + { + GenericMenu menu = new GenericMenu(); - // Display a delete button for the asset - DeleteButton(Config); + menu.AddItem(new GUIContent("Delete Config"), false, () => DeleteConfig(Config)); + menu.AddItem(new GUIContent("Rename Config"), false, () => { isRenaming = true; ObjectToRename = Config; renameText = ""; }); + menu.AddSeparator(""); + menu.AddItem(new GUIContent("Show In Project Folder"), false, () => ShowInProjectFolders(Config)); + menu.ShowAsContext(); + } - // Display the file name for the asset - GUIContent propertyContent = new GUIContent(fileName, fileName); - EditorGUILayout.LabelField(propertyContent, EditorStyles.miniBoldLabel, GUILayout.Width(120)); + /// + /// create a Horizontal (parameters will be horizontal) table for the properties of the object + /// + private void PutPropertiesForObject_H(List Configs) where T : ScriptableObject + { + try + { + // property names on horizontal line: + EditorGUILayout.BeginHorizontal(); + try + { + // An empty label to align property names properly in the UI + EditorGUILayout.LabelField("", GUILayout.Width(152)); - SerializedObject serializedObject = new(Config); + // Iterate through the properties of the first ScriptableObject to display their names + SerializedObject serializedObject = new(Configs[0]); SerializedProperty property = serializedObject.GetIterator(); - // Iterate through all properties to create editable fields based on their types bool ShouldNext = property.NextVisible(true); while (ShouldNext) { - if (property.propertyType != SerializedPropertyType.ArraySize && property.name != "m_Script" && property.name != "data") // Skip unwanted properties + if (property.propertyType != SerializedPropertyType.ArraySize && property.name != "m_Script" && property.name != "data") // Exclude internal Unity fields and arrays { - EditorGUILayout.PropertyField(property, GUIContent.none, true, GUIL_DefaultOptions); - serializedObject.ApplyModifiedProperties(); + // Show the name of each property as a label + EditorGUILayout.LabelField(property.name, GUIL_StandartOptions); } - ShouldNext = property.NextVisible(false); // Advance to the next property, excluding nested fields + ShouldNext = property.NextVisible(false); // Move to the next property, skipping nested children } - property.Reset(); } catch { - // Handle errors by refreshing the type list and regrouping + // If an error occurs, refresh the type list and regroup the objects LoadAvailableTypes(); GroupScriptableObjectsByType(); } EditorGUILayout.EndHorizontal(); - GUILayout.Space(PropertySpace); - } - } - catch - { - // Catch any top-level errors and reset the data - LoadAvailableTypes(); - GroupScriptableObjectsByType(); - } - } + // Exit if there are no configurations to display + if (Configs.Count == 0) + return; - private void DeleteConfig(T Config) where T : ScriptableObject - { - if (EditorUtility.DisplayDialog("Delete Config", "Are you sure you want to delete this config? \n\nYou cannot undo delete assets action.", "Yes", "No")) - { - AssetDatabase.DeleteAsset(AssetDatabase.GetAssetPath(Config)); - AssetDatabase.SaveAssets(); - AssetDatabase.Refresh(); - GroupScriptableObjectsByType(); // Refresh the list after deletion - } - } + // Iterate through each ScriptableObject in the list + foreach (var Config in Configs) + { + EditorGUILayout.BeginHorizontal(); + try + { + // Retrieve and display the asset's file name without its extension + string filePath = AssetDatabase.GetAssetPath(Config); + string fileName = System.IO.Path.GetFileNameWithoutExtension(filePath); + if (fileName == "") throw new System.Exception(); + + // Display the file name for the asset + GUIContent propertyContent = new GUIContent(fileName, fileName); + + + Rect elementRect = GUILayoutUtility.GetRect(120, 18, GUILayout.Width(120)); + + if (isRenaming && ObjectToRename != null && ObjectToRename == Config) + { + GUI.SetNextControlName("RenameField"); - public static float CalculatePropertyHeight(List configs, SerializedProperty property) where T : ScriptableObject - { - float maxHeight = 0f; + // Display a text field for renaming the asset.if renameText is empty, show the file name until the user types something + renameText = EditorGUI.TextField(elementRect, renameText == "" ? fileName : renameText); - foreach (var config in configs) - { - SerializedObject serializedObject = new(config); - SerializedProperty targetProperty = serializedObject.FindProperty(property.propertyPath); + Event e = Event.current; - if (targetProperty != null) - { - float height = EditorGUI.GetPropertyHeight(targetProperty, true); - maxHeight = Mathf.Max(maxHeight, height); - } - } + // textfield + confirm button (for mouse event it must also contain the button area) + elementRect.width = 145; + if (isRenaming && e.type == EventType.MouseDown && !elementRect.Contains(e.mousePosition)) + { + isRenaming = false; + GUI.FocusControl(null); + e.Use(); + } - return maxHeight; - } + if (FinishRenaming || Event.current.keyCode == KeyCode.Return || Event.current.keyCode == KeyCode.KeypadEnter) + { + AssetDatabase.RenameAsset(filePath, renameText); + AssetDatabase.SaveAssets(); + isRenaming = false; + FinishRenaming = false; + renameText = ""; + ObjectToRename = null; + GUI.FocusControl(null); + } + else if (Event.current.keyCode == KeyCode.Escape) + { + renameText = ""; + isRenaming = false; + ObjectToRename = null; + GUI.FocusControl(null); + } -} + EditorGUI.FocusTextInControl("RenameField"); + } + else + { + EditorGUI.LabelField(elementRect, propertyContent, EditorStyles.miniBoldLabel); + } + + // Display a delete button for the asset + OptionsButton(Config); + GUILayout.Space(3); -// Custom Popup Window for Config Type Selection -public class ConfigTypeSelectionPopup : PopupWindowContent -{ - private readonly List SelectedTypes; - private readonly List AvailableTypes; - private readonly Action OnSelectionChanged; - private Vector2 ScrollPos = new(); + SerializedObject serializedObject = new(Config); + SerializedProperty property = serializedObject.GetIterator(); - public ConfigTypeSelectionPopup(List selectedTypes, Action onSelectionChanged, List availableTypes) - { - this.SelectedTypes = selectedTypes; - this.OnSelectionChanged = onSelectionChanged; - this.AvailableTypes = availableTypes; - } + // Iterate through all properties to create editable fields based on their types + bool ShouldNext = property.NextVisible(true); + while (ShouldNext) + { + if (property.propertyType != SerializedPropertyType.ArraySize && property.name != "m_Script" && property.name != "data") // Skip unwanted properties + { + EditorGUILayout.PropertyField(property, GUIContent.none, true, GUIL_DefaultOptions); + serializedObject.ApplyModifiedProperties(); + } + ShouldNext = property.NextVisible(false); // Advance to the next property, excluding nested fields + } + property.Reset(); + } + catch + { + // Handle errors by refreshing the type list and regrouping + LoadAvailableTypes(); + GroupScriptableObjectsByType(); + } + EditorGUILayout.EndHorizontal(); + GUILayout.Space(PropertySpace); + } + } + catch + { + // Catch any top-level errors and reset the data + LoadAvailableTypes(); + GroupScriptableObjectsByType(); + } + } - public override Vector2 GetWindowSize() - { - return new Vector2(200, 500); // Define the dimensions of the popup window - } - public override void OnGUI(Rect rect) - { - GUILayout.Label("Select Config Types", EditorStyles.boldLabel); + private void DeleteConfig(T Config) where T : ScriptableObject + { + if (EditorUtility.DisplayDialog("Delete Config", "Are you sure you want to delete this config? \n\nYou cannot undo delete assets action.", "Yes", "No")) + { + AssetDatabase.DeleteAsset(AssetDatabase.GetAssetPath(Config)); + AssetDatabase.SaveAssets(); + AssetDatabase.Refresh(); + GroupScriptableObjectsByType(); // Refresh the list after deletion + } + } - if (AvailableTypes.Count > 0) + private void ShowInProjectFolders(T Config) where T : ScriptableObject { - ScrollPos = EditorGUILayout.BeginScrollView(ScrollPos); + string path = AssetDatabase.GetAssetPath(Config); + EditorUtility.FocusProjectWindow(); + Selection.activeObject = AssetDatabase.LoadAssetAtPath(path); + } - // Display each available type with a toggle to enable or disable it - foreach (var type in AvailableTypes) + public static float CalculatePropertyHeight(List configs, SerializedProperty property) where T : ScriptableObject + { + float maxHeight = 0f; + + foreach (var config in configs) { - bool isSelected = SelectedTypes.Contains(type); - bool toggle = EditorGUILayout.Toggle(type.Name, isSelected); + SerializedObject serializedObject = new(config); + SerializedProperty targetProperty = serializedObject.FindProperty(property.propertyPath); - if (toggle && !isSelected) + if (targetProperty != null) { - SelectedTypes.Add(type); // Add the type to the selection list - OnSelectionChanged.Invoke(); - ScriptableObjectEditorWindow.BasicFilters = SelectedTypes.Select(t => t.Name).ToArray(); - } - else if (!toggle && isSelected) - { - SelectedTypes.Remove(type); // Remove the type from the selection list - OnSelectionChanged.Invoke(); - ScriptableObjectEditorWindow.BasicFilters = SelectedTypes.Select(t => t.Name).ToArray(); + float height = EditorGUI.GetPropertyHeight(targetProperty, true); + maxHeight = Mathf.Max(maxHeight, height); } } - // Close the scrollable area within the popup - EditorGUILayout.EndScrollView(); + + return maxHeight; } + + void OnLostFocus() + { + isRenaming = false; + ObjectToRename = null; + renameText = ""; + GUI.FocusControl(null); + } + } } \ No newline at end of file diff --git a/Assets/Resources/ScriptableObjects/TestConfig.asset b/Assets/Resources/ScriptableObjects/TestConfig2.asset similarity index 96% rename from Assets/Resources/ScriptableObjects/TestConfig.asset rename to Assets/Resources/ScriptableObjects/TestConfig2.asset index 086f1d1..91eef47 100644 --- a/Assets/Resources/ScriptableObjects/TestConfig.asset +++ b/Assets/Resources/ScriptableObjects/TestConfig2.asset @@ -10,7 +10,7 @@ MonoBehaviour: m_Enabled: 1 m_EditorHideFlags: 0 m_Script: {fileID: 11500000, guid: b23340d9b453ca740945f54769125bb1, type: 3} - m_Name: TestConfig + m_Name: TestConfig2 m_EditorClassIdentifier: number: -13 value: 0 diff --git a/Assets/Resources/ScriptableObjects/TestConfig.asset.meta b/Assets/Resources/ScriptableObjects/TestConfig2.asset.meta similarity index 100% rename from Assets/Resources/ScriptableObjects/TestConfig.asset.meta rename to Assets/Resources/ScriptableObjects/TestConfig2.asset.meta diff --git a/Assets/Resources/ScriptableObjects/TestConfig 2.asset b/Assets/Resources/ScriptableObjects/TestConfig3.asset similarity index 96% rename from Assets/Resources/ScriptableObjects/TestConfig 2.asset rename to Assets/Resources/ScriptableObjects/TestConfig3.asset index 1648680..846b516 100644 --- a/Assets/Resources/ScriptableObjects/TestConfig 2.asset +++ b/Assets/Resources/ScriptableObjects/TestConfig3.asset @@ -10,7 +10,7 @@ MonoBehaviour: m_Enabled: 1 m_EditorHideFlags: 0 m_Script: {fileID: 11500000, guid: b23340d9b453ca740945f54769125bb1, type: 3} - m_Name: TestConfig 2 + m_Name: TestConfig3 m_EditorClassIdentifier: number: 22 value: 0 diff --git a/Assets/Resources/ScriptableObjects/TestConfig 2.asset.meta b/Assets/Resources/ScriptableObjects/TestConfig3.asset.meta similarity index 100% rename from Assets/Resources/ScriptableObjects/TestConfig 2.asset.meta rename to Assets/Resources/ScriptableObjects/TestConfig3.asset.meta