using System; using System.Collections; using System.Collections.Generic; using System.Runtime.InteropServices; using System.Text; using UnityEngine; namespace Omni { public class OmniDataComponent: MonoBehaviour { protected OmniManager omniManager; protected int startingStepCount; [Header("Output and Calculated Variables. Can be used to debug or poll during game.")] [HideInInspector] public Vector2 hidInput; // holds x and y values for movement from the controller [HideInInspector] public float currentOmniYaw; [HideInInspector] public int currentStepCount; [HideInInspector] public float omniOffset = 0f; [HideInInspector] public float angleBetweenOmniAndCamera; [HideInInspector] [Range(0.0f, 1.0f)] [Tooltip("Fully coupled to camera = 100%, Fully decoupled (follows torso/ring angle = 0%.")] public float couplingPercentage = 1.0f; protected bool hasSetCouplingPercentage = false; protected byte rawX = 0; protected byte rawY = 0; protected float omniX = 0; protected float omniY = 0; /* Disable unused variable warnings */ #pragma warning disable 0414 protected static OmniCommon.Messages.OmniRawData rawData; protected static OmniCommon.Messages.OmniMotionData motionData; #pragma warning restore 0414 private bool debugNotReceivingData = false; private bool hasReceivedOmniData = false; public void Setup(OmniManager manager) { omniManager = manager; } /// /// Pulls packets from the Omni and decodes them to populate the class variables and motiondata. /// public void ReadAndSetOmniData(OmniConnectionComponent connection, bool hasFullyInitialized) { ReadOmniData(connection); SetAfterReadOmniData(hasFullyInitialized); } /// /// Pulls packets from the Omni and decodes them to populate the motiondata. /// private void ReadOmniData(OmniConnectionComponent connection) { byte[] packet = null; if (omniManager.ReadData(ref packet) > 0) { OmniCommon.Messages.OmniBaseMessage obm = OmniCommon.OmniPacketBuilder.decodePacket(packet); if (debugNotReceivingData == true || hasReceivedOmniData == false) { Debug.Log(System.DateTime.Now.ToLongTimeString() + ": OmniDataComponent(ReadOmniData) - During this frame, the Omni started reading data from the Omni data packet."); debugNotReceivingData = false; StartCoroutine(connection.ConfigureOmniConnect()); } hasReceivedOmniData = true; if (obm != null) { switch (obm.MsgType) { case OmniCommon.Messages.MessageType.OmniMotionAndRawDataMessage: OmniCommon.Messages.OmniMotionAndRawDataMessage OmniMotionAndRawData = new OmniCommon.Messages.OmniMotionAndRawDataMessage(obm); motionData = OmniMotionAndRawData.GetMotionData(); break; default: break; } } } else { motionData = null; if (debugNotReceivingData == false) { Debug.LogError(System.DateTime.Now.ToLongTimeString() + ": OmniDataComponent(ReadOmniData) - During this frame, the Omni stopped receiving valid data from the Omni data packet."); debugNotReceivingData = true; } } } /// /// Populate the class variables from motiondata. /// private void SetAfterReadOmniData(bool hasFullyInitialized) { if (!IsMotionDataUnknown()) { currentOmniYaw = motionData.RingAngle; rawX = motionData.GamePad_X; rawY = motionData.GamePad_Y; omniX = motionData.GamePad_X; omniY = motionData.GamePad_Y; if (omniX > 0) { omniX = (omniX / 255.0f) * 2f - 1f; } else omniX = -1f; if (omniY > 0) { omniY = (omniY / 255.0f) * 2f - 1f; } else omniY = -1; //clamp '0' if (rawX == 127) { omniX = 0f; } if (rawY == 127) { omniY = 0f; } omniY *= -1f; hidInput = new Vector2(omniX, omniY); if (hasFullyInitialized) UpdateStepCountFromMotionData(); } else { hidInput = Vector2.zero; } } public void SetCouplingPercentage(bool needsCoupling) { if (hasSetCouplingPercentage == false) { couplingPercentage = !needsCoupling ? 1.0f : OmniMovementCalibration.GetCouplingPercentage(); hasSetCouplingPercentage = true; Debug.Log(System.DateTime.Now.ToLongTimeString() + ": OmniDataComponent(GetOmniInputForCharacterMovement) - Coupling Percentage = " + couplingPercentage); } } public float CalculateForwardRotation(bool needsCoupling) { //keep within bounds (0, 360) if (currentOmniYaw > 360f) currentOmniYaw -= 360f; if (currentOmniYaw < 0f) currentOmniYaw += 360f; //Get the coupling percentage from Omniverse SetCouplingPercentage(needsCoupling); //calculate forward rotation return (currentOmniYaw - omniOffset + transform.rotation.eulerAngles.y) + (angleBetweenOmniAndCamera * couplingPercentage); } //angle difference between camera and omni angle, used for decoupled effect public void ComputeAngleBetweenControllerAndCamera(Transform cameraReference) { float cameraYaw = cameraReference.rotation.eulerAngles.y; float adjustedOmniYaw = currentOmniYaw - omniOffset + transform.rotation.eulerAngles.y; angleBetweenOmniAndCamera = Mathf.Abs(cameraYaw - adjustedOmniYaw) % 360; angleBetweenOmniAndCamera = angleBetweenOmniAndCamera > 180 ? 360 - angleBetweenOmniAndCamera : angleBetweenOmniAndCamera; //calculate sign float angleForSignCalculation = (cameraYaw - adjustedOmniYaw) % 360; float sign = (angleForSignCalculation >= 0 && angleForSignCalculation <= 180) || (angleForSignCalculation <= -180 && angleForSignCalculation >= -360) ? 1 : -1; angleBetweenOmniAndCamera *= sign; } /// /// Updates step count from motion data after getting the initial step count in the align. /// protected void UpdateStepCountFromMotionData() { if (IsMotionDataUnknown()) return; currentStepCount = (int)motionData.StepCount - startingStepCount; } /// /// Resets step counter to 0. Call at anytime you want to reset the step count. /// public void ResetStepCount() { if (IsMotionDataUnknown()) return; startingStepCount = (int)motionData.StepCount; currentStepCount = 0; } public void ResetHasSetCouplingPercentage() { hasSetCouplingPercentage = false; } public bool IsMotionDataUnknown() { return motionData == null; } } }