using System.Collections; using System.Collections.Generic; using UnityEngine; using UnityEditor; using UnityEditor.PackageManager.Requests; using UnityEditor.PackageManager; using System; using System.IO; namespace Ximmerse.XR { /// /// Ximmerse SDK XR Setup binding. /// public static class SDKInputBindingSetup { [InitializeOnLoadMethod] static void AutoSetup() { GenerateXimmerseXRControllerInputBinding(); } #region Internal Process /// /// The default input binding required to access ximmerse ring controller event. /// static List axisList = new List { #region Default Unity bindings new InputAxis() { name = "Horizontal", descriptiveName = "Horizontal", dead = 0.19f, axis = 4, type = 0, }, new InputAxis() { name = "Vertical", descriptiveName = "Vertical", dead = 0.19f, axis = 5, type = 0, }, new InputAxis() { name = "Fire1", positiveButton = "left ctrl", altPositiveButton = "mouse 0", dead = 0.19f, axis = 5, type = 0, }, new InputAxis() { name = "Fire2", positiveButton = "left alt", altPositiveButton = "mouse 1", dead = 0.19f, axis = 5, type = 0, }, new InputAxis() { name = "Fire3", positiveButton = "left shift", altPositiveButton = "mouse 2", dead = 0.19f, axis = 5, type = 0, }, new InputAxis() { name = "Jump", positiveButton = "space", dead = 0.19f, axis = 5, type = 0, }, new InputAxis() { name = "Mouse X", dead = 0, sensitivity = 0.1f, axis = 1, type = 1, }, new InputAxis() { name = "Mouse Y", dead = 0, sensitivity = 0.1f, axis = 2, type = 1, }, new InputAxis() { name = "Mouse ScrollWheel", dead = 0, sensitivity = 0.1f, axis = 3, type = 1, }, new InputAxis() { name = "Submit", descriptiveName = "Submit", positiveButton = "joystick button 0", gravity = 0.0f, dead = 0.0f, sensitivity = 0.1f, type = 0, }, new InputAxis() { name = "Cancel", descriptiveName = "Cancel", positiveButton = "joystick button 1", gravity = 0.0f, dead = 0.0f, sensitivity = 0.1f, type = 0, }, #endregion #region LeftHand new InputAxis() { name = "XRI_Left_Primary2DAxis_Vertical", descriptiveName = "Device joystick/touchpad horizontal motion", dead = 0.19f, axis = 2, type = 2, }, new InputAxis() { name = "XRI_Left_Primary2DAxis_Horizontal", descriptiveName = "Device joystick/touchpad horizontal motion", dead = 0.19f, axis = 1, type = 2, }, new InputAxis() { name = "XRI_Left_Trigger", descriptiveName = "Device trigger axis", axis = 9, type = 2, }, new InputAxis() { name = "XRI_Left_Grip", descriptiveName = "Device grip axis", axis = 11, type = 2, }, new InputAxis() { name = "XRI_Left_IndexTouch", descriptiveName = "Device index finger proximity touch axis.", dead = 0.19f, axis = 13, type = 2, }, // Button Data new InputAxis() { name = "XRI_Left_PrimaryButton", descriptiveName = "Device primary button", positiveButton = "joystick button 2", gravity = 1000.0f, sensitivity = 1000.0f, type = 0, }, new InputAxis() { name = "XRI_Left_SecondaryButton", descriptiveName = "Device secondary button", positiveButton = "joystick button 3", gravity = 1000.0f, sensitivity = 1000.0f, type = 0, }, new InputAxis() { name = "XRI_Left_GripButton", descriptiveName = "Device grip button", positiveButton = "joystick button 4", gravity = 0.0f, dead = 0.0f, sensitivity = 0.1f, type = 0, }, new InputAxis() { name = "XRI_Left_TriggerButton", descriptiveName = "Device trigger button", positiveButton = "joystick button 14", gravity = 0.0f, dead = 0.0f, sensitivity = 0.1f, type = 0, }, new InputAxis() { name = "XRI_Left_MenuButton", descriptiveName = "Device menu button", positiveButton = "joystick button 6", gravity = 1000.0f, sensitivity = 1000.0f, type = 0, }, new InputAxis() { name = "XRI_Left_Primary2DAxisClick", descriptiveName = "Device stick/touchpad click", positiveButton = "joystick button 8", gravity = 0.0f, dead = 0.0f, sensitivity = 0.1f, type = 0, }, new InputAxis() { name = "XRI_Left_Primary2DAxisTouch", descriptiveName = "Device stick/touchpad touch", positiveButton = "joystick button 16", gravity = 0.0f, dead = 0.0f, sensitivity = 0.1f, type = 0, }, new InputAxis() { name = "XRI_Left_Thumbrest", descriptiveName = "Device thumbrest", positiveButton = "joystick button 18", gravity = 0.0f, dead = 0.0f, sensitivity = 0.1f, type = 0, }, #endregion #region RightHand //###################################################################################################################################### // Right Hand //###################################################################################################################################### new InputAxis() { name = "XRI_Right_Primary2DAxis_Vertical", descriptiveName = "Device joystick/touchpad horizontal motion", dead = 0.19f, axis = 5, type = 2, }, new InputAxis() { name = "XRI_Right_Primary2DAxis_Horizontal", descriptiveName = "Device joystick/touchpad horizontal motion", dead = 0.19f, axis = 4, type = 2, }, new InputAxis() { name = "XRI_Right_Trigger", descriptiveName = "Device trigger axis", axis = 10, type = 2, }, new InputAxis() { name = "XRI_Right_Grip", descriptiveName = "Device grip axis", axis = 12, type = 2, }, new InputAxis() { name = "XRI_Right_IndexTouch", descriptiveName = "Device index finger proximity touch axis.", dead = 0.19f, axis = 14, type = 2, }, // Button Data new InputAxis() { name = "XRI_Right_PrimaryButton", descriptiveName = "Device primary button", positiveButton = "joystick button 0", gravity = 1000.0f, sensitivity = 1000.0f, type = 0, }, new InputAxis() { name = "XRI_Right_SecondaryButton", descriptiveName = "Device secondary button", positiveButton = "joystick button 1", gravity = 1000.0f, sensitivity = 1000.0f, type = 0, }, new InputAxis() { name = "XRI_Right_GripButton", descriptiveName = "Device grip button", positiveButton = "joystick button 5", gravity = 0.0f, dead = 0.0f, sensitivity = 0.1f, type = 0, }, new InputAxis() { name = "XRI_Right_TriggerButton", descriptiveName = "Device trigger button", positiveButton = "joystick button 15", gravity = 0.0f, dead = 0.0f, sensitivity = 0.1f, type = 0, }, new InputAxis() { name = "XRI_Right_MenuButton", descriptiveName = "Device menu button", positiveButton = "joystick button 7", gravity = 1000.0f, sensitivity = 1000.0f, type = 0, }, new InputAxis() { name = "XRI_Right_Primary2DAxisClick", descriptiveName = "Device stick/touchpad click", positiveButton = "joystick button 9", gravity = 0.0f, dead = 0.0f, sensitivity = 0.1f, type = 0, }, new InputAxis() { name = "XRI_Right_Primary2DAxisTouch", descriptiveName = "Device stick/touchpad touch", positiveButton = "joystick button 17", gravity = 0.0f, dead = 0.0f, sensitivity = 0.1f, type = 0, }, new InputAxis() { name = "XRI_Right_Thumbrest", descriptiveName = "Device thumbrest", positiveButton = "joystick button 19", gravity = 0.0f, dead = 0.0f, sensitivity = 0.1f, type = 0, }, #endregion }; // Same as InputAxis.h internal class InputAxis { public string name = ""; public string descriptiveName = ""; public string descriptiveNegativeName = ""; public string negativeButton = ""; public string positiveButton = ""; public string altNegativeButton = ""; public string altPositiveButton = ""; public float gravity = 0.0f; public float dead = 0.001f; public float sensitivity = 1.0f; public bool snap = false; public bool invert = false; public int type = 0; public int axis = 0; public int joyNum = 0; } internal struct BindingData { public int newDataIndex; public int inputManagerIndex; public bool exists; } /// /// Main entrypoint for generating the XR Bindings and adding them to the Input Asset. The Custom uGUI editor calls this function when the user wishes to /// seed the Input Asset with XR bindings. /// static void GenerateXimmerseXRControllerInputBinding() { // seed map of axis data so we can whitewash against existing. Dictionary axisMap = new Dictionary(); for (int i = 0; i < axisList.Count; ++i) { axisMap.Add(axisList[i].name, new BindingData() { newDataIndex = i, exists = false, inputManagerIndex = -1 }); if (axisList[i].axis > 0) { axisList[i].axis--; } } // load the input asset var inputManagerAsset = AssetDatabase.LoadAllAssetsAtPath("ProjectSettings/InputManager.asset")[0]; if (inputManagerAsset != null) { var serializedObject = new SerializedObject(inputManagerAsset); var inputManagerCurrentData = serializedObject.FindProperty("m_Axes"); if (inputManagerCurrentData != null) { List currentInputData = new List(); LoadExistingDataAndCheckAgainstNewData(inputManagerCurrentData, ref axisMap, ref currentInputData); serializedObject.ApplyModifiedProperties(); ApplyDataToInputManager(currentInputData, axisList, axisMap, ref inputManagerCurrentData); serializedObject.ApplyModifiedProperties(); AssetDatabase.Refresh(); } } } static void ApplyDataToInputManager(List inputManagerData, List newData, Dictionary newDataMap, ref SerializedProperty arrayRoot) { // likely will be larger than we need, but that's ok. it'll be big enough for all the data which is worst case arrayRoot.arraySize = inputManagerData.Count + newData.Count; int arrayIndex = inputManagerData.Count; // write everything that doesn't clash from our new data for (int i = 0; i < newData.Count; ++i) { BindingData bindingData; if (newDataMap.TryGetValue(newData[i].name, out bindingData)) { if (bindingData.exists == true) { continue; } } var axisEntry = arrayRoot.GetArrayElementAtIndex(arrayIndex); WriteDataToInputAxis(newData[i], ref axisEntry); arrayIndex++; } arrayRoot.arraySize = arrayIndex; } static void WriteDataToInputAxis(InputAxis sourceData, ref SerializedProperty serializedProperty) { var iteratorProperty = serializedProperty.Copy(); iteratorProperty.Next(true); do { switch (iteratorProperty.name) { case "m_Name": iteratorProperty.stringValue = sourceData.name; break; case "descriptiveName": iteratorProperty.stringValue = sourceData.descriptiveName; break; case "descriptiveNegativeName": iteratorProperty.stringValue = sourceData.descriptiveNegativeName; break; case "negativeButton": iteratorProperty.stringValue = sourceData.negativeButton; break; case "positiveButton": iteratorProperty.stringValue = sourceData.positiveButton; break; case "altNegativeButton": iteratorProperty.stringValue = sourceData.altNegativeButton; break; case "altPositiveButton": iteratorProperty.stringValue = sourceData.altPositiveButton; break; case "gravity": iteratorProperty.floatValue = sourceData.gravity; break; case "dead": iteratorProperty.floatValue = sourceData.dead; break; case "sensitivity": iteratorProperty.floatValue = sourceData.sensitivity; break; case "snap": iteratorProperty.boolValue = sourceData.snap; break; case "invert": iteratorProperty.boolValue = sourceData.invert; break; case "type": iteratorProperty.intValue = sourceData.type; break; case "axis": iteratorProperty.intValue = sourceData.axis; break; case "joyNum": iteratorProperty.intValue = sourceData.joyNum; break; } } while (iteratorProperty.Next(false)); } static void LoadExistingDataAndCheckAgainstNewData(SerializedProperty arrayRoot, ref Dictionary newDataMap, ref List existingData) { existingData.Clear(); for (int i = 0; i < arrayRoot.arraySize; ++i) { InputAxis readData = new InputAxis(); var axisEntry = arrayRoot.GetArrayElementAtIndex(i); var iteratorProperty = axisEntry.Copy(); iteratorProperty.Next(true); do { switch (iteratorProperty.name) { case "m_Name": readData.name = iteratorProperty.stringValue; BindingData bindingData; if (newDataMap.TryGetValue(readData.name, out bindingData)) { // using TryGetElement returns a copy, not very useful. bindingData.exists = true; bindingData.inputManagerIndex = i; newDataMap[readData.name] = bindingData; } break; case "descriptiveName": readData.descriptiveName = iteratorProperty.stringValue; break; case "descriptiveNegativeName": readData.descriptiveNegativeName = iteratorProperty.stringValue; break; case "negativeButton": readData.negativeButton = iteratorProperty.stringValue; break; case "positiveButton": readData.positiveButton = iteratorProperty.stringValue; break; case "altNegativeButton": readData.altNegativeButton = iteratorProperty.stringValue; break; case "altPositiveButton": readData.altPositiveButton = iteratorProperty.stringValue; break; case "gravity": readData.gravity = iteratorProperty.floatValue; break; case "dead": readData.dead = iteratorProperty.floatValue; break; case "sensitivity": readData.sensitivity = iteratorProperty.floatValue; break; case "snap": readData.snap = iteratorProperty.boolValue; break; case "invert": readData.invert = iteratorProperty.boolValue; break; case "type": readData.type = iteratorProperty.intValue; break; case "axis": readData.axis = iteratorProperty.intValue; break; case "joyNum": readData.joyNum = iteratorProperty.intValue; break; } } while (iteratorProperty.Next(false)); existingData.Add(readData); } } #endregion } }