255 lines
7.3 KiB
C#
255 lines
7.3 KiB
C#
using System;
|
|
using System.Text;
|
|
using System.Collections.Generic;
|
|
using Golems.Attributes;
|
|
#if UNITY_EDITOR
|
|
using UnityEditor;
|
|
#endif
|
|
using UnityEngine;
|
|
using UnityEngine.Serialization;
|
|
|
|
namespace RogueUtils.Data
|
|
{
|
|
public abstract class BaseVariable<T> : SubBaseVariable, IValueMonitor<T>
|
|
#if UNITY_EDITOR
|
|
, ISerializationCallbackReceiver
|
|
#endif
|
|
{
|
|
//
|
|
// NOTE: you cannot have Editor only serialised fields in Generics, it will crash a build
|
|
// see https://issuetracker.unity3d.com/issues/serialization-layout-error-thrown-in-build-when-using-generic-classes-with-fields-that-only-exist-in-the-editor
|
|
//
|
|
[Multiline] public string m_Description = "";
|
|
|
|
[SerializeField] protected T m_Value;
|
|
|
|
// DW: Lets re-implement this down the line
|
|
/*#if UNITY_EDITOR
|
|
[NonSerialized]
|
|
[ShowInInspector]
|
|
[OnValueChanged("BaseHandleEditorValueChange")]
|
|
[LabelText("Value")]
|
|
//
|
|
// This is an inspector editable version of the value
|
|
//
|
|
protected T m_EditorValue;
|
|
#endif*/
|
|
|
|
/// <summary>
|
|
/// The reason for the m_ZeroOnExitPlayMode is that it is an Unity Editor only feature and
|
|
/// resets the Variable value so that Git does not see a bunch of changes to runtime
|
|
/// ScriptableObject Variables
|
|
/// </summary>
|
|
[SerializeField]
|
|
protected bool m_DefaultOnExitPlayMode = false;
|
|
|
|
private event EventHandler<OnChangeEventArgs> InternalOnChange;
|
|
|
|
public event EventHandler<OnChangeEventArgs> OnChange
|
|
{
|
|
add
|
|
{
|
|
InternalOnChange += value;
|
|
}
|
|
|
|
remove
|
|
{
|
|
InternalOnChange -= value;
|
|
}
|
|
}
|
|
|
|
public class OnChangeEventArgs : EventArgs
|
|
{
|
|
public T OldValue { get; private set; }
|
|
|
|
public T NewValue { get; private set; }
|
|
|
|
public OnChangeEventArgs(T value)
|
|
{
|
|
OldValue = value;
|
|
NewValue = value;
|
|
}
|
|
|
|
public OnChangeEventArgs(T oldValue, T newValue)
|
|
{
|
|
OldValue = oldValue;
|
|
NewValue = newValue;
|
|
}
|
|
}
|
|
|
|
protected virtual T DefaultValue
|
|
{
|
|
get => default;
|
|
}
|
|
|
|
public virtual T Value
|
|
{
|
|
get
|
|
{
|
|
return m_Value;
|
|
}
|
|
set
|
|
{
|
|
T oldValue = m_Value;
|
|
m_Value = value;
|
|
/*#if UNITY_EDITOR
|
|
m_EditorValue = m_Value;
|
|
#endif*/
|
|
BaseHandleValueChange();
|
|
InternalOnChange?.Invoke(this, new OnChangeEventArgs(oldValue, m_Value));
|
|
}
|
|
}
|
|
|
|
[Button]
|
|
public void ForceOnChange()
|
|
{
|
|
InternalOnChange?.Invoke(this, new OnChangeEventArgs(m_Value));
|
|
}
|
|
|
|
public override TValue GetValue<TValue>()
|
|
{
|
|
var value = Value;
|
|
if (value is TValue theValue)
|
|
{
|
|
return theValue;
|
|
}
|
|
return default;
|
|
}
|
|
|
|
public override object GetValueUntyped()
|
|
{
|
|
return Value;
|
|
}
|
|
|
|
public override void SetValueUntyped(object value)
|
|
{
|
|
if (value is T theValue)
|
|
{
|
|
Value = theValue;
|
|
}
|
|
}
|
|
|
|
public void MonitoredValueChanged(T value, T _)
|
|
{
|
|
Value = value;
|
|
}
|
|
|
|
protected virtual void OnEnable()
|
|
{
|
|
#if UNITY_EDITOR
|
|
EditorApplication.playModeStateChanged += HandlePlayModeStateChange;
|
|
#endif
|
|
}
|
|
|
|
protected virtual void OnDisable()
|
|
{
|
|
#if UNITY_EDITOR
|
|
EditorApplication.playModeStateChanged -= HandlePlayModeStateChange;
|
|
#endif
|
|
}
|
|
|
|
#if UNITY_EDITOR
|
|
private void HandlePlayModeStateChange(PlayModeStateChange stateChange)
|
|
{
|
|
bool doDefaultValue = false;
|
|
switch (stateChange)
|
|
{
|
|
case PlayModeStateChange.EnteredEditMode:
|
|
break;
|
|
case PlayModeStateChange.ExitingEditMode:
|
|
break;
|
|
case PlayModeStateChange.EnteredPlayMode:
|
|
break;
|
|
case PlayModeStateChange.ExitingPlayMode:
|
|
doDefaultValue = m_DefaultOnExitPlayMode;
|
|
break;
|
|
}
|
|
|
|
if (doDefaultValue)
|
|
{
|
|
var defaultValue = DefaultValue;
|
|
//Undo.RecordObject(this, $"{name}: Clearing list");
|
|
m_Value = defaultValue;
|
|
#if UNITY_EDITOR
|
|
// m_EditorValue = m_Value;
|
|
#endif
|
|
//
|
|
// Marking this dirty so Unity sees the value is its default value
|
|
// JJA: Doing this means the user has to manually save otherwise the Dirty flag carries over to the next time
|
|
// Play is hit, causing it to save with the value it has after entering play mode (ie the runtime, not default value).
|
|
// Bottom line: There is no need to set this dirty, as play mode changes aren't saved and by changing it back to default on exit we already avoid any chance of a runtime value being saved later
|
|
// EditorUtility.SetDirty(this);
|
|
}
|
|
|
|
AdditionalHandlePlayModeStateChange(stateChange);
|
|
}
|
|
|
|
/// <summary>
|
|
/// Do any additional changes needed when changing PlayMode.
|
|
/// NOTE: any override must be surrounded by #if UNITY_EDITOR as it is Editor only.
|
|
/// </summary>
|
|
/// <param name="stateChange"></param>
|
|
protected virtual void AdditionalHandlePlayModeStateChange(PlayModeStateChange stateChange)
|
|
{
|
|
}
|
|
#endif
|
|
|
|
#if UNITY_EDITOR
|
|
[System.Diagnostics.CodeAnalysis.SuppressMessage("CodeQuality", "IDE0051:Remove unused private members", Justification = "Odin")]
|
|
private void BaseHandleEditorValueChange()
|
|
{
|
|
HandleEditorValueChange();
|
|
//
|
|
// Marking this dirty so Unity sees the value change
|
|
//
|
|
EditorUtility.SetDirty(this);
|
|
}
|
|
|
|
protected virtual void HandleEditorValueChange()
|
|
{
|
|
//Value = m_EditorValue;
|
|
}
|
|
|
|
// [BoxGroup("Debug/Listeners")]
|
|
// [HideIf("@this.m_InspectorValueListeners == null || this.m_InspectorValueListeners.Count == 0")]
|
|
// [Button("Log Listeners")]
|
|
private void LogListListeners()
|
|
{
|
|
var listeners = InternalOnChange?.GetInvocationList();
|
|
|
|
if (listeners == null)
|
|
{
|
|
return;
|
|
}
|
|
|
|
StringBuilder builder = new StringBuilder();
|
|
foreach (var listener in listeners)
|
|
{
|
|
builder.AppendLine(string.Format("{0}: listener {1}", name, listener));
|
|
}
|
|
Debug.Log(builder.ToString());
|
|
}
|
|
#endif
|
|
|
|
public override string ToString()
|
|
{
|
|
if (m_Value == null)
|
|
{
|
|
return name + " (null)";
|
|
}
|
|
return name + " (" + m_Value.ToString() + ")";
|
|
}
|
|
|
|
#if UNITY_EDITOR
|
|
public void OnBeforeSerialize()
|
|
{
|
|
}
|
|
|
|
public void OnAfterDeserialize()
|
|
{
|
|
//m_EditorValue = m_Value;
|
|
}
|
|
#endif
|
|
}
|
|
}
|