private Vector3 GetCameraControlRotation(MouseDelta mouseDelta) { float inversionFactor = profile.IsControllerLookInverted ? -1.0f : 1.0f; Vector3 rot = Vector3.zero; if (this.isGamepadLookEnabled) { try { // Get the axes information from the right stick of X360 controller rot.x += InputCurve(UnityEngine.Input.GetAxis(profile.LookVertical)) * inversionFactor; rot.y += InputCurve(UnityEngine.Input.GetAxis(profile.LookHorizontal)); } catch (System.Exception) { this.isGamepadLookEnabled = false; } } mouseRotation.Update(profile.MouseLookButton, cancelRotationKey, profile.MouseLookToggle); if (mouseRotation.IsRotating) { rot.x += -InputCurve(mouseDelta.screenDelta.y * profile.MouseRotationSensitivity); rot.y += InputCurve(mouseDelta.screenDelta.x * profile.MouseRotationSensitivity); rot.z += InputCurve(mouseDelta.screenDelta.z * profile.MouseRotationSensitivity); } rot *= profile.MouseLookSpeed; return(rot); }
/// Apply changes to one controller and update tracking internal abstract void SimulateInput( ref long lastHandTrackedTimestamp, SimulatedControllerState state, bool isSimulating, bool isAlwaysVisible, MouseDelta mouseDelta, bool useMouseRotation);
/// <summary> /// Update hand state based on keyboard and mouse input /// </summary> private void SimulateUserInput(MouseDelta mouseDelta) { float time = Time.time; if (KeyInputSystem.GetKeyDown(profile.ToggleLeftHandKey)) { IsAlwaysVisibleLeft = !IsAlwaysVisibleLeft; } if (KeyInputSystem.GetKeyDown(profile.ToggleRightHandKey)) { IsAlwaysVisibleRight = !IsAlwaysVisibleRight; } if (!Application.isFocused) { isSimulatingLeft = false; isSimulatingRight = false; } else { if (KeyInputSystem.GetKeyDown(profile.LeftHandManipulationKey)) { isSimulatingLeft = true; if (lastSimulationLeft > 0.0f && time - lastSimulationLeft <= profile.DoublePressTime) { IsAlwaysVisibleLeft = !IsAlwaysVisibleLeft; } lastSimulationLeft = time; } if (KeyInputSystem.GetKeyUp(profile.LeftHandManipulationKey)) { isSimulatingLeft = false; } if (KeyInputSystem.GetKeyDown(profile.RightHandManipulationKey)) { isSimulatingRight = true; if (lastSimulationRight > 0.0f && time - lastSimulationRight <= profile.DoublePressTime) { IsAlwaysVisibleRight = !IsAlwaysVisibleRight; } lastSimulationRight = time; } if (KeyInputSystem.GetKeyUp(profile.RightHandManipulationKey)) { isSimulatingRight = false; } } mouseRotation.Update(profile.HandRotateButton, cancelRotationKey, false); SimulateHandInput(ref lastHandTrackedTimestampLeft, HandStateLeft, isSimulatingLeft, IsAlwaysVisibleLeft, mouseDelta, mouseRotation.IsRotating); SimulateHandInput(ref lastHandTrackedTimestampRight, HandStateRight, isSimulatingRight, IsAlwaysVisibleRight, mouseDelta, mouseRotation.IsRotating); float gestureAnimDelta = profile.HandGestureAnimationSpeed * Time.deltaTime; HandStateLeft.GestureBlending += gestureAnimDelta; HandStateRight.GestureBlending += gestureAnimDelta; }
/// <summary> /// Update controller state based on keyboard and mouse input /// </summary> protected virtual void SimulateUserInput(MouseDelta mouseDelta) { float time = Time.time; if (KeyInputSystem.GetKeyDown(profile.ToggleLeftControllerKey)) { IsAlwaysVisibleLeft = !IsAlwaysVisibleLeft; } if (KeyInputSystem.GetKeyDown(profile.ToggleRightControllerKey)) { IsAlwaysVisibleRight = !IsAlwaysVisibleRight; } if (!Application.isFocused && !KeyInputSystem.SimulatingInput) { IsSimulatingLeft = false; IsSimulatingRight = false; } else { if (KeyInputSystem.GetKeyDown(profile.LeftControllerManipulationKey)) { IsSimulatingLeft = true; if (lastSimulationLeft > 0.0f && time - lastSimulationLeft <= profile.DoublePressTime) { IsAlwaysVisibleLeft = !IsAlwaysVisibleLeft; } lastSimulationLeft = time; } if (KeyInputSystem.GetKeyUp(profile.LeftControllerManipulationKey)) { IsSimulatingLeft = false; } if (KeyInputSystem.GetKeyDown(profile.RightControllerManipulationKey)) { IsSimulatingRight = true; if (lastSimulationRight > 0.0f && time - lastSimulationRight <= profile.DoublePressTime) { IsAlwaysVisibleRight = !IsAlwaysVisibleRight; } lastSimulationRight = time; } if (KeyInputSystem.GetKeyUp(profile.RightControllerManipulationKey)) { IsSimulatingRight = false; } if (isSimulatingGaze) { lastSimulationGaze = time; } } mouseRotation.Update(profile.ControllerRotateButton, cancelRotationKey, false); SimulateInput(ref lastInputTrackedTimestampLeft, InputStateLeft, IsSimulatingLeft, IsAlwaysVisibleLeft, mouseDelta, mouseRotation.IsRotating); SimulateInput(ref lastInputTrackedTimestampRight, InputStateRight, IsSimulatingRight, IsAlwaysVisibleRight, mouseDelta, mouseRotation.IsRotating); SimulateInput(ref lastInputTrackedTimestampGaze, InputStateGaze, isSimulatingGaze, false, mouseDelta, mouseRotation.IsRotating); }
/// Apply changes to one hand and update tracking internal override void SimulateInput( ref long lastHandTrackedTimestamp, SimulatedControllerState state, bool isSimulating, bool isAlwaysVisible, MouseDelta mouseDelta, bool useMouseRotation) { var handState = state as SimulatedHandState; bool enableTracking = isAlwaysVisible || isSimulating; if (!handState.IsTracked && enableTracking) { ResetInput(handState, isSimulating); } if (isSimulating) { handState.SimulateInput(mouseDelta, useMouseRotation, profile.MouseRotationSensitivity, profile.MouseControllerRotationSpeed, profile.ControllerJitterAmount); if (isAlwaysVisible) { // Toggle gestures on/off handState.Gesture = ToggleGesture(handState.Gesture); } else { // Enable gesture while mouse button is pressed handState.Gesture = SelectGesture(); } } // Update tracked state of a hand. // If hideTimeout value is null, hands will stay visible after tracking stops. // TODO: DateTime.UtcNow can be quite imprecise, better use Stopwatch.GetTimestamp // https://stackoverflow.com/questions/2143140/c-sharp-datetime-now-precision DateTime currentTime = DateTime.UtcNow; if (enableTracking) { handState.IsTracked = true; lastHandTrackedTimestamp = currentTime.Ticks; } else { float timeSinceTracking = (float)currentTime.Subtract(new DateTime(lastHandTrackedTimestamp)).TotalSeconds; if (timeSinceTracking > profile.ControllerHideTimeout) { handState.IsTracked = false; } } }
/// <summary> /// Update hand state based on keyboard and mouse input /// </summary> protected override void SimulateUserInput(MouseDelta mouseDelta) { base.SimulateUserInput(mouseDelta); SimulatedHandState handStateLeft = InputStateLeft as SimulatedHandState; SimulatedHandState handStateRight = InputStateRight as SimulatedHandState; SimulatedHandState handStateGaze = InputStateGaze as SimulatedHandState; // This line explicitly uses unscaledDeltaTime because we don't want input simulation // to lag when the time scale is set to a value other than 1. Input should still continue // to move freely. float gestureAnimDelta = profile.HandGestureAnimationSpeed * Time.unscaledDeltaTime; handStateLeft.GestureBlending += gestureAnimDelta; handStateRight.GestureBlending += gestureAnimDelta; handStateGaze.GestureBlending = 1.0f; }
/// <summary> /// Translate and rotate the camera transform based on keyboard and mouse input. /// </summary> public void UpdateTransform(Transform transform, MouseDelta mouseDelta) { // Undo the last tracker to Unity transforms applied transform.Translate(-this.lastTrackerToUnityTranslation, Space.World); transform.Rotate(-this.lastTrackerToUnityRotation.eulerAngles, Space.World); // Calculate and apply the camera control movement this frame Vector3 rotate = GetCameraControlRotation(mouseDelta); Vector3 translate = GetCameraControlTranslation(transform); transform.Rotate(rotate.x, 0.0f, 0.0f); transform.Rotate(0.0f, rotate.y, 0.0f, Space.World); transform.Rotate(0.0f, 0.0f, rotate.z); transform.Translate(translate, Space.World); transform.Rotate(this.lastTrackerToUnityRotation.eulerAngles, Space.World); transform.Translate(this.lastTrackerToUnityTranslation, Space.World); }
public void SimulateInput(MouseDelta mouseDelta, bool useMouseRotation, float rotationSensitivity, float rotationScale, float noiseAmount) { if (useMouseRotation) { Vector3 rotationDeltaEulerAngles = Vector3.zero; rotationDeltaEulerAngles.x += -mouseDelta.screenDelta.y * rotationSensitivity; rotationDeltaEulerAngles.y += mouseDelta.screenDelta.x * rotationSensitivity; rotationDeltaEulerAngles.z += mouseDelta.screenDelta.z * rotationSensitivity; rotationDeltaEulerAngles *= rotationScale; ViewportRotation = ViewportRotation + rotationDeltaEulerAngles; } else { ViewportPosition += mouseDelta.viewportDelta; } JitterOffset = UnityEngine.Random.insideUnitSphere * noiseAmount; }
/// <summary> /// Capture a snapshot of simulated hand data based on current state. /// </summary> public bool UpdateHandData(SimulatedHandData handDataLeft, SimulatedHandData handDataRight, SimulatedHandData handDataGaze, MouseDelta mouseDelta) { SimulateUserInput(mouseDelta); SimulatedHandState handStateLeft = InputStateLeft as SimulatedHandState; SimulatedHandState handStateRight = InputStateRight as SimulatedHandState; SimulatedHandState handStateGaze = InputStateGaze as SimulatedHandState; handStateLeft.Update(); handStateRight.Update(); handStateGaze.Update(); bool handDataChanged = false; // Cache the generator delegates so we don't gc alloc every frame if (generatorLeft == null) { generatorLeft = handStateLeft.FillCurrentFrame; } if (generatorRight == null) { generatorRight = handStateRight.FillCurrentFrame; } if (generatorGaze == null) { generatorGaze = handStateGaze.FillCurrentFrame; } handDataChanged |= handDataLeft.Update(handStateLeft.IsTracked, handStateLeft.IsPinching, generatorLeft); handDataChanged |= handDataRight.Update(handStateRight.IsTracked, handStateRight.IsPinching, generatorRight); handDataChanged |= handDataGaze.Update(handStateGaze.IsTracked, handStateGaze.IsPinching, generatorGaze); return(handDataChanged); }
/// <summary> /// Update hand state based on keyboard and mouse input /// </summary> private void SimulateUserInput(MouseDelta mouseDelta) { float time = Time.time; if (KeyInputSystem.GetKeyDown(profile.ToggleLeftHandKey)) { IsAlwaysVisibleLeft = !IsAlwaysVisibleLeft; } if (KeyInputSystem.GetKeyDown(profile.ToggleRightHandKey)) { IsAlwaysVisibleRight = !IsAlwaysVisibleRight; } if (!Application.isFocused && !KeyInputSystem.SimulatingInput) { isSimulatingLeft = false; isSimulatingRight = false; } else { if (KeyInputSystem.GetKeyDown(profile.LeftHandManipulationKey)) { isSimulatingLeft = true; if (lastSimulationLeft > 0.0f && time - lastSimulationLeft <= profile.DoublePressTime) { IsAlwaysVisibleLeft = !IsAlwaysVisibleLeft; } lastSimulationLeft = time; } if (KeyInputSystem.GetKeyUp(profile.LeftHandManipulationKey)) { isSimulatingLeft = false; } if (KeyInputSystem.GetKeyDown(profile.RightHandManipulationKey)) { isSimulatingRight = true; if (lastSimulationRight > 0.0f && time - lastSimulationRight <= profile.DoublePressTime) { IsAlwaysVisibleRight = !IsAlwaysVisibleRight; } lastSimulationRight = time; } if (KeyInputSystem.GetKeyUp(profile.RightHandManipulationKey)) { isSimulatingRight = false; } if (isSimulatingGaze) { lastSimulationGaze = time; } } mouseRotation.Update(profile.HandRotateButton, cancelRotationKey, false); SimulateHandInput(ref lastHandTrackedTimestampLeft, HandStateLeft, isSimulatingLeft, IsAlwaysVisibleLeft, mouseDelta, mouseRotation.IsRotating); SimulateHandInput(ref lastHandTrackedTimestampRight, HandStateRight, isSimulatingRight, IsAlwaysVisibleRight, mouseDelta, mouseRotation.IsRotating); SimulateHandInput(ref lastHandTrackedTimestampGaze, HandStateGaze, isSimulatingGaze, false, mouseDelta, mouseRotation.IsRotating); // This line explicitly uses unscaledDeltaTime because we don't want input simulation // to lag when the time scale is set to a value other than 1. Input should still continue // to move freely. float gestureAnimDelta = profile.HandGestureAnimationSpeed * Time.unscaledDeltaTime; HandStateLeft.GestureBlending += gestureAnimDelta; HandStateRight.GestureBlending += gestureAnimDelta; HandStateGaze.GestureBlending = 1.0f; }
/// <inheritdoc /> internal override void SimulateInput(ref long lastMotionControllerTrackedTimestamp, SimulatedControllerState state, bool isSimulating, bool isAlwaysVisible, MouseDelta mouseDelta, bool useMouseRotation) { if (!(state is SimulatedMotionControllerState motionControllerState)) { return; } bool enableTracking = isAlwaysVisible || isSimulating; if (!motionControllerState.IsTracked && enableTracking) { ResetInput(motionControllerState, isSimulating); } if (isSimulating) { motionControllerState.SimulateInput(mouseDelta, useMouseRotation, profile.MouseRotationSensitivity, profile.MouseControllerRotationSpeed, profile.ControllerJitterAmount); motionControllerState.ButtonState = new SimulatedMotionControllerButtonState { IsSelecting = KeyInputSystem.GetKey(profile.MotionControllerTriggerKey), IsGrabbing = KeyInputSystem.GetKey(profile.MotionControllerGrabKey), IsPressingMenu = KeyInputSystem.GetKey(profile.MotionControllerMenuKey) }; } // Update tracked state of a motion controller. // If hideTimeout value is null, motion controllers will stay visible after tracking stops. // TODO: DateTime.UtcNow can be quite imprecise, better use Stopwatch.GetTimestamp // https://stackoverflow.com/questions/2143140/c-sharp-datetime-now-precision DateTime currentTime = DateTime.UtcNow; if (enableTracking) { motionControllerState.IsTracked = true; lastMotionControllerTrackedTimestamp = currentTime.Ticks; } else { float timeSinceTracking = (float)currentTime.Subtract(new DateTime(lastMotionControllerTrackedTimestamp)).TotalSeconds; if (timeSinceTracking > profile.ControllerHideTimeout) { motionControllerState.IsTracked = false; } } }
/// <summary> /// Capture a snapshot of simulated motion controller data based on current state. /// </summary> public void UpdateControllerData(SimulatedMotionControllerData motionControllerDataLeft, SimulatedMotionControllerData motionControllerDataRight, MouseDelta mouseDelta) { SimulateUserInput(mouseDelta); SimulatedMotionControllerState motionControllerStateLeft = InputStateLeft as SimulatedMotionControllerState; SimulatedMotionControllerState motionControllerStateRight = InputStateRight as SimulatedMotionControllerState; motionControllerStateLeft.Update(); motionControllerStateRight.Update(); // Cache the generator delegates so we don't gc alloc every frame if (updaterLeft == null) { updaterLeft = motionControllerStateLeft.UpdateControllerPose; } if (updaterRight == null) { updaterRight = motionControllerStateRight.UpdateControllerPose; } motionControllerDataLeft.Update(motionControllerStateLeft.IsTracked, motionControllerStateLeft.ButtonState, updaterLeft); motionControllerDataRight.Update(motionControllerStateRight.IsTracked, motionControllerStateRight.ButtonState, updaterRight); }