2019-04-16 22:32:17 +02:00
using System ;
2018-10-30 20:05:06 +01:00
using UnityEngine ;
namespace UnityAtoms
{
2019-10-15 22:21:56 +02:00
/// <summary>
/// Generic base class for Variables. Inherits from `AtomBaseVariable<T>`.
/// </summary>
/// <typeparam name="T">The Variable value type.</typeparam>
/// <typeparam name="E1">Event of type `AtomEvent<T>`.</typeparam>
/// <typeparam name="E2">Event of type `AtomEvent<T, T>`.</typeparam>
2019-10-14 16:51:54 +02:00
[EditorIcon("atom-icon-lush")]
2019-11-14 12:59:11 +01:00
public abstract class AtomVariable < T , E1 , E2 > : AtomBaseVariable < T >
2019-09-25 21:05:06 +02:00
where E1 : AtomEvent < T >
where E2 : AtomEvent < T , T >
2018-10-30 20:05:06 +01:00
{
2019-10-15 22:21:56 +02:00
/// <summary>
/// The Variable value as a property.
/// </summary>
2019-10-20 23:21:16 +02:00
/// <returns>Get or set the Variable's value.</returns>
2019-04-08 19:46:02 +02:00
public override T Value { get { return _value ; } set { SetValue ( value ) ; } }
2019-10-15 22:21:56 +02:00
/// <summary>
/// The inital value of the Variable.
/// </summary>
2019-04-08 19:46:02 +02:00
[SerializeField]
2019-10-03 21:34:57 +02:00
private T _initialValue = default ( T ) ;
2018-10-30 20:05:06 +01:00
2019-10-20 23:21:16 +02:00
/// <summary>
/// The inital Variable value as a property.
/// </summary>
/// <returns>Get the Variable's initial value.</returns>
public T InitialValue { get { return _value ; } }
2019-10-15 22:21:56 +02:00
/// <summary>
/// The value the Variable had before its value got changed last time.
/// </summary>
2019-10-20 23:21:16 +02:00
/// <value>Get the Variable's old value.</value>
2019-04-07 16:03:16 +02:00
public T OldValue { get { return _oldValue ; } }
2018-10-30 20:05:06 +01:00
[SerializeField]
2019-04-07 16:03:16 +02:00
private T _oldValue ;
2018-10-30 20:05:06 +01:00
2019-10-15 22:21:56 +02:00
/// <summary>
/// Changed Event triggered when the Variable value gets changed.
/// </summary>
2018-10-30 20:05:06 +01:00
public E1 Changed ;
2019-10-15 22:21:56 +02:00
/// <summary>
/// Changed with history Event triggered when the Variable value gets changed.
/// </summary>
2018-10-30 20:05:06 +01:00
public E2 ChangedWithHistory ;
protected abstract bool AreEqual ( T first , T second ) ;
2019-03-17 23:43:20 +01:00
private void OnEnable ( )
{
2019-11-14 12:59:11 +01:00
_oldValue = _initialValue ;
_value = _initialValue ;
2019-03-17 23:43:20 +01:00
if ( Changed = = null ) return ;
Changed . Raise ( Value ) ;
}
2019-10-15 22:21:56 +02:00
/// <summary>
/// Reset the Variable to its `_initalValue`.
/// </summary>
/// <param name="shouldTriggerEvents">Set to `true` if Events should be triggered on reset, otherwise `false`.</param>
2019-10-14 16:39:22 +02:00
public override sealed void Reset ( bool shouldTriggerEvents = false )
2019-09-30 00:26:53 +02:00
{
2019-09-30 22:55:33 +02:00
if ( ! shouldTriggerEvents )
{
_oldValue = _value ;
_value = _initialValue ;
}
else
{
SetValue ( _initialValue ) ;
}
2019-09-30 00:26:53 +02:00
}
2019-10-15 22:21:56 +02:00
/// <summary>
/// Set the Variable value.
/// </summary>
/// <param name="newValue">The new value to set.</param>
/// <returns>`true` if the value got changed, otherwise `false`.</returns>
2019-04-07 11:52:07 +02:00
public bool SetValue ( T newValue )
2018-10-30 20:05:06 +01:00
{
2019-04-08 19:46:02 +02:00
if ( ! AreEqual ( _value , newValue ) )
2018-10-30 20:05:06 +01:00
{
2019-04-08 19:46:02 +02:00
_oldValue = _value ;
_value = newValue ;
if ( Changed ! = null ) { Changed . Raise ( _value ) ; }
if ( ChangedWithHistory ! = null ) { ChangedWithHistory . Raise ( _value , _oldValue ) ; }
2019-04-05 13:40:26 +02:00
return true ;
2018-10-30 20:05:06 +01:00
}
2019-04-05 13:40:26 +02:00
return false ;
2018-10-30 20:05:06 +01:00
}
2019-10-15 22:21:56 +02:00
/// <summary>
/// Set the Variable value.
/// </summary>
/// <param name="variable">The value to set provided from another Variable.</param>
/// <returns>`true` if the value got changed, otherwise `false`.</returns>
2019-09-25 21:05:06 +02:00
public bool SetValue ( AtomVariable < T , E1 , E2 > variable )
2018-10-30 20:05:06 +01:00
{
return SetValue ( variable . Value ) ;
}
2019-04-08 19:46:02 +02:00
2019-04-16 22:32:17 +02:00
#region Observable
2019-10-15 22:21:56 +02:00
/// <summary>
/// Turn the Variable's change Event into an `IObservable<T>`. Makes the Variable's change Event compatible with for example UniRx.
/// </summary>
/// <returns>The Variable's change Event as an `IObservable<T>`.</returns>
2019-04-16 22:32:17 +02:00
public IObservable < T > ObserveChange ( )
{
if ( Changed = = null )
{
throw new Exception ( "You must assign a Changed event in order to observe variable changes." ) ;
}
return new ObservableEvent < T > ( Changed . Register , Changed . Unregister ) ;
}
2019-04-21 13:51:20 +02:00
2019-10-15 22:21:56 +02:00
/// <summary>
/// Turn the Variable's change with history Event into an `IObservable<T, T>`. Makes the Variable's change with history Event compatible with for example UniRx.
/// </summary>
/// <returns>The Variable's change Event as an `IObservable<T, T>`.</returns>
2019-04-21 13:51:20 +02:00
public IObservable < ValueTuple < T , T > > ObserveChangeWithHistory ( )
{
if ( ChangedWithHistory = = null )
{
throw new Exception ( "You must assign a ChangedWithHistory event in order to observe variable changes." ) ;
}
return new ObservableEvent < T , T , ValueTuple < T , T > > (
register : ChangedWithHistory . Register ,
unregister : ChangedWithHistory . Unregister ,
createCombinedModel : ( n , o ) = > new ValueTuple < T , T > ( n , o )
) ;
}
2019-04-16 22:32:17 +02:00
#endregion // Observable
2018-10-30 20:05:06 +01:00
}
2019-04-05 13:40:26 +02:00
}