Tanoda
InteractionBehaviour.cs
Go to the documentation of this file.
1/******************************************************************************
2 * Copyright (C) Ultraleap, Inc. 2011-2020. *
3 * *
4 * Use subject to the terms of the Apache License 2.0 available at *
5 * http://www.apache.org/licenses/LICENSE-2.0, or another agreement *
6 * between Ultraleap and you, your company or other organization. *
7 ******************************************************************************/
8
12using Leap.Unity.Query;
13using Leap.Unity.Space;
14using System;
15using System.Collections.Generic;
16using UnityEngine;
17
18namespace Leap.Unity.Interaction {
19
20 public enum ContactForceMode { Object, UI };
21
35 [RequireComponent(typeof(Rigidbody))]
36 public class InteractionBehaviour : MonoBehaviour, IInteractionBehaviour {
37
38 public const float MAX_ANGULAR_VELOCITY = 100F;
39
40 #region Public API
41
42 #region Hovering API
43
45 public bool isHovered { get { return _hoveringControllers.Count > 0; } }
46
53 get {
54 return _closestHoveringController;
55 }
56 }
57
60 get {
61 return _closestHoveringHand == null ? null
62 : _closestHoveringHand.leapHand;
63 }
64 }
65
71 get {
72 return _closestHoveringControllerDistance;
73 }
74 }
75
81 get {
82 return _hoveringControllers;
83 }
84 }
85
89 public bool isPrimaryHovered { get { return _primaryHoveringControllers.Count > 0; } }
90
99 get {
100 return _closestPrimaryHoveringController;
101 }
102 }
103
108 get {
109 return _primaryHoveringControllers;
110 }
111 }
112
120 get {
121 return _closestPrimaryHoveringHand == null ? null
122 : _closestPrimaryHoveringHand.leapHand;
123 }
124 }
125
132 get {
133 if (!isPrimaryHovered) return null;
134 return _closestPrimaryHoveringHand.leapHand
135 .Fingers[_closestPrimaryHoveringHand.primaryHoveringPointIndex];
136 }
137 }
138
146 get {
147 if (!isPrimaryHovered) return Vector3.zero;
149 }
150 }
151
159 public float primaryHoverDistance {
160 get {
161 if (!isPrimaryHovered) return float.PositiveInfinity;
163 }
164 }
165
166 #region Hover Events
167
176 public Action OnHoverBegin;
177
186 public Action OnHoverEnd;
187
196 public Action OnHoverStay;
197
206 public Action<InteractionController> OnPerControllerHoverBegin;
207
216 public Action<InteractionController> OnPerControllerHoverEnd;
217
218 #endregion
219
220 #region Primary Hover Events
221
230 public Action OnPrimaryHoverBegin;
231
240 public Action OnPrimaryHoverEnd;
241
250 public Action OnPrimaryHoverStay;
251
261 public Action<InteractionController> OnPerControllerPrimaryHoverBegin;
262
272 public Action<InteractionController> OnPerControllerPrimaryHoverEnd;
273
274 #endregion
275
276 #endregion
277
278 #region Grasping API
279
281 public bool isGrasped { get { return _graspingControllers.Count > 0; } }
282
290 public InteractionController graspingController { get { return _graspingControllers.Query().FirstOrDefault(); } }
291
296 public ReadonlyHashSet<InteractionController> graspingControllers { get { return _graspingControllers; } }
297
298 private HashSet<InteractionHand> _graspingHandsBuffer = new HashSet<InteractionHand>();
303 get {
304 _graspingHandsBuffer.Clear();
305 _graspingControllers.Query().OfType<InteractionHand>().FillHashSet(_graspingHandsBuffer);
306 return _graspingHandsBuffer;
307 }
308 }
309
315 public bool isSuspended { get { return _suspendingController != null; } }
316
330
331 #region Grasp Events
332
347 public GraspedMovementEvent OnGraspedMovement = (preSolvedPos, preSolvedRot,
348 solvedPos, solvedRot,
349 graspingControllers) => { };
350
358 public Action OnGraspBegin;
359
366 public Action OnGraspEnd;
367
378 public Action OnGraspStay;
379
390 public Action<InteractionController> OnPerControllerGraspBegin;
391
402 public Action<InteractionController> OnPerControllerGraspEnd;
403
415 public Action<InteractionController> OnSuspensionBegin;
416
426 public Action<InteractionController> OnSuspensionEnd;
427
428 #endregion
429
439 public bool ReleaseFromGrasp() {
440 if (isGrasped) {
442 return true;
443 }
444
445 return false;
446 }
447
453 public Vector3 GetGraspPoint(InteractionController intController) {
454 if (intController.graspedObject == this as IInteractionBehaviour) {
455 return intController.GetGraspPoint();
456 }
457 else {
458 Debug.LogError("Cannot get this object's grasp point: It is not currently grasped "
459 + "by the provided interaction controller.", intController);
460 return Vector3.zero;
461 }
462 }
463
464 #endregion
465
466 #region Contact API
467
473 get { return _contactingControllers; }
474 }
475
480 public Action OnContactBegin;
481
486 public Action OnContactEnd;
487
492 public Action OnContactStay;
493
497 public Action<InteractionController> OnPerControllerContactBegin;
498
502 public Action<InteractionController> OnPerControllerContactEnd;
503
504 #endregion
505
506 #region Forces API
507
517 public void AddLinearAcceleration(Vector3 acceleration) {
518 _appliedForces = true;
519 _accumulatedLinearAcceleration += acceleration;
520 }
521
532 public void AddAngularAcceleration(Vector3 acceleration) {
533 _appliedForces = true;
534 _accumulatedAngularAcceleration += acceleration;
535 }
536
537 #endregion
538
539 #region General API
540
545 public void SetKinematicWithoutGrasp(bool isKinematic) {
546 if (this.isGrasped) {
547 _wasKinematicBeforeGrasp = isKinematic;
548 }
549 else {
550 _rigidbody.isKinematic = isKinematic;
551 }
552 }
553
558 if (this.isGrasped) {
559 return _wasKinematicBeforeGrasp;
560 }
561 else {
562 return _rigidbody.isKinematic;
563 }
564 }
565
566 #endregion
567
568 #endregion
569
570 #region Inspector
571
572 [Tooltip("The Interaction Manager responsible for this interaction object.")]
573 [SerializeField]
574 private InteractionManager _manager;
576 get { return _manager; }
577 set {
578 if (Application.isPlaying) {
579 if (_manager != null && _manager.IsBehaviourRegistered(this)) {
580 _manager.UnregisterInteractionBehaviour(this);
581 }
582 }
583
584 _manager = value;
585
586 if (Application.isPlaying) {
587 if (_manager != null && !manager.IsBehaviourRegistered(this)) {
588 _manager.RegisterInteractionBehaviour(this);
589 }
590 }
591 }
592 }
593
594 private Rigidbody _rigidbody;
595 #if UNITY_EDITOR
596 new
597 #endif
599 public Rigidbody rigidbody {
600 get { return _rigidbody; }
601 protected set { _rigidbody = value; }
602 }
603
604 public ISpaceComponent space { get; protected set; }
605
606 [Header("Interaction Overrides")]
607
608 [Tooltip("This object will not receive callbacks from left controllers, right "
609 + "controllers, or either hand if this mode is set to anything other than "
610 + "None.")]
611 [SerializeField]
612 private IgnoreHoverMode _ignoreHoverMode = IgnoreHoverMode.None;
614 get { return _ignoreHoverMode; }
615 set {
616 _ignoreHoverMode = value;
617
618 if (_ignoreHoverMode != IgnoreHoverMode.None) {
619 ClearHoverTracking(onlyInvalidControllers: true);
620 }
621 }
622 }
623 [SerializeField, HideInInspector]
624 private bool _isIgnoringAllHoverState = false;
625
626 [Tooltip("Interaction controllers will not be able to mark this object as their "
627 + "primary hover if this property is checked. Primary hover requires hovering "
628 + "enabled to function, but it can be disabled independently of hovering.")]
629 [SerializeField]
630 [DisableIf("_isIgnoringAllHoverState", isEqualTo: true)]
631 private bool _ignorePrimaryHover = false;
632 public bool ignorePrimaryHover {
633 get { return _ignorePrimaryHover; }
634 set {
635 _ignorePrimaryHover = value;
636
637 if (_ignorePrimaryHover) {
639 }
640 }
641 }
642
643 [Tooltip("Interaction controllers will not be able to touch this object if this "
644 + "property is checked.")]
645 [SerializeField]
646 private bool _ignoreContact = false;
647 public bool ignoreContact {
648 get { return _ignoreContact; }
649 set {
650 _ignoreContact = value;
651
652 if (_ignoreContact) {
654 }
655 }
656 }
657
658 [Tooltip("Interaction controllers will not be able to grasp this object if this "
659 + "property is checked.")]
660 [SerializeField]
661 private bool _ignoreGrasping = false;
662 public bool ignoreGrasping {
663 get { return _ignoreGrasping; }
664 set {
665 _ignoreGrasping = value;
666
667 if (_ignoreGrasping && isGrasped) {
669 }
670 }
671 }
672
673 [Header("Contact Settings")]
674
675 [Tooltip("Determines how much force an interaction controller should apply to this "
676 + "object. For interface-style objects like buttons and sliders, choose UI. "
677 + "This will make the objects to feel lighter and more reactive to gentle "
678 + "touches; for normal physical objects, you'll almost always want Object.")]
679 [SerializeField]
680 private ContactForceMode _contactForceMode = ContactForceMode.Object;
682 get { return _contactForceMode; }
683 set { _contactForceMode = value; }
684 }
685
686 [Header("Grasp Settings")]
687
688 [Tooltip("Can this object be grasped simultaneously with two or more interaction "
689 + "controllers?")]
690 [SerializeField]
691 private bool _allowMultiGrasp = false;
692 public bool allowMultiGrasp {
693 get { return _allowMultiGrasp; }
694 set { _allowMultiGrasp = value; }
695 }
696
697 [Tooltip("Should interaction controllers move this object when it is grasped? "
698 + "Without this property checked, objects will still receive grasp callbacks, "
699 + "but you will need to move them manually via script.")]
700 [SerializeField]
701 [OnEditorChange("moveObjectWhenGrasped")]
702 private bool _moveObjectWhenGrasped = true;
704 get { return _moveObjectWhenGrasped; }
705 set {
706 if (_moveObjectWhenGrasped != value && value == false) {
707 if (graspedPoseHandler != null) {
709 }
710 }
711 _moveObjectWhenGrasped = value;
712 }
713 }
714
716 Inherit,
717 Kinematic,
718 Nonkinematic
719 }
720 [Tooltip("When the object is held by an interaction controller, how should it move to "
721 + "its new position? Nonkinematic bodies will collide with other Rigidbodies, "
722 + "so they might not reach the target position. Kinematic rigidbodies will "
723 + "always move to the target position, ignoring collisions. Inherit will "
724 + "simply use the isKinematic state of the Rigidbody from before it was "
725 + "grasped.")]
726 [DisableIf("_moveObjectWhenGrasped", isEqualTo: false)]
728
729 [Header("Layer Overrides")]
730
731 [SerializeField]
732 [OnEditorChange("overrideInteractionLayer")]
733 [Tooltip("If set to true, this interaction object will override the Interaction "
734 + "Manager's layer setting for its default layer. The interaction layer is "
735 + "used for an object when it is not grasped and not ignoring contact.")]
736 private bool _overrideInteractionLayer = false;
738 get {
739 return _overrideInteractionLayer;
740 }
741 set {
742 _overrideInteractionLayer = value;
743 }
744 }
745
746 [Tooltip("Sets the override layer to use for this object when it is not grasped and "
747 + "not ignoring contact.")]
748 [SerializeField]
749 private SingleLayer _interactionLayer;
751 get { return _interactionLayer; }
752 protected set { _interactionLayer = value; }
753 }
754
755 [SerializeField]
756 [OnEditorChange("overrideNoContactLayer")]
757 [Tooltip("If set to true, this interaction object will override the Interaction "
758 + "Manager's layer setting for its default no-contact layer. The no-contact "
759 + "layer should not collide with the contact bone layer; it is used when the "
760 + "interaction object is grasped or when it is ignoring contact.")]
761 private bool _overrideNoContactLayer = false;
763 get {
764 return _overrideNoContactLayer;
765 }
766 set {
767 _overrideNoContactLayer = value;
768 }
769 }
770
771 [Tooltip("Overrides the layer this interaction object should be on when it is grasped "
772 + "or ignoring contact. This layer should not collide with the contact bone "
773 + "layer -- the layer interaction controllers' colliders are on.")]
774 [SerializeField]
775 private SingleLayer _noContactLayer;
777 get { return _noContactLayer; }
778 protected set { _noContactLayer = value; }
779 }
780
781 #endregion
782
783 #region Unity Callbacks
784
785 protected virtual void OnValidate() {
786 rigidbody = GetComponent<Rigidbody>();
787
788 _isIgnoringAllHoverState = ignoreHoverMode == IgnoreHoverMode.Both;
789 if (_isIgnoringAllHoverState) _ignorePrimaryHover = true;
790 }
791
792 protected virtual void Awake() {
793 InitUnityEvents();
794
795 rigidbody = GetComponent<Rigidbody>();
796 rigidbody.maxAngularVelocity = MAX_ANGULAR_VELOCITY;
797 }
798
799 protected virtual void OnEnable() {
800 if (manager == null) {
802
803 if (manager == null) {
804 Debug.LogError("Interaction Behaviours require an Interaction Manager. Please "
805 + "ensure you have an InteractionManager in your scene.");
806 this.enabled = false;
807 }
808 }
809
810 if (manager != null && !manager.IsBehaviourRegistered(this)) {
812 }
813
814 // Make sure we have a list of all of this object's colliders.
816
817 // Refresh curved space. Currently a maximum of one (1) LeapSpace is supported per
818 // InteractionBehaviour.
819 foreach (var collider in _interactionColliders) {
820 var leapSpace = collider.transform.GetComponentInParent<ISpaceComponent>();
821 if (leapSpace != null) {
822 space = leapSpace;
823 break;
824 }
825 }
826
827 // Ensure physics layers are set up properly.
828 initLayers();
829 }
830
831 protected virtual void OnDisable() {
832 // Remove this object's layer tracking from the manager.
833 finalizeLayers();
834
835 if (manager != null && manager.IsBehaviourRegistered(this)) {
837 }
838 }
839
840 protected virtual void Start() {
841 // Check any Joint attachments to automatically be able to choose Kabsch pivot
842 // setting (grasping).
844 }
845
846 #endregion
847
853 public void FixedUpdateObject() {
854 fixedUpdateLayers();
855
856 if (_appliedForces) { FixedUpdateForces(); }
857 }
858
859 #region Hovering
860
861 private HashSet<InteractionController> _hoveringControllers = new HashSet<InteractionController>();
862
863 private InteractionController _closestHoveringController = null;
864 private float _closestHoveringControllerDistance = float.PositiveInfinity;
865 private InteractionHand _closestHoveringHand = null;
866
876 public virtual float GetHoverDistance(Vector3 worldPosition) {
877 float closestComparativeColliderDistance = float.PositiveInfinity;
878 bool hasColliders = false;
879 float testDistance = float.PositiveInfinity;
880
881 if (rigidbody == null) {
882 // The Interaction Object is probably being destroyed, or is otherwise in an
883 // invalid state.
884 return float.PositiveInfinity;
885 }
886
887 foreach (var collider in _interactionColliders) {
888 if (!hasColliders) hasColliders = true;
889
890 if (collider is MeshCollider) {
891 // Native, faster ClosestPoint, but no support for off-center colliders; use to
892 // support MeshColliders.
893 testDistance = (Physics.ClosestPoint(worldPosition,
894 collider,
895 collider.attachedRigidbody.position,
896 collider.attachedRigidbody.rotation)
897 - worldPosition).magnitude;
898 }
899 // Custom, slower ClosestPoint
900 else {
901 // Note: Should be using rigidbody position instead of transform; this will
902 // cause problems when colliders are moving very fast (one-frame delay).
903 testDistance = (collider.transform.TransformPoint(
904 collider.ClosestPointOnSurface(
905 collider.transform.InverseTransformPoint(worldPosition)))
906 - worldPosition).magnitude;
907 }
908
909 if (testDistance < closestComparativeColliderDistance) {
910 closestComparativeColliderDistance = testDistance;
911 }
912 }
913
914 if (!hasColliders) {
915 return (this.rigidbody.position - worldPosition).magnitude;
916 }
917 else {
918 return closestComparativeColliderDistance;
919 }
920 }
921
922 public void BeginHover(List<InteractionController> controllers) {
923 foreach (var controller in controllers) {
924 _hoveringControllers.Add(controller);
925 }
926
927 refreshClosestHoveringController();
928
929 foreach (var controller in controllers) {
930 OnPerControllerHoverBegin(controller);
931 }
932
933 if (_hoveringControllers.Count == controllers.Count) {
934 OnHoverBegin();
935 }
936 }
937
938 public void EndHover(List<InteractionController> controllers) {
939 foreach (var controller in controllers) {
940 _hoveringControllers.Remove(controller);
941 }
942
943 refreshClosestHoveringController();
944
945 foreach (var controller in controllers) {
946 OnPerControllerHoverEnd(controller);
947 }
948
949 if (_hoveringControllers.Count == 0) {
950 OnHoverEnd();
951 }
952 }
953
954 public void StayHovered(List<InteractionController> controllers) {
955 refreshClosestHoveringController();
956 OnHoverStay();
957 }
958
959 private void refreshClosestHoveringController() {
960 float closestControllerDistance = float.PositiveInfinity;
961 _closestHoveringController = getClosestController(_hoveringControllers,
962 out closestControllerDistance);
963 _closestHoveringControllerDistance = closestControllerDistance;
964
965 float closestHandDistance = float.PositiveInfinity;
966 _closestHoveringHand = getClosestController(_hoveringControllers,
967 out closestHandDistance,
968 controller => controller.intHand != null)
970 // closestHandDistance unused for now.
971 }
972
973 private InteractionController getClosestController(HashSet<InteractionController> controllers,
974 out float closestDistance,
975 Func<InteractionController, bool> filter = null) {
977 float closestHoveringControllerDist = float.PositiveInfinity;
978 foreach (var controller in controllers) {
979 if (filter != null && filter(controller) == false) continue;
980
981 float distance = GetHoverDistance(controller.hoverPoint);
982 if (closestHoveringHand == null
983 || distance < closestHoveringControllerDist) {
984 closestHoveringController = controller;
985 closestHoveringControllerDist = distance;
986 }
987 }
988
989 closestDistance = closestHoveringControllerDist;
991 }
992
1001 public void ClearHoverTracking(bool onlyInvalidControllers = false) {
1002 var tempControllers = Pool<HashSet<InteractionController>>.Spawn();
1003 try {
1004 foreach (var controller in hoveringControllers) {
1005 if (onlyInvalidControllers && this.ShouldIgnoreHover(controller)) {
1006 tempControllers.Add(controller);
1007 }
1008 }
1009
1010 foreach (var controller in tempControllers) {
1011 controller.ClearHoverTrackingForObject(this);
1012 }
1013 }
1014 finally {
1015 tempControllers.Clear();
1016 Pool<HashSet<InteractionController>>.Recycle(tempControllers);
1017 }
1018 }
1019
1020 private HashSet<InteractionController> _primaryHoveringControllers = new HashSet<InteractionController>();
1021 private InteractionController _closestPrimaryHoveringController = null;
1022 private InteractionHand _closestPrimaryHoveringHand = null;
1023
1024 public void BeginPrimaryHover(List<InteractionController> controllers) {
1025 foreach (var controller in controllers) {
1026 _primaryHoveringControllers.Add(controller);
1027 }
1028
1029 refreshClosestPrimaryHoveringController();
1030
1031 foreach (var controller in controllers) {
1033 }
1034
1035 if (_primaryHoveringControllers.Count == controllers.Count) {
1037 }
1038 }
1039
1040 public void EndPrimaryHover(List<InteractionController> controllers) {
1041 foreach (var controller in controllers) {
1042 _primaryHoveringControllers.Remove(controller);
1043 }
1044
1045 refreshClosestPrimaryHoveringController();
1046
1047 foreach (var controller in controllers) {
1049 }
1050
1051 if (_primaryHoveringControllers.Count == 0) {
1053 }
1054 }
1055
1056 public void StayPrimaryHovered(List<InteractionController> controllers) {
1057 refreshClosestPrimaryHoveringController();
1059 }
1060
1061 private void refreshClosestPrimaryHoveringController() {
1062 _closestPrimaryHoveringController = getClosestPrimaryHoveringController();
1063 _closestPrimaryHoveringHand = getClosestPrimaryHoveringController((controller) => controller.intHand != null) as InteractionHand;
1064 }
1065
1066 private InteractionController getClosestPrimaryHoveringController(Func<InteractionController, bool> filter = null) {
1067 InteractionController closestController = null;
1068 float closestDist = float.PositiveInfinity;
1069 foreach (var controller in _primaryHoveringControllers) {
1070 if (filter != null && filter(controller) == false) continue;
1071
1072 if (closestController == null || controller.primaryHoverDistance < closestDist) {
1073 closestController = controller;
1074 closestDist = controller.primaryHoverDistance;
1075 }
1076 }
1077 return closestController;
1078 }
1085 var tempControllers = Pool<HashSet<InteractionController>>.Spawn();
1086 try {
1087 foreach (var controller in primaryHoveringControllers) {
1088 tempControllers.Add(controller);
1089 }
1090
1091 foreach (var controller in tempControllers) {
1092 controller.ClearPrimaryHoverTracking();
1093 }
1094 }
1095 finally {
1096 tempControllers.Clear();
1097 Pool<HashSet<InteractionController>>.Recycle(tempControllers);
1098 }
1099 }
1100
1125 public List<Collider> primaryHoverColliders {
1126 get { return _interactionColliders; }
1127 }
1128
1129 #endregion
1130
1131 #region Contact
1132
1133 private HashSet<InteractionController> _contactingControllers = new HashSet<InteractionController>();
1134
1135 public void BeginContact(List<InteractionController> controllers) {
1136 foreach (var controller in controllers) {
1137 _contactingControllers.Add(controller);
1138
1139 OnPerControllerContactBegin(controller);
1140 }
1141
1142 if (_contactingControllers.Count == controllers.Count) {
1144 }
1145 }
1146
1147 public void EndContact(List<InteractionController> controllers) {
1148 foreach (var controller in controllers) {
1149 _contactingControllers.Remove(controller);
1150
1151 OnPerControllerContactEnd(controller);
1152 }
1153
1154 if (_contactingControllers.Count == 0) {
1155 OnContactEnd();
1156 }
1157 }
1158
1159 public void StayContacted(List<InteractionController> controllers) {
1160 OnContactStay();
1161 }
1162
1168 public void ClearContactTracking() {
1169 var tempControllers = Pool<HashSet<InteractionController>>.Spawn();
1170 try {
1171 foreach (var controller in contactingControllers) {
1172 tempControllers.Add(controller);
1173 }
1174
1175 foreach (var controller in tempControllers) {
1176 controller.ClearContactTrackingForObject(this);
1177 }
1178 }
1179 finally {
1180 tempControllers.Clear();
1181 Pool<HashSet<InteractionController>>.Recycle(tempControllers);
1182 }
1183 }
1184
1185 #endregion
1186
1187 #region Grasping
1188
1189 private HashSet<InteractionController> _graspingControllers = new HashSet<InteractionController>();
1190
1191 private bool _wasKinematicBeforeGrasp;
1192 private bool _justGrasped = false;
1193
1194 private float _dragBeforeGrasp = 0F;
1195 private float _angularDragBeforeGrasp = 0.05F;
1196
1197 private IGraspedPoseHandler _graspedPoseHandler;
1200 get {
1201 if (_graspedPoseHandler == null) {
1202 _graspedPoseHandler = new KabschGraspedPose(this);
1203 }
1204 return _graspedPoseHandler;
1205 }
1206 set {
1207 _graspedPoseHandler = value;
1208 }
1209 }
1210
1211 private KinematicGraspedMovement _lazyKinematicGraspedMovement;
1212 private KinematicGraspedMovement _kinematicGraspedMovement {
1213 get {
1214 if (_lazyKinematicGraspedMovement == null) {
1215 _lazyKinematicGraspedMovement = new KinematicGraspedMovement();
1216 }
1217 return _lazyKinematicGraspedMovement;
1218 }
1219 }
1220
1221 private NonKinematicGraspedMovement _lazyNonKinematicGraspedMovement;
1222 private NonKinematicGraspedMovement _nonKinematicGraspedMovement {
1223 get {
1224 if (_lazyNonKinematicGraspedMovement == null) {
1225 _lazyNonKinematicGraspedMovement = new NonKinematicGraspedMovement();
1226 }
1227 return _lazyNonKinematicGraspedMovement;
1228 }
1229 }
1230
1231 private IThrowHandler _throwHandler;
1234 get {
1235 if (_throwHandler == null) {
1236 _throwHandler = new SlidingWindowThrow();
1237 }
1238 return _throwHandler;
1239 }
1240 set {
1241 _throwHandler = value;
1242 }
1243 }
1244
1245 public void BeginGrasp(List<InteractionController> controllers) {
1246 _justGrasped = true;
1247
1248 // End suspension by ending the grasp on the suspending hand,
1249 // calling EndGrasp immediately.
1250 if (isSuspended) {
1252 }
1253
1254 // If multi-grasp is not allowed, release the old grasp.
1255 if (!allowMultiGrasp && isGrasped) {
1256 _graspingControllers.Query().First().ReleaseGrasp();
1257 }
1258
1259 // Add each newly grasping hand to internal reference and pose solver.
1260 foreach (var controller in controllers) {
1261 _graspingControllers.Add(controller);
1262
1265 }
1266
1267 // Fire interaction callback.
1268 OnPerControllerGraspBegin(controller);
1269 }
1270
1271 // If object wasn't grasped before, store rigidbody settings and
1272 // fire object interaction callback.
1273 if (_graspingControllers.Count == controllers.Count) {
1274
1275 // Remember drag settings pre-grasp, to be restored on release.
1276 _dragBeforeGrasp = rigidbody.drag;
1277 _angularDragBeforeGrasp = rigidbody.angularDrag;
1278
1279 // Remember kinematic state.
1280 _wasKinematicBeforeGrasp = rigidbody.isKinematic;
1281 switch (graspedMovementType) {
1282 case GraspedMovementType.Inherit: break; // no change
1283 case GraspedMovementType.Kinematic:
1284 rigidbody.isKinematic = true; break;
1285 case GraspedMovementType.Nonkinematic:
1286 rigidbody.isKinematic = false; break;
1287 }
1288
1289 // Set rigidbody drag/angular drag to zero.
1290 rigidbody.drag = 0F;
1291 rigidbody.angularDrag = 0F;
1292
1293 OnGraspBegin();
1294 }
1295 }
1296
1297 public void EndGrasp(List<InteractionController> controllers) {
1298 if (_graspingControllers.Count == controllers.Count && isSuspended) {
1299 // No grasped hands: Should not be suspended any more;
1300 // having been suspended also means we were only grasped by one hand
1301 EndSuspension(controllers[0]);
1302 }
1303
1304 foreach (var controller in controllers) {
1305 _graspingControllers.Remove(controller);
1306
1307 // Fire interaction callback.
1308 OnPerControllerGraspEnd(controller);
1309
1311 // Remove each hand from the pose solver.
1313 }
1314 }
1315
1316 // Possibly re-initialize the graspedPoseHandler.
1319
1320 foreach (var item in _graspingControllers) {
1322 }
1323 }
1324
1325 // If the object is no longer grasped by any hands, restore state and
1326 // activate throw handler.
1327 if (_graspingControllers.Count == 0) {
1328 // Restore drag settings from prior to the grasp.
1329 rigidbody.drag = _dragBeforeGrasp;
1330 rigidbody.angularDrag = _angularDragBeforeGrasp;
1331
1332 // Revert kinematic state.
1333 rigidbody.isKinematic = _wasKinematicBeforeGrasp;
1334
1335 if (controllers.Count == 1) {
1336 throwHandler.OnThrow(this, controllers.Query().First());
1337 }
1338
1339 OnGraspEnd();
1340
1341 if (_justGrasped) _justGrasped = false;
1342 }
1343 }
1344
1345 public void StayGrasped(List<InteractionController> controllers) {
1347 Vector3 origPosition = rigidbody.position;
1348 Quaternion origRotation = rigidbody.rotation;
1349 Vector3 newPosition;
1350 Quaternion newRotation;
1351
1352 graspedPoseHandler.GetGraspedPosition(out newPosition, out newRotation);
1353
1354 fixedUpdateGraspedMovement(new Pose(origPosition, origRotation),
1355 new Pose(newPosition, newRotation),
1356 controllers);
1357
1358 throwHandler.OnHold(this, controllers);
1359 }
1360
1361 OnGraspStay();
1362
1363 _justGrasped = false;
1364 }
1365
1366 protected virtual void fixedUpdateGraspedMovement(Pose origPose, Pose newPose,
1367 List<InteractionController> controllers) {
1368 IGraspedMovementHandler graspedMovementHandler
1369 = rigidbody.isKinematic ?
1370 (IGraspedMovementHandler)_kinematicGraspedMovement
1371 : (IGraspedMovementHandler)_nonKinematicGraspedMovement;
1372 graspedMovementHandler.MoveTo(newPose.position, newPose.rotation,
1373 this, _justGrasped);
1374
1375 OnGraspedMovement(origPose.position, origPose.rotation,
1376 newPose.position, newPose.rotation,
1377 controllers);
1378 }
1379
1381
1382 public void BeginSuspension(InteractionController controller) {
1383 _suspendingController = controller;
1384
1385 OnSuspensionBegin(controller);
1386 }
1387
1388 public void EndSuspension(InteractionController controller) {
1389 _suspendingController = null;
1390
1391 OnSuspensionEnd(controller);
1392 }
1393
1394 #endregion
1395
1396 #region Forces
1397
1398 private bool _appliedForces = false;
1399 protected Vector3 _accumulatedLinearAcceleration = Vector3.zero;
1400 protected Vector3 _accumulatedAngularAcceleration = Vector3.zero;
1401
1402 public void FixedUpdateForces() {
1403 if (!isGrasped) {
1404 //Only apply if non-zero to prevent waking up the body
1405 if (_accumulatedLinearAcceleration != Vector3.zero) {
1406 rigidbody.velocity += _accumulatedLinearAcceleration * Time.fixedDeltaTime;
1407 }
1408
1409 if (_accumulatedAngularAcceleration != Vector3.zero) {
1410 rigidbody.angularVelocity += _accumulatedAngularAcceleration * Time.fixedDeltaTime;
1411 }
1412
1413 //Reset so we can accumulate for the next frame
1414 _accumulatedLinearAcceleration = Vector3.zero;
1415 _accumulatedAngularAcceleration = Vector3.zero;
1416
1417 _appliedForces = false;
1418 }
1419 }
1420
1421 #endregion
1422
1423 #region Colliders
1424
1425 protected List<Collider> _interactionColliders = new List<Collider>();
1426
1437 Utils.FindColliders<Collider>(this.gameObject, _interactionColliders,
1438 includeInactiveObjects: false);
1439
1440 _interactionColliders.RemoveAll(
1441 c => c.GetComponent<IgnoreColliderForInteraction>() != null);
1442
1443 // Since the interaction colliders might have changed, or appeared for the first
1444 // time, set their layers appropriately.
1445 refreshInteractionColliderLayers();
1446 }
1447
1448 #endregion
1449
1450 #region Interaction Layers
1451
1452 private int _lastInteractionLayer = -1;
1453 private int _lastNoContactLayer = -1;
1454
1455 private void initLayers() {
1456 refreshInteractionLayer();
1457 refreshNoContactLayer();
1458
1459 (manager as IInternalInteractionManager).NotifyIntObjAddedInteractionLayer(this, interactionLayer, false);
1460 (manager as IInternalInteractionManager).NotifyIntObjAddedNoContactLayer(this, noContactLayer, false);
1461 (manager as IInternalInteractionManager).RefreshLayersNow();
1462
1463 _lastInteractionLayer = interactionLayer;
1464 _lastNoContactLayer = noContactLayer;
1465 }
1466
1467 private void refreshInteractionLayer() {
1470 }
1471
1472 private void refreshNoContactLayer() {
1475 }
1476
1477 private void fixedUpdateLayers() {
1478 using (new ProfilerSample("Interaction Behaviour: fixedUpdateLayers")) {
1479 int layer;
1480 refreshInteractionLayer();
1481 refreshNoContactLayer();
1482
1483 // Update the object's layer based on interaction state.
1484 if (ignoreContact) {
1485 layer = noContactLayer;
1486 }
1487 else {
1488 if (isGrasped) {
1489 layer = noContactLayer;
1490 }
1491 else {
1492 layer = interactionLayer;
1493 }
1494 }
1495 if (this.gameObject.layer != layer) {
1496 this.gameObject.layer = layer;
1497
1498 refreshInteractionColliderLayers();
1499 }
1500
1501 // Update the manager if necessary.
1502
1503 if (interactionLayer != _lastInteractionLayer) {
1504 (manager as IInternalInteractionManager).NotifyIntObjHasNewInteractionLayer(this, oldInteractionLayer: _lastInteractionLayer,
1505 newInteractionLayer: interactionLayer);
1506 _lastInteractionLayer = interactionLayer;
1507 }
1508
1509 if (noContactLayer != _lastNoContactLayer) {
1510 (manager as IInternalInteractionManager).NotifyIntObjHasNewNoContactLayer(this, oldNoContactLayer: _lastNoContactLayer,
1511 newNoContactLayer: noContactLayer);
1512 _lastNoContactLayer = noContactLayer;
1513 }
1514 }
1515 }
1516
1517 private void finalizeLayers() {
1518 (manager as IInternalInteractionManager).NotifyIntObjRemovedInteractionLayer(this, interactionLayer, false);
1519 (manager as IInternalInteractionManager).NotifyIntObjRemovedNoContactLayer(this, noContactLayer, false);
1520 (manager as IInternalInteractionManager).RefreshLayersNow();
1521 }
1522
1533 private void refreshInteractionColliderLayers() {
1534 for (int i = 0; i < _interactionColliders.Count; i++) {
1535 if (_interactionColliders[i].gameObject.layer != this.gameObject.layer) {
1536 _interactionColliders[i].gameObject.layer = this.gameObject.layer;
1537 }
1538 }
1539 }
1540
1541 #endregion
1542
1543 #region Locked Position (Joint) Checking
1544
1545 private bool _isPositionLocked = false;
1546
1559 public bool isPositionLocked { get { return _isPositionLocked; } }
1560
1567 if ((rigidbody.constraints & RigidbodyConstraints.FreezePositionX) > 0
1568 && (rigidbody.constraints & RigidbodyConstraints.FreezePositionY) > 0
1569 && (rigidbody.constraints & RigidbodyConstraints.FreezePositionZ) > 0) {
1570 _isPositionLocked = true;
1571 return;
1572 }
1573 else {
1574 _isPositionLocked = false;
1575
1576 Joint[] joints = rigidbody.GetComponents<Joint>();
1577 foreach (var joint in joints) {
1578 if (joint.connectedBody == null || joint.connectedBody.isKinematic) {
1579 if (joint is FixedJoint) {
1580 _isPositionLocked = true;
1581 return;
1582 }
1583 if (joint is HingeJoint) {
1584 _isPositionLocked = true;
1585 return;
1586 }
1587 // if (joint is SpringJoint) {
1588 // no check required; spring joints never fully lock position.
1589 // }
1590 if (joint is CharacterJoint) {
1591 _isPositionLocked = true;
1592 return;
1593 }
1594 ConfigurableJoint configJoint = joint as ConfigurableJoint;
1595 if (configJoint != null
1596 && (configJoint.xMotion == ConfigurableJointMotion.Locked
1597 || (configJoint.xMotion == ConfigurableJointMotion.Limited
1598 && configJoint.linearLimit.limit == 0F))
1599 && (configJoint.yMotion == ConfigurableJointMotion.Locked
1600 || (configJoint.yMotion == ConfigurableJointMotion.Limited
1601 && configJoint.linearLimit.limit == 0F))
1602 && (configJoint.zMotion == ConfigurableJointMotion.Locked
1603 || (configJoint.zMotion == ConfigurableJointMotion.Limited
1604 && configJoint.linearLimit.limit == 0F))) {
1605 _isPositionLocked = true;
1606 return;
1607 }
1608 }
1609 }
1610 }
1611 }
1612
1613 #endregion
1614
1615 #region Unity Events
1616
1617 [SerializeField]
1618 private EnumEventTable _eventTable;
1619
1620 public enum EventType {
1621 HoverBegin = 100,
1622 HoverEnd = 101,
1623 HoverStay = 102,
1624 PerControllerHoverBegin = 110,
1625 PerControllerHoverEnd = 111,
1626
1627 PrimaryHoverBegin = 120,
1628 PrimaryHoverEnd = 121,
1629 PrimaryHoverStay = 122,
1630 PerControllerPrimaryHoverBegin = 130,
1631 PerControllerPrimaryHoverEnd = 132,
1632
1633 GraspBegin = 140,
1634 GraspEnd = 141,
1635 GraspStay = 142,
1636 PerControllerGraspBegin = 150,
1637 PerControllerGraspEnd = 152,
1638
1639 SuspensionBegin = 160,
1640 SuspensionEnd = 161,
1641
1642 ContactBegin = 170,
1643 ContactEnd = 171,
1644 ContactStay = 172,
1645 PerControllerContactBegin = 180,
1646 PerControllerContactEnd = 181
1647 }
1648
1649 private void InitUnityEvents() {
1650 // If the interaction component is added at runtime, _eventTable won't have been
1651 // constructed yet.
1652 if (_eventTable == null) _eventTable = new EnumEventTable();
1653
1654 setupCallback(ref OnHoverBegin, EventType.HoverBegin);
1655 setupCallback(ref OnHoverEnd, EventType.HoverEnd);
1656 setupCallback(ref OnHoverStay, EventType.HoverStay);
1657 setupCallback(ref OnPerControllerHoverBegin, EventType.PerControllerHoverBegin);
1658 setupCallback(ref OnPerControllerHoverEnd, EventType.PerControllerHoverEnd);
1659
1660 setupCallback(ref OnPrimaryHoverBegin, EventType.PrimaryHoverBegin);
1661 setupCallback(ref OnPrimaryHoverEnd, EventType.PrimaryHoverEnd);
1662 setupCallback(ref OnPrimaryHoverStay, EventType.PrimaryHoverStay);
1663 setupCallback(ref OnPerControllerPrimaryHoverBegin, EventType.PerControllerPrimaryHoverBegin);
1664 setupCallback(ref OnPerControllerPrimaryHoverEnd, EventType.PerControllerPrimaryHoverEnd);
1665
1666 setupCallback(ref OnGraspBegin, EventType.GraspBegin);
1667 setupCallback(ref OnGraspEnd, EventType.GraspEnd);
1668 setupCallback(ref OnGraspStay, EventType.GraspStay);
1669 setupCallback(ref OnPerControllerGraspBegin, EventType.PerControllerGraspBegin);
1670 setupCallback(ref OnPerControllerGraspEnd, EventType.PerControllerGraspEnd);
1671
1672 setupCallback(ref OnSuspensionBegin, EventType.SuspensionBegin);
1673 setupCallback(ref OnSuspensionEnd, EventType.SuspensionEnd);
1674
1675 setupCallback(ref OnContactBegin, EventType.ContactBegin);
1676 setupCallback(ref OnContactEnd, EventType.ContactEnd);
1677 setupCallback(ref OnContactStay, EventType.ContactStay);
1678 setupCallback(ref OnPerControllerContactBegin, EventType.PerControllerContactBegin);
1679 setupCallback(ref OnPerControllerContactEnd, EventType.PerControllerContactEnd);
1680 }
1681
1682 private void setupCallback(ref Action action, EventType type) {
1683 if (_eventTable.HasUnityEvent((int)type)) {
1684 action += () => _eventTable.Invoke((int)type);
1685 }
1686 else {
1687 action += () => { };
1688 }
1689 }
1690
1691 private void setupCallback<T>(ref Action<T> action, EventType type) {
1692 if (_eventTable.HasUnityEvent((int)type)) {
1693 action += (h) => _eventTable.Invoke((int)type);
1694 }
1695 else {
1696 action += (h) => { };
1697 }
1698 }
1699
1700 #endregion
1701
1702 }
1703
1704}
UnityEngine.Debug Debug
Definition: TanodaServer.cs:19
Causes any Colliders located on the same GameObject to be ignored by the Interaction Engine....
The Finger class represents a tracked finger.
Definition: Finger.cs:20
The Hand class reports the physical characteristics of a detected hand.
Definition: Hand.cs:26
List< Finger > Fingers
The list of Finger objects detected in this frame that are attached to this hand, given in order from...
Definition: Hand.cs:159
bool HasUnityEvent(int enumValue)
void Invoke(int enumValue)
InteractionBehaviours are components that enable GameObjects to interact with interaction controllers...
Pose? latestScheduledGraspPose
Nonkinematic grasping motion applies clamped velocities to Interaction Behaviours when they are grasp...
ReadonlyHashSet< InteractionController > hoveringControllers
Gets all of the interaction controllers hovering near this object, whether they are Leap hands or sup...
bool ReleaseFromGrasp()
Releases this object from the interaction controller currently grasping it, if it is grasped,...
void StayPrimaryHovered(List< InteractionController > controllers)
Action< InteractionController > OnSuspensionBegin
Called when the interaction controller that is grasping this interaction object loses tracking....
Action OnPrimaryHoverStay
Called every fixed (physics) frame in which one or more interaction controllers is primarily hovering...
virtual float GetHoverDistance(Vector3 worldPosition)
Returns a comparative distance to this interaction object. Calculated by finding the smallest distanc...
void EndHover(List< InteractionController > controllers)
IGraspedPoseHandler graspedPoseHandler
Gets or sets the grasped pose handler for this Interaction object.
void SetKinematicWithoutGrasp(bool isKinematic)
Use this if you want to modify the isKinematic state of an interaction object while it is grasped; ot...
InteractionController primaryHoveringController
Gets the closest primary hovering interaction controller for this object, if it has one....
Action OnGraspStay
Called every fixed (physics) frame during which this object is grasped by one or more hands.
Action OnGraspBegin
Called when the object becomes grasped, if it was not already held by any interaction controllers on ...
void BeginSuspension(InteractionController controller)
void RefreshPositionLockedState()
Call this method if the InteractionBehaviour's Rigidbody becomes or unbecomes fully positionally lock...
IThrowHandler throwHandler
Gets or sets the throw handler for this Interaction object.
Action OnContactStay
Called every frame during which one or more interaction controllers is colliding with this object.
Action< InteractionController > OnSuspensionEnd
Called when an object ceases being suspended. An object is suspended if it is currently grasped by an...
Action< InteractionController > OnPerControllerHoverEnd
Called whenever an interaction controller leaves the hover activity radius around this interaction ob...
void StayContacted(List< InteractionController > controllers)
bool GetKinematicWithoutGrasp()
Use this to retrieve the isKinematic state of the interactino object ignoring any temporary modificat...
void StayGrasped(List< InteractionController > controllers)
Action< InteractionController > OnPerControllerContactBegin
Called whenever an interaction controller begins colliding with this object.
Action< InteractionController > OnPerControllerPrimaryHoverEnd
Called whenever an interaction controler (a Leap hand or supported VR controller) stops primarily hov...
ReadonlyHashSet< InteractionController > graspingControllers
Gets the set of all interaction controllers currently grasping this object. Interaction controllers i...
Rigidbody rigidbody
The Rigidbody associated with this interaction object.
void RefreshInteractionColliders()
Recursively searches the hierarchy of this Interaction object to find all of the Colliders that are a...
virtual void fixedUpdateGraspedMovement(Pose origPose, Pose newPose, List< InteractionController > controllers)
ReadonlyHashSet< InteractionController > contactingControllers
Gets a set of all InteractionControllers currently contacting this interaction object.
void EndGrasp(List< InteractionController > controllers)
bool isPrimaryHovered
Gets whether this object is the primary hover for any interaction controller.
void FixedUpdateObject()
The InteractionManager manually calls method this after all InteractionControllerBase objects are upd...
ReadonlyHashSet< InteractionHand > graspingHands
Gets a set of all Leap hands currently grasping this object.
void EndPrimaryHover(List< InteractionController > controllers)
void AddAngularAcceleration(Vector3 acceleration)
Adds an angular acceleration to the center of mass of this object. Use this instead of Rigidbody....
Action< InteractionController > OnPerControllerGraspEnd
Called whenever an interaction controller stops grasping this object.
Action< InteractionController > OnPerControllerPrimaryHoverBegin
Called whenever an interaction controller (a Leap hand or supported VR controller) begins primarily h...
Finger primaryHoveringFinger
Gets the finger that is currently primarily hovering over this object, of the closest primarily hover...
void ClearContactTracking()
Clears contact tracking for this object on any currently-contacting controllers. If the object is sti...
InteractionController graspingController
Gets the controller currently grasping this object. Warning: If allowMultigrasp is enabled on this ob...
void StayHovered(List< InteractionController > controllers)
Action OnContactEnd
Called when the object ceases colliding with any interaction controllers, if the object was collidi...
Action OnHoverStay
Called during every fixed (physics) frame in which one or more interaction controller is within the h...
void ClearPrimaryHoverTracking()
Clears primary hover tracking state for this object on all of the currently- primary-hovering control...
void BeginGrasp(List< InteractionController > controllers)
Action OnPrimaryHoverEnd
Called when the object ceases being the primary hover of any interaction controllers,...
Action OnHoverBegin
Called when the object becomes hovered by any nearby interaction controllers. The hover activity radi...
ReadonlyHashSet< InteractionController > primaryHoveringControllers
Gets the set of all interaction controllers primarily hovering over this object.
void EndSuspension(InteractionController controller)
Action OnGraspEnd
Called when the object is no longer grasped by any interaction controllers.
bool isPositionLocked
Returns whether the InteractionBehaviour has its position fully locked by its Rigidbody settings or b...
GraspedMovementEvent OnGraspedMovement
Called directly after this grasped object's Rigidbody has had its position and rotation set by its cu...
Action OnPrimaryHoverBegin
Called when the object becomes primarily hovered by any interaction controllers, if the object was no...
Action OnContactBegin
Called when this object begins colliding with any interaction controllers, if the object was not coll...
List< Collider > primaryHoverColliders
Gets the List of Colliders used for hover distance checking for this Interaction object....
bool isSuspended
Gets whether the object is currently suspended. An object is "suspended" if it is currently grasped b...
void BeginHover(List< InteractionController > controllers)
Vector3 GetGraspPoint(InteractionController intController)
Returns (approximately) where the argument hand is grasping this object. If the interaction controlle...
void EndContact(List< InteractionController > controllers)
bool isGrasped
Gets whether this object is grasped by any interaction controller.
void AddLinearAcceleration(Vector3 acceleration)
Adds a linear acceleration to the center of mass of this object. Use this instead of Rigidbody....
void BeginPrimaryHover(List< InteractionController > controllers)
bool isHovered
Gets whether any interaction controller is nearby.
void ClearHoverTracking(bool onlyInvalidControllers=false)
Clears hover tracking state for this object on all of the currently-hovering controllers....
Vector3 primaryHoveringControllerPoint
Gets the position of the primaryHoverPoint on the primary hovering interaction controller that is pri...
Hand primaryHoveringHand
Gets the primary hovering hand for this interaction object, if it has one. A hand is the primary hove...
float closestHoveringControllerDistance
Gets the distance from this object to the palm of the closest hand to this object,...
Hand closestHoveringHand
Gets the closest Leap hand to this object, or null if no hand is nearby.
InteractionController closestHoveringController
Gets the closest interaction controller to this object, or null if no controller is nearby....
Action< InteractionController > OnPerControllerContactEnd
Called whenever an interaction controller stops colliding with this object.
float primaryHoverDistance
Gets the distance to the primary hover point whose controller is primarily hovering over this object....
Action< InteractionController > OnPerControllerGraspBegin
Called whenever an interaction controller grasps this object.
Action< InteractionController > OnPerControllerHoverBegin
Called whenever an interaction controller enters the hover activity radius around this interaction ob...
Action OnHoverEnd
Called when the object stops being hovered by any nearby interaction controllers. The hover activity ...
void BeginContact(List< InteractionController > controllers)
bool ReleaseGrasp()
Releases the object this hand is holding and returns true if the hand was holding an object,...
Vector3 primaryHoveringPoint
Gets the position of the primary hovering point that is closest to its primary hovered object,...
int primaryHoveringPointIndex
Gets the index in the primaryHoverPoints array of the primary hover point that is currently closest t...
static void ReleaseGrasps(IInteractionBehaviour graspedObj, ReadonlyHashSet< InteractionController > controllers)
Helper static method for forcing multiple controllers to release their grasps on a single object simu...
abstract Vector3 GetGraspPoint()
Returns approximately where the controller is grasping the currently grasped InteractionBehaviour....
IInteractionBehaviour graspedObject
Gets the object the controller is currently grasping, or null if there is no such object.
float primaryHoverDistance
Gets the distance from the closest primary hover point on this controller to its primarily hovered ob...
Hand leapHand
Gets the last tracked state of the Leap hand.
bool UnregisterInteractionBehaviour(IInteractionBehaviour interactionObj)
Returns true if the Interaction Behaviour was registered with this manager; otherwise returns false....
bool IsBehaviourRegistered(IInteractionBehaviour interactionObj)
void RegisterInteractionBehaviour(IInteractionBehaviour interactionObj)
static InteractionManager instance
Often, only one InteractionManager is necessary per Unity scene. This property will contain that Inte...
This pose handler is the default implementation of IGraspedPoseHandler provided by the Interaction En...
This implementation of IGraspedMovementHandler moves its interaction object to a target position and ...
The sliding window throw handler implements a simple heuristic that provides a reasonably accurate me...
An IGraspedMovementHandler takes in a target position and rotation (a "pose", usually provided by an ...
void MoveTo(Vector3 solvedPosition, Quaternion solvedRotation, InteractionBehaviour interactionObj, bool justGrasped)
Called by an interaction object when its grasped pose handler has determined a target pose; this meth...
An IGraspedPoseHandler specifies where an object grasped by a Leap hand or controller (or multiple ha...
void ClearControllers()
Called e.g. if the InteractionBehaviour is set not to move while being grasped; this should clear any...
void GetGraspedPosition(out Vector3 position, out Quaternion rotation)
Calculate the best holding position and orientation given the current state of all InteractionControl...
void RemoveController(InteractionController controller)
Called when an InteractionController stops grasping a certain object; the controller should no longer...
void AddController(InteractionController controller)
Called when a new InteractionController begins grasping a certain object. The controller or Leap hand...
IInteractionBehaviour is the interface that defines all Interaction objects, specifying the minimum s...
Interaction objects feed their throw handlers callbacks when they are held (for data collection) and ...
void OnThrow(InteractionBehaviour intObj, InteractionController controller)
Called when an Interaction object is released by the last interaction controller holding it.
void OnHold(InteractionBehaviour intObj, ReadonlyList< InteractionController > controllers)
Called every FixedUpdate frame while an interaction object is being held.
delegate void GraspedMovementEvent(Vector3 oldPosition, Quaternion oldRotation, Vector3 newPosition, Quaternion newRotation, List< InteractionController > graspingControllers)
IgnoreHoverMode
Specified on a per-object basis to allow Interaction objects to ignore hover for the left hand,...
UnityEngine.Object Object
A position and rotation. You can multiply two poses; this acts like Matrix4x4 multiplication,...
Definition: Pose.cs:21
Quaternion rotation
Definition: Pose.cs:24
Vector3 position
Definition: Pose.cs:23
A simple wrapper around HashSet to provide readonly access. Useful when you want to return a HashSet ...
An object you can use to represent a single Unity layer as a dropdown in the inspector....
Definition: SingleLayer.cs:20