internal static unsafe void Initialize(OpenXRHmd hmd) { baseHMD = hmd; // make actions for (int i = 0; i < HAND_PATH_COUNT; i++) { for (int j = 0; j < 2; j++) { ActionCreateInfo action_info = new ActionCreateInfo() { Type = StructureType.TypeActionCreateInfo, ActionType = GetActionType((HAND_PATHS)i), }; Span <byte> aname = new Span <byte>(action_info.ActionName, 32); Span <byte> lname = new Span <byte>(action_info.LocalizedActionName, 32); string fullname = ((HAND_PATHS)i).ToString() + "H" + j.ToString() + '\0'; SilkMarshal.StringIntoSpan(fullname.ToLower(), aname); SilkMarshal.StringIntoSpan(fullname, lname); fixed(Silk.NET.OpenXR.Action *aptr = &MappedActions[j, i]) hmd.Xr.CreateAction(hmd.globalActionSet, &action_info, aptr); } } string allInputDetected = ""; // probe bindings for all profiles for (int i = 0; i < InteractionProfiles.Length; i++) { ulong profile = 0; hmd.Xr.StringToPath(hmd.Instance, InteractionProfiles[i], ref profile); List <ActionSuggestedBinding> bindings = new List <ActionSuggestedBinding>(); // for each hand... for (int hand = 0; hand < 2; hand++) { // for each path we want to bind... for (int path = 0; path < HAND_PATH_COUNT; path++) { // list all possible paths that might be valid and pick the first one List <string> possiblePaths = PathPriorities[path]; for (int pathattempt = 0; pathattempt < possiblePaths.Count; pathattempt++) { // get the hand at the start, then put in the attempt string final_path = hand == (int)TouchControllerHand.Left ? "/user/hand/left" : "/user/hand/right"; final_path += possiblePaths[pathattempt]; ulong hp_ulong = 0; hmd.Xr.StringToPath(hmd.Instance, final_path, ref hp_ulong); var suggest = new ActionSuggestedBinding() { Action = MappedActions[hand, path], Binding = hp_ulong }; if (IsPathSupported(hmd, profile, &suggest)) { // note that this controller has a touchpad/thumbstick switch ((HAND_PATHS)path) { case HAND_PATHS.ThumbstickX: HasThumbsticks.Add(profile); break; case HAND_PATHS.TrackpadX: HasTouchpads.Add(profile); break; } if (LogInputDetected) { allInputDetected += "\nGot " + final_path + " for " + InteractionProfiles[i]; } // got one! bindings.Add(suggest); break; } } } } // ok, we got all supported paths for this profile, lets do the final suggestion with all of them if (bindings.Count > 0) { ActionSuggestedBinding[] final_bindings = bindings.ToArray(); fixed(ActionSuggestedBinding *asbptr = &final_bindings[0]) { InteractionProfileSuggestedBinding suggested_bindings = new InteractionProfileSuggestedBinding() { Type = StructureType.TypeInteractionProfileSuggestedBinding, InteractionProfile = profile, CountSuggestedBindings = (uint)final_bindings.Length, SuggestedBindings = asbptr }; OpenXRHmd.CheckResult(hmd.Xr.SuggestInteractionProfileBinding(hmd.Instance, &suggested_bindings), "SuggestInteractionProfileBinding"); } } } if (LogInputDetected) { ErrorFileLogger.WriteLogToFile(allInputDetected); } }
private unsafe void Prepare() { // Create our API object for OpenXR. Xr = XR.GetApi(); Extensions.Clear(); //Extensions.Add("XR_KHR_vulkan_enable2"); Extensions.Add("XR_KHR_vulkan_enable"); Extensions.Add("XR_EXT_hp_mixed_reality_controller"); Extensions.Add("XR_HTC_vive_cosmos_controller_interaction"); Extensions.Add("XR_MSFT_hand_interaction"); Extensions.Add("XR_EXT_samsung_odyssey_controller"); uint propCount = 0; Xr.EnumerateInstanceExtensionProperties((byte *)null, 0, &propCount, null); ExtensionProperties[] props = new ExtensionProperties[propCount]; for (int i = 0; i < props.Length; i++) { props[i].Type = StructureType.TypeExtensionProperties; fixed(ExtensionProperties *pptr = &props[0]) Xr.EnumerateInstanceExtensionProperties((byte *)null, propCount, ref propCount, pptr); List <string> AvailableExtensions = new List <string>(); for (int i = 0; i < props.Length; i++) { fixed(void *nptr = props[i].ExtensionName) AvailableExtensions.Add(Marshal.PtrToStringAnsi(new System.IntPtr(nptr))); } for (int i = 0; i < Extensions.Count; i++) { if (AvailableExtensions.Contains(Extensions[i]) == false) { Extensions.RemoveAt(i); i--; } } InstanceCreateInfo instanceCreateInfo; var appInfo = new ApplicationInfo() { ApiVersion = new Version64(1, 0, 9) }; // We've got to marshal our strings and put them into global, immovable memory. To do that, we use // SilkMarshal. Span <byte> appName = new Span <byte>(appInfo.ApplicationName, 128); Span <byte> engName = new Span <byte>(appInfo.EngineName, 128); SilkMarshal.StringIntoSpan(System.AppDomain.CurrentDomain.FriendlyName, appName); SilkMarshal.StringIntoSpan("FocusEngine", engName); var requestedExtensions = SilkMarshal.StringArrayToPtr(Extensions); instanceCreateInfo = new InstanceCreateInfo ( applicationInfo: appInfo, enabledExtensionCount: (uint)Extensions.Count, enabledExtensionNames: (byte **)requestedExtensions ); // Now we're ready to make our instance! CheckResult(Xr.CreateInstance(in instanceCreateInfo, ref Instance), "CreateInstance"); // For our benefit, let's log some information about the instance we've just created. // skip this, as it crashes on Oculus runtime and is not needed /*InstanceProperties properties = new(); * CheckResult(Xr.GetInstanceProperties(Instance, ref properties), "GetInstanceProperties"); * * var runtimeName = SilkMarshal.PtrToString((nint)properties.RuntimeName); * var runtimeVersion = ((Version)(Version64)properties.RuntimeVersion).ToString(3); * * Console.WriteLine($"[INFO] Application: Using OpenXR Runtime \"{runtimeName}\" v{runtimeVersion}");*/ // We're creating a head-mounted-display (HMD, i.e. a VR headset) example, so we ask for a runtime which // supports that form factor. The response we get is a ulong that is the System ID. var getInfo = new SystemGetInfo(formFactor: FormFactor.HeadMountedDisplay); CheckResult(Xr.GetSystem(Instance, in getInfo, ref system_id), "GetSystem"); }