Tilt Five™ Unity API  1.4.1
WandDevice.cs
Go to the documentation of this file.
1 /*
2  * Copyright (C) 2020-2023 Tilt Five, Inc.
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 #if UNITY_2019_1_OR_NEWER && INPUTSYSTEM_AVAILABLE
18 using UnityEditor;
19 using UnityEngine;
20 using System;
21 using TiltFive.Logging;
22 using UnityEngine.InputSystem;
23 using UnityEngine.InputSystem.Controls;
24 using UnityEngine.InputSystem.Layouts;
25 using UnityEngine.InputSystem.LowLevel;
26 using UnityEngine.InputSystem.Utilities;
27 
28 namespace TiltFive
29 {
30  public struct WandState : IInputStateTypeInfo
31  {
32  public FourCC format => new FourCC('T', '5');
33 
34  [InputControl(name = "TiltFive", layout = "Button", bit = 0)]
35  public bool TiltFive;
36 
37  [InputControl(name = "One", layout = "Button", bit = 0)]
38  public bool One;
39 
40  [InputControl(name = "Two", layout = "Button", bit = 0)]
41  public bool Two;
42 
43  [InputControl(name = "A", layout = "Button", bit = 0)]
44  public bool A;
45 
46  [InputControl(name = "B", layout = "Button", bit = 0)]
47  public bool B;
48 
49  [InputControl(name = "X", layout = "Button", bit = 0)]
50  public bool X;
51 
52  [InputControl(name = "Y", layout = "Button", bit = 0)]
53  public bool Y;
54 
55  [InputControl(name = "Three", aliases = new string[]
56  { "thumbstickClick", "JoystickOrPadPressed", "thumbstickClicked", "thumbstickpressed", "primary2DAxisClick" },
57  layout = "Button", bit = 0)]
58  public bool Three;
59 
60  [InputControl(name = "Stick", aliases = new string[] { "Joystick", "Thumbstick"}, layout = "Stick")]
61  [InputControl(name = "Primary2DAxis", synthetic = true, useStateFrom = "Stick", layout = "Vector2")]
62  public Vector2 Stick;
63 
64  [InputControl(name = "Trigger", layout = "Axis")]
65  public float Trigger;
66 
67  [InputControl(name = "devicePosition", alias = "Position_Grip", layout = "Vector3")]
68  public Vector3 devicePosition;
69 
70  [InputControl(name = "Position_Fingertips", layout = "Vector3")]
71  public Vector3 FingertipsPosition;
72 
73  [InputControl(name = "Position_Aim", layout = "Vector3")]
74  public Vector3 AimPosition;
75 
76  [InputControl(name = "Position_Grip/Raw", layout = "Vector3")]
77  public Vector3 RawGripPosition;
78 
79  [InputControl(name = "Position_Fingertips/Raw", layout = "Vector3")]
80  public Vector3 RawFingertipsPosition;
81 
82  [InputControl(name = "Position_Aim/Raw", layout = "Vector3")]
83  public Vector3 RawAimPosition;
84 
85  [InputControl(name = "deviceRotation", alias = "Rotation", layout = "Quaternion")]
86  public Quaternion deviceRotation;
87 
88  [InputControl(name = "Rotation/Raw", layout = "Quaternion")]
89  public Quaternion RawRotation;
90 
91  [InputControl(name = "isTracked", layout = "Button")]
92  public bool isTracked;
93 
94  [InputControl(name = "trackingState", layout = "Integer")]
95  public int trackingState;
96  }
97 
98  [InputControlLayout(stateType = typeof(WandState), displayName = "Tilt Five Wand",
99  commonUsages = new string[] { "LeftHand", "RightHand" }, updateBeforeRender = true)]
100 #if UNITY_EDITOR
101  [InitializeOnLoad]
102 #endif
103  public class WandDevice : UnityEngine.InputSystem.XR.XRControllerWithRumble
104  {
105  #region Public Fields
106 
107  public PlayerIndex playerIndex { get; internal set; }
108  public ControllerIndex ControllerIndex { get; internal set; }
109 
110  #endregion
111 
112 
113  #region Controls
114 
115  public ButtonControl TiltFive { get; private set; }
116  public ButtonControl One { get; private set; }
117  public ButtonControl Two { get; private set; }
118  public ButtonControl Three { get; private set; }
119  public ButtonControl A { get; private set; }
120  public ButtonControl B { get; private set; }
121  public ButtonControl X { get; private set; }
122  public ButtonControl Y { get; private set; }
123 
124  public StickControl Stick { get; private set; }
125 
126  public AxisControl Trigger { get; private set; }
127 
128  public new Vector3Control devicePosition { get; private set; }
129  public Vector3Control FingertipsPosition { get; private set; }
130  public Vector3Control AimPosition { get; private set; }
131 
132  public Vector3Control RawGripPosition { get; private set; }
133  public Vector3Control RawFingertipsPosition { get; private set; }
134  public Vector3Control RawAimPosition { get; private set; }
135 
136  public new QuaternionControl deviceRotation { get; private set; }
137  public QuaternionControl RawRotation { get; private set; }
138 
139  public new ButtonControl isTracked { get; private set; }
140  public new IntegerControl trackingState { get; private set; }
141 
142  #endregion
143 
144 
145  #region Overrides
146 
147  protected override void FinishSetup()
148  {
149  base.FinishSetup();
150 
151  TiltFive = GetChildControl<ButtonControl>("TiltFive");
152  One = GetChildControl<ButtonControl>("One");
153  Two = GetChildControl<ButtonControl>("Two");
154  A = GetChildControl<ButtonControl>("A");
155  B = GetChildControl<ButtonControl>("B");
156  X = GetChildControl<ButtonControl>("X");
157  Y = GetChildControl<ButtonControl>("Y");
158  Three = GetChildControl<ButtonControl>("Three");
159 
160  Stick = GetChildControl<StickControl>("Stick");
161 
162  Trigger = GetChildControl<AxisControl>("Trigger");
163 
164  devicePosition = GetChildControl<Vector3Control>("Position_Grip");
165  FingertipsPosition = GetChildControl<Vector3Control>("Position_Fingertips");
166  AimPosition = GetChildControl<Vector3Control>("Position_Aim");
167 
168  RawGripPosition = GetChildControl<Vector3Control>("Position_Grip/Raw");
169  RawFingertipsPosition = GetChildControl<Vector3Control>("Position_Fingertips/Raw");
170  RawAimPosition = GetChildControl<Vector3Control>("Position_Aim/Raw");
171 
172  deviceRotation = GetChildControl<QuaternionControl>("Rotation");
173  RawRotation = GetChildControl<QuaternionControl>("Rotation/Raw");
174 
175  isTracked = GetChildControl<ButtonControl>("isTracked");
176  trackingState = GetChildControl<IntegerControl>("trackingState");
177  }
178 
179  protected override void RefreshConfiguration()
180  {
181  switch (ControllerIndex)
182  {
183  case ControllerIndex.Left:
184  if (usages.Contains(CommonUsages.RightHand))
185  {
186  InputSystem.RemoveDeviceUsage(this, CommonUsages.RightHand);
187  }
188  InputSystem.AddDeviceUsage(this, CommonUsages.LeftHand);
189  break;
190  case ControllerIndex.Right:
191  if(usages.Contains(CommonUsages.LeftHand))
192  {
193  InputSystem.RemoveDeviceUsage(this, CommonUsages.LeftHand);
194  }
195  InputSystem.AddDeviceUsage(this, CommonUsages.RightHand);
196  break;
197  default:
198  break;
199  }
200 
201  base.RefreshConfiguration();
202  }
203 
204  protected new void SendImpulse(float amplitude, float duration){
205  try
206  {
207  if(!Player.TryGetGlassesHandle(playerIndex, out var glassesHandle))
208  {
209  Log.Error("Failed to get glasses handle.");
210  return;
211  }
212  //SendImpulse expects seconds. We'll convert to milliseconds before passing to the Native Code
213  if(NativePlugin.SendImpulse(glassesHandle, ControllerIndex, amplitude, (UInt16)(Mathf.Clamp(duration, 0.0f, 0.320f) * 1000)) == 0)
214  {
215  return;
216  }
217  else
218  {
219  Log.Error("Failed to send impulse to wand.");
220  }
221  }
222  catch (DllNotFoundException e)
223  {
224  Log.Info("Tilt Five library missing. Could not connect to wand: {0}", e.Message);
225  }
226  catch (Exception e)
227  {
228  Log.Error(
229  "Failed to send impulse to wand: {0}",
230  e.ToString());
231  }
232  }
233 
234  #endregion
235 
236  static WandDevice()
237  {
238  InputSystem.RegisterLayout<WandDevice>(matches: new InputDeviceMatcher()
239  .WithInterface("WandDevice"));
240  }
241  }
242 }
243 #endif
Definition: Log.cs:21
ControllerIndex
Since wands are all physically identical (they have no "handedness"), it doesn't make sense to addres...
PlayerIndex
The Player index (e.g. Player One, Player Two, etc)