From 22fe6f8037a840582bf946cd687392235e514a67 Mon Sep 17 00:00:00 2001 From: Alijimpa Date: Mon, 22 Dec 2025 14:07:39 +0330 Subject: [PATCH 001/204] Cleanup Naming for Scyncing between Game & World --- Runtime/Core/Architecture/Game.cs | 200 +++++++++--------- Runtime/Core/Architecture/GameManager.cs | 2 +- Runtime/Core/Architecture/GameService.cs | 74 ++++++- Runtime/Core/Architecture/World.cs | 36 ++-- Runtime/ReadySet/DefaultsClass/DefaultGame.cs | 4 +- 5 files changed, 184 insertions(+), 132 deletions(-) diff --git a/Runtime/Core/Architecture/Game.cs b/Runtime/Core/Architecture/Game.cs index 81997b3..5487ab0 100644 --- a/Runtime/Core/Architecture/Game.cs +++ b/Runtime/Core/Architecture/Game.cs @@ -4,6 +4,10 @@ using UnityEngine.SceneManagement; using System.Linq; +#if UNITY_EDITOR +using UnityEditor; +#endif + namespace RealMethod { public abstract class Game : MonoBehaviour @@ -67,28 +71,29 @@ protected T NeedManager() where T : MonoBehaviour return Result; } // Private Functions - private void OnGameWorldReplaced(World NewWorld) + private void Notify_OnWorldInitiate(World NewWorld) { World = NewWorld; foreach (var service in GameServices) { - service.provider.WorldUpdated(); + service.Provider.WorldUpdated(); } - GameWorldSynced(World); + OnWorldChanged(World); } - private void OnGameQuit() + private void Notify_OnGameQuit() { - Application.quitting -= OnGameQuit; + ((IMethodSync)Service).UnbindMainWorldAdd(); + Application.quitting -= Notify_OnGameQuit; if (GameServices != null) { for (int i = 0; i < GameServices.Count; i++) { - GameServices[i].provider.Deleted(this); + GameServices[i].Provider.Deleted(this); GameServices.RemoveAt(i); } } - Service.provider.Deleted(this); - GameClosed(); + Service.Provider.Deleted(this); + OnGameClosed(); } // Public Static Functions public static T CastInstance() where T : class @@ -126,7 +131,7 @@ public static T CastWorld() where T : class // Create Service T newService = new T(); - newService.provider.Created(author); + newService.Provider.Created(author); if (Instance.Managers != null) { foreach (var manager in Instance.Managers) @@ -134,7 +139,7 @@ public static T CastWorld() where T : class manager.ResolveService(newService, true); } } - Service.OnServiceCreated?.Invoke(newService); + ((IMethodSync)Service).ServiceCreated(newService); Instance.GameServices.Add(newService); return newService; } @@ -150,8 +155,8 @@ public static bool RemoveService(object author) where T : Service manager.ResolveService(service, false); } } - Service.OnServiceRemoved?.Invoke(service); - service.provider.Deleted(author); + ((IMethodSync)Service).ServiceRemoved(service); + service.Provider.Deleted(author); Instance.GameServices.Remove(service); return true; } @@ -268,109 +273,108 @@ public static void SetSpeed(float speed, bool physicSafe = true) if (physicSafe) Time.fixedDeltaTime = 0.02f * Time.timeScale; // Keeps physics in sync } + public static void Quit() + { +#if UNITY_EDITOR + EditorApplication.isPlaying = false; +#else + Application.Quit(); +#endif + } // Private Static Functions [RuntimeInitializeOnLoadMethod(RuntimeInitializeLoadType.SubsystemRegistration)] private static void InitializeGame() { - Game[] components = FindObjectsByType(FindObjectsSortMode.InstanceID); - if (components.Length > 1) + // Load Project Setting + ProjectSettingAsset ProjectSettings = Resources.Load("RealMethod/RealMethodSetting"); + if (ProjectSettings == null) { - Debug.LogError($"Expected exactly one active 'Game' component in the scene, but found {components.Length}."); + Debug.LogError("ProjectSettingAsset is missing from Resources folder!"); + Quit(); return; } - // Load Project Setting - ProjectSettingAsset ProjectSettings = Resources.Load("RealMethod/RealMethodSetting"); - if (ProjectSettings != null) + + // Initiate Game Class + var emptyObject = new GameObject("RealGame"); + Type TargetClass = ProjectSettings.GetGameInstanceClass(); + if (TargetClass == null) { - // Initiate Game Class - if (components.Length == 0) - { - var emptyObject = new GameObject("RealGame"); - Type TargetClass = ProjectSettings.GetGameInstanceClass(); - if (TargetClass != null) - { - Instance = (Game)emptyObject.AddComponent(TargetClass); - if (Instance == null) - { - Debug.LogError($"Component of type {TargetClass} is not assignable from Game."); - Instance = emptyObject.AddComponent(); - } - } - else - { - Instance = emptyObject.AddComponent(); - } - } - else + Debug.LogWarning("GameInstanceClass that was empty. DefaultGame Created"); + Instance = emptyObject.AddComponent(); + } + if (typeof(Game).IsAssignableFrom(TargetClass)) + { + Instance = (Game)emptyObject.AddComponent(TargetClass); + } + else + { + Debug.LogWarning($"Component of type {TargetClass} is not assignable from Game. DefaultGame Created"); + Instance = emptyObject.AddComponent(); + } + + // Create Game Service + Type targetService = ProjectSettings.GetGameServiceClass(); + if (targetService == null) + { + Debug.LogWarning($"GetGameServiceClass that was empty. DefaultGameService Created"); + Service = new DefaultGameService(); + } + if (typeof(Service).IsAssignableFrom(targetService)) + { + try { - Instance = components[0]; + Service = (GameService)Activator.CreateInstance(targetService); } - // Create Game Service - Type targetService = ProjectSettings.GetGameServiceClass(); - if (targetService != null) - { - if (typeof(Service).IsAssignableFrom(targetService)) - { - try - { - Service = (GameService)Activator.CreateInstance(targetService); - } - catch (Exception ex) - { - Debug.LogError($"Failed to instantiate {targetService}: {ex.Message}"); - Service = new DefaultGameService(); - } - } - else - { - Debug.LogError($"Type {targetService} is not assignable to Service."); - Service = new DefaultGameService(); - } - } - else + catch (Exception ex) { + Debug.LogError($"Failed to instantiate {targetService}: {ex.Message}. DefaultGameService Created"); Service = new DefaultGameService(); } - Instance.GameServices = new List(3); - Service.OnWorldUpdate += Instance.OnGameWorldReplaced; - Service.provider.Created(Instance); - // Set Game Config - if (ProjectSettings.GetGameConfig() != null) - { - Config = ProjectSettings.GetGameConfig(); - } - else - { - Config = ScriptableObject.CreateInstance(); - } - Config.Initialized(Instance); - // Initiate GamePrefab & Managers - List CashManagers = new List(5); - foreach (var obj in ProjectSettings.GetGamePrefabs()) + } + else + { + Debug.LogWarning($"Type {targetService} is not assignable to Service. DefaultGameService Created"); + Service = new DefaultGameService(); + } + Instance.GameServices = new List(3); + ((IMethodSync)Service).BindMainWorldAdd(Instance.Notify_OnWorldInitiate); + Service.Provider.Created(Instance); + + // Set Game Config + if (ProjectSettings.GetGameConfig() != null) + { + Config = ProjectSettings.GetGameConfig(); + } + else + { + Config = ScriptableObject.CreateInstance(); + } + Config.Initialized(Instance); + + // Initiate GamePrefab & Managers + List CashManagers = new List(5); + foreach (var obj in ProjectSettings.GetGamePrefabs()) + { + if (obj != null) { - if (obj != null) + GameObject newobj = Instantiate(obj); + foreach (var manager in newobj.GetComponents()) { - GameObject newobj = Instantiate(obj); - foreach (var manager in newobj.GetComponents()) - { - manager.InitiateManager(true); - CashManagers.Add(manager); - } - DontDestroyOnLoad(newobj); + manager.InitiateManager(true); + CashManagers.Add(manager); } + DontDestroyOnLoad(newobj); } - Instance.Managers = CashManagers.ToArray(); - // Unload Project Setting - Resources.UnloadAsset(ProjectSettings); - // Move Self GameObject to DontDestroy - DontDestroyOnLoad(Instance.gameObject); - Application.quitting += Instance.OnGameQuit; - } - else - { - Debug.LogError("ProjectSettingAsset is missing from Resources folder!"); } + Instance.Managers = CashManagers.ToArray(); + + // Unload Project Setting + Resources.UnloadAsset(ProjectSettings); + + // Move Self GameObject to DontDestroy + DontDestroyOnLoad(Instance.gameObject); + Application.quitting += Instance.Notify_OnGameQuit; } [RuntimeInitializeOnLoadMethod(RuntimeInitializeLoadType.BeforeSceneLoad)] private static void RuntimeBeforeSceneLoad() @@ -392,8 +396,8 @@ private static void RuntimeAfterSceneLoad() // Abstract Methods protected abstract void GameInitialized(); protected abstract void GameStarted(); - protected abstract void GameWorldSynced(World NewWorld); - protected abstract void GameClosed(); + protected abstract void OnWorldChanged(World NewWorld); + protected abstract void OnGameClosed(); } } \ No newline at end of file diff --git a/Runtime/Core/Architecture/GameManager.cs b/Runtime/Core/Architecture/GameManager.cs index bf5c6e7..3b6290b 100644 --- a/Runtime/Core/Architecture/GameManager.cs +++ b/Runtime/Core/Architecture/GameManager.cs @@ -18,7 +18,7 @@ public interface IService public abstract class Service : IService { - public IService provider => this; + public IService Provider => this; // Implement IService Interface void IService.Created(object author) diff --git a/Runtime/Core/Architecture/GameService.cs b/Runtime/Core/Architecture/GameService.cs index 69717e5..b3afc46 100644 --- a/Runtime/Core/Architecture/GameService.cs +++ b/Runtime/Core/Architecture/GameService.cs @@ -8,19 +8,25 @@ namespace RealMethod { - public interface IWorldSync + public interface IMethodSync { bool IntroduceWorld(World world); + void BindMainWorldAdd(Action func); + void UnbindMainWorldAdd(); + void BindSideWorldAdd(Action func); + void UnbindSideWorldAdd(); + void ServiceCreated(Service service); + void ServiceRemoved(Service service); + void BindServicesUpdated(Action func); + void UnbindServicesUpdated(); } - public abstract class GameService : Service, IWorldSync + public abstract class GameService : Service, IMethodSync { - public IWorldSync Worldprovider => this; // Game Structure - public Action OnWorldUpdate; - public Action OnAdditiveWorld; - public Action OnServiceCreated; - public Action OnServiceRemoved; + private Action MainWorldEvent; + private Action SideWorldEvent; + private Action ServiceEvents; // Load Scene public Action OnSceneLoading; public Action OnSceneLoadingProcess; @@ -29,20 +35,66 @@ public abstract class GameService : Service, IWorldSync // Implement IWorldSync Interface // Any World in Awake time call this method - bool IWorldSync.IntroduceWorld(World world) + bool IMethodSync.IntroduceWorld(World world) { if (Game.World == null) { - OnWorldUpdate?.Invoke(world); + MainWorldEvent?.Invoke(world); return true; } else { - OnNewAdditiveWorld(world); - OnAdditiveWorld?.Invoke(world); + SideWorldEvent?.Invoke(world); return false; } } + void IMethodSync.BindMainWorldAdd(Action func) + { + if (MainWorldEvent != null) + { + Debug.LogWarning("BindMainWorldAdd is already binded this interface is internal didnt use in another script or your game"); + return; + } + MainWorldEvent = func; + } + void IMethodSync.UnbindMainWorldAdd() + { + MainWorldEvent = null; + } + void IMethodSync.BindSideWorldAdd(Action func) + { + if (SideWorldEvent != null) + { + Debug.LogWarning("BindSideWorldAdd is already binded this interface is internal didnt use in another script or your game"); + return; + } + SideWorldEvent = func; + } + void IMethodSync.UnbindSideWorldAdd() + { + SideWorldEvent = null; + } + void IMethodSync.ServiceCreated(Service service) + { + ServiceEvents.Invoke(service, true); + } + void IMethodSync.ServiceRemoved(Service service) + { + ServiceEvents.Invoke(service, false); + } + void IMethodSync.BindServicesUpdated(Action func) + { + if (ServiceEvents != null) + { + Debug.LogWarning("BindServicesUpdated is already binded this interface is internal didnt use in another script or your game"); + return; + } + ServiceEvents = func; + } + void IMethodSync.UnbindServicesUpdated() + { + ServiceEvents = null; + } // public Methods public virtual IEnumerator GetLoadScneCorotine(string sceneName) diff --git a/Runtime/Core/Architecture/World.cs b/Runtime/Core/Architecture/World.cs index a447056..972f5f3 100644 --- a/Runtime/Core/Architecture/World.cs +++ b/Runtime/Core/Architecture/World.cs @@ -23,14 +23,15 @@ public abstract class World : MonoBehaviour private void Awake() { //Connect to Game Service - if (Game.Service.Worldprovider.IntroduceWorld(this)) + IMethodSync SyncProvider = Game.Service; + if (SyncProvider.IntroduceWorld(this)) { - Game.Service.OnAdditiveWorld += AdditiveWorld; - Game.Service.OnServiceCreated += NotifyServiceCreated; - Game.Service.OnServiceRemoved += NotifyServiceRemoved; + SyncProvider.BindSideWorldAdd(Notify_OnAdditiveWorldInitiate); + SyncProvider.BindServicesUpdated(Notify_OnServicesUpdated); } else { + enabled = false; return; } @@ -54,9 +55,9 @@ private void Awake() } private void OnDestroy() { - Game.Service.OnAdditiveWorld -= AdditiveWorld; - Game.Service.OnServiceCreated -= NotifyServiceCreated; - Game.Service.OnServiceRemoved -= NotifyServiceRemoved; + IMethodSync SyncProvider = Game.Service; + SyncProvider.UnbindSideWorldAdd(); + SyncProvider.UnbindServicesUpdated(); } // Public Metthods public T GetManager() where T : class @@ -153,29 +154,24 @@ protected virtual bool InitiatePlayer(ref GameObject player) } } - protected virtual void AdditiveWorld(World TargetWorld) + protected virtual void OnAdditiveWorldAdded(GameObject WorldObject) { - Debug.LogWarning($"This World Class ({TargetWorld}) Deleted"); - Destroy(TargetWorld); + Destroy(WorldObject); } // Private Methods - private void NotifyServiceCreated(Service NewService) + private void Notify_OnAdditiveWorldInitiate(World TargetWorld) { - if (Managers != null) - { - foreach (var manager in Managers) - { - manager.ResolveService(NewService, true); - } - } + GameObject worldObject = TargetWorld.gameObject; + Destroy(TargetWorld); + OnAdditiveWorldAdded(worldObject); } - private void NotifyServiceRemoved(Service NewService) + private void Notify_OnServicesUpdated(Service NewService, bool stage) { if (Managers != null) { foreach (var manager in Managers) { - manager.ResolveService(NewService, false); + manager.ResolveService(NewService, stage); } } } diff --git a/Runtime/ReadySet/DefaultsClass/DefaultGame.cs b/Runtime/ReadySet/DefaultsClass/DefaultGame.cs index 764b121..57c2deb 100644 --- a/Runtime/ReadySet/DefaultsClass/DefaultGame.cs +++ b/Runtime/ReadySet/DefaultsClass/DefaultGame.cs @@ -14,11 +14,11 @@ protected override void GameStarted() { Debug.Log("DefultGame Started"); } - protected override void GameWorldSynced(World NewWorld) + protected override void OnWorldChanged(World NewWorld) { Debug.Log($"DefultGame Synced to {NewWorld}"); } - protected override void GameClosed() + protected override void OnGameClosed() { Debug.Log("DefultGame Closed"); } From cd2b47ea5722ac41e8cd66acebf2be18c214d868 Mon Sep 17 00:00:00 2001 From: Alijimpa Date: Mon, 22 Dec 2025 18:56:47 +0330 Subject: [PATCH 002/204] Refactor Core Section & Add Comment --- Editor/Core/Architecture/GameCompWindow.cs | 17 - Runtime/Core/Architecture/Game.cs | 450 ++++++++++++------ Runtime/Core/Architecture/GameConfig.cs | 14 + Runtime/Core/Architecture/GameManager.cs | 43 -- Runtime/Core/Architecture/GameService.cs | 108 ++++- Runtime/Core/Architecture/ManagerContracts.cs | 38 ++ .../Architecture/ManagerContracts.cs.meta | 2 + Runtime/Core/Architecture/ServiceContracts.cs | 64 +++ ...nager.cs.meta => ServiceContracts.cs.meta} | 0 Runtime/Core/Architecture/World.cs | 224 +++++++-- Runtime/Core/Architecture/WorldSceneConfig.cs | 38 +- Runtime/Core/Definitions/Assets.cs | 17 +- .../SceneReference.cs | 0 .../SceneReference.cs.meta | 0 .../SharedScripts/Structs/TransformData.cs | 8 +- .../DefaultsClass/DefaultGameService.cs | 4 - .../ReadySet/DefaultsClass/DefaultWorld.cs | 8 +- 17 files changed, 760 insertions(+), 275 deletions(-) delete mode 100644 Runtime/Core/Architecture/GameManager.cs create mode 100644 Runtime/Core/Architecture/ManagerContracts.cs create mode 100644 Runtime/Core/Architecture/ManagerContracts.cs.meta create mode 100644 Runtime/Core/Architecture/ServiceContracts.cs rename Runtime/Core/Architecture/{GameManager.cs.meta => ServiceContracts.cs.meta} (100%) rename Runtime/Core/{Architecture => Definitions}/SceneReference.cs (100%) rename Runtime/Core/{Architecture => Definitions}/SceneReference.cs.meta (100%) diff --git a/Editor/Core/Architecture/GameCompWindow.cs b/Editor/Core/Architecture/GameCompWindow.cs index 589ee28..13d6815 100644 --- a/Editor/Core/Architecture/GameCompWindow.cs +++ b/Editor/Core/Architecture/GameCompWindow.cs @@ -1,4 +1,3 @@ -using PlasticGui.WorkspaceWindow; using UnityEditor; namespace RealMethod @@ -18,10 +17,6 @@ public override void OnInspectorGUI() EditorGUILayout.Space(); if (BaseComponent != null) { - if (Game.World != null) - { - - } EditorGUILayout.LabelField($"{GetWorld()} | {GetSetvice()} | {GetConfig()}"); EditorGUILayout.Space(0.5f); string[] Data = BaseComponent.GetAllServiceNames(); @@ -32,10 +27,6 @@ public override void OnInspectorGUI() } } - - - - private string GetWorld() { return Game.World != null ? Game.World.GetType().Name : "World Not Valid"; @@ -49,14 +40,6 @@ private string GetConfig() return Game.Config != null ? Game.Config.GetType().Name : "GameConfig Not Valid"; } - - - - - - - - } diff --git a/Runtime/Core/Architecture/Game.cs b/Runtime/Core/Architecture/Game.cs index 5487ab0..9a710ef 100644 --- a/Runtime/Core/Architecture/Game.cs +++ b/Runtime/Core/Architecture/Game.cs @@ -10,13 +10,33 @@ namespace RealMethod { + /// + /// Core game singleton that manages the active , registered s, + /// configuration and high-level game lifecycle (initialization, start, and shutdown). + /// Derive from this class to implement project-specific behavior for the game's lifecycle hooks. + /// public abstract class Game : MonoBehaviour { - // Public Static Variables + /// + /// Singleton instance of the active game. + /// public static Game Instance; - public static GameConfig Config { get; private set; } + /// + /// The currently active . Updated when a world is initiated. + /// public static World World { get; private set; } + /// + /// The core implementation used for scene/world loading and service events. + /// public static GameService Service { get; private set; } + /// + /// Active game configuration instance. + /// + public static GameConfig Config { get; private set; } + /// + /// Convenience property returning the player GameObject from the current . + /// Returns null and logs a warning if no world is set. + /// public static GameObject Player { get @@ -29,73 +49,154 @@ public static GameObject Player return World.GetPlayerObject(); } } - public static bool isPaused => Time.timeScale == 0; + /// + /// Indicates whether the game is currently paused. + /// Returns true when Time.timeScale is set to 0; otherwise, false. + /// + public static bool IsPaused => Time.timeScale == 0; - // Private Variable + + /// + /// Cached array of managers that were instantiated from configured game prefabs. + /// private IGameManager[] Managers; + /// + /// List of runtime-registered instances owned by the game. + /// private List GameServices; - // Public Functions - public T GetManager() where T : class + + + + /// + /// Initializes the game singleton and core systems on subsystem registration. + /// This sets up the , game , + /// configuration, prefabs and managers and registers quit callbacks. + /// + [RuntimeInitializeOnLoadMethod(RuntimeInitializeLoadType.SubsystemRegistration)] + private static void InitializeGame() { - foreach (var manager in Managers) + // Load Project Setting + ProjectSettingAsset ProjectSettings = Resources.Load("RealMethod/RealMethodSetting"); + if (ProjectSettings == null) { - if (manager.GetManagerClass() is T Result) - { - return Result; - } + Debug.LogError("ProjectSettingAsset is missing from Resources folder!"); + Quit(); + return; } - return null; - } - public IGameManager GetManager(string ObjectName) - { - foreach (var manger in Managers) + + // Initiate Game Class + var emptyObject = new GameObject("RealGame"); + Type TargetClass = ProjectSettings.GetGameInstanceClass(); + if (TargetClass == null) { - if (manger.GetManagerClass().gameObject.name == ObjectName) + Debug.LogWarning("GameInstanceClass that was empty. DefaultGame Created"); + Instance = emptyObject.AddComponent(); + } + if (typeof(Game).IsAssignableFrom(TargetClass)) + { + Instance = (Game)emptyObject.AddComponent(TargetClass); + } + else + { + Debug.LogWarning($"Component of type {TargetClass} is not assignable from Game. DefaultGame Created"); + Instance = emptyObject.AddComponent(); + } + + // Create Game Service + Type targetService = ProjectSettings.GetGameServiceClass(); + if (targetService == null) + { + Debug.LogWarning($"GetGameServiceClass that was empty. DefaultGameService Created"); + Service = new DefaultGameService(); + } + if (typeof(Service).IsAssignableFrom(targetService)) + { + try { - return manger; + Service = (GameService)Activator.CreateInstance(targetService); + } + catch (Exception ex) + { + Debug.LogError($"Failed to instantiate {targetService}: {ex.Message}. DefaultGameService Created"); + Service = new DefaultGameService(); } } - return null; - } - // Protected Functions - protected T NeedManager() where T : MonoBehaviour - { - T Result = GetManager(); - if (Result == null) + else { - Result = gameObject.AddComponent(); - Debug.LogWarning($"Manager of type {typeof(T).Name} was not found. [A new one has been added]."); + Debug.LogWarning($"Type {targetService} is not assignable to Service. DefaultGameService Created"); + Service = new DefaultGameService(); + } + Instance.GameServices = new List(3); + ((IMethodSync)Service).BindMainWorldAdd(Instance.Notify_OnWorldInitiate); + ((IService)Service).Created(Instance); + // Set Game Config + if (ProjectSettings.GetGameConfig() != null) + { + Config = ProjectSettings.GetGameConfig(); } - return Result; + else + { + Config = ScriptableObject.CreateInstance(); + } + Config.Initialized(Instance); + + // Initiate GamePrefab & Managers + List CashManagers = new List(5); + foreach (var obj in ProjectSettings.GetGamePrefabs()) + { + if (obj != null) + { + GameObject newobj = Instantiate(obj); + foreach (var manager in newobj.GetComponents()) + { + manager.InitiateManager(true); + CashManagers.Add(manager); + } + DontDestroyOnLoad(newobj); + } + } + Instance.Managers = CashManagers.ToArray(); + + // Unload Project Setting + Resources.UnloadAsset(ProjectSettings); + ProjectSettings = null; + + // Move Self GameObject to DontDestroy + DontDestroyOnLoad(Instance.gameObject); + Application.quitting += Instance.Notify_OnGameQuit; } - // Private Functions - private void Notify_OnWorldInitiate(World NewWorld) + /// + /// Called before any scene is loaded. Invokes on the active instance. + /// + [RuntimeInitializeOnLoadMethod(RuntimeInitializeLoadType.BeforeSceneLoad)] + private static void RuntimeBeforeSceneLoad() { - World = NewWorld; - foreach (var service in GameServices) + if (Instance != null) { - service.Provider.WorldUpdated(); + Instance.GameInitialized(); } - OnWorldChanged(World); } - private void Notify_OnGameQuit() + /// + /// Called after a scene has finished loading. Invokes on the active instance. + /// + [RuntimeInitializeOnLoadMethod(RuntimeInitializeLoadType.AfterSceneLoad)] + private static void RuntimeAfterSceneLoad() { - ((IMethodSync)Service).UnbindMainWorldAdd(); - Application.quitting -= Notify_OnGameQuit; - if (GameServices != null) + if (Instance != null) { - for (int i = 0; i < GameServices.Count; i++) - { - GameServices[i].Provider.Deleted(this); - GameServices.RemoveAt(i); - } + Instance.GameStarted(); } - Service.Provider.Deleted(this); - OnGameClosed(); } - // Public Static Functions + + + /// + /// Attempts to cast the global to the specified type . + /// Logs an error and returns null if the cast fails. + /// + /// The target type to cast the instance to. + /// The casted instance of type , or null on failure. public static T CastInstance() where T : class { if (Instance is T CastedInstance) @@ -108,6 +209,12 @@ public static T CastInstance() where T : class return null; } } + /// + /// Attempts to cast the current to the specified type . + /// Logs an error and returns null if the cast fails. + /// + /// The target type to cast the world to. + /// The casted world of type , or null on failure. public static T CastWorld() where T : class { if (World is T CastedWorld) @@ -120,6 +227,13 @@ public static T CastWorld() where T : class return null; } } + /// + /// Adds a new service of type to the game if one does not already exist. + /// Newly created service will be bound to managers and notified to the global service system. + /// + /// Service type to add. + /// The object responsible for creating the service (used for provider callbacks). + /// The newly created service instance, or null if a service of the same type already exists. public static T AddService(object author) where T : Service, new() { // Check if a service of this type already exists @@ -131,7 +245,7 @@ public static T CastWorld() where T : class // Create Service T newService = new T(); - newService.Provider.Created(author); + ((IService)newService).Created(author); if (Instance.Managers != null) { foreach (var manager in Instance.Managers) @@ -143,6 +257,13 @@ public static T CastWorld() where T : class Instance.GameServices.Add(newService); return newService; } + /// + /// Removes the first service instance of type if present. + /// Managers and the global service system will be notified of the removal. + /// + /// Service type to remove. + /// The object requesting the removal (used for provider callbacks). + /// true if a service was found and removed; otherwise false. public static bool RemoveService(object author) where T : Service { var service = Instance.GameServices.FirstOrDefault(s => s.GetType() == typeof(T)); @@ -156,7 +277,7 @@ public static bool RemoveService(object author) where T : Service } } ((IMethodSync)Service).ServiceRemoved(service); - service.Provider.Deleted(author); + ((IService)service).Deleted(author); Instance.GameServices.Remove(service); return true; } @@ -164,10 +285,21 @@ public static bool RemoveService(object author) where T : Service Debug.LogWarning($"Service of type {typeof(T).Name} not found to remove."); return false; } + /// + /// Retrieves the first service instance of type if available. + /// + /// Service type to retrieve. + /// The service instance of type , or null if not found. public static T GetService() where T : Service { return Instance.GameServices.OfType().FirstOrDefault(); } + /// + /// Retrieves a service by its concrete . + /// Returns null and logs an error if the provided type is not a . + /// + /// Concrete service type to look up. + /// The matching service instance, or null if not found or invalid type. public static Service GetService(Type type) { if (!typeof(Service).IsAssignableFrom(type)) @@ -178,15 +310,31 @@ public static Service GetService(Type type) return Instance.GameServices.FirstOrDefault(s => s.GetType() == type); } + /// + /// Attempts to find a service of type . + /// + /// Service type to find. + /// Out parameter that receives the service if found. + /// true if the service was found; otherwise false. public static bool TryFindService(out T service) where T : Service { service = Instance.GameServices.OfType().FirstOrDefault(); return service != null; } + /// + /// Returns the type names of all registered game services. + /// + /// Array of service type names. public string[] GetAllServiceNames() { return GameServices.Select(service => service.GetType().Name).ToArray(); } + /// + /// Requests a scene load by build index via the configured . + /// If the requested scene is already active, a warning is logged and null is returned. + /// + /// Build index of the scene to open. + /// A driving the load operation, or null if not started. public static Coroutine OpenScene(int sceneIndex) { if (SceneManager.GetActiveScene().buildIndex != sceneIndex) @@ -199,10 +347,21 @@ public static Coroutine OpenScene(int sceneIndex) return null; } } + /// + /// Requests a scene load using a . + /// + /// Reference describing the scene to load. + /// A driving the load operation, or null if not started. public static Coroutine OpenScene(SceneReference scene) { return OpenScene(scene.ScneName); } + /// + /// Requests a scene load by name via the configured . + /// If the requested scene is already active, a warning is logged and null is returned. + /// + /// Name of the scene to open. + /// A driving the load operation, or null if not started. public static Coroutine OpenScene(string sceneName) { if (SceneManager.GetActiveScene().name != sceneName) @@ -215,6 +374,12 @@ public static Coroutine OpenScene(string sceneName) return null; } } + /// + /// Loads a multi-scene world configuration using the provided . + /// If the persistent scene for the world is already loaded, a warning is logged and null is returned. + /// + /// World scene configuration to load. + /// A driving the world load operation, or null if not started. public static Coroutine OpenWorld(WorldSceneConfig WorldScene) { if (SceneManager.GetActiveScene().buildIndex != SceneManager.GetSceneByPath(WorldScene.Persistent).buildIndex) @@ -227,10 +392,20 @@ public static Coroutine OpenWorld(WorldSceneConfig WorldScene) return null; } } + /// + /// Reloads the currently active scene via the configured . + /// + /// A driving the reload operation. public static Coroutine ReOpenScene() { return Instance.StartCoroutine(Service.GetLoadScneCorotine(SceneManager.GetActiveScene().name)); ; } + /// + /// Finds a manager of type in the current , + /// falling back to the global game managers if not found. + /// + /// Manager type to find. + /// An instance of the manager if found; otherwise null. public static T FindManager() where T : MonoBehaviour { T Result = null; @@ -246,10 +421,20 @@ public static T FindManager() where T : MonoBehaviour } return Instance.GetManager(); } + /// + /// Parents the provided GameObject to the game root instance. + /// + /// The GameObject to hold under the game root. public static void HoldGameObject(GameObject Target) { Target.transform.SetParent(Instance.transform); } + /// + /// Searches for a child GameObject with the given name and reparents it to . + /// + /// Name of the child GameObject to find. + /// New parent GameObject to assign. + /// true if the child was found and reparented; otherwise false. public static bool UnHoldGameObject(string GameObjectName, GameObject Target) { Transform[] Childs = Instance.GetComponentsInChildren(); @@ -263,16 +448,28 @@ public static bool UnHoldGameObject(string GameObjectName, GameObject Target) } return false; } + /// + /// Pauses or resumes the game by setting . + /// + /// If true the game is paused; otherwise resumed. public static void SetPause(bool paused) { Time.timeScale = paused ? 0 : 1; } + /// + /// Sets the global time scale and optionally adjusts fixed delta time for physics safety. + /// + /// New time scale to apply. + /// If true adjusts to keep physics stable. public static void SetSpeed(float speed, bool physicSafe = true) { Time.timeScale = speed; if (physicSafe) Time.fixedDeltaTime = 0.02f * Time.timeScale; // Keeps physics in sync } + /// + /// Quits the application. In the Unity Editor this stops play mode instead. + /// public static void Quit() { #if UNITY_EDITOR @@ -282,121 +479,94 @@ public static void Quit() #endif } - // Private Static Functions - [RuntimeInitializeOnLoadMethod(RuntimeInitializeLoadType.SubsystemRegistration)] - private static void InitializeGame() - { - // Load Project Setting - ProjectSettingAsset ProjectSettings = Resources.Load("RealMethod/RealMethodSetting"); - if (ProjectSettings == null) - { - Debug.LogError("ProjectSettingAsset is missing from Resources folder!"); - Quit(); - return; - } - // Initiate Game Class - var emptyObject = new GameObject("RealGame"); - Type TargetClass = ProjectSettings.GetGameInstanceClass(); - if (TargetClass == null) - { - Debug.LogWarning("GameInstanceClass that was empty. DefaultGame Created"); - Instance = emptyObject.AddComponent(); - } - if (typeof(Game).IsAssignableFrom(TargetClass)) - { - Instance = (Game)emptyObject.AddComponent(TargetClass); - } - else - { - Debug.LogWarning($"Component of type {TargetClass} is not assignable from Game. DefaultGame Created"); - Instance = emptyObject.AddComponent(); - } - - // Create Game Service - Type targetService = ProjectSettings.GetGameServiceClass(); - if (targetService == null) - { - Debug.LogWarning($"GetGameServiceClass that was empty. DefaultGameService Created"); - Service = new DefaultGameService(); - } - if (typeof(Service).IsAssignableFrom(targetService)) + /// + /// Retrieves a manager of type from this game's instantiated managers. + /// + /// Manager type to retrieve. + /// The manager instance if found; otherwise null. + public T GetManager() where T : class + { + foreach (var manager in Managers) { - try - { - Service = (GameService)Activator.CreateInstance(targetService); - } - catch (Exception ex) + if (manager.GetManagerClass() is T Result) { - Debug.LogError($"Failed to instantiate {targetService}: {ex.Message}. DefaultGameService Created"); - Service = new DefaultGameService(); + return Result; } } - else - { - Debug.LogWarning($"Type {targetService} is not assignable to Service. DefaultGameService Created"); - Service = new DefaultGameService(); - } - Instance.GameServices = new List(3); - ((IMethodSync)Service).BindMainWorldAdd(Instance.Notify_OnWorldInitiate); - Service.Provider.Created(Instance); - - // Set Game Config - if (ProjectSettings.GetGameConfig() != null) - { - Config = ProjectSettings.GetGameConfig(); - } - else - { - Config = ScriptableObject.CreateInstance(); - } - Config.Initialized(Instance); - - // Initiate GamePrefab & Managers - List CashManagers = new List(5); - foreach (var obj in ProjectSettings.GetGamePrefabs()) + return null; + } + /// + /// Retrieves an by the name of its GameObject. + /// + /// Name of the manager GameObject to find. + /// The matching , or null if none match. + public IGameManager GetManager(string ObjectName) + { + foreach (var manger in Managers) { - if (obj != null) + if (manger.GetManagerClass().gameObject.name == ObjectName) { - GameObject newobj = Instantiate(obj); - foreach (var manager in newobj.GetComponents()) - { - manager.InitiateManager(true); - CashManagers.Add(manager); - } - DontDestroyOnLoad(newobj); + return manger; } } - Instance.Managers = CashManagers.ToArray(); + return null; + } - // Unload Project Setting - Resources.UnloadAsset(ProjectSettings); - // Move Self GameObject to DontDestroy - DontDestroyOnLoad(Instance.gameObject); - Application.quitting += Instance.Notify_OnGameQuit; - } - [RuntimeInitializeOnLoadMethod(RuntimeInitializeLoadType.BeforeSceneLoad)] - private static void RuntimeBeforeSceneLoad() + /// + /// Callback invoked when a new is created or assigned. + /// Updates the static reference and notifies all services. + /// + /// The newly initiated world instance. + private void Notify_OnWorldInitiate(World NewWorld) { - if (Instance != null) + World = NewWorld; + foreach (var service in GameServices) { - Instance.GameInitialized(); + ((IService)service).WorldUpdated(); } + OnWorldChanged(World); } - [RuntimeInitializeOnLoadMethod(RuntimeInitializeLoadType.AfterSceneLoad)] - private static void RuntimeAfterSceneLoad() + /// + /// Handles application quit events: unbinds world callbacks, deletes services and invokes . + /// + private void Notify_OnGameQuit() { - if (Instance != null) + ((IMethodSync)Service).UnbindMainWorldAdd(); + Application.quitting -= Notify_OnGameQuit; + if (GameServices != null) { - Instance.GameStarted(); + for (int i = 0; i < GameServices.Count; i++) + { + ((IService)GameServices[i]).Deleted(this); + GameServices.RemoveAt(i); + } } + ((IService)Service).Deleted(this); + OnGameClosed(); } - // Abstract Methods + + /// + /// Called once when the game framework has finished initial initialization. + /// Implement this to perform game-specific initialization logic. + /// protected abstract void GameInitialized(); + /// + /// Called after the first scene has been loaded and the game has started. + /// Implement this to perform logic that should run once the first scene is active. + /// protected abstract void GameStarted(); + /// + /// Called when the current reference changes. + /// Implement to react to world switches. + /// + /// The new active world. protected abstract void OnWorldChanged(World NewWorld); + /// + /// Called when the game is closing. Implement to perform cleanup logic. + /// protected abstract void OnGameClosed(); } diff --git a/Runtime/Core/Architecture/GameConfig.cs b/Runtime/Core/Architecture/GameConfig.cs index 109059d..98c9ad6 100644 --- a/Runtime/Core/Architecture/GameConfig.cs +++ b/Runtime/Core/Architecture/GameConfig.cs @@ -3,14 +3,28 @@ namespace RealMethod { + /// + /// Base configuration asset for game-wide settings and initialization logic. + /// public abstract class GameConfig : ConfigAsset { [Header("Game")] [SerializeField] private float fadeTime = 0; + /// + /// Gets the duration (in seconds) used for screen fade transitions. + /// public float FadeTime => fadeTime; + /// + /// Called when the game is initialized, allowing the configuration + /// to apply settings or perform setup logic. + /// + /// + /// The Game instance responsible for initialization. + /// public abstract void Initialized(Game Author); } + } \ No newline at end of file diff --git a/Runtime/Core/Architecture/GameManager.cs b/Runtime/Core/Architecture/GameManager.cs deleted file mode 100644 index 3b6290b..0000000 --- a/Runtime/Core/Architecture/GameManager.cs +++ /dev/null @@ -1,43 +0,0 @@ -using UnityEngine; - -namespace RealMethod -{ - public interface IGameManager - { - MonoBehaviour GetManagerClass(); - void InitiateManager(bool AlwaysLoaded); - void ResolveService(Service service, bool active); - } - - public interface IService - { - void Created(object author); - void WorldUpdated(); - void Deleted(object author); - } - - public abstract class Service : IService - { - public IService Provider => this; - - // Implement IService Interface - void IService.Created(object author) - { - OnStart(author); - } - void IService.WorldUpdated() - { - OnNewWorld(); - } - void IService.Deleted(object author) - { - OnEnd(author); - } - - // Abstract Method - protected abstract void OnStart(object Author); - protected abstract void OnNewWorld(); - protected abstract void OnEnd(object Author); - } - -} \ No newline at end of file diff --git a/Runtime/Core/Architecture/GameService.cs b/Runtime/Core/Architecture/GameService.cs index b3afc46..d7974e6 100644 --- a/Runtime/Core/Architecture/GameService.cs +++ b/Runtime/Core/Architecture/GameService.cs @@ -8,33 +8,94 @@ namespace RealMethod { + /// + /// Defines synchronization hooks used internally to coordinate + /// worlds and services during runtime initialization. + /// public interface IMethodSync { + /// + /// Introduces a newly created world to the system. + /// + /// The world instance being introduced. + /// + /// True if the world is treated as the main world; + /// false if it is considered a side/additive world. + /// bool IntroduceWorld(World world); + /// + /// Binds a callback invoked when the main world is added. + /// void BindMainWorldAdd(Action func); + /// + /// Unbinds the main world added callback. + /// void UnbindMainWorldAdd(); + /// + /// Binds a callback invoked when a side (additive) world is added. + /// void BindSideWorldAdd(Action func); + /// + /// Unbinds the side world added callback. + /// void UnbindSideWorldAdd(); + /// + /// Notifies the system that a service has been created. + /// void ServiceCreated(Service service); + /// + /// Notifies the system that a service has been removed. + /// void ServiceRemoved(Service service); + /// + /// Binds a callback invoked when services are added or removed. + /// + /// + /// Callback receiving the service instance and its active state. + /// void BindServicesUpdated(Action func); + /// + /// Unbinds the service update callback. + /// void UnbindServicesUpdated(); } + + /// + /// Base class for any game services in the framework. + /// Provides core functionality for: + /// + /// World synchronization (main and additive worlds) + /// Service lifecycle notifications (created/removed) + /// Scene and world loading with progress reporting + /// + /// Inherits from and implements + /// to integrate with the game's internal world and service management system. + /// public abstract class GameService : Service, IMethodSync { + /// + /// Event invoked when a scene or world starts or finishes loading. + /// The boolean parameter is true when loading starts and false when loading ends. + /// + public event Action OnSceneLoading; + /// + /// Event invoked during scene or world loading to report progress. + /// The float parameter represents the loading progress from 0 (start) to 1 (complete). + /// + public event Action OnSceneLoadingProcess; + /// + /// Indicates whether a scene or world load operation is currently in progress. + /// + public bool IsLoading { get; protected set; } + // Game Structure private Action MainWorldEvent; private Action SideWorldEvent; private Action ServiceEvents; - // Load Scene - public Action OnSceneLoading; - public Action OnSceneLoadingProcess; - public bool IsLoading { get; protected set; } - // Implement IWorldSync Interface - // Any World in Awake time call this method + // Implement IMethodSync Interface bool IMethodSync.IntroduceWorld(World world) { if (Game.World == null) @@ -96,7 +157,15 @@ void IMethodSync.UnbindServicesUpdated() ServiceEvents = null; } - // public Methods + + /// + /// Starts loading a scene by name using a coroutine. + /// + /// The name of the scene to load. + /// + /// An IEnumerator coroutine for loading the scene, + /// or null if a load operation is already in progress. + /// public virtual IEnumerator GetLoadScneCorotine(string sceneName) { if (IsLoading == true) @@ -106,6 +175,14 @@ public virtual IEnumerator GetLoadScneCorotine(string sceneName) } return LoadSceneAsync(sceneName); } + /// + /// Starts loading a scene by build index using a coroutine. + /// + /// The build index of the scene to load. + /// + /// An IEnumerator coroutine for loading the scene, + /// or null if a load operation is already in progress. + /// public virtual IEnumerator GetLoadScneCorotine(int sceneIndex) { if (IsLoading == true) @@ -115,6 +192,14 @@ public virtual IEnumerator GetLoadScneCorotine(int sceneIndex) } return LoadSceneAsync(string.Empty, sceneIndex); } + /// + /// Starts loading a world configuration using a coroutine. + /// + /// The world scene configuration to load. + /// + /// An IEnumerator coroutine for loading the world, + /// or null if a load operation is already in progress. + /// public virtual IEnumerator GetLoadWorldCorotine(WorldSceneConfig WorldScene) { if (IsLoading == true) @@ -125,8 +210,6 @@ public virtual IEnumerator GetLoadWorldCorotine(WorldSceneConfig WorldScene) return LoadWorldAsync(WorldScene); } - // Abstract Methods - protected abstract void OnNewAdditiveWorld(World target); // Corotine private IEnumerator LoadSceneAsync(string scene, int scneIndex = -1) @@ -238,9 +321,11 @@ private IEnumerator LoadWorldAsync(WorldSceneConfig WS) } + + + #if UNITY_EDITOR - // Runs when entering Play Mode in Editor - [InitializeOnEnterPlayMode] + [InitializeOnEnterPlayMode] // Runs when entering Play Mode in Editor private static void EditorPlayModeInit() { var assets = Resources.FindObjectsOfTypeAll(); @@ -254,5 +339,6 @@ private static void EditorPlayModeInit() } #endif + } } \ No newline at end of file diff --git a/Runtime/Core/Architecture/ManagerContracts.cs b/Runtime/Core/Architecture/ManagerContracts.cs new file mode 100644 index 0000000..fec74db --- /dev/null +++ b/Runtime/Core/Architecture/ManagerContracts.cs @@ -0,0 +1,38 @@ +using UnityEngine; + +namespace RealMethod +{ + /// + /// Defines the core behavior required for all game manager classes. + /// + public interface IGameManager + { + /// + /// Returns the MonoBehaviour instance that implements this manager. + /// + /// + /// The MonoBehaviour associated with this game manager. + /// + MonoBehaviour GetManagerClass(); + + /// + /// Initializes the manager and prepares it for use in the game lifecycle. + /// + /// + /// If true, the manager should persist and remain loaded at all times. + /// + void InitiateManager(bool AlwaysLoaded); + + /// + /// Enables or disables a service handled by this manager. + /// + /// + /// The service to be resolved or managed. + /// + /// + /// Indicates whether the service should be activated (true) or deactivated (false). + /// + void ResolveService(Service service, bool active); + } + +} \ No newline at end of file diff --git a/Runtime/Core/Architecture/ManagerContracts.cs.meta b/Runtime/Core/Architecture/ManagerContracts.cs.meta new file mode 100644 index 0000000..66608a9 --- /dev/null +++ b/Runtime/Core/Architecture/ManagerContracts.cs.meta @@ -0,0 +1,2 @@ +fileFormatVersion: 2 +guid: d4832fe965ec2e242a7b04504a965182 \ No newline at end of file diff --git a/Runtime/Core/Architecture/ServiceContracts.cs b/Runtime/Core/Architecture/ServiceContracts.cs new file mode 100644 index 0000000..ed1a575 --- /dev/null +++ b/Runtime/Core/Architecture/ServiceContracts.cs @@ -0,0 +1,64 @@ + +namespace RealMethod +{ + /// + /// Defines the contract for a service that can respond to lifecycle events. + /// + public interface IService + { + /// + /// Called when the service is created. + /// + /// The object responsible for creating the service. + void Created(object author); + /// + /// Called when the world or environment updates. + /// + void WorldUpdated(); + /// + /// Called when the service is deleted or destroyed. + /// + /// The object responsible for deleting the service. + void Deleted(object author); + } + + /// + /// Base abstract class implementing . + /// Provides a framework for derived services to handle lifecycle events. + /// + public abstract class Service : IService + { + // Implement IService Interface + void IService.Created(object author) + { + OnStart(author); + } + void IService.WorldUpdated() + { + OnNewWorld(); + } + void IService.Deleted(object author) + { + OnEnd(author); + } + + + /// + /// Called when the service starts. Must be implemented by derived classes. + /// + /// The object responsible for creating the service. + protected abstract void OnStart(object Author); + /// + /// Called when a new world or environment is initialized. + /// Must be implemented by derived classes. + /// + protected abstract void OnNewWorld(); + /// + /// Called when the service ends or is deleted. + /// Must be implemented by derived classes. + /// + /// The object responsible for deleting the service. + protected abstract void OnEnd(object Author); + } + +} \ No newline at end of file diff --git a/Runtime/Core/Architecture/GameManager.cs.meta b/Runtime/Core/Architecture/ServiceContracts.cs.meta similarity index 100% rename from Runtime/Core/Architecture/GameManager.cs.meta rename to Runtime/Core/Architecture/ServiceContracts.cs.meta diff --git a/Runtime/Core/Architecture/World.cs b/Runtime/Core/Architecture/World.cs index 972f5f3..6c6ed51 100644 --- a/Runtime/Core/Architecture/World.cs +++ b/Runtime/Core/Architecture/World.cs @@ -3,23 +3,39 @@ namespace RealMethod { + public abstract class PlayerStarter : MonoBehaviour + { + [Header("Starter")] + [SerializeField] + private string posName = "None"; + public string PosName => posName; + } + + /// + /// Base class representing a game world / scene context. + /// Manages the player GameObject, locates and initializes child game managers, + /// and forwards service updates to managers. Concrete worlds should implement + /// and to perform + /// world-specific initialization and cleanup. + /// public abstract class World : MonoBehaviour { [Header("Player")] [SerializeField] - private bool IsPlayerInScene = true; - [SerializeField, ConditionalHide("IsPlayerInScene", true, false), TagSelector] - private string PlayerTag = "Player"; - [SerializeField, ConditionalHide("IsPlayerInScene", true, true)] - private GameObject DefualtPlayer; - [SerializeField, ConditionalHide("IsPlayerInScene", true, true)] - private Transform SpawnPoint; - - // Private Variable + private Prefab DefualtPlayer; + + private IGameManager[] Managers; private GameObject PlayerObject; - // Base Method + + + /// + /// Unity callback invoked when the script instance is being loaded. + /// Connects the world to the game service, binds service callbacks, + /// initializes child managers and locates or creates the player object, + /// then calls for world-specific initialization. + /// private void Awake() { //Connect to Game Service @@ -46,20 +62,38 @@ private void Awake() Managers = CashManagers.ToArray(); //Find Player or Create newone - if (!InitiatePlayer(ref PlayerObject)) + var scneplayer = GetPlayerInScene(); + if (scneplayer == null) { - return; + var starters = FindObjectsByType(FindObjectsSortMode.InstanceID); + Transform SpawnPoint = SelectSpawnPoint(starters); + PlayerObject = SpawnPlayer(DefualtPlayer, SpawnPoint); + } + else + { + PlayerObject = scneplayer; } - AwakeWorld(); + WorldBegin(); } + /// + /// Unity callback invoked when the object is being destroyed. + /// Unbinds previously bound service callbacks to avoid dangling references. + /// private void OnDestroy() { IMethodSync SyncProvider = Game.Service; SyncProvider.UnbindSideWorldAdd(); SyncProvider.UnbindServicesUpdated(); + WorldEnd(); } - // Public Metthods + + + /// + /// Returns a manager instance of the requested type if one exists on this world. + /// + /// The manager type to search for. + /// The manager instance cast to , or null if not found. public T GetManager() where T : class { foreach (var manager in Managers) @@ -71,6 +105,11 @@ public T GetManager() where T : class } return null; } + /// + /// Returns a manager whose associated GameObject has the specified name. + /// + /// The name of the manager's GameObject to find. + /// The matching , or null if none match. public IGameManager GetManager(string ObjectName) { foreach (var manger in Managers) @@ -82,18 +121,43 @@ public IGameManager GetManager(string ObjectName) } return null; } + /// + /// Returns the primary player for this world. + /// + /// Player index when supporting multiple players (currently unused). + /// The player GameObject reference, or null if none is present. public GameObject GetPlayerObject(byte index = 0) { return PlayerObject; } + /// + /// Gets a component of type from the player GameObject. + /// + /// Component type to retrieve (must derive from ). + /// Player index when supporting multiple players (currently unused). + /// The component instance if found; otherwise null. public T GetPlayerComponent(byte index = 0) where T : MonoBehaviour { return PlayerObject.GetComponent(); } + /// + /// Gets a component or class of type from the player GameObject. + /// This is a generic helper that uses Unity's GetComponent and returns the result + /// as a reference type. + /// + /// The class type to retrieve. + /// Player index when supporting multiple players (currently unused). + /// The requested class instance, or null if not found. public T GetPlayerClass(byte index = 0) where T : class { return PlayerObject.GetComponent(); } + /// + /// Retrieves all components of type attached to the player GameObject. + /// + /// Component type to retrieve. + /// Player index when supporting multiple players (currently unused). + /// Array of components if found; otherwise null and a warning is logged. public T[] GetPlayerComponents(byte index = 0) where T : MonoBehaviour { T[] components = PlayerObject.GetComponents(); @@ -104,6 +168,12 @@ public T[] GetPlayerComponents(byte index = 0) where T : MonoBehaviour Debug.LogWarning($"No components of type {typeof(T).Name} found on {PlayerObject.name} or its children."); return null; } + /// + /// Retrieves all components of type from the player GameObject and its children. + /// + /// Component type to retrieve. + /// Player index when supporting multiple players (currently unused). + /// Array of components if found; otherwise null and a warning is logged. public T[] GetPlayerComponentsInChilderen(byte index = 0) where T : MonoBehaviour { T[] components = PlayerObject.GetComponentsInChildren(); @@ -114,57 +184,106 @@ public T[] GetPlayerComponentsInChilderen(byte index = 0) where T : MonoBehav Debug.LogWarning($"No components of type {typeof(T).Name} found on {PlayerObject.name} or its children."); return null; } + /// + /// Retrieves the first component of type found on the player GameObject or its children. + /// + /// Component type to retrieve. + /// Player index when supporting multiple players (currently unused). + /// The component instance if found; otherwise null. public T GetPlayerComponentsInChildren(byte index = 0) where T : MonoBehaviour { return PlayerObject.GetComponentInChildren(); } - // Virtual Methods - protected virtual bool InitiatePlayer(ref GameObject player) + + + /// + /// Spawns the player character at the specified spawn point. + /// + /// + /// The player prefab to instantiate. If invalid, a fallback empty Player GameObject is created. + /// + /// + /// The transform representing the position and rotation where the player should spawn. + /// + /// + /// The spawned player GameObject. + /// + protected virtual GameObject SpawnPlayer(Prefab playerPrefab, Transform spawnPoint) { - if (IsPlayerInScene) + if (playerPrefab.IsValid()) { - player = GameObject.FindGameObjectWithTag(PlayerTag); - if (!player) - { - Debug.LogError("PlayerGameObject Cant Find in Scene"); - return false; - } - return true; + Transform player = Instantiate(playerPrefab.GetSoftClassTarget(), spawnPoint.position, spawnPoint.rotation); + player.SendMessage("OnSpawn", this, SendMessageOptions.DontRequireReceiver); + return player.gameObject; } else { - if (DefualtPlayer != null) - { - if (SpawnPoint) - { - player = Instantiate(DefualtPlayer, SpawnPoint.position, SpawnPoint.rotation); - } - else - { - player = Instantiate(DefualtPlayer, transform.position, Quaternion.identity); - } - return true; - } - else - { - player = new GameObject("Player"); - player.tag = "Player"; - return true; - } - + GameObject player = new GameObject("Player"); + player.tag = "Player"; + return player; + } + } + /// + /// Searches the current scene for an existing player GameObject. + /// + /// + /// The first GameObject found with the "Player" tag, or null if none exists. + /// + protected virtual GameObject GetPlayerInScene() + { + return GameObject.FindGameObjectWithTag("Player"); + } + /// + /// Selects a spawn point from the available PlayerStarter components. + /// + /// + /// An array of PlayerStarter objects that define possible spawn locations. + /// + /// + /// The transform of the selected spawn point. If none are available, + /// the current object's transform at the world origin is used. + /// + protected virtual Transform SelectSpawnPoint(PlayerStarter[] starters) + { + if (starters.Length > 0) + { + return starters[0].transform; + } + else + { + transform.position = Vector3.zero; + return transform; } } + /// + /// Called when an additive world GameObject is added to this world. + /// Default behaviour is to destroy the provided object; override to implement custom handling. + /// + /// The additive world GameObject that was added. protected virtual void OnAdditiveWorldAdded(GameObject WorldObject) { Destroy(WorldObject); } - // Private Methods + + + /// + /// Internal callback invoked by the service when an additive world is initiated. + /// Extracts the world GameObject, destroys the component instance, + /// and forwards the object to . + /// + /// The additive instance that was initiated. private void Notify_OnAdditiveWorldInitiate(World TargetWorld) { GameObject worldObject = TargetWorld.gameObject; Destroy(TargetWorld); OnAdditiveWorldAdded(worldObject); } + /// + /// Internal callback invoked when services are updated. Forwards the service update + /// to all managers so they can resolve or react to the change. + /// + /// The service that changed. + /// The stage or phase of the service update. private void Notify_OnServicesUpdated(Service NewService, bool stage) { if (Managers != null) @@ -175,8 +294,19 @@ private void Notify_OnServicesUpdated(Service NewService, bool stage) } } } - // Abstract Methods - protected abstract void AwakeWorld(); - protected abstract void DestroyWorld(); + + + /// + /// Called after the world is initialized in the context of this scene. + /// If this world is the main world, this runs normally. + /// If this world is loaded additively, it runs in additive context. + /// Use this to set up scene-specific systems, not global main-world logic. + /// + protected abstract void WorldBegin(); + /// + /// Called when the world is being destroyed to perform cleanup of world-specific state. + /// Implementations should release resources and unregister any world-specific hooks here. + /// + protected abstract void WorldEnd(); } } \ No newline at end of file diff --git a/Runtime/Core/Architecture/WorldSceneConfig.cs b/Runtime/Core/Architecture/WorldSceneConfig.cs index dda47d1..e8babb3 100644 --- a/Runtime/Core/Architecture/WorldSceneConfig.cs +++ b/Runtime/Core/Architecture/WorldSceneConfig.cs @@ -7,34 +7,58 @@ namespace RealMethod { + /// + /// ScriptableObject for configuring a world scene setup in Unity. + /// Allows specifying a persistent scene and multiple additive layers. + /// [CreateAssetMenu(fileName = "WorldScene", menuName = "Scene/WorldScene", order = 1)] public class WorldSceneConfig : ConfigAsset { [Header("Scenes")] + /// + /// The persistent scene that is always loaded and acts as the base scene. + /// [SerializeField] private SceneReference persistent; + /// + /// Public getter for the persistent scene. + /// public SceneReference Persistent => persistent; + /// + /// Array of additive layer scenes that can be loaded alongside the persistent scene. + /// [SerializeField] private SceneReference[] Layers; + /// + /// Gets the number of additive layer scenes. + /// public int Count => Layers.Length; + /// + /// Indexer to access additive layer scenes by index. + /// + /// Index of the layer scene. + /// The at the specified index. + public SceneReference this[int index] => Layers[index]; + + - public SceneReference this[int index] - { - get => Layers[index]; - } #if UNITY_EDITOR + /// + /// Opens the persistent scene and all additive layer scenes in the editor. + /// Only available in the Unity Editor. + /// public void OnAssetClick() { + // Open the persistent base scene in Single mode EditorSceneManager.OpenScene(Persistent, OpenSceneMode.Single); + + // Open all layer scenes additively foreach (var item in Layers) { EditorSceneManager.OpenScene(item, OpenSceneMode.Additive); } } #endif - - - } } \ No newline at end of file diff --git a/Runtime/Core/Definitions/Assets.cs b/Runtime/Core/Definitions/Assets.cs index fc40859..c28237c 100644 --- a/Runtime/Core/Definitions/Assets.cs +++ b/Runtime/Core/Definitions/Assets.cs @@ -44,6 +44,7 @@ public bool IsProjectAsset() #endif } + #if UNITY_EDITOR public virtual void OnEditorPlay() { @@ -57,7 +58,7 @@ public virtual void OnEditorPlay() public abstract class DataAsset : PrimitiveAsset { } - // TemplateAsset: is a PrimitiveAsset that you can't create new at runtime + // TemplateAsset: is a PrimitiveAsset that you can't create new at runtime & Should Use With Clone public abstract class TemplateAsset : PrimitiveAsset { protected virtual void OnEnable() @@ -72,6 +73,13 @@ protected virtual void OnEnable() } } } + +#if UNITY_EDITOR + public override void OnEditorPlay() + { + + } +#endif } // FileAsset: is a PrimitiveAsset that you can't clone at runtime public abstract class FileAsset : PrimitiveAsset @@ -104,6 +112,13 @@ protected virtual void OnEnable() return; } } + +#if UNITY_EDITOR + public override void OnEditorPlay() + { + + } +#endif } // ConfigAsset: is a UniqueAsset that you can't decelar modifier variable or method , all of things should be readonly public abstract class ConfigAsset : UniqueAsset diff --git a/Runtime/Core/Architecture/SceneReference.cs b/Runtime/Core/Definitions/SceneReference.cs similarity index 100% rename from Runtime/Core/Architecture/SceneReference.cs rename to Runtime/Core/Definitions/SceneReference.cs diff --git a/Runtime/Core/Architecture/SceneReference.cs.meta b/Runtime/Core/Definitions/SceneReference.cs.meta similarity index 100% rename from Runtime/Core/Architecture/SceneReference.cs.meta rename to Runtime/Core/Definitions/SceneReference.cs.meta diff --git a/Runtime/Library/SharedScripts/Structs/TransformData.cs b/Runtime/Library/SharedScripts/Structs/TransformData.cs index f541146..8fdc6a9 100644 --- a/Runtime/Library/SharedScripts/Structs/TransformData.cs +++ b/Runtime/Library/SharedScripts/Structs/TransformData.cs @@ -14,6 +14,12 @@ public TransformData(Vector3 pos, Quaternion rot, Vector3 scl) rotation = rot; scale = scl; } + public TransformData(Transform comp) + { + position = comp.position; + rotation = comp.rotation; + scale = comp.localScale; + } public static TransformData FromTransform(Transform t) { @@ -241,7 +247,7 @@ public static TransformData Scale(TransformData a, TransformData b, float t, Qua Vector3.Scale(a.scale, new Vector3(q.x, q.y, q.z)) ); } - + } } diff --git a/Runtime/ReadySet/DefaultsClass/DefaultGameService.cs b/Runtime/ReadySet/DefaultsClass/DefaultGameService.cs index 79b3c9f..2731fa7 100644 --- a/Runtime/ReadySet/DefaultsClass/DefaultGameService.cs +++ b/Runtime/ReadySet/DefaultsClass/DefaultGameService.cs @@ -10,10 +10,6 @@ protected override void OnStart(object Author) } protected override void OnNewWorld() { - } - protected override void OnNewAdditiveWorld(World target) - { - } protected override void OnEnd(object Author) { diff --git a/Runtime/ReadySet/DefaultsClass/DefaultWorld.cs b/Runtime/ReadySet/DefaultsClass/DefaultWorld.cs index 1712602..68cac71 100644 --- a/Runtime/ReadySet/DefaultsClass/DefaultWorld.cs +++ b/Runtime/ReadySet/DefaultsClass/DefaultWorld.cs @@ -5,13 +5,13 @@ namespace RealMethod [AddComponentMenu("RealMethod/Essential/DefaultWorld")] public sealed class DefaultWorld : World { - protected override void AwakeWorld() + protected override void WorldBegin() { - Debug.Log("DefaultWorld Awaked"); + Debug.Log("DefaultWorld Begin"); } - protected override void DestroyWorld() + protected override void WorldEnd() { - Debug.Log("DefaultWorld Destroyed"); + Debug.Log("DefaultWorld End"); } } } \ No newline at end of file From 0adb4fe1f59f941f86f8425789cd0e7344662575 Mon Sep 17 00:00:00 2001 From: Alijimpa Date: Tue, 23 Dec 2025 15:15:05 +0330 Subject: [PATCH 003/204] Refactor Prefab Define --- Editor/Core/Definitions/PrefabDrawer.cs | 26 ++++++++++++++++--------- Runtime/Core/Definitions/Prefab.cs | 6 +++--- 2 files changed, 20 insertions(+), 12 deletions(-) diff --git a/Editor/Core/Definitions/PrefabDrawer.cs b/Editor/Core/Definitions/PrefabDrawer.cs index 7962de3..c5a9840 100644 --- a/Editor/Core/Definitions/PrefabDrawer.cs +++ b/Editor/Core/Definitions/PrefabDrawer.cs @@ -1,4 +1,3 @@ -#if UNITY_EDITOR using UnityEditor; using UnityEngine; using System; @@ -14,12 +13,16 @@ public override void OnGUI(Rect position, SerializedProperty property, GUIConten if (prefabGOProp == null) { - EditorGUI.LabelField(position, label.text, "Invalid Prefab Field"); + EditorGUI.LabelField(position, label.text, "Cannot serialize generic prefab"); return; } EditorGUI.BeginProperty(position, label, property); + // Determine label text + // string displayLabel = prefabGOProp.objectReferenceValue != null ? label.text: $"{label.text} (Select a prefab...)"; + + // Draw the ObjectField for GameObject UnityEngine.Object newObject = EditorGUI.ObjectField( position, label, @@ -28,6 +31,7 @@ public override void OnGUI(Rect position, SerializedProperty property, GUIConten false ); + // Only update if changed if (newObject != prefabGOProp.objectReferenceValue) { if (newObject == null) @@ -36,19 +40,19 @@ public override void OnGUI(Rect position, SerializedProperty property, GUIConten } else if (PrefabUtility.IsPartOfPrefabAsset(newObject)) { - GameObject go = newObject as GameObject; - - // Get the actual object instance for this SerializedProperty - PrefabCore targetPrefab = GetTargetObjectOfProperty(property) as PrefabCore; + // Get the concrete PrefabCore instance + PrefabCore targetPrefab = fieldInfo.GetValue(property.serializedObject.targetObject) as PrefabCore; if (targetPrefab == null) { - EditorGUI.LabelField(position, label.text, "Invalid prefab wrapper."); + Debug.LogWarning("Invalid prefab wrapper."); return; } var targetClass = targetPrefab.GetTargetClass(); + GameObject go = newObject as GameObject; + // Type-check: the prefab must have the required component if (targetClass != null && go.GetComponent(targetClass) != null) { prefabGOProp.objectReferenceValue = newObject; @@ -64,10 +68,15 @@ public override void OnGUI(Rect position, SerializedProperty property, GUIConten } } + // --- Set GUI color to blue to indicate change --- + Color prevColor = GUI.color; + GUI.color = Color.cyan; // light blue + EditorGUI.ObjectField(position, label, prefabGOProp.objectReferenceValue, typeof(GameObject), false); + GUI.color = prevColor; EditorGUI.EndProperty(); } - // Utility to get the real object from a SerializedProperty + // --- Utility to get the actual object instance from SerializedProperty --- private object GetTargetObjectOfProperty(SerializedProperty prop) { if (prop == null) return null; @@ -114,4 +123,3 @@ private object GetValue(object source, string name, int index) } } } -#endif diff --git a/Runtime/Core/Definitions/Prefab.cs b/Runtime/Core/Definitions/Prefab.cs index c031ef8..be83a65 100644 --- a/Runtime/Core/Definitions/Prefab.cs +++ b/Runtime/Core/Definitions/Prefab.cs @@ -34,18 +34,18 @@ public bool HasInterface() [System.Serializable] public class PrefabCore : PrefabCore where T : Component { - // Prefab Methods + // PrefabCore Methods public override bool IsValid() { return asset != null && asset.GetComponent() != null; } + public override System.Type GetTargetClass() => typeof(T); // <--- implemented + // Public Method public T GetSoftClassTarget() { return asset.GetComponent(); } - - public override System.Type GetTargetClass() => typeof(T); // <--- implemented } From 9bdfe4539c8629008e7b5a78cbc19025962a040f Mon Sep 17 00:00:00 2001 From: Alijimpa Date: Tue, 23 Dec 2025 15:15:21 +0330 Subject: [PATCH 004/204] Implement Player Starter into project --- .../Core/Definitions/ConfigAssetValidator.cs | 3 - Editor/Core/Definitions/DataAssetEditor.cs | 4 +- .../ReadySet/Content/RealMethod_GameObject.cs | 27 ++++++++ .../Content/RealMethod_GameObject.cs.meta | 2 + Editor/ReadySet/Content/RealMethod_Prefab.cs | 2 +- Runtime/Core/Architecture/Game.cs | 8 ++- Runtime/Core/Architecture/GameService.cs | 24 ++++++- Runtime/Core/Architecture/World.cs | 7 +- Runtime/Library/Utilities/Draw.cs | 64 +++++++++++++++++-- .../Method/PlayerStarterComponent.cs | 31 +++++++++ .../Method/PlayerStarterComponent.cs.meta | 2 + 11 files changed, 155 insertions(+), 19 deletions(-) create mode 100644 Editor/ReadySet/Content/RealMethod_GameObject.cs create mode 100644 Editor/ReadySet/Content/RealMethod_GameObject.cs.meta create mode 100644 Runtime/ReadySet/Components/Method/PlayerStarterComponent.cs create mode 100644 Runtime/ReadySet/Components/Method/PlayerStarterComponent.cs.meta diff --git a/Editor/Core/Definitions/ConfigAssetValidator.cs b/Editor/Core/Definitions/ConfigAssetValidator.cs index bec8bc5..4d69de6 100644 --- a/Editor/Core/Definitions/ConfigAssetValidator.cs +++ b/Editor/Core/Definitions/ConfigAssetValidator.cs @@ -1,4 +1,3 @@ -#if UNITY_EDITOR using UnityEditor; using UnityEngine; using System; @@ -84,6 +83,4 @@ private static bool ViolatesPureMethodRules(MethodInfo method) return false; } } -#endif - } \ No newline at end of file diff --git a/Editor/Core/Definitions/DataAssetEditor.cs b/Editor/Core/Definitions/DataAssetEditor.cs index 2ee63d0..ece664f 100644 --- a/Editor/Core/Definitions/DataAssetEditor.cs +++ b/Editor/Core/Definitions/DataAssetEditor.cs @@ -1,4 +1,3 @@ -#if UNITY_EDITOR using UnityEditor; using UnityEngine; @@ -23,5 +22,4 @@ public static void DrawSubEditor (Object settings, ref bool foldout, ref UnityEd } } } -} -#endif \ No newline at end of file +} \ No newline at end of file diff --git a/Editor/ReadySet/Content/RealMethod_GameObject.cs b/Editor/ReadySet/Content/RealMethod_GameObject.cs new file mode 100644 index 0000000..720c92a --- /dev/null +++ b/Editor/ReadySet/Content/RealMethod_GameObject.cs @@ -0,0 +1,27 @@ +using UnityEditor; +using UnityEngine; + +namespace RealMethod.Editor +{ + class RealMethodGameObject + { + [MenuItem("GameObject/RealMethod/PlayerStarter", false, 10)] + static void CreatePlayerStarter(MenuCommand menuCommand) + { + // Create a new GameObject + GameObject go = new GameObject("PlayerStarter"); + + // Optional: add components + go.AddComponent(); + + // Place it in the scene, parented if needed + GameObjectUtility.SetParentAndAlign(go, menuCommand.context as GameObject); + + // Register the creation in Undo system (so Ctrl+Z works) + Undo.RegisterCreatedObjectUndo(go, "Create " + go.name); + + // Select the new GameObject + Selection.activeObject = go; + } + } +} \ No newline at end of file diff --git a/Editor/ReadySet/Content/RealMethod_GameObject.cs.meta b/Editor/ReadySet/Content/RealMethod_GameObject.cs.meta new file mode 100644 index 0000000..5a7589f --- /dev/null +++ b/Editor/ReadySet/Content/RealMethod_GameObject.cs.meta @@ -0,0 +1,2 @@ +fileFormatVersion: 2 +guid: d20b067d280180f4cbcf52a7b71ae786 \ No newline at end of file diff --git a/Editor/ReadySet/Content/RealMethod_Prefab.cs b/Editor/ReadySet/Content/RealMethod_Prefab.cs index 5227ed6..54cfc8b 100644 --- a/Editor/ReadySet/Content/RealMethod_Prefab.cs +++ b/Editor/ReadySet/Content/RealMethod_Prefab.cs @@ -1,7 +1,7 @@ using RealMethod.Editor; using UnityEditor; -namespace RealMethod +namespace RealMethod.Editor { class RealMethodPrefab { diff --git a/Runtime/Core/Architecture/Game.cs b/Runtime/Core/Architecture/Game.cs index 9a710ef..ceff0d3 100644 --- a/Runtime/Core/Architecture/Game.cs +++ b/Runtime/Core/Architecture/Game.cs @@ -435,17 +435,19 @@ public static void HoldGameObject(GameObject Target) /// Name of the child GameObject to find. /// New parent GameObject to assign. /// true if the child was found and reparented; otherwise false. - public static bool UnHoldGameObject(string GameObjectName, GameObject Target) + public static bool TryUnholdGameObject(string GameObjectName, out GameObject result) { Transform[] Childs = Instance.GetComponentsInChildren(); foreach (var item in Childs) { if (item.gameObject.name == GameObjectName) { - item.SetParent(Target.transform); + item.SetParent(null); + result = item.gameObject; return true; } } + result = null; return false; } /// @@ -533,8 +535,8 @@ private void Notify_OnWorldInitiate(World NewWorld) /// private void Notify_OnGameQuit() { - ((IMethodSync)Service).UnbindMainWorldAdd(); Application.quitting -= Notify_OnGameQuit; + ((IMethodSync)Service).UnbindMainWorldAdd(); if (GameServices != null) { for (int i = 0; i < GameServices.Count; i++) diff --git a/Runtime/Core/Architecture/GameService.cs b/Runtime/Core/Architecture/GameService.cs index d7974e6..9f2f93d 100644 --- a/Runtime/Core/Architecture/GameService.cs +++ b/Runtime/Core/Architecture/GameService.cs @@ -95,6 +95,7 @@ public abstract class GameService : Service, IMethodSync private Action ServiceEvents; + // Implement IMethodSync Interface bool IMethodSync.IntroduceWorld(World world) { @@ -284,7 +285,7 @@ private IEnumerator LoadWorldAsync(WorldSceneConfig WS) } while (!Load_opertation.isDone) { - OnSceneLoadingProcess?.Invoke(RM_Math.Map.RemapClamped(Load_opertation.progress, 0, 1, 0, 1 / WS.Count + 1)); + OnSceneLoadingProcess?.Invoke(Clamped(Load_opertation.progress, 0, 1, 0, 1 / WS.Count + 1)); OnSceneLoading?.Invoke(false); IsLoading = false; yield return null; @@ -303,7 +304,7 @@ private IEnumerator LoadWorldAsync(WorldSceneConfig WS) } while (!Additive_Load_opertation.isDone) { - OnSceneLoadingProcess?.Invoke(RM_Math.Map.RemapClamped(Load_opertation.progress, 0, 1, 0, 1 / WS.Count + 1 - (i + 1))); + OnSceneLoadingProcess?.Invoke(Clamped(Load_opertation.progress, 0, 1, 0, 1 / WS.Count + 1 - (i + 1))); yield return null; } } @@ -321,6 +322,25 @@ private IEnumerator LoadWorldAsync(WorldSceneConfig WS) } + // Private Functions + private float Clamped(float value, float inMin, float inMax, float outMin, float outMax) + { + // Prevent divide by zero + if (Mathf.Approximately(inMax, inMin)) + { + Debug.LogWarning("Input range is zero. Returning outMin."); + return outMin; + } + + // Normalize the input value to 0–1 within the input range + float t = (value - inMin) / (inMax - inMin); + + // Scale and offset to target range + float mappedValue = t * (outMax - outMin) + outMin; + + // Clamp result to the output range + return Mathf.Clamp(mappedValue, Mathf.Min(outMin, outMax), Mathf.Max(outMin, outMax)); + } diff --git a/Runtime/Core/Architecture/World.cs b/Runtime/Core/Architecture/World.cs index 6c6ed51..562e42d 100644 --- a/Runtime/Core/Architecture/World.cs +++ b/Runtime/Core/Architecture/World.cs @@ -5,7 +5,7 @@ namespace RealMethod { public abstract class PlayerStarter : MonoBehaviour { - [Header("Starter")] + [Header("Setting")] [SerializeField] private string posName = "None"; public string PosName => posName; @@ -76,6 +76,7 @@ private void Awake() WorldBegin(); } + /// /// Unity callback invoked when the object is being destroyed. /// Unbinds previously bound service callbacks to avoid dangling references. @@ -220,6 +221,7 @@ protected virtual GameObject SpawnPlayer(Prefab playerPrefab, Transform spawnPoi { GameObject player = new GameObject("Player"); player.tag = "Player"; + player.transform.SetPositionAndRotation(spawnPoint.position, spawnPoint.rotation); return player; } } @@ -247,7 +249,8 @@ protected virtual Transform SelectSpawnPoint(PlayerStarter[] starters) { if (starters.Length > 0) { - return starters[0].transform; + int index = Random.Range(0, starters.Length); + return starters[index].transform; } else { diff --git a/Runtime/Library/Utilities/Draw.cs b/Runtime/Library/Utilities/Draw.cs index e717172..eb47d0d 100644 --- a/Runtime/Library/Utilities/Draw.cs +++ b/Runtime/Library/Utilities/Draw.cs @@ -1,3 +1,4 @@ +using UnityEditor; using UnityEngine; namespace RealMethod @@ -6,7 +7,7 @@ public static class RM_Draw { public class gizmos { - public static void DrawCurve(AnimationCurve curve) + public static void Curve(AnimationCurve curve) { for (float t = 0; t < curve.keys[curve.length - 1].time; t += 0.1f) { @@ -14,7 +15,7 @@ public static void DrawCurve(AnimationCurve curve) } } // Draws a directional arrow using Gizmos (no color) - public static void DrawArrow(Vector3 position, Vector3 direction, float arrowHeadLength = 0.25f, float arrowHeadAngle = 20.0f) + public static void Arrow(Vector3 position, Vector3 direction, float arrowHeadLength = 0.25f, float arrowHeadAngle = 20.0f) { Gizmos.DrawRay(position, direction); @@ -24,7 +25,7 @@ public static void DrawArrow(Vector3 position, Vector3 direction, float arrowHea Gizmos.DrawRay(position + direction, left * arrowHeadLength); } // Draws a directional arrow using Gizmos (with color) - public static void DrawArrow(Vector3 position, Vector3 direction, Color color, float arrowHeadLength = 0.25f, float arrowHeadAngle = 20.0f) + public static void Arrow(Vector3 position, Vector3 direction, Color color, float arrowHeadLength = 0.25f, float arrowHeadAngle = 20.0f) { Gizmos.color = color; Gizmos.DrawRay(position, direction); @@ -34,12 +35,65 @@ public static void DrawArrow(Vector3 position, Vector3 direction, Color color, f Gizmos.DrawRay(position + direction, right * arrowHeadLength); Gizmos.DrawRay(position + direction, left * arrowHeadLength); } + // Draws a Capsule using Gizmos (no color) + public static void Capsule(Vector3 position, float height = 2f, float radius = 0.5f) + { + // Draw top sphere + Vector3 top = position + Vector3.up * (height / 2 - radius); + Gizmos.DrawWireSphere(top, radius); + + // Draw bottom sphere + Vector3 bottom = position + Vector3.down * (height / 2 - radius); + Gizmos.DrawWireSphere(bottom, radius); + + // Draw cylinder (approximation) + Gizmos.DrawLine(top + Vector3.forward * radius, bottom + Vector3.forward * radius); + Gizmos.DrawLine(top - Vector3.forward * radius, bottom - Vector3.forward * radius); + Gizmos.DrawLine(top + Vector3.right * radius, bottom + Vector3.right * radius); + Gizmos.DrawLine(top - Vector3.right * radius, bottom - Vector3.right * radius); + } + // Draws a Capsule using Gizmos (with color) + public static void Capsule(Vector3 position, Color color, float height = 2f, float radius = 0.5f) + { + // Save previous Gizmos color + Color prevColor = Gizmos.color; + Gizmos.color = color; + + // Draw top sphere + Vector3 top = position + Vector3.up * (height / 2 - radius); + Gizmos.DrawWireSphere(top, radius); + + // Draw bottom sphere + Vector3 bottom = position + Vector3.down * (height / 2 - radius); + Gizmos.DrawWireSphere(bottom, radius); + + // Draw cylinder (approximation) + Gizmos.DrawLine(top + Vector3.forward * radius, bottom + Vector3.forward * radius); + Gizmos.DrawLine(top - Vector3.forward * radius, bottom - Vector3.forward * radius); + Gizmos.DrawLine(top + Vector3.right * radius, bottom + Vector3.right * radius); + Gizmos.DrawLine(top - Vector3.right * radius, bottom - Vector3.right * radius); + + // Restore previous color + Gizmos.color = prevColor; + } + // Draw a Text using Gizmos (With Colort) + public static void Text(string text, Vector3 position, Color color, FontStyle font = FontStyle.Bold, TextAnchor ancher = TextAnchor.MiddleCenter) + { + // Set color + GUIStyle style = new GUIStyle(); + style.normal.textColor = color; + style.alignment = ancher; + style.fontStyle = font; + + // Draw the label above the GameObject + Handles.Label(position, text, style); + } } public class debug { // Draws a directional arrow using Debug.DrawRay (no color) - public static void DrawArrow(Vector3 position, Vector3 direction, float arrowHeadLength = 0.25f, float arrowHeadAngle = 20.0f) + public static void Arrow(Vector3 position, Vector3 direction, float arrowHeadLength = 0.25f, float arrowHeadAngle = 20.0f) { Debug.DrawRay(position, direction); @@ -49,7 +103,7 @@ public static void DrawArrow(Vector3 position, Vector3 direction, float arrowHea Debug.DrawRay(position + direction, left * arrowHeadLength); } // Draws a directional arrow using Debug.DrawRay (with color) - public static void DrawArrow(Vector3 position, Vector3 direction, Color color, float arrowHeadLength = 0.25f, float arrowHeadAngle = 20.0f) + public static void Arrow(Vector3 position, Vector3 direction, Color color, float arrowHeadLength = 0.25f, float arrowHeadAngle = 20.0f) { Debug.DrawRay(position, direction, color); diff --git a/Runtime/ReadySet/Components/Method/PlayerStarterComponent.cs b/Runtime/ReadySet/Components/Method/PlayerStarterComponent.cs new file mode 100644 index 0000000..a938873 --- /dev/null +++ b/Runtime/ReadySet/Components/Method/PlayerStarterComponent.cs @@ -0,0 +1,31 @@ +using UnityEngine; + +namespace RealMethod +{ + [AddComponentMenu("RealMethod/Method/PlayerStarter")] + public class PlayerStarterComponent : PlayerStarter + { + [Header("Debug")] + [SerializeField] + private float height = 2f; + [SerializeField] + private float radius = 0.5f; + + + // Unity Methods + private void Awake() + { + Destroy(gameObject); + } + + +#if UNITY_EDITOR + protected virtual void OnDrawGizmos() + { + RM_Draw.gizmos.Capsule(transform.position, Color.cyan, height, radius); + RM_Draw.gizmos.Arrow(transform.position, transform.forward, Color.red); + RM_Draw.gizmos.Text(PosName, transform.position + (transform.up * (height / 2)) + (Vector3.up * 0.1f), Color.black); + } +#endif + } +} \ No newline at end of file diff --git a/Runtime/ReadySet/Components/Method/PlayerStarterComponent.cs.meta b/Runtime/ReadySet/Components/Method/PlayerStarterComponent.cs.meta new file mode 100644 index 0000000..95d243c --- /dev/null +++ b/Runtime/ReadySet/Components/Method/PlayerStarterComponent.cs.meta @@ -0,0 +1,2 @@ +fileFormatVersion: 2 +guid: bd7492c4fc6b670479f8f302f507dd22 \ No newline at end of file From 977f0b9e24dc9f403f4a472ae8a5111c51fd59df Mon Sep 17 00:00:00 2001 From: Alijimpa Date: Tue, 23 Dec 2025 15:15:55 +0330 Subject: [PATCH 005/204] Change Header in World --- Runtime/Core/Architecture/World.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Runtime/Core/Architecture/World.cs b/Runtime/Core/Architecture/World.cs index 562e42d..1e3bbb8 100644 --- a/Runtime/Core/Architecture/World.cs +++ b/Runtime/Core/Architecture/World.cs @@ -20,7 +20,7 @@ public abstract class PlayerStarter : MonoBehaviour /// public abstract class World : MonoBehaviour { - [Header("Player")] + [Header("Setting")] [SerializeField] private Prefab DefualtPlayer; From d725126f9abe7d0fd1305c003d317933b8da2e0d Mon Sep 17 00:00:00 2001 From: Alijimpa Date: Tue, 23 Dec 2025 15:41:06 +0330 Subject: [PATCH 006/204] Refine all Script Template for Core --- Reservoir/ScriptTemplates/GameConfigTemplate.txt | 3 ++- .../ScriptTemplates/GameServiceTemplate.txt | 16 +--------------- Reservoir/ScriptTemplates/GameTemplate.txt | 15 ++++++++++++--- Reservoir/ScriptTemplates/ManagerTemplate.txt | 16 +++++++++------- Reservoir/ScriptTemplates/ServiceTemplate.txt | 5 +++++ Reservoir/ScriptTemplates/WorldTemplate.txt | 9 ++++++--- 6 files changed, 35 insertions(+), 29 deletions(-) diff --git a/Reservoir/ScriptTemplates/GameConfigTemplate.txt b/Reservoir/ScriptTemplates/GameConfigTemplate.txt index 7e7ae08..bca67f2 100644 --- a/Reservoir/ScriptTemplates/GameConfigTemplate.txt +++ b/Reservoir/ScriptTemplates/GameConfigTemplate.txt @@ -4,8 +4,9 @@ using RealMethod; [CreateAssetMenu(fileName = "#SCRIPTNAME#", menuName = "#PROJECTNAME#/#SCRIPTNAME#", order = 1)] public class #SCRIPTNAME# : GameConfig { - // Base GameSettingAsset Methods + // GameConfig Methods public override void Initialized(Game Author) { + // Called after load in Game by GameClass } } diff --git a/Reservoir/ScriptTemplates/GameServiceTemplate.txt b/Reservoir/ScriptTemplates/GameServiceTemplate.txt index f2476d2..fced4a8 100644 --- a/Reservoir/ScriptTemplates/GameServiceTemplate.txt +++ b/Reservoir/ScriptTemplates/GameServiceTemplate.txt @@ -3,22 +3,8 @@ using RealMethod; public class #SCRIPTNAME# : GameService { // Base Service Methods - protected override void OnStart(object Author) { } + protected override void OnStart(object Author) {} protected override void OnNewWorld() { } - protected override void OnNewAdditiveWorld(World target) { } protected override void OnEnd(object Author) { } - // GameService Virtual Methods - // public override IEnumerator GetLoadScneCorotine(SceneReference TargetScene) - // { - // return base.GetLoadScneCorotine(); - // } - // public override IEnumerator GetLoadWorldCorotine(WorldSceneConfig WorldScene) - // { - // return base.GetLoadWorldCorotine(); - // } - // public override IEnumerator GetReloadSWCorotine() - // { - // return base.GetReloadSWCorotine(); - // } } diff --git a/Reservoir/ScriptTemplates/GameTemplate.txt b/Reservoir/ScriptTemplates/GameTemplate.txt index de24ed5..16d7ecc 100644 --- a/Reservoir/ScriptTemplates/GameTemplate.txt +++ b/Reservoir/ScriptTemplates/GameTemplate.txt @@ -3,18 +3,27 @@ using RealMethod; public class #SCRIPTNAME# : Game { - // Base Game Methods + // Game Methods protected override void GameInitialized() { + // Called right after Unity finishes loading the engine before any scene or subsystem is loaded. + // You can insure when Called that GameService , GameConfig and all Managers Initilized. } protected override void GameStarted() { + // Called after Unity finishes initializing the engine, but before the first scene is loaded. + // It’s guaranteed to execute before any Awake() or Start() in your scene objects. } - protected override void GameWorldSynced(World NewWorld) + protected override void OnWorldChanged(World NewWorld) { + // Called when each World Initialized + // You can insure the Game.world refrence is valid + // Note: if you use world in scen and load scene as additive not OpenScen that world didnt connect to Game and removed by Main World class } - protected override void GameClosed() + protected override void OnGameClosed() { + // Called when application start exit + // You can insure this called befor and object destroy in scene (yes befor) } diff --git a/Reservoir/ScriptTemplates/ManagerTemplate.txt b/Reservoir/ScriptTemplates/ManagerTemplate.txt index c3ad458..66099c1 100644 --- a/Reservoir/ScriptTemplates/ManagerTemplate.txt +++ b/Reservoir/ScriptTemplates/ManagerTemplate.txt @@ -4,18 +4,20 @@ using RealMethod; public class #SCRIPTNAME# : MonoBehaviour, IGameManager { - // Implement IGameManage Methods - MonoBehaviour IGameManager.GetManagerClass() - { - return this; - } + + + + // Implement IGameManage Interface + MonoBehaviour IGameManager.GetManagerClass() => this; void IGameManager.InitiateManager(bool AlwaysLoaded) { - throw new System.NotImplementedException(); + // Called Just Once Befor any Awake called + // Called when World or Game initializing + // AlwaysLoaded means your manager initialize in GameScope(always valid) or World Scope(destroy after change World) } void IGameManager.ResolveService(Service service, bool active) { - throw new System.NotImplementedException(); + // Called When any Service Created or Deleted in Game } } diff --git a/Reservoir/ScriptTemplates/ServiceTemplate.txt b/Reservoir/ScriptTemplates/ServiceTemplate.txt index 2f89517..a71c6c1 100644 --- a/Reservoir/ScriptTemplates/ServiceTemplate.txt +++ b/Reservoir/ScriptTemplates/ServiceTemplate.txt @@ -6,12 +6,17 @@ public class #SCRIPTNAME# : Service // Service Methods protected override void OnStart(object Author) { + // Called right after Construct and stored in Game + // Called befor any Manager Know this Service Created } protected override void OnNewWorld() { + // Called after each World Initialized } protected override void OnEnd(object Author) { + // Called befor Destroyed. + // Called after all Manager know this Service going to Destroyed } } diff --git a/Reservoir/ScriptTemplates/WorldTemplate.txt b/Reservoir/ScriptTemplates/WorldTemplate.txt index 380a432..e81b175 100644 --- a/Reservoir/ScriptTemplates/WorldTemplate.txt +++ b/Reservoir/ScriptTemplates/WorldTemplate.txt @@ -2,13 +2,16 @@ using RealMethod; public class #SCRIPTNAME# : World { - // World Methods - protected override void AwakeWorld() + protected override void WorldBegin() { + // When World Awake + // Called befor awake and befor any Monobehaviort in Scene (by executionorder) + // You can insure your world is connect to game class and all Manager Initilize & Player Selected or Spawn in Scene } - protected override void DestroyWorld() + protected override void WorldEnd() { + // When World Destroy } } From 0b6a49604daf2e78bac75be6e8b7c898042115b7 Mon Sep 17 00:00:00 2001 From: Alijimpa Date: Thu, 25 Dec 2025 20:38:18 +0330 Subject: [PATCH 007/204] Iimplement ClassViewer editor for guid --- Documentation/Information.meta | 8 + Documentation/Information/ClassViewer.txt | 69 +++++ .../Information/ClassViewer.txt.meta | 7 + Documentation/Resource.meta | 8 + Editor/Library/Utilities/Core.cs | 1 + Editor/ReadySet/Tools/ClassViewerWindow.cs | 264 ++++++++++++++++++ .../ReadySet/Tools/ClassViewerWindow.cs.meta | 2 + 7 files changed, 359 insertions(+) create mode 100644 Documentation/Information.meta create mode 100644 Documentation/Information/ClassViewer.txt create mode 100644 Documentation/Information/ClassViewer.txt.meta create mode 100644 Documentation/Resource.meta create mode 100644 Editor/ReadySet/Tools/ClassViewerWindow.cs create mode 100644 Editor/ReadySet/Tools/ClassViewerWindow.cs.meta diff --git a/Documentation/Information.meta b/Documentation/Information.meta new file mode 100644 index 0000000..0b4d184 --- /dev/null +++ b/Documentation/Information.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: b31819f8abae8d6498ef952fa251bb85 +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Documentation/Information/ClassViewer.txt b/Documentation/Information/ClassViewer.txt new file mode 100644 index 0000000..bc5ba57 --- /dev/null +++ b/Documentation/Information/ClassViewer.txt @@ -0,0 +1,69 @@ +Runtime + Core + Architecture + Game -> This is a red word and bold green. Go to TEST https://github.com/AliJimpa/RealMethod/wiki/Assets. + World -> just test text ColortTEst Without link + GameConfig + GameService + ManagerContracts + ServiceContracts + WorldSceneConfig + Attributes + ButtonAttribute + ColorFieldAttribute + ConditionalHideAttribute + DropdownAttribute + DropdownFromArrayAttribute + DropdownFromDictionaryAttribute + EnumDescriptionAttribute + ExpandableAttribute + HelpBoxAttribute + HideInInspectorByEnumAttribute + InterfaceValidationDrawer + LayerAttribute + ListToPopupAttribute + MinMaxRangeAttribute + ReadOnlyAttribute + SeparatorAttribute + ShowInInspectorByEnumAttribute + ShowOnlyAttribute + ShowTypeAttribute + TagSelectorAttribute + Definitions + Assets + Identifier + Prefab + Tick + ProjectSetting + ProjectSettingAsset + Library + Extension + Interfaces + SharedScripts + Utilities + Vendor + Pattern + Components + DataAssets + DesignPatterns + Managers + Services + ReadySet + Commands + Components + DefaultsClass + Managers + Presets + Services + Toolkit + Ability + Actor + CSVFile + CurveViewer + Interaction + Inventory + PCG + Pickup + RPG + Tutorial + Upgrade diff --git a/Documentation/Information/ClassViewer.txt.meta b/Documentation/Information/ClassViewer.txt.meta new file mode 100644 index 0000000..9d6bfdd --- /dev/null +++ b/Documentation/Information/ClassViewer.txt.meta @@ -0,0 +1,7 @@ +fileFormatVersion: 2 +guid: 79055230a8dc125418831907cfeb785e +TextScriptImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Documentation/Resource.meta b/Documentation/Resource.meta new file mode 100644 index 0000000..16b3086 --- /dev/null +++ b/Documentation/Resource.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 7b6dff7ffa0c54f4c93b41811af269d5 +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Editor/Library/Utilities/Core.cs b/Editor/Library/Utilities/Core.cs index e41574f..fab8f91 100644 --- a/Editor/Library/Utilities/Core.cs +++ b/Editor/Library/Utilities/Core.cs @@ -9,6 +9,7 @@ public static class RM_CoreEditor public const string SetttingAssetPath = "Assets/Resources/RealMethod/RealMethodSetting.asset"; public static string ScriptTemplatesPath => GetPackagePath("com.mustard.realmethod") + "/Reservoir/ScriptTemplates"; public static string PrefabTemplatePath => GetPackagePath("com.mustard.realmethod") + "/Reservoir/Prefabs"; + public static string Documentation => GetPackagePath("com.mustard.realmethod") + "/Documentation/Information"; private static string GetPackagePath(string packageName) { diff --git a/Editor/ReadySet/Tools/ClassViewerWindow.cs b/Editor/ReadySet/Tools/ClassViewerWindow.cs new file mode 100644 index 0000000..b925957 --- /dev/null +++ b/Editor/ReadySet/Tools/ClassViewerWindow.cs @@ -0,0 +1,264 @@ +using UnityEngine; +using UnityEditor; +using System.Collections.Generic; +using System.IO; + +namespace RealMethod.Editor +{ + [System.Serializable] + public class ClassTreeNode + { + public string name; + public string toturial; // text after -> + public string link; // text afeter https + public List children = new List(); + } + + public class ClassViewerWindow : EditorWindow + { + private List rootNodes = new List(); + private Dictionary foldoutStates = new Dictionary(); + + private TextAsset textFile; + private Vector2 scrollPos; + private string searchQuery = ""; + + [MenuItem("Tools/RealMethod/ClassViewer")] + public static void Open() + { + GetWindow("ClassViewer"); + } + + // Unity Methods + private void OnEnable() + { + string ClassViewPath = "Assets/Realmethod/Documentation/Information/ClassViewer.txt"; // Just for Test + //string ClassViewPath = Path.Combine(RM_CoreEditor.Documentation, "ClassViewer.txt"); + if (!File.Exists(ClassViewPath)) + { + Debug.LogError($"ClassView file not found: {ClassViewPath}"); + Close(); + } + string ClassFile = File.ReadAllText(ClassViewPath); + LoadFromText(ClassFile); + } + private void OnGUI() + { + EditorGUILayout.BeginHorizontal(); + if (GUILayout.Button("Collaps")) + { + foreach (var node in rootNodes) + { + FoldLine(node, false); + } + } + if (GUILayout.Button("Expanded")) + { + foreach (var node in rootNodes) + { + FoldLine(node, true); + } + } + EditorGUILayout.EndHorizontal(); + EditorGUILayout.Space(); + searchQuery = EditorGUILayout.TextField("Search", searchQuery); + + EditorGUILayout.Space(); + + // 🔽 Scroll View + scrollPos = EditorGUILayout.BeginScrollView(scrollPos); + + foreach (var node in rootNodes) + { + DrawNodeWithSearch(node, 0); + } + + EditorGUILayout.EndScrollView(); + // 🔼 Scroll View + } + + private void LoadFromText(string text) + { + rootNodes.Clear(); + foldoutStates.Clear(); + + string[] lines = text.Split('\n'); + Stack stack = new Stack(); + + foreach (string rawLine in lines) + { + if (string.IsNullOrWhiteSpace(rawLine)) + continue; + + int indent = CountIndent(rawLine); + string trimmed = rawLine.Trim(); + + string nodeName = trimmed; + string endText = null; + string linkText = null; + + // 🔹 Parse "-> End Text" + string middleText = null; + int arrowIndex = trimmed.IndexOf("->"); + if (arrowIndex >= 0) + { + nodeName = trimmed.Substring(0, arrowIndex).Trim(); + middleText = trimmed.Substring(arrowIndex + 2).Trim(); + } + + if (middleText != null) + { + int linkindex = middleText.IndexOf("https"); + if (linkindex >= 0) + { + endText = middleText.Substring(0, linkindex).Trim(); + linkText = middleText.Substring(linkindex).Trim(); + } + } + else + { + endText = middleText; + } + + ClassTreeNode node = new ClassTreeNode + { + name = nodeName, + toturial = endText, + link = linkText + }; + + if (indent == 0) + { + rootNodes.Add(node); + stack.Clear(); + stack.Push(node); + } + else + { + while (stack.Count > indent) + stack.Pop(); + + stack.Peek().children.Add(node); + stack.Push(node); + } + } + } + private int CountIndent(string line) + { + int spaces = 0; + foreach (char c in line) + { + if (c == ' ') + spaces++; + else + break; + } + return spaces / 2; // 2 spaces = 1 level + } + + private bool DrawNodeWithSearch(ClassTreeNode node, int indent) + { + // Check if node matches search + bool nodeMatches = string.IsNullOrEmpty(searchQuery) || + node.name.ToLower().Contains(searchQuery.ToLower()) || + node.toturial?.ToLower().Contains(searchQuery.ToLower()) == true; + + // Check if any child matches + bool anyChildMatches = false; + foreach (var child in node.children) + { + if (NodeOrChildrenMatchSearch(child)) + { + anyChildMatches = true; + break; + } + } + + // If nothing matches, skip + if (!nodeMatches && !anyChildMatches) + return false; + + // Draw parent node + if (!foldoutStates.ContainsKey(node)) + foldoutStates[node] = true; + + EditorGUILayout.BeginHorizontal(); + GUILayout.Space(indent * 20); + foldoutStates[node] = + EditorGUILayout.Foldout(foldoutStates[node], node.name, true); + EditorGUILayout.EndHorizontal(); + + // Show endText as link if expanded + if (foldoutStates[node] && !string.IsNullOrEmpty(node.toturial)) + { + EditorGUILayout.BeginHorizontal(); + GUILayout.Space(indent * 20); + EditorGUILayout.BeginVertical("box"); + GUIStyle richLabel = new GUIStyle(EditorStyles.wordWrappedLabel); + richLabel.richText = true; + GUILayout.Label(node.toturial, richLabel); + //GUILayout.Label(node.toturial, new GUIStyle(EditorStyles.wordWrappedLabel)); + if (!string.IsNullOrEmpty(node.link)) + { + if (GUILayout.Button("Link", EditorStyles.linkLabel)) + { + OnEndTextClicked(node); + } + } + EditorGUILayout.EndVertical(); + EditorGUILayout.EndHorizontal(); + } + + + + // Draw children recursively only if expanded + if (foldoutStates[node]) + { + foreach (var child in node.children) + { + DrawNodeWithSearch(child, indent + 1); + } + } + + return true; + } + // Helper: check recursively if a node or any child matches search + private bool NodeOrChildrenMatchSearch(ClassTreeNode node) + { + bool match = string.IsNullOrEmpty(searchQuery) || + node.name.ToLower().Contains(searchQuery.ToLower()) || + node.toturial?.ToLower().Contains(searchQuery.ToLower()) == true; + + if (match) + return true; + + foreach (var child in node.children) + { + if (NodeOrChildrenMatchSearch(child)) + return true; + } + + return false; + } + private void FoldLine(ClassTreeNode node, bool result) + { + foldoutStates[node] = result; + if (foldoutStates[node]) + { + foreach (var child in node.children) + FoldLine(child, result); + } + } + private void OnEndTextClicked(ClassTreeNode node) + { + if (EditorUtility.DisplayDialog("OpenLink", node.link, "Open", "Cancel")) + { + // 3️⃣ OR open URL (if endText is a URL) + Application.OpenURL(node.link); + } + // 2️⃣ OR ping asset + // EditorGUIUtility.PingObject(yourObject); + } + + } +} diff --git a/Editor/ReadySet/Tools/ClassViewerWindow.cs.meta b/Editor/ReadySet/Tools/ClassViewerWindow.cs.meta new file mode 100644 index 0000000..4a30911 --- /dev/null +++ b/Editor/ReadySet/Tools/ClassViewerWindow.cs.meta @@ -0,0 +1,2 @@ +fileFormatVersion: 2 +guid: 15438cb6b5774124f90a5a787acca4c8 \ No newline at end of file From 34647925564e1e9b0ab2d0a098356579ef94162c Mon Sep 17 00:00:00 2001 From: Alijimpa Date: Thu, 25 Dec 2025 20:38:48 +0330 Subject: [PATCH 008/204] Implement Select player Radom befor selection by order --- Runtime/Core/Architecture/World.cs | 86 +++++++++++++++++-- .../Method/PlayerStarterComponent.cs | 23 +---- Runtime/ReadySet/DefaultsClass/DefaultGame.cs | 2 +- .../DefaultsClass/DefaultGameService.cs | 4 +- 4 files changed, 82 insertions(+), 33 deletions(-) diff --git a/Runtime/Core/Architecture/World.cs b/Runtime/Core/Architecture/World.cs index 1e3bbb8..fe81608 100644 --- a/Runtime/Core/Architecture/World.cs +++ b/Runtime/Core/Architecture/World.cs @@ -3,12 +3,63 @@ namespace RealMethod { + /// + /// Base class representing a locatioon for spawn player in scene + /// some virtual function in world calls can find all of object that has this class and with these spawing to location + /// public abstract class PlayerStarter : MonoBehaviour { [Header("Setting")] [SerializeField] private string posName = "None"; public string PosName => posName; + [SerializeField] + private float height = 2f; + [SerializeField] + private float radius = 0.5f; + + private bool hasPlayer = false; + + // Unity Method + private void Awake() + { + Destroy(gameObject); + } + + /// + /// Attempts to mark this spawn point as occupied by a player. + /// + /// + /// True if the spawn point was successfully marked as occupied; false if it is already occupied. + /// + public bool TryStartHere() + { + if (hasPlayer) + return false; + + hasPlayer = true; + return true; + } + /// + /// Check is player Spawn on this location. + /// + /// + /// True is already occupied. + /// + public bool CanStartHere() + { + return hasPlayer; + } + + +#if UNITY_EDITOR + protected virtual void OnDrawGizmos() + { + RM_Draw.gizmos.Capsule(transform.position, Color.cyan, height, radius); + RM_Draw.gizmos.Arrow(transform.position, transform.forward, Color.red); + RM_Draw.gizmos.Text(PosName, transform.position + (transform.up * (height / 2)) + (Vector3.up * 0.1f), Color.black); + } +#endif } /// @@ -24,12 +75,10 @@ public abstract class World : MonoBehaviour [SerializeField] private Prefab DefualtPlayer; - private IGameManager[] Managers; private GameObject PlayerObject; - /// /// Unity callback invoked when the script instance is being loaded. /// Connects the world to the game service, binds service callbacks, @@ -77,6 +126,7 @@ private void Awake() WorldBegin(); } + /// /// Unity callback invoked when the object is being destroyed. /// Unbinds previously bound service callbacks to avoid dangling references. @@ -122,6 +172,7 @@ public IGameManager GetManager(string ObjectName) } return null; } + /// /// Returns the primary player for this world. /// @@ -250,13 +301,32 @@ protected virtual Transform SelectSpawnPoint(PlayerStarter[] starters) if (starters.Length > 0) { int index = Random.Range(0, starters.Length); - return starters[index].transform; - } - else - { - transform.position = Vector3.zero; - return transform; + if (!starters[index].CanStartHere()) + { + return starters[index].transform; + } + foreach (var start in starters) + { + if (!start.CanStartHere()) + { + if (start.TryStartHere()) + { + return start.transform; + } + else + { + continue; + } + } + else + { + continue; + } + } } + + transform.position = Vector3.zero; + return transform; } /// /// Called when an additive world GameObject is added to this world. diff --git a/Runtime/ReadySet/Components/Method/PlayerStarterComponent.cs b/Runtime/ReadySet/Components/Method/PlayerStarterComponent.cs index a938873..afddb9e 100644 --- a/Runtime/ReadySet/Components/Method/PlayerStarterComponent.cs +++ b/Runtime/ReadySet/Components/Method/PlayerStarterComponent.cs @@ -3,29 +3,8 @@ namespace RealMethod { [AddComponentMenu("RealMethod/Method/PlayerStarter")] - public class PlayerStarterComponent : PlayerStarter + public sealed class PlayerStarterComponent : PlayerStarter { - [Header("Debug")] - [SerializeField] - private float height = 2f; - [SerializeField] - private float radius = 0.5f; - - // Unity Methods - private void Awake() - { - Destroy(gameObject); - } - - -#if UNITY_EDITOR - protected virtual void OnDrawGizmos() - { - RM_Draw.gizmos.Capsule(transform.position, Color.cyan, height, radius); - RM_Draw.gizmos.Arrow(transform.position, transform.forward, Color.red); - RM_Draw.gizmos.Text(PosName, transform.position + (transform.up * (height / 2)) + (Vector3.up * 0.1f), Color.black); - } -#endif } } \ No newline at end of file diff --git a/Runtime/ReadySet/DefaultsClass/DefaultGame.cs b/Runtime/ReadySet/DefaultsClass/DefaultGame.cs index 57c2deb..c4a9be7 100644 --- a/Runtime/ReadySet/DefaultsClass/DefaultGame.cs +++ b/Runtime/ReadySet/DefaultsClass/DefaultGame.cs @@ -16,7 +16,7 @@ protected override void GameStarted() } protected override void OnWorldChanged(World NewWorld) { - Debug.Log($"DefultGame Synced to {NewWorld}"); + Debug.Log($"DefultGame.World Change to {NewWorld}"); } protected override void OnGameClosed() { diff --git a/Runtime/ReadySet/DefaultsClass/DefaultGameService.cs b/Runtime/ReadySet/DefaultsClass/DefaultGameService.cs index 2731fa7..fb93638 100644 --- a/Runtime/ReadySet/DefaultsClass/DefaultGameService.cs +++ b/Runtime/ReadySet/DefaultsClass/DefaultGameService.cs @@ -6,14 +6,14 @@ public sealed class DefaultGameService : GameService { protected override void OnStart(object Author) { - Debug.Log("DefaultService Started"); + Debug.Log("DefaultGameService Started"); } protected override void OnNewWorld() { } protected override void OnEnd(object Author) { - Debug.Log("DefaultService Ended"); + Debug.Log("DefaultGameService Ended"); } } } \ No newline at end of file From 5b283d9ea3d426cb6bbbed4c4087f561a6b31167 Mon Sep 17 00:00:00 2001 From: Alijimpa Date: Sat, 27 Dec 2025 13:30:35 +0330 Subject: [PATCH 009/204] refine Class Structure --- Runtime/Core/Architecture/Game.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Runtime/Core/Architecture/Game.cs b/Runtime/Core/Architecture/Game.cs index ceff0d3..8c22902 100644 --- a/Runtime/Core/Architecture/Game.cs +++ b/Runtime/Core/Architecture/Game.cs @@ -87,7 +87,7 @@ private static void InitializeGame() // Initiate Game Class var emptyObject = new GameObject("RealGame"); - Type TargetClass = ProjectSettings.GetGameInstanceClass(); + Type TargetClass = ProjectSettings.GetGameInstanceType(); if (TargetClass == null) { Debug.LogWarning("GameInstanceClass that was empty. DefaultGame Created"); From 5544bcff0d46a1bbbb17436237044dea026b5e27 Mon Sep 17 00:00:00 2001 From: Alijimpa Date: Sat, 27 Dec 2025 16:14:31 +0330 Subject: [PATCH 010/204] Implement Base forlder structure for Ptoject Setting --- .../{GameCompWindow.cs => Game_Editor.cs} | 2 +- ...CompWindow.cs.meta => Game_Editor.cs.meta} | 0 ...nOrder.cs => WorldExecutionOrder_Tools.cs} | 2 +- ...meta => WorldExecutionOrder_Tools.cs.meta} | 0 ...tValidator.cs => ConfigAsset_Validator.cs} | 4 +- ....cs.meta => ConfigAsset_Validator.cs.meta} | 0 ...DataAssetEditor.cs => DataAsset_Editor.cs} | 2 +- ...ditor.cs.meta => DataAsset_Editor.cs.meta} | 0 .../{PrefabDrawer.cs => PrefabCore_Drawer.cs} | 85 +++---- ...awer.cs.meta => PrefabCore_Drawer.cs.meta} | 0 ...Window.cs => RealMethod_ProjectSetting.cs} | 218 +++++++++--------- ...meta => RealMethod_ProjectSetting.cs.meta} | 0 .../Sections/FolderSettingSection.cs | 34 +-- .../Sections/InitializerSection.cs | 4 +- Editor/Library/Utilities/Create.cs | 4 +- .../ReadySet/Content/RealMethod_GameObject.cs | 18 ++ .../ReadySet/Tools/AnimatorScriptGenerator.cs | 4 +- Editor/Toolkit/PCG/PCGEditorWindow.cs | 4 +- Editor/Toolkit/TerrainTools/TerrainEditor.cs | 2 +- Runtime/Core/Architecture/Game.cs | 2 +- .../ProjectSetting/ProjectSettingAsset.cs | 108 +++++---- 21 files changed, 272 insertions(+), 221 deletions(-) rename Editor/Core/Architecture/{GameCompWindow.cs => Game_Editor.cs} (95%) rename Editor/Core/Architecture/{GameCompWindow.cs.meta => Game_Editor.cs.meta} (100%) rename Editor/Core/Architecture/{AutoWorldExecutionOrder.cs => WorldExecutionOrder_Tools.cs} (97%) rename Editor/Core/Architecture/{AutoWorldExecutionOrder.cs.meta => WorldExecutionOrder_Tools.cs.meta} (100%) rename Editor/Core/Definitions/{ConfigAssetValidator.cs => ConfigAsset_Validator.cs} (97%) rename Editor/Core/Definitions/{ConfigAssetValidator.cs.meta => ConfigAsset_Validator.cs.meta} (100%) rename Editor/Core/Definitions/{DataAssetEditor.cs => DataAsset_Editor.cs} (94%) rename Editor/Core/Definitions/{DataAssetEditor.cs.meta => DataAsset_Editor.cs.meta} (100%) rename Editor/Core/Definitions/{PrefabDrawer.cs => PrefabCore_Drawer.cs} (61%) rename Editor/Core/Definitions/{PrefabDrawer.cs.meta => PrefabCore_Drawer.cs.meta} (100%) rename Editor/Core/ProjectSetting/{ProjectSettingWindow.cs => RealMethod_ProjectSetting.cs} (85%) rename Editor/Core/ProjectSetting/{ProjectSettingWindow.cs.meta => RealMethod_ProjectSetting.cs.meta} (100%) diff --git a/Editor/Core/Architecture/GameCompWindow.cs b/Editor/Core/Architecture/Game_Editor.cs similarity index 95% rename from Editor/Core/Architecture/GameCompWindow.cs rename to Editor/Core/Architecture/Game_Editor.cs index 13d6815..08c9380 100644 --- a/Editor/Core/Architecture/GameCompWindow.cs +++ b/Editor/Core/Architecture/Game_Editor.cs @@ -3,7 +3,7 @@ namespace RealMethod { [CustomEditor(typeof(Game), true)] - public class GameCompWindow : UnityEditor.Editor + public class Game_Editor : UnityEditor.Editor { private Game BaseComponent; diff --git a/Editor/Core/Architecture/GameCompWindow.cs.meta b/Editor/Core/Architecture/Game_Editor.cs.meta similarity index 100% rename from Editor/Core/Architecture/GameCompWindow.cs.meta rename to Editor/Core/Architecture/Game_Editor.cs.meta diff --git a/Editor/Core/Architecture/AutoWorldExecutionOrder.cs b/Editor/Core/Architecture/WorldExecutionOrder_Tools.cs similarity index 97% rename from Editor/Core/Architecture/AutoWorldExecutionOrder.cs rename to Editor/Core/Architecture/WorldExecutionOrder_Tools.cs index ab0e17c..f2b0fb7 100644 --- a/Editor/Core/Architecture/AutoWorldExecutionOrder.cs +++ b/Editor/Core/Architecture/WorldExecutionOrder_Tools.cs @@ -7,7 +7,7 @@ namespace RealMethod.Editor { //[InitializeOnLoad] - public static class AutoWorldExecutionOrder + public static class WorldExecutionOrder_Tools { [MenuItem("Tools/RealMethod/Core/ExecutionOrder" , priority = -1001)] static void ApplyExecutionOrder() diff --git a/Editor/Core/Architecture/AutoWorldExecutionOrder.cs.meta b/Editor/Core/Architecture/WorldExecutionOrder_Tools.cs.meta similarity index 100% rename from Editor/Core/Architecture/AutoWorldExecutionOrder.cs.meta rename to Editor/Core/Architecture/WorldExecutionOrder_Tools.cs.meta diff --git a/Editor/Core/Definitions/ConfigAssetValidator.cs b/Editor/Core/Definitions/ConfigAsset_Validator.cs similarity index 97% rename from Editor/Core/Definitions/ConfigAssetValidator.cs rename to Editor/Core/Definitions/ConfigAsset_Validator.cs index 4d69de6..65cf625 100644 --- a/Editor/Core/Definitions/ConfigAssetValidator.cs +++ b/Editor/Core/Definitions/ConfigAsset_Validator.cs @@ -7,9 +7,9 @@ namespace RealMethod.Editor { [InitializeOnLoad] - public static class ConfigAssetValidator + public static class ConfigAsset_Validator { - static ConfigAssetValidator() + static ConfigAsset_Validator() { EditorApplication.delayCall += ValidateAllConfigs; } diff --git a/Editor/Core/Definitions/ConfigAssetValidator.cs.meta b/Editor/Core/Definitions/ConfigAsset_Validator.cs.meta similarity index 100% rename from Editor/Core/Definitions/ConfigAssetValidator.cs.meta rename to Editor/Core/Definitions/ConfigAsset_Validator.cs.meta diff --git a/Editor/Core/Definitions/DataAssetEditor.cs b/Editor/Core/Definitions/DataAsset_Editor.cs similarity index 94% rename from Editor/Core/Definitions/DataAssetEditor.cs rename to Editor/Core/Definitions/DataAsset_Editor.cs index ece664f..fc68194 100644 --- a/Editor/Core/Definitions/DataAssetEditor.cs +++ b/Editor/Core/Definitions/DataAsset_Editor.cs @@ -3,7 +3,7 @@ namespace RealMethod.Editor { - public class DataAssetEditor : UnityEditor.Editor + public class DataAsset_Editor : UnityEditor.Editor { public static void DrawCompleteScriptableObjectEditor(string name, ref T settings, ref bool foldout, ref UnityEditor.Editor editor) where T : ScriptableObject { diff --git a/Editor/Core/Definitions/DataAssetEditor.cs.meta b/Editor/Core/Definitions/DataAsset_Editor.cs.meta similarity index 100% rename from Editor/Core/Definitions/DataAssetEditor.cs.meta rename to Editor/Core/Definitions/DataAsset_Editor.cs.meta diff --git a/Editor/Core/Definitions/PrefabDrawer.cs b/Editor/Core/Definitions/PrefabCore_Drawer.cs similarity index 61% rename from Editor/Core/Definitions/PrefabDrawer.cs rename to Editor/Core/Definitions/PrefabCore_Drawer.cs index c5a9840..37f4363 100644 --- a/Editor/Core/Definitions/PrefabDrawer.cs +++ b/Editor/Core/Definitions/PrefabCore_Drawer.cs @@ -5,7 +5,7 @@ namespace RealMethod.Editor { [CustomPropertyDrawer(typeof(PrefabCore), true)] - public class PrefabDrawer : PropertyDrawer + public class PrefabCore_Drawer : PropertyDrawer { public override void OnGUI(Rect position, SerializedProperty property, GUIContent label) { @@ -76,50 +76,51 @@ public override void OnGUI(Rect position, SerializedProperty property, GUIConten EditorGUI.EndProperty(); } - // --- Utility to get the actual object instance from SerializedProperty --- - private object GetTargetObjectOfProperty(SerializedProperty prop) - { - if (prop == null) return null; - string path = prop.propertyPath.Replace(".Array.data[", "["); - object obj = prop.serializedObject.targetObject; - string[] elements = path.Split('.'); - foreach (string element in elements) - { - if (element.Contains("[")) - { - string elementName = element.Substring(0, element.IndexOf("[")); - int index = Convert.ToInt32(element.Substring(element.IndexOf("[")).Replace("[", "").Replace("]", "")); - obj = GetValue(obj, elementName, index); - } - else - { - obj = GetValue(obj, element); - } - } - return obj; - } - private object GetValue(object source, string name) - { - if (source == null) return null; - var type = source.GetType(); - var f = type.GetField(name, System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.Public | System.Reflection.BindingFlags.Instance); - if (f == null) return null; - return f.GetValue(source); - } + // --- Utility to get the actual object instance from SerializedProperty --- + // private object GetTargetObjectOfProperty(SerializedProperty prop) + // { + // if (prop == null) return null; - private object GetValue(object source, string name, int index) - { - var enumerable = GetValue(source, name) as System.Collections.IEnumerable; - if (enumerable == null) return null; - var enm = enumerable.GetEnumerator(); - for (int i = 0; i <= index; i++) - { - if (!enm.MoveNext()) return null; - } - return enm.Current; - } + // string path = prop.propertyPath.Replace(".Array.data[", "["); + // object obj = prop.serializedObject.targetObject; + // string[] elements = path.Split('.'); + + // foreach (string element in elements) + // { + // if (element.Contains("[")) + // { + // string elementName = element.Substring(0, element.IndexOf("[")); + // int index = Convert.ToInt32(element.Substring(element.IndexOf("[")).Replace("[", "").Replace("]", "")); + // obj = GetValue(obj, elementName, index); + // } + // else + // { + // obj = GetValue(obj, element); + // } + // } + // return obj; + // } + // private object GetValue(object source, string name) + // { + // if (source == null) return null; + // var type = source.GetType(); + // var f = type.GetField(name, System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.Public | System.Reflection.BindingFlags.Instance); + // if (f == null) return null; + // return f.GetValue(source); + // } + // private object GetValue(object source, string name, int index) + // { + // var enumerable = GetValue(source, name) as System.Collections.IEnumerable; + // if (enumerable == null) return null; + // var enm = enumerable.GetEnumerator(); + // for (int i = 0; i <= index; i++) + // { + // if (!enm.MoveNext()) return null; + // } + // return enm.Current; + // } } } diff --git a/Editor/Core/Definitions/PrefabDrawer.cs.meta b/Editor/Core/Definitions/PrefabCore_Drawer.cs.meta similarity index 100% rename from Editor/Core/Definitions/PrefabDrawer.cs.meta rename to Editor/Core/Definitions/PrefabCore_Drawer.cs.meta diff --git a/Editor/Core/ProjectSetting/ProjectSettingWindow.cs b/Editor/Core/ProjectSetting/RealMethod_ProjectSetting.cs similarity index 85% rename from Editor/Core/ProjectSetting/ProjectSettingWindow.cs rename to Editor/Core/ProjectSetting/RealMethod_ProjectSetting.cs index 6f1ebfe..f085417 100644 --- a/Editor/Core/ProjectSetting/ProjectSettingWindow.cs +++ b/Editor/Core/ProjectSetting/RealMethod_ProjectSetting.cs @@ -7,7 +7,110 @@ namespace RealMethod.Editor { - public static class ProjectSettingWindow + interface ISectionSetting + { + void FirstSelected(ProjectSettingAsset storage); + void Draw(); + } + // Abstract base class for a settings section + public abstract class ProjectSettingSection : ISectionSetting + { + protected class ClassType + { + private List TypeList; + private string[] TypeName; + private int selctedIndex = 0; + private int newIndex; + + public ClassType() + { + // Get all available T types **only once** + TypeList = AppDomain.CurrentDomain.GetAssemblies() + .SelectMany(assembly => assembly.GetTypes()) + .Where(type => typeof(T).IsAssignableFrom(type) && !type.IsAbstract) + .ToList(); + + TypeName = TypeList.Select(t => t.FullName).ToArray(); + } + + public void Draw(SerializedObject projectSettings, string PropertyName, string DisplayName) + { + selctedIndex = System.Array.IndexOf(TypeName, projectSettings.FindProperty(PropertyName).stringValue); + newIndex = EditorGUILayout.Popup(DisplayName, selctedIndex, TypeName); + if (newIndex >= 0 && newIndex < TypeName.Length) + { + projectSettings.FindProperty(PropertyName).stringValue = TypeName[newIndex]; + } + } + } + private bool isReady = true;// Indicates whether the section is ready to render + private string message = string.Empty;// Error message to display if the section is not ready + private int errorid = 0;// Error ID to identify the type of error + + public ProjectSettingSection() + { + Initialized(); + } + + // Implement ISectionSetting Interface + void ISectionSetting.FirstSelected(ProjectSettingAsset storage) + { + BeginRender(storage); + } + void ISectionSetting.Draw() + { + EditorGUILayout.Space(); + EditorGUILayout.LabelField(GetTitle(), EditorStyles.boldLabel); // Section Title + + if (isReady) + { + // Render the section's content + UpdateRender(); + } + else + { + // Display an error message if the section is not ready + EditorGUILayout.HelpBox(message, MessageType.Error); + + // Provide a "Fix" button to resolve the error + if (GUILayout.Button("Fix")) + { + Fix(errorid); + } + } + } + + // Abstract Method + protected abstract void Initialized(); + protected abstract void BeginRender(ProjectSettingAsset Storage); + protected abstract void UpdateRender(); + protected abstract string GetTitle(); + protected abstract void Fix(int Id); + + // Protected Function + protected void Error(string Message, int Id = 0) + { + if (isReady) + { + isReady = false; + } + message = Message; + errorid = Id; + } + protected void ClearError() + { + message = string.Empty; + errorid = 0; + if (!isReady) + { + isReady = true; + } + UpdateRender(); + } + } + + // Project Setting + public static class RealMethod_ProjectSetting { private const string settingsPath = "Assets/Resources/RealMethod/RealMethodSetting.asset"; private static bool candraw = true;// Flag to determine if the UI can be drawn @@ -15,10 +118,11 @@ public static class ProjectSettingWindow // Array of sections to be rendered in the settings UI new InitializerSection(), new FolderSettingSection() - }; + }; - [SettingsProvider]// Create a SettingsProvider for Unity's Project Settings + [SettingsProvider] + // Create a SettingsProvider for Unity's Project Settings public static SettingsProvider CreateSettingsProvider() { var provider = new SettingsProvider("Project/Real Method", SettingsScope.Project) @@ -46,8 +150,9 @@ public static SettingsProvider CreateSettingsProvider() // Initialize each section with the loaded settings foreach (var item in sections) { + ISectionSetting ptovider = item; if (TargetStorage != null) - item.BeginRender(TargetStorage); + ptovider.FirstSelected(TargetStorage); } }, @@ -59,7 +164,8 @@ public static SettingsProvider CreateSettingsProvider() // Render each section foreach (var item in sections) { - item.UpdateRender(); + ISectionSetting ptovider = item; + ptovider.Draw(); // Add a separator line GUILayout.Box("", GUILayout.ExpandWidth(true), GUILayout.Height(1)); } @@ -79,8 +185,9 @@ public static SettingsProvider CreateSettingsProvider() ProjectSettingAsset TargetStorage = CreateSettingStorage(); foreach (var item in sections) { + ISectionSetting ptovider = item; if (TargetStorage != null) - item.BeginRender(TargetStorage); + ptovider.FirstSelected(TargetStorage); } candraw = true; @@ -108,103 +215,4 @@ private static ProjectSettingAsset CreateSettingStorage() return settings; } } - - - // Abstract base class for a settings section - public abstract class ProjectSettingSection - { - protected class ClassType - { - private List TypeList; - private string[] TypeName; - private int selctedIndex = 0; - private int newIndex; - - public ClassType() - { - // Get all available T types **only once** - TypeList = AppDomain.CurrentDomain.GetAssemblies() - .SelectMany(assembly => assembly.GetTypes()) - .Where(type => typeof(T).IsAssignableFrom(type) && !type.IsAbstract) - .ToList(); - - TypeName = TypeList.Select(t => t.FullName).ToArray(); - } - - public void Draw(SerializedObject projectSettings, string PropertyName, string DisplayName) - { - selctedIndex = System.Array.IndexOf(TypeName, projectSettings.FindProperty(PropertyName).stringValue); - newIndex = EditorGUILayout.Popup(DisplayName, selctedIndex, TypeName); - if (newIndex >= 0 && newIndex < TypeName.Length) - { - projectSettings.FindProperty(PropertyName).stringValue = TypeName[newIndex]; - } - } - } - private bool isReady = true;// Indicates whether the section is ready to render - private string message = string.Empty;// Error message to display if the section is not ready - private int errorid = 0;// Error ID to identify the type of error - - - public ProjectSettingSection() - { - Initialized(); - } - - public void BeginRender(ProjectSettingAsset storage) - { - FirstSelected(storage); - } - public void UpdateRender() - { - EditorGUILayout.Space(); - EditorGUILayout.LabelField(GetTitle(), EditorStyles.boldLabel); // Section Title - - if (isReady) - { - // Render the section's content - Draw(); - } - else - { - // Display an error message if the section is not ready - EditorGUILayout.HelpBox(message, MessageType.Error); - - // Provide a "Fix" button to resolve the error - if (GUILayout.Button("Fix")) - { - Fix(errorid); - } - } - } - - - protected abstract void Initialized(); - protected abstract void FirstSelected(ProjectSettingAsset Storage); - protected abstract void Draw(); - protected abstract string GetTitle(); - protected abstract void Fix(int Id); - - - protected void Error(string Message, int Id = 0) - { - if (isReady) - { - isReady = false; - } - message = Message; - errorid = Id; - } - protected void ClearError() - { - message = string.Empty; - errorid = 0; - if (!isReady) - { - isReady = true; - } - UpdateRender(); - } - - } } \ No newline at end of file diff --git a/Editor/Core/ProjectSetting/ProjectSettingWindow.cs.meta b/Editor/Core/ProjectSetting/RealMethod_ProjectSetting.cs.meta similarity index 100% rename from Editor/Core/ProjectSetting/ProjectSettingWindow.cs.meta rename to Editor/Core/ProjectSetting/RealMethod_ProjectSetting.cs.meta diff --git a/Editor/Core/ProjectSetting/Sections/FolderSettingSection.cs b/Editor/Core/ProjectSetting/Sections/FolderSettingSection.cs index 5396d8c..b9a6298 100644 --- a/Editor/Core/ProjectSetting/Sections/FolderSettingSection.cs +++ b/Editor/Core/ProjectSetting/Sections/FolderSettingSection.cs @@ -8,18 +8,26 @@ public class FolderSettingSection : ProjectSettingSection private ProjectSettingAsset MyStorage; private bool isPanelMaximize = false; // Add a toggle for minimizing the panel - // Implement Abstraction Methods + // Implement ProjectSettingSection Methods protected override void Initialized() { } - - protected override void FirstSelected(ProjectSettingAsset Storage) + protected override void BeginRender(ProjectSettingAsset Storage) { MyStorage = Storage; } - - protected override void Draw() + protected override void UpdateRender() { + string[] structureType = System.Enum.GetNames(typeof(ProjectSettingAsset.FolderStructureType)); + MyStorage.SetStructureType(EditorGUILayout.Popup("StructureType", MyStorage.GetStructureType(), structureType)); + if (MyStorage.GetStructureType() == 1) + { + if (!AssetDatabase.IsValidFolder("Assets/" + Application.productName)) + { + AssetDatabase.CreateFolder("Assets", Application.productName); + } + } + // Add a toggle button for minimizing or expanding the panel EditorGUILayout.BeginHorizontal(); isPanelMaximize = EditorGUILayout.Foldout(isPanelMaximize, "Folder List", true, EditorStyles.foldoutHeader); @@ -27,13 +35,13 @@ protected override void Draw() { foreach (var address in MyStorage.ProjectStructure) { - if (AssetDatabase.IsValidFolder(address.Path)) + if (AssetDatabase.IsValidFolder(address.AssetPath)) { Debug.Log($"Folder exists: {address}"); } else { - string folderpath = address.Path; + string folderpath = address.GetFolderPath(MyStorage); string FolderAddress = string.Join("/", folderpath.Split('/')[..^1]); // Remove the last segment of the path string folderName = System.IO.Path.GetFileName(folderpath); // Get the last segment of the path CreateFolder(FolderAddress, folderName); // Create the folder @@ -49,26 +57,26 @@ protected override void Draw() } // Render the folder list - for (int i = 0; i < MyStorage.ProjectStructure.Length; i++) + for (int i = 0; i < MyStorage.ProjectStructure.Count; i++) { EditorGUILayout.BeginHorizontal(); // Start horizontal layout // Display the folder path as a text field - MyStorage.ProjectStructure[i].Path = EditorGUILayout.TextField($"{i + 1}.{MyStorage.ProjectStructure[i].Identity}", MyStorage.ProjectStructure[i].Path); + MyStorage.SetFolderAddressPath(i, EditorGUILayout.TextField($"{i + 1}.{MyStorage.ProjectStructure[i].AssetType}", MyStorage.ProjectStructure[i].AssetPath)); - string ButtonName = AssetDatabase.IsValidFolder(MyStorage.ProjectStructure[i].Path) ? "Check" : "Create"; + string ButtonName = AssetDatabase.IsValidFolder(MyStorage.ProjectStructure[i].AssetPath) ? "Check" : "Create"; // Add a button next to the text field if (GUILayout.Button(ButtonName, GUILayout.Width(60))) { // Check if the folder exists - if (AssetDatabase.IsValidFolder(MyStorage.ProjectStructure[i].Path)) + if (AssetDatabase.IsValidFolder(MyStorage.ProjectStructure[i].AssetPath)) { Debug.Log($"Folder exists: {MyStorage.ProjectStructure[i]}"); } else { - string folderpath = MyStorage.ProjectStructure[i].Path; + string folderpath = MyStorage.ProjectStructure[i].GetFolderPath(MyStorage); string FolderAddress = string.Join("/", folderpath.Split('/')[..^1]); // Remove the last segment of the path string folderName = System.IO.Path.GetFileName(folderpath); // Get the last segment of the path CreateFolder(FolderAddress, folderName); // Create the folder @@ -83,11 +91,9 @@ protected override string GetTitle() { return "FolderStructure"; } - protected override void Fix(int Id) { } - private void CreateFolder(string parentFolder, string newFolderName) { string folderPath = System.IO.Path.Combine(parentFolder, newFolderName).Replace("\\", "/"); diff --git a/Editor/Core/ProjectSetting/Sections/InitializerSection.cs b/Editor/Core/ProjectSetting/Sections/InitializerSection.cs index 477e7f7..b975d3a 100644 --- a/Editor/Core/ProjectSetting/Sections/InitializerSection.cs +++ b/Editor/Core/ProjectSetting/Sections/InitializerSection.cs @@ -15,12 +15,12 @@ protected override void Initialized() gameClass = new ClassType(); gameService = new ClassType(); } - protected override void FirstSelected(ProjectSettingAsset Storage) + protected override void BeginRender(ProjectSettingAsset Storage) { SettingAsset = Storage; projectSettings = new SerializedObject(Storage); } - protected override void Draw() + protected override void UpdateRender() { if (projectSettings == null) return; diff --git a/Editor/Library/Utilities/Create.cs b/Editor/Library/Utilities/Create.cs index 012366e..54d4b61 100644 --- a/Editor/Library/Utilities/Create.cs +++ b/Editor/Library/Utilities/Create.cs @@ -12,7 +12,7 @@ public static string Script(string templateFileName, string defaultName, bool Us if (UseProject) { ProjectSettingAsset ProjectSetting = AssetDatabase.LoadAssetAtPath(RM_CoreEditor.SetttingAssetPath); - templatePath = Path.Combine(ProjectSetting.FindAddres(ProjectSettingAsset.IdentityAsset.ScriptTemplate).Path, templateFileName); + templatePath = Path.Combine(ProjectSetting[ProjectSettingAsset.AssetFormat.Other], templateFileName); } else { @@ -63,7 +63,7 @@ public static GameObject Prefab(string prefabName, bool UseProject = false) if (UseProject) { ProjectSettingAsset ProjectSetting = AssetDatabase.LoadAssetAtPath(RM_CoreEditor.SetttingAssetPath); - prefabPath = Path.Combine(ProjectSetting.FindAddres(ProjectSettingAsset.IdentityAsset.PrefabTemplate).Path, prefabName); + prefabPath = Path.Combine(ProjectSetting[ProjectSettingAsset.AssetFormat.Prefab], prefabName); } else { diff --git a/Editor/ReadySet/Content/RealMethod_GameObject.cs b/Editor/ReadySet/Content/RealMethod_GameObject.cs index 720c92a..e7e2e06 100644 --- a/Editor/ReadySet/Content/RealMethod_GameObject.cs +++ b/Editor/ReadySet/Content/RealMethod_GameObject.cs @@ -20,6 +20,24 @@ static void CreatePlayerStarter(MenuCommand menuCommand) // Register the creation in Undo system (so Ctrl+Z works) Undo.RegisterCreatedObjectUndo(go, "Create " + go.name); + // Select the new GameObject + Selection.activeObject = go; + } + [MenuItem("GameObject/RealMethod/World", false, 10)] + static void CreateWorld(MenuCommand menuCommand) + { + // Create a new GameObject + GameObject go = new GameObject("World"); + + // Optional: add components + go.AddComponent(); + + // Place it in the scene, parented if needed + GameObjectUtility.SetParentAndAlign(go, menuCommand.context as GameObject); + + // Register the creation in Undo system (so Ctrl+Z works) + Undo.RegisterCreatedObjectUndo(go, "Create " + go.name); + // Select the new GameObject Selection.activeObject = go; } diff --git a/Editor/ReadySet/Tools/AnimatorScriptGenerator.cs b/Editor/ReadySet/Tools/AnimatorScriptGenerator.cs index b5d512f..9267557 100644 --- a/Editor/ReadySet/Tools/AnimatorScriptGenerator.cs +++ b/Editor/ReadySet/Tools/AnimatorScriptGenerator.cs @@ -14,9 +14,9 @@ public class AnimatorScriptGenerator public static void GenerateScriptsFromAnimators() { ProjectSettingAsset TargetStorage; - if (ProjectSettingWindow.GetSettingStorage(out TargetStorage)) + if (RealMethod_ProjectSetting.GetSettingStorage(out TargetStorage)) { - outputFolder = TargetStorage.FindAddres(ProjectSettingAsset.IdentityAsset.AnimatorParam).Path; + outputFolder = TargetStorage[ProjectSettingAsset.AssetFormat.Script] + "/General/AnimatorParam"; } else { diff --git a/Editor/Toolkit/PCG/PCGEditorWindow.cs b/Editor/Toolkit/PCG/PCGEditorWindow.cs index a558103..01da03e 100644 --- a/Editor/Toolkit/PCG/PCGEditorWindow.cs +++ b/Editor/Toolkit/PCG/PCGEditorWindow.cs @@ -107,9 +107,9 @@ private void OnEnable() Cash = new EP_ScriptableObject("Cash", this); SelectedData = new EP_List("Data", this); CashAddress = new EP_String("Address", this); - CashAddress.SetValue(ProjectSetting.FindAddres(ProjectSettingAsset.IdentityAsset.PCG).Path + "/PCGCashAsset.asset"); + CashAddress.SetValue(ProjectSetting[ProjectSettingAsset.AssetFormat.ScriptableObject] + "/PCGCashAsset.asset"); PrefabAddress = new EP_String("Address", this); - PrefabAddress.SetValue(ProjectSetting.FindAddres(ProjectSettingAsset.IdentityAsset.Prefab).Path + "/PCG.prefab"); + PrefabAddress.SetValue(ProjectSetting.GetFolderAddressByType(ProjectSettingAsset.AssetFormat.Prefab).AssetPath + "/PCG.prefab"); ExportType = new EP_Enum("ExportType", this); // Subscribe to the selectionChanged event diff --git a/Editor/Toolkit/TerrainTools/TerrainEditor.cs b/Editor/Toolkit/TerrainTools/TerrainEditor.cs index cf50fcc..be899cd 100644 --- a/Editor/Toolkit/TerrainTools/TerrainEditor.cs +++ b/Editor/Toolkit/TerrainTools/TerrainEditor.cs @@ -94,7 +94,7 @@ public ExportTreeData(Terrain owner, UnityEditor.Editor editor) CashFile = new EP_ScriptableObject("Cash", editor); CashAddress = new EP_String("Address", editor); - CashAddress.SetValue(ProjectSetting.FindAddres(ProjectSettingAsset.IdentityAsset.PCG).Path + "/TerrainCash.asset"); + CashAddress.SetValue(ProjectSetting[ProjectSettingAsset.AssetFormat.ScriptableObject] + "/TerrainCash.asset"); } public void OnRender() diff --git a/Runtime/Core/Architecture/Game.cs b/Runtime/Core/Architecture/Game.cs index 8c22902..e5f7389 100644 --- a/Runtime/Core/Architecture/Game.cs +++ b/Runtime/Core/Architecture/Game.cs @@ -104,7 +104,7 @@ private static void InitializeGame() } // Create Game Service - Type targetService = ProjectSettings.GetGameServiceClass(); + Type targetService = ProjectSettings.GetGameServiceType(); if (targetService == null) { Debug.LogWarning($"GetGameServiceClass that was empty. DefaultGameService Created"); diff --git a/Runtime/Core/ProjectSetting/ProjectSettingAsset.cs b/Runtime/Core/ProjectSetting/ProjectSettingAsset.cs index cea5c51..3156a2e 100644 --- a/Runtime/Core/ProjectSetting/ProjectSettingAsset.cs +++ b/Runtime/Core/ProjectSetting/ProjectSettingAsset.cs @@ -1,4 +1,5 @@ using System; +using System.Collections.Generic; using UnityEngine; namespace RealMethod @@ -6,15 +7,22 @@ namespace RealMethod // Real Method Setting Storage public class ProjectSettingAsset : ScriptableObject { + private string ProjectName; [Serializable] public struct FolderAddress { - public IdentityAsset Identity; - public string Path; - public string FolderName => System.IO.Path.GetFileName(Path); + public AssetFormat AssetType; + public string AssetPath; + public string FolderName => System.IO.Path.GetFileName(AssetPath); + public string GetFolderPath(ProjectSettingAsset settingAsset) + { + string RootPath = settingAsset.GetStructureType() == 0 ? "Assets" : "Assets/"+Application.productName; + return $"{RootPath}/{AssetPath}"; + } + } [Serializable] - public enum IdentityAsset + public enum AssetFormat { Scene = 0, Script = 1, @@ -29,21 +37,20 @@ public enum IdentityAsset Audio = 10, Particle = 11, Animationclip = 12, - Miscellaneous = 13, - User = 14, - Resources = 15, - ThirdpartyPack = 16, - PCG = 17, - ScriptTemplate = 18, - PrefabTemplate = 19, - AnimatorParam, + Other = 13 + } + [Serializable] + public enum FolderStructureType + { + Assets = 0, + ProjectName = 1, } [Header("Initializer")] - [SerializeField] + [SerializeField, ReadOnly] private string GameClass = "RealMethod.DefultGame"; - [SerializeField] + [SerializeField, ReadOnly] private string GameService = "RealMethod.DefaultGameService"; [SerializeField] private GameConfig GameConfig; @@ -54,34 +61,37 @@ public enum IdentityAsset [SerializeField] private GameObject GamePrefab_3; [Header("FolderStructure")] - public FolderAddress[] ProjectStructure = new FolderAddress[21] + [SerializeField, ReadOnly] + private FolderStructureType structureType; + [SerializeField, ReadOnly] + private FolderAddress[] projectStructure = new FolderAddress[14] { - new FolderAddress { Identity = 0, Path = "Assets/1_Scenes"}, - new FolderAddress { Identity = (IdentityAsset)1, Path = "Assets/2_Scripts" }, - new FolderAddress { Identity = (IdentityAsset)2, Path = "Assets/3_Prefabs"}, - new FolderAddress { Identity = (IdentityAsset)3, Path = "Assets/4_Data" }, - new FolderAddress { Identity = (IdentityAsset)4, Path = "Assets/5_Mesh"}, - new FolderAddress { Identity = (IdentityAsset)5, Path = "Assets/5_Sprite"}, - new FolderAddress { Identity = (IdentityAsset)6, Path = "Assets/7_Misc/Textures"}, - new FolderAddress { Identity = (IdentityAsset)7, Path = "Assets/7_Misc/Videos"}, - new FolderAddress { Identity = (IdentityAsset)8, Path = "Assets/7_Misc/Materials"}, - new FolderAddress { Identity = (IdentityAsset)9, Path = "Assets/6_Shader"}, - new FolderAddress { Identity = (IdentityAsset)10, Path = "Assets/8_Sound&Music"}, - new FolderAddress { Identity = (IdentityAsset)11, Path = "Assets/9_VFX"}, - new FolderAddress { Identity = (IdentityAsset)12, Path = "Assets/10_Animation"}, - new FolderAddress { Identity = (IdentityAsset)13, Path = "Assets/7_Misc"}, - new FolderAddress { Identity = (IdentityAsset)14, Path = "Assets/Developer"}, - new FolderAddress { Identity = (IdentityAsset)15, Path = "Assets/Resources"}, - new FolderAddress { Identity = (IdentityAsset)16, Path = "Assets/~Thirdparty"}, - new FolderAddress { Identity = (IdentityAsset)17, Path = "Assets/4_Data/PCG"}, - new FolderAddress { Identity = (IdentityAsset)18, Path = "Assets/7_Misc/Templates/Scripts"}, - new FolderAddress { Identity = (IdentityAsset)19, Path = "Assets/7_Misc/Templates/Prefabs"}, - new FolderAddress { Identity = (IdentityAsset)20, Path = "Assets/2_Scripts/_Game/Utility"} + new FolderAddress { AssetType = 0, AssetPath = "1_Scenes"}, + new FolderAddress { AssetType = (AssetFormat)1, AssetPath = "2_Scripts" }, + new FolderAddress { AssetType = (AssetFormat)2, AssetPath = "3_Prefabs"}, + new FolderAddress { AssetType = (AssetFormat)3, AssetPath = "4_Data" }, + new FolderAddress { AssetType = (AssetFormat)4, AssetPath = "5_Mesh"}, + new FolderAddress { AssetType = (AssetFormat)5, AssetPath = "5_Sprite"}, + new FolderAddress { AssetType = (AssetFormat)6, AssetPath = "7_Misc/Textures"}, + new FolderAddress { AssetType = (AssetFormat)7, AssetPath = "7_Misc/Videos"}, + new FolderAddress { AssetType = (AssetFormat)8, AssetPath = "7_Misc/Materials"}, + new FolderAddress { AssetType = (AssetFormat)9, AssetPath = "6_Shader"}, + new FolderAddress { AssetType = (AssetFormat)10, AssetPath = "8_Sound&Music"}, + new FolderAddress { AssetType = (AssetFormat)11, AssetPath = "9_VFX"}, + new FolderAddress { AssetType = (AssetFormat)12, AssetPath = "10_Animation"}, + new FolderAddress { AssetType = (AssetFormat)13, AssetPath = "7_Misc"} }; + public IReadOnlyList ProjectStructure => projectStructure; + // Access values + public string this[AssetFormat type] + { + get => GetFolderAddressByType(type).GetFolderPath(this); + } + // Public Functions - public Type GetGameInstanceClass() + public Type GetGameInstanceType() { foreach (var assembly in AppDomain.CurrentDomain.GetAssemblies()) { @@ -91,7 +101,7 @@ public Type GetGameInstanceClass() } return null; } - public void SetGameInstanceClass(Type type) + public void SetGameInstanceType(Type type) { // Store fully qualified name of the type if (type != null) @@ -102,9 +112,8 @@ public void SetGameInstanceClass(Type type) { Debug.LogError("Type is null. Cannot set GameInstanceClass."); } - } - public Type GetGameServiceClass() + public Type GetGameServiceType() { foreach (var assembly in AppDomain.CurrentDomain.GetAssemblies()) { @@ -114,7 +123,7 @@ public Type GetGameServiceClass() } return null; } - public void SetGameServiceClass(Type type) + public void SetGameServiceType(Type type) { // Store fully qualified name of the type if (type != null) @@ -139,18 +148,27 @@ public GameObject[] GetGamePrefabs() GamePrefab_3, }; } - public FolderAddress FindAddres(IdentityAsset identity) + public int GetStructureType() + { + return (int)structureType; + } + public void SetStructureType(int type) + { + structureType = (FolderStructureType)type; + } + public FolderAddress GetFolderAddressByIndex(int index) => projectStructure[index]; + public void SetFolderAddressPath(int index, string value) => projectStructure[index].AssetPath = value; + public FolderAddress GetFolderAddressByType(AssetFormat identity) { - foreach (var PS in ProjectStructure) + foreach (var PS in projectStructure) { - if (PS.Identity == identity) + if (PS.AssetType == identity) { return PS; } } return default(FolderAddress); } - } From 80535b0b3ff779bfcb64e25df30be6618ad1e9ad Mon Sep 17 00:00:00 2001 From: Alijimpa Date: Sat, 27 Dec 2025 17:05:07 +0330 Subject: [PATCH 011/204] Refine Naming and folder sorting for Core --- Documentation/Information/ClassViewer.txt | 1 + Editor/Core/Architecture/Game_Editor.cs | 2 +- ...set_Validator.cs => ConfigAsset_Onload.cs} | 4 +- ...tor.cs.meta => ConfigAsset_Onload.cs.meta} | 0 .../RealMethod_ProjectSetting.cs | 6 +- ...gSection.cs => FolderStructure_Section.cs} | 2 +- ...s.meta => FolderStructure_Section.cs.meta} | 0 ...ction.cs => InitializerSetting_Section.cs} | 2 +- ...eta => InitializerSetting_Section.cs.meta} | 0 .../UnityAsset_Postprocessor.cs | 123 ------------------ .../SharedScripts/Classes/AssetProcess.cs | 67 ++++++++++ .../Classes/AssetProcess.cs.meta | 2 + .../ReadySet/Content/RealMethod_UnityAsset.cs | 6 +- .../Content/UnityAsset_Postprocessor.cs | 58 +++++++++ .../Content}/UnityAsset_Postprocessor.cs.meta | 0 Editor/Toolkit/PCG/PCG_UnityAsset.cs | 6 +- Reservoir/ScriptTemplates/GameTemplate.txt | 4 +- Runtime/Core/Architecture/Game.cs | 25 +++- .../ProjectSetting/ProjectSettingAsset.cs | 5 +- Runtime/ReadySet/DefaultsClass/DefaultGame.cs | 4 +- 20 files changed, 168 insertions(+), 149 deletions(-) rename Editor/Core/Definitions/{ConfigAsset_Validator.cs => ConfigAsset_Onload.cs} (97%) rename Editor/Core/Definitions/{ConfigAsset_Validator.cs.meta => ConfigAsset_Onload.cs.meta} (100%) rename Editor/Core/ProjectSetting/Sections/{FolderSettingSection.cs => FolderStructure_Section.cs} (98%) rename Editor/Core/ProjectSetting/Sections/{FolderSettingSection.cs.meta => FolderStructure_Section.cs.meta} (100%) rename Editor/Core/ProjectSetting/Sections/{InitializerSection.cs => InitializerSetting_Section.cs} (96%) rename Editor/Core/ProjectSetting/Sections/{InitializerSection.cs.meta => InitializerSetting_Section.cs.meta} (100%) delete mode 100644 Editor/Core/ProjectSetting/UnityAsset_Postprocessor.cs create mode 100644 Editor/Library/SharedScripts/Classes/AssetProcess.cs create mode 100644 Editor/Library/SharedScripts/Classes/AssetProcess.cs.meta create mode 100644 Editor/ReadySet/Content/UnityAsset_Postprocessor.cs rename Editor/{Core/ProjectSetting => ReadySet/Content}/UnityAsset_Postprocessor.cs.meta (100%) diff --git a/Documentation/Information/ClassViewer.txt b/Documentation/Information/ClassViewer.txt index bc5ba57..8d4a0d4 100644 --- a/Documentation/Information/ClassViewer.txt +++ b/Documentation/Information/ClassViewer.txt @@ -8,6 +8,7 @@ Runtime ManagerContracts ServiceContracts WorldSceneConfig + ProjectSettingAsset -> ProjectSettingAsset Should be in Resource>RealMethod>RealMethodSetting.asset and all RealMethod setting handeled by this asset and this name. Attributes ButtonAttribute ColorFieldAttribute diff --git a/Editor/Core/Architecture/Game_Editor.cs b/Editor/Core/Architecture/Game_Editor.cs index 08c9380..6ad9fdd 100644 --- a/Editor/Core/Architecture/Game_Editor.cs +++ b/Editor/Core/Architecture/Game_Editor.cs @@ -1,6 +1,6 @@ using UnityEditor; -namespace RealMethod +namespace RealMethod.Editor { [CustomEditor(typeof(Game), true)] public class Game_Editor : UnityEditor.Editor diff --git a/Editor/Core/Definitions/ConfigAsset_Validator.cs b/Editor/Core/Definitions/ConfigAsset_Onload.cs similarity index 97% rename from Editor/Core/Definitions/ConfigAsset_Validator.cs rename to Editor/Core/Definitions/ConfigAsset_Onload.cs index 65cf625..d5f4ee2 100644 --- a/Editor/Core/Definitions/ConfigAsset_Validator.cs +++ b/Editor/Core/Definitions/ConfigAsset_Onload.cs @@ -7,9 +7,9 @@ namespace RealMethod.Editor { [InitializeOnLoad] - public static class ConfigAsset_Validator + public static class ConfigAsset_Onload { - static ConfigAsset_Validator() + static ConfigAsset_Onload() { EditorApplication.delayCall += ValidateAllConfigs; } diff --git a/Editor/Core/Definitions/ConfigAsset_Validator.cs.meta b/Editor/Core/Definitions/ConfigAsset_Onload.cs.meta similarity index 100% rename from Editor/Core/Definitions/ConfigAsset_Validator.cs.meta rename to Editor/Core/Definitions/ConfigAsset_Onload.cs.meta diff --git a/Editor/Core/ProjectSetting/RealMethod_ProjectSetting.cs b/Editor/Core/ProjectSetting/RealMethod_ProjectSetting.cs index f085417..85690a4 100644 --- a/Editor/Core/ProjectSetting/RealMethod_ProjectSetting.cs +++ b/Editor/Core/ProjectSetting/RealMethod_ProjectSetting.cs @@ -7,11 +7,13 @@ namespace RealMethod.Editor { + // Interface for call base method in ProjectSettingSection by RealMethodSetting interface ISectionSetting { void FirstSelected(ProjectSettingAsset storage); void Draw(); } + // Abstract base class for a settings section public abstract class ProjectSettingSection : ISectionSetting { @@ -116,8 +118,8 @@ public static class RealMethod_ProjectSetting private static bool candraw = true;// Flag to determine if the UI can be drawn private static ProjectSettingSection[] sections = new ProjectSettingSection[2] { // Array of sections to be rendered in the settings UI - new InitializerSection(), - new FolderSettingSection() + new InitializerSetting_Section(), + new FolderStructure_Section() }; diff --git a/Editor/Core/ProjectSetting/Sections/FolderSettingSection.cs b/Editor/Core/ProjectSetting/Sections/FolderStructure_Section.cs similarity index 98% rename from Editor/Core/ProjectSetting/Sections/FolderSettingSection.cs rename to Editor/Core/ProjectSetting/Sections/FolderStructure_Section.cs index b9a6298..c62e6ea 100644 --- a/Editor/Core/ProjectSetting/Sections/FolderSettingSection.cs +++ b/Editor/Core/ProjectSetting/Sections/FolderStructure_Section.cs @@ -3,7 +3,7 @@ namespace RealMethod.Editor { - public class FolderSettingSection : ProjectSettingSection + public class FolderStructure_Section : ProjectSettingSection { private ProjectSettingAsset MyStorage; private bool isPanelMaximize = false; // Add a toggle for minimizing the panel diff --git a/Editor/Core/ProjectSetting/Sections/FolderSettingSection.cs.meta b/Editor/Core/ProjectSetting/Sections/FolderStructure_Section.cs.meta similarity index 100% rename from Editor/Core/ProjectSetting/Sections/FolderSettingSection.cs.meta rename to Editor/Core/ProjectSetting/Sections/FolderStructure_Section.cs.meta diff --git a/Editor/Core/ProjectSetting/Sections/InitializerSection.cs b/Editor/Core/ProjectSetting/Sections/InitializerSetting_Section.cs similarity index 96% rename from Editor/Core/ProjectSetting/Sections/InitializerSection.cs rename to Editor/Core/ProjectSetting/Sections/InitializerSetting_Section.cs index b975d3a..9fc11b2 100644 --- a/Editor/Core/ProjectSetting/Sections/InitializerSection.cs +++ b/Editor/Core/ProjectSetting/Sections/InitializerSetting_Section.cs @@ -3,7 +3,7 @@ namespace RealMethod.Editor { - public class InitializerSection : ProjectSettingSection + public class InitializerSetting_Section : ProjectSettingSection { private ClassType gameClass; private ClassType gameService; diff --git a/Editor/Core/ProjectSetting/Sections/InitializerSection.cs.meta b/Editor/Core/ProjectSetting/Sections/InitializerSetting_Section.cs.meta similarity index 100% rename from Editor/Core/ProjectSetting/Sections/InitializerSection.cs.meta rename to Editor/Core/ProjectSetting/Sections/InitializerSetting_Section.cs.meta diff --git a/Editor/Core/ProjectSetting/UnityAsset_Postprocessor.cs b/Editor/Core/ProjectSetting/UnityAsset_Postprocessor.cs deleted file mode 100644 index 95642d8..0000000 --- a/Editor/Core/ProjectSetting/UnityAsset_Postprocessor.cs +++ /dev/null @@ -1,123 +0,0 @@ -using UnityEditor; -using UnityEngine; - -namespace RealMethod.Editor -{ - public class UnityAsset_Postprocessor : AssetPostprocessor - { - static AssetHandeler[] AssetList = new AssetHandeler[5] { - new WorldScene_UnityAsset(), - new Table_UnityAsset(), - new PCGResource_UnityAsset(), - new PCGGeneration_UnityAsset(), - new PCGCash_UnityAsset() }; - - // private static void OnPostprocessAllAssets(string[] importedAssets, string[] deletedAssets, string[] movedAssets, string[] movedFromAssetPaths) - // { - // if (AssetList == null) - // { - // return; - // } - - // foreach (var asset in AssetList) - // { - // foreach (string assetPath in importedAssets) - // { - // asset.OnAssetImported(assetPath); - // } - // foreach (string assetPath in deletedAssets) - // { - // asset.OnAssetDeleted(assetPath); - // } - // for (int i = 0; i < movedAssets.Length; i++) - // { - // asset.OnAssetMoved(movedAssets[i], movedFromAssetPaths[i]); - // } - // } - // } - - [InitializeOnLoadMethod] - private static void OnDoubleClickScriptableObject() - { - EditorApplication.projectWindowItemOnGUI += (guid, rect) => - { - Event e = Event.current; - if (e.type == EventType.MouseDown && e.clickCount == 2) - { - string assetPath = AssetDatabase.GUIDToAssetPath(guid); - foreach (var asset in AssetList) - { - asset.OnAssetClick(assetPath, e); - } - } - }; - } - } - - - - public abstract class AssetHandeler - { - public AssetHandeler() - { - Initialized(); - } - - protected abstract void Initialized(); - public abstract void OnAssetImported(string AssetPath); - public abstract void OnAssetDeleted(string AssetPath); - public abstract void OnAssetMoved(string AssetPath, string FromPath); - public abstract void OnAssetClick(string AssetPath, Event e); - protected abstract string GetIconPath(); - } - - public abstract class AssetHandeler : AssetHandeler where T : Object - { - protected abstract void DoubleClick(T asset); - - public override void OnAssetImported(string AssetPath) - { - T loadedAsset; - if (TryLoadAsset(AssetPath, out loadedAsset)) - { - if (loadedAsset.GetType() == typeof(J)) - { - // Load your icon from Resources (adjust the path as needed) - Texture2D icon = Resources.Load(GetIconPath()); - if (icon != null) - { - EditorGUIUtility.SetIconForObject(loadedAsset, icon); - } - else - { - Debug.LogWarning("Custom icon not found. Please ensure the path and file are correct."); - } - } - } - else - { - Debug.LogWarning("Cant Load "); - } - } - public override void OnAssetClick(string AssetPath, Event e) - { - var asset = AssetDatabase.LoadAssetAtPath(AssetPath); - - if (asset != null) - { - DoubleClick(asset); - e.Use(); // Consume the event - } - } - - protected bool TryLoadAsset(string assetPath, out K asset) where K : Object - { - asset = AssetDatabase.LoadAssetAtPath(assetPath); - return asset != null; - } - } - - - - -} \ No newline at end of file diff --git a/Editor/Library/SharedScripts/Classes/AssetProcess.cs b/Editor/Library/SharedScripts/Classes/AssetProcess.cs new file mode 100644 index 0000000..85393ee --- /dev/null +++ b/Editor/Library/SharedScripts/Classes/AssetProcess.cs @@ -0,0 +1,67 @@ +using UnityEngine; +using UnityEditor; + + +namespace RealMethod.Editor +{ + public abstract class AssetProcess + { + public AssetProcess() + { + Initialized(); + } + + protected abstract void Initialized(); + public abstract void OnAssetImported(string AssetPath); + public abstract void OnAssetDeleted(string AssetPath); + public abstract void OnAssetMoved(string AssetPath, string FromPath); + public abstract void OnAssetClick(string AssetPath, Event e); + protected abstract string GetIconPath(); + } + public abstract class AssetProcess : AssetProcess where T : Object + { + protected abstract void DoubleClick(T asset); + + public override void OnAssetImported(string AssetPath) + { + T loadedAsset; + if (TryLoadAsset(AssetPath, out loadedAsset)) + { + if (loadedAsset.GetType() == typeof(J)) + { + // Load your icon from Resources (adjust the path as needed) + Texture2D icon = Resources.Load(GetIconPath()); + if (icon != null) + { + EditorGUIUtility.SetIconForObject(loadedAsset, icon); + } + else + { + Debug.LogWarning("Custom icon not found. Please ensure the path and file are correct."); + } + } + } + else + { + Debug.LogWarning("Cant Load "); + } + } + public override void OnAssetClick(string AssetPath, Event e) + { + var asset = AssetDatabase.LoadAssetAtPath(AssetPath); + + if (asset != null) + { + DoubleClick(asset); + e.Use(); // Consume the event + } + } + + protected bool TryLoadAsset(string assetPath, out K asset) where K : Object + { + asset = AssetDatabase.LoadAssetAtPath(assetPath); + return asset != null; + } + } + +} \ No newline at end of file diff --git a/Editor/Library/SharedScripts/Classes/AssetProcess.cs.meta b/Editor/Library/SharedScripts/Classes/AssetProcess.cs.meta new file mode 100644 index 0000000..0dc6766 --- /dev/null +++ b/Editor/Library/SharedScripts/Classes/AssetProcess.cs.meta @@ -0,0 +1,2 @@ +fileFormatVersion: 2 +guid: 060b9dbad7dba424b9f55475deb3b39d \ No newline at end of file diff --git a/Editor/ReadySet/Content/RealMethod_UnityAsset.cs b/Editor/ReadySet/Content/RealMethod_UnityAsset.cs index 48c1cde..98660cb 100644 --- a/Editor/ReadySet/Content/RealMethod_UnityAsset.cs +++ b/Editor/ReadySet/Content/RealMethod_UnityAsset.cs @@ -2,7 +2,7 @@ namespace RealMethod.Editor { - public class Table_UnityAsset : AssetHandeler + public class Table_UnityAsset : AssetProcess { protected override void Initialized() { @@ -26,7 +26,7 @@ protected override void DoubleClick(TableAsset asset) TableViewerWindow.OpenWindow(asset); } } - public class WorldScene_UnityAsset : AssetHandeler + public class WorldScene_UnityAsset : AssetProcess { protected override void Initialized() { @@ -49,7 +49,7 @@ protected override void DoubleClick(WorldSceneConfig asset) asset.OnAssetClick(); } } - public class Game_UnityAsset : AssetHandeler + public class Game_UnityAsset : AssetProcess { protected override void Initialized() { diff --git a/Editor/ReadySet/Content/UnityAsset_Postprocessor.cs b/Editor/ReadySet/Content/UnityAsset_Postprocessor.cs new file mode 100644 index 0000000..bfdbf40 --- /dev/null +++ b/Editor/ReadySet/Content/UnityAsset_Postprocessor.cs @@ -0,0 +1,58 @@ +using UnityEditor; +using UnityEngine; + +namespace RealMethod.Editor +{ + public class UnityAsset_Postprocessor : AssetPostprocessor + { + private static AssetProcess[] AssetList = new AssetProcess[5] + { + new WorldScene_UnityAsset(), + new Table_UnityAsset(), + new PCGResource_UnityAsset(), + new PCGGeneration_UnityAsset(), + new PCGCash_UnityAsset() + }; + + [InitializeOnLoadMethod] + private static void OnDoubleClickScriptableObject() + { + EditorApplication.projectWindowItemOnGUI += (guid, rect) => + { + Event e = Event.current; + if (e.type == EventType.MouseDown && e.clickCount == 2) + { + string assetPath = AssetDatabase.GUIDToAssetPath(guid); + foreach (var asset in AssetList) + { + asset.OnAssetClick(assetPath, e); + } + } + }; + } + + // private static void OnPostprocessAllAssets(string[] importedAssets, string[] deletedAssets, string[] movedAssets, string[] movedFromAssetPaths) + // { + // if (AssetList == null) + // { + // return; + // } + + // foreach (var asset in AssetList) + // { + // foreach (string assetPath in importedAssets) + // { + // asset.OnAssetImported(assetPath); + // } + // foreach (string assetPath in deletedAssets) + // { + // asset.OnAssetDeleted(assetPath); + // } + // for (int i = 0; i < movedAssets.Length; i++) + // { + // asset.OnAssetMoved(movedAssets[i], movedFromAssetPaths[i]); + // } + // } + // } + } +} \ No newline at end of file diff --git a/Editor/Core/ProjectSetting/UnityAsset_Postprocessor.cs.meta b/Editor/ReadySet/Content/UnityAsset_Postprocessor.cs.meta similarity index 100% rename from Editor/Core/ProjectSetting/UnityAsset_Postprocessor.cs.meta rename to Editor/ReadySet/Content/UnityAsset_Postprocessor.cs.meta diff --git a/Editor/Toolkit/PCG/PCG_UnityAsset.cs b/Editor/Toolkit/PCG/PCG_UnityAsset.cs index 1a976e3..01de736 100644 --- a/Editor/Toolkit/PCG/PCG_UnityAsset.cs +++ b/Editor/Toolkit/PCG/PCG_UnityAsset.cs @@ -1,6 +1,6 @@ namespace RealMethod.Editor { - public class PCGResource_UnityAsset : AssetHandeler + public class PCGResource_UnityAsset : AssetProcess { protected override void Initialized() { @@ -24,7 +24,7 @@ protected override void DoubleClick(PCGResourceConfig asset) } } - public class PCGGeneration_UnityAsset : AssetHandeler + public class PCGGeneration_UnityAsset : AssetProcess { protected override void Initialized() { @@ -48,7 +48,7 @@ protected override void DoubleClick(PCGGenerationAsset asset) } } - public class PCGCash_UnityAsset : AssetHandeler + public class PCGCash_UnityAsset : AssetProcess { protected override void Initialized() { diff --git a/Reservoir/ScriptTemplates/GameTemplate.txt b/Reservoir/ScriptTemplates/GameTemplate.txt index 16d7ecc..9227586 100644 --- a/Reservoir/ScriptTemplates/GameTemplate.txt +++ b/Reservoir/ScriptTemplates/GameTemplate.txt @@ -4,12 +4,12 @@ public class #SCRIPTNAME# : Game { // Game Methods - protected override void GameInitialized() + protected override void OnGameInitialized() { // Called right after Unity finishes loading the engine before any scene or subsystem is loaded. // You can insure when Called that GameService , GameConfig and all Managers Initilized. } - protected override void GameStarted() + protected override void OnGameStarted() { // Called after Unity finishes initializing the engine, but before the first scene is loaded. // It’s guaranteed to execute before any Awake() or Start() in your scene objects. diff --git a/Runtime/Core/Architecture/Game.cs b/Runtime/Core/Architecture/Game.cs index e5f7389..1c30658 100644 --- a/Runtime/Core/Architecture/Game.cs +++ b/Runtime/Core/Architecture/Game.cs @@ -102,6 +102,7 @@ private static void InitializeGame() Debug.LogWarning($"Component of type {TargetClass} is not assignable from Game. DefaultGame Created"); Instance = emptyObject.AddComponent(); } + Instance.OnProjectSeettingLoaded(ref ProjectSettings); // Create Game Service Type targetService = ProjectSettings.GetGameServiceType(); @@ -168,25 +169,25 @@ private static void InitializeGame() Application.quitting += Instance.Notify_OnGameQuit; } /// - /// Called before any scene is loaded. Invokes on the active instance. + /// Called before any scene is loaded. Invokes on the active instance. /// [RuntimeInitializeOnLoadMethod(RuntimeInitializeLoadType.BeforeSceneLoad)] private static void RuntimeBeforeSceneLoad() { if (Instance != null) { - Instance.GameInitialized(); + Instance.OnGameInitialized(); } } /// - /// Called after a scene has finished loading. Invokes on the active instance. + /// Called after a scene has finished loading. Invokes on the active instance. /// [RuntimeInitializeOnLoadMethod(RuntimeInitializeLoadType.AfterSceneLoad)] private static void RuntimeAfterSceneLoad() { if (Instance != null) { - Instance.GameStarted(); + Instance.OnGameStarted(); } } @@ -516,6 +517,18 @@ public IGameManager GetManager(string ObjectName) } + /// + /// Called after GameInstance Created befor GameService , GameConfig & Managers Initilized + /// if you use custom PtojectSetttingAsset class you can use instances after loaded in game + /// this refrence unloaded befor OnGameInitialized Called. + /// + /// ProjectSettingAsset refrence + protected virtual void OnProjectSeettingLoaded(ref ProjectSettingAsset setting) + { + // Nothing todo + } + + /// /// Callback invoked when a new is created or assigned. /// Updates the static reference and notifies all services. @@ -554,12 +567,12 @@ private void Notify_OnGameQuit() /// Called once when the game framework has finished initial initialization. /// Implement this to perform game-specific initialization logic. /// - protected abstract void GameInitialized(); + protected abstract void OnGameInitialized(); /// /// Called after the first scene has been loaded and the game has started. /// Implement this to perform logic that should run once the first scene is active. /// - protected abstract void GameStarted(); + protected abstract void OnGameStarted(); /// /// Called when the current reference changes. /// Implement to react to world switches. diff --git a/Runtime/Core/ProjectSetting/ProjectSettingAsset.cs b/Runtime/Core/ProjectSetting/ProjectSettingAsset.cs index 3156a2e..3b65e43 100644 --- a/Runtime/Core/ProjectSetting/ProjectSettingAsset.cs +++ b/Runtime/Core/ProjectSetting/ProjectSettingAsset.cs @@ -7,7 +7,6 @@ namespace RealMethod // Real Method Setting Storage public class ProjectSettingAsset : ScriptableObject { - private string ProjectName; [Serializable] public struct FolderAddress { @@ -16,7 +15,7 @@ public struct FolderAddress public string FolderName => System.IO.Path.GetFileName(AssetPath); public string GetFolderPath(ProjectSettingAsset settingAsset) { - string RootPath = settingAsset.GetStructureType() == 0 ? "Assets" : "Assets/"+Application.productName; + string RootPath = settingAsset.GetStructureType() == 0 ? "Assets" : "Assets/" + Application.productName; return $"{RootPath}/{AssetPath}"; } @@ -46,7 +45,6 @@ public enum FolderStructureType ProjectName = 1, } - [Header("Initializer")] [SerializeField, ReadOnly] private string GameClass = "RealMethod.DefultGame"; @@ -169,6 +167,7 @@ public FolderAddress GetFolderAddressByType(AssetFormat identity) } return default(FolderAddress); } + } diff --git a/Runtime/ReadySet/DefaultsClass/DefaultGame.cs b/Runtime/ReadySet/DefaultsClass/DefaultGame.cs index c4a9be7..fa1f575 100644 --- a/Runtime/ReadySet/DefaultsClass/DefaultGame.cs +++ b/Runtime/ReadySet/DefaultsClass/DefaultGame.cs @@ -6,11 +6,11 @@ namespace RealMethod [AddComponentMenu("RealMethod/Essential/DefultGame")] public sealed class DefultGame : Game { - protected override void GameInitialized() + protected override void OnGameInitialized() { Debug.Log("DefultGame Initialized"); } - protected override void GameStarted() + protected override void OnGameStarted() { Debug.Log("DefultGame Started"); } From 1a67ff77da17f6f8b14a2502d5ec9865327a09ef Mon Sep 17 00:00:00 2001 From: Alijimpa Date: Sat, 27 Dec 2025 17:12:59 +0330 Subject: [PATCH 012/204] Fix Class Viewer for Show Nunlink Address --- Editor/ReadySet/Tools/ClassViewerWindow.cs | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/Editor/ReadySet/Tools/ClassViewerWindow.cs b/Editor/ReadySet/Tools/ClassViewerWindow.cs index b925957..6a25e38 100644 --- a/Editor/ReadySet/Tools/ClassViewerWindow.cs +++ b/Editor/ReadySet/Tools/ClassViewerWindow.cs @@ -33,7 +33,7 @@ public static void Open() private void OnEnable() { string ClassViewPath = "Assets/Realmethod/Documentation/Information/ClassViewer.txt"; // Just for Test - //string ClassViewPath = Path.Combine(RM_CoreEditor.Documentation, "ClassViewer.txt"); + // string ClassViewPath = Path.Combine(RM_CoreEditor.Documentation, "ClassViewer.txt"); if (!File.Exists(ClassViewPath)) { Debug.LogError($"ClassView file not found: {ClassViewPath}"); @@ -114,10 +114,10 @@ private void LoadFromText(string text) endText = middleText.Substring(0, linkindex).Trim(); linkText = middleText.Substring(linkindex).Trim(); } - } - else - { - endText = middleText; + else + { + endText = middleText; + } } ClassTreeNode node = new ClassTreeNode From fbabe9bc62f7785d3f0138adad88d79ff0f81bb3 Mon Sep 17 00:00:00 2001 From: Alijimpa Date: Sun, 28 Dec 2025 12:10:05 +0330 Subject: [PATCH 013/204] Wrok on ReadMe --- Documentation/README.md | 26 +++ .../README.md.meta | 0 .../Resource/RM_Title.png | Bin .../Resource/RM_Title.png.meta | 0 README.md | 148 ------------------ 5 files changed, 26 insertions(+), 148 deletions(-) create mode 100644 Documentation/README.md rename README.md.meta => Documentation/README.md.meta (100%) rename Reservoir/Icons/Core/RealMethod.png => Documentation/Resource/RM_Title.png (100%) rename Reservoir/Icons/Core/RealMethod.png.meta => Documentation/Resource/RM_Title.png.meta (100%) delete mode 100644 README.md diff --git a/Documentation/README.md b/Documentation/README.md new file mode 100644 index 0000000..1b90d48 --- /dev/null +++ b/Documentation/README.md @@ -0,0 +1,26 @@ +# RealMethod +**"`RealMethod` is a minimal, Unreal-inspired architecture for structuring Unity games with clear lifetime, ownership, and system boundaries."** +### Links +* [Documentation(Wiki)](https://github.com/AliJimpa/RealMethod/wiki/Home) +* [Video Tutorials]() +### The Pitch +`RealMethod` is a minimal architectural framework for Unity. It provides a small, explicit structure for organizing game lifetime, world context, and systems, inspired by **Unreal Engine** concepts such as `GameInstance` and `GameMode`. + +`RealMethod` is designed to help programmers build and maintain scalable Unity projects by enforcing clear ownership and predictable lifecycles. It favors simplicity and clarity over abstraction and avoids heavy frameworks, dependency injection containers, or hidden execution flows. `RealMethod` focuses on structure, not gameplay, and does not attempt to replace Unity workflows. + +`RealMethod` is particularly suited for games and real-time applications where long-term maintainability matters: indie and studio projects, system-heavy games, tool-driven workflows, and projects that must evolve over time without architectural collapse. +* Clear ownership and responsibility +* Unreal-like mental model for Unity +* Minimal core, flexible edges +* Scales from small games +* experimental for productions +* Team-friendly and testable architecture +### Quick Setup +Install via Unity Package Manager: +1. Open Package Manager +2. Click Add package from Git URL +3. Paste +>https://github.com/AliJimpa/RealMethod.git +4. Follow the Getting Started guide +>https://github.com/AliJimpa/RealMethod/wiki/Quick-Setup + diff --git a/README.md.meta b/Documentation/README.md.meta similarity index 100% rename from README.md.meta rename to Documentation/README.md.meta diff --git a/Reservoir/Icons/Core/RealMethod.png b/Documentation/Resource/RM_Title.png similarity index 100% rename from Reservoir/Icons/Core/RealMethod.png rename to Documentation/Resource/RM_Title.png diff --git a/Reservoir/Icons/Core/RealMethod.png.meta b/Documentation/Resource/RM_Title.png.meta similarity index 100% rename from Reservoir/Icons/Core/RealMethod.png.meta rename to Documentation/Resource/RM_Title.png.meta diff --git a/README.md b/README.md deleted file mode 100644 index abe4bee..0000000 --- a/README.md +++ /dev/null @@ -1,148 +0,0 @@ -# 🌌 RealMethod -*A lightweight Unity architecture for scalable and modular project creation.* ---- - -## ✨ Overview - -**RealMethod** is a Unity package that defines a clean and consistent **project architecture**. -It focuses on separation of responsibility and lifecycle management, allowing developers to build games that are easily extendable, maintainable, and modular. - -RealMethod introduces five main layers: -- **Core** – Defines the base relationships between Game, World, Manager, and Service. -- **Library** – Common utility functions, interfaces, and shared components. -- **Pattern** – Predefined architecture patterns and reusable managers. -- **Toolkit** – Ready-to-use tools, inspectors, and debugging helpers. -- **ReadySet** – Example setups and templates for quick project initialization. - ---- - -## 🧩 Core Architecture - -### **Game** -- The **Game** class is the entry point of the RealMethod framework. -- It is a **singleton** that lives for the entire game lifecycle (until quit). -- Responsible for global operations such as: - - Scene management (`OpenScene`, `ReloadScene`, etc.) - - Time control (`SetGameSpeed`) - - Service construction and destruction - -All **Managers** and **Services** are registered through `Game`, ensuring consistent global access. - ---- - -### **World** -- The **World** class exists **once per scene** and acts as the runtime context for that scene. -- It initializes all **World-scoped Managers** and prepares the scene for gameplay. -- While **Game** persists between scenes, **World** resets when scenes change. -- Required in every scene that uses RealMethod. - ---- - -### **Manager** -- A **Manager** defines a controllable system within a given scope (Game or World). -- Implements the `IManager` interface. -- Managers are initialized **before Unity’s Awake/Start** callbacks. -- Can live in one of two scopes: - - **Game scope:** persists between scenes (registered under Game). - - **World scope:** tied to a specific scene (registered under World). - -Both Game and World automatically call `DontDestroyOnLoad` for their scoped Managers. - ---- - -### **Service** -- A **Service** is a lightweight, non-MonoBehaviour object managed by the Game. -- Created dynamically using `Game.CreateService()`. -- All Managers automatically recognize and can interact with new Services. -- Can be destroyed at any time via `Game.DestroyService()`. -- Ideal for runtime systems like data caching, analytics, or network clients. - ---- - -## ⚙️ Lifecycle Summary - -| Layer | Scope | Lifetime | Created By | Notes | -|-------|--------|-----------|-------------|-------| -| Game | Global | Until Quit | App Start | Singleton | -| World | Scene | Per Scene | Scene Load | Scene Context | -| Manager | Global/Scene | Anytime | Game/World | Registered in Game/Scene scope | -| Service | Runtime | Dynamic | Game | Fully managed objects | - ---- - -## 📦 Package Structure -RealMethod is organized into clearly separated runtime, editor, and resource layers — each designed to keep your project scalable, readable, and modular. -### 🧩 Runtime -Core runtime code that runs inside Unity builds. - -- **Core/** - - `Architecture/` – Core systems such as **Game**, **World**, **Manager**, and **Service**. - - `Attributes/` – Custom attributes used across the framework. - - `Definitions/` – Global enums, tags, and static definitions. - - `ProjectSetting/` – Runtime configuration and project constants. - -- **Library/** - - `Extension/` – Unity extensions and helper methods. - - `Interfaces/` – Common interfaces for modular communication. - - `SharedScripts/` – Shared data structures (Classes, Enums, Structs). - - `Utilities/` – Core utility scripts. - - `Vendor/SerializableDictionary/` – Third-party generic dictionary support. - -- **Pattern/** - - `Components/` – Base components using RealMethod patterns. - - `DataAssets/` – ScriptableObject-based configuration. - - `DesignPatterns/` – Common gameplay and architecture patterns. - - `Managers/` – Runtime manager implementations. - - `Services/` – Service classes managed by the Game/World. - -- **ReadySet/** - - `Commands/` – Command execution framework (Executors, Tasks). - - `Components/` – Common building blocks (Input, Method, Physics, Time, UI, Visual). - - `DefaultsClass/` – Predefined data and logic templates. - - `Managers/` – Ready-to-use manager classes. - - `Presets/` – Resource and pooling presets (PoolAsset, ResourceAsset, Task). - - `Services/` – Prebuilt services and systems. - -- **Toolkit/** - - `Ability/` – Ability system and samples. - - `Actor/` – Actor handling and lifecycle logic. - - `CSVFile/` – CSV parsing and data import tools. - - `CurveViewer/` – Editor curve visualization. - - `Interaction/` – Interaction handling system. - - `Inventory/` – Inventory architecture. - - `PCG/` – Procedural generation tools and resources. - - `Pickup/` – Item pickup logic. - - `RPG/` – RPG systems (Resource, StatSystem). - - `Tutorial/` – Tutorial system and utilities. - - `Upgrade/` – Upgrade and progression tools. - ---- - -### 🛠️ Editor -Unity Editor extensions for all RealMethod layers. - -- **Core/** – Editor scripts for Architecture, Definitions, and Project Settings. -- **Library/** – Shared scripts, vendor tools, and utilities. -- **Pattern/** – Custom editors for data assets and managers. -- **ReadySet/** – Editor tools for content setup and asset generation. -- **Toolkit/** – Editors for gameplay systems (Ability, Inventory, TerrainTools, etc.). - ---- - -### 🧃 Reservoir -Central storage for framework assets. - -- `Icons/` – Organized icons for Core, Pattern, and Toolkit editors. -- `Prefabs/` – Prefab resources for samples and managers. -- `SceneTemplates/` – Example scenes for quick setup. -- `ScriptTemplates/` – Script templates for fast development. - ---- - -### 🧪 Samples~ -Example projects demonstrating **PopupMessage** and **Tutorial** systems. - ---- - -### 🧠 Tests -Unit and integration tests for **General**, **Inspector**, and **ScenesDot** systems. From eb4d2e95429ef407acd1c6a0b027be8bbbb7f2c9 Mon Sep 17 00:00:00 2001 From: Alijimpa Date: Sun, 28 Dec 2025 12:15:25 +0330 Subject: [PATCH 014/204] Miss Readme Place --- Documentation/README.md => README.md | 0 Documentation/README.md.meta => README.md.meta | 0 2 files changed, 0 insertions(+), 0 deletions(-) rename Documentation/README.md => README.md (100%) rename Documentation/README.md.meta => README.md.meta (100%) diff --git a/Documentation/README.md b/README.md similarity index 100% rename from Documentation/README.md rename to README.md diff --git a/Documentation/README.md.meta b/README.md.meta similarity index 100% rename from Documentation/README.md.meta rename to README.md.meta From dab4f11f246033b85d8cc6cd62bd8f8565e2c3e4 Mon Sep 17 00:00:00 2001 From: Ali Badpa Date: Sun, 28 Dec 2025 12:29:59 +0330 Subject: [PATCH 015/204] Update README.md add gallry --- README.md | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/README.md b/README.md index 1b90d48..718e059 100644 --- a/README.md +++ b/README.md @@ -23,4 +23,9 @@ Install via Unity Package Manager: >https://github.com/AliJimpa/RealMethod.git 4. Follow the Getting Started guide >https://github.com/AliJimpa/RealMethod/wiki/Quick-Setup +### Gallery +Examples projects using RealMethod: [Death Pulse](https://github.com/wolfpld/tracy](https://cafebazaar.ir/app/com.Mustard.DeathPulse?l=en)), [Crush Conquest](https://cafebazaar.ir/app/com.Mustard.CrushConquest?l=en), [HeardSpoken]() and [Fireball](). +| | | +|--|--| +|
![Crush Conquest](https://s.cafebazaar.ir/images/icons/com.Mustard.CrushConquest-7bbd0921-42dc-4c79-8676-5a51a79bc6e4_512x512.png?x-img=v1/format,type_webp,lossless_false/resize,h_256,w_256,lossless_false/optimize) |
![Death Pulse](https://s.cafebazaar.ir/images/icons/com.Mustard.DeathPulse-eb40fcf1-095b-4619-97d5-527a7a86dc4f_512x512.png?x-img=v1/format,type_webp,lossless_false/resize,h_256,w_256,lossless_false/optimize) | From 80070a2d106586c7a3c2206767fe675dc6f37ecb Mon Sep 17 00:00:00 2001 From: Alijimpa Date: Thu, 5 Mar 2026 00:48:07 +0330 Subject: [PATCH 016/204] Remove Prefs class from Core in Library --- Runtime/Library/Utilities/Core.cs | 179 ------------------------------ 1 file changed, 179 deletions(-) diff --git a/Runtime/Library/Utilities/Core.cs b/Runtime/Library/Utilities/Core.cs index 85b8967..3bcd435 100644 --- a/Runtime/Library/Utilities/Core.cs +++ b/Runtime/Library/Utilities/Core.cs @@ -138,185 +138,6 @@ public static string GetVariableName(Expression> expression) } } - public class prefs - { - // Boolean - public static void SetBool(string key, bool value) - { - PlayerPrefs.SetInt(key, value ? 1 : 0); - } - public static bool GetBool(string key, bool defaultValue = false) - { - return PlayerPrefs.GetInt(key, defaultValue ? 1 : 0) == 1; - } - - // Vector3 - public static void SetVector3(string key, Vector3 value) - { - PlayerPrefs.SetFloat(key + "_V3x", value.x); - PlayerPrefs.SetFloat(key + "_V3y", value.y); - PlayerPrefs.SetFloat(key + "_V3z", value.z); - } - public static Vector3 GetVector3(string key, Vector3 defaultValue = default) - { - if (!PlayerPrefs.HasKey(key + "_V3x")) return defaultValue; - - float x = PlayerPrefs.GetFloat(key + "_V3x"); - float y = PlayerPrefs.GetFloat(key + "_V3y"); - float z = PlayerPrefs.GetFloat(key + "_V3z"); - return new Vector3(x, y, z); - } - public static bool HasVector3(string key) - { - return PlayerPrefs.HasKey(key + "_V3x"); - } - public static void DeleteVector3(string key) - { - PlayerPrefs.DeleteKey(key + "_V3x"); - PlayerPrefs.DeleteKey(key + "_V3y"); - PlayerPrefs.DeleteKey(key + "_V3z"); - PlayerPrefs.DeleteKey(key + "_V3w"); - } - - // Vector2 - public static void SetVector2(string key, Vector2 value) - { - PlayerPrefs.SetFloat(key + "_V2x", value.x); - PlayerPrefs.SetFloat(key + "_V2y", value.y); - } - public static Vector2 GetVector2(string key, Vector2 defaultValue = default) - { - if (!PlayerPrefs.HasKey(key + "_V2x")) return defaultValue; - - float x = PlayerPrefs.GetFloat(key + "_V2x"); - float y = PlayerPrefs.GetFloat(key + "_V2y"); - return new Vector2(x, y); - } - public static bool HasVector2(string key) - { - return PlayerPrefs.HasKey(key + "_V2x"); - } - public static void DeleteVector2(string key) - { - PlayerPrefs.DeleteKey(key + "_V2x"); - PlayerPrefs.DeleteKey(key + "_V2y"); - PlayerPrefs.DeleteKey(key + "_V2z"); - PlayerPrefs.DeleteKey(key + "_V2w"); - } - - // Quaternion - public static void SetQuaternion(string key, Quaternion value) - { - PlayerPrefs.SetFloat(key + "_Qx", value.x); - PlayerPrefs.SetFloat(key + "_Qy", value.y); - PlayerPrefs.SetFloat(key + "_Qz", value.z); - PlayerPrefs.SetFloat(key + "_Qw", value.w); - } - public static Quaternion GetQuaternion(string key, Quaternion defaultValue = default) - { - if (!PlayerPrefs.HasKey(key + "_Qx")) return defaultValue; - - float x = PlayerPrefs.GetFloat(key + "_Qx"); - float y = PlayerPrefs.GetFloat(key + "_Qy"); - float z = PlayerPrefs.GetFloat(key + "_Qz"); - float w = PlayerPrefs.GetFloat(key + "_Qw"); - return new Quaternion(x, y, z, w); - } - public static bool HasQuaternion(string key) - { - return PlayerPrefs.HasKey(key + "_Qx"); - } - public static void DeleteQuaternion(string key) - { - PlayerPrefs.DeleteKey(key + "_Qx"); - PlayerPrefs.DeleteKey(key + "_Qy"); - PlayerPrefs.DeleteKey(key + "_Qz"); - PlayerPrefs.DeleteKey(key + "_Qw"); - } - - // Transform - public static void SetTransform(string key, Transform transform, bool includeScale = false) - { - // Save Position - PlayerPrefs.SetFloat(key + "_pos_x", transform.position.x); - PlayerPrefs.SetFloat(key + "_pos_y", transform.position.y); - PlayerPrefs.SetFloat(key + "_pos_z", transform.position.z); - - // Save Rotation - PlayerPrefs.SetFloat(key + "_rot_x", transform.rotation.x); - PlayerPrefs.SetFloat(key + "_rot_y", transform.rotation.y); - PlayerPrefs.SetFloat(key + "_rot_z", transform.rotation.z); - PlayerPrefs.SetFloat(key + "_rot_w", transform.rotation.w); - - if (includeScale) - { - PlayerPrefs.SetFloat(key + "_scale_x", transform.localScale.x); - PlayerPrefs.SetFloat(key + "_scale_y", transform.localScale.y); - PlayerPrefs.SetFloat(key + "_scale_z", transform.localScale.z); - } - - PlayerPrefs.Save(); - } - public static void GetTransform(string key, Transform transform, bool includeScale = false) - { - if (!PlayerPrefs.HasKey(key + "_pos_x")) return; // check if saved - - // Load Position - float px = PlayerPrefs.GetFloat(key + "_pos_x"); - float py = PlayerPrefs.GetFloat(key + "_pos_y"); - float pz = PlayerPrefs.GetFloat(key + "_pos_z"); - - // Load Rotation - float rx = PlayerPrefs.GetFloat(key + "_rot_x"); - float ry = PlayerPrefs.GetFloat(key + "_rot_y"); - float rz = PlayerPrefs.GetFloat(key + "_rot_z"); - float rw = PlayerPrefs.GetFloat(key + "_rot_w"); - - transform.position = new Vector3(px, py, pz); - transform.rotation = new Quaternion(rx, ry, rz, rw); - - if (includeScale && PlayerPrefs.HasKey(key + "_scale_x")) - { - float sx = PlayerPrefs.GetFloat(key + "_scale_x"); - float sy = PlayerPrefs.GetFloat(key + "_scale_y"); - float sz = PlayerPrefs.GetFloat(key + "_scale_z"); - transform.localScale = new Vector3(sx, sy, sz); - } - } - public static bool HasTransform(string key) - { - return PlayerPrefs.HasKey(key + "_pos_x"); - } - public static void DeleteTransform(string key) - { - string[] suffixes = { - "_pos_x", "_pos_y", "_pos_z", - "_rot_x", "_rot_y", "_rot_z", "_rot_w", - "_scale_x", "_scale_y", "_scale_z" - }; - - foreach (var suffix in suffixes) - { - PlayerPrefs.DeleteKey(key + suffix); - } - } - - // Array - public static void SetArray(string key, T[] array) - { - string joined = string.Join("|", array); // Use a delimiter unlikely to appear in your strings - PlayerPrefs.SetString(key, joined); - PlayerPrefs.Save(); - } - public static T[] GetArray(string key) - { - if (!PlayerPrefs.HasKey(key)) return new T[0]; - - string joined = PlayerPrefs.GetString(key); - return joined.Split('|').Select(s => (T)System.Convert.ChangeType(s, typeof(T))).ToArray(); // Convert each string to T - } - } - public class enume { public static bool AreEnumValuesEqual(T a, J b) where T : Enum where J : Enum From 4ac2389e0a9fe4d0a8a41f49f2ea5b96c95b8f60 Mon Sep 17 00:00:00 2001 From: Alijimpa Date: Thu, 5 Mar 2026 15:34:22 +0330 Subject: [PATCH 017/204] Rename GameService to GameBridge --- Editor/Core/Architecture/Game_Editor.cs | 2 +- .../Sections/InitializerSetting_Section.cs | 6 ++-- .../Content/RealMethod_ScriptTemplate.cs | 12 +++---- ...iceTemplate.txt => GameBridgeTemplate.txt} | 2 +- ...e.txt.meta => GameBridgeTemplate.txt.meta} | 0 Runtime/Core/Architecture/Game.cs | 32 +++++++++---------- Runtime/Core/Architecture/GameService.cs | 7 ++-- Runtime/Core/Architecture/World.cs | 4 +-- .../ProjectSetting/ProjectSettingAsset.cs | 10 +++--- .../{DefaultsClass.meta => Essentials.meta} | 0 .../DefaultGame.cs | 0 .../DefaultGame.cs.meta | 0 .../DefaultGameBridge.cs} | 6 ++-- .../DefaultGameBridge.cs.meta} | 0 .../DefaultGameConfig.cs | 0 .../DefaultGameConfig.cs.meta | 0 .../DefaultWorld.cs | 0 .../DefaultWorld.cs.meta | 0 Runtime/ReadySet/Managers/ScreenManager.cs | 4 +-- 19 files changed, 43 insertions(+), 42 deletions(-) rename Reservoir/ScriptTemplates/{GameServiceTemplate.txt => GameBridgeTemplate.txt} (83%) rename Reservoir/ScriptTemplates/{GameServiceTemplate.txt.meta => GameBridgeTemplate.txt.meta} (100%) rename Runtime/ReadySet/{DefaultsClass.meta => Essentials.meta} (100%) rename Runtime/ReadySet/{DefaultsClass => Essentials}/DefaultGame.cs (100%) rename Runtime/ReadySet/{DefaultsClass => Essentials}/DefaultGame.cs.meta (100%) rename Runtime/ReadySet/{DefaultsClass/DefaultGameService.cs => Essentials/DefaultGameBridge.cs} (62%) rename Runtime/ReadySet/{DefaultsClass/DefaultGameService.cs.meta => Essentials/DefaultGameBridge.cs.meta} (100%) rename Runtime/ReadySet/{DefaultsClass => Essentials}/DefaultGameConfig.cs (100%) rename Runtime/ReadySet/{DefaultsClass => Essentials}/DefaultGameConfig.cs.meta (100%) rename Runtime/ReadySet/{DefaultsClass => Essentials}/DefaultWorld.cs (100%) rename Runtime/ReadySet/{DefaultsClass => Essentials}/DefaultWorld.cs.meta (100%) diff --git a/Editor/Core/Architecture/Game_Editor.cs b/Editor/Core/Architecture/Game_Editor.cs index 6ad9fdd..1b680ac 100644 --- a/Editor/Core/Architecture/Game_Editor.cs +++ b/Editor/Core/Architecture/Game_Editor.cs @@ -33,7 +33,7 @@ private string GetWorld() } private string GetSetvice() { - return Game.Service != null ? Game.Service.GetType().Name : "GameService Not Valid"; + return Game.Bridge != null ? Game.Bridge.GetType().Name : "GameService Not Valid"; } private string GetConfig() { diff --git a/Editor/Core/ProjectSetting/Sections/InitializerSetting_Section.cs b/Editor/Core/ProjectSetting/Sections/InitializerSetting_Section.cs index 9fc11b2..2d18cb9 100644 --- a/Editor/Core/ProjectSetting/Sections/InitializerSetting_Section.cs +++ b/Editor/Core/ProjectSetting/Sections/InitializerSetting_Section.cs @@ -6,14 +6,14 @@ namespace RealMethod.Editor public class InitializerSetting_Section : ProjectSettingSection { private ClassType gameClass; - private ClassType gameService; + private ClassType gameBridge; private SerializedObject projectSettings; private ProjectSettingAsset SettingAsset; protected override void Initialized() { gameClass = new ClassType(); - gameService = new ClassType(); + gameBridge = new ClassType(); } protected override void BeginRender(ProjectSettingAsset Storage) { @@ -30,7 +30,7 @@ protected override void UpdateRender() gameClass.Draw(projectSettings, "GameClass", "Game Class"); // GameServiceClass - gameService.Draw(projectSettings, "GameService", "Game Service"); + gameBridge.Draw(projectSettings, "GameBridge", "Game Bridge"); // GameSettingAsset EditorGUILayout.PropertyField(projectSettings.FindProperty("GameConfig"), new GUIContent("Game Config")); diff --git a/Editor/ReadySet/Content/RealMethod_ScriptTemplate.cs b/Editor/ReadySet/Content/RealMethod_ScriptTemplate.cs index 5c01799..18f8256 100644 --- a/Editor/ReadySet/Content/RealMethod_ScriptTemplate.cs +++ b/Editor/ReadySet/Content/RealMethod_ScriptTemplate.cs @@ -15,6 +15,11 @@ public static void CreateWorld() { string Path = RM_Create.Script("WorldTemplate.txt", "MyWorld.cs"); } + [MenuItem("Assets/Create/Scripting/RealMethod/Essential/GameBridge", false, 80)] + public static void CreateGameBridgeClass() + { + string Path = RM_Create.Script("GameBridgeTemplate.txt", "MyGameBridge.cs"); + } // Managers [MenuItem("Assets/Create/Scripting/RealMethod/Manager/BaseManager", false, 80)] @@ -70,11 +75,6 @@ public static void CreateService() { string Path = RM_Create.Script("ServiceTemplate.txt", "MyServicec.cs"); } - [MenuItem("Assets/Create/Scripting/RealMethod/Service/GameService", false, 80)] - public static void CreateGameServiceClass() - { - string Path = RM_Create.Script("GameServiceTemplate.txt", "MyGameService.cs"); - } [MenuItem("Assets/Create/Scripting/RealMethod/Service/StateService", false, 80)] public static void CreateStateService() { @@ -85,7 +85,7 @@ public static void CreateRuleService() { string Path = RM_Create.Script("RuleServiceTemplate.txt", "MyRuleService.cs"); } - + // Assets diff --git a/Reservoir/ScriptTemplates/GameServiceTemplate.txt b/Reservoir/ScriptTemplates/GameBridgeTemplate.txt similarity index 83% rename from Reservoir/ScriptTemplates/GameServiceTemplate.txt rename to Reservoir/ScriptTemplates/GameBridgeTemplate.txt index fced4a8..fcd0e3b 100644 --- a/Reservoir/ScriptTemplates/GameServiceTemplate.txt +++ b/Reservoir/ScriptTemplates/GameBridgeTemplate.txt @@ -1,6 +1,6 @@ using RealMethod; -public class #SCRIPTNAME# : GameService +public class #SCRIPTNAME# : GameBridge { // Base Service Methods protected override void OnStart(object Author) {} diff --git a/Reservoir/ScriptTemplates/GameServiceTemplate.txt.meta b/Reservoir/ScriptTemplates/GameBridgeTemplate.txt.meta similarity index 100% rename from Reservoir/ScriptTemplates/GameServiceTemplate.txt.meta rename to Reservoir/ScriptTemplates/GameBridgeTemplate.txt.meta diff --git a/Runtime/Core/Architecture/Game.cs b/Runtime/Core/Architecture/Game.cs index 1c30658..d136bdb 100644 --- a/Runtime/Core/Architecture/Game.cs +++ b/Runtime/Core/Architecture/Game.cs @@ -28,7 +28,7 @@ public abstract class Game : MonoBehaviour /// /// The core implementation used for scene/world loading and service events. /// - public static GameService Service { get; private set; } + public static GameBridge Bridge { get; private set; } /// /// Active game configuration instance. /// @@ -105,32 +105,32 @@ private static void InitializeGame() Instance.OnProjectSeettingLoaded(ref ProjectSettings); // Create Game Service - Type targetService = ProjectSettings.GetGameServiceType(); + Type targetService = ProjectSettings.GetGameBridgeType(); if (targetService == null) { Debug.LogWarning($"GetGameServiceClass that was empty. DefaultGameService Created"); - Service = new DefaultGameService(); + Bridge = new DefaultGameBridge(); } if (typeof(Service).IsAssignableFrom(targetService)) { try { - Service = (GameService)Activator.CreateInstance(targetService); + Bridge = (GameBridge)Activator.CreateInstance(targetService); } catch (Exception ex) { Debug.LogError($"Failed to instantiate {targetService}: {ex.Message}. DefaultGameService Created"); - Service = new DefaultGameService(); + Bridge = new DefaultGameBridge(); } } else { Debug.LogWarning($"Type {targetService} is not assignable to Service. DefaultGameService Created"); - Service = new DefaultGameService(); + Bridge = new DefaultGameBridge(); } Instance.GameServices = new List(3); - ((IMethodSync)Service).BindMainWorldAdd(Instance.Notify_OnWorldInitiate); - ((IService)Service).Created(Instance); + ((IMethodSync)Bridge).BindMainWorldAdd(Instance.Notify_OnWorldInitiate); + ((IService)Bridge).Created(Instance); // Set Game Config if (ProjectSettings.GetGameConfig() != null) @@ -254,7 +254,7 @@ public static T CastWorld() where T : class manager.ResolveService(newService, true); } } - ((IMethodSync)Service).ServiceCreated(newService); + ((IMethodSync)Bridge).ServiceCreated(newService); Instance.GameServices.Add(newService); return newService; } @@ -277,7 +277,7 @@ public static bool RemoveService(object author) where T : Service manager.ResolveService(service, false); } } - ((IMethodSync)Service).ServiceRemoved(service); + ((IMethodSync)Bridge).ServiceRemoved(service); ((IService)service).Deleted(author); Instance.GameServices.Remove(service); return true; @@ -340,7 +340,7 @@ public static Coroutine OpenScene(int sceneIndex) { if (SceneManager.GetActiveScene().buildIndex != sceneIndex) { - return Instance.StartCoroutine(Service.GetLoadScneCorotine(sceneIndex)); + return Instance.StartCoroutine(Bridge.GetLoadScneCorotine(sceneIndex)); } else { @@ -367,7 +367,7 @@ public static Coroutine OpenScene(string sceneName) { if (SceneManager.GetActiveScene().name != sceneName) { - return Instance.StartCoroutine(Service.GetLoadScneCorotine(sceneName)); + return Instance.StartCoroutine(Bridge.GetLoadScneCorotine(sceneName)); } else { @@ -385,7 +385,7 @@ public static Coroutine OpenWorld(WorldSceneConfig WorldScene) { if (SceneManager.GetActiveScene().buildIndex != SceneManager.GetSceneByPath(WorldScene.Persistent).buildIndex) { - return Instance.StartCoroutine(Service.GetLoadWorldCorotine(WorldScene)); + return Instance.StartCoroutine(Bridge.GetLoadWorldCorotine(WorldScene)); } else { @@ -399,7 +399,7 @@ public static Coroutine OpenWorld(WorldSceneConfig WorldScene) /// A driving the reload operation. public static Coroutine ReOpenScene() { - return Instance.StartCoroutine(Service.GetLoadScneCorotine(SceneManager.GetActiveScene().name)); ; + return Instance.StartCoroutine(Bridge.GetLoadScneCorotine(SceneManager.GetActiveScene().name)); ; } /// /// Finds a manager of type in the current , @@ -549,7 +549,7 @@ private void Notify_OnWorldInitiate(World NewWorld) private void Notify_OnGameQuit() { Application.quitting -= Notify_OnGameQuit; - ((IMethodSync)Service).UnbindMainWorldAdd(); + ((IMethodSync)Bridge).UnbindMainWorldAdd(); if (GameServices != null) { for (int i = 0; i < GameServices.Count; i++) @@ -558,7 +558,7 @@ private void Notify_OnGameQuit() GameServices.RemoveAt(i); } } - ((IService)Service).Deleted(this); + ((IService)Bridge).Deleted(this); OnGameClosed(); } diff --git a/Runtime/Core/Architecture/GameService.cs b/Runtime/Core/Architecture/GameService.cs index 9f2f93d..896824e 100644 --- a/Runtime/Core/Architecture/GameService.cs +++ b/Runtime/Core/Architecture/GameService.cs @@ -62,17 +62,18 @@ public interface IMethodSync /// - /// Base class for any game services in the framework. + /// Base class for any gamebridge in the framework. /// Provides core functionality for: /// /// World synchronization (main and additive worlds) /// Service lifecycle notifications (created/removed) - /// Scene and world loading with progress reporting + /// world check for single remove new version + /// Load & Unload Scene reporting /// /// Inherits from and implements /// to integrate with the game's internal world and service management system. /// - public abstract class GameService : Service, IMethodSync + public abstract class GameBridge : Service, IMethodSync { /// /// Event invoked when a scene or world starts or finishes loading. diff --git a/Runtime/Core/Architecture/World.cs b/Runtime/Core/Architecture/World.cs index fe81608..285f0fb 100644 --- a/Runtime/Core/Architecture/World.cs +++ b/Runtime/Core/Architecture/World.cs @@ -88,7 +88,7 @@ public abstract class World : MonoBehaviour private void Awake() { //Connect to Game Service - IMethodSync SyncProvider = Game.Service; + IMethodSync SyncProvider = Game.Bridge; if (SyncProvider.IntroduceWorld(this)) { SyncProvider.BindSideWorldAdd(Notify_OnAdditiveWorldInitiate); @@ -133,7 +133,7 @@ private void Awake() /// private void OnDestroy() { - IMethodSync SyncProvider = Game.Service; + IMethodSync SyncProvider = Game.Bridge; SyncProvider.UnbindSideWorldAdd(); SyncProvider.UnbindServicesUpdated(); WorldEnd(); diff --git a/Runtime/Core/ProjectSetting/ProjectSettingAsset.cs b/Runtime/Core/ProjectSetting/ProjectSettingAsset.cs index 3b65e43..582508a 100644 --- a/Runtime/Core/ProjectSetting/ProjectSettingAsset.cs +++ b/Runtime/Core/ProjectSetting/ProjectSettingAsset.cs @@ -49,7 +49,7 @@ public enum FolderStructureType [SerializeField, ReadOnly] private string GameClass = "RealMethod.DefultGame"; [SerializeField, ReadOnly] - private string GameService = "RealMethod.DefaultGameService"; + private string GameBridge = "RealMethod.DefaultGameBridge"; [SerializeField] private GameConfig GameConfig; [SerializeField] @@ -111,22 +111,22 @@ public void SetGameInstanceType(Type type) Debug.LogError("Type is null. Cannot set GameInstanceClass."); } } - public Type GetGameServiceType() + public Type GetGameBridgeType() { foreach (var assembly in AppDomain.CurrentDomain.GetAssemblies()) { - var type = assembly.GetType(GameService); + var type = assembly.GetType(GameBridge); if (type != null) return type; } return null; } - public void SetGameServiceType(Type type) + public void SetGameBridgeType(Type type) { // Store fully qualified name of the type if (type != null) { - GameService = type.AssemblyQualifiedName; + GameBridge = type.AssemblyQualifiedName; } else { diff --git a/Runtime/ReadySet/DefaultsClass.meta b/Runtime/ReadySet/Essentials.meta similarity index 100% rename from Runtime/ReadySet/DefaultsClass.meta rename to Runtime/ReadySet/Essentials.meta diff --git a/Runtime/ReadySet/DefaultsClass/DefaultGame.cs b/Runtime/ReadySet/Essentials/DefaultGame.cs similarity index 100% rename from Runtime/ReadySet/DefaultsClass/DefaultGame.cs rename to Runtime/ReadySet/Essentials/DefaultGame.cs diff --git a/Runtime/ReadySet/DefaultsClass/DefaultGame.cs.meta b/Runtime/ReadySet/Essentials/DefaultGame.cs.meta similarity index 100% rename from Runtime/ReadySet/DefaultsClass/DefaultGame.cs.meta rename to Runtime/ReadySet/Essentials/DefaultGame.cs.meta diff --git a/Runtime/ReadySet/DefaultsClass/DefaultGameService.cs b/Runtime/ReadySet/Essentials/DefaultGameBridge.cs similarity index 62% rename from Runtime/ReadySet/DefaultsClass/DefaultGameService.cs rename to Runtime/ReadySet/Essentials/DefaultGameBridge.cs index fb93638..77a72c4 100644 --- a/Runtime/ReadySet/DefaultsClass/DefaultGameService.cs +++ b/Runtime/ReadySet/Essentials/DefaultGameBridge.cs @@ -2,18 +2,18 @@ namespace RealMethod { - public sealed class DefaultGameService : GameService + public sealed class DefaultGameBridge : GameBridge { protected override void OnStart(object Author) { - Debug.Log("DefaultGameService Started"); + Debug.Log("DefaultBridge Started"); } protected override void OnNewWorld() { } protected override void OnEnd(object Author) { - Debug.Log("DefaultGameService Ended"); + Debug.Log("DefaultBridge Ended"); } } } \ No newline at end of file diff --git a/Runtime/ReadySet/DefaultsClass/DefaultGameService.cs.meta b/Runtime/ReadySet/Essentials/DefaultGameBridge.cs.meta similarity index 100% rename from Runtime/ReadySet/DefaultsClass/DefaultGameService.cs.meta rename to Runtime/ReadySet/Essentials/DefaultGameBridge.cs.meta diff --git a/Runtime/ReadySet/DefaultsClass/DefaultGameConfig.cs b/Runtime/ReadySet/Essentials/DefaultGameConfig.cs similarity index 100% rename from Runtime/ReadySet/DefaultsClass/DefaultGameConfig.cs rename to Runtime/ReadySet/Essentials/DefaultGameConfig.cs diff --git a/Runtime/ReadySet/DefaultsClass/DefaultGameConfig.cs.meta b/Runtime/ReadySet/Essentials/DefaultGameConfig.cs.meta similarity index 100% rename from Runtime/ReadySet/DefaultsClass/DefaultGameConfig.cs.meta rename to Runtime/ReadySet/Essentials/DefaultGameConfig.cs.meta diff --git a/Runtime/ReadySet/DefaultsClass/DefaultWorld.cs b/Runtime/ReadySet/Essentials/DefaultWorld.cs similarity index 100% rename from Runtime/ReadySet/DefaultsClass/DefaultWorld.cs rename to Runtime/ReadySet/Essentials/DefaultWorld.cs diff --git a/Runtime/ReadySet/DefaultsClass/DefaultWorld.cs.meta b/Runtime/ReadySet/Essentials/DefaultWorld.cs.meta similarity index 100% rename from Runtime/ReadySet/DefaultsClass/DefaultWorld.cs.meta rename to Runtime/ReadySet/Essentials/DefaultWorld.cs.meta diff --git a/Runtime/ReadySet/Managers/ScreenManager.cs b/Runtime/ReadySet/Managers/ScreenManager.cs index daf5843..3549b48 100644 --- a/Runtime/ReadySet/Managers/ScreenManager.cs +++ b/Runtime/ReadySet/Managers/ScreenManager.cs @@ -23,8 +23,8 @@ public sealed class ScreenManager : UIManager // UIManager Methods protected override void InitiateManager(bool alwaysLoaded) { - Game.Service.OnSceneLoading += (value) => OnLoadScne?.Invoke(value); - Game.Service.OnSceneLoadingProcess += (value) => OnLoading?.Invoke(value); + Game.Bridge.OnSceneLoading += (value) => OnLoadScne?.Invoke(value); + Game.Bridge.OnSceneLoadingProcess += (value) => OnLoading?.Invoke(value); if (Game.TryFindService(out Spawn SpawnServ)) { SpawnServ.BringManager(this); From cc10166fedd0014a76b6c4fc0cc643bd793e1658 Mon Sep 17 00:00:00 2001 From: Alijimpa Date: Thu, 5 Mar 2026 15:45:28 +0330 Subject: [PATCH 018/204] Cleanup all Comment for GameService rename to GameBridge --- .../Sections/InitializerSetting_Section.cs | 2 +- Reservoir/ScriptTemplates/GameTemplate.txt | 2 +- Runtime/Core/Architecture/Game.cs | 12 ++++++------ .../Architecture/{GameService.cs => GameBridge.cs} | 0 .../{GameService.cs.meta => GameBridge.cs.meta} | 0 Runtime/Core/Architecture/World.cs | 2 +- 6 files changed, 9 insertions(+), 9 deletions(-) rename Runtime/Core/Architecture/{GameService.cs => GameBridge.cs} (100%) rename Runtime/Core/Architecture/{GameService.cs.meta => GameBridge.cs.meta} (100%) diff --git a/Editor/Core/ProjectSetting/Sections/InitializerSetting_Section.cs b/Editor/Core/ProjectSetting/Sections/InitializerSetting_Section.cs index 2d18cb9..5950850 100644 --- a/Editor/Core/ProjectSetting/Sections/InitializerSetting_Section.cs +++ b/Editor/Core/ProjectSetting/Sections/InitializerSetting_Section.cs @@ -29,7 +29,7 @@ protected override void UpdateRender() // GameInstanceClass gameClass.Draw(projectSettings, "GameClass", "Game Class"); - // GameServiceClass + // GameBridgeClass gameBridge.Draw(projectSettings, "GameBridge", "Game Bridge"); // GameSettingAsset diff --git a/Reservoir/ScriptTemplates/GameTemplate.txt b/Reservoir/ScriptTemplates/GameTemplate.txt index 9227586..8121ade 100644 --- a/Reservoir/ScriptTemplates/GameTemplate.txt +++ b/Reservoir/ScriptTemplates/GameTemplate.txt @@ -7,7 +7,7 @@ public class #SCRIPTNAME# : Game protected override void OnGameInitialized() { // Called right after Unity finishes loading the engine before any scene or subsystem is loaded. - // You can insure when Called that GameService , GameConfig and all Managers Initilized. + // You can insure when Called that GameBridge , GameConfig and all Managers Initilized. } protected override void OnGameStarted() { diff --git a/Runtime/Core/Architecture/Game.cs b/Runtime/Core/Architecture/Game.cs index d136bdb..897356a 100644 --- a/Runtime/Core/Architecture/Game.cs +++ b/Runtime/Core/Architecture/Game.cs @@ -26,7 +26,7 @@ public abstract class Game : MonoBehaviour /// public static World World { get; private set; } /// - /// The core implementation used for scene/world loading and service events. + /// The core implementation used for scene/world loading and service events. /// public static GameBridge Bridge { get; private set; } /// @@ -104,11 +104,11 @@ private static void InitializeGame() } Instance.OnProjectSeettingLoaded(ref ProjectSettings); - // Create Game Service + // Create GameBridge Type targetService = ProjectSettings.GetGameBridgeType(); if (targetService == null) { - Debug.LogWarning($"GetGameServiceClass that was empty. DefaultGameService Created"); + Debug.LogWarning($"GetGameBridgeType that was empty. DefaultGameBridge Created"); Bridge = new DefaultGameBridge(); } if (typeof(Service).IsAssignableFrom(targetService)) @@ -119,13 +119,13 @@ private static void InitializeGame() } catch (Exception ex) { - Debug.LogError($"Failed to instantiate {targetService}: {ex.Message}. DefaultGameService Created"); + Debug.LogError($"Failed to instantiate {targetService}: {ex.Message}. DefaultGameBridge Created"); Bridge = new DefaultGameBridge(); } } else { - Debug.LogWarning($"Type {targetService} is not assignable to Service. DefaultGameService Created"); + Debug.LogWarning($"Type {targetService} is not assignable to Service. DefaultGameBridge Created"); Bridge = new DefaultGameBridge(); } Instance.GameServices = new List(3); @@ -518,7 +518,7 @@ public IGameManager GetManager(string ObjectName) /// - /// Called after GameInstance Created befor GameService , GameConfig & Managers Initilized + /// Called after GameInstance Created befor GameBridge , GameConfig & Managers Initilized /// if you use custom PtojectSetttingAsset class you can use instances after loaded in game /// this refrence unloaded befor OnGameInitialized Called. /// diff --git a/Runtime/Core/Architecture/GameService.cs b/Runtime/Core/Architecture/GameBridge.cs similarity index 100% rename from Runtime/Core/Architecture/GameService.cs rename to Runtime/Core/Architecture/GameBridge.cs diff --git a/Runtime/Core/Architecture/GameService.cs.meta b/Runtime/Core/Architecture/GameBridge.cs.meta similarity index 100% rename from Runtime/Core/Architecture/GameService.cs.meta rename to Runtime/Core/Architecture/GameBridge.cs.meta diff --git a/Runtime/Core/Architecture/World.cs b/Runtime/Core/Architecture/World.cs index 285f0fb..9e5394c 100644 --- a/Runtime/Core/Architecture/World.cs +++ b/Runtime/Core/Architecture/World.cs @@ -87,7 +87,7 @@ public abstract class World : MonoBehaviour /// private void Awake() { - //Connect to Game Service + //Connect to Game With Bridge IMethodSync SyncProvider = Game.Bridge; if (SyncProvider.IntroduceWorld(this)) { From 63c07764a260f006e93a05483b9c0308ec2f3fc4 Mon Sep 17 00:00:00 2001 From: Alijimpa Date: Fri, 6 Mar 2026 12:13:17 +0330 Subject: [PATCH 019/204] Refine Service --- Documentation/Information/ClassViewer.txt | 2 +- Editor/Core/Architecture/Game_Editor.cs | 2 +- Runtime/Core/Architecture/Game.cs | 6 +- Runtime/Core/Architecture/GameBridge.cs | 64 ++++++++----------- Runtime/Core/Architecture/ServiceContracts.cs | 8 +-- Runtime/Pattern/Services/InputService.cs | 2 +- Runtime/Pattern/Services/RuleService.cs | 2 +- Runtime/Pattern/Services/StateService.cs | 2 +- .../ReadySet/Essentials/DefaultGameBridge.cs | 2 +- Runtime/ReadySet/Services/NetworkService.cs | 2 +- Runtime/ReadySet/Services/PrintService.cs | 2 +- Runtime/ReadySet/Services/SpawanService.cs | 2 +- Runtime/ReadySet/Services/TimeService.cs | 2 +- 13 files changed, 45 insertions(+), 53 deletions(-) diff --git a/Documentation/Information/ClassViewer.txt b/Documentation/Information/ClassViewer.txt index 8d4a0d4..4d82ba3 100644 --- a/Documentation/Information/ClassViewer.txt +++ b/Documentation/Information/ClassViewer.txt @@ -4,7 +4,7 @@ Runtime Game -> This is a red word and bold green. Go to TEST https://github.com/AliJimpa/RealMethod/wiki/Assets. World -> just test text ColortTEst Without link GameConfig - GameService + GameBridge ManagerContracts ServiceContracts WorldSceneConfig diff --git a/Editor/Core/Architecture/Game_Editor.cs b/Editor/Core/Architecture/Game_Editor.cs index 1b680ac..221d5ff 100644 --- a/Editor/Core/Architecture/Game_Editor.cs +++ b/Editor/Core/Architecture/Game_Editor.cs @@ -33,7 +33,7 @@ private string GetWorld() } private string GetSetvice() { - return Game.Bridge != null ? Game.Bridge.GetType().Name : "GameService Not Valid"; + return Game.Bridge != null ? Game.Bridge.GetType().Name : "GameBridge Not Valid"; } private string GetConfig() { diff --git a/Runtime/Core/Architecture/Game.cs b/Runtime/Core/Architecture/Game.cs index 897356a..77eacbb 100644 --- a/Runtime/Core/Architecture/Game.cs +++ b/Runtime/Core/Architecture/Game.cs @@ -26,7 +26,7 @@ public abstract class Game : MonoBehaviour ///
public static World World { get; private set; } /// - /// The core implementation used for scene/world loading and service events. + /// The core implementation used for scene/world loading and basic events. /// public static GameBridge Bridge { get; private set; } /// @@ -536,11 +536,11 @@ protected virtual void OnProjectSeettingLoaded(ref ProjectSettingAsset setting) /// The newly initiated world instance. private void Notify_OnWorldInitiate(World NewWorld) { - World = NewWorld; foreach (var service in GameServices) { - ((IService)service).WorldUpdated(); + ((IService)service).ChangeWorld(NewWorld); } + World = NewWorld; OnWorldChanged(World); } /// diff --git a/Runtime/Core/Architecture/GameBridge.cs b/Runtime/Core/Architecture/GameBridge.cs index 896824e..e3de171 100644 --- a/Runtime/Core/Architecture/GameBridge.cs +++ b/Runtime/Core/Architecture/GameBridge.cs @@ -100,16 +100,7 @@ public abstract class GameBridge : Service, IMethodSync // Implement IMethodSync Interface bool IMethodSync.IntroduceWorld(World world) { - if (Game.World == null) - { - MainWorldEvent?.Invoke(world); - return true; - } - else - { - SideWorldEvent?.Invoke(world); - return false; - } + return RequestForNewWorld(world); } void IMethodSync.BindMainWorldAdd(Action func) { @@ -160,6 +151,28 @@ void IMethodSync.UnbindServicesUpdated() } + /// + /// Request for this NewWorld to set for Main World in Scene + /// + /// The New WorldClass Refrence in Scene + /// + /// If this request is valid return true that mean this world set as main world. + /// If this request false means this world import from scen that is additive and should deactive. + /// /// Starts loading a scene by name using a coroutine. /// @@ -172,7 +185,7 @@ public virtual IEnumerator GetLoadScneCorotine(string sceneName) { if (IsLoading == true) { - Debug.LogWarning($"Can't load Scene:{sceneName} The Service is in Loading"); + Debug.LogWarning($"Can't load Scene:{sceneName} The Bridge is in loading target scene"); return null; } return LoadSceneAsync(sceneName); @@ -189,7 +202,7 @@ public virtual IEnumerator GetLoadScneCorotine(int sceneIndex) { if (IsLoading == true) { - Debug.LogWarning($"Can't load Index:{sceneIndex} The Service is in Loading"); + Debug.LogWarning($"Can't load Index:{sceneIndex} The Bridge is in loading target scene"); return null; } return LoadSceneAsync(string.Empty, sceneIndex); @@ -206,7 +219,7 @@ public virtual IEnumerator GetLoadWorldCorotine(WorldSceneConfig WorldScene) { if (IsLoading == true) { - Debug.LogWarning($"Can't load World:{WorldScene} The Service is in Loading"); + Debug.LogWarning($"Can't load World:{WorldScene} The Bridge is in loading target scene"); return null; } return LoadWorldAsync(WorldScene); @@ -286,7 +299,7 @@ private IEnumerator LoadWorldAsync(WorldSceneConfig WS) } while (!Load_opertation.isDone) { - OnSceneLoadingProcess?.Invoke(Clamped(Load_opertation.progress, 0, 1, 0, 1 / WS.Count + 1)); + OnSceneLoadingProcess?.Invoke(RM_Math.Map.RemapClamped(Load_opertation.progress, 0, 1, 0, 1 / WS.Count + 1)); OnSceneLoading?.Invoke(false); IsLoading = false; yield return null; @@ -305,7 +318,7 @@ private IEnumerator LoadWorldAsync(WorldSceneConfig WS) } while (!Additive_Load_opertation.isDone) { - OnSceneLoadingProcess?.Invoke(Clamped(Load_opertation.progress, 0, 1, 0, 1 / WS.Count + 1 - (i + 1))); + OnSceneLoadingProcess?.Invoke(RM_Math.Map.RemapClamped(Load_opertation.progress, 0, 1, 0, 1 / WS.Count + 1 - (i + 1))); yield return null; } } @@ -323,27 +336,6 @@ private IEnumerator LoadWorldAsync(WorldSceneConfig WS) } - // Private Functions - private float Clamped(float value, float inMin, float inMax, float outMin, float outMax) - { - // Prevent divide by zero - if (Mathf.Approximately(inMax, inMin)) - { - Debug.LogWarning("Input range is zero. Returning outMin."); - return outMin; - } - - // Normalize the input value to 0–1 within the input range - float t = (value - inMin) / (inMax - inMin); - - // Scale and offset to target range - float mappedValue = t * (outMax - outMin) + outMin; - - // Clamp result to the output range - return Mathf.Clamp(mappedValue, Mathf.Min(outMin, outMax), Mathf.Max(outMin, outMax)); - } - - #if UNITY_EDITOR [InitializeOnEnterPlayMode] // Runs when entering Play Mode in Editor diff --git a/Runtime/Core/Architecture/ServiceContracts.cs b/Runtime/Core/Architecture/ServiceContracts.cs index ed1a575..ba313dc 100644 --- a/Runtime/Core/Architecture/ServiceContracts.cs +++ b/Runtime/Core/Architecture/ServiceContracts.cs @@ -14,7 +14,7 @@ public interface IService /// /// Called when the world or environment updates. /// - void WorldUpdated(); + void ChangeWorld(World NewWorld); /// /// Called when the service is deleted or destroyed. /// @@ -33,9 +33,9 @@ void IService.Created(object author) { OnStart(author); } - void IService.WorldUpdated() + void IService.ChangeWorld(World NewWorld) { - OnNewWorld(); + OnWorldChanged(Game.World, NewWorld); } void IService.Deleted(object author) { @@ -52,7 +52,7 @@ void IService.Deleted(object author) /// Called when a new world or environment is initialized. /// Must be implemented by derived classes. /// - protected abstract void OnNewWorld(); + protected abstract void OnWorldChanged(World Previous, World New); /// /// Called when the service ends or is deleted. /// Must be implemented by derived classes. diff --git a/Runtime/Pattern/Services/InputService.cs b/Runtime/Pattern/Services/InputService.cs index 65f80e9..d176352 100644 --- a/Runtime/Pattern/Services/InputService.cs +++ b/Runtime/Pattern/Services/InputService.cs @@ -14,7 +14,7 @@ protected sealed override void OnStart(object Author) ReplaceInputAsset(newAsset); } } - protected sealed override void OnNewWorld() + protected sealed override void OnWorldChanged(World Previous , World New) { if (TryFindInputAsset(out InputActionAsset newAsset)) { diff --git a/Runtime/Pattern/Services/RuleService.cs b/Runtime/Pattern/Services/RuleService.cs index 45d60d4..c27a2aa 100644 --- a/Runtime/Pattern/Services/RuleService.cs +++ b/Runtime/Pattern/Services/RuleService.cs @@ -13,7 +13,7 @@ public RuleService() Rules = new Hictionary>(5); } - protected override void OnNewWorld() + protected override void OnWorldChanged(World Previous , World New) { foreach (var item in Rules.GetValues()) { diff --git a/Runtime/Pattern/Services/StateService.cs b/Runtime/Pattern/Services/StateService.cs index 0b46d99..9d25e2c 100644 --- a/Runtime/Pattern/Services/StateService.cs +++ b/Runtime/Pattern/Services/StateService.cs @@ -16,7 +16,7 @@ public StateService(byte firstState) } // StateService Methods - protected sealed override void OnNewWorld() + protected sealed override void OnWorldChanged(World Previous , World New) { if (CanResetforNewWorld(Game.World)) { diff --git a/Runtime/ReadySet/Essentials/DefaultGameBridge.cs b/Runtime/ReadySet/Essentials/DefaultGameBridge.cs index 77a72c4..0b823f4 100644 --- a/Runtime/ReadySet/Essentials/DefaultGameBridge.cs +++ b/Runtime/ReadySet/Essentials/DefaultGameBridge.cs @@ -8,7 +8,7 @@ protected override void OnStart(object Author) { Debug.Log("DefaultBridge Started"); } - protected override void OnNewWorld() + protected override void OnWorldChanged(World Previous , World New) { } protected override void OnEnd(object Author) diff --git a/Runtime/ReadySet/Services/NetworkService.cs b/Runtime/ReadySet/Services/NetworkService.cs index 8263302..c4ae4f3 100644 --- a/Runtime/ReadySet/Services/NetworkService.cs +++ b/Runtime/ReadySet/Services/NetworkService.cs @@ -20,7 +20,7 @@ protected override void OnStart(object Author) { throw new NotImplementedException(); } - protected override void OnNewWorld() + protected override void OnWorldChanged(World Previous , World New) { throw new NotImplementedException(); } diff --git a/Runtime/ReadySet/Services/PrintService.cs b/Runtime/ReadySet/Services/PrintService.cs index 4ad7ad4..ce0ca5c 100644 --- a/Runtime/ReadySet/Services/PrintService.cs +++ b/Runtime/ReadySet/Services/PrintService.cs @@ -38,7 +38,7 @@ protected override void OnStart(object Author) manager.InitiateManager(true); } } - protected override void OnNewWorld() + protected override void OnWorldChanged(World Previous , World New) { Printer.Clear(); } diff --git a/Runtime/ReadySet/Services/SpawanService.cs b/Runtime/ReadySet/Services/SpawanService.cs index 7139124..2aea19b 100644 --- a/Runtime/ReadySet/Services/SpawanService.cs +++ b/Runtime/ReadySet/Services/SpawanService.cs @@ -41,7 +41,7 @@ protected override void OnStart(object Author) { GameDespawn = new Despawn(); } - protected override void OnNewWorld() + protected override void OnWorldChanged(World Previous , World New) { } protected override void OnEnd(object Author) diff --git a/Runtime/ReadySet/Services/TimeService.cs b/Runtime/ReadySet/Services/TimeService.cs index c98316b..465f504 100644 --- a/Runtime/ReadySet/Services/TimeService.cs +++ b/Runtime/ReadySet/Services/TimeService.cs @@ -15,7 +15,7 @@ protected override void OnStart(object Author) worldTime = Time.time; RecordTime = new Hictionary(10); } - protected override void OnNewWorld() + protected override void OnWorldChanged(World Previous , World New) { worldTime = Time.time; } From b362ea7ed22b39e486451a7781db7b7d7748b5da Mon Sep 17 00:00:00 2001 From: Alijimpa Date: Fri, 6 Mar 2026 13:29:27 +0330 Subject: [PATCH 020/204] Implement New Stage Event for Game Class --- Reservoir/ScriptTemplates/GameTemplate.txt | 9 +++++++-- Runtime/Core/Architecture/Game.cs | 13 ++++++++----- Runtime/ReadySet/Essentials/DefaultGame.cs | 9 +++++++-- 3 files changed, 22 insertions(+), 9 deletions(-) diff --git a/Reservoir/ScriptTemplates/GameTemplate.txt b/Reservoir/ScriptTemplates/GameTemplate.txt index 8121ade..52ee0d9 100644 --- a/Reservoir/ScriptTemplates/GameTemplate.txt +++ b/Reservoir/ScriptTemplates/GameTemplate.txt @@ -4,12 +4,17 @@ public class #SCRIPTNAME# : Game { // Game Methods + protected override void OnGameOpen() + { + // Called when game run in platform befor any scene loaded or any splash screen + // In this stage your game is fully empty. + } protected override void OnGameInitialized() { // Called right after Unity finishes loading the engine before any scene or subsystem is loaded. // You can insure when Called that GameBridge , GameConfig and all Managers Initilized. } - protected override void OnGameStarted() + protected override void OnGameStart() { // Called after Unity finishes initializing the engine, but before the first scene is loaded. // It’s guaranteed to execute before any Awake() or Start() in your scene objects. @@ -18,7 +23,7 @@ public class #SCRIPTNAME# : Game { // Called when each World Initialized // You can insure the Game.world refrence is valid - // Note: if you use world in scen and load scene as additive not OpenScen that world didnt connect to Game and removed by Main World class + // Note: if you use world in scene and load scene as additive not OpenScen that world didnt connect to Game and removed by Main World class } protected override void OnGameClosed() { diff --git a/Runtime/Core/Architecture/Game.cs b/Runtime/Core/Architecture/Game.cs index 77eacbb..7333956 100644 --- a/Runtime/Core/Architecture/Game.cs +++ b/Runtime/Core/Architecture/Game.cs @@ -85,7 +85,7 @@ private static void InitializeGame() return; } - // Initiate Game Class + // Initiate GameClass var emptyObject = new GameObject("RealGame"); Type TargetClass = ProjectSettings.GetGameInstanceType(); if (TargetClass == null) @@ -104,6 +104,8 @@ private static void InitializeGame() } Instance.OnProjectSeettingLoaded(ref ProjectSettings); + Instance.OnGameOpen(); + // Create GameBridge Type targetService = ProjectSettings.GetGameBridgeType(); if (targetService == null) @@ -132,7 +134,7 @@ private static void InitializeGame() ((IMethodSync)Bridge).BindMainWorldAdd(Instance.Notify_OnWorldInitiate); ((IService)Bridge).Created(Instance); - // Set Game Config + // Set GameConfig if (ProjectSettings.GetGameConfig() != null) { Config = ProjectSettings.GetGameConfig(); @@ -180,14 +182,14 @@ private static void RuntimeBeforeSceneLoad() } } /// - /// Called after a scene has finished loading. Invokes on the active instance. + /// Called after a scene has finished loading. Invokes on the active instance. /// [RuntimeInitializeOnLoadMethod(RuntimeInitializeLoadType.AfterSceneLoad)] private static void RuntimeAfterSceneLoad() { if (Instance != null) { - Instance.OnGameStarted(); + Instance.OnGameStart(); } } @@ -563,6 +565,7 @@ private void Notify_OnGameQuit() } + protected abstract void OnGameOpen(); /// /// Called once when the game framework has finished initial initialization. /// Implement this to perform game-specific initialization logic. @@ -572,7 +575,7 @@ private void Notify_OnGameQuit() /// Called after the first scene has been loaded and the game has started. /// Implement this to perform logic that should run once the first scene is active. /// - protected abstract void OnGameStarted(); + protected abstract void OnGameStart(); /// /// Called when the current reference changes. /// Implement to react to world switches. diff --git a/Runtime/ReadySet/Essentials/DefaultGame.cs b/Runtime/ReadySet/Essentials/DefaultGame.cs index fa1f575..59aea0d 100644 --- a/Runtime/ReadySet/Essentials/DefaultGame.cs +++ b/Runtime/ReadySet/Essentials/DefaultGame.cs @@ -6,22 +6,27 @@ namespace RealMethod [AddComponentMenu("RealMethod/Essential/DefultGame")] public sealed class DefultGame : Game { + protected override void OnGameOpen() + { + Debug.Log("DefultGame Opened"); + } protected override void OnGameInitialized() { Debug.Log("DefultGame Initialized"); } - protected override void OnGameStarted() + protected override void OnGameStart() { Debug.Log("DefultGame Started"); } protected override void OnWorldChanged(World NewWorld) { - Debug.Log($"DefultGame.World Change to {NewWorld}"); + Debug.Log($"New world assign: {NewWorld}"); } protected override void OnGameClosed() { Debug.Log("DefultGame Closed"); } + } } From 78e570a55813a41fc17bbbd5258250076e2b1c62 Mon Sep 17 00:00:00 2001 From: Alijimpa Date: Sun, 8 Mar 2026 13:23:14 +0330 Subject: [PATCH 021/204] Refine Game and Game Bridge --- .../ScriptTemplates/GameBridgeTemplate.txt | 2 +- Reservoir/ScriptTemplates/GameTemplate.txt | 11 +- Runtime/Core/Architecture/Game.cs | 172 ++++++++++- Runtime/Core/Architecture/GameBridge.cs | 292 +++++++++++++----- .../{ManagerContracts.cs => GameManager.cs} | 0 ...rContracts.cs.meta => GameManager.cs.meta} | 0 .../{ServiceContracts.cs => Service.cs} | 4 +- ...rviceContracts.cs.meta => Service.cs.meta} | 0 Runtime/Core/Architecture/World.cs | 29 +- Runtime/Library/Extension/GameObject.cs | 18 ++ Runtime/Pattern/Services/InputService.cs | 2 +- Runtime/Pattern/Services/RuleService.cs | 2 +- Runtime/Pattern/Services/StateService.cs | 2 +- .../ReadySet/Essentials/DefaultGameBridge.cs | 8 +- Runtime/ReadySet/Managers/ScreenManager.cs | 4 +- Runtime/ReadySet/Services/NetworkService.cs | 2 +- Runtime/ReadySet/Services/PrintService.cs | 2 +- Runtime/ReadySet/Services/SpawanService.cs | 2 +- Runtime/ReadySet/Services/TimeService.cs | 2 +- 19 files changed, 419 insertions(+), 135 deletions(-) rename Runtime/Core/Architecture/{ManagerContracts.cs => GameManager.cs} (100%) rename Runtime/Core/Architecture/{ManagerContracts.cs.meta => GameManager.cs.meta} (100%) rename Runtime/Core/Architecture/{ServiceContracts.cs => Service.cs} (94%) rename Runtime/Core/Architecture/{ServiceContracts.cs.meta => Service.cs.meta} (100%) diff --git a/Reservoir/ScriptTemplates/GameBridgeTemplate.txt b/Reservoir/ScriptTemplates/GameBridgeTemplate.txt index fcd0e3b..c262892 100644 --- a/Reservoir/ScriptTemplates/GameBridgeTemplate.txt +++ b/Reservoir/ScriptTemplates/GameBridgeTemplate.txt @@ -4,7 +4,7 @@ public class #SCRIPTNAME# : GameBridge { // Base Service Methods protected override void OnStart(object Author) {} - protected override void OnNewWorld() { } + protected override void OnWorldChanging() { } protected override void OnEnd(object Author) { } } diff --git a/Reservoir/ScriptTemplates/GameTemplate.txt b/Reservoir/ScriptTemplates/GameTemplate.txt index 52ee0d9..69ff4ff 100644 --- a/Reservoir/ScriptTemplates/GameTemplate.txt +++ b/Reservoir/ScriptTemplates/GameTemplate.txt @@ -6,16 +6,19 @@ public class #SCRIPTNAME# : Game // Game Methods protected override void OnGameOpen() { - // Called when game run in platform befor any scene loaded or any splash screen - // In this stage your game is fully empty. + // Invoked when starting up the runtime. Called before the first scene is loaded. + // Called when game run in platform befor any scene loaded or even splash screen + // In this stage your game component just created. } protected override void OnGameInitialized() { + // Invoked when the first scene's objects are loaded into memory but before Awake has been called. // Called right after Unity finishes loading the engine before any scene or subsystem is loaded. - // You can insure when Called that GameBridge , GameConfig and all Managers Initilized. + // You can insure when called that GameBridge , GameConfig and all Managers in GameScope Initilized. } protected override void OnGameStart() { + // Invoked when the first scene's objects are loaded into memory but before Awake has been called. // Called after Unity finishes initializing the engine, but before the first scene is loaded. // It’s guaranteed to execute before any Awake() or Start() in your scene objects. } @@ -23,7 +26,7 @@ public class #SCRIPTNAME# : Game { // Called when each World Initialized // You can insure the Game.world refrence is valid - // Note: if you use world in scene and load scene as additive not OpenScen that world didnt connect to Game and removed by Main World class + // Note: if you use world in scene and load scene as additive not OpenScen() that world didnt connect to Game and removed by Main World class (more= GameBridge) } protected override void OnGameClosed() { diff --git a/Runtime/Core/Architecture/Game.cs b/Runtime/Core/Architecture/Game.cs index 7333956..ab0b325 100644 --- a/Runtime/Core/Architecture/Game.cs +++ b/Runtime/Core/Architecture/Game.cs @@ -10,6 +10,27 @@ namespace RealMethod { + /// + /// Represents the possible outcomes of a Game process. + /// + public enum GameProcess + { + /// + /// The process finished successfully. + /// + Success, + /// + /// The process failed. + /// + Failure, + /// + /// The process was cancelled before completion. + /// + Cancelled + } + + + /// /// Core game singleton that manages the active , registered s, /// configuration and high-level game lifecycle (initialization, start, and shutdown). @@ -50,10 +71,64 @@ public static GameObject Player } } /// - /// Indicates whether the game is currently paused. - /// Returns true when Time.timeScale is set to 0; otherwise, false. + /// Indicates whether a scene or world load operation is currently in progress. + /// + public static bool IsPaused + { + get + { + if (Instance != null) + { + return Instance.IsGamePaused(); + } + else + { + Debug.LogWarning("GameInstance did not called !"); + return false; + } + } + } + /// + /// Indicates whether the game is in loading stage + /// Return true when game in loading section for new scene + /// + public static bool IsLoading => Instance.IsGameLoading(); + /// + /// Event invoked when a scene or world starts or finishes loading. + /// The boolean parameter is true when loading starts and false when loading ends. + /// + public static event Action OnSceneLoading + { + add { ((ILoadScneBridge)Bridge).OnSceneLoading += value; } + remove { ((ILoadScneBridge)Bridge).OnSceneLoading -= value; } + } + /// + /// Event invoked during scene or world loading to report progress. + /// The float parameter represents the loading progress from 0 (start) to 1 (complete). + /// + public static event Action OnSceneLoadingProcess + { + add { ((ILoadScneBridge)Bridge).OnSceneLoadingProcess += value; } + remove { ((ILoadScneBridge)Bridge).OnSceneLoadingProcess -= value; } + } + /// + /// This action called every time your game ready to play after load Scene & setup RealMethod + /// you can enshure that your game and world do anything and player can ready to play game + /// when you change scene after world initiate this evet invoke again. + /// + public static event Action OnReady + { + add { ((IRelationBridge)Bridge).OnGameReady += value; } + remove { ((IRelationBridge)Bridge).OnGameReady -= value; } + } + /// + /// Invoked when the process finishes. + /// Process in your game take define with yourelf. + /// (for example: show win screen, game over UI, load next level, etc). /// - public static bool IsPaused => Time.timeScale == 0; + public static event Action OnCompleted; + + /// @@ -72,6 +147,7 @@ public static GameObject Player /// Initializes the game singleton and core systems on subsystem registration. /// This sets up the , game , /// configuration, prefabs and managers and registers quit callbacks. + /// Invoked when starting up the runtime. Called before the first scene is loaded. /// [RuntimeInitializeOnLoadMethod(RuntimeInitializeLoadType.SubsystemRegistration)] private static void InitializeGame() @@ -131,7 +207,7 @@ private static void InitializeGame() Bridge = new DefaultGameBridge(); } Instance.GameServices = new List(3); - ((IMethodSync)Bridge).BindMainWorldAdd(Instance.Notify_OnWorldInitiate); + ((IRelationBridge)Bridge).BindWorldCreated(Instance.Notify_OnWorldInitiate); ((IService)Bridge).Created(Instance); // Set GameConfig @@ -172,6 +248,7 @@ private static void InitializeGame() } /// /// Called before any scene is loaded. Invokes on the active instance. + /// Invoked when the first scene's objects are loaded into memory but before Awake has been called. /// [RuntimeInitializeOnLoadMethod(RuntimeInitializeLoadType.BeforeSceneLoad)] private static void RuntimeBeforeSceneLoad() @@ -183,6 +260,8 @@ private static void RuntimeBeforeSceneLoad() } /// /// Called after a scene has finished loading. Invokes on the active instance. + /// Right after all Awake() and OnEnable() calls but befor Start() + /// Invoked when the first scene's objects are loaded into memory but before Awake has been called. /// [RuntimeInitializeOnLoadMethod(RuntimeInitializeLoadType.AfterSceneLoad)] private static void RuntimeAfterSceneLoad() @@ -194,6 +273,13 @@ private static void RuntimeAfterSceneLoad() } + /// + /// Attempts to invoke + /// + public static void Complete(GameProcess result) + { + OnCompleted.Invoke(result); + } /// /// Attempts to cast the global to the specified type . /// Logs an error and returns null if the cast fails. @@ -256,7 +342,7 @@ public static T CastWorld() where T : class manager.ResolveService(newService, true); } } - ((IMethodSync)Bridge).ServiceCreated(newService); + ((IRelationBridge)Bridge).ServiceCreated(newService); Instance.GameServices.Add(newService); return newService; } @@ -279,7 +365,7 @@ public static bool RemoveService(object author) where T : Service manager.ResolveService(service, false); } } - ((IMethodSync)Bridge).ServiceRemoved(service); + ((IRelationBridge)Bridge).ServiceRemoved(service); ((IService)service).Deleted(author); Instance.GameServices.Remove(service); return true; @@ -333,7 +419,7 @@ public string[] GetAllServiceNames() return GameServices.Select(service => service.GetType().Name).ToArray(); } /// - /// Requests a scene load by build index via the configured . + /// Requests a scene load by build index . /// If the requested scene is already active, a warning is logged and null is returned. /// /// Build index of the scene to open. @@ -360,7 +446,7 @@ public static Coroutine OpenScene(SceneReference scene) return OpenScene(scene.ScneName); } /// - /// Requests a scene load by name via the configured . + /// Requests a scene load by name. /// If the requested scene is already active, a warning is logged and null is returned. /// /// Name of the scene to open. @@ -378,6 +464,49 @@ public static Coroutine OpenScene(string sceneName) } } /// + /// Requests a Add scene by build index via the configured . + /// If the requested scene is already active, a warning is logged and null is returned. + /// + /// Build index of the scene to open. + /// callback event when scene complitly added + public static void AddScene(int sceneIndex, Action callback) + { + if (SceneManager.GetActiveScene().buildIndex != sceneIndex) + { + Instance.StartCoroutine(Bridge.GetAddScneCorotine(sceneIndex, callback)); + } + else + { + Debug.LogWarning("The scene is already loaded."); + } + } + /// + /// Requests a scene load using a . + /// + /// Reference describing the scene to load. + /// callback event when scene complitly added + public static void AddScene(SceneReference scene, Action callback) + { + AddScene(scene.ScneName, callback); + } + /// + /// Requests a scene load by name. + /// If the requested scene is already active, a warning is logged and null is returned. + /// + /// Name of the scene to open. + /// callback event when scene complitly added + public static void AddScene(string sceneName, Action callback) + { + if (SceneManager.GetActiveScene().name != sceneName) + { + Instance.StartCoroutine(Bridge.GetAddScneCorotine(sceneName, callback)); + } + else + { + Debug.LogWarning("The scene is already loaded."); + } + } + /// /// Loads a multi-scene world configuration using the provided . /// If the persistent scene for the world is already loaded, a warning is logged and null is returned. /// @@ -529,6 +658,22 @@ protected virtual void OnProjectSeettingLoaded(ref ProjectSettingAsset setting) { // Nothing todo } + /// + /// Check GamePause with time or any custom override. + /// + /// true if the timescale is 0; otherwise false. + protected virtual bool IsGamePaused() + { + return Time.timeScale == 0; + } + /// + /// Check GameLoading with Bridge to check loading stage. + /// + /// true if any scne in loading stage; otherwise false. + protected virtual bool IsGameLoading() + { + return ((ILoadScneBridge)Bridge).IsLoading; + } /// @@ -551,7 +696,7 @@ private void Notify_OnWorldInitiate(World NewWorld) private void Notify_OnGameQuit() { Application.quitting -= Notify_OnGameQuit; - ((IMethodSync)Bridge).UnbindMainWorldAdd(); + ((IRelationBridge)Bridge).UnbindWorldCreated(); if (GameServices != null) { for (int i = 0; i < GameServices.Count; i++) @@ -565,15 +710,24 @@ private void Notify_OnGameQuit() } + + /// + /// Called once when game opend in currect platform + /// Implement anything you want initiate befor realmethod initiate + /// Invoked when starting up the runtime. Called before the first scene is loaded. + /// protected abstract void OnGameOpen(); /// /// Called once when the game framework has finished initial initialization. /// Implement this to perform game-specific initialization logic. + /// Invoked when the first scene's objects are loaded into memory but before Awake has been called. /// protected abstract void OnGameInitialized(); /// /// Called after the first scene has been loaded and the game has started. /// Implement this to perform logic that should run once the first scene is active. + /// Right after all Awake() and OnEnable() calls but befor Start() + /// Invoked when the first scene's objects are loaded into memory but before Awake has been called. /// protected abstract void OnGameStart(); /// diff --git a/Runtime/Core/Architecture/GameBridge.cs b/Runtime/Core/Architecture/GameBridge.cs index e3de171..1b986a4 100644 --- a/Runtime/Core/Architecture/GameBridge.cs +++ b/Runtime/Core/Architecture/GameBridge.cs @@ -8,11 +8,12 @@ namespace RealMethod { + /// /// Defines synchronization hooks used internally to coordinate - /// worlds and services during runtime initialization. + /// worlds and Game during runtime initialization. /// - public interface IMethodSync + public interface IRelationBridge { /// /// Introduces a newly created world to the system. @@ -26,19 +27,11 @@ public interface IMethodSync /// /// Binds a callback invoked when the main world is added. /// - void BindMainWorldAdd(Action func); + void BindWorldCreated(Action func); /// /// Unbinds the main world added callback. /// - void UnbindMainWorldAdd(); - /// - /// Binds a callback invoked when a side (additive) world is added. - /// - void BindSideWorldAdd(Action func); - /// - /// Unbinds the side world added callback. - /// - void UnbindSideWorldAdd(); + void UnbindWorldCreated(); /// /// Notifies the system that a service has been created. /// @@ -58,85 +51,103 @@ public interface IMethodSync /// Unbinds the service update callback. /// void UnbindServicesUpdated(); + /// + /// Called by world class to tell game the initiation is complite + /// + void WorldIsReady(); + /// + /// Event invoked by World class to tell the realmethod initiation complite + /// Access by Game class + /// + event Action OnGameReady; } - - /// - /// Base class for any gamebridge in the framework. - /// Provides core functionality for: - /// - /// World synchronization (main and additive worlds) - /// Service lifecycle notifications (created/removed) - /// world check for single remove new version - /// Load & Unload Scene reporting - /// - /// Inherits from and implements - /// to integrate with the game's internal world and service management system. + /// Defines all events and stat need to know for loading scnes + /// to make internal connection from Game to unify all game events from Game class /// - public abstract class GameBridge : Service, IMethodSync + public interface ILoadScneBridge { /// /// Event invoked when a scene or world starts or finishes loading. /// The boolean parameter is true when loading starts and false when loading ends. /// - public event Action OnSceneLoading; + event Action OnSceneLoading; /// /// Event invoked during scene or world loading to report progress. /// The float parameter represents the loading progress from 0 (start) to 1 (complete). /// - public event Action OnSceneLoadingProcess; + event Action OnSceneLoadingProcess; /// /// Indicates whether a scene or world load operation is currently in progress. /// - public bool IsLoading { get; protected set; } + bool IsLoading { get; } + } - // Game Structure - private Action MainWorldEvent; - private Action SideWorldEvent; - private Action ServiceEvents; - // Implement IMethodSync Interface - bool IMethodSync.IntroduceWorld(World world) - { - return RequestForNewWorld(world); - } - void IMethodSync.BindMainWorldAdd(Action func) + /// + /// Base class for any gamebridge in the framework. + /// Provides core functionality for: + /// + /// World synchronization (main and additive worlds) + /// Service lifecycle notifications (created/removed) + /// world check for single remove new version + /// Load & Unload Scene reporting + /// + /// Inherits from and implements + /// to integrate with the game's internal world and service management system. + /// + public abstract class GameBridge : Service, IRelationBridge, ILoadScneBridge + { + // Events + private Action GameReadyEvent; + private Action NewWorldEvent; + private Action ServiceEvents; + private Action SceneLoadingEvent; + private Action SceneLoadingProcessEvent; + protected bool isLoading; + + + // Implement IRelationBridge Interface + event Action IRelationBridge.OnGameReady { - if (MainWorldEvent != null) + add { - Debug.LogWarning("BindMainWorldAdd is already binded this interface is internal didnt use in another script or your game"); - return; + GameReadyEvent += value; + } + + remove + { + GameReadyEvent -= value; } - MainWorldEvent = func; } - void IMethodSync.UnbindMainWorldAdd() + bool IRelationBridge.IntroduceWorld(World world) { - MainWorldEvent = null; + return RequestForNewWorld(world); } - void IMethodSync.BindSideWorldAdd(Action func) + void IRelationBridge.BindWorldCreated(Action func) { - if (SideWorldEvent != null) + if (NewWorldEvent != null) { - Debug.LogWarning("BindSideWorldAdd is already binded this interface is internal didnt use in another script or your game"); + Debug.LogWarning("BindMainWorldAdd is already binded this interface is internal didnt use in another script or your game"); return; } - SideWorldEvent = func; + NewWorldEvent = func; } - void IMethodSync.UnbindSideWorldAdd() + void IRelationBridge.UnbindWorldCreated() { - SideWorldEvent = null; + NewWorldEvent = null; } - void IMethodSync.ServiceCreated(Service service) + void IRelationBridge.ServiceCreated(Service service) { ServiceEvents.Invoke(service, true); } - void IMethodSync.ServiceRemoved(Service service) + void IRelationBridge.ServiceRemoved(Service service) { ServiceEvents.Invoke(service, false); } - void IMethodSync.BindServicesUpdated(Action func) + void IRelationBridge.BindServicesUpdated(Action func) { if (ServiceEvents != null) { @@ -145,10 +156,62 @@ void IMethodSync.BindServicesUpdated(Action func) } ServiceEvents = func; } - void IMethodSync.UnbindServicesUpdated() + void IRelationBridge.UnbindServicesUpdated() { ServiceEvents = null; } + void IRelationBridge.WorldIsReady() + { + GameReadyEvent.Invoke(); + } + + // Implement ILoadScneBridge Interface + event Action ILoadScneBridge.OnSceneLoading + { + add + { + SceneLoadingEvent += value; + } + + remove + { + SceneLoadingEvent -= value; + } + } + event Action ILoadScneBridge.OnSceneLoadingProcess + { + add + { + SceneLoadingProcessEvent += value; + } + + remove + { + SceneLoadingProcessEvent -= value; + } + } + bool ILoadScneBridge.IsLoading => isLoading; + + + + /// + /// Call this when you want to define new World class to game + /// + /// The world instance will set as main world for game. + protected void SetMianWorld(World world) + { + NewWorldEvent?.Invoke(world); + } + /// + /// Call this when you want to define new World class that created and should not be main world (probably deleted) + /// + /// The world instance will not set to main world for game. + protected void SetAdditiveWorld(World world) + { + world.enabled = false; + OnAdditiveWorldDetected(world); + } + /// @@ -164,16 +227,24 @@ protected virtual bool RequestForNewWorld(World NewWorld) // this approach world just when you destroy last world instance from scene if (Game.World == null) { - MainWorldEvent?.Invoke(NewWorld); + SetMianWorld(NewWorld); return true; } else { - SideWorldEvent?.Invoke(NewWorld); + SetAdditiveWorld(NewWorld); return false; } } /// + /// Called when new scene loaded and during base world valid new world created. + /// + /// The New WorldClass Refrence in AdditiveScene + protected virtual void OnAdditiveWorldDetected(World AdditiveWorld) + { + Despawn.GameObject(AdditiveWorld.gameObject); + } + /// /// Starts loading a scene by name using a coroutine. /// /// The name of the scene to load. @@ -183,7 +254,7 @@ protected virtual bool RequestForNewWorld(World NewWorld) /// public virtual IEnumerator GetLoadScneCorotine(string sceneName) { - if (IsLoading == true) + if (isLoading == true) { Debug.LogWarning($"Can't load Scene:{sceneName} The Bridge is in loading target scene"); return null; @@ -191,6 +262,23 @@ public virtual IEnumerator GetLoadScneCorotine(string sceneName) return LoadSceneAsync(sceneName); } /// + /// Starts Adding a scene by name using a coroutine. + /// + /// The name of the scene to load. + /// + /// An IEnumerator coroutine for Adding the scene, + /// or null if a load operation is already in progress. + /// + public virtual IEnumerator GetAddScneCorotine(string sceneName, Action callback) + { + if (isLoading == true) + { + Debug.LogWarning($"Can't load Scene:{sceneName} The Bridge is in loading target scene"); + return null; + } + return AddSceneAsync(callback, sceneName); + } + /// /// Starts loading a scene by build index using a coroutine. /// /// The build index of the scene to load. @@ -200,7 +288,7 @@ public virtual IEnumerator GetLoadScneCorotine(string sceneName) /// public virtual IEnumerator GetLoadScneCorotine(int sceneIndex) { - if (IsLoading == true) + if (isLoading == true) { Debug.LogWarning($"Can't load Index:{sceneIndex} The Bridge is in loading target scene"); return null; @@ -208,6 +296,23 @@ public virtual IEnumerator GetLoadScneCorotine(int sceneIndex) return LoadSceneAsync(string.Empty, sceneIndex); } /// + /// Starts Adding a scene by build index using a coroutine. + /// + /// The build index of the scene to load. + /// + /// An IEnumerator coroutine for Adding the scene, + /// or null if a load operation is already in progress. + /// + public virtual IEnumerator GetAddScneCorotine(int sceneIndex, Action callback) + { + if (isLoading == true) + { + Debug.LogWarning($"Can't load Index:{sceneIndex} The Bridge is in loading target scene"); + return null; + } + return AddSceneAsync(callback, string.Empty, sceneIndex); + } + /// /// Starts loading a world configuration using a coroutine. /// /// The world scene configuration to load. @@ -217,7 +322,7 @@ public virtual IEnumerator GetLoadScneCorotine(int sceneIndex) /// public virtual IEnumerator GetLoadWorldCorotine(WorldSceneConfig WorldScene) { - if (IsLoading == true) + if (isLoading == true) { Debug.LogWarning($"Can't load World:{WorldScene} The Bridge is in loading target scene"); return null; @@ -230,8 +335,8 @@ public virtual IEnumerator GetLoadWorldCorotine(WorldSceneConfig WorldScene) private IEnumerator LoadSceneAsync(string scene, int scneIndex = -1) { //StartLoading - IsLoading = true; - OnSceneLoading?.Invoke(true); + isLoading = true; + SceneLoadingEvent?.Invoke(true); float fadingtime = Game.Config.FadeTime; //Fading Screen @@ -253,16 +358,16 @@ private IEnumerator LoadSceneAsync(string scene, int scneIndex = -1) if (Load_opertation == null) { Debug.LogError("Failed to load scene. AsyncOperation is null."); - OnSceneLoading?.Invoke(false); - IsLoading = false; + SceneLoadingEvent?.Invoke(false); + isLoading = false; yield break; } while (!Load_opertation.isDone) { - OnSceneLoadingProcess?.Invoke(Load_opertation.progress); + SceneLoadingProcessEvent?.Invoke(Load_opertation.progress); yield return null; } - OnSceneLoadingProcess?.Invoke(1); + SceneLoadingProcessEvent?.Invoke(1); //Fading Screen if (fadingtime != 0) @@ -271,14 +376,39 @@ private IEnumerator LoadSceneAsync(string scene, int scneIndex = -1) } //FinishLoading - OnSceneLoading?.Invoke(false); - IsLoading = false; + SceneLoadingEvent?.Invoke(false); + isLoading = false; + } + private IEnumerator AddSceneAsync(Action callback, string scene, int scneIndex = -1) + { + //Loading Scene + AsyncOperation Load_opertation; + if (scneIndex > -1) + { + Load_opertation = SceneManager.LoadSceneAsync(scneIndex, LoadSceneMode.Additive); + } + else + { + Load_opertation = SceneManager.LoadSceneAsync(scene, LoadSceneMode.Additive); + } + if (Load_opertation == null) + { + Debug.LogError("Failed to Add scene. AsyncOperation is null."); + yield break; + } + while (!Load_opertation.isDone) + { + // Processing + yield return null; + } + // Process = 1; + callback?.Invoke(); } private IEnumerator LoadWorldAsync(WorldSceneConfig WS) { //StartLoading - IsLoading = true; - OnSceneLoading?.Invoke(true); + isLoading = true; + SceneLoadingEvent?.Invoke(true); float fadingtime = Game.Config.FadeTime; //Fading Screen @@ -293,15 +423,15 @@ private IEnumerator LoadWorldAsync(WorldSceneConfig WS) if (Load_opertation == null) { Debug.LogError("Failed to load scene. AsyncOperation is null."); - OnSceneLoading?.Invoke(false); - IsLoading = false; + SceneLoadingEvent?.Invoke(false); + isLoading = false; yield break; } while (!Load_opertation.isDone) { - OnSceneLoadingProcess?.Invoke(RM_Math.Map.RemapClamped(Load_opertation.progress, 0, 1, 0, 1 / WS.Count + 1)); - OnSceneLoading?.Invoke(false); - IsLoading = false; + SceneLoadingProcessEvent?.Invoke(RM_Math.Map.RemapClamped(Load_opertation.progress, 0, 1, 0, 1 / WS.Count + 1)); + SceneLoadingEvent?.Invoke(false); + isLoading = false; yield return null; } @@ -312,17 +442,17 @@ private IEnumerator LoadWorldAsync(WorldSceneConfig WS) if (Additive_Load_opertation == null) { Debug.LogError("Failed to load scene. AsyncOperation is null."); - OnSceneLoading?.Invoke(false); - IsLoading = false; + SceneLoadingEvent?.Invoke(false); + isLoading = false; yield break; } while (!Additive_Load_opertation.isDone) { - OnSceneLoadingProcess?.Invoke(RM_Math.Map.RemapClamped(Load_opertation.progress, 0, 1, 0, 1 / WS.Count + 1 - (i + 1))); + SceneLoadingProcessEvent?.Invoke(RM_Math.Map.RemapClamped(Load_opertation.progress, 0, 1, 0, 1 / WS.Count + 1 - (i + 1))); yield return null; } } - OnSceneLoadingProcess?.Invoke(1); + SceneLoadingProcessEvent?.Invoke(1); //Fading Screen if (fadingtime != 0) @@ -331,10 +461,10 @@ private IEnumerator LoadWorldAsync(WorldSceneConfig WS) } //FinishLoading - OnSceneLoading?.Invoke(false); - IsLoading = false; + SceneLoadingEvent?.Invoke(false); + isLoading = false; } - + #if UNITY_EDITOR diff --git a/Runtime/Core/Architecture/ManagerContracts.cs b/Runtime/Core/Architecture/GameManager.cs similarity index 100% rename from Runtime/Core/Architecture/ManagerContracts.cs rename to Runtime/Core/Architecture/GameManager.cs diff --git a/Runtime/Core/Architecture/ManagerContracts.cs.meta b/Runtime/Core/Architecture/GameManager.cs.meta similarity index 100% rename from Runtime/Core/Architecture/ManagerContracts.cs.meta rename to Runtime/Core/Architecture/GameManager.cs.meta diff --git a/Runtime/Core/Architecture/ServiceContracts.cs b/Runtime/Core/Architecture/Service.cs similarity index 94% rename from Runtime/Core/Architecture/ServiceContracts.cs rename to Runtime/Core/Architecture/Service.cs index ba313dc..99f5311 100644 --- a/Runtime/Core/Architecture/ServiceContracts.cs +++ b/Runtime/Core/Architecture/Service.cs @@ -35,7 +35,7 @@ void IService.Created(object author) } void IService.ChangeWorld(World NewWorld) { - OnWorldChanged(Game.World, NewWorld); + OnWorldChanging(Game.World, NewWorld); } void IService.Deleted(object author) { @@ -52,7 +52,7 @@ void IService.Deleted(object author) /// Called when a new world or environment is initialized. /// Must be implemented by derived classes. /// - protected abstract void OnWorldChanged(World Previous, World New); + protected abstract void OnWorldChanging(World Previous, World New); /// /// Called when the service ends or is deleted. /// Must be implemented by derived classes. diff --git a/Runtime/Core/Architecture/ServiceContracts.cs.meta b/Runtime/Core/Architecture/Service.cs.meta similarity index 100% rename from Runtime/Core/Architecture/ServiceContracts.cs.meta rename to Runtime/Core/Architecture/Service.cs.meta diff --git a/Runtime/Core/Architecture/World.cs b/Runtime/Core/Architecture/World.cs index 9e5394c..9e11487 100644 --- a/Runtime/Core/Architecture/World.cs +++ b/Runtime/Core/Architecture/World.cs @@ -88,15 +88,13 @@ public abstract class World : MonoBehaviour private void Awake() { //Connect to Game With Bridge - IMethodSync SyncProvider = Game.Bridge; + IRelationBridge SyncProvider = Game.Bridge; if (SyncProvider.IntroduceWorld(this)) { - SyncProvider.BindSideWorldAdd(Notify_OnAdditiveWorldInitiate); SyncProvider.BindServicesUpdated(Notify_OnServicesUpdated); } else { - enabled = false; return; } @@ -124,6 +122,7 @@ private void Awake() } WorldBegin(); + SyncProvider.WorldIsReady(); } @@ -133,8 +132,7 @@ private void Awake() /// private void OnDestroy() { - IMethodSync SyncProvider = Game.Bridge; - SyncProvider.UnbindSideWorldAdd(); + IRelationBridge SyncProvider = Game.Bridge; SyncProvider.UnbindServicesUpdated(); WorldEnd(); } @@ -328,29 +326,8 @@ protected virtual Transform SelectSpawnPoint(PlayerStarter[] starters) transform.position = Vector3.zero; return transform; } - /// - /// Called when an additive world GameObject is added to this world. - /// Default behaviour is to destroy the provided object; override to implement custom handling. - /// - /// The additive world GameObject that was added. - protected virtual void OnAdditiveWorldAdded(GameObject WorldObject) - { - Destroy(WorldObject); - } - /// - /// Internal callback invoked by the service when an additive world is initiated. - /// Extracts the world GameObject, destroys the component instance, - /// and forwards the object to . - /// - /// The additive instance that was initiated. - private void Notify_OnAdditiveWorldInitiate(World TargetWorld) - { - GameObject worldObject = TargetWorld.gameObject; - Destroy(TargetWorld); - OnAdditiveWorldAdded(worldObject); - } /// /// Internal callback invoked when services are updated. Forwards the service update /// to all managers so they can resolve or react to the change. diff --git a/Runtime/Library/Extension/GameObject.cs b/Runtime/Library/Extension/GameObject.cs index 7b5f9b6..2accc5b 100644 --- a/Runtime/Library/Extension/GameObject.cs +++ b/Runtime/Library/Extension/GameObject.cs @@ -5,6 +5,24 @@ namespace RealMethod { public static class GameObject_Extension { + public static void Attach(this GameObject owner, GameObject parent, bool worldPositionStays) + { + owner.transform.SetParent(parent.transform, worldPositionStays); + owner.SendAttachEvent(parent); + } + public static void Detach(this GameObject owner, GameObject parent) + { + owner.transform.SetParent(null); + owner.SendDetachEvent(); + } + public static void SendAttachEvent(this GameObject owner, Object spawner, SendMessageOptions option = SendMessageOptions.RequireReceiver) + { + owner.SendMessage("OnAttach", spawner, option); + } + public static void SendDetachEvent(this GameObject owner, SendMessageOptions option = SendMessageOptions.RequireReceiver) + { + owner.SendMessage("OnDetach", option); + } public static void SendSpawnEvent(this GameObject owner, Object spawner, SendMessageOptions option = SendMessageOptions.RequireReceiver) { owner.SendMessage("OnSpawn", spawner, option); diff --git a/Runtime/Pattern/Services/InputService.cs b/Runtime/Pattern/Services/InputService.cs index d176352..c4555ed 100644 --- a/Runtime/Pattern/Services/InputService.cs +++ b/Runtime/Pattern/Services/InputService.cs @@ -14,7 +14,7 @@ protected sealed override void OnStart(object Author) ReplaceInputAsset(newAsset); } } - protected sealed override void OnWorldChanged(World Previous , World New) + protected sealed override void OnWorldChanging(World Previous , World New) { if (TryFindInputAsset(out InputActionAsset newAsset)) { diff --git a/Runtime/Pattern/Services/RuleService.cs b/Runtime/Pattern/Services/RuleService.cs index c27a2aa..69f5a67 100644 --- a/Runtime/Pattern/Services/RuleService.cs +++ b/Runtime/Pattern/Services/RuleService.cs @@ -13,7 +13,7 @@ public RuleService() Rules = new Hictionary>(5); } - protected override void OnWorldChanged(World Previous , World New) + protected override void OnWorldChanging(World Previous , World New) { foreach (var item in Rules.GetValues()) { diff --git a/Runtime/Pattern/Services/StateService.cs b/Runtime/Pattern/Services/StateService.cs index 9d25e2c..884bd27 100644 --- a/Runtime/Pattern/Services/StateService.cs +++ b/Runtime/Pattern/Services/StateService.cs @@ -16,7 +16,7 @@ public StateService(byte firstState) } // StateService Methods - protected sealed override void OnWorldChanged(World Previous , World New) + protected sealed override void OnWorldChanging(World Previous , World New) { if (CanResetforNewWorld(Game.World)) { diff --git a/Runtime/ReadySet/Essentials/DefaultGameBridge.cs b/Runtime/ReadySet/Essentials/DefaultGameBridge.cs index 0b823f4..10d4035 100644 --- a/Runtime/ReadySet/Essentials/DefaultGameBridge.cs +++ b/Runtime/ReadySet/Essentials/DefaultGameBridge.cs @@ -6,14 +6,16 @@ public sealed class DefaultGameBridge : GameBridge { protected override void OnStart(object Author) { - Debug.Log("DefaultBridge Started"); + Debug.Log("DefaultBridge Connected"); } - protected override void OnWorldChanged(World Previous , World New) + protected override void OnWorldChanging(World Previous, World New) { } protected override void OnEnd(object Author) { - Debug.Log("DefaultBridge Ended"); + Debug.Log("DefaultBridge Disconnected"); } + + } } \ No newline at end of file diff --git a/Runtime/ReadySet/Managers/ScreenManager.cs b/Runtime/ReadySet/Managers/ScreenManager.cs index 3549b48..545a9c4 100644 --- a/Runtime/ReadySet/Managers/ScreenManager.cs +++ b/Runtime/ReadySet/Managers/ScreenManager.cs @@ -23,8 +23,8 @@ public sealed class ScreenManager : UIManager // UIManager Methods protected override void InitiateManager(bool alwaysLoaded) { - Game.Bridge.OnSceneLoading += (value) => OnLoadScne?.Invoke(value); - Game.Bridge.OnSceneLoadingProcess += (value) => OnLoading?.Invoke(value); + Game.OnSceneLoading += (value) => OnLoadScne?.Invoke(value); + Game.OnSceneLoadingProcess += (value) => OnLoading?.Invoke(value); if (Game.TryFindService(out Spawn SpawnServ)) { SpawnServ.BringManager(this); diff --git a/Runtime/ReadySet/Services/NetworkService.cs b/Runtime/ReadySet/Services/NetworkService.cs index c4ae4f3..d3ae787 100644 --- a/Runtime/ReadySet/Services/NetworkService.cs +++ b/Runtime/ReadySet/Services/NetworkService.cs @@ -20,7 +20,7 @@ protected override void OnStart(object Author) { throw new NotImplementedException(); } - protected override void OnWorldChanged(World Previous , World New) + protected override void OnWorldChanging(World Previous , World New) { throw new NotImplementedException(); } diff --git a/Runtime/ReadySet/Services/PrintService.cs b/Runtime/ReadySet/Services/PrintService.cs index ce0ca5c..03d23c7 100644 --- a/Runtime/ReadySet/Services/PrintService.cs +++ b/Runtime/ReadySet/Services/PrintService.cs @@ -38,7 +38,7 @@ protected override void OnStart(object Author) manager.InitiateManager(true); } } - protected override void OnWorldChanged(World Previous , World New) + protected override void OnWorldChanging(World Previous , World New) { Printer.Clear(); } diff --git a/Runtime/ReadySet/Services/SpawanService.cs b/Runtime/ReadySet/Services/SpawanService.cs index 2aea19b..308cdf1 100644 --- a/Runtime/ReadySet/Services/SpawanService.cs +++ b/Runtime/ReadySet/Services/SpawanService.cs @@ -41,7 +41,7 @@ protected override void OnStart(object Author) { GameDespawn = new Despawn(); } - protected override void OnWorldChanged(World Previous , World New) + protected override void OnWorldChanging(World Previous , World New) { } protected override void OnEnd(object Author) diff --git a/Runtime/ReadySet/Services/TimeService.cs b/Runtime/ReadySet/Services/TimeService.cs index 465f504..f5d6713 100644 --- a/Runtime/ReadySet/Services/TimeService.cs +++ b/Runtime/ReadySet/Services/TimeService.cs @@ -15,7 +15,7 @@ protected override void OnStart(object Author) worldTime = Time.time; RecordTime = new Hictionary(10); } - protected override void OnWorldChanged(World Previous , World New) + protected override void OnWorldChanging(World Previous , World New) { worldTime = Time.time; } From 070d217adc1f36899267b6af388f1184b914a71b Mon Sep 17 00:00:00 2001 From: Alijimpa Date: Sun, 8 Mar 2026 14:18:32 +0330 Subject: [PATCH 022/204] Fix errors and Move fadetime to game config --- Runtime/Core/Architecture/Game.cs | 2 +- Runtime/Core/Architecture/GameBridge.cs | 12 ++++++------ Runtime/Core/Architecture/GameConfig.cs | 13 +------------ Runtime/ReadySet/Essentials/DefaultGameConfig.cs | 12 +----------- 4 files changed, 9 insertions(+), 30 deletions(-) diff --git a/Runtime/Core/Architecture/Game.cs b/Runtime/Core/Architecture/Game.cs index ab0b325..b969797 100644 --- a/Runtime/Core/Architecture/Game.cs +++ b/Runtime/Core/Architecture/Game.cs @@ -219,7 +219,7 @@ private static void InitializeGame() { Config = ScriptableObject.CreateInstance(); } - Config.Initialized(Instance); + Config.Initialized(); // Initiate GamePrefab & Managers List CashManagers = new List(5); diff --git a/Runtime/Core/Architecture/GameBridge.cs b/Runtime/Core/Architecture/GameBridge.cs index 1b986a4..d12eda7 100644 --- a/Runtime/Core/Architecture/GameBridge.cs +++ b/Runtime/Core/Architecture/GameBridge.cs @@ -106,7 +106,8 @@ public abstract class GameBridge : Service, IRelationBridge, ILoadScneBridge private Action ServiceEvents; private Action SceneLoadingEvent; private Action SceneLoadingProcessEvent; - protected bool isLoading; + private bool isLoading; + protected float FadeTime { get; private set; } = 1; // Implement IRelationBridge Interface @@ -162,7 +163,7 @@ void IRelationBridge.UnbindServicesUpdated() } void IRelationBridge.WorldIsReady() { - GameReadyEvent.Invoke(); + GameReadyEvent?.Invoke(); } // Implement ILoadScneBridge Interface @@ -193,7 +194,6 @@ event Action ILoadScneBridge.OnSceneLoadingProcess bool ILoadScneBridge.IsLoading => isLoading; - /// /// Call this when you want to define new World class to game /// @@ -337,7 +337,7 @@ private IEnumerator LoadSceneAsync(string scene, int scneIndex = -1) //StartLoading isLoading = true; SceneLoadingEvent?.Invoke(true); - float fadingtime = Game.Config.FadeTime; + float fadingtime = FadeTime; //Fading Screen if (fadingtime != 0) @@ -409,7 +409,7 @@ private IEnumerator LoadWorldAsync(WorldSceneConfig WS) //StartLoading isLoading = true; SceneLoadingEvent?.Invoke(true); - float fadingtime = Game.Config.FadeTime; + float fadingtime = FadeTime; //Fading Screen if (fadingtime != 0) @@ -464,7 +464,7 @@ private IEnumerator LoadWorldAsync(WorldSceneConfig WS) SceneLoadingEvent?.Invoke(false); isLoading = false; } - + #if UNITY_EDITOR diff --git a/Runtime/Core/Architecture/GameConfig.cs b/Runtime/Core/Architecture/GameConfig.cs index 98c9ad6..004147c 100644 --- a/Runtime/Core/Architecture/GameConfig.cs +++ b/Runtime/Core/Architecture/GameConfig.cs @@ -8,22 +8,11 @@ namespace RealMethod /// public abstract class GameConfig : ConfigAsset { - [Header("Game")] - [SerializeField] - private float fadeTime = 0; - /// - /// Gets the duration (in seconds) used for screen fade transitions. - /// - public float FadeTime => fadeTime; - /// /// Called when the game is initialized, allowing the configuration /// to apply settings or perform setup logic. /// - /// - /// The Game instance responsible for initialization. - /// - public abstract void Initialized(Game Author); + public abstract void Initialized(); } diff --git a/Runtime/ReadySet/Essentials/DefaultGameConfig.cs b/Runtime/ReadySet/Essentials/DefaultGameConfig.cs index bcde6ed..9a1116b 100644 --- a/Runtime/ReadySet/Essentials/DefaultGameConfig.cs +++ b/Runtime/ReadySet/Essentials/DefaultGameConfig.cs @@ -4,19 +4,9 @@ namespace RealMethod { public sealed class DefaultGameConfig : GameConfig { - public override void Initialized(Game Author) + public override void Initialized() { Debug.Log("DefaultConfig Loaded"); } - - protected override void OnEnable() - { - if (HasCloneName()) - { - Debug.LogError($"UniqueAsset Can't Clone at Runtime, NewFile Removed!"); - Destroy(this); - return; - } - } } } From 6d5786a8dc722b7f68e5d44bc3cc00035f615393 Mon Sep 17 00:00:00 2001 From: Alijimpa Date: Sun, 8 Mar 2026 14:25:55 +0330 Subject: [PATCH 023/204] Fix GameConfig errors --- Runtime/Core/Architecture/GameBridge.cs | 2 +- Runtime/ReadySet/Essentials/DefaultGameConfig.cs | 10 ++++++++++ 2 files changed, 11 insertions(+), 1 deletion(-) diff --git a/Runtime/Core/Architecture/GameBridge.cs b/Runtime/Core/Architecture/GameBridge.cs index d12eda7..9209b59 100644 --- a/Runtime/Core/Architecture/GameBridge.cs +++ b/Runtime/Core/Architecture/GameBridge.cs @@ -107,7 +107,7 @@ public abstract class GameBridge : Service, IRelationBridge, ILoadScneBridge private Action SceneLoadingEvent; private Action SceneLoadingProcessEvent; private bool isLoading; - protected float FadeTime { get; private set; } = 1; + protected float FadeTime = 0; // Implement IRelationBridge Interface diff --git a/Runtime/ReadySet/Essentials/DefaultGameConfig.cs b/Runtime/ReadySet/Essentials/DefaultGameConfig.cs index 9a1116b..425372d 100644 --- a/Runtime/ReadySet/Essentials/DefaultGameConfig.cs +++ b/Runtime/ReadySet/Essentials/DefaultGameConfig.cs @@ -8,5 +8,15 @@ public override void Initialized() { Debug.Log("DefaultConfig Loaded"); } + + protected override void OnEnable() + { + if (HasCloneName()) + { + Debug.LogError($"UniqueAsset Can't Clone at Runtime, NewFile Removed!"); + Destroy(this); + return; + } + } } } From b23d0826bc887f7eb22f1088b305b2200b6371d7 Mon Sep 17 00:00:00 2001 From: Alijimpa Date: Sun, 8 Mar 2026 22:34:52 +0330 Subject: [PATCH 024/204] Implement Fname in Method --- Editor/Core/Definitions/FName_Drawer.cs | 34 ++++ Editor/Core/Definitions/FName_Drawer.cs.meta | 2 + Runtime/Core/Definitions/FName.cs | 167 +++++++++++++++++++ Runtime/Core/Definitions/FName.cs.meta | 2 + 4 files changed, 205 insertions(+) create mode 100644 Editor/Core/Definitions/FName_Drawer.cs create mode 100644 Editor/Core/Definitions/FName_Drawer.cs.meta create mode 100644 Runtime/Core/Definitions/FName.cs create mode 100644 Runtime/Core/Definitions/FName.cs.meta diff --git a/Editor/Core/Definitions/FName_Drawer.cs b/Editor/Core/Definitions/FName_Drawer.cs new file mode 100644 index 0000000..bd323e9 --- /dev/null +++ b/Editor/Core/Definitions/FName_Drawer.cs @@ -0,0 +1,34 @@ +using UnityEditor; +using UnityEngine; + +namespace RealMethod.Editor +{ + [CustomPropertyDrawer(typeof(FName))] + public class FName_Drawer : PropertyDrawer + { + public override void OnGUI(Rect position, SerializedProperty property, GUIContent label) + { + SerializedProperty idProp = property.FindPropertyRelative("id"); + + if (idProp == null) + { + EditorGUI.LabelField(position, label.text, "id field not found"); + return; + } + + string current = FName.GetString(idProp.intValue); + + EditorGUI.BeginProperty(position, label, property); + + string newValue = EditorGUI.TextField(position, label, current); + + if (newValue != current) + { + idProp.intValue = FName.GetOrCreateId(newValue); + } + + EditorGUI.EndProperty(); + } + } + +} \ No newline at end of file diff --git a/Editor/Core/Definitions/FName_Drawer.cs.meta b/Editor/Core/Definitions/FName_Drawer.cs.meta new file mode 100644 index 0000000..efbed6d --- /dev/null +++ b/Editor/Core/Definitions/FName_Drawer.cs.meta @@ -0,0 +1,2 @@ +fileFormatVersion: 2 +guid: 2ddcecdd6b6816a40926f6a6d2ac2a9a \ No newline at end of file diff --git a/Runtime/Core/Definitions/FName.cs b/Runtime/Core/Definitions/FName.cs new file mode 100644 index 0000000..42fb701 --- /dev/null +++ b/Runtime/Core/Definitions/FName.cs @@ -0,0 +1,167 @@ +using System; +using System.Collections.Generic; +using UnityEngine; + +namespace RealMethod +{ + /// + /// Lightweight engine-style string identifier. + /// Stores only an integer ID while the actual strings live in a global table. + /// + [Serializable] + public struct FName : IEquatable + { + /// + /// Maximum allowed characters for a name. + /// + public const int MaxLength = 1024; + + /// + /// Internal identifier referencing the global name table. + /// + [SerializeField] + private int id; + + /// + /// Stores strings by ID. + /// + private static readonly List idToName = new List(256); + + /// + /// Hash → list of IDs (collision bucket). + /// + private static readonly Dictionary> hashToIds = new Dictionary>(256); + + /// + /// Lock for thread-safe name registration. + /// + private static readonly object tableLock = new object(); + + /// + /// Creates a Name from a string. + /// + public FName(string value) + { + id = GetOrCreateId(value); + } + + /// + /// Returns the ID for a string or creates a new one. + /// + public static int GetOrCreateId(string value) + { + if (string.IsNullOrEmpty(value)) + throw new ArgumentException("Name cannot be null or empty."); + + if (value.Length > MaxLength) + throw new ArgumentException($"Name cannot exceed {MaxLength} characters."); + + int hash = value.GetHashCode(); + + lock (tableLock) + { + if (hashToIds.TryGetValue(hash, out var bucket)) + { + for (int i = 0; i < bucket.Count; i++) + { + int existingId = bucket[i]; + + if (idToName[existingId] == value) + return existingId; + } + } + else + { + bucket = new List(2); + hashToIds.Add(hash, bucket); + } + + int newId = idToName.Count; + + idToName.Add(value); + bucket.Add(newId); + + return newId; + } + } + + /// + /// Returns the string for an ID. + /// + public static string GetString(int id) + { + if (id < 0 || id >= idToName.Count) + return string.Empty; + + return idToName[id]; + } + + /// + /// Converts Name to string. + /// + public override string ToString() + { + return GetString(id); + } + + /// + /// Implicit conversion from string. + /// + public static implicit operator FName(string value) + { + return new FName(value); + } + + /// + /// Implicit conversion to string. + /// + public static implicit operator string(FName name) + { + return GetString(name.id); + } + + /// + /// Equality operator. + /// + public static bool operator ==(FName a, FName b) + { + return a.id == b.id; + } + + /// + /// Inequality operator. + /// + public static bool operator !=(FName a, FName b) + { + return a.id != b.id; + } + + /// + /// Checks equality with another Name. + /// + public bool Equals(FName other) + { + return id == other.id; + } + + /// + /// Checks equality with an object. + /// + public override bool Equals(object obj) + { + return obj is FName other && Equals(other); + } + + /// + /// Hash code of the Name. + /// + public override int GetHashCode() + { + return id; + } + } +} + + + + diff --git a/Runtime/Core/Definitions/FName.cs.meta b/Runtime/Core/Definitions/FName.cs.meta new file mode 100644 index 0000000..001e53f --- /dev/null +++ b/Runtime/Core/Definitions/FName.cs.meta @@ -0,0 +1,2 @@ +fileFormatVersion: 2 +guid: 9c6da38df6f709e40b377b75472167aa \ No newline at end of file From bd128f61bdabf52964fd5e312111689ffe8694f3 Mon Sep 17 00:00:00 2001 From: Alijimpa Date: Mon, 9 Mar 2026 00:47:55 +0330 Subject: [PATCH 025/204] Update Identifier to FName --- Runtime/Core/Definitions/Identifier.cs | 2 +- Runtime/Core/Definitions/Prefab.cs | 2 +- Runtime/Pattern/DataAssets/ItemAsset.cs | 2 +- Runtime/Pattern/DataAssets/ItemConfig.cs | 2 +- Runtime/Pattern/Managers/HapticManager.cs | 4 ++-- Runtime/Toolkit/Ability/AbilityAsset.cs | 2 +- Runtime/Toolkit/PCG/Assets/PCGCashAsset.cs | 2 +- Runtime/Toolkit/PCG/Assets/PCGResourceConfig.cs | 2 +- Runtime/Toolkit/RPG/Resource/ResourceData.cs | 2 +- Runtime/Toolkit/RPG/StatSystem/BuffConfig.cs | 2 +- Runtime/Toolkit/RPG/StatSystem/StatData.cs | 2 +- Runtime/Toolkit/RPG/StatSystem/StatProfile.cs | 2 +- Runtime/Toolkit/Tutorial/TutorialConfig.cs | 2 +- 13 files changed, 14 insertions(+), 14 deletions(-) diff --git a/Runtime/Core/Definitions/Identifier.cs b/Runtime/Core/Definitions/Identifier.cs index 7564b90..cca2609 100644 --- a/Runtime/Core/Definitions/Identifier.cs +++ b/Runtime/Core/Definitions/Identifier.cs @@ -2,6 +2,6 @@ namespace RealMethod { public interface IIdentifier { - string NameID { get; } + FName NameID { get; } } } \ No newline at end of file diff --git a/Runtime/Core/Definitions/Prefab.cs b/Runtime/Core/Definitions/Prefab.cs index be83a65..933a14e 100644 --- a/Runtime/Core/Definitions/Prefab.cs +++ b/Runtime/Core/Definitions/Prefab.cs @@ -10,7 +10,7 @@ public abstract class PrefabCore : IIdentifier [SerializeField] private GameObject PrefabAsset; // <-- this name must match public GameObject asset => PrefabAsset; - public string NameID => PrefabAsset != null ? PrefabAsset.name : "Empty"; + public FName NameID => PrefabAsset != null ? PrefabAsset.name : "Empty"; // Public Functions public J GetSoftClass() where J : Component diff --git a/Runtime/Pattern/DataAssets/ItemAsset.cs b/Runtime/Pattern/DataAssets/ItemAsset.cs index 591e285..28b7212 100644 --- a/Runtime/Pattern/DataAssets/ItemAsset.cs +++ b/Runtime/Pattern/DataAssets/ItemAsset.cs @@ -7,7 +7,7 @@ public abstract class ItemAsset : DataAsset, IItem [Header("Item")] [SerializeField] protected string itemName; - public string NameID => itemName; + public FName NameID => itemName; [SerializeField] protected Texture2D _icon; public Texture2D Icon => _icon; diff --git a/Runtime/Pattern/DataAssets/ItemConfig.cs b/Runtime/Pattern/DataAssets/ItemConfig.cs index f4a4b30..c0b6826 100644 --- a/Runtime/Pattern/DataAssets/ItemConfig.cs +++ b/Runtime/Pattern/DataAssets/ItemConfig.cs @@ -7,7 +7,7 @@ public abstract class ItemConfig : ConfigAsset, IItem [Header("Item")] [SerializeField] protected string itemName; - public string NameID => itemName; + public FName NameID => itemName; [SerializeField] protected Texture2D _icon; public Texture2D Icon => _icon; diff --git a/Runtime/Pattern/Managers/HapticManager.cs b/Runtime/Pattern/Managers/HapticManager.cs index 963f402..e3f48c7 100644 --- a/Runtime/Pattern/Managers/HapticManager.cs +++ b/Runtime/Pattern/Managers/HapticManager.cs @@ -22,7 +22,7 @@ private class HapticController : IHapticProvider private HapticManager Owner; // Implement IIdentifier Interface - public string NameID => Config.NameID; + public FName NameID => Config.NameID; // Implement IHapticProvider Interface public HapticController(HapticManager manager, HapticConfig config) { @@ -148,7 +148,7 @@ public abstract class HapticConfig : ConfigAsset, IIdentifier private string configName; // Implement - public string NameID => configName; + public FName NameID => configName; private void OnValidate() { diff --git a/Runtime/Toolkit/Ability/AbilityAsset.cs b/Runtime/Toolkit/Ability/AbilityAsset.cs index 8537322..4a073bb 100644 --- a/Runtime/Toolkit/Ability/AbilityAsset.cs +++ b/Runtime/Toolkit/Ability/AbilityAsset.cs @@ -8,7 +8,7 @@ public abstract class AbilityAsset : TemplateAsset, IAbility, ICooldown private float lastUsedTime = -Mathf.Infinity; // Implement IIdentifier Interface - string IIdentifier.NameID => name; + FName IIdentifier.NameID => name; // Implement IAbility Interface public bool CanUse(GameObject user) { diff --git a/Runtime/Toolkit/PCG/Assets/PCGCashAsset.cs b/Runtime/Toolkit/PCG/Assets/PCGCashAsset.cs index fa9672c..936255e 100644 --- a/Runtime/Toolkit/PCG/Assets/PCGCashAsset.cs +++ b/Runtime/Toolkit/PCG/Assets/PCGCashAsset.cs @@ -11,7 +11,7 @@ public interface IPCGCashAsset : IIdentifier public class PCGCashAsset : ConfigAsset, IPCGCashAsset { - public string NameID => name; + public FName NameID => name; [SerializeField] private PCGData[] CashData; diff --git a/Runtime/Toolkit/PCG/Assets/PCGResourceConfig.cs b/Runtime/Toolkit/PCG/Assets/PCGResourceConfig.cs index e8a65fe..6e2d35d 100644 --- a/Runtime/Toolkit/PCG/Assets/PCGResourceConfig.cs +++ b/Runtime/Toolkit/PCG/Assets/PCGResourceConfig.cs @@ -36,7 +36,7 @@ public struct PCGSource [CreateAssetMenu(fileName = "PCG_Resource", menuName = "RealMethod/PCG/Resource", order = 1)] public class PCGResourceConfig : ConfigAsset, IPCGResource { - public string NameID => name; + public FName NameID => name; [SerializeField] private PCGSource[] Sources; diff --git a/Runtime/Toolkit/RPG/Resource/ResourceData.cs b/Runtime/Toolkit/RPG/Resource/ResourceData.cs index bceffda..fdc9674 100644 --- a/Runtime/Toolkit/RPG/Resource/ResourceData.cs +++ b/Runtime/Toolkit/RPG/Resource/ResourceData.cs @@ -44,7 +44,7 @@ public ResourceData(string ReName, float val, float max) float IResource.Value => value; float IResource.MaxValue => GetMaxValue(defaultMaxValue); // Implement IIdentifier Interface - public string NameID => resourceName; + public FName NameID => resourceName; void IResource.Refill() { value = provider.MaxValue; diff --git a/Runtime/Toolkit/RPG/StatSystem/BuffConfig.cs b/Runtime/Toolkit/RPG/StatSystem/BuffConfig.cs index 4db7bc1..58862ff 100644 --- a/Runtime/Toolkit/RPG/StatSystem/BuffConfig.cs +++ b/Runtime/Toolkit/RPG/StatSystem/BuffConfig.cs @@ -9,7 +9,7 @@ public abstract class BuffConfig : ConfigAsset, IIdentifier [SerializeField] private string configName; // Implement IIdentifier Interface - public string NameID => configName; + public FName NameID => configName; // Abstract Method public abstract IStatModifier[] GetModifiers(T StateName) where T : System.Enum; diff --git a/Runtime/Toolkit/RPG/StatSystem/StatData.cs b/Runtime/Toolkit/RPG/StatSystem/StatData.cs index df8c768..6548c73 100644 --- a/Runtime/Toolkit/RPG/StatSystem/StatData.cs +++ b/Runtime/Toolkit/RPG/StatSystem/StatData.cs @@ -53,7 +53,7 @@ public BaseStatData(float startValue, float min, float max) // Implement IStat Interface - public string NameID => GetStatName(); + public FName NameID => GetStatName(); public float BaseValue => baseValue.GetMergeValue(); public float Value => GetFinalValue(); public float MinValue => minValue; diff --git a/Runtime/Toolkit/RPG/StatSystem/StatProfile.cs b/Runtime/Toolkit/RPG/StatSystem/StatProfile.cs index 0f8b5c6..16fb6e1 100644 --- a/Runtime/Toolkit/RPG/StatSystem/StatProfile.cs +++ b/Runtime/Toolkit/RPG/StatSystem/StatProfile.cs @@ -46,7 +46,7 @@ public IStat this[int index] } // Implement IIdentifier Interface - public string NameID => profileName; + public FName NameID => profileName; void IPrimitiveStatContainer.InitializeResource(IResourceData resource) { resource.Initialize(this); diff --git a/Runtime/Toolkit/Tutorial/TutorialConfig.cs b/Runtime/Toolkit/Tutorial/TutorialConfig.cs index 93d7fed..01a9021 100644 --- a/Runtime/Toolkit/Tutorial/TutorialConfig.cs +++ b/Runtime/Toolkit/Tutorial/TutorialConfig.cs @@ -35,7 +35,7 @@ public abstract class TutorialConfigCore : ConfigAsset, IItem, ITutorialSpawner // Implement IIdentifier Interface - public string NameID => label; + public FName NameID => label; // Implement IItem Interface public Texture2D Icon => icon; Sprite IItem.GetSpriteIcon() From 830e885fb18e8b2ffbf15a861775eadb29a8fff5 Mon Sep 17 00:00:00 2001 From: Alijimpa Date: Mon, 9 Mar 2026 10:33:51 +0330 Subject: [PATCH 026/204] Implement Update Names Table for editor --- Editor/Core/Definitions/FName_Drawer.cs | 2 +- Runtime/Core/Architecture/Game.cs | 1 + Runtime/Core/Definitions/FName.cs | 104 ++++++++++++++++++ .../ProjectSetting/ProjectSettingAsset.cs | 8 ++ 4 files changed, 114 insertions(+), 1 deletion(-) diff --git a/Editor/Core/Definitions/FName_Drawer.cs b/Editor/Core/Definitions/FName_Drawer.cs index bd323e9..7f52988 100644 --- a/Editor/Core/Definitions/FName_Drawer.cs +++ b/Editor/Core/Definitions/FName_Drawer.cs @@ -20,7 +20,7 @@ public override void OnGUI(Rect position, SerializedProperty property, GUIConten EditorGUI.BeginProperty(position, label, property); - string newValue = EditorGUI.TextField(position, label, current); + string newValue = EditorGUI.DelayedTextField(position, label, current); if (newValue != current) { diff --git a/Runtime/Core/Architecture/Game.cs b/Runtime/Core/Architecture/Game.cs index b969797..5abafc9 100644 --- a/Runtime/Core/Architecture/Game.cs +++ b/Runtime/Core/Architecture/Game.cs @@ -160,6 +160,7 @@ private static void InitializeGame() Quit(); return; } + ProjectSettings.OnLoadedInGame(); // Initiate GameClass var emptyObject = new GameObject("RealGame"); diff --git a/Runtime/Core/Definitions/FName.cs b/Runtime/Core/Definitions/FName.cs index 42fb701..4920e4a 100644 --- a/Runtime/Core/Definitions/FName.cs +++ b/Runtime/Core/Definitions/FName.cs @@ -2,6 +2,10 @@ using System.Collections.Generic; using UnityEngine; +#if UNITY_EDITOR +using UnityEditor.Callbacks; +#endif + namespace RealMethod { /// @@ -45,6 +49,51 @@ public FName(string value) id = GetOrCreateId(value); } + + /// + /// Called when Editor opend and restored all staring saved in editor time + /// + /// + public static void OnProjectSettingLoaded(ProjectSettingAsset setting) + { + if (setting == null) + { + Debug.LogError("FName Initialize failed: ProjectSettingAsset is null."); + return; + } + + lock (tableLock) + { + idToName.Clear(); + hashToIds.Clear(); + + var names = setting.Names; // assume List Names in the asset + + if (names == null) + return; + + for (int i = 0; i < names.Count; i++) + { + string value = names[i]; + + if (string.IsNullOrEmpty(value)) + continue; + + int id = idToName.Count; + idToName.Add(value); + + int hash = value.GetHashCode(); + + if (!hashToIds.TryGetValue(hash, out var bucket)) + { + bucket = new List(2); + hashToIds.Add(hash, bucket); + } + + bucket.Add(id); + } + } + } /// /// Returns the ID for a string or creates a new one. /// @@ -81,6 +130,16 @@ public static int GetOrCreateId(string value) idToName.Add(value); bucket.Add(newId); +#if UNITY_EDITOR + ProjectSettingAsset ProjectSettings = Resources.Load("RealMethod/RealMethodSetting"); + if (ProjectSettings == null) + { + Debug.LogError("ProjectSettingAsset is missing from Resources folder!"); + return 0; + } + ProjectSettings.Names = idToName; +#endif + return newId; } } @@ -159,6 +218,51 @@ public override int GetHashCode() { return id; } + + +#if UNITY_EDITOR + [DidReloadScripts] + private static void OnScriptsReloaded() + { + ProjectSettingAsset ProjectSettings = Resources.Load("RealMethod/RealMethodSetting"); + if (ProjectSettings == null) + { + Debug.LogError("ProjectSettingAsset is missing from Resources folder!"); + } + + lock (tableLock) + { + idToName.Clear(); + hashToIds.Clear(); + + var names = ProjectSettings.Names; // assume List Names in the asset + + if (names == null) + return; + + for (int i = 0; i < names.Count; i++) + { + string value = names[i]; + + if (string.IsNullOrEmpty(value)) + continue; + + int id = idToName.Count; + idToName.Add(value); + + int hash = value.GetHashCode(); + + if (!hashToIds.TryGetValue(hash, out var bucket)) + { + bucket = new List(2); + hashToIds.Add(hash, bucket); + } + + bucket.Add(id); + } + } + } +#endif } } diff --git a/Runtime/Core/ProjectSetting/ProjectSettingAsset.cs b/Runtime/Core/ProjectSetting/ProjectSettingAsset.cs index 582508a..5dba01b 100644 --- a/Runtime/Core/ProjectSetting/ProjectSettingAsset.cs +++ b/Runtime/Core/ProjectSetting/ProjectSettingAsset.cs @@ -80,6 +80,8 @@ public enum FolderStructureType new FolderAddress { AssetType = (AssetFormat)13, AssetPath = "7_Misc"} }; public IReadOnlyList ProjectStructure => projectStructure; + [Header("Names")] + public List Names = new(); // Access values @@ -89,6 +91,11 @@ public string this[AssetFormat type] } // Public Functions + public void OnLoadedInGame() + { + // Initialize base Name store in editor + FName.OnProjectSettingLoaded(this); + } public Type GetGameInstanceType() { foreach (var assembly in AppDomain.CurrentDomain.GetAssemblies()) @@ -168,6 +175,7 @@ public FolderAddress GetFolderAddressByType(AssetFormat identity) return default(FolderAddress); } + } From e33bdaf4fc30c699cb6d7e9d42acb3d4dbb2dd08 Mon Sep 17 00:00:00 2001 From: Alijimpa Date: Mon, 9 Mar 2026 23:18:37 +0330 Subject: [PATCH 027/204] Implement First version fo Blackboard --- Runtime/Library/Interfaces/Blackboard.cs | 37 +++ Runtime/Library/Interfaces/Blackboard.cs.meta | 2 + Runtime/Library/Interfaces/Data.cs | 32 -- Runtime/Library/Interfaces/Data.cs.meta | 2 - .../SharedScripts/Classes/Blackboard.cs | 301 ++++++++++++++++++ .../SharedScripts/Classes/Blackboard.cs.meta | 2 + .../Pattern/DesignPatterns/BlackboardAsset.cs | 53 +++ ...aAsset.cs.meta => BlackboardAsset.cs.meta} | 0 .../Pattern/DesignPatterns/SharedDataAsset.cs | 160 ---------- Runtime/ReadySet/Presets/BlackboardAsset.meta | 8 - .../BlackboardAsset/BlackboardAsset.cs | 21 -- .../BlackboardAsset/BlackboardAsset.cs.meta | 2 - 12 files changed, 395 insertions(+), 225 deletions(-) create mode 100644 Runtime/Library/Interfaces/Blackboard.cs create mode 100644 Runtime/Library/Interfaces/Blackboard.cs.meta delete mode 100644 Runtime/Library/Interfaces/Data.cs delete mode 100644 Runtime/Library/Interfaces/Data.cs.meta create mode 100644 Runtime/Library/SharedScripts/Classes/Blackboard.cs create mode 100644 Runtime/Library/SharedScripts/Classes/Blackboard.cs.meta create mode 100644 Runtime/Pattern/DesignPatterns/BlackboardAsset.cs rename Runtime/Pattern/DesignPatterns/{SharedDataAsset.cs.meta => BlackboardAsset.cs.meta} (100%) delete mode 100644 Runtime/Pattern/DesignPatterns/SharedDataAsset.cs delete mode 100644 Runtime/ReadySet/Presets/BlackboardAsset.meta delete mode 100644 Runtime/ReadySet/Presets/BlackboardAsset/BlackboardAsset.cs delete mode 100644 Runtime/ReadySet/Presets/BlackboardAsset/BlackboardAsset.cs.meta diff --git a/Runtime/Library/Interfaces/Blackboard.cs b/Runtime/Library/Interfaces/Blackboard.cs new file mode 100644 index 0000000..ad8e101 --- /dev/null +++ b/Runtime/Library/Interfaces/Blackboard.cs @@ -0,0 +1,37 @@ +using UnityEngine; + +namespace RealMethod +{ + public interface IBlackboard + { + bool HasBool(FName name); + void SetBool(FName name, bool target); + bool GetBool(FName name); + bool HasInt(FName name); + void SetInt(FName name, int target); + int GetInt(FName name); + bool HasFloat(FName name); + void SetFloat(FName name, float target); + float GetFloat(FName name); + bool HasString(FName name); + void SetString(FName name, string target); + string GetString(FName name); + bool HasVector2(FName name); + void SetVector2(FName name, Vector2 target); + Vector2 GetVector2(FName name); + bool HasVector3(FName name); + void SetVector3(FName name, Vector3 target); + Vector3 GetVector3(FName name); + bool HasPefab(FName name); + void SetPrefab(FName name, Prefab target); + Prefab GetPrefab(FName name); + bool HasAsset(FName name); + void SetAsset(FName name, PrimitiveAsset target); + PrimitiveAsset GetAsset(FName name); + bool HasComponent(FName name); + void SetComponent(FName name, Component target); + Component GetComponent(FName name); + } + + +} \ No newline at end of file diff --git a/Runtime/Library/Interfaces/Blackboard.cs.meta b/Runtime/Library/Interfaces/Blackboard.cs.meta new file mode 100644 index 0000000..53e109b --- /dev/null +++ b/Runtime/Library/Interfaces/Blackboard.cs.meta @@ -0,0 +1,2 @@ +fileFormatVersion: 2 +guid: 937a63b2d30994f4abca77c0ef7a2a52 \ No newline at end of file diff --git a/Runtime/Library/Interfaces/Data.cs b/Runtime/Library/Interfaces/Data.cs deleted file mode 100644 index 26eeaa9..0000000 --- a/Runtime/Library/Interfaces/Data.cs +++ /dev/null @@ -1,32 +0,0 @@ - -namespace RealMethod -{ - public interface IBlackboardPure - { - void SetBool(string name, bool target); - bool GetBool(string name); - void SetByte(string name, byte target); - byte GetByte(string name); - void SetInt(string name, int target); - int GetInt(string name); - void SetFloat(string name, float target); - float GetFloat(string name); - } - public interface IBlackboardUnity : IBlackboardPure - { - void SetVector2(string name, UnityEngine.Vector2 target); - UnityEngine.Vector2 GetVector2(string name); - void SetVector3(string name, UnityEngine.Vector3 target); - UnityEngine.Vector3 GetVector3(string name); - void SetObject(string name, UnityEngine.Object target); - UnityEngine.Object GetObject(string name); - } - public interface IBlackboard : IBlackboardUnity - { - void SetIdentity(string name, IIdentifier target); - IIdentifier GetIdentity(string name); - void SetAsset(string name, PrimitiveAsset target); - PrimitiveAsset GetAsset(string name); - - } -} \ No newline at end of file diff --git a/Runtime/Library/Interfaces/Data.cs.meta b/Runtime/Library/Interfaces/Data.cs.meta deleted file mode 100644 index cf06fea..0000000 --- a/Runtime/Library/Interfaces/Data.cs.meta +++ /dev/null @@ -1,2 +0,0 @@ -fileFormatVersion: 2 -guid: 011d67550e3bcf84997ecc1ad3c34e57 \ No newline at end of file diff --git a/Runtime/Library/SharedScripts/Classes/Blackboard.cs b/Runtime/Library/SharedScripts/Classes/Blackboard.cs new file mode 100644 index 0000000..64c3023 --- /dev/null +++ b/Runtime/Library/SharedScripts/Classes/Blackboard.cs @@ -0,0 +1,301 @@ +using System; +using UnityEngine; + +namespace RealMethod +{ + [Serializable] + public struct Blackboard + { + private enum ValueType + { + None = 0, + Bool = 1, + Int = 2, + Float = 3, + String = 4, + Vector2 = 5, + Vector3 = 6, + Prefab = 7, + Asset = 8, + Component = 10, + } + [Serializable] + private struct ValuePointer + { + [field: SerializeField] + public Hash128 Name { get; private set; } + [field: SerializeField] + public ValueType Type { get; private set; } + [field: SerializeField] + public int Index { get; private set; } + public bool IsValid => Type != ValueType.None; + + public ValuePointer(FName Vname, ValueType Vtype, int Vindex = -1) + { + if (Vtype != ValueType.None) + { + Name = Hash128.Compute(Vname); + Type = Vtype; + Index = Vindex; + } + else + { + Debug.LogWarning("Value didnt store in Blackboard,Type is None"); + Name = Hash128.Compute(string.Empty); + Type = ValueType.None; + Index = -1; + } + } + public void Clear() + { + Name = Hash128.Compute(string.Empty); + Type = ValueType.None; + Index = -1; + } + } + + [SerializeField, ReadOnly] + private ValuePointer[] Variables; + [SerializeField, ReadOnly] + private bool[] Boolean; + [SerializeField, ReadOnly] + private int[] Intiger; + [SerializeField, ReadOnly] + private float[] Float; + [SerializeField, ReadOnly] + private string[] String; + [SerializeField, ReadOnly] + private Vector2[] Vector2; + [SerializeField, ReadOnly] + private Vector3[] Vector3; + [SerializeField, ReadOnly] + private Prefab[] Prefab; + [SerializeField, ReadOnly] + private PrimitiveAsset[] Asset; + [SerializeField, ReadOnly] + private Component[] Component; + public int Length + { + get + { + int result = 0; + foreach (var item in Variables) + { + if (item.IsValid) + { + result++; + } + } + return result; + } + } + public int MaxSize + { + get + { + return Boolean.Length; + } + } + + public Blackboard(int size = 10) + { + int TypesCount = Enum.GetValues(typeof(ValueType)).Length - 1; + Variables = new ValuePointer[size * TypesCount]; + Boolean = new bool[size]; + Intiger = new int[size]; + Float = new float[size]; + String = new string[size]; + Vector2 = new Vector2[size]; + Vector3 = new Vector3[size]; + Prefab = new Prefab[size]; + Asset = new PrimitiveAsset[size]; + Component = new Component[size]; + } + + public bool HasValue(FName VariableName) + { + return TryFindPointer(VariableName, out ValuePointer outher); + } + public T GetValue(FName VariableName) + { + if (TryFindPointer(VariableName, out ValuePointer item)) + { + object result = item.Type switch + { + ValueType.Bool => Boolean[item.Index], + ValueType.Int => Intiger[item.Index], + ValueType.Float => Float[item.Index], + ValueType.String => String[item.Index], + ValueType.Vector2 => Vector2[item.Index], + ValueType.Vector3 => Vector3[item.Index], + ValueType.Prefab => Prefab[item.Index], + ValueType.Asset => Asset[item.Index], + ValueType.Component => Component[item.Index], + _ => null + }; + + if (result is T finalValue) + return finalValue; + + throw new InvalidCastException($"Variable '{VariableName}' is type {item.Type} but requested {typeof(T)}"); + } + + Debug.LogWarning($"Variable '{VariableName}' not found."); + return default; + } + public void SetValue(FName VariableName, T value) + { + if (TryFindPointer(VariableName, out ValuePointer item)) + { + SetValue(value, item.Index); + } + else + { + CreateValue(VariableName, value); + } + } + public bool CreateValue(FName VariableName, T DefaultValue) + { + ValueType TargetType = ConvertType(); + int TypeIndex = GetLengthByType(TargetType); + if (TypeIndex < MaxSize - 1) + { + if (SetValue(DefaultValue, TypeIndex)) + { + Variables[Length] = new ValuePointer(VariableName, TargetType, TypeIndex); + return true; + } + else + { + return false; + } + } + else + { + Debug.LogWarning($"Blackboard for Variable of {typeof(T)} is full"); + return false; + } + } + public bool RemoveValue(FName VariableName) + { + if (TryFindPointer(VariableName, out ValuePointer item)) + { + item.Clear(); + return true; + } + return false; + } + public void SetSize(int size) + { + int TypesCount = Enum.GetValues(typeof(ValueType)).Length - 1; + if (Variables == null || Variables.Length == 0) Variables = new ValuePointer[size * TypesCount]; + if (Boolean == null || Boolean.Length == 0) Boolean = new bool[size]; + if (Intiger == null || Intiger.Length == 0) Intiger = new int[size]; + if (Float == null || Float.Length == 0) Float = new float[size]; + if (String == null || String.Length == 0) String = new string[size]; + if (Vector2 == null || Vector2.Length == 0) Vector2 = new Vector2[size]; + if (Vector3 == null || Vector3.Length == 0) Vector3 = new Vector3[size]; + if (Prefab == null || Prefab.Length == 0) Prefab = new Prefab[size]; + if (Asset == null || Asset.Length == 0) Asset = new PrimitiveAsset[size]; + if (Component == null || Component.Length == 0) Component = new Component[size]; + } + public void Clear() + { + SetSize(MaxSize); + } + + private bool TryFindPointer(FName VariableName, out ValuePointer pointer) + { + Hash128 TargetName = Hash128.Compute(VariableName); + ValueType TargetType = ConvertType(); + foreach (var item in Variables) + { + if (item.Type == TargetType) + { + if (item.Name == TargetName) + { + pointer = item; + return true; + } + } + } + pointer = new ValuePointer(); + return false; + } + private int GetLengthByType(ValueType TargetType) + { + int result = 0; + foreach (var item in Variables) + { + if (item.Type == TargetType) + { + if (item.Index > result) + { + result = item.Index; + } + else + { + if (item.Index == result) + result++; + } + } + } + return result; + } + private ValueType ConvertType() + { + if (typeof(T) == typeof(bool)) { return ValueType.Bool; } + else if (typeof(T) == typeof(int)) { return ValueType.Int; } + else if (typeof(T) == typeof(float)) { return ValueType.Float; } + else if (typeof(T) == typeof(string)) { return ValueType.String; } + else if (typeof(T) == typeof(Vector2)) { return ValueType.Vector2; } + else if (typeof(T) == typeof(Vector3)) { return ValueType.Vector3; } + else if (typeof(T) == typeof(Prefab)) { return ValueType.Prefab; } + else if (typeof(T) == typeof(PrimitiveAsset)) { return ValueType.Asset; } + else if (typeof(T) == typeof(Component)) { return ValueType.Component; } + else { return ValueType.None; } + } + private bool SetValue(T value, int index) + { + if (index >= MaxSize) + { + Debug.LogError($"For this index {index} of {typeof(T)} didn't have any slot"); + return false; + } + switch (value) + { + case bool v: + Boolean[index] = v; + return true; + case int v: + Intiger[index] = v; + return true; + case float v: + Float[index] = v; + return true; + case string v: + String[index] = v; + return true; + case Vector2 v: + Vector2[index] = v; + return true; + case Vector3 v: + Vector3[index] = v; + return true; + case Prefab v: + Prefab[index] = v; + return true; + case PrimitiveAsset v: + Asset[index] = v; + return true; + case Component v: + Component[index] = v; + return true; + default: + Debug.LogError($"Type {typeof(T)} is not supported."); + return false; + } + } + } + +} \ No newline at end of file diff --git a/Runtime/Library/SharedScripts/Classes/Blackboard.cs.meta b/Runtime/Library/SharedScripts/Classes/Blackboard.cs.meta new file mode 100644 index 0000000..6f3e8fc --- /dev/null +++ b/Runtime/Library/SharedScripts/Classes/Blackboard.cs.meta @@ -0,0 +1,2 @@ +fileFormatVersion: 2 +guid: 2c2ddfb1230605e45a3c934f06e0209d \ No newline at end of file diff --git a/Runtime/Pattern/DesignPatterns/BlackboardAsset.cs b/Runtime/Pattern/DesignPatterns/BlackboardAsset.cs new file mode 100644 index 0000000..4103fb6 --- /dev/null +++ b/Runtime/Pattern/DesignPatterns/BlackboardAsset.cs @@ -0,0 +1,53 @@ +using UnityEngine; + +namespace RealMethod +{ + public abstract class BlackboardAsset : UniqueAsset, IBlackboard + { + public Blackboard Blackboard; + + // Implement IBlackboard Interface + public bool HasBool(FName name) => Blackboard.HasValue(name); + public void SetBool(FName name, bool target) => Blackboard.SetValue(name, target); + public bool GetBool(FName name) => Blackboard.GetValue(name); + public bool HasInt(FName name) => Blackboard.HasValue(name); + public void SetInt(FName name, int target) => Blackboard.SetValue(name, target); + public int GetInt(FName name) => Blackboard.GetValue(name); + public bool HasFloat(FName name) => Blackboard.HasValue(name); + public void SetFloat(FName name, float target) => Blackboard.SetValue(name, target); + public float GetFloat(FName name) => Blackboard.GetValue(name); + public bool HasString(FName name) => Blackboard.HasValue(name); + public void SetString(FName name, string target) => Blackboard.SetValue(name, target); + public string GetString(FName name) => Blackboard.GetValue(name); + public bool HasVector2(FName name) => Blackboard.HasValue(name); + public void SetVector2(FName name, Vector2 target) => Blackboard.SetValue(name, target); + public Vector2 GetVector2(FName name) => Blackboard.GetValue(name); + public bool HasVector3(FName name) => Blackboard.HasValue(name); + public void SetVector3(FName name, Vector3 target) => Blackboard.SetValue(name, target); + public Vector3 GetVector3(FName name) => Blackboard.GetValue(name); + public bool HasPefab(FName name) => Blackboard.HasValue(name); + public void SetPrefab(FName name, Prefab target) => Blackboard.SetValue(name, target); + public Prefab GetPrefab(FName name) => Blackboard.GetValue(name); + public bool HasAsset(FName name) => Blackboard.HasValue(name); + public void SetAsset(FName name, PrimitiveAsset target) => Blackboard.SetValue(name, target); + public PrimitiveAsset GetAsset(FName name) => Blackboard.GetValue(name); + public bool HasComponent(FName name) => Blackboard.HasValue(name); + public void SetComponent(FName name, Component target) => Blackboard.SetValue(name, target); + public Component GetComponent(FName name) => Blackboard.GetValue(name); + + + protected override void OnEnable() + { + Blackboard.SetSize(GetMaxSize()); + } + + [ContextMenu("Resize")] + private void OnResetSize() + { + Blackboard = new Blackboard(GetMaxSize()); + } + + // Abstract Methods + protected abstract int GetMaxSize(); + } +} \ No newline at end of file diff --git a/Runtime/Pattern/DesignPatterns/SharedDataAsset.cs.meta b/Runtime/Pattern/DesignPatterns/BlackboardAsset.cs.meta similarity index 100% rename from Runtime/Pattern/DesignPatterns/SharedDataAsset.cs.meta rename to Runtime/Pattern/DesignPatterns/BlackboardAsset.cs.meta diff --git a/Runtime/Pattern/DesignPatterns/SharedDataAsset.cs b/Runtime/Pattern/DesignPatterns/SharedDataAsset.cs deleted file mode 100644 index 6498c1d..0000000 --- a/Runtime/Pattern/DesignPatterns/SharedDataAsset.cs +++ /dev/null @@ -1,160 +0,0 @@ -using UnityEngine; - -namespace RealMethod -{ - // SharedDataAsset is a asset that can sore data by diffrent type - public abstract class SharedDataAsset : UniqueAsset, IBlackboard - { - [System.Serializable] - private class BB_Vector2_Dictionary : SerializableDictionary { } - [System.Serializable] - private class BB_Vector3_Dictionary : SerializableDictionary { } - [System.Serializable] - private class BB_Object_Dictionary : SerializableDictionary { } - [System.Serializable] - private class BB_Identity_Dictionary : SerializableDictionary { } - [Header("DataBase")] - [SerializeField, ReadOnly] - private StringBoolDictionary boolData; - [SerializeField, ReadOnly] - private StringByteDictionary byteData; - [SerializeField, ReadOnly] - private StringIntDictionary intData; - [SerializeField, ReadOnly] - private StringFloatDictionary floatData; - [SerializeField, ReadOnly] - private BB_Vector2_Dictionary vector2Data; - [SerializeField, ReadOnly] - private BB_Vector3_Dictionary vector3Data; - [SerializeField, ReadOnly] - private BB_Object_Dictionary objectData; - [SerializeField, ReadOnly] - private StringAssetObjectDictionary assetData; - [SerializeField, ReadOnly] - private BB_Identity_Dictionary idData; - - - public IBlackboard Provider => this; - public System.Action OnBlackBoardChanged; - public System.Action OnValueChanged; - - - - // Implement IBlackboardPure Interface - public void SetBool(string name, bool target) - { - SetValue(boolData, name, target); - } - public bool GetBool(string name) - { - return GetValue(boolData, name); - } - public void SetByte(string name, byte target) - { - SetValue(byteData, name, target); - } - public byte GetByte(string name) - { - return GetValue(byteData, name); - } - public void SetInt(string name, int target) - { - SetValue(intData, name, target); - } - public int GetInt(string name) - { - return GetValue(intData, name); - } - public void SetFloat(string name, float target) - { - SetValue(floatData, name, target); - } - public float GetFloat(string name) - { - return GetValue(floatData, name); - } - - // Implement IBlackboardUnity Interface - public void SetVector2(string name, Vector2 target) - { - SetValue(vector2Data, name, target); - } - public Vector2 GetVector2(string name) - { - return GetValue(vector2Data, name); - } - public void SetVector3(string name, Vector3 target) - { - SetValue(vector3Data, name, target); - } - public Vector3 GetVector3(string name) - { - return GetValue(vector3Data, name); - } - public void SetObject(string name, Object target) - { - SetValue(objectData, name, target); - } - public Object GetObject(string name) - { - return GetValue(objectData, name); - } - - // Implement IBlackboard Interface - public void SetIdentity(string name, IIdentifier target) - { - SetValue(idData, name, target); - } - public IIdentifier GetIdentity(string name) - { - return GetValue(idData, name); - } - public void SetAsset(string name, PrimitiveAsset target) - { - SetValue(assetData, name, target); - } - public PrimitiveAsset GetAsset(string name) - { - return GetValue(assetData, name); - } - - - - protected void SetValue(SerializableDictionary dic, string name, TValue value) - { - dic.Add(name, value); - OnBlackBoardChanged?.Invoke(Provider); - OnValueChanged?.Invoke(name); - } - protected TValue GetValue(SerializableDictionary dic, string name) - { - if (dic.TryGetValue(name, out TValue val)) - { - return val; - } - else - { - Debug.LogWarning($"[{name}]: Variable With name '{name}' didn't find in DataBase"); - return default; - } - } - - -#if UNITY_EDITOR - public override void OnEditorPlay() - { - boolData.Clear(); - byteData.Clear(); - intData.Clear(); - floatData.Clear(); - vector2Data.Clear(); - vector3Data.Clear(); - objectData.Clear(); - assetData.Clear(); - idData.Clear(); - } -#endif - - - } -} \ No newline at end of file diff --git a/Runtime/ReadySet/Presets/BlackboardAsset.meta b/Runtime/ReadySet/Presets/BlackboardAsset.meta deleted file mode 100644 index 81e0d21..0000000 --- a/Runtime/ReadySet/Presets/BlackboardAsset.meta +++ /dev/null @@ -1,8 +0,0 @@ -fileFormatVersion: 2 -guid: 62f1695444e933c4a91e447b85a2378a -folderAsset: yes -DefaultImporter: - externalObjects: {} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Runtime/ReadySet/Presets/BlackboardAsset/BlackboardAsset.cs b/Runtime/ReadySet/Presets/BlackboardAsset/BlackboardAsset.cs deleted file mode 100644 index 802017f..0000000 --- a/Runtime/ReadySet/Presets/BlackboardAsset/BlackboardAsset.cs +++ /dev/null @@ -1,21 +0,0 @@ -using UnityEngine; - -namespace RealMethod -{ - [CreateAssetMenu(fileName = "Blackboard", menuName = "RealMethod/Misc/Blackboard", order = 1)] - public sealed class BlackboardAsset : SharedDataAsset - { - [Header("Blackboard")] - [SerializeField] - private bool ResetOnPlay = false; - - -#if UNITY_EDITOR - public override void OnEditorPlay() - { - if (ResetOnPlay) - base.OnEditorPlay(); - } -#endif - } -} \ No newline at end of file diff --git a/Runtime/ReadySet/Presets/BlackboardAsset/BlackboardAsset.cs.meta b/Runtime/ReadySet/Presets/BlackboardAsset/BlackboardAsset.cs.meta deleted file mode 100644 index a120590..0000000 --- a/Runtime/ReadySet/Presets/BlackboardAsset/BlackboardAsset.cs.meta +++ /dev/null @@ -1,2 +0,0 @@ -fileFormatVersion: 2 -guid: f5ea7694f7fc6e041a03d91d630b159a \ No newline at end of file From 9f7202c0e7a9ff46e9565f587ccbb220811a9a14 Mon Sep 17 00:00:00 2001 From: Alijimpa Date: Tue, 10 Mar 2026 07:48:28 +0330 Subject: [PATCH 028/204] Beta Version FName --- Editor/Core/Definitions/FName_Drawer.cs | 9 +- Runtime/Core/Definitions/FName.cs | 107 ++++++++++++++++-------- 2 files changed, 78 insertions(+), 38 deletions(-) diff --git a/Editor/Core/Definitions/FName_Drawer.cs b/Editor/Core/Definitions/FName_Drawer.cs index 7f52988..8bb78b0 100644 --- a/Editor/Core/Definitions/FName_Drawer.cs +++ b/Editor/Core/Definitions/FName_Drawer.cs @@ -27,7 +27,14 @@ public override void OnGUI(Rect position, SerializedProperty property, GUIConten idProp.intValue = FName.GetOrCreateId(newValue); } - EditorGUI.EndProperty(); + + + // --- Set GUI color to blue to indicate change --- + // Color prevColor = GUI.color; + // GUI.color = Color.gray; // light blue + // EditorGUI.TextField(position, label, current); + // GUI.color = prevColor; + // EditorGUI.EndProperty(); } } diff --git a/Runtime/Core/Definitions/FName.cs b/Runtime/Core/Definitions/FName.cs index 4920e4a..851d30e 100644 --- a/Runtime/Core/Definitions/FName.cs +++ b/Runtime/Core/Definitions/FName.cs @@ -2,7 +2,9 @@ using System.Collections.Generic; using UnityEngine; + #if UNITY_EDITOR +using UnityEditor; using UnityEditor.Callbacks; #endif @@ -19,27 +21,39 @@ public struct FName : IEquatable /// Maximum allowed characters for a name. /// public const int MaxLength = 1024; - /// /// Internal identifier referencing the global name table. /// [SerializeField] private int id; - /// /// Stores strings by ID. /// private static readonly List idToName = new List(256); - /// /// Hash → list of IDs (collision bucket). /// private static readonly Dictionary> hashToIds = new Dictionary>(256); - /// /// Lock for thread-safe name registration. /// private static readonly object tableLock = new object(); +#if UNITY_EDITOR + private static bool editorInitialized = false; + private static ProjectSettingAsset _settings; + private static ProjectSettingAsset ProjectSettings + { + get + { + if (editorInitialized && _settings == null && !Application.isPlaying) + { + _settings = AssetDatabase.LoadAssetAtPath("Assets/RealMethod/RealMethodSetting.asset"); + } + return _settings; + } + } +#endif + /// /// Creates a Name from a string. @@ -50,10 +64,12 @@ public FName(string value) } + ////////// Static Functions /// - /// Called when Editor opend and restored all staring saved in editor time + /// Called at runtime during game load projectsetting + /// The projectsetting after load call these function with self refrence /// - /// + /// ProjectSetting instance loaded at runtime public static void OnProjectSettingLoaded(ProjectSettingAsset setting) { if (setting == null) @@ -131,19 +147,18 @@ public static int GetOrCreateId(string value) bucket.Add(newId); #if UNITY_EDITOR - ProjectSettingAsset ProjectSettings = Resources.Load("RealMethod/RealMethodSetting"); - if (ProjectSettings == null) + if (ProjectSettings != null) { - Debug.LogError("ProjectSettingAsset is missing from Resources folder!"); - return 0; + ProjectSettings.Names = idToName; + } + else + { + Debug.LogWarning("ProjectSettingAsset'NamesTable can't update, ProjectSettingAsset is not valid!"); } - ProjectSettings.Names = idToName; #endif - return newId; } } - /// /// Returns the string for an ID. /// @@ -155,6 +170,21 @@ public static string GetString(int id) return idToName[id]; } + + + ////////// Functions + /// + /// Checks equality with another Name. + /// + public bool Equals(FName other) + { + return id == other.id; + } + + + + + ////////// Overrides /// /// Converts Name to string. /// @@ -162,7 +192,24 @@ public override string ToString() { return GetString(id); } + /// + /// Checks equality with an object. + /// + public override bool Equals(object obj) + { + return obj is FName other && Equals(other); + } + /// + /// Hash code of the Name. + /// + public override int GetHashCode() + { + return id; + } + + + ////////// Operators /// /// Implicit conversion from string. /// @@ -195,39 +242,25 @@ public static implicit operator string(FName name) return a.id != b.id; } - /// - /// Checks equality with another Name. - /// - public bool Equals(FName other) - { - return id == other.id; - } - /// - /// Checks equality with an object. - /// - public override bool Equals(object obj) - { - return obj is FName other && Equals(other); - } - - /// - /// Hash code of the Name. - /// - public override int GetHashCode() - { - return id; - } #if UNITY_EDITOR + [InitializeOnLoadMethod] + private static void MarkEditorReady() + { + editorInitialized = true; + _settings = Resources.Load("RealMethod/RealMethodSetting"); + } [DidReloadScripts] private static void OnScriptsReloaded() { - ProjectSettingAsset ProjectSettings = Resources.Load("RealMethod/RealMethodSetting"); + editorInitialized = true; + if (ProjectSettings == null) { - Debug.LogError("ProjectSettingAsset is missing from Resources folder!"); + Debug.LogWarning("Static NamesTable can't update, ProjectSettingAsset is not valid!"); + return; } lock (tableLock) From abcd1070d9a1df1e44c63ab195cc0806146b309c Mon Sep 17 00:00:00 2001 From: Alijimpa Date: Tue, 10 Mar 2026 09:43:42 +0330 Subject: [PATCH 029/204] Implement Variable for Store Name 6 char --- Editor/Core/Definitions/FName_Drawer.cs | 41 ------ Editor/Core/Definitions/Name16_Drawer.cs | 49 +++++++ ...e_Drawer.cs.meta => Name16_Drawer.cs.meta} | 0 Runtime/Core/Definitions/Identifier.cs | 2 +- Runtime/Core/Definitions/Name16.cs | 132 ++++++++++++++++++ .../{FName.cs.meta => Name16.cs.meta} | 0 Runtime/Core/Definitions/Prefab.cs | 2 +- .../ProjectSetting/ProjectSettingAsset.cs | 2 +- Runtime/Library/Interfaces/Blackboard.cs | 54 +++---- .../SharedScripts/Classes/Blackboard.cs | 14 +- Runtime/Pattern/DataAssets/ItemAsset.cs | 2 +- Runtime/Pattern/DataAssets/ItemConfig.cs | 2 +- .../Pattern/DesignPatterns/BlackboardAsset.cs | 54 +++---- Runtime/Pattern/Managers/HapticManager.cs | 4 +- Runtime/Toolkit/Ability/AbilityAsset.cs | 2 +- Runtime/Toolkit/PCG/Assets/PCGCashAsset.cs | 2 +- .../Toolkit/PCG/Assets/PCGResourceConfig.cs | 2 +- Runtime/Toolkit/RPG/Resource/ResourceData.cs | 2 +- Runtime/Toolkit/RPG/StatSystem/BuffConfig.cs | 2 +- Runtime/Toolkit/RPG/StatSystem/StatData.cs | 2 +- Runtime/Toolkit/RPG/StatSystem/StatProfile.cs | 2 +- Runtime/Toolkit/Tutorial/TutorialConfig.cs | 2 +- .../Definitions => Tests/General}/FName.cs | 10 +- Tests/General/FName.cs.meta | 2 + 24 files changed, 263 insertions(+), 123 deletions(-) delete mode 100644 Editor/Core/Definitions/FName_Drawer.cs create mode 100644 Editor/Core/Definitions/Name16_Drawer.cs rename Editor/Core/Definitions/{FName_Drawer.cs.meta => Name16_Drawer.cs.meta} (100%) create mode 100644 Runtime/Core/Definitions/Name16.cs rename Runtime/Core/Definitions/{FName.cs.meta => Name16.cs.meta} (100%) rename {Runtime/Core/Definitions => Tests/General}/FName.cs (99%) create mode 100644 Tests/General/FName.cs.meta diff --git a/Editor/Core/Definitions/FName_Drawer.cs b/Editor/Core/Definitions/FName_Drawer.cs deleted file mode 100644 index 8bb78b0..0000000 --- a/Editor/Core/Definitions/FName_Drawer.cs +++ /dev/null @@ -1,41 +0,0 @@ -using UnityEditor; -using UnityEngine; - -namespace RealMethod.Editor -{ - [CustomPropertyDrawer(typeof(FName))] - public class FName_Drawer : PropertyDrawer - { - public override void OnGUI(Rect position, SerializedProperty property, GUIContent label) - { - SerializedProperty idProp = property.FindPropertyRelative("id"); - - if (idProp == null) - { - EditorGUI.LabelField(position, label.text, "id field not found"); - return; - } - - string current = FName.GetString(idProp.intValue); - - EditorGUI.BeginProperty(position, label, property); - - string newValue = EditorGUI.DelayedTextField(position, label, current); - - if (newValue != current) - { - idProp.intValue = FName.GetOrCreateId(newValue); - } - - - - // --- Set GUI color to blue to indicate change --- - // Color prevColor = GUI.color; - // GUI.color = Color.gray; // light blue - // EditorGUI.TextField(position, label, current); - // GUI.color = prevColor; - // EditorGUI.EndProperty(); - } - } - -} \ No newline at end of file diff --git a/Editor/Core/Definitions/Name16_Drawer.cs b/Editor/Core/Definitions/Name16_Drawer.cs new file mode 100644 index 0000000..aeb2001 --- /dev/null +++ b/Editor/Core/Definitions/Name16_Drawer.cs @@ -0,0 +1,49 @@ +using UnityEditor; +using UnityEngine; + +namespace RealMethod.Editor +{ + [CustomPropertyDrawer(typeof(Name16))] + public class Name16Drawer : PropertyDrawer + { + const int MaxLength = 16; + static readonly Color Tint = new Color(1f, 0.82f, 0.9f); // very light pink + + + public override void OnGUI(Rect position, SerializedProperty property, GUIContent label) + { + var aProp = property.FindPropertyRelative("Name_A"); + var bProp = property.FindPropertyRelative("Name_B"); + + Name16 value = new Name16(); + value.Name_A = (ulong)aProp.longValue; + value.Name_B = (ulong)bProp.longValue; + + string text = value.ToString(); + + EditorGUI.BeginProperty(position, label, property); + + Color oldColor = GUI.color; + GUI.color = Tint; // apply pink tint + + EditorGUI.BeginChangeCheck(); + string newText = EditorGUI.TextField(position, label, text); + + GUI.color = oldColor; // restore color + + if (EditorGUI.EndChangeCheck()) + { + if (newText.Length > MaxLength) + newText = newText.Substring(0, MaxLength); + + Name16 newValue = new Name16(newText); + + aProp.longValue = (long)newValue.Name_A; + bProp.longValue = (long)newValue.Name_B; + } + + EditorGUI.EndProperty(); + } + } + +} \ No newline at end of file diff --git a/Editor/Core/Definitions/FName_Drawer.cs.meta b/Editor/Core/Definitions/Name16_Drawer.cs.meta similarity index 100% rename from Editor/Core/Definitions/FName_Drawer.cs.meta rename to Editor/Core/Definitions/Name16_Drawer.cs.meta diff --git a/Runtime/Core/Definitions/Identifier.cs b/Runtime/Core/Definitions/Identifier.cs index cca2609..7684999 100644 --- a/Runtime/Core/Definitions/Identifier.cs +++ b/Runtime/Core/Definitions/Identifier.cs @@ -2,6 +2,6 @@ namespace RealMethod { public interface IIdentifier { - FName NameID { get; } + Name16 NameID { get; } } } \ No newline at end of file diff --git a/Runtime/Core/Definitions/Name16.cs b/Runtime/Core/Definitions/Name16.cs new file mode 100644 index 0000000..d72559d --- /dev/null +++ b/Runtime/Core/Definitions/Name16.cs @@ -0,0 +1,132 @@ +using System; +using System.Text; +using UnityEngine; + + + +namespace RealMethod +{ + /// + /// Lightweight engine-style string identifier. + /// Stores only an integer ID while the actual strings live in a global table. + /// + [Serializable] + public struct Name16 + { + [SerializeField] + public ulong Name_A; + [SerializeField] + public ulong Name_B; + + /// + /// Creates a Name from a string. + /// + public Name16(string value) + { + if (value.Length > 16) + throw new ArgumentException($"Name cannot exceed {16} characters."); + + Name_A = 0; + Name_B = 0; + + if (string.IsNullOrEmpty(value)) + return; + + int len = Math.Min(16, value.Length); + + for (int i = 0; i < len; i++) + { + byte b = (byte)value[i]; + + if (i < 8) + Name_A |= ((ulong)b) << (i * 8); + else + Name_B |= ((ulong)b) << ((i - 8) * 8); + } + } + + + /// + /// Checks equality with another Name. + /// + public bool Equals(Name16 other) + { + return this == other; + } + + + /// + /// Converts Name to string. + /// + public override string ToString() + { + Span bytes = stackalloc byte[16]; + + for (int i = 0; i < 8; i++) + bytes[i] = (byte)((Name_A >> (i * 8)) & 0xFF); + + for (int i = 0; i < 8; i++) + bytes[i + 8] = (byte)((Name_B >> (i * 8)) & 0xFF); + + int len = 16; + while (len > 0 && bytes[len - 1] == 0) + len--; + + return Encoding.ASCII.GetString(bytes.Slice(0, len)); + } + /// + /// Checks equality with an object. + /// + public override bool Equals(object obj) + { + return obj is Name16 other && Equals(other); + } + /// + /// Hash code of the Name. + /// + public override int GetHashCode() + { + return HashCode.Combine(Name_A, Name_B); + } + + + + /// + /// Implicit conversion from string. + /// + public static implicit operator Name16(string value) + { + return new Name16(value); + } + /// + /// Implicit conversion to string. + /// + public static implicit operator string(Name16 value) + { + return value.ToString(); + } + /// + /// Equality operator. + /// + public static bool operator ==(Name16 a, Name16 b) + { + return a.Name_A == b.Name_A && a.Name_B == b.Name_B; + } + /// + /// Inequality operator. + /// + public static bool operator !=(Name16 a, Name16 b) + { + return !(a == b); + } + + } + + + + +} + + + + diff --git a/Runtime/Core/Definitions/FName.cs.meta b/Runtime/Core/Definitions/Name16.cs.meta similarity index 100% rename from Runtime/Core/Definitions/FName.cs.meta rename to Runtime/Core/Definitions/Name16.cs.meta diff --git a/Runtime/Core/Definitions/Prefab.cs b/Runtime/Core/Definitions/Prefab.cs index 933a14e..5923624 100644 --- a/Runtime/Core/Definitions/Prefab.cs +++ b/Runtime/Core/Definitions/Prefab.cs @@ -10,7 +10,7 @@ public abstract class PrefabCore : IIdentifier [SerializeField] private GameObject PrefabAsset; // <-- this name must match public GameObject asset => PrefabAsset; - public FName NameID => PrefabAsset != null ? PrefabAsset.name : "Empty"; + public Name16 NameID => PrefabAsset != null ? PrefabAsset.name : "Empty"; // Public Functions public J GetSoftClass() where J : Component diff --git a/Runtime/Core/ProjectSetting/ProjectSettingAsset.cs b/Runtime/Core/ProjectSetting/ProjectSettingAsset.cs index 5dba01b..e11b50f 100644 --- a/Runtime/Core/ProjectSetting/ProjectSettingAsset.cs +++ b/Runtime/Core/ProjectSetting/ProjectSettingAsset.cs @@ -94,7 +94,7 @@ public string this[AssetFormat type] public void OnLoadedInGame() { // Initialize base Name store in editor - FName.OnProjectSettingLoaded(this); + ///Name16.OnProjectSettingLoaded(this); } public Type GetGameInstanceType() { diff --git a/Runtime/Library/Interfaces/Blackboard.cs b/Runtime/Library/Interfaces/Blackboard.cs index ad8e101..eb36f56 100644 --- a/Runtime/Library/Interfaces/Blackboard.cs +++ b/Runtime/Library/Interfaces/Blackboard.cs @@ -4,33 +4,33 @@ namespace RealMethod { public interface IBlackboard { - bool HasBool(FName name); - void SetBool(FName name, bool target); - bool GetBool(FName name); - bool HasInt(FName name); - void SetInt(FName name, int target); - int GetInt(FName name); - bool HasFloat(FName name); - void SetFloat(FName name, float target); - float GetFloat(FName name); - bool HasString(FName name); - void SetString(FName name, string target); - string GetString(FName name); - bool HasVector2(FName name); - void SetVector2(FName name, Vector2 target); - Vector2 GetVector2(FName name); - bool HasVector3(FName name); - void SetVector3(FName name, Vector3 target); - Vector3 GetVector3(FName name); - bool HasPefab(FName name); - void SetPrefab(FName name, Prefab target); - Prefab GetPrefab(FName name); - bool HasAsset(FName name); - void SetAsset(FName name, PrimitiveAsset target); - PrimitiveAsset GetAsset(FName name); - bool HasComponent(FName name); - void SetComponent(FName name, Component target); - Component GetComponent(FName name); + bool HasBool(Name16 name); + void SetBool(Name16 name, bool target); + bool GetBool(Name16 name); + bool HasInt(Name16 name); + void SetInt(Name16 name, int target); + int GetInt(Name16 name); + bool HasFloat(Name16 name); + void SetFloat(Name16 name, float target); + float GetFloat(Name16 name); + bool HasString(Name16 name); + void SetString(Name16 name, string target); + string GetString(Name16 name); + bool HasVector2(Name16 name); + void SetVector2(Name16 name, Vector2 target); + Vector2 GetVector2(Name16 name); + bool HasVector3(Name16 name); + void SetVector3(Name16 name, Vector3 target); + Vector3 GetVector3(Name16 name); + bool HasPefab(Name16 name); + void SetPrefab(Name16 name, Prefab target); + Prefab GetPrefab(Name16 name); + bool HasAsset(Name16 name); + void SetAsset(Name16 name, PrimitiveAsset target); + PrimitiveAsset GetAsset(Name16 name); + bool HasComponent(Name16 name); + void SetComponent(Name16 name, Component target); + Component GetComponent(Name16 name); } diff --git a/Runtime/Library/SharedScripts/Classes/Blackboard.cs b/Runtime/Library/SharedScripts/Classes/Blackboard.cs index 64c3023..a2c4e2e 100644 --- a/Runtime/Library/SharedScripts/Classes/Blackboard.cs +++ b/Runtime/Library/SharedScripts/Classes/Blackboard.cs @@ -30,7 +30,7 @@ private struct ValuePointer public int Index { get; private set; } public bool IsValid => Type != ValueType.None; - public ValuePointer(FName Vname, ValueType Vtype, int Vindex = -1) + public ValuePointer(Name16 Vname, ValueType Vtype, int Vindex = -1) { if (Vtype != ValueType.None) { @@ -112,11 +112,11 @@ public Blackboard(int size = 10) Component = new Component[size]; } - public bool HasValue(FName VariableName) + public bool HasValue(Name16 VariableName) { return TryFindPointer(VariableName, out ValuePointer outher); } - public T GetValue(FName VariableName) + public T GetValue(Name16 VariableName) { if (TryFindPointer(VariableName, out ValuePointer item)) { @@ -143,7 +143,7 @@ public T GetValue(FName VariableName) Debug.LogWarning($"Variable '{VariableName}' not found."); return default; } - public void SetValue(FName VariableName, T value) + public void SetValue(Name16 VariableName, T value) { if (TryFindPointer(VariableName, out ValuePointer item)) { @@ -154,7 +154,7 @@ public void SetValue(FName VariableName, T value) CreateValue(VariableName, value); } } - public bool CreateValue(FName VariableName, T DefaultValue) + public bool CreateValue(Name16 VariableName, T DefaultValue) { ValueType TargetType = ConvertType(); int TypeIndex = GetLengthByType(TargetType); @@ -176,7 +176,7 @@ public bool CreateValue(FName VariableName, T DefaultValue) return false; } } - public bool RemoveValue(FName VariableName) + public bool RemoveValue(Name16 VariableName) { if (TryFindPointer(VariableName, out ValuePointer item)) { @@ -204,7 +204,7 @@ public void Clear() SetSize(MaxSize); } - private bool TryFindPointer(FName VariableName, out ValuePointer pointer) + private bool TryFindPointer(Name16 VariableName, out ValuePointer pointer) { Hash128 TargetName = Hash128.Compute(VariableName); ValueType TargetType = ConvertType(); diff --git a/Runtime/Pattern/DataAssets/ItemAsset.cs b/Runtime/Pattern/DataAssets/ItemAsset.cs index 28b7212..b85144f 100644 --- a/Runtime/Pattern/DataAssets/ItemAsset.cs +++ b/Runtime/Pattern/DataAssets/ItemAsset.cs @@ -7,7 +7,7 @@ public abstract class ItemAsset : DataAsset, IItem [Header("Item")] [SerializeField] protected string itemName; - public FName NameID => itemName; + public Name16 NameID => itemName; [SerializeField] protected Texture2D _icon; public Texture2D Icon => _icon; diff --git a/Runtime/Pattern/DataAssets/ItemConfig.cs b/Runtime/Pattern/DataAssets/ItemConfig.cs index c0b6826..e9ead74 100644 --- a/Runtime/Pattern/DataAssets/ItemConfig.cs +++ b/Runtime/Pattern/DataAssets/ItemConfig.cs @@ -7,7 +7,7 @@ public abstract class ItemConfig : ConfigAsset, IItem [Header("Item")] [SerializeField] protected string itemName; - public FName NameID => itemName; + public Name16 NameID => itemName; [SerializeField] protected Texture2D _icon; public Texture2D Icon => _icon; diff --git a/Runtime/Pattern/DesignPatterns/BlackboardAsset.cs b/Runtime/Pattern/DesignPatterns/BlackboardAsset.cs index 4103fb6..c6b0607 100644 --- a/Runtime/Pattern/DesignPatterns/BlackboardAsset.cs +++ b/Runtime/Pattern/DesignPatterns/BlackboardAsset.cs @@ -7,33 +7,33 @@ public abstract class BlackboardAsset : UniqueAsset, IBlackboard public Blackboard Blackboard; // Implement IBlackboard Interface - public bool HasBool(FName name) => Blackboard.HasValue(name); - public void SetBool(FName name, bool target) => Blackboard.SetValue(name, target); - public bool GetBool(FName name) => Blackboard.GetValue(name); - public bool HasInt(FName name) => Blackboard.HasValue(name); - public void SetInt(FName name, int target) => Blackboard.SetValue(name, target); - public int GetInt(FName name) => Blackboard.GetValue(name); - public bool HasFloat(FName name) => Blackboard.HasValue(name); - public void SetFloat(FName name, float target) => Blackboard.SetValue(name, target); - public float GetFloat(FName name) => Blackboard.GetValue(name); - public bool HasString(FName name) => Blackboard.HasValue(name); - public void SetString(FName name, string target) => Blackboard.SetValue(name, target); - public string GetString(FName name) => Blackboard.GetValue(name); - public bool HasVector2(FName name) => Blackboard.HasValue(name); - public void SetVector2(FName name, Vector2 target) => Blackboard.SetValue(name, target); - public Vector2 GetVector2(FName name) => Blackboard.GetValue(name); - public bool HasVector3(FName name) => Blackboard.HasValue(name); - public void SetVector3(FName name, Vector3 target) => Blackboard.SetValue(name, target); - public Vector3 GetVector3(FName name) => Blackboard.GetValue(name); - public bool HasPefab(FName name) => Blackboard.HasValue(name); - public void SetPrefab(FName name, Prefab target) => Blackboard.SetValue(name, target); - public Prefab GetPrefab(FName name) => Blackboard.GetValue(name); - public bool HasAsset(FName name) => Blackboard.HasValue(name); - public void SetAsset(FName name, PrimitiveAsset target) => Blackboard.SetValue(name, target); - public PrimitiveAsset GetAsset(FName name) => Blackboard.GetValue(name); - public bool HasComponent(FName name) => Blackboard.HasValue(name); - public void SetComponent(FName name, Component target) => Blackboard.SetValue(name, target); - public Component GetComponent(FName name) => Blackboard.GetValue(name); + public bool HasBool(Name16 name) => Blackboard.HasValue(name); + public void SetBool(Name16 name, bool target) => Blackboard.SetValue(name, target); + public bool GetBool(Name16 name) => Blackboard.GetValue(name); + public bool HasInt(Name16 name) => Blackboard.HasValue(name); + public void SetInt(Name16 name, int target) => Blackboard.SetValue(name, target); + public int GetInt(Name16 name) => Blackboard.GetValue(name); + public bool HasFloat(Name16 name) => Blackboard.HasValue(name); + public void SetFloat(Name16 name, float target) => Blackboard.SetValue(name, target); + public float GetFloat(Name16 name) => Blackboard.GetValue(name); + public bool HasString(Name16 name) => Blackboard.HasValue(name); + public void SetString(Name16 name, string target) => Blackboard.SetValue(name, target); + public string GetString(Name16 name) => Blackboard.GetValue(name); + public bool HasVector2(Name16 name) => Blackboard.HasValue(name); + public void SetVector2(Name16 name, Vector2 target) => Blackboard.SetValue(name, target); + public Vector2 GetVector2(Name16 name) => Blackboard.GetValue(name); + public bool HasVector3(Name16 name) => Blackboard.HasValue(name); + public void SetVector3(Name16 name, Vector3 target) => Blackboard.SetValue(name, target); + public Vector3 GetVector3(Name16 name) => Blackboard.GetValue(name); + public bool HasPefab(Name16 name) => Blackboard.HasValue(name); + public void SetPrefab(Name16 name, Prefab target) => Blackboard.SetValue(name, target); + public Prefab GetPrefab(Name16 name) => Blackboard.GetValue(name); + public bool HasAsset(Name16 name) => Blackboard.HasValue(name); + public void SetAsset(Name16 name, PrimitiveAsset target) => Blackboard.SetValue(name, target); + public PrimitiveAsset GetAsset(Name16 name) => Blackboard.GetValue(name); + public bool HasComponent(Name16 name) => Blackboard.HasValue(name); + public void SetComponent(Name16 name, Component target) => Blackboard.SetValue(name, target); + public Component GetComponent(Name16 name) => Blackboard.GetValue(name); protected override void OnEnable() diff --git a/Runtime/Pattern/Managers/HapticManager.cs b/Runtime/Pattern/Managers/HapticManager.cs index e3f48c7..8931dee 100644 --- a/Runtime/Pattern/Managers/HapticManager.cs +++ b/Runtime/Pattern/Managers/HapticManager.cs @@ -22,7 +22,7 @@ private class HapticController : IHapticProvider private HapticManager Owner; // Implement IIdentifier Interface - public FName NameID => Config.NameID; + public Name16 NameID => Config.NameID; // Implement IHapticProvider Interface public HapticController(HapticManager manager, HapticConfig config) { @@ -148,7 +148,7 @@ public abstract class HapticConfig : ConfigAsset, IIdentifier private string configName; // Implement - public FName NameID => configName; + public Name16 NameID => configName; private void OnValidate() { diff --git a/Runtime/Toolkit/Ability/AbilityAsset.cs b/Runtime/Toolkit/Ability/AbilityAsset.cs index 4a073bb..eb6e28e 100644 --- a/Runtime/Toolkit/Ability/AbilityAsset.cs +++ b/Runtime/Toolkit/Ability/AbilityAsset.cs @@ -8,7 +8,7 @@ public abstract class AbilityAsset : TemplateAsset, IAbility, ICooldown private float lastUsedTime = -Mathf.Infinity; // Implement IIdentifier Interface - FName IIdentifier.NameID => name; + Name16 IIdentifier.NameID => name; // Implement IAbility Interface public bool CanUse(GameObject user) { diff --git a/Runtime/Toolkit/PCG/Assets/PCGCashAsset.cs b/Runtime/Toolkit/PCG/Assets/PCGCashAsset.cs index 936255e..a877b37 100644 --- a/Runtime/Toolkit/PCG/Assets/PCGCashAsset.cs +++ b/Runtime/Toolkit/PCG/Assets/PCGCashAsset.cs @@ -11,7 +11,7 @@ public interface IPCGCashAsset : IIdentifier public class PCGCashAsset : ConfigAsset, IPCGCashAsset { - public FName NameID => name; + public Name16 NameID => name; [SerializeField] private PCGData[] CashData; diff --git a/Runtime/Toolkit/PCG/Assets/PCGResourceConfig.cs b/Runtime/Toolkit/PCG/Assets/PCGResourceConfig.cs index 6e2d35d..90ba5db 100644 --- a/Runtime/Toolkit/PCG/Assets/PCGResourceConfig.cs +++ b/Runtime/Toolkit/PCG/Assets/PCGResourceConfig.cs @@ -36,7 +36,7 @@ public struct PCGSource [CreateAssetMenu(fileName = "PCG_Resource", menuName = "RealMethod/PCG/Resource", order = 1)] public class PCGResourceConfig : ConfigAsset, IPCGResource { - public FName NameID => name; + public Name16 NameID => name; [SerializeField] private PCGSource[] Sources; diff --git a/Runtime/Toolkit/RPG/Resource/ResourceData.cs b/Runtime/Toolkit/RPG/Resource/ResourceData.cs index fdc9674..98fc907 100644 --- a/Runtime/Toolkit/RPG/Resource/ResourceData.cs +++ b/Runtime/Toolkit/RPG/Resource/ResourceData.cs @@ -44,7 +44,7 @@ public ResourceData(string ReName, float val, float max) float IResource.Value => value; float IResource.MaxValue => GetMaxValue(defaultMaxValue); // Implement IIdentifier Interface - public FName NameID => resourceName; + public Name16 NameID => resourceName; void IResource.Refill() { value = provider.MaxValue; diff --git a/Runtime/Toolkit/RPG/StatSystem/BuffConfig.cs b/Runtime/Toolkit/RPG/StatSystem/BuffConfig.cs index 58862ff..afb2caf 100644 --- a/Runtime/Toolkit/RPG/StatSystem/BuffConfig.cs +++ b/Runtime/Toolkit/RPG/StatSystem/BuffConfig.cs @@ -9,7 +9,7 @@ public abstract class BuffConfig : ConfigAsset, IIdentifier [SerializeField] private string configName; // Implement IIdentifier Interface - public FName NameID => configName; + public Name16 NameID => configName; // Abstract Method public abstract IStatModifier[] GetModifiers(T StateName) where T : System.Enum; diff --git a/Runtime/Toolkit/RPG/StatSystem/StatData.cs b/Runtime/Toolkit/RPG/StatSystem/StatData.cs index 6548c73..55312ea 100644 --- a/Runtime/Toolkit/RPG/StatSystem/StatData.cs +++ b/Runtime/Toolkit/RPG/StatSystem/StatData.cs @@ -53,7 +53,7 @@ public BaseStatData(float startValue, float min, float max) // Implement IStat Interface - public FName NameID => GetStatName(); + public Name16 NameID => GetStatName(); public float BaseValue => baseValue.GetMergeValue(); public float Value => GetFinalValue(); public float MinValue => minValue; diff --git a/Runtime/Toolkit/RPG/StatSystem/StatProfile.cs b/Runtime/Toolkit/RPG/StatSystem/StatProfile.cs index 16fb6e1..e72db84 100644 --- a/Runtime/Toolkit/RPG/StatSystem/StatProfile.cs +++ b/Runtime/Toolkit/RPG/StatSystem/StatProfile.cs @@ -46,7 +46,7 @@ public IStat this[int index] } // Implement IIdentifier Interface - public FName NameID => profileName; + public Name16 NameID => profileName; void IPrimitiveStatContainer.InitializeResource(IResourceData resource) { resource.Initialize(this); diff --git a/Runtime/Toolkit/Tutorial/TutorialConfig.cs b/Runtime/Toolkit/Tutorial/TutorialConfig.cs index 01a9021..f436a01 100644 --- a/Runtime/Toolkit/Tutorial/TutorialConfig.cs +++ b/Runtime/Toolkit/Tutorial/TutorialConfig.cs @@ -35,7 +35,7 @@ public abstract class TutorialConfigCore : ConfigAsset, IItem, ITutorialSpawner // Implement IIdentifier Interface - public FName NameID => label; + public Name16 NameID => label; // Implement IItem Interface public Texture2D Icon => icon; Sprite IItem.GetSpriteIcon() diff --git a/Runtime/Core/Definitions/FName.cs b/Tests/General/FName.cs similarity index 99% rename from Runtime/Core/Definitions/FName.cs rename to Tests/General/FName.cs index 851d30e..237c6b6 100644 --- a/Runtime/Core/Definitions/FName.cs +++ b/Tests/General/FName.cs @@ -1,15 +1,16 @@ using System; -using System.Collections.Generic; using UnityEngine; - +using System.Collections.Generic; #if UNITY_EDITOR using UnityEditor; using UnityEditor.Callbacks; #endif + namespace RealMethod { + /// /// Lightweight engine-style string identifier. /// Stores only an integer ID while the actual strings live in a global table. @@ -297,8 +298,5 @@ private static void OnScriptsReloaded() } #endif } -} - - - +} \ No newline at end of file diff --git a/Tests/General/FName.cs.meta b/Tests/General/FName.cs.meta new file mode 100644 index 0000000..f7a56cc --- /dev/null +++ b/Tests/General/FName.cs.meta @@ -0,0 +1,2 @@ +fileFormatVersion: 2 +guid: 5c9694ddfc582e9428a68603ae6d6332 \ No newline at end of file From 27349bcd0699a6dc33b6bd3b78bcf48181c53f08 Mon Sep 17 00:00:00 2001 From: Alijimpa Date: Tue, 10 Mar 2026 09:47:38 +0330 Subject: [PATCH 030/204] Write Comment for Class --- Runtime/Core/Definitions/Name16.cs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/Runtime/Core/Definitions/Name16.cs b/Runtime/Core/Definitions/Name16.cs index d72559d..01e056e 100644 --- a/Runtime/Core/Definitions/Name16.cs +++ b/Runtime/Core/Definitions/Name16.cs @@ -7,8 +7,8 @@ namespace RealMethod { /// - /// Lightweight engine-style string identifier. - /// Stores only an integer ID while the actual strings live in a global table. + /// String identifier. + /// Store 16 character with very fast compairing /// [Serializable] public struct Name16 @@ -19,7 +19,7 @@ public struct Name16 public ulong Name_B; /// - /// Creates a Name from a string. + /// Creates a Name16 from a string. /// public Name16(string value) { From 0348bff5f8cf02f90518285e5d8368ab4dde4bc4 Mon Sep 17 00:00:00 2001 From: Alijimpa Date: Tue, 10 Mar 2026 09:48:07 +0330 Subject: [PATCH 031/204] Implement TName that is runtime Sore Name with Id it's very usefull for Repetetive name --- .../Library/SharedScripts/Structs/TName.cs | 18 +++++++++--------- .../SharedScripts/Structs/TName.cs.meta | 0 2 files changed, 9 insertions(+), 9 deletions(-) rename Tests/General/FName.cs => Runtime/Library/SharedScripts/Structs/TName.cs (94%) rename Tests/General/FName.cs.meta => Runtime/Library/SharedScripts/Structs/TName.cs.meta (100%) diff --git a/Tests/General/FName.cs b/Runtime/Library/SharedScripts/Structs/TName.cs similarity index 94% rename from Tests/General/FName.cs rename to Runtime/Library/SharedScripts/Structs/TName.cs index 237c6b6..6fd0301 100644 --- a/Tests/General/FName.cs +++ b/Runtime/Library/SharedScripts/Structs/TName.cs @@ -16,7 +16,7 @@ namespace RealMethod /// Stores only an integer ID while the actual strings live in a global table. /// [Serializable] - public struct FName : IEquatable + public struct TName : IEquatable { /// /// Maximum allowed characters for a name. @@ -59,7 +59,7 @@ private static ProjectSettingAsset ProjectSettings /// /// Creates a Name from a string. /// - public FName(string value) + public TName(string value) { id = GetOrCreateId(value); } @@ -177,7 +177,7 @@ public static string GetString(int id) /// /// Checks equality with another Name. /// - public bool Equals(FName other) + public bool Equals(TName other) { return id == other.id; } @@ -198,7 +198,7 @@ public override string ToString() /// public override bool Equals(object obj) { - return obj is FName other && Equals(other); + return obj is TName other && Equals(other); } /// /// Hash code of the Name. @@ -214,15 +214,15 @@ public override int GetHashCode() /// /// Implicit conversion from string. /// - public static implicit operator FName(string value) + public static implicit operator TName(string value) { - return new FName(value); + return new TName(value); } /// /// Implicit conversion to string. /// - public static implicit operator string(FName name) + public static implicit operator string(TName name) { return GetString(name.id); } @@ -230,7 +230,7 @@ public static implicit operator string(FName name) /// /// Equality operator. /// - public static bool operator ==(FName a, FName b) + public static bool operator ==(TName a, TName b) { return a.id == b.id; } @@ -238,7 +238,7 @@ public static implicit operator string(FName name) /// /// Inequality operator. /// - public static bool operator !=(FName a, FName b) + public static bool operator !=(TName a, TName b) { return a.id != b.id; } diff --git a/Tests/General/FName.cs.meta b/Runtime/Library/SharedScripts/Structs/TName.cs.meta similarity index 100% rename from Tests/General/FName.cs.meta rename to Runtime/Library/SharedScripts/Structs/TName.cs.meta From 24810bcd72b8549b3f367ce29b4839fd6b959800 Mon Sep 17 00:00:00 2001 From: Alijimpa Date: Tue, 10 Mar 2026 18:49:08 +0330 Subject: [PATCH 032/204] Implement Extera Section for ProjectSetting --- .../RealMethod_ProjectSetting.cs | 89 +++++++++++++++---- .../Sections/FolderStructure_Section.cs | 7 +- .../Sections/InitializerSetting_Section.cs | 6 +- .../ProjectSetting/ProjectSettingAsset.cs | 12 +++ 4 files changed, 93 insertions(+), 21 deletions(-) diff --git a/Editor/Core/ProjectSetting/RealMethod_ProjectSetting.cs b/Editor/Core/ProjectSetting/RealMethod_ProjectSetting.cs index 85690a4..c755752 100644 --- a/Editor/Core/ProjectSetting/RealMethod_ProjectSetting.cs +++ b/Editor/Core/ProjectSetting/RealMethod_ProjectSetting.cs @@ -12,11 +12,17 @@ interface ISectionSetting { void FirstSelected(ProjectSettingAsset storage); void Draw(); + bool IsRuntime(); } // Abstract base class for a settings section public abstract class ProjectSettingSection : ISectionSetting { + protected enum SectionType + { + Runtime, + Editor, + } protected class ClassType { private List TypeList; @@ -81,12 +87,17 @@ void ISectionSetting.Draw() } } } + bool ISectionSetting.IsRuntime() + { + return GetSectionType() == SectionType.Runtime; + } // Abstract Method protected abstract void Initialized(); protected abstract void BeginRender(ProjectSettingAsset Storage); protected abstract void UpdateRender(); protected abstract string GetTitle(); + protected abstract SectionType GetSectionType(); protected abstract void Fix(int Id); // Protected Function @@ -109,14 +120,15 @@ protected void ClearError() } UpdateRender(); } + + } // Project Setting public static class RealMethod_ProjectSetting { - private const string settingsPath = "Assets/Resources/RealMethod/RealMethodSetting.asset"; private static bool candraw = true;// Flag to determine if the UI can be drawn - private static ProjectSettingSection[] sections = new ProjectSettingSection[2] { + private static List sections = new List(3) { // Array of sections to be rendered in the settings UI new InitializerSetting_Section(), new FolderStructure_Section() @@ -127,9 +139,9 @@ public static class RealMethod_ProjectSetting // Create a SettingsProvider for Unity's Project Settings public static SettingsProvider CreateSettingsProvider() { - var provider = new SettingsProvider("Project/Real Method", SettingsScope.Project) + var provider = new SettingsProvider("Project/RealMethod", SettingsScope.Project) { - label = "Real Method", + label = "RealMethod", // Called when the settings tab is first selected activateHandler = (searchContext, rootElement) => @@ -139,7 +151,7 @@ public static SettingsProvider CreateSettingsProvider() // Attempt to load the settings asset if (!GetSettingStorage(out TargetStorage)) { - if (Directory.Exists(Path.GetDirectoryName(settingsPath))) + if (Directory.Exists(Path.GetDirectoryName(RM_CoreEditor.SetttingAssetPath))) { TargetStorage = CreateSettingStorage(); } @@ -149,32 +161,48 @@ public static SettingsProvider CreateSettingsProvider() } } - // Initialize each section with the loaded settings - foreach (var item in sections) - { - ISectionSetting ptovider = item; - if (TargetStorage != null) - ptovider.FirstSelected(TargetStorage); - } + // Initialize Main section with the loaded settings + ((ISectionSetting)sections[0]).FirstSelected(TargetStorage); + ((ISectionSetting)sections[1]).FirstSelected(TargetStorage); }, + // Called to draw the UI elements guiHandler = (searchContext) => { if (candraw) { + EditorGUILayout.Space(); + EditorGUILayout.LabelField("Runtime", EditorStyles.whiteBoldLabel); + GUILayout.Box("", GUILayout.ExpandWidth(true), GUILayout.Height(1)); // Render each section foreach (var item in sections) { ISectionSetting ptovider = item; - ptovider.Draw(); - // Add a separator line - GUILayout.Box("", GUILayout.ExpandWidth(true), GUILayout.Height(1)); + if (ptovider.IsRuntime()) + { + ptovider.Draw(); + EditorGUILayout.Space(1); + } + } + EditorGUILayout.Space(); + EditorGUILayout.LabelField("Editor", EditorStyles.whiteBoldLabel); + GUILayout.Box("", GUILayout.ExpandWidth(true), GUILayout.Height(1)); + foreach (var item in sections) + { + ISectionSetting ptovider = item; + if (!ptovider.IsRuntime()) + { + + ptovider.Draw(); + EditorGUILayout.Space(1); + + } } } else { - EditorGUILayout.HelpBox($"The Address is not valid {Path.GetDirectoryName(settingsPath)}", MessageType.Error); + EditorGUILayout.HelpBox($"The Address is not valid {Path.GetDirectoryName(RM_CoreEditor.SetttingAssetPath)}", MessageType.Error); if (GUILayout.Button("Fix")) { if (!Directory.Exists("Assets/Resources")) @@ -205,16 +233,41 @@ public static SettingsProvider CreateSettingsProvider() public static bool GetSettingStorage(out ProjectSettingAsset settings) { // Attempt to load the settings asset from the specified path - settings = AssetDatabase.LoadAssetAtPath(settingsPath); + settings = AssetDatabase.LoadAssetAtPath(RM_CoreEditor.SetttingAssetPath); + AddExteraSections(settings); return settings != null; } private static ProjectSettingAsset CreateSettingStorage() { // Create a new settings asset at the specified path ProjectSettingAsset settings = ScriptableObject.CreateInstance(); - AssetDatabase.CreateAsset(settings, settingsPath); + AssetDatabase.CreateAsset(settings, RM_CoreEditor.SetttingAssetPath); AssetDatabase.SaveAssets(); + AddExteraSections(settings); return settings; } + private static void AddExteraSections(ProjectSettingAsset settings) + { + Type[] sectiontypes = settings.GetExteraSections(); + foreach (var item in sectiontypes) + { + if (item != null) + { + if (typeof(ProjectSettingSection).IsAssignableFrom(item)) + { + try + { + ProjectSettingSection TargetSection = (ProjectSettingSection)Activator.CreateInstance(item); + ((ISectionSetting)TargetSection).FirstSelected(settings); + sections.Add(TargetSection); + } + catch (Exception ex) + { + Debug.LogError($"Failed to instantiate {item}: {ex.Message}. DefaultGameBridge Created"); + } + } + } + } + } } } \ No newline at end of file diff --git a/Editor/Core/ProjectSetting/Sections/FolderStructure_Section.cs b/Editor/Core/ProjectSetting/Sections/FolderStructure_Section.cs index c62e6ea..9a6d2f8 100644 --- a/Editor/Core/ProjectSetting/Sections/FolderStructure_Section.cs +++ b/Editor/Core/ProjectSetting/Sections/FolderStructure_Section.cs @@ -86,14 +86,19 @@ protected override void UpdateRender() EditorGUILayout.EndHorizontal(); // End horizontal layout } } - protected override string GetTitle() { return "FolderStructure"; } + protected override SectionType GetSectionType() + { + return SectionType.Editor; + } protected override void Fix(int Id) { } + + private void CreateFolder(string parentFolder, string newFolderName) { string folderPath = System.IO.Path.Combine(parentFolder, newFolderName).Replace("\\", "/"); diff --git a/Editor/Core/ProjectSetting/Sections/InitializerSetting_Section.cs b/Editor/Core/ProjectSetting/Sections/InitializerSetting_Section.cs index 5950850..154bc99 100644 --- a/Editor/Core/ProjectSetting/Sections/InitializerSetting_Section.cs +++ b/Editor/Core/ProjectSetting/Sections/InitializerSetting_Section.cs @@ -54,13 +54,15 @@ protected override string GetTitle() { return "Initializer"; } + protected override SectionType GetSectionType() + { + return SectionType.Runtime; + } protected override void Fix(int Id) { throw new System.NotImplementedException(); } - - } } \ No newline at end of file diff --git a/Runtime/Core/ProjectSetting/ProjectSettingAsset.cs b/Runtime/Core/ProjectSetting/ProjectSettingAsset.cs index e11b50f..8aa1940 100644 --- a/Runtime/Core/ProjectSetting/ProjectSettingAsset.cs +++ b/Runtime/Core/ProjectSetting/ProjectSettingAsset.cs @@ -2,6 +2,10 @@ using System.Collections.Generic; using UnityEngine; +// #if UNITY_EDITOR +// namespace RealMethod.Editor; +// #endif + namespace RealMethod { // Real Method Setting Storage @@ -176,6 +180,14 @@ public FolderAddress GetFolderAddressByType(AssetFormat identity) } + + +#if UNITY_EDITOR + public virtual Type[] GetExteraSections() + { + return null; + } +#endif } From be3142b307780022c1b8631d9c4ffd2a29fc2a4e Mon Sep 17 00:00:00 2001 From: Alijimpa Date: Wed, 11 Mar 2026 12:39:34 +0330 Subject: [PATCH 033/204] Implement Bata Version for Show Class --- Editor/ReadySet/Tools/ClassViewerWindow.cs | 453 +++++++++++------- .../ReadySet/Tools/ClassViewerWindow.cs.meta | 2 +- 2 files changed, 273 insertions(+), 182 deletions(-) diff --git a/Editor/ReadySet/Tools/ClassViewerWindow.cs b/Editor/ReadySet/Tools/ClassViewerWindow.cs index 6a25e38..6a07570 100644 --- a/Editor/ReadySet/Tools/ClassViewerWindow.cs +++ b/Editor/ReadySet/Tools/ClassViewerWindow.cs @@ -1,264 +1,355 @@ -using UnityEngine; -using UnityEditor; +using System; using System.Collections.Generic; -using System.IO; +using UnityEditor; +using UnityEngine; namespace RealMethod.Editor { - [System.Serializable] - public class ClassTreeNode + class FieldModule { - public string name; - public string toturial; // text after -> - public string link; // text afeter https - public List children = new List(); - } + private MonoScript MyScript; + private List MyChilds = new List(); + private string MyName = string.Empty; - public class ClassViewerWindow : EditorWindow - { - private List rootNodes = new List(); - private Dictionary foldoutStates = new Dictionary(); - private TextAsset textFile; - private Vector2 scrollPos; - private string searchQuery = ""; - [MenuItem("Tools/RealMethod/ClassViewer")] - public static void Open() + public string Title { - GetWindow("ClassViewer"); - } - - // Unity Methods - private void OnEnable() - { - string ClassViewPath = "Assets/Realmethod/Documentation/Information/ClassViewer.txt"; // Just for Test - // string ClassViewPath = Path.Combine(RM_CoreEditor.Documentation, "ClassViewer.txt"); - if (!File.Exists(ClassViewPath)) + get { - Debug.LogError($"ClassView file not found: {ClassViewPath}"); - Close(); - } - string ClassFile = File.ReadAllText(ClassViewPath); - LoadFromText(ClassFile); - } - private void OnGUI() - { - EditorGUILayout.BeginHorizontal(); - if (GUILayout.Button("Collaps")) - { - foreach (var node in rootNodes) + if (MyName == string.Empty) { - FoldLine(node, false); + return MyScript.name; } - } - if (GUILayout.Button("Expanded")) - { - foreach (var node in rootNodes) + else { - FoldLine(node, true); + return MyName; } } - EditorGUILayout.EndHorizontal(); - EditorGUILayout.Space(); - searchQuery = EditorGUILayout.TextField("Search", searchQuery); - - EditorGUILayout.Space(); + } + public MonoScript ScriptFile => MyScript; + public Type Class => MyScript.GetClass(); + public bool IsExpand { get; private set; } = false; - // 🔽 Scroll View - scrollPos = EditorGUILayout.BeginScrollView(scrollPos); - foreach (var node in rootNodes) - { - DrawNodeWithSearch(node, 0); - } - EditorGUILayout.EndScrollView(); - // 🔼 Scroll View + public FieldModule(string Name) + { + MyName = Name; } - - private void LoadFromText(string text) + public FieldModule(MonoScript script) { - rootNodes.Clear(); - foldoutStates.Clear(); + MyScript = script; + } - string[] lines = text.Split('\n'); - Stack stack = new Stack(); - foreach (string rawLine in lines) + public void Draw() + { + if (MyChilds.Count == 0) + { + EditorGUILayout.LabelField(Title); + } + else + { + IsExpand = EditorGUILayout.Foldout(IsExpand, Title, true); + if (IsExpand) + { + EditorGUI.indentLevel++; + foreach (var child in MyChilds) + { + child.Draw(); + } + EditorGUI.indentLevel--; + } + } + } + public void AddChild(MonoScript script) + { + FieldModule NewChildField = new FieldModule(script); + Type NewType = script.GetClass(); + if (NewType == null) { - if (string.IsNullOrWhiteSpace(rawLine)) - continue; + MyChilds.Add(NewChildField); + return; + } + Type NewParentType = NewType.BaseType; + if (NewParentType == null) + { + MyChilds.Add(NewChildField); + return; + } - int indent = CountIndent(rawLine); - string trimmed = rawLine.Trim(); - string nodeName = trimmed; - string endText = null; - string linkText = null; - // 🔹 Parse "-> End Text" - string middleText = null; - int arrowIndex = trimmed.IndexOf("->"); - if (arrowIndex >= 0) + // find parent from this child + foreach (var child in MyChilds) + { + Type ChildType = child.Class; + if (ChildType != null) { - nodeName = trimmed.Substring(0, arrowIndex).Trim(); - middleText = trimmed.Substring(arrowIndex + 2).Trim(); + if (NewParentType == ChildType) + { + child.AddChild(NewChildField.ScriptFile); + return; + } } + } - if (middleText != null) + // Find Child from This Field Child + List RemoveIndex = new List(); + for (int i = 0; i < MyChilds.Count; i++) + { + FieldModule child = MyChilds[i]; + Type ChildType = child.Class; + if (ChildType != null) { - int linkindex = middleText.IndexOf("https"); - if (linkindex >= 0) + Type ChildParentType = ChildType.BaseType; + if (ChildParentType != null) { - endText = middleText.Substring(0, linkindex).Trim(); - linkText = middleText.Substring(linkindex).Trim(); - } - else - { - endText = middleText; + if (NewType == ChildParentType) + { + RemoveIndex.Add(i); + NewChildField.AddChild(child.ScriptFile); + } } } + } - ClassTreeNode node = new ClassTreeNode - { - name = nodeName, - toturial = endText, - link = linkText - }; - if (indent == 0) + MyChilds.Add(NewChildField); + + foreach (var Index in RemoveIndex) + { + if (MyChilds.IsValidIndex(Index)) { - rootNodes.Add(node); - stack.Clear(); - stack.Push(node); + MyChilds.RemoveAt(Index); } else { - while (stack.Count > indent) - stack.Pop(); - - stack.Peek().children.Add(node); - stack.Push(node); + Debug.LogWarning($"[{Title}] Remove Index is not valid, TargetIndex={Index} , Count={MyChilds.Count}"); } } } - private int CountIndent(string line) + } + + + public class ClassViewerWindow : EditorWindow + { + private class ComboBox : EditorProperty where T : Enum { - int spaces = 0; - foreach (char c in line) + public ComboBox(string Name, UnityEngine.Object other) : base(Name, other) { - if (c == ' ') - spaces++; - else - break; } - return spaces / 2; // 2 spaces = 1 level - } - private bool DrawNodeWithSearch(ClassTreeNode node, int indent) - { - // Check if node matches search - bool nodeMatches = string.IsNullOrEmpty(searchQuery) || - node.name.ToLower().Contains(searchQuery.ToLower()) || - node.toturial?.ToLower().Contains(searchQuery.ToLower()) == true; - - // Check if any child matches - bool anyChildMatches = false; - foreach (var child in node.children) + protected override byte UpdateRender() { - if (NodeOrChildrenMatchSearch(child)) + CashValue = (T)EditorGUILayout.EnumPopup(CurrentValue, GUI.skin.FindStyle("ToolbarPopup"), GUILayout.Width(120)); + if (EqualityComparer.Default.Equals(CashValue, CurrentValue)) { - anyChildMatches = true; - break; + return 0; // No change + } + else + { + SetValue(CashValue); + return 1; // Changed } } + protected override void FixError(int Id) + { - // If nothing matches, skip - if (!nodeMatches && !anyChildMatches) - return false; + } - // Draw parent node - if (!foldoutStates.ContainsKey(node)) - foldoutStates[node] = true; + } + private enum FilterType + { + All, + MonoBehaviour, + ScriptableObject, + Editor + } - EditorGUILayout.BeginHorizontal(); - GUILayout.Space(indent * 20); - foldoutStates[node] = - EditorGUILayout.Foldout(foldoutStates[node], node.name, true); - EditorGUILayout.EndHorizontal(); + private Vector2 scroll; + private MonoScript[] ProjectScripts; + private Dictionary NameSpaces = new Dictionary(); + + private string search = ""; + private ComboBox filter; + private bool TEST; + + + [MenuItem("Tools/RealMethod/ClassViewer")] + public static void Open() + { - // Show endText as link if expanded - if (foldoutStates[node] && !string.IsNullOrEmpty(node.toturial)) + GetWindow("Class Viewer"); + } + private void OnEnable() + { + filter = new ComboBox("Filter", this); + ProjectScripts = LoadScripts(); + foreach (var script in ProjectScripts) { - EditorGUILayout.BeginHorizontal(); - GUILayout.Space(indent * 20); - EditorGUILayout.BeginVertical("box"); - GUIStyle richLabel = new GUIStyle(EditorStyles.wordWrappedLabel); - richLabel.richText = true; - GUILayout.Label(node.toturial, richLabel); - //GUILayout.Label(node.toturial, new GUIStyle(EditorStyles.wordWrappedLabel)); - if (!string.IsNullOrEmpty(node.link)) + if (script != null) { - if (GUILayout.Button("Link", EditorStyles.linkLabel)) + Type ScriptType = script.GetClass(); + if (ScriptType != null) + { + if (ScriptType.Namespace != null) + { + if (NameSpaces.TryGetValue(ScriptType.Namespace, out FieldModule Field)) + { + Field.AddChild(script); + } + else + { + FieldModule NewField = new FieldModule(ScriptType.Namespace); + NameSpaces.Add(ScriptType.Namespace, NewField); + NewField.AddChild(script); + } + } + else + { + if (NameSpaces.TryGetValue("NonSpace", out FieldModule Field)) + { + Field.AddChild(script); + } + else + { + FieldModule NewField = new FieldModule("NonSpace"); + NameSpaces.Add("NonSpace", NewField); + NewField.AddChild(script); + } + } + } + else { - OnEndTextClicked(node); + if (NameSpaces.TryGetValue("NoType", out FieldModule Field)) + { + Field.AddChild(script); + } + else + { + FieldModule NewField = new FieldModule("NoType"); + NameSpaces.Add("NoType", NewField); + NewField.AddChild(script); + } } + } - EditorGUILayout.EndVertical(); - EditorGUILayout.EndHorizontal(); } + } + private void OnGUI() + { + DrawToolbar(); + scroll = EditorGUILayout.BeginScrollView(scroll); + DrawList(); + EditorGUILayout.EndScrollView(); + } + private void DrawToolbar() + { + EditorGUILayout.BeginHorizontal(EditorStyles.toolbar); + search = GUILayout.TextField( + search, + GUI.skin.FindStyle("ToolbarSearchTextField"), + GUILayout.ExpandWidth(true) + ); - // Draw children recursively only if expanded - if (foldoutStates[node]) + if (GUILayout.Button( + GUIContent.none, + GUI.skin.FindStyle("ToolbarSearchCancelButton"))) { - foreach (var child in node.children) - { - DrawNodeWithSearch(child, indent + 1); - } + search = ""; + GUI.FocusControl(null); + } + filter.Render(); + if (GUILayout.Button("Refresh", EditorStyles.toolbarButton, GUILayout.Width(70))) + { + search = ""; + LoadScripts(); } - return true; + EditorGUILayout.EndHorizontal(); } - // Helper: check recursively if a node or any child matches search - private bool NodeOrChildrenMatchSearch(ClassTreeNode node) + private void DrawList() { - bool match = string.IsNullOrEmpty(searchQuery) || - node.name.ToLower().Contains(searchQuery.ToLower()) || - node.toturial?.ToLower().Contains(searchQuery.ToLower()) == true; - - if (match) - return true; - - foreach (var child in node.children) + foreach (var item in NameSpaces) { - if (NodeOrChildrenMatchSearch(child)) - return true; + item.Value.Draw(); } + } + private void DrawScriptList(ref MonoScript[] Scripts) + { + foreach (var script in Scripts) + { + if (!PassSearch(script)) continue; + if (!PassFilter(script)) continue; - return false; + DrawScript(script); + } } - private void FoldLine(ClassTreeNode node, bool result) + + + + private bool PassSearch(MonoScript script) + { + if (string.IsNullOrEmpty(search)) return true; + + return script.name.IndexOf(search, StringComparison.OrdinalIgnoreCase) >= 0; + } + private bool PassFilter(MonoScript script) { - foldoutStates[node] = result; - if (foldoutStates[node]) + Type type = script.GetClass(); + if (type == null) return false; + + return filter.GetValue() switch { - foreach (var child in node.children) - FoldLine(child, result); + FilterType.MonoBehaviour => type.IsSubclassOf(typeof(MonoBehaviour)), + FilterType.ScriptableObject => type.IsSubclassOf(typeof(ScriptableObject)), + FilterType.Editor => type.IsSubclassOf(typeof(UnityEditor.Editor)), + _ => true + }; + } + private void DrawScript(MonoScript script) + { + Type type = script.GetClass(); + string namespaceName = type?.Namespace ?? "No Namespace"; + + EditorGUILayout.BeginHorizontal(); + + if (GUILayout.Button(script.name, EditorStyles.label, GUILayout.Width(250))) + { + AssetDatabase.OpenAsset(script); } + + GUILayout.Label(namespaceName); + + EditorGUILayout.EndHorizontal(); } - private void OnEndTextClicked(ClassTreeNode node) + private MonoScript[] LoadScripts() { - if (EditorUtility.DisplayDialog("OpenLink", node.link, "Open", "Cancel")) + List scripts = new List(); + + string[] guids = AssetDatabase.FindAssets("t:MonoScript"); + + foreach (string guid in guids) { - // 3️⃣ OR open URL (if endText is a URL) - Application.OpenURL(node.link); + string path = AssetDatabase.GUIDToAssetPath(guid); + MonoScript script = AssetDatabase.LoadAssetAtPath(path); + + scripts.Add(script); } - // 2️⃣ OR ping asset - // EditorGUIUtility.PingObject(yourObject); + + scripts.Sort((a, b) => a.name.CompareTo(b.name)); + + return scripts.ToArray(); } + + + + + } } diff --git a/Editor/ReadySet/Tools/ClassViewerWindow.cs.meta b/Editor/ReadySet/Tools/ClassViewerWindow.cs.meta index 4a30911..7d84b2c 100644 --- a/Editor/ReadySet/Tools/ClassViewerWindow.cs.meta +++ b/Editor/ReadySet/Tools/ClassViewerWindow.cs.meta @@ -1,2 +1,2 @@ fileFormatVersion: 2 -guid: 15438cb6b5774124f90a5a787acca4c8 \ No newline at end of file +guid: cd4da7ba3d8b8fe4ea12071681b3d0ac \ No newline at end of file From 39cbfb6ab24ca0df1f95c11f7ece9a3025d6de90 Mon Sep 17 00:00:00 2001 From: Alijimpa Date: Thu, 12 Mar 2026 21:03:08 +0330 Subject: [PATCH 034/204] Fix and Refine ClassViewer --- Editor/ReadySet/Tools/ClassViewerWindow.cs | 333 ++++++++++++--------- 1 file changed, 189 insertions(+), 144 deletions(-) diff --git a/Editor/ReadySet/Tools/ClassViewerWindow.cs b/Editor/ReadySet/Tools/ClassViewerWindow.cs index 6a07570..8755dd8 100644 --- a/Editor/ReadySet/Tools/ClassViewerWindow.cs +++ b/Editor/ReadySet/Tools/ClassViewerWindow.cs @@ -7,12 +7,11 @@ namespace RealMethod.Editor { class FieldModule { - private MonoScript MyScript; + private MonoScript MyScript = null; private List MyChilds = new List(); private string MyName = string.Empty; - public string Title { get @@ -27,12 +26,10 @@ public string Title } } } + public bool HasFile => MyScript != null; public MonoScript ScriptFile => MyScript; - public Type Class => MyScript.GetClass(); public bool IsExpand { get; private set; } = false; - - public FieldModule(string Name) { MyName = Name; @@ -45,90 +42,145 @@ public FieldModule(MonoScript script) public void Draw() { - if (MyChilds.Count == 0) - { - EditorGUILayout.LabelField(Title); - } - else + EditorGUILayout.BeginHorizontal(); + DrawField(); + EditorGUILayout.EndHorizontal(); + if (IsExpand) { - IsExpand = EditorGUILayout.Foldout(IsExpand, Title, true); - if (IsExpand) + EditorGUI.indentLevel++; + foreach (var child in MyChilds) { - EditorGUI.indentLevel++; - foreach (var child in MyChilds) - { - child.Draw(); - } - EditorGUI.indentLevel--; + child.Draw(); } + EditorGUI.indentLevel--; } } - public void AddChild(MonoScript script) + public void AddChild(FieldModule ChildModule) { - FieldModule NewChildField = new FieldModule(script); - Type NewType = script.GetClass(); - if (NewType == null) + if (ChildModule == null) { - MyChilds.Add(NewChildField); + Print("ChildModule is not valid!"); return; } - Type NewParentType = NewType.BaseType; - if (NewParentType == null) + MyChilds.Add(ChildModule); + } + public void AddChild(MonoScript File) + { + Type NewType = File.GetClass(); + if (NewType == null || NewType.Namespace == null) { - MyChilds.Add(NewChildField); + Print($"MonoScript does't have have any 'MainClass'or'NameSpace' for Child[{File.name}]"); return; } + FieldModule NewModule = new FieldModule(File); + FieldModule ParentField = TraverseHierarchy(File.GetClass(), true); - - // find parent from this child - foreach (var child in MyChilds) + if (ParentField.TryFindField(NewModule.Title, out FieldModule result)) { - Type ChildType = child.Class; - if (ChildType != null) + if (!result.HasFile) { - if (NewParentType == ChildType) - { - child.AddChild(NewChildField.ScriptFile); - return; - } + result.SetFileScript(File); } } + else + { + ParentField.AddChild(NewModule); + } + + } + public void Expand() + { + IsExpand = true; + } - // Find Child from This Field Child - List RemoveIndex = new List(); - for (int i = 0; i < MyChilds.Count; i++) + private void DrawField() + { + Color old = GUI.color; + if (!HasFile) { - FieldModule child = MyChilds[i]; - Type ChildType = child.Class; - if (ChildType != null) - { - Type ChildParentType = ChildType.BaseType; - if (ChildParentType != null) - { - if (NewType == ChildParentType) - { - RemoveIndex.Add(i); - NewChildField.AddChild(child.ScriptFile); - } - } - } + GUI.color = new Color(0.9f, 0.9f, 0.9f); } + // Write Name as Label or Foldout + if (MyChilds.Count == 0) + { + EditorGUILayout.LabelField(Title); + IsExpand = false; + } + else + { + IsExpand = EditorGUILayout.Foldout(IsExpand, Title, true); + } - MyChilds.Add(NewChildField); + // Add Button + if (MyScript != null) + { + if (GUILayout.Button("OpenFile", EditorStyles.label)) + { + AssetDatabase.OpenAsset(MyScript); + } + } - foreach (var Index in RemoveIndex) + GUI.color = old; + } + private FieldModule TraverseHierarchy(Type Target, bool ReturnParent = false) + { + FieldModule ParentField = null; + Type ParentChildType = Target.BaseType; + if (ParentChildType != null) { - if (MyChilds.IsValidIndex(Index)) + if (ParentChildType.Namespace == Target.Namespace) { - MyChilds.RemoveAt(Index); + //Recursive + ParentField = TraverseHierarchy(ParentChildType); } - else + } + if (ParentField == null) + { + ParentField = GetOrCreateField(Target.Namespace); + } + return ReturnParent ? ParentField : ParentField.GetOrCreateField(Target.Name); + } + private void SetFileScript(MonoScript File) + { + MyScript = File; + } + private FieldModule GetOrCreateField(string title) + { + FieldModule Result = FindField(title); + if (Result == null) + { + Result = new FieldModule(title); + MyChilds.Add(Result); + } + return Result; + } + private FieldModule FindField(string title) + { + foreach (var child in MyChilds) + { + if (child.Title == title) + { return child; } + } + return null; + } + private bool TryFindField(string title, out FieldModule module) + { + foreach (var child in MyChilds) + { + if (child.Title == title) { - Debug.LogWarning($"[{Title}] Remove Index is not valid, TargetIndex={Index} , Count={MyChilds.Count}"); + module = child; + return true; } } + module = null; + return false; + } + private void Print(string message) + { + Debug.Log($"[{Title}]: {message}"); } } @@ -170,82 +222,52 @@ private enum FilterType private Vector2 scroll; private MonoScript[] ProjectScripts; - private Dictionary NameSpaces = new Dictionary(); - - private string search = ""; + private FieldModule Root; + private string search = string.Empty; private ComboBox filter; - private bool TEST; + public bool IsSearching + { + get + { + if (!string.IsNullOrEmpty(search)) + return true; + + if (filter.GetValue() != FilterType.All) + return true; + + return false; + } + } [MenuItem("Tools/RealMethod/ClassViewer")] public static void Open() { - GetWindow("Class Viewer"); } private void OnEnable() { filter = new ComboBox("Filter", this); ProjectScripts = LoadScripts(); - foreach (var script in ProjectScripts) - { - if (script != null) - { - Type ScriptType = script.GetClass(); - if (ScriptType != null) - { - if (ScriptType.Namespace != null) - { - if (NameSpaces.TryGetValue(ScriptType.Namespace, out FieldModule Field)) - { - Field.AddChild(script); - } - else - { - FieldModule NewField = new FieldModule(ScriptType.Namespace); - NameSpaces.Add(ScriptType.Namespace, NewField); - NewField.AddChild(script); - } - } - else - { - if (NameSpaces.TryGetValue("NonSpace", out FieldModule Field)) - { - Field.AddChild(script); - } - else - { - FieldModule NewField = new FieldModule("NonSpace"); - NameSpaces.Add("NonSpace", NewField); - NewField.AddChild(script); - } - } - } - else - { - if (NameSpaces.TryGetValue("NoType", out FieldModule Field)) - { - Field.AddChild(script); - } - else - { - FieldModule NewField = new FieldModule("NoType"); - NameSpaces.Add("NoType", NewField); - NewField.AddChild(script); - } - } - - } - } + Preper(); } private void OnGUI() { DrawToolbar(); scroll = EditorGUILayout.BeginScrollView(scroll); - DrawList(); + if (IsSearching) + { + DrawScriptList(); + } + else + { + Root.Draw(); + } EditorGUILayout.EndScrollView(); } + + private void DrawToolbar() { EditorGUILayout.BeginHorizontal(EditorStyles.toolbar); @@ -263,25 +285,23 @@ private void DrawToolbar() search = ""; GUI.FocusControl(null); } + filter.Render(); + if (GUILayout.Button("Refresh", EditorStyles.toolbarButton, GUILayout.Width(70))) { search = ""; - LoadScripts(); + filter.SetValue(FilterType.All); + Root = null; + ProjectScripts = LoadScripts(); + Preper(); } EditorGUILayout.EndHorizontal(); } - private void DrawList() - { - foreach (var item in NameSpaces) - { - item.Value.Draw(); - } - } - private void DrawScriptList(ref MonoScript[] Scripts) + private void DrawScriptList() { - foreach (var script in Scripts) + foreach (var script in ProjectScripts) { if (!PassSearch(script)) continue; if (!PassFilter(script)) continue; @@ -289,9 +309,22 @@ private void DrawScriptList(ref MonoScript[] Scripts) DrawScript(script); } } + void DrawScript(MonoScript script) + { + Type type = script.GetClass(); + string namespaceName = type?.Namespace ?? "No Namespace"; + EditorGUILayout.BeginHorizontal(); + GUILayout.Label($"{script.name}({namespaceName})", GUILayout.Width(200)); + if (GUILayout.Button("OpenFile", EditorStyles.label)) + { + AssetDatabase.OpenAsset(script); + } + + EditorGUILayout.EndHorizontal(); + } private bool PassSearch(MonoScript script) { if (string.IsNullOrEmpty(search)) return true; @@ -311,22 +344,6 @@ private bool PassFilter(MonoScript script) _ => true }; } - private void DrawScript(MonoScript script) - { - Type type = script.GetClass(); - string namespaceName = type?.Namespace ?? "No Namespace"; - - EditorGUILayout.BeginHorizontal(); - - if (GUILayout.Button(script.name, EditorStyles.label, GUILayout.Width(250))) - { - AssetDatabase.OpenAsset(script); - } - - GUILayout.Label(namespaceName); - - EditorGUILayout.EndHorizontal(); - } private MonoScript[] LoadScripts() { List scripts = new List(); @@ -345,11 +362,39 @@ private MonoScript[] LoadScripts() return scripts.ToArray(); } + private void Preper() + { + Root = new FieldModule("Root"); + FieldModule NoneNamespace = new FieldModule("Global (No Namespace)"); + FieldModule NoneClass = new FieldModule("No Type"); + Root.AddChild(NoneNamespace); + Root.AddChild(NoneClass); + foreach (var script in ProjectScripts) + { + if (script != null) + { + Type ScriptType = script.GetClass(); + if (ScriptType != null) + { + if (ScriptType.Namespace != null) + { + Root.AddChild(script); + } + else + { + NoneNamespace.AddChild(new FieldModule(script)); + } + } + else + { + NoneClass.AddChild(new FieldModule(script)); + } + } + } - - - + Root.Expand(); + } } } From 237728ee6fea7feabe7a16be8a9f177d0b2acfff Mon Sep 17 00:00:00 2001 From: Alijimpa Date: Fri, 13 Mar 2026 10:06:20 +0330 Subject: [PATCH 035/204] Refie or rename some editor script --- Editor/ReadySet/Tools/ClassViewerWindow.cs | 4 +- Editor/ReadySet/Tools/HelpWindow.cs | 264 +++++++++++++++++++++ Editor/ReadySet/Tools/HelpWindow.cs.meta | 2 + Tests/TESTWindow.cs | 97 ++++++++ Tests/TESTWindow.cs.meta | 2 + 5 files changed, 367 insertions(+), 2 deletions(-) create mode 100644 Editor/ReadySet/Tools/HelpWindow.cs create mode 100644 Editor/ReadySet/Tools/HelpWindow.cs.meta create mode 100644 Tests/TESTWindow.cs create mode 100644 Tests/TESTWindow.cs.meta diff --git a/Editor/ReadySet/Tools/ClassViewerWindow.cs b/Editor/ReadySet/Tools/ClassViewerWindow.cs index 8755dd8..54e7de0 100644 --- a/Editor/ReadySet/Tools/ClassViewerWindow.cs +++ b/Editor/ReadySet/Tools/ClassViewerWindow.cs @@ -105,7 +105,7 @@ private void DrawField() // Write Name as Label or Foldout if (MyChilds.Count == 0) { - EditorGUILayout.LabelField(Title); + EditorGUILayout.LabelField(Title, GUILayout.Width(300)); IsExpand = false; } else @@ -316,7 +316,7 @@ void DrawScript(MonoScript script) EditorGUILayout.BeginHorizontal(); - GUILayout.Label($"{script.name}({namespaceName})", GUILayout.Width(200)); + GUILayout.Label($"{script.name}({namespaceName})", GUILayout.Width(300)); if (GUILayout.Button("OpenFile", EditorStyles.label)) { diff --git a/Editor/ReadySet/Tools/HelpWindow.cs b/Editor/ReadySet/Tools/HelpWindow.cs new file mode 100644 index 0000000..0a1cc81 --- /dev/null +++ b/Editor/ReadySet/Tools/HelpWindow.cs @@ -0,0 +1,264 @@ +using UnityEngine; +using UnityEditor; +using System.Collections.Generic; +using System.IO; + +namespace RealMethod.Editor +{ + [System.Serializable] + public class HelpNode + { + public string name; + public string toturial; // text after -> + public string link; // text afeter https + public List children = new List(); + } + + public class HelpWindow : EditorWindow + { + private List rootNodes = new List(); + private Dictionary foldoutStates = new Dictionary(); + + private TextAsset textFile; + private Vector2 scrollPos; + private string searchQuery = ""; + + [MenuItem("Tools/RealMethod/Help")] + public static void Open() + { + GetWindow("Help"); + } + + // Unity Methods + private void OnEnable() + { + string ClassViewPath = "Assets/Realmethod/Documentation/Information/Help.txt"; // Just for Test + // string ClassViewPath = Path.Combine(RM_CoreEditor.Documentation, "Help.txt"); + if (!File.Exists(ClassViewPath)) + { + Debug.LogError($"ClassView file not found: {ClassViewPath}"); + Close(); + } + string ClassFile = File.ReadAllText(ClassViewPath); + LoadFromText(ClassFile); + } + private void OnGUI() + { + EditorGUILayout.BeginHorizontal(); + if (GUILayout.Button("Collaps")) + { + foreach (var node in rootNodes) + { + FoldLine(node, false); + } + } + if (GUILayout.Button("Expanded")) + { + foreach (var node in rootNodes) + { + FoldLine(node, true); + } + } + EditorGUILayout.EndHorizontal(); + EditorGUILayout.Space(); + searchQuery = EditorGUILayout.TextField("Search", searchQuery); + + EditorGUILayout.Space(); + + // 🔽 Scroll View + scrollPos = EditorGUILayout.BeginScrollView(scrollPos); + + foreach (var node in rootNodes) + { + DrawNodeWithSearch(node, 0); + } + + EditorGUILayout.EndScrollView(); + // 🔼 Scroll View + } + + private void LoadFromText(string text) + { + rootNodes.Clear(); + foldoutStates.Clear(); + + string[] lines = text.Split('\n'); + Stack stack = new Stack(); + + foreach (string rawLine in lines) + { + if (string.IsNullOrWhiteSpace(rawLine)) + continue; + + int indent = CountIndent(rawLine); + string trimmed = rawLine.Trim(); + + string nodeName = trimmed; + string endText = null; + string linkText = null; + + // 🔹 Parse "-> End Text" + string middleText = null; + int arrowIndex = trimmed.IndexOf("->"); + if (arrowIndex >= 0) + { + nodeName = trimmed.Substring(0, arrowIndex).Trim(); + middleText = trimmed.Substring(arrowIndex + 2).Trim(); + } + + if (middleText != null) + { + int linkindex = middleText.IndexOf("https"); + if (linkindex >= 0) + { + endText = middleText.Substring(0, linkindex).Trim(); + linkText = middleText.Substring(linkindex).Trim(); + } + else + { + endText = middleText; + } + } + + HelpNode node = new HelpNode + { + name = nodeName, + toturial = endText, + link = linkText + }; + + if (indent == 0) + { + rootNodes.Add(node); + stack.Clear(); + stack.Push(node); + } + else + { + while (stack.Count > indent) + stack.Pop(); + + stack.Peek().children.Add(node); + stack.Push(node); + } + } + } + private int CountIndent(string line) + { + int spaces = 0; + foreach (char c in line) + { + if (c == ' ') + spaces++; + else + break; + } + return spaces / 2; // 2 spaces = 1 level + } + + private bool DrawNodeWithSearch(HelpNode node, int indent) + { + // Check if node matches search + bool nodeMatches = string.IsNullOrEmpty(searchQuery) || + node.name.ToLower().Contains(searchQuery.ToLower()) || + node.toturial?.ToLower().Contains(searchQuery.ToLower()) == true; + + // Check if any child matches + bool anyChildMatches = false; + foreach (var child in node.children) + { + if (NodeOrChildrenMatchSearch(child)) + { + anyChildMatches = true; + break; + } + } + + // If nothing matches, skip + if (!nodeMatches && !anyChildMatches) + return false; + + // Draw parent node + if (!foldoutStates.ContainsKey(node)) + foldoutStates[node] = true; + + EditorGUILayout.BeginHorizontal(); + GUILayout.Space(indent * 20); + foldoutStates[node] = + EditorGUILayout.Foldout(foldoutStates[node], node.name, true); + EditorGUILayout.EndHorizontal(); + + // Show endText as link if expanded + if (foldoutStates[node] && !string.IsNullOrEmpty(node.toturial)) + { + EditorGUILayout.BeginHorizontal(); + GUILayout.Space(indent * 20); + EditorGUILayout.BeginVertical("box"); + GUIStyle richLabel = new GUIStyle(EditorStyles.wordWrappedLabel); + richLabel.richText = true; + GUILayout.Label(node.toturial, richLabel); + //GUILayout.Label(node.toturial, new GUIStyle(EditorStyles.wordWrappedLabel)); + if (!string.IsNullOrEmpty(node.link)) + { + if (GUILayout.Button("Link", EditorStyles.linkLabel)) + { + OnEndTextClicked(node); + } + } + EditorGUILayout.EndVertical(); + EditorGUILayout.EndHorizontal(); + } + + + + // Draw children recursively only if expanded + if (foldoutStates[node]) + { + foreach (var child in node.children) + { + DrawNodeWithSearch(child, indent + 1); + } + } + + return true; + } + // Helper: check recursively if a node or any child matches search + private bool NodeOrChildrenMatchSearch(HelpNode node) + { + bool match = string.IsNullOrEmpty(searchQuery) || + node.name.ToLower().Contains(searchQuery.ToLower()) || + node.toturial?.ToLower().Contains(searchQuery.ToLower()) == true; + + if (match) + return true; + + foreach (var child in node.children) + { + if (NodeOrChildrenMatchSearch(child)) + return true; + } + + return false; + } + private void FoldLine(HelpNode node, bool result) + { + foldoutStates[node] = result; + if (foldoutStates[node]) + { + foreach (var child in node.children) + FoldLine(child, result); + } + } + private void OnEndTextClicked(HelpNode node) + { + if (EditorUtility.DisplayDialog("OpenLink", node.link, "Open", "Cancel")) + { + // 3️⃣ OR open URL (if endText is a URL) + Application.OpenURL(node.link); + } + // 2️⃣ OR ping asset + // EditorGUIUtility.PingObject(yourObject); + } + + } +} diff --git a/Editor/ReadySet/Tools/HelpWindow.cs.meta b/Editor/ReadySet/Tools/HelpWindow.cs.meta new file mode 100644 index 0000000..4a30911 --- /dev/null +++ b/Editor/ReadySet/Tools/HelpWindow.cs.meta @@ -0,0 +1,2 @@ +fileFormatVersion: 2 +guid: 15438cb6b5774124f90a5a787acca4c8 \ No newline at end of file diff --git a/Tests/TESTWindow.cs b/Tests/TESTWindow.cs new file mode 100644 index 0000000..bd29791 --- /dev/null +++ b/Tests/TESTWindow.cs @@ -0,0 +1,97 @@ +using System; +using System.Collections.Generic; +using System.Reflection; +using Unity.VisualScripting; +using UnityEditor; +using UnityEngine; + +public class TESTWindow : EditorWindow +{ + private Vector2 scroll; + private MonoScript script; + private List Info = new List(); + + + + [MenuItem("Tools/RealMethod/TEST")] + public static void Open() + { + GetWindow("TEST"); + } + private void OnEnable() + { + + } + private void OnGUI() + { + if (GUILayout.Button("Refresh")) + { + Info.Clear(); + if (script == null) + return; + + AddInfo("name", script.name); + //AddInfo("text", script.text); + Type Scripttype = script.GetClass(); + AddInfo("Class", Scripttype.ToString()); + AddInfo("ClassName", Scripttype.Name); + AddInfo("FullName", Scripttype.FullName); + AddInfo("Namespace", Scripttype.Namespace); + Type Parenttype = Scripttype.BaseType; + AddInfo("Parent", Parenttype.Name); + AddInfo("IsClass", Scripttype.IsClass.ToString()); + AddInfo("IsAbstact", Scripttype.IsAbstract.ToString()); + AddInfo("IsInterface", Scripttype.IsInterface.ToString()); + AddInfo("IsEnum", Scripttype.IsEnum.ToString()); + AddInfo("IsStruct", Scripttype.IsStruct().ToString()); + AddInfo("IsSealed", Scripttype.IsSealed.ToString()); + Type[] Scriptinterfaces = Scripttype.GetInterfaces(); + AddInfo("Interfaces", Scriptinterfaces.Length.ToString()); + for (int i = 0; i < Scriptinterfaces.Length; i++) + { + AddInfo($"{i}", Scriptinterfaces[i].Name); + } + FieldInfo[] fields = Scripttype.GetFields(BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.Static); + AddInfo("Fields", fields.Length.ToString()); + for (int i = 0; i < fields.Length; i++) + { + AddInfo($"{i}.{fields[i].Name}", $"{fields[i].FieldType} - public[{fields[i].IsPublic}], private[{fields[i].IsPrivate}], static[{fields[i].IsStatic}] "); + } + PropertyInfo[] properties = Scripttype.GetProperties(BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.Static); + AddInfo("Properties", properties.Length.ToString()); + for (int i = 0; i < properties.Length; i++) + { + AddInfo($"{i}.{properties[i].Name}", $"{properties[i].PropertyType} - Canread[{properties[i].CanRead}], CanWrite[{properties[i].CanWrite}]"); + } + MethodInfo[] methods = Scripttype.GetMethods(BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.Static); + AddInfo("Methods", methods.Length.ToString()); + for (int i = 0; i < methods.Length; i++) + { + AddInfo($"{i}.{methods[i].Name}", $"{methods[i].ReturnType} - public[{methods[i].IsPublic}], virtual[{methods[i].IsVirtual}], static[{methods[i].IsStatic}]"); + } + ConstructorInfo[] constructors = Scripttype.GetConstructors(); + for (int i = 0; i < constructors.Length; i++) + { + AddInfo($"{i}.{constructors[i].Name}", $"Attributes = {constructors[i].Attributes}"); + } + } + + scroll = EditorGUILayout.BeginScrollView(scroll); + + script = (MonoScript)EditorGUILayout.ObjectField("Script", script, typeof(MonoScript), false); + if (Info != null) + { + foreach (var item in Info) + { + EditorGUILayout.LabelField(item); + } + } + EditorGUILayout.EndScrollView(); + } + + private void AddInfo(string Type, string data) + { + Info.Add($"{Type}: {data}"); + } + +} \ No newline at end of file diff --git a/Tests/TESTWindow.cs.meta b/Tests/TESTWindow.cs.meta new file mode 100644 index 0000000..cc0e2f1 --- /dev/null +++ b/Tests/TESTWindow.cs.meta @@ -0,0 +1,2 @@ +fileFormatVersion: 2 +guid: 6f8cbc3021e49e34c8257f059a685c88 \ No newline at end of file From 6312e6e94bdf04206f4363decaaa7573e4c81920 Mon Sep 17 00:00:00 2001 From: Alijimpa Date: Sat, 14 Mar 2026 14:42:25 +0330 Subject: [PATCH 036/204] Implement LibraryViewer & Refine ClassViewer Seperate Bridge from Library folder in package --- Editor/ReadySet/Tools/ClassViewerWindow.cs | 487 ++++++++++++++------ Editor/ReadySet/Tools/LibraryWindow.cs | 301 ++++++++++++ Editor/ReadySet/Tools/LibraryWindow.cs.meta | 2 + Runtime/Core/Architecture/GameBridge.cs | 27 +- Runtime/Library/Utilities/Math.cs | 5 +- Tests/ScriptInspectorWindow.cs | 131 ++++++ Tests/ScriptInspectorWindow.cs.meta | 2 + 7 files changed, 811 insertions(+), 144 deletions(-) create mode 100644 Editor/ReadySet/Tools/LibraryWindow.cs create mode 100644 Editor/ReadySet/Tools/LibraryWindow.cs.meta create mode 100644 Tests/ScriptInspectorWindow.cs create mode 100644 Tests/ScriptInspectorWindow.cs.meta diff --git a/Editor/ReadySet/Tools/ClassViewerWindow.cs b/Editor/ReadySet/Tools/ClassViewerWindow.cs index 54e7de0..6f0fd3b 100644 --- a/Editor/ReadySet/Tools/ClassViewerWindow.cs +++ b/Editor/ReadySet/Tools/ClassViewerWindow.cs @@ -1,192 +1,248 @@ using System; using System.Collections.Generic; +using System.Data.Common; +using System.Reflection; +using System.Text; using UnityEditor; using UnityEngine; namespace RealMethod.Editor { - class FieldModule + public class ClassViewerWindow : EditorWindow { - private MonoScript MyScript = null; - private List MyChilds = new List(); - private string MyName = string.Empty; + private class FieldModule + { + private ClassViewerWindow MyOwner; + private MonoScript MyScript = null; + private List MyChilds = new List(); + private string MyName = string.Empty; - public string Title - { - get + public string Title { - if (MyName == string.Empty) - { - return MyScript.name; - } - else + get { - return MyName; + if (MyScript != null) + { + return MyScript.GetClass().Name; + } + else + { + return MyName; + } } } - } - public bool HasFile => MyScript != null; - public MonoScript ScriptFile => MyScript; - public bool IsExpand { get; private set; } = false; + public bool HasFile => MyScript != null; + public MonoScript ScriptFile => MyScript; + public bool IsExpand { get; private set; } = false; - public FieldModule(string Name) - { - MyName = Name; - } - public FieldModule(MonoScript script) - { - MyScript = script; - } + public FieldModule(ClassViewerWindow owner, string Name) + { + MyOwner = owner; + MyName = Name; + } + public FieldModule(ClassViewerWindow owner, MonoScript script) + { + MyOwner = owner; + MyScript = script; + } - public void Draw() - { - EditorGUILayout.BeginHorizontal(); - DrawField(); - EditorGUILayout.EndHorizontal(); - if (IsExpand) + + public void Draw() { - EditorGUI.indentLevel++; - foreach (var child in MyChilds) + if (MyScript != null) { - child.Draw(); + if (MyScript.GetClass() == null) + return; + } + + EditorGUILayout.BeginHorizontal(); + DrawField(); + EditorGUILayout.EndHorizontal(); + if (IsExpand) + { + EditorGUI.indentLevel++; + foreach (var child in MyChilds) + { + child.Draw(); + } + EditorGUI.indentLevel--; } - EditorGUI.indentLevel--; } - } - public void AddChild(FieldModule ChildModule) - { - if (ChildModule == null) + public void AddChild(FieldModule ChildModule) { - Print("ChildModule is not valid!"); - return; + if (ChildModule == null) + { + Print("ChildModule is not valid!"); + return; + } + MyChilds.Add(ChildModule); } - MyChilds.Add(ChildModule); - } - public void AddChild(MonoScript File) - { - Type NewType = File.GetClass(); - if (NewType == null || NewType.Namespace == null) + public void AddChild(MonoScript File) { - Print($"MonoScript does't have have any 'MainClass'or'NameSpace' for Child[{File.name}]"); - return; - } + Type NewType = File.GetClass(); + if (NewType == null || NewType.Namespace == null) + { + Print($"MonoScript does't have have any 'MainClass'or'NameSpace' for Child[{File.name}]"); + return; + } - FieldModule NewModule = new FieldModule(File); - FieldModule ParentField = TraverseHierarchy(File.GetClass(), true); + FieldModule NewModule = new FieldModule(MyOwner, File); + FieldModule ParentField = TraverseHierarchy(File.GetClass(), true); - if (ParentField.TryFindField(NewModule.Title, out FieldModule result)) - { - if (!result.HasFile) + if (ParentField.TryFindField(NewModule.Title, out FieldModule result)) + { + if (!result.HasFile) + { + result.SetFileScript(File); + } + } + else { - result.SetFileScript(File); + ParentField.AddChild(NewModule); } + } - else + public void Expand() { - ParentField.AddChild(NewModule); + IsExpand = true; } - } - public void Expand() - { - IsExpand = true; - } - private void DrawField() - { - Color old = GUI.color; - if (!HasFile) + private void DrawField() { - GUI.color = new Color(0.9f, 0.9f, 0.9f); - } + Color old = GUI.color; + if (!HasFile) + { + GUI.color = new Color(0.9f, 0.9f, 0.9f); + } - // Write Name as Label or Foldout - if (MyChilds.Count == 0) + // Write Name as Label or Foldout + if (MyChilds.Count == 0) + { + EditorGUILayout.LabelField(Title, GUILayout.Width(300)); + IsExpand = false; + } + else + { + IsExpand = EditorGUILayout.Foldout(IsExpand, Title, true); + } + + // Add Button + if (MyScript) + { + if (GUILayout.Button("INFO ", EditorStyles.linkLabel)) + { + MyOwner.SelectedScript = MyScript; + } + if (MyScript != null) + { + if (GUILayout.Button("OpenFile ", EditorStyles.linkLabel)) + { + AssetDatabase.OpenAsset(MyScript); + } + } + } + GUI.color = old; + } + private FieldModule TraverseHierarchy(Type Target, bool ReturnParent = false) { - EditorGUILayout.LabelField(Title, GUILayout.Width(300)); - IsExpand = false; + FieldModule ParentField = null; + Type ParentChildType = Target.BaseType; + if (ParentChildType != null) + { + if (ParentChildType.Namespace == Target.Namespace) + { + //Recursive + ParentField = TraverseHierarchy(ParentChildType); + } + } + if (ParentField == null) + { + ParentField = GetOrCreateField(Target.Namespace, true); + if (Target.IsInterface) + { + ParentField = ParentField.GetOrCreateField(""); + } + if (Target.IsValueType && !Target.IsEnum) + { + ParentField = ParentField.GetOrCreateField(""); + } + } + return ReturnParent ? ParentField : ParentField.GetOrCreateField(Target.Name); } - else + private void SetFileScript(MonoScript File) { - IsExpand = EditorGUILayout.Foldout(IsExpand, Title, true); + MyScript = File; } - - // Add Button - if (MyScript != null) + private FieldModule GetOrCreateField(string title, bool IsNameSpace = false) { - if (GUILayout.Button("OpenFile", EditorStyles.label)) + FieldModule Result = FindField(title); + if (Result == null) { - AssetDatabase.OpenAsset(MyScript); + Result = new FieldModule(MyOwner, title); + MyChilds.Add(Result); + if (IsNameSpace) + { + Result.AddChild(new FieldModule(MyOwner, "")); + Result.AddChild(new FieldModule(MyOwner, "")); + } } + return Result; } - - GUI.color = old; - } - private FieldModule TraverseHierarchy(Type Target, bool ReturnParent = false) - { - FieldModule ParentField = null; - Type ParentChildType = Target.BaseType; - if (ParentChildType != null) + private FieldModule FindField(string title) { - if (ParentChildType.Namespace == Target.Namespace) + foreach (var child in MyChilds) { - //Recursive - ParentField = TraverseHierarchy(ParentChildType); + if (child.Title == title) + { return child; } } + return null; } - if (ParentField == null) + private bool TryFindField(string title, out FieldModule module) { - ParentField = GetOrCreateField(Target.Namespace); + foreach (var child in MyChilds) + { + if (child.Title == title) + { + module = child; + return true; + } + } + module = null; + return false; } - return ReturnParent ? ParentField : ParentField.GetOrCreateField(Target.Name); - } - private void SetFileScript(MonoScript File) - { - MyScript = File; - } - private FieldModule GetOrCreateField(string title) - { - FieldModule Result = FindField(title); - if (Result == null) + private void Print(string message) { - Result = new FieldModule(title); - MyChilds.Add(Result); + Debug.Log($"[{Title}]: {message}"); } - return Result; } - private FieldModule FindField(string title) + public class Ceckbox : EditorProperty { - foreach (var child in MyChilds) + public Ceckbox(string Name, UnityEngine.Object other) : base(Name, other) { - if (child.Title == title) - { return child; } } - return null; - } - private bool TryFindField(string title, out FieldModule module) - { - foreach (var child in MyChilds) + + + protected override byte UpdateRender() { - if (child.Title == title) + CashValue = GUILayout.Toggle(CurrentValue, GUIContent.none, GUILayout.Width(18)); + if (CashValue == CurrentValue) { - module = child; - return true; + return 0; + } + else + { + SetValue(CashValue); + return 1; } } - module = null; - return false; - } - private void Print(string message) - { - Debug.Log($"[{Title}]: {message}"); - } - } - + protected override void FixError(int Id) + { + } - public class ClassViewerWindow : EditorWindow - { + } private class ComboBox : EditorProperty where T : Enum { public ComboBox(string Name, UnityEngine.Object other) : base(Name, other) @@ -220,11 +276,16 @@ private enum FilterType Editor } + + private Vector2 scroll; private MonoScript[] ProjectScripts; private FieldModule Root; private string search = string.Empty; private ComboBox filter; + private Ceckbox AdvanceSerach; + private MonoScript SelectedScript; + public bool IsSearching { get @@ -248,6 +309,7 @@ public static void Open() private void OnEnable() { filter = new ComboBox("Filter", this); + AdvanceSerach = new Ceckbox("Checkbox", this); ProjectScripts = LoadScripts(); Preper(); } @@ -264,6 +326,23 @@ private void OnGUI() Root.Draw(); } EditorGUILayout.EndScrollView(); + if (SelectedScript != null) + { + EditorGUILayout.BeginVertical(EditorStyles.helpBox); + EditorGUILayout.BeginHorizontal(); + GUILayout.Label($"{SelectedScript.name}.cs"); + if (GUILayout.Button(GUIContent.none, GUI.skin.FindStyle("ToolbarSearchCancelButton"))) + { + SelectedScript = null; + } + EditorGUILayout.EndHorizontal(); + EditorGUILayout.TextArea(Analyze(SelectedScript), GUILayout.ExpandHeight(true)); + EditorGUILayout.EndVertical(); + } + EditorGUILayout.HelpBox( + " Note: This inspector uses reflection and can only detect the primary type in this script and its nested types. " + + "Additional classes, structs, enums, or interfaces declared outside the main type in the same file will not appear.", + MessageType.Info); } @@ -272,6 +351,8 @@ private void DrawToolbar() { EditorGUILayout.BeginHorizontal(EditorStyles.toolbar); + AdvanceSerach.Render(); + search = GUILayout.TextField( search, GUI.skin.FindStyle("ToolbarSearchTextField"), @@ -294,6 +375,7 @@ private void DrawToolbar() filter.SetValue(FilterType.All); Root = null; ProjectScripts = LoadScripts(); + SelectedScript = null; Preper(); } @@ -309,16 +391,22 @@ private void DrawScriptList() DrawScript(script); } } - void DrawScript(MonoScript script) + private void DrawScript(MonoScript script) { + Vector2 scroller = Vector2.zero; Type type = script.GetClass(); string namespaceName = type?.Namespace ?? "No Namespace"; EditorGUILayout.BeginHorizontal(); - GUILayout.Label($"{script.name}({namespaceName})", GUILayout.Width(300)); + GUILayout.Label($"{script.name}({namespaceName})", GUILayout.Width(400)); + + if (GUILayout.Button("INFO ", EditorStyles.linkLabel)) + { + SelectedScript = script; + } - if (GUILayout.Button("OpenFile", EditorStyles.label)) + if (GUILayout.Button("OpenFile ", EditorStyles.linkLabel)) { AssetDatabase.OpenAsset(script); } @@ -329,7 +417,19 @@ private bool PassSearch(MonoScript script) { if (string.IsNullOrEmpty(search)) return true; - return script.name.IndexOf(search, StringComparison.OrdinalIgnoreCase) >= 0; + string Result = string.Empty; + if (AdvanceSerach.GetValue()) + { + Result = GetScriptInfo(script); + } + else + { + string type = script.GetClass() != null ? script.GetClass().Name : string.Empty; + Result = $"{script.name},{type}"; + } + + return Result.IndexOf(search, StringComparison.OrdinalIgnoreCase) >= 0; + } private bool PassFilter(MonoScript script) { @@ -344,6 +444,29 @@ private bool PassFilter(MonoScript script) _ => true }; } + private string GetScriptInfo(MonoScript script) + { + if (script == null) return ""; + + Type type = script.GetClass(); + if (type == null) return script.name; + + string result = + script.name + "," + + type.Name + "," + + type.Namespace + "," + + (type.BaseType != null ? type.BaseType.Name : ""); + + var nestedTypes = type.GetNestedTypes( + BindingFlags.Public | BindingFlags.NonPublic); + + foreach (var nested in nestedTypes) + { + result += "," + nested.Name; + } + + return result; + } private MonoScript[] LoadScripts() { List scripts = new List(); @@ -362,11 +485,99 @@ private MonoScript[] LoadScripts() return scripts.ToArray(); } + private string Analyze(MonoScript script) + { + if (script == null) + { + return "No script selected."; + } + + Type type = script.GetClass(); + + if (type == null) + { + return "Could not find class in script."; + } + + StringBuilder sb = new StringBuilder(); + + sb.AppendLine("=== SCRIPT INFO ==="); + sb.AppendLine($"Namespace: {type.Namespace}"); + sb.AppendLine($"Class: {type.Name}"); + sb.AppendLine($"Abstract: {type.IsAbstract}"); + sb.AppendLine($"Sealed: {type.IsSealed}"); + sb.AppendLine($"Static: {type.IsAbstract && type.IsSealed}"); + sb.AppendLine(""); + + BindingFlags flags = + BindingFlags.Public | + BindingFlags.NonPublic | + BindingFlags.Instance | + BindingFlags.Static | + BindingFlags.DeclaredOnly; + + // Fields + sb.AppendLine("=== FIELDS ==="); + foreach (var field in type.GetFields(flags)) + { + sb.AppendLine($"{GetAccess(field)} {field.FieldType.Name} {field.Name}"); + } + + sb.AppendLine(""); + + // Properties + sb.AppendLine("=== PROPERTIES ==="); + foreach (var prop in type.GetProperties(flags)) + { + sb.AppendLine($"{prop.PropertyType.Name} {prop.Name}"); + } + + sb.AppendLine(""); + + // Methods + sb.AppendLine("=== METHODS ==="); + foreach (var method in type.GetMethods(flags)) + { + if (method.IsSpecialName) continue; + + sb.Append($"{GetAccess(method)} {method.ReturnType.Name} {method.Name}("); + + var parameters = method.GetParameters(); + + for (int i = 0; i < parameters.Length; i++) + { + sb.Append($"{parameters[i].ParameterType.Name} {parameters[i].Name}"); + + if (i < parameters.Length - 1) + sb.Append(", "); + } + + sb.AppendLine(")"); + } + + return sb.ToString(); + } + private string GetAccess(FieldInfo field) + { + if (field.IsPublic) return "public"; + if (field.IsPrivate) return "private"; + if (field.IsFamily) return "protected"; + if (field.IsAssembly) return "internal"; + return ""; + } + private string GetAccess(MethodInfo method) + { + if (method.IsPublic) return "public"; + if (method.IsPrivate) return "private"; + if (method.IsFamily) return "protected"; + if (method.IsAssembly) return "internal"; + return ""; + } private void Preper() { - Root = new FieldModule("Root"); - FieldModule NoneNamespace = new FieldModule("Global (No Namespace)"); - FieldModule NoneClass = new FieldModule("No Type"); + Root = new FieldModule(this, "Root"); + FieldModule NoneNamespace = new FieldModule(this, " (No Namespace)"); + FieldModule NoneClass = new FieldModule(this, " (No Type)"); Root.AddChild(NoneNamespace); Root.AddChild(NoneClass); @@ -383,12 +594,12 @@ private void Preper() } else { - NoneNamespace.AddChild(new FieldModule(script)); + NoneNamespace.AddChild(new FieldModule(this, script)); } } else { - NoneClass.AddChild(new FieldModule(script)); + NoneClass.AddChild(new FieldModule(this, script)); } } diff --git a/Editor/ReadySet/Tools/LibraryWindow.cs b/Editor/ReadySet/Tools/LibraryWindow.cs new file mode 100644 index 0000000..c748f12 --- /dev/null +++ b/Editor/ReadySet/Tools/LibraryWindow.cs @@ -0,0 +1,301 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Reflection; +using System.Text; +using UnityEditor; +using UnityEngine; + +namespace RealMethod.Editor +{ + public class LibraryWindow : EditorWindow + { + private class FieldModule + { + private Vector2 scroll; + private MonoScript File; + + + public Type Class { get; private set; } + public MethodInfo TargetMethod { get; private set; } + public string Title + { + get + { + return $"{Class.Name}.{TargetMethod.Name}"; + } + } + public bool IsExpand { get; private set; } = false; + public bool isStatic => Class.IsAbstract && Class.IsSealed; + + public FieldModule(MonoScript script, MethodInfo method) + { + File = script; + + if (method == null) + Print("Method is not valid!"); + TargetMethod = method; + + Type ClassType = script.GetClass(); + if (ClassType == null) + Print("Class is not valid!"); + Class = ClassType; + } + + public void Render() + { + EditorGUILayout.BeginHorizontal(); + IsExpand = EditorGUILayout.Foldout(IsExpand, $"{Title}({TargetMethod.GetParameters().Length})", true); + if (GUILayout.Button("OpenFile ", EditorStyles.linkLabel)) + { + Debug.Log("sdsdsd"); + AssetDatabase.OpenAsset(File); + } + EditorGUILayout.EndHorizontal(); + if (IsExpand) + { + EditorGUI.indentLevel++; + //EditorGUI.BeginDisabledGroup(true); + scroll = EditorGUILayout.BeginScrollView(scroll, GUILayout.Height(120)); + EditorGUILayout.TextArea(GetMethodBody(File, TargetMethod)); + EditorGUILayout.EndScrollView(); + //EditorGUI.EndDisabledGroup(); + EditorGUI.indentLevel--; + } + + } + + private string GetMethodBody(MonoScript script, MethodInfo method) + { + string path = AssetDatabase.GetAssetPath(script); + if (string.IsNullOrEmpty(path)) + { + return "Invalid script path."; + } + string[] lines = System.IO.File.ReadAllLines(path); + + StringBuilder sb = new StringBuilder(); + + int MethodLineNumber = -1; + for (int i = 0; i < lines.Length; i++) + { + if (lines[i].Contains(method.Name)) + { + MethodLineNumber = i; + break; + } + } + + if (MethodLineNumber == -1) + { + return "Something wrong!"; + } + + for (int i = MethodLineNumber; i < MethodLineNumber + 10; i++) + { + sb.AppendLine(lines[i]); + } + return sb.ToString(); + } + private void Print(string message) + { + Debug.Log($"[{Title}]: {message}"); + } + } + private class Dropdown : EditorProperty + { + private string[] Options; + public string CurrentOption => Options[GetValue()]; + + public Dropdown(string Name, string[] options, UnityEngine.Object other) : base(Name, other) + { + Options = options; + } + + protected override byte UpdateRender() + { + CashValue = EditorGUILayout.Popup(string.Empty, CurrentValue, Options, GUI.skin.FindStyle("ToolbarPopup"), GUILayout.Width(120)); + if (CashValue == CurrentValue) + { + return 0; // No change + } + else + { + SetValue(CashValue); + return 1; // Changed + } + } + protected override void FixError(int Id) + { + throw new NotImplementedException(); + } + } + + + private Vector2 scroll; + private Dropdown NameSpace_Filter; + private MonoScript[] Scripts; + private List Fields = new List(0); + private string search = string.Empty; + + + [MenuItem("Tools/RealMethod/LibraryWindow")] + public static void Open() + { + GetWindow("Library Window"); + } + private void OnEnable() + { + + Scripts = LoadScripts(); + CreateNameSpaceList(); + ReSetField(); + } + private void OnGUI() + { + DrawToolbar(); + scroll = EditorGUILayout.BeginScrollView(scroll); + foreach (var field in Fields) + { + if (!PassSearch(field)) continue; + if (!PassFilter(field)) continue; + + field.Render(); + } + EditorGUILayout.EndScrollView(); + EditorGUILayout.HelpBox( + " Note: This inspector uses reflection and can only detect the primary type in this script and its nested types. " + + "Additional classes, structs, enums, or interfaces declared outside the main type in the same file will not appear.", + MessageType.Info); + } + + + private void ReSetField() + { + Fields.Clear(); + + BindingFlags flags = + BindingFlags.Public | + BindingFlags.NonPublic | + BindingFlags.Instance | + BindingFlags.Static | + BindingFlags.DeclaredOnly; + + foreach (var script in Scripts) + { + Type mainType = script.GetClass(); + if (mainType == null) + continue; + + if (mainType.IsAbstract && mainType.IsSealed) + { + Type[] nestedTypes = mainType.GetNestedTypes(BindingFlags.Public); + foreach (var classtype in nestedTypes) + { + foreach (var method in classtype.GetMethods(flags)) + { + if (method.IsSpecialName) continue; + + if (!method.IsPublic) continue; + + if (!method.IsStatic) continue; + + if (method.IsDefined(typeof(System.Runtime.CompilerServices.ExtensionAttribute), false)) continue; + + Fields.Add(new FieldModule(script, method)); + } + } + } + + } + } + private void DrawToolbar() + { + EditorGUILayout.BeginHorizontal(EditorStyles.toolbar); + + search = GUILayout.TextField(search, GUI.skin.FindStyle("ToolbarSearchTextField"), GUILayout.ExpandWidth(true)); + + if (GUILayout.Button(GUIContent.none, GUI.skin.FindStyle("ToolbarSearchCancelButton"))) + { + search = ""; + GUI.FocusControl(null); + } + + if (NameSpace_Filter.Render() == 1) + ReSetField(); + + if (GUILayout.Button("Refresh", EditorStyles.toolbarButton, GUILayout.Width(70))) + { + search = ""; + Scripts = LoadScripts(); + CreateNameSpaceList(); + ReSetField(); + } + + EditorGUILayout.EndHorizontal(); + } + private bool PassSearch(FieldModule Field) + { + if (string.IsNullOrEmpty(search)) return true; + + return Field.Title.IndexOf(search, StringComparison.OrdinalIgnoreCase) >= 0; + } + private bool PassFilter(FieldModule Field) + { + if (NameSpace_Filter.GetValue() == 0) + return true; + + if (Field.Class.Namespace == NameSpace_Filter.CurrentOption) + return true; + + return false; + } + private void CreateNameSpaceList() + { + int RealMethodIndex = 0; + HashSet NameSpaceList = new HashSet() { "All" }; + foreach (var script in Scripts) + { + if (script == null) + continue; + + Type ClassType = script.GetClass(); + if (ClassType != null) + { + if (!string.IsNullOrEmpty(ClassType.Namespace)) + { + if (NameSpaceList.Add(ClassType.Namespace)) + { + if (ClassType.Namespace == "RealMethod") + { + RealMethodIndex = NameSpaceList.Count - 1; + } + } + } + } + } + // Set NameSpace Lisst to Dropdown box + NameSpace_Filter = new Dropdown("Filter", NameSpaceList.ToArray(), this); + NameSpace_Filter.SetValue(RealMethodIndex); + } + private MonoScript[] LoadScripts() + { + List scripts = new List(); + + string[] guids = AssetDatabase.FindAssets("t:MonoScript"); + + foreach (string guid in guids) + { + string path = AssetDatabase.GUIDToAssetPath(guid); + MonoScript script = AssetDatabase.LoadAssetAtPath(path); + + scripts.Add(script); + } + + scripts.Sort((a, b) => a.name.CompareTo(b.name)); + + return scripts.ToArray(); + } + + } +} \ No newline at end of file diff --git a/Editor/ReadySet/Tools/LibraryWindow.cs.meta b/Editor/ReadySet/Tools/LibraryWindow.cs.meta new file mode 100644 index 0000000..890bcc2 --- /dev/null +++ b/Editor/ReadySet/Tools/LibraryWindow.cs.meta @@ -0,0 +1,2 @@ +fileFormatVersion: 2 +guid: 5ff9e75fbed2b884b83172d51263511a \ No newline at end of file diff --git a/Runtime/Core/Architecture/GameBridge.cs b/Runtime/Core/Architecture/GameBridge.cs index 9209b59..84d46a8 100644 --- a/Runtime/Core/Architecture/GameBridge.cs +++ b/Runtime/Core/Architecture/GameBridge.cs @@ -331,6 +331,29 @@ public virtual IEnumerator GetLoadWorldCorotine(WorldSceneConfig WorldScene) } + + private float RemapClamped(float value, float inMin, float inMax, float outMin, float outMax) + { + // Prevent divide by zero + if (Mathf.Approximately(inMax, inMin)) + { + Debug.LogWarning("Input range is zero. Returning outMin."); + return outMin; + } + + // Normalize the input value to 0–1 within the input range + float t = (value - inMin) / (inMax - inMin); + + // Scale and offset to target range + float mappedValue = t * (outMax - outMin) + outMin; + + // Clamp result to the output range + return Mathf.Clamp(mappedValue, Mathf.Min(outMin, outMax), Mathf.Max(outMin, outMax)); + } + + + + // Corotine private IEnumerator LoadSceneAsync(string scene, int scneIndex = -1) { @@ -429,7 +452,7 @@ private IEnumerator LoadWorldAsync(WorldSceneConfig WS) } while (!Load_opertation.isDone) { - SceneLoadingProcessEvent?.Invoke(RM_Math.Map.RemapClamped(Load_opertation.progress, 0, 1, 0, 1 / WS.Count + 1)); + SceneLoadingProcessEvent?.Invoke(RemapClamped(Load_opertation.progress, 0, 1, 0, 1 / WS.Count + 1)); SceneLoadingEvent?.Invoke(false); isLoading = false; yield return null; @@ -448,7 +471,7 @@ private IEnumerator LoadWorldAsync(WorldSceneConfig WS) } while (!Additive_Load_opertation.isDone) { - SceneLoadingProcessEvent?.Invoke(RM_Math.Map.RemapClamped(Load_opertation.progress, 0, 1, 0, 1 / WS.Count + 1 - (i + 1))); + SceneLoadingProcessEvent?.Invoke(RemapClamped(Load_opertation.progress, 0, 1, 0, 1 / WS.Count + 1 - (i + 1))); yield return null; } } diff --git a/Runtime/Library/Utilities/Math.cs b/Runtime/Library/Utilities/Math.cs index aa92e9d..0c98c4b 100644 --- a/Runtime/Library/Utilities/Math.cs +++ b/Runtime/Library/Utilities/Math.cs @@ -7,9 +7,7 @@ public static class RM_Math { public static Vector3 TwoD => new Vector3(1, 0, 1); - public class Map - { - /// + /// /// Maps a float value from one range to another and clamps the result to the output range. /// /// The input value to map. @@ -52,7 +50,6 @@ public static bool IsInRange(float value, float min, float max, bool inclusiveMi return isAboveMin && isBelowMax; } - } public class Interpolate { diff --git a/Tests/ScriptInspectorWindow.cs b/Tests/ScriptInspectorWindow.cs new file mode 100644 index 0000000..3c17f81 --- /dev/null +++ b/Tests/ScriptInspectorWindow.cs @@ -0,0 +1,131 @@ +using UnityEngine; +using UnityEditor; +using System; +using System.Reflection; +using System.Text; + +public class ScriptInspectorWindow : EditorWindow +{ + private MonoScript script; + private Vector2 scroll; + private string output; + + [MenuItem("Tools/Script Inspector")] + static void Open() + { + GetWindow("Script Inspector"); + } + + void OnGUI() + { + EditorGUILayout.LabelField("Select MonoScript", EditorStyles.boldLabel); + + script = (MonoScript)EditorGUILayout.ObjectField( + "Script", + script, + typeof(MonoScript), + false); + + if (GUILayout.Button("Analyze Script")) + { + Analyze(); + } + + scroll = EditorGUILayout.BeginScrollView(scroll); + + EditorGUILayout.TextArea(output, GUILayout.ExpandHeight(true)); + + EditorGUILayout.EndScrollView(); + } + + void Analyze() + { + if (script == null) + { + output = "No script selected."; + return; + } + + Type type = script.GetClass(); + + if (type == null) + { + output = "Could not find class in script."; + return; + } + + StringBuilder sb = new StringBuilder(); + + sb.AppendLine("=== SCRIPT INFO ==="); + sb.AppendLine($"Namespace: {type.Namespace}"); + sb.AppendLine($"Class: {type.Name}"); + sb.AppendLine($"Abstract: {type.IsAbstract}"); + sb.AppendLine($"Sealed: {type.IsSealed}"); + sb.AppendLine($"Static: {type.IsAbstract && type.IsSealed}"); + sb.AppendLine(""); + + BindingFlags flags = + BindingFlags.Public | + BindingFlags.NonPublic | + BindingFlags.Instance | + BindingFlags.Static | + BindingFlags.DeclaredOnly; + + // Fields + sb.AppendLine("=== FIELDS ==="); + foreach (var field in type.GetFields(flags)) + { + sb.AppendLine($"{GetAccess(field)} {field.FieldType.Name} {field.Name}"); + } + + sb.AppendLine(""); + + // Properties + sb.AppendLine("=== PROPERTIES ==="); + foreach (var prop in type.GetProperties(flags)) + { + sb.AppendLine($"{prop.PropertyType.Name} {prop.Name}"); + } + + sb.AppendLine(""); + + // Methods + sb.AppendLine("=== METHODS ==="); + foreach (var method in type.GetMethods(flags)) + { + if (method.IsSpecialName) continue; + + sb.Append($"{GetAccess(method)} {method.ReturnType.Name} {method.Name}("); + + var parameters = method.GetParameters(); + + for (int i = 0; i < parameters.Length; i++) + { + sb.Append($"{parameters[i].ParameterType.Name} {parameters[i].Name}"); + + if (i < parameters.Length - 1) + sb.Append(", "); + } + + sb.AppendLine(")"); + } + + output = sb.ToString(); + } + string GetAccess(FieldInfo field) + { + if (field.IsPublic) return "public"; + if (field.IsPrivate) return "private"; + if (field.IsFamily) return "protected"; + if (field.IsAssembly) return "internal"; + return ""; + } + string GetAccess(MethodInfo method) + { + if (method.IsPublic) return "public"; + if (method.IsPrivate) return "private"; + if (method.IsFamily) return "protected"; + if (method.IsAssembly) return "internal"; + return ""; + } +} diff --git a/Tests/ScriptInspectorWindow.cs.meta b/Tests/ScriptInspectorWindow.cs.meta new file mode 100644 index 0000000..2b73dff --- /dev/null +++ b/Tests/ScriptInspectorWindow.cs.meta @@ -0,0 +1,2 @@ +fileFormatVersion: 2 +guid: b22bcee86d200fc468dcb300ec53b62d \ No newline at end of file From c7e7a9268c091b41ff482a39cf4eaff36158e62d Mon Sep 17 00:00:00 2001 From: Alijimpa Date: Sat, 14 Mar 2026 16:15:00 +0330 Subject: [PATCH 037/204] Refactor all Utility library in realmethod --- .../RealMethod_ProjectSetting.cs | 8 +- .../{Assets.cs => Assets_Library.cs} | 4 +- ...{Assets.cs.meta => Assets_Library.cs.meta} | 0 .../Utilities/{CSV.cs => CSV_Library.cs} | 3 - .../{CSV.cs.meta => CSV_Library.cs.meta} | 0 Editor/Library/Utilities/Core.cs | 37 ---- Editor/Library/Utilities/Create_Library.cs | 45 +++++ ...{Create.cs.meta => Create_Library.cs.meta} | 0 .../{Create.cs => Editor_Library.cs} | 80 ++++----- .../{Core.cs.meta => Editor_Library.cs.meta} | 0 ...MetaDataHandler.cs => MetaData_Library.cs} | 18 +- ...ndler.cs.meta => MetaData_Library.cs.meta} | 0 .../Content/RealMethod_ScriptTemplate.cs | 70 ++++---- Editor/ReadySet/Tools/ClassViewerWindow.cs | 2 +- ...ibraryWindow.cs => LibraryViewerWindow.cs} | 52 +++--- ...ow.cs.meta => LibraryViewerWindow.cs.meta} | 0 .../Toolkit/Ability/Ability_ScriptTemplate.cs | 6 +- Editor/Toolkit/Actor/Actor_ScriptTemplate.cs | 2 +- .../Inventory/Inventory_ScriptTemplate.cs | 2 +- Editor/Toolkit/PCG/PCGEditorWindow.cs | 2 +- Editor/Toolkit/PCG/PCG_ScriptTemplate.cs | 2 +- .../Toolkit/Pickup/Pickup_ScriptTemplate.cs | 4 +- Editor/Toolkit/RPG/RPG_ScriptTemplate.cs | 8 +- Editor/Toolkit/TerrainTools/TerrainEditor.cs | 4 +- .../Tutorial/Tutorial_ScriptTemplate.cs | 6 +- .../Toolkit/Upgrade/Upgrade_ScriptTemplate.cs | 4 +- Runtime/Core/Architecture/World.cs | 6 +- Runtime/Library/Extension/Animator.cs | 2 +- .../Library/Utilities/Animation_Library.cs | 43 +++++ .../Utilities/Animation_Library.cs.meta | 2 + .../Library/Utilities/Collection_Library.cs | 38 +++++ .../Utilities/Collection_Library.cs.meta | 2 + Runtime/Library/Utilities/Core.cs | 149 ---------------- Runtime/Library/Utilities/Core.cs.meta | 2 - Runtime/Library/Utilities/Coroutine.cs | 124 -------------- Runtime/Library/Utilities/Coroutine.cs.meta | 2 - Runtime/Library/Utilities/Debug_Library.cs | 29 ++++ .../Library/Utilities/Debug_Library.cs.meta | 2 + Runtime/Library/Utilities/Draw.cs | 118 ------------- Runtime/Library/Utilities/Draw.cs.meta | 2 - Runtime/Library/Utilities/Enum_Library.cs | 27 +++ .../Library/Utilities/Enum_Library.cs.meta | 2 + Runtime/Library/Utilities/File_Library.cs | 85 ++++++++++ .../Library/Utilities/File_Library.cs.meta | 2 + Runtime/Library/Utilities/Geometry.cs | 37 ---- Runtime/Library/Utilities/Geometry.cs.meta | 2 - Runtime/Library/Utilities/Gizmos_Library.cs | 100 +++++++++++ .../Library/Utilities/Gizmos_Library.cs.meta | 2 + Runtime/Library/Utilities/Math.cs | 159 ------------------ Runtime/Library/Utilities/Math_Library.cs | 154 +++++++++++++++++ .../{Math.cs.meta => Math_Library.cs.meta} | 0 Runtime/Library/Utilities/Physics.cs | 51 ------ Runtime/Library/Utilities/Physics.cs.meta | 2 - .../Library/Utilities/Reflection_Library.cs | 35 ++++ .../Utilities/Reflection_Library.cs.meta | 2 + .../{PlayerPrefs.cs => Save_Library.cs} | 2 +- ...ayerPrefs.cs.meta => Save_Library.cs.meta} | 0 Runtime/Library/Utilities/Time_Library.cs | 68 ++++++++ .../Library/Utilities/Time_Library.cs.meta | 2 + Runtime/Library/Utilities/Trace_Library.cs | 70 ++++++++ .../Library/Utilities/Trace_Library.cs.meta | 2 + .../Library/Utilities/Transform_Library.cs | 26 +++ .../Utilities/Transform_Library.cs.meta | 2 + Runtime/Library/Utilities/Tween_Library.cs | 68 ++++++++ .../Library/Utilities/Tween_Library.cs.meta | 2 + Runtime/Library/Utilities/UI_Library.cs | 26 +++ Runtime/Library/Utilities/UI_Library.cs.meta | 2 + Runtime/Library/Utilities/Vector_Library.cs | 31 ++++ .../Library/Utilities/Vector_Library.cs.meta | 2 + .../Toolkit/Inventory/InventorySaveFile.cs | 12 +- Runtime/Toolkit/RPG/StatSystem/BuffConfig.cs | 2 +- .../Toolkit/RPG/StatSystem/StatSaveFile.cs | 16 +- Runtime/Toolkit/Tutorial/TutorialSaveFile.cs | 4 +- Runtime/Toolkit/Upgrade/UpgradeSaveFile.cs | 8 +- Tests/ScriptInspectorWindow.cs | 131 --------------- Tests/ScriptInspectorWindow.cs.meta | 2 - Tests/TESTWindow.cs | 97 ----------- Tests/TESTWindow.cs.meta | 2 - 78 files changed, 1033 insertions(+), 1084 deletions(-) rename Editor/Library/Utilities/{Assets.cs => Assets_Library.cs} (85%) rename Editor/Library/Utilities/{Assets.cs.meta => Assets_Library.cs.meta} (100%) rename Editor/Library/Utilities/{CSV.cs => CSV_Library.cs} (99%) rename Editor/Library/Utilities/{CSV.cs.meta => CSV_Library.cs.meta} (100%) delete mode 100644 Editor/Library/Utilities/Core.cs create mode 100644 Editor/Library/Utilities/Create_Library.cs rename Editor/Library/Utilities/{Create.cs.meta => Create_Library.cs.meta} (100%) rename Editor/Library/Utilities/{Create.cs => Editor_Library.cs} (61%) rename Editor/Library/Utilities/{Core.cs.meta => Editor_Library.cs.meta} (100%) rename Editor/Library/Utilities/{MetaDataHandler.cs => MetaData_Library.cs} (90%) rename Editor/Library/Utilities/{MetaDataHandler.cs.meta => MetaData_Library.cs.meta} (100%) rename Editor/ReadySet/Tools/{LibraryWindow.cs => LibraryViewerWindow.cs} (90%) rename Editor/ReadySet/Tools/{LibraryWindow.cs.meta => LibraryViewerWindow.cs.meta} (100%) create mode 100644 Runtime/Library/Utilities/Animation_Library.cs create mode 100644 Runtime/Library/Utilities/Animation_Library.cs.meta create mode 100644 Runtime/Library/Utilities/Collection_Library.cs create mode 100644 Runtime/Library/Utilities/Collection_Library.cs.meta delete mode 100644 Runtime/Library/Utilities/Core.cs delete mode 100644 Runtime/Library/Utilities/Core.cs.meta delete mode 100644 Runtime/Library/Utilities/Coroutine.cs delete mode 100644 Runtime/Library/Utilities/Coroutine.cs.meta create mode 100644 Runtime/Library/Utilities/Debug_Library.cs create mode 100644 Runtime/Library/Utilities/Debug_Library.cs.meta delete mode 100644 Runtime/Library/Utilities/Draw.cs delete mode 100644 Runtime/Library/Utilities/Draw.cs.meta create mode 100644 Runtime/Library/Utilities/Enum_Library.cs create mode 100644 Runtime/Library/Utilities/Enum_Library.cs.meta create mode 100644 Runtime/Library/Utilities/File_Library.cs create mode 100644 Runtime/Library/Utilities/File_Library.cs.meta delete mode 100644 Runtime/Library/Utilities/Geometry.cs delete mode 100644 Runtime/Library/Utilities/Geometry.cs.meta create mode 100644 Runtime/Library/Utilities/Gizmos_Library.cs create mode 100644 Runtime/Library/Utilities/Gizmos_Library.cs.meta delete mode 100644 Runtime/Library/Utilities/Math.cs create mode 100644 Runtime/Library/Utilities/Math_Library.cs rename Runtime/Library/Utilities/{Math.cs.meta => Math_Library.cs.meta} (100%) delete mode 100644 Runtime/Library/Utilities/Physics.cs delete mode 100644 Runtime/Library/Utilities/Physics.cs.meta create mode 100644 Runtime/Library/Utilities/Reflection_Library.cs create mode 100644 Runtime/Library/Utilities/Reflection_Library.cs.meta rename Runtime/Library/Utilities/{PlayerPrefs.cs => Save_Library.cs} (99%) rename Runtime/Library/Utilities/{PlayerPrefs.cs.meta => Save_Library.cs.meta} (100%) create mode 100644 Runtime/Library/Utilities/Time_Library.cs create mode 100644 Runtime/Library/Utilities/Time_Library.cs.meta create mode 100644 Runtime/Library/Utilities/Trace_Library.cs create mode 100644 Runtime/Library/Utilities/Trace_Library.cs.meta create mode 100644 Runtime/Library/Utilities/Transform_Library.cs create mode 100644 Runtime/Library/Utilities/Transform_Library.cs.meta create mode 100644 Runtime/Library/Utilities/Tween_Library.cs create mode 100644 Runtime/Library/Utilities/Tween_Library.cs.meta create mode 100644 Runtime/Library/Utilities/UI_Library.cs create mode 100644 Runtime/Library/Utilities/UI_Library.cs.meta create mode 100644 Runtime/Library/Utilities/Vector_Library.cs create mode 100644 Runtime/Library/Utilities/Vector_Library.cs.meta delete mode 100644 Tests/ScriptInspectorWindow.cs delete mode 100644 Tests/ScriptInspectorWindow.cs.meta delete mode 100644 Tests/TESTWindow.cs delete mode 100644 Tests/TESTWindow.cs.meta diff --git a/Editor/Core/ProjectSetting/RealMethod_ProjectSetting.cs b/Editor/Core/ProjectSetting/RealMethod_ProjectSetting.cs index c755752..ca68ee7 100644 --- a/Editor/Core/ProjectSetting/RealMethod_ProjectSetting.cs +++ b/Editor/Core/ProjectSetting/RealMethod_ProjectSetting.cs @@ -151,7 +151,7 @@ public static SettingsProvider CreateSettingsProvider() // Attempt to load the settings asset if (!GetSettingStorage(out TargetStorage)) { - if (Directory.Exists(Path.GetDirectoryName(RM_CoreEditor.SetttingAssetPath))) + if (Directory.Exists(Path.GetDirectoryName(RM_Editor.SetttingAssetPath))) { TargetStorage = CreateSettingStorage(); } @@ -202,7 +202,7 @@ public static SettingsProvider CreateSettingsProvider() } else { - EditorGUILayout.HelpBox($"The Address is not valid {Path.GetDirectoryName(RM_CoreEditor.SetttingAssetPath)}", MessageType.Error); + EditorGUILayout.HelpBox($"The Address is not valid {Path.GetDirectoryName(RM_Editor.SetttingAssetPath)}", MessageType.Error); if (GUILayout.Button("Fix")) { if (!Directory.Exists("Assets/Resources")) @@ -233,7 +233,7 @@ public static SettingsProvider CreateSettingsProvider() public static bool GetSettingStorage(out ProjectSettingAsset settings) { // Attempt to load the settings asset from the specified path - settings = AssetDatabase.LoadAssetAtPath(RM_CoreEditor.SetttingAssetPath); + settings = AssetDatabase.LoadAssetAtPath(RM_Editor.SetttingAssetPath); AddExteraSections(settings); return settings != null; } @@ -241,7 +241,7 @@ private static ProjectSettingAsset CreateSettingStorage() { // Create a new settings asset at the specified path ProjectSettingAsset settings = ScriptableObject.CreateInstance(); - AssetDatabase.CreateAsset(settings, RM_CoreEditor.SetttingAssetPath); + AssetDatabase.CreateAsset(settings, RM_Editor.SetttingAssetPath); AssetDatabase.SaveAssets(); AddExteraSections(settings); return settings; diff --git a/Editor/Library/Utilities/Assets.cs b/Editor/Library/Utilities/Assets_Library.cs similarity index 85% rename from Editor/Library/Utilities/Assets.cs rename to Editor/Library/Utilities/Assets_Library.cs index 4ac6679..7767404 100644 --- a/Editor/Library/Utilities/Assets.cs +++ b/Editor/Library/Utilities/Assets_Library.cs @@ -4,9 +4,9 @@ namespace RealMethod.Editor { - public class RM_Assets + public static class RM_Asset { - public static string GetSelectedAssetPath() + public static string GetSelectedAssetDirectory() { string path = AssetDatabase.GetAssetPath(Selection.activeObject); if (string.IsNullOrEmpty(path)) return "Assets"; diff --git a/Editor/Library/Utilities/Assets.cs.meta b/Editor/Library/Utilities/Assets_Library.cs.meta similarity index 100% rename from Editor/Library/Utilities/Assets.cs.meta rename to Editor/Library/Utilities/Assets_Library.cs.meta diff --git a/Editor/Library/Utilities/CSV.cs b/Editor/Library/Utilities/CSV_Library.cs similarity index 99% rename from Editor/Library/Utilities/CSV.cs rename to Editor/Library/Utilities/CSV_Library.cs index 834e05a..63988eb 100644 --- a/Editor/Library/Utilities/CSV.cs +++ b/Editor/Library/Utilities/CSV_Library.cs @@ -10,7 +10,6 @@ public static string[] ParseCSVRow(string csvLine) { return ParseSingleLine(csvLine).ToArray(); } - public static List ParseCSV(string csvText) { List rows = new List(); @@ -24,7 +23,6 @@ public static List ParseCSV(string csvText) return rows; } - public static string[] ParseCSVToFlatArray(string csvText) { List cells = new List(); @@ -37,7 +35,6 @@ public static string[] ParseCSVToFlatArray(string csvText) return cells.ToArray(); } - // This method parses a single line of CSV text and returns a list of strings. private static List ParseSingleLine(string csvLine) { diff --git a/Editor/Library/Utilities/CSV.cs.meta b/Editor/Library/Utilities/CSV_Library.cs.meta similarity index 100% rename from Editor/Library/Utilities/CSV.cs.meta rename to Editor/Library/Utilities/CSV_Library.cs.meta diff --git a/Editor/Library/Utilities/Core.cs b/Editor/Library/Utilities/Core.cs deleted file mode 100644 index fab8f91..0000000 --- a/Editor/Library/Utilities/Core.cs +++ /dev/null @@ -1,37 +0,0 @@ -using System.IO; -using UnityEditor; -using UnityEngine; - -namespace RealMethod.Editor -{ - public static class RM_CoreEditor - { - public const string SetttingAssetPath = "Assets/Resources/RealMethod/RealMethodSetting.asset"; - public static string ScriptTemplatesPath => GetPackagePath("com.mustard.realmethod") + "/Reservoir/ScriptTemplates"; - public static string PrefabTemplatePath => GetPackagePath("com.mustard.realmethod") + "/Reservoir/Prefabs"; - public static string Documentation => GetPackagePath("com.mustard.realmethod") + "/Documentation/Information"; - - private static string GetPackagePath(string packageName) - { - string[] guids = AssetDatabase.FindAssets("package", new[] { "Packages/" + packageName }); - foreach (string guid in guids) - { - string path = AssetDatabase.GUIDToAssetPath(guid); - if (path.Contains(packageName)) - { - string packagePath = Path.GetDirectoryName(path); - while (!string.IsNullOrEmpty(packagePath)) - { - if (File.Exists(Path.Combine(packagePath, "package.json"))) - return packagePath; - - packagePath = Path.GetDirectoryName(packagePath); - } - } - } - - Debug.LogError($"Could not find package path for: {packageName}"); - return null; - } - } -} \ No newline at end of file diff --git a/Editor/Library/Utilities/Create_Library.cs b/Editor/Library/Utilities/Create_Library.cs new file mode 100644 index 0000000..e938f9c --- /dev/null +++ b/Editor/Library/Utilities/Create_Library.cs @@ -0,0 +1,45 @@ +using UnityEditor; +using UnityEngine; +using System.IO; + +namespace RealMethod.Editor +{ + public static class RM_Create + { + public static void GameObject(string Name = "GameObject") where T : Component + { + GameObject instance = new GameObject(Name); + // Register the creation in the undo system + Undo.RegisterCreatedObjectUndo(instance, "Create " + instance.name); + instance.AddComponent(); + // Select the newly created instance + Selection.activeObject = instance; + } + public static T Asset(string path) where T : PrimitiveAsset + { + // Create an instance of the PrimitiveAsset + T asset = ScriptableObject.CreateInstance(); + + // Ensure the directory exists + string directory = Path.GetDirectoryName(path); + if (!Directory.Exists(directory)) + { + Directory.CreateDirectory(directory); + } + + // Save the asset + AssetDatabase.CreateAsset(asset, path); + AssetDatabase.SaveAssets(); + + // Focus on the newly created asset in the Project window + EditorUtility.FocusProjectWindow(); + Selection.activeObject = asset; + + Debug.Log($"PrimitiveAsset of type {typeof(T).Name} created and saved at: {path}"); + + // Return the created asset + return asset; + } + } +} + diff --git a/Editor/Library/Utilities/Create.cs.meta b/Editor/Library/Utilities/Create_Library.cs.meta similarity index 100% rename from Editor/Library/Utilities/Create.cs.meta rename to Editor/Library/Utilities/Create_Library.cs.meta diff --git a/Editor/Library/Utilities/Create.cs b/Editor/Library/Utilities/Editor_Library.cs similarity index 61% rename from Editor/Library/Utilities/Create.cs rename to Editor/Library/Utilities/Editor_Library.cs index 54d4b61..0fed435 100644 --- a/Editor/Library/Utilities/Create.cs +++ b/Editor/Library/Utilities/Editor_Library.cs @@ -1,22 +1,49 @@ +using System.IO; using UnityEditor; using UnityEngine; -using System.IO; namespace RealMethod.Editor { - public static class RM_Create + public static class RM_Editor { - public static string Script(string templateFileName, string defaultName, bool UseProject = false) + public const string SetttingAssetPath = "Assets/Resources/RealMethod/RealMethodSetting.asset"; + public static string ScriptTemplatesPath => GetPackagePath("com.mustard.realmethod") + "/Reservoir/ScriptTemplates"; + public static string PrefabTemplatePath => GetPackagePath("com.mustard.realmethod") + "/Reservoir/Prefabs"; + public static string Documentation => GetPackagePath("com.mustard.realmethod") + "/Documentation/Information"; + + private static string GetPackagePath(string packageName) + { + string[] guids = AssetDatabase.FindAssets("package", new[] { "Packages/" + packageName }); + foreach (string guid in guids) + { + string path = AssetDatabase.GUIDToAssetPath(guid); + if (path.Contains(packageName)) + { + string packagePath = Path.GetDirectoryName(path); + while (!string.IsNullOrEmpty(packagePath)) + { + if (File.Exists(Path.Combine(packagePath, "package.json"))) + return packagePath; + + packagePath = Path.GetDirectoryName(packagePath); + } + } + } + + Debug.LogError($"Could not find package path for: {packageName}"); + return null; + } + public static string CreateScriptTemplate(string templateFileName, string defaultName, bool UseProject = false) { string templatePath = string.Empty; if (UseProject) { - ProjectSettingAsset ProjectSetting = AssetDatabase.LoadAssetAtPath(RM_CoreEditor.SetttingAssetPath); + ProjectSettingAsset ProjectSetting = AssetDatabase.LoadAssetAtPath(SetttingAssetPath); templatePath = Path.Combine(ProjectSetting[ProjectSettingAsset.AssetFormat.Other], templateFileName); } else { - templatePath = Path.Combine(RM_CoreEditor.ScriptTemplatesPath, templateFileName); + templatePath = Path.Combine(ScriptTemplatesPath, templateFileName); } @@ -26,7 +53,7 @@ public static string Script(string templateFileName, string defaultName, bool Us return string.Empty; } - string selectedPath = RM_Assets.GetSelectedAssetPath(); + string selectedPath = RM_Asset.GetSelectedAssetDirectory(); string newScriptPath = AssetDatabase.GenerateUniqueAssetPath(Path.Combine(selectedPath, defaultName)); // Prompt user for script name before creating the file @@ -56,18 +83,18 @@ public static string Script(string templateFileName, string defaultName, bool Us Selection.activeObject = AssetDatabase.LoadAssetAtPath(newScriptPath); return newScriptPath; } - public static GameObject Prefab(string prefabName, bool UseProject = false) + public static GameObject CreatePrefabTemplate(string prefabName, bool UseProject = false) { string prefabPath = string.Empty; if (UseProject) { - ProjectSettingAsset ProjectSetting = AssetDatabase.LoadAssetAtPath(RM_CoreEditor.SetttingAssetPath); + ProjectSettingAsset ProjectSetting = AssetDatabase.LoadAssetAtPath(SetttingAssetPath); prefabPath = Path.Combine(ProjectSetting[ProjectSettingAsset.AssetFormat.Prefab], prefabName); } else { - prefabPath = Path.Combine(RM_CoreEditor.PrefabTemplatePath, prefabName); + prefabPath = Path.Combine(PrefabTemplatePath, prefabName); } // Load the prefab from the specified path @@ -91,40 +118,7 @@ public static GameObject Prefab(string prefabName, bool UseProject = false) return null; } } - public static void GameObjectInScene(string Name = "GameObject") where T : Component - { - GameObject instance = new GameObject(Name); - // Register the creation in the undo system - Undo.RegisterCreatedObjectUndo(instance, "Create " + instance.name); - instance.AddComponent(); - // Select the newly created instance - Selection.activeObject = instance; - } - public static T ScriptableObj(string path) where T : ScriptableObject - { - // Create an instance of the ScriptableObject - T asset = ScriptableObject.CreateInstance(); - - // Ensure the directory exists - string directory = System.IO.Path.GetDirectoryName(path); - if (!System.IO.Directory.Exists(directory)) - { - System.IO.Directory.CreateDirectory(directory); - } - // Save the asset - AssetDatabase.CreateAsset(asset, path); - AssetDatabase.SaveAssets(); - // Focus on the newly created asset in the Project window - EditorUtility.FocusProjectWindow(); - Selection.activeObject = asset; - - Debug.Log($"ScriptableObject of type {typeof(T).Name} created and saved at: {path}"); - - // Return the created asset - return asset; - } } -} - +} \ No newline at end of file diff --git a/Editor/Library/Utilities/Core.cs.meta b/Editor/Library/Utilities/Editor_Library.cs.meta similarity index 100% rename from Editor/Library/Utilities/Core.cs.meta rename to Editor/Library/Utilities/Editor_Library.cs.meta diff --git a/Editor/Library/Utilities/MetaDataHandler.cs b/Editor/Library/Utilities/MetaData_Library.cs similarity index 90% rename from Editor/Library/Utilities/MetaDataHandler.cs rename to Editor/Library/Utilities/MetaData_Library.cs index b6fc635..caf091b 100644 --- a/Editor/Library/Utilities/MetaDataHandler.cs +++ b/Editor/Library/Utilities/MetaData_Library.cs @@ -9,7 +9,7 @@ public static class RM_MetaData { private static string GetMetaFilePath(string assetPath) => assetPath + ".meta"; - // 🔹 Automatically determines the mode (Text in Editor, Binary in Play Mode) + //Automatically determines the mode (Text in Editor, Binary in Play Mode) private static bool UseBinaryMode { get @@ -18,7 +18,7 @@ private static bool UseBinaryMode } } - // 🔹 Save metadata (Auto-Switch) + //Save metadata (Auto-Switch) public static void SaveCustomMetadata(string assetPath, string key, string value) { string metaFilePath = GetMetaFilePath(assetPath); @@ -35,7 +35,7 @@ public static void SaveCustomMetadata(string assetPath, string key, string value SaveTextMetadata(metaFilePath, key, value); } - // 🔹 Load metadata (Auto-Switch) + //Load metadata (Auto-Switch) public static string LoadCustomMetadata(string assetPath, string key) { string metaFilePath = GetMetaFilePath(assetPath); @@ -48,14 +48,14 @@ public static string LoadCustomMetadata(string assetPath, string key) return UseBinaryMode ? LoadBinaryMetadata(metaFilePath, key) : LoadTextMetadata(metaFilePath, key); } - // 🔹 Check if metadata exists + //Check if metadata exists public static bool HasMetadata(string assetPath, string key) { string metaFilePath = GetMetaFilePath(assetPath); return File.Exists(metaFilePath) && File.ReadAllText(metaFilePath).Contains($"{key}:"); } - // 🔹 Delete metadata entry + //Delete metadata entry public static void DeleteMetadata(string assetPath, string key) { string metaFilePath = GetMetaFilePath(assetPath); @@ -65,7 +65,7 @@ public static void DeleteMetadata(string assetPath, string key) File.WriteAllLines(metaFilePath, Array.FindAll(lines, line => !line.StartsWith($"{key}:"))); } - // 🔹 Save Text Metadata + //Save Text Metadata private static void SaveTextMetadata(string metaFilePath, string key, string value) { string[] lines = File.ReadAllLines(metaFilePath); @@ -85,7 +85,7 @@ private static void SaveTextMetadata(string metaFilePath, string key, string val else File.WriteAllLines(metaFilePath, lines); } - // 🔹 Load Text Metadata + //Load Text Metadata private static string LoadTextMetadata(string metaFilePath, string key) { foreach (string line in File.ReadAllLines(metaFilePath)) @@ -96,7 +96,7 @@ private static string LoadTextMetadata(string metaFilePath, string key) return null; } - // 🔹 Save Binary Metadata + //Save Binary Metadata private static void SaveBinaryMetadata(string metaFilePath, string key, string value) { using (BinaryWriter writer = new BinaryWriter(File.Open(metaFilePath, FileMode.Append))) @@ -106,7 +106,7 @@ private static void SaveBinaryMetadata(string metaFilePath, string key, string v } } - // 🔹 Load Binary Metadata + //Load Binary Metadata private static string LoadBinaryMetadata(string metaFilePath, string key) { using (BinaryReader reader = new BinaryReader(File.Open(metaFilePath, FileMode.Open))) diff --git a/Editor/Library/Utilities/MetaDataHandler.cs.meta b/Editor/Library/Utilities/MetaData_Library.cs.meta similarity index 100% rename from Editor/Library/Utilities/MetaDataHandler.cs.meta rename to Editor/Library/Utilities/MetaData_Library.cs.meta diff --git a/Editor/ReadySet/Content/RealMethod_ScriptTemplate.cs b/Editor/ReadySet/Content/RealMethod_ScriptTemplate.cs index 18f8256..6a2d85e 100644 --- a/Editor/ReadySet/Content/RealMethod_ScriptTemplate.cs +++ b/Editor/ReadySet/Content/RealMethod_ScriptTemplate.cs @@ -8,64 +8,64 @@ class RealMethodScriptTemplate [MenuItem("Assets/Create/Scripting/RealMethod/Essential/Game", false, 80)] public static void CreateGameClass() { - string Path = RM_Create.Script("GameTemplate.txt", "MyGame.cs"); + string Path = RM_Editor.CreateScriptTemplate("GameTemplate.txt", "MyGame.cs"); } [MenuItem("Assets/Create/Scripting/RealMethod/Essential/World", false, 80)] public static void CreateWorld() { - string Path = RM_Create.Script("WorldTemplate.txt", "MyWorld.cs"); + string Path = RM_Editor.CreateScriptTemplate("WorldTemplate.txt", "MyWorld.cs"); } [MenuItem("Assets/Create/Scripting/RealMethod/Essential/GameBridge", false, 80)] public static void CreateGameBridgeClass() { - string Path = RM_Create.Script("GameBridgeTemplate.txt", "MyGameBridge.cs"); + string Path = RM_Editor.CreateScriptTemplate("GameBridgeTemplate.txt", "MyGameBridge.cs"); } // Managers [MenuItem("Assets/Create/Scripting/RealMethod/Manager/BaseManager", false, 80)] public static void CreateManager() { - string Path = RM_Create.Script("ManagerTemplate.txt", "MyManager.cs"); + string Path = RM_Editor.CreateScriptTemplate("ManagerTemplate.txt", "MyManager.cs"); } [MenuItem("Assets/Create/Scripting/RealMethod/Manager/AudioManager", false, 80)] public static void CreateAudioManager() { - string Path = RM_Create.Script("AudioManagerTemplater.txt", "MyAudioManager.cs"); + string Path = RM_Editor.CreateScriptTemplate("AudioManagerTemplater.txt", "MyAudioManager.cs"); } [MenuItem("Assets/Create/Scripting/RealMethod/Manager/CompositManager", false, 80)] public static void CreateCompositManager() { - string Path = RM_Create.Script("CompositManagerTemplate.txt", "MyCompositManager.cs"); + string Path = RM_Editor.CreateScriptTemplate("CompositManagerTemplate.txt", "MyCompositManager.cs"); } [MenuItem("Assets/Create/Scripting/RealMethod/Manager/DataManager", false, 80)] public static void CreateDataManager() { - string Path = RM_Create.Script("DataManagerTemplate.txt", "MyDataManager.cs"); + string Path = RM_Editor.CreateScriptTemplate("DataManagerTemplate.txt", "MyDataManager.cs"); } [MenuItem("Assets/Create/Scripting/RealMethod/Manager/GizmoManager", false, 80)] public static void CreateGizmoManager() { - string Path = RM_Create.Script("GizmoManagerTemplate.txt", "MyGizmoManager.cs"); + string Path = RM_Editor.CreateScriptTemplate("GizmoManagerTemplate.txt", "MyGizmoManager.cs"); } [MenuItem("Assets/Create/Scripting/RealMethod/Manager/UIManager", false, 80)] public static void CreateUIManager() { - string Path = RM_Create.Script("UIManagerTemplate.txt", "MyUIManager.cs"); + string Path = RM_Editor.CreateScriptTemplate("UIManagerTemplate.txt", "MyUIManager.cs"); } [MenuItem("Assets/Create/Scripting/RealMethod/Manager/MixerManager", false, 80)] public static void CreateMixerManager() { - string Path = RM_Create.Script("MixerManagerTemplate.txt", "MyMixerManager.cs"); + string Path = RM_Editor.CreateScriptTemplate("MixerManagerTemplate.txt", "MyMixerManager.cs"); } [MenuItem("Assets/Create/Scripting/RealMethod/Manager/HapticManager", false, 80)] public static void CreateHapticManager() { - string Path = RM_Create.Script("HapticManagerTemplate.txt", "MyHapticManager.cs"); + string Path = RM_Editor.CreateScriptTemplate("HapticManagerTemplate.txt", "MyHapticManager.cs"); } [MenuItem("Assets/Create/Scripting/RealMethod/Manager/TickManager", false, 80)] public static void CreateTickManager() { - string Path = RM_Create.Script("TickManagerTemplate.txt", "MyTickManager.cs"); + string Path = RM_Editor.CreateScriptTemplate("TickManagerTemplate.txt", "MyTickManager.cs"); } @@ -73,17 +73,17 @@ public static void CreateTickManager() [MenuItem("Assets/Create/Scripting/RealMethod/Service/BaseService", false, 80)] public static void CreateService() { - string Path = RM_Create.Script("ServiceTemplate.txt", "MyServicec.cs"); + string Path = RM_Editor.CreateScriptTemplate("ServiceTemplate.txt", "MyServicec.cs"); } [MenuItem("Assets/Create/Scripting/RealMethod/Service/StateService", false, 80)] public static void CreateStateService() { - string Path = RM_Create.Script("StateServiceTemplate.txt", "MyStateService.cs"); + string Path = RM_Editor.CreateScriptTemplate("StateServiceTemplate.txt", "MyStateService.cs"); } [MenuItem("Assets/Create/Scripting/RealMethod/Service/RuleService", false, 80)] public static void CreateRuleService() { - string Path = RM_Create.Script("RuleServiceTemplate.txt", "MyRuleService.cs"); + string Path = RM_Editor.CreateScriptTemplate("RuleServiceTemplate.txt", "MyRuleService.cs"); } @@ -93,75 +93,75 @@ public static void CreateRuleService() [MenuItem("Assets/Create/Scripting/RealMethod/Asset/Data/BaseData", false, 80)] public static void CreateDataAsset() { - string Path = RM_Create.Script("DataAssetTemplate.txt", "MyDataAsset.cs"); + string Path = RM_Editor.CreateScriptTemplate("DataAssetTemplate.txt", "MyDataAsset.cs"); } [MenuItem("Assets/Create/Scripting/RealMethod/Asset/Data/ItemAsset", false, 80)] public static void CreateItemAsset() { - string Path = RM_Create.Script("ItemAssetTemplate.txt", "MyItemAsset.cs"); + string Path = RM_Editor.CreateScriptTemplate("ItemAssetTemplate.txt", "MyItemAsset.cs"); } [MenuItem("Assets/Create/Scripting/RealMethod/Asset/Data/TableAsset", false, 80)] public static void CreateTableAsset() { - string Path = RM_Create.Script("TableTemplate.txt", "MyTableAsset.cs"); + string Path = RM_Editor.CreateScriptTemplate("TableTemplate.txt", "MyTableAsset.cs"); } [MenuItem("Assets/Create/Scripting/RealMethod/Asset/Data/Task", false, 80)] public static void CreateTaskAsset() { - string Path = RM_Create.Script("TaskAssetTemplate.txt", "MyTaskAsset.cs"); + string Path = RM_Editor.CreateScriptTemplate("TaskAssetTemplate.txt", "MyTaskAsset.cs"); } // // Config [MenuItem("Assets/Create/Scripting/RealMethod/Asset/Config/BaseConfig", false, 80)] public static void CreateConfigAsset() { - string Path = RM_Create.Script("ConfigAssetTemplate.txt", "MyConfigAsset.cs"); + string Path = RM_Editor.CreateScriptTemplate("ConfigAssetTemplate.txt", "MyConfigAsset.cs"); } [MenuItem("Assets/Create/Scripting/RealMethod/Asset/Config/ItemConfig", false, 80)] public static void CreateItemConfig() { - string Path = RM_Create.Script("ItemConfigTemplate.txt", "MyItemConfig.cs"); + string Path = RM_Editor.CreateScriptTemplate("ItemConfigTemplate.txt", "MyItemConfig.cs"); } [MenuItem("Assets/Create/Scripting/RealMethod/Asset/Config/GameConfig", false, 80)] public static void CreateGameConfig() { - string Path = RM_Create.Script("GameConfigTemplate.txt", "MyGameConfig.cs"); + string Path = RM_Editor.CreateScriptTemplate("GameConfigTemplate.txt", "MyGameConfig.cs"); } [MenuItem("Assets/Create/Scripting/RealMethod/Asset/Config/HapticConfig", false, 80)] public static void CreateHapticConfig() { - string Path = RM_Create.Script("HapticConfigTemplate.txt", "MyHaptic.cs"); + string Path = RM_Editor.CreateScriptTemplate("HapticConfigTemplate.txt", "MyHaptic.cs"); } // // Files [MenuItem("Assets/Create/Scripting/RealMethod/Asset/File/BaseFile", false, 80)] public static void CreateFileAsset() { - string Path = RM_Create.Script("FileAssetTemplate.txt", "MyFileAsset.cs"); + string Path = RM_Editor.CreateScriptTemplate("FileAssetTemplate.txt", "MyFileAsset.cs"); } [MenuItem("Assets/Create/Scripting/RealMethod/Asset/File/SaveFile", false, 80)] public static void CreateSaveFile() { - string Path = RM_Create.Script("SaveFileTemplate.txt", "MySaveFile.cs"); + string Path = RM_Editor.CreateScriptTemplate("SaveFileTemplate.txt", "MySaveFile.cs"); } [MenuItem("Assets/Create/Scripting/RealMethod/Asset/File/GameSetting", false, 80)] public static void CreateGameSettingFile() { - string Path = RM_Create.Script("GameSettingFileTemplate.txt", "GameSettingFile.cs"); + string Path = RM_Editor.CreateScriptTemplate("GameSettingFileTemplate.txt", "GameSettingFile.cs"); } // // Unique [MenuItem("Assets/Create/Scripting/RealMethod/Asset/Unique/BaseUnique", false, 80)] public static void CreateUniqueAsset() { - string Path = RM_Create.Script("UniqueAssetTemplate.txt", "MyFileAsset.cs"); + string Path = RM_Editor.CreateScriptTemplate("UniqueAssetTemplate.txt", "MyFileAsset.cs"); } [MenuItem("Assets/Create/Scripting/RealMethod/Asset/Unique/SharedRootAsset", false, 80)] public static void CreateSharedRootAsset() { - string Path = RM_Create.Script("SharedRootAssetTemplate.txt", "MySharedRootAsset.cs"); + string Path = RM_Editor.CreateScriptTemplate("SharedRootAssetTemplate.txt", "MySharedRootAsset.cs"); } [MenuItem("Assets/Create/Scripting/RealMethod/Asset/Unique/PoolAsset", false, 80)] public static void CreatePoolAsset() { - string Path = RM_Create.Script("PoolAssetTemplate.txt", "MyPoolAsset.cs"); + string Path = RM_Editor.CreateScriptTemplate("PoolAssetTemplate.txt", "MyPoolAsset.cs"); } // General @@ -169,29 +169,29 @@ public static void CreatePoolAsset() [MenuItem("Assets/Create/Scripting/RealMethod/General/UI/Widget", false, 80)] public static void CreateWidget() { - string Path = RM_Create.Script("WidgetTemplate.txt", "MyWidget.cs"); + string Path = RM_Editor.CreateScriptTemplate("WidgetTemplate.txt", "MyWidget.cs"); } [MenuItem("Assets/Create/Scripting/RealMethod/General/UI/WidgetToolkit", false, 80)] public static void CreateWidgetToolkit() { - string Path = RM_Create.Script("WidgetToolkitTemplate.txt", "MyWidgetToolkit.cs"); + string Path = RM_Editor.CreateScriptTemplate("WidgetToolkitTemplate.txt", "MyWidgetToolkit.cs"); } // // Command [MenuItem("Assets/Create/Scripting/RealMethod/General/Command", false, 80)] public static void CreateCommand() { - string Path = RM_Create.Script("CommandTemplate.txt", "MyCommand.cs"); + string Path = RM_Editor.CreateScriptTemplate("CommandTemplate.txt", "MyCommand.cs"); } // // Trigger [MenuItem("Assets/Create/Scripting/RealMethod/General/Trigger/Trigger3D", false, 80)] public static void CreateTrigger3D() { - string Path = RM_Create.Script("Trigger3DTemplate.txt", "MyTrigger.cs"); + string Path = RM_Editor.CreateScriptTemplate("Trigger3DTemplate.txt", "MyTrigger.cs"); } [MenuItem("Assets/Create/Scripting/RealMethod/General/Trigger/Trigger2D", false, 80)] public static void CreateTrigger2D() { - string Path = RM_Create.Script("Trigger2DTemplate.txt", "MyTrigger.cs"); + string Path = RM_Editor.CreateScriptTemplate("Trigger2DTemplate.txt", "MyTrigger.cs"); } @@ -199,7 +199,7 @@ public static void CreateTrigger2D() [MenuItem("Assets/Create/Scripting/RealMethod/Editor/SettingSection", false, 80)] public static void CreateSettingSection() { - string Path = RM_Create.Script("SettingSectionTemplate.txt", "MySection.cs"); + string Path = RM_Editor.CreateScriptTemplate("SettingSectionTemplate.txt", "MySection.cs"); } diff --git a/Editor/ReadySet/Tools/ClassViewerWindow.cs b/Editor/ReadySet/Tools/ClassViewerWindow.cs index 6f0fd3b..ee1194e 100644 --- a/Editor/ReadySet/Tools/ClassViewerWindow.cs +++ b/Editor/ReadySet/Tools/ClassViewerWindow.cs @@ -301,7 +301,7 @@ public bool IsSearching } - [MenuItem("Tools/RealMethod/ClassViewer")] + [MenuItem("Tools/RealMethod/Viewer/ClassViewer")] public static void Open() { GetWindow("Class Viewer"); diff --git a/Editor/ReadySet/Tools/LibraryWindow.cs b/Editor/ReadySet/Tools/LibraryViewerWindow.cs similarity index 90% rename from Editor/ReadySet/Tools/LibraryWindow.cs rename to Editor/ReadySet/Tools/LibraryViewerWindow.cs index c748f12..aec57fc 100644 --- a/Editor/ReadySet/Tools/LibraryWindow.cs +++ b/Editor/ReadySet/Tools/LibraryViewerWindow.cs @@ -8,11 +8,11 @@ namespace RealMethod.Editor { - public class LibraryWindow : EditorWindow + public class LibraryViewerWindow : EditorWindow { private class FieldModule { - private Vector2 scroll; + //private Vector2 scroll; private MonoScript File; @@ -54,13 +54,11 @@ public void Render() EditorGUILayout.EndHorizontal(); if (IsExpand) { - EditorGUI.indentLevel++; //EditorGUI.BeginDisabledGroup(true); - scroll = EditorGUILayout.BeginScrollView(scroll, GUILayout.Height(120)); + //scroll = EditorGUILayout.BeginScrollView(scroll, GUILayout.Height(800)); EditorGUILayout.TextArea(GetMethodBody(File, TargetMethod)); - EditorGUILayout.EndScrollView(); + //EditorGUILayout.EndScrollView(); //EditorGUI.EndDisabledGroup(); - EditorGUI.indentLevel--; } } @@ -139,10 +137,10 @@ protected override void FixError(int Id) private string search = string.Empty; - [MenuItem("Tools/RealMethod/LibraryWindow")] + [MenuItem("Tools/RealMethod/Viewer/LibraryViewer")] public static void Open() { - GetWindow("Library Window"); + GetWindow("LibraryViewer"); } private void OnEnable() { @@ -174,12 +172,6 @@ private void ReSetField() { Fields.Clear(); - BindingFlags flags = - BindingFlags.Public | - BindingFlags.NonPublic | - BindingFlags.Instance | - BindingFlags.Static | - BindingFlags.DeclaredOnly; foreach (var script in Scripts) { @@ -189,24 +181,36 @@ private void ReSetField() if (mainType.IsAbstract && mainType.IsSealed) { + DrawField(script,mainType); Type[] nestedTypes = mainType.GetNestedTypes(BindingFlags.Public); foreach (var classtype in nestedTypes) { - foreach (var method in classtype.GetMethods(flags)) - { - if (method.IsSpecialName) continue; + DrawField(script,classtype); + } + } - if (!method.IsPublic) continue; + } + } + private void DrawField(MonoScript script, Type mainType) + { + BindingFlags flags = + BindingFlags.Public | + BindingFlags.NonPublic | + BindingFlags.Instance | + BindingFlags.Static | + BindingFlags.DeclaredOnly; - if (!method.IsStatic) continue; + foreach (var method in mainType.GetMethods(flags)) + { + if (method.IsSpecialName) continue; - if (method.IsDefined(typeof(System.Runtime.CompilerServices.ExtensionAttribute), false)) continue; + if (!method.IsPublic) continue; - Fields.Add(new FieldModule(script, method)); - } - } - } + if (!method.IsStatic) continue; + + if (method.IsDefined(typeof(System.Runtime.CompilerServices.ExtensionAttribute), false)) continue; + Fields.Add(new FieldModule(script, method)); } } private void DrawToolbar() diff --git a/Editor/ReadySet/Tools/LibraryWindow.cs.meta b/Editor/ReadySet/Tools/LibraryViewerWindow.cs.meta similarity index 100% rename from Editor/ReadySet/Tools/LibraryWindow.cs.meta rename to Editor/ReadySet/Tools/LibraryViewerWindow.cs.meta diff --git a/Editor/Toolkit/Ability/Ability_ScriptTemplate.cs b/Editor/Toolkit/Ability/Ability_ScriptTemplate.cs index 9c3c07f..d9cb8d5 100644 --- a/Editor/Toolkit/Ability/Ability_ScriptTemplate.cs +++ b/Editor/Toolkit/Ability/Ability_ScriptTemplate.cs @@ -7,17 +7,17 @@ class Ability_ScriptTemplate [MenuItem("Assets/Create/Scripting/RealMethod/Toolkit/Ability/AbilityAsset", false, 80)] public static void CreateAbilityAsset() { - string Path = RM_Create.Script("AbilityAssetTemplate.txt", "MyAbility.cs"); + string Path = RM_Editor.CreateScriptTemplate("AbilityAssetTemplate.txt", "MyAbility.cs"); } [MenuItem("Assets/Create/Scripting/RealMethod/Toolkit/Ability/AbilityActionAsset", false, 80)] public static void CreateAbilityAction() { - string Path = RM_Create.Script("AbilityActionAssetTemplate.txt", "MyAbilityAction.cs"); + string Path = RM_Editor.CreateScriptTemplate("AbilityActionAssetTemplate.txt", "MyAbilityAction.cs"); } [MenuItem("Assets/Create/Scripting/RealMethod/Toolkit/Ability/Effect", false, 80)] public static void CreateEffect() { - string Path = RM_Create.Script("AbilityEffectTemplate.txt", "MyEffect.cs"); + string Path = RM_Editor.CreateScriptTemplate("AbilityEffectTemplate.txt", "MyEffect.cs"); } } } \ No newline at end of file diff --git a/Editor/Toolkit/Actor/Actor_ScriptTemplate.cs b/Editor/Toolkit/Actor/Actor_ScriptTemplate.cs index d1c971e..120dc11 100644 --- a/Editor/Toolkit/Actor/Actor_ScriptTemplate.cs +++ b/Editor/Toolkit/Actor/Actor_ScriptTemplate.cs @@ -7,7 +7,7 @@ class Actor_ScriptTemplate [MenuItem("Assets/Create/Scripting/RealMethod/Toolkit/Actor/Act", false, 80)] public static void CreateActCommand() { - string Path = RM_Create.Script("ActTemplate.txt", "MyAct.cs"); + string Path = RM_Editor.CreateScriptTemplate("ActTemplate.txt", "MyAct.cs"); } } } \ No newline at end of file diff --git a/Editor/Toolkit/Inventory/Inventory_ScriptTemplate.cs b/Editor/Toolkit/Inventory/Inventory_ScriptTemplate.cs index 8f3da79..eb7eebf 100644 --- a/Editor/Toolkit/Inventory/Inventory_ScriptTemplate.cs +++ b/Editor/Toolkit/Inventory/Inventory_ScriptTemplate.cs @@ -7,7 +7,7 @@ class Inventory_ScriptTemplate [MenuItem("Assets/Create/Scripting/RealMethod/Toolkit/Inventory/Item", false, 80)] public static void CreateItem() { - string Path = RM_Create.Script("InventoryItemTemplate.txt", "MyItem.cs"); + string Path = RM_Editor.CreateScriptTemplate("InventoryItemTemplate.txt", "MyItem.cs"); } } } \ No newline at end of file diff --git a/Editor/Toolkit/PCG/PCGEditorWindow.cs b/Editor/Toolkit/PCG/PCGEditorWindow.cs index 01da03e..4b1ebcc 100644 --- a/Editor/Toolkit/PCG/PCGEditorWindow.cs +++ b/Editor/Toolkit/PCG/PCGEditorWindow.cs @@ -391,7 +391,7 @@ private void CashPanel() Cash.Render(); if (GUILayout.Button("CreateCash")) { - Cash.SetValue(RM_Create.ScriptableObj(CashAddress.GetValue())); + Cash.SetValue(RM_Create.Asset(CashAddress.GetValue())); } EditorGUILayout.EndHorizontal(); } diff --git a/Editor/Toolkit/PCG/PCG_ScriptTemplate.cs b/Editor/Toolkit/PCG/PCG_ScriptTemplate.cs index ade8809..ee20e90 100644 --- a/Editor/Toolkit/PCG/PCG_ScriptTemplate.cs +++ b/Editor/Toolkit/PCG/PCG_ScriptTemplate.cs @@ -7,7 +7,7 @@ class PCG_ScriptTemplate [MenuItem("Assets/Create/Scripting/RealMethod/Toolkit/PCG/Request", false, 80)] public static void CreatePCGRequest() { - string Path = RM_Create.Script("PCGRequestTamplate.txt", "MyRequest.cs"); + string Path = RM_Editor.CreateScriptTemplate("PCGRequestTamplate.txt", "MyRequest.cs"); } } } \ No newline at end of file diff --git a/Editor/Toolkit/Pickup/Pickup_ScriptTemplate.cs b/Editor/Toolkit/Pickup/Pickup_ScriptTemplate.cs index 2f3809f..b445ae2 100644 --- a/Editor/Toolkit/Pickup/Pickup_ScriptTemplate.cs +++ b/Editor/Toolkit/Pickup/Pickup_ScriptTemplate.cs @@ -7,12 +7,12 @@ class Pickup_ScriptTemplate [MenuItem("Assets/Create/Scripting/RealMethod/Toolkit/Pickup/Pickup3D", false, 80)] public static void CreatePickup3D() { - string Path = RM_Create.Script("Pickup3DTemplate.txt", "MyPickup.cs"); + string Path = RM_Editor.CreateScriptTemplate("Pickup3DTemplate.txt", "MyPickup.cs"); } [MenuItem("Assets/Create/Scripting/RealMethod/Toolkit/Pickup/Pickup2D", false, 80)] public static void CreatePickup2D() { - string Path = RM_Create.Script("Pickup2DTemplate.txt", "MyPickup.cs"); + string Path = RM_Editor.CreateScriptTemplate("Pickup2DTemplate.txt", "MyPickup.cs"); } } } \ No newline at end of file diff --git a/Editor/Toolkit/RPG/RPG_ScriptTemplate.cs b/Editor/Toolkit/RPG/RPG_ScriptTemplate.cs index 956250c..0a1f5c5 100644 --- a/Editor/Toolkit/RPG/RPG_ScriptTemplate.cs +++ b/Editor/Toolkit/RPG/RPG_ScriptTemplate.cs @@ -7,22 +7,22 @@ class RPG_ScriptTemplate [MenuItem("Assets/Create/Scripting/RealMethod/Toolkit/RPG/StatDefinition", false, 80)] public static void CreateStatDefinition() { - string Path = RM_Create.Script("StatDefinitionTemplate.txt", "StatDefinition.cs"); + string Path = RM_Editor.CreateScriptTemplate("StatDefinitionTemplate.txt", "StatDefinition.cs"); } [MenuItem("Assets/Create/Scripting/RealMethod/Toolkit/RPG/StatProfile", false, 80)] public static void CreateStatProfile() { - string Path = RM_Create.Script("StatProfileTemplate.txt", "MyProfile.cs"); + string Path = RM_Editor.CreateScriptTemplate("StatProfileTemplate.txt", "MyProfile.cs"); } [MenuItem("Assets/Create/Scripting/RealMethod/Toolkit/RPG/StatBuff", false, 80)] public static void CreateBuffConfig() { - string Path = RM_Create.Script("BuffConfigTemplate.txt", "MyBuff.cs"); + string Path = RM_Editor.CreateScriptTemplate("BuffConfigTemplate.txt", "MyBuff.cs"); } [MenuItem("Assets/Create/Scripting/RealMethod/Toolkit/RPG/ResourceData", false, 80)] public static void CreateResourceData() { - string Path = RM_Create.Script("ResourceDataTemplate.txt", "MyResource.cs"); + string Path = RM_Editor.CreateScriptTemplate("ResourceDataTemplate.txt", "MyResource.cs"); } } diff --git a/Editor/Toolkit/TerrainTools/TerrainEditor.cs b/Editor/Toolkit/TerrainTools/TerrainEditor.cs index be899cd..ff14667 100644 --- a/Editor/Toolkit/TerrainTools/TerrainEditor.cs +++ b/Editor/Toolkit/TerrainTools/TerrainEditor.cs @@ -138,8 +138,8 @@ public void OnRender() if (GUILayout.Button("CreateCash")) { string directoryfile = Path.GetDirectoryName(CashAddress.GetValue()); - PCGResourceConfig ResurcePack = RM_Create.ScriptableObj(directoryfile + "/TerrainResource.asset"); - PCGCashAsset Temporery = RM_Create.ScriptableObj(CashAddress.GetValue()); + PCGResourceConfig ResurcePack = RM_Create.Asset(directoryfile + "/TerrainResource.asset"); + PCGCashAsset Temporery = RM_Create.Asset(CashAddress.GetValue()); TerrainData Data = OwnerTerrain.terrainData; PCGSource[] TerrainSource = new PCGSource[Data.treePrototypes.Length]; TreeInstance[] trees = OwnerTerrain.terrainData.treeInstances; diff --git a/Editor/Toolkit/Tutorial/Tutorial_ScriptTemplate.cs b/Editor/Toolkit/Tutorial/Tutorial_ScriptTemplate.cs index e5f7653..b853459 100644 --- a/Editor/Toolkit/Tutorial/Tutorial_ScriptTemplate.cs +++ b/Editor/Toolkit/Tutorial/Tutorial_ScriptTemplate.cs @@ -7,19 +7,19 @@ class Tutorial_ScriptTemplate [MenuItem("Assets/Create/Scripting/RealMethod/Toolkit/Tutorial/ScreenWidget", false, 80)] public static void CreateTutorialScreen() { - string Path = RM_Create.Script("TutorialScreenTemplate.txt", "MyTutorialScreen.cs"); + string Path = RM_Editor.CreateScriptTemplate("TutorialScreenTemplate.txt", "MyTutorialScreen.cs"); } [MenuItem("Assets/Create/Scripting/RealMethod/Toolkit/Tutorial/UIunit", false, 80)] public static void CreateTutorialMessage() { - string Path = RM_Create.Script("TutorialUnitTemplate.txt", "MyTutorialUnit.cs"); + string Path = RM_Editor.CreateScriptTemplate("TutorialUnitTemplate.txt", "MyTutorialUnit.cs"); } [MenuItem("Assets/Create/Scripting/RealMethod/Toolkit/Tutorial/Config", false, 80)] public static void CreateTutorialConfig() { - string Path = RM_Create.Script("TutorialConfigTemplate.txt", "MyTutorialConfig.cs"); + string Path = RM_Editor.CreateScriptTemplate("TutorialConfigTemplate.txt", "MyTutorialConfig.cs"); } } } \ No newline at end of file diff --git a/Editor/Toolkit/Upgrade/Upgrade_ScriptTemplate.cs b/Editor/Toolkit/Upgrade/Upgrade_ScriptTemplate.cs index 063f71a..033240b 100644 --- a/Editor/Toolkit/Upgrade/Upgrade_ScriptTemplate.cs +++ b/Editor/Toolkit/Upgrade/Upgrade_ScriptTemplate.cs @@ -7,12 +7,12 @@ class Upgrade_ScriptTemplate [MenuItem("Assets/Create/Scripting/RealMethod/Toolkit/Upgrade/ItemAsset", false, 80)] public static void CreateItem() { - string Path = RM_Create.Script("UpgradeItemTemplate.txt", "MyUpgradeAsset.cs"); + string Path = RM_Editor.CreateScriptTemplate("UpgradeItemTemplate.txt", "MyUpgradeAsset.cs"); } [MenuItem("Assets/Create/Scripting/RealMethod/Toolkit/Upgrade/MapConfig", false, 80)] public static void CreateConfig() { - string Path = RM_Create.Script("UpgradeConfigTemplate.txt", "MyUpgradeConfig.cs"); + string Path = RM_Editor.CreateScriptTemplate("UpgradeConfigTemplate.txt", "MyUpgradeConfig.cs"); } } } \ No newline at end of file diff --git a/Runtime/Core/Architecture/World.cs b/Runtime/Core/Architecture/World.cs index 9e11487..5353fba 100644 --- a/Runtime/Core/Architecture/World.cs +++ b/Runtime/Core/Architecture/World.cs @@ -55,9 +55,9 @@ public bool CanStartHere() #if UNITY_EDITOR protected virtual void OnDrawGizmos() { - RM_Draw.gizmos.Capsule(transform.position, Color.cyan, height, radius); - RM_Draw.gizmos.Arrow(transform.position, transform.forward, Color.red); - RM_Draw.gizmos.Text(PosName, transform.position + (transform.up * (height / 2)) + (Vector3.up * 0.1f), Color.black); + RM_Gizmos.Capsule(transform.position, Color.cyan, height, radius); + RM_Gizmos.Arrow(transform.position, transform.forward, Color.red); + RM_Gizmos.Text(PosName, transform.position + (transform.up * (height / 2)) + (Vector3.up * 0.1f), Color.black); } #endif } diff --git a/Runtime/Library/Extension/Animator.cs b/Runtime/Library/Extension/Animator.cs index 3b44b8c..caa71aa 100644 --- a/Runtime/Library/Extension/Animator.cs +++ b/Runtime/Library/Extension/Animator.cs @@ -14,7 +14,7 @@ public static Coroutine PlayAndNotify(this Animator animator, string stateName, Debug.LogWarning("For Use PlayAndNotify you need to a MonoBehaviour for running Cortine for Finish Callback"); return null; } - return runner.StartCoroutine(RM_Coroutine.WaitForState(animator, layer, stateName, onFinished)); + return runner.StartCoroutine(RM_Animation.WaitForState(animator, layer, stateName, onFinished)); } /// diff --git a/Runtime/Library/Utilities/Animation_Library.cs b/Runtime/Library/Utilities/Animation_Library.cs new file mode 100644 index 0000000..ad7b2e1 --- /dev/null +++ b/Runtime/Library/Utilities/Animation_Library.cs @@ -0,0 +1,43 @@ +using System.Collections; +using UnityEngine; + +namespace RealMethod +{ + public static class RM_Animation + { + /// + /// Waits until the specified state is entered on an Animator layer, + /// then invokes a callback once the state becomes active. + /// + /// The Animator to monitor. + /// The Animator layer index to check. + /// The name of the state to wait for. + /// Callback invoked when the target state is reached. + /// + /// An that can be used with StartCoroutine(). + /// + /// + /// Useful for sequencing animations without hard‑coded delays. + /// Ensure that the Animator contains the target state on the specified layer. + /// + public static IEnumerator WaitForState(Animator animator, int layer, string stateName, System.Action onFinished) + { + // Wait until we actually enter the state + AnimatorStateInfo info = animator.GetCurrentAnimatorStateInfo(layer); + while (!info.IsName(stateName)) + { + yield return null; + info = animator.GetCurrentAnimatorStateInfo(layer); + } + + // Now wait until state finishes (non-looping assumption) + while (info.normalizedTime < 1f) + { + yield return null; + info = animator.GetCurrentAnimatorStateInfo(layer); + } + + onFinished?.Invoke(); + } + } +} \ No newline at end of file diff --git a/Runtime/Library/Utilities/Animation_Library.cs.meta b/Runtime/Library/Utilities/Animation_Library.cs.meta new file mode 100644 index 0000000..9e1fedb --- /dev/null +++ b/Runtime/Library/Utilities/Animation_Library.cs.meta @@ -0,0 +1,2 @@ +fileFormatVersion: 2 +guid: beb595d1cd67e9247ba2d5076b06d4f9 \ No newline at end of file diff --git a/Runtime/Library/Utilities/Collection_Library.cs b/Runtime/Library/Utilities/Collection_Library.cs new file mode 100644 index 0000000..183c659 --- /dev/null +++ b/Runtime/Library/Utilities/Collection_Library.cs @@ -0,0 +1,38 @@ +using System; +using System.Collections.Generic; + +namespace RealMethod +{ + public static class RM_Collection + { + /// + /// Retrieves an element from a collection at the specified index. + /// + /// The type of elements in the collection. + /// The collection of items to retrieve from. + /// The zero-based index of the element to retrieve. + /// + /// The element located at the specified index. + /// + /// + /// Thrown if the index is negative or exceeds the number of elements in the collection. + /// + /// + /// If the provided collection does not support indexed access (), + /// it will be converted to a list internally to allow indexing. + /// + public static T SafeGet(IEnumerable items, int index) + { + if (index < 0) + throw new ArgumentOutOfRangeException(nameof(index), "Index must be non-negative."); + + // Convert to array or list if you need index access + var itemList = items as IList ?? new List(items); + + if (index >= itemList.Count) + throw new ArgumentOutOfRangeException(nameof(index), "Index exceeds the collection count."); + + return itemList[index]; + } + } +} \ No newline at end of file diff --git a/Runtime/Library/Utilities/Collection_Library.cs.meta b/Runtime/Library/Utilities/Collection_Library.cs.meta new file mode 100644 index 0000000..5ce7d85 --- /dev/null +++ b/Runtime/Library/Utilities/Collection_Library.cs.meta @@ -0,0 +1,2 @@ +fileFormatVersion: 2 +guid: c20cf9a2535c6924ba075d1cf0dae35e \ No newline at end of file diff --git a/Runtime/Library/Utilities/Core.cs b/Runtime/Library/Utilities/Core.cs deleted file mode 100644 index 3bcd435..0000000 --- a/Runtime/Library/Utilities/Core.cs +++ /dev/null @@ -1,149 +0,0 @@ -using System; -using System.Collections.Generic; -using System.IO; -using System.Linq; -using System.Linq.Expressions; -using UnityEngine; -using UnityEngine.EventSystems; -using UnityEngine.UI; - -namespace RealMethod -{ - public static class RM_Core - { - public class input - { - public static bool IsTouchOverUI(GraphicRaycaster HUD_graphicRaycaster, Vector2 touchPosition) - { - // Create a pointer event data from the touch position - PointerEventData pointerEventData = new PointerEventData(null); - pointerEventData.position = touchPosition; - - // Create a list to hold the results - List results = new List(); - - // Raycast using the GraphicRaycaster and pointer event data - HUD_graphicRaycaster.Raycast(pointerEventData, results); - - // Check if we hit any UI elements - return results.Count > 0; - } - } - - public class enumerables - { - public static T GetGameObject(IEnumerable items, int index) - { - if (index < 0) - throw new ArgumentOutOfRangeException(nameof(index), "Index must be non-negative."); - - // Convert to array or list if you need index access - var itemList = items as IList ?? new List(items); - - if (index >= itemList.Count) - throw new ArgumentOutOfRangeException(nameof(index), "Index exceeds the collection count."); - - return itemList[index]; - } - } - - public class file - { - public static bool WriteToFile(string contents, string fullPath) - { - try - { - File.WriteAllText(fullPath, contents); - return true; - } - catch (Exception e) - { - Debug.LogError($"Failed to write to {fullPath} with exception {e}"); - return false; - } - } - public static bool WriteToFile(string contents, string fileName, string ext) - { - var fullPath = Path.Combine(Application.persistentDataPath, fileName + ext); - return WriteToFile(fullPath, contents); - } - - public static bool ReadFromFile(string fullPath, out string result) - { - if (!File.Exists(fullPath)) - { - result = string.Empty; - return false; - } - - try - { - result = File.ReadAllText(fullPath); - return true; - } - catch (Exception e) - { - Debug.LogError($"Failed to read from {fullPath} with exception {e}"); - result = ""; - return false; - } - } - public static bool ReadFromFile(string fileName, string ext, out string result) - { - var fullPath = Path.Combine(Application.persistentDataPath, fileName + ext); - return ReadFromFile(fullPath, out result); - } - - public static bool MoveFile(string fullPath_A, string fullPath_B) - { - try - { - if (File.Exists(fullPath_B)) - { - File.Delete(fullPath_B); - } - - if (!File.Exists(fullPath_A)) - { - return false; - } - - File.Move(fullPath_A, fullPath_B); - } - catch (Exception e) - { - Debug.LogError($"Failed to move file from {fullPath_A} to {fullPath_B} with exception {e}"); - return false; - } - - return true; - } - public static bool MoveFile(string fileName_A, string fileName_B, string ext) - { - var fullPath_A = Path.Combine(Application.persistentDataPath, fileName_A + ext); - var fullPath_B = Path.Combine(Application.persistentDataPath, fileName_B + ext); - return MoveFile(fullPath_A, fullPath_B); - } - } - - public class expression - { - public static string GetVariableName(Expression> expression) - { - if (expression.Body is MemberExpression memberExpression) - { - return memberExpression.Member.Name; - } - throw new ArgumentException("Expression is not a valid member expression."); - } - } - - public class enume - { - public static bool AreEnumValuesEqual(T a, J b) where T : Enum where J : Enum - { - return Convert.ToInt32(a) == Convert.ToInt32(b); - } - } - } -} \ No newline at end of file diff --git a/Runtime/Library/Utilities/Core.cs.meta b/Runtime/Library/Utilities/Core.cs.meta deleted file mode 100644 index a43f0f8..0000000 --- a/Runtime/Library/Utilities/Core.cs.meta +++ /dev/null @@ -1,2 +0,0 @@ -fileFormatVersion: 2 -guid: 6137ed14b90bee8439505d9a15df4c34 \ No newline at end of file diff --git a/Runtime/Library/Utilities/Coroutine.cs b/Runtime/Library/Utilities/Coroutine.cs deleted file mode 100644 index 24be9aa..0000000 --- a/Runtime/Library/Utilities/Coroutine.cs +++ /dev/null @@ -1,124 +0,0 @@ -using System.Collections; -using UnityEngine; - -namespace RealMethod -{ - public static class RM_Coroutine - { - private class CoroutineHandeler - { - public bool IsDone { get; private set; } - - public IEnumerator Run(IEnumerator coroutine) - { - yield return coroutine; - IsDone = true; - } - } - - - public static IEnumerator Delay(float duration, System.Action callback) - { - yield return new WaitForSeconds(duration); - callback?.Invoke(); - } - public static IEnumerator WaitUntil(System.Func condition, System.Action callback) - { - yield return new WaitUntil(condition); - callback?.Invoke(); - } - public static IEnumerator WaitWhile(System.Func condition, System.Action callback) - { - yield return new WaitWhile(condition); - callback?.Invoke(); - } - public static IEnumerator MoveTo(Transform target, Vector3 end, float duration) - { - Vector3 start = target.position; - float t = 0f; - while (t < duration) - { - t += Time.deltaTime; - target.position = Vector3.Lerp(start, end, t / duration); - yield return null; - } - target.position = end; - } - public static IEnumerator FadeCanvas(CanvasGroup canvas, float targetAlpha, float duration) - { - float start = canvas.alpha; - float t = 0f; - while (t < duration) - { - t += Time.deltaTime; - canvas.alpha = Mathf.Lerp(start, targetAlpha, t / duration); - yield return null; - } - canvas.alpha = targetAlpha; - } - public static IEnumerator ScaleTo(Transform target, Vector3 targetScale, float duration) - { - Vector3 start = target.localScale; - float t = 0f; - while (t < duration) - { - t += Time.deltaTime; - target.localScale = Vector3.Lerp(start, targetScale, t / duration); - yield return null; - } - target.localScale = targetScale; - } - public static IEnumerator RotateTo(Transform target, Quaternion targetRot, float duration) - { - Quaternion start = target.rotation; - float t = 0f; - while (t < duration) - { - t += Time.deltaTime; - target.rotation = Quaternion.Slerp(start, targetRot, t / duration); - yield return null; - } - target.rotation = targetRot; - } - public static IEnumerator Repeat(System.Action action, float interval, int count = -1) - { - int i = 0; - while (count < 0 || i < count) - { - action?.Invoke(); - i++; - yield return new WaitForSeconds(interval); - } - } - public static IEnumerator WaitForCoroutine(MonoBehaviour Owner, IEnumerator coroutine) - { - CoroutineHandeler handle = new CoroutineHandeler(); - yield return Owner.StartCoroutine(handle.Run(coroutine)); - } - public static IEnumerator DelayOneFrame(System.Action callback) - { - yield return new WaitForEndOfFrame(); - callback?.Invoke(); - } - public static IEnumerator WaitForState(Animator animator, int layer, string stateName, System.Action onFinished) - { - // Wait until we actually enter the state - AnimatorStateInfo info = animator.GetCurrentAnimatorStateInfo(layer); - while (!info.IsName(stateName)) - { - yield return null; - info = animator.GetCurrentAnimatorStateInfo(layer); - } - - // Now wait until state finishes (non-looping assumption) - while (info.normalizedTime < 1f) - { - yield return null; - info = animator.GetCurrentAnimatorStateInfo(layer); - } - - onFinished?.Invoke(); - } - } - -} \ No newline at end of file diff --git a/Runtime/Library/Utilities/Coroutine.cs.meta b/Runtime/Library/Utilities/Coroutine.cs.meta deleted file mode 100644 index 5a0eb7d..0000000 --- a/Runtime/Library/Utilities/Coroutine.cs.meta +++ /dev/null @@ -1,2 +0,0 @@ -fileFormatVersion: 2 -guid: 52e4b7690bd97e7438fd5adb46d2d1c1 \ No newline at end of file diff --git a/Runtime/Library/Utilities/Debug_Library.cs b/Runtime/Library/Utilities/Debug_Library.cs new file mode 100644 index 0000000..b9e2f32 --- /dev/null +++ b/Runtime/Library/Utilities/Debug_Library.cs @@ -0,0 +1,29 @@ +using UnityEngine; + +namespace RealMethod +{ + public static class RM_Debug + { + // Draws a directional arrow using Debug.DrawRay (no color) + public static void Arrow(Vector3 position, Vector3 direction, float arrowHeadLength = 0.25f, float arrowHeadAngle = 20.0f) + { + Debug.DrawRay(position, direction); + + Vector3 right = Quaternion.LookRotation(direction) * Quaternion.Euler(0, 180 + arrowHeadAngle, 0) * Vector3.forward; + Vector3 left = Quaternion.LookRotation(direction) * Quaternion.Euler(0, 180 - arrowHeadAngle, 0) * Vector3.forward; + Debug.DrawRay(position + direction, right * arrowHeadLength); + Debug.DrawRay(position + direction, left * arrowHeadLength); + } + // Draws a directional arrow using Debug.DrawRay (with color) + public static void Arrow(Vector3 position, Vector3 direction, Color color, float arrowHeadLength = 0.25f, float arrowHeadAngle = 20.0f) + { + Debug.DrawRay(position, direction, color); + + Vector3 right = Quaternion.LookRotation(direction) * Quaternion.Euler(0, 180 + arrowHeadAngle, 0) * Vector3.forward; + Vector3 left = Quaternion.LookRotation(direction) * Quaternion.Euler(0, 180 - arrowHeadAngle, 0) * Vector3.forward; + Debug.DrawRay(position + direction, right * arrowHeadLength, color); + Debug.DrawRay(position + direction, left * arrowHeadLength, color); + } + } + +} \ No newline at end of file diff --git a/Runtime/Library/Utilities/Debug_Library.cs.meta b/Runtime/Library/Utilities/Debug_Library.cs.meta new file mode 100644 index 0000000..c1ba93b --- /dev/null +++ b/Runtime/Library/Utilities/Debug_Library.cs.meta @@ -0,0 +1,2 @@ +fileFormatVersion: 2 +guid: a01a052ef371a7f4ea8276a4c54c103a \ No newline at end of file diff --git a/Runtime/Library/Utilities/Draw.cs b/Runtime/Library/Utilities/Draw.cs deleted file mode 100644 index eb47d0d..0000000 --- a/Runtime/Library/Utilities/Draw.cs +++ /dev/null @@ -1,118 +0,0 @@ -using UnityEditor; -using UnityEngine; - -namespace RealMethod -{ - public static class RM_Draw - { - public class gizmos - { - public static void Curve(AnimationCurve curve) - { - for (float t = 0; t < curve.keys[curve.length - 1].time; t += 0.1f) - { - Gizmos.DrawSphere(new Vector3(t, curve.Evaluate(t), 0), 0.1f); - } - } - // Draws a directional arrow using Gizmos (no color) - public static void Arrow(Vector3 position, Vector3 direction, float arrowHeadLength = 0.25f, float arrowHeadAngle = 20.0f) - { - Gizmos.DrawRay(position, direction); - - Vector3 right = Quaternion.LookRotation(direction) * Quaternion.Euler(0, 180 + arrowHeadAngle, 0) * Vector3.forward; - Vector3 left = Quaternion.LookRotation(direction) * Quaternion.Euler(0, 180 - arrowHeadAngle, 0) * Vector3.forward; - Gizmos.DrawRay(position + direction, right * arrowHeadLength); - Gizmos.DrawRay(position + direction, left * arrowHeadLength); - } - // Draws a directional arrow using Gizmos (with color) - public static void Arrow(Vector3 position, Vector3 direction, Color color, float arrowHeadLength = 0.25f, float arrowHeadAngle = 20.0f) - { - Gizmos.color = color; - Gizmos.DrawRay(position, direction); - - Vector3 right = Quaternion.LookRotation(direction) * Quaternion.Euler(0, 180 + arrowHeadAngle, 0) * Vector3.forward; - Vector3 left = Quaternion.LookRotation(direction) * Quaternion.Euler(0, 180 - arrowHeadAngle, 0) * Vector3.forward; - Gizmos.DrawRay(position + direction, right * arrowHeadLength); - Gizmos.DrawRay(position + direction, left * arrowHeadLength); - } - // Draws a Capsule using Gizmos (no color) - public static void Capsule(Vector3 position, float height = 2f, float radius = 0.5f) - { - // Draw top sphere - Vector3 top = position + Vector3.up * (height / 2 - radius); - Gizmos.DrawWireSphere(top, radius); - - // Draw bottom sphere - Vector3 bottom = position + Vector3.down * (height / 2 - radius); - Gizmos.DrawWireSphere(bottom, radius); - - // Draw cylinder (approximation) - Gizmos.DrawLine(top + Vector3.forward * radius, bottom + Vector3.forward * radius); - Gizmos.DrawLine(top - Vector3.forward * radius, bottom - Vector3.forward * radius); - Gizmos.DrawLine(top + Vector3.right * radius, bottom + Vector3.right * radius); - Gizmos.DrawLine(top - Vector3.right * radius, bottom - Vector3.right * radius); - } - // Draws a Capsule using Gizmos (with color) - public static void Capsule(Vector3 position, Color color, float height = 2f, float radius = 0.5f) - { - // Save previous Gizmos color - Color prevColor = Gizmos.color; - Gizmos.color = color; - - // Draw top sphere - Vector3 top = position + Vector3.up * (height / 2 - radius); - Gizmos.DrawWireSphere(top, radius); - - // Draw bottom sphere - Vector3 bottom = position + Vector3.down * (height / 2 - radius); - Gizmos.DrawWireSphere(bottom, radius); - - // Draw cylinder (approximation) - Gizmos.DrawLine(top + Vector3.forward * radius, bottom + Vector3.forward * radius); - Gizmos.DrawLine(top - Vector3.forward * radius, bottom - Vector3.forward * radius); - Gizmos.DrawLine(top + Vector3.right * radius, bottom + Vector3.right * radius); - Gizmos.DrawLine(top - Vector3.right * radius, bottom - Vector3.right * radius); - - // Restore previous color - Gizmos.color = prevColor; - } - // Draw a Text using Gizmos (With Colort) - public static void Text(string text, Vector3 position, Color color, FontStyle font = FontStyle.Bold, TextAnchor ancher = TextAnchor.MiddleCenter) - { - // Set color - GUIStyle style = new GUIStyle(); - style.normal.textColor = color; - style.alignment = ancher; - style.fontStyle = font; - - // Draw the label above the GameObject - Handles.Label(position, text, style); - } - } - - public class debug - { - // Draws a directional arrow using Debug.DrawRay (no color) - public static void Arrow(Vector3 position, Vector3 direction, float arrowHeadLength = 0.25f, float arrowHeadAngle = 20.0f) - { - Debug.DrawRay(position, direction); - - Vector3 right = Quaternion.LookRotation(direction) * Quaternion.Euler(0, 180 + arrowHeadAngle, 0) * Vector3.forward; - Vector3 left = Quaternion.LookRotation(direction) * Quaternion.Euler(0, 180 - arrowHeadAngle, 0) * Vector3.forward; - Debug.DrawRay(position + direction, right * arrowHeadLength); - Debug.DrawRay(position + direction, left * arrowHeadLength); - } - // Draws a directional arrow using Debug.DrawRay (with color) - public static void Arrow(Vector3 position, Vector3 direction, Color color, float arrowHeadLength = 0.25f, float arrowHeadAngle = 20.0f) - { - Debug.DrawRay(position, direction, color); - - Vector3 right = Quaternion.LookRotation(direction) * Quaternion.Euler(0, 180 + arrowHeadAngle, 0) * Vector3.forward; - Vector3 left = Quaternion.LookRotation(direction) * Quaternion.Euler(0, 180 - arrowHeadAngle, 0) * Vector3.forward; - Debug.DrawRay(position + direction, right * arrowHeadLength, color); - Debug.DrawRay(position + direction, left * arrowHeadLength, color); - } - } - - } -} \ No newline at end of file diff --git a/Runtime/Library/Utilities/Draw.cs.meta b/Runtime/Library/Utilities/Draw.cs.meta deleted file mode 100644 index 55198b3..0000000 --- a/Runtime/Library/Utilities/Draw.cs.meta +++ /dev/null @@ -1,2 +0,0 @@ -fileFormatVersion: 2 -guid: 17e9ab77f56e0034cb688c9aa2ba5b61 \ No newline at end of file diff --git a/Runtime/Library/Utilities/Enum_Library.cs b/Runtime/Library/Utilities/Enum_Library.cs new file mode 100644 index 0000000..75a9014 --- /dev/null +++ b/Runtime/Library/Utilities/Enum_Library.cs @@ -0,0 +1,27 @@ +using System; + +namespace RealMethod +{ + public static class RM_Enum + { + /// + /// Compares two enum values, even if they are of different enum types, + /// by comparing their underlying numeric values. + /// + /// The type of the first enum. + /// The type of the second enum. + /// The first enum value. + /// The second enum value. + /// + /// True if both enum values have the same underlying numeric value; otherwise false. + /// + /// + /// Useful when working with different enum types that share the same value mapping. + /// + + public static bool AreEnumValuesEqual(T a, J b) where T : Enum where J : Enum + { + return Convert.ToInt32(a) == Convert.ToInt32(b); + } + } +} \ No newline at end of file diff --git a/Runtime/Library/Utilities/Enum_Library.cs.meta b/Runtime/Library/Utilities/Enum_Library.cs.meta new file mode 100644 index 0000000..527f8be --- /dev/null +++ b/Runtime/Library/Utilities/Enum_Library.cs.meta @@ -0,0 +1,2 @@ +fileFormatVersion: 2 +guid: e5ffbf87db9a03e44918bc47cd961028 \ No newline at end of file diff --git a/Runtime/Library/Utilities/File_Library.cs b/Runtime/Library/Utilities/File_Library.cs new file mode 100644 index 0000000..7549f27 --- /dev/null +++ b/Runtime/Library/Utilities/File_Library.cs @@ -0,0 +1,85 @@ +using System; +using System.IO; +using UnityEngine; + +namespace RealMethod +{ + public static class RM_File + { + public static bool WriteToFile(string contents, string fullPath) + { + try + { + File.WriteAllText(fullPath, contents); + return true; + } + catch (Exception e) + { + Debug.LogError($"Failed to write to {fullPath} with exception {e}"); + return false; + } + } + public static bool WriteToFile(string contents, string fileName, string ext) + { + var fullPath = Path.Combine(Application.persistentDataPath, fileName + ext); + return WriteToFile(fullPath, contents); + } + + public static bool ReadFromFile(string fullPath, out string result) + { + if (!File.Exists(fullPath)) + { + result = string.Empty; + return false; + } + + try + { + result = File.ReadAllText(fullPath); + return true; + } + catch (Exception e) + { + Debug.LogError($"Failed to read from {fullPath} with exception {e}"); + result = ""; + return false; + } + } + public static bool ReadFromFile(string fileName, string ext, out string result) + { + var fullPath = Path.Combine(Application.persistentDataPath, fileName + ext); + return ReadFromFile(fullPath, out result); + } + + public static bool MoveFile(string fullPath_A, string fullPath_B) + { + try + { + if (File.Exists(fullPath_B)) + { + File.Delete(fullPath_B); + } + + if (!File.Exists(fullPath_A)) + { + return false; + } + + File.Move(fullPath_A, fullPath_B); + } + catch (Exception e) + { + Debug.LogError($"Failed to move file from {fullPath_A} to {fullPath_B} with exception {e}"); + return false; + } + + return true; + } + public static bool MoveFile(string fileName_A, string fileName_B, string ext) + { + var fullPath_A = Path.Combine(Application.persistentDataPath, fileName_A + ext); + var fullPath_B = Path.Combine(Application.persistentDataPath, fileName_B + ext); + return MoveFile(fullPath_A, fullPath_B); + } + } +} \ No newline at end of file diff --git a/Runtime/Library/Utilities/File_Library.cs.meta b/Runtime/Library/Utilities/File_Library.cs.meta new file mode 100644 index 0000000..c12d39a --- /dev/null +++ b/Runtime/Library/Utilities/File_Library.cs.meta @@ -0,0 +1,2 @@ +fileFormatVersion: 2 +guid: ff2fdeb8f4eb4e642a4b90da35765dc4 \ No newline at end of file diff --git a/Runtime/Library/Utilities/Geometry.cs b/Runtime/Library/Utilities/Geometry.cs deleted file mode 100644 index 6f412df..0000000 --- a/Runtime/Library/Utilities/Geometry.cs +++ /dev/null @@ -1,37 +0,0 @@ -using UnityEngine; - -namespace RealMethod -{ - public static class RM_Geometry - { - public class Space - { - public static Vector3 GetWorldPositionFromRelative(Transform from, Vector3 relativePos) - { - return from.TransformPoint(relativePos); - } - public static Vector3 GetRelativePosition(Transform from, Transform to) - { - return from.InverseTransformPoint(to.position); - } - } - public class Plane - { - public static bool IsVectorAlignedWithVector(Vector2 vectorA, Vector2 vectorB, float tolerance) - { - float angle = Vector2.Angle(vectorA.normalized, vectorB.normalized); - if (angle <= tolerance) return true; - - return false; - } - } - public class Angle - { - - } - public class Point - { - - } - } -} \ No newline at end of file diff --git a/Runtime/Library/Utilities/Geometry.cs.meta b/Runtime/Library/Utilities/Geometry.cs.meta deleted file mode 100644 index e5d62b4..0000000 --- a/Runtime/Library/Utilities/Geometry.cs.meta +++ /dev/null @@ -1,2 +0,0 @@ -fileFormatVersion: 2 -guid: 335396769639eec4a909baf07dd159e9 \ No newline at end of file diff --git a/Runtime/Library/Utilities/Gizmos_Library.cs b/Runtime/Library/Utilities/Gizmos_Library.cs new file mode 100644 index 0000000..70ab66f --- /dev/null +++ b/Runtime/Library/Utilities/Gizmos_Library.cs @@ -0,0 +1,100 @@ +using UnityEngine; +using UnityEditor; + +namespace RealMethod +{ + public static class RM_Gizmos + { + public static void Curve(AnimationCurve curve) + { + for (float t = 0; t < curve.keys[curve.length - 1].time; t += 0.1f) + { + Gizmos.DrawSphere(new Vector3(t, curve.Evaluate(t), 0), 0.1f); + } + } + /// + /// Draws a directional arrow in the scene for debugging or visualization. + /// + /// The starting position of the arrow. + /// The direction the arrow points to. + /// Length of the arrow head. + /// Angle of the arrow head in degrees. + /// + /// Typically used for debugging directions, forces, or movement in the Scene view. + /// Implementation may use Debug.DrawLine or Gizmos. + /// + public static void Arrow(Vector3 position, Vector3 direction, float arrowHeadLength = 0.25f, float arrowHeadAngle = 20.0f) + { + Gizmos.DrawRay(position, direction); + + Vector3 right = Quaternion.LookRotation(direction) * Quaternion.Euler(0, 180 + arrowHeadAngle, 0) * Vector3.forward; + Vector3 left = Quaternion.LookRotation(direction) * Quaternion.Euler(0, 180 - arrowHeadAngle, 0) * Vector3.forward; + Gizmos.DrawRay(position + direction, right * arrowHeadLength); + Gizmos.DrawRay(position + direction, left * arrowHeadLength); + } + // Draws a directional arrow using Gizmos (with color) + public static void Arrow(Vector3 position, Vector3 direction, Color color, float arrowHeadLength = 0.25f, float arrowHeadAngle = 20.0f) + { + Gizmos.color = color; + Gizmos.DrawRay(position, direction); + + Vector3 right = Quaternion.LookRotation(direction) * Quaternion.Euler(0, 180 + arrowHeadAngle, 0) * Vector3.forward; + Vector3 left = Quaternion.LookRotation(direction) * Quaternion.Euler(0, 180 - arrowHeadAngle, 0) * Vector3.forward; + Gizmos.DrawRay(position + direction, right * arrowHeadLength); + Gizmos.DrawRay(position + direction, left * arrowHeadLength); + } + // Draws a Capsule using Gizmos (no color) + public static void Capsule(Vector3 position, float height = 2f, float radius = 0.5f) + { + // Draw top sphere + Vector3 top = position + Vector3.up * (height / 2 - radius); + Gizmos.DrawWireSphere(top, radius); + + // Draw bottom sphere + Vector3 bottom = position + Vector3.down * (height / 2 - radius); + Gizmos.DrawWireSphere(bottom, radius); + + // Draw cylinder (approximation) + Gizmos.DrawLine(top + Vector3.forward * radius, bottom + Vector3.forward * radius); + Gizmos.DrawLine(top - Vector3.forward * radius, bottom - Vector3.forward * radius); + Gizmos.DrawLine(top + Vector3.right * radius, bottom + Vector3.right * radius); + Gizmos.DrawLine(top - Vector3.right * radius, bottom - Vector3.right * radius); + } + // Draws a Capsule using Gizmos (with color) + public static void Capsule(Vector3 position, Color color, float height = 2f, float radius = 0.5f) + { + // Save previous Gizmos color + Color prevColor = Gizmos.color; + Gizmos.color = color; + + // Draw top sphere + Vector3 top = position + Vector3.up * (height / 2 - radius); + Gizmos.DrawWireSphere(top, radius); + + // Draw bottom sphere + Vector3 bottom = position + Vector3.down * (height / 2 - radius); + Gizmos.DrawWireSphere(bottom, radius); + + // Draw cylinder (approximation) + Gizmos.DrawLine(top + Vector3.forward * radius, bottom + Vector3.forward * radius); + Gizmos.DrawLine(top - Vector3.forward * radius, bottom - Vector3.forward * radius); + Gizmos.DrawLine(top + Vector3.right * radius, bottom + Vector3.right * radius); + Gizmos.DrawLine(top - Vector3.right * radius, bottom - Vector3.right * radius); + + // Restore previous color + Gizmos.color = prevColor; + } + // Draw a Text using Gizmos (With Colort) + public static void Text(string text, Vector3 position, Color color, FontStyle font = FontStyle.Bold, TextAnchor ancher = TextAnchor.MiddleCenter) + { + // Set color + GUIStyle style = new GUIStyle(); + style.normal.textColor = color; + style.alignment = ancher; + style.fontStyle = font; + + // Draw the label above the GameObject + Handles.Label(position, text, style); + } + } +} \ No newline at end of file diff --git a/Runtime/Library/Utilities/Gizmos_Library.cs.meta b/Runtime/Library/Utilities/Gizmos_Library.cs.meta new file mode 100644 index 0000000..80104ac --- /dev/null +++ b/Runtime/Library/Utilities/Gizmos_Library.cs.meta @@ -0,0 +1,2 @@ +fileFormatVersion: 2 +guid: c891057bb2667044b994087f418ec1b1 \ No newline at end of file diff --git a/Runtime/Library/Utilities/Math.cs b/Runtime/Library/Utilities/Math.cs deleted file mode 100644 index 0c98c4b..0000000 --- a/Runtime/Library/Utilities/Math.cs +++ /dev/null @@ -1,159 +0,0 @@ -using UnityEngine; - - -namespace RealMethod -{ - public static class RM_Math - { - public static Vector3 TwoD => new Vector3(1, 0, 1); - - /// - /// Maps a float value from one range to another and clamps the result to the output range. - /// - /// The input value to map. - /// Minimum of the input range. - /// Maximum of the input range. - /// Minimum of the output range. - /// Maximum of the output range. - /// Mapped and clamped float value. - public static float RemapClamped(float value, float inMin, float inMax, float outMin, float outMax) - { - // Prevent divide by zero - if (Mathf.Approximately(inMax, inMin)) - { - Debug.LogWarning("Input range is zero. Returning outMin."); - return outMin; - } - - // Normalize the input value to 0–1 within the input range - float t = (value - inMin) / (inMax - inMin); - - // Scale and offset to target range - float mappedValue = t * (outMax - outMin) + outMin; - - // Clamp result to the output range - return Mathf.Clamp(mappedValue, Mathf.Min(outMin, outMax), Mathf.Max(outMin, outMax)); - } - /// - /// Determines whether a value is within a specified range, with control over boundary inclusivity. - /// - /// The value to check. - /// The lower bound of the range. - /// The upper bound of the range. - /// Whether the lower bound is inclusive (>=). - /// Whether the upper bound is inclusive (<=). - /// True if the value is within the range; otherwise, false. - public static bool IsInRange(float value, float min, float max, bool inclusiveMin = true, bool inclusiveMax = true) - { - bool isAboveMin = inclusiveMin ? value >= min : value > min; - bool isBelowMax = inclusiveMax ? value <= max : value < max; - - return isAboveMin && isBelowMax; - } - - public class Interpolate - { - /// - /// Interpolates a value from Current to Target, applying a given speed over DeltaTime. - /// Mimics Unreal Engine's FInterpTo function. - /// - /// The current value. - /// The target value. - /// The time step to apply the interpolation. - /// The interpolation speed. - /// The interpolated value. - public static float FInterpTo(float current, float target, float deltaTime, float interpSpeed) - { - if (interpSpeed <= 0f || Mathf.Approximately(current, target)) - { - return target; // If speed is zero or already at the target, no interpolation needed - } - - float delta = target - current; // Difference between current and target - float step = delta * Mathf.Clamp01(interpSpeed * deltaTime); // Calculate interpolation step - - return current + step; // Move the current value closer to the target - } - /// - /// Interpolates a value from Current to Target at a constant speed over DeltaTime. - /// Mimics Unreal Engine's FInterpToConstant function. - /// - /// The current value. - /// The target value. - /// The time step to apply the interpolation. - /// The constant speed of interpolation. - /// The interpolated value. - public static float FInterpToConstant(float current, float target, float deltaTime, float interpSpeed) - { - if (interpSpeed <= 0f || Mathf.Approximately(current, target)) - { - return target; // If speed is zero or already at the target, no interpolation needed - } - - // Calculate the step size for this frame - float step = interpSpeed * deltaTime; - - // Move towards the target by the step size, clamped to not overshoot - if (Mathf.Abs(target - current) <= step) - { - return target; // If within one step, snap to target - } - - // Move towards the target - return current + Mathf.Sign(target - current) * step; - } - public static Vector3 VInterpTo(Vector3 current, Vector3 target, float deltaTime, float interpSpeed) - { - if (interpSpeed <= 0f || current == target) - { - return target; // If speed is zero or already at the target, no interpolation needed - } - - // Interpolate towards the target - return Vector3.Lerp(current, target, Mathf.Clamp01(interpSpeed * deltaTime)); - } - public static Vector3 VInterpToConstant(Vector3 current, Vector3 target, float deltaTime, float interpSpeed) - { - if (interpSpeed <= 0f || current == target) - { - return target; // If speed is zero or already at the target, no interpolation needed - } - - // Calculate the step size - Vector3 direction = (target - current).normalized; - float distance = Vector3.Distance(current, target); - float step = interpSpeed * deltaTime; - - // Move towards the target by the step size, clamped to not overshoot - return distance <= step ? target : current + direction * step; - } - public static Quaternion RInterpTo(Quaternion current, Quaternion target, float deltaTime, float interpSpeed) - { - if (interpSpeed <= 0f || current == target) - { - return target; // If speed is zero or already at the target, no interpolation needed - } - - // Interpolate towards the target - return Quaternion.Slerp(current, target, Mathf.Clamp01(interpSpeed * deltaTime)); - } - public static Quaternion RInterpToConstant(Quaternion current, Quaternion target, float deltaTime, float interpSpeed) - { - if (interpSpeed <= 0f || current == target) - { - return target; // If speed is zero or already at the target, no interpolation needed - } - - // Calculate the step size - float angle = Quaternion.Angle(current, target); - float step = interpSpeed * deltaTime; - - // Rotate towards the target by the step size, clamped to not overshoot - return angle <= step ? target : Quaternion.RotateTowards(current, target, step); - } - - } - - } - -} diff --git a/Runtime/Library/Utilities/Math_Library.cs b/Runtime/Library/Utilities/Math_Library.cs new file mode 100644 index 0000000..41641f2 --- /dev/null +++ b/Runtime/Library/Utilities/Math_Library.cs @@ -0,0 +1,154 @@ +using UnityEngine; + + +namespace RealMethod +{ + public static class RM_Math + { + public static Vector3 TwoD => new Vector3(1, 0, 1); + + /// + /// Maps a float value from one range to another and clamps the result to the output range. + /// + /// The input value to map. + /// Minimum of the input range. + /// Maximum of the input range. + /// Minimum of the output range. + /// Maximum of the output range. + /// Mapped and clamped float value. + public static float RemapClamped(float value, float inMin, float inMax, float outMin, float outMax) + { + // Prevent divide by zero + if (Mathf.Approximately(inMax, inMin)) + { + Debug.LogWarning("Input range is zero. Returning outMin."); + return outMin; + } + + // Normalize the input value to 0–1 within the input range + float t = (value - inMin) / (inMax - inMin); + + // Scale and offset to target range + float mappedValue = t * (outMax - outMin) + outMin; + + // Clamp result to the output range + return Mathf.Clamp(mappedValue, Mathf.Min(outMin, outMax), Mathf.Max(outMin, outMax)); + } + /// + /// Determines whether a value is within a specified range, with control over boundary inclusivity. + /// + /// The value to check. + /// The lower bound of the range. + /// The upper bound of the range. + /// Whether the lower bound is inclusive (>=). + /// Whether the upper bound is inclusive (<=). + /// True if the value is within the range; otherwise, false. + public static bool IsInRange(float value, float min, float max, bool inclusiveMin = true, bool inclusiveMax = true) + { + bool isAboveMin = inclusiveMin ? value >= min : value > min; + bool isBelowMax = inclusiveMax ? value <= max : value < max; + + return isAboveMin && isBelowMax; + } + /// + /// Interpolates a value from Current to Target, applying a given speed over DeltaTime. + /// Mimics Unreal Engine's FInterpTo function. + /// + /// The current value. + /// The target value. + /// The time step to apply the interpolation. + /// The interpolation speed. + /// The interpolated value. + public static float FInterpTo(float current, float target, float deltaTime, float interpSpeed) + { + if (interpSpeed <= 0f || Mathf.Approximately(current, target)) + { + return target; // If speed is zero or already at the target, no interpolation needed + } + + float delta = target - current; // Difference between current and target + float step = delta * Mathf.Clamp01(interpSpeed * deltaTime); // Calculate interpolation step + + return current + step; // Move the current value closer to the target + } + /// + /// Interpolates a value from Current to Target at a constant speed over DeltaTime. + /// Mimics Unreal Engine's FInterpToConstant function. + /// + /// The current value. + /// The target value. + /// The time step to apply the interpolation. + /// The constant speed of interpolation. + /// The interpolated value. + public static float FInterpToConstant(float current, float target, float deltaTime, float interpSpeed) + { + if (interpSpeed <= 0f || Mathf.Approximately(current, target)) + { + return target; // If speed is zero or already at the target, no interpolation needed + } + + // Calculate the step size for this frame + float step = interpSpeed * deltaTime; + + // Move towards the target by the step size, clamped to not overshoot + if (Mathf.Abs(target - current) <= step) + { + return target; // If within one step, snap to target + } + + // Move towards the target + return current + Mathf.Sign(target - current) * step; + } + public static Vector3 VInterpTo(Vector3 current, Vector3 target, float deltaTime, float interpSpeed) + { + if (interpSpeed <= 0f || current == target) + { + return target; // If speed is zero or already at the target, no interpolation needed + } + + // Interpolate towards the target + return Vector3.Lerp(current, target, Mathf.Clamp01(interpSpeed * deltaTime)); + } + public static Vector3 VInterpToConstant(Vector3 current, Vector3 target, float deltaTime, float interpSpeed) + { + if (interpSpeed <= 0f || current == target) + { + return target; // If speed is zero or already at the target, no interpolation needed + } + + // Calculate the step size + Vector3 direction = (target - current).normalized; + float distance = Vector3.Distance(current, target); + float step = interpSpeed * deltaTime; + + // Move towards the target by the step size, clamped to not overshoot + return distance <= step ? target : current + direction * step; + } + public static Quaternion RInterpTo(Quaternion current, Quaternion target, float deltaTime, float interpSpeed) + { + if (interpSpeed <= 0f || current == target) + { + return target; // If speed is zero or already at the target, no interpolation needed + } + + // Interpolate towards the target + return Quaternion.Slerp(current, target, Mathf.Clamp01(interpSpeed * deltaTime)); + } + public static Quaternion RInterpToConstant(Quaternion current, Quaternion target, float deltaTime, float interpSpeed) + { + if (interpSpeed <= 0f || current == target) + { + return target; // If speed is zero or already at the target, no interpolation needed + } + + // Calculate the step size + float angle = Quaternion.Angle(current, target); + float step = interpSpeed * deltaTime; + + // Rotate towards the target by the step size, clamped to not overshoot + return angle <= step ? target : Quaternion.RotateTowards(current, target, step); + } + + } + +} diff --git a/Runtime/Library/Utilities/Math.cs.meta b/Runtime/Library/Utilities/Math_Library.cs.meta similarity index 100% rename from Runtime/Library/Utilities/Math.cs.meta rename to Runtime/Library/Utilities/Math_Library.cs.meta diff --git a/Runtime/Library/Utilities/Physics.cs b/Runtime/Library/Utilities/Physics.cs deleted file mode 100644 index 65afde9..0000000 --- a/Runtime/Library/Utilities/Physics.cs +++ /dev/null @@ -1,51 +0,0 @@ -using UnityEngine; - -namespace RealMethod -{ - public static class RM_Physics - { - public class Trace - { - public static bool Line(Vector3 Start, Vector3 Direction, float Length, LayerMask Layer, QueryTriggerInteraction TriggerInteraction, Color RayColor, Color HitColor, out RaycastHit HitResult) - { - bool Result; - Result = Physics.Raycast(Start, Direction, out HitResult, Length, Layer, TriggerInteraction); - float debuglength = HitResult.collider ? HitResult.distance : Length; - Color debugcolor = HitResult.collider ? HitColor : RayColor; - Debug.DrawRay(Start, Direction * debuglength, debugcolor); - return Result; - } - - public static bool Line(Vector3 Start, Vector3 Direction, float Length, LayerMask Layer, QueryTriggerInteraction TriggerInteraction, out RaycastHit HitResult) - { - bool Result; - Result = Physics.Raycast(Start, Direction, out HitResult, Length, Layer, TriggerInteraction); - float debuglength = HitResult.collider ? HitResult.distance : Length; - Color debugcolor = HitResult.collider ? Color.green : Color.red; - Debug.DrawRay(Start, Direction * debuglength, debugcolor); - return Result; - } - - public static bool Line(Vector3 Start, Vector3 Direction, float Length, LayerMask Layer, out RaycastHit HitResult) - { - bool Result; - Result = Physics.Raycast(Start, Direction, out HitResult, Length, Layer); - float debuglength = HitResult.collider ? HitResult.distance : Length; - Color debugcolor = HitResult.collider ? Color.green : Color.red; - Debug.DrawRay(Start, Direction * debuglength, debugcolor); - return Result; - } - - public static bool Line(Vector3 Start, Vector3 Direction, float Length, out RaycastHit HitResult) - { - bool Result; - Result = Physics.Raycast(Start, Direction, out HitResult, Length); - float debuglength = HitResult.collider ? HitResult.distance : Length; - Color debugcolor = HitResult.collider ? Color.green : Color.red; - Debug.DrawRay(Start, Direction * debuglength, debugcolor); - return Result; - } - } - - } -} \ No newline at end of file diff --git a/Runtime/Library/Utilities/Physics.cs.meta b/Runtime/Library/Utilities/Physics.cs.meta deleted file mode 100644 index 6f6ba36..0000000 --- a/Runtime/Library/Utilities/Physics.cs.meta +++ /dev/null @@ -1,2 +0,0 @@ -fileFormatVersion: 2 -guid: f07234397f0818143a880ee7d03a527e \ No newline at end of file diff --git a/Runtime/Library/Utilities/Reflection_Library.cs b/Runtime/Library/Utilities/Reflection_Library.cs new file mode 100644 index 0000000..1450842 --- /dev/null +++ b/Runtime/Library/Utilities/Reflection_Library.cs @@ -0,0 +1,35 @@ +using System; +using System.Linq.Expressions; + +namespace RealMethod +{ + public static class RM_Reflection + { + /// + /// Extracts the variable or property name from a lambda expression. + /// + /// The type of the variable or property. + /// + /// A lambda expression pointing to a variable or property + /// (e.g. () => myVariable or () => myObject.MyProperty). + /// + /// + /// The name of the variable or property represented by the expression. + /// + /// + /// Thrown if the expression does not represent a valid variable or property access. + /// + /// + /// This method is commonly used to avoid hard-coded string names, + /// especially for logging, debugging, and change-notification systems. + /// F + public static string GetVariableName(Expression> expression) + { + if (expression.Body is MemberExpression memberExpression) + { + return memberExpression.Member.Name; + } + throw new ArgumentException("Expression is not a valid member expression."); + } + } +} \ No newline at end of file diff --git a/Runtime/Library/Utilities/Reflection_Library.cs.meta b/Runtime/Library/Utilities/Reflection_Library.cs.meta new file mode 100644 index 0000000..0c81e1d --- /dev/null +++ b/Runtime/Library/Utilities/Reflection_Library.cs.meta @@ -0,0 +1,2 @@ +fileFormatVersion: 2 +guid: 298b3a9137927964ba5d5ec48bdf853b \ No newline at end of file diff --git a/Runtime/Library/Utilities/PlayerPrefs.cs b/Runtime/Library/Utilities/Save_Library.cs similarity index 99% rename from Runtime/Library/Utilities/PlayerPrefs.cs rename to Runtime/Library/Utilities/Save_Library.cs index 3d844e1..f2d2d24 100644 --- a/Runtime/Library/Utilities/PlayerPrefs.cs +++ b/Runtime/Library/Utilities/Save_Library.cs @@ -3,7 +3,7 @@ namespace RealMethod { - public static class RM_PlayerPrefs + public static class RM_Save { // Boolean public static void SetBool(string key, bool value) diff --git a/Runtime/Library/Utilities/PlayerPrefs.cs.meta b/Runtime/Library/Utilities/Save_Library.cs.meta similarity index 100% rename from Runtime/Library/Utilities/PlayerPrefs.cs.meta rename to Runtime/Library/Utilities/Save_Library.cs.meta diff --git a/Runtime/Library/Utilities/Time_Library.cs b/Runtime/Library/Utilities/Time_Library.cs new file mode 100644 index 0000000..89373f7 --- /dev/null +++ b/Runtime/Library/Utilities/Time_Library.cs @@ -0,0 +1,68 @@ +using UnityEngine; +using System.Collections; + + +namespace RealMethod +{ + public static class RM_Time + { + private class CoroutineHandeler + { + public bool IsDone { get; private set; } + + public IEnumerator Run(IEnumerator coroutine) + { + yield return coroutine; + IsDone = true; + } + } + + + /// + /// Waits for a specified duration and then invokes a callback. + /// + /// Time in seconds to wait before executing the callback. + /// The action to invoke after the delay. + /// + /// An IEnumerator that can be used in a Unity coroutine. + /// + /// + /// Must be started using StartCoroutine(). + /// + public static IEnumerator Delay(float duration, System.Action callback) + { + yield return new WaitForSeconds(duration); + callback?.Invoke(); + } + public static IEnumerator WaitUntil(System.Func condition, System.Action callback) + { + yield return new WaitUntil(condition); + callback?.Invoke(); + } + public static IEnumerator WaitWhile(System.Func condition, System.Action callback) + { + yield return new WaitWhile(condition); + callback?.Invoke(); + } + public static IEnumerator Repeat(System.Action action, float interval, int count = -1) + { + int i = 0; + while (count < 0 || i < count) + { + action?.Invoke(); + i++; + yield return new WaitForSeconds(interval); + } + } + public static IEnumerator DelayOneFrame(System.Action callback) + { + yield return new WaitForEndOfFrame(); + callback?.Invoke(); + } + public static IEnumerator WaitForCoroutine(MonoBehaviour Owner, IEnumerator coroutine) + { + CoroutineHandeler handle = new CoroutineHandeler(); + yield return Owner.StartCoroutine(handle.Run(coroutine)); + } + } +} \ No newline at end of file diff --git a/Runtime/Library/Utilities/Time_Library.cs.meta b/Runtime/Library/Utilities/Time_Library.cs.meta new file mode 100644 index 0000000..7c06477 --- /dev/null +++ b/Runtime/Library/Utilities/Time_Library.cs.meta @@ -0,0 +1,2 @@ +fileFormatVersion: 2 +guid: 72d36d1c7404fca4ead9a94680ca3050 \ No newline at end of file diff --git a/Runtime/Library/Utilities/Trace_Library.cs b/Runtime/Library/Utilities/Trace_Library.cs new file mode 100644 index 0000000..c8c582c --- /dev/null +++ b/Runtime/Library/Utilities/Trace_Library.cs @@ -0,0 +1,70 @@ +using UnityEngine; + +namespace RealMethod +{ + public static class RM_Trace + { + /// + /// Casts a debug line (ray) from a starting point in a given direction + /// with visual feedback for hits and misses. + /// + /// The origin point of the ray. + /// The direction the ray will fire in. + /// The maximum length of the ray. + /// The layer mask that the ray interacts with. + /// + /// Defines whether the ray should hit trigger colliders. + /// + /// Color of the ray if no hit occurs. + /// Color of the ray when a hit occurs. + /// + /// Output RaycastHit containing information about the hit. + /// + /// + /// True if the ray hits a collider; otherwise false. + /// + /// + /// Useful for debugging raycasts in the Scene view. + /// Typically implemented using Physics.Raycast() combined with Debug.DrawLine(). + /// + public static bool Line(Vector3 Start, Vector3 Direction, float Length, LayerMask Layer, QueryTriggerInteraction TriggerInteraction, Color RayColor, Color HitColor, out RaycastHit HitResult) + { + bool Result; + Result = Physics.Raycast(Start, Direction, out HitResult, Length, Layer, TriggerInteraction); + float debuglength = HitResult.collider ? HitResult.distance : Length; + Color debugcolor = HitResult.collider ? HitColor : RayColor; + Debug.DrawRay(Start, Direction * debuglength, debugcolor); + return Result; + } + + public static bool Line(Vector3 Start, Vector3 Direction, float Length, LayerMask Layer, QueryTriggerInteraction TriggerInteraction, out RaycastHit HitResult) + { + bool Result; + Result = Physics.Raycast(Start, Direction, out HitResult, Length, Layer, TriggerInteraction); + float debuglength = HitResult.collider ? HitResult.distance : Length; + Color debugcolor = HitResult.collider ? Color.green : Color.red; + Debug.DrawRay(Start, Direction * debuglength, debugcolor); + return Result; + } + + public static bool Line(Vector3 Start, Vector3 Direction, float Length, LayerMask Layer, out RaycastHit HitResult) + { + bool Result; + Result = Physics.Raycast(Start, Direction, out HitResult, Length, Layer); + float debuglength = HitResult.collider ? HitResult.distance : Length; + Color debugcolor = HitResult.collider ? Color.green : Color.red; + Debug.DrawRay(Start, Direction * debuglength, debugcolor); + return Result; + } + + public static bool Line(Vector3 Start, Vector3 Direction, float Length, out RaycastHit HitResult) + { + bool Result; + Result = Physics.Raycast(Start, Direction, out HitResult, Length); + float debuglength = HitResult.collider ? HitResult.distance : Length; + Color debugcolor = HitResult.collider ? Color.green : Color.red; + Debug.DrawRay(Start, Direction * debuglength, debugcolor); + return Result; + } + } +} \ No newline at end of file diff --git a/Runtime/Library/Utilities/Trace_Library.cs.meta b/Runtime/Library/Utilities/Trace_Library.cs.meta new file mode 100644 index 0000000..1f4e2a5 --- /dev/null +++ b/Runtime/Library/Utilities/Trace_Library.cs.meta @@ -0,0 +1,2 @@ +fileFormatVersion: 2 +guid: e72b5d1882269eb4c87476db08cef7fd \ No newline at end of file diff --git a/Runtime/Library/Utilities/Transform_Library.cs b/Runtime/Library/Utilities/Transform_Library.cs new file mode 100644 index 0000000..cad5e8a --- /dev/null +++ b/Runtime/Library/Utilities/Transform_Library.cs @@ -0,0 +1,26 @@ +using UnityEngine; + +namespace RealMethod +{ + public static class RM_Transform + { + /// + /// Converts a position defined relative to a transform into world space. + /// + /// The reference transform. + /// The position relative to the transform. + /// The corresponding world space position. + /// + /// Useful when you want to compute positions relative to an object + /// and convert them to world coordinates. + /// + public static Vector3 GetWorldPositionFromRelative(Transform from, Vector3 relativePos) + { + return from.TransformPoint(relativePos); + } + public static Vector3 GetRelativePosition(Transform from, Transform to) + { + return from.InverseTransformPoint(to.position); + } + } +} \ No newline at end of file diff --git a/Runtime/Library/Utilities/Transform_Library.cs.meta b/Runtime/Library/Utilities/Transform_Library.cs.meta new file mode 100644 index 0000000..1be6907 --- /dev/null +++ b/Runtime/Library/Utilities/Transform_Library.cs.meta @@ -0,0 +1,2 @@ +fileFormatVersion: 2 +guid: 8953e453fba18d04d9ab0848fb84c663 \ No newline at end of file diff --git a/Runtime/Library/Utilities/Tween_Library.cs b/Runtime/Library/Utilities/Tween_Library.cs new file mode 100644 index 0000000..4dba6f3 --- /dev/null +++ b/Runtime/Library/Utilities/Tween_Library.cs @@ -0,0 +1,68 @@ +using System.Collections; +using UnityEngine; + +namespace RealMethod +{ + public static class Tween + { + /// + /// Moves the target transform to a specified position over a given duration. + /// + /// The transform to move. + /// The target position. + /// The time in seconds to complete the movement. + /// An IEnumerator for use with StartCoroutine. + /// + /// Should be started with StartCoroutine(). + /// + public static IEnumerator MoveTo(Transform target, Vector3 end, float duration) + { + Vector3 start = target.position; + float t = 0f; + while (t < duration) + { + t += Time.deltaTime; + target.position = Vector3.Lerp(start, end, t / duration); + yield return null; + } + target.position = end; + } + public static IEnumerator FadeCanvas(CanvasGroup canvas, float targetAlpha, float duration) + { + float start = canvas.alpha; + float t = 0f; + while (t < duration) + { + t += Time.deltaTime; + canvas.alpha = Mathf.Lerp(start, targetAlpha, t / duration); + yield return null; + } + canvas.alpha = targetAlpha; + } + public static IEnumerator ScaleTo(Transform target, Vector3 targetScale, float duration) + { + Vector3 start = target.localScale; + float t = 0f; + while (t < duration) + { + t += Time.deltaTime; + target.localScale = Vector3.Lerp(start, targetScale, t / duration); + yield return null; + } + target.localScale = targetScale; + } + public static IEnumerator RotateTo(Transform target, Quaternion targetRot, float duration) + { + Quaternion start = target.rotation; + float t = 0f; + while (t < duration) + { + t += Time.deltaTime; + target.rotation = Quaternion.Slerp(start, targetRot, t / duration); + yield return null; + } + target.rotation = targetRot; + } + + } +} \ No newline at end of file diff --git a/Runtime/Library/Utilities/Tween_Library.cs.meta b/Runtime/Library/Utilities/Tween_Library.cs.meta new file mode 100644 index 0000000..e554de8 --- /dev/null +++ b/Runtime/Library/Utilities/Tween_Library.cs.meta @@ -0,0 +1,2 @@ +fileFormatVersion: 2 +guid: c5c296c6d6b432444b15ade9d82079bd \ No newline at end of file diff --git a/Runtime/Library/Utilities/UI_Library.cs b/Runtime/Library/Utilities/UI_Library.cs new file mode 100644 index 0000000..3084b1d --- /dev/null +++ b/Runtime/Library/Utilities/UI_Library.cs @@ -0,0 +1,26 @@ +using System.Collections.Generic; +using UnityEngine; +using UnityEngine.EventSystems; +using UnityEngine.UI; + +namespace RealMethod +{ + public static class RM_UI + { + public static bool IsTouchOverUI(GraphicRaycaster HUD_graphicRaycaster, Vector2 touchPosition) + { + // Create a pointer event data from the touch position + PointerEventData pointerEventData = new PointerEventData(null); + pointerEventData.position = touchPosition; + + // Create a list to hold the results + List results = new List(); + + // Raycast using the GraphicRaycaster and pointer event data + HUD_graphicRaycaster.Raycast(pointerEventData, results); + + // Check if we hit any UI elements + return results.Count > 0; + } + } +} \ No newline at end of file diff --git a/Runtime/Library/Utilities/UI_Library.cs.meta b/Runtime/Library/Utilities/UI_Library.cs.meta new file mode 100644 index 0000000..eee2035 --- /dev/null +++ b/Runtime/Library/Utilities/UI_Library.cs.meta @@ -0,0 +1,2 @@ +fileFormatVersion: 2 +guid: fc40a86d617dbe446bc15839695b6d05 \ No newline at end of file diff --git a/Runtime/Library/Utilities/Vector_Library.cs b/Runtime/Library/Utilities/Vector_Library.cs new file mode 100644 index 0000000..8ac1eab --- /dev/null +++ b/Runtime/Library/Utilities/Vector_Library.cs @@ -0,0 +1,31 @@ +using UnityEngine; + +namespace RealMethod +{ + public static class RM_Vector + { + /// + /// Determines whether two vectors are aligned within a specified tolerance. + /// + /// The first vector. + /// The second vector. + /// + /// The allowed deviation when comparing alignment. + /// Smaller values require closer directional similarity. + /// + /// + /// True if the vectors are aligned within the given tolerance; otherwise false. + /// + /// + /// Alignment usually means the vectors point in nearly the same direction, + /// typically evaluated using the dot product or angle between them. + /// + public static bool IsAligned(Vector2 vectorA, Vector2 vectorB, float tolerance) + { + float angle = Vector2.Angle(vectorA.normalized, vectorB.normalized); + if (angle <= tolerance) return true; + + return false; + } + } +} \ No newline at end of file diff --git a/Runtime/Library/Utilities/Vector_Library.cs.meta b/Runtime/Library/Utilities/Vector_Library.cs.meta new file mode 100644 index 0000000..0b0cdce --- /dev/null +++ b/Runtime/Library/Utilities/Vector_Library.cs.meta @@ -0,0 +1,2 @@ +fileFormatVersion: 2 +guid: 09d0d2dad219dab45a030c4238bd1320 \ No newline at end of file diff --git a/Runtime/Toolkit/Inventory/InventorySaveFile.cs b/Runtime/Toolkit/Inventory/InventorySaveFile.cs index 8daf63f..3b3df79 100644 --- a/Runtime/Toolkit/Inventory/InventorySaveFile.cs +++ b/Runtime/Toolkit/Inventory/InventorySaveFile.cs @@ -30,18 +30,18 @@ protected override void OnSaved() { if (UsePlayerPrefs) { - RM_PlayerPrefs.SetArray("ItemsName", ItemsName.ToArray()); - RM_PlayerPrefs.SetArray("ItemsQuantity", ItemsQuantity.ToArray()); - RM_PlayerPrefs.SetArray("ItemsCapacity", ItemsCapacity.ToArray()); + RM_Save.SetArray("ItemsName", ItemsName.ToArray()); + RM_Save.SetArray("ItemsQuantity", ItemsQuantity.ToArray()); + RM_Save.SetArray("ItemsCapacity", ItemsCapacity.ToArray()); } } protected override void OnLoaded() { if (UsePlayerPrefs) { - ItemsName = RM_PlayerPrefs.GetArray("ItemsName").ToList(); - ItemsQuantity = RM_PlayerPrefs.GetArray("ItemsQuantity").ToList(); - ItemsCapacity = RM_PlayerPrefs.GetArray("ItemsCapacity").ToList(); + ItemsName = RM_Save.GetArray("ItemsName").ToList(); + ItemsQuantity = RM_Save.GetArray("ItemsQuantity").ToList(); + ItemsCapacity = RM_Save.GetArray("ItemsCapacity").ToList(); } } protected override void OnDeleted() diff --git a/Runtime/Toolkit/RPG/StatSystem/BuffConfig.cs b/Runtime/Toolkit/RPG/StatSystem/BuffConfig.cs index afb2caf..dc3b416 100644 --- a/Runtime/Toolkit/RPG/StatSystem/BuffConfig.cs +++ b/Runtime/Toolkit/RPG/StatSystem/BuffConfig.cs @@ -59,7 +59,7 @@ public sealed override IStatModifier[] GetModifiers(J StateName) int targetindex = System.Convert.ToInt32(StateName); foreach (var modif in presets) { - if (RM_Core.enume.AreEnumValuesEqual(modif.Stat, StateName)) + if (RM_Enum.AreEnumValuesEqual(modif.Stat, StateName)) { Result.Add(modif); } diff --git a/Runtime/Toolkit/RPG/StatSystem/StatSaveFile.cs b/Runtime/Toolkit/RPG/StatSystem/StatSaveFile.cs index 867f38d..21e5632 100644 --- a/Runtime/Toolkit/RPG/StatSystem/StatSaveFile.cs +++ b/Runtime/Toolkit/RPG/StatSystem/StatSaveFile.cs @@ -26,20 +26,20 @@ protected override void OnSaved() { if (UsePlayerPrefs) { - RM_PlayerPrefs.SetArray("StatName", Names.ToArray()); - RM_PlayerPrefs.SetArray("StatBaseValue", BaseValue.ToArray()); - RM_PlayerPrefs.SetArray("StatMin", Mins.ToArray()); - RM_PlayerPrefs.SetArray("StatMax", Maxs.ToArray()); + RM_Save.SetArray("StatName", Names.ToArray()); + RM_Save.SetArray("StatBaseValue", BaseValue.ToArray()); + RM_Save.SetArray("StatMin", Mins.ToArray()); + RM_Save.SetArray("StatMax", Maxs.ToArray()); } } protected override void OnLoaded() { if (UsePlayerPrefs) { - Names = RM_PlayerPrefs.GetArray("StatName").ToList(); - BaseValue = RM_PlayerPrefs.GetArray("StatBaseValue").ToList(); - Mins = RM_PlayerPrefs.GetArray("StatMin").ToList(); - Maxs = RM_PlayerPrefs.GetArray("StatMax").ToList(); + Names = RM_Save.GetArray("StatName").ToList(); + BaseValue = RM_Save.GetArray("StatBaseValue").ToList(); + Mins = RM_Save.GetArray("StatMin").ToList(); + Maxs = RM_Save.GetArray("StatMax").ToList(); } } protected override void OnDeleted() diff --git a/Runtime/Toolkit/Tutorial/TutorialSaveFile.cs b/Runtime/Toolkit/Tutorial/TutorialSaveFile.cs index 793d322..96e5061 100644 --- a/Runtime/Toolkit/Tutorial/TutorialSaveFile.cs +++ b/Runtime/Toolkit/Tutorial/TutorialSaveFile.cs @@ -22,12 +22,12 @@ protected override void OnStable(DataManager manager) protected override void OnSaved() { if (UsePlayerPrefs) - RM_PlayerPrefs.SetArray("Tutorial", TutorialMessage.ToArray()); + RM_Save.SetArray("Tutorial", TutorialMessage.ToArray()); } protected override void OnLoaded() { if (UsePlayerPrefs) - TutorialMessage = RM_PlayerPrefs.GetArray("Tutorial").ToHashSet(); + TutorialMessage = RM_Save.GetArray("Tutorial").ToHashSet(); } protected override void OnDeleted() { diff --git a/Runtime/Toolkit/Upgrade/UpgradeSaveFile.cs b/Runtime/Toolkit/Upgrade/UpgradeSaveFile.cs index 37b41ec..875dbcc 100644 --- a/Runtime/Toolkit/Upgrade/UpgradeSaveFile.cs +++ b/Runtime/Toolkit/Upgrade/UpgradeSaveFile.cs @@ -21,16 +21,16 @@ protected override void OnSaved() { if (UsePlayerPrefs) { - RM_PlayerPrefs.SetArray("UnlockItems", UnlockItems.ToArray()); - RM_PlayerPrefs.SetArray("AvailableItems", AvailableItems.ToArray()); + RM_Save.SetArray("UnlockItems", UnlockItems.ToArray()); + RM_Save.SetArray("AvailableItems", AvailableItems.ToArray()); } } protected override void OnLoaded() { if (UsePlayerPrefs) { - UnlockItems = RM_PlayerPrefs.GetArray("UnlockItems").ToList(); - AvailableItems = RM_PlayerPrefs.GetArray("AvailableItems").ToList(); + UnlockItems = RM_Save.GetArray("UnlockItems").ToList(); + AvailableItems = RM_Save.GetArray("AvailableItems").ToList(); } } protected override void OnDeleted() diff --git a/Tests/ScriptInspectorWindow.cs b/Tests/ScriptInspectorWindow.cs deleted file mode 100644 index 3c17f81..0000000 --- a/Tests/ScriptInspectorWindow.cs +++ /dev/null @@ -1,131 +0,0 @@ -using UnityEngine; -using UnityEditor; -using System; -using System.Reflection; -using System.Text; - -public class ScriptInspectorWindow : EditorWindow -{ - private MonoScript script; - private Vector2 scroll; - private string output; - - [MenuItem("Tools/Script Inspector")] - static void Open() - { - GetWindow("Script Inspector"); - } - - void OnGUI() - { - EditorGUILayout.LabelField("Select MonoScript", EditorStyles.boldLabel); - - script = (MonoScript)EditorGUILayout.ObjectField( - "Script", - script, - typeof(MonoScript), - false); - - if (GUILayout.Button("Analyze Script")) - { - Analyze(); - } - - scroll = EditorGUILayout.BeginScrollView(scroll); - - EditorGUILayout.TextArea(output, GUILayout.ExpandHeight(true)); - - EditorGUILayout.EndScrollView(); - } - - void Analyze() - { - if (script == null) - { - output = "No script selected."; - return; - } - - Type type = script.GetClass(); - - if (type == null) - { - output = "Could not find class in script."; - return; - } - - StringBuilder sb = new StringBuilder(); - - sb.AppendLine("=== SCRIPT INFO ==="); - sb.AppendLine($"Namespace: {type.Namespace}"); - sb.AppendLine($"Class: {type.Name}"); - sb.AppendLine($"Abstract: {type.IsAbstract}"); - sb.AppendLine($"Sealed: {type.IsSealed}"); - sb.AppendLine($"Static: {type.IsAbstract && type.IsSealed}"); - sb.AppendLine(""); - - BindingFlags flags = - BindingFlags.Public | - BindingFlags.NonPublic | - BindingFlags.Instance | - BindingFlags.Static | - BindingFlags.DeclaredOnly; - - // Fields - sb.AppendLine("=== FIELDS ==="); - foreach (var field in type.GetFields(flags)) - { - sb.AppendLine($"{GetAccess(field)} {field.FieldType.Name} {field.Name}"); - } - - sb.AppendLine(""); - - // Properties - sb.AppendLine("=== PROPERTIES ==="); - foreach (var prop in type.GetProperties(flags)) - { - sb.AppendLine($"{prop.PropertyType.Name} {prop.Name}"); - } - - sb.AppendLine(""); - - // Methods - sb.AppendLine("=== METHODS ==="); - foreach (var method in type.GetMethods(flags)) - { - if (method.IsSpecialName) continue; - - sb.Append($"{GetAccess(method)} {method.ReturnType.Name} {method.Name}("); - - var parameters = method.GetParameters(); - - for (int i = 0; i < parameters.Length; i++) - { - sb.Append($"{parameters[i].ParameterType.Name} {parameters[i].Name}"); - - if (i < parameters.Length - 1) - sb.Append(", "); - } - - sb.AppendLine(")"); - } - - output = sb.ToString(); - } - string GetAccess(FieldInfo field) - { - if (field.IsPublic) return "public"; - if (field.IsPrivate) return "private"; - if (field.IsFamily) return "protected"; - if (field.IsAssembly) return "internal"; - return ""; - } - string GetAccess(MethodInfo method) - { - if (method.IsPublic) return "public"; - if (method.IsPrivate) return "private"; - if (method.IsFamily) return "protected"; - if (method.IsAssembly) return "internal"; - return ""; - } -} diff --git a/Tests/ScriptInspectorWindow.cs.meta b/Tests/ScriptInspectorWindow.cs.meta deleted file mode 100644 index 2b73dff..0000000 --- a/Tests/ScriptInspectorWindow.cs.meta +++ /dev/null @@ -1,2 +0,0 @@ -fileFormatVersion: 2 -guid: b22bcee86d200fc468dcb300ec53b62d \ No newline at end of file diff --git a/Tests/TESTWindow.cs b/Tests/TESTWindow.cs deleted file mode 100644 index bd29791..0000000 --- a/Tests/TESTWindow.cs +++ /dev/null @@ -1,97 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Reflection; -using Unity.VisualScripting; -using UnityEditor; -using UnityEngine; - -public class TESTWindow : EditorWindow -{ - private Vector2 scroll; - private MonoScript script; - private List Info = new List(); - - - - [MenuItem("Tools/RealMethod/TEST")] - public static void Open() - { - GetWindow("TEST"); - } - private void OnEnable() - { - - } - private void OnGUI() - { - if (GUILayout.Button("Refresh")) - { - Info.Clear(); - if (script == null) - return; - - AddInfo("name", script.name); - //AddInfo("text", script.text); - Type Scripttype = script.GetClass(); - AddInfo("Class", Scripttype.ToString()); - AddInfo("ClassName", Scripttype.Name); - AddInfo("FullName", Scripttype.FullName); - AddInfo("Namespace", Scripttype.Namespace); - Type Parenttype = Scripttype.BaseType; - AddInfo("Parent", Parenttype.Name); - AddInfo("IsClass", Scripttype.IsClass.ToString()); - AddInfo("IsAbstact", Scripttype.IsAbstract.ToString()); - AddInfo("IsInterface", Scripttype.IsInterface.ToString()); - AddInfo("IsEnum", Scripttype.IsEnum.ToString()); - AddInfo("IsStruct", Scripttype.IsStruct().ToString()); - AddInfo("IsSealed", Scripttype.IsSealed.ToString()); - Type[] Scriptinterfaces = Scripttype.GetInterfaces(); - AddInfo("Interfaces", Scriptinterfaces.Length.ToString()); - for (int i = 0; i < Scriptinterfaces.Length; i++) - { - AddInfo($"{i}", Scriptinterfaces[i].Name); - } - FieldInfo[] fields = Scripttype.GetFields(BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.Static); - AddInfo("Fields", fields.Length.ToString()); - for (int i = 0; i < fields.Length; i++) - { - AddInfo($"{i}.{fields[i].Name}", $"{fields[i].FieldType} - public[{fields[i].IsPublic}], private[{fields[i].IsPrivate}], static[{fields[i].IsStatic}] "); - } - PropertyInfo[] properties = Scripttype.GetProperties(BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.Static); - AddInfo("Properties", properties.Length.ToString()); - for (int i = 0; i < properties.Length; i++) - { - AddInfo($"{i}.{properties[i].Name}", $"{properties[i].PropertyType} - Canread[{properties[i].CanRead}], CanWrite[{properties[i].CanWrite}]"); - } - MethodInfo[] methods = Scripttype.GetMethods(BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.Static); - AddInfo("Methods", methods.Length.ToString()); - for (int i = 0; i < methods.Length; i++) - { - AddInfo($"{i}.{methods[i].Name}", $"{methods[i].ReturnType} - public[{methods[i].IsPublic}], virtual[{methods[i].IsVirtual}], static[{methods[i].IsStatic}]"); - } - ConstructorInfo[] constructors = Scripttype.GetConstructors(); - for (int i = 0; i < constructors.Length; i++) - { - AddInfo($"{i}.{constructors[i].Name}", $"Attributes = {constructors[i].Attributes}"); - } - } - - scroll = EditorGUILayout.BeginScrollView(scroll); - - script = (MonoScript)EditorGUILayout.ObjectField("Script", script, typeof(MonoScript), false); - if (Info != null) - { - foreach (var item in Info) - { - EditorGUILayout.LabelField(item); - } - } - EditorGUILayout.EndScrollView(); - } - - private void AddInfo(string Type, string data) - { - Info.Add($"{Type}: {data}"); - } - -} \ No newline at end of file diff --git a/Tests/TESTWindow.cs.meta b/Tests/TESTWindow.cs.meta deleted file mode 100644 index cc0e2f1..0000000 --- a/Tests/TESTWindow.cs.meta +++ /dev/null @@ -1,2 +0,0 @@ -fileFormatVersion: 2 -guid: 6f8cbc3021e49e34c8257f059a685c88 \ No newline at end of file From ab3127ebb38aec18a5e1946b858917cdc8a582da Mon Sep 17 00:00:00 2001 From: Alijimpa Date: Sat, 14 Mar 2026 16:36:03 +0330 Subject: [PATCH 038/204] Add Sorting for Namespace --- Editor/ReadySet/Tools/ClassViewerWindow.cs | 28 ++++++++++++++++++++-- 1 file changed, 26 insertions(+), 2 deletions(-) diff --git a/Editor/ReadySet/Tools/ClassViewerWindow.cs b/Editor/ReadySet/Tools/ClassViewerWindow.cs index ee1194e..f1cc3d7 100644 --- a/Editor/ReadySet/Tools/ClassViewerWindow.cs +++ b/Editor/ReadySet/Tools/ClassViewerWindow.cs @@ -24,7 +24,15 @@ public string Title { if (MyScript != null) { - return MyScript.GetClass().Name; + Type targetclass = MyScript.GetClass(); + if (targetclass != null) + { + return MyScript.GetClass().Name; + } + else + { + return MyScript.name; + } } else { @@ -107,6 +115,10 @@ public void AddChild(MonoScript File) public void Expand() { IsExpand = true; + for (int i = 2; i < MyChilds.Count; i++) + { + MyChilds[i].SortChild(); + } } @@ -213,6 +225,19 @@ private bool TryFindField(string title, out FieldModule module) module = null; return false; } + private void SortChild() + { + int fixedCount = 2; + + var sortablePart = MyChilds.GetRange(fixedCount, MyChilds.Count - fixedCount); + + sortablePart.Sort((a, b) => string.Compare(a.Title, b.Title, StringComparison.OrdinalIgnoreCase)); + + for (int i = 0; i < sortablePart.Count; i++) + { + MyChilds[fixedCount + i] = sortablePart[i]; + } + } private void Print(string message) { Debug.Log($"[{Title}]: {message}"); @@ -277,7 +302,6 @@ private enum FilterType } - private Vector2 scroll; private MonoScript[] ProjectScripts; private FieldModule Root; From 3e4797f60a0eaeba4061231b028c187ed8dcbdc8 Mon Sep 17 00:00:00 2001 From: Alijimpa Date: Mon, 16 Mar 2026 11:05:43 +0330 Subject: [PATCH 039/204] Implement ClassType for Store ClassNameParamter to construct in runtime --- Editor/Core/Definitions/ClassType_Drawer.cs | 106 ++++++++++++++++++ .../Core/Definitions/ClassType_Drawer.cs.meta | 2 + Runtime/Core/Definitions/ClassType.cs | 38 +++++++ Runtime/Core/Definitions/ClassType.cs.meta | 2 + Runtime/ReadySet/Services/SpawanService.cs | 6 +- 5 files changed, 151 insertions(+), 3 deletions(-) create mode 100644 Editor/Core/Definitions/ClassType_Drawer.cs create mode 100644 Editor/Core/Definitions/ClassType_Drawer.cs.meta create mode 100644 Runtime/Core/Definitions/ClassType.cs create mode 100644 Runtime/Core/Definitions/ClassType.cs.meta diff --git a/Editor/Core/Definitions/ClassType_Drawer.cs b/Editor/Core/Definitions/ClassType_Drawer.cs new file mode 100644 index 0000000..9f027f5 --- /dev/null +++ b/Editor/Core/Definitions/ClassType_Drawer.cs @@ -0,0 +1,106 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using UnityEditor; +using UnityEngine; + +namespace RealMethod.Editor +{ + [CustomPropertyDrawer(typeof(ClassType), true)] + public class ClassTypeDrawer : PropertyDrawer + { + private SerializedProperty MyProperty; + private Type TargetType; + private MonoScript[] scripts; + private string[] ClassList; + private int CurrentIndex; + private int NewIndex = -1; + + + public override void OnGUI(Rect position, SerializedProperty property, GUIContent label) + { + MyProperty = property.FindPropertyRelative("ClassName"); + + if (scripts == null) + { + scripts = LoadScripts(); + OnActive(); + } + + if (TargetType == null) + { + EditorGUI.LabelField(position, label.text, "Invalid ClassType"); + return; + } + + NewIndex = EditorGUI.Popup(position, label.text, CurrentIndex, ClassList); + + if (NewIndex != CurrentIndex) + { + MyProperty.stringValue = ClassList[NewIndex]; + CurrentIndex = NewIndex; + } + } + private void OnActive() + { + string TargetClass = GetTargetType().FullName; + TargetType = GetClassType(TargetClass); + + ClassList = AppDomain.CurrentDomain.GetAssemblies() + .SelectMany(a => a.GetTypes()) + .Where(t => TargetType.IsAssignableFrom(t) && !t.IsAbstract) + .Select(t => t.Name) + .OrderBy(n => n) + .ToArray(); + + if (string.IsNullOrEmpty(MyProperty.stringValue)) + { + CurrentIndex = ClassList.FindIndex(TargetClass); + } + else + { + CurrentIndex = ClassList.FindIndex(MyProperty.stringValue); + NewIndex = CurrentIndex; + } + + } + + private Type GetTargetType() + { + if (fieldInfo.FieldType.IsGenericType) + { + return fieldInfo.FieldType.GetGenericArguments()[0]; + } + + return null; + } + private Type GetClassType(string className) + { + foreach (var assembly in AppDomain.CurrentDomain.GetAssemblies()) + { + var type = assembly.GetType(className); + if (type != null) + return type; + } + return null; + } + private MonoScript[] LoadScripts() + { + List scripts = new List(); + + string[] guids = AssetDatabase.FindAssets("t:MonoScript"); + + foreach (string guid in guids) + { + string path = AssetDatabase.GUIDToAssetPath(guid); + MonoScript script = AssetDatabase.LoadAssetAtPath(path); + + scripts.Add(script); + } + + scripts.Sort((a, b) => a.name.CompareTo(b.name)); + + return scripts.ToArray(); + } + } +} \ No newline at end of file diff --git a/Editor/Core/Definitions/ClassType_Drawer.cs.meta b/Editor/Core/Definitions/ClassType_Drawer.cs.meta new file mode 100644 index 0000000..cc5f48b --- /dev/null +++ b/Editor/Core/Definitions/ClassType_Drawer.cs.meta @@ -0,0 +1,2 @@ +fileFormatVersion: 2 +guid: 7d22a982c67c68d4aa07c4bc76bb7282 \ No newline at end of file diff --git a/Runtime/Core/Definitions/ClassType.cs b/Runtime/Core/Definitions/ClassType.cs new file mode 100644 index 0000000..5f3e95b --- /dev/null +++ b/Runtime/Core/Definitions/ClassType.cs @@ -0,0 +1,38 @@ +using System; +using UnityEngine; + +namespace RealMethod +{ + public abstract class ClassType + { + [SerializeField] + protected string ClassName; + + protected Type GetClassType() + { + foreach (var assembly in AppDomain.CurrentDomain.GetAssemblies()) + { + var type = assembly.GetType(ClassName); + if (type != null) + return type; + } + return null; + } + } + + [Serializable] + public class ClassType : ClassType where T : class + { + // Operations + public static implicit operator Type(ClassType classType) + { + return classType.GetClassType(); + } + public static implicit operator ClassType(Type type) + { + return new ClassType { ClassName = type.FullName }; + } + } + + +} \ No newline at end of file diff --git a/Runtime/Core/Definitions/ClassType.cs.meta b/Runtime/Core/Definitions/ClassType.cs.meta new file mode 100644 index 0000000..86f64dd --- /dev/null +++ b/Runtime/Core/Definitions/ClassType.cs.meta @@ -0,0 +1,2 @@ +fileFormatVersion: 2 +guid: 6b2ce29e49455754b96688c6d4125d68 \ No newline at end of file diff --git a/Runtime/ReadySet/Services/SpawanService.cs b/Runtime/ReadySet/Services/SpawanService.cs index 308cdf1..a7d215b 100644 --- a/Runtime/ReadySet/Services/SpawanService.cs +++ b/Runtime/ReadySet/Services/SpawanService.cs @@ -41,7 +41,7 @@ protected override void OnStart(object Author) { GameDespawn = new Despawn(); } - protected override void OnWorldChanging(World Previous , World New) + protected override void OnWorldChanging(World Previous, World New) { } protected override void OnEnd(object Author) @@ -660,9 +660,9 @@ public static T Component(GameObject target, Object spawner = null) where T : } } - public static T Class() where T : Object, new() + public static T Class(System.Type classType) { - return new T(); + return (T)System.Activator.CreateInstance(classType); } // Realmethod From f8525ff67e2da307cb28829c198df9494550d4e0 Mon Sep 17 00:00:00 2001 From: Alijimpa Date: Mon, 16 Mar 2026 11:05:52 +0330 Subject: [PATCH 040/204] Fix all Build Error code --- Runtime/Library/Utilities/Gizmos_Library.cs | 2 ++ Tests/Editor.meta | 8 ++++++++ Tests/{Inspector => Editor}/DelegateDisplayEditor.cs | 0 Tests/{Inspector => Editor}/DelegateDisplayEditor.cs.meta | 0 4 files changed, 10 insertions(+) create mode 100644 Tests/Editor.meta rename Tests/{Inspector => Editor}/DelegateDisplayEditor.cs (100%) rename Tests/{Inspector => Editor}/DelegateDisplayEditor.cs.meta (100%) diff --git a/Runtime/Library/Utilities/Gizmos_Library.cs b/Runtime/Library/Utilities/Gizmos_Library.cs index 70ab66f..964809a 100644 --- a/Runtime/Library/Utilities/Gizmos_Library.cs +++ b/Runtime/Library/Utilities/Gizmos_Library.cs @@ -84,6 +84,7 @@ public static void Capsule(Vector3 position, Color color, float height = 2f, flo // Restore previous color Gizmos.color = prevColor; } +#if UNITY_EDITOR // Draw a Text using Gizmos (With Colort) public static void Text(string text, Vector3 position, Color color, FontStyle font = FontStyle.Bold, TextAnchor ancher = TextAnchor.MiddleCenter) { @@ -96,5 +97,6 @@ public static void Text(string text, Vector3 position, Color color, FontStyle fo // Draw the label above the GameObject Handles.Label(position, text, style); } +#endif } } \ No newline at end of file diff --git a/Tests/Editor.meta b/Tests/Editor.meta new file mode 100644 index 0000000..6882fdf --- /dev/null +++ b/Tests/Editor.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 09bd7b0e521680449aa84200b0bd469c +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Tests/Inspector/DelegateDisplayEditor.cs b/Tests/Editor/DelegateDisplayEditor.cs similarity index 100% rename from Tests/Inspector/DelegateDisplayEditor.cs rename to Tests/Editor/DelegateDisplayEditor.cs diff --git a/Tests/Inspector/DelegateDisplayEditor.cs.meta b/Tests/Editor/DelegateDisplayEditor.cs.meta similarity index 100% rename from Tests/Inspector/DelegateDisplayEditor.cs.meta rename to Tests/Editor/DelegateDisplayEditor.cs.meta From ab23bfc3f806175f2110145c97401fea54199c74 Mon Sep 17 00:00:00 2001 From: Alijimpa Date: Mon, 16 Mar 2026 14:24:42 +0330 Subject: [PATCH 041/204] Refine SoftClass --- Editor/Core/Definitions/ClassType_Drawer.cs | 106 ------------------ Editor/Core/Definitions/SoftType_Drawer.cs | 49 ++++++++ ...Drawer.cs.meta => SoftType_Drawer.cs.meta} | 0 Runtime/Core/Definitions/ClassType.cs | 38 ------- Runtime/Core/Definitions/SoftType.cs | 85 ++++++++++++++ .../{ClassType.cs.meta => SoftType.cs.meta} | 0 Runtime/ReadySet/Services/SpawanService.cs | 5 + 7 files changed, 139 insertions(+), 144 deletions(-) delete mode 100644 Editor/Core/Definitions/ClassType_Drawer.cs create mode 100644 Editor/Core/Definitions/SoftType_Drawer.cs rename Editor/Core/Definitions/{ClassType_Drawer.cs.meta => SoftType_Drawer.cs.meta} (100%) delete mode 100644 Runtime/Core/Definitions/ClassType.cs create mode 100644 Runtime/Core/Definitions/SoftType.cs rename Runtime/Core/Definitions/{ClassType.cs.meta => SoftType.cs.meta} (100%) diff --git a/Editor/Core/Definitions/ClassType_Drawer.cs b/Editor/Core/Definitions/ClassType_Drawer.cs deleted file mode 100644 index 9f027f5..0000000 --- a/Editor/Core/Definitions/ClassType_Drawer.cs +++ /dev/null @@ -1,106 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using UnityEditor; -using UnityEngine; - -namespace RealMethod.Editor -{ - [CustomPropertyDrawer(typeof(ClassType), true)] - public class ClassTypeDrawer : PropertyDrawer - { - private SerializedProperty MyProperty; - private Type TargetType; - private MonoScript[] scripts; - private string[] ClassList; - private int CurrentIndex; - private int NewIndex = -1; - - - public override void OnGUI(Rect position, SerializedProperty property, GUIContent label) - { - MyProperty = property.FindPropertyRelative("ClassName"); - - if (scripts == null) - { - scripts = LoadScripts(); - OnActive(); - } - - if (TargetType == null) - { - EditorGUI.LabelField(position, label.text, "Invalid ClassType"); - return; - } - - NewIndex = EditorGUI.Popup(position, label.text, CurrentIndex, ClassList); - - if (NewIndex != CurrentIndex) - { - MyProperty.stringValue = ClassList[NewIndex]; - CurrentIndex = NewIndex; - } - } - private void OnActive() - { - string TargetClass = GetTargetType().FullName; - TargetType = GetClassType(TargetClass); - - ClassList = AppDomain.CurrentDomain.GetAssemblies() - .SelectMany(a => a.GetTypes()) - .Where(t => TargetType.IsAssignableFrom(t) && !t.IsAbstract) - .Select(t => t.Name) - .OrderBy(n => n) - .ToArray(); - - if (string.IsNullOrEmpty(MyProperty.stringValue)) - { - CurrentIndex = ClassList.FindIndex(TargetClass); - } - else - { - CurrentIndex = ClassList.FindIndex(MyProperty.stringValue); - NewIndex = CurrentIndex; - } - - } - - private Type GetTargetType() - { - if (fieldInfo.FieldType.IsGenericType) - { - return fieldInfo.FieldType.GetGenericArguments()[0]; - } - - return null; - } - private Type GetClassType(string className) - { - foreach (var assembly in AppDomain.CurrentDomain.GetAssemblies()) - { - var type = assembly.GetType(className); - if (type != null) - return type; - } - return null; - } - private MonoScript[] LoadScripts() - { - List scripts = new List(); - - string[] guids = AssetDatabase.FindAssets("t:MonoScript"); - - foreach (string guid in guids) - { - string path = AssetDatabase.GUIDToAssetPath(guid); - MonoScript script = AssetDatabase.LoadAssetAtPath(path); - - scripts.Add(script); - } - - scripts.Sort((a, b) => a.name.CompareTo(b.name)); - - return scripts.ToArray(); - } - } -} \ No newline at end of file diff --git a/Editor/Core/Definitions/SoftType_Drawer.cs b/Editor/Core/Definitions/SoftType_Drawer.cs new file mode 100644 index 0000000..2cf7693 --- /dev/null +++ b/Editor/Core/Definitions/SoftType_Drawer.cs @@ -0,0 +1,49 @@ +using System; +using System.Linq; +using UnityEditor; +using UnityEngine; + +namespace RealMethod.Editor +{ + [CustomPropertyDrawer(typeof(SoftType), true)] + public class SoftTypeDrawer : PropertyDrawer + { + private string[] displayNames; + private string[] typeNames; + private int currentIndex; + + public override void OnGUI(Rect position, SerializedProperty property, GUIContent label) + { + var typeProp = property.FindPropertyRelative("typeName"); + + if (displayNames == null) + Initialize(typeProp); + + int newIndex = EditorGUI.Popup(position, label.text, currentIndex, displayNames); + + if (newIndex != currentIndex) + { + currentIndex = newIndex; + typeProp.stringValue = typeNames[newIndex]; + } + } + + private void Initialize(SerializedProperty property) + { + var baseType = fieldInfo.FieldType.GetGenericArguments()[0]; + + var types = AppDomain.CurrentDomain.GetAssemblies() + .SelectMany(a => a.GetTypes()) + .Where(t => baseType.IsAssignableFrom(t) && !t.IsAbstract) + .OrderBy(t => t.Name) + .ToArray(); + + displayNames = types.Select(t => t.Name).ToArray(); + typeNames = types.Select(t => t.AssemblyQualifiedName).ToArray(); + + currentIndex = Array.IndexOf(typeNames, property.stringValue); + if (currentIndex < 0) currentIndex = 0; + } + } + +} \ No newline at end of file diff --git a/Editor/Core/Definitions/ClassType_Drawer.cs.meta b/Editor/Core/Definitions/SoftType_Drawer.cs.meta similarity index 100% rename from Editor/Core/Definitions/ClassType_Drawer.cs.meta rename to Editor/Core/Definitions/SoftType_Drawer.cs.meta diff --git a/Runtime/Core/Definitions/ClassType.cs b/Runtime/Core/Definitions/ClassType.cs deleted file mode 100644 index 5f3e95b..0000000 --- a/Runtime/Core/Definitions/ClassType.cs +++ /dev/null @@ -1,38 +0,0 @@ -using System; -using UnityEngine; - -namespace RealMethod -{ - public abstract class ClassType - { - [SerializeField] - protected string ClassName; - - protected Type GetClassType() - { - foreach (var assembly in AppDomain.CurrentDomain.GetAssemblies()) - { - var type = assembly.GetType(ClassName); - if (type != null) - return type; - } - return null; - } - } - - [Serializable] - public class ClassType : ClassType where T : class - { - // Operations - public static implicit operator Type(ClassType classType) - { - return classType.GetClassType(); - } - public static implicit operator ClassType(Type type) - { - return new ClassType { ClassName = type.FullName }; - } - } - - -} \ No newline at end of file diff --git a/Runtime/Core/Definitions/SoftType.cs b/Runtime/Core/Definitions/SoftType.cs new file mode 100644 index 0000000..d1e6782 --- /dev/null +++ b/Runtime/Core/Definitions/SoftType.cs @@ -0,0 +1,85 @@ +using System; +using UnityEngine; + +namespace RealMethod +{ + public abstract class SoftType + { + [SerializeField] + protected string typeName; // => PropertyRelative + public Type Type + { + get => string.IsNullOrEmpty(typeName) ? null : Type.GetType(typeName); + set => typeName = value?.AssemblyQualifiedName; + } + + + + // Operations + public static implicit operator Type(SoftType softType) + { + return softType?.Type; + } + public static bool operator ==(SoftType a, SoftType b) + { + if (ReferenceEquals(a, b)) + return true; + + if (a is null || b is null) + return false; + + return a.typeName == b.typeName; + } + public static bool operator !=(SoftType a, SoftType b) + { + return !(a == b); + } + public static bool operator ==(SoftType a, Type b) + { + if (a is null || b is null) + return false; + + return a.typeName == b.AssemblyQualifiedName; + } + public static bool operator !=(SoftType a, Type b) + { + return !(a == b); + } + public static bool operator ==(Type a, SoftType b) + { + return b == a; + } + public static bool operator !=(Type a, SoftType b) + { + return !(b == a); + } + + // Override Methods + public override bool Equals(object obj) + { + if (obj is SoftType other) + return typeName == other.typeName; + + return false; + } + public override int GetHashCode() + { + return typeName?.GetHashCode() ?? 0; + } + } + + [Serializable] + public class SoftType : SoftType where T : class + { + // Operations + public static implicit operator SoftType(Type type) + { + if (type != null && !typeof(T).IsAssignableFrom(type)) + throw new InvalidCastException($"{type} is not assignable to {typeof(T)}"); + + return new SoftType { typeName = type?.AssemblyQualifiedName }; + } + } + + +} \ No newline at end of file diff --git a/Runtime/Core/Definitions/ClassType.cs.meta b/Runtime/Core/Definitions/SoftType.cs.meta similarity index 100% rename from Runtime/Core/Definitions/ClassType.cs.meta rename to Runtime/Core/Definitions/SoftType.cs.meta diff --git a/Runtime/ReadySet/Services/SpawanService.cs b/Runtime/ReadySet/Services/SpawanService.cs index a7d215b..b255924 100644 --- a/Runtime/ReadySet/Services/SpawanService.cs +++ b/Runtime/ReadySet/Services/SpawanService.cs @@ -662,6 +662,11 @@ public static T Component(GameObject target, Object spawner = null) where T : } public static T Class(System.Type classType) { + if (classType == null) + { + Debug.LogWarning($" {instance}: ClassType is not valid!"); + return default; + } return (T)System.Activator.CreateInstance(classType); } From ec543fce21b0b1ca35694a203193ba8c75e4c0f5 Mon Sep 17 00:00:00 2001 From: Alijimpa Date: Tue, 17 Mar 2026 09:26:22 +0330 Subject: [PATCH 042/204] Make Empty GameConfig --- Runtime/Core/Architecture/GameConfig.cs | 5 ----- Runtime/ReadySet/Essentials/DefaultGameConfig.cs | 6 +----- 2 files changed, 1 insertion(+), 10 deletions(-) diff --git a/Runtime/Core/Architecture/GameConfig.cs b/Runtime/Core/Architecture/GameConfig.cs index 004147c..c349a31 100644 --- a/Runtime/Core/Architecture/GameConfig.cs +++ b/Runtime/Core/Architecture/GameConfig.cs @@ -8,11 +8,6 @@ namespace RealMethod /// public abstract class GameConfig : ConfigAsset { - /// - /// Called when the game is initialized, allowing the configuration - /// to apply settings or perform setup logic. - /// - public abstract void Initialized(); } diff --git a/Runtime/ReadySet/Essentials/DefaultGameConfig.cs b/Runtime/ReadySet/Essentials/DefaultGameConfig.cs index 425372d..26ff554 100644 --- a/Runtime/ReadySet/Essentials/DefaultGameConfig.cs +++ b/Runtime/ReadySet/Essentials/DefaultGameConfig.cs @@ -4,11 +4,6 @@ namespace RealMethod { public sealed class DefaultGameConfig : GameConfig { - public override void Initialized() - { - Debug.Log("DefaultConfig Loaded"); - } - protected override void OnEnable() { if (HasCloneName()) @@ -17,6 +12,7 @@ protected override void OnEnable() Destroy(this); return; } + Debug.Log("DefaultConfig Loaded"); } } } From 737bea689b931fe0d7737bee06319b791b1f8871 Mon Sep 17 00:00:00 2001 From: Alijimpa Date: Tue, 17 Mar 2026 09:26:38 +0330 Subject: [PATCH 043/204] Add Operator for EditorProperty --- .../SharedScripts/Classes/EditorProperty.cs | 52 ++++++++++++++++++- 1 file changed, 50 insertions(+), 2 deletions(-) diff --git a/Editor/Library/SharedScripts/Classes/EditorProperty.cs b/Editor/Library/SharedScripts/Classes/EditorProperty.cs index 22cba31..7bdeb15 100644 --- a/Editor/Library/SharedScripts/Classes/EditorProperty.cs +++ b/Editor/Library/SharedScripts/Classes/EditorProperty.cs @@ -9,10 +9,11 @@ namespace RealMethod.Editor // This class is used to create custom editor properties that can be rendered in the Unity Editor. public abstract class EditorProperty { - protected Object Owner; - public string PropertyName { get; private set; } private ErrorAction PropertyError = null; + public Object Owner { get; private set; } + public string PropertyName { get; private set; } + public EditorProperty(string _Name, Object _Owner) { PropertyName = _Name; @@ -68,6 +69,53 @@ public void SetValue(T NewValue) CurrentValue = NewValue; } + // Operators + public static implicit operator T(EditorProperty property) + { + return property != null ? property.CurrentValue : default; + } + public static bool operator ==(EditorProperty a, EditorProperty b) + { + if (ReferenceEquals(a, b)) + return true; + + if (a is null || b is null) + return false; + + return EqualityComparer.Default.Equals(a.CurrentValue, b.CurrentValue); + } + public static bool operator !=(EditorProperty a, EditorProperty b) + { + return !(a == b); + } + public static bool operator ==(EditorProperty a, T b) + { + if (a is null) + return false; + + return EqualityComparer.Default.Equals(a.CurrentValue, b); + } + public static bool operator !=(EditorProperty a, T b) + { + return !(a == b); + } + + // Overrides + public override bool Equals(object obj) + { + if (obj is EditorProperty other) + return EqualityComparer.Default.Equals(CurrentValue, other.CurrentValue); + + if (obj is T value) + return EqualityComparer.Default.Equals(CurrentValue, value); + + return false; + } + public override int GetHashCode() + { + return CurrentValue?.GetHashCode() ?? 0; + } + } public abstract class EditorPropertyList : EditorProperty { From 8e37722e628b5246526a8e9b6fd5c68b3244755a Mon Sep 17 00:00:00 2001 From: Alijimpa Date: Tue, 17 Mar 2026 20:37:07 +0330 Subject: [PATCH 044/204] Refine EditorProperties class --- ...oad.cs => ConfigAsset_InitializeOnLoad.cs} | 4 +- ...a => ConfigAsset_InitializeOnLoad.cs.meta} | 0 Editor/Core/Definitions/Name16_Drawer.cs | 2 +- .../RealMethod_ProjectSetting.cs | 273 ------------------ .../RealMethod_ProjectSetting.cs.meta | 2 - .../SharedScripts/Classes/EditorProperty.cs | 19 +- .../ReadySet/Tools/AnimatorScriptGenerator.cs | 2 +- Editor/Toolkit/CSVFile/CSVFileEditor.cs | 6 +- Editor/Toolkit/PCG/PCGEditorWindow.cs | 12 +- Editor/Toolkit/TerrainTools/TerrainEditor.cs | 4 +- .../Library/SharedScripts/Structs/TName.cs | 132 --------- 11 files changed, 23 insertions(+), 433 deletions(-) rename Editor/Core/Definitions/{ConfigAsset_Onload.cs => ConfigAsset_InitializeOnLoad.cs} (96%) rename Editor/Core/Definitions/{ConfigAsset_Onload.cs.meta => ConfigAsset_InitializeOnLoad.cs.meta} (100%) delete mode 100644 Editor/Core/ProjectSetting/RealMethod_ProjectSetting.cs delete mode 100644 Editor/Core/ProjectSetting/RealMethod_ProjectSetting.cs.meta diff --git a/Editor/Core/Definitions/ConfigAsset_Onload.cs b/Editor/Core/Definitions/ConfigAsset_InitializeOnLoad.cs similarity index 96% rename from Editor/Core/Definitions/ConfigAsset_Onload.cs rename to Editor/Core/Definitions/ConfigAsset_InitializeOnLoad.cs index d5f4ee2..e991c09 100644 --- a/Editor/Core/Definitions/ConfigAsset_Onload.cs +++ b/Editor/Core/Definitions/ConfigAsset_InitializeOnLoad.cs @@ -7,9 +7,9 @@ namespace RealMethod.Editor { [InitializeOnLoad] - public static class ConfigAsset_Onload + public static class ConfigAsset_InitializeOnLoad { - static ConfigAsset_Onload() + static ConfigAsset_InitializeOnLoad() { EditorApplication.delayCall += ValidateAllConfigs; } diff --git a/Editor/Core/Definitions/ConfigAsset_Onload.cs.meta b/Editor/Core/Definitions/ConfigAsset_InitializeOnLoad.cs.meta similarity index 100% rename from Editor/Core/Definitions/ConfigAsset_Onload.cs.meta rename to Editor/Core/Definitions/ConfigAsset_InitializeOnLoad.cs.meta diff --git a/Editor/Core/Definitions/Name16_Drawer.cs b/Editor/Core/Definitions/Name16_Drawer.cs index aeb2001..7501da2 100644 --- a/Editor/Core/Definitions/Name16_Drawer.cs +++ b/Editor/Core/Definitions/Name16_Drawer.cs @@ -4,7 +4,7 @@ namespace RealMethod.Editor { [CustomPropertyDrawer(typeof(Name16))] - public class Name16Drawer : PropertyDrawer + public class Name16_Drawer : PropertyDrawer { const int MaxLength = 16; static readonly Color Tint = new Color(1f, 0.82f, 0.9f); // very light pink diff --git a/Editor/Core/ProjectSetting/RealMethod_ProjectSetting.cs b/Editor/Core/ProjectSetting/RealMethod_ProjectSetting.cs deleted file mode 100644 index ca68ee7..0000000 --- a/Editor/Core/ProjectSetting/RealMethod_ProjectSetting.cs +++ /dev/null @@ -1,273 +0,0 @@ -using System; -using System.Collections.Generic; -using System.IO; -using System.Linq; -using UnityEditor; -using UnityEngine; - -namespace RealMethod.Editor -{ - // Interface for call base method in ProjectSettingSection by RealMethodSetting - interface ISectionSetting - { - void FirstSelected(ProjectSettingAsset storage); - void Draw(); - bool IsRuntime(); - } - - // Abstract base class for a settings section - public abstract class ProjectSettingSection : ISectionSetting - { - protected enum SectionType - { - Runtime, - Editor, - } - protected class ClassType - { - private List TypeList; - private string[] TypeName; - private int selctedIndex = 0; - private int newIndex; - - public ClassType() - { - // Get all available T types **only once** - TypeList = AppDomain.CurrentDomain.GetAssemblies() - .SelectMany(assembly => assembly.GetTypes()) - .Where(type => typeof(T).IsAssignableFrom(type) && !type.IsAbstract) - .ToList(); - - TypeName = TypeList.Select(t => t.FullName).ToArray(); - } - - public void Draw(SerializedObject projectSettings, string PropertyName, string DisplayName) - { - selctedIndex = System.Array.IndexOf(TypeName, projectSettings.FindProperty(PropertyName).stringValue); - newIndex = EditorGUILayout.Popup(DisplayName, selctedIndex, TypeName); - if (newIndex >= 0 && newIndex < TypeName.Length) - { - projectSettings.FindProperty(PropertyName).stringValue = TypeName[newIndex]; - } - } - } - private bool isReady = true;// Indicates whether the section is ready to render - private string message = string.Empty;// Error message to display if the section is not ready - private int errorid = 0;// Error ID to identify the type of error - - public ProjectSettingSection() - { - Initialized(); - } - - // Implement ISectionSetting Interface - void ISectionSetting.FirstSelected(ProjectSettingAsset storage) - { - BeginRender(storage); - } - void ISectionSetting.Draw() - { - EditorGUILayout.Space(); - EditorGUILayout.LabelField(GetTitle(), EditorStyles.boldLabel); // Section Title - - if (isReady) - { - // Render the section's content - UpdateRender(); - } - else - { - // Display an error message if the section is not ready - EditorGUILayout.HelpBox(message, MessageType.Error); - - // Provide a "Fix" button to resolve the error - if (GUILayout.Button("Fix")) - { - Fix(errorid); - } - } - } - bool ISectionSetting.IsRuntime() - { - return GetSectionType() == SectionType.Runtime; - } - - // Abstract Method - protected abstract void Initialized(); - protected abstract void BeginRender(ProjectSettingAsset Storage); - protected abstract void UpdateRender(); - protected abstract string GetTitle(); - protected abstract SectionType GetSectionType(); - protected abstract void Fix(int Id); - - // Protected Function - protected void Error(string Message, int Id = 0) - { - if (isReady) - { - isReady = false; - } - message = Message; - errorid = Id; - } - protected void ClearError() - { - message = string.Empty; - errorid = 0; - if (!isReady) - { - isReady = true; - } - UpdateRender(); - } - - - } - - // Project Setting - public static class RealMethod_ProjectSetting - { - private static bool candraw = true;// Flag to determine if the UI can be drawn - private static List sections = new List(3) { - // Array of sections to be rendered in the settings UI - new InitializerSetting_Section(), - new FolderStructure_Section() - }; - - - [SettingsProvider] - // Create a SettingsProvider for Unity's Project Settings - public static SettingsProvider CreateSettingsProvider() - { - var provider = new SettingsProvider("Project/RealMethod", SettingsScope.Project) - { - label = "RealMethod", - - // Called when the settings tab is first selected - activateHandler = (searchContext, rootElement) => - { - ProjectSettingAsset TargetStorage = null; - - // Attempt to load the settings asset - if (!GetSettingStorage(out TargetStorage)) - { - if (Directory.Exists(Path.GetDirectoryName(RM_Editor.SetttingAssetPath))) - { - TargetStorage = CreateSettingStorage(); - } - else - { - candraw = false; - } - } - - // Initialize Main section with the loaded settings - ((ISectionSetting)sections[0]).FirstSelected(TargetStorage); - ((ISectionSetting)sections[1]).FirstSelected(TargetStorage); - }, - - - // Called to draw the UI elements - guiHandler = (searchContext) => - { - if (candraw) - { - EditorGUILayout.Space(); - EditorGUILayout.LabelField("Runtime", EditorStyles.whiteBoldLabel); - GUILayout.Box("", GUILayout.ExpandWidth(true), GUILayout.Height(1)); - // Render each section - foreach (var item in sections) - { - ISectionSetting ptovider = item; - if (ptovider.IsRuntime()) - { - ptovider.Draw(); - EditorGUILayout.Space(1); - } - } - EditorGUILayout.Space(); - EditorGUILayout.LabelField("Editor", EditorStyles.whiteBoldLabel); - GUILayout.Box("", GUILayout.ExpandWidth(true), GUILayout.Height(1)); - foreach (var item in sections) - { - ISectionSetting ptovider = item; - if (!ptovider.IsRuntime()) - { - - ptovider.Draw(); - EditorGUILayout.Space(1); - - } - } - } - else - { - EditorGUILayout.HelpBox($"The Address is not valid {Path.GetDirectoryName(RM_Editor.SetttingAssetPath)}", MessageType.Error); - if (GUILayout.Button("Fix")) - { - if (!Directory.Exists("Assets/Resources")) - AssetDatabase.CreateFolder("Assets", "Resources"); - - if (!Directory.Exists("Assets/Resources/RealMethod")) - AssetDatabase.CreateFolder("Assets/Resources", "RealMethod"); - - - ProjectSettingAsset TargetStorage = CreateSettingStorage(); - foreach (var item in sections) - { - ISectionSetting ptovider = item; - if (TargetStorage != null) - ptovider.FirstSelected(TargetStorage); - } - - candraw = true; - } - } - } - }; - - return provider; - } - - - public static bool GetSettingStorage(out ProjectSettingAsset settings) - { - // Attempt to load the settings asset from the specified path - settings = AssetDatabase.LoadAssetAtPath(RM_Editor.SetttingAssetPath); - AddExteraSections(settings); - return settings != null; - } - private static ProjectSettingAsset CreateSettingStorage() - { - // Create a new settings asset at the specified path - ProjectSettingAsset settings = ScriptableObject.CreateInstance(); - AssetDatabase.CreateAsset(settings, RM_Editor.SetttingAssetPath); - AssetDatabase.SaveAssets(); - AddExteraSections(settings); - return settings; - } - private static void AddExteraSections(ProjectSettingAsset settings) - { - Type[] sectiontypes = settings.GetExteraSections(); - foreach (var item in sectiontypes) - { - if (item != null) - { - if (typeof(ProjectSettingSection).IsAssignableFrom(item)) - { - try - { - ProjectSettingSection TargetSection = (ProjectSettingSection)Activator.CreateInstance(item); - ((ISectionSetting)TargetSection).FirstSelected(settings); - sections.Add(TargetSection); - } - catch (Exception ex) - { - Debug.LogError($"Failed to instantiate {item}: {ex.Message}. DefaultGameBridge Created"); - } - } - } - } - } - } -} \ No newline at end of file diff --git a/Editor/Core/ProjectSetting/RealMethod_ProjectSetting.cs.meta b/Editor/Core/ProjectSetting/RealMethod_ProjectSetting.cs.meta deleted file mode 100644 index 1b0be4e..0000000 --- a/Editor/Core/ProjectSetting/RealMethod_ProjectSetting.cs.meta +++ /dev/null @@ -1,2 +0,0 @@ -fileFormatVersion: 2 -guid: 4f212fbc9c566af4a95998bfc9171190 \ No newline at end of file diff --git a/Editor/Library/SharedScripts/Classes/EditorProperty.cs b/Editor/Library/SharedScripts/Classes/EditorProperty.cs index 7bdeb15..6b93eba 100644 --- a/Editor/Library/SharedScripts/Classes/EditorProperty.cs +++ b/Editor/Library/SharedScripts/Classes/EditorProperty.cs @@ -381,9 +381,9 @@ protected override void FixError(int Id) throw new System.NotImplementedException(); } } - public class EP_ScriptableObject : EditorProperty where T : ScriptableObject + public class EP_Asset : EditorProperty where T : PrimitiveAsset { - public EP_ScriptableObject(string Name, Object other) : base(Name, other) + public EP_Asset(string Name, Object other) : base(Name, other) { CurrentValue = null; CashValue = null; @@ -407,9 +407,9 @@ protected override void FixError(int Id) } } - public class EP_Class : EditorProperty where T : class + public class EP_Variable : EditorProperty where T : class { - public EP_Class(string Name, Object other) : base(Name, other) + public EP_Variable(string Name, Object other) : base(Name, other) { } @@ -664,9 +664,9 @@ public List GetList() } /// Sample EP_Storeable - public class EPS_ScriptableObjectList : EP_StoreableList where T : ScriptableObject + public class EPS_AssetList : EP_StoreableList where T : PrimitiveAsset { - public EPS_ScriptableObjectList(UnityEditor.Editor other, string Name) : base(other, Name) + public EPS_AssetList(UnityEditor.Editor other, string Name) : base(other, Name) { } @@ -763,9 +763,6 @@ private string GetTargetPath(T Target) return AssetDatabase.GetAssetPath(Target); } - - - } public class EPS_Enum : EP_Storeable where T : System.Enum { @@ -818,9 +815,9 @@ protected override void FixError(int Id) { } } - public class EPS_ScriptableObject : EP_Storeable where T : ScriptableObject + public class EPS_Asset : EP_Storeable where T : PrimitiveAsset { - public EPS_ScriptableObject(UnityEditor.Editor other, string Name) : base(other, Name) + public EPS_Asset(UnityEditor.Editor other, string Name) : base(other, Name) { } diff --git a/Editor/ReadySet/Tools/AnimatorScriptGenerator.cs b/Editor/ReadySet/Tools/AnimatorScriptGenerator.cs index 9267557..870a084 100644 --- a/Editor/ReadySet/Tools/AnimatorScriptGenerator.cs +++ b/Editor/ReadySet/Tools/AnimatorScriptGenerator.cs @@ -14,7 +14,7 @@ public class AnimatorScriptGenerator public static void GenerateScriptsFromAnimators() { ProjectSettingAsset TargetStorage; - if (RealMethod_ProjectSetting.GetSettingStorage(out TargetStorage)) + if (SettingsProvider.GetSettingStorage(out TargetStorage)) { outputFolder = TargetStorage[ProjectSettingAsset.AssetFormat.Script] + "/General/AnimatorParam"; } diff --git a/Editor/Toolkit/CSVFile/CSVFileEditor.cs b/Editor/Toolkit/CSVFile/CSVFileEditor.cs index c368931..905e4ee 100644 --- a/Editor/Toolkit/CSVFile/CSVFileEditor.cs +++ b/Editor/Toolkit/CSVFile/CSVFileEditor.cs @@ -10,7 +10,7 @@ namespace RealMethod.Editor [CustomEditor(typeof(TextAsset))] public class CSVFileEditor : UnityEditor.Editor { - class CustomList : EPS_ScriptableObjectList where T : ScriptableObject + class CustomList : EPS_AssetList where T : PrimitiveAsset { Color originalColor = GUI.backgroundColor; @@ -52,7 +52,7 @@ enum SheetType private string assetPath; private EPS_Enum ReadStyle; private SheetViewer TabelGUI; - private CustomList ObjectsPart; + private CustomList ObjectsPart; private EPS_Date LastUpdate; private EPS_Enum OnlineSheetType; private EPS_string SheetID; @@ -74,7 +74,7 @@ private void OnEnable() // Load the file content TabelGUI = new SheetViewer(textAsset); ReadStyle = new EPS_Enum(this, "ReadType"); - ObjectsPart = new CustomList(this, "SObjects"); + ObjectsPart = new CustomList(this, "SObjects"); LastUpdate = new EPS_Date(this, "LastUpdate"); SheetID = new EPS_string(this, "SheetID"); OnlineSheetType = new EPS_Enum(this, "SheetType"); diff --git a/Editor/Toolkit/PCG/PCGEditorWindow.cs b/Editor/Toolkit/PCG/PCGEditorWindow.cs index 4b1ebcc..80446ed 100644 --- a/Editor/Toolkit/PCG/PCGEditorWindow.cs +++ b/Editor/Toolkit/PCG/PCGEditorWindow.cs @@ -63,9 +63,9 @@ private enum PCGExportType } // Fields - private EP_ScriptableObject Resurce; - private EP_ScriptableObject Genration; - private EP_ScriptableObject Cash; + private EP_Asset Resurce; + private EP_Asset Genration; + private EP_Asset Cash; private EP_List SelectedData; private EP_String CashAddress; private EP_String PrefabAddress; @@ -102,9 +102,9 @@ private void OnEnable() Debug.LogError("ProjectSettingAsset is missing from Resources folder!"); } - Resurce = new EP_ScriptableObject("Resurce", this); - Genration = new EP_ScriptableObject("Genration", this); - Cash = new EP_ScriptableObject("Cash", this); + Resurce = new EP_Asset("Resurce", this); + Genration = new EP_Asset("Genration", this); + Cash = new EP_Asset("Cash", this); SelectedData = new EP_List("Data", this); CashAddress = new EP_String("Address", this); CashAddress.SetValue(ProjectSetting[ProjectSettingAsset.AssetFormat.ScriptableObject] + "/PCGCashAsset.asset"); diff --git a/Editor/Toolkit/TerrainTools/TerrainEditor.cs b/Editor/Toolkit/TerrainTools/TerrainEditor.cs index ff14667..b7a72fd 100644 --- a/Editor/Toolkit/TerrainTools/TerrainEditor.cs +++ b/Editor/Toolkit/TerrainTools/TerrainEditor.cs @@ -71,7 +71,7 @@ private int GetTreeCount() // If You Remove PCG Kit Just Remove ExportTreeData from this code. public class ExportTreeData : Object { - private EP_ScriptableObject CashFile; + private EP_Asset CashFile; private EP_String CashAddress; private ProjectSettingAsset ProjectSetting; private Terrain OwnerTerrain; @@ -92,7 +92,7 @@ public ExportTreeData(Terrain owner, UnityEditor.Editor editor) return; } - CashFile = new EP_ScriptableObject("Cash", editor); + CashFile = new EP_Asset("Cash", editor); CashAddress = new EP_String("Address", editor); CashAddress.SetValue(ProjectSetting[ProjectSettingAsset.AssetFormat.ScriptableObject] + "/TerrainCash.asset"); } diff --git a/Runtime/Library/SharedScripts/Structs/TName.cs b/Runtime/Library/SharedScripts/Structs/TName.cs index 6fd0301..53ed6d1 100644 --- a/Runtime/Library/SharedScripts/Structs/TName.cs +++ b/Runtime/Library/SharedScripts/Structs/TName.cs @@ -2,12 +2,6 @@ using UnityEngine; using System.Collections.Generic; -#if UNITY_EDITOR -using UnityEditor; -using UnityEditor.Callbacks; -#endif - - namespace RealMethod { @@ -15,7 +9,6 @@ namespace RealMethod /// Lightweight engine-style string identifier. /// Stores only an integer ID while the actual strings live in a global table. /// - [Serializable] public struct TName : IEquatable { /// @@ -25,7 +18,6 @@ public struct TName : IEquatable /// /// Internal identifier referencing the global name table. /// - [SerializeField] private int id; /// /// Stores strings by ID. @@ -39,21 +31,6 @@ public struct TName : IEquatable /// Lock for thread-safe name registration. /// private static readonly object tableLock = new object(); -#if UNITY_EDITOR - private static bool editorInitialized = false; - private static ProjectSettingAsset _settings; - private static ProjectSettingAsset ProjectSettings - { - get - { - if (editorInitialized && _settings == null && !Application.isPlaying) - { - _settings = AssetDatabase.LoadAssetAtPath("Assets/RealMethod/RealMethodSetting.asset"); - } - return _settings; - } - } -#endif /// @@ -67,51 +44,6 @@ public TName(string value) ////////// Static Functions /// - /// Called at runtime during game load projectsetting - /// The projectsetting after load call these function with self refrence - /// - /// ProjectSetting instance loaded at runtime - public static void OnProjectSettingLoaded(ProjectSettingAsset setting) - { - if (setting == null) - { - Debug.LogError("FName Initialize failed: ProjectSettingAsset is null."); - return; - } - - lock (tableLock) - { - idToName.Clear(); - hashToIds.Clear(); - - var names = setting.Names; // assume List Names in the asset - - if (names == null) - return; - - for (int i = 0; i < names.Count; i++) - { - string value = names[i]; - - if (string.IsNullOrEmpty(value)) - continue; - - int id = idToName.Count; - idToName.Add(value); - - int hash = value.GetHashCode(); - - if (!hashToIds.TryGetValue(hash, out var bucket)) - { - bucket = new List(2); - hashToIds.Add(hash, bucket); - } - - bucket.Add(id); - } - } - } - /// /// Returns the ID for a string or creates a new one. /// public static int GetOrCreateId(string value) @@ -147,16 +79,6 @@ public static int GetOrCreateId(string value) idToName.Add(value); bucket.Add(newId); -#if UNITY_EDITOR - if (ProjectSettings != null) - { - ProjectSettings.Names = idToName; - } - else - { - Debug.LogWarning("ProjectSettingAsset'NamesTable can't update, ProjectSettingAsset is not valid!"); - } -#endif return newId; } } @@ -243,60 +165,6 @@ public static implicit operator string(TName name) return a.id != b.id; } - - - -#if UNITY_EDITOR - [InitializeOnLoadMethod] - private static void MarkEditorReady() - { - editorInitialized = true; - _settings = Resources.Load("RealMethod/RealMethodSetting"); - } - [DidReloadScripts] - private static void OnScriptsReloaded() - { - editorInitialized = true; - - if (ProjectSettings == null) - { - Debug.LogWarning("Static NamesTable can't update, ProjectSettingAsset is not valid!"); - return; - } - - lock (tableLock) - { - idToName.Clear(); - hashToIds.Clear(); - - var names = ProjectSettings.Names; // assume List Names in the asset - - if (names == null) - return; - - for (int i = 0; i < names.Count; i++) - { - string value = names[i]; - - if (string.IsNullOrEmpty(value)) - continue; - - int id = idToName.Count; - idToName.Add(value); - - int hash = value.GetHashCode(); - - if (!hashToIds.TryGetValue(hash, out var bucket)) - { - bucket = new List(2); - hashToIds.Add(hash, bucket); - } - - bucket.Add(id); - } - } - } -#endif } } \ No newline at end of file From 3f0c421b8e1db90dc130143491ca1071c5f54e41 Mon Sep 17 00:00:00 2001 From: Alijimpa Date: Thu, 19 Mar 2026 20:24:28 +0330 Subject: [PATCH 045/204] Refine Editor File naming & GamePrefab System --- .../{Game_Editor.cs => GameEditor.cs} | 2 +- ...Game_Editor.cs.meta => GameEditor.cs.meta} | 0 ...er_Tools.cs => WorldExecutionOrderMenu.cs} | 3 +- ...s.meta => WorldExecutionOrderMenu.cs.meta} | 0 ...izeOnLoad.cs => ConfigAssetInitializer.cs} | 4 +- ...cs.meta => ConfigAssetInitializer.cs.meta} | 0 ...DataAsset_Editor.cs => DataAssetEditor.cs} | 2 +- ...Editor.cs.meta => DataAssetEditor.cs.meta} | 0 .../{Name16_Drawer.cs => Name16Drawer.cs} | 2 +- ...16_Drawer.cs.meta => Name16Drawer.cs.meta} | 0 ...efabCore_Drawer.cs => PrefabCoreDrawer.cs} | 0 ...rawer.cs.meta => PrefabCoreDrawer.cs.meta} | 0 .../{SoftType_Drawer.cs => SoftTypeDrawer.cs} | 0 ..._Drawer.cs.meta => SoftTypeDrawer.cs.meta} | 0 .../ProjectSetting/ProjectSettingProvider.cs | 248 ++++++++++++++++++ .../ProjectSettingProvider.cs.meta | 2 + .../Sections/InitializerSetting_Section.cs | 38 ++- .../Editor_Library.cs => Core/RealMethod.cs} | 8 +- .../RealMethod.cs.meta} | 0 .../SharedScripts/Classes/EditorProperty.cs | 98 ++++++- .../Content/RealMethod_ScriptTemplate.cs | 70 ++--- .../ReadySet/Tools/AnimatorScriptGenerator.cs | 2 +- .../Toolkit/Ability/Ability_ScriptTemplate.cs | 6 +- Editor/Toolkit/Actor/Actor_ScriptTemplate.cs | 2 +- .../Inventory/Inventory_ScriptTemplate.cs | 2 +- Editor/Toolkit/PCG/PCG_ScriptTemplate.cs | 2 +- .../Toolkit/Pickup/Pickup_ScriptTemplate.cs | 4 +- Editor/Toolkit/RPG/RPG_ScriptTemplate.cs | 8 +- .../Tutorial/Tutorial_ScriptTemplate.cs | 6 +- .../Toolkit/Upgrade/Upgrade_ScriptTemplate.cs | 4 +- Runtime/Core/Architecture/Game.cs | 121 ++++++--- Runtime/Core/Architecture/GameBridge.cs | 2 +- .../ProjectSetting/ProjectSettingAsset.cs | 126 ++++----- 33 files changed, 581 insertions(+), 181 deletions(-) rename Editor/Core/Architecture/{Game_Editor.cs => GameEditor.cs} (96%) rename Editor/Core/Architecture/{Game_Editor.cs.meta => GameEditor.cs.meta} (100%) rename Editor/Core/Architecture/{WorldExecutionOrder_Tools.cs => WorldExecutionOrderMenu.cs} (95%) rename Editor/Core/Architecture/{WorldExecutionOrder_Tools.cs.meta => WorldExecutionOrderMenu.cs.meta} (100%) rename Editor/Core/Definitions/{ConfigAsset_InitializeOnLoad.cs => ConfigAssetInitializer.cs} (96%) rename Editor/Core/Definitions/{ConfigAsset_InitializeOnLoad.cs.meta => ConfigAssetInitializer.cs.meta} (100%) rename Editor/Core/Definitions/{DataAsset_Editor.cs => DataAssetEditor.cs} (94%) rename Editor/Core/Definitions/{DataAsset_Editor.cs.meta => DataAssetEditor.cs.meta} (100%) rename Editor/Core/Definitions/{Name16_Drawer.cs => Name16Drawer.cs} (96%) rename Editor/Core/Definitions/{Name16_Drawer.cs.meta => Name16Drawer.cs.meta} (100%) rename Editor/Core/Definitions/{PrefabCore_Drawer.cs => PrefabCoreDrawer.cs} (100%) rename Editor/Core/Definitions/{PrefabCore_Drawer.cs.meta => PrefabCoreDrawer.cs.meta} (100%) rename Editor/Core/Definitions/{SoftType_Drawer.cs => SoftTypeDrawer.cs} (100%) rename Editor/Core/Definitions/{SoftType_Drawer.cs.meta => SoftTypeDrawer.cs.meta} (100%) create mode 100644 Editor/Core/ProjectSetting/ProjectSettingProvider.cs create mode 100644 Editor/Core/ProjectSetting/ProjectSettingProvider.cs.meta rename Editor/{Library/Utilities/Editor_Library.cs => Core/RealMethod.cs} (93%) rename Editor/{Library/Utilities/Editor_Library.cs.meta => Core/RealMethod.cs.meta} (100%) diff --git a/Editor/Core/Architecture/Game_Editor.cs b/Editor/Core/Architecture/GameEditor.cs similarity index 96% rename from Editor/Core/Architecture/Game_Editor.cs rename to Editor/Core/Architecture/GameEditor.cs index 221d5ff..c5db306 100644 --- a/Editor/Core/Architecture/Game_Editor.cs +++ b/Editor/Core/Architecture/GameEditor.cs @@ -3,7 +3,7 @@ namespace RealMethod.Editor { [CustomEditor(typeof(Game), true)] - public class Game_Editor : UnityEditor.Editor + public class GameEditor : UnityEditor.Editor { private Game BaseComponent; diff --git a/Editor/Core/Architecture/Game_Editor.cs.meta b/Editor/Core/Architecture/GameEditor.cs.meta similarity index 100% rename from Editor/Core/Architecture/Game_Editor.cs.meta rename to Editor/Core/Architecture/GameEditor.cs.meta diff --git a/Editor/Core/Architecture/WorldExecutionOrder_Tools.cs b/Editor/Core/Architecture/WorldExecutionOrderMenu.cs similarity index 95% rename from Editor/Core/Architecture/WorldExecutionOrder_Tools.cs rename to Editor/Core/Architecture/WorldExecutionOrderMenu.cs index f2b0fb7..c6fafe3 100644 --- a/Editor/Core/Architecture/WorldExecutionOrder_Tools.cs +++ b/Editor/Core/Architecture/WorldExecutionOrderMenu.cs @@ -6,8 +6,7 @@ namespace RealMethod.Editor { - //[InitializeOnLoad] - public static class WorldExecutionOrder_Tools + public static class WorldExecutionOrderMenu { [MenuItem("Tools/RealMethod/Core/ExecutionOrder" , priority = -1001)] static void ApplyExecutionOrder() diff --git a/Editor/Core/Architecture/WorldExecutionOrder_Tools.cs.meta b/Editor/Core/Architecture/WorldExecutionOrderMenu.cs.meta similarity index 100% rename from Editor/Core/Architecture/WorldExecutionOrder_Tools.cs.meta rename to Editor/Core/Architecture/WorldExecutionOrderMenu.cs.meta diff --git a/Editor/Core/Definitions/ConfigAsset_InitializeOnLoad.cs b/Editor/Core/Definitions/ConfigAssetInitializer.cs similarity index 96% rename from Editor/Core/Definitions/ConfigAsset_InitializeOnLoad.cs rename to Editor/Core/Definitions/ConfigAssetInitializer.cs index e991c09..967ac64 100644 --- a/Editor/Core/Definitions/ConfigAsset_InitializeOnLoad.cs +++ b/Editor/Core/Definitions/ConfigAssetInitializer.cs @@ -7,9 +7,9 @@ namespace RealMethod.Editor { [InitializeOnLoad] - public static class ConfigAsset_InitializeOnLoad + public static class ConfigAssetInitializer { - static ConfigAsset_InitializeOnLoad() + static ConfigAssetInitializer() { EditorApplication.delayCall += ValidateAllConfigs; } diff --git a/Editor/Core/Definitions/ConfigAsset_InitializeOnLoad.cs.meta b/Editor/Core/Definitions/ConfigAssetInitializer.cs.meta similarity index 100% rename from Editor/Core/Definitions/ConfigAsset_InitializeOnLoad.cs.meta rename to Editor/Core/Definitions/ConfigAssetInitializer.cs.meta diff --git a/Editor/Core/Definitions/DataAsset_Editor.cs b/Editor/Core/Definitions/DataAssetEditor.cs similarity index 94% rename from Editor/Core/Definitions/DataAsset_Editor.cs rename to Editor/Core/Definitions/DataAssetEditor.cs index fc68194..ece664f 100644 --- a/Editor/Core/Definitions/DataAsset_Editor.cs +++ b/Editor/Core/Definitions/DataAssetEditor.cs @@ -3,7 +3,7 @@ namespace RealMethod.Editor { - public class DataAsset_Editor : UnityEditor.Editor + public class DataAssetEditor : UnityEditor.Editor { public static void DrawCompleteScriptableObjectEditor(string name, ref T settings, ref bool foldout, ref UnityEditor.Editor editor) where T : ScriptableObject { diff --git a/Editor/Core/Definitions/DataAsset_Editor.cs.meta b/Editor/Core/Definitions/DataAssetEditor.cs.meta similarity index 100% rename from Editor/Core/Definitions/DataAsset_Editor.cs.meta rename to Editor/Core/Definitions/DataAssetEditor.cs.meta diff --git a/Editor/Core/Definitions/Name16_Drawer.cs b/Editor/Core/Definitions/Name16Drawer.cs similarity index 96% rename from Editor/Core/Definitions/Name16_Drawer.cs rename to Editor/Core/Definitions/Name16Drawer.cs index 7501da2..aeb2001 100644 --- a/Editor/Core/Definitions/Name16_Drawer.cs +++ b/Editor/Core/Definitions/Name16Drawer.cs @@ -4,7 +4,7 @@ namespace RealMethod.Editor { [CustomPropertyDrawer(typeof(Name16))] - public class Name16_Drawer : PropertyDrawer + public class Name16Drawer : PropertyDrawer { const int MaxLength = 16; static readonly Color Tint = new Color(1f, 0.82f, 0.9f); // very light pink diff --git a/Editor/Core/Definitions/Name16_Drawer.cs.meta b/Editor/Core/Definitions/Name16Drawer.cs.meta similarity index 100% rename from Editor/Core/Definitions/Name16_Drawer.cs.meta rename to Editor/Core/Definitions/Name16Drawer.cs.meta diff --git a/Editor/Core/Definitions/PrefabCore_Drawer.cs b/Editor/Core/Definitions/PrefabCoreDrawer.cs similarity index 100% rename from Editor/Core/Definitions/PrefabCore_Drawer.cs rename to Editor/Core/Definitions/PrefabCoreDrawer.cs diff --git a/Editor/Core/Definitions/PrefabCore_Drawer.cs.meta b/Editor/Core/Definitions/PrefabCoreDrawer.cs.meta similarity index 100% rename from Editor/Core/Definitions/PrefabCore_Drawer.cs.meta rename to Editor/Core/Definitions/PrefabCoreDrawer.cs.meta diff --git a/Editor/Core/Definitions/SoftType_Drawer.cs b/Editor/Core/Definitions/SoftTypeDrawer.cs similarity index 100% rename from Editor/Core/Definitions/SoftType_Drawer.cs rename to Editor/Core/Definitions/SoftTypeDrawer.cs diff --git a/Editor/Core/Definitions/SoftType_Drawer.cs.meta b/Editor/Core/Definitions/SoftTypeDrawer.cs.meta similarity index 100% rename from Editor/Core/Definitions/SoftType_Drawer.cs.meta rename to Editor/Core/Definitions/SoftTypeDrawer.cs.meta diff --git a/Editor/Core/ProjectSetting/ProjectSettingProvider.cs b/Editor/Core/ProjectSetting/ProjectSettingProvider.cs new file mode 100644 index 0000000..977a940 --- /dev/null +++ b/Editor/Core/ProjectSetting/ProjectSettingProvider.cs @@ -0,0 +1,248 @@ +using System; +using System.Collections.Generic; +using System.IO; +using System.Linq; +using UnityEditor; +using UnityEngine; + +namespace RealMethod.Editor +{ + // Interface for call base method in ProjectSettingSection by RealMethodSetting + interface ISectionSetting + { + void FirstSelected(ProjectSettingAsset storage); + void Draw(); + bool IsRuntime(); + } + // Abstract base class for a settings section + public abstract class ProjectSettingSection : ISectionSetting + { + protected enum SectionType + { + Runtime, + Editor, + } + protected class TypeSelector + { + private SerializedProperty myProperty; + private string fieldName; + private List typeList; + private string[] displayNames; + private string[] assemblyNames; + private int selectedIndex = 0; + private int newIndex; + + + public TypeSelector(SerializedProperty TargetStringProperty, string displayName) + { + if (TargetStringProperty != null && displayName != string.Empty) + { + myProperty = TargetStringProperty; + fieldName = displayName; + } + else + { + Debug.LogWarning("TypeSelector Can't Create"); + return; + } + + + typeList = AppDomain.CurrentDomain.GetAssemblies() + .SelectMany(a => a.GetTypes()) + .Where(t => typeof(T).IsAssignableFrom(t) && !t.IsAbstract) + .ToList(); + + displayNames = typeList.Select(t => $"{t.Namespace}.{t.Name}").ToArray(); // shown in UI + assemblyNames = typeList.Select(t => t.AssemblyQualifiedName).ToArray(); // stored + } + + public void Draw() + { + selectedIndex = Array.IndexOf(assemblyNames, myProperty.stringValue); + + newIndex = EditorGUILayout.Popup(fieldName, selectedIndex, displayNames); + + if (newIndex >= 0 && newIndex < assemblyNames.Length) + { + myProperty.stringValue = assemblyNames[newIndex]; + } + } + } + + private bool isReady = true;// Indicates whether the section is ready to render + private string message = string.Empty;// Error message to display if the section is not ready + private int errorid = 0;// Error ID to identify the type of error + + public ProjectSettingSection() + { + Initialized(); + } + + // Implement ISectionSetting Interface + void ISectionSetting.FirstSelected(ProjectSettingAsset storage) + { + BeginRender(storage); + } + void ISectionSetting.Draw() + { + EditorGUILayout.Space(); + EditorGUILayout.LabelField($"{GetTitle()} ({GetSectionType()})", EditorStyles.boldLabel); // Section Title + + if (isReady) + { + // Render the section's content + UpdateRender(); + } + else + { + // Display an error message if the section is not ready + EditorGUILayout.HelpBox(message, MessageType.Error); + + // Provide a "Fix" button to resolve the error + if (GUILayout.Button("Fix")) + { + Fix(errorid); + } + } + } + bool ISectionSetting.IsRuntime() + { + return GetSectionType() == SectionType.Runtime; + } + + // Abstract Method + protected abstract void Initialized(); + protected abstract void BeginRender(ProjectSettingAsset Storage); + protected abstract void UpdateRender(); + protected abstract string GetTitle(); + protected abstract SectionType GetSectionType(); + protected abstract void Fix(int Id); + + // Protected Function + protected void Error(string Message, int Id = 0) + { + if (isReady) + { + isReady = false; + } + message = Message; + errorid = Id; + } + protected void ClearError() + { + message = string.Empty; + errorid = 0; + if (!isReady) + { + isReady = true; + } + UpdateRender(); + } + + + } + + + + // Project Setting + public static class ProjectSettingProvider + { + private static bool candraw = true;// Flag to determine if the UI can be drawn + private static List sections = new List(2) { + // Array of sections to be rendered in the settings UI + new InitializerSetting_Section(), + new FolderStructure_Section() + }; + + + [SettingsProvider] + // Create a SettingsProvider for Unity's Project Settings + public static SettingsProvider CreateSettingsProvider() + { + var provider = new SettingsProvider("Project/RealMethod", SettingsScope.Project) + { + label = "RealMethod", + + // Called when the settings tab is first selected + activateHandler = (searchContext, rootElement) => + { + ProjectSettingAsset TargetStorage = null; + + // Attempt to load the settings asset + if (!RealMethod.GetSettingStorage(out TargetStorage)) + { + if (Directory.Exists(Path.GetDirectoryName(RealMethod.SetttingAssetPath))) + { + TargetStorage = CreateSettingStorage(); + } + else + { + candraw = false; + } + } + + // Initialize each section with the loaded settings + foreach (var item in sections) + { + ISectionSetting ptovider = item; + if (TargetStorage != null) + ptovider.FirstSelected(TargetStorage); + } + }, + + + // Called to draw the UI elements + guiHandler = (searchContext) => + { + if (candraw) + { + // Render each section + foreach (var item in sections) + { + ISectionSetting ptovider = item; + ptovider.Draw(); + // Add a separator line + GUILayout.Box("", GUILayout.ExpandWidth(true), GUILayout.Height(1)); + } + } + else + { + EditorGUILayout.HelpBox($"The Address is not valid {Path.GetDirectoryName(RealMethod.SetttingAssetPath)}", MessageType.Error); + if (GUILayout.Button("Fix")) + { + if (!Directory.Exists("Assets/Resources")) + AssetDatabase.CreateFolder("Assets", "Resources"); + + if (!Directory.Exists("Assets/Resources/RealMethod")) + AssetDatabase.CreateFolder("Assets/Resources", "RealMethod"); + + + ProjectSettingAsset TargetStorage = CreateSettingStorage(); + foreach (var item in sections) + { + ISectionSetting ptovider = item; + if (TargetStorage != null) + ptovider.FirstSelected(TargetStorage); + } + + candraw = true; + } + } + } + }; + + return provider; + } + + + + private static ProjectSettingAsset CreateSettingStorage() + { + // Create a new settings asset at the specified path + ProjectSettingAsset settings = ScriptableObject.CreateInstance(); + AssetDatabase.CreateAsset(settings, RealMethod.SetttingAssetPath); + AssetDatabase.SaveAssets(); + return settings; + } + } +} \ No newline at end of file diff --git a/Editor/Core/ProjectSetting/ProjectSettingProvider.cs.meta b/Editor/Core/ProjectSetting/ProjectSettingProvider.cs.meta new file mode 100644 index 0000000..1b0be4e --- /dev/null +++ b/Editor/Core/ProjectSetting/ProjectSettingProvider.cs.meta @@ -0,0 +1,2 @@ +fileFormatVersion: 2 +guid: 4f212fbc9c566af4a95998bfc9171190 \ No newline at end of file diff --git a/Editor/Core/ProjectSetting/Sections/InitializerSetting_Section.cs b/Editor/Core/ProjectSetting/Sections/InitializerSetting_Section.cs index 154bc99..b3e7bb7 100644 --- a/Editor/Core/ProjectSetting/Sections/InitializerSetting_Section.cs +++ b/Editor/Core/ProjectSetting/Sections/InitializerSetting_Section.cs @@ -5,20 +5,29 @@ namespace RealMethod.Editor { public class InitializerSetting_Section : ProjectSettingSection { - private ClassType gameClass; - private ClassType gameBridge; + private TypeSelector gameClass; + private TypeSelector gameBridge; private SerializedObject projectSettings; private ProjectSettingAsset SettingAsset; + protected override string GetTitle() + { + return "Initializer"; + } + protected override SectionType GetSectionType() + { + return SectionType.Runtime; + } protected override void Initialized() { - gameClass = new ClassType(); - gameBridge = new ClassType(); + } protected override void BeginRender(ProjectSettingAsset Storage) { SettingAsset = Storage; projectSettings = new SerializedObject(Storage); + gameClass = new TypeSelector(projectSettings.FindProperty("GameClass"), "Game Class"); + gameBridge = new TypeSelector(projectSettings.FindProperty("GameBridge"), "Game Bridge"); } protected override void UpdateRender() { @@ -27,18 +36,15 @@ protected override void UpdateRender() projectSettings.Update(); // GameInstanceClass - gameClass.Draw(projectSettings, "GameClass", "Game Class"); - + gameClass.Draw(); // GameBridgeClass - gameBridge.Draw(projectSettings, "GameBridge", "Game Bridge"); - + gameBridge.Draw(); // GameSettingAsset EditorGUILayout.PropertyField(projectSettings.FindProperty("GameConfig"), new GUIContent("Game Config")); - //GameInitialPrefabs - EditorGUILayout.PropertyField(projectSettings.FindProperty("GamePrefab_1"), new GUIContent("Game Prefab (1)")); - EditorGUILayout.PropertyField(projectSettings.FindProperty("GamePrefab_2"), new GUIContent("Game Prefab (2)")); - EditorGUILayout.PropertyField(projectSettings.FindProperty("GamePrefab_3"), new GUIContent("Game Prefab (3)")); + EditorGUILayout.PropertyField(projectSettings.FindProperty("GamePrefab_1"), new GUIContent("GameScope (Runtime)")); + EditorGUILayout.PropertyField(projectSettings.FindProperty("GamePrefab_2"), new GUIContent("GameScope (Editor)")); + EditorGUILayout.PropertyField(projectSettings.FindProperty("GamePrefab_3"), new GUIContent("Dedicated Server")); if (GUI.changed) { @@ -50,14 +56,6 @@ protected override void UpdateRender() projectSettings.ApplyModifiedProperties(); } - protected override string GetTitle() - { - return "Initializer"; - } - protected override SectionType GetSectionType() - { - return SectionType.Runtime; - } protected override void Fix(int Id) { throw new System.NotImplementedException(); diff --git a/Editor/Library/Utilities/Editor_Library.cs b/Editor/Core/RealMethod.cs similarity index 93% rename from Editor/Library/Utilities/Editor_Library.cs rename to Editor/Core/RealMethod.cs index 0fed435..43564eb 100644 --- a/Editor/Library/Utilities/Editor_Library.cs +++ b/Editor/Core/RealMethod.cs @@ -4,13 +4,19 @@ namespace RealMethod.Editor { - public static class RM_Editor + public static class RealMethod { public const string SetttingAssetPath = "Assets/Resources/RealMethod/RealMethodSetting.asset"; public static string ScriptTemplatesPath => GetPackagePath("com.mustard.realmethod") + "/Reservoir/ScriptTemplates"; public static string PrefabTemplatePath => GetPackagePath("com.mustard.realmethod") + "/Reservoir/Prefabs"; public static string Documentation => GetPackagePath("com.mustard.realmethod") + "/Documentation/Information"; + public static bool GetSettingStorage(out ProjectSettingAsset settings) + { + // Attempt to load the settings asset from the specified path + settings = AssetDatabase.LoadAssetAtPath(RealMethod.SetttingAssetPath); + return settings != null; + } private static string GetPackagePath(string packageName) { string[] guids = AssetDatabase.FindAssets("package", new[] { "Packages/" + packageName }); diff --git a/Editor/Library/Utilities/Editor_Library.cs.meta b/Editor/Core/RealMethod.cs.meta similarity index 100% rename from Editor/Library/Utilities/Editor_Library.cs.meta rename to Editor/Core/RealMethod.cs.meta diff --git a/Editor/Library/SharedScripts/Classes/EditorProperty.cs b/Editor/Library/SharedScripts/Classes/EditorProperty.cs index 6b93eba..824ef5c 100644 --- a/Editor/Library/SharedScripts/Classes/EditorProperty.cs +++ b/Editor/Library/SharedScripts/Classes/EditorProperty.cs @@ -3,17 +3,39 @@ using System.Collections.Generic; using System.Reflection; + namespace RealMethod.Editor { - // Base EditorProperty Class - // This class is used to create custom editor properties that can be rendered in the Unity Editor. + /// + /// Base class responsible for rendering a property in the Unity Editor + /// and handling potential validation errors with optional fix actions. + /// public abstract class EditorProperty { + /// + /// Holds the current error state for this property. + /// If not null, the property will render an error instead of its normal UI. + /// private ErrorAction PropertyError = null; + + /// + /// The Unity object that owns this property. + /// Usually a MonoBehaviour, ScriptableObject, or other UnityEngine.Object. + /// public Object Owner { get; private set; } + /// + /// Name of the property being rendered. + /// Used for identification and debugging. + /// public string PropertyName { get; private set; } + + /// + /// Creates a new editor property renderer. + /// + /// Name of the property. + /// Object that owns the property. public EditorProperty(string _Name, Object _Owner) { PropertyName = _Name; @@ -25,6 +47,14 @@ public EditorProperty(string _Name, Object _Owner) } } + + /// + /// Renders the property in the inspector. + /// If the property has an error, the error UI is rendered instead. + /// + /// + /// A byte result defined by the implementation (usually used for change flags or state). + /// public byte Render() { if (PropertyError == null) @@ -37,33 +67,88 @@ public byte Render() return 0; } } - + /// + /// Registers an error for this property and provides a fix callback. + /// When an error exists, normal rendering is replaced with an error UI. + /// + /// Error message shown in the inspector. + /// Identifier used to determine which fix action to apply. protected void Error(string message, int id) { PropertyError = new ErrorAction(message, id, FixError); } + + /// + /// Implemented by derived classes to render the property UI. + /// Called only when no error is active. + /// protected abstract byte UpdateRender(); + /// + /// Called when the user activates the fix action from an error message. + /// + /// Identifier of the error that should be fixed. protected abstract void FixError(int Id); } + /// + /// Generic editor property wrapper that stores and manages a value of type . + /// + /// This class extends and adds value storage, + /// comparison operators, and implicit conversion for easier usage in editor code. + /// + /// It is typically used by custom inspector systems to track a property's + /// current value and optionally compare against a cached value to detect changes. + /// + /// Type of the property value. public abstract class EditorProperty : EditorProperty { + /// + /// Returns true if the current value is valid (not null). + /// Mainly useful for reference types. + /// public bool isvalid => CurrentValue != null; + /// + /// Current value of the property. + /// This is the active value used by the editor UI. + /// protected T CurrentValue; + /// + /// Cached value used for change tracking or restoring previous state. + /// (Likely intended as "CacheValue".) + /// protected T CashValue; + /// + /// Creates a new property without assigning a default value. + /// + /// Name of the property. + /// Owner Unity object. public EditorProperty(string Name, Object other) : base(Name, other) { } + /// + /// Creates a new property with a default value. + /// The default is applied to both the current and cached values. + /// + /// Name of the property. + /// Owner Unity object. + /// Initial value assigned to the property. public EditorProperty(string Name, Object other, T DefaultValue) : base(Name, other) { CurrentValue = DefaultValue; CashValue = DefaultValue; } + /// + /// Returns the current value of the property. + /// public T GetValue() { return CurrentValue; } + /// + /// Updates the current value of the property. + /// + /// New value to assign. public void SetValue(T NewValue) { CurrentValue = NewValue; @@ -101,6 +186,10 @@ public static implicit operator T(EditorProperty property) } // Overrides + /// + /// Determines equality between this property and another object. + /// Supports comparison with both EditorProperty<T> and raw values of type T. + /// public override bool Equals(object obj) { if (obj is EditorProperty other) @@ -365,7 +454,7 @@ public EP_Dropdown(string Name, string[] options, Object other) : base(Name, oth protected override byte UpdateRender() { - CashValue = EditorGUILayout.Popup("Ability Effect", CurrentValue, Options); + CashValue = EditorGUILayout.Popup($"{PropertyName}:", CurrentValue, Options); if (CashValue == CurrentValue) { return 0; // No change @@ -572,7 +661,6 @@ protected override void FixError(int Id) } - // Storeable // EditorProperty that can be stored in the MetaData public abstract class EP_Storeable : EditorProperty diff --git a/Editor/ReadySet/Content/RealMethod_ScriptTemplate.cs b/Editor/ReadySet/Content/RealMethod_ScriptTemplate.cs index 6a2d85e..88e285d 100644 --- a/Editor/ReadySet/Content/RealMethod_ScriptTemplate.cs +++ b/Editor/ReadySet/Content/RealMethod_ScriptTemplate.cs @@ -8,64 +8,64 @@ class RealMethodScriptTemplate [MenuItem("Assets/Create/Scripting/RealMethod/Essential/Game", false, 80)] public static void CreateGameClass() { - string Path = RM_Editor.CreateScriptTemplate("GameTemplate.txt", "MyGame.cs"); + string Path = RealMethod.CreateScriptTemplate("GameTemplate.txt", "MyGame.cs"); } [MenuItem("Assets/Create/Scripting/RealMethod/Essential/World", false, 80)] public static void CreateWorld() { - string Path = RM_Editor.CreateScriptTemplate("WorldTemplate.txt", "MyWorld.cs"); + string Path = RealMethod.CreateScriptTemplate("WorldTemplate.txt", "MyWorld.cs"); } [MenuItem("Assets/Create/Scripting/RealMethod/Essential/GameBridge", false, 80)] public static void CreateGameBridgeClass() { - string Path = RM_Editor.CreateScriptTemplate("GameBridgeTemplate.txt", "MyGameBridge.cs"); + string Path = RealMethod.CreateScriptTemplate("GameBridgeTemplate.txt", "MyGameBridge.cs"); } // Managers [MenuItem("Assets/Create/Scripting/RealMethod/Manager/BaseManager", false, 80)] public static void CreateManager() { - string Path = RM_Editor.CreateScriptTemplate("ManagerTemplate.txt", "MyManager.cs"); + string Path = RealMethod.CreateScriptTemplate("ManagerTemplate.txt", "MyManager.cs"); } [MenuItem("Assets/Create/Scripting/RealMethod/Manager/AudioManager", false, 80)] public static void CreateAudioManager() { - string Path = RM_Editor.CreateScriptTemplate("AudioManagerTemplater.txt", "MyAudioManager.cs"); + string Path = RealMethod.CreateScriptTemplate("AudioManagerTemplater.txt", "MyAudioManager.cs"); } [MenuItem("Assets/Create/Scripting/RealMethod/Manager/CompositManager", false, 80)] public static void CreateCompositManager() { - string Path = RM_Editor.CreateScriptTemplate("CompositManagerTemplate.txt", "MyCompositManager.cs"); + string Path = RealMethod.CreateScriptTemplate("CompositManagerTemplate.txt", "MyCompositManager.cs"); } [MenuItem("Assets/Create/Scripting/RealMethod/Manager/DataManager", false, 80)] public static void CreateDataManager() { - string Path = RM_Editor.CreateScriptTemplate("DataManagerTemplate.txt", "MyDataManager.cs"); + string Path = RealMethod.CreateScriptTemplate("DataManagerTemplate.txt", "MyDataManager.cs"); } [MenuItem("Assets/Create/Scripting/RealMethod/Manager/GizmoManager", false, 80)] public static void CreateGizmoManager() { - string Path = RM_Editor.CreateScriptTemplate("GizmoManagerTemplate.txt", "MyGizmoManager.cs"); + string Path = RealMethod.CreateScriptTemplate("GizmoManagerTemplate.txt", "MyGizmoManager.cs"); } [MenuItem("Assets/Create/Scripting/RealMethod/Manager/UIManager", false, 80)] public static void CreateUIManager() { - string Path = RM_Editor.CreateScriptTemplate("UIManagerTemplate.txt", "MyUIManager.cs"); + string Path = RealMethod.CreateScriptTemplate("UIManagerTemplate.txt", "MyUIManager.cs"); } [MenuItem("Assets/Create/Scripting/RealMethod/Manager/MixerManager", false, 80)] public static void CreateMixerManager() { - string Path = RM_Editor.CreateScriptTemplate("MixerManagerTemplate.txt", "MyMixerManager.cs"); + string Path = RealMethod.CreateScriptTemplate("MixerManagerTemplate.txt", "MyMixerManager.cs"); } [MenuItem("Assets/Create/Scripting/RealMethod/Manager/HapticManager", false, 80)] public static void CreateHapticManager() { - string Path = RM_Editor.CreateScriptTemplate("HapticManagerTemplate.txt", "MyHapticManager.cs"); + string Path = RealMethod.CreateScriptTemplate("HapticManagerTemplate.txt", "MyHapticManager.cs"); } [MenuItem("Assets/Create/Scripting/RealMethod/Manager/TickManager", false, 80)] public static void CreateTickManager() { - string Path = RM_Editor.CreateScriptTemplate("TickManagerTemplate.txt", "MyTickManager.cs"); + string Path = RealMethod.CreateScriptTemplate("TickManagerTemplate.txt", "MyTickManager.cs"); } @@ -73,17 +73,17 @@ public static void CreateTickManager() [MenuItem("Assets/Create/Scripting/RealMethod/Service/BaseService", false, 80)] public static void CreateService() { - string Path = RM_Editor.CreateScriptTemplate("ServiceTemplate.txt", "MyServicec.cs"); + string Path = RealMethod.CreateScriptTemplate("ServiceTemplate.txt", "MyServicec.cs"); } [MenuItem("Assets/Create/Scripting/RealMethod/Service/StateService", false, 80)] public static void CreateStateService() { - string Path = RM_Editor.CreateScriptTemplate("StateServiceTemplate.txt", "MyStateService.cs"); + string Path = RealMethod.CreateScriptTemplate("StateServiceTemplate.txt", "MyStateService.cs"); } [MenuItem("Assets/Create/Scripting/RealMethod/Service/RuleService", false, 80)] public static void CreateRuleService() { - string Path = RM_Editor.CreateScriptTemplate("RuleServiceTemplate.txt", "MyRuleService.cs"); + string Path = RealMethod.CreateScriptTemplate("RuleServiceTemplate.txt", "MyRuleService.cs"); } @@ -93,75 +93,75 @@ public static void CreateRuleService() [MenuItem("Assets/Create/Scripting/RealMethod/Asset/Data/BaseData", false, 80)] public static void CreateDataAsset() { - string Path = RM_Editor.CreateScriptTemplate("DataAssetTemplate.txt", "MyDataAsset.cs"); + string Path = RealMethod.CreateScriptTemplate("DataAssetTemplate.txt", "MyDataAsset.cs"); } [MenuItem("Assets/Create/Scripting/RealMethod/Asset/Data/ItemAsset", false, 80)] public static void CreateItemAsset() { - string Path = RM_Editor.CreateScriptTemplate("ItemAssetTemplate.txt", "MyItemAsset.cs"); + string Path = RealMethod.CreateScriptTemplate("ItemAssetTemplate.txt", "MyItemAsset.cs"); } [MenuItem("Assets/Create/Scripting/RealMethod/Asset/Data/TableAsset", false, 80)] public static void CreateTableAsset() { - string Path = RM_Editor.CreateScriptTemplate("TableTemplate.txt", "MyTableAsset.cs"); + string Path = RealMethod.CreateScriptTemplate("TableTemplate.txt", "MyTableAsset.cs"); } [MenuItem("Assets/Create/Scripting/RealMethod/Asset/Data/Task", false, 80)] public static void CreateTaskAsset() { - string Path = RM_Editor.CreateScriptTemplate("TaskAssetTemplate.txt", "MyTaskAsset.cs"); + string Path = RealMethod.CreateScriptTemplate("TaskAssetTemplate.txt", "MyTaskAsset.cs"); } // // Config [MenuItem("Assets/Create/Scripting/RealMethod/Asset/Config/BaseConfig", false, 80)] public static void CreateConfigAsset() { - string Path = RM_Editor.CreateScriptTemplate("ConfigAssetTemplate.txt", "MyConfigAsset.cs"); + string Path = RealMethod.CreateScriptTemplate("ConfigAssetTemplate.txt", "MyConfigAsset.cs"); } [MenuItem("Assets/Create/Scripting/RealMethod/Asset/Config/ItemConfig", false, 80)] public static void CreateItemConfig() { - string Path = RM_Editor.CreateScriptTemplate("ItemConfigTemplate.txt", "MyItemConfig.cs"); + string Path = RealMethod.CreateScriptTemplate("ItemConfigTemplate.txt", "MyItemConfig.cs"); } [MenuItem("Assets/Create/Scripting/RealMethod/Asset/Config/GameConfig", false, 80)] public static void CreateGameConfig() { - string Path = RM_Editor.CreateScriptTemplate("GameConfigTemplate.txt", "MyGameConfig.cs"); + string Path = RealMethod.CreateScriptTemplate("GameConfigTemplate.txt", "MyGameConfig.cs"); } [MenuItem("Assets/Create/Scripting/RealMethod/Asset/Config/HapticConfig", false, 80)] public static void CreateHapticConfig() { - string Path = RM_Editor.CreateScriptTemplate("HapticConfigTemplate.txt", "MyHaptic.cs"); + string Path = RealMethod.CreateScriptTemplate("HapticConfigTemplate.txt", "MyHaptic.cs"); } // // Files [MenuItem("Assets/Create/Scripting/RealMethod/Asset/File/BaseFile", false, 80)] public static void CreateFileAsset() { - string Path = RM_Editor.CreateScriptTemplate("FileAssetTemplate.txt", "MyFileAsset.cs"); + string Path = RealMethod.CreateScriptTemplate("FileAssetTemplate.txt", "MyFileAsset.cs"); } [MenuItem("Assets/Create/Scripting/RealMethod/Asset/File/SaveFile", false, 80)] public static void CreateSaveFile() { - string Path = RM_Editor.CreateScriptTemplate("SaveFileTemplate.txt", "MySaveFile.cs"); + string Path = RealMethod.CreateScriptTemplate("SaveFileTemplate.txt", "MySaveFile.cs"); } [MenuItem("Assets/Create/Scripting/RealMethod/Asset/File/GameSetting", false, 80)] public static void CreateGameSettingFile() { - string Path = RM_Editor.CreateScriptTemplate("GameSettingFileTemplate.txt", "GameSettingFile.cs"); + string Path = RealMethod.CreateScriptTemplate("GameSettingFileTemplate.txt", "GameSettingFile.cs"); } // // Unique [MenuItem("Assets/Create/Scripting/RealMethod/Asset/Unique/BaseUnique", false, 80)] public static void CreateUniqueAsset() { - string Path = RM_Editor.CreateScriptTemplate("UniqueAssetTemplate.txt", "MyFileAsset.cs"); + string Path = RealMethod.CreateScriptTemplate("UniqueAssetTemplate.txt", "MyFileAsset.cs"); } [MenuItem("Assets/Create/Scripting/RealMethod/Asset/Unique/SharedRootAsset", false, 80)] public static void CreateSharedRootAsset() { - string Path = RM_Editor.CreateScriptTemplate("SharedRootAssetTemplate.txt", "MySharedRootAsset.cs"); + string Path = RealMethod.CreateScriptTemplate("SharedRootAssetTemplate.txt", "MySharedRootAsset.cs"); } [MenuItem("Assets/Create/Scripting/RealMethod/Asset/Unique/PoolAsset", false, 80)] public static void CreatePoolAsset() { - string Path = RM_Editor.CreateScriptTemplate("PoolAssetTemplate.txt", "MyPoolAsset.cs"); + string Path = RealMethod.CreateScriptTemplate("PoolAssetTemplate.txt", "MyPoolAsset.cs"); } // General @@ -169,29 +169,29 @@ public static void CreatePoolAsset() [MenuItem("Assets/Create/Scripting/RealMethod/General/UI/Widget", false, 80)] public static void CreateWidget() { - string Path = RM_Editor.CreateScriptTemplate("WidgetTemplate.txt", "MyWidget.cs"); + string Path = RealMethod.CreateScriptTemplate("WidgetTemplate.txt", "MyWidget.cs"); } [MenuItem("Assets/Create/Scripting/RealMethod/General/UI/WidgetToolkit", false, 80)] public static void CreateWidgetToolkit() { - string Path = RM_Editor.CreateScriptTemplate("WidgetToolkitTemplate.txt", "MyWidgetToolkit.cs"); + string Path = RealMethod.CreateScriptTemplate("WidgetToolkitTemplate.txt", "MyWidgetToolkit.cs"); } // // Command [MenuItem("Assets/Create/Scripting/RealMethod/General/Command", false, 80)] public static void CreateCommand() { - string Path = RM_Editor.CreateScriptTemplate("CommandTemplate.txt", "MyCommand.cs"); + string Path = RealMethod.CreateScriptTemplate("CommandTemplate.txt", "MyCommand.cs"); } // // Trigger [MenuItem("Assets/Create/Scripting/RealMethod/General/Trigger/Trigger3D", false, 80)] public static void CreateTrigger3D() { - string Path = RM_Editor.CreateScriptTemplate("Trigger3DTemplate.txt", "MyTrigger.cs"); + string Path = RealMethod.CreateScriptTemplate("Trigger3DTemplate.txt", "MyTrigger.cs"); } [MenuItem("Assets/Create/Scripting/RealMethod/General/Trigger/Trigger2D", false, 80)] public static void CreateTrigger2D() { - string Path = RM_Editor.CreateScriptTemplate("Trigger2DTemplate.txt", "MyTrigger.cs"); + string Path = RealMethod.CreateScriptTemplate("Trigger2DTemplate.txt", "MyTrigger.cs"); } @@ -199,7 +199,7 @@ public static void CreateTrigger2D() [MenuItem("Assets/Create/Scripting/RealMethod/Editor/SettingSection", false, 80)] public static void CreateSettingSection() { - string Path = RM_Editor.CreateScriptTemplate("SettingSectionTemplate.txt", "MySection.cs"); + string Path = RealMethod.CreateScriptTemplate("SettingSectionTemplate.txt", "MySection.cs"); } diff --git a/Editor/ReadySet/Tools/AnimatorScriptGenerator.cs b/Editor/ReadySet/Tools/AnimatorScriptGenerator.cs index 870a084..da0b7d7 100644 --- a/Editor/ReadySet/Tools/AnimatorScriptGenerator.cs +++ b/Editor/ReadySet/Tools/AnimatorScriptGenerator.cs @@ -14,7 +14,7 @@ public class AnimatorScriptGenerator public static void GenerateScriptsFromAnimators() { ProjectSettingAsset TargetStorage; - if (SettingsProvider.GetSettingStorage(out TargetStorage)) + if (RealMethod.GetSettingStorage(out TargetStorage)) { outputFolder = TargetStorage[ProjectSettingAsset.AssetFormat.Script] + "/General/AnimatorParam"; } diff --git a/Editor/Toolkit/Ability/Ability_ScriptTemplate.cs b/Editor/Toolkit/Ability/Ability_ScriptTemplate.cs index d9cb8d5..ded2dba 100644 --- a/Editor/Toolkit/Ability/Ability_ScriptTemplate.cs +++ b/Editor/Toolkit/Ability/Ability_ScriptTemplate.cs @@ -7,17 +7,17 @@ class Ability_ScriptTemplate [MenuItem("Assets/Create/Scripting/RealMethod/Toolkit/Ability/AbilityAsset", false, 80)] public static void CreateAbilityAsset() { - string Path = RM_Editor.CreateScriptTemplate("AbilityAssetTemplate.txt", "MyAbility.cs"); + string Path = RealMethod.CreateScriptTemplate("AbilityAssetTemplate.txt", "MyAbility.cs"); } [MenuItem("Assets/Create/Scripting/RealMethod/Toolkit/Ability/AbilityActionAsset", false, 80)] public static void CreateAbilityAction() { - string Path = RM_Editor.CreateScriptTemplate("AbilityActionAssetTemplate.txt", "MyAbilityAction.cs"); + string Path = RealMethod.CreateScriptTemplate("AbilityActionAssetTemplate.txt", "MyAbilityAction.cs"); } [MenuItem("Assets/Create/Scripting/RealMethod/Toolkit/Ability/Effect", false, 80)] public static void CreateEffect() { - string Path = RM_Editor.CreateScriptTemplate("AbilityEffectTemplate.txt", "MyEffect.cs"); + string Path = RealMethod.CreateScriptTemplate("AbilityEffectTemplate.txt", "MyEffect.cs"); } } } \ No newline at end of file diff --git a/Editor/Toolkit/Actor/Actor_ScriptTemplate.cs b/Editor/Toolkit/Actor/Actor_ScriptTemplate.cs index 120dc11..6aa14f0 100644 --- a/Editor/Toolkit/Actor/Actor_ScriptTemplate.cs +++ b/Editor/Toolkit/Actor/Actor_ScriptTemplate.cs @@ -7,7 +7,7 @@ class Actor_ScriptTemplate [MenuItem("Assets/Create/Scripting/RealMethod/Toolkit/Actor/Act", false, 80)] public static void CreateActCommand() { - string Path = RM_Editor.CreateScriptTemplate("ActTemplate.txt", "MyAct.cs"); + string Path = RealMethod.CreateScriptTemplate("ActTemplate.txt", "MyAct.cs"); } } } \ No newline at end of file diff --git a/Editor/Toolkit/Inventory/Inventory_ScriptTemplate.cs b/Editor/Toolkit/Inventory/Inventory_ScriptTemplate.cs index eb7eebf..0f5d837 100644 --- a/Editor/Toolkit/Inventory/Inventory_ScriptTemplate.cs +++ b/Editor/Toolkit/Inventory/Inventory_ScriptTemplate.cs @@ -7,7 +7,7 @@ class Inventory_ScriptTemplate [MenuItem("Assets/Create/Scripting/RealMethod/Toolkit/Inventory/Item", false, 80)] public static void CreateItem() { - string Path = RM_Editor.CreateScriptTemplate("InventoryItemTemplate.txt", "MyItem.cs"); + string Path = RealMethod.CreateScriptTemplate("InventoryItemTemplate.txt", "MyItem.cs"); } } } \ No newline at end of file diff --git a/Editor/Toolkit/PCG/PCG_ScriptTemplate.cs b/Editor/Toolkit/PCG/PCG_ScriptTemplate.cs index ee20e90..5a23ee4 100644 --- a/Editor/Toolkit/PCG/PCG_ScriptTemplate.cs +++ b/Editor/Toolkit/PCG/PCG_ScriptTemplate.cs @@ -7,7 +7,7 @@ class PCG_ScriptTemplate [MenuItem("Assets/Create/Scripting/RealMethod/Toolkit/PCG/Request", false, 80)] public static void CreatePCGRequest() { - string Path = RM_Editor.CreateScriptTemplate("PCGRequestTamplate.txt", "MyRequest.cs"); + string Path = RealMethod.CreateScriptTemplate("PCGRequestTamplate.txt", "MyRequest.cs"); } } } \ No newline at end of file diff --git a/Editor/Toolkit/Pickup/Pickup_ScriptTemplate.cs b/Editor/Toolkit/Pickup/Pickup_ScriptTemplate.cs index b445ae2..cd06536 100644 --- a/Editor/Toolkit/Pickup/Pickup_ScriptTemplate.cs +++ b/Editor/Toolkit/Pickup/Pickup_ScriptTemplate.cs @@ -7,12 +7,12 @@ class Pickup_ScriptTemplate [MenuItem("Assets/Create/Scripting/RealMethod/Toolkit/Pickup/Pickup3D", false, 80)] public static void CreatePickup3D() { - string Path = RM_Editor.CreateScriptTemplate("Pickup3DTemplate.txt", "MyPickup.cs"); + string Path = RealMethod.CreateScriptTemplate("Pickup3DTemplate.txt", "MyPickup.cs"); } [MenuItem("Assets/Create/Scripting/RealMethod/Toolkit/Pickup/Pickup2D", false, 80)] public static void CreatePickup2D() { - string Path = RM_Editor.CreateScriptTemplate("Pickup2DTemplate.txt", "MyPickup.cs"); + string Path = RealMethod.CreateScriptTemplate("Pickup2DTemplate.txt", "MyPickup.cs"); } } } \ No newline at end of file diff --git a/Editor/Toolkit/RPG/RPG_ScriptTemplate.cs b/Editor/Toolkit/RPG/RPG_ScriptTemplate.cs index 0a1f5c5..6dc3daf 100644 --- a/Editor/Toolkit/RPG/RPG_ScriptTemplate.cs +++ b/Editor/Toolkit/RPG/RPG_ScriptTemplate.cs @@ -7,22 +7,22 @@ class RPG_ScriptTemplate [MenuItem("Assets/Create/Scripting/RealMethod/Toolkit/RPG/StatDefinition", false, 80)] public static void CreateStatDefinition() { - string Path = RM_Editor.CreateScriptTemplate("StatDefinitionTemplate.txt", "StatDefinition.cs"); + string Path = RealMethod.CreateScriptTemplate("StatDefinitionTemplate.txt", "StatDefinition.cs"); } [MenuItem("Assets/Create/Scripting/RealMethod/Toolkit/RPG/StatProfile", false, 80)] public static void CreateStatProfile() { - string Path = RM_Editor.CreateScriptTemplate("StatProfileTemplate.txt", "MyProfile.cs"); + string Path = RealMethod.CreateScriptTemplate("StatProfileTemplate.txt", "MyProfile.cs"); } [MenuItem("Assets/Create/Scripting/RealMethod/Toolkit/RPG/StatBuff", false, 80)] public static void CreateBuffConfig() { - string Path = RM_Editor.CreateScriptTemplate("BuffConfigTemplate.txt", "MyBuff.cs"); + string Path = RealMethod.CreateScriptTemplate("BuffConfigTemplate.txt", "MyBuff.cs"); } [MenuItem("Assets/Create/Scripting/RealMethod/Toolkit/RPG/ResourceData", false, 80)] public static void CreateResourceData() { - string Path = RM_Editor.CreateScriptTemplate("ResourceDataTemplate.txt", "MyResource.cs"); + string Path = RealMethod.CreateScriptTemplate("ResourceDataTemplate.txt", "MyResource.cs"); } } diff --git a/Editor/Toolkit/Tutorial/Tutorial_ScriptTemplate.cs b/Editor/Toolkit/Tutorial/Tutorial_ScriptTemplate.cs index b853459..b6d7095 100644 --- a/Editor/Toolkit/Tutorial/Tutorial_ScriptTemplate.cs +++ b/Editor/Toolkit/Tutorial/Tutorial_ScriptTemplate.cs @@ -7,19 +7,19 @@ class Tutorial_ScriptTemplate [MenuItem("Assets/Create/Scripting/RealMethod/Toolkit/Tutorial/ScreenWidget", false, 80)] public static void CreateTutorialScreen() { - string Path = RM_Editor.CreateScriptTemplate("TutorialScreenTemplate.txt", "MyTutorialScreen.cs"); + string Path = RealMethod.CreateScriptTemplate("TutorialScreenTemplate.txt", "MyTutorialScreen.cs"); } [MenuItem("Assets/Create/Scripting/RealMethod/Toolkit/Tutorial/UIunit", false, 80)] public static void CreateTutorialMessage() { - string Path = RM_Editor.CreateScriptTemplate("TutorialUnitTemplate.txt", "MyTutorialUnit.cs"); + string Path = RealMethod.CreateScriptTemplate("TutorialUnitTemplate.txt", "MyTutorialUnit.cs"); } [MenuItem("Assets/Create/Scripting/RealMethod/Toolkit/Tutorial/Config", false, 80)] public static void CreateTutorialConfig() { - string Path = RM_Editor.CreateScriptTemplate("TutorialConfigTemplate.txt", "MyTutorialConfig.cs"); + string Path = RealMethod.CreateScriptTemplate("TutorialConfigTemplate.txt", "MyTutorialConfig.cs"); } } } \ No newline at end of file diff --git a/Editor/Toolkit/Upgrade/Upgrade_ScriptTemplate.cs b/Editor/Toolkit/Upgrade/Upgrade_ScriptTemplate.cs index 033240b..deb14f9 100644 --- a/Editor/Toolkit/Upgrade/Upgrade_ScriptTemplate.cs +++ b/Editor/Toolkit/Upgrade/Upgrade_ScriptTemplate.cs @@ -7,12 +7,12 @@ class Upgrade_ScriptTemplate [MenuItem("Assets/Create/Scripting/RealMethod/Toolkit/Upgrade/ItemAsset", false, 80)] public static void CreateItem() { - string Path = RM_Editor.CreateScriptTemplate("UpgradeItemTemplate.txt", "MyUpgradeAsset.cs"); + string Path = RealMethod.CreateScriptTemplate("UpgradeItemTemplate.txt", "MyUpgradeAsset.cs"); } [MenuItem("Assets/Create/Scripting/RealMethod/Toolkit/Upgrade/MapConfig", false, 80)] public static void CreateConfig() { - string Path = RM_Editor.CreateScriptTemplate("UpgradeConfigTemplate.txt", "MyUpgradeConfig.cs"); + string Path = RealMethod.CreateScriptTemplate("UpgradeConfigTemplate.txt", "MyUpgradeConfig.cs"); } } } \ No newline at end of file diff --git a/Runtime/Core/Architecture/Game.cs b/Runtime/Core/Architecture/Game.cs index 5abafc9..f8e49be 100644 --- a/Runtime/Core/Architecture/Game.cs +++ b/Runtime/Core/Architecture/Game.cs @@ -138,7 +138,7 @@ public static event Action OnReady /// /// List of runtime-registered instances owned by the game. /// - private List GameServices; + private List Services; @@ -160,31 +160,30 @@ private static void InitializeGame() Quit(); return; } - ProjectSettings.OnLoadedInGame(); // Initiate GameClass - var emptyObject = new GameObject("RealGame"); - Type TargetClass = ProjectSettings.GetGameInstanceType(); + var RealObject = new GameObject("RealMethod"); + Type TargetClass = ProjectSettings.GetGameType(); if (TargetClass == null) { Debug.LogWarning("GameInstanceClass that was empty. DefaultGame Created"); - Instance = emptyObject.AddComponent(); + Instance = RealObject.AddComponent(); } if (typeof(Game).IsAssignableFrom(TargetClass)) { - Instance = (Game)emptyObject.AddComponent(TargetClass); + Instance = (Game)RealObject.AddComponent(TargetClass); } else { Debug.LogWarning($"Component of type {TargetClass} is not assignable from Game. DefaultGame Created"); - Instance = emptyObject.AddComponent(); + Instance = RealObject.AddComponent(); } Instance.OnProjectSeettingLoaded(ref ProjectSettings); Instance.OnGameOpen(); // Create GameBridge - Type targetService = ProjectSettings.GetGameBridgeType(); + Type targetService = ProjectSettings.GetBridgeType(); if (targetService == null) { Debug.LogWarning($"GetGameBridgeType that was empty. DefaultGameBridge Created"); @@ -207,36 +206,87 @@ private static void InitializeGame() Debug.LogWarning($"Type {targetService} is not assignable to Service. DefaultGameBridge Created"); Bridge = new DefaultGameBridge(); } - Instance.GameServices = new List(3); + Instance.Services = new List(3); ((IRelationBridge)Bridge).BindWorldCreated(Instance.Notify_OnWorldInitiate); ((IService)Bridge).Created(Instance); // Set GameConfig - if (ProjectSettings.GetGameConfig() != null) + if (ProjectSettings.GetGameConfigAsset() != null) { - Config = ProjectSettings.GetGameConfig(); + Config = ProjectSettings.GetGameConfigAsset(); } else { Config = ScriptableObject.CreateInstance(); } - Config.Initialized(); // Initiate GamePrefab & Managers - List CashManagers = new List(5); - foreach (var obj in ProjectSettings.GetGamePrefabs()) + HashSet CashManagers = new HashSet(); + + if (ProjectSettings.GetPrefab_1() != null) { - if (obj != null) + GameObject newobj = Instantiate(ProjectSettings.GetPrefab_1()); + newobj.name = "GameScope(Runtime)"; + foreach (var manager in newobj.GetComponents()) { - GameObject newobj = Instantiate(obj); - foreach (var manager in newobj.GetComponents()) + if (!CashManagers.Contains(manager)) { manager.InitiateManager(true); CashManagers.Add(manager); } - DontDestroyOnLoad(newobj); + else + { + Debug.LogError($"You should not use a manager {manager} twice"); + throw new NotImplementedException(); + } + } + newobj.transform.SetParent(RealObject.transform); } +#if UNITY_EDITOR + if (ProjectSettings.GetPrefab_2() != null) + { + GameObject newobj = Instantiate(ProjectSettings.GetPrefab_2()); + newobj.name = "GameScope(Editor)"; + foreach (var manager in newobj.GetComponents()) + { + if (!CashManagers.Contains(manager)) + { + manager.InitiateManager(true); + CashManagers.Add(manager); + } + else + { + Debug.LogError($"You should not use a manager {manager} twice"); + throw new NotImplementedException(); + } + + } + newobj.transform.SetParent(RealObject.transform); + } +#endif +#if UNITY_SERVER + if (ProjectSettings.GetPrefab_3() != null) + { + GameObject newobj = Instantiate(ProjectSettings.GetPrefab_3()); + newobj.name = "GameScope(Server)"; + foreach (var manager in newobj.GetComponents()) + { + if (!CashManagers.Contains(manager)) + { + manager.InitiateManager(true); + CashManagers.Add(manager); + } + else + { + Debug.LogError($"You should not use a manager {manager} twice"); + throw new NotImplementedException(); + } + + } + newobj.transform.SetParent(RealObject.transform); + } +#endif Instance.Managers = CashManagers.ToArray(); // Unload Project Setting @@ -244,7 +294,7 @@ private static void InitializeGame() ProjectSettings = null; // Move Self GameObject to DontDestroy - DontDestroyOnLoad(Instance.gameObject); + DontDestroyOnLoad(RealObject); Application.quitting += Instance.Notify_OnGameQuit; } /// @@ -326,8 +376,15 @@ public static T CastWorld() where T : class /// The newly created service instance, or null if a service of the same type already exists. public static T AddService(object author) where T : Service, new() { + // Check if you game not initialized + if (Instance.Services == null) + { + Debug.LogWarning($"Game doesn't initialized !"); + return null; + } + // Check if a service of this type already exists - if (Instance.GameServices.Any(s => s.GetType() == typeof(T))) + if (Instance.Services.Any(s => s.GetType() == typeof(T))) { Debug.LogWarning($"Service of type {typeof(T).Name} already exists."); return null; @@ -344,7 +401,7 @@ public static T CastWorld() where T : class } } ((IRelationBridge)Bridge).ServiceCreated(newService); - Instance.GameServices.Add(newService); + Instance.Services.Add(newService); return newService; } /// @@ -356,7 +413,7 @@ public static T CastWorld() where T : class /// true if a service was found and removed; otherwise false. public static bool RemoveService(object author) where T : Service { - var service = Instance.GameServices.FirstOrDefault(s => s.GetType() == typeof(T)); + var service = Instance.Services.FirstOrDefault(s => s.GetType() == typeof(T)); if (service != null) { if (Instance.Managers != null) @@ -368,7 +425,7 @@ public static bool RemoveService(object author) where T : Service } ((IRelationBridge)Bridge).ServiceRemoved(service); ((IService)service).Deleted(author); - Instance.GameServices.Remove(service); + Instance.Services.Remove(service); return true; } @@ -382,7 +439,7 @@ public static bool RemoveService(object author) where T : Service /// The service instance of type , or null if not found. public static T GetService() where T : Service { - return Instance.GameServices.OfType().FirstOrDefault(); + return Instance.Services.OfType().FirstOrDefault(); } /// /// Retrieves a service by its concrete . @@ -398,7 +455,7 @@ public static Service GetService(Type type) return null; } - return Instance.GameServices.FirstOrDefault(s => s.GetType() == type); + return Instance.Services.FirstOrDefault(s => s.GetType() == type); } /// /// Attempts to find a service of type . @@ -408,7 +465,7 @@ public static Service GetService(Type type) /// true if the service was found; otherwise false. public static bool TryFindService(out T service) where T : Service { - service = Instance.GameServices.OfType().FirstOrDefault(); + service = Instance.Services.OfType().FirstOrDefault(); return service != null; } /// @@ -417,7 +474,7 @@ public static bool TryFindService(out T service) where T : Service /// Array of service type names. public string[] GetAllServiceNames() { - return GameServices.Select(service => service.GetType().Name).ToArray(); + return Services.Select(service => service.GetType().Name).ToArray(); } /// /// Requests a scene load by build index . @@ -684,7 +741,7 @@ protected virtual bool IsGameLoading() /// The newly initiated world instance. private void Notify_OnWorldInitiate(World NewWorld) { - foreach (var service in GameServices) + foreach (var service in Services) { ((IService)service).ChangeWorld(NewWorld); } @@ -698,12 +755,12 @@ private void Notify_OnGameQuit() { Application.quitting -= Notify_OnGameQuit; ((IRelationBridge)Bridge).UnbindWorldCreated(); - if (GameServices != null) + if (Services != null) { - for (int i = 0; i < GameServices.Count; i++) + for (int i = 0; i < Services.Count; i++) { - ((IService)GameServices[i]).Deleted(this); - GameServices.RemoveAt(i); + ((IService)Services[i]).Deleted(this); + Services.RemoveAt(i); } } ((IService)Bridge).Deleted(this); diff --git a/Runtime/Core/Architecture/GameBridge.cs b/Runtime/Core/Architecture/GameBridge.cs index 84d46a8..fe7a2bc 100644 --- a/Runtime/Core/Architecture/GameBridge.cs +++ b/Runtime/Core/Architecture/GameBridge.cs @@ -142,7 +142,7 @@ void IRelationBridge.UnbindWorldCreated() } void IRelationBridge.ServiceCreated(Service service) { - ServiceEvents.Invoke(service, true); + ServiceEvents?.Invoke(service, true); } void IRelationBridge.ServiceRemoved(Service service) { diff --git a/Runtime/Core/ProjectSetting/ProjectSettingAsset.cs b/Runtime/Core/ProjectSetting/ProjectSettingAsset.cs index 8aa1940..1d5769e 100644 --- a/Runtime/Core/ProjectSetting/ProjectSettingAsset.cs +++ b/Runtime/Core/ProjectSetting/ProjectSettingAsset.cs @@ -51,17 +51,25 @@ public enum FolderStructureType [Header("Initializer")] [SerializeField, ReadOnly] - private string GameClass = "RealMethod.DefultGame"; + public string GameClass = string.Empty; // <-- this name must match [SerializeField, ReadOnly] - private string GameBridge = "RealMethod.DefaultGameBridge"; + private string GameBridge = string.Empty; // <-- this name must match [SerializeField] - private GameConfig GameConfig; + private GameConfig GameConfig; // <-- this name must match [SerializeField] - private GameObject GamePrefab_1; + private GameObject GamePrefab_1; // <-- this name must match +#if UNITY_EDITOR [SerializeField] - private GameObject GamePrefab_2; + private GameObject GamePrefab_2; // <-- this name must match +#endif +#if UNITY_SERVER [SerializeField] - private GameObject GamePrefab_3; + private GameObject GamePrefab_3; // <-- this name must match +#endif + + + + [Header("FolderStructure")] [SerializeField, ReadOnly] private FolderStructureType structureType; @@ -94,69 +102,70 @@ public string this[AssetFormat type] get => GetFolderAddressByType(type).GetFolderPath(this); } - // Public Functions - public void OnLoadedInGame() + // Unity Methods + protected virtual void OnEnable() { - // Initialize base Name store in editor - ///Name16.OnProjectSettingLoaded(this); + if (string.IsNullOrEmpty(GameClass)) + GameClass = typeof(DefultGame).AssemblyQualifiedName; + if (string.IsNullOrEmpty(GameBridge)) + GameBridge = typeof(DefaultGameBridge).AssemblyQualifiedName; } - public Type GetGameInstanceType() + protected virtual void Reset() { - foreach (var assembly in AppDomain.CurrentDomain.GetAssemblies()) - { - var type = assembly.GetType(GameClass); - if (type != null) - return type; - } - return null; + if (string.IsNullOrEmpty(GameClass)) + GameClass = typeof(DefultGame).AssemblyQualifiedName; + if (string.IsNullOrEmpty(GameBridge)) + GameBridge = typeof(DefaultGameBridge).AssemblyQualifiedName; } - public void SetGameInstanceType(Type type) + + + + // Public Functions + public Type GetGameType() { - // Store fully qualified name of the type - if (type != null) - { - GameClass = type.AssemblyQualifiedName; - } - else - { - Debug.LogError("Type is null. Cannot set GameInstanceClass."); - } + return Type.GetType(GameClass); } - public Type GetGameBridgeType() + public Type GetBridgeType() { - foreach (var assembly in AppDomain.CurrentDomain.GetAssemblies()) - { - var type = assembly.GetType(GameBridge); - if (type != null) - return type; - } - return null; + return Type.GetType(GameBridge); } - public void SetGameBridgeType(Type type) + public GameConfig GetGameConfigAsset() { - // Store fully qualified name of the type - if (type != null) - { - GameBridge = type.AssemblyQualifiedName; - } - else - { - Debug.LogError("Type is null. Cannot set GameInstanceClass."); - } - + return GameConfig; } - public GameConfig GetGameConfig() + public GameObject GetPrefab_1() { - return GameConfig; + return GamePrefab_1; } - public GameObject[] GetGamePrefabs() + + + + + + + + + +#if UNITY_EDITOR + public GameObject GetPrefab_2() + { + return GamePrefab_2; + } +#endif + +#if UNITY_SERVER + public GameObject GetPrefab_3() { - return new GameObject[3] { - GamePrefab_1, - GamePrefab_2, - GamePrefab_3, - }; + return GamePrefab_3; } +#endif + + + + + + + public int GetStructureType() { return (int)structureType; @@ -181,13 +190,6 @@ public FolderAddress GetFolderAddressByType(AssetFormat identity) - -#if UNITY_EDITOR - public virtual Type[] GetExteraSections() - { - return null; - } -#endif } From 1bfd6dbd8f8dfe83a7582157b8d00b7d86f82018 Mon Sep 17 00:00:00 2001 From: Alijimpa Date: Mon, 23 Mar 2026 12:54:19 +0330 Subject: [PATCH 046/204] Implement Debug & Print Manager for Loging --- Runtime/Core/Architecture/Game.cs | 152 +++++ Runtime/Library/Interfaces/Draw.cs | 12 + Runtime/Library/Interfaces/Draw.cs.meta | 2 + Runtime/Pattern/Managers/GUIManager.cs | 133 ++++ Runtime/Pattern/Managers/GUIManager.cs.meta | 2 + Runtime/Pattern/Managers/GizmoManager.cs | 61 -- Runtime/Pattern/Managers/GizmoManager.cs.meta | 2 - Runtime/ReadySet/Essentials/DefaultGame.cs | 1 + Runtime/ReadySet/Managers/DebugManager.cs | 144 ++++ .../ReadySet/Managers/DebugManager.cs.meta | 2 + Runtime/ReadySet/Managers/PrintManager.cs | 630 ++++++------------ .../ReadySet/Managers/PrintManager.cs.meta | 2 +- Runtime/ReadySet/Managers/PrintManager2.cs | 461 +++++++++++++ .../ReadySet/Managers/PrintManager2.cs.meta | 2 + Runtime/ReadySet/Services/DebugService.cs | 66 ++ .../ReadySet/Services/DebugService.cs.meta | 2 + Runtime/ReadySet/Services/PrintService.cs | 77 --- .../ReadySet/Services/PrintService.cs.meta | 2 - Runtime/ReadySet/Services/SpawanService.cs | 52 ++ 19 files changed, 1241 insertions(+), 564 deletions(-) create mode 100644 Runtime/Library/Interfaces/Draw.cs create mode 100644 Runtime/Library/Interfaces/Draw.cs.meta create mode 100644 Runtime/Pattern/Managers/GUIManager.cs create mode 100644 Runtime/Pattern/Managers/GUIManager.cs.meta delete mode 100644 Runtime/Pattern/Managers/GizmoManager.cs delete mode 100644 Runtime/Pattern/Managers/GizmoManager.cs.meta create mode 100644 Runtime/ReadySet/Managers/DebugManager.cs create mode 100644 Runtime/ReadySet/Managers/DebugManager.cs.meta create mode 100644 Runtime/ReadySet/Managers/PrintManager2.cs create mode 100644 Runtime/ReadySet/Managers/PrintManager2.cs.meta create mode 100644 Runtime/ReadySet/Services/DebugService.cs create mode 100644 Runtime/ReadySet/Services/DebugService.cs.meta delete mode 100644 Runtime/ReadySet/Services/PrintService.cs delete mode 100644 Runtime/ReadySet/Services/PrintService.cs.meta diff --git a/Runtime/Core/Architecture/Game.cs b/Runtime/Core/Architecture/Game.cs index f8e49be..3dfabb0 100644 --- a/Runtime/Core/Architecture/Game.cs +++ b/Runtime/Core/Architecture/Game.cs @@ -671,6 +671,158 @@ public static void Quit() #endif } + /// + /// Logs a message to the Unity Console. + /// + /// String or object to be converted to string representation for display. + [System.Diagnostics.Conditional("UNITY_EDITOR")] + [System.Diagnostics.Conditional("DEVELOPMENT_BUILD")] + public static void Log(object message) + { + Debug.Log(message); + } + /// + /// Logs a message to the Unity Console. + /// + /// String or object to be converted to string representation for display. + /// Object to which the message applies. + [System.Diagnostics.Conditional("UNITY_EDITOR")] + [System.Diagnostics.Conditional("DEVELOPMENT_BUILD")] + public static void Log(object message, UnityEngine.Object context) + { + Debug.Log(message, context); + } + /// + /// A variant of Debug.Log that logs a warning message to the console. + /// + /// String or object to be converted to string representation for display. + [System.Diagnostics.Conditional("UNITY_EDITOR")] + [System.Diagnostics.Conditional("DEVELOPMENT_BUILD")] + public static void LogWarning(object message) + { + Debug.LogWarning(message); + } + /// + /// A variant of Debug.Log that logs a warning message to the console. + /// + /// String or object to be converted to string representation for display. + /// Object to which the message applies. + [System.Diagnostics.Conditional("UNITY_EDITOR")] + [System.Diagnostics.Conditional("DEVELOPMENT_BUILD")] + public static void LogWarning(object message, UnityEngine.Object context) + { + Debug.LogWarning(message, context); + } + /// + /// A variant of Debug.Log that logs an error message to the console. + /// + /// String or object to be converted to string representation for display. + [System.Diagnostics.Conditional("UNITY_EDITOR")] + [System.Diagnostics.Conditional("DEVELOPMENT_BUILD")] + public static void LogError(object message) + { + Debug.LogError(message); + } + /// + /// A variant of Debug.Log that logs an error message to the console. + /// + /// String or object to be converted to string representation for display. + /// Object to which the message applies. + [System.Diagnostics.Conditional("UNITY_EDITOR")] + [System.Diagnostics.Conditional("DEVELOPMENT_BUILD")] + public static void LogError(object message, UnityEngine.Object context) + { + Debug.LogError(message, context); + } + /// + /// A variant of Debug.Log that logs an error message to the console. + /// + /// Runtime Exception. + [System.Diagnostics.Conditional("UNITY_EDITOR")] + [System.Diagnostics.Conditional("DEVELOPMENT_BUILD")] + public static void LogException(Exception exception) + { + Debug.LogException(exception); + } + /// + /// A variant of Debug.Log that logs an error message to the console. + /// + /// Runtime Exception + /// Object to which the message applies. + [System.Diagnostics.Conditional("UNITY_EDITOR")] + [System.Diagnostics.Conditional("DEVELOPMENT_BUILD")] + public static void LogException(Exception exception, UnityEngine.Object context) + { + Debug.LogException(exception, context); + } + /// + /// Assert a condition and logs an error message to the Unity console on failure. + /// + /// Condition you expect to be true. + [System.Diagnostics.Conditional("UNITY_EDITOR")] + [System.Diagnostics.Conditional("DEVELOPMENT_BUILD")] + public static void Assert(bool condition) + { + Debug.Assert(condition); + } + /// + /// Assert a condition and logs an error message to the Unity console on failure. + /// + /// Condition you expect to be true. + /// String or object to be converted to string representation for display. + [System.Diagnostics.Conditional("UNITY_EDITOR")] + [System.Diagnostics.Conditional("DEVELOPMENT_BUILD")] + public static void Assert(bool condition, object message) + { + Debug.Assert(condition, message); + } + /// + /// Assert a condition and logs an error message to the Unity console on failure. + /// + /// Condition you expect to be true. + /// Object to which the message applies. + [System.Diagnostics.Conditional("UNITY_EDITOR")] + [System.Diagnostics.Conditional("DEVELOPMENT_BUILD")] + public static void Assert(bool condition, UnityEngine.Object context) + { + Debug.Assert(condition, context); + } + /// + /// Assert a condition and logs an error message to the Unity console on failure. + /// + /// Condition you expect to be true. + /// String or object to be converted to string representation for display. + [System.Diagnostics.Conditional("UNITY_EDITOR")] + [System.Diagnostics.Conditional("DEVELOPMENT_BUILD")] + public static void Assert(bool condition, string message) + { + Debug.Assert(condition, message); + } + /// + /// Assert a condition and logs an error message to the Unity console on failure. + /// + /// Condition you expect to be true. + /// String or object to be converted to string representation for display. + /// Object to which the message applies. + [System.Diagnostics.Conditional("UNITY_EDITOR")] + [System.Diagnostics.Conditional("DEVELOPMENT_BUILD")] + public static void Assert(bool condition, object message, UnityEngine.Object context) + { + Debug.Assert(condition, message, context); + } + /// + /// Assert a condition and logs an error message to the Unity console on failure. + /// + /// Condition you expect to be true. + /// String or object to be converted to string representation for display. + /// Object to which the message applies. + [System.Diagnostics.Conditional("UNITY_EDITOR")] + [System.Diagnostics.Conditional("DEVELOPMENT_BUILD")] + public static void Assert(bool condition, string message, UnityEngine.Object context) + { + Debug.Assert(condition, message, context); + } + /// /// Retrieves a manager of type from this game's instantiated managers. diff --git a/Runtime/Library/Interfaces/Draw.cs b/Runtime/Library/Interfaces/Draw.cs new file mode 100644 index 0000000..0aafd73 --- /dev/null +++ b/Runtime/Library/Interfaces/Draw.cs @@ -0,0 +1,12 @@ +using UnityEngine; + +namespace RealMethod +{ + public interface IDraw : IIdentifier + { + bool Start(IGameManager Manager); + bool CanDraw(); + void Draw(Vector2 Pivot, int Index); + void End(); + } +} \ No newline at end of file diff --git a/Runtime/Library/Interfaces/Draw.cs.meta b/Runtime/Library/Interfaces/Draw.cs.meta new file mode 100644 index 0000000..8656040 --- /dev/null +++ b/Runtime/Library/Interfaces/Draw.cs.meta @@ -0,0 +1,2 @@ +fileFormatVersion: 2 +guid: 4dfe7e9297074ca49ab4d715a4a69902 \ No newline at end of file diff --git a/Runtime/Pattern/Managers/GUIManager.cs b/Runtime/Pattern/Managers/GUIManager.cs new file mode 100644 index 0000000..4b9a316 --- /dev/null +++ b/Runtime/Pattern/Managers/GUIManager.cs @@ -0,0 +1,133 @@ +using System.Collections.Generic; +using UnityEngine; + +namespace RealMethod +{ + public abstract class GUIManager : MonoBehaviour, IGameManager + { + [Header("GUI")] + [SerializeField] + protected Vector2 Pivot = new Vector2(10, 10); + + //Implement IGameManager Interface + MonoBehaviour IGameManager.GetManagerClass() + { + return this; + } + + // Abstract Methods + public abstract void InitiateManager(bool AlwaysLoaded); + public abstract void ResolveService(Service service, bool active); + } + public abstract class GUIManager : GUIManager where T : IDraw + { + [SerializeField, ReadOnly] + protected List DrawList = new List(); + public int Count => DrawList.Count; + + // Functions + public virtual void Add(T Drawer) + { + if (Drawer == null) + { + Debug.LogWarning("The Drawer is not valid!"); + return; + } + + if (Drawer.Start(this)) + DrawList.Add(Drawer); + } + public virtual bool Remove(T Drawer) + { + Drawer.End(); + return DrawList.Remove(Drawer); + } + public virtual void Remove(int Index) + { + DrawList[Index].End(); + DrawList.RemoveAt(Index); + } + public virtual T Find(IIdentifier ID) + { + foreach (var Drawer in DrawList) + { + if (Drawer is IIdentifier id) + { + if (id == ID) + { + return Drawer; + } + } + } + return default; + } + public virtual T Find(Name16 Name) + { + foreach (var Drawer in DrawList) + { + if (Drawer.NameID == Name) + { + return Drawer; + } + } + return default; + } + public virtual T Find(int index) + { + return DrawList[index]; + } + public virtual bool TryFind(IIdentifier ID, out IDraw Drawer) + { + foreach (var drawer in DrawList) + { + if (drawer is IIdentifier id) + { + if (id == ID) + { + Drawer = drawer; + return true; + } + } + } + Drawer = null; + return false; + } + public virtual void Clear() + { + DrawList.Clear(); + } + + +#if UNITY_EDITOR || DEVELOPMENT_BUILD + protected virtual void PreDraw() + { + + } + protected virtual void DrawItem(T item, int index) + { + if (item.CanDraw()) + { + item.Draw(Pivot, index); + } + } + protected virtual void PostDraw() + { + + } + private void OnGUI() + { + PreDraw(); + if (DrawList.Count > 0) + { + for (int i = 0; i < DrawList.Count; i++) + { + DrawItem(DrawList[i], i); + } + } + PostDraw(); + } +#endif + + } +} + diff --git a/Runtime/Pattern/Managers/GUIManager.cs.meta b/Runtime/Pattern/Managers/GUIManager.cs.meta new file mode 100644 index 0000000..5d32dae --- /dev/null +++ b/Runtime/Pattern/Managers/GUIManager.cs.meta @@ -0,0 +1,2 @@ +fileFormatVersion: 2 +guid: 2c2e75245a16ce0478cb57487d47a20f \ No newline at end of file diff --git a/Runtime/Pattern/Managers/GizmoManager.cs b/Runtime/Pattern/Managers/GizmoManager.cs deleted file mode 100644 index 95db3f0..0000000 --- a/Runtime/Pattern/Managers/GizmoManager.cs +++ /dev/null @@ -1,61 +0,0 @@ -using UnityEngine; - -namespace RealMethod -{ - public abstract class GizmoManager : MonoBehaviour, IGameManager - { - protected abstract class GUIRenderer - { - public abstract void Start(GizmoManager Manager); - public abstract bool CanRender(); - public abstract void Draw(); - } - - [Header("GUI")] - [SerializeField] private Vector2 defualtposition = new Vector2(10, 10); - public Vector2 DefualtPosition => defualtposition; - - - private GUIRenderer[] RenderBox; - - //IGameManager Interface - MonoBehaviour IGameManager.GetManagerClass() - { - return this; - } - void IGameManager.InitiateManager(bool AlwaysLoaded) - { - if (!AlwaysLoaded) - { - Debug.LogError("You can't use GUIManager in [World] Scope"); - Destroy(this); - } - - RenderBox = GetRenderSlots(); - foreach (var Renderer in RenderBox) - { - Renderer.Start(this); - } - } - - - private void OnGUI() - { - foreach (var Renderer in RenderBox) - { - if (Renderer.CanRender()) - { - Renderer.Draw(); - } - } - } - - - // Abstract Methods - public abstract void ResolveService(Service service, bool active); - protected abstract GUIRenderer[] GetRenderSlots(); - - - } -} - diff --git a/Runtime/Pattern/Managers/GizmoManager.cs.meta b/Runtime/Pattern/Managers/GizmoManager.cs.meta deleted file mode 100644 index 0be36b6..0000000 --- a/Runtime/Pattern/Managers/GizmoManager.cs.meta +++ /dev/null @@ -1,2 +0,0 @@ -fileFormatVersion: 2 -guid: feda61cf5eb1b684fadf7cf1048a24cf \ No newline at end of file diff --git a/Runtime/ReadySet/Essentials/DefaultGame.cs b/Runtime/ReadySet/Essentials/DefaultGame.cs index 59aea0d..497ba5c 100644 --- a/Runtime/ReadySet/Essentials/DefaultGame.cs +++ b/Runtime/ReadySet/Essentials/DefaultGame.cs @@ -16,6 +16,7 @@ protected override void OnGameInitialized() } protected override void OnGameStart() { + AddService(this); Debug.Log("DefultGame Started"); } protected override void OnWorldChanged(World NewWorld) diff --git a/Runtime/ReadySet/Managers/DebugManager.cs b/Runtime/ReadySet/Managers/DebugManager.cs new file mode 100644 index 0000000..0ef0e1b --- /dev/null +++ b/Runtime/ReadySet/Managers/DebugManager.cs @@ -0,0 +1,144 @@ +using System; +using UnityEngine; + +namespace RealMethod +{ + public interface IButton : IIdentifier + { + void Update(string Name, string tooltip = "Empty"); + void Update(Vector2 Offcet); + event Action OnPressed; + } + + [System.Serializable] + public class ButtonData : IDraw, IButton + { + private DebugManager MyOwner; + [SerializeField] + private Name16 MyName; + private Action PressedEvent; + private Vector2 Offcet = Vector2.zero; + + public string Tooltip { get; private set; } + + + public ButtonData(Name16 ButtonName, Action callback) + { + MyName = ButtonName; + PressedEvent = callback; + } + + // Implement IIdentifier Interface + public Name16 NameID => MyName; + // Implement IGUIDrawer Interface + bool IDraw.Start(IGameManager Manager) + { + if (Manager.GetManagerClass() is DebugManager target) + { + MyOwner = target; + return true; + } + else + { + Debug.LogWarning($"LogData can't created the start manager should be {typeof(PrintManager)}"); + return false; + } + } + bool IDraw.CanDraw() + { + return true; + } + void IDraw.Draw(Vector2 Pivot, int Index) + { + if (GUI.Button(new Rect(Pivot.x + Offcet.x, (Pivot.y + Offcet.y) * Index, MyOwner.ButtonSize.x, MyOwner.ButtonSize.y), MyName)) + { + PressedEvent?.Invoke(); + } + + } + void IDraw.End() + { + PressedEvent = null; + } + // Implement IButton Interface + public event Action OnPressed + { + add + { + PressedEvent += value; + } + + remove + { + PressedEvent -= value; + } + } + public void Update(string Name, string tooltip = "Empty") + { + MyName = Name; + Tooltip = tooltip; + } + public void Update(Vector2 offcet) + { + Offcet = offcet; + } + } + + [AddComponentMenu("RealMethod/Manager/DebugManager")] + public class DebugManager : GUIManager + { + [Header("Debug Button")] + public Vector2 ScrollPosition = Vector2.zero; + [SerializeField] + private Vector2 buttonSize = new Vector2(200, 40); + public Vector2 ButtonSize => buttonSize; + [SerializeField] + private float buttonMargin = 20; + + // GUIManager Methods + public override void InitiateManager(bool AlwaysLoaded) + { + Pivot = new Vector2(0, 50); + } + public override void ResolveService(Service service, bool active) + { + } + + + public IButton AddButton(Name16 ButtonName, Action Callback) + { + var Result = new ButtonData(ButtonName, Callback); + ((IDraw)Result).Start(this); + Add(Result); + return Result; + } + public bool Remove(IButton button) + { + var result = Find(button); + ((IDraw)result).End(); + return DrawList.Remove(result); + } + + protected override void PreDraw() + { + base.PreDraw(); + RectOffset padding = GUI.skin.button.padding; + RectOffset margin = GUI.skin.button.margin; + // TODO: The height calculation should be done more correctly. + Rect viewRect = new Rect(0, 0, buttonSize.x, ((buttonSize.y + (padding.vertical + margin.vertical)) * Count) - buttonSize.y); + + ScrollPosition = GUI.BeginScrollView( + position: new Rect(Screen.width - buttonSize.x - buttonMargin, 10, buttonSize.x + buttonMargin, Screen.height - 10), + scrollPosition: ScrollPosition, + viewRect: viewRect, + alwaysShowHorizontal: false, + alwaysShowVertical: false); + } + protected override void PostDraw() + { + base.PostDraw(); + GUI.EndScrollView(); + } + + } +} \ No newline at end of file diff --git a/Runtime/ReadySet/Managers/DebugManager.cs.meta b/Runtime/ReadySet/Managers/DebugManager.cs.meta new file mode 100644 index 0000000..2d4a5ee --- /dev/null +++ b/Runtime/ReadySet/Managers/DebugManager.cs.meta @@ -0,0 +1,2 @@ +fileFormatVersion: 2 +guid: 3e677e1ad037f59428420540627a8706 \ No newline at end of file diff --git a/Runtime/ReadySet/Managers/PrintManager.cs b/Runtime/ReadySet/Managers/PrintManager.cs index cbf5c3f..9ee164d 100644 --- a/Runtime/ReadySet/Managers/PrintManager.cs +++ b/Runtime/ReadySet/Managers/PrintManager.cs @@ -1,429 +1,217 @@ using System; -using System.Collections; using System.Collections.Generic; -using System.Reflection; using UnityEngine; namespace RealMethod { - - [Serializable] - public class LogData - { - public string message; - public float duration; - public float x, y; - public int size; - public Color TextColor; - public LogType messagetype; - public Vector2 position => new Vector2(x, y); - - public LogData(string Message) - { - message = Message; - duration = 2f; - x = -1; - y = -1; - size = 1; - TextColor = Color.black; - messagetype = LogType.Log; - } - - public LogData(string Message, LogType type) - { - message = Message; - duration = 2f; - x = -1; - y = -1; - size = 1; - TextColor = GetColor(type); - messagetype = type; - } - public LogData(string Message, bool Console) - { - message = Message; - duration = 2f; - x = -1; - y = -1; - size = 1; - TextColor = Color.cyan; - messagetype = LogType.Log; - } - - public LogData(string Message, float Duration) - { - message = Message; - duration = Duration; - x = -1; - y = -1; - size = 1; - TextColor = Color.cyan; - messagetype = LogType.Log; - } - public LogData(string Message, float Duration, LogType type) - { - message = Message; - duration = Duration; - x = -1; - y = -1; - size = 1; - TextColor = GetColor(type); - messagetype = type; - } - public LogData(string Message, float Duration, bool Console) - { - message = Message; - duration = Duration; - x = -1; - y = -1; - size = 1; - TextColor = Color.cyan; - messagetype = LogType.Exception; - } - - public LogData(string Message, float Duration, Color TargetColor) - { - message = Message; - duration = Duration; - x = -1; - y = -1; - size = 1; - TextColor = TargetColor; - messagetype = LogType.Log; - } - - public LogData(string Message, Color TargetColor) - { - message = Message; - duration = 2f; - x = -1; - y = -1; - size = 1; - TextColor = TargetColor; - messagetype = LogType.Log; - } - - public LogData(string Message, float Duration, float X, float Y) - { - message = Message; - duration = Duration; - x = X; - y = Y; - size = 1; - TextColor = Color.cyan; - messagetype = LogType.Log; - } - public LogData(string Message, float Duration, float X, float Y, Color TargetColor) - { - message = Message; - duration = Duration; - x = X; - y = Y; - size = 1; - TextColor = TargetColor; - messagetype = LogType.Log; - } - - public LogData(string Message, float X, float Y) - { - message = Message; - duration = 2f; - x = X; - y = Y; - size = 1; - TextColor = Color.cyan; - messagetype = LogType.Log; - } - - public LogData(string Message, float Duration, float X, float Y, int Size) - { - message = Message; - duration = Duration; - x = X; - y = Y; - size = Size; - TextColor = Color.cyan; - messagetype = LogType.Log; - } - - public LogData(string Message, float X, float Y, int Size, bool Console, LogType type) - { - message = Message; - duration = 2f; - x = X; - y = Y; - size = Size > 0 ? Size : 1; - TextColor = Color.cyan; - messagetype = type; - } - - public LogData(string Message, float Duration, float X, float Y, int Size, Color TargetColor) - { - message = Message; - duration = Duration; - x = X; - y = Y; - size = Size > 0 ? Size : 1; - TextColor = TargetColor; - messagetype = LogType.Log; - } - public LogData(string Message, float Duration, float X, float Y, int Size, LogType type) - { - message = Message; - duration = Duration; - x = X; - y = Y; - size = Size > 0 ? Size : 1; - TextColor = GetColor(type); - messagetype = type; - } - - - private Color GetColor(LogType type) - { - switch (type) - { - case LogType.Log: - return Color.cyan; - case LogType.Warning: - return Color.yellow; - case LogType.Error: - return Color.red; - case LogType.Assert: - return Color.black; - case LogType.Exception: - return Color.white; - default: - return Color.blue; - } - } - } - [Serializable] - public class ButtonData - { - [SerializeField] string Name = "Button"; - [SerializeField] string Description = "This is a tooltip for the button"; - - [SerializeField] object TargetObject; - [SerializeField] string MethodName; - bool IsFunctionMethod = false; - [SerializeField] object[] MethodParametr; - - public ButtonData(string name, string description, object targetObject, string methodName, object[] methodParametr) - { - Name = name; - Description = description; - TargetObject = targetObject; - MethodName = methodName; - IsFunctionMethod = true; - MethodParametr = methodParametr; - } - - public ButtonData(string name, string description, object targetObject, string methodName) - { - Name = name; - Description = description; - TargetObject = targetObject; - MethodName = methodName; - } - - public ButtonData(string name, object targetObject, string methodName) - { - Name = name; - TargetObject = targetObject; - MethodName = methodName; - } - - public bool ButtonPressed() - { - bool Result; - if (IsFunctionMethod) - { - Type type = TargetObject.GetType(); - MethodInfo method = type.GetMethod(MethodName, BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance); - - if (method != null) - { - method.Invoke(TargetObject, MethodParametr); - Result = true; - } - else - { - Print.LogWarning("Method " + MethodName + " not found on " + TargetObject); - Result = false; - } - } - else - { - // Get the type of the target object - Type type = TargetObject.GetType(); - - // Find the method with the specified name - MethodInfo method = type.GetMethod(MethodName, BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance); - - if (method != null) - { - // Invoke the method on the target object - method.Invoke(TargetObject, null); - Result = true; - } - else - { - Print.LogWarning("Method " + MethodName + " not found on " + TargetObject); - Result = false; - } - } - - return Result; - } - public string GetName() - { - return Name; - } - public string GetDescription() - { - return Description; - } - - } - - [AddComponentMenu("RealMethod/Manager/PrintManager")] - public sealed class PrintManager : GizmoManager - { - private class LogRender : GUIRenderer - { - private PrintManager MyOWner; - public override void Start(GizmoManager Manager) - { - MyOWner = Manager as PrintManager; - } - public override bool CanRender() - { - return MyOWner.Logs.Count > 0; - } - public override void Draw() - { - for (int i = 0; i < MyOWner.Logs.Count; i++) - { - DrawLog(MyOWner.Logs[i], i); - } - } - - private void DrawLog(LogData log, int index) - { - int w = Screen.width * log.size; - int h = Screen.height * log.size; - float Xpos = log.position.x > 0 ? log.position.x : MyOWner.DefualtPosition.x; - float Ypos = log.position.y > 0 ? log.position.y : MyOWner.DefualtPosition.y + (index * MyOWner.PrintSpace); - - GUIStyle style = new GUIStyle(); - Rect rect = new Rect(Xpos, Ypos, w, h * 2 / 100); - style.alignment = TextAnchor.UpperLeft; - style.fontSize = h * 2 / 100; - style.normal.textColor = log.TextColor; - GUI.Label(rect, log.message, style); - } - } - private class ButtonRender : GUIRenderer - { - private PrintManager MyOWner; - - public override void Start(GizmoManager Manager) - { - MyOWner = Manager as PrintManager; - } - public override bool CanRender() - { - return MyOWner.Buttons.Count > 0; - } - public override void Draw() - { - RectOffset padding = GUI.skin.button.padding; - RectOffset margin = GUI.skin.button.margin; - - // TODO: The height calculation should be done more correctly. - Rect viewRect = new Rect(0, 0, MyOWner.ButtonSize.x, - ((MyOWner.ButtonSize.y + (padding.vertical + margin.vertical)) * MyOWner.Buttons.Count) - MyOWner.ButtonSize.y); - - - MyOWner.ScrollPosition = GUI.BeginScrollView( - position: new Rect(Screen.width - MyOWner.ButtonSize.x - MyOWner.ButtonMargin, 10, MyOWner.ButtonSize.x + MyOWner.ButtonMargin, Screen.height - 10), - scrollPosition: MyOWner.ScrollPosition, - viewRect: viewRect, - alwaysShowHorizontal: false, - alwaysShowVertical: false - ); - - for (int i = 0; i < MyOWner.Buttons.Count; i++) - { - if (GUI.Button(new Rect(0, 50 * i, MyOWner.ButtonSize.x, MyOWner.ButtonSize.y), MyOWner.Buttons[i].GetName())) - { - MyOWner.Buttons[i].ButtonPressed(); - } - } - GUI.EndScrollView(); - } - } - - - [Header("Log")] - public float PrintSpace = 20; - [Header("Button")] - [SerializeField] - private Vector2 ScrollPosition = Vector2.zero; - [SerializeField] - private Vector2 ButtonSize = new Vector2(200, 40); - [SerializeField] - private float ButtonMargin = 20; - [Header("Advance")] - [SerializeField, ReadOnly] - private List Logs = new List(); - [SerializeField, ReadOnly] - private List Buttons = new List(); - - - public override void ResolveService(Service service, bool active) - { - } - protected override GUIRenderer[] GetRenderSlots() - { - return new GUIRenderer[2] { new LogRender(), new ButtonRender() }; - } - - public void Add(LogData Log) - { - if (Log.duration > 0) - { - StartCoroutine(RemoveLog(Log)); - } - Logs.Add(Log); - } - public void Add(ButtonData Button) - { - Buttons.Add(Button); - } - public void Clear() - { - Logs.Clear(); - Buttons.Clear(); - } - - - // Enumerators - private IEnumerator RemoveLog(LogData log) - { - yield return new WaitForSeconds(log.duration); - Logs.Remove(log); - } - - } - - + public interface IPrint : IIdentifier + { + void Update(string Message); + void Update(Color Color); + void Update(Vector2 Offcet); + } + + [Serializable] + public class LogData : IDraw, IPrint + { + private PrintManager MyOwner; + [SerializeField] + private string MyMessage; + private int MySize => MyOwner.PrintSize; + private float StartTime; + private Vector2 Offcet = Vector2.zero; + private Color MyColor = Color.green; + + public bool IsStatic { get; private set; } = false; + [field: SerializeField] + public LogType Type { get; private set; } + public float Duration => IsStatic == false ? GetDuration(Type) : 0; + public bool IsFinished => IsStatic == false ? !(Time.time - StartTime <= Duration) : false; + public Color Color => IsStatic == false ? GetColor(Type) : MyColor; + + public LogData(string Message, LogType Type) + { + MyMessage = Message; + this.Type = Type; + } + public LogData(Vector2 offcet) + { + Offcet = offcet; + IsStatic = true; + } + + // Implement IIdentifier Interface + Name16 IIdentifier.NameID => GetHashCode().ToString(); + // Implement IGUIDrawer Interface + bool IDraw.Start(IGameManager Manager) + { + if (Manager.GetManagerClass() is PrintManager target) + { + MyOwner = target; + StartTime = Time.time; + return true; + } + else + { + Debug.LogWarning($"LogData can't created the start manager should be {typeof(PrintManager)}"); + return false; + } + } + bool IDraw.CanDraw() + { + if (IsStatic) + return true; + return !IsFinished; + } + void IDraw.Draw(Vector2 Pivot, int Index) + { + int w = Screen.width * MySize; + int h = Screen.height * MySize; + float Xpos = Pivot.x + Offcet.x; + float Ypos = Pivot.y + Offcet.y + (Index * MyOwner.PrintSpace); + + GUIStyle style = new GUIStyle(); + Rect rect = new Rect(Xpos, Ypos, w, h * 2 / 100); + style.alignment = TextAnchor.UpperLeft; + style.fontSize = h * 2 / 100; + style.normal.textColor = Color; + GUI.Label(rect, MyMessage, style); + } + void IDraw.End() + { + + } + // Implement IPrint Interface + void IPrint.Update(string message) + { + MyMessage = message; + } + void IPrint.Update(Color color) + { + MyColor = color; + } + void IPrint.Update(Vector2 offcet) + { + Offcet = offcet; + } + + private float GetDuration(LogType type) + { + switch (type) + { + case LogType.Log: + return 3; + case LogType.Warning: + return 5; + case LogType.Error: + return 8; + case LogType.Assert: + return 12; + case LogType.Exception: + return 15; + default: + return 0; + } + } + private Color GetColor(LogType type) + { + switch (type) + { + case LogType.Log: + return Color.cyan; + case LogType.Warning: + return Color.yellow; + case LogType.Error: + return Color.red; + case LogType.Assert: + return Color.white; + case LogType.Exception: + return Color.blue; + default: + return Color.black; + } + } + + + } + + + [AddComponentMenu("RealMethod/Manager/PrintManager")] + public sealed class PrintManager : GUIManager + { + [Header("Printer")] + [SerializeField] + private float printSpace = 20; + public float PrintSpace => printSpace; + [SerializeField] + private int printSize = 1; + public int PrintSize => printSize; + + [SerializeField, ReadOnly] + private List StaticData = new List(10); + + + // GUIManager Methods + public override void InitiateManager(bool AlwaysLoaded) + { + } + public override void ResolveService(Service service, bool active) + { + } + + public void Print(string Message, LogType Type) + { + Add(new LogData(Message, Type)); + } + public IPrint PrintStatic(Vector2 offcet) + { + var Result = new LogData(offcet); + ((IDraw)Result).Start(this); + StaticData.Add(Result); + return Result; + } + public bool RemoveStatic(IPrint ptinter) + { + IIdentifier ID = ptinter; + for (int i = 0; i < StaticData.Count; i++) + { + if (StaticData[i] == ID) + { + ((IDraw)StaticData[i]).End(); + StaticData.RemoveAt(i); + return true; + } + } + return false; + } + public void SetSize(int newSize) + { + printSize = newSize; + } + + protected override void PreDraw() + { + base.PreDraw(); + foreach (var item in StaticData) + { + if (item is IDraw Drawer) + { + Drawer.Draw(Pivot, 0); + } + } + + } + protected override void PostDraw() + { + base.PostDraw(); + for (int i = 0; i < DrawList.Count; i++) + { + if (DrawList[i].IsFinished) + { + DrawList.Remove(DrawList[i]); + } + } + } + } } - - - - - - diff --git a/Runtime/ReadySet/Managers/PrintManager.cs.meta b/Runtime/ReadySet/Managers/PrintManager.cs.meta index 2c40ebd..0be36b6 100644 --- a/Runtime/ReadySet/Managers/PrintManager.cs.meta +++ b/Runtime/ReadySet/Managers/PrintManager.cs.meta @@ -1,2 +1,2 @@ fileFormatVersion: 2 -guid: 9de82d8783153344b91caba717ca0ce4 \ No newline at end of file +guid: feda61cf5eb1b684fadf7cf1048a24cf \ No newline at end of file diff --git a/Runtime/ReadySet/Managers/PrintManager2.cs b/Runtime/ReadySet/Managers/PrintManager2.cs new file mode 100644 index 0000000..4bf0051 --- /dev/null +++ b/Runtime/ReadySet/Managers/PrintManager2.cs @@ -0,0 +1,461 @@ +using System; +using System.Collections; +using System.Collections.Generic; +using System.Reflection; +using UnityEngine; + +namespace RealMethod +{ + + [Serializable] + public class LogData2 + { + public string message; + public float duration; + public float x, y; + public int size; + public Color TextColor; + public LogType messagetype; + public Vector2 position => new Vector2(x, y); + + public LogData2(string Message) + { + message = Message; + duration = 2f; + x = -1; + y = -1; + size = 1; + TextColor = Color.black; + messagetype = LogType.Log; + } + + public LogData2(string Message, LogType type) + { + message = Message; + duration = 2f; + x = -1; + y = -1; + size = 1; + TextColor = GetColor(type); + messagetype = type; + } + public LogData2(string Message, bool Console) + { + message = Message; + duration = 2f; + x = -1; + y = -1; + size = 1; + TextColor = Color.cyan; + messagetype = LogType.Log; + } + + public LogData2(string Message, float Duration) + { + message = Message; + duration = Duration; + x = -1; + y = -1; + size = 1; + TextColor = Color.cyan; + messagetype = LogType.Log; + } + public LogData2(string Message, float Duration, LogType type) + { + message = Message; + duration = Duration; + x = -1; + y = -1; + size = 1; + TextColor = GetColor(type); + messagetype = type; + } + public LogData2(string Message, float Duration, bool Console) + { + message = Message; + duration = Duration; + x = -1; + y = -1; + size = 1; + TextColor = Color.cyan; + messagetype = LogType.Exception; + } + + public LogData2(string Message, float Duration, Color TargetColor) + { + message = Message; + duration = Duration; + x = -1; + y = -1; + size = 1; + TextColor = TargetColor; + messagetype = LogType.Log; + } + + public LogData2(string Message, Color TargetColor) + { + message = Message; + duration = 2f; + x = -1; + y = -1; + size = 1; + TextColor = TargetColor; + messagetype = LogType.Log; + } + + public LogData2(string Message, float Duration, float X, float Y) + { + message = Message; + duration = Duration; + x = X; + y = Y; + size = 1; + TextColor = Color.cyan; + messagetype = LogType.Log; + } + public LogData2(string Message, float Duration, float X, float Y, Color TargetColor) + { + message = Message; + duration = Duration; + x = X; + y = Y; + size = 1; + TextColor = TargetColor; + messagetype = LogType.Log; + } + + public LogData2(string Message, float X, float Y) + { + message = Message; + duration = 2f; + x = X; + y = Y; + size = 1; + TextColor = Color.cyan; + messagetype = LogType.Log; + } + + public LogData2(string Message, float Duration, float X, float Y, int Size) + { + message = Message; + duration = Duration; + x = X; + y = Y; + size = Size; + TextColor = Color.cyan; + messagetype = LogType.Log; + } + + public LogData2(string Message, float X, float Y, int Size, bool Console, LogType type) + { + message = Message; + duration = 2f; + x = X; + y = Y; + size = Size > 0 ? Size : 1; + TextColor = Color.cyan; + messagetype = type; + } + + public LogData2(string Message, float Duration, float X, float Y, int Size, Color TargetColor) + { + message = Message; + duration = Duration; + x = X; + y = Y; + size = Size > 0 ? Size : 1; + TextColor = TargetColor; + messagetype = LogType.Log; + } + public LogData2(string Message, float Duration, float X, float Y, int Size, LogType type) + { + message = Message; + duration = Duration; + x = X; + y = Y; + size = Size > 0 ? Size : 1; + TextColor = GetColor(type); + messagetype = type; + } + + + private Color GetColor(LogType type) + { + switch (type) + { + case LogType.Log: + return Color.cyan; + case LogType.Warning: + return Color.yellow; + case LogType.Error: + return Color.red; + case LogType.Assert: + return Color.black; + case LogType.Exception: + return Color.white; + default: + return Color.blue; + } + } + } + [Serializable] + public class ButtonData2 + { + [SerializeField] string Name = "Button"; + [SerializeField] string Description = "This is a tooltip for the button"; + + [SerializeField] object TargetObject; + [SerializeField] string MethodName; + bool IsFunctionMethod = false; + [SerializeField] object[] MethodParametr; + + public ButtonData2(string name, string description, object targetObject, string methodName, object[] methodParametr) + { + Name = name; + Description = description; + TargetObject = targetObject; + MethodName = methodName; + IsFunctionMethod = true; + MethodParametr = methodParametr; + } + + public ButtonData2(string name, string description, object targetObject, string methodName) + { + Name = name; + Description = description; + TargetObject = targetObject; + MethodName = methodName; + } + + public ButtonData2(string name, object targetObject, string methodName) + { + Name = name; + TargetObject = targetObject; + MethodName = methodName; + } + + public bool ButtonPressed() + { + bool Result; + if (IsFunctionMethod) + { + Type type = TargetObject.GetType(); + MethodInfo method = type.GetMethod(MethodName, BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance); + + if (method != null) + { + method.Invoke(TargetObject, MethodParametr); + Result = true; + } + else + { + //////Print.LogWarning("Method " + MethodName + " not found on " + TargetObject); + Result = false; + } + } + else + { + // Get the type of the target object + Type type = TargetObject.GetType(); + + // Find the method with the specified name + MethodInfo method = type.GetMethod(MethodName, BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance); + + if (method != null) + { + // Invoke the method on the target object + method.Invoke(TargetObject, null); + Result = true; + } + else + { + /////Print.LogWarning("Method " + MethodName + " not found on " + TargetObject); + Result = false; + } + } + + return Result; + } + public string GetName() + { + return Name; + } + public string GetDescription() + { + return Description; + } + + } + + [AddComponentMenu("RealMethod/Manager/PrintManager2")] + public sealed class PrintManager2 : MonoBehaviour + { + + private abstract class GUIRenderer + { + public abstract void Start(PrintManager2 Manager); + public abstract bool CanRender(); + public abstract void Draw(); + } + + private Vector2 DefualtPosition = new Vector2(10, 10); + + private class LogRender : GUIRenderer + { + private PrintManager2 MyOWner; + public override void Start(PrintManager2 Manager) + { + //MyOWner = Manager as PrintManager; + } + public override bool CanRender() + { + return MyOWner.Logs.Count > 0; + } + public override void Draw() + { + for (int i = 0; i < MyOWner.Logs.Count; i++) + { + DrawLog(MyOWner.Logs[i], i); + } + } + + private void DrawLog(LogData2 log, int index) + { + int w = Screen.width * log.size; + int h = Screen.height * log.size; + float Xpos = log.position.x > 0 ? log.position.x : MyOWner.DefualtPosition.x; + float Ypos = log.position.y > 0 ? log.position.y : MyOWner.DefualtPosition.y + (index * MyOWner.PrintSpace); + + GUIStyle style = new GUIStyle(); + Rect rect = new Rect(Xpos, Ypos, w, h * 2 / 100); + style.alignment = TextAnchor.UpperLeft; + style.fontSize = h * 2 / 100; + style.normal.textColor = log.TextColor; + GUI.Label(rect, log.message, style); + } + } + private class ButtonRender : GUIRenderer + { + private PrintManager2 MyOWner; + + public override void Start(PrintManager2 Manager) + { + //dMyOWner = Manager as PrintManager; + } + public override bool CanRender() + { + return MyOWner.Buttons.Count > 0; + } + public override void Draw() + { + RectOffset padding = GUI.skin.button.padding; + RectOffset margin = GUI.skin.button.margin; + + // TODO: The height calculation should be done more correctly. + Rect viewRect = new Rect(0, 0, MyOWner.ButtonSize.x, + ((MyOWner.ButtonSize.y + (padding.vertical + margin.vertical)) * MyOWner.Buttons.Count) - MyOWner.ButtonSize.y); + + + MyOWner.ScrollPosition = GUI.BeginScrollView( + position: new Rect(Screen.width - MyOWner.ButtonSize.x - MyOWner.ButtonMargin, 10, MyOWner.ButtonSize.x + MyOWner.ButtonMargin, Screen.height - 10), + scrollPosition: MyOWner.ScrollPosition, + viewRect: viewRect, + alwaysShowHorizontal: false, + alwaysShowVertical: false + ); + + for (int i = 0; i < MyOWner.Buttons.Count; i++) + { + if (GUI.Button(new Rect(0, 50 * i, MyOWner.ButtonSize.x, MyOWner.ButtonSize.y), MyOWner.Buttons[i].GetName())) + { + MyOWner.Buttons[i].ButtonPressed(); + } + } + GUI.EndScrollView(); + } + } + + + + + + + + + + + + + + + + [Header("Log")] + public float PrintSpace = 20; + [Header("Button")] + [SerializeField] + private Vector2 ScrollPosition = Vector2.zero; + [SerializeField] + private Vector2 ButtonSize = new Vector2(200, 40); + [SerializeField] + private float ButtonMargin = 20; + [Header("Advance")] + [SerializeField, ReadOnly] + private List Logs = new List(); + [SerializeField, ReadOnly] + private List Buttons = new List(); + + + + // public override void InitiateManager(bool AlwaysLoaded) + // { + // throw new NotImplementedException(); + // } + // public override void ResolveService(Service service, bool active) + // { + // } + + + + private GUIRenderer[] GetRenderSlots() + { + return new GUIRenderer[2] { new LogRender(), new ButtonRender() }; + } + + public void Add(LogData2 Log) + { + if (Log.duration > 0) + { + StartCoroutine(RemoveLog(Log)); + } + Logs.Add(Log); + } + public void Add(ButtonData2 Button) + { + Buttons.Add(Button); + } + public void Clear() + { + Logs.Clear(); + Buttons.Clear(); + } + + + // Enumerators + private IEnumerator RemoveLog(LogData2 log) + { + yield return new WaitForSeconds(log.duration); + Logs.Remove(log); + } + + + } + + +} + + + + + + + diff --git a/Runtime/ReadySet/Managers/PrintManager2.cs.meta b/Runtime/ReadySet/Managers/PrintManager2.cs.meta new file mode 100644 index 0000000..2c40ebd --- /dev/null +++ b/Runtime/ReadySet/Managers/PrintManager2.cs.meta @@ -0,0 +1,2 @@ +fileFormatVersion: 2 +guid: 9de82d8783153344b91caba717ca0ce4 \ No newline at end of file diff --git a/Runtime/ReadySet/Services/DebugService.cs b/Runtime/ReadySet/Services/DebugService.cs new file mode 100644 index 0000000..5d131d1 --- /dev/null +++ b/Runtime/ReadySet/Services/DebugService.cs @@ -0,0 +1,66 @@ +using UnityEngine; + +namespace RealMethod +{ + public class DebugService : Service, ILogHandler + { + private ILogHandler defaultLogHandler; + private PrintManager Printer; + + + // Implement ILogHandler Interfacwe + void ILogHandler.LogFormat(LogType logType, Object context, string format, params object[] args) + { + string message = string.Format(format, args); + + // Send message to screen system + if (Printer) + { + Printer.Print(message, logType); + } + + // Still send message to Unity console + defaultLogHandler.LogFormat(logType, context, format, args); + } + void ILogHandler.LogException(System.Exception exception, Object context) + { + // Send message to screen system + if (Printer) + { + Printer.Print(exception.Message, LogType.Exception); + } + + defaultLogHandler.LogException(exception, context); + } + + + // Service Methods + protected override void OnStart(object Author) + { + defaultLogHandler = Debug.unityLogger.logHandler; + Debug.unityLogger.logHandler = this; + CheckManager(); + } + protected override void OnWorldChanging(World Previous, World New) + { + CheckManager(); + } + protected override void OnEnd(object Author) + { + if(Printer != null) + { + Printer.Clear(); + } + } + + + + + private void CheckManager() + { + if (Printer == null) + Printer = Game.FindManager(); + } + + } +} \ No newline at end of file diff --git a/Runtime/ReadySet/Services/DebugService.cs.meta b/Runtime/ReadySet/Services/DebugService.cs.meta new file mode 100644 index 0000000..770cd70 --- /dev/null +++ b/Runtime/ReadySet/Services/DebugService.cs.meta @@ -0,0 +1,2 @@ +fileFormatVersion: 2 +guid: 41df5dfaa2fc5e046b734051776e6912 \ No newline at end of file diff --git a/Runtime/ReadySet/Services/PrintService.cs b/Runtime/ReadySet/Services/PrintService.cs deleted file mode 100644 index 03d23c7..0000000 --- a/Runtime/ReadySet/Services/PrintService.cs +++ /dev/null @@ -1,77 +0,0 @@ -using UnityEngine; - -namespace RealMethod -{ - public sealed class Print : Service - { - private static Print CacheInstance = null; - public static Print Instance - { - get - { - if (CacheInstance != null) - { - return CacheInstance; - } - else - { - if (Game.TryFindService(out Print CacheInstance)) - { - return CacheInstance; - } - CacheInstance = Game.AddService(null); - return CacheInstance; - } - } - } - public static PrintManager Manager => Instance.Printer; - - private PrintManager Printer; - - protected override void OnStart(object Author) - { - Printer = Game.Instance.GetManager(); - if (Printer == null) - { - Printer = Game.Instance.gameObject.AddComponent(); - IGameManager manager = Printer; - manager.InitiateManager(true); - } - } - protected override void OnWorldChanging(World Previous , World New) - { - Printer.Clear(); - } - protected override void OnEnd(object Author) - { - Object.Destroy(Printer); - CacheInstance = null; - } - - public static void Log(string message, Color color, float duration = 2) - { - Manager.Add(new LogData(message, duration, color)); - } - public static void Log(string message, float duration = 2) - { - Manager.Add(new LogData(message, duration)); - } - public static void LogWarning(string message, float duration = 2) - { - Manager.Add(new LogData(message, duration, LogType.Warning)); - } - public static void LogError(string message, float duration = 2) - { - Manager.Add(new LogData(message, duration, LogType.Error)); - } - public static void LogAssertion(string message, float duration = 2) - { - Manager.Add(new LogData(message, duration, LogType.Assert)); - } - public static void Button(string name, object author, string funtionName) - { - Manager.Add(new ButtonData(name, author, funtionName)); - } - } - -} \ No newline at end of file diff --git a/Runtime/ReadySet/Services/PrintService.cs.meta b/Runtime/ReadySet/Services/PrintService.cs.meta deleted file mode 100644 index 0e9d432..0000000 --- a/Runtime/ReadySet/Services/PrintService.cs.meta +++ /dev/null @@ -1,2 +0,0 @@ -fileFormatVersion: 2 -guid: e0b5c215c57b74e4fa9b546a9d6009e4 \ No newline at end of file diff --git a/Runtime/ReadySet/Services/SpawanService.cs b/Runtime/ReadySet/Services/SpawanService.cs index b255924..35f97a8 100644 --- a/Runtime/ReadySet/Services/SpawanService.cs +++ b/Runtime/ReadySet/Services/SpawanService.cs @@ -35,6 +35,8 @@ public static Spawn instance public TaskManager GameTask; public HapticManager GameHaptic; public EnumeratorManager GameEnumerator; + public PrintManager GamePrint => Game.FindManager(); + public DebugManager GameDebug => Game.FindManager(); // Base Service protected override void OnStart(object Author) @@ -758,6 +760,32 @@ public static ICoroutineTask CoroutineTask(IEnumerator routine) } } + // Debug + public static IPrint Printer(Vector2 offcet) + { + if (instance.GamePrint != null) + { + return instance.GamePrint.PrintStatic(offcet); + } + else + { + Debug.LogWarning($" {instance}: PrintManager is not available."); + return null; + } + } + public static IButton Button(Name16 Name, System.Action Callback) + { + if (instance.GameDebug != null) + { + return instance.GameDebug.AddButton(Name, Callback); + } + else + { + Debug.LogWarning($" {instance}: DebugManager is not available."); + return null; + } + } + // Other public static GameObject Empty(string name) { @@ -923,6 +951,30 @@ public static bool Haptic(IHapticProvider provider, bool debug = true) } return Spawn.instance.GameHaptic.Demolish(provider); } + + // Debug + public static bool Printer(IPrint printer, bool debug = true) + { + if (Spawn.instance.GamePrint == null) + { + if (debug) + Debug.LogWarning("Despawn PrintManager is not available."); + return false; + } + return Spawn.instance.GamePrint.RemoveStatic(printer); + } + public static bool Button(IButton button, bool debug = true) + { + if (Spawn.instance.GameDebug == null) + { + if (debug) + Debug.LogWarning("Despawn DebugManager is not available."); + return false; + } + return Spawn.instance.GameDebug.Remove(button); + } + + } } From 93156ac8d20b1e04beab117424d07ba91361a4d9 Mon Sep 17 00:00:00 2001 From: Alijimpa Date: Tue, 24 Mar 2026 09:47:13 +0330 Subject: [PATCH 047/204] Resort Core Folder for Editor --- Editor/Core/{Architecture.meta => Attribute.meta} | 2 +- .../{Definitions => Attribute}/ConfigAssetInitializer.cs | 0 .../ConfigAssetInitializer.cs.meta | 0 .../ProjectSettingProvider.cs | 0 .../ProjectSettingProvider.cs.meta | 0 Editor/Core/{ProjectSetting => Attribute}/Sections.meta | 0 .../Sections/FolderStructure_Section.cs | 0 .../Sections/FolderStructure_Section.cs.meta | 0 .../Sections/InitializerSetting_Section.cs | 0 .../Sections/InitializerSetting_Section.cs.meta | 0 .../WorldExecutionOrderMenu.cs | 0 .../WorldExecutionOrderMenu.cs.meta | 0 Editor/Core/{Definitions.meta => Drawers.meta} | 2 +- Editor/Core/{Definitions => Drawers}/Name16Drawer.cs | 0 Editor/Core/{Definitions => Drawers}/Name16Drawer.cs.meta | 0 Editor/Core/{Definitions => Drawers}/PrefabCoreDrawer.cs | 0 .../{Definitions => Drawers}/PrefabCoreDrawer.cs.meta | 0 Editor/Core/{Definitions => Drawers}/SoftTypeDrawer.cs | 0 .../Core/{Definitions => Drawers}/SoftTypeDrawer.cs.meta | 0 Editor/Core/{ProjectSetting.meta => Inspectors.meta} | 2 +- .../Core/{Definitions => Inspectors}/DataAssetEditor.cs | 0 .../{Definitions => Inspectors}/DataAssetEditor.cs.meta | 0 Editor/Core/{Architecture => Inspectors}/GameEditor.cs | 0 .../Core/{Architecture => Inspectors}/GameEditor.cs.meta | 0 Editor/Core/Utilities.meta | 8 ++++++++ Editor/Core/{ => Utilities}/RealMethod.cs | 0 Editor/Core/{ => Utilities}/RealMethod.cs.meta | 0 27 files changed, 11 insertions(+), 3 deletions(-) rename Editor/Core/{Architecture.meta => Attribute.meta} (77%) rename Editor/Core/{Definitions => Attribute}/ConfigAssetInitializer.cs (100%) rename Editor/Core/{Definitions => Attribute}/ConfigAssetInitializer.cs.meta (100%) rename Editor/Core/{ProjectSetting => Attribute}/ProjectSettingProvider.cs (100%) rename Editor/Core/{ProjectSetting => Attribute}/ProjectSettingProvider.cs.meta (100%) rename Editor/Core/{ProjectSetting => Attribute}/Sections.meta (100%) rename Editor/Core/{ProjectSetting => Attribute}/Sections/FolderStructure_Section.cs (100%) rename Editor/Core/{ProjectSetting => Attribute}/Sections/FolderStructure_Section.cs.meta (100%) rename Editor/Core/{ProjectSetting => Attribute}/Sections/InitializerSetting_Section.cs (100%) rename Editor/Core/{ProjectSetting => Attribute}/Sections/InitializerSetting_Section.cs.meta (100%) rename Editor/Core/{Architecture => Attribute}/WorldExecutionOrderMenu.cs (100%) rename Editor/Core/{Architecture => Attribute}/WorldExecutionOrderMenu.cs.meta (100%) rename Editor/Core/{Definitions.meta => Drawers.meta} (77%) rename Editor/Core/{Definitions => Drawers}/Name16Drawer.cs (100%) rename Editor/Core/{Definitions => Drawers}/Name16Drawer.cs.meta (100%) rename Editor/Core/{Definitions => Drawers}/PrefabCoreDrawer.cs (100%) rename Editor/Core/{Definitions => Drawers}/PrefabCoreDrawer.cs.meta (100%) rename Editor/Core/{Definitions => Drawers}/SoftTypeDrawer.cs (100%) rename Editor/Core/{Definitions => Drawers}/SoftTypeDrawer.cs.meta (100%) rename Editor/Core/{ProjectSetting.meta => Inspectors.meta} (77%) rename Editor/Core/{Definitions => Inspectors}/DataAssetEditor.cs (100%) rename Editor/Core/{Definitions => Inspectors}/DataAssetEditor.cs.meta (100%) rename Editor/Core/{Architecture => Inspectors}/GameEditor.cs (100%) rename Editor/Core/{Architecture => Inspectors}/GameEditor.cs.meta (100%) create mode 100644 Editor/Core/Utilities.meta rename Editor/Core/{ => Utilities}/RealMethod.cs (100%) rename Editor/Core/{ => Utilities}/RealMethod.cs.meta (100%) diff --git a/Editor/Core/Architecture.meta b/Editor/Core/Attribute.meta similarity index 77% rename from Editor/Core/Architecture.meta rename to Editor/Core/Attribute.meta index b1a05d7..3e26e47 100644 --- a/Editor/Core/Architecture.meta +++ b/Editor/Core/Attribute.meta @@ -1,5 +1,5 @@ fileFormatVersion: 2 -guid: 600171c84a5cb1e4c9936a94efd94541 +guid: 46009ab07d5815948a8a9bfd68b24f8b folderAsset: yes DefaultImporter: externalObjects: {} diff --git a/Editor/Core/Definitions/ConfigAssetInitializer.cs b/Editor/Core/Attribute/ConfigAssetInitializer.cs similarity index 100% rename from Editor/Core/Definitions/ConfigAssetInitializer.cs rename to Editor/Core/Attribute/ConfigAssetInitializer.cs diff --git a/Editor/Core/Definitions/ConfigAssetInitializer.cs.meta b/Editor/Core/Attribute/ConfigAssetInitializer.cs.meta similarity index 100% rename from Editor/Core/Definitions/ConfigAssetInitializer.cs.meta rename to Editor/Core/Attribute/ConfigAssetInitializer.cs.meta diff --git a/Editor/Core/ProjectSetting/ProjectSettingProvider.cs b/Editor/Core/Attribute/ProjectSettingProvider.cs similarity index 100% rename from Editor/Core/ProjectSetting/ProjectSettingProvider.cs rename to Editor/Core/Attribute/ProjectSettingProvider.cs diff --git a/Editor/Core/ProjectSetting/ProjectSettingProvider.cs.meta b/Editor/Core/Attribute/ProjectSettingProvider.cs.meta similarity index 100% rename from Editor/Core/ProjectSetting/ProjectSettingProvider.cs.meta rename to Editor/Core/Attribute/ProjectSettingProvider.cs.meta diff --git a/Editor/Core/ProjectSetting/Sections.meta b/Editor/Core/Attribute/Sections.meta similarity index 100% rename from Editor/Core/ProjectSetting/Sections.meta rename to Editor/Core/Attribute/Sections.meta diff --git a/Editor/Core/ProjectSetting/Sections/FolderStructure_Section.cs b/Editor/Core/Attribute/Sections/FolderStructure_Section.cs similarity index 100% rename from Editor/Core/ProjectSetting/Sections/FolderStructure_Section.cs rename to Editor/Core/Attribute/Sections/FolderStructure_Section.cs diff --git a/Editor/Core/ProjectSetting/Sections/FolderStructure_Section.cs.meta b/Editor/Core/Attribute/Sections/FolderStructure_Section.cs.meta similarity index 100% rename from Editor/Core/ProjectSetting/Sections/FolderStructure_Section.cs.meta rename to Editor/Core/Attribute/Sections/FolderStructure_Section.cs.meta diff --git a/Editor/Core/ProjectSetting/Sections/InitializerSetting_Section.cs b/Editor/Core/Attribute/Sections/InitializerSetting_Section.cs similarity index 100% rename from Editor/Core/ProjectSetting/Sections/InitializerSetting_Section.cs rename to Editor/Core/Attribute/Sections/InitializerSetting_Section.cs diff --git a/Editor/Core/ProjectSetting/Sections/InitializerSetting_Section.cs.meta b/Editor/Core/Attribute/Sections/InitializerSetting_Section.cs.meta similarity index 100% rename from Editor/Core/ProjectSetting/Sections/InitializerSetting_Section.cs.meta rename to Editor/Core/Attribute/Sections/InitializerSetting_Section.cs.meta diff --git a/Editor/Core/Architecture/WorldExecutionOrderMenu.cs b/Editor/Core/Attribute/WorldExecutionOrderMenu.cs similarity index 100% rename from Editor/Core/Architecture/WorldExecutionOrderMenu.cs rename to Editor/Core/Attribute/WorldExecutionOrderMenu.cs diff --git a/Editor/Core/Architecture/WorldExecutionOrderMenu.cs.meta b/Editor/Core/Attribute/WorldExecutionOrderMenu.cs.meta similarity index 100% rename from Editor/Core/Architecture/WorldExecutionOrderMenu.cs.meta rename to Editor/Core/Attribute/WorldExecutionOrderMenu.cs.meta diff --git a/Editor/Core/Definitions.meta b/Editor/Core/Drawers.meta similarity index 77% rename from Editor/Core/Definitions.meta rename to Editor/Core/Drawers.meta index ff7fd27..c71d71a 100644 --- a/Editor/Core/Definitions.meta +++ b/Editor/Core/Drawers.meta @@ -1,5 +1,5 @@ fileFormatVersion: 2 -guid: 04563dc2f2c64684c987eb7ddde21c3d +guid: 4b2ca676aa99da945bf729d345f81474 folderAsset: yes DefaultImporter: externalObjects: {} diff --git a/Editor/Core/Definitions/Name16Drawer.cs b/Editor/Core/Drawers/Name16Drawer.cs similarity index 100% rename from Editor/Core/Definitions/Name16Drawer.cs rename to Editor/Core/Drawers/Name16Drawer.cs diff --git a/Editor/Core/Definitions/Name16Drawer.cs.meta b/Editor/Core/Drawers/Name16Drawer.cs.meta similarity index 100% rename from Editor/Core/Definitions/Name16Drawer.cs.meta rename to Editor/Core/Drawers/Name16Drawer.cs.meta diff --git a/Editor/Core/Definitions/PrefabCoreDrawer.cs b/Editor/Core/Drawers/PrefabCoreDrawer.cs similarity index 100% rename from Editor/Core/Definitions/PrefabCoreDrawer.cs rename to Editor/Core/Drawers/PrefabCoreDrawer.cs diff --git a/Editor/Core/Definitions/PrefabCoreDrawer.cs.meta b/Editor/Core/Drawers/PrefabCoreDrawer.cs.meta similarity index 100% rename from Editor/Core/Definitions/PrefabCoreDrawer.cs.meta rename to Editor/Core/Drawers/PrefabCoreDrawer.cs.meta diff --git a/Editor/Core/Definitions/SoftTypeDrawer.cs b/Editor/Core/Drawers/SoftTypeDrawer.cs similarity index 100% rename from Editor/Core/Definitions/SoftTypeDrawer.cs rename to Editor/Core/Drawers/SoftTypeDrawer.cs diff --git a/Editor/Core/Definitions/SoftTypeDrawer.cs.meta b/Editor/Core/Drawers/SoftTypeDrawer.cs.meta similarity index 100% rename from Editor/Core/Definitions/SoftTypeDrawer.cs.meta rename to Editor/Core/Drawers/SoftTypeDrawer.cs.meta diff --git a/Editor/Core/ProjectSetting.meta b/Editor/Core/Inspectors.meta similarity index 77% rename from Editor/Core/ProjectSetting.meta rename to Editor/Core/Inspectors.meta index 9368b91..cea3ae1 100644 --- a/Editor/Core/ProjectSetting.meta +++ b/Editor/Core/Inspectors.meta @@ -1,5 +1,5 @@ fileFormatVersion: 2 -guid: 9b58be0a7cb56d449a05466c8d147894 +guid: 3b4a83e7828d63e4e893cb8244c6a31f folderAsset: yes DefaultImporter: externalObjects: {} diff --git a/Editor/Core/Definitions/DataAssetEditor.cs b/Editor/Core/Inspectors/DataAssetEditor.cs similarity index 100% rename from Editor/Core/Definitions/DataAssetEditor.cs rename to Editor/Core/Inspectors/DataAssetEditor.cs diff --git a/Editor/Core/Definitions/DataAssetEditor.cs.meta b/Editor/Core/Inspectors/DataAssetEditor.cs.meta similarity index 100% rename from Editor/Core/Definitions/DataAssetEditor.cs.meta rename to Editor/Core/Inspectors/DataAssetEditor.cs.meta diff --git a/Editor/Core/Architecture/GameEditor.cs b/Editor/Core/Inspectors/GameEditor.cs similarity index 100% rename from Editor/Core/Architecture/GameEditor.cs rename to Editor/Core/Inspectors/GameEditor.cs diff --git a/Editor/Core/Architecture/GameEditor.cs.meta b/Editor/Core/Inspectors/GameEditor.cs.meta similarity index 100% rename from Editor/Core/Architecture/GameEditor.cs.meta rename to Editor/Core/Inspectors/GameEditor.cs.meta diff --git a/Editor/Core/Utilities.meta b/Editor/Core/Utilities.meta new file mode 100644 index 0000000..c92a9ec --- /dev/null +++ b/Editor/Core/Utilities.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 0bdf41dbd1061b64299b20780a85c8c7 +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Editor/Core/RealMethod.cs b/Editor/Core/Utilities/RealMethod.cs similarity index 100% rename from Editor/Core/RealMethod.cs rename to Editor/Core/Utilities/RealMethod.cs diff --git a/Editor/Core/RealMethod.cs.meta b/Editor/Core/Utilities/RealMethod.cs.meta similarity index 100% rename from Editor/Core/RealMethod.cs.meta rename to Editor/Core/Utilities/RealMethod.cs.meta From 39ebca03b9738d937ba82838fb17f8b7055dad0f Mon Sep 17 00:00:00 2001 From: Alijimpa Date: Wed, 25 Mar 2026 08:18:53 +0330 Subject: [PATCH 048/204] Implement Base SettingEnum --- .../Core/Attribute/ProjectSettingProvider.cs | 7 +- .../Sections/FolderStructure_Section.cs | 27 ++-- .../Attribute/Sections/GameStatus_Section.cs | 70 ++++++++++ .../Sections/GameStatus_Section.cs.meta | 2 + Editor/Core/Drawers/SettingEnumDrawer.cs | 26 ++++ Editor/Core/Drawers/SettingEnumDrawer.cs.meta | 2 + Editor/Core/Utilities/RealMethod.cs | 6 +- .../ReadySet/Tools/AnimatorScriptGenerator.cs | 2 +- Editor/Toolkit/PCG/PCGEditorWindow.cs | 2 +- Editor/Toolkit/TerrainTools/TerrainEditor.cs | 2 +- Runtime/Core/Architecture/Game.cs | 37 +++++- Runtime/Core/Definitions/SettingEnum.cs | 117 +++++++++++++++++ Runtime/Core/Definitions/SettingEnum.cs.meta | 2 + .../ProjectSetting/ProjectSettingAsset.cs | 120 +++++++----------- 14 files changed, 325 insertions(+), 97 deletions(-) create mode 100644 Editor/Core/Attribute/Sections/GameStatus_Section.cs create mode 100644 Editor/Core/Attribute/Sections/GameStatus_Section.cs.meta create mode 100644 Editor/Core/Drawers/SettingEnumDrawer.cs create mode 100644 Editor/Core/Drawers/SettingEnumDrawer.cs.meta create mode 100644 Runtime/Core/Definitions/SettingEnum.cs create mode 100644 Runtime/Core/Definitions/SettingEnum.cs.meta diff --git a/Editor/Core/Attribute/ProjectSettingProvider.cs b/Editor/Core/Attribute/ProjectSettingProvider.cs index 977a940..b6d4e1a 100644 --- a/Editor/Core/Attribute/ProjectSettingProvider.cs +++ b/Editor/Core/Attribute/ProjectSettingProvider.cs @@ -91,7 +91,9 @@ void ISectionSetting.Draw() if (isReady) { // Render the section's content + EditorGUILayout.BeginVertical(EditorStyles.helpBox); UpdateRender(); + EditorGUILayout.EndVertical(); } else { @@ -148,10 +150,11 @@ protected void ClearError() public static class ProjectSettingProvider { private static bool candraw = true;// Flag to determine if the UI can be drawn - private static List sections = new List(2) { + private static List sections = new List(3) { // Array of sections to be rendered in the settings UI new InitializerSetting_Section(), - new FolderStructure_Section() + new FolderStructure_Section(), + new GameStatus_Section(), }; diff --git a/Editor/Core/Attribute/Sections/FolderStructure_Section.cs b/Editor/Core/Attribute/Sections/FolderStructure_Section.cs index 9a6d2f8..503cf2d 100644 --- a/Editor/Core/Attribute/Sections/FolderStructure_Section.cs +++ b/Editor/Core/Attribute/Sections/FolderStructure_Section.cs @@ -18,14 +18,9 @@ protected override void BeginRender(ProjectSettingAsset Storage) } protected override void UpdateRender() { - string[] structureType = System.Enum.GetNames(typeof(ProjectSettingAsset.FolderStructureType)); - MyStorage.SetStructureType(EditorGUILayout.Popup("StructureType", MyStorage.GetStructureType(), structureType)); - if (MyStorage.GetStructureType() == 1) + if (!AssetDatabase.IsValidFolder("Assets/" + Application.productName)) { - if (!AssetDatabase.IsValidFolder("Assets/" + Application.productName)) - { - AssetDatabase.CreateFolder("Assets", Application.productName); - } + AssetDatabase.CreateFolder("Assets", Application.productName); } // Add a toggle button for minimizing or expanding the panel @@ -33,7 +28,7 @@ protected override void UpdateRender() isPanelMaximize = EditorGUILayout.Foldout(isPanelMaximize, "Folder List", true, EditorStyles.foldoutHeader); if (GUILayout.Button("Create All", GUILayout.Width(80))) { - foreach (var address in MyStorage.ProjectStructure) + foreach (var address in MyStorage.FolderStructure) { if (AssetDatabase.IsValidFolder(address.AssetPath)) { @@ -57,26 +52,26 @@ protected override void UpdateRender() } // Render the folder list - for (int i = 0; i < MyStorage.ProjectStructure.Count; i++) + for (int i = 0; i < MyStorage.FolderStructure.Count; i++) { EditorGUILayout.BeginHorizontal(); // Start horizontal layout // Display the folder path as a text field - MyStorage.SetFolderAddressPath(i, EditorGUILayout.TextField($"{i + 1}.{MyStorage.ProjectStructure[i].AssetType}", MyStorage.ProjectStructure[i].AssetPath)); + MyStorage.SetFolderAddressPath(i, EditorGUILayout.TextField($"{i + 1}.{MyStorage.FolderStructure[i].AssetType}", MyStorage.FolderStructure[i].AssetPath)); - string ButtonName = AssetDatabase.IsValidFolder(MyStorage.ProjectStructure[i].AssetPath) ? "Check" : "Create"; + string ButtonName = AssetDatabase.IsValidFolder(MyStorage.FolderStructure[i].AssetPath) ? "Check" : "Create"; // Add a button next to the text field if (GUILayout.Button(ButtonName, GUILayout.Width(60))) { // Check if the folder exists - if (AssetDatabase.IsValidFolder(MyStorage.ProjectStructure[i].AssetPath)) + if (AssetDatabase.IsValidFolder(MyStorage.FolderStructure[i].AssetPath)) { - Debug.Log($"Folder exists: {MyStorage.ProjectStructure[i]}"); + Debug.Log($"Folder exists: {MyStorage.FolderStructure[i]}"); } else { - string folderpath = MyStorage.ProjectStructure[i].GetFolderPath(MyStorage); + string folderpath = MyStorage.FolderStructure[i].GetFolderPath(MyStorage); string FolderAddress = string.Join("/", folderpath.Split('/')[..^1]); // Remove the last segment of the path string folderName = System.IO.Path.GetFileName(folderpath); // Get the last segment of the path CreateFolder(FolderAddress, folderName); // Create the folder @@ -97,8 +92,8 @@ protected override SectionType GetSectionType() protected override void Fix(int Id) { } - - + + private void CreateFolder(string parentFolder, string newFolderName) { string folderPath = System.IO.Path.Combine(parentFolder, newFolderName).Replace("\\", "/"); diff --git a/Editor/Core/Attribute/Sections/GameStatus_Section.cs b/Editor/Core/Attribute/Sections/GameStatus_Section.cs new file mode 100644 index 0000000..02eb65b --- /dev/null +++ b/Editor/Core/Attribute/Sections/GameStatus_Section.cs @@ -0,0 +1,70 @@ + +using System.Collections.Generic; +using UnityEditor; +using UnityEngine; + +namespace RealMethod.Editor +{ + public class GameStatus_Section : ProjectSettingSection + { + private ProjectSettingAsset settings; + static List names = new List(); + + + protected override string GetTitle() + { + return "GameStatus"; + } + protected override SectionType GetSectionType() + { + return SectionType.Editor; + } + protected override void Initialized() + { + + } + protected override void BeginRender(ProjectSettingAsset Storage) + { + settings = Storage; + if (settings != null && names.Count == 0) + names.AddRange(settings.GetStatus()); + } + protected override void UpdateRender() + { + + EditorGUI.BeginChangeCheck(); + + int newSize = Mathf.Max(0, EditorGUILayout.IntField("Size", names.Count)); + + while (names.Count < newSize) + names.Add(""); + + while (names.Count > newSize) + names.RemoveAt(names.Count - 1); + + for (int i = 0; i < names.Count; i++) + { + names[i] = EditorGUILayout.TextField($"Element {i}", names[i]); + } + + if (EditorGUI.EndChangeCheck()) + { + if (settings != null) + { + Undo.RecordObject(settings, "Modify Game Status Names"); + + settings.SetStatus(names.ToArray()); + + EditorUtility.SetDirty(settings); + } + } + } + + protected override void Fix(int Id) + { + + } + + + } +} \ No newline at end of file diff --git a/Editor/Core/Attribute/Sections/GameStatus_Section.cs.meta b/Editor/Core/Attribute/Sections/GameStatus_Section.cs.meta new file mode 100644 index 0000000..0a82f4c --- /dev/null +++ b/Editor/Core/Attribute/Sections/GameStatus_Section.cs.meta @@ -0,0 +1,2 @@ +fileFormatVersion: 2 +guid: a6ecf6e981d7ae74ea5bfab2e27f9523 \ No newline at end of file diff --git a/Editor/Core/Drawers/SettingEnumDrawer.cs b/Editor/Core/Drawers/SettingEnumDrawer.cs new file mode 100644 index 0000000..4ad993c --- /dev/null +++ b/Editor/Core/Drawers/SettingEnumDrawer.cs @@ -0,0 +1,26 @@ +using UnityEditor; +using UnityEngine; + +namespace RealMethod.Editor +{ + [CustomPropertyDrawer(typeof(SettingEnum))] + public class SettingEnumDrawer : PropertyDrawer + { + public override void OnGUI(Rect position, SerializedProperty property, GUIContent label) + { + var valueProp = property.FindPropertyRelative("Value"); + + var ProjectSettings = AssetDatabase.LoadAssetAtPath("Assets/Resources/RealMethod/RealMethodSetting.asset"); + string[] names = ProjectSettings.GetStatus(); + + int index = valueProp.intValue; + + if (index >= names.Length) + index = 0; + + int newIndex = EditorGUI.Popup(position, label.text, index, names); + + valueProp.intValue = newIndex; + } + } +} \ No newline at end of file diff --git a/Editor/Core/Drawers/SettingEnumDrawer.cs.meta b/Editor/Core/Drawers/SettingEnumDrawer.cs.meta new file mode 100644 index 0000000..2ea542e --- /dev/null +++ b/Editor/Core/Drawers/SettingEnumDrawer.cs.meta @@ -0,0 +1,2 @@ +fileFormatVersion: 2 +guid: b498f42342792244b9f4ab755fd39a70 \ No newline at end of file diff --git a/Editor/Core/Utilities/RealMethod.cs b/Editor/Core/Utilities/RealMethod.cs index 43564eb..4d9f135 100644 --- a/Editor/Core/Utilities/RealMethod.cs +++ b/Editor/Core/Utilities/RealMethod.cs @@ -14,7 +14,7 @@ public static class RealMethod public static bool GetSettingStorage(out ProjectSettingAsset settings) { // Attempt to load the settings asset from the specified path - settings = AssetDatabase.LoadAssetAtPath(RealMethod.SetttingAssetPath); + settings = AssetDatabase.LoadAssetAtPath(SetttingAssetPath); return settings != null; } private static string GetPackagePath(string packageName) @@ -45,7 +45,7 @@ public static string CreateScriptTemplate(string templateFileName, string defaul if (UseProject) { ProjectSettingAsset ProjectSetting = AssetDatabase.LoadAssetAtPath(SetttingAssetPath); - templatePath = Path.Combine(ProjectSetting[ProjectSettingAsset.AssetFormat.Other], templateFileName); + templatePath = Path.Combine(ProjectSetting.GetFolderPathByType(ProjectSettingAsset.AssetFormat.Other), templateFileName); } else { @@ -96,7 +96,7 @@ public static GameObject CreatePrefabTemplate(string prefabName, bool UseProject if (UseProject) { ProjectSettingAsset ProjectSetting = AssetDatabase.LoadAssetAtPath(SetttingAssetPath); - prefabPath = Path.Combine(ProjectSetting[ProjectSettingAsset.AssetFormat.Prefab], prefabName); + prefabPath = Path.Combine(ProjectSetting.GetFolderPathByType(ProjectSettingAsset.AssetFormat.Prefab), prefabName); } else { diff --git a/Editor/ReadySet/Tools/AnimatorScriptGenerator.cs b/Editor/ReadySet/Tools/AnimatorScriptGenerator.cs index da0b7d7..3be0806 100644 --- a/Editor/ReadySet/Tools/AnimatorScriptGenerator.cs +++ b/Editor/ReadySet/Tools/AnimatorScriptGenerator.cs @@ -16,7 +16,7 @@ public static void GenerateScriptsFromAnimators() ProjectSettingAsset TargetStorage; if (RealMethod.GetSettingStorage(out TargetStorage)) { - outputFolder = TargetStorage[ProjectSettingAsset.AssetFormat.Script] + "/General/AnimatorParam"; + outputFolder = TargetStorage.GetFolderPathByType(ProjectSettingAsset.AssetFormat.Script) + "/General/AnimatorParam"; } else { diff --git a/Editor/Toolkit/PCG/PCGEditorWindow.cs b/Editor/Toolkit/PCG/PCGEditorWindow.cs index 80446ed..96f84d0 100644 --- a/Editor/Toolkit/PCG/PCGEditorWindow.cs +++ b/Editor/Toolkit/PCG/PCGEditorWindow.cs @@ -107,7 +107,7 @@ private void OnEnable() Cash = new EP_Asset("Cash", this); SelectedData = new EP_List("Data", this); CashAddress = new EP_String("Address", this); - CashAddress.SetValue(ProjectSetting[ProjectSettingAsset.AssetFormat.ScriptableObject] + "/PCGCashAsset.asset"); + CashAddress.SetValue(ProjectSetting.GetFolderPathByType(ProjectSettingAsset.AssetFormat.ScriptableObject) + "/PCGCashAsset.asset"); PrefabAddress = new EP_String("Address", this); PrefabAddress.SetValue(ProjectSetting.GetFolderAddressByType(ProjectSettingAsset.AssetFormat.Prefab).AssetPath + "/PCG.prefab"); ExportType = new EP_Enum("ExportType", this); diff --git a/Editor/Toolkit/TerrainTools/TerrainEditor.cs b/Editor/Toolkit/TerrainTools/TerrainEditor.cs index b7a72fd..72a9462 100644 --- a/Editor/Toolkit/TerrainTools/TerrainEditor.cs +++ b/Editor/Toolkit/TerrainTools/TerrainEditor.cs @@ -94,7 +94,7 @@ public ExportTreeData(Terrain owner, UnityEditor.Editor editor) CashFile = new EP_Asset("Cash", editor); CashAddress = new EP_String("Address", editor); - CashAddress.SetValue(ProjectSetting[ProjectSettingAsset.AssetFormat.ScriptableObject] + "/TerrainCash.asset"); + CashAddress.SetValue(ProjectSetting.GetFolderPathByType(ProjectSettingAsset.AssetFormat.ScriptableObject) + "/TerrainCash.asset"); } public void OnRender() diff --git a/Runtime/Core/Architecture/Game.cs b/Runtime/Core/Architecture/Game.cs index 3dfabb0..8f94abc 100644 --- a/Runtime/Core/Architecture/Game.cs +++ b/Runtime/Core/Architecture/Game.cs @@ -29,8 +29,6 @@ public enum GameProcess Cancelled } - - /// /// Core game singleton that manages the active , registered s, /// configuration and high-level game lifecycle (initialization, start, and shutdown). @@ -71,6 +69,10 @@ public static GameObject Player } } /// + /// Reperesent Game State that youser can define state in ProjectSetting + /// + public static SettingEnum State { get; private set; } = 0; + /// /// Indicates whether a scene or world load operation is currently in progress. /// public static bool IsPaused @@ -127,6 +129,10 @@ public static event Action OnReady /// (for example: show win screen, game over UI, load next level, etc). /// public static event Action OnCompleted; + /// + /// Invoked when game state changed. + /// + public static event Action OnStateChanged; @@ -660,6 +666,22 @@ public static void SetSpeed(float speed, bool physicSafe = true) Time.fixedDeltaTime = 0.02f * Time.timeScale; // Keeps physics in sync } /// + /// Sets the GameState to new state you want. + /// + /// Target State you want to cahgne + /// the refrence from who want to change the gamestate + /// + public static bool SetState(int NewState, object author) + { + if (Instance.CanChangeState(State, NewState, author)) + { + State = NewState; + OnStateChanged?.Invoke(State); + return true; + } + return false; + } + /// /// Quits the application. In the Unity Editor this stops play mode instead. /// public static void Quit() @@ -884,6 +906,17 @@ protected virtual bool IsGameLoading() { return ((ILoadScneBridge)Bridge).IsLoading; } + /// + /// Check for changing state from A to B by author. + /// + /// Current state + /// Target state + /// this object want to change state + /// + protected virtual bool CanChangeState(int A, int B, object author) + { + return true; + } /// diff --git a/Runtime/Core/Definitions/SettingEnum.cs b/Runtime/Core/Definitions/SettingEnum.cs new file mode 100644 index 0000000..fd02e09 --- /dev/null +++ b/Runtime/Core/Definitions/SettingEnum.cs @@ -0,0 +1,117 @@ +using System; +using UnityEngine; + +#if UNITY_EDITOR +using UnityEditor; +#endif + +namespace RealMethod +{ + /// + /// This struct stores a game status as a byte index. + /// The actual readable names are not stored here. + /// Instead, the names are defined in a global list + /// inside ProjectSettingsAsset that just compile in editor. + /// + [Serializable] + public struct SettingEnum + { + [SerializeField] + private int Value; // <-- this name must match + + public SettingEnum(int index = 0) + { + Value = index; + } + public SettingEnum(byte index = 0) + { + Value = index; + } + + + public static implicit operator SettingEnum(int val) + { + return new SettingEnum(val); + } + public static implicit operator int(SettingEnum status) + { + return status.Value; + } + public static implicit operator SettingEnum(byte val) + { + return new SettingEnum(val); + } + public static implicit operator byte(SettingEnum status) + { + return (byte)status.Value; + } + + +#if UNITY_EDITOR + public SettingEnum(string IndexName) + { + byte result = 0; + var ProjectSettings = AssetDatabase.LoadAssetAtPath("Assets/Resources/RealMethod/RealMethodSetting.asset"); + if (ProjectSettings) + { + var names = ProjectSettings.GetStatus(); + if (names == null) + result = 0; + for (int i = 0; i < names.Length; i++) + { + if (names[i] == IndexName) + { + result = (byte)i; + } + } + } + else + { + result = 0; + } + Value = result; + } + private string Name + { + get + { + var ProjectSettings = AssetDatabase.LoadAssetAtPath("Assets/Resources/RealMethod/RealMethodSetting.asset"); + if (ProjectSettings) + { + var names = ProjectSettings.GetStatus(); + if (names == null || Value >= names.Length) + return "Undefined"; + return names[Value]; + } + else + { + return "Undefined"; + } + } + } + public static implicit operator SettingEnum(string val) + { + return new SettingEnum(val); + } + public static implicit operator string(SettingEnum status) + { + var ProjectSettings = AssetDatabase.LoadAssetAtPath("Assets/Resources/RealMethod/RealMethodSetting.asset"); + if (ProjectSettings) + { + var names = ProjectSettings.GetStatus(); + if (names == null || status.Value >= names.Length) + return "Undefined"; + return names[status.Value]; + } + else + { + return "Undefined"; + } + } + public override string ToString() + { + return Name; + } +#endif + } +} \ No newline at end of file diff --git a/Runtime/Core/Definitions/SettingEnum.cs.meta b/Runtime/Core/Definitions/SettingEnum.cs.meta new file mode 100644 index 0000000..bdede59 --- /dev/null +++ b/Runtime/Core/Definitions/SettingEnum.cs.meta @@ -0,0 +1,2 @@ +fileFormatVersion: 2 +guid: a7798e11590785c479b5e152a3cd2ba5 \ No newline at end of file diff --git a/Runtime/Core/ProjectSetting/ProjectSettingAsset.cs b/Runtime/Core/ProjectSetting/ProjectSettingAsset.cs index 1d5769e..ff9169a 100644 --- a/Runtime/Core/ProjectSetting/ProjectSettingAsset.cs +++ b/Runtime/Core/ProjectSetting/ProjectSettingAsset.cs @@ -1,29 +1,13 @@ using System; using System.Collections.Generic; +using UnityEditor; using UnityEngine; -// #if UNITY_EDITOR -// namespace RealMethod.Editor; -// #endif - namespace RealMethod { // Real Method Setting Storage public class ProjectSettingAsset : ScriptableObject { - [Serializable] - public struct FolderAddress - { - public AssetFormat AssetType; - public string AssetPath; - public string FolderName => System.IO.Path.GetFileName(AssetPath); - public string GetFolderPath(ProjectSettingAsset settingAsset) - { - string RootPath = settingAsset.GetStructureType() == 0 ? "Assets" : "Assets/" + Application.productName; - return $"{RootPath}/{AssetPath}"; - } - - } [Serializable] public enum AssetFormat { @@ -43,12 +27,20 @@ public enum AssetFormat Other = 13 } [Serializable] - public enum FolderStructureType + public struct FolderAddress { - Assets = 0, - ProjectName = 1, + public AssetFormat AssetType; + public string AssetPath; + public string FolderName => System.IO.Path.GetFileName(AssetPath); + public string GetFolderPath(ProjectSettingAsset settingAsset) + { + string RootPath = "Assets/" + Application.productName; + return $"{RootPath}/{AssetPath}"; + } + } + [Header("Initializer")] [SerializeField, ReadOnly] public string GameClass = string.Empty; // <-- this name must match @@ -58,23 +50,21 @@ public enum FolderStructureType private GameConfig GameConfig; // <-- this name must match [SerializeField] private GameObject GamePrefab_1; // <-- this name must match + #if UNITY_EDITOR [SerializeField] private GameObject GamePrefab_2; // <-- this name must match #endif -#if UNITY_SERVER + +#if UNITY_SERVER || UNITY_EDITOR [SerializeField] private GameObject GamePrefab_3; // <-- this name must match #endif - - - +#if UNITY_EDITOR [Header("FolderStructure")] [SerializeField, ReadOnly] - private FolderStructureType structureType; - [SerializeField, ReadOnly] - private FolderAddress[] projectStructure = new FolderAddress[14] + private FolderAddress[] folderStructure = new FolderAddress[14] { new FolderAddress { AssetType = 0, AssetPath = "1_Scenes"}, new FolderAddress { AssetType = (AssetFormat)1, AssetPath = "2_Scripts" }, @@ -91,16 +81,12 @@ public enum FolderStructureType new FolderAddress { AssetType = (AssetFormat)12, AssetPath = "10_Animation"}, new FolderAddress { AssetType = (AssetFormat)13, AssetPath = "7_Misc"} }; - public IReadOnlyList ProjectStructure => projectStructure; - [Header("Names")] - public List Names = new(); - + public IReadOnlyList FolderStructure => folderStructure; + [Header("GameStatus")] + [SerializeField] + private string[] Status; +#endif - // Access values - public string this[AssetFormat type] - { - get => GetFolderAddressByType(type).GetFolderPath(this); - } // Unity Methods protected virtual void OnEnable() @@ -109,6 +95,8 @@ protected virtual void OnEnable() GameClass = typeof(DefultGame).AssemblyQualifiedName; if (string.IsNullOrEmpty(GameBridge)) GameBridge = typeof(DefaultGameBridge).AssemblyQualifiedName; + if (Status == null || Status.Length == 0) + Status = new string[4] { "Menu", "Playing", "Pause", "GameOver" }; } protected virtual void Reset() { @@ -116,6 +104,8 @@ protected virtual void Reset() GameClass = typeof(DefultGame).AssemblyQualifiedName; if (string.IsNullOrEmpty(GameBridge)) GameBridge = typeof(DefaultGameBridge).AssemblyQualifiedName; + if (Status == null || Status.Length == 0) + Status = new string[4] { "Menu", "Playing", "Pause", "GameOver" }; } @@ -138,56 +128,44 @@ public GameObject GetPrefab_1() return GamePrefab_1; } - - - - - - - - #if UNITY_EDITOR public GameObject GetPrefab_2() { return GamePrefab_2; } -#endif - -#if UNITY_SERVER - public GameObject GetPrefab_3() - { - return GamePrefab_3; - } -#endif - - - - - - - - public int GetStructureType() - { - return (int)structureType; - } - public void SetStructureType(int type) - { - structureType = (FolderStructureType)type; - } - public FolderAddress GetFolderAddressByIndex(int index) => projectStructure[index]; - public void SetFolderAddressPath(int index, string value) => projectStructure[index].AssetPath = value; public FolderAddress GetFolderAddressByType(AssetFormat identity) { - foreach (var PS in projectStructure) + foreach (var PS in folderStructure) { if (PS.AssetType == identity) { return PS; } } - return default(FolderAddress); + return default; + } + public string GetFolderPathByType(AssetFormat identity) + { + return GetFolderAddressByType(identity).GetFolderPath(this); } + public FolderAddress GetFolderAddressByIndex(int index) => folderStructure[index]; + public void SetFolderAddressPath(int index, string value) => folderStructure[index].AssetPath = value; + public string[] GetStatus() => Status; + public void SetStatus(string[] NewStatus) + { + if (NewStatus != null) + { + Status = NewStatus; + } + } +#endif +#if UNITY_SERVER || UNITY_EDITOR + public GameObject GetPrefab_3() + { + return GamePrefab_3; + } +#endif } From 228ffd1097285ab5cce8b1e9c725dde2cb660d32 Mon Sep 17 00:00:00 2001 From: Alijimpa Date: Wed, 25 Mar 2026 09:04:27 +0330 Subject: [PATCH 049/204] Rename Core LLibrary --- .../Core/Attribute/ProjectSettingProvider.cs | 8 +-- .../{RealMethod.cs => Editor_Library.cs} | 2 +- ...lMethod.cs.meta => Editor_Library.cs.meta} | 0 .../Content/RealMethod_ScriptTemplate.cs | 70 +++++++++---------- .../ReadySet/Tools/AnimatorScriptGenerator.cs | 2 +- .../Toolkit/Ability/Ability_ScriptTemplate.cs | 6 +- Editor/Toolkit/Actor/Actor_ScriptTemplate.cs | 2 +- .../Inventory/Inventory_ScriptTemplate.cs | 2 +- Editor/Toolkit/PCG/PCG_ScriptTemplate.cs | 2 +- .../Toolkit/Pickup/Pickup_ScriptTemplate.cs | 4 +- Editor/Toolkit/RPG/RPG_ScriptTemplate.cs | 8 +-- .../Tutorial/Tutorial_ScriptTemplate.cs | 6 +- .../Toolkit/Upgrade/Upgrade_ScriptTemplate.cs | 4 +- 13 files changed, 58 insertions(+), 58 deletions(-) rename Editor/Core/Utilities/{RealMethod.cs => Editor_Library.cs} (99%) rename Editor/Core/Utilities/{RealMethod.cs.meta => Editor_Library.cs.meta} (100%) diff --git a/Editor/Core/Attribute/ProjectSettingProvider.cs b/Editor/Core/Attribute/ProjectSettingProvider.cs index b6d4e1a..37d8e6a 100644 --- a/Editor/Core/Attribute/ProjectSettingProvider.cs +++ b/Editor/Core/Attribute/ProjectSettingProvider.cs @@ -172,9 +172,9 @@ public static SettingsProvider CreateSettingsProvider() ProjectSettingAsset TargetStorage = null; // Attempt to load the settings asset - if (!RealMethod.GetSettingStorage(out TargetStorage)) + if (!RM_Editor.GetSettingStorage(out TargetStorage)) { - if (Directory.Exists(Path.GetDirectoryName(RealMethod.SetttingAssetPath))) + if (Directory.Exists(Path.GetDirectoryName(RM_Editor.SetttingAssetPath))) { TargetStorage = CreateSettingStorage(); } @@ -210,7 +210,7 @@ public static SettingsProvider CreateSettingsProvider() } else { - EditorGUILayout.HelpBox($"The Address is not valid {Path.GetDirectoryName(RealMethod.SetttingAssetPath)}", MessageType.Error); + EditorGUILayout.HelpBox($"The Address is not valid {Path.GetDirectoryName(RM_Editor.SetttingAssetPath)}", MessageType.Error); if (GUILayout.Button("Fix")) { if (!Directory.Exists("Assets/Resources")) @@ -243,7 +243,7 @@ private static ProjectSettingAsset CreateSettingStorage() { // Create a new settings asset at the specified path ProjectSettingAsset settings = ScriptableObject.CreateInstance(); - AssetDatabase.CreateAsset(settings, RealMethod.SetttingAssetPath); + AssetDatabase.CreateAsset(settings, RM_Editor.SetttingAssetPath); AssetDatabase.SaveAssets(); return settings; } diff --git a/Editor/Core/Utilities/RealMethod.cs b/Editor/Core/Utilities/Editor_Library.cs similarity index 99% rename from Editor/Core/Utilities/RealMethod.cs rename to Editor/Core/Utilities/Editor_Library.cs index 4d9f135..1b274c5 100644 --- a/Editor/Core/Utilities/RealMethod.cs +++ b/Editor/Core/Utilities/Editor_Library.cs @@ -4,7 +4,7 @@ namespace RealMethod.Editor { - public static class RealMethod + public static class RM_Editor { public const string SetttingAssetPath = "Assets/Resources/RealMethod/RealMethodSetting.asset"; public static string ScriptTemplatesPath => GetPackagePath("com.mustard.realmethod") + "/Reservoir/ScriptTemplates"; diff --git a/Editor/Core/Utilities/RealMethod.cs.meta b/Editor/Core/Utilities/Editor_Library.cs.meta similarity index 100% rename from Editor/Core/Utilities/RealMethod.cs.meta rename to Editor/Core/Utilities/Editor_Library.cs.meta diff --git a/Editor/ReadySet/Content/RealMethod_ScriptTemplate.cs b/Editor/ReadySet/Content/RealMethod_ScriptTemplate.cs index 88e285d..6a2d85e 100644 --- a/Editor/ReadySet/Content/RealMethod_ScriptTemplate.cs +++ b/Editor/ReadySet/Content/RealMethod_ScriptTemplate.cs @@ -8,64 +8,64 @@ class RealMethodScriptTemplate [MenuItem("Assets/Create/Scripting/RealMethod/Essential/Game", false, 80)] public static void CreateGameClass() { - string Path = RealMethod.CreateScriptTemplate("GameTemplate.txt", "MyGame.cs"); + string Path = RM_Editor.CreateScriptTemplate("GameTemplate.txt", "MyGame.cs"); } [MenuItem("Assets/Create/Scripting/RealMethod/Essential/World", false, 80)] public static void CreateWorld() { - string Path = RealMethod.CreateScriptTemplate("WorldTemplate.txt", "MyWorld.cs"); + string Path = RM_Editor.CreateScriptTemplate("WorldTemplate.txt", "MyWorld.cs"); } [MenuItem("Assets/Create/Scripting/RealMethod/Essential/GameBridge", false, 80)] public static void CreateGameBridgeClass() { - string Path = RealMethod.CreateScriptTemplate("GameBridgeTemplate.txt", "MyGameBridge.cs"); + string Path = RM_Editor.CreateScriptTemplate("GameBridgeTemplate.txt", "MyGameBridge.cs"); } // Managers [MenuItem("Assets/Create/Scripting/RealMethod/Manager/BaseManager", false, 80)] public static void CreateManager() { - string Path = RealMethod.CreateScriptTemplate("ManagerTemplate.txt", "MyManager.cs"); + string Path = RM_Editor.CreateScriptTemplate("ManagerTemplate.txt", "MyManager.cs"); } [MenuItem("Assets/Create/Scripting/RealMethod/Manager/AudioManager", false, 80)] public static void CreateAudioManager() { - string Path = RealMethod.CreateScriptTemplate("AudioManagerTemplater.txt", "MyAudioManager.cs"); + string Path = RM_Editor.CreateScriptTemplate("AudioManagerTemplater.txt", "MyAudioManager.cs"); } [MenuItem("Assets/Create/Scripting/RealMethod/Manager/CompositManager", false, 80)] public static void CreateCompositManager() { - string Path = RealMethod.CreateScriptTemplate("CompositManagerTemplate.txt", "MyCompositManager.cs"); + string Path = RM_Editor.CreateScriptTemplate("CompositManagerTemplate.txt", "MyCompositManager.cs"); } [MenuItem("Assets/Create/Scripting/RealMethod/Manager/DataManager", false, 80)] public static void CreateDataManager() { - string Path = RealMethod.CreateScriptTemplate("DataManagerTemplate.txt", "MyDataManager.cs"); + string Path = RM_Editor.CreateScriptTemplate("DataManagerTemplate.txt", "MyDataManager.cs"); } [MenuItem("Assets/Create/Scripting/RealMethod/Manager/GizmoManager", false, 80)] public static void CreateGizmoManager() { - string Path = RealMethod.CreateScriptTemplate("GizmoManagerTemplate.txt", "MyGizmoManager.cs"); + string Path = RM_Editor.CreateScriptTemplate("GizmoManagerTemplate.txt", "MyGizmoManager.cs"); } [MenuItem("Assets/Create/Scripting/RealMethod/Manager/UIManager", false, 80)] public static void CreateUIManager() { - string Path = RealMethod.CreateScriptTemplate("UIManagerTemplate.txt", "MyUIManager.cs"); + string Path = RM_Editor.CreateScriptTemplate("UIManagerTemplate.txt", "MyUIManager.cs"); } [MenuItem("Assets/Create/Scripting/RealMethod/Manager/MixerManager", false, 80)] public static void CreateMixerManager() { - string Path = RealMethod.CreateScriptTemplate("MixerManagerTemplate.txt", "MyMixerManager.cs"); + string Path = RM_Editor.CreateScriptTemplate("MixerManagerTemplate.txt", "MyMixerManager.cs"); } [MenuItem("Assets/Create/Scripting/RealMethod/Manager/HapticManager", false, 80)] public static void CreateHapticManager() { - string Path = RealMethod.CreateScriptTemplate("HapticManagerTemplate.txt", "MyHapticManager.cs"); + string Path = RM_Editor.CreateScriptTemplate("HapticManagerTemplate.txt", "MyHapticManager.cs"); } [MenuItem("Assets/Create/Scripting/RealMethod/Manager/TickManager", false, 80)] public static void CreateTickManager() { - string Path = RealMethod.CreateScriptTemplate("TickManagerTemplate.txt", "MyTickManager.cs"); + string Path = RM_Editor.CreateScriptTemplate("TickManagerTemplate.txt", "MyTickManager.cs"); } @@ -73,17 +73,17 @@ public static void CreateTickManager() [MenuItem("Assets/Create/Scripting/RealMethod/Service/BaseService", false, 80)] public static void CreateService() { - string Path = RealMethod.CreateScriptTemplate("ServiceTemplate.txt", "MyServicec.cs"); + string Path = RM_Editor.CreateScriptTemplate("ServiceTemplate.txt", "MyServicec.cs"); } [MenuItem("Assets/Create/Scripting/RealMethod/Service/StateService", false, 80)] public static void CreateStateService() { - string Path = RealMethod.CreateScriptTemplate("StateServiceTemplate.txt", "MyStateService.cs"); + string Path = RM_Editor.CreateScriptTemplate("StateServiceTemplate.txt", "MyStateService.cs"); } [MenuItem("Assets/Create/Scripting/RealMethod/Service/RuleService", false, 80)] public static void CreateRuleService() { - string Path = RealMethod.CreateScriptTemplate("RuleServiceTemplate.txt", "MyRuleService.cs"); + string Path = RM_Editor.CreateScriptTemplate("RuleServiceTemplate.txt", "MyRuleService.cs"); } @@ -93,75 +93,75 @@ public static void CreateRuleService() [MenuItem("Assets/Create/Scripting/RealMethod/Asset/Data/BaseData", false, 80)] public static void CreateDataAsset() { - string Path = RealMethod.CreateScriptTemplate("DataAssetTemplate.txt", "MyDataAsset.cs"); + string Path = RM_Editor.CreateScriptTemplate("DataAssetTemplate.txt", "MyDataAsset.cs"); } [MenuItem("Assets/Create/Scripting/RealMethod/Asset/Data/ItemAsset", false, 80)] public static void CreateItemAsset() { - string Path = RealMethod.CreateScriptTemplate("ItemAssetTemplate.txt", "MyItemAsset.cs"); + string Path = RM_Editor.CreateScriptTemplate("ItemAssetTemplate.txt", "MyItemAsset.cs"); } [MenuItem("Assets/Create/Scripting/RealMethod/Asset/Data/TableAsset", false, 80)] public static void CreateTableAsset() { - string Path = RealMethod.CreateScriptTemplate("TableTemplate.txt", "MyTableAsset.cs"); + string Path = RM_Editor.CreateScriptTemplate("TableTemplate.txt", "MyTableAsset.cs"); } [MenuItem("Assets/Create/Scripting/RealMethod/Asset/Data/Task", false, 80)] public static void CreateTaskAsset() { - string Path = RealMethod.CreateScriptTemplate("TaskAssetTemplate.txt", "MyTaskAsset.cs"); + string Path = RM_Editor.CreateScriptTemplate("TaskAssetTemplate.txt", "MyTaskAsset.cs"); } // // Config [MenuItem("Assets/Create/Scripting/RealMethod/Asset/Config/BaseConfig", false, 80)] public static void CreateConfigAsset() { - string Path = RealMethod.CreateScriptTemplate("ConfigAssetTemplate.txt", "MyConfigAsset.cs"); + string Path = RM_Editor.CreateScriptTemplate("ConfigAssetTemplate.txt", "MyConfigAsset.cs"); } [MenuItem("Assets/Create/Scripting/RealMethod/Asset/Config/ItemConfig", false, 80)] public static void CreateItemConfig() { - string Path = RealMethod.CreateScriptTemplate("ItemConfigTemplate.txt", "MyItemConfig.cs"); + string Path = RM_Editor.CreateScriptTemplate("ItemConfigTemplate.txt", "MyItemConfig.cs"); } [MenuItem("Assets/Create/Scripting/RealMethod/Asset/Config/GameConfig", false, 80)] public static void CreateGameConfig() { - string Path = RealMethod.CreateScriptTemplate("GameConfigTemplate.txt", "MyGameConfig.cs"); + string Path = RM_Editor.CreateScriptTemplate("GameConfigTemplate.txt", "MyGameConfig.cs"); } [MenuItem("Assets/Create/Scripting/RealMethod/Asset/Config/HapticConfig", false, 80)] public static void CreateHapticConfig() { - string Path = RealMethod.CreateScriptTemplate("HapticConfigTemplate.txt", "MyHaptic.cs"); + string Path = RM_Editor.CreateScriptTemplate("HapticConfigTemplate.txt", "MyHaptic.cs"); } // // Files [MenuItem("Assets/Create/Scripting/RealMethod/Asset/File/BaseFile", false, 80)] public static void CreateFileAsset() { - string Path = RealMethod.CreateScriptTemplate("FileAssetTemplate.txt", "MyFileAsset.cs"); + string Path = RM_Editor.CreateScriptTemplate("FileAssetTemplate.txt", "MyFileAsset.cs"); } [MenuItem("Assets/Create/Scripting/RealMethod/Asset/File/SaveFile", false, 80)] public static void CreateSaveFile() { - string Path = RealMethod.CreateScriptTemplate("SaveFileTemplate.txt", "MySaveFile.cs"); + string Path = RM_Editor.CreateScriptTemplate("SaveFileTemplate.txt", "MySaveFile.cs"); } [MenuItem("Assets/Create/Scripting/RealMethod/Asset/File/GameSetting", false, 80)] public static void CreateGameSettingFile() { - string Path = RealMethod.CreateScriptTemplate("GameSettingFileTemplate.txt", "GameSettingFile.cs"); + string Path = RM_Editor.CreateScriptTemplate("GameSettingFileTemplate.txt", "GameSettingFile.cs"); } // // Unique [MenuItem("Assets/Create/Scripting/RealMethod/Asset/Unique/BaseUnique", false, 80)] public static void CreateUniqueAsset() { - string Path = RealMethod.CreateScriptTemplate("UniqueAssetTemplate.txt", "MyFileAsset.cs"); + string Path = RM_Editor.CreateScriptTemplate("UniqueAssetTemplate.txt", "MyFileAsset.cs"); } [MenuItem("Assets/Create/Scripting/RealMethod/Asset/Unique/SharedRootAsset", false, 80)] public static void CreateSharedRootAsset() { - string Path = RealMethod.CreateScriptTemplate("SharedRootAssetTemplate.txt", "MySharedRootAsset.cs"); + string Path = RM_Editor.CreateScriptTemplate("SharedRootAssetTemplate.txt", "MySharedRootAsset.cs"); } [MenuItem("Assets/Create/Scripting/RealMethod/Asset/Unique/PoolAsset", false, 80)] public static void CreatePoolAsset() { - string Path = RealMethod.CreateScriptTemplate("PoolAssetTemplate.txt", "MyPoolAsset.cs"); + string Path = RM_Editor.CreateScriptTemplate("PoolAssetTemplate.txt", "MyPoolAsset.cs"); } // General @@ -169,29 +169,29 @@ public static void CreatePoolAsset() [MenuItem("Assets/Create/Scripting/RealMethod/General/UI/Widget", false, 80)] public static void CreateWidget() { - string Path = RealMethod.CreateScriptTemplate("WidgetTemplate.txt", "MyWidget.cs"); + string Path = RM_Editor.CreateScriptTemplate("WidgetTemplate.txt", "MyWidget.cs"); } [MenuItem("Assets/Create/Scripting/RealMethod/General/UI/WidgetToolkit", false, 80)] public static void CreateWidgetToolkit() { - string Path = RealMethod.CreateScriptTemplate("WidgetToolkitTemplate.txt", "MyWidgetToolkit.cs"); + string Path = RM_Editor.CreateScriptTemplate("WidgetToolkitTemplate.txt", "MyWidgetToolkit.cs"); } // // Command [MenuItem("Assets/Create/Scripting/RealMethod/General/Command", false, 80)] public static void CreateCommand() { - string Path = RealMethod.CreateScriptTemplate("CommandTemplate.txt", "MyCommand.cs"); + string Path = RM_Editor.CreateScriptTemplate("CommandTemplate.txt", "MyCommand.cs"); } // // Trigger [MenuItem("Assets/Create/Scripting/RealMethod/General/Trigger/Trigger3D", false, 80)] public static void CreateTrigger3D() { - string Path = RealMethod.CreateScriptTemplate("Trigger3DTemplate.txt", "MyTrigger.cs"); + string Path = RM_Editor.CreateScriptTemplate("Trigger3DTemplate.txt", "MyTrigger.cs"); } [MenuItem("Assets/Create/Scripting/RealMethod/General/Trigger/Trigger2D", false, 80)] public static void CreateTrigger2D() { - string Path = RealMethod.CreateScriptTemplate("Trigger2DTemplate.txt", "MyTrigger.cs"); + string Path = RM_Editor.CreateScriptTemplate("Trigger2DTemplate.txt", "MyTrigger.cs"); } @@ -199,7 +199,7 @@ public static void CreateTrigger2D() [MenuItem("Assets/Create/Scripting/RealMethod/Editor/SettingSection", false, 80)] public static void CreateSettingSection() { - string Path = RealMethod.CreateScriptTemplate("SettingSectionTemplate.txt", "MySection.cs"); + string Path = RM_Editor.CreateScriptTemplate("SettingSectionTemplate.txt", "MySection.cs"); } diff --git a/Editor/ReadySet/Tools/AnimatorScriptGenerator.cs b/Editor/ReadySet/Tools/AnimatorScriptGenerator.cs index 3be0806..230cc17 100644 --- a/Editor/ReadySet/Tools/AnimatorScriptGenerator.cs +++ b/Editor/ReadySet/Tools/AnimatorScriptGenerator.cs @@ -14,7 +14,7 @@ public class AnimatorScriptGenerator public static void GenerateScriptsFromAnimators() { ProjectSettingAsset TargetStorage; - if (RealMethod.GetSettingStorage(out TargetStorage)) + if (RM_Editor.GetSettingStorage(out TargetStorage)) { outputFolder = TargetStorage.GetFolderPathByType(ProjectSettingAsset.AssetFormat.Script) + "/General/AnimatorParam"; } diff --git a/Editor/Toolkit/Ability/Ability_ScriptTemplate.cs b/Editor/Toolkit/Ability/Ability_ScriptTemplate.cs index ded2dba..d9cb8d5 100644 --- a/Editor/Toolkit/Ability/Ability_ScriptTemplate.cs +++ b/Editor/Toolkit/Ability/Ability_ScriptTemplate.cs @@ -7,17 +7,17 @@ class Ability_ScriptTemplate [MenuItem("Assets/Create/Scripting/RealMethod/Toolkit/Ability/AbilityAsset", false, 80)] public static void CreateAbilityAsset() { - string Path = RealMethod.CreateScriptTemplate("AbilityAssetTemplate.txt", "MyAbility.cs"); + string Path = RM_Editor.CreateScriptTemplate("AbilityAssetTemplate.txt", "MyAbility.cs"); } [MenuItem("Assets/Create/Scripting/RealMethod/Toolkit/Ability/AbilityActionAsset", false, 80)] public static void CreateAbilityAction() { - string Path = RealMethod.CreateScriptTemplate("AbilityActionAssetTemplate.txt", "MyAbilityAction.cs"); + string Path = RM_Editor.CreateScriptTemplate("AbilityActionAssetTemplate.txt", "MyAbilityAction.cs"); } [MenuItem("Assets/Create/Scripting/RealMethod/Toolkit/Ability/Effect", false, 80)] public static void CreateEffect() { - string Path = RealMethod.CreateScriptTemplate("AbilityEffectTemplate.txt", "MyEffect.cs"); + string Path = RM_Editor.CreateScriptTemplate("AbilityEffectTemplate.txt", "MyEffect.cs"); } } } \ No newline at end of file diff --git a/Editor/Toolkit/Actor/Actor_ScriptTemplate.cs b/Editor/Toolkit/Actor/Actor_ScriptTemplate.cs index 6aa14f0..120dc11 100644 --- a/Editor/Toolkit/Actor/Actor_ScriptTemplate.cs +++ b/Editor/Toolkit/Actor/Actor_ScriptTemplate.cs @@ -7,7 +7,7 @@ class Actor_ScriptTemplate [MenuItem("Assets/Create/Scripting/RealMethod/Toolkit/Actor/Act", false, 80)] public static void CreateActCommand() { - string Path = RealMethod.CreateScriptTemplate("ActTemplate.txt", "MyAct.cs"); + string Path = RM_Editor.CreateScriptTemplate("ActTemplate.txt", "MyAct.cs"); } } } \ No newline at end of file diff --git a/Editor/Toolkit/Inventory/Inventory_ScriptTemplate.cs b/Editor/Toolkit/Inventory/Inventory_ScriptTemplate.cs index 0f5d837..eb7eebf 100644 --- a/Editor/Toolkit/Inventory/Inventory_ScriptTemplate.cs +++ b/Editor/Toolkit/Inventory/Inventory_ScriptTemplate.cs @@ -7,7 +7,7 @@ class Inventory_ScriptTemplate [MenuItem("Assets/Create/Scripting/RealMethod/Toolkit/Inventory/Item", false, 80)] public static void CreateItem() { - string Path = RealMethod.CreateScriptTemplate("InventoryItemTemplate.txt", "MyItem.cs"); + string Path = RM_Editor.CreateScriptTemplate("InventoryItemTemplate.txt", "MyItem.cs"); } } } \ No newline at end of file diff --git a/Editor/Toolkit/PCG/PCG_ScriptTemplate.cs b/Editor/Toolkit/PCG/PCG_ScriptTemplate.cs index 5a23ee4..ee20e90 100644 --- a/Editor/Toolkit/PCG/PCG_ScriptTemplate.cs +++ b/Editor/Toolkit/PCG/PCG_ScriptTemplate.cs @@ -7,7 +7,7 @@ class PCG_ScriptTemplate [MenuItem("Assets/Create/Scripting/RealMethod/Toolkit/PCG/Request", false, 80)] public static void CreatePCGRequest() { - string Path = RealMethod.CreateScriptTemplate("PCGRequestTamplate.txt", "MyRequest.cs"); + string Path = RM_Editor.CreateScriptTemplate("PCGRequestTamplate.txt", "MyRequest.cs"); } } } \ No newline at end of file diff --git a/Editor/Toolkit/Pickup/Pickup_ScriptTemplate.cs b/Editor/Toolkit/Pickup/Pickup_ScriptTemplate.cs index cd06536..b445ae2 100644 --- a/Editor/Toolkit/Pickup/Pickup_ScriptTemplate.cs +++ b/Editor/Toolkit/Pickup/Pickup_ScriptTemplate.cs @@ -7,12 +7,12 @@ class Pickup_ScriptTemplate [MenuItem("Assets/Create/Scripting/RealMethod/Toolkit/Pickup/Pickup3D", false, 80)] public static void CreatePickup3D() { - string Path = RealMethod.CreateScriptTemplate("Pickup3DTemplate.txt", "MyPickup.cs"); + string Path = RM_Editor.CreateScriptTemplate("Pickup3DTemplate.txt", "MyPickup.cs"); } [MenuItem("Assets/Create/Scripting/RealMethod/Toolkit/Pickup/Pickup2D", false, 80)] public static void CreatePickup2D() { - string Path = RealMethod.CreateScriptTemplate("Pickup2DTemplate.txt", "MyPickup.cs"); + string Path = RM_Editor.CreateScriptTemplate("Pickup2DTemplate.txt", "MyPickup.cs"); } } } \ No newline at end of file diff --git a/Editor/Toolkit/RPG/RPG_ScriptTemplate.cs b/Editor/Toolkit/RPG/RPG_ScriptTemplate.cs index 6dc3daf..0a1f5c5 100644 --- a/Editor/Toolkit/RPG/RPG_ScriptTemplate.cs +++ b/Editor/Toolkit/RPG/RPG_ScriptTemplate.cs @@ -7,22 +7,22 @@ class RPG_ScriptTemplate [MenuItem("Assets/Create/Scripting/RealMethod/Toolkit/RPG/StatDefinition", false, 80)] public static void CreateStatDefinition() { - string Path = RealMethod.CreateScriptTemplate("StatDefinitionTemplate.txt", "StatDefinition.cs"); + string Path = RM_Editor.CreateScriptTemplate("StatDefinitionTemplate.txt", "StatDefinition.cs"); } [MenuItem("Assets/Create/Scripting/RealMethod/Toolkit/RPG/StatProfile", false, 80)] public static void CreateStatProfile() { - string Path = RealMethod.CreateScriptTemplate("StatProfileTemplate.txt", "MyProfile.cs"); + string Path = RM_Editor.CreateScriptTemplate("StatProfileTemplate.txt", "MyProfile.cs"); } [MenuItem("Assets/Create/Scripting/RealMethod/Toolkit/RPG/StatBuff", false, 80)] public static void CreateBuffConfig() { - string Path = RealMethod.CreateScriptTemplate("BuffConfigTemplate.txt", "MyBuff.cs"); + string Path = RM_Editor.CreateScriptTemplate("BuffConfigTemplate.txt", "MyBuff.cs"); } [MenuItem("Assets/Create/Scripting/RealMethod/Toolkit/RPG/ResourceData", false, 80)] public static void CreateResourceData() { - string Path = RealMethod.CreateScriptTemplate("ResourceDataTemplate.txt", "MyResource.cs"); + string Path = RM_Editor.CreateScriptTemplate("ResourceDataTemplate.txt", "MyResource.cs"); } } diff --git a/Editor/Toolkit/Tutorial/Tutorial_ScriptTemplate.cs b/Editor/Toolkit/Tutorial/Tutorial_ScriptTemplate.cs index b6d7095..b853459 100644 --- a/Editor/Toolkit/Tutorial/Tutorial_ScriptTemplate.cs +++ b/Editor/Toolkit/Tutorial/Tutorial_ScriptTemplate.cs @@ -7,19 +7,19 @@ class Tutorial_ScriptTemplate [MenuItem("Assets/Create/Scripting/RealMethod/Toolkit/Tutorial/ScreenWidget", false, 80)] public static void CreateTutorialScreen() { - string Path = RealMethod.CreateScriptTemplate("TutorialScreenTemplate.txt", "MyTutorialScreen.cs"); + string Path = RM_Editor.CreateScriptTemplate("TutorialScreenTemplate.txt", "MyTutorialScreen.cs"); } [MenuItem("Assets/Create/Scripting/RealMethod/Toolkit/Tutorial/UIunit", false, 80)] public static void CreateTutorialMessage() { - string Path = RealMethod.CreateScriptTemplate("TutorialUnitTemplate.txt", "MyTutorialUnit.cs"); + string Path = RM_Editor.CreateScriptTemplate("TutorialUnitTemplate.txt", "MyTutorialUnit.cs"); } [MenuItem("Assets/Create/Scripting/RealMethod/Toolkit/Tutorial/Config", false, 80)] public static void CreateTutorialConfig() { - string Path = RealMethod.CreateScriptTemplate("TutorialConfigTemplate.txt", "MyTutorialConfig.cs"); + string Path = RM_Editor.CreateScriptTemplate("TutorialConfigTemplate.txt", "MyTutorialConfig.cs"); } } } \ No newline at end of file diff --git a/Editor/Toolkit/Upgrade/Upgrade_ScriptTemplate.cs b/Editor/Toolkit/Upgrade/Upgrade_ScriptTemplate.cs index deb14f9..033240b 100644 --- a/Editor/Toolkit/Upgrade/Upgrade_ScriptTemplate.cs +++ b/Editor/Toolkit/Upgrade/Upgrade_ScriptTemplate.cs @@ -7,12 +7,12 @@ class Upgrade_ScriptTemplate [MenuItem("Assets/Create/Scripting/RealMethod/Toolkit/Upgrade/ItemAsset", false, 80)] public static void CreateItem() { - string Path = RealMethod.CreateScriptTemplate("UpgradeItemTemplate.txt", "MyUpgradeAsset.cs"); + string Path = RM_Editor.CreateScriptTemplate("UpgradeItemTemplate.txt", "MyUpgradeAsset.cs"); } [MenuItem("Assets/Create/Scripting/RealMethod/Toolkit/Upgrade/MapConfig", false, 80)] public static void CreateConfig() { - string Path = RealMethod.CreateScriptTemplate("UpgradeConfigTemplate.txt", "MyUpgradeConfig.cs"); + string Path = RM_Editor.CreateScriptTemplate("UpgradeConfigTemplate.txt", "MyUpgradeConfig.cs"); } } } \ No newline at end of file From c9bcc37e9783161f3ddeb968bb461117fd8b8346 Mon Sep 17 00:00:00 2001 From: Alijimpa Date: Thu, 26 Mar 2026 14:14:11 +0330 Subject: [PATCH 050/204] Implement GameState --- .../Core/Attribute/ProjectSettingProvider.cs | 2 +- .../Attribute/Sections/GameStatus_Section.cs | 73 ++++++--- Editor/Core/Drawers/SettingEnumDrawer.cs | 42 +++-- Editor/Core/Utilities/Editor_Library.cs | 2 +- .../ReadySet/Tools/AnimatorScriptGenerator.cs | 2 +- Runtime/Core/Architecture/Game.cs | 15 +- Runtime/Core/Definitions/SettingEnum.cs | 151 +++++++++++------- .../ProjectSetting/ProjectSettingAsset.cs | 21 +-- 8 files changed, 193 insertions(+), 115 deletions(-) diff --git a/Editor/Core/Attribute/ProjectSettingProvider.cs b/Editor/Core/Attribute/ProjectSettingProvider.cs index 37d8e6a..8db0e67 100644 --- a/Editor/Core/Attribute/ProjectSettingProvider.cs +++ b/Editor/Core/Attribute/ProjectSettingProvider.cs @@ -172,7 +172,7 @@ public static SettingsProvider CreateSettingsProvider() ProjectSettingAsset TargetStorage = null; // Attempt to load the settings asset - if (!RM_Editor.GetSettingStorage(out TargetStorage)) + if (!RM_Editor.TryGetSettingAsset(out TargetStorage)) { if (Directory.Exists(Path.GetDirectoryName(RM_Editor.SetttingAssetPath))) { diff --git a/Editor/Core/Attribute/Sections/GameStatus_Section.cs b/Editor/Core/Attribute/Sections/GameStatus_Section.cs index 02eb65b..d69423b 100644 --- a/Editor/Core/Attribute/Sections/GameStatus_Section.cs +++ b/Editor/Core/Attribute/Sections/GameStatus_Section.cs @@ -7,8 +7,32 @@ namespace RealMethod.Editor { public class GameStatus_Section : ProjectSettingSection { - private ProjectSettingAsset settings; - static List names = new List(); + private ProjectSettingAsset SettingAsset; + private SerializedObject projectSettings; + private List MyList + { + get + { + if (SettingAsset == null) + { + //Error("SettingAsset Can't find"); + return new List(0); + } + return SettingAsset.Status; + } + + set + { + if (SettingAsset != null) + { + SettingAsset.Status = value; + } + else + { + //Error("SettingAsset Can't find"); + } + } + } protected override string GetTitle() @@ -25,44 +49,53 @@ protected override void Initialized() } protected override void BeginRender(ProjectSettingAsset Storage) { - settings = Storage; - if (settings != null && names.Count == 0) - names.AddRange(settings.GetStatus()); + SettingAsset = Storage; + projectSettings = new SerializedObject(Storage); } protected override void UpdateRender() { - EditorGUI.BeginChangeCheck(); - int newSize = Mathf.Max(0, EditorGUILayout.IntField("Size", names.Count)); + EditorGUILayout.BeginHorizontal(); + EditorGUILayout.Space(5); + int newSize = Mathf.Max(0, EditorGUILayout.IntField("Size", MyList.Count)); + EditorGUILayout.EndHorizontal(); - while (names.Count < newSize) - names.Add(""); + while (MyList.Count < newSize) + MyList.Add(""); - while (names.Count > newSize) - names.RemoveAt(names.Count - 1); + while (MyList.Count > newSize) + MyList.RemoveAt(MyList.Count - 1); - for (int i = 0; i < names.Count; i++) + for (int i = 0; i < MyList.Count; i++) { - names[i] = EditorGUILayout.TextField($"Element {i}", names[i]); + MyList[i] = EditorGUILayout.TextField($"Element {i}", MyList[i]); } if (EditorGUI.EndChangeCheck()) { - if (settings != null) + if (projectSettings != null) { - Undo.RecordObject(settings, "Modify Game Status Names"); - - settings.SetStatus(names.ToArray()); - - EditorUtility.SetDirty(settings); + Undo.RecordObject(SettingAsset, "Modify Game Status Names"); + EditorUtility.SetDirty(SettingAsset); } } + + if (GUI.changed) + { + projectSettings.ApplyModifiedProperties(); + EditorUtility.SetDirty(SettingAsset); // Mark ScriptableObject dirty + AssetDatabase.SaveAssets(); // Optional: saves to disk immediately + AssetDatabase.Refresh(); + } + + projectSettings.ApplyModifiedProperties(); + } protected override void Fix(int Id) { - + ClearError(); } diff --git a/Editor/Core/Drawers/SettingEnumDrawer.cs b/Editor/Core/Drawers/SettingEnumDrawer.cs index 4ad993c..d73097a 100644 --- a/Editor/Core/Drawers/SettingEnumDrawer.cs +++ b/Editor/Core/Drawers/SettingEnumDrawer.cs @@ -6,21 +6,37 @@ namespace RealMethod.Editor [CustomPropertyDrawer(typeof(SettingEnum))] public class SettingEnumDrawer : PropertyDrawer { + private SerializedProperty MyParam = null; public override void OnGUI(Rect position, SerializedProperty property, GUIContent label) { - var valueProp = property.FindPropertyRelative("Value"); - - var ProjectSettings = AssetDatabase.LoadAssetAtPath("Assets/Resources/RealMethod/RealMethodSetting.asset"); - string[] names = ProjectSettings.GetStatus(); - - int index = valueProp.intValue; - - if (index >= names.Length) - index = 0; - - int newIndex = EditorGUI.Popup(position, label.text, index, names); - - valueProp.intValue = newIndex; + if (MyParam == null) + { + MyParam = property.FindPropertyRelative("Value"); + } + int index = MyParam.intValue; + if (RM_Editor.TryGetSettingAsset(out ProjectSettingAsset Setting)) + { + string[] names = Setting.Status.ToArray(); + if (index < names.Length && index >= 0) + { + int newIndex = EditorGUI.Popup(position, label.text, index, names); + MyParam.intValue = newIndex; + } + else + { + Color prevColor = GUI.color; + GUI.color = Color.red; // light blue + EditorGUI.LabelField(position, $"{label.text} [{index}]: Not Define!"); + GUI.color = prevColor; + } + } + else + { + Color prevColor = GUI.color; + GUI.color = Color.yellow; // light blue + EditorGUI.LabelField(position, $"{label.text} [{index}]: Can't load RealMethod ProjectSettingAsset."); + GUI.color = prevColor; + } } } } \ No newline at end of file diff --git a/Editor/Core/Utilities/Editor_Library.cs b/Editor/Core/Utilities/Editor_Library.cs index 1b274c5..d4cca11 100644 --- a/Editor/Core/Utilities/Editor_Library.cs +++ b/Editor/Core/Utilities/Editor_Library.cs @@ -11,7 +11,7 @@ public static class RM_Editor public static string PrefabTemplatePath => GetPackagePath("com.mustard.realmethod") + "/Reservoir/Prefabs"; public static string Documentation => GetPackagePath("com.mustard.realmethod") + "/Documentation/Information"; - public static bool GetSettingStorage(out ProjectSettingAsset settings) + public static bool TryGetSettingAsset(out ProjectSettingAsset settings) { // Attempt to load the settings asset from the specified path settings = AssetDatabase.LoadAssetAtPath(SetttingAssetPath); diff --git a/Editor/ReadySet/Tools/AnimatorScriptGenerator.cs b/Editor/ReadySet/Tools/AnimatorScriptGenerator.cs index 230cc17..5c03c5c 100644 --- a/Editor/ReadySet/Tools/AnimatorScriptGenerator.cs +++ b/Editor/ReadySet/Tools/AnimatorScriptGenerator.cs @@ -14,7 +14,7 @@ public class AnimatorScriptGenerator public static void GenerateScriptsFromAnimators() { ProjectSettingAsset TargetStorage; - if (RM_Editor.GetSettingStorage(out TargetStorage)) + if (RM_Editor.TryGetSettingAsset(out TargetStorage)) { outputFolder = TargetStorage.GetFolderPathByType(ProjectSettingAsset.AssetFormat.Script) + "/General/AnimatorParam"; } diff --git a/Runtime/Core/Architecture/Game.cs b/Runtime/Core/Architecture/Game.cs index 8f94abc..a996ab1 100644 --- a/Runtime/Core/Architecture/Game.cs +++ b/Runtime/Core/Architecture/Game.cs @@ -175,14 +175,17 @@ private static void InitializeGame() Debug.LogWarning("GameInstanceClass that was empty. DefaultGame Created"); Instance = RealObject.AddComponent(); } - if (typeof(Game).IsAssignableFrom(TargetClass)) - { - Instance = (Game)RealObject.AddComponent(TargetClass); - } else { - Debug.LogWarning($"Component of type {TargetClass} is not assignable from Game. DefaultGame Created"); - Instance = RealObject.AddComponent(); + if (typeof(Game).IsAssignableFrom(TargetClass)) + { + Instance = (Game)RealObject.AddComponent(TargetClass); + } + else + { + Debug.LogWarning($"Component of type {TargetClass} is not assignable from Game. DefaultGame Created"); + Instance = RealObject.AddComponent(); + } } Instance.OnProjectSeettingLoaded(ref ProjectSettings); diff --git a/Runtime/Core/Definitions/SettingEnum.cs b/Runtime/Core/Definitions/SettingEnum.cs index fd02e09..4bedbf6 100644 --- a/Runtime/Core/Definitions/SettingEnum.cs +++ b/Runtime/Core/Definitions/SettingEnum.cs @@ -45,73 +45,110 @@ public static implicit operator byte(SettingEnum status) { return (byte)status.Value; } - - -#if UNITY_EDITOR - public SettingEnum(string IndexName) + public static bool operator ==(SettingEnum a, SettingEnum b) { - byte result = 0; - var ProjectSettings = AssetDatabase.LoadAssetAtPath("Assets/Resources/RealMethod/RealMethodSetting.asset"); - if (ProjectSettings) - { - var names = ProjectSettings.GetStatus(); - if (names == null) - result = 0; - for (int i = 0; i < names.Length; i++) - { - if (names[i] == IndexName) - { - result = (byte)i; - } - } - } - else - { - result = 0; - } - Value = result; + return a.Value == b.Value; } - private string Name + public static bool operator !=(SettingEnum a, SettingEnum b) { - get - { - var ProjectSettings = AssetDatabase.LoadAssetAtPath("Assets/Resources/RealMethod/RealMethodSetting.asset"); - if (ProjectSettings) - { - var names = ProjectSettings.GetStatus(); - if (names == null || Value >= names.Length) - return "Undefined"; - return names[Value]; - } - else - { - return "Undefined"; - } - } + return a.Value != b.Value; } - public static implicit operator SettingEnum(string val) + public static bool operator <(SettingEnum a, SettingEnum b) { - return new SettingEnum(val); + return a.Value < b.Value; + } + public static bool operator >(SettingEnum a, SettingEnum b) + { + return a.Value > b.Value; + } + public static bool operator <=(SettingEnum a, SettingEnum b) + { + return a.Value <= b.Value; } - public static implicit operator string(SettingEnum status) + public static bool operator >=(SettingEnum a, SettingEnum b) { - var ProjectSettings = AssetDatabase.LoadAssetAtPath("Assets/Resources/RealMethod/RealMethodSetting.asset"); - if (ProjectSettings) - { - var names = ProjectSettings.GetStatus(); - if (names == null || status.Value >= names.Length) - return "Undefined"; - return names[status.Value]; - } - else - { - return "Undefined"; - } + return a.Value >= b.Value; } + + public override string ToString() { - return Name; + return $"SettingEnum index [{Value}]"; } -#endif + public override bool Equals(object obj) + { + return obj is SettingEnum other && other.Value == Value; + } + public override int GetHashCode() + { + return Value.GetHashCode(); + } + + + // #if UNITY_EDITOR + // public SettingEnum(string IndexName) + // { + // byte result = 0; + // var ProjectSettings = AssetDatabase.LoadAssetAtPath("Assets/Resources/RealMethod/RealMethodSetting.asset"); + // if (ProjectSettings) + // { + // var names = ProjectSettings.Status; + // if (names == null) + // result = 0; + // for (int i = 0; i < names.Count; i++) + // { + // if (names[i] == IndexName) + // { + // result = (byte)i; + // } + // } + // } + // else + // { + // result = 0; + // } + // Value = result; + // } + // private string Name + // { + // get + // { + // var ProjectSettings = AssetDatabase.LoadAssetAtPath("Assets/Resources/RealMethod/RealMethodSetting.asset"); + // if (ProjectSettings) + // { + // var names = ProjectSettings.Status; + // if (names == null || Value >= names.Count) + // return "Undefined"; + // return names[Value]; + // } + // else + // { + // return "Undefined"; + // } + // } + // } + // public static implicit operator SettingEnum(string val) + // { + // return new SettingEnum(val); + // } + // public static implicit operator string(SettingEnum status) + // { + // var ProjectSettings = AssetDatabase.LoadAssetAtPath("Assets/Resources/RealMethod/RealMethodSetting.asset"); + // if (ProjectSettings) + // { + // var names = ProjectSettings.Status; + // if (names == null || status.Value >= names.Count) + // return "Undefined"; + // return names[status.Value]; + // } + // else + // { + // return "Undefined"; + // } + // } + // #endif + + + } } \ No newline at end of file diff --git a/Runtime/Core/ProjectSetting/ProjectSettingAsset.cs b/Runtime/Core/ProjectSetting/ProjectSettingAsset.cs index ff9169a..e72629e 100644 --- a/Runtime/Core/ProjectSetting/ProjectSettingAsset.cs +++ b/Runtime/Core/ProjectSetting/ProjectSettingAsset.cs @@ -1,6 +1,5 @@ using System; using System.Collections.Generic; -using UnityEditor; using UnityEngine; namespace RealMethod @@ -43,7 +42,7 @@ public string GetFolderPath(ProjectSettingAsset settingAsset) [Header("Initializer")] [SerializeField, ReadOnly] - public string GameClass = string.Empty; // <-- this name must match + private string GameClass = string.Empty; // <-- this name must match [SerializeField, ReadOnly] private string GameBridge = string.Empty; // <-- this name must match [SerializeField] @@ -82,9 +81,11 @@ public string GetFolderPath(ProjectSettingAsset settingAsset) new FolderAddress { AssetType = (AssetFormat)13, AssetPath = "7_Misc"} }; public IReadOnlyList FolderStructure => folderStructure; +#endif + +#if UNITY_EDITOR [Header("GameStatus")] - [SerializeField] - private string[] Status; + public List Status = new List(4) { "Menu", "Playing", "Pause", "GameOver" }; #endif @@ -95,8 +96,6 @@ protected virtual void OnEnable() GameClass = typeof(DefultGame).AssemblyQualifiedName; if (string.IsNullOrEmpty(GameBridge)) GameBridge = typeof(DefaultGameBridge).AssemblyQualifiedName; - if (Status == null || Status.Length == 0) - Status = new string[4] { "Menu", "Playing", "Pause", "GameOver" }; } protected virtual void Reset() { @@ -104,8 +103,6 @@ protected virtual void Reset() GameClass = typeof(DefultGame).AssemblyQualifiedName; if (string.IsNullOrEmpty(GameBridge)) GameBridge = typeof(DefaultGameBridge).AssemblyQualifiedName; - if (Status == null || Status.Length == 0) - Status = new string[4] { "Menu", "Playing", "Pause", "GameOver" }; } @@ -150,14 +147,6 @@ public string GetFolderPathByType(AssetFormat identity) } public FolderAddress GetFolderAddressByIndex(int index) => folderStructure[index]; public void SetFolderAddressPath(int index, string value) => folderStructure[index].AssetPath = value; - public string[] GetStatus() => Status; - public void SetStatus(string[] NewStatus) - { - if (NewStatus != null) - { - Status = NewStatus; - } - } #endif #if UNITY_SERVER || UNITY_EDITOR From fe1072081eb44ebcb857ecc634671b0abf6e6131 Mon Sep 17 00:00:00 2001 From: Alijimpa Date: Fri, 27 Mar 2026 17:20:48 +0330 Subject: [PATCH 051/204] Refine Core Scritps --- Editor/Core/Inspectors/GameEditor.cs | 14 +-- Runtime/Core/Architecture/Game.cs | 23 ++--- Runtime/Core/Architecture/World.cs | 26 +++++- Runtime/Core/Definitions/SettingEnum.cs | 90 +++++-------------- .../ProjectSetting/ProjectSettingAsset.cs | 1 + 5 files changed, 70 insertions(+), 84 deletions(-) diff --git a/Editor/Core/Inspectors/GameEditor.cs b/Editor/Core/Inspectors/GameEditor.cs index c5db306..d65498a 100644 --- a/Editor/Core/Inspectors/GameEditor.cs +++ b/Editor/Core/Inspectors/GameEditor.cs @@ -1,3 +1,4 @@ +using System.Linq; using UnityEditor; namespace RealMethod.Editor @@ -17,12 +18,15 @@ public override void OnInspectorGUI() EditorGUILayout.Space(); if (BaseComponent != null) { - EditorGUILayout.LabelField($"{GetWorld()} | {GetSetvice()} | {GetConfig()}"); + EditorGUILayout.LabelField($"GameStat: {Game.State}"); + EditorGUILayout.LabelField($"{GetWorld()} | {GetBrgidge()} | {GetConfig()}"); EditorGUILayout.Space(0.5f); - string[] Data = BaseComponent.GetAllServiceNames(); - for (int i = 0; i < Data.Length; i++) + string[] Services = BaseComponent.GetAllServiceNames(); + string[] Managers = BaseComponent.gameObject.GetComponents().Select(c => c.GetManagerClass().name).ToArray(); + string[] WorldManagers = Game.World.gameObject.GetComponents().Select(c => c.GetManagerClass().name).ToArray(); + for (int i = 0; i < Services.Length; i++) { - EditorGUILayout.LabelField($"{i + 1}. {Data[i]}"); + EditorGUILayout.LabelField($"{i + 1}. {Services[i]}"); } } } @@ -31,7 +35,7 @@ private string GetWorld() { return Game.World != null ? Game.World.GetType().Name : "World Not Valid"; } - private string GetSetvice() + private string GetBrgidge() { return Game.Bridge != null ? Game.Bridge.GetType().Name : "GameBridge Not Valid"; } diff --git a/Runtime/Core/Architecture/Game.cs b/Runtime/Core/Architecture/Game.cs index a996ab1..5ab7f10 100644 --- a/Runtime/Core/Architecture/Game.cs +++ b/Runtime/Core/Architecture/Game.cs @@ -198,23 +198,26 @@ private static void InitializeGame() Debug.LogWarning($"GetGameBridgeType that was empty. DefaultGameBridge Created"); Bridge = new DefaultGameBridge(); } - if (typeof(Service).IsAssignableFrom(targetService)) + else { - try + if (typeof(GameBridge).IsAssignableFrom(targetService)) { - Bridge = (GameBridge)Activator.CreateInstance(targetService); + try + { + Bridge = (GameBridge)Activator.CreateInstance(targetService); + } + catch (Exception ex) + { + Debug.LogError($"Failed to instantiate {targetService}: {ex.Message}. DefaultGameBridge Created"); + Bridge = new DefaultGameBridge(); + } } - catch (Exception ex) + else { - Debug.LogError($"Failed to instantiate {targetService}: {ex.Message}. DefaultGameBridge Created"); + Debug.LogWarning($"Type {targetService} is not assignable to GameBridge. DefaultGameBridge Created"); Bridge = new DefaultGameBridge(); } } - else - { - Debug.LogWarning($"Type {targetService} is not assignable to Service. DefaultGameBridge Created"); - Bridge = new DefaultGameBridge(); - } Instance.Services = new List(3); ((IRelationBridge)Bridge).BindWorldCreated(Instance.Notify_OnWorldInitiate); ((IService)Bridge).Created(Instance); diff --git a/Runtime/Core/Architecture/World.cs b/Runtime/Core/Architecture/World.cs index 5353fba..8571f5f 100644 --- a/Runtime/Core/Architecture/World.cs +++ b/Runtime/Core/Architecture/World.cs @@ -108,7 +108,7 @@ private void Awake() Managers = new IGameManager[CashManagers.Count]; Managers = CashManagers.ToArray(); - //Find Player or Create newone + // Find Player or Create newone var scneplayer = GetPlayerInScene(); if (scneplayer == null) { @@ -121,11 +121,31 @@ private void Awake() PlayerObject = scneplayer; } + // Reset Location of World + transform.position = Vector3.zero; + transform.rotation = Quaternion.identity; + WorldBegin(); SyncProvider.WorldIsReady(); } - - +#if UNITY_EDITOR + /// + /// Called EveryFrame to Insure World position + /// + private void LateUpdate() + { + if (transform.position != Vector3.zero) + { + Debug.LogError("World position should not be changed!"); + transform.position = Vector3.zero; + } + if (transform.rotation != Quaternion.identity) + { + Debug.LogError("World rotation should not be changed!"); + transform.rotation = Quaternion.identity; + } + } +#endif /// /// Unity callback invoked when the object is being destroyed. /// Unbinds previously bound service callbacks to avoid dangling references. diff --git a/Runtime/Core/Definitions/SettingEnum.cs b/Runtime/Core/Definitions/SettingEnum.cs index 4bedbf6..b0bb060 100644 --- a/Runtime/Core/Definitions/SettingEnum.cs +++ b/Runtime/Core/Definitions/SettingEnum.cs @@ -71,10 +71,7 @@ public static implicit operator byte(SettingEnum status) } - public override string ToString() - { - return $"SettingEnum index [{Value}]"; - } + public override bool Equals(object obj) { return obj is SettingEnum other && other.Value == Value; @@ -85,68 +82,29 @@ public override int GetHashCode() } - // #if UNITY_EDITOR - // public SettingEnum(string IndexName) - // { - // byte result = 0; - // var ProjectSettings = AssetDatabase.LoadAssetAtPath("Assets/Resources/RealMethod/RealMethodSetting.asset"); - // if (ProjectSettings) - // { - // var names = ProjectSettings.Status; - // if (names == null) - // result = 0; - // for (int i = 0; i < names.Count; i++) - // { - // if (names[i] == IndexName) - // { - // result = (byte)i; - // } - // } - // } - // else - // { - // result = 0; - // } - // Value = result; - // } - // private string Name - // { - // get - // { - // var ProjectSettings = AssetDatabase.LoadAssetAtPath("Assets/Resources/RealMethod/RealMethodSetting.asset"); - // if (ProjectSettings) - // { - // var names = ProjectSettings.Status; - // if (names == null || Value >= names.Count) - // return "Undefined"; - // return names[Value]; - // } - // else - // { - // return "Undefined"; - // } - // } - // } - // public static implicit operator SettingEnum(string val) - // { - // return new SettingEnum(val); - // } - // public static implicit operator string(SettingEnum status) - // { - // var ProjectSettings = AssetDatabase.LoadAssetAtPath("Assets/Resources/RealMethod/RealMethodSetting.asset"); - // if (ProjectSettings) - // { - // var names = ProjectSettings.Status; - // if (names == null || status.Value >= names.Count) - // return "Undefined"; - // return names[status.Value]; - // } - // else - // { - // return "Undefined"; - // } - // } - // #endif +#if UNITY_EDITOR + public override string ToString() + { + var ProjectSettings = AssetDatabase.LoadAssetAtPath("Assets/Resources/RealMethod/RealMethodSetting.asset"); + if (ProjectSettings) + { + var names = ProjectSettings.Status; + if (names == null || Value >= names.Count) + return "Undefined"; + return names[Value]; + } + else + { + return $"SettingEnum index [{Value}]"; + } + + } +#else + public override string ToString() + { + return $"SettingEnum index [{Value}]"; + } +#endif diff --git a/Runtime/Core/ProjectSetting/ProjectSettingAsset.cs b/Runtime/Core/ProjectSetting/ProjectSettingAsset.cs index e72629e..82e78e2 100644 --- a/Runtime/Core/ProjectSetting/ProjectSettingAsset.cs +++ b/Runtime/Core/ProjectSetting/ProjectSettingAsset.cs @@ -85,6 +85,7 @@ public string GetFolderPath(ProjectSettingAsset settingAsset) #if UNITY_EDITOR [Header("GameStatus")] + [ReadOnly] public List Status = new List(4) { "Menu", "Playing", "Pause", "GameOver" }; #endif From 14b329cf6d3394094459242beafe290251082111 Mon Sep 17 00:00:00 2001 From: Alijimpa Date: Fri, 27 Mar 2026 18:27:46 +0330 Subject: [PATCH 052/204] Refine Prefab Classes --- Editor/Core/Drawers/PrefabCoreDrawer.cs | 2 +- Runtime/Core/Architecture/World.cs | 2 +- Runtime/Core/Definitions/Prefab.cs | 24 ++++++++++++++-------- Runtime/Library/Extension/GameObject.cs | 22 ++++++++++++++++++++ Runtime/ReadySet/Services/SpawanService.cs | 17 +++++++-------- 5 files changed, 49 insertions(+), 18 deletions(-) diff --git a/Editor/Core/Drawers/PrefabCoreDrawer.cs b/Editor/Core/Drawers/PrefabCoreDrawer.cs index 37f4363..6966919 100644 --- a/Editor/Core/Drawers/PrefabCoreDrawer.cs +++ b/Editor/Core/Drawers/PrefabCoreDrawer.cs @@ -49,7 +49,7 @@ public override void OnGUI(Rect position, SerializedProperty property, GUIConten return; } - var targetClass = targetPrefab.GetTargetClass(); + var targetClass = targetPrefab.GetMainType(); GameObject go = newObject as GameObject; // Type-check: the prefab must have the required component diff --git a/Runtime/Core/Architecture/World.cs b/Runtime/Core/Architecture/World.cs index 8571f5f..ab85834 100644 --- a/Runtime/Core/Architecture/World.cs +++ b/Runtime/Core/Architecture/World.cs @@ -282,7 +282,7 @@ protected virtual GameObject SpawnPlayer(Prefab playerPrefab, Transform spawnPoi { if (playerPrefab.IsValid()) { - Transform player = Instantiate(playerPrefab.GetSoftClassTarget(), spawnPoint.position, spawnPoint.rotation); + Transform player = Instantiate(playerPrefab.GetMainComponent(), spawnPoint.position, spawnPoint.rotation); player.SendMessage("OnSpawn", this, SendMessageOptions.DontRequireReceiver); return player.gameObject; } diff --git a/Runtime/Core/Definitions/Prefab.cs b/Runtime/Core/Definitions/Prefab.cs index 5923624..753a7bb 100644 --- a/Runtime/Core/Definitions/Prefab.cs +++ b/Runtime/Core/Definitions/Prefab.cs @@ -8,16 +8,18 @@ namespace RealMethod public abstract class PrefabCore : IIdentifier { [SerializeField] - private GameObject PrefabAsset; // <-- this name must match + protected GameObject PrefabAsset; // <-- this name must match public GameObject asset => PrefabAsset; + + // Implement IIdentidier Interface public Name16 NameID => PrefabAsset != null ? PrefabAsset.name : "Empty"; // Public Functions - public J GetSoftClass() where J : Component + public J GetSoftComponent() where J : Component { return PrefabAsset.GetComponent(); } - public J[] GetAllSoftClass() where J : Component + public J[] GetSoftComponentsInChildren() where J : Component { return PrefabAsset.GetComponentsInChildren(); } @@ -26,9 +28,15 @@ public bool HasInterface() return PrefabAsset.GetComponent() != null; } + // Operator + public static implicit operator GameObject(PrefabCore prefab) + { + return prefab.PrefabAsset; + } + // Abstract Methods public abstract bool IsValid(); - public abstract System.Type GetTargetClass(); // <--- added + public abstract System.Type GetMainType(); // <--- added } // Prefab Class [System.Serializable] @@ -37,14 +45,14 @@ public class PrefabCore : PrefabCore where T : Component // PrefabCore Methods public override bool IsValid() { - return asset != null && asset.GetComponent() != null; + return PrefabAsset != null && PrefabAsset.GetComponent() != null; } - public override System.Type GetTargetClass() => typeof(T); // <--- implemented + public override System.Type GetMainType() => typeof(T); // <--- implemented // Public Method - public T GetSoftClassTarget() + public T GetMainComponent() { - return asset.GetComponent(); + return PrefabAsset.GetComponent(); } } diff --git a/Runtime/Library/Extension/GameObject.cs b/Runtime/Library/Extension/GameObject.cs index 2accc5b..b4164dd 100644 --- a/Runtime/Library/Extension/GameObject.cs +++ b/Runtime/Library/Extension/GameObject.cs @@ -1,6 +1,10 @@ using UnityEngine; using System.Reflection; +#if UNITY_EDITOR +using UnityEditor; +#endif + namespace RealMethod { public static class GameObject_Extension @@ -63,5 +67,23 @@ public static TComponent CopyComponent(this GameObject desitation, T } return copy as TComponent; } + +#if UNITY_EDITOR + public static bool IsPrefabAsset(this GameObject obj) + { + return PrefabUtility.GetPrefabAssetType(obj) != PrefabAssetType.NotAPrefab + && PrefabUtility.GetPrefabInstanceStatus(obj) == PrefabInstanceStatus.NotAPrefab; + } + public static bool IsPrefabInstance(this GameObject obj) + { + return PrefabUtility.GetPrefabInstanceStatus(obj) == PrefabInstanceStatus.Connected; + } + public static bool IsSceneObject(this GameObject obj) + { + return PrefabUtility.GetPrefabAssetType(obj) == PrefabAssetType.NotAPrefab + && obj.scene.IsValid(); + } +#endif + } } \ No newline at end of file diff --git a/Runtime/ReadySet/Services/SpawanService.cs b/Runtime/ReadySet/Services/SpawanService.cs index 35f97a8..7b67cd6 100644 --- a/Runtime/ReadySet/Services/SpawanService.cs +++ b/Runtime/ReadySet/Services/SpawanService.cs @@ -160,6 +160,7 @@ public static GameObject Widget(UPrefab Prefab, string Name, Object spawner = nu { if (instance.GameUI != null) { + //if(Prefab) return instance.GameUI.AddLayer(Name, Prefab, spawner); } else @@ -506,52 +507,52 @@ public static T Prefab(PrefabCore prefab, Object spawner = null) where T : { if (spawner != null) { - T target = Object.Instantiate(prefab.GetSoftClassTarget()); + T target = Object.Instantiate(prefab.GetMainComponent()); target.SendSpawnEvent(spawner); return target; } else { - return Object.Instantiate(prefab.GetSoftClassTarget()); + return Object.Instantiate(prefab.GetMainComponent()); } } public static T Prefab(PrefabCore prefab, Transform parent, Object spawner = null) where T : Component { if (spawner != null) { - T target = Object.Instantiate(prefab.GetSoftClassTarget(), parent); + T target = Object.Instantiate(prefab.GetMainComponent(), parent); target.SendSpawnEvent(spawner); return target; } else { - return Object.Instantiate(prefab.GetSoftClassTarget(), parent); + return Object.Instantiate(prefab.GetMainComponent(), parent); } } public static T Prefab(PrefabCore prefab, Vector3 position, Quaternion rotation, Object spawner = null) where T : Component { if (spawner != null) { - T target = Object.Instantiate(prefab.GetSoftClassTarget(), position, rotation); + T target = Object.Instantiate(prefab.GetMainComponent(), position, rotation); target.SendSpawnEvent(spawner); return target; } else { - return Object.Instantiate(prefab.GetSoftClassTarget(), position, rotation); + return Object.Instantiate(prefab.GetMainComponent(), position, rotation); } } public static T Prefab(PrefabCore prefab, Transform parent, bool worldPositionStays, Object spawner = null) where T : Component { if (spawner != null) { - T target = Object.Instantiate(prefab.GetSoftClassTarget(), parent, worldPositionStays); + T target = Object.Instantiate(prefab.GetMainComponent(), parent, worldPositionStays); target.SendSpawnEvent(spawner); return target; } else { - return Object.Instantiate(prefab.GetSoftClassTarget(), parent, worldPositionStays); + return Object.Instantiate(prefab.GetMainComponent(), parent, worldPositionStays); } } From 5c1ec76e28e95027ba277fd8abcfa68f2ced001f Mon Sep 17 00:00:00 2001 From: Alijimpa Date: Fri, 27 Mar 2026 18:39:37 +0330 Subject: [PATCH 053/204] Refine PrefabCore Class --- Runtime/Core/Definitions/Prefab.cs | 4 ++- Runtime/Library/Extension/GameObject.cs | 20 +++++++++--- Runtime/Pattern/Managers/CompositManager.cs | 2 +- Runtime/Pattern/Managers/UIManager.cs | 4 +-- Runtime/ReadySet/Services/SpawanService.cs | 34 ++++++++++----------- Runtime/Toolkit/Tutorial/TutorialConfig.cs | 2 +- 6 files changed, 39 insertions(+), 27 deletions(-) diff --git a/Runtime/Core/Definitions/Prefab.cs b/Runtime/Core/Definitions/Prefab.cs index 753a7bb..c8b7948 100644 --- a/Runtime/Core/Definitions/Prefab.cs +++ b/Runtime/Core/Definitions/Prefab.cs @@ -9,7 +9,6 @@ public abstract class PrefabCore : IIdentifier { [SerializeField] protected GameObject PrefabAsset; // <-- this name must match - public GameObject asset => PrefabAsset; // Implement IIdentidier Interface public Name16 NameID => PrefabAsset != null ? PrefabAsset.name : "Empty"; @@ -28,6 +27,9 @@ public bool HasInterface() return PrefabAsset.GetComponent() != null; } + // Override Functions + public override int GetHashCode() => PrefabAsset != null ? PrefabAsset.GetHashCode() : 0; + // Operator public static implicit operator GameObject(PrefabCore prefab) { diff --git a/Runtime/Library/Extension/GameObject.cs b/Runtime/Library/Extension/GameObject.cs index b4164dd..a318c55 100644 --- a/Runtime/Library/Extension/GameObject.cs +++ b/Runtime/Library/Extension/GameObject.cs @@ -68,6 +68,18 @@ public static TComponent CopyComponent(this GameObject desitation, T return copy as TComponent; } +#if UNITY_EDITOR + public static bool IsInScene(this GameObject obj) + { + return PrefabUtility.GetPrefabAssetType(obj) == PrefabAssetType.NotAPrefab + && obj.scene.IsValid(); + } +#else + public static bool IsInScene(this GameObject obj) + { + return obj.scene.IsValid() && obj.scene.name != null; + } +#endif #if UNITY_EDITOR public static bool IsPrefabAsset(this GameObject obj) { @@ -78,12 +90,10 @@ public static bool IsPrefabInstance(this GameObject obj) { return PrefabUtility.GetPrefabInstanceStatus(obj) == PrefabInstanceStatus.Connected; } - public static bool IsSceneObject(this GameObject obj) - { - return PrefabUtility.GetPrefabAssetType(obj) == PrefabAssetType.NotAPrefab - && obj.scene.IsValid(); - } #endif + + + } } \ No newline at end of file diff --git a/Runtime/Pattern/Managers/CompositManager.cs b/Runtime/Pattern/Managers/CompositManager.cs index d59914b..1c7651c 100644 --- a/Runtime/Pattern/Managers/CompositManager.cs +++ b/Runtime/Pattern/Managers/CompositManager.cs @@ -88,7 +88,7 @@ public void AddLayer(string layerName, APrefab prefab) Debug.LogWarning($"Layer '{layerName}' already exists. Use a different name."); return; } - AudioSource source = Instantiate(prefab.asset, transform).GetComponent(); + AudioSource source = Instantiate(prefab, transform).GetComponent(); Layers.Add(layerName, source); } public void CreateLayer(AudioClip clip) diff --git a/Runtime/Pattern/Managers/UIManager.cs b/Runtime/Pattern/Managers/UIManager.cs index 9a35082..65b1997 100644 --- a/Runtime/Pattern/Managers/UIManager.cs +++ b/Runtime/Pattern/Managers/UIManager.cs @@ -204,7 +204,7 @@ public T CreateLayer(string name, VisualTreeAsset UIAsset, Object creator = n } public GameObject AddLayer(string name, UPrefab Prefab, Object spawner = null) { - GameObject SpawnedObject = Instantiate(Prefab.asset, header.position, Quaternion.identity, header); + GameObject SpawnedObject = Instantiate(Prefab, header.position, Quaternion.identity, header); if (spawner != null) { SpawnedObject.SendSpawnEvent(spawner); @@ -224,7 +224,7 @@ public T AddLayer(string name, UPrefab Prefab, Object spawner = null) where T Debug.LogError($"Prefab should has Widget Class Component"); return null; } - GameObject SpawnedObject = Instantiate(Prefab.asset, header.position, Quaternion.identity, header); + GameObject SpawnedObject = Instantiate(Prefab, header.position, Quaternion.identity, header); if (spawner != null) { SpawnedObject.SendSpawnEvent(spawner); diff --git a/Runtime/ReadySet/Services/SpawanService.cs b/Runtime/ReadySet/Services/SpawanService.cs index 7b67cd6..349ed64 100644 --- a/Runtime/ReadySet/Services/SpawanService.cs +++ b/Runtime/ReadySet/Services/SpawanService.cs @@ -402,104 +402,104 @@ public static GameObject Prefab(PrefabCore prefab, Object spawner = null) { if (spawner != null) { - GameObject target = Object.Instantiate(prefab.asset, Game.World.transform); + GameObject target = Object.Instantiate(prefab, Game.World.transform); target.SendSpawnEvent(spawner); return target; } else { - return Object.Instantiate(prefab.asset, Game.World.transform); + return Object.Instantiate(prefab, Game.World.transform); } } public static GameObject Prefab(PrefabCore prefab, Transform parent, Object spawner = null) { if (spawner != null) { - GameObject target = Object.Instantiate(prefab.asset, parent); + GameObject target = Object.Instantiate(prefab, parent); target.SendSpawnEvent(spawner); return target; } else { - return Object.Instantiate(prefab.asset, parent); + return Object.Instantiate(prefab, parent); } } public static GameObject Prefab(PrefabCore prefab, Transform parent, bool instantiateInWorldSpace, Object spawner = null) { if (spawner != null) { - GameObject target = Object.Instantiate(prefab.asset, parent, instantiateInWorldSpace); + GameObject target = Object.Instantiate(prefab, parent, instantiateInWorldSpace); target.SendSpawnEvent(spawner); return target; } else { - return Object.Instantiate(prefab.asset, parent, instantiateInWorldSpace); + return Object.Instantiate(prefab, parent, instantiateInWorldSpace); } } public static GameObject Prefab(PrefabCore prefab, Vector3 position, Vector3 rotation, Object spawner = null) { if (spawner != null) { - GameObject target = Object.Instantiate(prefab.asset, position, Quaternion.Euler(rotation)); + GameObject target = Object.Instantiate(prefab, position, Quaternion.Euler(rotation)); target.SendSpawnEvent(spawner); return target; } else { - return Object.Instantiate(prefab.asset, position, Quaternion.Euler(rotation)); + return Object.Instantiate(prefab, position, Quaternion.Euler(rotation)); } } public static GameObject Prefab(PrefabCore prefab, Vector3 position, Quaternion rotation, Object spawner = null) { if (spawner != null) { - GameObject target = Object.Instantiate(prefab.asset, position, rotation); + GameObject target = Object.Instantiate(prefab, position, rotation); target.SendSpawnEvent(spawner); return target; } else { - return Object.Instantiate(prefab.asset, position, rotation); + return Object.Instantiate(prefab, position, rotation); } } public static GameObject Prefab(PrefabCore prefab, Vector3 position, Object spawner = null) { if (spawner != null) { - GameObject target = Object.Instantiate(prefab.asset, position, Quaternion.identity); + GameObject target = Object.Instantiate(prefab, position, Quaternion.identity); target.SendSpawnEvent(spawner); return target; } else { - return Object.Instantiate(prefab.asset, position, Quaternion.identity); + return Object.Instantiate(prefab, position, Quaternion.identity); } } public static GameObject Prefab(PrefabCore prefab, Vector3 position, Vector3 rotation, Transform parent, Object spawner = null) { if (spawner != null) { - GameObject target = Object.Instantiate(prefab.asset, position, Quaternion.Euler(rotation), parent); + GameObject target = Object.Instantiate(prefab, position, Quaternion.Euler(rotation), parent); target.SendSpawnEvent(spawner); return target; } else { - return Object.Instantiate(prefab.asset, position, Quaternion.Euler(rotation), parent); + return Object.Instantiate(prefab, position, Quaternion.Euler(rotation), parent); } } public static GameObject Prefab(PrefabCore prefab, UnityEngine.SceneManagement.Scene scene, Object spawner = null) { if (spawner != null) { - GameObject target = Object.Instantiate(prefab.asset, scene) as GameObject; + GameObject target = Object.Instantiate(prefab, scene) as GameObject; target.SendSpawnEvent(spawner); return target; } else { - return Object.Instantiate(prefab.asset, scene) as GameObject; + return Object.Instantiate(prefab, scene) as GameObject; } } @@ -681,7 +681,7 @@ public static T Command(CPrefab prefab, MonoBehaviour owner, Object author) w Debug.LogWarning($" {instance}: Owner or Author is not available."); return null; } - GameObject SpawnedObject = Object.Instantiate(prefab.asset, owner.transform); + GameObject SpawnedObject = Object.Instantiate(prefab, owner.transform); T TargetCommand = SpawnedObject.GetComponent(); if (!TargetCommand.GetComponent().Initiate(author, owner)) { diff --git a/Runtime/Toolkit/Tutorial/TutorialConfig.cs b/Runtime/Toolkit/Tutorial/TutorialConfig.cs index f436a01..7652366 100644 --- a/Runtime/Toolkit/Tutorial/TutorialConfig.cs +++ b/Runtime/Toolkit/Tutorial/TutorialConfig.cs @@ -91,7 +91,7 @@ public class TutorialConfig : TutorialConfigCore // Implement TutorialConfigCore protected override UI_TutorialUnit InstantiateMessageObject(Transform parent) { - return Instantiate(tutorialPrefab.asset, parent).GetComponent(); + return Instantiate(tutorialPrefab, parent).GetComponent(); } #if UNITY_EDITOR From 4cfc27c9a35a2eef14ef4988a763c569f60bc770 Mon Sep 17 00:00:00 2001 From: Alijimpa Date: Fri, 27 Mar 2026 19:00:13 +0330 Subject: [PATCH 054/204] Implement Asset Drawer for Editor --- Editor/Core/Drawers/AssetsDrawer.cs | 17 +++++++++++++++++ Editor/Core/Drawers/AssetsDrawer.cs.meta | 2 ++ Editor/Core/Drawers/PrefabCoreDrawer.cs | 1 - 3 files changed, 19 insertions(+), 1 deletion(-) create mode 100644 Editor/Core/Drawers/AssetsDrawer.cs create mode 100644 Editor/Core/Drawers/AssetsDrawer.cs.meta diff --git a/Editor/Core/Drawers/AssetsDrawer.cs b/Editor/Core/Drawers/AssetsDrawer.cs new file mode 100644 index 0000000..c772820 --- /dev/null +++ b/Editor/Core/Drawers/AssetsDrawer.cs @@ -0,0 +1,17 @@ +using UnityEditor; +using UnityEngine; + +namespace RealMethod.Editor +{ + [CustomPropertyDrawer(typeof(PrimitiveAsset), true)] + public class Asset_Drawer : PropertyDrawer + { + public override void OnGUI(Rect position, SerializedProperty property, GUIContent label) + { + Color prevColor = GUI.color; + GUI.color = new Color(1f, 0.8f, 0.8f); + EditorGUI.PropertyField(position, property, label, true); + GUI.color = prevColor; + } + } +} \ No newline at end of file diff --git a/Editor/Core/Drawers/AssetsDrawer.cs.meta b/Editor/Core/Drawers/AssetsDrawer.cs.meta new file mode 100644 index 0000000..5f2cec9 --- /dev/null +++ b/Editor/Core/Drawers/AssetsDrawer.cs.meta @@ -0,0 +1,2 @@ +fileFormatVersion: 2 +guid: a177970772cd9c04184171cfabfc6ae9 \ No newline at end of file diff --git a/Editor/Core/Drawers/PrefabCoreDrawer.cs b/Editor/Core/Drawers/PrefabCoreDrawer.cs index 6966919..9035615 100644 --- a/Editor/Core/Drawers/PrefabCoreDrawer.cs +++ b/Editor/Core/Drawers/PrefabCoreDrawer.cs @@ -1,6 +1,5 @@ using UnityEditor; using UnityEngine; -using System; namespace RealMethod.Editor { From 252535377baafa19f4aa7f602076ca25e86552b4 Mon Sep 17 00:00:00 2001 From: Alijimpa Date: Sun, 29 Mar 2026 13:42:10 +0330 Subject: [PATCH 055/204] Refine SceneRefrence to Scene Asset and GloablEnum --- ...ttingEnumDrawer.cs => GlobalEnumDrawer.cs} | 4 +- ...rawer.cs.meta => GlobalEnumDrawer.cs.meta} | 0 Editor/Core/Drawers/SceneAssetDrawer.cs | 68 ++++++++++ Editor/Core/Drawers/SceneAssetDrawer.cs.meta | 2 + Runtime/Core/Architecture/Game.cs | 6 +- Runtime/Core/Architecture/World.cs | 12 +- Runtime/Core/Architecture/WorldSceneConfig.cs | 10 +- .../{SettingEnum.cs => GlobalEnum.cs} | 32 ++--- ...SettingEnum.cs.meta => GlobalEnum.cs.meta} | 0 Runtime/Core/Definitions/SceneAsset.cs | 62 ++++++++++ ...neReference.cs.meta => SceneAsset.cs.meta} | 0 Runtime/Core/Definitions/SceneReference.cs | 116 ------------------ .../ReadySet/Commands/Execut/C_ScneLoader.cs | 2 +- Runtime/ReadySet/Managers/DebugManager.cs | 4 + Runtime/ReadySet/Managers/PrintManager.cs | 2 + Tests/General/MissionManager.cs | 3 +- 16 files changed, 176 insertions(+), 147 deletions(-) rename Editor/Core/Drawers/{SettingEnumDrawer.cs => GlobalEnumDrawer.cs} (93%) rename Editor/Core/Drawers/{SettingEnumDrawer.cs.meta => GlobalEnumDrawer.cs.meta} (100%) create mode 100644 Editor/Core/Drawers/SceneAssetDrawer.cs create mode 100644 Editor/Core/Drawers/SceneAssetDrawer.cs.meta rename Runtime/Core/Definitions/{SettingEnum.cs => GlobalEnum.cs} (67%) rename Runtime/Core/Definitions/{SettingEnum.cs.meta => GlobalEnum.cs.meta} (100%) create mode 100644 Runtime/Core/Definitions/SceneAsset.cs rename Runtime/Core/Definitions/{SceneReference.cs.meta => SceneAsset.cs.meta} (100%) delete mode 100644 Runtime/Core/Definitions/SceneReference.cs diff --git a/Editor/Core/Drawers/SettingEnumDrawer.cs b/Editor/Core/Drawers/GlobalEnumDrawer.cs similarity index 93% rename from Editor/Core/Drawers/SettingEnumDrawer.cs rename to Editor/Core/Drawers/GlobalEnumDrawer.cs index d73097a..a163ff2 100644 --- a/Editor/Core/Drawers/SettingEnumDrawer.cs +++ b/Editor/Core/Drawers/GlobalEnumDrawer.cs @@ -3,8 +3,8 @@ namespace RealMethod.Editor { - [CustomPropertyDrawer(typeof(SettingEnum))] - public class SettingEnumDrawer : PropertyDrawer + [CustomPropertyDrawer(typeof(GlobalEnum))] + public class GlobalEnumDrawer : PropertyDrawer { private SerializedProperty MyParam = null; public override void OnGUI(Rect position, SerializedProperty property, GUIContent label) diff --git a/Editor/Core/Drawers/SettingEnumDrawer.cs.meta b/Editor/Core/Drawers/GlobalEnumDrawer.cs.meta similarity index 100% rename from Editor/Core/Drawers/SettingEnumDrawer.cs.meta rename to Editor/Core/Drawers/GlobalEnumDrawer.cs.meta diff --git a/Editor/Core/Drawers/SceneAssetDrawer.cs b/Editor/Core/Drawers/SceneAssetDrawer.cs new file mode 100644 index 0000000..9df5964 --- /dev/null +++ b/Editor/Core/Drawers/SceneAssetDrawer.cs @@ -0,0 +1,68 @@ +using UnityEditor; +using UnityEngine; +using UnityEngine.SceneManagement; + +namespace RealMethod.Editor +{ + [CustomPropertyDrawer(typeof(SceneAsset), true)] + public class SceneAssetDrawer : PropertyDrawer + { + private Texture2D checkIcon; + private Texture2D warningIcon; + + public override void OnGUI(Rect position, SerializedProperty property, GUIContent label) + { + // Load icons once + if (checkIcon == null) checkIcon = EditorGUIUtility.IconContent("TestPassed").image as Texture2D; + if (warningIcon == null) warningIcon = EditorGUIUtility.IconContent("console.warnicon").image as Texture2D; + + SerializedProperty sceneAssetProp = property.FindPropertyRelative("Asset"); + SerializedProperty scenePathProp = property.FindPropertyRelative("ScenePath"); + + EditorGUI.BeginProperty(position, label, property); + + // Restrict to SceneAsset type + Rect objectFieldRect = new Rect(position.x, position.y, position.width - 20, position.height); + EditorGUI.PropertyField(objectFieldRect, sceneAssetProp, label); + + if (sceneAssetProp.objectReferenceValue != null) + { + string path = AssetDatabase.GetAssetPath(sceneAssetProp.objectReferenceValue); + scenePathProp.stringValue = path; + + bool isInBuild = IsSceneInBuild(path); + + // Icon display + Rect iconRect = new Rect(position.x + position.width - 16, position.y + 2, 16, 16); + GUI.DrawTexture(iconRect, isInBuild ? checkIcon : warningIcon); + + // Tooltip if not included + if (!isInBuild) + { + GUIContent warningContent = new GUIContent("", "Scene is NOT in the active Build Profile.\nAdd it via File > Build Profiles."); + EditorGUI.LabelField(iconRect, warningContent); + } + } + else + { + scenePathProp.stringValue = string.Empty; + } + + EditorGUI.EndProperty(); + } + + private bool IsSceneInBuild(string scenePath) + { + for (int i = 0; i < SceneManager.sceneCountInBuildSettings; i++) + { + string listedScenePath = SceneUtility.GetScenePathByBuildIndex(i); + if (listedScenePath == scenePath) + return true; + } + return false; + } + } +} + + + diff --git a/Editor/Core/Drawers/SceneAssetDrawer.cs.meta b/Editor/Core/Drawers/SceneAssetDrawer.cs.meta new file mode 100644 index 0000000..77fc6bd --- /dev/null +++ b/Editor/Core/Drawers/SceneAssetDrawer.cs.meta @@ -0,0 +1,2 @@ +fileFormatVersion: 2 +guid: 17b36a74fca686a45a451a08879dfe1c \ No newline at end of file diff --git a/Runtime/Core/Architecture/Game.cs b/Runtime/Core/Architecture/Game.cs index 5ab7f10..3361f5e 100644 --- a/Runtime/Core/Architecture/Game.cs +++ b/Runtime/Core/Architecture/Game.cs @@ -71,7 +71,7 @@ public static GameObject Player /// /// Reperesent Game State that youser can define state in ProjectSetting /// - public static SettingEnum State { get; private set; } = 0; + public static GlobalEnum State { get; private set; } = 0; /// /// Indicates whether a scene or world load operation is currently in progress. /// @@ -511,7 +511,7 @@ public static Coroutine OpenScene(int sceneIndex) /// /// Reference describing the scene to load. /// A driving the load operation, or null if not started. - public static Coroutine OpenScene(SceneReference scene) + public static Coroutine OpenScene(SceneAsset scene) { return OpenScene(scene.ScneName); } @@ -555,7 +555,7 @@ public static void AddScene(int sceneIndex, Action callback) /// /// Reference describing the scene to load. /// callback event when scene complitly added - public static void AddScene(SceneReference scene, Action callback) + public static void AddScene(SceneAsset scene, Action callback) { AddScene(scene.ScneName, callback); } diff --git a/Runtime/Core/Architecture/World.cs b/Runtime/Core/Architecture/World.cs index ab85834..c60464d 100644 --- a/Runtime/Core/Architecture/World.cs +++ b/Runtime/Core/Architecture/World.cs @@ -9,14 +9,18 @@ namespace RealMethod /// public abstract class PlayerStarter : MonoBehaviour { - [Header("Setting")] + [Header("Details")] [SerializeField] private string posName = "None"; public string PosName => posName; + +#if UNITY_EDITOR + [Header("Debug")] [SerializeField] private float height = 2f; [SerializeField] private float radius = 0.5f; +#endif private bool hasPlayer = false; @@ -55,7 +59,11 @@ public bool CanStartHere() #if UNITY_EDITOR protected virtual void OnDrawGizmos() { - RM_Gizmos.Capsule(transform.position, Color.cyan, height, radius); + bool blocked = Physics.CheckCapsule(transform.position, transform.position + Vector3.up * height, radius); + + Color c = blocked ? Color.red : Color.cyan; + + RM_Gizmos.Capsule(transform.position, c, height, radius); RM_Gizmos.Arrow(transform.position, transform.forward, Color.red); RM_Gizmos.Text(PosName, transform.position + (transform.up * (height / 2)) + (Vector3.up * 0.1f), Color.black); } diff --git a/Runtime/Core/Architecture/WorldSceneConfig.cs b/Runtime/Core/Architecture/WorldSceneConfig.cs index e8babb3..b53e965 100644 --- a/Runtime/Core/Architecture/WorldSceneConfig.cs +++ b/Runtime/Core/Architecture/WorldSceneConfig.cs @@ -19,16 +19,16 @@ public class WorldSceneConfig : ConfigAsset /// The persistent scene that is always loaded and acts as the base scene. /// [SerializeField] - private SceneReference persistent; + private SceneAsset persistent; /// /// Public getter for the persistent scene. /// - public SceneReference Persistent => persistent; + public SceneAsset Persistent => persistent; /// /// Array of additive layer scenes that can be loaded alongside the persistent scene. /// [SerializeField] - private SceneReference[] Layers; + private SceneAsset[] Layers; /// /// Gets the number of additive layer scenes. /// @@ -37,8 +37,8 @@ public class WorldSceneConfig : ConfigAsset /// Indexer to access additive layer scenes by index. /// /// Index of the layer scene. - /// The at the specified index. - public SceneReference this[int index] => Layers[index]; + /// The at the specified index. + public SceneAsset this[int index] => Layers[index]; diff --git a/Runtime/Core/Definitions/SettingEnum.cs b/Runtime/Core/Definitions/GlobalEnum.cs similarity index 67% rename from Runtime/Core/Definitions/SettingEnum.cs rename to Runtime/Core/Definitions/GlobalEnum.cs index b0bb060..bf157b4 100644 --- a/Runtime/Core/Definitions/SettingEnum.cs +++ b/Runtime/Core/Definitions/GlobalEnum.cs @@ -14,58 +14,58 @@ namespace RealMethod /// inside ProjectSettingsAsset that just compile in editor. /// [Serializable] - public struct SettingEnum + public struct GlobalEnum { [SerializeField] private int Value; // <-- this name must match - public SettingEnum(int index = 0) + public GlobalEnum(int index = 0) { Value = index; } - public SettingEnum(byte index = 0) + public GlobalEnum(byte index = 0) { Value = index; } - public static implicit operator SettingEnum(int val) + public static implicit operator GlobalEnum(int val) { - return new SettingEnum(val); + return new GlobalEnum(val); } - public static implicit operator int(SettingEnum status) + public static implicit operator int(GlobalEnum status) { return status.Value; } - public static implicit operator SettingEnum(byte val) + public static implicit operator GlobalEnum(byte val) { - return new SettingEnum(val); + return new GlobalEnum(val); } - public static implicit operator byte(SettingEnum status) + public static implicit operator byte(GlobalEnum status) { return (byte)status.Value; } - public static bool operator ==(SettingEnum a, SettingEnum b) + public static bool operator ==(GlobalEnum a, GlobalEnum b) { return a.Value == b.Value; } - public static bool operator !=(SettingEnum a, SettingEnum b) + public static bool operator !=(GlobalEnum a, GlobalEnum b) { return a.Value != b.Value; } - public static bool operator <(SettingEnum a, SettingEnum b) + public static bool operator <(GlobalEnum a, GlobalEnum b) { return a.Value < b.Value; } - public static bool operator >(SettingEnum a, SettingEnum b) + public static bool operator >(GlobalEnum a, GlobalEnum b) { return a.Value > b.Value; } - public static bool operator <=(SettingEnum a, SettingEnum b) + public static bool operator <=(GlobalEnum a, GlobalEnum b) { return a.Value <= b.Value; } - public static bool operator >=(SettingEnum a, SettingEnum b) + public static bool operator >=(GlobalEnum a, GlobalEnum b) { return a.Value >= b.Value; } @@ -74,7 +74,7 @@ public static implicit operator byte(SettingEnum status) public override bool Equals(object obj) { - return obj is SettingEnum other && other.Value == Value; + return obj is GlobalEnum other && other.Value == Value; } public override int GetHashCode() { diff --git a/Runtime/Core/Definitions/SettingEnum.cs.meta b/Runtime/Core/Definitions/GlobalEnum.cs.meta similarity index 100% rename from Runtime/Core/Definitions/SettingEnum.cs.meta rename to Runtime/Core/Definitions/GlobalEnum.cs.meta diff --git a/Runtime/Core/Definitions/SceneAsset.cs b/Runtime/Core/Definitions/SceneAsset.cs new file mode 100644 index 0000000..b36c46f --- /dev/null +++ b/Runtime/Core/Definitions/SceneAsset.cs @@ -0,0 +1,62 @@ +using System; +using UnityEngine; + +#if UNITY_EDITOR +using UnityEditor; +#endif + +namespace RealMethod +{ + [Serializable] + public class SceneAsset : ISerializationCallbackReceiver + { +#if UNITY_EDITOR + public UnityEditor.SceneAsset Asset; // Only in editor +#endif + public string ScenePath; + public string ScneName => System.IO.Path.GetFileNameWithoutExtension(ScenePath); + + + // Implement ISerializationCallbackReceiver Interface + public void OnBeforeSerialize() + { +#if UNITY_EDITOR + UpdateScenePath(); +#endif + } + public void OnAfterDeserialize() + { + } + + // Implicit conversion to string + public static implicit operator string(SceneAsset sceneReference) + { + return sceneReference?.ScenePath; + } + + +#if UNITY_EDITOR + private void UpdateScenePath() + { + if (Asset != null) + { + string newPath = AssetDatabase.GetAssetPath(Asset); + if (ScenePath != newPath) + { + ScenePath = newPath; + EditorUtility.SetDirty(Selection.activeObject); + } + } + else + { + ScenePath = string.Empty; + } + } +#endif + + + } +} + + + diff --git a/Runtime/Core/Definitions/SceneReference.cs.meta b/Runtime/Core/Definitions/SceneAsset.cs.meta similarity index 100% rename from Runtime/Core/Definitions/SceneReference.cs.meta rename to Runtime/Core/Definitions/SceneAsset.cs.meta diff --git a/Runtime/Core/Definitions/SceneReference.cs b/Runtime/Core/Definitions/SceneReference.cs deleted file mode 100644 index c27efe8..0000000 --- a/Runtime/Core/Definitions/SceneReference.cs +++ /dev/null @@ -1,116 +0,0 @@ -using System; -using UnityEngine; -using UnityEngine.SceneManagement; -#if UNITY_EDITOR -using UnityEditor; -#endif - -[Serializable] -public class SceneReference : ISerializationCallbackReceiver -{ -#if UNITY_EDITOR - public SceneAsset SceneAsset; // Only in editor -#endif - public string ScenePath; - public string ScneName => System.IO.Path.GetFileNameWithoutExtension(ScenePath); - - public void OnBeforeSerialize() - { -#if UNITY_EDITOR - UpdateScenePath(); -#endif - } - - public void OnAfterDeserialize() { } - -#if UNITY_EDITOR - private void UpdateScenePath() - { - if (SceneAsset != null) - { - string newPath = AssetDatabase.GetAssetPath(SceneAsset); - if (ScenePath != newPath) - { - ScenePath = newPath; - EditorUtility.SetDirty(Selection.activeObject); - } - } - else - { - ScenePath = string.Empty; - } - } -#endif - - // Implicit conversion to string - public static implicit operator string(SceneReference sceneReference) - { - return sceneReference?.ScenePath; - } -} - -#if UNITY_EDITOR -[CustomPropertyDrawer(typeof(SceneReference), true)] -public class CustomSceneReferencePropertyDrawer : PropertyDrawer -{ - private Texture2D checkIcon; - private Texture2D warningIcon; - - public override void OnGUI(Rect position, SerializedProperty property, GUIContent label) - { - // Load icons once - if (checkIcon == null) checkIcon = EditorGUIUtility.IconContent("TestPassed").image as Texture2D; - if (warningIcon == null) warningIcon = EditorGUIUtility.IconContent("console.warnicon").image as Texture2D; - - SerializedProperty sceneAssetProp = property.FindPropertyRelative("SceneAsset"); - SerializedProperty scenePathProp = property.FindPropertyRelative("ScenePath"); - - EditorGUI.BeginProperty(position, label, property); - - // Restrict to SceneAsset type - Rect objectFieldRect = new Rect(position.x, position.y, position.width - 20, position.height); - EditorGUI.PropertyField(objectFieldRect, sceneAssetProp, label); - - if (sceneAssetProp.objectReferenceValue != null) - { - string path = AssetDatabase.GetAssetPath(sceneAssetProp.objectReferenceValue); - scenePathProp.stringValue = path; - - bool isInBuild = IsSceneInBuild(path); - - // Icon display - Rect iconRect = new Rect(position.x + position.width - 16, position.y + 2, 16, 16); - GUI.DrawTexture(iconRect, isInBuild ? checkIcon : warningIcon); - - // Tooltip if not included - if (!isInBuild) - { - GUIContent warningContent = new GUIContent("", "Scene is NOT in the active Build Profile.\nAdd it via File > Build Profiles."); - EditorGUI.LabelField(iconRect, warningContent); - } - } - else - { - scenePathProp.stringValue = string.Empty; - } - - EditorGUI.EndProperty(); - } - - private bool IsSceneInBuild(string scenePath) - { - for (int i = 0; i < SceneManager.sceneCountInBuildSettings; i++) - { - string listedScenePath = SceneUtility.GetScenePathByBuildIndex(i); - if (listedScenePath == scenePath) - return true; - } - return false; - } -} -#endif - - - - - diff --git a/Runtime/ReadySet/Commands/Execut/C_ScneLoader.cs b/Runtime/ReadySet/Commands/Execut/C_ScneLoader.cs index f557d3f..38d2221 100644 --- a/Runtime/ReadySet/Commands/Execut/C_ScneLoader.cs +++ b/Runtime/ReadySet/Commands/Execut/C_ScneLoader.cs @@ -22,7 +22,7 @@ private enum LoadMethod [SerializeField, ShowInInspectorByEnum("method", 1)] private string sceneName; [SerializeField, ShowInInspectorByEnum("method", 2)] - private SceneReference sceneAsset; + private SceneAsset sceneAsset; [SerializeField, ShowInInspectorByEnum("method", 3)] private WorldSceneConfig worldAsset; [Header("Setting")] diff --git a/Runtime/ReadySet/Managers/DebugManager.cs b/Runtime/ReadySet/Managers/DebugManager.cs index 0ef0e1b..355782b 100644 --- a/Runtime/ReadySet/Managers/DebugManager.cs +++ b/Runtime/ReadySet/Managers/DebugManager.cs @@ -92,8 +92,10 @@ public class DebugManager : GUIManager [SerializeField] private Vector2 buttonSize = new Vector2(200, 40); public Vector2 ButtonSize => buttonSize; +#if UNITY_EDITOR || DEVELOPMENT_BUILD [SerializeField] private float buttonMargin = 20; +#endif // GUIManager Methods public override void InitiateManager(bool AlwaysLoaded) @@ -119,6 +121,7 @@ public bool Remove(IButton button) return DrawList.Remove(result); } +#if UNITY_EDITOR || DEVELOPMENT_BUILD protected override void PreDraw() { base.PreDraw(); @@ -139,6 +142,7 @@ protected override void PostDraw() base.PostDraw(); GUI.EndScrollView(); } +#endif } } \ No newline at end of file diff --git a/Runtime/ReadySet/Managers/PrintManager.cs b/Runtime/ReadySet/Managers/PrintManager.cs index 9ee164d..ffa5fec 100644 --- a/Runtime/ReadySet/Managers/PrintManager.cs +++ b/Runtime/ReadySet/Managers/PrintManager.cs @@ -189,6 +189,7 @@ public void SetSize(int newSize) printSize = newSize; } +#if UNITY_EDITOR || DEVELOPMENT_BUILD protected override void PreDraw() { base.PreDraw(); @@ -212,6 +213,7 @@ protected override void PostDraw() } } } +#endif } } diff --git a/Tests/General/MissionManager.cs b/Tests/General/MissionManager.cs index 7871e39..940eaaf 100644 --- a/Tests/General/MissionManager.cs +++ b/Tests/General/MissionManager.cs @@ -1,4 +1,3 @@ -using System.Collections; using UnityEngine; using UnityEngine.Events; using UnityEngine.UI; @@ -24,7 +23,7 @@ public abstract class MissionManager : MonoBehaviour, IGameManager public GameObject UI; public Animator playerStatusAnimator; public GameObject MissionPassUI; - public SceneReference HomeScene; + public SceneAsset HomeScene; [Header("Events")] public UnityEvent OnMissionCompleted; From 544f4ac516f86fa5dc22c6c0774ed7893bde4688 Mon Sep 17 00:00:00 2001 From: Alijimpa Date: Mon, 30 Mar 2026 01:08:42 +0330 Subject: [PATCH 056/204] Refine half of Attribute (LayerStillHasIsuee) --- .../Core/Attribute/ProjectSettingProvider.cs | 1 - Editor/Core/Drawers/ColorFieldDrawet.cs | 19 ++ Editor/Core/Drawers/ColorFieldDrawet.cs.meta | 2 + Editor/Core/Drawers/ConditionalHideDrawer.cs | 69 +++++ .../Drawers/ConditionalHideDrawer.cs.meta | 2 + .../Core/Drawers/DropdownFromArrayDrawer.cs | 53 ++++ .../Drawers/DropdownFromArrayDrawer.cs.meta | 2 + .../Drawers/DropdownFromDictionaryDrawer.cs | 60 +++++ .../DropdownFromDictionaryDrawer.cs.meta | 2 + .../Core/Drawers/DropdownFromStringsDrawer.cs | 34 +-- .../Drawers/DropdownFromStringsDrawer.cs.meta | 2 + Editor/Core/Drawers/EnumDescriptionDrawer.cs | 53 ++++ .../Drawers/EnumDescriptionDrawer.cs.meta | 2 + Editor/Core/Drawers/ExpandableDrawer.cs | 219 ++++++++++++++++ Editor/Core/Drawers/ExpandableDrawer.cs.meta | 2 + Editor/Core/Drawers/HelpBoxDrawer.cs | 30 +++ Editor/Core/Drawers/HelpBoxDrawer.cs.meta | 2 + Editor/Core/Drawers/LayerDrawer.cs | 21 ++ Editor/Core/Drawers/LayerDrawer.cs.meta | 2 + Editor/Core/Inspectors/ButtonEditor.cs | 30 +++ Editor/Core/Inspectors/ButtonEditor.cs.meta | 2 + Editor/Core/Inspectors/MonoBehaviourEditor.cs | 15 ++ .../Inspectors/MonoBehaviourEditor.cs.meta | 2 + .../Core/Inspectors/PrimitiveAssetEditor.cs | 11 + .../Inspectors/PrimitiveAssetEditor.cs.meta | 2 + ...setEditor.cs => ScriptableObjectEditor.cs} | 2 +- ...cs.meta => ScriptableObjectEditor.cs.meta} | 0 Runtime/Core/Attributes/ButtonAttribute.cs | 45 +--- .../Core/Attributes/ColorFieldAttribute.cs | 79 +----- .../Attributes/ConditionalHideAttribute.cs | 86 +----- .../Attributes/DropdownFromArrayAttribute.cs | 75 +----- .../DropdownFromDictionaryAttribute.cs | 86 +----- .../DropdownFromStringsAttribute.cs | 24 ++ ...a => DropdownFromStringsAttribute.cs.meta} | 0 .../Attributes/EnumDescriptionAttribute.cs | 83 +----- .../Core/Attributes/ExpandableAttribute.cs | 246 +----------------- Runtime/Core/Attributes/HelpBoxAttribute.cs | 57 +--- Runtime/Core/Attributes/LayerAttribute.cs | 38 +-- Tests/Editor/DelegateDisplayEditor.cs | 86 +++--- 39 files changed, 766 insertions(+), 780 deletions(-) create mode 100644 Editor/Core/Drawers/ColorFieldDrawet.cs create mode 100644 Editor/Core/Drawers/ColorFieldDrawet.cs.meta create mode 100644 Editor/Core/Drawers/ConditionalHideDrawer.cs create mode 100644 Editor/Core/Drawers/ConditionalHideDrawer.cs.meta create mode 100644 Editor/Core/Drawers/DropdownFromArrayDrawer.cs create mode 100644 Editor/Core/Drawers/DropdownFromArrayDrawer.cs.meta create mode 100644 Editor/Core/Drawers/DropdownFromDictionaryDrawer.cs create mode 100644 Editor/Core/Drawers/DropdownFromDictionaryDrawer.cs.meta rename Runtime/Core/Attributes/DropdownAttribute.cs => Editor/Core/Drawers/DropdownFromStringsDrawer.cs (61%) create mode 100644 Editor/Core/Drawers/DropdownFromStringsDrawer.cs.meta create mode 100644 Editor/Core/Drawers/EnumDescriptionDrawer.cs create mode 100644 Editor/Core/Drawers/EnumDescriptionDrawer.cs.meta create mode 100644 Editor/Core/Drawers/ExpandableDrawer.cs create mode 100644 Editor/Core/Drawers/ExpandableDrawer.cs.meta create mode 100644 Editor/Core/Drawers/HelpBoxDrawer.cs create mode 100644 Editor/Core/Drawers/HelpBoxDrawer.cs.meta create mode 100644 Editor/Core/Drawers/LayerDrawer.cs create mode 100644 Editor/Core/Drawers/LayerDrawer.cs.meta create mode 100644 Editor/Core/Inspectors/ButtonEditor.cs create mode 100644 Editor/Core/Inspectors/ButtonEditor.cs.meta create mode 100644 Editor/Core/Inspectors/MonoBehaviourEditor.cs create mode 100644 Editor/Core/Inspectors/MonoBehaviourEditor.cs.meta create mode 100644 Editor/Core/Inspectors/PrimitiveAssetEditor.cs create mode 100644 Editor/Core/Inspectors/PrimitiveAssetEditor.cs.meta rename Editor/Core/Inspectors/{DataAssetEditor.cs => ScriptableObjectEditor.cs} (93%) rename Editor/Core/Inspectors/{DataAssetEditor.cs.meta => ScriptableObjectEditor.cs.meta} (100%) create mode 100644 Runtime/Core/Attributes/DropdownFromStringsAttribute.cs rename Runtime/Core/Attributes/{DropdownAttribute.cs.meta => DropdownFromStringsAttribute.cs.meta} (100%) diff --git a/Editor/Core/Attribute/ProjectSettingProvider.cs b/Editor/Core/Attribute/ProjectSettingProvider.cs index 8db0e67..db94118 100644 --- a/Editor/Core/Attribute/ProjectSettingProvider.cs +++ b/Editor/Core/Attribute/ProjectSettingProvider.cs @@ -238,7 +238,6 @@ public static SettingsProvider CreateSettingsProvider() } - private static ProjectSettingAsset CreateSettingStorage() { // Create a new settings asset at the specified path diff --git a/Editor/Core/Drawers/ColorFieldDrawet.cs b/Editor/Core/Drawers/ColorFieldDrawet.cs new file mode 100644 index 0000000..0fa3b79 --- /dev/null +++ b/Editor/Core/Drawers/ColorFieldDrawet.cs @@ -0,0 +1,19 @@ +using UnityEditor; +using UnityEngine; + +namespace RealMethod.Editor +{ + [CustomPropertyDrawer(typeof(ColorFieldAttribute))] + public class RequiredFieldDrawer : PropertyDrawer + { + public override void OnGUI(Rect position, SerializedProperty property, GUIContent label) + { + ColorFieldAttribute field = attribute as ColorFieldAttribute; + + GUI.color = field.color; //Set the color of the GUI + EditorGUI.PropertyField(position, property, label); //Draw the GUI + GUI.color = Color.white; //Reset the color of the GUI to white + + } + } +} \ No newline at end of file diff --git a/Editor/Core/Drawers/ColorFieldDrawet.cs.meta b/Editor/Core/Drawers/ColorFieldDrawet.cs.meta new file mode 100644 index 0000000..658df02 --- /dev/null +++ b/Editor/Core/Drawers/ColorFieldDrawet.cs.meta @@ -0,0 +1,2 @@ +fileFormatVersion: 2 +guid: eeddf87aa2f38034791a447abc095062 \ No newline at end of file diff --git a/Editor/Core/Drawers/ConditionalHideDrawer.cs b/Editor/Core/Drawers/ConditionalHideDrawer.cs new file mode 100644 index 0000000..7d6df37 --- /dev/null +++ b/Editor/Core/Drawers/ConditionalHideDrawer.cs @@ -0,0 +1,69 @@ +using UnityEditor; +using UnityEngine; + +namespace RealMethod.Editor +{ + [CustomPropertyDrawer(typeof(ConditionalHideAttribute))] + public class ConditionalHidePropertyDrawer : PropertyDrawer + { + public override float GetPropertyHeight(SerializedProperty property, GUIContent label) + { + ConditionalHideAttribute condHAtt = (ConditionalHideAttribute)attribute; + bool enabled = GetConditionalHideAttributeResult(condHAtt, property); + + if (!condHAtt.HideInInspector || enabled) + { + return EditorGUI.GetPropertyHeight(property, label); + } + else + { + return -EditorGUIUtility.standardVerticalSpacing; + } + } + public override void OnGUI(Rect position, SerializedProperty property, GUIContent label) + { + ConditionalHideAttribute condHAtt = (ConditionalHideAttribute)attribute; + bool enabled = GetConditionalHideAttributeResult(condHAtt, property); + + bool wasEnabled = GUI.enabled; + GUI.enabled = enabled; + + if (!condHAtt.HideInInspector || enabled) + { + EditorGUI.PropertyField(position, property, label, true); + } + + GUI.enabled = wasEnabled; + } + + + + private bool GetConditionalHideAttributeResult(ConditionalHideAttribute condHAtt, SerializedProperty property) + { + bool enabled = true; + + string propertyPath = property.propertyPath; // returns the property path of the property we want to apply the attribute to + string conditionPath = propertyPath.Replace(property.name, condHAtt.ConditionalSourceField); // changes the path to the conditionalsource property path + SerializedProperty sourcePropertyValue = property.serializedObject.FindProperty(conditionPath); + + if (sourcePropertyValue != null) + { + if (!condHAtt.ReverceCondition) + { + enabled = sourcePropertyValue.boolValue; + } + else + { + enabled = !sourcePropertyValue.boolValue; + } + + } + else + { + Debug.LogWarning("Attempting to use a ConditionalHideAttribute but no matching SourcePropertyValue found in object: " + condHAtt.ConditionalSourceField); + } + + return enabled; + } + } +} \ No newline at end of file diff --git a/Editor/Core/Drawers/ConditionalHideDrawer.cs.meta b/Editor/Core/Drawers/ConditionalHideDrawer.cs.meta new file mode 100644 index 0000000..6c85b64 --- /dev/null +++ b/Editor/Core/Drawers/ConditionalHideDrawer.cs.meta @@ -0,0 +1,2 @@ +fileFormatVersion: 2 +guid: 47ed489e327ef2e41b5047aaa4bc4d7d \ No newline at end of file diff --git a/Editor/Core/Drawers/DropdownFromArrayDrawer.cs b/Editor/Core/Drawers/DropdownFromArrayDrawer.cs new file mode 100644 index 0000000..19c5884 --- /dev/null +++ b/Editor/Core/Drawers/DropdownFromArrayDrawer.cs @@ -0,0 +1,53 @@ +using UnityEditor; +using UnityEngine; + +namespace RealMethod.Editor +{ + [CustomPropertyDrawer(typeof(DropdownFromArrayAttribute))] + public class DropdownFromArrayDrawer : PropertyDrawer + { + public override void OnGUI(Rect position, SerializedProperty property, GUIContent label) + { + DropdownFromArrayAttribute dropdownAttribute = (DropdownFromArrayAttribute)attribute; + string[] options = GetOptions(property, dropdownAttribute.TargetArray); + + if (options != null && options.Length > 0) + { + if (property.propertyType == SerializedPropertyType.String) + { + int index = Mathf.Max(0, System.Array.IndexOf(options, property.stringValue)); + index = EditorGUI.Popup(position, label.text, index, options); + property.stringValue = options[index]; + } + else + { + EditorGUI.LabelField(position, label.text, "Use DropdownFromArray with string."); + } + } + else + { + EditorGUI.LabelField(position, label.text, "Array not found or empty."); + } + } + + private string[] GetOptions(SerializedProperty property, string targetArry) + { + string[] options = null; + Object targetObject = property.serializedObject.targetObject; + System.Type targetType = targetObject.GetType(); + System.Reflection.FieldInfo fieldInfo = targetType.GetField(targetArry); + + if (fieldInfo != null) + { + options = fieldInfo.GetValue(targetObject) as string[]; + } + + return options; + } + + public override float GetPropertyHeight(SerializedProperty property, GUIContent label) + { + return EditorGUI.GetPropertyHeight(property, label, true); + } + } +} \ No newline at end of file diff --git a/Editor/Core/Drawers/DropdownFromArrayDrawer.cs.meta b/Editor/Core/Drawers/DropdownFromArrayDrawer.cs.meta new file mode 100644 index 0000000..d5209d0 --- /dev/null +++ b/Editor/Core/Drawers/DropdownFromArrayDrawer.cs.meta @@ -0,0 +1,2 @@ +fileFormatVersion: 2 +guid: ad31a5019cd88d54c94626d1bbb037aa \ No newline at end of file diff --git a/Editor/Core/Drawers/DropdownFromDictionaryDrawer.cs b/Editor/Core/Drawers/DropdownFromDictionaryDrawer.cs new file mode 100644 index 0000000..17fec49 --- /dev/null +++ b/Editor/Core/Drawers/DropdownFromDictionaryDrawer.cs @@ -0,0 +1,60 @@ +using System.Collections.Generic; +using UnityEditor; +using UnityEngine; + +namespace RealMethod.Editor +{ + [CustomPropertyDrawer(typeof(DropdownFromDictionaryAttribute))] + public class DropdownFromDictionaryDrawer : PropertyDrawer + { + public override void OnGUI(Rect position, SerializedProperty property, GUIContent label) + { + DropdownFromDictionaryAttribute dropdownAttribute = (DropdownFromDictionaryAttribute)attribute; + string[] options = GetOptions(property, dropdownAttribute.dictionaryFieldName); + + if (options != null && options.Length > 0) + { + if (property.propertyType == SerializedPropertyType.String) + { + int index = Mathf.Max(0, System.Array.IndexOf(options, property.stringValue)); + index = EditorGUI.Popup(position, label.text, index, options); + property.stringValue = options[index]; + } + else + { + EditorGUI.LabelField(position, label.text, "Use DropdownFromDictionary with string."); + } + } + else + { + EditorGUI.LabelField(position, label.text, "Dictionary not found or empty."); + } + } + + private string[] GetOptions(SerializedProperty property, string dictionaryFieldName) + { + string[] options = null; + Object targetObject = property.serializedObject.targetObject; + System.Type targetType = targetObject.GetType(); + System.Reflection.FieldInfo fieldInfo = targetType.GetField(dictionaryFieldName); + + if (fieldInfo != null) + { + var dictionary = fieldInfo.GetValue(targetObject) as Dictionary; + if (dictionary != null) + { + options = new string[dictionary.Count]; + dictionary.Keys.CopyTo(options, 0); + } + } + + return options; + } + + public override float GetPropertyHeight(SerializedProperty property, GUIContent label) + { + return EditorGUI.GetPropertyHeight(property, label, true); + } + } + +} \ No newline at end of file diff --git a/Editor/Core/Drawers/DropdownFromDictionaryDrawer.cs.meta b/Editor/Core/Drawers/DropdownFromDictionaryDrawer.cs.meta new file mode 100644 index 0000000..b982d39 --- /dev/null +++ b/Editor/Core/Drawers/DropdownFromDictionaryDrawer.cs.meta @@ -0,0 +1,2 @@ +fileFormatVersion: 2 +guid: dd4e08a9c9afbc649ba64dc8a002168c \ No newline at end of file diff --git a/Runtime/Core/Attributes/DropdownAttribute.cs b/Editor/Core/Drawers/DropdownFromStringsDrawer.cs similarity index 61% rename from Runtime/Core/Attributes/DropdownAttribute.cs rename to Editor/Core/Drawers/DropdownFromStringsDrawer.cs index 08ce7e8..b7691c7 100644 --- a/Runtime/Core/Attributes/DropdownAttribute.cs +++ b/Editor/Core/Drawers/DropdownFromStringsDrawer.cs @@ -1,29 +1,14 @@ -#if UNITY_EDITOR using UnityEditor; -#endif using UnityEngine; -namespace RealMethod +namespace RealMethod.Editor { - - public class DropdownAttribute : PropertyAttribute - { - public string[] options; - - public DropdownAttribute(params string[] options) - { - this.options = options; - } - } - -#if UNITY_EDITOR - - [CustomPropertyDrawer(typeof(DropdownAttribute))] - public class DropdownDrawer : PropertyDrawer + [CustomPropertyDrawer(typeof(DropdownFromStringsAttribute))] + public class DropdownFromStringsDrawer : PropertyDrawer { public override void OnGUI(Rect position, SerializedProperty property, GUIContent label) { - DropdownAttribute dropdownAttribute = (DropdownAttribute)attribute; + DropdownFromStringsAttribute dropdownAttribute = (DropdownFromStringsAttribute)attribute; if (property.propertyType == SerializedPropertyType.String) { @@ -43,13 +28,4 @@ public override void OnGUI(Rect position, SerializedProperty property, GUIConten } } } - -#endif -} - -// ----Use -// [Dropdown("Option1", "Option2", "Option3")] -// public string selectedOption; - -// [Dropdown("Option1", "Option2", "Option3")] -// public int selectedOptionIndex; +} \ No newline at end of file diff --git a/Editor/Core/Drawers/DropdownFromStringsDrawer.cs.meta b/Editor/Core/Drawers/DropdownFromStringsDrawer.cs.meta new file mode 100644 index 0000000..8003b34 --- /dev/null +++ b/Editor/Core/Drawers/DropdownFromStringsDrawer.cs.meta @@ -0,0 +1,2 @@ +fileFormatVersion: 2 +guid: 93150ce5c26a6bd44b4f1552fc8553b3 \ No newline at end of file diff --git a/Editor/Core/Drawers/EnumDescriptionDrawer.cs b/Editor/Core/Drawers/EnumDescriptionDrawer.cs new file mode 100644 index 0000000..929b688 --- /dev/null +++ b/Editor/Core/Drawers/EnumDescriptionDrawer.cs @@ -0,0 +1,53 @@ +using System; +using UnityEditor; +using UnityEngine; + +namespace RealMethod.Editor +{ + [CustomPropertyDrawer(typeof(EnumDescriptionAttribute))] + public class EnumDescriptionDrawer : PropertyDrawer + { + public override void OnGUI(Rect position, SerializedProperty property, GUIContent label) + { + if (property.propertyType == SerializedPropertyType.Enum) + { + // Get the enum type and value. + Type enumType = fieldInfo.FieldType; + int selectedIndex = property.enumValueIndex; + + // Get the descriptions for each enum value. + string[] descriptions = GetEnumDescriptions(enumType); + + if (descriptions != null && descriptions.Length > selectedIndex) + { + // Draw the popup with descriptions. + property.enumValueIndex = EditorGUI.Popup(position, label.text, selectedIndex, descriptions); + } + else + { + // Fallback to default behavior. + EditorGUI.PropertyField(position, property, label); + } + } + else + { + EditorGUI.PropertyField(position, property, label); + } + } + + private string[] GetEnumDescriptions(Type enumType) + { + var names = Enum.GetNames(enumType); + string[] descriptions = new string[names.Length]; + + for (int i = 0; i < names.Length; i++) + { + var field = enumType.GetField(names[i]); + var descriptionAttribute = Attribute.GetCustomAttribute(field, typeof(EnumDescriptionAttribute)) as EnumDescriptionAttribute; + descriptions[i] = descriptionAttribute != null ? descriptionAttribute.Description : names[i]; + } + + return descriptions; + } + } +} \ No newline at end of file diff --git a/Editor/Core/Drawers/EnumDescriptionDrawer.cs.meta b/Editor/Core/Drawers/EnumDescriptionDrawer.cs.meta new file mode 100644 index 0000000..05ee81f --- /dev/null +++ b/Editor/Core/Drawers/EnumDescriptionDrawer.cs.meta @@ -0,0 +1,2 @@ +fileFormatVersion: 2 +guid: 16a6b6f8280e964489d2e6b7629652a9 \ No newline at end of file diff --git a/Editor/Core/Drawers/ExpandableDrawer.cs b/Editor/Core/Drawers/ExpandableDrawer.cs new file mode 100644 index 0000000..ca73b59 --- /dev/null +++ b/Editor/Core/Drawers/ExpandableDrawer.cs @@ -0,0 +1,219 @@ +using System; +using System.Collections.Generic; +using UnityEditor; +using UnityEngine; + +namespace RealMethod.Editor +{ + /// + /// Draws the property field for any field marked with ExpandableAttribute. + /// + [CustomPropertyDrawer(typeof(ExpandableAttribute), true)] + public class ExpandableDrawer : PropertyDrawer + { + // Style Setup + // Use the following area to change the style of the expandable ScriptableObject drawers; + private enum BackgroundStyles + { + None, + HelpBox, + Darken, + Lighten + } + + /// + /// Whether the default editor Script field should be shown. + /// + private static bool SHOW_SCRIPT_FIELD = false; + /// + /// The spacing on the inside of the background rect. + /// + private static float INNER_SPACING = 6.0f; + /// + /// The spacing on the outside of the background rect. + /// + private static float OUTER_SPACING = 4.0f; + /// + /// The style the background uses. + /// + private static BackgroundStyles BACKGROUND_STYLE = BackgroundStyles.HelpBox; + /// + /// The colour that is used to darken the background. + /// + private static Color DARKEN_COLOUR = new Color(0.0f, 0.0f, 0.0f, 0.2f); + /// + /// The colour that is used to lighten the background. + /// + private static Color LIGHTEN_COLOUR = new Color(1.0f, 1.0f, 1.0f, 0.2f); + + + /// + /// Cached editor reference. + /// + private UnityEditor.Editor editor = null; + + public override float GetPropertyHeight(SerializedProperty property, GUIContent label) + { + float totalHeight = 0.0f; + + totalHeight += EditorGUIUtility.singleLineHeight; + + if (property.objectReferenceValue == null) + return totalHeight; + + if (!property.isExpanded) + return totalHeight; + + if (editor == null) + UnityEditor.Editor.CreateCachedEditor(property.objectReferenceValue, null, ref editor); + + if (editor == null) + return totalHeight; + + SerializedProperty field = editor.serializedObject.GetIterator(); + + field.NextVisible(true); + + if (SHOW_SCRIPT_FIELD) + { + totalHeight += EditorGUIUtility.singleLineHeight + EditorGUIUtility.standardVerticalSpacing; + } + + while (field.NextVisible(true)) + { + totalHeight += EditorGUI.GetPropertyHeight(field, true) + EditorGUIUtility.standardVerticalSpacing; + } + + totalHeight += INNER_SPACING * 2; + totalHeight += OUTER_SPACING * 2; + + return totalHeight; + } + public override void OnGUI(Rect position, SerializedProperty property, GUIContent label) + { + Rect fieldRect = new Rect(position); + fieldRect.height = EditorGUIUtility.singleLineHeight; + + EditorGUI.PropertyField(fieldRect, property, label, true); + + // if (property.objectReferenceValue == null) + // { + // Debug.Log("It's secretly null"); + // return; + // } + + property.isExpanded = EditorGUI.Foldout(fieldRect, property.isExpanded, GUIContent.none, true); + + if (!property.isExpanded) + return; + + if (editor == null) + UnityEditor.Editor.CreateCachedEditor(property.objectReferenceValue, null, ref editor); + + if (editor == null) + { + //Debug.Log ("Couldn't fetch editor"); + return; + } + + + #region Format Field Rects + List propertyRects = new List(); + Rect marchingRect = new Rect(fieldRect); + + Rect bodyRect = new Rect(fieldRect); + bodyRect.xMin += EditorGUI.indentLevel * 18; + bodyRect.yMin += EditorGUIUtility.singleLineHeight + EditorGUIUtility.standardVerticalSpacing + + OUTER_SPACING; + + SerializedProperty field = editor.serializedObject.GetIterator(); + field.NextVisible(true); + + marchingRect.y += INNER_SPACING + OUTER_SPACING; + + if (SHOW_SCRIPT_FIELD) + { + propertyRects.Add(marchingRect); + marchingRect.y += EditorGUIUtility.singleLineHeight + EditorGUIUtility.standardVerticalSpacing; + } + + while (field.NextVisible(true)) + { + marchingRect.y += marchingRect.height + EditorGUIUtility.standardVerticalSpacing; + marchingRect.height = EditorGUI.GetPropertyHeight(field, true); + propertyRects.Add(marchingRect); + } + + marchingRect.y += INNER_SPACING; + + bodyRect.yMax = marchingRect.yMax; + #endregion + + DrawBackground(bodyRect); + + #region Draw Fields + EditorGUI.indentLevel++; + + int index = 0; + field = editor.serializedObject.GetIterator(); + field.NextVisible(true); + + if (SHOW_SCRIPT_FIELD) + { + //Show the disabled script field + EditorGUI.BeginDisabledGroup(true); + EditorGUI.PropertyField(propertyRects[index], field, true); + EditorGUI.EndDisabledGroup(); + index++; + } + + //Replacement for "editor.OnInspectorGUI ();" so we have more control on how we draw the editor + while (field.NextVisible(true)) + { + try + { + EditorGUI.PropertyField(propertyRects[index], field, true); + } + catch (StackOverflowException) + { + field.objectReferenceValue = null; + Debug.LogError("Detected self-nesting cauisng a StackOverflowException, avoid using the same " + + "object iside a nested structure."); + } + + index++; + } + + EditorGUI.indentLevel--; + #endregion + } + + + /// + /// Draws the Background + /// + /// The Rect where the background is drawn. + private void DrawBackground(Rect rect) + { + switch (BACKGROUND_STYLE) + { + + case BackgroundStyles.HelpBox: + EditorGUI.HelpBox(rect, "", MessageType.None); + break; + + case BackgroundStyles.Darken: + EditorGUI.DrawRect(rect, DARKEN_COLOUR); + break; + + case BackgroundStyles.Lighten: + EditorGUI.DrawRect(rect, LIGHTEN_COLOUR); + break; + } + } + } + + + + +} \ No newline at end of file diff --git a/Editor/Core/Drawers/ExpandableDrawer.cs.meta b/Editor/Core/Drawers/ExpandableDrawer.cs.meta new file mode 100644 index 0000000..845d342 --- /dev/null +++ b/Editor/Core/Drawers/ExpandableDrawer.cs.meta @@ -0,0 +1,2 @@ +fileFormatVersion: 2 +guid: 4d330d952dca5b1429429089ed414c8a \ No newline at end of file diff --git a/Editor/Core/Drawers/HelpBoxDrawer.cs b/Editor/Core/Drawers/HelpBoxDrawer.cs new file mode 100644 index 0000000..17c6f60 --- /dev/null +++ b/Editor/Core/Drawers/HelpBoxDrawer.cs @@ -0,0 +1,30 @@ +using UnityEditor; +using UnityEngine; + +namespace RealMethod.Editor +{ + [CustomPropertyDrawer(typeof(HelpBoxAttribute))] + public class HelpBoxDrawer : PropertyDrawer + { + public override void OnGUI(Rect position, SerializedProperty property, GUIContent label) + { + HelpBoxAttribute helpBoxAttribute = (HelpBoxAttribute)attribute; + EditorGUI.BeginProperty(position, label, property); + // Calculate the height of the help box + var helpBoxHeight = EditorGUIUtility.singleLineHeight * helpBoxAttribute.height; + var helpBoxRect = new Rect(position.x, position.y, position.width, helpBoxHeight); + EditorGUI.HelpBox(helpBoxRect, helpBoxAttribute.text, (MessageType)helpBoxAttribute.messageType); + // Calculate the position of the property field + var propertyRect = new Rect(position.x, position.y + helpBoxHeight + EditorGUIUtility.standardVerticalSpacing, position.width, EditorGUIUtility.singleLineHeight); + EditorGUI.PropertyField(propertyRect, property, label); + EditorGUI.EndProperty(); + } + + public override float GetPropertyHeight(SerializedProperty property, GUIContent label) + { + HelpBoxAttribute helpBoxAttribute = (HelpBoxAttribute)attribute; + var helpBoxHeight = EditorGUIUtility.singleLineHeight * 2; + return helpBoxHeight + EditorGUIUtility.singleLineHeight + EditorGUIUtility.standardVerticalSpacing; + } + } +} \ No newline at end of file diff --git a/Editor/Core/Drawers/HelpBoxDrawer.cs.meta b/Editor/Core/Drawers/HelpBoxDrawer.cs.meta new file mode 100644 index 0000000..f9d948e --- /dev/null +++ b/Editor/Core/Drawers/HelpBoxDrawer.cs.meta @@ -0,0 +1,2 @@ +fileFormatVersion: 2 +guid: 7dc2a9809fb29c84f99cf655165efe0f \ No newline at end of file diff --git a/Editor/Core/Drawers/LayerDrawer.cs b/Editor/Core/Drawers/LayerDrawer.cs new file mode 100644 index 0000000..c65b375 --- /dev/null +++ b/Editor/Core/Drawers/LayerDrawer.cs @@ -0,0 +1,21 @@ +using UnityEditor; +using UnityEngine; + +namespace RealMethod.Editor +{ + [CustomPropertyDrawer(typeof(LayerAttribute))] + public class LayerDrawer : PropertyDrawer + { + public override void OnGUI(Rect position, SerializedProperty property, GUIContent label) + { + if (property.propertyType == SerializedPropertyType.Integer) + { + property.intValue = EditorGUI.LayerField(position, label, property.intValue); + } + else + { + EditorGUI.LabelField(position, label.text, "Use [Layer] with int."); + } + } + } +} \ No newline at end of file diff --git a/Editor/Core/Drawers/LayerDrawer.cs.meta b/Editor/Core/Drawers/LayerDrawer.cs.meta new file mode 100644 index 0000000..626a7fe --- /dev/null +++ b/Editor/Core/Drawers/LayerDrawer.cs.meta @@ -0,0 +1,2 @@ +fileFormatVersion: 2 +guid: af5212a855fb5084d898aba471657705 \ No newline at end of file diff --git a/Editor/Core/Inspectors/ButtonEditor.cs b/Editor/Core/Inspectors/ButtonEditor.cs new file mode 100644 index 0000000..a3c8599 --- /dev/null +++ b/Editor/Core/Inspectors/ButtonEditor.cs @@ -0,0 +1,30 @@ +using UnityEditor; +using UnityEngine; +using System.Linq; +using System.Reflection; + + +namespace RealMethod.Editor +{ + [CustomEditor(typeof(MonoBehaviour), true)] + public class ButtonDrawer : UnityEditor.Editor + { + public override void OnInspectorGUI() + { + base.OnInspectorGUI(); + + var targetType = target.GetType(); + var methods = targetType + .GetMethods(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic) + .Where(m => m.GetCustomAttribute() != null && m.GetParameters().Length == 0); + + foreach (var method in methods) + { + if (GUILayout.Button(method.Name)) + { + method.Invoke(target, null); + } + } + } + } +} \ No newline at end of file diff --git a/Editor/Core/Inspectors/ButtonEditor.cs.meta b/Editor/Core/Inspectors/ButtonEditor.cs.meta new file mode 100644 index 0000000..2503917 --- /dev/null +++ b/Editor/Core/Inspectors/ButtonEditor.cs.meta @@ -0,0 +1,2 @@ +fileFormatVersion: 2 +guid: b9640b8b2e43dc0419208f4283f8aa82 \ No newline at end of file diff --git a/Editor/Core/Inspectors/MonoBehaviourEditor.cs b/Editor/Core/Inspectors/MonoBehaviourEditor.cs new file mode 100644 index 0000000..228d054 --- /dev/null +++ b/Editor/Core/Inspectors/MonoBehaviourEditor.cs @@ -0,0 +1,15 @@ +using UnityEditor; +using UnityEngine; + +namespace RealMethod.Editor +{ + /// + /// Required for the fetching of a default editor on MonoBehaviour objects. + /// + [CanEditMultipleObjects] + [CustomEditor(typeof(MonoBehaviour), true)] + public class MonoBehaviourEditor : UnityEditor.Editor + { + + } +} \ No newline at end of file diff --git a/Editor/Core/Inspectors/MonoBehaviourEditor.cs.meta b/Editor/Core/Inspectors/MonoBehaviourEditor.cs.meta new file mode 100644 index 0000000..36acbb4 --- /dev/null +++ b/Editor/Core/Inspectors/MonoBehaviourEditor.cs.meta @@ -0,0 +1,2 @@ +fileFormatVersion: 2 +guid: 5d107c809858e504f9c8f63b13101d7c \ No newline at end of file diff --git a/Editor/Core/Inspectors/PrimitiveAssetEditor.cs b/Editor/Core/Inspectors/PrimitiveAssetEditor.cs new file mode 100644 index 0000000..fe8ec34 --- /dev/null +++ b/Editor/Core/Inspectors/PrimitiveAssetEditor.cs @@ -0,0 +1,11 @@ +using UnityEditor; + +namespace RealMethod.Editor +{ + /// + /// Required for the fetching of a default editor on ScriptableObject objects. + /// + [CanEditMultipleObjects] + [CustomEditor(typeof(PrimitiveAsset), true)] + public class PrimitiveAssetEditor : UnityEditor.Editor { } +} \ No newline at end of file diff --git a/Editor/Core/Inspectors/PrimitiveAssetEditor.cs.meta b/Editor/Core/Inspectors/PrimitiveAssetEditor.cs.meta new file mode 100644 index 0000000..78ce252 --- /dev/null +++ b/Editor/Core/Inspectors/PrimitiveAssetEditor.cs.meta @@ -0,0 +1,2 @@ +fileFormatVersion: 2 +guid: 9da63613ae73be84aac196a150fc3fa2 \ No newline at end of file diff --git a/Editor/Core/Inspectors/DataAssetEditor.cs b/Editor/Core/Inspectors/ScriptableObjectEditor.cs similarity index 93% rename from Editor/Core/Inspectors/DataAssetEditor.cs rename to Editor/Core/Inspectors/ScriptableObjectEditor.cs index ece664f..c28f317 100644 --- a/Editor/Core/Inspectors/DataAssetEditor.cs +++ b/Editor/Core/Inspectors/ScriptableObjectEditor.cs @@ -3,7 +3,7 @@ namespace RealMethod.Editor { - public class DataAssetEditor : UnityEditor.Editor + public class ScriptableObjectEditor : UnityEditor.Editor { public static void DrawCompleteScriptableObjectEditor(string name, ref T settings, ref bool foldout, ref UnityEditor.Editor editor) where T : ScriptableObject { diff --git a/Editor/Core/Inspectors/DataAssetEditor.cs.meta b/Editor/Core/Inspectors/ScriptableObjectEditor.cs.meta similarity index 100% rename from Editor/Core/Inspectors/DataAssetEditor.cs.meta rename to Editor/Core/Inspectors/ScriptableObjectEditor.cs.meta diff --git a/Runtime/Core/Attributes/ButtonAttribute.cs b/Runtime/Core/Attributes/ButtonAttribute.cs index 5d5ced0..2b7f3e4 100644 --- a/Runtime/Core/Attributes/ButtonAttribute.cs +++ b/Runtime/Core/Attributes/ButtonAttribute.cs @@ -1,45 +1,18 @@ using System; -using System.Linq; -using System.Reflection; -using UnityEngine; -#if UNITY_EDITOR -using UnityEditor; -#endif namespace RealMethod { + /// + /// + /// [Button] + /// private void DoSomething() + /// { + /// Debug.Log("DoSomething called from Inspector!"); + /// } + /// + /// [AttributeUsage(AttributeTargets.Method, Inherited = true)] public class ButtonAttribute : Attribute { } - -#if UNITY_EDITOR - [CustomEditor(typeof(MonoBehaviour), true)] - public class ButtonDrawer : Editor - { - public override void OnInspectorGUI() - { - base.OnInspectorGUI(); - - var targetType = target.GetType(); - var methods = targetType - .GetMethods(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic) - .Where(m => m.GetCustomAttribute() != null && m.GetParameters().Length == 0); - - foreach (var method in methods) - { - if (GUILayout.Button(method.Name)) - { - method.Invoke(target, null); - } - } - } - } -#endif - } -// [Button] -// private void DoSomething() -// { -// Debug.Log("DoSomething called from Inspector!"); -// } \ No newline at end of file diff --git a/Runtime/Core/Attributes/ColorFieldAttribute.cs b/Runtime/Core/Attributes/ColorFieldAttribute.cs index 6b628bc..ae07f61 100644 --- a/Runtime/Core/Attributes/ColorFieldAttribute.cs +++ b/Runtime/Core/Attributes/ColorFieldAttribute.cs @@ -1,78 +1,19 @@ using UnityEngine; -#if UNITY_EDITOR -using UnityEditor; -#endif - namespace RealMethod { - public enum FieldColor - { - Red, - Green, - Blue, - Yellow, - Black, - White, - Gray - } + /// + /// + /// [ColorFieldAttribute(R,G,B)] + /// public GameObject Target; + /// + /// public class ColorFieldAttribute : PropertyAttribute { - public Color color; + public Color color = Color.blue; - public ColorFieldAttribute(FieldColor _color = FieldColor.Red) + public ColorFieldAttribute(float r, float g, float b) { - switch (_color) - { - case FieldColor.Red: - color = Color.red; - break; - case FieldColor.Green: - color = Color.green; - break; - case FieldColor.Blue: - color = Color.blue; - break; - case FieldColor.Yellow: - color = Color.yellow; - break; - case FieldColor.Black: - color = Color.black; - break; - case FieldColor.White: - color = Color.white; - break; - case FieldColor.Gray: - color = Color.gray; - break; - default: - color = Color.red; - break; - } + color = new Color(r, g, b); } } - -#if UNITY_EDITOR - - [CustomPropertyDrawer(typeof(ColorFieldAttribute))] - public class RequiredFieldDrawer : PropertyDrawer - { - public override void OnGUI(Rect position, SerializedProperty property, GUIContent label) - { - ColorFieldAttribute field = attribute as ColorFieldAttribute; - - if (property.objectReferenceValue == null) - { - GUI.color = field.color; //Set the color of the GUI - EditorGUI.PropertyField(position, property, label); //Draw the GUI - GUI.color = Color.white; //Reset the color of the GUI to white - } - else - EditorGUI.PropertyField(position, property, label); - } - } -#endif -} - -///Use -///[ColorFieldAttribute(FieldColor.Blue)] -///public GameObject Test; \ No newline at end of file +} \ No newline at end of file diff --git a/Runtime/Core/Attributes/ConditionalHideAttribute.cs b/Runtime/Core/Attributes/ConditionalHideAttribute.cs index 36c36a6..5d380f5 100644 --- a/Runtime/Core/Attributes/ConditionalHideAttribute.cs +++ b/Runtime/Core/Attributes/ConditionalHideAttribute.cs @@ -1,10 +1,14 @@ using UnityEngine; -#if UNITY_EDITOR -using UnityEditor; -#endif namespace RealMethod { + /// + /// + /// public bool Variable; + /// [ConditionalHide("Variable", true, false)] + /// public String TargetName; + /// + /// public class ConditionalHideAttribute : PropertyAttribute { public string ConditionalSourceField; @@ -18,78 +22,4 @@ public ConditionalHideAttribute(string conditionalSourceField, bool hideInInspec ReverceCondition = reverceCondition; } } - -#if UNITY_EDITOR - - [CustomPropertyDrawer(typeof(ConditionalHideAttribute))] - public class ConditionalHidePropertyDrawer : PropertyDrawer - { - public override void OnGUI(Rect position, SerializedProperty property, GUIContent label) - { - ConditionalHideAttribute condHAtt = (ConditionalHideAttribute)attribute; - bool enabled = GetConditionalHideAttributeResult(condHAtt, property); - - bool wasEnabled = GUI.enabled; - GUI.enabled = enabled; - - if (!condHAtt.HideInInspector || enabled) - { - EditorGUI.PropertyField(position, property, label, true); - } - - GUI.enabled = wasEnabled; - } - - public override float GetPropertyHeight(SerializedProperty property, GUIContent label) - { - ConditionalHideAttribute condHAtt = (ConditionalHideAttribute)attribute; - bool enabled = GetConditionalHideAttributeResult(condHAtt, property); - - if (!condHAtt.HideInInspector || enabled) - { - return EditorGUI.GetPropertyHeight(property, label); - } - else - { - return -EditorGUIUtility.standardVerticalSpacing; - } - } - - private bool GetConditionalHideAttributeResult(ConditionalHideAttribute condHAtt, SerializedProperty property) - { - bool enabled = true; - - string propertyPath = property.propertyPath; // returns the property path of the property we want to apply the attribute to - string conditionPath = propertyPath.Replace(property.name, condHAtt.ConditionalSourceField); // changes the path to the conditionalsource property path - SerializedProperty sourcePropertyValue = property.serializedObject.FindProperty(conditionPath); - - if (sourcePropertyValue != null) - { - if (!condHAtt.ReverceCondition) - { - enabled = sourcePropertyValue.boolValue; - } - else - { - enabled = !sourcePropertyValue.boolValue; - } - - } - else - { - Debug.LogWarning("Attempting to use a ConditionalHideAttribute but no matching SourcePropertyValue found in object: " + condHAtt.ConditionalSourceField); - } - - return enabled; - } - } - -#endif - -} - -//Use -// [ConditionalHide("IsPlayerInScene", true, false)] -// First variable : Your boolean variable Name -// Second variable : if true= Show/Hide false= Visible/Invisible -// Third variable : if true= revert functionality +} \ No newline at end of file diff --git a/Runtime/Core/Attributes/DropdownFromArrayAttribute.cs b/Runtime/Core/Attributes/DropdownFromArrayAttribute.cs index eb76093..c230306 100644 --- a/Runtime/Core/Attributes/DropdownFromArrayAttribute.cs +++ b/Runtime/Core/Attributes/DropdownFromArrayAttribute.cs @@ -1,74 +1,21 @@ -#if UNITY_EDITOR -using UnityEditor; -#endif using UnityEngine; namespace RealMethod { + /// + /// + /// public string[] options = new string[] { "Option1", "Option2", "Option3" }; + /// + /// [StaticDropdown("options")] + /// public string selectedOption; + /// + /// public class DropdownFromArrayAttribute : PropertyAttribute { - public string arrayFieldName; - - public DropdownFromArrayAttribute(string arrayFieldName) - { - this.arrayFieldName = arrayFieldName; - } - } - -#if UNITY_EDITOR - - [CustomPropertyDrawer(typeof(DropdownFromArrayAttribute))] - public class DropdownFromArrayDrawer : PropertyDrawer - { - public override void OnGUI(Rect position, SerializedProperty property, GUIContent label) - { - DropdownFromArrayAttribute dropdownAttribute = (DropdownFromArrayAttribute)attribute; - string[] options = GetOptions(property, dropdownAttribute.arrayFieldName); - - if (options != null && options.Length > 0) - { - if (property.propertyType == SerializedPropertyType.String) - { - int index = Mathf.Max(0, System.Array.IndexOf(options, property.stringValue)); - index = EditorGUI.Popup(position, label.text, index, options); - property.stringValue = options[index]; - } - else - { - EditorGUI.LabelField(position, label.text, "Use DropdownFromArray with string."); - } - } - else - { - EditorGUI.LabelField(position, label.text, "Array not found or empty."); - } - } - - private string[] GetOptions(SerializedProperty property, string arrayFieldName) + public string TargetArray; + public DropdownFromArrayAttribute(string array) { - string[] options = null; - Object targetObject = property.serializedObject.targetObject; - System.Type targetType = targetObject.GetType(); - System.Reflection.FieldInfo fieldInfo = targetType.GetField(arrayFieldName); - - if (fieldInfo != null) - { - options = fieldInfo.GetValue(targetObject) as string[]; - } - - return options; - } - - public override float GetPropertyHeight(SerializedProperty property, GUIContent label) - { - return EditorGUI.GetPropertyHeight(property, label, true); + TargetArray = array; } } - -#endif } -// ---Use -// public string[] options = new string[] { "Option1", "Option2", "Option3" }; - -// [DropdownFromArray("options")] -// public string selectedOption; diff --git a/Runtime/Core/Attributes/DropdownFromDictionaryAttribute.cs b/Runtime/Core/Attributes/DropdownFromDictionaryAttribute.cs index b564ee7..cf06e7f 100644 --- a/Runtime/Core/Attributes/DropdownFromDictionaryAttribute.cs +++ b/Runtime/Core/Attributes/DropdownFromDictionaryAttribute.cs @@ -1,86 +1,26 @@ -using System.Collections.Generic; -#if UNITY_EDITOR -using UnityEditor; -#endif using UnityEngine; namespace RealMethod { + /// + /// + /// public Dictionary options = new Dictionary + /// { + /// { "Key1", "Value1" }, + /// { "Key2", "Value2" }, + /// { "Key3", "Value3" } + /// }; + /// + /// [DropdownFromDictionary("options")] + /// public string selectedOption; + /// + /// public class DropdownFromDictionaryAttribute : PropertyAttribute { public string dictionaryFieldName; - public DropdownFromDictionaryAttribute(string dictionaryFieldName) { this.dictionaryFieldName = dictionaryFieldName; } } - -#if UNITY_EDITOR - - [CustomPropertyDrawer(typeof(DropdownFromDictionaryAttribute))] - public class DropdownFromDictionaryDrawer : PropertyDrawer - { - public override void OnGUI(Rect position, SerializedProperty property, GUIContent label) - { - DropdownFromDictionaryAttribute dropdownAttribute = (DropdownFromDictionaryAttribute)attribute; - string[] options = GetOptions(property, dropdownAttribute.dictionaryFieldName); - - if (options != null && options.Length > 0) - { - if (property.propertyType == SerializedPropertyType.String) - { - int index = Mathf.Max(0, System.Array.IndexOf(options, property.stringValue)); - index = EditorGUI.Popup(position, label.text, index, options); - property.stringValue = options[index]; - } - else - { - EditorGUI.LabelField(position, label.text, "Use DropdownFromDictionary with string."); - } - } - else - { - EditorGUI.LabelField(position, label.text, "Dictionary not found or empty."); - } - } - - private string[] GetOptions(SerializedProperty property, string dictionaryFieldName) - { - string[] options = null; - Object targetObject = property.serializedObject.targetObject; - System.Type targetType = targetObject.GetType(); - System.Reflection.FieldInfo fieldInfo = targetType.GetField(dictionaryFieldName); - - if (fieldInfo != null) - { - var dictionary = fieldInfo.GetValue(targetObject) as Dictionary; - if (dictionary != null) - { - options = new string[dictionary.Count]; - dictionary.Keys.CopyTo(options, 0); - } - } - - return options; - } - - public override float GetPropertyHeight(SerializedProperty property, GUIContent label) - { - return EditorGUI.GetPropertyHeight(property, label, true); - } - } - -#endif } - -// ----Use -// public Dictionary options = new Dictionary -// { -// { "Key1", "Value1" }, -// { "Key2", "Value2" }, -// { "Key3", "Value3" } -// }; - -// [DropdownFromDictionary("options")] -// public string selectedOption; diff --git a/Runtime/Core/Attributes/DropdownFromStringsAttribute.cs b/Runtime/Core/Attributes/DropdownFromStringsAttribute.cs new file mode 100644 index 0000000..9640b33 --- /dev/null +++ b/Runtime/Core/Attributes/DropdownFromStringsAttribute.cs @@ -0,0 +1,24 @@ +using UnityEngine; + +namespace RealMethod +{ + /// + /// + /// Exaple_1: + /// [Dropdown("Option1", "Option2", "Option3")] + /// public string selectedOption; + /// Example_2: + /// [Dropdown("Option1", "Option2", "Option3")] + /// public int selectedOptionIndex; + /// + /// + public class DropdownFromStringsAttribute : PropertyAttribute + { + public string[] options; + + public DropdownFromStringsAttribute(params string[] options) + { + this.options = options; + } + } +} \ No newline at end of file diff --git a/Runtime/Core/Attributes/DropdownAttribute.cs.meta b/Runtime/Core/Attributes/DropdownFromStringsAttribute.cs.meta similarity index 100% rename from Runtime/Core/Attributes/DropdownAttribute.cs.meta rename to Runtime/Core/Attributes/DropdownFromStringsAttribute.cs.meta diff --git a/Runtime/Core/Attributes/EnumDescriptionAttribute.cs b/Runtime/Core/Attributes/EnumDescriptionAttribute.cs index 713b9da..e06b0d8 100644 --- a/Runtime/Core/Attributes/EnumDescriptionAttribute.cs +++ b/Runtime/Core/Attributes/EnumDescriptionAttribute.cs @@ -1,85 +1,30 @@ using System; using UnityEngine; -#if UNITY_EDITOR -using UnityEditor; -#endif namespace RealMethod { + /// + /// Example: + /// + /// public enum MyEnumWithDescriptions + /// { + /// [EnumDescription("This is the first option.")] + /// Option1, + /// [EnumDescription("This is the second option.")] + /// Option2, + /// [EnumDescription("This is the third option.")] + /// Option3 + /// } + /// + /// [AttributeUsage(AttributeTargets.Field, AllowMultiple = false)] public class EnumDescriptionAttribute : PropertyAttribute { public string Description { get; } - public EnumDescriptionAttribute(string description) { Description = description; } } - - -#if UNITY_EDITOR - - - [CustomPropertyDrawer(typeof(EnumDescriptionAttribute))] - public class EnumWithDescriptionsDrawer : PropertyDrawer - { - public override void OnGUI(Rect position, SerializedProperty property, GUIContent label) - { - if (property.propertyType == SerializedPropertyType.Enum) - { - // Get the enum type and value. - Type enumType = fieldInfo.FieldType; - int selectedIndex = property.enumValueIndex; - - // Get the descriptions for each enum value. - string[] descriptions = GetEnumDescriptions(enumType); - - if (descriptions != null && descriptions.Length > selectedIndex) - { - // Draw the popup with descriptions. - property.enumValueIndex = EditorGUI.Popup(position, label.text, selectedIndex, descriptions); - } - else - { - // Fallback to default behavior. - EditorGUI.PropertyField(position, property, label); - } - } - else - { - EditorGUI.PropertyField(position, property, label); - } - } - - private string[] GetEnumDescriptions(Type enumType) - { - var names = Enum.GetNames(enumType); - string[] descriptions = new string[names.Length]; - - for (int i = 0; i < names.Length; i++) - { - var field = enumType.GetField(names[i]); - var descriptionAttribute = Attribute.GetCustomAttribute(field, typeof(EnumDescriptionAttribute)) as EnumDescriptionAttribute; - descriptions[i] = descriptionAttribute != null ? descriptionAttribute.Description : names[i]; - } - - return descriptions; - } - } -#endif } - -//////Use -// public enum MyEnumWithDescriptions -// { -// [EnumDescription("This is the first option.")] -// Option1, - -// [EnumDescription("This is the second option.")] -// Option2, - -// [EnumDescription("This is the third option.")] -// Option3 -// } diff --git a/Runtime/Core/Attributes/ExpandableAttribute.cs b/Runtime/Core/Attributes/ExpandableAttribute.cs index eaf6424..9aa81dc 100644 --- a/Runtime/Core/Attributes/ExpandableAttribute.cs +++ b/Runtime/Core/Attributes/ExpandableAttribute.cs @@ -1,255 +1,19 @@ -using System; using UnityEngine; namespace RealMethod { - -#if UNITY_EDITOR - using System.Collections.Generic; - using UnityEditor; -#endif - /// /// Use this property on a ScriptableObject type to allow the editors drawing the field to draw an expandable /// area that allows for changing the values on the object without having to change editor. + /// + /// [Expandable] + /// public ScriptableObject TEST; + /// /// public class ExpandableAttribute : PropertyAttribute { public ExpandableAttribute() { - - } - } - -#if UNITY_EDITOR - /// - /// Draws the property field for any field marked with ExpandableAttribute. - /// - [CustomPropertyDrawer(typeof(ExpandableAttribute), true)] - public class ExpandableAttributeDrawer : PropertyDrawer - { - // Use the following area to change the style of the expandable ScriptableObject drawers; - #region Style Setup - private enum BackgroundStyles - { - None, - HelpBox, - Darken, - Lighten - } - - /// - /// Whether the default editor Script field should be shown. - /// - private static bool SHOW_SCRIPT_FIELD = false; - - /// - /// The spacing on the inside of the background rect. - /// - private static float INNER_SPACING = 6.0f; - - /// - /// The spacing on the outside of the background rect. - /// - private static float OUTER_SPACING = 4.0f; - - /// - /// The style the background uses. - /// - private static BackgroundStyles BACKGROUND_STYLE = BackgroundStyles.HelpBox; - - /// - /// The colour that is used to darken the background. - /// - private static Color DARKEN_COLOUR = new Color(0.0f, 0.0f, 0.0f, 0.2f); - - /// - /// The colour that is used to lighten the background. - /// - private static Color LIGHTEN_COLOUR = new Color(1.0f, 1.0f, 1.0f, 0.2f); - #endregion - - /// - /// Cached editor reference. - /// - private Editor editor = null; - - public override float GetPropertyHeight(SerializedProperty property, GUIContent label) - { - float totalHeight = 0.0f; - - totalHeight += EditorGUIUtility.singleLineHeight; - - if (property.objectReferenceValue == null) - return totalHeight; - - if (!property.isExpanded) - return totalHeight; - - if (editor == null) - Editor.CreateCachedEditor(property.objectReferenceValue, null, ref editor); - - if (editor == null) - return totalHeight; - - SerializedProperty field = editor.serializedObject.GetIterator(); - - field.NextVisible(true); - - if (SHOW_SCRIPT_FIELD) - { - totalHeight += EditorGUIUtility.singleLineHeight + EditorGUIUtility.standardVerticalSpacing; - } - - while (field.NextVisible(true)) - { - totalHeight += EditorGUI.GetPropertyHeight(field, true) + EditorGUIUtility.standardVerticalSpacing; - } - - totalHeight += INNER_SPACING * 2; - totalHeight += OUTER_SPACING * 2; - - return totalHeight; - } - - public override void OnGUI(Rect position, SerializedProperty property, GUIContent label) - { - Rect fieldRect = new Rect(position); - fieldRect.height = EditorGUIUtility.singleLineHeight; - - EditorGUI.PropertyField(fieldRect, property, label, true); - - if (property.objectReferenceValue == null) - { - Debug.Log("It's secretly null"); - return; - } - - property.isExpanded = EditorGUI.Foldout(fieldRect, property.isExpanded, GUIContent.none, true); - - if (!property.isExpanded) - return; - - if (editor == null) - Editor.CreateCachedEditor(property.objectReferenceValue, null, ref editor); - - if (editor == null) - { - //Debug.Log ("Couldn't fetch editor"); - return; - } - - - #region Format Field Rects - List propertyRects = new List(); - Rect marchingRect = new Rect(fieldRect); - - Rect bodyRect = new Rect(fieldRect); - bodyRect.xMin += EditorGUI.indentLevel * 18; - bodyRect.yMin += EditorGUIUtility.singleLineHeight + EditorGUIUtility.standardVerticalSpacing - + OUTER_SPACING; - - SerializedProperty field = editor.serializedObject.GetIterator(); - field.NextVisible(true); - - marchingRect.y += INNER_SPACING + OUTER_SPACING; - - if (SHOW_SCRIPT_FIELD) - { - propertyRects.Add(marchingRect); - marchingRect.y += EditorGUIUtility.singleLineHeight + EditorGUIUtility.standardVerticalSpacing; - } - - while (field.NextVisible(true)) - { - marchingRect.y += marchingRect.height + EditorGUIUtility.standardVerticalSpacing; - marchingRect.height = EditorGUI.GetPropertyHeight(field, true); - propertyRects.Add(marchingRect); - } - - marchingRect.y += INNER_SPACING; - - bodyRect.yMax = marchingRect.yMax; - #endregion - - DrawBackground(bodyRect); - - #region Draw Fields - EditorGUI.indentLevel++; - - int index = 0; - field = editor.serializedObject.GetIterator(); - field.NextVisible(true); - - if (SHOW_SCRIPT_FIELD) - { - //Show the disabled script field - EditorGUI.BeginDisabledGroup(true); - EditorGUI.PropertyField(propertyRects[index], field, true); - EditorGUI.EndDisabledGroup(); - index++; - } - - //Replacement for "editor.OnInspectorGUI ();" so we have more control on how we draw the editor - while (field.NextVisible(true)) - { - try - { - EditorGUI.PropertyField(propertyRects[index], field, true); - } - catch (StackOverflowException) - { - field.objectReferenceValue = null; - Debug.LogError("Detected self-nesting cauisng a StackOverflowException, avoid using the same " + - "object iside a nested structure."); - } - - index++; - } - - EditorGUI.indentLevel--; - #endregion - } - - /// - /// Draws the Background - /// - /// The Rect where the background is drawn. - private void DrawBackground(Rect rect) - { - switch (BACKGROUND_STYLE) - { - - case BackgroundStyles.HelpBox: - EditorGUI.HelpBox(rect, "", MessageType.None); - break; - - case BackgroundStyles.Darken: - EditorGUI.DrawRect(rect, DARKEN_COLOUR); - break; - - case BackgroundStyles.Lighten: - EditorGUI.DrawRect(rect, LIGHTEN_COLOUR); - break; - } } } - - /// - /// Required for the fetching of a default editor on MonoBehaviour objects. - /// - [CanEditMultipleObjects] - [CustomEditor(typeof(MonoBehaviour), true)] - public class MonoBehaviourEditor : Editor { } - - /// - /// Required for the fetching of a default editor on ScriptableObject objects. - /// - [CanEditMultipleObjects] - [CustomEditor(typeof(ScriptableObject), true)] - public class ScriptableObjectEditor : Editor { } -#endif -} -// ----Use -//[Expandable] -//public ScriptableObject TEST; \ No newline at end of file +} \ No newline at end of file diff --git a/Runtime/Core/Attributes/HelpBoxAttribute.cs b/Runtime/Core/Attributes/HelpBoxAttribute.cs index c924cd7..c73ce8b 100644 --- a/Runtime/Core/Attributes/HelpBoxAttribute.cs +++ b/Runtime/Core/Attributes/HelpBoxAttribute.cs @@ -1,63 +1,26 @@ using UnityEngine; -#if UNITY_EDITOR -using UnityEditor; -#endif namespace RealMethod { - public enum HelpBoxMessageType { None, Info, Warning, Error } - + /// + /// + /// [HelpBox("This is the first line of the help box.\nThis is the second line of the help box.", {0,1,2,3} )] + /// [TextArea(3, 10)] + /// public string Variable; + /// + /// {0:None,1:Info,2:Warning,3:Error} + /// public class HelpBoxAttribute : PropertyAttribute { - public string text; - public HelpBoxMessageType messageType; + public int messageType; public int height; - public HelpBoxAttribute(string text, HelpBoxMessageType messageType = HelpBoxMessageType.None, int Boxheight = 2) + public HelpBoxAttribute(string text, int messageType = 0, int Boxheight = 2) { this.text = text; this.messageType = messageType; height = Boxheight; } } - -#if UNITY_EDITOR - - [CustomPropertyDrawer(typeof(HelpBoxAttribute))] - public class HelpBoxDrawer : PropertyDrawer - { - public override void OnGUI(Rect position, SerializedProperty property, GUIContent label) - { - HelpBoxAttribute helpBoxAttribute = (HelpBoxAttribute)attribute; - - EditorGUI.BeginProperty(position, label, property); - - // Calculate the height of the help box - var helpBoxHeight = EditorGUIUtility.singleLineHeight * helpBoxAttribute.height; - var helpBoxRect = new Rect(position.x, position.y, position.width, helpBoxHeight); - EditorGUI.HelpBox(helpBoxRect, helpBoxAttribute.text, (MessageType)helpBoxAttribute.messageType); - - // Calculate the position of the property field - var propertyRect = new Rect(position.x, position.y + helpBoxHeight + EditorGUIUtility.standardVerticalSpacing, position.width, EditorGUIUtility.singleLineHeight); - EditorGUI.PropertyField(propertyRect, property, label); - - EditorGUI.EndProperty(); - } - - public override float GetPropertyHeight(SerializedProperty property, GUIContent label) - { - HelpBoxAttribute helpBoxAttribute = (HelpBoxAttribute)attribute; - var helpBoxHeight = EditorGUIUtility.singleLineHeight * 2; - return helpBoxHeight + EditorGUIUtility.singleLineHeight + EditorGUIUtility.standardVerticalSpacing; - } - } - -#endif - - } -// ----Use -// [HelpBox("This is the first line of the help box.\nThis is the second line of the help box.", HelpBoxMessageType.Info)] -// [TextArea(3, 10)] -// public string myMultiLineText; diff --git a/Runtime/Core/Attributes/LayerAttribute.cs b/Runtime/Core/Attributes/LayerAttribute.cs index 2d16caf..a2630dc 100644 --- a/Runtime/Core/Attributes/LayerAttribute.cs +++ b/Runtime/Core/Attributes/LayerAttribute.cs @@ -1,36 +1,16 @@ -#if UNITY_EDITOR -using UnityEditor; -#endif using UnityEngine; namespace RealMethod { - public class LayerAttribute : PropertyAttribute { } - - -#if UNITY_EDITOR - [CustomPropertyDrawer(typeof(LayerAttribute))] - public class LayerDrawer : PropertyDrawer + /// + /// + /// [DropdownFromStrings("Option1", "Option2", "Option3")] + /// [Layer] + /// public int layer; + /// + /// + public class LayerAttribute : PropertyAttribute { - public override void OnGUI(Rect position, SerializedProperty property, GUIContent label) - { - if (property.propertyType == SerializedPropertyType.Integer) - { - property.intValue = EditorGUI.LayerField(position, label, property.intValue); - } - else - { - EditorGUI.LabelField(position, label.text, "Use [Layer] with int."); - } - } - } -#endif - - - - // ----Use - // [Dropdown("Option1", "Option2", "Option3")] - // [Layer] - // public int layer; + } } \ No newline at end of file diff --git a/Tests/Editor/DelegateDisplayEditor.cs b/Tests/Editor/DelegateDisplayEditor.cs index 91e5359..2323260 100644 --- a/Tests/Editor/DelegateDisplayEditor.cs +++ b/Tests/Editor/DelegateDisplayEditor.cs @@ -5,60 +5,60 @@ namespace RealMethod { - [CustomEditor(typeof(MonoBehaviour), true)] - public class DelegateDisplayEditor : UnityEditor.Editor - { - public override void OnInspectorGUI() - { - base.OnInspectorGUI(); + // [CustomEditor(typeof(MonoBehaviour), true)] + // public class DelegateDisplayEditor : UnityEditor.Editor + // { + // public override void OnInspectorGUI() + // { + // base.OnInspectorGUI(); - MonoBehaviour targetMono = (MonoBehaviour)target; - Type type = targetMono.GetType(); + // MonoBehaviour targetMono = (MonoBehaviour)target; + // Type type = targetMono.GetType(); - BindingFlags flags = BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic; - var fields = type.GetFields(flags); + // BindingFlags flags = BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic; + // var fields = type.GetFields(flags); - EditorGUILayout.Space(); - EditorGUILayout.LabelField("Assigned Delegates", EditorStyles.boldLabel); + // EditorGUILayout.Space(); + // EditorGUILayout.LabelField("Assigned Delegates", EditorStyles.boldLabel); - bool anyShown = false; + // bool anyShown = false; - foreach (var field in fields) - { - // Check if it's a delegate or derived from MulticastDelegate (includes Action, Func, etc.) - if (typeof(MulticastDelegate).IsAssignableFrom(field.FieldType.BaseType)) - { - var del = field.GetValue(targetMono) as Delegate; + // foreach (var field in fields) + // { + // // Check if it's a delegate or derived from MulticastDelegate (includes Action, Func, etc.) + // if (typeof(MulticastDelegate).IsAssignableFrom(field.FieldType.BaseType)) + // { + // var del = field.GetValue(targetMono) as Delegate; - if (del != null) - { - Delegate[] invocationList = del.GetInvocationList(); + // if (del != null) + // { + // Delegate[] invocationList = del.GetInvocationList(); - foreach (var d in invocationList) - { - string methodName = d.Method?.Name ?? ""; - string targetName = d.Target?.GetType().Name ?? ""; + // foreach (var d in invocationList) + // { + // string methodName = d.Method?.Name ?? ""; + // string targetName = d.Target?.GetType().Name ?? ""; - EditorGUILayout.LabelField($"{field.Name}", $"{methodName} ({targetName})"); - } - } - else - { - EditorGUILayout.LabelField($"{field.Name}", ""); - } + // EditorGUILayout.LabelField($"{field.Name}", $"{methodName} ({targetName})"); + // } + // } + // else + // { + // EditorGUILayout.LabelField($"{field.Name}", ""); + // } - anyShown = true; - } - } + // anyShown = true; + // } + // } - if (!anyShown) - { - EditorGUILayout.LabelField("No delegates found."); - } + // if (!anyShown) + // { + // EditorGUILayout.LabelField("No delegates found."); + // } - Debug.Log("sdsdsd"); - } + // Debug.Log("sdsdsd"); + // } - } + // } } \ No newline at end of file From 194bb1be1ae7debc1d50b7d69f197133239d2006 Mon Sep 17 00:00:00 2001 From: Alijimpa Date: Mon, 30 Mar 2026 11:40:26 +0330 Subject: [PATCH 057/204] Refine All Attribute & Drawer --- ...xpandableDrawer.cs => AssetInlinDrawer.cs} | 4 +- ...rawer.cs.meta => AssetInlinDrawer.cs.meta} | 0 .../Drawers/ConditionalHideByEnumDrawer.cs | 35 ++++++++ .../ConditionalHideByEnumDrawer.cs.meta | 2 + .../Drawers/ConditionalShowByEnumDrawer.cs | 46 ++++++++++ .../ConditionalShowByEnumDrawer.cs.meta | 2 + ...tionDrawer.cs => DescriptionEnumDrawer.cs} | 6 +- ....cs.meta => DescriptionEnumDrawer.cs.meta} | 0 ...FromStringsDrawer.cs => DropdownDrawer.cs} | 6 +- ...sDrawer.cs.meta => DropdownDrawer.cs.meta} | 0 Editor/Core/Drawers/LineDrawer.cs | 39 ++++++++ Editor/Core/Drawers/LineDrawer.cs.meta | 2 + Editor/Core/Drawers/MinMaxRangeDrawer.cs | 51 +++++++++++ Editor/Core/Drawers/MinMaxRangeDrawer.cs.meta | 2 + .../Core/Drawers/PopupListDrawer.cs | 33 ++----- Editor/Core/Drawers/PopupListDrawer.cs.meta | 2 + Editor/Core/Drawers/ReadOnlyDrawer.cs | 21 +++++ Editor/Core/Drawers/ReadOnlyDrawer.cs.meta | 2 + Editor/Core/Drawers/ShowOnlyDrawer.cs | 35 ++++++++ Editor/Core/Drawers/ShowOnlyDrawer.cs.meta | 2 + Editor/Core/Drawers/TagSelectorDrawer.cs | 31 +++++++ Editor/Core/Drawers/TagSelectorDrawer.cs.meta | 2 + Editor/Core/Drawers/TypeSelectorDrawer.cs | 51 +++++++++++ .../Core/Drawers/TypeSelectorDrawer.cs.meta | 2 + ...bleAttribute.cs => AssetInlinAttribute.cs} | 4 +- ...te.cs.meta => AssetInlinAttribute.cs.meta} | 0 .../ConditionalHideByEnumAttribute.cs | 31 +++++++ ...=> ConditionalHideByEnumAttribute.cs.meta} | 0 .../ConditionalShowByEnumAttribute.cs | 34 +++++++ ...=> ConditionalShowByEnumAttribute.cs.meta} | 0 ...tribute.cs => DescriptionEnumAttribute.cs} | 4 +- ....meta => DescriptionEnumAttribute.cs.meta} | 0 ...ringsAttribute.cs => DropdownAttribute.cs} | 4 +- ...bute.cs.meta => DropdownAttribute.cs.meta} | 0 .../HideInInspectorByEnumAttribute.cs | 68 -------------- .../Attributes/InterfaceValidationDrawer.cs | 33 ------- .../InterfaceValidationDrawer.cs.meta | 2 - Runtime/Core/Attributes/LineAttribute.cs | 17 ++++ ...ttribute.cs.meta => LineAttribute.cs.meta} | 0 .../Core/Attributes/MinMaxRangeAttribute.cs | 64 ++------------ Runtime/Core/Attributes/PopupListAttribute.cs | 27 ++++++ ...ute.cs.meta => PopupListAttribute.cs.meta} | 0 Runtime/Core/Attributes/ReadOnlyAttribute.cs | 35 ++------ Runtime/Core/Attributes/SeparatorAttribute.cs | 53 ----------- .../ShowInInspectorByEnumAttribute.cs | 81 ----------------- Runtime/Core/Attributes/ShowOnlyAttribute.cs | 55 +++--------- Runtime/Core/Attributes/ShowTypeAttribute.cs | 88 ------------------- .../Core/Attributes/TagSelectorAttribute.cs | 43 ++------- .../Core/Attributes/TypeSelectorAttribute.cs | 22 +++++ ....cs.meta => TypeSelectorAttribute.cs.meta} | 0 Runtime/Pattern/Managers/UIManager.cs | 8 +- .../ReadySet/Commands/Execut/C_ScneLoader.cs | 12 +-- Runtime/ReadySet/Managers/SaveManager.cs | 10 +-- Runtime/Toolkit/PCG/PCG.cs | 4 +- 54 files changed, 527 insertions(+), 548 deletions(-) rename Editor/Core/Drawers/{ExpandableDrawer.cs => AssetInlinDrawer.cs} (98%) rename Editor/Core/Drawers/{ExpandableDrawer.cs.meta => AssetInlinDrawer.cs.meta} (100%) create mode 100644 Editor/Core/Drawers/ConditionalHideByEnumDrawer.cs create mode 100644 Editor/Core/Drawers/ConditionalHideByEnumDrawer.cs.meta create mode 100644 Editor/Core/Drawers/ConditionalShowByEnumDrawer.cs create mode 100644 Editor/Core/Drawers/ConditionalShowByEnumDrawer.cs.meta rename Editor/Core/Drawers/{EnumDescriptionDrawer.cs => DescriptionEnumDrawer.cs} (89%) rename Editor/Core/Drawers/{EnumDescriptionDrawer.cs.meta => DescriptionEnumDrawer.cs.meta} (100%) rename Editor/Core/Drawers/{DropdownFromStringsDrawer.cs => DropdownDrawer.cs} (82%) rename Editor/Core/Drawers/{DropdownFromStringsDrawer.cs.meta => DropdownDrawer.cs.meta} (100%) create mode 100644 Editor/Core/Drawers/LineDrawer.cs create mode 100644 Editor/Core/Drawers/LineDrawer.cs.meta create mode 100644 Editor/Core/Drawers/MinMaxRangeDrawer.cs create mode 100644 Editor/Core/Drawers/MinMaxRangeDrawer.cs.meta rename Runtime/Core/Attributes/ListToPopupAttribute.cs => Editor/Core/Drawers/PopupListDrawer.cs (64%) create mode 100644 Editor/Core/Drawers/PopupListDrawer.cs.meta create mode 100644 Editor/Core/Drawers/ReadOnlyDrawer.cs create mode 100644 Editor/Core/Drawers/ReadOnlyDrawer.cs.meta create mode 100644 Editor/Core/Drawers/ShowOnlyDrawer.cs create mode 100644 Editor/Core/Drawers/ShowOnlyDrawer.cs.meta create mode 100644 Editor/Core/Drawers/TagSelectorDrawer.cs create mode 100644 Editor/Core/Drawers/TagSelectorDrawer.cs.meta create mode 100644 Editor/Core/Drawers/TypeSelectorDrawer.cs create mode 100644 Editor/Core/Drawers/TypeSelectorDrawer.cs.meta rename Runtime/Core/Attributes/{ExpandableAttribute.cs => AssetInlinAttribute.cs} (81%) rename Runtime/Core/Attributes/{ExpandableAttribute.cs.meta => AssetInlinAttribute.cs.meta} (100%) create mode 100644 Runtime/Core/Attributes/ConditionalHideByEnumAttribute.cs rename Runtime/Core/Attributes/{HideInInspectorByEnumAttribute.cs.meta => ConditionalHideByEnumAttribute.cs.meta} (100%) create mode 100644 Runtime/Core/Attributes/ConditionalShowByEnumAttribute.cs rename Runtime/Core/Attributes/{ShowInInspectorByEnumAttribute.cs.meta => ConditionalShowByEnumAttribute.cs.meta} (100%) rename Runtime/Core/Attributes/{EnumDescriptionAttribute.cs => DescriptionEnumAttribute.cs} (83%) rename Runtime/Core/Attributes/{EnumDescriptionAttribute.cs.meta => DescriptionEnumAttribute.cs.meta} (100%) rename Runtime/Core/Attributes/{DropdownFromStringsAttribute.cs => DropdownAttribute.cs} (76%) rename Runtime/Core/Attributes/{DropdownFromStringsAttribute.cs.meta => DropdownAttribute.cs.meta} (100%) delete mode 100644 Runtime/Core/Attributes/HideInInspectorByEnumAttribute.cs delete mode 100644 Runtime/Core/Attributes/InterfaceValidationDrawer.cs delete mode 100644 Runtime/Core/Attributes/InterfaceValidationDrawer.cs.meta create mode 100644 Runtime/Core/Attributes/LineAttribute.cs rename Runtime/Core/Attributes/{SeparatorAttribute.cs.meta => LineAttribute.cs.meta} (100%) create mode 100644 Runtime/Core/Attributes/PopupListAttribute.cs rename Runtime/Core/Attributes/{ListToPopupAttribute.cs.meta => PopupListAttribute.cs.meta} (100%) delete mode 100644 Runtime/Core/Attributes/SeparatorAttribute.cs delete mode 100644 Runtime/Core/Attributes/ShowInInspectorByEnumAttribute.cs delete mode 100644 Runtime/Core/Attributes/ShowTypeAttribute.cs create mode 100644 Runtime/Core/Attributes/TypeSelectorAttribute.cs rename Runtime/Core/Attributes/{ShowTypeAttribute.cs.meta => TypeSelectorAttribute.cs.meta} (100%) diff --git a/Editor/Core/Drawers/ExpandableDrawer.cs b/Editor/Core/Drawers/AssetInlinDrawer.cs similarity index 98% rename from Editor/Core/Drawers/ExpandableDrawer.cs rename to Editor/Core/Drawers/AssetInlinDrawer.cs index ca73b59..6d60255 100644 --- a/Editor/Core/Drawers/ExpandableDrawer.cs +++ b/Editor/Core/Drawers/AssetInlinDrawer.cs @@ -8,8 +8,8 @@ namespace RealMethod.Editor /// /// Draws the property field for any field marked with ExpandableAttribute. /// - [CustomPropertyDrawer(typeof(ExpandableAttribute), true)] - public class ExpandableDrawer : PropertyDrawer + [CustomPropertyDrawer(typeof(AssetInlinAttribute), true)] + public class AssetInlinDrawer : PropertyDrawer { // Style Setup // Use the following area to change the style of the expandable ScriptableObject drawers; diff --git a/Editor/Core/Drawers/ExpandableDrawer.cs.meta b/Editor/Core/Drawers/AssetInlinDrawer.cs.meta similarity index 100% rename from Editor/Core/Drawers/ExpandableDrawer.cs.meta rename to Editor/Core/Drawers/AssetInlinDrawer.cs.meta diff --git a/Editor/Core/Drawers/ConditionalHideByEnumDrawer.cs b/Editor/Core/Drawers/ConditionalHideByEnumDrawer.cs new file mode 100644 index 0000000..59cd76c --- /dev/null +++ b/Editor/Core/Drawers/ConditionalHideByEnumDrawer.cs @@ -0,0 +1,35 @@ +using UnityEditor; +using UnityEngine; + +namespace RealMethod.Editor +{ + [CustomPropertyDrawer(typeof(ConditionalHideByEnumAttribute))] + public class ConditionalHideByEnumDrawer : PropertyDrawer + { + public override void OnGUI(Rect position, SerializedProperty property, GUIContent label) + { + ConditionalHideByEnumAttribute hideAttribute = (ConditionalHideByEnumAttribute)attribute; + SerializedProperty enumField = property.serializedObject.FindProperty(hideAttribute.EnumFieldName); + + if (enumField != null && enumField.enumValueIndex == hideAttribute.EnumValue) + { + return; // Do not draw the property if the condition matches. + } + + EditorGUI.PropertyField(position, property, label, true); + } + + public override float GetPropertyHeight(SerializedProperty property, GUIContent label) + { + ConditionalHideByEnumAttribute hideAttribute = (ConditionalHideByEnumAttribute)attribute; + SerializedProperty enumField = property.serializedObject.FindProperty(hideAttribute.EnumFieldName); + + if (enumField != null && enumField.enumValueIndex == hideAttribute.EnumValue) + { + return 0; // Hides the property by returning 0 height. + } + + return EditorGUI.GetPropertyHeight(property, label, true); + } + } +} \ No newline at end of file diff --git a/Editor/Core/Drawers/ConditionalHideByEnumDrawer.cs.meta b/Editor/Core/Drawers/ConditionalHideByEnumDrawer.cs.meta new file mode 100644 index 0000000..f4b0235 --- /dev/null +++ b/Editor/Core/Drawers/ConditionalHideByEnumDrawer.cs.meta @@ -0,0 +1,2 @@ +fileFormatVersion: 2 +guid: 07df77986e5a9f64eb6288db1009335b \ No newline at end of file diff --git a/Editor/Core/Drawers/ConditionalShowByEnumDrawer.cs b/Editor/Core/Drawers/ConditionalShowByEnumDrawer.cs new file mode 100644 index 0000000..20fc2ca --- /dev/null +++ b/Editor/Core/Drawers/ConditionalShowByEnumDrawer.cs @@ -0,0 +1,46 @@ +using UnityEditor; +using UnityEngine; + +namespace RealMethod.Editor +{ + [CustomPropertyDrawer(typeof(ConditionalShowByEnumAttribute))] + public class ConditionalShowByEnumDrawer : PropertyDrawer + { + public override void OnGUI(Rect position, SerializedProperty property, GUIContent label) + { + ConditionalShowByEnumAttribute showInInspector = (ConditionalShowByEnumAttribute)attribute; + SerializedProperty enumField = property.serializedObject.FindProperty(showInInspector.EnumFieldName); + + if (enumField != null && IsVisible(enumField, showInInspector.ShowValues)) + { + EditorGUI.PropertyField(position, property, label); + } + } + + public override float GetPropertyHeight(SerializedProperty property, GUIContent label) + { + ConditionalShowByEnumAttribute showInInspector = (ConditionalShowByEnumAttribute)attribute; + SerializedProperty enumField = property.serializedObject.FindProperty(showInInspector.EnumFieldName); + + if (enumField != null && IsVisible(enumField, showInInspector.ShowValues)) + { + return EditorGUI.GetPropertyHeight(property, label, true); + } + + return 0; // Hides the property + } + + private bool IsVisible(SerializedProperty enumField, object[] showValues) + { + foreach (var value in showValues) + { + if (enumField.propertyType == SerializedPropertyType.Enum && enumField.enumValueIndex == (int)value) + { + return true; + } + } + + return false; + } + } +} \ No newline at end of file diff --git a/Editor/Core/Drawers/ConditionalShowByEnumDrawer.cs.meta b/Editor/Core/Drawers/ConditionalShowByEnumDrawer.cs.meta new file mode 100644 index 0000000..054c05a --- /dev/null +++ b/Editor/Core/Drawers/ConditionalShowByEnumDrawer.cs.meta @@ -0,0 +1,2 @@ +fileFormatVersion: 2 +guid: efb65d24cd2c9e04c867b0cae6a7d5ef \ No newline at end of file diff --git a/Editor/Core/Drawers/EnumDescriptionDrawer.cs b/Editor/Core/Drawers/DescriptionEnumDrawer.cs similarity index 89% rename from Editor/Core/Drawers/EnumDescriptionDrawer.cs rename to Editor/Core/Drawers/DescriptionEnumDrawer.cs index 929b688..5f802a4 100644 --- a/Editor/Core/Drawers/EnumDescriptionDrawer.cs +++ b/Editor/Core/Drawers/DescriptionEnumDrawer.cs @@ -4,8 +4,8 @@ namespace RealMethod.Editor { - [CustomPropertyDrawer(typeof(EnumDescriptionAttribute))] - public class EnumDescriptionDrawer : PropertyDrawer + [CustomPropertyDrawer(typeof(DescriptionEnumAttribute))] + public class DescriptionEnumDrawer : PropertyDrawer { public override void OnGUI(Rect position, SerializedProperty property, GUIContent label) { @@ -43,7 +43,7 @@ private string[] GetEnumDescriptions(Type enumType) for (int i = 0; i < names.Length; i++) { var field = enumType.GetField(names[i]); - var descriptionAttribute = Attribute.GetCustomAttribute(field, typeof(EnumDescriptionAttribute)) as EnumDescriptionAttribute; + var descriptionAttribute = Attribute.GetCustomAttribute(field, typeof(DescriptionEnumAttribute)) as DescriptionEnumAttribute; descriptions[i] = descriptionAttribute != null ? descriptionAttribute.Description : names[i]; } diff --git a/Editor/Core/Drawers/EnumDescriptionDrawer.cs.meta b/Editor/Core/Drawers/DescriptionEnumDrawer.cs.meta similarity index 100% rename from Editor/Core/Drawers/EnumDescriptionDrawer.cs.meta rename to Editor/Core/Drawers/DescriptionEnumDrawer.cs.meta diff --git a/Editor/Core/Drawers/DropdownFromStringsDrawer.cs b/Editor/Core/Drawers/DropdownDrawer.cs similarity index 82% rename from Editor/Core/Drawers/DropdownFromStringsDrawer.cs rename to Editor/Core/Drawers/DropdownDrawer.cs index b7691c7..0bc2d7f 100644 --- a/Editor/Core/Drawers/DropdownFromStringsDrawer.cs +++ b/Editor/Core/Drawers/DropdownDrawer.cs @@ -3,12 +3,12 @@ namespace RealMethod.Editor { - [CustomPropertyDrawer(typeof(DropdownFromStringsAttribute))] - public class DropdownFromStringsDrawer : PropertyDrawer + [CustomPropertyDrawer(typeof(DropdownAttribute))] + public class DropdownDrawer : PropertyDrawer { public override void OnGUI(Rect position, SerializedProperty property, GUIContent label) { - DropdownFromStringsAttribute dropdownAttribute = (DropdownFromStringsAttribute)attribute; + DropdownAttribute dropdownAttribute = (DropdownAttribute)attribute; if (property.propertyType == SerializedPropertyType.String) { diff --git a/Editor/Core/Drawers/DropdownFromStringsDrawer.cs.meta b/Editor/Core/Drawers/DropdownDrawer.cs.meta similarity index 100% rename from Editor/Core/Drawers/DropdownFromStringsDrawer.cs.meta rename to Editor/Core/Drawers/DropdownDrawer.cs.meta diff --git a/Editor/Core/Drawers/LineDrawer.cs b/Editor/Core/Drawers/LineDrawer.cs new file mode 100644 index 0000000..b13c274 --- /dev/null +++ b/Editor/Core/Drawers/LineDrawer.cs @@ -0,0 +1,39 @@ +using UnityEditor; +using UnityEngine; + +namespace RealMethod.Editor +{ + [CustomPropertyDrawer(typeof(LineAttribute))] + public class LineDrawer : DecoratorDrawer + { + public override void OnGUI(Rect position) + { + // get a reference to the attribute + LineAttribute separatorAttribute + = attribute as LineAttribute; + // define the line to draw + Rect separatorRect = new Rect(position.xMin, + position.yMin + separatorAttribute.Spacing, + position.width, + separatorAttribute.Height); + // draw it + Color lineColor = EditorGUIUtility.isProSkin + ? new Color(0.2f, 0.2f, 0.2f, 1) + : new Color(0.7f, 0.7f, 0.7f, 1); + + EditorGUI.DrawRect(separatorRect, lineColor); + } + + public override float GetHeight() + { + LineAttribute separatorAttribute + = attribute as LineAttribute; + + float totalSpacing = separatorAttribute.Spacing + + separatorAttribute.Height + + separatorAttribute.Spacing; + + return totalSpacing; + } + } +} \ No newline at end of file diff --git a/Editor/Core/Drawers/LineDrawer.cs.meta b/Editor/Core/Drawers/LineDrawer.cs.meta new file mode 100644 index 0000000..62243d7 --- /dev/null +++ b/Editor/Core/Drawers/LineDrawer.cs.meta @@ -0,0 +1,2 @@ +fileFormatVersion: 2 +guid: e2604c09d5b614044a87657f1f3c6b54 \ No newline at end of file diff --git a/Editor/Core/Drawers/MinMaxRangeDrawer.cs b/Editor/Core/Drawers/MinMaxRangeDrawer.cs new file mode 100644 index 0000000..a1ab262 --- /dev/null +++ b/Editor/Core/Drawers/MinMaxRangeDrawer.cs @@ -0,0 +1,51 @@ +using UnityEditor; +using UnityEngine; + +namespace RealMethod.Editor +{ + [CustomPropertyDrawer(typeof(MinMaxRangeAttribute))] + public class MinMaxRangeDrawer : PropertyDrawer + { + public override void OnGUI(Rect position, SerializedProperty property, GUIContent label) + { + if (property.propertyType == SerializedPropertyType.Vector2) + { + MinMaxRangeAttribute range = (MinMaxRangeAttribute)attribute; + + Vector2 value = property.vector2Value; + + EditorGUI.BeginProperty(position, label, property); + + // Draw label + position = EditorGUI.PrefixLabel(position, label); + + // Draw min-max slider + float min = value.x; + float max = value.y; + + float sliderWidth = position.width * 0.6f; + float fieldWidth = (position.width - sliderWidth) / 2f; + + Rect minFieldRect = new Rect(position.x, position.y, fieldWidth - 2, position.height); + Rect sliderRect = new Rect(position.x + fieldWidth, position.y, sliderWidth, position.height); + Rect maxFieldRect = new Rect(position.x + fieldWidth + sliderWidth + 2, position.y, fieldWidth - 2, position.height); + + min = EditorGUI.FloatField(minFieldRect, min); + EditorGUI.MinMaxSlider(sliderRect, ref min, ref max, range.minLimit, range.maxLimit); + max = EditorGUI.FloatField(maxFieldRect, max); + + // Clamp values + min = Mathf.Clamp(min, range.minLimit, max); + max = Mathf.Clamp(max, min, range.maxLimit); + + property.vector2Value = new Vector2(min, max); + + EditorGUI.EndProperty(); + } + else + { + EditorGUI.LabelField(position, label.text, "Use MinMaxRange with Vector2"); + } + } + } +} \ No newline at end of file diff --git a/Editor/Core/Drawers/MinMaxRangeDrawer.cs.meta b/Editor/Core/Drawers/MinMaxRangeDrawer.cs.meta new file mode 100644 index 0000000..b063972 --- /dev/null +++ b/Editor/Core/Drawers/MinMaxRangeDrawer.cs.meta @@ -0,0 +1,2 @@ +fileFormatVersion: 2 +guid: 06fcdbe99bffac94b949f0b3d29aabe7 \ No newline at end of file diff --git a/Runtime/Core/Attributes/ListToPopupAttribute.cs b/Editor/Core/Drawers/PopupListDrawer.cs similarity index 64% rename from Runtime/Core/Attributes/ListToPopupAttribute.cs rename to Editor/Core/Drawers/PopupListDrawer.cs index 86c823d..b0a93d1 100644 --- a/Runtime/Core/Attributes/ListToPopupAttribute.cs +++ b/Editor/Core/Drawers/PopupListDrawer.cs @@ -1,33 +1,16 @@ -using System; using System.Collections.Generic; using System.Reflection; -#if UNITY_EDITOR using UnityEditor; -#endif using UnityEngine; -namespace RealMethod +namespace RealMethod.Editor { - public class ListToPopupAttribute : PropertyAttribute - { - public Type myType; - public string propertyName; - - public ListToPopupAttribute(Type _myType, string _propertyName) - { - myType = _myType; - propertyName = _propertyName; - } - } - -#if UNITY_EDITOR - - [CustomPropertyDrawer(typeof(ListToPopupAttribute))] - public class ListToPopupDrawer : PropertyDrawer + [CustomPropertyDrawer(typeof(PopupListAttribute))] + public class PopupListDrawer : PropertyDrawer { public override void OnGUI(Rect position, SerializedProperty property, GUIContent label) { - ListToPopupAttribute atb = attribute as ListToPopupAttribute; + PopupListAttribute atb = attribute as PopupListAttribute; List stringList = null; // Get the field using reflection @@ -57,10 +40,4 @@ public override void OnGUI(Rect position, SerializedProperty property, GUIConten } } } - -#endif -} -// ------------Use -// [ListToPopup(typeof(ExampleClass), "options")] -// public string selectedOption; -// public static List options = new List { "Option1", "Option2", "Option3" }; +} \ No newline at end of file diff --git a/Editor/Core/Drawers/PopupListDrawer.cs.meta b/Editor/Core/Drawers/PopupListDrawer.cs.meta new file mode 100644 index 0000000..6c9a03b --- /dev/null +++ b/Editor/Core/Drawers/PopupListDrawer.cs.meta @@ -0,0 +1,2 @@ +fileFormatVersion: 2 +guid: a289ef88415dda149980554c00cc8cfe \ No newline at end of file diff --git a/Editor/Core/Drawers/ReadOnlyDrawer.cs b/Editor/Core/Drawers/ReadOnlyDrawer.cs new file mode 100644 index 0000000..3d0b1ad --- /dev/null +++ b/Editor/Core/Drawers/ReadOnlyDrawer.cs @@ -0,0 +1,21 @@ +using UnityEditor; +using UnityEngine; + +namespace RealMethod.Editor +{ + [CustomPropertyDrawer(typeof(ReadOnlyAttribute))] + public class ReadOnlyDrawer : PropertyDrawer + { + public override void OnGUI(Rect position, SerializedProperty property, GUIContent label) + { + GUI.enabled = false; // Disable the GUI + EditorGUI.PropertyField(position, property, label, true); + GUI.enabled = true; // Enable the GUI + } + + public override float GetPropertyHeight(SerializedProperty property, GUIContent label) + { + return EditorGUI.GetPropertyHeight(property, label, true); + } + } +} \ No newline at end of file diff --git a/Editor/Core/Drawers/ReadOnlyDrawer.cs.meta b/Editor/Core/Drawers/ReadOnlyDrawer.cs.meta new file mode 100644 index 0000000..521007c --- /dev/null +++ b/Editor/Core/Drawers/ReadOnlyDrawer.cs.meta @@ -0,0 +1,2 @@ +fileFormatVersion: 2 +guid: d44334cf564e8644e8c743b8e93b2507 \ No newline at end of file diff --git a/Editor/Core/Drawers/ShowOnlyDrawer.cs b/Editor/Core/Drawers/ShowOnlyDrawer.cs new file mode 100644 index 0000000..58c3bd8 --- /dev/null +++ b/Editor/Core/Drawers/ShowOnlyDrawer.cs @@ -0,0 +1,35 @@ +using UnityEditor; +using UnityEngine; + +namespace RealMethod.Editor +{ + [CustomPropertyDrawer(typeof(ShowOnlyAttribute))] + public class ShowOnlyDrawer : PropertyDrawer + { + public override void OnGUI(Rect position, SerializedProperty prop, GUIContent label) + { + string valueStr; + + switch (prop.propertyType) + { + case SerializedPropertyType.Integer: + valueStr = prop.intValue.ToString(); + break; + case SerializedPropertyType.Boolean: + valueStr = prop.boolValue.ToString(); + break; + case SerializedPropertyType.Float: + valueStr = prop.floatValue.ToString("0.00000"); + break; + case SerializedPropertyType.String: + valueStr = prop.stringValue; + break; + default: + valueStr = "(not supported)"; + break; + } + + EditorGUI.LabelField(position, label.text, valueStr); + } + } +} \ No newline at end of file diff --git a/Editor/Core/Drawers/ShowOnlyDrawer.cs.meta b/Editor/Core/Drawers/ShowOnlyDrawer.cs.meta new file mode 100644 index 0000000..17459be --- /dev/null +++ b/Editor/Core/Drawers/ShowOnlyDrawer.cs.meta @@ -0,0 +1,2 @@ +fileFormatVersion: 2 +guid: 24cc41ec6d04b4344b61e6551c7320ef \ No newline at end of file diff --git a/Editor/Core/Drawers/TagSelectorDrawer.cs b/Editor/Core/Drawers/TagSelectorDrawer.cs new file mode 100644 index 0000000..f45531d --- /dev/null +++ b/Editor/Core/Drawers/TagSelectorDrawer.cs @@ -0,0 +1,31 @@ +using UnityEditor; +using UnityEngine; + +namespace RealMethod.Editor +{ + [CustomPropertyDrawer(typeof(TagSelectorAttribute))] + public class TagSelectorDrawer : PropertyDrawer + { + public override void OnGUI(Rect position, SerializedProperty property, GUIContent label) + { + TagSelectorAttribute tagSelector = (TagSelectorAttribute)attribute; + + if (tagSelector.UseDefaultTagFieldDrawer) + { + EditorGUI.PropertyField(position, property, label); + } + else + { + if (property.propertyType == SerializedPropertyType.String) + { + property.stringValue = EditorGUI.TagField(position, label, property.stringValue); + } + else + { + EditorGUI.PropertyField(position, property, label); + EditorGUI.HelpBox(position, "TagSelector can only be used with strings.", MessageType.Error); + } + } + } + } +} \ No newline at end of file diff --git a/Editor/Core/Drawers/TagSelectorDrawer.cs.meta b/Editor/Core/Drawers/TagSelectorDrawer.cs.meta new file mode 100644 index 0000000..b81f84f --- /dev/null +++ b/Editor/Core/Drawers/TagSelectorDrawer.cs.meta @@ -0,0 +1,2 @@ +fileFormatVersion: 2 +guid: c3a11f74a60467949a0aea20cd3c704c \ No newline at end of file diff --git a/Editor/Core/Drawers/TypeSelectorDrawer.cs b/Editor/Core/Drawers/TypeSelectorDrawer.cs new file mode 100644 index 0000000..fdcfa46 --- /dev/null +++ b/Editor/Core/Drawers/TypeSelectorDrawer.cs @@ -0,0 +1,51 @@ +using System; +using System.Linq; +using UnityEditor; +using UnityEngine; + +namespace RealMethod.Editor +{ + [CustomPropertyDrawer(typeof(TypeSelectorAttribute))] + public class TypeSelectorDrawer : PropertyDrawer + { + public override void OnGUI(Rect position, SerializedProperty property, GUIContent label) + { + TypeSelectorAttribute typeSelector = (TypeSelectorAttribute)attribute; + + + if (property.propertyType == SerializedPropertyType.String) + { + // Get all types derived from the specified base type + Type[] types = AppDomain.CurrentDomain.GetAssemblies() + .SelectMany(assembly => assembly.GetTypes()) + .Where(t => typeSelector.BaseType.IsAssignableFrom(t) && !t.IsAbstract) + .ToArray(); + + // Get the current type + string ClassName = property.stringValue; + Type currentType = !string.IsNullOrEmpty(ClassName) ? Type.GetType(ClassName) : null; + + // Get type names for the dropdown + string[] typeNames = types.Select(t => t.FullName).ToArray(); + int currentIndex = Array.IndexOf(typeNames, currentType?.FullName); + + // Show the dropdown in the Inspector + int selectedIndex = EditorGUI.Popup(position, label.text, currentIndex, typeNames); + + // Update the selected type + if (selectedIndex >= 0 && selectedIndex < types.Length) + { + property.stringValue = types[selectedIndex].AssemblyQualifiedName; + } + else + { + property.stringValue = string.Empty; + } + } + else + { + EditorGUI.LabelField(position, label.text, "Use TypeSelector with string."); + } + } + } +} \ No newline at end of file diff --git a/Editor/Core/Drawers/TypeSelectorDrawer.cs.meta b/Editor/Core/Drawers/TypeSelectorDrawer.cs.meta new file mode 100644 index 0000000..7ee3538 --- /dev/null +++ b/Editor/Core/Drawers/TypeSelectorDrawer.cs.meta @@ -0,0 +1,2 @@ +fileFormatVersion: 2 +guid: bbe6e5799205f324690a4af7e1a541d0 \ No newline at end of file diff --git a/Runtime/Core/Attributes/ExpandableAttribute.cs b/Runtime/Core/Attributes/AssetInlinAttribute.cs similarity index 81% rename from Runtime/Core/Attributes/ExpandableAttribute.cs rename to Runtime/Core/Attributes/AssetInlinAttribute.cs index 9aa81dc..50765c7 100644 --- a/Runtime/Core/Attributes/ExpandableAttribute.cs +++ b/Runtime/Core/Attributes/AssetInlinAttribute.cs @@ -10,9 +10,9 @@ namespace RealMethod /// public ScriptableObject TEST; /// /// - public class ExpandableAttribute : PropertyAttribute + public class AssetInlinAttribute : PropertyAttribute { - public ExpandableAttribute() + public AssetInlinAttribute() { } } diff --git a/Runtime/Core/Attributes/ExpandableAttribute.cs.meta b/Runtime/Core/Attributes/AssetInlinAttribute.cs.meta similarity index 100% rename from Runtime/Core/Attributes/ExpandableAttribute.cs.meta rename to Runtime/Core/Attributes/AssetInlinAttribute.cs.meta diff --git a/Runtime/Core/Attributes/ConditionalHideByEnumAttribute.cs b/Runtime/Core/Attributes/ConditionalHideByEnumAttribute.cs new file mode 100644 index 0000000..5999034 --- /dev/null +++ b/Runtime/Core/Attributes/ConditionalHideByEnumAttribute.cs @@ -0,0 +1,31 @@ +using UnityEngine; + + +namespace RealMethod +{ + /// + /// Example: + /// public enum DisplayMode + /// { + /// Mode1, + /// Mode2, + /// Mode3 + /// } + /// + /// public DisplayMode displayMode; + /// + /// [HideInInspectorByEnum("displayMode", 0)] + /// public int DisplaySize_Mode_1; + /// + public class ConditionalHideByEnumAttribute : PropertyAttribute + { + public string EnumFieldName { get; private set; } + public int EnumValue { get; private set; } + + public ConditionalHideByEnumAttribute(string enumFieldName, int enumValue) + { + EnumFieldName = enumFieldName; + EnumValue = enumValue; + } + } +} \ No newline at end of file diff --git a/Runtime/Core/Attributes/HideInInspectorByEnumAttribute.cs.meta b/Runtime/Core/Attributes/ConditionalHideByEnumAttribute.cs.meta similarity index 100% rename from Runtime/Core/Attributes/HideInInspectorByEnumAttribute.cs.meta rename to Runtime/Core/Attributes/ConditionalHideByEnumAttribute.cs.meta diff --git a/Runtime/Core/Attributes/ConditionalShowByEnumAttribute.cs b/Runtime/Core/Attributes/ConditionalShowByEnumAttribute.cs new file mode 100644 index 0000000..1b8a7dc --- /dev/null +++ b/Runtime/Core/Attributes/ConditionalShowByEnumAttribute.cs @@ -0,0 +1,34 @@ +using System; +using UnityEngine; + +namespace RealMethod +{ + /// + /// + /// public enum ExampleEnum + /// { + /// Option1, + /// Option2, + /// Option3 + /// } + /// + /// public ExampleEnum exampleEnum; + /// [ConditionalShowByEnum("exampleEnum", ExampleEnum.Option1, ExampleEnum.Option3)] + /// public string visibleOnlyForOption1And3; + /// [ConditionalShowByEnum("exampleEnum", ExampleEnum.Option2)] + /// public int visibleOnlyForOption2; + /// + /// + [AttributeUsage(AttributeTargets.Field, AllowMultiple = false)] + public class ConditionalShowByEnumAttribute : PropertyAttribute + { + public string EnumFieldName { get; } + public object[] ShowValues { get; } + + public ConditionalShowByEnumAttribute(string enumFieldName, params object[] showValues) + { + EnumFieldName = enumFieldName; + ShowValues = showValues; + } + } +} diff --git a/Runtime/Core/Attributes/ShowInInspectorByEnumAttribute.cs.meta b/Runtime/Core/Attributes/ConditionalShowByEnumAttribute.cs.meta similarity index 100% rename from Runtime/Core/Attributes/ShowInInspectorByEnumAttribute.cs.meta rename to Runtime/Core/Attributes/ConditionalShowByEnumAttribute.cs.meta diff --git a/Runtime/Core/Attributes/EnumDescriptionAttribute.cs b/Runtime/Core/Attributes/DescriptionEnumAttribute.cs similarity index 83% rename from Runtime/Core/Attributes/EnumDescriptionAttribute.cs rename to Runtime/Core/Attributes/DescriptionEnumAttribute.cs index e06b0d8..90228a4 100644 --- a/Runtime/Core/Attributes/EnumDescriptionAttribute.cs +++ b/Runtime/Core/Attributes/DescriptionEnumAttribute.cs @@ -18,10 +18,10 @@ namespace RealMethod /// /// [AttributeUsage(AttributeTargets.Field, AllowMultiple = false)] - public class EnumDescriptionAttribute : PropertyAttribute + public class DescriptionEnumAttribute : PropertyAttribute { public string Description { get; } - public EnumDescriptionAttribute(string description) + public DescriptionEnumAttribute(string description) { Description = description; } diff --git a/Runtime/Core/Attributes/EnumDescriptionAttribute.cs.meta b/Runtime/Core/Attributes/DescriptionEnumAttribute.cs.meta similarity index 100% rename from Runtime/Core/Attributes/EnumDescriptionAttribute.cs.meta rename to Runtime/Core/Attributes/DescriptionEnumAttribute.cs.meta diff --git a/Runtime/Core/Attributes/DropdownFromStringsAttribute.cs b/Runtime/Core/Attributes/DropdownAttribute.cs similarity index 76% rename from Runtime/Core/Attributes/DropdownFromStringsAttribute.cs rename to Runtime/Core/Attributes/DropdownAttribute.cs index 9640b33..fb2d402 100644 --- a/Runtime/Core/Attributes/DropdownFromStringsAttribute.cs +++ b/Runtime/Core/Attributes/DropdownAttribute.cs @@ -12,11 +12,11 @@ namespace RealMethod /// public int selectedOptionIndex; /// /// - public class DropdownFromStringsAttribute : PropertyAttribute + public class DropdownAttribute : PropertyAttribute { public string[] options; - public DropdownFromStringsAttribute(params string[] options) + public DropdownAttribute(params string[] options) { this.options = options; } diff --git a/Runtime/Core/Attributes/DropdownFromStringsAttribute.cs.meta b/Runtime/Core/Attributes/DropdownAttribute.cs.meta similarity index 100% rename from Runtime/Core/Attributes/DropdownFromStringsAttribute.cs.meta rename to Runtime/Core/Attributes/DropdownAttribute.cs.meta diff --git a/Runtime/Core/Attributes/HideInInspectorByEnumAttribute.cs b/Runtime/Core/Attributes/HideInInspectorByEnumAttribute.cs deleted file mode 100644 index 719a709..0000000 --- a/Runtime/Core/Attributes/HideInInspectorByEnumAttribute.cs +++ /dev/null @@ -1,68 +0,0 @@ -#if UNITY_EDITOR -using UnityEditor; -#endif -using UnityEngine; - - -namespace RealMethod -{ - public class HideInInspectorByEnumAttribute : PropertyAttribute - { - public string EnumFieldName { get; private set; } - public int EnumValue { get; private set; } - - public HideInInspectorByEnumAttribute(string enumFieldName, int enumValue) - { - EnumFieldName = enumFieldName; - EnumValue = enumValue; - } - } - - -#if UNITY_EDITOR - - [CustomPropertyDrawer(typeof(HideInInspectorByEnumAttribute))] - public class HideInInspectorByEnumDrawer : PropertyDrawer - { - public override void OnGUI(Rect position, SerializedProperty property, GUIContent label) - { - HideInInspectorByEnumAttribute hideAttribute = (HideInInspectorByEnumAttribute)attribute; - SerializedProperty enumField = property.serializedObject.FindProperty(hideAttribute.EnumFieldName); - - if (enumField != null && enumField.enumValueIndex == hideAttribute.EnumValue) - { - return; // Do not draw the property if the condition matches. - } - - EditorGUI.PropertyField(position, property, label, true); - } - - public override float GetPropertyHeight(SerializedProperty property, GUIContent label) - { - HideInInspectorByEnumAttribute hideAttribute = (HideInInspectorByEnumAttribute)attribute; - SerializedProperty enumField = property.serializedObject.FindProperty(hideAttribute.EnumFieldName); - - if (enumField != null && enumField.enumValueIndex == hideAttribute.EnumValue) - { - return 0; // Hides the property by returning 0 height. - } - - return EditorGUI.GetPropertyHeight(property, label, true); - } - } -#endif -} - - -///////////Use -// public enum DisplayMode -// { -// Mode1, -// Mode2, -// Mode3 -// } - -// [SerializeField] private DisplayMode displayMode; - -// [HideInInspectorByEnum("displayMode", 0)] // Hide when DisplayMode is Mode1 -// public int mode2SpecificValue; diff --git a/Runtime/Core/Attributes/InterfaceValidationDrawer.cs b/Runtime/Core/Attributes/InterfaceValidationDrawer.cs deleted file mode 100644 index 00b01f3..0000000 --- a/Runtime/Core/Attributes/InterfaceValidationDrawer.cs +++ /dev/null @@ -1,33 +0,0 @@ -#if UNITY_EDITOR - -// public interface IMotion -// { -// void StartMotion(); -// void StopMotion(); -// } - - - -// [CustomPropertyDrawer(typeof(ScriptableObject), true)] -// public class InterfaceValidationDrawer : PropertyDrawer -// { -// public override void OnGUI(Rect position, SerializedProperty property, GUIContent label) -// { -// EditorGUI.BeginProperty(position, label, property); - -// var obj = property.objectReferenceValue; - -// // Ensure the assigned object implements the desired interface -// if (obj != null && !(obj is IMotion)) -// { -// property.objectReferenceValue = null; -// Debug.LogError("Assigned object must implement the IMotion interface."); -// } - -// EditorGUI.PropertyField(position, property, label); - -// EditorGUI.EndProperty(); -// } -// } - -#endif diff --git a/Runtime/Core/Attributes/InterfaceValidationDrawer.cs.meta b/Runtime/Core/Attributes/InterfaceValidationDrawer.cs.meta deleted file mode 100644 index 34144b2..0000000 --- a/Runtime/Core/Attributes/InterfaceValidationDrawer.cs.meta +++ /dev/null @@ -1,2 +0,0 @@ -fileFormatVersion: 2 -guid: da7b638a07bb1ce4cad9aa63e8fe6057 \ No newline at end of file diff --git a/Runtime/Core/Attributes/LineAttribute.cs b/Runtime/Core/Attributes/LineAttribute.cs new file mode 100644 index 0000000..b7d07aa --- /dev/null +++ b/Runtime/Core/Attributes/LineAttribute.cs @@ -0,0 +1,17 @@ +using UnityEngine; + +namespace RealMethod +{ + [System.AttributeUsage(System.AttributeTargets.Field, AllowMultiple = true)] + public class LineAttribute : PropertyAttribute + { + public readonly float Height; + public readonly float Spacing; + + public LineAttribute(float height = 1, float spacing = 10) + { + Height = height; + Spacing = spacing; + } + } +} \ No newline at end of file diff --git a/Runtime/Core/Attributes/SeparatorAttribute.cs.meta b/Runtime/Core/Attributes/LineAttribute.cs.meta similarity index 100% rename from Runtime/Core/Attributes/SeparatorAttribute.cs.meta rename to Runtime/Core/Attributes/LineAttribute.cs.meta diff --git a/Runtime/Core/Attributes/MinMaxRangeAttribute.cs b/Runtime/Core/Attributes/MinMaxRangeAttribute.cs index 05692f4..dde4157 100644 --- a/Runtime/Core/Attributes/MinMaxRangeAttribute.cs +++ b/Runtime/Core/Attributes/MinMaxRangeAttribute.cs @@ -1,10 +1,13 @@ using UnityEngine; -#if UNITY_EDITOR -using UnityEditor; -#endif namespace RealMethod { + /// + /// + /// [MinMaxRange(0f, 100f)] + /// public Vector2 myRange; + /// + /// public class MinMaxRangeAttribute : PropertyAttribute { public float minLimit; @@ -16,57 +19,4 @@ public MinMaxRangeAttribute(float minLimit, float maxLimit) this.maxLimit = maxLimit; } } - -#if UNITY_EDITOR - [CustomPropertyDrawer(typeof(MinMaxRangeAttribute))] - public class MinMaxRangeDrawer : PropertyDrawer - { - public override void OnGUI(Rect position, SerializedProperty property, GUIContent label) - { - if (property.propertyType == SerializedPropertyType.Vector2) - { - MinMaxRangeAttribute range = (MinMaxRangeAttribute)attribute; - - Vector2 value = property.vector2Value; - - EditorGUI.BeginProperty(position, label, property); - - // Draw label - position = EditorGUI.PrefixLabel(position, label); - - // Draw min-max slider - float min = value.x; - float max = value.y; - - float sliderWidth = position.width * 0.6f; - float fieldWidth = (position.width - sliderWidth) / 2f; - - Rect minFieldRect = new Rect(position.x, position.y, fieldWidth - 2, position.height); - Rect sliderRect = new Rect(position.x + fieldWidth, position.y, sliderWidth, position.height); - Rect maxFieldRect = new Rect(position.x + fieldWidth + sliderWidth + 2, position.y, fieldWidth - 2, position.height); - - min = EditorGUI.FloatField(minFieldRect, min); - EditorGUI.MinMaxSlider(sliderRect, ref min, ref max, range.minLimit, range.maxLimit); - max = EditorGUI.FloatField(maxFieldRect, max); - - // Clamp values - min = Mathf.Clamp(min, range.minLimit, max); - max = Mathf.Clamp(max, min, range.maxLimit); - - property.vector2Value = new Vector2(min, max); - - EditorGUI.EndProperty(); - } - else - { - EditorGUI.LabelField(position, label.text, "Use MinMaxRange with Vector2"); - } - } - } -#endif - -} - - -// [MinMaxRange(0f, 100f)] -// public MinMaxFloat myRange; \ No newline at end of file +} \ No newline at end of file diff --git a/Runtime/Core/Attributes/PopupListAttribute.cs b/Runtime/Core/Attributes/PopupListAttribute.cs new file mode 100644 index 0000000..de97206 --- /dev/null +++ b/Runtime/Core/Attributes/PopupListAttribute.cs @@ -0,0 +1,27 @@ +using System; +using UnityEngine; + +namespace RealMethod +{ + /// + /// + /// ExampleClass{ + /// public static List options = new List { "Option1", "Option2", "Option3" }; + /// } + /// + /// [ListToPopup(typeof(ExampleClass), "options")] + /// public string selectedOption; + /// + /// + public class PopupListAttribute : PropertyAttribute + { + public Type myType; + public string propertyName; + + public PopupListAttribute(Type _myType, string _propertyName) + { + myType = _myType; + propertyName = _propertyName; + } + } +} diff --git a/Runtime/Core/Attributes/ListToPopupAttribute.cs.meta b/Runtime/Core/Attributes/PopupListAttribute.cs.meta similarity index 100% rename from Runtime/Core/Attributes/ListToPopupAttribute.cs.meta rename to Runtime/Core/Attributes/PopupListAttribute.cs.meta diff --git a/Runtime/Core/Attributes/ReadOnlyAttribute.cs b/Runtime/Core/Attributes/ReadOnlyAttribute.cs index 1ffcbb4..9b45d53 100644 --- a/Runtime/Core/Attributes/ReadOnlyAttribute.cs +++ b/Runtime/Core/Attributes/ReadOnlyAttribute.cs @@ -1,33 +1,12 @@ -#if UNITY_EDITOR -using UnityEditor; -#endif using UnityEngine; namespace RealMethod { - + /// + /// + /// [ReadOnly] + /// public int readOnlyValue = 42; + /// + /// public class ReadOnlyAttribute : PropertyAttribute { } - -#if UNITY_EDITOR - - [CustomPropertyDrawer(typeof(ReadOnlyAttribute))] - public class ReadOnlyDrawer : PropertyDrawer - { - public override void OnGUI(Rect position, SerializedProperty property, GUIContent label) - { - GUI.enabled = false; // Disable the GUI - EditorGUI.PropertyField(position, property, label, true); - GUI.enabled = true; // Enable the GUI - } - - public override float GetPropertyHeight(SerializedProperty property, GUIContent label) - { - return EditorGUI.GetPropertyHeight(property, label, true); - } - } - -#endif -} - -// --------Use -// [ReadOnly] public int readOnlyValue = 42; +} \ No newline at end of file diff --git a/Runtime/Core/Attributes/SeparatorAttribute.cs b/Runtime/Core/Attributes/SeparatorAttribute.cs deleted file mode 100644 index ddf1c30..0000000 --- a/Runtime/Core/Attributes/SeparatorAttribute.cs +++ /dev/null @@ -1,53 +0,0 @@ -using UnityEngine; -#if UNITY_EDITOR -using UnityEditor; -#endif - -namespace Name -{ - - [System.AttributeUsage(System.AttributeTargets.Field, AllowMultiple = true)] - public class SeparatorAttribute : PropertyAttribute - { - public readonly float Height; - public readonly float Spacing; - - public SeparatorAttribute(float height = 1, float spacing = 10) - { - Height = height; - Spacing = spacing; - } - } - -#if UNITY_EDITOR - [CustomPropertyDrawer(typeof(SeparatorAttribute))] - public class SeparatorDrawer : DecoratorDrawer - { - public override void OnGUI(Rect position) - { - // get a reference to the attribute - SeparatorAttribute separatorAttribute - = attribute as SeparatorAttribute; - // define the line to draw - Rect separatorRect = new Rect(position.xMin, - position.yMin + separatorAttribute.Spacing, - position.width, - separatorAttribute.Height); - // draw it - EditorGUI.DrawRect(separatorRect, Color.white); - } - - public override float GetHeight() - { - SeparatorAttribute separatorAttribute - = attribute as SeparatorAttribute; - - float totalSpacing = separatorAttribute.Spacing - + separatorAttribute.Height - + separatorAttribute.Spacing; - - return totalSpacing; - } - } -#endif -} \ No newline at end of file diff --git a/Runtime/Core/Attributes/ShowInInspectorByEnumAttribute.cs b/Runtime/Core/Attributes/ShowInInspectorByEnumAttribute.cs deleted file mode 100644 index a7c81db..0000000 --- a/Runtime/Core/Attributes/ShowInInspectorByEnumAttribute.cs +++ /dev/null @@ -1,81 +0,0 @@ -using System; -using UnityEngine; -#if UNITY_EDITOR -using UnityEditor; -#endif - -[AttributeUsage(AttributeTargets.Field, AllowMultiple = false)] -public class ShowInInspectorByEnumAttribute : PropertyAttribute -{ - public string EnumFieldName { get; } - public object[] ShowValues { get; } - - public ShowInInspectorByEnumAttribute(string enumFieldName, params object[] showValues) - { - EnumFieldName = enumFieldName; - ShowValues = showValues; - } -} - - -#if UNITY_EDITOR - -[CustomPropertyDrawer(typeof(ShowInInspectorByEnumAttribute))] -public class ShowInInspectorByEnumDrawer : PropertyDrawer -{ - public override void OnGUI(Rect position, SerializedProperty property, GUIContent label) - { - ShowInInspectorByEnumAttribute showInInspector = (ShowInInspectorByEnumAttribute)attribute; - SerializedProperty enumField = property.serializedObject.FindProperty(showInInspector.EnumFieldName); - - if (enumField != null && IsVisible(enumField, showInInspector.ShowValues)) - { - EditorGUI.PropertyField(position, property, label); - } - } - - public override float GetPropertyHeight(SerializedProperty property, GUIContent label) - { - ShowInInspectorByEnumAttribute showInInspector = (ShowInInspectorByEnumAttribute)attribute; - SerializedProperty enumField = property.serializedObject.FindProperty(showInInspector.EnumFieldName); - - if (enumField != null && IsVisible(enumField, showInInspector.ShowValues)) - { - return EditorGUI.GetPropertyHeight(property, label, true); - } - - return 0; // Hides the property - } - - private bool IsVisible(SerializedProperty enumField, object[] showValues) - { - foreach (var value in showValues) - { - if (enumField.propertyType == SerializedPropertyType.Enum && enumField.enumValueIndex == (int)value) - { - return true; - } - } - - return false; - } -} -#endif - - - - -////Use -// public enum ExampleEnum -// { -// Option1, -// Option2, -// Option3 -// } -// public ExampleEnum exampleEnum; - -// [ShowInInspectorByEnum("exampleEnum", ExampleEnum.Option1, ExampleEnum.Option3)] -// public string visibleOnlyForOption1And3; - -// [ShowInInspectorByEnum("exampleEnum", ExampleEnum.Option2)] -// public int visibleOnlyForOption2; \ No newline at end of file diff --git a/Runtime/Core/Attributes/ShowOnlyAttribute.cs b/Runtime/Core/Attributes/ShowOnlyAttribute.cs index dd988b5..202c322 100644 --- a/Runtime/Core/Attributes/ShowOnlyAttribute.cs +++ b/Runtime/Core/Attributes/ShowOnlyAttribute.cs @@ -5,48 +5,19 @@ namespace RealMethod { + /// + /// + /// [ShowOnly] + /// public float aaa = 123.45678f; + /// [ShowOnly] + /// public int bbb = 234; + /// [ShowOnly] + /// public bool ccc = false; + /// [ShowOnly] + /// bool ddd = true; + /// + /// public class ShowOnlyAttribute : PropertyAttribute { } - -#if UNITY_EDITOR - [CustomPropertyDrawer(typeof(ShowOnlyAttribute))] - public class ShowOnlyDrawer : PropertyDrawer - { - public override void OnGUI(Rect position, SerializedProperty prop, GUIContent label) - { - string valueStr; - - switch (prop.propertyType) - { - case SerializedPropertyType.Integer: - valueStr = prop.intValue.ToString(); - break; - case SerializedPropertyType.Boolean: - valueStr = prop.boolValue.ToString(); - break; - case SerializedPropertyType.Float: - valueStr = prop.floatValue.ToString("0.00000"); - break; - case SerializedPropertyType.String: - valueStr = prop.stringValue; - break; - default: - valueStr = "(not supported)"; - break; - } - - EditorGUI.LabelField(position, label.text, valueStr); - } - } -#endif -} - -// Use -// public class MyClass : MonoBehaviour -// { -// [ShowOnly] public float aaa = 123.45678f; -// [ShowOnly] public int bbb = 234; -// [ShowOnly] public bool ccc = false; -// [ShowOnly] [SerializeField] bool ddd = true; -// } \ No newline at end of file +} \ No newline at end of file diff --git a/Runtime/Core/Attributes/ShowTypeAttribute.cs b/Runtime/Core/Attributes/ShowTypeAttribute.cs deleted file mode 100644 index 8417bb7..0000000 --- a/Runtime/Core/Attributes/ShowTypeAttribute.cs +++ /dev/null @@ -1,88 +0,0 @@ - -using UnityEngine; -#if UNITY_EDITOR -using UnityEditor; -#endif -using System; -using System.Linq; - - - -namespace RealMethod -{ - [Serializable] - public class TypeReference - { - public string typeName; - - public Type Type - { - get { return string.IsNullOrEmpty(typeName) ? null : Type.GetType(typeName); } - set { typeName = value == null ? string.Empty : value.AssemblyQualifiedName; } - } - - public TypeReference() { } - - public TypeReference(Type type) - { - Type = type; - } - } - - public class TypeSelectorAttribute : PropertyAttribute - { - public Type BaseType { get; private set; } - - public TypeSelectorAttribute(Type baseType = null) - { - BaseType = baseType ?? typeof(object); - } - } - - -#if UNITY_EDITOR - [CustomPropertyDrawer(typeof(TypeSelectorAttribute))] - public class TypeReferenceDrawer : PropertyDrawer - { - public override void OnGUI(Rect position, SerializedProperty property, GUIContent label) - { - TypeSelectorAttribute typeSelector = (TypeSelectorAttribute)attribute; - - // Find the type reference field - SerializedProperty typeNameProperty = property.FindPropertyRelative("typeName"); - - // Get all types derived from the specified base type - Type[] types = AppDomain.CurrentDomain.GetAssemblies() - .SelectMany(assembly => assembly.GetTypes()) - .Where(t => typeSelector.BaseType.IsAssignableFrom(t) && !t.IsAbstract) - .ToArray(); - - // Get the current type - string currentTypeName = typeNameProperty.stringValue; - Type currentType = !string.IsNullOrEmpty(currentTypeName) ? Type.GetType(currentTypeName) : null; - - // Get type names for the dropdown - string[] typeNames = types.Select(t => t.FullName).ToArray(); - int currentIndex = System.Array.IndexOf(typeNames, currentType?.FullName); - - // Show the dropdown in the Inspector - int selectedIndex = EditorGUI.Popup(position, label.text, currentIndex, typeNames); - - // Update the selected type - if (selectedIndex >= 0 && selectedIndex < types.Length) - { - typeNameProperty.stringValue = types[selectedIndex].AssemblyQualifiedName; - } - else - { - typeNameProperty.stringValue = string.Empty; - } - } - } -#endif - -} - -//Use -//[TypeSelector(typeof(MonoBehaviour))] // You can specify the base type here -//public TypeReference selectedType; \ No newline at end of file diff --git a/Runtime/Core/Attributes/TagSelectorAttribute.cs b/Runtime/Core/Attributes/TagSelectorAttribute.cs index 6cfff5a..d004af9 100644 --- a/Runtime/Core/Attributes/TagSelectorAttribute.cs +++ b/Runtime/Core/Attributes/TagSelectorAttribute.cs @@ -1,45 +1,14 @@ using UnityEngine; -#if UNITY_EDITOR -using UnityEditor; -#endif namespace RealMethod { + /// + /// + /// [TagSelector] + /// + /// public class TagSelectorAttribute : PropertyAttribute { public bool UseDefaultTagFieldDrawer = false; } - - -#if UNITY_EDITOR - - [CustomPropertyDrawer(typeof(TagSelectorAttribute))] - public class TagSelectorPropertyDrawer : PropertyDrawer - { - public override void OnGUI(Rect position, SerializedProperty property, GUIContent label) - { - TagSelectorAttribute tagSelector = (TagSelectorAttribute)attribute; - - if (tagSelector.UseDefaultTagFieldDrawer) - { - EditorGUI.PropertyField(position, property, label); - } - else - { - if (property.propertyType == SerializedPropertyType.String) - { - property.stringValue = EditorGUI.TagField(position, label, property.stringValue); - } - else - { - EditorGUI.PropertyField(position, property, label); - EditorGUI.HelpBox(position, "TagSelector can only be used with strings.", MessageType.Error); - } - } - } - } -#endif -} - -//Use -// [TagSelector] +} \ No newline at end of file diff --git a/Runtime/Core/Attributes/TypeSelectorAttribute.cs b/Runtime/Core/Attributes/TypeSelectorAttribute.cs new file mode 100644 index 0000000..b74d4db --- /dev/null +++ b/Runtime/Core/Attributes/TypeSelectorAttribute.cs @@ -0,0 +1,22 @@ + +using UnityEngine; +#if UNITY_EDITOR +using UnityEditor; +#endif +using System; +using System.Linq; + + + +namespace RealMethod +{ + public class TypeSelectorAttribute : PropertyAttribute + { + public Type BaseType { get; private set; } + + public TypeSelectorAttribute(Type baseType = null) + { + BaseType = baseType ?? typeof(object); + } + } +} \ No newline at end of file diff --git a/Runtime/Core/Attributes/ShowTypeAttribute.cs.meta b/Runtime/Core/Attributes/TypeSelectorAttribute.cs.meta similarity index 100% rename from Runtime/Core/Attributes/ShowTypeAttribute.cs.meta rename to Runtime/Core/Attributes/TypeSelectorAttribute.cs.meta diff --git a/Runtime/Pattern/Managers/UIManager.cs b/Runtime/Pattern/Managers/UIManager.cs index 65b1997..921aa86 100644 --- a/Runtime/Pattern/Managers/UIManager.cs +++ b/Runtime/Pattern/Managers/UIManager.cs @@ -10,11 +10,11 @@ public abstract class UIManager : MonoBehaviour, IGameManager { public enum UIMethod { - [EnumDescription("IMGUI (Legacy - Editor Only)")] + [DescriptionEnum("IMGUI (Legacy - Editor Only)")] IMGUI, - [EnumDescription("uGUI - Canvas-based UI for runtime")] + [DescriptionEnum("uGUI - Canvas-based UI for runtime")] uGUI, - [EnumDescription("UI Toolkit - Modern retained UI system")] + [DescriptionEnum("UI Toolkit - Modern retained UI system")] UI_Toolkit } @@ -24,7 +24,7 @@ public enum UIMethod [SerializeField] private UIMethod method = UIMethod.uGUI; public UIMethod Method => method; - [SerializeField, ShowInInspectorByEnum("method", 2)] + [SerializeField, ConditionalShowByEnum("method", 2)] private PanelSettings UISetting; // Actions public System.Action OnFadeIn; diff --git a/Runtime/ReadySet/Commands/Execut/C_ScneLoader.cs b/Runtime/ReadySet/Commands/Execut/C_ScneLoader.cs index 38d2221..0b364cb 100644 --- a/Runtime/ReadySet/Commands/Execut/C_ScneLoader.cs +++ b/Runtime/ReadySet/Commands/Execut/C_ScneLoader.cs @@ -17,18 +17,18 @@ private enum LoadMethod [Header("Assets")] [SerializeField] private LoadMethod method = LoadMethod.SceneAsset; - [SerializeField, ShowInInspectorByEnum("method", 0)] + [SerializeField, ConditionalShowByEnum("method", 0)] private int sceneIndex; - [SerializeField, ShowInInspectorByEnum("method", 1)] + [SerializeField, ConditionalShowByEnum("method", 1)] private string sceneName; - [SerializeField, ShowInInspectorByEnum("method", 2)] + [SerializeField, ConditionalShowByEnum("method", 2)] private SceneAsset sceneAsset; - [SerializeField, ShowInInspectorByEnum("method", 3)] + [SerializeField, ConditionalShowByEnum("method", 3)] private WorldSceneConfig worldAsset; [Header("Setting")] - [SerializeField, ShowInInspectorByEnum("method", 0, 1)] + [SerializeField, ConditionalShowByEnum("method", 0, 1)] private bool IsAsync = false; - [SerializeField, ShowInInspectorByEnum("method", 0, 1)] + [SerializeField, ConditionalShowByEnum("method", 0, 1)] private LoadSceneMode LoadType = LoadSceneMode.Single; public Action OnAsyncSceneLoaded; diff --git a/Runtime/ReadySet/Managers/SaveManager.cs b/Runtime/ReadySet/Managers/SaveManager.cs index 6e7d3a0..a155fa9 100644 --- a/Runtime/ReadySet/Managers/SaveManager.cs +++ b/Runtime/ReadySet/Managers/SaveManager.cs @@ -24,17 +24,17 @@ public sealed class SaveManager : DataManager [Header("Behavior")] [SerializeField] private SaveMethod Format; public SaveMethod format => Format; - [SerializeField, HideInInspectorByEnum("Format", 0)] + [SerializeField, ConditionalHideByEnum("Format", 0)] private bool CustomPath = false; [SerializeField, ConditionalHide("CustomPath", true, false)] private string FilePath = Environment.GetFolderPath(Environment.SpecialFolder.Desktop); - [SerializeField, ShowInInspectorByEnum("Format", 0, 1)] + [SerializeField, ConditionalShowByEnum("Format", 0, 1)] private bool PublicField = true; - [SerializeField, ShowInInspectorByEnum("Format", 0, 1)] + [SerializeField, ConditionalShowByEnum("Format", 0, 1)] private bool ProtectedField = false; - [SerializeField, ShowInInspectorByEnum("Format", 0, 1)] + [SerializeField, ConditionalShowByEnum("Format", 0, 1)] private bool PrivateField = false; - [SerializeField, ShowInInspectorByEnum("Format", 0, 1)] + [SerializeField, ConditionalShowByEnum("Format", 0, 1)] private bool SerializeField = false; diff --git a/Runtime/Toolkit/PCG/PCG.cs b/Runtime/Toolkit/PCG/PCG.cs index 6b771ac..76e78db 100644 --- a/Runtime/Toolkit/PCG/PCG.cs +++ b/Runtime/Toolkit/PCG/PCG.cs @@ -17,9 +17,9 @@ public abstract class PCG : MonoBehaviour private PCGType Type; [SerializeField] private PCGResourceConfig Resource; - [SerializeField, ShowInInspectorByEnum("Type", 1)] + [SerializeField, ConditionalShowByEnum("Type", 1)] private PCGGenerationAsset Generation; - [SerializeField, ShowInInspectorByEnum("Type", 0)] + [SerializeField, ConditionalShowByEnum("Type", 0)] private PCGCashAsset CashFile; [Header("Load")] [SerializeField] From d74ce01d1c71c41895e6fb181d8ab001788d4ca7 Mon Sep 17 00:00:00 2001 From: Alijimpa Date: Mon, 30 Mar 2026 12:32:31 +0330 Subject: [PATCH 058/204] Refine and Implement Dictionary --- ...rializableDictionary.meta => Drawers.meta} | 2 +- .../MapDrawer.cs} | 517 ++++++++---------- .../MapDrawer.cs.meta} | 0 Editor/Library/Drawers/MapStorageDrawer.cs | 21 + .../Library/Drawers/MapStorageDrawer.cs.meta | 2 + Runtime/Library/Extension/Dictionary.cs | 3 +- Runtime/Library/SharedScripts/Classes/Map.cs | 240 ++++++++ .../Library/SharedScripts/Classes/Map.cs.meta | 2 + .../Classes}/SerializableHashSet.cs | 127 ++--- .../Classes}/SerializableHashSet.cs.meta | 0 Runtime/Library/Vendor.meta | 8 - .../Vendor/SerializableDictionary.meta | 8 - .../SerializableDictionary/Example.meta | 5 - .../SerializableDicitonary Example.unity | 256 --------- .../SerializableDicitonary Example.unity.meta | 4 - .../Example/UserSerializableDictionaries.cs | 26 - .../UserSerializableDictionaries.cs.meta | 12 - .../SerializableDictionary.cs | 259 --------- .../SerializableDictionary.cs.meta | 12 - .../SerializableDictionary.pdf | Bin 118820 -> 0 bytes .../SerializableDictionary.pdf.meta | 8 - .../SerializableDictionaryBase.cs | 17 - .../SerializableDictionaryBase.cs.meta | 2 - Runtime/Pattern/Managers/MixerManager.cs | 2 +- .../ReadySet/Components/UI/UI_GameSetting.cs | 2 +- Runtime/Toolkit/Ability/AbilityController.cs | 2 +- Runtime/Toolkit/RPG/Resource/ResourceData.cs | 2 +- Runtime/Toolkit/RPG/StatSystem/StatProfile.cs | 2 +- 28 files changed, 565 insertions(+), 976 deletions(-) rename Editor/Library/{Vendor/SerializableDictionary.meta => Drawers.meta} (77%) rename Editor/Library/{Vendor/SerializableDictionary/SerializableDictionaryPropertyDrawer.cs => Drawers/MapDrawer.cs} (96%) rename Editor/Library/{Vendor/SerializableDictionary/SerializableDictionaryPropertyDrawer.cs.meta => Drawers/MapDrawer.cs.meta} (100%) create mode 100644 Editor/Library/Drawers/MapStorageDrawer.cs create mode 100644 Editor/Library/Drawers/MapStorageDrawer.cs.meta create mode 100644 Runtime/Library/SharedScripts/Classes/Map.cs create mode 100644 Runtime/Library/SharedScripts/Classes/Map.cs.meta rename Runtime/Library/{Vendor/SerializableDictionary => SharedScripts/Classes}/SerializableHashSet.cs (96%) rename Runtime/Library/{Vendor/SerializableDictionary => SharedScripts/Classes}/SerializableHashSet.cs.meta (100%) delete mode 100644 Runtime/Library/Vendor.meta delete mode 100644 Runtime/Library/Vendor/SerializableDictionary.meta delete mode 100644 Runtime/Library/Vendor/SerializableDictionary/Example.meta delete mode 100644 Runtime/Library/Vendor/SerializableDictionary/Example/SerializableDicitonary Example.unity delete mode 100644 Runtime/Library/Vendor/SerializableDictionary/Example/SerializableDicitonary Example.unity.meta delete mode 100644 Runtime/Library/Vendor/SerializableDictionary/Example/UserSerializableDictionaries.cs delete mode 100644 Runtime/Library/Vendor/SerializableDictionary/Example/UserSerializableDictionaries.cs.meta delete mode 100644 Runtime/Library/Vendor/SerializableDictionary/SerializableDictionary.cs delete mode 100644 Runtime/Library/Vendor/SerializableDictionary/SerializableDictionary.cs.meta delete mode 100644 Runtime/Library/Vendor/SerializableDictionary/SerializableDictionary.pdf delete mode 100644 Runtime/Library/Vendor/SerializableDictionary/SerializableDictionary.pdf.meta delete mode 100644 Runtime/Library/Vendor/SerializableDictionary/SerializableDictionaryBase.cs delete mode 100644 Runtime/Library/Vendor/SerializableDictionary/SerializableDictionaryBase.cs.meta diff --git a/Editor/Library/Vendor/SerializableDictionary.meta b/Editor/Library/Drawers.meta similarity index 77% rename from Editor/Library/Vendor/SerializableDictionary.meta rename to Editor/Library/Drawers.meta index 52041f2..bfda2d7 100644 --- a/Editor/Library/Vendor/SerializableDictionary.meta +++ b/Editor/Library/Drawers.meta @@ -1,5 +1,5 @@ fileFormatVersion: 2 -guid: 8c73a086c2d5b9142b2f8d4d8befecfe +guid: 09f6f3abd6dcd6748b7743fe122234a1 folderAsset: yes DefaultImporter: externalObjects: {} diff --git a/Editor/Library/Vendor/SerializableDictionary/SerializableDictionaryPropertyDrawer.cs b/Editor/Library/Drawers/MapDrawer.cs similarity index 96% rename from Editor/Library/Vendor/SerializableDictionary/SerializableDictionaryPropertyDrawer.cs rename to Editor/Library/Drawers/MapDrawer.cs index 8e97de0..4266dfd 100644 --- a/Editor/Library/Vendor/SerializableDictionary/SerializableDictionaryPropertyDrawer.cs +++ b/Editor/Library/Drawers/MapDrawer.cs @@ -7,24 +7,12 @@ namespace RealMethod.Editor { - [CustomPropertyDrawer(typeof(SerializableDictionaryBase), true)] + [CustomPropertyDrawer(typeof(MapCore), true)] #if NET_4_6 || NET_STANDARD_2_0 [CustomPropertyDrawer(typeof(SerializableHashSetBase), true)] #endif - public class SerializableDictionaryPropertyDrawer : PropertyDrawer + public class MapDrawer : PropertyDrawer { - const string KeysFieldName = "m_keys"; - const string ValuesFieldName = "m_values"; - protected const float IndentWidth = 15f; - - static GUIContent s_iconPlus = IconContent("Toolbar Plus", "Add entry"); - static GUIContent s_iconMinus = IconContent("Toolbar Minus", "Remove entry"); - static GUIContent s_warningIconConflict = IconContent("console.warnicon.sml", "Conflicting key, this entry will be lost"); - static GUIContent s_warningIconOther = IconContent("console.infoicon.sml", "Conflicting key"); - static GUIContent s_warningIconNull = IconContent("console.warnicon.sml", "Null key, this entry will be lost"); - static GUIStyle s_buttonStyle = GUIStyle.none; - static GUIContent s_tempContent = new GUIContent(); - class ConflictState { @@ -36,7 +24,6 @@ class ConflictState public bool conflictValuePropertyExpanded = false; public float conflictLineHeight = 0f; } - struct PropertyIdentity { public PropertyIdentity(SerializedProperty property) @@ -48,9 +35,19 @@ public PropertyIdentity(SerializedProperty property) public UnityEngine.Object instance; public string propertyPath; } + struct EnumerationEntry + { + public SerializedProperty keyProperty; + public SerializedProperty valueProperty; + public int index; - static Dictionary s_conflictStateDict = new Dictionary(); - + public EnumerationEntry(SerializedProperty keyProperty, SerializedProperty valueProperty, int index) + { + this.keyProperty = keyProperty; + this.valueProperty = valueProperty; + this.index = index; + } + } enum Action { None, @@ -58,166 +55,52 @@ enum Action Remove } - public override void OnGUI(Rect position, SerializedProperty property, GUIContent label) - { - label = EditorGUI.BeginProperty(position, label, property); - - Action buttonAction = Action.None; - int buttonActionIndex = 0; - - var keyArrayProperty = property.FindPropertyRelative(KeysFieldName); - var valueArrayProperty = property.FindPropertyRelative(ValuesFieldName); - - ConflictState conflictState = GetConflictState(property); - - if (conflictState.conflictIndex != -1) - { - keyArrayProperty.InsertArrayElementAtIndex(conflictState.conflictIndex); - var keyProperty = keyArrayProperty.GetArrayElementAtIndex(conflictState.conflictIndex); - SetPropertyValue(keyProperty, conflictState.conflictKey); - keyProperty.isExpanded = conflictState.conflictKeyPropertyExpanded; - - if (valueArrayProperty != null) - { - valueArrayProperty.InsertArrayElementAtIndex(conflictState.conflictIndex); - var valueProperty = valueArrayProperty.GetArrayElementAtIndex(conflictState.conflictIndex); - SetPropertyValue(valueProperty, conflictState.conflictValue); - valueProperty.isExpanded = conflictState.conflictValuePropertyExpanded; - } - } - - var buttonWidth = s_buttonStyle.CalcSize(s_iconPlus).x; - - var labelPosition = position; - labelPosition.height = EditorGUIUtility.singleLineHeight; - if (property.isExpanded) - labelPosition.xMax -= s_buttonStyle.CalcSize(s_iconPlus).x; - - EditorGUI.PropertyField(labelPosition, property, label, false); - // property.isExpanded = EditorGUI.Foldout(labelPosition, property.isExpanded, label); - if (property.isExpanded) - { - var buttonPosition = position; - buttonPosition.xMin = buttonPosition.xMax - buttonWidth; - buttonPosition.height = EditorGUIUtility.singleLineHeight; - EditorGUI.BeginDisabledGroup(conflictState.conflictIndex != -1); - if (GUI.Button(buttonPosition, s_iconPlus, s_buttonStyle)) - { - buttonAction = Action.Add; - buttonActionIndex = keyArrayProperty.arraySize; - } - EditorGUI.EndDisabledGroup(); - - EditorGUI.indentLevel++; - var linePosition = position; - linePosition.y += EditorGUIUtility.singleLineHeight; - linePosition.xMax -= buttonWidth; - - foreach (var entry in EnumerateEntries(keyArrayProperty, valueArrayProperty)) - { - var keyProperty = entry.keyProperty; - var valueProperty = entry.valueProperty; - int i = entry.index; - - float lineHeight = DrawKeyValueLine(keyProperty, valueProperty, linePosition, i); - - buttonPosition = linePosition; - buttonPosition.x = linePosition.xMax; - buttonPosition.height = EditorGUIUtility.singleLineHeight; - if (GUI.Button(buttonPosition, s_iconMinus, s_buttonStyle)) - { - buttonAction = Action.Remove; - buttonActionIndex = i; - } - - if (i == conflictState.conflictIndex && conflictState.conflictOtherIndex == -1) - { - var iconPosition = linePosition; - iconPosition.size = s_buttonStyle.CalcSize(s_warningIconNull); - GUI.Label(iconPosition, s_warningIconNull); - } - else if (i == conflictState.conflictIndex) - { - var iconPosition = linePosition; - iconPosition.size = s_buttonStyle.CalcSize(s_warningIconConflict); - GUI.Label(iconPosition, s_warningIconConflict); - } - else if (i == conflictState.conflictOtherIndex) - { - var iconPosition = linePosition; - iconPosition.size = s_buttonStyle.CalcSize(s_warningIconOther); - GUI.Label(iconPosition, s_warningIconOther); - } - - - linePosition.y += lineHeight; - } + const string KeysFieldName = "m_keys"; + const string ValuesFieldName = "m_values"; + protected const float IndentWidth = 15f; - EditorGUI.indentLevel--; - } - if (buttonAction == Action.Add) - { - keyArrayProperty.InsertArrayElementAtIndex(buttonActionIndex); - if (valueArrayProperty != null) - valueArrayProperty.InsertArrayElementAtIndex(buttonActionIndex); - } - else if (buttonAction == Action.Remove) - { - DeleteArrayElementAtIndex(keyArrayProperty, buttonActionIndex); - if (valueArrayProperty != null) - DeleteArrayElementAtIndex(valueArrayProperty, buttonActionIndex); - } + static MapDrawer() + { + Dictionary serializedPropertyValueAccessorsNameDict = new Dictionary() { + { SerializedPropertyType.Integer, "intValue" }, + { SerializedPropertyType.Boolean, "boolValue" }, + { SerializedPropertyType.Float, "floatValue" }, + { SerializedPropertyType.String, "stringValue" }, + { SerializedPropertyType.Color, "colorValue" }, + { SerializedPropertyType.ObjectReference, "objectReferenceValue" }, + { SerializedPropertyType.LayerMask, "intValue" }, + { SerializedPropertyType.Enum, "intValue" }, + { SerializedPropertyType.Vector2, "vector2Value" }, + { SerializedPropertyType.Vector3, "vector3Value" }, + { SerializedPropertyType.Vector4, "vector4Value" }, + { SerializedPropertyType.Rect, "rectValue" }, + { SerializedPropertyType.ArraySize, "intValue" }, + { SerializedPropertyType.Character, "intValue" }, + { SerializedPropertyType.AnimationCurve, "animationCurveValue" }, + { SerializedPropertyType.Bounds, "boundsValue" }, + { SerializedPropertyType.Quaternion, "quaternionValue" }, + }; + Type serializedPropertyType = typeof(SerializedProperty); - conflictState.conflictKey = null; - conflictState.conflictValue = null; - conflictState.conflictIndex = -1; - conflictState.conflictOtherIndex = -1; - conflictState.conflictLineHeight = 0f; - conflictState.conflictKeyPropertyExpanded = false; - conflictState.conflictValuePropertyExpanded = false; + s_serializedPropertyValueAccessorsDict = new Dictionary(); + BindingFlags flags = BindingFlags.Instance | BindingFlags.Public; - foreach (var entry1 in EnumerateEntries(keyArrayProperty, valueArrayProperty)) + foreach (var kvp in serializedPropertyValueAccessorsNameDict) { - var keyProperty1 = entry1.keyProperty; - int i = entry1.index; - object keyProperty1Value = GetPropertyValue(keyProperty1); - - if (keyProperty1Value == null) - { - var valueProperty1 = entry1.valueProperty; - SaveProperty(keyProperty1, valueProperty1, i, -1, conflictState); - DeleteArrayElementAtIndex(keyArrayProperty, i); - if (valueArrayProperty != null) - DeleteArrayElementAtIndex(valueArrayProperty, i); - - break; - } - - - foreach (var entry2 in EnumerateEntries(keyArrayProperty, valueArrayProperty, i + 1)) - { - var keyProperty2 = entry2.keyProperty; - int j = entry2.index; - object keyProperty2Value = GetPropertyValue(keyProperty2); - - if (ComparePropertyValues(keyProperty1Value, keyProperty2Value)) - { - var valueProperty2 = entry2.valueProperty; - SaveProperty(keyProperty2, valueProperty2, j, i, conflictState); - DeleteArrayElementAtIndex(keyArrayProperty, j); - if (valueArrayProperty != null) - DeleteArrayElementAtIndex(valueArrayProperty, j); - - goto breakLoops; - } - } + PropertyInfo propertyInfo = serializedPropertyType.GetProperty(kvp.Value, flags); + s_serializedPropertyValueAccessorsDict.Add(kvp.Key, propertyInfo); } - breakLoops: - - EditorGUI.EndProperty(); } - + static GUIContent s_iconPlus = IconContent("Toolbar Plus", "Add entry"); + static GUIContent s_iconMinus = IconContent("Toolbar Minus", "Remove entry"); + static GUIContent s_warningIconConflict = IconContent("console.warnicon.sml", "Conflicting key, this entry will be lost"); + static GUIContent s_warningIconOther = IconContent("console.infoicon.sml", "Conflicting key"); + static GUIContent s_warningIconNull = IconContent("console.warnicon.sml", "Null key, this entry will be lost"); + static GUIStyle s_buttonStyle = GUIStyle.none; + static GUIContent s_tempContent = new GUIContent(); + static Dictionary s_conflictStateDict = new Dictionary(); + static Dictionary s_serializedPropertyValueAccessorsDict; static float DrawKeyValueLine(SerializedProperty keyProperty, SerializedProperty valueProperty, Rect linePosition, int index) { bool keyCanBeExpanded = CanPropertyBeExpanded(keyProperty); @@ -250,7 +133,6 @@ static float DrawKeyValueLine(SerializedProperty keyProperty, SerializedProperty } } } - static float DrawKeyValueLineSimple(SerializedProperty keyProperty, SerializedProperty valueProperty, string keyLabel, string valueLabel, Rect linePosition) { float labelWidth = EditorGUIUtility.labelWidth; @@ -276,7 +158,6 @@ static float DrawKeyValueLineSimple(SerializedProperty keyProperty, SerializedPr return Mathf.Max(keyPropertyHeight, valuePropertyHeight); } - static float DrawKeyValueLineExpand(SerializedProperty keyProperty, SerializedProperty valueProperty, Rect linePosition) { float labelWidth = EditorGUIUtility.labelWidth; @@ -296,7 +177,6 @@ static float DrawKeyValueLineExpand(SerializedProperty keyProperty, SerializedPr return Mathf.Max(keyPropertyHeight, valuePropertyHeight); } - static float DrawKeyLine(SerializedProperty keyProperty, Rect linePosition, string keyLabel) { float keyPropertyHeight = EditorGUI.GetPropertyHeight(keyProperty); @@ -309,7 +189,6 @@ static float DrawKeyLine(SerializedProperty keyProperty, Rect linePosition, stri return keyPropertyHeight; } - static bool CanPropertyBeExpanded(SerializedProperty property) { switch (property.propertyType) @@ -322,7 +201,6 @@ static bool CanPropertyBeExpanded(SerializedProperty property) return false; } } - static void SaveProperty(SerializedProperty keyProperty, SerializedProperty valueProperty, int index, int otherIndex, ConflictState conflictState) { conflictState.conflictKey = GetPropertyValue(keyProperty); @@ -336,37 +214,6 @@ static void SaveProperty(SerializedProperty keyProperty, SerializedProperty valu conflictState.conflictKeyPropertyExpanded = keyProperty.isExpanded; conflictState.conflictValuePropertyExpanded = valueProperty != null ? valueProperty.isExpanded : false; } - - public override float GetPropertyHeight(SerializedProperty property, GUIContent label) - { - float propertyHeight = EditorGUIUtility.singleLineHeight; - - if (property.isExpanded) - { - var keysProperty = property.FindPropertyRelative(KeysFieldName); - var valuesProperty = property.FindPropertyRelative(ValuesFieldName); - - foreach (var entry in EnumerateEntries(keysProperty, valuesProperty)) - { - var keyProperty = entry.keyProperty; - var valueProperty = entry.valueProperty; - float keyPropertyHeight = EditorGUI.GetPropertyHeight(keyProperty); - float valuePropertyHeight = valueProperty != null ? EditorGUI.GetPropertyHeight(valueProperty) : 0f; - float lineHeight = Mathf.Max(keyPropertyHeight, valuePropertyHeight); - propertyHeight += lineHeight; - } - - ConflictState conflictState = GetConflictState(property); - - if (conflictState.conflictIndex != -1) - { - propertyHeight += conflictState.conflictLineHeight; - } - } - - return propertyHeight; - } - static ConflictState GetConflictState(SerializedProperty property) { ConflictState conflictState; @@ -378,54 +225,16 @@ static ConflictState GetConflictState(SerializedProperty property) } return conflictState; } - - static Dictionary s_serializedPropertyValueAccessorsDict; - - static SerializableDictionaryPropertyDrawer() - { - Dictionary serializedPropertyValueAccessorsNameDict = new Dictionary() { - { SerializedPropertyType.Integer, "intValue" }, - { SerializedPropertyType.Boolean, "boolValue" }, - { SerializedPropertyType.Float, "floatValue" }, - { SerializedPropertyType.String, "stringValue" }, - { SerializedPropertyType.Color, "colorValue" }, - { SerializedPropertyType.ObjectReference, "objectReferenceValue" }, - { SerializedPropertyType.LayerMask, "intValue" }, - { SerializedPropertyType.Enum, "intValue" }, - { SerializedPropertyType.Vector2, "vector2Value" }, - { SerializedPropertyType.Vector3, "vector3Value" }, - { SerializedPropertyType.Vector4, "vector4Value" }, - { SerializedPropertyType.Rect, "rectValue" }, - { SerializedPropertyType.ArraySize, "intValue" }, - { SerializedPropertyType.Character, "intValue" }, - { SerializedPropertyType.AnimationCurve, "animationCurveValue" }, - { SerializedPropertyType.Bounds, "boundsValue" }, - { SerializedPropertyType.Quaternion, "quaternionValue" }, - }; - Type serializedPropertyType = typeof(SerializedProperty); - - s_serializedPropertyValueAccessorsDict = new Dictionary(); - BindingFlags flags = BindingFlags.Instance | BindingFlags.Public; - - foreach (var kvp in serializedPropertyValueAccessorsNameDict) - { - PropertyInfo propertyInfo = serializedPropertyType.GetProperty(kvp.Value, flags); - s_serializedPropertyValueAccessorsDict.Add(kvp.Key, propertyInfo); - } - } - static GUIContent IconContent(string name, string tooltip) { var builtinIcon = EditorGUIUtility.IconContent(name); return new GUIContent(builtinIcon.image, tooltip); } - static GUIContent TempContent(string text) { s_tempContent.text = text; return s_tempContent; } - static void DeleteArrayElementAtIndex(SerializedProperty arrayProperty, int index) { var property = arrayProperty.GetArrayElementAtIndex(index); @@ -437,7 +246,6 @@ static void DeleteArrayElementAtIndex(SerializedProperty arrayProperty, int inde arrayProperty.DeleteArrayElementAtIndex(index); } - public static object GetPropertyValue(SerializedProperty p) { PropertyInfo propertyInfo; @@ -453,7 +261,6 @@ public static object GetPropertyValue(SerializedProperty p) return GetPropertyValueGeneric(p); } } - static void SetPropertyValue(SerializedProperty p, object v) { PropertyInfo propertyInfo; @@ -469,7 +276,6 @@ static void SetPropertyValue(SerializedProperty p, object v) SetPropertyValueGeneric(p, v); } } - static object GetPropertyValueArray(SerializedProperty property) { object[] array = new object[property.arraySize]; @@ -480,7 +286,6 @@ static object GetPropertyValueArray(SerializedProperty property) } return array; } - static object GetPropertyValueGeneric(SerializedProperty property) { Dictionary dict = new Dictionary(); @@ -497,7 +302,6 @@ static object GetPropertyValueGeneric(SerializedProperty property) } return dict; } - static void SetPropertyValueArray(SerializedProperty property, object v) { object[] array = (object[])v; @@ -508,7 +312,6 @@ static void SetPropertyValueArray(SerializedProperty property, object v) SetPropertyValue(item, array[i]); } } - static void SetPropertyValueGeneric(SerializedProperty property, object v) { Dictionary dict = (Dictionary)v; @@ -523,7 +326,6 @@ static void SetPropertyValueGeneric(SerializedProperty property, object v) } while (iterator.Next(false) && iterator.propertyPath != end.propertyPath); } } - static bool ComparePropertyValues(object value1, object value2) { if (value1 is Dictionary && value2 is Dictionary) @@ -537,7 +339,6 @@ static bool ComparePropertyValues(object value1, object value2) return object.Equals(value1, value2); } } - static bool CompareDictionaries(Dictionary dict1, Dictionary dict2) { if (dict1.Count != dict2.Count) @@ -558,21 +359,6 @@ static bool CompareDictionaries(Dictionary dict1, Dictionary EnumerateEntries(SerializedProperty keyArrayProperty, SerializedProperty valueArrayProperty, int startIndex = 0) { if (keyArrayProperty.arraySize > startIndex) @@ -591,21 +377,200 @@ static IEnumerable EnumerateEntries(SerializedProperty keyArra && !SerializedProperty.EqualContents(keyProperty, endProperty)); } } - } - [CustomPropertyDrawer(typeof(SerializableDictionaryBase.Storage), true)] - public class SerializableDictionaryStoragePropertyDrawer : PropertyDrawer - { + public override void OnGUI(Rect position, SerializedProperty property, GUIContent label) { - property.Next(true); - EditorGUI.PropertyField(position, property, label, true); - } + label = EditorGUI.BeginProperty(position, label, property); + + Action buttonAction = Action.None; + int buttonActionIndex = 0; + + var keyArrayProperty = property.FindPropertyRelative(KeysFieldName); + var valueArrayProperty = property.FindPropertyRelative(ValuesFieldName); + + ConflictState conflictState = GetConflictState(property); + + if (conflictState.conflictIndex != -1) + { + keyArrayProperty.InsertArrayElementAtIndex(conflictState.conflictIndex); + var keyProperty = keyArrayProperty.GetArrayElementAtIndex(conflictState.conflictIndex); + SetPropertyValue(keyProperty, conflictState.conflictKey); + keyProperty.isExpanded = conflictState.conflictKeyPropertyExpanded; + + if (valueArrayProperty != null) + { + valueArrayProperty.InsertArrayElementAtIndex(conflictState.conflictIndex); + var valueProperty = valueArrayProperty.GetArrayElementAtIndex(conflictState.conflictIndex); + SetPropertyValue(valueProperty, conflictState.conflictValue); + valueProperty.isExpanded = conflictState.conflictValuePropertyExpanded; + } + } + + var buttonWidth = s_buttonStyle.CalcSize(s_iconPlus).x; + + var labelPosition = position; + labelPosition.height = EditorGUIUtility.singleLineHeight; + if (property.isExpanded) + labelPosition.xMax -= s_buttonStyle.CalcSize(s_iconPlus).x; + + // Modify label to include count + var newLabel = new GUIContent($"{label.text} ({keyArrayProperty.arraySize})"); + + EditorGUI.PropertyField(labelPosition, property, newLabel, false); + // property.isExpanded = EditorGUI.Foldout(labelPosition, property.isExpanded, label); + if (property.isExpanded) + { + var buttonPosition = position; + buttonPosition.xMin = buttonPosition.xMax - buttonWidth; + buttonPosition.height = EditorGUIUtility.singleLineHeight; + EditorGUI.BeginDisabledGroup(conflictState.conflictIndex != -1); + if (GUI.Button(buttonPosition, s_iconPlus, s_buttonStyle)) + { + buttonAction = Action.Add; + buttonActionIndex = keyArrayProperty.arraySize; + } + EditorGUI.EndDisabledGroup(); + + EditorGUI.indentLevel++; + var linePosition = position; + linePosition.y += EditorGUIUtility.singleLineHeight; + linePosition.xMax -= buttonWidth; + + foreach (var entry in EnumerateEntries(keyArrayProperty, valueArrayProperty)) + { + var keyProperty = entry.keyProperty; + var valueProperty = entry.valueProperty; + int i = entry.index; + + float lineHeight = DrawKeyValueLine(keyProperty, valueProperty, linePosition, i); + + buttonPosition = linePosition; + buttonPosition.x = linePosition.xMax; + buttonPosition.height = EditorGUIUtility.singleLineHeight; + if (GUI.Button(buttonPosition, s_iconMinus, s_buttonStyle)) + { + buttonAction = Action.Remove; + buttonActionIndex = i; + } + + if (i == conflictState.conflictIndex && conflictState.conflictOtherIndex == -1) + { + var iconPosition = linePosition; + iconPosition.size = s_buttonStyle.CalcSize(s_warningIconNull); + GUI.Label(iconPosition, s_warningIconNull); + } + else if (i == conflictState.conflictIndex) + { + var iconPosition = linePosition; + iconPosition.size = s_buttonStyle.CalcSize(s_warningIconConflict); + GUI.Label(iconPosition, s_warningIconConflict); + } + else if (i == conflictState.conflictOtherIndex) + { + var iconPosition = linePosition; + iconPosition.size = s_buttonStyle.CalcSize(s_warningIconOther); + GUI.Label(iconPosition, s_warningIconOther); + } + + + linePosition.y += lineHeight; + } + + EditorGUI.indentLevel--; + } + + if (buttonAction == Action.Add) + { + keyArrayProperty.InsertArrayElementAtIndex(buttonActionIndex); + if (valueArrayProperty != null) + valueArrayProperty.InsertArrayElementAtIndex(buttonActionIndex); + } + else if (buttonAction == Action.Remove) + { + DeleteArrayElementAtIndex(keyArrayProperty, buttonActionIndex); + if (valueArrayProperty != null) + DeleteArrayElementAtIndex(valueArrayProperty, buttonActionIndex); + } + + conflictState.conflictKey = null; + conflictState.conflictValue = null; + conflictState.conflictIndex = -1; + conflictState.conflictOtherIndex = -1; + conflictState.conflictLineHeight = 0f; + conflictState.conflictKeyPropertyExpanded = false; + conflictState.conflictValuePropertyExpanded = false; + + foreach (var entry1 in EnumerateEntries(keyArrayProperty, valueArrayProperty)) + { + var keyProperty1 = entry1.keyProperty; + int i = entry1.index; + object keyProperty1Value = GetPropertyValue(keyProperty1); + if (keyProperty1Value == null) + { + var valueProperty1 = entry1.valueProperty; + SaveProperty(keyProperty1, valueProperty1, i, -1, conflictState); + DeleteArrayElementAtIndex(keyArrayProperty, i); + if (valueArrayProperty != null) + DeleteArrayElementAtIndex(valueArrayProperty, i); + + break; + } + + + foreach (var entry2 in EnumerateEntries(keyArrayProperty, valueArrayProperty, i + 1)) + { + var keyProperty2 = entry2.keyProperty; + int j = entry2.index; + object keyProperty2Value = GetPropertyValue(keyProperty2); + + if (ComparePropertyValues(keyProperty1Value, keyProperty2Value)) + { + var valueProperty2 = entry2.valueProperty; + SaveProperty(keyProperty2, valueProperty2, j, i, conflictState); + DeleteArrayElementAtIndex(keyArrayProperty, j); + if (valueArrayProperty != null) + DeleteArrayElementAtIndex(valueArrayProperty, j); + + goto breakLoops; + } + } + } + breakLoops: + + EditorGUI.EndProperty(); + } public override float GetPropertyHeight(SerializedProperty property, GUIContent label) { - property.Next(true); - return EditorGUI.GetPropertyHeight(property); + float propertyHeight = EditorGUIUtility.singleLineHeight; + + if (property.isExpanded) + { + var keysProperty = property.FindPropertyRelative(KeysFieldName); + var valuesProperty = property.FindPropertyRelative(ValuesFieldName); + + foreach (var entry in EnumerateEntries(keysProperty, valuesProperty)) + { + var keyProperty = entry.keyProperty; + var valueProperty = entry.valueProperty; + float keyPropertyHeight = EditorGUI.GetPropertyHeight(keyProperty); + float valuePropertyHeight = valueProperty != null ? EditorGUI.GetPropertyHeight(valueProperty) : 0f; + float lineHeight = Mathf.Max(keyPropertyHeight, valuePropertyHeight); + propertyHeight += lineHeight; + } + + ConflictState conflictState = GetConflictState(property); + + if (conflictState.conflictIndex != -1) + { + propertyHeight += conflictState.conflictLineHeight; + } + } + + return propertyHeight; } } + + } \ No newline at end of file diff --git a/Editor/Library/Vendor/SerializableDictionary/SerializableDictionaryPropertyDrawer.cs.meta b/Editor/Library/Drawers/MapDrawer.cs.meta similarity index 100% rename from Editor/Library/Vendor/SerializableDictionary/SerializableDictionaryPropertyDrawer.cs.meta rename to Editor/Library/Drawers/MapDrawer.cs.meta diff --git a/Editor/Library/Drawers/MapStorageDrawer.cs b/Editor/Library/Drawers/MapStorageDrawer.cs new file mode 100644 index 0000000..e40d60e --- /dev/null +++ b/Editor/Library/Drawers/MapStorageDrawer.cs @@ -0,0 +1,21 @@ +using UnityEditor; +using UnityEngine; + +namespace RealMethod.Editor +{ + [CustomPropertyDrawer(typeof(MapCore.Storage), true)] + public class MapStorageDrawer : PropertyDrawer + { + public override void OnGUI(Rect position, SerializedProperty property, GUIContent label) + { + property.Next(true); + EditorGUI.PropertyField(position, property, label, true); + } + + public override float GetPropertyHeight(SerializedProperty property, GUIContent label) + { + property.Next(true); + return EditorGUI.GetPropertyHeight(property); + } + } +} \ No newline at end of file diff --git a/Editor/Library/Drawers/MapStorageDrawer.cs.meta b/Editor/Library/Drawers/MapStorageDrawer.cs.meta new file mode 100644 index 0000000..95b23ff --- /dev/null +++ b/Editor/Library/Drawers/MapStorageDrawer.cs.meta @@ -0,0 +1,2 @@ +fileFormatVersion: 2 +guid: 22efdf0df2df5bf44a89841c2078e044 \ No newline at end of file diff --git a/Runtime/Library/Extension/Dictionary.cs b/Runtime/Library/Extension/Dictionary.cs index 5114110..73e632b 100644 --- a/Runtime/Library/Extension/Dictionary.cs +++ b/Runtime/Library/Extension/Dictionary.cs @@ -4,6 +4,7 @@ namespace RealMethod { + public static class Dictionary_Extension { public static Tk GetKey(this Dictionary DataBase, int index) @@ -42,7 +43,7 @@ public static T Wheel(this Dictionary DataBase) // Fallback (should rarely happen due to floating point errors) return DataBase.Keys.Last(); } - public static T Wheel(this SerializableDictionary DataBase) + public static T Wheel(this Map DataBase) { if (DataBase == null || DataBase.Count == 0) throw new System.ArgumentException("Database is null or empty"); diff --git a/Runtime/Library/SharedScripts/Classes/Map.cs b/Runtime/Library/SharedScripts/Classes/Map.cs new file mode 100644 index 0000000..de230b3 --- /dev/null +++ b/Runtime/Library/SharedScripts/Classes/Map.cs @@ -0,0 +1,240 @@ +using System; +using System.Collections; +using System.Collections.Generic; +using System.Linq; +using System.Runtime.Serialization; +using UnityEngine; + +namespace RealMethod +{ + public abstract class MapCore + { + public abstract class Storage { } + + protected class Dictionary : System.Collections.Generic.Dictionary + { + public Dictionary() { } + public Dictionary(IDictionary dict) : base(dict) { } + public Dictionary(SerializationInfo info, StreamingContext context) : base(info, context) { } + } + } + [Serializable] + public abstract class MapCore : MapCore, IDictionary, IDictionary, ISerializationCallbackReceiver, IDeserializationCallback, ISerializable + { + Dictionary m_dict; + [SerializeField] + TKey[] m_keys; + [SerializeField] + TValueStorage[] m_values; + + + // Implement IDictionary Interface + public ICollection Keys { get { return ((IDictionary)m_dict).Keys; } } + public ICollection Values { get { return ((IDictionary)m_dict).Values; } } + public int Count { get { return ((IDictionary)m_dict).Count; } } + public bool IsReadOnly { get { return ((IDictionary)m_dict).IsReadOnly; } } + public TValue this[TKey key] + { + get { return ((IDictionary)m_dict)[key]; } + set { ((IDictionary)m_dict)[key] = value; } + } + public TKey GetKey(int index) + { + return m_dict.Keys.ElementAt(index); + } + public TValue GetValue(int index) + { + return m_dict.Values.ElementAt(index); + } + public void Add(TKey key, TValue value) + { + ((IDictionary)m_dict).Add(key, value); + } + public bool ContainsKey(TKey key) + { + return ((IDictionary)m_dict).ContainsKey(key); + } + public bool Remove(TKey key) + { + return ((IDictionary)m_dict).Remove(key); + } + public bool TryGetValue(TKey key, out TValue value) + { + return ((IDictionary)m_dict).TryGetValue(key, out value); + } + public void Add(KeyValuePair item) + { + ((IDictionary)m_dict).Add(item); + } + public void Clear() + { + ((IDictionary)m_dict).Clear(); + } + public bool Contains(KeyValuePair item) + { + return ((IDictionary)m_dict).Contains(item); + } + public void CopyTo(KeyValuePair[] array, int arrayIndex) + { + ((IDictionary)m_dict).CopyTo(array, arrayIndex); + } + public bool Remove(KeyValuePair item) + { + return ((IDictionary)m_dict).Remove(item); + } + public IEnumerator> GetEnumerator() + { + return ((IDictionary)m_dict).GetEnumerator(); + } + IEnumerator IEnumerable.GetEnumerator() + { + return ((IDictionary)m_dict).GetEnumerator(); + } + + // Implement IDictionary Interface + public bool IsFixedSize { get { return ((IDictionary)m_dict).IsFixedSize; } } + ICollection IDictionary.Keys { get { return ((IDictionary)m_dict).Keys; } } + ICollection IDictionary.Values { get { return ((IDictionary)m_dict).Values; } } + public bool IsSynchronized { get { return ((IDictionary)m_dict).IsSynchronized; } } + public object SyncRoot { get { return ((IDictionary)m_dict).SyncRoot; } } + public object this[object key] + { + get { return ((IDictionary)m_dict)[key]; } + set { ((IDictionary)m_dict)[key] = value; } + } + public void Add(object key, object value) + { + ((IDictionary)m_dict).Add(key, value); + } + public bool Contains(object key) + { + return ((IDictionary)m_dict).Contains(key); + } + IDictionaryEnumerator IDictionary.GetEnumerator() + { + return ((IDictionary)m_dict).GetEnumerator(); + } + public void Remove(object key) + { + ((IDictionary)m_dict).Remove(key); + } + public void CopyTo(System.Array array, int index) + { + ((IDictionary)m_dict).CopyTo(array, index); + } + + // Implement IDeserializationCallback Interface + public void OnDeserialization(object sender) + { + ((IDeserializationCallback)m_dict).OnDeserialization(sender); + } + + // Implement ISerializable Interface + protected MapCore(SerializationInfo info, StreamingContext context) + { + m_dict = new Dictionary(info, context); + } + public void GetObjectData(SerializationInfo info, StreamingContext context) + { + ((ISerializable)m_dict).GetObjectData(info, context); + } + + + + // Constructor + public MapCore() + { + m_dict = new Dictionary(); + } + public MapCore(IDictionary dict) + { + m_dict = new Dictionary(dict); + } + + // Functions + public void CopyFrom(IDictionary dict) + { + m_dict.Clear(); + foreach (var kvp in dict) + { + m_dict[kvp.Key] = kvp.Value; + } + } + public void OnAfterDeserialize() + { + if (m_keys != null && m_values != null && m_keys.Length == m_values.Length) + { + m_dict.Clear(); + int n = m_keys.Length; + for (int i = 0; i < n; ++i) + { + m_dict[m_keys[i]] = GetValue(m_values, i); + } + + m_keys = null; + m_values = null; + } + } + public void OnBeforeSerialize() + { + int n = m_dict.Count; + m_keys = new TKey[n]; + m_values = new TValueStorage[n]; + + int i = 0; + foreach (var kvp in m_dict) + { + m_keys[i] = kvp.Key; + SetValue(m_values, i, kvp.Value); + ++i; + } + } + + // Abstractions + protected abstract void SetValue(TValueStorage[] storage, int i, TValue value); + protected abstract TValue GetValue(TValueStorage[] storage, int i); + } + + + public static class SerializableDictionary + { + public class Storage : MapCore.Storage + { + public T data; + } + } + + [Serializable] + public class Map : MapCore + { + public Map() { } + public Map(IDictionary dict) : base(dict) { } + protected Map(SerializationInfo info, StreamingContext context) : base(info, context) { } + + protected override TValue GetValue(TValue[] storage, int i) + { + return storage[i]; + } + protected override void SetValue(TValue[] storage, int i, TValue value) + { + storage[i] = value; + } + } + [Serializable] + public class Map : MapCore where TValueStorage : SerializableDictionary.Storage, new() + { + public Map() { } + public Map(IDictionary dict) : base(dict) { } + protected Map(SerializationInfo info, StreamingContext context) : base(info, context) { } + + protected override TValue GetValue(TValueStorage[] storage, int i) + { + return storage[i].data; + } + protected override void SetValue(TValueStorage[] storage, int i, TValue value) + { + storage[i] = new TValueStorage(); + storage[i].data = value; + } + } +} \ No newline at end of file diff --git a/Runtime/Library/SharedScripts/Classes/Map.cs.meta b/Runtime/Library/SharedScripts/Classes/Map.cs.meta new file mode 100644 index 0000000..a0bfd23 --- /dev/null +++ b/Runtime/Library/SharedScripts/Classes/Map.cs.meta @@ -0,0 +1,2 @@ +fileFormatVersion: 2 +guid: b85e0b29837fdf9478b4b75facb9e18c \ No newline at end of file diff --git a/Runtime/Library/Vendor/SerializableDictionary/SerializableHashSet.cs b/Runtime/Library/SharedScripts/Classes/SerializableHashSet.cs similarity index 96% rename from Runtime/Library/Vendor/SerializableDictionary/SerializableHashSet.cs rename to Runtime/Library/SharedScripts/Classes/SerializableHashSet.cs index fe9bddd..82d0cde 100644 --- a/Runtime/Library/Vendor/SerializableDictionary/SerializableHashSet.cs +++ b/Runtime/Library/SharedScripts/Classes/SerializableHashSet.cs @@ -11,6 +11,7 @@ public abstract class SerializableHashSetBase { public abstract class Storage { } + protected class HashSet : System.Collections.Generic.HashSet { public HashSet() { } @@ -26,172 +27,146 @@ public abstract class SerializableHashSet : SerializableHashSetBase, ISet, [SerializeField] T[] m_keys; - public SerializableHashSet() - { - m_hashSet = new HashSet(); - } - - public SerializableHashSet(ISet set) - { - m_hashSet = new HashSet(set); - } - - public void CopyFrom(ISet set) - { - m_hashSet.Clear(); - foreach (var value in set) - { - m_hashSet.Add(value); - } - } - - public void OnAfterDeserialize() - { - if (m_keys != null) - { - m_hashSet.Clear(); - int n = m_keys.Length; - for (int i = 0; i < n; ++i) - { - m_hashSet.Add(m_keys[i]); - } - - m_keys = null; - } - } - - public void OnBeforeSerialize() - { - int n = m_hashSet.Count; - m_keys = new T[n]; - - int i = 0; - foreach (var value in m_hashSet) - { - m_keys[i] = value; - ++i; - } - } - - #region ISet + // Implement ISet Interface public int Count { get { return ((ISet)m_hashSet).Count; } } public bool IsReadOnly { get { return ((ISet)m_hashSet).IsReadOnly; } } - public bool Add(T item) { return ((ISet)m_hashSet).Add(item); } - public void ExceptWith(IEnumerable other) { ((ISet)m_hashSet).ExceptWith(other); } - public void IntersectWith(IEnumerable other) { ((ISet)m_hashSet).IntersectWith(other); } - public bool IsProperSubsetOf(IEnumerable other) { return ((ISet)m_hashSet).IsProperSubsetOf(other); } - public bool IsProperSupersetOf(IEnumerable other) { return ((ISet)m_hashSet).IsProperSupersetOf(other); } - public bool IsSubsetOf(IEnumerable other) { return ((ISet)m_hashSet).IsSubsetOf(other); } - public bool IsSupersetOf(IEnumerable other) { return ((ISet)m_hashSet).IsSupersetOf(other); } - public bool Overlaps(IEnumerable other) { return ((ISet)m_hashSet).Overlaps(other); } - public bool SetEquals(IEnumerable other) { return ((ISet)m_hashSet).SetEquals(other); } - public void SymmetricExceptWith(IEnumerable other) { ((ISet)m_hashSet).SymmetricExceptWith(other); } - public void UnionWith(IEnumerable other) { ((ISet)m_hashSet).UnionWith(other); } - void ICollection.Add(T item) { ((ISet)m_hashSet).Add(item); } - public void Clear() { ((ISet)m_hashSet).Clear(); } - public bool Contains(T item) { return ((ISet)m_hashSet).Contains(item); } - public void CopyTo(T[] array, int arrayIndex) { ((ISet)m_hashSet).CopyTo(array, arrayIndex); } - public bool Remove(T item) { return ((ISet)m_hashSet).Remove(item); } - public IEnumerator GetEnumerator() { return ((ISet)m_hashSet).GetEnumerator(); } - IEnumerator IEnumerable.GetEnumerator() { return ((ISet)m_hashSet).GetEnumerator(); } - #endregion - - #region IDeserializationCallback - + // Implement IDeserializationCallback Interface public void OnDeserialization(object sender) { ((IDeserializationCallback)m_hashSet).OnDeserialization(sender); } - #endregion - - #region ISerializable - + // Implement ISerializable Interface protected SerializableHashSet(SerializationInfo info, StreamingContext context) { m_hashSet = new HashSet(info, context); } - public void GetObjectData(SerializationInfo info, StreamingContext context) { ((ISerializable)m_hashSet).GetObjectData(info, context); } - #endregion + + + + public SerializableHashSet() + { + m_hashSet = new HashSet(); + } + public SerializableHashSet(ISet set) + { + m_hashSet = new HashSet(set); + } + + public void CopyFrom(ISet set) + { + m_hashSet.Clear(); + foreach (var value in set) + { + m_hashSet.Add(value); + } + } + public void OnAfterDeserialize() + { + if (m_keys != null) + { + m_hashSet.Clear(); + int n = m_keys.Length; + for (int i = 0; i < n; ++i) + { + m_hashSet.Add(m_keys[i]); + } + + m_keys = null; + } + } + public void OnBeforeSerialize() + { + int n = m_hashSet.Count; + m_keys = new T[n]; + + int i = 0; + foreach (var value in m_hashSet) + { + m_keys[i] = value; + ++i; + } + } + } } #endif \ No newline at end of file diff --git a/Runtime/Library/Vendor/SerializableDictionary/SerializableHashSet.cs.meta b/Runtime/Library/SharedScripts/Classes/SerializableHashSet.cs.meta similarity index 100% rename from Runtime/Library/Vendor/SerializableDictionary/SerializableHashSet.cs.meta rename to Runtime/Library/SharedScripts/Classes/SerializableHashSet.cs.meta diff --git a/Runtime/Library/Vendor.meta b/Runtime/Library/Vendor.meta deleted file mode 100644 index a03ab10..0000000 --- a/Runtime/Library/Vendor.meta +++ /dev/null @@ -1,8 +0,0 @@ -fileFormatVersion: 2 -guid: 351fbdcf34a545f49a22ac661ed8bcd3 -folderAsset: yes -DefaultImporter: - externalObjects: {} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Runtime/Library/Vendor/SerializableDictionary.meta b/Runtime/Library/Vendor/SerializableDictionary.meta deleted file mode 100644 index 443cf3d..0000000 --- a/Runtime/Library/Vendor/SerializableDictionary.meta +++ /dev/null @@ -1,8 +0,0 @@ -fileFormatVersion: 2 -guid: 096dbd1bd10691342aed2e35d663eabb -folderAsset: yes -DefaultImporter: - externalObjects: {} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Runtime/Library/Vendor/SerializableDictionary/Example.meta b/Runtime/Library/Vendor/SerializableDictionary/Example.meta deleted file mode 100644 index 5bbdabd..0000000 --- a/Runtime/Library/Vendor/SerializableDictionary/Example.meta +++ /dev/null @@ -1,5 +0,0 @@ -fileFormatVersion: 2 -guid: ea574807be3814126807ca7b22d13988 -folderAsset: yes -DefaultImporter: - userData: diff --git a/Runtime/Library/Vendor/SerializableDictionary/Example/SerializableDicitonary Example.unity b/Runtime/Library/Vendor/SerializableDictionary/Example/SerializableDicitonary Example.unity deleted file mode 100644 index 073e39e..0000000 --- a/Runtime/Library/Vendor/SerializableDictionary/Example/SerializableDicitonary Example.unity +++ /dev/null @@ -1,256 +0,0 @@ -%YAML 1.1 -%TAG !u! tag:unity3d.com,2011: ---- !u!29 &1 -OcclusionCullingSettings: - m_ObjectHideFlags: 0 - serializedVersion: 2 - m_OcclusionBakeSettings: - smallestOccluder: 5 - smallestHole: 0.25 - backfaceThreshold: 100 - m_SceneGUID: 00000000000000000000000000000000 - m_OcclusionCullingData: {fileID: 0} ---- !u!104 &2 -RenderSettings: - m_ObjectHideFlags: 0 - serializedVersion: 8 - m_Fog: 0 - m_FogColor: {r: 0.5, g: 0.5, b: 0.5, a: 1} - m_FogMode: 3 - m_FogDensity: 0.01 - m_LinearFogStart: 0 - m_LinearFogEnd: 300 - m_AmbientSkyColor: {r: 0.2, g: 0.2, b: 0.2, a: 1} - m_AmbientEquatorColor: {r: 0.2, g: 0.2, b: 0.2, a: 1} - m_AmbientGroundColor: {r: 0.2, g: 0.2, b: 0.2, a: 1} - m_AmbientIntensity: 1 - m_AmbientMode: 3 - m_SubtractiveShadowColor: {r: 0.42, g: 0.478, b: 0.627, a: 1} - m_SkyboxMaterial: {fileID: 0} - m_HaloStrength: 0.5 - m_FlareStrength: 1 - m_FlareFadeSpeed: 3 - m_HaloTexture: {fileID: 0} - m_SpotCookie: {fileID: 10001, guid: 0000000000000000e000000000000000, type: 0} - m_DefaultReflectionMode: 0 - m_DefaultReflectionResolution: 128 - m_ReflectionBounces: 1 - m_ReflectionIntensity: 1 - m_CustomReflection: {fileID: 0} - m_Sun: {fileID: 0} - m_IndirectSpecularColor: {r: 0, g: 0, b: 0, a: 1} ---- !u!157 &4 -LightmapSettings: - m_ObjectHideFlags: 0 - serializedVersion: 11 - m_GIWorkflowMode: 1 - m_GISettings: - serializedVersion: 2 - m_BounceScale: 1 - m_IndirectOutputScale: 1 - m_AlbedoBoost: 1 - m_TemporalCoherenceThreshold: 1 - m_EnvironmentLightingMode: 0 - m_EnableBakedLightmaps: 1 - m_EnableRealtimeLightmaps: 0 - m_LightmapEditorSettings: - serializedVersion: 9 - m_Resolution: 1 - m_BakeResolution: 50 - m_TextureWidth: 1024 - m_TextureHeight: 1024 - m_AO: 1 - m_AOMaxDistance: 1 - m_CompAOExponent: 1 - m_CompAOExponentDirect: 0 - m_Padding: 2 - m_LightmapParameters: {fileID: 0} - m_LightmapsBakeMode: 1 - m_TextureCompression: 0 - m_FinalGather: 0 - m_FinalGatherFiltering: 1 - m_FinalGatherRayCount: 256 - m_ReflectionCompression: 2 - m_MixedBakeMode: 1 - m_BakeBackend: 0 - m_PVRSampling: 1 - m_PVRDirectSampleCount: 32 - m_PVRSampleCount: 500 - m_PVRBounces: 2 - m_PVRFilterTypeDirect: 0 - m_PVRFilterTypeIndirect: 0 - m_PVRFilterTypeAO: 0 - m_PVRFilteringMode: 0 - m_PVRCulling: 1 - m_PVRFilteringGaussRadiusDirect: 1 - m_PVRFilteringGaussRadiusIndirect: 5 - m_PVRFilteringGaussRadiusAO: 2 - m_PVRFilteringAtrousPositionSigmaDirect: 0.5 - m_PVRFilteringAtrousPositionSigmaIndirect: 2 - m_PVRFilteringAtrousPositionSigmaAO: 1 - m_ShowResolutionOverlay: 1 - m_LightingDataAsset: {fileID: 0} - m_UseShadowmask: 0 ---- !u!196 &5 -NavMeshSettings: - serializedVersion: 2 - m_ObjectHideFlags: 0 - m_BuildSettings: - serializedVersion: 2 - agentTypeID: 0 - agentRadius: 0.5 - agentHeight: 2 - agentSlope: 45 - agentClimb: 0.4 - ledgeDropHeight: 0 - maxJumpAcrossDistance: 0 - minRegionArea: 2 - manualCellSize: 0 - cellSize: 0.16666666 - manualTileSize: 0 - tileSize: 256 - accuratePlacement: 0 - debug: - m_Flags: 0 - m_NavMeshData: {fileID: 0} ---- !u!1 &714127983 -GameObject: - m_ObjectHideFlags: 0 - m_PrefabParentObject: {fileID: 0} - m_PrefabInternal: {fileID: 0} - serializedVersion: 5 - m_Component: - - component: {fileID: 714127989} - - component: {fileID: 714127988} - - component: {fileID: 714127987} - - component: {fileID: 714127986} - - component: {fileID: 714127985} - - component: {fileID: 714127984} - m_Layer: 0 - m_Name: Main Camera - m_TagString: MainCamera - m_Icon: {fileID: 0} - m_NavMeshLayer: 0 - m_StaticEditorFlags: 0 - m_IsActive: 1 ---- !u!114 &714127984 -MonoBehaviour: - m_ObjectHideFlags: 0 - m_PrefabParentObject: {fileID: 0} - m_PrefabInternal: {fileID: 0} - m_GameObject: {fileID: 714127983} - m_Enabled: 1 - m_EditorHideFlags: 0 - m_Script: {fileID: 11500000, guid: d5ff00a74ccb984498070d9930a7944c, type: 3} - m_Name: - m_EditorClassIdentifier: - m_stringStringDictionary: - m_keys: - - first key - - second key - - third key - m_values: - - value A - - value B - - value C - m_objectColorDictionary: - m_keys: - - {fileID: 714127983} - - {fileID: 714127984} - m_values: - - {r: 0, g: 0, b: 1, a: 1} - - {r: 1, g: 0, b: 0, a: 1} - m_stringColorArrayDictionary: - m_keys: - - rainbow - - grayscale - m_values: - - data: - - {r: 1, g: 0, b: 0, a: 1} - - {r: 1, g: 0.40000004, b: 0, a: 1} - - {r: 1, g: 0.9333334, b: 0, a: 1} - - {r: 0, g: 1, b: 0, a: 1} - - {r: 0, g: 0.6, b: 1, a: 1} - - {r: 0.26666668, g: 0, b: 1, a: 1} - - {r: 0.6, g: 0, b: 1, a: 1} - - data: - - {r: 0, g: 0, b: 0, a: 0} - - {r: 0.2509804, g: 0.2509804, b: 0.2509804, a: 0.2509804} - - {r: 0.5019608, g: 0.5019608, b: 0.5019608, a: 0.5019608} - - {r: 0.7529412, g: 0.7529412, b: 0.7529412, a: 0.7529412} - - {r: 1, g: 1, b: 1, a: 1} - m_stringHashSet: - m_keys: - - item 1 - - item 2 - - item 3 ---- !u!81 &714127985 -AudioListener: - m_ObjectHideFlags: 0 - m_PrefabParentObject: {fileID: 0} - m_PrefabInternal: {fileID: 0} - m_GameObject: {fileID: 714127983} - m_Enabled: 1 ---- !u!124 &714127986 -Behaviour: - m_ObjectHideFlags: 0 - m_PrefabParentObject: {fileID: 0} - m_PrefabInternal: {fileID: 0} - m_GameObject: {fileID: 714127983} - m_Enabled: 1 ---- !u!92 &714127987 -Behaviour: - m_ObjectHideFlags: 0 - m_PrefabParentObject: {fileID: 0} - m_PrefabInternal: {fileID: 0} - m_GameObject: {fileID: 714127983} - m_Enabled: 1 ---- !u!20 &714127988 -Camera: - m_ObjectHideFlags: 0 - m_PrefabParentObject: {fileID: 0} - m_PrefabInternal: {fileID: 0} - m_GameObject: {fileID: 714127983} - m_Enabled: 1 - serializedVersion: 2 - m_ClearFlags: 1 - m_BackGroundColor: {r: 0.19215687, g: 0.3019608, b: 0.4745098, a: 0.019607844} - m_NormalizedViewPortRect: - serializedVersion: 2 - x: 0 - y: 0 - width: 1 - height: 1 - near clip plane: 0.3 - far clip plane: 1000 - field of view: 60 - orthographic: 0 - orthographic size: 5 - m_Depth: -1 - m_CullingMask: - serializedVersion: 2 - m_Bits: 4294967295 - m_RenderingPath: -1 - m_TargetTexture: {fileID: 0} - m_TargetDisplay: 0 - m_TargetEye: 3 - m_HDR: 0 - m_AllowMSAA: 1 - m_AllowDynamicResolution: 0 - m_ForceIntoRT: 0 - m_OcclusionCulling: 1 - m_StereoConvergence: 10 - m_StereoSeparation: 0.022 ---- !u!4 &714127989 -Transform: - m_ObjectHideFlags: 0 - m_PrefabParentObject: {fileID: 0} - m_PrefabInternal: {fileID: 0} - m_GameObject: {fileID: 714127983} - m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} - m_LocalPosition: {x: 0, y: 1, z: -10} - m_LocalScale: {x: 1, y: 1, z: 1} - m_Children: [] - m_Father: {fileID: 0} - m_RootOrder: 0 - m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} diff --git a/Runtime/Library/Vendor/SerializableDictionary/Example/SerializableDicitonary Example.unity.meta b/Runtime/Library/Vendor/SerializableDictionary/Example/SerializableDicitonary Example.unity.meta deleted file mode 100644 index 25ff160..0000000 --- a/Runtime/Library/Vendor/SerializableDictionary/Example/SerializableDicitonary Example.unity.meta +++ /dev/null @@ -1,4 +0,0 @@ -fileFormatVersion: 2 -guid: 6c0758ade4ba74b7493ce3806fa2f38b -DefaultImporter: - userData: diff --git a/Runtime/Library/Vendor/SerializableDictionary/Example/UserSerializableDictionaries.cs b/Runtime/Library/Vendor/SerializableDictionary/Example/UserSerializableDictionaries.cs deleted file mode 100644 index 13043a2..0000000 --- a/Runtime/Library/Vendor/SerializableDictionary/Example/UserSerializableDictionaries.cs +++ /dev/null @@ -1,26 +0,0 @@ -using System; -using UnityEngine; - -namespace RealMethod -{ - [Serializable] - public class StringBoolDictionary : SerializableDictionary { } - [Serializable] - public class StringByteDictionary : SerializableDictionary { } - [Serializable] - public class StringIntDictionary : SerializableDictionary { } - [Serializable] - public class StringFloatDictionary : SerializableDictionary { } - [Serializable] - public class StringAssetObjectDictionary : SerializableDictionary { } - [Serializable] - public class StringGObjectDictionary : SerializableDictionary { } - [Serializable] - public class ObjectColorDictionary : SerializableDictionary { } - - // ColorArray - [Serializable] - public class ColorArrayStorage : SerializableDictionary.Storage { } - [Serializable] - public class StringColorArrayDictionary : SerializableDictionary { } -} diff --git a/Runtime/Library/Vendor/SerializableDictionary/Example/UserSerializableDictionaries.cs.meta b/Runtime/Library/Vendor/SerializableDictionary/Example/UserSerializableDictionaries.cs.meta deleted file mode 100644 index 8b34ba9..0000000 --- a/Runtime/Library/Vendor/SerializableDictionary/Example/UserSerializableDictionaries.cs.meta +++ /dev/null @@ -1,12 +0,0 @@ -fileFormatVersion: 2 -guid: bd910530dd8f6b5429c65a494644ed09 -timeCreated: 1493639913 -licenseType: Free -MonoImporter: - serializedVersion: 2 - defaultReferences: [] - executionOrder: 0 - icon: {instanceID: 0} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Runtime/Library/Vendor/SerializableDictionary/SerializableDictionary.cs b/Runtime/Library/Vendor/SerializableDictionary/SerializableDictionary.cs deleted file mode 100644 index 4926666..0000000 --- a/Runtime/Library/Vendor/SerializableDictionary/SerializableDictionary.cs +++ /dev/null @@ -1,259 +0,0 @@ -using System; -using System.Collections; -using System.Collections.Generic; -using System.Linq; -using System.Runtime.Serialization; -using UnityEngine; - -namespace RealMethod -{ - [Serializable] - public abstract class SerializableDictionaryBase : SerializableDictionaryBase, IDictionary, IDictionary, ISerializationCallbackReceiver, IDeserializationCallback, ISerializable - { - Dictionary m_dict; - [SerializeField] - TKey[] m_keys; - [SerializeField] - TValueStorage[] m_values; - - public SerializableDictionaryBase() - { - m_dict = new Dictionary(); - } - - public SerializableDictionaryBase(IDictionary dict) - { - m_dict = new Dictionary(dict); - } - - protected abstract void SetValue(TValueStorage[] storage, int i, TValue value); - protected abstract TValue GetValue(TValueStorage[] storage, int i); - - public void CopyFrom(IDictionary dict) - { - m_dict.Clear(); - foreach (var kvp in dict) - { - m_dict[kvp.Key] = kvp.Value; - } - } - - public void OnAfterDeserialize() - { - if (m_keys != null && m_values != null && m_keys.Length == m_values.Length) - { - m_dict.Clear(); - int n = m_keys.Length; - for (int i = 0; i < n; ++i) - { - m_dict[m_keys[i]] = GetValue(m_values, i); - } - - m_keys = null; - m_values = null; - } - } - - public void OnBeforeSerialize() - { - int n = m_dict.Count; - m_keys = new TKey[n]; - m_values = new TValueStorage[n]; - - int i = 0; - foreach (var kvp in m_dict) - { - m_keys[i] = kvp.Key; - SetValue(m_values, i, kvp.Value); - ++i; - } - } - - #region IDictionary - - public ICollection Keys { get { return ((IDictionary)m_dict).Keys; } } - public ICollection Values { get { return ((IDictionary)m_dict).Values; } } - public int Count { get { return ((IDictionary)m_dict).Count; } } - public bool IsReadOnly { get { return ((IDictionary)m_dict).IsReadOnly; } } - - public TValue this[TKey key] - { - get { return ((IDictionary)m_dict)[key]; } - set { ((IDictionary)m_dict)[key] = value; } - } - - public TKey GetKey(int index) - { - return m_dict.Keys.ElementAt(index); - } - public TValue GetValue(int index) - { - return m_dict.Values.ElementAt(index); - } - public void Add(TKey key, TValue value) - { - ((IDictionary)m_dict).Add(key, value); - } - - public bool ContainsKey(TKey key) - { - return ((IDictionary)m_dict).ContainsKey(key); - } - - public bool Remove(TKey key) - { - return ((IDictionary)m_dict).Remove(key); - } - - public bool TryGetValue(TKey key, out TValue value) - { - return ((IDictionary)m_dict).TryGetValue(key, out value); - } - - public void Add(KeyValuePair item) - { - ((IDictionary)m_dict).Add(item); - } - - public void Clear() - { - ((IDictionary)m_dict).Clear(); - } - - public bool Contains(KeyValuePair item) - { - return ((IDictionary)m_dict).Contains(item); - } - - public void CopyTo(KeyValuePair[] array, int arrayIndex) - { - ((IDictionary)m_dict).CopyTo(array, arrayIndex); - } - - public bool Remove(KeyValuePair item) - { - return ((IDictionary)m_dict).Remove(item); - } - - public IEnumerator> GetEnumerator() - { - return ((IDictionary)m_dict).GetEnumerator(); - } - - IEnumerator IEnumerable.GetEnumerator() - { - return ((IDictionary)m_dict).GetEnumerator(); - } - - #endregion - - #region IDictionary - - public bool IsFixedSize { get { return ((IDictionary)m_dict).IsFixedSize; } } - ICollection IDictionary.Keys { get { return ((IDictionary)m_dict).Keys; } } - ICollection IDictionary.Values { get { return ((IDictionary)m_dict).Values; } } - public bool IsSynchronized { get { return ((IDictionary)m_dict).IsSynchronized; } } - public object SyncRoot { get { return ((IDictionary)m_dict).SyncRoot; } } - - public object this[object key] - { - get { return ((IDictionary)m_dict)[key]; } - set { ((IDictionary)m_dict)[key] = value; } - } - - public void Add(object key, object value) - { - ((IDictionary)m_dict).Add(key, value); - } - - public bool Contains(object key) - { - return ((IDictionary)m_dict).Contains(key); - } - - IDictionaryEnumerator IDictionary.GetEnumerator() - { - return ((IDictionary)m_dict).GetEnumerator(); - } - - public void Remove(object key) - { - ((IDictionary)m_dict).Remove(key); - } - - public void CopyTo(System.Array array, int index) - { - ((IDictionary)m_dict).CopyTo(array, index); - } - - #endregion - - #region IDeserializationCallback - - public void OnDeserialization(object sender) - { - ((IDeserializationCallback)m_dict).OnDeserialization(sender); - } - - #endregion - - #region ISerializable - - protected SerializableDictionaryBase(SerializationInfo info, StreamingContext context) - { - m_dict = new Dictionary(info, context); - } - - public void GetObjectData(SerializationInfo info, StreamingContext context) - { - ((ISerializable)m_dict).GetObjectData(info, context); - } - - #endregion - } - - public static class SerializableDictionary - { - public class Storage : SerializableDictionaryBase.Storage - { - public T data; - } - } - - [Serializable] - public class SerializableDictionary : SerializableDictionaryBase - { - public SerializableDictionary() { } - public SerializableDictionary(IDictionary dict) : base(dict) { } - protected SerializableDictionary(SerializationInfo info, StreamingContext context) : base(info, context) { } - - protected override TValue GetValue(TValue[] storage, int i) - { - return storage[i]; - } - - protected override void SetValue(TValue[] storage, int i, TValue value) - { - storage[i] = value; - } - } - - [Serializable] - public class SerializableDictionary : SerializableDictionaryBase where TValueStorage : SerializableDictionary.Storage, new() - { - public SerializableDictionary() { } - public SerializableDictionary(IDictionary dict) : base(dict) { } - protected SerializableDictionary(SerializationInfo info, StreamingContext context) : base(info, context) { } - - protected override TValue GetValue(TValueStorage[] storage, int i) - { - return storage[i].data; - } - - protected override void SetValue(TValueStorage[] storage, int i, TValue value) - { - storage[i] = new TValueStorage(); - storage[i].data = value; - } - } -} diff --git a/Runtime/Library/Vendor/SerializableDictionary/SerializableDictionary.cs.meta b/Runtime/Library/Vendor/SerializableDictionary/SerializableDictionary.cs.meta deleted file mode 100644 index 43f3882..0000000 --- a/Runtime/Library/Vendor/SerializableDictionary/SerializableDictionary.cs.meta +++ /dev/null @@ -1,12 +0,0 @@ -fileFormatVersion: 2 -guid: e7be1c9624387604fba4005ccf7dbd5a -timeCreated: 1492868176 -licenseType: Free -MonoImporter: - serializedVersion: 2 - defaultReferences: [] - executionOrder: 0 - icon: {instanceID: 0} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Runtime/Library/Vendor/SerializableDictionary/SerializableDictionary.pdf b/Runtime/Library/Vendor/SerializableDictionary/SerializableDictionary.pdf deleted file mode 100644 index cad88c3741b876ba54c027e072b84e2556514fd8..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 118820 zcmcG0by!qi+pY@IIdn)54uYg~NyE^cBHbm@Dc$MNAR#Hz-61I;At8bwjndt47QgrX z&iPLMbI!ROFXn>1_w2pav!3UE?)zQ?Rgsi_&cXTu1NwdI&k_a)4Lgmai4BI35SxUv zxv`6*GYw3_%GuH0+SQ&3gH6TR(ahD<9Q;z<*4mg2oJ(WR!wdfK&%xG?4wA+$<}@%# z0Zw)fK6Y*nE{+!*yj&d2?Cej$3mm8DX!d_TL_`F`+`;Vr7C8Ugt!Q{UnbWZ8D4W=r zo4R1Isk@rE{PP<*dt*y;3^r|RGZ!lwE`AOSHd%9PODh)|4sK3xPmXqu&gxFarr=yj zb2n>Kb2S-p3^s9Vm$xeB&JvFHPL2-d4lXo&7;Mtkb}rzl*re^i{Y#pgI+}sYDwsQ1 zg6s10ad3->(7bg4<6)2Ck-3xQuAwn=c@`0h+(IhV3n7SE^J-(Qc-)rP7rA3n4(;n% zP{E@hjd@2OiH%>Wk{?cJEwN{g5^5+FnfN2n>*HWd`uysG=z@FM*{ciRFSl!-SJJxq zzH|5`JT?!oVkD4U_VkZP{2bL1Fu@7hYufyCB0LJMC8|?%Hm1Nu=`$a zr`5aBGyc4t_4?JrPr*1k$KyI)-|_qx#~uM{#?+PF%o7&@k7`rtM+cq<-#h$o*JiT) zZ}vLCf3~{|Vc)YaM{{S?uR8EI_V%*hzyHobPm7jUQ~9CBWZk)i-m;?O`sD7qFgQv7 z6@oiu&}>d$O!}(pCE~-)`EnQuo4?P&_oI}%(3frJ7bN+p${(f|nyAS#es64~BqbHx zgrEhE=`ZYZH#RO^VSm#;^^$ZDhB%#zxB4rHSy;c77&?*}^}p%3+q(<8*up{ABO)S_ zl9m>a%2)f7sukZQPq>We3kraBu`avF9iDt&4ei%lyxnqt<#pY{D%Ha%o>JRlDlQTG zM9{*-gwy_K?KkpH1d}@Zg9O=0T_hTT(1r!yitF7WZk&x3b6h3E_q0tHmV(|-cL+oL zmbP0K=~sKBNZ!r}pzC$9{%m&LBIQ>p9yU8XJXAZcL|Zd>(&}@)Ewh{QSzq;o)H-W-TmI_TRtU7jL#+-!+>LC7(7YR}09=$u(;2Ewl|r@j5K*TBoUB z{d($Fw1T-Swff>_tLTm{#C$rt-O%gMYtYNmKYT(+Di4`A5L4k<2!J!`F?99GYY?ac4!7y)$($Q+~=LbZ(b>qXt%j z3~vcVV(sniM@B{z6&1s<$kbRY-(78brZ!KD)7GwBI0f7Nn%dASU=G0~#UCnhHL@cc7Tz~dN`kdkutrzks* zKROegfH62Er0TF#yW)0@&7Z@zcVa?q>DNIT-y1p%Umu@F$P3AchK7bt z(%QzithqMtGhC5#8X+NrSq~#^dQs~MhL8qjQq*6=qFAye86CT0Ydv~rw!Kfg;U-Xb zDv_Iu)sqPV<6ix^&==g?BUjr*s?T7sAFZBT?{jJ_N8$Qnp-I09pTSy*Mbusy81PAn z8}4iS5iZzY?0V>(sHi?VS~-2Hh0CA7xdHcMO9_@+nB8H8|EL)-WgE!WtG6RNbaQj_ zi6OGnxs``O4)H7pa5%@Heou7FLCR1tJP+!M4He0uOzf=~U5x%H6K63;je^d((jTY2 zF-=-&ui|`hxMn+3P8(FN!%x7g^bx_m@$P%D`rzQ8!CtV{Mr_z5y?00bDf=rwwGlayjAghftIA>}@uT0qX-#YGC)&@oYW>h6 zn(Sg+o9Qkq}H{>IAiBbRT;-sUvebE!K-!T4Jy|Hp4-97a|9Q}1+{jK*@rJkaG) zv=k*JgR9pmt-{sMkC)&^_+8I#H$TQTyZq@+ffF6|bueA%v)-=ksGO5^bv{se6sJFn zg(uzVO|9^zL+eGa#oV88wT7H-dhJ6jjxq!u@&p00|EAhx5 zxuZ)2x_?~W%Q&>3ef9F`WA2LA9XN87d`>jq^4^+{@UK3H;*bXLg)ALZ6nia1CMjU% zW2O1sTr$}vArNNb$%$25PLqrEQQdb!wq-Sr=|N%V@_YIHi+3*j2G@)!WA=FiqoXzgX2M5RJz$_Fs zSi8MFCMG7r`Akt{wBA!e0js=R5Ap8fM|x)Ww{LBarq7}5!79t!+gNoyb&W-qSglQb znA%EU5hwT;2A8zB{DBaXHbkpWPftHvSA3${Z8O{A&c^BVASnhFi9Od6-uJEY;4O)x z2#3wrMNwf7^MbZf_!VXb?$wQNe_F?$P>V^*#soH9qXmW(I(56QuI`^df420+P}tIr zAY^0_L{apMKQ{;EoQ?J#M9HSamqS)FiYioTrvfO_g@BF9=O8WA~bo57m3s+tu`l8YpV%wYY<+ioQVu&e2@oBPyV4Ybhs(e&KX1e*7$K|oLr)pptt?lFL_p=zB)uNr% z!D+!OTYe)Hf$DFss9fZ{YCKO0@;e$sU4N}}{dHpZZtrQ=E@^|2QKm`{B*<;Ot`M-r zI$Tt@ksz(i8-?ihio8J8Ge)2tKx31nby<_)0 zFNVthRip3C<%moimF6_%RY49>`|Zn|-#tuR?=>EDmDrt!{()RK0w}{R>f_w7CV2iP zleH}%4><$Fo48(P$fv; z83(h!6TaujiiwF;Oc7afw(XLZ8#Lvyz#oKNzII_i3#7S!{d$u?a~$_=fmqTq5rIHt zWa!J{T|U&JpEk2}#LVOBdIV!)DzSS^R-%#KFF}_uU{*abF#%u&Ja9}{CpeT2UO~Yd zq(Z<5pPHJ|!R6=YZ}RkPYVz!$K02&^>pa253I65E128mYQ)${C>-Jf?HNd46W^QTO z($cc`v(6S&AW&x!cW*K+;?1nFp2FjwL}+*wU2L_SQO|qt@81T6o$ZPiJ2t;(doHUy zYUD~PsMjUf=)PyDtgQTF?k`Kd5`Ny3NRP7hW(tbjcpfRHXV3n21|a=7v-{Y*gfB5xY|7+rqaXN!wzPHUqIwm zb_CI(t}~dn@4s$gZtZrO1+HnRY2n-~CC3<*N=r+B;CmzP^y%~G?d}lFu~K@OSca!h zF|mls^^A>ar->HaDG%J@Idtk5rL1VlF-DzZCOyae1LlVEA+z>FdGa{?eC{ zl9GY^f`X;yYcY(zXbMr+zlgRrVG$@7C#Q}vNJ0YcPEMVlO8ut3PIyG&S47#Uc9R=L z_PnHm>Nz}2mGk(%)Oc}m@kaFBBOR36+uL|XS>kESH>H!vsHks6{WhZ1JUsYpP>_** zPNuX2YkIa0BVlXuUmbZ223afYtQ;;c4W-TLT}txXn?5y5hrp7OlTF+)mBe7;;^H)l z>{XRFkINcc!@^LHQK$ADK8X0H3wqyNx<ME3@+kll^*KUGkDA_Y@AliT?N5F3x@))m zNwgQ5n%s5IB+(NCcUbry)64AJ8RWupX(e--HD^z^XX*Jc$A2F}B9OBUbhy|{8^yb1 zjcjutaen*uEmMu@bHvgcEj%rJW+AU*n1VnNXJJ z>;7*dxb0aM62rlE(wP<(^f;7y(vP3BV~Ox1rw1*Ph+ zXO6xSMB2a|c$f&G;YbUTt+q~ujiQ}zT1ap4dmj2OX9a3TL-`Y^4?U~$8??n2 z$axyBM_MnNS)O$W)ofdcxe8B~emK7%lWjTrp?4RoN(@|F z8T8;sC$oMVpTw#q>F|k>V$WqEF5RPFsNUK=mX{3ywP`ix#YH;%`y6>vtZ7Kkdm@ug zJaAj5Z*V6rOc@1GkS-4yP(5vSFkd5_osYhj+L*0P$xTd9@Jm^TtkpG;|NToLKlF?N zB4=5lRrjv@{QTVI6oxiJt4epixEZ>anTjAJp{6Dwxx1?3j_6%pT{TOaCm zU1PRoL<1o%6CnwC@}%wU#xDUuO1SokMW=;s#~=#uDA3|kCjT47;d5ca=X z+^IQCBwxOKz)Tn+iG+%?J^r!(`r;_+bzQZ_S?HEhw#X}|XHTE@1DrBH?=xAfDk35h zxX@@55fSnJsq*f08Aa?oZ=;jj)^r&X3f9ZFAbNMjgHW(Jxw)m9GBPN%YXJJ=3UzL! z5|hdJc`<-nNrX`#pKMHUyf(w{PF}ns6Yij71KOrgLLnB0ZjK^*qYtf7@7t zibFXtJS_Bf9g88{zYH{(zkeHr6KQ{+o#lW2Jf_XX$w{Zi0-F;Ir>l#L2A@YD&7^S} z3PU<2_yv~zL%>T8_c%7 zYq`PO&U~kTr{tZ8weV8nA|e9Nc|G=jyD$2tFcU^IK%t;(gLHG-{ivLr)G)6R!;{Rg zVu5p}Vd3BqqRWUe$cY4wMD4J3SRNf7{wDUlKIk{?i&p&s*L57LO5?J`P!dBJMKIYG z6y7HY3Q}=&bo5QFG}uGX+Ou_BCsN>w;iapdp(;c*ru?l1Sk!z8syT^ow*ZnT$T0Y~ zs%mPGYZk3W^C4oGgqaz`QykE3vfO5LFVNsLZi1BiTR}=v5{(rZ_h2knf<5_n`*Xuq zoiPgSk)J=wXF^g??-M{TNC4BXWM$E=cu}88$}vF1HXG5>kj1P9ZH3jB(Xg;IUWrwD zexI25jbWUDOD#e<(SyILf$==4sPot8zgZCp z2?03cZUgbON=i!i0TusQ?mZ)5CYDlDQ(>Zdta~6d(kt{El)yr+0}DBj=7ltuDji== z72q|tw^i|i4|3XPqzCBV4~Ak>5K~gl&mz(O8w&-Fp=Y3%<)S~0e(;1T8pWW^iyI1+ z61PGw#37I+P$GRn&SIJs*o8<=UZ8vNNWCZkHXcmi6@oIPQ&cHDF$s5astgGUNlPO; zWMpJi{F&>Edl}c4cic?kMZoxeljT?!(HBidKuCDp?4EDe(TaXGP$_Ax!~FA1f|Tr% z1^%nq)z;3==a(Rz>V!x4l+4v&>zkFn?Azla@PqcFxpr_uZbM#AoY!Q}+~a}CnVAZM zrisZ(LN-7XpyE=^gWek|pFGg8{3VG`KwuZ(=(RV!7e^aso8zXd0}1oHq{3b!?(pn>a=(79;{vne=&=Rit^rT zJNqF&m6z|Nb@B3;g@q+w&Dzj#;oU=|R0srF!jH_BvN`{iiVWg>C7aziu&%ByEKEj9 zDx@3Zn(AAYV1v(vv!C%|yYIz#rjD_(@e&BrD(pr7yBn~qPgB=%#N|~3HM!h(4a|%- zdU|>)yN8DrbaEv^v5dPu>g3v}s_~Wj1O^5cDx`HEzGqaN_&rE#+(X(7o0^>LEYhj9 z!k@FU)t3?u$Bl6;S-;i4-a`zaAqm*0bCP*SU>WAA@T!ZGQiZa@pK+HR_hHhPR4{vXMUEKrueMrcT z2t{x}-e}%rgb_3PhhuW&C#Ojd0>_>(zz<)%c+q-ydj$xYEI}-68dbXJ2RDQTpmGb- z8WJd^_vJ|vC~cyrKfhmtl6ZPK0WjCocy#e_!w5A?)HfU`R^90IFJ&-3J|tX_p@4mW z7$d6)K}`dfnee6GQHiMk{Va;Ybp5Q+xR;nc2lfy-7YhQ#fk02jo%McH$S-(pm5BwR z4EnbudVHZ(U8Yf0qu!A!DLJ_^N=Qf$_CB2~WbQs6vs8ujz-`nZ#YNTC&L@AT?w^#) zLIET?I0GaiDM|Be_tzT)yx=oAPax?2LqZx*j2hGk9??k*YwaGy_@y zU2Z#M5|WhaYEC=kZ8oh&pNm6m3Z5K$Ev;k>RZav?b#P!kkKvz;=I%;}qUy9yyS(&bjjPA-zZ){vQBB2yet>8bP*Vc_HI2t!?`rh1 zaph(WY_K1$Mp}&89f)i07h$8iys>1`sgPLFSz-P1U+4IL%9ZyZ`MI)-PA``Ii}ylD z4g=}rCA$Q~7_#tX&(xt-AO*MTdos+#|O>P9Dw>IK+G*z0(6x@_)8 zm8q|DnK33~xmKp^d3Q!+syAPi5u zRM~`dqk&}>BO(dz3jzg0uB@83FGBwE0D(sTZkdUUnov1{{n0TT@gMd1AI9RIw=e?L zzSfjGkOm8ljjiHKPiHso7Tjw+S_-57!2hRM;)EizBX3|kY90d zae-vS!NCF8^4;wvfVTJb@a3l$i$GZt*p>*#*`+frt*0nt~&f`UP?tEdR(hr zx27K=q2x5Rv9G7?j&tD_T6Cc$qAZv60T67#_C@U2g&0*;P*2P^%h z#V_%YSL!6u>m#G0FpFddK1v!Z21K(MG>%P8X+BE=0)lf!1IVbkxw-7MK-D3vSDV&% zbK}WZaIyic`RVB?Na-e3q>o@$y=#^u>5p#$0__)CJpt7Wa1ttxnT197mq6r$3QY|S zLP|=ks%0AiLBXPef~pk2aN16P7PHv-SqJD(3{+h9PoVVo_4Pd~eTf&`C${jL_f1}Y zcNk;%WO5+?Yy&?HKzin#crW=%%;yWaGbKKcidFB}(y0LK(!i5~d7_zI~|YF^&; zXE$~Lti(+kIm3N-zKMd@A=n?VX2_yZL=LmnkH6xPkqt(GtS_aa5?}p4;pK$KE+JPa zLz4d$D~mq<@36A8$MyLeqC8MYXk4hMs4zAjQqi?a6?~V(3#LpDS;zVRfSL!IG%%zF zdwWB;UpF{pVW9jb}cv-kt*FMLIZ#in>TOC*qF!bHI z=eeQJ%bS}ccV34NgO;{wr`4o4(hc#XN(U_3UqEjHi!|nm;PlK)Lz|bDVn&|J`fwT$ z&>px)e&kt7l|{h*aMsbn$EYpHIi!BJ`?eGm6!1|T6Gf@!*4TL9373diiwE{2=E!hJVIh(fVy^xIbNAW=7-@TB0cj6$te8!noJyR zmUOM{tS*|O1^Snli3(W%6~AK+!5n zO8x*`2>{s8)CMP5;Ghu%xfS%CiQ1th>P6xSh(Dp-A7;w*&lbG*uu0iFXJ^THC|+P^ zd3$+PV>F79x>mMG$5MK(^kJ84`ug60d^JunQ)8nV=-NXV5g-JAk>Lb^!kZO7Niw~7 zK{$uZ1F4mDBq~XL3O|S#3?q0}&oIA`^m7~GyJgp2YjKx)MX}god8PDao^@ihkU>() zDWkc*-fjPPm#3#Edm897m?{zE6cj7V%Q-}cd8^CIYFb)u7l-CnQLWplX=%o?UnS*? zM?ub!3IkfAW7|n`X({t=FJO6_`=7Ds*JCkaOOrw%oEF2RCgD?s4-E)G^lRnjYlWLU-Sv(V zCNt`?bw%`kt=vvDY+1Mt>WMNx=Llfq1Qc=TMU~|!Rr@wbsjRxyW}u^G*-vPNRbgQf zg-}uJb=j)JWIlPXyAO;4T%STM1RslBC0P*!$!`77N?UDXI$SogTLh>oVf53oJRfN-~f>S z8>87XFA?_u0?7qk;!{aU*W^elheXzgq&0gxJ5Y#zFUl26XqIX*wZ7O&ySgy~1^r}kJv*uFP@-$Na1>zgH)P zj{NvBz?o?o85#c-d;C5A%o0ZtY>P4*Q1A>AL1>tMqOho*XGSOogQFD5_Ez|LR+pET z16W4KBj&<=`n&FPevvG#&bO8lc=JADVqnt3 z$?uG#mYEK^(yjk&?^UaCPESrG!^pIR3P2}WdmJru=X3exC}q_Da;1m&hVyRk)(^-RZb!hwo)YwYT#7Eox2Q zt1oBZDwj(u!HDD5Rw0KwH6iG8|EuYVS^1R2s>0-Y$-&BHCNYHC#Kc~m&}lLcl~RXm z)8f^e<7eQSk_ zENtV6n>SG7Ud1HmWHo|b^*l>B;+U-t27v}e8FrHt^sFLuba%+_K7VqgGN1W%!&&}A zutjTPzcO#VuocEMzfP!JqIh3OSnCEN61$kx4uCKak1)_&Y^7(oN^Rsb(8|{OW$^aw z;Mdd9XErudgy2ag85!URmlVBK$-&=*CFh!|kf)4ES~KP;(*{aRE^*(`zddVr-Edf$ zIWvQrgY|JA(K%z#VEi!?g98L8YDCm*r$=XJrw47ncYM3%`Y8tc`_GnpOU1+htCjVf zqB%qoz;Qj;hs3ITh`w?U(aG*1I?nml$Zx`kf6#e%>N#~~=)l)|)7!rtX8*Roas6M| z-}t!xpSj;&@NxbR?l(^-4XKte8TK`W(_p)Iv^3Sob;ZS`V*_dd4?=q}U`Y^_%6Q)) z#>9A)?d(H@%;cbjxmF}$Stt(h?2Y}n;ru9@xnYX8V)w_@GLEo;wC zVO?S3E$5#4w1)CVriifb!WsWBFWpfxRYOTjL*Pbm{M#Ds1fD zKh%Ebv@I&Yv;qXuzuIMby|JH5OXU?5B!w4FcjnyZ>g{2_iDq0Gn$fz^@1KKQt=j;~ z#r2*H-Fy-jn=45V=B;Azxx~d*|FKz93dxXiVYnP@8}TCXaEzS zSsV>aAifx za1-(LgHclA2TDP=&j6+1X`7j?g1&A_I*7*Qe!9n#)c_$#%*PHfRMn!8kUONiS>yLU zT$N*q0yvA`sPn=769@Ghdae--#?e5BdnUg*tH75z?Sdl466j^dKBpsI+S%DjOQUSz ziq)cmX-<>zgZ>5#X*|S`yH6#t^`mr5I{#b7X&LbOy#n&ZncTL-!$x&_X_VdF-EcS@ zT%OWt-1BJNm?NZJjy0Ib1c=~_@;dD?6ue3k``SV;`7{jNnS>f0ntRZHe)IjInpfBuHg=;-7nq7a514!}{}cglp`aq)<4_zV zS)^Un`>P$xTZ5Pd2^O&7=YVmb67qOQ%*n|aPqICf40{czFO(%hQh}%Wl1L6#_wgf8 zprNZ9L7=}gIW@)o;ziE>cV$ug`9{_AIn8AH5jVKJ{Fm03mh6?3VufT-ut-(Z)F!6A^OM;=#LM(0s^veq z+411JU)#cJfrh}val7ZJQmhq z%l_$$p-|}=$>3G(V~!3W&z%JFU1GfVQ4Y>jVE16B84x zcGSoN<6loE?qp$Ud3VYSv@Ou2cTu9Rh2c`)ULTEi^CT^!HkfpNr1^Xj+~DWu2PBIW z)>nG%K26sw9OA;$(ZEM!mIO3Pz=F(_znZHuMLkm1)B71s#--AkKt@K!8l8PAy`jLw z&+mD4x&!-t5K!G{uAn>g^((O4GPX`7CoUI91{{Nx0v_}2;p!mJ=evS~-~MaZ(DBh6 zjjB$gvc7)(3i#LI1eLxQf56f|q*Q&McpfWsHvblo-#}t)^SP*Aez;7`WA_7OE#x=m zMn*XvyiaohMBN>Hnk`8#EhPo=(=<`Qcd<UOB_6Sg9+5yzQAP=Tc0Nu7hkIi;{EzNRT_fDjd$r^6nqd6dwH_eZ}Z#I zc!gxxhp?b$o&U3%y#`q${&EPa{#`E^~_kkg#I{n?dcVEJAP2+j(e=>An>VzzbEEj>bcz;)q zE1hLBQlDZvs&?vY)Q`ry{FA-QFQs{>9qvD%-d-Q%#kssiex|n5pSG2#YDn^2xfVd8 z))Ark20e?-LgS!23Fa&huS3THHPBs22}h7rmza<+7<`|td`Qk4#z zgs4B$xNVcKSvwcHy1D@6hDpqVcbBLCM&mKi#UKNW96Bm!k197h450*skBS%OQ&g-}k9U1wInR#Un`zZ~RC(V84#(6&hII(v6pJ*r} z)=cB?C`kUfj;u9XF4EKdo|d6t*891x%}%7vd3Xl<_xlWqtACwOrY%SQsUq02ArzfFr)m0zH=hFUu!9{e|jPan1z`1=bVKia@h7?IL{zckcGUmcZ>wb5n~`OW-8XSV zmTRYI(k;3=JMny$!}YJmK|8jj{(Vi@Oi?r5RZ)1ax0mjBb33-DXbdB?4=38d-zmyR z{kUD!6KiK>rBh|nE6>)pdRetk`meMbeBMu4auQo|QvYY>?&nSAo3Ymo3dKz4R;2RK zpUQH$(zD8PK5@UHEXM{1e}oC|R{|AN7T+6_i$wmi*Xep0ie-w0qJB4PaeW+RGYZ8Q zizsiszEW=FOI|TWaP;`Wm%qQkitVA#d4lpq{T>%?CM1qn$m{GP+v+!IJntN3uYB*_7*v5)-}QC7{(~ zW&PIQ-)~ZdMajnwC|}DUDohX}q4}%pq*8EzLoqNg^uQ0GUjvytP(&e1KvOyB0~R=@ zkiLLnQP~=JpnSgA>8%1Qx@o0Wwamt^lD3EH1#oyrGX`y49d%-9P)h z@kJ7FvzuWd;nh9K$P^dEiuI#=$m+ZcpMPvR6ep<&-7tSW*$^BU)(7 zuWQ2)0v4iBP`E*YhzhAsNzn$|0#aCXmp?I_ywG9akC6_vvZiLj4-I;Zv}nZ;PMioa z4*U08Z_3ECDKLvd1jJb7F|4Iik*Vo>g04Yg;UYLFHgDH| zUes2xjH8xF8OLY$-alLk9TSC^6j%^|MP&gv>;b@YSZr?tIs+gi>QSEBx$P|o_ai0c z=lk}$*=OfVHWIOr>KI`?5g?RS!^#B-v+eqD2oJ}Q?RER`vdwI@IX*r06G9M{Q`6-0Dz5Fdw@2gn`5v2$^i(y z%QDGle-o%@foo!G5hQTH7JCXt3coSK0!(cG?hw7Vh|l@{(Z=Y<5s<)ZYhPH2`8=-+ zTs;zxYn&<7DkJByOO@Url9A)kSf!WXf{NqZPoG5%853I^FKsaZe<6>kx&S|#*x3Ei zfaBX*lEa*JqE`M)P54`Rk5y(uvQUqM~;vGp|Xsmm{}xhu5`%O7Lf@lq5OL z_wu;O>*Uk2%=B*VvP>VL18|?D+GChP#j2jh#^nYHXY)FK7_snPPqVy_48VQ<{HdqF z236#5^pRjUvdJI!?5!b`kP_i!`1j3?ir%&UJj6~2CAC#eNYu+@hNCO%_Zs<`(aYkk zE7aMgbDCpJljzu1!jH8$JY}Lu6EZS}AX-S=QUl)Jz+v3l+6vkzQP9F3x`7El?{}}< z(198A98Rh$ix~h?6tJS6S33<;KWCC5R1ZN?A`Q71OH5MbZ_IBNHNd=_YR zP0e^%ULIYH9Vp=vxEu#~&j<(zNS^BjpWqX7>IhW_CA7*?ABeJ1@jD}DCGeL1kmy}7 z36GBe)@ZXqm~_?CNbFCqRLeF@l(Gbf$jKuE#65wc3L+I)pKP9JQS>!83m|s_%<0te zLV%559tI1I^fBwnt_sPQ{Gn?qbC~oXn8TTRR0dFj0Z6EzrA0q+Li^j+)^_0aX9DUe zD+q&bI!xrtsl3+En3SRR4NhNPHc`k{IU10*v9V#tJUlv*$Q~z%X)P`<@52&<@$&Eh zl>mRo^zZ>SxO@7>-I>?^BQ~HxB=i?6yTASAk76WCOG`RZU*}Y}BTRy9v^BPxQXM;P zi0L3&a*IAk*q1fH;aGKg8AOw$T=~IOlnr z6I?1~6cnPrxy9=OoK83c9C8nnr)TX@Y4$vyzRQ=)gw$86tl4Kt71xFuiAzKR(Ko0Fv-QutqGdr&!F)AFMCvrq{Pw3V4xp8dIUO$ zk32XgwWu*PlfUgB@#baS_CL%*=i^~wig0HOSHf{5XvAlL+W+0!y60Qv0oD?Tk=owO;czf%7W*U;8>2U<}Lws>w%&TnFT zd{s=uB#UY~8X`PgFD&08Vq&s7hvEGo;zx9NF?UHhQ3MJ6!-o&`KH|c@1ZF;J*HjqX zh1a!UgBV!aZ`X&>ac~@Bc{xtjQeFe{r5bcDpkxYwW_a=ot&P6GkLI2bH6NdA(8=gX zievw6a{p-kG9C$P2e=1deCKhP{{d=IXJ;p)H-Wl(p#nc(us{e{SrsQIC;#gbbL6i3 zQ^zB7a~Y4Jllu$U#CTu}N8nmXdASJSdS1VN{b^!+{9YvorHad9xbegW0bQiH%wjiw zv<2ksKwuoJuRo2al>iouuZPmSEglEUz>EUAooIU?8}66^wH{FVd^bSmbCCf>P)l81 zqAe&0=@%yyYTgz2xVV28G^om%d;yQ@H?_YV^Es~$gyYk%zM!E~YtCN}gZBhNOo)I< zJ6#s`G4#x#lAY6bn#J4u3b>j91>kky2C@qc&4YmCrY8P9UGar-!!`^=70&%C1qH6j zZAVX168XV^KoqO;2O+ZShh16~hQa`wUltb>m>U>Saa``*G6 z0s@I0P^DbK21pnX?S{L%1Ks!Wq`9pp@_~Spiy|rcDSq-=B?8A;WK()UQbJA%r?(r8 zlSIJ5da+$tli%mu30VkC;bSw8QOF@mzEkcbfGk@x6_{C4DPrQE1ns!FxpigmACH?e z7@#cyhV*-tsZ4Vscj8bA+t!~y4-J5k0+>WvgTh9EYnD!YMHnubFCaI9n-q>&0LUl? zJ{m|p4D%QE^m6avM)_<{k7T|SweN94K)}QMLFnW_rur=L4noI~TSFKOslob5gBKYc z9js3a6AKLu<>BEu_Rx8hP^g@}ySw|%8xbyBkeE*W44(v!H-Yz3&X2QOul0MOqJEtX z(c#D9V%Vy###%bJ?aNSLS|-NYHb=-l_e8+GF zorO&cu(f29@0h+RMT5ar~UOZf@&sxC3|z&oLGl>F6}! zHh#sDttx@Q@v^!Io+~CILhM;RXpZuM<4Oi8EG8klf+B%fimLm z>|B$WNWj*Ie8=5$R6$Ec@-e6?BkR3q(Y}(LI`sWux=*iaMJS=5iv^q*xcG$ z&J=Y`I;+$Mwzj%1*)M&b<$8=}u!PS!`rL(c_~=?_^kvO^%WbxPgMq=p!f7@dF0jeY zi$4Qcobd$#HU^Ui7Cd0N{lJzvfNcx^2sc!ksC8`V0zDGQZLLDbjLBbQ+41>K|}m3 zjEG8;F0JB#Ks6} zSaNaI0A_IW@88{pHVO`kRFn;{UNn#lXaWU#UIA)E#Q#>vR||+3B_&L);~&-}(8uwm z7~rsvh1R^8FH7vxCphv1+V~UH&U@wS6Vhzyh5?NR$ zZ+I)V+EjC#_ibos3xpf6#)=nSU;Aj~YZw^#EOkGw48(*A3bq^{9|IyQ=()l6eOyaG z0wEO}AgOleR#fc0zC9!X;)y|2Lj!N447X0D(L-_a=&{Ac#m>%mBA6=Xt_;-hdH+V+ zL;q2HSe+t4_H#PfDV4~Gm^lKsqp0x2la#N#{fNDYZ=?F4G#|wplt)cH$e{APl1a28xjgOEmGj&u>

ln`dp z#&8-iyT)F#0*>}zxwrL|`iH^Si{KgCm(&dn4Z+@!`c@et{ORzq`^FPcgZB1#oaA=T zSy%v71&CSlxn88u4?>=F#iF2(Fn{wG)wlpDCrJGq_ zd9ttPMy?+iCh@WdPyAC}@m(wdp)2FGCB8^GdtJ-0$vK4XUPR<=dlo5=mKQ(5v=B1T z5kC~HCif+~0S~`mzLkue3g2&cdxT=}hg3muBc2RMtcW%M21y z5FmtONjd0*gfd;hHi(p_sB_dEeENqXAb(8qFf(InNJdLesT@oIa+-spq~<{~_+|tv zD=T1g!52eoz+5j{17E6u_YnThXnqvtbCb&tmd};;~~ucTAhN&E<8F~vJ;7J zJju$)!h#rl0Z3Mz)i@nUovngMR-k&#v+i;tcYY#=tBH1PjwIff95pr^I_qP430}Yz zYzWr0E1lZT4rJfmET>H1Zcz`4D=W#v;g_m9z}E346x&o2><0~O($~_mu(poSu>$Kj zJfwIB^tJ)q%_!nXFVXp*xB>*#2J)v$XFUK*^Q>?(p!*Wjs?m+A!y#v$@KtNL{g~gS zI@l1=R@CxcRG#~2#a&qzkH6Z}I)439;4kW!;K%aYt2?y-` z%FQpGLm?BDte}H{t>~SZy71VYi+~xB)4lZ5r_W_&U6h%Jo;O-8=ojW=It9s|YQ}yap zLG1yCS$of(S?lZWuX~FyE&5QAlaZaTT7A@8_cefK>G5*b#{H2|#7$514CRy6U|wUivbVy1V`K^$D(e#a<=cs}|rw(w-jj zh0~so6zGI@H4G>!7?Zn33E$p?e=~YsedyCwFs9}SJPrCZdiEioNvauimIGE|CU=x& z4^K~J?KKMokqqE^4Xs3`%eO|R&bt8w;fUDM27v#gkk2U0%L}BhXZ?=Z1`hyQc0w6I zI-}eeR`&P2d&HXH84sERR%gIommCFA4D?7kIv;PKQ7V8010CRiFB)J?fCW9`AZd+v z0?Df+$EQCj?ekTG_8yd&q8m`UP>FvlE0!F!o%&ywh-ny5z0%JdAKd!)OlGR*d_ol{ zeO}?+?@4C;z9}-kxw|v{Lj*BU51NDwM{keZPZlCHx}*e|R6BGoexB!nsSR&b$A%`O zW!ZfhCZ&0T^c>$)i^G(Mj*q`lqDV-SlAG$RqLKheF#uiC4E=mOydF-vvFq)Jq6*l} z5TK!R-AAIaMOC3+Ue0QO=4|oT5xqZ)i($06+0~{Wa4;>5>y3cL%1{at@}CWQvIVRB zi;mzws%Ofi29Ppx zRN9y8ca^PZ{UR@-euYkeKv{rWn;Y`4F9B$xOH;}a@a1_5zVEi0FV=1_pN(lllHBzL zUK)|Uj0|j7MNv`cM4|gm72vLG^oN~=t{#pfRBXwU99qLsb|GX?t=y{;6giA_`>jy^B5TY!H)b$B*L{J{~=Fs?J;I#k{^a<$)7}t+qLr1SuJ(c;*-k zqSLAXB?{Y(ffwe<8sLD{7GUPfmFVmKjcU&}iBlvdv(HLyJk@AYB@SFA@?k0fh(35g zxRbR0eC4aseW&wP1#J$25(@h9)f4<981{uuFt%=^((0R=%|Gs|LjER$*aF}{XsN|!2~ioi+Owjg zqg7N@%VY`%ZeIJF0Fwe?^7Y~Nb^uN-ek6f)DdaJ}loe=F5;L%XD@tqYh!W_{QTz#kg6j;lrbt3hBHKF7=5_y$ zrf@!26a|nPiHWL-9TLcZ=V8D*LMReIwK$aHK$!w8P5-_~ysE^4RSF3C7G%V;Oa3A1 z7_JVq!9LfC>$SDgnb~kjh04f8>Ip#Q$U} z(ACwAB@|=;O)_P{uITkvb4@5WD2niYO!DBK>V!!{{Ujz)$p#`0fKJjCHYy{Qv$Hcz zH8m=h7V<#U`6{kAWmiUf&?K!3W^#RG6l!(g`nG3DI-JS50(v_~*C~`#sy{hlWdzaw z{cW+zh9wCV4ekE!4nRQPNNe?RGTpU+l6Iv&l;-H@XeOOiQdHCgC{O`oUm?ww=TR2m zmd-^cAOI8shi98`jHV92?)^{wIGzQ=rmfflCWjpnAk_(zL3h-3h!?e5^m`mI=jZsn zlmSK_64IsFSwO=FA~r-MfzlZ$O0X17?Dqh38eqa?o(6)a#988g8te1L%>GSYCw@%kJBIy%-a?)7XWMw5lls3N{R;1$OK@!m>7g5q${a?-okMP z1_q$n3^vwhJc-)M%IbOrFcSkhJs8|%cL;3d83cha2NYCzBpM~~EU)x{-gyqDsCfY4 z3jnQRdAtKLNq#;L1(q6*rI+uITZGS>Qs^P8AObPvGgD*l=M6LP@bG}5$LG6xm)lFk zTq6}p;Sxwc4U}6OcvMBj#m3Sp!0L!51E7p340>aYUHlwBRX_;iS5ME%+5mEkPESt( z?j0yno%H@PaGGP!!nrd6CB(mYCO$qspbe_c&qI=Ai}+E-fcHi|lVfObFd8Uxsi-Ug z-yksEX96tCL~_s<%6z&I2`9)IZ;U5VJ%Rit0E)qGU^66rFyt#_^T9a%^V>q?acE`! zSRzdr30s~a~W`Hy%gInE-+J22u!r1+k&#e@c!e|iNqI~Gp$76SHt<&kj zd;>R$+>Uw{wgj9Tpq!B8fQC3%xxa1z@T_uy1n~_#G<0oq zGr=Ds(-9XipuX#DFqEm$Zh&+@X+i|N3Q;G_hP?sUtmcNZvwQBYuK2*5n9uc8R$iVk zuYaY^zDFQi^G{DoSCUaw1R9ShyP|qwYS1Z~f!V1*V?GoPlWE>EmmUD<0GJ+)`#B0w zjM3kthoTPl&dy|)#3UphPUgeUFp>cVaNVyhcm?PZg8Y@1CdDXG>>=5Irc^4K7tiVn zR4>q^hs+Aa6(iGnAaVC);XU)J+4! z-u?CQ%AMb*wYVJz(gB~#A)q{*Flpxjh@t^fE5zIC^LNkFSpg$+J}%egTKFXXeZ<-I z$Bj<7r8CgPbXrcMh=kN>r+g2PE0!9Lp8}Kl!Z&NT`i8P>oz$FYGRT|r>4Z4{CWy3t zpYP}2e0+TPE;-bPZQ31n`T-i2*aOJeLEgZ!0jC~&e|EW*d8Yggrb`EDiQu)4a2XdL4*!f;>3zv7!^z|(chtZHyP*XD$ zXByd!*H~n9cMGI&*t<{8M@9Xpow!j|*M^~*HEZ22ESjb&Txxx!DDj)T(Bk z$nFypWh@GVQM5h$R}jr&-|CFT=X1%DYwH29F;poW5!*&H>wrUiIr=S-iM+g`T)cMt zhfJYVI(GWP-DljJ6*ezpM*PKv8L4^P_LSBlcfQb z5)|hLujwTs9@o$G_%8wfImL|t6mKD-BL3A&`xOmspi;~$7Fo8On3`%cz6CTAvZ%pg z`qUBKhXX4dhzF@$2UQXEWi~97;#0bOE3_wMcY$I-$wTd2A z=j9o>X>hn3id+CN+m0gSTXhp16-t*?e^RUeRX23=`MjCHrod#zo&li&khlj6TU0I+y{OGC+N6l@e-vv#y4GVF5Ef1ZjDpe;a01Mt=t${Pw?{NG7W zK~Md~<7wR=0^`8$|KU?ppntPQnl_lcOS5edf+_C$uzIvp3seh(Dvm}d%*BDI32}Mi zYY9WL=;10+8sGdRTFT0-g!KiO9pRM{eBkL*L)n8)O1h$Je-v5G6+p5F`AoNA}Ax zn4OW5^XZ@?F3gfnIm%7m=Ko1l7!dHusH|?+F@Bj%iz`*Xl6|B6c;s}yJhZ)KPyYec zM^7j~_`!oro)QAy^Y(tWQ(~VYi0GErBluBUiRACk)A`&-m-DeR*7h`{b7c7-S&Ws@ zF0j2YKe02_pgn$b^Vbkp6v|-|!%4Rn$bGoo;We>+^7DLtzrH-^PuS&@jUF+J^)t{r zjp1)k|7In-S+IzR!6pP>s?aR?Ygz5{Oen{a@TE&Zlvl4MLKN*qmq8mm9PI;4l-3Fs zPF@20D~If;x=v0sjGa{P2plTYMCVCUc>ZLU~6PM$dI($ZD+HwOP)uj?DwJ z`a0f!T|9V;hxw-Uxi!TbC3TYc)!Va(=zIgeFc{sPM?+Rgb3+wdvhlWi#5)EYR+1b@ zAL@p*1Kd}#pgh)?vyk?81%h(D^zwq?{`Dg%kjIxdO>U1N#_S?-dE z#{M|JX9wuWutYNwhQNBFNRG&Ct43Ca*iqOGY1)1iIcXy-M9HJ;kSQ-*y3J1K&Dgi! zv8CDyIxIEhkLt`BQE`!N&*F@7lk`Y*B!a8zy$o{u;TGqMbxBaoSmWr2laCf$Fetub;j*@Z{38K7i3*7HTO2xypJzlOPk!f!|_}L1-i? zWhxdn=#U9YMuJ)b@sbT8(?MZDM~e#Y+j1R7w?JT3m~sbk z+GQhg>9fo@miQqpr%aoQ$aPcymR$ztNf>osH6p(pQM-WPwRK5wo89b63g$Z)kAQF6854VLDXdj&mhpk z|n8eVg@3K57MPOFs5$+Jf)NZJ9lt*JxPqsut_?-YqOC@Kl$47r42@bsROTJY>MwmU)sy6PEt~Qkf_dvqg7*wP zMKto%C8yVNj3Z5_HJwCDXFqZa_nW9vXFuX9YSzUJKBD2}#SAc{y6Uz4R8-(H*1V-{ zV{zB%W+LPY%PGOLl;1qc^8Fgrf;csRpPJRJTltJ?o#^IVUaFyXv~g|P4>x;z-^8Ye z^(2LnsG2-MPM_R;ML=&s%7eSZe1?DZT|zu3k<0FPc(m|WGiN6xe8p% zvUT-#l@mkWP?W2iN@OWc?b3vY<@dC*?RYq*JHQNGNQshxm*f(cZR^1js{R&I5EC&B z-4j#c($~dy&_!@RPtxNVMO^2>qiyRj=D2AqcTZz|G+pyeDIMJgz(Rcg|q@o-;wiM`6rGv*cUL%nxjv64{N5MC@zVQb!lP z6f!XPEi`$1mNmYS@UL7!Vag2g;4LaF6lbHXgROzgb0hzMIdjBvY4=WA6~zGiyoBS*6oRdAG_Lo#louX@>V%m7G-fGb!5+@m5zQbx}o|W zE-G8?#qsnTF&KH}Kgr}v2DL&|DTF;)5-pk79X;Vx?|3r`y?(Pt*j?w?+!LE8>TdoHfo!G~pxTTQp?(e?CC>0)v&7dy)s-NwIS!(1L!`m@_Ah_I z)ziUABPf-K7-)wqGbCH8p-B~x^YUn&@dsaDznwBPV;F{mx+<@C9Z#pqK9Eh!1mA>=8~0 zU5odOuS7eSu+~lmeG^prlaNYUPb%i{32)80b8T3fGUN#l#4vU1)A403C&fSKF6i^)ex!)a@ALldJf<|-t+lxLYgy(qKN$z{XHStK){##U7Pyiv)<=r>13~jRkc2=mVtQdBG|322ILt4ixqpaWK*=G*JF-OJP}*?}-!sl_4WqUTJaOnmJbz*I9WYqd@No zDXk%}cRyF7$FgMZrl`4Ue1f!DFU%hlbPiUC5EDe=NR7-;H!#Ch7KFKqSp$=((N#wv z2PAq+Rm>sR(;Nnp8A8hp^o9HmV{)|4m7uO6tkM=L^p^%2oFG1auW>|7jsnloACH`= zUJ8(RA~~>qo}$woWtRwuF6a;iGt&WtK@@0tg9uK6EDbJNk_!fSP~kdidNKw#X}7gi zq3mQbi3T1BeU0~CP{u^VR7^GKMa|FKlN?KCE9%d@sz#3VGzm0s&J=eOtKpkl^~<7{ zVixw&WrPvT17>`r@f`S(y;C~`s6gJZz2qF=amYcY0!QHlK1@~e0RrXN;{tN7b2@0s z7(pZrQp%RAG+c5v9f6X{cz{L)! zSm0lysH?1*i&(Yf@K;jvN%zPT)jVC(dyGNpL@$DWZfGgJNX`oIAFT zpc^Ui386St8Lkl-NWt}QxOVV0oXFW9#?y4sA%@v>g&bod*57oba93O@f4kBnxx9Ko zBfhr7NWb71Tybv7?;@F^3SO;~s()_JK7M zyS9LWu|-1(H{nH@>Kq*dVMFhd;o&gOB+(l~3qTMbO7PZtqDiY-Jxz(lp9hob( zCp>+MGpp{YdDnWqzcSJvS{pXX84d#-uxF!K{0Lut3{?nb_rql{aE$J3dL3a8f~X=+ zH*>9x`wbQQ(=F1vIinx$%TZOciV-Y&LVzVC1u9cUmdYqpU%>30D5=k3wVMtyrb(A) zvZ<0}tSjk#WySj5YL~wL6$1R9;Vq3#!%0}T_&E*zoTy1l=hos43P-&G2Z%2FKg1fg zmac`^BN)PqSlSJi8&fi~{Sm>z?BxY|?3H#2lhlR`Bl%s?c7{xWqpKJf#)SPn)pj^w za%HQOQ%4W)ZL2L5)jDRp^`;dBmxI;vx6^;x<4Fw?&s`MAICIcIGG`+9-KSwdrjNiu z!ktM%r?~sTLKMx_`u*YZ`~R@|yZ!9tKsn=%ho1{M_D!>On~p4WpMe3HITD-GW9s6j zyiQb#-Q=buBhPbea8_V?jfCiMP$<-;9~{hb&doxremQ=P5#%&Wjd$g5^wm9_V77Z? z=L?zmYOpjy{c!v4W9cV&aiL$k$h0fYDCCTuLpV8sas*MTmwcN~i+ozh;-tbaM2+!c?i`;9uZOGYV7Ff z?zm7gYrl%;0=2jJHt%M^xi3>1a~DQ~5YA`BlBI|0aTDKJ2v0k$F}x|}ei5V#vv-in z^}V#NRx4Lok*y!ps)D7rr!?EG`ANB8b_E8R4Yd-r~ve-AmrC(py$E}7oltaEv zS+!$e*eyZMnJ%=;pkV}`Y1Ae;z&A{6>-AH4r+%fc>08FaEAZk9F0cQk@skw%y75AEqwTxv*hwx#`Lfh9yhUN#WHl|QL~dSJ zUGzAnnuBqN<*#l~^(Md3iTc>Il6$0fKc>F2pWu#~5RDW?mLxOR$sVJ%Mvb|S1}jsL z8YeW#zf|*kY!YnFf|oQMT%YE$@6k;|_3!ta%1K4J&<{wk0H{Z8XWfkKXR#juG zwD-Xv{w&(Gg;*?S$0huq+QBW-#kv|y2Ww(lGaHDIs#1g!iy0MpmP1!Vvbs#+7O{_dmp#@P{c1Z- z$?;%u7_P}Z1tYD7>KyJ02)B*3b}+wj@7k=u{4@`o=BV57YG3|oa{A9H1d9Vc>a)Y- zbmzLq&KRM!z^A;+E)=H}Top&l9UgskWsV&!s4+sK26Y#AiHxg-*lmNgR*Ia92y9=F zzgw}xq^1$ba=hLe;9$1Zh`PL0xdv$!+u`QYFX(4-y37Hmu$+wL(LE^c)U;tV8C3&33U+k?~TV#;w|Y>QJPM& zce!}hxH3Z)HxpI#pqo1|)bG@_)^M_?>=wOtbpDe%ayGN$s}jA|?PvRU{#$ly@&3}^ ziPXAk?`FS>_~sga1_gBzCQCPh$a1E2%lk-J4j-H@$^6yWW5}!cVHT8B4l@$tfaS7i znR9Dtbq|ok--s;B6sE3(%onY3t*VqFj4!vZgh3XMDBrRoqB40`zlN!S_wsG~nsOIs0`a&=HX5jueFP=C|fjuZ3O{`v7s+qOxsN)|^jxG}XuFmNbK4KpX3)FZ7uG0jN9E)!* zI8N|NC3j}dOf14F3-DcB{wnl0bqbf>=i*aBSvBWI2=RNluqDL(}E&m=*2Ku*R&MHdtrU+S4 zL4YF*anX)+7esrNgG6E(9R+Gs=O_XzPgN{h2pc6_#bA=S2&=cRL})1RR46%Er!NoR zv{rr;6$MI4za#=HP*n`CawRGPg-?7Crc_A*`#Q5*{jNwvv2FZO=1pJz1aGDI#@W5nApb9d|;o(KjRJ6=>5VF-NH^^%ce zyw=p&{|I~YX?GVRn#Nuy>qU0GB`<2%Xifjndn$;PY-JEu@@SjRNUmI?&~g3wGaHPb z^GR}YuLU#qOMiV9oFw?n2THA4`muXJ;Uu%v=V(Ld2e8PVa2as1JVp++Zxg82Amdh- z==VgT*6QuaQaG())|_3z_4CvW?_9$XRq0CK&I%)rH<|1O zfST_udHK?UxAm+-bvdq}WN%GjB6tx_R94s6N5A_Un2r~8h0Rk_;IpQVygSlD&Nv-7 z73Cp-pR5{4xORVBRm%KuBd!fa*wgK<+-P9^K$0af`OQz`%NUtN9V8daUKE&3uWjA>Ed+oNpb;Tm-< z7?wD<#}@dh@pz}GUWtO(00OsJKz4KMa);d0KPo&m_Q6Ku8|+GTO|$8AoY$JvY}d{j zq$=-=T`=?3lbwlX2xkxhctz{kr6M#%;<)_I_7-pEbt=U(T;>s5f061<4h z-#5B|j$#V6E8F1-@jU9s)Z3%4p%0PaJ;uWAo$|sgjhxibLCw@sZdMAy$gT3i$P_9+ z&u`L#uH6w|u#rlj5{M{KC;xLXN(;06-Yh19UMnWT7A>cS5I&}W7+bEoX=R4UQxqZn zo*5)XA~NJBBb;_NxXYInWNP270^6TdBZ#?mj$g3AB2DmFV#5PbyZPN0j-b#cnY*Sg>8>9BKUOgQx1Cyt8l%^CrPX}-ZRds>ZnXNnT0hd;hHEJXU7 zHe&Pq6dCx(RTH@8VLkkP6WJVEHp&R-ubkiaW!S3GqMVI1A59MFX;^PPPW|AL)3qVH z3<_8pva8=?iJEC9pyeByQz|sUrPop}k?io4af?5B%!bq%VRiZrrJklxeU|YKAz=gx zd~e6cmx{haX(;iu-^Rmss|iN-?3;0}@*XDi^^W~@ON9?w?MsCRy|rV+eh}x{P7o&X zivk_bgfOWYCABM8>gKWPZg{~Zm%%Ere0f6)-Q zE3srP7hOI1*>jLhf!hlVKW`S5)?+A0=Q@ap&feDcg6Ht5Oe{?wN5`K*DD zT~W}%4KDDfMGh4$`yxu1t+*vvMy)v0ljS06sghBkFbf3Mo;>fJKoz+>IeL9uos=BG zsn+YsD`OO6zjgEcq2bRYZ(c8c1J%uB3k2x|bIZ>*GBkOgL3?n(e+x6(vO=oxL|=5R z!}?helRn6DWJ&n}=8S=yhKEjPqoyz~X?^x<&txJS7rSOJg!*P<_ZO|LlV|uI{le1rStl|GfL71aOCbeS;0Te_+ z82izRM@~#3lA-?1@0U7-()Ap1sJeMM9Rx#cm}^k`Kw;J-Ga6qBTJ=M@NzuTa$;}X$ z=B6)psj|2$W|S#sDg@VVzR<88o8XjsBa9`Vxq5|>ACgg)7sgUJ2q&4+K6Vs;&*ZD~ zU$8T*JM9jQ8r_3EL3$aczzof;2q3~P`uIS~9aFLk@j5A9OX-37KmK7>qW;OT&fATY-c4( z@lW=VUoP}pJFMNrE?1RiyO$5EkDb%YR};J}4= zy^l^DTA5w5WR}oEx5NB{KCC}##;7iDaEj$(zKAMYLlNypUj$JQ3lT#J2_~Y! zgNq$^@~%J!NcZhkZxU|p zxXhiPx1YV$X4~K3ZcXmmutmM{hl_vDh$P#SK$9M>mLtP%U_uG0lqWOtHX?y0Ma$D* zM>&P35FuI=Hjt;1-TrD_b*Db$j_8#WJlp@O?UF(PTHDB{0c(pL4a&qQU)b9onWWDi zznVhPAFLhJNj0HkY>~y3Rmpo8e(%$9^kj}+ z1MS=eCo}?{J!&{&M4ZCISW@^ri;b~o5dmU>Mk4lZ&5v1pVC6;>$4#a>=@wF}NNZ-! zZ^gNgo(T3`__->(O6`Y?8Ppcib=~!I1Rvf&R4bfv6*P2N8%R{z$t<8HJGj(i$PjB@^NhKyz&LjhZ>WdjfL!*UFSrFEya z+E4~JW;D4(7>#N7(7_C0k_5IAtLL_e!05Ub+*`g%YA#2VY3m2IFFy3)w-s@s5X0`T zmONG(3Ey#TxUkkBaJyF38YcRWqZ4rSIo|~Gm9|D{({g%Q5A-V_HYlA zX2fMA*P6JWQ46^dF*2^=e4@_iZz=B`U^73Jt-UhoYcGU*!dhvcZAX%4kI-LcXL3JR zg2S-_2)yG%ar4V)A&sJ14nn;bRIBPexfVQimE^? z=>h3gYS_5CmOOoLI!`e*EL;eWo*Bk?Y5-B?n#f!cQS@A`$BfYah{RB!Ww~_q=xh@P zPC@~q;dPN}b8N7A*YJq<+%f{7i@5Q}7;u6~E!|wEp-(k=-JuYJGMv|lCxb+jFRp%7 z*8&l*sq@YFcyT`(2!^8MwtfX_bFtmX2=ZDOQk0oNLNed8fQkNQ0b|9=qi1CTXJBOt ziG-gd<25&Y`_(|8AAU<3`SX^FVoGMt&LoC~2~2no*nc@KFg=Zfg((EsJ%HV9yn|qj zLBKfhZcM}p6d|frh4k*XmBQrYJ^W>#x0uu|2XX@ll7EZb|u=5WuSW`*&qUvrl1W=3(RvgWQ;SdGIUz@(O z&Vp1q%1Ro=81TS?)8mJ-8(mN#x4NK1qs8`TaPh$UO=l)9?by+w+_+iHRg!IRERHH` znZR{hrCFimU^}KEXa@c+s_0GKiXmog|8XM~F<7Y^Dn=TzejML!=|X9K+}=>D!EUir zele7V53WC4A&F%|d*p=PN1Q#Yc-7Q50YNaX3?ZG;W%}%~D%83%F^sm^V7Hw|c1!iE zH_UmviY-Y;XhPSb4{=dxyW`I{`0lscrr*Z&UC4ROcH$V8bJz987fmd(7tK7f7sI+3 zR0em$5E);W(pTe$*-5O}ZM&paw`#hLReAEe=TbLTsFGt9`HE)-*wOfT1)L$3so&0j zvRZHD+vJ67S_@~ZvJoF-SqpEcZq;E7Eq95zfkjVwX+K& z2hi+{4mo|>l}GBVEj;YtGz>9@L>)#0=H@{*rO7p8^DX0j45W@ay+ccd?~d3ZCX=1v zjajm+o`~jqf6Y@Z2rAo^n!f`Lhyvrk5W0+-kOUr2zr@Tw4&+DF|M*iR&R~C6D*Wrj zTVtslrVjQgKIDAh{)douD4ev2ubGLZ@`wjI1<98F*^k*JHA_<0)BB$qh1RZ7l=>}p z{n@eVtkkz34A#Vir(9iFgy5SD12Si5z^5z0nVIMnZ%^yawvpp7nD5tx3?ux1fzw-%mLBSOz9|wNAg_zIlYO_y_*EZjyaJ68z+5^J$%6 zuAwajzr(_0OaU^hCVs1p{q6ZgjitoJYio2jW*+YvS-92d6#aQw>T?gPFN2*)fN{}6 z_!+z3|4mzi(k+JxYjo+Z5R#m)QuVy8CXPk+ZXiX0qQ2+O5M6@Kr~ zqC4m}+_(D2=uv?s%4Ruli6rE{E@kY!c14fx~cwKDl;IwIjfm zjdtL@@nfbA&oT{T=TaVIcJQTvwD7q{aiCD6>M>-fQ1^l;!b~<3&VxWW&Wi=%C36&h zYu_u+okkPs#+Ao}m44bY%F+U;Es*?(iPLsu3g_7DY2@#XkLGciLtsJqGl*Mqc4pQwFlzzHLP_?#!C^8&S4` zvzGL4G>ScyRc$`W4q4a*J2|9ECFHjYHf??`Y7UAj%DK*poCeh*D|G?9&`V!WU|XX3JbHf!tvgDzG#83Xq!kcA}e zT#EVWd60s7h4s3|HM@1&JtUuQ2?eO<%(Zjdx52;_MLJpalo}F%2km;bjFxFU*h!QJPYLH|%^B z4z0uaLj3zofj*UCTOS#{c(=h6dDB^kN)FWUl9sRbOUNtWP;%o*LH|I?@d)JnpSX?d ze~a6g|F1T=3*EI?(iRloCCxi$kQUD#5a9r9vyquds8J|6W2in`5Z+Iu!XI=AL*1p{ zRBZSF+@`}$oiNm1JIXVp&kg-_8ywOTq&%>;1PI8Lb+f{u1b&}OCxreuAKnRIAJ4Cf zqJB^BOY?DpkvmJDMZ*H8!ZJm*_l#u{hVySA@;L^Ig543sh&4UGOo>ZHu)5$k5rtQF z?$1tUM5I1bckTsC7;9+t^0Qr0aN4Qgx|h}AxXY=VwA$YgS~ZM7zG#7+dvJ>k^uO3s z((Q0PAx!xxjh~@}eX-I@i2@b2CT!3hKED6`5hRd^b6h!S2~`z@-#ypBX5=wqfwt2V z@YQbtlnl{z6Ke;5v2C_O_)DA)HN7(e-{8&#coP!}KHs9walu|LdhCu+Um46$I)o}5#B z)H2^Q%hCVyQ?i0;W-N^iXWqTx31e#aNRJ`-P5$yUzl_4zus$mitH7MXIQmx_^x~vE zc*cwz_*s4AJ|#=M?y(%1COiJZY+5~*Ua>|7A$7Nt(nNbY^v%aKEGwGhEQ#+#nK3?J z`?Q#@3oBY*yE%y#4Mjo@FIrhlI`~Tg3nti9EJoQh zxvg}%`|W)=f7p*v`RPM%j7k=!!Ghw=kC=ceSc#}|6?Gz0^p5l$K?q1d+c@J(SYi14 ze>bzW*jZ_R%M7JL%s6W1d6akMd6YJ@bua$N9+u=$tdf7BS25r%iMc!dMfQik$&Jge z=){t5;y6Q&*LRw2cpf#5yc5qi;NTz#M*@sz;Oo*-5|*|+IXnwamg~5aFkG4%xCjcx z*T2{l$U=a>3t65)(on#I#soJlDc7mjt?o^qq7AiqCh4*e+isyd2X%~mtmgPY&IyhT z(;P~}b@rv+?2iz?l}bH|+Tt}SS?rOoG^)K+pv@fojCRnDtY54J4Q~0Z_FNgh6;+dH z6?8)P7|t_Rj1^QkI2QrLw2HQ{*&j05*v25=Z+Wid9nDVH-^L-ciF}M>ggwZ(%WIVS zRplA9_rgnS)3Vt(ym@yT;3+)Y-_9XV$(bGc7p=r-gptPld<64GYQ)jzK~5&f6k+4i z7redX?wnKksI`wC7pLCw@pd@Q!LqU8so#Om0vCPFh&=nnXbUzD-RQHOhx6UV39IVI zKtzBJPm3#iMHn1j+fNNMkLUvAxt>OjCc;?k8~awdxvNIGgtn3Um#hh~ps~J^AC}?g znjwfRBr|`+?0FO$e?vXU{E1Sxclolh3$yp7y=uU(^E*Tvo#YEmyINZgmGhHG;}l_@ z!S7@g1^1gRmD<|^4dGLTc5k)HeNi>tuy?+RRJFKUY2IJO+$(|_L-HS*rLEE})KmRd zJ`1(-z1p;d7%v(3E4kQM!lcDT+bhyUV+VfOJK&7YtHCI|#xKY}z-_X zRKm{T1Qh2y7y5K`vV$)NrAV2f9w305LZ_Nl3v0JJiEgzCa&4u!uSZYpbgJy$IL9W; zMSiRsucBs_aQ!m2e=9`mww)D@gp`TaH+h`flH2W&Zgi7PQa+;jW}80DfFc#idGSj? zB8>XM$H=w#FI&tGW?dwHoozB{qAY&+m}gW^kUzTiB6ks$JFmi`D>o%Vd6*m-`hI7q z3R@xBy{GYoeD*VnW0M#e*t<*S<0=g96D#?xgmbMNH0%iHP)->Mtke4( z(LgRNCJlIwG7DH8`9GSgQ3Sf**xF&3G}LVM-LNufNA|$uXQOYW9&w@Z0#4}Wj`@Z~ zs{b^q7)R5z{pDyPc?v?O2+T29I)Ts4XO)sd&mzAkn{yOj+)RT?PLQlE$vN|`yPCfmAda8Qt zprhWApX1!}`2uLG%#6gpz9J#*7v)guZ1hf6An^!=sbZR;GOlH?mwSw}m&sqeKu@QV zjVphUuBWp2xja`crJ)~fbfkDKdVC_#jHMba*jn{#F`C@^Q;*;MK6=rch;Yg_o7dI3 zHO)FeUog`ghpE#N{tFdo$5V0EJrG6gHc;~eOBEZ%i2hzH8`juXWiyJ%1g)%UVjKAI z6&8ZZkudBdmB46cm>`qWoNSej5FFCF$G4wrbykNvrPmxgMwCvSq&iz-u`x)5;oNM- zW9Wpze~aq|;JDsW;hmC$SF?-uKqgv?BisU~N2 zZXM5hP(;)9x{CA`jW%{MTwvC4pYa^4{5UG*#+1#G(^*>v*nH)2pC_u;=I)mYW3E+T z5?$Zd?KudV%YSN`6rspmdj|v?YB`OB$Pt`?K$1xqCH_rh_FVOlN%9v;A@*db>z&GC z2qvqC!0qn~{_UjTv*z_H38^Jp0xS^>sWv+nraqhZ!0-Ddd0W;|rzA!+)xMJMOX@2` z^0je}ioBePk(Y}gNLm;Iw}EPzi%NoBOMGBBCFvgOmXWCrx)Uy0IZ~zG0}7LK>09^3 zTpJP}1E(=&+=Q8I2Y-pzR=dZlKtGnz2(=_(LdSLauQu<>-H2D0f-z;Gg1Q|Xr&XWk zAWt4|`)m5F%I~qWO9<^%5#gw}Z&Jc{=PcbW&_7Vb9PjLcT3$CR?8|q|Jg#MoXma?m zzV_s_rJQN^gCNYr(GzFEbC^mgX5i`QMkz9gNao1!c<0}AC#ow>7y(l!o6dBqF&L$T2hdh*l> zujAb1(QP}&pHr<|!#+GF(LOw_I0~%=#jXo-feDB|CSGCF-P(TBEM4r2Bb&*dRujrK z2gs%tmy{(YELZqGpP|y7eQT+&T2Pjzsc+P<$cm4dY3Y^DxR5&AkZIX)hRK>>wWurM z9h~Fv5gsVNRBcv1*Vk$@->8S9yZq`4IS!$F;_pA02Gf*6wl5lz@ zzfpGBK@hXKTVK^`HvSq!V)d(^IUVa+R}KsmD%|_2(a~bEz)5lME>HJ1*+hlMtFv^| zgaByq#2P;t?r%%J@%fU*xIbvt;aoBfNU_GB95)tsNw8Zx+0ef%Xuk{eP%U3l!J5{0 z(ZKQ%nFXao>#R=wVt6gh=`YnD!M6|QT8J=kG{IbNt#C(tI9#(% z9U-&b-u_`hicbcf5F?aYtOo7!3$CTyFQ@cgqEI1$~i(ka!r1&+OT>nWGkac9`NUw3(em(ENs z!te7I*(~*1ey8N-yLd;)Wd%CIuw-;sD}SFr{WTES$WBxnq(bkV~_)dc7q4#H*QU!q9lK`JJjhEx^fh6KdbND-;rE8c~iI$*aZ^;->pNF|mwo z-wPWn^$VkI+Bc9JWYrspI*wU#vSJ3+tYlf=P~bN<$4ydnhO6hkB=y@w($i5A!>|B2AJ z|Cb1jnVaqZQr2{};{b%_w^Va{1oHh>0ED!6(&NBl1Z@8wLJQ;w$odaL`xCw}7g2?8 zv1Bv#6FrVcKqFp#gB0q^XLsT?DHeODufUsMF9t3?+wo4EKf%XG>W&~3_jXUuJKKIg zVGn-yr!;)eJE!Y|GLi~SXqUe{J!r=vsEe;3zmGq&Kxyol)f}%_y_cncgN?Fz8+!!;uLT9*jkQK|_S2 z|HIf<2E@^9i6Q}lLvVL@5AN=+1Hpp3y9al7cXx*bcXu0tyG!sl`S$Ma-M8<@`_olj zQ^%{Tr@Bs^^9wk0&dU%bt_;A8fS>^_&y@Zy&wPKTX~QFE7&QgW&LQQNS2YnRXmO&x zi$XNxG=~wxv3ME>yRH0C3HMd{S)d^^z5yNbwTmDRLu&Syab=$}v(9gNq`S;D|4JQC z-nJvz{ov$T@qDYqNJBLN9!@+?k3)EdrkY3xwIzu`>H*I2wlWu4$gmHz$|%NxuXU?U z&Qbvfr$%__fQ%B9vSLMJ=%G(7Bxuc_A?At^3Ty*M<>fqGcqq+U80V#m<1A_%=bBz! z|6q}lAw2mFh|y3{O9#(!DS7+k{n@8=5^kYHcF6}H7{L*W(t{Wnp%ALGfkh!p1^d;4 z5T{4#zc==YxV?O|cWMZIaLJUm8nmxQht)g<7WkU0WeSdhl>+JrC8Q^X%Yje40^LU* z^{x6Fc`6lld3HL&X_4HTwM$8=4Ar~=Xi4@Ay?%{|Ye2-lWhfk11%Y;XhfcXw4kg!> z2%q+C{R`z*IFwu+LqB=yXUcZg0BKuGow7z2mwK0UBf5~H*D>+xQ)tjqY=9O%ZJ-Ub zmnf{P@a@a)7s{2TZ-LDaiF!Fdi(J36Rwc4pG%lv=(`L*0f!3s_c=RJ&=H5OtZJU8w ztN76vzHn&fT0cLnVKPhGz^4hFLQs}7{0f%Ap;Y_LoL^EA!l|o@Wzb5~qMVitY%9Bm zP8|3MS3h75Xn~SbS;wcGY4ex1tYntv2!u`MmeVn#6m55A_jW140u|99a;FS`$%V}P zF{St-_COk9zDGRC-bDueb%iEkstk*yY8sp{$TW3aLxlh5@IG)QhKN{63qBX?1je|! z;F{4dbtwInAZ6Z-a$0*i{``eKH_t)9uNOPkil}^(g{OYn=`?pO$2`XPU2P3rcbT1s z@;2!{MxM|`KiQ)CRcmM2#6v1WHnlyCZ+g~lLya>lhPIY`UV7UGPzhFDwJ5uRN#i6> z&)(EWaH%@HPRXJhXOszDiSCzGJ&sZot|}@ukcIGu{2g=h*n3A};hcY&E#!{`bsQmX_;$UW^ z^Y9cpkgm8FDu#U*A^d6&MysK)hKiaiVd4BM5-ACTJSqIaWT%8Hb>uh>kA>jm;N4yO zcN-;fa*Fmvf9_s1C}_weD~mG{gz<=BIpV(Y16u@3zx8rJ2R*6m)_+n%++tF%y8eUL zJ1%|~xjm@@wUH%amO;npHYS>w$&i@v(cIwU!UI-x;zpTrU2bxVt2K3+?YMeC7^0M+ zXy!@#MrGfO=K**1mN$PVI_RyG*)qX*E3!M}AIE?GY1NrSf+}>j;%ijeyR>Go^td(x zINK+Z4*@R~>9)XDHfCrXIJQC&XtvcKDd%SbAj>zk(CdZ*AZR5aB{xmR z>~}22O@-pbEzlCNWT2zEW+zqvR~nB_m03ioClE|e8=)3Z{z_9klUOUm%|Ipud)Zxl zV|)EJ132iSsy?}UuZqP!d08DUZIrBow=6A;p}G|Uw4bhdgm-l?=XoLLZ*GE53jS8n z$KJ!(%=ab`FNgxa8_4XxF<{1l!onXu3aHh2h%Zsr(Xr;Z&MDu7Ao=ajp{)&?Ic6W( zTQg|>_H54g_+!|FZ!_L;eAMNF%I56Ad*EB4*FOHrbhbTS`!dYNs?}+mN~fMRR`LT5 z;hG8?G(j_BHjUo~m*#FR14HD|f3{X;7@-n0QfIm{WS^D-;ua3xJqJ0m-FY5G_^ z5MwdhL(Sa7}M1_^xU^{_5Nm!jG*e@M* zd@i&J7w`bjRCMPxDd9l(Ri4sn^u>}NTy_@a<8oOn5opCT)8Lpwm_4{#0Ch3n*HHD|hZ|8Lx^@;ngKJ#f)G|wd zD=*Ut{`ocJoT>u*^~Vof&0R<>`dM)L)D^Il-znm|Dm3z`q>xQhG^yf|2;>9d+5wVhc~0pggdJT#o?#p0;poVK(#NQ_nq~J zH@^7cFI(8H`ExM%s?A?kx60{fv3!@)Pt)WeLU1h3>rmJ>`|obBZB0<`pTJXPtS|k? z)!>jnw=F<dr z3=@HZR{5HNk|Q;Wme_0)bUCZ|7~&GKU^Tu3ZjH*H%;o7a;B^C(es7QtB7v z)F*V6@QzVf8DG=}&x3SDTb^8^{Fc9rR-54jz_H^`0KS%Abvb1>42|(>Y3_2Q_vt%_?%e+!@Ys(I; z94H>A4yCS4tJh~7uM~}lXinJBIn|nc)#;+4u^rNkA+gb7vy)7pM^F!2rkM?kH7mzf zUatGL+&Fc&y_Hb?z_*f-a<~pl?T7hdGfmz{Bp&S1Xq>MsfoFGhmNoZ03KiheE6wlwb?l|eD{4Arn_F~`Ew z_q%Y{ZEuuU`5a#UOHY_`^bFlIgk|RJ)=u4+fH7%1*6u&KV!1iOi`+fO7i2$g( zUOWGvqt7;GVGV{yr4vEu!J)`yr<>py7Y2ZDk^M(8CHVK3RSHTSXkDO`{p%AW<=2w#Y&;r?zLVRnuBL+-iRV1f*bUkAKpkq+9*oQ}9?o%Pberbus`b9ECb63Npk0*Tm)lv? zaUEjD-_UJ&&|W5FN46{rej(RdSM^|vEl#x!Tf)jXdDZOQYvi)q z@w+6|WU0CwucXy#ddfzt`t-_{iJo?7dLm}(2`H|P6MblZ_qBkn66qr+MVg)h;JY{q`;LK02~4{4qMR%4z2J%`YlWXCBWjhWhuZ?iKJ4Y%+im z_%02e7Z~KkaeclzMjp!tQTB)j%Ku)#urUAstzcMK|E~;!TI;rWTqr)k+HI!*<}L$& zQXvy94_mT4qC8F-IBuc24;W7*CfOPjZp)oKs4wG{1W1Ph{l8aqsJ->gy(!EFt_`2s zP6E=vVdYsNp&L9}}xIEG%j)U!e3e$x*;A zw-pw?1aIEQ!fPh=bB*Y)6hRt_ogTMgf0`T8+a+~sGV%^MM1cHWScIid#YBi(Rp&r@ z#_Ib8RYE5j6_KLQi57b2Tm6(WwmZlXuww_z#6izLgoabx2p+2~GRYqu3m;!MfA@>y zStJ@3tBI+m+K6;UT0ePo8MaYt@i8K|?5+=IV#vVLXrzk`p6KldJA;W7ccgTNLICE9 zHj@LG3+gM((M<=i~2HIwZluXYeY)T71v6;s$3PGbl-5=-?0exBrUxCimx%zkj(I5Bq1AO zTaD4XA|Zb&K(3s0iTVZNg#)*^r+8f)^tuRjsXpU*sR>hI$i59kDB+d zbJ{JkoSNCEujj)NZuvKuI)diyjC?ISkpjAp;~5PXKdSmuat22krk6J)qu53z2ZbH1Czd3D4(#V|w({K-% zy)SoqUT)5>sQX}iH?f4Wp5ddi{*F{Uj+N&2!!8;VyQ%7V2W_wO&qEu7w>q0iQMlmPh`sm2Lm_;3c2C&570E?Z{Jaaet* z_fdfX+Ckg#skIJ{PKPx=3pWj(3z*3<$@KDz@|xYA(eIM0t-1xPKk-V}=Uj>^L8}bdaa)fiK#7!@qb}ZGIRvp{%-~UrTQ-g8yga{z%hx)6Ei8;IocRn|C_4* zBKaR?_{$?4ld6l6^FL<%Ya3<|tf7%t{!igRjjAs8_SU90f3*z?JOIa} z`PVeMTpY{*VwS%`v2t-Ser022X8UVWkSRGhI2lLR z9v@YZd>X{;9E@MNzp}G^1xamaFJ)?BX6{VP#li{l#Qe$u%G4qadPpsdg>B8OO^HEf z{!3NlpE1Y4$;r;h!NJV+m6(Bzm7S4`nd=|9m_b9AnT`8Deget$7XlQF%9NFu<*(n( zzgzYH(+`K0jfEM+o}8(znX@?yF()@0J4n04|H=sMo^{p@xr6zB67(f90vwo9vIk-BCbPiBq}5(g!(C&0v+-Qo>K|EE&%G2n%XA}wE>8| zjms>4JQ4ao@9(`Y?YUld4c^mi-F&wbY||6zfH2hfNI2<&ABlFj93H0EqpD)9m!ytd zZH9jaly9MJB_npb!%wEuzrMDNF4nqO6C1IN?B_CD?Abpv9OBP*c^AY)4$EbEu2XS& zyW?LoZ2Or^q$&3o;tnrL>J;VUUSVccXqG~5Fo93j|n{NF5~=dwh)| z7Z+K>Y_AHGf5o@T-3#{Ku0Ryvn1wIkNhsh8Jl!ruQhnL)5>;c16kA^u6aezwCyw?< zarPcv^Mv=R8!T0k9sQbR0=^9YkX`nYzJ#oWJWfvrQ>?bJP(0Z#7UX<&2u(e^YUmwN zCM9=72a4F3Gg%Cb%7SM|7pZCXkcG5an*C-NN7*Bqb-6*WfODSxa;#xWyx*YBo>p7f z`Kd?@Ze)5^UaAx6{UL8%T)&723?Fh03^L#=ZxswP{t?xyRHyu&I8LHCH)gg-kPDH# z3Uo%Q5|GpsIT|{pzgy-#VX1<_g7j6945*M^)-Dyq7rEflg#CLQMevK^xUkc21K3BD zJuCB0f;I0540I(_eZ2jN<`-R6&yb8!)rslZRKBEDjI?kb&!7Xa&A1Xcb4=#Q^ZZro z*mk(k0AyHZwO9G-YGJ@XZSip*f)Nz^RU#QidPc%x4r4g!_3Z@zcZd zXK$gWC9Zssw`t+4SHM2?Z4m`B)B@4{GK>wqpXum~+&97#9<+nRZN%3{BfXb`nnAqnw6PiOgLt5tBigYJX)W+eEWTtovaVGI^ zldOFowJt**uf9f@Oiy;zF32&t=f<@o(@vr}h>X*2GBs|qW+@Gx2rj1p?lQE02;ZrW zsNoE5Br2*>%|crtiL~^oP4G5pPlSqlgH5&^Ik5vqs>}`2;Ceo5H@XLM8_sj?Kd;SX zkmY?*u3$Kw?`NNgWaashBa!}e^7$wUV?jGdCc7BMBG@~np?FQrz#@$K4#pzrmHmFv zP1!igl<7~ZT3#enQ;>C51N@sFvM*r~)z5jn{UAPZff01m?x$*zGX_)s-eJd&aE(vv z7!hb{dEOg-c<+MXf<;xKQ+jqeDo7cW&$n@DXloWrC|990eUSkoc`-S^Fi&^2!#VxC zXqPy@CE(|2$oOZBcQOm8=O40Qp$G^)Wx2}SvMj+&Dr%8nI40$*7ytG~b;do}2{rHV zrzUcCduj&xx6$YfY zbj8pmPPdwK9BtHjYsAevVC>BUlo{z%tZV{&k*8G`IH)%K@`*xX(0Ejixbw~Wj_Kwc zpCbS8jMUHcznItY*Q#1Oi{tgy9SYnr4|&B|RB#{Qx-_fDDFw&cgV<5 zgPtLt$WPWGsaAveHl<$NOl{0@UjxT0d^7P_R|F z7E*=8y(z~iN#x4DYw^*VyU5rq{E4i((3ynnq;RIcFULJ8Vh`b@ET;77b7rlOV!>AX z=T4$qE=VUgq?;G(Zuv4Vq(1R2*S-`~&cHM#9si25kQ4$T4ZPs&z~^E+i{gdk@1im5 zr?G*^Y-NORm4dhJD5lKJlWz&B7tl6Sc=Io1zo1&RL|aE6=d?VCO=Y5)-N?#wUI`CQ zF7Mh*W|%#g_!(1Y_sFk>xgkIjTTD`H8f1uB5VS;fA$ypj`m#kw~-Ehrc&Q`fsG4Xg`hpva|x_RGsL| z*95SXnAh4H%<4BaS7ra^d>4PI@{MqeS1gJr3SCq1PU_ztsza?|f>B@-HeL+yoiL|M;-vaP)!rxeTp zg9&LDx;rMiaI5)yKYt)|z4prPmkwl|(}8P1#PP4g?`5^=-qGy$F5nFdSZWHgH=B;*%#s8!&}xOe(biqDF$3e zf5O#yeG91gVG>qRCwd^62f0cTk!1S=0pe;ov{xoA_qT({pMDMZkn3IT@8#PbgI5vn z5xbrof)0-=lW{kLX5`LxG+Fo%Rs0A*R$D!P}n~chD%!~0U5uC!%R`08| z4+R+zUC?W|R5#zIz)jyFXHfm6to9$3sK8m=p#FS6TlR1GQ?j7E&1z7dzFpbGj!s0F zd)20fPt;T!-<7)-wDidaY7M!`DlH|q5#!Kiu&$2rsgfPzK%%gh?)F3W=f*1h8Mx~Q z5P(HCLc0yMKvpNZ_A7?(^UI!2hJrI}$DR@7HqKH0dma%9LZzF9%}+=-^1d1vpTMI& zCVOD;RS-#QGIwWkE$5^nXTln079*7R? zV?`3+TVCyt9VWz}56o?fKZ^Z=;3FYkB>1)J9fFLWyuhJNC&G(81pA?N8| zBj`j!JRX6dSIZtls?CQz9_`d_!_)VdUxhLI;QUJC`l6cPf}&>R5L$&3q1(NZy;AAV zw@I)c)?lXvt4P!+4tbL+-VQxB`hgz;f4Xl3=xl1D11m?J#M?0*+D$=`BvJ_VsMiz` z{g;H$>rm6M39afw#WshzH30R~$uOC{BQF7PoZIRasvW5AgualzkR4xjqJy`PW^f${ zkxxFki1a?Tdk>lEt6bL2IX6$Gl&Y8=J>l&I?VOE!Z}QC3QHVO}UMiOuBi@HhA8*&v zPW@o-{mR55dv@FIeNR;t6jVpZGq4um38QlvJT$(8|48L2=BV7_^8=qiKo;{*)u>zL zG;x_{nA$JqmBMle z@EgP1C{HL{wz2+T%P(AmPw2s0nrVk0&t3E0!vc@^#~`#QFR>9{0N<+kVxM)* zGE#xCLnF;qPNzDKeqg)E8%TbLm6x2&?ifM>K^0Q1bGqRWC8xUB7dmzko%an z-h9QDLx7bbQ>Dj&A>DNtU@w50pVZ(zF%;{Uu(#H3MkCR6DNTzaZBZ_Fa@@q(Pf+#& zf`J{4W&WvoF&O6XC-Gfrei;6IWY!A}r^n>TefXVU2xuWZplp;-KVz|1lb&6*MF_R! zX=4OjRrQ(=1B+ieU0(t2p5nxOZ+`g%ewwzHpz1x*+Hy51%GUYcF4yf6;>2A;f=z{H zpwev6RY=f~NVfyeYyMD3ux0thPPj8ju}|#`T9qF_5};ri-8lYe|JN=DJ0J{ zy4SXL9uRy*Gt-B$@Qz_7cm~I#jquhm4~dysEpbbf!bvc_|}4EPddpbv!ZuLi7`MABa2`Y}y*xt@TA;_A9cUSVJX z(rGus7^bK03jQ4a3AolJZMB=o&gQ5M`*{0mgF%-R8iQZZ17m*nO5>!4V>n4~#bT%* z${V)&lYMjgC$1yf194j{OetoN0J z;_LTcHD0NnL1vTvE~(v}%hb5Pr-P?7>7O7Ozk_X7a~5{j^_!ek7xq6wC*^NT2Q22~ zEb*3_Ne>ZbC$VXDb}BJUg0EMCPr44wz}@pb=l3a0)@_Z)ws-)Qy8Py9N+rhVWsom7 z7tywz{2YIjyAxpvAp4)Us1O>jMk+6PF}(2QMg15@xm<^{$Z4Zfo~?mhS2pDg@sUt+ zJwUlYF4Gbm2L)Yme2_SjGsHTZuSg=<+SN8A#VFsTJmueF97(X5w&X3Zqzn)cEnG}r zP&@|jQOoyTvqCR+DZn<&wa74CmPfa0y5Y5+^-YSYKL-1zXcz_xqXm}%BRQs{WA242~oyknm7X-R!cRvl2PTm#j&&8-7Og`UB{dzXEC+ktFe8PIW zvMqtd8BbK6Pn+FwxmlHSejYz459-=f@3Aib(9MMk4+p>1-NqQk2n2We3L&n~VwB^1 z0{s-jbXxNBDs7&V;y4UX)r&ALYhO2gQvB+SMQ`clYP%l4lq|2Zcc1A`shdA}v8I+= zti6Z%dAXY9whx9J8*B)E&K?Dnoa8()2 zK6*@R;0!%&9e)!f82*@dcmke03O0B1o$-1a(q3GY`>onW#fIdH)?Lh171DC5UAe&2 z5w2M68iG$Ge|6B5#)b00HQm&tAHSvIPK)g>_djpF1eVd#^DTWQz(e#21J|c`((D2LymV4s ziwdJCR;@$@$#30TrX7;!chyq~D`E?nf5%1ZbxJe_$@=uhH(-!j^~=xGqt%WdLMhH5_wYVw(QEE>$qwt0o#@P9xms(V|E} zsP57woXz}${K77n#sE2NT>-M{exyTox^BJTKA*MvWj??C`)a!mr~EMA6gbcNV~=F$ zR_rfm(6VU_N*Yv(>lwld^bOWQ?<1H^CD#YqvbK3jlkpa)kmx6TKZ7%?*_5wN zyqEIQu3J{3FDj~8nt~8vY~!Z;TY?N<{`ft=Vb)#|o?LEW0nTlQ7B4JcM?VaDRLkAn zb}ikwYffsfruHo_$B8TZB&L3KG^hg12!lVww}p?EOQB3y6O_0rZ=>tW7C zIL_FV9TYM?y(N=RgIp-gevB2;&d6)$H+tL_yz#@F@~LM{!gi`f)c3%kn)%fVCjl1) zdYgN=lwB3pgP}hI=$tE>zlU{hu9OM`(LZnY0Sks+jig}egD|CzNKf@x;cX@w%JvUj ztg{ouk+!gXJidM!Wd=4ltB6UNNeAD^1Pk;(jEWV&vOx2UrZ64g*YVg5QHa@kzTVC=lX4?rtbX=W6&TZA*4Q7GsUN^&dgxc|m z!Ct@05pcHEcsAtbq5ou+jp_Xg?V65uYU@^sboBMqXBz!BYg3_KFgzq{ieddFq2RA(T4~%DXwrQ2k`4|2=LQRRl_Q@ zN6V^CrRsC9U?YQE8`UGd6QkoNnx&U$5*75bpslz>{0``M33~%FAfj$}$$gGxo_FVc zb{e<}Jt$w%i+Vb#To24KuGXX1%c$EN*ghg|skabWGVlmTQqvRKIennKc~0Q&4fct0 z4E2S51*5SI?WLJ!0qs=ulXWgm0fUBDoc@6J?Sn*>g_C*xEACDYc=o3wtzq1sekquZ zs!duMfes?L#}ubqcScXVGZJCB=JWlZGe5s=i+4;P340(MTM{}?kcL8F-9~Nnq$Mt0-h};3T>Sdj?0@2#_QzHWD-UUA z_m>Llo3;1&2wG~ujwSd!= z1ZDrhsAtk$dvHAnaunOGIas3sEEP*#F- zRZ1|ybwYGH^qaQC7oijx`&bCmNX-Xb-`Bl9K3ae~IeDh4XYl9k0|Hx~W>;A@escN0 zR#GG0-ubVnESZ#&bdrr0a+>s>kSFJIC_U4pICz%=9-x90}ET~QwCk36b*u0@EMZ1 zlFY}7ekTe=vMJ;f71!t~zH2)X$|1PRYnXaf&<<>;7}Jq!To9IW`*I!b3YYTo4(|QH&P%!kg7N1;y_>IJYiuPk0#_7U19-hfOLLkbV4BlSLs2 z#rv#16aMplL7N9M!rnBF0EX)!xN+g|H_@k$0VTe(Wc+a-JO=*{frpBxB)(a1fG6|| z*}(1QUh|1mvEhv~U2NHlw{^iVl*;nKhmpl7Eaz#6vzXY@8O-O+K3$$IfVZ2Z~ya{83 zpp&m#-eXVb@jYPACScCf2ufaprKEc2aClUq6=jy69l6eE{0dx8nvcu|*;3%1_0J|} zfZ=D{xCovM=F?X_NTytB=o7csD_pSTqDWAjYcrxP)rHj_(x*tCOy-0xi&jC;WtAj_FoT3W*Sj$z8Ylra>yizN&%WFxp17ksy4Ewr&-W$8Dpu4Fi@(F_E% z_~(SR^cc|fOxt(5U2vt=IU4C5ZKE@Pd@AEm{Z3K;+lRpL=OTgt zme&MA%w8PuyHC2$z8$s@5S3|=dBkN8M_QybryLefx8F6d$?nxUO4oTJOzXYHt-EfET$3 zegnPpew^CUH3@qB+!WmW?Y@rFd+(#m6u{h9^P4sFoPrW;8f6-F)g2XYnr2m26`oQA zMV#a@)$a09i=?6X4U4U&qo%Z`;3ixPm-&pMX6ej0jWk!kwX-G<3*^#jIWNZQuQpz5 zvKFCFcr985JV%dyYt03{~1 z-kCFzOn4inrrtQ8-^uU?gYj6?086*yQrSaB0IfVjwhmAAU4h3edSqR$hW*Z{H?yB` z1<8HNMcf4pGM1F0^rcMi7^Y-&sh3eAD8i*{vuEAsbuB*p!(2E* z#=F`&53R`q!`MCF(dEEU_;Gh^Si+$a@>RYGMVdPIqYpg72gcpseN7k^r(^DISbVS8 zeAeni{mRF?Kl{C}>Yg)_I2xBfEx&g3khn`>Rp?1|%|P%W=pEUU9QMIr)pq`wFXqHV z{-C~3RbcEcZc@6M2_{UQ2D>yyY#-{;=3MejB%NA4LE%Q`5w!2Q^q%(cKicWU0`|Pt z?1z3AGuvb14^vPid&X5ga890&FO8nhnZKB?nV*`EnP0QGZ*tV(nN*yoVbOQ?{&C+$ z)OO$Lkn%Eksq@7r)vN31&!*V$5JBhLpNILEo+>ZzU&n*PON6@4&a<=Xl80Xid?bnl zG~SM)B}0ELUzu;4?-p{z?BO4~7fr^eNM;aNco+SSUz1dc86XN5=tKIj|8w^{F|?QG zHDtua{qc8p=!X-wS8~4{zP^up|L>U4Mx<6jyeeZD+Vvo+Kx(fF6mCpA&r}!2<-C<9DkBXVW(NQ=(GJ6i6 znx*xO*(%z+WvW{J&BfsaD}y61dY6+tV_u zjTC1+o|E|}H5$!Ua9dLN$Cv8w&$u7>yaH^#3Ae;!G|J!M5txWuGpT;Y3QeL-Fyb*@76Kw2MuXjIb(Dz0~S_3s|vGQMm? zUIB%xS~O|ave5`tn9)4T(C%HGgN4-~eiGNP(&??VoR8E~^ zJJ~&9y@z#ae=h0}0hHIM_S?xL8xVuz8S9K@=Y6VIKYJ2i*m4Z$rnzc5I zY*VO4&=wg^H15Tl#WqW9HQmaX%9$!Zl-(*i7c>_%7nc{77r7QTPYCbj?-^WbpIe?| zIuti+36+4!Ok=5gDywQzhH#qX;u`4U>g?j0_z|iO<(K7`l|*GQi=rozC&MRHC#5Hb z_hHZJo@)Fhgqnhyy-K}mie(1n29>}vsztj+)f0<*-g~cm7}qeL0fFzib&9Konn?$X zq|MaT5t!BLixn1&&DabYk;`A2#2BP+EqocYWgXNV#5*fG5SCdcN~Zw^Z9UG}_C6rD zgZt>yq8F@3kH^{z;6`ufhrNNlfwO^QYKJ_sM_Q;=xeg+OyzH{2WpmS-4grIxw3E7% z`Z8RzSMy8L@!H!Of=vmhY-aW3Y(!K08lO#1i;$O)ZW(_We-VEbe*wQt=uuirn7|U@ zJf@Xw-YjA0cP|m$8vgR?84b(IrqZU;W3=ZaqsA8H;J&8RXkMf`08e!!*Qal=uwk|AuFOs|&AzTUF>RiEbO?exM zsmooNKEvmo_BHLT2d)y)2LZletx{-=o%G3&O?^H5lG@&+m^Vv%Xo1>Ncao! zVn3cQLi6`*l|b!SWj%BiN$r%eJALf#HD3VL4f#b-GZ%7;44l;fs|T&sgw+*$&Xm=S zP8VlwKU);OCYq+|vf(o7vRMt0o|&E*K=8!N9iSh(e2C~Sx)o-2Gt>oZHQII>na_)lRNB99Pv;=hm5@hHD;+WY+d=FrLa637-Kb1N!bzC37UQ(GyjHly^t`+W zMqJ$Zxs`7`Yy--Q0@e?@(#HrRU(5gfw0rSPWl%VOG9yxM=2 z9+I^BdM-6jHE-Q# z&8sGoFb+8ZMZ?lQ$vS| zpUEbUQ%1MQW^R0rZVqowcTRw;-~1apX9iyNllC$Hao%0{UHV=7UGiP^UAMEubNt7M z-;Us|(<_#5&c~Rastz?nvPR7zfT@kMjj@ffgRxx(P?8zt`s(%$)BBU@Mz$*{^NY0H zP6GL;egb-Nii)O1b(8WME%@HFN<%V!apRo&F|3t!9;?<3%`y#H((KsRedvA4ea!L_ z$56*um9mY}joJyd@5Z4VirRVfYJ@6;%9u2f$;D%=G@{x_vKJPn)i+sRf;n2%S8L9c zTxn|!nI2jkg*+51O1<;Ei|{pKXbfbclkAe_$8h$|_BHndjVcl<${81x$QEfWU5=Y@ zD=8}k7HcUhX)F;r0M*4y%BL0gi$7FUIaF;5T9kClZ5I7AioeTttSL__^Ok2XGFoaj zXRZOx^B>f_%DWc@EDf4-*9-{qkknwx+bwf=R_H31J2*QyL!QXEDN^^4t|bWy4l1Ee zuwAOGA~QSHwfs;osNFc+vUo?ccNE-~9hV)JUAUaN99r#L9bh(AFQzUoF19Y-FZ3Q! z+r!Y%BYj&u42t|>~nEE9l zJ8pWscdU1`cie9TE9x}LP@;!r1KTjlS;IxcNyBaEt8uo&l)G6V+id#Y9rxRmiCF~O zqIQ4!ft=ft^OEC|>ypE{8-acIsps^4&ne_`XiZSvfS{w#*>iC29`Hu>wdoXbO=_@9 z$|r~;pP?yP-`HT5a!szb({Rb}2i9JH(%w@1YHV5Hl0X%w1U=>!HrBMOhS9tq*=XJNUvA7eaU3_F@kGwpSHReUD2>5@lHR`Seosm2+ zcP7iM02o85W)t_WJzjH66eFk>Rr?bUq#qaV7H$?EoLS(al!wd}H5IuO-4qEFf0Wjg z<~Ve-3}IVEu?^v&MTHL`<~-*>=YTvDa|CjFa(r{%bHH=t6pg2a6p71ZrC?DjhW>w4<|UOlFEeb=|)=K1FFdpKY}aL?|# z`_<+h2{`oVTR+F|bjpr(zQt zs0`yGmAt4x&g0@cjc1`$1l615-!n{`Nf$E6=E2L!TuGZVaF^6CNpCaEs!8QzlQSHN zNuy)YD)QwiYPuDW*-oX7sg7KCllbNY4mE68I_4QkB#R*z9!eEdi>bI$h{X~rB@0@X z5CBJoCvk4%?wjnJ?iBUh+8(FNa>4wwc4l^@zg_$~> zbeNf`!_3S{2RqE%Va5(KGcz-DGSz3!x#!N@8R?Gnq^Gi~>}`8{Eqke?@^*cH34l#e z);tfMT*9UV5MU}5s9FZCGpA{jubV%oYKa?*6^j!YH5k=DfMQg7-CQ%~)}wCAYf-_Z zic=m{990}W|6Qr{*Ik{H+zFX;a_cvpLfb5%0h@vI8J(GR@t@nS=d3@YEyQ!}tL(Fx z*PAy}4aV3^vFrLLCv`uTjZ)Qfty1?t`_8>J6xr9eom%*iLpWH3VrxL)URxr+#+gmR?f7*ROh@2NGr1M;bEy#>P@8*C;g<4tQGtLLt3 z?u+Y>GPLcFoyU)psa#eM8F?+Y2aIm|+kr@YZ$tT!1X}IJ)byT)&k3}ul^!R@^OF@C zuV=0IGmev8)x^y;ZnFpUT6%QLjoyROjGtzQm1;)~ixUVC-2Ag0CV zt^`@c5gGw+s!MJ1!QaKE%3`)vWfWsP9bl2MTw)OTa(`kvSE^HP>Y*7umuTF@NX<;l z&j2X$XegUj$s_3y4;nmo;C7N#F%D-fTV-aa+$5BlL>f6R&E#1`{g~VSf~CtqByc35 zFp*>t@Zm-K>vJR#v;a?s*n}vNMIrg8`@2nvY)9)yOzFo~=b5rE4DK2w=Ed`Jsr$#) zV{%*QzOH!--w#Sk(!egGu~ci{xcyfiC`Vgtr8#B++Jcon-*I_Rp6nt5@#R_JKhfkIPP_<sa)T+?J1MXIJ!b+UuFHH+WYe%kC@U79k6_tP)Zd z@Ox9}@=be^gIdgB3Fo0q6@Gv&%?TFk0%N# z)~vBg+7iBspKEh_`fX2h?c2*RxcQ|em*?q*;2%r0Mkn*@N73-iE=EBHJZo7uF^VSk z$)i#X+UqaL_Q~NGg)aVr5bvb#=90EFFLT1Y;te@@@$_-+b&^g2k*f_N<)&rN{IQ-5KWCCPUnzG@_;)GdC@lX zzOx?AcGTOYr3oEAU#nw10-JhoHQ7O46B7DCCh1|OzPJShdpn5u2txD@)~-inEPb={=MxUJLB|H zJ<;yAQR|b|EB6V*#J-VMy-=hQZPEraHl;%S%YIyKUrz#Xx8CBZSW{R>A@4X&iZ#>n{eR1)5h=5tvr%Lbo;Lj z3c)(oVBy6dEyEv(LO6cEeuemwA5>z1xnFmKs4obS`Mm`PSYM*U?Ao{zd;~cyl&6D> zsVOHWoJ>-WFyiPMV#IvA_f(2(yjFWI7fS$&7eE&Gt?_g4r?N64wd3?^&X=dt7)C_E z0)8fjSb|;S{@OR+FtF9FRuk8?{2?lC>0o(5b!TEk>p=N9c?p79ToGMr?UEf03TWHh zTC>q5`8@k*>0h#U9hw|jRR_0kS$$KdsZd}L7R$MM3Jz^$t}epzbcpBo(ef*qib(nm zGAd9T6pvmM+KUxUx1GymSCZ#co(E#zHBV~3W3eaG3uKp&TxV#9#C4B{Dq$%rLJo!gZkr?U7B(XFz3>RTy{ON(% z`il^lSV5gwd!2T@o-usw+*bA6>QAxD0B|Kcd2xNqDI}X{QQT4`VO_;|!ffRqCVPL@ zrj$f$T4AWD8Pz#SG64LbEcVN%;;Pb>0P-*R-&I#Lw^wY1ZF&^ZDj7I$7_CH31J5+C z>pwKcH|F-(KN1t+KCEhseozLE?L6VVHC$#!-z+=>|shF zTCy~pif^#?=8ffv=_v7F5Cwx^tQTQb82bukeM_RDi2nN4CEGVbjsh31;uhcJyfkR7 zXa0f#S=BYeQ#6)N3W7`i+vl5X4&y?iEMiO~lHAZJl{Aa?UCS58wxrap-xXt-5H~ev zPOum;crg@)9mgyz=%6~tTa)<6J2~nlkwN=x4xF_x46E#rc0dLZd5uny1Q__6Bbp;h)IcQTfJgi@nFC^i}smvmez>_evDP?&F}{ z5bSiC=SM9lcC8WhW1<%dhfMX=tr^@`#W6Ocv*t#h&ofMUkPQ_E8kaXQM@^La7?JCfpJA~caeHW*yu}!kXM(*C&CQG|Viosvdfx#ci2B`B^BMKPP+IwPg(gKt2w-$BK`_rWWS>?enO{jH*!6rQF9qO3 zH!HVsl1?`vXyx?nEOZJ26>F%=EQ_W)v-Uz^ZT0!y-Q>UkAUvSILL?=>JnnEIP(c8T z{;r@&U*wTbp(#M+!3M>m5~;}1UcEOS*bCM7qQx-bOSv;aWdwzJ%JUaa=HRfPctLn! zN>sU#SzuD3&LAc1!?4f@DT{c=zyG=5B0p5;61mUV_YBQWR=c zbB&|Zf&xy>g3ZTUiE)yWHK*-LS_H4qT8qbPT)61uUT&4ZPb0zgufdB}*w zY|7%Zp7-P=DeN%@O8mSI7{bv#Nmy5TT81YT(4L==-d+{pKYf%$jSmve+in=m!K+c@ zs-NG%w6-QKa0D3KV$689B=sqOfN+ABEKv~-x;$e6#wCWgvK7H|@R{J12nrtc4#>+^V7H0FD>pNEwt zYxHa~esloHXz)o9!dHk36|^kr3ek$$1D^WPny^o4xAkmq%$`*1?S=#jh=^>{y~5If z8)j3uL(ml9G}@tC+@isMg!Li6LJ*m_d4LLR!nK3r<%I}>93dRNts5#U^&p`Yn?0|n z?Y=$}lp)4k?%HYI;did)+1+x`yx5D6T}Rke1ONovd-Rr-Nk_~Y zWA}i+1PQYc{9FVX^|7u%a&9tt3!DF71`E4P>1M{&rgkHvqBVk9{J zUFi=OOZhHebSwChM}8F{@e&Zag%W%Bde}`)aO}DUm*Q3+-werc{f!X|8kk2SfC9ch zo*-cokb6BxvRl5SJ>pEhog?_rHaq<@4Zo>g=Wd!zHx5Rg&VddlL$O#cUZeLkx`(4b zm;{%rZ&RtdAFV^(HtET>eO;9)RL%-0c{}UmMvE&upWI_~zeqjB5pE7`PY#uLr-d_OTQAA%K+nvxoZ9L?~;?yI@iv&`%4@VR) zK%U46keo`CbzTX6yVo+2>$!7Bz}D+!Y8M{_!3Mv>={sUayTO5Fy0V6b2X_HA13^`Y z=Y~Y^{o{e-1^`(B?e(+xgDu#Q<_NXLHf*~CRc??sjc^w72xk0&!%zK0cDpB-$I+d> zeNM+0_a};Mfp%DCXS`IC{j4sJg@*%`CcPh$59^1?c{DGauL;KOAIohgdMKZ}8;7?kj$fPBu5N;{s&uPu!)KJuK~ zuYla3UUwFQ&`VO^@UaMQXyjU-^2^>JuFfW$#G^0n)EzTX0yNoyURRnTonDJzw@MSD8-wV zR}rVhAv-Jx8Cg-PClyf;8`o7G`+<&2FQp3V*u*E7-_N93{L<8+*SNI^*KEi5Epe>N zC+vDEr?aS{v(O^v;S}!98%NAgE>^xnlX4%a9c4UvzQ1Gf-cEGDKFj4?sE=NXd%3_E z=?r&)Be^dA6nOYrn9M{8@R72_=pB(-e=&p9GIpY!9_#Erz+Ml~ytH!UU}+>m$`#_r z)k^tjAs<5%V%_OS9t9ZEISjnH30aM&W~WFn&)ZsH&N7tQ7>{P0b-C@WPDYLTGOIPC z)&)ei-jCATw%Y0#s_HV$I;2yqtp^}Q=BL`6QMxo5Jpdl^iQHRO3mVUgW4y(h=Kws6 zRa!8(=7ppJugJ$l+ya`%P8BmG_|NwR3ay2?P8LJ4PV5ju+@XOp6;2k2p-FP4BLB{@@VmLdI+0^g=(5*aQ&iGU6W?+H&kmYa>;LkKMNpeVIuP( zXeGfS>wdzwXB7Bn8p~P8@LL%@}aRvtao+-z=$!f^RH!-WVd@!J-vt z*rg&8;CxJGX6_+*w8Q&lmTgyf7>mUvuCP?#UYcJUNUBu#j;n?A9C<`c(&}vaAdWLr z<9jhc?60`o{~P=_PZ8qe#OhqBYr=ur9D8v^B}K<)UiC&^HAP;f-1sL+YfIP#*@-2? z-*kd@WIQjHT=F=vUZSL`8%j*v8s3)ib=7O>T4TOFVO5i5jhpKr>*<_HXW=I;DdUmc zIIITT2t21h)@K(svyHgD7(D6%gSrPNjqwm!!oMZbZ>V_AvkP8y} zw8&JFCNN^^xX1@TmS8@4KR8zF15+V`y#^^Tz8NZ6NM)hPoGfIEklr;R1vmCqqgeGP z@;d#19o1LrFhXdj_v?dZ8Dw~q!*D$F^$@Z4XT#m<fs1^4R^e_(v!1t9!Z(x_O2GVHWUUbCbKN9kp#IK z>eSGr#)$X*5<*X;bPH=T2w{uy zLh-by{4`%1 z!>}a|OnqOONUN3O)xb7o6(h=^jN6$v__{DExyI=8K@1AT}%HS;I3z+q3 zl&0x$va{epQA0K=0W^q?k-Z?D=elapcm~UVUy~|AQMh0dC@{Aa1)o}BA9`kgP1+>A zi2ByHkH;EG@+SovvgsJ%C8Hns5C#)>$m&+otHlZRxTFS|ACe8@O*d*LRv4?vfkS|Z zkGv{{u_U~3aQsWuH*P*T`6=45z^s>LG#5gizRo@TC#Db1Phk&HA5|Yc+!$Rw2~-RI z-^F?wXja`X)mF<`E|}^41jf=!{0|H~!>hL+Uc3UN(ebv4y2*7{$CUE%#k8zREhob> zYcq?|o3!uqV{B&M35R++%-{3t@%UE7p^s3#Vx}==3>Yx{W1ANNe(T|reAfJ0ChN7U zQJNbjdewF{)$ctFKj>Dq_pf(c5cx~rD6oFVUYWf4-FIH`e6%U+NOhYwmClKeBv9n4 z)D;9jS;zCI?Cycr!tk5XL?%)uHH>)dtL#^tEL;S3UrqEEGt9R*)h9}sr7+OYGpt+t z$f+=gs0UVuS_Lj34VvK%cp{V8f_nqy!*uYNi|7F z7UbN;0G|^CJL$HD#ZvQ_WM_~Rk77Gex~F>8wQGNfe~4q}wg2`idk!cWpN2d6$ z^}A_70=JAW$7Y^??zUgcW<{7WxeI0_M*2|-zmUG(k0aTrhIR$Xoj@G&I})PgzSXj| z569}56;)H|Z+EMOgo%;kt$W)KGJ#1gX+Cw1h1h{>@!Xj?b9el2xX^Dj=kV}sqK^}{{ zaM*0)hi72kxyS8hS>xXc`z8$b>xRs{a7- z6*?i#R(YvqP6c(Hm1&)BPq9^V*neEUC#&&Kq#z7+X_FpFOb{v-Du?%%Ta8%m!1u`M zm;)zfj?1`+iv*qeDt)a1&qpj0Fkl#i6o9cRpFaQ59#pADf>n+73rvSy*)hsyS+!xFMNP!}AW|*w*&57m13?lux%$VEg?kk9H7qP0onf z2{s#Z%cA@&hvb>`MB;qR{Q!7$kluWWoDFQ@66Wp(dTvT%MJ!s{^CsFfh7J3jPuzQq zy(pH;B8to3V_LdiQ^~wJ*`FD)_HlZX#{%urN-jw}DF%{|00a|kYhip!z;O?E|M=#T z4aw05`EDF`EZsSk%kU!flj4nWyX~tRw;LAOj3qMH1}&d zv!7~$Z=BrJPjO@)m#gC$nF^r;!I7?S(g>Cp2Fs zhK7JUyzcd!t>lc%u~2W*^n?jmDOrhtZ`!TF>h(`Z;n*|Wg$aG~wI~l~7$okq_$BSp zk86(`mx^|6fV#vNY>~@{&W#dc+_ZS)E*N@awAo6XUU7F74Wof99rZNaa<4}Twi5yI zK1Qmxp<$o^WO{~eQ(F)u0I8t57kk?wShxqV_~JT9SU5)TMv!_d+?qu}zeT16V_aM8s}nG!j$fG<=Z_NuDMi$1dy7 z`g9gbsnB(hIk6)4ISYxFH~>nT_`8Kl!fd)oP8z$_3K<`}*t{jcYJsy(bKd+5&d2ad z|3SOQijwqXg^t6a_vlh1O;^Wb_w$66t`0ld@$=zo6L!mK)?yb9-^aFzmz|1BxW-_eGrBpwx%~S|O!x7`=ZG#4-OoCn;GOo;qatiVx z$p+NKl`Q309*She#7$a?Ts>*b?<7BqIfj-fKf;m38mt#5;P3+{yt-D~c*+VN@1tZu zi3t(V<=N#WCS_vRm>m@M=&!$TTB5e^=E0S%pSAFL6ctl>$h}#{-ftF;;)r<5d}RO-hI?VQC4&!(ul{_5GRsYShPj zgK4Q|JTqeQHx(7Y30bC2P_3s=OrJV3M!X%vo%SbIWAxV$R-acuD&JN5!5zPm`I!3{ ztfM@{(Q9LGYVAPMllGlz4@|`+dLv=;5Eo59>PjyN=c!WY_DAUToCRU+!#MZZq6v#e z4VT)+ZU>!N|I){TX)tNl%}`iH#YIg}nEzPIq^s> zj?OGeClI($8HD1vaP}a2;={2KVkMmt?CPHQEW9Uc9WyvT@{&j^DroGflFQn+k|C7m z4%Vst%qN#j=IvW2&`5B(!Y}C6RY(5ula3VT+n<{42cGODjk9+Y4^Phy!x1@# z5CDhlm|T4T8jJBw(k2g`f@2;7M|(^$g|ZdKp7GH!JaUW#36HWdg4au06eis)e8W|J zr9$N*LmhR+t?NNE63;sJ)`mn2*4=8^LG>LTJ8hf^p3ZYYzS%=xQ?#Lv``X~od~;#q z_o_lNN{YrB9}x6_FgAa4*FWN^`zUY{(*pR>W`(M{FLL6 z=wX;%rpUv037-HU&oF&8yUw{KaZ~*XIuFuA^$4kU@9KOXTr;dYd-3@A2pLd2Hv_H~ zH|qvY8~{tvC_v}t7S|npJ1G+1i}P5?)Nt(b!dq`^@E(5u=<1VyJ7`l?|K8Z-Y+@#V z_2S$)p`x=rF_8_qss_!Y2E7WdaER!XcLLsB1(hDq{Q$00%d~s!(&dF{Ma0$%j&H6o zI30)G%ID-dMA*86vmnA=0d4D+n^i>66mq}T+cP=BA$5M^{io$o`Kq+gayeu`b3tJ| zMo`?KiVQwRu#gL^|MOnH0nyejr2c0+!tLEi<~UE4JJd@->uj*olx#V}f z9M&(72)>wAKXi1?z16qnaJ~H>n4Bh*#M?G)QbnHNo@csWi<;VnWKY+Y8m6J0WluEM zYr$w%_8fKe*!W#uu6c?t@HpMoX6+^fGCOxS2#0=8n0-FX-rh)vQ1ait^&(|RZPpeY zSHEqGLCl5^L-p6J=J~7WDdnrKg}1w`1Y9qc?LN7F|DI|4*gZ)@JjPT- zxF9Ol0&RA0+Y$CzYGpjj1H*ACJ;HNce}aG(FYp6V@gvBX8ln)^>veS2?GSMt)gPzf zaoFc^>b}jSnXv4@RZ_02{Zeo%`67Sa^znTC<04KUgsr3k3dyxfNO9e2>fnM^c9Fm3 zT}%qlnr8IV{q|gTgR|5COuu1|I})>cR%_X`@j5D9hYG~=(CJdCcCDR;NstTu%U$J$ zC|3jb)T#`9T~kYzQky$qn10cwpC5*U;Vj0W-N$Bw%sJ>mzbaA9(_#E^lG2kTe7Sde z*h}ed`Pb~>p|AU(6{fE5)vT|_+x)HPjB8;<72jJf69360RO~t4=5v<7XXVug+^5@d zUpiqt(lBAN{Kr+gfXC@PX{=oK^9^Q}8yEr2BZs$qPqEaK-YoaaqJZ}u<5g82@{H{F zueMbg50W)S>j4j*Zh!KNb^~-l-&|o@#lEL^k{zj96r-WtNgW4G&ZB>+yvoe^EW)Qj zbXp@d*RVtspgN)`C4Z~V@t!HVk`#L7;~oF5^>q0623;6Vk@d81owT0`#ggjKeM&xjXWE@~Q zq!|rabcKcj-(!f2wF=Z5;nUC~FB$qvz~$1CfrsYR4e5m7z)J5G^|Sc8=a$FtM6#pz%601UU}hC1U}*^M7K7b#+r#%rDYI;a zN@Ay``@hE+&wdNELuiieEtbkqNH1W<+BZ;5I541)of*wpoKJu_h9hc&b-)^87b;>v z_hSIj@npcV#D5#@rl!{5>5K%1ZyXmoqhMoBS6ma9}xS3U=E z9_@wNOL|5GK_(#fa3aximVZTw=6B#Kx=M^srm4Uf(!)a+df+{4FfW4DrXe2G--wm~ zvle!8T2Z60wkvwau{WQ=I}$BWc`@!GNlBS*M_>)pE5zt-1#0a2p>v8L=S ztvE`zt<_%k){$D570JAl3BAGc6tt`vM5rTb3+-+NcEbG}mzRVxmU9U(*@8H(H5a2? zt-I2QW%8(xWx&2DHc*H;<`iIrB;hBA` z&>YAW5G)=qEqw^krf=N1y*MZqqg)&3;22D~`7`fRqr>6p0K&K3$yqST$A>W=2022A zsz9Tpqs(wjJ;_%{T<+%0+E4iyF{^Gto41kIV9Tb%H59J$?!Yzj`dve`h+&4yJ+eOs6M!Lnh;9K!B5u;8bZXLI9ykeND7=gBS6J~Z0=!xFZp^wEEAGR{F5~Jj@ zI&no6eMICmP()XoZ$rGTC79Nz#Z9{OXE=tH?4OcN9X%HVFBrq$T3MD}Gy#NxTm+OH zR&1^4Sb4Myb*~QitK%cmt~OC?qUU={Ssy*S<8^|lt)^5dqa+u|H_IsNiHigk@UYvH zyJrW?ljRX5TiW0cpc{On4Kj)aFTYLf`8;tA6-B-gZ^}+PuD#^W$e>qmn-y$8Vmq^o z?2Y+Z?G_r*8W37FHwo4^xift)9mPU$J}@L?B#kYrl6%#@C@j}9R&;i((QC(5+`XSW zZL(5(m(vhnzn9w^U=qIHAfxYJQNK0*vOrHjj9W0zL)XMD-)Nqvq+(Tbw}3*>ON?xv zE*Gv?*Uh&W-Qu)g;=#lFIJ0Vj)7orGnYQ$8B z&RJ{dO)F*@@iK*VCHp;gmxbl(SHLyfd^2+RG?qlDp8#a-4?FGFXs13Q&16niGEY3y zge!bZuVy1GQwoEqJ1P~SN=C@GCssw_J5gH;!~>1-Uh#62g6RfpJaOze0SeW8A|9ce zDW5q3VW%?F!?0>LDXd)ML@sy?a*Lq4geyK!FO3;O^6Zud>Kg-yg%(EpS`c<5SUoPn z9Y^&F{ivx?DT2hy^gL zGV^4jP}LH7Cl*+YgKAT>E=?&H;~&&}?hULv8k;r7863r%(OkX1i@q3Yf4!$N2yij6 zN@FC)o;Z+f^gOKOqf?t%YSsW`21g8p$d(&wM&zgO3t_OsCr_J6#f-D0{ni*{caDPu zGt%6cInZd$OLAY?7;W-EnTbkWYM>99 z16?U*eeLh{F>6_)6>VK56E|m=uCC)`rfRh4BGB@YrpwsIv!+So z)NmEB{5)X{a;$^KkkU$c^gYV!l^{FFMTsh^HBRdEAdyg;5#uyz?8Q8YVWW&+YZ-hH z=>)OpQmFDmzWAViushNum#V_a1sQDo+4yo{kM3u5OMW$Gw9HF2KMI*&X85yZA>G8t zAK_@#4Ug}PXxm}orkXS>*_6~a%uNT>wraTb*H^45p~(Dk12;PS`mzJBWhV3nWWHb# z$YZFB)Erp;ayiHu)%hveJ!%W_LS#iwseQ=q7*J4uKY7W?Q~g_gB0sM0YzVytXkQg1 z)OBmRRqM2+Z8*MwlMj}j5#r2@1m3<>=uRu^V6*-HMU004dZ=jsrBTR@n%u!rU6|S5M5tDy+&2h8eCWt>&n<*V+oFZw3 zc{g?N8FeC>6_l5F6ew*Nm9?2Eft(q(kYY(~v%AZ_ZjMldP5KW9CIRI-h0MS(s&}kQ*3t!Tu_6BAWxS;TUnbUBL&ydokrJ07Jl&S~y+occn)oCP8RQElJvLJ`H zh+1-TVM`Z?FAFWDNQsb2{gH&oZDA7$7FH(75;NGn9=pPV&xb}G7PaN>5l3l38^Ht3 zRRkc9@1gW244a3@%9v8jEOVB``Y$Pyu>S<5zrJ>(;rOCy5Yvy;>t`~UH%wLLv|)wE zaY(@EIJ3qEP8<7nrpbmzc1#&>^+77RDEL^Y@2ZniF!n%rz3>7ipevVl36AIv9-}`^S)&DmY2wB(w{~1NCqcCdOPxN*D6}_%qM>}f67FLL= z39a@hu;?8mKS4WJk=Zo9t16Z)7_kIzf@>lpck!aMjsnaZN$wuYfK3%zdkqJz$1kBK z$bL$^A3sTJdtQG!*@3d zAS@CD5^eNyEcT+tMLK23%lAX`sx39r5yWPPP{}9(fmC<+9SSD=QzejgjR+Aq#GGK50_+)*(jJ5`j3F8kdgx z=51i7#`x09W&ai&rNdY9zfRsic=i8J%y=aeGdmL%$^SMpp5?Ea!2imOXZaUI|DOc) ze>C|&81a`!{%?*t5z9Y${Qu_H|A#IAe=_3%KrZ`Vw)$T`fv9*6Rt7E>b|7kvK}^I!A;{t>4CC7S;o z$NyOm;6DQRf7b(GW&#?*%*4zNr2qfz`d1@>g`J6kivwuWzXSn*_WvdS|8If-OiT=a zqXH-r@qZTtVCMj?9Wc6>iRjsYG6R33;jiieFb@9_hRiHnoD8h2eyQS?&kF%(8xE@)?Tm<%W|fB^mU-B6=Qp zy#ewD2`FcjLhd|D>~{Af&5#qyzG@T_p0InU*VKa@hN&a-qT}(_%QIT|23Lh0;89wt zvE1e&=L_&^KA;vX4tO)M*4b70RXueKd16zAuSUViM!JZ*@hFskZZW@G;_-0*JW3T# zRLA(U^jKwIwEVu9&UQi~ev_eNYJvx$}SW+&l&~5M3-%7G z6^u{J=bDbN*HDZrUy5H2Lgj%F zW~AbM7jsW)%VPB{dsdTCTxy+VFy$gA3zT`M9#*P!9Z^rlkkgUHj3132KWoL>QG~g( zP@fCD-8vafq_n88EpGQFhX)@Ok=+r{6Jq1#b$8}AGc)tqa}X3iDf8ClR;O*J56si? zJ|N|NK|=>en!tGr{kyXLd;ffBZ`^=;?FY*!i>aD3y_nH5Dcpr-2-EJV%n2PwJmh3I zK&Wa-`^hO6seTtpBQBodl9xD~COg|9%|qz`t!$%56M@e>BpS&!wml&fT#6N53AL zhE5z|h3P9+4}Y=$pRbC^wP{drEs>pO9gYvVYd$mZCk#38BAZ}&?=iYQau#m<Ky!14mW34cyi5tHwp23nG->)OBRI? zMyV!jbr6NY7#gP0!1SP~X1W&OZge`GO00Ftd)lQqbE;fB;(GA)duwl?dDj$kN<>X4 zU;o{U z(`L7*#LvF;inCa)-JF-ae$Ju&}tzINg;n-6dZlV(woL za`TpvmCRpE4fe$jVmzrAzjlN&kScoQ8L@RDsh@ku4ys?o4ADTQQp|TL2lGcZxCg{z zY25yL50H4evjkYeghu8{dFE-^Al~$H7-yV(Q(h7?NY8uepU6jSdY@<>cyc-|p>ZNh z6A&2pCNPp4(p&nv58^yGlN)AOk^+B&plu$aUXOr`O9ImTa6`_mL zYP-YI^a*u?x?NHS??aRZc_WpF@{79&Qr@j!9O`0sAP+PZXxV90@A#KU`=8&Eg7EOt zkyfh~3V!t*gw>q(3Hjo!YltQkqQtH1kI{Bm6n+nB=8e=0cQXOMcbF;5W3&x&)SpzP zVIQUyko>Kq)heSapP6a48mC6CSrU_{xb=!j$*>o-?ic20Jxp@M<)q&7rNb781Zz?os1dOS0Vi@Fl_z9DDrJ{ZHRM;!hU*SFi-x*NtBMueVD7bX6a!(^ktOmQkX(?|T4UfZ z?Df*b0%t}hO9M56R$KfADUO3fKgI<5i4q>Ci&U_X(k%$i?kp|PbpjZtkcQ%rlteHC z{TGAqp)KJ~HmW|#-QqtHJw0#{vY!v{fQSII*c%1HlE=##<`4`a0#+do*e;4L*5U(0(vM zI0`|K;0^5ytW?2~IKJV}WrpH)xs7(se&!Iyx8Qv=T-kpbZj8vM1Wbf)^t#{&c{Ta# zg1ysm+wB9Ne?3?Sg;cfNg-FN3w2{9Zy|H~}JlZ*K;XCG?((cc!ddKlt%rU&-j_=mJ zp}#kAaV$1EZFq)GWSo(Z{R?cU$e)jCpq9 z2YPhm`iCNDS8x)v4Z@hc9ejye53&Piqc9Q4PR%lB<7P`@t7?Hqm@y=0gSf<%`b5Jc zlKb{f0HkwB&RNb4^9oR{Gq(R3)?Z@AJTfW%ylk!qSV@U~5W8rS*w3PsP-8GRLl|5P zyE$7Rq<{218pQv@!{EJIxcb?kSC(hf^g=H1&Un6&RlNRu{P5Z5*>ZKi*6<@N6Jo>3 z0#*UvORfd{w#UkkZ_5{Gcmd3uD$9T34PG0yvmnyw&tcE!fVP38S3^h zd5E5jbbC)grF5~{W}4~fa+#Z9y1QRO!$;0hW+8Dvc|+DmtQJkgJF%=EisF|GvaY?1 zNUTt~p&hrlq1&&A+rEU^W%l?eZ+7^)AK`(?<0;p{Ea24Bnx8kv$}6@K!IkUrBpCD^`_9#_Grp0=aeI(*zh+n6 z43w|tAS@-FBqPE>$s)-5J8KJkKP_MPAeSb%fLnBi?0i2#xIfn_mE7w6Nwt+;@8Wv& z3%1wh^VPBIPptBI=M2g7oI~F*cK|oz$Kf*!zg&G3mGeT7w0*YSZ`{n&%hbSly)5(( zxhDg6_Za@-aP~1Y*LT1!#-t)Fp~>($zm*&J2o9JB`rRG=J$+tb>L|LaoSu_Jx>H0_ zs6hwvy+w?_ZNH`w27Ba#gss-+cvslOV2^I9jGAfn4kA!&c5>2j4`ms3EQG)Xz4fS1 z>;ZkX8%Z{4_0OjzxDMJ&YWTxEqWs9X5|YIg+@4x4YP>i1;Adh)91MOY<9NR6_xG#G zTC@+1iq)jv`1c{I#O-ZJ_1&=NzF$gDVERZ3W6Sw>2SSa3&g!2Py(=zUPv|94_X`bI zv)`@V!sjS5=-ClDLKqfZ?w&=C&TX$aN0vA5TKPlOE`mNVxOE_EMZ3Tc3$jZ&b3pcn zwoq1_;d$=|+$s()%CnF#yWN!b{MtfK`176pV(1_cNj9;il9774mL-QRapr?2==;=1 zk{Oj$^dUx2t%gCooFkDC?S4?Llp&G{Z=x&|XJ+_#q8r&jx_x~WjwD{>JMx5d*(G~w zLnELaXeI5MM8?cH!CO$W!27^%U6av;)>#Hm{{iMBM5~5Wlsg_x>YQ`7-y?zf!f+=V z@*7!UQt%K8d^pC2y4av&yh-?TMUj{*w4KInTbK}u)Ej4krZ=O(8?f-KvVTa8e0u9+ z2@)2wy`JiuY#6=s-4X15j!`kK70b#uicw^#gr(^unBXC(iugg2wx_5*p_|8=niEle zQBHxxSQ`~kfj6Kbwr?L5zNq+!r_jGmjQ;!(dY)u= zj=P>dqQlc-RlC-pQP11mwp1>dF*SIE!z^`)HG4>{bS4z`j$&qgm_LD|aHbRXf$E9j zs7QFH!Y6~hMXiG$0yqzDm&iRQ%p*KiLT;dhtamiu4J~n{Jt;-OEeWeA0L0w4C)hx&e=G7+ z&VCt2ueqp*^mJuR?2rfdCkC6LX=V7s6a%895qPsO#gvonS04e{ztQEUwiDD((D)^? znY+H zBtm4r7+J@fNioqy%s(30R`kHe5_oIZBvl`nCe7~ z{T8GhBRo&U_;MKovLDXHw*hKhJA-z+L3a|`qWr}F?y#vC;Yw$5C9V0#bU{p~26-dn zeLi~PEv+&t5FgoR{rC#qf-yQNMo=#;0MT^{e*47%D%!-zuXpH`YX^5$y^tol9}i84 z;>L~nqlw6dV+wJ<`>;O)nO0WhjcqBdW5^Ny!O)J3F4}QQh6YhH11ExWA!Me&f9q4T zZ$ol5UKMfa!jST8%JsOL5AxB`0DO^X4aQ1julG$y?*zY-WCZnLW|;9t z?A9;ToM7lJM2T@HNX`nDuXNAvQ5lDN>r5x9nCu>R3^`>xb}ia@1HX;d@@JAX(@D4X+4$T9x?BeUpX*7 zm52s!={5f0e&)WbgSab%xTA`Djal`kyy%3!%z7p8s@s)zadjiW_F1{s>-V%%3|(4n z-~TM)c_mCuf3~-ze6S3TrF)Y-^kzG-EZ&qBJSaTYwU8*7T&5bsx5=n~$%~yrVz!2O zY36vwuZNlZaiOKC@?ap!n8A+}+{E)@KQx{2G6Q)up+;3D>(*6HxK?V!_41Bge98CS zfaV|vS3kHa@{ZTasz&Zzt{v6!&N-vpPSO|#UuESx^dC5Q5bkaUwm#NUcZG@g&!r*O z&&H-epC{DXI6*s*V!vDWYdcT%AxBQeo8ok7i(6mNm0BI{SZ24Zw6>%8NdG(JxbB%! zt-H*6r#K4EXVOc9fwsx|38ex2$+l<8J?dQnfpS29Dy`pjQ-opeXw4O9laaQGRsOcG ze*`Plj+dVUCf{}jLNnp%Q_E1DXhtB6FI-~8R7N98{=A@LcyJ1jlkC$tRbm4e8^3@G zP=W+)D(Nb{dUf?myOsphs>bD5rUThWFun&f?vrIFZMQRMsJvp7zV6b-00!;rp;Mj# zXlST2a@ojSRB~wlPU2 zwr$MBwlT5uWMbR4ZCexDPEMRNv2)@R=gz(LeucNHt3N>RuCBFL@Ad!Tiskn~)utrk z*GX+qIB;*?K}}U1s7zKxB(}?l<)%hoMj)Pt0^QH73Kf464;pt*bd}%S^<23f{+&|3 zVY)8SxQTns^~VvC-o%&1U#T*lSf&q2=f9g=>qj$$56}&EO0Ecy6#V(o<<`|4)egcl z?&2Vc_pJ0*@Y%=h=aO`9Zx4!t6Bn>P0c8my$O1 zO2>pD61!d&pT;Y|VX4H$P zEw}t)uqx6A)?1U4Si&{jHI{#re@OM2T@}&wTc->ZQkUJ@$HEcd6uYTDFZS7X3X;~T zHb&y*jV2%fA&1HydZ?SSkcj2{k2RPTgQvo9#Zi_&e%5DhP;f;#mY>u0{`+e^zb7FJ z-I$5`sExX(=zm(@IHB_pFP+D88^tO7oc#S_H!bt=7Exyy=OG#(m5=h2VHA|6dl-5# znk>37K6kAu`^ytyheV;qDGE;@oLSOh+9&cp-#XvBZ?gh=jz~mb-u8jlUyi;%A72WF zl*k&oCBI_okq^o4uZ2z?dOhch_)J(KbEx)mSPS=kp+;TeqUnsXuP)iUPZ~9juN^=Y z`!_Z*(qNxay=ndgsPkM}=Xv}AFbfUY{C%I+KW;sNaqc+sp8b^eId0`UdR#FX8xr48 zKvDLcX>HL@5+4;O%ZT>YRG9r<;i@B^Y#m2Ky@zMMhkPfRsM8XFQU=Q); zD@cmy1QRu$(WMwkt(G~nAJbzKO3{PNk zOwEe)^ZS&!z;Ivb%f3PDA0_{waXI66?5~c`Aw~m+-3XGz8g=>gVC9V%F3}}u-ixTa zo!;Kj9)#ZFnPG2V4$ZXw^6z8{`ekaZ>YFl}UdEe~5zA`M4YA?#i+P)LSu0_pLC<}y z5+l>ACO#ZCL3gljs!B^H*OHz@u5Q9@hv+IlEKoGHKo#Wg-|elbQxAst$7$cqRqMqp zJL^K8WTbV28|Xy6E^v?dEl^A0CA-8L=y2zMI!ouk{qlQMe9m4b4Rx|Z-%Q?$wPMEFxUC`X2mh8yUylxffyy14~%|!M` zy$;12VH+_E-|}1@JdJu94kcClBD>)&G$f74t~};;kVXEO+Rp}k^m|{the{PXP^vJh z2s2~ufhfV=q6=A=m3`a3sJSeB=HZPM?c$N-322X+z3E+4jl{%rm65VQbdI@orL%m;=$VL1zz#n@_u>e1-8|Db2f z9q%k?>teJB%qr_rj5J5?_WTlN#cLp{>275Ue zbE&5^cYk=(&TJ$Md3bWEmFukulZlXUzbS3 zh1lP=g9mppuH=9uw{4xt`u0c2Mp_DO-Lhx!i;R=5M-aDYUSA|bBbJ0P8{8!fppp2z z@5mJ^&$}JAT@Lf|?muzvWA7keC3`ZyMLmwf zf#2mG{4A_OMWLCYUXf-~KFw<0bp# zqsFrrKUgFWq2~^d2t zRdgmPW1)ypNnf&0N7engb2vvPAXsjqO)Q3j#KHXm^-LoD{3k=oE4-K`-JI48Jc_bH9^yvkXolpTj|n^w^*~p%)_ib0ydcdt*ak zwS&|R#4qCq4c+_7AI`kRIQenXCX8j9x>8*}7vWpyKl32ZYdW8Ns17Mh>Uk7a+>>NT z{0LHbcKs2ADdyzN+IJP@-(TWOB9isRr2L?u^x#|jEJEuIrGJ^-aZFJ{~A9XepWku%9BZgx9=#O^zXw<{GPrZ{q=YK zI^LgadLsnEG{ruI@wEco&*Qxv?+1U~Ns44&z~gs!uL0+4{p%-DQ-T7d+aDhS*QBZ< zd3|}u*SK}lEg7v(b8n}DLDmH)*SOp5WYn9AVTL$Z&&K0aQw*2IiDI9fpy4ZTVQ3z$u40+<>2KM)6j9YN;skE$T4n~iufiBQp*! zv(r!CKMC4_%1=V)J8@PbMUyx9uy~cB-Vw!pgko@kYygv-H2cziiIUEB!5WAOF6p=u zjXK_0NVOMarOs?@5u}aXLdg#urni4zZKi0YW&g^~TOf}qaHzvEf>%M7zP`Qt$9q$>Lb4&8#y|N(Zo(2E&*1e{J_87!)pOV4w*{Sfk97C) z?&SAK?uKpz3k8oH_6&pN%!Zug&BXJZIEFGD$zSbZrcf(#mABvaJ&*n1qxOI!S^u5* z#FOqlI(kDm|ElA0m`8rTod2)3tB5uPQz=8;8mIDk*A?=$7i(x|wWFwC8CrCy~fKD1XU6&O?(ueO-sXOsEB4Pbg}3di)Z>TR6!i^-lGuBvol(YqABLis8eg4uff zuBk1k=KM(FEuY%~NGew<7SRi+9j^Y_C!Hu7go=C8%&XE9c>?4EEgm%W9lcXL97C*X z&#Ry~$)}Ier+bv^e6ZyMy-r?C&5+L%#{Hy;ST~FF3X3)oEkn|!gb%hs7S%DFmPlr+ zFB0oFNeg8Ye`@;sGMCzXOt$iWZUC1hVpj>AS#nq*0?2PPxbIk^zkXh%g3l&Tdj&G4 zZqXt=`hTs8Kn5raocu~=r`0$BF8$kXSf648V(l?ciS#I+(2t}mqm^9s#NL%47iZ5s z^FJ9!URS(W-&rA8uNK2QQZdX5FM@Uk#J)pULTf;cL8NGeIaVVP!~H=efDaAg7lXPH zRKeG2xGdsL6|NOJ%vI)fyXH>Pt{R*8RN`eLl zga;x9&@=Tx@PDA<42e*YHJq1;89CW$=Snkz@B>N3Gz(i|ScB-H7J@9rC|U>f*1>RJ4DBhA99l};NR#q!R+?2@AtMf)ax(nMX zF?~0XO4d33!l}>hd}YNZ#>*e|9s|TDTa+Ef0(iGRAGCtWe+wKhz<~Qpd3=1Kw?0d>O>E zlh_G?QNlQ24@!8(df$2z2`IDwML97B^2LJeA92^0nNI5j{ar&$SEc_#yGjZ8!k$Lm z@1*c?UghQ({n%;3+hXAz^Zme7l<1Ei`tvg_Av+{n+aD;&$$ED*W_F0mT;tZ7m_N#&TKB6BJ7&zs87>2&0 znEkKeYZ)os{b!mz^%h^}Klt5V>^ZN$8gi;JCi!OyWh8z~C%J|myGOS>I`bqEU%oUw z6EA*IcnhOTbKTwfI@%S2;J8HX_w-pO1W;kKX~E9RPW!iK=#!yPx5XBl{>qyBsQ?J_q;EsHnInoy-$Km^_?X%gf_4S6Tw&oOE9&@a#Zl!T#ME*13;1w@?FtcEaxWQxvE89H`&E6a}t} z(>l);>rXe%6&6Tk>9jCL?ko7y>uxT+d4lo#Q%D&P0i`ON6?!H<0VMIApr-m)=+{a_ zwXDN;vZTJyP6N_|sTkj~Dw9KgIaeG0j@+8-k3j3LF*F9EHs~&%!D8V>;i1!fGgsi# zT#G*DPw?FhFT9H(_U&${am>0>A4`vlF4nc<5b1^DUPm;LOAg*pqDjs;I&O|$H9+^Y zc0v0HE6r_gICjKSp=?6;GiZ+gOCRWe34`*mXUbvme7?lWby)DXM-=nZnFcn`gJYjW z#YwL!3iurhc#$CXRRPsfD5%SoFukxh{!1Qx2o2dsIP{z_R$yY;I@H z-ljPt@YoSFb8@)_&j$PV)TLOqQJGj;QNh&FX)<)G^*?_{5mDQwS!)$*NA*#&q@iT! zY1t}P#g*+cwe_y#tC6J%=$v1uRmg)Gb}C%^mwrquRI(MBRz+JdXw?$bYjiFNGY)MW zH5==7IUW%+4%fUH{riaY8C`hyUOYAcJ$i2+J?bNz9=e=gEJJcK9F6+CIBDr=nXP`# z#pV9@Y{_@o1B<+*_QLMPK*gu+pQU|d=*cP)BRW{HAMq@iw&KaGxmCux+HqPy_z}B2 zM%_~2MTB*E!jFphbf3?%fR3f`ND_@WRzAYwM&*fsC1ga^ep=LhTAv$AfjAgyiC9$+ zL#B|K*+~7%X$T(?NNph3iA5#TXy2&UsMJVGwa&@M#7Du$+R3FI9QK=fU4Wh2`M-U$ zsQWva1$0C_X3PTV;4^BDZ-^|+Z4BDMWMaX_;=yN$CdM-VnTI_@AIjYDQRz607G0XS zPs!;K>b;DgGpwEc@%yO1Xd@p?y@;#l?e%|_nkUY11h`OnGSea;qD>PbBJLtY4EIL_ zM8?MD7VlT5txefla5-DXJWG5kP$@=yJoLcCk&QKE?L2E-b9yr%r(tD983BY10~C`H#LBuB4PGiFn^7rJxslbN_uhNlr^9z<+u;kOHmr zB)S1IADa~UIbIQCFkS&!;)HqGX0RS=5lv z1i2Mooo1(PBDrcO3CWWc8qA2&?%CmY&WPB{&Dp*GO=5A-w zDS&}yDSlPx_AZKARO6+5vC4;o74tCs5{=>7tA(;-?On+UKiF!$cc-3m!B3>t2~_5|s@r+5 zkGP<-PuNZt7`zw!w~S}e$AXx0{Xu=NI*I{@BV9$H=czwX!xty&pmz zZw1^#^>~@YI^T5E8!=P|xAl-fYDK46TC98W1Sy)Qtef+M?V4KX@@wT&FVhRmmNSrB zgfy#el-g??(aPH_-CeuBQv2(@qmjvzu}| z3jeJ>sXCO)cksW24!?HSn49B&DL$PU_L<}EsStdsJ$OFby8)6=(iLRs2>alNQ#4mH`ZH4j$3P>oX7 z_C4-5d(axDK}pwX=kgb27!Bi~qen03{NmLU@NIYxrqfK$P5Bad3DIBFX)Na+uZP-c zRR5mm9WuX~dqJ)BZH0Riyoq>K>Mkc(_feU*IA?p(S}@ZwYj`Yp?09eJlJJt>wdM=l zwz}pOWfSER4VGTas`#aJIn{l8-2)Gz_d_A0Byll!+KsTf>FXf_&2zp$h$N!#hrImo zMIf7sxQ%%E?-PM+knD)^g-#?pVK3pf>D^f*KH&uW`RBh}o?~@3Y=wj6y{4Iw*ql+T zd;Uz1lOdn1hz+pKCrZJ5!4dMaOQvl8Nz5~{FMB`|>mKWEnJ=O7obfT^Gow&W!(qeS z+A~96cEg_Ci$Gs~#4}udC6)11d?8(;0!E zr1UEO%IJB_Io2b!Th$*0!}`A3dKF{UmesWLnsd8z2DdhVj$JYL>h)T-&1@T!`n}V;01OwYkG7(1{n=G$ zD)7}ID}(1h&N1971r+>rNE~_FKpi<7v#Zi8nC{5kWv`W91MllX6X`I~%^B-z?Xk0# z(;L(Fu+x@|8#R~Q?a`WrYwNb{;dK_c8v^b5Ve4@1Ne-qt8yEJ-J|PYkTRPNFG(Is7 zR)XtFPdrN-a<9aRyQhY z;RI(y%nDjq*E9Z6x7=@Ij-$M{v+r(wVf}+0cMk80pLoDIkDI)AhrXEpVUK%{7t&8s zATrRK3^*_Pm+UU#8S;}|6hZkG`;%UDM)aWIp7lB7o$<3Rz5a2@;|z4#-Dcb-zv;AT zVFN8V)Mo)~D!I&j5D;W>_yugizJzyI+Z<79TE3Ka56`nWSy#TadO{YQXK9SN)OL^h z7-MMxZs0z_cTatqudTbehwPa1GchHNP{}4!OYSE#*d((MCewRSHE4+4$+D}}9%e92 zrbDTTS0!rbFi_y8Maw#?IiIo68_6XGs}*ZV$R*3km6a|nNma#aXfe>HWh9sJmLe@_ zRTXQaBuXbGnkBa)rTWQD= zd0Ww@j6*GtYECt{W_IP+7WtpXDCbc3QE#ZaRf(QikXeu&F*`pqKg+tJ(N?#qu%Q__Ys(9+tIe=b$vJDgC!*1-Mce* zZSB!4xMdS$8pPKfv%{?-^q=;3kwgpxI4o#tDA`Y@uggr~{0`x6A&{rL&+g;pZO_TZ zg%_}8z6E$6bn;_fIv+YeK^R^*La4w~UH{O$4K=HWr;R2KYj_we*^Ywr1K`nU{qnQ57|x94Hc$p&vJ zLN(7n!TN^zhWSa(1ifmubZyMo|7z#b&#If{Ifl0MF=jW;ZRiBC821cbRm_TqpCc1x z7ZHd5A|f5O!(sb3PmF2zj5^&I7pS^GXO6=YO&}R(DwV6c-8mh}ixvA_OFzyR{HFIx z%7zt(C6%nYL}!u8Geuw#_gl(~a--5jgNuPMEsjA-vm{$}r*n(INr6p$w%tBR z>5H?OW;5K!gv!M9W4>lVO$(lbI;KpVS_G(ZX;SEBX-%6tX0_Y^!i%`XromGidoCWr zoVc|(<}qR^Y_poCSzW<7S7>`#PmaS5@5W8(k3Czk`{lB(OX+qQr1(;S~A z7iS-@KbsPvD3MiML9B73_t)z4tmne>PN%8CY5;dVp+l@|NkY=EZLZ(3jj}YH)apFA zC1I0_vs{V^x&x=m(L|Ip{~Qp{m4}>kn;giNLfr`_dp!1-?9my%mQJq>LMNI` zan41iy|+mP4#CX4Som0tlDfq?YbRGW0iwLvIjL;jB_@Y-ZpKX9SuU4O{-JL+@jPUl zWW3`!*t7J;;_oS*)h0_sv-jeYW)+Ync}_iCr7MJKI?5bmck< zz6w#9$?O(pQ{x(uRaokjK+GE$Qz-XBlS043ABEC|R(}V@ybHApJqne-Q!el>ur7!u5)xn#5D?%H*k^R4 zTp_tjb|)Kd)SGIz)oiR@5xFaNr~7pnZq=KuwSk&0Ho%*YS8(ppeg!)Vj^?~*I8WzB z!*<@nMhzW-YbSBHW8NP|({?`4yTQ8>yF3TK0VR8{`4x; z1vuM~*1^pmn;8GNA_X5E;(FoYxCPQxDch3P#Z7`Mc8A)hP97!V2E_#$+mzPHO&o`6 z9>tvc*#%46mR2T*b{=UTiJThYs@diIrF=mC;<4SlEpqEgYuM)fCdC!3L(@}n`%fQP z{c7grbURi%##ZfCdxx^8>Zj~>IsLl2MS$%^>!Y5`R-wZRk4;Y7S{w5w@urqT&QtkQ zdb{CP(bdW>z}*I9-QDKVCcNphX>{f1P|$AtCibTCCiC|5?MHX@N0s4ny&Z3Bj$S+- zK-TI{>GYps7sF+@odw065}!w?KgtPO&p@w{cfk9ckS!@^LJly8 zc808!tTbhb{;c((NoF)zhG*+1PsX-*!$G-jz`iTaH9tofnaRr2-6ABGQl!<2e? z-qIYkc${=u%Vw(SW(pVGG;ZAt)Qwc(W^I=5Z-)f@T2IsI_S2AEg$6P#O!!GLQ=^A` zU7fxe-&koU#Q9ZO$Z033kJNtKbj2EIvCw8@q#Pmrmh4J4(5x|jq{Js!dRj`l6sR&k`_P0yK7JbF8_{O!^ewyow!-I2aEfj&|7TfZxB z+vxhcN9sSN?ue@^W?S=`#v{XLLih;&$h9kDJ7@Nna%0z}EKh7Kk2?&nN+AV*9a0uiiiAY6H0i05!$o)A?rz$}YjU^rrBW6(?W&v=!*lY- zRMOO?G9xvos)SVX$Fx`3k1_?D{}b6z(@B%VWqy?XS{h#Z?+nu>^r4bVjfgrfeM}}n z)~sy2%z4SvCYVb#n@TagTt>aj=KrKa^=xVj*_JZ?CF~`GGg+Jbht!AGhgdG-f8ODD zVOr+Y{0uxF@ zFJ)cLIGcXVc*MPQ{J<5~H?Hch?k{gx(!Q|!SKSNv^^z{}o)SMQdh7S*?HYj!Jy0}| zG|)5HPBZOR#rq-(d-Hqaofe-4BmoQ0evfdOMQU8B9cwaEB!0Mt4enTP^kxC z`GMs#>Qi=?w@3e-6@F?UNk>;yN$jM|FQkB$#1XMU8^GoC^AOiEqc+Y@(3SPN!>qm2)F4V zbtiB?Y%6XFJGSuFIb(oJTUpSf0VwIc#R3!<#Psb1n>l~&*$LJ z#2hyqQ{VF{Q@#=U^yTf@T-xm0*c$N!@HS)ytovR0y9Wp^lbWEn!f%9pXufNHtiG>) zaKCeZw7q-0*}YvnU%Y~D*Y1HA4Irn#%D2E1r&Fgxr%R`Or}KUwa0a*y90D!@r+}Nl zv9CbURUiO32iye?0vCakz>R`q&_3uKbPT!%?Sak$77DIGN1!W^Swge)mf7X_Wz*Ba z6Q56y=rC{%I1dCCoRR${J0&|Ly9}5R9T8m-o%w1E=={R`Lij5AO!`#)T>NDJ9Dg_a zNO&868GoaNk%N#_Z`G2(3SxdwCHbAelLTDhDudFw>9!dKVMtsXl#>L3AP zc8T2U-V;QosBPi8==#HT(zTd?5`c_dD)%OlnXqMC8)?Uw?m--_U z0KYFR?7|+S(;VtrjoOS_v~+9gxc_Yw^V)Wibct)@05opzcyVj@HTcN+QZBP1SFhn|JdStrrwFy^NSFlem zPZDolK1m!sYGGxry{{==2dD?sm98@bIA8eqlzmixWcN-PIW#n_ZC+eHx=-wyIJNR_ z!zAZ$DSI;J(D^%4K|%P!~meW+Fa ziR`@4yn23x@Vw`-PyQp*jnIkisn>4H#C@<;(~0Cf*1UXvS-wU7QGSN-h0ujC`8?db z)I80+<@`lHb3X51pc2RND=BaOLma1?Z%W*ouX-$O-`SW;AK}~z;)?Mrz_B9 z$rJlq=SQ#K(C46tO+mBrmguHcEXa2&wxo|&@s5OZsIP?Po`lyjD;fk(IS$UFf9Z=T zxP1IL6+G}+$RN$ZCVomOc%kmU)PCP?c;)WD=6x>*9)MqwpZz`wO2QVGtd9h3EVH3! z`Yc6T`uzZ(qawJLt z7>FQ08b7NVl2sS9H|P#)OmUt(<0$f>q*RSHKRAuKOEMe&e0DX2W1iGh1?<&W;DC4P z0zfqm+ebAAH5c9Ek>J()or@YLs#DrW>{oOtl`mD%vH~8t=gkYNhZd>ihLF#c&lc6C zHPx@tHAKc*mRGNmAl1z^-TuGwoKw$#PVxN=vK7|2P{jWg5+&fzIMIAD|PB` z*LvJ`8Vy=)az}Ewj8qw{+U*KwYSbxmRB+h)AO=$HTI-~tFeEtpX)@vi#=no5;q_Gp zm_Tn06G;h4qB3qm0)|aG;X_5+TpVH)uPp<6L;jyy2ByiPI=#O$q8;lol+luQIB;YX zx5Vh%x*r6t0TyesQR3u8KaX_EDBNR|l_T1t7F5Q`ROhY3uDRP3J)b&cump@A@)Y0H z``Wkv(rqH{ktF6uQ#FD1QVy*woN#aA39B@!wC5m*lANHAV~EiCs}{LIuGPq`)7Oi1 zyMDVFKpsLv2%VB`juQBjbIED)!SrWw)L^ZNRyS9G8w^Rge)vrx^`w?cS>(V}^26`}el2VguxV9nh!soF6-ldT; zgI2W9tlmw5qzQSJCBC>5mlt!|W0Epsf_E*s>uQif6rYW!utX79l)6ct@xzY9EQ34hqncO;yB$128xF zu}Gcf(mlI4c1);rQaW>ui=ucb%vS8vd;IfJl%0|1us1n!SN!X*?1{K`D&ZM4>@>7b zlqC-#!A$nfn$7vQ3Y&#Bla!!1*pZM0|MSR-?sD!)1>4^>5?tRPyEHznu(5wgri_N@ z>MFv-^l}XNg<4Q;?;FQPb(+KZ6NRY>@P!KS`2`ZGdvjm!OLY&SSYg2Q%0q{?C|63<+U^^Al9T4(CY%iQf=u#A)r%L8JsTvlT#1O ze_fECASbnL@M4w-KqY({>l^;eYc(F0J$Hr`tvGM)wm2yP%x-?qKT&pj8fBaZ%ZGaG!!#q2M*(=lIJvG0!+fU) zr?oDF&(;Y;2O}~`-Kn-5g}sd5txIayhOXP(%v5DeiwSZYS9xqp z$yMdX_Q~VZcNf#c3Pz_!Ev9adFQ+VMOX{_M;pffO%Sda;(9aC7@GHgp+ekwiVGX=gxL+-tb@*&VJN8m^qZOpU!sB1fNq z2V+;PXVvN|<5H#}I7cE`Tz_0l-%)WQ$DVznbk=_P-mb4`73h4ua#|;L_eN#%@GbI}SfSR|Mx|Q}{D#_? zdZ9#jY2cE3fqL?q50;yS^>&VrR~++9hw_fR=CVcFrx= zrPNl1}DzIN^O6zD_O1W^Z{f6ae zsJs))jc8k2tSk0`HVyb+-M$ekpHRWZVN{*E1^h*1chvrrfW3FSxkN~Z?vIg?#y4yF z?_mi}pKS&l(U$Z%*A6&E)YC|tChB2Rn0lR^h2U}=hCG9lhlJn1rxI`(R%Kt<(H2Rt zu+9h6N^xG<=&O{b){dsuY=BB~jvf+nXyHPz=k{h;IP^+#eO|)~eSP_~#u8KAAlXTJ zAP$S(34-IzO*yt^wLsXj@;0t9?NQ87*u{IRy4-FTLY4jb*ok7IEG7rL1WoBkU>}4~ zf$$vc8FrE;jB!`fGH50%% z)fc?-A5^Q~G#~xT7$&C|an1a>155~k8ZovUVDM&x56z-kE~k8IGJ?(B$co-L$ZN2% zsp4mq0DbphqxD$5sdI2&6Cg{vxJb9Lb4^%BS#4QRZllw0F2NyF_YRN6-*^@1UDnRL9z`cb|_4Mh#9XBYvqIEQoPduQ6RCQB9Zebes(UMWmjw1Fcv!d!CrE`WmqL_HvyaR(&Ah7E=z=q=0)7n`Og8f)lkaY7A# zNKE||(q>a8pI^lCbU@@A#(ICNbalOy+T^+$PWo0=dY-tRSWb?PhKaMvymg7D+pJ?@ zgkd4U-=#v7N_!h56xOgW`u7EX0zOoout0y@r19S4Pi*-Gx$)x-1ib93-#D7x1 ztyPaEruNdp(ta=?GlZmtFuE{6r}fDxm#Nv*q%yq7sp%5u$qNc`ms(zzqOmr%TF#Zm zTX&YHpaa}e!|ep@+mKI0WzX`QPp|&^LpVD)M%+LnSh)OpYc<(>SIQ1c=s5far<5F@ zEvbJU88O^Nf~e5wI1}fQYI=0N%~v{9mf?CBN)rbEFP|AsyE#t_U6jA4@sF9g+Yf2g z$71@+Uv{)<)x?5Ty?>e@uZ!sOR;oMj#hJNAb&6Bs$9J7q;}(R`q??{}0HnlAYjVTE z?XC6v@NF))BQd3`UmLI>Ya2zi2yVa@=4mCAQi0V&3eTap!%k^78l$~%Z5y&+^N)pR zX09=bA83lEHUlZ&cBx`#kWZ8!77?k$86n3YQlWlAL_$0Cm3*^3d2ikKXGiR!>PM!dfYe3`?>x>-w-Wm=Ba0)PQ6W*Z*veGxG>*#K z>7Cq*>Fc@csq2}YaQRzes2S{3PNllQ1|SX-DA(+!3JoiT%tT!t^~O5)=s%`w(l z8(>4#PmMm@&68Xsmhb3@;Cx>Sc4{2@{r9auU`H}N(Pu*S%H|4m^8}+SUw_gE_3?d# zetY?iI!nGB3QapHD_yECH21qQSP}P6q`o(Xn-t}t>TiU8H<&3Ux`Nj=%rolE+Z}V*T%^ytAf5c zxmSBEdHtQcA1HDO`oIl%pZ)~rAscM*LbC>NB8U&5HA^6}wW9F;J>%kAgx8v2aJV{w zho>rtA4g1L1)(!(zTo{=6-vjZ9aO8}mxTeo2>tgQ_x*AbQFP{c;r=2^yh|faK8R7E zdRjux=_an22bBFl`^$|mc3e+meuDzxiT6!fM#NkQ_8t)tH_Id#ktXy1@2wP~e>4@r zVP9_u8+kIGpD7g|fi;>Z=;t3H+$0vd>OXQ)(mOBLMK9Oy!tZZ85uHDTIY-*8oVLhk z!g2kl`iFPuu1y(3O$nnDX@7>Eglfa6V%YbL=z8XBNOsHFzyNAk2^Dw9b(jvz&Ds~i z?NQyWQ4jnu5_I*FCBCZr@TJG5 z^;NpRKbaB}L%S!i_V}45%5+UjDdS>a`~|QFVeIOum{50&;ZWPpPL<2?xZP}Q1Z@x0 zKVu}UU2Ncjy|22`o3!L=tGOeM5A54ECEw~hGhsolDc0YAj~+cfYJLxI-1@=r`X|%6 zS-G2$B7Y`&SxhrL1{oKH@m^Y<_CE_-|4Jqz*Mv#d##G3u5dH#&SGfE4y)*rIF1I@1 zlg8}pG=<*sAG=f2D-hVB>oMz};-XA{7sq>opk+o66Tnl7xO z{m0}$;c7ku0dV(nfnbesko6Zn-y(S`)0lz;nOgJ7l_|BCXBYf4A4`?5tObmNge8wt ziZy8(+;i+H39BLvHKFN5r2TULAD?OJJD-Ug6I|`}Zh@)5_-A<^eCxaf&Yf-TglUmh z)TTz(%ziCTcZfhPOBlYnQ6WbegYs<@#(#Wg3Y!~mlj5}#dA-uQqd~w=)gbPSWlQ{@ z5%z9!Er*%oqKfIJT44vc{`v;0RQb_blI}OT)5on_qiz(v=_;6jn67UeS+Y=MN;Wr5nc6Xf9BAsCZf>)^a!bl%Q)Vm_)BAN9kV&+8S9i4K~ZsiFF^ z*!-F|*h;`1wGQwGBlfzFA4~#dv1dLAg{Ua}NV^3fk}p&fS(0q*0#l`pl^+Mz}mvs9^|o)i%)iyl>tu|9$+hIT~AAa(aa z&J|$r+Hqu=eTvcIxQb_X5bT0{^RmUi$)5e zq;K@nLxtc)C1qm7TzLwhESeUM$L|aZNB7)bdWR)>jo$6-g58VW-YtLAJs5HKg9`f!WmXVnHuF7ewZW2vUKRC<#&r#H=z%QvBoB3i6|7<-s9>$ALf-^RK}uZ!UQQ zyLDtXUDcQ?60-m&ahynwHWFl4JS+>{tJAHYl=+<-rc07dx9f4Nzig=1bCO0cZw0o4 zvP2acA*|5WGGcMpvIz{p5!j<3fWyrF1KSS0=4?#{fNPomBqiXv7Gs|Xcx{F)ZU%fi z3iKACSU?7cSH?39^yRAr9*1i2P7?P`c8sP3dzTVI*)3l?7vp?n&eb2XP_cebk%Dw( z^~y~?yn>z&UN1~n5QR3L*8bevy7M71I9B@%tt?KT`JBJimvSW_J-mMV0r_|8ZCn23 zxj#51k$=dC)zn3dF_$YvZoEv{*F^?kb5tS)HDxdpX1tolWR|C*?Y6RJOq&2is==@n z$AOG9P=ml-n}+}a3QI;>s>Jpd$zD!Q5wPJGz^i(|2X$Njd8z2CdWi4O$R!vSw*_da zAa>p6aItDKlQV0-qarq_vhfYbnTv$Gz)cXAr*b1gWsJFNViN3rsu#_9FzU5|5xK46 zDnuuT-k2esGvm45rX)jK-$8UgwfO2=(WT!NeaXjP@wKZ4{7m0|^&$Ii>3$@x!nQKg zbt4M;cyq43nxMYO@1wrI_@0-RdUU4KVlQD}Exq=aZrA1A-U;(P^XQ_kf*!Z!!0bT# zDk+0~B&~7HBlUuq`Yt6BI)*&S+6Wbt8k~l3 z;U|YN2s>hW0r2>&!w|Najp`PRD1aDq{t+?=P7CNT#l`T-H$?)aDIXNBBPz2egFDmL zplaIfU$ndYXzh(zV_V=Hd{Bu8uzhoqY(r8UouhD9qsE6gK<0xAg!e@93dxXGOo3yq8t>Lz(ctsaE^ zgU{^!lHR&h`t@PiLzDB;N7dEVy6A)A7gpaYu#WB!gC5qTePV?{vC09jT;JjdAsUWR zza-Z+jDDQy)XXY5mpy?5 z$9oSh_0~Qi{Ov_>uOQcPt~MY!yNp6E-r0P!7%X)zp@8cSjHx%)sYBl67ItFBIMafT zMSpzVCbe*eN`Tv_R81lDX1sztwNj+GZcqZuTA1Bs36QZ420rO70VRk;9hXZ5wtkW4 zq(y^dJbhQ(dyl;pTD|+NIDdf)%lGnT+S^|id*i#c{jusL3>@#m=fx}w9a7nGe_M3@ z*&U@Kou;;Zul^54|8qdxA5?k7)Pp4a(Sad3)yVJ^ncK@4YCq{XT66QwGAI)RvsO-n zkN|)Vxy)4j(S}_`f&_9$Je;fk-Jg-AG25P)@vg!F$}sM@G<0OC?^ItwKSx3XqCwwm z0=&;JZYav0(ej|+zpw+N0oMs9Hig}~8vb`H_&L7krK#~Y>#z8o_U+a?akzVxd7|{z z<=<70R`iYw*Xs`lk?DBeU+e{y(E`wD!DugIX{!UTJk6AvP~ec595QLqmod(MX@RQi@qAe0lt8RN zmJ;?p>m8#&lyHVnvL+Fo6@n{g4xIyJaI1tirvnQcW1~8b@)%j3qgN%$+C2eD7y>}R z68iegsI|hELMLM8Tgsprb@P>lOh82dP>KqNa^xr^l2?Yyqm>jkLXT$rAJwI{J!}!j z8h!V97A~gfTNP;`XIBe#R1=yHg8_SP>HB% zKD>F0L*jJ#cibl5?Q;t!qUn1&)3=>$&jJDs2NvKf=9 zfKfdZ_WFvq+%hWq0&d$nZv<;q(Q@TH%{MDOIBs-MAjFnp`baXziYCKM))Hv2lT57} zjm-dkt5Y;z(=%}K)-L_@hvd(_Bz$8G8oC?20d5^1SZ*WBx+y5Y~KN_q+2}eaQes9;Yqec>cTK4L`k=`=1N;qAuPG z(2JkwRP&79R~Md#+pzE3?|+PS=?l;<0;|7aUI5tJ$=Pz0e}3nHo;ALj2qG#xULI@) zETxZ<(|*g?Ff{tq+6>RB;n)t(Ewf>lGs`n)l<$s=pxr+0tirhLsgB2D986FlowI#- z%>K!@{Ql6Yb2hx(Z~kPY)G)(6LXW+FQCaig)(W#|mC(U{9>eAZ!VwG-}-MBaqpQL0~$sCn1J)S@IaneVEe^TFS9PptsQar}?ywMfI9JFex|6}+S-5#(Lf=h#`|<=}GxA8t&1V1lsR^>UYC zbj`ZLU{p?&fr8$~+$Na?7Rw({OWXfC-;H^Pmrc5K2!I1e_JYJwyr$rTC=#lLhzI#m zK^M*B6LSD3pd5gy)EbrN*?WIht`hk4LNh%}V%p)Hj0FCS?CuSM^nx&xpqWc@0?qMk z-MAYT@SNv0Z^$y?k2W^M&K+5B)YhI@3=~wMpdLa64G558)l>!7WtfU-x&tsD4Sj!U zS*+?$!1-p#zcSBZl(t{SuCRaAeI88I^u4S0+J89O-HSKHWxt;IirZhE9-z(b>D!#2 zqKplSFYDZLVOS`2YJiC4?_b?>x{;o`PLCGU_Vgc{_?YJ>-@@{ZI&dC8a&p!1xp1xU zf{?WIbh`7i$I9{gfGa(o+}pciW~$ICgqSb1jtFTog0n|^xQ#^W2XRnU0+%+enU_HG zZDkNRy@F1S-mO_vuf&@eH%M{u#aI*L#vV^`wmSo@VpC`fk4SCaX-f zalJ!fuBmBaRY{QYQga#&_bx9*T=4NpCU7CtxH-9|hM%|VK9h=4?_bh_6#KADb%k10&g3H+}i?fa2 z=3rHBros;CFLFMhc$xr@z88qIQQ7$)j%KT*rORk);bgUZ#s8#@So>-46w|P~>)5(X zOk@(1vD?;e@irNcZxK^P32o=xoxP&Vbas^0dCb7*8)`bdtR{kDt{pBxlTF!VF@kWS zTz#f=O2!E2dHY@f<&_3tV&Y8)doy=#?Iq#VeQ#m51|a0VNCqGe9oJD&h=@vMYG)hZ zTtSXRlBeYFW5y?>jireZ?V1pU8&Wh20@M99Y|lQdJG=-uKU7MSeh$!CS0_Nln>wZOcxz4LX0=#?P-fHR-xcSmQ(HVY;-)f*E2_n;%g znOB;6S+PT{0B(^79B&swu*>=995te_xR_~kc>pZNw_>;MCMRAU=LKZ}8eH))z9$DL z4%uVhAsKx9FD3#ACy#GUg@JkP_`QgfaOFMz7pd*A@cJWoWr8*0g&zaaye!B(az&@Z zG6#|EAJPk_N&7S0$ow+oRl z2h~$<(qk?yxFNCQbHD`wm^5Gl!_oQIV{gYQ2?~Z@smXg$Q*A_sMu-DiWX9nGS2-mn zUd|E2R|*8WGp-^|fC*V5cvl7c8%je;?mKs~Pyt2jf36q`StIE@nIMd}Yx< zw(pPKF5TmM?a-^coX+xAE{jr?^+d%SuVZPjmFAM+U1?PmRVI?Jt_lwaCp-XIIk8K+ zajo?345z$v(_7k3yfRzXPhEL*fjdJF%$?{C!gFla>W9g-W7Oq-M5tmHf|)K1E(d1W zTQQY=1R&3-joXZD-@2;3t?8=@oI3i@EN%eJ$`Hv)c&e_0Cn&h`J%XHten&oVzkwG0 z5qZeKXp1#TxiXAQw^N@cM_->sOv%^Fbv>=;&FF0#L7cTmn3|O*e)p+sWQwX4P1z#m zd!iPrOM=g+Mr(L@Y{6&38J%^5FWA4DU`2klGxwS>*cktpS{fW3+f|Dw+81OdYHFNF8{V z%l=MG-mGxGl;wrDzi#y&&|Q0mKi~IW`&n71sc{J*6#HhUp6R`5wasj`yHhJe^G7xmE#fX)JQ1Q6AGFqNBoa zhBgnQ4c~1?N<7X}d_~}FnXTyF!Sf(nd?od`v0&jykT+3YO;`TdS@%1~)D`tsg;ecX zXsg()&P#0F1OIn1T0;ka4S)0>+{rUen<*5v8CmS)bT#~ekr~rR#p)i6^JSKt8q4!Z z%TFhy@3jM~c^S1tum&Wn=y9(z66x_&6IM>h*=HL#%TOm)$-eGPk{8{N?8cnxz_o~_zVd#+ndAB;tr&K2Nz7_Z zFn-^A2emhZq)chnkNS^C?=jE|6v zV@t(418X*iNP8(s*UNi3U(*6nSeSIRM%$V|u8xmaxq_8&xluhE(~aB6m3shmHz&d{wfWJcWJ(>y!>JC-`d)vGD)3g5h*AhUBO z`EJ3|7PB7wLT8qbX$l)f{_UiR}$zif}fqvC8*_6`%-p8J8aP7v-8@m0e`eEoe@A1IhpH)hDiD1Da z)u`57o7u^c-fyiQ?Q$T_PRH@}qgQ9?nuSRm5X)FJPDFy?{-Y~6!DO7mA<^6o# z{n%;;J4vNXJm-sRYc$d|CjQr#EGJp<0G3598%HAxY%oaYKKJ{J6KRY_5}L49?=bl} zB0)cegjmn*vBy1_#-r7d=i9*=`6Iz(zP2)AdA#^|#q#LCcnW_t=zH{zE;Q_>eEu&s zpJ0`2WgH7erx!J|L268}7arb@?@p}*yz{btHxzLlnKGesrieV(YH;Us0*?hQ4<>jm zMoX-i&Xi$p-&n4;nJ~AU*N#e(vGvuez}rSc+8k}!qegd? zK`ZCgF|L*;nv+~e(`H6EbD6LoAu0ATI)i<2haKDOk12{g`(AO}sm=*}8O25XlFQQw ziCJTTD)_lPbDmsCb9v(be(Iw^a)xSi*1i={Qo`R?iU z$G*ibZ)8}{<1xK*E7|=QCWbA!Kf%z5lP>pX zrT9TL*6nL&+}=O)gv*Fv(4<1Jc8PX{+SDJkEm^1XVfU9CaPWNBL_C&Z@I+?d$G!o} za3G@o69MrbM)+Sq%$OPfH?vGPX(K9_0U_-A9;N+44`rqW6mdxD#t6Q;6W$RD)E!m#a=Y-d1*FKSPj9kFkj)=@Z}5 zmFX^5;v0a4r`QL_!?f-hPpTd?U>>o!vDgffsWM~(Ze9Rtp+1Yh1_f`0^X*DWZsv z)s;$K?g600>m;T~^JJ9Cf3^~{631D(7v9Dxd5f9NTmpo<)`*DDV{4LqV}v)WACvoT z_aT-i)v@sWBQmG5n)&>rbW1q?lMTT7zczr1r-SK_A@}1x{up`FPga6oy|I?sk|F_tG-kATt!NQUv z{}%iAGE7kPKT|69;*uh=h7JVuk|sZrpQVfEf1j=F>Fi=^D`{tDPr$=NuViX&>Fna< zNkAcJVsB(h2}LjOWMb-MX=hGA@&7IMGgH~s!NJDV_8$ny@Y8&HbpmY$0ya*jAGDE^ zj)Q@Pjr0E&3I8?v|5~^ITqOKopY8ui5_107lAKIGqU8TWBxL&$64&pqWBB1L+1dZ+qaOcV%34jYUsB^1MO0P!)s&{9t*S~^&tfsB*1T>-S)~RW&yC&H22U9aE6+*Yke;I5YO%li#>~oO7RZOhZf%gTPdnDIxGE&d=!J@>xg! zOt5&386vbCM}xuWpy_i!8WI;yP{JXO!o$hc6nm>3!Vr=;%vj|QsMlT2CB!^Rs8VY& z7U3w*cL)QH$u3CobWA7=hBkJY!cTZDD!jS;uF$!{*=!!?R0oMQ%=A_3P;FT{2dWA_v&ljB2LjmCe)lwRMxrc zCf92YrS$&B_6x^CG0IfEb0P7^DTZkY3{ue_<^HZio}$SvaErU^U{Dj@ztS72@Yx=U^@^5&m!~BX}{UvDML%q_|y0BJp+l3LSS2547-s~{{ z`6I+{v2TVcP!!Akv5B~qy?2Y-YJ4;6{h0$iEg$+=S8v19N-do8V+#SW0?fb7{=(?K zHfI(Vg^cIFu={`kKEDKY_rG_!zwJIS!z?ewwXoeCd^e4G?_z$dv{WE{<7UWm2U@F6 z_}3}%eQr&j5ZHt=#an*nzQJ$Y%e&l)q=kWg6YT)OeV&< z>1ElsdNjZP0KkB_05W_V6rb@Z-OnuVJ#zjO1oH8od|Ka=Y34pw$jZ%S ztZlN?&}(iR{4U=pEwz2BSg2|izkVjts{dlx%ChvG8nFa5$Sd35$Gg<5eUwGlG8ATK z(R1#-I=sx3y~Z!b!*fbhV_zW8-R=#O16plvFMU<`;LBH*SYE#_HOydZDa_K7)Y_3- zDA>Sh{N zRpH*_w|(Auj`=18EZi0QmcG@U-Sna9k(xk_HoUqNbv(8_^^?YaGgF>p$8PffLs8+lo|9Ec+;M$GBaxICN6C&HkOpy!^57|yS#vIb^VoVD~ZLrLL?Vo)Oa2| z*Tjact(yAhlslv>i^Pd#P`W>(XgCtkqej`h&| zd8N5cG;yib%WM=;is~->ri;iOT=%KjF#_D=Vs`zu73#;mRkhr z&unLNT}V%HSs;v;Bn8}w=7;^!c&&UE7YEOeH4qj(><=G-K%(Ti{7Bp&Yt z^<}toV$R}*o-}ni_(`n#tZV0H2k|Jt3V(9=c&|Oj?~_ly+O32ii|>?v@`mc-k#rCI zcINwt(*1pPspxg$K0OC7>Al!(AzNd=#^HM8TYL>Tag0tqIsMiN;0>S;sAaj&6{L1i zsM&GMlUqO-d-smy8{dDHb(v@%TlP*8-x0-<`@qd9ui0yEXzp(o9L|EjSPXQfi}!eP z3{d8bYs=$;^8nCT9*d>%smwF0fi3KdlhHj>i26J;)!I~u`W3qN%+aHFLh=2zM_U8G zZ1F}q7xiwlj33?n;fNRU0C1tGs%^?;X>RcRj#H87);f6CTkPi}pGFYC-Fpt~x^b`Yg=az#6)9$Eu>RSlqv>EcOx3R))^%TC?z!QNwx^ z-G^uG6^*mmnJ%Z6p$Rw_sIRT+Io#$O&Kc>s#E0Kvc3MQ=+Q}BqCHZHC>mYF|0&^Sr z%0Fl>ivzcSSC$aq44(7cs(zQB`N2MgwV~C@*Cem~5nt!Kf}06n#XDuApSeQQ$UV{S z!<0Q9ZTjf-IH*)k41X0_G549;y5PpM^*;&XZNQ#(pD=13RuDm;i|tEspcOXB2Mr|2;mJfj~_VU#Y3h4wsUgJFvJ7& zt;vh0T6>A;k>ZDo7wBI#TKv|2M0`WR%f$^cMF z+E$>K&VK^nHv?*X0)(#wcJ7KO&6@E)h2zU zZX```C$%3-3(R}gyPR{vK$kvSg%akg`2un~%|G*5Rv<_1J3Dm%8{n_^B%RtxZJF@r zvq3J6_Bmm2EnRT8_!^Vm6W-W!&-@vXzW!1DxB8^(+(eD1#EUUN+V*D++4ryO!S7&&=fyg=_V_Ps)9G*7^`&0QY>l~@ zZ@KT(c*z?7#tVPIRrgyP`{JwkwLBA9&~*Ra4k_UKdz(LVy`5&y$Q{>}A6qQ<{lKh! zI&S)V2Hp(KdY_$I-E?WSnxeR8yjWEc%9C|<$K6y#{@>52e)FraH^5v-h=+URmn%35dX)W9P@0y?2X)5<)$|aBCSL*MxQOzvE-a9<74C-4etZf#< z&s|=;H1fb&x4Ja%b_(C#eCyq^ub;Vo=0(E2?4@{)Z|*~H?mZoHm|EUzcxhX%Gz&e> zRP*Zv{_Yl^*?fK!2u}GxA`5q)?8{$tK^^+Cb5FIo&5VZc3+l~m$Fot_zKLbU+u#vu ztC@c6qw7UG*bPoaXy0|$;=KJA0X4qz%6?#GPZP^6Jn<|o@@vJV^~|L`-?PWlU+;=} zBh$VO;vB-~(r(-1^ER26!>f8C{L%bk)XNsWIL=K^R_?`T8I4ZzUJt_d@m&(wtzSPK zD5Lk$nY!7nPiN@Dr(UBrI6j|RTY9Bu(BxRK`TFlim7hL)X4SEdythl|%TDr;uA}q? zwEUAfs$MAGZ9o71c$UXtH{OycJ6`I&JwNo{8M4RmuMcy6Xhn7w z&|exgr{4k9->>r4ySKachf1P2l17AGSRSk^$g@B*qR54yx^n;?bO1CWnFv}DenOrU zpdPGQu$Gt>1QQOOb2_Z*Xj#=q_yJ;l%&4}au76P}DS+w4R}!G%1+yKE7jYj2L@R=y zXoC20G55{-_7@!xOH2XGgimo1)(ejgZ)LI~rUAf<^eA8-`{)fJx0S)Sv$Vg+L0KZi z=L~{3{`zjs`cN=~oN0o(_CR^X2^1?(WPuUts}6!m1Y$g?5Nv{5ZAYIM(i7OFtjm5X z7^kWW;$ARA{Sn$1Oir|@c}ISxWBrW`m`*k;!zg$`_Jn#I8M?Rrgo`fIi?NsF=z+Ed(bO=6V`1_$F2^gq-8BAYD{4dg$&xc;Li+H ztrByMeB%(9QJw|?9Rj*ww&G9^gu01D32B3_N!s#JPa-q1y9i#y2iKj;LF|||n#ryD zMvj4GQ;9~FwwC6bhM4wB*`vSgH14-s0O_K(%x>R> zSi@vL)r3{CDY$g+h=jM=x7fEKFU=koc5Cw8Jm%-}lsDybgGaYB=re(=Uk_*PVOBl( ztM~H)33fnd`aK?Yyh6uGGc`Qw&mZnyna-UvS3KHYEg*%HkBbgtYo+Glgf49FHb-l3 z=CNs|EAq8m-ER-l<@!P=qmcnX5{Yur<-c<}e9lIdkL5$_ zyLNmNzGc4@9m_d4ezjBg?ZpUb?n*Ruz9mT*!^5&^^UM&ab7%D-j*M{x4eG63GqDs1g0-#mMHJ)eeOB+ z{l(*x-TxkkMimeKngzd`6hE2%hDG(<2%mD>KI*9d0jvMkR{+70Z;}jHLhgyoPO9kv zmKTYh)arnD73{rxYeFz}S7?HPDTiYMf+;DMIM+sgCD?*Qz83bLj3bf=!Pg%_LK2M5 zL`a`O&i6NeY7G9h7~sZTuqqxBa0V4DuZ%0IuThemC)|Y~vyJnmf%9*8zSw==2CYEo z-@tsq=-EaKMy;T%V*@*mm+#;~OSmnUUH_z8;KuVVw!5CHQ_p)#UaGupR(afkcLK+KMPI zo9lH)q(vl)2+Q3p8lPH)Y!!TGKzjDCG*Q=r*`eD^{Q7q%(@t;6JPLE`y5bkyr3?MXVRf&l#UEYm~zkjvDH|AT3u7))D!IaupI& zVB-d}9#TvQjvB^(fVqn47bn-9`9PnKX)a>t2BRK=s|3&$e4QXwXYluHxnjZ!@fY`> zptGRphBlu@)oE!2hZUdKv3p-8O3mf%Ar|DDi0etW^w4|5KfmUpQzNc<%*R@yPm*sDOXFIN7g@3GR94#A)nyX z^W{>r705?Ny5wbu97n?rn{)`+h(HgIxD>92@DZ2IiW(`uRjJmYG!sbY_CFeftZc)h* zb%i3npu5M>p^YQIgGwIhAJsbCJH)-Gdz+_0)*;dgh*=ki0Rqe#0T$eEkpR;m$e016 z2WB4}-@l@{Yjt9EeRU+m z(8k)v+{WH#YPJ8R?Y87rd*6LTd1PVaI@UbKJoY$-A7cjFpGA*Bk42A3kL}CkW9=pS zHtM$OHVdhCQ5h-aO$yjBJ*k3(5_Vi%s$pKjlBSFL0`UnFAL8B7eHVFGc~k2}hl9k2 z(1#L7Eek>)Qasdnz;V}lH{=GElQ0LRXLu_GrL^)U*FlPd)`va^aT@A41V7|{AbtRJ zx5z>BMYD}a2iXt#H#B?5PH6T3?QV;McpEt)rHCcjFa%u`MOg@xN{JYia%ffs`ePt( zC_ijLAWMW=F(FG#*uq&8SZs-!RWYk2OpWaMtOgeRdkq*%B-z3UODJ10tp$}Vb1X|N zQ!HC-|IR*h8M%z{;YgCMRPy|-=&AS-_9=kt=I?Jc1-RIbr%Tz@XW61i{}TB zUY!0A^^MeOW)Dnx+L8yXUUc*gwFj;rYHyhS==m+S2l93h{4V`X`U?YJT(l$Pc3A5^ z?hCF?l>6S+PoV?ecJT9_?~CsT;1_~_$n!q%i}45K7m9xv|ET!Q$_oWwn0&^FbZlvv zQkROnRDzb|pPvXiFePkCO{EAnr`on-rQ)4Tiz=^on7!(J4U9mP5y zbwVZP%Fq-lUb3aMED1^_;>utZajB$rDcaHwrD_y$5hH>S0wM&d7!e|-TcYiu@Qer{ zpUBLTgt8JuO9`xGvJy;7IV}WkN#awI)FzS|3G3nNMFPK)*u8QQs;?+fNQG*t0;Ez9 zO19E0C1pspqDcO60>F|Qq@p2;LMd8OnaY|FYS)xADP2;bNYySB!NMrPL>Xih{9$#u z#PV_3!&4__Pq2OxO*^`o6z#FbgS0zkrz#%pmceNv**xmd$3RPM3p!_h-hCvnfpO-Vnw>6G+w&AWT2mXDwuV)}IMN!NQXlsPrhloz~JW6zl;^W$f zb9Zc>FUmVx%(QH@ zjI^x0=2~W6+boMLQ!JYY4BZA=c3yK$15NV}NvEa@R0~!MSPNRpiKnOwTnoR-R%B|k zmlxEUU~Q#0=AN2>FC~~Q*)C-|=j~Y1d&sAYyobt9^c>l?$fpahqn%H|_ZA+69r3p4 zr_1ppp-%wo6Z~lCO7bISW`p;L-YQ>cK4o-d_|em6h4+}=LSJ}3m3#v6(9#!(_o5%D z9YJ}iewU06H9xdzi1ecA7m^RTK49OfdMWA1_oD8U?EK_`P&z{M(sG?X8!_?{r_DC* zsd>q5iuoh7F5K_Iy%oQ}brYn`NAJmbNp6bLM|Yme?{z+yJK}$eZpzn2 zb3c(h5K2zKmhI0-i!85@=8@gndnQ7fiO}GoM!L-NNfyZ=Olkgzz5NH(ql-*2jzDX zydg&q1#pstAW07;xJy=u{h$F!)(=5&5``dD4`pzYg&^;RS{k<(0%@mPBw!Dbxa%|^ zWCx{gCtV%O7m{_-jv(`gWITvdh~7l~sXG(G-9s{p)Q&(-K%h4$%o7L!VL?R}L^y+n z4G{^1k}Ml9qb#c|vn)F;!<^qxs&5iqr?O3xA}Mc@J)L;3-4mXJ}T~0z@ zdZl!y#Cu+MjfC1M0*B@@?Mdod@>=>@>b-<_9$X2&GJa8dBHc^Mw{%-6@S*0R+eM0t z+Lt^xQBL}}^zud za+5Mu>XUTmPqwvtNqmV;W#^*o8P(x9?BR%0jE=fo(zG;rDSnB434UqeJc4EQLkNpp zT(a?@$7$J59;$2y)mDOE>XGz)NqK3zQ;?4QZ~FJK?FJI;Ql@cI@9~BvrJsOK3flCv ziAX2l_Bb77xMW+W3LIM6L^SDIsq>PRgLNm`SKn9QS7FcIk3=7VFO4q|J_>&-e=>hM z{G?t5Eecvk{8wonMEL>b17aa!9t`;Y!NXz?3cN7fJH`(fy^wOMN|WMQ9QdSOM5nQH zldL2;v&8Z-8>a9nQu$<06FyA=sBxh}OwTYHqM4*&6G%;|JmSf*`vcI1oGuBqgwzAl zSM68s*OXZy3(EYoUUa2H<~z;ToY{njgdg{2l79mIAo`BoY`l*E+pgsSZ-X?3 zOjM|gY2jT|gWSI`drw`>+O9$yg>4l!s^m~gsd@%6O2rncjg-p?xI^4hm9@$XBr@vG zRQJ^95XlKV)7l34jEb&Wp8_8W8HFcmd`j>T$BEGi@*fvM`H=b0`7nV&?Vk$4S&gIE zqZCIq8bY4BKd~|ad5C>ja#wSg%b@qqgy>QKA0`C+0P>FrA^y*VXfOHkAe8*n{1kux zh!EBjwG;OLOo+QqC*@aR4Vo#`BM9mc^U$?{=m8?bw40zhg$zm_dK9RI(BqKT0T#nb z26+!D4LTm;DTFjg=#a_*q+QFyw7YUA?N{mc;-3IoO4BH5$Ls{i>_zXgY^PrYExfxm08c-?kJ)9Q*AkA*vI=K(hMg5w2>7wKBCdxTkfaJVJJjscZ_NpL)q zTOEI~JWj>`y_k`EC!Q;JP_qo)ur5!e#X?_$Krz!uUp4v<09+zA|hd+ hmGSRdcutX@3;x@LH z7@ufnvK>ido6Gg##=05+A}AiByIi!0i8lWDg``@u#?AZ%I8JcY3Cm;7%R|okwRs%Y z`1r=Add-}0tqq#eHgPw)v1qN0JDTZVRhx>bmN8g2VF61}q%^idVNER@jyd%yG4?&2z{3!vvDSx%O>pHaLuJ6*R+h?$8a&F>G5jp}qwQx-QRB-;JS~Foc_4 z;fF+)hwkixTy(_>uq_}i8?`d&prtP>@Ii8z8=XB@gWf{Z3A}}D@{$i4Q+&Oo6x7q0 zl;tVu^XwZN3ayfBKV>kG_Hx!{knq8~YrjMW;Y+l0gk=1Bzl1T+VQ89~?f$&iNdI2g z#scvUTwZ1yenckl7vy6xqBsw`&@m6PZDO8Hn`RaW361Taoo=^6tjS=mOGQ3>UXkKN zUT-q<(p*P5YCVE#=&)I9=T=O5w{aAfeo=GtO&Wc0P_qUNMp`IiaPK29H}QJ`sGAW? z+jRJ~kO#h%Za#^dF)B80=C;fUUE5e?uOcnDL3Oyy+?a-4Oe#$WiGH_gAs9jmjMwsT zlwc6Hs}yV_vXHIqt`it1X=)!3n)((^znzYMZ?xifJrW|HM^5|?$Jn*bW8$8th zcaOnNwWb2=_{|zUh%@#41maxZK04vB0M&k|g%PFz&4a}*!q8XGsr&*fgYKK)+|^|y z&d3^43!57!s+Pc0xn$bh;qrzT6+C-`Td@r2HmtCIGrKm19kAb+M+$UMqdrfN)l$-x z8(aUay0eUmV`~>QjYH!eoS+Hr8Z_p)5$&jYH-asbwM&q%V%$xI%sR52VR8vO zcE3Vd;@1vY`Cyj3=KWi-+hbHz6Ty5`6#rvmVwh%4uz6g=_xK|*$XSnx%DY`iueq@v zxrQG4*bGN!%a}Z_Io|eEf;M2E?1SZmb3m3y_S=y=;WD}wydR61@MgpD>Q)@$)iZ+4 zK7ew!)>afFYq`sA9H$7nim#7C^Ml$y5gsvEa%LYxY+~oO;o5^LLPwtzZ{?GV8NNXs zgKNyJz0+0s=XD}knBrS0^!#swO=s*R zeqU0k8Z_P^Dk7H7x(scFqWeJ3-X$Ms0kXr)+0i+EIQf2Z{1OF34 z=XdR8{)KG%z zK6r-^j8`pZ^$c6FQp?LP-M_9uI|@YWhr_ShKt}V1TvCyRefIq*7B(QBa+mrp=a(HCqyrc`4>m7k-;LE8Sr~+ z2RmbD$uD=DZxhWDXSKy@(sj)eGbJ+=WQlN(Xu9MmW4OupE(hlx<2z$lByN_wO1rfz zBI2Bf=0c>IH!|_j7m&UX1`)ZSPwi?raAjuwXyUnY3~?Pic!fbm5~Y|5X$|}?gMApT zJS3pGbX_u0M?NtX9j*lH6{{9~V>+AA3g3z|tQiKC!{~|<`-TJRZ1(2@w77H?08N|i zH3)z1ck4IX>kvN8LUfwXLRnU4Asa4RAuPHJkPYW84NzktP{U;_oaG@GD00-T&}^?o z$a2sv32Mv+iX3)(fNsSI#}B%-KzwS{K#MuR6&J%a7V9|(4v1kMp@_wL3ewnQk^?Pf1MT*^JwfguLcJM?OY>Pc3*JGuHb}DqSmwNC3UZerR6p!S1-UB`CLVPI zo6lNVm|niIIvbX-Fik=Fn$OBvn5H4(AkA#xg^OV(i%xLu<)px z3zS?6RB<+pWf3X?;<^|HvV56=R5hOkvwWF`#5A*s6OuNw=@Nz399;>tXf{}YsDjLMfMd>7l7y-I;>IBJeBe;?q#|LgGnEn{@xHhZ z=))w$Qzs>QK3OOdF}ewAOXY6FK_c!%=}eSq4M_`<0@TC651!-oJ{Ah&ZZ;u^Zt{Nu zVQ$1s&;A#0wMA!Y<_^s8tLLGEnVO zQSFvsCpcl$UEj{GCdr1JnIPZL#)+oFPk-By`Jk06EM20&=@pA|_VoG8ms5z@B-cmC z1GY%=E6((5>Db!AoO6k0jIR{4E(Q<&m5Pw89N5ZSX=V$iKYe#jo5@PIb+`+f8H+uG z&)(o)+jP#Du}k;;;T$=mCa=Nw*nMCoFXGTVdVo_Dk|H*D`#EiUr0WFn<=&Aj3mxW-F zO?tiK+bz}6p&<)k(OCNWZtdq8opc^Y&$t;xc{_XUi31n;Zw{UbGXnD8?B9N`O`IW? zFXONHe#udk#8OO|)~(ur7PEkt!PUpqE)q@jY+SR0xV>9*%ji--;%tAKc5YCM9Lc$#>k^d}mF;vGt_Z_e2O{$8VJdeCmdU-k%t?!U%OuD6g zI0JhFV(IvsbQPi^MR}_9Kz_Atyxup_DlqhZ^1kV#>E8Um?SJj=sC{1n4ED-w(KyBO zz2bkx_c@(`J^*(sn4hYJB)JQL0d5s;6=4|| zpM?RI>9`m9SYs`=Gowvrfx6I z$5RgM{!fZYix>q`Zt_S)@pChu_XP6FP$yZZzW<892%rJR55^YO7ikqn7wG}<7T+G- z9^W3}47h35so+22|H(hXALvg3*aL{bj047D$6?xE-o&QEdL!Ku*yEg`Z^Ca{bvksi zcPe#i_*47$__G4^VK4x~NZyFIc=lLlD4WKefKF-uM}JHJ1aA_O87B7i;2%Zq(L2y6%pA{-(B5f%~V z4(<+s3iI2)-Cx*$-Cxf?(_cuGC0j6?B%3iCNQo4UJ_u_9D*zCHC5Nj;GJ%-}SilHU z;!na(qD8}+!%DPRx>_veb&l2%9$R0YR%V)W-W6(ie7o#rV_*)950pKW74@XYybQio9c z1+OmXa<00qx%84$0xR`G3>w6QwlMH2&$t{|emSB$Za9wFXE-n9P&9is#TZ7ne7)y2 zl8)7b%Lsg+`dQESA)V0{D@wFwvEwB4i`5gHrAx5zegvYp2pSyUr1_>^F>hc~aEQ1$ z+T{Qr7eG!tZVHbJJ@P$nKv7=Nr1d4&%S?qTtR5A!Y%MH7g-2f0tBsRX1pd9!j*B|Q z2rZaa&9RZg%?@nW=hGl&$q|G1mm9ENJ9eQtbC%=x+ZvBHzK;!!^EnF!y}a3xY~wE=-a+BZ2}Q_|T0V0igFuQ>^=_z0cvk5(`tzM0s9p>Nf_v)ehmIF{luJ zQuMrpU;3PJ&(gvp6klFHp6%_pri^I*>@#>`#npyx=(s&2&MyGp9Sw(?vr6~`$+S{G zh07XoDEHd`g4`1bTi#+1g@_XGv_qQne4jrCIQnrTADiP}C~judVwOAK1biU=N=1V< zWnT}=rO{(k+(0HCvP*tj58JPTEF;I&ssni@r1T4nhMl)O1caE04XyxT9NN>cIf6{@ zAQt{mKRj^&CDO4dgFTVBm@7Kl^;{(t9vY+O2ML(`P;ya*V{-8=1Kc^MGDXO97T^Kg z%Mxt)1@7T&BWlp|8EXPytJVqIto@PEAR}Bcz718axLbn#v4f)C(*G1Y{JQkzQ!gBJ zAuLC&SRB7p5%N|w=cUYl;q(d9KUX)nIEv^iyvh5RVu1ERI!Rg!?$X(Cth>J5wL(Yo zm~yfMru=(&1cU1dGoy49UX|}{-PV<4%^ag=xzW2;Z~CxTEN6Z+;(uhmZ$AdQ>s~3y zG=}5KXWieW|Goos#0NW3kO?ki`!>ECJZ|d-nD&Tk2z0~uL|`!Jr>Pkvk=30fv$%;e zQi7D_5Z_BO&Eo2Gh>>5{+?60-Qt{+fs4E*e_IUP!KgoYA7qd62qa>hEi=yGR zmMNZS8wg(I_!y!yjnt3_ho-<(a(`>zQZYW607ugJF^|L@N$25_I>^U6khgU*3yCghe$~Rv2ORO?e+QNQ*pTaPm17Y9I13gEPm9dYQTRL7V zri9~kaYzy5iK*u+9~*y@hZn14CLxHcgBPAP|9~qQ&hGpUV*ByqnTnrsTy{X)qe?0b zZSps|?~}p#`Os*I&ojFx8&TXLdW=e8+7{7pZ@GmObp{{jeizZu_R@(LY1ss-LAUZ@ z#IoCj_qAN>7vyyvYZeY>__|&6&^m5Vmq7C&k9NUrs~sqNeVVFdkzkwULzOlu?rXc4 zFl+<(t`!a+XcWagvo|f-Nk1T(8Sfr1Zk}yfUmxMJJ$#I9T%S`d!bdZv0)qmQu(+!@ zU6!Xz3Y}BR2(I4Pa}#AJT8FDb%Qmj<0*m>wS;~B#3k)(cvQ`qNVVD$oQ>A3Q^>8Rx zsjo}#sP28?JfU{7T)97W1fh~^zik}(WJ8j_h0%Crso~(8Z~Cc1zy{pGJM_bGuDT03 z(x2tCKlU&2IYlem31q+8vE#@#xKHO+u9B!2e5^$Xda(vXm4&6H6h{@yg-N9L>r_QD z0ZF8>mcb>Z2MBkHX>${nVu6;9zA^;F*oG9B4^I}ABYY(E-*4B@L-G05$NRhnONG-i zvu2sa(A<1>maFYIf_J>cCObm0aCm~`IXu%XYUQFMdlkcZ7uzCHe~aNo-Uh~l;eC{U zx3c^BJW^jg;T6Vx``~LYih-hUU+f{StTIB6V2*EcRr6a5GG;pPSz#%XY=<=CWY{Oi zny?i;Pwq^QE=5uBdi_L`M+rr*b={WZl`P?o`fCA&>1-05EhKtfk@gMmRP@}n0m?KM zKFW;j3yeX4PfT*@GG0AhjT>xi#clpk@#eNb`1a{q=ehIGUq5bO)yw^FDg)V(LvG%h z=UXa-#~@GM2o}pAV&=v-`!On+7?<2LIm6`SG7MR4YR-CWCB>)4!_%ct_p%nC$bb0w z!6@TgDR-GralieTiv0JZvTDS@B$kuNnYt#ds`Y%iO z3X`n#Vj|ewn*`$LB(ARv;big%p_YVfh@r_!trF90ZQ1+hwxs@szi3Pdkwh4%{ywp}qbl@nxc39X(7q{K z^21|m+caKZFgr(;@MNK5tUyYTN-9(#HcLd_0`QZ{#Lo!T36}~iXYdY}PPn-}8tJX< z_jWNhRGyqf%0<{%*gz5_nyH;J!$N{ng*P^0LA;Am0xHC(LT_j`31>TqHOONXmERANYB%20#@$!5ztYN8&v2Xc(`FOFAusMZ5dr|G${`Bzm%4!{l09=u| zJcZ8~GO+uNNaXRLIs$U6f8wZ*%My0Zkm6PQoycDIUI`|A;J)GQ97*4CcYAT7SJv9d zH|-W}7uG(cuzBYKJdG9buisj;q$EUYOAA%9dyjixK^l9KqO#0ZYo9PO*J$n@jHNaTLv}Q&GvSe!xtFsup8QM0nlfwLdVqiVou&WyYNWONedm5WNpu`v% z?%MLsXm42j(fyvN=h%+r%h`P(P)iXuHP3S{oAQ-(wO`Kgigp>EpXE)$k(bX`W(HJg zNr+Z;&_{OJ4$+Q|?&|NhQ=~jYzZq(-l33yHCjv-h4DLLnJ$!z464V)FYfleg6Ybt4 zQ8PvKuQ`f3xOn)R%7W}u#L<6C8;Rf5v=~N3fsG%PLH)ZfQwtES1~Q1gz}|X}m)H z^~;Ql8>)h4mPyqE=UvddibE-y1r&>{p}X8cAC*SxafJJ?Vr#QgJd!{Abqu_*)-8FF zKGwDNPI7E8H95^H$pjbDgVgA0xbBFKCsb#yFK~P$Mo5|Bh+Jm7ssr}I)b>o8)COi@ z_spzk8DugNp~T{4Uwl``A%ZsGWB1o~8WUs6p$&H~UT=9TY51yCsI88!m#$(%=In%X zo#0-}-J6Tu7n`56FT{i31RK)YoE&%4g@?q@tJ7M<;ew2Rsh+m>`$#O(tcqcqBU^p? z%!&$rR!qqWQFxPh@(WG>_~<$54X_@+-%Uz-GYl#yj-lK@^}{R1_)xv~W!Y{%Z@DKw zepxMSOBCr~EY|_59o1z>=VZ>#@Jh7hp}CD^+wHj(%Z;(ZDe;+qv?SdRLf4I|H6z0oEN}+f>wv*<&l2kIrbdNtAVKUlb@w?8 zLpo?p#^da!j2YC=ST)J~rN*(jFRumcD3kbiz6R~#Qa{^^%7Z-)p-=~uN#_uUDhtHL zfco#FH*@&RQBzGeOt3Dl6dv}%!V@! zgOnYB|+l8;Pr~Z37PnEd&4i(Z4MwtivZfw$xLuk^HJCL|IO8Pgd z0h>0QT8|}Zz5>(F_mPoYJ-EKq`AjY|&5f(+7>V^d7iK4^$I3bnXF4!`7$M~a|f+F9gAmUUUb5w(r3XV zBA4Fxi%v<4JwCE@tkk8u_&e0=9KS!tX5rWq#_0Hh;;rrNCly5$`DszoOMd(RK4PVW zKHo`~mvjMoC!}%g_+{IDWAiCR97l2zmESRK6c5ndogW|=p$LriUT)u(vb{18*IIassWpS#wkMRVW=Z|PQB?%VaJsKf zI2?uJEWy1f%GB`zocU-a*-ACWa-3d1^9+nvAFgZ<6ZsRk`Dv+g8nT*CIrOhS8HEyp z8}b2)^s#OuaY>zHd?N()G%}HWt@I(j zO<_b`;o4fYOl~9onmVr4vVR^^-f0%|>nBTs9>=%SH8&5-g>&Z7mNrwW@nv(7k@&BV z%(y?-a-XUuIgEiblJ%JabDoI2KO*b9MEJ;!4tR-86SS~iqjIP9wuos7XUHvuY3;(1 zuMb$G;+zT$*97Mm9jBU% zq6hqrSPbVx5s86^_RVj5+^opnWN%{(=EzswdyUr=?N{`kJnSY8J|u4EamCo6e#m0Rc>cdf5q;h;4ff)Q53hr`1#fD>pV*Yh@5 zFQX9=AMKVW>g6DNdo{uW_p0OUSU76qkH!wgFum}s_6px0D`;s&$#|nS@$ViV;6tZ) z7g^a#)dNi{rg(cNHk8ZS>&z?h=CciJQkOvDhqNn4?b2UqxEg*3a}9rDOcTH6vL)Nb zU4%+YE#Ykqug8}ocJ)YA{XP-^5mZcYn>V=DzoDC3)CEe>@hr3kN+6?-^O&Zc64xlw zt;ldD{0_U={e6ZebpZ-Zg*165hE^;#ANrEVRqmS_>te`4lNM~pPi!q>)~lYtTf@yE zHivg@D%w0Dqp55m3IaSco=xAB5S)Rcbm#!-#vpi zY;QxJ5LN`ITvw=e-PdiS?+G+2qJp?IWD+h*XpKqjSYZBRGy2(b(DAWoohy@U%o&QJgG0EX0w;)?ZfNh7KJUP>2f zJQ|MycSu4?O)JNb%KALrN7eS(&0weF&HZn#Hk2dg7>rJ5<+&%t>zS(UmhL~*Q*wl? zTb4gG&KQo@=UmJT%y&pr_L2S*&XG zZdI)GScNR8W;Zn0U8xW+E&55S#*qa)O03M4yNs}on-9T?FfJ$56*AKq{c5tAZJ5KS z-!g_q!F|gmR`staEFiG9m<^=Mo3IIG-=hjO97Ys>2jn$6vaJaJ(d3mDG{iQ_+v-TcQyPmt|fo2 zY-^iB6OVXafLo|ueeJ9>|BLW-GhB0ldzwB58geadaOl8X2`)}zY|O|V4gNSjQlEQr z-|s{7l(v+c(n6w0W#~6NBd+Iz0(Z0Amac#X1RG$Q^M|Yaf$JV$sg*f|S8Zc{0nsbjq^QE{b4JJecM7$a z=U2XE$?oq$;kH3uSx(pk_WCu=>peuiOuAxoiuAUiu;1CDJLuZ?3|;UDrkjCl; z*Y;w2UlY726KyZswiTV+-6_i|5~H#YlXeJ;e?lK)gQGNFeXpsh-qzQv@u(?~WV9D8 zy4hD0l!{^;PKfaVf?3t7$b^{#>7*5E`U111P@*-g~=di)@P9gDD`H=04rsR zo{lb`u7K-c>=fqq>YD0GKml9PgXb#tEw_wQ^q~u0eE~&d!s_j=-a@cKFr%r&dK-=LSk!&vuHtLrSpU6|F zS20$W^c-pT%Nlgx8~fz7uBr&Wb@S`&g9$Pau_4Ia{GgxZscJ$_hwOAkrqPiVtAl57 z>ktVvWz(n2mZ|PU7{hG+o+Df2P}DDZQvYSS*?i?2Q!n(iNKI=Z58&)4^~D>U6sbHa z6)ba}{!ydF#xn}vF;7ZtUxA$+Tk6GZW;BJ}v4jBGv)4*11d4gT7}ltF3OuefV{) zSrY8-Eo69kzlc?X6qLydJU{oIw$ECW=#%pFuadsjC5aml0?mq)+nU#fU|$J}%rAc@ zcIix*y(EN&9{@2%&E*G)#mX}UvYFH9%fbgQCfgSbkera0>GNdke84;_VPW`reGCt8 zz&PgLd0wx93+=h9P~ch)Rn8mlG&2E8Q zEP`S`%dO#YilZL%BODkWHV9g1#|FKaOm0I~ve_)A>?;OU`E4;W?tC8$@gCG&?B9 z)YKbL{q{N_fveIx_O(nxZJjDAuyXjbX+092G|>dYSkxvs+k=z>I|g}>Q2Bc}e*Iq0 z;cjm7iOTnnq~Xog!tX_JNakJ(GcmPG##iuf?>1^_wh`1bkcU;*6%+P@e`~stU5zqj zySorDAOqo1GT4VCMlrX8C1kAYZ5O_)B2|DSfD}nT%IVYkn*7?p`v|E6O`a%^z0`vw zbLywGZM5A_gw%a}ur5IeM0gq+(Xerj?0eL5uZ+XlDc;41C;&i9v)@Ds`ta2=D! zwY%k3`!_t3vB#+p{#j7uUdynFhi2|D+kJ;g>(rO9nocMUrpo8nrpeuTMqb!vQ7+TV z4@^Rden{U&=wZw5L|VEXWjn<^J|kq25_QrW@}E+u7ju0%t;@a*EfKHcl65FSsOJHx z(_=H#+(eUWugmjiuS(<{*ZRkOVf(a2Xc5Mvd!Gl8c z=r!M?=`{-NpFmV&6y3vM_2o|3DsqYqaY$GEck-w)!6QCrDsnsv5DRrH})t_e-$fZ&Oiz#ss|uyhi`RnMs|gdkcZft zhrv<|KqHN_RoF+3j%3^8jeUE{Txmr#;e`Cl+W?efSt7$!$6%~>bS&34qjG(Rlj+br z#vNQUq)L43ohTG!_l1h4IX7u(tyA&e!6Grw^p}+$58hh8WEwmib9AcYAq6XXQf=OM zxLF+-IG?jP4)zQ}h!c(s^fvDwittClBR9?BXDqK!8I7yIJi^^}&2(jQSimf_M{a-5 zPn8TjrLT=d)59;)sOFFgcsF=Ep^Vij`yCGfo88W%W!R-$ZU{&S#a*3h@#{>xAZ$6C zT5xz|Kj5YJyWX3?cnh~ z4A!@faSmwn@6gw!O3+YE*vJpWXV)Wgd>3`wdn#8L^}$F&IY6G2ag-`RG=t0cMy~b8 zXH{u6n{ux{+|a~Rkl$11b&~Q3356f{DETyn_iUHhXZdSA?TQ9>`KdGcN=@w^y&x~? zZCB2~H+Iqi!^bo1&9EG5*a6*#j~X7ebpqP@WRdC%pG?{M+gGpZhO4jV`3V_U{6LXq zWogTVtHs|)?4|=7hP$_`^=>1PHhzGSOsyjwO!KQ7$3_C?>(nQjJ}|DNcs~Y`)V7z{ zrt?^szD(?u#fVawR1vZ*!J`Kkj9d=IO&gh|dHSjsz#9bIPAxx;unO0UTn}DEUAIE> z9EPq}^F&0ZODeVO4W3J%#x8hlmia`kB8rUUTjlQ6fxcDugKiqWw6{_WLVk0ZVRm!-3|ArG5#$t+8m_h ze2khV)#r|nItZQb(`=StPsIi4Iv5VSb35KN)~5ORhzO*A6GBV5J?|JO(0J5|{z81~ z9`^7H=4rqpE7-7~gy~CAk*32qFXGZ2cCCi-!Q5r9-p15rul|jRH*-4y=SJTz0r=%g zc}p*(q1#h4AK&Dq;QFpICi)_%>LgDY**3&I?Cz`laY4Jlfw9x~pwE~bw?cxK=G`8> z<5-LO>H4oCl@M6jmqWpn3wg9e-+cF{o^Z%tt>-DY*D5Phi2CfOOCu@an&UXXdVPCD zPA0zQ9x5H$m8I|D+~kb>Jd|ff`S#S58sph2;dy_G2;oPo^u3~}l90A|O}t~&b<)`& zLpfHI`o}{!bIA1Zlo*#z`_7bUvAB$fGcvRKoshs6Fr%HPGe5a1qL3$IIKq)aLw_9Z^v*NG+vjE-(MjkCt`%bf5iI z%RoU{QSjY54XYWzAwVa{i+K30CI??L@-i|hvE>dAAwVJhNN2!Qu5tqsg`k;xcJLz$ z*}Q2%uXlzVL0}*+eMe6xn+mCpc$S_|ieRlo8+e7XdAg;ws4>e+#u1uVO{t7Hf%eAI zU}<$o375Q#bhSn(;pJTN(2zuCF$jyrk;QH`;~X>j?j#Z+7M zU~1pR$oK7EX0oNB_ez8KKf;_dZMKr4?cFnv?=5j8(Z=-Oo)WMQc<6yxRLuLjZJnmZ z+mO-LUwe6^b2Z9S)T|rbkHQcl2s(W8Tcz-#li;62ekk{;;#uA9GZi@L4t?gXk6Yf> zRjFQ#0%h`7ES?rgC_;TZ^fPE}{Hd@tb#1?~<+44(T9I0M@;k=etgu>o9mcB{T(l;y zt7YRjC*CA6C7G-fRBKK4@Vz-bdTxshuVUFY1uJ{ygc9k+Yuy_@U7vl3Sbgf~4;W&n z9Cm;TPe>`!mHg6MxFN6rP2*6fp^fp7ac;%V722fK9}-~2DEwi-3G)GVwHSx*GNn}3I5!)cDnSVrfxin!|lAG5M ztUF+A>MVXz73uTEZaO)xj>&T0p_}NnNl^-|1-EqdR}8&?qVm*6x+!ar%M}=hmo%cZ z37iZ5-dm0CUJ8i7aPtQrxGvj+6c^&Qi;Hs(UKIk#`Fd-C?*p~W+bLR1)6UCxd2k7g zqHVw&2yjv%mxXA|YTvb3Bg~}omiTt^_S;f&_@~X8UVAnpd8e2lq3iE3n?;eN(2P`B zkr0nO<^$;TX6J^eC(ZrwH56(>j7SW)ZLh(_CH+NG3ivtGHi$^m17YP>rl3KFpdoi< zfx1E|JZ%u&UR6!7zj&C!@IHIz-e8giTr0x+ZBOwrW!_u?^$kCmtwX-W{|mkL4@dUD zKpf@d`x`!Z%`!+73v%ic-e%1j`120)_4_zcmOF_VVSfkulF9OFcEWa_1%93Y76$L} zl%|VPrNrKt@r?6)oMx*5$nBb5YS#tmmtpf)=cP22 zQ+x>4Q)q;qwBYBWx}Q;($G`2=<4#7kgnZ_Z20~ZZ9ws5946xsrAcb*dm(yt9#vs8H z7G-U&=eFtUEPFY(>4-StTDfWU3(jPziPpyBJNN;D1q`k~}secB-IdIe9V4CojKFQ591xFoF>8MI72Xr4&CQpN(dy` z@rwP5EKVjwLIHJ4A#XHp!!Ai5ci3pv*dPNjuUM2{xn-X9zSSyE7=bbOcsjZ8Tz7k! zhkrEx*)93Td_8-7(q}BxH@Rkak8q7_#PgqF%?UqwSRQ`8qIualjNqp_*e zA40F9qn)vesk0NM4y)pODN0sVQ+MYVq_53ON%4OjCH{4kdBN05x;sn1OmTKL{Zm(( zjgtKjY5Ij7EX_{I$^Pf`55D&gDEQBHsh8`2K*%rGrPwJs{;2ckl!KDvFRAd$hRP~u zYGPq1Zs-07`O8Mh&CgBA_kz!VVF|x9@&W{QqWp_}-60w~dRP^G{&@tq&e9ZnnSc!o$VK@pm8aaPf2hqZ~I6@89FW!_EH>JNP+y zx&PiC|BEtzx0j!b;~(+h=i>TD-1uL@_BUPF*?Bm*{-(=|jFx4Q_ISB@{$|HZIo|(MKW9fn3u{wH)R&=B#lq9{Pl~fD+u6Mga(@k_FKGEc e82$e>tU5UxIy(P#GqAJsv2k#q($Y#QNc|6sCQQ-* diff --git a/Runtime/Library/Vendor/SerializableDictionary/SerializableDictionary.pdf.meta b/Runtime/Library/Vendor/SerializableDictionary/SerializableDictionary.pdf.meta deleted file mode 100644 index b3b5190..0000000 --- a/Runtime/Library/Vendor/SerializableDictionary/SerializableDictionary.pdf.meta +++ /dev/null @@ -1,8 +0,0 @@ -fileFormatVersion: 2 -guid: 8eb73a56b3a6ee64ab2c30cac8878d8f -timeCreated: 1492869030 -licenseType: Free -DefaultImporter: - userData: - assetBundleName: - assetBundleVariant: diff --git a/Runtime/Library/Vendor/SerializableDictionary/SerializableDictionaryBase.cs b/Runtime/Library/Vendor/SerializableDictionary/SerializableDictionaryBase.cs deleted file mode 100644 index 6e4ac3a..0000000 --- a/Runtime/Library/Vendor/SerializableDictionary/SerializableDictionaryBase.cs +++ /dev/null @@ -1,17 +0,0 @@ -using System.Collections.Generic; -using System.Runtime.Serialization; - -namespace RealMethod -{ - public abstract class SerializableDictionaryBase - { - public abstract class Storage { } - - protected class Dictionary : System.Collections.Generic.Dictionary - { - public Dictionary() { } - public Dictionary(IDictionary dict) : base(dict) { } - public Dictionary(SerializationInfo info, StreamingContext context) : base(info, context) { } - } - } -} \ No newline at end of file diff --git a/Runtime/Library/Vendor/SerializableDictionary/SerializableDictionaryBase.cs.meta b/Runtime/Library/Vendor/SerializableDictionary/SerializableDictionaryBase.cs.meta deleted file mode 100644 index 6585f82..0000000 --- a/Runtime/Library/Vendor/SerializableDictionary/SerializableDictionaryBase.cs.meta +++ /dev/null @@ -1,2 +0,0 @@ -fileFormatVersion: 2 -guid: 3e4c04725aff7c545b5c49a0059c0c48 \ No newline at end of file diff --git a/Runtime/Pattern/Managers/MixerManager.cs b/Runtime/Pattern/Managers/MixerManager.cs index 14dd331..ee9b26e 100644 --- a/Runtime/Pattern/Managers/MixerManager.cs +++ b/Runtime/Pattern/Managers/MixerManager.cs @@ -11,7 +11,7 @@ public abstract class MixerManager : MonoBehaviour, IGameManager private AudioMixer Mixer; public AudioMixer mixer => Mixer; [SerializeField] - private StringFloatDictionary Parameter; + private Map Parameter; // Operators public float this[string name] diff --git a/Runtime/ReadySet/Components/UI/UI_GameSetting.cs b/Runtime/ReadySet/Components/UI/UI_GameSetting.cs index c4241be..569724c 100644 --- a/Runtime/ReadySet/Components/UI/UI_GameSetting.cs +++ b/Runtime/ReadySet/Components/UI/UI_GameSetting.cs @@ -6,7 +6,7 @@ namespace RealMethod { [Serializable] - public class SelectableElement : SerializableDictionary { } + public class SelectableElement : Map { } public interface ISettingStorage : IStorage { bool IsSettingDirty { get; } diff --git a/Runtime/Toolkit/Ability/AbilityController.cs b/Runtime/Toolkit/Ability/AbilityController.cs index 9a16a2d..2a565cc 100644 --- a/Runtime/Toolkit/Ability/AbilityController.cs +++ b/Runtime/Toolkit/Ability/AbilityController.cs @@ -39,7 +39,7 @@ void IAbilityAction.UseInput(InputAction.CallbackContext context) public abstract class AbilityController : MonoBehaviour { [System.Serializable] - private class InputAbility : SerializableDictionary { } + private class InputAbility : Map { } [Header("Setting")] [SerializeField] diff --git a/Runtime/Toolkit/RPG/Resource/ResourceData.cs b/Runtime/Toolkit/RPG/Resource/ResourceData.cs index 98fc907..0fcfe13 100644 --- a/Runtime/Toolkit/RPG/Resource/ResourceData.cs +++ b/Runtime/Toolkit/RPG/Resource/ResourceData.cs @@ -83,7 +83,7 @@ void IConsumableResource.Consume(float amount) public abstract class ResourceData : ResourceData, IResourceData where T : System.Enum { [System.Serializable] - private class StatRatio : SerializableDictionary { } + private class StatRatio : Map { } // Variable [SerializeField, ReadOnly] private float additiveMaxValue = 0; diff --git a/Runtime/Toolkit/RPG/StatSystem/StatProfile.cs b/Runtime/Toolkit/RPG/StatSystem/StatProfile.cs index e72db84..12661a9 100644 --- a/Runtime/Toolkit/RPG/StatSystem/StatProfile.cs +++ b/Runtime/Toolkit/RPG/StatSystem/StatProfile.cs @@ -91,7 +91,7 @@ protected sealed override bool LoadStorage() public abstract class StatProfile : StatProfileStorage, IPrimitiveStatContainer where En : System.Enum where Sd : StatData { [System.Serializable] - private class GameStat : SerializableDictionary { } + private class GameStat : Map { } [Header("Definition")] [SerializeField] private GameStat ChacterStats; From 2e55a438d0f21eb899e2b5c2c5432ba86754f04a Mon Sep 17 00:00:00 2001 From: Alijimpa Date: Mon, 30 Mar 2026 12:47:31 +0330 Subject: [PATCH 059/204] Refine WorldAsset Naming and concept define --- Editor/ReadySet/Content/RealMethod_UnityAsset.cs | 6 +++--- Editor/ReadySet/Content/UnityAsset_Postprocessor.cs | 2 +- Runtime/Core/Architecture/Game.cs | 2 +- Runtime/Core/Architecture/GameBridge.cs | 6 +++--- Runtime/Core/Architecture/GameConfig.cs | 5 ----- Runtime/Core/Architecture/Service.cs | 1 - .../WorldSceneConfig.cs => Definitions/WorldAsset.cs} | 5 ++--- .../WorldAsset.cs.meta} | 0 Runtime/ReadySet/Commands/Execut/C_ScneLoader.cs | 2 +- 9 files changed, 11 insertions(+), 18 deletions(-) rename Runtime/Core/{Architecture/WorldSceneConfig.cs => Definitions/WorldAsset.cs} (93%) rename Runtime/Core/{Architecture/WorldSceneConfig.cs.meta => Definitions/WorldAsset.cs.meta} (100%) diff --git a/Editor/ReadySet/Content/RealMethod_UnityAsset.cs b/Editor/ReadySet/Content/RealMethod_UnityAsset.cs index 98660cb..635a67f 100644 --- a/Editor/ReadySet/Content/RealMethod_UnityAsset.cs +++ b/Editor/ReadySet/Content/RealMethod_UnityAsset.cs @@ -26,7 +26,7 @@ protected override void DoubleClick(TableAsset asset) TableViewerWindow.OpenWindow(asset); } } - public class WorldScene_UnityAsset : AssetProcess + public class WorldAsset_UnityAsset : AssetProcess { protected override void Initialized() { @@ -44,7 +44,7 @@ protected override string GetIconPath() { return "Icons/Core/WorldSceneAsset"; } - protected override void DoubleClick(WorldSceneConfig asset) + protected override void DoubleClick(WorldAsset asset) { asset.OnAssetClick(); } @@ -69,7 +69,7 @@ protected override string GetIconPath() } protected override void DoubleClick(MonoScript asset) { - + } } diff --git a/Editor/ReadySet/Content/UnityAsset_Postprocessor.cs b/Editor/ReadySet/Content/UnityAsset_Postprocessor.cs index bfdbf40..173e2a3 100644 --- a/Editor/ReadySet/Content/UnityAsset_Postprocessor.cs +++ b/Editor/ReadySet/Content/UnityAsset_Postprocessor.cs @@ -7,7 +7,7 @@ public class UnityAsset_Postprocessor : AssetPostprocessor { private static AssetProcess[] AssetList = new AssetProcess[5] { - new WorldScene_UnityAsset(), + new WorldAsset_UnityAsset(), new Table_UnityAsset(), new PCGResource_UnityAsset(), new PCGGeneration_UnityAsset(), diff --git a/Runtime/Core/Architecture/Game.cs b/Runtime/Core/Architecture/Game.cs index 3361f5e..b5b63db 100644 --- a/Runtime/Core/Architecture/Game.cs +++ b/Runtime/Core/Architecture/Game.cs @@ -582,7 +582,7 @@ public static void AddScene(string sceneName, Action callback) ///

/// World scene configuration to load. /// A driving the world load operation, or null if not started. - public static Coroutine OpenWorld(WorldSceneConfig WorldScene) + public static Coroutine OpenWorld(WorldAsset WorldScene) { if (SceneManager.GetActiveScene().buildIndex != SceneManager.GetSceneByPath(WorldScene.Persistent).buildIndex) { diff --git a/Runtime/Core/Architecture/GameBridge.cs b/Runtime/Core/Architecture/GameBridge.cs index fe7a2bc..e8c2491 100644 --- a/Runtime/Core/Architecture/GameBridge.cs +++ b/Runtime/Core/Architecture/GameBridge.cs @@ -315,12 +315,12 @@ public virtual IEnumerator GetAddScneCorotine(int sceneIndex, Action callback) /// /// Starts loading a world configuration using a coroutine. /// - /// The world scene configuration to load. + /// The worldAsset to load. /// /// An IEnumerator coroutine for loading the world, /// or null if a load operation is already in progress. /// - public virtual IEnumerator GetLoadWorldCorotine(WorldSceneConfig WorldScene) + public virtual IEnumerator GetLoadWorldCorotine(WorldAsset WorldScene) { if (isLoading == true) { @@ -427,7 +427,7 @@ private IEnumerator AddSceneAsync(Action callback, string scene, int scneIndex = // Process = 1; callback?.Invoke(); } - private IEnumerator LoadWorldAsync(WorldSceneConfig WS) + private IEnumerator LoadWorldAsync(WorldAsset WS) { //StartLoading isLoading = true; diff --git a/Runtime/Core/Architecture/GameConfig.cs b/Runtime/Core/Architecture/GameConfig.cs index c349a31..3ec9fe0 100644 --- a/Runtime/Core/Architecture/GameConfig.cs +++ b/Runtime/Core/Architecture/GameConfig.cs @@ -1,6 +1,3 @@ - -using UnityEngine; - namespace RealMethod { /// @@ -9,6 +6,4 @@ namespace RealMethod public abstract class GameConfig : ConfigAsset { } - - } \ No newline at end of file diff --git a/Runtime/Core/Architecture/Service.cs b/Runtime/Core/Architecture/Service.cs index 99f5311..d96f2cf 100644 --- a/Runtime/Core/Architecture/Service.cs +++ b/Runtime/Core/Architecture/Service.cs @@ -1,4 +1,3 @@ - namespace RealMethod { /// diff --git a/Runtime/Core/Architecture/WorldSceneConfig.cs b/Runtime/Core/Definitions/WorldAsset.cs similarity index 93% rename from Runtime/Core/Architecture/WorldSceneConfig.cs rename to Runtime/Core/Definitions/WorldAsset.cs index b53e965..6b1da7b 100644 --- a/Runtime/Core/Architecture/WorldSceneConfig.cs +++ b/Runtime/Core/Definitions/WorldAsset.cs @@ -4,15 +4,14 @@ using UnityEditor.SceneManagement; #endif - namespace RealMethod { /// /// ScriptableObject for configuring a world scene setup in Unity. /// Allows specifying a persistent scene and multiple additive layers. /// - [CreateAssetMenu(fileName = "WorldScene", menuName = "Scene/WorldScene", order = 1)] - public class WorldSceneConfig : ConfigAsset + [CreateAssetMenu(fileName = "WorldAsset", menuName = "Scene/World", order = 1)] + public class WorldAsset : UniqueAsset { [Header("Scenes")] /// diff --git a/Runtime/Core/Architecture/WorldSceneConfig.cs.meta b/Runtime/Core/Definitions/WorldAsset.cs.meta similarity index 100% rename from Runtime/Core/Architecture/WorldSceneConfig.cs.meta rename to Runtime/Core/Definitions/WorldAsset.cs.meta diff --git a/Runtime/ReadySet/Commands/Execut/C_ScneLoader.cs b/Runtime/ReadySet/Commands/Execut/C_ScneLoader.cs index 0b364cb..65b1c7b 100644 --- a/Runtime/ReadySet/Commands/Execut/C_ScneLoader.cs +++ b/Runtime/ReadySet/Commands/Execut/C_ScneLoader.cs @@ -24,7 +24,7 @@ private enum LoadMethod [SerializeField, ConditionalShowByEnum("method", 2)] private SceneAsset sceneAsset; [SerializeField, ConditionalShowByEnum("method", 3)] - private WorldSceneConfig worldAsset; + private WorldAsset worldAsset; [Header("Setting")] [SerializeField, ConditionalShowByEnum("method", 0, 1)] private bool IsAsync = false; From 898e790a3fd64d34555f76336ad427716b178a44 Mon Sep 17 00:00:00 2001 From: Alijimpa Date: Mon, 30 Mar 2026 13:04:34 +0330 Subject: [PATCH 060/204] Refine Some Naming and method in Core section --- Editor/Core/Drawers/PrefabCoreDrawer.cs | 47 ------------------------ Editor/Core/Utilities/Editor_Library.cs | 9 +++++ Runtime/Core/Architecture/Game.cs | 48 +++++++++++++++++++++++++ Runtime/Core/Architecture/World.cs | 2 +- 4 files changed, 58 insertions(+), 48 deletions(-) diff --git a/Editor/Core/Drawers/PrefabCoreDrawer.cs b/Editor/Core/Drawers/PrefabCoreDrawer.cs index 9035615..16ad77f 100644 --- a/Editor/Core/Drawers/PrefabCoreDrawer.cs +++ b/Editor/Core/Drawers/PrefabCoreDrawer.cs @@ -74,52 +74,5 @@ public override void OnGUI(Rect position, SerializedProperty property, GUIConten GUI.color = prevColor; EditorGUI.EndProperty(); } - - - - - // --- Utility to get the actual object instance from SerializedProperty --- - // private object GetTargetObjectOfProperty(SerializedProperty prop) - // { - // if (prop == null) return null; - - // string path = prop.propertyPath.Replace(".Array.data[", "["); - // object obj = prop.serializedObject.targetObject; - // string[] elements = path.Split('.'); - - // foreach (string element in elements) - // { - // if (element.Contains("[")) - // { - // string elementName = element.Substring(0, element.IndexOf("[")); - // int index = Convert.ToInt32(element.Substring(element.IndexOf("[")).Replace("[", "").Replace("]", "")); - // obj = GetValue(obj, elementName, index); - // } - // else - // { - // obj = GetValue(obj, element); - // } - // } - // return obj; - // } - // private object GetValue(object source, string name) - // { - // if (source == null) return null; - // var type = source.GetType(); - // var f = type.GetField(name, System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.Public | System.Reflection.BindingFlags.Instance); - // if (f == null) return null; - // return f.GetValue(source); - // } - // private object GetValue(object source, string name, int index) - // { - // var enumerable = GetValue(source, name) as System.Collections.IEnumerable; - // if (enumerable == null) return null; - // var enm = enumerable.GetEnumerator(); - // for (int i = 0; i <= index; i++) - // { - // if (!enm.MoveNext()) return null; - // } - // return enm.Current; - // } } } diff --git a/Editor/Core/Utilities/Editor_Library.cs b/Editor/Core/Utilities/Editor_Library.cs index d4cca11..ae1bae3 100644 --- a/Editor/Core/Utilities/Editor_Library.cs +++ b/Editor/Core/Utilities/Editor_Library.cs @@ -124,6 +124,15 @@ public static GameObject CreatePrefabTemplate(string prefabName, bool UseProject return null; } } + public static string GetScenePathByName(string name) + { + foreach (var scene in EditorBuildSettings.scenes) + { + if (scene.path.Contains(name)) + return scene.path; + } + return null; + } } diff --git a/Runtime/Core/Architecture/Game.cs b/Runtime/Core/Architecture/Game.cs index b5b63db..4f01eb4 100644 --- a/Runtime/Core/Architecture/Game.cs +++ b/Runtime/Core/Architecture/Game.cs @@ -6,6 +6,7 @@ #if UNITY_EDITOR using UnityEditor; +using UnityEditor.SceneManagement; #endif namespace RealMethod @@ -508,12 +509,25 @@ public static Coroutine OpenScene(int sceneIndex) } /// /// Requests a scene load using a . + /// Note: this method work in [Editor]. /// /// Reference describing the scene to load. /// A driving the load operation, or null if not started. public static Coroutine OpenScene(SceneAsset scene) { +#if UNITY_EDITOR + if (!Application.isPlaying) + { + EditorSceneManager.OpenScene(scene.ScenePath, OpenSceneMode.Single); + return null; + } + else + { + return OpenScene(scene.ScneName); + } +#else return OpenScene(scene.ScneName); +#endif } /// /// Requests a scene load by name. @@ -552,12 +566,24 @@ public static void AddScene(int sceneIndex, Action callback) } /// /// Requests a scene load using a . + /// Note: this method work in [Editor]. /// /// Reference describing the scene to load. /// callback event when scene complitly added public static void AddScene(SceneAsset scene, Action callback) { +#if UNITY_EDITOR + if (!Application.isPlaying) + { + EditorSceneManager.OpenScene(scene.ScenePath, OpenSceneMode.Additive); + } + else + { + AddScene(scene.ScneName, callback); + } +#else AddScene(scene.ScneName, callback); +#endif } /// /// Requests a scene load by name. @@ -579,11 +605,31 @@ public static void AddScene(string sceneName, Action callback) /// /// Loads a multi-scene world configuration using the provided . /// If the persistent scene for the world is already loaded, a warning is logged and null is returned. + /// Note: this method work in [Editor]. /// /// World scene configuration to load. /// A driving the world load operation, or null if not started. public static Coroutine OpenWorld(WorldAsset WorldScene) { +#if UNITY_EDITOR + if (!Application.isPlaying) + { + WorldScene.OnAssetClick(); + return null; + } + else + { + if (SceneManager.GetActiveScene().buildIndex != SceneManager.GetSceneByPath(WorldScene.Persistent).buildIndex) + { + return Instance.StartCoroutine(Bridge.GetLoadWorldCorotine(WorldScene)); + } + else + { + Debug.LogWarning("The Persistent Scene is already loaded."); + return null; + } + } +#else if (SceneManager.GetActiveScene().buildIndex != SceneManager.GetSceneByPath(WorldScene.Persistent).buildIndex) { return Instance.StartCoroutine(Bridge.GetLoadWorldCorotine(WorldScene)); @@ -593,6 +639,8 @@ public static Coroutine OpenWorld(WorldAsset WorldScene) Debug.LogWarning("The Persistent Scene is already loaded."); return null; } +#endif + } /// /// Reloads the currently active scene via the configured . diff --git a/Runtime/Core/Architecture/World.cs b/Runtime/Core/Architecture/World.cs index c60464d..a7df731 100644 --- a/Runtime/Core/Architecture/World.cs +++ b/Runtime/Core/Architecture/World.cs @@ -15,7 +15,7 @@ public abstract class PlayerStarter : MonoBehaviour public string PosName => posName; #if UNITY_EDITOR - [Header("Debug")] + [Header("Gizmo")] [SerializeField] private float height = 2f; [SerializeField] From 5afe76385ec88a80146289203fdcbeed72a87873 Mon Sep 17 00:00:00 2001 From: Alijimpa Date: Mon, 30 Mar 2026 22:12:38 +0330 Subject: [PATCH 061/204] Refine Folder Orginazing --- Editor/Core/InitializeOnLoad.meta | 8 ++++++++ .../ConfigAssetInitializer.cs | 0 .../ConfigAssetInitializer.cs.meta | 0 Editor/Core/MenuItem.meta | 8 ++++++++ .../{Attribute => MenuItem}/WorldExecutionOrderMenu.cs | 0 .../WorldExecutionOrderMenu.cs.meta | 0 Editor/Core/{Attribute.meta => ProjectSetting.meta} | 0 .../ProjectSettingProvider.cs | 0 .../ProjectSettingProvider.cs.meta | 0 Editor/Core/{Attribute => ProjectSetting}/Sections.meta | 0 .../Sections/FolderStructure_Section.cs | 0 .../Sections/FolderStructure_Section.cs.meta | 0 .../Sections/GameStatus_Section.cs | 0 .../Sections/GameStatus_Section.cs.meta | 0 .../Sections/InitializerSetting_Section.cs | 0 .../Sections/InitializerSetting_Section.cs.meta | 0 16 files changed, 16 insertions(+) create mode 100644 Editor/Core/InitializeOnLoad.meta rename Editor/Core/{Attribute => InitializeOnLoad}/ConfigAssetInitializer.cs (100%) rename Editor/Core/{Attribute => InitializeOnLoad}/ConfigAssetInitializer.cs.meta (100%) create mode 100644 Editor/Core/MenuItem.meta rename Editor/Core/{Attribute => MenuItem}/WorldExecutionOrderMenu.cs (100%) rename Editor/Core/{Attribute => MenuItem}/WorldExecutionOrderMenu.cs.meta (100%) rename Editor/Core/{Attribute.meta => ProjectSetting.meta} (100%) rename Editor/Core/{Attribute => ProjectSetting}/ProjectSettingProvider.cs (100%) rename Editor/Core/{Attribute => ProjectSetting}/ProjectSettingProvider.cs.meta (100%) rename Editor/Core/{Attribute => ProjectSetting}/Sections.meta (100%) rename Editor/Core/{Attribute => ProjectSetting}/Sections/FolderStructure_Section.cs (100%) rename Editor/Core/{Attribute => ProjectSetting}/Sections/FolderStructure_Section.cs.meta (100%) rename Editor/Core/{Attribute => ProjectSetting}/Sections/GameStatus_Section.cs (100%) rename Editor/Core/{Attribute => ProjectSetting}/Sections/GameStatus_Section.cs.meta (100%) rename Editor/Core/{Attribute => ProjectSetting}/Sections/InitializerSetting_Section.cs (100%) rename Editor/Core/{Attribute => ProjectSetting}/Sections/InitializerSetting_Section.cs.meta (100%) diff --git a/Editor/Core/InitializeOnLoad.meta b/Editor/Core/InitializeOnLoad.meta new file mode 100644 index 0000000..6c8fe82 --- /dev/null +++ b/Editor/Core/InitializeOnLoad.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: efad1f04ce1244c449edfa22bfb8686f +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Editor/Core/Attribute/ConfigAssetInitializer.cs b/Editor/Core/InitializeOnLoad/ConfigAssetInitializer.cs similarity index 100% rename from Editor/Core/Attribute/ConfigAssetInitializer.cs rename to Editor/Core/InitializeOnLoad/ConfigAssetInitializer.cs diff --git a/Editor/Core/Attribute/ConfigAssetInitializer.cs.meta b/Editor/Core/InitializeOnLoad/ConfigAssetInitializer.cs.meta similarity index 100% rename from Editor/Core/Attribute/ConfigAssetInitializer.cs.meta rename to Editor/Core/InitializeOnLoad/ConfigAssetInitializer.cs.meta diff --git a/Editor/Core/MenuItem.meta b/Editor/Core/MenuItem.meta new file mode 100644 index 0000000..0bb4c4d --- /dev/null +++ b/Editor/Core/MenuItem.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: ffc42bc08d097ab468267973c58637fd +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Editor/Core/Attribute/WorldExecutionOrderMenu.cs b/Editor/Core/MenuItem/WorldExecutionOrderMenu.cs similarity index 100% rename from Editor/Core/Attribute/WorldExecutionOrderMenu.cs rename to Editor/Core/MenuItem/WorldExecutionOrderMenu.cs diff --git a/Editor/Core/Attribute/WorldExecutionOrderMenu.cs.meta b/Editor/Core/MenuItem/WorldExecutionOrderMenu.cs.meta similarity index 100% rename from Editor/Core/Attribute/WorldExecutionOrderMenu.cs.meta rename to Editor/Core/MenuItem/WorldExecutionOrderMenu.cs.meta diff --git a/Editor/Core/Attribute.meta b/Editor/Core/ProjectSetting.meta similarity index 100% rename from Editor/Core/Attribute.meta rename to Editor/Core/ProjectSetting.meta diff --git a/Editor/Core/Attribute/ProjectSettingProvider.cs b/Editor/Core/ProjectSetting/ProjectSettingProvider.cs similarity index 100% rename from Editor/Core/Attribute/ProjectSettingProvider.cs rename to Editor/Core/ProjectSetting/ProjectSettingProvider.cs diff --git a/Editor/Core/Attribute/ProjectSettingProvider.cs.meta b/Editor/Core/ProjectSetting/ProjectSettingProvider.cs.meta similarity index 100% rename from Editor/Core/Attribute/ProjectSettingProvider.cs.meta rename to Editor/Core/ProjectSetting/ProjectSettingProvider.cs.meta diff --git a/Editor/Core/Attribute/Sections.meta b/Editor/Core/ProjectSetting/Sections.meta similarity index 100% rename from Editor/Core/Attribute/Sections.meta rename to Editor/Core/ProjectSetting/Sections.meta diff --git a/Editor/Core/Attribute/Sections/FolderStructure_Section.cs b/Editor/Core/ProjectSetting/Sections/FolderStructure_Section.cs similarity index 100% rename from Editor/Core/Attribute/Sections/FolderStructure_Section.cs rename to Editor/Core/ProjectSetting/Sections/FolderStructure_Section.cs diff --git a/Editor/Core/Attribute/Sections/FolderStructure_Section.cs.meta b/Editor/Core/ProjectSetting/Sections/FolderStructure_Section.cs.meta similarity index 100% rename from Editor/Core/Attribute/Sections/FolderStructure_Section.cs.meta rename to Editor/Core/ProjectSetting/Sections/FolderStructure_Section.cs.meta diff --git a/Editor/Core/Attribute/Sections/GameStatus_Section.cs b/Editor/Core/ProjectSetting/Sections/GameStatus_Section.cs similarity index 100% rename from Editor/Core/Attribute/Sections/GameStatus_Section.cs rename to Editor/Core/ProjectSetting/Sections/GameStatus_Section.cs diff --git a/Editor/Core/Attribute/Sections/GameStatus_Section.cs.meta b/Editor/Core/ProjectSetting/Sections/GameStatus_Section.cs.meta similarity index 100% rename from Editor/Core/Attribute/Sections/GameStatus_Section.cs.meta rename to Editor/Core/ProjectSetting/Sections/GameStatus_Section.cs.meta diff --git a/Editor/Core/Attribute/Sections/InitializerSetting_Section.cs b/Editor/Core/ProjectSetting/Sections/InitializerSetting_Section.cs similarity index 100% rename from Editor/Core/Attribute/Sections/InitializerSetting_Section.cs rename to Editor/Core/ProjectSetting/Sections/InitializerSetting_Section.cs diff --git a/Editor/Core/Attribute/Sections/InitializerSetting_Section.cs.meta b/Editor/Core/ProjectSetting/Sections/InitializerSetting_Section.cs.meta similarity index 100% rename from Editor/Core/Attribute/Sections/InitializerSetting_Section.cs.meta rename to Editor/Core/ProjectSetting/Sections/InitializerSetting_Section.cs.meta From 267dab72c8c96c2370f9abe417fff71d0737b117 Mon Sep 17 00:00:00 2001 From: Alijimpa Date: Tue, 31 Mar 2026 12:18:34 +0330 Subject: [PATCH 062/204] Refine Game & GameBridge --- Runtime/Core/Architecture/Game.cs | 11 +- Runtime/Core/Architecture/GameBridge.cs | 84 +++++++++++- Runtime/Library/Extension/GameObject.cs | 126 ++++++++++++++++-- .../Components/Method/SharedObject.cs | 18 +++ .../Components/Method/SharedObject.cs.meta | 2 + 5 files changed, 226 insertions(+), 15 deletions(-) create mode 100644 Runtime/ReadySet/Components/Method/SharedObject.cs create mode 100644 Runtime/ReadySet/Components/Method/SharedObject.cs.meta diff --git a/Runtime/Core/Architecture/Game.cs b/Runtime/Core/Architecture/Game.cs index 4f01eb4..34ddebe 100644 --- a/Runtime/Core/Architecture/Game.cs +++ b/Runtime/Core/Architecture/Game.cs @@ -675,8 +675,10 @@ public static T FindManager() where T : MonoBehaviour /// Parents the provided GameObject to the game root instance. /// /// The GameObject to hold under the game root. - public static void HoldGameObject(GameObject Target) + /// The GameObject name change to new Name for searching. + public static void HoldGameObject(GameObject Target, Name16 TargetName) { + Target.name = TargetName; Target.transform.SetParent(Instance.transform); } /// @@ -685,14 +687,15 @@ public static void HoldGameObject(GameObject Target) /// Name of the child GameObject to find. /// New parent GameObject to assign. /// true if the child was found and reparented; otherwise false. - public static bool TryUnholdGameObject(string GameObjectName, out GameObject result) + public static bool TryUnholdGameObject(Name16 GameObjectName, out GameObject result) { + string TargetName = GameObjectName.ToString(); Transform[] Childs = Instance.GetComponentsInChildren(); foreach (var item in Childs) { - if (item.gameObject.name == GameObjectName) + if (item.gameObject.name == TargetName) { - item.SetParent(null); + item.SetParent(World.transform); result = item.gameObject; return true; } diff --git a/Runtime/Core/Architecture/GameBridge.cs b/Runtime/Core/Architecture/GameBridge.cs index e8c2491..864ab36 100644 --- a/Runtime/Core/Architecture/GameBridge.cs +++ b/Runtime/Core/Architecture/GameBridge.cs @@ -2,6 +2,9 @@ using System.Collections; using UnityEngine; using UnityEngine.SceneManagement; +using System.Collections.Generic; + + #if UNITY_EDITOR using UnityEditor; #endif @@ -107,6 +110,8 @@ public abstract class GameBridge : Service, IRelationBridge, ILoadScneBridge private Action SceneLoadingEvent; private Action SceneLoadingProcessEvent; private bool isLoading; + private List Shareds = new List(5); + private bool IsHolding = false; protected float FadeTime = 0; @@ -193,6 +198,51 @@ event Action ILoadScneBridge.OnSceneLoadingProcess } bool ILoadScneBridge.IsLoading => isLoading; + /// + /// Adds a GameObject to the shared objects collection so it can be accessed or managed globally. + /// + /// GameObject should be always loaded cross scenes + public void AddSharedObject(GameObject obj) + { + if (IsHolding) + { + Debug.LogError("You can't Set Object as Shared in holding time"); + return; + } + Shareds.Add(obj); + obj.transform.SetParent(Game.World.transform); + } + /// + /// Removes a GameObject from the shared objects collection when it is no longer needed or should no longer be shared. + /// + /// GameObject should not be always loaded cross scenes + public void RemoveSharedObject(GameObject obj) + { + if (IsHolding) + { + Debug.LogError("You can't Set Object as Shared in holding time"); + return; + } + Shareds.Remove(obj); + obj.transform.SetParent(null); + } + /// + /// Check is GameObject is in Shared List + /// + /// the target gameobject you want to check + /// Return True when you gameobject is in shared list + public bool IsSharedObject(GameObject obj) + { + foreach (var item in Shareds) + { + if (item == obj) + { + return true; + } + } + return false; + } + /// /// Call this when you want to define new World class to game @@ -211,6 +261,35 @@ protected void SetAdditiveWorld(World world) world.enabled = false; OnAdditiveWorldDetected(world); } + /// + /// Called in loading scene for holding some object to load complitly new scene. + /// With this you can managed some GameObject to active cross scene. + /// + /// Hold in Game class or back to persistance scne + protected void HoldSharedObject(bool active) + { + if (Shareds.Count > 0) + { + if (active) + { + IsHolding = true; + foreach (var item in Shareds) + { + item.transform.SetParent(Game.Instance.transform); + } + } + else + { + foreach (var item in Shareds) + { + item.transform.SetParent(Game.World.transform); + } + IsHolding = false; + } + + } + } + @@ -353,13 +432,13 @@ private float RemapClamped(float value, float inMin, float inMax, float outMin, - // Corotine private IEnumerator LoadSceneAsync(string scene, int scneIndex = -1) { //StartLoading isLoading = true; SceneLoadingEvent?.Invoke(true); + HoldSharedObject(true); float fadingtime = FadeTime; //Fading Screen @@ -400,6 +479,7 @@ private IEnumerator LoadSceneAsync(string scene, int scneIndex = -1) //FinishLoading SceneLoadingEvent?.Invoke(false); + HoldSharedObject(false); isLoading = false; } private IEnumerator AddSceneAsync(Action callback, string scene, int scneIndex = -1) @@ -432,6 +512,7 @@ private IEnumerator LoadWorldAsync(WorldAsset WS) //StartLoading isLoading = true; SceneLoadingEvent?.Invoke(true); + HoldSharedObject(true); float fadingtime = FadeTime; //Fading Screen @@ -457,6 +538,7 @@ private IEnumerator LoadWorldAsync(WorldAsset WS) isLoading = false; yield return null; } + HoldSharedObject(false); // Load Additive Levels for (int i = 0; i < WS.Count; i++) diff --git a/Runtime/Library/Extension/GameObject.cs b/Runtime/Library/Extension/GameObject.cs index a318c55..f82e6a8 100644 --- a/Runtime/Library/Extension/GameObject.cs +++ b/Runtime/Library/Extension/GameObject.cs @@ -7,34 +7,79 @@ namespace RealMethod { + /// + /// Extension methods for the GameObject class to add common functionalities. + /// public static class GameObject_Extension { + /// + /// Attaches this GameObject to a specified parent GameObject, optionally preserving world position. + /// Also sends an "OnAttach" message to the owner GameObject. + /// + /// The GameObject to attach. + /// The GameObject to attach to. + /// If true, the parent-relative position, rotation, and scale are modified so that the last local transformation is equal to the world transformation. public static void Attach(this GameObject owner, GameObject parent, bool worldPositionStays) { owner.transform.SetParent(parent.transform, worldPositionStays); owner.SendAttachEvent(parent); } + /// + /// Detaches this GameObject from its current parent and sends an "OnDetach" message. + /// + /// The GameObject to detach. + /// The parent GameObject it was attached to (primarily for context, not used in the current implementation). public static void Detach(this GameObject owner, GameObject parent) { owner.transform.SetParent(null); owner.SendDetachEvent(); } + /// + /// Sends an "OnAttach" message to the owner GameObject. + /// + /// The GameObject to send the message to. + /// The object that triggered the attach event (passed as parameter to the message). + /// Specifies whether the message must be received, or if it is optional. public static void SendAttachEvent(this GameObject owner, Object spawner, SendMessageOptions option = SendMessageOptions.RequireReceiver) { owner.SendMessage("OnAttach", spawner, option); } + /// + /// Sends an "OnDetach" message to the owner GameObject. + /// + /// The GameObject to send the message to. + /// Specifies whether the message must be received, or if it is optional. public static void SendDetachEvent(this GameObject owner, SendMessageOptions option = SendMessageOptions.RequireReceiver) { owner.SendMessage("OnDetach", option); } + /// + /// Sends an "OnSpawn" message to the owner GameObject. + /// + /// The GameObject to send the message to. + /// The object that triggered the spawn event (passed as parameter to the message). + /// Specifies whether the message must be received, or if it is optional. public static void SendSpawnEvent(this GameObject owner, Object spawner, SendMessageOptions option = SendMessageOptions.RequireReceiver) { owner.SendMessage("OnSpawn", spawner, option); } + /// + /// Sends an "OnDespawn" message to the owner GameObject. + /// + /// The GameObject to send the message to. + /// The object that triggered the despawn event (passed as parameter to the message). + /// Specifies whether the message must be received, or if it is optional. public static void SendDespawnEvent(this GameObject owner, Object despawner, SendMessageOptions option = SendMessageOptions.RequireReceiver) { owner.SendMessage("OnDespawn", despawner, option); } + /// + /// Adds a new component of type TComponent to the GameObject and initializes it without arguments. + /// + /// The type of the component to add, must inherit from MonoBehaviour and IInitializable. + /// This type parameter is unused in this overload. + /// The GameObject to add the component to. + /// The newly added and initialized component. public static TComponent AddComponent(this GameObject gameObject) where TComponent : MonoBehaviour, IInitializable { @@ -42,6 +87,14 @@ public static TComponent AddComponent(this GameObject gam component.Initialize(); return component; } + /// + /// Adds a new component of type TComponent to the GameObject and initializes it with a single argument. + /// + /// The type of the component to add, must inherit from MonoBehaviour and IInitializableWithArgument. + /// The type of the argument used for initialization. + /// The GameObject to add the component to. + /// The argument to pass to the component's Initialize method. + /// The newly added and initialized component. public static TComponent AddComponent(this GameObject gameObject, TArgument argument) where TComponent : MonoBehaviour, IInitializableWithArgument { @@ -49,6 +102,16 @@ public static TComponent AddComponent(this GameObject gam component.Initialize(argument); return component; } + /// + /// Adds a new component of type TComponent to the GameObject and initializes it with two arguments. + /// + /// The type of the component to add, must inherit from MonoBehaviour and IInitializableWithTwoArgument. + /// The type of the first argument used for initialization. + /// The type of the second argument used for initialization. + /// The GameObject to add the component to. + /// The first argument to pass to the component's Initialize method. + /// The second argument to pass to the component's Initialize method. + /// The newly added and initialized component. public static TComponent AddComponent(this GameObject gameObject, TArgumentA argumentA, TArgumentB argumentB) where TComponent : MonoBehaviour, IInitializableWithTwoArgument { @@ -56,6 +119,13 @@ public static TComponent AddComponent(this G component.Initialize(argumentA, argumentB); return component; } + /// + /// Copies all public fields from an original component to a new component of the same type on a destination GameObject. + /// + /// The type of the component to copy. Must inherit from Component. + /// The GameObject to add the copied component to. + /// The component to copy from. + /// The newly created and populated component on the destination GameObject. public static TComponent CopyComponent(this GameObject desitation, TComponent originalComponent) where TComponent : Component { System.Type componentType = originalComponent.GetType(); @@ -67,33 +137,69 @@ public static TComponent CopyComponent(this GameObject desitation, T } return copy as TComponent; } - -#if UNITY_EDITOR + /// + /// Checks if a GameObject is a valid scene object (not a prefab asset, and belongs to a scene). + /// This method's behavior differs slightly between Editor and runtime. + /// + /// The GameObject to check. + /// True if the GameObject is in a scene, false otherwise. public static bool IsInScene(this GameObject obj) { +#if UNITY_EDITOR return PrefabUtility.GetPrefabAssetType(obj) == PrefabAssetType.NotAPrefab - && obj.scene.IsValid(); - } + && obj.scene.IsValid(); #else - public static bool IsInScene(this GameObject obj) - { return obj.scene.IsValid() && obj.scene.name != null; - } #endif + } + /// + /// Registers the GameObject with a shared object system. + /// + /// The GameObject to register. + public static void Share(this GameObject obj) + { + Game.Bridge.AddSharedObject(obj); + } + /// + /// Unregisters the GameObject from the shared object system. + /// + /// The GameObject to unregister. + public static void Unshare(this GameObject obj) + { + Game.Bridge.RemoveSharedObject(obj); + } + /// + /// Checks if the GameObject is currently registered in the shared object system. + /// + /// The GameObject to check. + /// True if the GameObject is shared, false otherwise. + public static bool IsShared(this GameObject obj) + { + return Game.Bridge.IsSharedObject(obj); + } + + #if UNITY_EDITOR + /// + /// Checks if the GameObject is a prefab asset itself (not an instance of a prefab). + /// + /// The GameObject to check. + /// True if it's a prefab asset, false otherwise. public static bool IsPrefabAsset(this GameObject obj) { return PrefabUtility.GetPrefabAssetType(obj) != PrefabAssetType.NotAPrefab && PrefabUtility.GetPrefabInstanceStatus(obj) == PrefabInstanceStatus.NotAPrefab; } + /// + /// Checks if the GameObject is an instance of a connected prefab. + /// + /// The GameObject to check. + /// True if it's a connected prefab instance, false otherwise. public static bool IsPrefabInstance(this GameObject obj) { return PrefabUtility.GetPrefabInstanceStatus(obj) == PrefabInstanceStatus.Connected; } #endif - - - } } \ No newline at end of file diff --git a/Runtime/ReadySet/Components/Method/SharedObject.cs b/Runtime/ReadySet/Components/Method/SharedObject.cs new file mode 100644 index 0000000..83ff717 --- /dev/null +++ b/Runtime/ReadySet/Components/Method/SharedObject.cs @@ -0,0 +1,18 @@ +using UnityEngine; + +namespace RealMethod +{ + [AddComponentMenu("RealMethod/Method/SharedObject")] + public sealed class SharedObject : MonoBehaviour + { + private void OnEnable() + { + gameObject.Share(); + } + + private void OnDisable() + { + gameObject.Unshare(); + } + } +} \ No newline at end of file diff --git a/Runtime/ReadySet/Components/Method/SharedObject.cs.meta b/Runtime/ReadySet/Components/Method/SharedObject.cs.meta new file mode 100644 index 0000000..3c8faf4 --- /dev/null +++ b/Runtime/ReadySet/Components/Method/SharedObject.cs.meta @@ -0,0 +1,2 @@ +fileFormatVersion: 2 +guid: 4c9371d81fcc7de44945374996c4ce62 \ No newline at end of file From 64f0558dfdce24fc758772afbd6b26ac85035ed4 Mon Sep 17 00:00:00 2001 From: Alijimpa Date: Wed, 1 Apr 2026 08:13:22 +0330 Subject: [PATCH 063/204] Refine Library forlder and Hictionary script --- Editor/Library/{Vendor.meta => MenuItem.meta} | 2 +- .../EditorIcons.cs | 0 .../EditorIcons.cs.meta | 0 Editor/Library/Vendor/UnityEditorIcons.meta | 8 - Runtime/Library/Extension/Animator.cs | 11 +- Runtime/Library/Extension/Array.cs | 19 ++- Runtime/Library/Extension/Dictionary.cs | 1 - Runtime/Library/Extension/Transform.cs | 2 +- .../SharedScripts/Classes/Hictionary.cs | 138 ++++++++++++++++++ .../{Structs => Classes}/Hictionary.cs.meta | 0 .../SharedScripts/Structs/Hictionary.cs | 92 ------------ .../Library/SharedScripts/Structs/TName.cs | 1 - Runtime/Library/Utilities/Array_Library.cs | 18 +++ .../Library/Utilities/Array_Library.cs.meta | 2 + Runtime/Pattern/Managers/CompositManager.cs | 2 +- Runtime/Pattern/Managers/UIManager.cs | 4 +- Runtime/Pattern/Services/RuleService.cs | 10 +- Runtime/Toolkit/Inventory/Inventory.cs | 9 +- 18 files changed, 193 insertions(+), 126 deletions(-) rename Editor/Library/{Vendor.meta => MenuItem.meta} (77%) rename Editor/Library/{Vendor/UnityEditorIcons => MenuItem}/EditorIcons.cs (100%) rename Editor/Library/{Vendor/UnityEditorIcons => MenuItem}/EditorIcons.cs.meta (100%) delete mode 100644 Editor/Library/Vendor/UnityEditorIcons.meta create mode 100644 Runtime/Library/SharedScripts/Classes/Hictionary.cs rename Runtime/Library/SharedScripts/{Structs => Classes}/Hictionary.cs.meta (100%) delete mode 100644 Runtime/Library/SharedScripts/Structs/Hictionary.cs create mode 100644 Runtime/Library/Utilities/Array_Library.cs create mode 100644 Runtime/Library/Utilities/Array_Library.cs.meta diff --git a/Editor/Library/Vendor.meta b/Editor/Library/MenuItem.meta similarity index 77% rename from Editor/Library/Vendor.meta rename to Editor/Library/MenuItem.meta index 95cd04e..528bfd2 100644 --- a/Editor/Library/Vendor.meta +++ b/Editor/Library/MenuItem.meta @@ -1,5 +1,5 @@ fileFormatVersion: 2 -guid: b6449ef571a85534abe38c8766ce2b2c +guid: c42de7ea7ccb8124c81a1cca94b15c47 folderAsset: yes DefaultImporter: externalObjects: {} diff --git a/Editor/Library/Vendor/UnityEditorIcons/EditorIcons.cs b/Editor/Library/MenuItem/EditorIcons.cs similarity index 100% rename from Editor/Library/Vendor/UnityEditorIcons/EditorIcons.cs rename to Editor/Library/MenuItem/EditorIcons.cs diff --git a/Editor/Library/Vendor/UnityEditorIcons/EditorIcons.cs.meta b/Editor/Library/MenuItem/EditorIcons.cs.meta similarity index 100% rename from Editor/Library/Vendor/UnityEditorIcons/EditorIcons.cs.meta rename to Editor/Library/MenuItem/EditorIcons.cs.meta diff --git a/Editor/Library/Vendor/UnityEditorIcons.meta b/Editor/Library/Vendor/UnityEditorIcons.meta deleted file mode 100644 index 5a74db5..0000000 --- a/Editor/Library/Vendor/UnityEditorIcons.meta +++ /dev/null @@ -1,8 +0,0 @@ -fileFormatVersion: 2 -guid: b053aa00d882df041a089f1bd0dffd26 -folderAsset: yes -DefaultImporter: - externalObjects: {} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Runtime/Library/Extension/Animator.cs b/Runtime/Library/Extension/Animator.cs index caa71aa..c06af73 100644 --- a/Runtime/Library/Extension/Animator.cs +++ b/Runtime/Library/Extension/Animator.cs @@ -4,19 +4,18 @@ namespace RealMethod { public static class Animator_Extension { - public static Coroutine PlayAndNotify(this Animator animator, string stateName, System.Action onFinished, int layer = 0) + public static Coroutine Play(this Animator animator, string stateName, System.Action onFinished, int layer = 0) { animator.Play(stateName, layer); // Start a coroutine to watch for finish var runner = animator.GetComponent(); if (runner == null) { - Debug.LogWarning("For Use PlayAndNotify you need to a MonoBehaviour for running Cortine for Finish Callback"); + Debug.LogWarning("For Use Play you need to a MonoBehaviour for running Cortine for Finish Callback"); return null; } return runner.StartCoroutine(RM_Animation.WaitForState(animator, layer, stateName, onFinished)); } - /// /// Checks if the Animator is currently playing a specific state. /// @@ -25,7 +24,6 @@ public static bool IsPlaying(this Animator animator, string stateName, int layer var info = animator.GetCurrentAnimatorStateInfo(layer); return info.IsName(stateName) && info.normalizedTime < 1f; } - /// /// Checks if the Animator is in a specific state (finished or still playing). /// @@ -33,7 +31,6 @@ public static bool IsInState(this Animator animator, string stateName, int layer { return animator.GetCurrentAnimatorStateInfo(layer).IsName(stateName); } - /// /// Returns the normalized progress of the current animation state (0 → 1). /// @@ -41,7 +38,6 @@ public static float GetProgress(this Animator animator, int layer = 0) { return animator.GetCurrentAnimatorStateInfo(layer).normalizedTime; } - /// /// Safely sets a trigger (resets it first to avoid stuck transitions). /// @@ -50,7 +46,6 @@ public static void SetTriggerSafe(this Animator animator, string triggerName) animator.ResetTrigger(triggerName); animator.SetTrigger(triggerName); } - /// /// Immediately stops all animations and plays the given state. /// @@ -59,7 +54,6 @@ public static void ForcePlay(this Animator animator, string stateName, int layer animator.Play(stateName, layer, normalizedTime); animator.Update(0f); // force immediate update so the state is applied instantly } - /// /// Checks if the current state is about to end (useful for chaining combos). /// @@ -68,7 +62,6 @@ public static bool IsNearEnd(this Animator animator, float threshold = 0.9f, int var info = animator.GetCurrentAnimatorStateInfo(layer); return info.normalizedTime >= threshold && !info.loop; } - /// /// Crossfades safely only if the target state isn’t already playing. /// diff --git a/Runtime/Library/Extension/Array.cs b/Runtime/Library/Extension/Array.cs index 68a5424..d594a0a 100644 --- a/Runtime/Library/Extension/Array.cs +++ b/Runtime/Library/Extension/Array.cs @@ -4,7 +4,6 @@ namespace RealMethod { public static class Array_Extension { - // Extention public static bool IsValidIndex(this Array array, int index) { return index >= 0 && index < array.Length; @@ -51,6 +50,24 @@ public static int Sum(this int[] array) } return sum; } + /// + /// Appends two arrays into a new combined array. + /// + /// The element type of the arrays. + /// The first array. + /// The second array. + /// A new array containing elements of both arrays. + public static T[] CombineWith(this T[] first, T[] second) + { + if (first == null) return second; + if (second == null) return first; + + T[] result = new T[first.Length + second.Length]; + Array.Copy(first, 0, result, 0, first.Length); + Array.Copy(second, 0, result, first.Length, second.Length); + + return result; + } } } \ No newline at end of file diff --git a/Runtime/Library/Extension/Dictionary.cs b/Runtime/Library/Extension/Dictionary.cs index 73e632b..e4fe1b4 100644 --- a/Runtime/Library/Extension/Dictionary.cs +++ b/Runtime/Library/Extension/Dictionary.cs @@ -4,7 +4,6 @@ namespace RealMethod { - public static class Dictionary_Extension { public static Tk GetKey(this Dictionary DataBase, int index) diff --git a/Runtime/Library/Extension/Transform.cs b/Runtime/Library/Extension/Transform.cs index d4c4f7a..57d5c43 100644 --- a/Runtime/Library/Extension/Transform.cs +++ b/Runtime/Library/Extension/Transform.cs @@ -10,7 +10,7 @@ public static void SetTransform(this Transform trans, Transform newtransform) trans.rotation = newtransform.rotation; trans.localScale = newtransform.localScale; } - public static Transform FindSocket(this Transform trans, string socketname) + public static Transform FindSocket(this Transform trans, Name16 socketname) { foreach (var item in trans.GetComponentsInChildren()) { diff --git a/Runtime/Library/SharedScripts/Classes/Hictionary.cs b/Runtime/Library/SharedScripts/Classes/Hictionary.cs new file mode 100644 index 0000000..a6cb4b5 --- /dev/null +++ b/Runtime/Library/SharedScripts/Classes/Hictionary.cs @@ -0,0 +1,138 @@ +using UnityEngine; +using System.Collections; +using System.Collections.Generic; + + +namespace RealMethod +{ + /// + /// A dictionary keyed by string but internally hashes each key using . + /// Provides stable lookups and near-zero collision risk. + /// + public class Hictionary : IEnumerable> + { + private Dictionary list; + private static int GlobalIdCounter; + private int InstanceId; + + + /// + /// Gets the number of entries. + /// + public int Count => list?.Count ?? 0; + public bool IsValid => list != null; + /// + /// Gets all stored keys. + /// + public ICollection Keys + { + get + { + List keys = new(); + foreach (var k in list.Keys) + keys.Add(k.ToString()); + return keys; + } + } + /// + /// Gets all stored values. + /// + public IEnumerable Values + { + get + { + return list.Values; + } + } + public bool IsReadOnly => false; + + + public Hictionary(int prewarm = 10) + { + InstanceId = ++GlobalIdCounter; + list = new Dictionary(prewarm); + } + + + // Indexer + public T this[string name] + { + get => list[Key(name)]; + set => list[Key(name)] = value; + } + + // Implement IEnumerable Interface + public IEnumerator> GetEnumerator() + { + return list.GetEnumerator(); + } + IEnumerator IEnumerable.GetEnumerator() + { + return GetEnumerator(); + } + + + // Functions + public bool ContainsKey(string name) + { + return list.ContainsKey(Key(name)); + } + public bool TryGetValue(string name, out T value) + { + return list.TryGetValue(Key(name), out value); + } + /// + /// Adds or replaces an entry by name. + /// + public void Add(string name, T value) + { + list.Add(Key(name), value); + } + public bool TryAdd(string name, T value) + { + return list.TryAdd(Key(name), value); + } + /// + /// Removes an entry by name. + /// + public bool Remove(string name) + { + return list.Remove(Key(name)); + } + /// + /// Removes all entries. + /// + public void Clear() + { + list.Clear(); + } + public string[] GetKeys() + { + int c = list.Count; + string[] result = new string[c]; + + int i = 0; + foreach (var kvp in list) + result[i++] = kvp.Key.ToString(); + + return result; + } + + public string Find(T value) + { + foreach (var kvp in list) + { + if (EqualityComparer.Default.Equals(kvp.Value, value)) + return kvp.Key.ToString(); + } + + return null; + } + + + /// + /// Computes a stable 128-bit key from a string. + /// + private Hash128 Key(string name) => Hash128.Compute(name); + } +} \ No newline at end of file diff --git a/Runtime/Library/SharedScripts/Structs/Hictionary.cs.meta b/Runtime/Library/SharedScripts/Classes/Hictionary.cs.meta similarity index 100% rename from Runtime/Library/SharedScripts/Structs/Hictionary.cs.meta rename to Runtime/Library/SharedScripts/Classes/Hictionary.cs.meta diff --git a/Runtime/Library/SharedScripts/Structs/Hictionary.cs b/Runtime/Library/SharedScripts/Structs/Hictionary.cs deleted file mode 100644 index feb2ffb..0000000 --- a/Runtime/Library/SharedScripts/Structs/Hictionary.cs +++ /dev/null @@ -1,92 +0,0 @@ -using UnityEngine; -using System.Collections.Generic; -using System.Collections; - - -namespace RealMethod -{ - public struct Hictionary //: IEnumerable> - { - private Dictionary List; - public int Count => List.Count; - - - public Hictionary(int Prewarm) - { - List = new Dictionary(Prewarm); - } - - // Access values - public T this[string Name] - { - get => List[Hash128.Compute(Name)]; - set => List[Hash128.Compute(Name)] = value; - } - - public bool IsValid() - { - return List != null; - } - public bool ContainsKey(string Name) - { - return List.ContainsKey(Hash128.Compute(Name)); - } - public void Add(string Name, T Value) - { - List.Add(Hash128.Compute(Name), Value); - } - public bool Remove(string Name) - { - return List.Remove(Hash128.Compute(Name)); - } - public bool TryGetValue(string Name, out T Result) - { - return List.TryGetValue(Hash128.Compute(Name), out Result); - } - public string[] GetKeys() - { - var keys = new List(List.Keys); - string[] result = new string[keys.Count]; - for (int i = 0; i < keys.Count; i++) - { - result[i] = keys[i].ToString(); - } - return result; - } - public T[] GetValues() - { - return new List(List.Values).ToArray(); - } - public void Clear() - { - List.Clear(); - } - public string Find(T value) - { - foreach (var dictionary in List) - { - if (EqualityComparer.Default.Equals(dictionary.Value, value)) - { - return dictionary.Key.ToString(); - } - } - return null; - } - public bool TryAdd(string Name, T Value) - { - return List.TryAdd(Hash128.Compute(Name), Value); - } - - // // Implement IEnumerable> - // public IEnumerator> GetEnumerator() - // { - // return List.GetEnumerator(); // Delegates to the internal dictionary - // } - - // // Non-generic IEnumerable - // IEnumerator IEnumerable.GetEnumerator() - // { - // return GetEnumerator(); - // } - } -} \ No newline at end of file diff --git a/Runtime/Library/SharedScripts/Structs/TName.cs b/Runtime/Library/SharedScripts/Structs/TName.cs index 53ed6d1..69549c5 100644 --- a/Runtime/Library/SharedScripts/Structs/TName.cs +++ b/Runtime/Library/SharedScripts/Structs/TName.cs @@ -1,5 +1,4 @@ using System; -using UnityEngine; using System.Collections.Generic; namespace RealMethod diff --git a/Runtime/Library/Utilities/Array_Library.cs b/Runtime/Library/Utilities/Array_Library.cs new file mode 100644 index 0000000..16dd017 --- /dev/null +++ b/Runtime/Library/Utilities/Array_Library.cs @@ -0,0 +1,18 @@ +using System; + +namespace RealMethod +{ + public static class RM_Array + { + public static T[] Append(T[] a, T[] b) + { + if (a == null) return b; + if (b == null) return a; + + T[] result = new T[a.Length + b.Length]; + Array.Copy(a, result, a.Length); + Array.Copy(b, 0, result, a.Length, b.Length); + return result; + } + } +} \ No newline at end of file diff --git a/Runtime/Library/Utilities/Array_Library.cs.meta b/Runtime/Library/Utilities/Array_Library.cs.meta new file mode 100644 index 0000000..0f6a957 --- /dev/null +++ b/Runtime/Library/Utilities/Array_Library.cs.meta @@ -0,0 +1,2 @@ +fileFormatVersion: 2 +guid: 28c869befe42f604087bb85ebccdccd8 \ No newline at end of file diff --git a/Runtime/Pattern/Managers/CompositManager.cs b/Runtime/Pattern/Managers/CompositManager.cs index 1c7651c..5929a19 100644 --- a/Runtime/Pattern/Managers/CompositManager.cs +++ b/Runtime/Pattern/Managers/CompositManager.cs @@ -223,7 +223,7 @@ public MusicLerp CreateLerp(string LayerA, string LayerB) } public AudioBehaviour[] GetLayers() { - return Layers.GetValues().ToArray(); + return Layers.Values.ToArray(); } // Protected Functions diff --git a/Runtime/Pattern/Managers/UIManager.cs b/Runtime/Pattern/Managers/UIManager.cs index 921aa86..e445057 100644 --- a/Runtime/Pattern/Managers/UIManager.cs +++ b/Runtime/Pattern/Managers/UIManager.cs @@ -528,9 +528,9 @@ public T FindClassInLayers() where T : class { T Reslut = null; IWidget TargetWidget; - foreach (var Lay in Layers.GetValues()) + foreach (var Lay in Layers) { - TargetWidget = Lay.GetComponent(); + TargetWidget = Lay.Value.GetComponent(); if (TargetWidget == null) { continue; diff --git a/Runtime/Pattern/Services/RuleService.cs b/Runtime/Pattern/Services/RuleService.cs index 69f5a67..0e42d9f 100644 --- a/Runtime/Pattern/Services/RuleService.cs +++ b/Runtime/Pattern/Services/RuleService.cs @@ -13,11 +13,11 @@ public RuleService() Rules = new Hictionary>(5); } - protected override void OnWorldChanging(World Previous , World New) + protected override void OnWorldChanging(World Previous, World New) { - foreach (var item in Rules.GetValues()) + foreach (var item in Rules) { - item.Check(); + item.Value.Check(); } } @@ -37,9 +37,9 @@ public void Check(string rule) } public void UpdateRules() { - foreach (Observer item in Rules.GetValues()) + foreach (var item in Rules) { - item.Check(); + item.Value.Check(); } } public bool InEffect(string rule) diff --git a/Runtime/Toolkit/Inventory/Inventory.cs b/Runtime/Toolkit/Inventory/Inventory.cs index b2dd96f..9778acf 100644 --- a/Runtime/Toolkit/Inventory/Inventory.cs +++ b/Runtime/Toolkit/Inventory/Inventory.cs @@ -1,4 +1,5 @@ using System.Collections.Generic; +using System.Linq; using UnityEngine; namespace RealMethod @@ -111,7 +112,7 @@ private enum BehaviorType // Private Variable private Hictionary Items; - public int Count => Items.IsValid() ? Items.Count : 0; + public int Count => Items.IsValid ? Items.Count : 0; protected IInventoryStorage inventoryStorage { get; private set; } @@ -351,7 +352,7 @@ public bool DeleteItem(IInventoryItem item) public T[] CopyItemsByClass() where T : IInventoryItem { List Result = new List(); - foreach (var pack in Items.GetValues()) + foreach (var pack in Items.Values) { if (pack.provider is T finditem) { @@ -369,9 +370,9 @@ public void Clear() // Protected Functions protected InventoryItemProperty[] GetCopyItemsProperty() { - var values = Items.GetValues(); + var values = Items.Values; var copy = new InventoryItemProperty[Items.Count]; - values.CopyTo(copy, 0); + values.ToArray().CopyTo(copy, 0); return copy; } From e080665d660a56dd7cae7df26de29ca6f218020c Mon Sep 17 00:00:00 2001 From: Alijimpa Date: Wed, 1 Apr 2026 09:37:43 +0330 Subject: [PATCH 064/204] Rename Hictionary --- .../Classes/{Hictionary.cs => NameTable.cs} | 4 ++-- .../{Hictionary.cs.meta => NameTable.cs.meta} | 0 .../Structs/{TName.cs => UniqueName.cs} | 18 +++++++++--------- .../{TName.cs.meta => UniqueName.cs.meta} | 0 Runtime/Pattern/Components/WidgetToolkit.cs | 4 ++-- Runtime/Pattern/Managers/CompositManager.cs | 2 +- Runtime/Pattern/Managers/UIManager.cs | 2 +- Runtime/Pattern/Services/RuleService.cs | 4 ++-- Runtime/ReadySet/Services/TimeService.cs | 4 ++-- Runtime/Toolkit/Inventory/Inventory.cs | 8 ++++---- 10 files changed, 23 insertions(+), 23 deletions(-) rename Runtime/Library/SharedScripts/Classes/{Hictionary.cs => NameTable.cs} (96%) rename Runtime/Library/SharedScripts/Classes/{Hictionary.cs.meta => NameTable.cs.meta} (100%) rename Runtime/Library/SharedScripts/Structs/{TName.cs => UniqueName.cs} (88%) rename Runtime/Library/SharedScripts/Structs/{TName.cs.meta => UniqueName.cs.meta} (100%) diff --git a/Runtime/Library/SharedScripts/Classes/Hictionary.cs b/Runtime/Library/SharedScripts/Classes/NameTable.cs similarity index 96% rename from Runtime/Library/SharedScripts/Classes/Hictionary.cs rename to Runtime/Library/SharedScripts/Classes/NameTable.cs index a6cb4b5..dd092ce 100644 --- a/Runtime/Library/SharedScripts/Classes/Hictionary.cs +++ b/Runtime/Library/SharedScripts/Classes/NameTable.cs @@ -9,7 +9,7 @@ namespace RealMethod /// A dictionary keyed by string but internally hashes each key using . /// Provides stable lookups and near-zero collision risk. /// - public class Hictionary : IEnumerable> + public class NameTable : IEnumerable> { private Dictionary list; private static int GlobalIdCounter; @@ -47,7 +47,7 @@ public IEnumerable Values public bool IsReadOnly => false; - public Hictionary(int prewarm = 10) + public NameTable(int prewarm = 10) { InstanceId = ++GlobalIdCounter; list = new Dictionary(prewarm); diff --git a/Runtime/Library/SharedScripts/Classes/Hictionary.cs.meta b/Runtime/Library/SharedScripts/Classes/NameTable.cs.meta similarity index 100% rename from Runtime/Library/SharedScripts/Classes/Hictionary.cs.meta rename to Runtime/Library/SharedScripts/Classes/NameTable.cs.meta diff --git a/Runtime/Library/SharedScripts/Structs/TName.cs b/Runtime/Library/SharedScripts/Structs/UniqueName.cs similarity index 88% rename from Runtime/Library/SharedScripts/Structs/TName.cs rename to Runtime/Library/SharedScripts/Structs/UniqueName.cs index 69549c5..c73aa3d 100644 --- a/Runtime/Library/SharedScripts/Structs/TName.cs +++ b/Runtime/Library/SharedScripts/Structs/UniqueName.cs @@ -8,7 +8,7 @@ namespace RealMethod /// Lightweight engine-style string identifier. /// Stores only an integer ID while the actual strings live in a global table. /// - public struct TName : IEquatable + public struct UniqueName : IEquatable { /// /// Maximum allowed characters for a name. @@ -35,7 +35,7 @@ public struct TName : IEquatable /// /// Creates a Name from a string. /// - public TName(string value) + public UniqueName(string value) { id = GetOrCreateId(value); } @@ -98,7 +98,7 @@ public static string GetString(int id) /// /// Checks equality with another Name. /// - public bool Equals(TName other) + public bool Equals(UniqueName other) { return id == other.id; } @@ -119,7 +119,7 @@ public override string ToString() /// public override bool Equals(object obj) { - return obj is TName other && Equals(other); + return obj is UniqueName other && Equals(other); } /// /// Hash code of the Name. @@ -135,15 +135,15 @@ public override int GetHashCode() /// /// Implicit conversion from string. /// - public static implicit operator TName(string value) + public static implicit operator UniqueName(string value) { - return new TName(value); + return new UniqueName(value); } /// /// Implicit conversion to string. /// - public static implicit operator string(TName name) + public static implicit operator string(UniqueName name) { return GetString(name.id); } @@ -151,7 +151,7 @@ public static implicit operator string(TName name) /// /// Equality operator. /// - public static bool operator ==(TName a, TName b) + public static bool operator ==(UniqueName a, UniqueName b) { return a.id == b.id; } @@ -159,7 +159,7 @@ public static implicit operator string(TName name) /// /// Inequality operator. /// - public static bool operator !=(TName a, TName b) + public static bool operator !=(UniqueName a, UniqueName b) { return a.id != b.id; } diff --git a/Runtime/Library/SharedScripts/Structs/TName.cs.meta b/Runtime/Library/SharedScripts/Structs/UniqueName.cs.meta similarity index 100% rename from Runtime/Library/SharedScripts/Structs/TName.cs.meta rename to Runtime/Library/SharedScripts/Structs/UniqueName.cs.meta diff --git a/Runtime/Pattern/Components/WidgetToolkit.cs b/Runtime/Pattern/Components/WidgetToolkit.cs index 967e9c7..70ca721 100644 --- a/Runtime/Pattern/Components/WidgetToolkit.cs +++ b/Runtime/Pattern/Components/WidgetToolkit.cs @@ -12,7 +12,7 @@ public abstract class WidgetToolkit : MonoBehaviour, IWidget public UIDocument Design { get; private set; } public VisualElement Canvas => Design.rootVisualElement; - protected Hictionary Pages; + protected NameTable Pages; public VisualElement this[string Name] @@ -32,7 +32,7 @@ void IWidget.SceneInitialized(UIManager manager) Design = GetComponent(); - Pages = new Hictionary(); + Pages = new NameTable(); List allElement = Canvas.Query().ToList(); foreach (var ElmName in PageNames) { diff --git a/Runtime/Pattern/Managers/CompositManager.cs b/Runtime/Pattern/Managers/CompositManager.cs index 5929a19..12e8220 100644 --- a/Runtime/Pattern/Managers/CompositManager.cs +++ b/Runtime/Pattern/Managers/CompositManager.cs @@ -35,7 +35,7 @@ public void Pitch(float alpha, float minPitch = -3f, float maxPitch = 3f) [SerializeField] private AudioMixerGroup DefaultGroup; - private Hictionary Layers = new Hictionary(5); + private NameTable Layers = new NameTable(5); public int LayerCount => Layers.Count; // Public Functions diff --git a/Runtime/Pattern/Managers/UIManager.cs b/Runtime/Pattern/Managers/UIManager.cs index e445057..acd1417 100644 --- a/Runtime/Pattern/Managers/UIManager.cs +++ b/Runtime/Pattern/Managers/UIManager.cs @@ -30,7 +30,7 @@ public enum UIMethod public System.Action OnFadeIn; public System.Action OnFadeOut; // Private Variable - private Hictionary Layers = new Hictionary(5); + private NameTable Layers = new NameTable(5); diff --git a/Runtime/Pattern/Services/RuleService.cs b/Runtime/Pattern/Services/RuleService.cs index 0e42d9f..ce9fa40 100644 --- a/Runtime/Pattern/Services/RuleService.cs +++ b/Runtime/Pattern/Services/RuleService.cs @@ -6,11 +6,11 @@ public abstract class RuleService : Service { public Action OnAddedRule; public Action OnFinishRule; - private Hictionary> Rules; + private NameTable> Rules; public RuleService() { - Rules = new Hictionary>(5); + Rules = new NameTable>(5); } protected override void OnWorldChanging(World Previous, World New) diff --git a/Runtime/ReadySet/Services/TimeService.cs b/Runtime/ReadySet/Services/TimeService.cs index f5d6713..b5151b1 100644 --- a/Runtime/ReadySet/Services/TimeService.cs +++ b/Runtime/ReadySet/Services/TimeService.cs @@ -6,14 +6,14 @@ public sealed class TimeService : Service { private float serviceTime; private float worldTime; - private Hictionary RecordTime; + private NameTable RecordTime; // Service Methods protected override void OnStart(object Author) { serviceTime = Time.time; worldTime = Time.time; - RecordTime = new Hictionary(10); + RecordTime = new NameTable(10); } protected override void OnWorldChanging(World Previous , World New) { diff --git a/Runtime/Toolkit/Inventory/Inventory.cs b/Runtime/Toolkit/Inventory/Inventory.cs index 9778acf..1d1c7ce 100644 --- a/Runtime/Toolkit/Inventory/Inventory.cs +++ b/Runtime/Toolkit/Inventory/Inventory.cs @@ -111,7 +111,7 @@ private enum BehaviorType public System.Action OnItemRemoved; // Private Variable - private Hictionary Items; + private NameTable Items; public int Count => Items.IsValid ? Items.Count : 0; protected IInventoryStorage inventoryStorage { get; private set; } @@ -137,7 +137,7 @@ private void Awake() if (LoadStorage()) { InventoryItemProperty[] cacheItems = inventoryStorage.GetItems(); - Items = new Hictionary(cacheItems.Length); + Items = new NameTable(cacheItems.Length); foreach (var data in cacheItems) { Items.Add(data.Name, data); @@ -147,7 +147,7 @@ private void Awake() { if (DefaultItem != null) { - Items = new Hictionary(DefaultItem.Length); + Items = new NameTable(DefaultItem.Length); foreach (var itemAsset in DefaultItem) { if (itemAsset is IInventoryItem item) @@ -163,7 +163,7 @@ private void Awake() } else { - Items = new Hictionary(5); + Items = new NameTable(5); } } } From a7fa6a277c9ebdf307c2684652fb61edd067961b Mon Sep 17 00:00:00 2001 From: Alijimpa Date: Wed, 1 Apr 2026 11:34:00 +0330 Subject: [PATCH 065/204] Implement DoOnce & Flag --- .../Library/SharedScripts/Classes/DoOnce.cs | 28 ---------- Runtime/Library/SharedScripts/Classes/Flag.cs | 53 +++++++++++++++++++ .../SharedScripts/Classes/Flag.cs.meta | 2 + .../SharedScripts/Classes/NameTable.cs | 4 +- .../SharedScripts/Enumeration/General_Enum.cs | 24 --------- .../Enumeration/General_Enum.cs.meta | 2 - .../SharedScripts/Enumeration/LoadStage.cs | 8 +++ .../Enumeration/LoadStage.cs.meta | 2 + .../SharedScripts/Enumeration/TriggerStage.cs | 10 ++++ .../Enumeration/TriggerStage.cs.meta | 2 + .../SharedScripts/Enumeration/UpdateMethod.cs | 11 ++++ .../Enumeration/UpdateMethod.cs.meta | 2 + .../Library/SharedScripts/Structs/DoOnce.cs | 30 +++++++++++ .../{Classes => Structs}/DoOnce.cs.meta | 0 14 files changed, 122 insertions(+), 56 deletions(-) delete mode 100644 Runtime/Library/SharedScripts/Classes/DoOnce.cs create mode 100644 Runtime/Library/SharedScripts/Classes/Flag.cs create mode 100644 Runtime/Library/SharedScripts/Classes/Flag.cs.meta delete mode 100644 Runtime/Library/SharedScripts/Enumeration/General_Enum.cs delete mode 100644 Runtime/Library/SharedScripts/Enumeration/General_Enum.cs.meta create mode 100644 Runtime/Library/SharedScripts/Enumeration/LoadStage.cs create mode 100644 Runtime/Library/SharedScripts/Enumeration/LoadStage.cs.meta create mode 100644 Runtime/Library/SharedScripts/Enumeration/TriggerStage.cs create mode 100644 Runtime/Library/SharedScripts/Enumeration/TriggerStage.cs.meta create mode 100644 Runtime/Library/SharedScripts/Enumeration/UpdateMethod.cs create mode 100644 Runtime/Library/SharedScripts/Enumeration/UpdateMethod.cs.meta create mode 100644 Runtime/Library/SharedScripts/Structs/DoOnce.cs rename Runtime/Library/SharedScripts/{Classes => Structs}/DoOnce.cs.meta (100%) diff --git a/Runtime/Library/SharedScripts/Classes/DoOnce.cs b/Runtime/Library/SharedScripts/Classes/DoOnce.cs deleted file mode 100644 index 1179b94..0000000 --- a/Runtime/Library/SharedScripts/Classes/DoOnce.cs +++ /dev/null @@ -1,28 +0,0 @@ -namespace RealMethod -{ - public class DoOnce - { - private bool hasRun = false; - - /// - /// Executes the given action only once. - /// - public void Do(System.Action action) - { - if (!hasRun) - { - hasRun = true; - action?.Invoke(); - } - } - - /// - /// Resets the DoOnce so it can run again. - /// - public void Reset() - { - hasRun = false; - } - } - -} \ No newline at end of file diff --git a/Runtime/Library/SharedScripts/Classes/Flag.cs b/Runtime/Library/SharedScripts/Classes/Flag.cs new file mode 100644 index 0000000..4f11619 --- /dev/null +++ b/Runtime/Library/SharedScripts/Classes/Flag.cs @@ -0,0 +1,53 @@ +using UnityEngine; + +namespace RealMethod +{ + public static class Flag + { + private static readonly NameTable Flags = new NameTable(); + + public static void Create(string name) + { + Flags.Add(name, false); + } + public static void Set(string name, bool DefaultValue) + { + if (Flags.ContainsKey(name)) + { + Flags[name] = DefaultValue; + } + else + { + Debug.LogWarning($"Can't find Flag with {name}!"); + } + } + public static bool Get(string name) + { + if (Flags.ContainsKey(name)) + { + return Flags[name]; + } + else + { + Debug.LogWarning($"Can't find Flag with {name}!"); + return false; + } + } + public static bool IsValid(string name) + { + return Flags.ContainsKey(name); + } + public static void Remove(string name) + { + if (Flags.ContainsKey(name)) + { + Flags.Remove(name); + } + else + { + Debug.LogWarning($"Can't find Flag with {name}!"); + } + } + + } +} \ No newline at end of file diff --git a/Runtime/Library/SharedScripts/Classes/Flag.cs.meta b/Runtime/Library/SharedScripts/Classes/Flag.cs.meta new file mode 100644 index 0000000..d1f3cef --- /dev/null +++ b/Runtime/Library/SharedScripts/Classes/Flag.cs.meta @@ -0,0 +1,2 @@ +fileFormatVersion: 2 +guid: fec39332a051c3846b5fe6c0b5d75f19 \ No newline at end of file diff --git a/Runtime/Library/SharedScripts/Classes/NameTable.cs b/Runtime/Library/SharedScripts/Classes/NameTable.cs index dd092ce..ec78d83 100644 --- a/Runtime/Library/SharedScripts/Classes/NameTable.cs +++ b/Runtime/Library/SharedScripts/Classes/NameTable.cs @@ -13,7 +13,7 @@ public class NameTable : IEnumerable> { private Dictionary list; private static int GlobalIdCounter; - private int InstanceId; + public int ID { get; private set; } /// @@ -49,7 +49,7 @@ public IEnumerable Values public NameTable(int prewarm = 10) { - InstanceId = ++GlobalIdCounter; + ID = ++GlobalIdCounter; list = new Dictionary(prewarm); } diff --git a/Runtime/Library/SharedScripts/Enumeration/General_Enum.cs b/Runtime/Library/SharedScripts/Enumeration/General_Enum.cs deleted file mode 100644 index ae54ac4..0000000 --- a/Runtime/Library/SharedScripts/Enumeration/General_Enum.cs +++ /dev/null @@ -1,24 +0,0 @@ -namespace RealMethod -{ - public enum UpdateMethod - { - None = 0, - LateUpdate = 2, - Update = 3, - FixedUpdate = 4 - - } - public enum LoadStage - { - Ascync, - Scync - } - public enum TriggerStage - { - None = 0, - Enter = 1, - Stay = 2, - Exit = 2, - } - -} \ No newline at end of file diff --git a/Runtime/Library/SharedScripts/Enumeration/General_Enum.cs.meta b/Runtime/Library/SharedScripts/Enumeration/General_Enum.cs.meta deleted file mode 100644 index aa05f61..0000000 --- a/Runtime/Library/SharedScripts/Enumeration/General_Enum.cs.meta +++ /dev/null @@ -1,2 +0,0 @@ -fileFormatVersion: 2 -guid: 4c9c5efed73019a45bf952ed85894ddf \ No newline at end of file diff --git a/Runtime/Library/SharedScripts/Enumeration/LoadStage.cs b/Runtime/Library/SharedScripts/Enumeration/LoadStage.cs new file mode 100644 index 0000000..a049d96 --- /dev/null +++ b/Runtime/Library/SharedScripts/Enumeration/LoadStage.cs @@ -0,0 +1,8 @@ +namespace RealMethod +{ + public enum LoadStage + { + Ascync, + Scync + } +} \ No newline at end of file diff --git a/Runtime/Library/SharedScripts/Enumeration/LoadStage.cs.meta b/Runtime/Library/SharedScripts/Enumeration/LoadStage.cs.meta new file mode 100644 index 0000000..4190f8d --- /dev/null +++ b/Runtime/Library/SharedScripts/Enumeration/LoadStage.cs.meta @@ -0,0 +1,2 @@ +fileFormatVersion: 2 +guid: ab35c5257c5b2844ca7e06f6abadd67b \ No newline at end of file diff --git a/Runtime/Library/SharedScripts/Enumeration/TriggerStage.cs b/Runtime/Library/SharedScripts/Enumeration/TriggerStage.cs new file mode 100644 index 0000000..d872f78 --- /dev/null +++ b/Runtime/Library/SharedScripts/Enumeration/TriggerStage.cs @@ -0,0 +1,10 @@ +namespace RealMethod +{ + public enum TriggerStage + { + None = 0, + Enter = 1, + Stay = 2, + Exit = 2, + } +} \ No newline at end of file diff --git a/Runtime/Library/SharedScripts/Enumeration/TriggerStage.cs.meta b/Runtime/Library/SharedScripts/Enumeration/TriggerStage.cs.meta new file mode 100644 index 0000000..cc9d810 --- /dev/null +++ b/Runtime/Library/SharedScripts/Enumeration/TriggerStage.cs.meta @@ -0,0 +1,2 @@ +fileFormatVersion: 2 +guid: ee704ee3594278c4aa5a69d62535fc40 \ No newline at end of file diff --git a/Runtime/Library/SharedScripts/Enumeration/UpdateMethod.cs b/Runtime/Library/SharedScripts/Enumeration/UpdateMethod.cs new file mode 100644 index 0000000..e7dfffe --- /dev/null +++ b/Runtime/Library/SharedScripts/Enumeration/UpdateMethod.cs @@ -0,0 +1,11 @@ +namespace RealMethod +{ + public enum UpdateMethod + { + None = 0, + LateUpdate = 2, + Update = 3, + FixedUpdate = 4 + + } +} \ No newline at end of file diff --git a/Runtime/Library/SharedScripts/Enumeration/UpdateMethod.cs.meta b/Runtime/Library/SharedScripts/Enumeration/UpdateMethod.cs.meta new file mode 100644 index 0000000..37256b1 --- /dev/null +++ b/Runtime/Library/SharedScripts/Enumeration/UpdateMethod.cs.meta @@ -0,0 +1,2 @@ +fileFormatVersion: 2 +guid: 48a68344ff70da84d8d012e3eb9efe59 \ No newline at end of file diff --git a/Runtime/Library/SharedScripts/Structs/DoOnce.cs b/Runtime/Library/SharedScripts/Structs/DoOnce.cs new file mode 100644 index 0000000..e3781e4 --- /dev/null +++ b/Runtime/Library/SharedScripts/Structs/DoOnce.cs @@ -0,0 +1,30 @@ + +namespace RealMethod +{ + public static class DoOnce + { + private static readonly NameTable Flags = new NameTable(); + public static bool Check(string name) + { + if (!Flags.ContainsKey(name)) + Flags.Add(name, false); + + if (Flags[name]) return false; + + Flags[name] = true; + return true; + } + public static void Reset(string name) + { + if (Flags.ContainsKey(name)) + { + Flags[name] = false; + } + else + { + Flags.Add(name, false); + } + } + } + +} \ No newline at end of file diff --git a/Runtime/Library/SharedScripts/Classes/DoOnce.cs.meta b/Runtime/Library/SharedScripts/Structs/DoOnce.cs.meta similarity index 100% rename from Runtime/Library/SharedScripts/Classes/DoOnce.cs.meta rename to Runtime/Library/SharedScripts/Structs/DoOnce.cs.meta From 0ce2abfee2a578aa57ce179572a8546c715d4e5f Mon Sep 17 00:00:00 2001 From: Alijimpa Date: Wed, 1 Apr 2026 19:19:07 +0330 Subject: [PATCH 066/204] Change identity for ErrorAction class to struct --- Editor/Library/SharedScripts/Structs.meta | 8 ++++++++ .../SharedScripts/{Classes => Structs}/ErrorAction.cs | 4 ++-- .../{Classes => Structs}/ErrorAction.cs.meta | 0 3 files changed, 10 insertions(+), 2 deletions(-) create mode 100644 Editor/Library/SharedScripts/Structs.meta rename Editor/Library/SharedScripts/{Classes => Structs}/ErrorAction.cs (91%) rename Editor/Library/SharedScripts/{Classes => Structs}/ErrorAction.cs.meta (100%) diff --git a/Editor/Library/SharedScripts/Structs.meta b/Editor/Library/SharedScripts/Structs.meta new file mode 100644 index 0000000..cf19f97 --- /dev/null +++ b/Editor/Library/SharedScripts/Structs.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 8f6e53f4684bb6f42bf96ae27ac86bb8 +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Editor/Library/SharedScripts/Classes/ErrorAction.cs b/Editor/Library/SharedScripts/Structs/ErrorAction.cs similarity index 91% rename from Editor/Library/SharedScripts/Classes/ErrorAction.cs rename to Editor/Library/SharedScripts/Structs/ErrorAction.cs index d42bf7f..b544b25 100644 --- a/Editor/Library/SharedScripts/Classes/ErrorAction.cs +++ b/Editor/Library/SharedScripts/Structs/ErrorAction.cs @@ -4,11 +4,11 @@ namespace RealMethod.Editor { - public class ErrorAction + public struct ErrorAction { public string ErrorMessage { get; private set; } private Action OnFixed; - private int ID = 0; + private int ID; public ErrorAction(string message, int id, Action callback) { diff --git a/Editor/Library/SharedScripts/Classes/ErrorAction.cs.meta b/Editor/Library/SharedScripts/Structs/ErrorAction.cs.meta similarity index 100% rename from Editor/Library/SharedScripts/Classes/ErrorAction.cs.meta rename to Editor/Library/SharedScripts/Structs/ErrorAction.cs.meta From e3fdc86507a65ab68b1d0c12e2ac2634f497f967 Mon Sep 17 00:00:00 2001 From: Alijimpa Date: Wed, 1 Apr 2026 19:30:21 +0330 Subject: [PATCH 067/204] Fix ErrorAction Struct --- Editor/Library/SharedScripts/Classes/EditorProperty.cs | 6 +++--- Editor/Library/SharedScripts/Structs/ErrorAction.cs | 5 ++++- 2 files changed, 7 insertions(+), 4 deletions(-) diff --git a/Editor/Library/SharedScripts/Classes/EditorProperty.cs b/Editor/Library/SharedScripts/Classes/EditorProperty.cs index 824ef5c..2228ac5 100644 --- a/Editor/Library/SharedScripts/Classes/EditorProperty.cs +++ b/Editor/Library/SharedScripts/Classes/EditorProperty.cs @@ -16,7 +16,7 @@ public abstract class EditorProperty /// Holds the current error state for this property. /// If not null, the property will render an error instead of its normal UI. /// - private ErrorAction PropertyError = null; + private ErrorAction PropertyError; /// @@ -57,7 +57,7 @@ public EditorProperty(string _Name, Object _Owner) /// public byte Render() { - if (PropertyError == null) + if (!PropertyError.IsValid) { return UpdateRender(); } @@ -75,7 +75,7 @@ public byte Render() /// Identifier used to determine which fix action to apply. protected void Error(string message, int id) { - PropertyError = new ErrorAction(message, id, FixError); + PropertyError.Create(message, id, FixError); } diff --git a/Editor/Library/SharedScripts/Structs/ErrorAction.cs b/Editor/Library/SharedScripts/Structs/ErrorAction.cs index b544b25..316550a 100644 --- a/Editor/Library/SharedScripts/Structs/ErrorAction.cs +++ b/Editor/Library/SharedScripts/Structs/ErrorAction.cs @@ -6,11 +6,13 @@ namespace RealMethod.Editor { public struct ErrorAction { + public bool IsValid => string.IsNullOrEmpty(ErrorMessage); public string ErrorMessage { get; private set; } private Action OnFixed; private int ID; - public ErrorAction(string message, int id, Action callback) + + public void Create(string message, int id, Action callback) { ErrorMessage = message; ID = id; @@ -23,6 +25,7 @@ public void RenderError() if (GUILayout.Button("Fix Issue")) { + ErrorMessage = string.Empty; OnFixed?.Invoke(ID); } } From 0d5a94d767c96aef004f172f69415e901eb08f48 Mon Sep 17 00:00:00 2001 From: Alijimpa Date: Wed, 1 Apr 2026 19:57:47 +0330 Subject: [PATCH 068/204] Unity Project Setting Address --- Editor/Core/Utilities/Editor_Library.cs | 2 +- Runtime/Core/Definitions/GlobalEnum.cs | 6 +----- Runtime/Core/ProjectSetting/ProjectSettingAsset.cs | 5 +++++ Runtime/{Core/Definitions => Library/Interfaces}/Tick.cs | 0 .../{Core/Definitions => Library/Interfaces}/Tick.cs.meta | 0 5 files changed, 7 insertions(+), 6 deletions(-) rename Runtime/{Core/Definitions => Library/Interfaces}/Tick.cs (100%) rename Runtime/{Core/Definitions => Library/Interfaces}/Tick.cs.meta (100%) diff --git a/Editor/Core/Utilities/Editor_Library.cs b/Editor/Core/Utilities/Editor_Library.cs index ae1bae3..68347e9 100644 --- a/Editor/Core/Utilities/Editor_Library.cs +++ b/Editor/Core/Utilities/Editor_Library.cs @@ -6,7 +6,7 @@ namespace RealMethod.Editor { public static class RM_Editor { - public const string SetttingAssetPath = "Assets/Resources/RealMethod/RealMethodSetting.asset"; + public static string SetttingAssetPath = ProjectSettingAsset.Path; public static string ScriptTemplatesPath => GetPackagePath("com.mustard.realmethod") + "/Reservoir/ScriptTemplates"; public static string PrefabTemplatePath => GetPackagePath("com.mustard.realmethod") + "/Reservoir/Prefabs"; public static string Documentation => GetPackagePath("com.mustard.realmethod") + "/Documentation/Information"; diff --git a/Runtime/Core/Definitions/GlobalEnum.cs b/Runtime/Core/Definitions/GlobalEnum.cs index bf157b4..5f249fe 100644 --- a/Runtime/Core/Definitions/GlobalEnum.cs +++ b/Runtime/Core/Definitions/GlobalEnum.cs @@ -1,10 +1,6 @@ using System; using UnityEngine; -#if UNITY_EDITOR -using UnityEditor; -#endif - namespace RealMethod { /// @@ -85,7 +81,7 @@ public override int GetHashCode() #if UNITY_EDITOR public override string ToString() { - var ProjectSettings = AssetDatabase.LoadAssetAtPath("Assets/Resources/RealMethod/RealMethodSetting.asset"); + var ProjectSettings = ProjectSettingAsset.Loaded(); if (ProjectSettings) { var names = ProjectSettings.Status; diff --git a/Runtime/Core/ProjectSetting/ProjectSettingAsset.cs b/Runtime/Core/ProjectSetting/ProjectSettingAsset.cs index 82e78e2..df247c6 100644 --- a/Runtime/Core/ProjectSetting/ProjectSettingAsset.cs +++ b/Runtime/Core/ProjectSetting/ProjectSettingAsset.cs @@ -39,6 +39,7 @@ public string GetFolderPath(ProjectSettingAsset settingAsset) } + public static string Path = "Assets/Resources/RealMethod/RealMethodSetting.asset"; [Header("Initializer")] [SerializeField, ReadOnly] @@ -127,6 +128,10 @@ public GameObject GetPrefab_1() } #if UNITY_EDITOR + public static ProjectSettingAsset Loaded() + { + return UnityEditor.AssetDatabase.LoadAssetAtPath(Path); + } public GameObject GetPrefab_2() { return GamePrefab_2; diff --git a/Runtime/Core/Definitions/Tick.cs b/Runtime/Library/Interfaces/Tick.cs similarity index 100% rename from Runtime/Core/Definitions/Tick.cs rename to Runtime/Library/Interfaces/Tick.cs diff --git a/Runtime/Core/Definitions/Tick.cs.meta b/Runtime/Library/Interfaces/Tick.cs.meta similarity index 100% rename from Runtime/Core/Definitions/Tick.cs.meta rename to Runtime/Library/Interfaces/Tick.cs.meta From db2c04c6c05eea34b43f29e75399cf10b08becaf Mon Sep 17 00:00:00 2001 From: Alijimpa Date: Wed, 1 Apr 2026 20:22:39 +0330 Subject: [PATCH 069/204] Refie Pattern Folder And Command System --- .../Pattern/{DataAssets.meta => Assets.meta} | 0 .../BlackboardAsset.cs | 0 .../BlackboardAsset.cs.meta | 0 .../{DataAssets => Assets}/FactoryAsset.cs | 0 .../FactoryAsset.cs.meta | 0 .../{DataAssets => Assets}/ItemAsset.cs | 0 .../{DataAssets => Assets}/ItemAsset.cs.meta | 0 .../{DataAssets => Assets}/ItemConfig.cs | 0 .../{DataAssets => Assets}/ItemConfig.cs.meta | 0 .../{DesignPatterns => Assets}/PoolAsset.cs | 0 .../PoolAsset.cs.meta | 0 .../{DataAssets => Assets}/ResourcAsset.cs | 0 .../ResourcAsset.cs.meta | 0 .../SharedRootAsset.cs | 0 .../SharedRootAsset.cs.meta | 0 .../{DataAssets => Assets}/TableAsset.cs | 0 .../{DataAssets => Assets}/TableAsset.cs.meta | 0 .../{DesignPatterns => Components}/Command.cs | 23 +++++++++---------- .../Command.cs.meta | 0 Runtime/Pattern/DesignPatterns.meta | 8 ------- Runtime/ReadySet/Commands/Execut/C_Death.cs | 6 ++--- Runtime/ReadySet/Commands/Execut/C_Event.cs | 10 ++++---- .../Commands/Execut/C_EventCollider.cs | 10 ++++---- .../ReadySet/Commands/Execut/C_Fracture.cs | 10 ++++---- Runtime/ReadySet/Commands/Execut/C_Haptic.cs | 6 ++--- Runtime/ReadySet/Commands/Execut/C_Notify.cs | 6 ++--- .../ReadySet/Commands/Execut/C_ScneLoader.cs | 6 ++--- Runtime/ReadySet/Commands/Execut/C_Spawner.cs | 8 +++---- .../Components/Physic/CommandTrigger2D.cs | 2 +- .../Components/Physic/CommandTrigger3D.cs | 2 +- .../Components/Visual/EffectPlayer.cs | 2 +- Runtime/ReadySet/Services/SpawanService.cs | 6 ++--- .../Toolkit/PCG/Assets/PCGGenerationAsset.cs | 8 +++---- Runtime/Toolkit/PCG/PCGRequest.cs | 2 +- Runtime/Toolkit/Pickup/C_PickupItem.cs | 6 ++--- 35 files changed, 56 insertions(+), 65 deletions(-) rename Runtime/Pattern/{DataAssets.meta => Assets.meta} (100%) rename Runtime/Pattern/{DesignPatterns => Assets}/BlackboardAsset.cs (100%) rename Runtime/Pattern/{DesignPatterns => Assets}/BlackboardAsset.cs.meta (100%) rename Runtime/Pattern/{DataAssets => Assets}/FactoryAsset.cs (100%) rename Runtime/Pattern/{DataAssets => Assets}/FactoryAsset.cs.meta (100%) rename Runtime/Pattern/{DataAssets => Assets}/ItemAsset.cs (100%) rename Runtime/Pattern/{DataAssets => Assets}/ItemAsset.cs.meta (100%) rename Runtime/Pattern/{DataAssets => Assets}/ItemConfig.cs (100%) rename Runtime/Pattern/{DataAssets => Assets}/ItemConfig.cs.meta (100%) rename Runtime/Pattern/{DesignPatterns => Assets}/PoolAsset.cs (100%) rename Runtime/Pattern/{DesignPatterns => Assets}/PoolAsset.cs.meta (100%) rename Runtime/Pattern/{DataAssets => Assets}/ResourcAsset.cs (100%) rename Runtime/Pattern/{DataAssets => Assets}/ResourcAsset.cs.meta (100%) rename Runtime/Pattern/{DesignPatterns => Assets}/SharedRootAsset.cs (100%) rename Runtime/Pattern/{DesignPatterns => Assets}/SharedRootAsset.cs.meta (100%) rename Runtime/Pattern/{DataAssets => Assets}/TableAsset.cs (100%) rename Runtime/Pattern/{DataAssets => Assets}/TableAsset.cs.meta (100%) rename Runtime/Pattern/{DesignPatterns => Components}/Command.cs (64%) rename Runtime/Pattern/{DesignPatterns => Components}/Command.cs.meta (100%) delete mode 100644 Runtime/Pattern/DesignPatterns.meta diff --git a/Runtime/Pattern/DataAssets.meta b/Runtime/Pattern/Assets.meta similarity index 100% rename from Runtime/Pattern/DataAssets.meta rename to Runtime/Pattern/Assets.meta diff --git a/Runtime/Pattern/DesignPatterns/BlackboardAsset.cs b/Runtime/Pattern/Assets/BlackboardAsset.cs similarity index 100% rename from Runtime/Pattern/DesignPatterns/BlackboardAsset.cs rename to Runtime/Pattern/Assets/BlackboardAsset.cs diff --git a/Runtime/Pattern/DesignPatterns/BlackboardAsset.cs.meta b/Runtime/Pattern/Assets/BlackboardAsset.cs.meta similarity index 100% rename from Runtime/Pattern/DesignPatterns/BlackboardAsset.cs.meta rename to Runtime/Pattern/Assets/BlackboardAsset.cs.meta diff --git a/Runtime/Pattern/DataAssets/FactoryAsset.cs b/Runtime/Pattern/Assets/FactoryAsset.cs similarity index 100% rename from Runtime/Pattern/DataAssets/FactoryAsset.cs rename to Runtime/Pattern/Assets/FactoryAsset.cs diff --git a/Runtime/Pattern/DataAssets/FactoryAsset.cs.meta b/Runtime/Pattern/Assets/FactoryAsset.cs.meta similarity index 100% rename from Runtime/Pattern/DataAssets/FactoryAsset.cs.meta rename to Runtime/Pattern/Assets/FactoryAsset.cs.meta diff --git a/Runtime/Pattern/DataAssets/ItemAsset.cs b/Runtime/Pattern/Assets/ItemAsset.cs similarity index 100% rename from Runtime/Pattern/DataAssets/ItemAsset.cs rename to Runtime/Pattern/Assets/ItemAsset.cs diff --git a/Runtime/Pattern/DataAssets/ItemAsset.cs.meta b/Runtime/Pattern/Assets/ItemAsset.cs.meta similarity index 100% rename from Runtime/Pattern/DataAssets/ItemAsset.cs.meta rename to Runtime/Pattern/Assets/ItemAsset.cs.meta diff --git a/Runtime/Pattern/DataAssets/ItemConfig.cs b/Runtime/Pattern/Assets/ItemConfig.cs similarity index 100% rename from Runtime/Pattern/DataAssets/ItemConfig.cs rename to Runtime/Pattern/Assets/ItemConfig.cs diff --git a/Runtime/Pattern/DataAssets/ItemConfig.cs.meta b/Runtime/Pattern/Assets/ItemConfig.cs.meta similarity index 100% rename from Runtime/Pattern/DataAssets/ItemConfig.cs.meta rename to Runtime/Pattern/Assets/ItemConfig.cs.meta diff --git a/Runtime/Pattern/DesignPatterns/PoolAsset.cs b/Runtime/Pattern/Assets/PoolAsset.cs similarity index 100% rename from Runtime/Pattern/DesignPatterns/PoolAsset.cs rename to Runtime/Pattern/Assets/PoolAsset.cs diff --git a/Runtime/Pattern/DesignPatterns/PoolAsset.cs.meta b/Runtime/Pattern/Assets/PoolAsset.cs.meta similarity index 100% rename from Runtime/Pattern/DesignPatterns/PoolAsset.cs.meta rename to Runtime/Pattern/Assets/PoolAsset.cs.meta diff --git a/Runtime/Pattern/DataAssets/ResourcAsset.cs b/Runtime/Pattern/Assets/ResourcAsset.cs similarity index 100% rename from Runtime/Pattern/DataAssets/ResourcAsset.cs rename to Runtime/Pattern/Assets/ResourcAsset.cs diff --git a/Runtime/Pattern/DataAssets/ResourcAsset.cs.meta b/Runtime/Pattern/Assets/ResourcAsset.cs.meta similarity index 100% rename from Runtime/Pattern/DataAssets/ResourcAsset.cs.meta rename to Runtime/Pattern/Assets/ResourcAsset.cs.meta diff --git a/Runtime/Pattern/DesignPatterns/SharedRootAsset.cs b/Runtime/Pattern/Assets/SharedRootAsset.cs similarity index 100% rename from Runtime/Pattern/DesignPatterns/SharedRootAsset.cs rename to Runtime/Pattern/Assets/SharedRootAsset.cs diff --git a/Runtime/Pattern/DesignPatterns/SharedRootAsset.cs.meta b/Runtime/Pattern/Assets/SharedRootAsset.cs.meta similarity index 100% rename from Runtime/Pattern/DesignPatterns/SharedRootAsset.cs.meta rename to Runtime/Pattern/Assets/SharedRootAsset.cs.meta diff --git a/Runtime/Pattern/DataAssets/TableAsset.cs b/Runtime/Pattern/Assets/TableAsset.cs similarity index 100% rename from Runtime/Pattern/DataAssets/TableAsset.cs rename to Runtime/Pattern/Assets/TableAsset.cs diff --git a/Runtime/Pattern/DataAssets/TableAsset.cs.meta b/Runtime/Pattern/Assets/TableAsset.cs.meta similarity index 100% rename from Runtime/Pattern/DataAssets/TableAsset.cs.meta rename to Runtime/Pattern/Assets/TableAsset.cs.meta diff --git a/Runtime/Pattern/DesignPatterns/Command.cs b/Runtime/Pattern/Components/Command.cs similarity index 64% rename from Runtime/Pattern/DesignPatterns/Command.cs rename to Runtime/Pattern/Components/Command.cs index ccdb5d8..e7c41a8 100644 --- a/Runtime/Pattern/DesignPatterns/Command.cs +++ b/Runtime/Pattern/Components/Command.cs @@ -5,18 +5,22 @@ namespace RealMethod // A base command you can execute immediately. public interface ICommand { - bool Initiate(Object author, Object owner); + bool Initiate(Object owner); void ExecuteCommand(object Executer); } - + [System.Serializable] + public class CPrefab : PrefabCore + { + + } // Base Command public abstract class Command : MonoBehaviour, ICommand { // Implement ICommand Interface - bool ICommand.Initiate(Object author, Object owner) + bool ICommand.Initiate(Object owner) { - return OnInitiate(author, owner); + return OnInitiate(owner); } void ICommand.ExecuteCommand(object Executer) { @@ -27,15 +31,10 @@ void ICommand.ExecuteCommand(object Executer) } // Abstract Methods - protected abstract bool OnInitiate(Object author, Object owner); - protected abstract void Execute(object Owner); - protected abstract bool CanExecute(object Owner); + protected abstract bool OnInitiate(Object owner); + protected abstract void Execute(object Executer); + protected abstract bool CanExecute(object Executer); } - [System.Serializable] - public class CPrefab : PrefabCore - { - - } } \ No newline at end of file diff --git a/Runtime/Pattern/DesignPatterns/Command.cs.meta b/Runtime/Pattern/Components/Command.cs.meta similarity index 100% rename from Runtime/Pattern/DesignPatterns/Command.cs.meta rename to Runtime/Pattern/Components/Command.cs.meta diff --git a/Runtime/Pattern/DesignPatterns.meta b/Runtime/Pattern/DesignPatterns.meta deleted file mode 100644 index 14b7342..0000000 --- a/Runtime/Pattern/DesignPatterns.meta +++ /dev/null @@ -1,8 +0,0 @@ -fileFormatVersion: 2 -guid: 745627a11c3491948b5aa84eab895d79 -folderAsset: yes -DefaultImporter: - externalObjects: {} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Runtime/ReadySet/Commands/Execut/C_Death.cs b/Runtime/ReadySet/Commands/Execut/C_Death.cs index 9fe2519..c6fbd4a 100644 --- a/Runtime/ReadySet/Commands/Execut/C_Death.cs +++ b/Runtime/ReadySet/Commands/Execut/C_Death.cs @@ -19,7 +19,7 @@ public sealed class C_Death : Command // Base ExecutCommand Methods - protected override bool OnInitiate(Object author, Object owner) + protected override bool OnInitiate(Object owner) { return true; } @@ -27,12 +27,12 @@ protected override bool CanExecute(object Owner) { return enabled; } - protected override void Execute(object Owner) + protected override void Execute(object Executer) { if (UseExecuter) { - if (Owner is MonoBehaviour Mono) + if (Executer is MonoBehaviour Mono) { ApplyDeath(Mono.gameObject); } diff --git a/Runtime/ReadySet/Commands/Execut/C_Event.cs b/Runtime/ReadySet/Commands/Execut/C_Event.cs index 8115451..be19f78 100644 --- a/Runtime/ReadySet/Commands/Execut/C_Event.cs +++ b/Runtime/ReadySet/Commands/Execut/C_Event.cs @@ -9,23 +9,23 @@ public sealed class C_Event : Command public UnityEvent OnExecute; // ExecutCommand Methods - protected override bool OnInitiate(Object author, Object owner) + protected override bool OnInitiate( Object owner) { return true; } - protected override bool CanExecute(object Owner) + protected override bool CanExecute(object Executer) { return enabled; } - protected override void Execute(object Owner) + protected override void Execute(object Executer) { - if (Owner is MonoBehaviour MyOwner) + if (Executer is MonoBehaviour MyOwner) { OnExecute?.Invoke(MyOwner); } else { - Debug.LogError("Event_com.Execute: Owner is not a MonoBehaviour. Event not invoked."); + Debug.LogError("Event_com.Execute: Executer is not a MonoBehaviour. Event not invoked."); } } } diff --git a/Runtime/ReadySet/Commands/Execut/C_EventCollider.cs b/Runtime/ReadySet/Commands/Execut/C_EventCollider.cs index 100dfb4..2f1bf7b 100644 --- a/Runtime/ReadySet/Commands/Execut/C_EventCollider.cs +++ b/Runtime/ReadySet/Commands/Execut/C_EventCollider.cs @@ -9,23 +9,23 @@ public sealed class C_EventCollider : Command public UnityEvent OnTrigger; // ExecutCommand Methods - protected override bool OnInitiate(Object author, Object owner) + protected override bool OnInitiate(Object owner) { return true; } - protected override bool CanExecute(object Owner) + protected override bool CanExecute(object Executer) { return enabled; } - protected override void Execute(object Owner) + protected override void Execute(object Executer) { - if (Owner is Collider col) + if (Executer is Collider col) { OnTrigger?.Invoke(col); } else { - Debug.LogError("EventCollider_com.Execute: Owner is not a Collider. Event not invoked."); + Debug.LogError("EventCollider_com.Execute: Executer is not a Collider. Event not invoked."); } } } diff --git a/Runtime/ReadySet/Commands/Execut/C_Fracture.cs b/Runtime/ReadySet/Commands/Execut/C_Fracture.cs index 5333b70..dcb7414 100644 --- a/Runtime/ReadySet/Commands/Execut/C_Fracture.cs +++ b/Runtime/ReadySet/Commands/Execut/C_Fracture.cs @@ -37,7 +37,7 @@ public sealed class C_Fracture : Command // ExecutCommand Methods - protected override bool OnInitiate(UnityEngine.Object author, UnityEngine.Object owner) + protected override bool OnInitiate(UnityEngine.Object owner) { if (HealthyObject) HealthyObject.SetActive(true); @@ -45,19 +45,19 @@ protected override bool OnInitiate(UnityEngine.Object author, UnityEngine.Object DamagedObject.SetActive(false); return true; } - protected override bool CanExecute(object Owner) + protected override bool CanExecute(object Executer) { return enabled; } - protected override void Execute(object Owner) + protected override void Execute(object Executer) { - if (Owner is Collider col) + if (Executer is Collider col) { Fracture(col); return; } - if (Owner is Transform trans) + if (Executer is Transform trans) { Fracture(trans); } diff --git a/Runtime/ReadySet/Commands/Execut/C_Haptic.cs b/Runtime/ReadySet/Commands/Execut/C_Haptic.cs index c1cb3c7..a636b8c 100644 --- a/Runtime/ReadySet/Commands/Execut/C_Haptic.cs +++ b/Runtime/ReadySet/Commands/Execut/C_Haptic.cs @@ -10,16 +10,16 @@ public sealed class C_Haptic : Command private HapticManager manager; // Command Methods - protected override bool OnInitiate(Object author, Object owner) + protected override bool OnInitiate(Object owner) { manager = Game.FindManager(); return manager != null; } - protected override bool CanExecute(object Owner) + protected override bool CanExecute(object Executer) { return enabled && manager != null; } - protected override void Execute(object Owner) + protected override void Execute(object Executer) { foreach (var conf in configs) { diff --git a/Runtime/ReadySet/Commands/Execut/C_Notify.cs b/Runtime/ReadySet/Commands/Execut/C_Notify.cs index 518862b..4d7106e 100644 --- a/Runtime/ReadySet/Commands/Execut/C_Notify.cs +++ b/Runtime/ReadySet/Commands/Execut/C_Notify.cs @@ -56,16 +56,16 @@ private enum TimerBehavior // ExecutCommand Methods - protected override bool OnInitiate(Object author, Object owner) + protected override bool OnInitiate(Object owner) { NotifyStatus = new bool[notify.Length]; return true; } - protected override bool CanExecute(object Owner) + protected override bool CanExecute(object Executer) { return enabled; } - protected override void Execute(object Owner) + protected override void Execute(object Executer) { StartTimer(); } diff --git a/Runtime/ReadySet/Commands/Execut/C_ScneLoader.cs b/Runtime/ReadySet/Commands/Execut/C_ScneLoader.cs index 65b1c7b..cbb5ba5 100644 --- a/Runtime/ReadySet/Commands/Execut/C_ScneLoader.cs +++ b/Runtime/ReadySet/Commands/Execut/C_ScneLoader.cs @@ -36,15 +36,15 @@ private enum LoadMethod // ExecutCommand Methods - protected override bool OnInitiate(UnityEngine.Object author, UnityEngine.Object owner) + protected override bool OnInitiate(UnityEngine.Object owner) { return true; } - protected override bool CanExecute(object Owner) + protected override bool CanExecute(object Executer) { return enabled; } - protected override void Execute(object Owner) + protected override void Execute(object Executer) { switch (method) { diff --git a/Runtime/ReadySet/Commands/Execut/C_Spawner.cs b/Runtime/ReadySet/Commands/Execut/C_Spawner.cs index 4941320..9899971 100644 --- a/Runtime/ReadySet/Commands/Execut/C_Spawner.cs +++ b/Runtime/ReadySet/Commands/Execut/C_Spawner.cs @@ -16,22 +16,22 @@ public sealed class C_Spawner : Command [SerializeField] private Prefab PrefabAsset; // ExecutCommand Methods - protected override bool OnInitiate(Object author, Object owner) + protected override bool OnInitiate(Object owner) { return true; } - protected override bool CanExecute(object Owner) + protected override bool CanExecute(object Executer) { return enabled; } - protected override void Execute(object Owner) + protected override void Execute(object Executer) { if (PrefabAsset == null) return; if (AutoAttach) { - if (Owner is MonoBehaviour Mono) + if (Executer is MonoBehaviour Mono) { Transform target = Spawn.Prefab(PrefabAsset, Mono.transform); if (!SelfPose) diff --git a/Runtime/ReadySet/Components/Physic/CommandTrigger2D.cs b/Runtime/ReadySet/Components/Physic/CommandTrigger2D.cs index cb1c99c..7dd735b 100644 --- a/Runtime/ReadySet/Components/Physic/CommandTrigger2D.cs +++ b/Runtime/ReadySet/Components/Physic/CommandTrigger2D.cs @@ -10,7 +10,7 @@ private void Awake() { foreach (var command in GetComponents()) { - command.Initiate(null, this); + command.Initiate(this); } } diff --git a/Runtime/ReadySet/Components/Physic/CommandTrigger3D.cs b/Runtime/ReadySet/Components/Physic/CommandTrigger3D.cs index a75c6de..8a484de 100644 --- a/Runtime/ReadySet/Components/Physic/CommandTrigger3D.cs +++ b/Runtime/ReadySet/Components/Physic/CommandTrigger3D.cs @@ -10,7 +10,7 @@ private void Awake() { foreach (var command in GetComponents()) { - command.Initiate(null, this); + command.Initiate(this); } } diff --git a/Runtime/ReadySet/Components/Visual/EffectPlayer.cs b/Runtime/ReadySet/Components/Visual/EffectPlayer.cs index f8700d5..0ea64ee 100644 --- a/Runtime/ReadySet/Components/Visual/EffectPlayer.cs +++ b/Runtime/ReadySet/Components/Visual/EffectPlayer.cs @@ -25,7 +25,7 @@ private void Awake() ICommand[] CommandInitators = GetComponents(); foreach (var com in CommandInitators) { - com.Initiate(this, this); + com.Initiate(this); } } private void OnEnable() diff --git a/Runtime/ReadySet/Services/SpawanService.cs b/Runtime/ReadySet/Services/SpawanService.cs index 349ed64..d579d39 100644 --- a/Runtime/ReadySet/Services/SpawanService.cs +++ b/Runtime/ReadySet/Services/SpawanService.cs @@ -674,16 +674,16 @@ public static T Class(System.Type classType) } // Realmethod - public static T Command(CPrefab prefab, MonoBehaviour owner, Object author) where T : Command + public static T Command(CPrefab prefab, MonoBehaviour owner) where T : Command { - if (owner == null || author == null) + if (owner == null) { Debug.LogWarning($" {instance}: Owner or Author is not available."); return null; } GameObject SpawnedObject = Object.Instantiate(prefab, owner.transform); T TargetCommand = SpawnedObject.GetComponent(); - if (!TargetCommand.GetComponent().Initiate(author, owner)) + if (!TargetCommand.GetComponent().Initiate(owner)) { Debug.LogWarning($"Spawn Command Breack: Initiation failed for command '{typeof(T).Name}' on '{prefab.NameID}'."); } diff --git a/Runtime/Toolkit/PCG/Assets/PCGGenerationAsset.cs b/Runtime/Toolkit/PCG/Assets/PCGGenerationAsset.cs index f4868fb..4b38c99 100644 --- a/Runtime/Toolkit/PCG/Assets/PCGGenerationAsset.cs +++ b/Runtime/Toolkit/PCG/Assets/PCGGenerationAsset.cs @@ -168,7 +168,7 @@ private PCGData Stage_Background(PCGData Data) var requestInterface = MyRequest as ICommand; if (requestInterface != null) { - if (!requestInterface.Initiate(this, this)) + if (!requestInterface.Initiate(this)) { Debug.LogWarning($"{this.name}> ICommandInitiator.Initiate failed for {MyRequest.GetType().Name}"); } @@ -205,7 +205,7 @@ private PCGData Stage_Middleground(PCGData Data) var requestInterface = MyRequest as ICommand; if (requestInterface != null) { - if (!requestInterface.Initiate(this, this)) + if (!requestInterface.Initiate(this)) { Debug.LogWarning($"{this.name}> ICommandInitiator.Initiate failed for {MyRequest.GetType().Name}"); } @@ -242,7 +242,7 @@ private PCGData Stage_Foreground(PCGData Data) var requestInterface = MyRequest as ICommand; if (requestInterface != null) { - if (!requestInterface.Initiate(this, this)) + if (!requestInterface.Initiate(this)) { Debug.LogWarning($"{this.name}> ICommandInitiator.Initiate failed for {MyRequest.GetType().Name}"); } @@ -279,7 +279,7 @@ private PCGData Stage_PostProcess(PCGData Data) var requestInterface = MyRequest as ICommand; if (requestInterface != null) { - if (!requestInterface.Initiate(this, this)) + if (!requestInterface.Initiate(this)) { Debug.LogWarning($"{this.name}> ICommandInitiator.Initiate failed for {MyRequest.GetType().Name}"); } diff --git a/Runtime/Toolkit/PCG/PCGRequest.cs b/Runtime/Toolkit/PCG/PCGRequest.cs index 048ceb2..384fab4 100644 --- a/Runtime/Toolkit/PCG/PCGRequest.cs +++ b/Runtime/Toolkit/PCG/PCGRequest.cs @@ -14,7 +14,7 @@ public abstract class PCGRequest : ICommand private PCGGenerationAsset Owner; // Implement ICommand Interface - bool ICommand.Initiate(Object author, Object owner) + bool ICommand.Initiate(Object owner) { if (owner is PCGGenerationAsset result) { diff --git a/Runtime/Toolkit/Pickup/C_PickupItem.cs b/Runtime/Toolkit/Pickup/C_PickupItem.cs index 39ccb48..5fac90c 100644 --- a/Runtime/Toolkit/Pickup/C_PickupItem.cs +++ b/Runtime/Toolkit/Pickup/C_PickupItem.cs @@ -19,7 +19,7 @@ public sealed class C_PickupItem : Command private IInventoryItem itemprovider; // ExecutCommand Methods - protected override bool OnInitiate(Object author, Object owner) + protected override bool OnInitiate(Object owner) { if (items == null) { @@ -36,12 +36,12 @@ protected override bool OnInitiate(Object author, Object owner) return false; } } - protected override bool CanExecute(object Owner) + protected override bool CanExecute(object Executer) { if (!enabled) return false; - if (Owner is Component mono) + if (Executer is Component mono) { IPicker Picker = mono.GetComponent(); if (Picker != null) From 4829436e0d4ea397f02da924f44d941ba7d9883d Mon Sep 17 00:00:00 2001 From: Alijimpa Date: Wed, 1 Apr 2026 20:31:49 +0330 Subject: [PATCH 070/204] Resort all Interface and Component --- Runtime/Library/Interfaces/Command.cs | 12 ++++++++ Runtime/Library/Interfaces/Command.cs.meta | 2 ++ Runtime/Library/Interfaces/Factory.cs | 13 +++++++++ Runtime/Library/Interfaces/Factory.cs.meta | 2 ++ Runtime/Library/Interfaces/Pool.cs | 34 ++++++++++++++++++++++ Runtime/Library/Interfaces/Pool.cs.meta | 2 ++ Runtime/Library/Interfaces/Widget.cs | 10 +++++++ Runtime/Library/Interfaces/Widget.cs.meta | 2 ++ Runtime/Pattern/Assets/FactoryAsset.cs | 19 ++++-------- Runtime/Pattern/Assets/PoolAsset.cs | 27 ----------------- Runtime/Pattern/Components/Command.cs | 6 ---- Runtime/Pattern/Managers/UIManager.cs | 6 +--- 12 files changed, 84 insertions(+), 51 deletions(-) create mode 100644 Runtime/Library/Interfaces/Command.cs create mode 100644 Runtime/Library/Interfaces/Command.cs.meta create mode 100644 Runtime/Library/Interfaces/Factory.cs create mode 100644 Runtime/Library/Interfaces/Factory.cs.meta create mode 100644 Runtime/Library/Interfaces/Pool.cs create mode 100644 Runtime/Library/Interfaces/Pool.cs.meta create mode 100644 Runtime/Library/Interfaces/Widget.cs create mode 100644 Runtime/Library/Interfaces/Widget.cs.meta diff --git a/Runtime/Library/Interfaces/Command.cs b/Runtime/Library/Interfaces/Command.cs new file mode 100644 index 0000000..80a7a6d --- /dev/null +++ b/Runtime/Library/Interfaces/Command.cs @@ -0,0 +1,12 @@ +using UnityEngine; + +namespace RealMethod +{ + // A base command you can execute immediately. + public interface ICommand + { + bool Initiate(Object owner); + void ExecuteCommand(object Executer); + } + +} \ No newline at end of file diff --git a/Runtime/Library/Interfaces/Command.cs.meta b/Runtime/Library/Interfaces/Command.cs.meta new file mode 100644 index 0000000..596df09 --- /dev/null +++ b/Runtime/Library/Interfaces/Command.cs.meta @@ -0,0 +1,2 @@ +fileFormatVersion: 2 +guid: 3b1af94cc4165924f91dd898a4b30ee0 \ No newline at end of file diff --git a/Runtime/Library/Interfaces/Factory.cs b/Runtime/Library/Interfaces/Factory.cs new file mode 100644 index 0000000..fa97c28 --- /dev/null +++ b/Runtime/Library/Interfaces/Factory.cs @@ -0,0 +1,13 @@ +namespace RealMethod +{ + public interface IFactoryEditorAccess + { + + } + public interface IFactoryAction : ICommand + { + //void Initiate(); + //void Execute(); + } + +} \ No newline at end of file diff --git a/Runtime/Library/Interfaces/Factory.cs.meta b/Runtime/Library/Interfaces/Factory.cs.meta new file mode 100644 index 0000000..eca5952 --- /dev/null +++ b/Runtime/Library/Interfaces/Factory.cs.meta @@ -0,0 +1,2 @@ +fileFormatVersion: 2 +guid: f34a9b4304409044088b9fc1e89ecf18 \ No newline at end of file diff --git a/Runtime/Library/Interfaces/Pool.cs b/Runtime/Library/Interfaces/Pool.cs new file mode 100644 index 0000000..a55a9ad --- /dev/null +++ b/Runtime/Library/Interfaces/Pool.cs @@ -0,0 +1,34 @@ +using UnityEngine; +using System.Collections; +using System.Collections.Generic; + + +namespace RealMethod +{ + public interface IPool + { + void Prewarm(int amount = 1); + IEnumerator PrewarmEachFrame(int amount = 1); + void Request(); + void Return(int amount = 1); + void Remove(int amount = 1, bool Force = false); + void Clean(); + } + public interface IPool : IPool + { + IEnumerable Request(int amount = 1); + } + public interface IPoolSpawner where J : Component + { + J Spawn(Vector3 location, Quaternion rotation, Vector3 scale); + J Spawn(Vector3 location, Quaternion rotation); + J Spawn(Vector3 location); + J Spawn(); + } + public interface IPoolDespawner where J : Component + { + void Despawn(); + void Despawn(J target); + } + +} \ No newline at end of file diff --git a/Runtime/Library/Interfaces/Pool.cs.meta b/Runtime/Library/Interfaces/Pool.cs.meta new file mode 100644 index 0000000..f07675e --- /dev/null +++ b/Runtime/Library/Interfaces/Pool.cs.meta @@ -0,0 +1,2 @@ +fileFormatVersion: 2 +guid: abf6234193204404496125105048b8a7 \ No newline at end of file diff --git a/Runtime/Library/Interfaces/Widget.cs b/Runtime/Library/Interfaces/Widget.cs new file mode 100644 index 0000000..736aed5 --- /dev/null +++ b/Runtime/Library/Interfaces/Widget.cs @@ -0,0 +1,10 @@ +using UnityEngine; + +namespace RealMethod +{ + public interface IWidget + { + MonoBehaviour GetWidgetClass(); + void SceneInitialized(UIManager manager); + } +} \ No newline at end of file diff --git a/Runtime/Library/Interfaces/Widget.cs.meta b/Runtime/Library/Interfaces/Widget.cs.meta new file mode 100644 index 0000000..a56524a --- /dev/null +++ b/Runtime/Library/Interfaces/Widget.cs.meta @@ -0,0 +1,2 @@ +fileFormatVersion: 2 +guid: 5ccd760c30543b141a059a176b7555a8 \ No newline at end of file diff --git a/Runtime/Pattern/Assets/FactoryAsset.cs b/Runtime/Pattern/Assets/FactoryAsset.cs index aa774fe..03166d8 100644 --- a/Runtime/Pattern/Assets/FactoryAsset.cs +++ b/Runtime/Pattern/Assets/FactoryAsset.cs @@ -1,28 +1,21 @@ +using UnityEngine; + namespace RealMethod { - public interface IFactoryEditorAccess - { - - } - public interface IFactoryAction - { - void Initiate(); - void Execute(); - } - public struct FactoryProduct : IFactoryAction { - public void Initiate() + // Implement ICommand Interface + bool ICommand.Initiate(Object owner) { throw new System.NotImplementedException(); } - public void Execute() + void ICommand.ExecuteCommand(object Executer) { throw new System.NotImplementedException(); } } - + public abstract class FactoryAsset : DataAsset { diff --git a/Runtime/Pattern/Assets/PoolAsset.cs b/Runtime/Pattern/Assets/PoolAsset.cs index 406e58e..008614e 100644 --- a/Runtime/Pattern/Assets/PoolAsset.cs +++ b/Runtime/Pattern/Assets/PoolAsset.cs @@ -182,33 +182,6 @@ public override void OnEditorPlay() } #endif } - - public interface IPool - { - void Prewarm(int amount = 1); - IEnumerator PrewarmEachFrame(int amount = 1); - void Request(); - void Return(int amount = 1); - void Remove(int amount = 1, bool Force = false); - void Clean(); - } - public interface IPool : IPool - { - IEnumerable Request(int amount = 1); - } - public interface IPoolSpawner where J : Component - { - J Spawn(Vector3 location, Quaternion rotation, Vector3 scale); - J Spawn(Vector3 location, Quaternion rotation); - J Spawn(Vector3 location); - J Spawn(); - } - public interface IPoolDespawner where J : Component - { - void Despawn(); - void Despawn(J target); - } - } diff --git a/Runtime/Pattern/Components/Command.cs b/Runtime/Pattern/Components/Command.cs index e7c41a8..2b6dfc0 100644 --- a/Runtime/Pattern/Components/Command.cs +++ b/Runtime/Pattern/Components/Command.cs @@ -2,12 +2,6 @@ namespace RealMethod { - // A base command you can execute immediately. - public interface ICommand - { - bool Initiate(Object owner); - void ExecuteCommand(object Executer); - } [System.Serializable] public class CPrefab : PrefabCore diff --git a/Runtime/Pattern/Managers/UIManager.cs b/Runtime/Pattern/Managers/UIManager.cs index acd1417..6ee6eee 100644 --- a/Runtime/Pattern/Managers/UIManager.cs +++ b/Runtime/Pattern/Managers/UIManager.cs @@ -620,9 +620,5 @@ private IEnumerator FadeOut(CanvasGroup canvas, float fadeDuration, System.Actio } - public interface IWidget - { - MonoBehaviour GetWidgetClass(); - void SceneInitialized(UIManager manager); - } + } From 6e3231030096da9cfd636ca845e8bde605d941e4 Mon Sep 17 00:00:00 2001 From: Alijimpa Date: Wed, 1 Apr 2026 20:54:43 +0330 Subject: [PATCH 071/204] Resort Editor Pattern --- Editor/Pattern/{DataAssets.meta => Inspectors.meta} | 2 +- .../{Manager => Inspectors}/CompositManagerCompWindow.cs | 0 .../{Manager => Inspectors}/CompositManagerCompWindow.cs.meta | 0 Editor/Pattern/{Manager => Inspectors}/DataManagerCompWindow.cs | 0 .../{Manager => Inspectors}/DataManagerCompWindow.cs.meta | 0 Editor/Pattern/{DataAssets => Inspectors}/FactoryEditor.cs | 0 Editor/Pattern/{DataAssets => Inspectors}/FactoryEditor.cs.meta | 0 Editor/Pattern/{DataAssets => Inspectors}/ResourcEditor.cs | 0 Editor/Pattern/{DataAssets => Inspectors}/ResourcEditor.cs.meta | 0 Editor/Pattern/{Manager => Inspectors}/TaskManagerCompWindow.cs | 0 .../{Manager => Inspectors}/TaskManagerCompWindow.cs.meta | 0 Editor/Pattern/{Manager.meta => Windows.meta} | 2 +- Editor/Pattern/{DataAssets => Windows}/TableViewerWindow.cs | 0 .../Pattern/{DataAssets => Windows}/TableViewerWindow.cs.meta | 0 Runtime/Library/Utilities/UI_Library.cs | 2 ++ 15 files changed, 4 insertions(+), 2 deletions(-) rename Editor/Pattern/{DataAssets.meta => Inspectors.meta} (77%) rename Editor/Pattern/{Manager => Inspectors}/CompositManagerCompWindow.cs (100%) rename Editor/Pattern/{Manager => Inspectors}/CompositManagerCompWindow.cs.meta (100%) rename Editor/Pattern/{Manager => Inspectors}/DataManagerCompWindow.cs (100%) rename Editor/Pattern/{Manager => Inspectors}/DataManagerCompWindow.cs.meta (100%) rename Editor/Pattern/{DataAssets => Inspectors}/FactoryEditor.cs (100%) rename Editor/Pattern/{DataAssets => Inspectors}/FactoryEditor.cs.meta (100%) rename Editor/Pattern/{DataAssets => Inspectors}/ResourcEditor.cs (100%) rename Editor/Pattern/{DataAssets => Inspectors}/ResourcEditor.cs.meta (100%) rename Editor/Pattern/{Manager => Inspectors}/TaskManagerCompWindow.cs (100%) rename Editor/Pattern/{Manager => Inspectors}/TaskManagerCompWindow.cs.meta (100%) rename Editor/Pattern/{Manager.meta => Windows.meta} (77%) rename Editor/Pattern/{DataAssets => Windows}/TableViewerWindow.cs (100%) rename Editor/Pattern/{DataAssets => Windows}/TableViewerWindow.cs.meta (100%) diff --git a/Editor/Pattern/DataAssets.meta b/Editor/Pattern/Inspectors.meta similarity index 77% rename from Editor/Pattern/DataAssets.meta rename to Editor/Pattern/Inspectors.meta index 9b782dc..04fcdba 100644 --- a/Editor/Pattern/DataAssets.meta +++ b/Editor/Pattern/Inspectors.meta @@ -1,5 +1,5 @@ fileFormatVersion: 2 -guid: 8353593eea5c6884ea594f163d264236 +guid: 8e1de2e7481e79942ad4d69f21a3c713 folderAsset: yes DefaultImporter: externalObjects: {} diff --git a/Editor/Pattern/Manager/CompositManagerCompWindow.cs b/Editor/Pattern/Inspectors/CompositManagerCompWindow.cs similarity index 100% rename from Editor/Pattern/Manager/CompositManagerCompWindow.cs rename to Editor/Pattern/Inspectors/CompositManagerCompWindow.cs diff --git a/Editor/Pattern/Manager/CompositManagerCompWindow.cs.meta b/Editor/Pattern/Inspectors/CompositManagerCompWindow.cs.meta similarity index 100% rename from Editor/Pattern/Manager/CompositManagerCompWindow.cs.meta rename to Editor/Pattern/Inspectors/CompositManagerCompWindow.cs.meta diff --git a/Editor/Pattern/Manager/DataManagerCompWindow.cs b/Editor/Pattern/Inspectors/DataManagerCompWindow.cs similarity index 100% rename from Editor/Pattern/Manager/DataManagerCompWindow.cs rename to Editor/Pattern/Inspectors/DataManagerCompWindow.cs diff --git a/Editor/Pattern/Manager/DataManagerCompWindow.cs.meta b/Editor/Pattern/Inspectors/DataManagerCompWindow.cs.meta similarity index 100% rename from Editor/Pattern/Manager/DataManagerCompWindow.cs.meta rename to Editor/Pattern/Inspectors/DataManagerCompWindow.cs.meta diff --git a/Editor/Pattern/DataAssets/FactoryEditor.cs b/Editor/Pattern/Inspectors/FactoryEditor.cs similarity index 100% rename from Editor/Pattern/DataAssets/FactoryEditor.cs rename to Editor/Pattern/Inspectors/FactoryEditor.cs diff --git a/Editor/Pattern/DataAssets/FactoryEditor.cs.meta b/Editor/Pattern/Inspectors/FactoryEditor.cs.meta similarity index 100% rename from Editor/Pattern/DataAssets/FactoryEditor.cs.meta rename to Editor/Pattern/Inspectors/FactoryEditor.cs.meta diff --git a/Editor/Pattern/DataAssets/ResourcEditor.cs b/Editor/Pattern/Inspectors/ResourcEditor.cs similarity index 100% rename from Editor/Pattern/DataAssets/ResourcEditor.cs rename to Editor/Pattern/Inspectors/ResourcEditor.cs diff --git a/Editor/Pattern/DataAssets/ResourcEditor.cs.meta b/Editor/Pattern/Inspectors/ResourcEditor.cs.meta similarity index 100% rename from Editor/Pattern/DataAssets/ResourcEditor.cs.meta rename to Editor/Pattern/Inspectors/ResourcEditor.cs.meta diff --git a/Editor/Pattern/Manager/TaskManagerCompWindow.cs b/Editor/Pattern/Inspectors/TaskManagerCompWindow.cs similarity index 100% rename from Editor/Pattern/Manager/TaskManagerCompWindow.cs rename to Editor/Pattern/Inspectors/TaskManagerCompWindow.cs diff --git a/Editor/Pattern/Manager/TaskManagerCompWindow.cs.meta b/Editor/Pattern/Inspectors/TaskManagerCompWindow.cs.meta similarity index 100% rename from Editor/Pattern/Manager/TaskManagerCompWindow.cs.meta rename to Editor/Pattern/Inspectors/TaskManagerCompWindow.cs.meta diff --git a/Editor/Pattern/Manager.meta b/Editor/Pattern/Windows.meta similarity index 77% rename from Editor/Pattern/Manager.meta rename to Editor/Pattern/Windows.meta index f5bedd2..66b6dc5 100644 --- a/Editor/Pattern/Manager.meta +++ b/Editor/Pattern/Windows.meta @@ -1,5 +1,5 @@ fileFormatVersion: 2 -guid: 9536b0ab30e69e9409f6c9e050b38995 +guid: 77cc5644be719ee4b8d874ef041e74a5 folderAsset: yes DefaultImporter: externalObjects: {} diff --git a/Editor/Pattern/DataAssets/TableViewerWindow.cs b/Editor/Pattern/Windows/TableViewerWindow.cs similarity index 100% rename from Editor/Pattern/DataAssets/TableViewerWindow.cs rename to Editor/Pattern/Windows/TableViewerWindow.cs diff --git a/Editor/Pattern/DataAssets/TableViewerWindow.cs.meta b/Editor/Pattern/Windows/TableViewerWindow.cs.meta similarity index 100% rename from Editor/Pattern/DataAssets/TableViewerWindow.cs.meta rename to Editor/Pattern/Windows/TableViewerWindow.cs.meta diff --git a/Runtime/Library/Utilities/UI_Library.cs b/Runtime/Library/Utilities/UI_Library.cs index 3084b1d..7d7c261 100644 --- a/Runtime/Library/Utilities/UI_Library.cs +++ b/Runtime/Library/Utilities/UI_Library.cs @@ -1,3 +1,4 @@ +using System.Collections; using System.Collections.Generic; using UnityEngine; using UnityEngine.EventSystems; @@ -22,5 +23,6 @@ public static bool IsTouchOverUI(GraphicRaycaster HUD_graphicRaycaster, Vector2 // Check if we hit any UI elements return results.Count > 0; } + } } \ No newline at end of file From 1d77e7f85f2a8a94bcfca4f2b401c45137c946d9 Mon Sep 17 00:00:00 2001 From: Alijimpa Date: Thu, 2 Apr 2026 00:07:08 +0330 Subject: [PATCH 072/204] Rename Function for TickManager --- Editor/Pattern/Inspectors/TaskManagerCompWindow.cs | 2 +- Runtime/Library/Utilities/UI_Library.cs | 2 -- Runtime/Pattern/Managers/TickManager.cs | 10 +++++----- 3 files changed, 6 insertions(+), 8 deletions(-) diff --git a/Editor/Pattern/Inspectors/TaskManagerCompWindow.cs b/Editor/Pattern/Inspectors/TaskManagerCompWindow.cs index cd8e542..eca9e38 100644 --- a/Editor/Pattern/Inspectors/TaskManagerCompWindow.cs +++ b/Editor/Pattern/Inspectors/TaskManagerCompWindow.cs @@ -22,7 +22,7 @@ public override void OnInspectorGUI() { if (BaseComponent.Count > 0) { - ITask[] tasks = BaseComponent.GetAllTasks(); + ITask[] tasks = BaseComponent.GetAllUnits(); foreach (var task in tasks) { EditorGUILayout.LabelField($"{task}"); diff --git a/Runtime/Library/Utilities/UI_Library.cs b/Runtime/Library/Utilities/UI_Library.cs index 7d7c261..3084b1d 100644 --- a/Runtime/Library/Utilities/UI_Library.cs +++ b/Runtime/Library/Utilities/UI_Library.cs @@ -1,4 +1,3 @@ -using System.Collections; using System.Collections.Generic; using UnityEngine; using UnityEngine.EventSystems; @@ -23,6 +22,5 @@ public static bool IsTouchOverUI(GraphicRaycaster HUD_graphicRaycaster, Vector2 // Check if we hit any UI elements return results.Count > 0; } - } } \ No newline at end of file diff --git a/Runtime/Pattern/Managers/TickManager.cs b/Runtime/Pattern/Managers/TickManager.cs index e01fb48..5520c20 100644 --- a/Runtime/Pattern/Managers/TickManager.cs +++ b/Runtime/Pattern/Managers/TickManager.cs @@ -34,21 +34,21 @@ private void LateUpdate() { if (updateMethod == UpdateMethod.LateUpdate) { - callUnits(); + CallUnits(); } } private void Update() { if (updateMethod == UpdateMethod.Update) { - callUnits(); + CallUnits(); } } private void FixedUpdate() { if (updateMethod == UpdateMethod.FixedUpdate) { - callUnits(); + CallUnits(); } } @@ -57,13 +57,13 @@ public bool IsValid(T unit) { return units.Contains(unit); } - public T[] GetAllTasks() + public T[] GetAllUnits() { return units.ToArray(); } // Private Functions - private void callUnits() + private void CallUnits() { float delta = Time.deltaTime; for (int i = 0; i < units.Count; i++) From 8357221111707b78a6aa604b7cd92e40677e9d57 Mon Sep 17 00:00:00 2001 From: Alijimpa Date: Thu, 2 Apr 2026 21:49:29 +0330 Subject: [PATCH 073/204] Implement Check UniqManager class for World --- Runtime/Core/Architecture/World.cs | 15 ++++++++++++--- Runtime/Library/Extension/GameObject.cs | 9 +++++++++ 2 files changed, 21 insertions(+), 3 deletions(-) diff --git a/Runtime/Core/Architecture/World.cs b/Runtime/Core/Architecture/World.cs index a7df731..37c902a 100644 --- a/Runtime/Core/Architecture/World.cs +++ b/Runtime/Core/Architecture/World.cs @@ -108,10 +108,19 @@ private void Awake() // Get All Managers List CashManagers = new List(10); - foreach (var manager in GetComponentsInChildren()) // Self Mangers + foreach (var manager in GetComponents()) { - manager.InitiateManager(false); - CashManagers.Add(manager); + if (!CashManagers.Contains(manager)) + { + manager.InitiateManager(true); + CashManagers.Add(manager); + } + else + { + Debug.LogError($"You should not use a manager {manager} twice"); + throw new System.NotImplementedException(); + } + } Managers = new IGameManager[CashManagers.Count]; Managers = CashManagers.ToArray(); diff --git a/Runtime/Library/Extension/GameObject.cs b/Runtime/Library/Extension/GameObject.cs index f82e6a8..a0dceb5 100644 --- a/Runtime/Library/Extension/GameObject.cs +++ b/Runtime/Library/Extension/GameObject.cs @@ -177,6 +177,15 @@ public static bool IsShared(this GameObject obj) { return Game.Bridge.IsSharedObject(obj); } + /// + /// Check if GameObject was lives in DontDestroyOnload scene + /// + /// The GameObject to check. + /// True if the GameObject is in DontDestroyOnload scene, false otherwise. + public static bool IsDontDestroyOnLoad(this GameObject obj) + { + return obj.scene.name == "DontDestroyOnLoad"; + } #if UNITY_EDITOR From ba8acdedc0158c9857417beb7b2d51c1b8e5d67a Mon Sep 17 00:00:00 2001 From: Alijimpa Date: Thu, 2 Apr 2026 22:46:02 +0330 Subject: [PATCH 074/204] Refine Servie system --- Editor/Core/InitializeOnEnterPlayMode.meta | 8 ++ Runtime/Core/Architecture/Game.cs | 127 ++++++++++++------ Runtime/Core/Architecture/Service.cs | 11 ++ Runtime/Pattern/Managers/AudioManager.cs | 2 +- Runtime/Pattern/Managers/CompositManager.cs | 2 +- Runtime/Pattern/Managers/HapticManager.cs | 2 +- .../ReadySet/Components/Method/RuleEvent.cs | 2 +- Runtime/ReadySet/Managers/CoroutineManager.cs | 2 +- Runtime/ReadySet/Managers/HUDManager.cs | 2 +- Runtime/ReadySet/Managers/ScreenManager.cs | 2 +- Runtime/ReadySet/Managers/TaskManager.cs | 2 +- Runtime/ReadySet/Services/SpawanService.cs | 2 +- 12 files changed, 111 insertions(+), 53 deletions(-) create mode 100644 Editor/Core/InitializeOnEnterPlayMode.meta diff --git a/Editor/Core/InitializeOnEnterPlayMode.meta b/Editor/Core/InitializeOnEnterPlayMode.meta new file mode 100644 index 0000000..1e69ed9 --- /dev/null +++ b/Editor/Core/InitializeOnEnterPlayMode.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: c41562d680cd7724aaed78043c99689b +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Runtime/Core/Architecture/Game.cs b/Runtime/Core/Architecture/Game.cs index 34ddebe..6fc8fdc 100644 --- a/Runtime/Core/Architecture/Game.cs +++ b/Runtime/Core/Architecture/Game.cs @@ -91,6 +91,7 @@ public static bool IsPaused } } } + public static bool IsGameInitialized { get; private set; } = false; /// /// Indicates whether the game is in loading stage /// Return true when game in loading section for new scene @@ -145,7 +146,7 @@ public static event Action OnReady /// /// List of runtime-registered instances owned by the game. /// - private List Services; + private readonly Dictionary Services = new(); @@ -219,7 +220,6 @@ private static void InitializeGame() Bridge = new DefaultGameBridge(); } } - Instance.Services = new List(3); ((IRelationBridge)Bridge).BindWorldCreated(Instance.Notify_OnWorldInitiate); ((IService)Bridge).Created(Instance); @@ -319,6 +319,7 @@ private static void RuntimeBeforeSceneLoad() { if (Instance != null) { + IsGameInitialized = true; Instance.OnGameInitialized(); } } @@ -390,22 +391,16 @@ public static T CastWorld() where T : class public static T AddService(object author) where T : Service, new() { // Check if you game not initialized - if (Instance.Services == null) + if (!IsGameInitialized) { Debug.LogWarning($"Game doesn't initialized !"); return null; } - // Check if a service of this type already exists - if (Instance.Services.Any(s => s.GetType() == typeof(T))) - { - Debug.LogWarning($"Service of type {typeof(T).Name} already exists."); - return null; - } - // Create Service T newService = new T(); - ((IService)newService).Created(author); + if (!RegisterService(newService, author)) + return null; if (Instance.Managers != null) { foreach (var manager in Instance.Managers) @@ -414,11 +409,40 @@ public static T CastWorld() where T : class } } ((IRelationBridge)Bridge).ServiceCreated(newService); - Instance.Services.Add(newService); return newService; } /// - /// Removes the first service instance of type if present. + /// Register new instance () that include 'IService' interface . + /// New Service instance register to the game if one des not already exist + /// + /// Any Type can inplement 'IService' interface + /// Any Instance can inplement 'IService' interface + /// The object responsible for creating the service (used for provider callbacks). + /// The newly created service instance, or null if a service of the same type already exists. + public static bool RegisterService(T service, object author) + { + if (service is IService provider) + { + Type TypeService = typeof(T); + + if (Instance.Services.ContainsKey(TypeService)) + { + Debug.LogError($"Service {TypeService} already registered."); + return false; + } + + provider.Created(author); + Instance.Services[TypeService] = provider; + return true; + } + else + { + Debug.LogError($"The class '{service.GetType().Name}' must implement the IService interface."); + return false; + } + } + /// + /// Removes the service instance of type if present. /// Managers and the global service system will be notified of the removal. /// /// Service type to remove. @@ -426,19 +450,23 @@ public static T CastWorld() where T : class /// true if a service was found and removed; otherwise false. public static bool RemoveService(object author) where T : Service { - var service = Instance.Services.FirstOrDefault(s => s.GetType() == typeof(T)); - if (service != null) + Type TypeService = typeof(T); + var provider = Instance.Services[TypeService]; + if (provider != null) { - if (Instance.Managers != null) + if (provider.GetServiceClass() is Service service) { - foreach (var manager in Instance.Managers) + if (Instance.Managers != null) { - manager.ResolveService(service, false); + foreach (var manager in Instance.Managers) + { + manager.ResolveService(service, false); + } } + ((IRelationBridge)Bridge).ServiceRemoved(service); } - ((IRelationBridge)Bridge).ServiceRemoved(service); - ((IService)service).Deleted(author); - Instance.Services.Remove(service); + provider.Deleted(author); + Unregister(); return true; } @@ -446,29 +474,27 @@ public static bool RemoveService(object author) where T : Service return false; } /// - /// Retrieves the first service instance of type if available. + /// Remove service instance /// - /// Service type to retrieve. - /// The service instance of type , or null if not found. - public static T GetService() where T : Service + /// The object type that implement 'IService' + public static void Unregister() { - return Instance.Services.OfType().FirstOrDefault(); + Instance.Services.Remove(typeof(T)); } /// - /// Retrieves a service by its concrete . - /// Returns null and logs an error if the provided type is not a . + /// Retrieves the service instance of type if available. /// - /// Concrete service type to look up. - /// The matching service instance, or null if not found or invalid type. - public static Service GetService(Type type) + /// Service type to retrieve. + /// The service instance of type , or null if not found. + public static T GetService() { - if (!typeof(Service).IsAssignableFrom(type)) - { - Debug.LogError($"Type {type.Name} is not a valid Service."); - return null; - } + Type TypeService = typeof(T); + + if (Instance.Services.TryGetValue(TypeService, out var provider)) + return (T)provider.GetServiceClass(); - return Instance.Services.FirstOrDefault(s => s.GetType() == type); + Debug.LogError($"Service {TypeService} not found."); + return default; } /// /// Attempts to find a service of type . @@ -476,10 +502,23 @@ public static Service GetService(Type type) /// Service type to find. /// Out parameter that receives the service if found. /// true if the service was found; otherwise false. - public static bool TryFindService(out T service) where T : Service + public static bool TryGetService(out T service) where T : Service + { + if (Instance.Services.TryGetValue(typeof(T), out var provider)) + { + service = (T)provider.GetServiceClass(); + return true; + } + + service = default; + return false; + } + /// + /// Clear all services in Game + /// + public static void ClearService() { - service = Instance.Services.OfType().FirstOrDefault(); - return service != null; + Instance.Services.Clear(); } /// /// Returns the type names of all registered game services. @@ -985,7 +1024,7 @@ private void Notify_OnWorldInitiate(World NewWorld) { foreach (var service in Services) { - ((IService)service).ChangeWorld(NewWorld); + service.Value.ChangeWorld(NewWorld); } World = NewWorld; OnWorldChanged(World); @@ -999,11 +1038,11 @@ private void Notify_OnGameQuit() ((IRelationBridge)Bridge).UnbindWorldCreated(); if (Services != null) { - for (int i = 0; i < Services.Count; i++) + foreach (var service in Services) { - ((IService)Services[i]).Deleted(this); - Services.RemoveAt(i); + service.Value.Deleted(this); } + ClearService(); } ((IService)Bridge).Deleted(this); OnGameClosed(); diff --git a/Runtime/Core/Architecture/Service.cs b/Runtime/Core/Architecture/Service.cs index d96f2cf..5eb75e1 100644 --- a/Runtime/Core/Architecture/Service.cs +++ b/Runtime/Core/Architecture/Service.cs @@ -5,6 +5,13 @@ namespace RealMethod /// public interface IService { + /// + /// Returns the object instance that implements this service. + /// + /// + /// The object associated with this service. + /// + object GetServiceClass(); /// /// Called when the service is created. /// @@ -28,6 +35,10 @@ public interface IService public abstract class Service : IService { // Implement IService Interface + object IService.GetServiceClass() + { + return this; + } void IService.Created(object author) { OnStart(author); diff --git a/Runtime/Pattern/Managers/AudioManager.cs b/Runtime/Pattern/Managers/AudioManager.cs index e075c0b..45f73c9 100644 --- a/Runtime/Pattern/Managers/AudioManager.cs +++ b/Runtime/Pattern/Managers/AudioManager.cs @@ -23,7 +23,7 @@ protected override void InitiateManager(bool AlwaysLoaded) return; } - if (CanBringtoSpawn() && Game.TryFindService(out Spawn SpawnServ)) + if (CanBringtoSpawn() && Game.TryGetService(out Spawn SpawnServ)) { SpawnServ.BringManager(this); } diff --git a/Runtime/Pattern/Managers/CompositManager.cs b/Runtime/Pattern/Managers/CompositManager.cs index 12e8220..795ec54 100644 --- a/Runtime/Pattern/Managers/CompositManager.cs +++ b/Runtime/Pattern/Managers/CompositManager.cs @@ -369,7 +369,7 @@ protected sealed override void InitiateManager(bool AlwaysLoaded) InitiateLayers(); OnInitiate(AlwaysLoaded); InitiateMusicStates(); - if (Game.TryFindService(out stateService)) + if (Game.TryGetService(out stateService)) { stateService.OnStateUpdate += OnStateChanged; if (RunFirstState) diff --git a/Runtime/Pattern/Managers/HapticManager.cs b/Runtime/Pattern/Managers/HapticManager.cs index 8931dee..325882e 100644 --- a/Runtime/Pattern/Managers/HapticManager.cs +++ b/Runtime/Pattern/Managers/HapticManager.cs @@ -73,7 +73,7 @@ public void InitiateManager(bool AlwaysLoaded) return; } - if (Game.TryFindService(out Spawn SpawnServ)) + if (Game.TryGetService(out Spawn SpawnServ)) { SpawnServ.BringManager(this); } diff --git a/Runtime/ReadySet/Components/Method/RuleEvent.cs b/Runtime/ReadySet/Components/Method/RuleEvent.cs index 3a230c0..b08329f 100644 --- a/Runtime/ReadySet/Components/Method/RuleEvent.cs +++ b/Runtime/ReadySet/Components/Method/RuleEvent.cs @@ -19,7 +19,7 @@ public sealed class RuleEvent : MonoBehaviour private void Awake() { - if (Game.TryFindService(out ruleServ)) + if (Game.TryGetService(out ruleServ)) { if (ruleServ.IsValid(Rule)) { diff --git a/Runtime/ReadySet/Managers/CoroutineManager.cs b/Runtime/ReadySet/Managers/CoroutineManager.cs index 59b001a..aa53fbb 100644 --- a/Runtime/ReadySet/Managers/CoroutineManager.cs +++ b/Runtime/ReadySet/Managers/CoroutineManager.cs @@ -5,7 +5,7 @@ public class CoroutineManager : EnumeratorManager // EnumeratorManager Methods protected override void InitiateManager(bool alwaysLoaded) { - if (Game.TryFindService(out Spawn SpawnServ)) + if (Game.TryGetService(out Spawn SpawnServ)) { SpawnServ.BringManager(this); } diff --git a/Runtime/ReadySet/Managers/HUDManager.cs b/Runtime/ReadySet/Managers/HUDManager.cs index adfb47a..ee01c46 100644 --- a/Runtime/ReadySet/Managers/HUDManager.cs +++ b/Runtime/ReadySet/Managers/HUDManager.cs @@ -9,7 +9,7 @@ public sealed class HUDManager : UIManager // UIManager Methods protected override void InitiateManager(bool alwaysLoaded) { - if (Game.TryFindService(out Spawn SpawnServ)) + if (Game.TryGetService(out Spawn SpawnServ)) { SpawnServ.BringManager(this); } diff --git a/Runtime/ReadySet/Managers/ScreenManager.cs b/Runtime/ReadySet/Managers/ScreenManager.cs index 545a9c4..5ddd5b8 100644 --- a/Runtime/ReadySet/Managers/ScreenManager.cs +++ b/Runtime/ReadySet/Managers/ScreenManager.cs @@ -25,7 +25,7 @@ protected override void InitiateManager(bool alwaysLoaded) { Game.OnSceneLoading += (value) => OnLoadScne?.Invoke(value); Game.OnSceneLoadingProcess += (value) => OnLoading?.Invoke(value); - if (Game.TryFindService(out Spawn SpawnServ)) + if (Game.TryGetService(out Spawn SpawnServ)) { SpawnServ.BringManager(this); } diff --git a/Runtime/ReadySet/Managers/TaskManager.cs b/Runtime/ReadySet/Managers/TaskManager.cs index 5e6196f..2202039 100644 --- a/Runtime/ReadySet/Managers/TaskManager.cs +++ b/Runtime/ReadySet/Managers/TaskManager.cs @@ -19,7 +19,7 @@ public sealed class TaskManager : TickManager // TickManager Methods protected override void InitiateManager(bool alwaysLoaded) { - if (Game.TryFindService(out Spawn SpawnServ)) + if (Game.TryGetService(out Spawn SpawnServ)) { SpawnServ.BringManager(this); } diff --git a/Runtime/ReadySet/Services/SpawanService.cs b/Runtime/ReadySet/Services/SpawanService.cs index d579d39..1b6cba3 100644 --- a/Runtime/ReadySet/Services/SpawanService.cs +++ b/Runtime/ReadySet/Services/SpawanService.cs @@ -18,7 +18,7 @@ public static Spawn instance } else { - if (Game.TryFindService(out Spawn CacheInstance)) + if (Game.TryGetService(out Spawn CacheInstance)) { return CacheInstance; } From 959b3749e37aad01c61066b822a797c3b25e3936 Mon Sep 17 00:00:00 2001 From: Alijimpa Date: Thu, 2 Apr 2026 23:17:07 +0330 Subject: [PATCH 075/204] Add Safty check for Parenting --- Runtime/Core/Architecture/GameBridge.cs | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/Runtime/Core/Architecture/GameBridge.cs b/Runtime/Core/Architecture/GameBridge.cs index 864ab36..b7573a0 100644 --- a/Runtime/Core/Architecture/GameBridge.cs +++ b/Runtime/Core/Architecture/GameBridge.cs @@ -210,7 +210,8 @@ public void AddSharedObject(GameObject obj) return; } Shareds.Add(obj); - obj.transform.SetParent(Game.World.transform); + if (obj.gameObject.activeInHierarchy && Game.World.gameObject.activeInHierarchy) + obj.transform.SetParent(Game.World.transform); } /// /// Removes a GameObject from the shared objects collection when it is no longer needed or should no longer be shared. @@ -224,7 +225,8 @@ public void RemoveSharedObject(GameObject obj) return; } Shareds.Remove(obj); - obj.transform.SetParent(null); + if (obj.gameObject.activeInHierarchy) + obj.transform.SetParent(null); } /// /// Check is GameObject is in Shared List From 94513794a6bb382d92a47c8d74f7bcd3bbe97275 Mon Sep 17 00:00:00 2001 From: Alijimpa Date: Thu, 2 Apr 2026 23:42:52 +0330 Subject: [PATCH 076/204] Add Safty Check for World & Game --- Runtime/Core/Architecture/Game.cs | 54 +++++++++++++++++++++++++++++- Runtime/Core/Architecture/World.cs | 27 ++++++++++++--- 2 files changed, 75 insertions(+), 6 deletions(-) diff --git a/Runtime/Core/Architecture/Game.cs b/Runtime/Core/Architecture/Game.cs index 6fc8fdc..5608454 100644 --- a/Runtime/Core/Architecture/Game.cs +++ b/Runtime/Core/Architecture/Game.cs @@ -391,7 +391,7 @@ public static T CastWorld() where T : class public static T AddService(object author) where T : Service, new() { // Check if you game not initialized - if (!IsGameInitialized) + if (Bridge == null) { Debug.LogWarning($"Game doesn't initialized !"); return null; @@ -1048,6 +1048,58 @@ private void Notify_OnGameQuit() OnGameClosed(); } +#if UNITY_EDITOR + private void Awake() + { + + } + private void OnEnable() + { + + } + private void Start() + { + + } + private void OnDisable() + { + if (!EditorApplication.isPlayingOrWillChangePlaymode) + return; // Ignore disable caused by editor closing play mode + + if (gameObject.activeSelf == false) + { + Debug.LogWarning($"You can't Deactive {gameObject.name} GameObject"); + gameObject.SetActive(true); + } + if (enabled == false) + { + Debug.LogWarning($"You can't Disable {GetType().Name} Component"); + enabled = true; + } + } + private void LateUpdate() + { + if (transform.position != Vector3.zero) + { + Debug.LogWarning($"{gameObject.name} position should not be changed!"); + transform.position = Vector3.zero; + } + if (transform.rotation != Quaternion.identity) + { + Debug.LogWarning($"{gameObject.name} rotation should not be changed!"); + transform.rotation = Quaternion.identity; + } + } + private void Update() + { + + } + private void FixedUpdate() + { + + } +#endif + /// diff --git a/Runtime/Core/Architecture/World.cs b/Runtime/Core/Architecture/World.cs index 37c902a..f70da60 100644 --- a/Runtime/Core/Architecture/World.cs +++ b/Runtime/Core/Architecture/World.cs @@ -146,22 +146,39 @@ private void Awake() SyncProvider.WorldIsReady(); } #if UNITY_EDITOR - /// - /// Called EveryFrame to Insure World position - /// + private void OnEnable() + { + + } + private void OnDisable() + { + if (gameObject.activeSelf == true && enabled == false) + { + Debug.LogWarning($"You can't Disable {GetType().Name} Component"); + enabled = true; + } + } private void LateUpdate() { if (transform.position != Vector3.zero) { - Debug.LogError("World position should not be changed!"); + Debug.LogWarning($"{gameObject.name} position should not be changed!"); transform.position = Vector3.zero; } if (transform.rotation != Quaternion.identity) { - Debug.LogError("World rotation should not be changed!"); + Debug.LogWarning($"{gameObject.name} rotation should not be changed!"); transform.rotation = Quaternion.identity; } } + private void Update() + { + + } + private void FixedUpdate() + { + + } #endif /// /// Unity callback invoked when the object is being destroyed. From 0246568dc00d3c63065caaea2e32eff6058a1632 Mon Sep 17 00:00:00 2001 From: Alijimpa Date: Thu, 2 Apr 2026 23:51:06 +0330 Subject: [PATCH 077/204] Implement Clear Services when Awake --- Runtime/Core/Architecture/World.cs | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/Runtime/Core/Architecture/World.cs b/Runtime/Core/Architecture/World.cs index f70da60..5f62052 100644 --- a/Runtime/Core/Architecture/World.cs +++ b/Runtime/Core/Architecture/World.cs @@ -80,9 +80,12 @@ protected virtual void OnDrawGizmos() public abstract class World : MonoBehaviour { [Header("Setting")] + [SerializeField, Tooltip("Clears all registered services on Awake.")] + private bool clearServices; [SerializeField] private Prefab DefualtPlayer; + private IGameManager[] Managers; private GameObject PlayerObject; @@ -99,6 +102,10 @@ private void Awake() IRelationBridge SyncProvider = Game.Bridge; if (SyncProvider.IntroduceWorld(this)) { + if (clearServices) + { + Game.ClearService(); + } SyncProvider.BindServicesUpdated(Notify_OnServicesUpdated); } else From 9cf1cde8c8e28d843dc7b586372fbf09bf1e93ce Mon Sep 17 00:00:00 2001 From: Alijimpa Date: Fri, 3 Apr 2026 00:34:24 +0330 Subject: [PATCH 078/204] Refine Game World Insure Check --- Editor/Core/Inspectors/GameEditor.cs | 2 +- Runtime/Core/Architecture/Game.cs | 6 +++++- Runtime/Core/Architecture/GameBridge.cs | 2 +- Runtime/Core/Architecture/World.cs | 5 ----- 4 files changed, 7 insertions(+), 8 deletions(-) diff --git a/Editor/Core/Inspectors/GameEditor.cs b/Editor/Core/Inspectors/GameEditor.cs index d65498a..3e76f66 100644 --- a/Editor/Core/Inspectors/GameEditor.cs +++ b/Editor/Core/Inspectors/GameEditor.cs @@ -23,7 +23,7 @@ public override void OnInspectorGUI() EditorGUILayout.Space(0.5f); string[] Services = BaseComponent.GetAllServiceNames(); string[] Managers = BaseComponent.gameObject.GetComponents().Select(c => c.GetManagerClass().name).ToArray(); - string[] WorldManagers = Game.World.gameObject.GetComponents().Select(c => c.GetManagerClass().name).ToArray(); + string[] WorldManagers = Game.World ? Game.World.gameObject.GetComponents().Select(c => c.GetManagerClass().name).ToArray() : new string[0]; for (int i = 0; i < Services.Length; i++) { EditorGUILayout.LabelField($"{i + 1}. {Services[i]}"); diff --git a/Runtime/Core/Architecture/Game.cs b/Runtime/Core/Architecture/Game.cs index 5608454..0895d84 100644 --- a/Runtime/Core/Architecture/Game.cs +++ b/Runtime/Core/Architecture/Game.cs @@ -1051,7 +1051,11 @@ private void Notify_OnGameQuit() #if UNITY_EDITOR private void Awake() { - + if (Instance != null) + { + Debug.LogError($"This [{this}] component should not be added manually to the scene."); + Destroy(this); + } } private void OnEnable() { diff --git a/Runtime/Core/Architecture/GameBridge.cs b/Runtime/Core/Architecture/GameBridge.cs index b7573a0..c9e308a 100644 --- a/Runtime/Core/Architecture/GameBridge.cs +++ b/Runtime/Core/Architecture/GameBridge.cs @@ -323,7 +323,7 @@ protected virtual bool RequestForNewWorld(World NewWorld) /// The New WorldClass Refrence in AdditiveScene protected virtual void OnAdditiveWorldDetected(World AdditiveWorld) { - Despawn.GameObject(AdditiveWorld.gameObject); + UnityEngine.Object.Destroy(AdditiveWorld.gameObject); } /// /// Starts loading a scene by name using a coroutine. diff --git a/Runtime/Core/Architecture/World.cs b/Runtime/Core/Architecture/World.cs index 5f62052..8ec8f27 100644 --- a/Runtime/Core/Architecture/World.cs +++ b/Runtime/Core/Architecture/World.cs @@ -159,11 +159,6 @@ private void OnEnable() } private void OnDisable() { - if (gameObject.activeSelf == true && enabled == false) - { - Debug.LogWarning($"You can't Disable {GetType().Name} Component"); - enabled = true; - } } private void LateUpdate() { From f7d6e64d3db5c20f16cb77dd42107fd9f7832dc9 Mon Sep 17 00:00:00 2001 From: Alijimpa Date: Fri, 3 Apr 2026 11:17:56 +0330 Subject: [PATCH 079/204] Rename GameMessage Class --- Runtime/Core/Definitions/GameMessage.cs | 13 +++ Runtime/Core/Definitions/GameMessage.cs.meta | 2 + Runtime/Library/Extension/GameObject.cs | 97 +++++++++----------- 3 files changed, 56 insertions(+), 56 deletions(-) create mode 100644 Runtime/Core/Definitions/GameMessage.cs create mode 100644 Runtime/Core/Definitions/GameMessage.cs.meta diff --git a/Runtime/Core/Definitions/GameMessage.cs b/Runtime/Core/Definitions/GameMessage.cs new file mode 100644 index 0000000..8930be3 --- /dev/null +++ b/Runtime/Core/Definitions/GameMessage.cs @@ -0,0 +1,13 @@ +namespace RealMethod +{ + public static class GameMessage + { + public const string Spawn = "OnSpawn"; + public const string Despawn = "OnDespawn"; + public const string Attach = "OnAttach"; + public const string Detach = "OnDetach"; + public const string Share = "OnShare"; + public const string ApplyDamage = "TakeDamage"; + public const string Heal = "Heal"; + } +} \ No newline at end of file diff --git a/Runtime/Core/Definitions/GameMessage.cs.meta b/Runtime/Core/Definitions/GameMessage.cs.meta new file mode 100644 index 0000000..c3c17a5 --- /dev/null +++ b/Runtime/Core/Definitions/GameMessage.cs.meta @@ -0,0 +1,2 @@ +fileFormatVersion: 2 +guid: 5f841a73e68d0554f983f85c3882199d \ No newline at end of file diff --git a/Runtime/Library/Extension/GameObject.cs b/Runtime/Library/Extension/GameObject.cs index a0dceb5..4b35646 100644 --- a/Runtime/Library/Extension/GameObject.cs +++ b/Runtime/Library/Extension/GameObject.cs @@ -12,78 +12,61 @@ namespace RealMethod /// public static class GameObject_Extension { + /// + /// Applies damage to the target GameObject using two fallback methods: + /// 1) If the object implements , damage is applied directly through TakeDamage. + /// 2) Otherwise, a Unity SendMessage call is made using GameMessages.ApplyDamage. + /// + /// This allows all GameObjects to receive damage regardless of whether they use the interface + /// or the older SendMessage-based system. + /// + /// The GameObject that should receive damage. + /// The damage payload containing values such as damage amount and hit details. + public static void ApplyDamage(this GameObject target, HitData hitdata) + { + IDamageable provider = target.GetComponent(); + if (provider != null) + { + provider.TakeDamage(hitdata.damage); + } + else + { + target.SendMessage(GameMessage.ApplyDamage, hitdata, SendMessageOptions.RequireReceiver); + } + } /// /// Attaches this GameObject to a specified parent GameObject, optionally preserving world position. /// Also sends an "OnAttach" message to the owner GameObject. /// - /// The GameObject to attach. + /// The GameObject to attach. /// The GameObject to attach to. /// If true, the parent-relative position, rotation, and scale are modified so that the last local transformation is equal to the world transformation. - public static void Attach(this GameObject owner, GameObject parent, bool worldPositionStays) + public static void Attach(this GameObject target, GameObject parent, bool worldPositionStays) { - owner.transform.SetParent(parent.transform, worldPositionStays); - owner.SendAttachEvent(parent); + target.transform.SetParent(parent.transform, worldPositionStays); + target.SendMessage(GameMessage.Attach, parent, SendMessageOptions.DontRequireReceiver); } /// /// Detaches this GameObject from its current parent and sends an "OnDetach" message. /// - /// The GameObject to detach. + /// The GameObject to detach. /// The parent GameObject it was attached to (primarily for context, not used in the current implementation). - public static void Detach(this GameObject owner, GameObject parent) - { - owner.transform.SetParent(null); - owner.SendDetachEvent(); - } - /// - /// Sends an "OnAttach" message to the owner GameObject. - /// - /// The GameObject to send the message to. - /// The object that triggered the attach event (passed as parameter to the message). - /// Specifies whether the message must be received, or if it is optional. - public static void SendAttachEvent(this GameObject owner, Object spawner, SendMessageOptions option = SendMessageOptions.RequireReceiver) - { - owner.SendMessage("OnAttach", spawner, option); - } - /// - /// Sends an "OnDetach" message to the owner GameObject. - /// - /// The GameObject to send the message to. - /// Specifies whether the message must be received, or if it is optional. - public static void SendDetachEvent(this GameObject owner, SendMessageOptions option = SendMessageOptions.RequireReceiver) - { - owner.SendMessage("OnDetach", option); - } - /// - /// Sends an "OnSpawn" message to the owner GameObject. - /// - /// The GameObject to send the message to. - /// The object that triggered the spawn event (passed as parameter to the message). - /// Specifies whether the message must be received, or if it is optional. - public static void SendSpawnEvent(this GameObject owner, Object spawner, SendMessageOptions option = SendMessageOptions.RequireReceiver) - { - owner.SendMessage("OnSpawn", spawner, option); - } - /// - /// Sends an "OnDespawn" message to the owner GameObject. - /// - /// The GameObject to send the message to. - /// The object that triggered the despawn event (passed as parameter to the message). - /// Specifies whether the message must be received, or if it is optional. - public static void SendDespawnEvent(this GameObject owner, Object despawner, SendMessageOptions option = SendMessageOptions.RequireReceiver) + public static void Detach(this GameObject target, GameObject parent) { - owner.SendMessage("OnDespawn", despawner, option); + target.transform.SetParent(null); + target.SendMessage(GameMessage.Detach, SendMessageOptions.DontRequireReceiver); } /// /// Adds a new component of type TComponent to the GameObject and initializes it without arguments. /// /// The type of the component to add, must inherit from MonoBehaviour and IInitializable. /// This type parameter is unused in this overload. - /// The GameObject to add the component to. + /// The GameObject to add the component to. /// The newly added and initialized component. - public static TComponent AddComponent(this GameObject gameObject) + public static TComponent AddComponent(this GameObject target) where TComponent : MonoBehaviour, IInitializable { - var component = gameObject.AddComponent(); + var component = target.AddComponent(); component.Initialize(); return component; } @@ -92,13 +75,13 @@ public static TComponent AddComponent(this GameObject gam /// /// The type of the component to add, must inherit from MonoBehaviour and IInitializableWithArgument. /// The type of the argument used for initialization. - /// The GameObject to add the component to. + /// The GameObject to add the component to. /// The argument to pass to the component's Initialize method. /// The newly added and initialized component. - public static TComponent AddComponent(this GameObject gameObject, TArgument argument) + public static TComponent AddComponent(this GameObject target, TArgument argument) where TComponent : MonoBehaviour, IInitializableWithArgument { - var component = gameObject.AddComponent(); + var component = target.AddComponent(); component.Initialize(argument); return component; } @@ -108,14 +91,14 @@ public static TComponent AddComponent(this GameObject gam /// The type of the component to add, must inherit from MonoBehaviour and IInitializableWithTwoArgument. /// The type of the first argument used for initialization. /// The type of the second argument used for initialization. - /// The GameObject to add the component to. + /// The GameObject to add the component to. /// The first argument to pass to the component's Initialize method. /// The second argument to pass to the component's Initialize method. /// The newly added and initialized component. - public static TComponent AddComponent(this GameObject gameObject, TArgumentA argumentA, TArgumentB argumentB) + public static TComponent AddComponent(this GameObject target, TArgumentA argumentA, TArgumentB argumentB) where TComponent : MonoBehaviour, IInitializableWithTwoArgument { - var component = gameObject.AddComponent(); + var component = target.AddComponent(); component.Initialize(argumentA, argumentB); return component; } @@ -159,6 +142,7 @@ public static bool IsInScene(this GameObject obj) public static void Share(this GameObject obj) { Game.Bridge.AddSharedObject(obj); + obj.SendMessage(GameMessage.Share, true, SendMessageOptions.DontRequireReceiver); } /// /// Unregisters the GameObject from the shared object system. @@ -167,6 +151,7 @@ public static void Share(this GameObject obj) public static void Unshare(this GameObject obj) { Game.Bridge.RemoveSharedObject(obj); + obj.SendMessage(GameMessage.Share, false, SendMessageOptions.DontRequireReceiver); } /// /// Checks if the GameObject is currently registered in the shared object system. From b55407fdfc9d17ece786794f8b5d31aea6e89780 Mon Sep 17 00:00:00 2001 From: Alijimpa Date: Sun, 5 Apr 2026 08:33:55 +0330 Subject: [PATCH 080/204] Implement GameObject Feature and messaging invoke --- Runtime/Core/Definitions/GameMessage.cs | 4 +- Runtime/Library/Extension/Component.cs | 50 ++++++++- Runtime/Library/Extension/GameObject.cs | 105 ++++++++++++++++-- Runtime/Library/Extension/Transform.cs | 10 ++ Runtime/Library/Interfaces/Damage.cs | 40 ------- Runtime/Library/Interfaces/Damageable.cs | 18 +++ .../{Damage.cs.meta => Damageable.cs.meta} | 0 Runtime/Library/Interfaces/Initializable.cs | 29 ++++- Runtime/Library/Interfaces/Label.cs | 32 ++++++ Runtime/Library/Interfaces/Label.cs.meta | 2 + .../Library/SharedScripts/Structs/HitData.cs | 65 +++++++++++ .../SharedScripts/Structs/HitData.cs.meta | 2 + Runtime/Library/Utilities/Trace_Library.cs | 3 - Runtime/Pattern/Managers/UIManager.cs | 20 ++-- Runtime/ReadySet/Commands/Execut/C_Death.cs | 25 +---- .../Components/Time/DestroyAfterDelay.cs | 4 +- Runtime/ReadySet/Services/SpawanService.cs | 44 ++++---- 17 files changed, 333 insertions(+), 120 deletions(-) delete mode 100644 Runtime/Library/Interfaces/Damage.cs create mode 100644 Runtime/Library/Interfaces/Damageable.cs rename Runtime/Library/Interfaces/{Damage.cs.meta => Damageable.cs.meta} (100%) create mode 100644 Runtime/Library/Interfaces/Label.cs create mode 100644 Runtime/Library/Interfaces/Label.cs.meta create mode 100644 Runtime/Library/SharedScripts/Structs/HitData.cs create mode 100644 Runtime/Library/SharedScripts/Structs/HitData.cs.meta diff --git a/Runtime/Core/Definitions/GameMessage.cs b/Runtime/Core/Definitions/GameMessage.cs index 8930be3..22256b8 100644 --- a/Runtime/Core/Definitions/GameMessage.cs +++ b/Runtime/Core/Definitions/GameMessage.cs @@ -4,10 +4,10 @@ public static class GameMessage { public const string Spawn = "OnSpawn"; public const string Despawn = "OnDespawn"; + public const string ApplyDamage = "OnTakeDamage"; + public const string Die = "OnDie"; public const string Attach = "OnAttach"; public const string Detach = "OnDetach"; public const string Share = "OnShare"; - public const string ApplyDamage = "TakeDamage"; - public const string Heal = "Heal"; } } \ No newline at end of file diff --git a/Runtime/Library/Extension/Component.cs b/Runtime/Library/Extension/Component.cs index b312c7b..f0ba125 100644 --- a/Runtime/Library/Extension/Component.cs +++ b/Runtime/Library/Extension/Component.cs @@ -4,13 +4,55 @@ namespace RealMethod { public static class Component_Extension { - public static void SendSpawnEvent(this Component owner, Object spawner, SendMessageOptions option = SendMessageOptions.RequireReceiver) + public static void InvokeSpawnEvent(this Component owner, Object spawner = null, SendMessageOptions option = SendMessageOptions.RequireReceiver) { - owner.SendMessage("OnSpawn", spawner, option); + if (spawner != null) + { + if (owner is ISpawnWithAuthor provider) + { + provider.OnSpawn(spawner); + } + else + { + owner.SendMessage(GameMessage.Spawn, spawner, option); + } + } + else + { + if (owner is ISpawn provider) + { + provider.OnSpawn(); + } + else + { + owner.SendMessage(GameMessage.Spawn, option); + } + } } - public static void SendDespawnEvent(this Component owner, Object despawner, SendMessageOptions option = SendMessageOptions.RequireReceiver) + public static void InvokeDespawnEvent(this Component owner, Object despawner = null, SendMessageOptions option = SendMessageOptions.RequireReceiver) { - owner.SendMessage("OnDespawn", despawner, option); + if (despawner != null) + { + if (owner is IDespawnWithAuthor provider) + { + provider.OnDespawn(despawner); + } + else + { + owner.SendMessage(GameMessage.Despawn, despawner, option); + } + } + else + { + if (owner is IDespawn provider) + { + provider.OnDespawn(); + } + else + { + owner.SendMessage(GameMessage.Despawn, option); + } + } } } } \ No newline at end of file diff --git a/Runtime/Library/Extension/GameObject.cs b/Runtime/Library/Extension/GameObject.cs index 4b35646..2005692 100644 --- a/Runtime/Library/Extension/GameObject.cs +++ b/Runtime/Library/Extension/GameObject.cs @@ -12,6 +12,18 @@ namespace RealMethod /// public static class GameObject_Extension { + public static void Death(this GameObject target) + { + IDamageable provider = target.GetComponent(); + if (provider != null) + { + provider.Die(); + } + else + { + target.SendMessage(GameMessage.Die, SendMessageOptions.RequireReceiver); + } + } /// /// Applies damage to the target GameObject using two fallback methods: /// 1) If the object implements , damage is applied directly through TakeDamage. @@ -27,7 +39,7 @@ public static void ApplyDamage(this GameObject target, HitData hitdata) IDamageable provider = target.GetComponent(); if (provider != null) { - provider.TakeDamage(hitdata.damage); + provider.TakeDamage(hitdata); } else { @@ -57,6 +69,72 @@ public static void Detach(this GameObject target, GameObject parent) target.SendMessage(GameMessage.Detach, SendMessageOptions.DontRequireReceiver); } /// + /// Sends an "OnSpawn" message to the owner GameObject. + /// + /// The GameObject to send the message to. + /// The object that triggered the spawn event (passed as parameter to the message). + /// Specifies whether the message must be received, or if it is optional. + public static void InvokeSpawnEvent(this GameObject owner, Object spawner = null, SendMessageOptions option = SendMessageOptions.RequireReceiver) + { + if (spawner != null) + { + ISpawnWithAuthor provider = owner.GetComponent(); + if (provider != null) + { + provider.OnSpawn(spawner); + } + else + { + owner.SendMessage(GameMessage.Spawn, spawner, option); + } + } + else + { + ISpawn provider = owner.GetComponent(); + if (provider != null) + { + provider.OnSpawn(); + } + else + { + owner.SendMessage(GameMessage.Spawn, option); + } + } + } + /// + /// Sends an "OnDespawn" message to the owner GameObject. + /// + /// The GameObject to send the message to. + /// The object that triggered the despawn event (passed as parameter to the message). + /// Specifies whether the message must be received, or if it is optional. + public static void InvokeDespawnEvent(this GameObject owner, Object despawner = null, SendMessageOptions option = SendMessageOptions.RequireReceiver) + { + if (despawner != null) + { + IDespawnWithAuthor provider = owner.GetComponent(); + if (provider != null) + { + provider.OnDespawn(despawner); + } + else + { + owner.SendMessage(GameMessage.Despawn, despawner, option); + } + } + else + { + IDespawn provider = owner.GetComponent(); + if (provider != null) + { + provider.OnDespawn(); + } + else + { + owner.SendMessage(GameMessage.Despawn, option); + } + } + } + /// /// Adds a new component of type TComponent to the GameObject and initializes it without arguments. /// /// The type of the component to add, must inherit from MonoBehaviour and IInitializable. @@ -64,10 +142,10 @@ public static void Detach(this GameObject target, GameObject parent) /// The GameObject to add the component to. /// The newly added and initialized component. public static TComponent AddComponent(this GameObject target) - where TComponent : MonoBehaviour, IInitializable + where TComponent : MonoBehaviour, ISpawn { var component = target.AddComponent(); - component.Initialize(); + component.OnSpawn(); return component; } /// @@ -79,10 +157,10 @@ public static TComponent AddComponent(this GameObject tar /// The argument to pass to the component's Initialize method. /// The newly added and initialized component. public static TComponent AddComponent(this GameObject target, TArgument argument) - where TComponent : MonoBehaviour, IInitializableWithArgument + where TComponent : MonoBehaviour, ISpawnWithArgument { var component = target.AddComponent(); - component.Initialize(argument); + component.OnSpawn(argument); return component; } /// @@ -96,10 +174,10 @@ public static TComponent AddComponent(this GameObject tar /// The second argument to pass to the component's Initialize method. /// The newly added and initialized component. public static TComponent AddComponent(this GameObject target, TArgumentA argumentA, TArgumentB argumentB) - where TComponent : MonoBehaviour, IInitializableWithTwoArgument + where TComponent : MonoBehaviour, ISpawnWithTwoArgument { var component = target.AddComponent(); - component.Initialize(argumentA, argumentB); + component.OnSpawn(argumentA, argumentB); return component; } /// @@ -171,6 +249,19 @@ public static bool IsDontDestroyOnLoad(this GameObject obj) { return obj.scene.name == "DontDestroyOnLoad"; } + /// + /// Set layer on object and children + /// + /// GameObject Target + /// the layer you want to set that + public static void SetLayerRecursively(this GameObject target, int layer) + { + foreach (Transform t in target.GetComponentsInChildren(true)) + { + t.gameObject.layer = layer; + } + } + #if UNITY_EDITOR diff --git a/Runtime/Library/Extension/Transform.cs b/Runtime/Library/Extension/Transform.cs index 57d5c43..39c14f8 100644 --- a/Runtime/Library/Extension/Transform.cs +++ b/Runtime/Library/Extension/Transform.cs @@ -22,5 +22,15 @@ public static Transform FindSocket(this Transform trans, Name16 socketname) Debug.LogError($"Not find any socket with {socketname} name"); return trans; } + /// + /// Reset transform quickly + /// + /// Target terasform + public static void Reset(this Transform t) + { + t.localPosition = Vector3.zero; + t.localRotation = Quaternion.identity; + t.localScale = Vector3.one; + } } } \ No newline at end of file diff --git a/Runtime/Library/Interfaces/Damage.cs b/Runtime/Library/Interfaces/Damage.cs deleted file mode 100644 index edb0734..0000000 --- a/Runtime/Library/Interfaces/Damage.cs +++ /dev/null @@ -1,40 +0,0 @@ -using UnityEngine; - -namespace RealMethod -{ - public interface IDamage - { - /// - /// Returns true if the object is already dead. - /// - bool IsDead { get; } - /// - /// Called when the object dies or is destroyed due to damage. - /// - void Die(); - } - public interface IDamageable : IDamage - { - float MaxHealth { get; } - float CurrentHealth { get; } - /// - /// Simple damage (only amount + optional source) - /// - void TakeDamage(float amount, GameObject source = null); - void Restore(float amount); - } - /// - /// Interface for objects that can take and restore damage. - /// - /// The type representing TakeDamage data (e.g., int, float, struct). - public interface IDamageable : IDamageable where T : struct where R : struct - { - /// - /// Applies damage to the object. - /// - /// The raw data of damage. - /// The GameObject or system causing the damage. - void TakeDamage(T data); - void Restore(R amount); - } -} \ No newline at end of file diff --git a/Runtime/Library/Interfaces/Damageable.cs b/Runtime/Library/Interfaces/Damageable.cs new file mode 100644 index 0000000..65e6674 --- /dev/null +++ b/Runtime/Library/Interfaces/Damageable.cs @@ -0,0 +1,18 @@ +using UnityEngine; + +namespace RealMethod +{ + public interface IDamageable + { + /// + /// Simple damage (only amount + optional source) + /// + /// Incloude all data that need for reperesent damage + void TakeDamage(HitData HitInfo); + /// + /// Called when the object dies or is destroyed due to damage. + /// + void Die(); + } + +} \ No newline at end of file diff --git a/Runtime/Library/Interfaces/Damage.cs.meta b/Runtime/Library/Interfaces/Damageable.cs.meta similarity index 100% rename from Runtime/Library/Interfaces/Damage.cs.meta rename to Runtime/Library/Interfaces/Damageable.cs.meta diff --git a/Runtime/Library/Interfaces/Initializable.cs b/Runtime/Library/Interfaces/Initializable.cs index abd8185..2681c1f 100644 --- a/Runtime/Library/Interfaces/Initializable.cs +++ b/Runtime/Library/Interfaces/Initializable.cs @@ -1,18 +1,35 @@ +using UnityEngine; + namespace RealMethod { - public interface IInitializable + + public interface ISpawn + { + void OnSpawn(); + } + public interface ISpawnWithAuthor + { + void OnSpawn(Object author); + } + public interface ISpawnWithArgument + { + void OnSpawn(TArgument argument); + } + public interface ISpawnWithTwoArgument { - void Initialize(); + void OnSpawn(TArgumentA argumentA, TArgumentB argumentB); } - public interface IInitializableWithArgument + public interface IDespawn { - void Initialize(TArgument argument); + void OnDespawn(); } - public interface IInitializableWithTwoArgument + public interface IDespawnWithAuthor { - void Initialize(TArgumentA argumentA, TArgumentB argumentB); + void OnDespawn(Object author); } + + } diff --git a/Runtime/Library/Interfaces/Label.cs b/Runtime/Library/Interfaces/Label.cs new file mode 100644 index 0000000..aa7d5b2 --- /dev/null +++ b/Runtime/Library/Interfaces/Label.cs @@ -0,0 +1,32 @@ +namespace RealMethod +{ + public interface ILabel + { + + } + + + // public interface IDamage + // { + // /// + // /// Returns true if the object is already dead. + // /// + // bool IsDead { get; } + + // } + + /// + /// Interface for objects that can take and restore damage. + /// + /// The type representing TakeDamage data (e.g., int, float, struct). + // public interface IDamageable : IDamageable where T : struct where R : struct + // { + // /// + // /// Applies damage to the object. + // /// + // /// The raw data of damage. + // /// The GameObject or system causing the damage. + // void TakeDamage(T data); + // void Restore(R amount); + // } +} \ No newline at end of file diff --git a/Runtime/Library/Interfaces/Label.cs.meta b/Runtime/Library/Interfaces/Label.cs.meta new file mode 100644 index 0000000..a56f9cc --- /dev/null +++ b/Runtime/Library/Interfaces/Label.cs.meta @@ -0,0 +1,2 @@ +fileFormatVersion: 2 +guid: 5afe719b2c95deb4fb7bf11e45120c68 \ No newline at end of file diff --git a/Runtime/Library/SharedScripts/Structs/HitData.cs b/Runtime/Library/SharedScripts/Structs/HitData.cs new file mode 100644 index 0000000..1449dc9 --- /dev/null +++ b/Runtime/Library/SharedScripts/Structs/HitData.cs @@ -0,0 +1,65 @@ +using UnityEngine; + +namespace RealMethod +{ + public struct HitData + { + // Actors + public GameObject attacker; + public GameObject target; + + // Components + public Collider collider; + public Rigidbody rigidbody; + + // Location + public Vector3 point; // Impact point + public Vector3 normal; // Impact normal + public Vector3 traceStart; // Trace start + public Vector3 traceEnd; // Trace end + + // Direction + public Vector3 direction; + + // Distance + public float distance; + + // Damage + public float damage; + + // Surface info + public PhysicsMaterial physicMaterial; + + // State + public bool blockingHit; + public bool startPenetrating; + + // Utility constructor + public HitData(RaycastHit hit, GameObject attacker, float damage) + { + this.attacker = attacker; + this.target = hit.collider ? hit.collider.gameObject : null; + + collider = hit.collider; + rigidbody = hit.rigidbody; + + point = hit.point; + normal = hit.normal; + + traceStart = Vector3.zero; + traceEnd = Vector3.zero; + + direction = Vector3.zero; + + distance = hit.distance; + + this.damage = damage; + + physicMaterial = hit.collider ? hit.collider.sharedMaterial : null; + + blockingHit = true; + startPenetrating = false; + } + } + +} \ No newline at end of file diff --git a/Runtime/Library/SharedScripts/Structs/HitData.cs.meta b/Runtime/Library/SharedScripts/Structs/HitData.cs.meta new file mode 100644 index 0000000..cccc9c2 --- /dev/null +++ b/Runtime/Library/SharedScripts/Structs/HitData.cs.meta @@ -0,0 +1,2 @@ +fileFormatVersion: 2 +guid: d33abd97910ff4347bf0d3399d36925c \ No newline at end of file diff --git a/Runtime/Library/Utilities/Trace_Library.cs b/Runtime/Library/Utilities/Trace_Library.cs index c8c582c..c982cbb 100644 --- a/Runtime/Library/Utilities/Trace_Library.cs +++ b/Runtime/Library/Utilities/Trace_Library.cs @@ -36,7 +36,6 @@ public static bool Line(Vector3 Start, Vector3 Direction, float Length, LayerMas Debug.DrawRay(Start, Direction * debuglength, debugcolor); return Result; } - public static bool Line(Vector3 Start, Vector3 Direction, float Length, LayerMask Layer, QueryTriggerInteraction TriggerInteraction, out RaycastHit HitResult) { bool Result; @@ -46,7 +45,6 @@ public static bool Line(Vector3 Start, Vector3 Direction, float Length, LayerMas Debug.DrawRay(Start, Direction * debuglength, debugcolor); return Result; } - public static bool Line(Vector3 Start, Vector3 Direction, float Length, LayerMask Layer, out RaycastHit HitResult) { bool Result; @@ -56,7 +54,6 @@ public static bool Line(Vector3 Start, Vector3 Direction, float Length, LayerMas Debug.DrawRay(Start, Direction * debuglength, debugcolor); return Result; } - public static bool Line(Vector3 Start, Vector3 Direction, float Length, out RaycastHit HitResult) { bool Result; diff --git a/Runtime/Pattern/Managers/UIManager.cs b/Runtime/Pattern/Managers/UIManager.cs index 6ee6eee..17c4b27 100644 --- a/Runtime/Pattern/Managers/UIManager.cs +++ b/Runtime/Pattern/Managers/UIManager.cs @@ -133,11 +133,11 @@ public T CreateLayer(string name, Object creator = null) where T : MonoBehavi { if (creator != null) { - widget.GetWidgetClass().SendSpawnEvent(creator); + widget.GetWidgetClass().InvokeSpawnEvent(creator); } else { - widget.GetWidgetClass().SendSpawnEvent(this, SendMessageOptions.DontRequireReceiver); + widget.GetWidgetClass().InvokeSpawnEvent(this, SendMessageOptions.DontRequireReceiver); } } return TargetClass; @@ -188,11 +188,11 @@ public T CreateLayer(string name, VisualTreeAsset UIAsset, Object creator = n { if (creator != null) { - widget.GetWidgetClass().SendSpawnEvent(creator); + widget.GetWidgetClass().InvokeSpawnEvent(creator); } else { - widget.GetWidgetClass().SendSpawnEvent(this, SendMessageOptions.DontRequireReceiver); + widget.GetWidgetClass().InvokeSpawnEvent(this, SendMessageOptions.DontRequireReceiver); } } return TargetClass; @@ -207,11 +207,11 @@ public GameObject AddLayer(string name, UPrefab Prefab, Object spawner = null) GameObject SpawnedObject = Instantiate(Prefab, header.position, Quaternion.identity, header); if (spawner != null) { - SpawnedObject.SendSpawnEvent(spawner); + SpawnedObject.InvokeSpawnEvent(spawner); } else { - SpawnedObject.SendSpawnEvent(this, SendMessageOptions.DontRequireReceiver); + SpawnedObject.InvokeSpawnEvent(this, SendMessageOptions.DontRequireReceiver); } SpawnedObject.name = name; Layers.Add(name, SpawnedObject); @@ -227,11 +227,11 @@ public T AddLayer(string name, UPrefab Prefab, Object spawner = null) where T GameObject SpawnedObject = Instantiate(Prefab, header.position, Quaternion.identity, header); if (spawner != null) { - SpawnedObject.SendSpawnEvent(spawner); + SpawnedObject.InvokeSpawnEvent(spawner); } else { - SpawnedObject.SendSpawnEvent(this, SendMessageOptions.DontRequireReceiver); + SpawnedObject.InvokeSpawnEvent(this, SendMessageOptions.DontRequireReceiver); } SpawnedObject.name = name; Layers.Add(name, SpawnedObject); @@ -261,11 +261,11 @@ public bool RemoveLayer(string name, Object despawner = null) { if (despawner != null) { - Target.SendDespawnEvent(despawner); + Target.InvokeDespawnEvent(despawner); } else { - Target.SendDespawnEvent(this, SendMessageOptions.DontRequireReceiver); + Target.InvokeDespawnEvent(this, SendMessageOptions.DontRequireReceiver); } Destroy(Target); } diff --git a/Runtime/ReadySet/Commands/Execut/C_Death.cs b/Runtime/ReadySet/Commands/Execut/C_Death.cs index c6fbd4a..d46712f 100644 --- a/Runtime/ReadySet/Commands/Execut/C_Death.cs +++ b/Runtime/ReadySet/Commands/Execut/C_Death.cs @@ -11,11 +11,6 @@ public sealed class C_Death : Command private bool UseExecuter = true; [SerializeField, ConditionalHide("UseExecuter", true, true)] private GameObject Target; - [Header("Method")] - [SerializeField] - private bool WithInterface = true; - [SerializeField] - private bool WithSendMessage = false; // Base ExecutCommand Methods @@ -56,25 +51,7 @@ private void ApplyDeath(GameObject target) return; } - // Interface - if (WithInterface) - { - IDamage interfce = target.GetComponent(); - if (interfce != null) - { - interfce.Die(); - } - else - { - Debug.LogError($"IDamage interface not found on the {target}."); - } - } - - // SendMessage - if (WithSendMessage) - { - target.SendMessage("Die", SendMessageOptions.RequireReceiver); - } + target.Death(); } } diff --git a/Runtime/ReadySet/Components/Time/DestroyAfterDelay.cs b/Runtime/ReadySet/Components/Time/DestroyAfterDelay.cs index de8cfde..c14b684 100644 --- a/Runtime/ReadySet/Components/Time/DestroyAfterDelay.cs +++ b/Runtime/ReadySet/Components/Time/DestroyAfterDelay.cs @@ -3,12 +3,12 @@ namespace RealMethod { [AddComponentMenu("RealMethod/Time/DestroyAfterDelay")] - public sealed class DestroyAfterDelay : MonoBehaviour, IInitializableWithArgument + public sealed class DestroyAfterDelay : MonoBehaviour, ISpawnWithArgument { public float Delay = 5; // Implement IInitializableWithArgument Interface - public void Initialize(float argument) + public void OnSpawn(float argument) { Delay = argument; } diff --git a/Runtime/ReadySet/Services/SpawanService.cs b/Runtime/ReadySet/Services/SpawanService.cs index 1b6cba3..083b573 100644 --- a/Runtime/ReadySet/Services/SpawanService.cs +++ b/Runtime/ReadySet/Services/SpawanService.cs @@ -307,11 +307,11 @@ public static T Clone(T original, Object spawner = null) where T : Object var target = Object.Instantiate(original); if (target is MonoBehaviour mono) { - mono.SendSpawnEvent(spawner); + mono.InvokeSpawnEvent(spawner); } else if (target is GameObject obj) { - obj.SendSpawnEvent(spawner); + obj.InvokeSpawnEvent(spawner); } else { @@ -331,11 +331,11 @@ public static T Clone(T original, Transform parent, Object spawner = null) wh var target = Object.Instantiate(original, parent); if (target is MonoBehaviour mono) { - mono.SendSpawnEvent(spawner); + mono.InvokeSpawnEvent(spawner); } else if (target is GameObject obj) { - obj.SendSpawnEvent(spawner); + obj.InvokeSpawnEvent(spawner); } else { @@ -355,11 +355,11 @@ public static T Clone(T original, Vector3 position, Quaternion rotation, Obje var target = Object.Instantiate(original, position, rotation); if (target is MonoBehaviour mono) { - mono.SendSpawnEvent(spawner); + mono.InvokeSpawnEvent(spawner); } else if (target is GameObject obj) { - obj.SendSpawnEvent(spawner); + obj.InvokeSpawnEvent(spawner); } else { @@ -379,11 +379,11 @@ public static T Clone(T original, Transform parent, bool worldPositionStays, var target = Object.Instantiate(original, parent, worldPositionStays); if (target is MonoBehaviour mono) { - mono.SendSpawnEvent(spawner); + mono.InvokeSpawnEvent(spawner); } else if (target is GameObject obj) { - obj.SendSpawnEvent(spawner); + obj.InvokeSpawnEvent(spawner); } else { @@ -403,7 +403,7 @@ public static GameObject Prefab(PrefabCore prefab, Object spawner = null) if (spawner != null) { GameObject target = Object.Instantiate(prefab, Game.World.transform); - target.SendSpawnEvent(spawner); + target.InvokeSpawnEvent(spawner); return target; } else @@ -416,7 +416,7 @@ public static GameObject Prefab(PrefabCore prefab, Transform parent, Object spaw if (spawner != null) { GameObject target = Object.Instantiate(prefab, parent); - target.SendSpawnEvent(spawner); + target.InvokeSpawnEvent(spawner); return target; } else @@ -429,7 +429,7 @@ public static GameObject Prefab(PrefabCore prefab, Transform parent, bool instan if (spawner != null) { GameObject target = Object.Instantiate(prefab, parent, instantiateInWorldSpace); - target.SendSpawnEvent(spawner); + target.InvokeSpawnEvent(spawner); return target; } else @@ -442,7 +442,7 @@ public static GameObject Prefab(PrefabCore prefab, Vector3 position, Vector3 rot if (spawner != null) { GameObject target = Object.Instantiate(prefab, position, Quaternion.Euler(rotation)); - target.SendSpawnEvent(spawner); + target.InvokeSpawnEvent(spawner); return target; } else @@ -455,7 +455,7 @@ public static GameObject Prefab(PrefabCore prefab, Vector3 position, Quaternion if (spawner != null) { GameObject target = Object.Instantiate(prefab, position, rotation); - target.SendSpawnEvent(spawner); + target.InvokeSpawnEvent(spawner); return target; } else @@ -468,7 +468,7 @@ public static GameObject Prefab(PrefabCore prefab, Vector3 position, Object spaw if (spawner != null) { GameObject target = Object.Instantiate(prefab, position, Quaternion.identity); - target.SendSpawnEvent(spawner); + target.InvokeSpawnEvent(spawner); return target; } else @@ -481,7 +481,7 @@ public static GameObject Prefab(PrefabCore prefab, Vector3 position, Vector3 rot if (spawner != null) { GameObject target = Object.Instantiate(prefab, position, Quaternion.Euler(rotation), parent); - target.SendSpawnEvent(spawner); + target.InvokeSpawnEvent(spawner); return target; } else @@ -494,7 +494,7 @@ public static GameObject Prefab(PrefabCore prefab, UnityEngine.SceneManagement.S if (spawner != null) { GameObject target = Object.Instantiate(prefab, scene) as GameObject; - target.SendSpawnEvent(spawner); + target.InvokeSpawnEvent(spawner); return target; } else @@ -508,7 +508,7 @@ public static T Prefab(PrefabCore prefab, Object spawner = null) where T : if (spawner != null) { T target = Object.Instantiate(prefab.GetMainComponent()); - target.SendSpawnEvent(spawner); + target.InvokeSpawnEvent(spawner); return target; } else @@ -521,7 +521,7 @@ public static T Prefab(PrefabCore prefab, Transform parent, Object spawner if (spawner != null) { T target = Object.Instantiate(prefab.GetMainComponent(), parent); - target.SendSpawnEvent(spawner); + target.InvokeSpawnEvent(spawner); return target; } else @@ -534,7 +534,7 @@ public static T Prefab(PrefabCore prefab, Vector3 position, Quaternion rot if (spawner != null) { T target = Object.Instantiate(prefab.GetMainComponent(), position, rotation); - target.SendSpawnEvent(spawner); + target.InvokeSpawnEvent(spawner); return target; } else @@ -547,7 +547,7 @@ public static T Prefab(PrefabCore prefab, Transform parent, bool worldPosi if (spawner != null) { T target = Object.Instantiate(prefab.GetMainComponent(), parent, worldPositionStays); - target.SendSpawnEvent(spawner); + target.InvokeSpawnEvent(spawner); return target; } else @@ -652,7 +652,7 @@ public static T Component(GameObject target, Object spawner = null) where T : var result = target.AddComponent(); if (spawner != null) { - result.SendSpawnEvent(spawner); + result.InvokeSpawnEvent(spawner); } return target.AddComponent(); } @@ -852,7 +852,7 @@ public static bool GameObject(GameObject target, Object spawner = null, bool deb { if (spawner != null) { - target.SendDespawnEvent(spawner); + target.InvokeDespawnEvent(spawner); } Object.Destroy(target); return true; From 6e349139a34c7b52f627154dd693d0fbbce5b2b5 Mon Sep 17 00:00:00 2001 From: Alijimpa Date: Sun, 5 Apr 2026 11:09:51 +0330 Subject: [PATCH 081/204] Implement Attack for Socket --- Runtime/Library/Extension/GameObject.cs | 16 +++++++++++++++- Runtime/Library/Extension/Transform.cs | 2 +- 2 files changed, 16 insertions(+), 2 deletions(-) diff --git a/Runtime/Library/Extension/GameObject.cs b/Runtime/Library/Extension/GameObject.cs index 2005692..979d93d 100644 --- a/Runtime/Library/Extension/GameObject.cs +++ b/Runtime/Library/Extension/GameObject.cs @@ -47,13 +47,27 @@ public static void ApplyDamage(this GameObject target, HitData hitdata) } } /// + /// Attaches this GameObject to a specified Socket transform, optionally preserving world position. + /// Also sends an "OnAttach" message to the owner GameObject. + /// + /// The GameObject to attach. + /// The Transform to get Socket from that. + /// The Socket name to attach to + /// If true, the parent-relative position, rotation, and scale are modified so that the last local transformation is equal to the world transformation. + public static void Attach(this GameObject target, Transform parent, Name16 socketname, bool worldPositionStays = true) + { + Transform MySocket = parent.GetSocket(socketname); + MySocket.SetParent(parent.transform, worldPositionStays); + target.SendMessage(GameMessage.Attach, parent, SendMessageOptions.DontRequireReceiver); + } + /// /// Attaches this GameObject to a specified parent GameObject, optionally preserving world position. /// Also sends an "OnAttach" message to the owner GameObject. /// /// The GameObject to attach. /// The GameObject to attach to. /// If true, the parent-relative position, rotation, and scale are modified so that the last local transformation is equal to the world transformation. - public static void Attach(this GameObject target, GameObject parent, bool worldPositionStays) + public static void Attach(this GameObject target, GameObject parent, bool worldPositionStays = true) { target.transform.SetParent(parent.transform, worldPositionStays); target.SendMessage(GameMessage.Attach, parent, SendMessageOptions.DontRequireReceiver); diff --git a/Runtime/Library/Extension/Transform.cs b/Runtime/Library/Extension/Transform.cs index 39c14f8..606fb2f 100644 --- a/Runtime/Library/Extension/Transform.cs +++ b/Runtime/Library/Extension/Transform.cs @@ -10,7 +10,7 @@ public static void SetTransform(this Transform trans, Transform newtransform) trans.rotation = newtransform.rotation; trans.localScale = newtransform.localScale; } - public static Transform FindSocket(this Transform trans, Name16 socketname) + public static Transform GetSocket(this Transform trans, Name16 socketname) { foreach (var item in trans.GetComponentsInChildren()) { From b6d4a64a29cc71d2f043969c8efe856a93ffe4bc Mon Sep 17 00:00:00 2001 From: Alijimpa Date: Sun, 5 Apr 2026 15:44:44 +0330 Subject: [PATCH 082/204] REfine Asset Spawning and Project Setting Asset --- Runtime/Core/Definitions/Assets.cs | 17 ++++++++++++++--- .../Core/ProjectSetting/ProjectSettingAsset.cs | 2 +- Runtime/ReadySet/Services/SpawanService.cs | 16 +++++++++++----- 3 files changed, 26 insertions(+), 9 deletions(-) diff --git a/Runtime/Core/Definitions/Assets.cs b/Runtime/Core/Definitions/Assets.cs index c28237c..3666fb6 100644 --- a/Runtime/Core/Definitions/Assets.cs +++ b/Runtime/Core/Definitions/Assets.cs @@ -8,17 +8,28 @@ namespace RealMethod public interface IAsset { PrimitiveAsset GetAsset(); - void OnSpawned(Object spawner); } // PrimitiveAsset: is a ScriptableObject with some functions & IAsset interface - public abstract class PrimitiveAsset : ScriptableObject, IAsset + public abstract class PrimitiveAsset : ScriptableObject, IAsset, ISpawn, ISpawnWithAuthor { // Implement IAsset Interface PrimitiveAsset IAsset.GetAsset() { return this; } - public virtual void OnSpawned(Object spawner) + // Implement ISpawn interface + void ISpawn.OnSpawn() + { + OnSpawn(null); + } + // Implement ISpawnWithAuthor interface + void ISpawnWithAuthor.OnSpawn(Object author) + { + OnSpawn(author); + } + + + protected virtual void OnSpawn(Object spawner) { } diff --git a/Runtime/Core/ProjectSetting/ProjectSettingAsset.cs b/Runtime/Core/ProjectSetting/ProjectSettingAsset.cs index df247c6..bf009a1 100644 --- a/Runtime/Core/ProjectSetting/ProjectSettingAsset.cs +++ b/Runtime/Core/ProjectSetting/ProjectSettingAsset.cs @@ -5,7 +5,7 @@ namespace RealMethod { // Real Method Setting Storage - public class ProjectSettingAsset : ScriptableObject + public class ProjectSettingAsset : PrimitiveAsset { [Serializable] public enum AssetFormat diff --git a/Runtime/ReadySet/Services/SpawanService.cs b/Runtime/ReadySet/Services/SpawanService.cs index 083b573..43986f3 100644 --- a/Runtime/ReadySet/Services/SpawanService.cs +++ b/Runtime/ReadySet/Services/SpawanService.cs @@ -691,17 +691,23 @@ public static T Command(CPrefab prefab, MonoBehaviour owner) where T : Comman } public static T Asset(Object spawner = null) where T : PrimitiveAsset { + var target = ScriptableObject.CreateInstance(); if (spawner != null) { - var target = ScriptableObject.CreateInstance(); - IAsset provider = target; - provider.OnSpawned(spawner); - return target; + if (target is ISpawnWithAuthor provider) + { + provider.OnSpawn(spawner); + } + } else { - return ScriptableObject.CreateInstance(); + if (target is ISpawn provider) + { + provider.OnSpawn(); + } } + return target; } // Task From edc846a016c7db78929cbd81706b6e0f41d5f8dc Mon Sep 17 00:00:00 2001 From: Alijimpa Date: Sun, 5 Apr 2026 16:23:31 +0330 Subject: [PATCH 083/204] Refine SameNaming warning for spawning --- Runtime/ReadySet/Presets/PoolAsset/AudioPool.cs | 6 +++--- Runtime/ReadySet/Presets/PoolAsset/ParticlePool.cs | 5 +++-- Runtime/ReadySet/Presets/PoolAsset/PrefabPool.cs | 6 +++--- 3 files changed, 9 insertions(+), 8 deletions(-) diff --git a/Runtime/ReadySet/Presets/PoolAsset/AudioPool.cs b/Runtime/ReadySet/Presets/PoolAsset/AudioPool.cs index 9e05671..6bd6c83 100644 --- a/Runtime/ReadySet/Presets/PoolAsset/AudioPool.cs +++ b/Runtime/ReadySet/Presets/PoolAsset/AudioPool.cs @@ -6,7 +6,7 @@ namespace RealMethod { [CreateAssetMenu(fileName = "AudioPool", menuName = "RealMethod/Pool/AudioPool", order = 1)] - public sealed class AudioPool : PoolAsset , IPoolSpawner + public sealed class AudioPool : PoolAsset, IPoolSpawner { [Header("Setting")] [SerializeField] @@ -21,7 +21,7 @@ public sealed class AudioPool : PoolAsset , IPoolSpawner OnSpawn; + public event Action OnSpawned; // Private Variable @@ -87,7 +87,7 @@ public AudioSource Spawn(int index) public AudioSource Spawn() { AudioSource result = Request(); - OnSpawn?.Invoke(result); + OnSpawned?.Invoke(result); return result; } diff --git a/Runtime/ReadySet/Presets/PoolAsset/ParticlePool.cs b/Runtime/ReadySet/Presets/PoolAsset/ParticlePool.cs index b53afae..65ff9d4 100644 --- a/Runtime/ReadySet/Presets/PoolAsset/ParticlePool.cs +++ b/Runtime/ReadySet/Presets/PoolAsset/ParticlePool.cs @@ -14,7 +14,8 @@ public sealed class ParticlePool : PoolAsset , IPoolSpawner OnSpawn; + public event Action OnSpawned; + // Private Variable private byte UseCacheData = 0; //0:NoCashing 1:CachePosition 2:CachePosition&Rotation 3:CacheTransform @@ -48,7 +49,7 @@ public ParticleSystem Spawn(Vector3 location) public ParticleSystem Spawn() { ParticleSystem result = Request(); - OnSpawn?.Invoke(result); + OnSpawned?.Invoke(result); return result; } diff --git a/Runtime/ReadySet/Presets/PoolAsset/PrefabPool.cs b/Runtime/ReadySet/Presets/PoolAsset/PrefabPool.cs index 5b92d3f..79c25ec 100644 --- a/Runtime/ReadySet/Presets/PoolAsset/PrefabPool.cs +++ b/Runtime/ReadySet/Presets/PoolAsset/PrefabPool.cs @@ -16,7 +16,7 @@ public sealed class PrefabPool : PoolAsset, IPoolSpawner, private float duration = 2; //Actions - public Action OnSpawn; + public event Action OnSpawned; // Private Variable @@ -74,14 +74,14 @@ public Transform Spawn(float overrideDuration) { CacheDuration = overrideDuration; Transform result = Request(); - OnSpawn?.Invoke(result); + OnSpawned?.Invoke(result); return result; } public Transform Spawn() { CacheDuration = duration; Transform result = Request(); - OnSpawn?.Invoke(result); + OnSpawned?.Invoke(result); return result; } public void Despawn() From ba5da64db815ff5620520183cc0bca7c7a56618a Mon Sep 17 00:00:00 2001 From: Alijimpa Date: Sun, 5 Apr 2026 16:23:50 +0330 Subject: [PATCH 084/204] Move Primitive Asset EditorPlay --- Runtime/Core/Architecture/GameBridge.cs | 24 ------------------------ Runtime/Core/Definitions/Assets.cs | 13 +++++++++++++ 2 files changed, 13 insertions(+), 24 deletions(-) diff --git a/Runtime/Core/Architecture/GameBridge.cs b/Runtime/Core/Architecture/GameBridge.cs index c9e308a..09e3a25 100644 --- a/Runtime/Core/Architecture/GameBridge.cs +++ b/Runtime/Core/Architecture/GameBridge.cs @@ -4,11 +4,6 @@ using UnityEngine.SceneManagement; using System.Collections.Generic; - -#if UNITY_EDITOR -using UnityEditor; -#endif - namespace RealMethod { @@ -87,8 +82,6 @@ public interface ILoadScneBridge } - - /// /// Base class for any gamebridge in the framework. /// Provides core functionality for: @@ -573,22 +566,5 @@ private IEnumerator LoadWorldAsync(WorldAsset WS) } - -#if UNITY_EDITOR - [InitializeOnEnterPlayMode] // Runs when entering Play Mode in Editor - private static void EditorPlayModeInit() - { - var assets = Resources.FindObjectsOfTypeAll(); - foreach (var asset in assets) - { - if (asset.IsProjectAsset()) - { - asset.OnEditorPlay(); - } - } - } -#endif - - } } \ No newline at end of file diff --git a/Runtime/Core/Definitions/Assets.cs b/Runtime/Core/Definitions/Assets.cs index 3666fb6..8387b86 100644 --- a/Runtime/Core/Definitions/Assets.cs +++ b/Runtime/Core/Definitions/Assets.cs @@ -57,6 +57,19 @@ public bool IsProjectAsset() #if UNITY_EDITOR + [InitializeOnEnterPlayMode] // Runs when entering Play Mode in Editor + private static void EditorPlayModeInit() + { + var assets = Resources.FindObjectsOfTypeAll(); + foreach (var asset in assets) + { + if (asset.IsProjectAsset()) + { + asset.OnEditorPlay(); + } + } + } + public virtual void OnEditorPlay() { Debug.Log($"[{GetType()}] -> {name} OnEditorPlay called."); From 0afa3707f39163e8b7bc597cc326a76f5887f44e Mon Sep 17 00:00:00 2001 From: Alijimpa Date: Mon, 6 Apr 2026 10:08:44 +0330 Subject: [PATCH 085/204] Implement CompileGuard System --- Editor/Core/InitializeOnLoad/CompileGuard.cs | 149 ++++++++++++++++++ .../InitializeOnLoad/CompileGuard.cs.meta | 2 + .../ConfigAssetInitializer.cs | 86 ---------- .../Rules.meta} | 2 +- .../Rules/ConfigAssetsRule.cs | 88 +++++++++++ .../ConfigAssetsRule.cs.meta} | 0 .../ProjectSetting/ProjectSettingProvider.cs | 105 +++++++++++- .../Sections/CompileRule_Section.cs | 85 ++++++++++ .../Sections/CompileRule_Section.cs.meta | 2 + 9 files changed, 430 insertions(+), 89 deletions(-) create mode 100644 Editor/Core/InitializeOnLoad/CompileGuard.cs create mode 100644 Editor/Core/InitializeOnLoad/CompileGuard.cs.meta delete mode 100644 Editor/Core/InitializeOnLoad/ConfigAssetInitializer.cs rename Editor/Core/{InitializeOnEnterPlayMode.meta => InitializeOnLoad/Rules.meta} (77%) create mode 100644 Editor/Core/InitializeOnLoad/Rules/ConfigAssetsRule.cs rename Editor/Core/InitializeOnLoad/{ConfigAssetInitializer.cs.meta => Rules/ConfigAssetsRule.cs.meta} (100%) create mode 100644 Editor/Core/ProjectSetting/Sections/CompileRule_Section.cs create mode 100644 Editor/Core/ProjectSetting/Sections/CompileRule_Section.cs.meta diff --git a/Editor/Core/InitializeOnLoad/CompileGuard.cs b/Editor/Core/InitializeOnLoad/CompileGuard.cs new file mode 100644 index 0000000..1bfce19 --- /dev/null +++ b/Editor/Core/InitializeOnLoad/CompileGuard.cs @@ -0,0 +1,149 @@ +using UnityEditor; +using UnityEditor.Compilation; +using System; +using UnityEngine; + + +namespace RealMethod.Editor +{ + public abstract class CompileRule + { + public enum RuleMode + { + Disable = 0, + CompilationPipeline = 1, + EditorApplication = 2 + } + + public CompileRule() + { + Initilized(); + } + + + protected abstract void Initilized(); + public abstract RuleMode GetRuleMode(); + public abstract Type GetBaseType(); + public abstract void OnCheck(Type type); + } + + + [InitializeOnLoad] + public static class CompileGuard + { + private static ProjectSettingAsset ProjectSetting_Cache; + private static ProjectSettingAsset ProjectSetting + { + get + { + if (ProjectSetting_Cache == null) + { + if (!RM_Editor.TryGetSettingAsset(out ProjectSetting_Cache)) + { + return null; + } + } + return ProjectSetting_Cache; + } + } + private static System.Reflection.Assembly[] Assemblies; + private static CompileRule[] Ruls; + + public static Type[] DefaultRuls = new Type[1] { + // Array of ruls to that should be run always for RealMethod + typeof(ConfigAssetsRule), + }; + + + static CompileGuard() + { + CompilationPipeline.compilationFinished += OnCompilationFinished; + EditorApplication.delayCall += OnEditorUpdated; + } + + private static void OnCompilationFinished(object obj) + { + CheckRuls(CompileRule.RuleMode.CompilationPipeline); + } + private static void OnEditorUpdated() + { + CheckRuls(CompileRule.RuleMode.EditorApplication); + } + private static void CheckRuls(CompileRule.RuleMode mode) + { + if (ProjectSetting == null) + return; + + if (Ruls == null) + { + Type[] RulsClass = ProjectSetting.GetCompileRules(); + if (RulsClass == null) + return; + + Ruls = new CompileRule[RulsClass.Length]; + for (int i = 0; i < RulsClass.Length; i++) + { + if (RulsClass[i] == null) + continue; + + if (typeof(CompileRule).IsAssignableFrom(RulsClass[i])) + { + try + { + Ruls[i] = (CompileRule)Activator.CreateInstance(RulsClass[i]); + } + catch (Exception ex) + { + Debug.LogError($"Failed to instantiate {RulsClass[i]}: {ex.Message}."); + return; + } + } + else + { + Debug.LogError($"Type {RulsClass[i]} is not assignable to CompileRule."); + return; + } + } + } + + if (Assemblies == null) + { + Assemblies = AppDomain.CurrentDomain.GetAssemblies(); + } + + Type[] types; + foreach (var assembly in Assemblies) + { + try + { + types = assembly.GetTypes(); + } + catch + { + continue; + } + + foreach (var type in types) + { + if (Ruls == null) + return; + + foreach (var rule in Ruls) + { + if (rule == null) + continue; + if (rule.GetRuleMode() != mode) + continue; + + if (type.IsSubclassOf(rule.GetBaseType())) + { + rule.OnCheck(type); + } + } + } + } + } + } + + +} diff --git a/Editor/Core/InitializeOnLoad/CompileGuard.cs.meta b/Editor/Core/InitializeOnLoad/CompileGuard.cs.meta new file mode 100644 index 0000000..169716b --- /dev/null +++ b/Editor/Core/InitializeOnLoad/CompileGuard.cs.meta @@ -0,0 +1,2 @@ +fileFormatVersion: 2 +guid: 7177b9c29b1bfdf4998168fa58642b35 \ No newline at end of file diff --git a/Editor/Core/InitializeOnLoad/ConfigAssetInitializer.cs b/Editor/Core/InitializeOnLoad/ConfigAssetInitializer.cs deleted file mode 100644 index 967ac64..0000000 --- a/Editor/Core/InitializeOnLoad/ConfigAssetInitializer.cs +++ /dev/null @@ -1,86 +0,0 @@ -using UnityEditor; -using UnityEngine; -using System; -using System.Reflection; -using System.Linq; - -namespace RealMethod.Editor -{ - [InitializeOnLoad] - public static class ConfigAssetInitializer - { - static ConfigAssetInitializer() - { - EditorApplication.delayCall += ValidateAllConfigs; - } - - public static void ValidateAllConfigs() - { - var configTypes = AppDomain.CurrentDomain.GetAssemblies() - .SelectMany(a => a.GetTypes()) - .Where(t => t.IsSubclassOf(typeof(ConfigAsset))); - - foreach (var type in configTypes) - { - // 🔹 Check fields - var badFields = type.GetFields(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.DeclaredOnly) - .Where(f => !f.IsInitOnly && !f.IsLiteral && !f.IsDefined(typeof(SerializeField), false)) - .ToList(); - - foreach (var f in badFields) - { - Debug.LogError($"❌ '{type.Name}' has non-readonly field '{f.Name}' — only readonly fields allowed in Config-derived classes."); - } - - // 🔹 Check methods - var badMethods = type.GetMethods(BindingFlags.Instance | BindingFlags.Public | BindingFlags.DeclaredOnly) - .Where(m => !m.IsSpecialName && !m.IsConstructor) - .Where(m => ViolatesPureMethodRules(m)) - .ToList(); - - foreach (var m in badMethods) - { - Debug.LogError($"❌ '{type.Name}' public method '{m.Name}' modifies state — only pure getter/return methods are allowed in Config-derived classes."); - } - } - } - private static bool ViolatesPureMethodRules(MethodInfo method) - { - try - { - var body = method.GetMethodBody(); - if (body == null) - return false; - - var il = body.GetILAsByteArray(); - if (il == null) - return false; - - // Look for IL opcodes that store data or call setters - for (int i = 0; i < il.Length - 1; i++) - { - byte b = il[i]; - byte next = il[i + 1]; - - // Store field (stfld or stsfld) - if (b == 0x7D || b == 0x80) - return true; - - // Callvirt / call that might be setter - if (b == 0x28) - { - var tokens = method.Module.ResolveMethod(BitConverter.ToInt32(il, i + 1)); - if (tokens.Name.StartsWith("set_", StringComparison.Ordinal)) - return true; - } - } - } - catch - { - // Ignore methods that can't be inspected - } - - return false; - } - } -} \ No newline at end of file diff --git a/Editor/Core/InitializeOnEnterPlayMode.meta b/Editor/Core/InitializeOnLoad/Rules.meta similarity index 77% rename from Editor/Core/InitializeOnEnterPlayMode.meta rename to Editor/Core/InitializeOnLoad/Rules.meta index 1e69ed9..553a751 100644 --- a/Editor/Core/InitializeOnEnterPlayMode.meta +++ b/Editor/Core/InitializeOnLoad/Rules.meta @@ -1,5 +1,5 @@ fileFormatVersion: 2 -guid: c41562d680cd7724aaed78043c99689b +guid: 24f3441ca9697e34f926a8ca3105ac53 folderAsset: yes DefaultImporter: externalObjects: {} diff --git a/Editor/Core/InitializeOnLoad/Rules/ConfigAssetsRule.cs b/Editor/Core/InitializeOnLoad/Rules/ConfigAssetsRule.cs new file mode 100644 index 0000000..dc78743 --- /dev/null +++ b/Editor/Core/InitializeOnLoad/Rules/ConfigAssetsRule.cs @@ -0,0 +1,88 @@ +using System; +using System.Linq; +using System.Reflection; +using UnityEngine; + +namespace RealMethod.Editor +{ + + public class ConfigAssetsRule : CompileRule + { + // CompileRule Methods + protected override void Initilized() + { + } + public override RuleMode GetRuleMode() + { + return RuleMode.EditorApplication; + } + public override Type GetBaseType() + { + return typeof(ConfigAsset); + } + public override void OnCheck(Type type) + { + // 🔹 Check fields + var badFields = type.GetFields(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.DeclaredOnly) + .Where(f => !f.IsInitOnly && !f.IsLiteral && !f.IsDefined(typeof(SerializeField), false)) + .ToList(); + + foreach (var f in badFields) + { + Debug.LogError($"❌ '{type.Name}' has non-readonly field '{f.Name}' — only readonly fields allowed in Config-derived classes."); + } + + // 🔹 Check methods + var badMethods = type.GetMethods(BindingFlags.Instance | BindingFlags.Public | BindingFlags.DeclaredOnly) + .Where(m => !m.IsSpecialName && !m.IsConstructor) + .Where(m => ViolatesPureMethodRules(m)) + .ToList(); + + foreach (var m in badMethods) + { + Debug.LogError($"❌ '{type.Name}' public method '{m.Name}' modifies state — only pure getter/return methods are allowed in Config-derived classes."); + } + } + + + // Functions + private bool ViolatesPureMethodRules(MethodInfo method) + { + try + { + var body = method.GetMethodBody(); + if (body == null) + return false; + + var il = body.GetILAsByteArray(); + if (il == null) + return false; + + // Look for IL opcodes that store data or call setters + for (int i = 0; i < il.Length - 1; i++) + { + byte b = il[i]; + byte next = il[i + 1]; + + // Store field (stfld or stsfld) + if (b == 0x7D || b == 0x80) + return true; + + // Callvirt / call that might be setter + if (b == 0x28) + { + var tokens = method.Module.ResolveMethod(BitConverter.ToInt32(il, i + 1)); + if (tokens.Name.StartsWith("set_", StringComparison.Ordinal)) + return true; + } + } + } + catch + { + // Ignore methods that can't be inspected + } + + return false; + } + } +} \ No newline at end of file diff --git a/Editor/Core/InitializeOnLoad/ConfigAssetInitializer.cs.meta b/Editor/Core/InitializeOnLoad/Rules/ConfigAssetsRule.cs.meta similarity index 100% rename from Editor/Core/InitializeOnLoad/ConfigAssetInitializer.cs.meta rename to Editor/Core/InitializeOnLoad/Rules/ConfigAssetsRule.cs.meta diff --git a/Editor/Core/ProjectSetting/ProjectSettingProvider.cs b/Editor/Core/ProjectSetting/ProjectSettingProvider.cs index db94118..fea44d8 100644 --- a/Editor/Core/ProjectSetting/ProjectSettingProvider.cs +++ b/Editor/Core/ProjectSetting/ProjectSettingProvider.cs @@ -68,6 +68,107 @@ public void Draw() } } } + protected class ArrayTypeSelector + { + protected SerializedProperty myProperty; + private string fieldName; + private List typeList; + private string[] displayNames; + private string[] assemblyNames; + private int selectedIndex = 0; + private int newIndex; + private readonly int EnforceDisable = -1; + + + public ArrayTypeSelector(SerializedProperty TargetStringProperty, string displayName) + { + if (TargetStringProperty != null && displayName != string.Empty) + { + myProperty = TargetStringProperty; + fieldName = displayName; + } + else + { + Debug.LogWarning("TypeSelector Can't Create"); + return; + } + + typeList = AppDomain.CurrentDomain.GetAssemblies() + .SelectMany(a => a.GetTypes()) + .Where(t => typeof(T).IsAssignableFrom(t) && !t.IsAbstract) + .ToList(); + + displayNames = typeList.Select(t => $"{t.Namespace}.{t.Name}").ToArray(); // shown in UI + assemblyNames = typeList.Select(t => t.AssemblyQualifiedName).ToArray(); // stored + + EnforceDisable = GetEnforceDisableIndex(); + } + public void Draw() + { + if (!myProperty.isArray) + return; + + if(myProperty.arraySize == 0) + { + DefaultInitiation(); + } + + for (int i = 0; i < myProperty.arraySize; i++) + { + EditorGUILayout.BeginHorizontal(); + + SerializedProperty element = myProperty.GetArrayElementAtIndex(i); + selectedIndex = Array.IndexOf(assemblyNames, element.stringValue); + + if (i < EnforceDisable) + GUI.enabled = false; + + newIndex = EditorGUILayout.Popup(fieldName, selectedIndex, displayNames); + if (newIndex >= 0 && newIndex < assemblyNames.Length) + { + element.stringValue = assemblyNames[newIndex]; + } + + GUI.enabled = true; + + // Prevent removing first two elements + if (i >= EnforceDisable) + { + if (GUILayout.Button("Remove", GUILayout.Width(70))) + { + myProperty.DeleteArrayElementAtIndex(i); + } + } + else + { + GUI.enabled = false; + GUILayout.Button("Locked", GUILayout.Width(70)); + GUI.enabled = true; + } + + EditorGUILayout.EndHorizontal(); + + } + + GUILayout.Space(10); + + if (GUILayout.Button("Add New")) + { + myProperty.InsertArrayElementAtIndex(myProperty.arraySize); + } + + } + + + protected virtual int GetEnforceDisableIndex() + { + return -1; + } + protected virtual void DefaultInitiation() + { + + } + } private bool isReady = true;// Indicates whether the section is ready to render private string message = string.Empty;// Error message to display if the section is not ready @@ -141,7 +242,6 @@ protected void ClearError() UpdateRender(); } - } @@ -150,11 +250,12 @@ protected void ClearError() public static class ProjectSettingProvider { private static bool candraw = true;// Flag to determine if the UI can be drawn - private static List sections = new List(3) { + private static ProjectSettingSection[] sections = new ProjectSettingSection[4] { // Array of sections to be rendered in the settings UI new InitializerSetting_Section(), new FolderStructure_Section(), new GameStatus_Section(), + new CompileRule_Section(), }; diff --git a/Editor/Core/ProjectSetting/Sections/CompileRule_Section.cs b/Editor/Core/ProjectSetting/Sections/CompileRule_Section.cs new file mode 100644 index 0000000..8695745 --- /dev/null +++ b/Editor/Core/ProjectSetting/Sections/CompileRule_Section.cs @@ -0,0 +1,85 @@ + +using System; +using System.Collections.Generic; +using System.Linq; +using UnityEditor; +using UnityEngine; + +namespace RealMethod.Editor +{ + public class CompileRule_Section : ProjectSettingSection + { + private class RuleSelector : ArrayTypeSelector + { + + public RuleSelector(SerializedProperty TargetStringProperty, string displayName) : base(TargetStringProperty, displayName) + { + } + + protected override int GetEnforceDisableIndex() + { + return CompileGuard.DefaultRuls.Length; + } + protected override void DefaultInitiation() + { + foreach (var ruletype in CompileGuard.DefaultRuls) + { + int Index = myProperty.arraySize; + myProperty.InsertArrayElementAtIndex(Index); + SerializedProperty element = myProperty.GetArrayElementAtIndex(Index); + element.stringValue = ruletype.AssemblyQualifiedName; + } + } + } + + private ProjectSettingAsset SettingAsset; + private SerializedObject projectSettings; + private RuleSelector Rules; + + + // Implement ProjectSettingSection Methods + protected override void Initialized() + { + + } + protected override string GetTitle() + { + return "CompileRules"; + } + protected override SectionType GetSectionType() + { + return SectionType.Editor; + } + protected override void BeginRender(ProjectSettingAsset Storage) + { + SettingAsset = Storage; + projectSettings = new SerializedObject(Storage); + Rules = new RuleSelector(projectSettings.FindProperty("Rules"), "Rules"); + } + protected override void UpdateRender() + { + if (projectSettings == null) return; + + projectSettings.Update(); + Rules.Draw(); + + if (GUI.changed) + { + projectSettings.ApplyModifiedProperties(); + EditorUtility.SetDirty(SettingAsset); // Mark ScriptableObject dirty + AssetDatabase.SaveAssets(); // Optional: saves to disk immediately + AssetDatabase.Refresh(); + } + + projectSettings.ApplyModifiedProperties(); + + } + + + protected override void Fix(int Id) + { + + } + + } +} \ No newline at end of file diff --git a/Editor/Core/ProjectSetting/Sections/CompileRule_Section.cs.meta b/Editor/Core/ProjectSetting/Sections/CompileRule_Section.cs.meta new file mode 100644 index 0000000..d771a57 --- /dev/null +++ b/Editor/Core/ProjectSetting/Sections/CompileRule_Section.cs.meta @@ -0,0 +1,2 @@ +fileFormatVersion: 2 +guid: de6204fe01936154fbd368730fc129c5 \ No newline at end of file From 4c926f63fefe7d15d40e585346bccaa263284d87 Mon Sep 17 00:00:00 2001 From: Alijimpa Date: Mon, 6 Apr 2026 10:25:58 +0330 Subject: [PATCH 086/204] Implement Script Template for CompileRule --- Editor/Core/InitializeOnLoad/CompileGuard.cs | 72 ++++++++++++++++--- .../Rules/ConfigAssetsRule.cs | 4 +- .../InitializeOnLoad/Rules/ServiceRule.cs | 27 +++++++ .../Rules/ServiceRule.cs.meta | 2 + .../Sections/CompileRule_Section.cs | 2 +- .../Content/RealMethod_ScriptTemplate.cs | 5 ++ .../ScriptTemplates/CompileRuleTemplate.txt | 26 +++++++ .../CompileRuleTemplate.txt.meta | 7 ++ .../ProjectSetting/ProjectSettingAsset.cs | 16 +++-- 9 files changed, 145 insertions(+), 16 deletions(-) create mode 100644 Editor/Core/InitializeOnLoad/Rules/ServiceRule.cs create mode 100644 Editor/Core/InitializeOnLoad/Rules/ServiceRule.cs.meta create mode 100644 Reservoir/ScriptTemplates/CompileRuleTemplate.txt create mode 100644 Reservoir/ScriptTemplates/CompileRuleTemplate.txt.meta diff --git a/Editor/Core/InitializeOnLoad/CompileGuard.cs b/Editor/Core/InitializeOnLoad/CompileGuard.cs index 1bfce19..8578448 100644 --- a/Editor/Core/InitializeOnLoad/CompileGuard.cs +++ b/Editor/Core/InitializeOnLoad/CompileGuard.cs @@ -6,13 +6,35 @@ namespace RealMethod.Editor { + /// + /// Base class for creating custom compile-time or editor-time validation rules. + /// Rules are instantiated by CompileGuard and triggered automatically depending + /// on the selected . + /// public abstract class CompileRule { - public enum RuleMode + /// + /// Defines when a should be executed by . + /// This controls which editor event triggers the rule validation. + /// + public enum RuleExecutionMode { + /// + /// Rule is disabled and will never be executed. + /// Disable = 0, - CompilationPipeline = 1, - EditorApplication = 2 + /// + /// Rule runs after Unity finishes compiling scripts. + /// Triggered by . + /// Useful for validating code structure or assets after compilation. + /// + AfterCompilation = 1, + /// + /// Rule runs on the editor update loop after the editor loads. + /// Triggered using . + /// Useful for checks that should occur once the editor is ready. + /// + EditorStartup = 2 } public CompileRule() @@ -20,15 +42,47 @@ public CompileRule() Initilized(); } - + /// + /// Called automatically right after the rule is constructed. + /// Use this to initialize internal data, cache values, or set up + /// anything needed before the rule is used by CompileGuard. + /// protected abstract void Initilized(); - public abstract RuleMode GetRuleMode(); + /// + /// Defines when this rule should run during the editor lifecycle. + /// The returned determines whether + /// CompileGuard triggers this rule during: + /// - script compilation (CompilationPipeline), or + /// - editor updates (EditorApplication). + /// + public abstract RuleExecutionMode GetRuleMode(); + /// + /// Returns the base type that this rule should scan for. + /// CompileGuard will call for every type in the project + /// that inherits from the returned base type. + /// + /// + /// A Type that all target classes must derive from. + /// public abstract Type GetBaseType(); + /// + /// Called when CompileGuard finds a type that inherits from the rule's base type. + /// Implement validation logic here. This method is invoked automatically for each + /// matching type during the selected rule mode. + /// + /// + /// The discovered type that matches . + /// public abstract void OnCheck(Type type); } [InitializeOnLoad] + /// + /// Central system that discovers and executes all CompileRule instances. + /// It triggers rules during compilation or editor updates depending on their mode, + /// and passes every project type that matches the rule's base type. + /// public static class CompileGuard { private static ProjectSettingAsset ProjectSetting_Cache; @@ -63,13 +117,13 @@ static CompileGuard() private static void OnCompilationFinished(object obj) { - CheckRuls(CompileRule.RuleMode.CompilationPipeline); + CheckRuls(CompileRule.RuleExecutionMode.AfterCompilation); } private static void OnEditorUpdated() { - CheckRuls(CompileRule.RuleMode.EditorApplication); + CheckRuls(CompileRule.RuleExecutionMode.EditorStartup); } - private static void CheckRuls(CompileRule.RuleMode mode) + private static void CheckRuls(CompileRule.RuleExecutionMode mode) { if (ProjectSetting == null) return; @@ -127,7 +181,7 @@ private static void CheckRuls(CompileRule.RuleMode mode) { if (Ruls == null) return; - + foreach (var rule in Ruls) { if (rule == null) diff --git a/Editor/Core/InitializeOnLoad/Rules/ConfigAssetsRule.cs b/Editor/Core/InitializeOnLoad/Rules/ConfigAssetsRule.cs index dc78743..06b5cd5 100644 --- a/Editor/Core/InitializeOnLoad/Rules/ConfigAssetsRule.cs +++ b/Editor/Core/InitializeOnLoad/Rules/ConfigAssetsRule.cs @@ -12,9 +12,9 @@ public class ConfigAssetsRule : CompileRule protected override void Initilized() { } - public override RuleMode GetRuleMode() + public override RuleExecutionMode GetRuleMode() { - return RuleMode.EditorApplication; + return RuleExecutionMode.EditorStartup; } public override Type GetBaseType() { diff --git a/Editor/Core/InitializeOnLoad/Rules/ServiceRule.cs b/Editor/Core/InitializeOnLoad/Rules/ServiceRule.cs new file mode 100644 index 0000000..02c10b9 --- /dev/null +++ b/Editor/Core/InitializeOnLoad/Rules/ServiceRule.cs @@ -0,0 +1,27 @@ +using System; + +namespace RealMethod.Editor +{ + public class ServiceRule : CompileRule + { + // CompileRule Methods + protected override void Initilized() + { + + } + public override RuleExecutionMode GetRuleMode() + { + return RuleExecutionMode.AfterCompilation; + } + public override Type GetBaseType() + { + return typeof(Service); + } + public override void OnCheck(Type type) + { + throw new NotImplementedException(); + } + + + } +} \ No newline at end of file diff --git a/Editor/Core/InitializeOnLoad/Rules/ServiceRule.cs.meta b/Editor/Core/InitializeOnLoad/Rules/ServiceRule.cs.meta new file mode 100644 index 0000000..db007c2 --- /dev/null +++ b/Editor/Core/InitializeOnLoad/Rules/ServiceRule.cs.meta @@ -0,0 +1,2 @@ +fileFormatVersion: 2 +guid: d5ced9cc83a3eaa4bbf313a3a3c0d44c \ No newline at end of file diff --git a/Editor/Core/ProjectSetting/Sections/CompileRule_Section.cs b/Editor/Core/ProjectSetting/Sections/CompileRule_Section.cs index 8695745..3f403e3 100644 --- a/Editor/Core/ProjectSetting/Sections/CompileRule_Section.cs +++ b/Editor/Core/ProjectSetting/Sections/CompileRule_Section.cs @@ -44,7 +44,7 @@ protected override void Initialized() } protected override string GetTitle() { - return "CompileRules"; + return "CompileGuard"; } protected override SectionType GetSectionType() { diff --git a/Editor/ReadySet/Content/RealMethod_ScriptTemplate.cs b/Editor/ReadySet/Content/RealMethod_ScriptTemplate.cs index 6a2d85e..215cbf8 100644 --- a/Editor/ReadySet/Content/RealMethod_ScriptTemplate.cs +++ b/Editor/ReadySet/Content/RealMethod_ScriptTemplate.cs @@ -196,6 +196,11 @@ public static void CreateTrigger2D() // Editor + [MenuItem("Assets/Create/Scripting/RealMethod/Editor/CompileRule", false, 80)] + public static void CreateCompileRule() + { + string Path = RM_Editor.CreateScriptTemplate("CompileRuleTemplate.txt", "MyRule.cs"); + } [MenuItem("Assets/Create/Scripting/RealMethod/Editor/SettingSection", false, 80)] public static void CreateSettingSection() { diff --git a/Reservoir/ScriptTemplates/CompileRuleTemplate.txt b/Reservoir/ScriptTemplates/CompileRuleTemplate.txt new file mode 100644 index 0000000..6584032 --- /dev/null +++ b/Reservoir/ScriptTemplates/CompileRuleTemplate.txt @@ -0,0 +1,26 @@ +using System; +using RealMethod.Editor; +using UnityEngine; + +public class #SCRIPTNAME# : CompileRule +{ + // CompileRule Methods + protected override void Initilized() + { + // Called right after Construct + } + public override RuleExecutionMode GetRuleMode() + { + // Defines when this rule should be executed + return RuleExecutionMode.AfterCompilation; + } + public override Type GetBaseType() + { + // A Type that all target classes must derive from + return typeof(MonoBehaviour); + } + public override void OnCheck(Type type) + { + // Called when CompileGuard finds a type that inherits from the rule's base type. + } +} diff --git a/Reservoir/ScriptTemplates/CompileRuleTemplate.txt.meta b/Reservoir/ScriptTemplates/CompileRuleTemplate.txt.meta new file mode 100644 index 0000000..07c8093 --- /dev/null +++ b/Reservoir/ScriptTemplates/CompileRuleTemplate.txt.meta @@ -0,0 +1,7 @@ +fileFormatVersion: 2 +guid: ff50126801b38d34db2274c3060c4695 +TextScriptImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Runtime/Core/ProjectSetting/ProjectSettingAsset.cs b/Runtime/Core/ProjectSetting/ProjectSettingAsset.cs index bf009a1..07dbbd4 100644 --- a/Runtime/Core/ProjectSetting/ProjectSettingAsset.cs +++ b/Runtime/Core/ProjectSetting/ProjectSettingAsset.cs @@ -82,15 +82,14 @@ public string GetFolderPath(ProjectSettingAsset settingAsset) new FolderAddress { AssetType = (AssetFormat)13, AssetPath = "7_Misc"} }; public IReadOnlyList FolderStructure => folderStructure; -#endif - -#if UNITY_EDITOR [Header("GameStatus")] [ReadOnly] public List Status = new List(4) { "Menu", "Playing", "Pause", "GameOver" }; + [Header("CompileGuard")] + [SerializeField, ReadOnly] + private string[] Rules; #endif - // Unity Methods protected virtual void OnEnable() { @@ -153,6 +152,15 @@ public string GetFolderPathByType(AssetFormat identity) } public FolderAddress GetFolderAddressByIndex(int index) => folderStructure[index]; public void SetFolderAddressPath(int index, string value) => folderStructure[index].AssetPath = value; + public Type[] GetCompileRules() + { + List result = new List(); + foreach (var item in Rules) + { + result.Add(Type.GetType(item)); + } + return result.ToArray(); + } #endif #if UNITY_SERVER || UNITY_EDITOR From fb439551c184a7e25f1cdeee2ddf57535ba13950 Mon Sep 17 00:00:00 2001 From: Alijimpa Date: Mon, 6 Apr 2026 12:18:38 +0330 Subject: [PATCH 087/204] IMplement Service Rule --- Editor/Core/InitializeOnLoad/CompileGuard.cs | 3 +- .../InitializeOnLoad/Rules/ServiceRule.cs | 28 +++++++++++++++++-- .../Sections/CompileRule_Section.cs | 4 --- 3 files changed, 28 insertions(+), 7 deletions(-) diff --git a/Editor/Core/InitializeOnLoad/CompileGuard.cs b/Editor/Core/InitializeOnLoad/CompileGuard.cs index 8578448..d577ad7 100644 --- a/Editor/Core/InitializeOnLoad/CompileGuard.cs +++ b/Editor/Core/InitializeOnLoad/CompileGuard.cs @@ -103,9 +103,10 @@ private static ProjectSettingAsset ProjectSetting private static System.Reflection.Assembly[] Assemblies; private static CompileRule[] Ruls; - public static Type[] DefaultRuls = new Type[1] { + public static Type[] DefaultRuls = new Type[2] { // Array of ruls to that should be run always for RealMethod typeof(ConfigAssetsRule), + typeof(ServiceRule), }; diff --git a/Editor/Core/InitializeOnLoad/Rules/ServiceRule.cs b/Editor/Core/InitializeOnLoad/Rules/ServiceRule.cs index 02c10b9..23a875d 100644 --- a/Editor/Core/InitializeOnLoad/Rules/ServiceRule.cs +++ b/Editor/Core/InitializeOnLoad/Rules/ServiceRule.cs @@ -1,4 +1,6 @@ using System; +using System.Reflection; +using UnityEngine; namespace RealMethod.Editor { @@ -7,7 +9,7 @@ public class ServiceRule : CompileRule // CompileRule Methods protected override void Initilized() { - + } public override RuleExecutionMode GetRuleMode() { @@ -19,7 +21,29 @@ public override Type GetBaseType() } public override void OnCheck(Type type) { - throw new NotImplementedException(); + // Check if class is static + if (type.IsAbstract && type.IsSealed) + { + Debug.LogError($"Service '{type.FullName}' cannot be static."); + return; + } + + // Check for static methods + var methods = type.GetMethods( + BindingFlags.Public | + BindingFlags.NonPublic | + BindingFlags.Static | + BindingFlags.DeclaredOnly + ); + + foreach (var method in methods) + { + if (method.IsStatic) + { + Debug.LogError($"Service '{type.FullName}' contains static method '{method.Name}'. Static methods are not allowed in Service classes." + ); + } + } } diff --git a/Editor/Core/ProjectSetting/Sections/CompileRule_Section.cs b/Editor/Core/ProjectSetting/Sections/CompileRule_Section.cs index 3f403e3..096e663 100644 --- a/Editor/Core/ProjectSetting/Sections/CompileRule_Section.cs +++ b/Editor/Core/ProjectSetting/Sections/CompileRule_Section.cs @@ -1,7 +1,3 @@ - -using System; -using System.Collections.Generic; -using System.Linq; using UnityEditor; using UnityEngine; From a980feb06a0de2851c583f0c7eb2955baedafc55 Mon Sep 17 00:00:00 2001 From: Alijimpa Date: Mon, 6 Apr 2026 13:11:45 +0330 Subject: [PATCH 088/204] Change Method in Service Inteface --- Runtime/Core/Architecture/Game.cs | 2 +- Runtime/Core/Architecture/Service.cs | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/Runtime/Core/Architecture/Game.cs b/Runtime/Core/Architecture/Game.cs index 0895d84..57db100 100644 --- a/Runtime/Core/Architecture/Game.cs +++ b/Runtime/Core/Architecture/Game.cs @@ -1024,7 +1024,7 @@ private void Notify_OnWorldInitiate(World NewWorld) { foreach (var service in Services) { - service.Value.ChangeWorld(NewWorld); + service.Value.ChangingWorld(NewWorld); } World = NewWorld; OnWorldChanged(World); diff --git a/Runtime/Core/Architecture/Service.cs b/Runtime/Core/Architecture/Service.cs index 5eb75e1..e485d28 100644 --- a/Runtime/Core/Architecture/Service.cs +++ b/Runtime/Core/Architecture/Service.cs @@ -20,7 +20,7 @@ public interface IService /// /// Called when the world or environment updates. /// - void ChangeWorld(World NewWorld); + void ChangingWorld(World NewWorld); /// /// Called when the service is deleted or destroyed. /// @@ -43,7 +43,7 @@ void IService.Created(object author) { OnStart(author); } - void IService.ChangeWorld(World NewWorld) + void IService.ChangingWorld(World NewWorld) { OnWorldChanging(Game.World, NewWorld); } From 581a03168193d5e689d52c2f8e4e7aa3a345dccd Mon Sep 17 00:00:00 2001 From: Alijimpa Date: Mon, 6 Apr 2026 14:05:59 +0330 Subject: [PATCH 089/204] Rename Method and Fix Project Setting for editor play --- Runtime/Core/Architecture/Game.cs | 6 ++++-- Runtime/Core/Definitions/GlobalEnum.cs | 2 +- Runtime/Core/ProjectSetting/ProjectSettingAsset.cs | 5 ++++- 3 files changed, 9 insertions(+), 4 deletions(-) diff --git a/Runtime/Core/Architecture/Game.cs b/Runtime/Core/Architecture/Game.cs index 57db100..3a86295 100644 --- a/Runtime/Core/Architecture/Game.cs +++ b/Runtime/Core/Architecture/Game.cs @@ -486,14 +486,16 @@ public static void Unregister() /// /// Service type to retrieve. /// The service instance of type , or null if not found. - public static T GetService() + public static T GetService(bool Printdebug = true) { Type TypeService = typeof(T); if (Instance.Services.TryGetValue(TypeService, out var provider)) return (T)provider.GetServiceClass(); - Debug.LogError($"Service {TypeService} not found."); + if (Printdebug) + Debug.LogError($"Service {TypeService} not found."); + return default; } /// diff --git a/Runtime/Core/Definitions/GlobalEnum.cs b/Runtime/Core/Definitions/GlobalEnum.cs index 5f249fe..ef59a60 100644 --- a/Runtime/Core/Definitions/GlobalEnum.cs +++ b/Runtime/Core/Definitions/GlobalEnum.cs @@ -81,7 +81,7 @@ public override int GetHashCode() #if UNITY_EDITOR public override string ToString() { - var ProjectSettings = ProjectSettingAsset.Loaded(); + var ProjectSettings = ProjectSettingAsset.Load(); if (ProjectSettings) { var names = ProjectSettings.Status; diff --git a/Runtime/Core/ProjectSetting/ProjectSettingAsset.cs b/Runtime/Core/ProjectSetting/ProjectSettingAsset.cs index 07dbbd4..4165f34 100644 --- a/Runtime/Core/ProjectSetting/ProjectSettingAsset.cs +++ b/Runtime/Core/ProjectSetting/ProjectSettingAsset.cs @@ -127,10 +127,13 @@ public GameObject GetPrefab_1() } #if UNITY_EDITOR - public static ProjectSettingAsset Loaded() + public static ProjectSettingAsset Load() { return UnityEditor.AssetDatabase.LoadAssetAtPath(Path); } + public override void OnEditorPlay() + { + } public GameObject GetPrefab_2() { return GamePrefab_2; From f9cf413f7e3afd37c34f62dbf9100ade29511824 Mon Sep 17 00:00:00 2001 From: Alijimpa Date: Mon, 6 Apr 2026 20:26:40 +0330 Subject: [PATCH 090/204] Rename FindManager to GetManager --- .../InitializeOnLoad/Rules/ServiceRule.cs | 4 +-- Runtime/Core/Architecture/Game.cs | 26 ++++++++++++++----- Runtime/Core/Architecture/World.cs | 4 +-- Runtime/ReadySet/Services/DebugService.cs | 2 +- 4 files changed, 24 insertions(+), 12 deletions(-) diff --git a/Editor/Core/InitializeOnLoad/Rules/ServiceRule.cs b/Editor/Core/InitializeOnLoad/Rules/ServiceRule.cs index 23a875d..1471934 100644 --- a/Editor/Core/InitializeOnLoad/Rules/ServiceRule.cs +++ b/Editor/Core/InitializeOnLoad/Rules/ServiceRule.cs @@ -40,12 +40,10 @@ public override void OnCheck(Type type) { if (method.IsStatic) { - Debug.LogError($"Service '{type.FullName}' contains static method '{method.Name}'. Static methods are not allowed in Service classes." - ); + Debug.LogError($"Service '{type.FullName}' contains static method '{method.Name}'. Static methods are not allowed in Service classes."); } } } - } } \ No newline at end of file diff --git a/Runtime/Core/Architecture/Game.cs b/Runtime/Core/Architecture/Game.cs index 3a86295..15ebb16 100644 --- a/Runtime/Core/Architecture/Game.cs +++ b/Runtime/Core/Architecture/Game.cs @@ -528,7 +528,7 @@ public static void ClearService() /// Array of service type names. public string[] GetAllServiceNames() { - return Services.Select(service => service.GetType().Name).ToArray(); + return Services.Keys.Select(t => t.Name).ToArray(); } /// /// Requests a scene load by build index . @@ -697,20 +697,20 @@ public static Coroutine ReOpenScene() /// /// Manager type to find. /// An instance of the manager if found; otherwise null. - public static T FindManager() where T : MonoBehaviour + public static T GetManager() where T : MonoBehaviour { T Result = null; if (World != null) { - Result = World.GetManager(); + Result = World.FindManager(); } if (Result != null) { return Result; } - return Instance.GetManager(); + return Instance.FindManager(); } /// /// Parents the provided GameObject to the game root instance. @@ -797,6 +797,7 @@ public static void Quit() /// String or object to be converted to string representation for display. [System.Diagnostics.Conditional("UNITY_EDITOR")] [System.Diagnostics.Conditional("DEVELOPMENT_BUILD")] + [HideInCallstack] public static void Log(object message) { Debug.Log(message); @@ -808,6 +809,7 @@ public static void Log(object message) /// Object to which the message applies. [System.Diagnostics.Conditional("UNITY_EDITOR")] [System.Diagnostics.Conditional("DEVELOPMENT_BUILD")] + [HideInCallstack] public static void Log(object message, UnityEngine.Object context) { Debug.Log(message, context); @@ -818,6 +820,7 @@ public static void Log(object message, UnityEngine.Object context) /// String or object to be converted to string representation for display. [System.Diagnostics.Conditional("UNITY_EDITOR")] [System.Diagnostics.Conditional("DEVELOPMENT_BUILD")] + [HideInCallstack] public static void LogWarning(object message) { Debug.LogWarning(message); @@ -829,6 +832,7 @@ public static void LogWarning(object message) /// Object to which the message applies. [System.Diagnostics.Conditional("UNITY_EDITOR")] [System.Diagnostics.Conditional("DEVELOPMENT_BUILD")] + [HideInCallstack] public static void LogWarning(object message, UnityEngine.Object context) { Debug.LogWarning(message, context); @@ -839,6 +843,7 @@ public static void LogWarning(object message, UnityEngine.Object context) /// String or object to be converted to string representation for display. [System.Diagnostics.Conditional("UNITY_EDITOR")] [System.Diagnostics.Conditional("DEVELOPMENT_BUILD")] + [HideInCallstack] public static void LogError(object message) { Debug.LogError(message); @@ -850,6 +855,7 @@ public static void LogError(object message) /// Object to which the message applies. [System.Diagnostics.Conditional("UNITY_EDITOR")] [System.Diagnostics.Conditional("DEVELOPMENT_BUILD")] + [HideInCallstack] public static void LogError(object message, UnityEngine.Object context) { Debug.LogError(message, context); @@ -860,6 +866,7 @@ public static void LogError(object message, UnityEngine.Object context) /// Runtime Exception. [System.Diagnostics.Conditional("UNITY_EDITOR")] [System.Diagnostics.Conditional("DEVELOPMENT_BUILD")] + [HideInCallstack] public static void LogException(Exception exception) { Debug.LogException(exception); @@ -871,6 +878,7 @@ public static void LogException(Exception exception) /// Object to which the message applies. [System.Diagnostics.Conditional("UNITY_EDITOR")] [System.Diagnostics.Conditional("DEVELOPMENT_BUILD")] + [HideInCallstack] public static void LogException(Exception exception, UnityEngine.Object context) { Debug.LogException(exception, context); @@ -881,6 +889,7 @@ public static void LogException(Exception exception, UnityEngine.Object context) /// Condition you expect to be true. [System.Diagnostics.Conditional("UNITY_EDITOR")] [System.Diagnostics.Conditional("DEVELOPMENT_BUILD")] + [HideInCallstack] public static void Assert(bool condition) { Debug.Assert(condition); @@ -892,6 +901,7 @@ public static void Assert(bool condition) /// String or object to be converted to string representation for display. [System.Diagnostics.Conditional("UNITY_EDITOR")] [System.Diagnostics.Conditional("DEVELOPMENT_BUILD")] + [HideInCallstack] public static void Assert(bool condition, object message) { Debug.Assert(condition, message); @@ -903,6 +913,7 @@ public static void Assert(bool condition, object message) /// Object to which the message applies. [System.Diagnostics.Conditional("UNITY_EDITOR")] [System.Diagnostics.Conditional("DEVELOPMENT_BUILD")] + [HideInCallstack] public static void Assert(bool condition, UnityEngine.Object context) { Debug.Assert(condition, context); @@ -914,6 +925,7 @@ public static void Assert(bool condition, UnityEngine.Object context) /// String or object to be converted to string representation for display. [System.Diagnostics.Conditional("UNITY_EDITOR")] [System.Diagnostics.Conditional("DEVELOPMENT_BUILD")] + [HideInCallstack] public static void Assert(bool condition, string message) { Debug.Assert(condition, message); @@ -926,6 +938,7 @@ public static void Assert(bool condition, string message) /// Object to which the message applies. [System.Diagnostics.Conditional("UNITY_EDITOR")] [System.Diagnostics.Conditional("DEVELOPMENT_BUILD")] + [HideInCallstack] public static void Assert(bool condition, object message, UnityEngine.Object context) { Debug.Assert(condition, message, context); @@ -938,6 +951,7 @@ public static void Assert(bool condition, object message, UnityEngine.Object con /// Object to which the message applies. [System.Diagnostics.Conditional("UNITY_EDITOR")] [System.Diagnostics.Conditional("DEVELOPMENT_BUILD")] + [HideInCallstack] public static void Assert(bool condition, string message, UnityEngine.Object context) { Debug.Assert(condition, message, context); @@ -949,7 +963,7 @@ public static void Assert(bool condition, string message, UnityEngine.Object con /// /// Manager type to retrieve. /// The manager instance if found; otherwise null. - public T GetManager() where T : class + public T FindManager() where T : class { foreach (var manager in Managers) { @@ -965,7 +979,7 @@ public T GetManager() where T : class /// /// Name of the manager GameObject to find. /// The matching , or null if none match. - public IGameManager GetManager(string ObjectName) + public IGameManager FindManager(string ObjectName) { foreach (var manger in Managers) { diff --git a/Runtime/Core/Architecture/World.cs b/Runtime/Core/Architecture/World.cs index 8ec8f27..686c37f 100644 --- a/Runtime/Core/Architecture/World.cs +++ b/Runtime/Core/Architecture/World.cs @@ -199,7 +199,7 @@ private void OnDestroy() /// /// The manager type to search for. /// The manager instance cast to , or null if not found. - public T GetManager() where T : class + public T FindManager() where T : class { foreach (var manager in Managers) { @@ -215,7 +215,7 @@ public T GetManager() where T : class /// /// The name of the manager's GameObject to find. /// The matching , or null if none match. - public IGameManager GetManager(string ObjectName) + public IGameManager FindManager(string ObjectName) { foreach (var manger in Managers) { diff --git a/Runtime/ReadySet/Services/DebugService.cs b/Runtime/ReadySet/Services/DebugService.cs index 5d131d1..81456bf 100644 --- a/Runtime/ReadySet/Services/DebugService.cs +++ b/Runtime/ReadySet/Services/DebugService.cs @@ -59,7 +59,7 @@ protected override void OnEnd(object Author) private void CheckManager() { if (Printer == null) - Printer = Game.FindManager(); + Printer = Game.GetManager(); } } From f83621d9ab67744f1b331e07bd4a2ed4ecafae10 Mon Sep 17 00:00:00 2001 From: Alijimpa Date: Mon, 6 Apr 2026 21:23:24 +0330 Subject: [PATCH 091/204] Refine Spawn&Despawn Services --- .../ScriptTemplates/AudioManagerTemplater.txt | 6 +- Runtime/Pattern/Managers/AudioManager.cs | 18 +- Runtime/Pattern/Managers/DataManager.cs | 2 +- Runtime/Pattern/Managers/HapticManager.cs | 9 - Runtime/ReadySet/Commands/Execut/C_Haptic.cs | 2 +- Runtime/ReadySet/Managers/CoroutineManager.cs | 11 +- Runtime/ReadySet/Managers/HUDManager.cs | 8 - Runtime/ReadySet/Managers/ScreenManager.cs | 8 - Runtime/ReadySet/Managers/SoundManager.cs | 3 +- Runtime/ReadySet/Managers/TaskManager.cs | 9 - .../ReadySet/Presets/PoolAsset/AudioPool.cs | 2 +- Runtime/ReadySet/Services/DespawnService.cs | 284 +++++++++++ .../ReadySet/Services/DespawnService.cs.meta | 2 + Runtime/ReadySet/Services/SpawanService.cs | 458 ++++++------------ .../RPG/StatSystem/CharacterStatComponent.cs | 2 +- 15 files changed, 446 insertions(+), 378 deletions(-) create mode 100644 Runtime/ReadySet/Services/DespawnService.cs create mode 100644 Runtime/ReadySet/Services/DespawnService.cs.meta diff --git a/Reservoir/ScriptTemplates/AudioManagerTemplater.txt b/Reservoir/ScriptTemplates/AudioManagerTemplater.txt index 2160161..c2c8b41 100644 --- a/Reservoir/ScriptTemplates/AudioManagerTemplater.txt +++ b/Reservoir/ScriptTemplates/AudioManagerTemplater.txt @@ -2,6 +2,8 @@ using RealMethod; public class #SCRIPTNAME# : AudioManager { - - + // AudioManager Methods + protected override void InitiateService(Service service) + { + } } diff --git a/Runtime/Pattern/Managers/AudioManager.cs b/Runtime/Pattern/Managers/AudioManager.cs index 45f73c9..6227f5e 100644 --- a/Runtime/Pattern/Managers/AudioManager.cs +++ b/Runtime/Pattern/Managers/AudioManager.cs @@ -23,11 +23,6 @@ protected override void InitiateManager(bool AlwaysLoaded) return; } - if (CanBringtoSpawn() && Game.TryGetService(out Spawn SpawnServ)) - { - SpawnServ.BringManager(this); - } - soundPool = new ObjectPool( createFunc: CreateSource, actionOnGet: OnTakeSource, @@ -35,15 +30,7 @@ protected override void InitiateManager(bool AlwaysLoaded) actionOnDestroy: OnDestroySource, collectionCheck: false, defaultCapacity: 10, - maxSize: 500 - ); - } - protected override void InitiateService(Service service) - { - if (CanBringtoSpawn() && service is Spawn SpawnServ) - { - SpawnServ.BringManager(this); - } + maxSize: 500); } // Public Functions @@ -121,9 +108,6 @@ private void OnDestroySource(AudioSource source) Destroy(source.gameObject); } - // Abstract Methods - protected abstract bool CanBringtoSpawn(); - // Enumerator Methods private IEnumerator PauseAfterSecond(AudioSource source, float time) { diff --git a/Runtime/Pattern/Managers/DataManager.cs b/Runtime/Pattern/Managers/DataManager.cs index 4735aaf..e7e449a 100644 --- a/Runtime/Pattern/Managers/DataManager.cs +++ b/Runtime/Pattern/Managers/DataManager.cs @@ -58,7 +58,7 @@ public T provider // Public Functions public bool Load(Object author) { - return Load(author, Game.FindManager()); + return Load(author, Game.GetManager()); } public bool Load(Object author, DataManager saveManager) { diff --git a/Runtime/Pattern/Managers/HapticManager.cs b/Runtime/Pattern/Managers/HapticManager.cs index 325882e..2638279 100644 --- a/Runtime/Pattern/Managers/HapticManager.cs +++ b/Runtime/Pattern/Managers/HapticManager.cs @@ -73,11 +73,6 @@ public void InitiateManager(bool AlwaysLoaded) return; } - if (Game.TryGetService(out Spawn SpawnServ)) - { - SpawnServ.BringManager(this); - } - if (DefaultConfig != null) { foreach (var conf in DefaultConfig) @@ -88,10 +83,6 @@ public void InitiateManager(bool AlwaysLoaded) } public void ResolveService(Service service, bool active) { - if (service is Spawn spawnservice) - { - spawnservice.BringManager(this); - } } diff --git a/Runtime/ReadySet/Commands/Execut/C_Haptic.cs b/Runtime/ReadySet/Commands/Execut/C_Haptic.cs index a636b8c..b5f716c 100644 --- a/Runtime/ReadySet/Commands/Execut/C_Haptic.cs +++ b/Runtime/ReadySet/Commands/Execut/C_Haptic.cs @@ -12,7 +12,7 @@ public sealed class C_Haptic : Command // Command Methods protected override bool OnInitiate(Object owner) { - manager = Game.FindManager(); + manager = Game.GetManager(); return manager != null; } protected override bool CanExecute(object Executer) diff --git a/Runtime/ReadySet/Managers/CoroutineManager.cs b/Runtime/ReadySet/Managers/CoroutineManager.cs index aa53fbb..cecca45 100644 --- a/Runtime/ReadySet/Managers/CoroutineManager.cs +++ b/Runtime/ReadySet/Managers/CoroutineManager.cs @@ -1,21 +1,16 @@ +using UnityEngine; + namespace RealMethod { + [AddComponentMenu("RealMethod/Manager/CoroutineManager")] public class CoroutineManager : EnumeratorManager { // EnumeratorManager Methods protected override void InitiateManager(bool alwaysLoaded) { - if (Game.TryGetService(out Spawn SpawnServ)) - { - SpawnServ.BringManager(this); - } } protected override void InitiateService(Service service) { - if (service is Spawn spawnservice) - { - spawnservice.BringManager(this); - } } } diff --git a/Runtime/ReadySet/Managers/HUDManager.cs b/Runtime/ReadySet/Managers/HUDManager.cs index ee01c46..5ee195f 100644 --- a/Runtime/ReadySet/Managers/HUDManager.cs +++ b/Runtime/ReadySet/Managers/HUDManager.cs @@ -9,17 +9,9 @@ public sealed class HUDManager : UIManager // UIManager Methods protected override void InitiateManager(bool alwaysLoaded) { - if (Game.TryGetService(out Spawn SpawnServ)) - { - SpawnServ.BringManager(this); - } } protected override void InitiateService(Service newService) { - if (newService is Spawn spawnservice) - { - spawnservice.BringManager(this); - } } } diff --git a/Runtime/ReadySet/Managers/ScreenManager.cs b/Runtime/ReadySet/Managers/ScreenManager.cs index 5ddd5b8..3419a6b 100644 --- a/Runtime/ReadySet/Managers/ScreenManager.cs +++ b/Runtime/ReadySet/Managers/ScreenManager.cs @@ -25,17 +25,9 @@ protected override void InitiateManager(bool alwaysLoaded) { Game.OnSceneLoading += (value) => OnLoadScne?.Invoke(value); Game.OnSceneLoadingProcess += (value) => OnLoading?.Invoke(value); - if (Game.TryGetService(out Spawn SpawnServ)) - { - SpawnServ.BringManager(this); - } } protected override void InitiateService(Service newService) { - if (newService is Spawn spawnservice) - { - spawnservice.BringManager(this); - } } public void SetInformer(IInformer messanger) diff --git a/Runtime/ReadySet/Managers/SoundManager.cs b/Runtime/ReadySet/Managers/SoundManager.cs index c675968..a78a636 100644 --- a/Runtime/ReadySet/Managers/SoundManager.cs +++ b/Runtime/ReadySet/Managers/SoundManager.cs @@ -6,9 +6,8 @@ namespace RealMethod public sealed class SoundManager : AudioManager { // AudioManager Methods - protected override bool CanBringtoSpawn() + protected override void InitiateService(Service service) { - return true; } } } \ No newline at end of file diff --git a/Runtime/ReadySet/Managers/TaskManager.cs b/Runtime/ReadySet/Managers/TaskManager.cs index 2202039..f8c0ae1 100644 --- a/Runtime/ReadySet/Managers/TaskManager.cs +++ b/Runtime/ReadySet/Managers/TaskManager.cs @@ -19,11 +19,6 @@ public sealed class TaskManager : TickManager // TickManager Methods protected override void InitiateManager(bool alwaysLoaded) { - if (Game.TryGetService(out Spawn SpawnServ)) - { - SpawnServ.BringManager(this); - } - if (DefaultTasks != null) { for (int i = 0; i < DefaultTasks.Length; i++) @@ -34,10 +29,6 @@ protected override void InitiateManager(bool alwaysLoaded) } protected override void InitiateService(Service service) { - if (service is Spawn spawnservice) - { - spawnservice.BringManager(this); - } } protected override bool CheckUnit(ITask unit) { diff --git a/Runtime/ReadySet/Presets/PoolAsset/AudioPool.cs b/Runtime/ReadySet/Presets/PoolAsset/AudioPool.cs index 6bd6c83..b5be71a 100644 --- a/Runtime/ReadySet/Presets/PoolAsset/AudioPool.cs +++ b/Runtime/ReadySet/Presets/PoolAsset/AudioPool.cs @@ -109,7 +109,7 @@ private AudioClip GetRandomClip() // Base PoolAsset Methods protected override void OnRootInitiate(Transform Root) { - AudioManager audiomanager = Game.World.GetManager(); + AudioManager audiomanager = Game.World.FindManager(); if (audiomanager != null) { Root.SetParent(audiomanager.transform); diff --git a/Runtime/ReadySet/Services/DespawnService.cs b/Runtime/ReadySet/Services/DespawnService.cs new file mode 100644 index 0000000..d5b7252 --- /dev/null +++ b/Runtime/ReadySet/Services/DespawnService.cs @@ -0,0 +1,284 @@ +using System.Collections.Generic; +using UnityEngine; + +namespace RealMethod +{ + /// + /// Despawn is a sealed static service used to instantiate gameplay objects such as + /// prefabs, UI elements, audio sources, and other spawnable types. + /// + /// This class automatically locates the required manager instances from the + /// World scope. When a new spawn request is made, Despawn will: + /// 1) Look for a cached manager of the requested type. + /// 2) If missing, it will attempt to find the manager inside World. + /// 3) The found manager is cached internally for reuse to avoid repeated lookups. + /// + /// Developers may register their own managers manually if needed. + /// This is useful when: + /// • A custom manager needs to be used before Despawn's automatic discovery. + /// • Multiple child managers inherit from an abstract base manager. + /// (Example: UIManager → ScreenManager / HUDManager) + /// Despawn will always pick the FIRST accessible base type (UIManager), + /// unless the developer registers a specific child manager earlier. + /// + /// Important notes: + /// • Despawn is a sealed class and cannot be inherited or modified. + /// • Spawn’s methods work only with the corresponding manager types + /// (UIManager, AudioManager, ScreenManager, TaskManager, HapticManager, EnumeratorManager & ..). + /// • When scenes change, World scope clears all managers. Despawn will also + /// lose cached references and re-discover managers on the next request. + /// Developers must ensure their managers are available in World before + /// calling Despawn. + /// + /// To manually register a manager early: + /// Game.World.SpawnService.AddManager(customManager); + /// This guarantees Despawn will use the developer‑provided manager instead of + /// auto-discovering one. + /// + /// Overall, Despawn provides a fast, centralized, and manager‑aware spawning + /// system that intelligently reuses previously found managers and adapts to + /// scene changes. + /// + public sealed class Despawn : IService + { + private static Despawn Ins + { + get + { + var CacheInstance = Game.GetService(false); + if (CacheInstance == null) + { + CacheInstance = new Despawn(); + Game.RegisterService(CacheInstance, null); + } + return CacheInstance; + } + } + private Dictionary Managers; + + + + + public Despawn() + { + Managers = new(); + } + public Despawn(Dictionary DefaultManager) + { + Managers = DefaultManager; + } + + + // Implement IService Interface + public object GetServiceClass() => this; + void IService.Created(object Author) + { + } + void IService.ChangingWorld(World NewWorld) + { + Managers.Clear(); + } + void IService.Deleted(object Author) + { + Managers.Clear(); + } + + // Public Functions + public void AddManager(IGameManager manager) + { + System.Type ManagerType = manager.GetManagerClass().GetType(); + if (Managers.ContainsKey(ManagerType)) + { + Managers.Add(ManagerType, manager); + } + else + { + Debug.LogWarning($"{Ins}: Manager of type '{ManagerType.Name}' already exists. Skipping add."); + } + } + + + // Public Functions + private static T GetManager() where T : MonoBehaviour + { + System.Type type = typeof(T); + if (Ins.Managers.ContainsKey(type)) + { + if (Ins.Managers[type].GetManagerClass() is T manager) + { + return manager; + } + } + else + { + var manager = Game.World.FindManager(); + if (manager is IGameManager provider) + { + Ins.Managers.Add(type, provider); + return manager; + } + } + + Debug.LogError($"{Ins}:Failed to spawn, Manager({typeof(T).Name}) is not available."); + return null; + } + + + + // UI + public static bool Widget(string Name, Object spawner = null, bool debug = true) + { + if (GetManager() == null) + { + if (debug) + Debug.LogWarning("Despawn UIManager is not available."); + return false; + } + + return GetManager().RemoveLayer(Name, spawner); + } + public static bool Widget(MonoBehaviour Comp, Object spawner = null, bool debug = true) + { + if (GetManager() == null) + { + if (debug) + Debug.LogWarning("Despawn UIManager is not available."); + return false; + } + + return GetManager().RemoveLayer(Comp, spawner); + } + + // Prefab + public static bool GameObject(GameObject target, Object spawner = null, bool debug = true) + { + if (target != null) + { + if (spawner != null) + { + target.InvokeDespawnEvent(spawner); + } + Object.Destroy(target); + return true; + } + else + { + if (debug) + Debug.LogWarning("Despawn target is not available."); + return false; + } + } + + // Pool + public static bool Pool(PoolAsset asset, bool debug = true) where T : Component + { + if (asset is IPoolDespawner pooler) + { + pooler.Despawn(); + return true; + } + else + { + if (debug) + Debug.LogWarning("PoolAsset does not implement IPoolDespawner."); + return false; + } + } + public static bool Pool(PoolAsset asset, T target, bool debug = true) where T : Component + { + if (asset is IPoolDespawner pooler) + { + pooler.Despawn(target); + return true; + } + else + { + if (debug) + Debug.LogWarning("PoolAsset does not implement IPoolDespawner."); + return false; + } + } + + // Task + public static bool Task(object TaskObj, Object author, bool debug = true) + { + if (GetManager() == null) + { + if (debug) + Debug.LogWarning("TaskManager is not available."); + return false; + } + + if (TaskObj is ITask task) + { + if (GetManager().IsValid(task)) + { + GetManager().Remove(task, author); + return true; + } + else + { + if (debug) + Debug.LogWarning($"Task Not Found!"); + return false; + } + } + else + { + if (debug) + Debug.LogWarning($"Your Object should have {typeof(ITask)} Interfave"); + return false; + } + } + + // Enumerator + public static bool Coroutine(Coroutine coroutine, bool debug = true) + { + if (GetManager() == null) + { + if (debug) + Debug.LogWarning("TaskManager is not available."); + return false; + } + + GetManager().Stop(coroutine); + return true; + } + + // Haptic + public static bool Haptic(IHapticProvider provider, bool debug = true) + { + if (GetManager() == null) + { + if (debug) + Debug.LogWarning("HapticManager is not available."); + return false; + } + return GetManager().Demolish(provider); + } + + // Debug + public static bool Printer(IPrint printer, bool debug = true) + { + if (GetManager() == null) + { + if (debug) + Debug.LogWarning("Despawn PrintManager is not available."); + return false; + } + return GetManager().RemoveStatic(printer); + } + public static bool Button(IButton button, bool debug = true) + { + if (GetManager() == null) + { + if (debug) + Debug.LogWarning("Despawn DebugManager is not available."); + return false; + } + return GetManager().Remove(button); + } + + + } +} \ No newline at end of file diff --git a/Runtime/ReadySet/Services/DespawnService.cs.meta b/Runtime/ReadySet/Services/DespawnService.cs.meta new file mode 100644 index 0000000..23e6071 --- /dev/null +++ b/Runtime/ReadySet/Services/DespawnService.cs.meta @@ -0,0 +1,2 @@ +fileFormatVersion: 2 +guid: 4d4786c83f476584184bb4cc13d2e042 \ No newline at end of file diff --git a/Runtime/ReadySet/Services/SpawanService.cs b/Runtime/ReadySet/Services/SpawanService.cs index 43986f3..2c980c0 100644 --- a/Runtime/ReadySet/Services/SpawanService.cs +++ b/Runtime/ReadySet/Services/SpawanService.cs @@ -2,194 +2,187 @@ using UnityEngine; using UnityEngine.Audio; using UnityEngine.UIElements; +using System.Collections.Generic; namespace RealMethod { - public sealed class Spawn : Service + /// + /// Spawn is a sealed static service used to instantiate gameplay objects such as + /// prefabs, UI elements, audio sources, and other spawnable types. + /// + /// This class automatically locates the required manager instances from the + /// World scope. When a new spawn request is made, Spawn will: + /// 1) Look for a cached manager of the requested type. + /// 2) If missing, it will attempt to find the manager inside World. + /// 3) The found manager is cached internally for reuse to avoid repeated lookups. + /// + /// Developers may register their own managers manually if needed. + /// This is useful when: + /// • A custom manager needs to be used before Spawn's automatic discovery. + /// • Multiple child managers inherit from an abstract base manager. + /// (Example: UIManager → ScreenManager / HUDManager) + /// Spawn will always pick the FIRST accessible base type (UIManager), + /// unless the developer registers a specific child manager earlier. + /// + /// Important notes: + /// • Spawn is a sealed class and cannot be inherited or modified. + /// • Spawn’s methods work only with the corresponding manager types + /// (UIManager, AudioManager, ScreenManager, TaskManager, HapticManager, EnumeratorManager & ..). + /// • When scenes change, World scope clears all managers. Spawn will also + /// lose cached references and re-discover managers on the next request. + /// Developers must ensure their managers are available in World before + /// calling Spawn. + /// + /// To manually register a manager early: + /// Game.World.SpawnService.AddManager(customManager); + /// This guarantees Spawn will use the developer‑provided manager instead of + /// auto-discovering one. + /// + /// Overall, Spawn provides a fast, centralized, and manager‑aware spawning + /// system that intelligently reuses previously found managers and adapts to + /// scene changes. + /// + public sealed class Spawn : IService { - private static Spawn CacheInstance = null; - public static Spawn instance + private static Spawn Ins { get { - if (CacheInstance != null) + var CacheInstance = Game.GetService(false); + if (CacheInstance == null) { - return CacheInstance; - } - else - { - if (Game.TryGetService(out Spawn CacheInstance)) - { - return CacheInstance; - } - CacheInstance = Game.AddService(null); - return CacheInstance; + CacheInstance = new Spawn(); + Game.RegisterService(CacheInstance, null); } + return CacheInstance; } } - public Despawn GameDespawn; - public AudioManager GameAudio; - public UIManager GameUI; - public ScreenManager GameScreen; - public TaskManager GameTask; - public HapticManager GameHaptic; - public EnumeratorManager GameEnumerator; - public PrintManager GamePrint => Game.FindManager(); - public DebugManager GameDebug => Game.FindManager(); + private Dictionary Managers; - // Base Service - protected override void OnStart(object Author) + + public Spawn() + { + Managers = new(); + } + public Spawn(Dictionary DefaultManager) { - GameDespawn = new Despawn(); + Managers = DefaultManager; } - protected override void OnWorldChanging(World Previous, World New) + + + // Implement IService Interface + public object GetServiceClass() => this; + void IService.Created(object Author) { } - protected override void OnEnd(object Author) + void IService.ChangingWorld(World NewWorld) { - GameDespawn = null; - GameAudio = null; - GameUI = null; - GameScreen = null; - GameTask = null; - GameHaptic = null; - GameEnumerator = null; - CacheInstance = null; + Managers.Clear(); + } + void IService.Deleted(object Author) + { + Managers.Clear(); } // Public Functions - public void BringManager(IGameManager manager) + public void AddManager(IGameManager manager) { - MonoBehaviour TargetManager = manager.GetManagerClass(); - switch (TargetManager) // **Order is very important** + System.Type ManagerType = manager.GetManagerClass().GetType(); + if (Managers.ContainsKey(ManagerType)) { - case ScreenManager screenmanager: // Bring ScreenManager - if (GameScreen == null) - { - GameScreen = screenmanager; - } - else - { - Debug.LogError($"Spawn Service already have {typeof(ScreenManager)} Cant Enter this {screenmanager}"); - } - break; - case TaskManager taskmanager: // Bring TaskManager - if (GameTask == null) - { - GameTask = taskmanager; - } - else - { - Debug.LogError($"Spawn Service already have {typeof(TaskManager)} Cant Enter this {taskmanager}"); - } - break; - case EnumeratorManager enumeratormanager: - if (GameEnumerator == null) - { - GameEnumerator = enumeratormanager; - } - else - { - Debug.LogError($"Spawn Service already have {typeof(EnumeratorManager)} Cant Enter this {enumeratormanager}"); - } - break; - case HapticManager hapticmanager: - if (GameHaptic == null) - { - GameHaptic = hapticmanager; - } - else - { - Debug.LogError($"Spawn Service already have {typeof(HapticManager)} Cant Enter this {hapticmanager}"); - } - break; - case AudioManager audiomanager: // Brind AudioManager - if (GameAudio == null) - { - GameAudio = audiomanager; - } - else - { - Debug.LogError($"Spawn Service already have {typeof(AudioManager)} Cant Enter this {audiomanager}"); - } - break; - case UIManager uIManager: // Brind UIManager - if (GameUI == null) - { - GameUI = uIManager; - } - else - { - Debug.LogError($"Spawn Service already have {typeof(UIManager)} Cant Enter this {uIManager}"); - } - break; - default: - Debug.LogWarning($"{TargetManager.gameObject}:Manager not define in SpawnService"); - break; + Managers.Add(ManagerType, manager); + } + else + { + Debug.LogWarning($"{Ins}: Manager of type '{ManagerType.Name}' already exists. Skipping add."); } } + // Private Functions + private static T GetManager() where T : MonoBehaviour + { + System.Type type = typeof(T); + if (Ins.Managers.ContainsKey(type)) + { + if (Ins.Managers[type].GetManagerClass() is T manager) + { + return manager; + } + } + else + { + var manager = Game.World.FindManager(); + if (manager is IGameManager provider) + { + Ins.Managers.Add(type, provider); + return manager; + } + } + + Debug.LogError($"{Ins}:Failed to spawn, Manager({typeof(T).Name}) is not available. [Note:Manger should be in WorldScope or add manualy]"); + return null; + } // UI public static T Widget(string Name, Object spawner = null) where T : MonoBehaviour { - if (instance.GameUI != null) + if (GetManager() != null) { - return instance.GameUI.CreateLayer(Name, spawner); + return GetManager().CreateLayer(Name, spawner); } else { - Debug.LogWarning($" {instance}: UIManager is not available."); + Debug.LogWarning($" {Ins}: UIManager is not available."); return null; } } public static T Widget(VisualTreeAsset UIAsset, string Name, Object spawner = null) where T : MonoBehaviour { - if (instance.GameUI != null) + if (GetManager() != null) { - return instance.GameUI.CreateLayer(Name, UIAsset, spawner); + return GetManager().CreateLayer(Name, UIAsset, spawner); } else { - Debug.LogWarning($" {instance}: UIManager is not available."); + Debug.LogWarning($" {Ins}: UIManager is not available."); return null; } } public static GameObject Widget(UPrefab Prefab, string Name, Object spawner = null) { - if (instance.GameUI != null) + if (GetManager() != null) { //if(Prefab) - return instance.GameUI.AddLayer(Name, Prefab, spawner); + return GetManager().AddLayer(Name, Prefab, spawner); } else { - Debug.LogWarning($" {instance}: UIManager is not available."); + Debug.LogWarning($" {Ins}: UIManager is not available."); return null; } } public static T Widget(UPrefab Prefab, string Name, Object spawner = null) where T : MonoBehaviour { - if (instance.GameUI != null) + if (GetManager() != null) { - return instance.GameUI.AddLayer(Name, Prefab, spawner); + return GetManager().AddLayer(Name, Prefab, spawner); } else { - Debug.LogWarning($" {instance}: UIManager is not available."); + Debug.LogWarning($" {Ins}: UIManager is not available."); return null; } } public static UIDocument UIDoc(string Name, VisualTreeAsset UIAsset) { - if (instance.GameUI != null) + if (GetManager() != null) { - return instance.GameUI.CreateLayer(Name, UIAsset); + return GetManager().CreateLayer(Name, UIAsset); } else { - Debug.LogWarning($" {instance}: UIManager is not available."); + Debug.LogWarning($" {Ins}: UIManager is not available."); return null; } } @@ -197,11 +190,11 @@ public static UIDocument UIDoc(string Name, VisualTreeAsset UIAsset) // Screen public static void Message(string message) { - if (instance.GameScreen != null) + if (GetManager() != null) { - if (instance.GameScreen.Informer != null) + if (GetManager().Informer != null) { - instance.GameScreen.Informer.Popup(message); + GetManager().Informer.Popup(message); } else { @@ -210,16 +203,16 @@ public static void Message(string message) } else { - Debug.LogWarning($" {instance}: ScreenManager is not available."); + Debug.LogWarning($" {Ins}: ScreenManager is not available."); } } public static void Message(string message, float duration) { - if (instance.GameScreen != null) + if (GetManager() != null) { - if (instance.GameScreen.Informer != null) + if (GetManager().Informer != null) { - instance.GameScreen.Informer.Popup(message, duration); + GetManager().Informer.Popup(message, duration); } else { @@ -228,16 +221,16 @@ public static void Message(string message, float duration) } else { - Debug.LogWarning($" {instance}: ScreenManager is not available."); + Debug.LogWarning($" {Ins}: ScreenManager is not available."); } } // Sound public static AudioSource Sound3D(AudioClip clip, Vector3 location, Transform parent = null, AudioMixerGroup group = null, float rolloffDistanceMin = 1f, bool loop = false, float pauseTime = 0, bool autoDestroy = true) { - if (instance.GameAudio != null) + if (GetManager() != null) { - return instance.GameAudio.PlaySound(clip, location, parent, group, rolloffDistanceMin, loop, pauseTime, autoDestroy); + return GetManager().PlaySound(clip, location, parent, group, rolloffDistanceMin, loop, pauseTime, autoDestroy); } else { @@ -268,9 +261,9 @@ public static AudioSource Sound3D(AudioClip clip, Vector3 location, Transform pa } public static AudioSource Sound2D(AudioClip clip, AudioMixerGroup group = null, float rolloffDistanceMin = 1f, bool loop = false, float pauseTime = 0, bool autoDestroy = true) { - if (instance.GameAudio != null) + if (GetManager() != null) { - return instance.GameAudio.PlaySound2D(clip, group, 1, loop, pauseTime, autoDestroy); + return GetManager().PlaySound2D(clip, group, 1, loop, pauseTime, autoDestroy); } else { @@ -623,13 +616,13 @@ public static EffectPlayer Effect(EPrefab prefab, Transform parent, Object spawn // Haptic public static IHapticProvider Haptic(HapticConfig config) { - if (instance.GameHaptic != null) + if (GetManager() != null) { - return instance.GameHaptic.Produce(config); + return GetManager().Produce(config); } else { - Debug.LogWarning($" {instance}: HapticManager is not available."); + Debug.LogWarning($" {Ins}: HapticManager is not available."); return null; } } @@ -658,7 +651,7 @@ public static T Component(GameObject target, Object spawner = null) where T : } else { - Debug.LogWarning($" {instance}: target is not valid."); + Debug.LogWarning($" {Ins}: target is not valid."); return null; } @@ -667,7 +660,7 @@ public static T Class(System.Type classType) { if (classType == null) { - Debug.LogWarning($" {instance}: ClassType is not valid!"); + Debug.LogWarning($" {Ins}: ClassType is not valid!"); return default; } return (T)System.Activator.CreateInstance(classType); @@ -678,7 +671,7 @@ public static T Command(CPrefab prefab, MonoBehaviour owner) where T : Comman { if (owner == null) { - Debug.LogWarning($" {instance}: Owner or Author is not available."); + Debug.LogWarning($" {Ins}: Owner or Author is not available."); return null; } GameObject SpawnedObject = Object.Instantiate(prefab, owner.transform); @@ -713,13 +706,13 @@ public static T Asset(Object spawner = null) where T : PrimitiveAsset // Task public static bool Task(object TaskObj, Object author) { - if (instance.GameTask != null) + if (GetManager() != null) { if (TaskObj is ITask task) { - if (!instance.GameTask.IsValid(task)) + if (!GetManager().IsValid(task)) { - instance.GameTask.Add(task, author); + GetManager().Add(task, author); return true; } else @@ -736,7 +729,7 @@ public static bool Task(object TaskObj, Object author) } else { - Debug.LogWarning($" {instance}: TaskManager is not available."); + Debug.LogWarning($" {Ins}: TaskManager is not available."); return false; } } @@ -744,25 +737,25 @@ public static bool Task(object TaskObj, Object author) // Enumerator public static Coroutine Coroutine(IEnumerator routine) { - if (instance.GameEnumerator != null) + if (GetManager() != null) { - return instance.GameEnumerator.Run(routine); + return GetManager().Run(routine); } else { - Debug.LogWarning($" {instance}: EnumeratorManager is not available."); + Debug.LogWarning($" {Ins}: EnumeratorManager is not available."); return null; } } public static ICoroutineTask CoroutineTask(IEnumerator routine) { - if (instance.GameEnumerator != null) + if (GetManager() != null) { - return instance.GameEnumerator.StartTask(routine); + return GetManager().StartTask(routine); } else { - Debug.LogWarning($" {instance}: EnumeratorManager is not available."); + Debug.LogWarning($" {Ins}: EnumeratorManager is not available."); return null; } } @@ -770,25 +763,25 @@ public static ICoroutineTask CoroutineTask(IEnumerator routine) // Debug public static IPrint Printer(Vector2 offcet) { - if (instance.GamePrint != null) + if (GetManager() != null) { - return instance.GamePrint.PrintStatic(offcet); + return GetManager().PrintStatic(offcet); } else { - Debug.LogWarning($" {instance}: PrintManager is not available."); + Debug.LogWarning($" {Ins}: PrintManager is not available."); return null; } } public static IButton Button(Name16 Name, System.Action Callback) { - if (instance.GameDebug != null) + if (GetManager() != null) { - return instance.GameDebug.AddButton(Name, Callback); + return GetManager().AddButton(Name, Callback); } else { - Debug.LogWarning($" {instance}: DebugManager is not available."); + Debug.LogWarning($" {Ins}: DebugManager is not available."); return null; } } @@ -815,173 +808,16 @@ public static AudioSource Audio(AudioClip clip) GameObject emptyobject = new GameObject(clip.name); AudioSource source = emptyobject.AddComponent(); source.clip = clip; - if (instance.GameAudio != null) + if (GetManager() != null) { - source.outputAudioMixerGroup = instance.GameAudio.defaultGroup; - emptyobject.transform.SetParent(instance.GameAudio.transform); + source.outputAudioMixerGroup = GetManager().defaultGroup; + emptyobject.transform.SetParent(GetManager().transform); } return source; } } - public sealed class Despawn - { - // UI - public static bool Widget(string Name, Object spawner = null, bool debug = true) - { - if (Spawn.instance.GameUI == null) - { - if (debug) - Debug.LogWarning("Despawn UIManager is not available."); - return false; - } - return Spawn.instance.GameUI.RemoveLayer(Name, spawner); - } - public static bool Widget(MonoBehaviour Comp, Object spawner = null, bool debug = true) - { - if (Spawn.instance.GameUI == null) - { - if (debug) - Debug.LogWarning("Despawn UIManager is not available."); - return false; - } - - return Spawn.instance.GameUI.RemoveLayer(Comp, spawner); - } - - // Prefab - public static bool GameObject(GameObject target, Object spawner = null, bool debug = true) - { - if (target != null) - { - if (spawner != null) - { - target.InvokeDespawnEvent(spawner); - } - Object.Destroy(target); - return true; - } - else - { - if (debug) - Debug.LogWarning("Despawn target is not available."); - return false; - } - } - - // Pool - public static bool Pool(PoolAsset asset, bool debug = true) where T : Component - { - if (asset is IPoolDespawner pooler) - { - pooler.Despawn(); - return true; - } - else - { - if (debug) - Debug.LogWarning("PoolAsset does not implement IPoolDespawner."); - return false; - } - } - public static bool Pool(PoolAsset asset, T target, bool debug = true) where T : Component - { - if (asset is IPoolDespawner pooler) - { - pooler.Despawn(target); - return true; - } - else - { - if (debug) - Debug.LogWarning("PoolAsset does not implement IPoolDespawner."); - return false; - } - } - - // Task - public static bool Task(object TaskObj, Object author, bool debug = true) - { - if (Spawn.instance.GameTask == null) - { - if (debug) - Debug.LogWarning("TaskManager is not available."); - return false; - } - - if (TaskObj is ITask task) - { - if (Spawn.instance.GameTask.IsValid(task)) - { - Spawn.instance.GameTask.Remove(task, author); - return true; - } - else - { - if (debug) - Debug.LogWarning($"Task Not Found!"); - return false; - } - } - else - { - if (debug) - Debug.LogWarning($"Your Object should have {typeof(ITask)} Interfave"); - return false; - } - } - - // Enumerator - public static bool Coroutine(Coroutine coroutine, bool debug = true) - { - if (Spawn.instance.GameEnumerator == null) - { - if (debug) - Debug.LogWarning("TaskManager is not available."); - return false; - } - - Spawn.instance.GameEnumerator.Stop(coroutine); - return true; - } - - // Haptic - public static bool Haptic(IHapticProvider provider, bool debug = true) - { - if (Spawn.instance.GameHaptic == null) - { - if (debug) - Debug.LogWarning("HapticManager is not available."); - return false; - } - return Spawn.instance.GameHaptic.Demolish(provider); - } - - // Debug - public static bool Printer(IPrint printer, bool debug = true) - { - if (Spawn.instance.GamePrint == null) - { - if (debug) - Debug.LogWarning("Despawn PrintManager is not available."); - return false; - } - return Spawn.instance.GamePrint.RemoveStatic(printer); - } - public static bool Button(IButton button, bool debug = true) - { - if (Spawn.instance.GameDebug == null) - { - if (debug) - Debug.LogWarning("Despawn DebugManager is not available."); - return false; - } - return Spawn.instance.GameDebug.Remove(button); - } - - - } } diff --git a/Runtime/Toolkit/RPG/StatSystem/CharacterStatComponent.cs b/Runtime/Toolkit/RPG/StatSystem/CharacterStatComponent.cs index b3acf7a..fc274fe 100644 --- a/Runtime/Toolkit/RPG/StatSystem/CharacterStatComponent.cs +++ b/Runtime/Toolkit/RPG/StatSystem/CharacterStatComponent.cs @@ -31,7 +31,7 @@ private void Awake() } private void Start() { - SaveSystem = Game.FindManager(); + SaveSystem = Game.GetManager(); } private void OnEnable() { From bbe8810c2b523820a20282846bbce90e53bccd4b Mon Sep 17 00:00:00 2001 From: Alijimpa Date: Tue, 7 Apr 2026 07:48:52 +0330 Subject: [PATCH 092/204] Refine Audio Manager --- Runtime/Core/Architecture/World.cs | 2 +- Runtime/Pattern/Managers/AudioManager.cs | 8 ++++---- Runtime/ReadySet/Services/SpawanService.cs | 2 +- 3 files changed, 6 insertions(+), 6 deletions(-) diff --git a/Runtime/Core/Architecture/World.cs b/Runtime/Core/Architecture/World.cs index 686c37f..e589170 100644 --- a/Runtime/Core/Architecture/World.cs +++ b/Runtime/Core/Architecture/World.cs @@ -119,7 +119,7 @@ private void Awake() { if (!CashManagers.Contains(manager)) { - manager.InitiateManager(true); + manager.InitiateManager(false); CashManagers.Add(manager); } else diff --git a/Runtime/Pattern/Managers/AudioManager.cs b/Runtime/Pattern/Managers/AudioManager.cs index 6227f5e..c258e86 100644 --- a/Runtime/Pattern/Managers/AudioManager.cs +++ b/Runtime/Pattern/Managers/AudioManager.cs @@ -10,8 +10,8 @@ public abstract class AudioManager : MixerManager { [Header("Audio")] [SerializeField] - private AudioMixerGroup DefaultGroup; - public AudioMixerGroup defaultGroup => DefaultGroup; + private AudioMixerGroup defaultGroup; + public AudioMixerGroup DefaultGroup => defaultGroup; public ObjectPool soundPool; @@ -38,7 +38,7 @@ public AudioSource PlaySound(AudioClip clip, Vector3 location, Transform parent { AudioSource source = soundPool.Get(); source.clip = clip; - source.outputAudioMixerGroup = group != null ? group : DefaultGroup; + source.outputAudioMixerGroup = group != null ? group : defaultGroup; source.spatialBlend = 1; source.minDistance = rolloffDistanceMin; source.loop = loop; @@ -62,7 +62,7 @@ public AudioSource PlaySound2D(AudioClip clip, AudioMixerGroup group = null, flo { AudioSource source = soundPool.Get(); source.clip = clip; - source.outputAudioMixerGroup = group != null ? group : DefaultGroup; + source.outputAudioMixerGroup = group != null ? group : defaultGroup; source.spatialBlend = 0; source.minDistance = rolloffDistanceMin; source.loop = loop; diff --git a/Runtime/ReadySet/Services/SpawanService.cs b/Runtime/ReadySet/Services/SpawanService.cs index 2c980c0..b756eaa 100644 --- a/Runtime/ReadySet/Services/SpawanService.cs +++ b/Runtime/ReadySet/Services/SpawanService.cs @@ -810,7 +810,7 @@ public static AudioSource Audio(AudioClip clip) source.clip = clip; if (GetManager() != null) { - source.outputAudioMixerGroup = GetManager().defaultGroup; + source.outputAudioMixerGroup = GetManager().DefaultGroup; emptyobject.transform.SetParent(GetManager().transform); } return source; From a004d7508c44d5688ad416b84a37a4bc88918e82 Mon Sep 17 00:00:00 2001 From: Alijimpa Date: Wed, 8 Apr 2026 14:26:13 +0330 Subject: [PATCH 093/204] Refine Music Manager --- .../CompositManagerTemplate.txt | 62 +--- Runtime/Library/Utilities/Audio_Library.cs | 37 ++ .../Library/Utilities/Audio_Library.cs.meta | 2 + Runtime/Pattern/Managers/AudioManager.cs | 2 + Runtime/Pattern/Managers/CompositManager.cs | 339 +++++++----------- Runtime/Pattern/Managers/MixerManager.cs | 49 +-- Runtime/ReadySet/Managers/MusicManager.cs | 94 ++--- Runtime/ReadySet/Managers/SoundManager.cs | 3 +- 8 files changed, 243 insertions(+), 345 deletions(-) create mode 100644 Runtime/Library/Utilities/Audio_Library.cs create mode 100644 Runtime/Library/Utilities/Audio_Library.cs.meta diff --git a/Reservoir/ScriptTemplates/CompositManagerTemplate.txt b/Reservoir/ScriptTemplates/CompositManagerTemplate.txt index 753502e..79fcf3d 100644 --- a/Reservoir/ScriptTemplates/CompositManagerTemplate.txt +++ b/Reservoir/ScriptTemplates/CompositManagerTemplate.txt @@ -1,65 +1,23 @@ using RealMethod; -public class #SCRIPTNAME# : CompositManager +public class #SCRIPTNAME# : CompositManager { - [Header("Music")] + [Header("MusicList")] [SerializeField] - private AudioClip[] CreateLayers; - [SerializeField] - private bool AddServiceOnInitiate = false; + private Map Clips = new Map(); - protected override void OnInitiate(bool AlwaysLoaded) + // IGameManager Interface + protected override void InitiateManager(bool AlwaysLoaded) { - foreach (var clip in CreateLayers) + base.InitiateManager(AlwaysLoaded); + foreach (var clip in Clips) { - CreateLayer(clip); + CreateLayer(clip.Key, clip.Value); } - if (AddServiceOnInitiate) - Game.AddService(this); - } - protected override void MusicStateAssigned() - { - } -} - -public enum MUSCIENUM -{ - Default, - STATE_1, - STATE_2, -} - -public sealed class STATESETVICE : StateService -{ - public MUSCIENUM() : base(MUSCIENUM.Default) // This is the First State Value - { - - } - - // Service Methods - protected override void OnStart(object Author) - { - } - protected override void OnEnd(object Author) - { - } - // StateService Methods - protected override DefaulMusicLayer DefaultState() - { - return DefaulMusicLayer.Default; - } - public override bool CanSwitch(DefaulMusicLayer A, DefaulMusicLayer B) - { - if (A == B) - { - return false; - } - return true; - } - protected override bool CanResetforNewWorld(World NewWorld) + protected override bool CompairStates(MUSCIENUM State_A, MUSCIENUM State_B) { - return false; + return State_A == State_B; } } \ No newline at end of file diff --git a/Runtime/Library/Utilities/Audio_Library.cs b/Runtime/Library/Utilities/Audio_Library.cs new file mode 100644 index 0000000..9f73874 --- /dev/null +++ b/Runtime/Library/Utilities/Audio_Library.cs @@ -0,0 +1,37 @@ +using System.Collections; +using UnityEngine; + +namespace RealMethod +{ + public static class RM_Audio + { + public static IEnumerator FadeIn(AudioSource source, float duration) + { + source.Play(); + source.volume = 0f; // Start volume at 0 + float timer = 0f; + while (timer < duration) + { + float t = timer / duration; + source.volume = Mathf.Lerp(0f, 1f, t); + timer += Time.deltaTime; + yield return null; + } + source.volume = 1f; // Ensure volume is set to 1 at the end + } + public static IEnumerator FadeOut(AudioSource source, float duration) + { + source.volume = 1f; // Start volume at 1 + float timer = 0f; + while (timer < duration) + { + float t = timer / duration; + source.volume = Mathf.Lerp(1f, 0f, t); + timer += Time.deltaTime; + yield return null; + } + source.volume = 0f; // Ensure volume is set to 0 at the end + source.Stop(); + } + } +} \ No newline at end of file diff --git a/Runtime/Library/Utilities/Audio_Library.cs.meta b/Runtime/Library/Utilities/Audio_Library.cs.meta new file mode 100644 index 0000000..d1b083f --- /dev/null +++ b/Runtime/Library/Utilities/Audio_Library.cs.meta @@ -0,0 +1,2 @@ +fileFormatVersion: 2 +guid: bce6038384528304090fe144e937d7d1 \ No newline at end of file diff --git a/Runtime/Pattern/Managers/AudioManager.cs b/Runtime/Pattern/Managers/AudioManager.cs index c258e86..649ec9d 100644 --- a/Runtime/Pattern/Managers/AudioManager.cs +++ b/Runtime/Pattern/Managers/AudioManager.cs @@ -17,6 +17,8 @@ public abstract class AudioManager : MixerManager protected override void InitiateManager(bool AlwaysLoaded) { + base.InitiateManager(AlwaysLoaded); + if (AlwaysLoaded) { Debug.LogError("You can't use AudioManager in [Game] Scope"); diff --git a/Runtime/Pattern/Managers/CompositManager.cs b/Runtime/Pattern/Managers/CompositManager.cs index 795ec54..5714665 100644 --- a/Runtime/Pattern/Managers/CompositManager.cs +++ b/Runtime/Pattern/Managers/CompositManager.cs @@ -1,5 +1,4 @@ using System; -using System.Collections; using System.Collections.Generic; using System.Linq; using UnityEngine; @@ -33,13 +32,37 @@ public void Pitch(float alpha, float minPitch = -3f, float maxPitch = 3f) } [Header("Composit")] [SerializeField] + private Transform header; + [SerializeField] private AudioMixerGroup DefaultGroup; - private NameTable Layers = new NameTable(5); + protected NameTable Layers = new NameTable(5); public int LayerCount => Layers.Count; + // Override Methods + protected override void InitiateManager(bool AlwaysLoaded) + { + base.InitiateManager(AlwaysLoaded); + + foreach (Transform item in header) + { + AudioSource source = item.GetComponent(); + if (source != null) + { + if (!Layers.ContainsKey(item.name)) + { + Layers.Add(item.name, source); + } + else + { + Debug.LogWarning($"Layer '{item.name}' already exists in the manager."); + } + } + } + } + // Public Functions - public void PlayLayer(string layerName) + public void PlayLayer(Name16 layerName) { if (Layers.ContainsKey(layerName)) { @@ -58,7 +81,7 @@ public void PlayLayer(string layerName) Debug.LogWarning($"Layer '{layerName}' does not exist in the manager."); } } - public void PauseLayer(string layerName) + public void PauseLayer(Name16 layerName) { if (Layers.ContainsKey(layerName)) { @@ -77,25 +100,35 @@ public void PauseLayer(string layerName) Debug.LogWarning($"Layer '{layerName}' does not exist in the manager."); } } - public bool IsValidLayer(string layerName) + public void Pause() + { + foreach (var layer in Layers) + { + if (layer.Value is AudioSource source) + { + source.Pause(); + } + } + } + public bool IsValidLayer(Name16 layerName) { return Layers.ContainsKey(layerName); } - public void AddLayer(string layerName, APrefab prefab) + public void AddLayer(Name16 layerName, APrefab prefab) { if (IsValidLayer(layerName)) { Debug.LogWarning($"Layer '{layerName}' already exists. Use a different name."); return; } - AudioSource source = Instantiate(prefab, transform).GetComponent(); + AudioSource source = Instantiate(prefab, header).GetComponent(); Layers.Add(layerName, source); } public void CreateLayer(AudioClip clip) { CreateLayer(clip.name, clip); } - public void CreateLayer(string layerName, AudioClip clip) + public void CreateLayer(Name16 layerName, AudioClip clip) { if (IsValidLayer(layerName)) { @@ -103,7 +136,7 @@ public void CreateLayer(string layerName, AudioClip clip) return; } GameObject SoundObject = new GameObject("Layer_" + clip.name, new Type[1] { typeof(AudioSource) }); - SoundObject.transform.SetParent(transform); + SoundObject.transform.SetParent(header); AudioSource source = SoundObject.GetComponent(); source.clip = clip; source.outputAudioMixerGroup = DefaultGroup; @@ -113,7 +146,7 @@ public void CreateLayer(string layerName, AudioClip clip) source.loop = true; Layers.Add(layerName, source); } - public void RemoveLayer(string layerName) + public void RemoveLayer(Name16 layerName) { if (Layers.ContainsKey(layerName)) { @@ -125,14 +158,14 @@ public void RemoveLayer(string layerName) Debug.LogWarning($"Layer '{layerName}' does not exist in the manager."); } } - public void FadeInLayer(string layerName, float duration) + public void FadeInLayer(Name16 layerName, float duration) { if (Layers.ContainsKey(layerName)) { AudioSource source = Layers[layerName] as AudioSource; if (source != null) { - StartCoroutine(FadeIn(source, duration)); + StartCoroutine(RM_Audio.FadeIn(source, duration)); } else { @@ -144,14 +177,14 @@ public void FadeInLayer(string layerName, float duration) Debug.LogWarning($"Cannot fade in layer: {layerName} not found."); } } - public void FadeOutLayer(string layerName, float duration) + public void FadeOutLayer(Name16 layerName, float duration) { if (Layers.ContainsKey(layerName)) { AudioSource source = Layers[layerName] as AudioSource; if (source != null) { - StartCoroutine(FadeOut(source, duration)); + StartCoroutine(RM_Audio.FadeOut(source, duration)); } else { @@ -163,7 +196,7 @@ public void FadeOutLayer(string layerName, float duration) Debug.LogWarning($"Cannot fade out layer: {layerName} not found."); } } - public void CrossfadeLayer(string layerA, string layerB, float duration) + public void CrossfadeLayer(Name16 layerA, Name16 layerB, float duration) { if (Layers.ContainsKey(layerA) && Layers.ContainsKey(layerB)) { @@ -171,8 +204,8 @@ public void CrossfadeLayer(string layerA, string layerB, float duration) AudioSource sourceB = Layers[layerB] as AudioSource; if (sourceA != null && sourceB != null) { - StartCoroutine(FadeIn(sourceB, duration)); - StartCoroutine(FadeOut(sourceA, duration)); + StartCoroutine(RM_Audio.FadeIn(sourceB, duration)); + StartCoroutine(RM_Audio.FadeOut(sourceA, duration)); } else { @@ -184,11 +217,22 @@ public void CrossfadeLayer(string layerA, string layerB, float duration) Debug.LogWarning($"Cannot crossfade layers: {layerA} or {layerB} not found."); } } - public void TransitionToSnapshot(AudioMixerSnapshot snapshot, float transitionTime = 1f) + public AudioSource[] GetActiveLayers() { - snapshot?.TransitionTo(transitionTime); + List Result = new List(); + foreach (var layer in Layers) + { + if (layer.Value is AudioSource source) + { + if (source.isPlaying) + { + Result.Add(source); + } + } + } + return Result.ToArray(); } - public T GetLayerComponent(string layerName) where T : AudioBehaviour + public T GetLayer(Name16 layerName) where T : AudioBehaviour { if (Layers.ContainsKey(layerName)) { @@ -200,7 +244,7 @@ public T GetLayerComponent(string layerName) where T : AudioBehaviour return null; } } - public AudioSource GetLayer(string layerName) + public AudioSource GetLayer(Name16 layerName) { if (Layers.ContainsKey(layerName)) { @@ -212,248 +256,141 @@ public AudioSource GetLayer(string layerName) return null; } } - public MusicLerp CreateLerp(string LayerA, string LayerB) - { - if (!Layers.ContainsKey(LayerA) || !Layers.ContainsKey(LayerB)) - { - Debug.LogWarning($"Cannot create lerp: {LayerA} or {LayerB} not found."); - return default; - } - return new MusicLerp((AudioSource)Layers[LayerA], (AudioSource)Layers[LayerB]); - } public AudioBehaviour[] GetLayers() { return Layers.Values.ToArray(); } - // Protected Functions - protected void InitiateLayers() - { - foreach (Transform item in transform) - { - AudioSource source = item.GetComponent(); - if (source != null) - { - if (!Layers.ContainsKey(item.name)) - { - Layers.Add(item.name, source); - } - else - { - Debug.LogWarning($"Layer '{item.name}' already exists in the manager."); - } - } - } - } - - // Enumerator - private IEnumerator FadeIn(AudioSource source, float duration) - { - source.Play(); - source.volume = 0f; // Start volume at 0 - float timer = 0f; - while (timer < duration) - { - float t = timer / duration; - source.volume = Mathf.Lerp(0f, 1f, t); - timer += Time.deltaTime; - yield return null; - } - source.volume = 1f; // Ensure volume is set to 1 at the end - } - private IEnumerator FadeOut(AudioSource source, float duration) + public MusicLerp CreateLerp(Name16 LayerA, Name16 LayerB) { - source.volume = 1f; // Start volume at 1 - float timer = 0f; - while (timer < duration) + if (!Layers.ContainsKey(LayerA) || !Layers.ContainsKey(LayerB)) { - float t = timer / duration; - source.volume = Mathf.Lerp(1f, 0f, t); - timer += Time.deltaTime; - yield return null; + Debug.LogWarning($"Cannot create lerp: {LayerA} or {LayerB} not found."); + return default; } - source.volume = 0f; // Ensure volume is set to 0 at the end - source.Stop(); + return new MusicLerp((AudioSource)Layers[LayerA], (AudioSource)Layers[LayerB]); } } - - public abstract class CompositManager : CompositManager where T : StateService where J : Enum + public abstract class CompositManager : CompositManager { [Serializable] protected struct MusicState { [SerializeField] - private J State; - public J state => State; - [SerializeField] - private bool CrossWithPreviousState; - [Space] + private bool DeactivePreviousLayers; [SerializeField] - private string[] FadeInLayers; + private Name16[] ActiveLayers; [SerializeField] - private string[] FadeOutLayers; + private bool FadingMethod; + [SerializeField, ConditionalHide("FadingMethod", true, false)] + private float Duration; [Space] [SerializeField] + private bool ApplySnapshot; + [SerializeField, ConditionalHide("ApplySnapshot", true, false)] public AudioMixerSnapshot shot; - [SerializeField] - private float duration; - - private CompositManager manager; - public void Start(CompositManager owner) - { - manager = owner; - } - public void Run(MusicState previousState) + public void Play(CompositManager manager) { - if (manager == null) + if (DeactivePreviousLayers) { - return; - } - if (CrossWithPreviousState) - { - previousState.Reverse(); - } - if (FadeInLayers != null) - { - foreach (var layer in FadeInLayers) + AudioSource[] layers = manager.GetActiveLayers(); + foreach (var layer in layers) { - manager.FadeInLayer(layer, duration); + if (FadingMethod) + { + manager.StartCoroutine(RM_Audio.FadeOut(layer, Duration)); + } + else + { + layer.Stop(); + } + } } - if (FadeOutLayers != null) + + foreach (var layer in ActiveLayers) { - foreach (var layer in FadeOutLayers) + if (FadingMethod) { - manager.FadeOutLayer(layer, duration); + manager.FadeInLayer(layer, Duration); + } + else + { + manager.PauseLayer(layer); } } - if (shot != null) - { - manager.TransitionToSnapshot(shot, duration); - } - } - public void Reverse() - { - if (manager == null) - { - return; - } - if (FadeInLayers != null) + if (ApplySnapshot) { - foreach (var layer in FadeInLayers) - { - manager.FadeOutLayer(layer, duration); - } + manager.TransitionToSnapshot(shot, Duration); } } } - [Header("State")] + [field: SerializeField] + protected bool PlayOnStart { get; private set; } = true; + [field: SerializeField] + public T CurrentState { get; protected set; } [SerializeField] - private MusicState[] StateBehavior; - [SerializeField, Tooltip("Run the default state on initiate, if true, the 'FirstState' in the Service Class will be run Behavior.")] - private bool RunFirstState = false; + protected Map StateBehavior = new Map(); - protected T stateService; - public J currentState => stateService.GetCurrentState(); + public event Action OnMusicChange; - // IGameManager Interface Implementation - protected sealed override void InitiateManager(bool AlwaysLoaded) + // Unity + protected virtual void Start() { - InitiateLayers(); - OnInitiate(AlwaysLoaded); - InitiateMusicStates(); - if (Game.TryGetService(out stateService)) + if (PlayOnStart) { - stateService.OnStateUpdate += OnStateChanged; - if (RunFirstState) - { - if (IsValidState(currentState)) - { - GetMusicState(currentState).Run(default); - } - else - { - Debug.LogWarning($"First state '{currentState}' is not valid in the music state behavior."); - } - } - MusicStateAssigned(); + PlayState(CurrentState, false); } } - protected sealed override void InitiateService(Service service) + + // Public Functions + public void PlayState(T state, bool CompairState = true) { - if (stateService == null) + if (CompairState) { - if (service is T stateserv) + if (CompairStates(state, CurrentState)) { - stateService = stateserv; - stateService.OnStateUpdate += OnStateChanged; - if (IsValidState(currentState)) - { - GetMusicState(currentState).Run(default); - } - else - { - Debug.LogWarning($"First state '{currentState}' is not valid in the music state behavior."); - } - MusicStateAssigned(); + Debug.LogWarning($"State {state} already is playing"); + return; } } - } - - - // Protected Methods - protected virtual void OnStateChanged(StateService service) - { - J NewState = stateService.GetCurrentState(); - if (IsValidState(NewState)) + if (TryFindState(state, out MusicState Music)) { - MusicState NewMusicState = GetMusicState(NewState); - J LastState = stateService.GetPreviousState(); - MusicState LastMusicState = GetMusicState(LastState); - NewMusicState.Run(LastMusicState); + Music.Play(this); + CurrentState = state; + OnMusicChange?.Invoke(CurrentState); } - } - - // Private Methods - private void InitiateMusicStates() - { - List seen = new List(); - - for (int i = 0; i < StateBehavior.Length; i++) + else { - if (seen.Contains(StateBehavior[i].state)) - { - Debug.LogWarning($"Duplicate layer '{StateBehavior[i].state}' found at index {i} (already added at index {seen.IndexOf(StateBehavior[i].state)})"); - } - else - { - StateBehavior[i].Start(this); - seen.Add(StateBehavior[i].state); - } + Debug.LogWarning($"State ({state}) is not valid in the music state behavior."); } } - private bool IsValidState(J state) + public bool IsValidState(T TargetState) { - return StateBehavior.Any(s => s.state.Equals(state)); + return StateBehavior.ContainsKey(TargetState); } - private MusicState GetMusicState(J state) + + // Private Functions + protected bool TryFindState(T TargetState, out MusicState result) { - return StateBehavior.FirstOrDefault(s => s.state.Equals(state)); + if (StateBehavior.ContainsKey(TargetState)) + { + result = StateBehavior[TargetState]; + return true; + } + result = default; + return false; } - - //Abstract Method - protected abstract void OnInitiate(bool AlwaysLoaded); - protected abstract void MusicStateAssigned(); - + // Abstraction Methods + protected abstract bool CompairStates(T State_A, T State_B); } - } \ No newline at end of file diff --git a/Runtime/Pattern/Managers/MixerManager.cs b/Runtime/Pattern/Managers/MixerManager.cs index ee9b26e..ade5b2b 100644 --- a/Runtime/Pattern/Managers/MixerManager.cs +++ b/Runtime/Pattern/Managers/MixerManager.cs @@ -8,16 +8,22 @@ public abstract class MixerManager : MonoBehaviour, IGameManager { [Header("Mixer")] [SerializeField] - private AudioMixer Mixer; - public AudioMixer mixer => Mixer; + private AudioMixer mixer; + public AudioMixer Mixer => mixer; +#if UNITY_EDITOR [SerializeField] private Map Parameter; +#endif // Operators - public float this[string name] + public float this[string param] { - get => Parameter[name]; - set => Parameter[name] = value; + get + { + mixer.GetFloat(param, out float result); + return result; + } + set => mixer.SetFloat(param, value); } // IGameManager Interface Implementation @@ -31,22 +37,22 @@ void IGameManager.InitiateManager(bool AlwaysLoaded) } void IGameManager.ResolveService(Service service, bool active) { - InitiateService(service); + ResolveService(service, active); } // Unity Methods #if UNITY_EDITOR private void OnValidate() { - if (Mixer != null) + if (mixer != null) { Parameter.Clear(); - System.Array parameters = (System.Array)Mixer.GetType().GetProperty("exposedParameters").GetValue(Mixer, null); + System.Array parameters = (System.Array)mixer.GetType().GetProperty("exposedParameters").GetValue(mixer, null); for (int i = 0; i < parameters.Length; i++) { var o = parameters.GetValue(i); string PrametrName = (string)o.GetType().GetField("name").GetValue(o); - Mixer.GetFloat(PrametrName, out float result); + mixer.GetFloat(PrametrName, out float result); Parameter.Add(PrametrName, result); } } @@ -54,25 +60,20 @@ private void OnValidate() #endif // Public Functions - public void Sync() + public void TransitionToSnapshot(AudioMixerSnapshot snapshot, float transitionTime = 1f) + { + snapshot?.TransitionTo(transitionTime); + } + + // Protected Method + protected virtual void InitiateManager(bool AlwaysLoaded) { - if (Mixer != null) - { - foreach (var param in Parameter) - { - Mixer.SetFloat(param.Key, param.Value); - } - } - else - { - Debug.LogError("AudioMixers Not Valid!"); - } } + protected virtual void ResolveService(Service service, bool active) + { - // Abstract Method - protected abstract void InitiateManager(bool AlwaysLoaded); - protected abstract void InitiateService(Service service); + } } diff --git a/Runtime/ReadySet/Managers/MusicManager.cs b/Runtime/ReadySet/Managers/MusicManager.cs index 520e34d..78350de 100644 --- a/Runtime/ReadySet/Managers/MusicManager.cs +++ b/Runtime/ReadySet/Managers/MusicManager.cs @@ -3,96 +3,56 @@ namespace RealMethod { [AddComponentMenu("RealMethod/Manager/MusicManager")] - public sealed class MusicManager : CompositManager + public sealed class MusicManager : CompositManager { - [Header("Music")] + [Header("MusicList")] [SerializeField] - private AudioClip[] CreateLayers; - [SerializeField] - private bool AddServiceOnInitiate = false; + private Map Clips = new Map(); - protected override void OnInitiate(bool AlwaysLoaded) + // IGameManager Interface + protected override void InitiateManager(bool AlwaysLoaded) { - foreach (var clip in CreateLayers) + base.InitiateManager(AlwaysLoaded); + foreach (var clip in Clips) { - CreateLayer(clip); + CreateLayer(clip.Key, clip.Value); } - if (AddServiceOnInitiate) - Game.AddService(this); - } - protected override void MusicStateAssigned() - { } - } - - public enum DefaulMusicLayer - { - Default, - Menu, - StartGame, - Level, - Cutscene, - Victory, - Defeat, - GameOver, - Tutorial, - Loading, - Exploration, - Combat, - Dialogue, - Quest, - Fight, - BossFight, - Puzzle, - Hint, - Mission, - Story, - Chase, - Damaged, - Racing, - Pause, - Inventory, - EndGame, - } - - public sealed class DefaulMusicState : StateService - { - public DefaulMusicState() : base(DefaulMusicLayer.Default) // Replace default(StateList) with an actual enum value if needed + // Unity Methods + private void OnEnable() { - + Game.OnStateChanged += OnStateChange; } - - // Service Methods - protected override void OnStart(object Author) + protected override void Start() { + if (PlayOnStart) + { + CurrentState = Game.State; + } + base.Start(); } - protected override void OnEnd(object Author) + private void OnDisable() { - + Game.OnStateChanged -= OnStateChange; } - // StateService Methods - protected override DefaulMusicLayer DefaultState() + // CompositManager Methods + protected override bool CompairStates(GlobalEnum State_A, GlobalEnum State_B) { - return DefaulMusicLayer.Default; + return State_A == State_B; } - public override bool CanSwitch(DefaulMusicLayer A, DefaulMusicLayer B) + + // Functions + private void OnStateChange(int stateIndex) { - if (A == B) + if (IsValidState(stateIndex)) { - return false; + PlayState(stateIndex); } - return true; } - protected override bool CanResetforNewWorld(World NewWorld) - { - return false; - } - } - } \ No newline at end of file diff --git a/Runtime/ReadySet/Managers/SoundManager.cs b/Runtime/ReadySet/Managers/SoundManager.cs index a78a636..531e585 100644 --- a/Runtime/ReadySet/Managers/SoundManager.cs +++ b/Runtime/ReadySet/Managers/SoundManager.cs @@ -6,8 +6,9 @@ namespace RealMethod public sealed class SoundManager : AudioManager { // AudioManager Methods - protected override void InitiateService(Service service) + protected override void ResolveService(Service service, bool active) { + base.ResolveService(service, active); } } } \ No newline at end of file From 2d0b36120065fe8a091f058c68cf4575efb28976 Mon Sep 17 00:00:00 2001 From: Alijimpa Date: Wed, 8 Apr 2026 14:26:31 +0330 Subject: [PATCH 094/204] Fix GlobalEnum Refine Default State --- Editor/Core/Drawers/GlobalEnumDrawer.cs | 34 +++++++++---------- .../ScriptTemplates/AudioManagerTemplater.txt | 3 +- .../ProjectSetting/ProjectSettingAsset.cs | 2 +- 3 files changed, 19 insertions(+), 20 deletions(-) diff --git a/Editor/Core/Drawers/GlobalEnumDrawer.cs b/Editor/Core/Drawers/GlobalEnumDrawer.cs index a163ff2..9c21d5b 100644 --- a/Editor/Core/Drawers/GlobalEnumDrawer.cs +++ b/Editor/Core/Drawers/GlobalEnumDrawer.cs @@ -6,36 +6,34 @@ namespace RealMethod.Editor [CustomPropertyDrawer(typeof(GlobalEnum))] public class GlobalEnumDrawer : PropertyDrawer { - private SerializedProperty MyParam = null; public override void OnGUI(Rect position, SerializedProperty property, GUIContent label) { - if (MyParam == null) - { - MyParam = property.FindPropertyRelative("Value"); - } - int index = MyParam.intValue; - if (RM_Editor.TryGetSettingAsset(out ProjectSettingAsset Setting)) + SerializedProperty valueProp = property.FindPropertyRelative("Value"); + int index = valueProp.intValue; + + if (RM_Editor.TryGetSettingAsset(out ProjectSettingAsset setting)) { - string[] names = Setting.Status.ToArray(); - if (index < names.Length && index >= 0) + string[] names = setting.Status.ToArray(); + + if (index >= 0 && index < names.Length) { int newIndex = EditorGUI.Popup(position, label.text, index, names); - MyParam.intValue = newIndex; + valueProp.intValue = newIndex; } else { - Color prevColor = GUI.color; - GUI.color = Color.red; // light blue - EditorGUI.LabelField(position, $"{label.text} [{index}]: Not Define!"); - GUI.color = prevColor; + Color prev = GUI.color; + GUI.color = Color.red; + EditorGUI.LabelField(position, $"{label.text} [{index}]: Not Defined!"); + GUI.color = prev; } } else { - Color prevColor = GUI.color; - GUI.color = Color.yellow; // light blue - EditorGUI.LabelField(position, $"{label.text} [{index}]: Can't load RealMethod ProjectSettingAsset."); - GUI.color = prevColor; + Color prev = GUI.color; + GUI.color = Color.yellow; + EditorGUI.LabelField(position, $"{label.text} [{index}]: Can't load ProjectSettingAsset."); + GUI.color = prev; } } } diff --git a/Reservoir/ScriptTemplates/AudioManagerTemplater.txt b/Reservoir/ScriptTemplates/AudioManagerTemplater.txt index c2c8b41..b6cc999 100644 --- a/Reservoir/ScriptTemplates/AudioManagerTemplater.txt +++ b/Reservoir/ScriptTemplates/AudioManagerTemplater.txt @@ -3,7 +3,8 @@ using RealMethod; public class #SCRIPTNAME# : AudioManager { // AudioManager Methods - protected override void InitiateService(Service service) + protected override void ResolveService(Service service, bool active) { + base.ResolveService(service, active); } } diff --git a/Runtime/Core/ProjectSetting/ProjectSettingAsset.cs b/Runtime/Core/ProjectSetting/ProjectSettingAsset.cs index 4165f34..16598c5 100644 --- a/Runtime/Core/ProjectSetting/ProjectSettingAsset.cs +++ b/Runtime/Core/ProjectSetting/ProjectSettingAsset.cs @@ -84,7 +84,7 @@ public string GetFolderPath(ProjectSettingAsset settingAsset) public IReadOnlyList FolderStructure => folderStructure; [Header("GameStatus")] [ReadOnly] - public List Status = new List(4) { "Menu", "Playing", "Pause", "GameOver" }; + public List Status = new List(5) { "Default", "Menu", "Playing", "Pause", "GameOver" }; [Header("CompileGuard")] [SerializeField, ReadOnly] private string[] Rules; From f012753804ad10e1c4af36b40742178ee22b9252 Mon Sep 17 00:00:00 2001 From: Alijimpa Date: Wed, 8 Apr 2026 22:36:24 +0330 Subject: [PATCH 095/204] Refine CompileGuard system --- Editor/Core/InitializeOnLoad/CompileGuard.cs | 86 ++++++++++++++----- .../InitializeOnLoad/Rules/CloneAssetsRule.cs | 44 ++++++++++ .../Rules/CloneAssetsRule.cs.meta | 2 + .../Rules/ConfigAssetsRule.cs | 18 +++- .../InitializeOnLoad/Rules/ServiceRule.cs | 18 ++-- .../ScriptTemplates/CompileRuleTemplate.txt | 22 +++-- 6 files changed, 153 insertions(+), 37 deletions(-) create mode 100644 Editor/Core/InitializeOnLoad/Rules/CloneAssetsRule.cs create mode 100644 Editor/Core/InitializeOnLoad/Rules/CloneAssetsRule.cs.meta diff --git a/Editor/Core/InitializeOnLoad/CompileGuard.cs b/Editor/Core/InitializeOnLoad/CompileGuard.cs index d577ad7..62a21ea 100644 --- a/Editor/Core/InitializeOnLoad/CompileGuard.cs +++ b/Editor/Core/InitializeOnLoad/CompileGuard.cs @@ -19,22 +19,38 @@ public abstract class CompileRule /// public enum RuleExecutionMode { - /// - /// Rule is disabled and will never be executed. - /// - Disable = 0, /// /// Rule runs after Unity finishes compiling scripts. /// Triggered by . /// Useful for validating code structure or assets after compilation. /// - AfterCompilation = 1, + AfterCompilation = 0, /// /// Rule runs on the editor update loop after the editor loads. /// Triggered using . /// Useful for checks that should occur once the editor is ready. /// - EditorStartup = 2 + EditorStartup = 1, + /// + /// Rule runs after the editor has fully returned to Edit Mode. + /// The editor is back to its normal editing state. + /// + EnteredEditMode = 2, + /// + /// Rule runs when the editor is about to leave Edit Mode and start entering Play Mode. + /// This happens before Play Mode is fully active. + /// + ExitingEditMode = 3, + /// + /// Rule runs after the editor has fully entered Play Mode. + /// Game logic is now running. + /// + EnteredPlayMode = 4, + /// + /// Rule runs when the editor is about to stop Play Mode and return to Edit Mode. + /// Game execution is shutting down. + /// + ExitingPlayMode = 5, } public CompileRule() @@ -49,13 +65,11 @@ public CompileRule() /// protected abstract void Initilized(); /// - /// Defines when this rule should run during the editor lifecycle. - /// The returned determines whether - /// CompileGuard triggers this rule during: - /// - script compilation (CompilationPipeline), or - /// - editor updates (EditorApplication). + /// Called befor rule check, + /// Once per event mode /// - public abstract RuleExecutionMode GetRuleMode(); + /// Represent whitch mode started + public abstract void OnStart(RuleExecutionMode mode); /// /// Returns the base type that this rule should scan for. /// CompileGuard will call for every type in the project @@ -64,16 +78,22 @@ public CompileRule() /// /// A Type that all target classes must derive from. /// - public abstract Type GetBaseType(); + public abstract Type GetSubClass(RuleExecutionMode mode); /// /// Called when CompileGuard finds a type that inherits from the rule's base type. /// Implement validation logic here. This method is invoked automatically for each /// matching type during the selected rule mode. /// /// - /// The discovered type that matches . + /// The discovered type that matches . /// public abstract void OnCheck(Type type); + /// + /// Called after rule checkd, + /// Once per event mode + /// + /// Represent whitch mode started + public abstract void OnEnd(RuleExecutionMode mode); } @@ -101,12 +121,13 @@ private static ProjectSettingAsset ProjectSetting } } private static System.Reflection.Assembly[] Assemblies; - private static CompileRule[] Ruls; + private static CompileRule[] Rules; - public static Type[] DefaultRuls = new Type[2] { + public static Type[] DefaultRuls = new Type[3] { // Array of ruls to that should be run always for RealMethod typeof(ConfigAssetsRule), typeof(ServiceRule), + typeof(CloneAssetsRule), }; @@ -114,6 +135,7 @@ static CompileGuard() { CompilationPipeline.compilationFinished += OnCompilationFinished; EditorApplication.delayCall += OnEditorUpdated; + EditorApplication.playModeStateChanged += OnPlayModeChanged; } private static void OnCompilationFinished(object obj) @@ -124,18 +146,23 @@ private static void OnEditorUpdated() { CheckRuls(CompileRule.RuleExecutionMode.EditorStartup); } + private static void OnPlayModeChanged(PlayModeStateChange state) + { + int index = (int)state + 2; + CheckRuls((CompileRule.RuleExecutionMode)index); + } private static void CheckRuls(CompileRule.RuleExecutionMode mode) { if (ProjectSetting == null) return; - if (Ruls == null) + if (Rules == null) { Type[] RulsClass = ProjectSetting.GetCompileRules(); if (RulsClass == null) return; - Ruls = new CompileRule[RulsClass.Length]; + Rules = new CompileRule[RulsClass.Length]; for (int i = 0; i < RulsClass.Length; i++) { if (RulsClass[i] == null) @@ -145,7 +172,7 @@ private static void CheckRuls(CompileRule.RuleExecutionMode mode) { try { - Ruls[i] = (CompileRule)Activator.CreateInstance(RulsClass[i]); + Rules[i] = (CompileRule)Activator.CreateInstance(RulsClass[i]); } catch (Exception ex) { @@ -166,6 +193,13 @@ private static void CheckRuls(CompileRule.RuleExecutionMode mode) Assemblies = AppDomain.CurrentDomain.GetAssemblies(); } + // Start + foreach (var rule in Rules) + { + rule.OnStart(mode); + } + + // Checking Type[] types; foreach (var assembly in Assemblies) { @@ -180,23 +214,29 @@ private static void CheckRuls(CompileRule.RuleExecutionMode mode) foreach (var type in types) { - if (Ruls == null) + if (Rules == null) return; - foreach (var rule in Ruls) + foreach (var rule in Rules) { if (rule == null) continue; - if (rule.GetRuleMode() != mode) + if (rule.GetSubClass(mode) == null) continue; - if (type.IsSubclassOf(rule.GetBaseType())) + if (type.IsSubclassOf(rule.GetSubClass(mode))) { rule.OnCheck(type); } } } } + + // End + foreach (var rule in Rules) + { + rule.OnEnd(mode); + } } } diff --git a/Editor/Core/InitializeOnLoad/Rules/CloneAssetsRule.cs b/Editor/Core/InitializeOnLoad/Rules/CloneAssetsRule.cs new file mode 100644 index 0000000..1ec4e2e --- /dev/null +++ b/Editor/Core/InitializeOnLoad/Rules/CloneAssetsRule.cs @@ -0,0 +1,44 @@ +using System; +using UnityEditor; +using UnityEngine; + +namespace RealMethod.Editor +{ + public class CloneAssetsRule : CompileRule + { + protected override void Initilized() + { + + } + public override RuleExecutionMode GetRuleMode() + { + return RuleExecutionMode.EnteredPlayMode; + } + public override void OnStart(RuleExecutionMode mode) + { + } + public override Type GetBaseType() + { + return null; + //return typeof(CloneAsset); + } + public override void OnCheck(Type type) + { + var assets = Resources.FindObjectsOfTypeAll(); + + foreach (var asset in assets) + { + if (AssetDatabase.Contains(asset)) + { + Debug.LogWarning( + $"PrimitiveAsset '{asset.name}' is used directly in Play Mode. " + + $"A runtime instance or clone should be used instead.", + asset); + } + } + } + public override void OnEnd(RuleExecutionMode mode) + { + } + } +} \ No newline at end of file diff --git a/Editor/Core/InitializeOnLoad/Rules/CloneAssetsRule.cs.meta b/Editor/Core/InitializeOnLoad/Rules/CloneAssetsRule.cs.meta new file mode 100644 index 0000000..1df2d7f --- /dev/null +++ b/Editor/Core/InitializeOnLoad/Rules/CloneAssetsRule.cs.meta @@ -0,0 +1,2 @@ +fileFormatVersion: 2 +guid: afe89030ce51ae1479937042bf16b9f4 \ No newline at end of file diff --git a/Editor/Core/InitializeOnLoad/Rules/ConfigAssetsRule.cs b/Editor/Core/InitializeOnLoad/Rules/ConfigAssetsRule.cs index 06b5cd5..9be1151 100644 --- a/Editor/Core/InitializeOnLoad/Rules/ConfigAssetsRule.cs +++ b/Editor/Core/InitializeOnLoad/Rules/ConfigAssetsRule.cs @@ -12,13 +12,19 @@ public class ConfigAssetsRule : CompileRule protected override void Initilized() { } - public override RuleExecutionMode GetRuleMode() + public override void OnStart(RuleExecutionMode mode) { - return RuleExecutionMode.EditorStartup; } - public override Type GetBaseType() + public override Type GetSubClass(RuleExecutionMode mode) { - return typeof(ConfigAsset); + if (mode == RuleExecutionMode.EditorStartup) + { + return typeof(ConfigAsset); + } + else + { + return null; + } } public override void OnCheck(Type type) { @@ -43,6 +49,9 @@ public override void OnCheck(Type type) Debug.LogError($"❌ '{type.Name}' public method '{m.Name}' modifies state — only pure getter/return methods are allowed in Config-derived classes."); } } + public override void OnEnd(RuleExecutionMode mode) + { + } // Functions @@ -84,5 +93,6 @@ private bool ViolatesPureMethodRules(MethodInfo method) return false; } + } } \ No newline at end of file diff --git a/Editor/Core/InitializeOnLoad/Rules/ServiceRule.cs b/Editor/Core/InitializeOnLoad/Rules/ServiceRule.cs index 1471934..c5cf574 100644 --- a/Editor/Core/InitializeOnLoad/Rules/ServiceRule.cs +++ b/Editor/Core/InitializeOnLoad/Rules/ServiceRule.cs @@ -11,13 +11,19 @@ protected override void Initilized() { } - public override RuleExecutionMode GetRuleMode() + public override void OnStart(RuleExecutionMode mode) { - return RuleExecutionMode.AfterCompilation; } - public override Type GetBaseType() + public override Type GetSubClass(RuleExecutionMode mode) { - return typeof(Service); + if (mode == RuleExecutionMode.AfterCompilation) + { + return typeof(Service); + } + else + { + return null; + } } public override void OnCheck(Type type) { @@ -44,6 +50,8 @@ public override void OnCheck(Type type) } } } - + public override void OnEnd(RuleExecutionMode mode) + { + } } } \ No newline at end of file diff --git a/Reservoir/ScriptTemplates/CompileRuleTemplate.txt b/Reservoir/ScriptTemplates/CompileRuleTemplate.txt index 6584032..6f59bc4 100644 --- a/Reservoir/ScriptTemplates/CompileRuleTemplate.txt +++ b/Reservoir/ScriptTemplates/CompileRuleTemplate.txt @@ -9,18 +9,30 @@ public class #SCRIPTNAME# : CompileRule { // Called right after Construct } - public override RuleExecutionMode GetRuleMode() + public override void OnStart(RuleExecutionMode mode) { - // Defines when this rule should be executed - return RuleExecutionMode.AfterCompilation; + // Called befor checking stage } - public override Type GetBaseType() + public override Type GetSubClass(RuleExecutionMode mode) { // A Type that all target classes must derive from - return typeof(MonoBehaviour); + if (mode == RuleExecutionMode.AfterCompilation) + { + return typeof(MonoBehaviour); + } + else + { + // Skip other mode + return null; + } } public override void OnCheck(Type type) { // Called when CompileGuard finds a type that inherits from the rule's base type. } + public override void OnEnd(RuleExecutionMode mode) + { + // Called after cheking stage + } + } From bb74d9b0d6d8d2e799923849a97e0c4a958815f4 Mon Sep 17 00:00:00 2001 From: Alijimpa Date: Wed, 15 Apr 2026 14:29:05 +0330 Subject: [PATCH 096/204] Refine Primitive Asset Editor Events --- Runtime/Core/Definitions/Assets.cs | 81 ++++++++++--------- .../ProjectSetting/ProjectSettingAsset.cs | 14 ++-- Runtime/Pattern/Assets/PoolAsset.cs | 18 ++++- Runtime/Pattern/Assets/ResourcAsset.cs | 15 +++- Runtime/Pattern/Managers/DataManager.cs | 5 -- Runtime/ReadySet/Managers/TaskManager.cs | 33 +++++--- .../ReadySet/Presets/PoolAsset/AudioPool.cs | 7 +- .../Presets/PoolAsset/ParticlePool.cs | 12 ++- .../ReadySet/Presets/PoolAsset/PrefabPool.cs | 9 +-- Runtime/ReadySet/Services/DebugService.cs | 11 ++- Runtime/Toolkit/Ability/AbilityAsset.cs | 18 +---- .../Toolkit/PCG/Assets/PCGGenerationAsset.cs | 16 +++- Runtime/Toolkit/RPG/StatSystem/StatProfile.cs | 7 -- .../Toolkit/RPG/StatSystem/StatSaveFile.cs | 9 +-- Runtime/Toolkit/Tutorial/TutorialSaveFile.cs | 16 +++- Runtime/Toolkit/Upgrade/UpgradeSaveFile.cs | 17 +++- 16 files changed, 167 insertions(+), 121 deletions(-) diff --git a/Runtime/Core/Definitions/Assets.cs b/Runtime/Core/Definitions/Assets.cs index 8387b86..7b2139d 100644 --- a/Runtime/Core/Definitions/Assets.cs +++ b/Runtime/Core/Definitions/Assets.cs @@ -9,7 +9,12 @@ public interface IAsset { PrimitiveAsset GetAsset(); } - // PrimitiveAsset: is a ScriptableObject with some functions & IAsset interface + + /// + /// Base class for all custom asset types in the system. + /// Provides shared functionality and common rules for assets derived from ScriptableObject, + /// such as cloning, instancing, or direct usage depending on the derived asset type. + /// public abstract class PrimitiveAsset : ScriptableObject, IAsset, ISpawn, ISpawnWithAuthor { // Implement IAsset Interface @@ -57,33 +62,34 @@ public bool IsProjectAsset() #if UNITY_EDITOR - [InitializeOnEnterPlayMode] // Runs when entering Play Mode in Editor - private static void EditorPlayModeInit() - { - var assets = Resources.FindObjectsOfTypeAll(); - foreach (var asset in assets) - { - if (asset.IsProjectAsset()) - { - asset.OnEditorPlay(); - } - } - } - - public virtual void OnEditorPlay() + /// + /// Returns whether Reset() should be automatically called for the given + /// PlayModeStateChange. If this method returns true, Unity's Reset() method + /// on this ScriptableObject will be invoked for that state. + /// + /// The current play mode state change. + public virtual bool AutoReset(PlayModeStateChange state) { - Debug.Log($"[{GetType()}] -> {name} OnEditorPlay called."); + return false; } #endif } - // DataAsset: is just a PrimitiveAsset + /// + /// A standard asset used to store data. + /// Developers can create and use these assets directly in the project + /// and access the functionality provided by PrimitiveAsset. + /// public abstract class DataAsset : PrimitiveAsset { } - // TemplateAsset: is a PrimitiveAsset that you can't create new at runtime & Should Use With Clone - public abstract class TemplateAsset : PrimitiveAsset + /// + /// Represents an asset used only as a clone. + /// This asset cannot be used directly or instantiated normally. + /// Its purpose is to generate clones that will be used instead of the original asset. + /// + public abstract class CloneAsset : PrimitiveAsset { protected virtual void OnEnable() { @@ -91,22 +97,19 @@ protected virtual void OnEnable() { if (!IsProjectAsset()) { - Debug.LogError($"TemplateAsset Can't Create New Instance at Runtime, NewFile Removed!"); + Debug.LogError($"CloneAsset Can't Create New Instance at Runtime, NewFile Removed!"); Destroy(this); return; } } } - -#if UNITY_EDITOR - public override void OnEditorPlay() - { - - } -#endif } - // FileAsset: is a PrimitiveAsset that you can't clone at runtime - public abstract class FileAsset : PrimitiveAsset + /// + /// Represents an asset that defines how to create new instances. + /// The asset itself cannot be used directly or cloned. + /// Instead, the system creates new independent instances based on this asset's data. + /// + public abstract class InstanceAsset : PrimitiveAsset { protected virtual void OnEnable() { @@ -118,7 +121,11 @@ protected virtual void OnEnable() } } } - // UniqueAsset: is a PrimitiveAsset that you can't clone or create new at runtime + /// + /// Represents a unique shared asset in the project. + /// Developers must use the asset directly and cannot clone it + /// or create new instances from it. + /// public abstract class UniqueAsset : PrimitiveAsset { protected virtual void OnEnable() @@ -136,15 +143,13 @@ protected virtual void OnEnable() return; } } - -#if UNITY_EDITOR - public override void OnEditorPlay() - { - - } -#endif } - // ConfigAsset: is a UniqueAsset that you can't decelar modifier variable or method , all of things should be readonly + /// + /// A specialized UniqueAsset used for global configuration. + /// The asset is intended to be read-only at runtime, + /// and developers should not add mutable fields or methods + /// that modify its configuration values. + /// public abstract class ConfigAsset : UniqueAsset { diff --git a/Runtime/Core/ProjectSetting/ProjectSettingAsset.cs b/Runtime/Core/ProjectSetting/ProjectSettingAsset.cs index 16598c5..b49a0bf 100644 --- a/Runtime/Core/ProjectSetting/ProjectSettingAsset.cs +++ b/Runtime/Core/ProjectSetting/ProjectSettingAsset.cs @@ -87,7 +87,9 @@ public string GetFolderPath(ProjectSettingAsset settingAsset) public List Status = new List(5) { "Default", "Menu", "Playing", "Pause", "GameOver" }; [Header("CompileGuard")] [SerializeField, ReadOnly] - private string[] Rules; + private bool Compiling = true; // <-- this name must match + [SerializeField, ReadOnly] + private string[] Rules = null; // <-- this name must match #endif // Unity Methods @@ -107,7 +109,6 @@ protected virtual void Reset() } - // Public Functions public Type GetGameType() { @@ -131,9 +132,6 @@ public static ProjectSettingAsset Load() { return UnityEditor.AssetDatabase.LoadAssetAtPath(Path); } - public override void OnEditorPlay() - { - } public GameObject GetPrefab_2() { return GamePrefab_2; @@ -155,6 +153,10 @@ public string GetFolderPathByType(AssetFormat identity) } public FolderAddress GetFolderAddressByIndex(int index) => folderStructure[index]; public void SetFolderAddressPath(int index, string value) => folderStructure[index].AssetPath = value; + public bool CanCompile() + { + return Compiling; + } public Type[] GetCompileRules() { List result = new List(); @@ -172,8 +174,6 @@ public GameObject GetPrefab_3() return GamePrefab_3; } #endif - - } diff --git a/Runtime/Pattern/Assets/PoolAsset.cs b/Runtime/Pattern/Assets/PoolAsset.cs index 008614e..c02e243 100644 --- a/Runtime/Pattern/Assets/PoolAsset.cs +++ b/Runtime/Pattern/Assets/PoolAsset.cs @@ -2,6 +2,10 @@ using System.Collections.Generic; using UnityEngine; +#if UNITY_EDITOR +using UnityEditor; +#endif + namespace RealMethod { public class PoolComponent : MonoBehaviour @@ -172,13 +176,19 @@ private void CallPoolBackEvent(T Target, IEnumerator Corotine) protected abstract T CreateObject(); protected abstract IEnumerator PostProcess(T Comp); + protected virtual void Reset() + { + Prewarmed = false; + } + #if UNITY_EDITOR - // Base DataAsset Methods - public override void OnEditorPlay() + public override bool AutoReset(PlayModeStateChange state) { - //base.OnEditorPlay(); - Prewarmed = false; + if (state == PlayModeStateChange.ExitingPlayMode) + return true; + + return base.AutoReset(state); } #endif } diff --git a/Runtime/Pattern/Assets/ResourcAsset.cs b/Runtime/Pattern/Assets/ResourcAsset.cs index a897ef5..529d64a 100644 --- a/Runtime/Pattern/Assets/ResourcAsset.cs +++ b/Runtime/Pattern/Assets/ResourcAsset.cs @@ -2,6 +2,10 @@ using System.Threading.Tasks; using UnityEngine; +#if UNITY_EDITOR +using UnityEditor; +#endif + namespace RealMethod { public abstract class ResourcAsset : DataAsset @@ -144,11 +148,18 @@ private IEnumerator LoadRoutine(System.Action result) } -#if UNITY_EDITOR - public override void OnEditorPlay() + private void Reset() { Asset = null; } + +#if UNITY_EDITOR + public override bool AutoReset(PlayModeStateChange state) + { + if (PlayModeStateChange.ExitingPlayMode == state) + return true; + return base.AutoReset(state); + } #endif } diff --git a/Runtime/Pattern/Managers/DataManager.cs b/Runtime/Pattern/Managers/DataManager.cs index e7e449a..107d763 100644 --- a/Runtime/Pattern/Managers/DataManager.cs +++ b/Runtime/Pattern/Managers/DataManager.cs @@ -357,11 +357,6 @@ void IDataFile.FileRemoved() #if UNITY_EDITOR - [ContextMenu("ResetToDefault")] - private void Editor_BacktoDefault() - { - OnEditorPlay(); - } [ContextMenu("Save")] private void Editor_SaveSelf() { diff --git a/Runtime/ReadySet/Managers/TaskManager.cs b/Runtime/ReadySet/Managers/TaskManager.cs index f8c0ae1..f5e3933 100644 --- a/Runtime/ReadySet/Managers/TaskManager.cs +++ b/Runtime/ReadySet/Managers/TaskManager.cs @@ -1,5 +1,9 @@ using UnityEngine; +#if UNITY_EDITOR +using UnityEditor; +#endif + namespace RealMethod { public delegate void TaskCallback(bool enable); @@ -80,15 +84,22 @@ void ITask.Disable(Object author) onTaskStatus?.Invoke(false); } + protected virtual void Reset() + { + IsEnable = false; + } + // Abstract Methods protected abstract void OnTaskEnable(Object author); protected abstract void OnTaskUpdate(float delta); protected abstract void OnTaskDisable(Object author); #if UNITY_EDITOR - public override void OnEditorPlay() + public override bool AutoReset(PlayModeStateChange state) { - IsEnable = false; + if (state == PlayModeStateChange.ExitingPlayMode) + return true; + return base.AutoReset(state); } #endif } @@ -214,6 +225,7 @@ void IBehaviour.Clear() isValidated = false; Author = null; } + // Implement IBehaviourCycle Interface public bool IsInfinit => infinit; public float RemainingTime => residuary; @@ -238,6 +250,7 @@ void IBehaviourCycle.Start(float overrideTime) Debug.LogError("First You Sould Initiate Behaviour"); } } + // Implement IBehaviourAction Interface public bool IsPaused => !isRunning; void IBehaviourAction.Pause() @@ -293,6 +306,13 @@ protected virtual bool CanUpdate() } + // Unity Methods + protected override void Reset() + { + base.Reset(); + ResetTaskValues(); + } + // Abstract Methods protected abstract void OnInitiate(); protected abstract void OnBegin(); @@ -302,15 +322,6 @@ protected virtual bool CanUpdate() protected abstract void OnReset(); protected abstract void OnEnd(); -#if UNITY_EDITOR - public sealed override void OnEditorPlay() - { - base.OnEditorPlay(); - ResetTaskValues(); - } -#endif - - } } \ No newline at end of file diff --git a/Runtime/ReadySet/Presets/PoolAsset/AudioPool.cs b/Runtime/ReadySet/Presets/PoolAsset/AudioPool.cs index b5be71a..8782e88 100644 --- a/Runtime/ReadySet/Presets/PoolAsset/AudioPool.cs +++ b/Runtime/ReadySet/Presets/PoolAsset/AudioPool.cs @@ -192,14 +192,11 @@ protected override IEnumerator PostProcess(AudioSource Comp) return PoolBack(Comp); } -#if UNITY_EDITOR - // Base DataAsset Methods - public override void OnEditorPlay() + protected override void Reset() { - base.OnEditorPlay(); + base.Reset(); UseCacheData = 0; } -#endif // IEnumerator private IEnumerator PoolBack(AudioSource source) diff --git a/Runtime/ReadySet/Presets/PoolAsset/ParticlePool.cs b/Runtime/ReadySet/Presets/PoolAsset/ParticlePool.cs index 65ff9d4..d2adf7b 100644 --- a/Runtime/ReadySet/Presets/PoolAsset/ParticlePool.cs +++ b/Runtime/ReadySet/Presets/PoolAsset/ParticlePool.cs @@ -6,7 +6,7 @@ namespace RealMethod { [CreateAssetMenu(fileName = "ParticlePool", menuName = "RealMethod/Pool/ParticlePool", order = 1)] - public sealed class ParticlePool : PoolAsset , IPoolSpawner + public sealed class ParticlePool : PoolAsset, IPoolSpawner { [Header("Setting")] [SerializeField] @@ -15,7 +15,7 @@ public sealed class ParticlePool : PoolAsset , IPoolSpawner OnSpawned; - + // Private Variable private byte UseCacheData = 0; //0:NoCashing 1:CachePosition 2:CachePosition&Rotation 3:CacheTransform @@ -94,14 +94,12 @@ protected override IEnumerator PostProcess(ParticleSystem Comp) return PoolBack(Comp); } -#if UNITY_EDITOR - // Base DataAsset Methods - public override void OnEditorPlay() + + protected override void Reset() { - base.OnEditorPlay(); + base.Reset(); UseCacheData = 0; } -#endif // IEnumerator diff --git a/Runtime/ReadySet/Presets/PoolAsset/PrefabPool.cs b/Runtime/ReadySet/Presets/PoolAsset/PrefabPool.cs index 79c25ec..bde10e6 100644 --- a/Runtime/ReadySet/Presets/PoolAsset/PrefabPool.cs +++ b/Runtime/ReadySet/Presets/PoolAsset/PrefabPool.cs @@ -149,15 +149,14 @@ protected override IEnumerator PostProcess(Transform Comp) return autoDespawn ? PoolBack(Comp) : null; } -#if UNITY_EDITOR - // Base DataAsset Methods - public override void OnEditorPlay() + + protected override void Reset() { - base.OnEditorPlay(); + base.Reset(); UseCacheData = 0; CacheDuration = 0; } -#endif + // IEnumerator private IEnumerator PoolBack(Transform Transf) { diff --git a/Runtime/ReadySet/Services/DebugService.cs b/Runtime/ReadySet/Services/DebugService.cs index 81456bf..bbaf10f 100644 --- a/Runtime/ReadySet/Services/DebugService.cs +++ b/Runtime/ReadySet/Services/DebugService.cs @@ -20,7 +20,14 @@ void ILogHandler.LogFormat(LogType logType, Object context, string format, param } // Still send message to Unity console - defaultLogHandler.LogFormat(logType, context, format, args); + if (defaultLogHandler != null) + { + defaultLogHandler.LogFormat(logType, context, format, args); + } + else + { + Debug.unityLogger.logHandler.LogFormat(logType, context, format, args); + } } void ILogHandler.LogException(System.Exception exception, Object context) { @@ -47,7 +54,7 @@ protected override void OnWorldChanging(World Previous, World New) } protected override void OnEnd(object Author) { - if(Printer != null) + if (Printer != null) { Printer.Clear(); } diff --git a/Runtime/Toolkit/Ability/AbilityAsset.cs b/Runtime/Toolkit/Ability/AbilityAsset.cs index eb6e28e..db3acf5 100644 --- a/Runtime/Toolkit/Ability/AbilityAsset.cs +++ b/Runtime/Toolkit/Ability/AbilityAsset.cs @@ -1,9 +1,10 @@ using System.Collections.Generic; using UnityEngine; + namespace RealMethod { - public abstract class AbilityAsset : TemplateAsset, IAbility, ICooldown + public abstract class AbilityAsset : CloneAsset, IAbility, ICooldown { private float lastUsedTime = -Mathf.Infinity; @@ -59,13 +60,6 @@ public void ResetCooldown() protected abstract float GetCooldown(); protected abstract IAbilityEffect[] GetEffects(); protected abstract bool Prerequisite(GameObject user); - -#if UNITY_EDITOR - public override void OnEditorPlay() - { - lastUsedTime = -Mathf.Infinity; - } -#endif } public abstract class AbilityEffectAsset : AbilityAsset { @@ -120,13 +114,5 @@ private System.Type GetClassType(string classname) } return null; } - -#if UNITY_EDITOR - public override void OnEditorPlay() - { - base.OnEditorPlay(); - myEffects = null; - } -#endif } } \ No newline at end of file diff --git a/Runtime/Toolkit/PCG/Assets/PCGGenerationAsset.cs b/Runtime/Toolkit/PCG/Assets/PCGGenerationAsset.cs index 4b38c99..16594da 100644 --- a/Runtime/Toolkit/PCG/Assets/PCGGenerationAsset.cs +++ b/Runtime/Toolkit/PCG/Assets/PCGGenerationAsset.cs @@ -3,6 +3,10 @@ using System.Linq; using UnityEngine; +#if UNITY_EDITOR +using UnityEditor; +#endif + namespace RealMethod { [Serializable] @@ -324,11 +328,19 @@ private void PrintGuide() Guide += MyLine + Environment.NewLine; } } -#if UNITY_EDITOR - public override void OnEditorPlay() + + private void Reset() { PrintGuide(); } + +#if UNITY_EDITOR + public override bool AutoReset(PlayModeStateChange state) + { + if (state == PlayModeStateChange.ExitingPlayMode) + return true; + return base.AutoReset(state); + } #endif } diff --git a/Runtime/Toolkit/RPG/StatSystem/StatProfile.cs b/Runtime/Toolkit/RPG/StatSystem/StatProfile.cs index 12661a9..0139e51 100644 --- a/Runtime/Toolkit/RPG/StatSystem/StatProfile.cs +++ b/Runtime/Toolkit/RPG/StatSystem/StatProfile.cs @@ -277,13 +277,6 @@ private void CheckStorage() } } - -#if UNITY_EDITOR - public override void OnEditorPlay() - { - Clear(); - } -#endif } } \ No newline at end of file diff --git a/Runtime/Toolkit/RPG/StatSystem/StatSaveFile.cs b/Runtime/Toolkit/RPG/StatSystem/StatSaveFile.cs index 21e5632..85d4f1e 100644 --- a/Runtime/Toolkit/RPG/StatSystem/StatSaveFile.cs +++ b/Runtime/Toolkit/RPG/StatSystem/StatSaveFile.cs @@ -18,7 +18,7 @@ public class StatSaveFile : SaveFile, IStatStorage public List Mins = new List(5); public List Maxs = new List(5); - + // SaveFile Methods protected override void OnStable(DataManager manager) { } @@ -53,7 +53,6 @@ protected override void OnDeleted() } } - // Implement IStorage Interface void IStorage.StorageCreated(Object author) { @@ -97,14 +96,14 @@ bool IStatStorage.TryLoadStats(StatData data) return false; } -#if UNITY_EDITOR - public override void OnEditorPlay() + + // Unity Event + private void Reset() { Names.Clear(); BaseValue.Clear(); Mins.Clear(); Maxs.Clear(); } -#endif } } \ No newline at end of file diff --git a/Runtime/Toolkit/Tutorial/TutorialSaveFile.cs b/Runtime/Toolkit/Tutorial/TutorialSaveFile.cs index 96e5061..a7400a0 100644 --- a/Runtime/Toolkit/Tutorial/TutorialSaveFile.cs +++ b/Runtime/Toolkit/Tutorial/TutorialSaveFile.cs @@ -2,6 +2,10 @@ using System.Linq; using UnityEngine; +#if UNITY_EDITOR +using UnityEditor; +#endif + namespace RealMethod { [CreateAssetMenu(fileName = "TutorialSaveFile", menuName = "RealMethod/Tutorial/SaveFile", order = 1)] @@ -61,11 +65,19 @@ void IStorage.StorageClear() TutorialMessage.Clear(); } -#if UNITY_EDITOR - public override void OnEditorPlay() + + private void Reset() { TutorialMessage.Clear(); } + +#if UNITY_EDITOR + public override bool AutoReset(PlayModeStateChange state) + { + if (state == PlayModeStateChange.ExitingPlayMode) + return true; + return base.AutoReset(state); + } #endif } diff --git a/Runtime/Toolkit/Upgrade/UpgradeSaveFile.cs b/Runtime/Toolkit/Upgrade/UpgradeSaveFile.cs index 875dbcc..50c6399 100644 --- a/Runtime/Toolkit/Upgrade/UpgradeSaveFile.cs +++ b/Runtime/Toolkit/Upgrade/UpgradeSaveFile.cs @@ -2,6 +2,10 @@ using System.Linq; using UnityEngine; +#if UNITY_EDITOR +using UnityEditor; +#endif + namespace RealMethod { [CreateAssetMenu(fileName = "UpgradeSaveFile", menuName = "RealMethod/Upgrade/SaveFile", order = 1)] @@ -93,12 +97,19 @@ void IStorage.StorageClear() } -#if UNITY_EDITOR - public override void OnEditorPlay() + private void Reset() { - //base.OnEditorPlay(); ((IStorage)this).StorageClear(); } + + +#if UNITY_EDITOR + public override bool AutoReset(PlayModeStateChange state) + { + if (state == PlayModeStateChange.ExitingPlayMode) + return true; + return base.AutoReset(state); + } #endif } From 8494eab728ad3110f12dbf30ae0a6034a153d734 Mon Sep 17 00:00:00 2001 From: Alijimpa Date: Wed, 15 Apr 2026 14:29:26 +0330 Subject: [PATCH 097/204] Implement Invoke Function by name for ScriptableObjects --- Runtime/Library/Extension/ScriptableObject.cs | 28 +++++++++++++++++++ .../Extension/ScriptableObject.cs.meta | 2 ++ 2 files changed, 30 insertions(+) create mode 100644 Runtime/Library/Extension/ScriptableObject.cs create mode 100644 Runtime/Library/Extension/ScriptableObject.cs.meta diff --git a/Runtime/Library/Extension/ScriptableObject.cs b/Runtime/Library/Extension/ScriptableObject.cs new file mode 100644 index 0000000..7f026c0 --- /dev/null +++ b/Runtime/Library/Extension/ScriptableObject.cs @@ -0,0 +1,28 @@ +using System.Reflection; +using UnityEngine; + +namespace RealMethod +{ + public static class ScriptableObject_Extension + { + public static void Invoke(this ScriptableObject so, string methodName) + { + so.Invoke(methodName, null); + } + public static void Invoke(this ScriptableObject so, string methodName, object[] parameters) + { + var method = so.GetType().GetMethod(methodName, + BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic); + + if (method != null) + { + method.Invoke(so, parameters); + } + else + { + Debug.LogError($"Method '{methodName}' not found."); + } + } + + } +} \ No newline at end of file diff --git a/Runtime/Library/Extension/ScriptableObject.cs.meta b/Runtime/Library/Extension/ScriptableObject.cs.meta new file mode 100644 index 0000000..073a688 --- /dev/null +++ b/Runtime/Library/Extension/ScriptableObject.cs.meta @@ -0,0 +1,2 @@ +fileFormatVersion: 2 +guid: f1e3fbce41e63464e99c5d3a91da779c \ No newline at end of file From cd6c286e7e81b4ed2294b2af5f7be0bcf7bb6132 Mon Sep 17 00:00:00 2001 From: Alijimpa Date: Wed, 15 Apr 2026 14:30:14 +0330 Subject: [PATCH 098/204] Implement Enambing for Compileing Gaulard --- Editor/Core/ProjectSetting/ProjectSettingProvider.cs | 5 +++++ Editor/Core/ProjectSetting/Sections/CompileRule_Section.cs | 6 +++++- 2 files changed, 10 insertions(+), 1 deletion(-) diff --git a/Editor/Core/ProjectSetting/ProjectSettingProvider.cs b/Editor/Core/ProjectSetting/ProjectSettingProvider.cs index fea44d8..1174df8 100644 --- a/Editor/Core/ProjectSetting/ProjectSettingProvider.cs +++ b/Editor/Core/ProjectSetting/ProjectSettingProvider.cs @@ -108,6 +108,11 @@ public void Draw() if (!myProperty.isArray) return; + if(myProperty.arraySize < EnforceDisable) + { + myProperty.ClearArray(); + } + if(myProperty.arraySize == 0) { DefaultInitiation(); diff --git a/Editor/Core/ProjectSetting/Sections/CompileRule_Section.cs b/Editor/Core/ProjectSetting/Sections/CompileRule_Section.cs index 096e663..875b957 100644 --- a/Editor/Core/ProjectSetting/Sections/CompileRule_Section.cs +++ b/Editor/Core/ProjectSetting/Sections/CompileRule_Section.cs @@ -24,10 +24,12 @@ protected override void DefaultInitiation() myProperty.InsertArrayElementAtIndex(Index); SerializedProperty element = myProperty.GetArrayElementAtIndex(Index); element.stringValue = ruletype.AssemblyQualifiedName; + Debug.LogWarning($"====> {ruletype}"); } } } + private SerializedProperty CompilingSerialized; private ProjectSettingAsset SettingAsset; private SerializedObject projectSettings; private RuleSelector Rules; @@ -36,7 +38,6 @@ protected override void DefaultInitiation() // Implement ProjectSettingSection Methods protected override void Initialized() { - } protected override string GetTitle() { @@ -50,6 +51,7 @@ protected override void BeginRender(ProjectSettingAsset Storage) { SettingAsset = Storage; projectSettings = new SerializedObject(Storage); + CompilingSerialized = projectSettings.FindProperty("Compiling"); Rules = new RuleSelector(projectSettings.FindProperty("Rules"), "Rules"); } protected override void UpdateRender() @@ -57,6 +59,8 @@ protected override void UpdateRender() if (projectSettings == null) return; projectSettings.Update(); + CompilingSerialized.boolValue = EditorGUILayout.Toggle("Enable", CompilingSerialized.boolValue, GUILayout.Width(100)); + Rules.Draw(); if (GUI.changed) From 142d7819d4db1384b3e55a10d41d8a3aabc78f8e Mon Sep 17 00:00:00 2001 From: Alijimpa Date: Wed, 15 Apr 2026 15:45:50 +0330 Subject: [PATCH 099/204] Refine Compile Guard --- Editor/Core/InitializeOnLoad/CompileGuard.cs | 72 +++++++++---------- .../InitializeOnLoad/Rules/CloneAssetsRule.cs | 48 ++++++------- .../Rules/ConfigAssetsRule.cs | 12 +--- .../Rules/PrimitveAssetsRule.cs | 38 ++++++++++ .../Rules/PrimitveAssetsRule.cs.meta | 2 + .../InitializeOnLoad/Rules/ServiceRule.cs | 12 +--- .../ScriptTemplates/CompileRuleTemplate.txt | 17 ++--- 7 files changed, 103 insertions(+), 98 deletions(-) create mode 100644 Editor/Core/InitializeOnLoad/Rules/PrimitveAssetsRule.cs create mode 100644 Editor/Core/InitializeOnLoad/Rules/PrimitveAssetsRule.cs.meta diff --git a/Editor/Core/InitializeOnLoad/CompileGuard.cs b/Editor/Core/InitializeOnLoad/CompileGuard.cs index 62a21ea..18e2866 100644 --- a/Editor/Core/InitializeOnLoad/CompileGuard.cs +++ b/Editor/Core/InitializeOnLoad/CompileGuard.cs @@ -53,11 +53,13 @@ public enum RuleExecutionMode ExitingPlayMode = 5, } + public CompileRule() { Initilized(); } + /// /// Called automatically right after the rule is constructed. /// Use this to initialize internal data, cache values, or set up @@ -65,35 +67,25 @@ public CompileRule() /// protected abstract void Initilized(); /// - /// Called befor rule check, - /// Once per event mode - /// - /// Represent whitch mode started - public abstract void OnStart(RuleExecutionMode mode); - /// - /// Returns the base type that this rule should scan for. - /// CompileGuard will call for every type in the project - /// that inherits from the returned base type. + /// Determines whether this rule can perform a check using the specified + /// execution mode and target type. Override this method in derived classes + /// to define which modes and types the rule supports. /// + /// The rule execution mode being requested. + /// The target data type to evaluate. /// - /// A Type that all target classes must derive from. + /// True if the rule can check the given mode and type; otherwise, false. /// - public abstract Type GetSubClass(RuleExecutionMode mode); + public abstract bool CanCheck(RuleExecutionMode mode, Type type); /// /// Called when CompileGuard finds a type that inherits from the rule's base type. /// Implement validation logic here. This method is invoked automatically for each /// matching type during the selected rule mode. /// /// - /// The discovered type that matches . + /// The discovered type that matches . /// public abstract void OnCheck(Type type); - /// - /// Called after rule checkd, - /// Once per event mode - /// - /// Represent whitch mode started - public abstract void OnEnd(RuleExecutionMode mode); } @@ -122,17 +114,27 @@ private static ProjectSettingAsset ProjectSetting } private static System.Reflection.Assembly[] Assemblies; private static CompileRule[] Rules; + private static bool initialized; - public static Type[] DefaultRuls = new Type[3] { + public static readonly Type[] DefaultRuls = new Type[3] { // Array of ruls to that should be run always for RealMethod typeof(ConfigAssetsRule), typeof(ServiceRule), - typeof(CloneAssetsRule), + typeof(PrimitveAssetsRule), + }; static CompileGuard() { + if (!ProjectSetting.CanCompile()) + { + return; + } + + if (initialized) return; + initialized = true; + CompilationPipeline.compilationFinished += OnCompilationFinished; EditorApplication.delayCall += OnEditorUpdated; EditorApplication.playModeStateChanged += OnPlayModeChanged; @@ -151,16 +153,23 @@ private static void OnPlayModeChanged(PlayModeStateChange state) int index = (int)state + 2; CheckRuls((CompileRule.RuleExecutionMode)index); } + + + // Checking process private static void CheckRuls(CompileRule.RuleExecutionMode mode) { if (ProjectSetting == null) return; + if (Rules == null) { Type[] RulsClass = ProjectSetting.GetCompileRules(); if (RulsClass == null) + { + Debug.LogError($"ProjectSetting didn't have Compilerule but compileguard is enable"); return; + } Rules = new CompileRule[RulsClass.Length]; for (int i = 0; i < RulsClass.Length; i++) @@ -188,17 +197,12 @@ private static void CheckRuls(CompileRule.RuleExecutionMode mode) } } + if (Assemblies == null) { Assemblies = AppDomain.CurrentDomain.GetAssemblies(); } - // Start - foreach (var rule in Rules) - { - rule.OnStart(mode); - } - // Checking Type[] types; foreach (var assembly in Assemblies) @@ -214,29 +218,17 @@ private static void CheckRuls(CompileRule.RuleExecutionMode mode) foreach (var type in types) { - if (Rules == null) - return; - foreach (var rule in Rules) { if (rule == null) continue; - if (rule.GetSubClass(mode) == null) + if (rule.CanCheck(mode, type) == false) continue; - if (type.IsSubclassOf(rule.GetSubClass(mode))) - { - rule.OnCheck(type); - } + rule.OnCheck(type); } } } - - // End - foreach (var rule in Rules) - { - rule.OnEnd(mode); - } } } diff --git a/Editor/Core/InitializeOnLoad/Rules/CloneAssetsRule.cs b/Editor/Core/InitializeOnLoad/Rules/CloneAssetsRule.cs index 1ec4e2e..3137f4b 100644 --- a/Editor/Core/InitializeOnLoad/Rules/CloneAssetsRule.cs +++ b/Editor/Core/InitializeOnLoad/Rules/CloneAssetsRule.cs @@ -1,6 +1,4 @@ using System; -using UnityEditor; -using UnityEngine; namespace RealMethod.Editor { @@ -10,35 +8,31 @@ protected override void Initilized() { } - public override RuleExecutionMode GetRuleMode() + public override bool CanCheck(RuleExecutionMode mode, Type type) { - return RuleExecutionMode.EnteredPlayMode; - } - public override void OnStart(RuleExecutionMode mode) - { - } - public override Type GetBaseType() - { - return null; - //return typeof(CloneAsset); + return false; + // if (mode == RuleExecutionMode.AfterCompilation) + // { + // return typeof(Service); + // } + // else + // { + // return null; + // } } public override void OnCheck(Type type) { - var assets = Resources.FindObjectsOfTypeAll(); - - foreach (var asset in assets) - { - if (AssetDatabase.Contains(asset)) - { - Debug.LogWarning( - $"PrimitiveAsset '{asset.name}' is used directly in Play Mode. " + - $"A runtime instance or clone should be used instead.", - asset); - } - } - } - public override void OnEnd(RuleExecutionMode mode) - { + // var assets = Resources.FindObjectsOfTypeAll(); + // foreach (var asset in assets) + // { + // if (AssetDatabase.Contains(asset)) + // { + // Debug.LogWarning( + // $"PrimitiveAsset '{asset.name}' is used directly in Play Mode. " + + // $"A runtime instance or clone should be used instead.", + // asset); + // } + // } } } } \ No newline at end of file diff --git a/Editor/Core/InitializeOnLoad/Rules/ConfigAssetsRule.cs b/Editor/Core/InitializeOnLoad/Rules/ConfigAssetsRule.cs index 9be1151..961b5be 100644 --- a/Editor/Core/InitializeOnLoad/Rules/ConfigAssetsRule.cs +++ b/Editor/Core/InitializeOnLoad/Rules/ConfigAssetsRule.cs @@ -12,18 +12,15 @@ public class ConfigAssetsRule : CompileRule protected override void Initilized() { } - public override void OnStart(RuleExecutionMode mode) - { - } - public override Type GetSubClass(RuleExecutionMode mode) + public override bool CanCheck(RuleExecutionMode mode, Type type) { if (mode == RuleExecutionMode.EditorStartup) { - return typeof(ConfigAsset); + return type.IsSubclassOf(typeof(ConfigAsset)); } else { - return null; + return false; } } public override void OnCheck(Type type) @@ -49,9 +46,6 @@ public override void OnCheck(Type type) Debug.LogError($"❌ '{type.Name}' public method '{m.Name}' modifies state — only pure getter/return methods are allowed in Config-derived classes."); } } - public override void OnEnd(RuleExecutionMode mode) - { - } // Functions diff --git a/Editor/Core/InitializeOnLoad/Rules/PrimitveAssetsRule.cs b/Editor/Core/InitializeOnLoad/Rules/PrimitveAssetsRule.cs new file mode 100644 index 0000000..d1be6c4 --- /dev/null +++ b/Editor/Core/InitializeOnLoad/Rules/PrimitveAssetsRule.cs @@ -0,0 +1,38 @@ +using System; +using UnityEngine; +using UnityEditor; + +namespace RealMethod.Editor +{ + public class PrimitveAssetsRule : CompileRule + { + private PrimitiveAsset[] assets = null; + private int state = 0; + + protected override void Initilized() + { + assets = Resources.FindObjectsOfTypeAll(); + } + public override bool CanCheck(RuleExecutionMode mode, Type type) + { + if ((int)mode < 2) + return false; + + + state = (int)mode - 2; + return true; + } + public override void OnCheck(Type type) + { + foreach (var asset in assets) + { + if (asset.AutoReset((PlayModeStateChange)state)) + { + asset.Invoke("Reset"); + } + } + } + + + } +} \ No newline at end of file diff --git a/Editor/Core/InitializeOnLoad/Rules/PrimitveAssetsRule.cs.meta b/Editor/Core/InitializeOnLoad/Rules/PrimitveAssetsRule.cs.meta new file mode 100644 index 0000000..c7a5b4e --- /dev/null +++ b/Editor/Core/InitializeOnLoad/Rules/PrimitveAssetsRule.cs.meta @@ -0,0 +1,2 @@ +fileFormatVersion: 2 +guid: 83de4f43792a7cd4bb82451acfff8360 \ No newline at end of file diff --git a/Editor/Core/InitializeOnLoad/Rules/ServiceRule.cs b/Editor/Core/InitializeOnLoad/Rules/ServiceRule.cs index c5cf574..c7da8c9 100644 --- a/Editor/Core/InitializeOnLoad/Rules/ServiceRule.cs +++ b/Editor/Core/InitializeOnLoad/Rules/ServiceRule.cs @@ -11,18 +11,15 @@ protected override void Initilized() { } - public override void OnStart(RuleExecutionMode mode) - { - } - public override Type GetSubClass(RuleExecutionMode mode) + public override bool CanCheck(RuleExecutionMode mode, Type type) { if (mode == RuleExecutionMode.AfterCompilation) { - return typeof(Service); + return type.IsSubclassOf(typeof(Service)); } else { - return null; + return false; } } public override void OnCheck(Type type) @@ -50,8 +47,5 @@ public override void OnCheck(Type type) } } } - public override void OnEnd(RuleExecutionMode mode) - { - } } } \ No newline at end of file diff --git a/Reservoir/ScriptTemplates/CompileRuleTemplate.txt b/Reservoir/ScriptTemplates/CompileRuleTemplate.txt index 6f59bc4..8342dfa 100644 --- a/Reservoir/ScriptTemplates/CompileRuleTemplate.txt +++ b/Reservoir/ScriptTemplates/CompileRuleTemplate.txt @@ -9,30 +9,21 @@ public class #SCRIPTNAME# : CompileRule { // Called right after Construct } - public override void OnStart(RuleExecutionMode mode) - { - // Called befor checking stage - } - public override Type GetSubClass(RuleExecutionMode mode) + public override bool CanCheck(RuleExecutionMode mode, Type type) { // A Type that all target classes must derive from if (mode == RuleExecutionMode.AfterCompilation) { - return typeof(MonoBehaviour); + return type.IsSubclassOf(typeof(????)); } else { // Skip other mode - return null; + return false; } } public override void OnCheck(Type type) { - // Called when CompileGuard finds a type that inherits from the rule's base type. + // Called when CanCheck was true. } - public override void OnEnd(RuleExecutionMode mode) - { - // Called after cheking stage - } - } From 7c777ca5be3249ba4baf9cde38cfd95c98dd76db Mon Sep 17 00:00:00 2001 From: Alijimpa Date: Wed, 15 Apr 2026 19:13:31 +0330 Subject: [PATCH 100/204] Refine Assets Definitions --- Editor/Core/InitializeOnLoad/CompileGuard.cs | 13 +++ .../InitializeOnLoad/Rules/CloneAssetsRule.cs | 38 -------- .../Rules/CloneAssetsRule.cs.meta | 2 - .../Rules/ConfigAssetsRule.cs | 3 + .../Rules/PrimitveAssetsRule.cs | 35 +++++-- .../InitializeOnLoad/Rules/ServiceRule.cs | 3 + .../ScriptTemplates/CompileRuleTemplate.txt | 4 + Runtime/Core/Definitions/Assets.cs | 92 +++++++++++++++++-- .../ProjectSetting/ProjectSettingAsset.cs | 3 + Runtime/Pattern/Assets/BlackboardAsset.cs | 2 +- .../ReadySet/Essentials/DefaultGameConfig.cs | 2 +- Runtime/ReadySet/Services/SpawanService.cs | 8 +- 12 files changed, 140 insertions(+), 65 deletions(-) delete mode 100644 Editor/Core/InitializeOnLoad/Rules/CloneAssetsRule.cs delete mode 100644 Editor/Core/InitializeOnLoad/Rules/CloneAssetsRule.cs.meta diff --git a/Editor/Core/InitializeOnLoad/CompileGuard.cs b/Editor/Core/InitializeOnLoad/CompileGuard.cs index 18e2866..e1e94a8 100644 --- a/Editor/Core/InitializeOnLoad/CompileGuard.cs +++ b/Editor/Core/InitializeOnLoad/CompileGuard.cs @@ -67,6 +67,13 @@ public CompileRule() /// protected abstract void Initilized(); /// + /// Performs rule initialization for the specified execution mode. + /// This method is called once per mode before any type scanning or rule checks begin. + /// Use it to reset internal state, prepare data, or configure the rule + /// + /// The execution mode for the current validation pass. + public abstract void OnStartCheck(RuleExecutionMode mode); + /// /// Determines whether this rule can perform a check using the specified /// execution mode and target type. Override this method in derived classes /// to define which modes and types the rule supports. @@ -203,6 +210,12 @@ private static void CheckRuls(CompileRule.RuleExecutionMode mode) Assemblies = AppDomain.CurrentDomain.GetAssemblies(); } + // StartMode + foreach (var rule in Rules) + { + rule.OnStartCheck(mode); + } + // Checking Type[] types; foreach (var assembly in Assemblies) diff --git a/Editor/Core/InitializeOnLoad/Rules/CloneAssetsRule.cs b/Editor/Core/InitializeOnLoad/Rules/CloneAssetsRule.cs deleted file mode 100644 index 3137f4b..0000000 --- a/Editor/Core/InitializeOnLoad/Rules/CloneAssetsRule.cs +++ /dev/null @@ -1,38 +0,0 @@ -using System; - -namespace RealMethod.Editor -{ - public class CloneAssetsRule : CompileRule - { - protected override void Initilized() - { - - } - public override bool CanCheck(RuleExecutionMode mode, Type type) - { - return false; - // if (mode == RuleExecutionMode.AfterCompilation) - // { - // return typeof(Service); - // } - // else - // { - // return null; - // } - } - public override void OnCheck(Type type) - { - // var assets = Resources.FindObjectsOfTypeAll(); - // foreach (var asset in assets) - // { - // if (AssetDatabase.Contains(asset)) - // { - // Debug.LogWarning( - // $"PrimitiveAsset '{asset.name}' is used directly in Play Mode. " + - // $"A runtime instance or clone should be used instead.", - // asset); - // } - // } - } - } -} \ No newline at end of file diff --git a/Editor/Core/InitializeOnLoad/Rules/CloneAssetsRule.cs.meta b/Editor/Core/InitializeOnLoad/Rules/CloneAssetsRule.cs.meta deleted file mode 100644 index 1df2d7f..0000000 --- a/Editor/Core/InitializeOnLoad/Rules/CloneAssetsRule.cs.meta +++ /dev/null @@ -1,2 +0,0 @@ -fileFormatVersion: 2 -guid: afe89030ce51ae1479937042bf16b9f4 \ No newline at end of file diff --git a/Editor/Core/InitializeOnLoad/Rules/ConfigAssetsRule.cs b/Editor/Core/InitializeOnLoad/Rules/ConfigAssetsRule.cs index 961b5be..0b0fc2c 100644 --- a/Editor/Core/InitializeOnLoad/Rules/ConfigAssetsRule.cs +++ b/Editor/Core/InitializeOnLoad/Rules/ConfigAssetsRule.cs @@ -12,6 +12,9 @@ public class ConfigAssetsRule : CompileRule protected override void Initilized() { } + public override void OnStartCheck(RuleExecutionMode mode) + { + } public override bool CanCheck(RuleExecutionMode mode, Type type) { if (mode == RuleExecutionMode.EditorStartup) diff --git a/Editor/Core/InitializeOnLoad/Rules/PrimitveAssetsRule.cs b/Editor/Core/InitializeOnLoad/Rules/PrimitveAssetsRule.cs index d1be6c4..f093c43 100644 --- a/Editor/Core/InitializeOnLoad/Rules/PrimitveAssetsRule.cs +++ b/Editor/Core/InitializeOnLoad/Rules/PrimitveAssetsRule.cs @@ -7,32 +7,47 @@ namespace RealMethod.Editor public class PrimitveAssetsRule : CompileRule { private PrimitiveAsset[] assets = null; - private int state = 0; protected override void Initilized() { assets = Resources.FindObjectsOfTypeAll(); } - public override bool CanCheck(RuleExecutionMode mode, Type type) + public override void OnStartCheck(RuleExecutionMode mode) { if ((int)mode < 2) - return false; - + return; - state = (int)mode - 2; - return true; - } - public override void OnCheck(Type type) - { + PlayModeStateChange CurrentMode = (PlayModeStateChange)((int)mode - 2); foreach (var asset in assets) { - if (asset.AutoReset((PlayModeStateChange)state)) + if (mode == RuleExecutionMode.EnteredPlayMode) + { + asset.Invoke("OnValidateAsset"); + if (AssetDatabase.Contains(asset)) + { + if (asset is InstanceAsset) + { + Debug.LogWarning($"InstanceAsset '{asset.name}' is used directly in Play Mode. " + + $"A runtime instanceAsset should be used instead.Create() at runtime", + asset); + } + } + } + + if (asset.AutoReset(CurrentMode)) { asset.Invoke("Reset"); } } } + public override bool CanCheck(RuleExecutionMode mode, Type type) + { + return false; + } + public override void OnCheck(Type type) + { + } } } \ No newline at end of file diff --git a/Editor/Core/InitializeOnLoad/Rules/ServiceRule.cs b/Editor/Core/InitializeOnLoad/Rules/ServiceRule.cs index c7da8c9..6d37b52 100644 --- a/Editor/Core/InitializeOnLoad/Rules/ServiceRule.cs +++ b/Editor/Core/InitializeOnLoad/Rules/ServiceRule.cs @@ -10,6 +10,9 @@ public class ServiceRule : CompileRule protected override void Initilized() { + } + public override void OnStartCheck(RuleExecutionMode mode) + { } public override bool CanCheck(RuleExecutionMode mode, Type type) { diff --git a/Reservoir/ScriptTemplates/CompileRuleTemplate.txt b/Reservoir/ScriptTemplates/CompileRuleTemplate.txt index 8342dfa..73e984b 100644 --- a/Reservoir/ScriptTemplates/CompileRuleTemplate.txt +++ b/Reservoir/ScriptTemplates/CompileRuleTemplate.txt @@ -9,6 +9,10 @@ public class #SCRIPTNAME# : CompileRule { // Called right after Construct } + public override void OnStartCheck(RuleExecutionMode mode) + { + // Called once per mode befor any cheking. + } public override bool CanCheck(RuleExecutionMode mode, Type type) { // A Type that all target classes must derive from diff --git a/Runtime/Core/Definitions/Assets.cs b/Runtime/Core/Definitions/Assets.cs index 7b2139d..978f41a 100644 --- a/Runtime/Core/Definitions/Assets.cs +++ b/Runtime/Core/Definitions/Assets.cs @@ -1,4 +1,6 @@ using UnityEngine; +using UnityEngine.InputSystem.EnhancedTouch; + #if UNITY_EDITOR using UnityEditor; #endif @@ -72,6 +74,7 @@ public virtual bool AutoReset(PlayModeStateChange state) { return false; } + protected abstract void OnValidateAsset(); #endif } @@ -83,6 +86,12 @@ public virtual bool AutoReset(PlayModeStateChange state) /// public abstract class DataAsset : PrimitiveAsset { +#if UNITY_EDITOR + protected override sealed void OnValidateAsset() + { + + } +#endif } /// /// Represents an asset used only as a clone. @@ -91,18 +100,48 @@ public abstract class DataAsset : PrimitiveAsset /// public abstract class CloneAsset : PrimitiveAsset { - protected virtual void OnEnable() + [SerializeField, HideInInspector] + private bool _isRuntimeClone = false; + +#if UNITY_EDITOR + protected override sealed void OnValidateAsset() { if (!HasCloneName()) { if (!IsProjectAsset()) { - Debug.LogError($"CloneAsset Can't Create New Instance at Runtime, NewFile Removed!"); - Destroy(this); + Debug.LogError($"[{name}] CloneAsset cannot create new instance at runtime. Asset has been removed!"); + DestroyImmediate(this); return; } } } +#endif + + /// + /// Creates a runtime clone of this asset and marks it as safe for usage. + /// Direct project assets cannot be used; only cloned copies are valid. + /// + public CloneAsset Clone() + { + var clone = Instantiate(this); + clone._isRuntimeClone = true; + //clone.name = $"{name}_Clone"; + return clone; + } + + /// + /// Ensures this asset can be used safely. Throws an error if it's a direct project asset. + /// + protected void EnsureClonedUsage() + { +#if UNITY_EDITOR || DEVELOPMENT_BUILD + if (!_isRuntimeClone) + { + Debug.LogError($"[{name}] You cannot use a direct asset of type {GetType().Name}. Use Clone() instead."); + } +#endif + } } /// /// Represents an asset that defines how to create new instances. @@ -111,15 +150,48 @@ protected virtual void OnEnable() /// public abstract class InstanceAsset : PrimitiveAsset { - protected virtual void OnEnable() + [SerializeField, HideInInspector] + private bool _isRuntimeInstance = false; + +#if UNITY_EDITOR + protected override sealed void OnValidateAsset() { if (HasCloneName()) { - Debug.LogError($"FileAsset Can't Clone at Runtime, NewFile Removed!"); - Destroy(this); + Debug.LogError($"[{name}] InstanceAsset cannot be cloned directly. The cloned asset has been removed!"); + DestroyImmediate(this); return; } } +#endif + + /// + /// Creates a valid runtime instance of this InstanceAsset. + /// This is the only allowed way to use InstanceAsset at runtime. + /// + public static T Create(string name = "") where T : InstanceAsset + { + T inst = CreateInstance(); + inst._isRuntimeInstance = true; + inst.name = $"{name}_Instance"; + return inst; + } + + /// + /// Ensures this asset is being used correctly. + /// Only runtime-created instances are allowed at runtime. + /// + protected void EnsureInstanceUsage() + { +#if UNITY_EDITOR || DEVELOPMENT_BUILD + if (!_isRuntimeInstance) + { + Debug.LogError( + $"[{name}] InstanceAsset must be instantiated using Create(). " + + "Direct use of project asset is not allowed."); + } +#endif + } } /// /// Represents a unique shared asset in the project. @@ -128,21 +200,23 @@ protected virtual void OnEnable() /// public abstract class UniqueAsset : PrimitiveAsset { - protected virtual void OnEnable() +#if UNITY_EDITOR + protected override sealed void OnValidateAsset() { if (HasCloneName()) { - Debug.LogError($"UniqueAsset Can't Clone at Runtime, NewFile Removed!"); + Debug.LogError($"[{name}] UniqueAsset cannot clone at runtime. NewAsset has been removed!"); Destroy(this); return; } if (!IsProjectAsset()) { - Debug.LogError($"UniqueAsset Can't Create New Instance at Runtime, NewFile Removed!"); + Debug.LogError($"[{name}] UniqueAsset cannot create new instance at runtime. NewAsset has been removed!"); Destroy(this); return; } } +#endif } /// /// A specialized UniqueAsset used for global configuration. diff --git a/Runtime/Core/ProjectSetting/ProjectSettingAsset.cs b/Runtime/Core/ProjectSetting/ProjectSettingAsset.cs index b49a0bf..705753a 100644 --- a/Runtime/Core/ProjectSetting/ProjectSettingAsset.cs +++ b/Runtime/Core/ProjectSetting/ProjectSettingAsset.cs @@ -128,6 +128,9 @@ public GameObject GetPrefab_1() } #if UNITY_EDITOR + protected override void OnValidateAsset() + { + } public static ProjectSettingAsset Load() { return UnityEditor.AssetDatabase.LoadAssetAtPath(Path); diff --git a/Runtime/Pattern/Assets/BlackboardAsset.cs b/Runtime/Pattern/Assets/BlackboardAsset.cs index c6b0607..39f8f59 100644 --- a/Runtime/Pattern/Assets/BlackboardAsset.cs +++ b/Runtime/Pattern/Assets/BlackboardAsset.cs @@ -36,7 +36,7 @@ public abstract class BlackboardAsset : UniqueAsset, IBlackboard public Component GetComponent(Name16 name) => Blackboard.GetValue(name); - protected override void OnEnable() + protected virtual void OnEnable() { Blackboard.SetSize(GetMaxSize()); } diff --git a/Runtime/ReadySet/Essentials/DefaultGameConfig.cs b/Runtime/ReadySet/Essentials/DefaultGameConfig.cs index 26ff554..b7b867d 100644 --- a/Runtime/ReadySet/Essentials/DefaultGameConfig.cs +++ b/Runtime/ReadySet/Essentials/DefaultGameConfig.cs @@ -4,7 +4,7 @@ namespace RealMethod { public sealed class DefaultGameConfig : GameConfig { - protected override void OnEnable() + private void OnEnable() { if (HasCloneName()) { diff --git a/Runtime/ReadySet/Services/SpawanService.cs b/Runtime/ReadySet/Services/SpawanService.cs index b756eaa..dd78937 100644 --- a/Runtime/ReadySet/Services/SpawanService.cs +++ b/Runtime/ReadySet/Services/SpawanService.cs @@ -308,7 +308,7 @@ public static T Clone(T original, Object spawner = null) where T : Object } else { - Debug.LogWarning($"Spawn Event can only be sent to MonoBehaviour or GameObject. Target type: {target.GetType()}"); + Debug.LogWarning($"Spawn Event can only be send to MonoBehaviour or GameObject. Target type: {target.GetType()}"); } return target; } @@ -332,7 +332,7 @@ public static T Clone(T original, Transform parent, Object spawner = null) wh } else { - Debug.LogWarning($"Spawn Event can only be sent to MonoBehaviour or GameObject. Target type: {target.GetType()}"); + Debug.LogWarning($"Spawn Event can only be send to MonoBehaviour or GameObject. Target type: {target.GetType()}"); } return target; } @@ -356,7 +356,7 @@ public static T Clone(T original, Vector3 position, Quaternion rotation, Obje } else { - Debug.LogWarning($"Spawn Event can only be sent to MonoBehaviour or GameObject. Target type: {target.GetType()}"); + Debug.LogWarning($"Spawn Event can only be send to MonoBehaviour or GameObject. Target type: {target.GetType()}"); } return target; } @@ -380,7 +380,7 @@ public static T Clone(T original, Transform parent, bool worldPositionStays, } else { - Debug.LogWarning($"Spawn Event can only be sent to MonoBehaviour or GameObject. Target type: {target.GetType()}"); + Debug.LogWarning($"Spawn Event can only be send to MonoBehaviour or GameObject. Target type: {target.GetType()}"); } return target; } From 89f3ea42d194b72d1f484f2335745fc5eee03565 Mon Sep 17 00:00:00 2001 From: Alijimpa Date: Thu, 16 Apr 2026 10:06:24 +0330 Subject: [PATCH 101/204] Refine all Asset Defenition --- .../Rules/PrimitveAssetsRule.cs | 6 +- Reservoir/ScriptTemplates/CloneAsset.txt | 7 ++ Reservoir/ScriptTemplates/CloneAsset.txt.meta | 7 ++ .../ScriptTemplates/ConfigAssetTemplate.txt | 6 -- .../ScriptTemplates/DataAssetTemplate.txt | 6 -- .../ScriptTemplates/FileAssetTemplate.txt | 13 --- Reservoir/ScriptTemplates/InstanceAsset.txt | 7 ++ ...mplate.txt.meta => InstanceAsset.txt.meta} | 0 .../ScriptTemplates/UniqueAssetTemplate.txt | 6 -- Runtime/Core/Definitions/Assets.cs | 102 +++++------------- Runtime/Core/Definitions/GameMessage.cs | 2 + .../ProjectSetting/ProjectSettingAsset.cs | 2 +- Runtime/Library/Extension/ScriptableObject.cs | 67 +++++++++++- Runtime/Library/Utilities/Game_Library.cs | 22 ++++ .../Library/Utilities/Game_Library.cs.meta | 2 + Runtime/ReadySet/Services/DespawnService.cs | 32 ++++-- Runtime/ReadySet/Services/SpawanService.cs | 46 +++++--- 17 files changed, 204 insertions(+), 129 deletions(-) create mode 100644 Reservoir/ScriptTemplates/CloneAsset.txt create mode 100644 Reservoir/ScriptTemplates/CloneAsset.txt.meta delete mode 100644 Reservoir/ScriptTemplates/FileAssetTemplate.txt create mode 100644 Reservoir/ScriptTemplates/InstanceAsset.txt rename Reservoir/ScriptTemplates/{FileAssetTemplate.txt.meta => InstanceAsset.txt.meta} (100%) create mode 100644 Runtime/Library/Utilities/Game_Library.cs create mode 100644 Runtime/Library/Utilities/Game_Library.cs.meta diff --git a/Editor/Core/InitializeOnLoad/Rules/PrimitveAssetsRule.cs b/Editor/Core/InitializeOnLoad/Rules/PrimitveAssetsRule.cs index f093c43..7c89316 100644 --- a/Editor/Core/InitializeOnLoad/Rules/PrimitveAssetsRule.cs +++ b/Editor/Core/InitializeOnLoad/Rules/PrimitveAssetsRule.cs @@ -22,7 +22,9 @@ public override void OnStartCheck(RuleExecutionMode mode) { if (mode == RuleExecutionMode.EnteredPlayMode) { - asset.Invoke("OnValidateAsset"); + if (asset is not DataAsset) + asset.Invoke(GameMessage.AssetPermission); + if (AssetDatabase.Contains(asset)) { if (asset is InstanceAsset) @@ -36,7 +38,7 @@ public override void OnStartCheck(RuleExecutionMode mode) if (asset.AutoReset(CurrentMode)) { - asset.Invoke("Reset"); + asset.Invoke(GameMessage.Reset); } } } diff --git a/Reservoir/ScriptTemplates/CloneAsset.txt b/Reservoir/ScriptTemplates/CloneAsset.txt new file mode 100644 index 0000000..995524d --- /dev/null +++ b/Reservoir/ScriptTemplates/CloneAsset.txt @@ -0,0 +1,7 @@ +using UnityEngine; +using RealMethod; + +[CreateAssetMenu(fileName = "#SCRIPTNAME#", menuName = "#PROJECTNAME#/#SCRIPTNAME#", order = 1)] +public class #SCRIPTNAME# : CloneAsset +{ +} diff --git a/Reservoir/ScriptTemplates/CloneAsset.txt.meta b/Reservoir/ScriptTemplates/CloneAsset.txt.meta new file mode 100644 index 0000000..d802343 --- /dev/null +++ b/Reservoir/ScriptTemplates/CloneAsset.txt.meta @@ -0,0 +1,7 @@ +fileFormatVersion: 2 +guid: 109cba7c2bec5bb4cb7ea64f2236b1f2 +TextScriptImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Reservoir/ScriptTemplates/ConfigAssetTemplate.txt b/Reservoir/ScriptTemplates/ConfigAssetTemplate.txt index 42a4a16..397f888 100644 --- a/Reservoir/ScriptTemplates/ConfigAssetTemplate.txt +++ b/Reservoir/ScriptTemplates/ConfigAssetTemplate.txt @@ -4,10 +4,4 @@ using RealMethod; [CreateAssetMenu(fileName = "#SCRIPTNAME#", menuName = "#PROJECTNAME#/#SCRIPTNAME#", order = 1)] public class #SCRIPTNAME# : ConfigAsset { - #if UNITY_EDITOR - // public override void OnEditorPlay() - // { - // base.OnEditorPlay(); - // } - #endif } diff --git a/Reservoir/ScriptTemplates/DataAssetTemplate.txt b/Reservoir/ScriptTemplates/DataAssetTemplate.txt index 2b4c0cc..895c8cc 100644 --- a/Reservoir/ScriptTemplates/DataAssetTemplate.txt +++ b/Reservoir/ScriptTemplates/DataAssetTemplate.txt @@ -4,10 +4,4 @@ using RealMethod; [CreateAssetMenu(fileName = "#SCRIPTNAME#", menuName = "#PROJECTNAME#/#SCRIPTNAME#", order = 1)] public class #SCRIPTNAME# : DataAsset { - #if UNITY_EDITOR - // public override void OnEditorPlay() - // { - // base.OnEditorPlay(); - // } - #endif } \ No newline at end of file diff --git a/Reservoir/ScriptTemplates/FileAssetTemplate.txt b/Reservoir/ScriptTemplates/FileAssetTemplate.txt deleted file mode 100644 index be13179..0000000 --- a/Reservoir/ScriptTemplates/FileAssetTemplate.txt +++ /dev/null @@ -1,13 +0,0 @@ -using UnityEngine; -using RealMethod; - -[CreateAssetMenu(fileName = "#SCRIPTNAME#", menuName = "#PROJECTNAME#/#SCRIPTNAME#", order = 1)] -public class #SCRIPTNAME# : FileAsset -{ - #if UNITY_EDITOR - // public override void OnEditorPlay() - // { - // base.OnEditorPlay(); - // } - #endif -} diff --git a/Reservoir/ScriptTemplates/InstanceAsset.txt b/Reservoir/ScriptTemplates/InstanceAsset.txt new file mode 100644 index 0000000..9faab92 --- /dev/null +++ b/Reservoir/ScriptTemplates/InstanceAsset.txt @@ -0,0 +1,7 @@ +using UnityEngine; +using RealMethod; + +[CreateAssetMenu(fileName = "#SCRIPTNAME#", menuName = "#PROJECTNAME#/#SCRIPTNAME#", order = 1)] +public class #SCRIPTNAME# : InstanceAsset +{ +} diff --git a/Reservoir/ScriptTemplates/FileAssetTemplate.txt.meta b/Reservoir/ScriptTemplates/InstanceAsset.txt.meta similarity index 100% rename from Reservoir/ScriptTemplates/FileAssetTemplate.txt.meta rename to Reservoir/ScriptTemplates/InstanceAsset.txt.meta diff --git a/Reservoir/ScriptTemplates/UniqueAssetTemplate.txt b/Reservoir/ScriptTemplates/UniqueAssetTemplate.txt index 85899e0..c5f5388 100644 --- a/Reservoir/ScriptTemplates/UniqueAssetTemplate.txt +++ b/Reservoir/ScriptTemplates/UniqueAssetTemplate.txt @@ -4,10 +4,4 @@ using RealMethod; [CreateAssetMenu(fileName = "#SCRIPTNAME#", menuName = "#PROJECTNAME#/#SCRIPTNAME#", order = 1)] public class #SCRIPTNAME# : UniqueAsset { - #if UNITY_EDITOR - // public override void OnEditorPlay() - // { - // base.OnEditorPlay(); - // } - #endif } diff --git a/Runtime/Core/Definitions/Assets.cs b/Runtime/Core/Definitions/Assets.cs index 978f41a..3faec1b 100644 --- a/Runtime/Core/Definitions/Assets.cs +++ b/Runtime/Core/Definitions/Assets.cs @@ -1,5 +1,4 @@ using UnityEngine; -using UnityEngine.InputSystem.EnhancedTouch; #if UNITY_EDITOR using UnityEditor; @@ -19,19 +18,21 @@ public interface IAsset /// public abstract class PrimitiveAsset : ScriptableObject, IAsset, ISpawn, ISpawnWithAuthor { + public bool IsSpawned { get; private set; } = false; // Implement IAsset Interface - PrimitiveAsset IAsset.GetAsset() - { - return this; - } + PrimitiveAsset IAsset.GetAsset() => this; // Implement ISpawn interface void ISpawn.OnSpawn() { + IsSpawned = true; + EnsureAssetPermission(); OnSpawn(null); } // Implement ISpawnWithAuthor interface void ISpawnWithAuthor.OnSpawn(Object author) { + IsSpawned = true; + EnsureAssetPermission(); OnSpawn(author); } @@ -39,6 +40,15 @@ void ISpawnWithAuthor.OnSpawn(Object author) protected virtual void OnSpawn(Object spawner) { + } + /// + /// Ensures this asset can be used safely. Throws an error if it's not. + /// + protected virtual void EnsureAssetPermission() + { +#if UNITY_EDITOR || DEVELOPMENT_BUILD + Debug.LogError($"[{name}] For this asset didnt write any permission."); +#endif } public bool HasCloneName() @@ -74,7 +84,6 @@ public virtual bool AutoReset(PlayModeStateChange state) { return false; } - protected abstract void OnValidateAsset(); #endif } @@ -86,12 +95,7 @@ public virtual bool AutoReset(PlayModeStateChange state) /// public abstract class DataAsset : PrimitiveAsset { -#if UNITY_EDITOR - protected override sealed void OnValidateAsset() - { - } -#endif } /// /// Represents an asset used only as a clone. @@ -100,12 +104,9 @@ protected override sealed void OnValidateAsset() /// public abstract class CloneAsset : PrimitiveAsset { - [SerializeField, HideInInspector] - private bool _isRuntimeClone = false; - -#if UNITY_EDITOR - protected override sealed void OnValidateAsset() + protected sealed override void EnsureAssetPermission() { +#if UNITY_EDITOR || DEVELOPMENT_BUILD if (!HasCloneName()) { if (!IsProjectAsset()) @@ -115,33 +116,9 @@ protected override sealed void OnValidateAsset() return; } } - } #endif - - /// - /// Creates a runtime clone of this asset and marks it as safe for usage. - /// Direct project assets cannot be used; only cloned copies are valid. - /// - public CloneAsset Clone() - { - var clone = Instantiate(this); - clone._isRuntimeClone = true; - //clone.name = $"{name}_Clone"; - return clone; } - /// - /// Ensures this asset can be used safely. Throws an error if it's a direct project asset. - /// - protected void EnsureClonedUsage() - { -#if UNITY_EDITOR || DEVELOPMENT_BUILD - if (!_isRuntimeClone) - { - Debug.LogError($"[{name}] You cannot use a direct asset of type {GetType().Name}. Use Clone() instead."); - } -#endif - } } /// /// Represents an asset that defines how to create new instances. @@ -150,45 +127,24 @@ protected void EnsureClonedUsage() /// public abstract class InstanceAsset : PrimitiveAsset { - [SerializeField, HideInInspector] - private bool _isRuntimeInstance = false; - -#if UNITY_EDITOR - protected override sealed void OnValidateAsset() + protected sealed override void EnsureAssetPermission() { +#if UNITY_EDITOR || DEVELOPMENT_BUILD if (HasCloneName()) { Debug.LogError($"[{name}] InstanceAsset cannot be cloned directly. The cloned asset has been removed!"); DestroyImmediate(this); return; } - } -#endif - - /// - /// Creates a valid runtime instance of this InstanceAsset. - /// This is the only allowed way to use InstanceAsset at runtime. - /// - public static T Create(string name = "") where T : InstanceAsset - { - T inst = CreateInstance(); - inst._isRuntimeInstance = true; - inst.name = $"{name}_Instance"; - return inst; - } - /// - /// Ensures this asset is being used correctly. - /// Only runtime-created instances are allowed at runtime. - /// - protected void EnsureInstanceUsage() - { -#if UNITY_EDITOR || DEVELOPMENT_BUILD - if (!_isRuntimeInstance) + if (IsSpawned) { - Debug.LogError( - $"[{name}] InstanceAsset must be instantiated using Create(). " + - "Direct use of project asset is not allowed."); + if (IsProjectAsset()) + { + Debug.LogError($"[{name}] This asset is direct asset but Spawn Event called. Asset has been removed!"); + DestroyImmediate(this); + return; + } } #endif } @@ -200,9 +156,9 @@ protected void EnsureInstanceUsage() /// public abstract class UniqueAsset : PrimitiveAsset { -#if UNITY_EDITOR - protected override sealed void OnValidateAsset() + protected sealed override void EnsureAssetPermission() { +#if UNITY_EDITOR || DEVELOPMENT_BUILD if (HasCloneName()) { Debug.LogError($"[{name}] UniqueAsset cannot clone at runtime. NewAsset has been removed!"); @@ -215,8 +171,8 @@ protected override sealed void OnValidateAsset() Destroy(this); return; } - } #endif + } } /// /// A specialized UniqueAsset used for global configuration. diff --git a/Runtime/Core/Definitions/GameMessage.cs b/Runtime/Core/Definitions/GameMessage.cs index 22256b8..744ec14 100644 --- a/Runtime/Core/Definitions/GameMessage.cs +++ b/Runtime/Core/Definitions/GameMessage.cs @@ -9,5 +9,7 @@ public static class GameMessage public const string Attach = "OnAttach"; public const string Detach = "OnDetach"; public const string Share = "OnShare"; + public const string AssetPermission = "EnsureAssetPermission"; + public const string Reset = "Reset"; } } \ No newline at end of file diff --git a/Runtime/Core/ProjectSetting/ProjectSettingAsset.cs b/Runtime/Core/ProjectSetting/ProjectSettingAsset.cs index 705753a..493c5ce 100644 --- a/Runtime/Core/ProjectSetting/ProjectSettingAsset.cs +++ b/Runtime/Core/ProjectSetting/ProjectSettingAsset.cs @@ -128,7 +128,7 @@ public GameObject GetPrefab_1() } #if UNITY_EDITOR - protected override void OnValidateAsset() + protected sealed override void EnsureAssetPermission() { } public static ProjectSettingAsset Load() diff --git a/Runtime/Library/Extension/ScriptableObject.cs b/Runtime/Library/Extension/ScriptableObject.cs index 7f026c0..e7eb864 100644 --- a/Runtime/Library/Extension/ScriptableObject.cs +++ b/Runtime/Library/Extension/ScriptableObject.cs @@ -5,6 +5,67 @@ namespace RealMethod { public static class ScriptableObject_Extension { + /// + /// Sends an "OnSpawn" message to the owner GameObject. + /// + /// The GameObject to send the message to. + /// The object that triggered the spawn event (passed as parameter to the message). + public static void InvokeSpawnEvent(this ScriptableObject owner, Object spawner = null) + { + if (spawner != null) + { + if (owner is ISpawnWithAuthor provider) + { + provider.OnSpawn(spawner); + } + else + { + owner.Invoke(GameMessage.Spawn, new object[1] { spawner }); + } + } + else + { + if (owner is ISpawn provider) + { + provider.OnSpawn(); + } + else + { + owner.Invoke(GameMessage.Spawn); + } + } + } + /// + /// Sends an "OnDespawn" message to the owner GameObject. + /// + /// The GameObject to send the message to. + /// The object that triggered the despawn event (passed as parameter to the message). + public static void InvokeDespawnEvent(this ScriptableObject owner, Object despawner = null) + { + if (despawner != null) + { + if (owner is IDespawnWithAuthor provider) + { + provider.OnDespawn(despawner); + } + else + { + owner.Invoke(GameMessage.Despawn, new object[1] { despawner }); + } + } + else + { + if (owner is IDespawn provider) + { + provider.OnDespawn(); + } + else + { + owner.Invoke(GameMessage.Despawn); + } + } + } + public static void Invoke(this ScriptableObject so, string methodName) { so.Invoke(methodName, null); @@ -23,6 +84,10 @@ public static void Invoke(this ScriptableObject so, string methodName, object[] Debug.LogError($"Method '{methodName}' not found."); } } - + public static ScriptableObject Clone(this ScriptableObject so) + { + return ScriptableObject.Instantiate(so); + } + } } \ No newline at end of file diff --git a/Runtime/Library/Utilities/Game_Library.cs b/Runtime/Library/Utilities/Game_Library.cs new file mode 100644 index 0000000..fa1edf8 --- /dev/null +++ b/Runtime/Library/Utilities/Game_Library.cs @@ -0,0 +1,22 @@ +#if UNITY_EDITOR +using UnityEditor; +#endif +using UnityEngine; + +namespace RealMethod +{ + public static class RM_Game + { + public static bool IsPlaying + { + get + { +#if UNITY_EDITOR + return EditorApplication.isPlaying && EditorApplication.isPlayingOrWillChangePlaymode == false; +#else + return Application.isPlaying; // Runtime fallback +#endif + } + } + } +} \ No newline at end of file diff --git a/Runtime/Library/Utilities/Game_Library.cs.meta b/Runtime/Library/Utilities/Game_Library.cs.meta new file mode 100644 index 0000000..82a35f3 --- /dev/null +++ b/Runtime/Library/Utilities/Game_Library.cs.meta @@ -0,0 +1,2 @@ +fileFormatVersion: 2 +guid: e6d999204daa40649b779c0253b21ef7 \ No newline at end of file diff --git a/Runtime/ReadySet/Services/DespawnService.cs b/Runtime/ReadySet/Services/DespawnService.cs index d5b7252..154caa4 100644 --- a/Runtime/ReadySet/Services/DespawnService.cs +++ b/Runtime/ReadySet/Services/DespawnService.cs @@ -126,7 +126,7 @@ private static T GetManager() where T : MonoBehaviour // UI - public static bool Widget(string Name, Object spawner = null, bool debug = true) + public static bool Widget(string Name, Object despawner = null, bool debug = true) { if (GetManager() == null) { @@ -135,9 +135,9 @@ public static bool Widget(string Name, Object spawner = null, bool debug = true) return false; } - return GetManager().RemoveLayer(Name, spawner); + return GetManager().RemoveLayer(Name, despawner); } - public static bool Widget(MonoBehaviour Comp, Object spawner = null, bool debug = true) + public static bool Widget(MonoBehaviour Comp, Object despawner = null, bool debug = true) { if (GetManager() == null) { @@ -146,17 +146,17 @@ public static bool Widget(MonoBehaviour Comp, Object spawner = null, bool debug return false; } - return GetManager().RemoveLayer(Comp, spawner); + return GetManager().RemoveLayer(Comp, despawner); } // Prefab - public static bool GameObject(GameObject target, Object spawner = null, bool debug = true) + public static bool GameObject(GameObject target, Object despawner = null, bool debug = true) { if (target != null) { - if (spawner != null) + if (despawner != null) { - target.InvokeDespawnEvent(spawner); + target.InvokeDespawnEvent(despawner); } Object.Destroy(target); return true; @@ -199,6 +199,24 @@ public static bool Pool(PoolAsset asset, T target, bool debug = true) wher } } + // Realmethod + public static bool Asset(T target, Object despawner = null, bool debug = true) where T : PrimitiveAsset + { + if (target != null) + { + Object.Destroy(target); + target.InvokeDespawnEvent(despawner); + return true; + } + else + { + if (debug) + Debug.LogWarning($"Asset is not Valid!"); + return false; + } + } + + // Task public static bool Task(object TaskObj, Object author, bool debug = true) { diff --git a/Runtime/ReadySet/Services/SpawanService.cs b/Runtime/ReadySet/Services/SpawanService.cs index dd78937..853e75c 100644 --- a/Runtime/ReadySet/Services/SpawanService.cs +++ b/Runtime/ReadySet/Services/SpawanService.cs @@ -306,6 +306,10 @@ public static T Clone(T original, Object spawner = null) where T : Object { obj.InvokeSpawnEvent(spawner); } + else if (target is PrimitiveAsset asset) + { + asset.InvokeSpawnEvent(spawner); + } else { Debug.LogWarning($"Spawn Event can only be send to MonoBehaviour or GameObject. Target type: {target.GetType()}"); @@ -330,6 +334,10 @@ public static T Clone(T original, Transform parent, Object spawner = null) wh { obj.InvokeSpawnEvent(spawner); } + else if (target is PrimitiveAsset asset) + { + asset.InvokeSpawnEvent(spawner); + } else { Debug.LogWarning($"Spawn Event can only be send to MonoBehaviour or GameObject. Target type: {target.GetType()}"); @@ -354,6 +362,10 @@ public static T Clone(T original, Vector3 position, Quaternion rotation, Obje { obj.InvokeSpawnEvent(spawner); } + else if (target is PrimitiveAsset asset) + { + asset.InvokeSpawnEvent(spawner); + } else { Debug.LogWarning($"Spawn Event can only be send to MonoBehaviour or GameObject. Target type: {target.GetType()}"); @@ -378,6 +390,10 @@ public static T Clone(T original, Transform parent, bool worldPositionStays, { obj.InvokeSpawnEvent(spawner); } + else if (target is PrimitiveAsset asset) + { + asset.InvokeSpawnEvent(spawner); + } else { Debug.LogWarning($"Spawn Event can only be send to MonoBehaviour or GameObject. Target type: {target.GetType()}"); @@ -685,24 +701,26 @@ public static T Command(CPrefab prefab, MonoBehaviour owner) where T : Comman public static T Asset(Object spawner = null) where T : PrimitiveAsset { var target = ScriptableObject.CreateInstance(); - if (spawner != null) - { - if (target is ISpawnWithAuthor provider) - { - provider.OnSpawn(spawner); - } + target.InvokeSpawnEvent(spawner); + target.name = $"{typeof(T).Name}_Instance"; - } - else - { - if (target is ISpawn provider) - { - provider.OnSpawn(); - } - } return target; } + public static PrimitiveAsset Asset(System.Type type, Object spawner = null) + { + if (type == null) + throw new System.ArgumentNullException(nameof(type)); + + if (!typeof(PrimitiveAsset).IsAssignableFrom(type)) + throw new System.ArgumentException( + $"Type {type.Name} must inherit from PrimitiveAsset."); + + PrimitiveAsset target = (PrimitiveAsset)ScriptableObject.CreateInstance(type); + target.InvokeSpawnEvent(spawner); + target.name = $"{type.Name}_Instance"; + return target; + } // Task public static bool Task(object TaskObj, Object author) { From ffb2c3a672e32173aebc3b049e6149528f2ed3f3 Mon Sep 17 00:00:00 2001 From: Alijimpa Date: Thu, 16 Apr 2026 12:42:43 +0330 Subject: [PATCH 102/204] Implement Default Service --- Runtime/Core/Architecture/Game.cs | 15 ++++++++++++++- Runtime/Core/Architecture/World.cs | 9 +++++---- Runtime/ReadySet/Essentials/DefaultGame.cs | 10 +++++++++- 3 files changed, 28 insertions(+), 6 deletions(-) diff --git a/Runtime/Core/Architecture/Game.cs b/Runtime/Core/Architecture/Game.cs index 15ebb16..fec2276 100644 --- a/Runtime/Core/Architecture/Game.cs +++ b/Runtime/Core/Architecture/Game.cs @@ -98,6 +98,11 @@ public static bool IsPaused /// public static bool IsLoading => Instance.IsGameLoading(); /// + /// Returns true if the Game system has one or more registered services; + /// otherwise, returns false. + /// + public static bool HasService => Instance.Services.Count > 0; + /// /// Event invoked when a scene or world starts or finishes loading. /// The boolean parameter is true when loading starts and false when loading ends. /// @@ -495,7 +500,7 @@ public static T GetService(bool Printdebug = true) if (Printdebug) Debug.LogError($"Service {TypeService} not found."); - + return default; } /// @@ -521,6 +526,7 @@ public static bool TryGetService(out T service) where T : Service public static void ClearService() { Instance.Services.Clear(); + Instance.OnServiceCleand(); } /// /// Returns the type names of all registered game services. @@ -1029,6 +1035,13 @@ protected virtual bool CanChangeState(int A, int B, object author) { return true; } + /// + /// Called after GameServices clear. + /// + protected virtual void OnServiceCleand() + { + + } /// diff --git a/Runtime/Core/Architecture/World.cs b/Runtime/Core/Architecture/World.cs index e589170..3318ba4 100644 --- a/Runtime/Core/Architecture/World.cs +++ b/Runtime/Core/Architecture/World.cs @@ -102,10 +102,6 @@ private void Awake() IRelationBridge SyncProvider = Game.Bridge; if (SyncProvider.IntroduceWorld(this)) { - if (clearServices) - { - Game.ClearService(); - } SyncProvider.BindServicesUpdated(Notify_OnServicesUpdated); } else @@ -149,6 +145,11 @@ private void Awake() transform.position = Vector3.zero; transform.rotation = Quaternion.identity; + if (clearServices) + { + Game.ClearService(); + } + WorldBegin(); SyncProvider.WorldIsReady(); } diff --git a/Runtime/ReadySet/Essentials/DefaultGame.cs b/Runtime/ReadySet/Essentials/DefaultGame.cs index 497ba5c..b892b97 100644 --- a/Runtime/ReadySet/Essentials/DefaultGame.cs +++ b/Runtime/ReadySet/Essentials/DefaultGame.cs @@ -1,4 +1,5 @@ +using System; using UnityEngine; namespace RealMethod @@ -16,7 +17,6 @@ protected override void OnGameInitialized() } protected override void OnGameStart() { - AddService(this); Debug.Log("DefultGame Started"); } protected override void OnWorldChanged(World NewWorld) @@ -29,5 +29,13 @@ protected override void OnGameClosed() } + + protected override void OnServiceCleand() + { +#if UNITY_EDITOR + AddService(this); +#endif + } + } } From 22d35a1e92886d754944fcb6f9fd5298f43e1e98 Mon Sep 17 00:00:00 2001 From: Alijimpa Date: Thu, 16 Apr 2026 14:12:12 +0330 Subject: [PATCH 103/204] Implement Overlap World Refine Holding Stage and ShareObject --- .../ScriptTemplates/GameBridgeTemplate.txt | 5 -- Runtime/Core/Architecture/Game.cs | 7 +- Runtime/Core/Architecture/GameBridge.cs | 74 ++++++++++++++----- Runtime/Core/Architecture/World.cs | 2 +- Runtime/Library/Extension/GameObject.cs | 14 +++- .../Components/Method/SharedObject.cs | 6 +- Runtime/ReadySet/Essentials/DefaultGame.cs | 1 - .../ReadySet/Essentials/DefaultGameBridge.cs | 15 ---- 8 files changed, 77 insertions(+), 47 deletions(-) diff --git a/Reservoir/ScriptTemplates/GameBridgeTemplate.txt b/Reservoir/ScriptTemplates/GameBridgeTemplate.txt index c262892..fabf4ee 100644 --- a/Reservoir/ScriptTemplates/GameBridgeTemplate.txt +++ b/Reservoir/ScriptTemplates/GameBridgeTemplate.txt @@ -2,9 +2,4 @@ using RealMethod; public class #SCRIPTNAME# : GameBridge { - // Base Service Methods - protected override void OnStart(object Author) {} - protected override void OnWorldChanging() { } - protected override void OnEnd(object Author) { } - } diff --git a/Runtime/Core/Architecture/Game.cs b/Runtime/Core/Architecture/Game.cs index fec2276..6837eae 100644 --- a/Runtime/Core/Architecture/Game.cs +++ b/Runtime/Core/Architecture/Game.cs @@ -74,6 +74,10 @@ public static GameObject Player /// public static GlobalEnum State { get; private set; } = 0; /// + /// This represents the persistent scene reference used for managing components across the game lifecycle. + /// + public static Scene PersistentScene => ((IRelationBridge)Bridge).InstanceScene; + /// /// Indicates whether a scene or world load operation is currently in progress. /// public static bool IsPaused @@ -796,7 +800,6 @@ public static void Quit() Application.Quit(); #endif } - /// /// Logs a message to the Unity Console. /// @@ -1040,7 +1043,7 @@ protected virtual bool CanChangeState(int A, int B, object author) /// protected virtual void OnServiceCleand() { - + } diff --git a/Runtime/Core/Architecture/GameBridge.cs b/Runtime/Core/Architecture/GameBridge.cs index 09e3a25..5431a66 100644 --- a/Runtime/Core/Architecture/GameBridge.cs +++ b/Runtime/Core/Architecture/GameBridge.cs @@ -3,6 +3,7 @@ using UnityEngine; using UnityEngine.SceneManagement; using System.Collections.Generic; +using Codice.Client.Common; namespace RealMethod { @@ -13,6 +14,10 @@ namespace RealMethod /// public interface IRelationBridge { + /// + /// This represents the persistent scene + /// + Scene InstanceScene { get; } /// /// Introduces a newly created world to the system. /// @@ -21,7 +26,7 @@ public interface IRelationBridge /// True if the world is treated as the main world; /// false if it is considered a side/additive world. /// - bool IntroduceWorld(World world); + bool RegisterWorld(World world); /// /// Binds a callback invoked when the main world is added. /// @@ -94,7 +99,7 @@ public interface ILoadScneBridge /// Inherits from and implements /// to integrate with the game's internal world and service management system. /// - public abstract class GameBridge : Service, IRelationBridge, ILoadScneBridge + public abstract class GameBridge : IService, IRelationBridge, ILoadScneBridge { // Events private Action GameReadyEvent; @@ -104,8 +109,25 @@ public abstract class GameBridge : Service, IRelationBridge, ILoadScneBridge private Action SceneLoadingProcessEvent; private bool isLoading; private List Shareds = new List(5); - private bool IsHolding = false; + public bool IsHolding { get; private set; } = false; protected float FadeTime = 0; + private Scene CurrrentScene; + public static Scene LastActiveScene; + public static bool SceneWillUnload { get; private set; } + + // Implement IService Interface + object IService.GetServiceClass() => this; + void IService.Created(object author) + { + SceneManager.activeSceneChanged += OnActiveSceneChanged; + } + void IService.ChangingWorld(World NewWorld) + { + } + void IService.Deleted(object author) + { + SceneManager.activeSceneChanged -= OnActiveSceneChanged; + } // Implement IRelationBridge Interface @@ -121,9 +143,10 @@ event Action IRelationBridge.OnGameReady GameReadyEvent -= value; } } - bool IRelationBridge.IntroduceWorld(World world) + Scene IRelationBridge.InstanceScene => CurrrentScene; + bool IRelationBridge.RegisterWorld(World world) { - return RequestForNewWorld(world); + return TryToRegisterWorld(world); } void IRelationBridge.BindWorldCreated(Action func) { @@ -197,11 +220,6 @@ event Action ILoadScneBridge.OnSceneLoadingProcess /// GameObject should be always loaded cross scenes public void AddSharedObject(GameObject obj) { - if (IsHolding) - { - Debug.LogError("You can't Set Object as Shared in holding time"); - return; - } Shareds.Add(obj); if (obj.gameObject.activeInHierarchy && Game.World.gameObject.activeInHierarchy) obj.transform.SetParent(Game.World.transform); @@ -212,11 +230,6 @@ public void AddSharedObject(GameObject obj) /// GameObject should not be always loaded cross scenes public void RemoveSharedObject(GameObject obj) { - if (IsHolding) - { - Debug.LogError("You can't Set Object as Shared in holding time"); - return; - } Shareds.Remove(obj); if (obj.gameObject.activeInHierarchy) obj.transform.SetParent(null); @@ -245,7 +258,9 @@ public bool IsSharedObject(GameObject obj) /// The world instance will set as main world for game. protected void SetMianWorld(World world) { + CurrrentScene = world.gameObject.scene; NewWorldEvent?.Invoke(world); + SceneWillUnload = false; } /// /// Call this when you want to define new World class that created and should not be main world (probably deleted) @@ -296,17 +311,34 @@ protected void HoldSharedObject(bool active) /// If this request is valid return true that mean this world set as main world. /// If this request false means this world import from scen that is additive and should deactive. /// Additive load + if (NewScene != CurrrentScene) { SetAdditiveWorld(NewWorld); + return false; ; + } + else + { + Debug.LogError($"[WorldRegistry] Duplicate world in SAME scene : {NewWorld.gameObject.name} / {Game.World.gameObject}"); return false; } } @@ -405,7 +437,11 @@ public virtual IEnumerator GetLoadWorldCorotine(WorldAsset WorldScene) } - + private static void OnActiveSceneChanged(Scene oldScene, Scene newScene) + { + LastActiveScene = newScene; + SceneWillUnload = true; // old scene will be destroyed next frame + } private float RemapClamped(float value, float inMin, float inMax, float outMin, float outMax) { // Prevent divide by zero diff --git a/Runtime/Core/Architecture/World.cs b/Runtime/Core/Architecture/World.cs index 3318ba4..1e98d24 100644 --- a/Runtime/Core/Architecture/World.cs +++ b/Runtime/Core/Architecture/World.cs @@ -100,7 +100,7 @@ private void Awake() { //Connect to Game With Bridge IRelationBridge SyncProvider = Game.Bridge; - if (SyncProvider.IntroduceWorld(this)) + if (SyncProvider.RegisterWorld(this)) { SyncProvider.BindServicesUpdated(Notify_OnServicesUpdated); } diff --git a/Runtime/Library/Extension/GameObject.cs b/Runtime/Library/Extension/GameObject.cs index 979d93d..4075d02 100644 --- a/Runtime/Library/Extension/GameObject.cs +++ b/Runtime/Library/Extension/GameObject.cs @@ -231,8 +231,13 @@ public static bool IsInScene(this GameObject obj) /// Registers the GameObject with a shared object system. /// /// The GameObject to register. - public static void Share(this GameObject obj) + public static void Share(this GameObject obj , bool safety = true) { + if (Game.Bridge.IsHolding && safety) + { + Debug.LogError("You can't Set Object as Shared in holding time (When bridge hold all object in gamescope or unhold)"); + return; + } Game.Bridge.AddSharedObject(obj); obj.SendMessage(GameMessage.Share, true, SendMessageOptions.DontRequireReceiver); } @@ -240,8 +245,13 @@ public static void Share(this GameObject obj) /// Unregisters the GameObject from the shared object system. /// /// The GameObject to unregister. - public static void Unshare(this GameObject obj) + public static void Unshare(this GameObject obj, bool safety = true) { + if (Game.Bridge.IsHolding && safety) + { + Debug.LogError("You can't Set Object as Shared in holding time (When bridge hold all object in gamescope or unhold)"); + return; + } Game.Bridge.RemoveSharedObject(obj); obj.SendMessage(GameMessage.Share, false, SendMessageOptions.DontRequireReceiver); } diff --git a/Runtime/ReadySet/Components/Method/SharedObject.cs b/Runtime/ReadySet/Components/Method/SharedObject.cs index 83ff717..c3a0fae 100644 --- a/Runtime/ReadySet/Components/Method/SharedObject.cs +++ b/Runtime/ReadySet/Components/Method/SharedObject.cs @@ -5,14 +5,16 @@ namespace RealMethod [AddComponentMenu("RealMethod/Method/SharedObject")] public sealed class SharedObject : MonoBehaviour { + [SerializeField] + private bool CheckSaftyShare = false; private void OnEnable() { - gameObject.Share(); + gameObject.Share(CheckSaftyShare); } private void OnDisable() { - gameObject.Unshare(); + gameObject.Unshare(CheckSaftyShare); } } } \ No newline at end of file diff --git a/Runtime/ReadySet/Essentials/DefaultGame.cs b/Runtime/ReadySet/Essentials/DefaultGame.cs index b892b97..0d7ea9a 100644 --- a/Runtime/ReadySet/Essentials/DefaultGame.cs +++ b/Runtime/ReadySet/Essentials/DefaultGame.cs @@ -1,5 +1,4 @@ -using System; using UnityEngine; namespace RealMethod diff --git a/Runtime/ReadySet/Essentials/DefaultGameBridge.cs b/Runtime/ReadySet/Essentials/DefaultGameBridge.cs index 10d4035..7adc94f 100644 --- a/Runtime/ReadySet/Essentials/DefaultGameBridge.cs +++ b/Runtime/ReadySet/Essentials/DefaultGameBridge.cs @@ -1,21 +1,6 @@ -using UnityEngine; - namespace RealMethod { public sealed class DefaultGameBridge : GameBridge { - protected override void OnStart(object Author) - { - Debug.Log("DefaultBridge Connected"); - } - protected override void OnWorldChanging(World Previous, World New) - { - } - protected override void OnEnd(object Author) - { - Debug.Log("DefaultBridge Disconnected"); - } - - } } \ No newline at end of file From 466d9841889792d905f3f580672d684c7919febe Mon Sep 17 00:00:00 2001 From: Alijimpa Date: Thu, 16 Apr 2026 20:02:23 +0330 Subject: [PATCH 104/204] Implement Type Extionsion --- Runtime/Library/Extension/Object.cs | 35 ++++++++++++++++++++++++++ Runtime/Library/Extension/Type.cs | 24 ++++++++++++++++++ Runtime/Library/Extension/Type.cs.meta | 2 ++ 3 files changed, 61 insertions(+) create mode 100644 Runtime/Library/Extension/Type.cs create mode 100644 Runtime/Library/Extension/Type.cs.meta diff --git a/Runtime/Library/Extension/Object.cs b/Runtime/Library/Extension/Object.cs index db3ad9b..800a6e9 100644 --- a/Runtime/Library/Extension/Object.cs +++ b/Runtime/Library/Extension/Object.cs @@ -16,5 +16,40 @@ public static bool NullChecker(this Object Obj, string Name) return false; } } + public static T Cast(this object obj) where T : class + { + return (T)obj; + } + public static bool TryCast(this object obj, out T result) where T : class + { + if (obj is T refrence) + { + result = refrence; + return true; + } + else + { + result = null; + return false; + } + } + public static SoftType GetSoftType(this object obj) where T : System.Type + { + return obj.GetType(); + } + public static bool TryGetType(this object obj, out SoftType result) where T : System.Type + { + System.Type targetType = obj.GetType(); + if (targetType.IsAssignableFrom(typeof(T))) + { + result = obj.GetType(); + return true; + } + else + { + result = null; + return false; + } + } } } \ No newline at end of file diff --git a/Runtime/Library/Extension/Type.cs b/Runtime/Library/Extension/Type.cs new file mode 100644 index 0000000..78ca40c --- /dev/null +++ b/Runtime/Library/Extension/Type.cs @@ -0,0 +1,24 @@ +using System; + +namespace RealMethod +{ + public static class Type_Extension + { + public static bool IsChild(this Type type) where T : Type + { + return type.IsAssignableFrom(typeof(T)); + } + public static bool IsChild(this Type type, Type target) + { + return type.IsAssignableFrom(target); + } + public static bool IsChild(this SoftType soft) where T : Type + { + return soft.Type.IsAssignableFrom(typeof(T)); + } + public static bool IsChild(this SoftType soft, SoftType target) + { + return soft.Type.IsAssignableFrom(target); + } + } +} \ No newline at end of file diff --git a/Runtime/Library/Extension/Type.cs.meta b/Runtime/Library/Extension/Type.cs.meta new file mode 100644 index 0000000..7650dc4 --- /dev/null +++ b/Runtime/Library/Extension/Type.cs.meta @@ -0,0 +1,2 @@ +fileFormatVersion: 2 +guid: 5db382bc1559fc345abb66c2256eb1b8 \ No newline at end of file From eeee51fbb489a26180d1d2f6730d984054892d6c Mon Sep 17 00:00:00 2001 From: Alijimpa Date: Fri, 17 Apr 2026 07:51:50 +0330 Subject: [PATCH 105/204] Rename ProjectSetting Sections --- Editor/Core/ProjectSetting/ProjectSettingProvider.cs | 8 ++++---- .../{CompileRule_Section.cs => CompileRuleSection.cs} | 2 +- ...ileRule_Section.cs.meta => CompileRuleSection.cs.meta} | 0 ...lderStructure_Section.cs => FolderStructureSection.cs} | 2 +- ...ure_Section.cs.meta => FolderStructureSection.cs.meta} | 0 .../{GameStatus_Section.cs => GameStatusSection.cs} | 2 +- ...meStatus_Section.cs.meta => GameStatusSection.cs.meta} | 0 ...zerSetting_Section.cs => InitializerSettingSection.cs} | 2 +- ..._Section.cs.meta => InitializerSettingSection.cs.meta} | 0 9 files changed, 8 insertions(+), 8 deletions(-) rename Editor/Core/ProjectSetting/Sections/{CompileRule_Section.cs => CompileRuleSection.cs} (97%) rename Editor/Core/ProjectSetting/Sections/{CompileRule_Section.cs.meta => CompileRuleSection.cs.meta} (100%) rename Editor/Core/ProjectSetting/Sections/{FolderStructure_Section.cs => FolderStructureSection.cs} (98%) rename Editor/Core/ProjectSetting/Sections/{FolderStructure_Section.cs.meta => FolderStructureSection.cs.meta} (100%) rename Editor/Core/ProjectSetting/Sections/{GameStatus_Section.cs => GameStatusSection.cs} (97%) rename Editor/Core/ProjectSetting/Sections/{GameStatus_Section.cs.meta => GameStatusSection.cs.meta} (100%) rename Editor/Core/ProjectSetting/Sections/{InitializerSetting_Section.cs => InitializerSettingSection.cs} (97%) rename Editor/Core/ProjectSetting/Sections/{InitializerSetting_Section.cs.meta => InitializerSettingSection.cs.meta} (100%) diff --git a/Editor/Core/ProjectSetting/ProjectSettingProvider.cs b/Editor/Core/ProjectSetting/ProjectSettingProvider.cs index 1174df8..373c6d9 100644 --- a/Editor/Core/ProjectSetting/ProjectSettingProvider.cs +++ b/Editor/Core/ProjectSetting/ProjectSettingProvider.cs @@ -257,10 +257,10 @@ public static class ProjectSettingProvider private static bool candraw = true;// Flag to determine if the UI can be drawn private static ProjectSettingSection[] sections = new ProjectSettingSection[4] { // Array of sections to be rendered in the settings UI - new InitializerSetting_Section(), - new FolderStructure_Section(), - new GameStatus_Section(), - new CompileRule_Section(), + new InitializerSettingSection(), + new FolderStructureSection(), + new GameStatusSection(), + new CompileRuleSection(), }; diff --git a/Editor/Core/ProjectSetting/Sections/CompileRule_Section.cs b/Editor/Core/ProjectSetting/Sections/CompileRuleSection.cs similarity index 97% rename from Editor/Core/ProjectSetting/Sections/CompileRule_Section.cs rename to Editor/Core/ProjectSetting/Sections/CompileRuleSection.cs index 875b957..9995922 100644 --- a/Editor/Core/ProjectSetting/Sections/CompileRule_Section.cs +++ b/Editor/Core/ProjectSetting/Sections/CompileRuleSection.cs @@ -3,7 +3,7 @@ namespace RealMethod.Editor { - public class CompileRule_Section : ProjectSettingSection + public class CompileRuleSection : ProjectSettingSection { private class RuleSelector : ArrayTypeSelector { diff --git a/Editor/Core/ProjectSetting/Sections/CompileRule_Section.cs.meta b/Editor/Core/ProjectSetting/Sections/CompileRuleSection.cs.meta similarity index 100% rename from Editor/Core/ProjectSetting/Sections/CompileRule_Section.cs.meta rename to Editor/Core/ProjectSetting/Sections/CompileRuleSection.cs.meta diff --git a/Editor/Core/ProjectSetting/Sections/FolderStructure_Section.cs b/Editor/Core/ProjectSetting/Sections/FolderStructureSection.cs similarity index 98% rename from Editor/Core/ProjectSetting/Sections/FolderStructure_Section.cs rename to Editor/Core/ProjectSetting/Sections/FolderStructureSection.cs index 503cf2d..9771a35 100644 --- a/Editor/Core/ProjectSetting/Sections/FolderStructure_Section.cs +++ b/Editor/Core/ProjectSetting/Sections/FolderStructureSection.cs @@ -3,7 +3,7 @@ namespace RealMethod.Editor { - public class FolderStructure_Section : ProjectSettingSection + public class FolderStructureSection : ProjectSettingSection { private ProjectSettingAsset MyStorage; private bool isPanelMaximize = false; // Add a toggle for minimizing the panel diff --git a/Editor/Core/ProjectSetting/Sections/FolderStructure_Section.cs.meta b/Editor/Core/ProjectSetting/Sections/FolderStructureSection.cs.meta similarity index 100% rename from Editor/Core/ProjectSetting/Sections/FolderStructure_Section.cs.meta rename to Editor/Core/ProjectSetting/Sections/FolderStructureSection.cs.meta diff --git a/Editor/Core/ProjectSetting/Sections/GameStatus_Section.cs b/Editor/Core/ProjectSetting/Sections/GameStatusSection.cs similarity index 97% rename from Editor/Core/ProjectSetting/Sections/GameStatus_Section.cs rename to Editor/Core/ProjectSetting/Sections/GameStatusSection.cs index d69423b..87b7dd3 100644 --- a/Editor/Core/ProjectSetting/Sections/GameStatus_Section.cs +++ b/Editor/Core/ProjectSetting/Sections/GameStatusSection.cs @@ -5,7 +5,7 @@ namespace RealMethod.Editor { - public class GameStatus_Section : ProjectSettingSection + public class GameStatusSection : ProjectSettingSection { private ProjectSettingAsset SettingAsset; private SerializedObject projectSettings; diff --git a/Editor/Core/ProjectSetting/Sections/GameStatus_Section.cs.meta b/Editor/Core/ProjectSetting/Sections/GameStatusSection.cs.meta similarity index 100% rename from Editor/Core/ProjectSetting/Sections/GameStatus_Section.cs.meta rename to Editor/Core/ProjectSetting/Sections/GameStatusSection.cs.meta diff --git a/Editor/Core/ProjectSetting/Sections/InitializerSetting_Section.cs b/Editor/Core/ProjectSetting/Sections/InitializerSettingSection.cs similarity index 97% rename from Editor/Core/ProjectSetting/Sections/InitializerSetting_Section.cs rename to Editor/Core/ProjectSetting/Sections/InitializerSettingSection.cs index b3e7bb7..5bcdfda 100644 --- a/Editor/Core/ProjectSetting/Sections/InitializerSetting_Section.cs +++ b/Editor/Core/ProjectSetting/Sections/InitializerSettingSection.cs @@ -3,7 +3,7 @@ namespace RealMethod.Editor { - public class InitializerSetting_Section : ProjectSettingSection + public class InitializerSettingSection : ProjectSettingSection { private TypeSelector gameClass; private TypeSelector gameBridge; diff --git a/Editor/Core/ProjectSetting/Sections/InitializerSetting_Section.cs.meta b/Editor/Core/ProjectSetting/Sections/InitializerSettingSection.cs.meta similarity index 100% rename from Editor/Core/ProjectSetting/Sections/InitializerSetting_Section.cs.meta rename to Editor/Core/ProjectSetting/Sections/InitializerSettingSection.cs.meta From 525a78191a1b2e22bcfb0d6c31a1be321c860855 Mon Sep 17 00:00:00 2001 From: Alijimpa Date: Fri, 17 Apr 2026 08:07:59 +0330 Subject: [PATCH 106/204] Rename Message cont Name --- .../Rules/PrimitveAssetsRule.cs | 4 +- .../{GameMessage.cs => GameNameConstants.cs} | 15 +++- ...sage.cs.meta => GameNameConstants.cs.meta} | 0 Runtime/Library/Extension/Component.cs | 8 +- Runtime/Library/Extension/GameObject.cs | 22 +++--- Runtime/Library/Extension/ScriptableObject.cs | 8 +- Tests/Events.cs | 76 +++++++++++++++++++ Tests/Events.cs.meta | 2 + 8 files changed, 112 insertions(+), 23 deletions(-) rename Runtime/Core/Definitions/{GameMessage.cs => GameNameConstants.cs} (74%) rename Runtime/Core/Definitions/{GameMessage.cs.meta => GameNameConstants.cs.meta} (100%) create mode 100644 Tests/Events.cs create mode 100644 Tests/Events.cs.meta diff --git a/Editor/Core/InitializeOnLoad/Rules/PrimitveAssetsRule.cs b/Editor/Core/InitializeOnLoad/Rules/PrimitveAssetsRule.cs index 7c89316..2fb2a16 100644 --- a/Editor/Core/InitializeOnLoad/Rules/PrimitveAssetsRule.cs +++ b/Editor/Core/InitializeOnLoad/Rules/PrimitveAssetsRule.cs @@ -23,7 +23,7 @@ public override void OnStartCheck(RuleExecutionMode mode) if (mode == RuleExecutionMode.EnteredPlayMode) { if (asset is not DataAsset) - asset.Invoke(GameMessage.AssetPermission); + asset.Invoke(FunctionNames.AssetPermission); if (AssetDatabase.Contains(asset)) { @@ -38,7 +38,7 @@ public override void OnStartCheck(RuleExecutionMode mode) if (asset.AutoReset(CurrentMode)) { - asset.Invoke(GameMessage.Reset); + asset.Invoke(FunctionNames.Reset); } } } diff --git a/Runtime/Core/Definitions/GameMessage.cs b/Runtime/Core/Definitions/GameNameConstants.cs similarity index 74% rename from Runtime/Core/Definitions/GameMessage.cs rename to Runtime/Core/Definitions/GameNameConstants.cs index 744ec14..75cc4c8 100644 --- a/Runtime/Core/Definitions/GameMessage.cs +++ b/Runtime/Core/Definitions/GameNameConstants.cs @@ -1,14 +1,25 @@ namespace RealMethod { - public static class GameMessage + public static class MessageNames { + // Lifecycle public const string Spawn = "OnSpawn"; public const string Despawn = "OnDespawn"; - public const string ApplyDamage = "OnTakeDamage"; public const string Die = "OnDie"; + + // Combat + public const string ApplyDamage = "OnTakeDamage"; + + // Attachment public const string Attach = "OnAttach"; public const string Detach = "OnDetach"; + + // Misc public const string Share = "OnShare"; + } + + public static class FunctionNames + { public const string AssetPermission = "EnsureAssetPermission"; public const string Reset = "Reset"; } diff --git a/Runtime/Core/Definitions/GameMessage.cs.meta b/Runtime/Core/Definitions/GameNameConstants.cs.meta similarity index 100% rename from Runtime/Core/Definitions/GameMessage.cs.meta rename to Runtime/Core/Definitions/GameNameConstants.cs.meta diff --git a/Runtime/Library/Extension/Component.cs b/Runtime/Library/Extension/Component.cs index f0ba125..b7e5bea 100644 --- a/Runtime/Library/Extension/Component.cs +++ b/Runtime/Library/Extension/Component.cs @@ -14,7 +14,7 @@ public static void InvokeSpawnEvent(this Component owner, Object spawner = null, } else { - owner.SendMessage(GameMessage.Spawn, spawner, option); + owner.SendMessage(MessageNames.Spawn, spawner, option); } } else @@ -25,7 +25,7 @@ public static void InvokeSpawnEvent(this Component owner, Object spawner = null, } else { - owner.SendMessage(GameMessage.Spawn, option); + owner.SendMessage(MessageNames.Spawn, option); } } } @@ -39,7 +39,7 @@ public static void InvokeDespawnEvent(this Component owner, Object despawner = n } else { - owner.SendMessage(GameMessage.Despawn, despawner, option); + owner.SendMessage(MessageNames.Despawn, despawner, option); } } else @@ -50,7 +50,7 @@ public static void InvokeDespawnEvent(this Component owner, Object despawner = n } else { - owner.SendMessage(GameMessage.Despawn, option); + owner.SendMessage(MessageNames.Despawn, option); } } } diff --git a/Runtime/Library/Extension/GameObject.cs b/Runtime/Library/Extension/GameObject.cs index 4075d02..03f8602 100644 --- a/Runtime/Library/Extension/GameObject.cs +++ b/Runtime/Library/Extension/GameObject.cs @@ -21,7 +21,7 @@ public static void Death(this GameObject target) } else { - target.SendMessage(GameMessage.Die, SendMessageOptions.RequireReceiver); + target.SendMessage(MessageNames.Die, SendMessageOptions.RequireReceiver); } } /// @@ -43,7 +43,7 @@ public static void ApplyDamage(this GameObject target, HitData hitdata) } else { - target.SendMessage(GameMessage.ApplyDamage, hitdata, SendMessageOptions.RequireReceiver); + target.SendMessage(MessageNames.ApplyDamage, hitdata, SendMessageOptions.RequireReceiver); } } /// @@ -58,7 +58,7 @@ public static void Attach(this GameObject target, Transform parent, Name16 socke { Transform MySocket = parent.GetSocket(socketname); MySocket.SetParent(parent.transform, worldPositionStays); - target.SendMessage(GameMessage.Attach, parent, SendMessageOptions.DontRequireReceiver); + target.SendMessage(MessageNames.Attach, parent, SendMessageOptions.DontRequireReceiver); } /// /// Attaches this GameObject to a specified parent GameObject, optionally preserving world position. @@ -70,7 +70,7 @@ public static void Attach(this GameObject target, Transform parent, Name16 socke public static void Attach(this GameObject target, GameObject parent, bool worldPositionStays = true) { target.transform.SetParent(parent.transform, worldPositionStays); - target.SendMessage(GameMessage.Attach, parent, SendMessageOptions.DontRequireReceiver); + target.SendMessage(MessageNames.Attach, parent, SendMessageOptions.DontRequireReceiver); } /// /// Detaches this GameObject from its current parent and sends an "OnDetach" message. @@ -80,7 +80,7 @@ public static void Attach(this GameObject target, GameObject parent, bool worldP public static void Detach(this GameObject target, GameObject parent) { target.transform.SetParent(null); - target.SendMessage(GameMessage.Detach, SendMessageOptions.DontRequireReceiver); + target.SendMessage(MessageNames.Detach, SendMessageOptions.DontRequireReceiver); } /// /// Sends an "OnSpawn" message to the owner GameObject. @@ -99,7 +99,7 @@ public static void InvokeSpawnEvent(this GameObject owner, Object spawner = null } else { - owner.SendMessage(GameMessage.Spawn, spawner, option); + owner.SendMessage(MessageNames.Spawn, spawner, option); } } else @@ -111,7 +111,7 @@ public static void InvokeSpawnEvent(this GameObject owner, Object spawner = null } else { - owner.SendMessage(GameMessage.Spawn, option); + owner.SendMessage(MessageNames.Spawn, option); } } } @@ -132,7 +132,7 @@ public static void InvokeDespawnEvent(this GameObject owner, Object despawner = } else { - owner.SendMessage(GameMessage.Despawn, despawner, option); + owner.SendMessage(MessageNames.Despawn, despawner, option); } } else @@ -144,7 +144,7 @@ public static void InvokeDespawnEvent(this GameObject owner, Object despawner = } else { - owner.SendMessage(GameMessage.Despawn, option); + owner.SendMessage(MessageNames.Despawn, option); } } } @@ -239,7 +239,7 @@ public static void Share(this GameObject obj , bool safety = true) return; } Game.Bridge.AddSharedObject(obj); - obj.SendMessage(GameMessage.Share, true, SendMessageOptions.DontRequireReceiver); + obj.SendMessage(MessageNames.Share, true, SendMessageOptions.DontRequireReceiver); } /// /// Unregisters the GameObject from the shared object system. @@ -253,7 +253,7 @@ public static void Unshare(this GameObject obj, bool safety = true) return; } Game.Bridge.RemoveSharedObject(obj); - obj.SendMessage(GameMessage.Share, false, SendMessageOptions.DontRequireReceiver); + obj.SendMessage(MessageNames.Share, false, SendMessageOptions.DontRequireReceiver); } /// /// Checks if the GameObject is currently registered in the shared object system. diff --git a/Runtime/Library/Extension/ScriptableObject.cs b/Runtime/Library/Extension/ScriptableObject.cs index e7eb864..07f09df 100644 --- a/Runtime/Library/Extension/ScriptableObject.cs +++ b/Runtime/Library/Extension/ScriptableObject.cs @@ -20,7 +20,7 @@ public static void InvokeSpawnEvent(this ScriptableObject owner, Object spawner } else { - owner.Invoke(GameMessage.Spawn, new object[1] { spawner }); + owner.Invoke(MessageNames.Spawn, new object[1] { spawner }); } } else @@ -31,7 +31,7 @@ public static void InvokeSpawnEvent(this ScriptableObject owner, Object spawner } else { - owner.Invoke(GameMessage.Spawn); + owner.Invoke(MessageNames.Spawn); } } } @@ -50,7 +50,7 @@ public static void InvokeDespawnEvent(this ScriptableObject owner, Object despaw } else { - owner.Invoke(GameMessage.Despawn, new object[1] { despawner }); + owner.Invoke(MessageNames.Despawn, new object[1] { despawner }); } } else @@ -61,7 +61,7 @@ public static void InvokeDespawnEvent(this ScriptableObject owner, Object despaw } else { - owner.Invoke(GameMessage.Despawn); + owner.Invoke(MessageNames.Despawn); } } } diff --git a/Tests/Events.cs b/Tests/Events.cs new file mode 100644 index 0000000..5982055 --- /dev/null +++ b/Tests/Events.cs @@ -0,0 +1,76 @@ +using System; +using System.Collections.Generic; + +public enum GameEvent +{ + Spawn, + Despawn, + Die, + TakeDamage, + Heal, + Attach, + Detach, + Share, + Reset +} + + +public static class EventBus +{ + private static readonly Dictionary> _eventMap = + new Dictionary>(); + + public static void Subscribe(string eventName, Action callback) + { + if (!_eventMap.ContainsKey(eventName)) + _eventMap[eventName] = delegate { }; + + _eventMap[eventName] += callback; + } + + public static void Unsubscribe(string eventName, Action callback) + { + if (_eventMap.ContainsKey(eventName)) + _eventMap[eventName] -= callback; + } + + public static void Raise(string eventName, object payload = null) + { + if (_eventMap.TryGetValue(eventName, out var callbacks)) + callbacks?.Invoke(payload); + } + + public static void Raise(GameEvent ev, object payload = null) + => Raise(ev.ToName(), payload); +} + +// EventBus.Subscribe(GameEvent.Spawn.ToName(), OnSpawn); +// private void OnSpawn(object payload) +// { +// // Handle your event +// } +// EventBus.Raise(GameEvent.Spawn); +// EventBus.Raise(GameEvent.TakeDamage, new DamageInfo { amount = 20 }); + + +public static class GameEventExtensions +{ + public static string ToName(this GameEvent ev) + { + return ev.ToString(); + } +} + +public static class TypedEventBus +{ + private static event Action OnEvent; + + public static void Subscribe(Action callback) => OnEvent += callback; + public static void Unsubscribe(Action callback) => OnEvent -= callback; + + public static void Raise(T payload) => OnEvent?.Invoke(payload); +} + +// TypedEventBus.Subscribe(OnDamage); +// TypedEventBus.Raise(new DamageInfo(25)); + diff --git a/Tests/Events.cs.meta b/Tests/Events.cs.meta new file mode 100644 index 0000000..60c5335 --- /dev/null +++ b/Tests/Events.cs.meta @@ -0,0 +1,2 @@ +fileFormatVersion: 2 +guid: 354ebf6331ef0354c9b72e315428bcfa \ No newline at end of file From 089f6c53104fffdfd935caef9de44d8f682d025f Mon Sep 17 00:00:00 2001 From: Alijimpa Date: Fri, 17 Apr 2026 08:14:42 +0330 Subject: [PATCH 107/204] Rename World Order menu --- .../{WorldExecutionOrderMenu.cs => FixupExecutionMenu.cs} | 4 ++-- ...dExecutionOrderMenu.cs.meta => FixupExecutionMenu.cs.meta} | 0 2 files changed, 2 insertions(+), 2 deletions(-) rename Editor/Core/MenuItem/{WorldExecutionOrderMenu.cs => FixupExecutionMenu.cs} (92%) rename Editor/Core/MenuItem/{WorldExecutionOrderMenu.cs.meta => FixupExecutionMenu.cs.meta} (100%) diff --git a/Editor/Core/MenuItem/WorldExecutionOrderMenu.cs b/Editor/Core/MenuItem/FixupExecutionMenu.cs similarity index 92% rename from Editor/Core/MenuItem/WorldExecutionOrderMenu.cs rename to Editor/Core/MenuItem/FixupExecutionMenu.cs index c6fafe3..bc530f1 100644 --- a/Editor/Core/MenuItem/WorldExecutionOrderMenu.cs +++ b/Editor/Core/MenuItem/FixupExecutionMenu.cs @@ -6,9 +6,9 @@ namespace RealMethod.Editor { - public static class WorldExecutionOrderMenu + public static class FixupExecutionMenu { - [MenuItem("Tools/RealMethod/Core/ExecutionOrder" , priority = -1001)] + [MenuItem("Tools/RealMethod/Core/FixupExecutionOrder" , priority = -1001)] static void ApplyExecutionOrder() { SetExecutionOrderForDerivedTypes(typeof(World), -18); // ← change base class and order here diff --git a/Editor/Core/MenuItem/WorldExecutionOrderMenu.cs.meta b/Editor/Core/MenuItem/FixupExecutionMenu.cs.meta similarity index 100% rename from Editor/Core/MenuItem/WorldExecutionOrderMenu.cs.meta rename to Editor/Core/MenuItem/FixupExecutionMenu.cs.meta From e2b922cb743a63c83a1c40b640478192c9bf717e Mon Sep 17 00:00:00 2001 From: Alijimpa Date: Fri, 17 Apr 2026 08:41:22 +0330 Subject: [PATCH 108/204] Move Some functiion Reame some Scripts --- Editor/Core/Utilities/Editor_Library.cs | 7 ++++++ .../{EditorIcons.cs => EditorIconsMenu.cs} | 4 ++-- ...rIcons.cs.meta => EditorIconsMenu.cs.meta} | 0 Editor/Pattern/Scripts.meta | 8 +++++++ .../Scripts}/AssetProcess.cs | 0 .../Scripts}/AssetProcess.cs.meta | 0 Runtime/Library/Utilities/Game_Library.cs | 22 ------------------- .../Library/Utilities/Game_Library.cs.meta | 2 -- 8 files changed, 17 insertions(+), 26 deletions(-) rename Editor/Library/MenuItem/{EditorIcons.cs => EditorIconsMenu.cs} (99%) rename Editor/Library/MenuItem/{EditorIcons.cs.meta => EditorIconsMenu.cs.meta} (100%) create mode 100644 Editor/Pattern/Scripts.meta rename Editor/{Library/SharedScripts/Classes => Pattern/Scripts}/AssetProcess.cs (100%) rename Editor/{Library/SharedScripts/Classes => Pattern/Scripts}/AssetProcess.cs.meta (100%) delete mode 100644 Runtime/Library/Utilities/Game_Library.cs delete mode 100644 Runtime/Library/Utilities/Game_Library.cs.meta diff --git a/Editor/Core/Utilities/Editor_Library.cs b/Editor/Core/Utilities/Editor_Library.cs index 68347e9..8ebe688 100644 --- a/Editor/Core/Utilities/Editor_Library.cs +++ b/Editor/Core/Utilities/Editor_Library.cs @@ -10,6 +10,13 @@ public static class RM_Editor public static string ScriptTemplatesPath => GetPackagePath("com.mustard.realmethod") + "/Reservoir/ScriptTemplates"; public static string PrefabTemplatePath => GetPackagePath("com.mustard.realmethod") + "/Reservoir/Prefabs"; public static string Documentation => GetPackagePath("com.mustard.realmethod") + "/Documentation/Information"; + public static bool IsPlayMode + { + get + { + return EditorApplication.isPlaying && EditorApplication.isPlayingOrWillChangePlaymode == false; + } + } public static bool TryGetSettingAsset(out ProjectSettingAsset settings) { diff --git a/Editor/Library/MenuItem/EditorIcons.cs b/Editor/Library/MenuItem/EditorIconsMenu.cs similarity index 99% rename from Editor/Library/MenuItem/EditorIcons.cs rename to Editor/Library/MenuItem/EditorIconsMenu.cs index 8c72e7e..bd071a8 100644 --- a/Editor/Library/MenuItem/EditorIcons.cs +++ b/Editor/Library/MenuItem/EditorIconsMenu.cs @@ -10,7 +10,7 @@ namespace RealMethod.Editor { #if UNITY_EDITOR - public class EditorIcons : EditorWindow + public class EditorIconsMenu : EditorWindow { [MenuItem("Tools/RealMethod/Vendor/EditorIcons")] public static void EditorIconsOpen() @@ -18,7 +18,7 @@ public static void EditorIconsOpen() #if UNITY_2018 var w = GetWindow("Editor Icons"); #else - var w = CreateWindow("Editor Icons"); + var w = CreateWindow("Editor Icons"); #endif w.ShowUtility(); w.minSize = new Vector2(320, 450); diff --git a/Editor/Library/MenuItem/EditorIcons.cs.meta b/Editor/Library/MenuItem/EditorIconsMenu.cs.meta similarity index 100% rename from Editor/Library/MenuItem/EditorIcons.cs.meta rename to Editor/Library/MenuItem/EditorIconsMenu.cs.meta diff --git a/Editor/Pattern/Scripts.meta b/Editor/Pattern/Scripts.meta new file mode 100644 index 0000000..e2c4f1f --- /dev/null +++ b/Editor/Pattern/Scripts.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: f5cd3bfd4d154e541a2b99bc9161a185 +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Editor/Library/SharedScripts/Classes/AssetProcess.cs b/Editor/Pattern/Scripts/AssetProcess.cs similarity index 100% rename from Editor/Library/SharedScripts/Classes/AssetProcess.cs rename to Editor/Pattern/Scripts/AssetProcess.cs diff --git a/Editor/Library/SharedScripts/Classes/AssetProcess.cs.meta b/Editor/Pattern/Scripts/AssetProcess.cs.meta similarity index 100% rename from Editor/Library/SharedScripts/Classes/AssetProcess.cs.meta rename to Editor/Pattern/Scripts/AssetProcess.cs.meta diff --git a/Runtime/Library/Utilities/Game_Library.cs b/Runtime/Library/Utilities/Game_Library.cs deleted file mode 100644 index fa1edf8..0000000 --- a/Runtime/Library/Utilities/Game_Library.cs +++ /dev/null @@ -1,22 +0,0 @@ -#if UNITY_EDITOR -using UnityEditor; -#endif -using UnityEngine; - -namespace RealMethod -{ - public static class RM_Game - { - public static bool IsPlaying - { - get - { -#if UNITY_EDITOR - return EditorApplication.isPlaying && EditorApplication.isPlayingOrWillChangePlaymode == false; -#else - return Application.isPlaying; // Runtime fallback -#endif - } - } - } -} \ No newline at end of file diff --git a/Runtime/Library/Utilities/Game_Library.cs.meta b/Runtime/Library/Utilities/Game_Library.cs.meta deleted file mode 100644 index 82a35f3..0000000 --- a/Runtime/Library/Utilities/Game_Library.cs.meta +++ /dev/null @@ -1,2 +0,0 @@ -fileFormatVersion: 2 -guid: e6d999204daa40649b779c0253b21ef7 \ No newline at end of file From 3133ed2fc66ccf63f23ac4a2e60637eff4330bee Mon Sep 17 00:00:00 2001 From: Alijimpa Date: Fri, 17 Apr 2026 09:32:58 +0330 Subject: [PATCH 109/204] Rename All Library Classes --- Editor/Library/Utilities/{Assets_Library.cs => AssetsLibrary.cs} | 0 .../Utilities/{Assets_Library.cs.meta => AssetsLibrary.cs.meta} | 0 Editor/Library/Utilities/{CSV_Library.cs => CSVLibrary.cs} | 0 .../Library/Utilities/{CSV_Library.cs.meta => CSVLibrary.cs.meta} | 0 Editor/Library/Utilities/{Create_Library.cs => CreateLibrary.cs} | 0 .../Utilities/{Create_Library.cs.meta => CreateLibrary.cs.meta} | 0 .../Library/Utilities/{MetaData_Library.cs => MetaDataLibrary.cs} | 0 .../{MetaData_Library.cs.meta => MetaDataLibrary.cs.meta} | 0 .../Utilities/{Animation_Library.cs => AnimationLibrary.cs} | 0 .../{Animation_Library.cs.meta => AnimationLibrary.cs.meta} | 0 Runtime/Library/Utilities/{Array_Library.cs => ArrayLibrary.cs} | 0 .../Utilities/{Array_Library.cs.meta => ArrayLibrary.cs.meta} | 0 Runtime/Library/Utilities/{Audio_Library.cs => AudioLibrary.cs} | 0 .../Utilities/{Audio_Library.cs.meta => AudioLibrary.cs.meta} | 0 .../Utilities/{Collection_Library.cs => CollectionLibrary.cs} | 0 .../{Collection_Library.cs.meta => CollectionLibrary.cs.meta} | 0 Runtime/Library/Utilities/{Debug_Library.cs => DebugLibrary.cs} | 0 .../Utilities/{Debug_Library.cs.meta => DebugLibrary.cs.meta} | 0 Runtime/Library/Utilities/{Enum_Library.cs => EnumLibrary.cs} | 0 .../Utilities/{Enum_Library.cs.meta => EnumLibrary.cs.meta} | 0 Runtime/Library/Utilities/{File_Library.cs => FileLibrary.cs} | 0 .../Utilities/{File_Library.cs.meta => FileLibrary.cs.meta} | 0 Runtime/Library/Utilities/{Gizmos_Library.cs => GizmosLibrary.cs} | 0 .../Utilities/{Gizmos_Library.cs.meta => GizmosLibrary.cs.meta} | 0 Runtime/Library/Utilities/{Math_Library.cs => MathLibrary.cs} | 0 .../Utilities/{Math_Library.cs.meta => MathLibrary.cs.meta} | 0 .../Utilities/{Reflection_Library.cs => ReflectionLibrary.cs} | 0 .../{Reflection_Library.cs.meta => ReflectionLibrary.cs.meta} | 0 Runtime/Library/Utilities/{Save_Library.cs => SaveLibrary.cs} | 0 .../Utilities/{Save_Library.cs.meta => SaveLibrary.cs.meta} | 0 Runtime/Library/Utilities/{Time_Library.cs => TimeLibrary.cs} | 0 .../Utilities/{Time_Library.cs.meta => TimeLibrary.cs.meta} | 0 Runtime/Library/Utilities/{Trace_Library.cs => TraceLibrary.cs} | 0 .../Utilities/{Trace_Library.cs.meta => TraceLibrary.cs.meta} | 0 .../Utilities/{Transform_Library.cs => TransformLibrary.cs} | 0 .../{Transform_Library.cs.meta => TransformLibrary.cs.meta} | 0 Runtime/Library/Utilities/{Tween_Library.cs => TweenLibrary.cs} | 0 .../Utilities/{Tween_Library.cs.meta => TweenLibrary.cs.meta} | 0 Runtime/Library/Utilities/{UI_Library.cs => UILibrary.cs} | 0 .../Library/Utilities/{UI_Library.cs.meta => UILibrary.cs.meta} | 0 Runtime/Library/Utilities/{Vector_Library.cs => VectorLibrary.cs} | 0 .../Utilities/{Vector_Library.cs.meta => VectorLibrary.cs.meta} | 0 42 files changed, 0 insertions(+), 0 deletions(-) rename Editor/Library/Utilities/{Assets_Library.cs => AssetsLibrary.cs} (100%) rename Editor/Library/Utilities/{Assets_Library.cs.meta => AssetsLibrary.cs.meta} (100%) rename Editor/Library/Utilities/{CSV_Library.cs => CSVLibrary.cs} (100%) rename Editor/Library/Utilities/{CSV_Library.cs.meta => CSVLibrary.cs.meta} (100%) rename Editor/Library/Utilities/{Create_Library.cs => CreateLibrary.cs} (100%) rename Editor/Library/Utilities/{Create_Library.cs.meta => CreateLibrary.cs.meta} (100%) rename Editor/Library/Utilities/{MetaData_Library.cs => MetaDataLibrary.cs} (100%) rename Editor/Library/Utilities/{MetaData_Library.cs.meta => MetaDataLibrary.cs.meta} (100%) rename Runtime/Library/Utilities/{Animation_Library.cs => AnimationLibrary.cs} (100%) rename Runtime/Library/Utilities/{Animation_Library.cs.meta => AnimationLibrary.cs.meta} (100%) rename Runtime/Library/Utilities/{Array_Library.cs => ArrayLibrary.cs} (100%) rename Runtime/Library/Utilities/{Array_Library.cs.meta => ArrayLibrary.cs.meta} (100%) rename Runtime/Library/Utilities/{Audio_Library.cs => AudioLibrary.cs} (100%) rename Runtime/Library/Utilities/{Audio_Library.cs.meta => AudioLibrary.cs.meta} (100%) rename Runtime/Library/Utilities/{Collection_Library.cs => CollectionLibrary.cs} (100%) rename Runtime/Library/Utilities/{Collection_Library.cs.meta => CollectionLibrary.cs.meta} (100%) rename Runtime/Library/Utilities/{Debug_Library.cs => DebugLibrary.cs} (100%) rename Runtime/Library/Utilities/{Debug_Library.cs.meta => DebugLibrary.cs.meta} (100%) rename Runtime/Library/Utilities/{Enum_Library.cs => EnumLibrary.cs} (100%) rename Runtime/Library/Utilities/{Enum_Library.cs.meta => EnumLibrary.cs.meta} (100%) rename Runtime/Library/Utilities/{File_Library.cs => FileLibrary.cs} (100%) rename Runtime/Library/Utilities/{File_Library.cs.meta => FileLibrary.cs.meta} (100%) rename Runtime/Library/Utilities/{Gizmos_Library.cs => GizmosLibrary.cs} (100%) rename Runtime/Library/Utilities/{Gizmos_Library.cs.meta => GizmosLibrary.cs.meta} (100%) rename Runtime/Library/Utilities/{Math_Library.cs => MathLibrary.cs} (100%) rename Runtime/Library/Utilities/{Math_Library.cs.meta => MathLibrary.cs.meta} (100%) rename Runtime/Library/Utilities/{Reflection_Library.cs => ReflectionLibrary.cs} (100%) rename Runtime/Library/Utilities/{Reflection_Library.cs.meta => ReflectionLibrary.cs.meta} (100%) rename Runtime/Library/Utilities/{Save_Library.cs => SaveLibrary.cs} (100%) rename Runtime/Library/Utilities/{Save_Library.cs.meta => SaveLibrary.cs.meta} (100%) rename Runtime/Library/Utilities/{Time_Library.cs => TimeLibrary.cs} (100%) rename Runtime/Library/Utilities/{Time_Library.cs.meta => TimeLibrary.cs.meta} (100%) rename Runtime/Library/Utilities/{Trace_Library.cs => TraceLibrary.cs} (100%) rename Runtime/Library/Utilities/{Trace_Library.cs.meta => TraceLibrary.cs.meta} (100%) rename Runtime/Library/Utilities/{Transform_Library.cs => TransformLibrary.cs} (100%) rename Runtime/Library/Utilities/{Transform_Library.cs.meta => TransformLibrary.cs.meta} (100%) rename Runtime/Library/Utilities/{Tween_Library.cs => TweenLibrary.cs} (100%) rename Runtime/Library/Utilities/{Tween_Library.cs.meta => TweenLibrary.cs.meta} (100%) rename Runtime/Library/Utilities/{UI_Library.cs => UILibrary.cs} (100%) rename Runtime/Library/Utilities/{UI_Library.cs.meta => UILibrary.cs.meta} (100%) rename Runtime/Library/Utilities/{Vector_Library.cs => VectorLibrary.cs} (100%) rename Runtime/Library/Utilities/{Vector_Library.cs.meta => VectorLibrary.cs.meta} (100%) diff --git a/Editor/Library/Utilities/Assets_Library.cs b/Editor/Library/Utilities/AssetsLibrary.cs similarity index 100% rename from Editor/Library/Utilities/Assets_Library.cs rename to Editor/Library/Utilities/AssetsLibrary.cs diff --git a/Editor/Library/Utilities/Assets_Library.cs.meta b/Editor/Library/Utilities/AssetsLibrary.cs.meta similarity index 100% rename from Editor/Library/Utilities/Assets_Library.cs.meta rename to Editor/Library/Utilities/AssetsLibrary.cs.meta diff --git a/Editor/Library/Utilities/CSV_Library.cs b/Editor/Library/Utilities/CSVLibrary.cs similarity index 100% rename from Editor/Library/Utilities/CSV_Library.cs rename to Editor/Library/Utilities/CSVLibrary.cs diff --git a/Editor/Library/Utilities/CSV_Library.cs.meta b/Editor/Library/Utilities/CSVLibrary.cs.meta similarity index 100% rename from Editor/Library/Utilities/CSV_Library.cs.meta rename to Editor/Library/Utilities/CSVLibrary.cs.meta diff --git a/Editor/Library/Utilities/Create_Library.cs b/Editor/Library/Utilities/CreateLibrary.cs similarity index 100% rename from Editor/Library/Utilities/Create_Library.cs rename to Editor/Library/Utilities/CreateLibrary.cs diff --git a/Editor/Library/Utilities/Create_Library.cs.meta b/Editor/Library/Utilities/CreateLibrary.cs.meta similarity index 100% rename from Editor/Library/Utilities/Create_Library.cs.meta rename to Editor/Library/Utilities/CreateLibrary.cs.meta diff --git a/Editor/Library/Utilities/MetaData_Library.cs b/Editor/Library/Utilities/MetaDataLibrary.cs similarity index 100% rename from Editor/Library/Utilities/MetaData_Library.cs rename to Editor/Library/Utilities/MetaDataLibrary.cs diff --git a/Editor/Library/Utilities/MetaData_Library.cs.meta b/Editor/Library/Utilities/MetaDataLibrary.cs.meta similarity index 100% rename from Editor/Library/Utilities/MetaData_Library.cs.meta rename to Editor/Library/Utilities/MetaDataLibrary.cs.meta diff --git a/Runtime/Library/Utilities/Animation_Library.cs b/Runtime/Library/Utilities/AnimationLibrary.cs similarity index 100% rename from Runtime/Library/Utilities/Animation_Library.cs rename to Runtime/Library/Utilities/AnimationLibrary.cs diff --git a/Runtime/Library/Utilities/Animation_Library.cs.meta b/Runtime/Library/Utilities/AnimationLibrary.cs.meta similarity index 100% rename from Runtime/Library/Utilities/Animation_Library.cs.meta rename to Runtime/Library/Utilities/AnimationLibrary.cs.meta diff --git a/Runtime/Library/Utilities/Array_Library.cs b/Runtime/Library/Utilities/ArrayLibrary.cs similarity index 100% rename from Runtime/Library/Utilities/Array_Library.cs rename to Runtime/Library/Utilities/ArrayLibrary.cs diff --git a/Runtime/Library/Utilities/Array_Library.cs.meta b/Runtime/Library/Utilities/ArrayLibrary.cs.meta similarity index 100% rename from Runtime/Library/Utilities/Array_Library.cs.meta rename to Runtime/Library/Utilities/ArrayLibrary.cs.meta diff --git a/Runtime/Library/Utilities/Audio_Library.cs b/Runtime/Library/Utilities/AudioLibrary.cs similarity index 100% rename from Runtime/Library/Utilities/Audio_Library.cs rename to Runtime/Library/Utilities/AudioLibrary.cs diff --git a/Runtime/Library/Utilities/Audio_Library.cs.meta b/Runtime/Library/Utilities/AudioLibrary.cs.meta similarity index 100% rename from Runtime/Library/Utilities/Audio_Library.cs.meta rename to Runtime/Library/Utilities/AudioLibrary.cs.meta diff --git a/Runtime/Library/Utilities/Collection_Library.cs b/Runtime/Library/Utilities/CollectionLibrary.cs similarity index 100% rename from Runtime/Library/Utilities/Collection_Library.cs rename to Runtime/Library/Utilities/CollectionLibrary.cs diff --git a/Runtime/Library/Utilities/Collection_Library.cs.meta b/Runtime/Library/Utilities/CollectionLibrary.cs.meta similarity index 100% rename from Runtime/Library/Utilities/Collection_Library.cs.meta rename to Runtime/Library/Utilities/CollectionLibrary.cs.meta diff --git a/Runtime/Library/Utilities/Debug_Library.cs b/Runtime/Library/Utilities/DebugLibrary.cs similarity index 100% rename from Runtime/Library/Utilities/Debug_Library.cs rename to Runtime/Library/Utilities/DebugLibrary.cs diff --git a/Runtime/Library/Utilities/Debug_Library.cs.meta b/Runtime/Library/Utilities/DebugLibrary.cs.meta similarity index 100% rename from Runtime/Library/Utilities/Debug_Library.cs.meta rename to Runtime/Library/Utilities/DebugLibrary.cs.meta diff --git a/Runtime/Library/Utilities/Enum_Library.cs b/Runtime/Library/Utilities/EnumLibrary.cs similarity index 100% rename from Runtime/Library/Utilities/Enum_Library.cs rename to Runtime/Library/Utilities/EnumLibrary.cs diff --git a/Runtime/Library/Utilities/Enum_Library.cs.meta b/Runtime/Library/Utilities/EnumLibrary.cs.meta similarity index 100% rename from Runtime/Library/Utilities/Enum_Library.cs.meta rename to Runtime/Library/Utilities/EnumLibrary.cs.meta diff --git a/Runtime/Library/Utilities/File_Library.cs b/Runtime/Library/Utilities/FileLibrary.cs similarity index 100% rename from Runtime/Library/Utilities/File_Library.cs rename to Runtime/Library/Utilities/FileLibrary.cs diff --git a/Runtime/Library/Utilities/File_Library.cs.meta b/Runtime/Library/Utilities/FileLibrary.cs.meta similarity index 100% rename from Runtime/Library/Utilities/File_Library.cs.meta rename to Runtime/Library/Utilities/FileLibrary.cs.meta diff --git a/Runtime/Library/Utilities/Gizmos_Library.cs b/Runtime/Library/Utilities/GizmosLibrary.cs similarity index 100% rename from Runtime/Library/Utilities/Gizmos_Library.cs rename to Runtime/Library/Utilities/GizmosLibrary.cs diff --git a/Runtime/Library/Utilities/Gizmos_Library.cs.meta b/Runtime/Library/Utilities/GizmosLibrary.cs.meta similarity index 100% rename from Runtime/Library/Utilities/Gizmos_Library.cs.meta rename to Runtime/Library/Utilities/GizmosLibrary.cs.meta diff --git a/Runtime/Library/Utilities/Math_Library.cs b/Runtime/Library/Utilities/MathLibrary.cs similarity index 100% rename from Runtime/Library/Utilities/Math_Library.cs rename to Runtime/Library/Utilities/MathLibrary.cs diff --git a/Runtime/Library/Utilities/Math_Library.cs.meta b/Runtime/Library/Utilities/MathLibrary.cs.meta similarity index 100% rename from Runtime/Library/Utilities/Math_Library.cs.meta rename to Runtime/Library/Utilities/MathLibrary.cs.meta diff --git a/Runtime/Library/Utilities/Reflection_Library.cs b/Runtime/Library/Utilities/ReflectionLibrary.cs similarity index 100% rename from Runtime/Library/Utilities/Reflection_Library.cs rename to Runtime/Library/Utilities/ReflectionLibrary.cs diff --git a/Runtime/Library/Utilities/Reflection_Library.cs.meta b/Runtime/Library/Utilities/ReflectionLibrary.cs.meta similarity index 100% rename from Runtime/Library/Utilities/Reflection_Library.cs.meta rename to Runtime/Library/Utilities/ReflectionLibrary.cs.meta diff --git a/Runtime/Library/Utilities/Save_Library.cs b/Runtime/Library/Utilities/SaveLibrary.cs similarity index 100% rename from Runtime/Library/Utilities/Save_Library.cs rename to Runtime/Library/Utilities/SaveLibrary.cs diff --git a/Runtime/Library/Utilities/Save_Library.cs.meta b/Runtime/Library/Utilities/SaveLibrary.cs.meta similarity index 100% rename from Runtime/Library/Utilities/Save_Library.cs.meta rename to Runtime/Library/Utilities/SaveLibrary.cs.meta diff --git a/Runtime/Library/Utilities/Time_Library.cs b/Runtime/Library/Utilities/TimeLibrary.cs similarity index 100% rename from Runtime/Library/Utilities/Time_Library.cs rename to Runtime/Library/Utilities/TimeLibrary.cs diff --git a/Runtime/Library/Utilities/Time_Library.cs.meta b/Runtime/Library/Utilities/TimeLibrary.cs.meta similarity index 100% rename from Runtime/Library/Utilities/Time_Library.cs.meta rename to Runtime/Library/Utilities/TimeLibrary.cs.meta diff --git a/Runtime/Library/Utilities/Trace_Library.cs b/Runtime/Library/Utilities/TraceLibrary.cs similarity index 100% rename from Runtime/Library/Utilities/Trace_Library.cs rename to Runtime/Library/Utilities/TraceLibrary.cs diff --git a/Runtime/Library/Utilities/Trace_Library.cs.meta b/Runtime/Library/Utilities/TraceLibrary.cs.meta similarity index 100% rename from Runtime/Library/Utilities/Trace_Library.cs.meta rename to Runtime/Library/Utilities/TraceLibrary.cs.meta diff --git a/Runtime/Library/Utilities/Transform_Library.cs b/Runtime/Library/Utilities/TransformLibrary.cs similarity index 100% rename from Runtime/Library/Utilities/Transform_Library.cs rename to Runtime/Library/Utilities/TransformLibrary.cs diff --git a/Runtime/Library/Utilities/Transform_Library.cs.meta b/Runtime/Library/Utilities/TransformLibrary.cs.meta similarity index 100% rename from Runtime/Library/Utilities/Transform_Library.cs.meta rename to Runtime/Library/Utilities/TransformLibrary.cs.meta diff --git a/Runtime/Library/Utilities/Tween_Library.cs b/Runtime/Library/Utilities/TweenLibrary.cs similarity index 100% rename from Runtime/Library/Utilities/Tween_Library.cs rename to Runtime/Library/Utilities/TweenLibrary.cs diff --git a/Runtime/Library/Utilities/Tween_Library.cs.meta b/Runtime/Library/Utilities/TweenLibrary.cs.meta similarity index 100% rename from Runtime/Library/Utilities/Tween_Library.cs.meta rename to Runtime/Library/Utilities/TweenLibrary.cs.meta diff --git a/Runtime/Library/Utilities/UI_Library.cs b/Runtime/Library/Utilities/UILibrary.cs similarity index 100% rename from Runtime/Library/Utilities/UI_Library.cs rename to Runtime/Library/Utilities/UILibrary.cs diff --git a/Runtime/Library/Utilities/UI_Library.cs.meta b/Runtime/Library/Utilities/UILibrary.cs.meta similarity index 100% rename from Runtime/Library/Utilities/UI_Library.cs.meta rename to Runtime/Library/Utilities/UILibrary.cs.meta diff --git a/Runtime/Library/Utilities/Vector_Library.cs b/Runtime/Library/Utilities/VectorLibrary.cs similarity index 100% rename from Runtime/Library/Utilities/Vector_Library.cs rename to Runtime/Library/Utilities/VectorLibrary.cs diff --git a/Runtime/Library/Utilities/Vector_Library.cs.meta b/Runtime/Library/Utilities/VectorLibrary.cs.meta similarity index 100% rename from Runtime/Library/Utilities/Vector_Library.cs.meta rename to Runtime/Library/Utilities/VectorLibrary.cs.meta From 6c108c96f343634bc152f34523413249b97ef779 Mon Sep 17 00:00:00 2001 From: Alijimpa Date: Sat, 18 Apr 2026 15:50:16 +0330 Subject: [PATCH 110/204] Refine Sorting script file and exitors meethods --- .../Rules/PrimitveAssetsRule.cs | 2 +- Editor/Core/MenuItem/CoreMenu.cs | 120 +++++++++ Editor/Core/MenuItem/CoreMenu.cs.meta | 2 + Editor/Core/Utilities/Editor_Library.cs | 119 +++++---- ...CompWindow.cs => CompositManagerEditor.cs} | 2 +- ....cs.meta => CompositManagerEditor.cs.meta} | 0 ...agerCompWindow.cs => DataManagerEditor.cs} | 2 +- ...ndow.cs.meta => DataManagerEditor.cs.meta} | 0 ...FactoryEditor.cs => FactoryAssetEditor.cs} | 2 +- ...tor.cs.meta => FactoryAssetEditor.cs.meta} | 0 ...ResourcEditor.cs => ResourcAssetEditor.cs} | 2 +- ...tor.cs.meta => ResourcAssetEditor.cs.meta} | 0 ...agerCompWindow.cs => TaskManagerEditor.cs} | 2 +- ...ndow.cs.meta => TaskManagerEditor.cs.meta} | 0 Editor/Pattern/MenuItem.meta | 8 + Editor/Pattern/MenuItem/PatternMenu.cs | 143 +++++++++++ Editor/Pattern/MenuItem/PatternMenu.cs.meta | 2 + .../ReadySet/Content/RealMethod_GameObject.cs | 45 ---- .../Content/RealMethod_GameObject.cs.meta | 2 - .../Content/RealMethod_ScriptTemplate.cs | 227 ------------------ .../Content/RealMethod_ScriptTemplate.cs.meta | 2 - Editor/Toolkit/Ability/AbilityMenu.cs | 27 +++ ...ptTemplate.cs.meta => AbilityMenu.cs.meta} | 0 .../Toolkit/Ability/Ability_ScriptTemplate.cs | 23 -- Editor/Toolkit/Actor/ActorMenu.cs | 16 ++ ...riptTemplate.cs.meta => ActorMenu.cs.meta} | 0 Editor/Toolkit/Actor/Actor_ScriptTemplate.cs | 13 - Editor/Toolkit/Inventory/InventoryMenu.cs | 16 ++ ...Template.cs.meta => InventoryMenu.cs.meta} | 0 .../Inventory/Inventory_ScriptTemplate.cs | 13 - Editor/Toolkit/PCG/PCGMenu.cs | 15 ++ ...ScriptTemplate.cs.meta => PCGMenu.cs.meta} | 0 Editor/Toolkit/PCG/PCG_ScriptTemplate.cs | 13 - Editor/Toolkit/Pickup/PickupMenu.cs | 21 ++ ...iptTemplate.cs.meta => PickupMenu.cs.meta} | 0 .../Toolkit/Pickup/Pickup_ScriptTemplate.cs | 18 -- Editor/Toolkit/RPG/RPGMenu.cs | 33 +++ ...ScriptTemplate.cs.meta => RPGMenu.cs.meta} | 0 Editor/Toolkit/RPG/RPG_ScriptTemplate.cs | 29 --- Editor/Toolkit/Tutorial/TutorialMenu.cs | 26 ++ ...tTemplate.cs.meta => TutorialMenu.cs.meta} | 0 .../Tutorial/Tutorial_ScriptTemplate.cs | 25 -- Editor/Toolkit/Upgrade/UpgradeMenu.cs | 22 ++ ...ptTemplate.cs.meta => UpgradeMenu.cs.meta} | 0 .../Toolkit/Upgrade/Upgrade_ScriptTemplate.cs | 18 -- Reservoir/ScriptTemplates/Core.meta | 8 + .../Core/CloneAssetTemplate.txt | 7 + .../CloneAssetTemplate.txt.meta} | 2 +- .../{ => Core}/ConfigAssetTemplate.txt | 0 .../{ => Core}/ConfigAssetTemplate.txt.meta | 0 .../{ => Core}/DataAssetTemplate.txt | 0 .../{ => Core}/DataAssetTemplate.txt.meta | 0 .../Core/FileAssetTemplate.txt | 7 + .../Core/FileAssetTemplate.txt.meta | 7 + .../{ => Core}/GameBridgeTemplate.txt | 0 .../{ => Core}/GameBridgeTemplate.txt.meta | 0 .../{ => Core}/GameConfigTemplate.txt | 0 .../{ => Core}/GameConfigTemplate.txt.meta | 0 .../{ => Core}/GameTemplate.txt | 0 .../{ => Core}/GameTemplate.txt.meta | 0 .../{ => Core}/ManagerTemplate.txt | 0 .../{ => Core}/ManagerTemplate.txt.meta | 0 .../{ => Core}/ServiceTemplate.txt | 0 .../{ => Core}/ServiceTemplate.txt.meta | 0 .../{ => Core}/UniqueAssetTemplate.txt | 0 .../{ => Core}/UniqueAssetTemplate.txt.meta | 0 .../{ => Core}/WorldTemplate.txt | 0 .../{ => Core}/WorldTemplate.txt.meta | 0 .../ScriptTemplates/ItemAssetTemplate.txt | 13 - Reservoir/ScriptTemplates/Pattern.meta | 8 + .../AudioManagerTemplate.txt} | 0 .../AudioManagerTemplate.txt.meta} | 0 .../{ => Pattern}/CommandTemplate.txt | 0 .../{ => Pattern}/CommandTemplate.txt.meta | 0 .../{ => Pattern}/CompositManagerTemplate.txt | 0 .../CompositManagerTemplate.txt.meta | 0 .../{ => Pattern}/DataManagerTemplate.txt | 0 .../DataManagerTemplate.txt.meta | 0 .../{ => Pattern}/GameSettingFileTemplate.txt | 0 .../GameSettingFileTemplate.txt.meta | 0 .../{ => Pattern}/GizmoManagerTemplate.txt | 0 .../GizmoManagerTemplate.txt.meta | 0 .../{ => Pattern}/HapticConfigTemplate.txt | 0 .../HapticConfigTemplate.txt.meta | 0 .../{ => Pattern}/ItemConfigTemplate.txt | 0 .../{ => Pattern}/ItemConfigTemplate.txt.meta | 0 .../{ => Pattern}/MixerManagerTemplate.txt | 0 .../MixerManagerTemplate.txt.meta | 0 .../{ => Pattern}/PoolAssetTemplate.txt | 0 .../{ => Pattern}/PoolAssetTemplate.txt.meta | 0 .../{ => Pattern}/SaveFileTemplate.txt | 0 .../{ => Pattern}/SaveFileTemplate.txt.meta | 0 .../{ => Pattern}/SharedRootAssetTemplate.txt | 0 .../SharedRootAssetTemplate.txt.meta | 0 .../TableAssetTemplate.txt} | 0 .../TableAssetTemplate.txt.meta} | 0 .../{ => Pattern}/TaskAssetTemplate.txt | 0 .../{ => Pattern}/TaskAssetTemplate.txt.meta | 0 .../{ => Pattern}/TickManagerTemplate.txt | 0 .../TickManagerTemplate.txt.meta | 0 .../{ => Pattern}/Trigger2DTemplate.txt | 0 .../{ => Pattern}/Trigger2DTemplate.txt.meta | 0 .../{ => Pattern}/Trigger3DTemplate.txt | 0 .../{ => Pattern}/Trigger3DTemplate.txt.meta | 0 .../{ => Pattern}/UIManagerTemplate.txt | 0 .../{ => Pattern}/UIManagerTemplate.txt.meta | 0 .../{ => Pattern}/WidgetTemplate.txt | 0 .../{ => Pattern}/WidgetTemplate.txt.meta | 0 Reservoir/ScriptTemplates/Toolkit.meta | 8 + .../{ => Toolkit}/UpgradeConfigTemplate.txt | 0 .../UpgradeConfigTemplate.txt.meta | 0 .../{ => Toolkit}/UpgradeItemTemplate.txt | 0 .../UpgradeItemTemplate.txt.meta | 0 Runtime/Core/Definitions/Assets.cs | 66 +++-- Runtime/Library/Interfaces/Item.cs | 2 +- Runtime/Pattern/Assets/ItemAsset.cs | 44 ---- Runtime/Pattern/Assets/ItemAsset.cs.meta | 2 - Runtime/Pattern/Assets/ItemConfig.cs | 2 +- Runtime/Toolkit/Inventory/Inventory.cs | 2 +- Runtime/Toolkit/Tutorial/TutorialConfig.cs | 2 +- 120 files changed, 610 insertions(+), 580 deletions(-) create mode 100644 Editor/Core/MenuItem/CoreMenu.cs create mode 100644 Editor/Core/MenuItem/CoreMenu.cs.meta rename Editor/Pattern/Inspectors/{CompositManagerCompWindow.cs => CompositManagerEditor.cs} (96%) rename Editor/Pattern/Inspectors/{CompositManagerCompWindow.cs.meta => CompositManagerEditor.cs.meta} (100%) rename Editor/Pattern/Inspectors/{DataManagerCompWindow.cs => DataManagerEditor.cs} (94%) rename Editor/Pattern/Inspectors/{DataManagerCompWindow.cs.meta => DataManagerEditor.cs.meta} (100%) rename Editor/Pattern/Inspectors/{FactoryEditor.cs => FactoryAssetEditor.cs} (96%) rename Editor/Pattern/Inspectors/{FactoryEditor.cs.meta => FactoryAssetEditor.cs.meta} (100%) rename Editor/Pattern/Inspectors/{ResourcEditor.cs => ResourcAssetEditor.cs} (97%) rename Editor/Pattern/Inspectors/{ResourcEditor.cs.meta => ResourcAssetEditor.cs.meta} (100%) rename Editor/Pattern/Inspectors/{TaskManagerCompWindow.cs => TaskManagerEditor.cs} (97%) rename Editor/Pattern/Inspectors/{TaskManagerCompWindow.cs.meta => TaskManagerEditor.cs.meta} (100%) create mode 100644 Editor/Pattern/MenuItem.meta create mode 100644 Editor/Pattern/MenuItem/PatternMenu.cs create mode 100644 Editor/Pattern/MenuItem/PatternMenu.cs.meta delete mode 100644 Editor/ReadySet/Content/RealMethod_GameObject.cs delete mode 100644 Editor/ReadySet/Content/RealMethod_GameObject.cs.meta delete mode 100644 Editor/ReadySet/Content/RealMethod_ScriptTemplate.cs delete mode 100644 Editor/ReadySet/Content/RealMethod_ScriptTemplate.cs.meta create mode 100644 Editor/Toolkit/Ability/AbilityMenu.cs rename Editor/Toolkit/Ability/{Ability_ScriptTemplate.cs.meta => AbilityMenu.cs.meta} (100%) delete mode 100644 Editor/Toolkit/Ability/Ability_ScriptTemplate.cs create mode 100644 Editor/Toolkit/Actor/ActorMenu.cs rename Editor/Toolkit/Actor/{Actor_ScriptTemplate.cs.meta => ActorMenu.cs.meta} (100%) delete mode 100644 Editor/Toolkit/Actor/Actor_ScriptTemplate.cs create mode 100644 Editor/Toolkit/Inventory/InventoryMenu.cs rename Editor/Toolkit/Inventory/{Inventory_ScriptTemplate.cs.meta => InventoryMenu.cs.meta} (100%) delete mode 100644 Editor/Toolkit/Inventory/Inventory_ScriptTemplate.cs create mode 100644 Editor/Toolkit/PCG/PCGMenu.cs rename Editor/Toolkit/PCG/{PCG_ScriptTemplate.cs.meta => PCGMenu.cs.meta} (100%) delete mode 100644 Editor/Toolkit/PCG/PCG_ScriptTemplate.cs create mode 100644 Editor/Toolkit/Pickup/PickupMenu.cs rename Editor/Toolkit/Pickup/{Pickup_ScriptTemplate.cs.meta => PickupMenu.cs.meta} (100%) delete mode 100644 Editor/Toolkit/Pickup/Pickup_ScriptTemplate.cs create mode 100644 Editor/Toolkit/RPG/RPGMenu.cs rename Editor/Toolkit/RPG/{RPG_ScriptTemplate.cs.meta => RPGMenu.cs.meta} (100%) delete mode 100644 Editor/Toolkit/RPG/RPG_ScriptTemplate.cs create mode 100644 Editor/Toolkit/Tutorial/TutorialMenu.cs rename Editor/Toolkit/Tutorial/{Tutorial_ScriptTemplate.cs.meta => TutorialMenu.cs.meta} (100%) delete mode 100644 Editor/Toolkit/Tutorial/Tutorial_ScriptTemplate.cs create mode 100644 Editor/Toolkit/Upgrade/UpgradeMenu.cs rename Editor/Toolkit/Upgrade/{Upgrade_ScriptTemplate.cs.meta => UpgradeMenu.cs.meta} (100%) delete mode 100644 Editor/Toolkit/Upgrade/Upgrade_ScriptTemplate.cs create mode 100644 Reservoir/ScriptTemplates/Core.meta create mode 100644 Reservoir/ScriptTemplates/Core/CloneAssetTemplate.txt rename Reservoir/ScriptTemplates/{ItemAssetTemplate.txt.meta => Core/CloneAssetTemplate.txt.meta} (75%) rename Reservoir/ScriptTemplates/{ => Core}/ConfigAssetTemplate.txt (100%) rename Reservoir/ScriptTemplates/{ => Core}/ConfigAssetTemplate.txt.meta (100%) rename Reservoir/ScriptTemplates/{ => Core}/DataAssetTemplate.txt (100%) rename Reservoir/ScriptTemplates/{ => Core}/DataAssetTemplate.txt.meta (100%) create mode 100644 Reservoir/ScriptTemplates/Core/FileAssetTemplate.txt create mode 100644 Reservoir/ScriptTemplates/Core/FileAssetTemplate.txt.meta rename Reservoir/ScriptTemplates/{ => Core}/GameBridgeTemplate.txt (100%) rename Reservoir/ScriptTemplates/{ => Core}/GameBridgeTemplate.txt.meta (100%) rename Reservoir/ScriptTemplates/{ => Core}/GameConfigTemplate.txt (100%) rename Reservoir/ScriptTemplates/{ => Core}/GameConfigTemplate.txt.meta (100%) rename Reservoir/ScriptTemplates/{ => Core}/GameTemplate.txt (100%) rename Reservoir/ScriptTemplates/{ => Core}/GameTemplate.txt.meta (100%) rename Reservoir/ScriptTemplates/{ => Core}/ManagerTemplate.txt (100%) rename Reservoir/ScriptTemplates/{ => Core}/ManagerTemplate.txt.meta (100%) rename Reservoir/ScriptTemplates/{ => Core}/ServiceTemplate.txt (100%) rename Reservoir/ScriptTemplates/{ => Core}/ServiceTemplate.txt.meta (100%) rename Reservoir/ScriptTemplates/{ => Core}/UniqueAssetTemplate.txt (100%) rename Reservoir/ScriptTemplates/{ => Core}/UniqueAssetTemplate.txt.meta (100%) rename Reservoir/ScriptTemplates/{ => Core}/WorldTemplate.txt (100%) rename Reservoir/ScriptTemplates/{ => Core}/WorldTemplate.txt.meta (100%) delete mode 100644 Reservoir/ScriptTemplates/ItemAssetTemplate.txt create mode 100644 Reservoir/ScriptTemplates/Pattern.meta rename Reservoir/ScriptTemplates/{AudioManagerTemplater.txt => Pattern/AudioManagerTemplate.txt} (100%) rename Reservoir/ScriptTemplates/{AudioManagerTemplater.txt.meta => Pattern/AudioManagerTemplate.txt.meta} (100%) rename Reservoir/ScriptTemplates/{ => Pattern}/CommandTemplate.txt (100%) rename Reservoir/ScriptTemplates/{ => Pattern}/CommandTemplate.txt.meta (100%) rename Reservoir/ScriptTemplates/{ => Pattern}/CompositManagerTemplate.txt (100%) rename Reservoir/ScriptTemplates/{ => Pattern}/CompositManagerTemplate.txt.meta (100%) rename Reservoir/ScriptTemplates/{ => Pattern}/DataManagerTemplate.txt (100%) rename Reservoir/ScriptTemplates/{ => Pattern}/DataManagerTemplate.txt.meta (100%) rename Reservoir/ScriptTemplates/{ => Pattern}/GameSettingFileTemplate.txt (100%) rename Reservoir/ScriptTemplates/{ => Pattern}/GameSettingFileTemplate.txt.meta (100%) rename Reservoir/ScriptTemplates/{ => Pattern}/GizmoManagerTemplate.txt (100%) rename Reservoir/ScriptTemplates/{ => Pattern}/GizmoManagerTemplate.txt.meta (100%) rename Reservoir/ScriptTemplates/{ => Pattern}/HapticConfigTemplate.txt (100%) rename Reservoir/ScriptTemplates/{ => Pattern}/HapticConfigTemplate.txt.meta (100%) rename Reservoir/ScriptTemplates/{ => Pattern}/ItemConfigTemplate.txt (100%) rename Reservoir/ScriptTemplates/{ => Pattern}/ItemConfigTemplate.txt.meta (100%) rename Reservoir/ScriptTemplates/{ => Pattern}/MixerManagerTemplate.txt (100%) rename Reservoir/ScriptTemplates/{ => Pattern}/MixerManagerTemplate.txt.meta (100%) rename Reservoir/ScriptTemplates/{ => Pattern}/PoolAssetTemplate.txt (100%) rename Reservoir/ScriptTemplates/{ => Pattern}/PoolAssetTemplate.txt.meta (100%) rename Reservoir/ScriptTemplates/{ => Pattern}/SaveFileTemplate.txt (100%) rename Reservoir/ScriptTemplates/{ => Pattern}/SaveFileTemplate.txt.meta (100%) rename Reservoir/ScriptTemplates/{ => Pattern}/SharedRootAssetTemplate.txt (100%) rename Reservoir/ScriptTemplates/{ => Pattern}/SharedRootAssetTemplate.txt.meta (100%) rename Reservoir/ScriptTemplates/{TableTemplate.txt => Pattern/TableAssetTemplate.txt} (100%) rename Reservoir/ScriptTemplates/{TableTemplate.txt.meta => Pattern/TableAssetTemplate.txt.meta} (100%) rename Reservoir/ScriptTemplates/{ => Pattern}/TaskAssetTemplate.txt (100%) rename Reservoir/ScriptTemplates/{ => Pattern}/TaskAssetTemplate.txt.meta (100%) rename Reservoir/ScriptTemplates/{ => Pattern}/TickManagerTemplate.txt (100%) rename Reservoir/ScriptTemplates/{ => Pattern}/TickManagerTemplate.txt.meta (100%) rename Reservoir/ScriptTemplates/{ => Pattern}/Trigger2DTemplate.txt (100%) rename Reservoir/ScriptTemplates/{ => Pattern}/Trigger2DTemplate.txt.meta (100%) rename Reservoir/ScriptTemplates/{ => Pattern}/Trigger3DTemplate.txt (100%) rename Reservoir/ScriptTemplates/{ => Pattern}/Trigger3DTemplate.txt.meta (100%) rename Reservoir/ScriptTemplates/{ => Pattern}/UIManagerTemplate.txt (100%) rename Reservoir/ScriptTemplates/{ => Pattern}/UIManagerTemplate.txt.meta (100%) rename Reservoir/ScriptTemplates/{ => Pattern}/WidgetTemplate.txt (100%) rename Reservoir/ScriptTemplates/{ => Pattern}/WidgetTemplate.txt.meta (100%) create mode 100644 Reservoir/ScriptTemplates/Toolkit.meta rename Reservoir/ScriptTemplates/{ => Toolkit}/UpgradeConfigTemplate.txt (100%) rename Reservoir/ScriptTemplates/{ => Toolkit}/UpgradeConfigTemplate.txt.meta (100%) rename Reservoir/ScriptTemplates/{ => Toolkit}/UpgradeItemTemplate.txt (100%) rename Reservoir/ScriptTemplates/{ => Toolkit}/UpgradeItemTemplate.txt.meta (100%) delete mode 100644 Runtime/Pattern/Assets/ItemAsset.cs delete mode 100644 Runtime/Pattern/Assets/ItemAsset.cs.meta diff --git a/Editor/Core/InitializeOnLoad/Rules/PrimitveAssetsRule.cs b/Editor/Core/InitializeOnLoad/Rules/PrimitveAssetsRule.cs index 2fb2a16..9cd4c09 100644 --- a/Editor/Core/InitializeOnLoad/Rules/PrimitveAssetsRule.cs +++ b/Editor/Core/InitializeOnLoad/Rules/PrimitveAssetsRule.cs @@ -27,7 +27,7 @@ public override void OnStartCheck(RuleExecutionMode mode) if (AssetDatabase.Contains(asset)) { - if (asset is InstanceAsset) + if (asset is FileAsset) { Debug.LogWarning($"InstanceAsset '{asset.name}' is used directly in Play Mode. " + $"A runtime instanceAsset should be used instead.Create() at runtime", diff --git a/Editor/Core/MenuItem/CoreMenu.cs b/Editor/Core/MenuItem/CoreMenu.cs new file mode 100644 index 0000000..8b700c8 --- /dev/null +++ b/Editor/Core/MenuItem/CoreMenu.cs @@ -0,0 +1,120 @@ +using UnityEditor; +using UnityEngine; + +namespace RealMethod.Editor +{ + class CoreMenu + { + private const RealMethodLayer MenuLayer = RealMethodLayer.Core; + + + ///////////// GameObject \\\\\\\\\\\\ + [MenuItem(RM_Editor.GameObjectMenuItemPath + "PlayerStarter", false, 10)] + static void CreatePlayerStarter(MenuCommand menuCommand) + { + // Create a new GameObject + GameObject go = new GameObject("PlayerStarter"); + + // Optional: add components + go.AddComponent(); + + // Place it in the scene, parented if needed + GameObjectUtility.SetParentAndAlign(go, menuCommand.context as GameObject); + + // Register the creation in Undo system (so Ctrl+Z works) + Undo.RegisterCreatedObjectUndo(go, "Create " + go.name); + + // Select the new GameObject + Selection.activeObject = go; + } + [MenuItem(RM_Editor.GameObjectMenuItemPath + "World", false, 10)] + static void CreateWorld(MenuCommand menuCommand) + { + // Create a new GameObject + GameObject go = new GameObject("World"); + + // Optional: add components + go.AddComponent(); + + // Place it in the scene, parented if needed + GameObjectUtility.SetParentAndAlign(go, menuCommand.context as GameObject); + + // Register the creation in Undo system (so Ctrl+Z works) + Undo.RegisterCreatedObjectUndo(go, "Create " + go.name); + + // Select the new GameObject + Selection.activeObject = go; + } + + + ////////////// Scripts \\\\\\\\\\\\ + // Essentials + [MenuItem(RM_Editor.ScriptMenuItemPath + "Essential/Game", false, 80)] + public static void CreateGameClass() + { + RM_Editor.CreateScriptTemplate("Game", MenuLayer); + } + [MenuItem(RM_Editor.ScriptMenuItemPath + "Essential/World", false, 80)] + public static void CreateWorld() + { + RM_Editor.CreateScriptTemplate("World", MenuLayer); + } + [MenuItem(RM_Editor.ScriptMenuItemPath + "Essential/GameBridge", false, 80)] + public static void CreateGameBridgeClass() + { + RM_Editor.CreateScriptTemplate("GameBridge", MenuLayer); + } + // Managers + [MenuItem(RM_Editor.ScriptMenuItemPath + "Manager/EmptyManager", false, 80)] + public static void CreateManager() + { + RM_Editor.CreateScriptTemplate("Manager", MenuLayer); + } + // Services + [MenuItem(RM_Editor.ScriptMenuItemPath + "Service/EmptyService", false, 80)] + public static void CreateService() + { + RM_Editor.CreateScriptTemplate("Service", MenuLayer); + } + // Assets + [MenuItem(RM_Editor.ScriptMenuItemPath + "Asset/Data/EmptyDataAsset", false, 80)] + public static void CreateDataAsset() + { + RM_Editor.CreateScriptTemplate("DataAsset", MenuLayer); + } + [MenuItem(RM_Editor.ScriptMenuItemPath + "Asset/Clone/EmptyCloneAsset", false, 80)] + public static void CreateCloneAsset() + { + RM_Editor.CreateScriptTemplate("CloneAsset", MenuLayer); + } + [MenuItem(RM_Editor.ScriptMenuItemPath + "Asset/Unique/EmptyUniqueAsset", false, 80)] + public static void CreateUniqueAsset() + { + RM_Editor.CreateScriptTemplate("UniqueAsset", MenuLayer); + } + [MenuItem(RM_Editor.ScriptMenuItemPath + "Asset/Config/EmptyConfigAsset", false, 80)] + public static void CreateConfigAsset() + { + RM_Editor.CreateScriptTemplate("ConfigAsset", MenuLayer); + } + [MenuItem(RM_Editor.ScriptMenuItemPath + "Asset/File/EmptyFileAsset", false, 80)] + public static void CreateFileAsset() + { + RM_Editor.CreateScriptTemplate("FileAsset", MenuLayer); + } + [MenuItem(RM_Editor.ScriptMenuItemPath + "Asset/Config/Game", false, 80)] + public static void CreateGameConfig() + { + RM_Editor.CreateScriptTemplate("GameConfig", MenuLayer); + } + // Editor + [MenuItem(RM_Editor.ScriptMenuItemPath + "Editor/CompileRule", false, 80)] + public static void CreateCompileRule() + { + RM_Editor.CreateScriptTemplate("CompileRule", MenuLayer); + } + + + + } +} \ No newline at end of file diff --git a/Editor/Core/MenuItem/CoreMenu.cs.meta b/Editor/Core/MenuItem/CoreMenu.cs.meta new file mode 100644 index 0000000..1c9ed7a --- /dev/null +++ b/Editor/Core/MenuItem/CoreMenu.cs.meta @@ -0,0 +1,2 @@ +fileFormatVersion: 2 +guid: ca9b255b431903b41a6cad7b4423abe6 \ No newline at end of file diff --git a/Editor/Core/Utilities/Editor_Library.cs b/Editor/Core/Utilities/Editor_Library.cs index 8ebe688..f7cb531 100644 --- a/Editor/Core/Utilities/Editor_Library.cs +++ b/Editor/Core/Utilities/Editor_Library.cs @@ -4,11 +4,22 @@ namespace RealMethod.Editor { + public enum RealMethodLayer + { + Core, + Library, + Pattern, + ReadySet, + Toolkit + } + public static class RM_Editor { public static string SetttingAssetPath = ProjectSettingAsset.Path; public static string ScriptTemplatesPath => GetPackagePath("com.mustard.realmethod") + "/Reservoir/ScriptTemplates"; public static string PrefabTemplatePath => GetPackagePath("com.mustard.realmethod") + "/Reservoir/Prefabs"; + public const string GameObjectMenuItemPath = "GameObject/RealMethod/"; + public const string ScriptMenuItemPath = "Assets/Create/Scripting/RealMethod/"; public static string Documentation => GetPackagePath("com.mustard.realmethod") + "/Documentation/Information"; public static bool IsPlayMode { @@ -46,55 +57,11 @@ private static string GetPackagePath(string packageName) Debug.LogError($"Could not find package path for: {packageName}"); return null; } - public static string CreateScriptTemplate(string templateFileName, string defaultName, bool UseProject = false) + public static void CreateScriptTemplate(string TemplateName, RealMethodLayer layer) { - string templatePath = string.Empty; - if (UseProject) - { - ProjectSettingAsset ProjectSetting = AssetDatabase.LoadAssetAtPath(SetttingAssetPath); - templatePath = Path.Combine(ProjectSetting.GetFolderPathByType(ProjectSettingAsset.AssetFormat.Other), templateFileName); - } - else - { - templatePath = Path.Combine(ScriptTemplatesPath, templateFileName); - } - - - if (!File.Exists(templatePath)) - { - Debug.LogError($"Template file not found: {templatePath}"); - return string.Empty; - } - - string selectedPath = RM_Asset.GetSelectedAssetDirectory(); - string newScriptPath = AssetDatabase.GenerateUniqueAssetPath(Path.Combine(selectedPath, defaultName)); - - // Prompt user for script name before creating the file - string inputName = EditorUtility.SaveFilePanel( - "Create Script", - selectedPath, - Path.GetFileNameWithoutExtension(defaultName), - "cs" - ); - - if (string.IsNullOrEmpty(inputName)) - return string.Empty; - - // Ensure the path is relative to the Assets folder - if (inputName.StartsWith(Application.dataPath)) - newScriptPath = "Assets" + inputName.Substring(Application.dataPath.Length); - else - newScriptPath = inputName; - - string template = File.ReadAllText(templatePath); - template = template.Replace("#SCRIPTNAME#", Path.GetFileNameWithoutExtension(newScriptPath)); - string projectName = Application.productName; - template = template.Replace("#PROJECTNAME#", projectName); - - File.WriteAllText(newScriptPath, template); - AssetDatabase.Refresh(); - Selection.activeObject = AssetDatabase.LoadAssetAtPath(newScriptPath); - return newScriptPath; + string NewFileName = $"My{TemplateName}.cs"; + string TemplateFileName = $"{layer}/{TemplateName}Template.txt"; + string NewFilePath = CreateScriptTemplate(TemplateFileName, NewFileName); } public static GameObject CreatePrefabTemplate(string prefabName, bool UseProject = false) { @@ -142,5 +109,61 @@ public static string GetScenePathByName(string name) } + + + + private static string CreateScriptTemplate(string templateFileName, string defaultName) + { + string templatePath = string.Empty; + try + { + templatePath = Path.Combine(ScriptTemplatesPath, templateFileName); + } + catch (System.Exception) + { + Debug.LogWarning("Can't combine path for template, use other addres in project setting."); + ProjectSettingAsset ProjectSetting = AssetDatabase.LoadAssetAtPath(SetttingAssetPath); + templatePath = Path.Combine(ProjectSetting.GetFolderPathByType(ProjectSettingAsset.AssetFormat.Other), templateFileName); + //throw; + } + + + if (!File.Exists(templatePath)) + { + Debug.LogError($"Template file not found: {templatePath}"); + return string.Empty; + } + + string selectedPath = RM_Asset.GetSelectedAssetDirectory(); + string newScriptPath = AssetDatabase.GenerateUniqueAssetPath(Path.Combine(selectedPath, defaultName)); + + // Prompt user for script name before creating the file + string inputName = EditorUtility.SaveFilePanel( + "Create Script", + selectedPath, + Path.GetFileNameWithoutExtension(defaultName), + "cs" + ); + + if (string.IsNullOrEmpty(inputName)) + return string.Empty; + + // Ensure the path is relative to the Assets folder + if (inputName.StartsWith(Application.dataPath)) + newScriptPath = "Assets" + inputName.Substring(Application.dataPath.Length); + else + newScriptPath = inputName; + + string template = File.ReadAllText(templatePath); + template = template.Replace("#SCRIPTNAME#", Path.GetFileNameWithoutExtension(newScriptPath)); + string projectName = Application.productName; + template = template.Replace("#PROJECTNAME#", projectName); + + File.WriteAllText(newScriptPath, template); + AssetDatabase.Refresh(); + Selection.activeObject = AssetDatabase.LoadAssetAtPath(newScriptPath); + return newScriptPath; + } + } } \ No newline at end of file diff --git a/Editor/Pattern/Inspectors/CompositManagerCompWindow.cs b/Editor/Pattern/Inspectors/CompositManagerEditor.cs similarity index 96% rename from Editor/Pattern/Inspectors/CompositManagerCompWindow.cs rename to Editor/Pattern/Inspectors/CompositManagerEditor.cs index 7f44592..da7723f 100644 --- a/Editor/Pattern/Inspectors/CompositManagerCompWindow.cs +++ b/Editor/Pattern/Inspectors/CompositManagerEditor.cs @@ -4,7 +4,7 @@ namespace RealMethod { [CustomEditor(typeof(CompositManager), true)] - public class CompositManagerCompWindow : UnityEditor.Editor + public class CompositManagerEditor : UnityEditor.Editor { private CompositManager BaseComponent; diff --git a/Editor/Pattern/Inspectors/CompositManagerCompWindow.cs.meta b/Editor/Pattern/Inspectors/CompositManagerEditor.cs.meta similarity index 100% rename from Editor/Pattern/Inspectors/CompositManagerCompWindow.cs.meta rename to Editor/Pattern/Inspectors/CompositManagerEditor.cs.meta diff --git a/Editor/Pattern/Inspectors/DataManagerCompWindow.cs b/Editor/Pattern/Inspectors/DataManagerEditor.cs similarity index 94% rename from Editor/Pattern/Inspectors/DataManagerCompWindow.cs rename to Editor/Pattern/Inspectors/DataManagerEditor.cs index 2870910..64a0885 100644 --- a/Editor/Pattern/Inspectors/DataManagerCompWindow.cs +++ b/Editor/Pattern/Inspectors/DataManagerEditor.cs @@ -3,7 +3,7 @@ namespace RealMethod { [CustomEditor(typeof(DataManager), true)] - public class DataManagerCompWindow : UnityEditor.Editor + public class DataManagerEditor : UnityEditor.Editor { private DataManager BaseComponent; diff --git a/Editor/Pattern/Inspectors/DataManagerCompWindow.cs.meta b/Editor/Pattern/Inspectors/DataManagerEditor.cs.meta similarity index 100% rename from Editor/Pattern/Inspectors/DataManagerCompWindow.cs.meta rename to Editor/Pattern/Inspectors/DataManagerEditor.cs.meta diff --git a/Editor/Pattern/Inspectors/FactoryEditor.cs b/Editor/Pattern/Inspectors/FactoryAssetEditor.cs similarity index 96% rename from Editor/Pattern/Inspectors/FactoryEditor.cs rename to Editor/Pattern/Inspectors/FactoryAssetEditor.cs index 5d29cda..ac749a8 100644 --- a/Editor/Pattern/Inspectors/FactoryEditor.cs +++ b/Editor/Pattern/Inspectors/FactoryAssetEditor.cs @@ -5,7 +5,7 @@ namespace RealMethod.Editor { [CustomEditor(typeof(FactoryAsset), true)] - public class FactoryEditor : UnityEditor.Editor + public class FactoryAssetEditor : UnityEditor.Editor { private FactoryAsset TargetAsset; private string[] actionNames; diff --git a/Editor/Pattern/Inspectors/FactoryEditor.cs.meta b/Editor/Pattern/Inspectors/FactoryAssetEditor.cs.meta similarity index 100% rename from Editor/Pattern/Inspectors/FactoryEditor.cs.meta rename to Editor/Pattern/Inspectors/FactoryAssetEditor.cs.meta diff --git a/Editor/Pattern/Inspectors/ResourcEditor.cs b/Editor/Pattern/Inspectors/ResourcAssetEditor.cs similarity index 97% rename from Editor/Pattern/Inspectors/ResourcEditor.cs rename to Editor/Pattern/Inspectors/ResourcAssetEditor.cs index c578f72..55b8d1a 100644 --- a/Editor/Pattern/Inspectors/ResourcEditor.cs +++ b/Editor/Pattern/Inspectors/ResourcAssetEditor.cs @@ -4,7 +4,7 @@ namespace RealMethod.Editor { [CustomEditor(typeof(ResourcAsset<>), true)] - public class ResourcEditor : UnityEditor.Editor + public class ResourcAssetEditor : UnityEditor.Editor { private object baseComponent; private System.Type targetType; diff --git a/Editor/Pattern/Inspectors/ResourcEditor.cs.meta b/Editor/Pattern/Inspectors/ResourcAssetEditor.cs.meta similarity index 100% rename from Editor/Pattern/Inspectors/ResourcEditor.cs.meta rename to Editor/Pattern/Inspectors/ResourcAssetEditor.cs.meta diff --git a/Editor/Pattern/Inspectors/TaskManagerCompWindow.cs b/Editor/Pattern/Inspectors/TaskManagerEditor.cs similarity index 97% rename from Editor/Pattern/Inspectors/TaskManagerCompWindow.cs rename to Editor/Pattern/Inspectors/TaskManagerEditor.cs index eca9e38..3ad9442 100644 --- a/Editor/Pattern/Inspectors/TaskManagerCompWindow.cs +++ b/Editor/Pattern/Inspectors/TaskManagerEditor.cs @@ -4,7 +4,7 @@ namespace RealMethod { [CustomEditor(typeof(TaskManager), true)] - public class TaskManagerCompWindow : UnityEditor.Editor + public class TaskManagerEditor : UnityEditor.Editor { private TaskManager BaseComponent; diff --git a/Editor/Pattern/Inspectors/TaskManagerCompWindow.cs.meta b/Editor/Pattern/Inspectors/TaskManagerEditor.cs.meta similarity index 100% rename from Editor/Pattern/Inspectors/TaskManagerCompWindow.cs.meta rename to Editor/Pattern/Inspectors/TaskManagerEditor.cs.meta diff --git a/Editor/Pattern/MenuItem.meta b/Editor/Pattern/MenuItem.meta new file mode 100644 index 0000000..b13b520 --- /dev/null +++ b/Editor/Pattern/MenuItem.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 2267a5fc0c3695047931a476d844fa6d +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Editor/Pattern/MenuItem/PatternMenu.cs b/Editor/Pattern/MenuItem/PatternMenu.cs new file mode 100644 index 0000000..05c319b --- /dev/null +++ b/Editor/Pattern/MenuItem/PatternMenu.cs @@ -0,0 +1,143 @@ + +using UnityEditor; + +namespace RealMethod.Editor +{ + class PatternMenu + { + private const RealMethodLayer MenuLayer = RealMethodLayer.Pattern; + + + ////////////// Scripts \\\\\\\\\\\\ + // Managers + [MenuItem(RM_Editor.ScriptMenuItemPath + "Manager/AudioManager", false, 80)] + public static void CreateAudioManager() + { + RM_Editor.CreateScriptTemplate("AudioManager", MenuLayer); + } + [MenuItem(RM_Editor.ScriptMenuItemPath + "Manager/CompositManager", false, 80)] + public static void CreateCompositManager() + { + RM_Editor.CreateScriptTemplate("CompositManager", MenuLayer); + } + [MenuItem(RM_Editor.ScriptMenuItemPath + "Manager/DataManager", false, 80)] + public static void CreateDataManager() + { + RM_Editor.CreateScriptTemplate("DataManager", MenuLayer); + } + [MenuItem(RM_Editor.ScriptMenuItemPath + "Manager/GizmoManager", false, 80)] + public static void CreateGizmoManager() + { + RM_Editor.CreateScriptTemplate("GizmoManager", MenuLayer); + } + [MenuItem(RM_Editor.ScriptMenuItemPath + "Manager/UIManager", false, 80)] + public static void CreateUIManager() + { + RM_Editor.CreateScriptTemplate("UIManager", MenuLayer); + } + [MenuItem(RM_Editor.ScriptMenuItemPath + "Manager/MixerManager", false, 80)] + public static void CreateMixerManager() + { + RM_Editor.CreateScriptTemplate("MixerManager", MenuLayer); + } + [MenuItem(RM_Editor.ScriptMenuItemPath + "Manager/HapticManager", false, 80)] + public static void CreateHapticManager() + { + RM_Editor.CreateScriptTemplate("HapticManager", MenuLayer); + } + [MenuItem(RM_Editor.ScriptMenuItemPath + "Manager/TickManager", false, 80)] + public static void CreateTickManager() + { + RM_Editor.CreateScriptTemplate("TickManager", MenuLayer); + } + + // Services + [MenuItem(RM_Editor.ScriptMenuItemPath + "Service/StateService", false, 80)] + public static void CreateStateService() + { + RM_Editor.CreateScriptTemplate("StateService", MenuLayer); + } + [MenuItem(RM_Editor.ScriptMenuItemPath + "Service/RuleService", false, 80)] + public static void CreateRuleService() + { + RM_Editor.CreateScriptTemplate("RuleService", MenuLayer); + } + + // Assets + [MenuItem(RM_Editor.ScriptMenuItemPath + "Asset/Data/Table", false, 80)] + public static void CreateTableAsset() + { + RM_Editor.CreateScriptTemplate("TableAsset", MenuLayer); + } + [MenuItem(RM_Editor.ScriptMenuItemPath + "Asset/Data/Task", false, 80)] + public static void CreateTaskAsset() + { + RM_Editor.CreateScriptTemplate("TaskAsset", MenuLayer); + } + [MenuItem(RM_Editor.ScriptMenuItemPath + "Asset/Config/Item", false, 80)] + public static void CreateItemConfig() + { + RM_Editor.CreateScriptTemplate("ItemConfig", MenuLayer); + } + [MenuItem(RM_Editor.ScriptMenuItemPath + "Asset/Config/Haptic", false, 80)] + public static void CreateHapticConfig() + { + RM_Editor.CreateScriptTemplate("HapticConfig", MenuLayer); + } + [MenuItem(RM_Editor.ScriptMenuItemPath + "Asset/File/Save", false, 80)] + public static void CreateSaveFile() + { + RM_Editor.CreateScriptTemplate("SaveFile", MenuLayer); + } + [MenuItem(RM_Editor.ScriptMenuItemPath + "Asset/ّFile/GameSetting", false, 80)] + public static void CreateGameSettingFile() + { + RM_Editor.CreateScriptTemplate("GameSettingFile", MenuLayer); + } + [MenuItem(RM_Editor.ScriptMenuItemPath + "Asset/Unique/SharedRootAsset", false, 80)] + public static void CreateSharedRootAsset() + { + RM_Editor.CreateScriptTemplate("SharedRootAsset", MenuLayer); + } + [MenuItem(RM_Editor.ScriptMenuItemPath + "Asset/Unique/PoolAsset", false, 80)] + public static void CreatePoolAsset() + { + RM_Editor.CreateScriptTemplate("PoolAsset", MenuLayer); + } + + // UI + [MenuItem(RM_Editor.ScriptMenuItemPath + "General/UI/Widget", false, 80)] + public static void CreateWidget() + { + RM_Editor.CreateScriptTemplate("Widget", MenuLayer); + } + [MenuItem(RM_Editor.ScriptMenuItemPath + "General/UI/WidgetToolkit", false, 80)] + public static void CreateWidgetToolkit() + { + RM_Editor.CreateScriptTemplate("WidgetToolkit", MenuLayer); + } + + // Command + [MenuItem(RM_Editor.ScriptMenuItemPath + "General/Command", false, 80)] + public static void CreateCommand() + { + RM_Editor.CreateScriptTemplate("Command", MenuLayer); + } + + // Trigger + [MenuItem(RM_Editor.ScriptMenuItemPath + "General/Trigger/Trigger3D", false, 80)] + public static void CreateTrigger3D() + { + RM_Editor.CreateScriptTemplate("Trigger3D", MenuLayer); + } + [MenuItem(RM_Editor.ScriptMenuItemPath + "General/Trigger/Trigger2D", false, 80)] + public static void CreateTrigger2D() + { + RM_Editor.CreateScriptTemplate("Trigger2D", MenuLayer); + } + + + + + } +} \ No newline at end of file diff --git a/Editor/Pattern/MenuItem/PatternMenu.cs.meta b/Editor/Pattern/MenuItem/PatternMenu.cs.meta new file mode 100644 index 0000000..a00391b --- /dev/null +++ b/Editor/Pattern/MenuItem/PatternMenu.cs.meta @@ -0,0 +1,2 @@ +fileFormatVersion: 2 +guid: b0e82e6f28f685a4481da01a36af2169 \ No newline at end of file diff --git a/Editor/ReadySet/Content/RealMethod_GameObject.cs b/Editor/ReadySet/Content/RealMethod_GameObject.cs deleted file mode 100644 index e7e2e06..0000000 --- a/Editor/ReadySet/Content/RealMethod_GameObject.cs +++ /dev/null @@ -1,45 +0,0 @@ -using UnityEditor; -using UnityEngine; - -namespace RealMethod.Editor -{ - class RealMethodGameObject - { - [MenuItem("GameObject/RealMethod/PlayerStarter", false, 10)] - static void CreatePlayerStarter(MenuCommand menuCommand) - { - // Create a new GameObject - GameObject go = new GameObject("PlayerStarter"); - - // Optional: add components - go.AddComponent(); - - // Place it in the scene, parented if needed - GameObjectUtility.SetParentAndAlign(go, menuCommand.context as GameObject); - - // Register the creation in Undo system (so Ctrl+Z works) - Undo.RegisterCreatedObjectUndo(go, "Create " + go.name); - - // Select the new GameObject - Selection.activeObject = go; - } - [MenuItem("GameObject/RealMethod/World", false, 10)] - static void CreateWorld(MenuCommand menuCommand) - { - // Create a new GameObject - GameObject go = new GameObject("World"); - - // Optional: add components - go.AddComponent(); - - // Place it in the scene, parented if needed - GameObjectUtility.SetParentAndAlign(go, menuCommand.context as GameObject); - - // Register the creation in Undo system (so Ctrl+Z works) - Undo.RegisterCreatedObjectUndo(go, "Create " + go.name); - - // Select the new GameObject - Selection.activeObject = go; - } - } -} \ No newline at end of file diff --git a/Editor/ReadySet/Content/RealMethod_GameObject.cs.meta b/Editor/ReadySet/Content/RealMethod_GameObject.cs.meta deleted file mode 100644 index 5a7589f..0000000 --- a/Editor/ReadySet/Content/RealMethod_GameObject.cs.meta +++ /dev/null @@ -1,2 +0,0 @@ -fileFormatVersion: 2 -guid: d20b067d280180f4cbcf52a7b71ae786 \ No newline at end of file diff --git a/Editor/ReadySet/Content/RealMethod_ScriptTemplate.cs b/Editor/ReadySet/Content/RealMethod_ScriptTemplate.cs deleted file mode 100644 index 215cbf8..0000000 --- a/Editor/ReadySet/Content/RealMethod_ScriptTemplate.cs +++ /dev/null @@ -1,227 +0,0 @@ -using UnityEditor; - -namespace RealMethod.Editor -{ - class RealMethodScriptTemplate - { - // Essential - [MenuItem("Assets/Create/Scripting/RealMethod/Essential/Game", false, 80)] - public static void CreateGameClass() - { - string Path = RM_Editor.CreateScriptTemplate("GameTemplate.txt", "MyGame.cs"); - } - [MenuItem("Assets/Create/Scripting/RealMethod/Essential/World", false, 80)] - public static void CreateWorld() - { - string Path = RM_Editor.CreateScriptTemplate("WorldTemplate.txt", "MyWorld.cs"); - } - [MenuItem("Assets/Create/Scripting/RealMethod/Essential/GameBridge", false, 80)] - public static void CreateGameBridgeClass() - { - string Path = RM_Editor.CreateScriptTemplate("GameBridgeTemplate.txt", "MyGameBridge.cs"); - } - - // Managers - [MenuItem("Assets/Create/Scripting/RealMethod/Manager/BaseManager", false, 80)] - public static void CreateManager() - { - string Path = RM_Editor.CreateScriptTemplate("ManagerTemplate.txt", "MyManager.cs"); - } - [MenuItem("Assets/Create/Scripting/RealMethod/Manager/AudioManager", false, 80)] - public static void CreateAudioManager() - { - string Path = RM_Editor.CreateScriptTemplate("AudioManagerTemplater.txt", "MyAudioManager.cs"); - } - [MenuItem("Assets/Create/Scripting/RealMethod/Manager/CompositManager", false, 80)] - public static void CreateCompositManager() - { - string Path = RM_Editor.CreateScriptTemplate("CompositManagerTemplate.txt", "MyCompositManager.cs"); - } - [MenuItem("Assets/Create/Scripting/RealMethod/Manager/DataManager", false, 80)] - public static void CreateDataManager() - { - string Path = RM_Editor.CreateScriptTemplate("DataManagerTemplate.txt", "MyDataManager.cs"); - } - [MenuItem("Assets/Create/Scripting/RealMethod/Manager/GizmoManager", false, 80)] - public static void CreateGizmoManager() - { - string Path = RM_Editor.CreateScriptTemplate("GizmoManagerTemplate.txt", "MyGizmoManager.cs"); - } - [MenuItem("Assets/Create/Scripting/RealMethod/Manager/UIManager", false, 80)] - public static void CreateUIManager() - { - string Path = RM_Editor.CreateScriptTemplate("UIManagerTemplate.txt", "MyUIManager.cs"); - } - [MenuItem("Assets/Create/Scripting/RealMethod/Manager/MixerManager", false, 80)] - public static void CreateMixerManager() - { - string Path = RM_Editor.CreateScriptTemplate("MixerManagerTemplate.txt", "MyMixerManager.cs"); - } - [MenuItem("Assets/Create/Scripting/RealMethod/Manager/HapticManager", false, 80)] - public static void CreateHapticManager() - { - string Path = RM_Editor.CreateScriptTemplate("HapticManagerTemplate.txt", "MyHapticManager.cs"); - } - [MenuItem("Assets/Create/Scripting/RealMethod/Manager/TickManager", false, 80)] - public static void CreateTickManager() - { - string Path = RM_Editor.CreateScriptTemplate("TickManagerTemplate.txt", "MyTickManager.cs"); - } - - - // Service - [MenuItem("Assets/Create/Scripting/RealMethod/Service/BaseService", false, 80)] - public static void CreateService() - { - string Path = RM_Editor.CreateScriptTemplate("ServiceTemplate.txt", "MyServicec.cs"); - } - [MenuItem("Assets/Create/Scripting/RealMethod/Service/StateService", false, 80)] - public static void CreateStateService() - { - string Path = RM_Editor.CreateScriptTemplate("StateServiceTemplate.txt", "MyStateService.cs"); - } - [MenuItem("Assets/Create/Scripting/RealMethod/Service/RuleService", false, 80)] - public static void CreateRuleService() - { - string Path = RM_Editor.CreateScriptTemplate("RuleServiceTemplate.txt", "MyRuleService.cs"); - } - - - - // Assets - // // Data - [MenuItem("Assets/Create/Scripting/RealMethod/Asset/Data/BaseData", false, 80)] - public static void CreateDataAsset() - { - string Path = RM_Editor.CreateScriptTemplate("DataAssetTemplate.txt", "MyDataAsset.cs"); - } - [MenuItem("Assets/Create/Scripting/RealMethod/Asset/Data/ItemAsset", false, 80)] - public static void CreateItemAsset() - { - string Path = RM_Editor.CreateScriptTemplate("ItemAssetTemplate.txt", "MyItemAsset.cs"); - } - [MenuItem("Assets/Create/Scripting/RealMethod/Asset/Data/TableAsset", false, 80)] - public static void CreateTableAsset() - { - string Path = RM_Editor.CreateScriptTemplate("TableTemplate.txt", "MyTableAsset.cs"); - } - [MenuItem("Assets/Create/Scripting/RealMethod/Asset/Data/Task", false, 80)] - public static void CreateTaskAsset() - { - string Path = RM_Editor.CreateScriptTemplate("TaskAssetTemplate.txt", "MyTaskAsset.cs"); - } - // // Config - [MenuItem("Assets/Create/Scripting/RealMethod/Asset/Config/BaseConfig", false, 80)] - public static void CreateConfigAsset() - { - string Path = RM_Editor.CreateScriptTemplate("ConfigAssetTemplate.txt", "MyConfigAsset.cs"); - } - [MenuItem("Assets/Create/Scripting/RealMethod/Asset/Config/ItemConfig", false, 80)] - public static void CreateItemConfig() - { - string Path = RM_Editor.CreateScriptTemplate("ItemConfigTemplate.txt", "MyItemConfig.cs"); - } - [MenuItem("Assets/Create/Scripting/RealMethod/Asset/Config/GameConfig", false, 80)] - public static void CreateGameConfig() - { - string Path = RM_Editor.CreateScriptTemplate("GameConfigTemplate.txt", "MyGameConfig.cs"); - } - [MenuItem("Assets/Create/Scripting/RealMethod/Asset/Config/HapticConfig", false, 80)] - public static void CreateHapticConfig() - { - string Path = RM_Editor.CreateScriptTemplate("HapticConfigTemplate.txt", "MyHaptic.cs"); - } - // // Files - [MenuItem("Assets/Create/Scripting/RealMethod/Asset/File/BaseFile", false, 80)] - public static void CreateFileAsset() - { - string Path = RM_Editor.CreateScriptTemplate("FileAssetTemplate.txt", "MyFileAsset.cs"); - } - [MenuItem("Assets/Create/Scripting/RealMethod/Asset/File/SaveFile", false, 80)] - public static void CreateSaveFile() - { - string Path = RM_Editor.CreateScriptTemplate("SaveFileTemplate.txt", "MySaveFile.cs"); - } - [MenuItem("Assets/Create/Scripting/RealMethod/Asset/File/GameSetting", false, 80)] - public static void CreateGameSettingFile() - { - string Path = RM_Editor.CreateScriptTemplate("GameSettingFileTemplate.txt", "GameSettingFile.cs"); - } - // // Unique - [MenuItem("Assets/Create/Scripting/RealMethod/Asset/Unique/BaseUnique", false, 80)] - public static void CreateUniqueAsset() - { - string Path = RM_Editor.CreateScriptTemplate("UniqueAssetTemplate.txt", "MyFileAsset.cs"); - } - [MenuItem("Assets/Create/Scripting/RealMethod/Asset/Unique/SharedRootAsset", false, 80)] - public static void CreateSharedRootAsset() - { - string Path = RM_Editor.CreateScriptTemplate("SharedRootAssetTemplate.txt", "MySharedRootAsset.cs"); - } - [MenuItem("Assets/Create/Scripting/RealMethod/Asset/Unique/PoolAsset", false, 80)] - public static void CreatePoolAsset() - { - string Path = RM_Editor.CreateScriptTemplate("PoolAssetTemplate.txt", "MyPoolAsset.cs"); - } - - // General - // // UI - [MenuItem("Assets/Create/Scripting/RealMethod/General/UI/Widget", false, 80)] - public static void CreateWidget() - { - string Path = RM_Editor.CreateScriptTemplate("WidgetTemplate.txt", "MyWidget.cs"); - } - [MenuItem("Assets/Create/Scripting/RealMethod/General/UI/WidgetToolkit", false, 80)] - public static void CreateWidgetToolkit() - { - string Path = RM_Editor.CreateScriptTemplate("WidgetToolkitTemplate.txt", "MyWidgetToolkit.cs"); - } - // // Command - [MenuItem("Assets/Create/Scripting/RealMethod/General/Command", false, 80)] - public static void CreateCommand() - { - string Path = RM_Editor.CreateScriptTemplate("CommandTemplate.txt", "MyCommand.cs"); - } - // // Trigger - [MenuItem("Assets/Create/Scripting/RealMethod/General/Trigger/Trigger3D", false, 80)] - public static void CreateTrigger3D() - { - string Path = RM_Editor.CreateScriptTemplate("Trigger3DTemplate.txt", "MyTrigger.cs"); - } - [MenuItem("Assets/Create/Scripting/RealMethod/General/Trigger/Trigger2D", false, 80)] - public static void CreateTrigger2D() - { - string Path = RM_Editor.CreateScriptTemplate("Trigger2DTemplate.txt", "MyTrigger.cs"); - } - - - // Editor - [MenuItem("Assets/Create/Scripting/RealMethod/Editor/CompileRule", false, 80)] - public static void CreateCompileRule() - { - string Path = RM_Editor.CreateScriptTemplate("CompileRuleTemplate.txt", "MyRule.cs"); - } - [MenuItem("Assets/Create/Scripting/RealMethod/Editor/SettingSection", false, 80)] - public static void CreateSettingSection() - { - string Path = RM_Editor.CreateScriptTemplate("SettingSectionTemplate.txt", "MySection.cs"); - } - - - - - - - - - - - - - - - - - - } -} \ No newline at end of file diff --git a/Editor/ReadySet/Content/RealMethod_ScriptTemplate.cs.meta b/Editor/ReadySet/Content/RealMethod_ScriptTemplate.cs.meta deleted file mode 100644 index 6620672..0000000 --- a/Editor/ReadySet/Content/RealMethod_ScriptTemplate.cs.meta +++ /dev/null @@ -1,2 +0,0 @@ -fileFormatVersion: 2 -guid: a58e933f91efb7f4192f2e164c491a85 \ No newline at end of file diff --git a/Editor/Toolkit/Ability/AbilityMenu.cs b/Editor/Toolkit/Ability/AbilityMenu.cs new file mode 100644 index 0000000..1cf07b8 --- /dev/null +++ b/Editor/Toolkit/Ability/AbilityMenu.cs @@ -0,0 +1,27 @@ +using UnityEditor; + +namespace RealMethod.Editor +{ + class AbilityMenu + { + private const RealMethodLayer MenuLayer = RealMethodLayer.Toolkit; + + + + [MenuItem(RM_Editor.ScriptMenuItemPath + "Toolkit/Ability/AbilityAsset", false, 80)] + public static void CreateAbilityAsset() + { + RM_Editor.CreateScriptTemplate("AbilityAsset", MenuLayer); + } + [MenuItem(RM_Editor.ScriptMenuItemPath + "Toolkit/Ability/AbilityActionAsset", false, 80)] + public static void CreateAbilityAction() + { + RM_Editor.CreateScriptTemplate("AbilityActionAsset", MenuLayer); + } + [MenuItem(RM_Editor.ScriptMenuItemPath + "Toolkit/Ability/Effect", false, 80)] + public static void CreateEffect() + { + RM_Editor.CreateScriptTemplate("AbilityEffect", MenuLayer); + } + } +} \ No newline at end of file diff --git a/Editor/Toolkit/Ability/Ability_ScriptTemplate.cs.meta b/Editor/Toolkit/Ability/AbilityMenu.cs.meta similarity index 100% rename from Editor/Toolkit/Ability/Ability_ScriptTemplate.cs.meta rename to Editor/Toolkit/Ability/AbilityMenu.cs.meta diff --git a/Editor/Toolkit/Ability/Ability_ScriptTemplate.cs b/Editor/Toolkit/Ability/Ability_ScriptTemplate.cs deleted file mode 100644 index d9cb8d5..0000000 --- a/Editor/Toolkit/Ability/Ability_ScriptTemplate.cs +++ /dev/null @@ -1,23 +0,0 @@ -using UnityEditor; - -namespace RealMethod.Editor -{ - class Ability_ScriptTemplate - { - [MenuItem("Assets/Create/Scripting/RealMethod/Toolkit/Ability/AbilityAsset", false, 80)] - public static void CreateAbilityAsset() - { - string Path = RM_Editor.CreateScriptTemplate("AbilityAssetTemplate.txt", "MyAbility.cs"); - } - [MenuItem("Assets/Create/Scripting/RealMethod/Toolkit/Ability/AbilityActionAsset", false, 80)] - public static void CreateAbilityAction() - { - string Path = RM_Editor.CreateScriptTemplate("AbilityActionAssetTemplate.txt", "MyAbilityAction.cs"); - } - [MenuItem("Assets/Create/Scripting/RealMethod/Toolkit/Ability/Effect", false, 80)] - public static void CreateEffect() - { - string Path = RM_Editor.CreateScriptTemplate("AbilityEffectTemplate.txt", "MyEffect.cs"); - } - } -} \ No newline at end of file diff --git a/Editor/Toolkit/Actor/ActorMenu.cs b/Editor/Toolkit/Actor/ActorMenu.cs new file mode 100644 index 0000000..2796d62 --- /dev/null +++ b/Editor/Toolkit/Actor/ActorMenu.cs @@ -0,0 +1,16 @@ +using UnityEditor; + +namespace RealMethod.Editor +{ + class ActorMenu + { + private const RealMethodLayer MenuLayer = RealMethodLayer.Toolkit; + + + [MenuItem(RM_Editor.ScriptMenuItemPath + "Toolkit/Actor/Act", false, 80)] + public static void CreateActCommand() + { + RM_Editor.CreateScriptTemplate("Act", MenuLayer); + } + } +} \ No newline at end of file diff --git a/Editor/Toolkit/Actor/Actor_ScriptTemplate.cs.meta b/Editor/Toolkit/Actor/ActorMenu.cs.meta similarity index 100% rename from Editor/Toolkit/Actor/Actor_ScriptTemplate.cs.meta rename to Editor/Toolkit/Actor/ActorMenu.cs.meta diff --git a/Editor/Toolkit/Actor/Actor_ScriptTemplate.cs b/Editor/Toolkit/Actor/Actor_ScriptTemplate.cs deleted file mode 100644 index 120dc11..0000000 --- a/Editor/Toolkit/Actor/Actor_ScriptTemplate.cs +++ /dev/null @@ -1,13 +0,0 @@ -using UnityEditor; - -namespace RealMethod.Editor -{ - class Actor_ScriptTemplate - { - [MenuItem("Assets/Create/Scripting/RealMethod/Toolkit/Actor/Act", false, 80)] - public static void CreateActCommand() - { - string Path = RM_Editor.CreateScriptTemplate("ActTemplate.txt", "MyAct.cs"); - } - } -} \ No newline at end of file diff --git a/Editor/Toolkit/Inventory/InventoryMenu.cs b/Editor/Toolkit/Inventory/InventoryMenu.cs new file mode 100644 index 0000000..a0a9d8f --- /dev/null +++ b/Editor/Toolkit/Inventory/InventoryMenu.cs @@ -0,0 +1,16 @@ +using UnityEditor; + +namespace RealMethod.Editor +{ + class InventoryMenu + { + private const RealMethodLayer MenuLayer = RealMethodLayer.Toolkit; + + + [MenuItem(RM_Editor.ScriptMenuItemPath + "Toolkit/Inventory/Item", false, 80)] + public static void CreateItem() + { + RM_Editor.CreateScriptTemplate("InventoryItem", MenuLayer); + } + } +} \ No newline at end of file diff --git a/Editor/Toolkit/Inventory/Inventory_ScriptTemplate.cs.meta b/Editor/Toolkit/Inventory/InventoryMenu.cs.meta similarity index 100% rename from Editor/Toolkit/Inventory/Inventory_ScriptTemplate.cs.meta rename to Editor/Toolkit/Inventory/InventoryMenu.cs.meta diff --git a/Editor/Toolkit/Inventory/Inventory_ScriptTemplate.cs b/Editor/Toolkit/Inventory/Inventory_ScriptTemplate.cs deleted file mode 100644 index eb7eebf..0000000 --- a/Editor/Toolkit/Inventory/Inventory_ScriptTemplate.cs +++ /dev/null @@ -1,13 +0,0 @@ -using UnityEditor; - -namespace RealMethod.Editor -{ - class Inventory_ScriptTemplate - { - [MenuItem("Assets/Create/Scripting/RealMethod/Toolkit/Inventory/Item", false, 80)] - public static void CreateItem() - { - string Path = RM_Editor.CreateScriptTemplate("InventoryItemTemplate.txt", "MyItem.cs"); - } - } -} \ No newline at end of file diff --git a/Editor/Toolkit/PCG/PCGMenu.cs b/Editor/Toolkit/PCG/PCGMenu.cs new file mode 100644 index 0000000..586d190 --- /dev/null +++ b/Editor/Toolkit/PCG/PCGMenu.cs @@ -0,0 +1,15 @@ +using UnityEditor; + +namespace RealMethod.Editor +{ + class PCGMenu + { + private const RealMethodLayer MenuLayer = RealMethodLayer.Toolkit; + + [MenuItem(RM_Editor.ScriptMenuItemPath + "Toolkit/PCG/Request", false, 80)] + public static void CreatePCGRequest() + { + RM_Editor.CreateScriptTemplate("PCGRequest", MenuLayer); + } + } +} \ No newline at end of file diff --git a/Editor/Toolkit/PCG/PCG_ScriptTemplate.cs.meta b/Editor/Toolkit/PCG/PCGMenu.cs.meta similarity index 100% rename from Editor/Toolkit/PCG/PCG_ScriptTemplate.cs.meta rename to Editor/Toolkit/PCG/PCGMenu.cs.meta diff --git a/Editor/Toolkit/PCG/PCG_ScriptTemplate.cs b/Editor/Toolkit/PCG/PCG_ScriptTemplate.cs deleted file mode 100644 index ee20e90..0000000 --- a/Editor/Toolkit/PCG/PCG_ScriptTemplate.cs +++ /dev/null @@ -1,13 +0,0 @@ -using UnityEditor; - -namespace RealMethod.Editor -{ - class PCG_ScriptTemplate - { - [MenuItem("Assets/Create/Scripting/RealMethod/Toolkit/PCG/Request", false, 80)] - public static void CreatePCGRequest() - { - string Path = RM_Editor.CreateScriptTemplate("PCGRequestTamplate.txt", "MyRequest.cs"); - } - } -} \ No newline at end of file diff --git a/Editor/Toolkit/Pickup/PickupMenu.cs b/Editor/Toolkit/Pickup/PickupMenu.cs new file mode 100644 index 0000000..fb59fd6 --- /dev/null +++ b/Editor/Toolkit/Pickup/PickupMenu.cs @@ -0,0 +1,21 @@ +using UnityEditor; + +namespace RealMethod.Editor +{ + class PickupMenu + { + private const RealMethodLayer MenuLayer = RealMethodLayer.Toolkit; + + + [MenuItem(RM_Editor.ScriptMenuItemPath + "Toolkit/Pickup/Pickup3D", false, 80)] + public static void CreatePickup3D() + { + RM_Editor.CreateScriptTemplate("Pickup3D", MenuLayer); + } + [MenuItem(RM_Editor.ScriptMenuItemPath + "Toolkit/Pickup/Pickup2D", false, 80)] + public static void CreatePickup2D() + { + RM_Editor.CreateScriptTemplate("Pickup2D", MenuLayer); + } + } +} \ No newline at end of file diff --git a/Editor/Toolkit/Pickup/Pickup_ScriptTemplate.cs.meta b/Editor/Toolkit/Pickup/PickupMenu.cs.meta similarity index 100% rename from Editor/Toolkit/Pickup/Pickup_ScriptTemplate.cs.meta rename to Editor/Toolkit/Pickup/PickupMenu.cs.meta diff --git a/Editor/Toolkit/Pickup/Pickup_ScriptTemplate.cs b/Editor/Toolkit/Pickup/Pickup_ScriptTemplate.cs deleted file mode 100644 index b445ae2..0000000 --- a/Editor/Toolkit/Pickup/Pickup_ScriptTemplate.cs +++ /dev/null @@ -1,18 +0,0 @@ -using UnityEditor; - -namespace RealMethod.Editor -{ - class Pickup_ScriptTemplate - { - [MenuItem("Assets/Create/Scripting/RealMethod/Toolkit/Pickup/Pickup3D", false, 80)] - public static void CreatePickup3D() - { - string Path = RM_Editor.CreateScriptTemplate("Pickup3DTemplate.txt", "MyPickup.cs"); - } - [MenuItem("Assets/Create/Scripting/RealMethod/Toolkit/Pickup/Pickup2D", false, 80)] - public static void CreatePickup2D() - { - string Path = RM_Editor.CreateScriptTemplate("Pickup2DTemplate.txt", "MyPickup.cs"); - } - } -} \ No newline at end of file diff --git a/Editor/Toolkit/RPG/RPGMenu.cs b/Editor/Toolkit/RPG/RPGMenu.cs new file mode 100644 index 0000000..57cc049 --- /dev/null +++ b/Editor/Toolkit/RPG/RPGMenu.cs @@ -0,0 +1,33 @@ +using UnityEditor; + +namespace RealMethod.Editor +{ + class RPGMenu + { + private const RealMethodLayer MenuLayer = RealMethodLayer.Toolkit; + + + + [MenuItem(RM_Editor.ScriptMenuItemPath + "Toolkit/RPG/StatDefinition", false, 80)] + public static void CreateStatDefinition() + { + RM_Editor.CreateScriptTemplate("StatDefinition", MenuLayer); + } + [MenuItem(RM_Editor.ScriptMenuItemPath + "Toolkit/RPG/StatProfile", false, 80)] + public static void CreateStatProfile() + { + RM_Editor.CreateScriptTemplate("StatProfile", MenuLayer); + } + [MenuItem(RM_Editor.ScriptMenuItemPath + "Toolkit/RPG/StatBuff", false, 80)] + public static void CreateBuffConfig() + { + RM_Editor.CreateScriptTemplate("BuffConfig", MenuLayer); + } + [MenuItem(RM_Editor.ScriptMenuItemPath + "Toolkit/RPG/ResourceData", false, 80)] + public static void CreateResourceData() + { + RM_Editor.CreateScriptTemplate("ResourceData", MenuLayer); + } + + } +} \ No newline at end of file diff --git a/Editor/Toolkit/RPG/RPG_ScriptTemplate.cs.meta b/Editor/Toolkit/RPG/RPGMenu.cs.meta similarity index 100% rename from Editor/Toolkit/RPG/RPG_ScriptTemplate.cs.meta rename to Editor/Toolkit/RPG/RPGMenu.cs.meta diff --git a/Editor/Toolkit/RPG/RPG_ScriptTemplate.cs b/Editor/Toolkit/RPG/RPG_ScriptTemplate.cs deleted file mode 100644 index 0a1f5c5..0000000 --- a/Editor/Toolkit/RPG/RPG_ScriptTemplate.cs +++ /dev/null @@ -1,29 +0,0 @@ -using UnityEditor; - -namespace RealMethod.Editor -{ - class RPG_ScriptTemplate - { - [MenuItem("Assets/Create/Scripting/RealMethod/Toolkit/RPG/StatDefinition", false, 80)] - public static void CreateStatDefinition() - { - string Path = RM_Editor.CreateScriptTemplate("StatDefinitionTemplate.txt", "StatDefinition.cs"); - } - [MenuItem("Assets/Create/Scripting/RealMethod/Toolkit/RPG/StatProfile", false, 80)] - public static void CreateStatProfile() - { - string Path = RM_Editor.CreateScriptTemplate("StatProfileTemplate.txt", "MyProfile.cs"); - } - [MenuItem("Assets/Create/Scripting/RealMethod/Toolkit/RPG/StatBuff", false, 80)] - public static void CreateBuffConfig() - { - string Path = RM_Editor.CreateScriptTemplate("BuffConfigTemplate.txt", "MyBuff.cs"); - } - [MenuItem("Assets/Create/Scripting/RealMethod/Toolkit/RPG/ResourceData", false, 80)] - public static void CreateResourceData() - { - string Path = RM_Editor.CreateScriptTemplate("ResourceDataTemplate.txt", "MyResource.cs"); - } - - } -} \ No newline at end of file diff --git a/Editor/Toolkit/Tutorial/TutorialMenu.cs b/Editor/Toolkit/Tutorial/TutorialMenu.cs new file mode 100644 index 0000000..0fde983 --- /dev/null +++ b/Editor/Toolkit/Tutorial/TutorialMenu.cs @@ -0,0 +1,26 @@ +using UnityEditor; + +namespace RealMethod.Editor +{ + class TutorialMenu + { + private const RealMethodLayer MenuLayer = RealMethodLayer.Toolkit; + + + [MenuItem(RM_Editor.ScriptMenuItemPath + "Toolkit/Tutorial/Screen", false, 80)] + public static void CreateTutorialScreen() + { + RM_Editor.CreateScriptTemplate("TutorialScreen", MenuLayer); + } + [MenuItem(RM_Editor.ScriptMenuItemPath + "Toolkit/Tutorial/UIunit", false, 80)] + public static void CreateTutorialMessage() + { + RM_Editor.CreateScriptTemplate("TutorialUnit", MenuLayer); + } + [MenuItem(RM_Editor.ScriptMenuItemPath + "Toolkit/Tutorial/Config", false, 80)] + public static void CreateTutorialConfig() + { + RM_Editor.CreateScriptTemplate("TutorialConfig", MenuLayer); + } + } +} \ No newline at end of file diff --git a/Editor/Toolkit/Tutorial/Tutorial_ScriptTemplate.cs.meta b/Editor/Toolkit/Tutorial/TutorialMenu.cs.meta similarity index 100% rename from Editor/Toolkit/Tutorial/Tutorial_ScriptTemplate.cs.meta rename to Editor/Toolkit/Tutorial/TutorialMenu.cs.meta diff --git a/Editor/Toolkit/Tutorial/Tutorial_ScriptTemplate.cs b/Editor/Toolkit/Tutorial/Tutorial_ScriptTemplate.cs deleted file mode 100644 index b853459..0000000 --- a/Editor/Toolkit/Tutorial/Tutorial_ScriptTemplate.cs +++ /dev/null @@ -1,25 +0,0 @@ -using UnityEditor; - -namespace RealMethod.Editor -{ - class Tutorial_ScriptTemplate - { - [MenuItem("Assets/Create/Scripting/RealMethod/Toolkit/Tutorial/ScreenWidget", false, 80)] - public static void CreateTutorialScreen() - { - string Path = RM_Editor.CreateScriptTemplate("TutorialScreenTemplate.txt", "MyTutorialScreen.cs"); - } - - [MenuItem("Assets/Create/Scripting/RealMethod/Toolkit/Tutorial/UIunit", false, 80)] - public static void CreateTutorialMessage() - { - string Path = RM_Editor.CreateScriptTemplate("TutorialUnitTemplate.txt", "MyTutorialUnit.cs"); - } - - [MenuItem("Assets/Create/Scripting/RealMethod/Toolkit/Tutorial/Config", false, 80)] - public static void CreateTutorialConfig() - { - string Path = RM_Editor.CreateScriptTemplate("TutorialConfigTemplate.txt", "MyTutorialConfig.cs"); - } - } -} \ No newline at end of file diff --git a/Editor/Toolkit/Upgrade/UpgradeMenu.cs b/Editor/Toolkit/Upgrade/UpgradeMenu.cs new file mode 100644 index 0000000..6b8f486 --- /dev/null +++ b/Editor/Toolkit/Upgrade/UpgradeMenu.cs @@ -0,0 +1,22 @@ +using UnityEditor; + +namespace RealMethod.Editor +{ + class UpgradeMenu + { + private const RealMethodLayer MenuLayer = RealMethodLayer.Toolkit; + + + + [MenuItem(RM_Editor.ScriptMenuItemPath + "Toolkit/Upgrade/Item", false, 80)] + public static void CreateItem() + { + RM_Editor.CreateScriptTemplate("UpgradeItem", MenuLayer); + } + [MenuItem(RM_Editor.ScriptMenuItemPath + "Toolkit/Upgrade/Map", false, 80)] + public static void CreateConfig() + { + RM_Editor.CreateScriptTemplate("UpgradeConfig", MenuLayer); + } + } +} \ No newline at end of file diff --git a/Editor/Toolkit/Upgrade/Upgrade_ScriptTemplate.cs.meta b/Editor/Toolkit/Upgrade/UpgradeMenu.cs.meta similarity index 100% rename from Editor/Toolkit/Upgrade/Upgrade_ScriptTemplate.cs.meta rename to Editor/Toolkit/Upgrade/UpgradeMenu.cs.meta diff --git a/Editor/Toolkit/Upgrade/Upgrade_ScriptTemplate.cs b/Editor/Toolkit/Upgrade/Upgrade_ScriptTemplate.cs deleted file mode 100644 index 033240b..0000000 --- a/Editor/Toolkit/Upgrade/Upgrade_ScriptTemplate.cs +++ /dev/null @@ -1,18 +0,0 @@ -using UnityEditor; - -namespace RealMethod.Editor -{ - class Upgrade_ScriptTemplate - { - [MenuItem("Assets/Create/Scripting/RealMethod/Toolkit/Upgrade/ItemAsset", false, 80)] - public static void CreateItem() - { - string Path = RM_Editor.CreateScriptTemplate("UpgradeItemTemplate.txt", "MyUpgradeAsset.cs"); - } - [MenuItem("Assets/Create/Scripting/RealMethod/Toolkit/Upgrade/MapConfig", false, 80)] - public static void CreateConfig() - { - string Path = RM_Editor.CreateScriptTemplate("UpgradeConfigTemplate.txt", "MyUpgradeConfig.cs"); - } - } -} \ No newline at end of file diff --git a/Reservoir/ScriptTemplates/Core.meta b/Reservoir/ScriptTemplates/Core.meta new file mode 100644 index 0000000..92623ef --- /dev/null +++ b/Reservoir/ScriptTemplates/Core.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: d66d434cac454c34f823e1a3cea9a39e +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Reservoir/ScriptTemplates/Core/CloneAssetTemplate.txt b/Reservoir/ScriptTemplates/Core/CloneAssetTemplate.txt new file mode 100644 index 0000000..9c24adb --- /dev/null +++ b/Reservoir/ScriptTemplates/Core/CloneAssetTemplate.txt @@ -0,0 +1,7 @@ +using UnityEngine; +using RealMethod; + +[CreateAssetMenu(fileName = "#SCRIPTNAME#", menuName = "#PROJECTNAME#/#SCRIPTNAME#", order = 1)] +public class #SCRIPTNAME# : CloneAsset +{ +} \ No newline at end of file diff --git a/Reservoir/ScriptTemplates/ItemAssetTemplate.txt.meta b/Reservoir/ScriptTemplates/Core/CloneAssetTemplate.txt.meta similarity index 75% rename from Reservoir/ScriptTemplates/ItemAssetTemplate.txt.meta rename to Reservoir/ScriptTemplates/Core/CloneAssetTemplate.txt.meta index d7efbd4..e5b5e0f 100644 --- a/Reservoir/ScriptTemplates/ItemAssetTemplate.txt.meta +++ b/Reservoir/ScriptTemplates/Core/CloneAssetTemplate.txt.meta @@ -1,5 +1,5 @@ fileFormatVersion: 2 -guid: bb63fd5394661484babdcdc725c3d48a +guid: 22f923a8fe4c59b4baca28070f31141c TextScriptImporter: externalObjects: {} userData: diff --git a/Reservoir/ScriptTemplates/ConfigAssetTemplate.txt b/Reservoir/ScriptTemplates/Core/ConfigAssetTemplate.txt similarity index 100% rename from Reservoir/ScriptTemplates/ConfigAssetTemplate.txt rename to Reservoir/ScriptTemplates/Core/ConfigAssetTemplate.txt diff --git a/Reservoir/ScriptTemplates/ConfigAssetTemplate.txt.meta b/Reservoir/ScriptTemplates/Core/ConfigAssetTemplate.txt.meta similarity index 100% rename from Reservoir/ScriptTemplates/ConfigAssetTemplate.txt.meta rename to Reservoir/ScriptTemplates/Core/ConfigAssetTemplate.txt.meta diff --git a/Reservoir/ScriptTemplates/DataAssetTemplate.txt b/Reservoir/ScriptTemplates/Core/DataAssetTemplate.txt similarity index 100% rename from Reservoir/ScriptTemplates/DataAssetTemplate.txt rename to Reservoir/ScriptTemplates/Core/DataAssetTemplate.txt diff --git a/Reservoir/ScriptTemplates/DataAssetTemplate.txt.meta b/Reservoir/ScriptTemplates/Core/DataAssetTemplate.txt.meta similarity index 100% rename from Reservoir/ScriptTemplates/DataAssetTemplate.txt.meta rename to Reservoir/ScriptTemplates/Core/DataAssetTemplate.txt.meta diff --git a/Reservoir/ScriptTemplates/Core/FileAssetTemplate.txt b/Reservoir/ScriptTemplates/Core/FileAssetTemplate.txt new file mode 100644 index 0000000..61eaebc --- /dev/null +++ b/Reservoir/ScriptTemplates/Core/FileAssetTemplate.txt @@ -0,0 +1,7 @@ +using UnityEngine; +using RealMethod; + +[CreateAssetMenu(fileName = "#SCRIPTNAME#", menuName = "#PROJECTNAME#/#SCRIPTNAME#", order = 1)] +public class #SCRIPTNAME# : FileAsset +{ +} diff --git a/Reservoir/ScriptTemplates/Core/FileAssetTemplate.txt.meta b/Reservoir/ScriptTemplates/Core/FileAssetTemplate.txt.meta new file mode 100644 index 0000000..375ee17 --- /dev/null +++ b/Reservoir/ScriptTemplates/Core/FileAssetTemplate.txt.meta @@ -0,0 +1,7 @@ +fileFormatVersion: 2 +guid: 939c3f2e8c0d6a347a60d9b6a104ed73 +TextScriptImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Reservoir/ScriptTemplates/GameBridgeTemplate.txt b/Reservoir/ScriptTemplates/Core/GameBridgeTemplate.txt similarity index 100% rename from Reservoir/ScriptTemplates/GameBridgeTemplate.txt rename to Reservoir/ScriptTemplates/Core/GameBridgeTemplate.txt diff --git a/Reservoir/ScriptTemplates/GameBridgeTemplate.txt.meta b/Reservoir/ScriptTemplates/Core/GameBridgeTemplate.txt.meta similarity index 100% rename from Reservoir/ScriptTemplates/GameBridgeTemplate.txt.meta rename to Reservoir/ScriptTemplates/Core/GameBridgeTemplate.txt.meta diff --git a/Reservoir/ScriptTemplates/GameConfigTemplate.txt b/Reservoir/ScriptTemplates/Core/GameConfigTemplate.txt similarity index 100% rename from Reservoir/ScriptTemplates/GameConfigTemplate.txt rename to Reservoir/ScriptTemplates/Core/GameConfigTemplate.txt diff --git a/Reservoir/ScriptTemplates/GameConfigTemplate.txt.meta b/Reservoir/ScriptTemplates/Core/GameConfigTemplate.txt.meta similarity index 100% rename from Reservoir/ScriptTemplates/GameConfigTemplate.txt.meta rename to Reservoir/ScriptTemplates/Core/GameConfigTemplate.txt.meta diff --git a/Reservoir/ScriptTemplates/GameTemplate.txt b/Reservoir/ScriptTemplates/Core/GameTemplate.txt similarity index 100% rename from Reservoir/ScriptTemplates/GameTemplate.txt rename to Reservoir/ScriptTemplates/Core/GameTemplate.txt diff --git a/Reservoir/ScriptTemplates/GameTemplate.txt.meta b/Reservoir/ScriptTemplates/Core/GameTemplate.txt.meta similarity index 100% rename from Reservoir/ScriptTemplates/GameTemplate.txt.meta rename to Reservoir/ScriptTemplates/Core/GameTemplate.txt.meta diff --git a/Reservoir/ScriptTemplates/ManagerTemplate.txt b/Reservoir/ScriptTemplates/Core/ManagerTemplate.txt similarity index 100% rename from Reservoir/ScriptTemplates/ManagerTemplate.txt rename to Reservoir/ScriptTemplates/Core/ManagerTemplate.txt diff --git a/Reservoir/ScriptTemplates/ManagerTemplate.txt.meta b/Reservoir/ScriptTemplates/Core/ManagerTemplate.txt.meta similarity index 100% rename from Reservoir/ScriptTemplates/ManagerTemplate.txt.meta rename to Reservoir/ScriptTemplates/Core/ManagerTemplate.txt.meta diff --git a/Reservoir/ScriptTemplates/ServiceTemplate.txt b/Reservoir/ScriptTemplates/Core/ServiceTemplate.txt similarity index 100% rename from Reservoir/ScriptTemplates/ServiceTemplate.txt rename to Reservoir/ScriptTemplates/Core/ServiceTemplate.txt diff --git a/Reservoir/ScriptTemplates/ServiceTemplate.txt.meta b/Reservoir/ScriptTemplates/Core/ServiceTemplate.txt.meta similarity index 100% rename from Reservoir/ScriptTemplates/ServiceTemplate.txt.meta rename to Reservoir/ScriptTemplates/Core/ServiceTemplate.txt.meta diff --git a/Reservoir/ScriptTemplates/UniqueAssetTemplate.txt b/Reservoir/ScriptTemplates/Core/UniqueAssetTemplate.txt similarity index 100% rename from Reservoir/ScriptTemplates/UniqueAssetTemplate.txt rename to Reservoir/ScriptTemplates/Core/UniqueAssetTemplate.txt diff --git a/Reservoir/ScriptTemplates/UniqueAssetTemplate.txt.meta b/Reservoir/ScriptTemplates/Core/UniqueAssetTemplate.txt.meta similarity index 100% rename from Reservoir/ScriptTemplates/UniqueAssetTemplate.txt.meta rename to Reservoir/ScriptTemplates/Core/UniqueAssetTemplate.txt.meta diff --git a/Reservoir/ScriptTemplates/WorldTemplate.txt b/Reservoir/ScriptTemplates/Core/WorldTemplate.txt similarity index 100% rename from Reservoir/ScriptTemplates/WorldTemplate.txt rename to Reservoir/ScriptTemplates/Core/WorldTemplate.txt diff --git a/Reservoir/ScriptTemplates/WorldTemplate.txt.meta b/Reservoir/ScriptTemplates/Core/WorldTemplate.txt.meta similarity index 100% rename from Reservoir/ScriptTemplates/WorldTemplate.txt.meta rename to Reservoir/ScriptTemplates/Core/WorldTemplate.txt.meta diff --git a/Reservoir/ScriptTemplates/ItemAssetTemplate.txt b/Reservoir/ScriptTemplates/ItemAssetTemplate.txt deleted file mode 100644 index c1c8d60..0000000 --- a/Reservoir/ScriptTemplates/ItemAssetTemplate.txt +++ /dev/null @@ -1,13 +0,0 @@ -using UnityEngine; -using RealMethod; - -[CreateAssetMenu(fileName = "#SCRIPTNAME#", menuName = "#PROJECTNAME#/#SCRIPTNAME#", order = 1)] -public class #SCRIPTNAME# : ItemAsset -{ - #if UNITY_EDITOR - // public override void OnEditorPlay() - // { - // base.OnEditorPlay(); - // } - #endif -} diff --git a/Reservoir/ScriptTemplates/Pattern.meta b/Reservoir/ScriptTemplates/Pattern.meta new file mode 100644 index 0000000..65b0d77 --- /dev/null +++ b/Reservoir/ScriptTemplates/Pattern.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: bbc5ddc017cc6cf43a5f82f18222a728 +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Reservoir/ScriptTemplates/AudioManagerTemplater.txt b/Reservoir/ScriptTemplates/Pattern/AudioManagerTemplate.txt similarity index 100% rename from Reservoir/ScriptTemplates/AudioManagerTemplater.txt rename to Reservoir/ScriptTemplates/Pattern/AudioManagerTemplate.txt diff --git a/Reservoir/ScriptTemplates/AudioManagerTemplater.txt.meta b/Reservoir/ScriptTemplates/Pattern/AudioManagerTemplate.txt.meta similarity index 100% rename from Reservoir/ScriptTemplates/AudioManagerTemplater.txt.meta rename to Reservoir/ScriptTemplates/Pattern/AudioManagerTemplate.txt.meta diff --git a/Reservoir/ScriptTemplates/CommandTemplate.txt b/Reservoir/ScriptTemplates/Pattern/CommandTemplate.txt similarity index 100% rename from Reservoir/ScriptTemplates/CommandTemplate.txt rename to Reservoir/ScriptTemplates/Pattern/CommandTemplate.txt diff --git a/Reservoir/ScriptTemplates/CommandTemplate.txt.meta b/Reservoir/ScriptTemplates/Pattern/CommandTemplate.txt.meta similarity index 100% rename from Reservoir/ScriptTemplates/CommandTemplate.txt.meta rename to Reservoir/ScriptTemplates/Pattern/CommandTemplate.txt.meta diff --git a/Reservoir/ScriptTemplates/CompositManagerTemplate.txt b/Reservoir/ScriptTemplates/Pattern/CompositManagerTemplate.txt similarity index 100% rename from Reservoir/ScriptTemplates/CompositManagerTemplate.txt rename to Reservoir/ScriptTemplates/Pattern/CompositManagerTemplate.txt diff --git a/Reservoir/ScriptTemplates/CompositManagerTemplate.txt.meta b/Reservoir/ScriptTemplates/Pattern/CompositManagerTemplate.txt.meta similarity index 100% rename from Reservoir/ScriptTemplates/CompositManagerTemplate.txt.meta rename to Reservoir/ScriptTemplates/Pattern/CompositManagerTemplate.txt.meta diff --git a/Reservoir/ScriptTemplates/DataManagerTemplate.txt b/Reservoir/ScriptTemplates/Pattern/DataManagerTemplate.txt similarity index 100% rename from Reservoir/ScriptTemplates/DataManagerTemplate.txt rename to Reservoir/ScriptTemplates/Pattern/DataManagerTemplate.txt diff --git a/Reservoir/ScriptTemplates/DataManagerTemplate.txt.meta b/Reservoir/ScriptTemplates/Pattern/DataManagerTemplate.txt.meta similarity index 100% rename from Reservoir/ScriptTemplates/DataManagerTemplate.txt.meta rename to Reservoir/ScriptTemplates/Pattern/DataManagerTemplate.txt.meta diff --git a/Reservoir/ScriptTemplates/GameSettingFileTemplate.txt b/Reservoir/ScriptTemplates/Pattern/GameSettingFileTemplate.txt similarity index 100% rename from Reservoir/ScriptTemplates/GameSettingFileTemplate.txt rename to Reservoir/ScriptTemplates/Pattern/GameSettingFileTemplate.txt diff --git a/Reservoir/ScriptTemplates/GameSettingFileTemplate.txt.meta b/Reservoir/ScriptTemplates/Pattern/GameSettingFileTemplate.txt.meta similarity index 100% rename from Reservoir/ScriptTemplates/GameSettingFileTemplate.txt.meta rename to Reservoir/ScriptTemplates/Pattern/GameSettingFileTemplate.txt.meta diff --git a/Reservoir/ScriptTemplates/GizmoManagerTemplate.txt b/Reservoir/ScriptTemplates/Pattern/GizmoManagerTemplate.txt similarity index 100% rename from Reservoir/ScriptTemplates/GizmoManagerTemplate.txt rename to Reservoir/ScriptTemplates/Pattern/GizmoManagerTemplate.txt diff --git a/Reservoir/ScriptTemplates/GizmoManagerTemplate.txt.meta b/Reservoir/ScriptTemplates/Pattern/GizmoManagerTemplate.txt.meta similarity index 100% rename from Reservoir/ScriptTemplates/GizmoManagerTemplate.txt.meta rename to Reservoir/ScriptTemplates/Pattern/GizmoManagerTemplate.txt.meta diff --git a/Reservoir/ScriptTemplates/HapticConfigTemplate.txt b/Reservoir/ScriptTemplates/Pattern/HapticConfigTemplate.txt similarity index 100% rename from Reservoir/ScriptTemplates/HapticConfigTemplate.txt rename to Reservoir/ScriptTemplates/Pattern/HapticConfigTemplate.txt diff --git a/Reservoir/ScriptTemplates/HapticConfigTemplate.txt.meta b/Reservoir/ScriptTemplates/Pattern/HapticConfigTemplate.txt.meta similarity index 100% rename from Reservoir/ScriptTemplates/HapticConfigTemplate.txt.meta rename to Reservoir/ScriptTemplates/Pattern/HapticConfigTemplate.txt.meta diff --git a/Reservoir/ScriptTemplates/ItemConfigTemplate.txt b/Reservoir/ScriptTemplates/Pattern/ItemConfigTemplate.txt similarity index 100% rename from Reservoir/ScriptTemplates/ItemConfigTemplate.txt rename to Reservoir/ScriptTemplates/Pattern/ItemConfigTemplate.txt diff --git a/Reservoir/ScriptTemplates/ItemConfigTemplate.txt.meta b/Reservoir/ScriptTemplates/Pattern/ItemConfigTemplate.txt.meta similarity index 100% rename from Reservoir/ScriptTemplates/ItemConfigTemplate.txt.meta rename to Reservoir/ScriptTemplates/Pattern/ItemConfigTemplate.txt.meta diff --git a/Reservoir/ScriptTemplates/MixerManagerTemplate.txt b/Reservoir/ScriptTemplates/Pattern/MixerManagerTemplate.txt similarity index 100% rename from Reservoir/ScriptTemplates/MixerManagerTemplate.txt rename to Reservoir/ScriptTemplates/Pattern/MixerManagerTemplate.txt diff --git a/Reservoir/ScriptTemplates/MixerManagerTemplate.txt.meta b/Reservoir/ScriptTemplates/Pattern/MixerManagerTemplate.txt.meta similarity index 100% rename from Reservoir/ScriptTemplates/MixerManagerTemplate.txt.meta rename to Reservoir/ScriptTemplates/Pattern/MixerManagerTemplate.txt.meta diff --git a/Reservoir/ScriptTemplates/PoolAssetTemplate.txt b/Reservoir/ScriptTemplates/Pattern/PoolAssetTemplate.txt similarity index 100% rename from Reservoir/ScriptTemplates/PoolAssetTemplate.txt rename to Reservoir/ScriptTemplates/Pattern/PoolAssetTemplate.txt diff --git a/Reservoir/ScriptTemplates/PoolAssetTemplate.txt.meta b/Reservoir/ScriptTemplates/Pattern/PoolAssetTemplate.txt.meta similarity index 100% rename from Reservoir/ScriptTemplates/PoolAssetTemplate.txt.meta rename to Reservoir/ScriptTemplates/Pattern/PoolAssetTemplate.txt.meta diff --git a/Reservoir/ScriptTemplates/SaveFileTemplate.txt b/Reservoir/ScriptTemplates/Pattern/SaveFileTemplate.txt similarity index 100% rename from Reservoir/ScriptTemplates/SaveFileTemplate.txt rename to Reservoir/ScriptTemplates/Pattern/SaveFileTemplate.txt diff --git a/Reservoir/ScriptTemplates/SaveFileTemplate.txt.meta b/Reservoir/ScriptTemplates/Pattern/SaveFileTemplate.txt.meta similarity index 100% rename from Reservoir/ScriptTemplates/SaveFileTemplate.txt.meta rename to Reservoir/ScriptTemplates/Pattern/SaveFileTemplate.txt.meta diff --git a/Reservoir/ScriptTemplates/SharedRootAssetTemplate.txt b/Reservoir/ScriptTemplates/Pattern/SharedRootAssetTemplate.txt similarity index 100% rename from Reservoir/ScriptTemplates/SharedRootAssetTemplate.txt rename to Reservoir/ScriptTemplates/Pattern/SharedRootAssetTemplate.txt diff --git a/Reservoir/ScriptTemplates/SharedRootAssetTemplate.txt.meta b/Reservoir/ScriptTemplates/Pattern/SharedRootAssetTemplate.txt.meta similarity index 100% rename from Reservoir/ScriptTemplates/SharedRootAssetTemplate.txt.meta rename to Reservoir/ScriptTemplates/Pattern/SharedRootAssetTemplate.txt.meta diff --git a/Reservoir/ScriptTemplates/TableTemplate.txt b/Reservoir/ScriptTemplates/Pattern/TableAssetTemplate.txt similarity index 100% rename from Reservoir/ScriptTemplates/TableTemplate.txt rename to Reservoir/ScriptTemplates/Pattern/TableAssetTemplate.txt diff --git a/Reservoir/ScriptTemplates/TableTemplate.txt.meta b/Reservoir/ScriptTemplates/Pattern/TableAssetTemplate.txt.meta similarity index 100% rename from Reservoir/ScriptTemplates/TableTemplate.txt.meta rename to Reservoir/ScriptTemplates/Pattern/TableAssetTemplate.txt.meta diff --git a/Reservoir/ScriptTemplates/TaskAssetTemplate.txt b/Reservoir/ScriptTemplates/Pattern/TaskAssetTemplate.txt similarity index 100% rename from Reservoir/ScriptTemplates/TaskAssetTemplate.txt rename to Reservoir/ScriptTemplates/Pattern/TaskAssetTemplate.txt diff --git a/Reservoir/ScriptTemplates/TaskAssetTemplate.txt.meta b/Reservoir/ScriptTemplates/Pattern/TaskAssetTemplate.txt.meta similarity index 100% rename from Reservoir/ScriptTemplates/TaskAssetTemplate.txt.meta rename to Reservoir/ScriptTemplates/Pattern/TaskAssetTemplate.txt.meta diff --git a/Reservoir/ScriptTemplates/TickManagerTemplate.txt b/Reservoir/ScriptTemplates/Pattern/TickManagerTemplate.txt similarity index 100% rename from Reservoir/ScriptTemplates/TickManagerTemplate.txt rename to Reservoir/ScriptTemplates/Pattern/TickManagerTemplate.txt diff --git a/Reservoir/ScriptTemplates/TickManagerTemplate.txt.meta b/Reservoir/ScriptTemplates/Pattern/TickManagerTemplate.txt.meta similarity index 100% rename from Reservoir/ScriptTemplates/TickManagerTemplate.txt.meta rename to Reservoir/ScriptTemplates/Pattern/TickManagerTemplate.txt.meta diff --git a/Reservoir/ScriptTemplates/Trigger2DTemplate.txt b/Reservoir/ScriptTemplates/Pattern/Trigger2DTemplate.txt similarity index 100% rename from Reservoir/ScriptTemplates/Trigger2DTemplate.txt rename to Reservoir/ScriptTemplates/Pattern/Trigger2DTemplate.txt diff --git a/Reservoir/ScriptTemplates/Trigger2DTemplate.txt.meta b/Reservoir/ScriptTemplates/Pattern/Trigger2DTemplate.txt.meta similarity index 100% rename from Reservoir/ScriptTemplates/Trigger2DTemplate.txt.meta rename to Reservoir/ScriptTemplates/Pattern/Trigger2DTemplate.txt.meta diff --git a/Reservoir/ScriptTemplates/Trigger3DTemplate.txt b/Reservoir/ScriptTemplates/Pattern/Trigger3DTemplate.txt similarity index 100% rename from Reservoir/ScriptTemplates/Trigger3DTemplate.txt rename to Reservoir/ScriptTemplates/Pattern/Trigger3DTemplate.txt diff --git a/Reservoir/ScriptTemplates/Trigger3DTemplate.txt.meta b/Reservoir/ScriptTemplates/Pattern/Trigger3DTemplate.txt.meta similarity index 100% rename from Reservoir/ScriptTemplates/Trigger3DTemplate.txt.meta rename to Reservoir/ScriptTemplates/Pattern/Trigger3DTemplate.txt.meta diff --git a/Reservoir/ScriptTemplates/UIManagerTemplate.txt b/Reservoir/ScriptTemplates/Pattern/UIManagerTemplate.txt similarity index 100% rename from Reservoir/ScriptTemplates/UIManagerTemplate.txt rename to Reservoir/ScriptTemplates/Pattern/UIManagerTemplate.txt diff --git a/Reservoir/ScriptTemplates/UIManagerTemplate.txt.meta b/Reservoir/ScriptTemplates/Pattern/UIManagerTemplate.txt.meta similarity index 100% rename from Reservoir/ScriptTemplates/UIManagerTemplate.txt.meta rename to Reservoir/ScriptTemplates/Pattern/UIManagerTemplate.txt.meta diff --git a/Reservoir/ScriptTemplates/WidgetTemplate.txt b/Reservoir/ScriptTemplates/Pattern/WidgetTemplate.txt similarity index 100% rename from Reservoir/ScriptTemplates/WidgetTemplate.txt rename to Reservoir/ScriptTemplates/Pattern/WidgetTemplate.txt diff --git a/Reservoir/ScriptTemplates/WidgetTemplate.txt.meta b/Reservoir/ScriptTemplates/Pattern/WidgetTemplate.txt.meta similarity index 100% rename from Reservoir/ScriptTemplates/WidgetTemplate.txt.meta rename to Reservoir/ScriptTemplates/Pattern/WidgetTemplate.txt.meta diff --git a/Reservoir/ScriptTemplates/Toolkit.meta b/Reservoir/ScriptTemplates/Toolkit.meta new file mode 100644 index 0000000..efa985c --- /dev/null +++ b/Reservoir/ScriptTemplates/Toolkit.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 002acfcd71cdf2e45a91d3a78b0c40a0 +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Reservoir/ScriptTemplates/UpgradeConfigTemplate.txt b/Reservoir/ScriptTemplates/Toolkit/UpgradeConfigTemplate.txt similarity index 100% rename from Reservoir/ScriptTemplates/UpgradeConfigTemplate.txt rename to Reservoir/ScriptTemplates/Toolkit/UpgradeConfigTemplate.txt diff --git a/Reservoir/ScriptTemplates/UpgradeConfigTemplate.txt.meta b/Reservoir/ScriptTemplates/Toolkit/UpgradeConfigTemplate.txt.meta similarity index 100% rename from Reservoir/ScriptTemplates/UpgradeConfigTemplate.txt.meta rename to Reservoir/ScriptTemplates/Toolkit/UpgradeConfigTemplate.txt.meta diff --git a/Reservoir/ScriptTemplates/UpgradeItemTemplate.txt b/Reservoir/ScriptTemplates/Toolkit/UpgradeItemTemplate.txt similarity index 100% rename from Reservoir/ScriptTemplates/UpgradeItemTemplate.txt rename to Reservoir/ScriptTemplates/Toolkit/UpgradeItemTemplate.txt diff --git a/Reservoir/ScriptTemplates/UpgradeItemTemplate.txt.meta b/Reservoir/ScriptTemplates/Toolkit/UpgradeItemTemplate.txt.meta similarity index 100% rename from Reservoir/ScriptTemplates/UpgradeItemTemplate.txt.meta rename to Reservoir/ScriptTemplates/Toolkit/UpgradeItemTemplate.txt.meta diff --git a/Runtime/Core/Definitions/Assets.cs b/Runtime/Core/Definitions/Assets.cs index 3faec1b..6de8f47 100644 --- a/Runtime/Core/Definitions/Assets.cs +++ b/Runtime/Core/Definitions/Assets.cs @@ -39,7 +39,9 @@ void ISpawnWithAuthor.OnSpawn(Object author) protected virtual void OnSpawn(Object spawner) { - +#if UNITY_EDITOR || DEVELOPMENT_BUILD + Debug.Log($"[{name}] Spawned"); +#endif } /// /// Ensures this asset can be used safely. Throws an error if it's not. @@ -121,54 +123,25 @@ protected sealed override void EnsureAssetPermission() } /// - /// Represents an asset that defines how to create new instances. - /// The asset itself cannot be used directly or cloned. - /// Instead, the system creates new independent instances based on this asset's data. - /// - public abstract class InstanceAsset : PrimitiveAsset - { - protected sealed override void EnsureAssetPermission() - { -#if UNITY_EDITOR || DEVELOPMENT_BUILD - if (HasCloneName()) - { - Debug.LogError($"[{name}] InstanceAsset cannot be cloned directly. The cloned asset has been removed!"); - DestroyImmediate(this); - return; - } - - if (IsSpawned) - { - if (IsProjectAsset()) - { - Debug.LogError($"[{name}] This asset is direct asset but Spawn Event called. Asset has been removed!"); - DestroyImmediate(this); - return; - } - } -#endif - } - } - /// /// Represents a unique shared asset in the project. /// Developers must use the asset directly and cannot clone it /// or create new instances from it. /// public abstract class UniqueAsset : PrimitiveAsset { - protected sealed override void EnsureAssetPermission() + protected override void EnsureAssetPermission() { #if UNITY_EDITOR || DEVELOPMENT_BUILD if (HasCloneName()) { Debug.LogError($"[{name}] UniqueAsset cannot clone at runtime. NewAsset has been removed!"); - Destroy(this); + DestroyImmediate(this); return; } if (!IsProjectAsset()) { Debug.LogError($"[{name}] UniqueAsset cannot create new instance at runtime. NewAsset has been removed!"); - Destroy(this); + DestroyImmediate(this); return; } #endif @@ -184,5 +157,30 @@ public abstract class ConfigAsset : UniqueAsset { } - + /// + /// A specialized UniqueAsset used for File system. + /// The asset is uniqueAsset can instance at runtime. + /// and developer can use fileasset for saving data in asset, + /// or in runtime asset creation. + /// The asset itself cannot be used cloned. + /// Instead, the system creates new independent instances based on this asset's data. + /// + public abstract class FileAsset : UniqueAsset + { + protected override void EnsureAssetPermission() + { +#if UNITY_EDITOR || DEVELOPMENT_BUILD + base.EnsureAssetPermission(); + if (IsSpawned) + { + if (IsProjectAsset()) + { + Debug.LogError($"[{name}] This asset is direct asset but Spawn Event called. Asset has been removed!"); + DestroyImmediate(this); + return; + } + } +#endif + } + } } \ No newline at end of file diff --git a/Runtime/Library/Interfaces/Item.cs b/Runtime/Library/Interfaces/Item.cs index 621bc4c..0c89b6b 100644 --- a/Runtime/Library/Interfaces/Item.cs +++ b/Runtime/Library/Interfaces/Item.cs @@ -8,7 +8,7 @@ public interface IItem : IIdentifier Sprite GetSpriteIcon(); Sprite GetSpriteIcon(Rect rect, Vector2 pivot); #if UNITY_EDITOR - void ChangeItemName(string NewName); + void SetItemName(string NewName); #endif } diff --git a/Runtime/Pattern/Assets/ItemAsset.cs b/Runtime/Pattern/Assets/ItemAsset.cs deleted file mode 100644 index b85144f..0000000 --- a/Runtime/Pattern/Assets/ItemAsset.cs +++ /dev/null @@ -1,44 +0,0 @@ -using UnityEngine; - -namespace RealMethod -{ - public abstract class ItemAsset : DataAsset, IItem - { - [Header("Item")] - [SerializeField] - protected string itemName; - public Name16 NameID => itemName; - [SerializeField] - protected Texture2D _icon; - public Texture2D Icon => _icon; - - // Implement IItemData Interface - public Sprite GetSpriteIcon() - { - return GetSpriteIcon(new Rect(0, 0, _icon.width, _icon.height), - new Vector2(0.5f, 0.5f) - ); - } - public Sprite GetSpriteIcon(Rect rect, Vector2 pivot) - { - if (_icon != null) - { - return Sprite.Create(_icon, rect, pivot); - } - else - { - Debug.LogWarning("ItemAsset: Icon is not assigned for item '" + itemName + "'."); - return null; - } - } - - -#if UNITY_EDITOR - void IItem.ChangeItemName(string NewName) - { - itemName = NewName; - } -#endif - - } -} \ No newline at end of file diff --git a/Runtime/Pattern/Assets/ItemAsset.cs.meta b/Runtime/Pattern/Assets/ItemAsset.cs.meta deleted file mode 100644 index 7f41f57..0000000 --- a/Runtime/Pattern/Assets/ItemAsset.cs.meta +++ /dev/null @@ -1,2 +0,0 @@ -fileFormatVersion: 2 -guid: d9e96fd8f2ec59d45a61cdc750523d5e \ No newline at end of file diff --git a/Runtime/Pattern/Assets/ItemConfig.cs b/Runtime/Pattern/Assets/ItemConfig.cs index e9ead74..1946366 100644 --- a/Runtime/Pattern/Assets/ItemConfig.cs +++ b/Runtime/Pattern/Assets/ItemConfig.cs @@ -34,7 +34,7 @@ Sprite IItem.GetSpriteIcon(Rect rect, Vector2 pivot) #if UNITY_EDITOR - void IItem.ChangeItemName(string NewName) + void IItem.SetItemName(string NewName) { itemName = NewName; } diff --git a/Runtime/Toolkit/Inventory/Inventory.cs b/Runtime/Toolkit/Inventory/Inventory.cs index 1d1c7ce..a68e042 100644 --- a/Runtime/Toolkit/Inventory/Inventory.cs +++ b/Runtime/Toolkit/Inventory/Inventory.cs @@ -103,7 +103,7 @@ private enum BehaviorType [SerializeField] private BehaviorType Behavior; [SerializeField] - private ItemAsset[] DefaultItem; + private PrimitiveAsset[] DefaultItem; // Actions public System.Action OnItemAdded; diff --git a/Runtime/Toolkit/Tutorial/TutorialConfig.cs b/Runtime/Toolkit/Tutorial/TutorialConfig.cs index 7652366..e663bf2 100644 --- a/Runtime/Toolkit/Tutorial/TutorialConfig.cs +++ b/Runtime/Toolkit/Tutorial/TutorialConfig.cs @@ -73,7 +73,7 @@ ITutorialMessage ITutorialSpawner.InstantiateMessage(Transform parent) protected abstract UI_TutorialUnit InstantiateMessageObject(Transform parent); #if UNITY_EDITOR - void IItem.ChangeItemName(string newLabel) + void IItem.SetItemName(string newLabel) { label = newLabel; } From 0359cd1478f9328be5574cf516c91b428f99aba4 Mon Sep 17 00:00:00 2001 From: Alijimpa Date: Sat, 18 Apr 2026 15:50:31 +0330 Subject: [PATCH 111/204] Other Script for Start --- Reservoir/ScriptTemplates/CloneAsset.txt | 7 ------- Reservoir/ScriptTemplates/CloneAsset.txt.meta | 7 ------- Reservoir/ScriptTemplates/InstanceAsset.txt | 7 ------- Reservoir/ScriptTemplates/InstanceAsset.txt.meta | 7 ------- .../{ => Pattern}/WidgetToolkitTemplate.txt | 0 .../{ => Pattern}/WidgetToolkitTemplate.txt.meta | 0 .../{ => Toolkit}/AbilityActionAssetTemplate.txt | 0 .../{ => Toolkit}/AbilityActionAssetTemplate.txt.meta | 0 .../ScriptTemplates/{ => Toolkit}/AbilityAssetTemplate.txt | 0 .../{ => Toolkit}/AbilityAssetTemplate.txt.meta | 0 .../{ => Toolkit}/AbilityEffectTemplate.txt | 0 .../{ => Toolkit}/AbilityEffectTemplate.txt.meta | 0 .../ScriptTemplates/{ => Toolkit}/BuffConfigTemplate.txt | 0 .../{ => Toolkit}/BuffConfigTemplate.txt.meta | 0 .../{ => Toolkit}/InventoryItemTemplate.txt | 0 .../{ => Toolkit}/InventoryItemTemplate.txt.meta | 0 .../ScriptTemplates/{ => Toolkit}/PCGRequestTamplate.txt | 0 .../{ => Toolkit}/PCGRequestTamplate.txt.meta | 0 .../ScriptTemplates/{ => Toolkit}/Pickup2DTemplate.txt | 0 .../{ => Toolkit}/Pickup2DTemplate.txt.meta | 0 .../ScriptTemplates/{ => Toolkit}/Pickup3DTemplate.txt | 0 .../{ => Toolkit}/Pickup3DTemplate.txt.meta | 0 22 files changed, 28 deletions(-) delete mode 100644 Reservoir/ScriptTemplates/CloneAsset.txt delete mode 100644 Reservoir/ScriptTemplates/CloneAsset.txt.meta delete mode 100644 Reservoir/ScriptTemplates/InstanceAsset.txt delete mode 100644 Reservoir/ScriptTemplates/InstanceAsset.txt.meta rename Reservoir/ScriptTemplates/{ => Pattern}/WidgetToolkitTemplate.txt (100%) rename Reservoir/ScriptTemplates/{ => Pattern}/WidgetToolkitTemplate.txt.meta (100%) rename Reservoir/ScriptTemplates/{ => Toolkit}/AbilityActionAssetTemplate.txt (100%) rename Reservoir/ScriptTemplates/{ => Toolkit}/AbilityActionAssetTemplate.txt.meta (100%) rename Reservoir/ScriptTemplates/{ => Toolkit}/AbilityAssetTemplate.txt (100%) rename Reservoir/ScriptTemplates/{ => Toolkit}/AbilityAssetTemplate.txt.meta (100%) rename Reservoir/ScriptTemplates/{ => Toolkit}/AbilityEffectTemplate.txt (100%) rename Reservoir/ScriptTemplates/{ => Toolkit}/AbilityEffectTemplate.txt.meta (100%) rename Reservoir/ScriptTemplates/{ => Toolkit}/BuffConfigTemplate.txt (100%) rename Reservoir/ScriptTemplates/{ => Toolkit}/BuffConfigTemplate.txt.meta (100%) rename Reservoir/ScriptTemplates/{ => Toolkit}/InventoryItemTemplate.txt (100%) rename Reservoir/ScriptTemplates/{ => Toolkit}/InventoryItemTemplate.txt.meta (100%) rename Reservoir/ScriptTemplates/{ => Toolkit}/PCGRequestTamplate.txt (100%) rename Reservoir/ScriptTemplates/{ => Toolkit}/PCGRequestTamplate.txt.meta (100%) rename Reservoir/ScriptTemplates/{ => Toolkit}/Pickup2DTemplate.txt (100%) rename Reservoir/ScriptTemplates/{ => Toolkit}/Pickup2DTemplate.txt.meta (100%) rename Reservoir/ScriptTemplates/{ => Toolkit}/Pickup3DTemplate.txt (100%) rename Reservoir/ScriptTemplates/{ => Toolkit}/Pickup3DTemplate.txt.meta (100%) diff --git a/Reservoir/ScriptTemplates/CloneAsset.txt b/Reservoir/ScriptTemplates/CloneAsset.txt deleted file mode 100644 index 995524d..0000000 --- a/Reservoir/ScriptTemplates/CloneAsset.txt +++ /dev/null @@ -1,7 +0,0 @@ -using UnityEngine; -using RealMethod; - -[CreateAssetMenu(fileName = "#SCRIPTNAME#", menuName = "#PROJECTNAME#/#SCRIPTNAME#", order = 1)] -public class #SCRIPTNAME# : CloneAsset -{ -} diff --git a/Reservoir/ScriptTemplates/CloneAsset.txt.meta b/Reservoir/ScriptTemplates/CloneAsset.txt.meta deleted file mode 100644 index d802343..0000000 --- a/Reservoir/ScriptTemplates/CloneAsset.txt.meta +++ /dev/null @@ -1,7 +0,0 @@ -fileFormatVersion: 2 -guid: 109cba7c2bec5bb4cb7ea64f2236b1f2 -TextScriptImporter: - externalObjects: {} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Reservoir/ScriptTemplates/InstanceAsset.txt b/Reservoir/ScriptTemplates/InstanceAsset.txt deleted file mode 100644 index 9faab92..0000000 --- a/Reservoir/ScriptTemplates/InstanceAsset.txt +++ /dev/null @@ -1,7 +0,0 @@ -using UnityEngine; -using RealMethod; - -[CreateAssetMenu(fileName = "#SCRIPTNAME#", menuName = "#PROJECTNAME#/#SCRIPTNAME#", order = 1)] -public class #SCRIPTNAME# : InstanceAsset -{ -} diff --git a/Reservoir/ScriptTemplates/InstanceAsset.txt.meta b/Reservoir/ScriptTemplates/InstanceAsset.txt.meta deleted file mode 100644 index c2f1e25..0000000 --- a/Reservoir/ScriptTemplates/InstanceAsset.txt.meta +++ /dev/null @@ -1,7 +0,0 @@ -fileFormatVersion: 2 -guid: 4744f0022d011cf44a0b25e6e9f8cd79 -TextScriptImporter: - externalObjects: {} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Reservoir/ScriptTemplates/WidgetToolkitTemplate.txt b/Reservoir/ScriptTemplates/Pattern/WidgetToolkitTemplate.txt similarity index 100% rename from Reservoir/ScriptTemplates/WidgetToolkitTemplate.txt rename to Reservoir/ScriptTemplates/Pattern/WidgetToolkitTemplate.txt diff --git a/Reservoir/ScriptTemplates/WidgetToolkitTemplate.txt.meta b/Reservoir/ScriptTemplates/Pattern/WidgetToolkitTemplate.txt.meta similarity index 100% rename from Reservoir/ScriptTemplates/WidgetToolkitTemplate.txt.meta rename to Reservoir/ScriptTemplates/Pattern/WidgetToolkitTemplate.txt.meta diff --git a/Reservoir/ScriptTemplates/AbilityActionAssetTemplate.txt b/Reservoir/ScriptTemplates/Toolkit/AbilityActionAssetTemplate.txt similarity index 100% rename from Reservoir/ScriptTemplates/AbilityActionAssetTemplate.txt rename to Reservoir/ScriptTemplates/Toolkit/AbilityActionAssetTemplate.txt diff --git a/Reservoir/ScriptTemplates/AbilityActionAssetTemplate.txt.meta b/Reservoir/ScriptTemplates/Toolkit/AbilityActionAssetTemplate.txt.meta similarity index 100% rename from Reservoir/ScriptTemplates/AbilityActionAssetTemplate.txt.meta rename to Reservoir/ScriptTemplates/Toolkit/AbilityActionAssetTemplate.txt.meta diff --git a/Reservoir/ScriptTemplates/AbilityAssetTemplate.txt b/Reservoir/ScriptTemplates/Toolkit/AbilityAssetTemplate.txt similarity index 100% rename from Reservoir/ScriptTemplates/AbilityAssetTemplate.txt rename to Reservoir/ScriptTemplates/Toolkit/AbilityAssetTemplate.txt diff --git a/Reservoir/ScriptTemplates/AbilityAssetTemplate.txt.meta b/Reservoir/ScriptTemplates/Toolkit/AbilityAssetTemplate.txt.meta similarity index 100% rename from Reservoir/ScriptTemplates/AbilityAssetTemplate.txt.meta rename to Reservoir/ScriptTemplates/Toolkit/AbilityAssetTemplate.txt.meta diff --git a/Reservoir/ScriptTemplates/AbilityEffectTemplate.txt b/Reservoir/ScriptTemplates/Toolkit/AbilityEffectTemplate.txt similarity index 100% rename from Reservoir/ScriptTemplates/AbilityEffectTemplate.txt rename to Reservoir/ScriptTemplates/Toolkit/AbilityEffectTemplate.txt diff --git a/Reservoir/ScriptTemplates/AbilityEffectTemplate.txt.meta b/Reservoir/ScriptTemplates/Toolkit/AbilityEffectTemplate.txt.meta similarity index 100% rename from Reservoir/ScriptTemplates/AbilityEffectTemplate.txt.meta rename to Reservoir/ScriptTemplates/Toolkit/AbilityEffectTemplate.txt.meta diff --git a/Reservoir/ScriptTemplates/BuffConfigTemplate.txt b/Reservoir/ScriptTemplates/Toolkit/BuffConfigTemplate.txt similarity index 100% rename from Reservoir/ScriptTemplates/BuffConfigTemplate.txt rename to Reservoir/ScriptTemplates/Toolkit/BuffConfigTemplate.txt diff --git a/Reservoir/ScriptTemplates/BuffConfigTemplate.txt.meta b/Reservoir/ScriptTemplates/Toolkit/BuffConfigTemplate.txt.meta similarity index 100% rename from Reservoir/ScriptTemplates/BuffConfigTemplate.txt.meta rename to Reservoir/ScriptTemplates/Toolkit/BuffConfigTemplate.txt.meta diff --git a/Reservoir/ScriptTemplates/InventoryItemTemplate.txt b/Reservoir/ScriptTemplates/Toolkit/InventoryItemTemplate.txt similarity index 100% rename from Reservoir/ScriptTemplates/InventoryItemTemplate.txt rename to Reservoir/ScriptTemplates/Toolkit/InventoryItemTemplate.txt diff --git a/Reservoir/ScriptTemplates/InventoryItemTemplate.txt.meta b/Reservoir/ScriptTemplates/Toolkit/InventoryItemTemplate.txt.meta similarity index 100% rename from Reservoir/ScriptTemplates/InventoryItemTemplate.txt.meta rename to Reservoir/ScriptTemplates/Toolkit/InventoryItemTemplate.txt.meta diff --git a/Reservoir/ScriptTemplates/PCGRequestTamplate.txt b/Reservoir/ScriptTemplates/Toolkit/PCGRequestTamplate.txt similarity index 100% rename from Reservoir/ScriptTemplates/PCGRequestTamplate.txt rename to Reservoir/ScriptTemplates/Toolkit/PCGRequestTamplate.txt diff --git a/Reservoir/ScriptTemplates/PCGRequestTamplate.txt.meta b/Reservoir/ScriptTemplates/Toolkit/PCGRequestTamplate.txt.meta similarity index 100% rename from Reservoir/ScriptTemplates/PCGRequestTamplate.txt.meta rename to Reservoir/ScriptTemplates/Toolkit/PCGRequestTamplate.txt.meta diff --git a/Reservoir/ScriptTemplates/Pickup2DTemplate.txt b/Reservoir/ScriptTemplates/Toolkit/Pickup2DTemplate.txt similarity index 100% rename from Reservoir/ScriptTemplates/Pickup2DTemplate.txt rename to Reservoir/ScriptTemplates/Toolkit/Pickup2DTemplate.txt diff --git a/Reservoir/ScriptTemplates/Pickup2DTemplate.txt.meta b/Reservoir/ScriptTemplates/Toolkit/Pickup2DTemplate.txt.meta similarity index 100% rename from Reservoir/ScriptTemplates/Pickup2DTemplate.txt.meta rename to Reservoir/ScriptTemplates/Toolkit/Pickup2DTemplate.txt.meta diff --git a/Reservoir/ScriptTemplates/Pickup3DTemplate.txt b/Reservoir/ScriptTemplates/Toolkit/Pickup3DTemplate.txt similarity index 100% rename from Reservoir/ScriptTemplates/Pickup3DTemplate.txt rename to Reservoir/ScriptTemplates/Toolkit/Pickup3DTemplate.txt diff --git a/Reservoir/ScriptTemplates/Pickup3DTemplate.txt.meta b/Reservoir/ScriptTemplates/Toolkit/Pickup3DTemplate.txt.meta similarity index 100% rename from Reservoir/ScriptTemplates/Pickup3DTemplate.txt.meta rename to Reservoir/ScriptTemplates/Toolkit/Pickup3DTemplate.txt.meta From e743ff27481aa4310cd04078ee49df9a313fa978 Mon Sep 17 00:00:00 2001 From: Alijimpa Date: Sat, 18 Apr 2026 16:28:50 +0330 Subject: [PATCH 112/204] Resort for all Script Tmplate --- Editor/Core/Utilities/Editor_Library.cs | 14 ++++++-------- Editor/Pattern/MenuItem/PatternMenu.cs | 2 +- Editor/Toolkit/Inventory/InventoryMenu.cs | 1 + 3 files changed, 8 insertions(+), 9 deletions(-) diff --git a/Editor/Core/Utilities/Editor_Library.cs b/Editor/Core/Utilities/Editor_Library.cs index f7cb531..4a9ea67 100644 --- a/Editor/Core/Utilities/Editor_Library.cs +++ b/Editor/Core/Utilities/Editor_Library.cs @@ -60,7 +60,7 @@ private static string GetPackagePath(string packageName) public static void CreateScriptTemplate(string TemplateName, RealMethodLayer layer) { string NewFileName = $"My{TemplateName}.cs"; - string TemplateFileName = $"{layer}/{TemplateName}Template.txt"; + string TemplateFileName = $"{layer}\\{TemplateName}Template.txt"; string NewFilePath = CreateScriptTemplate(TemplateFileName, NewFileName); } public static GameObject CreatePrefabTemplate(string prefabName, bool UseProject = false) @@ -115,16 +115,14 @@ public static string GetScenePathByName(string name) private static string CreateScriptTemplate(string templateFileName, string defaultName) { string templatePath = string.Empty; - try + if (Directory.Exists("Assets/RealDev/_General")) { - templatePath = Path.Combine(ScriptTemplatesPath, templateFileName); + Debug.LogWarning("When This Message show RealMetod using hardcode addres becuase find [Assets/RealDev/_General]"); + templatePath = Path.Combine("Assets\\RealMethod\\Reservoir\\ScriptTemplates\\", templateFileName); } - catch (System.Exception) + else { - Debug.LogWarning("Can't combine path for template, use other addres in project setting."); - ProjectSettingAsset ProjectSetting = AssetDatabase.LoadAssetAtPath(SetttingAssetPath); - templatePath = Path.Combine(ProjectSetting.GetFolderPathByType(ProjectSettingAsset.AssetFormat.Other), templateFileName); - //throw; + templatePath = Path.Combine(ScriptTemplatesPath, templateFileName); } diff --git a/Editor/Pattern/MenuItem/PatternMenu.cs b/Editor/Pattern/MenuItem/PatternMenu.cs index 05c319b..c5f3946 100644 --- a/Editor/Pattern/MenuItem/PatternMenu.cs +++ b/Editor/Pattern/MenuItem/PatternMenu.cs @@ -89,7 +89,7 @@ public static void CreateSaveFile() { RM_Editor.CreateScriptTemplate("SaveFile", MenuLayer); } - [MenuItem(RM_Editor.ScriptMenuItemPath + "Asset/ّFile/GameSetting", false, 80)] + [MenuItem(RM_Editor.ScriptMenuItemPath + "Asset/File/GameSetting", false, 80)] public static void CreateGameSettingFile() { RM_Editor.CreateScriptTemplate("GameSettingFile", MenuLayer); diff --git a/Editor/Toolkit/Inventory/InventoryMenu.cs b/Editor/Toolkit/Inventory/InventoryMenu.cs index a0a9d8f..bc0feeb 100644 --- a/Editor/Toolkit/Inventory/InventoryMenu.cs +++ b/Editor/Toolkit/Inventory/InventoryMenu.cs @@ -7,6 +7,7 @@ class InventoryMenu private const RealMethodLayer MenuLayer = RealMethodLayer.Toolkit; + [MenuItem(RM_Editor.ScriptMenuItemPath + "Toolkit/Inventory/Item", false, 80)] public static void CreateItem() { From fb3046da24075c81ee486f3239f6c7679910e5b9 Mon Sep 17 00:00:00 2001 From: Alijimpa Date: Sat, 18 Apr 2026 21:57:26 +0330 Subject: [PATCH 113/204] Fix Sorting Menu Item --- Editor/Core/MenuItem/CoreMenu.cs | 24 ++++++------ Editor/Core/Utilities/Editor_Library.cs | 34 +++++++++++++++- Editor/Pattern/MenuItem/PatternMenu.cs | 48 +++++++++++------------ Editor/Toolkit/Ability/AbilityMenu.cs | 6 +-- Editor/Toolkit/Actor/ActorMenu.cs | 2 +- Editor/Toolkit/Inventory/InventoryMenu.cs | 2 +- Editor/Toolkit/PCG/PCGMenu.cs | 2 +- Editor/Toolkit/Pickup/PickupMenu.cs | 4 +- Editor/Toolkit/RPG/RPGMenu.cs | 8 ++-- Editor/Toolkit/Tutorial/TutorialMenu.cs | 6 +-- Editor/Toolkit/Upgrade/UpgradeMenu.cs | 4 +- 11 files changed, 86 insertions(+), 54 deletions(-) diff --git a/Editor/Core/MenuItem/CoreMenu.cs b/Editor/Core/MenuItem/CoreMenu.cs index 8b700c8..b68d671 100644 --- a/Editor/Core/MenuItem/CoreMenu.cs +++ b/Editor/Core/MenuItem/CoreMenu.cs @@ -49,66 +49,66 @@ static void CreateWorld(MenuCommand menuCommand) ////////////// Scripts \\\\\\\\\\\\ // Essentials - [MenuItem(RM_Editor.ScriptMenuItemPath + "Essential/Game", false, 80)] + [MenuItem(RM_Editor.ScriptMenuItemPath + "Essential/Game", false, RM_Editor.MenuOrder.Essential_Head)] public static void CreateGameClass() { RM_Editor.CreateScriptTemplate("Game", MenuLayer); } - [MenuItem(RM_Editor.ScriptMenuItemPath + "Essential/World", false, 80)] + [MenuItem(RM_Editor.ScriptMenuItemPath + "Essential/World", false, RM_Editor.MenuOrder.Essential_Body)] public static void CreateWorld() { RM_Editor.CreateScriptTemplate("World", MenuLayer); } - [MenuItem(RM_Editor.ScriptMenuItemPath + "Essential/GameBridge", false, 80)] + [MenuItem(RM_Editor.ScriptMenuItemPath + "Essential/GameBridge", false, RM_Editor.MenuOrder.Essential_Body)] public static void CreateGameBridgeClass() { RM_Editor.CreateScriptTemplate("GameBridge", MenuLayer); } // Managers - [MenuItem(RM_Editor.ScriptMenuItemPath + "Manager/EmptyManager", false, 80)] + [MenuItem(RM_Editor.ScriptMenuItemPath + "Manager/EmptyManager", false, RM_Editor.MenuOrder.Manager_Head)] public static void CreateManager() { RM_Editor.CreateScriptTemplate("Manager", MenuLayer); } // Services - [MenuItem(RM_Editor.ScriptMenuItemPath + "Service/EmptyService", false, 80)] + [MenuItem(RM_Editor.ScriptMenuItemPath + "Service/EmptyService", false, RM_Editor.MenuOrder.Service_Head)] public static void CreateService() { RM_Editor.CreateScriptTemplate("Service", MenuLayer); } // Assets - [MenuItem(RM_Editor.ScriptMenuItemPath + "Asset/Data/EmptyDataAsset", false, 80)] + [MenuItem(RM_Editor.ScriptMenuItemPath + "Asset/Data/EmptyDataAsset", false, RM_Editor.MenuOrder.DataAsset_Head)] public static void CreateDataAsset() { RM_Editor.CreateScriptTemplate("DataAsset", MenuLayer); } - [MenuItem(RM_Editor.ScriptMenuItemPath + "Asset/Clone/EmptyCloneAsset", false, 80)] + [MenuItem(RM_Editor.ScriptMenuItemPath + "Asset/Clone/EmptyCloneAsset", false, RM_Editor.MenuOrder.CloneAsset_Head)] public static void CreateCloneAsset() { RM_Editor.CreateScriptTemplate("CloneAsset", MenuLayer); } - [MenuItem(RM_Editor.ScriptMenuItemPath + "Asset/Unique/EmptyUniqueAsset", false, 80)] + [MenuItem(RM_Editor.ScriptMenuItemPath + "Asset/Unique/EmptyUniqueAsset", false, RM_Editor.MenuOrder.UniqueAsset_Head)] public static void CreateUniqueAsset() { RM_Editor.CreateScriptTemplate("UniqueAsset", MenuLayer); } - [MenuItem(RM_Editor.ScriptMenuItemPath + "Asset/Config/EmptyConfigAsset", false, 80)] + [MenuItem(RM_Editor.ScriptMenuItemPath + "Asset/Config/EmptyConfigAsset", false, RM_Editor.MenuOrder.ConfigAsset_Head)] public static void CreateConfigAsset() { RM_Editor.CreateScriptTemplate("ConfigAsset", MenuLayer); } - [MenuItem(RM_Editor.ScriptMenuItemPath + "Asset/File/EmptyFileAsset", false, 80)] + [MenuItem(RM_Editor.ScriptMenuItemPath + "Asset/File/EmptyFileAsset", false, RM_Editor.MenuOrder.FileAsset_Head)] public static void CreateFileAsset() { RM_Editor.CreateScriptTemplate("FileAsset", MenuLayer); } - [MenuItem(RM_Editor.ScriptMenuItemPath + "Asset/Config/Game", false, 80)] + [MenuItem(RM_Editor.ScriptMenuItemPath + "Asset/Config/Game", false, RM_Editor.MenuOrder.ConfigAsset_Body)] public static void CreateGameConfig() { RM_Editor.CreateScriptTemplate("GameConfig", MenuLayer); } // Editor - [MenuItem(RM_Editor.ScriptMenuItemPath + "Editor/CompileRule", false, 80)] + [MenuItem(RM_Editor.ScriptMenuItemPath + "Editor/CompileRule", false, RM_Editor.MenuOrder.Editor)] public static void CreateCompileRule() { RM_Editor.CreateScriptTemplate("CompileRule", MenuLayer); diff --git a/Editor/Core/Utilities/Editor_Library.cs b/Editor/Core/Utilities/Editor_Library.cs index 4a9ea67..54bd01e 100644 --- a/Editor/Core/Utilities/Editor_Library.cs +++ b/Editor/Core/Utilities/Editor_Library.cs @@ -15,6 +15,34 @@ public enum RealMethodLayer public static class RM_Editor { + public static class MenuOrder + { + private const int starter = 80; + private const int space = 1; + private const int priorityjumps = 11; + + + + public const int Essential_Head = starter; + public const int Essential_Body = Essential_Head; + public const int Manager_Head = Essential_Head + space; + public const int Manager_Body = Manager_Head + priorityjumps; + public const int Service_Head = Manager_Head + space; + public const int Service_Body = Service_Head + priorityjumps; + public const int DataAsset_Head = Service_Head + space; + public const int DataAsset_Body = DataAsset_Head + priorityjumps; + public const int CloneAsset_Head = DataAsset_Head + space; + public const int CloneAsset_Body = CloneAsset_Head + priorityjumps; + public const int UniqueAsset_Head = CloneAsset_Head + space; + public const int UniqueAsset_Body = UniqueAsset_Head + priorityjumps; + public const int ConfigAsset_Head = UniqueAsset_Head + space; + public const int ConfigAsset_Body = ConfigAsset_Head + priorityjumps; + public const int FileAsset_Head = ConfigAsset_Head + space; + public const int FileAsset_Body = FileAsset_Head + priorityjumps; + public const int Method = FileAsset_Head + space; + public const int Toolkit = Method + space; + public const int Editor = Toolkit + space + priorityjumps; + } public static string SetttingAssetPath = ProjectSettingAsset.Path; public static string ScriptTemplatesPath => GetPackagePath("com.mustard.realmethod") + "/Reservoir/ScriptTemplates"; public static string PrefabTemplatePath => GetPackagePath("com.mustard.realmethod") + "/Reservoir/Prefabs"; @@ -29,6 +57,10 @@ public static bool IsPlayMode } } + + + + // Functions public static bool TryGetSettingAsset(out ProjectSettingAsset settings) { // Attempt to load the settings asset from the specified path @@ -111,7 +143,7 @@ public static string GetScenePathByName(string name) - + // Methods private static string CreateScriptTemplate(string templateFileName, string defaultName) { string templatePath = string.Empty; diff --git a/Editor/Pattern/MenuItem/PatternMenu.cs b/Editor/Pattern/MenuItem/PatternMenu.cs index c5f3946..d0d769e 100644 --- a/Editor/Pattern/MenuItem/PatternMenu.cs +++ b/Editor/Pattern/MenuItem/PatternMenu.cs @@ -10,127 +10,127 @@ class PatternMenu ////////////// Scripts \\\\\\\\\\\\ // Managers - [MenuItem(RM_Editor.ScriptMenuItemPath + "Manager/AudioManager", false, 80)] + [MenuItem(RM_Editor.ScriptMenuItemPath + "Manager/AudioManager", false, RM_Editor.MenuOrder.Manager_Body)] public static void CreateAudioManager() { RM_Editor.CreateScriptTemplate("AudioManager", MenuLayer); } - [MenuItem(RM_Editor.ScriptMenuItemPath + "Manager/CompositManager", false, 80)] + [MenuItem(RM_Editor.ScriptMenuItemPath + "Manager/CompositManager", false, RM_Editor.MenuOrder.Manager_Body)] public static void CreateCompositManager() { RM_Editor.CreateScriptTemplate("CompositManager", MenuLayer); } - [MenuItem(RM_Editor.ScriptMenuItemPath + "Manager/DataManager", false, 80)] + [MenuItem(RM_Editor.ScriptMenuItemPath + "Manager/DataManager", false, RM_Editor.MenuOrder.Manager_Body)] public static void CreateDataManager() { RM_Editor.CreateScriptTemplate("DataManager", MenuLayer); } - [MenuItem(RM_Editor.ScriptMenuItemPath + "Manager/GizmoManager", false, 80)] + [MenuItem(RM_Editor.ScriptMenuItemPath + "Manager/GizmoManager", false, RM_Editor.MenuOrder.Manager_Body)] public static void CreateGizmoManager() { RM_Editor.CreateScriptTemplate("GizmoManager", MenuLayer); } - [MenuItem(RM_Editor.ScriptMenuItemPath + "Manager/UIManager", false, 80)] + [MenuItem(RM_Editor.ScriptMenuItemPath + "Manager/UIManager", false, RM_Editor.MenuOrder.Manager_Body)] public static void CreateUIManager() { RM_Editor.CreateScriptTemplate("UIManager", MenuLayer); } - [MenuItem(RM_Editor.ScriptMenuItemPath + "Manager/MixerManager", false, 80)] + [MenuItem(RM_Editor.ScriptMenuItemPath + "Manager/MixerManager", false, RM_Editor.MenuOrder.Manager_Body)] public static void CreateMixerManager() { RM_Editor.CreateScriptTemplate("MixerManager", MenuLayer); } - [MenuItem(RM_Editor.ScriptMenuItemPath + "Manager/HapticManager", false, 80)] + [MenuItem(RM_Editor.ScriptMenuItemPath + "Manager/HapticManager", false, RM_Editor.MenuOrder.Manager_Body)] public static void CreateHapticManager() { RM_Editor.CreateScriptTemplate("HapticManager", MenuLayer); } - [MenuItem(RM_Editor.ScriptMenuItemPath + "Manager/TickManager", false, 80)] + [MenuItem(RM_Editor.ScriptMenuItemPath + "Manager/TickManager", false, RM_Editor.MenuOrder.Manager_Body)] public static void CreateTickManager() { RM_Editor.CreateScriptTemplate("TickManager", MenuLayer); } // Services - [MenuItem(RM_Editor.ScriptMenuItemPath + "Service/StateService", false, 80)] + [MenuItem(RM_Editor.ScriptMenuItemPath + "Service/StateService", false, RM_Editor.MenuOrder.Service_Body)] public static void CreateStateService() { RM_Editor.CreateScriptTemplate("StateService", MenuLayer); } - [MenuItem(RM_Editor.ScriptMenuItemPath + "Service/RuleService", false, 80)] + [MenuItem(RM_Editor.ScriptMenuItemPath + "Service/RuleService", false, RM_Editor.MenuOrder.Service_Body)] public static void CreateRuleService() { RM_Editor.CreateScriptTemplate("RuleService", MenuLayer); } // Assets - [MenuItem(RM_Editor.ScriptMenuItemPath + "Asset/Data/Table", false, 80)] + [MenuItem(RM_Editor.ScriptMenuItemPath + "Asset/Data/Table", false, RM_Editor.MenuOrder.DataAsset_Body)] public static void CreateTableAsset() { RM_Editor.CreateScriptTemplate("TableAsset", MenuLayer); } - [MenuItem(RM_Editor.ScriptMenuItemPath + "Asset/Data/Task", false, 80)] + [MenuItem(RM_Editor.ScriptMenuItemPath + "Asset/Data/Task", false, RM_Editor.MenuOrder.DataAsset_Body)] public static void CreateTaskAsset() { RM_Editor.CreateScriptTemplate("TaskAsset", MenuLayer); } - [MenuItem(RM_Editor.ScriptMenuItemPath + "Asset/Config/Item", false, 80)] + [MenuItem(RM_Editor.ScriptMenuItemPath + "Asset/Config/Item", false, RM_Editor.MenuOrder.ConfigAsset_Body)] public static void CreateItemConfig() { RM_Editor.CreateScriptTemplate("ItemConfig", MenuLayer); } - [MenuItem(RM_Editor.ScriptMenuItemPath + "Asset/Config/Haptic", false, 80)] + [MenuItem(RM_Editor.ScriptMenuItemPath + "Asset/Config/Haptic", false, RM_Editor.MenuOrder.ConfigAsset_Body)] public static void CreateHapticConfig() { RM_Editor.CreateScriptTemplate("HapticConfig", MenuLayer); } - [MenuItem(RM_Editor.ScriptMenuItemPath + "Asset/File/Save", false, 80)] + [MenuItem(RM_Editor.ScriptMenuItemPath + "Asset/File/Save", false, RM_Editor.MenuOrder.FileAsset_Body)] public static void CreateSaveFile() { RM_Editor.CreateScriptTemplate("SaveFile", MenuLayer); } - [MenuItem(RM_Editor.ScriptMenuItemPath + "Asset/File/GameSetting", false, 80)] + [MenuItem(RM_Editor.ScriptMenuItemPath + "Asset/File/GameSetting", false, RM_Editor.MenuOrder.FileAsset_Body)] public static void CreateGameSettingFile() { RM_Editor.CreateScriptTemplate("GameSettingFile", MenuLayer); } - [MenuItem(RM_Editor.ScriptMenuItemPath + "Asset/Unique/SharedRootAsset", false, 80)] + [MenuItem(RM_Editor.ScriptMenuItemPath + "Asset/Unique/SharedRootAsset", false, RM_Editor.MenuOrder.UniqueAsset_Body)] public static void CreateSharedRootAsset() { RM_Editor.CreateScriptTemplate("SharedRootAsset", MenuLayer); } - [MenuItem(RM_Editor.ScriptMenuItemPath + "Asset/Unique/PoolAsset", false, 80)] + [MenuItem(RM_Editor.ScriptMenuItemPath + "Asset/Unique/PoolAsset", false, RM_Editor.MenuOrder.UniqueAsset_Body)] public static void CreatePoolAsset() { RM_Editor.CreateScriptTemplate("PoolAsset", MenuLayer); } // UI - [MenuItem(RM_Editor.ScriptMenuItemPath + "General/UI/Widget", false, 80)] + [MenuItem(RM_Editor.ScriptMenuItemPath + "Method/UI/Widget", false, RM_Editor.MenuOrder.Method)] public static void CreateWidget() { RM_Editor.CreateScriptTemplate("Widget", MenuLayer); } - [MenuItem(RM_Editor.ScriptMenuItemPath + "General/UI/WidgetToolkit", false, 80)] + [MenuItem(RM_Editor.ScriptMenuItemPath + "Method/UI/WidgetToolkit", false, RM_Editor.MenuOrder.Method)] public static void CreateWidgetToolkit() { RM_Editor.CreateScriptTemplate("WidgetToolkit", MenuLayer); } // Command - [MenuItem(RM_Editor.ScriptMenuItemPath + "General/Command", false, 80)] + [MenuItem(RM_Editor.ScriptMenuItemPath + "Method/Command", false, RM_Editor.MenuOrder.Method)] public static void CreateCommand() { RM_Editor.CreateScriptTemplate("Command", MenuLayer); } - + // Trigger - [MenuItem(RM_Editor.ScriptMenuItemPath + "General/Trigger/Trigger3D", false, 80)] + [MenuItem(RM_Editor.ScriptMenuItemPath + "Method/Trigger/Trigger3D", false, RM_Editor.MenuOrder.Method)] public static void CreateTrigger3D() { RM_Editor.CreateScriptTemplate("Trigger3D", MenuLayer); } - [MenuItem(RM_Editor.ScriptMenuItemPath + "General/Trigger/Trigger2D", false, 80)] + [MenuItem(RM_Editor.ScriptMenuItemPath + "Method/Trigger/Trigger2D", false, RM_Editor.MenuOrder.Method)] public static void CreateTrigger2D() { RM_Editor.CreateScriptTemplate("Trigger2D", MenuLayer); diff --git a/Editor/Toolkit/Ability/AbilityMenu.cs b/Editor/Toolkit/Ability/AbilityMenu.cs index 1cf07b8..c21b344 100644 --- a/Editor/Toolkit/Ability/AbilityMenu.cs +++ b/Editor/Toolkit/Ability/AbilityMenu.cs @@ -8,17 +8,17 @@ class AbilityMenu - [MenuItem(RM_Editor.ScriptMenuItemPath + "Toolkit/Ability/AbilityAsset", false, 80)] + [MenuItem(RM_Editor.ScriptMenuItemPath + "Toolkit/Ability/AbilityAsset", false, RM_Editor.MenuOrder.Toolkit)] public static void CreateAbilityAsset() { RM_Editor.CreateScriptTemplate("AbilityAsset", MenuLayer); } - [MenuItem(RM_Editor.ScriptMenuItemPath + "Toolkit/Ability/AbilityActionAsset", false, 80)] + [MenuItem(RM_Editor.ScriptMenuItemPath + "Toolkit/Ability/AbilityActionAsset", false, RM_Editor.MenuOrder.Toolkit)] public static void CreateAbilityAction() { RM_Editor.CreateScriptTemplate("AbilityActionAsset", MenuLayer); } - [MenuItem(RM_Editor.ScriptMenuItemPath + "Toolkit/Ability/Effect", false, 80)] + [MenuItem(RM_Editor.ScriptMenuItemPath + "Toolkit/Ability/Effect", false, RM_Editor.MenuOrder.Toolkit)] public static void CreateEffect() { RM_Editor.CreateScriptTemplate("AbilityEffect", MenuLayer); diff --git a/Editor/Toolkit/Actor/ActorMenu.cs b/Editor/Toolkit/Actor/ActorMenu.cs index 2796d62..0b35707 100644 --- a/Editor/Toolkit/Actor/ActorMenu.cs +++ b/Editor/Toolkit/Actor/ActorMenu.cs @@ -7,7 +7,7 @@ class ActorMenu private const RealMethodLayer MenuLayer = RealMethodLayer.Toolkit; - [MenuItem(RM_Editor.ScriptMenuItemPath + "Toolkit/Actor/Act", false, 80)] + [MenuItem(RM_Editor.ScriptMenuItemPath + "Toolkit/Actor/Act", false, RM_Editor.MenuOrder.Toolkit)] public static void CreateActCommand() { RM_Editor.CreateScriptTemplate("Act", MenuLayer); diff --git a/Editor/Toolkit/Inventory/InventoryMenu.cs b/Editor/Toolkit/Inventory/InventoryMenu.cs index bc0feeb..83f1a09 100644 --- a/Editor/Toolkit/Inventory/InventoryMenu.cs +++ b/Editor/Toolkit/Inventory/InventoryMenu.cs @@ -8,7 +8,7 @@ class InventoryMenu - [MenuItem(RM_Editor.ScriptMenuItemPath + "Toolkit/Inventory/Item", false, 80)] + [MenuItem(RM_Editor.ScriptMenuItemPath + "Toolkit/Inventory/Item", false, RM_Editor.MenuOrder.Toolkit)] public static void CreateItem() { RM_Editor.CreateScriptTemplate("InventoryItem", MenuLayer); diff --git a/Editor/Toolkit/PCG/PCGMenu.cs b/Editor/Toolkit/PCG/PCGMenu.cs index 586d190..3c97e9e 100644 --- a/Editor/Toolkit/PCG/PCGMenu.cs +++ b/Editor/Toolkit/PCG/PCGMenu.cs @@ -6,7 +6,7 @@ class PCGMenu { private const RealMethodLayer MenuLayer = RealMethodLayer.Toolkit; - [MenuItem(RM_Editor.ScriptMenuItemPath + "Toolkit/PCG/Request", false, 80)] + [MenuItem(RM_Editor.ScriptMenuItemPath + "Toolkit/PCG/Request", false, RM_Editor.MenuOrder.Toolkit)] public static void CreatePCGRequest() { RM_Editor.CreateScriptTemplate("PCGRequest", MenuLayer); diff --git a/Editor/Toolkit/Pickup/PickupMenu.cs b/Editor/Toolkit/Pickup/PickupMenu.cs index fb59fd6..2771648 100644 --- a/Editor/Toolkit/Pickup/PickupMenu.cs +++ b/Editor/Toolkit/Pickup/PickupMenu.cs @@ -7,12 +7,12 @@ class PickupMenu private const RealMethodLayer MenuLayer = RealMethodLayer.Toolkit; - [MenuItem(RM_Editor.ScriptMenuItemPath + "Toolkit/Pickup/Pickup3D", false, 80)] + [MenuItem(RM_Editor.ScriptMenuItemPath + "Toolkit/Pickup/Pickup3D", false, RM_Editor.MenuOrder.Toolkit)] public static void CreatePickup3D() { RM_Editor.CreateScriptTemplate("Pickup3D", MenuLayer); } - [MenuItem(RM_Editor.ScriptMenuItemPath + "Toolkit/Pickup/Pickup2D", false, 80)] + [MenuItem(RM_Editor.ScriptMenuItemPath + "Toolkit/Pickup/Pickup2D", false, RM_Editor.MenuOrder.Toolkit)] public static void CreatePickup2D() { RM_Editor.CreateScriptTemplate("Pickup2D", MenuLayer); diff --git a/Editor/Toolkit/RPG/RPGMenu.cs b/Editor/Toolkit/RPG/RPGMenu.cs index 57cc049..527d00a 100644 --- a/Editor/Toolkit/RPG/RPGMenu.cs +++ b/Editor/Toolkit/RPG/RPGMenu.cs @@ -8,22 +8,22 @@ class RPGMenu - [MenuItem(RM_Editor.ScriptMenuItemPath + "Toolkit/RPG/StatDefinition", false, 80)] + [MenuItem(RM_Editor.ScriptMenuItemPath + "Toolkit/RPG/StatDefinition", false, RM_Editor.MenuOrder.Toolkit)] public static void CreateStatDefinition() { RM_Editor.CreateScriptTemplate("StatDefinition", MenuLayer); } - [MenuItem(RM_Editor.ScriptMenuItemPath + "Toolkit/RPG/StatProfile", false, 80)] + [MenuItem(RM_Editor.ScriptMenuItemPath + "Toolkit/RPG/StatProfile", false, RM_Editor.MenuOrder.Toolkit)] public static void CreateStatProfile() { RM_Editor.CreateScriptTemplate("StatProfile", MenuLayer); } - [MenuItem(RM_Editor.ScriptMenuItemPath + "Toolkit/RPG/StatBuff", false, 80)] + [MenuItem(RM_Editor.ScriptMenuItemPath + "Toolkit/RPG/StatBuff", false, RM_Editor.MenuOrder.Toolkit)] public static void CreateBuffConfig() { RM_Editor.CreateScriptTemplate("BuffConfig", MenuLayer); } - [MenuItem(RM_Editor.ScriptMenuItemPath + "Toolkit/RPG/ResourceData", false, 80)] + [MenuItem(RM_Editor.ScriptMenuItemPath + "Toolkit/RPG/ResourceData", false, RM_Editor.MenuOrder.Toolkit)] public static void CreateResourceData() { RM_Editor.CreateScriptTemplate("ResourceData", MenuLayer); diff --git a/Editor/Toolkit/Tutorial/TutorialMenu.cs b/Editor/Toolkit/Tutorial/TutorialMenu.cs index 0fde983..6ced5b6 100644 --- a/Editor/Toolkit/Tutorial/TutorialMenu.cs +++ b/Editor/Toolkit/Tutorial/TutorialMenu.cs @@ -7,17 +7,17 @@ class TutorialMenu private const RealMethodLayer MenuLayer = RealMethodLayer.Toolkit; - [MenuItem(RM_Editor.ScriptMenuItemPath + "Toolkit/Tutorial/Screen", false, 80)] + [MenuItem(RM_Editor.ScriptMenuItemPath + "Toolkit/Tutorial/Screen", false, RM_Editor.MenuOrder.Toolkit)] public static void CreateTutorialScreen() { RM_Editor.CreateScriptTemplate("TutorialScreen", MenuLayer); } - [MenuItem(RM_Editor.ScriptMenuItemPath + "Toolkit/Tutorial/UIunit", false, 80)] + [MenuItem(RM_Editor.ScriptMenuItemPath + "Toolkit/Tutorial/UIunit", false, RM_Editor.MenuOrder.Toolkit)] public static void CreateTutorialMessage() { RM_Editor.CreateScriptTemplate("TutorialUnit", MenuLayer); } - [MenuItem(RM_Editor.ScriptMenuItemPath + "Toolkit/Tutorial/Config", false, 80)] + [MenuItem(RM_Editor.ScriptMenuItemPath + "Toolkit/Tutorial/Config", false, RM_Editor.MenuOrder.Toolkit)] public static void CreateTutorialConfig() { RM_Editor.CreateScriptTemplate("TutorialConfig", MenuLayer); diff --git a/Editor/Toolkit/Upgrade/UpgradeMenu.cs b/Editor/Toolkit/Upgrade/UpgradeMenu.cs index 6b8f486..bffe6af 100644 --- a/Editor/Toolkit/Upgrade/UpgradeMenu.cs +++ b/Editor/Toolkit/Upgrade/UpgradeMenu.cs @@ -8,12 +8,12 @@ class UpgradeMenu - [MenuItem(RM_Editor.ScriptMenuItemPath + "Toolkit/Upgrade/Item", false, 80)] + [MenuItem(RM_Editor.ScriptMenuItemPath + "Toolkit/Upgrade/Item", false, RM_Editor.MenuOrder.Toolkit)] public static void CreateItem() { RM_Editor.CreateScriptTemplate("UpgradeItem", MenuLayer); } - [MenuItem(RM_Editor.ScriptMenuItemPath + "Toolkit/Upgrade/Map", false, 80)] + [MenuItem(RM_Editor.ScriptMenuItemPath + "Toolkit/Upgrade/Map", false, RM_Editor.MenuOrder.Toolkit)] public static void CreateConfig() { RM_Editor.CreateScriptTemplate("UpgradeConfig", MenuLayer); From 618dd95a2f64d26ffcb8d5ab86133d5b8a4a8301 Mon Sep 17 00:00:00 2001 From: Alijimpa Date: Sat, 18 Apr 2026 22:12:50 +0330 Subject: [PATCH 114/204] Refine all Audio Manager --- Editor/Core/MenuItem/CoreMenu.cs | 4 +- Runtime/Pattern/Managers/AudioManager.cs | 5 ++- Runtime/Pattern/Managers/CompositManager.cs | 3 +- Runtime/Pattern/Managers/MixerManager.cs | 46 ++++++++++----------- Runtime/ReadySet/Managers/MusicManager.cs | 4 +- Runtime/ReadySet/Managers/SoundManager.cs | 2 +- 6 files changed, 32 insertions(+), 32 deletions(-) diff --git a/Editor/Core/MenuItem/CoreMenu.cs b/Editor/Core/MenuItem/CoreMenu.cs index b68d671..3afc334 100644 --- a/Editor/Core/MenuItem/CoreMenu.cs +++ b/Editor/Core/MenuItem/CoreMenu.cs @@ -9,7 +9,7 @@ class CoreMenu ///////////// GameObject \\\\\\\\\\\\ - [MenuItem(RM_Editor.GameObjectMenuItemPath + "PlayerStarter", false, 10)] + [MenuItem(RM_Editor.GameObjectMenuItemPath + "PlayerStarter", false, 1)] static void CreatePlayerStarter(MenuCommand menuCommand) { // Create a new GameObject @@ -27,7 +27,7 @@ static void CreatePlayerStarter(MenuCommand menuCommand) // Select the new GameObject Selection.activeObject = go; } - [MenuItem(RM_Editor.GameObjectMenuItemPath + "World", false, 10)] + [MenuItem(RM_Editor.GameObjectMenuItemPath + "World", false, 1)] static void CreateWorld(MenuCommand menuCommand) { // Create a new GameObject diff --git a/Runtime/Pattern/Managers/AudioManager.cs b/Runtime/Pattern/Managers/AudioManager.cs index 649ec9d..7d71ad4 100644 --- a/Runtime/Pattern/Managers/AudioManager.cs +++ b/Runtime/Pattern/Managers/AudioManager.cs @@ -15,10 +15,11 @@ public abstract class AudioManager : MixerManager public ObjectPool soundPool; - protected override void InitiateManager(bool AlwaysLoaded) + // Manager + public override void InitiateManager(bool AlwaysLoaded) { base.InitiateManager(AlwaysLoaded); - + if (AlwaysLoaded) { Debug.LogError("You can't use AudioManager in [Game] Scope"); diff --git a/Runtime/Pattern/Managers/CompositManager.cs b/Runtime/Pattern/Managers/CompositManager.cs index 5714665..690b4b9 100644 --- a/Runtime/Pattern/Managers/CompositManager.cs +++ b/Runtime/Pattern/Managers/CompositManager.cs @@ -40,7 +40,7 @@ public void Pitch(float alpha, float minPitch = -3f, float maxPitch = 3f) public int LayerCount => Layers.Count; // Override Methods - protected override void InitiateManager(bool AlwaysLoaded) + public override void InitiateManager(bool AlwaysLoaded) { base.InitiateManager(AlwaysLoaded); @@ -270,7 +270,6 @@ public MusicLerp CreateLerp(Name16 LayerA, Name16 LayerB) } return new MusicLerp((AudioSource)Layers[LayerA], (AudioSource)Layers[LayerB]); } - } public abstract class CompositManager : CompositManager diff --git a/Runtime/Pattern/Managers/MixerManager.cs b/Runtime/Pattern/Managers/MixerManager.cs index ade5b2b..59abf4e 100644 --- a/Runtime/Pattern/Managers/MixerManager.cs +++ b/Runtime/Pattern/Managers/MixerManager.cs @@ -15,34 +15,24 @@ public abstract class MixerManager : MonoBehaviour, IGameManager private Map Parameter; #endif - // Operators - public float this[string param] - { - get - { - mixer.GetFloat(param, out float result); - return result; - } - set => mixer.SetFloat(param, value); - } // IGameManager Interface Implementation MonoBehaviour IGameManager.GetManagerClass() { return this; } - void IGameManager.InitiateManager(bool AlwaysLoaded) + public virtual void InitiateManager(bool AlwaysLoaded) { - InitiateManager(AlwaysLoaded); + } - void IGameManager.ResolveService(Service service, bool active) + public virtual void ResolveService(Service service, bool active) { - ResolveService(service, active); + } // Unity Methods #if UNITY_EDITOR - private void OnValidate() + protected virtual void OnValidate() { if (mixer != null) { @@ -60,19 +50,29 @@ private void OnValidate() #endif // Public Functions - public void TransitionToSnapshot(AudioMixerSnapshot snapshot, float transitionTime = 1f) + public void SetParam(string param, float value) { - snapshot?.TransitionTo(transitionTime); + mixer.SetFloat(param, value); } - - // Protected Method - protected virtual void InitiateManager(bool AlwaysLoaded) + public float GetParam(string param) { - + if (mixer.GetFloat(param, out float result)) + { + return result; + } + else + { + Debug.LogError($"Can't find any value with param:({param})"); + return 0; + } } - protected virtual void ResolveService(Service service, bool active) + public bool TryGetParam(string param, out float result) { - + return mixer.GetFloat(param, out result); + } + public void TransitionToSnapshot(AudioMixerSnapshot snapshot, float transitionTime = 1f) + { + snapshot?.TransitionTo(transitionTime); } } diff --git a/Runtime/ReadySet/Managers/MusicManager.cs b/Runtime/ReadySet/Managers/MusicManager.cs index 78350de..43dc7e5 100644 --- a/Runtime/ReadySet/Managers/MusicManager.cs +++ b/Runtime/ReadySet/Managers/MusicManager.cs @@ -9,8 +9,8 @@ public sealed class MusicManager : CompositManager [SerializeField] private Map Clips = new Map(); - // IGameManager Interface - protected override void InitiateManager(bool AlwaysLoaded) + // GameManager + public override void InitiateManager(bool AlwaysLoaded) { base.InitiateManager(AlwaysLoaded); foreach (var clip in Clips) diff --git a/Runtime/ReadySet/Managers/SoundManager.cs b/Runtime/ReadySet/Managers/SoundManager.cs index 531e585..ab3c94e 100644 --- a/Runtime/ReadySet/Managers/SoundManager.cs +++ b/Runtime/ReadySet/Managers/SoundManager.cs @@ -6,7 +6,7 @@ namespace RealMethod public sealed class SoundManager : AudioManager { // AudioManager Methods - protected override void ResolveService(Service service, bool active) + public override void ResolveService(Service service, bool active) { base.ResolveService(service, active); } From 43f56e2139fc93c5b23d87a5f315e5ea42c01e5b Mon Sep 17 00:00:00 2001 From: Alijimpa Date: Sun, 19 Apr 2026 20:35:05 +0330 Subject: [PATCH 115/204] Refine FileAsset oredering and defenation --- Editor/Core/MenuItem/CoreMenu.cs | 5 -- Editor/Core/Utilities/Editor_Library.cs | 4 +- Editor/Pattern/MenuItem/PatternMenu.cs | 10 ++- .../{Core => Pattern}/FileAssetTemplate.txt | 0 .../FileAssetTemplate.txt.meta | 0 Runtime/Core/Definitions/Assets.cs | 33 ++------- Runtime/Library/Interfaces/File.cs | 10 +++ Runtime/Library/Interfaces/File.cs.meta | 2 + Runtime/Pattern/Assets/FileAsset.cs | 68 +++++++++++++++++++ Runtime/Pattern/Assets/FileAsset.cs.meta | 2 + 10 files changed, 96 insertions(+), 38 deletions(-) rename Reservoir/ScriptTemplates/{Core => Pattern}/FileAssetTemplate.txt (100%) rename Reservoir/ScriptTemplates/{Core => Pattern}/FileAssetTemplate.txt.meta (100%) create mode 100644 Runtime/Library/Interfaces/File.cs create mode 100644 Runtime/Library/Interfaces/File.cs.meta create mode 100644 Runtime/Pattern/Assets/FileAsset.cs create mode 100644 Runtime/Pattern/Assets/FileAsset.cs.meta diff --git a/Editor/Core/MenuItem/CoreMenu.cs b/Editor/Core/MenuItem/CoreMenu.cs index 3afc334..3019d2c 100644 --- a/Editor/Core/MenuItem/CoreMenu.cs +++ b/Editor/Core/MenuItem/CoreMenu.cs @@ -97,11 +97,6 @@ public static void CreateConfigAsset() { RM_Editor.CreateScriptTemplate("ConfigAsset", MenuLayer); } - [MenuItem(RM_Editor.ScriptMenuItemPath + "Asset/File/EmptyFileAsset", false, RM_Editor.MenuOrder.FileAsset_Head)] - public static void CreateFileAsset() - { - RM_Editor.CreateScriptTemplate("FileAsset", MenuLayer); - } [MenuItem(RM_Editor.ScriptMenuItemPath + "Asset/Config/Game", false, RM_Editor.MenuOrder.ConfigAsset_Body)] public static void CreateGameConfig() { diff --git a/Editor/Core/Utilities/Editor_Library.cs b/Editor/Core/Utilities/Editor_Library.cs index 54bd01e..d5802a7 100644 --- a/Editor/Core/Utilities/Editor_Library.cs +++ b/Editor/Core/Utilities/Editor_Library.cs @@ -37,9 +37,7 @@ public static class MenuOrder public const int UniqueAsset_Body = UniqueAsset_Head + priorityjumps; public const int ConfigAsset_Head = UniqueAsset_Head + space; public const int ConfigAsset_Body = ConfigAsset_Head + priorityjumps; - public const int FileAsset_Head = ConfigAsset_Head + space; - public const int FileAsset_Body = FileAsset_Head + priorityjumps; - public const int Method = FileAsset_Head + space; + public const int Method = ConfigAsset_Body + space; public const int Toolkit = Method + space; public const int Editor = Toolkit + space + priorityjumps; } diff --git a/Editor/Pattern/MenuItem/PatternMenu.cs b/Editor/Pattern/MenuItem/PatternMenu.cs index d0d769e..cc59c40 100644 --- a/Editor/Pattern/MenuItem/PatternMenu.cs +++ b/Editor/Pattern/MenuItem/PatternMenu.cs @@ -84,12 +84,17 @@ public static void CreateHapticConfig() { RM_Editor.CreateScriptTemplate("HapticConfig", MenuLayer); } - [MenuItem(RM_Editor.ScriptMenuItemPath + "Asset/File/Save", false, RM_Editor.MenuOrder.FileAsset_Body)] + [MenuItem(RM_Editor.ScriptMenuItemPath + "Asset/File/EmptyFileAsset", false, RM_Editor.MenuOrder.UniqueAsset_Body)] + public static void CreateFileAsset() + { + RM_Editor.CreateScriptTemplate("FileAsset", MenuLayer); + } + [MenuItem(RM_Editor.ScriptMenuItemPath + "Asset/File/Save", false, RM_Editor.MenuOrder.UniqueAsset_Body)] public static void CreateSaveFile() { RM_Editor.CreateScriptTemplate("SaveFile", MenuLayer); } - [MenuItem(RM_Editor.ScriptMenuItemPath + "Asset/File/GameSetting", false, RM_Editor.MenuOrder.FileAsset_Body)] + [MenuItem(RM_Editor.ScriptMenuItemPath + "Asset/File/GameSetting", false, RM_Editor.MenuOrder.UniqueAsset_Body)] public static void CreateGameSettingFile() { RM_Editor.CreateScriptTemplate("GameSettingFile", MenuLayer); @@ -105,6 +110,7 @@ public static void CreatePoolAsset() RM_Editor.CreateScriptTemplate("PoolAsset", MenuLayer); } + // UI [MenuItem(RM_Editor.ScriptMenuItemPath + "Method/UI/Widget", false, RM_Editor.MenuOrder.Method)] public static void CreateWidget() diff --git a/Reservoir/ScriptTemplates/Core/FileAssetTemplate.txt b/Reservoir/ScriptTemplates/Pattern/FileAssetTemplate.txt similarity index 100% rename from Reservoir/ScriptTemplates/Core/FileAssetTemplate.txt rename to Reservoir/ScriptTemplates/Pattern/FileAssetTemplate.txt diff --git a/Reservoir/ScriptTemplates/Core/FileAssetTemplate.txt.meta b/Reservoir/ScriptTemplates/Pattern/FileAssetTemplate.txt.meta similarity index 100% rename from Reservoir/ScriptTemplates/Core/FileAssetTemplate.txt.meta rename to Reservoir/ScriptTemplates/Pattern/FileAssetTemplate.txt.meta diff --git a/Runtime/Core/Definitions/Assets.cs b/Runtime/Core/Definitions/Assets.cs index 6de8f47..4375ec0 100644 --- a/Runtime/Core/Definitions/Assets.cs +++ b/Runtime/Core/Definitions/Assets.cs @@ -6,7 +6,7 @@ namespace RealMethod { - public interface IAsset + public interface IAsset : IIdentifier { PrimitiveAsset GetAsset(); } @@ -19,6 +19,9 @@ public interface IAsset public abstract class PrimitiveAsset : ScriptableObject, IAsset, ISpawn, ISpawnWithAuthor { public bool IsSpawned { get; private set; } = false; + + // Implement IIdentifier Interface + public Name16 NameID => name; // Implement IAsset Interface PrimitiveAsset IAsset.GetAsset() => this; // Implement ISpawn interface @@ -157,30 +160,4 @@ public abstract class ConfigAsset : UniqueAsset { } - /// - /// A specialized UniqueAsset used for File system. - /// The asset is uniqueAsset can instance at runtime. - /// and developer can use fileasset for saving data in asset, - /// or in runtime asset creation. - /// The asset itself cannot be used cloned. - /// Instead, the system creates new independent instances based on this asset's data. - /// - public abstract class FileAsset : UniqueAsset - { - protected override void EnsureAssetPermission() - { -#if UNITY_EDITOR || DEVELOPMENT_BUILD - base.EnsureAssetPermission(); - if (IsSpawned) - { - if (IsProjectAsset()) - { - Debug.LogError($"[{name}] This asset is direct asset but Spawn Event called. Asset has been removed!"); - DestroyImmediate(this); - return; - } - } -#endif - } - } -} \ No newline at end of file +} diff --git a/Runtime/Library/Interfaces/File.cs b/Runtime/Library/Interfaces/File.cs new file mode 100644 index 0000000..184ac02 --- /dev/null +++ b/Runtime/Library/Interfaces/File.cs @@ -0,0 +1,10 @@ +using System; + +namespace RealMethod +{ + public interface IFile : IIdentifier + { + DateTime CreateTime { get; } + DateTime ModifiedTime { get; } + } +} \ No newline at end of file diff --git a/Runtime/Library/Interfaces/File.cs.meta b/Runtime/Library/Interfaces/File.cs.meta new file mode 100644 index 0000000..623dd53 --- /dev/null +++ b/Runtime/Library/Interfaces/File.cs.meta @@ -0,0 +1,2 @@ +fileFormatVersion: 2 +guid: 6c684480001c7de4aaf0295cd17845ec \ No newline at end of file diff --git a/Runtime/Pattern/Assets/FileAsset.cs b/Runtime/Pattern/Assets/FileAsset.cs new file mode 100644 index 0000000..c1683ac --- /dev/null +++ b/Runtime/Pattern/Assets/FileAsset.cs @@ -0,0 +1,68 @@ +using System; +using UnityEngine; + +namespace RealMethod +{ + /// + /// A specialized UniqueAsset used for File system. + /// The asset is uniqueAsset can instance at runtime. + /// and developer can use fileasset for saving data in asset, + /// or in runtime asset creation. + /// The asset itself cannot be used cloned. + /// Instead, the system creates new independent instances based on this asset's data. + /// + public abstract class FileAsset : UniqueAsset, IFile + { + [Header("File")] + [SerializeField, TextArea(5, 20)] + private string fileContents; + private DateTime createTime; + private DateTime modifiedTime; + + // Implement IFile Interface + DateTime IFile.CreateTime => createTime; + DateTime IFile.ModifiedTime => modifiedTime; + + // Unity Events + protected virtual void OnEnable() + { + createTime = DateTime.Now; + } + + // Virtual Methods + protected sealed override void EnsureAssetPermission() + { +#if UNITY_EDITOR || DEVELOPMENT_BUILD + if (HasCloneName()) + { + Debug.LogError($"[{name}] FileAsset cannot clone at runtime. NewAsset has been removed!"); + DestroyImmediate(this); + return; + } + if (IsSpawned) + { + if (IsProjectAsset()) + { + Debug.LogError($"[{name}] This asset is direct asset but Spawn Event called. Asset has been removed!"); + DestroyImmediate(this); + return; + } + } +#endif + } + + // Protected Methods + protected void Modifiy() + { + modifiedTime = DateTime.Now; + EnsureAssetPermission(); + } + +#if UNITY_EDITOR + protected virtual void OnValidate() + { + Modifiy(); + } +#endif + } +} \ No newline at end of file diff --git a/Runtime/Pattern/Assets/FileAsset.cs.meta b/Runtime/Pattern/Assets/FileAsset.cs.meta new file mode 100644 index 0000000..3e03daa --- /dev/null +++ b/Runtime/Pattern/Assets/FileAsset.cs.meta @@ -0,0 +1,2 @@ +fileFormatVersion: 2 +guid: ea69fb27b44567a4ba06ab6a8464898d \ No newline at end of file From 834d1fc21f6cc7956343ea2d95dcf0be5b224755 Mon Sep 17 00:00:00 2001 From: Alijimpa Date: Mon, 20 Apr 2026 22:14:28 +0330 Subject: [PATCH 116/204] Refine SaveManager --- ...aManagerEditor.cs => SaveManagerEditor.cs} | 8 +- ...itor.cs.meta => SaveManagerEditor.cs.meta} | 0 Editor/Pattern/MenuItem/PatternMenu.cs | 6 +- .../Pattern/DataManagerTemplate.txt | 28 - .../Pattern/GameSettingFileTemplate.txt | 2 +- .../Pattern/GizmoManagerTemplate.txt | 2 +- .../Pattern/SaveFileTemplate.txt | 6 - .../Pattern/SaveManagerTemplate.txt | 6 + ....txt.meta => SaveManagerTemplate.txt.meta} | 0 Runtime/Library/Interfaces/File.cs | 2 + Runtime/Library/Interfaces/Save.cs | 16 + Runtime/Library/Interfaces/Save.cs.meta | 2 + Runtime/Pattern/Assets/SaveFile.cs | 66 ++ Runtime/Pattern/Assets/SaveFile.cs.meta | 2 + Runtime/Pattern/Managers/DataManager.cs | 405 ------------ Runtime/Pattern/Managers/SaveManager.cs | 616 ++++++++++++++++++ Runtime/Pattern/Managers/SaveManager.cs.meta | 2 + Runtime/Pattern/Managers/StorageFile.cs | 118 ++++ ...ataManager.cs.meta => StorageFile.cs.meta} | 0 .../Components/Method/SharedObject.cs | 20 - .../Components/Method/SharedObject.cs.meta | 2 - Runtime/ReadySet/Managers/SaveManager.cs | 365 ----------- Runtime/ReadySet/Managers/StorageManager.cs | 10 + ...Manager.cs.meta => StorageManager.cs.meta} | 0 .../Toolkit/Inventory/InventorySaveFile.cs | 13 - .../Toolkit/RPG/StatSystem/StatSaveFile.cs | 13 - Runtime/Toolkit/Tutorial/TutorialSaveFile.cs | 8 - Runtime/Toolkit/Upgrade/UpgradeSaveFile.cs | 12 - Tests/FileManager.cs | 118 ++++ Tests/FileManager.cs.meta | 2 + Tests/General/MissionManager.cs | 4 +- Tests/General/TutorialManager.cs | 2 +- 32 files changed, 971 insertions(+), 885 deletions(-) rename Editor/Pattern/Inspectors/{DataManagerEditor.cs => SaveManagerEditor.cs} (82%) rename Editor/Pattern/Inspectors/{DataManagerEditor.cs.meta => SaveManagerEditor.cs.meta} (100%) delete mode 100644 Reservoir/ScriptTemplates/Pattern/DataManagerTemplate.txt create mode 100644 Reservoir/ScriptTemplates/Pattern/SaveManagerTemplate.txt rename Reservoir/ScriptTemplates/Pattern/{DataManagerTemplate.txt.meta => SaveManagerTemplate.txt.meta} (100%) create mode 100644 Runtime/Library/Interfaces/Save.cs create mode 100644 Runtime/Library/Interfaces/Save.cs.meta create mode 100644 Runtime/Pattern/Assets/SaveFile.cs create mode 100644 Runtime/Pattern/Assets/SaveFile.cs.meta delete mode 100644 Runtime/Pattern/Managers/DataManager.cs create mode 100644 Runtime/Pattern/Managers/SaveManager.cs create mode 100644 Runtime/Pattern/Managers/SaveManager.cs.meta create mode 100644 Runtime/Pattern/Managers/StorageFile.cs rename Runtime/Pattern/Managers/{DataManager.cs.meta => StorageFile.cs.meta} (100%) delete mode 100644 Runtime/ReadySet/Components/Method/SharedObject.cs delete mode 100644 Runtime/ReadySet/Components/Method/SharedObject.cs.meta delete mode 100644 Runtime/ReadySet/Managers/SaveManager.cs create mode 100644 Runtime/ReadySet/Managers/StorageManager.cs rename Runtime/ReadySet/Managers/{SaveManager.cs.meta => StorageManager.cs.meta} (100%) create mode 100644 Tests/FileManager.cs create mode 100644 Tests/FileManager.cs.meta diff --git a/Editor/Pattern/Inspectors/DataManagerEditor.cs b/Editor/Pattern/Inspectors/SaveManagerEditor.cs similarity index 82% rename from Editor/Pattern/Inspectors/DataManagerEditor.cs rename to Editor/Pattern/Inspectors/SaveManagerEditor.cs index 64a0885..9e45873 100644 --- a/Editor/Pattern/Inspectors/DataManagerEditor.cs +++ b/Editor/Pattern/Inspectors/SaveManagerEditor.cs @@ -2,14 +2,14 @@ namespace RealMethod { - [CustomEditor(typeof(DataManager), true)] - public class DataManagerEditor : UnityEditor.Editor + [CustomEditor(typeof(SaveManager), true)] + public class SaveManagerEditor : UnityEditor.Editor { - private DataManager BaseComponent; + private SaveManager BaseComponent; private void OnEnable() { - BaseComponent = (DataManager)target; + BaseComponent = (SaveManager)target; } public override void OnInspectorGUI() diff --git a/Editor/Pattern/Inspectors/DataManagerEditor.cs.meta b/Editor/Pattern/Inspectors/SaveManagerEditor.cs.meta similarity index 100% rename from Editor/Pattern/Inspectors/DataManagerEditor.cs.meta rename to Editor/Pattern/Inspectors/SaveManagerEditor.cs.meta diff --git a/Editor/Pattern/MenuItem/PatternMenu.cs b/Editor/Pattern/MenuItem/PatternMenu.cs index cc59c40..8402b5a 100644 --- a/Editor/Pattern/MenuItem/PatternMenu.cs +++ b/Editor/Pattern/MenuItem/PatternMenu.cs @@ -20,10 +20,10 @@ public static void CreateCompositManager() { RM_Editor.CreateScriptTemplate("CompositManager", MenuLayer); } - [MenuItem(RM_Editor.ScriptMenuItemPath + "Manager/DataManager", false, RM_Editor.MenuOrder.Manager_Body)] - public static void CreateDataManager() + [MenuItem(RM_Editor.ScriptMenuItemPath + "Manager/SaveManager", false, RM_Editor.MenuOrder.Manager_Body)] + public static void CreateSaveManager() { - RM_Editor.CreateScriptTemplate("DataManager", MenuLayer); + RM_Editor.CreateScriptTemplate("SaveManager", MenuLayer); } [MenuItem(RM_Editor.ScriptMenuItemPath + "Manager/GizmoManager", false, RM_Editor.MenuOrder.Manager_Body)] public static void CreateGizmoManager() diff --git a/Reservoir/ScriptTemplates/Pattern/DataManagerTemplate.txt b/Reservoir/ScriptTemplates/Pattern/DataManagerTemplate.txt deleted file mode 100644 index 9991f8e..0000000 --- a/Reservoir/ScriptTemplates/Pattern/DataManagerTemplate.txt +++ /dev/null @@ -1,28 +0,0 @@ -using RealMethod; - -public class #SCRIPTNAME# : DataManager -{ - - // Base DataManager Methods - protected override void ResolveService(Service service, bool active) - { - throw new System.NotImplementedException(); - } - protected override void OnSaveFile(SaveFile targetfile) - { - throw new System.NotImplementedException(); - } - protected override void OnLoadFile(SaveFile targetfile) - { - throw new System.NotImplementedException(); - } - protected override void OnDelete(SaveFile targetfile) - { - throw new System.NotImplementedException(); - } - protected override bool IsExist(SaveFile targetfile) - { - throw new System.NotImplementedException(); - } - -} diff --git a/Reservoir/ScriptTemplates/Pattern/GameSettingFileTemplate.txt b/Reservoir/ScriptTemplates/Pattern/GameSettingFileTemplate.txt index 5a0d620..e749ac6 100644 --- a/Reservoir/ScriptTemplates/Pattern/GameSettingFileTemplate.txt +++ b/Reservoir/ScriptTemplates/Pattern/GameSettingFileTemplate.txt @@ -5,7 +5,7 @@ using UnityEngine; public class #SCRIPTNAME# : SettingFile { // SaveFile Methods - protected override void OnStable(DataManager manager){} + protected override void OnStable(SaveManager manager){} protected override void OnLoaded(){} protected override void OnDeleted(){} diff --git a/Reservoir/ScriptTemplates/Pattern/GizmoManagerTemplate.txt b/Reservoir/ScriptTemplates/Pattern/GizmoManagerTemplate.txt index 546c370..6bcd48b 100644 --- a/Reservoir/ScriptTemplates/Pattern/GizmoManagerTemplate.txt +++ b/Reservoir/ScriptTemplates/Pattern/GizmoManagerTemplate.txt @@ -2,7 +2,7 @@ using RealMethod; public class #SCRIPTNAME# : GizmoManager { - // Base DataManager Methods + // Base SaveManager Methods protected override GUIRenderer[] GetRenderSlots() { throw new System.NotImplementedException(); diff --git a/Reservoir/ScriptTemplates/Pattern/SaveFileTemplate.txt b/Reservoir/ScriptTemplates/Pattern/SaveFileTemplate.txt index 7631c75..84f31a9 100644 --- a/Reservoir/ScriptTemplates/Pattern/SaveFileTemplate.txt +++ b/Reservoir/ScriptTemplates/Pattern/SaveFileTemplate.txt @@ -5,16 +5,10 @@ using UnityEngine; public class #SCRIPTNAME# : SaveFile { // SaveFile Method - protected override void OnStable(DataManager manager) - { - } protected override void OnSaved() { } protected override void OnLoaded() { } - protected override void OnDeleted() - { - } } diff --git a/Reservoir/ScriptTemplates/Pattern/SaveManagerTemplate.txt b/Reservoir/ScriptTemplates/Pattern/SaveManagerTemplate.txt new file mode 100644 index 0000000..7a70b65 --- /dev/null +++ b/Reservoir/ScriptTemplates/Pattern/SaveManagerTemplate.txt @@ -0,0 +1,6 @@ +using RealMethod; + +public class #SCRIPTNAME# : SaveMethodManager +{ + +} diff --git a/Reservoir/ScriptTemplates/Pattern/DataManagerTemplate.txt.meta b/Reservoir/ScriptTemplates/Pattern/SaveManagerTemplate.txt.meta similarity index 100% rename from Reservoir/ScriptTemplates/Pattern/DataManagerTemplate.txt.meta rename to Reservoir/ScriptTemplates/Pattern/SaveManagerTemplate.txt.meta diff --git a/Runtime/Library/Interfaces/File.cs b/Runtime/Library/Interfaces/File.cs index 184ac02..e544c12 100644 --- a/Runtime/Library/Interfaces/File.cs +++ b/Runtime/Library/Interfaces/File.cs @@ -4,7 +4,9 @@ namespace RealMethod { public interface IFile : IIdentifier { + string Name { get; } DateTime CreateTime { get; } DateTime ModifiedTime { get; } + object GetObject(); } } \ No newline at end of file diff --git a/Runtime/Library/Interfaces/Save.cs b/Runtime/Library/Interfaces/Save.cs new file mode 100644 index 0000000..69b9e79 --- /dev/null +++ b/Runtime/Library/Interfaces/Save.cs @@ -0,0 +1,16 @@ +namespace RealMethod +{ + public interface ISave : IIdentifier + { + void OnLoaded(); + void OnSaved(); + } + + public interface ISaveSystem + { + bool IsExist(IFile file); + void Save(IFile file); + void Load(IFile file); + void Delete(IFile file); + } +} \ No newline at end of file diff --git a/Runtime/Library/Interfaces/Save.cs.meta b/Runtime/Library/Interfaces/Save.cs.meta new file mode 100644 index 0000000..9f0eba5 --- /dev/null +++ b/Runtime/Library/Interfaces/Save.cs.meta @@ -0,0 +1,2 @@ +fileFormatVersion: 2 +guid: 9d6971ea25ef788479f2dd1c7f6897ee \ No newline at end of file diff --git a/Runtime/Pattern/Assets/SaveFile.cs b/Runtime/Pattern/Assets/SaveFile.cs new file mode 100644 index 0000000..1549500 --- /dev/null +++ b/Runtime/Pattern/Assets/SaveFile.cs @@ -0,0 +1,66 @@ +using UnityEngine; + +namespace RealMethod +{ + /// + /// this is FileAsset that implement ISave Interface with some Editor Function + /// for testing save and load + /// + public abstract class SaveFile : FileAsset, ISave + { + // Implement ISave Interface + void ISave.OnLoaded() + { + OnLoaded(); + } + void ISave.OnSaved() + { + OnSaved(); + } + + protected abstract void OnLoaded(); + protected abstract void OnSaved(); + +#if UNITY_EDITOR + [ContextMenu("Save")] + private void Editor_SaveSelf() + { + var manager = FindFirstObjectByType(); + if (manager != null) + { + manager.Save(this); + } + else + { + Debug.LogError("No SaveManager found in the scene."); + } + } + [ContextMenu("Load")] + private void Editor_LoadSelf() + { + var manager = FindFirstObjectByType(); + if (manager != null) + { + manager.Load(this); + } + else + { + Debug.LogError("No SaveManager found in the scene."); + } + } + [ContextMenu("Delete")] + private void Editor_Delete() + { + var manager = FindFirstObjectByType(); + if (manager != null) + { + manager.Delete(this); + } + else + { + Debug.LogError("No SaveManager found in the scene."); + } + } +#endif + } +} \ No newline at end of file diff --git a/Runtime/Pattern/Assets/SaveFile.cs.meta b/Runtime/Pattern/Assets/SaveFile.cs.meta new file mode 100644 index 0000000..d684db0 --- /dev/null +++ b/Runtime/Pattern/Assets/SaveFile.cs.meta @@ -0,0 +1,2 @@ +fileFormatVersion: 2 +guid: f680f5cc45f833d4ab1e78d5984c13d6 \ No newline at end of file diff --git a/Runtime/Pattern/Managers/DataManager.cs b/Runtime/Pattern/Managers/DataManager.cs deleted file mode 100644 index 107d763..0000000 --- a/Runtime/Pattern/Managers/DataManager.cs +++ /dev/null @@ -1,405 +0,0 @@ -using UnityEngine; - -namespace RealMethod -{ - public interface IDataFile - { - void InitiateFile(DataManager manager); - void FileLoaded(); - void FileSaved(); - void FileRemoved(); - } - public interface IStorage - { - void StorageCreated(Object author); - void StorageLoaded(Object author); - void StorageClear(); - } - [System.Serializable] - public struct StorageFile where T : IStorage where J : SaveFile - { - [SerializeField] - private bool UseCustomFile; - [SerializeField, ConditionalHide("UseCustomFile", true, false)] - private SaveFile _SaveFile; - public SaveFile file - { - get - { - if (_SaveFile == null) - { - if (!TryGetStorage(out cacheProvider)) - { - Debug.LogWarning($"{this}: Can't get Storage Interface Something is wrong in your 'CustomSavefile' or 'SaveFileClass'"); - return default; - } - } - return _SaveFile; - } - } - private T cacheProvider; - public T provider - { - get - { - if (cacheProvider == null) - { - if (!TryGetStorage(out cacheProvider)) - { - Debug.LogWarning($"{this}: Can't get Storage Interface Something is wrong in your 'CustomSavefile' or 'SaveFileClass'"); - return default; - } - } - return cacheProvider; - } - } - - - // Public Functions - public bool Load(Object author) - { - return Load(author, Game.GetManager()); - } - public bool Load(Object author, DataManager saveManager) - { - if (saveManager == null) - { - Debug.LogWarning($"{this}: Initiate faield we need DataManager"); - return false; - } - - if (saveManager.IsExistFile(file)) - { - saveManager.LoadFile(file); - provider.StorageLoaded(author); - return true; - } - else - { - provider.StorageCreated(author); - return false; - } - } - public void Clear() - { - provider.StorageClear(); - } - - // Private Functions - private bool TryGetStorage(out T _provider) - { - if (UseCustomFile) - { - if (_SaveFile is T customProvider) - { - _provider = customProvider; - return true; - } - else - { - Debug.LogWarning("Storage Interface not implemented in Customfile."); - UseCustomFile = false; - } - } - _SaveFile = ScriptableObject.CreateInstance(); - if (_SaveFile is T autoProvider) - { - _SaveFile.name = $"RM{typeof(J)}"; - _provider = autoProvider; - return true; - } - else - { - Debug.LogError($"Storage Interface not implemented in SaveFileType {typeof(J)}"); - _provider = default; - return false; - } - } - } - - - // DataMaanger Class - public abstract class DataManager : MonoBehaviour, IGameManager - { - - [Header("Basic")] - [SerializeField] - private bool LoadOnInitiate = true; - [SerializeField] - private SaveFile[] StableFiles; - - // Actions - public System.Action OnFileLoaded; - public System.Action OnFileSaved; - - public byte Logindex { get; private set; } - public string[] DataLog { get; private set; } - - // Operators - public SaveFile this[int Index] - { - get => StableFiles[Index]; - protected set => StableFiles[Index] = value; - } - - - - // Implement IGameManager Interface - MonoBehaviour IGameManager.GetManagerClass() - { - return this; - } - void IGameManager.InitiateManager(bool AlwaysLoaded) - { - Logindex = 0; - DataLog = new string[5]; - - foreach (var file in StableFiles) - { - file.provider.InitiateFile(this); - if (LoadOnInitiate) - { - if (IsExistFile(file)) - LoadFile(file); - } - } - } - void IGameManager.ResolveService(Service service, bool active) - { - InitiateService(service); - } - - - // Public Functions - public void Save() - { - if (StableFiles == null) - { - Debug.LogError("StableFiles is not valid"); - return; - } - foreach (var file in StableFiles) - { - if (file == null) - { - Debug.LogError("File is not valid"); - continue; - } - OnSaveFile(file); - file.provider.FileSaved(); - OnFileSaved?.Invoke(file); - } - } - public void SaveFile(int Index) - { - if (StableFiles.IsValidIndex(Index)) - { - SaveFile(StableFiles[Index]); - } - else - { - Debug.LogError("Invalid index passed to SaveFile: " + Index); - } - } - public void SaveFile(SaveFile file) - { - if (file == null) - { - Debug.LogError("File is not valid"); - return; - } - OnSaveFile(file); - file.provider.FileSaved(); - OnFileSaved?.Invoke(file); - } - public void Load() - { - if (StableFiles == null) - { - Debug.LogError("StableFiles is not valid"); - return; - } - foreach (var file in StableFiles) - { - if (file == null) - { - Debug.LogError("File Does not valid"); - continue; - } - OnLoadFile(file); - file.provider.FileLoaded(); - OnFileLoaded?.Invoke(file); - } - } - public void LoadFile(int Index) - { - if (StableFiles.IsValidIndex(Index)) - { - LoadFile(StableFiles[Index]); - } - else - { - Debug.LogError("Invalid index passed to LoadFile: " + Index); - } - } - public void LoadFile(SaveFile file) - { - if (file == null) - { - Debug.LogError("File Does not valid"); - return; - } - - OnLoadFile(file); - file.provider.FileLoaded(); - OnFileLoaded?.Invoke(file); - } - public void DeleteFile(int Index) - { - if (StableFiles.IsValidIndex(Index)) - { - DeleteFile(StableFiles[Index]); - } - else - { - Debug.LogError("Invalid index passed to DeleteFile: " + Index); - } - } - public void DeleteFile(SaveFile file) - { - if (file == null) - { - Debug.LogError("File Does not valid"); - return; - } - - OnDeleteFile(file); - file.provider.FileRemoved(); - } - public bool IsExistFile(int Index) - { - if (StableFiles.IsValidIndex(Index)) - { - return IsExistFile(StableFiles[Index]); - } - else - { - Debug.LogError("Invalid index passed to IsExistFile: " + Index); - return false; - } - } - public bool IsExistFile(SaveFile file) - { - if (file == null) - { - Debug.LogError("File Does not valid"); - return false; - } - return IsExist(file); - } - - - // Protected Function - protected void WriteLog(string message, SaveFile file) - { - if (Application.isPlaying && DataLog != null) - { - if (Logindex == 0) - { - DataLog[0] = $"{System.DateTime.Now} -- {file.name} -- {message}"; - Logindex++; - } - else - { - DataLog[Logindex % DataLog.Length] = $"{System.DateTime.Now} -- {file.name} -- {message}"; - Logindex++; - } - } - } - - - // Abstract Mehtod - protected abstract void InitiateService(Service service); - protected abstract bool IsExist(SaveFile targetfile); - protected abstract void OnDeleteFile(SaveFile targetfile); - protected abstract void OnSaveFile(SaveFile targetfile); - protected abstract void OnLoadFile(SaveFile targetfile); - } - - // Save File Class - public abstract class SaveFile : DataAsset, IDataFile - { - public IDataFile provider => this; - - // Implement IDataPersistence Interface - void IDataFile.InitiateFile(DataManager manager) - { - OnStable(manager); - } - void IDataFile.FileSaved() - { - OnSaved(); - } - void IDataFile.FileLoaded() - { - OnLoaded(); - } - void IDataFile.FileRemoved() - { - OnDeleted(); - } - - - protected abstract void OnStable(DataManager manager); - protected abstract void OnLoaded(); - protected abstract void OnSaved(); - protected abstract void OnDeleted(); - - -#if UNITY_EDITOR - [ContextMenu("Save")] - private void Editor_SaveSelf() - { - var manager = FindFirstObjectByType(); - if (manager != null) - { - manager.SaveFile(this); - } - else - { - Debug.LogError("No DataManager found in the scene."); - } - } - [ContextMenu("Load")] - private void Editor_LoadSelf() - { - var manager = FindFirstObjectByType(); - if (manager != null) - { - manager.LoadFile(this); - } - else - { - Debug.LogError("No DataManager found in the scene."); - } - } - [ContextMenu("Delete")] - private void Editor_Delete() - { - var manager = FindFirstObjectByType(); - if (manager != null) - { - manager.DeleteFile(this); - } - else - { - Debug.LogError("No DataManager found in the scene."); - } - } -#endif - - - - } - -} \ No newline at end of file diff --git a/Runtime/Pattern/Managers/SaveManager.cs b/Runtime/Pattern/Managers/SaveManager.cs new file mode 100644 index 0000000..a42031e --- /dev/null +++ b/Runtime/Pattern/Managers/SaveManager.cs @@ -0,0 +1,616 @@ +using System.Runtime.Serialization.Formatters.Binary; +using System.Collections.Generic; +using System.Xml.Serialization; +using System.Reflection; +using System.IO; +using UnityEngine; + +namespace RealMethod +{ + [System.Serializable] + public enum SaveFormat + { + PlayerPrefs = 0, + TEXT = 1, + XML = 2, + JSON = 3, + Binary = 4, + } + public interface ISaveMethod + { + SaveFormat Format { get; } + string Path { get; } + BindingFlags FieldFlags { get; } + BindingFlags PropertieFlags { get; } + } + + + public abstract class SaveManager : MonoBehaviour, IGameManager , ISaveSystem + { + // Actions + public event System.Action OnLoaded; + public event System.Action OnSaved; + public event System.Action OnDeleted; + +#if UNITY_EDITOR + public byte Logindex { get; private set; } + public string[] DataLog { get; private set; } +#endif + + + // Implement IGameManager Interface + MonoBehaviour IGameManager.GetManagerClass() + { + return this; + } + public virtual void InitiateManager(bool AlwaysLoaded) + { +#if UNITY_EDITOR + Logindex = 0; + DataLog = new string[5]; +#endif + } + public virtual void ResolveService(Service service, bool active) + { + } + + + // Functions + public bool IsExist(IFile file) + { + if (!Validate(file)) + return false; + + return IsExistFile(file, GetMethod(file)); + } + public void Save(IFile file) + { + if (!Validate(file)) + return; + + if (file.GetObject() is ISave provider) + { + OnSave(file, GetMethod(file)); + provider.OnSaved(); + OnSaved?.Invoke(file); + +#if UNITY_EDITOR + WriteLog($"Save ({GetMethod(file)})", file); +#endif + } + else + { + Debug.LogWarning($"For saving file you should implement ISave interface in {file.GetObject()}"); + return; + } + } + public void Load(IFile file) + { + if (!Validate(file)) + return; + + if (file.GetObject() is ISave provider) + { + OnLoad(file, GetMethod(file)); + provider.OnLoaded(); + OnLoaded?.Invoke(file); +#if UNITY_EDITOR + WriteLog($"Save ({GetMethod(file)})", file); +#endif + } + else + { + Debug.LogWarning($"For loading file you should implement ISave interface in {file.GetObject()}"); + return; + } + } + public void Delete(IFile file) + { + if (!Validate(file)) + return; + + OnDelete(file, GetMethod(file)); + OnDeleted?.Invoke(file); +#if UNITY_EDITOR + WriteLog($"Save ({GetMethod(file)})", file); +#endif + } + + // Methods + protected virtual bool Validate(IFile file) + { + if (file == null && file.GetObject() != null) + { + Debug.LogError("File Does not valid"); + return false; + } + return true; + } + protected virtual ISaveMethod GetMethod(IFile file) + { + if (file.GetObject().HasImplementInterface(out ISaveMethod method)) + { + return method; + } + else + { + if (this is ISaveMethod provider) + { + return provider; + } + else + { + throw new System.InvalidOperationException($"You Should Implement {typeof(ISaveMethod)}, in SameManager Class for save / load files"); + } + } + } + + + // Abstract Mehtod + protected abstract bool IsExistFile(IFile file, ISaveMethod Method); + protected abstract void OnSave(IFile file, ISaveMethod Method); + protected abstract void OnLoad(IFile file, ISaveMethod Method); + protected abstract void OnDelete(IFile file, ISaveMethod Method); +#if UNITY_EDITOR + private void WriteLog(string message, IFile file) + { + if (Application.isPlaying && DataLog != null) + { + if (Logindex == 0) + { + DataLog[0] = $"{System.DateTime.Now} -- {file.Name} -- {message}"; + Logindex++; + } + else + { + DataLog[Logindex % DataLog.Length] = $"{System.DateTime.Now} -- {file.Name} -- {message}"; + Logindex++; + } + } + } +#endif + } + public abstract class SaveMethodManager : SaveManager, ISaveMethod + { + [Header("SaveMethod")] + [SerializeField] + private SaveFormat fromat; + [SerializeField, ConditionalHideByEnum("fromat", 0)] + private bool CustomPath = false; + [SerializeField, ConditionalHide("CustomPath", true, false)] + private string FilePath = System.Environment.GetFolderPath(System.Environment.SpecialFolder.Desktop); + [SerializeField, ConditionalShowByEnum("fromat", SaveFormat.PlayerPrefs, SaveFormat.TEXT)] + private BindingFlags FieldFlags = BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic; + [SerializeField, ConditionalShowByEnum("fromat", SaveFormat.PlayerPrefs, SaveFormat.TEXT)] + private BindingFlags PropertieFlags = BindingFlags.Default; + + // Implement ISaveMethod Interface + SaveFormat ISaveMethod.Format => fromat; + string ISaveMethod.Path => FilePath; + BindingFlags ISaveMethod.FieldFlags => FieldFlags; + BindingFlags ISaveMethod.PropertieFlags => PropertieFlags; + + + // SaveManager Methods + protected override bool IsExistFile(IFile file, ISaveMethod Method) + { + switch (Method.Format) + { + case SaveFormat.Binary: + return File.Exists(GetPath(file, Method)); + case SaveFormat.XML: + return File.Exists(GetPath(file, Method)); + case SaveFormat.JSON: + return File.Exists(GetPath(file, Method)); + case SaveFormat.TEXT: + return File.Exists(GetPath(file, Method)); + case SaveFormat.PlayerPrefs: + return PlayerPrefs.HasKey(file.Name); + default: + Debug.LogWarning($"The {Method.Format} is not implement"); + return false; + } + } + protected override void OnSave(IFile file, ISaveMethod Method) + { + object fileObject = file.GetObject(); + + switch (Method.Format) + { + case SaveFormat.Binary: + BinaryFormatter bf = new BinaryFormatter(); +#pragma warning disable SYSLIB0011 // Suppress BinaryFormatter warning (only use in trusted context) + using (var stream = new FileStream(GetPath(file, Method), FileMode.Create)) + { + try + { + bf.Serialize(stream, fileObject); + } + catch (System.Exception e) + { + Debug.LogError($"Failed to serialize {file.Name} to {GetPath(file, Method)}: {e}"); + return; + } + } +#pragma warning restore SYSLIB0011 + break; + case SaveFormat.XML: + var xml = new XmlSerializer(fileObject.GetType()); + using (var stream = new FileStream(GetPath(file, Method), FileMode.Create)) + { + xml.Serialize(stream, fileObject); + } + break; + case SaveFormat.JSON: + string jsoncontent = JsonUtility.ToJson(fileObject, true); + File.WriteAllText(GetPath(file, Method), jsoncontent); + break; + case SaveFormat.TEXT: + List lines = new List(); + FieldInfo[] T_fields = fileObject.GetFields(Method.FieldFlags); + PropertyInfo[] T_properties = fileObject.GetProperties(Method.PropertieFlags); + foreach (FieldInfo field in T_fields) + { + lines.Add($"{field.Name}={field.GetValue(file)}"); + } + foreach (PropertyInfo property in T_properties) + { + lines.Add($"{property.Name}={property.GetValue(file)}"); + } + File.WriteAllLines(GetPath(file, Method), lines); + break; + case SaveFormat.PlayerPrefs: + FieldInfo[] PP_fields = fileObject.GetFields(Method.FieldFlags); + PropertyInfo[] PP_properties = fileObject.GetProperties(Method.PropertieFlags); + foreach (FieldInfo field in PP_fields) + { + PlayerPrefsSetValueByField(field, fileObject); + } + foreach (PropertyInfo property in PP_properties) + { + PlayerPrefsSetValueByProperty(property, fileObject); + } + PlayerPrefs.SetString(file.Name, System.DateTime.Now.ToString()); + PlayerPrefs.Save(); + break; + default: + Debug.LogWarning($"The {Method} is not implement"); + break; + } + } + protected override void OnLoad(IFile file, ISaveMethod Method) + { + object fileObject = file.GetObject(); + + switch (Method.Format) + { + case SaveFormat.Binary: + var bf = new BinaryFormatter(); +#pragma warning disable SYSLIB0011 + using (var stream = new FileStream(GetPath(file, Method), FileMode.Open)) + { + fileObject = bf.Deserialize(stream); + + } +#pragma warning restore SYSLIB0011 + break; + case SaveFormat.XML: + var xml = new XmlSerializer(file.GetType()); + using (var stream = new FileStream(GetPath(file, Method), FileMode.Open)) + { + fileObject = xml.Deserialize(stream); + } + break; + case SaveFormat.JSON: + string jsoncontent; + try + { + jsoncontent = File.ReadAllText(GetPath(file, Method)); + JsonUtility.FromJsonOverwrite(jsoncontent, fileObject); + } + catch (System.Exception e) + { + Debug.LogError($"Failed to read from {GetPath(file, Method)} with exception {e}"); + return; + } + break; + case SaveFormat.TEXT: + FieldInfo[] T_fields = fileObject.GetFields(Method.FieldFlags); + PropertyInfo[] T_properties = fileObject.GetProperties(Method.PropertieFlags); + foreach (string line in File.ReadLines(GetPath(file, Method))) + { + string[] parts = line.Split("="); + if (parts.Length < 2) continue; + string lineName = parts[0]; + string lineValue = parts[1]; + foreach (FieldInfo info in T_fields) + { + if (info.Name == lineName) + { + object value = null; + System.Type type = info.FieldType; + try + { + if (type == typeof(int)) + value = int.Parse(lineValue); + else if (type == typeof(float)) + value = float.Parse(lineValue); + else if (type == typeof(bool)) + value = bool.Parse(lineValue); + else if (type == typeof(string)) + value = lineValue; + else if (type.IsEnum) + value = System.Enum.Parse(type, lineValue); + else if (type == typeof(byte)) + value = byte.Parse(lineValue); + else + Debug.LogWarning($"Unsupported type: {type.Name}"); + info.SetValue(file, value); + } + catch (System.Exception ex) + { + Debug.LogWarning($"Failed to set value for {info.Name}: {ex.Message}"); + } + } + } + foreach (PropertyInfo property in T_properties) + { + if (property.Name == lineName) + { + object value = null; + System.Type type = property.PropertyType; + try + { + if (type == typeof(int)) + value = int.Parse(lineValue); + else if (type == typeof(float)) + value = float.Parse(lineValue); + else if (type == typeof(bool)) + value = bool.Parse(lineValue); + else if (type == typeof(string)) + value = lineValue; + else if (type.IsEnum) + value = System.Enum.Parse(type, lineValue); + else if (type == typeof(byte)) + value = byte.Parse(lineValue); + else + Debug.LogWarning($"Unsupported type: {type.Name}"); + property.SetValue(file, value); + } + catch (System.Exception ex) + { + Debug.LogWarning($"Failed to set value for {property.Name}: {ex.Message}"); + } + } + } + } + break; + case SaveFormat.PlayerPrefs: + FieldInfo[] PP_fields = fileObject.GetFields(Method.FieldFlags); + PropertyInfo[] PP_properties = fileObject.GetProperties(Method.PropertieFlags); + foreach (FieldInfo field in PP_fields) + { + PlayerPrefsGetValueByField(field, fileObject); + } + foreach (PropertyInfo property in PP_properties) + { + PlayerPrefsGetValueByProperty(property, fileObject); + } + break; + default: + Debug.LogWarning($"The {Method} is not implement"); + break; + } + } + protected override void OnDelete(IFile file, ISaveMethod Method) + { + object fileObject = file.GetObject(); + + switch (Method.Format) + { + case SaveFormat.Binary: + File.Delete(GetPath(file, Method)); + break; + case SaveFormat.XML: + File.Delete(GetPath(file, Method)); + break; + case SaveFormat.JSON: + File.Delete(GetPath(file, Method)); + break; + case SaveFormat.TEXT: + File.Delete(GetPath(file, Method)); + break; + case SaveFormat.PlayerPrefs: + FieldInfo[] PP_fields = fileObject.GetFields(Method.FieldFlags); + PropertyInfo[] PP_properties = fileObject.GetProperties(Method.PropertieFlags); + foreach (FieldInfo field in PP_fields) + { + PlayerPrefs.DeleteKey(field.Name); + } + foreach (PropertyInfo property in PP_properties) + { + PlayerPrefs.DeleteKey(property.Name); + } + break; + default: + Debug.LogWarning($"The {Method} is not implement"); + break; + } + } + + // Methods + protected virtual string GetPath(IFile file, ISaveMethod method) + { + string filename = file.Name; + string filetype = method.Format == SaveFormat.TEXT ? ".txt" : + method.Format == SaveFormat.Binary ? ".RSave" : + method.Format == SaveFormat.XML ? ".xml" : + method.Format == SaveFormat.JSON ? ".json" : ""; + + if (CustomPath) + { + return method.Path + "/" + filename + filetype; + } + else + { + return Application.persistentDataPath + "/" + filename + filetype; + } + } + + // Private Method + private void PlayerPrefsSetValueByField(FieldInfo field, object source) + { + string key = field.Name; + object value = field.GetValue(source); + + if (value is int intValue) + { + PlayerPrefs.SetInt(key, intValue); + } + else if (value is float floatValue) + { + PlayerPrefs.SetFloat(key, floatValue); + } + else if (value is string stringValue) + { + PlayerPrefs.SetString(key, stringValue); + } + else if (value is bool boolValue) + { + PlayerPrefs.SetInt(key, boolValue ? 1 : 0); + } + else if (value is System.Enum enumvalue) + { + PlayerPrefs.SetInt(key, System.Convert.ToInt32(enumvalue)); + } + else if (value is byte bytevalue) + { + PlayerPrefs.SetInt(key, bytevalue); + } + else + { + Debug.LogWarning($"Unsupported type for PlayerPrefs: {value?.GetType().Name} (Key: {key})"); + } + } + private void PlayerPrefsSetValueByProperty(PropertyInfo property, object source) + { + string key = property.Name; + object value = property.GetValue(source); + + if (value is int intValue) + { + PlayerPrefs.SetInt(key, intValue); + } + else if (value is float floatValue) + { + PlayerPrefs.SetFloat(key, floatValue); + } + else if (value is string stringValue) + { + PlayerPrefs.SetString(key, stringValue); + } + else if (value is bool boolValue) + { + PlayerPrefs.SetInt(key, boolValue ? 1 : 0); + } + else if (value is System.Enum enumvalue) + { + PlayerPrefs.SetInt(key, System.Convert.ToInt32(enumvalue)); + } + else if (value is byte bytevalue) + { + PlayerPrefs.SetInt(key, bytevalue); + } + else + { + Debug.LogWarning($"Unsupported type for PlayerPrefs: {value?.GetType().Name} (Key: {key})"); + } + } + private void PlayerPrefsGetValueByField(FieldInfo field, object source) + { + string key = field.Name; + + if (!PlayerPrefs.HasKey(key)) return; + + if (field.FieldType == typeof(int)) + { + field.SetValue(source, PlayerPrefs.GetInt(key)); + } + else if (field.FieldType == typeof(float)) + { + field.SetValue(source, PlayerPrefs.GetFloat(key)); + } + else if (field.FieldType == typeof(string)) + { + field.SetValue(source, PlayerPrefs.GetString(key)); + } + else if (field.FieldType == typeof(bool)) + { + field.SetValue(source, PlayerPrefs.GetInt(key) == 1); + } + else if (field.FieldType == typeof(System.Enum)) + { + field.SetValue(source, PlayerPrefs.GetInt(key) == 1); + } + else if (field.FieldType == typeof(byte)) + { + field.SetValue(source, PlayerPrefs.GetInt(key) == 1); + } + } + private void PlayerPrefsGetValueByProperty(PropertyInfo property, object source) + { + string key = property.Name; + + if (!PlayerPrefs.HasKey(key)) return; + + if (property.PropertyType == typeof(int)) + { + property.SetValue(source, PlayerPrefs.GetInt(key)); + } + else if (property.PropertyType == typeof(float)) + { + property.SetValue(source, PlayerPrefs.GetFloat(key)); + } + else if (property.PropertyType == typeof(string)) + { + property.SetValue(source, PlayerPrefs.GetString(key)); + } + else if (property.PropertyType == typeof(bool)) + { + property.SetValue(source, PlayerPrefs.GetInt(key) == 1); + } + else if (property.PropertyType == typeof(System.Enum)) + { + property.SetValue(source, PlayerPrefs.GetInt(key) == 1); + } + else if (property.PropertyType == typeof(byte)) + { + property.SetValue(source, PlayerPrefs.GetInt(key) == 1); + } + } + + } + public abstract class SaveLoadManager : SaveMethodManager + { + [Header("SaveSetting")] + [SerializeField] + private bool LoadOnInitiate = true; + [SerializeField, ConditionalHide("LoadOnInitiate", true, false)] + private SaveFile[] DefaultFile = new SaveFile[0]; + + // IGameManager + public override void InitiateManager(bool AlwaysLoaded) + { + base.InitiateManager(AlwaysLoaded); + + if (LoadOnInitiate) + { + foreach (var file in DefaultFile) + { + Load(file); + } + } + } + } + +} \ No newline at end of file diff --git a/Runtime/Pattern/Managers/SaveManager.cs.meta b/Runtime/Pattern/Managers/SaveManager.cs.meta new file mode 100644 index 0000000..5281466 --- /dev/null +++ b/Runtime/Pattern/Managers/SaveManager.cs.meta @@ -0,0 +1,2 @@ +fileFormatVersion: 2 +guid: 9923681aac3097a46b06fbdfa85c89ac \ No newline at end of file diff --git a/Runtime/Pattern/Managers/StorageFile.cs b/Runtime/Pattern/Managers/StorageFile.cs new file mode 100644 index 0000000..7719843 --- /dev/null +++ b/Runtime/Pattern/Managers/StorageFile.cs @@ -0,0 +1,118 @@ +using UnityEngine; + +namespace RealMethod +{ + + public interface IStorage + { + void StorageCreated(Object author); + void StorageLoaded(Object author); + void StorageClear(); + } + [System.Serializable] + public struct StorageFile where T : IStorage where J : FileAsset + { + [SerializeField] + private bool UseCustomFile; + [SerializeField, ConditionalHide("UseCustomFile", true, false)] + private J _SaveFile; + public J file + { + get + { + if (_SaveFile == null) + { + if (!TryGetStorage(out cacheProvider)) + { + Debug.LogWarning($"{this}: Can't get Storage Interface Something is wrong in your 'CustomSavefile' or 'SaveFileClass'"); + return default; + } + } + return _SaveFile; + } + } + private T cacheProvider; + public T provider + { + get + { + if (cacheProvider == null) + { + if (!TryGetStorage(out cacheProvider)) + { + Debug.LogWarning($"{this}: Can't get Storage Interface Something is wrong in your 'CustomSavefile' or 'SaveFileClass'"); + return default; + } + } + return cacheProvider; + } + } + + + // Public Functions + public bool Load(Object author) + { + ISaveSystem Savesystem = Game.Instance.gameObject.GetComponent(); + if (Savesystem == null) + Savesystem = Game.World.gameObject.GetComponent(); + + return Load(author, Savesystem); + } + public bool Load(Object author, ISaveSystem manager) + { + if (manager == null) + { + Debug.LogWarning($"{this}: Initiate faield we need SaveManager"); + return false; + } + + if (manager.IsExist(file)) + { + manager.Load(file); + provider.StorageLoaded(author); + return true; + } + else + { + provider.StorageCreated(author); + return false; + } + } + public void Clear() + { + provider.StorageClear(); + } + + // Private Functions + private bool TryGetStorage(out T _provider) + { + if (UseCustomFile) + { + if (_SaveFile is T customProvider) + { + _provider = customProvider; + return true; + } + else + { + Debug.LogWarning("Storage Interface not implemented in Customfile."); + UseCustomFile = false; + } + } + _SaveFile = ScriptableObject.CreateInstance(); + if (_SaveFile is T autoProvider) + { + _SaveFile.name = $"RM{typeof(J)}"; + _provider = autoProvider; + return true; + } + else + { + Debug.LogError($"Storage Interface not implemented in SaveFileType {typeof(J)}"); + _provider = default; + return false; + } + } + } + +} \ No newline at end of file diff --git a/Runtime/Pattern/Managers/DataManager.cs.meta b/Runtime/Pattern/Managers/StorageFile.cs.meta similarity index 100% rename from Runtime/Pattern/Managers/DataManager.cs.meta rename to Runtime/Pattern/Managers/StorageFile.cs.meta diff --git a/Runtime/ReadySet/Components/Method/SharedObject.cs b/Runtime/ReadySet/Components/Method/SharedObject.cs deleted file mode 100644 index c3a0fae..0000000 --- a/Runtime/ReadySet/Components/Method/SharedObject.cs +++ /dev/null @@ -1,20 +0,0 @@ -using UnityEngine; - -namespace RealMethod -{ - [AddComponentMenu("RealMethod/Method/SharedObject")] - public sealed class SharedObject : MonoBehaviour - { - [SerializeField] - private bool CheckSaftyShare = false; - private void OnEnable() - { - gameObject.Share(CheckSaftyShare); - } - - private void OnDisable() - { - gameObject.Unshare(CheckSaftyShare); - } - } -} \ No newline at end of file diff --git a/Runtime/ReadySet/Components/Method/SharedObject.cs.meta b/Runtime/ReadySet/Components/Method/SharedObject.cs.meta deleted file mode 100644 index 3c8faf4..0000000 --- a/Runtime/ReadySet/Components/Method/SharedObject.cs.meta +++ /dev/null @@ -1,2 +0,0 @@ -fileFormatVersion: 2 -guid: 4c9371d81fcc7de44945374996c4ce62 \ No newline at end of file diff --git a/Runtime/ReadySet/Managers/SaveManager.cs b/Runtime/ReadySet/Managers/SaveManager.cs deleted file mode 100644 index a155fa9..0000000 --- a/Runtime/ReadySet/Managers/SaveManager.cs +++ /dev/null @@ -1,365 +0,0 @@ -using System; -using System.Collections.Generic; -using System.IO; -using System.Reflection; -using System.Runtime.Serialization.Formatters.Binary; -using System.Xml.Serialization; -using UnityEngine; - -namespace RealMethod -{ - [Serializable] - public enum SaveMethod - { - PlayerPrefs, - TEXT, - XML, - JSON, - Binary, - } - - [AddComponentMenu("RealMethod/Manager/SaveManager")] - public sealed class SaveManager : DataManager - { - [Header("Behavior")] - [SerializeField] private SaveMethod Format; - public SaveMethod format => Format; - [SerializeField, ConditionalHideByEnum("Format", 0)] - private bool CustomPath = false; - [SerializeField, ConditionalHide("CustomPath", true, false)] - private string FilePath = Environment.GetFolderPath(Environment.SpecialFolder.Desktop); - [SerializeField, ConditionalShowByEnum("Format", 0, 1)] - private bool PublicField = true; - [SerializeField, ConditionalShowByEnum("Format", 0, 1)] - private bool ProtectedField = false; - [SerializeField, ConditionalShowByEnum("Format", 0, 1)] - private bool PrivateField = false; - [SerializeField, ConditionalShowByEnum("Format", 0, 1)] - private bool SerializeField = false; - - - // DataManager Methods - protected override void InitiateService(Service service) - { - - } - protected override bool IsExist(SaveFile file) - { - switch (Format) - { - case SaveMethod.Binary: - return File.Exists(GetPath(file)); - case SaveMethod.XML: - return File.Exists(GetPath(file)); - case SaveMethod.JSON: - return File.Exists(GetPath(file)); - case SaveMethod.TEXT: - return File.Exists(GetPath(file)); - case SaveMethod.PlayerPrefs: - return PlayerPrefs.HasKey(file.name); - default: - Debug.LogWarning($"The {Format} is not implement"); - return false; - } - } - protected override void OnSaveFile(SaveFile file) - { - switch (Format) - { - case SaveMethod.Binary: - BinaryFormatter bf = new BinaryFormatter(); -#pragma warning disable SYSLIB0011 // Suppress BinaryFormatter warning (only use in trusted context) - using (var stream = new FileStream(GetPath(file), FileMode.Create)) - { - try - { - bf.Serialize(stream, file); - } - catch (Exception e) - { - Debug.LogError($"Failed to serialize {file.name} to {GetPath(file)}: {e}"); - return; - } - } -#pragma warning restore SYSLIB0011 - break; - case SaveMethod.XML: - var xml = new XmlSerializer(file.GetType()); - using (var stream = new FileStream(GetPath(file), FileMode.Create)) - { - xml.Serialize(stream, file); - } - break; - case SaveMethod.JSON: - string jsoncontent = JsonUtility.ToJson(file, true); - File.WriteAllText(GetPath(file), jsoncontent); - break; - case SaveMethod.TEXT: - List lines = new List(); - foreach (FieldInfo field in ScanFieldsFile(file)) - { - lines.Add($"{field.Name}={field.GetValue(file)}"); - } - File.WriteAllLines(GetPath(file), lines); - break; - case SaveMethod.PlayerPrefs: - foreach (FieldInfo field in ScanFieldsFile(file)) - { - PlayerPrefsSetValueByField(field, file); - } - PlayerPrefs.SetString(file.name, DateTime.Now.ToString()); - PlayerPrefs.Save(); - break; - default: - Debug.LogWarning($"The {Format} is not implement"); - break; - } - WriteLog($"Save ({Format})", file); - } - protected override void OnLoadFile(SaveFile file) - { - switch (Format) - { - case SaveMethod.Binary: - var bf = new BinaryFormatter(); -#pragma warning disable SYSLIB0011 - using (var stream = new FileStream(GetPath(file), FileMode.Open)) - { - file = (SaveFile)bf.Deserialize(stream); - } -#pragma warning restore SYSLIB0011 - break; - case SaveMethod.XML: - var xml = new XmlSerializer(file.GetType()); - using (var stream = new FileStream(GetPath(file), FileMode.Open)) - { - file = (SaveFile)xml.Deserialize(stream); - } - break; - case SaveMethod.JSON: - string jsoncontent; - try - { - jsoncontent = File.ReadAllText(GetPath(file)); - JsonUtility.FromJsonOverwrite(jsoncontent, file); - } - catch (Exception e) - { - Debug.LogError($"Failed to read from {GetPath(file)} with exception {e}"); - return; - } - break; - case SaveMethod.TEXT: - FieldInfo[] fields = ScanFieldsFile(file); - foreach (string line in File.ReadLines(GetPath(file))) - { - string[] parts = line.Split("="); - if (parts.Length < 2) continue; - string lineName = parts[0]; - string lineValue = parts[1]; - foreach (FieldInfo info in fields) - { - if (info.Name == lineName) - { - object value = null; - Type type = info.FieldType; - try - { - if (type == typeof(int)) - value = int.Parse(lineValue); - else if (type == typeof(float)) - value = float.Parse(lineValue); - else if (type == typeof(bool)) - value = bool.Parse(lineValue); - else if (type == typeof(string)) - value = lineValue; - else if (type.IsEnum) - value = Enum.Parse(type, lineValue); - else if (type == typeof(byte)) - value = byte.Parse(lineValue); - else - Debug.LogWarning($"Unsupported type: {type.Name}"); - info.SetValue(file, value); - } - catch (Exception ex) - { - Debug.LogWarning($"Failed to set value for {info.Name}: {ex.Message}"); - } - } - } - } - break; - case SaveMethod.PlayerPrefs: - foreach (FieldInfo field in ScanFieldsFile(file)) - { - PlayerPrefsGetValueByField(field, file); - } - break; - default: - Debug.LogWarning($"The {Format} is not implement"); - break; - } - WriteLog($"Load ({Format})", file); - } - protected override void OnDeleteFile(SaveFile file) - { - switch (Format) - { - case SaveMethod.Binary: - File.Delete(GetPath(file)); - break; - case SaveMethod.XML: - File.Delete(GetPath(file)); - break; - case SaveMethod.JSON: - File.Delete(GetPath(file)); - break; - case SaveMethod.TEXT: - File.Delete(GetPath(file)); - break; - case SaveMethod.PlayerPrefs: - foreach (FieldInfo field in ScanFieldsFile(file)) - { - PlayerPrefs.DeleteKey(field.Name); - } - PlayerPrefs.DeleteKey(file.name); - break; - default: - Debug.LogWarning($"The {Format} is not implement"); - break; - } - WriteLog($"Delete ({Format})", file); - } - - // Private Functions - private string GetPath(SaveFile file) - { - string filename = file.name; - string filetype = Format == SaveMethod.TEXT ? ".txt" : - Format == SaveMethod.Binary ? ".RSave" : - Format == SaveMethod.XML ? ".xml" : - Format == SaveMethod.JSON ? ".json" : ""; - - if (CustomPath) - { - return FilePath + "/" + filename + filetype; - } - else - { - return Application.persistentDataPath + "/" + filename + filetype; - } - } - private FieldInfo[] ScanFieldsFile(SaveFile file) - { - List Result = new List(); - Type type = file.GetType(); - BindingFlags flags = BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.Static; - - FieldInfo[] fields = type.GetFields(flags); - - foreach (FieldInfo field in fields) - { - if (field.IsPublic) - { - if (PublicField) - { - Result.Add(field); - continue; - } - } - if (field.IsFamily) - { - if (ProtectedField) - { - Result.Add(field); - continue; - } - } - if (field.IsPrivate) - { - if (PrivateField) - { - Result.Add(field); - continue; - } - } - if (SerializeField) - { - if (field.GetCustomAttribute() != null) - { - Result.Add(field); - continue; - } - } - } - - return Result.ToArray(); - } - private void PlayerPrefsSetValueByField(FieldInfo field, object source) - { - string key = field.Name; - object value = field.GetValue(source); - - if (value is int intValue) - { - PlayerPrefs.SetInt(key, intValue); - } - else if (value is float floatValue) - { - PlayerPrefs.SetFloat(key, floatValue); - } - else if (value is string stringValue) - { - PlayerPrefs.SetString(key, stringValue); - } - else if (value is bool boolValue) - { - PlayerPrefs.SetInt(key, boolValue ? 1 : 0); - } - else if (value is Enum enumvalue) - { - PlayerPrefs.SetInt(key, Convert.ToInt32(enumvalue)); - } - else if (value is byte bytevalue) - { - PlayerPrefs.SetInt(key, bytevalue); - } - else - { - Debug.LogWarning($"Unsupported type for PlayerPrefs: {value?.GetType().Name} (Key: {key})"); - } - } - private void PlayerPrefsGetValueByField(FieldInfo field, object source) - { - string key = field.Name; - - if (!PlayerPrefs.HasKey(key)) return; - - if (field.FieldType == typeof(int)) - { - field.SetValue(source, PlayerPrefs.GetInt(key)); - } - else if (field.FieldType == typeof(float)) - { - field.SetValue(source, PlayerPrefs.GetFloat(key)); - } - else if (field.FieldType == typeof(string)) - { - field.SetValue(source, PlayerPrefs.GetString(key)); - } - else if (field.FieldType == typeof(bool)) - { - field.SetValue(source, PlayerPrefs.GetInt(key) == 1); - } - else if (field.FieldType == typeof(Enum)) - { - field.SetValue(source, PlayerPrefs.GetInt(key) == 1); - } - else if (field.FieldType == typeof(byte)) - { - field.SetValue(source, PlayerPrefs.GetInt(key) == 1); - } - } - - } -} \ No newline at end of file diff --git a/Runtime/ReadySet/Managers/StorageManager.cs b/Runtime/ReadySet/Managers/StorageManager.cs new file mode 100644 index 0000000..0e5cacb --- /dev/null +++ b/Runtime/ReadySet/Managers/StorageManager.cs @@ -0,0 +1,10 @@ +using UnityEngine; + +namespace RealMethod +{ + [AddComponentMenu("RealMethod/Manager/SaveManager")] + public sealed class StorageManager : SaveLoadManager + { + + } +} \ No newline at end of file diff --git a/Runtime/ReadySet/Managers/SaveManager.cs.meta b/Runtime/ReadySet/Managers/StorageManager.cs.meta similarity index 100% rename from Runtime/ReadySet/Managers/SaveManager.cs.meta rename to Runtime/ReadySet/Managers/StorageManager.cs.meta diff --git a/Runtime/Toolkit/Inventory/InventorySaveFile.cs b/Runtime/Toolkit/Inventory/InventorySaveFile.cs index 3b3df79..333213e 100644 --- a/Runtime/Toolkit/Inventory/InventorySaveFile.cs +++ b/Runtime/Toolkit/Inventory/InventorySaveFile.cs @@ -22,10 +22,6 @@ public class InventorySaveFile : SaveFile, IInventoryStorage // SaveFile Methods - protected override void OnStable(DataManager manager) - { - - } protected override void OnSaved() { if (UsePlayerPrefs) @@ -44,15 +40,6 @@ protected override void OnLoaded() ItemsCapacity = RM_Save.GetArray("ItemsCapacity").ToList(); } } - protected override void OnDeleted() - { - if (UsePlayerPrefs) - { - ItemsName = null; - ItemsQuantity = null; - ItemsCapacity = null; - } - } // Implement IInventorySave Interface diff --git a/Runtime/Toolkit/RPG/StatSystem/StatSaveFile.cs b/Runtime/Toolkit/RPG/StatSystem/StatSaveFile.cs index 85d4f1e..c19aaa6 100644 --- a/Runtime/Toolkit/RPG/StatSystem/StatSaveFile.cs +++ b/Runtime/Toolkit/RPG/StatSystem/StatSaveFile.cs @@ -19,9 +19,6 @@ public class StatSaveFile : SaveFile, IStatStorage public List Maxs = new List(5); // SaveFile Methods - protected override void OnStable(DataManager manager) - { - } protected override void OnSaved() { if (UsePlayerPrefs) @@ -42,16 +39,6 @@ protected override void OnLoaded() Maxs = RM_Save.GetArray("StatMax").ToList(); } } - protected override void OnDeleted() - { - if (UsePlayerPrefs) - { - Names = null; - BaseValue = null; - Mins = null; - Maxs = null; - } - } // Implement IStorage Interface void IStorage.StorageCreated(Object author) diff --git a/Runtime/Toolkit/Tutorial/TutorialSaveFile.cs b/Runtime/Toolkit/Tutorial/TutorialSaveFile.cs index a7400a0..e3ef01f 100644 --- a/Runtime/Toolkit/Tutorial/TutorialSaveFile.cs +++ b/Runtime/Toolkit/Tutorial/TutorialSaveFile.cs @@ -20,9 +20,6 @@ public class TutorialSaveFile : SaveFile, ITutorialStorage public HashSet TutorialMessage = new HashSet(); // SaveFile Method - protected override void OnStable(DataManager manager) - { - } protected override void OnSaved() { if (UsePlayerPrefs) @@ -33,11 +30,6 @@ protected override void OnLoaded() if (UsePlayerPrefs) TutorialMessage = RM_Save.GetArray("Tutorial").ToHashSet(); } - protected override void OnDeleted() - { - if (UsePlayerPrefs) - TutorialMessage.Clear(); - } // IMplement ITutorialStorage Interface void IStorage.StorageCreated(Object author) diff --git a/Runtime/Toolkit/Upgrade/UpgradeSaveFile.cs b/Runtime/Toolkit/Upgrade/UpgradeSaveFile.cs index 50c6399..ccad0a5 100644 --- a/Runtime/Toolkit/Upgrade/UpgradeSaveFile.cs +++ b/Runtime/Toolkit/Upgrade/UpgradeSaveFile.cs @@ -18,9 +18,6 @@ public class UpgradeSaveFile : SaveFile, IUpgradeStorage public List AvailableItems; // Base SaveFile Method - protected override void OnStable(DataManager manager) - { - } protected override void OnSaved() { if (UsePlayerPrefs) @@ -37,15 +34,6 @@ protected override void OnLoaded() AvailableItems = RM_Save.GetArray("AvailableItems").ToList(); } } - protected override void OnDeleted() - { - if (UsePlayerPrefs) - { - UnlockItems = null; - AvailableItems = null; - } - - } // Implement IUpgradeStorage Interface diff --git a/Tests/FileManager.cs b/Tests/FileManager.cs new file mode 100644 index 0000000..2aefa27 --- /dev/null +++ b/Tests/FileManager.cs @@ -0,0 +1,118 @@ +using System.Collections.Generic; +using System.Reflection; +using UnityEngine; + +namespace RealMethod +{ + public abstract class FileManager : MonoBehaviour, IGameManager + { + protected class FileData + { + public FieldInfo[] Fields { get; private set; } + public PropertyInfo[] Properties { get; private set; } + + public FileData(object Instance, BindingFlags flags) + { + System.Type type = Instance.GetType(); + Fields = type.GetFields(flags); + Properties = type.GetProperties(flags); + } + } + protected Dictionary FileList = new Dictionary(); + + public event System.Action OnFileAdded; + public event System.Action OnFileRemoved; + + // Implement IGameManager Interface + MonoBehaviour IGameManager.GetManagerClass() + { + return this; + } + public virtual void InitiateManager(bool AlwaysLoaded) + { + + } + public virtual void ResolveService(Service service, bool active) + { + + } + + // Functions + public bool AddFile(IFile file) + { + if (!FileList.ContainsKey(file)) + { + if (CanAddFile(file)) + { + FileList.Add(file, CreateFileData(file)); + OnFileAdded?.Invoke(file); + return true; + } + else + { + Debug.LogWarning($"Can't Add file with name: {file.Name}"); + return false; + } + } + else + { + Debug.LogWarning($"There is a file with this name: {file.Name}"); + return false; + } + } + public bool RemoveFile(IFile file) + { + if (FileList.ContainsKey(file)) + { + FileList.Remove(file); + OnFileRemoved?.Invoke(file); + return true; + } + else + { + Debug.LogWarning($"Can't find any file with this name: {file.Name}"); + return false; + } + } + public bool IsValidFile(IFile file) + { + return FileList.ContainsKey(file); + } + protected T GetFileData(IFile file) where T : FileData + { + return (T)FileList[file]; + } + + // Methods + protected virtual BindingFlags GetFlagSetting() + { + return BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.Static; + } + protected virtual FileData CreateFileData(IFile file) + { + return new FileData(file.GetObject(), GetFlagSetting()); + } + + // Abstraction Methods + protected abstract bool CanAddFile(IFile file); + } + + public abstract class FileManager : FileManager where T : FileAsset + { + [Header("Files")] + [SerializeField] + private T[] Files; + + + // IGameManager + public override void InitiateManager(bool AlwaysLoaded) + { + base.InitiateManager(AlwaysLoaded); + foreach (var file in Files) + { + AddFile(file); + } + Files = null; + } + } +} \ No newline at end of file diff --git a/Tests/FileManager.cs.meta b/Tests/FileManager.cs.meta new file mode 100644 index 0000000..61e8aa7 --- /dev/null +++ b/Tests/FileManager.cs.meta @@ -0,0 +1,2 @@ +fileFormatVersion: 2 +guid: 3a9a003a670dfa440ac2138c4913af6a \ No newline at end of file diff --git a/Tests/General/MissionManager.cs b/Tests/General/MissionManager.cs index 940eaaf..0b1912d 100644 --- a/Tests/General/MissionManager.cs +++ b/Tests/General/MissionManager.cs @@ -33,8 +33,6 @@ public abstract class MissionManager : MonoBehaviour, IGameManager //private PlayerEnergy playerenargy; // private Rigidbody body; private int currentObstacleCount = 0; - // private bool IsMissionComplited = false; - private DataManager dataManager; private Text GoalRecord; private Text GoalTitle; private Button NextLevel; @@ -54,7 +52,7 @@ public void InitiateManager(bool AlwaysLoaded) //playercontroller = PlayerObject.GetComponent(); //playerenargy = PlayerObject.GetComponent(); //body = PlayerObject.GetComponent(); - dataManager = Game.Instance.GetComponent(); + //dataManager = Game.Instance.GetComponent(); GoalRecord = UI.GetComponentsInChildren()[1]; GoalTitle = UI.GetComponentsInChildren()[0]; GoalRecord.text = $"{currentObstacleCount}/{ObstacleCount}"; diff --git a/Tests/General/TutorialManager.cs b/Tests/General/TutorialManager.cs index 1e1b603..95b1933 100644 --- a/Tests/General/TutorialManager.cs +++ b/Tests/General/TutorialManager.cs @@ -224,7 +224,7 @@ private void OnPlayerMassChanged(float mass) // aIManager.SetEnemySpawnEnabled(true); // ResetPlayer(); // Savefile.FirstPlay = true; - // Game.Instance.GetComponent().SaveFile(); + // Game.Instance.GetComponent().SaveFile(); // Destroy(this); // } From 3c9906dec1624028d2c17dd24e85b653f1401871 Mon Sep 17 00:00:00 2001 From: Alijimpa Date: Mon, 20 Apr 2026 22:17:15 +0330 Subject: [PATCH 117/204] Remove NameID from Some Asset --- Runtime/Pattern/Assets/FileAsset.cs | 6 ++++++ Runtime/Pattern/Assets/ItemConfig.cs | 1 - Runtime/Pattern/Managers/HapticManager.cs | 3 --- Runtime/Toolkit/PCG/Assets/PCGCashAsset.cs | 1 - Runtime/Toolkit/PCG/Assets/PCGResourceConfig.cs | 1 - Runtime/Toolkit/RPG/StatSystem/BuffConfig.cs | 2 -- Runtime/Toolkit/RPG/StatSystem/CharacterStatComponent.cs | 6 +++--- Runtime/Toolkit/RPG/StatSystem/StatProfile.cs | 3 +-- Runtime/Toolkit/Tutorial/TutorialConfig.cs | 3 --- 9 files changed, 10 insertions(+), 16 deletions(-) diff --git a/Runtime/Pattern/Assets/FileAsset.cs b/Runtime/Pattern/Assets/FileAsset.cs index c1683ac..9fb4847 100644 --- a/Runtime/Pattern/Assets/FileAsset.cs +++ b/Runtime/Pattern/Assets/FileAsset.cs @@ -19,9 +19,13 @@ public abstract class FileAsset : UniqueAsset, IFile private DateTime createTime; private DateTime modifiedTime; + // Implement IFile Interface + string IFile.Name => name; DateTime IFile.CreateTime => createTime; DateTime IFile.ModifiedTime => modifiedTime; + public object GetObject() => this; + // Unity Events protected virtual void OnEnable() @@ -63,6 +67,8 @@ protected virtual void OnValidate() { Modifiy(); } + + #endif } } \ No newline at end of file diff --git a/Runtime/Pattern/Assets/ItemConfig.cs b/Runtime/Pattern/Assets/ItemConfig.cs index 1946366..b128bf6 100644 --- a/Runtime/Pattern/Assets/ItemConfig.cs +++ b/Runtime/Pattern/Assets/ItemConfig.cs @@ -7,7 +7,6 @@ public abstract class ItemConfig : ConfigAsset, IItem [Header("Item")] [SerializeField] protected string itemName; - public Name16 NameID => itemName; [SerializeField] protected Texture2D _icon; public Texture2D Icon => _icon; diff --git a/Runtime/Pattern/Managers/HapticManager.cs b/Runtime/Pattern/Managers/HapticManager.cs index 2638279..780dcd8 100644 --- a/Runtime/Pattern/Managers/HapticManager.cs +++ b/Runtime/Pattern/Managers/HapticManager.cs @@ -138,9 +138,6 @@ public abstract class HapticConfig : ConfigAsset, IIdentifier [SerializeField] private string configName; - // Implement - public Name16 NameID => configName; - private void OnValidate() { configName = name; diff --git a/Runtime/Toolkit/PCG/Assets/PCGCashAsset.cs b/Runtime/Toolkit/PCG/Assets/PCGCashAsset.cs index a877b37..36d472c 100644 --- a/Runtime/Toolkit/PCG/Assets/PCGCashAsset.cs +++ b/Runtime/Toolkit/PCG/Assets/PCGCashAsset.cs @@ -11,7 +11,6 @@ public interface IPCGCashAsset : IIdentifier public class PCGCashAsset : ConfigAsset, IPCGCashAsset { - public Name16 NameID => name; [SerializeField] private PCGData[] CashData; diff --git a/Runtime/Toolkit/PCG/Assets/PCGResourceConfig.cs b/Runtime/Toolkit/PCG/Assets/PCGResourceConfig.cs index 90ba5db..623bab9 100644 --- a/Runtime/Toolkit/PCG/Assets/PCGResourceConfig.cs +++ b/Runtime/Toolkit/PCG/Assets/PCGResourceConfig.cs @@ -36,7 +36,6 @@ public struct PCGSource [CreateAssetMenu(fileName = "PCG_Resource", menuName = "RealMethod/PCG/Resource", order = 1)] public class PCGResourceConfig : ConfigAsset, IPCGResource { - public Name16 NameID => name; [SerializeField] private PCGSource[] Sources; diff --git a/Runtime/Toolkit/RPG/StatSystem/BuffConfig.cs b/Runtime/Toolkit/RPG/StatSystem/BuffConfig.cs index dc3b416..e38fca6 100644 --- a/Runtime/Toolkit/RPG/StatSystem/BuffConfig.cs +++ b/Runtime/Toolkit/RPG/StatSystem/BuffConfig.cs @@ -8,8 +8,6 @@ public abstract class BuffConfig : ConfigAsset, IIdentifier [Header("Setting")] [SerializeField] private string configName; - // Implement IIdentifier Interface - public Name16 NameID => configName; // Abstract Method public abstract IStatModifier[] GetModifiers(T StateName) where T : System.Enum; diff --git a/Runtime/Toolkit/RPG/StatSystem/CharacterStatComponent.cs b/Runtime/Toolkit/RPG/StatSystem/CharacterStatComponent.cs index fc274fe..92d8985 100644 --- a/Runtime/Toolkit/RPG/StatSystem/CharacterStatComponent.cs +++ b/Runtime/Toolkit/RPG/StatSystem/CharacterStatComponent.cs @@ -14,7 +14,7 @@ public abstract class CharacterStat : MonoBehaviour, IPrimitiveStatContainer private BuffConfig[] DefaultBuff; - protected DataManager SaveSystem; + protected SaveManager SaveSystem; // Unity Methods @@ -31,7 +31,7 @@ private void Awake() } private void Start() { - SaveSystem = Game.GetManager(); + SaveSystem = Game.GetManager(); } private void OnEnable() { @@ -93,7 +93,7 @@ public void Save() if (SaveSystem) { Profile.StoreStats(); - SaveSystem.SaveFile(Profile.file); + SaveSystem.Save(Profile.file); } else { diff --git a/Runtime/Toolkit/RPG/StatSystem/StatProfile.cs b/Runtime/Toolkit/RPG/StatSystem/StatProfile.cs index 0139e51..4f9728b 100644 --- a/Runtime/Toolkit/RPG/StatSystem/StatProfile.cs +++ b/Runtime/Toolkit/RPG/StatSystem/StatProfile.cs @@ -45,8 +45,7 @@ public IStat this[int index] } } - // Implement IIdentifier Interface - public Name16 NameID => profileName; + // Implement IPrimitiveStatContainer Interface void IPrimitiveStatContainer.InitializeResource(IResourceData resource) { resource.Initialize(this); diff --git a/Runtime/Toolkit/Tutorial/TutorialConfig.cs b/Runtime/Toolkit/Tutorial/TutorialConfig.cs index e663bf2..b42da6e 100644 --- a/Runtime/Toolkit/Tutorial/TutorialConfig.cs +++ b/Runtime/Toolkit/Tutorial/TutorialConfig.cs @@ -33,9 +33,6 @@ public abstract class TutorialConfigCore : ConfigAsset, IItem, ITutorialSpawner private float offset; public float Offset => offset; - - // Implement IIdentifier Interface - public Name16 NameID => label; // Implement IItem Interface public Texture2D Icon => icon; Sprite IItem.GetSpriteIcon() From 78ac6c39a4ea8c92bc910adaac6f4b11b28dcba7 Mon Sep 17 00:00:00 2001 From: Alijimpa Date: Mon, 20 Apr 2026 22:17:44 +0330 Subject: [PATCH 118/204] Implement two Function for Check Interface Implemantion --- Runtime/Library/Extension/GameObject.cs | 78 +++++++++++++------------ Runtime/Library/Extension/Object.cs | 68 ++++++++++++++++++++- 2 files changed, 107 insertions(+), 39 deletions(-) diff --git a/Runtime/Library/Extension/GameObject.cs b/Runtime/Library/Extension/GameObject.cs index 03f8602..bdfb79c 100644 --- a/Runtime/Library/Extension/GameObject.cs +++ b/Runtime/Library/Extension/GameObject.cs @@ -228,43 +228,6 @@ public static bool IsInScene(this GameObject obj) #endif } /// - /// Registers the GameObject with a shared object system. - /// - /// The GameObject to register. - public static void Share(this GameObject obj , bool safety = true) - { - if (Game.Bridge.IsHolding && safety) - { - Debug.LogError("You can't Set Object as Shared in holding time (When bridge hold all object in gamescope or unhold)"); - return; - } - Game.Bridge.AddSharedObject(obj); - obj.SendMessage(MessageNames.Share, true, SendMessageOptions.DontRequireReceiver); - } - /// - /// Unregisters the GameObject from the shared object system. - /// - /// The GameObject to unregister. - public static void Unshare(this GameObject obj, bool safety = true) - { - if (Game.Bridge.IsHolding && safety) - { - Debug.LogError("You can't Set Object as Shared in holding time (When bridge hold all object in gamescope or unhold)"); - return; - } - Game.Bridge.RemoveSharedObject(obj); - obj.SendMessage(MessageNames.Share, false, SendMessageOptions.DontRequireReceiver); - } - /// - /// Checks if the GameObject is currently registered in the shared object system. - /// - /// The GameObject to check. - /// True if the GameObject is shared, false otherwise. - public static bool IsShared(this GameObject obj) - { - return Game.Bridge.IsSharedObject(obj); - } - /// /// Check if GameObject was lives in DontDestroyOnload scene /// /// The GameObject to check. @@ -285,7 +248,48 @@ public static void SetLayerRecursively(this GameObject target, int layer) t.gameObject.layer = layer; } } + /// + /// Checks whether the GameObject contains a component that implements or matches type T. + /// + /// The interface or component type to search for. + /// The GameObject to check. + /// True if a component of type T exists on the GameObject; otherwise false. + public static bool HasImplementInterface(this GameObject target) + { + if (target != null) + { + T provider = target.GetComponent(); + if (provider != null) + { + return true; + } + } + return false; + } + /// + /// Checks whether the GameObject contains a component that implements or matches type T + /// and returns the found component. + /// + /// The interface or component type to search for. + /// The GameObject to check. + /// Outputs the found component if one exists. + /// True if a component of type T exists on the GameObject; otherwise false. + public static bool HasImplementInterface(this GameObject target, out T Result) + { + if (target != null) + { + T provider = target.GetComponent(); + if (provider != null) + { + Result = provider; + return true; + } + } + Result = default; + return false; + + } #if UNITY_EDITOR diff --git a/Runtime/Library/Extension/Object.cs b/Runtime/Library/Extension/Object.cs index 800a6e9..db8c061 100644 --- a/Runtime/Library/Extension/Object.cs +++ b/Runtime/Library/Extension/Object.cs @@ -4,9 +4,9 @@ namespace RealMethod { public static class Object_Extension { - public static bool NullChecker(this Object Obj, string Name) + public static bool NullChecker(this object Obj, string Name) { - if (Obj) + if (Obj != null) { return true; } @@ -51,5 +51,69 @@ public static bool TryGetType(this object obj, out SoftType result) where return false; } } + /// + /// Checks whether the object contains a component that implements or matches type T. + /// + /// The interface or component type to search for. + /// The object to check. + /// True if a component of type T exists on the object; otherwise false. + public static bool HasImplementInterface(this object target) + { + if (target != null) + { + if (target is T provider) + { + return true; + } + } + return false; + } + /// + /// Checks whether the object contains a component that implements or matches type T + /// and returns the found component. + /// + /// The interface or component type to search for. + /// The object to check. + /// Outputs the found component if one exists. + /// True if a component of type T exists on the object; otherwise false. + public static bool HasImplementInterface(this object target, out T Result) + { + if (target != null) + { + if (target is T provider) + { + Result = provider; + return true; + } + } + + Result = default; + return false; + + } + /// + /// Get all fields from object by filtering bindingflags + /// + /// the object refrence + /// make filtering witch type of field + /// Array of Fieldinfo + public static System.Reflection.FieldInfo[] GetFields(this object target, System.Reflection.BindingFlags flags) + { + System.Type type = target.GetType(); + return type.GetFields(flags); + } + /// + /// Get all Property from object by filtering bindingflags + /// + /// the object refrence + /// make filtering witch type of Property + /// Array of PropertyInfo + public static System.Reflection.PropertyInfo[] GetProperties(this object target, System.Reflection.BindingFlags flags) + { + System.Type type = target.GetType(); + return type.GetProperties(flags); + } + + } } \ No newline at end of file From abe55f5014538307b6a36125e4bfc266cbc4a375 Mon Sep 17 00:00:00 2001 From: Alijimpa Date: Mon, 20 Apr 2026 22:40:30 +0330 Subject: [PATCH 119/204] Fix FileAsset CompileRule --- .../Rules/PrimitveAssetsRule.cs | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/Editor/Core/InitializeOnLoad/Rules/PrimitveAssetsRule.cs b/Editor/Core/InitializeOnLoad/Rules/PrimitveAssetsRule.cs index 9cd4c09..4e08ec7 100644 --- a/Editor/Core/InitializeOnLoad/Rules/PrimitveAssetsRule.cs +++ b/Editor/Core/InitializeOnLoad/Rules/PrimitveAssetsRule.cs @@ -25,15 +25,15 @@ public override void OnStartCheck(RuleExecutionMode mode) if (asset is not DataAsset) asset.Invoke(FunctionNames.AssetPermission); - if (AssetDatabase.Contains(asset)) - { - if (asset is FileAsset) - { - Debug.LogWarning($"InstanceAsset '{asset.name}' is used directly in Play Mode. " + - $"A runtime instanceAsset should be used instead.Create() at runtime", - asset); - } - } + // if (AssetDatabase.Contains(asset)) + // { + // if (asset is FileAsset) + // { + // Debug.LogWarning($"InstanceAsset '{asset.name}' is used directly in Play Mode. " + + // $"A runtime instanceAsset should be used instead.Create() at runtime", + // asset); + // } + // } } if (asset.AutoReset(CurrentMode)) From de88f63276fdcd5c0cf5b647dcdc45d608b9c3c4 Mon Sep 17 00:00:00 2001 From: Alijimpa Date: Mon, 20 Apr 2026 22:51:52 +0330 Subject: [PATCH 120/204] AddDescription --- Runtime/Pattern/Assets/FileAsset.cs | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/Runtime/Pattern/Assets/FileAsset.cs b/Runtime/Pattern/Assets/FileAsset.cs index 9fb4847..00ace95 100644 --- a/Runtime/Pattern/Assets/FileAsset.cs +++ b/Runtime/Pattern/Assets/FileAsset.cs @@ -14,8 +14,8 @@ namespace RealMethod public abstract class FileAsset : UniqueAsset, IFile { [Header("File")] - [SerializeField, TextArea(5, 20)] - private string fileContents; + [SerializeField, TextArea(3, 20)] + private string description; private DateTime createTime; private DateTime modifiedTime; @@ -66,9 +66,11 @@ protected void Modifiy() protected virtual void OnValidate() { Modifiy(); + if (string.IsNullOrWhiteSpace(description)) + { + description = $"Description for {name}.\nWrite details here..."; + } } - - #endif } } \ No newline at end of file From 6f930b75403329043e7ce6e2a74e84d899b2f5ec Mon Sep 17 00:00:00 2001 From: Alijimpa Date: Tue, 21 Apr 2026 11:53:39 +0330 Subject: [PATCH 121/204] Add Save UniqAsset with playerPrefs --- Runtime/Library/Utilities/SaveLibrary.cs | 33 ++++++++++++++++++++++++ 1 file changed, 33 insertions(+) diff --git a/Runtime/Library/Utilities/SaveLibrary.cs b/Runtime/Library/Utilities/SaveLibrary.cs index f2d2d24..2540a58 100644 --- a/Runtime/Library/Utilities/SaveLibrary.cs +++ b/Runtime/Library/Utilities/SaveLibrary.cs @@ -1,6 +1,10 @@ using System.Linq; using UnityEngine; +#if UNITY_ADDRESSABLES +using UnityEngine.AddressableAssets; +#endif + namespace RealMethod { public static class RM_Save @@ -180,5 +184,34 @@ public static T[] GetArray(string key) string joined = PlayerPrefs.GetString(key); return joined.Split('|').Select(s => (T)System.Convert.ChangeType(s, typeof(T))).ToArray(); // Convert each string to T } + + // Asset + public static void SetAsset(string key, T asset) where T : UniqueAsset + { + string savedAddress = string.Empty; +#if UNITY_ADDRESSABLES + savedAddress = AddressablesUtility.GetAddress(asset); +#else + savedAddress = asset.name; +#endif + PlayerPrefs.SetString(key, savedAddress); + PlayerPrefs.Save(); + } + public static T GetAsset(string key) where T : UniqueAsset + { + if (!PlayerPrefs.HasKey(key)) return null; + string savedAddress = PlayerPrefs.GetString(key); + +#if UNITY_ADDRESSABLES + if (!string.IsNullOrEmpty(savedAddress)) + { + loadedObject = await Addressables.LoadAssetAsync(savedAddress).Task; + return loadedObject; + } +#else + return Resources.Load(savedAddress); +#endif + } + } } \ No newline at end of file From fe86bf1c49f00d452cacaede7086bafbb7c7261a Mon Sep 17 00:00:00 2001 From: Alijimpa Date: Tue, 21 Apr 2026 11:53:51 +0330 Subject: [PATCH 122/204] Refine Editor ContexMenu tools --- Runtime/Pattern/Assets/SaveFile.cs | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/Runtime/Pattern/Assets/SaveFile.cs b/Runtime/Pattern/Assets/SaveFile.cs index 1549500..8da837b 100644 --- a/Runtime/Pattern/Assets/SaveFile.cs +++ b/Runtime/Pattern/Assets/SaveFile.cs @@ -61,6 +61,19 @@ private void Editor_Delete() Debug.LogError("No SaveManager found in the scene."); } } + [ContextMenu("IsExist")] + private void Editor_IsExist() + { + var manager = FindFirstObjectByType(); + if (manager != null) + { + Debug.Log($"[{name}] IsExist: {manager.IsExist(this)}"); + } + else + { + Debug.LogError("No SaveManager found in the scene."); + } + } #endif } } \ No newline at end of file From e1a6b80a1d7e5ab116da82b21d3630ab48ecf6ef Mon Sep 17 00:00:00 2001 From: Alijimpa Date: Tue, 21 Apr 2026 23:18:32 +0330 Subject: [PATCH 123/204] Refine Interfnal Sendmessage & Implement Save Invoker --- Runtime/Core/Definitions/GameNameConstants.cs | 5 +- Runtime/Library/Extension/Object.cs | 49 +++++++++++++++++++ Runtime/Library/Extension/ScriptableObject.cs | 32 +++--------- 3 files changed, 58 insertions(+), 28 deletions(-) diff --git a/Runtime/Core/Definitions/GameNameConstants.cs b/Runtime/Core/Definitions/GameNameConstants.cs index 75cc4c8..0d2338a 100644 --- a/Runtime/Core/Definitions/GameNameConstants.cs +++ b/Runtime/Core/Definitions/GameNameConstants.cs @@ -14,8 +14,9 @@ public static class MessageNames public const string Attach = "OnAttach"; public const string Detach = "OnDetach"; - // Misc - public const string Share = "OnShare"; + // Save + public const string Save = "OnSave"; + public const string Load = "Onload"; } public static class FunctionNames diff --git a/Runtime/Library/Extension/Object.cs b/Runtime/Library/Extension/Object.cs index db8c061..5df06f6 100644 --- a/Runtime/Library/Extension/Object.cs +++ b/Runtime/Library/Extension/Object.cs @@ -1,3 +1,4 @@ +using System.Reflection; using UnityEngine; namespace RealMethod @@ -16,6 +17,54 @@ public static bool NullChecker(this object Obj, string Name) return false; } } + public static void InvokeSaveEvent(this object obj, SendMessageOptions option = SendMessageOptions.RequireReceiver) + { + if (obj is ISave provider) + { + provider.OnSaved(); + } + else + { + obj.SendMessage(MessageNames.Save, option); + } + } + public static void InvokeLoadEvent(this object obj, SendMessageOptions option = SendMessageOptions.RequireReceiver) + { + if (obj is ISave provider) + { + provider.OnLoaded(); + } + else + { + obj.SendMessage(MessageNames.Load, option); + } + } + public static void SendMessage(this object so, string methodName, SendMessageOptions option) + { + so.SendMessage(methodName, null, option); + } + public static void SendMessage(this object obj, string methodName, object parameter, SendMessageOptions options) + { + var method = obj.GetType().GetMethod(methodName, + BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.Static); + + if (method != null) + { + if (parameter == null) + { + method.Invoke(obj, null); + } + else + { + method.Invoke(obj, new object[1] { parameter }); + } + } + else + { + if (options == SendMessageOptions.RequireReceiver) + Debug.LogError($"[SendMessageError] Method '{methodName}' was not found on '{obj}'."); + } + } public static T Cast(this object obj) where T : class { return (T)obj; diff --git a/Runtime/Library/Extension/ScriptableObject.cs b/Runtime/Library/Extension/ScriptableObject.cs index 07f09df..cfb213d 100644 --- a/Runtime/Library/Extension/ScriptableObject.cs +++ b/Runtime/Library/Extension/ScriptableObject.cs @@ -1,4 +1,3 @@ -using System.Reflection; using UnityEngine; namespace RealMethod @@ -10,7 +9,7 @@ public static class ScriptableObject_Extension /// /// The GameObject to send the message to. /// The object that triggered the spawn event (passed as parameter to the message). - public static void InvokeSpawnEvent(this ScriptableObject owner, Object spawner = null) + public static void InvokeSpawnEvent(this ScriptableObject owner, Object spawner = null, SendMessageOptions option = SendMessageOptions.RequireReceiver) { if (spawner != null) { @@ -20,7 +19,7 @@ public static void InvokeSpawnEvent(this ScriptableObject owner, Object spawner } else { - owner.Invoke(MessageNames.Spawn, new object[1] { spawner }); + owner.SendMessage(MessageNames.Spawn, spawner, option); } } else @@ -31,7 +30,7 @@ public static void InvokeSpawnEvent(this ScriptableObject owner, Object spawner } else { - owner.Invoke(MessageNames.Spawn); + owner.SendMessage(MessageNames.Spawn, option); } } } @@ -40,7 +39,7 @@ public static void InvokeSpawnEvent(this ScriptableObject owner, Object spawner /// /// The GameObject to send the message to. /// The object that triggered the despawn event (passed as parameter to the message). - public static void InvokeDespawnEvent(this ScriptableObject owner, Object despawner = null) + public static void InvokeDespawnEvent(this ScriptableObject owner, Object despawner = null, SendMessageOptions option = SendMessageOptions.RequireReceiver) { if (despawner != null) { @@ -50,7 +49,7 @@ public static void InvokeDespawnEvent(this ScriptableObject owner, Object despaw } else { - owner.Invoke(MessageNames.Despawn, new object[1] { despawner }); + owner.SendMessage(MessageNames.Despawn, despawner, option); } } else @@ -61,29 +60,10 @@ public static void InvokeDespawnEvent(this ScriptableObject owner, Object despaw } else { - owner.Invoke(MessageNames.Despawn); + owner.SendMessage(MessageNames.Despawn, option); } } } - - public static void Invoke(this ScriptableObject so, string methodName) - { - so.Invoke(methodName, null); - } - public static void Invoke(this ScriptableObject so, string methodName, object[] parameters) - { - var method = so.GetType().GetMethod(methodName, - BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic); - - if (method != null) - { - method.Invoke(so, parameters); - } - else - { - Debug.LogError($"Method '{methodName}' not found."); - } - } public static ScriptableObject Clone(this ScriptableObject so) { return ScriptableObject.Instantiate(so); From 9d55255dd9ebcee91a3dfb43468978d935c469a4 Mon Sep 17 00:00:00 2001 From: Alijimpa Date: Tue, 21 Apr 2026 23:28:54 +0330 Subject: [PATCH 124/204] Implement ApplyDamage Overload method --- Runtime/Library/Extension/GameObject.cs | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/Runtime/Library/Extension/GameObject.cs b/Runtime/Library/Extension/GameObject.cs index bdfb79c..4cbd33e 100644 --- a/Runtime/Library/Extension/GameObject.cs +++ b/Runtime/Library/Extension/GameObject.cs @@ -25,6 +25,16 @@ public static void Death(this GameObject target) } } /// + /// pplies damage to the target GameObject. + /// + /// The GameObject that should receive damage. + /// ther GameObject how applyed damage + /// The damage payload containing specific value + public static void ApplyDamage(this GameObject target, GameObject attacker, float damage) + { + target.ApplyDamage(new HitData(new RaycastHit(), attacker, damage)); + } + /// /// Applies damage to the target GameObject using two fallback methods: /// 1) If the object implements , damage is applied directly through TakeDamage. /// 2) Otherwise, a Unity SendMessage call is made using GameMessages.ApplyDamage. From c855490807b8cb50ed1188a354a1864a430c244f Mon Sep 17 00:00:00 2001 From: Alijimpa Date: Wed, 22 Apr 2026 11:23:30 +0330 Subject: [PATCH 125/204] Refine Namespace and implement SaveManager --- .../Inspectors/CompositManagerEditor.cs | 2 +- .../Pattern/Inspectors/SaveManagerEditor.cs | 29 ++++++++++--------- .../Pattern/Inspectors/TaskManagerEditor.cs | 2 +- 3 files changed, 17 insertions(+), 16 deletions(-) diff --git a/Editor/Pattern/Inspectors/CompositManagerEditor.cs b/Editor/Pattern/Inspectors/CompositManagerEditor.cs index da7723f..6bcfc77 100644 --- a/Editor/Pattern/Inspectors/CompositManagerEditor.cs +++ b/Editor/Pattern/Inspectors/CompositManagerEditor.cs @@ -1,7 +1,7 @@ using UnityEditor; using UnityEngine; -namespace RealMethod +namespace RealMethod.Editor { [CustomEditor(typeof(CompositManager), true)] public class CompositManagerEditor : UnityEditor.Editor diff --git a/Editor/Pattern/Inspectors/SaveManagerEditor.cs b/Editor/Pattern/Inspectors/SaveManagerEditor.cs index 9e45873..5f62e39 100644 --- a/Editor/Pattern/Inspectors/SaveManagerEditor.cs +++ b/Editor/Pattern/Inspectors/SaveManagerEditor.cs @@ -1,39 +1,40 @@ using UnityEditor; +using UnityEngine; -namespace RealMethod +namespace RealMethod.Editor { [CustomEditor(typeof(SaveManager), true)] public class SaveManagerEditor : UnityEditor.Editor { - private SaveManager BaseComponent; + private SaveManager Component; private bool IsShowLoadedFile = false; private void OnEnable() { - BaseComponent = (SaveManager)target; + Component = (SaveManager)target; } public override void OnInspectorGUI() { base.OnInspectorGUI(); - EditorGUILayout.Space(); - EditorGUILayout.LabelField(" ----------------- History ----------------- "); - if (BaseComponent != null) + EditorGUILayout.LabelField("", GUI.skin.horizontalSlider); + IsShowLoadedFile = EditorGUILayout.Foldout(IsShowLoadedFile, "Files", true, EditorStyles.foldoutHeader); + if (IsShowLoadedFile) { - if (BaseComponent.DataLog != null && BaseComponent.DataLog.Length > 0) + IFile[] files = Component.GetAllFiles(); + if (Component != null) { - foreach (var item in BaseComponent.DataLog) + foreach (var file in files) { - if (item != string.Empty) - { - EditorGUILayout.LabelField(item); - } + EditorGUILayout.LabelField($"{file.Key}({file.GetObject().GetType()})"); } } EditorGUILayout.Space(); - EditorGUILayout.LabelField($"TotalLog: {BaseComponent.Logindex}"); + EditorGUILayout.LabelField($"Total: {files.Length}"); } - } + + } + } \ No newline at end of file diff --git a/Editor/Pattern/Inspectors/TaskManagerEditor.cs b/Editor/Pattern/Inspectors/TaskManagerEditor.cs index 3ad9442..c3e531a 100644 --- a/Editor/Pattern/Inspectors/TaskManagerEditor.cs +++ b/Editor/Pattern/Inspectors/TaskManagerEditor.cs @@ -1,7 +1,7 @@ using System; using UnityEditor; -namespace RealMethod +namespace RealMethod.Editor { [CustomEditor(typeof(TaskManager), true)] public class TaskManagerEditor : UnityEditor.Editor From 5dee2cd7373947eed305f7700bc85b56bf4f3597 Mon Sep 17 00:00:00 2001 From: Alijimpa Date: Thu, 23 Apr 2026 00:02:17 +0330 Subject: [PATCH 126/204] Fix & Refine SoftTyp Struct --- Editor/Core/Drawers/SoftTypeDrawer.cs | 4 ++++ Runtime/Core/Definitions/SoftType.cs | 8 +++++++- 2 files changed, 11 insertions(+), 1 deletion(-) diff --git a/Editor/Core/Drawers/SoftTypeDrawer.cs b/Editor/Core/Drawers/SoftTypeDrawer.cs index 2cf7693..1697f01 100644 --- a/Editor/Core/Drawers/SoftTypeDrawer.cs +++ b/Editor/Core/Drawers/SoftTypeDrawer.cs @@ -17,7 +17,11 @@ public override void OnGUI(Rect position, SerializedProperty property, GUIConten var typeProp = property.FindPropertyRelative("typeName"); if (displayNames == null) + { Initialize(typeProp); + typeProp.stringValue = typeNames[currentIndex]; + } + int newIndex = EditorGUI.Popup(position, label.text, currentIndex, displayNames); diff --git a/Runtime/Core/Definitions/SoftType.cs b/Runtime/Core/Definitions/SoftType.cs index d1e6782..33b5e99 100644 --- a/Runtime/Core/Definitions/SoftType.cs +++ b/Runtime/Core/Definitions/SoftType.cs @@ -9,7 +9,7 @@ public abstract class SoftType protected string typeName; // => PropertyRelative public Type Type { - get => string.IsNullOrEmpty(typeName) ? null : Type.GetType(typeName); + get => string.IsNullOrEmpty(typeName) ? GetNullType() : Type.GetType(typeName); set => typeName = value?.AssemblyQualifiedName; } @@ -66,6 +66,9 @@ public override int GetHashCode() { return typeName?.GetHashCode() ?? 0; } + + // Abstract Method + protected abstract Type GetNullType(); } [Serializable] @@ -79,6 +82,9 @@ public static implicit operator SoftType(Type type) return new SoftType { typeName = type?.AssemblyQualifiedName }; } + + // SoftType Method + protected override Type GetNullType() => typeof(T); } From 11f633eef6cc1eb911ef98abe1c27aa2b203b611 Mon Sep 17 00:00:00 2001 From: Alijimpa Date: Thu, 23 Apr 2026 00:11:10 +0330 Subject: [PATCH 127/204] Refine Some Extention functions --- Runtime/Library/Extension/Object.cs | 17 +++++++++++++++++ Runtime/Library/Extension/Type.cs | 15 ++++----------- 2 files changed, 21 insertions(+), 11 deletions(-) diff --git a/Runtime/Library/Extension/Object.cs b/Runtime/Library/Extension/Object.cs index 5df06f6..f8c05fe 100644 --- a/Runtime/Library/Extension/Object.cs +++ b/Runtime/Library/Extension/Object.cs @@ -65,6 +65,23 @@ public static void SendMessage(this object obj, string methodName, object parame Debug.LogError($"[SendMessageError] Method '{methodName}' was not found on '{obj}'."); } } + /// + /// Attempts to cast the given to the specified at runtime. + /// + /// The source object to be cast. + /// The target type to cast to. + /// + /// Return true is cansting correct + /// + public static bool CanCast(this object obj, System.Type type) + { + if (obj == null) + throw new System.ArgumentNullException(nameof(obj)); + if (type == null) + throw new System.ArgumentNullException(nameof(type)); + + return type.IsInstanceOfType(obj); + } public static T Cast(this object obj) where T : class { return (T)obj; diff --git a/Runtime/Library/Extension/Type.cs b/Runtime/Library/Extension/Type.cs index 78ca40c..e264e3c 100644 --- a/Runtime/Library/Extension/Type.cs +++ b/Runtime/Library/Extension/Type.cs @@ -4,21 +4,14 @@ namespace RealMethod { public static class Type_Extension { - public static bool IsChild(this Type type) where T : Type + public static bool IsChild(this Type type) { - return type.IsAssignableFrom(typeof(T)); + return typeof(T).IsAssignableFrom(type); } public static bool IsChild(this Type type, Type target) { - return type.IsAssignableFrom(target); - } - public static bool IsChild(this SoftType soft) where T : Type - { - return soft.Type.IsAssignableFrom(typeof(T)); - } - public static bool IsChild(this SoftType soft, SoftType target) - { - return soft.Type.IsAssignableFrom(target); + return target.IsAssignableFrom(type); } + } } \ No newline at end of file From bf9705b34912ce69f844d68bb8faa522049f7cdb Mon Sep 17 00:00:00 2001 From: Alijimpa Date: Thu, 23 Apr 2026 00:25:58 +0330 Subject: [PATCH 128/204] Rename Function --- Runtime/Library/Extension/Object.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Runtime/Library/Extension/Object.cs b/Runtime/Library/Extension/Object.cs index f8c05fe..cf17a22 100644 --- a/Runtime/Library/Extension/Object.cs +++ b/Runtime/Library/Extension/Object.cs @@ -73,7 +73,7 @@ public static void SendMessage(this object obj, string methodName, object parame /// /// Return true is cansting correct /// - public static bool CanCast(this object obj, System.Type type) + public static bool IsChild(this object obj, System.Type type) { if (obj == null) throw new System.ArgumentNullException(nameof(obj)); From 0a0aa0487a90e0b5a9735c9fcb876d261dff27d3 Mon Sep 17 00:00:00 2001 From: Alijimpa Date: Thu, 23 Apr 2026 18:46:20 +0330 Subject: [PATCH 129/204] Refine SaveSystem --- .../Pattern/Inspectors/SaveManagerEditor.cs | 7 +- Runtime/Core/Architecture/Game.cs | 52 ++ Runtime/Core/Definitions/Save.cs | 218 +++++ .../Definitions}/Save.cs.meta | 0 Runtime/Library/Interfaces/File.cs | 12 - Runtime/Library/Interfaces/File.cs.meta | 2 - Runtime/Library/Interfaces/Save.cs | 16 - Runtime/Pattern/Assets/FileAsset.cs | 76 -- Runtime/Pattern/Assets/FileAsset.cs.meta | 2 - Runtime/Pattern/Assets/SaveFile.cs | 79 -- Runtime/Pattern/Assets/SaveFile.cs.meta | 2 - Runtime/Pattern/Managers/SaveManager.cs | 801 +++++++++++++++--- Runtime/Pattern/Managers/StorageFile.cs | 185 +++- Runtime/ReadySet/Managers/StorageManager.cs | 20 +- Tests/FileManager.cs | 38 +- 15 files changed, 1156 insertions(+), 354 deletions(-) create mode 100644 Runtime/Core/Definitions/Save.cs rename Runtime/{Library/Interfaces => Core/Definitions}/Save.cs.meta (100%) delete mode 100644 Runtime/Library/Interfaces/File.cs delete mode 100644 Runtime/Library/Interfaces/File.cs.meta delete mode 100644 Runtime/Library/Interfaces/Save.cs delete mode 100644 Runtime/Pattern/Assets/FileAsset.cs delete mode 100644 Runtime/Pattern/Assets/FileAsset.cs.meta delete mode 100644 Runtime/Pattern/Assets/SaveFile.cs delete mode 100644 Runtime/Pattern/Assets/SaveFile.cs.meta diff --git a/Editor/Pattern/Inspectors/SaveManagerEditor.cs b/Editor/Pattern/Inspectors/SaveManagerEditor.cs index 5f62e39..9f46dcc 100644 --- a/Editor/Pattern/Inspectors/SaveManagerEditor.cs +++ b/Editor/Pattern/Inspectors/SaveManagerEditor.cs @@ -6,7 +6,8 @@ namespace RealMethod.Editor [CustomEditor(typeof(SaveManager), true)] public class SaveManagerEditor : UnityEditor.Editor { - private SaveManager Component; private bool IsShowLoadedFile = false; + private SaveManager Component; + private bool IsShowLoadedFile = true; private void OnEnable() { @@ -23,9 +24,9 @@ public override void OnInspectorGUI() IFile[] files = Component.GetAllFiles(); if (Component != null) { - foreach (var file in files) + for (int i = 0; i < files.Length; i++) { - EditorGUILayout.LabelField($"{file.Key}({file.GetObject().GetType()})"); + EditorGUILayout.LabelField($"{i}.[{files[i].Key}]: {files[i].GetObject().GetType()}"); } } EditorGUILayout.Space(); diff --git a/Runtime/Core/Architecture/Game.cs b/Runtime/Core/Architecture/Game.cs index 6837eae..8c5f177 100644 --- a/Runtime/Core/Architecture/Game.cs +++ b/Runtime/Core/Architecture/Game.cs @@ -146,8 +146,29 @@ public static event Action OnReady public static event Action OnStateChanged; + /// + /// Gets the active implementation used for saving, + /// loading, and checking file existence. This value is assigned internally + /// through CheckSaveSystem. + /// + public ISaveSystem SaveSystem + { + get + { + if (IsGameInitialized == false) + { + Debug.LogWarning("Game has not been initialized yet! You cannot call this method before initialization."); + return null; + } + + ISaveSystem result = World.gameObject.GetComponent(); + if (result == null) + result = gameObject.GetComponentInChildren(); + return result; + } + } /// /// Cached array of managers that were instantiated from configured game prefabs. /// @@ -160,6 +181,7 @@ public static event Action OnReady + /// /// Initializes the game singleton and core systems on subsystem registration. /// This sets up the , game , @@ -790,6 +812,34 @@ public static bool SetState(int NewState, object author) return false; } /// + /// Saves the provided file using the active implementation. + /// Logs a warning if no save system is available. + /// + public static void Save() + { + var system = Instance.SaveSystem; + if (system == null) + { + Debug.LogWarning("There is not any ISaveSystem Implemntation"); + return; + } + system.SaveAll(); + } + /// + /// Loads the provided file using the active implementation. + /// Logs a warning if no save system is available. + /// + public static void Load() + { + var system = Instance.SaveSystem; + if (system == null) + { + Debug.LogWarning("There is not any ISaveSystem Implemntation"); + return; + } + system.LoadAll(); + } + /// /// Quits the application. In the Unity Editor this stops play mode instead. /// public static void Quit() @@ -1047,6 +1097,7 @@ protected virtual void OnServiceCleand() } + /// /// Callback invoked when a new is created or assigned. /// Updates the static reference and notifies all services. @@ -1080,6 +1131,7 @@ private void Notify_OnGameQuit() OnGameClosed(); } + #if UNITY_EDITOR private void Awake() { diff --git a/Runtime/Core/Definitions/Save.cs b/Runtime/Core/Definitions/Save.cs new file mode 100644 index 0000000..ddb40df --- /dev/null +++ b/Runtime/Core/Definitions/Save.cs @@ -0,0 +1,218 @@ +using UnityEditor; +using UnityEngine; + +namespace RealMethod +{ + + public interface IFile : IIdentifier + { + string Key { get; } + object GetObject(); + } + + + public interface ISaveSystem + { + /// + /// Checks whether the specified file exists in the save storage. + /// + bool IsExist(IFile file); + /// + /// Saves the specified file to the save storage. + /// + void Save(IFile file); + /// + /// Loads the specified file from the save storage into memory. + /// + void Load(IFile file); + /// + /// Deletes the specified file from the save storage. + /// + void Delete(IFile file); + /// + /// Save all file or Specific file that implemented + /// + void SaveAll(); + /// + /// Load all file or specific file that implemented + /// + void LoadAll(); + /// + /// use for adding file to filelist in savemsystem. + /// if you want to use saveall or geting file with name + /// + /// target file you want adding + /// return true if can add + bool AddFile(IFile file); + /// + /// use for removing file to filelist in savesystem + /// + /// target file you want removing + /// return true if can remove + bool RemoveFile(IFile file); + /// + /// Determines whether the specified file already exists in the file list. + /// Checks by object reference unless IFile implementations override equality. + /// + /// The file instance to check. + /// True if the file is found in the list; otherwise false. + bool HasFile(IFile file); + /// + /// The file that created by savesystem for merging all file selected in sytem to one file + /// + IFile MainSaveFile { get; } + } + public interface ISave + { + void OnLoaded(); + void OnSaved(); + } + + + public interface ISaveFile : IFile, ISave + { + void SetName(string NewName); + } + + + /// + /// this is UniqueAsset that implement ISaveFile Interface with some Editor Function + /// for testing save and load + /// + public abstract class SaveAsset : UniqueAsset, ISaveFile + { + // Implement IFile Interface + string IFile.Key => name; + object IFile.GetObject() => this; + // Implement ISave Interface + void ISave.OnLoaded() + { + OnLoaded(); + } + void ISave.OnSaved() + { + OnSaved(); + } + // Implement ISaveFile Interface + void ISaveFile.SetName(string NewName) + { + Debug.LogWarning($"Can't change Name for Asset({name}). the SaveAsset get asset name for file naming"); + } + + // Unity Method + protected virtual void OnEnable() + { +#if !UNITY_EDITOR + ISaveSystem saveSystem = Game.Instance.SaveSystem; + if (saveSystem != null) + { + if (!saveSystem.HasFile(this)) + saveSystem.AddFile(this); + } + else + { + Debug.LogError("Can't find SaveSystem"); + } +#endif + } + protected virtual void OnDisable() + { +#if !UNITY_EDITOR + ISaveSystem saveSystem = Game.Instance.SaveSystem; + if (saveSystem != null) + { + if (saveSystem.HasFile(this)) + saveSystem.RemoveFile(this); + } + else + { + Debug.LogError("Can't find SaveSystem"); + } +#endif + } + protected virtual void Reset() + { +#if UNITY_EDITOR + ISaveSystem saveSystem = Game.Instance.SaveSystem; + if (saveSystem != null) + { + if (!saveSystem.HasFile(this)) + saveSystem.AddFile(this); + } + else + { + Debug.LogError("Can't find SaveSystem"); + } +#endif + } + + protected abstract void OnLoaded(); + protected abstract void OnSaved(); + + +#if UNITY_EDITOR + public override bool AutoReset(PlayModeStateChange state) + { + if (state == PlayModeStateChange.EnteredPlayMode) + return true; + return base.AutoReset(state); + } + [ContextMenu("Save")] + private void Editor_SaveSelf() + { + var manager = FindFirstObjectByType(); + if (manager != null) + { + manager.Save(this); + } + else + { + Debug.LogError("No SaveManager found in the scene."); + } + } + [ContextMenu("Load")] + private void Editor_LoadSelf() + { + var manager = FindFirstObjectByType(); + if (manager != null) + { + manager.Load(this); + } + else + { + Debug.LogError("No SaveManager found in the scene."); + } + } + [ContextMenu("Delete")] + private void Editor_Delete() + { + var manager = FindFirstObjectByType(); + if (manager != null) + { + manager.Delete(this); + } + else + { + Debug.LogError("No SaveManager found in the scene."); + } + } + [ContextMenu("IsExist")] + private void Editor_IsExist() + { + var manager = FindFirstObjectByType(); + if (manager != null) + { + Debug.Log($"[{name}] IsExist: {manager.IsExist(this)}"); + } + else + { + Debug.LogError("No SaveManager found in the scene."); + } + } +#endif + + + } + + +} \ No newline at end of file diff --git a/Runtime/Library/Interfaces/Save.cs.meta b/Runtime/Core/Definitions/Save.cs.meta similarity index 100% rename from Runtime/Library/Interfaces/Save.cs.meta rename to Runtime/Core/Definitions/Save.cs.meta diff --git a/Runtime/Library/Interfaces/File.cs b/Runtime/Library/Interfaces/File.cs deleted file mode 100644 index e544c12..0000000 --- a/Runtime/Library/Interfaces/File.cs +++ /dev/null @@ -1,12 +0,0 @@ -using System; - -namespace RealMethod -{ - public interface IFile : IIdentifier - { - string Name { get; } - DateTime CreateTime { get; } - DateTime ModifiedTime { get; } - object GetObject(); - } -} \ No newline at end of file diff --git a/Runtime/Library/Interfaces/File.cs.meta b/Runtime/Library/Interfaces/File.cs.meta deleted file mode 100644 index 623dd53..0000000 --- a/Runtime/Library/Interfaces/File.cs.meta +++ /dev/null @@ -1,2 +0,0 @@ -fileFormatVersion: 2 -guid: 6c684480001c7de4aaf0295cd17845ec \ No newline at end of file diff --git a/Runtime/Library/Interfaces/Save.cs b/Runtime/Library/Interfaces/Save.cs deleted file mode 100644 index 69b9e79..0000000 --- a/Runtime/Library/Interfaces/Save.cs +++ /dev/null @@ -1,16 +0,0 @@ -namespace RealMethod -{ - public interface ISave : IIdentifier - { - void OnLoaded(); - void OnSaved(); - } - - public interface ISaveSystem - { - bool IsExist(IFile file); - void Save(IFile file); - void Load(IFile file); - void Delete(IFile file); - } -} \ No newline at end of file diff --git a/Runtime/Pattern/Assets/FileAsset.cs b/Runtime/Pattern/Assets/FileAsset.cs deleted file mode 100644 index 00ace95..0000000 --- a/Runtime/Pattern/Assets/FileAsset.cs +++ /dev/null @@ -1,76 +0,0 @@ -using System; -using UnityEngine; - -namespace RealMethod -{ - /// - /// A specialized UniqueAsset used for File system. - /// The asset is uniqueAsset can instance at runtime. - /// and developer can use fileasset for saving data in asset, - /// or in runtime asset creation. - /// The asset itself cannot be used cloned. - /// Instead, the system creates new independent instances based on this asset's data. - /// - public abstract class FileAsset : UniqueAsset, IFile - { - [Header("File")] - [SerializeField, TextArea(3, 20)] - private string description; - private DateTime createTime; - private DateTime modifiedTime; - - - // Implement IFile Interface - string IFile.Name => name; - DateTime IFile.CreateTime => createTime; - DateTime IFile.ModifiedTime => modifiedTime; - public object GetObject() => this; - - - // Unity Events - protected virtual void OnEnable() - { - createTime = DateTime.Now; - } - - // Virtual Methods - protected sealed override void EnsureAssetPermission() - { -#if UNITY_EDITOR || DEVELOPMENT_BUILD - if (HasCloneName()) - { - Debug.LogError($"[{name}] FileAsset cannot clone at runtime. NewAsset has been removed!"); - DestroyImmediate(this); - return; - } - if (IsSpawned) - { - if (IsProjectAsset()) - { - Debug.LogError($"[{name}] This asset is direct asset but Spawn Event called. Asset has been removed!"); - DestroyImmediate(this); - return; - } - } -#endif - } - - // Protected Methods - protected void Modifiy() - { - modifiedTime = DateTime.Now; - EnsureAssetPermission(); - } - -#if UNITY_EDITOR - protected virtual void OnValidate() - { - Modifiy(); - if (string.IsNullOrWhiteSpace(description)) - { - description = $"Description for {name}.\nWrite details here..."; - } - } -#endif - } -} \ No newline at end of file diff --git a/Runtime/Pattern/Assets/FileAsset.cs.meta b/Runtime/Pattern/Assets/FileAsset.cs.meta deleted file mode 100644 index 3e03daa..0000000 --- a/Runtime/Pattern/Assets/FileAsset.cs.meta +++ /dev/null @@ -1,2 +0,0 @@ -fileFormatVersion: 2 -guid: ea69fb27b44567a4ba06ab6a8464898d \ No newline at end of file diff --git a/Runtime/Pattern/Assets/SaveFile.cs b/Runtime/Pattern/Assets/SaveFile.cs deleted file mode 100644 index 8da837b..0000000 --- a/Runtime/Pattern/Assets/SaveFile.cs +++ /dev/null @@ -1,79 +0,0 @@ -using UnityEngine; - -namespace RealMethod -{ - /// - /// this is FileAsset that implement ISave Interface with some Editor Function - /// for testing save and load - /// - public abstract class SaveFile : FileAsset, ISave - { - // Implement ISave Interface - void ISave.OnLoaded() - { - OnLoaded(); - } - void ISave.OnSaved() - { - OnSaved(); - } - - protected abstract void OnLoaded(); - protected abstract void OnSaved(); - -#if UNITY_EDITOR - [ContextMenu("Save")] - private void Editor_SaveSelf() - { - var manager = FindFirstObjectByType(); - if (manager != null) - { - manager.Save(this); - } - else - { - Debug.LogError("No SaveManager found in the scene."); - } - } - [ContextMenu("Load")] - private void Editor_LoadSelf() - { - var manager = FindFirstObjectByType(); - if (manager != null) - { - manager.Load(this); - } - else - { - Debug.LogError("No SaveManager found in the scene."); - } - } - [ContextMenu("Delete")] - private void Editor_Delete() - { - var manager = FindFirstObjectByType(); - if (manager != null) - { - manager.Delete(this); - } - else - { - Debug.LogError("No SaveManager found in the scene."); - } - } - [ContextMenu("IsExist")] - private void Editor_IsExist() - { - var manager = FindFirstObjectByType(); - if (manager != null) - { - Debug.Log($"[{name}] IsExist: {manager.IsExist(this)}"); - } - else - { - Debug.LogError("No SaveManager found in the scene."); - } - } -#endif - } -} \ No newline at end of file diff --git a/Runtime/Pattern/Assets/SaveFile.cs.meta b/Runtime/Pattern/Assets/SaveFile.cs.meta deleted file mode 100644 index d684db0..0000000 --- a/Runtime/Pattern/Assets/SaveFile.cs.meta +++ /dev/null @@ -1,2 +0,0 @@ -fileFormatVersion: 2 -guid: f680f5cc45f833d4ab1e78d5984c13d6 \ No newline at end of file diff --git a/Runtime/Pattern/Managers/SaveManager.cs b/Runtime/Pattern/Managers/SaveManager.cs index a42031e..42550f5 100644 --- a/Runtime/Pattern/Managers/SaveManager.cs +++ b/Runtime/Pattern/Managers/SaveManager.cs @@ -4,17 +4,32 @@ using System.Reflection; using System.IO; using UnityEngine; +using System.Linq; +using System.ComponentModel; namespace RealMethod { + [System.Serializable] + public enum SaveFileStructure + { + [DescriptionEnum("Always read/write one fixed file")] + SingleFile, + [DescriptionEnum("Each save item is saved separately")] + MultiFile, + [DescriptionEnum("Save multiple items but merge them into one output file")] + MergedFile + } [System.Serializable] public enum SaveFormat { - PlayerPrefs = 0, - TEXT = 1, - XML = 2, - JSON = 3, - Binary = 4, + [DescriptionEnum("Didn't Store any data just call OnSave&OnLoad Event")] + None = 0, + PlayerPrefs = 1, + TEXT = 2, + XML = 3, + JSON = 4, + Binary = 5, + Custom = 6, } public interface ISaveMethod { @@ -23,19 +38,31 @@ public interface ISaveMethod BindingFlags FieldFlags { get; } BindingFlags PropertieFlags { get; } } + public interface IMergeFile : ISaveFile + { + void Write(string fileName, string variableName, System.Type variableType, object variableValue); + object Read(string fileName, string variableName, System.Type variableType); + } - public abstract class SaveManager : MonoBehaviour, IGameManager , ISaveSystem + + public abstract class SaveManager : MonoBehaviour, IGameManager, ISaveSystem { + [Header("Mode")] + [SerializeField] + protected SaveFileStructure Mode = SaveFileStructure.MultiFile; + [Space] + [SerializeField, ConditionalShowByEnum("Mode", SaveFileStructure.MergedFile)] + private BindingFlags MergedFieldFlags = BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic; + [SerializeField, ConditionalShowByEnum("Mode", SaveFileStructure.MergedFile)] + private BindingFlags MergedPropertieFlags = BindingFlags.Default; // Actions public event System.Action OnLoaded; public event System.Action OnSaved; public event System.Action OnDeleted; -#if UNITY_EDITOR - public byte Logindex { get; private set; } - public string[] DataLog { get; private set; } -#endif + + // Implement IGameManager Interface @@ -45,19 +72,52 @@ MonoBehaviour IGameManager.GetManagerClass() } public virtual void InitiateManager(bool AlwaysLoaded) { -#if UNITY_EDITOR - Logindex = 0; - DataLog = new string[5]; -#endif + if (Mode != SaveFileStructure.MultiFile) + { + IFile provider = CreateMainFile(); + ISaveMethod method = GetMethod(provider); + if (method.Format == SaveFormat.None) + { + OnLoad(provider, method); + } + else + { + if (IsExistFile(provider, method)) + { + OnLoad(provider, method); + } + } + } } public virtual void ResolveService(Service service, bool active) { } - // Functions + // Implement ISaveSystem Interface + /// + /// The file that created by savesystem for merging all file selected in sytem to one file or SingleFile + /// + public IFile MainSaveFile + { + get + { + if (Mode == SaveFileStructure.MultiFile) + { + Debug.LogWarning("MainSaveFile Just created in SingleFile & MergedFile"); + return null; + } + else + { + return GetMainFile(); + } + } + } public bool IsExist(IFile file) { + if (!CanContinue("check isExist")) + return false; + if (!Validate(file)) return false; @@ -65,58 +125,223 @@ public bool IsExist(IFile file) } public void Save(IFile file) { + if (!CanContinue("Save")) + return; + if (!Validate(file)) return; - if (file.GetObject() is ISave provider) + try { OnSave(file, GetMethod(file)); - provider.OnSaved(); - OnSaved?.Invoke(file); - -#if UNITY_EDITOR - WriteLog($"Save ({GetMethod(file)})", file); -#endif } - else + catch (System.Exception ex) { - Debug.LogWarning($"For saving file you should implement ISave interface in {file.GetObject()}"); + Debug.LogError(ex); return; } + file.GetObject().InvokeSaveEvent(); + OnSaved?.Invoke(file); +#if UNITY_EDITOR || DEVELOPMENT_BUILD + WriteLog($"Save({GetMethod(file).Format}) Class({file.GetObject().GetType()})"); +#endif } public void Load(IFile file) { + if (!CanContinue("Load")) + return; + if (!Validate(file)) return; - if (file.GetObject() is ISave provider) + try { OnLoad(file, GetMethod(file)); - provider.OnLoaded(); - OnLoaded?.Invoke(file); -#if UNITY_EDITOR - WriteLog($"Save ({GetMethod(file)})", file); -#endif } - else + catch (System.Exception ex) { - Debug.LogWarning($"For loading file you should implement ISave interface in {file.GetObject()}"); + Debug.LogError(ex); return; } + file.GetObject().InvokeLoadEvent(); + OnLoaded?.Invoke(file); +#if UNITY_EDITOR || DEVELOPMENT_BUILD + WriteLog($"Load({GetMethod(file).Format}) Class({file.GetObject().GetType()})"); +#endif } public void Delete(IFile file) { if (!Validate(file)) return; - OnDelete(file, GetMethod(file)); + try + { + OnDelete(file, GetMethod(file)); + } + catch (System.Exception ex) + { + Debug.LogError(ex); + return; + } OnDeleted?.Invoke(file); -#if UNITY_EDITOR - WriteLog($"Save ({GetMethod(file)})", file); +#if UNITY_EDITOR || DEVELOPMENT_BUILD + WriteLog($"Delete({GetMethod(file).Format}) Class({file.GetObject().GetType()})"); #endif } + [ContextMenu("Save")] + void ISaveSystem.SaveAll() + { + IFile[] files = GetAllFiles(); + if (files != null) + { + switch (Mode) + { + case SaveFileStructure.SingleFile: + if (!Validate(MainSaveFile)) + return; + + try + { + OnSave(MainSaveFile, GetMethod(MainSaveFile)); + } + catch (System.Exception ex) + { + Debug.LogError(ex); + return; + } + MainSaveFile.GetObject().InvokeSaveEvent(); + OnSaved?.Invoke(MainSaveFile); +#if UNITY_EDITOR || DEVELOPMENT_BUILD + WriteLog($"Save[SingleFile]({GetMethod(MainSaveFile).Format}) Class({MainSaveFile.GetObject().GetType()})"); +#endif + break; + case SaveFileStructure.MultiFile: + foreach (var file in files) + { + Save(file); + } + break; + case SaveFileStructure.MergedFile: + foreach (var file in files) + { + WriteToMergeFile(file, MergedFieldFlags, MergedPropertieFlags); + } + + + if (!Validate(MainSaveFile)) + return; + + try + { + OnSave(MainSaveFile, GetMethod(MainSaveFile)); + } + catch (System.Exception ex) + { + Debug.LogError(ex); + return; + } + MainSaveFile.GetObject().InvokeSaveEvent(); + OnSaved?.Invoke(MainSaveFile); +#if UNITY_EDITOR || DEVELOPMENT_BUILD + WriteLog($"Save[MergedFile]({GetMethod(MainSaveFile).Format}) Class({MainSaveFile.GetObject().GetType()})"); +#endif + break; + } + } + } + [ContextMenu("Load")] + void ISaveSystem.LoadAll() + { + IFile[] files = GetAllFiles(); + if (files != null) + { + switch (Mode) + { + case SaveFileStructure.SingleFile: + if (!Validate(MainSaveFile)) + return; + + try + { + OnLoad(MainSaveFile, GetMethod(MainSaveFile)); + } + catch (System.Exception ex) + { + Debug.LogError(ex); + return; + } + MainSaveFile.GetObject().InvokeLoadEvent(); + OnLoaded?.Invoke(MainSaveFile); +#if UNITY_EDITOR || DEVELOPMENT_BUILD + WriteLog($"Load({GetMethod(MainSaveFile).Format}) Class({MainSaveFile.GetObject().GetType()})"); +#endif + break; + case SaveFileStructure.MultiFile: + foreach (var file in files) + { + Save(file); + } + break; + case SaveFileStructure.MergedFile: + foreach (var file in files) + { + ReadFromMergeFile(file, MergedFieldFlags, MergedPropertieFlags); + } + + + if (!Validate(MainSaveFile)) + return; + + try + { + OnLoad(MainSaveFile, GetMethod(MainSaveFile)); + } + catch (System.Exception ex) + { + Debug.LogError(ex); + return; + } + MainSaveFile.GetObject().InvokeLoadEvent(); + OnLoaded?.Invoke(MainSaveFile); +#if UNITY_EDITOR || DEVELOPMENT_BUILD + WriteLog($"Load({GetMethod(MainSaveFile).Format}) Class({MainSaveFile.GetObject().GetType()})"); +#endif + break; + } + } + } + /// + /// use for adding file to filelist in savemsystem. + /// if you want to use saveall or geting file with name + /// + /// target file you want adding + /// return true if can add + public abstract bool AddFile(IFile file); + /// + /// use for removing file to filelist in savesystem + /// + /// target file you want removing + /// return true if can remove + public abstract bool RemoveFile(IFile file); + /// + /// Determines whether the specified file already exists in the file list. + /// Checks by object reference unless IFile implementations override equality. + /// + /// The file instance to check. + /// True if the file is found in the list; otherwise false. + public abstract bool HasFile(IFile file); + // Methods + protected virtual bool CanContinue(string message) + { + if (Mode == SaveFileStructure.MultiFile) + { + return true; + } + Debug.LogError($"You can't {message} when SaveMode is {Mode}"); + return false; + } protected virtual bool Validate(IFile file) { if (file == null && file.GetObject() != null) @@ -128,7 +353,7 @@ protected virtual bool Validate(IFile file) } protected virtual ISaveMethod GetMethod(IFile file) { - if (file.GetObject().HasImplementInterface(out ISaveMethod method)) + if (file != null && file.GetObject().HasImplementInterface(out ISaveMethod method)) { return method; } @@ -144,6 +369,32 @@ protected virtual ISaveMethod GetMethod(IFile file) } } } + protected virtual void WriteToMergeFile(IFile file, BindingFlags fieldFlags, BindingFlags propertyFlags) + { + object FileObject = file.GetObject(); + IMergeFile mergefile = GetMainFile(); + foreach (var field in FileObject.GetFields(fieldFlags)) + { + mergefile.Write(file.Key, field.Name, field.FieldType, field.GetValue(FileObject)); + } + foreach (var propery in FileObject.GetProperties(propertyFlags)) + { + mergefile.Write(file.Key, propery.Name, propery.PropertyType, propery.GetValue(FileObject)); + } + } + protected virtual void ReadFromMergeFile(IFile file, BindingFlags fieldFlags, BindingFlags propertyFlags) + { + object FileObject = file.GetObject(); + IMergeFile mergefile = GetMainFile(); + foreach (var field in FileObject.GetFields(fieldFlags)) + { + field.SetValue(FileObject, mergefile.Read(file.Key, field.Name, field.FieldType)); + } + foreach (var propery in FileObject.GetProperties(propertyFlags)) + { + propery.SetValue(FileObject, mergefile.Read(file.Key, propery.Name, propery.PropertyType)); + } + } // Abstract Mehtod @@ -151,39 +402,40 @@ protected virtual ISaveMethod GetMethod(IFile file) protected abstract void OnSave(IFile file, ISaveMethod Method); protected abstract void OnLoad(IFile file, ISaveMethod Method); protected abstract void OnDelete(IFile file, ISaveMethod Method); -#if UNITY_EDITOR - private void WriteLog(string message, IFile file) + protected abstract IFile CreateMainFile(); + protected abstract T GetMainFile() where T : IFile; + public abstract IFile[] GetAllFiles(); + + +#if UNITY_EDITOR || DEVELOPMENT_BUILD + protected virtual void WriteLog(string message) { - if (Application.isPlaying && DataLog != null) - { - if (Logindex == 0) - { - DataLog[0] = $"{System.DateTime.Now} -- {file.Name} -- {message}"; - Logindex++; - } - else - { - DataLog[Logindex % DataLog.Length] = $"{System.DateTime.Now} -- {file.Name} -- {message}"; - Logindex++; - } - } + Debug.Log($"{System.DateTime.Now} -- {message}"); } #endif } - public abstract class SaveMethodManager : SaveManager, ISaveMethod + public abstract class SaveManager_Method : SaveManager, ISaveMethod { + protected enum SaveState + { + IsExist = 0, + Save = 1, + Load = 2, + Delete = 3 + } [Header("SaveMethod")] [SerializeField] private SaveFormat fromat; - [SerializeField, ConditionalHideByEnum("fromat", 0)] + [SerializeField, ConditionalHideByEnum("fromat", SaveFormat.None, SaveFormat.PlayerPrefs)] private bool CustomPath = false; - [SerializeField, ConditionalHide("CustomPath", true, false)] + [SerializeField, ConditionalHideByEnum("fromat", SaveFormat.None, SaveFormat.PlayerPrefs), ConditionalHide("CustomPath", true, false)] private string FilePath = System.Environment.GetFolderPath(System.Environment.SpecialFolder.Desktop); - [SerializeField, ConditionalShowByEnum("fromat", SaveFormat.PlayerPrefs, SaveFormat.TEXT)] + [SerializeField, ConditionalShowByEnum("fromat", SaveFormat.PlayerPrefs, SaveFormat.TEXT, SaveFormat.Custom)] private BindingFlags FieldFlags = BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic; - [SerializeField, ConditionalShowByEnum("fromat", SaveFormat.PlayerPrefs, SaveFormat.TEXT)] + [SerializeField, ConditionalShowByEnum("fromat", SaveFormat.PlayerPrefs, SaveFormat.TEXT, SaveFormat.Custom)] private BindingFlags PropertieFlags = BindingFlags.Default; + // Implement ISaveMethod Interface SaveFormat ISaveMethod.Format => fromat; string ISaveMethod.Path => FilePath; @@ -196,6 +448,9 @@ protected override bool IsExistFile(IFile file, ISaveMethod Method) { switch (Method.Format) { + case SaveFormat.None: + Debug.LogWarning("SaveSystem can't check IsExistFile with None format"); + return false; case SaveFormat.Binary: return File.Exists(GetPath(file, Method)); case SaveFormat.XML: @@ -205,7 +460,9 @@ protected override bool IsExistFile(IFile file, ISaveMethod Method) case SaveFormat.TEXT: return File.Exists(GetPath(file, Method)); case SaveFormat.PlayerPrefs: - return PlayerPrefs.HasKey(file.Name); + return PlayerPrefs.HasKey(file.Key); + case SaveFormat.Custom: + return CustomSavefile(file, Method, SaveState.IsExist); default: Debug.LogWarning($"The {Method.Format} is not implement"); return false; @@ -217,6 +474,12 @@ protected override void OnSave(IFile file, ISaveMethod Method) switch (Method.Format) { + case SaveFormat.None: + if (fileObject is not ISave) + { + Debug.LogError($"Your file({fileObject}) with name({file.Key}) should implement ISave Interface"); + } + break; case SaveFormat.Binary: BinaryFormatter bf = new BinaryFormatter(); #pragma warning disable SYSLIB0011 // Suppress BinaryFormatter warning (only use in trusted context) @@ -228,7 +491,7 @@ protected override void OnSave(IFile file, ISaveMethod Method) } catch (System.Exception e) { - Debug.LogError($"Failed to serialize {file.Name} to {GetPath(file, Method)}: {e}"); + Debug.LogError($"Failed to serialize {file.Key} to {GetPath(file, Method)}: {e}"); return; } } @@ -264,17 +527,20 @@ protected override void OnSave(IFile file, ISaveMethod Method) PropertyInfo[] PP_properties = fileObject.GetProperties(Method.PropertieFlags); foreach (FieldInfo field in PP_fields) { - PlayerPrefsSetValueByField(field, fileObject); + Set_PlayerPrefsInfo(field, fileObject); } foreach (PropertyInfo property in PP_properties) { - PlayerPrefsSetValueByProperty(property, fileObject); + Set_PlayerPrefsInfo(property, fileObject); } - PlayerPrefs.SetString(file.Name, System.DateTime.Now.ToString()); + PlayerPrefs.SetString(file.Key, System.DateTime.Now.ToString()); PlayerPrefs.Save(); break; + case SaveFormat.Custom: + CustomSavefile(file, Method, SaveState.Save); + break; default: - Debug.LogWarning($"The {Method} is not implement"); + Debug.LogWarning($"The {Method.Format} is not implement"); break; } } @@ -284,6 +550,12 @@ protected override void OnLoad(IFile file, ISaveMethod Method) switch (Method.Format) { + case SaveFormat.None: + if (fileObject is not ISave) + { + Debug.LogError($"Your file({fileObject}) with name({file.Key}) should implement ISave Interface"); + } + break; case SaveFormat.Binary: var bf = new BinaryFormatter(); #pragma warning disable SYSLIB0011 @@ -390,15 +662,18 @@ protected override void OnLoad(IFile file, ISaveMethod Method) PropertyInfo[] PP_properties = fileObject.GetProperties(Method.PropertieFlags); foreach (FieldInfo field in PP_fields) { - PlayerPrefsGetValueByField(field, fileObject); + Get_PlayerPrefsInfo(field, fileObject); } foreach (PropertyInfo property in PP_properties) { - PlayerPrefsGetValueByProperty(property, fileObject); + Get_PlayerPrefsInfo(property, fileObject); } break; + case SaveFormat.Custom: + CustomSavefile(file, Method, SaveState.Load); + break; default: - Debug.LogWarning($"The {Method} is not implement"); + Debug.LogWarning($"The {Method.Format} is not implement"); break; } } @@ -408,6 +683,9 @@ protected override void OnDelete(IFile file, ISaveMethod Method) switch (Method.Format) { + case SaveFormat.None: + Debug.LogWarning("SaveSystem can't delete with None format"); + break; case SaveFormat.Binary: File.Delete(GetPath(file, Method)); break; @@ -432,8 +710,11 @@ protected override void OnDelete(IFile file, ISaveMethod Method) PlayerPrefs.DeleteKey(property.Name); } break; + case SaveFormat.Custom: + CustomSavefile(file, Method, SaveState.Delete); + break; default: - Debug.LogWarning($"The {Method} is not implement"); + Debug.LogWarning($"The {Method.Format} is not implement"); break; } } @@ -441,11 +722,8 @@ protected override void OnDelete(IFile file, ISaveMethod Method) // Methods protected virtual string GetPath(IFile file, ISaveMethod method) { - string filename = file.Name; - string filetype = method.Format == SaveFormat.TEXT ? ".txt" : - method.Format == SaveFormat.Binary ? ".RSave" : - method.Format == SaveFormat.XML ? ".xml" : - method.Format == SaveFormat.JSON ? ".json" : ""; + string filename = file.Key; + string filetype = GetFileType(method); if (CustomPath) { @@ -456,12 +734,19 @@ protected virtual string GetPath(IFile file, ISaveMethod method) return Application.persistentDataPath + "/" + filename + filetype; } } + protected virtual string GetFileType(ISaveMethod method) + { + return method.Format == SaveFormat.TEXT ? ".txt" : + method.Format == SaveFormat.Binary ? ".RSave" : + method.Format == SaveFormat.XML ? ".xml" : + method.Format == SaveFormat.JSON ? ".json" : ""; + } // Private Method - private void PlayerPrefsSetValueByField(FieldInfo field, object source) + private void Set_PlayerPrefsInfo(MemberInfo info, object source) { - string key = field.Name; - object value = field.GetValue(source); + string key = info.Name; + object value = GetValueInfo(info, source); if (value is int intValue) { @@ -487,129 +772,373 @@ private void PlayerPrefsSetValueByField(FieldInfo field, object source) { PlayerPrefs.SetInt(key, bytevalue); } - else + else if (value is Vector2 v2Value) { - Debug.LogWarning($"Unsupported type for PlayerPrefs: {value?.GetType().Name} (Key: {key})"); + RM_Save.SetVector2(key, v2Value); } - } - private void PlayerPrefsSetValueByProperty(PropertyInfo property, object source) - { - string key = property.Name; - object value = property.GetValue(source); - - if (value is int intValue) + else if (value is Vector3 v3Value) { - PlayerPrefs.SetInt(key, intValue); + RM_Save.SetVector3(key, v3Value); } - else if (value is float floatValue) + else if (value is Quaternion quatValue) { - PlayerPrefs.SetFloat(key, floatValue); + RM_Save.SetQuaternion(key, quatValue); } - else if (value is string stringValue) + else if (value is Transform transValue) { - PlayerPrefs.SetString(key, stringValue); + RM_Save.SetTransform(key, transValue); } - else if (value is bool boolValue) + else if (value is UniqueAsset asset) { - PlayerPrefs.SetInt(key, boolValue ? 1 : 0); + RM_Save.SetAsset(key, asset); } - else if (value is System.Enum enumvalue) + else if (value is IList Intlist) { - PlayerPrefs.SetInt(key, System.Convert.ToInt32(enumvalue)); + RM_Save.SetArray(key, Intlist.ToArray()); } - else if (value is byte bytevalue) + else if (value is IList FloatList) { - PlayerPrefs.SetInt(key, bytevalue); + RM_Save.SetArray(key, FloatList.ToArray()); + } + else if (value is IList StringList) + { + RM_Save.SetArray(key, StringList.ToArray()); + } + else if (value is IList BoolList) + { + RM_Save.SetArray(key, BoolList.ToArray()); + } + else if (value is IList EnumList) + { + RM_Save.SetArray(key, EnumList.ToArray()); + } + else if (value is IList ByteList) + { + RM_Save.SetArray(key, ByteList.ToArray()); + } + else if (value is IList V3List) + { + RM_Save.SetArray(key, V3List.ToArray()); + } + else if (value is IList V2List) + { + RM_Save.SetArray(key, V2List.ToArray()); + } + else if (value is int[] IntArray) + { + RM_Save.SetArray(key, IntArray); + } + else if (value is float[] FloatArray) + { + RM_Save.SetArray(key, FloatArray); + } + else if (value is string[] StringArray) + { + RM_Save.SetArray(key, StringArray); + } + else if (value is bool[] BoolArray) + { + RM_Save.SetArray(key, BoolArray); + } + else if (value is System.Enum[] EnumArray) + { + RM_Save.SetArray(key, EnumArray); + } + else if (value is byte[] ByteArray) + { + RM_Save.SetArray(key, ByteArray); + } + else if (value is Vector3[] V3Array) + { + RM_Save.SetArray(key, V3Array); + } + else if (value is Vector2[] V2Array) + { + RM_Save.SetArray(key, V2Array); } else { Debug.LogWarning($"Unsupported type for PlayerPrefs: {value?.GetType().Name} (Key: {key})"); } + } - private void PlayerPrefsGetValueByField(FieldInfo field, object source) + private void Get_PlayerPrefsInfo(MemberInfo info, object source) { - string key = field.Name; + string key = info.Name; + System.Type type = GetInfoType(info); if (!PlayerPrefs.HasKey(key)) return; - if (field.FieldType == typeof(int)) + if (type == typeof(int)) + { + SetValueInfo(info, source, PlayerPrefs.GetInt(key)); + } + else if (type == typeof(float)) + { + SetValueInfo(info, source, PlayerPrefs.GetFloat(key)); + } + else if (type == typeof(string)) + { + SetValueInfo(info, source, PlayerPrefs.GetString(key)); + } + else if (type == typeof(bool)) + { + SetValueInfo(info, source, PlayerPrefs.GetInt(key) == 1); + } + else if (type == typeof(System.Enum)) + { + SetValueInfo(info, source, PlayerPrefs.GetInt(key)); + } + else if (type == typeof(byte)) + { + SetValueInfo(info, source, PlayerPrefs.GetInt(key)); + } + else if (type == typeof(Vector2)) + { + SetValueInfo(info, source, RM_Save.GetVector2(key)); + } + else if (type == typeof(Vector3)) + { + SetValueInfo(info, source, RM_Save.GetVector3(key)); + } + else if (type == typeof(Quaternion)) + { + SetValueInfo(info, source, RM_Save.GetQuaternion(key)); + } + else if (type == typeof(Transform)) + { + Transform t = (Transform)GetValueInfo(info, source); + RM_Save.GetTransform(key, t); + } + else if (type == typeof(UniqueAsset)) + { + SetValueInfo(info, source, RM_Save.GetAsset(key)); + } + else if (type == typeof(List)) + { + SetValueInfo(info, source, RM_Save.GetArray(key).ToList()); + } + else if (type == typeof(List)) + { + SetValueInfo(info, source, RM_Save.GetArray(key).ToList()); + } + else if (type == typeof(List)) + { + SetValueInfo(info, source, RM_Save.GetArray(key).ToList()); + } + else if (type == typeof(List)) + { + SetValueInfo(info, source, RM_Save.GetArray(key).ToList()); + } + else if (type == typeof(List)) { - field.SetValue(source, PlayerPrefs.GetInt(key)); + SetValueInfo(info, source, RM_Save.GetArray(key).ToList()); } - else if (field.FieldType == typeof(float)) + else if (type == typeof(List)) { - field.SetValue(source, PlayerPrefs.GetFloat(key)); + SetValueInfo(info, source, RM_Save.GetArray(key).ToList()); } - else if (field.FieldType == typeof(string)) + else if (type == typeof(List)) { - field.SetValue(source, PlayerPrefs.GetString(key)); + SetValueInfo(info, source, RM_Save.GetArray(key).ToList()); } - else if (field.FieldType == typeof(bool)) + else if (type == typeof(List)) { - field.SetValue(source, PlayerPrefs.GetInt(key) == 1); + SetValueInfo(info, source, RM_Save.GetArray(key).ToList()); } - else if (field.FieldType == typeof(System.Enum)) + else if (type == typeof(int[])) { - field.SetValue(source, PlayerPrefs.GetInt(key) == 1); + SetValueInfo(info, source, RM_Save.GetArray(key)); } - else if (field.FieldType == typeof(byte)) + else if (type == typeof(float[])) { - field.SetValue(source, PlayerPrefs.GetInt(key) == 1); + SetValueInfo(info, source, RM_Save.GetArray(key)); + } + else if (type == typeof(string[])) + { + SetValueInfo(info, source, RM_Save.GetArray(key)); + } + else if (type == typeof(bool[])) + { + SetValueInfo(info, source, RM_Save.GetArray(key)); + } + else if (type == typeof(System.Enum[])) + { + SetValueInfo(info, source, RM_Save.GetArray(key)); + } + else if (type == typeof(byte[])) + { + SetValueInfo(info, source, RM_Save.GetArray(key)); + } + else if (type == typeof(Vector2[])) + { + SetValueInfo(info, source, RM_Save.GetArray(key)); + } + else if (type == typeof(Vector3[])) + { + SetValueInfo(info, source, RM_Save.GetArray(key)); } } - private void PlayerPrefsGetValueByProperty(PropertyInfo property, object source) + private object GetValueInfo(MemberInfo info, object source) { - string key = property.Name; - - if (!PlayerPrefs.HasKey(key)) return; - - if (property.PropertyType == typeof(int)) + if (info is FieldInfo field) { - property.SetValue(source, PlayerPrefs.GetInt(key)); + return field.GetValue(source); } - else if (property.PropertyType == typeof(float)) + else if (info is PropertyInfo property) { - property.SetValue(source, PlayerPrefs.GetFloat(key)); + return property.GetValue(source); } - else if (property.PropertyType == typeof(string)) + else + { + Debug.LogError("Something wrong MemeberInfo has not correct valid"); + return null; + } + } + private void SetValueInfo(MemberInfo info, object source, T value) + { + if (info is FieldInfo field) + { + field.SetValue(source, value); + } + else if (info is PropertyInfo property) + { + property.SetValue(source, value); + } + else { - property.SetValue(source, PlayerPrefs.GetString(key)); + Debug.LogError("Something wrong MemeberInfo has not correct valid"); + return; } - else if (property.PropertyType == typeof(bool)) + } + private System.Type GetInfoType(MemberInfo info) + { + if (info is FieldInfo field) { - property.SetValue(source, PlayerPrefs.GetInt(key) == 1); + return field.FieldType; } - else if (property.PropertyType == typeof(System.Enum)) + else if (info is PropertyInfo property) { - property.SetValue(source, PlayerPrefs.GetInt(key) == 1); + return property.PropertyType; } - else if (property.PropertyType == typeof(byte)) + else { - property.SetValue(source, PlayerPrefs.GetInt(key) == 1); + Debug.LogError("Something wrong MemeberInfo has not correct valid"); + return null; } } + + // Abstract Mehtod + protected abstract bool CustomSavefile(IFile file, ISaveMethod Method, SaveState state); + + +#if UNITY_EDITOR || DEVELOPMENT_BUILD + [ContextMenu("PrintPath")] + private void PrintPath() + { + if (fromat == SaveFormat.PlayerPrefs) + { + Debug.Log("PlayerPrefs store by OS [Not Specefic location]"); + return; + } + + string filetype = fromat == SaveFormat.TEXT ? ".txt" : + fromat == SaveFormat.Binary ? ".RSave" : + fromat == SaveFormat.XML ? ".xml" : + fromat == SaveFormat.JSON ? ".json" : ""; + + if (CustomPath) + { + Debug.Log(FilePath + "/FileName" + filetype); + } + else + { + Debug.Log(Application.persistentDataPath + "/FileName" + filetype); + } + } +#endif + } - public abstract class SaveLoadManager : SaveMethodManager + public abstract class SaveManager_Storage : SaveManager_Method { - [Header("SaveSetting")] - [SerializeField] - private bool LoadOnInitiate = true; - [SerializeField, ConditionalHide("LoadOnInitiate", true, false)] - private SaveFile[] DefaultFile = new SaveFile[0]; + [Header("Details")] + [SerializeField, ConditionalShowByEnum("Mode", SaveFileStructure.SingleFile)] + private SaveAsset SingeFileAsset; + [SerializeField, ConditionalShowByEnum("Mode", SaveFileStructure.MergedFile)] + private SoftType MergeFileClass; + private object MySaveFile; + public readonly List FileList = new List(3); + - // IGameManager - public override void InitiateManager(bool AlwaysLoaded) + // SaveManager Methods + protected override IFile CreateMainFile() { - base.InitiateManager(AlwaysLoaded); + if (Mode == SaveFileStructure.MergedFile) + { + MySaveFile = System.Activator.CreateInstance(MergeFileClass); + } + if (Mode == SaveFileStructure.SingleFile) + { + MySaveFile = ScriptableObject.CreateInstance(SingeFileAsset.GetType()); + } - if (LoadOnInitiate) + if (MySaveFile is IFile provider) { - foreach (var file in DefaultFile) + return provider; + } + else + { + Debug.LogError("Your MainFile should implement IFile interface"); + return null; + } + } + protected override T GetMainFile() + { + return (T)MySaveFile; + } + public override bool HasFile(IFile file) + { + return FileList.Contains(file); + } + public override bool AddFile(IFile file) + { + if (file == null) + { + WriteLog($"File not valid"); + return false; + } + + if (FileList.Contains(file))// reference comparison + { + WriteLog($"File({file.Key}) already added"); + return false; + } + + if (Mode == SaveFileStructure.MultiFile) + { + if (IsExist(file)) { Load(file); } } + + FileList.Add(file); + return true; + } + public override bool RemoveFile(IFile file) + { + if (file == null) + { + WriteLog($"File not valid"); + return false; + } + + return FileList.Remove(file); // removes same reference + } + public override IFile[] GetAllFiles() + { + return FileList.ToArray(); } } diff --git a/Runtime/Pattern/Managers/StorageFile.cs b/Runtime/Pattern/Managers/StorageFile.cs index 7719843..6925c60 100644 --- a/Runtime/Pattern/Managers/StorageFile.cs +++ b/Runtime/Pattern/Managers/StorageFile.cs @@ -1,3 +1,4 @@ +using System; using UnityEngine; namespace RealMethod @@ -5,12 +6,13 @@ namespace RealMethod public interface IStorage { - void StorageCreated(Object author); - void StorageLoaded(Object author); + void StorageCreated(UnityEngine.Object author); + void StorageLoaded(UnityEngine.Object author); void StorageClear(); } - [System.Serializable] - public struct StorageFile where T : IStorage where J : FileAsset + + [Serializable] + public struct StorageFile where T : IStorage where J : SaveAsset { [SerializeField] private bool UseCustomFile; @@ -50,7 +52,7 @@ public T provider // Public Functions - public bool Load(Object author) + public bool Load(UnityEngine.Object author) { ISaveSystem Savesystem = Game.Instance.gameObject.GetComponent(); if (Savesystem == null) @@ -58,7 +60,7 @@ public bool Load(Object author) return Load(author, Savesystem); } - public bool Load(Object author, ISaveSystem manager) + public bool Load(UnityEngine.Object author, ISaveSystem manager) { if (manager == null) { @@ -83,6 +85,7 @@ public void Clear() provider.StorageClear(); } + // Private Functions private bool TryGetStorage(out T _provider) { @@ -115,4 +118,174 @@ private bool TryGetStorage(out T _provider) } } + + public enum StorageMode + { + [DescriptionEnum("Instantiated uniquely for the owner(self).")] + Exclusive = 0, + + [DescriptionEnum("Shared instance obtained from an FileAsset, SaveSystem, or any other global provider.")] + Shared = 1 + } + + [Serializable] + public struct Storage where T : IFile + { + [SerializeField] + private StorageMode Mode; + [Space] + [SerializeField, ConditionalShowByEnum("Mode", StorageMode.Shared)] + private bool UseAsset; + [SerializeField, ConditionalShowByEnum("Mode", StorageMode.Shared), ConditionalHide("UseAsset", true, false)] + private SaveAsset FileAsset; + [SerializeField, ConditionalShowByEnum("Mode", StorageMode.Shared), ConditionalHide("UseAsset", true, true), ShowOnly] + private string SelectedMergeFile; + [SerializeField, ConditionalShowByEnum("Mode", StorageMode.Exclusive)] + private bool UseSelf; + [SerializeField, ConditionalShowByEnum("Mode", StorageMode.Exclusive), ConditionalHide("UseSelf", true, true)] + private string FileName; + [SerializeField, ConditionalShowByEnum("Mode", StorageMode.Exclusive), ConditionalHide("UseSelf", true, true)] + private SoftType FileClass; + + + // Private Fields + private UnityEngine.Object _owner; + private T _file; + private ISaveSystem _saveSystem; + private IFile _mergeFile; + + // Properties + private ISaveSystem saveSystem + { + get + { + if (_saveSystem == null) + { + _saveSystem = Game.Instance.SaveSystem; + } + return _saveSystem; + } + } + public T File + { + get + { + if (_file == null) + { + Refresh(); + } + + return _file; + } + } + public bool IsExist + { + get + { + return saveSystem.IsExist(_file); + } + } + + // Functions + public void Refresh() + { + if (Mode == StorageMode.Shared) + { + if (UseAsset) + { + if (FileAsset == null) + { + Debug.LogError($"Your FileAsset is not valid"); + _file = default; + } + + if (FileAsset is T provider) + { + _file = provider; + } + else + { + Debug.LogError($"Your FileAsset({FileAsset.name}) Should implement {typeof(T)} interface"); + return; + } + } + else + { + _mergeFile = saveSystem.MainSaveFile; + if (_mergeFile != null) + { + SelectedMergeFile = _mergeFile.GetObject().GetType().ToString(); + if (_mergeFile is T provider) + { + _file = provider; + } + else + { + Debug.LogError($"Your MergeFile({_mergeFile.GetObject().GetType()}) Should implement {typeof(T)} interface"); + return; + } + } + else + { + Debug.LogError($"MergeFile in savesystem is not valid"); + return; + } + } + } + else + { + if (UseSelf) + { + if (_owner == null) + { + Debug.LogError($"Your SelfRefrence is not valid [use SetSelf(this) function befor get File]"); + return; + } + + if (_owner is T provider) + { + saveSystem.AddFile(provider); + _file = provider; + } + else + { + Debug.LogError($"Your SelfRefrence({_owner.name}) Should implement {typeof(T)} interface"); + return; + } + } + else + { + object instance = FileClass.Type.CreateInstance(); + if (instance is T provider) + { + if (instance is ISaveFile saveProvider) + { + saveProvider.SetName(FileName); + } + saveSystem.AddFile(provider); + _file = provider; + } + else + { + Debug.LogError($"Your class type({FileClass}) Should implement {typeof(T)} interface"); + return; + } + } + } + + } + public void SetSelf(UnityEngine.Object self) + { + _owner = self; + } + public void Save() + { + saveSystem.Save(_file); + } + public void SetFileName(string NewName) + { + FileName = NewName; + } + } + } \ No newline at end of file diff --git a/Runtime/ReadySet/Managers/StorageManager.cs b/Runtime/ReadySet/Managers/StorageManager.cs index 0e5cacb..7120d6d 100644 --- a/Runtime/ReadySet/Managers/StorageManager.cs +++ b/Runtime/ReadySet/Managers/StorageManager.cs @@ -1,10 +1,28 @@ +using System.Collections.Generic; using UnityEngine; namespace RealMethod { [AddComponentMenu("RealMethod/Manager/SaveManager")] - public sealed class StorageManager : SaveLoadManager + public sealed class StorageManager : SaveManager_Storage { +#if UNITY_EDITOR || DEVELOPMENT_BUILD + [SerializeField] + private bool Log = true; + protected override void WriteLog(string message) + { + if (Log) + { + base.WriteLog(message); + } + } +#endif + // SaveManager Method + protected override bool CustomSavefile(IFile file, ISaveMethod Method, SaveState state) + { + Debug.LogWarning("Didn't Implement any CustomSaving"); + return false; + } } } \ No newline at end of file diff --git a/Tests/FileManager.cs b/Tests/FileManager.cs index 2aefa27..aaeedea 100644 --- a/Tests/FileManager.cs +++ b/Tests/FileManager.cs @@ -50,13 +50,13 @@ public bool AddFile(IFile file) } else { - Debug.LogWarning($"Can't Add file with name: {file.Name}"); + Debug.LogWarning($"Can't Add file with name: {file.Key}"); return false; } } else { - Debug.LogWarning($"There is a file with this name: {file.Name}"); + Debug.LogWarning($"There is a file with this name: {file.Key}"); return false; } } @@ -70,7 +70,7 @@ public bool RemoveFile(IFile file) } else { - Debug.LogWarning($"Can't find any file with this name: {file.Name}"); + Debug.LogWarning($"Can't find any file with this name: {file.Key}"); return false; } } @@ -97,22 +97,22 @@ protected virtual FileData CreateFileData(IFile file) protected abstract bool CanAddFile(IFile file); } - public abstract class FileManager : FileManager where T : FileAsset - { - [Header("Files")] - [SerializeField] - private T[] Files; + // public abstract class FileManager : FileManager where T : FileAsset + // { + // [Header("Files")] + // [SerializeField] + // private T[] Files; - // IGameManager - public override void InitiateManager(bool AlwaysLoaded) - { - base.InitiateManager(AlwaysLoaded); - foreach (var file in Files) - { - AddFile(file); - } - Files = null; - } - } + // // IGameManager + // public override void InitiateManager(bool AlwaysLoaded) + // { + // base.InitiateManager(AlwaysLoaded); + // foreach (var file in Files) + // { + // AddFile(file); + // } + // Files = null; + // } + // } } \ No newline at end of file From ab8e13946fd20204cb26a15ea7c22665e8edc639 Mon Sep 17 00:00:00 2001 From: Alijimpa Date: Thu, 23 Apr 2026 18:46:44 +0330 Subject: [PATCH 130/204] Refine all ConditionalDrawer --- .../Drawers/ConditionalHideByEnumDrawer.cs | 43 +++++++++++++------ .../Drawers/ConditionalShowByEnumDrawer.cs | 21 ++++++--- .../Rules/PrimitveAssetsRule.cs | 4 +- Runtime/Library/Extension/Object.cs | 6 +-- Runtime/Library/Extension/Type.cs | 13 +++++- .../ReadySet/Components/UI/UI_GameSetting.cs | 4 +- Runtime/Toolkit/Inventory/Inventory.cs | 2 +- .../Toolkit/Inventory/InventorySaveFile.cs | 2 +- Runtime/Toolkit/RPG/StatSystem/StatProfile.cs | 2 +- .../Toolkit/RPG/StatSystem/StatSaveFile.cs | 6 ++- Runtime/Toolkit/Tutorial/TutorialSaveFile.cs | 5 ++- Runtime/Toolkit/Tutorial/W_Tutorial.cs | 2 +- .../Upgrade/Sample/ChainUpgradeMapConfig.cs | 2 +- Runtime/Toolkit/Upgrade/Upgrade.cs | 2 +- Runtime/Toolkit/Upgrade/UpgradeSaveFile.cs | 5 ++- 15 files changed, 79 insertions(+), 40 deletions(-) diff --git a/Editor/Core/Drawers/ConditionalHideByEnumDrawer.cs b/Editor/Core/Drawers/ConditionalHideByEnumDrawer.cs index 59cd76c..7d9be6a 100644 --- a/Editor/Core/Drawers/ConditionalHideByEnumDrawer.cs +++ b/Editor/Core/Drawers/ConditionalHideByEnumDrawer.cs @@ -8,28 +8,47 @@ public class ConditionalHideByEnumDrawer : PropertyDrawer { public override void OnGUI(Rect position, SerializedProperty property, GUIContent label) { - ConditionalHideByEnumAttribute hideAttribute = (ConditionalHideByEnumAttribute)attribute; - SerializedProperty enumField = property.serializedObject.FindProperty(hideAttribute.EnumFieldName); + var attr = (ConditionalHideByEnumAttribute)attribute; - if (enumField != null && enumField.enumValueIndex == hideAttribute.EnumValue) + // Build sibling path: replace "UseAsset" with "Mode", etc. + string enumPath = property.propertyPath.Replace(property.name, attr.EnumFieldName); + SerializedProperty enumField = property.serializedObject.FindProperty(enumPath); + + if (enumField != null && !ShouldHide(enumField, attr.HideValues)) { - return; // Do not draw the property if the condition matches. + EditorGUI.PropertyField(position, property, label, true); } - - EditorGUI.PropertyField(position, property, label, true); } public override float GetPropertyHeight(SerializedProperty property, GUIContent label) { - ConditionalHideByEnumAttribute hideAttribute = (ConditionalHideByEnumAttribute)attribute; - SerializedProperty enumField = property.serializedObject.FindProperty(hideAttribute.EnumFieldName); + var attr = (ConditionalHideByEnumAttribute)attribute; + + // Must use the SAME path logic as in OnGUI + string enumPath = property.propertyPath.Replace(property.name, attr.EnumFieldName); + SerializedProperty enumField = property.serializedObject.FindProperty(enumPath); - if (enumField != null && enumField.enumValueIndex == hideAttribute.EnumValue) + if (enumField != null && !ShouldHide(enumField, attr.HideValues)) + { + return EditorGUI.GetPropertyHeight(property, label, true); + } + + // fully hide line + return -EditorGUIUtility.standardVerticalSpacing; + } + + private bool ShouldHide(SerializedProperty enumField, object[] hideValues) + { + if (enumField.propertyType == SerializedPropertyType.Enum) { - return 0; // Hides the property by returning 0 height. + foreach (var value in hideValues) + { + if (enumField.enumValueIndex == (int)value) + return true; // hide when enum matches any of these + } } - return EditorGUI.GetPropertyHeight(property, label, true); + return false; } } -} \ No newline at end of file +} diff --git a/Editor/Core/Drawers/ConditionalShowByEnumDrawer.cs b/Editor/Core/Drawers/ConditionalShowByEnumDrawer.cs index 20fc2ca..0d41b4e 100644 --- a/Editor/Core/Drawers/ConditionalShowByEnumDrawer.cs +++ b/Editor/Core/Drawers/ConditionalShowByEnumDrawer.cs @@ -8,10 +8,13 @@ public class ConditionalShowByEnumDrawer : PropertyDrawer { public override void OnGUI(Rect position, SerializedProperty property, GUIContent label) { - ConditionalShowByEnumAttribute showInInspector = (ConditionalShowByEnumAttribute)attribute; - SerializedProperty enumField = property.serializedObject.FindProperty(showInInspector.EnumFieldName); + var attr = (ConditionalShowByEnumAttribute)attribute; - if (enumField != null && IsVisible(enumField, showInInspector.ShowValues)) + // Build sibling path: replace "UseAsset" with "Mode", etc. + string enumPath = property.propertyPath.Replace(property.name, attr.EnumFieldName); + SerializedProperty enumField = property.serializedObject.FindProperty(enumPath); + + if (enumField != null && IsVisible(enumField, attr.ShowValues)) { EditorGUI.PropertyField(position, property, label); } @@ -19,15 +22,19 @@ public override void OnGUI(Rect position, SerializedProperty property, GUIConten public override float GetPropertyHeight(SerializedProperty property, GUIContent label) { - ConditionalShowByEnumAttribute showInInspector = (ConditionalShowByEnumAttribute)attribute; - SerializedProperty enumField = property.serializedObject.FindProperty(showInInspector.EnumFieldName); + var attr = (ConditionalShowByEnumAttribute)attribute; + + // Must use the SAME path logic as in OnGUI + string enumPath = property.propertyPath.Replace(property.name, attr.EnumFieldName); + SerializedProperty enumField = property.serializedObject.FindProperty(enumPath); - if (enumField != null && IsVisible(enumField, showInInspector.ShowValues)) + if (enumField != null && IsVisible(enumField, attr.ShowValues)) { return EditorGUI.GetPropertyHeight(property, label, true); } - return 0; // Hides the property + // fully hide line + return -EditorGUIUtility.standardVerticalSpacing; } private bool IsVisible(SerializedProperty enumField, object[] showValues) diff --git a/Editor/Core/InitializeOnLoad/Rules/PrimitveAssetsRule.cs b/Editor/Core/InitializeOnLoad/Rules/PrimitveAssetsRule.cs index 4e08ec7..8bdace9 100644 --- a/Editor/Core/InitializeOnLoad/Rules/PrimitveAssetsRule.cs +++ b/Editor/Core/InitializeOnLoad/Rules/PrimitveAssetsRule.cs @@ -23,7 +23,7 @@ public override void OnStartCheck(RuleExecutionMode mode) if (mode == RuleExecutionMode.EnteredPlayMode) { if (asset is not DataAsset) - asset.Invoke(FunctionNames.AssetPermission); + asset.SendMessage(FunctionNames.AssetPermission, SendMessageOptions.RequireReceiver); // if (AssetDatabase.Contains(asset)) // { @@ -38,7 +38,7 @@ public override void OnStartCheck(RuleExecutionMode mode) if (asset.AutoReset(CurrentMode)) { - asset.Invoke(FunctionNames.Reset); + asset.SendMessage(FunctionNames.Reset, SendMessageOptions.RequireReceiver); } } } diff --git a/Runtime/Library/Extension/Object.cs b/Runtime/Library/Extension/Object.cs index cf17a22..7924de6 100644 --- a/Runtime/Library/Extension/Object.cs +++ b/Runtime/Library/Extension/Object.cs @@ -163,7 +163,7 @@ public static bool HasImplementInterface(this object target, out T Result) /// the object refrence /// make filtering witch type of field /// Array of Fieldinfo - public static System.Reflection.FieldInfo[] GetFields(this object target, System.Reflection.BindingFlags flags) + public static FieldInfo[] GetFields(this object target, BindingFlags flags) { System.Type type = target.GetType(); return type.GetFields(flags); @@ -174,12 +174,10 @@ public static System.Reflection.FieldInfo[] GetFields(this object target, System /// the object refrence /// make filtering witch type of Property /// Array of PropertyInfo - public static System.Reflection.PropertyInfo[] GetProperties(this object target, System.Reflection.BindingFlags flags) + public static PropertyInfo[] GetProperties(this object target, BindingFlags flags) { System.Type type = target.GetType(); return type.GetProperties(flags); } - - } } \ No newline at end of file diff --git a/Runtime/Library/Extension/Type.cs b/Runtime/Library/Extension/Type.cs index e264e3c..7479786 100644 --- a/Runtime/Library/Extension/Type.cs +++ b/Runtime/Library/Extension/Type.cs @@ -1,4 +1,5 @@ using System; +using UnityEngine; namespace RealMethod { @@ -12,6 +13,16 @@ public static bool IsChild(this Type type, Type target) { return target.IsAssignableFrom(type); } - + public static object CreateInstance(this Type type) + { + if (type.IsChild(typeof(ScriptableObject))) + { + return ScriptableObject.CreateInstance(type); + } + else + { + return Activator.CreateInstance(type); + } + } } } \ No newline at end of file diff --git a/Runtime/ReadySet/Components/UI/UI_GameSetting.cs b/Runtime/ReadySet/Components/UI/UI_GameSetting.cs index 569724c..6971a5d 100644 --- a/Runtime/ReadySet/Components/UI/UI_GameSetting.cs +++ b/Runtime/ReadySet/Components/UI/UI_GameSetting.cs @@ -28,7 +28,7 @@ public sealed class UI_GameSetting : MonoBehaviour private StorageFile Storage; public bool isFileDirty => Storage.provider.IsSettingDirty; - public SaveFile file => Storage.file; + public SaveAsset file => Storage.file; public bool isInSync { get; private set; } = false; // Unity Methods @@ -243,7 +243,7 @@ private void OnToggleChanged(bool value) } } - public abstract class SettingFile : SaveFile, ISettingStorage + public abstract class SettingFile : SaveAsset, ISettingStorage { protected bool IsDirty { get; private set; } diff --git a/Runtime/Toolkit/Inventory/Inventory.cs b/Runtime/Toolkit/Inventory/Inventory.cs index a68e042..f76d7fb 100644 --- a/Runtime/Toolkit/Inventory/Inventory.cs +++ b/Runtime/Toolkit/Inventory/Inventory.cs @@ -463,7 +463,7 @@ public abstract class InventoryStorage : Inventory [Header("Save")] [SerializeField] private StorageFile storage; - public SaveFile file => storage.file; + public SaveAsset file => storage.file; // override Methods protected sealed override IInventoryStorage GetStorage() diff --git a/Runtime/Toolkit/Inventory/InventorySaveFile.cs b/Runtime/Toolkit/Inventory/InventorySaveFile.cs index 333213e..2e14a90 100644 --- a/Runtime/Toolkit/Inventory/InventorySaveFile.cs +++ b/Runtime/Toolkit/Inventory/InventorySaveFile.cs @@ -5,7 +5,7 @@ namespace RealMethod { [CreateAssetMenu(fileName = "InventorySaveFile", menuName = "RealMethod/Inventory/SaveFile", order = 1)] - public class InventorySaveFile : SaveFile, IInventoryStorage + public class InventorySaveFile : SaveAsset, IInventoryStorage { [Header("Inventory")] [SerializeField, ReadOnly, TextArea] diff --git a/Runtime/Toolkit/RPG/StatSystem/StatProfile.cs b/Runtime/Toolkit/RPG/StatSystem/StatProfile.cs index 4f9728b..012ae76 100644 --- a/Runtime/Toolkit/RPG/StatSystem/StatProfile.cs +++ b/Runtime/Toolkit/RPG/StatSystem/StatProfile.cs @@ -76,7 +76,7 @@ public abstract class StatProfileStorage : StatProfile [Header("Save")] [SerializeField] private StorageFile storage; - public SaveFile file => storage.file; + public SaveAsset file => storage.file; protected sealed override IStatStorage GetStorage() { diff --git a/Runtime/Toolkit/RPG/StatSystem/StatSaveFile.cs b/Runtime/Toolkit/RPG/StatSystem/StatSaveFile.cs index c19aaa6..0014d30 100644 --- a/Runtime/Toolkit/RPG/StatSystem/StatSaveFile.cs +++ b/Runtime/Toolkit/RPG/StatSystem/StatSaveFile.cs @@ -5,7 +5,7 @@ namespace RealMethod { [CreateAssetMenu(fileName = "StatSaveFile", menuName = "RealMethod/RPG/StatSaveFile", order = 1)] - public class StatSaveFile : SaveFile, IStatStorage + public class StatSaveFile : SaveAsset, IStatStorage { [Header("Stat")] [SerializeField, ReadOnly, TextArea] @@ -85,8 +85,10 @@ bool IStatStorage.TryLoadStats(StatData data) // Unity Event - private void Reset() + protected override void Reset() { + base.Reset(); + Names.Clear(); BaseValue.Clear(); Mins.Clear(); diff --git a/Runtime/Toolkit/Tutorial/TutorialSaveFile.cs b/Runtime/Toolkit/Tutorial/TutorialSaveFile.cs index e3ef01f..81dc037 100644 --- a/Runtime/Toolkit/Tutorial/TutorialSaveFile.cs +++ b/Runtime/Toolkit/Tutorial/TutorialSaveFile.cs @@ -9,7 +9,7 @@ namespace RealMethod { [CreateAssetMenu(fileName = "TutorialSaveFile", menuName = "RealMethod/Tutorial/SaveFile", order = 1)] - public class TutorialSaveFile : SaveFile, ITutorialStorage + public class TutorialSaveFile : SaveAsset, ITutorialStorage { [Header("Tutorial")] [SerializeField, ReadOnly, TextArea] @@ -58,8 +58,9 @@ void IStorage.StorageClear() } - private void Reset() + protected override void Reset() { + base.Reset(); TutorialMessage.Clear(); } diff --git a/Runtime/Toolkit/Tutorial/W_Tutorial.cs b/Runtime/Toolkit/Tutorial/W_Tutorial.cs index 4cde322..823ad44 100644 --- a/Runtime/Toolkit/Tutorial/W_Tutorial.cs +++ b/Runtime/Toolkit/Tutorial/W_Tutorial.cs @@ -108,7 +108,7 @@ public abstract class W_TutorialStorage : W_Tutorial [Header("Save")] [SerializeField] private StorageFile storage; - public SaveFile file => storage.file; + public SaveAsset file => storage.file; protected sealed override ITutorialStorage GetStorage() { diff --git a/Runtime/Toolkit/Upgrade/Sample/ChainUpgradeMapConfig.cs b/Runtime/Toolkit/Upgrade/Sample/ChainUpgradeMapConfig.cs index f15f956..20d3ea8 100644 --- a/Runtime/Toolkit/Upgrade/Sample/ChainUpgradeMapConfig.cs +++ b/Runtime/Toolkit/Upgrade/Sample/ChainUpgradeMapConfig.cs @@ -70,7 +70,7 @@ public class ChainUpgradeMapConfig : UpgradeMapConfig, IChainUpgrade { [Header("Setting")] [SerializeField] - private SaveFile CoinFile; + private SaveAsset CoinFile; [SerializeField] public int[] pricing; [SerializeField, ReadOnly] diff --git a/Runtime/Toolkit/Upgrade/Upgrade.cs b/Runtime/Toolkit/Upgrade/Upgrade.cs index d3e6d78..a653137 100644 --- a/Runtime/Toolkit/Upgrade/Upgrade.cs +++ b/Runtime/Toolkit/Upgrade/Upgrade.cs @@ -321,7 +321,7 @@ public abstract class UpgradeStorage : Upgrade [Header("Save")] [SerializeField] private StorageFile storage; - public SaveFile file => storage.file; + public SaveAsset file => storage.file; // override Methods protected sealed override IUpgradeStorage GetStorage() diff --git a/Runtime/Toolkit/Upgrade/UpgradeSaveFile.cs b/Runtime/Toolkit/Upgrade/UpgradeSaveFile.cs index ccad0a5..dea5595 100644 --- a/Runtime/Toolkit/Upgrade/UpgradeSaveFile.cs +++ b/Runtime/Toolkit/Upgrade/UpgradeSaveFile.cs @@ -9,7 +9,7 @@ namespace RealMethod { [CreateAssetMenu(fileName = "UpgradeSaveFile", menuName = "RealMethod/Upgrade/SaveFile", order = 1)] - public class UpgradeSaveFile : SaveFile, IUpgradeStorage + public class UpgradeSaveFile : SaveAsset, IUpgradeStorage { [Header("Setting")] public bool UsePlayerPrefs = true; @@ -85,8 +85,9 @@ void IStorage.StorageClear() } - private void Reset() + protected override void Reset() { + base.Reset(); ((IStorage)this).StorageClear(); } From b71f6089c9d8f9027c983ff0f1fa9574b37b10a8 Mon Sep 17 00:00:00 2001 From: Alijimpa Date: Thu, 23 Apr 2026 18:48:01 +0330 Subject: [PATCH 131/204] Check Attributes --- .../Attributes/ConditionalHideAttribute.cs | 1 + .../ConditionalHideByEnumAttribute.cs | 28 ++++++++++--------- 2 files changed, 16 insertions(+), 13 deletions(-) diff --git a/Runtime/Core/Attributes/ConditionalHideAttribute.cs b/Runtime/Core/Attributes/ConditionalHideAttribute.cs index 5d380f5..b6571bc 100644 --- a/Runtime/Core/Attributes/ConditionalHideAttribute.cs +++ b/Runtime/Core/Attributes/ConditionalHideAttribute.cs @@ -8,6 +8,7 @@ namespace RealMethod /// [ConditionalHide("Variable", true, false)] /// public String TargetName; /// + /// conditionalSourceField,hideInInspector, reverceCondition /// public class ConditionalHideAttribute : PropertyAttribute { diff --git a/Runtime/Core/Attributes/ConditionalHideByEnumAttribute.cs b/Runtime/Core/Attributes/ConditionalHideByEnumAttribute.cs index 5999034..8276351 100644 --- a/Runtime/Core/Attributes/ConditionalHideByEnumAttribute.cs +++ b/Runtime/Core/Attributes/ConditionalHideByEnumAttribute.cs @@ -4,28 +4,30 @@ namespace RealMethod { /// - /// Example: - /// public enum DisplayMode + /// + /// public enum ExampleEnum /// { - /// Mode1, - /// Mode2, - /// Mode3 + /// Option1, + /// Option2, + /// Option3 /// } /// - /// public DisplayMode displayMode; - /// - /// [HideInInspectorByEnum("displayMode", 0)] - /// public int DisplaySize_Mode_1; + /// public ExampleEnum exampleEnum; + /// [ConditionalHideByEnum("exampleEnum", ExampleEnum.Option1, ExampleEnum.Option3)] + /// public string hideOnlyForOption1And3; + /// [ConditionalHideByEnum("exampleEnum", ExampleEnum.Option2)] + /// public int hideOnlyForOption2; + /// /// public class ConditionalHideByEnumAttribute : PropertyAttribute { - public string EnumFieldName { get; private set; } - public int EnumValue { get; private set; } + public string EnumFieldName; + public object[] HideValues; - public ConditionalHideByEnumAttribute(string enumFieldName, int enumValue) + public ConditionalHideByEnumAttribute(string enumFieldName, params object[] hideValues) { EnumFieldName = enumFieldName; - EnumValue = enumValue; + HideValues = hideValues; } } } \ No newline at end of file From a8b74d6926ad65ea2f1b73ded3734d1040c03058 Mon Sep 17 00:00:00 2001 From: Alijimpa Date: Thu, 23 Apr 2026 18:59:55 +0330 Subject: [PATCH 132/204] Remove old Storage --- Runtime/Pattern/Managers/StorageFile.cs | 121 +----------------- .../ReadySet/Components/UI/UI_GameSetting.cs | 58 ++++----- Runtime/Toolkit/Inventory/Inventory.cs | 10 +- .../Toolkit/Inventory/InventoryInterface.cs | 2 +- .../Toolkit/Inventory/InventorySaveFile.cs | 24 ++-- Runtime/Toolkit/RPG/StatSystem/StatProfile.cs | 10 +- .../Toolkit/RPG/StatSystem/StatSaveFile.cs | 18 +-- .../Toolkit/Tutorial/TutorialInterfaces.cs | 2 +- Runtime/Toolkit/Tutorial/TutorialSaveFile.cs | 20 +-- Runtime/Toolkit/Tutorial/W_Tutorial.cs | 10 +- Runtime/Toolkit/Upgrade/Upgrade.cs | 10 +- Runtime/Toolkit/Upgrade/UpgradeInterface.cs | 2 +- Runtime/Toolkit/Upgrade/UpgradeSaveFile.cs | 46 +++---- 13 files changed, 110 insertions(+), 223 deletions(-) diff --git a/Runtime/Pattern/Managers/StorageFile.cs b/Runtime/Pattern/Managers/StorageFile.cs index 6925c60..f71ad0b 100644 --- a/Runtime/Pattern/Managers/StorageFile.cs +++ b/Runtime/Pattern/Managers/StorageFile.cs @@ -3,122 +3,6 @@ namespace RealMethod { - - public interface IStorage - { - void StorageCreated(UnityEngine.Object author); - void StorageLoaded(UnityEngine.Object author); - void StorageClear(); - } - - [Serializable] - public struct StorageFile where T : IStorage where J : SaveAsset - { - [SerializeField] - private bool UseCustomFile; - [SerializeField, ConditionalHide("UseCustomFile", true, false)] - private J _SaveFile; - public J file - { - get - { - if (_SaveFile == null) - { - if (!TryGetStorage(out cacheProvider)) - { - Debug.LogWarning($"{this}: Can't get Storage Interface Something is wrong in your 'CustomSavefile' or 'SaveFileClass'"); - return default; - } - } - return _SaveFile; - } - } - private T cacheProvider; - public T provider - { - get - { - if (cacheProvider == null) - { - if (!TryGetStorage(out cacheProvider)) - { - Debug.LogWarning($"{this}: Can't get Storage Interface Something is wrong in your 'CustomSavefile' or 'SaveFileClass'"); - return default; - } - } - return cacheProvider; - } - } - - - // Public Functions - public bool Load(UnityEngine.Object author) - { - ISaveSystem Savesystem = Game.Instance.gameObject.GetComponent(); - if (Savesystem == null) - Savesystem = Game.World.gameObject.GetComponent(); - - return Load(author, Savesystem); - } - public bool Load(UnityEngine.Object author, ISaveSystem manager) - { - if (manager == null) - { - Debug.LogWarning($"{this}: Initiate faield we need SaveManager"); - return false; - } - - if (manager.IsExist(file)) - { - manager.Load(file); - provider.StorageLoaded(author); - return true; - } - else - { - provider.StorageCreated(author); - return false; - } - } - public void Clear() - { - provider.StorageClear(); - } - - - // Private Functions - private bool TryGetStorage(out T _provider) - { - if (UseCustomFile) - { - if (_SaveFile is T customProvider) - { - _provider = customProvider; - return true; - } - else - { - Debug.LogWarning("Storage Interface not implemented in Customfile."); - UseCustomFile = false; - } - } - _SaveFile = ScriptableObject.CreateInstance(); - if (_SaveFile is T autoProvider) - { - _SaveFile.name = $"RM{typeof(J)}"; - _provider = autoProvider; - return true; - } - else - { - Debug.LogError($"Storage Interface not implemented in SaveFileType {typeof(J)}"); - _provider = default; - return false; - } - } - } - - public enum StorageMode { [DescriptionEnum("Instantiated uniquely for the owner(self).")] @@ -127,7 +11,6 @@ public enum StorageMode [DescriptionEnum("Shared instance obtained from an FileAsset, SaveSystem, or any other global provider.")] Shared = 1 } - [Serializable] public struct Storage where T : IFile { @@ -286,6 +169,10 @@ public void SetFileName(string NewName) { FileName = NewName; } + public void Clear() + { + Debug.LogWarning("Clear Dint implement! Sorry"); + } } } \ No newline at end of file diff --git a/Runtime/ReadySet/Components/UI/UI_GameSetting.cs b/Runtime/ReadySet/Components/UI/UI_GameSetting.cs index 6971a5d..712bb7f 100644 --- a/Runtime/ReadySet/Components/UI/UI_GameSetting.cs +++ b/Runtime/ReadySet/Components/UI/UI_GameSetting.cs @@ -7,7 +7,7 @@ namespace RealMethod { [Serializable] public class SelectableElement : Map { } - public interface ISettingStorage : IStorage + public interface ISettingStorage : IFile { bool IsSettingDirty { get; } void OnFileSynced(); @@ -25,10 +25,10 @@ public sealed class UI_GameSetting : MonoBehaviour private SelectableElement UIElements; [Header("Save")] [SerializeField] - private StorageFile Storage; + private Storage Storage; - public bool isFileDirty => Storage.provider.IsSettingDirty; - public SaveAsset file => Storage.file; + public bool isFileDirty => Storage.File.IsSettingDirty; + public ISettingStorage file => Storage.File; public bool isInSync { get; private set; } = false; // Unity Methods @@ -60,11 +60,11 @@ private void Awake() private void OnEnable() { // Sacan all variable in save file - Scaning.Scan(Storage.file); + Scaning.Scan(Storage.File); } private void Start() { - Storage.Load(this); + Storage.Refresh(); SyncUI(); } private void OnDisable() @@ -84,28 +84,28 @@ public void SyncFile(Selectable element) } foreach (FieldInfo field in Scaning.GetFields()) { - object value = field.GetValue(Storage.file); + object value = field.GetValue(Storage.File); switch (value) { case float f: if (element is Slider slide) { if (field.Name == label) - field.SetValue(Storage.file, slide.value); + field.SetValue(Storage.File, slide.value); } break; case int i: if (element is Dropdown dropdown) { if (field.Name == label) - field.SetValue(Storage.file, dropdown.value); + field.SetValue(Storage.File, dropdown.value); } break; case bool b: if (element is Toggle toggle) { if (field.Name == label) - field.SetValue(Storage.file, toggle.isOn); + field.SetValue(Storage.File, toggle.isOn); } break; default: @@ -113,7 +113,7 @@ public void SyncFile(Selectable element) break; } } - Storage.provider.OnFileSynced(); + Storage.File.OnFileSynced(); isInSync = false; } public void SyncFile() @@ -126,25 +126,25 @@ public void SyncFile() { if (element.Key == fileData[i].Name) { - object value = fileData[i].GetValue(Storage.file); + object value = fileData[i].GetValue(Storage.File); switch (value) { case float fl: if (element.Value is Slider slide) { - fileData[i].SetValue(Storage.file, slide.value); + fileData[i].SetValue(Storage.File, slide.value); } break; case int iin: if (element.Value is Dropdown dropdown) { - fileData[i].SetValue(Storage.file, dropdown.value); + fileData[i].SetValue(Storage.File, dropdown.value); } break; case bool bo: if (element.Value is Toggle toggle) { - fileData[i].SetValue(Storage.file, toggle.isOn); + fileData[i].SetValue(Storage.File, toggle.isOn); } break; default: @@ -154,7 +154,7 @@ public void SyncFile() } } } - Storage.provider.OnFileSynced(); + Storage.File.OnFileSynced(); isInSync = false; } [ContextMenu("Sync_UI")] @@ -168,7 +168,7 @@ public void SyncUI() { if (element.Key == fileData[i].Name) { - object value = fileData[i].GetValue(Storage.file); + object value = fileData[i].GetValue(Storage.File); switch (value) { case float fl: @@ -249,23 +249,23 @@ public abstract class SettingFile : SaveAsset, ISettingStorage // Implement ISettingStorage Interface public bool IsSettingDirty => IsDirty; - void IStorage.StorageCreated(UnityEngine.Object author) - { - SetupSettingData(); - } - void IStorage.StorageLoaded(UnityEngine.Object author) - { - ApplySettingData(); - } + // void IStorage.StorageCreated(UnityEngine.Object author) + // { + // SetupSettingData(); + // } + // void IStorage.StorageLoaded(UnityEngine.Object author) + // { + // ApplySettingData(); + // } void ISettingStorage.OnFileSynced() { IsDirty = true; ApplySettingData(); } - void IStorage.StorageClear() - { - OnResetSetting(); - } + // void IStorage.StorageClear() + // { + // OnResetSetting(); + // } // Protected Method protected sealed override void OnSaved() diff --git a/Runtime/Toolkit/Inventory/Inventory.cs b/Runtime/Toolkit/Inventory/Inventory.cs index f76d7fb..3ce6130 100644 --- a/Runtime/Toolkit/Inventory/Inventory.cs +++ b/Runtime/Toolkit/Inventory/Inventory.cs @@ -364,7 +364,7 @@ public T[] CopyItemsByClass() where T : IInventoryItem public void Clear() { Items.Clear(); - inventoryStorage.StorageClear(); + ////inventoryStorage.StorageClear(); } // Protected Functions @@ -462,17 +462,17 @@ public abstract class InventoryStorage : Inventory { [Header("Save")] [SerializeField] - private StorageFile storage; - public SaveAsset file => storage.file; + private Storage storage; + public IFile file => storage.File; // override Methods protected sealed override IInventoryStorage GetStorage() { - return storage.provider; + return storage.File; } protected sealed override bool LoadStorage() { - return storage.Load(this); + return storage.IsExist; } } diff --git a/Runtime/Toolkit/Inventory/InventoryInterface.cs b/Runtime/Toolkit/Inventory/InventoryInterface.cs index 2f12e63..a9e77ea 100644 --- a/Runtime/Toolkit/Inventory/InventoryInterface.cs +++ b/Runtime/Toolkit/Inventory/InventoryInterface.cs @@ -1,6 +1,6 @@ namespace RealMethod { - public interface IInventoryStorage : IStorage + public interface IInventoryStorage : IFile { InventoryItemProperty[] GetItems(); void CreateItem(InventoryItemProperty item); diff --git a/Runtime/Toolkit/Inventory/InventorySaveFile.cs b/Runtime/Toolkit/Inventory/InventorySaveFile.cs index 2e14a90..9b9c84d 100644 --- a/Runtime/Toolkit/Inventory/InventorySaveFile.cs +++ b/Runtime/Toolkit/Inventory/InventorySaveFile.cs @@ -43,12 +43,12 @@ protected override void OnLoaded() // Implement IInventorySave Interface - void IStorage.StorageCreated(Object author) - { - } - void IStorage.StorageLoaded(Object author) - { - } + // void IStorage.StorageCreated(Object author) + // { + // } + // void IStorage.StorageLoaded(Object author) + // { + // } void IInventoryStorage.CreateItem(InventoryItemProperty item) { ItemsName.Add(item.Name); @@ -106,12 +106,12 @@ InventoryItemProperty[] IInventoryStorage.GetItems() } return Result.ToArray(); } - void IStorage.StorageClear() - { - ItemsName.Clear(); - ItemsQuantity.Clear(); - ItemsCapacity.Clear(); - } + // void IStorage.StorageClear() + // { + // ItemsName.Clear(); + // ItemsQuantity.Clear(); + // ItemsCapacity.Clear(); + // } // Private Functions private int GetIndexItem(string name) diff --git a/Runtime/Toolkit/RPG/StatSystem/StatProfile.cs b/Runtime/Toolkit/RPG/StatSystem/StatProfile.cs index 012ae76..b8c9b1e 100644 --- a/Runtime/Toolkit/RPG/StatSystem/StatProfile.cs +++ b/Runtime/Toolkit/RPG/StatSystem/StatProfile.cs @@ -18,7 +18,7 @@ public interface IPrimitiveStatContainer : IPrimitiveStatContainer where T : void DeclineBuff(IStatModifier modifier, T identity); IStat GetStat(T identity); } - public interface IStatStorage : IStorage + public interface IStatStorage : IFile { void StoreStats(IStat[] stat); bool TryLoadStats(StatData data); @@ -75,16 +75,16 @@ public abstract class StatProfileStorage : StatProfile { [Header("Save")] [SerializeField] - private StorageFile storage; - public SaveAsset file => storage.file; + private Storage storage; + public IStatStorage file => storage.File; protected sealed override IStatStorage GetStorage() { - return storage.provider; + return storage.File; } protected sealed override bool LoadStorage() { - return storage.Load(this); + return storage.IsExist; } } public abstract class StatProfile : StatProfileStorage, IPrimitiveStatContainer where En : System.Enum where Sd : StatData diff --git a/Runtime/Toolkit/RPG/StatSystem/StatSaveFile.cs b/Runtime/Toolkit/RPG/StatSystem/StatSaveFile.cs index 0014d30..12f04c1 100644 --- a/Runtime/Toolkit/RPG/StatSystem/StatSaveFile.cs +++ b/Runtime/Toolkit/RPG/StatSystem/StatSaveFile.cs @@ -41,15 +41,15 @@ protected override void OnLoaded() } // Implement IStorage Interface - void IStorage.StorageCreated(Object author) - { - } - void IStorage.StorageLoaded(Object author) - { - } - void IStorage.StorageClear() - { - } + // void IStorage.StorageCreated(Object author) + // { + // } + // void IStorage.StorageLoaded(Object author) + // { + // } + // void IStorage.StorageClear() + // { + // } // Implement IStatStorage Interface void IStatStorage.StoreStats(IStat[] stats) { diff --git a/Runtime/Toolkit/Tutorial/TutorialInterfaces.cs b/Runtime/Toolkit/Tutorial/TutorialInterfaces.cs index aed740d..7d29e6e 100644 --- a/Runtime/Toolkit/Tutorial/TutorialInterfaces.cs +++ b/Runtime/Toolkit/Tutorial/TutorialInterfaces.cs @@ -13,7 +13,7 @@ public interface ITutorialMessage T GetClass() where T : UI_TutorialUnit; void Initiate(Object author, IWidget owner, TutorialConfig config); } - public interface ITutorialStorage : IStorage + public interface ITutorialStorage : IFile { void AddNewTutorial(TutorialConfig conf); bool RemoveTutorial(TutorialConfig conf); diff --git a/Runtime/Toolkit/Tutorial/TutorialSaveFile.cs b/Runtime/Toolkit/Tutorial/TutorialSaveFile.cs index 81dc037..0cee95f 100644 --- a/Runtime/Toolkit/Tutorial/TutorialSaveFile.cs +++ b/Runtime/Toolkit/Tutorial/TutorialSaveFile.cs @@ -32,14 +32,14 @@ protected override void OnLoaded() } // IMplement ITutorialStorage Interface - void IStorage.StorageCreated(Object author) - { + // void IStorage.StorageCreated(Object author) + // { - } - void IStorage.StorageLoaded(Object author) - { + // } + // void IStorage.StorageLoaded(Object author) + // { - } + // } void ITutorialStorage.AddNewTutorial(TutorialConfig conf) { TutorialMessage.Add(conf.NameID); @@ -52,10 +52,10 @@ bool ITutorialStorage.IsValidTutorial(TutorialConfig conf) { return TutorialMessage.Contains(conf.NameID); } - void IStorage.StorageClear() - { - TutorialMessage.Clear(); - } + // void IStorage.StorageClear() + // { + // TutorialMessage.Clear(); + // } protected override void Reset() diff --git a/Runtime/Toolkit/Tutorial/W_Tutorial.cs b/Runtime/Toolkit/Tutorial/W_Tutorial.cs index 823ad44..db96d10 100644 --- a/Runtime/Toolkit/Tutorial/W_Tutorial.cs +++ b/Runtime/Toolkit/Tutorial/W_Tutorial.cs @@ -83,7 +83,7 @@ public bool ResetMessage(TutorialConfig config) } public void Clear() { - tutorialStorage.StorageClear(); + ////tutorialStorage.StorageClear(); } // Private Functions @@ -107,16 +107,16 @@ public abstract class W_TutorialStorage : W_Tutorial { [Header("Save")] [SerializeField] - private StorageFile storage; - public SaveAsset file => storage.file; + private Storage storage; + public IFile file => storage.File; protected sealed override ITutorialStorage GetStorage() { - return storage.provider; + return storage.File; } protected sealed override bool LoadStorage() { - return storage.Load(this); + return storage.IsExist; } } } \ No newline at end of file diff --git a/Runtime/Toolkit/Upgrade/Upgrade.cs b/Runtime/Toolkit/Upgrade/Upgrade.cs index a653137..ef4a5e4 100644 --- a/Runtime/Toolkit/Upgrade/Upgrade.cs +++ b/Runtime/Toolkit/Upgrade/Upgrade.cs @@ -259,7 +259,7 @@ public void Clear() } } } - upgradeStorage.StorageClear(); + //////upgradeStorage.StorageClear(); // Create AvailableItems AvailableItems = new List(Maps.Length); foreach (var conf in Maps) @@ -320,17 +320,17 @@ public abstract class UpgradeStorage : Upgrade { [Header("Save")] [SerializeField] - private StorageFile storage; - public SaveAsset file => storage.file; + private Storage storage; + public IFile file => storage.File; // override Methods protected sealed override IUpgradeStorage GetStorage() { - return storage.provider; + return storage.File; } protected sealed override bool LoadStorage() { - return storage.Load(this); + return storage.IsExist; } } diff --git a/Runtime/Toolkit/Upgrade/UpgradeInterface.cs b/Runtime/Toolkit/Upgrade/UpgradeInterface.cs index 621d30e..3580f8e 100644 --- a/Runtime/Toolkit/Upgrade/UpgradeInterface.cs +++ b/Runtime/Toolkit/Upgrade/UpgradeInterface.cs @@ -28,7 +28,7 @@ public interface IUpgradeConfig IUpgradeItem GetStartItem(); } - public interface IUpgradeStorage : IStorage + public interface IUpgradeStorage : IFile { void UnlockItem(IUpgradeItem item); void LockItem(IUpgradeItem item); diff --git a/Runtime/Toolkit/Upgrade/UpgradeSaveFile.cs b/Runtime/Toolkit/Upgrade/UpgradeSaveFile.cs index dea5595..fd728d5 100644 --- a/Runtime/Toolkit/Upgrade/UpgradeSaveFile.cs +++ b/Runtime/Toolkit/Upgrade/UpgradeSaveFile.cs @@ -37,21 +37,21 @@ protected override void OnLoaded() // Implement IUpgradeStorage Interface - void IStorage.StorageCreated(Object author) - { - if (author is Upgrade upgrator) - { - UnlockItems = new List(upgrator.ItemCount); - AvailableItems = new List(); - } - else - { - Debug.LogWarning($"{this} Storage Should create by Upgrade Class"); - } - } - void IStorage.StorageLoaded(Object author) - { - } + // void IStorage.StorageCreated(Object author) + // { + // if (author is Upgrade upgrator) + // { + // UnlockItems = new List(upgrator.ItemCount); + // AvailableItems = new List(); + // } + // else + // { + // Debug.LogWarning($"{this} Storage Should create by Upgrade Class"); + // } + // } + // void IStorage.StorageLoaded(Object author) + // { + // } void IUpgradeStorage.UnlockItem(IUpgradeItem item) { UnlockItems.Add(item.Label); @@ -76,19 +76,19 @@ string[] IUpgradeStorage.GetUnlockItems() { return UnlockItems.ToArray(); } - void IStorage.StorageClear() - { - if (UnlockItems != null) - UnlockItems.Clear(); - if (UnlockItems != null) - AvailableItems.Clear(); - } + // void IStorage.StorageClear() + // { + // if (UnlockItems != null) + // UnlockItems.Clear(); + // if (UnlockItems != null) + // AvailableItems.Clear(); + // } protected override void Reset() { base.Reset(); - ((IStorage)this).StorageClear(); + //((IFile)this).StorageClear(); } From 6a6f806cbc8cfacb64d53cd5b95b85d36051ae39 Mon Sep 17 00:00:00 2001 From: Alijimpa Date: Thu, 23 Apr 2026 22:55:01 +0330 Subject: [PATCH 133/204] Rename IFile Properties --- .../Pattern/Inspectors/SaveManagerEditor.cs | 2 +- Runtime/Core/Definitions/Save.cs | 8 +-- .../SharedScripts/Structs/Storage.cs} | 4 +- .../SharedScripts/Structs/Storage.cs.meta} | 0 Runtime/Pattern/Managers/SaveManager.cs | 62 +++++++++---------- Tests/FileManager.cs | 6 +- 6 files changed, 41 insertions(+), 41 deletions(-) rename Runtime/{Pattern/Managers/StorageFile.cs => Library/SharedScripts/Structs/Storage.cs} (97%) rename Runtime/{Pattern/Managers/StorageFile.cs.meta => Library/SharedScripts/Structs/Storage.cs.meta} (100%) diff --git a/Editor/Pattern/Inspectors/SaveManagerEditor.cs b/Editor/Pattern/Inspectors/SaveManagerEditor.cs index 9f46dcc..1840189 100644 --- a/Editor/Pattern/Inspectors/SaveManagerEditor.cs +++ b/Editor/Pattern/Inspectors/SaveManagerEditor.cs @@ -26,7 +26,7 @@ public override void OnInspectorGUI() { for (int i = 0; i < files.Length; i++) { - EditorGUILayout.LabelField($"{i}.[{files[i].Key}]: {files[i].GetObject().GetType()}"); + EditorGUILayout.LabelField($"{i}.[{files[i].FileName}]: {files[i].FileObject.GetType()}"); } } EditorGUILayout.Space(); diff --git a/Runtime/Core/Definitions/Save.cs b/Runtime/Core/Definitions/Save.cs index ddb40df..ffef276 100644 --- a/Runtime/Core/Definitions/Save.cs +++ b/Runtime/Core/Definitions/Save.cs @@ -6,8 +6,8 @@ namespace RealMethod public interface IFile : IIdentifier { - string Key { get; } - object GetObject(); + string FileName { get; } + object FileObject { get; } } @@ -82,8 +82,8 @@ public interface ISaveFile : IFile, ISave public abstract class SaveAsset : UniqueAsset, ISaveFile { // Implement IFile Interface - string IFile.Key => name; - object IFile.GetObject() => this; + string IFile.FileName => name; + object IFile.FileObject => this; // Implement ISave Interface void ISave.OnLoaded() { diff --git a/Runtime/Pattern/Managers/StorageFile.cs b/Runtime/Library/SharedScripts/Structs/Storage.cs similarity index 97% rename from Runtime/Pattern/Managers/StorageFile.cs rename to Runtime/Library/SharedScripts/Structs/Storage.cs index f71ad0b..57037bd 100644 --- a/Runtime/Pattern/Managers/StorageFile.cs +++ b/Runtime/Library/SharedScripts/Structs/Storage.cs @@ -97,14 +97,14 @@ public void Refresh() _mergeFile = saveSystem.MainSaveFile; if (_mergeFile != null) { - SelectedMergeFile = _mergeFile.GetObject().GetType().ToString(); + SelectedMergeFile = _mergeFile.FileObject.GetType().ToString(); if (_mergeFile is T provider) { _file = provider; } else { - Debug.LogError($"Your MergeFile({_mergeFile.GetObject().GetType()}) Should implement {typeof(T)} interface"); + Debug.LogError($"Your MergeFile({_mergeFile.FileObject.GetType()}) Should implement {typeof(T)} interface"); return; } } diff --git a/Runtime/Pattern/Managers/StorageFile.cs.meta b/Runtime/Library/SharedScripts/Structs/Storage.cs.meta similarity index 100% rename from Runtime/Pattern/Managers/StorageFile.cs.meta rename to Runtime/Library/SharedScripts/Structs/Storage.cs.meta diff --git a/Runtime/Pattern/Managers/SaveManager.cs b/Runtime/Pattern/Managers/SaveManager.cs index 42550f5..d49d71b 100644 --- a/Runtime/Pattern/Managers/SaveManager.cs +++ b/Runtime/Pattern/Managers/SaveManager.cs @@ -140,10 +140,10 @@ public void Save(IFile file) Debug.LogError(ex); return; } - file.GetObject().InvokeSaveEvent(); + file.FileObject.InvokeSaveEvent(); OnSaved?.Invoke(file); #if UNITY_EDITOR || DEVELOPMENT_BUILD - WriteLog($"Save({GetMethod(file).Format}) Class({file.GetObject().GetType()})"); + WriteLog($"Save({GetMethod(file).Format}) Class({file.FileObject.GetType()})"); #endif } public void Load(IFile file) @@ -163,10 +163,10 @@ public void Load(IFile file) Debug.LogError(ex); return; } - file.GetObject().InvokeLoadEvent(); + file.FileObject.InvokeLoadEvent(); OnLoaded?.Invoke(file); #if UNITY_EDITOR || DEVELOPMENT_BUILD - WriteLog($"Load({GetMethod(file).Format}) Class({file.GetObject().GetType()})"); + WriteLog($"Load({GetMethod(file).Format}) Class({file.FileObject.GetType()})"); #endif } public void Delete(IFile file) @@ -185,7 +185,7 @@ public void Delete(IFile file) } OnDeleted?.Invoke(file); #if UNITY_EDITOR || DEVELOPMENT_BUILD - WriteLog($"Delete({GetMethod(file).Format}) Class({file.GetObject().GetType()})"); + WriteLog($"Delete({GetMethod(file).Format}) Class({file.FileObject.GetType()})"); #endif } [ContextMenu("Save")] @@ -209,10 +209,10 @@ void ISaveSystem.SaveAll() Debug.LogError(ex); return; } - MainSaveFile.GetObject().InvokeSaveEvent(); + MainSaveFile.FileObject.InvokeSaveEvent(); OnSaved?.Invoke(MainSaveFile); #if UNITY_EDITOR || DEVELOPMENT_BUILD - WriteLog($"Save[SingleFile]({GetMethod(MainSaveFile).Format}) Class({MainSaveFile.GetObject().GetType()})"); + WriteLog($"Save[SingleFile]({GetMethod(MainSaveFile).Format}) Class({MainSaveFile.FileObject.GetType()})"); #endif break; case SaveFileStructure.MultiFile: @@ -240,10 +240,10 @@ void ISaveSystem.SaveAll() Debug.LogError(ex); return; } - MainSaveFile.GetObject().InvokeSaveEvent(); + MainSaveFile.FileObject.InvokeSaveEvent(); OnSaved?.Invoke(MainSaveFile); #if UNITY_EDITOR || DEVELOPMENT_BUILD - WriteLog($"Save[MergedFile]({GetMethod(MainSaveFile).Format}) Class({MainSaveFile.GetObject().GetType()})"); + WriteLog($"Save[MergedFile]({GetMethod(MainSaveFile).Format}) Class({MainSaveFile.FileObject.GetType()})"); #endif break; } @@ -270,10 +270,10 @@ void ISaveSystem.LoadAll() Debug.LogError(ex); return; } - MainSaveFile.GetObject().InvokeLoadEvent(); + MainSaveFile.FileObject.InvokeLoadEvent(); OnLoaded?.Invoke(MainSaveFile); #if UNITY_EDITOR || DEVELOPMENT_BUILD - WriteLog($"Load({GetMethod(MainSaveFile).Format}) Class({MainSaveFile.GetObject().GetType()})"); + WriteLog($"Load({GetMethod(MainSaveFile).Format}) Class({MainSaveFile.FileObject.GetType()})"); #endif break; case SaveFileStructure.MultiFile: @@ -301,10 +301,10 @@ void ISaveSystem.LoadAll() Debug.LogError(ex); return; } - MainSaveFile.GetObject().InvokeLoadEvent(); + MainSaveFile.FileObject.InvokeLoadEvent(); OnLoaded?.Invoke(MainSaveFile); #if UNITY_EDITOR || DEVELOPMENT_BUILD - WriteLog($"Load({GetMethod(MainSaveFile).Format}) Class({MainSaveFile.GetObject().GetType()})"); + WriteLog($"Load({GetMethod(MainSaveFile).Format}) Class({MainSaveFile.FileObject.GetType()})"); #endif break; } @@ -344,7 +344,7 @@ protected virtual bool CanContinue(string message) } protected virtual bool Validate(IFile file) { - if (file == null && file.GetObject() != null) + if (file == null && file.FileObject != null) { Debug.LogError("File Does not valid"); return false; @@ -353,7 +353,7 @@ protected virtual bool Validate(IFile file) } protected virtual ISaveMethod GetMethod(IFile file) { - if (file != null && file.GetObject().HasImplementInterface(out ISaveMethod method)) + if (file != null && file.FileObject.HasImplementInterface(out ISaveMethod method)) { return method; } @@ -371,28 +371,28 @@ protected virtual ISaveMethod GetMethod(IFile file) } protected virtual void WriteToMergeFile(IFile file, BindingFlags fieldFlags, BindingFlags propertyFlags) { - object FileObject = file.GetObject(); + object FileObject = file.FileObject; IMergeFile mergefile = GetMainFile(); foreach (var field in FileObject.GetFields(fieldFlags)) { - mergefile.Write(file.Key, field.Name, field.FieldType, field.GetValue(FileObject)); + mergefile.Write(file.FileName, field.Name, field.FieldType, field.GetValue(FileObject)); } foreach (var propery in FileObject.GetProperties(propertyFlags)) { - mergefile.Write(file.Key, propery.Name, propery.PropertyType, propery.GetValue(FileObject)); + mergefile.Write(file.FileName, propery.Name, propery.PropertyType, propery.GetValue(FileObject)); } } protected virtual void ReadFromMergeFile(IFile file, BindingFlags fieldFlags, BindingFlags propertyFlags) { - object FileObject = file.GetObject(); + object FileObject = file.FileObject; IMergeFile mergefile = GetMainFile(); foreach (var field in FileObject.GetFields(fieldFlags)) { - field.SetValue(FileObject, mergefile.Read(file.Key, field.Name, field.FieldType)); + field.SetValue(FileObject, mergefile.Read(file.FileName, field.Name, field.FieldType)); } foreach (var propery in FileObject.GetProperties(propertyFlags)) { - propery.SetValue(FileObject, mergefile.Read(file.Key, propery.Name, propery.PropertyType)); + propery.SetValue(FileObject, mergefile.Read(file.FileName, propery.Name, propery.PropertyType)); } } @@ -460,7 +460,7 @@ protected override bool IsExistFile(IFile file, ISaveMethod Method) case SaveFormat.TEXT: return File.Exists(GetPath(file, Method)); case SaveFormat.PlayerPrefs: - return PlayerPrefs.HasKey(file.Key); + return PlayerPrefs.HasKey(file.FileName); case SaveFormat.Custom: return CustomSavefile(file, Method, SaveState.IsExist); default: @@ -470,14 +470,14 @@ protected override bool IsExistFile(IFile file, ISaveMethod Method) } protected override void OnSave(IFile file, ISaveMethod Method) { - object fileObject = file.GetObject(); + object fileObject = file.FileObject; switch (Method.Format) { case SaveFormat.None: if (fileObject is not ISave) { - Debug.LogError($"Your file({fileObject}) with name({file.Key}) should implement ISave Interface"); + Debug.LogError($"Your file({fileObject}) with name({file.FileName}) should implement ISave Interface"); } break; case SaveFormat.Binary: @@ -491,7 +491,7 @@ protected override void OnSave(IFile file, ISaveMethod Method) } catch (System.Exception e) { - Debug.LogError($"Failed to serialize {file.Key} to {GetPath(file, Method)}: {e}"); + Debug.LogError($"Failed to serialize {file.FileName} to {GetPath(file, Method)}: {e}"); return; } } @@ -533,7 +533,7 @@ protected override void OnSave(IFile file, ISaveMethod Method) { Set_PlayerPrefsInfo(property, fileObject); } - PlayerPrefs.SetString(file.Key, System.DateTime.Now.ToString()); + PlayerPrefs.SetString(file.FileName, System.DateTime.Now.ToString()); PlayerPrefs.Save(); break; case SaveFormat.Custom: @@ -546,14 +546,14 @@ protected override void OnSave(IFile file, ISaveMethod Method) } protected override void OnLoad(IFile file, ISaveMethod Method) { - object fileObject = file.GetObject(); + object fileObject = file.FileObject; switch (Method.Format) { case SaveFormat.None: if (fileObject is not ISave) { - Debug.LogError($"Your file({fileObject}) with name({file.Key}) should implement ISave Interface"); + Debug.LogError($"Your file({fileObject}) with name({file.FileName}) should implement ISave Interface"); } break; case SaveFormat.Binary: @@ -679,7 +679,7 @@ protected override void OnLoad(IFile file, ISaveMethod Method) } protected override void OnDelete(IFile file, ISaveMethod Method) { - object fileObject = file.GetObject(); + object fileObject = file.FileObject; switch (Method.Format) { @@ -722,7 +722,7 @@ protected override void OnDelete(IFile file, ISaveMethod Method) // Methods protected virtual string GetPath(IFile file, ISaveMethod method) { - string filename = file.Key; + string filename = file.FileName; string filetype = GetFileType(method); if (CustomPath) @@ -1111,7 +1111,7 @@ public override bool AddFile(IFile file) if (FileList.Contains(file))// reference comparison { - WriteLog($"File({file.Key}) already added"); + WriteLog($"File({file.FileName}) already added"); return false; } diff --git a/Tests/FileManager.cs b/Tests/FileManager.cs index aaeedea..adb9f80 100644 --- a/Tests/FileManager.cs +++ b/Tests/FileManager.cs @@ -50,13 +50,13 @@ public bool AddFile(IFile file) } else { - Debug.LogWarning($"Can't Add file with name: {file.Key}"); + Debug.LogWarning($"Can't Add file with name: {file.FileName}"); return false; } } else { - Debug.LogWarning($"There is a file with this name: {file.Key}"); + Debug.LogWarning($"There is a file with this name: {file.FileName}"); return false; } } @@ -70,7 +70,7 @@ public bool RemoveFile(IFile file) } else { - Debug.LogWarning($"Can't find any file with this name: {file.Key}"); + Debug.LogWarning($"Can't find any file with this name: {file.FileName}"); return false; } } From 6f87cfb8a7a8b18a2c8c737bedff4beec004e959 Mon Sep 17 00:00:00 2001 From: Alijimpa Date: Thu, 23 Apr 2026 23:09:22 +0330 Subject: [PATCH 134/204] REfine some drawer for softtype and SaveManager --- Editor/Core/Drawers/SoftTypeDrawer.cs | 10 +++++++-- .../Pattern/Inspectors/SaveManagerEditor.cs | 22 ++++++++++--------- Runtime/Pattern/Managers/SaveManager.cs | 1 + Tests/FileManager.cs | 2 +- 4 files changed, 22 insertions(+), 13 deletions(-) diff --git a/Editor/Core/Drawers/SoftTypeDrawer.cs b/Editor/Core/Drawers/SoftTypeDrawer.cs index 1697f01..6108b67 100644 --- a/Editor/Core/Drawers/SoftTypeDrawer.cs +++ b/Editor/Core/Drawers/SoftTypeDrawer.cs @@ -19,9 +19,15 @@ public override void OnGUI(Rect position, SerializedProperty property, GUIConten if (displayNames == null) { Initialize(typeProp); - typeProp.stringValue = typeNames[currentIndex]; + if (displayNames.Length > 0) + typeProp.stringValue = typeNames[currentIndex]; + } + + if (displayNames.Length == 0) + { + EditorGUI.LabelField(position, label.text, "No class found"); + return; } - int newIndex = EditorGUI.Popup(position, label.text, currentIndex, displayNames); diff --git a/Editor/Pattern/Inspectors/SaveManagerEditor.cs b/Editor/Pattern/Inspectors/SaveManagerEditor.cs index 1840189..d73bfd8 100644 --- a/Editor/Pattern/Inspectors/SaveManagerEditor.cs +++ b/Editor/Pattern/Inspectors/SaveManagerEditor.cs @@ -17,22 +17,24 @@ private void OnEnable() public override void OnInspectorGUI() { base.OnInspectorGUI(); - EditorGUILayout.LabelField("", GUI.skin.horizontalSlider); - IsShowLoadedFile = EditorGUILayout.Foldout(IsShowLoadedFile, "Files", true, EditorStyles.foldoutHeader); - if (IsShowLoadedFile) + if (!Component.IsInSingleFile) { - IFile[] files = Component.GetAllFiles(); - if (Component != null) + EditorGUILayout.LabelField("", GUI.skin.horizontalSlider); + IsShowLoadedFile = EditorGUILayout.Foldout(IsShowLoadedFile, "Files", true, EditorStyles.foldoutHeader); + if (IsShowLoadedFile) { - for (int i = 0; i < files.Length; i++) + IFile[] files = Component.GetAllFiles(); + if (Component != null) { - EditorGUILayout.LabelField($"{i}.[{files[i].FileName}]: {files[i].FileObject.GetType()}"); + for (int i = 0; i < files.Length; i++) + { + EditorGUILayout.LabelField($"{i}.[{files[i].FileName}]: {files[i].FileObject.GetType()}"); + } } + EditorGUILayout.Space(); + EditorGUILayout.LabelField($"Total: {files.Length}"); } - EditorGUILayout.Space(); - EditorGUILayout.LabelField($"Total: {files.Length}"); } - } diff --git a/Runtime/Pattern/Managers/SaveManager.cs b/Runtime/Pattern/Managers/SaveManager.cs index d49d71b..25e10b5 100644 --- a/Runtime/Pattern/Managers/SaveManager.cs +++ b/Runtime/Pattern/Managers/SaveManager.cs @@ -56,6 +56,7 @@ public abstract class SaveManager : MonoBehaviour, IGameManager, ISaveSystem private BindingFlags MergedFieldFlags = BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic; [SerializeField, ConditionalShowByEnum("Mode", SaveFileStructure.MergedFile)] private BindingFlags MergedPropertieFlags = BindingFlags.Default; + public bool IsInSingleFile => Mode == SaveFileStructure.SingleFile; // Actions public event System.Action OnLoaded; public event System.Action OnSaved; diff --git a/Tests/FileManager.cs b/Tests/FileManager.cs index adb9f80..ac0d214 100644 --- a/Tests/FileManager.cs +++ b/Tests/FileManager.cs @@ -90,7 +90,7 @@ protected virtual BindingFlags GetFlagSetting() } protected virtual FileData CreateFileData(IFile file) { - return new FileData(file.GetObject(), GetFlagSetting()); + return new FileData(file.FileObject, GetFlagSetting()); } // Abstraction Methods From 40c5e17b4cc743154750cdc00933430a309b32a2 Mon Sep 17 00:00:00 2001 From: Alijimpa Date: Thu, 23 Apr 2026 23:11:55 +0330 Subject: [PATCH 135/204] Rename script file --- Runtime/Core/Definitions/Identifier.cs | 2 +- .../Definitions/{GameNameConstants.cs => RealMethodNames.cs} | 0 .../{GameNameConstants.cs.meta => RealMethodNames.cs.meta} | 0 3 files changed, 1 insertion(+), 1 deletion(-) rename Runtime/Core/Definitions/{GameNameConstants.cs => RealMethodNames.cs} (100%) rename Runtime/Core/Definitions/{GameNameConstants.cs.meta => RealMethodNames.cs.meta} (100%) diff --git a/Runtime/Core/Definitions/Identifier.cs b/Runtime/Core/Definitions/Identifier.cs index 7684999..601c30c 100644 --- a/Runtime/Core/Definitions/Identifier.cs +++ b/Runtime/Core/Definitions/Identifier.cs @@ -2,6 +2,6 @@ namespace RealMethod { public interface IIdentifier { - Name16 NameID { get; } + //Name16 NameID { get; } } } \ No newline at end of file diff --git a/Runtime/Core/Definitions/GameNameConstants.cs b/Runtime/Core/Definitions/RealMethodNames.cs similarity index 100% rename from Runtime/Core/Definitions/GameNameConstants.cs rename to Runtime/Core/Definitions/RealMethodNames.cs diff --git a/Runtime/Core/Definitions/GameNameConstants.cs.meta b/Runtime/Core/Definitions/RealMethodNames.cs.meta similarity index 100% rename from Runtime/Core/Definitions/GameNameConstants.cs.meta rename to Runtime/Core/Definitions/RealMethodNames.cs.meta From d62c9469afe02654278d5bb45c4db50076c10054 Mon Sep 17 00:00:00 2001 From: Alijimpa Date: Sat, 25 Apr 2026 17:41:59 +0330 Subject: [PATCH 136/204] Implement Draw Pattern in game --- Runtime/Core/Architecture/Game.cs | 86 ++++++++++++++++++++++++++- Runtime/Core/Definitions/Draw.cs | 24 ++++++++ Runtime/Core/Definitions/Draw.cs.meta | 2 + Runtime/Core/Definitions/Task.cs | 11 ++++ Runtime/Core/Definitions/Task.cs.meta | 2 + 5 files changed, 124 insertions(+), 1 deletion(-) create mode 100644 Runtime/Core/Definitions/Draw.cs create mode 100644 Runtime/Core/Definitions/Draw.cs.meta create mode 100644 Runtime/Core/Definitions/Task.cs create mode 100644 Runtime/Core/Definitions/Task.cs.meta diff --git a/Runtime/Core/Architecture/Game.cs b/Runtime/Core/Architecture/Game.cs index 8c5f177..b7cbfab 100644 --- a/Runtime/Core/Architecture/Game.cs +++ b/Runtime/Core/Architecture/Game.cs @@ -181,7 +181,6 @@ public ISaveSystem SaveSystem - /// /// Initializes the game singleton and core systems on subsystem registration. /// This sets up the , game , @@ -369,6 +368,8 @@ private static void RuntimeAfterSceneLoad() } + + /// /// Attempts to invoke /// @@ -1015,6 +1016,36 @@ public static void Assert(bool condition, string message, UnityEngine.Object con { Debug.Assert(condition, message, context); } + /// + /// Adds a new draw task to the rendering queue. + /// + /// The draw task to add. Ignored if null. + [System.Diagnostics.Conditional("UNITY_EDITOR")] + [System.Diagnostics.Conditional("DEVELOPMENT_BUILD")] + [HideInCallstack] + public static void Draw(IDrawTask element) + { + if (element != null) + { + Instance.DrawTasks.Add(element); + element.Active(); + } + } + /// + /// Removes the specified draw task from the rendering queue. + /// + /// The draw task to remove. + [System.Diagnostics.Conditional("UNITY_EDITOR")] + [System.Diagnostics.Conditional("DEVELOPMENT_BUILD")] + [HideInCallstack] + public static void Erase(IDrawTask element) + { + Instance.DrawTasks.Remove(element); + element.Deactive(); + } + + + /// @@ -1051,6 +1082,8 @@ public IGameManager FindManager(string ObjectName) } + + /// /// Called after GameInstance Created befor GameBridge , GameConfig & Managers Initilized /// if you use custom PtojectSetttingAsset class you can use instances after loaded in game @@ -1098,6 +1131,7 @@ protected virtual void OnServiceCleand() + /// /// Callback invoked when a new is created or assigned. /// Updates the static reference and notifies all services. @@ -1189,6 +1223,56 @@ private void FixedUpdate() #endif +#if UNITY_EDITOR || DEVELOPMENT_BUILD + /// + /// A list containing all active draw tasks queued for rendering. + /// + private readonly List DrawTasks = new List(); + private void OnGUI() + { + for (int i = 0; i < DrawTasks.Count; i++) + { + IDrawTask task = DrawTasks[i]; + + if (task == null || task.IsExpired()) + { + if (task != null) + task.Deactive(); + DrawTasks.RemoveAt(i); + continue; + } + + if (task.GetDrawMode() != DrawMode.GUI) + continue; + + if (task.CanDraw(i)) + task.Draw(i); + } + } + private void OnDrawGizmos() + { + for (int i = 0; i < DrawTasks.Count; i++) + { + IDrawTask task = DrawTasks[i]; + + if (task == null || task.IsExpired()) + { + if (task != null) + task.Deactive(); + DrawTasks.RemoveAt(i); + continue; + } + + if (task.GetDrawMode() != DrawMode.Gizmo) + continue; + + if (task.CanDraw(i)) + task.Draw(i); + } + } +#endif + + /// /// Called once when game opend in currect platform diff --git a/Runtime/Core/Definitions/Draw.cs b/Runtime/Core/Definitions/Draw.cs new file mode 100644 index 0000000..f81f98d --- /dev/null +++ b/Runtime/Core/Definitions/Draw.cs @@ -0,0 +1,24 @@ + +namespace RealMethod +{ + public enum DrawMode + { + GUI, + Gizmo, + } + + public interface IDraw : IIdentifier + { + bool CanDraw(int Index); + void Draw(int Index); + } + + public interface IDrawTask : IDraw, ITask + { + int Priority { get; } + bool IsExpired(); + DrawMode GetDrawMode(); + } + + +} \ No newline at end of file diff --git a/Runtime/Core/Definitions/Draw.cs.meta b/Runtime/Core/Definitions/Draw.cs.meta new file mode 100644 index 0000000..8656040 --- /dev/null +++ b/Runtime/Core/Definitions/Draw.cs.meta @@ -0,0 +1,2 @@ +fileFormatVersion: 2 +guid: 4dfe7e9297074ca49ab4d715a4a69902 \ No newline at end of file diff --git a/Runtime/Core/Definitions/Task.cs b/Runtime/Core/Definitions/Task.cs new file mode 100644 index 0000000..20c9c97 --- /dev/null +++ b/Runtime/Core/Definitions/Task.cs @@ -0,0 +1,11 @@ +using System; + +namespace RealMethod +{ + public interface ITask + { + void Active(); + void Deactive(); + } + +} \ No newline at end of file diff --git a/Runtime/Core/Definitions/Task.cs.meta b/Runtime/Core/Definitions/Task.cs.meta new file mode 100644 index 0000000..46c96a9 --- /dev/null +++ b/Runtime/Core/Definitions/Task.cs.meta @@ -0,0 +1,2 @@ +fileFormatVersion: 2 +guid: e9488560ad3e25c428377b069afeaa1a \ No newline at end of file From 6a0ff61ede8e33e26ca8313386141bccf1749db2 Mon Sep 17 00:00:00 2001 From: Alijimpa Date: Sat, 25 Apr 2026 17:42:30 +0330 Subject: [PATCH 137/204] Refine InvokeSpawnEvent --- Runtime/Library/Extension/Component.cs | 58 ------ Runtime/Library/Extension/Component.cs.meta | 2 - Runtime/Library/Extension/GameObject.cs | 66 ------- Runtime/Library/Extension/Object.cs | 174 ++++++++++++++++++ Runtime/Library/Extension/ScriptableObject.cs | 60 ------ 5 files changed, 174 insertions(+), 186 deletions(-) delete mode 100644 Runtime/Library/Extension/Component.cs delete mode 100644 Runtime/Library/Extension/Component.cs.meta diff --git a/Runtime/Library/Extension/Component.cs b/Runtime/Library/Extension/Component.cs deleted file mode 100644 index b7e5bea..0000000 --- a/Runtime/Library/Extension/Component.cs +++ /dev/null @@ -1,58 +0,0 @@ -using UnityEngine; - -namespace RealMethod -{ - public static class Component_Extension - { - public static void InvokeSpawnEvent(this Component owner, Object spawner = null, SendMessageOptions option = SendMessageOptions.RequireReceiver) - { - if (spawner != null) - { - if (owner is ISpawnWithAuthor provider) - { - provider.OnSpawn(spawner); - } - else - { - owner.SendMessage(MessageNames.Spawn, spawner, option); - } - } - else - { - if (owner is ISpawn provider) - { - provider.OnSpawn(); - } - else - { - owner.SendMessage(MessageNames.Spawn, option); - } - } - } - public static void InvokeDespawnEvent(this Component owner, Object despawner = null, SendMessageOptions option = SendMessageOptions.RequireReceiver) - { - if (despawner != null) - { - if (owner is IDespawnWithAuthor provider) - { - provider.OnDespawn(despawner); - } - else - { - owner.SendMessage(MessageNames.Despawn, despawner, option); - } - } - else - { - if (owner is IDespawn provider) - { - provider.OnDespawn(); - } - else - { - owner.SendMessage(MessageNames.Despawn, option); - } - } - } - } -} \ No newline at end of file diff --git a/Runtime/Library/Extension/Component.cs.meta b/Runtime/Library/Extension/Component.cs.meta deleted file mode 100644 index a23013d..0000000 --- a/Runtime/Library/Extension/Component.cs.meta +++ /dev/null @@ -1,2 +0,0 @@ -fileFormatVersion: 2 -guid: 81728d66b32736d438d7ed5ae52dade5 \ No newline at end of file diff --git a/Runtime/Library/Extension/GameObject.cs b/Runtime/Library/Extension/GameObject.cs index 4cbd33e..48ca5e9 100644 --- a/Runtime/Library/Extension/GameObject.cs +++ b/Runtime/Library/Extension/GameObject.cs @@ -93,72 +93,6 @@ public static void Detach(this GameObject target, GameObject parent) target.SendMessage(MessageNames.Detach, SendMessageOptions.DontRequireReceiver); } /// - /// Sends an "OnSpawn" message to the owner GameObject. - /// - /// The GameObject to send the message to. - /// The object that triggered the spawn event (passed as parameter to the message). - /// Specifies whether the message must be received, or if it is optional. - public static void InvokeSpawnEvent(this GameObject owner, Object spawner = null, SendMessageOptions option = SendMessageOptions.RequireReceiver) - { - if (spawner != null) - { - ISpawnWithAuthor provider = owner.GetComponent(); - if (provider != null) - { - provider.OnSpawn(spawner); - } - else - { - owner.SendMessage(MessageNames.Spawn, spawner, option); - } - } - else - { - ISpawn provider = owner.GetComponent(); - if (provider != null) - { - provider.OnSpawn(); - } - else - { - owner.SendMessage(MessageNames.Spawn, option); - } - } - } - /// - /// Sends an "OnDespawn" message to the owner GameObject. - /// - /// The GameObject to send the message to. - /// The object that triggered the despawn event (passed as parameter to the message). - /// Specifies whether the message must be received, or if it is optional. - public static void InvokeDespawnEvent(this GameObject owner, Object despawner = null, SendMessageOptions option = SendMessageOptions.RequireReceiver) - { - if (despawner != null) - { - IDespawnWithAuthor provider = owner.GetComponent(); - if (provider != null) - { - provider.OnDespawn(despawner); - } - else - { - owner.SendMessage(MessageNames.Despawn, despawner, option); - } - } - else - { - IDespawn provider = owner.GetComponent(); - if (provider != null) - { - provider.OnDespawn(); - } - else - { - owner.SendMessage(MessageNames.Despawn, option); - } - } - } - /// /// Adds a new component of type TComponent to the GameObject and initializes it without arguments. /// /// The type of the component to add, must inherit from MonoBehaviour and IInitializable. diff --git a/Runtime/Library/Extension/Object.cs b/Runtime/Library/Extension/Object.cs index 7924de6..ae821f5 100644 --- a/Runtime/Library/Extension/Object.cs +++ b/Runtime/Library/Extension/Object.cs @@ -17,6 +17,180 @@ public static bool NullChecker(this object Obj, string Name) return false; } } + /// + /// Sends an "OnSpawn" message to the owner object. + /// Auto detect type for MonoBehaviour,GameObject,PrimitiveAsset and object + /// + /// The GameObject to send the message to. + /// The object that triggered the spawn event (passed as parameter to the message). + /// Specifies whether the message must be received, or if it is optional. + public static void InvokeSpawnEvent(this object owner, Object spawner = null, SendMessageOptions option = SendMessageOptions.DontRequireReceiver) + { + if (owner is MonoBehaviour mono) + { + if (spawner != null) + { + if (mono is ISpawnWithAuthor provider) + { + provider.OnSpawn(spawner); + } + else + { + mono.SendMessage(MessageNames.Spawn, spawner, option); + } + } + else + { + if (mono is ISpawn provider) + { + provider.OnSpawn(); + } + else + { + mono.SendMessage(MessageNames.Spawn, option); + } + } + } + else if (owner is GameObject gameobject) + { + if (spawner != null) + { + ISpawnWithAuthor provider = gameobject.GetComponent(); + if (provider != null) + { + provider.OnSpawn(spawner); + } + else + { + gameobject.SendMessage(MessageNames.Spawn, spawner, option); + } + } + else + { + ISpawn provider = gameobject.GetComponent(); + if (provider != null) + { + provider.OnSpawn(); + } + else + { + gameobject.SendMessage(MessageNames.Spawn, option); + } + } + } + else + { + if (spawner != null) + { + if (owner is ISpawnWithAuthor provider) + { + provider.OnSpawn(spawner); + } + else + { + owner.SendMessage(MessageNames.Spawn, spawner, option); + } + } + else + { + if (owner is ISpawn provider) + { + provider.OnSpawn(); + } + else + { + owner.SendMessage(MessageNames.Spawn, option); + } + } + } + } + /// + /// Sends an "OnDespawn" message to the owner object. + /// Auto detect type for MonoBehaviour,GameObject,PrimitiveAsset and object + /// + /// The GameObject to send the message to. + /// The object that triggered the despawn event (passed as parameter to the message). + /// Specifies whether the message must be received, or if it is optional. + public static void InvokeDespawnEvent(this object owner, Object despawner = null, SendMessageOptions option = SendMessageOptions.DontRequireReceiver) + { + if (owner is MonoBehaviour mono) + { + if (despawner != null) + { + if (mono is IDespawnWithAuthor provider) + { + provider.OnDespawn(despawner); + } + else + { + mono.SendMessage(MessageNames.Despawn, despawner, option); + } + } + else + { + if (mono is IDespawn provider) + { + provider.OnDespawn(); + } + else + { + mono.SendMessage(MessageNames.Despawn, option); + } + } + } + else if (owner is GameObject gameobject) + { + if (despawner != null) + { + IDespawnWithAuthor provider = gameobject.GetComponent(); + if (provider != null) + { + provider.OnDespawn(despawner); + } + else + { + gameobject.SendMessage(MessageNames.Despawn, despawner, option); + } + } + else + { + IDespawn provider = gameobject.GetComponent(); + if (provider != null) + { + provider.OnDespawn(); + } + else + { + gameobject.SendMessage(MessageNames.Despawn, option); + } + } + } + else + { + if (despawner != null) + { + if (owner is IDespawnWithAuthor provider) + { + provider.OnDespawn(despawner); + } + else + { + owner.SendMessage(MessageNames.Despawn, despawner, option); + } + } + else + { + if (owner is IDespawn provider) + { + provider.OnDespawn(); + } + else + { + owner.SendMessage(MessageNames.Despawn, option); + } + } + } + } public static void InvokeSaveEvent(this object obj, SendMessageOptions option = SendMessageOptions.RequireReceiver) { if (obj is ISave provider) diff --git a/Runtime/Library/Extension/ScriptableObject.cs b/Runtime/Library/Extension/ScriptableObject.cs index cfb213d..f6b3ebd 100644 --- a/Runtime/Library/Extension/ScriptableObject.cs +++ b/Runtime/Library/Extension/ScriptableObject.cs @@ -4,66 +4,6 @@ namespace RealMethod { public static class ScriptableObject_Extension { - /// - /// Sends an "OnSpawn" message to the owner GameObject. - /// - /// The GameObject to send the message to. - /// The object that triggered the spawn event (passed as parameter to the message). - public static void InvokeSpawnEvent(this ScriptableObject owner, Object spawner = null, SendMessageOptions option = SendMessageOptions.RequireReceiver) - { - if (spawner != null) - { - if (owner is ISpawnWithAuthor provider) - { - provider.OnSpawn(spawner); - } - else - { - owner.SendMessage(MessageNames.Spawn, spawner, option); - } - } - else - { - if (owner is ISpawn provider) - { - provider.OnSpawn(); - } - else - { - owner.SendMessage(MessageNames.Spawn, option); - } - } - } - /// - /// Sends an "OnDespawn" message to the owner GameObject. - /// - /// The GameObject to send the message to. - /// The object that triggered the despawn event (passed as parameter to the message). - public static void InvokeDespawnEvent(this ScriptableObject owner, Object despawner = null, SendMessageOptions option = SendMessageOptions.RequireReceiver) - { - if (despawner != null) - { - if (owner is IDespawnWithAuthor provider) - { - provider.OnDespawn(despawner); - } - else - { - owner.SendMessage(MessageNames.Despawn, despawner, option); - } - } - else - { - if (owner is IDespawn provider) - { - provider.OnDespawn(); - } - else - { - owner.SendMessage(MessageNames.Despawn, option); - } - } - } public static ScriptableObject Clone(this ScriptableObject so) { return ScriptableObject.Instantiate(so); From 5bb4513faaee5b00b6fd351ebef204f1192bc7cf Mon Sep 17 00:00:00 2001 From: Alijimpa Date: Sat, 25 Apr 2026 17:44:21 +0330 Subject: [PATCH 138/204] Refine Class for New Draw System --- Runtime/Library/Interfaces/Draw.cs | 12 --- Runtime/Library/Interfaces/Draw.cs.meta | 2 - Runtime/Pattern/Managers/TickManager.cs | 82 -------------------- Runtime/Pattern/Managers/TickManager.cs.meta | 2 - Runtime/ReadySet/Managers/DebugManager.cs | 38 +++++++-- Runtime/ReadySet/Managers/PrintManager.cs | 28 ++++--- 6 files changed, 50 insertions(+), 114 deletions(-) delete mode 100644 Runtime/Library/Interfaces/Draw.cs delete mode 100644 Runtime/Library/Interfaces/Draw.cs.meta delete mode 100644 Runtime/Pattern/Managers/TickManager.cs delete mode 100644 Runtime/Pattern/Managers/TickManager.cs.meta diff --git a/Runtime/Library/Interfaces/Draw.cs b/Runtime/Library/Interfaces/Draw.cs deleted file mode 100644 index 0aafd73..0000000 --- a/Runtime/Library/Interfaces/Draw.cs +++ /dev/null @@ -1,12 +0,0 @@ -using UnityEngine; - -namespace RealMethod -{ - public interface IDraw : IIdentifier - { - bool Start(IGameManager Manager); - bool CanDraw(); - void Draw(Vector2 Pivot, int Index); - void End(); - } -} \ No newline at end of file diff --git a/Runtime/Library/Interfaces/Draw.cs.meta b/Runtime/Library/Interfaces/Draw.cs.meta deleted file mode 100644 index 8656040..0000000 --- a/Runtime/Library/Interfaces/Draw.cs.meta +++ /dev/null @@ -1,2 +0,0 @@ -fileFormatVersion: 2 -guid: 4dfe7e9297074ca49ab4d715a4a69902 \ No newline at end of file diff --git a/Runtime/Pattern/Managers/TickManager.cs b/Runtime/Pattern/Managers/TickManager.cs deleted file mode 100644 index 5520c20..0000000 --- a/Runtime/Pattern/Managers/TickManager.cs +++ /dev/null @@ -1,82 +0,0 @@ -using System.Collections.Generic; -using UnityEngine; - -namespace RealMethod -{ - public abstract class TickManager : MonoBehaviour, IGameManager where T : ITick - { - [Header("Tick")] - [SerializeField] - private UpdateMethod updateMethod = UpdateMethod.Update; - [SerializeField] - private int baseCapacity = 10; - - protected List units { get; private set; } - public int Count => units != null ? units.Count : 0; - - // Implement IGameManager Interface - MonoBehaviour IGameManager.GetManagerClass() - { - return this; - } - void IGameManager.InitiateManager(bool AlwaysLoaded) - { - units = new List(baseCapacity); - InitiateManager(AlwaysLoaded); - } - void IGameManager.ResolveService(Service service, bool active) - { - InitiateService(service); - } - - // Unity Methods - private void LateUpdate() - { - if (updateMethod == UpdateMethod.LateUpdate) - { - CallUnits(); - } - } - private void Update() - { - if (updateMethod == UpdateMethod.Update) - { - CallUnits(); - } - } - private void FixedUpdate() - { - if (updateMethod == UpdateMethod.FixedUpdate) - { - CallUnits(); - } - } - - // Public Functions - public bool IsValid(T unit) - { - return units.Contains(unit); - } - public T[] GetAllUnits() - { - return units.ToArray(); - } - - // Private Functions - private void CallUnits() - { - float delta = Time.deltaTime; - for (int i = 0; i < units.Count; i++) - { - var unit = units[i]; - if (CheckUnit(unit)) - unit.Tick(delta); - } - } - - // Abstract Methods - protected abstract void InitiateManager(bool alwaysLoaded); - protected abstract void InitiateService(Service service); - protected abstract bool CheckUnit(T unit); - } -} \ No newline at end of file diff --git a/Runtime/Pattern/Managers/TickManager.cs.meta b/Runtime/Pattern/Managers/TickManager.cs.meta deleted file mode 100644 index 3d6c48f..0000000 --- a/Runtime/Pattern/Managers/TickManager.cs.meta +++ /dev/null @@ -1,2 +0,0 @@ -fileFormatVersion: 2 -guid: 87611a023127fcc4b90c043e9956d2d3 \ No newline at end of file diff --git a/Runtime/ReadySet/Managers/DebugManager.cs b/Runtime/ReadySet/Managers/DebugManager.cs index 355782b..e42ca00 100644 --- a/Runtime/ReadySet/Managers/DebugManager.cs +++ b/Runtime/ReadySet/Managers/DebugManager.cs @@ -10,8 +10,17 @@ public interface IButton : IIdentifier event Action OnPressed; } + + public interface IDrawWorkaround : IDraw + { + bool Start(IGameManager Manager); + bool CanDraw(); + void Draw(Vector2 Pivot, int Index); + void End(); + } + [System.Serializable] - public class ButtonData : IDraw, IButton + public class ButtonData : IDrawWorkaround, IButton { private DebugManager MyOwner; [SerializeField] @@ -31,7 +40,7 @@ public ButtonData(Name16 ButtonName, Action callback) // Implement IIdentifier Interface public Name16 NameID => MyName; // Implement IGUIDrawer Interface - bool IDraw.Start(IGameManager Manager) + bool IDrawWorkaround.Start(IGameManager Manager) { if (Manager.GetManagerClass() is DebugManager target) { @@ -44,11 +53,11 @@ bool IDraw.Start(IGameManager Manager) return false; } } - bool IDraw.CanDraw() + bool IDrawWorkaround.CanDraw() { return true; } - void IDraw.Draw(Vector2 Pivot, int Index) + void IDrawWorkaround.Draw(Vector2 Pivot, int Index) { if (GUI.Button(new Rect(Pivot.x + Offcet.x, (Pivot.y + Offcet.y) * Index, MyOwner.ButtonSize.x, MyOwner.ButtonSize.y), MyName)) { @@ -56,7 +65,7 @@ void IDraw.Draw(Vector2 Pivot, int Index) } } - void IDraw.End() + void IDrawWorkaround.End() { PressedEvent = null; } @@ -82,6 +91,21 @@ public void Update(Vector2 offcet) { Offcet = offcet; } + + public void Start(IGameManager Manager) + { + throw new NotImplementedException(); + } + + public bool CanDraw(int Index) + { + throw new NotImplementedException(); + } + + public void Draw(int Index) + { + throw new NotImplementedException(); + } } [AddComponentMenu("RealMethod/Manager/DebugManager")] @@ -110,14 +134,14 @@ public override void ResolveService(Service service, bool active) public IButton AddButton(Name16 ButtonName, Action Callback) { var Result = new ButtonData(ButtonName, Callback); - ((IDraw)Result).Start(this); + ((IDrawWorkaround)Result).Start(this); Add(Result); return Result; } public bool Remove(IButton button) { var result = Find(button); - ((IDraw)result).End(); + ((IDrawWorkaround)result).End(); return DrawList.Remove(result); } diff --git a/Runtime/ReadySet/Managers/PrintManager.cs b/Runtime/ReadySet/Managers/PrintManager.cs index ffa5fec..62056c4 100644 --- a/Runtime/ReadySet/Managers/PrintManager.cs +++ b/Runtime/ReadySet/Managers/PrintManager.cs @@ -11,8 +11,10 @@ public interface IPrint : IIdentifier void Update(Vector2 Offcet); } + + [Serializable] - public class LogData : IDraw, IPrint + public class LogData : IDrawWorkaround, IPrint { private PrintManager MyOwner; [SerializeField] @@ -43,7 +45,7 @@ public LogData(Vector2 offcet) // Implement IIdentifier Interface Name16 IIdentifier.NameID => GetHashCode().ToString(); // Implement IGUIDrawer Interface - bool IDraw.Start(IGameManager Manager) + bool IDrawWorkaround.Start(IGameManager Manager) { if (Manager.GetManagerClass() is PrintManager target) { @@ -57,13 +59,13 @@ bool IDraw.Start(IGameManager Manager) return false; } } - bool IDraw.CanDraw() + bool IDrawWorkaround.CanDraw() { if (IsStatic) return true; return !IsFinished; } - void IDraw.Draw(Vector2 Pivot, int Index) + void IDrawWorkaround.Draw(Vector2 Pivot, int Index) { int w = Screen.width * MySize; int h = Screen.height * MySize; @@ -77,7 +79,7 @@ void IDraw.Draw(Vector2 Pivot, int Index) style.normal.textColor = Color; GUI.Label(rect, MyMessage, style); } - void IDraw.End() + void IDrawWorkaround.End() { } @@ -132,8 +134,16 @@ private Color GetColor(LogType type) } } + public bool CanDraw(int Index) + { + throw new NotImplementedException(); + } - } + public void Draw(int Index) + { + throw new NotImplementedException(); + } + } [AddComponentMenu("RealMethod/Manager/PrintManager")] @@ -166,7 +176,7 @@ public void Print(string Message, LogType Type) public IPrint PrintStatic(Vector2 offcet) { var Result = new LogData(offcet); - ((IDraw)Result).Start(this); + ((IDrawWorkaround)Result).Start(this); StaticData.Add(Result); return Result; } @@ -177,7 +187,7 @@ public bool RemoveStatic(IPrint ptinter) { if (StaticData[i] == ID) { - ((IDraw)StaticData[i]).End(); + ((IDrawWorkaround)StaticData[i]).End(); StaticData.RemoveAt(i); return true; } @@ -195,7 +205,7 @@ protected override void PreDraw() base.PreDraw(); foreach (var item in StaticData) { - if (item is IDraw Drawer) + if (item is IDrawWorkaround Drawer) { Drawer.Draw(Pivot, 0); } From 499b5d6a5fe4fd7a45f698f2068add604b54221c Mon Sep 17 00:00:00 2001 From: Alijimpa Date: Sat, 25 Apr 2026 17:44:54 +0330 Subject: [PATCH 139/204] Refine Spawn&Despawn Service for New InvokeSpawnEvent --- Runtime/ReadySet/Services/DespawnService.cs | 33 +------ Runtime/ReadySet/Services/SpawanService.cs | 100 ++------------------ 2 files changed, 14 insertions(+), 119 deletions(-) diff --git a/Runtime/ReadySet/Services/DespawnService.cs b/Runtime/ReadySet/Services/DespawnService.cs index 154caa4..5e148b4 100644 --- a/Runtime/ReadySet/Services/DespawnService.cs +++ b/Runtime/ReadySet/Services/DespawnService.cs @@ -119,7 +119,7 @@ private static T GetManager() where T : MonoBehaviour } } - Debug.LogError($"{Ins}:Failed to spawn, Manager({typeof(T).Name}) is not available."); + Debug.LogError($"{Ins}:Failed to Despawn, Manager({typeof(T).Name}) is not available."); return null; } @@ -218,35 +218,12 @@ public static bool Asset(T target, Object despawner = null, bool debug = true // Task - public static bool Task(object TaskObj, Object author, bool debug = true) + public static bool Task(T task) where T : IHandle { - if (GetManager() == null) - { - if (debug) - Debug.LogWarning("TaskManager is not available."); - return false; - } - - if (TaskObj is ITask task) - { - if (GetManager().IsValid(task)) - { - GetManager().Remove(task, author); - return true; - } - else - { - if (debug) - Debug.LogWarning($"Task Not Found!"); - return false; - } - } - else - { - if (debug) - Debug.LogWarning($"Your Object should have {typeof(ITask)} Interfave"); + TaskManager manager = GetManager>(); + if (manager == null) return false; - } + return manager.Destroy(task); } // Enumerator diff --git a/Runtime/ReadySet/Services/SpawanService.cs b/Runtime/ReadySet/Services/SpawanService.cs index 853e75c..b41dc5d 100644 --- a/Runtime/ReadySet/Services/SpawanService.cs +++ b/Runtime/ReadySet/Services/SpawanService.cs @@ -298,22 +298,7 @@ public static T Clone(T original, Object spawner = null) where T : Object if (spawner != null) { var target = Object.Instantiate(original); - if (target is MonoBehaviour mono) - { - mono.InvokeSpawnEvent(spawner); - } - else if (target is GameObject obj) - { - obj.InvokeSpawnEvent(spawner); - } - else if (target is PrimitiveAsset asset) - { - asset.InvokeSpawnEvent(spawner); - } - else - { - Debug.LogWarning($"Spawn Event can only be send to MonoBehaviour or GameObject. Target type: {target.GetType()}"); - } + target.InvokeSpawnEvent(spawner); return target; } else @@ -326,22 +311,7 @@ public static T Clone(T original, Transform parent, Object spawner = null) wh if (spawner != null) { var target = Object.Instantiate(original, parent); - if (target is MonoBehaviour mono) - { - mono.InvokeSpawnEvent(spawner); - } - else if (target is GameObject obj) - { - obj.InvokeSpawnEvent(spawner); - } - else if (target is PrimitiveAsset asset) - { - asset.InvokeSpawnEvent(spawner); - } - else - { - Debug.LogWarning($"Spawn Event can only be send to MonoBehaviour or GameObject. Target type: {target.GetType()}"); - } + target.InvokeSpawnEvent(spawner); return target; } else @@ -354,22 +324,7 @@ public static T Clone(T original, Vector3 position, Quaternion rotation, Obje if (spawner != null) { var target = Object.Instantiate(original, position, rotation); - if (target is MonoBehaviour mono) - { - mono.InvokeSpawnEvent(spawner); - } - else if (target is GameObject obj) - { - obj.InvokeSpawnEvent(spawner); - } - else if (target is PrimitiveAsset asset) - { - asset.InvokeSpawnEvent(spawner); - } - else - { - Debug.LogWarning($"Spawn Event can only be send to MonoBehaviour or GameObject. Target type: {target.GetType()}"); - } + target.InvokeSpawnEvent(spawner); return target; } else @@ -382,22 +337,7 @@ public static T Clone(T original, Transform parent, bool worldPositionStays, if (spawner != null) { var target = Object.Instantiate(original, parent, worldPositionStays); - if (target is MonoBehaviour mono) - { - mono.InvokeSpawnEvent(spawner); - } - else if (target is GameObject obj) - { - obj.InvokeSpawnEvent(spawner); - } - else if (target is PrimitiveAsset asset) - { - asset.InvokeSpawnEvent(spawner); - } - else - { - Debug.LogWarning($"Spawn Event can only be send to MonoBehaviour or GameObject. Target type: {target.GetType()}"); - } + target.InvokeSpawnEvent(spawner); return target; } else @@ -722,34 +662,12 @@ public static PrimitiveAsset Asset(System.Type type, Object spawner = null) return target; } // Task - public static bool Task(object TaskObj, Object author) + public static T Task(F Task, bool AutoStart = false) where T : IHandle where F : class { - if (GetManager() != null) - { - if (TaskObj is ITask task) - { - if (!GetManager().IsValid(task)) - { - GetManager().Add(task, author); - return true; - } - else - { - Debug.LogWarning($"Task already is running"); - return false; - } - } - else - { - Debug.LogWarning($"Your Object should have {typeof(ITask)} Interface"); - return false; - } - } - else - { - Debug.LogWarning($" {Ins}: TaskManager is not available."); - return false; - } + TaskManager manager = GetManager>(); + if (manager == null) + return default; + return manager.Create(Task, AutoStart); } // Enumerator From cb8ad8be46de39b8609aec43468cfc0b07d3536a Mon Sep 17 00:00:00 2001 From: Alijimpa Date: Sat, 25 Apr 2026 17:46:05 +0330 Subject: [PATCH 140/204] Implement New TaskManager --- .../Pattern/Inspectors/TaskManagerEditor.cs | 67 +--- Editor/ReadySet/Inspectors.meta | 8 + .../ReadySet/Inspectors/MotionAssetEditor.cs | 46 +++ .../Inspectors/MotionAssetEditor.cs.meta | 2 + Runtime/Pattern/Managers/TaskManager.cs | 168 +++++++++ Runtime/Pattern/Managers/TaskManager.cs.meta | 2 + Runtime/ReadySet/Managers/ActionManager.cs | 62 ++++ ...kManager.cs.meta => ActionManager.cs.meta} | 0 Runtime/ReadySet/Managers/MotionManager.cs | 271 ++++++++++++--- Runtime/ReadySet/Managers/TaskManager.cs | 327 ------------------ 10 files changed, 521 insertions(+), 432 deletions(-) create mode 100644 Editor/ReadySet/Inspectors.meta create mode 100644 Editor/ReadySet/Inspectors/MotionAssetEditor.cs create mode 100644 Editor/ReadySet/Inspectors/MotionAssetEditor.cs.meta create mode 100644 Runtime/Pattern/Managers/TaskManager.cs create mode 100644 Runtime/Pattern/Managers/TaskManager.cs.meta create mode 100644 Runtime/ReadySet/Managers/ActionManager.cs rename Runtime/ReadySet/Managers/{TaskManager.cs.meta => ActionManager.cs.meta} (100%) delete mode 100644 Runtime/ReadySet/Managers/TaskManager.cs diff --git a/Editor/Pattern/Inspectors/TaskManagerEditor.cs b/Editor/Pattern/Inspectors/TaskManagerEditor.cs index c3e531a..9595a7c 100644 --- a/Editor/Pattern/Inspectors/TaskManagerEditor.cs +++ b/Editor/Pattern/Inspectors/TaskManagerEditor.cs @@ -1,5 +1,7 @@ -using System; +using System.Collections; +using System.Reflection; using UnityEditor; +using UnityEngine; namespace RealMethod.Editor { @@ -7,28 +9,37 @@ namespace RealMethod.Editor public class TaskManagerEditor : UnityEditor.Editor { private TaskManager BaseComponent; + FieldInfo tasksField; private void OnEnable() { BaseComponent = (TaskManager)target; + tasksField = target.GetType().GetField( + "Tasks", + BindingFlags.Instance | BindingFlags.NonPublic | BindingFlags.Public + + ); + } public override void OnInspectorGUI() { base.OnInspectorGUI(); - EditorGUILayout.Space(); - EditorGUILayout.LabelField(" ----------------- Tasks ----------------- "); + EditorGUILayout.LabelField("", GUI.skin.horizontalSlider); if (BaseComponent != null) { if (BaseComponent.Count > 0) { - ITask[] tasks = BaseComponent.GetAllUnits(); - foreach (var task in tasks) + IList tasks = tasksField.GetValue(target) as IList; + for (int i = 0; i < tasks.Count; i++) { - EditorGUILayout.LabelField($"{task}"); + object task = tasks[i]; + if (task == null) + continue; + EditorGUILayout.LabelField($"{i}.{task.GetType().Name}", EditorStyles.boldLabel); } EditorGUILayout.Space(); - EditorGUILayout.LabelField($"Total: {tasks.Length}"); + EditorGUILayout.LabelField($"Total: {BaseComponent.Count}"); } } @@ -38,47 +49,5 @@ public override void OnInspectorGUI() } - [CustomEditor(typeof(TaskAsset), true)] - public class TaskAssetCompWindow : UnityEditor.Editor - { - private TaskAsset BaseAsset; - - private void OnEnable() - { - BaseAsset = (TaskAsset)target; - } - - public override void OnInspectorGUI() - { - base.OnInspectorGUI(); - EditorGUILayout.Space(); - EditorGUILayout.LabelField("Debug.... "); - if (BaseAsset != null) - { - EditorGUILayout.LabelField($"Status: {CheckStatus(BaseAsset)}"); - if (BaseAsset is TaskBehaviour provider) - { - if (provider.IsInfinit) - { - EditorGUILayout.LabelField($"Time: Infinit"); - } - else - { - EditorGUILayout.LabelField($"Time: {Math.Round(provider.ElapsedTime, 2)} ({Math.Round((1 - provider.NormalizedTime) * 100, 2)}%)"); - } - } - - } - } - - - private string CheckStatus(TaskAsset task) - { - return task.IsEnable ? "Enable" : "Disable"; - } - } - - - } \ No newline at end of file diff --git a/Editor/ReadySet/Inspectors.meta b/Editor/ReadySet/Inspectors.meta new file mode 100644 index 0000000..232a6b0 --- /dev/null +++ b/Editor/ReadySet/Inspectors.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: dfdfee6ded1444748b9cf7cbeaa31b5d +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Editor/ReadySet/Inspectors/MotionAssetEditor.cs b/Editor/ReadySet/Inspectors/MotionAssetEditor.cs new file mode 100644 index 0000000..eb9dfb6 --- /dev/null +++ b/Editor/ReadySet/Inspectors/MotionAssetEditor.cs @@ -0,0 +1,46 @@ +using System; +using UnityEditor; +using UnityEngine; + +namespace RealMethod.Editor +{ + [CustomEditor(typeof(MotionAsset), true)] + public class TaskAssetCompWindow : UnityEditor.Editor + { + private MotionAsset BaseAsset; + + private void OnEnable() + { + BaseAsset = (MotionAsset)target; + } + + public override void OnInspectorGUI() + { + base.OnInspectorGUI(); + EditorGUILayout.LabelField("", GUI.skin.horizontalSlider); + EditorGUILayout.LabelField("Debug.... "); + if (BaseAsset != null) + { + EditorGUILayout.LabelField($"Status: {CheckStatus(BaseAsset)}"); + if (BaseAsset is IHandleBehaviourAction provider) + { + if (provider.IsInfinit) + { + EditorGUILayout.LabelField($"Time: Infinit"); + } + else + { + EditorGUILayout.LabelField($"Time: {Math.Round(provider.ElapsedTime, 2)} ({Math.Round((1 - provider.NormalizedTime) * 100, 2)}%)"); + } + } + + } + } + + + private string CheckStatus(MotionAsset task) + { + return task.IsEnable ? "Enable" : "Disable"; + } + } +} \ No newline at end of file diff --git a/Editor/ReadySet/Inspectors/MotionAssetEditor.cs.meta b/Editor/ReadySet/Inspectors/MotionAssetEditor.cs.meta new file mode 100644 index 0000000..5043f2e --- /dev/null +++ b/Editor/ReadySet/Inspectors/MotionAssetEditor.cs.meta @@ -0,0 +1,2 @@ +fileFormatVersion: 2 +guid: 3cd743d5832d4f94a943b7e8e19a2042 \ No newline at end of file diff --git a/Runtime/Pattern/Managers/TaskManager.cs b/Runtime/Pattern/Managers/TaskManager.cs new file mode 100644 index 0000000..eef6166 --- /dev/null +++ b/Runtime/Pattern/Managers/TaskManager.cs @@ -0,0 +1,168 @@ +using System; +using System.Collections.Generic; +using UnityEngine; + +namespace RealMethod +{ + public interface ITask : ITask, ITick where T : IHandle + { + T Controller { get; } + } + + public abstract class TaskManager : MonoBehaviour, IGameManager + { + protected readonly List Tasks = new List(); + public int Count => Tasks != null ? Tasks.Count : 0; + + // Implement IGameManager Interface + MonoBehaviour IGameManager.GetManagerClass() + { + return this; + } + void IGameManager.InitiateManager(bool AlwaysLoaded) + { + InitiateManager(AlwaysLoaded); + } + void IGameManager.ResolveService(Service service, bool active) + { + ResolveService(service); + } + + // Abstract Methods + protected abstract void InitiateManager(bool alwaysLoaded); + protected abstract void ResolveService(Service service); + } + public abstract class TaskManager : TaskManager where J : IHandle + { + + public abstract J Create(F Task, bool AutoStart = false) where F : class; + public abstract J FindByName(Name16 TaskName); + public abstract bool Destroy(J motion); + } + public abstract class TaskManager : TaskManager where T : ITask where J : IHandle + { + [Header("Setting")] + [SerializeField] + private bool EnableTick = true; + + + public event Action OnTaskAdded; + public event Action OnTaskRemoved; + + + // Unity Method + private void Update() + { + if (EnableTick == false) + return; + + float delta = Time.deltaTime; + foreach (var task in Tasks) + { + if (task is T provider) + provider.Tick(delta); + } + } + + // Function + public override J Create(F Task, bool autoStart = false) where F : class + { + if (TryCreateNewInstance(Task, out F TaskObject)) + { + J Provider = AddTask(TaskObject); + if (Provider != null) + { + if (autoStart) + AutoStart(Provider); + return Provider; + } + else + { + return default; + } + } + else + { + Debug.LogWarning($"Can't create instance with Type({typeof(F)})"); + return default; + } + } + public override J FindByName(Name16 TaskName) + { + foreach (var task in Tasks) + { + if (task is J provider) + { + if (provider.NameID == TaskName) + { + return provider; + } + } + } + return default; + } + public override bool Destroy(J motion) + { + return RemoveTask(motion); + } + + // Method + protected J AddTask(object Task) + { + if (Task == null) + { + Debug.LogWarning($"Task is not valid"); + return default; + } + + if (Task is T provider) + { + Tasks.Add(Task); + provider.Active(); + OnTaskAdded?.Invoke(provider.Controller); + Task.InvokeSpawnEvent(); + return provider.Controller; + } + else + { + Debug.LogWarning($"Task({Task}) should implement {typeof(T)}"); + return default; + } + } + protected bool RemoveTask(T task) + { + if (Tasks.Contains(task)) + { + task.Deactive(); + OnTaskRemoved?.Invoke(task.Controller); + return Tasks.Remove(task); + } + else + { + return false; + } + } + protected bool RemoveTask(J behavior) + { + foreach (object task in Tasks) + { + if (task is T provider) + { + if (provider.Controller.NameID == behavior.NameID) + { + provider.Deactive(); + OnTaskRemoved?.Invoke(provider.Controller); + provider.InvokeDespawnEvent(); + return Tasks.Remove(provider); + } + } + } + return false; + } + + // Abstract Methods + protected abstract bool TryCreateNewInstance

(object ClassType, out P result) where P : class; + protected abstract void AutoStart(J Handle); + } + +} \ No newline at end of file diff --git a/Runtime/Pattern/Managers/TaskManager.cs.meta b/Runtime/Pattern/Managers/TaskManager.cs.meta new file mode 100644 index 0000000..3d48962 --- /dev/null +++ b/Runtime/Pattern/Managers/TaskManager.cs.meta @@ -0,0 +1,2 @@ +fileFormatVersion: 2 +guid: 93918933848831043b4d95e4f18fd91b \ No newline at end of file diff --git a/Runtime/ReadySet/Managers/ActionManager.cs b/Runtime/ReadySet/Managers/ActionManager.cs new file mode 100644 index 0000000..f1da9a4 --- /dev/null +++ b/Runtime/ReadySet/Managers/ActionManager.cs @@ -0,0 +1,62 @@ +using System; +using UnityEngine; + +namespace RealMethod +{ + + public interface IAction : IHandle + { + void Starter(); + } + public interface IActionTask : ITask + { + + } + + public sealed class ActionClass : SoftType + { + + } + + + + [AddComponentMenu("RealMethod/Manager/ActionManager")] + public sealed class ActionManager : TaskManager + { + [Header("Action")] + private SoftType[] DefaultActions; + + // TaskMaanger Methods + protected override void InitiateManager(bool alwaysLoaded) + { + if (DefaultActions != null) + { + for (int i = 0; i < DefaultActions.Length; i++) + { + Create(DefaultActions[i]); + } + } + } + protected override void ResolveService(Service service) + { + } + protected override bool TryCreateNewInstance

(object ClassType, out P result) + { + if (ClassType is ActionClass ActionType) + { + result = ActionType.Type.CreateInstance() as P; + return true; + } + else + { + result = null; + return false; + } + } + protected override void AutoStart(IAction Handle) + { + Handle.Starter(); + } + + } +} \ No newline at end of file diff --git a/Runtime/ReadySet/Managers/TaskManager.cs.meta b/Runtime/ReadySet/Managers/ActionManager.cs.meta similarity index 100% rename from Runtime/ReadySet/Managers/TaskManager.cs.meta rename to Runtime/ReadySet/Managers/ActionManager.cs.meta diff --git a/Runtime/ReadySet/Managers/MotionManager.cs b/Runtime/ReadySet/Managers/MotionManager.cs index 394399b..40fc054 100644 --- a/Runtime/ReadySet/Managers/MotionManager.cs +++ b/Runtime/ReadySet/Managers/MotionManager.cs @@ -1,104 +1,263 @@ - using UnityEngine; namespace RealMethod { - public interface IMotion : IBehaviourAction , ITick + public interface IMotion : IHandleBehaviourAction + { + } + public interface IMotionTask : ITask { } - public sealed class MotionManager : TickManager + public abstract class MotionAsset : CloneAsset, IMotion, IMotionTask { - [Header("Motion")] + [Header("Task")] [SerializeField] - private MotionAsset[] DefaultMotions; + private bool infinit = false; + [SerializeField, ConditionalHide("infinit", true, true)] + private float baseDuration = 5; + public bool IsEnable { get; private set; } - // TickManager Methods - protected override void InitiateManager(bool alwaysLoaded) + + // Private Variable + private bool islive = false; + private bool isRunning = true; + private float residuary = -1; + private float lifetime = -1; + + + + // Implement ITask Interface + void ITask.Active() { - if (DefaultMotions != null) + IsEnable = true; + OnEnable(); + } + void ITask.Deactive() + { + Finish(); + IsEnable = false; + OnDisable(); + } + // Implement ITask Interface + IMotion ITask.Controller => this; + // Implement ITick Interface + void ITick.Tick(float deltaTime) + { + // Check Initiate + if (!IsEnable) { - for (int i = 0; i < DefaultMotions.Length; i++) + Debug.LogError("First You Sould Validate"); + return; + } + + // Check Started + if (!islive) + { + return; + } + + // Gate for Puse Updating Command + if (!CanUpdate()) + { + return; + } + + // Handel Lifetime Command + if (residuary > 0) + { + // Calculate Time + residuary -= Time.deltaTime; + } + else + { + if (!infinit) { - Create(DefaultMotions[i], this); + // Stop Command Teime over + residuary = 0; + Finish(); + return; } } + + OnUpdate(deltaTime); } - protected override void InitiateService(Service service) + // Implement IHandleBehaviour Interface + bool IHandleBehaviour.IsStarted => islive; + void IHandleBehaviour.Start() { + lifetime = infinit ? 0 : baseDuration; + if (IsEnable) + { + if (!islive) + { + residuary = lifetime; + OnBegin(); + islive = true; + } + } + else + { + Debug.LogError("First You Sould Active Task"); + } } - protected override bool CheckUnit(MotionAsset unit) + void IHandleBehaviour.Stop() { - return true; + if (IsEnable) + { + if (islive) + { + islive = false; + OnEnd(); + } + } + else + { + Debug.LogError("First You Sould Initiate Command with ICommandInitiator"); + } } - - public IMotion Create(MotionAsset motion, Object author) + void IHandleBehaviour.Clear() { - var TargetMotion = Instantiate(motion); - IMotion provider = TargetMotion; - provider.Start(); - units.Add(TargetMotion); - return provider; + Finish(); + IsEnable = false; } - public bool Delete() + // Implement IHandleBehaviourCycle Interface + bool IHandleBehaviourCycle.IsFinished => !islive; + bool IHandleBehaviourCycle.IsInfinit => infinit; + float IHandleBehaviourCycle.RemainingTime => residuary; + float IHandleBehaviourCycle.ElapsedTime => lifetime - residuary; + float IHandleBehaviourCycle.NormalizedTime => residuary / lifetime; + void IHandleBehaviourCycle.Start(float overrideTime) { - return true; + lifetime = overrideTime; + if (IsEnable) + { + if (!islive) + { + residuary = lifetime; + OnBegin(); + islive = true; + } + } + else + { + Debug.LogError("First You Sould Initiate Behaviour"); + } } - } - - public abstract class MotionAsset : DataAsset, IMotion - { - // Implement ITick Interface - void ITick.Tick(float deltaTime) + // Implement IHandleBehaviourAction Interface + bool IHandleBehaviourAction.IsPaused => !isRunning; + void IHandleBehaviourAction.Pause() { - Debug.Log(name); + isRunning = false; + OnPause(); } - // Implement IBehaviour Interface - bool IBehaviour.IsStarted => throw new System.NotImplementedException(); - void IBehaviour.Start() + void IHandleBehaviourAction.Resume() { - Debug.Log("Hello"); + isRunning = true; + OnResume(); } - void IBehaviour.Stop() + void IHandleBehaviourAction.Reset() { - throw new System.NotImplementedException(); + ResetToDefault(); + isRunning = true; + OnReset(); } - void IBehaviour.Clear() + void IHandleBehaviourAction.Restart(float Duration) { - throw new System.NotImplementedException(); + ResetToDefault(); + isRunning = true; + OnReset(); + if (Duration > 0) + { + ((IHandleBehaviourCycle)this).Start(Duration); + } + else + { + ((IHandleBehaviourCycle)this).Start(); + } } - // Implement IBehaviourCycle Interface - bool IBehaviourCycle.IsFinished => throw new System.NotImplementedException(); - bool IBehaviourCycle.IsInfinit => throw new System.NotImplementedException(); - float IBehaviourCycle.RemainingTime => throw new System.NotImplementedException(); - float IBehaviourCycle.ElapsedTime => throw new System.NotImplementedException(); - float IBehaviourCycle.NormalizedTime => throw new System.NotImplementedException(); - void IBehaviourCycle.Start(float overrideTime) + + + // Method + protected void Finish() + { + if (islive) + ((IHandleBehaviour)this).Stop(); + } + protected void Reset() + { + IsEnable = false; + ResetToDefault(); + } + private void ResetToDefault() { - throw new System.NotImplementedException(); + islive = false; + isRunning = true; + lifetime = -1; + residuary = -1; } - // Implement IBehaviourAction Interface - bool IBehaviourAction.IsPaused => throw new System.NotImplementedException(); - void IBehaviourAction.Pause() + protected virtual bool CanUpdate() + { + return isRunning; + } + + + // Abstract Methods + protected abstract void OnEnable(); + protected abstract void OnBegin(); + protected abstract void OnUpdate(float deltaTime); + protected abstract void OnPause(); + protected abstract void OnResume(); + protected abstract void OnReset(); + protected abstract void OnEnd(); + protected abstract void OnDisable(); + } + + + [AddComponentMenu("RealMethod/Manager/MotionManager")] + public sealed class MotionManager : TaskManager + { + [Header("Motion")] + [SerializeField] + private MotionAsset[] DefaultMotions; + + + + // TickManager Methods + protected override void InitiateManager(bool alwaysLoaded) { - throw new System.NotImplementedException(); + if (DefaultMotions != null) + { + for (int i = 0; i < DefaultMotions.Length; i++) + { + Create(DefaultMotions[i]); + } + } } - void IBehaviourAction.Resume() + protected override void ResolveService(Service service) { - throw new System.NotImplementedException(); } - void IBehaviourAction.Reset() + protected override bool TryCreateNewInstance

(object ClassType, out P result) { - throw new System.NotImplementedException(); + if (ClassType is PrimitiveAsset asset) + { + result = ScriptableObject.Instantiate(asset) as P; + return true; + } + else + { + result = null; + return false; + } } - void IBehaviourAction.Restart(float Duration) + protected override void AutoStart(IMotion Handle) { - throw new System.NotImplementedException(); + Handle.Start(); } - } + } diff --git a/Runtime/ReadySet/Managers/TaskManager.cs b/Runtime/ReadySet/Managers/TaskManager.cs deleted file mode 100644 index f5e3933..0000000 --- a/Runtime/ReadySet/Managers/TaskManager.cs +++ /dev/null @@ -1,327 +0,0 @@ -using UnityEngine; - -#if UNITY_EDITOR -using UnityEditor; -#endif - -namespace RealMethod -{ - public delegate void TaskCallback(bool enable); - public interface ITask : ITick - { - void Enable(Object author); - void Disable(Object author); - } - - [AddComponentMenu("RealMethod/Manager/TaskManager")] - public sealed class TaskManager : TickManager - { - [Header("Task")] - [SerializeField] - private TaskAsset[] DefaultTasks; - - // TickManager Methods - protected override void InitiateManager(bool alwaysLoaded) - { - if (DefaultTasks != null) - { - for (int i = 0; i < DefaultTasks.Length; i++) - { - Add(DefaultTasks[i], this); - } - } - } - protected override void InitiateService(Service service) - { - } - protected override bool CheckUnit(ITask unit) - { - return true; - } - - - // Public Functions - public void Add(ITask task, Object author) - { - task.Enable(author); - units.Add(task); - } - public bool Remove(ITask task, Object author) - { - if (units.Contains(task)) - { - task.Disable(author); - units.Remove(task); - return true; - } - else - { - return false; - } - } - } - - public abstract class TaskAsset : DataAsset, ITask - { - private event TaskCallback onTaskStatus; - public bool IsEnable { get; private set; } - - // Implement ITask Interface - void ITask.Enable(Object author) - { - IsEnable = true; - OnTaskEnable(author); - onTaskStatus?.Invoke(true); - } - void ITick.Tick(float delta) - { - OnTaskUpdate(delta); - } - void ITask.Disable(Object author) - { - IsEnable = false; - OnTaskDisable(author); - onTaskStatus?.Invoke(false); - } - - protected virtual void Reset() - { - IsEnable = false; - } - - // Abstract Methods - protected abstract void OnTaskEnable(Object author); - protected abstract void OnTaskUpdate(float delta); - protected abstract void OnTaskDisable(Object author); - -#if UNITY_EDITOR - public override bool AutoReset(PlayModeStateChange state) - { - if (state == PlayModeStateChange.ExitingPlayMode) - return true; - return base.AutoReset(state); - } -#endif - } - public abstract class TaskBehaviour : TaskAsset, IBehaviourAction - { - [Header("Task")] - [SerializeField] - private bool infinit = false; - [SerializeField, ConditionalHide("infinit", true, true)] - private float baseDuration = 5; - - // Public Variable - public System.Action OnStarted; - public System.Action OnPaused; - public System.Action OnResumed; - public System.Action OnFinished; - - // Protected Variable - protected Object Author { get; private set; } - - // Private Variable - private bool isValidated; - private float lifetime = -1; - private float residuary = -1; - private bool islive = false; - private bool isRunning = true; - - - // TaskAsset Methods - protected sealed override void OnTaskEnable(Object author) - { - Author = author; - isValidated = true; - OnInitiate(); - ((IBehaviour)this).Start(); - } - protected sealed override void OnTaskUpdate(float delta) - { - // Check Initiate - if (!isValidated) - { - Debug.LogError("First You Sould Validate"); - return; - } - - // Check Started - if (!islive) - { - return; - } - - // Gate for Puse Updating Command - if (!CanUpdate()) - { - return; - } - - // Handel Lifetime Command - if (residuary > 0) - { - // Calculate Time - residuary -= Time.deltaTime; - } - else - { - if (!infinit) - { - // Stop Command Teime over - residuary = 0; - Finish(); - return; - } - } - - OnUpdate(); - } - protected sealed override void OnTaskDisable(Object author) - { - isValidated = false; - Author = null; - } - - - // Implement IBehaviour Interface - public bool IsStarted => islive; - void IBehaviour.Start() - { - lifetime = infinit ? 0 : baseDuration; - if (isValidated) - { - if (!islive) - { - residuary = lifetime; - OnBegin(); - OnStarted?.Invoke(this); - islive = true; - } - } - else - { - Debug.LogError("First You Sould Initiate Behaviour"); - } - } - void IBehaviour.Stop() - { - if (isValidated) - { - if (islive) - { - islive = false; - OnEnd(); - OnFinished?.Invoke(this); - } - } - else - { - Debug.LogError("First You Sould Initiate Command with ICommandInitiator"); - } - } - void IBehaviour.Clear() - { - Finish(); - isValidated = false; - Author = null; - } - - // Implement IBehaviourCycle Interface - public bool IsInfinit => infinit; - public float RemainingTime => residuary; - public float ElapsedTime => lifetime - residuary; - public float NormalizedTime => residuary / lifetime; - public bool IsFinished => !islive; - void IBehaviourCycle.Start(float overrideTime) - { - lifetime = overrideTime; - if (isValidated) - { - if (!islive) - { - residuary = lifetime; - OnBegin(); - OnStarted?.Invoke(this); - islive = true; - } - } - else - { - Debug.LogError("First You Sould Initiate Behaviour"); - } - } - - // Implement IBehaviourAction Interface - public bool IsPaused => !isRunning; - void IBehaviourAction.Pause() - { - isRunning = false; - OnPause(); - OnPaused?.Invoke(this); - } - void IBehaviourAction.Resume() - { - isRunning = true; - OnResume(); - OnResumed?.Invoke(this); - } - void IBehaviourAction.Reset() - { - ResetTaskValues(); - isRunning = true; - OnReset(); - } - void IBehaviourAction.Restart(float Duration) - { - ResetTaskValues(); - isRunning = true; - OnReset(); - if (Duration > 0) - { - ((IBehaviourCycle)this).Start(Duration); - } - else - { - ((IBehaviour)this).Start(); - } - } - - - // Functions - public void Finish() - { - if (islive) - ((IBehaviour)this).Stop(); - } - private void ResetTaskValues() - { - islive = false; - isRunning = true; - lifetime = -1; - residuary = -1; - } - protected virtual bool CanUpdate() - { - return isRunning; - } - - - // Unity Methods - protected override void Reset() - { - base.Reset(); - ResetTaskValues(); - } - - // Abstract Methods - protected abstract void OnInitiate(); - protected abstract void OnBegin(); - protected abstract void OnUpdate(); - protected abstract void OnPause(); - protected abstract void OnResume(); - protected abstract void OnReset(); - protected abstract void OnEnd(); - - } - -} \ No newline at end of file From 668daea0d3705d54a4f1d48ad53405a254b5a133 Mon Sep 17 00:00:00 2001 From: Alijimpa Date: Sat, 25 Apr 2026 17:47:06 +0330 Subject: [PATCH 141/204] Refine SaveManager --- Runtime/Pattern/Managers/SaveManager.cs | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/Runtime/Pattern/Managers/SaveManager.cs b/Runtime/Pattern/Managers/SaveManager.cs index 25e10b5..61cd5da 100644 --- a/Runtime/Pattern/Managers/SaveManager.cs +++ b/Runtime/Pattern/Managers/SaveManager.cs @@ -1081,7 +1081,15 @@ protected override IFile CreateMainFile() } if (Mode == SaveFileStructure.SingleFile) { - MySaveFile = ScriptableObject.CreateInstance(SingeFileAsset.GetType()); + if (SingeFileAsset != null) + { + MySaveFile = ScriptableObject.CreateInstance(SingeFileAsset.GetType()); + } + else + { + Debug.LogWarning("SingleFileAsset is not valid"); + // Mode = SaveFileStructure.MultiFile; + } } if (MySaveFile is IFile provider) From 27c812e9ed385e51acd4ee4ff29b730b8b9f9f74 Mon Sep 17 00:00:00 2001 From: Alijimpa Date: Sat, 25 Apr 2026 17:47:23 +0330 Subject: [PATCH 142/204] Refactor Behavior Interface Defenation --- Runtime/Library/Interfaces/Behaviour.cs.meta | 2 -- .../Interfaces/{Behaviour.cs => Handle.cs} | 31 ++++++++++++++++--- Runtime/Library/Interfaces/Handle.cs.meta | 2 ++ 3 files changed, 29 insertions(+), 6 deletions(-) delete mode 100644 Runtime/Library/Interfaces/Behaviour.cs.meta rename Runtime/Library/Interfaces/{Behaviour.cs => Handle.cs} (60%) create mode 100644 Runtime/Library/Interfaces/Handle.cs.meta diff --git a/Runtime/Library/Interfaces/Behaviour.cs.meta b/Runtime/Library/Interfaces/Behaviour.cs.meta deleted file mode 100644 index 3f23462..0000000 --- a/Runtime/Library/Interfaces/Behaviour.cs.meta +++ /dev/null @@ -1,2 +0,0 @@ -fileFormatVersion: 2 -guid: 8f64c6d8086f93f498d15565af34d021 \ No newline at end of file diff --git a/Runtime/Library/Interfaces/Behaviour.cs b/Runtime/Library/Interfaces/Handle.cs similarity index 60% rename from Runtime/Library/Interfaces/Behaviour.cs rename to Runtime/Library/Interfaces/Handle.cs index e57c0aa..f381c39 100644 --- a/Runtime/Library/Interfaces/Behaviour.cs +++ b/Runtime/Library/Interfaces/Handle.cs @@ -1,6 +1,28 @@ namespace RealMethod { - public interface IBehaviour + ///

+ /// Represents the root interface for any system that exposes + /// an external control handle. + /// + /// This interface itself defines no functionality; instead, it acts + /// as a conceptual marker for objects whose execution, lifecycle, + /// or behavior can be controlled through derived interfaces such as + /// IHandleTrigger, IHandleLifecycle, IHandleTimed, or IHandleAction. + /// + /// In other words, IHandle identifies a controllable unit that + /// provides a unified access point for interacting with the + /// underlying process, behavior, or action. + /// + public interface IHandle : IIdentifier + { + } + + public interface IHandleTrigger : IHandle + { + void Trigger(); + void Cancel(); + } + public interface IHandleBehaviour : IHandle { /// Called when the Behaviour starts. void Start(); @@ -11,10 +33,10 @@ public interface IBehaviour /// Whether the Behaviour is currently started. bool IsStarted { get; } } - public interface IBehaviourCycle : IBehaviour + public interface IHandleBehaviourCycle : IHandleBehaviour { /// Called when the Behaviour starts with override Time. - void Start(float overrideTime); + void Start(float Duration); // Whether the Behaviour has finished execution. bool IsFinished { get; } /// Has Behaviour infinit lifetime. @@ -26,7 +48,7 @@ public interface IBehaviourCycle : IBehaviour /// Normalized time since Behaviour Live. float NormalizedTime { get; } } - public interface IBehaviourAction : IBehaviourCycle + public interface IHandleBehaviourAction : IHandleBehaviourCycle { /// Called to pause the Behaviour temporarily. void Pause(); @@ -40,4 +62,5 @@ public interface IBehaviourAction : IBehaviourCycle bool IsPaused { get; } } + } \ No newline at end of file diff --git a/Runtime/Library/Interfaces/Handle.cs.meta b/Runtime/Library/Interfaces/Handle.cs.meta new file mode 100644 index 0000000..dc5a0ed --- /dev/null +++ b/Runtime/Library/Interfaces/Handle.cs.meta @@ -0,0 +1,2 @@ +fileFormatVersion: 2 +guid: ca758207c40f53048bdc05d13910b196 \ No newline at end of file From 4210dcf8da68c7421d401d2ec456fad17c5bbfaf Mon Sep 17 00:00:00 2001 From: Alijimpa Date: Sat, 25 Apr 2026 17:48:08 +0330 Subject: [PATCH 143/204] REfine RetriggerableDelay --- .../Presets/{Task.meta => Class.meta} | 0 Runtime/ReadySet/Presets/Class/ActionSlot.cs | 234 ++++++++++++++++++ .../ReadySet/Presets/Class/ActionSlot.cs.meta | 2 + .../Presets/Class/RetriggerableDelay.cs | 56 +++++ .../RetriggerableDelay.cs.meta} | 0 .../Presets/Task/RetriggerableDelayTask.cs | 62 ----- 6 files changed, 292 insertions(+), 62 deletions(-) rename Runtime/ReadySet/Presets/{Task.meta => Class.meta} (100%) create mode 100644 Runtime/ReadySet/Presets/Class/ActionSlot.cs create mode 100644 Runtime/ReadySet/Presets/Class/ActionSlot.cs.meta create mode 100644 Runtime/ReadySet/Presets/Class/RetriggerableDelay.cs rename Runtime/ReadySet/Presets/{Task/RetriggerableDelayTask.cs.meta => Class/RetriggerableDelay.cs.meta} (100%) delete mode 100644 Runtime/ReadySet/Presets/Task/RetriggerableDelayTask.cs diff --git a/Runtime/ReadySet/Presets/Task.meta b/Runtime/ReadySet/Presets/Class.meta similarity index 100% rename from Runtime/ReadySet/Presets/Task.meta rename to Runtime/ReadySet/Presets/Class.meta diff --git a/Runtime/ReadySet/Presets/Class/ActionSlot.cs b/Runtime/ReadySet/Presets/Class/ActionSlot.cs new file mode 100644 index 0000000..eaeaeec --- /dev/null +++ b/Runtime/ReadySet/Presets/Class/ActionSlot.cs @@ -0,0 +1,234 @@ +using System; +using UnityEngine; + +namespace RealMethod +{ + public abstract class ActionSlot : IAction, IActionTask, IHandleBehaviourAction + { + [Header("Task")] + [SerializeField] + private Name16 name; + [SerializeField] + private bool infinit = false; + [SerializeField, ConditionalHide("infinit", true, true)] + private float baseDuration = 5; + public bool IsEnable { get; private set; } + + // Private Variable + private bool islive = false; + private bool isValidated; + private float lifetime = -1; + private float residuary = -1; + private bool isRunning = true; + + + // Actions Delegate + public event Action OnStarted; + public event Action OnPaused; + public event Action OnResumed; + public event Action OnFinished; + + + // Implement IIdentifier Interface + Name16 IIdentifier.NameID => GetType().ToString(); + // Implement ITask Interface + void ITask.Active() + { + IsEnable = true; + isValidated = true; + OnEnable(); + } + void ITask.Deactive() + { + IsEnable = false; + isValidated = false; + OnDisable(); + } + // Implement ITask Interface + IAction ITask.Controller => this; + // Implement ITick Interface + void ITick.Tick(float delta) + { + // Check Initiate + if (!isValidated) + { + Debug.LogError("First You Sould Validate"); + return; + } + + // Check Started + if (!islive) + { + return; + } + + // Gate for Puse Updating Command + if (!CanUpdate()) + { + return; + } + + // Handel Lifetime Command + if (residuary > 0) + { + // Calculate Time + residuary -= Time.deltaTime; + } + else + { + if (!infinit) + { + // Stop Command Teime over + residuary = 0; + Finish(); + return; + } + } + + OnUpdate(delta); + } + // Implement IAction Interface + void IAction.Starter() + { + throw new NotImplementedException(); + } + // Implement IBehaviour Interface + public bool IsStarted => islive; + void IHandleBehaviour.Start() + { + lifetime = infinit ? 0 : baseDuration; + if (isValidated) + { + if (!islive) + { + residuary = lifetime; + OnBegin(); + OnStarted?.Invoke(this); + islive = true; + } + } + else + { + Debug.LogError("First You Sould Initiate Behaviour"); + } + } + void IHandleBehaviour.Stop() + { + if (isValidated) + { + if (islive) + { + islive = false; + OnEnd(); + OnFinished?.Invoke(this); + } + } + else + { + Debug.LogError("First You Sould Initiate Command with ICommandInitiator"); + } + } + void IHandleBehaviour.Clear() + { + Finish(); + isValidated = false; + } + // Implement IBehaviourCycle Interface + public bool IsInfinit => infinit; + public float RemainingTime => residuary; + public float ElapsedTime => lifetime - residuary; + public float NormalizedTime => residuary / lifetime; + public bool IsFinished => !islive; + void IHandleBehaviourCycle.Start(float overrideTime) + { + lifetime = overrideTime; + if (isValidated) + { + if (!islive) + { + residuary = lifetime; + OnBegin(); + OnStarted?.Invoke(this); + islive = true; + } + } + else + { + Debug.LogError("First You Sould Initiate Behaviour"); + } + } + // Implement IBehaviourAction Interface + public bool IsPaused => !isRunning; + void IHandleBehaviourAction.Pause() + { + isRunning = false; + OnPause(); + OnPaused?.Invoke(this); + } + void IHandleBehaviourAction.Resume() + { + isRunning = true; + OnResume(); + OnResumed?.Invoke(this); + } + void IHandleBehaviourAction.Reset() + { + ResetTaskValues(); + isRunning = true; + OnReset(); + } + void IHandleBehaviourAction.Restart(float Duration) + { + ResetTaskValues(); + isRunning = true; + OnReset(); + if (Duration > 0) + { + ((IHandleBehaviourCycle)this).Start(Duration); + } + else + { + ((IHandleBehaviour)this).Start(); + } + } + + + // Functions + public void Finish() + { + if (islive) + ((IHandleBehaviour)this).Stop(); + } + + // Methods + private void ResetTaskValues() + { + islive = false; + isRunning = true; + lifetime = -1; + residuary = -1; + } + protected virtual bool CanUpdate() + { + return isRunning; + } + protected virtual void Reset() + { + IsEnable = false; + ResetTaskValues(); + } + + + // Abstract Methods + protected abstract void OnEnable(); + protected abstract void OnBegin(); + protected abstract void OnUpdate(float delta); + protected abstract void OnPause(); + protected abstract void OnResume(); + protected abstract void OnReset(); + protected abstract void OnEnd(); + protected abstract void OnDisable(); + + } + +} \ No newline at end of file diff --git a/Runtime/ReadySet/Presets/Class/ActionSlot.cs.meta b/Runtime/ReadySet/Presets/Class/ActionSlot.cs.meta new file mode 100644 index 0000000..ddbcaac --- /dev/null +++ b/Runtime/ReadySet/Presets/Class/ActionSlot.cs.meta @@ -0,0 +1,2 @@ +fileFormatVersion: 2 +guid: 0f1be7d745ee1e9409a6fc9c89f463a9 \ No newline at end of file diff --git a/Runtime/ReadySet/Presets/Class/RetriggerableDelay.cs b/Runtime/ReadySet/Presets/Class/RetriggerableDelay.cs new file mode 100644 index 0000000..5a8ffa5 --- /dev/null +++ b/Runtime/ReadySet/Presets/Class/RetriggerableDelay.cs @@ -0,0 +1,56 @@ +using System; +using System.Threading; +using System.Threading.Tasks; + +public class RetriggerDelay +{ + private static int _nextId; + public int Id { get; } + + private CancellationTokenSource _cts; + private readonly float _delay; + private bool _isRunning; + + public event Action OnCompleted; + + public RetriggerDelay(float delay) + { + Id = ++_nextId; + _delay = delay; + } + + public async void Trigger() + { + // Cancel any previous delay + _cts?.Cancel(); + + _cts = new CancellationTokenSource(); + var token = _cts.Token; + + _isRunning = true; + + try + { + // Convert seconds → milliseconds + await Task.Delay((int)(_delay * 1000f), token); + + if (!token.IsCancellationRequested) + { + _isRunning = false; + OnCompleted?.Invoke(this); // notifies external system to destroy/remove + } + } + catch (TaskCanceledException) + { + // Expected when retriggered + } + } + + public void Cancel() + { + _cts?.Cancel(); + _isRunning = false; + } + + public bool IsRunning => _isRunning; +} diff --git a/Runtime/ReadySet/Presets/Task/RetriggerableDelayTask.cs.meta b/Runtime/ReadySet/Presets/Class/RetriggerableDelay.cs.meta similarity index 100% rename from Runtime/ReadySet/Presets/Task/RetriggerableDelayTask.cs.meta rename to Runtime/ReadySet/Presets/Class/RetriggerableDelay.cs.meta diff --git a/Runtime/ReadySet/Presets/Task/RetriggerableDelayTask.cs b/Runtime/ReadySet/Presets/Task/RetriggerableDelayTask.cs deleted file mode 100644 index 404d1f9..0000000 --- a/Runtime/ReadySet/Presets/Task/RetriggerableDelayTask.cs +++ /dev/null @@ -1,62 +0,0 @@ - - -using RealMethod; -using UnityEngine; - -namespace RealMethod -{ - public class RetriggerableDelay : ITask - { - private float _delay; - private System.Action _onElapsed; - private float _endTime; - private bool _running; - private Object MyAuthor; - - public RetriggerableDelay(float delay, System.Action onElapsed) - { - _delay = delay; - _onElapsed = onElapsed; - } - - // Implement ITask Interface - void ITask.Enable(Object author) - { - MyAuthor = author; - _endTime = Time.time + _delay; - _running = true; - } - void ITask.Disable(Object author) - { - MyAuthor = null; - } - // Implement ITick Interface - void ITick.Tick(float deltaTime) - { - if (_running && Time.time >= _endTime) - { - _running = false; - _onElapsed?.Invoke(); - if (MyAuthor != null) - Despawn.Task(this, MyAuthor); - } - } - - - /// - /// Restart the delay countdown. - /// - public void Trigger() - { - _endTime = Time.time + _delay; - _running = true; - } - /// Cancel without firing. - public void Cancel() => _running = false; - - - - } - - -} \ No newline at end of file From 08d530f2d9fef4b59326e5b43b7ff88bd2e20972 Mon Sep 17 00:00:00 2001 From: Alijimpa Date: Sat, 25 Apr 2026 17:48:23 +0330 Subject: [PATCH 144/204] Rename Save Defenation --- .../Core/Definitions/{Save.cs => Save&File.cs} | 17 +++++++---------- .../{Save.cs.meta => Save&File.cs.meta} | 0 2 files changed, 7 insertions(+), 10 deletions(-) rename Runtime/Core/Definitions/{Save.cs => Save&File.cs} (99%) rename Runtime/Core/Definitions/{Save.cs.meta => Save&File.cs.meta} (100%) diff --git a/Runtime/Core/Definitions/Save.cs b/Runtime/Core/Definitions/Save&File.cs similarity index 99% rename from Runtime/Core/Definitions/Save.cs rename to Runtime/Core/Definitions/Save&File.cs index ffef276..e3f372d 100644 --- a/Runtime/Core/Definitions/Save.cs +++ b/Runtime/Core/Definitions/Save&File.cs @@ -3,14 +3,20 @@ namespace RealMethod { - + // FILE public interface IFile : IIdentifier { string FileName { get; } object FileObject { get; } } + public interface ISaveFile : IFile, ISave + { + void SetName(string NewName); + } + + // SAVE public interface ISaveSystem { /// @@ -67,14 +73,6 @@ public interface ISave void OnLoaded(); void OnSaved(); } - - - public interface ISaveFile : IFile, ISave - { - void SetName(string NewName); - } - - /// /// this is UniqueAsset that implement ISaveFile Interface with some Editor Function /// for testing save and load @@ -214,5 +212,4 @@ private void Editor_IsExist() } - } \ No newline at end of file diff --git a/Runtime/Core/Definitions/Save.cs.meta b/Runtime/Core/Definitions/Save&File.cs.meta similarity index 100% rename from Runtime/Core/Definitions/Save.cs.meta rename to Runtime/Core/Definitions/Save&File.cs.meta From 18d4b70af64524c4e59e62f21c14aede37e4b078 Mon Sep 17 00:00:00 2001 From: Alijimpa Date: Sat, 25 Apr 2026 17:49:39 +0330 Subject: [PATCH 145/204] Rename RetriggerDelay file sript --- .../Presets/Class/{RetriggerableDelay.cs => RetriggerDelay.cs} | 0 .../Class/{RetriggerableDelay.cs.meta => RetriggerDelay.cs.meta} | 0 2 files changed, 0 insertions(+), 0 deletions(-) rename Runtime/ReadySet/Presets/Class/{RetriggerableDelay.cs => RetriggerDelay.cs} (100%) rename Runtime/ReadySet/Presets/Class/{RetriggerableDelay.cs.meta => RetriggerDelay.cs.meta} (100%) diff --git a/Runtime/ReadySet/Presets/Class/RetriggerableDelay.cs b/Runtime/ReadySet/Presets/Class/RetriggerDelay.cs similarity index 100% rename from Runtime/ReadySet/Presets/Class/RetriggerableDelay.cs rename to Runtime/ReadySet/Presets/Class/RetriggerDelay.cs diff --git a/Runtime/ReadySet/Presets/Class/RetriggerableDelay.cs.meta b/Runtime/ReadySet/Presets/Class/RetriggerDelay.cs.meta similarity index 100% rename from Runtime/ReadySet/Presets/Class/RetriggerableDelay.cs.meta rename to Runtime/ReadySet/Presets/Class/RetriggerDelay.cs.meta From f8520f7b94ac8e257eae5f694db29ce4c81c90c9 Mon Sep 17 00:00:00 2001 From: Alijimpa Date: Sat, 25 Apr 2026 17:59:51 +0330 Subject: [PATCH 146/204] Implemen sorting for draw list in Game --- Runtime/Core/Architecture/Game.cs | 1 + 1 file changed, 1 insertion(+) diff --git a/Runtime/Core/Architecture/Game.cs b/Runtime/Core/Architecture/Game.cs index b7cbfab..d8b3d88 100644 --- a/Runtime/Core/Architecture/Game.cs +++ b/Runtime/Core/Architecture/Game.cs @@ -1028,6 +1028,7 @@ public static void Draw(IDrawTask element) if (element != null) { Instance.DrawTasks.Add(element); + Instance.DrawTasks.Sort((a, b) => a.Priority.CompareTo(b.Priority)); element.Active(); } } From 9a048622ab4cefda9778410eba48f1f817980303 Mon Sep 17 00:00:00 2001 From: Alijimpa Date: Sun, 26 Apr 2026 18:17:11 +0330 Subject: [PATCH 147/204] Refine Service Info --- Editor/Core/Inspectors/GameEditor.cs | 6 +- Runtime/Core/Architecture/Game.cs | 16 +- Runtime/Core/Architecture/GameBridge.cs | 78 +--------- Runtime/Core/Architecture/Service.cs | 22 +++ Runtime/ReadySet/Essentials/DefaultGame.cs | 1 + Runtime/ReadySet/Services/DebugService.cs | 161 +++++++++++++++++--- Runtime/ReadySet/Services/DespawnService.cs | 16 +- Runtime/ReadySet/Services/SpawanService.cs | 18 +-- 8 files changed, 191 insertions(+), 127 deletions(-) diff --git a/Editor/Core/Inspectors/GameEditor.cs b/Editor/Core/Inspectors/GameEditor.cs index 3e76f66..48008ae 100644 --- a/Editor/Core/Inspectors/GameEditor.cs +++ b/Editor/Core/Inspectors/GameEditor.cs @@ -21,9 +21,9 @@ public override void OnInspectorGUI() EditorGUILayout.LabelField($"GameStat: {Game.State}"); EditorGUILayout.LabelField($"{GetWorld()} | {GetBrgidge()} | {GetConfig()}"); EditorGUILayout.Space(0.5f); - string[] Services = BaseComponent.GetAllServiceNames(); - string[] Managers = BaseComponent.gameObject.GetComponents().Select(c => c.GetManagerClass().name).ToArray(); - string[] WorldManagers = Game.World ? Game.World.gameObject.GetComponents().Select(c => c.GetManagerClass().name).ToArray() : new string[0]; + string[] Services = BaseComponent.GetAllServiceInfo(); + //string[] Managers = BaseComponent.gameObject.GetComponents().Select(c => c.GetManagerClass().name).ToArray(); + //string[] WorldManagers = Game.World ? Game.World.gameObject.GetComponents().Select(c => c.GetManagerClass().name).ToArray() : new string[0]; for (int i = 0; i < Services.Length; i++) { EditorGUILayout.LabelField($"{i + 1}. {Services[i]}"); diff --git a/Runtime/Core/Architecture/Game.cs b/Runtime/Core/Architecture/Game.cs index d8b3d88..fad438f 100644 --- a/Runtime/Core/Architecture/Game.cs +++ b/Runtime/Core/Architecture/Game.cs @@ -556,14 +556,6 @@ public static void ClearService() Instance.OnServiceCleand(); } /// - /// Returns the type names of all registered game services. - /// - /// Array of service type names. - public string[] GetAllServiceNames() - { - return Services.Keys.Select(t => t.Name).ToArray(); - } - /// /// Requests a scene load by build index . /// If the requested scene is already active, a warning is logged and null is returned. /// @@ -1221,6 +1213,14 @@ private void FixedUpdate() { } + /// + /// Returns the type names of all registered game services. + /// + /// Array of service type names. + public string[] GetAllServiceInfo() + { + return Services.Values.Select(t => t.GetInspectorInfo()).ToArray(); + } #endif diff --git a/Runtime/Core/Architecture/GameBridge.cs b/Runtime/Core/Architecture/GameBridge.cs index 5431a66..d5c2d56 100644 --- a/Runtime/Core/Architecture/GameBridge.cs +++ b/Runtime/Core/Architecture/GameBridge.cs @@ -4,6 +4,7 @@ using UnityEngine.SceneManagement; using System.Collections.Generic; using Codice.Client.Common; +using System.Runtime.CompilerServices; namespace RealMethod { @@ -108,7 +109,6 @@ public abstract class GameBridge : IService, IRelationBridge, ILoadScneBridge private Action SceneLoadingEvent; private Action SceneLoadingProcessEvent; private bool isLoading; - private List Shareds = new List(5); public bool IsHolding { get; private set; } = false; protected float FadeTime = 0; private Scene CurrrentScene; @@ -128,7 +128,12 @@ void IService.Deleted(object author) { SceneManager.activeSceneChanged -= OnActiveSceneChanged; } - +#if UNITY_EDITOR + string IService.GetInspectorInfo() + { + return $"IsLoading:{isLoading} - FadeTime:{FadeTime}"; + } +#endif // Implement IRelationBridge Interface event Action IRelationBridge.OnGameReady @@ -214,43 +219,6 @@ event Action ILoadScneBridge.OnSceneLoadingProcess } bool ILoadScneBridge.IsLoading => isLoading; - /// - /// Adds a GameObject to the shared objects collection so it can be accessed or managed globally. - /// - /// GameObject should be always loaded cross scenes - public void AddSharedObject(GameObject obj) - { - Shareds.Add(obj); - if (obj.gameObject.activeInHierarchy && Game.World.gameObject.activeInHierarchy) - obj.transform.SetParent(Game.World.transform); - } - /// - /// Removes a GameObject from the shared objects collection when it is no longer needed or should no longer be shared. - /// - /// GameObject should not be always loaded cross scenes - public void RemoveSharedObject(GameObject obj) - { - Shareds.Remove(obj); - if (obj.gameObject.activeInHierarchy) - obj.transform.SetParent(null); - } - /// - /// Check is GameObject is in Shared List - /// - /// the target gameobject you want to check - /// Return True when you gameobject is in shared list - public bool IsSharedObject(GameObject obj) - { - foreach (var item in Shareds) - { - if (item == obj) - { - return true; - } - } - return false; - } - /// /// Call this when you want to define new World class to game @@ -271,34 +239,7 @@ protected void SetAdditiveWorld(World world) world.enabled = false; OnAdditiveWorldDetected(world); } - /// - /// Called in loading scene for holding some object to load complitly new scene. - /// With this you can managed some GameObject to active cross scene. - /// - /// Hold in Game class or back to persistance scne - protected void HoldSharedObject(bool active) - { - if (Shareds.Count > 0) - { - if (active) - { - IsHolding = true; - foreach (var item in Shareds) - { - item.transform.SetParent(Game.Instance.transform); - } - } - else - { - foreach (var item in Shareds) - { - item.transform.SetParent(Game.World.transform); - } - IsHolding = false; - } - } - } @@ -469,7 +410,6 @@ private IEnumerator LoadSceneAsync(string scene, int scneIndex = -1) //StartLoading isLoading = true; SceneLoadingEvent?.Invoke(true); - HoldSharedObject(true); float fadingtime = FadeTime; //Fading Screen @@ -510,7 +450,6 @@ private IEnumerator LoadSceneAsync(string scene, int scneIndex = -1) //FinishLoading SceneLoadingEvent?.Invoke(false); - HoldSharedObject(false); isLoading = false; } private IEnumerator AddSceneAsync(Action callback, string scene, int scneIndex = -1) @@ -543,7 +482,6 @@ private IEnumerator LoadWorldAsync(WorldAsset WS) //StartLoading isLoading = true; SceneLoadingEvent?.Invoke(true); - HoldSharedObject(true); float fadingtime = FadeTime; //Fading Screen @@ -569,7 +507,6 @@ private IEnumerator LoadWorldAsync(WorldAsset WS) isLoading = false; yield return null; } - HoldSharedObject(false); // Load Additive Levels for (int i = 0; i < WS.Count; i++) @@ -601,6 +538,5 @@ private IEnumerator LoadWorldAsync(WorldAsset WS) isLoading = false; } - } } \ No newline at end of file diff --git a/Runtime/Core/Architecture/Service.cs b/Runtime/Core/Architecture/Service.cs index e485d28..1125a9a 100644 --- a/Runtime/Core/Architecture/Service.cs +++ b/Runtime/Core/Architecture/Service.cs @@ -26,6 +26,15 @@ public interface IService /// /// The object responsible for deleting the service. void Deleted(object author); +#if UNITY_EDITOR + /// + /// Returns a formatted string containing information about this service + /// intended for display in the Unity Inspector or debugging interfaces. + /// This method is for visualization purposes only and must not affect logic. + /// + /// Formatted display information. + string GetInspectorInfo(); +#endif } /// @@ -51,6 +60,17 @@ void IService.Deleted(object author) { OnEnd(author); } +# if UNITY_EDITOR + string IService.GetInspectorInfo() + { + return GetDisplayInfo(); + } + protected virtual string GetDisplayInfo() + { + return GetType().ToString()+": "; + } +#endif + /// @@ -69,6 +89,8 @@ void IService.Deleted(object author) /// /// The object responsible for deleting the service. protected abstract void OnEnd(object Author); + + } } \ No newline at end of file diff --git a/Runtime/ReadySet/Essentials/DefaultGame.cs b/Runtime/ReadySet/Essentials/DefaultGame.cs index 0d7ea9a..014568b 100644 --- a/Runtime/ReadySet/Essentials/DefaultGame.cs +++ b/Runtime/ReadySet/Essentials/DefaultGame.cs @@ -12,6 +12,7 @@ protected override void OnGameOpen() } protected override void OnGameInitialized() { + AddService(this); Debug.Log("DefultGame Initialized"); } protected override void OnGameStart() diff --git a/Runtime/ReadySet/Services/DebugService.cs b/Runtime/ReadySet/Services/DebugService.cs index bbaf10f..30a5042 100644 --- a/Runtime/ReadySet/Services/DebugService.cs +++ b/Runtime/ReadySet/Services/DebugService.cs @@ -1,11 +1,133 @@ +using System.Collections.Generic; using UnityEngine; namespace RealMethod { - public class DebugService : Service, ILogHandler + public sealed class DebugService : Service, ILogHandler { + private class LogLine : IDrawTask + { + private DebugService MyOwner; + private string MyMessage; + private LogType MyType; + private Vector2 MyOffcet; + private float ActiveTime; + + + public Vector2 Pivot => MyOwner.PrintPivot; + public float Space => MyOwner.PrintSpace; + private int Size => MyOwner.PrintSize; + public bool IsFinished => !(Time.time - ActiveTime <= Duration); + public float Duration + { + get + { + switch (MyType) + { + case LogType.Log: + return 5; + case LogType.Warning: + return 10; + case LogType.Error: + return 15; + case LogType.Assert: + return 20; + case LogType.Exception: + return 25; + default: + return 0; + } + } + } + public Color Color + { + get + { + switch (MyType) + { + case LogType.Log: + return Color.cyan; + case LogType.Warning: + return Color.yellow; + case LogType.Error: + return Color.red; + case LogType.Assert: + return Color.white; + case LogType.Exception: + return Color.blue; + default: + return Color.black; + } + } + } + + + + public LogLine(DebugService owner, string message, LogType type) + { + MyOwner = owner; + MyMessage = message; + MyType = type; + MyOffcet = Vector2.zero; + ActiveTime = 0; + } + public LogLine(DebugService owner, string message, LogType type, Vector2 offcet) + { + MyOwner = owner; + MyMessage = message; + MyType = type; + MyOffcet = offcet; + ActiveTime = 0; + } + + // Implement IIdentifier Interface + Name16 IIdentifier.NameID => throw new System.NotImplementedException(); + // Implemetn ITask Interface + void ITask.Active() + { + ActiveTime = Time.time; + } + void ITask.Deactive() + { + MyOwner.OnLineDeactive(this); + } + // Implement IDraw Interface + bool IDraw.CanDraw(int Index) + { + return !IsFinished; + } + void IDraw.Draw(int Index) + { + int w = Screen.width * Size; + int h = Screen.height * Size; + float Xpos = Pivot.x + MyOffcet.x; + float Ypos = Pivot.y + MyOffcet.y + (Index * Space); + + GUIStyle style = new GUIStyle(); + Rect rect = new Rect(Xpos, Ypos, w, h * 2 / 100); + style.alignment = TextAnchor.UpperLeft; + style.fontSize = h * 2 / 100; + style.normal.textColor = Color; + GUI.Label(rect, MyMessage, style); + } + // Implement IDrawTask Interface + int IDrawTask.Priority => 0; + bool IDrawTask.IsExpired() + { + return IsFinished; + } + DrawMode IDrawTask.GetDrawMode() + { + return DrawMode.GUI; + } + + } private ILogHandler defaultLogHandler; - private PrintManager Printer; + + private List Lines = new List(10); + public Vector2 PrintPivot = Vector2.zero; + public float PrintSpace = 20; + public int PrintSize = 1; // Implement ILogHandler Interfacwe @@ -14,10 +136,9 @@ void ILogHandler.LogFormat(LogType logType, Object context, string format, param string message = string.Format(format, args); // Send message to screen system - if (Printer) - { - Printer.Print(message, logType); - } + LogLine NewLine = new LogLine(this, message, logType); + Lines.Add(NewLine); + Game.Draw(NewLine); // Still send message to Unity console if (defaultLogHandler != null) @@ -32,10 +153,9 @@ void ILogHandler.LogFormat(LogType logType, Object context, string format, param void ILogHandler.LogException(System.Exception exception, Object context) { // Send message to screen system - if (Printer) - { - Printer.Print(exception.Message, LogType.Exception); - } + LogLine NewLine = new LogLine(this, exception.Message, LogType.Exception); + Lines.Add(NewLine); + Game.Draw(NewLine); defaultLogHandler.LogException(exception, context); } @@ -46,28 +166,23 @@ protected override void OnStart(object Author) { defaultLogHandler = Debug.unityLogger.logHandler; Debug.unityLogger.logHandler = this; - CheckManager(); } protected override void OnWorldChanging(World Previous, World New) { - CheckManager(); } protected override void OnEnd(object Author) { - if (Printer != null) - { - Printer.Clear(); - } + Lines.Clear(); } - - - - - private void CheckManager() + protected override string GetDisplayInfo() { - if (Printer == null) - Printer = Game.GetManager(); + return $"{base.GetDisplayInfo()}Lines:{Lines.Count}"; } + // Methods + private void OnLineDeactive(LogLine line) + { + Lines.Remove(line); + } } } \ No newline at end of file diff --git a/Runtime/ReadySet/Services/DespawnService.cs b/Runtime/ReadySet/Services/DespawnService.cs index 5e148b4..7b55017 100644 --- a/Runtime/ReadySet/Services/DespawnService.cs +++ b/Runtime/ReadySet/Services/DespawnService.cs @@ -82,6 +82,12 @@ void IService.Deleted(object Author) { Managers.Clear(); } +#if UNITY_EDITOR + string IService.GetInspectorInfo() + { + return $"SelectedManagers:{Managers.Count}"; + } +#endif // Public Functions public void AddManager(IGameManager manager) @@ -253,16 +259,6 @@ public static bool Haptic(IHapticProvider provider, bool debug = true) } // Debug - public static bool Printer(IPrint printer, bool debug = true) - { - if (GetManager() == null) - { - if (debug) - Debug.LogWarning("Despawn PrintManager is not available."); - return false; - } - return GetManager().RemoveStatic(printer); - } public static bool Button(IButton button, bool debug = true) { if (GetManager() == null) diff --git a/Runtime/ReadySet/Services/SpawanService.cs b/Runtime/ReadySet/Services/SpawanService.cs index b41dc5d..607666f 100644 --- a/Runtime/ReadySet/Services/SpawanService.cs +++ b/Runtime/ReadySet/Services/SpawanService.cs @@ -84,6 +84,12 @@ void IService.Deleted(object Author) { Managers.Clear(); } +#if UNITY_EDITOR + string IService.GetInspectorInfo() + { + return $"SelectedManagers:{Managers.Count}"; + } +#endif // Public Functions public void AddManager(IGameManager manager) @@ -697,18 +703,6 @@ public static ICoroutineTask CoroutineTask(IEnumerator routine) } // Debug - public static IPrint Printer(Vector2 offcet) - { - if (GetManager() != null) - { - return GetManager().PrintStatic(offcet); - } - else - { - Debug.LogWarning($" {Ins}: PrintManager is not available."); - return null; - } - } public static IButton Button(Name16 Name, System.Action Callback) { if (GetManager() != null) From 5eec3d186e7d36cebbdbfd624b4bc4837e36e177 Mon Sep 17 00:00:00 2001 From: Alijimpa Date: Mon, 27 Apr 2026 09:48:45 +0330 Subject: [PATCH 148/204] Refine C# REfrence inshure alocation and deacloaction for game services --- Runtime/Core/Architecture/Game.cs | 17 +++++++++-------- Runtime/Core/Architecture/World.cs | 7 ------- Runtime/ReadySet/Essentials/DefaultGame.cs | 8 -------- Runtime/ReadySet/Services/DebugService.cs | 2 ++ 4 files changed, 11 insertions(+), 23 deletions(-) diff --git a/Runtime/Core/Architecture/Game.cs b/Runtime/Core/Architecture/Game.cs index fad438f..1ebdad5 100644 --- a/Runtime/Core/Architecture/Game.cs +++ b/Runtime/Core/Architecture/Game.cs @@ -553,7 +553,6 @@ public static bool TryGetService(out T service) where T : Service public static void ClearService() { Instance.Services.Clear(); - Instance.OnServiceCleand(); } /// /// Requests a scene load by build index . @@ -1114,13 +1113,6 @@ protected virtual bool CanChangeState(int A, int B, object author) { return true; } - /// - /// Called after GameServices clear. - /// - protected virtual void OnServiceCleand() - { - - } @@ -1155,6 +1147,15 @@ private void Notify_OnGameQuit() ClearService(); } ((IService)Bridge).Deleted(this); +#if UNITY_EDITOR + // Debug only: force GC to verify no references remain + GC.Collect(); + GC.WaitForPendingFinalizers(); + GC.Collect(); +#endif +#if UNITY_EDITOR || DEVELOPMENT_BUILD + DrawTasks.Clear(); +#endif OnGameClosed(); } diff --git a/Runtime/Core/Architecture/World.cs b/Runtime/Core/Architecture/World.cs index 1e98d24..3fac445 100644 --- a/Runtime/Core/Architecture/World.cs +++ b/Runtime/Core/Architecture/World.cs @@ -80,8 +80,6 @@ protected virtual void OnDrawGizmos() public abstract class World : MonoBehaviour { [Header("Setting")] - [SerializeField, Tooltip("Clears all registered services on Awake.")] - private bool clearServices; [SerializeField] private Prefab DefualtPlayer; @@ -145,11 +143,6 @@ private void Awake() transform.position = Vector3.zero; transform.rotation = Quaternion.identity; - if (clearServices) - { - Game.ClearService(); - } - WorldBegin(); SyncProvider.WorldIsReady(); } diff --git a/Runtime/ReadySet/Essentials/DefaultGame.cs b/Runtime/ReadySet/Essentials/DefaultGame.cs index 014568b..1be472d 100644 --- a/Runtime/ReadySet/Essentials/DefaultGame.cs +++ b/Runtime/ReadySet/Essentials/DefaultGame.cs @@ -29,13 +29,5 @@ protected override void OnGameClosed() } - - protected override void OnServiceCleand() - { -#if UNITY_EDITOR - AddService(this); -#endif - } - } } diff --git a/Runtime/ReadySet/Services/DebugService.cs b/Runtime/ReadySet/Services/DebugService.cs index 30a5042..22baeb1 100644 --- a/Runtime/ReadySet/Services/DebugService.cs +++ b/Runtime/ReadySet/Services/DebugService.cs @@ -172,6 +172,8 @@ protected override void OnWorldChanging(World Previous, World New) } protected override void OnEnd(object Author) { + if (defaultLogHandler != null) + Debug.unityLogger.logHandler = defaultLogHandler; Lines.Clear(); } protected override string GetDisplayInfo() From 69ced474c0bfc1bbfdb9c03bd88cbb011005eef9 Mon Sep 17 00:00:00 2001 From: Alijimpa Date: Tue, 28 Apr 2026 00:14:19 +0330 Subject: [PATCH 149/204] Optimizing ordering for Draw --- Runtime/Core/Architecture/Game.cs | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/Runtime/Core/Architecture/Game.cs b/Runtime/Core/Architecture/Game.cs index 1ebdad5..c6046c1 100644 --- a/Runtime/Core/Architecture/Game.cs +++ b/Runtime/Core/Architecture/Game.cs @@ -1019,7 +1019,10 @@ public static void Draw(IDrawTask element) if (element != null) { Instance.DrawTasks.Add(element); - Instance.DrawTasks.Sort((a, b) => a.Priority.CompareTo(b.Priority)); + if (element.Priority != 0) + { + Instance.DrawTasks.Sort((a, b) => a.Priority.CompareTo(b.Priority)); + } element.Active(); } } From ab9c8b61931c8ee23e66af204a2a04a44c07b7d4 Mon Sep 17 00:00:00 2001 From: Alijimpa Date: Tue, 28 Apr 2026 00:15:26 +0330 Subject: [PATCH 150/204] Implement DEveloperManager --- .../SharedScripts/Enumeration/Directions.cs | 11 + .../Enumeration/Directions.cs.meta | 2 + .../SharedScripts/Structs/StyleData.cs | 94 +++ .../SharedScripts/Structs/StyleData.cs.meta | 2 + Runtime/Pattern/Assets/DrawAsset.cs | 542 ++++++++++++++++++ Runtime/Pattern/Assets/DrawAsset.cs.meta | 2 + Runtime/Pattern/Managers/DeveloperManager.cs | 156 +++++ .../Pattern/Managers/DeveloperManager.cs.meta | 2 + Runtime/ReadySet/Managers/DevManager.cs | 19 + Runtime/ReadySet/Managers/DevManager.cs.meta | 2 + Runtime/ReadySet/Presets/DevAsset.cs | 10 + Runtime/ReadySet/Presets/DevAsset.cs.meta | 2 + 12 files changed, 844 insertions(+) create mode 100644 Runtime/Library/SharedScripts/Enumeration/Directions.cs create mode 100644 Runtime/Library/SharedScripts/Enumeration/Directions.cs.meta create mode 100644 Runtime/Library/SharedScripts/Structs/StyleData.cs create mode 100644 Runtime/Library/SharedScripts/Structs/StyleData.cs.meta create mode 100644 Runtime/Pattern/Assets/DrawAsset.cs create mode 100644 Runtime/Pattern/Assets/DrawAsset.cs.meta create mode 100644 Runtime/Pattern/Managers/DeveloperManager.cs create mode 100644 Runtime/Pattern/Managers/DeveloperManager.cs.meta create mode 100644 Runtime/ReadySet/Managers/DevManager.cs create mode 100644 Runtime/ReadySet/Managers/DevManager.cs.meta create mode 100644 Runtime/ReadySet/Presets/DevAsset.cs create mode 100644 Runtime/ReadySet/Presets/DevAsset.cs.meta diff --git a/Runtime/Library/SharedScripts/Enumeration/Directions.cs b/Runtime/Library/SharedScripts/Enumeration/Directions.cs new file mode 100644 index 0000000..9c4b533 --- /dev/null +++ b/Runtime/Library/SharedScripts/Enumeration/Directions.cs @@ -0,0 +1,11 @@ +namespace RealMethod +{ + public enum Corner + { + UpRight, + UpLeft, + DownRight, + DownLeft + } + +} \ No newline at end of file diff --git a/Runtime/Library/SharedScripts/Enumeration/Directions.cs.meta b/Runtime/Library/SharedScripts/Enumeration/Directions.cs.meta new file mode 100644 index 0000000..4e8864a --- /dev/null +++ b/Runtime/Library/SharedScripts/Enumeration/Directions.cs.meta @@ -0,0 +1,2 @@ +fileFormatVersion: 2 +guid: fdc2da0d08ac4df4fbcd39e1635572c7 \ No newline at end of file diff --git a/Runtime/Library/SharedScripts/Structs/StyleData.cs b/Runtime/Library/SharedScripts/Structs/StyleData.cs new file mode 100644 index 0000000..fce4fee --- /dev/null +++ b/Runtime/Library/SharedScripts/Structs/StyleData.cs @@ -0,0 +1,94 @@ +#if UNITY_EDITOR || DEVELOPMENT_BUILD +using UnityEngine; +namespace RealMethod +{ + [System.Serializable] + public struct GUIStyleStateData + { + public Texture2D background; + public Color textColor; + + + public void Apply(GUIStyleState state) + { + state.background = background; + state.textColor = textColor; + } + } + + [System.Serializable] + public struct GUIStyleData + { + public Font font; + public int fontSize; + public FontStyle fontStyle; + + public TextAnchor alignment; + public bool wordWrap; + public bool richText; + public bool clipping; + + public Vector2 contentOffset; + + public RectOffset padding; + public RectOffset margin; + public RectOffset border; + public RectOffset overflow; + + public float fixedWidth; + public float fixedHeight; + + public bool stretchWidth; + public bool stretchHeight; + + public GUIStyleStateData normal; + public GUIStyleStateData hover; + public GUIStyleStateData active; + public GUIStyleStateData focused; + + public GUIStyleStateData onNormal; + public GUIStyleStateData onHover; + public GUIStyleStateData onActive; + public GUIStyleStateData onFocused; + + public GUIStyle Build() + { + GUIStyle style = new GUIStyle(); + + style.font = font; + style.fontSize = fontSize; + style.fontStyle = fontStyle; + + style.alignment = alignment; + style.wordWrap = wordWrap; + style.richText = richText; + style.clipping = clipping ? TextClipping.Clip : TextClipping.Overflow; + + style.contentOffset = contentOffset; + + style.padding = padding; + style.margin = margin; + style.border = border; + style.overflow = overflow; + + style.fixedWidth = fixedWidth; + style.fixedHeight = fixedHeight; + + style.stretchWidth = stretchWidth; + style.stretchHeight = stretchHeight; + + normal.Apply(style.normal); + hover.Apply(style.hover); + active.Apply(style.active); + focused.Apply(style.focused); + + onNormal.Apply(style.onNormal); + onHover.Apply(style.onHover); + onActive.Apply(style.onActive); + onFocused.Apply(style.onFocused); + + return style; + } + } +} +#endif \ No newline at end of file diff --git a/Runtime/Library/SharedScripts/Structs/StyleData.cs.meta b/Runtime/Library/SharedScripts/Structs/StyleData.cs.meta new file mode 100644 index 0000000..940f843 --- /dev/null +++ b/Runtime/Library/SharedScripts/Structs/StyleData.cs.meta @@ -0,0 +1,2 @@ +fileFormatVersion: 2 +guid: 628530e17d7ff0340bd4e395b9615c2a \ No newline at end of file diff --git a/Runtime/Pattern/Assets/DrawAsset.cs b/Runtime/Pattern/Assets/DrawAsset.cs new file mode 100644 index 0000000..4d9fc2c --- /dev/null +++ b/Runtime/Pattern/Assets/DrawAsset.cs @@ -0,0 +1,542 @@ +#if UNITY_EDITOR || DEVELOPMENT_BUILD +using System; +using UnityEngine; +namespace RealMethod +{ + + public interface IDrawWindow + { + void OnButtonClick(Name16 ButtonName); + void OnButtonHold(Name16 ButtonName); + void OnToggleChange(Name16 ToggleName, bool Val); + Rect GetRect(Rect element, int index); + GUIStyle GetStyle(int ID); + } + + public abstract class DrawAsset : ConfigAsset, IDraw, ITask, IDrawWindow + { + public enum BuiltInGUIType + { + Label = 0, + Button = 1, + RepeatButton = 2, + Toggle = 3, + TextField = 4, + PasswordField = 5, + TextArea = 6, + HorizontalSlider = 7, + HorizontalScrollbar = 8, + VerticalSlider = 9, + VerticalScrollbar = 10, + Box = 11, + Group_Begin = 12, + Group_End = 13, + ScrollView_Begin = 14, + ScrollView_End = 15, + SelectionGrid = 16, + Clip_Begin = 17, + Clip_End = 18, + DrawTexture = 19, + Toolbar = 20, + } + + [Serializable] + private class DrawSlot : IDraw + { + private enum GUIStyleMode + { + Skin = 0, + Custom_1 = 1, + Custom_2 = 2, + Custom_3 = 3, + None = 4, + } + [Header("Info")] + public Name16 NameID; + public BuiltInGUIType GUIType; + [SerializeField] + private GUIStyleMode StyleMode; + public bool Reset = false; + public Rect Transform = Rect.zero; + [Header("Setting")] + [ConditionalShowByEnum("GUIType", BuiltInGUIType.Button, BuiltInGUIType.RepeatButton, BuiltInGUIType.Toggle, BuiltInGUIType.Box)] + public string Title; + [ConditionalShowByEnum("GUIType", BuiltInGUIType.Label, BuiltInGUIType.TextField, BuiltInGUIType.PasswordField, BuiltInGUIType.TextArea)] + public string Text; + [ConditionalShowByEnum("GUIType", BuiltInGUIType.Toggle)] + public bool Toggle; + [ConditionalShowByEnum("GUIType", BuiltInGUIType.HorizontalScrollbar, BuiltInGUIType.HorizontalSlider, BuiltInGUIType.VerticalScrollbar, BuiltInGUIType.VerticalSlider)] + public float Slider; + [ConditionalShowByEnum("GUIType", BuiltInGUIType.HorizontalSlider, BuiltInGUIType.VerticalSlider)] + public float SliderMin; + [ConditionalShowByEnum("GUIType", BuiltInGUIType.HorizontalSlider, BuiltInGUIType.VerticalSlider)] + public float SliderMax; + [ConditionalShowByEnum("GUIType", BuiltInGUIType.HorizontalScrollbar, BuiltInGUIType.VerticalScrollbar)] + public float ScrollSize; + [ConditionalShowByEnum("GUIType", BuiltInGUIType.ScrollView_Begin)] + public Vector2 scrollPos; + [ConditionalShowByEnum("GUIType", BuiltInGUIType.ScrollView_Begin)] + public Vector2 ContentSize; + [ConditionalShowByEnum("GUIType", BuiltInGUIType.SelectionGrid)] + public int SelectedIndex; + [ConditionalShowByEnum("GUIType", BuiltInGUIType.SelectionGrid, BuiltInGUIType.Toolbar)] + public string Option; + [ConditionalShowByEnum("GUIType", BuiltInGUIType.SelectionGrid)] + public int Columns; + [ConditionalShowByEnum("GUIType", BuiltInGUIType.DrawTexture)] + public Texture Texture; + + // Private Variable + private IDrawWindow window; + public bool IsActive => window != null; + + + // Implement IIdentifier Interface + Name16 IIdentifier.NameID => NameID; + // Implement IDraw Interface + bool IDraw.CanDraw(int Index) + { + if (!IsActive) + return false; + + if (string.IsNullOrEmpty(NameID)) + { + Debug.LogWarning($"[{GUIType}]: NameID Should Not be Empty"); + return false; + } + + switch (GUIType) + { + // ----------- SIMPLE TEXT ELEMENTS ----------- + case BuiltInGUIType.Label: + return !string.IsNullOrEmpty(Text); + + case BuiltInGUIType.TextField: + case BuiltInGUIType.PasswordField: + case BuiltInGUIType.TextArea: + // These can draw even if empty text + return true; + + // ----------- BUTTONS & TOGGLES ----------- + case BuiltInGUIType.Button: + case BuiltInGUIType.RepeatButton: + case BuiltInGUIType.Toggle: + case BuiltInGUIType.Toolbar: + return !string.IsNullOrEmpty(Text); + + // ----------- SLIDERS & SCROLLBARS ----------- + case BuiltInGUIType.HorizontalSlider: + case BuiltInGUIType.VerticalSlider: + case BuiltInGUIType.HorizontalScrollbar: + case BuiltInGUIType.VerticalScrollbar: + return SliderMin < SliderMax; + + // ----------- CONTAINERS ALWAYS DRAW ----------- + case BuiltInGUIType.Group_Begin: + case BuiltInGUIType.Group_End: + case BuiltInGUIType.Clip_Begin: + case BuiltInGUIType.Clip_End: + case BuiltInGUIType.ScrollView_Begin: + case BuiltInGUIType.ScrollView_End: + return true; + + // ----------- SELECTION GRID ----------- + case BuiltInGUIType.SelectionGrid: + //return Options != null && Options.Length > 0; + return string.IsNullOrEmpty(Option); + + // ----------- BOX ----------- + case BuiltInGUIType.Box: + return !string.IsNullOrEmpty(Title); + + // ----------- DRAW TEXTURE ----------- + case BuiltInGUIType.DrawTexture: + return Texture != null; + + // ----------- OTHER ----------- + + // ----------- DEFAULT (fallback) ----------- + default: + Debug.LogWarning($"Not Implement for {GUIType}"); + return false; + } + } + void IDraw.Draw(int Index) + { + Rect Position = window.GetRect(Transform, Index); + GUIStyle Style = GetStyle(); + + switch (GUIType) + { + // ---------------- BASIC CONTROLS ---------------- + case BuiltInGUIType.Label: + GUI.Label(Position, Text, Style); + break; + + case BuiltInGUIType.Button: + if (GUI.Button(Position, Title, Style)) + window.OnButtonClick(NameID); + break; + + case BuiltInGUIType.RepeatButton: + if (GUI.RepeatButton(Position, Title, Style)) + window.OnButtonHold(NameID); + break; + + case BuiltInGUIType.Toggle: + bool result = GUI.Toggle(Position, Toggle, Title, Style); + if (result != Toggle) + window.OnToggleChange(NameID, result); + Toggle = result; + break; + + case BuiltInGUIType.TextField: + Text = GUI.TextField(Position, Text, Style); + break; + + case BuiltInGUIType.PasswordField: + Text = GUI.PasswordField(Position, Text, '*', Style); + break; + + case BuiltInGUIType.TextArea: + Text = GUI.TextArea(Position, Text, Style); + break; + + // ---------------- SLIDERS / SCROLLBARS ---------------- + case BuiltInGUIType.HorizontalSlider: + Slider = GUI.HorizontalSlider(Position, Slider, SliderMin, SliderMax); + break; + + case BuiltInGUIType.VerticalSlider: + Slider = GUI.VerticalSlider(Position, Slider, SliderMin, SliderMax); + break; + + case BuiltInGUIType.HorizontalScrollbar: + Slider = GUI.HorizontalScrollbar(Position, Slider, ScrollSize, SliderMin, SliderMax); + break; + + case BuiltInGUIType.VerticalScrollbar: + Slider = GUI.VerticalScrollbar(Position, Slider, ScrollSize, SliderMin, SliderMax); + break; + + // ---------------- CONTAINERS ---------------- + case BuiltInGUIType.Box: + GUI.Box(Position, Title, Style); + break; + + case BuiltInGUIType.Group_Begin: + GUI.BeginGroup(Position, Style); + break; + + case BuiltInGUIType.Group_End: + GUI.EndGroup(); + break; + + case BuiltInGUIType.Clip_Begin: + GUI.BeginClip(Position); + break; + + case BuiltInGUIType.Clip_End: + GUI.EndClip(); + break; + + // ---------------- SCROLL VIEW ---------------- + case BuiltInGUIType.ScrollView_Begin: + scrollPos = GUI.BeginScrollView( + Position, + scrollPos, + new Rect(0, 0, ContentSize.x, ContentSize.y), + false, + true + ); + break; + + case BuiltInGUIType.ScrollView_End: + GUI.EndScrollView(); + break; + + // ---------------- COMPLEX CONTROLS ---------------- + case BuiltInGUIType.SelectionGrid: + SelectedIndex = GUI.SelectionGrid(Position, SelectedIndex, new string[1] { Option }, Columns, Style); + break; + + case BuiltInGUIType.DrawTexture: + GUI.DrawTexture(Position, Texture, ScaleMode.ScaleToFit, true); + break; + + case BuiltInGUIType.Toolbar: + SelectedIndex = GUI.Toolbar(Position, SelectedIndex, new string[1] { Option }, Style); + break; + + // ---------------- FALLBACK ---------------- + default: + Debug.LogWarning($"GUI Type {GUIType} not implemented."); + break; + } + } + + + public void Active(DrawAsset owner) + { + window = owner; + } + public void Deactive() + { + window = null; + } + public void OnValidate(int Index) + { + if (string.IsNullOrEmpty(NameID)) + NameID = Index.ToString(); + + if (Reset == true) + { + Reset = false; + Transform = GetDefaultRect(GUIType); + Title = string.Empty; + Text = string.Empty; + Toggle = false; + Slider = 0; + SliderMin = 0; + SliderMax = 1; + ScrollSize = 0.1f; + scrollPos = Vector2.zero; + ContentSize = new Vector2(500, 500); + SelectedIndex = 0; + Option = string.Empty; + Columns = 2; + Texture = null; + } + + if (SliderMax == 0) + SliderMax = 1; + if (ScrollSize == 0) + ScrollSize = 0.1f; + if (ContentSize.x == 0) + ContentSize.x = 500; + if (ContentSize.y == 0) + ContentSize.y = 500; + if (Columns == 0) + Columns = 2; + } + + private GUIStyle GetStyle() + { + switch (StyleMode) + { + case GUIStyleMode.Skin: + switch (GUIType) + { + case BuiltInGUIType.Label: return GUI.skin.label; + case BuiltInGUIType.Box: return GUI.skin.box; + case BuiltInGUIType.Button: return GUI.skin.button; + case BuiltInGUIType.Toggle: return GUI.skin.toggle; + case BuiltInGUIType.TextField: return GUI.skin.textField; + case BuiltInGUIType.TextArea: return GUI.skin.textArea; + case BuiltInGUIType.HorizontalSlider: return GUI.skin.horizontalSlider; + case BuiltInGUIType.VerticalSlider: return GUI.skin.verticalSlider; + case BuiltInGUIType.HorizontalScrollbar: return GUI.skin.horizontalScrollbar; + case BuiltInGUIType.VerticalScrollbar: return GUI.skin.verticalScrollbar; + case BuiltInGUIType.ScrollView_Begin: return GUI.skin.scrollView; + default: return GUI.skin.label; + } + case GUIStyleMode.Custom_1: + return window.GetStyle(1); + case GUIStyleMode.Custom_2: + return window.GetStyle(2); + case GUIStyleMode.Custom_3: + return window.GetStyle(3); + case GUIStyleMode.None: + return new GUIStyle(); + default: + return null; + } + } + public static Rect GetDefaultRect(BuiltInGUIType type) + { + switch (type) + { + // -------- TEXT / BASIC -------- + case BuiltInGUIType.Label: + return new Rect(10, 10, 120, 20); + + case BuiltInGUIType.Button: + case BuiltInGUIType.RepeatButton: + case BuiltInGUIType.Toggle: + return new Rect(10, 10, 120, 25); + + case BuiltInGUIType.TextField: + case BuiltInGUIType.PasswordField: + return new Rect(10, 10, 160, 22); + + case BuiltInGUIType.TextArea: + return new Rect(10, 10, 200, 80); + + // -------- SLIDERS -------- + case BuiltInGUIType.HorizontalSlider: + return new Rect(10, 10, 200, 20); + + case BuiltInGUIType.VerticalSlider: + return new Rect(10, 10, 20, 200); + + // -------- SCROLLBARS -------- + case BuiltInGUIType.HorizontalScrollbar: + return new Rect(10, 10, 200, 18); + + case BuiltInGUIType.VerticalScrollbar: + return new Rect(10, 10, 18, 200); + + // -------- CONTAINERS -------- + case BuiltInGUIType.Box: + return new Rect(10, 10, 200, 100); + + case BuiltInGUIType.Group_Begin: + return new Rect(10, 10, 300, 200); + + case BuiltInGUIType.Group_End: + return Rect.zero; + + case BuiltInGUIType.ScrollView_Begin: + return new Rect(10, 10, 300, 200); + + case BuiltInGUIType.ScrollView_End: + return Rect.zero; + + case BuiltInGUIType.Clip_Begin: + return new Rect(10, 10, 200, 150); + + case BuiltInGUIType.Clip_End: + return Rect.zero; + + // -------- COMPLEX CONTROLS -------- + case BuiltInGUIType.SelectionGrid: + return new Rect(10, 10, 250, 100); + + case BuiltInGUIType.Toolbar: + return new Rect(10, 10, 250, 25); + + // -------- TEXTURE -------- + case BuiltInGUIType.DrawTexture: + return new Rect(10, 10, 128, 128); + + default: + return new Rect(10, 10, 100, 25); + } + } + + + } + + + [Header("Window")] + [SerializeField] + private bool WindowsForm = true; + [SerializeField, ConditionalHide("WindowsForm", true, false)] + private string Text = "Window"; + [SerializeField, ConditionalHide("WindowsForm", true, false)] + private Rect Position = new Rect(150, 50, 250, 150); + [SerializeField, ConditionalHide("WindowsForm", true, false)] + private Rect DragSpace = new Rect(0, 0, Screen.width, Screen.height); + [Header("Rendering")] + [SerializeField] + private GUIStyleData CustomStyle_1; + [SerializeField] + private GUIStyleData CustomStyle_2; + [SerializeField] + private GUIStyleData CustomStyle_3; + [Header("Items")] + [SerializeField] + private DrawSlot[] DrawItems; + + + // Implement ITask Interface + void ITask.Active() + { + foreach (var item in DrawItems) + { + item.Active(this); + } + } + void ITask.Deactive() + { + foreach (var item in DrawItems) + { + item.Deactive(); + } + } + // Implement IDraw Interface + bool IDraw.CanDraw(int Index) + { + return DrawItems != null && DrawItems.Length > 0; + } + void IDraw.Draw(int Index) + { + if (WindowsForm) + { + Position = GUI.Window(Index, Position, OnWindowsDraw, Text); + } + else + { + Drawing(); + } + } + // Implement IDrawWindow Interface + void IDrawWindow.OnButtonClick(Name16 ButtonName) + { + + } + void IDrawWindow.OnButtonHold(Name16 ButtonName) + { + throw new NotImplementedException(); + } + void IDrawWindow.OnToggleChange(Name16 ToggleName, bool Val) + { + throw new NotImplementedException(); + } + Rect IDrawWindow.GetRect(Rect element, int index) + { + return element; + //return new Rect(Position.x + element.x, Position.y + element.y, element.width, element.height); + } + GUIStyle IDrawWindow.GetStyle(int ID) + { + if (ID == 1) + return CustomStyle_1.Build(); + if (ID == 1) + return CustomStyle_2.Build(); + if (ID == 1) + return CustomStyle_3.Build(); + + Debug.LogWarning($"Din't implement any Style for ID: {ID}"); + return null; + } + + // Unity Method + private void OnValidate() + { + for (int i = 0; i < DrawItems.Length; i++) + { + DrawItems[i].OnValidate(i); + } + } + + // Methods + private void Drawing() + { + for (int i = 0; i < DrawItems.Length; i++) + { + IDraw provider = DrawItems[i]; + if (provider.CanDraw(i)) + provider.Draw(i); + } + } + private void OnWindowsDraw(int id) + { + Drawing(); + GUI.DragWindow(DragSpace); + } + } + + +} +#endif \ No newline at end of file diff --git a/Runtime/Pattern/Assets/DrawAsset.cs.meta b/Runtime/Pattern/Assets/DrawAsset.cs.meta new file mode 100644 index 0000000..4e988a6 --- /dev/null +++ b/Runtime/Pattern/Assets/DrawAsset.cs.meta @@ -0,0 +1,2 @@ +fileFormatVersion: 2 +guid: 56f5ca6bda2e55547b50df8a3e272ffe \ No newline at end of file diff --git a/Runtime/Pattern/Managers/DeveloperManager.cs b/Runtime/Pattern/Managers/DeveloperManager.cs new file mode 100644 index 0000000..d5c9d57 --- /dev/null +++ b/Runtime/Pattern/Managers/DeveloperManager.cs @@ -0,0 +1,156 @@ +#if UNITY_EDITOR || DEVELOPMENT_BUILD +using UnityEngine; + +namespace RealMethod +{ + public abstract class DeveloperManager : MonoBehaviour, IGameManager + { + private enum VisiblityModes + { + [DescriptionEnum("WindowsAsset Draw in screen just with OnEnable & OnDisable Component")] + None, + [DescriptionEnum("WindowsAsset Draw in screen with Open() & Close() Functions")] + Manually, + [DescriptionEnum("WindowsAsset Draw in screen with Open & Close Button in Game")] + UI, + [DescriptionEnum("WindowsAsset Draw in screen with [~] Button(Toggle) in Keyboard")] + Input, + } + [Header("Developer")] + [SerializeField] + private Map WindowsAsset = new Map(); + [Header("Setting")] + [SerializeField] + private VisiblityModes ControlMode; + [SerializeField, ConditionalShowByEnum("ControlMode", VisiblityModes.UI)] + private Corner ButtonPosition = Corner.UpRight; + [SerializeField, ConditionalShowByEnum("ControlMode", VisiblityModes.UI)] + private Vector2 Scale = new Vector2(50, 30); + [SerializeField, ConditionalShowByEnum("ControlMode", VisiblityModes.UI)] + private float margin = 0.8f; + + public bool IsOpen { get; private set; } = true; + public Rect ButtonRect => RM_GUI.GetButtonRect(ButtonPosition, Scale.x, Scale.y, margin); + + + + // Implement IGameManager Interface + MonoBehaviour IGameManager.GetManagerClass() + { + return this; + } + void IGameManager.InitiateManager(bool AlwaysLoaded) + { + InitiateManager(AlwaysLoaded); + } + void IGameManager.ResolveService(Service service, bool active) + { + ResolveService(service); + } + + + // Unity Methods + private void OnEnable() + { + foreach (var Asset in WindowsAsset) + { + ((ITask)Asset.Key).Active(); + } + } + private void OnGUI() + { + if (IsOpen) + { + if (ControlMode == VisiblityModes.UI) + { + if (GUI.Button(ButtonRect, "Close")) + { + Close(); + } + } + + + for (int i = 0; i < WindowsAsset.Count; i++) + { + if (WindowsAsset.GetValue(i) == false) + continue; + + IDraw task = WindowsAsset.GetKey(i); + + if (task == null) + { + WindowsAsset.Remove(i); + continue; + } + + if (task.CanDraw(i)) + task.Draw(i); + } + } + else + { + if (ControlMode == VisiblityModes.UI) + { + if (GUI.Button(ButtonRect, "Open")) + { + Open(); + } + } + } + } + private void OnDisable() + { + foreach (var Asset in WindowsAsset) + { + ((ITask)Asset.Key).Deactive(); + } + } + + // Functions + public void Add(DrawAsset asset) + { + if (asset == null) + { + Debug.LogWarning("Can't Add Asset, in not valid!"); + return; + } + WindowsAsset.Add(asset, true); + ((ITask)asset).Active(); + } + public bool Remove(DrawAsset asset) + { + for (int i = 0; i < WindowsAsset.Count; i++) + { + DrawAsset target = WindowsAsset.GetKey(i); + if (target == asset) + { + ((ITask)target).Deactive(); + return WindowsAsset.Remove(target); + } + } + return false; + } + [Button] + public void Open() + { + if (ControlMode == VisiblityModes.None) + return; + IsOpen = true; + } + [Button] + public void Close() + { + if (ControlMode == VisiblityModes.None) + return; + IsOpen = false; + } + + + // Abstract Methods + protected abstract void InitiateManager(bool alwaysLoaded); + protected abstract void ResolveService(Service service); + } + + +} +#endif \ No newline at end of file diff --git a/Runtime/Pattern/Managers/DeveloperManager.cs.meta b/Runtime/Pattern/Managers/DeveloperManager.cs.meta new file mode 100644 index 0000000..6d99974 --- /dev/null +++ b/Runtime/Pattern/Managers/DeveloperManager.cs.meta @@ -0,0 +1,2 @@ +fileFormatVersion: 2 +guid: 60721334d77f6f8478942a48479f8cfc \ No newline at end of file diff --git a/Runtime/ReadySet/Managers/DevManager.cs b/Runtime/ReadySet/Managers/DevManager.cs new file mode 100644 index 0000000..b0216af --- /dev/null +++ b/Runtime/ReadySet/Managers/DevManager.cs @@ -0,0 +1,19 @@ +#if UNITY_EDITOR || DEVELOPMENT_BUILD +using UnityEngine; + +namespace RealMethod +{ + [AddComponentMenu("RealMethod/Manager/DeveloperManager")] + public class DevManager : DeveloperManager + { + + // DeveloperManager Methods + protected override void InitiateManager(bool alwaysLoaded) + { + } + protected override void ResolveService(Service service) + { + } + } +} +#endif \ No newline at end of file diff --git a/Runtime/ReadySet/Managers/DevManager.cs.meta b/Runtime/ReadySet/Managers/DevManager.cs.meta new file mode 100644 index 0000000..82c30f3 --- /dev/null +++ b/Runtime/ReadySet/Managers/DevManager.cs.meta @@ -0,0 +1,2 @@ +fileFormatVersion: 2 +guid: ab9dc0e8c357282459cab65d10fb9e49 \ No newline at end of file diff --git a/Runtime/ReadySet/Presets/DevAsset.cs b/Runtime/ReadySet/Presets/DevAsset.cs new file mode 100644 index 0000000..01dc109 --- /dev/null +++ b/Runtime/ReadySet/Presets/DevAsset.cs @@ -0,0 +1,10 @@ +using UnityEngine; + +namespace RealMethod +{ + [CreateAssetMenu(fileName = "Dev", menuName = "RealMethod/Develop/Dev", order = 1)] + public class DevAsset : DrawAsset + { + + } +} \ No newline at end of file diff --git a/Runtime/ReadySet/Presets/DevAsset.cs.meta b/Runtime/ReadySet/Presets/DevAsset.cs.meta new file mode 100644 index 0000000..8d89347 --- /dev/null +++ b/Runtime/ReadySet/Presets/DevAsset.cs.meta @@ -0,0 +1,2 @@ +fileFormatVersion: 2 +guid: cfe184d5f05c3b4489c49c11fd28f8ac \ No newline at end of file From 1b78403e302836637863666d841745bf61465911 Mon Sep 17 00:00:00 2001 From: Alijimpa Date: Tue, 28 Apr 2026 00:15:43 +0330 Subject: [PATCH 151/204] Implement GUI Library --- Runtime/Library/Utilities/GUILibrary.cs | 41 ++++++++++++++++++++ Runtime/Library/Utilities/GUILibrary.cs.meta | 2 + 2 files changed, 43 insertions(+) create mode 100644 Runtime/Library/Utilities/GUILibrary.cs create mode 100644 Runtime/Library/Utilities/GUILibrary.cs.meta diff --git a/Runtime/Library/Utilities/GUILibrary.cs b/Runtime/Library/Utilities/GUILibrary.cs new file mode 100644 index 0000000..e2610be --- /dev/null +++ b/Runtime/Library/Utilities/GUILibrary.cs @@ -0,0 +1,41 @@ +#if UNITY_EDITOR || DEVELOPMENT_BUILD +using UnityEngine; + +namespace RealMethod +{ + public static class RM_GUI + { + public static Rect GetButtonRect(Corner corner, float width, float height, float margin = 10f) + { + float x = 0; + float y = 0; + + switch (corner) + { + case Corner.UpLeft: + x = margin; + y = margin; + break; + + case Corner.UpRight: + x = Screen.width - width - margin; + y = margin; + break; + + case Corner.DownLeft: + x = margin; + y = Screen.height - height - margin; + break; + + case Corner.DownRight: + x = Screen.width - width - margin; + y = Screen.height - height - margin; + break; + } + + return new Rect(x, y, width, height); + } + } + +} +#endif \ No newline at end of file diff --git a/Runtime/Library/Utilities/GUILibrary.cs.meta b/Runtime/Library/Utilities/GUILibrary.cs.meta new file mode 100644 index 0000000..6495254 --- /dev/null +++ b/Runtime/Library/Utilities/GUILibrary.cs.meta @@ -0,0 +1,2 @@ +fileFormatVersion: 2 +guid: cb062f936e2190e4eb17ab7cbb030eaf \ No newline at end of file From a51ee21ac1449dd3313a1b060c20c0c6147c6841 Mon Sep 17 00:00:00 2001 From: Alijimpa Date: Tue, 28 Apr 2026 00:24:55 +0330 Subject: [PATCH 152/204] Rename GUIAssets --- Runtime/Pattern/Assets/{DrawAsset.cs => GUIAsset.cs} | 4 ++-- .../Assets/{DrawAsset.cs.meta => GUIAsset.cs.meta} | 0 Runtime/ReadySet/Presets/DevAsset.cs | 10 ---------- Runtime/ReadySet/Presets/DrawAsset.cs | 10 ++++++++++ .../Presets/{DevAsset.cs.meta => DrawAsset.cs.meta} | 0 5 files changed, 12 insertions(+), 12 deletions(-) rename Runtime/Pattern/Assets/{DrawAsset.cs => GUIAsset.cs} (99%) rename Runtime/Pattern/Assets/{DrawAsset.cs.meta => GUIAsset.cs.meta} (100%) delete mode 100644 Runtime/ReadySet/Presets/DevAsset.cs create mode 100644 Runtime/ReadySet/Presets/DrawAsset.cs rename Runtime/ReadySet/Presets/{DevAsset.cs.meta => DrawAsset.cs.meta} (100%) diff --git a/Runtime/Pattern/Assets/DrawAsset.cs b/Runtime/Pattern/Assets/GUIAsset.cs similarity index 99% rename from Runtime/Pattern/Assets/DrawAsset.cs rename to Runtime/Pattern/Assets/GUIAsset.cs index 4d9fc2c..f23126d 100644 --- a/Runtime/Pattern/Assets/DrawAsset.cs +++ b/Runtime/Pattern/Assets/GUIAsset.cs @@ -13,7 +13,7 @@ public interface IDrawWindow GUIStyle GetStyle(int ID); } - public abstract class DrawAsset : ConfigAsset, IDraw, ITask, IDrawWindow + public abstract class GUIAsset : UniqueAsset, IDraw, ITask, IDrawWindow { public enum BuiltInGUIType { @@ -276,7 +276,7 @@ void IDraw.Draw(int Index) } - public void Active(DrawAsset owner) + public void Active(GUIAsset owner) { window = owner; } diff --git a/Runtime/Pattern/Assets/DrawAsset.cs.meta b/Runtime/Pattern/Assets/GUIAsset.cs.meta similarity index 100% rename from Runtime/Pattern/Assets/DrawAsset.cs.meta rename to Runtime/Pattern/Assets/GUIAsset.cs.meta diff --git a/Runtime/ReadySet/Presets/DevAsset.cs b/Runtime/ReadySet/Presets/DevAsset.cs deleted file mode 100644 index 01dc109..0000000 --- a/Runtime/ReadySet/Presets/DevAsset.cs +++ /dev/null @@ -1,10 +0,0 @@ -using UnityEngine; - -namespace RealMethod -{ - [CreateAssetMenu(fileName = "Dev", menuName = "RealMethod/Develop/Dev", order = 1)] - public class DevAsset : DrawAsset - { - - } -} \ No newline at end of file diff --git a/Runtime/ReadySet/Presets/DrawAsset.cs b/Runtime/ReadySet/Presets/DrawAsset.cs new file mode 100644 index 0000000..602f9f9 --- /dev/null +++ b/Runtime/ReadySet/Presets/DrawAsset.cs @@ -0,0 +1,10 @@ +using UnityEngine; + +namespace RealMethod +{ + [CreateAssetMenu(fileName = "Draw", menuName = "RealMethod/Develop/DrawAsset", order = 1)] + public class DrawAsset : GUIAsset + { + + } +} \ No newline at end of file diff --git a/Runtime/ReadySet/Presets/DevAsset.cs.meta b/Runtime/ReadySet/Presets/DrawAsset.cs.meta similarity index 100% rename from Runtime/ReadySet/Presets/DevAsset.cs.meta rename to Runtime/ReadySet/Presets/DrawAsset.cs.meta From c1dff84535a7a4b1fb40b540f9e589d83951eaf5 Mon Sep 17 00:00:00 2001 From: Alijimpa Date: Tue, 28 Apr 2026 00:25:29 +0330 Subject: [PATCH 153/204] ReScale Debug Print Log --- Runtime/Library/Utilities/GizmosLibrary.cs | 7 ++-- Runtime/ReadySet/Managers/DebugManager.cs | 38 +++++++++++----------- 2 files changed, 23 insertions(+), 22 deletions(-) diff --git a/Runtime/Library/Utilities/GizmosLibrary.cs b/Runtime/Library/Utilities/GizmosLibrary.cs index 964809a..58038dd 100644 --- a/Runtime/Library/Utilities/GizmosLibrary.cs +++ b/Runtime/Library/Utilities/GizmosLibrary.cs @@ -1,3 +1,4 @@ +#if UNITY_EDITOR using UnityEngine; using UnityEditor; @@ -84,7 +85,7 @@ public static void Capsule(Vector3 position, Color color, float height = 2f, flo // Restore previous color Gizmos.color = prevColor; } -#if UNITY_EDITOR + // Draw a Text using Gizmos (With Colort) public static void Text(string text, Vector3 position, Color color, FontStyle font = FontStyle.Bold, TextAnchor ancher = TextAnchor.MiddleCenter) { @@ -97,6 +98,6 @@ public static void Text(string text, Vector3 position, Color color, FontStyle fo // Draw the label above the GameObject Handles.Label(position, text, style); } -#endif } -} \ No newline at end of file +} +#endif \ No newline at end of file diff --git a/Runtime/ReadySet/Managers/DebugManager.cs b/Runtime/ReadySet/Managers/DebugManager.cs index e42ca00..f059648 100644 --- a/Runtime/ReadySet/Managers/DebugManager.cs +++ b/Runtime/ReadySet/Managers/DebugManager.cs @@ -49,7 +49,7 @@ bool IDrawWorkaround.Start(IGameManager Manager) } else { - Debug.LogWarning($"LogData can't created the start manager should be {typeof(PrintManager)}"); + Debug.LogWarning($"LogData can't created the start manager should be {typeof(DebugManager)}"); return false; } } @@ -109,7 +109,7 @@ public void Draw(int Index) } [AddComponentMenu("RealMethod/Manager/DebugManager")] - public class DebugManager : GUIManager + public class DebugManager : MonoBehaviour { [Header("Debug Button")] public Vector2 ScrollPosition = Vector2.zero; @@ -122,37 +122,37 @@ public class DebugManager : GUIManager #endif // GUIManager Methods - public override void InitiateManager(bool AlwaysLoaded) - { - Pivot = new Vector2(0, 50); - } - public override void ResolveService(Service service, bool active) - { - } + // public override void InitiateManager(bool AlwaysLoaded) + // { + // Pivot = new Vector2(0, 50); + // } + // public override void ResolveService(Service service, bool active) + // { + // } public IButton AddButton(Name16 ButtonName, Action Callback) { var Result = new ButtonData(ButtonName, Callback); - ((IDrawWorkaround)Result).Start(this); - Add(Result); + //((IDrawWorkaround)Result).Start(this); + //Add(Result); return Result; } public bool Remove(IButton button) { - var result = Find(button); - ((IDrawWorkaround)result).End(); - return DrawList.Remove(result); + // var result = Find(button); + //((IDrawWorkaround)result).End(); + return false;//DrawList.Remove(result); } #if UNITY_EDITOR || DEVELOPMENT_BUILD - protected override void PreDraw() + protected void PreDraw() { - base.PreDraw(); + //base.PreDraw(); RectOffset padding = GUI.skin.button.padding; RectOffset margin = GUI.skin.button.margin; // TODO: The height calculation should be done more correctly. - Rect viewRect = new Rect(0, 0, buttonSize.x, ((buttonSize.y + (padding.vertical + margin.vertical)) * Count) - buttonSize.y); + Rect viewRect = new Rect(0, 0, buttonSize.x, ((buttonSize.y + (padding.vertical + margin.vertical)) * 000) - buttonSize.y); ScrollPosition = GUI.BeginScrollView( position: new Rect(Screen.width - buttonSize.x - buttonMargin, 10, buttonSize.x + buttonMargin, Screen.height - 10), @@ -161,9 +161,9 @@ protected override void PreDraw() alwaysShowHorizontal: false, alwaysShowVertical: false); } - protected override void PostDraw() + protected void PostDraw() { - base.PostDraw(); + //base.PostDraw(); GUI.EndScrollView(); } #endif From 0104ebe8472ec09da24315fbd6674de552065504 Mon Sep 17 00:00:00 2001 From: Alijimpa Date: Tue, 28 Apr 2026 13:01:00 +0330 Subject: [PATCH 154/204] Set Seald for all Attribute --- Runtime/Core/Attributes/AssetInlinAttribute.cs | 2 +- Runtime/Core/Attributes/ButtonAttribute.cs | 2 +- Runtime/Core/Attributes/ColorFieldAttribute.cs | 2 +- Runtime/Core/Attributes/ConditionalHideAttribute.cs | 2 +- Runtime/Core/Attributes/ConditionalHideByEnumAttribute.cs | 2 +- Runtime/Core/Attributes/ConditionalShowByEnumAttribute.cs | 2 +- Runtime/Core/Attributes/DescriptionEnumAttribute.cs | 2 +- Runtime/Core/Attributes/DropdownAttribute.cs | 2 +- Runtime/Core/Attributes/DropdownFromArrayAttribute.cs | 2 +- Runtime/Core/Attributes/DropdownFromDictionaryAttribute.cs | 2 +- Runtime/Core/Attributes/HelpBoxAttribute.cs | 2 +- Runtime/Core/Attributes/LayerAttribute.cs | 2 +- Runtime/Core/Attributes/LineAttribute.cs | 2 +- Runtime/Core/Attributes/MinMaxRangeAttribute.cs | 2 +- Runtime/Core/Attributes/PopupListAttribute.cs | 2 +- Runtime/Core/Attributes/ReadOnlyAttribute.cs | 2 +- Runtime/Core/Attributes/ShowOnlyAttribute.cs | 2 +- Runtime/Core/Attributes/TagSelectorAttribute.cs | 2 +- Runtime/Core/Attributes/TypeSelectorAttribute.cs | 2 +- 19 files changed, 19 insertions(+), 19 deletions(-) diff --git a/Runtime/Core/Attributes/AssetInlinAttribute.cs b/Runtime/Core/Attributes/AssetInlinAttribute.cs index 50765c7..a4d22db 100644 --- a/Runtime/Core/Attributes/AssetInlinAttribute.cs +++ b/Runtime/Core/Attributes/AssetInlinAttribute.cs @@ -10,7 +10,7 @@ namespace RealMethod /// public ScriptableObject TEST; /// /// - public class AssetInlinAttribute : PropertyAttribute + public sealed class AssetInlinAttribute : PropertyAttribute { public AssetInlinAttribute() { diff --git a/Runtime/Core/Attributes/ButtonAttribute.cs b/Runtime/Core/Attributes/ButtonAttribute.cs index 2b7f3e4..cde42af 100644 --- a/Runtime/Core/Attributes/ButtonAttribute.cs +++ b/Runtime/Core/Attributes/ButtonAttribute.cs @@ -12,7 +12,7 @@ namespace RealMethod /// /// [AttributeUsage(AttributeTargets.Method, Inherited = true)] - public class ButtonAttribute : Attribute { } + public sealed class ButtonAttribute : Attribute { } } diff --git a/Runtime/Core/Attributes/ColorFieldAttribute.cs b/Runtime/Core/Attributes/ColorFieldAttribute.cs index ae07f61..99c7527 100644 --- a/Runtime/Core/Attributes/ColorFieldAttribute.cs +++ b/Runtime/Core/Attributes/ColorFieldAttribute.cs @@ -7,7 +7,7 @@ namespace RealMethod /// public GameObject Target; /// /// - public class ColorFieldAttribute : PropertyAttribute + public sealed class ColorFieldAttribute : PropertyAttribute { public Color color = Color.blue; diff --git a/Runtime/Core/Attributes/ConditionalHideAttribute.cs b/Runtime/Core/Attributes/ConditionalHideAttribute.cs index b6571bc..0955a31 100644 --- a/Runtime/Core/Attributes/ConditionalHideAttribute.cs +++ b/Runtime/Core/Attributes/ConditionalHideAttribute.cs @@ -10,7 +10,7 @@ namespace RealMethod /// /// conditionalSourceField,hideInInspector, reverceCondition /// - public class ConditionalHideAttribute : PropertyAttribute + public sealed class ConditionalHideAttribute : PropertyAttribute { public string ConditionalSourceField; public bool HideInInspector; diff --git a/Runtime/Core/Attributes/ConditionalHideByEnumAttribute.cs b/Runtime/Core/Attributes/ConditionalHideByEnumAttribute.cs index 8276351..dce0594 100644 --- a/Runtime/Core/Attributes/ConditionalHideByEnumAttribute.cs +++ b/Runtime/Core/Attributes/ConditionalHideByEnumAttribute.cs @@ -19,7 +19,7 @@ namespace RealMethod /// public int hideOnlyForOption2; /// /// - public class ConditionalHideByEnumAttribute : PropertyAttribute + public sealed class ConditionalHideByEnumAttribute : PropertyAttribute { public string EnumFieldName; public object[] HideValues; diff --git a/Runtime/Core/Attributes/ConditionalShowByEnumAttribute.cs b/Runtime/Core/Attributes/ConditionalShowByEnumAttribute.cs index 1b8a7dc..304d1b6 100644 --- a/Runtime/Core/Attributes/ConditionalShowByEnumAttribute.cs +++ b/Runtime/Core/Attributes/ConditionalShowByEnumAttribute.cs @@ -20,7 +20,7 @@ namespace RealMethod /// /// [AttributeUsage(AttributeTargets.Field, AllowMultiple = false)] - public class ConditionalShowByEnumAttribute : PropertyAttribute + public sealed class ConditionalShowByEnumAttribute : PropertyAttribute { public string EnumFieldName { get; } public object[] ShowValues { get; } diff --git a/Runtime/Core/Attributes/DescriptionEnumAttribute.cs b/Runtime/Core/Attributes/DescriptionEnumAttribute.cs index 90228a4..a545a23 100644 --- a/Runtime/Core/Attributes/DescriptionEnumAttribute.cs +++ b/Runtime/Core/Attributes/DescriptionEnumAttribute.cs @@ -18,7 +18,7 @@ namespace RealMethod /// /// [AttributeUsage(AttributeTargets.Field, AllowMultiple = false)] - public class DescriptionEnumAttribute : PropertyAttribute + public sealed class DescriptionEnumAttribute : PropertyAttribute { public string Description { get; } public DescriptionEnumAttribute(string description) diff --git a/Runtime/Core/Attributes/DropdownAttribute.cs b/Runtime/Core/Attributes/DropdownAttribute.cs index fb2d402..62ca529 100644 --- a/Runtime/Core/Attributes/DropdownAttribute.cs +++ b/Runtime/Core/Attributes/DropdownAttribute.cs @@ -12,7 +12,7 @@ namespace RealMethod /// public int selectedOptionIndex; /// /// - public class DropdownAttribute : PropertyAttribute + public sealed class DropdownAttribute : PropertyAttribute { public string[] options; diff --git a/Runtime/Core/Attributes/DropdownFromArrayAttribute.cs b/Runtime/Core/Attributes/DropdownFromArrayAttribute.cs index c230306..55c5be0 100644 --- a/Runtime/Core/Attributes/DropdownFromArrayAttribute.cs +++ b/Runtime/Core/Attributes/DropdownFromArrayAttribute.cs @@ -10,7 +10,7 @@ namespace RealMethod /// public string selectedOption; /// /// - public class DropdownFromArrayAttribute : PropertyAttribute + public sealed class DropdownFromArrayAttribute : PropertyAttribute { public string TargetArray; public DropdownFromArrayAttribute(string array) diff --git a/Runtime/Core/Attributes/DropdownFromDictionaryAttribute.cs b/Runtime/Core/Attributes/DropdownFromDictionaryAttribute.cs index cf06e7f..4b3794b 100644 --- a/Runtime/Core/Attributes/DropdownFromDictionaryAttribute.cs +++ b/Runtime/Core/Attributes/DropdownFromDictionaryAttribute.cs @@ -15,7 +15,7 @@ namespace RealMethod /// public string selectedOption; /// /// - public class DropdownFromDictionaryAttribute : PropertyAttribute + public sealed class DropdownFromDictionaryAttribute : PropertyAttribute { public string dictionaryFieldName; public DropdownFromDictionaryAttribute(string dictionaryFieldName) diff --git a/Runtime/Core/Attributes/HelpBoxAttribute.cs b/Runtime/Core/Attributes/HelpBoxAttribute.cs index c73ce8b..6c54159 100644 --- a/Runtime/Core/Attributes/HelpBoxAttribute.cs +++ b/Runtime/Core/Attributes/HelpBoxAttribute.cs @@ -10,7 +10,7 @@ namespace RealMethod /// /// {0:None,1:Info,2:Warning,3:Error} /// - public class HelpBoxAttribute : PropertyAttribute + public sealed class HelpBoxAttribute : PropertyAttribute { public string text; public int messageType; diff --git a/Runtime/Core/Attributes/LayerAttribute.cs b/Runtime/Core/Attributes/LayerAttribute.cs index a2630dc..01b8b6b 100644 --- a/Runtime/Core/Attributes/LayerAttribute.cs +++ b/Runtime/Core/Attributes/LayerAttribute.cs @@ -9,7 +9,7 @@ namespace RealMethod /// public int layer; /// /// - public class LayerAttribute : PropertyAttribute + public sealed class LayerAttribute : PropertyAttribute { } diff --git a/Runtime/Core/Attributes/LineAttribute.cs b/Runtime/Core/Attributes/LineAttribute.cs index b7d07aa..d3c3df2 100644 --- a/Runtime/Core/Attributes/LineAttribute.cs +++ b/Runtime/Core/Attributes/LineAttribute.cs @@ -3,7 +3,7 @@ namespace RealMethod { [System.AttributeUsage(System.AttributeTargets.Field, AllowMultiple = true)] - public class LineAttribute : PropertyAttribute + public sealed class LineAttribute : PropertyAttribute { public readonly float Height; public readonly float Spacing; diff --git a/Runtime/Core/Attributes/MinMaxRangeAttribute.cs b/Runtime/Core/Attributes/MinMaxRangeAttribute.cs index dde4157..312cb44 100644 --- a/Runtime/Core/Attributes/MinMaxRangeAttribute.cs +++ b/Runtime/Core/Attributes/MinMaxRangeAttribute.cs @@ -8,7 +8,7 @@ namespace RealMethod /// public Vector2 myRange; /// /// - public class MinMaxRangeAttribute : PropertyAttribute + public sealed class MinMaxRangeAttribute : PropertyAttribute { public float minLimit; public float maxLimit; diff --git a/Runtime/Core/Attributes/PopupListAttribute.cs b/Runtime/Core/Attributes/PopupListAttribute.cs index de97206..c41c20e 100644 --- a/Runtime/Core/Attributes/PopupListAttribute.cs +++ b/Runtime/Core/Attributes/PopupListAttribute.cs @@ -13,7 +13,7 @@ namespace RealMethod /// public string selectedOption; /// /// - public class PopupListAttribute : PropertyAttribute + public sealed class PopupListAttribute : PropertyAttribute { public Type myType; public string propertyName; diff --git a/Runtime/Core/Attributes/ReadOnlyAttribute.cs b/Runtime/Core/Attributes/ReadOnlyAttribute.cs index 9b45d53..66b001c 100644 --- a/Runtime/Core/Attributes/ReadOnlyAttribute.cs +++ b/Runtime/Core/Attributes/ReadOnlyAttribute.cs @@ -8,5 +8,5 @@ namespace RealMethod /// public int readOnlyValue = 42; /// /// - public class ReadOnlyAttribute : PropertyAttribute { } + public sealed class ReadOnlyAttribute : PropertyAttribute { } } \ No newline at end of file diff --git a/Runtime/Core/Attributes/ShowOnlyAttribute.cs b/Runtime/Core/Attributes/ShowOnlyAttribute.cs index 202c322..03fa8e7 100644 --- a/Runtime/Core/Attributes/ShowOnlyAttribute.cs +++ b/Runtime/Core/Attributes/ShowOnlyAttribute.cs @@ -17,7 +17,7 @@ namespace RealMethod /// bool ddd = true; /// /// - public class ShowOnlyAttribute : PropertyAttribute + public sealed class ShowOnlyAttribute : PropertyAttribute { } } \ No newline at end of file diff --git a/Runtime/Core/Attributes/TagSelectorAttribute.cs b/Runtime/Core/Attributes/TagSelectorAttribute.cs index d004af9..0d9a288 100644 --- a/Runtime/Core/Attributes/TagSelectorAttribute.cs +++ b/Runtime/Core/Attributes/TagSelectorAttribute.cs @@ -7,7 +7,7 @@ namespace RealMethod /// [TagSelector] /// /// - public class TagSelectorAttribute : PropertyAttribute + public sealed class TagSelectorAttribute : PropertyAttribute { public bool UseDefaultTagFieldDrawer = false; } diff --git a/Runtime/Core/Attributes/TypeSelectorAttribute.cs b/Runtime/Core/Attributes/TypeSelectorAttribute.cs index b74d4db..b1389c7 100644 --- a/Runtime/Core/Attributes/TypeSelectorAttribute.cs +++ b/Runtime/Core/Attributes/TypeSelectorAttribute.cs @@ -10,7 +10,7 @@ namespace RealMethod { - public class TypeSelectorAttribute : PropertyAttribute + public sealed class TypeSelectorAttribute : PropertyAttribute { public Type BaseType { get; private set; } From 1e2de6aafcddf3b4f9ae3ec8a07bf2b16acc1ffb Mon Sep 17 00:00:00 2001 From: Alijimpa Date: Tue, 28 Apr 2026 13:01:19 +0330 Subject: [PATCH 155/204] Implement Pure Attribute for Methods --- .../Core/InitializeOnLoad/Rules/PureRule.cs | 145 ++++++++++++++++++ .../InitializeOnLoad/Rules/PureRule.cs.meta | 2 + Runtime/Core/Attributes/PureAttribute.cs | 22 +++ Runtime/Core/Attributes/PureAttribute.cs.meta | 2 + 4 files changed, 171 insertions(+) create mode 100644 Editor/Core/InitializeOnLoad/Rules/PureRule.cs create mode 100644 Editor/Core/InitializeOnLoad/Rules/PureRule.cs.meta create mode 100644 Runtime/Core/Attributes/PureAttribute.cs create mode 100644 Runtime/Core/Attributes/PureAttribute.cs.meta diff --git a/Editor/Core/InitializeOnLoad/Rules/PureRule.cs b/Editor/Core/InitializeOnLoad/Rules/PureRule.cs new file mode 100644 index 0000000..57bda23 --- /dev/null +++ b/Editor/Core/InitializeOnLoad/Rules/PureRule.cs @@ -0,0 +1,145 @@ +using System; +using System.Reflection; +using UnityEngine; + +namespace RealMethod.Editor +{ + public class PureRule : CompileRule + { + // CompileRule MEthods + protected override void Initilized() + { + throw new NotImplementedException(); + } + public override void OnStartCheck(RuleExecutionMode mode) + { + } + public override bool CanCheck(RuleExecutionMode mode, Type type) + { + if (mode == RuleExecutionMode.AfterCompilation) + { + return true; + } + else + { + return false; + } + } + public override void OnCheck(Type type) + { + foreach (var method in type.GetMethods( + BindingFlags.Public | + BindingFlags.NonPublic | + BindingFlags.Instance | + BindingFlags.Static | + BindingFlags.DeclaredOnly)) + { + // Ignore methods without PureAttribute + if (!method.IsDefined(typeof(PureAttribute), false)) + continue; + + // Check the calls inside the method + if (!IsMethodPure(method)) + { + Debug.LogError( + $"PURE METHOD VIOLATION in {type.FullName}.{method.Name}():\n" + + $"→ This method is marked [Pure] but calls an impure method!" + ); + } + } + } + + + private bool IsMethodPure(MethodInfo method) + { + var body = method.GetMethodBody(); + if (body == null) + return true; + + var il = body.GetILAsByteArray(); + int pos = 0; + + while (pos < il.Length) + { + byte op = il[pos]; + + // CALL or CALLVIRT opcodes + if (op == 0x28 || op == 0x6F) + { + int metadataToken = BitConverter.ToInt32(il, pos + 1); + var called = method.Module.ResolveMethod(metadataToken) as MethodInfo; + + if (called != null) + { + // If called method is not marked [Pure] → error + if (!called.IsDefined(typeof(PureAttribute), false)) + return false; + } + } + + pos++; + } + + return true; + } + private bool IsPure(MethodInfo method) + { + // 1. Explicitly marked as pure + if (method.GetCustomAttribute() != null) + return true; + + // 2. Implicit analysis + return IsMethodImplicitlyPure(method); + } + private bool IsMethodImplicitlyPure(MethodInfo method) + { + // Any setter = NOT pure + if (method.IsSpecialName && method.Name.StartsWith("set_")) + return false; + + // Inspect instructions (Cecil would be ideal, but unavailable at runtime) + // Simple heuristic: if method writes to fields, it's impure + var body = method.GetMethodBody(); + if (body == null) + return true; // e.g., extern methods are assumed pure + + var il = body.GetILAsByteArray(); + + // Look for IL opcodes that indicate mutation + // stfld = write to field + // stsfld = write to static field + // call/set = property setter + // callvirt = method call (we check purity recursively) + + for (int i = 0; i < il.Length; i++) + { + byte code = il[i]; + + // stfld or stsfld (field writes) + if (code == 0x7D || code == 0x80) + return false; + + // call / callvirt: check called method purity + if (code == 0x28 || code == 0x6F) + { + // Read metadata token + int token = BitConverter.ToInt32(il, i + 1); + var calledMethod = method.Module.ResolveMethod(token) as MethodInfo; + + if (calledMethod == null) + continue; + + // If called method is not pure => this method is impure + if (!IsPure(calledMethod)) + return false; + } + } + + return true; + } + + + + + } +} \ No newline at end of file diff --git a/Editor/Core/InitializeOnLoad/Rules/PureRule.cs.meta b/Editor/Core/InitializeOnLoad/Rules/PureRule.cs.meta new file mode 100644 index 0000000..108444b --- /dev/null +++ b/Editor/Core/InitializeOnLoad/Rules/PureRule.cs.meta @@ -0,0 +1,2 @@ +fileFormatVersion: 2 +guid: 14a6add6319d3c04e824d67efc811507 \ No newline at end of file diff --git a/Runtime/Core/Attributes/PureAttribute.cs b/Runtime/Core/Attributes/PureAttribute.cs new file mode 100644 index 0000000..e5b9649 --- /dev/null +++ b/Runtime/Core/Attributes/PureAttribute.cs @@ -0,0 +1,22 @@ +using System; + +namespace RealMethod +{ + /// + /// + /// [Pure] + /// float A() => 1; + /// [Pure] + /// float B() => A(); // allowed + /// ///////////// + /// float Helper() => 10; // NOT PURE + /// [Pure] + /// float C() => Helper(); // ❌ violation! + /// + /// + [AttributeUsage(AttributeTargets.Method)] + public sealed class PureAttribute : Attribute + { + // Empty: marker attribute only + } +} \ No newline at end of file diff --git a/Runtime/Core/Attributes/PureAttribute.cs.meta b/Runtime/Core/Attributes/PureAttribute.cs.meta new file mode 100644 index 0000000..4bc89b0 --- /dev/null +++ b/Runtime/Core/Attributes/PureAttribute.cs.meta @@ -0,0 +1,2 @@ +fileFormatVersion: 2 +guid: dde25feea08c3a947be547bebf7cc6f0 \ No newline at end of file From 75b05a6df2468d5b88df5baf236221de4eab7a79 Mon Sep 17 00:00:00 2001 From: Alijimpa Date: Tue, 28 Apr 2026 13:02:12 +0330 Subject: [PATCH 156/204] REmove debug when didnt find savemanager --- Runtime/Core/Definitions/Save&File.cs | 8 -------- 1 file changed, 8 deletions(-) diff --git a/Runtime/Core/Definitions/Save&File.cs b/Runtime/Core/Definitions/Save&File.cs index e3f372d..d1d0adc 100644 --- a/Runtime/Core/Definitions/Save&File.cs +++ b/Runtime/Core/Definitions/Save&File.cs @@ -107,10 +107,6 @@ protected virtual void OnEnable() if (!saveSystem.HasFile(this)) saveSystem.AddFile(this); } - else - { - Debug.LogError("Can't find SaveSystem"); - } #endif } protected virtual void OnDisable() @@ -137,10 +133,6 @@ protected virtual void Reset() if (!saveSystem.HasFile(this)) saveSystem.AddFile(this); } - else - { - Debug.LogError("Can't find SaveSystem"); - } #endif } From aec8996446d1f7735d665080f3d5aabb350790b2 Mon Sep 17 00:00:00 2001 From: Alijimpa Date: Tue, 28 Apr 2026 13:04:24 +0330 Subject: [PATCH 157/204] add default compile rule --- Editor/Core/InitializeOnLoad/CompileGuard.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Editor/Core/InitializeOnLoad/CompileGuard.cs b/Editor/Core/InitializeOnLoad/CompileGuard.cs index e1e94a8..3a0cd57 100644 --- a/Editor/Core/InitializeOnLoad/CompileGuard.cs +++ b/Editor/Core/InitializeOnLoad/CompileGuard.cs @@ -123,12 +123,12 @@ private static ProjectSettingAsset ProjectSetting private static CompileRule[] Rules; private static bool initialized; - public static readonly Type[] DefaultRuls = new Type[3] { + public static readonly Type[] DefaultRuls = new Type[4] { // Array of ruls to that should be run always for RealMethod typeof(ConfigAssetsRule), typeof(ServiceRule), typeof(PrimitveAssetsRule), - + typeof(PureRule), }; From 3fb489e6ea7b41fbddedc749cddff4133ca02151 Mon Sep 17 00:00:00 2001 From: Alijimpa Date: Tue, 28 Apr 2026 15:59:26 +0330 Subject: [PATCH 158/204] Implement Attribute for Show ing nameId in Inspector --- Editor/Core/Drawers/SlugDrawer.cs | 22 +++++++++++++++++++ Editor/Core/Drawers/SlugDrawer.cs.meta | 2 ++ Runtime/Core/Attributes/SlugAttribute.cs | 11 ++++++++++ Runtime/Core/Attributes/SlugAttribute.cs.meta | 2 ++ 4 files changed, 37 insertions(+) create mode 100644 Editor/Core/Drawers/SlugDrawer.cs create mode 100644 Editor/Core/Drawers/SlugDrawer.cs.meta create mode 100644 Runtime/Core/Attributes/SlugAttribute.cs create mode 100644 Runtime/Core/Attributes/SlugAttribute.cs.meta diff --git a/Editor/Core/Drawers/SlugDrawer.cs b/Editor/Core/Drawers/SlugDrawer.cs new file mode 100644 index 0000000..fe09839 --- /dev/null +++ b/Editor/Core/Drawers/SlugDrawer.cs @@ -0,0 +1,22 @@ +#if UNITY_EDITOR +using UnityEditor; +using UnityEngine; + +[CustomPropertyDrawer(typeof(SlugAttribute))] +public class SlugDrawer : PropertyDrawer +{ + public override void OnGUI(Rect position, SerializedProperty property, GUIContent label) + { + SlugAttribute attr = (SlugAttribute)attribute; + + // Draw label normally + position = EditorGUI.PrefixLabel(position, label); + + // Shrink width + position.width *= attr.WidthScale; + + // Draw the text field + EditorGUI.PropertyField(position, property, GUIContent.none); + } +} +#endif diff --git a/Editor/Core/Drawers/SlugDrawer.cs.meta b/Editor/Core/Drawers/SlugDrawer.cs.meta new file mode 100644 index 0000000..fd2254a --- /dev/null +++ b/Editor/Core/Drawers/SlugDrawer.cs.meta @@ -0,0 +1,2 @@ +fileFormatVersion: 2 +guid: 943d7c0715f903d4fa0b76804a8f7110 \ No newline at end of file diff --git a/Runtime/Core/Attributes/SlugAttribute.cs b/Runtime/Core/Attributes/SlugAttribute.cs new file mode 100644 index 0000000..97847d9 --- /dev/null +++ b/Runtime/Core/Attributes/SlugAttribute.cs @@ -0,0 +1,11 @@ +using UnityEngine; + +public class SlugAttribute : PropertyAttribute +{ + // Scale the width (0.0 = tiny, 1.0 = normal) + public float WidthScale = 0.5f; + public SlugAttribute(float _widthScale = 0.5f) + { + WidthScale = _widthScale; + } +} diff --git a/Runtime/Core/Attributes/SlugAttribute.cs.meta b/Runtime/Core/Attributes/SlugAttribute.cs.meta new file mode 100644 index 0000000..0e8e171 --- /dev/null +++ b/Runtime/Core/Attributes/SlugAttribute.cs.meta @@ -0,0 +1,2 @@ +fileFormatVersion: 2 +guid: c708d0a804cfd3f4d95287b25667e0dd \ No newline at end of file From b453a222c7263e420447929aee55b561269f1ccf Mon Sep 17 00:00:00 2001 From: Alijimpa Date: Wed, 29 Apr 2026 08:44:01 +0330 Subject: [PATCH 159/204] Fix Typo nameing for World and size text in DebugService --- Runtime/Core/Architecture/World.cs | 4 ++-- Runtime/ReadySet/Services/DebugService.cs | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/Runtime/Core/Architecture/World.cs b/Runtime/Core/Architecture/World.cs index 3fac445..1fee593 100644 --- a/Runtime/Core/Architecture/World.cs +++ b/Runtime/Core/Architecture/World.cs @@ -81,7 +81,7 @@ public abstract class World : MonoBehaviour { [Header("Setting")] [SerializeField] - private Prefab DefualtPlayer; + private Prefab DefaultPlayer; private IGameManager[] Managers; @@ -132,7 +132,7 @@ private void Awake() { var starters = FindObjectsByType(FindObjectsSortMode.InstanceID); Transform SpawnPoint = SelectSpawnPoint(starters); - PlayerObject = SpawnPlayer(DefualtPlayer, SpawnPoint); + PlayerObject = SpawnPlayer(DefaultPlayer, SpawnPoint); } else { diff --git a/Runtime/ReadySet/Services/DebugService.cs b/Runtime/ReadySet/Services/DebugService.cs index 22baeb1..1c4ac35 100644 --- a/Runtime/ReadySet/Services/DebugService.cs +++ b/Runtime/ReadySet/Services/DebugService.cs @@ -125,8 +125,8 @@ DrawMode IDrawTask.GetDrawMode() private ILogHandler defaultLogHandler; private List Lines = new List(10); - public Vector2 PrintPivot = Vector2.zero; - public float PrintSpace = 20; + public Vector2 PrintPivot = new Vector2(10, 10); + public float PrintSpace => Screen.height / 40; public int PrintSize = 1; From c847818f731c3de569c167611d2f3f5910eb2323 Mon Sep 17 00:00:00 2001 From: Alijimpa Date: Wed, 29 Apr 2026 09:21:50 +0330 Subject: [PATCH 160/204] Implement InputType Enum --- .../{LoadStage.cs => CSharpSystem.cs} | 0 .../Enumeration/CSharpSystem.cs.meta | 2 ++ .../Enumeration/LoadStage.cs.meta | 2 -- .../SharedScripts/Enumeration/TriggerStage.cs | 10 -------- .../Enumeration/TriggerStage.cs.meta | 2 -- .../SharedScripts/Enumeration/UnitySystem.cs | 23 +++++++++++++++++++ .../Enumeration/UnitySystem.cs.meta | 2 ++ .../SharedScripts/Enumeration/UpdateMethod.cs | 11 --------- .../Enumeration/UpdateMethod.cs.meta | 2 -- 9 files changed, 27 insertions(+), 27 deletions(-) rename Runtime/Library/SharedScripts/Enumeration/{LoadStage.cs => CSharpSystem.cs} (100%) create mode 100644 Runtime/Library/SharedScripts/Enumeration/CSharpSystem.cs.meta delete mode 100644 Runtime/Library/SharedScripts/Enumeration/LoadStage.cs.meta delete mode 100644 Runtime/Library/SharedScripts/Enumeration/TriggerStage.cs delete mode 100644 Runtime/Library/SharedScripts/Enumeration/TriggerStage.cs.meta create mode 100644 Runtime/Library/SharedScripts/Enumeration/UnitySystem.cs create mode 100644 Runtime/Library/SharedScripts/Enumeration/UnitySystem.cs.meta delete mode 100644 Runtime/Library/SharedScripts/Enumeration/UpdateMethod.cs delete mode 100644 Runtime/Library/SharedScripts/Enumeration/UpdateMethod.cs.meta diff --git a/Runtime/Library/SharedScripts/Enumeration/LoadStage.cs b/Runtime/Library/SharedScripts/Enumeration/CSharpSystem.cs similarity index 100% rename from Runtime/Library/SharedScripts/Enumeration/LoadStage.cs rename to Runtime/Library/SharedScripts/Enumeration/CSharpSystem.cs diff --git a/Runtime/Library/SharedScripts/Enumeration/CSharpSystem.cs.meta b/Runtime/Library/SharedScripts/Enumeration/CSharpSystem.cs.meta new file mode 100644 index 0000000..3b0d3e3 --- /dev/null +++ b/Runtime/Library/SharedScripts/Enumeration/CSharpSystem.cs.meta @@ -0,0 +1,2 @@ +fileFormatVersion: 2 +guid: 7d04823552b8ad949bbfb7ab73c91703 \ No newline at end of file diff --git a/Runtime/Library/SharedScripts/Enumeration/LoadStage.cs.meta b/Runtime/Library/SharedScripts/Enumeration/LoadStage.cs.meta deleted file mode 100644 index 4190f8d..0000000 --- a/Runtime/Library/SharedScripts/Enumeration/LoadStage.cs.meta +++ /dev/null @@ -1,2 +0,0 @@ -fileFormatVersion: 2 -guid: ab35c5257c5b2844ca7e06f6abadd67b \ No newline at end of file diff --git a/Runtime/Library/SharedScripts/Enumeration/TriggerStage.cs b/Runtime/Library/SharedScripts/Enumeration/TriggerStage.cs deleted file mode 100644 index d872f78..0000000 --- a/Runtime/Library/SharedScripts/Enumeration/TriggerStage.cs +++ /dev/null @@ -1,10 +0,0 @@ -namespace RealMethod -{ - public enum TriggerStage - { - None = 0, - Enter = 1, - Stay = 2, - Exit = 2, - } -} \ No newline at end of file diff --git a/Runtime/Library/SharedScripts/Enumeration/TriggerStage.cs.meta b/Runtime/Library/SharedScripts/Enumeration/TriggerStage.cs.meta deleted file mode 100644 index cc9d810..0000000 --- a/Runtime/Library/SharedScripts/Enumeration/TriggerStage.cs.meta +++ /dev/null @@ -1,2 +0,0 @@ -fileFormatVersion: 2 -guid: ee704ee3594278c4aa5a69d62535fc40 \ No newline at end of file diff --git a/Runtime/Library/SharedScripts/Enumeration/UnitySystem.cs b/Runtime/Library/SharedScripts/Enumeration/UnitySystem.cs new file mode 100644 index 0000000..c743742 --- /dev/null +++ b/Runtime/Library/SharedScripts/Enumeration/UnitySystem.cs @@ -0,0 +1,23 @@ +namespace RealMethod +{ + public enum UpdateMethod + { + None = 0, + LateUpdate = 2, + Update = 3, + FixedUpdate = 4 + + } + public enum TriggerStage + { + None = 0, + Enter = 1, + Stay = 2, + Exit = 2, + } + public enum InputSystemType + { + OldInputSystem, + NewInputSystem + } +} \ No newline at end of file diff --git a/Runtime/Library/SharedScripts/Enumeration/UnitySystem.cs.meta b/Runtime/Library/SharedScripts/Enumeration/UnitySystem.cs.meta new file mode 100644 index 0000000..315d74b --- /dev/null +++ b/Runtime/Library/SharedScripts/Enumeration/UnitySystem.cs.meta @@ -0,0 +1,2 @@ +fileFormatVersion: 2 +guid: f4ed914a31845584ab8fec0e3985f650 \ No newline at end of file diff --git a/Runtime/Library/SharedScripts/Enumeration/UpdateMethod.cs b/Runtime/Library/SharedScripts/Enumeration/UpdateMethod.cs deleted file mode 100644 index e7dfffe..0000000 --- a/Runtime/Library/SharedScripts/Enumeration/UpdateMethod.cs +++ /dev/null @@ -1,11 +0,0 @@ -namespace RealMethod -{ - public enum UpdateMethod - { - None = 0, - LateUpdate = 2, - Update = 3, - FixedUpdate = 4 - - } -} \ No newline at end of file diff --git a/Runtime/Library/SharedScripts/Enumeration/UpdateMethod.cs.meta b/Runtime/Library/SharedScripts/Enumeration/UpdateMethod.cs.meta deleted file mode 100644 index 37256b1..0000000 --- a/Runtime/Library/SharedScripts/Enumeration/UpdateMethod.cs.meta +++ /dev/null @@ -1,2 +0,0 @@ -fileFormatVersion: 2 -guid: 48a68344ff70da84d8d012e3eb9efe59 \ No newline at end of file From 5e5edf715e4827a92df93660d9af2fd55940c0cc Mon Sep 17 00:00:00 2001 From: Alijimpa Date: Wed, 29 Apr 2026 10:22:57 +0330 Subject: [PATCH 161/204] Implement DeveloperManager for GUI --- .../Inspectors/DeveloperManagerEditor.cs | 39 +++ .../Inspectors/DeveloperManagerEditor.cs.meta | 2 + Runtime/Pattern/Assets/GUIAsset.cs | 324 +++++++++++++++--- Runtime/Pattern/Managers/DeveloperManager.cs | 195 ++++++++--- Runtime/ReadySet/Managers/DevManager.cs | 6 +- Runtime/ReadySet/Presets/DrawAsset.cs | 15 + 6 files changed, 479 insertions(+), 102 deletions(-) create mode 100644 Editor/Pattern/Inspectors/DeveloperManagerEditor.cs create mode 100644 Editor/Pattern/Inspectors/DeveloperManagerEditor.cs.meta diff --git a/Editor/Pattern/Inspectors/DeveloperManagerEditor.cs b/Editor/Pattern/Inspectors/DeveloperManagerEditor.cs new file mode 100644 index 0000000..33a2b4a --- /dev/null +++ b/Editor/Pattern/Inspectors/DeveloperManagerEditor.cs @@ -0,0 +1,39 @@ +using UnityEditor; +using UnityEngine; + +namespace RealMethod.Editor +{ + [CustomEditor(typeof(DeveloperManager), true)] + public class DeveloperManagerEditor : UnityEditor.Editor + { + private DeveloperManager Comp; + private void OnEnable() + { + Comp = (DeveloperManager)target; + } + + public override void OnInspectorGUI() + { + base.OnInspectorGUI(); + EditorGUILayout.Space(); + EditorGUILayout.LabelField("", GUI.skin.horizontalSlider); + EditorGUILayout.BeginHorizontal(); + if (GUILayout.Button("Open")) + { + Comp.Open(); + } + if (GUILayout.Button("Close")) + { + Comp.Close(); + } + EditorGUILayout.EndHorizontal(); + EditorGUILayout.LabelField($"Status: {IsOpen()}"); + } + + + private string IsOpen() + { + return Comp.IsOpen ? "Open" : "Close"; + } + } +} \ No newline at end of file diff --git a/Editor/Pattern/Inspectors/DeveloperManagerEditor.cs.meta b/Editor/Pattern/Inspectors/DeveloperManagerEditor.cs.meta new file mode 100644 index 0000000..f86534d --- /dev/null +++ b/Editor/Pattern/Inspectors/DeveloperManagerEditor.cs.meta @@ -0,0 +1,2 @@ +fileFormatVersion: 2 +guid: 0d75ebb150273ea4c8884e5b7438b491 \ No newline at end of file diff --git a/Runtime/Pattern/Assets/GUIAsset.cs b/Runtime/Pattern/Assets/GUIAsset.cs index f23126d..1f0b704 100644 --- a/Runtime/Pattern/Assets/GUIAsset.cs +++ b/Runtime/Pattern/Assets/GUIAsset.cs @@ -1,20 +1,43 @@ #if UNITY_EDITOR || DEVELOPMENT_BUILD using System; +using System.Collections.Generic; +using System.Reflection; +using UnityEditor; using UnityEngine; + namespace RealMethod { public interface IDrawWindow { - void OnButtonClick(Name16 ButtonName); - void OnButtonHold(Name16 ButtonName); - void OnToggleChange(Name16 ToggleName, bool Val); + void OnButtonClick(string ButtonName); + void OnToggleChange(string ToggleName, bool Val); Rect GetRect(Rect element, int index); GUIStyle GetStyle(int ID); } public abstract class GUIAsset : UniqueAsset, IDraw, ITask, IDrawWindow { + [Serializable] + public class MemberVariable : MemberBinding + { + public object GetValue() + { + if (SelectedMember is System.Reflection.FieldInfo FInfo) + { + return FInfo.GetValue(SelectedComponent); + } + else if (SelectedMember is System.Reflection.PropertyInfo PInfo) + { + return PInfo.GetValue(SelectedComponent); + } + else + { + Debug.LogWarning($"Member '{SelectedMember.Name}' not found on component type '{SelectedComponent.GetType()}'."); + return default; + } + } + } public enum BuiltInGUIType { Label = 0, @@ -39,7 +62,6 @@ public enum BuiltInGUIType DrawTexture = 19, Toolbar = 20, } - [Serializable] private class DrawSlot : IDraw { @@ -51,14 +73,15 @@ private enum GUIStyleMode Custom_3 = 3, None = 4, } - [Header("Info")] - public Name16 NameID; + [Header("GUI Info")] + [Slug] + public string NameID; public BuiltInGUIType GUIType; [SerializeField] private GUIStyleMode StyleMode; public bool Reset = false; public Rect Transform = Rect.zero; - [Header("Setting")] + [Header("GUI Setting")] [ConditionalShowByEnum("GUIType", BuiltInGUIType.Button, BuiltInGUIType.RepeatButton, BuiltInGUIType.Toggle, BuiltInGUIType.Box)] public string Title; [ConditionalShowByEnum("GUIType", BuiltInGUIType.Label, BuiltInGUIType.TextField, BuiltInGUIType.PasswordField, BuiltInGUIType.TextArea)] @@ -85,10 +108,22 @@ private enum GUIStyleMode public int Columns; [ConditionalShowByEnum("GUIType", BuiltInGUIType.DrawTexture)] public Texture Texture; + [Header("MemberInfo")] + [ConditionalShowByEnum("GUIType", BuiltInGUIType.Button, BuiltInGUIType.RepeatButton, BuiltInGUIType.Toggle, + BuiltInGUIType.Label, BuiltInGUIType.TextField, BuiltInGUIType.PasswordField, BuiltInGUIType.TextArea)] + public bool UseMember = false; + [ConditionalHide("UseMember", true, false)] + public string gameObjectName; + [ConditionalHide("UseMember", true, false)] + public SoftType componentType; + [ConditionalHide("UseMember", true, false)] + public string memberName; + // Private Variable private IDrawWindow window; public bool IsActive => window != null; + private Component CachedComponent; // Implement IIdentifier Interface @@ -170,36 +205,76 @@ void IDraw.Draw(int Index) { // ---------------- BASIC CONTROLS ---------------- case BuiltInGUIType.Label: - GUI.Label(Position, Text, Style); + if (UseMember) + { + GUI.Label(Position, GetMemberValue().ToString(), Style); + } + else + { + GUI.Label(Position, Text, Style); + } break; case BuiltInGUIType.Button: if (GUI.Button(Position, Title, Style)) + { + if (UseMember) + InvokeMemberMethod(); window.OnButtonClick(NameID); + } break; case BuiltInGUIType.RepeatButton: if (GUI.RepeatButton(Position, Title, Style)) - window.OnButtonHold(NameID); + { + if (UseMember) + InvokeMemberMethod(); + window.OnButtonClick(NameID); + } break; case BuiltInGUIType.Toggle: bool result = GUI.Toggle(Position, Toggle, Title, Style); if (result != Toggle) + { + if (UseMember) + InvokeMemberMethod(result); window.OnToggleChange(NameID, result); + } Toggle = result; break; case BuiltInGUIType.TextField: - Text = GUI.TextField(Position, Text, Style); + if (UseMember) + { + Text = GUI.TextField(Position, GetMemberValue().ToString(), Style); + } + else + { + Text = GUI.TextField(Position, Text, Style); + } break; case BuiltInGUIType.PasswordField: - Text = GUI.PasswordField(Position, Text, '*', Style); + if (UseMember) + { + Text = GUI.PasswordField(Position, GetMemberValue().ToString(), '*', Style); + } + else + { + Text = GUI.PasswordField(Position, Text, '*', Style); + } break; case BuiltInGUIType.TextArea: - Text = GUI.TextArea(Position, Text, Style); + if (UseMember) + { + Text = GUI.TextArea(Position, GetMemberValue().ToString(), Style); + } + else + { + Text = GUI.TextArea(Position, Text, Style); + } break; // ---------------- SLIDERS / SCROLLBARS ---------------- @@ -275,7 +350,7 @@ void IDraw.Draw(int Index) } } - + // Functions public void Active(GUIAsset owner) { window = owner; @@ -289,12 +364,20 @@ public void OnValidate(int Index) if (string.IsNullOrEmpty(NameID)) NameID = Index.ToString(); + if (string.IsNullOrEmpty(memberName)) + memberName = NameID; + + if ((int)GUIType > 6) + { + UseMember = false; + } + if (Reset == true) { Reset = false; Transform = GetDefaultRect(GUIType); - Title = string.Empty; - Text = string.Empty; + //Title = string.Empty; + //Text = string.Empty; Toggle = false; Slider = 0; SliderMin = 0; @@ -303,9 +386,9 @@ public void OnValidate(int Index) scrollPos = Vector2.zero; ContentSize = new Vector2(500, 500); SelectedIndex = 0; - Option = string.Empty; + //Option = string.Empty; Columns = 2; - Texture = null; + //Texture = null; } if (SliderMax == 0) @@ -320,6 +403,7 @@ public void OnValidate(int Index) Columns = 2; } + // Methods private GUIStyle GetStyle() { switch (StyleMode) @@ -352,79 +436,134 @@ private GUIStyle GetStyle() return null; } } - public static Rect GetDefaultRect(BuiltInGUIType type) + private Rect GetDefaultRect(BuiltInGUIType type) { switch (type) { // -------- TEXT / BASIC -------- case BuiltInGUIType.Label: - return new Rect(10, 10, 120, 20); + return new Rect(10, 20, 120, 20); case BuiltInGUIType.Button: case BuiltInGUIType.RepeatButton: case BuiltInGUIType.Toggle: - return new Rect(10, 10, 120, 25); + return new Rect(10, 20, 120, 25); case BuiltInGUIType.TextField: case BuiltInGUIType.PasswordField: - return new Rect(10, 10, 160, 22); + return new Rect(10, 20, 160, 22); case BuiltInGUIType.TextArea: - return new Rect(10, 10, 200, 80); + return new Rect(10, 20, 200, 80); // -------- SLIDERS -------- case BuiltInGUIType.HorizontalSlider: - return new Rect(10, 10, 200, 20); + return new Rect(10, 20, 200, 20); case BuiltInGUIType.VerticalSlider: - return new Rect(10, 10, 20, 200); + return new Rect(10, 20, 20, 200); // -------- SCROLLBARS -------- case BuiltInGUIType.HorizontalScrollbar: - return new Rect(10, 10, 200, 18); + return new Rect(10, 20, 200, 18); case BuiltInGUIType.VerticalScrollbar: - return new Rect(10, 10, 18, 200); + return new Rect(10, 20, 18, 200); // -------- CONTAINERS -------- case BuiltInGUIType.Box: - return new Rect(10, 10, 200, 100); + return new Rect(10, 20, 200, 100); case BuiltInGUIType.Group_Begin: - return new Rect(10, 10, 300, 200); + return new Rect(10, 20, 300, 200); case BuiltInGUIType.Group_End: return Rect.zero; case BuiltInGUIType.ScrollView_Begin: - return new Rect(10, 10, 300, 200); + return new Rect(10, 20, 300, 200); case BuiltInGUIType.ScrollView_End: return Rect.zero; case BuiltInGUIType.Clip_Begin: - return new Rect(10, 10, 200, 150); + return new Rect(10, 20, 200, 150); case BuiltInGUIType.Clip_End: return Rect.zero; // -------- COMPLEX CONTROLS -------- case BuiltInGUIType.SelectionGrid: - return new Rect(10, 10, 250, 100); + return new Rect(10, 20, 250, 100); case BuiltInGUIType.Toolbar: - return new Rect(10, 10, 250, 25); + return new Rect(10, 20, 250, 25); // -------- TEXTURE -------- case BuiltInGUIType.DrawTexture: - return new Rect(10, 10, 128, 128); + return new Rect(10, 20, 128, 128); default: - return new Rect(10, 10, 100, 25); + return new Rect(10, 20, 100, 25); + } + } + private Component GetComponent() + { + if (CachedComponent != null) + return CachedComponent; + + var Target = GameObject.Find(gameObjectName); + if (Target == null) + { + Debug.LogWarning($"GameObject '{gameObjectName}' not found."); + return null; } + + CachedComponent = Target.GetComponent(componentType.Type); + if (CachedComponent == null) + Debug.LogWarning($"Component type '{componentType.Type}' not found."); + + return CachedComponent; } + private object GetMemberValue() + { + Component SelectedComponent = GetComponent(); + + // Get Meember + Type type = componentType.Type; + FieldInfo Field = type.GetField(memberName, + BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance); + + if (Field != null) + { + return Field.GetValue(SelectedComponent); + } + PropertyInfo Property = type.GetProperty(memberName, + BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance); + if (Property != null) + { + return Property.GetValue(SelectedComponent); + } + + Debug.LogWarning($"Member '{memberName}' not found on component type '{SelectedComponent.GetType()}'."); + return null; + } + private void InvokeMemberMethod(params object[] arguments) + { + Type type = componentType.Type; + MethodInfo method = type.GetMethod(memberName, BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance); + + if (method == null) + { + Debug.LogWarning($"Method '{memberName}' not found on '{type}'."); + return; + } + + Component SelectedComponent = GetComponent(); + method.Invoke(SelectedComponent, arguments); + } } @@ -436,7 +575,9 @@ public static Rect GetDefaultRect(BuiltInGUIType type) [SerializeField, ConditionalHide("WindowsForm", true, false)] private Rect Position = new Rect(150, 50, 250, 150); [SerializeField, ConditionalHide("WindowsForm", true, false)] - private Rect DragSpace = new Rect(0, 0, Screen.width, Screen.height); + private bool Dragable = true; + [SerializeField, ConditionalHide("WindowsForm", true, false)] + private Rect DragBoundry = new Rect(0, 0, Screen.width, Screen.height); [Header("Rendering")] [SerializeField] private GUIStyleData CustomStyle_1; @@ -445,13 +586,31 @@ public static Rect GetDefaultRect(BuiltInGUIType type) [SerializeField] private GUIStyleData CustomStyle_3; [Header("Items")] + [SerializeField, Tooltip("the value is the amount added per index step")] + private Vector2 StepOffset = Vector2.zero; [SerializeField] private DrawSlot[] DrawItems; + protected DeveloperManager manager { get; private set; } = null; + public bool IsActive => manager != null; + + // Implement ITask Interface void ITask.Active() { + if (IsActive) + { + Debug.LogWarning($"This Asset({name}) already is active."); + return; + } + + manager = Game.GetManager(); + if (manager == null) + { + Debug.LogWarning($"Can't find {typeof(DeveloperManager)} for Asset({name})"); + } + foreach (var item in DrawItems) { item.Active(this); @@ -481,30 +640,27 @@ void IDraw.Draw(int Index) } } // Implement IDrawWindow Interface - void IDrawWindow.OnButtonClick(Name16 ButtonName) - { - - } - void IDrawWindow.OnButtonHold(Name16 ButtonName) - { - throw new NotImplementedException(); - } - void IDrawWindow.OnToggleChange(Name16 ToggleName, bool Val) - { - throw new NotImplementedException(); - } + public abstract void OnToggleChange(string ToggleName, bool Val); + public abstract void OnButtonClick(string ButtonName); Rect IDrawWindow.GetRect(Rect element, int index) { - return element; - //return new Rect(Position.x + element.x, Position.y + element.y, element.width, element.height); + if (StepOffset == Vector2.zero) + { + return element; + } + else + { + Vector2 offcet = StepOffset * index; + return new Rect(element.x + offcet.x, element.y + offcet.y, element.width, element.height); + } } GUIStyle IDrawWindow.GetStyle(int ID) { if (ID == 1) return CustomStyle_1.Build(); - if (ID == 1) + if (ID == 2) return CustomStyle_2.Build(); - if (ID == 1) + if (ID == 3) return CustomStyle_3.Build(); Debug.LogWarning($"Din't implement any Style for ID: {ID}"); @@ -519,6 +675,59 @@ private void OnValidate() DrawItems[i].OnValidate(i); } } + protected virtual void Reset() + { + manager = null; + } + + // Functions + public string GetTextItem(string nameID) + { + foreach (var item in DrawItems) + { + if (item.GUIType == BuiltInGUIType.TextField || item.GUIType == BuiltInGUIType.PasswordField || item.GUIType == BuiltInGUIType.TextArea) + { + if (item.NameID == nameID) + return item.Text; + } + } + return string.Empty; + } + public void SetTextItem(string nameID, string text) + { + foreach (var item in DrawItems) + { + if (item.GUIType == BuiltInGUIType.TextField || item.GUIType == BuiltInGUIType.PasswordField || item.GUIType == BuiltInGUIType.TextArea) + { + if (item.NameID == nameID) + { + item.Text = text; + return; + } + } + } + } + public bool HasItem(string nameID) + { + foreach (var item in DrawItems) + { + if (item.NameID == nameID) + return true; + } + return false; + } + public string[] GetItemList(BuiltInGUIType type) + { + List result = new List(); + foreach (var item in DrawItems) + { + if (item.GUIType == type) + { + result.Add(item.NameID); + } + } + return result.ToArray(); + } // Methods private void Drawing() @@ -533,8 +742,19 @@ private void Drawing() private void OnWindowsDraw(int id) { Drawing(); - GUI.DragWindow(DragSpace); + if (Dragable) + GUI.DragWindow(DragBoundry); + } + + +#if UNITY_EDITOR + public override bool AutoReset(PlayModeStateChange state) + { + if (state == PlayModeStateChange.ExitingPlayMode) + return true; + return base.AutoReset(state); } +#endif } diff --git a/Runtime/Pattern/Managers/DeveloperManager.cs b/Runtime/Pattern/Managers/DeveloperManager.cs index d5c9d57..ca97ca8 100644 --- a/Runtime/Pattern/Managers/DeveloperManager.cs +++ b/Runtime/Pattern/Managers/DeveloperManager.cs @@ -1,5 +1,9 @@ #if UNITY_EDITOR || DEVELOPMENT_BUILD +using System.Linq; using UnityEngine; +#if ENABLE_INPUT_SYSTEM +using UnityEngine.InputSystem; +#endif namespace RealMethod { @@ -18,18 +22,28 @@ private enum VisiblityModes } [Header("Developer")] [SerializeField] - private Map WindowsAsset = new Map(); + private Map GUIAssets = new Map(); [Header("Setting")] [SerializeField] + private bool isOpen = true; + public bool IsOpen => isOpen; + [SerializeField] private VisiblityModes ControlMode; [SerializeField, ConditionalShowByEnum("ControlMode", VisiblityModes.UI)] - private Corner ButtonPosition = Corner.UpRight; + private Dir9 ButtonPosition = Dir9.UpRight; [SerializeField, ConditionalShowByEnum("ControlMode", VisiblityModes.UI)] private Vector2 Scale = new Vector2(50, 30); [SerializeField, ConditionalShowByEnum("ControlMode", VisiblityModes.UI)] private float margin = 0.8f; + [SerializeField, ConditionalShowByEnum("ControlMode", VisiblityModes.Input)] + public InputSystemType inputSystem = InputSystemType.OldInputSystem; + [SerializeField, ConditionalShowByEnum("ControlMode", VisiblityModes.Input), ConditionalHideByEnum("inputSystem", InputSystemType.NewInputSystem)] + public KeyCode oldKey = KeyCode.BackQuote; +#if ENABLE_INPUT_SYSTEM + [SerializeField, ConditionalShowByEnum("ControlMode", VisiblityModes.Input), ConditionalHideByEnum("inputSystem", InputSystemType.OldInputSystem)] + public InputActionReference inputAction; +#endif - public bool IsOpen { get; private set; } = true; public Rect ButtonRect => RM_GUI.GetButtonRect(ButtonPosition, Scale.x, Scale.y, margin); @@ -39,47 +53,56 @@ MonoBehaviour IGameManager.GetManagerClass() { return this; } - void IGameManager.InitiateManager(bool AlwaysLoaded) - { - InitiateManager(AlwaysLoaded); - } - void IGameManager.ResolveService(Service service, bool active) - { - ResolveService(service); - } - // Unity Methods private void OnEnable() { - foreach (var Asset in WindowsAsset) + if (ControlMode == VisiblityModes.Input && inputSystem == InputSystemType.NewInputSystem) + { +#if ENABLE_INPUT_SYSTEM + inputAction.action.Enable(); + inputAction.action.performed += OnUITrigger; +#endif + } + + + foreach (var Asset in GUIAssets) { ((ITask)Asset.Key).Active(); } } + void Update() + { + if (ControlMode == VisiblityModes.Input && inputSystem == InputSystemType.OldInputSystem) + { + if (Input.GetKeyDown(oldKey)) + { + TriggerVisiblity(); + } + } + } private void OnGUI() { - if (IsOpen) + if (ControlMode == VisiblityModes.UI) { - if (ControlMode == VisiblityModes.UI) + if (GUI.Button(ButtonRect, IsOpen ? "Open" : "Close")) { - if (GUI.Button(ButtonRect, "Close")) - { - Close(); - } + TriggerVisiblity(); } + } - - for (int i = 0; i < WindowsAsset.Count; i++) + if (IsOpen) + { + for (int i = 0; i < GUIAssets.Count; i++) { - if (WindowsAsset.GetValue(i) == false) + if (GUIAssets.GetValue(i) == false) continue; - IDraw task = WindowsAsset.GetKey(i); + IDraw task = GUIAssets.GetKey(i); if (task == null) { - WindowsAsset.Remove(i); + GUIAssets.Remove(i); continue; } @@ -87,26 +110,90 @@ private void OnGUI() task.Draw(i); } } - else - { - if (ControlMode == VisiblityModes.UI) - { - if (GUI.Button(ButtonRect, "Open")) - { - Open(); - } - } - } } private void OnDisable() { - foreach (var Asset in WindowsAsset) + if (ControlMode == VisiblityModes.Input && inputSystem == InputSystemType.NewInputSystem) + { +#if ENABLE_INPUT_SYSTEM + inputAction.action.performed -= OnUITrigger; + inputAction.action.Disable(); +#endif + } + + foreach (var Asset in GUIAssets) { ((ITask)Asset.Key).Deactive(); } } // Functions + public void SetVisisblityEnable(int Index) + { + if (Index < 0) + { + Debug.LogWarning("Index should not be less than 0 for Change Visisblity"); + return; + } + if (GUIAssets.Count > Index) + { + var key = GUIAssets.Keys.ElementAt(Index); + GUIAssets[key] = true; + } + else + { + Debug.LogWarning($"Can't Find Asset for Index {Index}"); + } + } + public void SetVisisblityDisable(int Index) + { + if (Index < 0) + { + Debug.LogWarning("Index should not be less than 0 for Change Visisblity"); + return; + } + if (GUIAssets.Count > Index) + { + var key = GUIAssets.Keys.ElementAt(Index); + GUIAssets[key] = false; + } + else + { + Debug.LogWarning($"Can't Find Asset for Index {Index}"); + } + } + public void SetVisisblityEnable(GUIAsset asset) + { + if (asset == null) + { + Debug.LogWarning("Asset is not valid for Change Visisblity"); + return; + } + if (GUIAssets.ContainsKey(asset)) + { + GUIAssets[asset] = true; + } + else + { + Debug.LogWarning($"Can't Find Asset for Index {asset}"); + } + } + public void SetVisisblityDisable(GUIAsset asset) + { + if (asset == null) + { + Debug.LogWarning("Asset is not valid for Change Visisblity"); + return; + } + if (GUIAssets.ContainsKey(asset)) + { + GUIAssets[asset] = false; + } + else + { + Debug.LogWarning($"Can't Find Asset for Index {asset}"); + } + } public void Add(DrawAsset asset) { if (asset == null) @@ -114,41 +201,55 @@ public void Add(DrawAsset asset) Debug.LogWarning("Can't Add Asset, in not valid!"); return; } - WindowsAsset.Add(asset, true); + GUIAssets.Add(asset, true); ((ITask)asset).Active(); } - public bool Remove(DrawAsset asset) + public bool Remove(GUIAsset asset) { - for (int i = 0; i < WindowsAsset.Count; i++) + for (int i = 0; i < GUIAssets.Count; i++) { - DrawAsset target = WindowsAsset.GetKey(i); + GUIAsset target = GUIAssets.GetKey(i); if (target == asset) { ((ITask)target).Deactive(); - return WindowsAsset.Remove(target); + return GUIAssets.Remove(target); } } return false; } - [Button] public void Open() { if (ControlMode == VisiblityModes.None) return; - IsOpen = true; + isOpen = true; } - [Button] public void Close() { if (ControlMode == VisiblityModes.None) return; - IsOpen = false; + isOpen = false; + } + public void TriggerVisiblity() + { + if (IsOpen) + { + Close(); + } + else + { + Open(); + } } - // Abstract Methods - protected abstract void InitiateManager(bool alwaysLoaded); - protected abstract void ResolveService(Service service); +#if ENABLE_INPUT_SYSTEM + private void OnUITrigger(InputAction.CallbackContext context) + { + TriggerVisiblity(); + } +#endif + public abstract void InitiateManager(bool alwaysLoaded); + public abstract void ResolveService(Service service, bool active); } diff --git a/Runtime/ReadySet/Managers/DevManager.cs b/Runtime/ReadySet/Managers/DevManager.cs index b0216af..514ff96 100644 --- a/Runtime/ReadySet/Managers/DevManager.cs +++ b/Runtime/ReadySet/Managers/DevManager.cs @@ -1,4 +1,5 @@ #if UNITY_EDITOR || DEVELOPMENT_BUILD +using System.Reflection; using UnityEngine; namespace RealMethod @@ -6,12 +7,11 @@ namespace RealMethod [AddComponentMenu("RealMethod/Manager/DeveloperManager")] public class DevManager : DeveloperManager { - // DeveloperManager Methods - protected override void InitiateManager(bool alwaysLoaded) + public override void InitiateManager(bool alwaysLoaded) { } - protected override void ResolveService(Service service) + public override void ResolveService(Service service, bool active) { } } diff --git a/Runtime/ReadySet/Presets/DrawAsset.cs b/Runtime/ReadySet/Presets/DrawAsset.cs index 602f9f9..7cee7c7 100644 --- a/Runtime/ReadySet/Presets/DrawAsset.cs +++ b/Runtime/ReadySet/Presets/DrawAsset.cs @@ -1,3 +1,4 @@ +using System; using UnityEngine; namespace RealMethod @@ -5,6 +6,20 @@ namespace RealMethod [CreateAssetMenu(fileName = "Draw", menuName = "RealMethod/Develop/DrawAsset", order = 1)] public class DrawAsset : GUIAsset { + public event Action OnButtonClicked; + public event Action OnToggleChanged; + + + // GUIAsset Methods + public override void OnButtonClick(string ButtonName) + { + OnButtonClicked?.Invoke(ButtonName); + } + public override void OnToggleChange(string ToggleName, bool Val) + { + OnToggleChanged?.Invoke(ToggleName, Val); + } + } } \ No newline at end of file From a590b1014745bd7493cc138c85cb3b79fe5f03db Mon Sep 17 00:00:00 2001 From: Alijimpa Date: Wed, 29 Apr 2026 10:23:30 +0330 Subject: [PATCH 162/204] Refine Basic Enums for Directions --- .../SharedScripts/Enumeration/Directions.cs | 53 +++++++++++++++++-- Runtime/Library/Utilities/GUILibrary.cs | 36 +++++++++++-- 2 files changed, 81 insertions(+), 8 deletions(-) diff --git a/Runtime/Library/SharedScripts/Enumeration/Directions.cs b/Runtime/Library/SharedScripts/Enumeration/Directions.cs index 9c4b533..485a5f1 100644 --- a/Runtime/Library/SharedScripts/Enumeration/Directions.cs +++ b/Runtime/Library/SharedScripts/Enumeration/Directions.cs @@ -1,11 +1,58 @@ namespace RealMethod { - public enum Corner + /// + /// Only the four cardinal directions. + /// + public enum Dir4 { + Up, + Right, + Down, + Left + } + /// + /// Direction4 + Center (neutral). + /// + public enum Dir5 + { + Center, + Up, + Right, + Down, + Left + } + /// + /// Cardinal + diagonal directions. + /// + public enum Dir8 + { + Up, + UpRight, + Right, + DownRight, + Down, + DownLeft, + Left, + UpLeft + } + /// + /// Direction8 + Center. + /// + public enum Dir9 + { + Center, + Up, UpRight, - UpLeft, + Right, DownRight, - DownLeft + Down, + DownLeft, + Left, + UpLeft } + + + + } \ No newline at end of file diff --git a/Runtime/Library/Utilities/GUILibrary.cs b/Runtime/Library/Utilities/GUILibrary.cs index e2610be..e7577f6 100644 --- a/Runtime/Library/Utilities/GUILibrary.cs +++ b/Runtime/Library/Utilities/GUILibrary.cs @@ -5,36 +5,62 @@ namespace RealMethod { public static class RM_GUI { - public static Rect GetButtonRect(Corner corner, float width, float height, float margin = 10f) + public static Rect GetButtonRect(Dir9 corner, float width, float height, float margin = 10f) { float x = 0; float y = 0; switch (corner) { - case Corner.UpLeft: + case Dir9.UpLeft: x = margin; y = margin; break; - case Corner.UpRight: + case Dir9.Up: + x = (Screen.width - width) * 0.5f; + y = margin; + break; + + case Dir9.UpRight: x = Screen.width - width - margin; y = margin; break; - case Corner.DownLeft: + case Dir9.Left: x = margin; + y = (Screen.height - height) * 0.5f; + break; + + case Dir9.Right: + x = Screen.width - width - margin; + y = (Screen.height - height) * 0.5f; + break; + + case Dir9.DownLeft: + x = margin; + y = Screen.height - height - margin; + break; + + case Dir9.Down: + x = (Screen.width - width) * 0.5f; y = Screen.height - height - margin; break; - case Corner.DownRight: + case Dir9.DownRight: x = Screen.width - width - margin; y = Screen.height - height - margin; break; + + case Dir9.Center: + x = (Screen.width - width) * 0.5f; + y = (Screen.height - height) * 0.5f; + break; } return new Rect(x, y, width, height); } + } } From b5ad191e90225eea9847ce62f27d2b466c33d291 Mon Sep 17 00:00:00 2001 From: Alijimpa Date: Wed, 29 Apr 2026 10:23:49 +0330 Subject: [PATCH 163/204] Implement MemeberBinding --- .../SharedScripts/Classes/MemberBinding.cs | 164 ++++++++++++++++++ .../Classes/MemberBinding.cs.meta | 2 + 2 files changed, 166 insertions(+) create mode 100644 Runtime/Library/SharedScripts/Classes/MemberBinding.cs create mode 100644 Runtime/Library/SharedScripts/Classes/MemberBinding.cs.meta diff --git a/Runtime/Library/SharedScripts/Classes/MemberBinding.cs b/Runtime/Library/SharedScripts/Classes/MemberBinding.cs new file mode 100644 index 0000000..db441b3 --- /dev/null +++ b/Runtime/Library/SharedScripts/Classes/MemberBinding.cs @@ -0,0 +1,164 @@ +using System; +using System.Reflection; +using UnityEngine; + +namespace RealMethod +{ + public abstract class MemberBinding + { + [Header("Member Info")] + [SerializeField] + private bool UseRefrence = false; + [SerializeField, ConditionalHide("UseRefrence", true, true)] + private string gameObjectName; + [SerializeField, ConditionalHide("UseRefrence", true, false)] + private GameObject Ref; + [SerializeField] + private SoftType componentType; + [SerializeField, Slug] + private string memberName; + public GameObject SelectedGameObject + { + get + { + if (UseRefrence) + { + return Ref; + } + + if (cachedObject == null) + { + cachedObject = FindGameObject(); + } + return cachedObject; + } + } + public Component SelectedComponent + { + get + { + if (cachedComponent == null) + { + cachedComponent = FindComponent(SelectedGameObject); + } + return cachedComponent; + } + } + public MemberInfo SelectedMember + { + get + { + if (cachedMember == null) + { + cachedMember = FindMemeber(componentType.Type, memberName); + } + return cachedMember; + } + } + + private GameObject cachedObject; + private Component cachedComponent; + private MemberInfo cachedMember; + + + protected virtual GameObject FindGameObject() + { + var Target = GameObject.Find(gameObjectName); + if (Target == null) + { + Debug.LogWarning($"GameObject '{gameObjectName}' not found."); + } + return null; + } + protected virtual Component FindComponent(GameObject target) + { + var comp = target.GetComponent(componentType.Type); + if (comp == null) + { + Debug.LogWarning($"Component type '{componentType}' not found."); + } + return comp; + } + protected virtual MemberInfo FindMemeber(Type type, string memberName) + { + MemberInfo Info = type.GetField(memberName, + BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance); + + if (Info == null) + { + Info = type.GetProperty(memberName, + BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance); + } + + return Info; + } + } + + + [Serializable] + public class MemberVariable : MemberBinding where T : struct + { + public T GetValue() + { + if (SelectedMember is FieldInfo FInfo) + { + return (T)FInfo.GetValue(SelectedComponent); + } + else if (SelectedMember is PropertyInfo PInfo) + { + return (T)PInfo.GetValue(SelectedComponent); + } + else + { + Debug.LogWarning($"Member '{SelectedMember.Name}' not found on component type '{SelectedComponent.GetType()}'."); + return default; + } + } + } + [Serializable] + public class MemberMethod : MemberBinding + { + // MemberBinding Methods + protected override MemberInfo FindMemeber(Type type, string memberName) + { + MethodInfo method = type.GetMethod(memberName, + BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance); + + if (method == null) + { + Debug.LogWarning($"Method '{memberName}' not found on '{type}'."); + return null; + } + + return method; + } + + // Functions + public void Invoke(params object[] arguments) + { + if (SelectedMember is MethodInfo Info) + { + if (arguments == null) + { + Info.Invoke(SelectedComponent, null); + } + else + { + if (arguments.Length > 0) + { + Info.Invoke(SelectedComponent, arguments); + } + } + } + else + { + Debug.LogWarning($"Member '{SelectedMember}' should be [MethodInfo] for Invoking."); + } + } + + } + + + + +} \ No newline at end of file diff --git a/Runtime/Library/SharedScripts/Classes/MemberBinding.cs.meta b/Runtime/Library/SharedScripts/Classes/MemberBinding.cs.meta new file mode 100644 index 0000000..2bdee0f --- /dev/null +++ b/Runtime/Library/SharedScripts/Classes/MemberBinding.cs.meta @@ -0,0 +1,2 @@ +fileFormatVersion: 2 +guid: 10c20d6a5d4d0ae4f9e539304b76448e \ No newline at end of file From 2cda50ef9f1793a7056862343d5dcf2aa20bfa42 Mon Sep 17 00:00:00 2001 From: Alijimpa Date: Wed, 29 Apr 2026 10:24:25 +0330 Subject: [PATCH 164/204] Remove Old Manager --- Runtime/Pattern/Managers/GUIManager.cs | 133 ---------- Runtime/Pattern/Managers/GUIManager.cs.meta | 2 - Runtime/Pattern/Managers/HapticManager.cs | 2 +- Runtime/ReadySet/Managers/PrintManager.cs | 229 ------------------ .../ReadySet/Managers/PrintManager.cs.meta | 2 - 5 files changed, 1 insertion(+), 367 deletions(-) delete mode 100644 Runtime/Pattern/Managers/GUIManager.cs delete mode 100644 Runtime/Pattern/Managers/GUIManager.cs.meta delete mode 100644 Runtime/ReadySet/Managers/PrintManager.cs delete mode 100644 Runtime/ReadySet/Managers/PrintManager.cs.meta diff --git a/Runtime/Pattern/Managers/GUIManager.cs b/Runtime/Pattern/Managers/GUIManager.cs deleted file mode 100644 index 4b9a316..0000000 --- a/Runtime/Pattern/Managers/GUIManager.cs +++ /dev/null @@ -1,133 +0,0 @@ -using System.Collections.Generic; -using UnityEngine; - -namespace RealMethod -{ - public abstract class GUIManager : MonoBehaviour, IGameManager - { - [Header("GUI")] - [SerializeField] - protected Vector2 Pivot = new Vector2(10, 10); - - //Implement IGameManager Interface - MonoBehaviour IGameManager.GetManagerClass() - { - return this; - } - - // Abstract Methods - public abstract void InitiateManager(bool AlwaysLoaded); - public abstract void ResolveService(Service service, bool active); - } - public abstract class GUIManager : GUIManager where T : IDraw - { - [SerializeField, ReadOnly] - protected List DrawList = new List(); - public int Count => DrawList.Count; - - // Functions - public virtual void Add(T Drawer) - { - if (Drawer == null) - { - Debug.LogWarning("The Drawer is not valid!"); - return; - } - - if (Drawer.Start(this)) - DrawList.Add(Drawer); - } - public virtual bool Remove(T Drawer) - { - Drawer.End(); - return DrawList.Remove(Drawer); - } - public virtual void Remove(int Index) - { - DrawList[Index].End(); - DrawList.RemoveAt(Index); - } - public virtual T Find(IIdentifier ID) - { - foreach (var Drawer in DrawList) - { - if (Drawer is IIdentifier id) - { - if (id == ID) - { - return Drawer; - } - } - } - return default; - } - public virtual T Find(Name16 Name) - { - foreach (var Drawer in DrawList) - { - if (Drawer.NameID == Name) - { - return Drawer; - } - } - return default; - } - public virtual T Find(int index) - { - return DrawList[index]; - } - public virtual bool TryFind(IIdentifier ID, out IDraw Drawer) - { - foreach (var drawer in DrawList) - { - if (drawer is IIdentifier id) - { - if (id == ID) - { - Drawer = drawer; - return true; - } - } - } - Drawer = null; - return false; - } - public virtual void Clear() - { - DrawList.Clear(); - } - - -#if UNITY_EDITOR || DEVELOPMENT_BUILD - protected virtual void PreDraw() - { - - } - protected virtual void DrawItem(T item, int index) - { - if (item.CanDraw()) - { - item.Draw(Pivot, index); - } - } - protected virtual void PostDraw() - { - - } - private void OnGUI() - { - PreDraw(); - if (DrawList.Count > 0) - { - for (int i = 0; i < DrawList.Count; i++) - { - DrawItem(DrawList[i], i); - } - } - PostDraw(); - } -#endif - - } -} - diff --git a/Runtime/Pattern/Managers/GUIManager.cs.meta b/Runtime/Pattern/Managers/GUIManager.cs.meta deleted file mode 100644 index 5d32dae..0000000 --- a/Runtime/Pattern/Managers/GUIManager.cs.meta +++ /dev/null @@ -1,2 +0,0 @@ -fileFormatVersion: 2 -guid: 2c2e75245a16ce0478cb57487d47a20f \ No newline at end of file diff --git a/Runtime/Pattern/Managers/HapticManager.cs b/Runtime/Pattern/Managers/HapticManager.cs index 780dcd8..d7112e0 100644 --- a/Runtime/Pattern/Managers/HapticManager.cs +++ b/Runtime/Pattern/Managers/HapticManager.cs @@ -101,7 +101,7 @@ public bool Demolish(IHapticProvider target) { foreach (var item in produceList) { - if (item.NameID == target.NameID) + if (item == target) { return produceList.Remove(item); } diff --git a/Runtime/ReadySet/Managers/PrintManager.cs b/Runtime/ReadySet/Managers/PrintManager.cs deleted file mode 100644 index 62056c4..0000000 --- a/Runtime/ReadySet/Managers/PrintManager.cs +++ /dev/null @@ -1,229 +0,0 @@ -using System; -using System.Collections.Generic; -using UnityEngine; - -namespace RealMethod -{ - public interface IPrint : IIdentifier - { - void Update(string Message); - void Update(Color Color); - void Update(Vector2 Offcet); - } - - - - [Serializable] - public class LogData : IDrawWorkaround, IPrint - { - private PrintManager MyOwner; - [SerializeField] - private string MyMessage; - private int MySize => MyOwner.PrintSize; - private float StartTime; - private Vector2 Offcet = Vector2.zero; - private Color MyColor = Color.green; - - public bool IsStatic { get; private set; } = false; - [field: SerializeField] - public LogType Type { get; private set; } - public float Duration => IsStatic == false ? GetDuration(Type) : 0; - public bool IsFinished => IsStatic == false ? !(Time.time - StartTime <= Duration) : false; - public Color Color => IsStatic == false ? GetColor(Type) : MyColor; - - public LogData(string Message, LogType Type) - { - MyMessage = Message; - this.Type = Type; - } - public LogData(Vector2 offcet) - { - Offcet = offcet; - IsStatic = true; - } - - // Implement IIdentifier Interface - Name16 IIdentifier.NameID => GetHashCode().ToString(); - // Implement IGUIDrawer Interface - bool IDrawWorkaround.Start(IGameManager Manager) - { - if (Manager.GetManagerClass() is PrintManager target) - { - MyOwner = target; - StartTime = Time.time; - return true; - } - else - { - Debug.LogWarning($"LogData can't created the start manager should be {typeof(PrintManager)}"); - return false; - } - } - bool IDrawWorkaround.CanDraw() - { - if (IsStatic) - return true; - return !IsFinished; - } - void IDrawWorkaround.Draw(Vector2 Pivot, int Index) - { - int w = Screen.width * MySize; - int h = Screen.height * MySize; - float Xpos = Pivot.x + Offcet.x; - float Ypos = Pivot.y + Offcet.y + (Index * MyOwner.PrintSpace); - - GUIStyle style = new GUIStyle(); - Rect rect = new Rect(Xpos, Ypos, w, h * 2 / 100); - style.alignment = TextAnchor.UpperLeft; - style.fontSize = h * 2 / 100; - style.normal.textColor = Color; - GUI.Label(rect, MyMessage, style); - } - void IDrawWorkaround.End() - { - - } - // Implement IPrint Interface - void IPrint.Update(string message) - { - MyMessage = message; - } - void IPrint.Update(Color color) - { - MyColor = color; - } - void IPrint.Update(Vector2 offcet) - { - Offcet = offcet; - } - - private float GetDuration(LogType type) - { - switch (type) - { - case LogType.Log: - return 3; - case LogType.Warning: - return 5; - case LogType.Error: - return 8; - case LogType.Assert: - return 12; - case LogType.Exception: - return 15; - default: - return 0; - } - } - private Color GetColor(LogType type) - { - switch (type) - { - case LogType.Log: - return Color.cyan; - case LogType.Warning: - return Color.yellow; - case LogType.Error: - return Color.red; - case LogType.Assert: - return Color.white; - case LogType.Exception: - return Color.blue; - default: - return Color.black; - } - } - - public bool CanDraw(int Index) - { - throw new NotImplementedException(); - } - - public void Draw(int Index) - { - throw new NotImplementedException(); - } - } - - - [AddComponentMenu("RealMethod/Manager/PrintManager")] - public sealed class PrintManager : GUIManager - { - [Header("Printer")] - [SerializeField] - private float printSpace = 20; - public float PrintSpace => printSpace; - [SerializeField] - private int printSize = 1; - public int PrintSize => printSize; - - [SerializeField, ReadOnly] - private List StaticData = new List(10); - - - // GUIManager Methods - public override void InitiateManager(bool AlwaysLoaded) - { - } - public override void ResolveService(Service service, bool active) - { - } - - public void Print(string Message, LogType Type) - { - Add(new LogData(Message, Type)); - } - public IPrint PrintStatic(Vector2 offcet) - { - var Result = new LogData(offcet); - ((IDrawWorkaround)Result).Start(this); - StaticData.Add(Result); - return Result; - } - public bool RemoveStatic(IPrint ptinter) - { - IIdentifier ID = ptinter; - for (int i = 0; i < StaticData.Count; i++) - { - if (StaticData[i] == ID) - { - ((IDrawWorkaround)StaticData[i]).End(); - StaticData.RemoveAt(i); - return true; - } - } - return false; - } - public void SetSize(int newSize) - { - printSize = newSize; - } - -#if UNITY_EDITOR || DEVELOPMENT_BUILD - protected override void PreDraw() - { - base.PreDraw(); - foreach (var item in StaticData) - { - if (item is IDrawWorkaround Drawer) - { - Drawer.Draw(Pivot, 0); - } - } - - } - protected override void PostDraw() - { - base.PostDraw(); - for (int i = 0; i < DrawList.Count; i++) - { - if (DrawList[i].IsFinished) - { - DrawList.Remove(DrawList[i]); - } - } - } -#endif - } -} - diff --git a/Runtime/ReadySet/Managers/PrintManager.cs.meta b/Runtime/ReadySet/Managers/PrintManager.cs.meta deleted file mode 100644 index 0be36b6..0000000 --- a/Runtime/ReadySet/Managers/PrintManager.cs.meta +++ /dev/null @@ -1,2 +0,0 @@ -fileFormatVersion: 2 -guid: feda61cf5eb1b684fadf7cf1048a24cf \ No newline at end of file From d5bf1714256074ca170873d3b08a0f6c400528a2 Mon Sep 17 00:00:00 2001 From: Alijimpa Date: Wed, 29 Apr 2026 10:25:36 +0330 Subject: [PATCH 165/204] REmove old Manager --- Runtime/ReadySet/Managers/DebugManager.cs | 172 ------- .../ReadySet/Managers/DebugManager.cs.meta | 2 - Runtime/ReadySet/Managers/PrintManager2.cs | 461 ------------------ .../ReadySet/Managers/PrintManager2.cs.meta | 2 - 4 files changed, 637 deletions(-) delete mode 100644 Runtime/ReadySet/Managers/DebugManager.cs delete mode 100644 Runtime/ReadySet/Managers/DebugManager.cs.meta delete mode 100644 Runtime/ReadySet/Managers/PrintManager2.cs delete mode 100644 Runtime/ReadySet/Managers/PrintManager2.cs.meta diff --git a/Runtime/ReadySet/Managers/DebugManager.cs b/Runtime/ReadySet/Managers/DebugManager.cs deleted file mode 100644 index f059648..0000000 --- a/Runtime/ReadySet/Managers/DebugManager.cs +++ /dev/null @@ -1,172 +0,0 @@ -using System; -using UnityEngine; - -namespace RealMethod -{ - public interface IButton : IIdentifier - { - void Update(string Name, string tooltip = "Empty"); - void Update(Vector2 Offcet); - event Action OnPressed; - } - - - public interface IDrawWorkaround : IDraw - { - bool Start(IGameManager Manager); - bool CanDraw(); - void Draw(Vector2 Pivot, int Index); - void End(); - } - - [System.Serializable] - public class ButtonData : IDrawWorkaround, IButton - { - private DebugManager MyOwner; - [SerializeField] - private Name16 MyName; - private Action PressedEvent; - private Vector2 Offcet = Vector2.zero; - - public string Tooltip { get; private set; } - - - public ButtonData(Name16 ButtonName, Action callback) - { - MyName = ButtonName; - PressedEvent = callback; - } - - // Implement IIdentifier Interface - public Name16 NameID => MyName; - // Implement IGUIDrawer Interface - bool IDrawWorkaround.Start(IGameManager Manager) - { - if (Manager.GetManagerClass() is DebugManager target) - { - MyOwner = target; - return true; - } - else - { - Debug.LogWarning($"LogData can't created the start manager should be {typeof(DebugManager)}"); - return false; - } - } - bool IDrawWorkaround.CanDraw() - { - return true; - } - void IDrawWorkaround.Draw(Vector2 Pivot, int Index) - { - if (GUI.Button(new Rect(Pivot.x + Offcet.x, (Pivot.y + Offcet.y) * Index, MyOwner.ButtonSize.x, MyOwner.ButtonSize.y), MyName)) - { - PressedEvent?.Invoke(); - } - - } - void IDrawWorkaround.End() - { - PressedEvent = null; - } - // Implement IButton Interface - public event Action OnPressed - { - add - { - PressedEvent += value; - } - - remove - { - PressedEvent -= value; - } - } - public void Update(string Name, string tooltip = "Empty") - { - MyName = Name; - Tooltip = tooltip; - } - public void Update(Vector2 offcet) - { - Offcet = offcet; - } - - public void Start(IGameManager Manager) - { - throw new NotImplementedException(); - } - - public bool CanDraw(int Index) - { - throw new NotImplementedException(); - } - - public void Draw(int Index) - { - throw new NotImplementedException(); - } - } - - [AddComponentMenu("RealMethod/Manager/DebugManager")] - public class DebugManager : MonoBehaviour - { - [Header("Debug Button")] - public Vector2 ScrollPosition = Vector2.zero; - [SerializeField] - private Vector2 buttonSize = new Vector2(200, 40); - public Vector2 ButtonSize => buttonSize; -#if UNITY_EDITOR || DEVELOPMENT_BUILD - [SerializeField] - private float buttonMargin = 20; -#endif - - // GUIManager Methods - // public override void InitiateManager(bool AlwaysLoaded) - // { - // Pivot = new Vector2(0, 50); - // } - // public override void ResolveService(Service service, bool active) - // { - // } - - - public IButton AddButton(Name16 ButtonName, Action Callback) - { - var Result = new ButtonData(ButtonName, Callback); - //((IDrawWorkaround)Result).Start(this); - //Add(Result); - return Result; - } - public bool Remove(IButton button) - { - // var result = Find(button); - //((IDrawWorkaround)result).End(); - return false;//DrawList.Remove(result); - } - -#if UNITY_EDITOR || DEVELOPMENT_BUILD - protected void PreDraw() - { - //base.PreDraw(); - RectOffset padding = GUI.skin.button.padding; - RectOffset margin = GUI.skin.button.margin; - // TODO: The height calculation should be done more correctly. - Rect viewRect = new Rect(0, 0, buttonSize.x, ((buttonSize.y + (padding.vertical + margin.vertical)) * 000) - buttonSize.y); - - ScrollPosition = GUI.BeginScrollView( - position: new Rect(Screen.width - buttonSize.x - buttonMargin, 10, buttonSize.x + buttonMargin, Screen.height - 10), - scrollPosition: ScrollPosition, - viewRect: viewRect, - alwaysShowHorizontal: false, - alwaysShowVertical: false); - } - protected void PostDraw() - { - //base.PostDraw(); - GUI.EndScrollView(); - } -#endif - - } -} \ No newline at end of file diff --git a/Runtime/ReadySet/Managers/DebugManager.cs.meta b/Runtime/ReadySet/Managers/DebugManager.cs.meta deleted file mode 100644 index 2d4a5ee..0000000 --- a/Runtime/ReadySet/Managers/DebugManager.cs.meta +++ /dev/null @@ -1,2 +0,0 @@ -fileFormatVersion: 2 -guid: 3e677e1ad037f59428420540627a8706 \ No newline at end of file diff --git a/Runtime/ReadySet/Managers/PrintManager2.cs b/Runtime/ReadySet/Managers/PrintManager2.cs deleted file mode 100644 index 4bf0051..0000000 --- a/Runtime/ReadySet/Managers/PrintManager2.cs +++ /dev/null @@ -1,461 +0,0 @@ -using System; -using System.Collections; -using System.Collections.Generic; -using System.Reflection; -using UnityEngine; - -namespace RealMethod -{ - - [Serializable] - public class LogData2 - { - public string message; - public float duration; - public float x, y; - public int size; - public Color TextColor; - public LogType messagetype; - public Vector2 position => new Vector2(x, y); - - public LogData2(string Message) - { - message = Message; - duration = 2f; - x = -1; - y = -1; - size = 1; - TextColor = Color.black; - messagetype = LogType.Log; - } - - public LogData2(string Message, LogType type) - { - message = Message; - duration = 2f; - x = -1; - y = -1; - size = 1; - TextColor = GetColor(type); - messagetype = type; - } - public LogData2(string Message, bool Console) - { - message = Message; - duration = 2f; - x = -1; - y = -1; - size = 1; - TextColor = Color.cyan; - messagetype = LogType.Log; - } - - public LogData2(string Message, float Duration) - { - message = Message; - duration = Duration; - x = -1; - y = -1; - size = 1; - TextColor = Color.cyan; - messagetype = LogType.Log; - } - public LogData2(string Message, float Duration, LogType type) - { - message = Message; - duration = Duration; - x = -1; - y = -1; - size = 1; - TextColor = GetColor(type); - messagetype = type; - } - public LogData2(string Message, float Duration, bool Console) - { - message = Message; - duration = Duration; - x = -1; - y = -1; - size = 1; - TextColor = Color.cyan; - messagetype = LogType.Exception; - } - - public LogData2(string Message, float Duration, Color TargetColor) - { - message = Message; - duration = Duration; - x = -1; - y = -1; - size = 1; - TextColor = TargetColor; - messagetype = LogType.Log; - } - - public LogData2(string Message, Color TargetColor) - { - message = Message; - duration = 2f; - x = -1; - y = -1; - size = 1; - TextColor = TargetColor; - messagetype = LogType.Log; - } - - public LogData2(string Message, float Duration, float X, float Y) - { - message = Message; - duration = Duration; - x = X; - y = Y; - size = 1; - TextColor = Color.cyan; - messagetype = LogType.Log; - } - public LogData2(string Message, float Duration, float X, float Y, Color TargetColor) - { - message = Message; - duration = Duration; - x = X; - y = Y; - size = 1; - TextColor = TargetColor; - messagetype = LogType.Log; - } - - public LogData2(string Message, float X, float Y) - { - message = Message; - duration = 2f; - x = X; - y = Y; - size = 1; - TextColor = Color.cyan; - messagetype = LogType.Log; - } - - public LogData2(string Message, float Duration, float X, float Y, int Size) - { - message = Message; - duration = Duration; - x = X; - y = Y; - size = Size; - TextColor = Color.cyan; - messagetype = LogType.Log; - } - - public LogData2(string Message, float X, float Y, int Size, bool Console, LogType type) - { - message = Message; - duration = 2f; - x = X; - y = Y; - size = Size > 0 ? Size : 1; - TextColor = Color.cyan; - messagetype = type; - } - - public LogData2(string Message, float Duration, float X, float Y, int Size, Color TargetColor) - { - message = Message; - duration = Duration; - x = X; - y = Y; - size = Size > 0 ? Size : 1; - TextColor = TargetColor; - messagetype = LogType.Log; - } - public LogData2(string Message, float Duration, float X, float Y, int Size, LogType type) - { - message = Message; - duration = Duration; - x = X; - y = Y; - size = Size > 0 ? Size : 1; - TextColor = GetColor(type); - messagetype = type; - } - - - private Color GetColor(LogType type) - { - switch (type) - { - case LogType.Log: - return Color.cyan; - case LogType.Warning: - return Color.yellow; - case LogType.Error: - return Color.red; - case LogType.Assert: - return Color.black; - case LogType.Exception: - return Color.white; - default: - return Color.blue; - } - } - } - [Serializable] - public class ButtonData2 - { - [SerializeField] string Name = "Button"; - [SerializeField] string Description = "This is a tooltip for the button"; - - [SerializeField] object TargetObject; - [SerializeField] string MethodName; - bool IsFunctionMethod = false; - [SerializeField] object[] MethodParametr; - - public ButtonData2(string name, string description, object targetObject, string methodName, object[] methodParametr) - { - Name = name; - Description = description; - TargetObject = targetObject; - MethodName = methodName; - IsFunctionMethod = true; - MethodParametr = methodParametr; - } - - public ButtonData2(string name, string description, object targetObject, string methodName) - { - Name = name; - Description = description; - TargetObject = targetObject; - MethodName = methodName; - } - - public ButtonData2(string name, object targetObject, string methodName) - { - Name = name; - TargetObject = targetObject; - MethodName = methodName; - } - - public bool ButtonPressed() - { - bool Result; - if (IsFunctionMethod) - { - Type type = TargetObject.GetType(); - MethodInfo method = type.GetMethod(MethodName, BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance); - - if (method != null) - { - method.Invoke(TargetObject, MethodParametr); - Result = true; - } - else - { - //////Print.LogWarning("Method " + MethodName + " not found on " + TargetObject); - Result = false; - } - } - else - { - // Get the type of the target object - Type type = TargetObject.GetType(); - - // Find the method with the specified name - MethodInfo method = type.GetMethod(MethodName, BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance); - - if (method != null) - { - // Invoke the method on the target object - method.Invoke(TargetObject, null); - Result = true; - } - else - { - /////Print.LogWarning("Method " + MethodName + " not found on " + TargetObject); - Result = false; - } - } - - return Result; - } - public string GetName() - { - return Name; - } - public string GetDescription() - { - return Description; - } - - } - - [AddComponentMenu("RealMethod/Manager/PrintManager2")] - public sealed class PrintManager2 : MonoBehaviour - { - - private abstract class GUIRenderer - { - public abstract void Start(PrintManager2 Manager); - public abstract bool CanRender(); - public abstract void Draw(); - } - - private Vector2 DefualtPosition = new Vector2(10, 10); - - private class LogRender : GUIRenderer - { - private PrintManager2 MyOWner; - public override void Start(PrintManager2 Manager) - { - //MyOWner = Manager as PrintManager; - } - public override bool CanRender() - { - return MyOWner.Logs.Count > 0; - } - public override void Draw() - { - for (int i = 0; i < MyOWner.Logs.Count; i++) - { - DrawLog(MyOWner.Logs[i], i); - } - } - - private void DrawLog(LogData2 log, int index) - { - int w = Screen.width * log.size; - int h = Screen.height * log.size; - float Xpos = log.position.x > 0 ? log.position.x : MyOWner.DefualtPosition.x; - float Ypos = log.position.y > 0 ? log.position.y : MyOWner.DefualtPosition.y + (index * MyOWner.PrintSpace); - - GUIStyle style = new GUIStyle(); - Rect rect = new Rect(Xpos, Ypos, w, h * 2 / 100); - style.alignment = TextAnchor.UpperLeft; - style.fontSize = h * 2 / 100; - style.normal.textColor = log.TextColor; - GUI.Label(rect, log.message, style); - } - } - private class ButtonRender : GUIRenderer - { - private PrintManager2 MyOWner; - - public override void Start(PrintManager2 Manager) - { - //dMyOWner = Manager as PrintManager; - } - public override bool CanRender() - { - return MyOWner.Buttons.Count > 0; - } - public override void Draw() - { - RectOffset padding = GUI.skin.button.padding; - RectOffset margin = GUI.skin.button.margin; - - // TODO: The height calculation should be done more correctly. - Rect viewRect = new Rect(0, 0, MyOWner.ButtonSize.x, - ((MyOWner.ButtonSize.y + (padding.vertical + margin.vertical)) * MyOWner.Buttons.Count) - MyOWner.ButtonSize.y); - - - MyOWner.ScrollPosition = GUI.BeginScrollView( - position: new Rect(Screen.width - MyOWner.ButtonSize.x - MyOWner.ButtonMargin, 10, MyOWner.ButtonSize.x + MyOWner.ButtonMargin, Screen.height - 10), - scrollPosition: MyOWner.ScrollPosition, - viewRect: viewRect, - alwaysShowHorizontal: false, - alwaysShowVertical: false - ); - - for (int i = 0; i < MyOWner.Buttons.Count; i++) - { - if (GUI.Button(new Rect(0, 50 * i, MyOWner.ButtonSize.x, MyOWner.ButtonSize.y), MyOWner.Buttons[i].GetName())) - { - MyOWner.Buttons[i].ButtonPressed(); - } - } - GUI.EndScrollView(); - } - } - - - - - - - - - - - - - - - - [Header("Log")] - public float PrintSpace = 20; - [Header("Button")] - [SerializeField] - private Vector2 ScrollPosition = Vector2.zero; - [SerializeField] - private Vector2 ButtonSize = new Vector2(200, 40); - [SerializeField] - private float ButtonMargin = 20; - [Header("Advance")] - [SerializeField, ReadOnly] - private List Logs = new List(); - [SerializeField, ReadOnly] - private List Buttons = new List(); - - - - // public override void InitiateManager(bool AlwaysLoaded) - // { - // throw new NotImplementedException(); - // } - // public override void ResolveService(Service service, bool active) - // { - // } - - - - private GUIRenderer[] GetRenderSlots() - { - return new GUIRenderer[2] { new LogRender(), new ButtonRender() }; - } - - public void Add(LogData2 Log) - { - if (Log.duration > 0) - { - StartCoroutine(RemoveLog(Log)); - } - Logs.Add(Log); - } - public void Add(ButtonData2 Button) - { - Buttons.Add(Button); - } - public void Clear() - { - Logs.Clear(); - Buttons.Clear(); - } - - - // Enumerators - private IEnumerator RemoveLog(LogData2 log) - { - yield return new WaitForSeconds(log.duration); - Logs.Remove(log); - } - - - } - - -} - - - - - - - diff --git a/Runtime/ReadySet/Managers/PrintManager2.cs.meta b/Runtime/ReadySet/Managers/PrintManager2.cs.meta deleted file mode 100644 index 2c40ebd..0000000 --- a/Runtime/ReadySet/Managers/PrintManager2.cs.meta +++ /dev/null @@ -1,2 +0,0 @@ -fileFormatVersion: 2 -guid: 9de82d8783153344b91caba717ca0ce4 \ No newline at end of file From e9f02831f8204d0637b05e6252aa8882d4fa27ad Mon Sep 17 00:00:00 2001 From: Alijimpa Date: Wed, 29 Apr 2026 11:58:57 +0330 Subject: [PATCH 166/204] Remove Spawn Button Function --- Runtime/ReadySet/Services/DespawnService.cs | 12 ------------ Runtime/ReadySet/Services/SpawanService.cs | 14 -------------- 2 files changed, 26 deletions(-) diff --git a/Runtime/ReadySet/Services/DespawnService.cs b/Runtime/ReadySet/Services/DespawnService.cs index 7b55017..1f29816 100644 --- a/Runtime/ReadySet/Services/DespawnService.cs +++ b/Runtime/ReadySet/Services/DespawnService.cs @@ -258,18 +258,6 @@ public static bool Haptic(IHapticProvider provider, bool debug = true) return GetManager().Demolish(provider); } - // Debug - public static bool Button(IButton button, bool debug = true) - { - if (GetManager() == null) - { - if (debug) - Debug.LogWarning("Despawn DebugManager is not available."); - return false; - } - return GetManager().Remove(button); - } - } } \ No newline at end of file diff --git a/Runtime/ReadySet/Services/SpawanService.cs b/Runtime/ReadySet/Services/SpawanService.cs index 607666f..1103880 100644 --- a/Runtime/ReadySet/Services/SpawanService.cs +++ b/Runtime/ReadySet/Services/SpawanService.cs @@ -702,20 +702,6 @@ public static ICoroutineTask CoroutineTask(IEnumerator routine) } } - // Debug - public static IButton Button(Name16 Name, System.Action Callback) - { - if (GetManager() != null) - { - return GetManager().AddButton(Name, Callback); - } - else - { - Debug.LogWarning($" {Ins}: DebugManager is not available."); - return null; - } - } - // Other public static GameObject Empty(string name) { From 25a36c4640af02f87d581f69e31f96e8b91462ef Mon Sep 17 00:00:00 2001 From: Alijimpa Date: Wed, 29 Apr 2026 15:13:15 +0330 Subject: [PATCH 167/204] Refine IIdentifier Interface and implement Some Extention Method for that --- Runtime/Core/Definitions/Identifier.cs | 36 +++++++++++++++++++- Runtime/Library/Extension/Interface.cs | 37 +++++++++++++++++++++ Runtime/Library/Extension/Interface.cs.meta | 2 ++ Runtime/Library/Extension/Object.cs | 27 +++++++++++++++ Runtime/Library/Extension/Transform.cs | 4 +++ 5 files changed, 105 insertions(+), 1 deletion(-) create mode 100644 Runtime/Library/Extension/Interface.cs create mode 100644 Runtime/Library/Extension/Interface.cs.meta diff --git a/Runtime/Core/Definitions/Identifier.cs b/Runtime/Core/Definitions/Identifier.cs index 601c30c..8e82881 100644 --- a/Runtime/Core/Definitions/Identifier.cs +++ b/Runtime/Core/Definitions/Identifier.cs @@ -1,7 +1,41 @@ +using System; + namespace RealMethod { + /// + /// Represents a base contract for objects that can identify themselves. + /// Provides access to the current instance through the property. + /// This interface serves as the root for different identifier strategies. + /// public interface IIdentifier { - //Name16 NameID { get; } + /// + /// Gets the current instance of the implementing object. + /// Useful for generic identifier handling where the object reference is needed. + /// + object Self => this; + } + /// + /// Represents an identifier based on a human-readable name. + /// The name acts as a unique or semi-unique identifier within a specific context. + /// + public interface INameIdentifier : IIdentifier + { + /// + /// Gets the name used to identify the object. + /// The value may be formatted using the attribute. + /// + string SelfName { get; } + } + /// + /// Represents an identifier based on a globally unique identifier (GUID). + /// This ensures uniqueness across systems, sessions, and instances. + /// + public interface IGuidIdentifier : IIdentifier + { + /// + /// Gets the globally unique identifier associated with the object. + /// + Guid SelfID { get; } } } \ No newline at end of file diff --git a/Runtime/Library/Extension/Interface.cs b/Runtime/Library/Extension/Interface.cs new file mode 100644 index 0000000..e8c4bbe --- /dev/null +++ b/Runtime/Library/Extension/Interface.cs @@ -0,0 +1,37 @@ +using UnityEngine; + +namespace RealMethod +{ + /// + /// Extension methods for the Interface to add common functionalities. + /// + public static class Interface_Extension + { + public static bool IsSame(this IIdentifier a, IIdentifier b) + { + // 1. Exactly same reference + if (ReferenceEquals(a, b)) + return true; + + // 2. If one is null + if (a is null || b is null) + return false; + + return Equals(a.Self, b.Self); + } + public static bool HasNameID(this INameIdentifier target, string Name) + { + if (Name == string.Empty) + { + Debug.LogWarning("HasNameID is false [Name is empty]"); + return false; + } + if (target.SelfName == string.Empty) + { + Debug.LogWarning("HasNameID is false [NameID is empty]"); + return false; + } + return target.SelfName == Name; + } + } +} \ No newline at end of file diff --git a/Runtime/Library/Extension/Interface.cs.meta b/Runtime/Library/Extension/Interface.cs.meta new file mode 100644 index 0000000..74ff06b --- /dev/null +++ b/Runtime/Library/Extension/Interface.cs.meta @@ -0,0 +1,2 @@ +fileFormatVersion: 2 +guid: 3ea7987ff424800478430001ef0e023e \ No newline at end of file diff --git a/Runtime/Library/Extension/Object.cs b/Runtime/Library/Extension/Object.cs index ae821f5..fd111cc 100644 --- a/Runtime/Library/Extension/Object.cs +++ b/Runtime/Library/Extension/Object.cs @@ -353,5 +353,32 @@ public static PropertyInfo[] GetProperties(this object target, BindingFlags flag System.Type type = target.GetType(); return type.GetProperties(flags); } + public static IIdentifier GetID(this object obj) + { + return GetID(obj); + } + public static T GetID(this object obj) where T : IIdentifier + { + if (obj is T Provider) + { + return Provider; + } + else + { + return default; + } + } + public static bool HasNameID(this object obj, string NameID) + { + if (obj is INameIdentifier Provider) + { + return Provider.HasNameID(NameID); + } + else + { + Debug.LogError($"Target Object({obj}) should implement {typeof(INameIdentifier)} interface."); + return false; + } + } } } \ No newline at end of file diff --git a/Runtime/Library/Extension/Transform.cs b/Runtime/Library/Extension/Transform.cs index 606fb2f..eb47536 100644 --- a/Runtime/Library/Extension/Transform.cs +++ b/Runtime/Library/Extension/Transform.cs @@ -32,5 +32,9 @@ public static void Reset(this Transform t) t.localRotation = Quaternion.identity; t.localScale = Vector3.one; } + public static TransformData ConvertToData(this Transform trans) + { + return new TransformData(trans); + } } } \ No newline at end of file From dbd45909a214a90e3dc50ba9fb99b4cf4a394fd0 Mon Sep 17 00:00:00 2001 From: Alijimpa Date: Wed, 29 Apr 2026 15:13:37 +0330 Subject: [PATCH 168/204] REfine code with new IIdentifier System --- .../Ability/AbilityControllerEditor.cs | 2 +- Editor/Toolkit/Inventory/InventoryEditor.cs | 2 +- Runtime/Pattern/Assets/GUIAsset.cs | 2 - Runtime/Pattern/Managers/TaskManager.cs | 12 ++++-- Runtime/ReadySet/Managers/MotionManager.cs | 1 - Runtime/ReadySet/Presets/Class/ActionSlot.cs | 2 - Runtime/ReadySet/Services/DebugService.cs | 2 - Runtime/Toolkit/Ability/AbilityAsset.cs | 2 - Runtime/Toolkit/Inventory/Inventory.cs | 40 +++++++++---------- .../Toolkit/Inventory/InventoryInterface.cs | 2 +- .../Toolkit/Inventory/InventorySaveFile.cs | 10 ++--- .../Toolkit/RPG/StatSystem/StatSaveFile.cs | 34 ++++++++-------- 12 files changed, 54 insertions(+), 57 deletions(-) diff --git a/Editor/Toolkit/Ability/AbilityControllerEditor.cs b/Editor/Toolkit/Ability/AbilityControllerEditor.cs index 9f15cb5..8d0b736 100644 --- a/Editor/Toolkit/Ability/AbilityControllerEditor.cs +++ b/Editor/Toolkit/Ability/AbilityControllerEditor.cs @@ -23,7 +23,7 @@ public override void OnInspectorGUI() EditorGUILayout.LabelField($"Debug ({MyController.Count})", EditorStyles.boldLabel); for (int i = 0; i < MyController.Count; i++) { - EditorGUILayout.LabelField($"{MyController.GetAbility(i).NameID}: {IsReady(MyController.GetAbility(i))}"); + EditorGUILayout.LabelField($"{MyController.GetAbility(i).Self}: {IsReady(MyController.GetAbility(i))}"); } } diff --git a/Editor/Toolkit/Inventory/InventoryEditor.cs b/Editor/Toolkit/Inventory/InventoryEditor.cs index d67918b..7942242 100644 --- a/Editor/Toolkit/Inventory/InventoryEditor.cs +++ b/Editor/Toolkit/Inventory/InventoryEditor.cs @@ -26,7 +26,7 @@ public override void OnInspectorGUI() { //EditorGUILayout.BeginHorizontal(); int ItemQuantity = BaseComponent.GetQuantity(item); - EditorGUILayout.LabelField($"Name: {item.NameID}({item.NameID}) - Quantity: {ItemQuantity} "); + EditorGUILayout.LabelField($"Name: {item.SelfName}({item.SelfName}) - Quantity: {ItemQuantity} "); total += ItemQuantity; //EditorGUILayout.EndHorizontal(); } diff --git a/Runtime/Pattern/Assets/GUIAsset.cs b/Runtime/Pattern/Assets/GUIAsset.cs index 1f0b704..8cf1fee 100644 --- a/Runtime/Pattern/Assets/GUIAsset.cs +++ b/Runtime/Pattern/Assets/GUIAsset.cs @@ -126,8 +126,6 @@ private enum GUIStyleMode private Component CachedComponent; - // Implement IIdentifier Interface - Name16 IIdentifier.NameID => NameID; // Implement IDraw Interface bool IDraw.CanDraw(int Index) { diff --git a/Runtime/Pattern/Managers/TaskManager.cs b/Runtime/Pattern/Managers/TaskManager.cs index eef6166..4aaabd9 100644 --- a/Runtime/Pattern/Managers/TaskManager.cs +++ b/Runtime/Pattern/Managers/TaskManager.cs @@ -6,6 +6,7 @@ namespace RealMethod { public interface ITask : ITask, ITick where T : IHandle { + string ID => this.GetType().ToString(); T Controller { get; } } @@ -91,12 +92,17 @@ public override J FindByName(Name16 TaskName) { foreach (var task in Tasks) { - if (task is J provider) + if (task.HasNameID(TaskName)) { - if (provider.NameID == TaskName) + if (task is J provider) { return provider; } + else + { + Debug.LogWarning($"Task({task}) should implement {typeof(J)}"); + return default; + } } } return default; @@ -148,7 +154,7 @@ protected bool RemoveTask(J behavior) { if (task is T provider) { - if (provider.Controller.NameID == behavior.NameID) + if (provider.Controller.IsSame(behavior)) { provider.Deactive(); OnTaskRemoved?.Invoke(provider.Controller); diff --git a/Runtime/ReadySet/Managers/MotionManager.cs b/Runtime/ReadySet/Managers/MotionManager.cs index 40fc054..b120c0e 100644 --- a/Runtime/ReadySet/Managers/MotionManager.cs +++ b/Runtime/ReadySet/Managers/MotionManager.cs @@ -27,7 +27,6 @@ public abstract class MotionAsset : CloneAsset, IMotion, IMotionTask private float lifetime = -1; - // Implement ITask Interface void ITask.Active() { diff --git a/Runtime/ReadySet/Presets/Class/ActionSlot.cs b/Runtime/ReadySet/Presets/Class/ActionSlot.cs index eaeaeec..e4bcbfc 100644 --- a/Runtime/ReadySet/Presets/Class/ActionSlot.cs +++ b/Runtime/ReadySet/Presets/Class/ActionSlot.cs @@ -29,8 +29,6 @@ public abstract class ActionSlot : IAction, IActionTask, IHandleBehaviourAction public event Action OnFinished; - // Implement IIdentifier Interface - Name16 IIdentifier.NameID => GetType().ToString(); // Implement ITask Interface void ITask.Active() { diff --git a/Runtime/ReadySet/Services/DebugService.cs b/Runtime/ReadySet/Services/DebugService.cs index 1c4ac35..6f3819c 100644 --- a/Runtime/ReadySet/Services/DebugService.cs +++ b/Runtime/ReadySet/Services/DebugService.cs @@ -80,8 +80,6 @@ public LogLine(DebugService owner, string message, LogType type, Vector2 offcet) ActiveTime = 0; } - // Implement IIdentifier Interface - Name16 IIdentifier.NameID => throw new System.NotImplementedException(); // Implemetn ITask Interface void ITask.Active() { diff --git a/Runtime/Toolkit/Ability/AbilityAsset.cs b/Runtime/Toolkit/Ability/AbilityAsset.cs index db3acf5..da10501 100644 --- a/Runtime/Toolkit/Ability/AbilityAsset.cs +++ b/Runtime/Toolkit/Ability/AbilityAsset.cs @@ -8,8 +8,6 @@ public abstract class AbilityAsset : CloneAsset, IAbility, ICooldown { private float lastUsedTime = -Mathf.Infinity; - // Implement IIdentifier Interface - Name16 IIdentifier.NameID => name; // Implement IAbility Interface public bool CanUse(GameObject user) { diff --git a/Runtime/Toolkit/Inventory/Inventory.cs b/Runtime/Toolkit/Inventory/Inventory.cs index 3ce6130..fa1b3b8 100644 --- a/Runtime/Toolkit/Inventory/Inventory.cs +++ b/Runtime/Toolkit/Inventory/Inventory.cs @@ -5,12 +5,12 @@ namespace RealMethod { - public class InventoryItemProperty : IResource + public class InventoryItemProperty : IResource, INameIdentifier { [SerializeField] private IInventoryItem Item; public IInventoryItem provider => Item; - public string Name => provider.NameID; + public string SelfName => provider.SelfName; [SerializeField] private int ItemQuantity; public int Quantity => ItemQuantity; @@ -140,7 +140,7 @@ private void Awake() Items = new NameTable(cacheItems.Length); foreach (var data in cacheItems) { - Items.Add(data.Name, data); + Items.Add(data.SelfName, data); } } else @@ -197,31 +197,31 @@ public bool TryFindResourceItem(string itemTitle, out IResource resource) } public IResource GetResourceProvider(IInventoryItem item) { - return Items[item.NameID]; + return Items[item.SelfName]; } public int GetQuantity(IInventoryItem item) { - if (Items.ContainsKey(item.NameID)) + if (Items.ContainsKey(item.SelfName)) { - return Items[item.NameID].Quantity; + return Items[item.SelfName].Quantity; } else { return 0; } } - public bool IsValidItem(IIdentifier item) + public bool IsValidItem(INameIdentifier Name) { - return Items.ContainsKey(item.NameID); + return Items.ContainsKey(Name.SelfName); } public bool AddNewItem(IInventoryItem item, int quantity, int capacity) { - if (!Items.ContainsKey(item.NameID)) + if (!Items.ContainsKey(item.SelfName)) { if (item.CanPickUp(this)) { InventoryItemProperty NewItem = new InventoryItemProperty(item, quantity, capacity); - Items.Add(item.NameID, NewItem); + Items.Add(item.SelfName, NewItem); inventoryStorage.CreateItem(NewItem); MessageBehavior(ItemState.Create, item, quantity); return true; @@ -233,7 +233,7 @@ public bool AddNewItem(IInventoryItem item, int quantity, int capacity) } else { - Debug.LogWarning($"Item with this Name {item.NameID} already there"); + Debug.LogWarning($"Item with this Name {item.SelfName} already there"); return false; } } @@ -241,11 +241,11 @@ public bool AddItem(IInventoryItem item, int quantity = 1) { if (_capacity == 0 || Items.Count < _capacity) { - if (Items.ContainsKey(item.NameID)) + if (Items.ContainsKey(item.SelfName)) { if (item.CanChange(true)) { - Items[item.NameID].Add(quantity); + Items[item.SelfName].Add(quantity); inventoryStorage.UpdateQuantity(item, quantity); MessageBehavior(ItemState.Update, item, quantity); } @@ -255,7 +255,7 @@ public bool AddItem(IInventoryItem item, int quantity = 1) if (item.CanPickUp(this)) { InventoryItemProperty NewItem = new InventoryItemProperty(item, quantity); - Items.Add(item.NameID, NewItem); + Items.Add(item.SelfName, NewItem); inventoryStorage.CreateItem(NewItem); MessageBehavior(ItemState.Create, item, quantity); } @@ -271,7 +271,7 @@ public bool AddItem(IInventoryItem item, int quantity = 1) public bool SetItemCapacity(IInventoryItem item, int newCpacity) { InventoryItemProperty target; - if (Items.TryGetValue(item.NameID, out target)) + if (Items.TryGetValue(item.SelfName, out target)) { inventoryStorage.UpdateCapacity(item, newCpacity); target.NewCpacity(newCpacity); @@ -279,14 +279,14 @@ public bool SetItemCapacity(IInventoryItem item, int newCpacity) } else { - Debug.LogError($"Can't Find Item With this Name {item.NameID}"); + Debug.LogError($"Can't Find Item With this Name {item.SelfName}"); return false; } } public bool RemoveItem(IInventoryItem item, int quantity = 1) { InventoryItemProperty target; - if (Items.TryGetValue(item.NameID, out target)) + if (Items.TryGetValue(item.SelfName, out target)) { if (item.CanChange(true)) { @@ -300,7 +300,7 @@ public bool RemoveItem(IInventoryItem item, int quantity = 1) { if (item.CanDropp(this)) { - if (Items.Remove(item.NameID)) + if (Items.Remove(item.SelfName)) { inventoryStorage.DestroyItem(item); MessageBehavior(ItemState.Delete, null, 0); @@ -333,9 +333,9 @@ public bool RemoveItem(IInventoryItem item, int quantity = 1) } public bool DeleteItem(IInventoryItem item) { - if (Items.ContainsKey(item.NameID)) + if (Items.ContainsKey(item.SelfName)) { - bool Result = Items.Remove(item.NameID); + bool Result = Items.Remove(item.SelfName); if (Result) { inventoryStorage.DestroyItem(item); diff --git a/Runtime/Toolkit/Inventory/InventoryInterface.cs b/Runtime/Toolkit/Inventory/InventoryInterface.cs index a9e77ea..747df8d 100644 --- a/Runtime/Toolkit/Inventory/InventoryInterface.cs +++ b/Runtime/Toolkit/Inventory/InventoryInterface.cs @@ -10,7 +10,7 @@ public interface IInventoryStorage : IFile void UpdateCapacity(IInventoryItem item, int value); } - public interface IInventoryItem : IItem , IResourceItem + public interface IInventoryItem : IItem, IResourceItem, INameIdentifier { void PickedUp(Inventory owner, int quantity); void Cahanged(int quantity); diff --git a/Runtime/Toolkit/Inventory/InventorySaveFile.cs b/Runtime/Toolkit/Inventory/InventorySaveFile.cs index 9b9c84d..83f0bb3 100644 --- a/Runtime/Toolkit/Inventory/InventorySaveFile.cs +++ b/Runtime/Toolkit/Inventory/InventorySaveFile.cs @@ -51,20 +51,20 @@ protected override void OnLoaded() // } void IInventoryStorage.CreateItem(InventoryItemProperty item) { - ItemsName.Add(item.Name); + ItemsName.Add(item.SelfName); ItemsQuantity.Add(item.Quantity); ItemsCapacity.Add(item.Capacity); } void IInventoryStorage.DestroyItem(IInventoryItem item) { - int Target = GetIndexItem(item.NameID); + int Target = GetIndexItem(item.SelfName); ItemsName.RemoveAt(Target); ItemsQuantity.RemoveAt(Target); ItemsCapacity.RemoveAt(Target); } void IInventoryStorage.UpdateQuantity(IInventoryItem item, int amount) { - int Target = GetIndexItem(item.NameID); + int Target = GetIndexItem(item.SelfName); if (amount != 0) { ItemsQuantity[Target] += amount; @@ -77,7 +77,7 @@ void IInventoryStorage.UpdateQuantity(IInventoryItem item, int amount) } void IInventoryStorage.UpdateCapacity(IInventoryItem item, int value) { - int Target = GetIndexItem(item.NameID); + int Target = GetIndexItem(item.SelfName); ItemsCapacity[Target] = value; } InventoryItemProperty[] IInventoryStorage.GetItems() @@ -91,7 +91,7 @@ InventoryItemProperty[] IInventoryStorage.GetItems() { for (int i = 0; i < ItemsName.Count; i++) { - if (ItemsName[i] == item.NameID) + if (ItemsName[i] == item.SelfName) { Result.Add(new InventoryItemProperty(item, ItemsQuantity[i], ItemsCapacity[i])); continue; diff --git a/Runtime/Toolkit/RPG/StatSystem/StatSaveFile.cs b/Runtime/Toolkit/RPG/StatSystem/StatSaveFile.cs index 12f04c1..400ff0e 100644 --- a/Runtime/Toolkit/RPG/StatSystem/StatSaveFile.cs +++ b/Runtime/Toolkit/RPG/StatSystem/StatSaveFile.cs @@ -53,23 +53,23 @@ protected override void OnLoaded() // Implement IStatStorage Interface void IStatStorage.StoreStats(IStat[] stats) { - foreach (var stat in stats) - { - if (Names.Contains(stat.NameID)) - { - int targetindex = Names.IndexOf(stat.NameID); - BaseValue[targetindex] = stat.BaseValue; - Mins[targetindex] = stat.MinValue; - Maxs[targetindex] = stat.MaxValue; - } - else - { - Names.Add(stat.NameID); - BaseValue.Add(stat.BaseValue); - Mins.Add(stat.MinValue); - Maxs.Add(stat.MaxValue); - } - } + // foreach (var stat in stats) + // { + // if (Names.Contains(stat.NameID)) + // { + // int targetindex = Names.IndexOf(stat.NameID); + // BaseValue[targetindex] = stat.BaseValue; + // Mins[targetindex] = stat.MinValue; + // Maxs[targetindex] = stat.MaxValue; + // } + // else + // { + // Names.Add(stat.NameID); + // BaseValue.Add(stat.BaseValue); + // Mins.Add(stat.MinValue); + // Maxs.Add(stat.MaxValue); + // } + // } } bool IStatStorage.TryLoadStats(StatData data) { From 82260ffad022cb327dd9c0e0b6dc8becc7988873 Mon Sep 17 00:00:00 2001 From: Alijimpa Date: Wed, 29 Apr 2026 15:31:15 +0330 Subject: [PATCH 169/204] Refine Code Retunr Self Refrence --- Runtime/Core/Architecture/Game.cs | 10 +++++----- Runtime/Core/Architecture/GameBridge.cs | 1 - Runtime/Core/Architecture/GameManager.cs | 11 ++++++----- Runtime/Core/Architecture/Service.cs | 11 ++--------- Runtime/Core/Architecture/World.cs | 4 ++-- Runtime/Pattern/Managers/DeveloperManager.cs | 8 -------- Runtime/Pattern/Managers/MixerManager.cs | 4 ---- Runtime/Pattern/Managers/SaveManager.cs | 4 ---- Runtime/Pattern/Managers/TaskManager.cs | 4 ---- Runtime/Pattern/Managers/UIManager.cs | 4 ---- Runtime/ReadySet/Services/DespawnService.cs | 4 ++-- Runtime/ReadySet/Services/SpawanService.cs | 4 ++-- Tests/FileManager.cs | 4 ---- 13 files changed, 19 insertions(+), 54 deletions(-) diff --git a/Runtime/Core/Architecture/Game.cs b/Runtime/Core/Architecture/Game.cs index c6046c1..92ad915 100644 --- a/Runtime/Core/Architecture/Game.cs +++ b/Runtime/Core/Architecture/Game.cs @@ -486,7 +486,7 @@ public static bool RemoveService(object author) where T : Service var provider = Instance.Services[TypeService]; if (provider != null) { - if (provider.GetServiceClass() is Service service) + if (provider.Self is Service service) { if (Instance.Managers != null) { @@ -523,7 +523,7 @@ public static T GetService(bool Printdebug = true) Type TypeService = typeof(T); if (Instance.Services.TryGetValue(TypeService, out var provider)) - return (T)provider.GetServiceClass(); + return (T)provider.Self; if (Printdebug) Debug.LogError($"Service {TypeService} not found."); @@ -540,7 +540,7 @@ public static bool TryGetService(out T service) where T : Service { if (Instance.Services.TryGetValue(typeof(T), out var provider)) { - service = (T)provider.GetServiceClass(); + service = (T)provider.Self; return true; } @@ -1052,7 +1052,7 @@ public T FindManager() where T : class { foreach (var manager in Managers) { - if (manager.GetManagerClass() is T Result) + if (manager.Component is T Result) { return Result; } @@ -1068,7 +1068,7 @@ public IGameManager FindManager(string ObjectName) { foreach (var manger in Managers) { - if (manger.GetManagerClass().gameObject.name == ObjectName) + if (manger.Component.gameObject.name == ObjectName) { return manger; } diff --git a/Runtime/Core/Architecture/GameBridge.cs b/Runtime/Core/Architecture/GameBridge.cs index d5c2d56..5dc96af 100644 --- a/Runtime/Core/Architecture/GameBridge.cs +++ b/Runtime/Core/Architecture/GameBridge.cs @@ -116,7 +116,6 @@ public abstract class GameBridge : IService, IRelationBridge, ILoadScneBridge public static bool SceneWillUnload { get; private set; } // Implement IService Interface - object IService.GetServiceClass() => this; void IService.Created(object author) { SceneManager.activeSceneChanged += OnActiveSceneChanged; diff --git a/Runtime/Core/Architecture/GameManager.cs b/Runtime/Core/Architecture/GameManager.cs index fec74db..e73da09 100644 --- a/Runtime/Core/Architecture/GameManager.cs +++ b/Runtime/Core/Architecture/GameManager.cs @@ -8,12 +8,13 @@ namespace RealMethod public interface IGameManager { /// - /// Returns the MonoBehaviour instance that implements this manager. + /// Gets the Unity instance that implements this interface. /// - /// - /// The MonoBehaviour associated with this game manager. - /// - MonoBehaviour GetManagerClass(); + /// + /// This allows systems interacting with the interface to access the underlying + /// Unity component and its associated GameObject and Transform. + /// + Component Component => (Component)this; /// /// Initializes the manager and prepares it for use in the game lifecycle. diff --git a/Runtime/Core/Architecture/Service.cs b/Runtime/Core/Architecture/Service.cs index 1125a9a..92fead6 100644 --- a/Runtime/Core/Architecture/Service.cs +++ b/Runtime/Core/Architecture/Service.cs @@ -8,10 +8,7 @@ public interface IService /// /// Returns the object instance that implements this service. /// - /// - /// The object associated with this service. - /// - object GetServiceClass(); + object Self => this; /// /// Called when the service is created. /// @@ -44,10 +41,6 @@ public interface IService public abstract class Service : IService { // Implement IService Interface - object IService.GetServiceClass() - { - return this; - } void IService.Created(object author) { OnStart(author); @@ -67,7 +60,7 @@ string IService.GetInspectorInfo() } protected virtual string GetDisplayInfo() { - return GetType().ToString()+": "; + return GetType().ToString() + ": "; } #endif diff --git a/Runtime/Core/Architecture/World.cs b/Runtime/Core/Architecture/World.cs index 1fee593..259a0f2 100644 --- a/Runtime/Core/Architecture/World.cs +++ b/Runtime/Core/Architecture/World.cs @@ -197,7 +197,7 @@ public T FindManager() where T : class { foreach (var manager in Managers) { - if (manager.GetManagerClass() is T Result) + if (manager.Component is T Result) { return Result; } @@ -213,7 +213,7 @@ public IGameManager FindManager(string ObjectName) { foreach (var manger in Managers) { - if (manger.GetManagerClass().gameObject.name == ObjectName) + if (manger.Component.gameObject.name == ObjectName) { return manger; } diff --git a/Runtime/Pattern/Managers/DeveloperManager.cs b/Runtime/Pattern/Managers/DeveloperManager.cs index ca97ca8..7f11822 100644 --- a/Runtime/Pattern/Managers/DeveloperManager.cs +++ b/Runtime/Pattern/Managers/DeveloperManager.cs @@ -46,14 +46,6 @@ private enum VisiblityModes public Rect ButtonRect => RM_GUI.GetButtonRect(ButtonPosition, Scale.x, Scale.y, margin); - - - // Implement IGameManager Interface - MonoBehaviour IGameManager.GetManagerClass() - { - return this; - } - // Unity Methods private void OnEnable() { diff --git a/Runtime/Pattern/Managers/MixerManager.cs b/Runtime/Pattern/Managers/MixerManager.cs index 59abf4e..de7c3a2 100644 --- a/Runtime/Pattern/Managers/MixerManager.cs +++ b/Runtime/Pattern/Managers/MixerManager.cs @@ -17,10 +17,6 @@ public abstract class MixerManager : MonoBehaviour, IGameManager // IGameManager Interface Implementation - MonoBehaviour IGameManager.GetManagerClass() - { - return this; - } public virtual void InitiateManager(bool AlwaysLoaded) { diff --git a/Runtime/Pattern/Managers/SaveManager.cs b/Runtime/Pattern/Managers/SaveManager.cs index 61cd5da..5579e0e 100644 --- a/Runtime/Pattern/Managers/SaveManager.cs +++ b/Runtime/Pattern/Managers/SaveManager.cs @@ -67,10 +67,6 @@ public abstract class SaveManager : MonoBehaviour, IGameManager, ISaveSystem // Implement IGameManager Interface - MonoBehaviour IGameManager.GetManagerClass() - { - return this; - } public virtual void InitiateManager(bool AlwaysLoaded) { if (Mode != SaveFileStructure.MultiFile) diff --git a/Runtime/Pattern/Managers/TaskManager.cs b/Runtime/Pattern/Managers/TaskManager.cs index 4aaabd9..fbcf2a3 100644 --- a/Runtime/Pattern/Managers/TaskManager.cs +++ b/Runtime/Pattern/Managers/TaskManager.cs @@ -16,10 +16,6 @@ public abstract class TaskManager : MonoBehaviour, IGameManager public int Count => Tasks != null ? Tasks.Count : 0; // Implement IGameManager Interface - MonoBehaviour IGameManager.GetManagerClass() - { - return this; - } void IGameManager.InitiateManager(bool AlwaysLoaded) { InitiateManager(AlwaysLoaded); diff --git a/Runtime/Pattern/Managers/UIManager.cs b/Runtime/Pattern/Managers/UIManager.cs index 17c4b27..04d0aa7 100644 --- a/Runtime/Pattern/Managers/UIManager.cs +++ b/Runtime/Pattern/Managers/UIManager.cs @@ -35,10 +35,6 @@ public enum UIMethod // Implement IGameManager Interface - MonoBehaviour IGameManager.GetManagerClass() - { - return this; - } void IGameManager.InitiateManager(bool alwaysLoaded) { if (header == null) diff --git a/Runtime/ReadySet/Services/DespawnService.cs b/Runtime/ReadySet/Services/DespawnService.cs index 1f29816..6814b85 100644 --- a/Runtime/ReadySet/Services/DespawnService.cs +++ b/Runtime/ReadySet/Services/DespawnService.cs @@ -92,7 +92,7 @@ string IService.GetInspectorInfo() // Public Functions public void AddManager(IGameManager manager) { - System.Type ManagerType = manager.GetManagerClass().GetType(); + System.Type ManagerType = manager.Component.GetType(); if (Managers.ContainsKey(ManagerType)) { Managers.Add(ManagerType, manager); @@ -110,7 +110,7 @@ private static T GetManager() where T : MonoBehaviour System.Type type = typeof(T); if (Ins.Managers.ContainsKey(type)) { - if (Ins.Managers[type].GetManagerClass() is T manager) + if (Ins.Managers[type].Component is T manager) { return manager; } diff --git a/Runtime/ReadySet/Services/SpawanService.cs b/Runtime/ReadySet/Services/SpawanService.cs index 1103880..7a531b4 100644 --- a/Runtime/ReadySet/Services/SpawanService.cs +++ b/Runtime/ReadySet/Services/SpawanService.cs @@ -94,7 +94,7 @@ string IService.GetInspectorInfo() // Public Functions public void AddManager(IGameManager manager) { - System.Type ManagerType = manager.GetManagerClass().GetType(); + System.Type ManagerType = manager.Component.GetType(); if (Managers.ContainsKey(ManagerType)) { Managers.Add(ManagerType, manager); @@ -111,7 +111,7 @@ private static T GetManager() where T : MonoBehaviour System.Type type = typeof(T); if (Ins.Managers.ContainsKey(type)) { - if (Ins.Managers[type].GetManagerClass() is T manager) + if (Ins.Managers[type].Component is T manager) { return manager; } diff --git a/Tests/FileManager.cs b/Tests/FileManager.cs index ac0d214..3b22d88 100644 --- a/Tests/FileManager.cs +++ b/Tests/FileManager.cs @@ -24,10 +24,6 @@ public FileData(object Instance, BindingFlags flags) public event System.Action OnFileRemoved; // Implement IGameManager Interface - MonoBehaviour IGameManager.GetManagerClass() - { - return this; - } public virtual void InitiateManager(bool AlwaysLoaded) { From c7fd8e56c8e9120481faeaf480175ff9ec9c44ba Mon Sep 17 00:00:00 2001 From: Alijimpa Date: Wed, 29 Apr 2026 19:10:27 +0330 Subject: [PATCH 170/204] Refine Complitly Service Defenation to Service Locator --- Runtime/Core/Architecture/Game.cs | 129 +++++------------- Runtime/Core/Architecture/GameBridge.cs | 49 +------ Runtime/Core/Architecture/GameManager.cs | 11 -- Runtime/Core/Architecture/Service.cs | 48 +++---- Runtime/Core/Architecture/World.cs | 26 +--- Runtime/Core/Definitions/BackgroundService.cs | 80 +++++++++++ .../Definitions/BackgroundService.cs.meta | 2 + Runtime/Pattern/Managers/EnumeratorManager.cs | 5 - Runtime/Pattern/Managers/LogManager.cs | 23 ++++ Runtime/Pattern/Managers/LogManager.cs.meta | 2 + Runtime/Pattern/Managers/TaskManager.cs | 5 - Runtime/Pattern/Managers/UIManager.cs | 5 - Runtime/Pattern/Services/InputService.cs | 6 +- Runtime/Pattern/Services/RuleService.cs | 2 +- Runtime/Pattern/Services/StateService.cs | 2 +- Runtime/ReadySet/Essentials/DefaultGame.cs | 3 +- Runtime/ReadySet/Managers/ActionManager.cs | 3 - Runtime/ReadySet/Managers/CoroutineManager.cs | 3 - Runtime/ReadySet/Managers/HUDManager.cs | 3 - Runtime/ReadySet/Managers/MotionManager.cs | 3 - Runtime/ReadySet/Managers/ScreenManager.cs | 4 - Runtime/ReadySet/Services/DebugService.cs | 6 +- Runtime/ReadySet/Services/DespawnService.cs | 6 +- Runtime/ReadySet/Services/NetworkService.cs | 8 +- Runtime/ReadySet/Services/SpawanService.cs | 6 +- Runtime/ReadySet/Services/TimeService.cs | 6 +- 26 files changed, 187 insertions(+), 259 deletions(-) create mode 100644 Runtime/Core/Definitions/BackgroundService.cs create mode 100644 Runtime/Core/Definitions/BackgroundService.cs.meta create mode 100644 Runtime/Pattern/Managers/LogManager.cs create mode 100644 Runtime/Pattern/Managers/LogManager.cs.meta diff --git a/Runtime/Core/Architecture/Game.cs b/Runtime/Core/Architecture/Game.cs index 92ad915..475a41f 100644 --- a/Runtime/Core/Architecture/Game.cs +++ b/Runtime/Core/Architecture/Game.cs @@ -31,7 +31,7 @@ public enum GameProcess } /// - /// Core game singleton that manages the active , registered s, + /// Core game singleton that manages the active , registered s, /// configuration and high-level game lifecycle (initialization, start, and shutdown). /// Derive from this class to implement project-specific behavior for the game's lifecycle hooks. /// @@ -174,7 +174,7 @@ public ISaveSystem SaveSystem /// private IGameManager[] Managers; /// - /// List of runtime-registered instances owned by the game. + /// List of runtime-registered instances owned by the game. /// private readonly Dictionary Services = new(); @@ -183,7 +183,7 @@ public ISaveSystem SaveSystem /// /// Initializes the game singleton and core systems on subsystem registration. - /// This sets up the , game , + /// This sets up the , game , /// configuration, prefabs and managers and registers quit callbacks. /// Invoked when starting up the runtime. Called before the first scene is loaded. /// @@ -251,7 +251,7 @@ private static void InitializeGame() } } ((IRelationBridge)Bridge).BindWorldCreated(Instance.Notify_OnWorldInitiate); - ((IService)Bridge).Created(Instance); + ((IService)Bridge).OnRegister(Instance); // Set GameConfig if (ProjectSettings.GetGameConfigAsset() != null) @@ -414,111 +414,52 @@ public static T CastWorld() where T : class } } /// - /// Adds a new service of type to the game if one does not already exist. - /// Newly created service will be bound to managers and notified to the global service system. - /// - /// Service type to add. - /// The object responsible for creating the service (used for provider callbacks). - /// The newly created service instance, or null if a service of the same type already exists. - public static T AddService(object author) where T : Service, new() - { - // Check if you game not initialized - if (Bridge == null) - { - Debug.LogWarning($"Game doesn't initialized !"); - return null; - } - - // Create Service - T newService = new T(); - if (!RegisterService(newService, author)) - return null; - if (Instance.Managers != null) - { - foreach (var manager in Instance.Managers) - { - manager.ResolveService(newService, true); - } - } - ((IRelationBridge)Bridge).ServiceCreated(newService); - return newService; - } - /// /// Register new instance () that include 'IService' interface . - /// New Service instance register to the game if one des not already exist + /// New IService instance register to the game if one des not already exist /// /// Any Type can inplement 'IService' interface /// Any Instance can inplement 'IService' interface /// The object responsible for creating the service (used for provider callbacks). /// The newly created service instance, or null if a service of the same type already exists. - public static bool RegisterService(T service, object author) + public static bool RegisterService(T service, object author = null) where T : IService { - if (service is IService provider) - { - Type TypeService = typeof(T); - - if (Instance.Services.ContainsKey(TypeService)) - { - Debug.LogError($"Service {TypeService} already registered."); - return false; - } + Type TypeService = typeof(T); - provider.Created(author); - Instance.Services[TypeService] = provider; - return true; - } - else + if (Instance.Services.ContainsKey(TypeService)) { - Debug.LogError($"The class '{service.GetType().Name}' must implement the IService interface."); + Debug.LogError($"IService {TypeService} already registered."); return false; } - } - /// - /// Removes the service instance of type if present. - /// Managers and the global service system will be notified of the removal. - /// - /// Service type to remove. - /// The object requesting the removal (used for provider callbacks). - /// true if a service was found and removed; otherwise false. - public static bool RemoveService(object author) where T : Service - { - Type TypeService = typeof(T); - var provider = Instance.Services[TypeService]; - if (provider != null) - { - if (provider.Self is Service service) - { - if (Instance.Managers != null) - { - foreach (var manager in Instance.Managers) - { - manager.ResolveService(service, false); - } - } - ((IRelationBridge)Bridge).ServiceRemoved(service); - } - provider.Deleted(author); - Unregister(); - return true; - } - Debug.LogWarning($"Service of type {typeof(T).Name} not found to remove."); - return false; + service.OnRegister(author); + Instance.Services[TypeService] = service; + return true; } /// /// Remove service instance /// /// The object type that implement 'IService' - public static void Unregister() + public static bool Unregister(object author = null) where T : IService { - Instance.Services.Remove(typeof(T)); + Type TypeService = typeof(T); + + if (Instance.Services.ContainsKey(TypeService)) + { + Instance.Services[TypeService].OnUnregister(author); + return Instance.Services.Remove(typeof(T)); ; + } + else + { + Debug.LogWarning($"IService {TypeService} Not found."); + return false; + } } /// /// Retrieves the service instance of type if available. /// - /// Service type to retrieve. + /// IService type to retrieve. /// The service instance of type , or null if not found. - public static T GetService(bool Printdebug = true) + public static T GetService(bool Printdebug = true) where T : IService { Type TypeService = typeof(T); @@ -526,17 +467,17 @@ public static T GetService(bool Printdebug = true) return (T)provider.Self; if (Printdebug) - Debug.LogError($"Service {TypeService} not found."); + Debug.LogError($"IService {TypeService} not found."); return default; } /// /// Attempts to find a service of type . /// - /// Service type to find. + /// IService type to find. /// Out parameter that receives the service if found. /// true if the service was found; otherwise false. - public static bool TryGetService(out T service) where T : Service + public static bool TryGetService(out T service) where T : IService { if (Instance.Services.TryGetValue(typeof(T), out var provider)) { @@ -613,7 +554,7 @@ public static Coroutine OpenScene(string sceneName) } } /// - /// Requests a Add scene by build index via the configured . + /// Requests a Add scene by build index via the configured . /// If the requested scene is already active, a warning is logged and null is returned. /// /// Build index of the scene to open. @@ -708,7 +649,7 @@ public static Coroutine OpenWorld(WorldAsset WorldScene) } /// - /// Reloads the currently active scene via the configured . + /// Reloads the currently active scene via the configured . /// /// A driving the reload operation. public static Coroutine ReOpenScene() @@ -1129,7 +1070,7 @@ private void Notify_OnWorldInitiate(World NewWorld) { foreach (var service in Services) { - service.Value.ChangingWorld(NewWorld); + service.Value.OnWorldChanging(World, NewWorld); } World = NewWorld; OnWorldChanged(World); @@ -1145,11 +1086,11 @@ private void Notify_OnGameQuit() { foreach (var service in Services) { - service.Value.Deleted(this); + service.Value.OnUnregister(this); } ClearService(); } - ((IService)Bridge).Deleted(this); + ((IService)Bridge).OnUnregister(this); #if UNITY_EDITOR // Debug only: force GC to verify no references remain GC.Collect(); diff --git a/Runtime/Core/Architecture/GameBridge.cs b/Runtime/Core/Architecture/GameBridge.cs index 5dc96af..18bf307 100644 --- a/Runtime/Core/Architecture/GameBridge.cs +++ b/Runtime/Core/Architecture/GameBridge.cs @@ -37,25 +37,6 @@ public interface IRelationBridge /// void UnbindWorldCreated(); /// - /// Notifies the system that a service has been created. - /// - void ServiceCreated(Service service); - /// - /// Notifies the system that a service has been removed. - /// - void ServiceRemoved(Service service); - /// - /// Binds a callback invoked when services are added or removed. - /// - /// - /// Callback receiving the service instance and its active state. - /// - void BindServicesUpdated(Action func); - /// - /// Unbinds the service update callback. - /// - void UnbindServicesUpdated(); - /// /// Called by world class to tell game the initiation is complite /// void WorldIsReady(); @@ -105,7 +86,6 @@ public abstract class GameBridge : IService, IRelationBridge, ILoadScneBridge // Events private Action GameReadyEvent; private Action NewWorldEvent; - private Action ServiceEvents; private Action SceneLoadingEvent; private Action SceneLoadingProcessEvent; private bool isLoading; @@ -116,14 +96,15 @@ public abstract class GameBridge : IService, IRelationBridge, ILoadScneBridge public static bool SceneWillUnload { get; private set; } // Implement IService Interface - void IService.Created(object author) + void IService.OnRegister(object author) { SceneManager.activeSceneChanged += OnActiveSceneChanged; } - void IService.ChangingWorld(World NewWorld) + void IService.OnWorldChanging(World Previous, World New) { + throw new NotImplementedException(); } - void IService.Deleted(object author) + void IService.OnUnregister(object author) { SceneManager.activeSceneChanged -= OnActiveSceneChanged; } @@ -165,27 +146,6 @@ void IRelationBridge.UnbindWorldCreated() { NewWorldEvent = null; } - void IRelationBridge.ServiceCreated(Service service) - { - ServiceEvents?.Invoke(service, true); - } - void IRelationBridge.ServiceRemoved(Service service) - { - ServiceEvents.Invoke(service, false); - } - void IRelationBridge.BindServicesUpdated(Action func) - { - if (ServiceEvents != null) - { - Debug.LogWarning("BindServicesUpdated is already binded this interface is internal didnt use in another script or your game"); - return; - } - ServiceEvents = func; - } - void IRelationBridge.UnbindServicesUpdated() - { - ServiceEvents = null; - } void IRelationBridge.WorldIsReady() { GameReadyEvent?.Invoke(); @@ -537,5 +497,6 @@ private IEnumerator LoadWorldAsync(WorldAsset WS) isLoading = false; } + } } \ No newline at end of file diff --git a/Runtime/Core/Architecture/GameManager.cs b/Runtime/Core/Architecture/GameManager.cs index e73da09..658bf93 100644 --- a/Runtime/Core/Architecture/GameManager.cs +++ b/Runtime/Core/Architecture/GameManager.cs @@ -23,17 +23,6 @@ public interface IGameManager /// If true, the manager should persist and remain loaded at all times. /// void InitiateManager(bool AlwaysLoaded); - - /// - /// Enables or disables a service handled by this manager. - /// - /// - /// The service to be resolved or managed. - /// - /// - /// Indicates whether the service should be activated (true) or deactivated (false). - /// - void ResolveService(Service service, bool active); } } \ No newline at end of file diff --git a/Runtime/Core/Architecture/Service.cs b/Runtime/Core/Architecture/Service.cs index 92fead6..f9e13f0 100644 --- a/Runtime/Core/Architecture/Service.cs +++ b/Runtime/Core/Architecture/Service.cs @@ -13,16 +13,16 @@ public interface IService /// Called when the service is created. /// /// The object responsible for creating the service. - void Created(object author); + void OnRegister(object author); /// /// Called when the world or environment updates. /// - void ChangingWorld(World NewWorld); + void OnWorldChanging(World Previous, World New); /// /// Called when the service is deleted or destroyed. /// /// The object responsible for deleting the service. - void Deleted(object author); + void OnUnregister(object author); #if UNITY_EDITOR /// /// Returns a formatted string containing information about this service @@ -41,48 +41,32 @@ public interface IService public abstract class Service : IService { // Implement IService Interface - void IService.Created(object author) - { - OnStart(author); - } - void IService.ChangingWorld(World NewWorld) - { - OnWorldChanging(Game.World, NewWorld); - } - void IService.Deleted(object author) - { - OnEnd(author); - } -# if UNITY_EDITOR - string IService.GetInspectorInfo() - { - return GetDisplayInfo(); - } - protected virtual string GetDisplayInfo() - { - return GetType().ToString() + ": "; - } -#endif - - - /// /// Called when the service starts. Must be implemented by derived classes. /// /// The object responsible for creating the service. - protected abstract void OnStart(object Author); + public abstract void OnRegister(object author); /// /// Called when a new world or environment is initialized. /// Must be implemented by derived classes. /// - protected abstract void OnWorldChanging(World Previous, World New); + public abstract void OnWorldChanging(World Previous, World New); /// /// Called when the service ends or is deleted. /// Must be implemented by derived classes. /// /// The object responsible for deleting the service. - protected abstract void OnEnd(object Author); - + public abstract void OnUnregister(object author); +#if UNITY_EDITOR + string IService.GetInspectorInfo() + { + return GetDisplayInfo(); + } + protected virtual string GetDisplayInfo() + { + return GetType().ToString() + ": "; + } +#endif } diff --git a/Runtime/Core/Architecture/World.cs b/Runtime/Core/Architecture/World.cs index 259a0f2..066adc6 100644 --- a/Runtime/Core/Architecture/World.cs +++ b/Runtime/Core/Architecture/World.cs @@ -98,11 +98,7 @@ private void Awake() { //Connect to Game With Bridge IRelationBridge SyncProvider = Game.Bridge; - if (SyncProvider.RegisterWorld(this)) - { - SyncProvider.BindServicesUpdated(Notify_OnServicesUpdated); - } - else + if (!SyncProvider.RegisterWorld(this)) { return; } @@ -182,8 +178,6 @@ private void FixedUpdate() /// private void OnDestroy() { - IRelationBridge SyncProvider = Game.Bridge; - SyncProvider.UnbindServicesUpdated(); WorldEnd(); } @@ -378,24 +372,6 @@ protected virtual Transform SelectSpawnPoint(PlayerStarter[] starters) } - /// - /// Internal callback invoked when services are updated. Forwards the service update - /// to all managers so they can resolve or react to the change. - /// - /// The service that changed. - /// The stage or phase of the service update. - private void Notify_OnServicesUpdated(Service NewService, bool stage) - { - if (Managers != null) - { - foreach (var manager in Managers) - { - manager.ResolveService(NewService, stage); - } - } - } - - /// /// Called after the world is initialized in the context of this scene. /// If this world is the main world, this runs normally. diff --git a/Runtime/Core/Definitions/BackgroundService.cs b/Runtime/Core/Definitions/BackgroundService.cs new file mode 100644 index 0000000..cad076a --- /dev/null +++ b/Runtime/Core/Definitions/BackgroundService.cs @@ -0,0 +1,80 @@ +namespace RealMethod +{ + public abstract class BackgroundService : Service + { + public override void OnRegister(object Author) + { + throw new System.NotImplementedException(); + } + public override void OnWorldChanging(World Previous, World New) + { + throw new System.NotImplementedException(); + } + public override void OnUnregister(object Author) + { + throw new System.NotImplementedException(); + } + } + + + + + public class AnalyticsService : BackgroundService + { + public void Track(string eventName, params object[] arguments) { } + public void LevelStart(int levelIndex) { } + public void LevelComplete(int levelIndex) { } + public void Error(string message, string stacktrace = "") { } + } + public class CloudService : BackgroundService + { + public void Save(object data) { } + public void Load(System.Action onLoaded) { } + public void Sync() { } + } + public class AuthService : BackgroundService + { + public void LoginGuest() { } + public void LoginGoogle() { } + public void LoginApple() { } + public void Logout() { } + public string GetUserId() { return ""; } + } + public class RemoteConfigService : BackgroundService + { + public void Refresh(System.Action onComplete = null) { } + public T Get(string key, T defaultValue = default) { return defaultValue; } + } + // public class LogService : BackgroundService + // { + // public void Info(string message) { } + // public void Warning(string message) { } + // public void Error(string message) { } + // } + public class StoreService : RemoteConfigService + { + public void Purchase(string productId) { } + public void RestorePurchases() { } + } + public class SettingsService : StoreService + { + public float Volume { get; set; } + public string Language { get; set; } + public int GraphicsQuality { get; set; } + + public void Load() { } + public void Save() { } + } + public class DeviceService : StoreService + { + public string UniqueID => ""; + public string Platform => ""; + public int Memory => 0; + } + // public class DebugService : DeviceService + // { + // public void ShowFPS(bool active) { } + // public void ShowToast(string message) { } + // public void SetGodMode(bool active) { } + // } +} \ No newline at end of file diff --git a/Runtime/Core/Definitions/BackgroundService.cs.meta b/Runtime/Core/Definitions/BackgroundService.cs.meta new file mode 100644 index 0000000..5fe6ce8 --- /dev/null +++ b/Runtime/Core/Definitions/BackgroundService.cs.meta @@ -0,0 +1,2 @@ +fileFormatVersion: 2 +guid: 34f4b741d9061d44e9155bc4c54b190c \ No newline at end of file diff --git a/Runtime/Pattern/Managers/EnumeratorManager.cs b/Runtime/Pattern/Managers/EnumeratorManager.cs index 66ce41d..716812e 100644 --- a/Runtime/Pattern/Managers/EnumeratorManager.cs +++ b/Runtime/Pattern/Managers/EnumeratorManager.cs @@ -70,10 +70,6 @@ void IGameManager.InitiateManager(bool AlwaysLoaded) { InitiateManager(AlwaysLoaded); } - void IGameManager.ResolveService(Service service, bool active) - { - InitiateService(service); - } // Unity Methods @@ -108,7 +104,6 @@ public void Stop(Coroutine coroutine) // Abstract Methods protected abstract void InitiateManager(bool alwaysLoaded); - protected abstract void InitiateService(Service newService); } diff --git a/Runtime/Pattern/Managers/LogManager.cs b/Runtime/Pattern/Managers/LogManager.cs new file mode 100644 index 0000000..296571e --- /dev/null +++ b/Runtime/Pattern/Managers/LogManager.cs @@ -0,0 +1,23 @@ +using UnityEngine; + +namespace RealMethod +{ + public class LogManager : MonoBehaviour, IGameManager + { + void IGameManager.InitiateManager(bool AlwaysLoaded) + { + if (!AlwaysLoaded) + { + Debug.LogError("LogManager should be Initiate in GameScope."); + Destroy(this); + } + } + + + + + + + + } +} \ No newline at end of file diff --git a/Runtime/Pattern/Managers/LogManager.cs.meta b/Runtime/Pattern/Managers/LogManager.cs.meta new file mode 100644 index 0000000..3195380 --- /dev/null +++ b/Runtime/Pattern/Managers/LogManager.cs.meta @@ -0,0 +1,2 @@ +fileFormatVersion: 2 +guid: 964d17416768e4540aca53dd2e600936 \ No newline at end of file diff --git a/Runtime/Pattern/Managers/TaskManager.cs b/Runtime/Pattern/Managers/TaskManager.cs index fbcf2a3..fd45f05 100644 --- a/Runtime/Pattern/Managers/TaskManager.cs +++ b/Runtime/Pattern/Managers/TaskManager.cs @@ -20,14 +20,9 @@ void IGameManager.InitiateManager(bool AlwaysLoaded) { InitiateManager(AlwaysLoaded); } - void IGameManager.ResolveService(Service service, bool active) - { - ResolveService(service); - } // Abstract Methods protected abstract void InitiateManager(bool alwaysLoaded); - protected abstract void ResolveService(Service service); } public abstract class TaskManager : TaskManager where J : IHandle { diff --git a/Runtime/Pattern/Managers/UIManager.cs b/Runtime/Pattern/Managers/UIManager.cs index 04d0aa7..98e2510 100644 --- a/Runtime/Pattern/Managers/UIManager.cs +++ b/Runtime/Pattern/Managers/UIManager.cs @@ -71,10 +71,6 @@ void IGameManager.InitiateManager(bool alwaysLoaded) InitiateManager(alwaysLoaded); } - void IGameManager.ResolveService(Service service, bool active) - { - InitiateService(service); - } // Unity Methods @@ -547,7 +543,6 @@ public T FindClassInLayers() where T : class // Abstract Methods protected abstract void InitiateManager(bool alwaysLoaded); - protected abstract void InitiateService(Service newService); //Enumerators private IEnumerator FadeIn(CanvasGroup canvas, float fadeDuration) diff --git a/Runtime/Pattern/Services/InputService.cs b/Runtime/Pattern/Services/InputService.cs index c4555ed..0e39f95 100644 --- a/Runtime/Pattern/Services/InputService.cs +++ b/Runtime/Pattern/Services/InputService.cs @@ -7,21 +7,21 @@ public abstract class InputService : Service { private InputActionAsset CurrentInputAsset; - protected sealed override void OnStart(object Author) + public sealed override void OnRegister(object Author) { if (TryFindInputAsset(out InputActionAsset newAsset)) { ReplaceInputAsset(newAsset); } } - protected sealed override void OnWorldChanging(World Previous , World New) + public sealed override void OnWorldChanging(World Previous, World New) { if (TryFindInputAsset(out InputActionAsset newAsset)) { ReplaceInputAsset(newAsset); } } - protected sealed override void OnEnd(object Author) + public sealed override void OnUnregister(object Author) { if (CurrentInputAsset != null) { diff --git a/Runtime/Pattern/Services/RuleService.cs b/Runtime/Pattern/Services/RuleService.cs index ce9fa40..6c032f4 100644 --- a/Runtime/Pattern/Services/RuleService.cs +++ b/Runtime/Pattern/Services/RuleService.cs @@ -13,7 +13,7 @@ public RuleService() Rules = new NameTable>(5); } - protected override void OnWorldChanging(World Previous, World New) + public override void OnWorldChanging(World Previous, World New) { foreach (var item in Rules) { diff --git a/Runtime/Pattern/Services/StateService.cs b/Runtime/Pattern/Services/StateService.cs index 884bd27..2e36aa7 100644 --- a/Runtime/Pattern/Services/StateService.cs +++ b/Runtime/Pattern/Services/StateService.cs @@ -16,7 +16,7 @@ public StateService(byte firstState) } // StateService Methods - protected sealed override void OnWorldChanging(World Previous , World New) + public sealed override void OnWorldChanging(World Previous , World New) { if (CanResetforNewWorld(Game.World)) { diff --git a/Runtime/ReadySet/Essentials/DefaultGame.cs b/Runtime/ReadySet/Essentials/DefaultGame.cs index 1be472d..56603ef 100644 --- a/Runtime/ReadySet/Essentials/DefaultGame.cs +++ b/Runtime/ReadySet/Essentials/DefaultGame.cs @@ -12,7 +12,8 @@ protected override void OnGameOpen() } protected override void OnGameInitialized() { - AddService(this); + //DebugService NewDebug = new DebugService(); + //RegisterService(NewDebug, this); Debug.Log("DefultGame Initialized"); } protected override void OnGameStart() diff --git a/Runtime/ReadySet/Managers/ActionManager.cs b/Runtime/ReadySet/Managers/ActionManager.cs index f1da9a4..8b10599 100644 --- a/Runtime/ReadySet/Managers/ActionManager.cs +++ b/Runtime/ReadySet/Managers/ActionManager.cs @@ -37,9 +37,6 @@ protected override void InitiateManager(bool alwaysLoaded) } } } - protected override void ResolveService(Service service) - { - } protected override bool TryCreateNewInstance

(object ClassType, out P result) { if (ClassType is ActionClass ActionType) diff --git a/Runtime/ReadySet/Managers/CoroutineManager.cs b/Runtime/ReadySet/Managers/CoroutineManager.cs index cecca45..16b7c77 100644 --- a/Runtime/ReadySet/Managers/CoroutineManager.cs +++ b/Runtime/ReadySet/Managers/CoroutineManager.cs @@ -9,9 +9,6 @@ public class CoroutineManager : EnumeratorManager protected override void InitiateManager(bool alwaysLoaded) { } - protected override void InitiateService(Service service) - { - } } } \ No newline at end of file diff --git a/Runtime/ReadySet/Managers/HUDManager.cs b/Runtime/ReadySet/Managers/HUDManager.cs index 5ee195f..a2a00d3 100644 --- a/Runtime/ReadySet/Managers/HUDManager.cs +++ b/Runtime/ReadySet/Managers/HUDManager.cs @@ -10,9 +10,6 @@ public sealed class HUDManager : UIManager protected override void InitiateManager(bool alwaysLoaded) { } - protected override void InitiateService(Service newService) - { - } } } \ No newline at end of file diff --git a/Runtime/ReadySet/Managers/MotionManager.cs b/Runtime/ReadySet/Managers/MotionManager.cs index b120c0e..1e83ba3 100644 --- a/Runtime/ReadySet/Managers/MotionManager.cs +++ b/Runtime/ReadySet/Managers/MotionManager.cs @@ -234,9 +234,6 @@ protected override void InitiateManager(bool alwaysLoaded) } } } - protected override void ResolveService(Service service) - { - } protected override bool TryCreateNewInstance

(object ClassType, out P result) { if (ClassType is PrimitiveAsset asset) diff --git a/Runtime/ReadySet/Managers/ScreenManager.cs b/Runtime/ReadySet/Managers/ScreenManager.cs index 3419a6b..160ffba 100644 --- a/Runtime/ReadySet/Managers/ScreenManager.cs +++ b/Runtime/ReadySet/Managers/ScreenManager.cs @@ -26,10 +26,6 @@ protected override void InitiateManager(bool alwaysLoaded) Game.OnSceneLoading += (value) => OnLoadScne?.Invoke(value); Game.OnSceneLoadingProcess += (value) => OnLoading?.Invoke(value); } - protected override void InitiateService(Service newService) - { - } - public void SetInformer(IInformer messanger) { Informer = messanger; diff --git a/Runtime/ReadySet/Services/DebugService.cs b/Runtime/ReadySet/Services/DebugService.cs index 6f3819c..8faf239 100644 --- a/Runtime/ReadySet/Services/DebugService.cs +++ b/Runtime/ReadySet/Services/DebugService.cs @@ -160,15 +160,15 @@ void ILogHandler.LogException(System.Exception exception, Object context) // Service Methods - protected override void OnStart(object Author) + public override void OnRegister(object Author) { defaultLogHandler = Debug.unityLogger.logHandler; Debug.unityLogger.logHandler = this; } - protected override void OnWorldChanging(World Previous, World New) + public override void OnWorldChanging(World Previous, World New) { } - protected override void OnEnd(object Author) + public override void OnUnregister(object Author) { if (defaultLogHandler != null) Debug.unityLogger.logHandler = defaultLogHandler; diff --git a/Runtime/ReadySet/Services/DespawnService.cs b/Runtime/ReadySet/Services/DespawnService.cs index 6814b85..fe0d949 100644 --- a/Runtime/ReadySet/Services/DespawnService.cs +++ b/Runtime/ReadySet/Services/DespawnService.cs @@ -71,14 +71,14 @@ public Despawn(Dictionary DefaultManager) // Implement IService Interface public object GetServiceClass() => this; - void IService.Created(object Author) + void IService.OnRegister(object Author) { } - void IService.ChangingWorld(World NewWorld) + void IService.OnWorldChanging(World Previous, World New) { Managers.Clear(); } - void IService.Deleted(object Author) + void IService.OnUnregister(object Author) { Managers.Clear(); } diff --git a/Runtime/ReadySet/Services/NetworkService.cs b/Runtime/ReadySet/Services/NetworkService.cs index d3ae787..8f4de01 100644 --- a/Runtime/ReadySet/Services/NetworkService.cs +++ b/Runtime/ReadySet/Services/NetworkService.cs @@ -16,15 +16,15 @@ public sealed class NetworkService : Service - protected override void OnStart(object Author) + public override void OnRegister(object Author) { throw new NotImplementedException(); } - protected override void OnWorldChanging(World Previous , World New) + public override void OnWorldChanging(World Previous, World New) { throw new NotImplementedException(); } - protected override void OnEnd(object Author) + public override void OnUnregister(object Author) { throw new NotImplementedException(); } @@ -81,7 +81,7 @@ public IEnumerator DownloadImage(Action callback) callback(DownloadHandlerTexture.GetContent(request)); } - + } diff --git a/Runtime/ReadySet/Services/SpawanService.cs b/Runtime/ReadySet/Services/SpawanService.cs index 7a531b4..05d6c96 100644 --- a/Runtime/ReadySet/Services/SpawanService.cs +++ b/Runtime/ReadySet/Services/SpawanService.cs @@ -73,14 +73,14 @@ public Spawn(Dictionary DefaultManager) // Implement IService Interface public object GetServiceClass() => this; - void IService.Created(object Author) + void IService.OnRegister(object Author) { } - void IService.ChangingWorld(World NewWorld) + void IService.OnWorldChanging(World Previous, World New) { Managers.Clear(); } - void IService.Deleted(object Author) + void IService.OnUnregister(object Author) { Managers.Clear(); } diff --git a/Runtime/ReadySet/Services/TimeService.cs b/Runtime/ReadySet/Services/TimeService.cs index b5151b1..45805b4 100644 --- a/Runtime/ReadySet/Services/TimeService.cs +++ b/Runtime/ReadySet/Services/TimeService.cs @@ -9,17 +9,17 @@ public sealed class TimeService : Service private NameTable RecordTime; // Service Methods - protected override void OnStart(object Author) + public override void OnRegister(object Author) { serviceTime = Time.time; worldTime = Time.time; RecordTime = new NameTable(10); } - protected override void OnWorldChanging(World Previous , World New) + public override void OnWorldChanging(World Previous, World New) { worldTime = Time.time; } - protected override void OnEnd(object Author) + public override void OnUnregister(object Author) { RecordTime.Clear(); } From 8d98de568f2ac9d5b838435ebf930696fc5ca173 Mon Sep 17 00:00:00 2001 From: Alijimpa Date: Thu, 30 Apr 2026 09:19:44 +0330 Subject: [PATCH 171/204] Fix with new Service System --- Runtime/ReadySet/Services/DespawnService.cs | 4 ++-- Runtime/ReadySet/Services/SpawanService.cs | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/Runtime/ReadySet/Services/DespawnService.cs b/Runtime/ReadySet/Services/DespawnService.cs index fe0d949..166c6e6 100644 --- a/Runtime/ReadySet/Services/DespawnService.cs +++ b/Runtime/ReadySet/Services/DespawnService.cs @@ -45,11 +45,11 @@ private static Despawn Ins { get { - var CacheInstance = Game.GetService(false); + var CacheInstance = Game.GetService(); if (CacheInstance == null) { CacheInstance = new Despawn(); - Game.RegisterService(CacheInstance, null); + Game.Register(CacheInstance, null); } return CacheInstance; } diff --git a/Runtime/ReadySet/Services/SpawanService.cs b/Runtime/ReadySet/Services/SpawanService.cs index 05d6c96..6f200e6 100644 --- a/Runtime/ReadySet/Services/SpawanService.cs +++ b/Runtime/ReadySet/Services/SpawanService.cs @@ -48,11 +48,11 @@ private static Spawn Ins { get { - var CacheInstance = Game.GetService(false); + var CacheInstance = Game.GetService(); if (CacheInstance == null) { CacheInstance = new Spawn(); - Game.RegisterService(CacheInstance, null); + Game.Register(CacheInstance, null); } return CacheInstance; } From 8e0d2fa5018dbb8361c4a7187bb440bb595e8ab7 Mon Sep 17 00:00:00 2001 From: Alijimpa Date: Thu, 30 Apr 2026 12:45:14 +0330 Subject: [PATCH 172/204] Convet to Interface --- Runtime/Core/Architecture/Game.cs | 58 ++++++-- Runtime/Core/Definitions/BackgroundService.cs | 124 +++++++++--------- 2 files changed, 108 insertions(+), 74 deletions(-) diff --git a/Runtime/Core/Architecture/Game.cs b/Runtime/Core/Architecture/Game.cs index 475a41f..44fc836 100644 --- a/Runtime/Core/Architecture/Game.cs +++ b/Runtime/Core/Architecture/Game.cs @@ -414,14 +414,28 @@ public static T CastWorld() where T : class } } ///

- /// Register new instance () that include 'IService' interface . - /// New IService instance register to the game if one des not already exist - /// - /// Any Type can inplement 'IService' interface - /// Any Instance can inplement 'IService' interface - /// The object responsible for creating the service (used for provider callbacks). - /// The newly created service instance, or null if a service of the same type already exists. - public static bool RegisterService(T service, object author = null) where T : IService + /// Registers a service instance of type in the service container. + /// + /// + /// The type of the service to register. Must implement . + /// + /// + /// The service instance to register. + /// + /// + /// Optional object providing context or ownership information for the registration. + /// Passed to . + /// + /// + /// true if the service was successfully registered; + /// false if a service of the same type is already registered. + /// + /// + /// This method prevents duplicate registrations. If a service of the same type + /// is already registered, an error is logged and the method returns false. + /// Upon successful registration, is invoked. + /// + public static bool Register(T service, object author = null) where T : IService { Type TypeService = typeof(T); @@ -434,6 +448,21 @@ public static bool RegisterService(T service, object author = null) where T : service.OnRegister(author); Instance.Services[TypeService] = service; return true; + + } + /// + /// Checks whether a service of type is currently registered + /// in the Service Locator. + /// + /// + /// The type of service to check. The type must implement . + /// + /// + /// true if a service of type is registered; otherwise false. + /// + public static bool IsRegistered() where T : IService + { + return Instance.Services.ContainsKey(typeof(T)); } /// /// Remove service instance @@ -446,7 +475,7 @@ public static bool Unregister(object author = null) where T : IService if (Instance.Services.ContainsKey(TypeService)) { Instance.Services[TypeService].OnUnregister(author); - return Instance.Services.Remove(typeof(T)); ; + return Instance.Services.Remove(TypeService); ; } else { @@ -459,17 +488,14 @@ public static bool Unregister(object author = null) where T : IService /// /// IService type to retrieve. /// The service instance of type , or null if not found. - public static T GetService(bool Printdebug = true) where T : IService + public static T GetService() where T : IService { Type TypeService = typeof(T); if (Instance.Services.TryGetValue(TypeService, out var provider)) return (T)provider.Self; - if (Printdebug) - Debug.LogError($"IService {TypeService} not found."); - - return default; + throw new Exception($"Service {TypeService} not registered."); } /// /// Attempts to find a service of type . @@ -493,6 +519,10 @@ public static bool TryGetService(out T service) where T : IService /// public static void ClearService() { + foreach (var service in Instance.Services.Values) + { + service.OnUnregister(null); + } Instance.Services.Clear(); } /// diff --git a/Runtime/Core/Definitions/BackgroundService.cs b/Runtime/Core/Definitions/BackgroundService.cs index cad076a..59d8f3b 100644 --- a/Runtime/Core/Definitions/BackgroundService.cs +++ b/Runtime/Core/Definitions/BackgroundService.cs @@ -1,80 +1,84 @@ namespace RealMethod { - public abstract class BackgroundService : Service + public interface IAnalyticsService { - public override void OnRegister(object Author) - { - throw new System.NotImplementedException(); - } - public override void OnWorldChanging(World Previous, World New) - { - throw new System.NotImplementedException(); - } - public override void OnUnregister(object Author) - { - throw new System.NotImplementedException(); - } + void Track(string eventName, params object[] arguments); + void LevelStart(int levelIndex); + void LevelComplete(int levelIndex); + void Error(string message, string stacktrace = ""); } - - - - - public class AnalyticsService : BackgroundService + public interface ICloudService + { + void Save(object data); + void Load(System.Action onLoaded); + void Sync(); + } + public interface IAuthService + { + void LoginGuest(); + void LoginGoogle(); + void LoginApple(); + void Logout(); + string GetUserId(); + } + public interface ILeaderboardService { - public void Track(string eventName, params object[] arguments) { } - public void LevelStart(int levelIndex) { } - public void LevelComplete(int levelIndex) { } - public void Error(string message, string stacktrace = "") { } + void Submit(int score); + void GetTop(int count, System.Action onResult); + void GetAroundPlayer(System.Action onResult); } - public class CloudService : BackgroundService + public interface IRemoteConfigService { - public void Save(object data) { } - public void Load(System.Action onLoaded) { } - public void Sync() { } + void Refresh(System.Action onComplete = null); + T Get(string key, T defaultValue = default); } - public class AuthService : BackgroundService + public interface ILogService { - public void LoginGuest() { } - public void LoginGoogle() { } - public void LoginApple() { } - public void Logout() { } - public string GetUserId() { return ""; } + void Info(string message); + void Warning(string message); + void Error(string message); } - public class RemoteConfigService : BackgroundService + public interface IStoreService { - public void Refresh(System.Action onComplete = null) { } - public T Get(string key, T defaultValue = default) { return defaultValue; } + void Purchase(string productId); + void RestorePurchases(); } - // public class LogService : BackgroundService - // { - // public void Info(string message) { } - // public void Warning(string message) { } - // public void Error(string message) { } - // } - public class StoreService : RemoteConfigService + public interface INotificationService { - public void Purchase(string productId) { } - public void RestorePurchases() { } + void Schedule(string message, int delaySeconds); + void CancelAll(); } - public class SettingsService : StoreService + public interface ISettingsService { - public float Volume { get; set; } - public string Language { get; set; } - public int GraphicsQuality { get; set; } + float Volume { get; set; } + string Language { get; set; } + int GraphicsQuality { get; set; } - public void Load() { } - public void Save() { } + void Load(); + void Save(); } - public class DeviceService : StoreService + public interface IDeviceService { - public string UniqueID => ""; - public string Platform => ""; - public int Memory => 0; + string UniqueID { get; } + string Platform { get; } + int Memory { get; } } - // public class DebugService : DeviceService - // { - // public void ShowFPS(bool active) { } - // public void ShowToast(string message) { } - // public void SetGodMode(bool active) { } - // } + public interface IDebugService + { + void ShowFPS(bool active); + void ShowToast(string message); + void SetGodMode(bool active); + } + + + public interface ILogSystem + { + void Log(object message, UnityEngine.Object context); + void LogWarning(object message, UnityEngine.Object context); + void LogError(object message, UnityEngine.Object context); + //void LogException(Exception exception, UnityEngine.Object context); + void Assert(object message, UnityEngine.Object context); + } + + } \ No newline at end of file From 353f49d3a1285090c40978b28b50be63c72d39a6 Mon Sep 17 00:00:00 2001 From: Alijimpa Date: Thu, 30 Apr 2026 16:07:35 +0330 Subject: [PATCH 173/204] Refactor Game&World With now System Defenation --- Runtime/Core/Architecture/Game.cs | 125 +++++------------------ Runtime/Core/Architecture/GameManager.cs | 6 +- Runtime/Core/Architecture/Scope.cs | 110 ++++++++++++++++++++ Runtime/Core/Architecture/Scope.cs.meta | 2 + Runtime/Core/Architecture/World.cs | 53 +--------- 5 files changed, 140 insertions(+), 156 deletions(-) create mode 100644 Runtime/Core/Architecture/Scope.cs create mode 100644 Runtime/Core/Architecture/Scope.cs.meta diff --git a/Runtime/Core/Architecture/Game.cs b/Runtime/Core/Architecture/Game.cs index 44fc836..c6abec7 100644 --- a/Runtime/Core/Architecture/Game.cs +++ b/Runtime/Core/Architecture/Game.cs @@ -35,7 +35,7 @@ public enum GameProcess /// configuration and high-level game lifecycle (initialization, start, and shutdown). /// Derive from this class to implement project-specific behavior for the game's lifecycle hooks. /// - public abstract class Game : MonoBehaviour + public abstract class Game : Scope { /// /// Singleton instance of the active game. @@ -169,10 +169,8 @@ public ISaveSystem SaveSystem return result; } } - /// - /// Cached array of managers that were instantiated from configured game prefabs. - /// - private IGameManager[] Managers; + + /// /// List of runtime-registered instances owned by the game. /// @@ -264,26 +262,12 @@ private static void InitializeGame() } // Initiate GamePrefab & Managers - HashSet CashManagers = new HashSet(); - + GameObject[] Objects = new GameObject[3]; if (ProjectSettings.GetPrefab_1() != null) { GameObject newobj = Instantiate(ProjectSettings.GetPrefab_1()); newobj.name = "GameScope(Runtime)"; - foreach (var manager in newobj.GetComponents()) - { - if (!CashManagers.Contains(manager)) - { - manager.InitiateManager(true); - CashManagers.Add(manager); - } - else - { - Debug.LogError($"You should not use a manager {manager} twice"); - throw new NotImplementedException(); - } - - } + Objects[0] = newobj; newobj.transform.SetParent(RealObject.transform); } #if UNITY_EDITOR @@ -291,20 +275,7 @@ private static void InitializeGame() { GameObject newobj = Instantiate(ProjectSettings.GetPrefab_2()); newobj.name = "GameScope(Editor)"; - foreach (var manager in newobj.GetComponents()) - { - if (!CashManagers.Contains(manager)) - { - manager.InitiateManager(true); - CashManagers.Add(manager); - } - else - { - Debug.LogError($"You should not use a manager {manager} twice"); - throw new NotImplementedException(); - } - - } + Objects[1] = newobj; newobj.transform.SetParent(RealObject.transform); } #endif @@ -313,24 +284,12 @@ private static void InitializeGame() { GameObject newobj = Instantiate(ProjectSettings.GetPrefab_3()); newobj.name = "GameScope(Server)"; - foreach (var manager in newobj.GetComponents()) - { - if (!CashManagers.Contains(manager)) - { - manager.InitiateManager(true); - CashManagers.Add(manager); - } - else - { - Debug.LogError($"You should not use a manager {manager} twice"); - throw new NotImplementedException(); - } - - } + Objects[2] = newobj; newobj.transform.SetParent(RealObject.transform); } #endif - Instance.Managers = CashManagers.ToArray(); + Instance.CollectManagers(Objects); + // Unload Project Setting Resources.UnloadAsset(ProjectSettings); @@ -687,25 +646,24 @@ public static Coroutine ReOpenScene() return Instance.StartCoroutine(Bridge.GetLoadScneCorotine(SceneManager.GetActiveScene().name)); ; } /// - /// Finds a manager of type in the current , - /// falling back to the global game managers if not found. + /// Retrieves a manager of type from the active manager scopes. + /// The search is performed in the following order: + /// 1. The current World scope (if available). + /// 2. The global Instance scope. /// - /// Manager type to find. - /// An instance of the manager if found; otherwise null. - public static T GetManager() where T : MonoBehaviour + /// The type of manager to retrieve. + /// + /// The manager of type if found; otherwise null. + /// + public static T GetManager() where T : Component, IGameManager { - T Result = null; + if (World != null && World.TryFindManager(out T worldResult)) + return worldResult; - if (World != null) - { - Result = World.FindManager(); - } + if (Instance.TryFindManager(out T gameResult)) + return gameResult; - if (Result != null) - { - return Result; - } - return Instance.FindManager(); + return null; } /// /// Parents the provided GameObject to the game root instance. @@ -1013,43 +971,6 @@ public static void Erase(IDrawTask element) - - /// - /// Retrieves a manager of type from this game's instantiated managers. - /// - /// Manager type to retrieve. - /// The manager instance if found; otherwise null. - public T FindManager() where T : class - { - foreach (var manager in Managers) - { - if (manager.Component is T Result) - { - return Result; - } - } - return null; - } - /// - /// Retrieves an by the name of its GameObject. - /// - /// Name of the manager GameObject to find. - /// The matching , or null if none match. - public IGameManager FindManager(string ObjectName) - { - foreach (var manger in Managers) - { - if (manger.Component.gameObject.name == ObjectName) - { - return manger; - } - } - return null; - } - - - - /// /// Called after GameInstance Created befor GameBridge , GameConfig & Managers Initilized /// if you use custom PtojectSetttingAsset class you can use instances after loaded in game diff --git a/Runtime/Core/Architecture/GameManager.cs b/Runtime/Core/Architecture/GameManager.cs index 658bf93..e1f9de9 100644 --- a/Runtime/Core/Architecture/GameManager.cs +++ b/Runtime/Core/Architecture/GameManager.cs @@ -19,10 +19,10 @@ public interface IGameManager /// /// Initializes the manager and prepares it for use in the game lifecycle. /// - /// - /// If true, the manager should persist and remain loaded at all times. + /// + /// Whitch owner class Initiation the manager /// - void InitiateManager(bool AlwaysLoaded); + void InitiateManager(Scope owner); } } \ No newline at end of file diff --git a/Runtime/Core/Architecture/Scope.cs b/Runtime/Core/Architecture/Scope.cs new file mode 100644 index 0000000..062205f --- /dev/null +++ b/Runtime/Core/Architecture/Scope.cs @@ -0,0 +1,110 @@ +using System.Collections.Generic; +using System.Linq; +using UnityEngine; + +namespace RealMethod +{ + public abstract class Scope : MonoBehaviour + { + /// + /// Cached array of managers that were instantiated from configured game prefabs or World gameobject. + /// + private IGameManager[] Managers = null; + /// + /// Cached array of managers that were instantiated from configured game prefabs or World gameobject. + /// + // public IReadOnlyList manager => Managers; + + + /// + /// Attempts to find a manager whose Component matches the specified type . + /// + /// The component type to search for. + /// + /// When this method returns, contains the found component of type if successful; + /// otherwise null. + /// + /// + /// true if a matching manager component was found; otherwise false. + /// + public bool TryFindManager(out T result) where T : Component, IGameManager + { + result = null; + + if (Managers == null) + return false; + + foreach (var manager in Managers) + { + if (manager?.Component is T found) + { + result = found; + return true; + } + } + + return false; + } + + + + /// + /// Collects all components from the provided GameObjects, + /// initializes them, and stores them internally. + /// + /// This method can only be executed once. If it is called again after managers + /// have already been collected, an error will be logged and the method will exit. + /// + /// Duplicate manager instances are ignored and logged as warnings. + /// + /// + /// Array of GameObjects to search for components. + /// Null objects in the array are skipped. + /// + protected void CollectManagers(GameObject[] Objects) + { + if (Objects == null) + { + Debug.LogError("CollectManagers received a null GameObjects array."); + return; + } + + + if (Managers != null) + { + Debug.LogError("CollectManagers was called more than once. This is not allowed."); + return; + } + + HashSet managerCache = new HashSet(); + for (int i = 0; i < Objects.Length; i++) + { + GameObject Obj = Objects[i]; + if (Obj == null) + continue; + + var found = Obj.GetComponents(); + + foreach (var manager in found) + { + if (managerCache.Add(manager)) + { + manager.InitiateManager(this); + } + else + { + Debug.LogWarning($"Duplicate manager detected: {manager.GetType().Name} in {manager.Component.gameObject.name}"); + continue; + } + } + } + Managers = managerCache.ToArray(); + } + + + + } + + + +} \ No newline at end of file diff --git a/Runtime/Core/Architecture/Scope.cs.meta b/Runtime/Core/Architecture/Scope.cs.meta new file mode 100644 index 0000000..f8577a3 --- /dev/null +++ b/Runtime/Core/Architecture/Scope.cs.meta @@ -0,0 +1,2 @@ +fileFormatVersion: 2 +guid: cdc1d3e86457c474ca9464cbbf61f0f6 \ No newline at end of file diff --git a/Runtime/Core/Architecture/World.cs b/Runtime/Core/Architecture/World.cs index 066adc6..1f94f65 100644 --- a/Runtime/Core/Architecture/World.cs +++ b/Runtime/Core/Architecture/World.cs @@ -77,14 +77,13 @@ protected virtual void OnDrawGizmos() /// and to perform /// world-specific initialization and cleanup. /// - public abstract class World : MonoBehaviour + public abstract class World : Scope { [Header("Setting")] [SerializeField] private Prefab DefaultPlayer; - private IGameManager[] Managers; private GameObject PlayerObject; @@ -104,23 +103,7 @@ private void Awake() } // Get All Managers - List CashManagers = new List(10); - foreach (var manager in GetComponents()) - { - if (!CashManagers.Contains(manager)) - { - manager.InitiateManager(false); - CashManagers.Add(manager); - } - else - { - Debug.LogError($"You should not use a manager {manager} twice"); - throw new System.NotImplementedException(); - } - - } - Managers = new IGameManager[CashManagers.Count]; - Managers = CashManagers.ToArray(); + CollectManagers(new GameObject[1] { gameObject }); // Find Player or Create newone var scneplayer = GetPlayerInScene(); @@ -182,38 +165,6 @@ private void OnDestroy() } - /// - /// Returns a manager instance of the requested type if one exists on this world. - /// - /// The manager type to search for. - /// The manager instance cast to , or null if not found. - public T FindManager() where T : class - { - foreach (var manager in Managers) - { - if (manager.Component is T Result) - { - return Result; - } - } - return null; - } - /// - /// Returns a manager whose associated GameObject has the specified name. - /// - /// The name of the manager's GameObject to find. - /// The matching , or null if none match. - public IGameManager FindManager(string ObjectName) - { - foreach (var manger in Managers) - { - if (manger.Component.gameObject.name == ObjectName) - { - return manger; - } - } - return null; - } /// /// Returns the primary player for this world. From dae7fe4974856e8430253167922cb0d0c7347dc2 Mon Sep 17 00:00:00 2001 From: Alijimpa Date: Thu, 30 Apr 2026 16:07:57 +0330 Subject: [PATCH 174/204] Fix all IGameManager Method with New Version --- .../ScriptTemplates/Core/ManagerTemplate.txt | 12 ++---------- .../Pattern/AudioManagerTemplate.txt | 5 ----- .../Pattern/CompositManagerTemplate.txt | 4 ++-- .../Pattern/GizmoManagerTemplate.txt | 4 ---- .../Pattern/MixerManagerTemplate.txt | 6 +----- .../Pattern/TickManagerTemplate.txt | 6 +----- .../Pattern/UIManagerTemplate.txt | 6 +----- Runtime/Pattern/Managers/AudioManager.cs | 6 +++--- Runtime/Pattern/Managers/CompositManager.cs | 4 ++-- Runtime/Pattern/Managers/DeveloperManager.cs | 3 +-- Runtime/Pattern/Managers/EnumeratorManager.cs | 6 +++--- Runtime/Pattern/Managers/HapticManager.cs | 8 ++------ Runtime/Pattern/Managers/LogManager.cs | 4 ++-- Runtime/Pattern/Managers/MixerManager.cs | 6 +----- Runtime/Pattern/Managers/SaveManager.cs | 5 +---- Runtime/Pattern/Managers/TaskManager.cs | 6 +++--- Runtime/Pattern/Managers/UIManager.cs | 16 ++++++++++------ Runtime/ReadySet/Managers/ActionManager.cs | 2 +- Runtime/ReadySet/Managers/CoroutineManager.cs | 2 +- Runtime/ReadySet/Managers/DevManager.cs | 5 +---- Runtime/ReadySet/Managers/HUDManager.cs | 2 +- Runtime/ReadySet/Managers/MotionManager.cs | 2 +- Runtime/ReadySet/Managers/MusicManager.cs | 4 ++-- Runtime/ReadySet/Managers/ScreenManager.cs | 2 +- Runtime/ReadySet/Managers/SoundManager.cs | 5 ----- 25 files changed, 43 insertions(+), 88 deletions(-) diff --git a/Reservoir/ScriptTemplates/Core/ManagerTemplate.txt b/Reservoir/ScriptTemplates/Core/ManagerTemplate.txt index 66099c1..83cef78 100644 --- a/Reservoir/ScriptTemplates/Core/ManagerTemplate.txt +++ b/Reservoir/ScriptTemplates/Core/ManagerTemplate.txt @@ -3,21 +3,13 @@ using RealMethod; public class #SCRIPTNAME# : MonoBehaviour, IGameManager { - - - - // Implement IGameManage Interface MonoBehaviour IGameManager.GetManagerClass() => this; - void IGameManager.InitiateManager(bool AlwaysLoaded) + void IGameManager.InitiateManager(Scope owner) { // Called Just Once Befor any Awake called // Called when World or Game initializing - // AlwaysLoaded means your manager initialize in GameScope(always valid) or World Scope(destroy after change World) - } - void IGameManager.ResolveService(Service service, bool active) - { - // Called When any Service Created or Deleted in Game + // Owner means your manager initialize in GameScope(always valid) or World Scope(destroy after change World) } } diff --git a/Reservoir/ScriptTemplates/Pattern/AudioManagerTemplate.txt b/Reservoir/ScriptTemplates/Pattern/AudioManagerTemplate.txt index b6cc999..b3e80db 100644 --- a/Reservoir/ScriptTemplates/Pattern/AudioManagerTemplate.txt +++ b/Reservoir/ScriptTemplates/Pattern/AudioManagerTemplate.txt @@ -2,9 +2,4 @@ using RealMethod; public class #SCRIPTNAME# : AudioManager { - // AudioManager Methods - protected override void ResolveService(Service service, bool active) - { - base.ResolveService(service, active); - } } diff --git a/Reservoir/ScriptTemplates/Pattern/CompositManagerTemplate.txt b/Reservoir/ScriptTemplates/Pattern/CompositManagerTemplate.txt index 79fcf3d..3d54e3b 100644 --- a/Reservoir/ScriptTemplates/Pattern/CompositManagerTemplate.txt +++ b/Reservoir/ScriptTemplates/Pattern/CompositManagerTemplate.txt @@ -7,9 +7,9 @@ public class #SCRIPTNAME# : CompositManager private Map Clips = new Map(); // IGameManager Interface - protected override void InitiateManager(bool AlwaysLoaded) + protected override void InitiateManager(Scope owner) { - base.InitiateManager(AlwaysLoaded); + base.InitiateManager(owner); foreach (var clip in Clips) { CreateLayer(clip.Key, clip.Value); diff --git a/Reservoir/ScriptTemplates/Pattern/GizmoManagerTemplate.txt b/Reservoir/ScriptTemplates/Pattern/GizmoManagerTemplate.txt index 6bcd48b..4653ff1 100644 --- a/Reservoir/ScriptTemplates/Pattern/GizmoManagerTemplate.txt +++ b/Reservoir/ScriptTemplates/Pattern/GizmoManagerTemplate.txt @@ -7,9 +7,5 @@ public class #SCRIPTNAME# : GizmoManager { throw new System.NotImplementedException(); } - protected override void ResolveService(Service service, bool active) - { - throw new System.NotImplementedException(); - } } diff --git a/Reservoir/ScriptTemplates/Pattern/MixerManagerTemplate.txt b/Reservoir/ScriptTemplates/Pattern/MixerManagerTemplate.txt index 0d2d04b..b044190 100644 --- a/Reservoir/ScriptTemplates/Pattern/MixerManagerTemplate.txt +++ b/Reservoir/ScriptTemplates/Pattern/MixerManagerTemplate.txt @@ -4,11 +4,7 @@ public class #SCRIPTNAME# : MixerManager { // Implement IGameManage Methods - protected override void InitiateManager(bool AlwaysLoaded) - { - throw new System.NotImplementedException(); - } - protected override void ResolveService(Service service, bool active) + protected override void InitiateManager(Scope owner) { throw new System.NotImplementedException(); } diff --git a/Reservoir/ScriptTemplates/Pattern/TickManagerTemplate.txt b/Reservoir/ScriptTemplates/Pattern/TickManagerTemplate.txt index 1a7ab79..72e4e8a 100644 --- a/Reservoir/ScriptTemplates/Pattern/TickManagerTemplate.txt +++ b/Reservoir/ScriptTemplates/Pattern/TickManagerTemplate.txt @@ -4,13 +4,9 @@ public class #SCRIPTNAME# : TickManager { // TickManager Methods - protected override void InitiateManager(bool alwaysLoaded) + protected override void InitiateManager(Scope owner) { - } - protected override void ResolveService(Service service, bool active) - { - } protected override bool CheckUnit(T unit) { diff --git a/Reservoir/ScriptTemplates/Pattern/UIManagerTemplate.txt b/Reservoir/ScriptTemplates/Pattern/UIManagerTemplate.txt index e3274d3..33137c4 100644 --- a/Reservoir/ScriptTemplates/Pattern/UIManagerTemplate.txt +++ b/Reservoir/ScriptTemplates/Pattern/UIManagerTemplate.txt @@ -4,13 +4,9 @@ public class #SCRIPTNAME# : UIManager { // UIManager Methods - protected override void InitiateManager(bool alwaysLoaded) + protected override void InitiateManager(Scope owner) { } - protected override void ResolveService(Service service, bool active) - { - - } } diff --git a/Runtime/Pattern/Managers/AudioManager.cs b/Runtime/Pattern/Managers/AudioManager.cs index 7d71ad4..2191dc8 100644 --- a/Runtime/Pattern/Managers/AudioManager.cs +++ b/Runtime/Pattern/Managers/AudioManager.cs @@ -16,11 +16,11 @@ public abstract class AudioManager : MixerManager public ObjectPool soundPool; // Manager - public override void InitiateManager(bool AlwaysLoaded) + public override void InitiateManager(Scope owner) { - base.InitiateManager(AlwaysLoaded); + base.InitiateManager(owner); - if (AlwaysLoaded) + if (owner.IsGameScope()) { Debug.LogError("You can't use AudioManager in [Game] Scope"); return; diff --git a/Runtime/Pattern/Managers/CompositManager.cs b/Runtime/Pattern/Managers/CompositManager.cs index 690b4b9..1a632c4 100644 --- a/Runtime/Pattern/Managers/CompositManager.cs +++ b/Runtime/Pattern/Managers/CompositManager.cs @@ -40,9 +40,9 @@ public void Pitch(float alpha, float minPitch = -3f, float maxPitch = 3f) public int LayerCount => Layers.Count; // Override Methods - public override void InitiateManager(bool AlwaysLoaded) + public override void InitiateManager(Scope owner) { - base.InitiateManager(AlwaysLoaded); + base.InitiateManager(owner); foreach (Transform item in header) { diff --git a/Runtime/Pattern/Managers/DeveloperManager.cs b/Runtime/Pattern/Managers/DeveloperManager.cs index 7f11822..58a0dc7 100644 --- a/Runtime/Pattern/Managers/DeveloperManager.cs +++ b/Runtime/Pattern/Managers/DeveloperManager.cs @@ -240,8 +240,7 @@ private void OnUITrigger(InputAction.CallbackContext context) TriggerVisiblity(); } #endif - public abstract void InitiateManager(bool alwaysLoaded); - public abstract void ResolveService(Service service, bool active); + public abstract void InitiateManager(Scope owner); } diff --git a/Runtime/Pattern/Managers/EnumeratorManager.cs b/Runtime/Pattern/Managers/EnumeratorManager.cs index 716812e..67f87f3 100644 --- a/Runtime/Pattern/Managers/EnumeratorManager.cs +++ b/Runtime/Pattern/Managers/EnumeratorManager.cs @@ -66,9 +66,9 @@ public MonoBehaviour GetManagerClass() { return this; } - void IGameManager.InitiateManager(bool AlwaysLoaded) + void IGameManager.InitiateManager(Scope owner) { - InitiateManager(AlwaysLoaded); + InitiateManager(owner); } @@ -103,7 +103,7 @@ public void Stop(Coroutine coroutine) // Abstract Methods - protected abstract void InitiateManager(bool alwaysLoaded); + protected abstract void InitiateManager(Scope owner); } diff --git a/Runtime/Pattern/Managers/HapticManager.cs b/Runtime/Pattern/Managers/HapticManager.cs index d7112e0..26678b4 100644 --- a/Runtime/Pattern/Managers/HapticManager.cs +++ b/Runtime/Pattern/Managers/HapticManager.cs @@ -65,9 +65,9 @@ public MonoBehaviour GetManagerClass() { return this; } - public void InitiateManager(bool AlwaysLoaded) + public void InitiateManager(Scope owner) { - if (!AlwaysLoaded) + if (owner.IsWorldScope()) { Debug.LogWarning("HapticManager Should initiate in Game Scope"); return; @@ -81,10 +81,6 @@ public void InitiateManager(bool AlwaysLoaded) } } } - public void ResolveService(Service service, bool active) - { - } - // Public Methods public IHapticProvider Produce(HapticConfig config) diff --git a/Runtime/Pattern/Managers/LogManager.cs b/Runtime/Pattern/Managers/LogManager.cs index 296571e..538453a 100644 --- a/Runtime/Pattern/Managers/LogManager.cs +++ b/Runtime/Pattern/Managers/LogManager.cs @@ -4,9 +4,9 @@ namespace RealMethod { public class LogManager : MonoBehaviour, IGameManager { - void IGameManager.InitiateManager(bool AlwaysLoaded) + void IGameManager.InitiateManager(Scope owner) { - if (!AlwaysLoaded) + if (owner.IsWorldScope()) { Debug.LogError("LogManager should be Initiate in GameScope."); Destroy(this); diff --git a/Runtime/Pattern/Managers/MixerManager.cs b/Runtime/Pattern/Managers/MixerManager.cs index de7c3a2..3e3ba13 100644 --- a/Runtime/Pattern/Managers/MixerManager.cs +++ b/Runtime/Pattern/Managers/MixerManager.cs @@ -17,11 +17,7 @@ public abstract class MixerManager : MonoBehaviour, IGameManager // IGameManager Interface Implementation - public virtual void InitiateManager(bool AlwaysLoaded) - { - - } - public virtual void ResolveService(Service service, bool active) + public virtual void InitiateManager(Scope owner) { } diff --git a/Runtime/Pattern/Managers/SaveManager.cs b/Runtime/Pattern/Managers/SaveManager.cs index 5579e0e..a9c0392 100644 --- a/Runtime/Pattern/Managers/SaveManager.cs +++ b/Runtime/Pattern/Managers/SaveManager.cs @@ -67,7 +67,7 @@ public abstract class SaveManager : MonoBehaviour, IGameManager, ISaveSystem // Implement IGameManager Interface - public virtual void InitiateManager(bool AlwaysLoaded) + public virtual void InitiateManager(Scope owner) { if (Mode != SaveFileStructure.MultiFile) { @@ -86,9 +86,6 @@ public virtual void InitiateManager(bool AlwaysLoaded) } } } - public virtual void ResolveService(Service service, bool active) - { - } // Implement ISaveSystem Interface diff --git a/Runtime/Pattern/Managers/TaskManager.cs b/Runtime/Pattern/Managers/TaskManager.cs index fd45f05..e5df656 100644 --- a/Runtime/Pattern/Managers/TaskManager.cs +++ b/Runtime/Pattern/Managers/TaskManager.cs @@ -16,13 +16,13 @@ public abstract class TaskManager : MonoBehaviour, IGameManager public int Count => Tasks != null ? Tasks.Count : 0; // Implement IGameManager Interface - void IGameManager.InitiateManager(bool AlwaysLoaded) + void IGameManager.InitiateManager(Scope owner) { - InitiateManager(AlwaysLoaded); + InitiateManager(owner); } // Abstract Methods - protected abstract void InitiateManager(bool alwaysLoaded); + protected abstract void InitiateManager(Scope owner); } public abstract class TaskManager : TaskManager where J : IHandle { diff --git a/Runtime/Pattern/Managers/UIManager.cs b/Runtime/Pattern/Managers/UIManager.cs index 98e2510..30ec57e 100644 --- a/Runtime/Pattern/Managers/UIManager.cs +++ b/Runtime/Pattern/Managers/UIManager.cs @@ -35,7 +35,7 @@ public enum UIMethod // Implement IGameManager Interface - void IGameManager.InitiateManager(bool alwaysLoaded) + void IGameManager.InitiateManager(Scope owner) { if (header == null) { @@ -69,7 +69,7 @@ void IGameManager.InitiateManager(bool alwaysLoaded) } } - InitiateManager(alwaysLoaded); + InitiateManager(owner); } @@ -77,8 +77,12 @@ void IGameManager.InitiateManager(bool alwaysLoaded) #if UNITY_EDITOR private void OnValidate() { - if (gameObject.layer != 5) - gameObject.layer = 5; + if (header != null) + { + if (header.gameObject.layer != 5) + header.gameObject.layer = 5; + } + } #endif @@ -542,7 +546,7 @@ public T FindClassInLayers() where T : class } // Abstract Methods - protected abstract void InitiateManager(bool alwaysLoaded); + protected abstract void InitiateManager(Scope owner); //Enumerators private IEnumerator FadeIn(CanvasGroup canvas, float fadeDuration) @@ -611,5 +615,5 @@ private IEnumerator FadeOut(CanvasGroup canvas, float fadeDuration, System.Actio } - + } diff --git a/Runtime/ReadySet/Managers/ActionManager.cs b/Runtime/ReadySet/Managers/ActionManager.cs index 8b10599..94c0bf3 100644 --- a/Runtime/ReadySet/Managers/ActionManager.cs +++ b/Runtime/ReadySet/Managers/ActionManager.cs @@ -27,7 +27,7 @@ public sealed class ActionManager : TaskManager private SoftType[] DefaultActions; // TaskMaanger Methods - protected override void InitiateManager(bool alwaysLoaded) + protected override void InitiateManager(Scope owner) { if (DefaultActions != null) { diff --git a/Runtime/ReadySet/Managers/CoroutineManager.cs b/Runtime/ReadySet/Managers/CoroutineManager.cs index 16b7c77..29a9efb 100644 --- a/Runtime/ReadySet/Managers/CoroutineManager.cs +++ b/Runtime/ReadySet/Managers/CoroutineManager.cs @@ -6,7 +6,7 @@ namespace RealMethod public class CoroutineManager : EnumeratorManager { // EnumeratorManager Methods - protected override void InitiateManager(bool alwaysLoaded) + protected override void InitiateManager(Scope owner) { } diff --git a/Runtime/ReadySet/Managers/DevManager.cs b/Runtime/ReadySet/Managers/DevManager.cs index 514ff96..6b64a33 100644 --- a/Runtime/ReadySet/Managers/DevManager.cs +++ b/Runtime/ReadySet/Managers/DevManager.cs @@ -8,10 +8,7 @@ namespace RealMethod public class DevManager : DeveloperManager { // DeveloperManager Methods - public override void InitiateManager(bool alwaysLoaded) - { - } - public override void ResolveService(Service service, bool active) + public override void InitiateManager(Scope owner) { } } diff --git a/Runtime/ReadySet/Managers/HUDManager.cs b/Runtime/ReadySet/Managers/HUDManager.cs index a2a00d3..fd74d8d 100644 --- a/Runtime/ReadySet/Managers/HUDManager.cs +++ b/Runtime/ReadySet/Managers/HUDManager.cs @@ -7,7 +7,7 @@ public sealed class HUDManager : UIManager { // UIManager Methods - protected override void InitiateManager(bool alwaysLoaded) + protected override void InitiateManager(Scope owner) { } diff --git a/Runtime/ReadySet/Managers/MotionManager.cs b/Runtime/ReadySet/Managers/MotionManager.cs index 1e83ba3..da89f9a 100644 --- a/Runtime/ReadySet/Managers/MotionManager.cs +++ b/Runtime/ReadySet/Managers/MotionManager.cs @@ -224,7 +224,7 @@ public sealed class MotionManager : TaskManager // TickManager Methods - protected override void InitiateManager(bool alwaysLoaded) + protected override void InitiateManager(Scope owner) { if (DefaultMotions != null) { diff --git a/Runtime/ReadySet/Managers/MusicManager.cs b/Runtime/ReadySet/Managers/MusicManager.cs index 43dc7e5..d7a7129 100644 --- a/Runtime/ReadySet/Managers/MusicManager.cs +++ b/Runtime/ReadySet/Managers/MusicManager.cs @@ -10,9 +10,9 @@ public sealed class MusicManager : CompositManager private Map Clips = new Map(); // GameManager - public override void InitiateManager(bool AlwaysLoaded) + public override void InitiateManager(Scope owner) { - base.InitiateManager(AlwaysLoaded); + base.InitiateManager(owner); foreach (var clip in Clips) { CreateLayer(clip.Key, clip.Value); diff --git a/Runtime/ReadySet/Managers/ScreenManager.cs b/Runtime/ReadySet/Managers/ScreenManager.cs index 160ffba..f14a668 100644 --- a/Runtime/ReadySet/Managers/ScreenManager.cs +++ b/Runtime/ReadySet/Managers/ScreenManager.cs @@ -21,7 +21,7 @@ public sealed class ScreenManager : UIManager public IInformer Informer { get; private set; } // UIManager Methods - protected override void InitiateManager(bool alwaysLoaded) + protected override void InitiateManager(Scope owner) { Game.OnSceneLoading += (value) => OnLoadScne?.Invoke(value); Game.OnSceneLoadingProcess += (value) => OnLoading?.Invoke(value); diff --git a/Runtime/ReadySet/Managers/SoundManager.cs b/Runtime/ReadySet/Managers/SoundManager.cs index ab3c94e..7e009c6 100644 --- a/Runtime/ReadySet/Managers/SoundManager.cs +++ b/Runtime/ReadySet/Managers/SoundManager.cs @@ -5,10 +5,5 @@ namespace RealMethod [AddComponentMenu("RealMethod/Manager/SoundManager")] public sealed class SoundManager : AudioManager { - // AudioManager Methods - public override void ResolveService(Service service, bool active) - { - base.ResolveService(service, active); - } } } \ No newline at end of file From 31c91d321539f4bd64e5bc53e06274b637988972 Mon Sep 17 00:00:00 2001 From: Alijimpa Date: Thu, 30 Apr 2026 16:08:11 +0330 Subject: [PATCH 175/204] Fix These with new IGameManager --- Tests/FileManager.cs | 6 +----- Tests/General/AIManager.cs | 8 ++------ Tests/General/EnvironmentManager.cs | 7 +------ Tests/General/LevelManager.cs | 7 +------ Tests/General/MissionManager.cs | 5 +---- Tests/General/SpawnManager.cs | 13 ++----------- Tests/General/TutorialManager.cs | 6 +----- 7 files changed, 9 insertions(+), 43 deletions(-) diff --git a/Tests/FileManager.cs b/Tests/FileManager.cs index 3b22d88..284aa23 100644 --- a/Tests/FileManager.cs +++ b/Tests/FileManager.cs @@ -24,11 +24,7 @@ public FileData(object Instance, BindingFlags flags) public event System.Action OnFileRemoved; // Implement IGameManager Interface - public virtual void InitiateManager(bool AlwaysLoaded) - { - - } - public virtual void ResolveService(Service service, bool active) + public virtual void InitiateManager(Scope owner) { } diff --git a/Tests/General/AIManager.cs b/Tests/General/AIManager.cs index fa577c7..075c948 100644 --- a/Tests/General/AIManager.cs +++ b/Tests/General/AIManager.cs @@ -45,9 +45,9 @@ public MonoBehaviour GetManagerClass() { return this; } - public void InitiateManager(bool AlwaysLoaded) + public void InitiateManager(Scope owner) { - if (AlwaysLoaded) return; + if (owner.IsGameScope()) return; // MyWorld = GetComponent(); // if (MyWorld == null) Debug.LogError("AIDirector Couldn't Find World."); @@ -56,10 +56,6 @@ public void InitiateManager(bool AlwaysLoaded) // MyWorld.OnGameBegin += OnGameStarted; } - public void ResolveService(Service service, bool active) - { - throw new System.NotImplementedException(); - } // #endregion diff --git a/Tests/General/EnvironmentManager.cs b/Tests/General/EnvironmentManager.cs index 5e21f4c..1980810 100644 --- a/Tests/General/EnvironmentManager.cs +++ b/Tests/General/EnvironmentManager.cs @@ -33,16 +33,11 @@ public MonoBehaviour GetManagerClass() } // Initializes the manager and subscribes to the difficulty change event - public void InitiateManager(bool AlwaysLoaded) + public void InitiateManager(Scope owner) { //CCGame.CastWorld().OndifficultyChange += OnPlayerLevelChanged; } - // Placeholder for initiating services, currently does nothing - public void ResolveService(Service service, bool active) - { - } - #endregion // Event handler for player level change diff --git a/Tests/General/LevelManager.cs b/Tests/General/LevelManager.cs index be47b59..95ecbfe 100644 --- a/Tests/General/LevelManager.cs +++ b/Tests/General/LevelManager.cs @@ -34,7 +34,7 @@ public MonoBehaviour GetManagerClass() { return this; } - public void InitiateManager(bool AlwaysLoaded) + public void InitiateManager(Scope owner) { // if (!LG) // { @@ -53,11 +53,6 @@ public void InitiateManager(bool AlwaysLoaded) StartCoroutine(OnPlayerLocationChange()); } - public void ResolveService(Service service, bool active) - { - throw new System.NotImplementedException(); - } - private void OnEnable() { diff --git a/Tests/General/MissionManager.cs b/Tests/General/MissionManager.cs index 0b1912d..873a7a3 100644 --- a/Tests/General/MissionManager.cs +++ b/Tests/General/MissionManager.cs @@ -45,7 +45,7 @@ public MonoBehaviour GetManagerClass() { return this; } - public void InitiateManager(bool AlwaysLoaded) + public void InitiateManager(Scope owner) { //MyWorld = Game.CastWorld(); //GameObject PlayerObject = MyWorld.GetPlayerObject(); @@ -62,9 +62,6 @@ public void InitiateManager(bool AlwaysLoaded) //if (GameData.GetMissionsLength() == MissionID) //NextLevel.gameObject.SetActive(false); } - public void ResolveService(Service service, bool active) - { - } diff --git a/Tests/General/SpawnManager.cs b/Tests/General/SpawnManager.cs index 4da961b..2154a23 100644 --- a/Tests/General/SpawnManager.cs +++ b/Tests/General/SpawnManager.cs @@ -46,20 +46,11 @@ public void StopManager() throw new System.NotImplementedException(); } - public MonoBehaviour GetManagerClass() - { - return this; - } - public void InitiateManager(bool AlwaysLoaded) - { - throw new System.NotImplementedException(); - } - public void ResolveService(Service service, bool active) + + public void InitiateManager(Scope owner) { throw new System.NotImplementedException(); } - - } } diff --git a/Tests/General/TutorialManager.cs b/Tests/General/TutorialManager.cs index 95b1933..a2ddc18 100644 --- a/Tests/General/TutorialManager.cs +++ b/Tests/General/TutorialManager.cs @@ -51,7 +51,7 @@ public MonoBehaviour GetManagerClass() { return this; } - public void InitiateManager(bool AlwaysLoaded) + public void InitiateManager(Scope owner) { // if (Savefile == null) // { @@ -72,10 +72,6 @@ public void InitiateManager(bool AlwaysLoaded) // Destroy(this); // } } - public void ResolveService(Service service, bool active) - { - } - // Private Methods private void BeginTutorial() From 7df7b93097ef74e0718af2276793594637e54111 Mon Sep 17 00:00:00 2001 From: Alijimpa Date: Thu, 30 Apr 2026 17:11:57 +0330 Subject: [PATCH 176/204] Implement Some Extension Eethod for Chacking Scope --- Runtime/Core/Architecture/Scope.cs | 8 +------- Runtime/Core/Definitions/Method_Extension.cs | 15 +++++++++++++++ Runtime/Core/Definitions/Method_Extension.cs.meta | 2 ++ Runtime/ReadySet/Presets/PoolAsset/AudioPool.cs | 3 +-- Runtime/ReadySet/Services/DespawnService.cs | 10 ++++------ Runtime/ReadySet/Services/SpawanService.cs | 10 ++++------ 6 files changed, 27 insertions(+), 21 deletions(-) create mode 100644 Runtime/Core/Definitions/Method_Extension.cs create mode 100644 Runtime/Core/Definitions/Method_Extension.cs.meta diff --git a/Runtime/Core/Architecture/Scope.cs b/Runtime/Core/Architecture/Scope.cs index 062205f..837132e 100644 --- a/Runtime/Core/Architecture/Scope.cs +++ b/Runtime/Core/Architecture/Scope.cs @@ -10,10 +10,7 @@ public abstract class Scope : MonoBehaviour /// Cached array of managers that were instantiated from configured game prefabs or World gameobject. /// private IGameManager[] Managers = null; - /// - /// Cached array of managers that were instantiated from configured game prefabs or World gameobject. - /// - // public IReadOnlyList manager => Managers; + /// @@ -47,7 +44,6 @@ public bool TryFindManager(out T result) where T : Component, IGameManager } - /// /// Collects all components from the provided GameObjects, /// initializes them, and stores them internally. @@ -101,8 +97,6 @@ protected void CollectManagers(GameObject[] Objects) Managers = managerCache.ToArray(); } - - } diff --git a/Runtime/Core/Definitions/Method_Extension.cs b/Runtime/Core/Definitions/Method_Extension.cs new file mode 100644 index 0000000..04dbb47 --- /dev/null +++ b/Runtime/Core/Definitions/Method_Extension.cs @@ -0,0 +1,15 @@ +namespace RealMethod +{ + public static class Method_Extension + { + public static bool IsGameScope(this Scope target) + { + return target is Game; + } + public static bool IsWorldScope(this Scope target) + { + return target is World; + } + + } +} \ No newline at end of file diff --git a/Runtime/Core/Definitions/Method_Extension.cs.meta b/Runtime/Core/Definitions/Method_Extension.cs.meta new file mode 100644 index 0000000..459f9ae --- /dev/null +++ b/Runtime/Core/Definitions/Method_Extension.cs.meta @@ -0,0 +1,2 @@ +fileFormatVersion: 2 +guid: 43e8dfce657418446b4075c5897ecf40 \ No newline at end of file diff --git a/Runtime/ReadySet/Presets/PoolAsset/AudioPool.cs b/Runtime/ReadySet/Presets/PoolAsset/AudioPool.cs index 8782e88..c78df96 100644 --- a/Runtime/ReadySet/Presets/PoolAsset/AudioPool.cs +++ b/Runtime/ReadySet/Presets/PoolAsset/AudioPool.cs @@ -109,8 +109,7 @@ private AudioClip GetRandomClip() // Base PoolAsset Methods protected override void OnRootInitiate(Transform Root) { - AudioManager audiomanager = Game.World.FindManager(); - if (audiomanager != null) + if (Game.World.TryFindManager(out AudioManager audiomanager)) { Root.SetParent(audiomanager.transform); } diff --git a/Runtime/ReadySet/Services/DespawnService.cs b/Runtime/ReadySet/Services/DespawnService.cs index 166c6e6..5939d1f 100644 --- a/Runtime/ReadySet/Services/DespawnService.cs +++ b/Runtime/ReadySet/Services/DespawnService.cs @@ -45,8 +45,7 @@ private static Despawn Ins { get { - var CacheInstance = Game.GetService(); - if (CacheInstance == null) + if (!Game.TryGetService(out Despawn CacheInstance)) { CacheInstance = new Despawn(); Game.Register(CacheInstance, null); @@ -105,7 +104,7 @@ public void AddManager(IGameManager manager) // Public Functions - private static T GetManager() where T : MonoBehaviour + private static T GetManager() where T : Component, IGameManager { System.Type type = typeof(T); if (Ins.Managers.ContainsKey(type)) @@ -117,10 +116,9 @@ private static T GetManager() where T : MonoBehaviour } else { - var manager = Game.World.FindManager(); - if (manager is IGameManager provider) + if (Game.World.TryFindManager(out T manager)) { - Ins.Managers.Add(type, provider); + Ins.Managers.Add(type, manager); return manager; } } diff --git a/Runtime/ReadySet/Services/SpawanService.cs b/Runtime/ReadySet/Services/SpawanService.cs index 6f200e6..36bca8d 100644 --- a/Runtime/ReadySet/Services/SpawanService.cs +++ b/Runtime/ReadySet/Services/SpawanService.cs @@ -48,8 +48,7 @@ private static Spawn Ins { get { - var CacheInstance = Game.GetService(); - if (CacheInstance == null) + if (!Game.TryGetService(out Spawn CacheInstance)) { CacheInstance = new Spawn(); Game.Register(CacheInstance, null); @@ -106,7 +105,7 @@ public void AddManager(IGameManager manager) } // Private Functions - private static T GetManager() where T : MonoBehaviour + private static T GetManager() where T : Component, IGameManager { System.Type type = typeof(T); if (Ins.Managers.ContainsKey(type)) @@ -118,10 +117,9 @@ private static T GetManager() where T : MonoBehaviour } else { - var manager = Game.World.FindManager(); - if (manager is IGameManager provider) + if (Game.World.TryFindManager(out T manager)) { - Ins.Managers.Add(type, provider); + Ins.Managers.Add(type, manager); return manager; } } From 61d0349c9c375571170d45e02e866b8ffab2db38 Mon Sep 17 00:00:00 2001 From: Alijimpa Date: Sun, 3 May 2026 08:53:22 +0330 Subject: [PATCH 177/204] Implement ServiceLocator & Kernel With Scope Defenation And Implementation for Core --- Runtime/Core/AAA/Kernel.cs | 29 ++++ Runtime/Core/AAA/Kernel.cs.meta | 2 + Runtime/Core/AAA/Scope.cs | 124 +++++++++++++++ Runtime/Core/AAA/Scope.cs.meta | 2 + Runtime/Core/AAA/ServiceLocator.cs | 191 ++++++++++++++++++++++++ Runtime/Core/AAA/ServiceLocator.cs.meta | 2 + 6 files changed, 350 insertions(+) create mode 100644 Runtime/Core/AAA/Kernel.cs create mode 100644 Runtime/Core/AAA/Kernel.cs.meta create mode 100644 Runtime/Core/AAA/Scope.cs create mode 100644 Runtime/Core/AAA/Scope.cs.meta create mode 100644 Runtime/Core/AAA/ServiceLocator.cs create mode 100644 Runtime/Core/AAA/ServiceLocator.cs.meta diff --git a/Runtime/Core/AAA/Kernel.cs b/Runtime/Core/AAA/Kernel.cs new file mode 100644 index 0000000..6934f00 --- /dev/null +++ b/Runtime/Core/AAA/Kernel.cs @@ -0,0 +1,29 @@ +using System; +using UnityEngine; + +namespace RealMethod +{ + /// + /// The foundational runtime core of the RealMethod framework. + /// Provides the minimal infrastructure required for all higher-level systems, + /// including lightweight dependency injection and the base module/manager pipeline. + /// + /// This class does not implement gameplay logic and is not intended to be used + /// directly by typical developers. Instead, it serves as the internal root that + /// powers , Scope, and Scope. + /// + /// Responsibilities: + /// • Acts as the DI root for registering and resolving services. + /// • Provides the shared base for all game modules and managers. + /// • Defines internal lifecycle hooks used by all scopes. + /// + /// Regular users normally interact only with GameScope or WorldScope, + /// while RealKernel remains an internal framework component. + /// + public abstract class Kernel : MonoBehaviour + { + protected static ServiceLocator Services => _serviceLocator.Value; + private static Lazy _serviceLocator = new Lazy(() => new ServiceLocator()); + + } +} \ No newline at end of file diff --git a/Runtime/Core/AAA/Kernel.cs.meta b/Runtime/Core/AAA/Kernel.cs.meta new file mode 100644 index 0000000..8ec1e6f --- /dev/null +++ b/Runtime/Core/AAA/Kernel.cs.meta @@ -0,0 +1,2 @@ +fileFormatVersion: 2 +guid: 91e1d8f8c6d65f74e8cbe55162d21bfc \ No newline at end of file diff --git a/Runtime/Core/AAA/Scope.cs b/Runtime/Core/AAA/Scope.cs new file mode 100644 index 0000000..9b15ac0 --- /dev/null +++ b/Runtime/Core/AAA/Scope.cs @@ -0,0 +1,124 @@ +using UnityEngine; + +namespace RealMethod +{ + /// + /// An abstract base class that extends to provide a structured + /// container for managing game systems and features within a specific context. + /// + /// Scope instances are responsible for collecting, initializing, and providing access + /// to various implementations. + /// It acts as a localized service locator for its immediate context and potentially + /// delegates to parent scopes for unresolved dependencies. + /// + /// This class defines the core manager lifecycle within a given boundary, such as + /// global application lifetime or a scene-specific context. + /// + /// + /// Developers will typically implement or inherit from concrete Scope types like + /// Scope (for global systems) or Scope (for scene-bound systems). + /// + public abstract class Scope : Kernel + { + /// + /// Cached array of managers that were instantiated from configured game prefabs or World gameobject. + /// + //private IGameManager[] Managers = null; + + + /// + /// Attempts to find a manager whose Component matches the specified type . + /// + /// The component type to search for. + /// + /// When this method returns, contains the found component of type if successful; + /// otherwise null. + /// + /// + /// true if a matching manager component was found; otherwise false. + /// + public bool TryFindManager(out T result) where T : Component, IGameManager + { + return Services.TryGet(out result); + // result = null; + + // if (Managers == null) + // { + // Debug.LogError("Managers list is not initialized. Call CollectManagers() before searching."); + // return false; + // } + + // foreach (var manager in Managers) + // { + // if (manager == null) + // { + // Debug.LogError($"A manager reference({typeof(T)}) has been removed or destroyed. Managers should never be null."); + // return false; + // } + // if (manager.Component is T found) + // { + // result = found; + // return true; + // } + // } + // return false; + } + /// + /// Collects all components from the provided GameObjects, + /// initializes them, and stores them internally. + /// + /// This method can only be executed once. If it is called again after managers + /// have already been collected, an error will be logged and the method will exit. + /// + /// Duplicate manager instances are ignored and logged as warnings. + /// + /// + /// Array of GameObjects to search for components. + /// Null objects in the array are skipped. + /// + protected void CollectManagers(GameObject[] Objects) + { + if (Objects == null) + { + Debug.LogError("CollectManagers received a null GameObjects array."); + return; + } + + // if (Managers != null) + // { + // Debug.LogError("CollectManagers was called more than once. This is not allowed."); + // return; + // } + + //HashSet managerCache = new HashSet(); + for (int i = 0; i < Objects.Length; i++) + { + GameObject Obj = Objects[i]; + if (Obj == null) + continue; + + var found = Obj.GetComponents(); + + foreach (var manager in found) + { + Component comp = manager.Component; + Services.Register(comp.GetType(), comp); + manager.InitiateManager(this); + // if (managerCache.Add(manager)) + // { + // } + // else + // { + // Debug.LogWarning($"Duplicate manager detected: {manager.GetType().Name} in {manager.Component.gameObject.name}"); + // continue; + // } + } + } + //Managers = managerCache.ToArray(); + } + + } + + + +} \ No newline at end of file diff --git a/Runtime/Core/AAA/Scope.cs.meta b/Runtime/Core/AAA/Scope.cs.meta new file mode 100644 index 0000000..f8577a3 --- /dev/null +++ b/Runtime/Core/AAA/Scope.cs.meta @@ -0,0 +1,2 @@ +fileFormatVersion: 2 +guid: cdc1d3e86457c474ca9464cbbf61f0f6 \ No newline at end of file diff --git a/Runtime/Core/AAA/ServiceLocator.cs b/Runtime/Core/AAA/ServiceLocator.cs new file mode 100644 index 0000000..2938e3a --- /dev/null +++ b/Runtime/Core/AAA/ServiceLocator.cs @@ -0,0 +1,191 @@ +using System; +using System.Collections.Generic; + +namespace RealMethod +{ + + /// + /// Global service locator with automatic garbage collection safety. + /// Stores services by interface type using WeakReferences. + /// Thread‑safe for Register / Get / Remove operations. + /// + public class ServiceLocator + { + private readonly Dictionary> _services = new(); + private readonly object _lock = new(); + + /// + /// Register a service instance under its concrete or interface type T. + /// T must implement IService so we know this is a service. + /// Stored internally as WeakReference<object>. + /// + public void Register(T service, bool overwrite = false) + where T : class + { + Register(typeof(T), service, overwrite); + } + + /// + /// Register a service instance under its concrete or interface type T. + /// T must implement IService so we know this is a service. + /// Stored internally as WeakReference<object>. + /// + public void Register(Type type, object service, bool overwrite = false) + { + if (type == null) + throw new ArgumentNullException(nameof(type)); + + if (service == null) + throw new ArgumentNullException(nameof(service)); + + if (!type.IsAssignableFrom(service.GetType())) + throw new ArgumentException($"{service.GetType().Name} is not assignable to {type.Name}"); + + lock (_lock) + { + if (_services.TryGetValue(type, out var weak)) + { + if (!weak.TryGetTarget(out _)) + { + _services[type] = new WeakReference(service); + return; + } + + if (overwrite) + { + _services[type] = new WeakReference(service); + return; + } + + throw new InvalidOperationException( + $"Service of type {type.Name} is already registered and still alive."); + } + + _services[type] = new WeakReference(service); + } + } + + /// + /// Register only if no live instance is currently registered for T. + /// + public void RegisterIfAbsent(T service) + where T : class + { + if (service == null) + throw new ArgumentNullException(nameof(service)); + + var type = typeof(T); + + lock (_lock) + { + if (!_services.TryGetValue(type, out var weak) || + !weak.TryGetTarget(out _)) + { + _services[type] = new WeakReference(service); + } + } + } + + /// + /// Get the registered instance for type T. + /// Returns null if not found or GC-collected. + /// You can call this as Get<PlayerObject>(). + /// + public T Get() where T : class + { + var type = typeof(T); + + lock (_lock) + { + if (_services.TryGetValue(type, out var weak)) + { + if (weak.TryGetTarget(out var obj) && obj != null) + { + return obj as T; + } + + // Weak reference dead → remove entry + _services.Remove(type); + } + return null; + } + } + + /// + /// Try to get the registered instance for type T. + /// + public bool TryGet(out T result) where T : class + { + var type = typeof(T); + + lock (_lock) + { + if (_services.TryGetValue(type, out var weak)) + { + if (weak.TryGetTarget(out var obj) && obj != null) + { + result = obj as T; + return result != null; + } + + // Weak reference dead → remove entry + _services.Remove(type); + } + } + + result = null; + return false; + } + + /// + /// Check whether a live instance exists for type T. + /// + public bool Exists() where T : class + { + var type = typeof(T); + + lock (_lock) + { + return _services.TryGetValue(type, out var weak) && + weak.TryGetTarget(out _); + } + } + + /// + /// Manually unregisters (removes) a service type. + /// + public void Unregister() where T : class + { + var type = typeof(T); + lock (_lock) + { + _services.Remove(type); + } + } + /// + /// Removes the service associated with type + /// from the Service Locator. + /// + /// + /// If no service of this type is registered, the method does nothing. + /// Use this when services are registered using generic calls such as + /// Register<T>(instance). + /// + public void Unregister(Type type) + { + if (_services.ContainsKey(type)) + _services.Remove(type); + } + + /// + /// Force-clears all services from the locator. + /// + public void ClearAll() + { + lock (_lock) + { + _services.Clear(); + } + } + } +} diff --git a/Runtime/Core/AAA/ServiceLocator.cs.meta b/Runtime/Core/AAA/ServiceLocator.cs.meta new file mode 100644 index 0000000..d11f4d4 --- /dev/null +++ b/Runtime/Core/AAA/ServiceLocator.cs.meta @@ -0,0 +1,2 @@ +fileFormatVersion: 2 +guid: c7f15b6d00f6b51469e7e8eb40786050 \ No newline at end of file From 85c796365499da589b137ede9c947ed89f9f5f2f Mon Sep 17 00:00:00 2001 From: Alijimpa Date: Sun, 3 May 2026 08:53:55 +0330 Subject: [PATCH 178/204] Move all DefaultCoreClass to Core Folder for fix Dependency Missing --- Runtime/Core/DefaultClass/DefaultGameBridge.cs | 11 +++++++++++ Runtime/Core/DefaultClass/DefaultGameBridge.cs.meta | 2 ++ .../DefaultClass}/DefaultGameConfig.cs | 2 +- Runtime/Core/DefaultClass/DefaultGameConfig.cs.meta | 2 ++ .../Essentials => Core/DefaultClass}/DefaultWorld.cs | 0 Runtime/Core/DefaultClass/DefaultWorld.cs.meta | 2 ++ .../DefaultClass/DefultGame.cs} | 3 +-- Runtime/Core/DefaultClass/DefultGame.cs.meta | 2 ++ Runtime/ReadySet/Essentials/DefaultGame.cs.meta | 2 -- Runtime/ReadySet/Essentials/DefaultGameBridge.cs | 6 ------ Runtime/ReadySet/Essentials/DefaultGameBridge.cs.meta | 2 -- Runtime/ReadySet/Essentials/DefaultGameConfig.cs.meta | 2 -- Runtime/ReadySet/Essentials/DefaultWorld.cs.meta | 11 ----------- 13 files changed, 21 insertions(+), 26 deletions(-) create mode 100644 Runtime/Core/DefaultClass/DefaultGameBridge.cs create mode 100644 Runtime/Core/DefaultClass/DefaultGameBridge.cs.meta rename Runtime/{ReadySet/Essentials => Core/DefaultClass}/DefaultGameConfig.cs (99%) create mode 100644 Runtime/Core/DefaultClass/DefaultGameConfig.cs.meta rename Runtime/{ReadySet/Essentials => Core/DefaultClass}/DefaultWorld.cs (100%) create mode 100644 Runtime/Core/DefaultClass/DefaultWorld.cs.meta rename Runtime/{ReadySet/Essentials/DefaultGame.cs => Core/DefaultClass/DefultGame.cs} (99%) create mode 100644 Runtime/Core/DefaultClass/DefultGame.cs.meta delete mode 100644 Runtime/ReadySet/Essentials/DefaultGame.cs.meta delete mode 100644 Runtime/ReadySet/Essentials/DefaultGameBridge.cs delete mode 100644 Runtime/ReadySet/Essentials/DefaultGameBridge.cs.meta delete mode 100644 Runtime/ReadySet/Essentials/DefaultGameConfig.cs.meta delete mode 100644 Runtime/ReadySet/Essentials/DefaultWorld.cs.meta diff --git a/Runtime/Core/DefaultClass/DefaultGameBridge.cs b/Runtime/Core/DefaultClass/DefaultGameBridge.cs new file mode 100644 index 0000000..a0a636e --- /dev/null +++ b/Runtime/Core/DefaultClass/DefaultGameBridge.cs @@ -0,0 +1,11 @@ +using System; + +namespace RealMethod +{ + public sealed class DefaultGameBridge : GameBridge + { + public DefaultGameBridge(Action method) : base(method) + { + } + } +} \ No newline at end of file diff --git a/Runtime/Core/DefaultClass/DefaultGameBridge.cs.meta b/Runtime/Core/DefaultClass/DefaultGameBridge.cs.meta new file mode 100644 index 0000000..a694d81 --- /dev/null +++ b/Runtime/Core/DefaultClass/DefaultGameBridge.cs.meta @@ -0,0 +1,2 @@ +fileFormatVersion: 2 +guid: 0b901207892a9954dab8c1d7f64585d2 \ No newline at end of file diff --git a/Runtime/ReadySet/Essentials/DefaultGameConfig.cs b/Runtime/Core/DefaultClass/DefaultGameConfig.cs similarity index 99% rename from Runtime/ReadySet/Essentials/DefaultGameConfig.cs rename to Runtime/Core/DefaultClass/DefaultGameConfig.cs index b7b867d..eb351ed 100644 --- a/Runtime/ReadySet/Essentials/DefaultGameConfig.cs +++ b/Runtime/Core/DefaultClass/DefaultGameConfig.cs @@ -15,4 +15,4 @@ private void OnEnable() Debug.Log("DefaultConfig Loaded"); } } -} +} \ No newline at end of file diff --git a/Runtime/Core/DefaultClass/DefaultGameConfig.cs.meta b/Runtime/Core/DefaultClass/DefaultGameConfig.cs.meta new file mode 100644 index 0000000..ea55e35 --- /dev/null +++ b/Runtime/Core/DefaultClass/DefaultGameConfig.cs.meta @@ -0,0 +1,2 @@ +fileFormatVersion: 2 +guid: a4cc479376d66c44f948e7d169085cb0 \ No newline at end of file diff --git a/Runtime/ReadySet/Essentials/DefaultWorld.cs b/Runtime/Core/DefaultClass/DefaultWorld.cs similarity index 100% rename from Runtime/ReadySet/Essentials/DefaultWorld.cs rename to Runtime/Core/DefaultClass/DefaultWorld.cs diff --git a/Runtime/Core/DefaultClass/DefaultWorld.cs.meta b/Runtime/Core/DefaultClass/DefaultWorld.cs.meta new file mode 100644 index 0000000..dfc3ba5 --- /dev/null +++ b/Runtime/Core/DefaultClass/DefaultWorld.cs.meta @@ -0,0 +1,2 @@ +fileFormatVersion: 2 +guid: 943a52a6287851443a5d5533c5f32179 \ No newline at end of file diff --git a/Runtime/ReadySet/Essentials/DefaultGame.cs b/Runtime/Core/DefaultClass/DefultGame.cs similarity index 99% rename from Runtime/ReadySet/Essentials/DefaultGame.cs rename to Runtime/Core/DefaultClass/DefultGame.cs index 56603ef..6788589 100644 --- a/Runtime/ReadySet/Essentials/DefaultGame.cs +++ b/Runtime/Core/DefaultClass/DefultGame.cs @@ -1,4 +1,3 @@ - using UnityEngine; namespace RealMethod @@ -31,4 +30,4 @@ protected override void OnGameClosed() } -} +} \ No newline at end of file diff --git a/Runtime/Core/DefaultClass/DefultGame.cs.meta b/Runtime/Core/DefaultClass/DefultGame.cs.meta new file mode 100644 index 0000000..9a70b43 --- /dev/null +++ b/Runtime/Core/DefaultClass/DefultGame.cs.meta @@ -0,0 +1,2 @@ +fileFormatVersion: 2 +guid: c771ef0ee64623c498c795821ba35b23 \ No newline at end of file diff --git a/Runtime/ReadySet/Essentials/DefaultGame.cs.meta b/Runtime/ReadySet/Essentials/DefaultGame.cs.meta deleted file mode 100644 index 00d5c8d..0000000 --- a/Runtime/ReadySet/Essentials/DefaultGame.cs.meta +++ /dev/null @@ -1,2 +0,0 @@ -fileFormatVersion: 2 -guid: a9b35df15c1e89149aac0cecec223892 \ No newline at end of file diff --git a/Runtime/ReadySet/Essentials/DefaultGameBridge.cs b/Runtime/ReadySet/Essentials/DefaultGameBridge.cs deleted file mode 100644 index 7adc94f..0000000 --- a/Runtime/ReadySet/Essentials/DefaultGameBridge.cs +++ /dev/null @@ -1,6 +0,0 @@ -namespace RealMethod -{ - public sealed class DefaultGameBridge : GameBridge - { - } -} \ No newline at end of file diff --git a/Runtime/ReadySet/Essentials/DefaultGameBridge.cs.meta b/Runtime/ReadySet/Essentials/DefaultGameBridge.cs.meta deleted file mode 100644 index 8e1d1fa..0000000 --- a/Runtime/ReadySet/Essentials/DefaultGameBridge.cs.meta +++ /dev/null @@ -1,2 +0,0 @@ -fileFormatVersion: 2 -guid: 1fb3607f9f50dff45825e72bce5f8c09 \ No newline at end of file diff --git a/Runtime/ReadySet/Essentials/DefaultGameConfig.cs.meta b/Runtime/ReadySet/Essentials/DefaultGameConfig.cs.meta deleted file mode 100644 index a5c7c23..0000000 --- a/Runtime/ReadySet/Essentials/DefaultGameConfig.cs.meta +++ /dev/null @@ -1,2 +0,0 @@ -fileFormatVersion: 2 -guid: 6e2afeeef06adef459b7e9f845f1f27d \ No newline at end of file diff --git a/Runtime/ReadySet/Essentials/DefaultWorld.cs.meta b/Runtime/ReadySet/Essentials/DefaultWorld.cs.meta deleted file mode 100644 index bd198da..0000000 --- a/Runtime/ReadySet/Essentials/DefaultWorld.cs.meta +++ /dev/null @@ -1,11 +0,0 @@ -fileFormatVersion: 2 -guid: 45f6c9bddd831b14093e7ed8e1414a72 -MonoImporter: - externalObjects: {} - serializedVersion: 2 - defaultReferences: [] - executionOrder: -18 - icon: {instanceID: 0} - userData: - assetBundleName: - assetBundleVariant: From 1d93e2494e573b8f28581149e4cba734aea90153 Mon Sep 17 00:00:00 2001 From: Alijimpa Date: Sun, 3 May 2026 23:18:03 +0330 Subject: [PATCH 179/204] Refine all class with New Artutecture --- Runtime/Core/AAA.meta | 8 + Runtime/Core/AAA/Kernel.cs | 10 +- Runtime/Core/AAA/Scope.cs | 48 +--- Runtime/Core/AAA/ServiceLocator.cs | 49 ++-- Runtime/Core/Architecture/Game.cs | 159 ++++------- Runtime/Core/Architecture/GameBridge.cs | 270 +++++++++++------- Runtime/Core/Architecture/GameManager.cs | 16 ++ Runtime/Core/Architecture/Scope.cs | 104 ------- Runtime/Core/Architecture/Scope.cs.meta | 2 - Runtime/Core/Architecture/Service.cs | 86 ++---- Runtime/Core/Architecture/Service.cs.meta | 11 +- Runtime/Core/DefaultClass.meta | 8 + Runtime/Core/DefaultClass/DefultGame.cs | 3 +- Runtime/Core/Definitions/InspectorInfo.cs | 15 + .../Core/Definitions/InspectorInfo.cs.meta | 2 + Runtime/Pattern/Services/InputService.cs | 14 +- Runtime/Pattern/Services/RuleService.cs | 3 +- Runtime/Pattern/Services/StateService.cs | 3 +- Runtime/ReadySet/Services/DebugService.cs | 38 ++- .../{DespawnService.cs => Despawn.cs} | 44 +-- ...DespawnService.cs.meta => Despawn.cs.meta} | 0 Runtime/ReadySet/Services/NetworkService.cs | 8 +- .../Services/{SpawanService.cs => Spawan.cs} | 41 +-- .../{SpawanService.cs.meta => Spawan.cs.meta} | 0 Runtime/ReadySet/Services/TimeService.cs | 14 +- 25 files changed, 423 insertions(+), 533 deletions(-) create mode 100644 Runtime/Core/AAA.meta delete mode 100644 Runtime/Core/Architecture/Scope.cs delete mode 100644 Runtime/Core/Architecture/Scope.cs.meta create mode 100644 Runtime/Core/DefaultClass.meta create mode 100644 Runtime/Core/Definitions/InspectorInfo.cs create mode 100644 Runtime/Core/Definitions/InspectorInfo.cs.meta rename Runtime/ReadySet/Services/{DespawnService.cs => Despawn.cs} (89%) rename Runtime/ReadySet/Services/{DespawnService.cs.meta => Despawn.cs.meta} (100%) rename Runtime/ReadySet/Services/{SpawanService.cs => Spawan.cs} (96%) rename Runtime/ReadySet/Services/{SpawanService.cs.meta => Spawan.cs.meta} (100%) diff --git a/Runtime/Core/AAA.meta b/Runtime/Core/AAA.meta new file mode 100644 index 0000000..0a56ca0 --- /dev/null +++ b/Runtime/Core/AAA.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 1b599ae98725ff84c852b9c8a2b26660 +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Runtime/Core/AAA/Kernel.cs b/Runtime/Core/AAA/Kernel.cs index 6934f00..315c22e 100644 --- a/Runtime/Core/AAA/Kernel.cs +++ b/Runtime/Core/AAA/Kernel.cs @@ -22,8 +22,14 @@ namespace RealMethod /// public abstract class Kernel : MonoBehaviour { - protected static ServiceLocator Services => _serviceLocator.Value; + protected static ServiceLocator Registry => _serviceLocator.Value; private static Lazy _serviceLocator = new Lazy(() => new ServiceLocator()); - + +#if UNITY_EDITOR + public virtual IInspectorInfo[] GetAllInfo() + { + return new IInspectorInfo[1] { Registry }; + } +#endif } } \ No newline at end of file diff --git a/Runtime/Core/AAA/Scope.cs b/Runtime/Core/AAA/Scope.cs index 9b15ac0..eb4775c 100644 --- a/Runtime/Core/AAA/Scope.cs +++ b/Runtime/Core/AAA/Scope.cs @@ -20,12 +20,6 @@ namespace RealMethod /// public abstract class Scope : Kernel { - /// - /// Cached array of managers that were instantiated from configured game prefabs or World gameobject. - /// - //private IGameManager[] Managers = null; - - /// /// Attempts to find a manager whose Component matches the specified type . /// @@ -39,29 +33,7 @@ public abstract class Scope : Kernel /// public bool TryFindManager(out T result) where T : Component, IGameManager { - return Services.TryGet(out result); - // result = null; - - // if (Managers == null) - // { - // Debug.LogError("Managers list is not initialized. Call CollectManagers() before searching."); - // return false; - // } - - // foreach (var manager in Managers) - // { - // if (manager == null) - // { - // Debug.LogError($"A manager reference({typeof(T)}) has been removed or destroyed. Managers should never be null."); - // return false; - // } - // if (manager.Component is T found) - // { - // result = found; - // return true; - // } - // } - // return false; + return Registry.TryGet(out result); } /// /// Collects all components from the provided GameObjects, @@ -84,13 +56,6 @@ protected void CollectManagers(GameObject[] Objects) return; } - // if (Managers != null) - // { - // Debug.LogError("CollectManagers was called more than once. This is not allowed."); - // return; - // } - - //HashSet managerCache = new HashSet(); for (int i = 0; i < Objects.Length; i++) { GameObject Obj = Objects[i]; @@ -102,19 +67,10 @@ protected void CollectManagers(GameObject[] Objects) foreach (var manager in found) { Component comp = manager.Component; - Services.Register(comp.GetType(), comp); + Registry.Register(comp, comp.GetType()); manager.InitiateManager(this); - // if (managerCache.Add(manager)) - // { - // } - // else - // { - // Debug.LogWarning($"Duplicate manager detected: {manager.GetType().Name} in {manager.Component.gameObject.name}"); - // continue; - // } } } - //Managers = managerCache.ToArray(); } } diff --git a/Runtime/Core/AAA/ServiceLocator.cs b/Runtime/Core/AAA/ServiceLocator.cs index 2938e3a..3a724ab 100644 --- a/Runtime/Core/AAA/ServiceLocator.cs +++ b/Runtime/Core/AAA/ServiceLocator.cs @@ -9,11 +9,22 @@ namespace RealMethod /// Stores services by interface type using WeakReferences. /// Thread‑safe for Register / Get / Remove operations. /// - public class ServiceLocator + public sealed class ServiceLocator : IInspectorInfo { private readonly Dictionary> _services = new(); + public int Count => _services.Count; private readonly object _lock = new(); + + + // Implement IInspectorInfo Interface + string IInspectorInfo.GetInfo() + { + return $"Regitereis({_services.Count})"; + } + + + /// /// Register a service instance under its concrete or interface type T. /// T must implement IService so we know this is a service. @@ -22,49 +33,55 @@ public class ServiceLocator public void Register(T service, bool overwrite = false) where T : class { - Register(typeof(T), service, overwrite); + Register(service, typeof(T), overwrite); } - /// /// Register a service instance under its concrete or interface type T. /// T must implement IService so we know this is a service. /// Stored internally as WeakReference<object>. /// - public void Register(Type type, object service, bool overwrite = false) + public void Register(object service, Type type = null, bool overwrite = false) { + Type serviceType = null; if (type == null) - throw new ArgumentNullException(nameof(type)); + { + serviceType = service.GetType(); + } + else + { + serviceType = type; + } + if (service == null) throw new ArgumentNullException(nameof(service)); - if (!type.IsAssignableFrom(service.GetType())) - throw new ArgumentException($"{service.GetType().Name} is not assignable to {type.Name}"); + if (!serviceType.IsAssignableFrom(service.GetType())) + throw new ArgumentException($"{service.GetType().Name} is not assignable to {serviceType.Name}"); lock (_lock) { - if (_services.TryGetValue(type, out var weak)) + if (_services.TryGetValue(serviceType, out var weak)) { if (!weak.TryGetTarget(out _)) { - _services[type] = new WeakReference(service); + _services[serviceType] = new WeakReference(service); return; } if (overwrite) { - _services[type] = new WeakReference(service); + _services[serviceType] = new WeakReference(service); return; } throw new InvalidOperationException( - $"Service of type {type.Name} is already registered and still alive."); + $"Service of type {serviceType.Name} is already registered and still alive."); } - _services[type] = new WeakReference(service); + _services[serviceType] = new WeakReference(service); } } - /// /// Register only if no live instance is currently registered for T. /// @@ -85,7 +102,6 @@ public void RegisterIfAbsent(T service) } } } - /// /// Get the registered instance for type T. /// Returns null if not found or GC-collected. @@ -110,7 +126,6 @@ public T Get() where T : class return null; } } - /// /// Try to get the registered instance for type T. /// @@ -136,7 +151,6 @@ public bool TryGet(out T result) where T : class result = null; return false; } - /// /// Check whether a live instance exists for type T. /// @@ -150,7 +164,6 @@ public bool Exists() where T : class weak.TryGetTarget(out _); } } - /// /// Manually unregisters (removes) a service type. /// @@ -176,7 +189,6 @@ public void Unregister(Type type) if (_services.ContainsKey(type)) _services.Remove(type); } - /// /// Force-clears all services from the locator. /// @@ -187,5 +199,6 @@ public void ClearAll() _services.Clear(); } } + } } diff --git a/Runtime/Core/Architecture/Game.cs b/Runtime/Core/Architecture/Game.cs index c6abec7..2f964bd 100644 --- a/Runtime/Core/Architecture/Game.cs +++ b/Runtime/Core/Architecture/Game.cs @@ -4,6 +4,7 @@ using UnityEngine.SceneManagement; using System.Linq; + #if UNITY_EDITOR using UnityEditor; using UnityEditor.SceneManagement; @@ -105,7 +106,7 @@ public static bool IsPaused /// Returns true if the Game system has one or more registered services; /// otherwise, returns false. /// - public static bool HasService => Instance.Services.Count > 0; + public static bool HasService => Instance.GameServices.Count > 0; /// /// Event invoked when a scene or world starts or finishes loading. /// The boolean parameter is true when loading starts and false when loading ends. @@ -172,9 +173,9 @@ public ISaveSystem SaveSystem /// - /// List of runtime-registered instances owned by the game. + /// List of runtime-registered instances owned by the game. /// - private readonly Dictionary Services = new(); + private readonly List GameServices = new List(); @@ -226,7 +227,7 @@ private static void InitializeGame() if (targetService == null) { Debug.LogWarning($"GetGameBridgeType that was empty. DefaultGameBridge Created"); - Bridge = new DefaultGameBridge(); + Bridge = new DefaultGameBridge(Instance.Notify_OnWorldInitiate); } else { @@ -234,22 +235,21 @@ private static void InitializeGame() { try { - Bridge = (GameBridge)Activator.CreateInstance(targetService); + var parameter = new object[1] { (Action)Instance.Notify_OnWorldInitiate }; + Bridge = (GameBridge)Activator.CreateInstance(targetService, parameter); } catch (Exception ex) { Debug.LogError($"Failed to instantiate {targetService}: {ex.Message}. DefaultGameBridge Created"); - Bridge = new DefaultGameBridge(); + Bridge = new DefaultGameBridge(Instance.Notify_OnWorldInitiate); } } else { Debug.LogWarning($"Type {targetService} is not assignable to GameBridge. DefaultGameBridge Created"); - Bridge = new DefaultGameBridge(); + Bridge = new DefaultGameBridge(Instance.Notify_OnWorldInitiate); } } - ((IRelationBridge)Bridge).BindWorldCreated(Instance.Notify_OnWorldInitiate); - ((IService)Bridge).OnRegister(Instance); // Set GameConfig if (ProjectSettings.GetGameConfigAsset() != null) @@ -373,88 +373,60 @@ public static T CastWorld() where T : class } } /// - /// Registers a service instance of type in the service container. + /// Adds a new service of type to the game if one does not already exist. + /// Newly created service will be bound to managers and notified to the global service system. /// - /// - /// The type of the service to register. Must implement . - /// - /// - /// The service instance to register. - /// - /// - /// Optional object providing context or ownership information for the registration. - /// Passed to . - /// - /// - /// true if the service was successfully registered; - /// false if a service of the same type is already registered. - /// - /// - /// This method prevents duplicate registrations. If a service of the same type - /// is already registered, an error is logged and the method returns false. - /// Upon successful registration, is invoked. - /// - public static bool Register(T service, object author = null) where T : IService - { - Type TypeService = typeof(T); - - if (Instance.Services.ContainsKey(TypeService)) + /// Service type to add. + /// The newly created service instance, or null if a service of the same type already exists. + public static T AddService() where T : Service, new() + { + // Check if you game not initialized + if (!IsGameInitialized) { - Debug.LogError($"IService {TypeService} already registered."); - return false; + Debug.LogWarning($"Game doesn't initialized !"); + return null; } - service.OnRegister(author); - Instance.Services[TypeService] = service; - return true; + if (Registry.Exists()) + { + Debug.LogWarning($"Service of type {typeof(T)} is already added and still alive."); + return null; + } + // Create Service + T newService = new T(); + Registry.Register(newService); + Instance.GameServices.Add(newService); + return newService; } /// - /// Checks whether a service of type is currently registered - /// in the Service Locator. + /// Removes the service instance of type if present. + /// Managers and the global service system will be notified of the removal. /// - /// - /// The type of service to check. The type must implement . - /// - /// - /// true if a service of type is registered; otherwise false. - /// - public static bool IsRegistered() where T : IService + /// Service type to remove. + /// true if a service was found and removed; otherwise false. + public static bool RemoveService() where T : Service { - return Instance.Services.ContainsKey(typeof(T)); - } - /// - /// Remove service instance - /// - /// The object type that implement 'IService' - public static bool Unregister(object author = null) where T : IService - { - Type TypeService = typeof(T); - - if (Instance.Services.ContainsKey(TypeService)) - { - Instance.Services[TypeService].OnUnregister(author); - return Instance.Services.Remove(TypeService); ; - } - else + Service targetService = Instance.GameServices.FirstOrDefault(s => s.GetType() == typeof(T)); + if (targetService != null) { - Debug.LogWarning($"IService {TypeService} Not found."); - return false; + Instance.GameServices.Remove(targetService); + Registry.Unregister(); + ((IDisposable)targetService).Dispose(); + targetService = null; + return true; } + Debug.LogWarning($"Service of type {typeof(T).Name} not found to remove."); + return false; } /// /// Retrieves the service instance of type if available. /// /// IService type to retrieve. /// The service instance of type , or null if not found. - public static T GetService() where T : IService + public static T GetService() where T : Service { - Type TypeService = typeof(T); - - if (Instance.Services.TryGetValue(TypeService, out var provider)) - return (T)provider.Self; - - throw new Exception($"Service {TypeService} not registered."); + return Registry.Get(); } /// /// Attempts to find a service of type . @@ -462,27 +434,16 @@ public static T GetService() where T : IService /// IService type to find. /// Out parameter that receives the service if found. /// true if the service was found; otherwise false. - public static bool TryGetService(out T service) where T : IService + public static bool TryGetService(out T service) where T : Service { - if (Instance.Services.TryGetValue(typeof(T), out var provider)) - { - service = (T)provider.Self; - return true; - } - - service = default; - return false; + return Registry.TryGet(out service); } /// /// Clear all services in Game /// public static void ClearService() { - foreach (var service in Instance.Services.Values) - { - service.OnUnregister(null); - } - Instance.Services.Clear(); + Registry.ClearAll(); } /// /// Requests a scene load by build index . @@ -1019,10 +980,6 @@ protected virtual bool CanChangeState(int A, int B, object author) /// The newly initiated world instance. private void Notify_OnWorldInitiate(World NewWorld) { - foreach (var service in Services) - { - service.Value.OnWorldChanging(World, NewWorld); - } World = NewWorld; OnWorldChanged(World); } @@ -1032,16 +989,9 @@ private void Notify_OnWorldInitiate(World NewWorld) private void Notify_OnGameQuit() { Application.quitting -= Notify_OnGameQuit; - ((IRelationBridge)Bridge).UnbindWorldCreated(); - if (Services != null) - { - foreach (var service in Services) - { - service.Value.OnUnregister(this); - } - ClearService(); - } - ((IService)Bridge).OnUnregister(this); + ClearService(); + ((IDisposable)Bridge).Dispose(); + Bridge = null; #if UNITY_EDITOR // Debug only: force GC to verify no references remain GC.Collect(); @@ -1113,9 +1063,11 @@ private void FixedUpdate() /// Returns the type names of all registered game services. /// /// Array of service type names. - public string[] GetAllServiceInfo() + public override IInspectorInfo[] GetAllInfo() { - return Services.Values.Select(t => t.GetInspectorInfo()).ToArray(); + var baseInfo = base.GetAllInfo(); + var servicesInfo = GameServices != null ? GameServices.OfType().ToArray() : Array.Empty(); + return baseInfo.Concat(servicesInfo).ToArray(); } #endif @@ -1202,4 +1154,5 @@ private void OnDrawGizmos() protected abstract void OnGameClosed(); } + } \ No newline at end of file diff --git a/Runtime/Core/Architecture/GameBridge.cs b/Runtime/Core/Architecture/GameBridge.cs index 18bf307..66ef043 100644 --- a/Runtime/Core/Architecture/GameBridge.cs +++ b/Runtime/Core/Architecture/GameBridge.cs @@ -1,10 +1,8 @@ using System; using System.Collections; +using System.Collections.Generic; using UnityEngine; using UnityEngine.SceneManagement; -using System.Collections.Generic; -using Codice.Client.Common; -using System.Runtime.CompilerServices; namespace RealMethod { @@ -29,14 +27,6 @@ public interface IRelationBridge /// bool RegisterWorld(World world); /// - /// Binds a callback invoked when the main world is added. - /// - void BindWorldCreated(Action func); - /// - /// Unbinds the main world added callback. - /// - void UnbindWorldCreated(); - /// /// Called by world class to tell game the initiation is complite /// void WorldIsReady(); @@ -69,6 +59,18 @@ public interface ILoadScneBridge } + /// + /// A bridge that receives notifications before and after the global world changes. + /// + public interface IBridge + { + /// + /// Called after the new world has been set as the active global world. + /// + void OnWorldChanged(World world); + } + + /// /// Base class for any gamebridge in the framework. /// Provides core functionality for: @@ -81,40 +83,38 @@ public interface ILoadScneBridge /// Inherits from and implements /// to integrate with the game's internal world and service management system. /// - public abstract class GameBridge : IService, IRelationBridge, ILoadScneBridge + public abstract class GameBridge : IDisposable, IRelationBridge, ILoadScneBridge, IInspectorInfo { // Events private Action GameReadyEvent; - private Action NewWorldEvent; + private Action SceneLoadingEvent; private Action SceneLoadingProcessEvent; private bool isLoading; public bool IsHolding { get; private set; } = false; protected float FadeTime = 0; private Scene CurrrentScene; - public static Scene LastActiveScene; - public static bool SceneWillUnload { get; private set; } + public Scene LastActiveScene; + public bool SceneWillUnload { get; private set; } + + private readonly Action OnNextWorld; + private readonly List> bridges = new(); - // Implement IService Interface - void IService.OnRegister(object author) + + + public GameBridge(Action method) { + OnNextWorld = method ?? throw new ArgumentNullException(nameof(method)); SceneManager.activeSceneChanged += OnActiveSceneChanged; } - void IService.OnWorldChanging(World Previous, World New) - { - throw new NotImplementedException(); - } - void IService.OnUnregister(object author) + + + + // Implement IDisposable Interface + void IDisposable.Dispose() { SceneManager.activeSceneChanged -= OnActiveSceneChanged; } -#if UNITY_EDITOR - string IService.GetInspectorInfo() - { - return $"IsLoading:{isLoading} - FadeTime:{FadeTime}"; - } -#endif - // Implement IRelationBridge Interface event Action IRelationBridge.OnGameReady { @@ -133,24 +133,10 @@ bool IRelationBridge.RegisterWorld(World world) { return TryToRegisterWorld(world); } - void IRelationBridge.BindWorldCreated(Action func) - { - if (NewWorldEvent != null) - { - Debug.LogWarning("BindMainWorldAdd is already binded this interface is internal didnt use in another script or your game"); - return; - } - NewWorldEvent = func; - } - void IRelationBridge.UnbindWorldCreated() - { - NewWorldEvent = null; - } void IRelationBridge.WorldIsReady() { GameReadyEvent?.Invoke(); } - // Implement ILoadScneBridge Interface event Action ILoadScneBridge.OnSceneLoading { @@ -179,76 +165,53 @@ event Action ILoadScneBridge.OnSceneLoadingProcess bool ILoadScneBridge.IsLoading => isLoading; - /// - /// Call this when you want to define new World class to game - /// - /// The world instance will set as main world for game. - protected void SetMianWorld(World world) - { - CurrrentScene = world.gameObject.scene; - NewWorldEvent?.Invoke(world); - SceneWillUnload = false; - } - /// - /// Call this when you want to define new World class that created and should not be main world (probably deleted) - /// - /// The world instance will not set to main world for game. - protected void SetAdditiveWorld(World world) - { - world.enabled = false; - OnAdditiveWorldDetected(world); - } - - /// - /// Request for this NewWorld to set for Main World in Scene + /// Registers a bridge provider using a weak reference. + /// Prevents duplicate bindings and ignores null providers. /// - /// The New WorldClass Refrence in Scene - /// - /// If this request is valid return true that mean this world set as main world. - /// If this request false means this world import from scen that is additive and should deactive. - /// The bridge instance to bind. + /// Thrown when provider is null. + public void Bind(IBridge provider) { - Scene NewScene = NewWorld.gameObject.scene; + if (provider == null) + throw new ArgumentNullException(nameof(provider)); - // If no instance yet, this becomes the persistent instance - if (Game.World == null) + // Prevent duplicates + foreach (var weak in bridges) { - SetMianWorld(NewWorld); - return true; + if (weak.TryGetTarget(out IBridge existing) && existing == provider) + return; // Already stored } - // This is a new scene loaded in Single mode - if (SceneWillUnload && NewScene == LastActiveScene) - { - // Replace instance because old scene is going away immediately - SetMianWorld(NewWorld); - return true; - } - - // Different scene but NOT replacing old => Additive load - if (NewScene != CurrrentScene) - { - SetAdditiveWorld(NewWorld); - return false; ; - } - else - { - Debug.LogError($"[WorldRegistry] Duplicate world in SAME scene : {NewWorld.gameObject.name} / {Game.World.gameObject}"); - return false; - } + bridges.Add(new WeakReference(provider)); } /// - /// Called when new scene loaded and during base world valid new world created. + /// Removes the specified bridge instance from the registry. /// - /// The New WorldClass Refrence in AdditiveScene - protected virtual void OnAdditiveWorldDetected(World AdditiveWorld) + /// The object to unbind (must implement IBridge). + /// + /// True if the bridge was found and removed; otherwise false. + /// + public bool Unbind(object obj) { - UnityEngine.Object.Destroy(AdditiveWorld.gameObject); + if (obj is not IBridge provider) + return false; + + for (int i = bridges.Count - 1; i >= 0; i--) // reverse-safe removal + { + var weak = bridges[i]; + + if (!weak.TryGetTarget(out IBridge bridge) || bridge == provider) + { + bridges.RemoveAt(i); + return true; + } + } + + return false; } /// /// Starts loading a scene by name using a coroutine. @@ -337,11 +300,104 @@ public virtual IEnumerator GetLoadWorldCorotine(WorldAsset WorldScene) } - private static void OnActiveSceneChanged(Scene oldScene, Scene newScene) + + + + + /// + /// Call this when you want to define new World class to game + /// + /// The world instance will set as main world for game. + protected void SetMianWorld(World world) + { + CurrrentScene = world.gameObject.scene; + OnNextWorld.Invoke(world); + NotifyBridges(world); + SceneWillUnload = false; + } + /// + /// Call this when you want to define new World class that created and should not be main world (probably deleted) + /// + /// The world instance will not set to main world for game. + protected void SetAdditiveWorld(World world) + { + world.enabled = false; + OnAdditiveWorldDetected(world); + } + /// + /// Request for this NewWorld to set for Main World in Scene + /// + /// The New WorldClass Refrence in Scene + /// + /// If this request is valid return true that mean this world set as main world. + /// If this request false means this world import from scen that is additive and should deactive. + /// Additive load + if (NewScene != CurrrentScene) + { + SetAdditiveWorld(NewWorld); + return false; ; + } + else + { + Debug.LogError($"[WorldRegistry] Duplicate world in SAME scene : {NewWorld.gameObject.name} / {Game.World.gameObject}"); + return false; + } + } + /// + /// Called when new scene loaded and during base world valid new world created. + /// + /// The New WorldClass Refrence in AdditiveScene + protected virtual void OnAdditiveWorldDetected(World AdditiveWorld) + { + UnityEngine.Object.Destroy(AdditiveWorld.gameObject); + } + + + + + private void OnActiveSceneChanged(Scene oldScene, Scene newScene) { LastActiveScene = newScene; SceneWillUnload = true; // old scene will be destroyed next frame } + /// + /// Calls the bridge method on all active bridge instances. + /// Invalid or collected references are removed automatically. + /// + private void NotifyBridges(World Newworld) + { + for (int i = bridges.Count - 1; i >= 0; i--) + { + if (bridges[i].TryGetTarget(out IBridge bridge)) + { + bridge.OnWorldChanged(Newworld); + } + else + { + bridges.RemoveAt(i); + } + } + } private float RemapClamped(float value, float inMin, float inMax, float outMin, float outMax) { // Prevent divide by zero @@ -498,5 +554,19 @@ private IEnumerator LoadWorldAsync(WorldAsset WS) } + + + +#if UNITY_EDITOR + // Implement IInspectorInfo Interface + string IInspectorInfo.GetInfo() + { + //GetType().ToString() + ": " + return $"IsLoading:{isLoading} - FadeTime:{FadeTime}"; + } +#endif + + + } } \ No newline at end of file diff --git a/Runtime/Core/Architecture/GameManager.cs b/Runtime/Core/Architecture/GameManager.cs index e1f9de9..44e5c68 100644 --- a/Runtime/Core/Architecture/GameManager.cs +++ b/Runtime/Core/Architecture/GameManager.cs @@ -25,4 +25,20 @@ public interface IGameManager void InitiateManager(Scope owner); } + public class GameManager : MonoBehaviour, IGameManager + { + // Implement IGameManager Interface + public void InitiateManager(Scope owner) + { + OnInitiateManager(owner); + } + + + + protected virtual void OnInitiateManager(Scope owner) + { + + } + } + } \ No newline at end of file diff --git a/Runtime/Core/Architecture/Scope.cs b/Runtime/Core/Architecture/Scope.cs deleted file mode 100644 index 837132e..0000000 --- a/Runtime/Core/Architecture/Scope.cs +++ /dev/null @@ -1,104 +0,0 @@ -using System.Collections.Generic; -using System.Linq; -using UnityEngine; - -namespace RealMethod -{ - public abstract class Scope : MonoBehaviour - { - /// - /// Cached array of managers that were instantiated from configured game prefabs or World gameobject. - /// - private IGameManager[] Managers = null; - - - - /// - /// Attempts to find a manager whose Component matches the specified type . - /// - /// The component type to search for. - /// - /// When this method returns, contains the found component of type if successful; - /// otherwise null. - /// - /// - /// true if a matching manager component was found; otherwise false. - /// - public bool TryFindManager(out T result) where T : Component, IGameManager - { - result = null; - - if (Managers == null) - return false; - - foreach (var manager in Managers) - { - if (manager?.Component is T found) - { - result = found; - return true; - } - } - - return false; - } - - - /// - /// Collects all components from the provided GameObjects, - /// initializes them, and stores them internally. - /// - /// This method can only be executed once. If it is called again after managers - /// have already been collected, an error will be logged and the method will exit. - /// - /// Duplicate manager instances are ignored and logged as warnings. - /// - /// - /// Array of GameObjects to search for components. - /// Null objects in the array are skipped. - /// - protected void CollectManagers(GameObject[] Objects) - { - if (Objects == null) - { - Debug.LogError("CollectManagers received a null GameObjects array."); - return; - } - - - if (Managers != null) - { - Debug.LogError("CollectManagers was called more than once. This is not allowed."); - return; - } - - HashSet managerCache = new HashSet(); - for (int i = 0; i < Objects.Length; i++) - { - GameObject Obj = Objects[i]; - if (Obj == null) - continue; - - var found = Obj.GetComponents(); - - foreach (var manager in found) - { - if (managerCache.Add(manager)) - { - manager.InitiateManager(this); - } - else - { - Debug.LogWarning($"Duplicate manager detected: {manager.GetType().Name} in {manager.Component.gameObject.name}"); - continue; - } - } - } - Managers = managerCache.ToArray(); - } - - } - - - -} \ No newline at end of file diff --git a/Runtime/Core/Architecture/Scope.cs.meta b/Runtime/Core/Architecture/Scope.cs.meta deleted file mode 100644 index f8577a3..0000000 --- a/Runtime/Core/Architecture/Scope.cs.meta +++ /dev/null @@ -1,2 +0,0 @@ -fileFormatVersion: 2 -guid: cdc1d3e86457c474ca9464cbbf61f0f6 \ No newline at end of file diff --git a/Runtime/Core/Architecture/Service.cs b/Runtime/Core/Architecture/Service.cs index f9e13f0..ebae9b2 100644 --- a/Runtime/Core/Architecture/Service.cs +++ b/Runtime/Core/Architecture/Service.cs @@ -1,73 +1,39 @@ +using System; + namespace RealMethod { - /// - /// Defines the contract for a service that can respond to lifecycle events. - /// - public interface IService + public abstract class Service : IBridge, IInspectorInfo, IDisposable { - /// - /// Returns the object instance that implements this service. - /// - object Self => this; - /// - /// Called when the service is created. - /// - /// The object responsible for creating the service. - void OnRegister(object author); - /// - /// Called when the world or environment updates. - /// - void OnWorldChanging(World Previous, World New); - /// - /// Called when the service is deleted or destroyed. - /// - /// The object responsible for deleting the service. - void OnUnregister(object author); -#if UNITY_EDITOR - /// - /// Returns a formatted string containing information about this service - /// intended for display in the Unity Inspector or debugging interfaces. - /// This method is for visualization purposes only and must not affect logic. - /// - /// Formatted display information. - string GetInspectorInfo(); -#endif - } + public Service() + { + Game.Bridge.Bind(this); + OnBegin(); + } + + // Implement IBridge Interface + void IBridge.OnWorldChanged(World world) => OnWorldChanged(); + void IDisposable.Dispose() + { + Game.Bridge.Unbind(this); + OnEnd(); + } + + // Abstraction Methods + protected abstract void OnBegin(); + protected abstract void OnWorldChanged(); + protected abstract void OnEnd(); - /// - /// Base abstract class implementing . - /// Provides a framework for derived services to handle lifecycle events. - /// - public abstract class Service : IService - { - // Implement IService Interface - /// - /// Called when the service starts. Must be implemented by derived classes. - /// - /// The object responsible for creating the service. - public abstract void OnRegister(object author); - /// - /// Called when a new world or environment is initialized. - /// Must be implemented by derived classes. - /// - public abstract void OnWorldChanging(World Previous, World New); - /// - /// Called when the service ends or is deleted. - /// Must be implemented by derived classes. - /// - /// The object responsible for deleting the service. - public abstract void OnUnregister(object author); #if UNITY_EDITOR - string IService.GetInspectorInfo() + string IInspectorInfo.GetInfo() { - return GetDisplayInfo(); + return GetInspectorInfo(); } - protected virtual string GetDisplayInfo() + protected virtual string GetInspectorInfo() { - return GetType().ToString() + ": "; + return null; } #endif - } + } \ No newline at end of file diff --git a/Runtime/Core/Architecture/Service.cs.meta b/Runtime/Core/Architecture/Service.cs.meta index 2076019..8527ce4 100644 --- a/Runtime/Core/Architecture/Service.cs.meta +++ b/Runtime/Core/Architecture/Service.cs.meta @@ -1,11 +1,2 @@ fileFormatVersion: 2 -guid: 127dbea1049718c4684febe56e2000cc -MonoImporter: - externalObjects: {} - serializedVersion: 2 - defaultReferences: [] - executionOrder: 0 - icon: {instanceID: 0} - userData: - assetBundleName: - assetBundleVariant: +guid: ec193cd2194f8614eb221434996c3f62 \ No newline at end of file diff --git a/Runtime/Core/DefaultClass.meta b/Runtime/Core/DefaultClass.meta new file mode 100644 index 0000000..3508edf --- /dev/null +++ b/Runtime/Core/DefaultClass.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: c2eb30f6d9195524693f6c11671ee28b +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Runtime/Core/DefaultClass/DefultGame.cs b/Runtime/Core/DefaultClass/DefultGame.cs index 6788589..8b1b30b 100644 --- a/Runtime/Core/DefaultClass/DefultGame.cs +++ b/Runtime/Core/DefaultClass/DefultGame.cs @@ -11,8 +11,7 @@ protected override void OnGameOpen() } protected override void OnGameInitialized() { - //DebugService NewDebug = new DebugService(); - //RegisterService(NewDebug, this); + AddService(); Debug.Log("DefultGame Initialized"); } protected override void OnGameStart() diff --git a/Runtime/Core/Definitions/InspectorInfo.cs b/Runtime/Core/Definitions/InspectorInfo.cs new file mode 100644 index 0000000..8eb34f2 --- /dev/null +++ b/Runtime/Core/Definitions/InspectorInfo.cs @@ -0,0 +1,15 @@ +namespace RealMethod +{ + public interface IInspectorInfo + { +#if UNITY_EDITOR + /// + /// Returns a formatted string containing information about this service + /// intended for display in the Unity Inspector or debugging interfaces. + /// This method is for visualization purposes only and must not affect logic. + /// + /// Formatted display information. + string GetInfo(); +#endif + } +} \ No newline at end of file diff --git a/Runtime/Core/Definitions/InspectorInfo.cs.meta b/Runtime/Core/Definitions/InspectorInfo.cs.meta new file mode 100644 index 0000000..b1251df --- /dev/null +++ b/Runtime/Core/Definitions/InspectorInfo.cs.meta @@ -0,0 +1,2 @@ +fileFormatVersion: 2 +guid: 1d6b0a4bb10ab3a478b1d62bd5e92926 \ No newline at end of file diff --git a/Runtime/Pattern/Services/InputService.cs b/Runtime/Pattern/Services/InputService.cs index 0e39f95..9470fa6 100644 --- a/Runtime/Pattern/Services/InputService.cs +++ b/Runtime/Pattern/Services/InputService.cs @@ -7,27 +7,33 @@ public abstract class InputService : Service { private InputActionAsset CurrentInputAsset; - public sealed override void OnRegister(object Author) + protected override void OnBegin() { if (TryFindInputAsset(out InputActionAsset newAsset)) { ReplaceInputAsset(newAsset); } } - public sealed override void OnWorldChanging(World Previous, World New) + protected override void OnWorldChanged() { if (TryFindInputAsset(out InputActionAsset newAsset)) { ReplaceInputAsset(newAsset); } } - public sealed override void OnUnregister(object Author) + protected override void OnEnd() { if (CurrentInputAsset != null) { OnDisposeInputAsset(CurrentInputAsset); } } +#if UNITY_EDITOR + protected override string GetInspectorInfo() + { + return CurrentInputAsset.name; + } +#endif public void ReplaceInputAsset(InputActionAsset asset) @@ -64,6 +70,8 @@ protected virtual bool TryFindInputAsset(out InputActionAsset asset) protected abstract void OnAcquireInputAsset(InputActionAsset asset); protected abstract void OnDisposeInputAsset(InputActionAsset asset); + + } diff --git a/Runtime/Pattern/Services/RuleService.cs b/Runtime/Pattern/Services/RuleService.cs index 6c032f4..38262fa 100644 --- a/Runtime/Pattern/Services/RuleService.cs +++ b/Runtime/Pattern/Services/RuleService.cs @@ -13,7 +13,8 @@ public RuleService() Rules = new NameTable>(5); } - public override void OnWorldChanging(World Previous, World New) + + protected override void OnWorldChanged() { foreach (var item in Rules) { diff --git a/Runtime/Pattern/Services/StateService.cs b/Runtime/Pattern/Services/StateService.cs index 2e36aa7..8184aa7 100644 --- a/Runtime/Pattern/Services/StateService.cs +++ b/Runtime/Pattern/Services/StateService.cs @@ -16,14 +16,13 @@ public StateService(byte firstState) } // StateService Methods - public sealed override void OnWorldChanging(World Previous , World New) + protected override void OnWorldChanged() { if (CanResetforNewWorld(Game.World)) { ResetToDefault(); } } - // Public Functions public bool SetState(byte target) { diff --git a/Runtime/ReadySet/Services/DebugService.cs b/Runtime/ReadySet/Services/DebugService.cs index 8faf239..824d887 100644 --- a/Runtime/ReadySet/Services/DebugService.cs +++ b/Runtime/ReadySet/Services/DebugService.cs @@ -87,7 +87,7 @@ void ITask.Active() } void ITask.Deactive() { - MyOwner.OnLineDeactive(this); + MyOwner.RemoveLog(this); } // Implement IDraw Interface bool IDraw.CanDraw(int Index) @@ -120,12 +120,13 @@ DrawMode IDrawTask.GetDrawMode() } } - private ILogHandler defaultLogHandler; - - private List Lines = new List(10); + // LineSetting public Vector2 PrintPivot = new Vector2(10, 10); public float PrintSpace => Screen.height / 40; public int PrintSize = 1; + private List Lines = new List(10); + private ILogHandler defaultLogHandler; + public event System.Action OnLogWrited; // Implement ILogHandler Interfacwe @@ -147,6 +148,7 @@ void ILogHandler.LogFormat(LogType logType, Object context, string format, param { Debug.unityLogger.logHandler.LogFormat(logType, context, format, args); } + OnLogWrited?.Invoke(logType, format); } void ILogHandler.LogException(System.Exception exception, Object context) { @@ -156,33 +158,41 @@ void ILogHandler.LogException(System.Exception exception, Object context) Game.Draw(NewLine); defaultLogHandler.LogException(exception, context); + OnLogWrited?.Invoke(LogType.Exception, exception.Message); } + // Service Methods - public override void OnRegister(object Author) + protected override void OnBegin() { defaultLogHandler = Debug.unityLogger.logHandler; Debug.unityLogger.logHandler = this; } - public override void OnWorldChanging(World Previous, World New) + protected override void OnWorldChanged() { + // Nothing } - public override void OnUnregister(object Author) + protected override void OnEnd() { - if (defaultLogHandler != null) - Debug.unityLogger.logHandler = defaultLogHandler; + Debug.unityLogger.logHandler = defaultLogHandler; Lines.Clear(); } - protected override string GetDisplayInfo() - { - return $"{base.GetDisplayInfo()}Lines:{Lines.Count}"; - } // Methods - private void OnLineDeactive(LogLine line) + private void RemoveLog(LogLine line) { Lines.Remove(line); } + + + +#if UNITY_EDITOR + protected override string GetInspectorInfo() + { + return $"Lines({Lines.Count})"; + } +#endif + } } \ No newline at end of file diff --git a/Runtime/ReadySet/Services/DespawnService.cs b/Runtime/ReadySet/Services/Despawn.cs similarity index 89% rename from Runtime/ReadySet/Services/DespawnService.cs rename to Runtime/ReadySet/Services/Despawn.cs index 5939d1f..153a528 100644 --- a/Runtime/ReadySet/Services/DespawnService.cs +++ b/Runtime/ReadySet/Services/Despawn.cs @@ -39,55 +39,41 @@ namespace RealMethod /// system that intelligently reuses previously found managers and adapts to /// scene changes. /// - public sealed class Despawn : IService + public sealed class Despawn : IBridge, System.IDisposable, IInspectorInfo { - private static Despawn Ins - { - get - { - if (!Game.TryGetService(out Despawn CacheInstance)) - { - CacheInstance = new Despawn(); - Game.Register(CacheInstance, null); - } - return CacheInstance; - } - } - private Dictionary Managers; - + private static Despawn Ins => CacheInstance.Value; + private static System.Lazy CacheInstance = new System.Lazy(() => new Despawn()); + private Dictionary Managers; public Despawn() { + Game.Bridge.Bind(this); Managers = new(); } - public Despawn(Dictionary DefaultManager) - { - Managers = DefaultManager; - } - - // Implement IService Interface - public object GetServiceClass() => this; - void IService.OnRegister(object Author) - { - } - void IService.OnWorldChanging(World Previous, World New) + // Implement IBridge Interface + void IBridge.OnWorldChanged(World world) { Managers.Clear(); } - void IService.OnUnregister(object Author) + // Implement IDisposable Interface + void System.IDisposable.Dispose() { + Game.Bridge.Unbind(this); Managers.Clear(); } + #if UNITY_EDITOR - string IService.GetInspectorInfo() + // Implement IInspectorInfo Interface + string IInspectorInfo.GetInfo() { - return $"SelectedManagers:{Managers.Count}"; + return $"Managers({Managers.Count})"; } #endif + // Public Functions public void AddManager(IGameManager manager) { diff --git a/Runtime/ReadySet/Services/DespawnService.cs.meta b/Runtime/ReadySet/Services/Despawn.cs.meta similarity index 100% rename from Runtime/ReadySet/Services/DespawnService.cs.meta rename to Runtime/ReadySet/Services/Despawn.cs.meta diff --git a/Runtime/ReadySet/Services/NetworkService.cs b/Runtime/ReadySet/Services/NetworkService.cs index 8f4de01..550c7ee 100644 --- a/Runtime/ReadySet/Services/NetworkService.cs +++ b/Runtime/ReadySet/Services/NetworkService.cs @@ -15,16 +15,15 @@ public sealed class NetworkService : Service private const string xmlApi = "http://api.openweathermap.org/data/2.5/weather?q=Chicago,us&mode=xml&APPID="; - - public override void OnRegister(object Author) + protected override void OnBegin() { throw new NotImplementedException(); } - public override void OnWorldChanging(World Previous, World New) + protected override void OnWorldChanged() { throw new NotImplementedException(); } - public override void OnUnregister(object Author) + protected override void OnEnd() { throw new NotImplementedException(); } @@ -82,7 +81,6 @@ public IEnumerator DownloadImage(Action callback) } - } } diff --git a/Runtime/ReadySet/Services/SpawanService.cs b/Runtime/ReadySet/Services/Spawan.cs similarity index 96% rename from Runtime/ReadySet/Services/SpawanService.cs rename to Runtime/ReadySet/Services/Spawan.cs index 36bca8d..a5643e1 100644 --- a/Runtime/ReadySet/Services/SpawanService.cs +++ b/Runtime/ReadySet/Services/Spawan.cs @@ -42,51 +42,36 @@ namespace RealMethod /// system that intelligently reuses previously found managers and adapts to /// scene changes. /// - public sealed class Spawn : IService + public sealed class Spawn : IBridge, System.IDisposable, IInspectorInfo { - private static Spawn Ins - { - get - { - if (!Game.TryGetService(out Spawn CacheInstance)) - { - CacheInstance = new Spawn(); - Game.Register(CacheInstance, null); - } - return CacheInstance; - } - } + private static Spawn Ins => CacheInstance.Value; + private static System.Lazy CacheInstance = new System.Lazy(() => new Spawn()); private Dictionary Managers; public Spawn() { + Game.Bridge.Bind(this); Managers = new(); } - public Spawn(Dictionary DefaultManager) - { - Managers = DefaultManager; - } - - // Implement IService Interface - public object GetServiceClass() => this; - void IService.OnRegister(object Author) - { - } - void IService.OnWorldChanging(World Previous, World New) + // Implement IBridge Interface + void IBridge.OnWorldChanged(World world) { Managers.Clear(); } - void IService.OnUnregister(object Author) + // Implement IDisposable Interface + void System.IDisposable.Dispose() { + Game.Bridge.Unbind(this); Managers.Clear(); } #if UNITY_EDITOR - string IService.GetInspectorInfo() + // Implement IInspectorInfo Interface + string IInspectorInfo.GetInfo() { - return $"SelectedManagers:{Managers.Count}"; + return $"Managers({Managers.Count})"; } #endif @@ -731,7 +716,5 @@ public static AudioSource Audio(AudioClip clip) } } - - } diff --git a/Runtime/ReadySet/Services/SpawanService.cs.meta b/Runtime/ReadySet/Services/Spawan.cs.meta similarity index 100% rename from Runtime/ReadySet/Services/SpawanService.cs.meta rename to Runtime/ReadySet/Services/Spawan.cs.meta diff --git a/Runtime/ReadySet/Services/TimeService.cs b/Runtime/ReadySet/Services/TimeService.cs index 45805b4..5162ce9 100644 --- a/Runtime/ReadySet/Services/TimeService.cs +++ b/Runtime/ReadySet/Services/TimeService.cs @@ -9,20 +9,26 @@ public sealed class TimeService : Service private NameTable RecordTime; // Service Methods - public override void OnRegister(object Author) + protected override void OnBegin() { serviceTime = Time.time; worldTime = Time.time; RecordTime = new NameTable(10); } - public override void OnWorldChanging(World Previous, World New) + protected override void OnWorldChanged() { worldTime = Time.time; } - public override void OnUnregister(object Author) + protected override void OnEnd() { RecordTime.Clear(); } +#if UNITY_EDITOR + protected override string GetInspectorInfo() + { + return $"Record({RecordTime.Count})"; + } +#endif // Public Functions public bool CheckRecord(string tag, float targettime) @@ -68,6 +74,8 @@ public bool IsValidTime(string tag) { return RecordTime.ContainsKey(tag); } + + } } From 1924866e1b17a049c2c56e235bd32eb0f1117691 Mon Sep 17 00:00:00 2001 From: Alijimpa Date: Sun, 3 May 2026 23:18:17 +0330 Subject: [PATCH 180/204] Fix GameEditor --- Editor/Core/Inspectors/GameEditor.cs | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/Editor/Core/Inspectors/GameEditor.cs b/Editor/Core/Inspectors/GameEditor.cs index 48008ae..95c9228 100644 --- a/Editor/Core/Inspectors/GameEditor.cs +++ b/Editor/Core/Inspectors/GameEditor.cs @@ -1,4 +1,3 @@ -using System.Linq; using UnityEditor; namespace RealMethod.Editor @@ -21,12 +20,12 @@ public override void OnInspectorGUI() EditorGUILayout.LabelField($"GameStat: {Game.State}"); EditorGUILayout.LabelField($"{GetWorld()} | {GetBrgidge()} | {GetConfig()}"); EditorGUILayout.Space(0.5f); - string[] Services = BaseComponent.GetAllServiceInfo(); + IInspectorInfo[] Info = BaseComponent.GetAllInfo(); //string[] Managers = BaseComponent.gameObject.GetComponents().Select(c => c.GetManagerClass().name).ToArray(); //string[] WorldManagers = Game.World ? Game.World.gameObject.GetComponents().Select(c => c.GetManagerClass().name).ToArray() : new string[0]; - for (int i = 0; i < Services.Length; i++) + for (int i = 0; i < Info.Length; i++) { - EditorGUILayout.LabelField($"{i + 1}. {Services[i]}"); + EditorGUILayout.LabelField($"{i + 1}.{Info[i].GetType().Name}-> {Info[i].GetInfo()}"); } } } From 0970e590f6880bb9b1b50f5dfae23defb28c1f70 Mon Sep 17 00:00:00 2001 From: Alijimpa Date: Mon, 4 May 2026 00:08:45 +0330 Subject: [PATCH 181/204] Refiene Inspector Info for all Implementation text style --- Editor/Core/Inspectors/GameEditor.cs | 31 +++++++------------ Runtime/Core/Architecture/Game.cs | 14 +++++++-- Runtime/Core/Architecture/GameBridge.cs | 7 +++-- Runtime/Core/Architecture/GameConfig.cs | 12 ++++++- .../{Method_Extension.cs => Extensions.cs} | 2 +- ...d_Extension.cs.meta => Extensions.cs.meta} | 0 .../{BackgroundService.cs => Systems.cs} | 0 ...kgroundService.cs.meta => Systems.cs.meta} | 0 Runtime/Core/{AAA.meta => Framework.meta} | 0 Runtime/Core/{AAA => Framework}/Kernel.cs | 0 .../Core/{AAA => Framework}/Kernel.cs.meta | 0 Runtime/Core/{AAA => Framework}/Scope.cs | 0 Runtime/Core/{AAA => Framework}/Scope.cs.meta | 0 .../Core/{AAA => Framework}/ServiceLocator.cs | 21 +++++++------ .../{AAA => Framework}/ServiceLocator.cs.meta | 0 Runtime/ReadySet/Services/DebugService.cs | 2 +- Runtime/ReadySet/Services/Despawn.cs | 2 +- Runtime/ReadySet/Services/Spawan.cs | 2 +- Runtime/ReadySet/Services/TimeService.cs | 2 +- 19 files changed, 55 insertions(+), 40 deletions(-) rename Runtime/Core/Definitions/{Method_Extension.cs => Extensions.cs} (86%) rename Runtime/Core/Definitions/{Method_Extension.cs.meta => Extensions.cs.meta} (100%) rename Runtime/Core/Definitions/{BackgroundService.cs => Systems.cs} (100%) rename Runtime/Core/Definitions/{BackgroundService.cs.meta => Systems.cs.meta} (100%) rename Runtime/Core/{AAA.meta => Framework.meta} (100%) rename Runtime/Core/{AAA => Framework}/Kernel.cs (100%) rename Runtime/Core/{AAA => Framework}/Kernel.cs.meta (100%) rename Runtime/Core/{AAA => Framework}/Scope.cs (100%) rename Runtime/Core/{AAA => Framework}/Scope.cs.meta (100%) rename Runtime/Core/{AAA => Framework}/ServiceLocator.cs (98%) rename Runtime/Core/{AAA => Framework}/ServiceLocator.cs.meta (100%) diff --git a/Editor/Core/Inspectors/GameEditor.cs b/Editor/Core/Inspectors/GameEditor.cs index 95c9228..f747754 100644 --- a/Editor/Core/Inspectors/GameEditor.cs +++ b/Editor/Core/Inspectors/GameEditor.cs @@ -5,43 +5,34 @@ namespace RealMethod.Editor [CustomEditor(typeof(Game), true)] public class GameEditor : UnityEditor.Editor { - private Game BaseComponent; + private Game Comp; + private string WorldName => Game.World != null ? Game.World.GetType().Name : "World Not Valid"; + private string BridgeName => Game.Bridge != null ? Game.Bridge.GetType().Name : "GameBridge Not Valid"; + private string ConfigName => Game.Config != null ? Game.Config.GetType().Name : "GameConfig Not Valid"; private void OnEnable() { - BaseComponent = (Game)target; + Comp = (Game)target; } public override void OnInspectorGUI() { base.OnInspectorGUI(); EditorGUILayout.Space(); - if (BaseComponent != null) + if (Comp != null) { + EditorGUILayout.LabelField($"{WorldName} | {BridgeName} | {ConfigName}"); EditorGUILayout.LabelField($"GameStat: {Game.State}"); - EditorGUILayout.LabelField($"{GetWorld()} | {GetBrgidge()} | {GetConfig()}"); EditorGUILayout.Space(0.5f); - IInspectorInfo[] Info = BaseComponent.GetAllInfo(); - //string[] Managers = BaseComponent.gameObject.GetComponents().Select(c => c.GetManagerClass().name).ToArray(); - //string[] WorldManagers = Game.World ? Game.World.gameObject.GetComponents().Select(c => c.GetManagerClass().name).ToArray() : new string[0]; + + EditorGUILayout.LabelField($"----------------------------"); + IInspectorInfo[] Info = Comp.GetAllInfo(); for (int i = 0; i < Info.Length; i++) { - EditorGUILayout.LabelField($"{i + 1}.{Info[i].GetType().Name}-> {Info[i].GetInfo()}"); + EditorGUILayout.LabelField($"{i + 1}.{Info[i].GetType().Name}-> {Info[i].GetInfo()}"); } } } - private string GetWorld() - { - return Game.World != null ? Game.World.GetType().Name : "World Not Valid"; - } - private string GetBrgidge() - { - return Game.Bridge != null ? Game.Bridge.GetType().Name : "GameBridge Not Valid"; - } - private string GetConfig() - { - return Game.Config != null ? Game.Config.GetType().Name : "GameConfig Not Valid"; - } } diff --git a/Runtime/Core/Architecture/Game.cs b/Runtime/Core/Architecture/Game.cs index 2f964bd..b8a91b5 100644 --- a/Runtime/Core/Architecture/Game.cs +++ b/Runtime/Core/Architecture/Game.cs @@ -1065,9 +1065,19 @@ private void FixedUpdate() /// Array of service type names. public override IInspectorInfo[] GetAllInfo() { - var baseInfo = base.GetAllInfo(); + List Result = new List(); + foreach (var item in base.GetAllInfo()) + { + Result.Add(item); + } + Result.Add(Bridge); + Result.Add(Config); var servicesInfo = GameServices != null ? GameServices.OfType().ToArray() : Array.Empty(); - return baseInfo.Concat(servicesInfo).ToArray(); + foreach (var item in servicesInfo) + { + Result.Add(item); + } + return Result.ToArray(); } #endif diff --git a/Runtime/Core/Architecture/GameBridge.cs b/Runtime/Core/Architecture/GameBridge.cs index 66ef043..abd704d 100644 --- a/Runtime/Core/Architecture/GameBridge.cs +++ b/Runtime/Core/Architecture/GameBridge.cs @@ -561,8 +561,11 @@ private IEnumerator LoadWorldAsync(WorldAsset WS) // Implement IInspectorInfo Interface string IInspectorInfo.GetInfo() { - //GetType().ToString() + ": " - return $"IsLoading:{isLoading} - FadeTime:{FadeTime}"; + return $"IsLoading ({isLoading}) , FadeTime ({FadeTime}) , {GetInspectorInfo()}"; + } + protected virtual string GetInspectorInfo() + { + return null; } #endif diff --git a/Runtime/Core/Architecture/GameConfig.cs b/Runtime/Core/Architecture/GameConfig.cs index 3ec9fe0..33716b4 100644 --- a/Runtime/Core/Architecture/GameConfig.cs +++ b/Runtime/Core/Architecture/GameConfig.cs @@ -3,7 +3,17 @@ namespace RealMethod /// /// Base configuration asset for game-wide settings and initialization logic. /// - public abstract class GameConfig : ConfigAsset + public abstract class GameConfig : ConfigAsset, IInspectorInfo { +#if UNITY_EDITOR + string IInspectorInfo.GetInfo() + { + return GetInspectorInfo(); + } + protected virtual string GetInspectorInfo() + { + return null; + } +#endif } } \ No newline at end of file diff --git a/Runtime/Core/Definitions/Method_Extension.cs b/Runtime/Core/Definitions/Extensions.cs similarity index 86% rename from Runtime/Core/Definitions/Method_Extension.cs rename to Runtime/Core/Definitions/Extensions.cs index 04dbb47..6f457ab 100644 --- a/Runtime/Core/Definitions/Method_Extension.cs +++ b/Runtime/Core/Definitions/Extensions.cs @@ -1,6 +1,6 @@ namespace RealMethod { - public static class Method_Extension + public static class Extensions { public static bool IsGameScope(this Scope target) { diff --git a/Runtime/Core/Definitions/Method_Extension.cs.meta b/Runtime/Core/Definitions/Extensions.cs.meta similarity index 100% rename from Runtime/Core/Definitions/Method_Extension.cs.meta rename to Runtime/Core/Definitions/Extensions.cs.meta diff --git a/Runtime/Core/Definitions/BackgroundService.cs b/Runtime/Core/Definitions/Systems.cs similarity index 100% rename from Runtime/Core/Definitions/BackgroundService.cs rename to Runtime/Core/Definitions/Systems.cs diff --git a/Runtime/Core/Definitions/BackgroundService.cs.meta b/Runtime/Core/Definitions/Systems.cs.meta similarity index 100% rename from Runtime/Core/Definitions/BackgroundService.cs.meta rename to Runtime/Core/Definitions/Systems.cs.meta diff --git a/Runtime/Core/AAA.meta b/Runtime/Core/Framework.meta similarity index 100% rename from Runtime/Core/AAA.meta rename to Runtime/Core/Framework.meta diff --git a/Runtime/Core/AAA/Kernel.cs b/Runtime/Core/Framework/Kernel.cs similarity index 100% rename from Runtime/Core/AAA/Kernel.cs rename to Runtime/Core/Framework/Kernel.cs diff --git a/Runtime/Core/AAA/Kernel.cs.meta b/Runtime/Core/Framework/Kernel.cs.meta similarity index 100% rename from Runtime/Core/AAA/Kernel.cs.meta rename to Runtime/Core/Framework/Kernel.cs.meta diff --git a/Runtime/Core/AAA/Scope.cs b/Runtime/Core/Framework/Scope.cs similarity index 100% rename from Runtime/Core/AAA/Scope.cs rename to Runtime/Core/Framework/Scope.cs diff --git a/Runtime/Core/AAA/Scope.cs.meta b/Runtime/Core/Framework/Scope.cs.meta similarity index 100% rename from Runtime/Core/AAA/Scope.cs.meta rename to Runtime/Core/Framework/Scope.cs.meta diff --git a/Runtime/Core/AAA/ServiceLocator.cs b/Runtime/Core/Framework/ServiceLocator.cs similarity index 98% rename from Runtime/Core/AAA/ServiceLocator.cs rename to Runtime/Core/Framework/ServiceLocator.cs index 3a724ab..b7e15bf 100644 --- a/Runtime/Core/AAA/ServiceLocator.cs +++ b/Runtime/Core/Framework/ServiceLocator.cs @@ -15,16 +15,6 @@ public sealed class ServiceLocator : IInspectorInfo public int Count => _services.Count; private readonly object _lock = new(); - - - // Implement IInspectorInfo Interface - string IInspectorInfo.GetInfo() - { - return $"Regitereis({_services.Count})"; - } - - - /// /// Register a service instance under its concrete or interface type T. /// T must implement IService so we know this is a service. @@ -200,5 +190,16 @@ public void ClearAll() } } + + + +#if UNITY_EDITOR + // Implement IInspectorInfo Interface + string IInspectorInfo.GetInfo() + { + return $"Registered ({_services.Count})"; + } +#endif + } } diff --git a/Runtime/Core/AAA/ServiceLocator.cs.meta b/Runtime/Core/Framework/ServiceLocator.cs.meta similarity index 100% rename from Runtime/Core/AAA/ServiceLocator.cs.meta rename to Runtime/Core/Framework/ServiceLocator.cs.meta diff --git a/Runtime/ReadySet/Services/DebugService.cs b/Runtime/ReadySet/Services/DebugService.cs index 824d887..87b6b0c 100644 --- a/Runtime/ReadySet/Services/DebugService.cs +++ b/Runtime/ReadySet/Services/DebugService.cs @@ -190,7 +190,7 @@ private void RemoveLog(LogLine line) #if UNITY_EDITOR protected override string GetInspectorInfo() { - return $"Lines({Lines.Count})"; + return $"Lines ({Lines.Count})"; } #endif diff --git a/Runtime/ReadySet/Services/Despawn.cs b/Runtime/ReadySet/Services/Despawn.cs index 153a528..3ca2ec2 100644 --- a/Runtime/ReadySet/Services/Despawn.cs +++ b/Runtime/ReadySet/Services/Despawn.cs @@ -69,7 +69,7 @@ void System.IDisposable.Dispose() // Implement IInspectorInfo Interface string IInspectorInfo.GetInfo() { - return $"Managers({Managers.Count})"; + return $"Managers ({Managers.Count})"; } #endif diff --git a/Runtime/ReadySet/Services/Spawan.cs b/Runtime/ReadySet/Services/Spawan.cs index a5643e1..8d89b02 100644 --- a/Runtime/ReadySet/Services/Spawan.cs +++ b/Runtime/ReadySet/Services/Spawan.cs @@ -71,7 +71,7 @@ void System.IDisposable.Dispose() // Implement IInspectorInfo Interface string IInspectorInfo.GetInfo() { - return $"Managers({Managers.Count})"; + return $"Managers ({Managers.Count})"; } #endif diff --git a/Runtime/ReadySet/Services/TimeService.cs b/Runtime/ReadySet/Services/TimeService.cs index 5162ce9..b6b0d7b 100644 --- a/Runtime/ReadySet/Services/TimeService.cs +++ b/Runtime/ReadySet/Services/TimeService.cs @@ -26,7 +26,7 @@ protected override void OnEnd() #if UNITY_EDITOR protected override string GetInspectorInfo() { - return $"Record({RecordTime.Count})"; + return $"Record ({RecordTime.Count})"; } #endif From 1af60da211a1748fb343a3adf704a223c7169862 Mon Sep 17 00:00:00 2001 From: Alijimpa Date: Mon, 4 May 2026 00:14:39 +0330 Subject: [PATCH 182/204] Implement Auto Interface Called --- Runtime/Core/Framework/ServiceLocator.cs | 50 +++++++++++++++++++++--- 1 file changed, 45 insertions(+), 5 deletions(-) diff --git a/Runtime/Core/Framework/ServiceLocator.cs b/Runtime/Core/Framework/ServiceLocator.cs index b7e15bf..c13c1d3 100644 --- a/Runtime/Core/Framework/ServiceLocator.cs +++ b/Runtime/Core/Framework/ServiceLocator.cs @@ -4,6 +4,23 @@ namespace RealMethod { + /// + /// Defines the contract for a service that can respond to lifecycle events. + /// + public interface IRegistrable + { + /// + /// Called when the service is created. + /// + /// The object responsible for creating the service. + void OnRegister(); + /// + /// Called when the service is deleted or destroyed. + /// + /// The object responsible for deleting the service. + void OnUnregister(); + } + /// /// Global service locator with automatic garbage collection safety. /// Stores services by interface type using WeakReferences. @@ -56,12 +73,16 @@ public void Register(object service, Type type = null, bool overwrite = false) if (!weak.TryGetTarget(out _)) { _services[serviceType] = new WeakReference(service); + if (service is IRegistrable provider1) + provider1.OnRegister(); return; } if (overwrite) { _services[serviceType] = new WeakReference(service); + if (service is IRegistrable provider2) + provider2.OnRegister(); return; } @@ -70,6 +91,8 @@ public void Register(object service, Type type = null, bool overwrite = false) } _services[serviceType] = new WeakReference(service); + if (service is IRegistrable provider3) + provider3.OnRegister(); } } /// @@ -89,6 +112,8 @@ public void RegisterIfAbsent(T service) !weak.TryGetTarget(out _)) { _services[type] = new WeakReference(service); + if (service is IRegistrable provider) + provider.OnRegister(); } } } @@ -157,12 +182,12 @@ public bool Exists() where T : class /// /// Manually unregisters (removes) a service type. /// - public void Unregister() where T : class + public bool Unregister() where T : class { var type = typeof(T); lock (_lock) { - _services.Remove(type); + return Unregister(type); } } /// @@ -174,10 +199,21 @@ public void Unregister() where T : class /// Use this when services are registered using generic calls such as /// Register<T>(instance). /// - public void Unregister(Type type) + public bool Unregister(Type type) { - if (_services.ContainsKey(type)) - _services.Remove(type); + lock (_lock) + { + if (_services.ContainsKey(type)) + { + if (_services[type].TryGetTarget(out object target)) + { + if (target is IRegistrable provider) + provider.OnRegister(); + } + return _services.Remove(type); + } + return false; + } } /// /// Force-clears all services from the locator. @@ -186,6 +222,10 @@ public void ClearAll() { lock (_lock) { + foreach (var item in _services) + { + Unregister(item.Key); + } _services.Clear(); } } From 6061909d8b50e7cdbd68bf7bbb324e76c6dd7521 Mon Sep 17 00:00:00 2001 From: Alijimpa Date: Mon, 4 May 2026 16:54:36 +0330 Subject: [PATCH 183/204] Implement DependencyInjection & Attribute --- Runtime/Core/Architecture/Game.cs | 25 +-- Runtime/Core/Architecture/World.cs | 1 - Runtime/Core/Attributes/InjectAttribute.cs | 14 ++ .../Core/Attributes/InjectAttribute.cs.meta | 2 + Runtime/Core/Framework/GameModule.cs | 36 +++++ Runtime/Core/Framework/GameModule.cs.meta | 2 + Runtime/Core/Framework/Kernel.cs | 12 +- Runtime/Core/Framework/Modules.meta | 8 + .../Framework/Modules/DependencyInjection.cs | 150 ++++++++++++++++++ .../Modules/DependencyInjection.cs.meta | 2 + .../Framework/{ => Modules}/ServiceLocator.cs | 30 +--- .../{ => Modules}/ServiceLocator.cs.meta | 0 Runtime/Core/Framework/Scope.cs | 4 +- 13 files changed, 243 insertions(+), 43 deletions(-) create mode 100644 Runtime/Core/Attributes/InjectAttribute.cs create mode 100644 Runtime/Core/Attributes/InjectAttribute.cs.meta create mode 100644 Runtime/Core/Framework/GameModule.cs create mode 100644 Runtime/Core/Framework/GameModule.cs.meta create mode 100644 Runtime/Core/Framework/Modules.meta create mode 100644 Runtime/Core/Framework/Modules/DependencyInjection.cs create mode 100644 Runtime/Core/Framework/Modules/DependencyInjection.cs.meta rename Runtime/Core/Framework/{ => Modules}/ServiceLocator.cs (88%) rename Runtime/Core/Framework/{ => Modules}/ServiceLocator.cs.meta (100%) diff --git a/Runtime/Core/Architecture/Game.cs b/Runtime/Core/Architecture/Game.cs index b8a91b5..853ee51 100644 --- a/Runtime/Core/Architecture/Game.cs +++ b/Runtime/Core/Architecture/Game.cs @@ -106,7 +106,7 @@ public static bool IsPaused /// Returns true if the Game system has one or more registered services; /// otherwise, returns false. /// - public static bool HasService => Instance.GameServices.Count > 0; + public static bool HasService => Instance.myServicObjects.Count > 0; /// /// Event invoked when a scene or world starts or finishes loading. /// The boolean parameter is true when loading starts and false when loading ends. @@ -175,7 +175,7 @@ public ISaveSystem SaveSystem /// /// List of runtime-registered instances owned by the game. /// - private readonly List GameServices = new List(); + private readonly List myServicObjects = new List(); @@ -372,6 +372,7 @@ public static T CastWorld() where T : class return null; } } + /// /// Adds a new service of type to the game if one does not already exist. /// Newly created service will be bound to managers and notified to the global service system. @@ -387,7 +388,7 @@ public static T CastWorld() where T : class return null; } - if (Registry.Exists()) + if (Services.Exists()) { Debug.LogWarning($"Service of type {typeof(T)} is already added and still alive."); return null; @@ -395,8 +396,8 @@ public static T CastWorld() where T : class // Create Service T newService = new T(); - Registry.Register(newService); - Instance.GameServices.Add(newService); + Services.Register(newService); + Instance.myServicObjects.Add(newService); return newService; } /// @@ -407,11 +408,11 @@ public static T CastWorld() where T : class /// true if a service was found and removed; otherwise false. public static bool RemoveService() where T : Service { - Service targetService = Instance.GameServices.FirstOrDefault(s => s.GetType() == typeof(T)); + Service targetService = Instance.myServicObjects.FirstOrDefault(s => s.GetType() == typeof(T)); if (targetService != null) { - Instance.GameServices.Remove(targetService); - Registry.Unregister(); + Instance.myServicObjects.Remove(targetService); + Services.Unregister(); ((IDisposable)targetService).Dispose(); targetService = null; return true; @@ -426,7 +427,7 @@ public static bool RemoveService() where T : Service /// The service instance of type , or null if not found. public static T GetService() where T : Service { - return Registry.Get(); + return Services.Get(); } /// /// Attempts to find a service of type . @@ -436,14 +437,14 @@ public static T GetService() where T : Service /// true if the service was found; otherwise false. public static bool TryGetService(out T service) where T : Service { - return Registry.TryGet(out service); + return Services.TryGet(out service); } /// /// Clear all services in Game /// public static void ClearService() { - Registry.ClearAll(); + Services.ClearAll(); } /// /// Requests a scene load by build index . @@ -1072,7 +1073,7 @@ public override IInspectorInfo[] GetAllInfo() } Result.Add(Bridge); Result.Add(Config); - var servicesInfo = GameServices != null ? GameServices.OfType().ToArray() : Array.Empty(); + var servicesInfo = myServicObjects != null ? myServicObjects.OfType().ToArray() : Array.Empty(); foreach (var item in servicesInfo) { Result.Add(item); diff --git a/Runtime/Core/Architecture/World.cs b/Runtime/Core/Architecture/World.cs index 1f94f65..cf08c4e 100644 --- a/Runtime/Core/Architecture/World.cs +++ b/Runtime/Core/Architecture/World.cs @@ -1,4 +1,3 @@ -using System.Collections.Generic; using UnityEngine; namespace RealMethod diff --git a/Runtime/Core/Attributes/InjectAttribute.cs b/Runtime/Core/Attributes/InjectAttribute.cs new file mode 100644 index 0000000..3b1f909 --- /dev/null +++ b/Runtime/Core/Attributes/InjectAttribute.cs @@ -0,0 +1,14 @@ +namespace RealMethod +{ + using System; + + [AttributeUsage( + AttributeTargets.Field | + AttributeTargets.Property | + AttributeTargets.Method | + AttributeTargets.Constructor)] + public sealed class InjectAttribute : Attribute + { + } + +} \ No newline at end of file diff --git a/Runtime/Core/Attributes/InjectAttribute.cs.meta b/Runtime/Core/Attributes/InjectAttribute.cs.meta new file mode 100644 index 0000000..11c4873 --- /dev/null +++ b/Runtime/Core/Attributes/InjectAttribute.cs.meta @@ -0,0 +1,2 @@ +fileFormatVersion: 2 +guid: 60e011c06b2fa0642a6b6c0dcc2a74f0 \ No newline at end of file diff --git a/Runtime/Core/Framework/GameModule.cs b/Runtime/Core/Framework/GameModule.cs new file mode 100644 index 0000000..4af538f --- /dev/null +++ b/Runtime/Core/Framework/GameModule.cs @@ -0,0 +1,36 @@ +using System; +using System.Collections.Generic; + +namespace RealMethod +{ + /// + /// Defines the contract for a service that can respond to lifecycle events. + /// + public interface IRegistrable + { + /// + /// Called when the service is created. + /// + /// The object responsible for creating the service. + void OnRegister(); + /// + /// Called when the service is deleted or destroyed. + /// + /// The object responsible for deleting the service. + void OnUnregister(); + } + + + public abstract class GameModule : IInspectorInfo + { + protected static readonly Dictionary> Repository = new(); + +#if UNITY_EDITOR + string IInspectorInfo.GetInfo() + { + return GetInspectorInfor(); + } + protected abstract string GetInspectorInfor(); +#endif + } +} \ No newline at end of file diff --git a/Runtime/Core/Framework/GameModule.cs.meta b/Runtime/Core/Framework/GameModule.cs.meta new file mode 100644 index 0000000..841caea --- /dev/null +++ b/Runtime/Core/Framework/GameModule.cs.meta @@ -0,0 +1,2 @@ +fileFormatVersion: 2 +guid: e7b025512bcd3a8469548a82c5c07fc1 \ No newline at end of file diff --git a/Runtime/Core/Framework/Kernel.cs b/Runtime/Core/Framework/Kernel.cs index 315c22e..b9f11c1 100644 --- a/Runtime/Core/Framework/Kernel.cs +++ b/Runtime/Core/Framework/Kernel.cs @@ -22,13 +22,21 @@ namespace RealMethod /// public abstract class Kernel : MonoBehaviour { - protected static ServiceLocator Registry => _serviceLocator.Value; private static Lazy _serviceLocator = new Lazy(() => new ServiceLocator()); + private static Lazy _dependencyInjection = new Lazy(() => new DependencyInjection()); + + + // GameModules + protected static ServiceLocator Services => _serviceLocator.Value; + protected static DependencyInjection DInjection => _dependencyInjection.Value; + + + #if UNITY_EDITOR public virtual IInspectorInfo[] GetAllInfo() { - return new IInspectorInfo[1] { Registry }; + return new IInspectorInfo[2] { Services, DInjection }; } #endif } diff --git a/Runtime/Core/Framework/Modules.meta b/Runtime/Core/Framework/Modules.meta new file mode 100644 index 0000000..3904b1d --- /dev/null +++ b/Runtime/Core/Framework/Modules.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 15362fcc122cff641955c9545d9da9f5 +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Runtime/Core/Framework/Modules/DependencyInjection.cs b/Runtime/Core/Framework/Modules/DependencyInjection.cs new file mode 100644 index 0000000..a7c9162 --- /dev/null +++ b/Runtime/Core/Framework/Modules/DependencyInjection.cs @@ -0,0 +1,150 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Reflection; + +namespace RealMethod +{ + public sealed class DependencyInjection : GameModule + { + private readonly object _lock = new(); + private Dictionary> bindings => Repository; + + /// + /// Registers the specified instance as a dependency in the DI container. + /// After registration, any object resolving or being injected + /// with the same type will receive this instance. + /// + public void Bind(TInterface instance) + { + lock (_lock) + { + bindings[typeof(TInterface)] = new WeakReference(instance); + if (instance is IRegistrable provider) + provider.OnRegister(); + } + } + + /// + /// Resolves a dependency of the specified type. + /// Automatically constructs non-MonoBehaviour classes using constructor injection. + /// + public static T Resolve() + { + return (T)Resolve(typeof(T)); + } + + public static object Resolve(Type type) + { + // If already registered, return directly + // if (bindings.TryGetValue(type, out var existing)) + // return existing; + + // Handle constructor injection + var ctor = GetInjectableConstructor(type); + if (ctor != null) + { + var parameters = ctor.GetParameters(); + var args = parameters.Select(p => Resolve(p.ParameterType)).ToArray(); + var instance = Activator.CreateInstance(type, args); + + // Optionally inject remaining [Inject] fields + Inject(instance); + + return instance; + } + + // Fallback for parameterless types + var parameterless = type.GetConstructor(Type.EmptyTypes); + if (parameterless != null) + { + var instance = Activator.CreateInstance(type); + Inject(instance); + return instance; + } + + throw new InvalidOperationException($"Cannot resolve type {type.Name}: no registered instance or injectable constructor."); + } + + private static ConstructorInfo GetInjectableConstructor(Type type) + { + // Check if any constructor has [Inject] + var markedCtor = type.GetConstructors() + .FirstOrDefault(c => Attribute.IsDefined(c, typeof(InjectAttribute))); + if (markedCtor != null) + return markedCtor; + + // Otherwise, pick the one with most parameters for best DI heuristics + return type.GetConstructors() + .OrderByDescending(c => c.GetParameters().Length) + .FirstOrDefault(); + } + + /// + /// Injects all fields, properties, and methods marked with [Inject]. + /// Works for MonoBehaviours, ScriptableObjects, and normal classes. + /// + public static void Inject(object target) + { + var type = target.GetType(); + + // Fields + foreach (var field in type.GetFields(BindingFlags.Instance | BindingFlags.NonPublic | BindingFlags.Public)) + { + if (Attribute.IsDefined(field, typeof(InjectAttribute))) + { + var dependency = Resolve(field.FieldType); + field.SetValue(target, dependency); + } + } + + // Properties + foreach (var prop in type.GetProperties(BindingFlags.Instance | BindingFlags.NonPublic | BindingFlags.Public)) + { + if (Attribute.IsDefined(prop, typeof(InjectAttribute)) && prop.CanWrite) + { + var dependency = Resolve(prop.PropertyType); + prop.SetValue(target, dependency); + } + } + + // Methods + foreach (var method in type.GetMethods(BindingFlags.Instance | BindingFlags.NonPublic | BindingFlags.Public)) + { + if (Attribute.IsDefined(method, typeof(InjectAttribute))) + { + var parameters = method.GetParameters(); + var args = parameters.Select(p => Resolve(p.ParameterType)).ToArray(); + method.Invoke(target, args); + } + } + } + + + + + public TInterface Resolve2() + { + lock (_lock) + { + Type type = typeof(TInterface); + if (bindings.ContainsKey(type)) + { + if (bindings[type].TryGetTarget(out object target)) + { + return (TInterface)target; + } + bindings.Remove(type); + } + return default; + } + } + +#if UNITY_EDITOR + protected override string GetInspectorInfor() + { + return $"Repository ({bindings.Count})"; + } +#endif + } +} \ No newline at end of file diff --git a/Runtime/Core/Framework/Modules/DependencyInjection.cs.meta b/Runtime/Core/Framework/Modules/DependencyInjection.cs.meta new file mode 100644 index 0000000..3fea0e7 --- /dev/null +++ b/Runtime/Core/Framework/Modules/DependencyInjection.cs.meta @@ -0,0 +1,2 @@ +fileFormatVersion: 2 +guid: e6fc0ab6e758e49468a4513618244863 \ No newline at end of file diff --git a/Runtime/Core/Framework/ServiceLocator.cs b/Runtime/Core/Framework/Modules/ServiceLocator.cs similarity index 88% rename from Runtime/Core/Framework/ServiceLocator.cs rename to Runtime/Core/Framework/Modules/ServiceLocator.cs index c13c1d3..871ba59 100644 --- a/Runtime/Core/Framework/ServiceLocator.cs +++ b/Runtime/Core/Framework/Modules/ServiceLocator.cs @@ -3,34 +3,15 @@ namespace RealMethod { - - /// - /// Defines the contract for a service that can respond to lifecycle events. - /// - public interface IRegistrable - { - /// - /// Called when the service is created. - /// - /// The object responsible for creating the service. - void OnRegister(); - /// - /// Called when the service is deleted or destroyed. - /// - /// The object responsible for deleting the service. - void OnUnregister(); - } - /// /// Global service locator with automatic garbage collection safety. /// Stores services by interface type using WeakReferences. /// Thread‑safe for Register / Get / Remove operations. /// - public sealed class ServiceLocator : IInspectorInfo + public sealed class ServiceLocator : GameModule { - private readonly Dictionary> _services = new(); - public int Count => _services.Count; private readonly object _lock = new(); + private Dictionary> _services => Repository; /// /// Register a service instance under its concrete or interface type T. @@ -231,13 +212,10 @@ public void ClearAll() } - - #if UNITY_EDITOR - // Implement IInspectorInfo Interface - string IInspectorInfo.GetInfo() + protected override string GetInspectorInfor() { - return $"Registered ({_services.Count})"; + return $"Repository ({_services.Count})"; } #endif diff --git a/Runtime/Core/Framework/ServiceLocator.cs.meta b/Runtime/Core/Framework/Modules/ServiceLocator.cs.meta similarity index 100% rename from Runtime/Core/Framework/ServiceLocator.cs.meta rename to Runtime/Core/Framework/Modules/ServiceLocator.cs.meta diff --git a/Runtime/Core/Framework/Scope.cs b/Runtime/Core/Framework/Scope.cs index eb4775c..97e8049 100644 --- a/Runtime/Core/Framework/Scope.cs +++ b/Runtime/Core/Framework/Scope.cs @@ -33,7 +33,7 @@ public abstract class Scope : Kernel /// public bool TryFindManager(out T result) where T : Component, IGameManager { - return Registry.TryGet(out result); + return Services.TryGet(out result); } /// /// Collects all components from the provided GameObjects, @@ -67,7 +67,7 @@ protected void CollectManagers(GameObject[] Objects) foreach (var manager in found) { Component comp = manager.Component; - Registry.Register(comp, comp.GetType()); + Services.Register(comp, comp.GetType(), true); manager.InitiateManager(this); } } From 56d1ac8b15792859c2bcbb87d4b601511886bcd5 Mon Sep 17 00:00:00 2001 From: Alijimpa Date: Mon, 4 May 2026 16:57:42 +0330 Subject: [PATCH 184/204] Rename Service Class --- Editor/Core/InitializeOnLoad/Rules/ServiceRule.cs | 2 +- Runtime/Core/Architecture/Game.cs | 14 +++++++------- Runtime/Core/Architecture/GameBridge.cs | 2 +- .../Architecture/{Service.cs => GameService.cs} | 8 ++++++-- .../{Service.cs.meta => GameService.cs.meta} | 0 Runtime/Pattern/Services/InputService.cs | 2 +- Runtime/Pattern/Services/RuleService.cs | 2 +- Runtime/Pattern/Services/StateService.cs | 2 +- Runtime/ReadySet/Services/DebugService.cs | 2 +- Runtime/ReadySet/Services/NetworkService.cs | 2 +- Runtime/ReadySet/Services/TimeService.cs | 2 +- 11 files changed, 21 insertions(+), 17 deletions(-) rename Runtime/Core/Architecture/{Service.cs => GameService.cs} (82%) rename Runtime/Core/Architecture/{Service.cs.meta => GameService.cs.meta} (100%) diff --git a/Editor/Core/InitializeOnLoad/Rules/ServiceRule.cs b/Editor/Core/InitializeOnLoad/Rules/ServiceRule.cs index 6d37b52..75fd030 100644 --- a/Editor/Core/InitializeOnLoad/Rules/ServiceRule.cs +++ b/Editor/Core/InitializeOnLoad/Rules/ServiceRule.cs @@ -18,7 +18,7 @@ public override bool CanCheck(RuleExecutionMode mode, Type type) { if (mode == RuleExecutionMode.AfterCompilation) { - return type.IsSubclassOf(typeof(Service)); + return type.IsSubclassOf(typeof(GameService)); } else { diff --git a/Runtime/Core/Architecture/Game.cs b/Runtime/Core/Architecture/Game.cs index 853ee51..40d176b 100644 --- a/Runtime/Core/Architecture/Game.cs +++ b/Runtime/Core/Architecture/Game.cs @@ -173,9 +173,9 @@ public ISaveSystem SaveSystem /// - /// List of runtime-registered instances owned by the game. + /// List of runtime-registered instances owned by the game. /// - private readonly List myServicObjects = new List(); + private readonly List myServicObjects = new List(); @@ -379,7 +379,7 @@ public static T CastWorld() where T : class /// /// Service type to add. /// The newly created service instance, or null if a service of the same type already exists. - public static T AddService() where T : Service, new() + public static T AddService() where T : GameService, new() { // Check if you game not initialized if (!IsGameInitialized) @@ -406,9 +406,9 @@ public static T CastWorld() where T : class /// /// Service type to remove. /// true if a service was found and removed; otherwise false. - public static bool RemoveService() where T : Service + public static bool RemoveService() where T : GameService { - Service targetService = Instance.myServicObjects.FirstOrDefault(s => s.GetType() == typeof(T)); + GameService targetService = Instance.myServicObjects.FirstOrDefault(s => s.GetType() == typeof(T)); if (targetService != null) { Instance.myServicObjects.Remove(targetService); @@ -425,7 +425,7 @@ public static bool RemoveService() where T : Service /// /// IService type to retrieve. /// The service instance of type , or null if not found. - public static T GetService() where T : Service + public static T GetService() where T : GameService { return Services.Get(); } @@ -435,7 +435,7 @@ public static T GetService() where T : Service /// IService type to find. /// Out parameter that receives the service if found. /// true if the service was found; otherwise false. - public static bool TryGetService(out T service) where T : Service + public static bool TryGetService(out T service) where T : GameService { return Services.TryGet(out service); } diff --git a/Runtime/Core/Architecture/GameBridge.cs b/Runtime/Core/Architecture/GameBridge.cs index abd704d..c879e17 100644 --- a/Runtime/Core/Architecture/GameBridge.cs +++ b/Runtime/Core/Architecture/GameBridge.cs @@ -80,7 +80,7 @@ public interface IBridge /// world check for single remove new version /// Load & Unload Scene reporting /// - /// Inherits from and implements + /// Inherits from and implements /// to integrate with the game's internal world and service management system. /// public abstract class GameBridge : IDisposable, IRelationBridge, ILoadScneBridge, IInspectorInfo diff --git a/Runtime/Core/Architecture/Service.cs b/Runtime/Core/Architecture/GameService.cs similarity index 82% rename from Runtime/Core/Architecture/Service.cs rename to Runtime/Core/Architecture/GameService.cs index ebae9b2..0c1b35d 100644 --- a/Runtime/Core/Architecture/Service.cs +++ b/Runtime/Core/Architecture/GameService.cs @@ -2,9 +2,13 @@ namespace RealMethod { - public abstract class Service : IBridge, IInspectorInfo, IDisposable + public interface IGameService : IBridge, IInspectorInfo, IDisposable { - public Service() + } + + public abstract class GameService : IGameService + { + public GameService() { Game.Bridge.Bind(this); OnBegin(); diff --git a/Runtime/Core/Architecture/Service.cs.meta b/Runtime/Core/Architecture/GameService.cs.meta similarity index 100% rename from Runtime/Core/Architecture/Service.cs.meta rename to Runtime/Core/Architecture/GameService.cs.meta diff --git a/Runtime/Pattern/Services/InputService.cs b/Runtime/Pattern/Services/InputService.cs index 9470fa6..2b8b669 100644 --- a/Runtime/Pattern/Services/InputService.cs +++ b/Runtime/Pattern/Services/InputService.cs @@ -3,7 +3,7 @@ namespace RealMethod { - public abstract class InputService : Service + public abstract class InputService : GameService { private InputActionAsset CurrentInputAsset; diff --git a/Runtime/Pattern/Services/RuleService.cs b/Runtime/Pattern/Services/RuleService.cs index 38262fa..f0897d4 100644 --- a/Runtime/Pattern/Services/RuleService.cs +++ b/Runtime/Pattern/Services/RuleService.cs @@ -2,7 +2,7 @@ namespace RealMethod { - public abstract class RuleService : Service + public abstract class RuleService : GameService { public Action OnAddedRule; public Action OnFinishRule; diff --git a/Runtime/Pattern/Services/StateService.cs b/Runtime/Pattern/Services/StateService.cs index 8184aa7..75f1f36 100644 --- a/Runtime/Pattern/Services/StateService.cs +++ b/Runtime/Pattern/Services/StateService.cs @@ -3,7 +3,7 @@ namespace RealMethod { - public abstract class StateService : Service + public abstract class StateService : GameService { protected byte currentState { get; private set; } protected byte previousState { get; private set; } diff --git a/Runtime/ReadySet/Services/DebugService.cs b/Runtime/ReadySet/Services/DebugService.cs index 87b6b0c..789019a 100644 --- a/Runtime/ReadySet/Services/DebugService.cs +++ b/Runtime/ReadySet/Services/DebugService.cs @@ -3,7 +3,7 @@ namespace RealMethod { - public sealed class DebugService : Service, ILogHandler + public sealed class DebugService : GameService, ILogHandler { private class LogLine : IDrawTask { diff --git a/Runtime/ReadySet/Services/NetworkService.cs b/Runtime/ReadySet/Services/NetworkService.cs index 550c7ee..5bcc744 100644 --- a/Runtime/ReadySet/Services/NetworkService.cs +++ b/Runtime/ReadySet/Services/NetworkService.cs @@ -5,7 +5,7 @@ namespace RealMethod { - public sealed class NetworkService : Service + public sealed class NetworkService : GameService { //Const Variable private const string webImage = "http://upload.wikimedia.org/wikipedia/commons/c/c5/Moraine_Lake_17092005.jpg"; diff --git a/Runtime/ReadySet/Services/TimeService.cs b/Runtime/ReadySet/Services/TimeService.cs index b6b0d7b..7fdd136 100644 --- a/Runtime/ReadySet/Services/TimeService.cs +++ b/Runtime/ReadySet/Services/TimeService.cs @@ -2,7 +2,7 @@ namespace RealMethod { - public sealed class TimeService : Service + public sealed class TimeService : GameService { private float serviceTime; private float worldTime; From 29e8af2ecc5e99a4ff09a6dc979d1b4ee0c3d7f4 Mon Sep 17 00:00:00 2001 From: Alijimpa Date: Thu, 7 May 2026 17:51:07 +0330 Subject: [PATCH 185/204] Implement Artutarture between systems and implement New naming rule --- Runtime/Core/Architecture/Game.cs | 89 +---- Runtime/Core/Architecture/GameService.cs | 14 +- Runtime/Core/Architecture/World.cs | 3 +- Runtime/Core/DefaultClass/DefultGame.cs | 2 +- Runtime/Core/Definitions/Service.cs | 6 + Runtime/Core/Definitions/Service.cs.meta | 2 + .../{GameModule.cs => GameSubsystem.cs} | 12 +- ...meModule.cs.meta => GameSubsystem.cs.meta} | 0 Runtime/Core/Framework/Kernel.cs | 17 +- .../Framework/Modules/DependencyInjection.cs | 9 +- .../Core/Framework/Modules/ServiceLocator.cs | 19 +- Runtime/Core/Framework/Scope.cs | 372 +++++++++++++++++- 12 files changed, 429 insertions(+), 116 deletions(-) create mode 100644 Runtime/Core/Definitions/Service.cs create mode 100644 Runtime/Core/Definitions/Service.cs.meta rename Runtime/Core/Framework/{GameModule.cs => GameSubsystem.cs} (80%) rename Runtime/Core/Framework/{GameModule.cs.meta => GameSubsystem.cs.meta} (100%) diff --git a/Runtime/Core/Architecture/Game.cs b/Runtime/Core/Architecture/Game.cs index 40d176b..f2b825d 100644 --- a/Runtime/Core/Architecture/Game.cs +++ b/Runtime/Core/Architecture/Game.cs @@ -288,7 +288,7 @@ private static void InitializeGame() newobj.transform.SetParent(RealObject.transform); } #endif - Instance.CollectManagers(Objects); + Instance.OpenScope(Objects); // Unload Project Setting @@ -372,79 +372,21 @@ public static T CastWorld() where T : class return null; } } - /// - /// Adds a new service of type to the game if one does not already exist. - /// Newly created service will be bound to managers and notified to the global service system. + /// Retrieves the service instance of type if available. /// - /// Service type to add. - /// The newly created service instance, or null if a service of the same type already exists. - public static T AddService() where T : GameService, new() + /// IService type to retrieve. + /// The service instance of type , or null if not found. + public static T GetService() where T : IService { - // Check if you game not initialized - if (!IsGameInitialized) - { - Debug.LogWarning($"Game doesn't initialized !"); - return null; - } - - if (Services.Exists()) + if (Services.TryGet(out T Myservice)) { - Debug.LogWarning($"Service of type {typeof(T)} is already added and still alive."); - return null; + return Myservice; } - - // Create Service - T newService = new T(); - Services.Register(newService); - Instance.myServicObjects.Add(newService); - return newService; - } - /// - /// Removes the service instance of type if present. - /// Managers and the global service system will be notified of the removal. - /// - /// Service type to remove. - /// true if a service was found and removed; otherwise false. - public static bool RemoveService() where T : GameService - { - GameService targetService = Instance.myServicObjects.FirstOrDefault(s => s.GetType() == typeof(T)); - if (targetService != null) + else { - Instance.myServicObjects.Remove(targetService); - Services.Unregister(); - ((IDisposable)targetService).Dispose(); - targetService = null; - return true; + return default; } - Debug.LogWarning($"Service of type {typeof(T).Name} not found to remove."); - return false; - } - /// - /// Retrieves the service instance of type if available. - /// - /// IService type to retrieve. - /// The service instance of type , or null if not found. - public static T GetService() where T : GameService - { - return Services.Get(); - } - /// - /// Attempts to find a service of type . - /// - /// IService type to find. - /// Out parameter that receives the service if found. - /// true if the service was found; otherwise false. - public static bool TryGetService(out T service) where T : GameService - { - return Services.TryGet(out service); - } - /// - /// Clear all services in Game - /// - public static void ClearService() - { - Services.ClearAll(); } /// /// Requests a scene load by build index . @@ -619,10 +561,10 @@ public static Coroutine ReOpenScene() /// public static T GetManager() where T : Component, IGameManager { - if (World != null && World.TryFindManager(out T worldResult)) + if (World != null && World.TryFindGameManager(out T worldResult)) return worldResult; - if (Instance.TryFindManager(out T gameResult)) + if (Instance.TryFindGameManager(out T gameResult)) return gameResult; return null; @@ -990,17 +932,18 @@ private void Notify_OnWorldInitiate(World NewWorld) private void Notify_OnGameQuit() { Application.quitting -= Notify_OnGameQuit; - ClearService(); + CloseScope(); ((IDisposable)Bridge).Dispose(); Bridge = null; +#if UNITY_EDITOR || DEVELOPMENT_BUILD + DrawTasks.Clear(); +#endif + #if UNITY_EDITOR // Debug only: force GC to verify no references remain GC.Collect(); GC.WaitForPendingFinalizers(); GC.Collect(); -#endif -#if UNITY_EDITOR || DEVELOPMENT_BUILD - DrawTasks.Clear(); #endif OnGameClosed(); } diff --git a/Runtime/Core/Architecture/GameService.cs b/Runtime/Core/Architecture/GameService.cs index 0c1b35d..9542c02 100644 --- a/Runtime/Core/Architecture/GameService.cs +++ b/Runtime/Core/Architecture/GameService.cs @@ -1,15 +1,19 @@ using System; +using UnityEngine; namespace RealMethod { - public interface IGameService : IBridge, IInspectorInfo, IDisposable - { - } - - public abstract class GameService : IGameService + public abstract class GameService : IBridge, IInspectorInfo, IDisposable { public GameService() { + // Check if you game not initialized + if (!Game.IsGameInitialized) + { + Debug.LogWarning($"Game doesn't initialized !"); + return; + } + Game.Bridge.Bind(this); OnBegin(); } diff --git a/Runtime/Core/Architecture/World.cs b/Runtime/Core/Architecture/World.cs index cf08c4e..2738fef 100644 --- a/Runtime/Core/Architecture/World.cs +++ b/Runtime/Core/Architecture/World.cs @@ -102,7 +102,7 @@ private void Awake() } // Get All Managers - CollectManagers(new GameObject[1] { gameObject }); + OpenScope(new GameObject[1] { gameObject }); // Find Player or Create newone var scneplayer = GetPlayerInScene(); @@ -160,6 +160,7 @@ private void FixedUpdate() /// private void OnDestroy() { + CloseScope(); WorldEnd(); } diff --git a/Runtime/Core/DefaultClass/DefultGame.cs b/Runtime/Core/DefaultClass/DefultGame.cs index 8b1b30b..9fb05e1 100644 --- a/Runtime/Core/DefaultClass/DefultGame.cs +++ b/Runtime/Core/DefaultClass/DefultGame.cs @@ -11,7 +11,7 @@ protected override void OnGameOpen() } protected override void OnGameInitialized() { - AddService(); + AddGameService(); Debug.Log("DefultGame Initialized"); } protected override void OnGameStart() diff --git a/Runtime/Core/Definitions/Service.cs b/Runtime/Core/Definitions/Service.cs new file mode 100644 index 0000000..2ff9ccd --- /dev/null +++ b/Runtime/Core/Definitions/Service.cs @@ -0,0 +1,6 @@ +namespace RealMethod +{ + public interface IService { + + } +} \ No newline at end of file diff --git a/Runtime/Core/Definitions/Service.cs.meta b/Runtime/Core/Definitions/Service.cs.meta new file mode 100644 index 0000000..1e4cbf1 --- /dev/null +++ b/Runtime/Core/Definitions/Service.cs.meta @@ -0,0 +1,2 @@ +fileFormatVersion: 2 +guid: 7fac47f2ec1af7c479ff9393e8298cca \ No newline at end of file diff --git a/Runtime/Core/Framework/GameModule.cs b/Runtime/Core/Framework/GameSubsystem.cs similarity index 80% rename from Runtime/Core/Framework/GameModule.cs rename to Runtime/Core/Framework/GameSubsystem.cs index 4af538f..da832a2 100644 --- a/Runtime/Core/Framework/GameModule.cs +++ b/Runtime/Core/Framework/GameSubsystem.cs @@ -20,10 +20,16 @@ public interface IRegistrable void OnUnregister(); } - - public abstract class GameModule : IInspectorInfo + + public abstract class GameSubsystem : IInspectorInfo { - protected static readonly Dictionary> Repository = new(); + protected IShareData Data { get; private set; } + + + public GameSubsystem(IShareData data) + { + Data = data; + } #if UNITY_EDITOR string IInspectorInfo.GetInfo() diff --git a/Runtime/Core/Framework/GameModule.cs.meta b/Runtime/Core/Framework/GameSubsystem.cs.meta similarity index 100% rename from Runtime/Core/Framework/GameModule.cs.meta rename to Runtime/Core/Framework/GameSubsystem.cs.meta diff --git a/Runtime/Core/Framework/Kernel.cs b/Runtime/Core/Framework/Kernel.cs index b9f11c1..3594b7d 100644 --- a/Runtime/Core/Framework/Kernel.cs +++ b/Runtime/Core/Framework/Kernel.cs @@ -1,8 +1,15 @@ using System; +using System.Collections.Generic; using UnityEngine; namespace RealMethod { + public interface IShareData + { + Dictionary> Repository { get; } + } + + /// /// The foundational runtime core of the RealMethod framework. /// Provides the minimal infrastructure required for all higher-level systems, @@ -20,19 +27,23 @@ namespace RealMethod /// Regular users normally interact only with GameScope or WorldScope, /// while RealKernel remains an internal framework component. /// - public abstract class Kernel : MonoBehaviour + public abstract class Kernel : MonoBehaviour, IShareData { - private static Lazy _serviceLocator = new Lazy(() => new ServiceLocator()); - private static Lazy _dependencyInjection = new Lazy(() => new DependencyInjection()); + private static readonly Dictionary> _rpository = new(); + private static Lazy _serviceLocator = new Lazy(() => new ServiceLocator(Game.Instance)); + private static Lazy _dependencyInjection = new Lazy(() => new DependencyInjection(Game.Instance)); // GameModules + Dictionary> IShareData.Repository => _rpository; protected static ServiceLocator Services => _serviceLocator.Value; protected static DependencyInjection DInjection => _dependencyInjection.Value; + + #if UNITY_EDITOR public virtual IInspectorInfo[] GetAllInfo() { diff --git a/Runtime/Core/Framework/Modules/DependencyInjection.cs b/Runtime/Core/Framework/Modules/DependencyInjection.cs index a7c9162..427c45d 100644 --- a/Runtime/Core/Framework/Modules/DependencyInjection.cs +++ b/Runtime/Core/Framework/Modules/DependencyInjection.cs @@ -5,10 +5,15 @@ namespace RealMethod { - public sealed class DependencyInjection : GameModule + public sealed class DependencyInjection : GameSubsystem { private readonly object _lock = new(); - private Dictionary> bindings => Repository; + private Dictionary> bindings => Data.Repository; + + public DependencyInjection(IShareData data) : base(data) + { + } + /// /// Registers the specified instance as a dependency in the DI container. diff --git a/Runtime/Core/Framework/Modules/ServiceLocator.cs b/Runtime/Core/Framework/Modules/ServiceLocator.cs index 871ba59..dd40b2b 100644 --- a/Runtime/Core/Framework/Modules/ServiceLocator.cs +++ b/Runtime/Core/Framework/Modules/ServiceLocator.cs @@ -8,10 +8,14 @@ namespace RealMethod /// Stores services by interface type using WeakReferences. /// Thread‑safe for Register / Get / Remove operations. /// - public sealed class ServiceLocator : GameModule + public sealed class ServiceLocator : GameSubsystem { private readonly object _lock = new(); - private Dictionary> _services => Repository; + private Dictionary> _services => Data.Repository; + + public ServiceLocator(IShareData data) : base(data) + { + } /// /// Register a service instance under its concrete or interface type T. @@ -125,7 +129,7 @@ public T Get() where T : class /// /// Try to get the registered instance for type T. /// - public bool TryGet(out T result) where T : class + public bool TryGet(out T result) { var type = typeof(T); @@ -135,17 +139,18 @@ public bool TryGet(out T result) where T : class { if (weak.TryGetTarget(out var obj) && obj != null) { - result = obj as T; + result = (T)obj; return result != null; } // Weak reference dead → remove entry _services.Remove(type); } - } - result = null; - return false; + + result = default; + return false; + } } /// /// Check whether a live instance exists for type T. diff --git a/Runtime/Core/Framework/Scope.cs b/Runtime/Core/Framework/Scope.cs index 97e8049..171969b 100644 --- a/Runtime/Core/Framework/Scope.cs +++ b/Runtime/Core/Framework/Scope.cs @@ -1,3 +1,5 @@ +using System; +using System.Collections.Generic; using UnityEngine; namespace RealMethod @@ -20,6 +22,18 @@ namespace RealMethod /// public abstract class Scope : Kernel { + public bool IsScopeOpened { get; private set; } = false; + /// + /// Cached array of managers that were instantiated from configured game prefabs or World gameobject. + /// + private IGameManager[] _gameManagers; + /// + /// Cached list of modules that were instantiated from scope functions (add / remove). + /// + private List _gameServices; + + + /// /// Attempts to find a manager whose Component matches the specified type . /// @@ -31,47 +45,363 @@ public abstract class Scope : Kernel /// /// true if a matching manager component was found; otherwise false. /// - public bool TryFindManager(out T result) where T : Component, IGameManager + public bool TryFindGameManager(out T result) where T : Component, IGameManager + { + result = null; + + if (IsScopeLive()) + return false; + + if (_gameManagers == null) + { + return false; + } + + foreach (var manager in _gameManagers) + { + if (manager == null) + { + Debug.LogError($"A manager reference({typeof(T)}) has been removed or destroyed. Managers should never be null."); + return false; + } + if (manager.Component is T found) + { + result = found; + return true; + } + } + return false; + } + /// + /// Attempts to locate an existing game service of type within the current scope. + /// If the scope is not active, or the service list is unavailable, the method returns false. + /// Null service entries produce an error log, as game services are expected to remain valid, + /// and the search is aborted. + /// + /// + /// The type of game service to search for. Must inherit from . + /// + /// + /// When the method returns, contains the found service instance if a match is discovered; otherwise null. + /// + /// + /// True if a service of type is found; otherwise false. + /// + public bool TryFindGameService(out T result) where T : GameService + { + result = null; + + if (IsScopeLive()) + return false; + + if (_gameServices == null) + { + return false; + } + + foreach (var service in _gameServices) + { + if (service == null) + { + Debug.LogError($"A GameService reference({typeof(T)}) has been removed or destroyed. GameService should never be null."); + return false; + } + if (service is T targetclass) + { + result = targetclass; + return true; + } + } + return false; + } + /// + /// Creates, stores, and registers a new service of type . + /// If a service of the same type already exists, the method logs a warning and returns null. + /// The created service must implement to be registered and returned. + /// All implemented interfaces derived from are registered + /// in the service container, except the base interface itself. + /// + /// + /// The type of service to create and add. Must inherit from + /// and provide a parameterless constructor. + /// + /// + /// The created service as if successful; otherwise null. + /// + public IService AddGameService() where T : GameService, new() + { + if (IsExistsModule()) + { + Debug.LogWarning($"Service of type {typeof(T)} is already added and still alive."); + return null; + } + + // Create Service + T newService = new T(); + _gameServices.Add(newService); + + if (newService is IService provider) + { + var interfaces = newService.GetType().GetInterfaces(); + foreach (var i in interfaces) + { + // Skip the base Interface + if (i == typeof(IService)) + continue; + + // Only interfaces derived from Interface + if (typeof(IService).IsAssignableFrom(i)) + { + Services.Register(newService, i, false); + } + } + return provider; + } + else + { + Debug.LogWarning($"Service of type {typeof(T)} should implement one of tye {typeof(IService)} interface"); + return null; + } + } + /// + /// Removes a service of type from the scope. + /// If the service exists, it will be unregistered and disposed. + /// + /// + /// Type of the service to remove. + /// + /// + /// True if the service was successfully removed; otherwise false. + /// + public bool RemoveGameService() where T : GameService + { + if (!IsExistsModule()) + { + Debug.LogWarning($"Service of type {typeof(T)} is not exist."); + return false; + } + return RemoveGameService(typeof(T)); + } + public void ClearGameServices() { - return Services.TryGet(out result); + for (int i = 0; i < _gameServices.Count; i++) + { + var interfaces = _gameServices[i].GetType().GetInterfaces(); + foreach (var interf in interfaces) + { + // Only interfaces derived from Interface + if (typeof(IService).IsAssignableFrom(interf)) + { + Services.Unregister(interf); + } + } + ((IDisposable)_gameServices[i]).Dispose(); + _gameServices.RemoveAt(i); + } + _gameServices.Clear(); } + + + + /// - /// Collects all components from the provided GameObjects, - /// initializes them, and stores them internally. - /// - /// This method can only be executed once. If it is called again after managers - /// have already been collected, an error will be logged and the method will exit. - /// - /// Duplicate manager instances are ignored and logged as warnings. + /// Opens the scope and initializes managers and services for the provided GameObjects. + /// It collects all instances from the given objects and prepares + /// the internal service container. If the scope is already opened, the call will be ignored. /// /// - /// Array of GameObjects to search for components. - /// Null objects in the array are skipped. + /// Array of GameObjects that may contain managers to be collected and registered in this scope. /// - protected void CollectManagers(GameObject[] Objects) + protected void OpenScope(GameObject[] Objects) { + if (IsScopeOpened) + { + Debug.LogWarning($"{this} This scope it was opend befor."); + return; + } + IsScopeOpened = true; + + _gameServices = new List(10); + + if (Objects == null) { - Debug.LogError("CollectManagers received a null GameObjects array."); + Debug.LogError("OpeningScope failed: GameObject array 'Objects' is null."); return; } + + List result = new List(); for (int i = 0; i < Objects.Length; i++) { - GameObject Obj = Objects[i]; - if (Obj == null) - continue; + var Newmanager = CollectManagers(Objects[i]); + foreach (var manager in Newmanager) + { + result.Add(manager); + } + } + _gameManagers = result.ToArray(); + } + /// + /// Closes the current scope and releases all registered services and managers. + /// All services implementing are unregistered and disposed, + /// and all managers are properly dispensed. If the scope is already closed, + /// the call will be ignored. + /// + protected void CloseScope() + { + if (!IsScopeOpened) + { + Debug.LogWarning($"{this} This scope it was Closed befor."); + return; + } + IsScopeOpened = false; + + for (int i = 0; i < _gameServices.Count; i++) + { + var interfaces = _gameServices[i].GetType().GetInterfaces(); + foreach (var interf in interfaces) + { + // Only interfaces derived from Interface + if (typeof(IService).IsAssignableFrom(interf)) + { + Services.Unregister(interf); + } + } + ((IDisposable)_gameServices[i]).Dispose(); + _gameServices.RemoveAt(i); + } + _gameServices = null; + + foreach (var manager in _gameManagers) + { + DispenseManagers(manager); + } + _gameManagers = null; + + } + + + + + private bool RemoveGameService(Type type) + { + if (type == null) + return false; + + + for (int i = 0; i < _gameServices.Count; i++) + { + if (_gameServices[i].GetType() == type) + { + var interfaces = _gameServices[i].GetType().GetInterfaces(); + foreach (var interf in interfaces) + { + // Only interfaces derived from Interface + if (typeof(IService).IsAssignableFrom(interf)) + { + Services.Unregister(interf); + } + } + ((IDisposable)_gameServices[i]).Dispose(); + _gameServices.RemoveAt(i); + return true; + } + } + + Debug.LogWarning($"Service of type {type.Name} not found to remove."); + return false; + } + private IGameManager[] CollectManagers(GameObject Object) + { + if (Object == null) + { + Debug.LogWarning("CollectManagers: GameObject 'Object' is null."); + return null; + } + + var managers = Object.GetComponents(); + + foreach (var manager in managers) + { + Component comp = manager.Component; + RegisterInterface(comp); + RegisterInterface(comp); + manager.InitiateManager(this); + } + + return managers; + } + private void DispenseManagers(IGameManager manager) + { + if (manager == null) + { + Debug.LogWarning("DispenseManagers: Manager 'manager' is null."); + return; + } + Component comp = manager.Component; + UnregisterInterface(comp); + UnregisterInterface(comp); + manager.InitiateManager(this); + } + private void RegisterInterface(Component comp) + { + if (comp is T service) + { + var interfaces = comp.GetType().GetInterfaces(); - var found = Obj.GetComponents(); + foreach (var i in interfaces) + { + // Skip the base Interface + if (i == typeof(T)) + continue; + + // Only interfaces derived from Interface + if (typeof(T).IsAssignableFrom(i)) + { + Services.Register(comp, i, false); + } + } + } + } + private void UnregisterInterface(Component comp) + { + if (comp is T service) + { + var interfaces = comp.GetType().GetInterfaces(); - foreach (var manager in found) + foreach (var i in interfaces) { - Component comp = manager.Component; - Services.Register(comp, comp.GetType(), true); - manager.InitiateManager(this); + // Skip the base Interface + if (i == typeof(T)) + continue; + + // Only interfaces derived from Interface + if (typeof(T).IsAssignableFrom(i)) + { + Services.Unregister(i); + } } } } + private bool IsScopeLive() + { + if (!IsScopeOpened) + { + Debug.LogWarning($"First you shoul open Scope."); + return false; + } + return true; + } + private bool IsExistsModule() where T : GameService + { + foreach (var module in _gameServices) + { + if (module is T) + return true; + } + return false; + } } From 8ff402e7adc6350fa60930ca1adc1b14a594d7ce Mon Sep 17 00:00:00 2001 From: Alijimpa Date: Fri, 8 May 2026 15:48:45 +0330 Subject: [PATCH 186/204] Implement GameService Class From GameModuel and base strcucture in scope --- Runtime/Core/Architecture/GameService.cs | 56 ++++----- Runtime/Core/Architecture/GameService.cs.meta | 2 +- Runtime/Core/Framework/GameModule.cs | 64 ++++++++++ Runtime/Core/Framework/GameModule.cs.meta | 2 + Runtime/Core/Framework/GameSubsystem.cs | 31 ++--- Runtime/Core/Framework/Kernel.cs | 16 +-- Runtime/Core/Framework/Scope.cs | 111 +++++++----------- .../{Modules.meta => Subsystems.meta} | 0 .../DependencyInjection.cs | 2 +- .../DependencyInjection.cs.meta | 0 .../{Modules => Subsystems}/ServiceLocator.cs | 2 +- .../ServiceLocator.cs.meta | 0 12 files changed, 146 insertions(+), 140 deletions(-) create mode 100644 Runtime/Core/Framework/GameModule.cs create mode 100644 Runtime/Core/Framework/GameModule.cs.meta rename Runtime/Core/Framework/{Modules.meta => Subsystems.meta} (100%) rename Runtime/Core/Framework/{Modules => Subsystems}/DependencyInjection.cs (98%) rename Runtime/Core/Framework/{Modules => Subsystems}/DependencyInjection.cs.meta (100%) rename Runtime/Core/Framework/{Modules => Subsystems}/ServiceLocator.cs (99%) rename Runtime/Core/Framework/{Modules => Subsystems}/ServiceLocator.cs.meta (100%) diff --git a/Runtime/Core/Architecture/GameService.cs b/Runtime/Core/Architecture/GameService.cs index 9542c02..e5d464f 100644 --- a/Runtime/Core/Architecture/GameService.cs +++ b/Runtime/Core/Architecture/GameService.cs @@ -1,47 +1,31 @@ -using System; using UnityEngine; namespace RealMethod { - public abstract class GameService : IBridge, IInspectorInfo, IDisposable + /// + /// Defines a contract for services in the game architecture. + /// Extends the IIdentifier interface. + /// + public interface IService : IIdentifier { - public GameService() - { - // Check if you game not initialized - if (!Game.IsGameInitialized) - { - Debug.LogWarning($"Game doesn't initialized !"); - return; - } - - Game.Bridge.Bind(this); - OnBegin(); - } - - // Implement IBridge Interface - void IBridge.OnWorldChanged(World world) => OnWorldChanged(); - void IDisposable.Dispose() - { - Game.Bridge.Unbind(this); - OnEnd(); - } - // Abstraction Methods - protected abstract void OnBegin(); - protected abstract void OnWorldChanged(); - protected abstract void OnEnd(); + } -#if UNITY_EDITOR - string IInspectorInfo.GetInfo() - { - return GetInspectorInfo(); - } - protected virtual string GetInspectorInfo() + /// + /// Represents a service in the game architecture, extending the functionality of GameModule. + /// Ensures that all derived services implement the IService interface. + /// + public abstract class GameService : GameModule + { + /// + /// Initializes a new instance of the GameService class. + /// Validates that the derived class implements the IService interface. + /// Logs an error if the IService interface is not implemented. + /// + public GameService() : base() { - return null; + if (this is not IService) + Debug.LogError($"Service of type {GetType().Name} should implement one of tye {typeof(IService).Name} interface"); } -#endif } - - } \ No newline at end of file diff --git a/Runtime/Core/Architecture/GameService.cs.meta b/Runtime/Core/Architecture/GameService.cs.meta index 8527ce4..298e5dd 100644 --- a/Runtime/Core/Architecture/GameService.cs.meta +++ b/Runtime/Core/Architecture/GameService.cs.meta @@ -1,2 +1,2 @@ fileFormatVersion: 2 -guid: ec193cd2194f8614eb221434996c3f62 \ No newline at end of file +guid: 7252e9f27b21b194ab50679f8b4e4be2 \ No newline at end of file diff --git a/Runtime/Core/Framework/GameModule.cs b/Runtime/Core/Framework/GameModule.cs new file mode 100644 index 0000000..4bd04f3 --- /dev/null +++ b/Runtime/Core/Framework/GameModule.cs @@ -0,0 +1,64 @@ +using System; +using UnityEngine; + +namespace RealMethod +{ + /// + /// Abstract base class for game modules, providing lifecycle management and integration with the Game system. + /// A is instantiated once per module type + /// and automatically registered by Scope"/>. + /// Implements IBridge, IInspectorInfo, and IDisposable interfaces. + /// + public abstract class GameModule : IBridge, IInspectorInfo, IDisposable + { + /// + /// Initializes a new instance of the GameModule class. + /// Checks if the game is initialized and binds the module to the Game.Bridge. + /// Calls the OnBegin method for initialization. + /// + public GameModule() + { + // Check if you game not initialized + if (!Game.IsGameInitialized) + { + Debug.LogWarning($"Game doesn't initialized !"); + return; + } + Game.Bridge.Bind(this); + OnBegin(); + } + + // Implement IBridge Interface + void IBridge.OnWorldChanged(World world) => OnWorldChanged(); + void IDisposable.Dispose() + { + Game.Bridge.Unbind(this); + OnEnd(); + } + + // Abstraction Methods + protected abstract void OnBegin(); + protected abstract void OnWorldChanged(); + protected abstract void OnEnd(); + +#if UNITY_EDITOR + /// + /// Provides information for the Unity Inspector in the editor. + /// + /// A string containing inspector information. + string IInspectorInfo.GetInfo() + { + return GetInspectorInfo(); + } + /// + /// Can be overridden to provide custom information for the Unity Inspector. + /// Default implementation returns null. + /// + /// A string containing custom inspector information. + protected virtual string GetInspectorInfo() + { + return null; + } +#endif + } +} \ No newline at end of file diff --git a/Runtime/Core/Framework/GameModule.cs.meta b/Runtime/Core/Framework/GameModule.cs.meta new file mode 100644 index 0000000..8527ce4 --- /dev/null +++ b/Runtime/Core/Framework/GameModule.cs.meta @@ -0,0 +1,2 @@ +fileFormatVersion: 2 +guid: ec193cd2194f8614eb221434996c3f62 \ No newline at end of file diff --git a/Runtime/Core/Framework/GameSubsystem.cs b/Runtime/Core/Framework/GameSubsystem.cs index da832a2..e3bfdc4 100644 --- a/Runtime/Core/Framework/GameSubsystem.cs +++ b/Runtime/Core/Framework/GameSubsystem.cs @@ -3,30 +3,21 @@ namespace RealMethod { - /// - /// Defines the contract for a service that can respond to lifecycle events. - /// - public interface IRegistrable - { - /// - /// Called when the service is created. - /// - /// The object responsible for creating the service. - void OnRegister(); - /// - /// Called when the service is deleted or destroyed. - /// - /// The object responsible for deleting the service. - void OnUnregister(); - } - - public abstract class GameSubsystem : IInspectorInfo { - protected IShareData Data { get; private set; } + public class ShareData + { + public Dictionary> Repository { get; } + + public ShareData(int prewarm) + { + Repository = new Dictionary>(prewarm); + } + } + protected ShareData Data { get; private set; } - public GameSubsystem(IShareData data) + public GameSubsystem(ShareData data) { Data = data; } diff --git a/Runtime/Core/Framework/Kernel.cs b/Runtime/Core/Framework/Kernel.cs index 3594b7d..1265542 100644 --- a/Runtime/Core/Framework/Kernel.cs +++ b/Runtime/Core/Framework/Kernel.cs @@ -1,15 +1,8 @@ using System; -using System.Collections.Generic; using UnityEngine; namespace RealMethod { - public interface IShareData - { - Dictionary> Repository { get; } - } - - /// /// The foundational runtime core of the RealMethod framework. /// Provides the minimal infrastructure required for all higher-level systems, @@ -27,15 +20,14 @@ public interface IShareData /// Regular users normally interact only with GameScope or WorldScope, /// while RealKernel remains an internal framework component. /// - public abstract class Kernel : MonoBehaviour, IShareData + public abstract class Kernel : MonoBehaviour { - private static readonly Dictionary> _rpository = new(); - private static Lazy _serviceLocator = new Lazy(() => new ServiceLocator(Game.Instance)); - private static Lazy _dependencyInjection = new Lazy(() => new DependencyInjection(Game.Instance)); + private static readonly GameSubsystem.ShareData _rpository = new GameSubsystem.ShareData(10); + private static Lazy _serviceLocator = new Lazy(() => new ServiceLocator(_rpository)); + private static Lazy _dependencyInjection = new Lazy(() => new DependencyInjection(_rpository)); // GameModules - Dictionary> IShareData.Repository => _rpository; protected static ServiceLocator Services => _serviceLocator.Value; protected static DependencyInjection DInjection => _dependencyInjection.Value; diff --git a/Runtime/Core/Framework/Scope.cs b/Runtime/Core/Framework/Scope.cs index 171969b..d897c46 100644 --- a/Runtime/Core/Framework/Scope.cs +++ b/Runtime/Core/Framework/Scope.cs @@ -30,7 +30,7 @@ public abstract class Scope : Kernel /// /// Cached list of modules that were instantiated from scope functions (add / remove). /// - private List _gameServices; + private List _gameModules; @@ -79,7 +79,7 @@ public bool TryFindGameManager(out T result) where T : Component, IGameManage /// and the search is aborted. /// /// - /// The type of game service to search for. Must inherit from . + /// The type of game service to search for. Must inherit from . /// /// /// When the method returns, contains the found service instance if a match is discovered; otherwise null. @@ -87,19 +87,19 @@ public bool TryFindGameManager(out T result) where T : Component, IGameManage /// /// True if a service of type is found; otherwise false. /// - public bool TryFindGameService(out T result) where T : GameService + public bool TryFindModule(out T result) where T : GameModule { result = null; if (IsScopeLive()) return false; - if (_gameServices == null) + if (_gameModules == null) { return false; } - foreach (var service in _gameServices) + foreach (var service in _gameModules) { if (service == null) { @@ -122,13 +122,13 @@ public bool TryFindGameService(out T result) where T : GameService /// in the service container, except the base interface itself. /// /// - /// The type of service to create and add. Must inherit from + /// The type of service to create and add. Must inherit from /// and provide a parameterless constructor. /// /// /// The created service as if successful; otherwise null. /// - public IService AddGameService() where T : GameService, new() + public T AddModule() where T : GameModule, new() { if (IsExistsModule()) { @@ -138,30 +138,10 @@ public bool TryFindGameService(out T result) where T : GameService // Create Service T newService = new T(); - _gameServices.Add(newService); + _gameModules.Add(newService); + RegisterInterface(newService); - if (newService is IService provider) - { - var interfaces = newService.GetType().GetInterfaces(); - foreach (var i in interfaces) - { - // Skip the base Interface - if (i == typeof(IService)) - continue; - - // Only interfaces derived from Interface - if (typeof(IService).IsAssignableFrom(i)) - { - Services.Register(newService, i, false); - } - } - return provider; - } - else - { - Debug.LogWarning($"Service of type {typeof(T)} should implement one of tye {typeof(IService)} interface"); - return null; - } + return newService; } /// /// Removes a service of type from the scope. @@ -173,20 +153,20 @@ public bool TryFindGameService(out T result) where T : GameService /// /// True if the service was successfully removed; otherwise false. /// - public bool RemoveGameService() where T : GameService + public bool RemoveModule() where T : GameModule { if (!IsExistsModule()) { Debug.LogWarning($"Service of type {typeof(T)} is not exist."); return false; } - return RemoveGameService(typeof(T)); + return RemoveModule(typeof(T)); } - public void ClearGameServices() + public void ClearModules() { - for (int i = 0; i < _gameServices.Count; i++) + for (int i = 0; i < _gameModules.Count; i++) { - var interfaces = _gameServices[i].GetType().GetInterfaces(); + var interfaces = _gameModules[i].GetType().GetInterfaces(); foreach (var interf in interfaces) { // Only interfaces derived from Interface @@ -195,10 +175,10 @@ public void ClearGameServices() Services.Unregister(interf); } } - ((IDisposable)_gameServices[i]).Dispose(); - _gameServices.RemoveAt(i); + ((IDisposable)_gameModules[i]).Dispose(); + _gameModules.RemoveAt(i); } - _gameServices.Clear(); + _gameModules.Clear(); } @@ -221,7 +201,7 @@ protected void OpenScope(GameObject[] Objects) } IsScopeOpened = true; - _gameServices = new List(10); + _gameModules = new List(10); if (Objects == null) @@ -235,9 +215,12 @@ protected void OpenScope(GameObject[] Objects) for (int i = 0; i < Objects.Length; i++) { var Newmanager = CollectManagers(Objects[i]); - foreach (var manager in Newmanager) + if (Newmanager != null) { - result.Add(manager); + foreach (var manager in Newmanager) + { + result.Add(manager); + } } } _gameManagers = result.ToArray(); @@ -257,9 +240,9 @@ protected void CloseScope() } IsScopeOpened = false; - for (int i = 0; i < _gameServices.Count; i++) + for (int i = 0; i < _gameModules.Count; i++) { - var interfaces = _gameServices[i].GetType().GetInterfaces(); + var interfaces = _gameModules[i].GetType().GetInterfaces(); foreach (var interf in interfaces) { // Only interfaces derived from Interface @@ -268,10 +251,10 @@ protected void CloseScope() Services.Unregister(interf); } } - ((IDisposable)_gameServices[i]).Dispose(); - _gameServices.RemoveAt(i); + ((IDisposable)_gameModules[i]).Dispose(); + _gameModules.RemoveAt(i); } - _gameServices = null; + _gameModules = null; foreach (var manager in _gameManagers) { @@ -284,27 +267,19 @@ protected void CloseScope() - private bool RemoveGameService(Type type) + private bool RemoveModule(Type type) { if (type == null) return false; - for (int i = 0; i < _gameServices.Count; i++) + for (int i = 0; i < _gameModules.Count; i++) { - if (_gameServices[i].GetType() == type) + if (_gameModules[i].GetType() == type) { - var interfaces = _gameServices[i].GetType().GetInterfaces(); - foreach (var interf in interfaces) - { - // Only interfaces derived from Interface - if (typeof(IService).IsAssignableFrom(interf)) - { - Services.Unregister(interf); - } - } - ((IDisposable)_gameServices[i]).Dispose(); - _gameServices.RemoveAt(i); + UnregisterInterface(_gameModules[i]); + ((IDisposable)_gameModules[i]).Dispose(); + _gameModules.RemoveAt(i); return true; } } @@ -316,7 +291,7 @@ private IGameManager[] CollectManagers(GameObject Object) { if (Object == null) { - Debug.LogWarning("CollectManagers: GameObject 'Object' is null."); + // Debug.LogWarning("CollectManagers: GameObject 'Object' is null."); return null; } @@ -329,7 +304,6 @@ private IGameManager[] CollectManagers(GameObject Object) RegisterInterface(comp); manager.InitiateManager(this); } - return managers; } private void DispenseManagers(IGameManager manager) @@ -342,11 +316,10 @@ private void DispenseManagers(IGameManager manager) Component comp = manager.Component; UnregisterInterface(comp); UnregisterInterface(comp); - manager.InitiateManager(this); } - private void RegisterInterface(Component comp) + private void RegisterInterface(object comp) { - if (comp is T service) + if (comp is T) { var interfaces = comp.GetType().GetInterfaces(); @@ -364,9 +337,9 @@ private void RegisterInterface(Component comp) } } } - private void UnregisterInterface(Component comp) + private void UnregisterInterface(object comp) { - if (comp is T service) + if (comp is T) { var interfaces = comp.GetType().GetInterfaces(); @@ -393,9 +366,9 @@ private bool IsScopeLive() } return true; } - private bool IsExistsModule() where T : GameService + private bool IsExistsModule() where T : GameModule { - foreach (var module in _gameServices) + foreach (var module in _gameModules) { if (module is T) return true; diff --git a/Runtime/Core/Framework/Modules.meta b/Runtime/Core/Framework/Subsystems.meta similarity index 100% rename from Runtime/Core/Framework/Modules.meta rename to Runtime/Core/Framework/Subsystems.meta diff --git a/Runtime/Core/Framework/Modules/DependencyInjection.cs b/Runtime/Core/Framework/Subsystems/DependencyInjection.cs similarity index 98% rename from Runtime/Core/Framework/Modules/DependencyInjection.cs rename to Runtime/Core/Framework/Subsystems/DependencyInjection.cs index 427c45d..08a3dad 100644 --- a/Runtime/Core/Framework/Modules/DependencyInjection.cs +++ b/Runtime/Core/Framework/Subsystems/DependencyInjection.cs @@ -10,7 +10,7 @@ public sealed class DependencyInjection : GameSubsystem private readonly object _lock = new(); private Dictionary> bindings => Data.Repository; - public DependencyInjection(IShareData data) : base(data) + public DependencyInjection(ShareData data) : base(data) { } diff --git a/Runtime/Core/Framework/Modules/DependencyInjection.cs.meta b/Runtime/Core/Framework/Subsystems/DependencyInjection.cs.meta similarity index 100% rename from Runtime/Core/Framework/Modules/DependencyInjection.cs.meta rename to Runtime/Core/Framework/Subsystems/DependencyInjection.cs.meta diff --git a/Runtime/Core/Framework/Modules/ServiceLocator.cs b/Runtime/Core/Framework/Subsystems/ServiceLocator.cs similarity index 99% rename from Runtime/Core/Framework/Modules/ServiceLocator.cs rename to Runtime/Core/Framework/Subsystems/ServiceLocator.cs index dd40b2b..87c1296 100644 --- a/Runtime/Core/Framework/Modules/ServiceLocator.cs +++ b/Runtime/Core/Framework/Subsystems/ServiceLocator.cs @@ -13,7 +13,7 @@ public sealed class ServiceLocator : GameSubsystem private readonly object _lock = new(); private Dictionary> _services => Data.Repository; - public ServiceLocator(IShareData data) : base(data) + public ServiceLocator(ShareData data) : base(data) { } diff --git a/Runtime/Core/Framework/Modules/ServiceLocator.cs.meta b/Runtime/Core/Framework/Subsystems/ServiceLocator.cs.meta similarity index 100% rename from Runtime/Core/Framework/Modules/ServiceLocator.cs.meta rename to Runtime/Core/Framework/Subsystems/ServiceLocator.cs.meta From 2159955d5314160ae7d49251f51f02be1a8da38e Mon Sep 17 00:00:00 2001 From: Alijimpa Date: Fri, 8 May 2026 16:24:52 +0330 Subject: [PATCH 187/204] Implement InspectorInfo Interface for Game and core class --- Editor/Core/Inspectors/GameEditor.cs | 28 +++++++++++++++---- Runtime/Core/Architecture/Game.cs | 25 ++--------------- Runtime/Core/Architecture/GameBridge.cs | 2 +- Runtime/Core/Architecture/World.cs | 4 +++ Runtime/Core/DefaultClass/DefultGame.cs | 2 +- Runtime/Core/Definitions/InspectorInfo.cs | 1 + Runtime/Core/Framework/GameSubsystem.cs | 9 +++++- Runtime/Core/Framework/Kernel.cs | 2 +- Runtime/Core/Framework/Scope.cs | 25 +++++++++++++++++ .../Subsystems/DependencyInjection.cs | 21 +++++++++++++- .../Framework/Subsystems/ServiceLocator.cs | 14 +++++++++- 11 files changed, 98 insertions(+), 35 deletions(-) diff --git a/Editor/Core/Inspectors/GameEditor.cs b/Editor/Core/Inspectors/GameEditor.cs index f747754..2d2bb12 100644 --- a/Editor/Core/Inspectors/GameEditor.cs +++ b/Editor/Core/Inspectors/GameEditor.cs @@ -1,4 +1,5 @@ using UnityEditor; +using UnityEngine; namespace RealMethod.Editor { @@ -9,10 +10,14 @@ public class GameEditor : UnityEditor.Editor private string WorldName => Game.World != null ? Game.World.GetType().Name : "World Not Valid"; private string BridgeName => Game.Bridge != null ? Game.Bridge.GetType().Name : "GameBridge Not Valid"; private string ConfigName => Game.Config != null ? Game.Config.GetType().Name : "GameConfig Not Valid"; + private IInspectorInfo[] InfoList; + private bool[] FoldoutList; private void OnEnable() { Comp = (Game)target; + InfoList = Comp.GetAllInfo(); + FoldoutList = new bool[InfoList.Length]; } public override void OnInspectorGUI() { @@ -22,14 +27,25 @@ public override void OnInspectorGUI() { EditorGUILayout.LabelField($"{WorldName} | {BridgeName} | {ConfigName}"); EditorGUILayout.LabelField($"GameStat: {Game.State}"); - EditorGUILayout.Space(0.5f); - - EditorGUILayout.LabelField($"----------------------------"); - IInspectorInfo[] Info = Comp.GetAllInfo(); - for (int i = 0; i < Info.Length; i++) + EditorGUILayout.LabelField("", GUI.skin.horizontalSlider); + if (InfoList != null) { - EditorGUILayout.LabelField($"{i + 1}.{Info[i].GetType().Name}-> {Info[i].GetInfo()}"); + for (int i = 0; i < InfoList.Length; i++) + { + IInspectorInfo info = InfoList[i]; + if (info == null) + continue; + + FoldoutList[i] = EditorGUILayout.Foldout(FoldoutList[i], $"{i + 1}. {info.GetTitleInfo()}", true, EditorStyles.foldoutHeader); + if (FoldoutList[i]) + { + GUIStyle style = new GUIStyle(EditorStyles.label); + style.wordWrap = true; + EditorGUILayout.LabelField(info.GetInfo(), style); + } + } } + } } diff --git a/Runtime/Core/Architecture/Game.cs b/Runtime/Core/Architecture/Game.cs index f2b825d..807f7a1 100644 --- a/Runtime/Core/Architecture/Game.cs +++ b/Runtime/Core/Architecture/Game.cs @@ -2,7 +2,6 @@ using System.Collections.Generic; using UnityEngine; using UnityEngine.SceneManagement; -using System.Linq; #if UNITY_EDITOR @@ -103,11 +102,6 @@ public static bool IsPaused /// public static bool IsLoading => Instance.IsGameLoading(); /// - /// Returns true if the Game system has one or more registered services; - /// otherwise, returns false. - /// - public static bool HasService => Instance.myServicObjects.Count > 0; - /// /// Event invoked when a scene or world starts or finishes loading. /// The boolean parameter is true when loading starts and false when loading ends. /// @@ -172,17 +166,9 @@ public ISaveSystem SaveSystem } - /// - /// List of runtime-registered instances owned by the game. - /// - private readonly List myServicObjects = new List(); - - - - /// /// Initializes the game singleton and core systems on subsystem registration. - /// This sets up the , game , + /// This sets up the , game , /// configuration, prefabs and managers and registers quit callbacks. /// Invoked when starting up the runtime. Called before the first scene is loaded. /// @@ -1009,18 +995,11 @@ private void FixedUpdate() /// Array of service type names. public override IInspectorInfo[] GetAllInfo() { - List Result = new List(); + List Result = new List(10) { Bridge, Config }; foreach (var item in base.GetAllInfo()) { Result.Add(item); } - Result.Add(Bridge); - Result.Add(Config); - var servicesInfo = myServicObjects != null ? myServicObjects.OfType().ToArray() : Array.Empty(); - foreach (var item in servicesInfo) - { - Result.Add(item); - } return Result.ToArray(); } #endif diff --git a/Runtime/Core/Architecture/GameBridge.cs b/Runtime/Core/Architecture/GameBridge.cs index c879e17..9542e77 100644 --- a/Runtime/Core/Architecture/GameBridge.cs +++ b/Runtime/Core/Architecture/GameBridge.cs @@ -80,7 +80,7 @@ public interface IBridge /// world check for single remove new version /// Load & Unload Scene reporting /// - /// Inherits from and implements + /// Inherits from and implements /// to integrate with the game's internal world and service management system. /// public abstract class GameBridge : IDisposable, IRelationBridge, ILoadScneBridge, IInspectorInfo diff --git a/Runtime/Core/Architecture/World.cs b/Runtime/Core/Architecture/World.cs index 2738fef..846af65 100644 --- a/Runtime/Core/Architecture/World.cs +++ b/Runtime/Core/Architecture/World.cs @@ -153,6 +153,10 @@ private void FixedUpdate() { } + public sealed override IInspectorInfo[] GetAllInfo() + { + return null; + } #endif /// /// Unity callback invoked when the object is being destroyed. diff --git a/Runtime/Core/DefaultClass/DefultGame.cs b/Runtime/Core/DefaultClass/DefultGame.cs index 9fb05e1..02652de 100644 --- a/Runtime/Core/DefaultClass/DefultGame.cs +++ b/Runtime/Core/DefaultClass/DefultGame.cs @@ -11,7 +11,7 @@ protected override void OnGameOpen() } protected override void OnGameInitialized() { - AddGameService(); + AddModule(); Debug.Log("DefultGame Initialized"); } protected override void OnGameStart() diff --git a/Runtime/Core/Definitions/InspectorInfo.cs b/Runtime/Core/Definitions/InspectorInfo.cs index 8eb34f2..2174bba 100644 --- a/Runtime/Core/Definitions/InspectorInfo.cs +++ b/Runtime/Core/Definitions/InspectorInfo.cs @@ -3,6 +3,7 @@ namespace RealMethod public interface IInspectorInfo { #if UNITY_EDITOR + string GetTitleInfo() => GetType().Name; /// /// Returns a formatted string containing information about this service /// intended for display in the Unity Inspector or debugging interfaces. diff --git a/Runtime/Core/Framework/GameSubsystem.cs b/Runtime/Core/Framework/GameSubsystem.cs index e3bfdc4..12987f7 100644 --- a/Runtime/Core/Framework/GameSubsystem.cs +++ b/Runtime/Core/Framework/GameSubsystem.cs @@ -5,7 +5,7 @@ namespace RealMethod { public abstract class GameSubsystem : IInspectorInfo { - public class ShareData + public class ShareData : IInspectorInfo { public Dictionary> Repository { get; } @@ -13,6 +13,13 @@ public ShareData(int prewarm) { Repository = new Dictionary>(prewarm); } + +#if UNITY_EDITOR + string IInspectorInfo.GetInfo() + { + return $"Repository ({Repository.Count})"; + } +#endif } protected ShareData Data { get; private set; } diff --git a/Runtime/Core/Framework/Kernel.cs b/Runtime/Core/Framework/Kernel.cs index 1265542..c42c97b 100644 --- a/Runtime/Core/Framework/Kernel.cs +++ b/Runtime/Core/Framework/Kernel.cs @@ -39,7 +39,7 @@ public abstract class Kernel : MonoBehaviour #if UNITY_EDITOR public virtual IInspectorInfo[] GetAllInfo() { - return new IInspectorInfo[2] { Services, DInjection }; + return new IInspectorInfo[3] { _rpository ,Services, DInjection }; } #endif } diff --git a/Runtime/Core/Framework/Scope.cs b/Runtime/Core/Framework/Scope.cs index d897c46..fa4348d 100644 --- a/Runtime/Core/Framework/Scope.cs +++ b/Runtime/Core/Framework/Scope.cs @@ -1,5 +1,6 @@ using System; using System.Collections.Generic; +using System.Linq; using UnityEngine; namespace RealMethod @@ -22,6 +23,11 @@ namespace RealMethod /// public abstract class Scope : Kernel { + /// + /// Returns true if the Game system has one or more module; + /// otherwise, returns false. + /// + public bool HasModule => _gameModules.Count > 0; public bool IsScopeOpened { get; private set; } = false; /// /// Cached array of managers that were instantiated from configured game prefabs or World gameobject. @@ -376,6 +382,25 @@ private bool IsExistsModule() where T : GameModule return false; } + +#if UNITY_EDITOR + public override IInspectorInfo[] GetAllInfo() + { + List Result = new List(); + foreach (var item in base.GetAllInfo()) + { + Result.Add(item); + } + // My Info + var servicesInfo = _gameModules != null ? _gameModules.OfType().ToArray() : Array.Empty(); + foreach (var item in servicesInfo) + { + Result.Add(item); + } + return Result.ToArray(); + } +#endif + } diff --git a/Runtime/Core/Framework/Subsystems/DependencyInjection.cs b/Runtime/Core/Framework/Subsystems/DependencyInjection.cs index 08a3dad..367a496 100644 --- a/Runtime/Core/Framework/Subsystems/DependencyInjection.cs +++ b/Runtime/Core/Framework/Subsystems/DependencyInjection.cs @@ -5,6 +5,12 @@ namespace RealMethod { + public interface IFeature + { + + } + + public sealed class DependencyInjection : GameSubsystem { private readonly object _lock = new(); @@ -148,7 +154,20 @@ public TInterface Resolve2() #if UNITY_EDITOR protected override string GetInspectorInfor() { - return $"Repository ({bindings.Count})"; + System.Text.StringBuilder sb = new System.Text.StringBuilder(); + for (int i = 0; i < bindings.Count; i++) + { + var type = bindings.GetKey(i); + if (type is IFeature) + { + var weakRef = bindings.GetValue(i); + if (weakRef.TryGetTarget(out var target)) + sb.AppendLine($"{i}. {type.Name} -> Alive ({target})"); + else + sb.AppendLine($"{i}. {type.Name} -> Collected"); + } + } + return sb.ToString(); } #endif } diff --git a/Runtime/Core/Framework/Subsystems/ServiceLocator.cs b/Runtime/Core/Framework/Subsystems/ServiceLocator.cs index 87c1296..f23cdb3 100644 --- a/Runtime/Core/Framework/Subsystems/ServiceLocator.cs +++ b/Runtime/Core/Framework/Subsystems/ServiceLocator.cs @@ -220,7 +220,19 @@ public void ClearAll() #if UNITY_EDITOR protected override string GetInspectorInfor() { - return $"Repository ({_services.Count})"; + System.Text.StringBuilder sb = new System.Text.StringBuilder(); + + for (int i = 0; i < _services.Count; i++) + { + var type = _services.GetKey(i); + var weakRef = _services.GetValue(i); + if (weakRef.TryGetTarget(out var target)) + sb.AppendLine($"{i}. {type.Name} -> Alive ({target})"); + else + sb.AppendLine($"{i}. {type.Name} -> Collected"); + } + + return sb.ToString(); } #endif From ad3daff6c0dbfd5dc6e72c164032fe4ae522520a Mon Sep 17 00:00:00 2001 From: Alijimpa Date: Fri, 8 May 2026 16:36:35 +0330 Subject: [PATCH 188/204] Refine all service world user in hole package --- .../{ServiceRule.cs => GameModuleRule.cs} | 6 +-- ...iceRule.cs.meta => GameModuleRule.cs.meta} | 0 Editor/Core/Inspectors/GameEditor.cs | 2 +- Runtime/Core/Architecture/GameBridge.cs | 3 -- Runtime/Core/Architecture/World.cs | 4 +- Runtime/Core/Definitions/InspectorInfo.cs | 2 +- Runtime/Core/Definitions/Registrable.cs | 17 +++++++ Runtime/Core/Definitions/Registrable.cs.meta | 2 + Runtime/Core/Definitions/Service.cs | 6 --- Runtime/Core/Definitions/Service.cs.meta | 2 - Runtime/Core/Definitions/Systems.cs | 2 +- Runtime/Pattern/Services/InputService.cs | 2 +- Runtime/Pattern/Services/RuleService.cs | 16 +++++-- Runtime/Pattern/Services/StateService.cs | 2 +- .../{DebugService.cs => DebugModule.cs} | 45 +++++++++++++------ ...bugService.cs.meta => DebugModule.cs.meta} | 0 Runtime/ReadySet/Services/Despawn.cs | 4 +- Runtime/ReadySet/Services/NetworkService.cs | 2 +- Runtime/ReadySet/Services/Spawan.cs | 4 +- Runtime/ReadySet/Services/TimeService.cs | 4 +- 20 files changed, 80 insertions(+), 45 deletions(-) rename Editor/Core/InitializeOnLoad/Rules/{ServiceRule.cs => GameModuleRule.cs} (78%) rename Editor/Core/InitializeOnLoad/Rules/{ServiceRule.cs.meta => GameModuleRule.cs.meta} (100%) create mode 100644 Runtime/Core/Definitions/Registrable.cs create mode 100644 Runtime/Core/Definitions/Registrable.cs.meta delete mode 100644 Runtime/Core/Definitions/Service.cs delete mode 100644 Runtime/Core/Definitions/Service.cs.meta rename Runtime/ReadySet/Services/{DebugService.cs => DebugModule.cs} (81%) rename Runtime/ReadySet/Services/{DebugService.cs.meta => DebugModule.cs.meta} (100%) diff --git a/Editor/Core/InitializeOnLoad/Rules/ServiceRule.cs b/Editor/Core/InitializeOnLoad/Rules/GameModuleRule.cs similarity index 78% rename from Editor/Core/InitializeOnLoad/Rules/ServiceRule.cs rename to Editor/Core/InitializeOnLoad/Rules/GameModuleRule.cs index 75fd030..4995309 100644 --- a/Editor/Core/InitializeOnLoad/Rules/ServiceRule.cs +++ b/Editor/Core/InitializeOnLoad/Rules/GameModuleRule.cs @@ -18,7 +18,7 @@ public override bool CanCheck(RuleExecutionMode mode, Type type) { if (mode == RuleExecutionMode.AfterCompilation) { - return type.IsSubclassOf(typeof(GameService)); + return type.IsSubclassOf(typeof(GameModule)); } else { @@ -30,7 +30,7 @@ public override void OnCheck(Type type) // Check if class is static if (type.IsAbstract && type.IsSealed) { - Debug.LogError($"Service '{type.FullName}' cannot be static."); + Debug.LogError($"{typeof(GameModule).Name} class '{type.FullName}' cannot be static."); return; } @@ -46,7 +46,7 @@ public override void OnCheck(Type type) { if (method.IsStatic) { - Debug.LogError($"Service '{type.FullName}' contains static method '{method.Name}'. Static methods are not allowed in Service classes."); + Debug.LogError($"Module '{type.FullName}' contains static method '{method.Name}'. Static methods are not allowed in module classes."); } } } diff --git a/Editor/Core/InitializeOnLoad/Rules/ServiceRule.cs.meta b/Editor/Core/InitializeOnLoad/Rules/GameModuleRule.cs.meta similarity index 100% rename from Editor/Core/InitializeOnLoad/Rules/ServiceRule.cs.meta rename to Editor/Core/InitializeOnLoad/Rules/GameModuleRule.cs.meta diff --git a/Editor/Core/Inspectors/GameEditor.cs b/Editor/Core/Inspectors/GameEditor.cs index 2d2bb12..d34379a 100644 --- a/Editor/Core/Inspectors/GameEditor.cs +++ b/Editor/Core/Inspectors/GameEditor.cs @@ -27,7 +27,7 @@ public override void OnInspectorGUI() { EditorGUILayout.LabelField($"{WorldName} | {BridgeName} | {ConfigName}"); EditorGUILayout.LabelField($"GameStat: {Game.State}"); - EditorGUILayout.LabelField("", GUI.skin.horizontalSlider); + EditorGUILayout.LabelField($"----------------------------------------({InfoList.Length})----------------------------------------"); if (InfoList != null) { for (int i = 0; i < InfoList.Length; i++) diff --git a/Runtime/Core/Architecture/GameBridge.cs b/Runtime/Core/Architecture/GameBridge.cs index 9542e77..a59b158 100644 --- a/Runtime/Core/Architecture/GameBridge.cs +++ b/Runtime/Core/Architecture/GameBridge.cs @@ -76,12 +76,9 @@ public interface IBridge /// Provides core functionality for: /// /// World synchronization (main and additive worlds) - /// Service lifecycle notifications (created/removed) /// world check for single remove new version /// Load & Unload Scene reporting /// - /// Inherits from and implements - /// to integrate with the game's internal world and service management system. /// public abstract class GameBridge : IDisposable, IRelationBridge, ILoadScneBridge, IInspectorInfo { diff --git a/Runtime/Core/Architecture/World.cs b/Runtime/Core/Architecture/World.cs index 846af65..eecfed5 100644 --- a/Runtime/Core/Architecture/World.cs +++ b/Runtime/Core/Architecture/World.cs @@ -72,7 +72,7 @@ protected virtual void OnDrawGizmos() /// /// Base class representing a game world / scene context. /// Manages the player GameObject, locates and initializes child game managers, - /// and forwards service updates to managers. Concrete worlds should implement + /// Concrete worlds should implement /// and to perform /// world-specific initialization and cleanup. /// @@ -88,7 +88,6 @@ public abstract class World : Scope /// /// Unity callback invoked when the script instance is being loaded. - /// Connects the world to the game service, binds service callbacks, /// initializes child managers and locates or creates the player object, /// then calls for world-specific initialization. /// @@ -160,7 +159,6 @@ public sealed override IInspectorInfo[] GetAllInfo() #endif /// /// Unity callback invoked when the object is being destroyed. - /// Unbinds previously bound service callbacks to avoid dangling references. /// private void OnDestroy() { diff --git a/Runtime/Core/Definitions/InspectorInfo.cs b/Runtime/Core/Definitions/InspectorInfo.cs index 2174bba..a2624a9 100644 --- a/Runtime/Core/Definitions/InspectorInfo.cs +++ b/Runtime/Core/Definitions/InspectorInfo.cs @@ -5,7 +5,7 @@ public interface IInspectorInfo #if UNITY_EDITOR string GetTitleInfo() => GetType().Name; /// - /// Returns a formatted string containing information about this service + /// Returns a formatted string containing information about any object can show properties /// intended for display in the Unity Inspector or debugging interfaces. /// This method is for visualization purposes only and must not affect logic. /// diff --git a/Runtime/Core/Definitions/Registrable.cs b/Runtime/Core/Definitions/Registrable.cs new file mode 100644 index 0000000..3553081 --- /dev/null +++ b/Runtime/Core/Definitions/Registrable.cs @@ -0,0 +1,17 @@ +namespace RealMethod +{ + /// + /// Defines the contract for a object that can respond to lifecycle events. + /// + public interface IRegistrable + { + /// + /// Called when the object registerd by servicelocator. + /// + void OnRegister(); + /// + /// Called when unregisterd the object is deleted or destroyed from servicelocator. + /// + void OnUnregister(); + } +} \ No newline at end of file diff --git a/Runtime/Core/Definitions/Registrable.cs.meta b/Runtime/Core/Definitions/Registrable.cs.meta new file mode 100644 index 0000000..2ad0320 --- /dev/null +++ b/Runtime/Core/Definitions/Registrable.cs.meta @@ -0,0 +1,2 @@ +fileFormatVersion: 2 +guid: 3d859c9d6fcb91241aa741c6a8dabe1d \ No newline at end of file diff --git a/Runtime/Core/Definitions/Service.cs b/Runtime/Core/Definitions/Service.cs deleted file mode 100644 index 2ff9ccd..0000000 --- a/Runtime/Core/Definitions/Service.cs +++ /dev/null @@ -1,6 +0,0 @@ -namespace RealMethod -{ - public interface IService { - - } -} \ No newline at end of file diff --git a/Runtime/Core/Definitions/Service.cs.meta b/Runtime/Core/Definitions/Service.cs.meta deleted file mode 100644 index 1e4cbf1..0000000 --- a/Runtime/Core/Definitions/Service.cs.meta +++ /dev/null @@ -1,2 +0,0 @@ -fileFormatVersion: 2 -guid: 7fac47f2ec1af7c479ff9393e8298cca \ No newline at end of file diff --git a/Runtime/Core/Definitions/Systems.cs b/Runtime/Core/Definitions/Systems.cs index 59d8f3b..3fc1f58 100644 --- a/Runtime/Core/Definitions/Systems.cs +++ b/Runtime/Core/Definitions/Systems.cs @@ -63,7 +63,7 @@ public interface IDeviceService string Platform { get; } int Memory { get; } } - public interface IDebugService + public interface IDebugService2 { void ShowFPS(bool active); void ShowToast(string message); diff --git a/Runtime/Pattern/Services/InputService.cs b/Runtime/Pattern/Services/InputService.cs index 2b8b669..4d87e43 100644 --- a/Runtime/Pattern/Services/InputService.cs +++ b/Runtime/Pattern/Services/InputService.cs @@ -3,7 +3,7 @@ namespace RealMethod { - public abstract class InputService : GameService + public abstract class InputService : GameModule { private InputActionAsset CurrentInputAsset; diff --git a/Runtime/Pattern/Services/RuleService.cs b/Runtime/Pattern/Services/RuleService.cs index f0897d4..a0247b6 100644 --- a/Runtime/Pattern/Services/RuleService.cs +++ b/Runtime/Pattern/Services/RuleService.cs @@ -2,10 +2,20 @@ namespace RealMethod { - public abstract class RuleService : GameService + public interface IRuleService : IService { - public Action OnAddedRule; - public Action OnFinishRule; + bool InEffect(string rule); + bool IsValid(string rule); + void BindRule(string Name, Action callback); + event Action OnAddedRule; + event Action OnFinishRule; + } + + + public abstract class RuleService : GameModule, IRuleService + { + public event Action OnAddedRule; + public event Action OnFinishRule; private NameTable> Rules; public RuleService() diff --git a/Runtime/Pattern/Services/StateService.cs b/Runtime/Pattern/Services/StateService.cs index 75f1f36..12e15e6 100644 --- a/Runtime/Pattern/Services/StateService.cs +++ b/Runtime/Pattern/Services/StateService.cs @@ -3,7 +3,7 @@ namespace RealMethod { - public abstract class StateService : GameService + public abstract class StateService : GameModule { protected byte currentState { get; private set; } protected byte previousState { get; private set; } diff --git a/Runtime/ReadySet/Services/DebugService.cs b/Runtime/ReadySet/Services/DebugModule.cs similarity index 81% rename from Runtime/ReadySet/Services/DebugService.cs rename to Runtime/ReadySet/Services/DebugModule.cs index 789019a..bc0c245 100644 --- a/Runtime/ReadySet/Services/DebugService.cs +++ b/Runtime/ReadySet/Services/DebugModule.cs @@ -3,20 +3,30 @@ namespace RealMethod { - public sealed class DebugService : GameService, ILogHandler + public interface IDebugService : IService + { + Vector2 PrintPivot { get; } + float PrintSpace { get; } + int PrintSize { get; } + event System.Action OnLogWrited; + + void SetPivot(Vector2 pivot); + void SetSize(int size); + } + public sealed class DebugModule : GameModule, ILogHandler, IDebugService { private class LogLine : IDrawTask { - private DebugService MyOwner; + private DebugModule MyOwner; private string MyMessage; private LogType MyType; private Vector2 MyOffcet; private float ActiveTime; - public Vector2 Pivot => MyOwner.PrintPivot; - public float Space => MyOwner.PrintSpace; - private int Size => MyOwner.PrintSize; + public Vector2 Pivot => MyOwner.Pivot; + public float Space => ((IDebugService)MyOwner).PrintSpace; + private int Size => MyOwner.Size; public bool IsFinished => !(Time.time - ActiveTime <= Duration); public float Duration { @@ -63,7 +73,7 @@ public Color Color - public LogLine(DebugService owner, string message, LogType type) + public LogLine(DebugModule owner, string message, LogType type) { MyOwner = owner; MyMessage = message; @@ -71,7 +81,7 @@ public LogLine(DebugService owner, string message, LogType type) MyOffcet = Vector2.zero; ActiveTime = 0; } - public LogLine(DebugService owner, string message, LogType type, Vector2 offcet) + public LogLine(DebugModule owner, string message, LogType type, Vector2 offcet) { MyOwner = owner; MyMessage = message; @@ -120,10 +130,8 @@ DrawMode IDrawTask.GetDrawMode() } } - // LineSetting - public Vector2 PrintPivot = new Vector2(10, 10); - public float PrintSpace => Screen.height / 40; - public int PrintSize = 1; + private Vector2 Pivot = new Vector2(10, 10); + private int Size = 1; private List Lines = new List(10); private ILogHandler defaultLogHandler; public event System.Action OnLogWrited; @@ -160,10 +168,21 @@ void ILogHandler.LogException(System.Exception exception, Object context) defaultLogHandler.LogException(exception, context); OnLogWrited?.Invoke(LogType.Exception, exception.Message); } + // Implement IDebugService Interface + Vector2 IDebugService.PrintPivot => Pivot; + int IDebugService.PrintSize => Size; + float IDebugService.PrintSpace => Screen.height / 40; + void IDebugService.SetPivot(Vector2 pivot) + { + Pivot = pivot; + } + void IDebugService.SetSize(int size) + { + Size = size; + } - - // Service Methods + // Module Methods protected override void OnBegin() { defaultLogHandler = Debug.unityLogger.logHandler; diff --git a/Runtime/ReadySet/Services/DebugService.cs.meta b/Runtime/ReadySet/Services/DebugModule.cs.meta similarity index 100% rename from Runtime/ReadySet/Services/DebugService.cs.meta rename to Runtime/ReadySet/Services/DebugModule.cs.meta diff --git a/Runtime/ReadySet/Services/Despawn.cs b/Runtime/ReadySet/Services/Despawn.cs index 3ca2ec2..b78b544 100644 --- a/Runtime/ReadySet/Services/Despawn.cs +++ b/Runtime/ReadySet/Services/Despawn.cs @@ -4,7 +4,7 @@ namespace RealMethod { /// - /// Despawn is a sealed static service used to instantiate gameplay objects such as + /// Despawn is a sealed static class used to instantiate gameplay objects such as /// prefabs, UI elements, audio sources, and other spawnable types. /// /// This class automatically locates the required manager instances from the @@ -102,7 +102,7 @@ private static T GetManager() where T : Component, IGameManager } else { - if (Game.World.TryFindManager(out T manager)) + if (Game.World.TryFindGameManager(out T manager)) { Ins.Managers.Add(type, manager); return manager; diff --git a/Runtime/ReadySet/Services/NetworkService.cs b/Runtime/ReadySet/Services/NetworkService.cs index 5bcc744..5b9c081 100644 --- a/Runtime/ReadySet/Services/NetworkService.cs +++ b/Runtime/ReadySet/Services/NetworkService.cs @@ -5,7 +5,7 @@ namespace RealMethod { - public sealed class NetworkService : GameService + public sealed class NetworkService : GameModule { //Const Variable private const string webImage = "http://upload.wikimedia.org/wikipedia/commons/c/c5/Moraine_Lake_17092005.jpg"; diff --git a/Runtime/ReadySet/Services/Spawan.cs b/Runtime/ReadySet/Services/Spawan.cs index 8d89b02..41111b2 100644 --- a/Runtime/ReadySet/Services/Spawan.cs +++ b/Runtime/ReadySet/Services/Spawan.cs @@ -7,7 +7,7 @@ namespace RealMethod { /// - /// Spawn is a sealed static service used to instantiate gameplay objects such as + /// Spawn is a sealed static class used to instantiate gameplay objects such as /// prefabs, UI elements, audio sources, and other spawnable types. /// /// This class automatically locates the required manager instances from the @@ -102,7 +102,7 @@ private static T GetManager() where T : Component, IGameManager } else { - if (Game.World.TryFindManager(out T manager)) + if (Game.World.TryFindGameManager(out T manager)) { Ins.Managers.Add(type, manager); return manager; diff --git a/Runtime/ReadySet/Services/TimeService.cs b/Runtime/ReadySet/Services/TimeService.cs index 7fdd136..1e1bcb7 100644 --- a/Runtime/ReadySet/Services/TimeService.cs +++ b/Runtime/ReadySet/Services/TimeService.cs @@ -2,13 +2,13 @@ namespace RealMethod { - public sealed class TimeService : GameService + public sealed class TimeService : GameModule { private float serviceTime; private float worldTime; private NameTable RecordTime; - // Service Methods + // Module Methods protected override void OnBegin() { serviceTime = Time.time; From dfc3938849995cbaa77583aea2f928bcd0f63125 Mon Sep 17 00:00:00 2001 From: Alijimpa Date: Fri, 8 May 2026 17:25:19 +0330 Subject: [PATCH 189/204] Impleemnt Singletine Template (Context ) and refine Spawn & Despawn Context --- Runtime/Core/Definitions/Context.cs | 72 +++++ Runtime/Core/Definitions/Context.cs.meta | 2 + .../Enumeration/RealMethodSystem.cs | 9 + .../Enumeration/RealMethodSystem.cs.meta | 2 + Runtime/ReadySet/Services/Despawn.cs | 152 +++++----- Runtime/ReadySet/Services/Spawan.cs | 263 +++++++----------- 6 files changed, 281 insertions(+), 219 deletions(-) create mode 100644 Runtime/Core/Definitions/Context.cs create mode 100644 Runtime/Core/Definitions/Context.cs.meta create mode 100644 Runtime/Library/SharedScripts/Enumeration/RealMethodSystem.cs create mode 100644 Runtime/Library/SharedScripts/Enumeration/RealMethodSystem.cs.meta diff --git a/Runtime/Core/Definitions/Context.cs b/Runtime/Core/Definitions/Context.cs new file mode 100644 index 0000000..b958b22 --- /dev/null +++ b/Runtime/Core/Definitions/Context.cs @@ -0,0 +1,72 @@ +using System; + +namespace RealMethod +{ + + /// + /// Generic singleton base class. + /// Ensures only one instance of type exists. + /// + public abstract class Context : IDisposable where T : Context, new() + { + private static T _instance; + private static readonly object _lock = new object(); + + + + /// + /// Gets the single instance of this type. + /// + public static T Instance + { + get + { + lock (_lock) + { + if (_instance == null) + { + // Use Reflection to create the instance since + // the constructor is private/protected + _instance = (T)Activator.CreateInstance(typeof(T), true); + } + return _instance; + } + } + } + + /// + /// Prevents external instantiation. + /// + protected Context() + { + OnBegin(); + } + + /// + /// Cleans up the singleton instance. + /// + public virtual void Dispose() + { + lock (_lock) + { + if (_instance != null) + { + OnEnd(); + _instance = null; // Removing the reference + } + } + } + + + + + /// + /// Override this to perform custom Starter logic (like Subscribing events). + /// + protected abstract void OnBegin(); + /// + /// Override this to perform custom cleanup logic (like Unsubscribing events). + /// + protected abstract void OnEnd(); + } +} diff --git a/Runtime/Core/Definitions/Context.cs.meta b/Runtime/Core/Definitions/Context.cs.meta new file mode 100644 index 0000000..5c5d1af --- /dev/null +++ b/Runtime/Core/Definitions/Context.cs.meta @@ -0,0 +1,2 @@ +fileFormatVersion: 2 +guid: 67b9ab8283ceda845835bf1a2c7ba940 \ No newline at end of file diff --git a/Runtime/Library/SharedScripts/Enumeration/RealMethodSystem.cs b/Runtime/Library/SharedScripts/Enumeration/RealMethodSystem.cs new file mode 100644 index 0000000..c47c71f --- /dev/null +++ b/Runtime/Library/SharedScripts/Enumeration/RealMethodSystem.cs @@ -0,0 +1,9 @@ +namespace RealMethod +{ + public enum ScopeContext + { + Both, + World, + Game, + } +} \ No newline at end of file diff --git a/Runtime/Library/SharedScripts/Enumeration/RealMethodSystem.cs.meta b/Runtime/Library/SharedScripts/Enumeration/RealMethodSystem.cs.meta new file mode 100644 index 0000000..2ba78a1 --- /dev/null +++ b/Runtime/Library/SharedScripts/Enumeration/RealMethodSystem.cs.meta @@ -0,0 +1,2 @@ +fileFormatVersion: 2 +guid: 3b0e9a1cf2fcb274085686abcc9366ab \ No newline at end of file diff --git a/Runtime/ReadySet/Services/Despawn.cs b/Runtime/ReadySet/Services/Despawn.cs index b78b544..b1a6038 100644 --- a/Runtime/ReadySet/Services/Despawn.cs +++ b/Runtime/ReadySet/Services/Despawn.cs @@ -39,104 +39,130 @@ namespace RealMethod /// system that intelligently reuses previously found managers and adapts to /// scene changes. /// - public sealed class Despawn : IBridge, System.IDisposable, IInspectorInfo + public sealed class Despawn : Context, IBridge, IInspectorInfo { - private static Despawn Ins => CacheInstance.Value; - private static System.Lazy CacheInstance = new System.Lazy(() => new Despawn()); - - - private Dictionary Managers; - - public Despawn() - { - Game.Bridge.Bind(this); - Managers = new(); - } + private Dictionary GameManagers; + private Dictionary WorldManagers; // Implement IBridge Interface void IBridge.OnWorldChanged(World world) { - Managers.Clear(); - } - // Implement IDisposable Interface - void System.IDisposable.Dispose() - { - Game.Bridge.Unbind(this); - Managers.Clear(); + WorldManagers.Clear(); + Debug.Log("ChangeWorld Spawn"); } -#if UNITY_EDITOR - // Implement IInspectorInfo Interface - string IInspectorInfo.GetInfo() + protected override void OnBegin() { - return $"Managers ({Managers.Count})"; - } -#endif - - - // Public Functions - public void AddManager(IGameManager manager) - { - System.Type ManagerType = manager.Component.GetType(); - if (Managers.ContainsKey(ManagerType)) - { - Managers.Add(ManagerType, manager); - } - else + // Check if you game not initialized + if (!Game.IsGameInitialized) { - Debug.LogWarning($"{Ins}: Manager of type '{ManagerType.Name}' already exists. Skipping add."); + Debug.LogWarning($"Game doesn't initialized !"); + return; } + Game.Bridge.Bind(this); + GameManagers = new(); + WorldManagers = new(); + Debug.Log("Begin Spawn"); + } + protected override void OnEnd() + { + Game.Bridge.Unbind(this); + GameManagers = null; + WorldManagers = null; + Debug.Log("End Spawn"); } - - // Public Functions - private static T GetManager() where T : Component, IGameManager + private static T Get(ScopeContext context = ScopeContext.Both) where T : Component, IGameManager { System.Type type = typeof(T); - if (Ins.Managers.ContainsKey(type)) - { - if (Ins.Managers[type].Component is T manager) - { - return manager; - } - } - else + + switch (context) { - if (Game.World.TryFindGameManager(out T manager)) - { - Ins.Managers.Add(type, manager); - return manager; - } + case ScopeContext.World: + if (Instance.WorldManagers.ContainsKey(type)) + { + return (T)Instance.WorldManagers[type].Component; + } + else + { + if (Game.World.TryFindGameManager(out T manager)) + { + Instance.WorldManagers.Add(type, manager); + return manager; + } + } + break; + case ScopeContext.Game: + if (Instance.GameManagers.ContainsKey(type)) + { + return (T)Instance.GameManagers[type].Component; + } + else + { + if (Game.Instance.TryFindGameManager(out T manager)) + { + Instance.GameManagers.Add(type, manager); + return manager; + } + } + break; + case ScopeContext.Both: + if (Instance.WorldManagers.ContainsKey(type)) + { + return (T)Instance.WorldManagers[type].Component; + } + else if (Instance.GameManagers.ContainsKey(type)) + { + return (T)Instance.GameManagers[type].Component; + } + else if (Game.World.TryFindGameManager(out T manager1)) + { + Instance.WorldManagers.Add(type, manager1); + return manager1; + } + else if (Game.Instance.TryFindGameManager(out T manager2)) + { + Instance.GameManagers.Add(type, manager2); + return manager2; + } + break; } - Debug.LogError($"{Ins}:Failed to Despawn, Manager({typeof(T).Name}) is not available."); + Debug.LogError($"{Instance}:Failed to spawn, Manager({typeof(T).Name}) is not available. [{context} Context]"); return null; } +#if UNITY_EDITOR + string IInspectorInfo.GetInfo() + { + return $"GameManagers ({GameManagers.Count}) , WorldManagers ({WorldManagers.Count})"; + } +#endif + // UI public static bool Widget(string Name, Object despawner = null, bool debug = true) { - if (GetManager() == null) + if (Get() == null) { if (debug) Debug.LogWarning("Despawn UIManager is not available."); return false; } - return GetManager().RemoveLayer(Name, despawner); + return Get().RemoveLayer(Name, despawner); } public static bool Widget(MonoBehaviour Comp, Object despawner = null, bool debug = true) { - if (GetManager() == null) + if (Get() == null) { if (debug) Debug.LogWarning("Despawn UIManager is not available."); return false; } - return GetManager().RemoveLayer(Comp, despawner); + return Get().RemoveLayer(Comp, despawner); } // Prefab @@ -210,7 +236,7 @@ public static bool Asset(T target, Object despawner = null, bool debug = true // Task public static bool Task(T task) where T : IHandle { - TaskManager manager = GetManager>(); + TaskManager manager = Get>(); if (manager == null) return false; return manager.Destroy(task); @@ -219,27 +245,27 @@ public static bool Task(T task) where T : IHandle // Enumerator public static bool Coroutine(Coroutine coroutine, bool debug = true) { - if (GetManager() == null) + if (Get() == null) { if (debug) Debug.LogWarning("TaskManager is not available."); return false; } - GetManager().Stop(coroutine); + Get().Stop(coroutine); return true; } // Haptic public static bool Haptic(IHapticProvider provider, bool debug = true) { - if (GetManager() == null) + if (Get() == null) { if (debug) Debug.LogWarning("HapticManager is not available."); return false; } - return GetManager().Demolish(provider); + return Get().Demolish(provider); } diff --git a/Runtime/ReadySet/Services/Spawan.cs b/Runtime/ReadySet/Services/Spawan.cs index 41111b2..23394cd 100644 --- a/Runtime/ReadySet/Services/Spawan.cs +++ b/Runtime/ReadySet/Services/Spawan.cs @@ -42,184 +42,159 @@ namespace RealMethod /// system that intelligently reuses previously found managers and adapts to /// scene changes. /// - public sealed class Spawn : IBridge, System.IDisposable, IInspectorInfo + public sealed class Spawn : Context, IBridge, IInspectorInfo { - private static Spawn Ins => CacheInstance.Value; - private static System.Lazy CacheInstance = new System.Lazy(() => new Spawn()); - - private Dictionary Managers; - - - public Spawn() - { - Game.Bridge.Bind(this); - Managers = new(); - } + private Dictionary GameManagers; + private Dictionary WorldManagers; // Implement IBridge Interface void IBridge.OnWorldChanged(World world) { - Managers.Clear(); - } - // Implement IDisposable Interface - void System.IDisposable.Dispose() - { - Game.Bridge.Unbind(this); - Managers.Clear(); - } -#if UNITY_EDITOR - // Implement IInspectorInfo Interface - string IInspectorInfo.GetInfo() - { - return $"Managers ({Managers.Count})"; + WorldManagers.Clear(); + Debug.Log("ChangeWorld Spawn"); } -#endif - // Public Functions - public void AddManager(IGameManager manager) + protected override void OnBegin() { - System.Type ManagerType = manager.Component.GetType(); - if (Managers.ContainsKey(ManagerType)) - { - Managers.Add(ManagerType, manager); - } - else + // Check if you game not initialized + if (!Game.IsGameInitialized) { - Debug.LogWarning($"{Ins}: Manager of type '{ManagerType.Name}' already exists. Skipping add."); + Debug.LogWarning($"Game doesn't initialized !"); + return; } + Game.Bridge.Bind(this); + GameManagers = new(); + WorldManagers = new(); + Debug.Log("Begin Spawn"); + } + protected override void OnEnd() + { + Game.Bridge.Unbind(this); + GameManagers = null; + WorldManagers = null; + Debug.Log("End Spawn"); } - // Private Functions - private static T GetManager() where T : Component, IGameManager + private static T Get(ScopeContext context = ScopeContext.Both) where T : Component, IGameManager { System.Type type = typeof(T); - if (Ins.Managers.ContainsKey(type)) - { - if (Ins.Managers[type].Component is T manager) - { - return manager; - } - } - else - { - if (Game.World.TryFindGameManager(out T manager)) - { - Ins.Managers.Add(type, manager); - return manager; - } + + switch (context) + { + case ScopeContext.World: + if (Instance.WorldManagers.ContainsKey(type)) + { + return (T)Instance.WorldManagers[type].Component; + } + else + { + if (Game.World.TryFindGameManager(out T manager)) + { + Instance.WorldManagers.Add(type, manager); + return manager; + } + } + break; + case ScopeContext.Game: + if (Instance.GameManagers.ContainsKey(type)) + { + return (T)Instance.GameManagers[type].Component; + } + else + { + if (Game.Instance.TryFindGameManager(out T manager)) + { + Instance.GameManagers.Add(type, manager); + return manager; + } + } + break; + case ScopeContext.Both: + if (Instance.WorldManagers.ContainsKey(type)) + { + return (T)Instance.WorldManagers[type].Component; + } + else if (Instance.GameManagers.ContainsKey(type)) + { + return (T)Instance.GameManagers[type].Component; + } + else if (Game.World.TryFindGameManager(out T manager1)) + { + Instance.WorldManagers.Add(type, manager1); + return manager1; + } + else if (Game.Instance.TryFindGameManager(out T manager2)) + { + Instance.GameManagers.Add(type, manager2); + return manager2; + } + break; } - Debug.LogError($"{Ins}:Failed to spawn, Manager({typeof(T).Name}) is not available. [Note:Manger should be in WorldScope or add manualy]"); + Debug.LogError($"{Instance}:Failed to spawn, Manager({typeof(T).Name}) is not available. [{context} Context]"); return null; } + +#if UNITY_EDITOR + string IInspectorInfo.GetInfo() + { + return $"GameManagers ({GameManagers.Count}) , WorldManagers ({WorldManagers.Count})"; + } +#endif + // UI public static T Widget(string Name, Object spawner = null) where T : MonoBehaviour { - if (GetManager() != null) - { - return GetManager().CreateLayer(Name, spawner); - } - else - { - Debug.LogWarning($" {Ins}: UIManager is not available."); - return null; - } + return Get().CreateLayer(Name, spawner); } public static T Widget(VisualTreeAsset UIAsset, string Name, Object spawner = null) where T : MonoBehaviour { - if (GetManager() != null) - { - return GetManager().CreateLayer(Name, UIAsset, spawner); - } - else - { - Debug.LogWarning($" {Ins}: UIManager is not available."); - return null; - } + return Get().CreateLayer(Name, UIAsset, spawner); } public static GameObject Widget(UPrefab Prefab, string Name, Object spawner = null) { - if (GetManager() != null) - { - //if(Prefab) - return GetManager().AddLayer(Name, Prefab, spawner); - } - else - { - Debug.LogWarning($" {Ins}: UIManager is not available."); - return null; - } + return Get().AddLayer(Name, Prefab, spawner); } public static T Widget(UPrefab Prefab, string Name, Object spawner = null) where T : MonoBehaviour { - if (GetManager() != null) - { - return GetManager().AddLayer(Name, Prefab, spawner); - } - else - { - Debug.LogWarning($" {Ins}: UIManager is not available."); - return null; - } + return Get().AddLayer(Name, Prefab, spawner); } public static UIDocument UIDoc(string Name, VisualTreeAsset UIAsset) { - if (GetManager() != null) - { - return GetManager().CreateLayer(Name, UIAsset); - } - else - { - Debug.LogWarning($" {Ins}: UIManager is not available."); - return null; - } + return Get().CreateLayer(Name, UIAsset); } // Screen public static void Message(string message) { - if (GetManager() != null) + if (Get().Informer != null) { - if (GetManager().Informer != null) - { - GetManager().Informer.Popup(message); - } - else - { - Debug.LogWarning($"ScreenMaanger need to set Informer"); - } + Get().Informer.Popup(message); } else { - Debug.LogWarning($" {Ins}: ScreenManager is not available."); + Debug.LogWarning($"ScreenMaanger need to set Informer"); } } public static void Message(string message, float duration) { - if (GetManager() != null) + if (Get().Informer != null) { - if (GetManager().Informer != null) - { - GetManager().Informer.Popup(message, duration); - } - else - { - Debug.LogWarning($"ScreenMaanger need to set Informer"); - } + Get().Informer.Popup(message, duration); } else { - Debug.LogWarning($" {Ins}: ScreenManager is not available."); + Debug.LogWarning($"ScreenMaanger need to set Informer"); } } // Sound public static AudioSource Sound3D(AudioClip clip, Vector3 location, Transform parent = null, AudioMixerGroup group = null, float rolloffDistanceMin = 1f, bool loop = false, float pauseTime = 0, bool autoDestroy = true) { - if (GetManager() != null) + if (Get() != null) { - return GetManager().PlaySound(clip, location, parent, group, rolloffDistanceMin, loop, pauseTime, autoDestroy); + return Get().PlaySound(clip, location, parent, group, rolloffDistanceMin, loop, pauseTime, autoDestroy); } else { @@ -250,9 +225,9 @@ public static AudioSource Sound3D(AudioClip clip, Vector3 location, Transform pa } public static AudioSource Sound2D(AudioClip clip, AudioMixerGroup group = null, float rolloffDistanceMin = 1f, bool loop = false, float pauseTime = 0, bool autoDestroy = true) { - if (GetManager() != null) + if (Get() != null) { - return GetManager().PlaySound2D(clip, group, 1, loop, pauseTime, autoDestroy); + return Get().PlaySound2D(clip, group, 1, loop, pauseTime, autoDestroy); } else { @@ -561,15 +536,7 @@ public static EffectPlayer Effect(EPrefab prefab, Transform parent, Object spawn // Haptic public static IHapticProvider Haptic(HapticConfig config) { - if (GetManager() != null) - { - return GetManager().Produce(config); - } - else - { - Debug.LogWarning($" {Ins}: HapticManager is not available."); - return null; - } + return Get().Produce(config); } // Particle @@ -596,7 +563,7 @@ public static T Component(GameObject target, Object spawner = null) where T : } else { - Debug.LogWarning($" {Ins}: target is not valid."); + Debug.LogWarning($" {Instance}: target is not valid."); return null; } @@ -605,7 +572,7 @@ public static T Class(System.Type classType) { if (classType == null) { - Debug.LogWarning($" {Ins}: ClassType is not valid!"); + Debug.LogWarning($" {Instance}: ClassType is not valid!"); return default; } return (T)System.Activator.CreateInstance(classType); @@ -616,7 +583,7 @@ public static T Command(CPrefab prefab, MonoBehaviour owner) where T : Comman { if (owner == null) { - Debug.LogWarning($" {Ins}: Owner or Author is not available."); + Debug.LogWarning($" {Instance}: Owner or Author is not available."); return null; } GameObject SpawnedObject = Object.Instantiate(prefab, owner.transform); @@ -653,7 +620,7 @@ public static PrimitiveAsset Asset(System.Type type, Object spawner = null) // Task public static T Task(F Task, bool AutoStart = false) where T : IHandle where F : class { - TaskManager manager = GetManager>(); + TaskManager manager = Get>(); if (manager == null) return default; return manager.Create(Task, AutoStart); @@ -662,27 +629,11 @@ public static T Task(F Task, bool AutoStart = false) where T : IHandle whe // Enumerator public static Coroutine Coroutine(IEnumerator routine) { - if (GetManager() != null) - { - return GetManager().Run(routine); - } - else - { - Debug.LogWarning($" {Ins}: EnumeratorManager is not available."); - return null; - } + return Get().Run(routine); } public static ICoroutineTask CoroutineTask(IEnumerator routine) { - if (GetManager() != null) - { - return GetManager().StartTask(routine); - } - else - { - Debug.LogWarning($" {Ins}: EnumeratorManager is not available."); - return null; - } + return Get().StartTask(routine); } // Other @@ -707,10 +658,10 @@ public static AudioSource Audio(AudioClip clip) GameObject emptyobject = new GameObject(clip.name); AudioSource source = emptyobject.AddComponent(); source.clip = clip; - if (GetManager() != null) + if (Get() != null) { - source.outputAudioMixerGroup = GetManager().DefaultGroup; - emptyobject.transform.SetParent(GetManager().transform); + source.outputAudioMixerGroup = Get().DefaultGroup; + emptyobject.transform.SetParent(Get().transform); } return source; } From 75e17cc0bb008e2bf0ba060f71bd80f6fca89e55 Mon Sep 17 00:00:00 2001 From: Alijimpa Date: Fri, 8 May 2026 18:20:06 +0330 Subject: [PATCH 190/204] Implement SpawServicec --- Runtime/Core/Framework/Scope.cs | 39 +++++++++++++--- .../Subsystems/DependencyInjection.cs | 2 - .../Framework/Subsystems/ServiceLocator.cs | 16 +------ .../Interfaces}/Registrable.cs | 0 .../Interfaces}/Registrable.cs.meta | 0 .../Enumeration/RealMethodSystem.cs | 2 +- Runtime/ReadySet/Services/Despawn.cs | 8 ++-- Runtime/ReadySet/Services/Spawan.cs | 45 +++++++++++++++++-- Runtime/ReadySet/Services/TimeService.cs | 7 ++- 9 files changed, 87 insertions(+), 32 deletions(-) rename Runtime/{Core/Definitions => Library/Interfaces}/Registrable.cs (100%) rename Runtime/{Core/Definitions => Library/Interfaces}/Registrable.cs.meta (100%) diff --git a/Runtime/Core/Framework/Scope.cs b/Runtime/Core/Framework/Scope.cs index fa4348d..d5a1e54 100644 --- a/Runtime/Core/Framework/Scope.cs +++ b/Runtime/Core/Framework/Scope.cs @@ -138,16 +138,36 @@ public bool TryFindModule(out T result) where T : GameModule { if (IsExistsModule()) { - Debug.LogWarning($"Service of type {typeof(T)} is already added and still alive."); + Debug.LogWarning($"Module of type {typeof(T)} is already added and still alive."); return null; } // Create Service - T newService = new T(); - _gameModules.Add(newService); - RegisterInterface(newService); + T newModule = new T(); + _gameModules.Add(newModule); + RegisterInterface(newModule); - return newService; + return newModule; + } + public GameModule AddModule(Type moduleType) + { + if (IsExistsModule(moduleType)) + { + Debug.LogWarning($"Module of type {moduleType.Name} is already added and still alive."); + return null; + } + + if (!typeof(GameModule).IsAssignableFrom(moduleType)) + { + Debug.LogWarning($"Your type({moduleType.Name}) is not assignable to GameModuel"); + return null; + } + + // Create Service + GameModule newModule = (GameModule)Activator.CreateInstance(moduleType); + _gameModules.Add(newModule); + RegisterInterface(newModule); + return newModule; } /// /// Removes a service of type from the scope. @@ -381,6 +401,15 @@ private bool IsExistsModule() where T : GameModule } return false; } + private bool IsExistsModule(Type moduleType) + { + foreach (var module in _gameModules) + { + if (module.GetType() == moduleType) + return true; + } + return false; + } #if UNITY_EDITOR diff --git a/Runtime/Core/Framework/Subsystems/DependencyInjection.cs b/Runtime/Core/Framework/Subsystems/DependencyInjection.cs index 367a496..b982891 100644 --- a/Runtime/Core/Framework/Subsystems/DependencyInjection.cs +++ b/Runtime/Core/Framework/Subsystems/DependencyInjection.cs @@ -31,8 +31,6 @@ public void Bind(TInterface instance) lock (_lock) { bindings[typeof(TInterface)] = new WeakReference(instance); - if (instance is IRegistrable provider) - provider.OnRegister(); } } diff --git a/Runtime/Core/Framework/Subsystems/ServiceLocator.cs b/Runtime/Core/Framework/Subsystems/ServiceLocator.cs index f23cdb3..2721d05 100644 --- a/Runtime/Core/Framework/Subsystems/ServiceLocator.cs +++ b/Runtime/Core/Framework/Subsystems/ServiceLocator.cs @@ -58,16 +58,12 @@ public void Register(object service, Type type = null, bool overwrite = false) if (!weak.TryGetTarget(out _)) { _services[serviceType] = new WeakReference(service); - if (service is IRegistrable provider1) - provider1.OnRegister(); return; } if (overwrite) { _services[serviceType] = new WeakReference(service); - if (service is IRegistrable provider2) - provider2.OnRegister(); return; } @@ -76,15 +72,12 @@ public void Register(object service, Type type = null, bool overwrite = false) } _services[serviceType] = new WeakReference(service); - if (service is IRegistrable provider3) - provider3.OnRegister(); } } /// /// Register only if no live instance is currently registered for T. /// - public void RegisterIfAbsent(T service) - where T : class + public void RegisterIfAbsent(T service)where T : class { if (service == null) throw new ArgumentNullException(nameof(service)); @@ -97,8 +90,6 @@ public void RegisterIfAbsent(T service) !weak.TryGetTarget(out _)) { _services[type] = new WeakReference(service); - if (service is IRegistrable provider) - provider.OnRegister(); } } } @@ -191,11 +182,6 @@ public bool Unregister(Type type) { if (_services.ContainsKey(type)) { - if (_services[type].TryGetTarget(out object target)) - { - if (target is IRegistrable provider) - provider.OnRegister(); - } return _services.Remove(type); } return false; diff --git a/Runtime/Core/Definitions/Registrable.cs b/Runtime/Library/Interfaces/Registrable.cs similarity index 100% rename from Runtime/Core/Definitions/Registrable.cs rename to Runtime/Library/Interfaces/Registrable.cs diff --git a/Runtime/Core/Definitions/Registrable.cs.meta b/Runtime/Library/Interfaces/Registrable.cs.meta similarity index 100% rename from Runtime/Core/Definitions/Registrable.cs.meta rename to Runtime/Library/Interfaces/Registrable.cs.meta diff --git a/Runtime/Library/SharedScripts/Enumeration/RealMethodSystem.cs b/Runtime/Library/SharedScripts/Enumeration/RealMethodSystem.cs index c47c71f..2db7881 100644 --- a/Runtime/Library/SharedScripts/Enumeration/RealMethodSystem.cs +++ b/Runtime/Library/SharedScripts/Enumeration/RealMethodSystem.cs @@ -1,6 +1,6 @@ namespace RealMethod { - public enum ScopeContext + public enum ScopeTarget { Both, World, diff --git a/Runtime/ReadySet/Services/Despawn.cs b/Runtime/ReadySet/Services/Despawn.cs index b1a6038..468f6a8 100644 --- a/Runtime/ReadySet/Services/Despawn.cs +++ b/Runtime/ReadySet/Services/Despawn.cs @@ -72,13 +72,13 @@ protected override void OnEnd() Debug.Log("End Spawn"); } - private static T Get(ScopeContext context = ScopeContext.Both) where T : Component, IGameManager + private static T Get(ScopeTarget context = ScopeTarget.Both) where T : Component, IGameManager { System.Type type = typeof(T); switch (context) { - case ScopeContext.World: + case ScopeTarget.World: if (Instance.WorldManagers.ContainsKey(type)) { return (T)Instance.WorldManagers[type].Component; @@ -92,7 +92,7 @@ private static T Get(ScopeContext context = ScopeContext.Both) where T : Comp } } break; - case ScopeContext.Game: + case ScopeTarget.Game: if (Instance.GameManagers.ContainsKey(type)) { return (T)Instance.GameManagers[type].Component; @@ -106,7 +106,7 @@ private static T Get(ScopeContext context = ScopeContext.Both) where T : Comp } } break; - case ScopeContext.Both: + case ScopeTarget.Both: if (Instance.WorldManagers.ContainsKey(type)) { return (T)Instance.WorldManagers[type].Component; diff --git a/Runtime/ReadySet/Services/Spawan.cs b/Runtime/ReadySet/Services/Spawan.cs index 23394cd..061dc43 100644 --- a/Runtime/ReadySet/Services/Spawan.cs +++ b/Runtime/ReadySet/Services/Spawan.cs @@ -75,13 +75,13 @@ protected override void OnEnd() Debug.Log("End Spawn"); } - private static T Get(ScopeContext context = ScopeContext.Both) where T : Component, IGameManager + private static T Get(ScopeTarget context = ScopeTarget.Both) where T : Component, IGameManager { System.Type type = typeof(T); switch (context) { - case ScopeContext.World: + case ScopeTarget.World: if (Instance.WorldManagers.ContainsKey(type)) { return (T)Instance.WorldManagers[type].Component; @@ -95,7 +95,7 @@ private static T Get(ScopeContext context = ScopeContext.Both) where T : Comp } } break; - case ScopeContext.Game: + case ScopeTarget.Game: if (Instance.GameManagers.ContainsKey(type)) { return (T)Instance.GameManagers[type].Component; @@ -109,7 +109,7 @@ private static T Get(ScopeContext context = ScopeContext.Both) where T : Comp } } break; - case ScopeContext.Both: + case ScopeTarget.Both: if (Instance.WorldManagers.ContainsKey(type)) { return (T)Instance.WorldManagers[type].Component; @@ -617,6 +617,43 @@ public static PrimitiveAsset Asset(System.Type type, Object spawner = null) return target; } + public static T Service(System.Type ServiceType) where T : IService + { + if (ServiceType == null) + { + Debug.LogWarning($" {Instance}: classType is not valid."); + return default; + } + + bool result = false; + var interfaces = ServiceType.GetInterfaces(); + foreach (var i in interfaces) + { + // Only interfaces derived from Interface + if (typeof(IService).IsAssignableFrom(i)) + result = true; + } + + if (result == false) + { + Debug.LogWarning($" {ServiceType.Name}: has not implement any IService."); + return default; + } + + // Can Select Scope + GameModule newModule = Game.Instance.AddModule(ServiceType); + if (newModule != null) + { + newModule.InvokeReqisterEvent(); + if (newModule is T provider) + { + return provider; + } + } + + return default; + } + // Task public static T Task(F Task, bool AutoStart = false) where T : IHandle where F : class { diff --git a/Runtime/ReadySet/Services/TimeService.cs b/Runtime/ReadySet/Services/TimeService.cs index 1e1bcb7..0d92e9a 100644 --- a/Runtime/ReadySet/Services/TimeService.cs +++ b/Runtime/ReadySet/Services/TimeService.cs @@ -2,7 +2,12 @@ namespace RealMethod { - public sealed class TimeService : GameModule + public interface ITimer : IService + { + + } + + public sealed class TimeService : GameService, ITimer { private float serviceTime; private float worldTime; From c66e70672f1eef715f07220af87bf6da6ed99a12 Mon Sep 17 00:00:00 2001 From: Alijimpa Date: Sat, 9 May 2026 08:38:48 +0330 Subject: [PATCH 191/204] Add Service for Spawn & Despawn --- Runtime/Core/Definitions/RealMethodNames.cs | 4 + Runtime/Core/Definitions/Save&File.cs | 5 - Runtime/Library/Extension/Object.cs | 38 +++- Runtime/Library/Extension/Type.cs | 26 +++ Runtime/Library/Interfaces/Save.cs | 8 + Runtime/Library/Interfaces/Save.cs.meta | 2 + .../ReadySet/Components/Method/RuleEvent.cs | 5 +- Runtime/ReadySet/Essentials.meta | 8 - .../ReadySet/Presets/PoolAsset/AudioPool.cs | 2 +- Runtime/ReadySet/Services/Despawn.cs | 36 ++- Runtime/ReadySet/Services/Spawan.cs | 79 ++++--- Tests/TrashService.cs | 205 ++++++++++++++++++ Tests/TrashService.cs.meta | 2 + 13 files changed, 370 insertions(+), 50 deletions(-) create mode 100644 Runtime/Library/Interfaces/Save.cs create mode 100644 Runtime/Library/Interfaces/Save.cs.meta delete mode 100644 Runtime/ReadySet/Essentials.meta create mode 100644 Tests/TrashService.cs create mode 100644 Tests/TrashService.cs.meta diff --git a/Runtime/Core/Definitions/RealMethodNames.cs b/Runtime/Core/Definitions/RealMethodNames.cs index 0d2338a..e1015a0 100644 --- a/Runtime/Core/Definitions/RealMethodNames.cs +++ b/Runtime/Core/Definitions/RealMethodNames.cs @@ -17,6 +17,10 @@ public static class MessageNames // Save public const string Save = "OnSave"; public const string Load = "Onload"; + + // Register + public const string Register = "OnRegister"; + public const string Unregister = "OnUnregister"; } public static class FunctionNames diff --git a/Runtime/Core/Definitions/Save&File.cs b/Runtime/Core/Definitions/Save&File.cs index d1d0adc..491dae5 100644 --- a/Runtime/Core/Definitions/Save&File.cs +++ b/Runtime/Core/Definitions/Save&File.cs @@ -68,11 +68,6 @@ public interface ISaveSystem /// IFile MainSaveFile { get; } } - public interface ISave - { - void OnLoaded(); - void OnSaved(); - } /// /// this is UniqueAsset that implement ISaveFile Interface with some Editor Function /// for testing save and load diff --git a/Runtime/Library/Extension/Object.cs b/Runtime/Library/Extension/Object.cs index fd111cc..9a8cbed 100644 --- a/Runtime/Library/Extension/Object.cs +++ b/Runtime/Library/Extension/Object.cs @@ -213,13 +213,41 @@ public static void InvokeLoadEvent(this object obj, SendMessageOptions option = obj.SendMessage(MessageNames.Load, option); } } - public static void SendMessage(this object so, string methodName, SendMessageOptions option) + public static void InvokeReqisterEvent(this object obj, SendMessageOptions option = SendMessageOptions.DontRequireReceiver) { - so.SendMessage(methodName, null, option); + if (obj is IRegistrable provider) + { + provider.OnRegister(); + } + else + { + obj.SendMessage(MessageNames.Register, option); + } + } + public static void InvokeUnreqisterEvent(this object obj, SendMessageOptions option = SendMessageOptions.DontRequireReceiver) + { + if (obj is IRegistrable provider) + { + provider.OnUnregister(); + } + else + { + obj.SendMessage(MessageNames.Unregister, option); + } + } + public static void SendMessage(this object obj, string methodName, SendMessageOptions option) + { + obj.SendMessage(methodName, null, option); } public static void SendMessage(this object obj, string methodName, object parameter, SendMessageOptions options) { - var method = obj.GetType().GetMethod(methodName, + if (obj is Component comp) + { + comp.SendMessage(methodName, parameter, options); + return; + } + + var method = obj.GetType().GetMethodInHierarchy(methodName, BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.Static); if (method != null) @@ -380,5 +408,9 @@ public static bool HasNameID(this object obj, string NameID) return false; } } + public static void Destroy(this System.IDisposable provider) + { + + } } } \ No newline at end of file diff --git a/Runtime/Library/Extension/Type.cs b/Runtime/Library/Extension/Type.cs index 7479786..b9bf5ad 100644 --- a/Runtime/Library/Extension/Type.cs +++ b/Runtime/Library/Extension/Type.cs @@ -1,4 +1,5 @@ using System; +using System.Reflection; using UnityEngine; namespace RealMethod @@ -24,5 +25,30 @@ public static object CreateInstance(this Type type) return Activator.CreateInstance(type); } } + public static MethodInfo GetMethodInHierarchy(this Type type, string methodName, BindingFlags flags = BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.Static | BindingFlags.DeclaredOnly) + { + while (type != null) + { + var method = type.GetMethod(methodName, flags); + if (method != null) + return method; + + type = type.BaseType; + } + + return null; + } + public static bool HasImplementInterface(this Type type) + { + var interfaces = type.GetInterfaces(); + foreach (var i in interfaces) + { + // Only interfaces derived from Interface + if (typeof(T).IsAssignableFrom(i)) + return true; + } + return false; + } + } } \ No newline at end of file diff --git a/Runtime/Library/Interfaces/Save.cs b/Runtime/Library/Interfaces/Save.cs new file mode 100644 index 0000000..f3a1aab --- /dev/null +++ b/Runtime/Library/Interfaces/Save.cs @@ -0,0 +1,8 @@ +namespace RealMethod +{ + public interface ISave + { + void OnLoaded(); + void OnSaved(); + } +} \ No newline at end of file diff --git a/Runtime/Library/Interfaces/Save.cs.meta b/Runtime/Library/Interfaces/Save.cs.meta new file mode 100644 index 0000000..9ed3476 --- /dev/null +++ b/Runtime/Library/Interfaces/Save.cs.meta @@ -0,0 +1,2 @@ +fileFormatVersion: 2 +guid: a7ae0ff1d5367584fa20e0d798e23445 \ No newline at end of file diff --git a/Runtime/ReadySet/Components/Method/RuleEvent.cs b/Runtime/ReadySet/Components/Method/RuleEvent.cs index b08329f..8056671 100644 --- a/Runtime/ReadySet/Components/Method/RuleEvent.cs +++ b/Runtime/ReadySet/Components/Method/RuleEvent.cs @@ -14,12 +14,13 @@ public sealed class RuleEvent : MonoBehaviour [SerializeField] private UnityEvent RuleEffect; - private RuleService ruleServ; + private IRuleService ruleServ; public bool IsServiceRegistered => ruleServ != null; private void Awake() { - if (Game.TryGetService(out ruleServ)) + ruleServ = Game.GetService(); + if (ruleServ != null) { if (ruleServ.IsValid(Rule)) { diff --git a/Runtime/ReadySet/Essentials.meta b/Runtime/ReadySet/Essentials.meta deleted file mode 100644 index 3508edf..0000000 --- a/Runtime/ReadySet/Essentials.meta +++ /dev/null @@ -1,8 +0,0 @@ -fileFormatVersion: 2 -guid: c2eb30f6d9195524693f6c11671ee28b -folderAsset: yes -DefaultImporter: - externalObjects: {} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Runtime/ReadySet/Presets/PoolAsset/AudioPool.cs b/Runtime/ReadySet/Presets/PoolAsset/AudioPool.cs index c78df96..62cbcc3 100644 --- a/Runtime/ReadySet/Presets/PoolAsset/AudioPool.cs +++ b/Runtime/ReadySet/Presets/PoolAsset/AudioPool.cs @@ -109,7 +109,7 @@ private AudioClip GetRandomClip() // Base PoolAsset Methods protected override void OnRootInitiate(Transform Root) { - if (Game.World.TryFindManager(out AudioManager audiomanager)) + if (Game.World.TryFindGameManager(out AudioManager audiomanager)) { Root.SetParent(audiomanager.transform); } diff --git a/Runtime/ReadySet/Services/Despawn.cs b/Runtime/ReadySet/Services/Despawn.cs index 468f6a8..189286e 100644 --- a/Runtime/ReadySet/Services/Despawn.cs +++ b/Runtime/ReadySet/Services/Despawn.cs @@ -142,27 +142,27 @@ string IInspectorInfo.GetInfo() // UI - public static bool Widget(string Name, Object despawner = null, bool debug = true) + public static bool Widget(string Name, Object despawner = null, bool debug = true, ScopeTarget Scope = ScopeTarget.Both) { - if (Get() == null) + if (Get(Scope) == null) { if (debug) Debug.LogWarning("Despawn UIManager is not available."); return false; } - return Get().RemoveLayer(Name, despawner); + return Get(Scope).RemoveLayer(Name, despawner); } - public static bool Widget(MonoBehaviour Comp, Object despawner = null, bool debug = true) + public static bool Widget(MonoBehaviour Comp, Object despawner = null, bool debug = true, ScopeTarget Scope = ScopeTarget.Both) { - if (Get() == null) + if (Get(Scope) == null) { if (debug) Debug.LogWarning("Despawn UIManager is not available."); return false; } - return Get().RemoveLayer(Comp, despawner); + return Get(Scope).RemoveLayer(Comp, despawner); } // Prefab @@ -231,6 +231,16 @@ public static bool Asset(T target, Object despawner = null, bool debug = true return false; } } + public static bool Service(ScopeTarget Scope = ScopeTarget.Game) where T : GameService, new() + { + if (GetScope(Scope).TryFindModule(out T result)) + { + result.InvokeUnreqisterEvent(); + return GetScope(Scope).RemoveModule(); + } + + return false; + } // Task @@ -269,5 +279,19 @@ public static bool Haptic(IHapticProvider provider, bool debug = true) } + + private static Scope GetScope(ScopeTarget Scope) + { + switch (Scope) + { + case ScopeTarget.Game: + return Game.Instance; + case ScopeTarget.World: + return Game.World; + default: + Debug.LogWarning("Your ScopeTarget should be World or Game"); + return null; + } + } } } \ No newline at end of file diff --git a/Runtime/ReadySet/Services/Spawan.cs b/Runtime/ReadySet/Services/Spawan.cs index 061dc43..6a956cf 100644 --- a/Runtime/ReadySet/Services/Spawan.cs +++ b/Runtime/ReadySet/Services/Spawan.cs @@ -144,25 +144,25 @@ string IInspectorInfo.GetInfo() #endif // UI - public static T Widget(string Name, Object spawner = null) where T : MonoBehaviour + public static T Widget(string Name, Object spawner = null, ScopeTarget Scope = ScopeTarget.Both) where T : MonoBehaviour { - return Get().CreateLayer(Name, spawner); + return Get(Scope).CreateLayer(Name, spawner); } - public static T Widget(VisualTreeAsset UIAsset, string Name, Object spawner = null) where T : MonoBehaviour + public static T Widget(VisualTreeAsset UIAsset, string Name, Object spawner = null, ScopeTarget Scope = ScopeTarget.Both) where T : MonoBehaviour { - return Get().CreateLayer(Name, UIAsset, spawner); + return Get(Scope).CreateLayer(Name, UIAsset, spawner); } - public static GameObject Widget(UPrefab Prefab, string Name, Object spawner = null) + public static GameObject Widget(UPrefab Prefab, string Name, Object spawner = null, ScopeTarget Scope = ScopeTarget.Both) { - return Get().AddLayer(Name, Prefab, spawner); + return Get(Scope).AddLayer(Name, Prefab, spawner); } - public static T Widget(UPrefab Prefab, string Name, Object spawner = null) where T : MonoBehaviour + public static T Widget(UPrefab Prefab, string Name, Object spawner = null, ScopeTarget Scope = ScopeTarget.Both) where T : MonoBehaviour { - return Get().AddLayer(Name, Prefab, spawner); + return Get(Scope).AddLayer(Name, Prefab, spawner); } - public static UIDocument UIDoc(string Name, VisualTreeAsset UIAsset) + public static UIDocument UIDoc(string Name, VisualTreeAsset UIAsset, ScopeTarget Scope = ScopeTarget.Both) { - return Get().CreateLayer(Name, UIAsset); + return Get(Scope).CreateLayer(Name, UIAsset); } // Screen @@ -534,9 +534,9 @@ public static EffectPlayer Effect(EPrefab prefab, Transform parent, Object spawn } // Haptic - public static IHapticProvider Haptic(HapticConfig config) + public static IHapticProvider Haptic(HapticConfig config, ScopeTarget Scope = ScopeTarget.Both) { - return Get().Produce(config); + return Get(Scope).Produce(config); } // Particle @@ -617,7 +617,17 @@ public static PrimitiveAsset Asset(System.Type type, Object spawner = null) return target; } - public static T Service(System.Type ServiceType) where T : IService + public static bool Service(ScopeTarget Scope = ScopeTarget.Game) where T : GameService, new() + { + T newModule = GetScope(Scope).AddModule(); + if (newModule != null) + { + newModule.InvokeReqisterEvent(); + return true; + } + return false; + } + public static T Service(System.Type ServiceType, ScopeTarget Scope = ScopeTarget.Game) where T : IService { if (ServiceType == null) { @@ -625,23 +635,13 @@ public static T Service(System.Type ServiceType) where T : IService return default; } - bool result = false; - var interfaces = ServiceType.GetInterfaces(); - foreach (var i in interfaces) - { - // Only interfaces derived from Interface - if (typeof(IService).IsAssignableFrom(i)) - result = true; - } - - if (result == false) + if (!ServiceType.HasImplementInterface()) { Debug.LogWarning($" {ServiceType.Name}: has not implement any IService."); return default; } - // Can Select Scope - GameModule newModule = Game.Instance.AddModule(ServiceType); + GameModule newModule = GetScope(Scope).AddModule(ServiceType); if (newModule != null) { newModule.InvokeReqisterEvent(); @@ -653,6 +653,20 @@ public static T Service(System.Type ServiceType) where T : IService return default; } + public static J Service(ScopeTarget Scope = ScopeTarget.Game) where T : GameService, new() where J : IService + { + T newModule = GetScope(Scope).AddModule(); + if (newModule != null) + { + newModule.InvokeReqisterEvent(); + if (newModule is J provider) + { + return provider; + } + } + return default; + } + // Task public static T Task(F Task, bool AutoStart = false) where T : IHandle where F : class @@ -703,6 +717,21 @@ public static AudioSource Audio(AudioClip clip) return source; } + + + private static Scope GetScope(ScopeTarget Scope) + { + switch (Scope) + { + case ScopeTarget.Game: + return Game.Instance; + case ScopeTarget.World: + return Game.World; + default: + Debug.LogWarning("Your ScopeTarget should be World or Game"); + return null; + } + } } } diff --git a/Tests/TrashService.cs b/Tests/TrashService.cs new file mode 100644 index 0000000..f43ec2d --- /dev/null +++ b/Tests/TrashService.cs @@ -0,0 +1,205 @@ + + + + + + + +/// +/// List of runtime-registered instances owned by the game. +/// +// private readonly Dictionary Services = new(); + +/// +/// Returns true if the Game system has one or more registered services; +/// otherwise, returns false. +/// +// public static bool HasService => Instance.Services.Count > 0; + + + + + + + +/// +/// Registers a service instance of type in the service container. +/// +/// +/// The type of the service to register. Must implement . +/// +/// +/// The service instance to register. +/// +/// +/// Optional object providing context or ownership information for the registration. +/// Passed to . +/// +/// +/// true if the service was successfully registered; +/// false if a service of the same type is already registered. +/// +/// +/// This method prevents duplicate registrations. If a service of the same type +/// is already registered, an error is logged and the method returns false. +/// Upon successful registration, is invoked. +/// +// public static bool Register(T service, object author = null) where T : IService +// { +// Type TypeService = typeof(T); + +// if (Instance.Services.ContainsKey(TypeService)) +// { +// Debug.LogError($"IService {TypeService} already registered."); +// return false; +// } + +// service.OnRegister(author); +// Instance.Services[TypeService] = service; +// return true; + +// } +/// +/// Checks whether a service of type is currently registered +/// in the Service Locator. +/// +/// +/// The type of service to check. The type must implement . +/// +/// +/// true if a service of type is registered; otherwise false. +/// +// public static bool IsRegistered() where T : IService +// { +// return Instance.Services.ContainsKey(typeof(T)); +// } +/// +/// Remove service instance +/// +/// The object type that implement 'IService' +// public static bool Unregister(object author = null) where T : IService +// { +// Type TypeService = typeof(T); + +// if (Instance.Services.ContainsKey(TypeService)) +// { +// Instance.Services[TypeService].OnUnregister(author); +// return Instance.Services.Remove(TypeService); ; +// } +// else +// { +// Debug.LogWarning($"IService {TypeService} Not found."); +// return false; +// } +// } +/// +/// Retrieves the service instance of type if available. +/// +/// IService type to retrieve. +/// The service instance of type , or null if not found. +// public static T GetService() where T : IService +// { +// Type TypeService = typeof(T); + +// if (Instance.Services.TryGetValue(TypeService, out var provider)) +// return (T)provider.Self; + +// throw new Exception($"Service {TypeService} not registered."); +// } +/// +/// Attempts to find a service of type . +/// +/// IService type to find. +/// Out parameter that receives the service if found. +/// true if the service was found; otherwise false. +// public static bool TryGetService(out T service) where T : IService +// { +// if (Instance.Services.TryGetValue(typeof(T), out var provider)) +// { +// service = (T)provider.Self; +// return true; +// } + +// service = default; +// return false; +// } +/// +/// Clear all services in Game +/// +// public static void ClearService() +// { +// foreach (var service in Instance.Services.Values) +// { +// service.OnUnregister(null); +// } +// Instance.Services.Clear(); +// } + + + +// private void Notify_OnWorldInitiate(World NewWorld) +// { +// foreach (var service in Services) +// { +// service.Value.OnWorldChanging(World, NewWorld); +// } +// World = NewWorld; +// OnWorldChanged(World); +// } + + + + + + + + + + + + +/// +/// Base abstract class implementing . +/// Provides a framework for derived services to handle lifecycle events. +/// +// public abstract class Service : IService +// { +// // Implement IService Interface +// /// +// /// Called when the service starts. Must be implemented by derived classes. +// /// +// /// The object responsible for creating the service. +// public abstract void OnRegister(object author); +// /// +// /// Called when a new world or environment is initialized. +// /// Must be implemented by derived classes. +// /// +// public abstract void OnWorldChanging(World Previous, World New); +// /// +// /// Called when the service ends or is deleted. +// /// Must be implemented by derived classes. +// /// +// /// The object responsible for deleting the service. +// public abstract void OnUnregister(object author); +// #if UNITY_EDITOR +// string IService.GetInspectorInfo() +// { +// return GetDisplayInfo(); +// } +// protected virtual string GetDisplayInfo() +// { +// return GetType().ToString() + ": "; +// } +// #endif + +// } + + + +/// + /// Returns the object instance that implements this service. + /// + // object Self => this; + + + diff --git a/Tests/TrashService.cs.meta b/Tests/TrashService.cs.meta new file mode 100644 index 0000000..8bf822d --- /dev/null +++ b/Tests/TrashService.cs.meta @@ -0,0 +1,2 @@ +fileFormatVersion: 2 +guid: f38c2ceee0a62d040a2db048084faf4c \ No newline at end of file From 3f94064d227c278e457afe4e173775af95701105 Mon Sep 17 00:00:00 2001 From: Alijimpa Date: Sat, 9 May 2026 09:14:34 +0330 Subject: [PATCH 192/204] Fix Cleanup refrence for Susbseyste, --- Runtime/Core/Architecture/Game.cs | 5 +- Runtime/Core/Framework/GameSubsystem.cs | 30 ++++++++++-- Runtime/Core/Framework/Kernel.cs | 47 ++++++++++++++++--- .../Subsystems/DependencyInjection.cs | 12 +++-- .../Framework/Subsystems/ServiceLocator.cs | 9 +++- 5 files changed, 85 insertions(+), 18 deletions(-) diff --git a/Runtime/Core/Architecture/Game.cs b/Runtime/Core/Architecture/Game.cs index 807f7a1..00c650f 100644 --- a/Runtime/Core/Architecture/Game.cs +++ b/Runtime/Core/Architecture/Game.cs @@ -913,11 +913,12 @@ private void Notify_OnWorldInitiate(World NewWorld) OnWorldChanged(World); } /// - /// Handles application quit events: unbinds world callbacks, deletes services and invokes . + /// Handles application quit events: unbinds world callbacks, deletes modules and invokes . /// private void Notify_OnGameQuit() { Application.quitting -= Notify_OnGameQuit; + OnGameClosed(); CloseScope(); ((IDisposable)Bridge).Dispose(); Bridge = null; @@ -931,7 +932,7 @@ private void Notify_OnGameQuit() GC.WaitForPendingFinalizers(); GC.Collect(); #endif - OnGameClosed(); + ClearKernel(); } diff --git a/Runtime/Core/Framework/GameSubsystem.cs b/Runtime/Core/Framework/GameSubsystem.cs index 12987f7..ea7b237 100644 --- a/Runtime/Core/Framework/GameSubsystem.cs +++ b/Runtime/Core/Framework/GameSubsystem.cs @@ -3,9 +3,14 @@ namespace RealMethod { - public abstract class GameSubsystem : IInspectorInfo + public interface IBootstrap { - public class ShareData : IInspectorInfo + void Setup(GameSubsystem.ShareData data); + } + + public abstract class GameSubsystem : IInspectorInfo, IDisposable, IBootstrap + { + public class ShareData : IInspectorInfo, IDisposable { public Dictionary> Repository { get; } @@ -14,6 +19,13 @@ public ShareData(int prewarm) Repository = new Dictionary>(prewarm); } + + // Implement IDisposable Interface + void IDisposable.Dispose() + { + Repository.Clear(); + } + #if UNITY_EDITOR string IInspectorInfo.GetInfo() { @@ -24,11 +36,23 @@ string IInspectorInfo.GetInfo() protected ShareData Data { get; private set; } - public GameSubsystem(ShareData data) + // Implement IBootstrap Interface + void IBootstrap.Setup(ShareData data) { Data = data; + OnBegin(); + } + // Implement IDisposable Interface + void IDisposable.Dispose() + { + OnEnd(); + Data = null; } + protected abstract void OnBegin(); + protected abstract void OnEnd(); + + #if UNITY_EDITOR string IInspectorInfo.GetInfo() { diff --git a/Runtime/Core/Framework/Kernel.cs b/Runtime/Core/Framework/Kernel.cs index c42c97b..33d5a07 100644 --- a/Runtime/Core/Framework/Kernel.cs +++ b/Runtime/Core/Framework/Kernel.cs @@ -23,23 +23,58 @@ namespace RealMethod public abstract class Kernel : MonoBehaviour { private static readonly GameSubsystem.ShareData _rpository = new GameSubsystem.ShareData(10); - private static Lazy _serviceLocator = new Lazy(() => new ServiceLocator(_rpository)); - private static Lazy _dependencyInjection = new Lazy(() => new DependencyInjection(_rpository)); + private static ServiceLocator _serviceLocator; + private static DependencyInjection _dependencyInjection; // GameModules - protected static ServiceLocator Services => _serviceLocator.Value; - protected static DependencyInjection DInjection => _dependencyInjection.Value; - + protected static ServiceLocator Services + { + get + { + if (_serviceLocator == null) + { + _serviceLocator = new ServiceLocator(); + ((IBootstrap)_serviceLocator).Setup(_rpository); + } + return _serviceLocator; + } + } + protected static DependencyInjection DInjection + { + get + { + if (_dependencyInjection == null) + { + _dependencyInjection = new DependencyInjection(); + ((IBootstrap)_serviceLocator).Setup(_rpository); + } + return _dependencyInjection; + } + } + protected static void ClearKernel() + { + if (_serviceLocator != null) + { + ((IDisposable)_serviceLocator).Dispose(); + _serviceLocator = null; + } + if (_dependencyInjection != null) + { + ((IDisposable)_dependencyInjection).Dispose(); + _dependencyInjection = null; + } + ((IDisposable)_rpository).Dispose(); + } #if UNITY_EDITOR public virtual IInspectorInfo[] GetAllInfo() { - return new IInspectorInfo[3] { _rpository ,Services, DInjection }; + return new IInspectorInfo[3] { _rpository, Services, DInjection }; } #endif } diff --git a/Runtime/Core/Framework/Subsystems/DependencyInjection.cs b/Runtime/Core/Framework/Subsystems/DependencyInjection.cs index b982891..4c2c690 100644 --- a/Runtime/Core/Framework/Subsystems/DependencyInjection.cs +++ b/Runtime/Core/Framework/Subsystems/DependencyInjection.cs @@ -16,11 +16,17 @@ public sealed class DependencyInjection : GameSubsystem private readonly object _lock = new(); private Dictionary> bindings => Data.Repository; - public DependencyInjection(ShareData data) : base(data) + + // GameSubsystem Methods + protected override void OnBegin() + { + } + protected override void OnEnd() { } + /// /// Registers the specified instance as a dependency in the DI container. /// After registration, any object resolving or being injected @@ -42,7 +48,6 @@ public static T Resolve() { return (T)Resolve(typeof(T)); } - public static object Resolve(Type type) { // If already registered, return directly @@ -74,7 +79,6 @@ public static object Resolve(Type type) throw new InvalidOperationException($"Cannot resolve type {type.Name}: no registered instance or injectable constructor."); } - private static ConstructorInfo GetInjectableConstructor(Type type) { // Check if any constructor has [Inject] @@ -88,7 +92,6 @@ private static ConstructorInfo GetInjectableConstructor(Type type) .OrderByDescending(c => c.GetParameters().Length) .FirstOrDefault(); } - /// /// Injects all fields, properties, and methods marked with [Inject]. /// Works for MonoBehaviours, ScriptableObjects, and normal classes. @@ -131,7 +134,6 @@ public static void Inject(object target) - public TInterface Resolve2() { lock (_lock) diff --git a/Runtime/Core/Framework/Subsystems/ServiceLocator.cs b/Runtime/Core/Framework/Subsystems/ServiceLocator.cs index 2721d05..d2fef6a 100644 --- a/Runtime/Core/Framework/Subsystems/ServiceLocator.cs +++ b/Runtime/Core/Framework/Subsystems/ServiceLocator.cs @@ -13,9 +13,14 @@ public sealed class ServiceLocator : GameSubsystem private readonly object _lock = new(); private Dictionary> _services => Data.Repository; - public ServiceLocator(ShareData data) : base(data) + // GameSubsystem Methods + protected override void OnBegin() { } + protected override void OnEnd() + { + } + /// /// Register a service instance under its concrete or interface type T. @@ -77,7 +82,7 @@ public void Register(object service, Type type = null, bool overwrite = false) /// /// Register only if no live instance is currently registered for T. /// - public void RegisterIfAbsent(T service)where T : class + public void RegisterIfAbsent(T service) where T : class { if (service == null) throw new ArgumentNullException(nameof(service)); From 79272f6faa6c96bc662f1938b702dd045b33598c Mon Sep 17 00:00:00 2001 From: Alijimpa Date: Sat, 9 May 2026 13:23:49 +0330 Subject: [PATCH 193/204] Implement DInjection and Feature Defenation --- Runtime/Core/Architecture/Game.cs | 15 +++ Runtime/Core/Definitions/Feature.cs | 8 ++ Runtime/Core/Definitions/Feature.cs.meta | 2 + Runtime/Core/Framework/GameSubsystem.cs | 2 +- Runtime/Core/Framework/Kernel.cs | 24 +++- .../Subsystems/DependencyInjection.cs | 114 ++++++++---------- 6 files changed, 94 insertions(+), 71 deletions(-) create mode 100644 Runtime/Core/Definitions/Feature.cs create mode 100644 Runtime/Core/Definitions/Feature.cs.meta diff --git a/Runtime/Core/Architecture/Game.cs b/Runtime/Core/Architecture/Game.cs index 00c650f..bde9223 100644 --- a/Runtime/Core/Architecture/Game.cs +++ b/Runtime/Core/Architecture/Game.cs @@ -359,6 +359,21 @@ public static T CastWorld() where T : class } } /// + /// + /// + public static void Inject(object target) + { + DInjection.Inject(target); + } + public static void Enable(F instance, bool overwrite = false) where F : IFeature + { + DInjection.Register(instance, overwrite); + } + public static bool Disable() where F : IFeature + { + return DInjection.Unregister(); + } + /// /// Retrieves the service instance of type if available. /// /// IService type to retrieve. diff --git a/Runtime/Core/Definitions/Feature.cs b/Runtime/Core/Definitions/Feature.cs new file mode 100644 index 0000000..c363f02 --- /dev/null +++ b/Runtime/Core/Definitions/Feature.cs @@ -0,0 +1,8 @@ +namespace RealMethod +{ + public interface IFeature + { + + } + +} \ No newline at end of file diff --git a/Runtime/Core/Definitions/Feature.cs.meta b/Runtime/Core/Definitions/Feature.cs.meta new file mode 100644 index 0000000..370e684 --- /dev/null +++ b/Runtime/Core/Definitions/Feature.cs.meta @@ -0,0 +1,2 @@ +fileFormatVersion: 2 +guid: 37c641f6b55f84749a203eaf44e249b8 \ No newline at end of file diff --git a/Runtime/Core/Framework/GameSubsystem.cs b/Runtime/Core/Framework/GameSubsystem.cs index ea7b237..e582ba3 100644 --- a/Runtime/Core/Framework/GameSubsystem.cs +++ b/Runtime/Core/Framework/GameSubsystem.cs @@ -10,7 +10,7 @@ public interface IBootstrap public abstract class GameSubsystem : IInspectorInfo, IDisposable, IBootstrap { - public class ShareData : IInspectorInfo, IDisposable + public sealed class ShareData : IInspectorInfo, IDisposable { public Dictionary> Repository { get; } diff --git a/Runtime/Core/Framework/Kernel.cs b/Runtime/Core/Framework/Kernel.cs index 33d5a07..9df3f20 100644 --- a/Runtime/Core/Framework/Kernel.cs +++ b/Runtime/Core/Framework/Kernel.cs @@ -22,12 +22,23 @@ namespace RealMethod /// public abstract class Kernel : MonoBehaviour { - private static readonly GameSubsystem.ShareData _rpository = new GameSubsystem.ShareData(10); + private static GameSubsystem.ShareData _rpository; private static ServiceLocator _serviceLocator; private static DependencyInjection _dependencyInjection; // GameModules + private static GameSubsystem.ShareData Repo + { + get + { + if (_rpository == null) + { + _rpository = new GameSubsystem.ShareData(10); + } + return _rpository; + } + } protected static ServiceLocator Services { get @@ -35,7 +46,7 @@ protected static ServiceLocator Services if (_serviceLocator == null) { _serviceLocator = new ServiceLocator(); - ((IBootstrap)_serviceLocator).Setup(_rpository); + ((IBootstrap)_serviceLocator).Setup(Repo); } return _serviceLocator; } @@ -47,7 +58,7 @@ protected static DependencyInjection DInjection if (_dependencyInjection == null) { _dependencyInjection = new DependencyInjection(); - ((IBootstrap)_serviceLocator).Setup(_rpository); + ((IBootstrap)_dependencyInjection).Setup(Repo); } return _dependencyInjection; } @@ -66,7 +77,12 @@ protected static void ClearKernel() ((IDisposable)_dependencyInjection).Dispose(); _dependencyInjection = null; } - ((IDisposable)_rpository).Dispose(); + if (_rpository != null) + { + ((IDisposable)_rpository).Dispose(); + _rpository = null; + } + } diff --git a/Runtime/Core/Framework/Subsystems/DependencyInjection.cs b/Runtime/Core/Framework/Subsystems/DependencyInjection.cs index 4c2c690..234514f 100644 --- a/Runtime/Core/Framework/Subsystems/DependencyInjection.cs +++ b/Runtime/Core/Framework/Subsystems/DependencyInjection.cs @@ -2,15 +2,10 @@ using System.Collections.Generic; using System.Linq; using System.Reflection; +using UnityEngine; namespace RealMethod { - public interface IFeature - { - - } - - public sealed class DependencyInjection : GameSubsystem { private readonly object _lock = new(); @@ -32,71 +27,59 @@ protected override void OnEnd() /// After registration, any object resolving or being injected /// with the same type will receive this instance. /// - public void Bind(TInterface instance) + public void Register(T instance, bool overwrite = false) { lock (_lock) { - bindings[typeof(TInterface)] = new WeakReference(instance); - } - } + Type objectType = typeof(T); + if (bindings.TryGetValue(objectType, out var weak)) + { + if (!weak.TryGetTarget(out _)) + { + bindings[objectType] = new WeakReference(instance); + return; + } - /// - /// Resolves a dependency of the specified type. - /// Automatically constructs non-MonoBehaviour classes using constructor injection. - /// - public static T Resolve() - { - return (T)Resolve(typeof(T)); - } - public static object Resolve(Type type) - { - // If already registered, return directly - // if (bindings.TryGetValue(type, out var existing)) - // return existing; + if (overwrite) + { + bindings[objectType] = new WeakReference(instance); + return; + } - // Handle constructor injection - var ctor = GetInjectableConstructor(type); - if (ctor != null) - { - var parameters = ctor.GetParameters(); - var args = parameters.Select(p => Resolve(p.ParameterType)).ToArray(); - var instance = Activator.CreateInstance(type, args); + throw new InvalidOperationException( + $"Instance of type {objectType.Name} is already registered and still alive."); + } - // Optionally inject remaining [Inject] fields - Inject(instance); - return instance; + bindings[objectType] = new WeakReference(instance); } - - // Fallback for parameterless types - var parameterless = type.GetConstructor(Type.EmptyTypes); - if (parameterless != null) + } + public bool Unregister() + { + var type = typeof(T); + lock (_lock) { - var instance = Activator.CreateInstance(type); - Inject(instance); - return instance; + return Unregister(type); } - - throw new InvalidOperationException($"Cannot resolve type {type.Name}: no registered instance or injectable constructor."); } - private static ConstructorInfo GetInjectableConstructor(Type type) + public bool Unregister(Type type) { - // Check if any constructor has [Inject] - var markedCtor = type.GetConstructors() - .FirstOrDefault(c => Attribute.IsDefined(c, typeof(InjectAttribute))); - if (markedCtor != null) - return markedCtor; - - // Otherwise, pick the one with most parameters for best DI heuristics - return type.GetConstructors() - .OrderByDescending(c => c.GetParameters().Length) - .FirstOrDefault(); + lock (_lock) + { + if (bindings.ContainsKey(type)) + { + return bindings.Remove(type); + } + return false; + } } + + /// /// Injects all fields, properties, and methods marked with [Inject]. /// Works for MonoBehaviours, ScriptableObjects, and normal classes. /// - public static void Inject(object target) + public void Inject(object target) { var type = target.GetType(); @@ -133,22 +116,21 @@ public static void Inject(object target) } - - public TInterface Resolve2() + private object Resolve(Type type) { - lock (_lock) + // If already registered, return directly + if (bindings != null) { - Type type = typeof(TInterface); - if (bindings.ContainsKey(type)) + if (bindings.TryGetValue(type, out var weak)) { - if (bindings[type].TryGetTarget(out object target)) - { - return (TInterface)target; - } - bindings.Remove(type); + if (weak.TryGetTarget(out object existing)) + return existing; } - return default; + } + + Debug.LogError($"Cannot resolve type {type.Name}: no registered instance or injectable constructor."); + return null; } #if UNITY_EDITOR @@ -158,7 +140,7 @@ protected override string GetInspectorInfor() for (int i = 0; i < bindings.Count; i++) { var type = bindings.GetKey(i); - if (type is IFeature) + if (typeof(IFeature).IsAssignableFrom(type)) { var weakRef = bindings.GetValue(i); if (weakRef.TryGetTarget(out var target)) From cc25e40b7f21c799a97301d1077fe9f777d0a645 Mon Sep 17 00:00:00 2001 From: Alijimpa Date: Sat, 9 May 2026 13:25:36 +0330 Subject: [PATCH 194/204] Write cummery for my Methods --- Runtime/Core/Architecture/Game.cs | 16 +++++++++++++++- 1 file changed, 15 insertions(+), 1 deletion(-) diff --git a/Runtime/Core/Architecture/Game.cs b/Runtime/Core/Architecture/Game.cs index bde9223..2e6e526 100644 --- a/Runtime/Core/Architecture/Game.cs +++ b/Runtime/Core/Architecture/Game.cs @@ -359,16 +359,30 @@ public static T CastWorld() where T : class } } /// - /// + /// Injects dependencies into the specified target object using the internal dependency injection system. /// + /// The object whose dependencies should be injected. public static void Inject(object target) { DInjection.Inject(target); } + /// + /// Registers and enables a feature instance in the dependency injection container. + /// + /// Type of the feature implementing . + /// The feature instance to register. + /// + /// If true, replaces an existing registered feature of the same type; otherwise keeps the existing one. + /// public static void Enable(F instance, bool overwrite = false) where F : IFeature { DInjection.Register(instance, overwrite); } + /// + /// Disables and unregisters a feature of the specified type from the dependency injection container. + /// + /// Type of the feature implementing . + /// True if the feature was successfully removed; otherwise false. public static bool Disable() where F : IFeature { return DInjection.Unregister(); From 281dc6a8da23912eb900d709e1b7a83b26ca8644 Mon Sep 17 00:00:00 2001 From: Alijimpa Date: Sat, 9 May 2026 16:22:51 +0330 Subject: [PATCH 195/204] REfine SaveService and seperate some defenation --- .../Pattern/Inspectors/SaveManagerEditor.cs | 2 +- Runtime/Core/Architecture/Game.cs | 80 +++---- Runtime/Core/Definitions/File.cs | 20 ++ .../{Save&File.cs.meta => File.cs.meta} | 0 Runtime/Core/Definitions/Save&File.cs | 202 ------------------ Runtime/Core/Definitions/Systems.cs | 74 +++++-- Runtime/Library/Extension/Object.cs | 4 +- Runtime/Library/Interfaces/Damageable.cs | 2 - .../Interfaces/{Save.cs => Saveable.cs} | 2 +- .../{Save.cs.meta => Saveable.cs.meta} | 0 .../{Initializable.cs => Spawnable.cs} | 0 ...nitializable.cs.meta => Spawnable.cs.meta} | 0 .../Library/SharedScripts/Structs/Storage.cs | 12 +- Runtime/Pattern/Assets/SaveAsset.cs | 143 +++++++++++++ Runtime/Pattern/Assets/SaveAsset.cs.meta | 2 + Runtime/Pattern/Managers/SaveManager.cs | 58 ++--- .../ReadySet/Components/UI/UI_GameSetting.cs | 2 +- .../Toolkit/Inventory/InventorySaveFile.cs | 2 +- .../Toolkit/RPG/StatSystem/StatSaveFile.cs | 2 +- Runtime/Toolkit/Tutorial/TutorialSaveFile.cs | 2 +- .../Upgrade/Sample/ChainUpgradeMapConfig.cs | 2 +- Runtime/Toolkit/Upgrade/UpgradeSaveFile.cs | 2 +- Tests/FileManager.cs | 2 +- 23 files changed, 315 insertions(+), 300 deletions(-) create mode 100644 Runtime/Core/Definitions/File.cs rename Runtime/Core/Definitions/{Save&File.cs.meta => File.cs.meta} (100%) delete mode 100644 Runtime/Core/Definitions/Save&File.cs rename Runtime/Library/Interfaces/{Save.cs => Saveable.cs} (73%) rename Runtime/Library/Interfaces/{Save.cs.meta => Saveable.cs.meta} (100%) rename Runtime/Library/Interfaces/{Initializable.cs => Spawnable.cs} (100%) rename Runtime/Library/Interfaces/{Initializable.cs.meta => Spawnable.cs.meta} (100%) create mode 100644 Runtime/Pattern/Assets/SaveAsset.cs create mode 100644 Runtime/Pattern/Assets/SaveAsset.cs.meta diff --git a/Editor/Pattern/Inspectors/SaveManagerEditor.cs b/Editor/Pattern/Inspectors/SaveManagerEditor.cs index d73bfd8..bf3653c 100644 --- a/Editor/Pattern/Inspectors/SaveManagerEditor.cs +++ b/Editor/Pattern/Inspectors/SaveManagerEditor.cs @@ -28,7 +28,7 @@ public override void OnInspectorGUI() { for (int i = 0; i < files.Length; i++) { - EditorGUILayout.LabelField($"{i}.[{files[i].FileName}]: {files[i].FileObject.GetType()}"); + EditorGUILayout.LabelField($"{i}.[{files[i].FileName}]: {files[i].Self.GetType()}"); } } EditorGUILayout.Space(); diff --git a/Runtime/Core/Architecture/Game.cs b/Runtime/Core/Architecture/Game.cs index 2e6e526..d98f814 100644 --- a/Runtime/Core/Architecture/Game.cs +++ b/Runtime/Core/Architecture/Game.cs @@ -140,32 +140,6 @@ public static event Action OnReady /// public static event Action OnStateChanged; - - /// - /// Gets the active implementation used for saving, - /// loading, and checking file existence. This value is assigned internally - /// through CheckSaveSystem. - /// - public ISaveSystem SaveSystem - { - get - { - if (IsGameInitialized == false) - { - Debug.LogWarning("Game has not been initialized yet! You cannot call this method before initialization."); - return null; - } - - - ISaveSystem result = World.gameObject.GetComponent(); - if (result == null) - result = gameObject.GetComponentInChildren(); - - return result; - } - } - - /// /// Initializes the game singleton and core systems on subsystem registration. /// This sets up the , game , @@ -652,32 +626,62 @@ public static bool SetState(int NewState, object author) return false; } /// - /// Saves the provided file using the active implementation. + /// Saves the provided file using the active implementation. /// Logs a warning if no save system is available. /// - public static void Save() + public static void Save(bool cloude = false) { - var system = Instance.SaveSystem; - if (system == null) + IStorageService storage = GetService(); + if (storage != null) + { + storage.Save(); + } + else { Debug.LogWarning("There is not any ISaveSystem Implemntation"); - return; } - system.SaveAll(); + + if (cloude) + { + ICloudService cloudeserv = GetService(); + if (cloudeserv != null) + { + cloudeserv.Save(); + } + else + { + Debug.LogWarning("There is not any ICloudService Implemntation"); + } + } } /// - /// Loads the provided file using the active implementation. + /// Loads the provided file using the active implementation. /// Logs a warning if no save system is available. /// - public static void Load() + public static void Load(bool cloude = false) { - var system = Instance.SaveSystem; - if (system == null) + IStorageService storage = GetService(); + if (storage != null) + { + storage.Load(); + } + else { Debug.LogWarning("There is not any ISaveSystem Implemntation"); - return; } - system.LoadAll(); + + if (cloude) + { + ICloudService cloudeserv = GetService(); + if (cloudeserv != null) + { + cloudeserv.Load(); + } + else + { + Debug.LogWarning("There is not any ICloudService Implemntation"); + } + } } /// /// Quits the application. In the Unity Editor this stops play mode instead. diff --git a/Runtime/Core/Definitions/File.cs b/Runtime/Core/Definitions/File.cs new file mode 100644 index 0000000..beafc4a --- /dev/null +++ b/Runtime/Core/Definitions/File.cs @@ -0,0 +1,20 @@ +namespace RealMethod +{ + // FILE + public interface IFile : IIdentifier + { + string FileName { get; } + } + + + /// + /// this is UniqueAsset that implement ISaveFile Interface with some Editor Function + /// for testing save and load + /// + public abstract class FileAsset : UniqueAsset, IFile + { + // Implement IFile Interface + string IFile.FileName => name; + } + +} \ No newline at end of file diff --git a/Runtime/Core/Definitions/Save&File.cs.meta b/Runtime/Core/Definitions/File.cs.meta similarity index 100% rename from Runtime/Core/Definitions/Save&File.cs.meta rename to Runtime/Core/Definitions/File.cs.meta diff --git a/Runtime/Core/Definitions/Save&File.cs b/Runtime/Core/Definitions/Save&File.cs deleted file mode 100644 index 491dae5..0000000 --- a/Runtime/Core/Definitions/Save&File.cs +++ /dev/null @@ -1,202 +0,0 @@ -using UnityEditor; -using UnityEngine; - -namespace RealMethod -{ - // FILE - public interface IFile : IIdentifier - { - string FileName { get; } - object FileObject { get; } - } - public interface ISaveFile : IFile, ISave - { - void SetName(string NewName); - } - - - - // SAVE - public interface ISaveSystem - { - /// - /// Checks whether the specified file exists in the save storage. - /// - bool IsExist(IFile file); - /// - /// Saves the specified file to the save storage. - /// - void Save(IFile file); - /// - /// Loads the specified file from the save storage into memory. - /// - void Load(IFile file); - /// - /// Deletes the specified file from the save storage. - /// - void Delete(IFile file); - /// - /// Save all file or Specific file that implemented - /// - void SaveAll(); - /// - /// Load all file or specific file that implemented - /// - void LoadAll(); - /// - /// use for adding file to filelist in savemsystem. - /// if you want to use saveall or geting file with name - /// - /// target file you want adding - /// return true if can add - bool AddFile(IFile file); - /// - /// use for removing file to filelist in savesystem - /// - /// target file you want removing - /// return true if can remove - bool RemoveFile(IFile file); - /// - /// Determines whether the specified file already exists in the file list. - /// Checks by object reference unless IFile implementations override equality. - /// - /// The file instance to check. - /// True if the file is found in the list; otherwise false. - bool HasFile(IFile file); - /// - /// The file that created by savesystem for merging all file selected in sytem to one file - /// - IFile MainSaveFile { get; } - } - /// - /// this is UniqueAsset that implement ISaveFile Interface with some Editor Function - /// for testing save and load - /// - public abstract class SaveAsset : UniqueAsset, ISaveFile - { - // Implement IFile Interface - string IFile.FileName => name; - object IFile.FileObject => this; - // Implement ISave Interface - void ISave.OnLoaded() - { - OnLoaded(); - } - void ISave.OnSaved() - { - OnSaved(); - } - // Implement ISaveFile Interface - void ISaveFile.SetName(string NewName) - { - Debug.LogWarning($"Can't change Name for Asset({name}). the SaveAsset get asset name for file naming"); - } - - // Unity Method - protected virtual void OnEnable() - { -#if !UNITY_EDITOR - ISaveSystem saveSystem = Game.Instance.SaveSystem; - if (saveSystem != null) - { - if (!saveSystem.HasFile(this)) - saveSystem.AddFile(this); - } -#endif - } - protected virtual void OnDisable() - { -#if !UNITY_EDITOR - ISaveSystem saveSystem = Game.Instance.SaveSystem; - if (saveSystem != null) - { - if (saveSystem.HasFile(this)) - saveSystem.RemoveFile(this); - } - else - { - Debug.LogError("Can't find SaveSystem"); - } -#endif - } - protected virtual void Reset() - { -#if UNITY_EDITOR - ISaveSystem saveSystem = Game.Instance.SaveSystem; - if (saveSystem != null) - { - if (!saveSystem.HasFile(this)) - saveSystem.AddFile(this); - } -#endif - } - - protected abstract void OnLoaded(); - protected abstract void OnSaved(); - - -#if UNITY_EDITOR - public override bool AutoReset(PlayModeStateChange state) - { - if (state == PlayModeStateChange.EnteredPlayMode) - return true; - return base.AutoReset(state); - } - [ContextMenu("Save")] - private void Editor_SaveSelf() - { - var manager = FindFirstObjectByType(); - if (manager != null) - { - manager.Save(this); - } - else - { - Debug.LogError("No SaveManager found in the scene."); - } - } - [ContextMenu("Load")] - private void Editor_LoadSelf() - { - var manager = FindFirstObjectByType(); - if (manager != null) - { - manager.Load(this); - } - else - { - Debug.LogError("No SaveManager found in the scene."); - } - } - [ContextMenu("Delete")] - private void Editor_Delete() - { - var manager = FindFirstObjectByType(); - if (manager != null) - { - manager.Delete(this); - } - else - { - Debug.LogError("No SaveManager found in the scene."); - } - } - [ContextMenu("IsExist")] - private void Editor_IsExist() - { - var manager = FindFirstObjectByType(); - if (manager != null) - { - Debug.Log($"[{name}] IsExist: {manager.IsExist(this)}"); - } - else - { - Debug.LogError("No SaveManager found in the scene."); - } - } -#endif - - - } - -} \ No newline at end of file diff --git a/Runtime/Core/Definitions/Systems.cs b/Runtime/Core/Definitions/Systems.cs index 3fc1f58..3b0fdd5 100644 --- a/Runtime/Core/Definitions/Systems.cs +++ b/Runtime/Core/Definitions/Systems.cs @@ -1,19 +1,24 @@ namespace RealMethod { - public interface IAnalyticsService + public interface IAnalyticsService : IService { void Track(string eventName, params object[] arguments); void LevelStart(int levelIndex); void LevelComplete(int levelIndex); void Error(string message, string stacktrace = ""); } - public interface ICloudService + public interface ISaveService : IService + { + void Load(); + void Save(); + } + public interface ICloudService : ISaveService { void Save(object data); void Load(System.Action onLoaded); void Sync(); } - public interface IAuthService + public interface IAuthService : IService { void LoginGuest(); void LoginGoogle(); @@ -21,55 +26,94 @@ public interface IAuthService void Logout(); string GetUserId(); } - public interface ILeaderboardService + public interface ILeaderboardService : IService { void Submit(int score); void GetTop(int count, System.Action onResult); void GetAroundPlayer(System.Action onResult); } - public interface IRemoteConfigService + public interface IRemoteConfigService : IService { void Refresh(System.Action onComplete = null); T Get(string key, T defaultValue = default); } - public interface ILogService + public interface ILogService : IService { void Info(string message); void Warning(string message); void Error(string message); } - public interface IStoreService + public interface IStoreService : IService { void Purchase(string productId); void RestorePurchases(); } - public interface INotificationService + public interface INotificationService : IService { void Schedule(string message, int delaySeconds); void CancelAll(); } - public interface ISettingsService + public interface ISettingsService : ISaveService { float Volume { get; set; } string Language { get; set; } int GraphicsQuality { get; set; } - - void Load(); - void Save(); } - public interface IDeviceService + public interface IDeviceService : IService { string UniqueID { get; } string Platform { get; } int Memory { get; } } - public interface IDebugService2 + public interface IDebugService2 : IService { void ShowFPS(bool active); void ShowToast(string message); void SetGodMode(bool active); } - + public interface IStorageService : ISaveService + { + /// + /// Checks whether the specified file exists in the save storage. + /// + bool IsExist(IFile file); + /// + /// Saves the specified file to the save storage. + /// + void Save(IFile file); + /// + /// Loads the specified file from the save storage into memory. + /// + void Load(IFile file); + /// + /// Deletes the specified file from the save storage. + /// + void Delete(IFile file); + /// + /// use for adding file to filelist in savemsystem. + /// if you want to use saveall or geting file with name + /// + /// target file you want adding + /// return true if can add + bool AddFile(IFile file); + /// + /// use for removing file to filelist in savesystem + /// + /// target file you want removing + /// return true if can remove + bool RemoveFile(IFile file); + /// + /// Determines whether the specified file already exists in the file list. + /// Checks by object reference unless IFile implementations override equality. + /// + /// The file instance to check. + /// True if the file is found in the list; otherwise false. + bool HasFile(IFile file); + /// + /// The file that created by savesystem for merging all file selected in sytem to one file + /// + IFile MainSaveFile { get; } + } public interface ILogSystem { diff --git a/Runtime/Library/Extension/Object.cs b/Runtime/Library/Extension/Object.cs index 9a8cbed..f856350 100644 --- a/Runtime/Library/Extension/Object.cs +++ b/Runtime/Library/Extension/Object.cs @@ -193,7 +193,7 @@ public static void InvokeDespawnEvent(this object owner, Object despawner = null } public static void InvokeSaveEvent(this object obj, SendMessageOptions option = SendMessageOptions.RequireReceiver) { - if (obj is ISave provider) + if (obj is ISaveable provider) { provider.OnSaved(); } @@ -204,7 +204,7 @@ public static void InvokeSaveEvent(this object obj, SendMessageOptions option = } public static void InvokeLoadEvent(this object obj, SendMessageOptions option = SendMessageOptions.RequireReceiver) { - if (obj is ISave provider) + if (obj is ISaveable provider) { provider.OnLoaded(); } diff --git a/Runtime/Library/Interfaces/Damageable.cs b/Runtime/Library/Interfaces/Damageable.cs index 65e6674..c4e622b 100644 --- a/Runtime/Library/Interfaces/Damageable.cs +++ b/Runtime/Library/Interfaces/Damageable.cs @@ -1,5 +1,3 @@ -using UnityEngine; - namespace RealMethod { public interface IDamageable diff --git a/Runtime/Library/Interfaces/Save.cs b/Runtime/Library/Interfaces/Saveable.cs similarity index 73% rename from Runtime/Library/Interfaces/Save.cs rename to Runtime/Library/Interfaces/Saveable.cs index f3a1aab..a63f3ad 100644 --- a/Runtime/Library/Interfaces/Save.cs +++ b/Runtime/Library/Interfaces/Saveable.cs @@ -1,6 +1,6 @@ namespace RealMethod { - public interface ISave + public interface ISaveable { void OnLoaded(); void OnSaved(); diff --git a/Runtime/Library/Interfaces/Save.cs.meta b/Runtime/Library/Interfaces/Saveable.cs.meta similarity index 100% rename from Runtime/Library/Interfaces/Save.cs.meta rename to Runtime/Library/Interfaces/Saveable.cs.meta diff --git a/Runtime/Library/Interfaces/Initializable.cs b/Runtime/Library/Interfaces/Spawnable.cs similarity index 100% rename from Runtime/Library/Interfaces/Initializable.cs rename to Runtime/Library/Interfaces/Spawnable.cs diff --git a/Runtime/Library/Interfaces/Initializable.cs.meta b/Runtime/Library/Interfaces/Spawnable.cs.meta similarity index 100% rename from Runtime/Library/Interfaces/Initializable.cs.meta rename to Runtime/Library/Interfaces/Spawnable.cs.meta diff --git a/Runtime/Library/SharedScripts/Structs/Storage.cs b/Runtime/Library/SharedScripts/Structs/Storage.cs index 57037bd..ef5142e 100644 --- a/Runtime/Library/SharedScripts/Structs/Storage.cs +++ b/Runtime/Library/SharedScripts/Structs/Storage.cs @@ -20,7 +20,7 @@ public struct Storage where T : IFile [SerializeField, ConditionalShowByEnum("Mode", StorageMode.Shared)] private bool UseAsset; [SerializeField, ConditionalShowByEnum("Mode", StorageMode.Shared), ConditionalHide("UseAsset", true, false)] - private SaveAsset FileAsset; + private FileAsset FileAsset; [SerializeField, ConditionalShowByEnum("Mode", StorageMode.Shared), ConditionalHide("UseAsset", true, true), ShowOnly] private string SelectedMergeFile; [SerializeField, ConditionalShowByEnum("Mode", StorageMode.Exclusive)] @@ -34,17 +34,17 @@ public struct Storage where T : IFile // Private Fields private UnityEngine.Object _owner; private T _file; - private ISaveSystem _saveSystem; + private IStorageService _saveSystem; private IFile _mergeFile; // Properties - private ISaveSystem saveSystem + private IStorageService saveSystem { get { if (_saveSystem == null) { - _saveSystem = Game.Instance.SaveSystem; + _saveSystem = Game.GetService(); } return _saveSystem; } @@ -97,14 +97,14 @@ public void Refresh() _mergeFile = saveSystem.MainSaveFile; if (_mergeFile != null) { - SelectedMergeFile = _mergeFile.FileObject.GetType().ToString(); + SelectedMergeFile = _mergeFile.Self.GetType().ToString(); if (_mergeFile is T provider) { _file = provider; } else { - Debug.LogError($"Your MergeFile({_mergeFile.FileObject.GetType()}) Should implement {typeof(T)} interface"); + Debug.LogError($"Your MergeFile({_mergeFile.Self.GetType()}) Should implement {typeof(T)} interface"); return; } } diff --git a/Runtime/Pattern/Assets/SaveAsset.cs b/Runtime/Pattern/Assets/SaveAsset.cs new file mode 100644 index 0000000..c5a6f33 --- /dev/null +++ b/Runtime/Pattern/Assets/SaveAsset.cs @@ -0,0 +1,143 @@ + +using UnityEditor; +#if UNITY_EDITOR +using UnityEngine; +#endif + +namespace RealMethod +{ + public interface ISaveFile : IFile, ISaveable + { + void SetName(string NewName); + } + + public abstract class SaveFileAsset : FileAsset, ISaveFile + { + // Implement ISave Interface + void ISaveable.OnLoaded() + { + OnLoaded(); + } + void ISaveable.OnSaved() + { + OnSaved(); + } + // Implement ISaveFile Interface + void ISaveFile.SetName(string NewName) + { + Debug.LogWarning($"Can't change Name for Asset({name}). the SaveAsset get asset name for file naming"); + } + + + // Unity Method + protected virtual void OnEnable() + { +#if !UNITY_EDITOR + ISaveSystem saveSystem = Game.GetService(); + if (saveSystem != null) + { + if (!saveSystem.HasFile(this)) + saveSystem.AddFile(this); + }else + { + Debug.LogError("Can't find SaveSystem"); + } +#endif + } + protected virtual void OnDisable() + { +#if !UNITY_EDITOR + ISaveSystem saveSystem = Game.GetService(); + if (saveSystem != null) + { + if (saveSystem.HasFile(this)) + saveSystem.RemoveFile(this); + } + else + { + Debug.LogError("Can't find SaveSystem"); + } +#endif + } + protected virtual void Reset() + { +#if UNITY_EDITOR + IStorageService saveSystem = Game.GetService(); + if (saveSystem != null) + { + if (!saveSystem.HasFile(this)) + saveSystem.AddFile(this); + } + else + { + Debug.LogError("Can't find SaveSystem"); + } +#endif + } + + + protected abstract void OnLoaded(); + protected abstract void OnSaved(); + +#if UNITY_EDITOR + public override bool AutoReset(PlayModeStateChange state) + { + if (state == PlayModeStateChange.EnteredPlayMode) + return true; + return base.AutoReset(state); + } + [ContextMenu("Save")] + private void Editor_SaveSelf() + { + var manager = Game.GetService(); + if (manager != null) + { + manager.Save(this); + } + else + { + Debug.LogError($"No {typeof(IStorageService)} found in the scene."); + } + } + [ContextMenu("Load")] + private void Editor_LoadSelf() + { + var manager = Game.GetService(); + if (manager != null) + { + manager.Load(this); + } + else + { + Debug.LogError($"No {typeof(IStorageService)} found in the scene."); + } + } + [ContextMenu("Delete")] + private void Editor_Delete() + { + var manager = Game.GetService(); + if (manager != null) + { + manager.Delete(this); + } + else + { + Debug.LogError($"No {typeof(IStorageService)} found in the scene."); + } + } + [ContextMenu("IsExist")] + private void Editor_IsExist() + { + var manager = Game.GetService(); + if (manager != null) + { + Debug.Log($"[{name}] IsExist: {manager.IsExist(this)}"); + } + else + { + Debug.LogError($"No {typeof(IStorageService)} found in the scene."); + } + } +#endif + } +} \ No newline at end of file diff --git a/Runtime/Pattern/Assets/SaveAsset.cs.meta b/Runtime/Pattern/Assets/SaveAsset.cs.meta new file mode 100644 index 0000000..5b0314e --- /dev/null +++ b/Runtime/Pattern/Assets/SaveAsset.cs.meta @@ -0,0 +1,2 @@ +fileFormatVersion: 2 +guid: 480d36d987d58bf4c9bfae34e36a02bf \ No newline at end of file diff --git a/Runtime/Pattern/Managers/SaveManager.cs b/Runtime/Pattern/Managers/SaveManager.cs index a9c0392..970a995 100644 --- a/Runtime/Pattern/Managers/SaveManager.cs +++ b/Runtime/Pattern/Managers/SaveManager.cs @@ -46,7 +46,7 @@ public interface IMergeFile : ISaveFile - public abstract class SaveManager : MonoBehaviour, IGameManager, ISaveSystem + public abstract class SaveManager : MonoBehaviour, IGameManager, IStorageService { [Header("Mode")] [SerializeField] @@ -134,10 +134,10 @@ public void Save(IFile file) Debug.LogError(ex); return; } - file.FileObject.InvokeSaveEvent(); + file.Self.InvokeSaveEvent(); OnSaved?.Invoke(file); #if UNITY_EDITOR || DEVELOPMENT_BUILD - WriteLog($"Save({GetMethod(file).Format}) Class({file.FileObject.GetType()})"); + WriteLog($"Save({GetMethod(file).Format}) Class({file.Self.GetType()})"); #endif } public void Load(IFile file) @@ -157,10 +157,10 @@ public void Load(IFile file) Debug.LogError(ex); return; } - file.FileObject.InvokeLoadEvent(); + file.Self.InvokeLoadEvent(); OnLoaded?.Invoke(file); #if UNITY_EDITOR || DEVELOPMENT_BUILD - WriteLog($"Load({GetMethod(file).Format}) Class({file.FileObject.GetType()})"); + WriteLog($"Load({GetMethod(file).Format}) Class({file.Self.GetType()})"); #endif } public void Delete(IFile file) @@ -179,11 +179,14 @@ public void Delete(IFile file) } OnDeleted?.Invoke(file); #if UNITY_EDITOR || DEVELOPMENT_BUILD - WriteLog($"Delete({GetMethod(file).Format}) Class({file.FileObject.GetType()})"); + WriteLog($"Delete({GetMethod(file).Format}) Class({file.Self.GetType()})"); #endif } [ContextMenu("Save")] - void ISaveSystem.SaveAll() + /// + /// Save all file or Specific file that implemented + /// + void ISaveService.Save() { IFile[] files = GetAllFiles(); if (files != null) @@ -203,10 +206,10 @@ void ISaveSystem.SaveAll() Debug.LogError(ex); return; } - MainSaveFile.FileObject.InvokeSaveEvent(); + MainSaveFile.Self.InvokeSaveEvent(); OnSaved?.Invoke(MainSaveFile); #if UNITY_EDITOR || DEVELOPMENT_BUILD - WriteLog($"Save[SingleFile]({GetMethod(MainSaveFile).Format}) Class({MainSaveFile.FileObject.GetType()})"); + WriteLog($"Save[SingleFile]({GetMethod(MainSaveFile).Format}) Class({MainSaveFile.Self.GetType()})"); #endif break; case SaveFileStructure.MultiFile: @@ -234,17 +237,20 @@ void ISaveSystem.SaveAll() Debug.LogError(ex); return; } - MainSaveFile.FileObject.InvokeSaveEvent(); + MainSaveFile.Self.InvokeSaveEvent(); OnSaved?.Invoke(MainSaveFile); #if UNITY_EDITOR || DEVELOPMENT_BUILD - WriteLog($"Save[MergedFile]({GetMethod(MainSaveFile).Format}) Class({MainSaveFile.FileObject.GetType()})"); + WriteLog($"Save[MergedFile]({GetMethod(MainSaveFile).Format}) Class({MainSaveFile.Self.GetType()})"); #endif break; } } } [ContextMenu("Load")] - void ISaveSystem.LoadAll() + /// + /// Load all file or specific file that implemented + /// + void ISaveService.Load() { IFile[] files = GetAllFiles(); if (files != null) @@ -264,10 +270,10 @@ void ISaveSystem.LoadAll() Debug.LogError(ex); return; } - MainSaveFile.FileObject.InvokeLoadEvent(); + MainSaveFile.Self.InvokeLoadEvent(); OnLoaded?.Invoke(MainSaveFile); #if UNITY_EDITOR || DEVELOPMENT_BUILD - WriteLog($"Load({GetMethod(MainSaveFile).Format}) Class({MainSaveFile.FileObject.GetType()})"); + WriteLog($"Load({GetMethod(MainSaveFile).Format}) Class({MainSaveFile.Self.GetType()})"); #endif break; case SaveFileStructure.MultiFile: @@ -295,10 +301,10 @@ void ISaveSystem.LoadAll() Debug.LogError(ex); return; } - MainSaveFile.FileObject.InvokeLoadEvent(); + MainSaveFile.Self.InvokeLoadEvent(); OnLoaded?.Invoke(MainSaveFile); #if UNITY_EDITOR || DEVELOPMENT_BUILD - WriteLog($"Load({GetMethod(MainSaveFile).Format}) Class({MainSaveFile.FileObject.GetType()})"); + WriteLog($"Load({GetMethod(MainSaveFile).Format}) Class({MainSaveFile.Self.GetType()})"); #endif break; } @@ -338,7 +344,7 @@ protected virtual bool CanContinue(string message) } protected virtual bool Validate(IFile file) { - if (file == null && file.FileObject != null) + if (file == null && file.Self != null) { Debug.LogError("File Does not valid"); return false; @@ -347,7 +353,7 @@ protected virtual bool Validate(IFile file) } protected virtual ISaveMethod GetMethod(IFile file) { - if (file != null && file.FileObject.HasImplementInterface(out ISaveMethod method)) + if (file != null && file.Self.HasImplementInterface(out ISaveMethod method)) { return method; } @@ -365,7 +371,7 @@ protected virtual ISaveMethod GetMethod(IFile file) } protected virtual void WriteToMergeFile(IFile file, BindingFlags fieldFlags, BindingFlags propertyFlags) { - object FileObject = file.FileObject; + object FileObject = file.Self; IMergeFile mergefile = GetMainFile(); foreach (var field in FileObject.GetFields(fieldFlags)) { @@ -378,7 +384,7 @@ protected virtual void WriteToMergeFile(IFile file, BindingFlags fieldFlags, Bin } protected virtual void ReadFromMergeFile(IFile file, BindingFlags fieldFlags, BindingFlags propertyFlags) { - object FileObject = file.FileObject; + object FileObject = file.Self; IMergeFile mergefile = GetMainFile(); foreach (var field in FileObject.GetFields(fieldFlags)) { @@ -464,12 +470,12 @@ protected override bool IsExistFile(IFile file, ISaveMethod Method) } protected override void OnSave(IFile file, ISaveMethod Method) { - object fileObject = file.FileObject; + object fileObject = file.Self; switch (Method.Format) { case SaveFormat.None: - if (fileObject is not ISave) + if (fileObject is not ISaveable) { Debug.LogError($"Your file({fileObject}) with name({file.FileName}) should implement ISave Interface"); } @@ -540,12 +546,12 @@ protected override void OnSave(IFile file, ISaveMethod Method) } protected override void OnLoad(IFile file, ISaveMethod Method) { - object fileObject = file.FileObject; + object fileObject = file.Self; switch (Method.Format) { case SaveFormat.None: - if (fileObject is not ISave) + if (fileObject is not ISaveable) { Debug.LogError($"Your file({fileObject}) with name({file.FileName}) should implement ISave Interface"); } @@ -673,7 +679,7 @@ protected override void OnLoad(IFile file, ISaveMethod Method) } protected override void OnDelete(IFile file, ISaveMethod Method) { - object fileObject = file.FileObject; + object fileObject = file.Self; switch (Method.Format) { @@ -1058,7 +1064,7 @@ public abstract class SaveManager_Storage : SaveManager_Method { [Header("Details")] [SerializeField, ConditionalShowByEnum("Mode", SaveFileStructure.SingleFile)] - private SaveAsset SingeFileAsset; + private FileAsset SingeFileAsset; [SerializeField, ConditionalShowByEnum("Mode", SaveFileStructure.MergedFile)] private SoftType MergeFileClass; private object MySaveFile; diff --git a/Runtime/ReadySet/Components/UI/UI_GameSetting.cs b/Runtime/ReadySet/Components/UI/UI_GameSetting.cs index 712bb7f..5e2954e 100644 --- a/Runtime/ReadySet/Components/UI/UI_GameSetting.cs +++ b/Runtime/ReadySet/Components/UI/UI_GameSetting.cs @@ -243,7 +243,7 @@ private void OnToggleChanged(bool value) } } - public abstract class SettingFile : SaveAsset, ISettingStorage + public abstract class SettingFile : SaveFileAsset, ISettingStorage { protected bool IsDirty { get; private set; } diff --git a/Runtime/Toolkit/Inventory/InventorySaveFile.cs b/Runtime/Toolkit/Inventory/InventorySaveFile.cs index 83f0bb3..9dc1542 100644 --- a/Runtime/Toolkit/Inventory/InventorySaveFile.cs +++ b/Runtime/Toolkit/Inventory/InventorySaveFile.cs @@ -5,7 +5,7 @@ namespace RealMethod { [CreateAssetMenu(fileName = "InventorySaveFile", menuName = "RealMethod/Inventory/SaveFile", order = 1)] - public class InventorySaveFile : SaveAsset, IInventoryStorage + public class InventorySaveFile : SaveFileAsset, IInventoryStorage { [Header("Inventory")] [SerializeField, ReadOnly, TextArea] diff --git a/Runtime/Toolkit/RPG/StatSystem/StatSaveFile.cs b/Runtime/Toolkit/RPG/StatSystem/StatSaveFile.cs index 400ff0e..9f5939f 100644 --- a/Runtime/Toolkit/RPG/StatSystem/StatSaveFile.cs +++ b/Runtime/Toolkit/RPG/StatSystem/StatSaveFile.cs @@ -5,7 +5,7 @@ namespace RealMethod { [CreateAssetMenu(fileName = "StatSaveFile", menuName = "RealMethod/RPG/StatSaveFile", order = 1)] - public class StatSaveFile : SaveAsset, IStatStorage + public class StatSaveFile : SaveFileAsset, IStatStorage { [Header("Stat")] [SerializeField, ReadOnly, TextArea] diff --git a/Runtime/Toolkit/Tutorial/TutorialSaveFile.cs b/Runtime/Toolkit/Tutorial/TutorialSaveFile.cs index 0cee95f..9690ffe 100644 --- a/Runtime/Toolkit/Tutorial/TutorialSaveFile.cs +++ b/Runtime/Toolkit/Tutorial/TutorialSaveFile.cs @@ -9,7 +9,7 @@ namespace RealMethod { [CreateAssetMenu(fileName = "TutorialSaveFile", menuName = "RealMethod/Tutorial/SaveFile", order = 1)] - public class TutorialSaveFile : SaveAsset, ITutorialStorage + public class TutorialSaveFile : SaveFileAsset, ITutorialStorage { [Header("Tutorial")] [SerializeField, ReadOnly, TextArea] diff --git a/Runtime/Toolkit/Upgrade/Sample/ChainUpgradeMapConfig.cs b/Runtime/Toolkit/Upgrade/Sample/ChainUpgradeMapConfig.cs index 20d3ea8..0a36091 100644 --- a/Runtime/Toolkit/Upgrade/Sample/ChainUpgradeMapConfig.cs +++ b/Runtime/Toolkit/Upgrade/Sample/ChainUpgradeMapConfig.cs @@ -70,7 +70,7 @@ public class ChainUpgradeMapConfig : UpgradeMapConfig, IChainUpgrade { [Header("Setting")] [SerializeField] - private SaveAsset CoinFile; + private FileAsset CoinFile; [SerializeField] public int[] pricing; [SerializeField, ReadOnly] diff --git a/Runtime/Toolkit/Upgrade/UpgradeSaveFile.cs b/Runtime/Toolkit/Upgrade/UpgradeSaveFile.cs index fd728d5..a70e8b9 100644 --- a/Runtime/Toolkit/Upgrade/UpgradeSaveFile.cs +++ b/Runtime/Toolkit/Upgrade/UpgradeSaveFile.cs @@ -9,7 +9,7 @@ namespace RealMethod { [CreateAssetMenu(fileName = "UpgradeSaveFile", menuName = "RealMethod/Upgrade/SaveFile", order = 1)] - public class UpgradeSaveFile : SaveAsset, IUpgradeStorage + public class UpgradeSaveFile : SaveFileAsset, IUpgradeStorage { [Header("Setting")] public bool UsePlayerPrefs = true; diff --git a/Tests/FileManager.cs b/Tests/FileManager.cs index 284aa23..ee23a1a 100644 --- a/Tests/FileManager.cs +++ b/Tests/FileManager.cs @@ -82,7 +82,7 @@ protected virtual BindingFlags GetFlagSetting() } protected virtual FileData CreateFileData(IFile file) { - return new FileData(file.FileObject, GetFlagSetting()); + return new FileData(file.Self, GetFlagSetting()); } // Abstraction Methods From 1c7ffdad78413cceb2141d5631bc26973f0471cc Mon Sep 17 00:00:00 2001 From: Alijimpa Date: Sat, 9 May 2026 16:28:51 +0330 Subject: [PATCH 196/204] Refine Services Template --- .../Definitions/{Systems.cs => Services.cs} | 27 ++++++++++++----- .../{Systems.cs.meta => Services.cs.meta} | 0 Runtime/ReadySet/Services/DebugModule.cs | 29 ++++++++----------- 3 files changed, 32 insertions(+), 24 deletions(-) rename Runtime/Core/Definitions/{Systems.cs => Services.cs} (85%) rename Runtime/Core/Definitions/{Systems.cs.meta => Services.cs.meta} (100%) diff --git a/Runtime/Core/Definitions/Systems.cs b/Runtime/Core/Definitions/Services.cs similarity index 85% rename from Runtime/Core/Definitions/Systems.cs rename to Runtime/Core/Definitions/Services.cs index 3b0fdd5..c5a96e8 100644 --- a/Runtime/Core/Definitions/Systems.cs +++ b/Runtime/Core/Definitions/Services.cs @@ -1,3 +1,5 @@ +using UnityEngine; + namespace RealMethod { public interface IAnalyticsService : IService @@ -65,7 +67,19 @@ public interface IDeviceService : IService string Platform { get; } int Memory { get; } } - public interface IDebugService2 : IService + public interface IGUIService : IService + { + Vector2 PrintPivot { get; } + int PrintSize { get; } + void SetPivot(Vector2 pivot); + void SetSize(int size); + } + public interface IDebugService : IGUIService + { + float PrintSpace { get; } + event System.Action OnLogWrited; + } + public interface IDeveloperService : IService { void ShowFPS(bool active); void ShowToast(string message); @@ -114,14 +128,13 @@ public interface IStorageService : ISaveService /// IFile MainSaveFile { get; } } - - public interface ILogSystem + public interface ILogService2 : IService { - void Log(object message, UnityEngine.Object context); - void LogWarning(object message, UnityEngine.Object context); - void LogError(object message, UnityEngine.Object context); + void Log(object message, Object context); + void LogWarning(object message, Object context); + void LogError(object message, Object context); //void LogException(Exception exception, UnityEngine.Object context); - void Assert(object message, UnityEngine.Object context); + void Assert(object message, Object context); } diff --git a/Runtime/Core/Definitions/Systems.cs.meta b/Runtime/Core/Definitions/Services.cs.meta similarity index 100% rename from Runtime/Core/Definitions/Systems.cs.meta rename to Runtime/Core/Definitions/Services.cs.meta diff --git a/Runtime/ReadySet/Services/DebugModule.cs b/Runtime/ReadySet/Services/DebugModule.cs index bc0c245..272551e 100644 --- a/Runtime/ReadySet/Services/DebugModule.cs +++ b/Runtime/ReadySet/Services/DebugModule.cs @@ -3,16 +3,6 @@ namespace RealMethod { - public interface IDebugService : IService - { - Vector2 PrintPivot { get; } - float PrintSpace { get; } - int PrintSize { get; } - event System.Action OnLogWrited; - - void SetPivot(Vector2 pivot); - void SetSize(int size); - } public sealed class DebugModule : GameModule, ILogHandler, IDebugService { private class LogLine : IDrawTask @@ -134,7 +124,6 @@ DrawMode IDrawTask.GetDrawMode() private int Size = 1; private List Lines = new List(10); private ILogHandler defaultLogHandler; - public event System.Action OnLogWrited; // Implement ILogHandler Interfacwe @@ -168,18 +157,21 @@ void ILogHandler.LogException(System.Exception exception, Object context) defaultLogHandler.LogException(exception, context); OnLogWrited?.Invoke(LogType.Exception, exception.Message); } - // Implement IDebugService Interface - Vector2 IDebugService.PrintPivot => Pivot; - int IDebugService.PrintSize => Size; - float IDebugService.PrintSpace => Screen.height / 40; - void IDebugService.SetPivot(Vector2 pivot) + // Implement IGUIService Interface + Vector2 IGUIService.PrintPivot => Pivot; + int IGUIService.PrintSize => Size; + void IGUIService.SetPivot(Vector2 pivot) { Pivot = pivot; } - void IDebugService.SetSize(int size) + void IGUIService.SetSize(int size) { Size = size; } + // Implement IDebugService Interface + float IDebugService.PrintSpace => Screen.height / 40; + public event System.Action OnLogWrited; + // Module Methods @@ -198,6 +190,9 @@ protected override void OnEnd() Lines.Clear(); } + + + // Methods private void RemoveLog(LogLine line) { From ae4d25e96348b5070e128bc896a595180527c532 Mon Sep 17 00:00:00 2001 From: Alijimpa Date: Sun, 10 May 2026 16:52:14 +0330 Subject: [PATCH 197/204] Refin Game Bridge for event and properties --- Runtime/Core/Architecture/GameBridge.cs | 166 +++++++-------------- Runtime/Core/Architecture/World.cs | 10 +- Runtime/ReadySet/Managers/ScreenManager.cs | 4 +- 3 files changed, 60 insertions(+), 120 deletions(-) diff --git a/Runtime/Core/Architecture/GameBridge.cs b/Runtime/Core/Architecture/GameBridge.cs index a59b158..8a53f9b 100644 --- a/Runtime/Core/Architecture/GameBridge.cs +++ b/Runtime/Core/Architecture/GameBridge.cs @@ -11,12 +11,8 @@ namespace RealMethod /// Defines synchronization hooks used internally to coordinate /// worlds and Game during runtime initialization. /// - public interface IRelationBridge + public interface IWorldBridge { - /// - /// This represents the persistent scene - /// - Scene InstanceScene { get; } /// /// Introduces a newly created world to the system. /// @@ -26,36 +22,6 @@ public interface IRelationBridge /// false if it is considered a side/additive world. /// bool RegisterWorld(World world); - /// - /// Called by world class to tell game the initiation is complite - /// - void WorldIsReady(); - /// - /// Event invoked by World class to tell the realmethod initiation complite - /// Access by Game class - /// - event Action OnGameReady; - } - /// - /// Defines all events and stat need to know for loading scnes - /// to make internal connection from Game to unify all game events from Game class - /// - public interface ILoadScneBridge - { - /// - /// Event invoked when a scene or world starts or finishes loading. - /// The boolean parameter is true when loading starts and false when loading ends. - /// - event Action OnSceneLoading; - /// - /// Event invoked during scene or world loading to report progress. - /// The float parameter represents the loading progress from 0 (start) to 1 (complete). - /// - event Action OnSceneLoadingProcess; - /// - /// Indicates whether a scene or world load operation is currently in progress. - /// - bool IsLoading { get; } } @@ -80,20 +46,31 @@ public interface IBridge /// Load & Unload Scene reporting /// /// - public abstract class GameBridge : IDisposable, IRelationBridge, ILoadScneBridge, IInspectorInfo + public abstract class GameBridge : IDisposable, IWorldBridge, IInspectorInfo { - // Events - private Action GameReadyEvent; + /// + /// Indicates whether a scene or world load operation is currently in progress. + /// + public bool IsLoading { get; private set; } = false; + public bool SceneWillUnload { get; private set; } + /// + /// This represents the persistent scene reference used for managing components across the game lifecycle. + /// + public Scene CurrrentScene { get; private set; } + /// + /// Event invoked when a scene or world starts or finishes loading. + /// The boolean parameter is true when loading starts and false when loading ends. + /// + public event Action OnSceneLoading; + /// + /// Event invoked during scene or world loading to report progress. + /// The float parameter represents the loading progress from 0 (start) to 1 (complete). + /// + public event Action OnSceneLoadingProcess; - private Action SceneLoadingEvent; - private Action SceneLoadingProcessEvent; - private bool isLoading; - public bool IsHolding { get; private set; } = false; protected float FadeTime = 0; - private Scene CurrrentScene; - public Scene LastActiveScene; - public bool SceneWillUnload { get; private set; } + private Scene LastActiveScene; private readonly Action OnNextWorld; private readonly List> bridges = new(); @@ -113,53 +90,10 @@ void IDisposable.Dispose() SceneManager.activeSceneChanged -= OnActiveSceneChanged; } // Implement IRelationBridge Interface - event Action IRelationBridge.OnGameReady - { - add - { - GameReadyEvent += value; - } - - remove - { - GameReadyEvent -= value; - } - } - Scene IRelationBridge.InstanceScene => CurrrentScene; - bool IRelationBridge.RegisterWorld(World world) + bool IWorldBridge.RegisterWorld(World world) { return TryToRegisterWorld(world); } - void IRelationBridge.WorldIsReady() - { - GameReadyEvent?.Invoke(); - } - // Implement ILoadScneBridge Interface - event Action ILoadScneBridge.OnSceneLoading - { - add - { - SceneLoadingEvent += value; - } - - remove - { - SceneLoadingEvent -= value; - } - } - event Action ILoadScneBridge.OnSceneLoadingProcess - { - add - { - SceneLoadingProcessEvent += value; - } - - remove - { - SceneLoadingProcessEvent -= value; - } - } - bool ILoadScneBridge.IsLoading => isLoading; @@ -220,7 +154,7 @@ public bool Unbind(object obj) /// public virtual IEnumerator GetLoadScneCorotine(string sceneName) { - if (isLoading == true) + if (IsLoading == true) { Debug.LogWarning($"Can't load Scene:{sceneName} The Bridge is in loading target scene"); return null; @@ -237,7 +171,7 @@ public virtual IEnumerator GetLoadScneCorotine(string sceneName) /// public virtual IEnumerator GetAddScneCorotine(string sceneName, Action callback) { - if (isLoading == true) + if (IsLoading == true) { Debug.LogWarning($"Can't load Scene:{sceneName} The Bridge is in loading target scene"); return null; @@ -254,7 +188,7 @@ public virtual IEnumerator GetAddScneCorotine(string sceneName, Action callback) /// public virtual IEnumerator GetLoadScneCorotine(int sceneIndex) { - if (isLoading == true) + if (IsLoading == true) { Debug.LogWarning($"Can't load Index:{sceneIndex} The Bridge is in loading target scene"); return null; @@ -271,7 +205,7 @@ public virtual IEnumerator GetLoadScneCorotine(int sceneIndex) /// public virtual IEnumerator GetAddScneCorotine(int sceneIndex, Action callback) { - if (isLoading == true) + if (IsLoading == true) { Debug.LogWarning($"Can't load Index:{sceneIndex} The Bridge is in loading target scene"); return null; @@ -288,7 +222,7 @@ public virtual IEnumerator GetAddScneCorotine(int sceneIndex, Action callback) /// public virtual IEnumerator GetLoadWorldCorotine(WorldAsset WorldScene) { - if (isLoading == true) + if (IsLoading == true) { Debug.LogWarning($"Can't load World:{WorldScene} The Bridge is in loading target scene"); return null; @@ -420,8 +354,8 @@ private float RemapClamped(float value, float inMin, float inMax, float outMin, private IEnumerator LoadSceneAsync(string scene, int scneIndex = -1) { //StartLoading - isLoading = true; - SceneLoadingEvent?.Invoke(true); + IsLoading = true; + OnSceneLoading?.Invoke(true); float fadingtime = FadeTime; //Fading Screen @@ -443,16 +377,16 @@ private IEnumerator LoadSceneAsync(string scene, int scneIndex = -1) if (Load_opertation == null) { Debug.LogError("Failed to load scene. AsyncOperation is null."); - SceneLoadingEvent?.Invoke(false); - isLoading = false; + OnSceneLoading?.Invoke(false); + IsLoading = false; yield break; } while (!Load_opertation.isDone) { - SceneLoadingProcessEvent?.Invoke(Load_opertation.progress); + OnSceneLoadingProcess?.Invoke(Load_opertation.progress); yield return null; } - SceneLoadingProcessEvent?.Invoke(1); + OnSceneLoadingProcess?.Invoke(1); //Fading Screen if (fadingtime != 0) @@ -461,8 +395,8 @@ private IEnumerator LoadSceneAsync(string scene, int scneIndex = -1) } //FinishLoading - SceneLoadingEvent?.Invoke(false); - isLoading = false; + OnSceneLoading?.Invoke(false); + IsLoading = false; } private IEnumerator AddSceneAsync(Action callback, string scene, int scneIndex = -1) { @@ -492,8 +426,8 @@ private IEnumerator AddSceneAsync(Action callback, string scene, int scneIndex = private IEnumerator LoadWorldAsync(WorldAsset WS) { //StartLoading - isLoading = true; - SceneLoadingEvent?.Invoke(true); + IsLoading = true; + OnSceneLoading?.Invoke(true); float fadingtime = FadeTime; //Fading Screen @@ -508,15 +442,15 @@ private IEnumerator LoadWorldAsync(WorldAsset WS) if (Load_opertation == null) { Debug.LogError("Failed to load scene. AsyncOperation is null."); - SceneLoadingEvent?.Invoke(false); - isLoading = false; + OnSceneLoading?.Invoke(false); + IsLoading = false; yield break; } while (!Load_opertation.isDone) { - SceneLoadingProcessEvent?.Invoke(RemapClamped(Load_opertation.progress, 0, 1, 0, 1 / WS.Count + 1)); - SceneLoadingEvent?.Invoke(false); - isLoading = false; + OnSceneLoadingProcess?.Invoke(RemapClamped(Load_opertation.progress, 0, 1, 0, 1 / WS.Count + 1)); + OnSceneLoading?.Invoke(false); + IsLoading = false; yield return null; } @@ -527,17 +461,17 @@ private IEnumerator LoadWorldAsync(WorldAsset WS) if (Additive_Load_opertation == null) { Debug.LogError("Failed to load scene. AsyncOperation is null."); - SceneLoadingEvent?.Invoke(false); - isLoading = false; + OnSceneLoading?.Invoke(false); + IsLoading = false; yield break; } while (!Additive_Load_opertation.isDone) { - SceneLoadingProcessEvent?.Invoke(RemapClamped(Load_opertation.progress, 0, 1, 0, 1 / WS.Count + 1 - (i + 1))); + OnSceneLoadingProcess?.Invoke(RemapClamped(Load_opertation.progress, 0, 1, 0, 1 / WS.Count + 1 - (i + 1))); yield return null; } } - SceneLoadingProcessEvent?.Invoke(1); + OnSceneLoadingProcess?.Invoke(1); //Fading Screen if (fadingtime != 0) @@ -546,8 +480,8 @@ private IEnumerator LoadWorldAsync(WorldAsset WS) } //FinishLoading - SceneLoadingEvent?.Invoke(false); - isLoading = false; + OnSceneLoading?.Invoke(false); + IsLoading = false; } @@ -558,7 +492,7 @@ private IEnumerator LoadWorldAsync(WorldAsset WS) // Implement IInspectorInfo Interface string IInspectorInfo.GetInfo() { - return $"IsLoading ({isLoading}) , FadeTime ({FadeTime}) , {GetInspectorInfo()}"; + return $"IsLoading ({IsLoading}) , FadeTime ({FadeTime}) , {GetInspectorInfo()}"; } protected virtual string GetInspectorInfo() { diff --git a/Runtime/Core/Architecture/World.cs b/Runtime/Core/Architecture/World.cs index eecfed5..479a2ce 100644 --- a/Runtime/Core/Architecture/World.cs +++ b/Runtime/Core/Architecture/World.cs @@ -81,6 +81,12 @@ public abstract class World : Scope [Header("Setting")] [SerializeField] private Prefab DefaultPlayer; + /// + /// This action called every time your game ready to play after load Scene & setup RealMethod + /// you can enshure that your game and world do anything and player can ready to play game + /// when you change scene after world initiate this evet invoke again. + /// + public static event System.Action OnReady; private GameObject PlayerObject; @@ -94,7 +100,7 @@ public abstract class World : Scope private void Awake() { //Connect to Game With Bridge - IRelationBridge SyncProvider = Game.Bridge; + IWorldBridge SyncProvider = Game.Bridge; if (!SyncProvider.RegisterWorld(this)) { return; @@ -121,7 +127,7 @@ private void Awake() transform.rotation = Quaternion.identity; WorldBegin(); - SyncProvider.WorldIsReady(); + OnReady?.Invoke(); } #if UNITY_EDITOR private void OnEnable() diff --git a/Runtime/ReadySet/Managers/ScreenManager.cs b/Runtime/ReadySet/Managers/ScreenManager.cs index f14a668..188c4c4 100644 --- a/Runtime/ReadySet/Managers/ScreenManager.cs +++ b/Runtime/ReadySet/Managers/ScreenManager.cs @@ -23,8 +23,8 @@ public sealed class ScreenManager : UIManager // UIManager Methods protected override void InitiateManager(Scope owner) { - Game.OnSceneLoading += (value) => OnLoadScne?.Invoke(value); - Game.OnSceneLoadingProcess += (value) => OnLoading?.Invoke(value); + Game.Bridge.OnSceneLoading += (value) => OnLoadScne?.Invoke(value); + Game.Bridge.OnSceneLoadingProcess += (value) => OnLoading?.Invoke(value); } public void SetInformer(IInformer messanger) { From c515ffec8217112773d1f6523772fc5f314362b3 Mon Sep 17 00:00:00 2001 From: Alijimpa Date: Sun, 10 May 2026 16:52:24 +0330 Subject: [PATCH 198/204] Implement Basic for EventBus --- Runtime/Core/Architecture/Game.cs | 74 +++++++------ Runtime/Core/Definitions/Event.cs | 4 + Runtime/Core/Definitions/Event.cs.meta | 2 + Runtime/Core/Framework/GameSubsystem.cs | 5 +- Runtime/Core/Framework/Kernel.cs | 21 +++- Runtime/Core/Framework/Subsystems/EventBus.cs | 100 ++++++++++++++++++ .../Framework/Subsystems/EventBus.cs.meta | 2 + 7 files changed, 170 insertions(+), 38 deletions(-) create mode 100644 Runtime/Core/Definitions/Event.cs create mode 100644 Runtime/Core/Definitions/Event.cs.meta create mode 100644 Runtime/Core/Framework/Subsystems/EventBus.cs create mode 100644 Runtime/Core/Framework/Subsystems/EventBus.cs.meta diff --git a/Runtime/Core/Architecture/Game.cs b/Runtime/Core/Architecture/Game.cs index d98f814..51b7a5f 100644 --- a/Runtime/Core/Architecture/Game.cs +++ b/Runtime/Core/Architecture/Game.cs @@ -74,10 +74,6 @@ public static GameObject Player /// public static GlobalEnum State { get; private set; } = 0; /// - /// This represents the persistent scene reference used for managing components across the game lifecycle. - /// - public static Scene PersistentScene => ((IRelationBridge)Bridge).InstanceScene; - /// /// Indicates whether a scene or world load operation is currently in progress. /// public static bool IsPaused @@ -101,34 +97,8 @@ public static bool IsPaused /// Return true when game in loading section for new scene /// public static bool IsLoading => Instance.IsGameLoading(); - /// - /// Event invoked when a scene or world starts or finishes loading. - /// The boolean parameter is true when loading starts and false when loading ends. - /// - public static event Action OnSceneLoading - { - add { ((ILoadScneBridge)Bridge).OnSceneLoading += value; } - remove { ((ILoadScneBridge)Bridge).OnSceneLoading -= value; } - } - /// - /// Event invoked during scene or world loading to report progress. - /// The float parameter represents the loading progress from 0 (start) to 1 (complete). - /// - public static event Action OnSceneLoadingProcess - { - add { ((ILoadScneBridge)Bridge).OnSceneLoadingProcess += value; } - remove { ((ILoadScneBridge)Bridge).OnSceneLoadingProcess -= value; } - } - /// - /// This action called every time your game ready to play after load Scene & setup RealMethod - /// you can enshure that your game and world do anything and player can ready to play game - /// when you change scene after world initiate this evet invoke again. - /// - public static event Action OnReady - { - add { ((IRelationBridge)Bridge).OnGameReady += value; } - remove { ((IRelationBridge)Bridge).OnGameReady -= value; } - } + + /// /// Invoked when the process finishes. /// Process in your game take define with yourelf. @@ -140,6 +110,10 @@ public static event Action OnReady /// public static event Action OnStateChanged; + + + + /// /// Initializes the game singleton and core systems on subsystem registration. /// This sets up the , game , @@ -250,7 +224,6 @@ private static void InitializeGame() #endif Instance.OpenScope(Objects); - // Unload Project Setting Resources.UnloadAsset(ProjectSettings); ProjectSettings = null; @@ -378,6 +351,33 @@ public static T GetService() where T : IService } } /// + /// Publishes an event to all subscribers of the specified event type. + /// + /// Type of the event. + /// The event data to publish. + public void Publish(T eventData) where T : IEvent + { + EventBus.Publish(eventData); + } + /// + /// Subscribes a listener to a specific event type. + /// + /// Type of the event to listen for. + /// Callback invoked when the event is published. + public void Subscribe(Action listener) where T : IEvent + { + EventBus.Subscribe(listener); + } + /// + /// Unsubscribes a listener from a specific event type. + /// + /// Type of the event. + /// The listener to remove. + public void Unsubscribe(Action listener) where T : IEvent + { + EventBus.Subscribe(listener); + } + /// /// Requests a scene load by build index . /// If the requested scene is already active, a warning is logged and null is returned. /// @@ -918,7 +918,7 @@ protected virtual bool IsGamePaused() /// true if any scne in loading stage; otherwise false. protected virtual bool IsGameLoading() { - return ((ILoadScneBridge)Bridge).IsLoading; + return Bridge.IsLoading; } /// /// Check for changing state from A to B by author. @@ -952,19 +952,23 @@ private void Notify_OnGameQuit() { Application.quitting -= Notify_OnGameQuit; OnGameClosed(); + // Scope CloseScope(); + // Bridge ((IDisposable)Bridge).Dispose(); Bridge = null; + // Draw #if UNITY_EDITOR || DEVELOPMENT_BUILD DrawTasks.Clear(); #endif - + // GC #if UNITY_EDITOR // Debug only: force GC to verify no references remain GC.Collect(); GC.WaitForPendingFinalizers(); GC.Collect(); #endif + // Kernel ClearKernel(); } diff --git a/Runtime/Core/Definitions/Event.cs b/Runtime/Core/Definitions/Event.cs new file mode 100644 index 0000000..d0b3a2f --- /dev/null +++ b/Runtime/Core/Definitions/Event.cs @@ -0,0 +1,4 @@ +namespace RealMethod +{ + public interface IEvent { } +} \ No newline at end of file diff --git a/Runtime/Core/Definitions/Event.cs.meta b/Runtime/Core/Definitions/Event.cs.meta new file mode 100644 index 0000000..4b3b956 --- /dev/null +++ b/Runtime/Core/Definitions/Event.cs.meta @@ -0,0 +1,2 @@ +fileFormatVersion: 2 +guid: 602ac2be96ab007448d28dd436ea78ae \ No newline at end of file diff --git a/Runtime/Core/Framework/GameSubsystem.cs b/Runtime/Core/Framework/GameSubsystem.cs index e582ba3..6bc0213 100644 --- a/Runtime/Core/Framework/GameSubsystem.cs +++ b/Runtime/Core/Framework/GameSubsystem.cs @@ -13,10 +13,12 @@ public abstract class GameSubsystem : IInspectorInfo, IDisposable, IBootstrap public sealed class ShareData : IInspectorInfo, IDisposable { public Dictionary> Repository { get; } + public Dictionary> Events { get; } public ShareData(int prewarm) { Repository = new Dictionary>(prewarm); + Events = new Dictionary>(prewarm); } @@ -24,12 +26,13 @@ public ShareData(int prewarm) void IDisposable.Dispose() { Repository.Clear(); + Events.Clear(); } #if UNITY_EDITOR string IInspectorInfo.GetInfo() { - return $"Repository ({Repository.Count})"; + return $"Repository ({Repository.Count}) , Events ({Events.Count})"; } #endif } diff --git a/Runtime/Core/Framework/Kernel.cs b/Runtime/Core/Framework/Kernel.cs index 9df3f20..8163408 100644 --- a/Runtime/Core/Framework/Kernel.cs +++ b/Runtime/Core/Framework/Kernel.cs @@ -25,6 +25,7 @@ public abstract class Kernel : MonoBehaviour private static GameSubsystem.ShareData _rpository; private static ServiceLocator _serviceLocator; private static DependencyInjection _dependencyInjection; + private static EventBus _eventBus; // GameModules @@ -63,7 +64,18 @@ protected static DependencyInjection DInjection return _dependencyInjection; } } - + protected static EventBus EventBus + { + get + { + if (_eventBus == null) + { + _eventBus = new EventBus(); + ((IBootstrap)_eventBus).Setup(Repo); + } + return _eventBus; + } + } protected static void ClearKernel() { @@ -77,6 +89,11 @@ protected static void ClearKernel() ((IDisposable)_dependencyInjection).Dispose(); _dependencyInjection = null; } + if (_eventBus != null) + { + ((IDisposable)_eventBus).Dispose(); + _eventBus = null; + } if (_rpository != null) { ((IDisposable)_rpository).Dispose(); @@ -90,7 +107,7 @@ protected static void ClearKernel() #if UNITY_EDITOR public virtual IInspectorInfo[] GetAllInfo() { - return new IInspectorInfo[3] { _rpository, Services, DInjection }; + return new IInspectorInfo[4] { _rpository, Services, DInjection, EventBus }; } #endif } diff --git a/Runtime/Core/Framework/Subsystems/EventBus.cs b/Runtime/Core/Framework/Subsystems/EventBus.cs new file mode 100644 index 0000000..7cdf43e --- /dev/null +++ b/Runtime/Core/Framework/Subsystems/EventBus.cs @@ -0,0 +1,100 @@ +using System; +using System.Collections.Generic; +using UnityEngine; + +namespace RealMethod +{ + public sealed class EventBus : GameSubsystem + { + private readonly object _lock = new(); + private Dictionary> _subscribers => Data.Events; + + + + // GameSubsystem Methods + protected override void OnBegin() + { + } + protected override void OnEnd() + { + } + + + + + + public void Subscribe(Action listener) + { + var type = typeof(T); + + if (!_subscribers.TryGetValue(type, out var listeners)) + { + listeners = new List(); + _subscribers[type] = listeners; + } + + if (!listeners.Contains(listener)) + { + listeners.Add(listener); + } + } + public void Unsubscribe(Action listener) + { + var type = typeof(T); + + if (!_subscribers.TryGetValue(type, out var listeners)) + return; + + listeners.Remove(listener); + + if (listeners.Count == 0) + { + _subscribers.Remove(type); + } + } + public void Publish(T eventData) + { + var type = typeof(T); + + if (!_subscribers.TryGetValue(type, out var listeners)) + return; + + var listenersCopy = listeners.ToArray(); + + foreach (var listener in listenersCopy) + { + try + { + ((Action)listener)?.Invoke(eventData); + } + catch (Exception ex) + { + Debug.LogException(ex); + } + } + } + public void Clear() + { + _subscribers.Clear(); + } + + +#if UNITY_EDITOR + protected override string GetInspectorInfor() + { + System.Text.StringBuilder sb = new System.Text.StringBuilder(); + + for (int i = 0; i < _subscribers.Count; i++) + { + var type = _subscribers.GetKey(i); + List weakRef = _subscribers.GetValue(i); + sb.AppendLine($"{i}. {type.Name} -> Listener ({weakRef.Count})"); + } + + return sb.ToString(); + } +#endif + + } + +} \ No newline at end of file diff --git a/Runtime/Core/Framework/Subsystems/EventBus.cs.meta b/Runtime/Core/Framework/Subsystems/EventBus.cs.meta new file mode 100644 index 0000000..e991dba --- /dev/null +++ b/Runtime/Core/Framework/Subsystems/EventBus.cs.meta @@ -0,0 +1,2 @@ +fileFormatVersion: 2 +guid: 78b636ff334a55f4a8ccbafda05b0cf3 \ No newline at end of file From 569f3c55454c5c9fda7a986a0160d1378c55e3ac Mon Sep 17 00:00:00 2001 From: Alijimpa Date: Sun, 10 May 2026 17:07:48 +0330 Subject: [PATCH 199/204] Fix Bridge Name and Service locator filter for Log --- Runtime/Core/Architecture/GameBridge.cs | 2 +- Runtime/Core/Framework/Subsystems/ServiceLocator.cs | 13 ++++++++----- 2 files changed, 9 insertions(+), 6 deletions(-) diff --git a/Runtime/Core/Architecture/GameBridge.cs b/Runtime/Core/Architecture/GameBridge.cs index 8a53f9b..b22aaad 100644 --- a/Runtime/Core/Architecture/GameBridge.cs +++ b/Runtime/Core/Architecture/GameBridge.cs @@ -492,7 +492,7 @@ private IEnumerator LoadWorldAsync(WorldAsset WS) // Implement IInspectorInfo Interface string IInspectorInfo.GetInfo() { - return $"IsLoading ({IsLoading}) , FadeTime ({FadeTime}) , {GetInspectorInfo()}"; + return $"IsLoading ({IsLoading}) , FadeTime ({FadeTime}) , BridgeConnect ({bridges.Count}) , {GetInspectorInfo()}"; } protected virtual string GetInspectorInfo() { diff --git a/Runtime/Core/Framework/Subsystems/ServiceLocator.cs b/Runtime/Core/Framework/Subsystems/ServiceLocator.cs index d2fef6a..441d0ea 100644 --- a/Runtime/Core/Framework/Subsystems/ServiceLocator.cs +++ b/Runtime/Core/Framework/Subsystems/ServiceLocator.cs @@ -216,11 +216,14 @@ protected override string GetInspectorInfor() for (int i = 0; i < _services.Count; i++) { var type = _services.GetKey(i); - var weakRef = _services.GetValue(i); - if (weakRef.TryGetTarget(out var target)) - sb.AppendLine($"{i}. {type.Name} -> Alive ({target})"); - else - sb.AppendLine($"{i}. {type.Name} -> Collected"); + if (typeof(IService).IsAssignableFrom(type)) + { + var weakRef = _services.GetValue(i); + if (weakRef.TryGetTarget(out var target)) + sb.AppendLine($"{i}. {type.Name} -> Alive ({target})"); + else + sb.AppendLine($"{i}. {type.Name} -> Collected"); + } } return sb.ToString(); From 3f48d66ab9c1c73cfd7c53e893c5f33d5b936d37 Mon Sep 17 00:00:00 2001 From: Alijimpa Date: Sun, 10 May 2026 17:11:33 +0330 Subject: [PATCH 200/204] Implement Base Stracture for notify --- Runtime/Core/Definitions/RealMethodNames.cs | 3 +++ Runtime/Library/Extension/Object.cs | 11 +++++++++++ Runtime/Library/Interfaces/Notifiable.cs | 7 +++++++ Runtime/Library/Interfaces/Notifiable.cs.meta | 2 ++ 4 files changed, 23 insertions(+) create mode 100644 Runtime/Library/Interfaces/Notifiable.cs create mode 100644 Runtime/Library/Interfaces/Notifiable.cs.meta diff --git a/Runtime/Core/Definitions/RealMethodNames.cs b/Runtime/Core/Definitions/RealMethodNames.cs index e1015a0..440471b 100644 --- a/Runtime/Core/Definitions/RealMethodNames.cs +++ b/Runtime/Core/Definitions/RealMethodNames.cs @@ -21,6 +21,9 @@ public static class MessageNames // Register public const string Register = "OnRegister"; public const string Unregister = "OnUnregister"; + + // Messaenger + public const string Notify = "OnNotify"; } public static class FunctionNames diff --git a/Runtime/Library/Extension/Object.cs b/Runtime/Library/Extension/Object.cs index f856350..7291d90 100644 --- a/Runtime/Library/Extension/Object.cs +++ b/Runtime/Library/Extension/Object.cs @@ -235,6 +235,17 @@ public static void InvokeUnreqisterEvent(this object obj, SendMessageOptions opt obj.SendMessage(MessageNames.Unregister, option); } } + public static void InvokeNotify(this object obj, string tag, SendMessageOptions option = SendMessageOptions.RequireReceiver) + { + if (obj is INotifiable provider) + { + provider.OnNotify(tag); + } + else + { + obj.SendMessage(MessageNames.Notify, tag, option); + } + } public static void SendMessage(this object obj, string methodName, SendMessageOptions option) { obj.SendMessage(methodName, null, option); diff --git a/Runtime/Library/Interfaces/Notifiable.cs b/Runtime/Library/Interfaces/Notifiable.cs new file mode 100644 index 0000000..ee11ca6 --- /dev/null +++ b/Runtime/Library/Interfaces/Notifiable.cs @@ -0,0 +1,7 @@ +namespace RealMethod +{ + public interface INotifiable + { + void OnNotify(string tag); + } +} \ No newline at end of file diff --git a/Runtime/Library/Interfaces/Notifiable.cs.meta b/Runtime/Library/Interfaces/Notifiable.cs.meta new file mode 100644 index 0000000..ad691b8 --- /dev/null +++ b/Runtime/Library/Interfaces/Notifiable.cs.meta @@ -0,0 +1,2 @@ +fileFormatVersion: 2 +guid: 9c6e6c363a0724d44ae42c5137136c6a \ No newline at end of file From dabdd94f95bf9f20fe3b371667fcf75f29dbbd05 Mon Sep 17 00:00:00 2001 From: Alijimpa Date: Sun, 10 May 2026 18:38:36 +0330 Subject: [PATCH 201/204] Implement EnumStorage for GAme --- Runtime/Core/Architecture/Game.cs | 27 +--- Runtime/Core/Definitions/EnumStorage.cs | 124 +++++++++++++++++++ Runtime/Core/Definitions/EnumStorage.cs.meta | 2 + Runtime/Core/Definitions/GlobalEnum.cs | 31 +---- Runtime/ReadySet/Managers/MusicManager.cs | 10 +- 5 files changed, 137 insertions(+), 57 deletions(-) create mode 100644 Runtime/Core/Definitions/EnumStorage.cs create mode 100644 Runtime/Core/Definitions/EnumStorage.cs.meta diff --git a/Runtime/Core/Architecture/Game.cs b/Runtime/Core/Architecture/Game.cs index 51b7a5f..4ed01a6 100644 --- a/Runtime/Core/Architecture/Game.cs +++ b/Runtime/Core/Architecture/Game.cs @@ -72,7 +72,7 @@ public static GameObject Player /// /// Reperesent Game State that youser can define state in ProjectSetting /// - public static GlobalEnum State { get; private set; } = 0; + public static readonly EnumStorage State = new EnumStorage(); /// /// Indicates whether a scene or world load operation is currently in progress. /// @@ -97,19 +97,12 @@ public static bool IsPaused /// Return true when game in loading section for new scene /// public static bool IsLoading => Instance.IsGameLoading(); - - /// /// Invoked when the process finishes. /// Process in your game take define with yourelf. /// (for example: show win screen, game over UI, load next level, etc). /// public static event Action OnCompleted; - /// - /// Invoked when game state changed. - /// - public static event Action OnStateChanged; - @@ -610,22 +603,6 @@ public static void SetSpeed(float speed, bool physicSafe = true) Time.fixedDeltaTime = 0.02f * Time.timeScale; // Keeps physics in sync } /// - /// Sets the GameState to new state you want. - /// - /// Target State you want to cahgne - /// the refrence from who want to change the gamestate - /// - public static bool SetState(int NewState, object author) - { - if (Instance.CanChangeState(State, NewState, author)) - { - State = NewState; - OnStateChanged?.Invoke(State); - return true; - } - return false; - } - /// /// Saves the provided file using the active implementation. /// Logs a warning if no save system is available. /// @@ -952,6 +929,8 @@ private void Notify_OnGameQuit() { Application.quitting -= Notify_OnGameQuit; OnGameClosed(); + // State + ((IDisposable)State).Dispose(); // Scope CloseScope(); // Bridge diff --git a/Runtime/Core/Definitions/EnumStorage.cs b/Runtime/Core/Definitions/EnumStorage.cs new file mode 100644 index 0000000..1eca887 --- /dev/null +++ b/Runtime/Core/Definitions/EnumStorage.cs @@ -0,0 +1,124 @@ +using System; +using System.Collections.Generic; + +namespace RealMethod +{ + public sealed class EnumStorage : IDisposable + { + private GlobalEnum _state; + private readonly Dictionary _values = new(); + /// + /// Invoked when game state changed. + /// + public event Action OnStateChanged; + + public GlobalEnum Global + { + get => _state; + set + { + if (_state == value) + return; + + var old = _state; + _state = value; + + OnStateChanged?.Invoke(old, _state); + } + } + + // Implement IDisposable Interface + void IDisposable.Dispose() + { + _values.Clear(); + } + + public void Set(T enumValue) where T : Enum + { + _values[typeof(T)] = Convert.ToByte(enumValue); + } + public T Get() where T : Enum + { + Type type = typeof(T); + + if (!_values.TryGetValue(type, out byte storedValue)) + { + storedValue = 0; + _values[type] = 0; + } + + return (T)Enum.ToObject(type, storedValue); + } + + + // -------- Operator Overloads -------- + public static implicit operator GlobalEnum(EnumStorage storage) + { + return storage.Global; + } + + public static implicit operator EnumStorage(GlobalEnum value) + { + return new EnumStorage { Global = value }; + } + + public static bool operator ==(EnumStorage a, GlobalEnum b) + => a is not null && a._state == b; + + public static bool operator !=(EnumStorage a, GlobalEnum b) + => !(a == b); + + public static bool operator <(EnumStorage a, GlobalEnum b) + => a is not null && a._state < b; + + public static bool operator >(EnumStorage a, GlobalEnum b) + => a is not null && a._state > b; + + public static bool operator <=(EnumStorage a, GlobalEnum b) + => a is not null && a._state <= b; + + public static bool operator >=(EnumStorage a, GlobalEnum b) + => a is not null && a._state >= b; + + public static bool operator ==(GlobalEnum a, EnumStorage b) + => b == a; + + public static bool operator !=(GlobalEnum a, EnumStorage b) + => !(b == a); + + public static bool operator <(GlobalEnum a, EnumStorage b) + => b is not null && a < b._state; + + public static bool operator >(GlobalEnum a, EnumStorage b) + => b is not null && a > b._state; + + public static bool operator <=(GlobalEnum a, EnumStorage b) + => b is not null && a <= b._state; + + public static bool operator >=(GlobalEnum a, EnumStorage b) + => b is not null && a >= b._state; + + // -------- Overrides -------- + + public override bool Equals(object obj) + { + if (obj is EnumStorage other) + return _state.Equals(other._state); + + if (obj is GlobalEnum e) + return _state.Equals(e); + + return false; + } + + public override int GetHashCode() + { + return _state.GetHashCode(); + } + + public override string ToString() + { + return _state.ToString(); + } + } +} \ No newline at end of file diff --git a/Runtime/Core/Definitions/EnumStorage.cs.meta b/Runtime/Core/Definitions/EnumStorage.cs.meta new file mode 100644 index 0000000..6b5981d --- /dev/null +++ b/Runtime/Core/Definitions/EnumStorage.cs.meta @@ -0,0 +1,2 @@ +fileFormatVersion: 2 +guid: 62bca4ee2575e6240a01e4f582caa5c8 \ No newline at end of file diff --git a/Runtime/Core/Definitions/GlobalEnum.cs b/Runtime/Core/Definitions/GlobalEnum.cs index ef59a60..64cd470 100644 --- a/Runtime/Core/Definitions/GlobalEnum.cs +++ b/Runtime/Core/Definitions/GlobalEnum.cs @@ -14,33 +14,8 @@ public struct GlobalEnum { [SerializeField] private int Value; // <-- this name must match + - public GlobalEnum(int index = 0) - { - Value = index; - } - public GlobalEnum(byte index = 0) - { - Value = index; - } - - - public static implicit operator GlobalEnum(int val) - { - return new GlobalEnum(val); - } - public static implicit operator int(GlobalEnum status) - { - return status.Value; - } - public static implicit operator GlobalEnum(byte val) - { - return new GlobalEnum(val); - } - public static implicit operator byte(GlobalEnum status) - { - return (byte)status.Value; - } public static bool operator ==(GlobalEnum a, GlobalEnum b) { return a.Value == b.Value; @@ -91,14 +66,14 @@ public override string ToString() } else { - return $"SettingEnum index [{Value}]"; + return $"GlobalEnum index [{Value}]"; } } #else public override string ToString() { - return $"SettingEnum index [{Value}]"; + return $"GlobalEnum index [{Value}]"; } #endif diff --git a/Runtime/ReadySet/Managers/MusicManager.cs b/Runtime/ReadySet/Managers/MusicManager.cs index d7a7129..1f55307 100644 --- a/Runtime/ReadySet/Managers/MusicManager.cs +++ b/Runtime/ReadySet/Managers/MusicManager.cs @@ -22,7 +22,7 @@ public override void InitiateManager(Scope owner) // Unity Methods private void OnEnable() { - Game.OnStateChanged += OnStateChange; + Game.State.OnStateChanged += OnStateChange; } protected override void Start() { @@ -34,7 +34,7 @@ protected override void Start() } private void OnDisable() { - Game.OnStateChanged -= OnStateChange; + Game.State.OnStateChanged -= OnStateChange; } // CompositManager Methods @@ -44,11 +44,11 @@ protected override bool CompairStates(GlobalEnum State_A, GlobalEnum State_B) } // Functions - private void OnStateChange(int stateIndex) + private void OnStateChange(GlobalEnum a, GlobalEnum b) { - if (IsValidState(stateIndex)) + if (IsValidState(b)) { - PlayState(stateIndex); + PlayState(b); } } } From 0dee5d5276a5d0a914bbd0aa0a64f3f026e5a051 Mon Sep 17 00:00:00 2001 From: Alijimpa Date: Mon, 11 May 2026 18:17:04 +0330 Subject: [PATCH 202/204] REsort files and folder --- .../EnumStorage.cs | 2 - .../EnumStorage.cs.meta | 0 Runtime/Core/Architecture/Game.cs | 135 +++++++----------- Runtime/Core/Framework/BaseClass.meta | 8 ++ .../Framework/{ => BaseClass}/GameModule.cs | 0 .../{ => BaseClass}/GameModule.cs.meta | 0 .../{ => BaseClass}/GameSubsystem.cs | 0 .../{ => BaseClass}/GameSubsystem.cs.meta | 0 8 files changed, 63 insertions(+), 82 deletions(-) rename Runtime/Core/{Definitions => Architecture}/EnumStorage.cs (99%) rename Runtime/Core/{Definitions => Architecture}/EnumStorage.cs.meta (100%) create mode 100644 Runtime/Core/Framework/BaseClass.meta rename Runtime/Core/Framework/{ => BaseClass}/GameModule.cs (100%) rename Runtime/Core/Framework/{ => BaseClass}/GameModule.cs.meta (100%) rename Runtime/Core/Framework/{ => BaseClass}/GameSubsystem.cs (100%) rename Runtime/Core/Framework/{ => BaseClass}/GameSubsystem.cs.meta (100%) diff --git a/Runtime/Core/Definitions/EnumStorage.cs b/Runtime/Core/Architecture/EnumStorage.cs similarity index 99% rename from Runtime/Core/Definitions/EnumStorage.cs rename to Runtime/Core/Architecture/EnumStorage.cs index 1eca887..d207504 100644 --- a/Runtime/Core/Definitions/EnumStorage.cs +++ b/Runtime/Core/Architecture/EnumStorage.cs @@ -110,12 +110,10 @@ public override bool Equals(object obj) return false; } - public override int GetHashCode() { return _state.GetHashCode(); } - public override string ToString() { return _state.ToString(); diff --git a/Runtime/Core/Definitions/EnumStorage.cs.meta b/Runtime/Core/Architecture/EnumStorage.cs.meta similarity index 100% rename from Runtime/Core/Definitions/EnumStorage.cs.meta rename to Runtime/Core/Architecture/EnumStorage.cs.meta diff --git a/Runtime/Core/Architecture/Game.cs b/Runtime/Core/Architecture/Game.cs index 4ed01a6..75bac70 100644 --- a/Runtime/Core/Architecture/Game.cs +++ b/Runtime/Core/Architecture/Game.cs @@ -11,24 +11,6 @@ namespace RealMethod { - /// - /// Represents the possible outcomes of a Game process. - /// - public enum GameProcess - { - /// - /// The process finished successfully. - /// - Success, - /// - /// The process failed. - /// - Failure, - /// - /// The process was cancelled before completion. - /// - Cancelled - } /// /// Core game singleton that manages the active , registered s, @@ -91,18 +73,31 @@ public static bool IsPaused } } } - public static bool IsGameInitialized { get; private set; } = false; /// /// Indicates whether the game is in loading stage /// Return true when game in loading section for new scene /// - public static bool IsLoading => Instance.IsGameLoading(); + public static bool IsLoading + { + get + { + if (Instance != null) + { + return Instance.IsGameLoading(); + } + else + { + Debug.LogWarning("GameInstance did not called !"); + return false; + } + } + } /// - /// Invoked when the process finishes. - /// Process in your game take define with yourelf. - /// (for example: show win screen, game over UI, load next level, etc). + /// Indicate whether the game complitly initialized. + /// after true OnGameInitialized called. + /// befor first scene load /// - public static event Action OnCompleted; + public static bool IsGameInitialized { get; private set; } = false; @@ -254,14 +249,6 @@ private static void RuntimeAfterSceneLoad() - - /// - /// Attempts to invoke - /// - public static void Complete(GameProcess result) - { - OnCompleted.Invoke(result); - } /// /// Attempts to cast the global to the specified type . /// Logs an error and returns null if the cast fails. @@ -299,6 +286,42 @@ public static T CastWorld() where T : class } } /// + /// Retrieves a manager of type from the active manager scopes. + /// The search is performed in the following order: + /// 1. The current World scope (if available). + /// 2. The global Instance scope. + /// + /// The type of manager to retrieve. + /// + /// The manager of type if found; otherwise null. + /// + public static T GetManager() where T : Component, IGameManager + { + if (World != null && World.TryFindGameManager(out T worldResult)) + return worldResult; + + if (Instance.TryFindGameManager(out T gameResult)) + return gameResult; + + return null; + } + /// + /// Retrieves the service instance of type if available. + /// + /// IService type to retrieve. + /// The service instance of type , or null if not found. + public static T GetService() where T : IService + { + if (Services.TryGet(out T Myservice)) + { + return Myservice; + } + else + { + return default; + } + } + /// /// Injects dependencies into the specified target object using the internal dependency injection system. /// /// The object whose dependencies should be injected. @@ -328,22 +351,6 @@ public static bool Disable() where F : IFeature return DInjection.Unregister(); } /// - /// Retrieves the service instance of type if available. - /// - /// IService type to retrieve. - /// The service instance of type , or null if not found. - public static T GetService() where T : IService - { - if (Services.TryGet(out T Myservice)) - { - return Myservice; - } - else - { - return default; - } - } - /// /// Publishes an event to all subscribers of the specified event type. /// /// Type of the event. @@ -532,26 +539,6 @@ public static Coroutine ReOpenScene() return Instance.StartCoroutine(Bridge.GetLoadScneCorotine(SceneManager.GetActiveScene().name)); ; } /// - /// Retrieves a manager of type from the active manager scopes. - /// The search is performed in the following order: - /// 1. The current World scope (if available). - /// 2. The global Instance scope. - /// - /// The type of manager to retrieve. - /// - /// The manager of type if found; otherwise null. - /// - public static T GetManager() where T : Component, IGameManager - { - if (World != null && World.TryFindGameManager(out T worldResult)) - return worldResult; - - if (Instance.TryFindGameManager(out T gameResult)) - return gameResult; - - return null; - } - /// /// Parents the provided GameObject to the game root instance. /// /// The GameObject to hold under the game root. @@ -897,18 +884,6 @@ protected virtual bool IsGameLoading() { return Bridge.IsLoading; } - /// - /// Check for changing state from A to B by author. - /// - /// Current state - /// Target state - /// this object want to change state - /// - protected virtual bool CanChangeState(int A, int B, object author) - { - return true; - } - diff --git a/Runtime/Core/Framework/BaseClass.meta b/Runtime/Core/Framework/BaseClass.meta new file mode 100644 index 0000000..83bb0f0 --- /dev/null +++ b/Runtime/Core/Framework/BaseClass.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 0cb2e08d9acb8624aacf270ca02db351 +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Runtime/Core/Framework/GameModule.cs b/Runtime/Core/Framework/BaseClass/GameModule.cs similarity index 100% rename from Runtime/Core/Framework/GameModule.cs rename to Runtime/Core/Framework/BaseClass/GameModule.cs diff --git a/Runtime/Core/Framework/GameModule.cs.meta b/Runtime/Core/Framework/BaseClass/GameModule.cs.meta similarity index 100% rename from Runtime/Core/Framework/GameModule.cs.meta rename to Runtime/Core/Framework/BaseClass/GameModule.cs.meta diff --git a/Runtime/Core/Framework/GameSubsystem.cs b/Runtime/Core/Framework/BaseClass/GameSubsystem.cs similarity index 100% rename from Runtime/Core/Framework/GameSubsystem.cs rename to Runtime/Core/Framework/BaseClass/GameSubsystem.cs diff --git a/Runtime/Core/Framework/GameSubsystem.cs.meta b/Runtime/Core/Framework/BaseClass/GameSubsystem.cs.meta similarity index 100% rename from Runtime/Core/Framework/GameSubsystem.cs.meta rename to Runtime/Core/Framework/BaseClass/GameSubsystem.cs.meta From cafe630e12d3e80b7c98ca4d0b023641bee2d1f1 Mon Sep 17 00:00:00 2001 From: Alijimpa Date: Mon, 11 May 2026 18:17:18 +0330 Subject: [PATCH 203/204] Implement Simple MissionManager --- Tests/MissionManager.cs | 49 ++++++++++++++++++++++++++++++++++++ Tests/MissionManager.cs.meta | 2 ++ 2 files changed, 51 insertions(+) create mode 100644 Tests/MissionManager.cs create mode 100644 Tests/MissionManager.cs.meta diff --git a/Tests/MissionManager.cs b/Tests/MissionManager.cs new file mode 100644 index 0000000..557c558 --- /dev/null +++ b/Tests/MissionManager.cs @@ -0,0 +1,49 @@ +using System; +using UnityEngine; + +namespace RealMethod +{ + /// + /// Represents the possible outcomes of a Game process. + /// + public enum GameProcess + { + /// + /// The process finished successfully. + /// + Success, + /// + /// The process failed. + /// + Failure, + /// + /// The process was cancelled before completion. + /// + Cancelled + } + + public class MissionManager2 : MonoBehaviour, IGameManager + { + /// + /// Invoked when the process finishes. + /// Process in your game take define with yourelf. + /// (for example: show win screen, game over UI, load next level, etc). + /// + public static event Action OnCompleted; + + public void InitiateManager(Scope owner) + { + throw new System.NotImplementedException(); + } + + /// + /// Attempts to invoke + /// + public void Complete(GameProcess result) + { + OnCompleted.Invoke(result); + } + + + } +} \ No newline at end of file diff --git a/Tests/MissionManager.cs.meta b/Tests/MissionManager.cs.meta new file mode 100644 index 0000000..201eff8 --- /dev/null +++ b/Tests/MissionManager.cs.meta @@ -0,0 +1,2 @@ +fileFormatVersion: 2 +guid: 6af078be0e3f22740a33816d1826bc98 \ No newline at end of file From 09189b4c0d9218e690a924f1d8e57f233dac98e6 Mon Sep 17 00:00:00 2001 From: Alijimpa Date: Tue, 12 May 2026 16:28:13 +0330 Subject: [PATCH 204/204] Implement EventAsset --- Runtime/Core/Architecture/Game.cs | 6 +- Runtime/Pattern/Assets/DelegateAsset.cs | 210 ++++++++++++++++++ Runtime/Pattern/Assets/DelegateAsset.cs.meta | 2 + Runtime/ReadySet/Presets/DrawAsset.cs | 2 +- Runtime/ReadySet/Presets/EventAssets.meta | 8 + .../Presets/EventAssets/EventAsset.cs | 52 +++++ .../Presets/EventAssets/EventAsset.cs.meta | 2 + .../Presets/EventAssets/EventAsset_Bool.cs | 10 + .../EventAssets/EventAsset_Bool.cs.meta | 2 + .../Presets/EventAssets/EventAsset_Float.cs | 10 + .../EventAssets/EventAsset_Float.cs.meta | 2 + .../Presets/EventAssets/EventAsset_Int.cs | 10 + .../EventAssets/EventAsset_Int.cs.meta | 2 + 13 files changed, 314 insertions(+), 4 deletions(-) create mode 100644 Runtime/Pattern/Assets/DelegateAsset.cs create mode 100644 Runtime/Pattern/Assets/DelegateAsset.cs.meta create mode 100644 Runtime/ReadySet/Presets/EventAssets.meta create mode 100644 Runtime/ReadySet/Presets/EventAssets/EventAsset.cs create mode 100644 Runtime/ReadySet/Presets/EventAssets/EventAsset.cs.meta create mode 100644 Runtime/ReadySet/Presets/EventAssets/EventAsset_Bool.cs create mode 100644 Runtime/ReadySet/Presets/EventAssets/EventAsset_Bool.cs.meta create mode 100644 Runtime/ReadySet/Presets/EventAssets/EventAsset_Float.cs create mode 100644 Runtime/ReadySet/Presets/EventAssets/EventAsset_Float.cs.meta create mode 100644 Runtime/ReadySet/Presets/EventAssets/EventAsset_Int.cs create mode 100644 Runtime/ReadySet/Presets/EventAssets/EventAsset_Int.cs.meta diff --git a/Runtime/Core/Architecture/Game.cs b/Runtime/Core/Architecture/Game.cs index 75bac70..5167e80 100644 --- a/Runtime/Core/Architecture/Game.cs +++ b/Runtime/Core/Architecture/Game.cs @@ -355,7 +355,7 @@ public static bool Disable() where F : IFeature /// /// Type of the event. /// The event data to publish. - public void Publish(T eventData) where T : IEvent + public static void Publish(T eventData) where T : IEvent { EventBus.Publish(eventData); } @@ -364,7 +364,7 @@ public void Publish(T eventData) where T : IEvent /// /// Type of the event to listen for. /// Callback invoked when the event is published. - public void Subscribe(Action listener) where T : IEvent + public static void Subscribe(Action listener) where T : IEvent { EventBus.Subscribe(listener); } @@ -373,7 +373,7 @@ public void Subscribe(Action listener) where T : IEvent /// /// Type of the event. /// The listener to remove. - public void Unsubscribe(Action listener) where T : IEvent + public static void Unsubscribe(Action listener) where T : IEvent { EventBus.Subscribe(listener); } diff --git a/Runtime/Pattern/Assets/DelegateAsset.cs b/Runtime/Pattern/Assets/DelegateAsset.cs new file mode 100644 index 0000000..655fd58 --- /dev/null +++ b/Runtime/Pattern/Assets/DelegateAsset.cs @@ -0,0 +1,210 @@ +using System; +using UnityEngine; + +namespace RealMethod +{ + public abstract class DelegateAsset : UniqueAsset + { + public abstract void Invoke(); + + public abstract void AddListener(D listener) where D : Delegate; + public abstract void RemoveListener(D listener) where D : Delegate; + +#if UNITY_EDITOR + [ContextMenu("Invoke")] + private void Raise() + { + Invoke(); + } +#endif + } + + public abstract class EventAsset : DelegateAsset + { + [SerializeField] + private bool CanUseDefaultValue = false; + [SerializeField, ConditionalHide("CanUseDefaultValue", true, false)] + private T DefaultValue; + private event Action _event; + + + public void Invoke(T value) + { + _event?.Invoke(value); + } + + public override void Invoke() + { + if (CanUseDefaultValue) + { + _event?.Invoke(DefaultValue); + } + else + { + Debug.LogWarning($"You can Invoke {GetType().Name} Event with Defaut value, [CanUseDefaultValue = false]"); + } + } + public override void AddListener(D listener) + { + if (listener is Action provider) + { + _event += provider; + } + else + { + Debug.LogWarning($"The listener should be {typeof(Action)} for binding, AddListener Faild!"); + } + } + public override void RemoveListener(D listener) + { + if (listener is Action provider) + { + _event -= provider; + } + else + { + Debug.LogWarning($"The listener should be {typeof(Action)} for binding, AddListener Faild!"); + } + } + + + // -------- Operator Overloads -------- + public static EventAsset operator +(EventAsset asset, Action listener) + { + asset._event += listener; + return asset; + } + public static EventAsset operator -(EventAsset asset, Action listener) + { + asset._event -= listener; + return asset; + } + } + public abstract class EventAsset : DelegateAsset + { + [SerializeField] + private bool CanUseDefaultValue = false; + [SerializeField, ConditionalHide("CanUseDefaultValue", true, false)] + private T DefaultValue_st; + [SerializeField, ConditionalHide("CanUseDefaultValue", true, false)] + private J DefaultValue_nd; + + private event Action _event; + + public void Invoke(T value, J value2) + { + _event?.Invoke(value, value2); + } + + + public override void Invoke() + { + if (CanUseDefaultValue) + { + _event?.Invoke(DefaultValue_st, DefaultValue_nd); + } + else + { + Debug.LogWarning($"You can Invoke {GetType().Name} Event with Defaut value"); + } + } + public override void AddListener(D listener) + { + if (listener is Action provider) + { + _event += provider; + } + else + { + Debug.LogWarning($"The listener should be {typeof(Action)} for binding, AddListener Faild!"); + } + } + public override void RemoveListener(D listener) + { + if (listener is Action provider) + { + _event -= provider; + } + else + { + Debug.LogWarning($"The listener should be {typeof(Action)} for binding, AddListener Faild!"); + } + } + + // -------- Operator Overloads -------- + public static EventAsset operator +(EventAsset asset, Action listener) + { + asset._event += listener; + return asset; + } + public static EventAsset operator -(EventAsset asset, Action listener) + { + asset._event -= listener; + return asset; + } + } + public abstract class EventAsset : DelegateAsset + { + [SerializeField] + private bool CanUseDefaultValue = false; + [SerializeField, ConditionalHide("CanUseDefaultValue", true, false)] + private T DefaultValue_st; + [SerializeField, ConditionalHide("CanUseDefaultValue", true, false)] + private J DefaultValue_nd; + [SerializeField, ConditionalHide("CanUseDefaultValue", true, false)] + private F DefaultValue_rd; + + private event Action _event; + + public void Invoke(T value, J value2, F value3) + { + _event?.Invoke(value, value2, value3); + } + + public override void Invoke() + { + if (CanUseDefaultValue) + { + _event?.Invoke(DefaultValue_st, DefaultValue_nd, DefaultValue_rd); + } + else + { + Debug.LogWarning($"You can Invoke {GetType().Name} Event with Defaut value"); + } + } + public override void AddListener(D listener) + { + if (listener is Action provider) + { + _event += provider; + } + else + { + Debug.LogWarning($"The listener should be {typeof(Action)} for binding, AddListener Faild!"); + } + } + public override void RemoveListener(D listener) + { + if (listener is Action provider) + { + _event -= provider; + } + else + { + Debug.LogWarning($"The listener should be {typeof(Action)} for binding, AddListener Faild!"); + } + } + + // -------- Operator Overloads -------- + public static EventAsset operator +(EventAsset asset, Action listener) + { + asset._event += listener; + return asset; + } + public static EventAsset operator -(EventAsset asset, Action listener) + { + asset._event -= listener; + return asset; + } + } +} \ No newline at end of file diff --git a/Runtime/Pattern/Assets/DelegateAsset.cs.meta b/Runtime/Pattern/Assets/DelegateAsset.cs.meta new file mode 100644 index 0000000..399c94e --- /dev/null +++ b/Runtime/Pattern/Assets/DelegateAsset.cs.meta @@ -0,0 +1,2 @@ +fileFormatVersion: 2 +guid: 3c7a1be8157370e46899c483df7a9710 \ No newline at end of file diff --git a/Runtime/ReadySet/Presets/DrawAsset.cs b/Runtime/ReadySet/Presets/DrawAsset.cs index 7cee7c7..6fec7e5 100644 --- a/Runtime/ReadySet/Presets/DrawAsset.cs +++ b/Runtime/ReadySet/Presets/DrawAsset.cs @@ -4,7 +4,7 @@ namespace RealMethod { [CreateAssetMenu(fileName = "Draw", menuName = "RealMethod/Develop/DrawAsset", order = 1)] - public class DrawAsset : GUIAsset + public sealed class DrawAsset : GUIAsset { public event Action OnButtonClicked; public event Action OnToggleChanged; diff --git a/Runtime/ReadySet/Presets/EventAssets.meta b/Runtime/ReadySet/Presets/EventAssets.meta new file mode 100644 index 0000000..d9aaf74 --- /dev/null +++ b/Runtime/ReadySet/Presets/EventAssets.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: ff804b2662bedbc4a84d89dfe1020b8c +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Runtime/ReadySet/Presets/EventAssets/EventAsset.cs b/Runtime/ReadySet/Presets/EventAssets/EventAsset.cs new file mode 100644 index 0000000..a27b2d6 --- /dev/null +++ b/Runtime/ReadySet/Presets/EventAssets/EventAsset.cs @@ -0,0 +1,52 @@ +using System; +using UnityEngine; + +namespace RealMethod +{ + [CreateAssetMenu(fileName = "EventAsset", menuName = "RealMethod/Delegate/Event", order = 1)] + public class EventAsset : DelegateAsset + { + private event Action _event; + + public override void Invoke() + { + _event?.Invoke(); + } + public override void AddListener(T listener) + { + if (listener is Action provider) + { + _event += provider; + } + else + { + Debug.LogWarning($"The listener should be {typeof(Action)} for binding, AddListener Faild!"); + } + } + public override void RemoveListener(T listener) + { + if (listener is Action provider) + { + _event -= provider; + } + else + { + Debug.LogWarning($"The listener should be {typeof(Action)} for binding, AddListener Faild!"); + } + } + + + + // -------- Operator Overloads -------- + public static EventAsset operator +(EventAsset asset, Action listener) + { + asset._event += listener; + return asset; + } + public static EventAsset operator -(EventAsset asset, Action listener) + { + asset._event -= listener; + return asset; + } + } +} \ No newline at end of file diff --git a/Runtime/ReadySet/Presets/EventAssets/EventAsset.cs.meta b/Runtime/ReadySet/Presets/EventAssets/EventAsset.cs.meta new file mode 100644 index 0000000..58f35f3 --- /dev/null +++ b/Runtime/ReadySet/Presets/EventAssets/EventAsset.cs.meta @@ -0,0 +1,2 @@ +fileFormatVersion: 2 +guid: afe46b0903a8c654d91c6b06a2bf66ba \ No newline at end of file diff --git a/Runtime/ReadySet/Presets/EventAssets/EventAsset_Bool.cs b/Runtime/ReadySet/Presets/EventAssets/EventAsset_Bool.cs new file mode 100644 index 0000000..8f04014 --- /dev/null +++ b/Runtime/ReadySet/Presets/EventAssets/EventAsset_Bool.cs @@ -0,0 +1,10 @@ +using UnityEngine; + +namespace RealMethod +{ + [CreateAssetMenu(fileName = "EventAsset_Bool", menuName = "RealMethod/Delegate/EventAsset_Bool", order = 1)] + public sealed class EventAsset_Bool : EventAsset + { + + } +} \ No newline at end of file diff --git a/Runtime/ReadySet/Presets/EventAssets/EventAsset_Bool.cs.meta b/Runtime/ReadySet/Presets/EventAssets/EventAsset_Bool.cs.meta new file mode 100644 index 0000000..ee63998 --- /dev/null +++ b/Runtime/ReadySet/Presets/EventAssets/EventAsset_Bool.cs.meta @@ -0,0 +1,2 @@ +fileFormatVersion: 2 +guid: cc70a3838fde1884a96551fb79c459cd \ No newline at end of file diff --git a/Runtime/ReadySet/Presets/EventAssets/EventAsset_Float.cs b/Runtime/ReadySet/Presets/EventAssets/EventAsset_Float.cs new file mode 100644 index 0000000..c6f71e3 --- /dev/null +++ b/Runtime/ReadySet/Presets/EventAssets/EventAsset_Float.cs @@ -0,0 +1,10 @@ +using UnityEngine; + +namespace RealMethod +{ + [CreateAssetMenu(fileName = "Event_Float", menuName = "RealMethod/Delegate/Event_Float", order = 1)] + public sealed class EventAsset_Float : EventAsset + { + + } +} \ No newline at end of file diff --git a/Runtime/ReadySet/Presets/EventAssets/EventAsset_Float.cs.meta b/Runtime/ReadySet/Presets/EventAssets/EventAsset_Float.cs.meta new file mode 100644 index 0000000..3a4c6d7 --- /dev/null +++ b/Runtime/ReadySet/Presets/EventAssets/EventAsset_Float.cs.meta @@ -0,0 +1,2 @@ +fileFormatVersion: 2 +guid: f4073eb9c78ffe7409ae092c2d31536f \ No newline at end of file diff --git a/Runtime/ReadySet/Presets/EventAssets/EventAsset_Int.cs b/Runtime/ReadySet/Presets/EventAssets/EventAsset_Int.cs new file mode 100644 index 0000000..52da6a8 --- /dev/null +++ b/Runtime/ReadySet/Presets/EventAssets/EventAsset_Int.cs @@ -0,0 +1,10 @@ +using UnityEngine; + +namespace RealMethod +{ + [CreateAssetMenu(fileName = "Event_Int", menuName = "RealMethod/Delegate/Event_Int", order = 1)] + public sealed class EventAsset_Int : EventAsset + { + + } +} \ No newline at end of file diff --git a/Runtime/ReadySet/Presets/EventAssets/EventAsset_Int.cs.meta b/Runtime/ReadySet/Presets/EventAssets/EventAsset_Int.cs.meta new file mode 100644 index 0000000..fc1df30 --- /dev/null +++ b/Runtime/ReadySet/Presets/EventAssets/EventAsset_Int.cs.meta @@ -0,0 +1,2 @@ +fileFormatVersion: 2 +guid: d02c747e423451242bc2b0292b38e1f2 \ No newline at end of file