First Commit

This commit is contained in:
2025-05-18 22:39:39 +03:00
commit 042ede7228
440 changed files with 103153 additions and 0 deletions

254
Assets/BaseVariable.cs Normal file
View File

@@ -0,0 +1,254 @@
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
}
}