namespace Zinnia.Data.Operation.Mutation
{
using System;
using UnityEngine;
using Zinnia.Data.Type;
using Zinnia.Extension;
///
/// Mutates the Euler rotation of a transform with an optional custom rotation origin.
///
public class TransformEulerRotationMutator : TransformPropertyMutator
{
#region Rotation Settings
[Header("Rotation Settings")]
[Tooltip("An optional rotation origin to perform the rotation around. The origin must be a child of the TransformPropertyMutator.Target.")]
[SerializeField]
private GameObject origin;
///
/// An optional rotation origin to perform the rotation around. The origin must be a child of the .
///
public GameObject Origin
{
get
{
return origin;
}
set
{
origin = value;
if (this.IsMemberChangeAllowed())
{
OnAfterOriginChange();
}
}
}
[Tooltip("Determines which axes to consider from the Origin.")]
[SerializeField]
private Vector3State applyOriginOnAxis = Vector3State.True;
///
/// Determines which axes to consider from the .
///
public Vector3State ApplyOriginOnAxis
{
get
{
return applyOriginOnAxis;
}
set
{
applyOriginOnAxis = value;
}
}
#endregion
///
/// Clears .
///
public virtual void ClearOrigin()
{
if (!this.IsValidState())
{
return;
}
Origin = default;
}
///
/// Clears .
///
public virtual void ClearApplyOriginOnAxis()
{
if (!this.IsValidState())
{
return;
}
ApplyOriginOnAxis = default;
}
///
/// Sets the x value.
///
/// The value to set to.
public virtual void SetApplyOriginOnAxisX(bool value)
{
ApplyOriginOnAxis = new Vector3State(value, ApplyOriginOnAxis.yState, ApplyOriginOnAxis.zState);
}
///
/// Sets the y value.
///
/// The value to set to.
public virtual void SetApplyOriginOnAxisY(bool value)
{
ApplyOriginOnAxis = new Vector3State(ApplyOriginOnAxis.xState, value, ApplyOriginOnAxis.zState);
}
///
/// Sets the z value.
///
/// The value to set to.
public virtual void SetApplyOriginOnAxisZ(bool value)
{
ApplyOriginOnAxis = new Vector3State(ApplyOriginOnAxis.xState, ApplyOriginOnAxis.yState, value);
}
///
protected override float GetGlobalAxisValue(int axis)
{
return Target != null ? Target.transform.eulerAngles[axis] : default;
}
///
protected override float GetLocalAxisValue(int axis)
{
return Target != null ? Target.transform.localEulerAngles[axis] : default;
}
///
protected override Vector3 GetNewSetValue(Vector3 input)
{
return input;
}
///
protected override Vector3 GetNewIncrementValue(Vector3 input)
{
if (Target == null)
{
return default;
}
return (UseLocalValues ? Target.transform.localEulerAngles : Target.transform.eulerAngles) + input;
}
///
protected override Vector3 SetGlobalTargetValue(Vector3 input)
{
if (Target == null)
{
return default;
}
Vector3 originPosition = GetOriginPosition();
Target.transform.eulerAngles = input;
ApplyRotationOriginPosition(originPosition);
return Target.transform.eulerAngles;
}
///
protected override Vector3 SetLocalTargetValue(Vector3 input)
{
if (Target == null)
{
return default;
}
Vector3 originPosition = GetOriginPosition();
Target.transform.localEulerAngles = input;
ApplyRotationOriginPosition(originPosition);
return Target.transform.localEulerAngles;
}
protected virtual void OnEnable()
{
OnAfterOriginChange();
}
///
/// Returns the position if a is defined.
///
/// The origin position.
protected virtual Vector3 GetOriginPosition()
{
if (Origin == null)
{
return Vector3.zero;
}
Vector3 originAxesToApply = ApplyOriginOnAxis.ToVector3();
Vector3? cachedOriginLocalPosition = null;
if (!originAxesToApply.ApproxEquals(Vector3.one))
{
cachedOriginLocalPosition = Origin.transform.localPosition;
originAxesToApply.Scale(Origin.transform.localPosition);
Origin.transform.localPosition = originAxesToApply;
}
Vector3 returnValue = Origin.transform.position;
if (cachedOriginLocalPosition != null)
{
Origin.transform.localPosition = cachedOriginLocalPosition.GetValueOrDefault();
}
return returnValue;
}
///
/// Applies the position of the to the to ensure it rotates around the set origin.
///
/// The offset position to apply.
protected virtual void ApplyRotationOriginPosition(Vector3 originPosition)
{
if (Origin == null)
{
return;
}
originPosition -= GetOriginPosition();
Target.transform.position += originPosition;
}
///
/// Called after has been changed.
///
protected virtual void OnAfterOriginChange()
{
if (Origin == null || Target == null)
{
return;
}
if (!Origin.transform.IsChildOf(Target.transform))
{
throw new ArgumentException($"The `RotationOrigin` [{Origin.name}] must be a child of the `Target` [{Target.name}] GameObject.");
}
}
[Obsolete("Use `OnAfterOriginChange` instead.")]
protected virtual void OnAfterRotationOriginChange()
{
OnAfterOriginChange();
}
}
}