添加插件
This commit is contained in:
@@ -0,0 +1,29 @@
|
||||
using UnityEngine;
|
||||
|
||||
namespace Obvious.Soap
|
||||
{
|
||||
[CreateAssetMenu(fileName = "scriptable_variable_bool.asset", menuName = "Soap/ScriptableVariables/bool")]
|
||||
[System.Serializable]
|
||||
public class BoolVariable : ScriptableVariable<bool>
|
||||
{
|
||||
public override void Save()
|
||||
{
|
||||
PlayerPrefs.SetInt(Guid, Value ? 1 : 0);
|
||||
base.Save();
|
||||
}
|
||||
|
||||
public override void Load()
|
||||
{
|
||||
Value = PlayerPrefs.GetInt(Guid, DefaultValue ? 1 : 0) > 0;
|
||||
base.Load();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Use this to toggle the value of the variable.
|
||||
/// </summary>
|
||||
public void Toggle()
|
||||
{
|
||||
Value = !Value;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 6a11231538da9894d8dce88b47df6a36
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {fileID: 2800000, guid: 8173878b5f4d7724784454801c58c9c4, type: 3}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,36 @@
|
||||
using UnityEngine;
|
||||
|
||||
namespace Obvious.Soap
|
||||
{
|
||||
[CreateAssetMenu(fileName = "scriptable_variable_color.asset", menuName = "Soap/ScriptableVariables/color")]
|
||||
public class ColorVariable : ScriptableVariable<Color>
|
||||
{
|
||||
public override void Save()
|
||||
{
|
||||
PlayerPrefs.SetFloat(Guid + "_r", Value.r);
|
||||
PlayerPrefs.SetFloat(Guid + "_g", Value.g);
|
||||
PlayerPrefs.SetFloat(Guid + "_b", Value.b);
|
||||
PlayerPrefs.SetFloat(Guid + "_a", Value.a);
|
||||
base.Save();
|
||||
}
|
||||
|
||||
public override void Load()
|
||||
{
|
||||
var r = PlayerPrefs.GetFloat(Guid + "_r", DefaultValue.r);
|
||||
var g = PlayerPrefs.GetFloat(Guid + "_g", DefaultValue.g);
|
||||
var b = PlayerPrefs.GetFloat(Guid + "_b", DefaultValue.b);
|
||||
var a = PlayerPrefs.GetFloat(Guid + "_a", DefaultValue.a);
|
||||
Value = new Color(r, g, b, a);
|
||||
base.Load();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Sets a random color.
|
||||
/// </summary>
|
||||
public void SetRandom()
|
||||
{
|
||||
var beautifulColor = Random.ColorHSV(0f, 1f, 1f, 1f, 0.5f, 1f);
|
||||
Value = beautifulColor;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: b7046b79ca6dcd147b7412e32a7dbb69
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {fileID: 2800000, guid: 8173878b5f4d7724784454801c58c9c4, type: 3}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,15 @@
|
||||
using UnityEngine;
|
||||
|
||||
namespace Obvious.Soap
|
||||
{
|
||||
[CreateAssetMenu(fileName = "scriptable_variable_component.asset", menuName = "Soap/ScriptableVariables/Component")]
|
||||
public class ComponentVariable : ScriptableVariable<Component>
|
||||
{
|
||||
public override string ToString()
|
||||
{
|
||||
if (Value == null)
|
||||
return $"{name} : null";
|
||||
return $"{name} : {Value.GetType().Name} (GameObject: {Value.gameObject.name})";
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 6658d50afb1d4574ea142fa9bf4758ad
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {fileID: 2800000, guid: 8173878b5f4d7724784454801c58c9c4, type: 3}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,99 @@
|
||||
using UnityEngine;
|
||||
#if ODIN_INSPECTOR
|
||||
using Sirenix.OdinInspector;
|
||||
#else
|
||||
using Obvious.Soap.Attributes;
|
||||
#endif
|
||||
namespace Obvious.Soap
|
||||
{
|
||||
[CreateAssetMenu(fileName = "scriptable_variable_float.asset", menuName = "Soap/ScriptableVariables/float")]
|
||||
public class FloatVariable : ScriptableVariable<float>
|
||||
{
|
||||
[Tooltip("Clamps the value of this variable to a minimum and maximum.")]
|
||||
#if ODIN_INSPECTOR
|
||||
[PropertyOrder(5)]
|
||||
#endif
|
||||
[SerializeField] private bool _isClamped = false;
|
||||
public bool IsClamped
|
||||
{
|
||||
get => _isClamped;
|
||||
set => _isClamped = value;
|
||||
}
|
||||
[Tooltip("If clamped, sets the minimum and maximum")]
|
||||
[SerializeField]
|
||||
#if ODIN_INSPECTOR
|
||||
[ShowIf("_isClamped")]
|
||||
[PropertyOrder(6)][Indent]
|
||||
#else
|
||||
[ShowIf("_isClamped")]
|
||||
#endif
|
||||
private FloatReference _min = new FloatReference(0,true);
|
||||
public FloatReference MinReference
|
||||
{
|
||||
get => _min;
|
||||
set => _min = value;
|
||||
}
|
||||
public float Min => _min.Value;
|
||||
|
||||
[Tooltip("If clamped, sets the minimum and maximum")]
|
||||
[SerializeField]
|
||||
#if ODIN_INSPECTOR
|
||||
[ShowIf("_isClamped")]
|
||||
[PropertyOrder(7)][Indent]
|
||||
#else
|
||||
[ShowIf("_isClamped")]
|
||||
#endif
|
||||
private FloatReference _max = new FloatReference(float.MaxValue,true);
|
||||
public FloatReference MaxReference
|
||||
{
|
||||
get => _max;
|
||||
set => _max = value;
|
||||
}
|
||||
public float Max => _max.Value;
|
||||
/// <summary>
|
||||
/// Returns the percentage of the value between the minimum and maximum.
|
||||
/// </summary>
|
||||
public float Ratio => Mathf.InverseLerp( _min.Value, _max.Value, Value);
|
||||
|
||||
public override void Save()
|
||||
{
|
||||
PlayerPrefs.SetFloat(Guid, Value);
|
||||
base.Save();
|
||||
}
|
||||
|
||||
public override void Load()
|
||||
{
|
||||
Value = PlayerPrefs.GetFloat(Guid, DefaultValue);
|
||||
base.Load();
|
||||
}
|
||||
|
||||
public void Add(float value)
|
||||
{
|
||||
Value += value;
|
||||
}
|
||||
|
||||
public override float Value
|
||||
{
|
||||
get => base.Value;
|
||||
set
|
||||
{
|
||||
var clampedValue = _isClamped ? Mathf.Clamp(value, _min.Value, _max.Value) : value;
|
||||
base.Value = clampedValue;
|
||||
}
|
||||
}
|
||||
|
||||
#if UNITY_EDITOR
|
||||
protected override void OnValidate()
|
||||
{
|
||||
if (_isClamped)
|
||||
{
|
||||
var clampedValue = Mathf.Clamp(Value, _min.Value, _max.Value);
|
||||
if (Value < clampedValue || Value > clampedValue)
|
||||
Value = clampedValue;
|
||||
}
|
||||
|
||||
base.OnValidate();
|
||||
}
|
||||
#endif
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: a9978ce9c8bdc724896114c9952c52ea
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {fileID: 2800000, guid: 8173878b5f4d7724784454801c58c9c4, type: 3}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,10 @@
|
||||
using UnityEngine;
|
||||
|
||||
namespace Obvious.Soap
|
||||
{
|
||||
[CreateAssetMenu(fileName = "scriptable_variable_gameObject.asset", menuName = "Soap/ScriptableVariables/GameObject")]
|
||||
public class GameObjectVariable : ScriptableVariable<GameObject>
|
||||
{
|
||||
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 5798d9261dd3eae4d920ab34987f7ade
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {fileID: 2800000, guid: 8173878b5f4d7724784454801c58c9c4, type: 3}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,103 @@
|
||||
using UnityEngine;
|
||||
#if ODIN_INSPECTOR
|
||||
using Sirenix.OdinInspector;
|
||||
#else
|
||||
using Obvious.Soap.Attributes;
|
||||
#endif
|
||||
|
||||
namespace Obvious.Soap
|
||||
{
|
||||
[CreateAssetMenu(fileName = "scriptable_variable_int.asset", menuName = "Soap/ScriptableVariables/int")]
|
||||
public class IntVariable : ScriptableVariable<int>
|
||||
{
|
||||
[Tooltip("Clamps the value of this variable to a minimum and maximum.")]
|
||||
#if ODIN_INSPECTOR
|
||||
[PropertyOrder(5)]
|
||||
#endif
|
||||
[SerializeField]
|
||||
private bool _isClamped = false;
|
||||
public bool IsClamped
|
||||
{
|
||||
get => _isClamped;
|
||||
set => _isClamped = value;
|
||||
}
|
||||
|
||||
[Tooltip("If clamped, sets the minimum and maximum")]
|
||||
[SerializeField]
|
||||
#if ODIN_INSPECTOR
|
||||
[ShowIf("_isClamped")]
|
||||
[PropertyOrder(6)][Indent]
|
||||
#else
|
||||
[ShowIf("_isClamped")]
|
||||
#endif
|
||||
private IntReference _min = new IntReference(0,true);
|
||||
public IntReference MinReference
|
||||
{
|
||||
get => _min;
|
||||
set => _min = value;
|
||||
}
|
||||
public int Min => _min.Value;
|
||||
|
||||
[Tooltip("If clamped, sets the minimum and maximum")]
|
||||
[SerializeField]
|
||||
#if ODIN_INSPECTOR
|
||||
[ShowIf("_isClamped")]
|
||||
[PropertyOrder(7)][Indent]
|
||||
#else
|
||||
[ShowIf("_isClamped")]
|
||||
#endif
|
||||
private IntReference _max = new IntReference(int.MaxValue,true);
|
||||
public IntReference MaxReference
|
||||
{
|
||||
get => _max;
|
||||
set => _max = value;
|
||||
}
|
||||
public int Max => _max.Value;
|
||||
|
||||
/// <summary>
|
||||
/// Returns the percentage of the value between the minimum and maximum.
|
||||
/// </summary>
|
||||
public float Ratio => Mathf.InverseLerp( _min.Value, _max.Value, Value);
|
||||
|
||||
public override void Save()
|
||||
{
|
||||
PlayerPrefs.SetInt(Guid, Value);
|
||||
base.Save();
|
||||
}
|
||||
|
||||
public override void Load()
|
||||
{
|
||||
Value = PlayerPrefs.GetInt(Guid, DefaultValue);
|
||||
base.Load();
|
||||
}
|
||||
|
||||
public void Add(int value)
|
||||
{
|
||||
Value += value;
|
||||
}
|
||||
|
||||
public override int Value
|
||||
{
|
||||
get => base.Value;
|
||||
set
|
||||
{
|
||||
var clampedValue = _isClamped ? Mathf.Clamp(value, _min.Value, _max.Value) : value;
|
||||
base.Value = clampedValue;
|
||||
}
|
||||
}
|
||||
|
||||
#if UNITY_EDITOR
|
||||
protected override void OnValidate()
|
||||
{
|
||||
if (IsClamped)
|
||||
{
|
||||
var clampedValue = Mathf.Clamp(Value, _min.Value, _max.Value);
|
||||
if (Value < clampedValue || Value > clampedValue)
|
||||
Value = clampedValue;
|
||||
}
|
||||
|
||||
base.OnValidate();
|
||||
}
|
||||
#endif
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 56cdb8ad39a5bdd4f8ed3d18fae14a63
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {fileID: 2800000, guid: 8173878b5f4d7724784454801c58c9c4, type: 3}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,11 @@
|
||||
using UnityEngine;
|
||||
using Obvious.Soap;
|
||||
|
||||
namespace Obvious.Soap
|
||||
{
|
||||
[CreateAssetMenu(fileName = "scriptable_variable_" + nameof(Quaternion), menuName = "Soap/ScriptableVariables/"+ nameof(Quaternion))]
|
||||
public class QuaternionVariable : ScriptableVariable<Quaternion>
|
||||
{
|
||||
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 0d5e637945a57d243bfbf35cab0eba1e
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {fileID: 2800000, guid: 8173878b5f4d7724784454801c58c9c4, type: 3}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,342 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using UnityEngine;
|
||||
using UnityEngine.SceneManagement;
|
||||
using Object = UnityEngine.Object;
|
||||
#if UNITY_EDITOR
|
||||
using UnityEditor;
|
||||
#endif
|
||||
#if ODIN_INSPECTOR
|
||||
using Sirenix.OdinInspector;
|
||||
#else
|
||||
using Obvious.Soap.Attributes;
|
||||
#endif
|
||||
|
||||
namespace Obvious.Soap
|
||||
{
|
||||
public abstract class ScriptableVariable<T> : ScriptableVariableBase, IReset, IDrawObjectsInInspector
|
||||
{
|
||||
[Tooltip(
|
||||
"The value of the variable. This will be reset on play mode exit to the value it had before entering play mode.")]
|
||||
[SerializeField]
|
||||
#if ODIN_INSPECTOR
|
||||
[HideInPlayMode][PropertyOrder(-1)]
|
||||
#endif
|
||||
protected T _value;
|
||||
|
||||
[Tooltip("Log in the console whenever this variable is changed, loaded or saved.")] [SerializeField]
|
||||
protected bool _debugLogEnabled;
|
||||
#if ODIN_INSPECTOR
|
||||
[PropertyOrder(1)]
|
||||
#endif
|
||||
[Tooltip("If true, saves the value to Player Prefs and loads it onEnable.")] [SerializeField]
|
||||
protected bool _saved;
|
||||
|
||||
[Tooltip(
|
||||
"The default value of this variable. When loading from PlayerPrefs the first time, it will be set to this value.")]
|
||||
[SerializeField]
|
||||
#if ODIN_INSPECTOR
|
||||
[ShowIf("_saved")]
|
||||
[PropertyOrder(2)]
|
||||
[Indent]
|
||||
[BoxGroup]
|
||||
#else
|
||||
[ShowIf("_saved", true)]
|
||||
#endif
|
||||
private T _defaultValue;
|
||||
|
||||
#if ODIN_INSPECTOR
|
||||
[PropertyOrder(5)]
|
||||
#endif
|
||||
[Tooltip("Reset to initial value." +
|
||||
" Scene Loaded : when the scene is loaded." +
|
||||
" Application Start : Once, when the application starts." +
|
||||
" None : Never.")]
|
||||
[SerializeField]
|
||||
private ResetType _resetOn = ResetType.SceneLoaded;
|
||||
|
||||
public override ResetType ResetType
|
||||
{
|
||||
get => _resetOn;
|
||||
set => _resetOn = value;
|
||||
}
|
||||
|
||||
protected T _initialValue;
|
||||
|
||||
[SerializeField]
|
||||
#if ODIN_INSPECTOR
|
||||
[HideInEditorMode][PropertyOrder(-1)]
|
||||
#endif
|
||||
protected T _runtimeValue;
|
||||
|
||||
private readonly List<Object> _listenersObjects = new List<Object>();
|
||||
#if ODIN_INSPECTOR
|
||||
[HideInEditorMode]
|
||||
[ShowInInspector,EnableGUI]
|
||||
[PropertyOrder(100)]
|
||||
public IEnumerable<Object> ObjectsReactingToOnValueChangedEvent => _listenersObjects;
|
||||
#endif
|
||||
|
||||
protected Action<T> _onValueChanged;
|
||||
|
||||
/// <summary> Event raised when the variable value changes. </summary>
|
||||
public event Action<T> OnValueChanged
|
||||
{
|
||||
add
|
||||
{
|
||||
_onValueChanged += value;
|
||||
#if UNITY_EDITOR
|
||||
var listener = value.Target as Object;
|
||||
AddListener(listener);
|
||||
#endif
|
||||
}
|
||||
remove
|
||||
{
|
||||
_onValueChanged -= value;
|
||||
#if UNITY_EDITOR
|
||||
var listener = value.Target as Object;
|
||||
RemoveListener(listener);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// The previous value just after the value changed.
|
||||
/// </summary>
|
||||
public T PreviousValue { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// The default value this variable is reset to.
|
||||
/// </summary>
|
||||
public T DefaultValue => _defaultValue;
|
||||
|
||||
#if UNITY_EDITOR
|
||||
private T Read() => Application.isPlaying ? _runtimeValue : _value;
|
||||
private void Write(T v)
|
||||
{
|
||||
if (Application.isPlaying)
|
||||
_runtimeValue = v;
|
||||
else
|
||||
_value = v;
|
||||
}
|
||||
#else
|
||||
private T Read() => _value;
|
||||
private void Write(T v) { _value = v; }
|
||||
#endif
|
||||
|
||||
/// <summary>
|
||||
/// Modify this to change the value of the variable.
|
||||
/// Triggers OnValueChanged event.
|
||||
/// </summary>
|
||||
public virtual T Value
|
||||
{
|
||||
get => Read();
|
||||
set
|
||||
{
|
||||
var current = Read();
|
||||
if (EqualityComparer<T>.Default.Equals(current, value))
|
||||
return;
|
||||
|
||||
Write(value);
|
||||
ValueChanged(true);
|
||||
}
|
||||
}
|
||||
|
||||
public virtual void SetValueWithoutNotify(T value)
|
||||
{
|
||||
var current = Read();
|
||||
if (EqualityComparer<T>.Default.Equals(current, value))
|
||||
return;
|
||||
|
||||
Write(value);
|
||||
ValueChanged(false);
|
||||
}
|
||||
|
||||
public virtual void ValueChanged(bool triggerEvent = true)
|
||||
{
|
||||
if (_saved)
|
||||
Save();
|
||||
|
||||
if (_debugLogEnabled)
|
||||
{
|
||||
var suffix = _saved ? " <color=#f75369>[Saved]</color>" : "";
|
||||
Debug.Log($"{GetColorizedString()}{suffix}", this);
|
||||
}
|
||||
|
||||
if (triggerEvent)
|
||||
_onValueChanged?.Invoke(Read());
|
||||
|
||||
PreviousValue = Read();
|
||||
#if UNITY_EDITOR
|
||||
if (this != null) //for runtime variables, the instance will be destroyed so do not repaint.
|
||||
RepaintRequest?.Invoke();
|
||||
#endif
|
||||
}
|
||||
|
||||
public override Type GetGenericType => typeof(T);
|
||||
|
||||
protected virtual void Awake()
|
||||
{
|
||||
//Prevents from resetting if no reference in a scene
|
||||
hideFlags = HideFlags.DontUnloadUnusedAsset;
|
||||
}
|
||||
|
||||
protected virtual void OnEnable()
|
||||
{
|
||||
#if UNITY_EDITOR
|
||||
EditorApplication.playModeStateChanged += OnPlayModeStateChanged;
|
||||
#else
|
||||
Init();
|
||||
#endif
|
||||
if (_resetOn == ResetType.SceneLoaded)
|
||||
SceneManager.sceneLoaded += OnSceneLoaded;
|
||||
}
|
||||
|
||||
protected virtual void OnDisable()
|
||||
{
|
||||
#if UNITY_EDITOR
|
||||
EditorApplication.playModeStateChanged -= OnPlayModeStateChanged;
|
||||
#endif
|
||||
SceneManager.sceneLoaded -= OnSceneLoaded;
|
||||
}
|
||||
|
||||
protected virtual void OnSceneLoaded(Scene scene, LoadSceneMode mode)
|
||||
{
|
||||
//the reset mode can change after the game has started, so we need to check it here.
|
||||
if (_resetOn != ResetType.SceneLoaded)
|
||||
return;
|
||||
|
||||
if (mode == LoadSceneMode.Single)
|
||||
{
|
||||
if (_saved)
|
||||
Load();
|
||||
else
|
||||
ResetValue();
|
||||
}
|
||||
}
|
||||
|
||||
#if UNITY_EDITOR
|
||||
public void OnPlayModeStateChanged(PlayModeStateChange playModeStateChange)
|
||||
{
|
||||
if (playModeStateChange == PlayModeStateChange.ExitingEditMode)
|
||||
{
|
||||
Init();
|
||||
}
|
||||
else if (playModeStateChange == PlayModeStateChange.EnteredEditMode)
|
||||
{
|
||||
if (!_saved)
|
||||
{
|
||||
ResetValue();
|
||||
}
|
||||
else
|
||||
{
|
||||
if (EqualityComparer<T>.Default.Equals(_value, _runtimeValue))
|
||||
return;
|
||||
|
||||
// Set the value to the runtime value
|
||||
_value = _runtimeValue;
|
||||
_runtimeValue = _initialValue;
|
||||
EditorUtility.SetDirty(this);
|
||||
RepaintRequest?.Invoke();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
protected virtual void OnValidate()
|
||||
{
|
||||
//In default play mode, this get called before OnEnable(). Therefore a saved variable can get saved before loading.
|
||||
//This check prevents the latter.
|
||||
if (EqualityComparer<T>.Default.Equals(Read(), PreviousValue))
|
||||
return;
|
||||
ValueChanged();
|
||||
}
|
||||
|
||||
/// <summary> Reset the SO to default.</summary>
|
||||
internal override void Reset()
|
||||
{
|
||||
base.Reset();
|
||||
_listenersObjects.Clear();
|
||||
Value = default;
|
||||
_initialValue = default;
|
||||
_runtimeValue = default;
|
||||
PreviousValue = default;
|
||||
_saved = false;
|
||||
_resetOn = ResetType.SceneLoaded;
|
||||
_debugLogEnabled = false;
|
||||
}
|
||||
|
||||
public void AddListener(Object listener)
|
||||
{
|
||||
if (listener != null && !_listenersObjects.Contains(listener))
|
||||
_listenersObjects.Add(listener);
|
||||
}
|
||||
|
||||
public void RemoveListener(Object listener)
|
||||
{
|
||||
if (_listenersObjects.Contains(listener))
|
||||
_listenersObjects.Remove(listener);
|
||||
}
|
||||
#endif
|
||||
|
||||
private void Init()
|
||||
{
|
||||
if (_saved)
|
||||
Load();
|
||||
|
||||
_initialValue = _value;
|
||||
_runtimeValue = _value;
|
||||
PreviousValue = _value;
|
||||
_listenersObjects.Clear();
|
||||
}
|
||||
|
||||
/// <summary> Reset to initial value</summary>
|
||||
public void ResetValue()
|
||||
{
|
||||
Value = _initialValue;
|
||||
PreviousValue = _initialValue;
|
||||
_runtimeValue = _initialValue;
|
||||
}
|
||||
|
||||
public virtual void Save()
|
||||
{
|
||||
}
|
||||
|
||||
public virtual void Load()
|
||||
{
|
||||
PreviousValue = _value;
|
||||
|
||||
if (_debugLogEnabled)
|
||||
Debug.Log($"{GetColorizedString()} <color=#f75369>[Loaded].</color>", this);
|
||||
}
|
||||
|
||||
public override string ToString()
|
||||
{
|
||||
return $"{name} : {Value}";
|
||||
}
|
||||
|
||||
protected virtual string GetColorizedString() => $"<color=#f75369>[Variable]</color> {ToString()}";
|
||||
|
||||
public IReadOnlyList<Object> EditorListeners => _listenersObjects.AsReadOnly();
|
||||
|
||||
public static implicit operator T(ScriptableVariable<T> variable) => variable.Value;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Defines when the variable is reset.
|
||||
/// </summary>
|
||||
public enum ResetType
|
||||
{
|
||||
SceneLoaded,
|
||||
ApplicationStarts,
|
||||
None
|
||||
}
|
||||
|
||||
public enum CustomVariableType
|
||||
{
|
||||
None,
|
||||
Bool,
|
||||
Int,
|
||||
Float,
|
||||
String
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 9dcab23e1548c9344916733798631cec
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,54 @@
|
||||
using UnityEngine;
|
||||
#if ODIN_INSPECTOR
|
||||
using Sirenix.OdinInspector;
|
||||
#endif
|
||||
|
||||
namespace Obvious.Soap
|
||||
{
|
||||
[HelpURL("https://obvious-game.gitbook.io/soap/soap-core-assets/scriptable-variable")]
|
||||
public abstract class ScriptableVariableBase : ScriptableBase
|
||||
{
|
||||
#if ODIN_INSPECTOR
|
||||
[PropertyOrder(4)]
|
||||
[DisableIf("_saveGuid", SaveGuidType.Auto)]
|
||||
[ShowIf("_saved")]
|
||||
[Indent]
|
||||
[BoxGroup]
|
||||
#endif
|
||||
[SerializeField]
|
||||
private string _guid;
|
||||
|
||||
#if ODIN_INSPECTOR
|
||||
[PropertyOrder(3)]
|
||||
[ShowIf("_saved")]
|
||||
[Indent]
|
||||
[BoxGroup]
|
||||
//[LabelWidth(80)]
|
||||
#endif
|
||||
[Tooltip("ID used as the Player Prefs Key.\n" +
|
||||
"Auto: Guid is generated automatically base on the asset path.\n" +
|
||||
"Manual: Guid can be overwritten manually.")]
|
||||
[SerializeField]
|
||||
private SaveGuidType _saveGuid;
|
||||
|
||||
public SaveGuidType SaveGuid => _saveGuid;
|
||||
|
||||
/// <summary>
|
||||
/// Guid is needed to save/load the value to PlayerPrefs.
|
||||
/// </summary>
|
||||
public string Guid
|
||||
{
|
||||
get => _guid;
|
||||
set => _guid = value;
|
||||
}
|
||||
|
||||
public virtual ResetType ResetType { get; set; }
|
||||
|
||||
}
|
||||
|
||||
public enum SaveGuidType
|
||||
{
|
||||
Auto,
|
||||
Manual,
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: dffd90b3e4094da298b30ac2f9553d0b
|
||||
timeCreated: 1675031065
|
||||
@@ -0,0 +1,20 @@
|
||||
using UnityEngine;
|
||||
|
||||
namespace Obvious.Soap
|
||||
{
|
||||
[CreateAssetMenu(fileName = "scriptable_variable_string.asset", menuName = "Soap/ScriptableVariables/string")]
|
||||
public class StringVariable : ScriptableVariable<string>
|
||||
{
|
||||
public override void Save()
|
||||
{
|
||||
PlayerPrefs.SetString(Guid, Value);
|
||||
base.Save();
|
||||
}
|
||||
|
||||
public override void Load()
|
||||
{
|
||||
Value = PlayerPrefs.GetString(Guid, DefaultValue);
|
||||
base.Load();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: fbb51723e892a404a87b22018981eb5d
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {fileID: 2800000, guid: 8173878b5f4d7724784454801c58c9c4, type: 3}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,8 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 0d709c36840cc4b4986ebe2c5e3ed2b2
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,7 @@
|
||||
namespace Obvious.Soap
|
||||
{
|
||||
[System.Serializable]
|
||||
public class BoolReference : VariableReference<BoolVariable, bool>
|
||||
{
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 04cd28045cfa5ca40b0c1811c7de86af
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,7 @@
|
||||
namespace Obvious.Soap
|
||||
{
|
||||
[System.Serializable]
|
||||
public class ColorReference : VariableReference<ColorVariable, UnityEngine.Color>
|
||||
{
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 0c16be5b350d07740960221d2f880d4b
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,16 @@
|
||||
namespace Obvious.Soap
|
||||
{
|
||||
[System.Serializable]
|
||||
public class FloatReference : VariableReference<FloatVariable, float>
|
||||
{
|
||||
public FloatReference()
|
||||
{
|
||||
}
|
||||
|
||||
public FloatReference(float initialValue, bool useLocal = false)
|
||||
{
|
||||
LocalValue = initialValue;
|
||||
UseLocal = useLocal;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: d69d26f58cf51154cb43cf597b57d0dd
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,16 @@
|
||||
namespace Obvious.Soap
|
||||
{
|
||||
[System.Serializable]
|
||||
public class IntReference : VariableReference<IntVariable, int>
|
||||
{
|
||||
public IntReference()
|
||||
{
|
||||
}
|
||||
|
||||
public IntReference(int initialValue, bool useLocal = false)
|
||||
{
|
||||
LocalValue = initialValue;
|
||||
UseLocal = useLocal;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: a9c0318cbda96274daa33a0b0a4a65a4
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,7 @@
|
||||
namespace Obvious.Soap
|
||||
{
|
||||
[System.Serializable]
|
||||
public class StringReference : VariableReference<StringVariable, string>
|
||||
{
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 5be4248575855e344ad1a3d62c03d779
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,85 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using UnityEngine;
|
||||
|
||||
namespace Obvious.Soap
|
||||
{
|
||||
//Unity cannot serialize generic types, so we need to create a non-generic base class
|
||||
public abstract class VariableReferenceBase { }
|
||||
|
||||
[Serializable]
|
||||
public abstract class VariableReference<V, T> : VariableReferenceBase, ISerializationCallbackReceiver where V : ScriptableVariable<T>
|
||||
{
|
||||
public bool UseLocal;
|
||||
public T LocalValue;
|
||||
public V Variable;
|
||||
|
||||
private Action<T> _onValueChanged;
|
||||
|
||||
[NonSerialized] private T _lastSerializedLocalValue;
|
||||
|
||||
public T Value
|
||||
{
|
||||
get
|
||||
{
|
||||
if (UseLocal)
|
||||
return LocalValue;
|
||||
|
||||
if (Variable == null)
|
||||
return default;
|
||||
return Variable.Value;
|
||||
}
|
||||
set
|
||||
{
|
||||
if (UseLocal)
|
||||
{
|
||||
if (Equals(LocalValue, value))
|
||||
return;
|
||||
|
||||
LocalValue = value;
|
||||
_onValueChanged?.Invoke(LocalValue);
|
||||
}
|
||||
else
|
||||
{
|
||||
Variable.Value = value;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary> Event raised when the variable reference value changes.
|
||||
/// Is triggered for both local and variable. </summary>
|
||||
public event Action<T> OnValueChanged
|
||||
{
|
||||
add
|
||||
{
|
||||
_onValueChanged += value;
|
||||
if (Variable != null)
|
||||
Variable.OnValueChanged += value;
|
||||
}
|
||||
remove
|
||||
{
|
||||
_onValueChanged -= value;
|
||||
if (Variable != null)
|
||||
Variable.OnValueChanged -= value;
|
||||
}
|
||||
}
|
||||
|
||||
public static implicit operator T(VariableReference<V, T> reference)
|
||||
{
|
||||
return reference.Value;
|
||||
}
|
||||
|
||||
public void OnBeforeSerialize()
|
||||
{
|
||||
_lastSerializedLocalValue = LocalValue;
|
||||
}
|
||||
|
||||
public void OnAfterDeserialize()
|
||||
{
|
||||
if (UseLocal && !EqualityComparer<T>.Default.Equals(_lastSerializedLocalValue, LocalValue))
|
||||
{
|
||||
_onValueChanged?.Invoke(LocalValue);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 8349e47b1834dc2409db52bf4844dabb
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,7 @@
|
||||
namespace Obvious.Soap
|
||||
{
|
||||
[System.Serializable]
|
||||
public class Vector2IntReference : VariableReference<Vector2IntVariable, UnityEngine.Vector2Int>
|
||||
{
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: dbd9d492c80528946a0b29ed44c02f21
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,7 @@
|
||||
namespace Obvious.Soap
|
||||
{
|
||||
[System.Serializable]
|
||||
public class Vector2Reference : VariableReference<Vector2Variable, UnityEngine.Vector2>
|
||||
{
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: d2475a2952069444791b28c347f20912
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,7 @@
|
||||
namespace Obvious.Soap
|
||||
{
|
||||
[System.Serializable]
|
||||
public class Vector3Reference : VariableReference<Vector3Variable, UnityEngine.Vector3>
|
||||
{
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 24c4af42bed07564ca5b965a62b3b6ca
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,23 @@
|
||||
using UnityEngine;
|
||||
|
||||
namespace Obvious.Soap
|
||||
{
|
||||
[CreateAssetMenu(fileName = "scriptable_variable_vector2Int", menuName = "Soap/ScriptableVariables/Vector2Int")]
|
||||
public class Vector2IntVariable : ScriptableVariable<Vector2Int>
|
||||
{
|
||||
public override void Save()
|
||||
{
|
||||
PlayerPrefs.SetInt(Guid + "_x", Value.x);
|
||||
PlayerPrefs.SetInt(Guid + "_y", Value.y);
|
||||
base.Save();
|
||||
}
|
||||
|
||||
public override void Load()
|
||||
{
|
||||
var x = PlayerPrefs.GetInt(Guid + "_x", DefaultValue.x);
|
||||
var y = PlayerPrefs.GetInt(Guid + "_y", DefaultValue.y);
|
||||
Value = new Vector2Int(x,y);
|
||||
base.Load();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 1afa6fbeda4c35d45a09c5812a671a42
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {fileID: 2800000, guid: 8173878b5f4d7724784454801c58c9c4, type: 3}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,23 @@
|
||||
using UnityEngine;
|
||||
|
||||
namespace Obvious.Soap
|
||||
{
|
||||
[CreateAssetMenu(fileName = "scriptable_variable_vector2.asset", menuName = "Soap/ScriptableVariables/Vector2")]
|
||||
public class Vector2Variable : ScriptableVariable<Vector2>
|
||||
{
|
||||
public override void Save()
|
||||
{
|
||||
PlayerPrefs.SetFloat(Guid + "_x", Value.x);
|
||||
PlayerPrefs.SetFloat(Guid + "_y", Value.y);
|
||||
base.Save();
|
||||
}
|
||||
|
||||
public override void Load()
|
||||
{
|
||||
var x = PlayerPrefs.GetFloat(Guid + "_x", DefaultValue.x);
|
||||
var y = PlayerPrefs.GetFloat(Guid + "_y", DefaultValue.y);
|
||||
Value = new Vector2(x,y);
|
||||
base.Load();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 33653d5fffc16644bb2d768701efbabf
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {fileID: 2800000, guid: 8173878b5f4d7724784454801c58c9c4, type: 3}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,25 @@
|
||||
using UnityEngine;
|
||||
|
||||
namespace Obvious.Soap
|
||||
{
|
||||
[CreateAssetMenu(fileName = "scriptable_variable_vector3.asset", menuName = "Soap/ScriptableVariables/Vector3")]
|
||||
public class Vector3Variable : ScriptableVariable<Vector3>
|
||||
{
|
||||
public override void Save()
|
||||
{
|
||||
PlayerPrefs.SetFloat(Guid + "_x", Value.x);
|
||||
PlayerPrefs.SetFloat(Guid + "_y", Value.y);
|
||||
PlayerPrefs.SetFloat(Guid + "_z", Value.z);
|
||||
base.Save();
|
||||
}
|
||||
|
||||
public override void Load()
|
||||
{
|
||||
var x = PlayerPrefs.GetFloat(Guid + "_x", DefaultValue.x);
|
||||
var y = PlayerPrefs.GetFloat(Guid + "_y", DefaultValue.y);
|
||||
var z = PlayerPrefs.GetFloat(Guid + "_z", DefaultValue.z);
|
||||
Value = new Vector3(x,y,z);
|
||||
base.Load();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 1300736a6c75069498acdad864241816
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {fileID: 2800000, guid: 8173878b5f4d7724784454801c58c9c4, type: 3}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
Reference in New Issue
Block a user