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; } } }