forked from Shardstone/trail-into-darkness
Added a bunch of utilities and modfief the character data structue
This commit is contained in:
@@ -0,0 +1,154 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Diagnostics;
|
||||
using UnityEngine;
|
||||
#if UNITY_EDITOR
|
||||
using UnityEditor;
|
||||
#endif
|
||||
|
||||
namespace Jovian.Utilities {
|
||||
/// <summary>
|
||||
/// <b>Editor use-only.</b><br/>
|
||||
/// Allows easy access between different instances. Supports 1 instance per type. <br/>
|
||||
/// Add instances and retrieve elsewhere.<br/><br/>
|
||||
/// Read more: https://en.wikipedia.org/wiki/Service_locator_pattern
|
||||
/// </summary>
|
||||
public static class EditorServiceLocator {
|
||||
private sealed class ServiceNotFoundException : Exception {
|
||||
public ServiceNotFoundException(Type type) : base($"ServiceNotFoundException. Type={type}") { }
|
||||
}
|
||||
|
||||
private static Dictionary<Type, object> serviceContainer = new();
|
||||
public static bool IsDirty { get; private set; }
|
||||
|
||||
#if UNITY_EDITOR
|
||||
public static Dictionary<Type, object> ServiceContainer => serviceContainer;
|
||||
#endif
|
||||
|
||||
[RuntimeInitializeOnLoadMethod]
|
||||
public static void Init() {
|
||||
serviceContainer = new();
|
||||
}
|
||||
|
||||
#if UNITY_EDITOR
|
||||
[InitializeOnEnterPlayMode]
|
||||
private static void Reset(EnterPlayModeOptions options) {
|
||||
serviceContainer?.Clear();
|
||||
IsDirty = true;
|
||||
}
|
||||
#endif
|
||||
|
||||
/// <summary>
|
||||
/// Add an instance to the locator. Will throw an exception if a type already exists in the locator.
|
||||
/// <seealso cref="AddOrReplace{T}"/>
|
||||
/// </summary>
|
||||
[Conditional("UNITY_EDITOR")]
|
||||
public static void Add<T>(T service) {
|
||||
#if UNITY_EDITOR
|
||||
if (service == null) {
|
||||
throw new NullReferenceException($"Service is null. Expected instance of type '{typeof(T)}'");
|
||||
}
|
||||
|
||||
serviceContainer.Add(typeof(T), service);
|
||||
IsDirty = true;
|
||||
#else
|
||||
UnityEngine.Debug.LogWarning($"EditorServiceLocator should not be used outside of the Editor");
|
||||
#endif
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Add an instance to the locator. Will replace any existing instance without an exception.
|
||||
/// An alias for <see cref="Set{T}"/>
|
||||
/// </summary>
|
||||
[Conditional("UNITY_EDITOR")]
|
||||
public static void AddOrReplace<T>(T service) {
|
||||
Set(service);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Add an instance to the locator. Will replace any existing instance without an exception.
|
||||
/// An alias for <see cref="AddOrReplace{T}"/>
|
||||
/// </summary>
|
||||
[Conditional("UNITY_EDITOR")]
|
||||
public static void Set<T>(T service) {
|
||||
#if UNITY_EDITOR
|
||||
if (service == null) {
|
||||
throw new NullReferenceException($"Service is null. Expected instance of type '{typeof(T)}'");
|
||||
}
|
||||
|
||||
serviceContainer[typeof(T)] = service;
|
||||
IsDirty = true;
|
||||
#else
|
||||
UnityEngine.Debug.LogWarning($"EditorServiceLocator should not be used outside of the Editor");
|
||||
#endif
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Removes any type matching the instance passed in from the locator. This is good practice.
|
||||
/// </summary>
|
||||
/// <param name="service"></param>
|
||||
/// <typeparam name="T"></typeparam>
|
||||
/// <exception cref="NullReferenceException"></exception>
|
||||
[Conditional("UNITY_EDITOR")]
|
||||
public static void Remove<T>(T service) {
|
||||
#if UNITY_EDITOR
|
||||
if (service == null) {
|
||||
throw new NullReferenceException($"Service is null. Expected instance of type '{typeof(T)}'");
|
||||
}
|
||||
|
||||
serviceContainer.Remove(typeof(T));
|
||||
IsDirty = true;
|
||||
#else
|
||||
UnityEngine.Debug.LogWarning($"EditorServiceLocator should not be used outside of the Editor");
|
||||
#endif
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Retrieves an instance from the locator matching the type. Will throw an exception if nothing is found.
|
||||
/// <seealso cref="TryGet{T}(out T)"/>
|
||||
/// </summary>
|
||||
public static T Get<T>() {
|
||||
#if UNITY_EDITOR
|
||||
if (serviceContainer.TryGetValue(typeof(T), out object service)) {
|
||||
return (T)service;
|
||||
}
|
||||
#endif
|
||||
throw new ServiceNotFoundException(typeof(T));
|
||||
}
|
||||
|
||||
[Obsolete("Use Get<T> or TryGet<T>(out T) since they follow the C# conventions for TryGet")]
|
||||
public static T TryGet<T>() {
|
||||
#if UNITY_EDITOR
|
||||
if (serviceContainer.TryGetValue(typeof(T), out object service)) {
|
||||
return (T)service;
|
||||
}
|
||||
#endif
|
||||
return default;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Retrieves an instance from the locator matching the type. Returns true/false based on success.
|
||||
/// </summary>
|
||||
public static bool TryGet<T>(out T instance) {
|
||||
#if UNITY_EDITOR
|
||||
if (serviceContainer.TryGetValue(typeof(T), out object service)) {
|
||||
instance = (T)service;
|
||||
return instance != null;
|
||||
}
|
||||
#endif
|
||||
instance = default;
|
||||
return false;
|
||||
}
|
||||
|
||||
[Conditional("UNITY_EDITOR")]
|
||||
public static void Clear() {
|
||||
serviceContainer.Clear();
|
||||
IsDirty = true;
|
||||
}
|
||||
|
||||
[Conditional("UNITY_EDITOR")]
|
||||
public static void Clean() {
|
||||
IsDirty = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user