Cleanup the editor assembly and provide a tool overview doc

This commit is contained in:
Michal Adam Pikulski
2025-10-21 14:54:58 +02:00
parent 0a240da9a7
commit 2abcf5c76a
38 changed files with 169 additions and 0 deletions

View File

@@ -0,0 +1,211 @@
using UnityEngine;
using UnityEditor;
using System.Collections.Generic;
using System.Linq;
using System.IO;
namespace AppleHills.Core.Settings.Editor
{
public class DeveloperSettingsEditorWindow : EditorWindow
{
private Vector2 scrollPosition;
private List<BaseDeveloperSettings> allDeveloperSettings = new List<BaseDeveloperSettings>();
private string[] tabNames = new string[] { "Diving", "Debug", "Other Systems" }; // Added Debug tab
private int selectedTab = 0;
private Dictionary<string, SerializedObject> serializedSettingsObjects = new Dictionary<string, SerializedObject>();
private GUIStyle headerStyle;
[MenuItem("AppleHills/Developer Settings Editor")]
public static void ShowWindow()
{
GetWindow<DeveloperSettingsEditorWindow>("Developer Settings");
}
private void OnEnable()
{
LoadAllSettings();
}
private void LoadAllSettings()
{
allDeveloperSettings.Clear();
serializedSettingsObjects.Clear();
// Find all developer settings assets
string[] guids = AssetDatabase.FindAssets("t:BaseDeveloperSettings");
foreach (string guid in guids)
{
string path = AssetDatabase.GUIDToAssetPath(guid);
BaseDeveloperSettings settings = AssetDatabase.LoadAssetAtPath<BaseDeveloperSettings>(path);
if (settings != null)
{
allDeveloperSettings.Add(settings);
serializedSettingsObjects[settings.GetType().Name] = new SerializedObject(settings);
}
}
// If any settings are missing, create them
CreateSettingsIfMissing<DivingDeveloperSettings>("DivingDeveloperSettings");
CreateSettingsIfMissing<DebugSettings>("DebugSettings");
// Add more developer settings types here as needed
// CreateSettingsIfMissing<OtherDeveloperSettings>("OtherDeveloperSettings");
}
private void CreateSettingsIfMissing<T>(string fileName) where T : BaseDeveloperSettings
{
if (!allDeveloperSettings.Any(s => s is T))
{
// Check if the asset already exists
string[] guids = AssetDatabase.FindAssets($"t:{typeof(T).Name}");
if (guids.Length == 0)
{
// Create the settings folder if it doesn't exist
string settingsFolder = "Assets/Settings/Developer";
if (!AssetDatabase.IsValidFolder("Assets/Settings"))
{
AssetDatabase.CreateFolder("Assets", "Settings");
}
if (!AssetDatabase.IsValidFolder(settingsFolder))
{
AssetDatabase.CreateFolder("Assets/Settings", "Developer");
}
// Create new settings asset
T settings = CreateInstance<T>();
string path = $"{settingsFolder}/{fileName}.asset";
AssetDatabase.CreateAsset(settings, path);
AssetDatabase.SaveAssets();
allDeveloperSettings.Add(settings);
serializedSettingsObjects[typeof(T).Name] = new SerializedObject(settings);
Debug.Log($"Created missing developer settings asset: {path}");
}
else
{
// Load existing asset
string path = AssetDatabase.GUIDToAssetPath(guids[0]);
T settings = AssetDatabase.LoadAssetAtPath<T>(path);
allDeveloperSettings.Add(settings);
serializedSettingsObjects[typeof(T).Name] = new SerializedObject(settings);
}
}
}
private void OnGUI()
{
if (headerStyle == null)
{
headerStyle = new GUIStyle(EditorStyles.boldLabel);
headerStyle.fontSize = 14;
headerStyle.margin = new RectOffset(0, 0, 10, 10);
}
EditorGUILayout.Space(10);
EditorGUILayout.LabelField("Apple Hills Developer Settings", headerStyle);
EditorGUILayout.HelpBox("This editor is for technical settings intended for developers. For gameplay settings, use the Game Settings editor.", MessageType.Info);
EditorGUILayout.Space(10);
selectedTab = GUILayout.Toolbar(selectedTab, tabNames);
scrollPosition = EditorGUILayout.BeginScrollView(scrollPosition);
switch (selectedTab)
{
case 0: // Diving
DrawSettingsEditor<DivingDeveloperSettings>();
break;
case 1: // Debug
DrawSettingsEditor<DebugSettings>();
break;
case 2: // Other Systems
EditorGUILayout.HelpBox("Other developer settings will appear here as they are added.", MessageType.Info);
break;
// Add additional cases as more developer settings types are added
}
EditorGUILayout.EndScrollView();
EditorGUILayout.Space(10);
EditorGUILayout.BeginHorizontal();
GUILayout.FlexibleSpace();
if (GUILayout.Button("Refresh", GUILayout.Width(100)))
{
LoadAllSettings();
}
if (GUILayout.Button("Save All", GUILayout.Width(100)))
{
foreach (var serializedObj in serializedSettingsObjects.Values)
{
serializedObj.ApplyModifiedProperties();
EditorUtility.SetDirty(serializedObj.targetObject);
}
AssetDatabase.SaveAssets();
Debug.Log("All developer settings saved!");
}
EditorGUILayout.EndHorizontal();
}
private void DrawSettingsEditor<T>() where T : BaseDeveloperSettings
{
BaseDeveloperSettings settings = allDeveloperSettings.Find(s => s is T);
if (settings == null)
{
EditorGUILayout.HelpBox($"No {typeof(T).Name} found. Click Refresh to create one.", MessageType.Warning);
return;
}
SerializedObject serializedObj = serializedSettingsObjects[typeof(T).Name];
serializedObj.Update();
EditorGUILayout.Space(10);
// Draw all properties
SerializedProperty property = serializedObj.GetIterator();
bool enterChildren = true;
while (property.NextVisible(enterChildren))
{
enterChildren = false;
// Skip the script field
if (property.name == "m_Script") continue;
// Group headers
if (property.isArray && property.propertyType == SerializedPropertyType.Generic)
{
EditorGUILayout.LabelField(property.displayName, EditorStyles.boldLabel);
}
EditorGUILayout.PropertyField(property, true);
}
// Apply changes
if (serializedObj.ApplyModifiedProperties())
{
EditorUtility.SetDirty(settings);
// Trigger OnValidate on the asset
if (settings != null)
{
settings.OnValidate();
}
}
}
// Helper method to highlight important fields
private void DrawHighlightedProperty(SerializedProperty property, string tooltip = null)
{
GUI.backgroundColor = new Color(0.8f, 0.9f, 1f); // Light blue for developer settings
EditorGUILayout.BeginVertical(EditorStyles.helpBox);
GUI.backgroundColor = Color.white;
EditorGUILayout.PropertyField(property, new GUIContent(property.displayName, tooltip));
EditorGUILayout.EndVertical();
}
}
}

View File

@@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: 8ab6d9fee0924431b8e22edb500b35df
timeCreated: 1758710778

View File

@@ -0,0 +1,104 @@
using UnityEditor;
using AppleHills.Core.Settings;
using UnityEngine;
namespace AppleHills.Editor
{
/// <summary>
/// Provides access to settings in editor (non-play) mode
/// </summary>
[InitializeOnLoad]
public static class EditorSettingsProvider
{
private static PlayerFollowerSettings _playerFollowerSettings;
private static InteractionSettings _interactionSettings;
private static DivingMinigameSettings _divingMinigameSettings;
// Static constructor will be called when Unity loads/reloads scripts
static EditorSettingsProvider()
{
LoadAllSettings();
// Set up the delegates in SettingsAccess
AppleHills.SettingsAccess.SetupEditorProviders(
GetPlayerStopDistance,
GetPlayerStopDistanceDirectInteraction,
GetPuzzlePromptRange
);
// Subscribe to asset changes to auto-refresh when settings are modified
EditorApplication.delayCall += () =>
{
EditorApplication.projectChanged += OnProjectChanged;
};
}
private static void OnProjectChanged()
{
// Check if any settings assets have changed
if (HasSettingsChanged())
{
LoadAllSettings();
RefreshSceneViews();
}
}
private static bool HasSettingsChanged()
{
// Simplified check - you might want to make this more efficient
// by checking timestamps or specific files
return true;
}
public static void LoadAllSettings()
{
_playerFollowerSettings = AssetDatabase.LoadAssetAtPath<PlayerFollowerSettings>("Assets/Settings/PlayerFollowerSettings.asset");
_interactionSettings = AssetDatabase.LoadAssetAtPath<InteractionSettings>("Assets/Settings/InteractionSettings.asset");
_divingMinigameSettings = AssetDatabase.LoadAssetAtPath<DivingMinigameSettings>("Assets/Settings/MinigameSettings.asset");
// Re-register the delegates in case they were lost
AppleHills.SettingsAccess.SetupEditorProviders(
GetPlayerStopDistance,
GetPlayerStopDistanceDirectInteraction,
GetPuzzlePromptRange
);
Debug.Log("Editor settings loaded for Scene View use");
}
public static void RefreshSceneViews()
{
// Force scene views to repaint to refresh gizmos
SceneView.RepaintAll();
}
// Implementation of delegate methods
private static float GetPlayerStopDistance()
{
return _interactionSettings?.PlayerStopDistance ?? 6.0f;
}
private static float GetPlayerStopDistanceDirectInteraction()
{
return _interactionSettings?.PlayerStopDistanceDirectInteraction ?? 2.0f;
}
private static float GetPuzzlePromptRange()
{
return _interactionSettings?.DefaultPuzzlePromptRange ?? 3.0f;
}
// Other utility methods
public static T GetSettings<T>() where T : BaseSettings
{
if (typeof(T) == typeof(PlayerFollowerSettings))
return _playerFollowerSettings as T;
else if (typeof(T) == typeof(InteractionSettings))
return _interactionSettings as T;
else if (typeof(T) == typeof(DivingMinigameSettings))
return _divingMinigameSettings as T;
return null;
}
}
}

View File

@@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: 1e8da573a8db4ea892fe476592276e0f
timeCreated: 1758634265

View File

@@ -0,0 +1,195 @@
using UnityEngine;
using UnityEditor;
using System.Collections.Generic;
using System.Linq;
using System.IO;
namespace AppleHills.Core.Settings.Editor
{
public class SettingsEditorWindow : EditorWindow
{
private Vector2 scrollPosition;
private List<BaseSettings> allSettings = new List<BaseSettings>();
private string[] tabNames = new string[] { "Player & Follower", "Interaction & Items", "Diving Minigame" };
private int selectedTab = 0;
private Dictionary<string, SerializedObject> serializedSettingsObjects = new Dictionary<string, SerializedObject>();
private GUIStyle headerStyle;
[MenuItem("AppleHills/Settings Editor")]
public static void ShowWindow()
{
GetWindow<SettingsEditorWindow>("Game Settings");
}
private void OnEnable()
{
LoadAllSettings();
}
private void LoadAllSettings()
{
allSettings.Clear();
serializedSettingsObjects.Clear();
// Find all settings assets
string[] guids = AssetDatabase.FindAssets("t:BaseSettings");
foreach (string guid in guids)
{
string path = AssetDatabase.GUIDToAssetPath(guid);
BaseSettings settings = AssetDatabase.LoadAssetAtPath<BaseSettings>(path);
if (settings != null)
{
allSettings.Add(settings);
serializedSettingsObjects[settings.GetType().Name] = new SerializedObject(settings);
}
}
// If any settings are missing, create them
CreateSettingsIfMissing<PlayerFollowerSettings>("PlayerFollowerSettings");
CreateSettingsIfMissing<InteractionSettings>("InteractionSettings");
CreateSettingsIfMissing<DivingMinigameSettings>("DivingMinigameSettings");
}
private void CreateSettingsIfMissing<T>(string fileName) where T : BaseSettings
{
if (!allSettings.Any(s => s is T))
{
// Check if the asset already exists
string[] guids = AssetDatabase.FindAssets($"t:{typeof(T).Name}");
if (guids.Length == 0)
{
// Create the settings folder if it doesn't exist
if (!AssetDatabase.IsValidFolder("Assets/Settings"))
{
AssetDatabase.CreateFolder("Assets", "Settings");
}
// Create new settings asset
T settings = CreateInstance<T>();
string path = $"Assets/Settings/{fileName}.asset";
AssetDatabase.CreateAsset(settings, path);
AssetDatabase.SaveAssets();
allSettings.Add(settings);
serializedSettingsObjects[typeof(T).Name] = new SerializedObject(settings);
Debug.Log($"Created missing settings asset: {path}");
}
else
{
// Load existing asset
string path = AssetDatabase.GUIDToAssetPath(guids[0]);
T settings = AssetDatabase.LoadAssetAtPath<T>(path);
allSettings.Add(settings);
serializedSettingsObjects[typeof(T).Name] = new SerializedObject(settings);
}
}
}
private void OnGUI()
{
if (headerStyle == null)
{
headerStyle = new GUIStyle(EditorStyles.boldLabel);
headerStyle.fontSize = 14;
headerStyle.margin = new RectOffset(0, 0, 10, 10);
}
EditorGUILayout.Space(10);
EditorGUILayout.LabelField("Apple Hills Game Settings", headerStyle);
EditorGUILayout.HelpBox("Use this window to modify game settings. Changes are saved automatically.", MessageType.Info);
EditorGUILayout.Space(10);
selectedTab = GUILayout.Toolbar(selectedTab, tabNames);
scrollPosition = EditorGUILayout.BeginScrollView(scrollPosition);
switch (selectedTab)
{
case 0: // Player & Follower
DrawSettingsEditor<PlayerFollowerSettings>();
break;
case 1: // Interaction & Items
DrawSettingsEditor<InteractionSettings>();
break;
case 2: // Minigames
DrawSettingsEditor<DivingMinigameSettings>();
break;
}
EditorGUILayout.EndScrollView();
EditorGUILayout.Space(10);
EditorGUILayout.BeginHorizontal();
GUILayout.FlexibleSpace();
if (GUILayout.Button("Refresh", GUILayout.Width(100)))
{
LoadAllSettings();
}
if (GUILayout.Button("Save All", GUILayout.Width(100)))
{
foreach (var serializedObj in serializedSettingsObjects.Values)
{
serializedObj.ApplyModifiedProperties();
EditorUtility.SetDirty(serializedObj.targetObject);
}
AssetDatabase.SaveAssets();
// Refresh editor settings after save
AppleHills.Editor.EditorSettingsProvider.LoadAllSettings();
AppleHills.Editor.EditorSettingsProvider.RefreshSceneViews();
Debug.Log("All settings saved and editor views refreshed!");
}
EditorGUILayout.EndHorizontal();
}
private void DrawSettingsEditor<T>() where T : BaseSettings
{
BaseSettings settings = allSettings.Find(s => s is T);
if (settings == null)
{
EditorGUILayout.HelpBox($"No {typeof(T).Name} found. Click Refresh to create one.", MessageType.Warning);
return;
}
SerializedObject serializedObj = serializedSettingsObjects[typeof(T).Name];
serializedObj.Update();
EditorGUILayout.Space(10);
// Draw all properties
SerializedProperty property = serializedObj.GetIterator();
bool enterChildren = true;
while (property.NextVisible(enterChildren))
{
enterChildren = false;
// Skip the script field
if (property.name == "m_Script") continue;
EditorGUILayout.PropertyField(property, true);
}
// Apply changes
if (serializedObj.ApplyModifiedProperties())
{
EditorUtility.SetDirty(settings);
}
}
// Helper method to highlight important fields
private void DrawHighlightedProperty(SerializedProperty property, string tooltip = null)
{
GUI.backgroundColor = new Color(1f, 1f, 0.8f);
EditorGUILayout.BeginVertical(EditorStyles.helpBox);
GUI.backgroundColor = Color.white;
EditorGUILayout.PropertyField(property, new GUIContent(property.displayName, tooltip));
EditorGUILayout.EndVertical();
}
}
}

View File

@@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: bfb9e77c746e41a2903603a39df3d424
timeCreated: 1758619952