/// <param name="inputSource">The device you would like to get data from. Any if the action is not device specific.</param> public override void UpdateValue(SteamVR_Input_Sources inputSource) { lastActionData[inputSource] = actionData[inputSource]; lastActive[inputSource] = active[inputSource]; EVRInputError err = OpenVR.Input.GetAnalogActionData(handle, ref tempActionData, actionData_size, SteamVR_Input_Source.GetHandle(inputSource)); if (err != EVRInputError.None) { Debug.LogError("GetAnalogActionData error (" + fullPath + "): " + err.ToString() + " handle: " + handle.ToString()); } active[inputSource] = tempActionData.bActive; activeOrigin[inputSource] = tempActionData.activeOrigin; updateTime[inputSource] = tempActionData.fUpdateTime; changed[inputSource] = false; actionData[inputSource] = tempActionData; if (Mathf.Abs(GetAxisDelta(inputSource)) > changeTolerance) { changed[inputSource] = true; lastChanged[inputSource] = Time.time; if (onChange[inputSource] != null) { onChange[inputSource].Invoke(this); } } if (onUpdate[inputSource] != null) { onUpdate[inputSource].Invoke(this); } if (onActiveChange[inputSource] != null && lastActive[inputSource] != active[inputSource]) { onActiveChange[inputSource].Invoke(this, active[inputSource]); } }
/// <summary> /// SteamVR_Standalone keeps a log of past poses so you can retrieve old poses or estimated poses in the future by passing in a secondsFromNow value that is negative or positive. /// </summary> /// <param name="secondsFromNow">The time offset in the future (estimated) or in the past (previously recorded) you want to get data from</param> /// <returns>true if we successfully returned a pose</returns> public bool GetPoseAtTimeOffset(float secondsFromNow, out Vector3 positionAtTime, out Quaternion rotationAtTime, out Vector3 velocityAtTime, out Vector3 angularVelocityAtTime) { EVRInputError err = OpenVR.Input.GetPoseActionDataRelativeToNow(handle, universeOrigin, secondsFromNow, ref tempPoseActionData, poseActionData_size, inputSourceHandle); if (err != EVRInputError.None) { Debug.LogError("<b>[SteamVR_Standalone]</b> GetPoseActionData error (" + fullPath + "): " + err.ToString() + " handle: " + handle.ToString()); //todo: this should be an error velocityAtTime = Vector3.zero; angularVelocityAtTime = Vector3.zero; positionAtTime = Vector3.zero; rotationAtTime = Quaternion.identity; return(false); } velocityAtTime = GetUnityCoordinateVelocity(tempPoseActionData.pose.vVelocity); angularVelocityAtTime = GetUnityCoordinateAngularVelocity(tempPoseActionData.pose.vAngularVelocity); positionAtTime = tempPoseActionData.pose.mDeviceToAbsoluteTracking.GetPosition(); rotationAtTime = tempPoseActionData.pose.mDeviceToAbsoluteTracking.GetRotation(); return(true); }
/// <summary> /// Trigger the haptics at a certain time for a certain length /// </summary> /// <param name="secondsFromNow">How long from the current time to execute the action (in seconds - can be 0)</param> /// <param name="durationSeconds">How long the haptic action should last (in seconds)</param> /// <param name="frequency">How often the haptic motor should bounce (0 - 320 in hz. The lower end being more useful)</param> /// <param name="amplitude">How intense the haptic action should be (0 - 1)</param> /// <param name="inputSource">The device you would like to execute the haptic action. Any if the action is not device specific.</param> public void Execute(float secondsFromNow, float durationSeconds, float frequency, float amplitude) { if (SteamVR_Input.isStartupFrame) { return; } timeLastExecuted = Time.realtimeSinceStartup; EVRInputError err = OpenVR.Input.TriggerHapticVibrationAction(handle, secondsFromNow, durationSeconds, frequency, amplitude, inputSourceHandle); //Debug.Log(string.Format("[{5}: haptic] secondsFromNow({0}), durationSeconds({1}), frequency({2}), amplitude({3}), inputSource({4})", secondsFromNow, durationSeconds, frequency, amplitude, inputSource, this.GetShortName())); if (err != EVRInputError.None) { Debug.LogError("<b>[SteamVR_Standalone]</b> TriggerHapticVibrationAction (" + fullPath + ") error: " + err.ToString() + " handle: " + handle.ToString()); } if (onExecute != null) { onExecute.Invoke(vibrationAction, inputSource, secondsFromNow, durationSeconds, frequency, amplitude); } }
public static void Initialize() { List <SteamVR_Input_Sources> allSourcesList = new List <SteamVR_Input_Sources>(); string[] enumNames = System.Enum.GetNames(enumType); inputSourceHandlesBySource = new Dictionary <SteamVR_Input_Sources, ulong>(new SteamVR_Input_Sources_Comparer()); inputSourceSourcesByHandle = new Dictionary <ulong, SteamVR_Input_Sources>(); for (int enumIndex = 0; enumIndex < enumNames.Length; enumIndex++) { string path = GetPath(enumNames[enumIndex]); ulong handle = 0; EVRInputError err = OpenVR.Input.GetInputSourceHandle(path, ref handle); if (err != EVRInputError.None) { Debug.LogError("<b>[SteamVR]</b> GetInputSourceHandle (" + path + ") error: " + err.ToString()); } if (enumNames[enumIndex] == SteamVR_Input_Sources.Any.ToString()) //todo: temporary hack { inputSourceHandlesBySource.Add((SteamVR_Input_Sources)enumIndex, 0); inputSourceSourcesByHandle.Add(0, (SteamVR_Input_Sources)enumIndex); } else { inputSourceHandlesBySource.Add((SteamVR_Input_Sources)enumIndex, handle); inputSourceSourcesByHandle.Add(handle, (SteamVR_Input_Sources)enumIndex); } allSourcesList.Add((SteamVR_Input_Sources)enumIndex); } allSources = allSourcesList.ToArray(); }
/// <summary><strong>[Should not be called by user code]</strong> /// Updates the data for this action and this input source. Sends related events. /// </summary> public virtual void UpdateValue(bool skipStateAndEventUpdates) { lastChanged = changed; lastPoseActionData = poseActionData; lastLocalPosition = localPosition; lastLocalRotation = localRotation; lastVelocity = velocity; lastAngularVelocity = angularVelocity; EVRInputError err = OpenVR.Input.GetPoseActionData(handle, universeOrigin, predictedSecondsFromNow, ref poseActionData, poseActionData_size, inputSourceHandle); if (err != EVRInputError.None) { if (err == EVRInputError.InvalidHandle && Time.realtimeSinceStartup < 5) { //ignore. This is probably just steamvr input starting up. //todo: get this fixed } else { Debug.LogError("<b>[SteamVR]</b> GetPoseActionData error (" + fullPath + "): " + err.ToString() + " Handle: " + handle.ToString() + ". Input source: " + inputSource.ToString()); } } SetCacheVariables(); changed = GetChanged(); if (changed) { changedTime = updateTime + predictedSecondsFromNow; } if (skipStateAndEventUpdates == false) { CheckAndSendEvents(); } }
internal OpenVRInputException(string message, EVRInputError error) : base(message) { Error = error; }
private bool TryGetDeviceIndexFromOrigin(CVRInput vrInput, ulong origin, out OriginData originData, out EVRInputError error) { if (!m_originDataCache.TryGetValue(origin, out originData)) { var originInfo = default(InputOriginInfo_t); error = vrInput.GetOriginTrackedDeviceInfo(origin, ref originInfo, m_originInfoSize); if (error != EVRInputError.None) { originData = new OriginData() { devicePath = OpenVR.k_ulInvalidInputValueHandle, deviceIndex = OpenVR.k_unTrackedDeviceIndexInvalid, }; return(false); } else { originData = new OriginData() { devicePath = originInfo.devicePath, deviceIndex = originInfo.trackedDeviceIndex, }; s_devicePathHandles[originInfo.trackedDeviceIndex] = originInfo.devicePath; //Debug.Log("Set device path " + originInfo.trackedDeviceIndex + " to " + originInfo.devicePath); m_originDataCache.Add(origin, originData); return(true); } } else { error = EVRInputError.None; return(true); } }
private static void Worker() { Thread.CurrentThread.IsBackground = true; while (true) { // Getting events var vrEvents = new List <VREvent_t>(); var vrEvent = new VREvent_t(); try { while (OpenVR.System.PollNextEvent(ref vrEvent, Utils.SizeOf(vrEvent))) { vrEvents.Add(vrEvent); } } catch (Exception e) { Utils.PrintWarning($"Could not get evemt: {e.Message}"); } // Priting events foreach (var e in vrEvents) { var pid = e.data.process.pid; if ((EVREventType)vrEvent.eventType != EVREventType.VREvent_None) { var name = Enum.GetName(typeof(EVREventType), e.eventType); var message = $"[{pid}] {name}"; if (pid == 0) { Utils.PrintVerbose(message); } else if (name.ToLower().Contains("fail")) { Utils.PrintWarning(message); } else if (name.ToLower().Contains("error")) { Utils.PrintError(message); } else if (name.ToLower().Contains("success")) { Utils.PrintInfo(message); } else { Utils.Print(message); } } } // Update action set // Seems I need the action set when updating the state of actions. var actionSet = new VRActiveActionSet_t(); actionSet.ulActionSet = mActionSetHandle; var actionSetArr = new VRActiveActionSet_t[1] { actionSet }; // But I cannot get the size of an array so I supply the one for the set inside the array. // No really sure what I am actually supposed to do here (or above). var errorUAS = OpenVR.Input.UpdateActionState(actionSetArr, Utils.SizeOf(actionSet)); if (errorUAS != EVRInputError.None) { Utils.PrintError($"UpdateActionState Error: {Enum.GetName(typeof(EVRInputError), errorUAS)}"); } // Get input actions var roles = new ETrackedControllerRole[] { ETrackedControllerRole.LeftHand, ETrackedControllerRole.RightHand }; foreach (var role in roles) { // Get device to restrict to, appears mandatory, makes sense for shared actions. uint index = OpenVR.System.GetTrackedDeviceIndexForControllerRole(role); // Load action data var action = new InputDigitalActionData_t(); // I assume this is used for boolean inputs. var size = Utils.SizeOf(action); var error = OpenVR.Input.GetDigitalActionData(mActionHandle, ref action, size, index); // Result if (error != mLastError) { mLastError = error; Utils.PrintError($"DigitalActionDataError: {Enum.GetName(typeof(EVRInputError), error)}"); } Debug.WriteLine(action.bActive + " " + action.bChanged); if (action.bChanged) { Utils.PrintInfo($"Action state changed to: {action.bState}"); } } // Restrict rate Thread.Sleep(1000 / 30); } }
public override void UpdateValue(SteamVR_Input_Sources inputSource, bool skipStateAndEventUpdates) { if (skipStateAndEventUpdates == false) { base.ResetLastStates(inputSource); } base.UpdateValue(inputSource, true); bool poseChanged = base.changed[inputSource]; int inputSourceInt = (int)inputSource; if (skipStateAndEventUpdates == false) { changed[inputSource] = false; for (int boneIndex = 0; boneIndex < numBones; boneIndex++) { lastBonePositions[inputSourceInt][boneIndex] = bonePositions[inputSourceInt][boneIndex]; lastBoneRotations[inputSourceInt][boneIndex] = boneRotations[inputSourceInt][boneIndex]; } } EVRInputError err = OpenVR.Input.GetSkeletalActionData(handle, ref tempSkeletonActionData, skeletonActionData_size, SteamVR_Input_Source.GetHandle(inputSource)); if (err != EVRInputError.None) { // Debug.LogError("GetSkeletalActionData error (" + fullPath + "): " + err.ToString() + " handle: " + handle.ToString()); active[inputSource] = false; return; } active[inputSource] = active[inputSource] && tempSkeletonActionData.bActive; //anding from the pose active state activeOrigin[inputSource] = tempSkeletonActionData.activeOrigin; if (active[inputSource]) { err = OpenVR.Input.GetSkeletalBoneData(handle, skeletalTransformSpace[inputSource], rangeOfMotion[inputSource], tempBoneTransforms, SteamVR_Input_Source.GetHandle(inputSource)); if (err != EVRInputError.None) { Debug.LogError("GetSkeletalBoneData error (" + fullPath + "): " + err.ToString() + " handle: " + handle.ToString()); } for (int boneIndex = 0; boneIndex < tempBoneTransforms.Length; boneIndex++) { // SteamVR's coordinate system is right handed, and Unity's is left handed. The FBX data has its // X axis flipped when Unity imports it, so here we need to flip the X axis as well bonePositions[inputSourceInt][boneIndex].x = -tempBoneTransforms[boneIndex].position.v0; bonePositions[inputSourceInt][boneIndex].y = tempBoneTransforms[boneIndex].position.v1; bonePositions[inputSourceInt][boneIndex].z = tempBoneTransforms[boneIndex].position.v2; boneRotations[inputSourceInt][boneIndex].x = tempBoneTransforms[boneIndex].orientation.x; boneRotations[inputSourceInt][boneIndex].y = -tempBoneTransforms[boneIndex].orientation.y; boneRotations[inputSourceInt][boneIndex].z = -tempBoneTransforms[boneIndex].orientation.z; boneRotations[inputSourceInt][boneIndex].w = tempBoneTransforms[boneIndex].orientation.w; } // Now that we're in the same handedness as Unity, rotate the root bone around the Y axis // so that forward is facing down +Z Quaternion qFixUpRot = Quaternion.AngleAxis(Mathf.PI * Mathf.Rad2Deg, Vector3.up); boneRotations[inputSourceInt][0] = qFixUpRot * boneRotations[inputSourceInt][0]; } changed[inputSource] = changed[inputSource] || poseChanged; if (skipStateAndEventUpdates == false) { for (int boneIndex = 0; boneIndex < tempBoneTransforms.Length; boneIndex++) { if (Vector3.Distance(lastBonePositions[inputSourceInt][boneIndex], bonePositions[inputSourceInt][boneIndex]) > changeTolerance) { changed[inputSource] |= true; break; } if (Mathf.Abs(Quaternion.Angle(lastBoneRotations[inputSourceInt][boneIndex], boneRotations[inputSourceInt][boneIndex])) > changeTolerance) { changed[inputSource] |= true; break; } } base.CheckAndSendEvents(inputSource); } if (changed[inputSource]) { lastChanged[inputSource] = Time.time; } if (skipStateAndEventUpdates == false) { lastRecordedActive[inputSource] = active[inputSource]; lastRecordedPoseActionData[inputSource] = poseActionData[inputSource]; } }
/// <summary><strong>[Should not be called by user code]</strong> /// Updates the data for this action and this input source. Sends related events. /// </summary> public override void UpdateValue() { lastActionData = actionData; lastActive = active; lastAxis = axis; lastDelta = delta; EVRInputError err = OpenVR.Input.GetAnalogActionData(handle, ref actionData, actionData_size, SteamVR_Input_Source.GetHandle(inputSource)); if (err != EVRInputError.None) { Debug.LogError("<b>[SteamVR]</b> GetAnalogActionData error (" + fullPath + "): " + err.ToString() + " handle: " + handle.ToString()); } updateTime = Time.realtimeSinceStartup; axis = new Vector3(actionData.x, actionData.y, actionData.z); delta = new Vector3(actionData.deltaX, actionData.deltaY, actionData.deltaZ); changed = false; if (active) { if (delta.magnitude > changeTolerance) { changed = true; changedTime = Time.realtimeSinceStartup + actionData .fUpdateTime; //fUpdateTime is the time from the time the action was called that the action changed if (onChange != null) { onChange.Invoke(vector3Action, inputSource, axis, delta); } } if (axis != Vector3.zero) { if (onAxis != null) { onAxis.Invoke(vector3Action, inputSource, axis, delta); } } if (onUpdate != null) { onUpdate.Invoke(vector3Action, inputSource, axis, delta); } } if (onActiveBindingChange != null && lastActiveBinding != activeBinding) { onActiveBindingChange.Invoke(vector3Action, inputSource, activeBinding); } if (onActiveChange != null && lastActive != active) { onActiveChange.Invoke(vector3Action, inputSource, activeBinding); } }
/// <summary> /// Checks if it can connect to OpenVR. /// </summary> /// <returns></returns> private bool AttemptOpenVRConnection(ref CVRSystem system) { system = null; EVRInitError eie = new EVRInitError(); try { system = OpenVR.Init(ref eie, EVRApplicationType.VRApplication_Background); } catch (Exception ex) { system = null; //MessageBox.Show("Err 1: " + ex.Message); } if (eie == EVRInitError.Init_NoServerForBackgroundApp) { system = null; return(true); } if (system == null) { return(false); } this._useLegacyInput = true; EVRApplicationError appError = OpenVR.Applications.AddApplicationManifest(Path.GetFullPath("./manifest/app.vrmanifest"), false); if (appError != EVRApplicationError.None) { return(true); //Will use legacy input } EVRInputError ioError = OpenVR.Input.SetActionManifestPath(Path.GetFullPath("./manifest/actions.json")); if (ioError != EVRInputError.None) { return(true); //Will use legacy input } if (!LoadAction("/actions/default/in/reset_viewport", ref this.actionResetViewport)) { return(true); //Will use legacy input } if (!LoadAction("/actions/default/in/reset_viewport_leftgrip", ref this.actionResetViewportLeftGrip)) { return(true); //Will use legacy input } if (!LoadAction("/actions/default/in/reset_viewport_rightgrip", ref this.actionResetViewportRightGrip)) { return(true); //Will use legacy input } if (OpenVR.Input.GetActionSetHandle("/actions/default", ref this.actionHandle) != EVRInputError.None) { return(true); //Will use legacy input } this._useLegacyInput = false; //Actions loaded successfully, we can use the modern input. return(true); }
/// <summary> /// Loads an action from the VR manifest. /// </summary> /// <param name="actionName"></param> /// <param name="handle"></param> /// <returns></returns> private bool LoadAction(string actionName, ref ulong handle) { EVRInputError ioError = OpenVR.Input.GetActionHandle(actionName, ref handle); return(ioError == EVRInputError.None); }