SteamVR_Action_Pose.cs
45.6 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
//======= Copyright (c) Valve Corporation, All rights reserved. ===============
using UnityEngine;
using System.Collections;
using System;
using Valve.VR;
using System.Runtime.InteropServices;
using System.Collections.Generic;
namespace Valve.VR
{
[Serializable]
/// <summary>
/// Pose actions represent a position, rotation, and velocities inside the tracked space.
/// SteamVR keeps a log of past poses so you can retrieve old poses with GetPoseAtTimeOffset or GetVelocitiesAtTimeOffset.
/// You can also pass in times in the future to these methods for SteamVR's best prediction of where the pose will be at that time.
/// </summary>
public class SteamVR_Action_Pose : SteamVR_Action_Pose_Base<SteamVR_Action_Pose_Source_Map<SteamVR_Action_Pose_Source>, SteamVR_Action_Pose_Source>, ISerializationCallbackReceiver
{
public delegate void ActiveChangeHandler(SteamVR_Action_Pose fromAction, SteamVR_Input_Sources fromSource, bool active);
public delegate void ChangeHandler(SteamVR_Action_Pose fromAction, SteamVR_Input_Sources fromSource);
public delegate void UpdateHandler(SteamVR_Action_Pose fromAction, SteamVR_Input_Sources fromSource);
public delegate void TrackingChangeHandler(SteamVR_Action_Pose fromAction, SteamVR_Input_Sources fromSource, ETrackingResult trackingState);
public delegate void ValidPoseChangeHandler(SteamVR_Action_Pose fromAction, SteamVR_Input_Sources fromSource, bool validPose);
public delegate void DeviceConnectedChangeHandler(SteamVR_Action_Pose fromAction, SteamVR_Input_Sources fromSource, bool deviceConnected);
/// <summary><strong>[Shortcut to: SteamVR_Input_Sources.Any]</strong> Event fires when the active state (ActionSet active and binding active) changes</summary>
public event ActiveChangeHandler onActiveChange
{ add { sourceMap[SteamVR_Input_Sources.Any].onActiveChange += value; } remove { sourceMap[SteamVR_Input_Sources.Any].onActiveChange -= value; } }
/// <summary><strong>[Shortcut to: SteamVR_Input_Sources.Any]</strong> Event fires when the active state of the binding changes</summary>
public event ActiveChangeHandler onActiveBindingChange
{ add { sourceMap[SteamVR_Input_Sources.Any].onActiveBindingChange += value; } remove { sourceMap[SteamVR_Input_Sources.Any].onActiveBindingChange -= value; } }
/// <summary><strong>[Shortcut to: SteamVR_Input_Sources.Any]</strong> Event fires when the orientation of the pose changes more than the changeTolerance</summary>
public event ChangeHandler onChange
{ add { sourceMap[SteamVR_Input_Sources.Any].onChange += value; } remove { sourceMap[SteamVR_Input_Sources.Any].onChange -= value; } }
/// <summary><strong>[Shortcut to: SteamVR_Input_Sources.Any]</strong> Event fires when the action is updated</summary>
public event UpdateHandler onUpdate
{ add { sourceMap[SteamVR_Input_Sources.Any].onUpdate += value; } remove { sourceMap[SteamVR_Input_Sources.Any].onUpdate -= value; } }
/// <summary><strong>[Shortcut to: SteamVR_Input_Sources.Any]</strong> Event fires when the state of the tracking has changed</summary>
public event TrackingChangeHandler onTrackingChanged
{ add { sourceMap[SteamVR_Input_Sources.Any].onTrackingChanged += value; } remove { sourceMap[SteamVR_Input_Sources.Any].onTrackingChanged -= value; } }
/// <summary><strong>[Shortcut to: SteamVR_Input_Sources.Any]</strong> Event fires when the validity of the pose has changed</summary>
public event ValidPoseChangeHandler onValidPoseChanged
{ add { sourceMap[SteamVR_Input_Sources.Any].onValidPoseChanged += value; } remove { sourceMap[SteamVR_Input_Sources.Any].onValidPoseChanged -= value; } }
/// <summary><strong>[Shortcut to: SteamVR_Input_Sources.Any]</strong> Event fires when the device bound to this pose is connected or disconnected</summary>
public event DeviceConnectedChangeHandler onDeviceConnectedChanged
{ add { sourceMap[SteamVR_Input_Sources.Any].onDeviceConnectedChanged += value; } remove { sourceMap[SteamVR_Input_Sources.Any].onDeviceConnectedChanged -= value; } }
/// <summary>Fires an event when a device is connected or disconnected.</summary>
/// <param name="inputSource">The device you would like to add an event to. Any if the action is not device specific.</param>
/// <param name="functionToCall">The method you would like to be called when a device is connected. Should take a SteamVR_Action_Pose as a param</param>
public void AddOnDeviceConnectedChanged(SteamVR_Input_Sources inputSource, DeviceConnectedChangeHandler functionToCall)
{
sourceMap[inputSource].onDeviceConnectedChanged += functionToCall;
}
/// <summary>Stops executing the function setup by the corresponding AddListener</summary>
/// <param name="inputSource">The device you would like to remove an event from. Any if the action is not device specific.</param>
/// <param name="functionToStopCalling">The method you would like to stop calling when a device is connected. Should take a SteamVR_Action_Pose as a param</param>
public void RemoveOnDeviceConnectedChanged(SteamVR_Input_Sources inputSource, DeviceConnectedChangeHandler functionToStopCalling)
{
sourceMap[inputSource].onDeviceConnectedChanged -= functionToStopCalling;
}
/// <summary>Fires an event when the tracking of the device has changed</summary>
/// <param name="inputSource">The device you would like to add an event to. Any if the action is not device specific.</param>
/// <param name="functionToCall">The method you would like to be called when tracking has changed. Should take a SteamVR_Action_Pose as a param</param>
public void AddOnTrackingChanged(SteamVR_Input_Sources inputSource, TrackingChangeHandler functionToCall)
{
sourceMap[inputSource].onTrackingChanged += functionToCall;
}
/// <summary>Stops executing the function setup by the corresponding AddListener</summary>
/// <param name="inputSource">The device you would like to remove an event from. Any if the action is not device specific.</param>
/// <param name="functionToStopCalling">The method you would like to stop calling when tracking has changed. Should take a SteamVR_Action_Pose as a param</param>
public void RemoveOnTrackingChanged(SteamVR_Input_Sources inputSource, TrackingChangeHandler functionToStopCalling)
{
sourceMap[inputSource].onTrackingChanged -= functionToStopCalling;
}
/// <summary>Fires an event when the device now has a valid pose or no longer has a valid pose</summary>
/// <param name="inputSource">The device you would like to add an event to. Any if the action is not device specific.</param>
/// <param name="functionToCall">The method you would like to be called when the pose has become valid or invalid. Should take a SteamVR_Action_Pose as a param</param>
public void AddOnValidPoseChanged(SteamVR_Input_Sources inputSource, ValidPoseChangeHandler functionToCall)
{
sourceMap[inputSource].onValidPoseChanged += functionToCall;
}
/// <summary>Stops executing the function setup by the corresponding AddListener</summary>
/// <param name="inputSource">The device you would like to remove an event from. Any if the action is not device specific.</param>
/// <param name="functionToStopCalling">The method you would like to stop calling when the pose has become valid or invalid. Should take a SteamVR_Action_Pose as a param</param>
public void RemoveOnValidPoseChanged(SteamVR_Input_Sources inputSource, ValidPoseChangeHandler functionToStopCalling)
{
sourceMap[inputSource].onValidPoseChanged -= functionToStopCalling;
}
/// <summary>Executes a function when this action's bound state changes</summary>
/// <param name="inputSource">The device you would like to get data from. Any if the action is not device specific.</param>
public void AddOnActiveChangeListener(SteamVR_Input_Sources inputSource, ActiveChangeHandler functionToCall)
{
sourceMap[inputSource].onActiveChange += functionToCall;
}
/// <summary>Stops executing the function setup by the corresponding AddListener</summary>
/// <param name="functionToStopCalling">The local function that you've setup to receive update events</param>
/// <param name="inputSource">The device you would like to get data from. Any if the action is not device specific.</param>
public void RemoveOnActiveChangeListener(SteamVR_Input_Sources inputSource, ActiveChangeHandler functionToStopCalling)
{
sourceMap[inputSource].onActiveChange -= functionToStopCalling;
}
/// <summary>Executes a function when the state of this action (with the specified inputSource) changes</summary>
/// <param name="functionToCall">A local function that receives the boolean action who's state has changed, the corresponding input source, and the new value</param>
/// <param name="inputSource">The device you would like to get data from. Any if the action is not device specific.</param>
public void AddOnChangeListener(SteamVR_Input_Sources inputSource, ChangeHandler functionToCall)
{
sourceMap[inputSource].onChange += functionToCall;
}
/// <summary>Stops executing the function setup by the corresponding AddListener</summary>
/// <param name="functionToStopCalling">The local function that you've setup to receive on change events</param>
/// <param name="inputSource">The device you would like to get data from. Any if the action is not device specific.</param>
public void RemoveOnChangeListener(SteamVR_Input_Sources inputSource, ChangeHandler functionToStopCalling)
{
sourceMap[inputSource].onChange -= functionToStopCalling;
}
/// <summary>Executes a function when the state of this action (with the specified inputSource) is updated.</summary>
/// <param name="functionToCall">A local function that receives the boolean action who's state has changed, the corresponding input source, and the new value</param>
/// <param name="inputSource">The device you would like to get data from. Any if the action is not device specific.</param>
public void AddOnUpdateListener(SteamVR_Input_Sources inputSource, UpdateHandler functionToCall)
{
sourceMap[inputSource].onUpdate += functionToCall;
}
/// <summary>Stops executing the function setup by the corresponding AddListener</summary>
/// <param name="functionToStopCalling">The local function that you've setup to receive update events</param>
/// <param name="inputSource">The device you would like to get data from. Any if the action is not device specific.</param>
public void RemoveOnUpdateListener(SteamVR_Input_Sources inputSource, UpdateHandler functionToStopCalling)
{
sourceMap[inputSource].onUpdate -= functionToStopCalling;
}
/// <summary>
/// Removes all listeners, useful for dispose pattern
/// </summary>
public void RemoveAllListeners(SteamVR_Input_Sources input_Sources)
{
sourceMap[input_Sources].RemoveAllListeners();
}
void ISerializationCallbackReceiver.OnBeforeSerialize() { }
void ISerializationCallbackReceiver.OnAfterDeserialize()
{
InitAfterDeserialize();
}
/// <summary>
/// Sets all pose and skeleton actions to use the specified universe origin.
/// </summary>
public static void SetTrackingUniverseOrigin(ETrackingUniverseOrigin newOrigin)
{
SetUniverseOrigin(newOrigin);
OpenVR.Compositor.SetTrackingSpace(newOrigin);
}
}
[Serializable]
/// <summary>
/// The base pose action (pose and skeleton inherit from this)
/// </summary>
public abstract class SteamVR_Action_Pose_Base<SourceMap, SourceElement> : SteamVR_Action_In<SourceMap, SourceElement>, ISteamVR_Action_Pose
where SourceMap : SteamVR_Action_Pose_Source_Map<SourceElement>, new()
where SourceElement : SteamVR_Action_Pose_Source, new()
{
/// <summary>
/// Sets all pose (and skeleton) actions to use the specified universe origin.
/// </summary>
protected static void SetUniverseOrigin(ETrackingUniverseOrigin newOrigin)
{
for (int actionIndex = 0; actionIndex < SteamVR_Input.actionsPose.Length; actionIndex++)
{
SteamVR_Input.actionsPose[actionIndex].sourceMap.SetTrackingUniverseOrigin(newOrigin);
}
for (int actionIndex = 0; actionIndex < SteamVR_Input.actionsSkeleton.Length; actionIndex++)
{
SteamVR_Input.actionsSkeleton[actionIndex].sourceMap.SetTrackingUniverseOrigin(newOrigin);
}
}
/// <summary><strong>[Shortcut to: SteamVR_Input_Sources.Any]</strong> The local position of this action relative to the universe origin</summary>
public Vector3 localPosition { get { return sourceMap[SteamVR_Input_Sources.Any].localPosition; } }
/// <summary><strong>[Shortcut to: SteamVR_Input_Sources.Any]</strong> The local rotation of this action relative to the universe origin</summary>
public Quaternion localRotation { get { return sourceMap[SteamVR_Input_Sources.Any].localRotation; } }
/// <summary><strong>[Shortcut to: SteamVR_Input_Sources.Any]</strong> The state of the tracking system that is used to create pose data (position, rotation, etc)</summary>
public ETrackingResult trackingState { get { return sourceMap[SteamVR_Input_Sources.Any].trackingState; } }
/// <summary><strong>[Shortcut to: SteamVR_Input_Sources.Any]</strong> The local velocity of this pose relative to the universe origin</summary>
public Vector3 velocity { get { return sourceMap[SteamVR_Input_Sources.Any].velocity; } }
/// <summary><strong>[Shortcut to: SteamVR_Input_Sources.Any]</strong> The local angular velocity of this pose relative to the universe origin</summary>
public Vector3 angularVelocity { get { return sourceMap[SteamVR_Input_Sources.Any].angularVelocity; } }
/// <summary><strong>[Shortcut to: SteamVR_Input_Sources.Any]</strong> True if the pose retrieved for this action and input source is valid (good data from the tracking source)</summary>
public bool poseIsValid { get { return sourceMap[SteamVR_Input_Sources.Any].poseIsValid; } }
/// <summary><strong>[Shortcut to: SteamVR_Input_Sources.Any]</strong> True if the device bound to this action and input source is connected</summary>
public bool deviceIsConnected { get { return sourceMap[SteamVR_Input_Sources.Any].deviceIsConnected; } }
/// <summary><strong>[Shortcut to: SteamVR_Input_Sources.Any]</strong> The local position for this pose during the previous update</summary>
public Vector3 lastLocalPosition { get { return sourceMap[SteamVR_Input_Sources.Any].lastLocalPosition; } }
/// <summary><strong>[Shortcut to: SteamVR_Input_Sources.Any]</strong> The local rotation for this pose during the previous update</summary>
public Quaternion lastLocalRotation { get { return sourceMap[SteamVR_Input_Sources.Any].lastLocalRotation; } }
/// <summary><strong>[Shortcut to: SteamVR_Input_Sources.Any]</strong> The tracking state for this pose during the previous update</summary>
public ETrackingResult lastTrackingState { get { return sourceMap[SteamVR_Input_Sources.Any].lastTrackingState; } }
/// <summary><strong>[Shortcut to: SteamVR_Input_Sources.Any]</strong> The velocity for this pose during the previous update</summary>
public Vector3 lastVelocity { get { return sourceMap[SteamVR_Input_Sources.Any].lastVelocity; } }
/// <summary><strong>[Shortcut to: SteamVR_Input_Sources.Any]</strong> The angular velocity for this pose during the previous update</summary>
public Vector3 lastAngularVelocity { get { return sourceMap[SteamVR_Input_Sources.Any].lastAngularVelocity; } }
/// <summary><strong>[Shortcut to: SteamVR_Input_Sources.Any]</strong> True if the pose was valid during the previous update</summary>
public bool lastPoseIsValid { get { return sourceMap[SteamVR_Input_Sources.Any].lastPoseIsValid; } }
/// <summary><strong>[Shortcut to: SteamVR_Input_Sources.Any]</strong> True if the device bound to this action was connected during the previous update</summary>
public bool lastDeviceIsConnected { get { return sourceMap[SteamVR_Input_Sources.Any].lastDeviceIsConnected; } }
public SteamVR_Action_Pose_Base() { }
/// <summary>
/// <strong>[Should not be called by user code]</strong>
/// Updates the data for all the input sources the system has detected need to be updated.
/// </summary>
public virtual void UpdateValues(bool skipStateAndEventUpdates)
{
sourceMap.UpdateValues(skipStateAndEventUpdates);
}
/// <summary>
/// SteamVR 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="inputSource">The device you would like to get data from. Any if the action is not device specific.</param>
/// <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 the call succeeded</returns>
public bool GetVelocitiesAtTimeOffset(SteamVR_Input_Sources inputSource, float secondsFromNow, out Vector3 velocity, out Vector3 angularVelocity)
{
return sourceMap[inputSource].GetVelocitiesAtTimeOffset(secondsFromNow, out velocity, out angularVelocity);
}
/// <summary>
/// SteamVR 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="inputSource">The device you would like to get data from. Any if the action is not device specific.</param>
/// <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 the call succeeded</returns>
public bool GetPoseAtTimeOffset(SteamVR_Input_Sources inputSource, float secondsFromNow, out Vector3 localPosition, out Quaternion localRotation, out Vector3 velocity, out Vector3 angularVelocity)
{
return sourceMap[inputSource].GetPoseAtTimeOffset(secondsFromNow, out localPosition, out localRotation, out velocity, out angularVelocity);
}
/// <summary>
/// Update a transform's local position and local roation to match the pose from the most recent update
/// </summary>
/// <param name="inputSource">The device you would like to get data from. Any if the action is not device specific.</param>
/// <param name="transformToUpdate">The transform of the object to be updated</param>
public virtual void UpdateTransform(SteamVR_Input_Sources inputSource, Transform transformToUpdate)
{
sourceMap[inputSource].UpdateTransform(transformToUpdate);
}
/// <summary>The local position of this action relative to the universe origin</summary>
/// <param name="inputSource">The device you would like to get data from. Any if the action is not device specific.</param>
public Vector3 GetLocalPosition(SteamVR_Input_Sources inputSource)
{
return sourceMap[inputSource].localPosition;
}
/// <summary>The local rotation of this action relative to the universe origin</summary>
/// <param name="inputSource">The device you would like to get data from. Any if the action is not device specific.</param>
public Quaternion GetLocalRotation(SteamVR_Input_Sources inputSource)
{
return sourceMap[inputSource].localRotation;
}
/// <summary>The local velocity of this pose relative to the universe origin</summary>
/// <param name="inputSource">The device you would like to get data from. Any if the action is not device specific.</param>
public Vector3 GetVelocity(SteamVR_Input_Sources inputSource)
{
return sourceMap[inputSource].velocity;
}
/// <summary>The local angular velocity of this pose relative to the universe origin</summary>
/// <param name="inputSource">The device you would like to get data from. Any if the action is not device specific.</param>
public Vector3 GetAngularVelocity(SteamVR_Input_Sources inputSource)
{
return sourceMap[inputSource].angularVelocity;
}
/// <summary>True if the device bound to this action and input source is connected</summary>
/// <param name="inputSource">The device you would like to get data from. Any if the action is not device specific.</param>
public bool GetDeviceIsConnected(SteamVR_Input_Sources inputSource)
{
return sourceMap[inputSource].deviceIsConnected;
}
/// <summary>True if the pose retrieved for this action and input source is valid (good data from the tracking source)</summary>
/// <param name="inputSource">The device you would like to get data from. Any if the action is not device specific.</param>
public bool GetPoseIsValid(SteamVR_Input_Sources inputSource)
{
return sourceMap[inputSource].poseIsValid;
}
/// <summary>The state of the tracking system that is used to create pose data (position, rotation, etc)</summary>
/// <param name="inputSource">The device you would like to get data from. Any if the action is not device specific.</param>
public ETrackingResult GetTrackingResult(SteamVR_Input_Sources inputSource)
{
return sourceMap[inputSource].trackingState;
}
/// <summary>The local position for this pose during the previous update</summary>
/// <param name="inputSource">The device you would like to get data from. Any if the action is not device specific.</param>
public Vector3 GetLastLocalPosition(SteamVR_Input_Sources inputSource)
{
return sourceMap[inputSource].lastLocalPosition;
}
/// <summary>The local rotation for this pose during the previous update</summary>
/// <param name="inputSource">The device you would like to get data from. Any if the action is not device specific.</param>
public Quaternion GetLastLocalRotation(SteamVR_Input_Sources inputSource)
{
return sourceMap[inputSource].lastLocalRotation;
}
/// <summary>The velocity for this pose during the previous update</summary>
/// <param name="inputSource">The device you would like to get data from. Any if the action is not device specific.</param>
public Vector3 GetLastVelocity(SteamVR_Input_Sources inputSource)
{
return sourceMap[inputSource].lastVelocity;
}
/// <summary>The angular velocity for this pose during the previous update</summary>
/// <param name="inputSource">The device you would like to get data from. Any if the action is not device specific.</param>
public Vector3 GetLastAngularVelocity(SteamVR_Input_Sources inputSource)
{
return sourceMap[inputSource].lastAngularVelocity;
}
/// <summary>True if the device bound to this action was connected during the previous update</summary>
/// <param name="inputSource">The device you would like to get data from. Any if the action is not device specific.</param>
public bool GetLastDeviceIsConnected(SteamVR_Input_Sources inputSource)
{
return sourceMap[inputSource].lastDeviceIsConnected;
}
/// <summary>True if the pose was valid during the previous update</summary>
/// <param name="inputSource">The device you would like to get data from. Any if the action is not device specific.</param>
public bool GetLastPoseIsValid(SteamVR_Input_Sources inputSource)
{
return sourceMap[inputSource].lastPoseIsValid;
}
/// <summary>The tracking state for this pose during the previous update</summary>
/// <param name="inputSource">The device you would like to get data from. Any if the action is not device specific.</param>
public ETrackingResult GetLastTrackingResult(SteamVR_Input_Sources inputSource)
{
return sourceMap[inputSource].lastTrackingState;
}
}
/// <summary>
/// Boolean actions are either true or false. There is an onStateUp and onStateDown event for the rising and falling edge.
/// </summary>
public class SteamVR_Action_Pose_Source_Map<Source> : SteamVR_Action_In_Source_Map<Source>
where Source : SteamVR_Action_Pose_Source, new()
{
/// <summary>
/// Sets all pose (and skeleton) actions to use the specified universe origin without going through the sourcemap indexer
/// </summary>
public void SetTrackingUniverseOrigin(ETrackingUniverseOrigin newOrigin)
{
for (int sourceIndex = 0; sourceIndex < sources.Length; sourceIndex++)
{
if (sources[sourceIndex] != null)
sources[sourceIndex].universeOrigin = newOrigin;
}
}
public virtual void UpdateValues(bool skipStateAndEventUpdates)
{
for (int sourceIndex = 0; sourceIndex < updatingSources.Count; sourceIndex++)
{
sources[updatingSources[sourceIndex]].UpdateValue(skipStateAndEventUpdates);
}
}
}
public class SteamVR_Action_Pose_Source : SteamVR_Action_In_Source, ISteamVR_Action_Pose
{
public ETrackingUniverseOrigin universeOrigin = ETrackingUniverseOrigin.TrackingUniverseRawAndUncalibrated;
protected static uint poseActionData_size = 0;
/// <summary>The distance the pose needs to move/rotate before a change is detected</summary>
public float changeTolerance = Mathf.Epsilon;
/// <summary>Event fires when the active state (ActionSet active and binding active) changes</summary>
public event SteamVR_Action_Pose.ActiveChangeHandler onActiveChange;
/// <summary>Event fires when the active state of the binding changes</summary>
public event SteamVR_Action_Pose.ActiveChangeHandler onActiveBindingChange;
/// <summary>Event fires when the orientation of the pose changes more than the changeTolerance</summary>
public event SteamVR_Action_Pose.ChangeHandler onChange;
/// <summary>Event fires when the action is updated</summary>
public event SteamVR_Action_Pose.UpdateHandler onUpdate;
/// <summary>Event fires when the state of the tracking system that is used to create pose data (position, rotation, etc) changes</summary>
public event SteamVR_Action_Pose.TrackingChangeHandler onTrackingChanged;
/// <summary>Event fires when the state of the pose data retrieved for this action changes validity (good/bad data from the tracking source)</summary>
public event SteamVR_Action_Pose.ValidPoseChangeHandler onValidPoseChanged;
/// <summary>Event fires when the device bound to this action is connected or disconnected</summary>
public event SteamVR_Action_Pose.DeviceConnectedChangeHandler onDeviceConnectedChanged;
/// <summary>True when the orientation of the pose has changhed more than changeTolerance in the last update. Note: Will only return true if the action is also active.</summary>
public override bool changed { get; protected set; }
/// <summary>The value of the action's 'changed' during the previous update</summary>
public override bool lastChanged { get; protected set; }
/// <summary>The handle to the origin of the component that was used to update this pose</summary>
public override ulong activeOrigin
{
get
{
if (active)
return poseActionData.activeOrigin;
return 0;
}
}
/// <summary>The handle to the origin of the component that was used to update the value for this action (for the previous update)</summary>
public override ulong lastActiveOrigin { get { return lastPoseActionData.activeOrigin; } }
/// <summary>True if this action is bound and the ActionSet is active</summary>
public override bool active { get { return activeBinding && action.actionSet.IsActive(inputSource); } }
/// <summary>True if the action is bound</summary>
public override bool activeBinding { get { return poseActionData.bActive; } }
/// <summary>If the action was active (ActionSet active and binding active) during the last update</summary>
public override bool lastActive { get; protected set; }
/// <summary>If the action's binding was active during the previous update</summary>
public override bool lastActiveBinding { get { return lastPoseActionData.bActive; } }
/// <summary>The state of the tracking system that is used to create pose data (position, rotation, etc)</summary>
public ETrackingResult trackingState { get { return poseActionData.pose.eTrackingResult; } }
/// <summary>The tracking state for this pose during the previous update</summary>
public ETrackingResult lastTrackingState { get { return lastPoseActionData.pose.eTrackingResult; } }
/// <summary>True if the pose retrieved for this action and input source is valid (good data from the tracking source)</summary>
public bool poseIsValid { get { return poseActionData.pose.bPoseIsValid; } }
/// <summary>True if the pose was valid during the previous update</summary>
public bool lastPoseIsValid { get { return lastPoseActionData.pose.bPoseIsValid; } }
/// <summary>True if the device bound to this action and input source is connected</summary>
public bool deviceIsConnected { get { return poseActionData.pose.bDeviceIsConnected; } }
/// <summary>True if the device bound to this action was connected during the previous update</summary>
public bool lastDeviceIsConnected { get { return lastPoseActionData.pose.bDeviceIsConnected; } }
/// <summary>The local position of this action relative to the universe origin</summary>
public Vector3 localPosition { get; protected set; }
/// <summary>The local rotation of this action relative to the universe origin</summary>
public Quaternion localRotation { get; protected set; }
/// <summary>The local position for this pose during the previous update</summary>
public Vector3 lastLocalPosition { get; protected set; }
/// <summary>The local rotation for this pose during the previous update</summary>
public Quaternion lastLocalRotation { get; protected set; }
/// <summary>The local velocity of this pose relative to the universe origin</summary>
public Vector3 velocity { get; protected set; }
/// <summary>The velocity for this pose during the previous update</summary>
public Vector3 lastVelocity { get; protected set; }
/// <summary>The local angular velocity of this pose relative to the universe origin</summary>
public Vector3 angularVelocity { get; protected set; }
/// <summary>The angular velocity for this pose during the previous update</summary>
public Vector3 lastAngularVelocity { get; protected set; }
protected InputPoseActionData_t poseActionData = new InputPoseActionData_t();
protected InputPoseActionData_t lastPoseActionData = new InputPoseActionData_t();
protected InputPoseActionData_t tempPoseActionData = new InputPoseActionData_t();
protected SteamVR_Action_Pose poseAction;
/// <summary>
/// <strong>[Should not be called by user code]</strong> Sets up the internals of the action source before SteamVR has been initialized.
/// </summary>
public override void Preinitialize(SteamVR_Action wrappingAction, SteamVR_Input_Sources forInputSource)
{
base.Preinitialize(wrappingAction, forInputSource);
poseAction = wrappingAction as SteamVR_Action_Pose;
}
/// <summary>
/// <strong>[Should not be called by user code]</strong>
/// Initializes the handle for the inputSource, the pose action data size, and any other related SteamVR data.
/// </summary>
public override void Initialize()
{
base.Initialize();
if (poseActionData_size == 0)
poseActionData_size = (uint)Marshal.SizeOf(typeof(InputPoseActionData_t));
}
/// <summary>
/// Removes all listeners, useful for dispose pattern
/// </summary>
public virtual void RemoveAllListeners()
{
Delegate[] delegates;
if (onActiveChange != null)
{
delegates = onActiveChange.GetInvocationList();
if (delegates != null)
foreach (Delegate existingDelegate in delegates)
onActiveChange -= (SteamVR_Action_Pose.ActiveChangeHandler)existingDelegate;
}
if (onChange != null)
{
delegates = onChange.GetInvocationList();
if (delegates != null)
foreach (Delegate existingDelegate in delegates)
onChange -= (SteamVR_Action_Pose.ChangeHandler)existingDelegate;
}
if (onUpdate != null)
{
delegates = onUpdate.GetInvocationList();
if (delegates != null)
foreach (Delegate existingDelegate in delegates)
onUpdate -= (SteamVR_Action_Pose.UpdateHandler)existingDelegate;
}
if (onTrackingChanged != null)
{
delegates = onTrackingChanged.GetInvocationList();
if (delegates != null)
foreach (Delegate existingDelegate in delegates)
onTrackingChanged -= (SteamVR_Action_Pose.TrackingChangeHandler)existingDelegate;
}
if (onValidPoseChanged != null)
{
delegates = onValidPoseChanged.GetInvocationList();
if (delegates != null)
foreach (Delegate existingDelegate in delegates)
onValidPoseChanged -= (SteamVR_Action_Pose.ValidPoseChangeHandler)existingDelegate;
}
if (onDeviceConnectedChanged != null)
{
delegates = onDeviceConnectedChanged.GetInvocationList();
if (delegates != null)
foreach (Delegate existingDelegate in delegates)
onDeviceConnectedChanged -= (SteamVR_Action_Pose.DeviceConnectedChangeHandler)existingDelegate;
}
}
/// <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()
{
UpdateValue(false);
}
public static float framesAhead = 2;
/// <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;
if (framesAhead == 0)
err = OpenVR.Input.GetPoseActionDataForNextFrame(handle, universeOrigin, ref poseActionData, poseActionData_size, inputSourceHandle);
else
err = OpenVR.Input.GetPoseActionDataRelativeToNow(handle, universeOrigin, framesAhead * (Time.timeScale / SteamVR.instance.hmd_DisplayFrequency), ref poseActionData, poseActionData_size, inputSourceHandle);
if (err != EVRInputError.None)
{
Debug.LogError("<b>[SteamVR]</b> GetPoseActionData error (" + fullPath + "): " + err.ToString() + " Handle: " + handle.ToString() + ". Input source: " + inputSource.ToString());
}
if (active)
{
SetCacheVariables();
changed = GetChanged();
}
if (changed)
changedTime = updateTime;
if (skipStateAndEventUpdates == false)
CheckAndSendEvents();
}
protected void SetCacheVariables()
{
localPosition = poseActionData.pose.mDeviceToAbsoluteTracking.GetPosition();
localRotation = poseActionData.pose.mDeviceToAbsoluteTracking.GetRotation();
velocity = GetUnityCoordinateVelocity(poseActionData.pose.vVelocity);
angularVelocity = GetUnityCoordinateAngularVelocity(poseActionData.pose.vAngularVelocity);
updateTime = Time.realtimeSinceStartup;
}
protected bool GetChanged()
{
if (Vector3.Distance(localPosition, lastLocalPosition) > changeTolerance)
return true;
else if (Mathf.Abs(Quaternion.Angle(localRotation, lastLocalRotation)) > changeTolerance)
return true;
else if (Vector3.Distance(velocity, lastVelocity) > changeTolerance)
return true;
else if (Vector3.Distance(angularVelocity, lastAngularVelocity) > changeTolerance)
return true;
return false;
}
/// <summary>
/// SteamVR 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 GetVelocitiesAtTimeOffset(float secondsFromNow, 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]</b> GetPoseActionData error (" + fullPath + "): " + err.ToString() + " handle: " + handle.ToString()); //todo: this should be an error
velocityAtTime = Vector3.zero;
angularVelocityAtTime = Vector3.zero;
return false;
}
velocityAtTime = GetUnityCoordinateVelocity(tempPoseActionData.pose.vVelocity);
angularVelocityAtTime = GetUnityCoordinateAngularVelocity(tempPoseActionData.pose.vAngularVelocity);
return true;
}
/// <summary>
/// SteamVR 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]</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>
/// Update a transform's local position and local roation to match the pose.
/// </summary>
/// <param name="transformToUpdate">The transform of the object to be updated</param>
public void UpdateTransform(Transform transformToUpdate)
{
transformToUpdate.localPosition = localPosition;
transformToUpdate.localRotation = localRotation;
}
protected virtual void CheckAndSendEvents()
{
if (trackingState != lastTrackingState && onTrackingChanged != null)
onTrackingChanged.Invoke(poseAction, inputSource, trackingState);
if (poseIsValid != lastPoseIsValid && onValidPoseChanged != null)
onValidPoseChanged.Invoke(poseAction, inputSource, poseIsValid);
if (deviceIsConnected != lastDeviceIsConnected && onDeviceConnectedChanged != null)
onDeviceConnectedChanged.Invoke(poseAction, inputSource, deviceIsConnected);
if (changed && onChange != null)
onChange.Invoke(poseAction, inputSource);
if (active != lastActive && onActiveChange != null)
onActiveChange.Invoke(poseAction, inputSource, active);
if (activeBinding != lastActiveBinding && onActiveBindingChange != null)
onActiveBindingChange.Invoke(poseAction, inputSource, activeBinding);
if (onUpdate != null)
onUpdate.Invoke(poseAction, inputSource);
}
protected Vector3 GetUnityCoordinateVelocity(HmdVector3_t vector)
{
return GetUnityCoordinateVelocity(vector.v0, vector.v1, vector.v2);
}
protected Vector3 GetUnityCoordinateAngularVelocity(HmdVector3_t vector)
{
return GetUnityCoordinateAngularVelocity(vector.v0, vector.v1, vector.v2);
}
protected Vector3 GetUnityCoordinateVelocity(float x, float y, float z)
{
Vector3 vector = new Vector3();
vector.x = x;
vector.y = y;
vector.z = -z;
return vector;
}
protected Vector3 GetUnityCoordinateAngularVelocity(float x, float y, float z)
{
Vector3 vector = new Vector3();
vector.x = -x;
vector.y = -y;
vector.z = z;
return vector;
}
}
/// <summary>
/// Boolean actions are either true or false. There is an onStateUp and onStateDown event for the rising and falling edge.
/// </summary>
public interface ISteamVR_Action_Pose : ISteamVR_Action_In_Source
{
/// <summary>The local position of this action relative to the universe origin</summary>
Vector3 localPosition { get; }
/// <summary>The local rotation of this action relative to the universe origin</summary>
Quaternion localRotation { get; }
/// <summary>The state of the tracking system that is used to create pose data (position, rotation, etc)</summary>
ETrackingResult trackingState { get; }
/// <summary>The local velocity of this pose relative to the universe origin</summary>
Vector3 velocity { get; }
/// <summary>The local angular velocity of this pose relative to the universe origin</summary>
Vector3 angularVelocity { get; }
/// <summary>True if the pose retrieved for this action and input source is valid (good data from the tracking source)</summary>
bool poseIsValid { get; }
/// <summary>True if the device bound to this action and input source is connected</summary>
bool deviceIsConnected { get; }
/// <summary>The local position for this pose during the previous update</summary>
Vector3 lastLocalPosition { get; }
/// <summary>The local rotation for this pose during the previous update</summary>
Quaternion lastLocalRotation { get; }
/// <summary>The tracking state for this pose during the previous update</summary>
ETrackingResult lastTrackingState { get; }
/// <summary>The velocity for this pose during the previous update</summary>
Vector3 lastVelocity { get; }
/// <summary>The angular velocity for this pose during the previous update</summary>
Vector3 lastAngularVelocity { get; }
/// <summary>True if the pose was valid during the previous update</summary>
bool lastPoseIsValid { get; }
/// <summary>True if the device bound to this action was connected during the previous update</summary>
bool lastDeviceIsConnected { get; }
}
}