namespace Zinnia.Data.Operation.Mutation
{
using System;
using UnityEngine;
using UnityEngine.Events;
using Zinnia.Data.Type;
using Zinnia.Extension;
///
/// Provides a basis for mutating transform Vector3 properties.
///
public abstract class TransformPropertyMutator : MonoBehaviour
{
///
/// Defines the event with the specified state.
///
[Serializable]
public class UnityEvent : UnityEvent { }
#region Target Settings
[Header("Target Settings")]
[Tooltip("The target to mutate.")]
[SerializeField]
private GameObject target;
///
/// The target to mutate.
///
public GameObject Target
{
get
{
return target;
}
set
{
target = value;
}
}
[Tooltip("Determines whether to allow any mutation to take place.")]
[SerializeField]
private bool allowMutate = true;
///
/// Determines whether to allow any mutation to take place.
///
public bool AllowMutate
{
get
{
return allowMutate;
}
set
{
allowMutate = value;
}
}
[Tooltip("Determines whether to mutate the local or global values.")]
[SerializeField]
private bool useLocalValues;
///
/// Determines whether to mutate the local or global values.
///
public bool UseLocalValues
{
get
{
return useLocalValues;
}
set
{
useLocalValues = value;
}
}
[Tooltip("Determines which axes to mutate.")]
[SerializeField]
private Vector3State mutateOnAxis = Vector3State.True;
///
/// Determines which axes to mutate.
///
public Vector3State MutateOnAxis
{
get
{
return mutateOnAxis;
}
set
{
mutateOnAxis = value;
}
}
#endregion
#region Mutation Events
///
/// Is emitted before the property is mutated.
///
[Header("Mutation Events")]
public UnityEvent PreMutated = new UnityEvent();
///
/// Is emitted after the property is mutated.
///
public UnityEvent PostMutated = new UnityEvent();
///
/// Is emitted if the mutation is skipped due to being false.
///
public UnityEvent MutationSkipped = new UnityEvent();
#endregion
///
/// Clears .
///
public virtual void ClearTarget()
{
if (!this.IsValidState())
{
return;
}
Target = default;
}
///
/// Clears .
///
public virtual void ClearMutateOnAxis()
{
if (!this.IsValidState())
{
return;
}
MutateOnAxis = default;
}
///
/// Sets the x value.
///
/// The value to set to.
public virtual void SetMutateOnAxisX(bool value)
{
MutateOnAxis = new Vector3State(value, MutateOnAxis.yState, MutateOnAxis.zState);
}
///
/// Sets the y value.
///
/// The value to set to.
public virtual void SetMutateOnAxisY(bool value)
{
MutateOnAxis = new Vector3State(MutateOnAxis.xState, value, MutateOnAxis.zState);
}
///
/// Sets the z value.
///
/// The value to set to.
public virtual void SetMutateOnAxisZ(bool value)
{
MutateOnAxis = new Vector3State(MutateOnAxis.xState, MutateOnAxis.yState, value);
}
///
/// Sets the property to the new value.
///
/// The value to set it to.
/// The mutated value if the current component is and the is valid. Otherwise returns the default value for .
public virtual Vector3 SetProperty(Vector3 input)
{
return UpdateProperty(GetNewSetValue(LockSetInput(input)));
}
///
/// Sets the property to the new value.
///
/// The value to set it to.
public virtual void DoSetProperty(Vector3 input)
{
SetProperty(input);
}
///
/// Increments the property by the given value.
///
/// The value to increment by.
/// The mutated value if the current component is and the is valid. Otherwise returns the default value for .
public virtual Vector3 IncrementProperty(Vector3 input)
{
return UpdateProperty(GetNewIncrementValue(LockIncrementInput(input)));
}
///
/// Increments the property by the given value.
///
/// The value to increment by.
public virtual void DoIncrementProperty(Vector3 input)
{
IncrementProperty(input);
}
///
/// Gets the new value to set the input on.
///
/// The input to set.
/// The updated value.
protected abstract Vector3 GetNewSetValue(Vector3 input);
///
/// Gets the new value to increment the input on.
///
/// The input to increment by.
/// The updated value.
protected abstract Vector3 GetNewIncrementValue(Vector3 input);
///
/// Sets the local property to the new value.
///
/// The value to set it to.
/// The new value.
protected abstract Vector3 SetLocalTargetValue(Vector3 input);
///
/// Sets the global property to the new value.
///
/// The value to set it to.
/// The new value.
protected abstract Vector3 SetGlobalTargetValue(Vector3 input);
///
/// Gets the value for a given axis on the local property.
///
/// The axis to get the value from.
/// The axis value.
protected abstract float GetLocalAxisValue(int axis);
///
/// Gets the value for a given axis on the global property.
///
/// The axis to get the value from.
/// The axis value.
protected abstract float GetGlobalAxisValue(int axis);
///
/// Updates the property to the given value.
///
/// The value to update the property to.
/// The updated value of the property.
protected virtual Vector3 UpdateProperty(Vector3 input)
{
if (!IsValid())
{
return default;
}
PreMutated?.Invoke(input);
if (AllowMutate)
{
input = UseLocalValues ? SetLocalTargetValue(input) : SetGlobalTargetValue(input);
PostMutated?.Invoke(input);
}
else
{
MutationSkipped?.Invoke(input);
}
return input;
}
///
/// Locks the set input based on the locked axes.
///
/// The input to lock.
/// The input locked on the required axes.
protected virtual Vector3 LockSetInput(Vector3 input)
{
input.x = MutateOnAxis.xState ? input.x : GetAxisValue(0);
input.y = MutateOnAxis.yState ? input.y : GetAxisValue(1);
input.z = MutateOnAxis.zState ? input.z : GetAxisValue(2);
return input;
}
///
/// Locks the increment input based on the locked axes.
///
/// The input to lock.
/// The input locked on the required axes.
protected virtual Vector3 LockIncrementInput(Vector3 input)
{
input.x = MutateOnAxis.xState ? input.x : 0f;
input.y = MutateOnAxis.yState ? input.y : 0f;
input.z = MutateOnAxis.zState ? input.z : 0f;
return input;
}
///
/// Gets the value for a given axis.
///
/// The axis to get the value from.
/// The axis value.
protected virtual float GetAxisValue(int axis)
{
return UseLocalValues ? GetLocalAxisValue(axis) : GetGlobalAxisValue(axis);
}
///
/// Determines if the process is valid.
///
/// if it is valid.
protected virtual bool IsValid()
{
if (!this.IsValidState())
{
return default;
}
return Target != null;
}
}
}