diff --git a/plugin_OpenVR/Assets/Strings/en.json b/plugin_OpenVR/Assets/Strings/en.json index ff5becb..919574f 100644 --- a/plugin_OpenVR/Assets/Strings/en.json +++ b/plugin_OpenVR/Assets/Strings/en.json @@ -1,186 +1,226 @@ { "language": "en", - "messages": [ - { - "id": "/GeneralPage/Tips/TrackingFreeze/Buttons/Index", - "translation": "B, Grip and Trigger" - }, - { - "id": "/GeneralPage/Tips/TrackingFreeze/Buttons/Oculus", - "translation": "X, Grip and Trigger" - }, - { - "id": "/GeneralPage/Tips/TrackingFreeze/Buttons/VIVE", - "translation": "the Touchpad, Grip and Trigger" - }, - { - "id": "/GeneralPage/Tips/TrackingFreeze/Buttons/WMR", - "translation": "the Menu Button, Grip and Trigger" - }, - { - "id": "/GeneralPage/Tips/TrackingFreeze/Footer", - "translation": "This binding can be changed within SteamVR input settings." - }, - { - "id": "/GeneralPage/Tips/TrackingFreeze/Header", - "translation": "You can also toggle tracker freeze while in VR! \nPress {0} on your left controller." - }, - { - "id": "/SettingsPage/Buttons/ReManifest", - "translation": "Reinstall SteamVR manifests" - }, - { - "id": "/SettingsPage/Buttons/ReRegister", - "translation": "Re-register SteamVR driver entry" - }, - { - "id": "/SettingsPage/ReManifest/Error/NotFound", - "translation": "Amethyst vr manifest couldn't be installed.\nIs it even somewhere around here...?" - }, - { - "id": "/SettingsPage/ReManifest/Error/Other", - "translation": "Amethyst vr manifest couldn't be installed.\nPlease check SteamVR logs and consider reporting it." - }, - { - "id": "/SettingsPage/Tips/FlipToggle/Buttons/Index", - "translation": "B, Grip and Trigger" - }, - { - "id": "/SettingsPage/Tips/FlipToggle/Buttons/Oculus", - "translation": "A, Grip and Trigger" - }, - { - "id": "/SettingsPage/Tips/FlipToggle/Buttons/VIVE", - "translation": "the Touchpad, Grip and Trigger" - }, - { - "id": "/SettingsPage/Tips/FlipToggle/Buttons/WMR", - "translation": "the Menu Button, Grip and Trigger" - }, - { - "id": "/SettingsPage/Tips/FlipToggle/Footer", - "translation": "This binding can be changed within SteamVR input settings." - }, - { - "id": "/SettingsPage/Tips/FlipToggle/Header", - "translation": "You can also toggle skeleton flip while in VR! \nPress {0} on your right controller." - }, - { - "id": "/ServerStatuses/WTF", - "translation": "COULD NOT CHECK STATUS (ᗜˬᗜ)\nE_WTF\nSomething's fucked a really big time." - }, - { - "id": "/ServerStatuses/Success", - "translation": "Success! (Code {0})\nI_OK\nEverything's good!" - }, - { - "id": "/ServerStatuses/OpenVRError", - "translation": "OPENVR INIT ERROR (Code {0})\nE_OVRINIT_ERROR\nCheck if SteamVR is running, and your VR headset is connected properly to it, and click 'Refresh' to check again. Additionally, you can restart SteamVR and check its logs.", - "translatorComment": "[Refresh] as in the refresh button, /DevicesPage/Buttons/Reconnect @Amethyst, make sure it's the same string!" - }, - { - "id": "/ServerStatuses/OpenVRElevatedError", - "translation": "OPENVR ELEVATED (Code {0})\nE_VRSERVER_RUNAS\nAmethyst can't communicate with the OpenVR API if SteamVR is running with administrator privileges, please start it normally. Optionally, you can run Amethyst as administrator too, to suppress this specific error." - }, - { - "id": "/ServerStatuses/AmethystElevatedError", - "translation": "AMETHYST ELEVATED (Code {0})\nE_AMETHYST_RUNAS\nAmethyst is running with admin rights, please start it normally. Amethyst can't communicate with the OpenVR API whenever running with administrator privileges." - }, - { - "id": "/ServerStatuses/IVRInputError", - "translation": "OPENVR ACTIONS ERROR (Code {0})\nE_IVRINPUT_ERROR\nCheck if SteamVR is working properly, and your VR controllers are present in it. Additionally, you can restart SteamVR and check its logs." - }, - { - "id": "/ServerStatuses/ConnectionError", - "translation": "SERVER CONNECTION ERROR (Code {0})\nE_CONNECTION_ERROR\nCheck SteamVR add-ons (NOT overlays) and enable Amethyst. You can also try re-registering the driver entry from SteamVR service settings within Amethyst." - }, - { - "id": "/ServerStatuses/RPCChannelFailure", - "translation": "RPC CHANNEL FAILURE (Code {0})\nE_RPC_CHAN_FAILURE\nCould not connect to the the RPC channel because it was null. Please restart, check logs and write to us on Discord." - }, - { - "id": "/ServerStatuses/Exception", - "translation": "EXCEPTION WHILE CHECKING (Code {0})\nE_EXCEPTION_WHILE_CHECKING\nThere was an exception starting the RPC server: {1}" - }, - { - "id": "/ServerStatuses/ServerFailure", - "translation": "FATAL SERVER FAILURE (Code {0})\nE_FATAL_SERVER_FAILURE\nPlease restart, check logs and write to us on Discord." - }, - { - "id": "/CrashHandler/ReRegister/DriverNotFound", - "translation": "The Amethyst Driver folder wasn't found.\nIs it even somewhere around here...?" - }, - { - "id": "/CrashHandler/ReRegister/ExistingDrivers/Content", - "translation": "One or more drivers named 'Amethyst'\nalready exist, remove them now?" - }, - { - "id": "/CrashHandler/ReRegister/ExistingDrivers/Content_K2EX", - "translation": "A copy of the K2EX SteamVR driver was found.\nIt is incompatible with Amethyst and needs to be removed.\nDo it now?" - }, - { - "id": "/CrashHandler/ReRegister/ExistingDrivers/PrimaryButton", - "translation": "Remove" - }, - { - "id": "/CrashHandler/ReRegister/ExistingDrivers/PrimaryButton_K2EX", - "translation": "Remove" - }, - { - "id": "/CrashHandler/ReRegister/ExistingDrivers/SecondaryButton", - "translation": "Abort" - }, - { - "id": "/CrashHandler/ReRegister/ExistingDrivers/SecondaryButton_K2EX", - "translation": "Abort" - }, - { - "id": "/CrashHandler/ReRegister/FatalRegisterException", - "translation": "Couldn't register Amethyst Driver,\na fatal exception occurred." - }, - { - "id": "/CrashHandler/ReRegister/FatalRemoveException", - "translation": "Couldn't remove Amethyst Driver,\na fatal exception occurred." - }, - { - "id": "/CrashHandler/ReRegister/FatalRemoveException_K2EX", - "translation": "Couldn't remove the K2EX SteamVR driver,\na fatal exception occurred." - }, - { - "id": "/CrashHandler/ReRegister/Elevation", - "translation": "Amethyst won't be able to kill the SteamVR process\nbecause it's running with administrator privileges.\nPlease force close SteamVR manually and try again." - }, - { - "id": "/CrashHandler/ReRegister/Finished", - "translation": "You're good to go!" - }, - { - "id": "/CrashHandler/ReRegister/KillSteamVR/Content", - "translation": "SteamVR needs to be shut down\nto register properly, kill it now?" - }, - { - "id": "/CrashHandler/ReRegister/KillSteamVR/PrimaryButton", - "translation": "Kill" - }, - { - "id": "/CrashHandler/ReRegister/KillSteamVR/SecondaryButton", - "translation": "Abort" - }, - { - "id": "/CrashHandler/ReRegister/OpenVRPathsError", - "translation": "OpenVRPaths couldn't be read!\nMake sure it's not corrupted,\nand run SteamVR at least once." - }, - { - "id": "/CrashHandler/ReRegister/OpenVRPathsWriteError", - "translation": "Couldn't register Amethyst Driver,\nopenvrpaths write error." - }, - { - "id": "/CrashHandler/ReRegister/SteamVRNotFound", - "translation": "SteamVR couldn't be found,\nmake sure it's installed." - }, - { - "id": "/Dependencies/Driver", - "translation": "OpenVR Driver" - } - ] + "messages": [ + { + "id": "/GeneralPage/Tips/TrackingFreeze/Buttons/Index", + "translation": "B, Grip and Trigger" + }, + { + "id": "/GeneralPage/Tips/TrackingFreeze/Buttons/Oculus", + "translation": "X, Grip and Trigger" + }, + { + "id": "/GeneralPage/Tips/TrackingFreeze/Buttons/VIVE", + "translation": "the Touchpad, Grip and Trigger" + }, + { + "id": "/GeneralPage/Tips/TrackingFreeze/Buttons/WMR", + "translation": "the Menu Button, Grip and Trigger" + }, + { + "id": "/GeneralPage/Tips/TrackingFreeze/Footer", + "translation": "This binding can be changed within SteamVR input settings." + }, + { + "id": "/GeneralPage/Tips/TrackingFreeze/Header", + "translation": "You can also toggle tracker freeze while in VR! \nPress {0} on your left controller." + }, + { + "id": "/SettingsPage/Buttons/ReManifest", + "translation": "Reinstall SteamVR manifests" + }, + { + "id": "/SettingsPage/Buttons/ReRegister", + "translation": "Re-register SteamVR driver entry" + }, + { + "id": "/SettingsPage/ReManifest/Error/NotFound", + "translation": "Amethyst vr manifest couldn't be installed.\nIs it even somewhere around here...?" + }, + { + "id": "/SettingsPage/ReManifest/Error/Other", + "translation": "Amethyst vr manifest couldn't be installed.\nPlease check SteamVR logs and consider reporting it." + }, + { + "id": "/SettingsPage/Tips/FlipToggle/Buttons/Index", + "translation": "B, Grip and Trigger" + }, + { + "id": "/SettingsPage/Tips/FlipToggle/Buttons/Oculus", + "translation": "A, Grip and Trigger" + }, + { + "id": "/SettingsPage/Tips/FlipToggle/Buttons/VIVE", + "translation": "the Touchpad, Grip and Trigger" + }, + { + "id": "/SettingsPage/Tips/FlipToggle/Buttons/WMR", + "translation": "the Menu Button, Grip and Trigger" + }, + { + "id": "/SettingsPage/Tips/FlipToggle/Footer", + "translation": "This binding can be changed within SteamVR input settings." + }, + { + "id": "/SettingsPage/Tips/FlipToggle/Header", + "translation": "You can also toggle skeleton flip while in VR! \nPress {0} on your right controller." + }, + { + "id": "/ServerStatuses/WTF", + "translation": "COULD NOT CHECK STATUS (ᗜˬᗜ)\nE_WTF\nSomething's fucked a really big time." + }, + { + "id": "/ServerStatuses/Success", + "translation": "Success! (Code {0})\nI_OK\nEverything's good!" + }, + { + "id": "/ServerStatuses/OpenVRError", + "translation": "OPENVR INIT ERROR (Code {0})\nE_OVRINIT_ERROR\nCheck if SteamVR is running, and your VR headset is connected properly to it, and click 'Refresh' to check again. Additionally, you can restart SteamVR and check its logs.", + "translatorComment": "[Refresh] as in the refresh button, /DevicesPage/Buttons/Reconnect @Amethyst, make sure it's the same string!" + }, + { + "id": "/ServerStatuses/OpenVRElevatedError", + "translation": "OPENVR ELEVATED (Code {0})\nE_VRSERVER_RUNAS\nAmethyst can't communicate with the OpenVR API if SteamVR is running with administrator privileges, please start it normally. Optionally, you can run Amethyst as administrator too, to suppress this specific error." + }, + { + "id": "/ServerStatuses/AmethystElevatedError", + "translation": "AMETHYST ELEVATED (Code {0})\nE_AMETHYST_RUNAS\nAmethyst is running with admin rights, please start it normally. Amethyst can't communicate with the OpenVR API whenever running with administrator privileges." + }, + { + "id": "/ServerStatuses/IVRInputError", + "translation": "OPENVR ACTIONS ERROR (Code {0})\nE_IVRINPUT_ERROR\nCheck if SteamVR is working properly, and your VR controllers are present in it. Additionally, you can restart SteamVR and check its logs." + }, + { + "id": "/ServerStatuses/ConnectionError", + "translation": "SERVER CONNECTION ERROR (Code {0})\nE_CONNECTION_ERROR\nCheck SteamVR add-ons (NOT overlays) and enable Amethyst. You can also try re-registering the driver entry from SteamVR service settings within Amethyst." + }, + { + "id": "/ServerStatuses/RPCChannelFailure", + "translation": "RPC CHANNEL FAILURE (Code {0})\nE_RPC_CHAN_FAILURE\nCould not connect to the the RPC channel because it was null. Please restart, check logs and write to us on Discord." + }, + { + "id": "/ServerStatuses/Exception", + "translation": "EXCEPTION WHILE CHECKING (Code {0})\nE_EXCEPTION_WHILE_CHECKING\nThere was an exception starting the RPC server: {1}" + }, + { + "id": "/ServerStatuses/ServerFailure", + "translation": "FATAL SERVER FAILURE (Code {0})\nE_FATAL_SERVER_FAILURE\nPlease restart, check logs and write to us on Discord." + }, + { + "id": "/CrashHandler/ReRegister/DriverNotFound", + "translation": "The Amethyst Driver folder wasn't found.\nIs it even somewhere around here...?" + }, + { + "id": "/CrashHandler/ReRegister/ExistingDrivers/Content", + "translation": "One or more drivers named 'Amethyst'\nalready exist, remove them now?" + }, + { + "id": "/CrashHandler/ReRegister/ExistingDrivers/Content_K2EX", + "translation": "A copy of the K2EX SteamVR driver was found.\nIt is incompatible with Amethyst and needs to be removed.\nDo it now?" + }, + { + "id": "/CrashHandler/ReRegister/ExistingDrivers/PrimaryButton", + "translation": "Remove" + }, + { + "id": "/CrashHandler/ReRegister/ExistingDrivers/PrimaryButton_K2EX", + "translation": "Remove" + }, + { + "id": "/CrashHandler/ReRegister/ExistingDrivers/SecondaryButton", + "translation": "Abort" + }, + { + "id": "/CrashHandler/ReRegister/ExistingDrivers/SecondaryButton_K2EX", + "translation": "Abort" + }, + { + "id": "/CrashHandler/ReRegister/FatalRegisterException", + "translation": "Couldn't register Amethyst Driver,\na fatal exception occurred." + }, + { + "id": "/CrashHandler/ReRegister/FatalRemoveException", + "translation": "Couldn't remove Amethyst Driver,\na fatal exception occurred." + }, + { + "id": "/CrashHandler/ReRegister/FatalRemoveException_K2EX", + "translation": "Couldn't remove the K2EX SteamVR driver,\na fatal exception occurred." + }, + { + "id": "/CrashHandler/ReRegister/Elevation", + "translation": "Amethyst won't be able to kill the SteamVR process\nbecause it's running with administrator privileges.\nPlease force close SteamVR manually and try again." + }, + { + "id": "/CrashHandler/ReRegister/Finished", + "translation": "You're good to go!" + }, + { + "id": "/CrashHandler/ReRegister/KillSteamVR/Content", + "translation": "SteamVR needs to be shut down\nto register properly, kill it now?" + }, + { + "id": "/CrashHandler/ReRegister/KillSteamVR/PrimaryButton", + "translation": "Kill" + }, + { + "id": "/CrashHandler/ReRegister/KillSteamVR/SecondaryButton", + "translation": "Abort" + }, + { + "id": "/CrashHandler/ReRegister/OpenVRPathsError", + "translation": "OpenVRPaths couldn't be read!\nMake sure it's not corrupted,\nand run SteamVR at least once." + }, + { + "id": "/CrashHandler/ReRegister/OpenVRPathsWriteError", + "translation": "Couldn't register Amethyst Driver,\nopenvrpaths write error." + }, + { + "id": "/CrashHandler/ReRegister/SteamVRNotFound", + "translation": "SteamVR couldn't be found,\nmake sure it's installed." + }, + { + "id": "/Dependencies/Driver", + "translation": "OpenVR Driver" + }, + { + "id": "/InputActions/Buttons/View", + "translation": "Manage custom input actions" + }, + { + "id": "/InputActions/Picker/Options/New", + "translation": "New action" + }, + { + "id": "/SettingsPage/Placeholders/NewAction", + "translation": "New Input Action" + }, + { + "id": "/InputActions/Buttons/Test", + "translation": "Test" + }, + { + "id": "/InputActions/Buttons/Remove", + "translation": "Remove" + }, + { + "id": "/InputActions/Buttons/Add", + "translation": "Add" + }, + { + "id": "/InputActions/Title/NoSelection", + "translation": "No selection" + }, + { + "id": "/InputActions/Picker/NoSelection", + "translation": "Click on one of the registered input actions to preview it.\nYou'll be able to edit its code, test, or delete forever." + }, + { + "id": "/InputActions/Code/Input", + "translation": "Write your own handler for this input action using C#, and click 'Add' to register the action in SteamVR. Then, go to SteamVR Input settings and bind your chord to your own input.\n\nYou can use the chord data by accessing the 'data' global variable. It's also possible to evaluate the script in Amethyst's context by adding \"hosted\" at the beginning.\n\nFor example, to despawn the trackers:\n{\n hosted\n Interfacing.AppTrackersInitialized = false;\n}\n\nFor more info, please refer to docs.k2vr.tech and learn.microsoft.com" + }, + { + "id": "/InputActions/Code/Test", + "translation": "The output from code testing will appear here..." + } + ] } \ No newline at end of file diff --git a/plugin_OpenVR/EvrInput.cs b/plugin_OpenVR/EvrInput.cs index cecc92c..080096f 100644 --- a/plugin_OpenVR/EvrInput.cs +++ b/plugin_OpenVR/EvrInput.cs @@ -44,7 +44,7 @@ public bool IsValid ]; [JsonProperty("actions")] - public List Actions { get; set; } = + public List Actions { get; set; } = [ new("/actions/default/in/TrackerFreeze", "boolean", "optional"), new("/actions/default/in/FlipToggle", "boolean", "optional"), @@ -82,61 +82,83 @@ public bool IsValid } ]; - public Action this[string path] => Actions.FirstOrDefault(x => x.Name == path); + public InputAction this[string path] => Actions.FirstOrDefault(x => x.Name == path); public class DefaultBindings(string controllerType = "", string path = "") { [JsonProperty("controller_type")] public string ControllerType { get; set; } = controllerType; [JsonProperty("binding_url")] public string Binding { get; set; } = path; } +} + +public class InputAction(string name = "", string type = "boolean", string requirement = null) +{ + [JsonProperty("name")] public string Name { get; set; } = name; + [JsonProperty("type")] public string Type { get; set; } = type; + + [JsonProperty("requirement", NullValueHandling = NullValueHandling.Ignore)] + public string Requirement { get; set; } = requirement; + + [JsonIgnore] public static IAmethystHost Host => SteamVR.HostStatic; + [JsonIgnore] private ulong Handle { get; set; } + [JsonIgnore] public bool Data => DataDigital.bState; + [JsonIgnore] public Vector2 State => new(DataAnalog.x, DataAnalog.y); + [JsonIgnore] private InputDigitalActionData_t DataDigital { get; set; } + [JsonIgnore] private InputAnalogActionData_t DataAnalog { get; set; } + [JsonIgnore] public bool Valid => Host is not null && !string.IsNullOrEmpty(Name) && !string.IsNullOrEmpty(Type); + [JsonIgnore] public bool Custom => new ActionsManifest().Actions.All(x => x.Name != Name); - public class Action(string name = "", string type = "boolean", string requirement = null) + [JsonIgnore] + public string Code { - [JsonProperty("name")] public string Name { get; set; } = name; - [JsonProperty("type")] public string Type { get; set; } = type; - - [JsonProperty("requirement", NullValueHandling = NullValueHandling.Ignore)] - public string Requirement { get; set; } = requirement; - - [JsonIgnore] public static IAmethystHost Host => SteamVR.HostStatic; - [JsonIgnore] private ulong Handle { get; set; } - [JsonIgnore] public bool Data => DataDigital.bState; - [JsonIgnore] public Vector2 State => new(DataAnalog.x, DataAnalog.y); - [JsonIgnore] private InputDigitalActionData_t DataDigital { get; set; } - [JsonIgnore] private InputAnalogActionData_t DataAnalog { get; set; } - [JsonIgnore] public bool Valid => Host is not null && !string.IsNullOrEmpty(Name) && !string.IsNullOrEmpty(Type); - - [JsonIgnore] - public string Code - { - get => Host?.PluginSettings.GetSetting(Handle, string.Empty); - set => Host?.PluginSettings.SetSetting(Handle, value); - } + get => Host?.PluginSettings.GetSetting(Name, string.Empty); + set => Host?.PluginSettings.SetSetting(Name, value); + } - public async Task Invoke(object data) - { - // Exit with a custom message to be shown by the crash handler - Host?.Log($"Trying to evaluate expression \"{Code}\" for data \"{data}\"..."); + public async Task Invoke(object data) + { + // Exit with a custom message to be shown by the crash handler + Host?.Log($"Trying to evaluate expression \"{Code}\" for data \"{data}\"..."); - try - { - return (await CSharpScript.EvaluateAsync($"object data = {data};{Code.Trim()}", - ScriptOptions.Default //.WithImports("Amethyst.Classes") + try + { + return Host is not null && Code.StartsWith("hosted") + ? ((dynamic)Host).Eval($"{(data is not null ? $"object data = {data};" : "")}" + + $"{Code.Replace("hosted", string.Empty).Trim()}") + : (await CSharpScript.EvaluateAsync( + $"{(data is not null ? $"object data = {data};" : "")}" + + $"{Code.Trim()}", ScriptOptions.Default.WithImports("plugin_OpenVR") .WithReferences(typeof(IAmethystHost).Assembly) .WithReferences(typeof(SteamVR).Assembly) .AddImports("System.Linq"))).ToString(); - } - catch (Exception ex) - { - return $"Evaluation error: '{ex}'"; - } } + catch (Exception ex) + { + return ex.Message; + } + } - public void SetName(ActionsManifest json, string name) + public string NameLocalized + { + get + { + var json = SteamVR.VrInputStatic?.RegisteredActions; + if (json is null) return null; + + return json.Localization + .FirstOrDefault(x => x.TryGetValue("language_tag", out var language) && + language.Contains(Host?.LanguageCode ?? "en"), + json.Localization.FirstOrDefault()) + ?.TryGetValue(Name ?? string.Empty, out var name) ?? false + ? name + : Name ?? string.Empty; + } + set { + var json = SteamVR.VrInputStatic?.RegisteredActions; if (json is null) return; - json.Localization ??= new ActionsManifest().Localization; + json.Localization ??= new ActionsManifest().Localization; var languageRoot = json.Localization .FirstOrDefault(x => x.TryGetValue("language_tag", out var language) && language.Contains(Host?.LanguageCode ?? "en"), null); @@ -152,74 +174,63 @@ public void SetName(ActionsManifest json, string name) } if (languageRoot is null) return; // Error - languageRoot[Name] = name; - } - - public string GetName(ActionsManifest json) - { - return json?.Localization - .FirstOrDefault(x => x.TryGetValue("language_tag", out var language) && - language.Contains(Host?.LanguageCode ?? "en"), - json.Localization.FirstOrDefault()) - ?.TryGetValue(Name ?? string.Empty, out var name) ?? false - ? name - : Name ?? string.Empty; + languageRoot[Name] = value; } + } - public EVRInputError Register() - { - var pHandle = Handle; - var error = OpenVR.Input.GetActionHandle(Name, ref pHandle); + public EVRInputError Register() + { + var pHandle = Handle; + var error = OpenVR.Input.GetActionHandle(Name, ref pHandle); - Handle = pHandle; - return error; - } + Handle = pHandle; + return error; + } - public bool UpdateState() + public bool UpdateState() + { + var result = Type switch { - var result = Type switch - { - "boolean" => GetDigitalState(), - "vector2" => GetAnalogState(), - _ => false - }; + "boolean" => GetDigitalState(), + "vector2" => GetAnalogState(), + _ => false + }; - return result || Requirement is "optional"; - } + return result || Requirement is "optional"; + } - private bool GetDigitalState() - { - if (!SteamVR.Initialized || OpenVR.Input is null) return false; // Sanity check + private bool GetDigitalState() + { + if (!SteamVR.Initialized || OpenVR.Input is null) return false; // Sanity check - var pData = DataDigital; - var error = OpenVR.Input.GetDigitalActionData( - Handle, ref pData, - (uint)Marshal.SizeOf(), - OpenVR.k_ulInvalidInputValueHandle); + var pData = DataDigital; + var error = OpenVR.Input.GetDigitalActionData( + Handle, ref pData, + (uint)Marshal.SizeOf(), + OpenVR.k_ulInvalidInputValueHandle); - DataDigital = pData; + DataDigital = pData; - if (error == EVRInputError.None) return DataDigital.bState; - Host?.Log($"GetDigitalActionData call error: {error}", LogSeverity.Error); - return false; - } + if (error == EVRInputError.None) return DataDigital.bState; + Host?.Log($"GetDigitalActionData call error: {error}", LogSeverity.Error); + return false; + } - private bool GetAnalogState() - { - if (!SteamVR.Initialized || OpenVR.Input is null) return false; // Sanity check + private bool GetAnalogState() + { + if (!SteamVR.Initialized || OpenVR.Input is null) return false; // Sanity check - var pData = DataAnalog; - var error = OpenVR.Input.GetAnalogActionData( - Handle, ref pData, - (uint)Marshal.SizeOf(), - OpenVR.k_ulInvalidInputValueHandle); + var pData = DataAnalog; + var error = OpenVR.Input.GetAnalogActionData( + Handle, ref pData, + (uint)Marshal.SizeOf(), + OpenVR.k_ulInvalidInputValueHandle); - DataAnalog = pData; + DataAnalog = pData; - if (error == EVRInputError.None) return DataDigital.bState; - Host?.Log($"GetAnalogActionData call error: {error}", LogSeverity.Error); - return false; - } + if (error == EVRInputError.None) return DataDigital.bState; + Host?.Log($"GetAnalogActionData call error: {error}", LogSeverity.Error); + return false; } } @@ -250,6 +261,26 @@ private static (uint Left, uint Right) VrControllerIndexes => ( : OpenVR.k_unTrackedDeviceIndexInvalid ); + public void SaveSettings() + { + var manifestPath = Path.Join(PackageUtils.GetAmethystAppDataPath(), "Amethyst", "actions.json"); + File.WriteAllText(manifestPath, JsonConvert.SerializeObject(RegisteredActions, Formatting.Indented)); + } + + public string ReadSettings() + { + var manifestPath = Path.Join(PackageUtils.GetAmethystAppDataPath(), "Amethyst", "actions.json"); + RegisteredActions = File.Exists(manifestPath) + ? JsonConvert.DeserializeObject( + File.ReadAllText(manifestPath)) ?? new ActionsManifest(true) + : new ActionsManifest(true); + + if (RegisteredActions.WasNull || !RegisteredActions.IsValid) // Re-generate the action manifest if it's not found + File.WriteAllText(manifestPath, JsonConvert.SerializeObject(RegisteredActions, Formatting.Indented)); + + return manifestPath; + } + // Note: SteamVR must be initialized beforehand. // Preferred type is (vr::VRApplication_Scene) public bool InitInputActions() @@ -258,15 +289,7 @@ public bool InitInputActions() try { - var manifestPath = Path.Join(PackageUtils.GetAmethystAppDataPath(), "Amethyst", "actions.json"); - RegisteredActions = File.Exists(manifestPath) - ? JsonConvert.DeserializeObject( - File.ReadAllText(manifestPath)) ?? new ActionsManifest(true) - : new ActionsManifest(true); - - if (RegisteredActions.WasNull || !RegisteredActions.IsValid) // Re-generate the action manifest if it's not found - File.WriteAllText(manifestPath, JsonConvert.SerializeObject(RegisteredActions, Formatting.Indented)); - + var manifestPath = ReadSettings(); if (!File.Exists(manifestPath)) { Host.Log("Action manifest was not found in the program " + diff --git a/plugin_OpenVR/OpenVR.cs b/plugin_OpenVR/OpenVR.cs index 203a8a3..c106907 100644 --- a/plugin_OpenVR/OpenVR.cs +++ b/plugin_OpenVR/OpenVR.cs @@ -41,6 +41,7 @@ public class SteamVR : IServiceEndpoint private ulong _vrOverlayHandle = OpenVR.k_ulOverlayHandleInvalid; public SteamEvrInput VrInput { get; set; } + public static SteamEvrInput VrInputStatic { get; set; } public static bool Initialized { get; private set; } private static object InitLock { get; } = new(); @@ -216,13 +217,15 @@ public string TrackingSystemName public void OnLoad() { VrInput ??= new SteamEvrInput(Host); + VrInputStatic = VrInput; + HostStatic = Host; + Settings ??= new SettingsPage { DataParent = this, Host = Host }; InterfaceRoot = new Page { Content = Settings }; - HostStatic = Host; PluginLoaded = true; } diff --git a/plugin_OpenVR/Pages/SettingsPage.xaml b/plugin_OpenVR/Pages/SettingsPage.xaml index b4cb572..a3d1046 100644 --- a/plugin_OpenVR/Pages/SettingsPage.xaml +++ b/plugin_OpenVR/Pages/SettingsPage.xaml @@ -2,12 +2,13 @@ + xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" + xmlns:pluginOpenVr="using:plugin_OpenVR"> -