123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123 |
- using UnityEngine.InputSystem.Layouts;
- using UnityEngine.InputSystem.LowLevel;
- using UnityEngine.InputSystem.Utilities;
-
- ////REVIEW: expose euler angle subcontrols?
-
- namespace UnityEngine.InputSystem.Controls
- {
- /// <summary>
- /// A generic input control reading quaternion (rotation) values.
- /// </summary>
- public class QuaternionControl : InputControl<Quaternion>
- {
- // Accessing these components as individual controls usually doesn't make too much sense,
- // but having these controls allows changing the state format on the quaternion without
- // requiring the control to explicitly support the various different storage formats.
- // Also, it allows putting processors on the individual components which may be necessary
- // to properly convert the source data.
-
- /// <summary>
- /// The X component of the quaternion.
- /// </summary>
- /// <value>Control representing the X component.</value>
- [InputControl(displayName = "X")]
- public AxisControl x { get; set; }
-
- /// <summary>
- /// The Y component of the quaternion.
- /// </summary>
- /// <value>Control representing the Y component.</value>
- [InputControl(displayName = "Y")]
- public AxisControl y { get; set; }
-
- /// <summary>
- /// The Z component of the quaternion.
- /// </summary>
- /// <value>Control representing the Z component.</value>
- [InputControl(displayName = "Z")]
- public AxisControl z { get; set; }
-
- /// <summary>
- /// The W component of the quaternion.
- /// </summary>
- /// <value>Control representing the W component.</value>
- [InputControl(displayName = "W")]
- public AxisControl w { get; set; }
-
- /// <summary>
- /// Default-initialize the control.
- /// </summary>
- public QuaternionControl()
- {
- m_StateBlock.sizeInBits = sizeof(float) * 4 * 8;
- m_StateBlock.format = InputStateBlock.FormatQuaternion;
- }
-
- /// <inheritdoc/>
- protected override void FinishSetup()
- {
- x = GetChildControl<AxisControl>("x");
- y = GetChildControl<AxisControl>("y");
- z = GetChildControl<AxisControl>("z");
- w = GetChildControl<AxisControl>("w");
- base.FinishSetup();
- }
-
- /// <inheritdoc/>
- public override unsafe Quaternion ReadUnprocessedValueFromState(void* statePtr)
- {
- switch (m_OptimizedControlDataType)
- {
- case InputStateBlock.kFormatQuaternion:
- return *(Quaternion*)((byte*)statePtr + (int)m_StateBlock.byteOffset);
- default:
- return new Quaternion(
- x.ReadValueFromStateWithCaching(statePtr),
- y.ReadValueFromStateWithCaching(statePtr),
- z.ReadValueFromStateWithCaching(statePtr),
- w.ReadUnprocessedValueFromStateWithCaching(statePtr));
- }
- }
-
- /// <inheritdoc/>
- public override unsafe void WriteValueIntoState(Quaternion value, void* statePtr)
- {
- switch (m_OptimizedControlDataType)
- {
- case InputStateBlock.kFormatQuaternion:
- *(Quaternion*)((byte*)statePtr + (int)m_StateBlock.byteOffset) = value;
- break;
- default:
- x.WriteValueIntoState(value.x, statePtr);
- y.WriteValueIntoState(value.y, statePtr);
- z.WriteValueIntoState(value.z, statePtr);
- w.WriteValueIntoState(value.w, statePtr);
- break;
- }
- }
-
- protected override FourCC CalculateOptimizedControlDataType()
- {
- if (
- m_StateBlock.sizeInBits == sizeof(float) * 4 * 8 &&
- m_StateBlock.bitOffset == 0 &&
- x.optimizedControlDataType == InputStateBlock.FormatFloat &&
- y.optimizedControlDataType == InputStateBlock.FormatFloat &&
- z.optimizedControlDataType == InputStateBlock.FormatFloat &&
- w.optimizedControlDataType == InputStateBlock.FormatFloat &&
- y.m_StateBlock.byteOffset == x.m_StateBlock.byteOffset + 4 &&
- z.m_StateBlock.byteOffset == x.m_StateBlock.byteOffset + 8 &&
- w.m_StateBlock.byteOffset == x.m_StateBlock.byteOffset + 12 &&
- // For some unknown reason ReadUnprocessedValueFromState here uses ReadValueFromState on x/y/z (but not w)
- // which means we can't optimize if there any processors on x/y/z
- x.m_ProcessorStack.length == 0 &&
- y.m_ProcessorStack.length == 0 &&
- z.m_ProcessorStack.length == 0
- )
- return InputStateBlock.FormatQuaternion;
-
- return InputStateBlock.FormatInvalid;
- }
- }
- }
|