private bool UpdateHandDataFromState(SimulatedHandData frame, SimulatedHandState state) { bool handDataChanged = false; bool wasTracked = frame.IsTracked; bool wasPinching = frame.IsPinching; frame.IsTracked = state.IsVisible; frame.IsPinching = state.IsPinching; if (wasTracked != frame.IsTracked || wasPinching != frame.IsPinching) { handDataChanged = true; } if (frame.IsTracked) { var prevTime = frame.Timestamp; frame.Timestamp = DateTime.UtcNow.Ticks; if (frame.Timestamp != prevTime) { state.FillCurrentFrame(frame.Joints); handDataChanged = true; } } else { // If frame is not tracked, set timestamp to zero frame.Timestamp = 0; } return(handDataChanged); }
public CustomSimulatedHandDataProvider(MixedRealityInputSimulationProfile _profile) { profile = _profile; stateLeft = new SimulatedHandState(Handedness.Left); stateRight = new SimulatedHandState(Handedness.Right); }
public SimulatedHandDataProvider(MixedRealityInputSimulationProfile _profile) { profile = _profile; HandStateLeft = new SimulatedHandState(Handedness.Left); HandStateRight = new SimulatedHandState(Handedness.Right); HandStateLeft.Gesture = profile.DefaultHandGesture; HandStateRight.Gesture = profile.DefaultHandGesture; }
/// Apply changes to one hand and update tracking private void SimulateHandInput( ref long lastSimulatedTimestamp, SimulatedHandState state, bool isSimulating, bool isAlwaysVisible, Vector3 mouseDelta, Vector3 rotationDeltaEulerAngles) { bool enableTracking = isAlwaysVisible || isSimulating; if (!state.IsTracked && enableTracking) { // Start at current mouse position Vector3 mousePos = UnityEngine.Input.mousePosition; state.ScreenPosition = new Vector3(mousePos.x, mousePos.y, profile.DefaultHandDistance); } if (isSimulating) { state.SimulateInput(mouseDelta, profile.HandJitterAmount, rotationDeltaEulerAngles); if (isAlwaysVisible) { // Toggle gestures on/off state.Gesture = ToggleGesture(state.Gesture); } else { // Enable gesture while mouse button is pressed state.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) { state.IsTracked = true; lastSimulatedTimestamp = currentTime.Ticks; } else { float timeSinceTracking = (float)currentTime.Subtract(new DateTime(lastSimulatedTimestamp)).TotalSeconds; if (timeSinceTracking > profile.HandHideTimeout) { state.IsTracked = false; } } }
private void AnimateGesture(SimulatedHandState state, float gestureAnimDelta) { if (state.IsAlwaysTracked) { // Toggle gestures on/off state.AnimateGesture(ToggleGesture(state.Gesture), gestureAnimDelta); } else { // Enable gesture while mouse button is pressed state.AnimateGesture(SelectGesture(), gestureAnimDelta); } }
/// Apply changes to one hand and update tracking private void SimulateHandInput( ref long lastHandTrackedTimestamp, SimulatedHandState state, bool isSimulating, bool isAlwaysVisible, MouseDelta mouseDelta, bool useMouseRotation) { bool enableTracking = isAlwaysVisible || isSimulating; if (!state.IsTracked && enableTracking) { ResetHand(state, isSimulating); } if (isSimulating) { state.SimulateInput(mouseDelta, useMouseRotation, profile.MouseRotationSensitivity, profile.MouseHandRotationSpeed, profile.HandJitterAmount); if (isAlwaysVisible) { // Toggle gestures on/off state.Gesture = ToggleGesture(state.Gesture); } else { // Enable gesture while mouse button is pressed state.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) { state.IsTracked = true; lastHandTrackedTimestamp = currentTime.Ticks; } else { float timeSinceTracking = (float)currentTime.Subtract(new DateTime(lastHandTrackedTimestamp)).TotalSeconds; if (timeSinceTracking > profile.HandHideTimeout) { state.IsTracked = false; } } }
public SimulatedHandDataProvider(MixedRealityInputSimulationProfile _profile) : base(_profile) { InputStateLeft = new SimulatedHandState(Handedness.Left); InputStateRight = new SimulatedHandState(Handedness.Right); InputStateGaze = new SimulatedHandState(Handedness.None); SimulatedHandState handStateLeft = InputStateLeft as SimulatedHandState; SimulatedHandState handStateRight = InputStateRight as SimulatedHandState; SimulatedHandState handStateGaze = InputStateGaze as SimulatedHandState; handStateLeft.Gesture = profile.DefaultHandGesture; handStateRight.Gesture = profile.DefaultHandGesture; handStateGaze.Gesture = profile.DefaultHandGesture; }
/// <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; }
private void ResetHand(SimulatedHandState state, bool isSimulating) { if (isSimulating) { // Start at current mouse position Vector3 mousePos = UnityEngine.Input.mousePosition; state.ViewportPosition = CameraCache.Main.ScreenToViewportPoint(new Vector3(mousePos.x, mousePos.y, profile.DefaultHandDistance)); } else { state.ViewportPosition = new Vector3(0.5f, 0.5f, profile.DefaultHandDistance); } state.Gesture = profile.DefaultHandGesture; state.ResetGesture(); state.ResetRotation(); }
public void RecenterHand(Handedness handedness) { SimulatedHandState handToMove = stateRight; if (handedness == Handedness.Left) { handToMove = stateLeft; } else if (handedness == Handedness.Right) { handToMove = stateRight; } else { RecenterHand(Handedness.Left); RecenterHand(Handedness.Right); return; } handToMove.RecenterAtDistance(profile.DefaultHandDistance); AnimateGesture(handToMove, profile.HandGestureAnimationSpeed * Time.deltaTime); ApplyHandData(); }
/// <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); }