Advertisement
Inbal

Untitled

Aug 21st, 2019
696
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 77.71 KB | None | 0 0
  1. //======= Copyright (c) Valve Corporation, All rights reserved. ===============
  2. //
  3. // Purpose: The hands used by the player in the vr interaction system
  4. //
  5. //=============================================================================
  6.  
  7. using UnityEngine;
  8. using System;
  9. using System.Collections;
  10. using System.Collections.Generic;
  11. using System.Collections.ObjectModel;
  12. using UnityEngine.Events;
  13. using System.Threading;
  14. using Valve.VR.Extras;
  15.  
  16. namespace Valve.VR.InteractionSystem
  17. {
  18. //-------------------------------------------------------------------------
  19. // Links with an appropriate SteamVR controller and facilitates
  20. // interactions with objects in the virtual world.
  21. //-------------------------------------------------------------------------
  22. public class Hand : MonoBehaviour
  23. {
  24. // The flags used to determine how an object is attached to the hand.
  25. [Flags]
  26. public enum AttachmentFlags
  27. {
  28. SnapOnAttach = 1 << 0, // The object should snap to the position of the specified attachment point on the hand.
  29. DetachOthers = 1 << 1, // Other objects attached to this hand will be detached.
  30. DetachFromOtherHand = 1 << 2, // This object will be detached from the other hand.
  31. ParentToHand = 1 << 3, // The object will be parented to the hand.
  32. VelocityMovement = 1 << 4, // The object will attempt to move to match the position and rotation of the hand.
  33. TurnOnKinematic = 1 << 5, // The object will not respond to external physics.
  34. TurnOffGravity = 1 << 6, // The object will not respond to external physics.
  35. AllowSidegrade = 1 << 7, // The object is able to switch from a pinch grab to a grip grab. Decreases likelyhood of a good throw but also decreases likelyhood of accidental drop
  36. };
  37.  
  38. public const AttachmentFlags defaultAttachmentFlags = AttachmentFlags.ParentToHand |
  39. AttachmentFlags.DetachOthers |
  40. AttachmentFlags.DetachFromOtherHand |
  41. AttachmentFlags.TurnOnKinematic |
  42. AttachmentFlags.SnapOnAttach;
  43.  
  44.  
  45. // ADDED FOR TWO HAND INTERACTION START
  46.  
  47. Vector3 initialHandPosition1; // first hand position
  48. Vector3 initialHandPosition2; // second hand position
  49. Quaternion initialObjectRotation; // grabbed object rotation
  50. Vector3 initialObjectScale; // grabbed object scale
  51. Vector3 initialObjectDirection; // direction of object to midpoint of both hands
  52. public bool twoHandGrab = false; // bool, so you know when grabbed with 2 hands
  53.  
  54. // ADDED FOR TWO HAND INTERACTION END
  55.  
  56.  
  57. public Hand otherHand;
  58. public SteamVR_Input_Sources handType;
  59.  
  60. public SteamVR_Behaviour_Pose trackedObject;
  61.  
  62.  
  63. public SteamVR_Action_Boolean teleportAction = SteamVR_Input.GetAction<SteamVR_Action_Boolean>("Teleport");
  64.  
  65. public SteamVR_Action_Boolean grabPinchAction = SteamVR_Input.GetAction<SteamVR_Action_Boolean>("GrabPinch");
  66.  
  67. public SteamVR_Action_Boolean grabGripAction = SteamVR_Input.GetAction<SteamVR_Action_Boolean>("GrabGrip");
  68.  
  69. public SteamVR_Action_Vibration hapticAction = SteamVR_Input.GetAction<SteamVR_Action_Vibration>("Haptic");
  70.  
  71. public SteamVR_Action_Boolean uiInteractAction = SteamVR_Input.GetAction<SteamVR_Action_Boolean>("InteractUI");
  72.  
  73. public bool useHoverSphere = true;
  74. public Transform hoverSphereTransform;
  75. public float hoverSphereRadius = 0.05f;
  76. public LayerMask hoverLayerMask = -1;
  77. public float hoverUpdateInterval = 0.1f;
  78.  
  79. public bool useControllerHoverComponent = true;
  80. public string controllerHoverComponent = "tip";
  81. public float controllerHoverRadius = 0.075f;
  82.  
  83. public bool useFingerJointHover = true;
  84. public SteamVR_Skeleton_JointIndexEnum fingerJointHover = SteamVR_Skeleton_JointIndexEnum.indexTip;
  85. public float fingerJointHoverRadius = 0.025f;
  86.  
  87. [Tooltip("A transform on the hand to center attached objects on")]
  88. public Transform objectAttachmentPoint;
  89.  
  90. public Camera noSteamVRFallbackCamera;
  91. public float noSteamVRFallbackMaxDistanceNoItem = 10.0f;
  92. public float noSteamVRFallbackMaxDistanceWithItem = 0.5f;
  93. private float noSteamVRFallbackInteractorDistance = -1.0f;
  94.  
  95. public GameObject renderModelPrefab;
  96. protected List<RenderModel> renderModels = new List<RenderModel>();
  97. protected RenderModel mainRenderModel;
  98. protected RenderModel hoverhighlightRenderModel;
  99.  
  100. public bool showDebugText = false;
  101. public bool spewDebugText = false;
  102. public bool showDebugInteractables = false;
  103.  
  104. public struct AttachedObject
  105. {
  106. public GameObject attachedObject;
  107. public Interactable interactable;
  108. public Rigidbody attachedRigidbody;
  109. public CollisionDetectionMode collisionDetectionMode;
  110. public bool attachedRigidbodyWasKinematic;
  111. public bool attachedRigidbodyUsedGravity;
  112. public GameObject originalParent;
  113. public bool isParentedToHand;
  114. public GrabTypes grabbedWithType;
  115. public AttachmentFlags attachmentFlags;
  116. public Vector3 initialPositionalOffset;
  117. public Quaternion initialRotationalOffset;
  118. public Transform attachedOffsetTransform;
  119. public Transform handAttachmentPointTransform;
  120. public Vector3 easeSourcePosition;
  121. public Quaternion easeSourceRotation;
  122. public float attachTime;
  123.  
  124. public bool HasAttachFlag(AttachmentFlags flag)
  125. {
  126. return (attachmentFlags & flag) == flag;
  127. }
  128. }
  129.  
  130. private List<AttachedObject> attachedObjects = new List<AttachedObject>();
  131.  
  132. public ReadOnlyCollection<AttachedObject> AttachedObjects
  133. {
  134. get { return attachedObjects.AsReadOnly(); }
  135. }
  136.  
  137. public bool hoverLocked { get; private set; }
  138.  
  139. private Interactable _hoveringInteractable;
  140.  
  141. private TextMesh debugText;
  142. private int prevOverlappingColliders = 0;
  143.  
  144. private const int ColliderArraySize = 16;
  145. private Collider[] overlappingColliders;
  146.  
  147. private Player playerInstance;
  148.  
  149. private GameObject applicationLostFocusObject;
  150.  
  151. private SteamVR_Events.Action inputFocusAction;
  152.  
  153. public bool isActive
  154. {
  155. get
  156. {
  157. if (trackedObject != null)
  158. return trackedObject.isActive;
  159.  
  160. return this.gameObject.activeInHierarchy;
  161. }
  162. }
  163.  
  164. public bool isPoseValid
  165. {
  166. get
  167. {
  168. return trackedObject.isValid;
  169. }
  170. }
  171.  
  172.  
  173. //-------------------------------------------------
  174. // The Interactable object this Hand is currently hovering over
  175. //-------------------------------------------------
  176. public Interactable hoveringInteractable
  177. {
  178. get { return _hoveringInteractable; }
  179. set
  180. {
  181. if (_hoveringInteractable != value)
  182. {
  183. if (_hoveringInteractable != null)
  184. {
  185. if (spewDebugText)
  186. HandDebugLog("HoverEnd " + _hoveringInteractable.gameObject);
  187. _hoveringInteractable.SendMessage("OnHandHoverEnd", this, SendMessageOptions.DontRequireReceiver);
  188.  
  189. //Note: The _hoveringInteractable can change after sending the OnHandHoverEnd message so we need to check it again before broadcasting this message
  190. if (_hoveringInteractable != null)
  191. {
  192. this.BroadcastMessage("OnParentHandHoverEnd", _hoveringInteractable, SendMessageOptions.DontRequireReceiver); // let objects attached to the hand know that a hover has ended
  193. }
  194. }
  195.  
  196. _hoveringInteractable = value;
  197.  
  198. if (_hoveringInteractable != null)
  199. {
  200. if (spewDebugText)
  201. HandDebugLog("HoverBegin " + _hoveringInteractable.gameObject);
  202. _hoveringInteractable.SendMessage("OnHandHoverBegin", this, SendMessageOptions.DontRequireReceiver);
  203.  
  204. //Note: The _hoveringInteractable can change after sending the OnHandHoverBegin message so we need to check it again before broadcasting this message
  205. if (_hoveringInteractable != null)
  206. {
  207. this.BroadcastMessage("OnParentHandHoverBegin", _hoveringInteractable, SendMessageOptions.DontRequireReceiver); // let objects attached to the hand know that a hover has begun
  208. }
  209. }
  210. }
  211. }
  212. }
  213.  
  214.  
  215. //-------------------------------------------------
  216. // Active GameObject attached to this Hand
  217. //-------------------------------------------------
  218. public GameObject currentAttachedObject
  219. {
  220. get
  221. {
  222. CleanUpAttachedObjectStack();
  223.  
  224. if (attachedObjects.Count > 0)
  225. {
  226. return attachedObjects[attachedObjects.Count - 1].attachedObject;
  227. }
  228.  
  229. return null;
  230. }
  231. }
  232.  
  233. public AttachedObject? currentAttachedObjectInfo
  234. {
  235. get
  236. {
  237. CleanUpAttachedObjectStack();
  238.  
  239. if (attachedObjects.Count > 0)
  240. {
  241. return attachedObjects[attachedObjects.Count - 1];
  242. }
  243.  
  244. return null;
  245. }
  246. }
  247.  
  248. public SteamVR_Behaviour_Skeleton skeleton
  249. {
  250. get
  251. {
  252. if (mainRenderModel != null)
  253. return mainRenderModel.GetSkeleton();
  254.  
  255. return null;
  256. }
  257. }
  258.  
  259. public void ShowController(bool permanent = false)
  260. {
  261. if (mainRenderModel != null)
  262. mainRenderModel.SetControllerVisibility(true, permanent);
  263.  
  264. if (hoverhighlightRenderModel != null)
  265. hoverhighlightRenderModel.SetControllerVisibility(true, permanent);
  266. }
  267.  
  268. public void HideController(bool permanent = false)
  269. {
  270. if (mainRenderModel != null)
  271. mainRenderModel.SetControllerVisibility(false, permanent);
  272.  
  273. if (hoverhighlightRenderModel != null)
  274. hoverhighlightRenderModel.SetControllerVisibility(false, permanent);
  275. }
  276.  
  277. public void ShowSkeleton(bool permanent = false)
  278. {
  279. if (mainRenderModel != null)
  280. mainRenderModel.SetHandVisibility(true, permanent);
  281.  
  282. if (hoverhighlightRenderModel != null)
  283. hoverhighlightRenderModel.SetHandVisibility(true, permanent);
  284. }
  285.  
  286. public void HideSkeleton(bool permanent = false)
  287. {
  288. if (mainRenderModel != null)
  289. mainRenderModel.SetHandVisibility(false, permanent);
  290.  
  291. if (hoverhighlightRenderModel != null)
  292. hoverhighlightRenderModel.SetHandVisibility(false, permanent);
  293. }
  294.  
  295. public bool HasSkeleton()
  296. {
  297. return mainRenderModel != null && mainRenderModel.GetSkeleton() != null;
  298. }
  299.  
  300. public void Show()
  301. {
  302. SetVisibility(true);
  303. }
  304.  
  305. public void Hide()
  306. {
  307. SetVisibility(false);
  308. }
  309.  
  310. public void SetVisibility(bool visible)
  311. {
  312. if (mainRenderModel != null)
  313. mainRenderModel.SetVisibility(visible);
  314. }
  315.  
  316. public void SetSkeletonRangeOfMotion(EVRSkeletalMotionRange newRangeOfMotion, float blendOverSeconds = 0.1f)
  317. {
  318. for (int renderModelIndex = 0; renderModelIndex < renderModels.Count; renderModelIndex++)
  319. {
  320. renderModels[renderModelIndex].SetSkeletonRangeOfMotion(newRangeOfMotion, blendOverSeconds);
  321. }
  322. }
  323.  
  324. public void SetTemporarySkeletonRangeOfMotion(SkeletalMotionRangeChange temporaryRangeOfMotionChange, float blendOverSeconds = 0.1f)
  325. {
  326. for (int renderModelIndex = 0; renderModelIndex < renderModels.Count; renderModelIndex++)
  327. {
  328. renderModels[renderModelIndex].SetTemporarySkeletonRangeOfMotion(temporaryRangeOfMotionChange, blendOverSeconds);
  329. }
  330. }
  331.  
  332. public void ResetTemporarySkeletonRangeOfMotion(float blendOverSeconds = 0.1f)
  333. {
  334. for (int renderModelIndex = 0; renderModelIndex < renderModels.Count; renderModelIndex++)
  335. {
  336. renderModels[renderModelIndex].ResetTemporarySkeletonRangeOfMotion(blendOverSeconds);
  337. }
  338. }
  339.  
  340. public void SetAnimationState(int stateValue)
  341. {
  342. for (int renderModelIndex = 0; renderModelIndex < renderModels.Count; renderModelIndex++)
  343. {
  344. renderModels[renderModelIndex].SetAnimationState(stateValue);
  345. }
  346. }
  347.  
  348. public void StopAnimation()
  349. {
  350. for (int renderModelIndex = 0; renderModelIndex < renderModels.Count; renderModelIndex++)
  351. {
  352. renderModels[renderModelIndex].StopAnimation();
  353. }
  354. }
  355.  
  356.  
  357. //-------------------------------------------------
  358. // Attach a GameObject to this GameObject
  359. //
  360. // objectToAttach - The GameObject to attach
  361. // flags - The flags to use for attaching the object
  362. // attachmentPoint - Name of the GameObject in the hierarchy of this Hand which should act as the attachment point for this GameObject
  363. //-------------------------------------------------
  364. public void AttachObject(GameObject objectToAttach, GrabTypes grabbedWithType, AttachmentFlags flags = defaultAttachmentFlags, Transform attachmentOffset = null)
  365. {
  366.  
  367. AttachedObject attachedObject = new AttachedObject();
  368. attachedObject.attachmentFlags = flags;
  369. attachedObject.attachedOffsetTransform = attachmentOffset;
  370. attachedObject.attachTime = Time.time;
  371.  
  372. // ADDED FOR TWO HAND INTERACTION START
  373. if (otherHand.ObjectIsAttached(objectToAttach))
  374. {
  375.  
  376. initialHandPosition1 = trackedObject.transform.position;
  377. initialHandPosition2 = otherHand.trackedObject.transform.position;
  378. initialObjectRotation = objectToAttach.transform.rotation;
  379. initialObjectScale = objectToAttach.transform.localScale;
  380. initialObjectDirection = objectToAttach.transform.position - (initialHandPosition1 + initialHandPosition2) * 0.5f;
  381.  
  382. otherHand.currentAttachedObject.transform.parent = null; // unset parent (the first hand), so it's moving freely
  383. AttachedObject objInfo = otherHand.getAttachedObjectInfo(objectToAttach); // get first hand object attachInfo
  384.  
  385. if (objInfo.attachedObject != null)
  386. {
  387. objInfo.attachmentFlags &= ~AttachmentFlags.ParentToHand; // negate the ParentToHand flag
  388. objInfo.isParentedToHand = false; // set parentToHand variable false
  389. otherHand.replaceAttachedObjectInfo(objInfo, objectToAttach); // replace object attachInfo
  390. }
  391.  
  392. attachedObject.attachmentFlags &= ~(AttachmentFlags.ParentToHand | AttachmentFlags.SnapOnAttach | AttachmentFlags.DetachFromOtherHand); // negate the ParentToHand, SnapOnAttach and DetachFromOtherHand flags
  393.  
  394. twoHandGrab = true; // bool, so you know grabbed with 2 hands
  395. }
  396. // ADDED FOR TWO HAND INTERACTION END
  397.  
  398. if (flags == 0)
  399. {
  400. flags = defaultAttachmentFlags;
  401. }
  402.  
  403. //Make sure top object on stack is non-null
  404. CleanUpAttachedObjectStack();
  405.  
  406. //Detach the object if it is already attached so that it can get re-attached at the top of the stack
  407. if (ObjectIsAttached(objectToAttach))
  408. DetachObject(objectToAttach);
  409.  
  410. //Detach from the other hand if requested
  411. if (attachedObject.HasAttachFlag(AttachmentFlags.DetachFromOtherHand))
  412. {
  413. if (otherHand != null)
  414. otherHand.DetachObject(objectToAttach);
  415. }
  416.  
  417. if (attachedObject.HasAttachFlag(AttachmentFlags.DetachOthers))
  418. {
  419. //Detach all the objects from the stack
  420. while (attachedObjects.Count > 0)
  421. {
  422. DetachObject(attachedObjects[0].attachedObject);
  423. }
  424. }
  425.  
  426. if (currentAttachedObject)
  427. {
  428. currentAttachedObject.SendMessage("OnHandFocusLost", this, SendMessageOptions.DontRequireReceiver);
  429. }
  430.  
  431. attachedObject.attachedObject = objectToAttach;
  432. attachedObject.interactable = objectToAttach.GetComponent<Interactable>();
  433. attachedObject.handAttachmentPointTransform = this.transform;
  434.  
  435. if (attachedObject.interactable != null)
  436. {
  437.  
  438. if (attachedObject.interactable.attachEaseIn)
  439. {
  440. attachedObject.easeSourcePosition = attachedObject.attachedObject.transform.position;
  441. attachedObject.easeSourceRotation = attachedObject.attachedObject.transform.rotation;
  442. attachedObject.interactable.snapAttachEaseInCompleted = false;
  443. }
  444.  
  445. if (attachedObject.interactable.useHandObjectAttachmentPoint)
  446. attachedObject.handAttachmentPointTransform = objectAttachmentPoint;
  447.  
  448. if (attachedObject.interactable.hideHandOnAttach)
  449. Hide();
  450.  
  451. if (attachedObject.interactable.hideSkeletonOnAttach && mainRenderModel != null && mainRenderModel.displayHandByDefault)
  452. HideSkeleton();
  453.  
  454. if (attachedObject.interactable.hideControllerOnAttach && mainRenderModel != null && mainRenderModel.displayControllerByDefault)
  455. HideController();
  456.  
  457. if (attachedObject.interactable.handAnimationOnPickup != 0)
  458. SetAnimationState(attachedObject.interactable.handAnimationOnPickup);
  459.  
  460. if (attachedObject.interactable.setRangeOfMotionOnPickup != SkeletalMotionRangeChange.None)
  461. SetTemporarySkeletonRangeOfMotion(attachedObject.interactable.setRangeOfMotionOnPickup);
  462.  
  463. }
  464.  
  465. attachedObject.originalParent = objectToAttach.transform.parent != null ? objectToAttach.transform.parent.gameObject : null;
  466.  
  467. attachedObject.attachedRigidbody = objectToAttach.GetComponent<Rigidbody>();
  468. if (attachedObject.attachedRigidbody != null)
  469. {
  470. if (attachedObject.interactable.attachedToHand != null) //already attached to another hand
  471. {
  472. //if it was attached to another hand, get the flags from that hand
  473.  
  474. for (int attachedIndex = 0; attachedIndex < attachedObject.interactable.attachedToHand.attachedObjects.Count; attachedIndex++)
  475. {
  476. AttachedObject attachedObjectInList = attachedObject.interactable.attachedToHand.attachedObjects[attachedIndex];
  477. if (attachedObjectInList.interactable == attachedObject.interactable)
  478. {
  479. attachedObject.attachedRigidbodyWasKinematic = attachedObjectInList.attachedRigidbodyWasKinematic;
  480. attachedObject.attachedRigidbodyUsedGravity = attachedObjectInList.attachedRigidbodyUsedGravity;
  481. attachedObject.originalParent = attachedObjectInList.originalParent;
  482. }
  483. }
  484. }
  485. else
  486. {
  487. attachedObject.attachedRigidbodyWasKinematic = attachedObject.attachedRigidbody.isKinematic;
  488. attachedObject.attachedRigidbodyUsedGravity = attachedObject.attachedRigidbody.useGravity;
  489. }
  490. }
  491.  
  492. attachedObject.grabbedWithType = grabbedWithType;
  493.  
  494. if (attachedObject.HasAttachFlag(AttachmentFlags.ParentToHand))
  495. {
  496. //Parent the object to the hand
  497. objectToAttach.transform.parent = this.transform;
  498. attachedObject.isParentedToHand = true;
  499. }
  500. else
  501. {
  502. attachedObject.isParentedToHand = false;
  503. }
  504.  
  505. if (attachedObject.HasAttachFlag(AttachmentFlags.SnapOnAttach))
  506. {
  507. if (attachedObject.interactable != null && attachedObject.interactable.skeletonPoser != null && HasSkeleton())
  508. {
  509. SteamVR_Skeleton_PoseSnapshot pose = attachedObject.interactable.skeletonPoser.GetBlendedPose(skeleton);
  510.  
  511. //snap the object to the center of the attach point
  512. objectToAttach.transform.position = this.transform.TransformPoint(pose.position);
  513. objectToAttach.transform.rotation = this.transform.rotation * pose.rotation;
  514.  
  515. attachedObject.initialPositionalOffset = attachedObject.handAttachmentPointTransform.InverseTransformPoint(objectToAttach.transform.position);
  516. attachedObject.initialRotationalOffset = Quaternion.Inverse(attachedObject.handAttachmentPointTransform.rotation) * objectToAttach.transform.rotation;
  517. }
  518. else
  519. {
  520. if (attachmentOffset != null)
  521. {
  522. //offset the object from the hand by the positional and rotational difference between the offset transform and the attached object
  523. Quaternion rotDiff = Quaternion.Inverse(attachmentOffset.transform.rotation) * objectToAttach.transform.rotation;
  524. objectToAttach.transform.rotation = attachedObject.handAttachmentPointTransform.rotation * rotDiff;
  525.  
  526. Vector3 posDiff = objectToAttach.transform.position - attachmentOffset.transform.position;
  527. objectToAttach.transform.position = attachedObject.handAttachmentPointTransform.position + posDiff;
  528. }
  529. else
  530. {
  531. //snap the object to the center of the attach point
  532. objectToAttach.transform.rotation = attachedObject.handAttachmentPointTransform.rotation;
  533. objectToAttach.transform.position = attachedObject.handAttachmentPointTransform.position;
  534. }
  535.  
  536. Transform followPoint = objectToAttach.transform;
  537.  
  538. attachedObject.initialPositionalOffset = attachedObject.handAttachmentPointTransform.InverseTransformPoint(followPoint.position);
  539. attachedObject.initialRotationalOffset = Quaternion.Inverse(attachedObject.handAttachmentPointTransform.rotation) * followPoint.rotation;
  540. }
  541. }
  542. else
  543. {
  544. if (attachedObject.interactable != null && attachedObject.interactable.skeletonPoser != null && HasSkeleton())
  545. {
  546. attachedObject.initialPositionalOffset = attachedObject.handAttachmentPointTransform.InverseTransformPoint(objectToAttach.transform.position);
  547. attachedObject.initialRotationalOffset = Quaternion.Inverse(attachedObject.handAttachmentPointTransform.rotation) * objectToAttach.transform.rotation;
  548. }
  549. else
  550. {
  551. if (attachmentOffset != null)
  552. {
  553. //get the initial positional and rotational offsets between the hand and the offset transform
  554. Quaternion rotDiff = Quaternion.Inverse(attachmentOffset.transform.rotation) * objectToAttach.transform.rotation;
  555. Quaternion targetRotation = attachedObject.handAttachmentPointTransform.rotation * rotDiff;
  556. Quaternion rotationPositionBy = targetRotation * Quaternion.Inverse(objectToAttach.transform.rotation);
  557.  
  558. Vector3 posDiff = (rotationPositionBy * objectToAttach.transform.position) - (rotationPositionBy * attachmentOffset.transform.position);
  559.  
  560. attachedObject.initialPositionalOffset = attachedObject.handAttachmentPointTransform.InverseTransformPoint(attachedObject.handAttachmentPointTransform.position + posDiff);
  561. attachedObject.initialRotationalOffset = Quaternion.Inverse(attachedObject.handAttachmentPointTransform.rotation) * (attachedObject.handAttachmentPointTransform.rotation * rotDiff);
  562. }
  563. else
  564. {
  565. attachedObject.initialPositionalOffset = attachedObject.handAttachmentPointTransform.InverseTransformPoint(objectToAttach.transform.position);
  566. attachedObject.initialRotationalOffset = Quaternion.Inverse(attachedObject.handAttachmentPointTransform.rotation) * objectToAttach.transform.rotation;
  567. }
  568. }
  569. }
  570.  
  571.  
  572.  
  573. if (attachedObject.HasAttachFlag(AttachmentFlags.TurnOnKinematic))
  574. {
  575. if (attachedObject.attachedRigidbody != null)
  576. {
  577. attachedObject.collisionDetectionMode = attachedObject.attachedRigidbody.collisionDetectionMode;
  578. if (attachedObject.collisionDetectionMode == CollisionDetectionMode.Continuous)
  579. attachedObject.attachedRigidbody.collisionDetectionMode = CollisionDetectionMode.Discrete;
  580.  
  581. attachedObject.attachedRigidbody.isKinematic = true;
  582. }
  583. }
  584.  
  585. if (attachedObject.HasAttachFlag(AttachmentFlags.TurnOffGravity))
  586. {
  587. if (attachedObject.attachedRigidbody != null)
  588. {
  589. attachedObject.attachedRigidbody.useGravity = false;
  590. }
  591. }
  592.  
  593. if (attachedObject.interactable != null && attachedObject.interactable.attachEaseIn)
  594. {
  595. attachedObject.attachedObject.transform.position = attachedObject.easeSourcePosition;
  596. attachedObject.attachedObject.transform.rotation = attachedObject.easeSourceRotation;
  597. }
  598.  
  599. attachedObjects.Add(attachedObject);
  600.  
  601. UpdateHovering();
  602.  
  603. if (spewDebugText)
  604. HandDebugLog("AttachObject " + objectToAttach);
  605. objectToAttach.SendMessage("OnAttachedToHand", this, SendMessageOptions.DontRequireReceiver);
  606. }
  607.  
  608. private void replaceAttachedObjectInfo(AttachedObject objInfo, GameObject objectToAttach)
  609. {
  610. throw new NotImplementedException();
  611. }
  612.  
  613. public bool ObjectIsAttached(GameObject go)
  614. {
  615. for (int attachedIndex = 0; attachedIndex < attachedObjects.Count; attachedIndex++)
  616. {
  617. if (attachedObjects[attachedIndex].attachedObject == go)
  618. return true;
  619. }
  620.  
  621. return false;
  622. }
  623.  
  624. public void ForceHoverUnlock()
  625. {
  626. hoverLocked = false;
  627. }
  628.  
  629. internal void ResetAttachedTransform(AttachedObject value)
  630. {
  631. throw new NotImplementedException();
  632. }
  633.  
  634. //-------------------------------------------------
  635. // Detach this GameObject from the attached object stack of this Hand
  636. //
  637. // objectToDetach - The GameObject to detach from this Hand
  638. //-------------------------------------------------
  639. public void DetachObject(GameObject objectToDetach, bool restoreOriginalParent = true)
  640. {
  641. int index = attachedObjects.FindIndex(l => l.attachedObject == objectToDetach);
  642. if (index != -1)
  643. {
  644. if (spewDebugText)
  645. HandDebugLog("DetachObject " + objectToDetach);
  646.  
  647. Debug.Log("OnDetachObject");
  648.  
  649. GameObject prevTopObject = currentAttachedObject;
  650.  
  651.  
  652.  
  653. if (attachedObjects[index].interactable != null)
  654. {
  655. if (attachedObjects[index].interactable.hideHandOnAttach)
  656. Show();
  657.  
  658. if (attachedObjects[index].interactable.hideSkeletonOnAttach && mainRenderModel != null && mainRenderModel.displayHandByDefault)
  659. ShowSkeleton();
  660.  
  661. if (attachedObjects[index].interactable.hideControllerOnAttach && mainRenderModel != null && mainRenderModel.displayControllerByDefault)
  662. ShowController();
  663.  
  664. if (attachedObjects[index].interactable.handAnimationOnPickup != 0)
  665. StopAnimation();
  666.  
  667. if (attachedObjects[index].interactable.setRangeOfMotionOnPickup != SkeletalMotionRangeChange.None)
  668. ResetTemporarySkeletonRangeOfMotion();
  669. }
  670.  
  671. Transform parentTransform = null;
  672. if (attachedObjects[index].isParentedToHand)
  673. {
  674. if (restoreOriginalParent && (attachedObjects[index].originalParent != null))
  675. {
  676. parentTransform = attachedObjects[index].originalParent.transform;
  677. }
  678.  
  679. if (attachedObjects[index].attachedObject != null)
  680. {
  681. attachedObjects[index].attachedObject.transform.parent = parentTransform;
  682. }
  683. }
  684.  
  685. if (attachedObjects[index].HasAttachFlag(AttachmentFlags.TurnOnKinematic))
  686. {
  687. if (attachedObjects[index].attachedRigidbody != null)
  688. {
  689. attachedObjects[index].attachedRigidbody.isKinematic = attachedObjects[index].attachedRigidbodyWasKinematic;
  690. attachedObjects[index].attachedRigidbody.collisionDetectionMode = attachedObjects[index].collisionDetectionMode;
  691. }
  692. }
  693.  
  694. if (attachedObjects[index].HasAttachFlag(AttachmentFlags.TurnOffGravity))
  695. {
  696. if (attachedObjects[index].attachedObject != null)
  697. {
  698. if (attachedObjects[index].attachedRigidbody != null)
  699. attachedObjects[index].attachedRigidbody.useGravity = attachedObjects[index].attachedRigidbodyUsedGravity;
  700. }
  701. }
  702.  
  703. if (attachedObjects[index].interactable != null && attachedObjects[index].interactable.handFollowTransform && HasSkeleton())
  704. {
  705. skeleton.transform.localPosition = Vector3.zero;
  706. skeleton.transform.localRotation = Quaternion.identity;
  707. }
  708.  
  709. if (attachedObjects[index].attachedObject != null)
  710. {
  711. if (attachedObjects[index].interactable == null || (attachedObjects[index].interactable != null && attachedObjects[index].interactable.isDestroying == false))
  712. attachedObjects[index].attachedObject.SetActive(true);
  713.  
  714. attachedObjects[index].attachedObject.SendMessage("OnDetachedFromHand", this, SendMessageOptions.DontRequireReceiver);
  715. }
  716.  
  717. attachedObjects.RemoveAt(index);
  718.  
  719. CleanUpAttachedObjectStack();
  720.  
  721. // ADDED FOR TWO HAND INTERACTION START
  722. if (otherHand.twoHandGrab)
  723. {
  724. otherHand.twoHandGrab = false;
  725. otherHand.AttachObject(otherHand.currentAttachedObject, otherHand.GetBestGrabbingType(GrabTypes.None));
  726. }
  727.  
  728. if (twoHandGrab)
  729. {
  730. twoHandGrab = false;
  731. otherHand.AttachObject(prevTopObject, otherHand.GetBestGrabbingType(GrabTypes.None));
  732. }
  733. // ADDED FOR TWO HAND INTERACTION END
  734.  
  735. GameObject newTopObject = currentAttachedObject;
  736.  
  737. hoverLocked = false;
  738.  
  739.  
  740. //Give focus to the top most object on the stack if it changed
  741. if (newTopObject != null && newTopObject != prevTopObject)
  742. {
  743. newTopObject.SetActive(true);
  744. newTopObject.SendMessage("OnHandFocusAcquired", this, SendMessageOptions.DontRequireReceiver);
  745. }
  746. }
  747.  
  748. CleanUpAttachedObjectStack();
  749.  
  750. if (mainRenderModel != null)
  751. mainRenderModel.MatchHandToTransform(mainRenderModel.transform);
  752. if (hoverhighlightRenderModel != null)
  753. hoverhighlightRenderModel.MatchHandToTransform(hoverhighlightRenderModel.transform);
  754. }
  755.  
  756.  
  757. //-------------------------------------------------
  758. // Get the world velocity of the VR Hand.
  759. //-------------------------------------------------
  760. public Vector3 GetTrackedObjectVelocity(float timeOffset = 0)
  761. {
  762. if (trackedObject == null)
  763. {
  764. Vector3 velocityTarget, angularTarget;
  765. GetUpdatedAttachedVelocities(currentAttachedObjectInfo.Value, out velocityTarget, out angularTarget);
  766. return velocityTarget;
  767. }
  768.  
  769. if (isActive)
  770. {
  771. if (timeOffset == 0)
  772. return Player.instance.trackingOriginTransform.TransformVector(trackedObject.GetVelocity());
  773. else
  774. {
  775. Vector3 velocity;
  776. Vector3 angularVelocity;
  777.  
  778. trackedObject.GetVelocitiesAtTimeOffset(timeOffset, out velocity, out angularVelocity);
  779. return Player.instance.trackingOriginTransform.TransformVector(velocity);
  780. }
  781. }
  782.  
  783. return Vector3.zero;
  784. }
  785.  
  786.  
  787. //-------------------------------------------------
  788. // Get the world space angular velocity of the VR Hand.
  789. //-------------------------------------------------
  790. public Vector3 GetTrackedObjectAngularVelocity(float timeOffset = 0)
  791. {
  792. if (trackedObject == null)
  793. {
  794. Vector3 velocityTarget, angularTarget;
  795. GetUpdatedAttachedVelocities(currentAttachedObjectInfo.Value, out velocityTarget, out angularTarget);
  796. return angularTarget;
  797. }
  798.  
  799. if (isActive)
  800. {
  801. if (timeOffset == 0)
  802. return Player.instance.trackingOriginTransform.TransformDirection(trackedObject.GetAngularVelocity());
  803. else
  804. {
  805. Vector3 velocity;
  806. Vector3 angularVelocity;
  807.  
  808. trackedObject.GetVelocitiesAtTimeOffset(timeOffset, out velocity, out angularVelocity);
  809. return Player.instance.trackingOriginTransform.TransformDirection(angularVelocity);
  810. }
  811. }
  812.  
  813. return Vector3.zero;
  814. }
  815.  
  816. public void GetEstimatedPeakVelocities(out Vector3 velocity, out Vector3 angularVelocity)
  817. {
  818. trackedObject.GetEstimatedPeakVelocities(out velocity, out angularVelocity);
  819. velocity = Player.instance.trackingOriginTransform.TransformVector(velocity);
  820. angularVelocity = Player.instance.trackingOriginTransform.TransformDirection(angularVelocity);
  821. }
  822.  
  823.  
  824. //-------------------------------------------------
  825. private void CleanUpAttachedObjectStack()
  826. {
  827. attachedObjects.RemoveAll(l => l.attachedObject == null);
  828. }
  829.  
  830.  
  831. //-------------------------------------------------
  832. protected virtual void Awake()
  833. {
  834. inputFocusAction = SteamVR_Events.InputFocusAction(OnInputFocus);
  835.  
  836. if (hoverSphereTransform == null)
  837. hoverSphereTransform = this.transform;
  838.  
  839. if (objectAttachmentPoint == null)
  840. objectAttachmentPoint = this.transform;
  841.  
  842. applicationLostFocusObject = new GameObject("_application_lost_focus");
  843. applicationLostFocusObject.transform.parent = transform;
  844. applicationLostFocusObject.SetActive(false);
  845.  
  846. if (trackedObject == null)
  847. {
  848. trackedObject = this.gameObject.GetComponent<SteamVR_Behaviour_Pose>();
  849.  
  850. if (trackedObject != null)
  851. {
  852. trackedObject.onTransformUpdatedEvent += OnTransformUpdated;
  853.  
  854. // ADDED FOR TWO HAND INTERACTION START
  855. trackedObject.onTransformUpdatedEvent += TwoHandGrabbingUpdate;
  856. // ADDED FOR TWO HAND INTERACTION END
  857. }
  858. }
  859. }
  860.  
  861. protected virtual void OnDestroy()
  862. {
  863. if (trackedObject != null)
  864. {
  865. trackedObject.onTransformUpdatedEvent -= OnTransformUpdated;
  866. // ADDED FOR TWO HAND INTERACTION START
  867. trackedObject.onTransformUpdatedEvent -= TwoHandGrabbingUpdate;
  868. // ADDED FOR TWO HAND INTERACTION END
  869. }
  870. }
  871.  
  872. protected virtual void OnTransformUpdated(SteamVR_Behaviour_Pose updatedPose, SteamVR_Input_Sources updatedSource)
  873. {
  874. HandFollowUpdate();
  875. }
  876.  
  877. //-------------------------------------------------
  878. protected virtual IEnumerator Start()
  879. {
  880. // save off player instance
  881. playerInstance = Player.instance;
  882. if (!playerInstance)
  883. {
  884. Debug.LogError("<b>[SteamVR Interaction]</b> No player instance found in Hand Start()");
  885. }
  886.  
  887. // allocate array for colliders
  888. overlappingColliders = new Collider[ColliderArraySize];
  889.  
  890. // We are a "no SteamVR fallback hand" if we have this camera set
  891. // we'll use the right mouse to look around and left mouse to interact
  892. // - don't need to find the device
  893. if (noSteamVRFallbackCamera)
  894. {
  895. yield break;
  896. }
  897.  
  898. //Debug.Log( "<b>[SteamVR Interaction]</b> Hand - initializing connection routine" );
  899.  
  900. while (true)
  901. {
  902. if (isPoseValid)
  903. {
  904. InitController();
  905. break;
  906. }
  907.  
  908. yield return null;
  909. }
  910. }
  911.  
  912.  
  913. //-------------------------------------------------
  914. protected virtual void UpdateHovering()
  915. {
  916. if ((noSteamVRFallbackCamera == null) && (isActive == false))
  917. {
  918. return;
  919. }
  920.  
  921. if (hoverLocked)
  922. return;
  923.  
  924. if (applicationLostFocusObject.activeSelf)
  925. return;
  926.  
  927. float closestDistance = float.MaxValue;
  928. Interactable closestInteractable = null;
  929.  
  930. if (useHoverSphere)
  931. {
  932. float scaledHoverRadius = hoverSphereRadius * Mathf.Abs(SteamVR_Utils.GetLossyScale(hoverSphereTransform));
  933. CheckHoveringForTransform(hoverSphereTransform.position, scaledHoverRadius, ref closestDistance, ref closestInteractable, Color.green);
  934. }
  935.  
  936. if (useControllerHoverComponent && mainRenderModel != null && mainRenderModel.IsControllerVisibile())
  937. {
  938. float scaledHoverRadius = controllerHoverRadius * Mathf.Abs(SteamVR_Utils.GetLossyScale(this.transform));
  939. CheckHoveringForTransform(mainRenderModel.GetControllerPosition(controllerHoverComponent), scaledHoverRadius / 2f, ref closestDistance, ref closestInteractable, Color.blue);
  940. }
  941.  
  942. if (useFingerJointHover && mainRenderModel != null && mainRenderModel.IsHandVisibile())
  943. {
  944. float scaledHoverRadius = fingerJointHoverRadius * Mathf.Abs(SteamVR_Utils.GetLossyScale(this.transform));
  945. CheckHoveringForTransform(mainRenderModel.GetBonePosition((int)fingerJointHover), scaledHoverRadius / 2f, ref closestDistance, ref closestInteractable, Color.yellow);
  946. }
  947.  
  948. // Hover on this one
  949. hoveringInteractable = closestInteractable;
  950. }
  951.  
  952. protected virtual bool CheckHoveringForTransform(Vector3 hoverPosition, float hoverRadius, ref float closestDistance, ref Interactable closestInteractable, Color debugColor)
  953. {
  954. bool foundCloser = false;
  955.  
  956. // null out old vals
  957. for (int i = 0; i < overlappingColliders.Length; ++i)
  958. {
  959. overlappingColliders[i] = null;
  960. }
  961.  
  962. int numColliding = Physics.OverlapSphereNonAlloc(hoverPosition, hoverRadius, overlappingColliders, hoverLayerMask.value);
  963.  
  964. if (numColliding == ColliderArraySize)
  965. Debug.LogWarning("<b>[SteamVR Interaction]</b> This hand is overlapping the max number of colliders: " + ColliderArraySize + ". Some collisions may be missed. Increase ColliderArraySize on Hand.cs");
  966.  
  967. // DebugVar
  968. int iActualColliderCount = 0;
  969.  
  970. // Pick the closest hovering
  971. for (int colliderIndex = 0; colliderIndex < overlappingColliders.Length; colliderIndex++)
  972. {
  973. Collider collider = overlappingColliders[colliderIndex];
  974.  
  975. if (collider == null)
  976. continue;
  977.  
  978. Interactable contacting = collider.GetComponentInParent<Interactable>();
  979.  
  980. // Yeah, it's null, skip
  981. if (contacting == null)
  982. continue;
  983.  
  984. // Ignore this collider for hovering
  985. IgnoreHovering ignore = collider.GetComponent<IgnoreHovering>();
  986. if (ignore != null)
  987. {
  988. if (ignore.onlyIgnoreHand == null || ignore.onlyIgnoreHand == this)
  989. {
  990. continue;
  991. }
  992. }
  993.  
  994. // Can't hover over the object if it's attached
  995. bool hoveringOverAttached = false;
  996. for (int attachedIndex = 0; attachedIndex < attachedObjects.Count; attachedIndex++)
  997. {
  998. if (attachedObjects[attachedIndex].attachedObject == contacting.gameObject)
  999. {
  1000. hoveringOverAttached = true;
  1001. break;
  1002. }
  1003. }
  1004. if (hoveringOverAttached)
  1005. continue;
  1006.  
  1007. // Occupied by another hand, so we can't touch it
  1008. if (otherHand && otherHand.hoveringInteractable == contacting)
  1009. continue;
  1010.  
  1011. // Best candidate so far...
  1012. float distance = Vector3.Distance(contacting.transform.position, hoverPosition);
  1013. if (distance < closestDistance)
  1014. {
  1015. closestDistance = distance;
  1016. closestInteractable = contacting;
  1017. foundCloser = true;
  1018. }
  1019. iActualColliderCount++;
  1020. }
  1021.  
  1022. if (showDebugInteractables && foundCloser)
  1023. {
  1024. Debug.DrawLine(hoverPosition, closestInteractable.transform.position, debugColor, .05f, false);
  1025. }
  1026.  
  1027. if (iActualColliderCount > 0 && iActualColliderCount != prevOverlappingColliders)
  1028. {
  1029. prevOverlappingColliders = iActualColliderCount;
  1030.  
  1031. if (spewDebugText)
  1032. HandDebugLog("Found " + iActualColliderCount + " overlapping colliders.");
  1033. }
  1034.  
  1035. return foundCloser;
  1036. }
  1037.  
  1038.  
  1039. //-------------------------------------------------
  1040. protected virtual void UpdateNoSteamVRFallback()
  1041. {
  1042. if (noSteamVRFallbackCamera)
  1043. {
  1044. Ray ray = noSteamVRFallbackCamera.ScreenPointToRay(Input.mousePosition);
  1045.  
  1046. if (attachedObjects.Count > 0)
  1047. {
  1048. // Holding down the mouse:
  1049. // move around a fixed distance from the camera
  1050. transform.position = ray.origin + noSteamVRFallbackInteractorDistance * ray.direction;
  1051. }
  1052. else
  1053. {
  1054. // Not holding down the mouse:
  1055. // cast out a ray to see what we should mouse over
  1056.  
  1057. // Don't want to hit the hand and anything underneath it
  1058. // So move it back behind the camera when we do the raycast
  1059. Vector3 oldPosition = transform.position;
  1060. transform.position = noSteamVRFallbackCamera.transform.forward * (-1000.0f);
  1061.  
  1062. RaycastHit raycastHit;
  1063. if (Physics.Raycast(ray, out raycastHit, noSteamVRFallbackMaxDistanceNoItem))
  1064. {
  1065. transform.position = raycastHit.point;
  1066.  
  1067. // Remember this distance in case we click and drag the mouse
  1068. noSteamVRFallbackInteractorDistance = Mathf.Min(noSteamVRFallbackMaxDistanceNoItem, raycastHit.distance);
  1069. }
  1070. else if (noSteamVRFallbackInteractorDistance > 0.0f)
  1071. {
  1072. // Move it around at the distance we last had a hit
  1073. transform.position = ray.origin + Mathf.Min(noSteamVRFallbackMaxDistanceNoItem, noSteamVRFallbackInteractorDistance) * ray.direction;
  1074. }
  1075. else
  1076. {
  1077. // Didn't hit, just leave it where it was
  1078. transform.position = oldPosition;
  1079. }
  1080. }
  1081. }
  1082. }
  1083.  
  1084.  
  1085. //-------------------------------------------------
  1086. private void UpdateDebugText()
  1087. {
  1088. if (showDebugText)
  1089. {
  1090. if (debugText == null)
  1091. {
  1092. debugText = new GameObject("_debug_text").AddComponent<TextMesh>();
  1093. debugText.fontSize = 120;
  1094. debugText.characterSize = 0.001f;
  1095. debugText.transform.parent = transform;
  1096.  
  1097. debugText.transform.localRotation = Quaternion.Euler(90.0f, 0.0f, 0.0f);
  1098. }
  1099.  
  1100. if (handType == SteamVR_Input_Sources.RightHand)
  1101. {
  1102. debugText.transform.localPosition = new Vector3(-0.05f, 0.0f, 0.0f);
  1103. debugText.alignment = TextAlignment.Right;
  1104. debugText.anchor = TextAnchor.UpperRight;
  1105. }
  1106. else
  1107. {
  1108. debugText.transform.localPosition = new Vector3(0.05f, 0.0f, 0.0f);
  1109. debugText.alignment = TextAlignment.Left;
  1110. debugText.anchor = TextAnchor.UpperLeft;
  1111. }
  1112.  
  1113. debugText.text = string.Format(
  1114. "Hovering: {0}\n" +
  1115. "Hover Lock: {1}\n" +
  1116. "Attached: {2}\n" +
  1117. "Total Attached: {3}\n" +
  1118. "Type: {4}\n",
  1119. (hoveringInteractable ? hoveringInteractable.gameObject.name : "null"),
  1120. hoverLocked,
  1121. (currentAttachedObject ? currentAttachedObject.name : "null"),
  1122. attachedObjects.Count,
  1123. handType.ToString());
  1124. }
  1125. else
  1126. {
  1127. if (debugText != null)
  1128. {
  1129. Destroy(debugText.gameObject);
  1130. }
  1131. }
  1132. }
  1133.  
  1134.  
  1135. //-------------------------------------------------
  1136. protected virtual void OnEnable()
  1137. {
  1138. inputFocusAction.enabled = true;
  1139.  
  1140. // Stagger updates between hands
  1141. float hoverUpdateBegin = ((otherHand != null) && (otherHand.GetInstanceID() < GetInstanceID())) ? (0.5f * hoverUpdateInterval) : (0.0f);
  1142. InvokeRepeating("UpdateHovering", hoverUpdateBegin, hoverUpdateInterval);
  1143. InvokeRepeating("UpdateDebugText", hoverUpdateBegin, hoverUpdateInterval);
  1144. }
  1145.  
  1146.  
  1147. //-------------------------------------------------
  1148. protected virtual void OnDisable()
  1149. {
  1150. inputFocusAction.enabled = false;
  1151.  
  1152. CancelInvoke();
  1153. }
  1154.  
  1155. float Remap(float value, float from1, float to1, float from2, float to2)
  1156. {
  1157. return (value - from1) / (to1 - from1) * (to2 - from2) + from2;
  1158. }
  1159.  
  1160. //-------------------------------------------------
  1161. protected virtual void Update()
  1162. {
  1163.  
  1164. UpdateNoSteamVRFallback();
  1165.  
  1166. GameObject attachedObject = currentAttachedObject;
  1167. if (attachedObject != null)
  1168. {
  1169. attachedObject.SendMessage("HandAttachedUpdate", this, SendMessageOptions.DontRequireReceiver);
  1170. }
  1171.  
  1172. if (hoveringInteractable)
  1173. {
  1174. hoveringInteractable.SendMessage("HandHoverUpdate", this, SendMessageOptions.DontRequireReceiver);
  1175. }
  1176. }
  1177.  
  1178. /// <summary>
  1179. /// Returns true when the hand is currently hovering over the interactable passed in
  1180. /// </summary>
  1181. public bool IsStillHovering(Interactable interactable)
  1182. {
  1183. return hoveringInteractable == interactable;
  1184. }
  1185.  
  1186. protected virtual void HandFollowUpdate()
  1187. {
  1188. GameObject attachedObject = currentAttachedObject;
  1189. if (attachedObject != null)
  1190. {
  1191. if (currentAttachedObjectInfo.Value.interactable != null)
  1192. {
  1193. SteamVR_Skeleton_PoseSnapshot pose = null;
  1194.  
  1195. if (currentAttachedObjectInfo.Value.interactable.skeletonPoser != null && HasSkeleton())
  1196. {
  1197. pose = currentAttachedObjectInfo.Value.interactable.skeletonPoser.GetBlendedPose(skeleton);
  1198. }
  1199.  
  1200. if (currentAttachedObjectInfo.Value.interactable.handFollowTransform)
  1201. {
  1202. Quaternion targetHandRotation;
  1203. Vector3 targetHandPosition;
  1204.  
  1205. if (pose == null)
  1206. {
  1207. Quaternion offset = Quaternion.Inverse(this.transform.rotation) * currentAttachedObjectInfo.Value.handAttachmentPointTransform.rotation;
  1208. targetHandRotation = currentAttachedObjectInfo.Value.interactable.transform.rotation * Quaternion.Inverse(offset);
  1209.  
  1210. Vector3 worldOffset = (this.transform.position - currentAttachedObjectInfo.Value.handAttachmentPointTransform.position);
  1211. Quaternion rotationDiff = mainRenderModel.GetHandRotation() * Quaternion.Inverse(this.transform.rotation);
  1212. Vector3 localOffset = rotationDiff * worldOffset;
  1213. targetHandPosition = currentAttachedObjectInfo.Value.interactable.transform.position + localOffset;
  1214. }
  1215. else
  1216. {
  1217. Transform objectT = currentAttachedObjectInfo.Value.attachedObject.transform;
  1218. Vector3 oldItemPos = objectT.position;
  1219. Quaternion oldItemRot = objectT.transform.rotation;
  1220. objectT.position = TargetItemPosition(currentAttachedObjectInfo.Value);
  1221. objectT.rotation = TargetItemRotation(currentAttachedObjectInfo.Value);
  1222. Vector3 localSkelePos = objectT.InverseTransformPoint(transform.position);
  1223. Quaternion localSkeleRot = Quaternion.Inverse(objectT.rotation) * transform.rotation;
  1224. objectT.position = oldItemPos;
  1225. objectT.rotation = oldItemRot;
  1226.  
  1227. targetHandPosition = objectT.TransformPoint(localSkelePos);
  1228. targetHandRotation = objectT.rotation * localSkeleRot;
  1229. }
  1230.  
  1231. if (mainRenderModel != null)
  1232. mainRenderModel.SetHandRotation(targetHandRotation);
  1233. if (hoverhighlightRenderModel != null)
  1234. hoverhighlightRenderModel.SetHandRotation(targetHandRotation);
  1235.  
  1236. if (mainRenderModel != null)
  1237. mainRenderModel.SetHandPosition(targetHandPosition);
  1238. if (hoverhighlightRenderModel != null)
  1239. hoverhighlightRenderModel.SetHandPosition(targetHandPosition);
  1240. }
  1241. }
  1242. }
  1243. }
  1244.  
  1245. protected virtual void FixedUpdate()
  1246. {
  1247. if (currentAttachedObject != null)
  1248. {
  1249. AttachedObject attachedInfo = currentAttachedObjectInfo.Value;
  1250. if (attachedInfo.attachedObject != null)
  1251. {
  1252. if (attachedInfo.HasAttachFlag(AttachmentFlags.VelocityMovement))
  1253. {
  1254. if (attachedInfo.interactable.attachEaseIn == false || attachedInfo.interactable.snapAttachEaseInCompleted)
  1255. UpdateAttachedVelocity(attachedInfo);
  1256.  
  1257. /*if (attachedInfo.interactable.handFollowTransformPosition)
  1258. {
  1259. skeleton.transform.position = TargetSkeletonPosition(attachedInfo);
  1260. skeleton.transform.rotation = attachedInfo.attachedObject.transform.rotation * attachedInfo.skeletonLockRotation;
  1261. }*/
  1262. }
  1263. else
  1264. {
  1265. if (attachedInfo.HasAttachFlag(AttachmentFlags.ParentToHand))
  1266. {
  1267. attachedInfo.attachedObject.transform.position = TargetItemPosition(attachedInfo);
  1268. attachedInfo.attachedObject.transform.rotation = TargetItemRotation(attachedInfo);
  1269. }
  1270. }
  1271.  
  1272.  
  1273. if (attachedInfo.interactable.attachEaseIn)
  1274. {
  1275. float t = Util.RemapNumberClamped(Time.time, attachedInfo.attachTime, attachedInfo.attachTime + attachedInfo.interactable.snapAttachEaseInTime, 0.0f, 1.0f);
  1276. if (t < 1.0f)
  1277. {
  1278. if (attachedInfo.HasAttachFlag(AttachmentFlags.VelocityMovement))
  1279. {
  1280. attachedInfo.attachedRigidbody.velocity = Vector3.zero;
  1281. attachedInfo.attachedRigidbody.angularVelocity = Vector3.zero;
  1282. }
  1283. t = attachedInfo.interactable.snapAttachEaseInCurve.Evaluate(t);
  1284. attachedInfo.attachedObject.transform.position = Vector3.Lerp(attachedInfo.easeSourcePosition, TargetItemPosition(attachedInfo), t);
  1285. attachedInfo.attachedObject.transform.rotation = Quaternion.Lerp(attachedInfo.easeSourceRotation, TargetItemRotation(attachedInfo), t);
  1286. }
  1287. else if (!attachedInfo.interactable.snapAttachEaseInCompleted)
  1288. {
  1289. attachedInfo.interactable.gameObject.SendMessage("OnThrowableAttachEaseInCompleted", this, SendMessageOptions.DontRequireReceiver);
  1290. attachedInfo.interactable.snapAttachEaseInCompleted = true;
  1291. }
  1292. }
  1293. }
  1294. }
  1295. }
  1296.  
  1297. protected const float MaxVelocityChange = 10f;
  1298. protected const float VelocityMagic = 6000f;
  1299. protected const float AngularVelocityMagic = 50f;
  1300. protected const float MaxAngularVelocityChange = 20f;
  1301.  
  1302. protected void UpdateAttachedVelocity(AttachedObject attachedObjectInfo)
  1303. {
  1304. Vector3 velocityTarget, angularTarget;
  1305. bool success = GetUpdatedAttachedVelocities(attachedObjectInfo, out velocityTarget, out angularTarget);
  1306. if (success)
  1307. {
  1308. float scale = SteamVR_Utils.GetLossyScale(currentAttachedObjectInfo.Value.handAttachmentPointTransform);
  1309. float maxAngularVelocityChange = MaxAngularVelocityChange * scale;
  1310. float maxVelocityChange = MaxVelocityChange * scale;
  1311.  
  1312. attachedObjectInfo.attachedRigidbody.velocity = Vector3.MoveTowards(attachedObjectInfo.attachedRigidbody.velocity, velocityTarget, maxVelocityChange);
  1313. attachedObjectInfo.attachedRigidbody.angularVelocity = Vector3.MoveTowards(attachedObjectInfo.attachedRigidbody.angularVelocity, angularTarget, maxAngularVelocityChange);
  1314. }
  1315. }
  1316.  
  1317. protected Vector3 TargetItemPosition(AttachedObject attachedObject)
  1318. {
  1319. if (attachedObject.interactable != null && attachedObject.interactable.skeletonPoser != null && HasSkeleton())
  1320. {
  1321. Vector3 tp = attachedObject.handAttachmentPointTransform.InverseTransformPoint(transform.TransformPoint(attachedObject.interactable.skeletonPoser.GetBlendedPose(skeleton).position));
  1322. //tp.x *= -1;
  1323. return currentAttachedObjectInfo.Value.handAttachmentPointTransform.TransformPoint(tp);
  1324. }
  1325. else
  1326. {
  1327. return currentAttachedObjectInfo.Value.handAttachmentPointTransform.TransformPoint(attachedObject.initialPositionalOffset);
  1328. }
  1329. }
  1330.  
  1331. protected Quaternion TargetItemRotation(AttachedObject attachedObject)
  1332. {
  1333. if (attachedObject.interactable != null && attachedObject.interactable.skeletonPoser != null && HasSkeleton())
  1334. {
  1335. Quaternion tr = Quaternion.Inverse(attachedObject.handAttachmentPointTransform.rotation) * (transform.rotation * attachedObject.interactable.skeletonPoser.GetBlendedPose(skeleton).rotation);
  1336. return currentAttachedObjectInfo.Value.handAttachmentPointTransform.rotation * tr;
  1337. }
  1338. else
  1339. {
  1340. return currentAttachedObjectInfo.Value.handAttachmentPointTransform.rotation * attachedObject.initialRotationalOffset;
  1341. }
  1342. }
  1343.  
  1344. protected bool GetUpdatedAttachedVelocities(AttachedObject attachedObjectInfo, out Vector3 velocityTarget, out Vector3 angularTarget)
  1345. {
  1346. bool realNumbers = false;
  1347.  
  1348.  
  1349. float velocityMagic = VelocityMagic;
  1350. float angularVelocityMagic = AngularVelocityMagic;
  1351.  
  1352. Vector3 targetItemPosition = TargetItemPosition(attachedObjectInfo);
  1353. Vector3 positionDelta = (targetItemPosition - attachedObjectInfo.attachedRigidbody.position);
  1354. velocityTarget = (positionDelta * velocityMagic * Time.deltaTime);
  1355.  
  1356. if (float.IsNaN(velocityTarget.x) == false && float.IsInfinity(velocityTarget.x) == false)
  1357. {
  1358. if (noSteamVRFallbackCamera)
  1359. velocityTarget /= 10; //hacky fix for fallback
  1360.  
  1361. realNumbers = true;
  1362. }
  1363. else
  1364. velocityTarget = Vector3.zero;
  1365.  
  1366.  
  1367. Quaternion targetItemRotation = TargetItemRotation(attachedObjectInfo);
  1368. Quaternion rotationDelta = targetItemRotation * Quaternion.Inverse(attachedObjectInfo.attachedObject.transform.rotation);
  1369.  
  1370.  
  1371. float angle;
  1372. Vector3 axis;
  1373. rotationDelta.ToAngleAxis(out angle, out axis);
  1374.  
  1375. if (angle > 180)
  1376. angle -= 360;
  1377.  
  1378. if (angle != 0 && float.IsNaN(axis.x) == false && float.IsInfinity(axis.x) == false)
  1379. {
  1380. angularTarget = angle * axis * angularVelocityMagic * Time.deltaTime;
  1381.  
  1382. if (noSteamVRFallbackCamera)
  1383. angularTarget /= 10; //hacky fix for fallback
  1384.  
  1385. realNumbers &= true;
  1386. }
  1387. else
  1388. angularTarget = Vector3.zero;
  1389.  
  1390. return realNumbers;
  1391. }
  1392.  
  1393.  
  1394. //-------------------------------------------------
  1395. protected virtual void OnInputFocus(bool hasFocus)
  1396. {
  1397. if (hasFocus)
  1398. {
  1399. DetachObject(applicationLostFocusObject, true);
  1400. applicationLostFocusObject.SetActive(false);
  1401. UpdateHovering();
  1402. BroadcastMessage("OnParentHandInputFocusAcquired", SendMessageOptions.DontRequireReceiver);
  1403. }
  1404. else
  1405. {
  1406. applicationLostFocusObject.SetActive(true);
  1407. AttachObject(applicationLostFocusObject, GrabTypes.Scripted, AttachmentFlags.ParentToHand);
  1408. BroadcastMessage("OnParentHandInputFocusLost", SendMessageOptions.DontRequireReceiver);
  1409. }
  1410. }
  1411.  
  1412. //-------------------------------------------------
  1413. protected virtual void OnDrawGizmos()
  1414. {
  1415. if (useHoverSphere && hoverSphereTransform != null)
  1416. {
  1417. Gizmos.color = Color.green;
  1418. float scaledHoverRadius = hoverSphereRadius * Mathf.Abs(SteamVR_Utils.GetLossyScale(hoverSphereTransform));
  1419. Gizmos.DrawWireSphere(hoverSphereTransform.position, scaledHoverRadius / 2);
  1420. }
  1421.  
  1422. if (useControllerHoverComponent && mainRenderModel != null && mainRenderModel.IsControllerVisibile())
  1423. {
  1424. Gizmos.color = Color.blue;
  1425. float scaledHoverRadius = controllerHoverRadius * Mathf.Abs(SteamVR_Utils.GetLossyScale(this.transform));
  1426. Gizmos.DrawWireSphere(mainRenderModel.GetControllerPosition(controllerHoverComponent), scaledHoverRadius / 2);
  1427. }
  1428.  
  1429. if (useFingerJointHover && mainRenderModel != null && mainRenderModel.IsHandVisibile())
  1430. {
  1431. Gizmos.color = Color.yellow;
  1432. float scaledHoverRadius = fingerJointHoverRadius * Mathf.Abs(SteamVR_Utils.GetLossyScale(this.transform));
  1433. Gizmos.DrawWireSphere(mainRenderModel.GetBonePosition((int)fingerJointHover), scaledHoverRadius / 2);
  1434. }
  1435. }
  1436.  
  1437.  
  1438. //-------------------------------------------------
  1439. private void HandDebugLog(string msg)
  1440. {
  1441. if (spewDebugText)
  1442. {
  1443. Debug.Log("<b>[SteamVR Interaction]</b> Hand (" + this.name + "): " + msg);
  1444. }
  1445. }
  1446.  
  1447.  
  1448. //-------------------------------------------------
  1449. // Continue to hover over this object indefinitely, whether or not the Hand moves out of its interaction trigger volume.
  1450. //
  1451. // interactable - The Interactable to hover over indefinitely.
  1452. //-------------------------------------------------
  1453. public void HoverLock(Interactable interactable)
  1454. {
  1455. if (spewDebugText)
  1456. HandDebugLog("HoverLock " + interactable);
  1457. hoverLocked = true;
  1458. hoveringInteractable = interactable;
  1459. }
  1460.  
  1461.  
  1462. //-------------------------------------------------
  1463. // Stop hovering over this object indefinitely.
  1464. //
  1465. // interactable - The hover-locked Interactable to stop hovering over indefinitely.
  1466. //-------------------------------------------------
  1467. public void HoverUnlock(Interactable interactable)
  1468. {
  1469. if (spewDebugText)
  1470. HandDebugLog("HoverUnlock " + interactable);
  1471.  
  1472. if (hoveringInteractable == interactable)
  1473. {
  1474. hoverLocked = false;
  1475. }
  1476. }
  1477.  
  1478. public void TriggerHapticPulse(ushort microSecondsDuration)
  1479. {
  1480. float seconds = (float)microSecondsDuration / 1000000f;
  1481. hapticAction.Execute(0, seconds, 1f / seconds, 1, handType);
  1482. }
  1483.  
  1484. public void TriggerHapticPulse(float duration, float frequency, float amplitude)
  1485. {
  1486. hapticAction.Execute(0, duration, frequency, amplitude, handType);
  1487. }
  1488.  
  1489. public void ShowGrabHint()
  1490. {
  1491. ControllerButtonHints.ShowButtonHint(this, grabGripAction); //todo: assess
  1492. }
  1493.  
  1494. public void HideGrabHint()
  1495. {
  1496. ControllerButtonHints.HideButtonHint(this, grabGripAction); //todo: assess
  1497. }
  1498.  
  1499. public void ShowGrabHint(string text)
  1500. {
  1501. ControllerButtonHints.ShowTextHint(this, grabGripAction, text);
  1502. }
  1503.  
  1504. public GrabTypes GetGrabStarting(GrabTypes explicitType = GrabTypes.None)
  1505. {
  1506. if (explicitType != GrabTypes.None)
  1507. {
  1508. if (noSteamVRFallbackCamera)
  1509. {
  1510. if (Input.GetMouseButtonDown(0))
  1511. return explicitType;
  1512. }
  1513.  
  1514. if (explicitType == GrabTypes.Pinch && grabPinchAction.GetStateDown(handType))
  1515. return GrabTypes.Pinch;
  1516. if (explicitType == GrabTypes.Grip && grabGripAction.GetStateDown(handType))
  1517. return GrabTypes.Grip;
  1518. }
  1519. else
  1520. {
  1521. if (noSteamVRFallbackCamera)
  1522. {
  1523. if (Input.GetMouseButtonDown(0))
  1524. return GrabTypes.Grip;
  1525. }
  1526.  
  1527. if (grabPinchAction.GetStateDown(handType))
  1528. return GrabTypes.Pinch;
  1529. if (grabGripAction.GetStateDown(handType))
  1530. return GrabTypes.Grip;
  1531. }
  1532.  
  1533. return GrabTypes.None;
  1534. }
  1535.  
  1536. public GrabTypes GetGrabEnding(GrabTypes explicitType = GrabTypes.None)
  1537. {
  1538. if (explicitType != GrabTypes.None)
  1539. {
  1540. if (noSteamVRFallbackCamera)
  1541. {
  1542. if (Input.GetMouseButtonUp(0))
  1543. return explicitType;
  1544. }
  1545.  
  1546. if (explicitType == GrabTypes.Pinch && grabPinchAction.GetStateUp(handType))
  1547. return GrabTypes.Pinch;
  1548. if (explicitType == GrabTypes.Grip && grabGripAction.GetStateUp(handType))
  1549. return GrabTypes.Grip;
  1550. }
  1551. else
  1552. {
  1553. if (noSteamVRFallbackCamera)
  1554. {
  1555. if (Input.GetMouseButtonUp(0))
  1556. return GrabTypes.Grip;
  1557. }
  1558.  
  1559. if (grabPinchAction.GetStateUp(handType))
  1560. return GrabTypes.Pinch;
  1561. if (grabGripAction.GetStateUp(handType))
  1562. return GrabTypes.Grip;
  1563. }
  1564.  
  1565. return GrabTypes.None;
  1566. }
  1567.  
  1568. public bool IsGrabEnding(GameObject attachedObject)
  1569. {
  1570. for (int attachedObjectIndex = 0; attachedObjectIndex < attachedObjects.Count; attachedObjectIndex++)
  1571. {
  1572. if (attachedObjects[attachedObjectIndex].attachedObject == attachedObject)
  1573. {
  1574. return IsGrabbingWithType(attachedObjects[attachedObjectIndex].grabbedWithType) == false;
  1575. }
  1576. }
  1577.  
  1578. return false;
  1579. }
  1580.  
  1581. public bool IsGrabbingWithType(GrabTypes type)
  1582. {
  1583. if (noSteamVRFallbackCamera)
  1584. {
  1585. if (Input.GetMouseButton(0))
  1586. return true;
  1587. }
  1588.  
  1589. switch (type)
  1590. {
  1591. case GrabTypes.Pinch:
  1592. return grabPinchAction.GetState(handType);
  1593.  
  1594. case GrabTypes.Grip:
  1595. return grabGripAction.GetState(handType);
  1596.  
  1597. default:
  1598. return false;
  1599. }
  1600. }
  1601.  
  1602. public bool IsGrabbingWithOppositeType(GrabTypes type)
  1603. {
  1604. if (noSteamVRFallbackCamera)
  1605. {
  1606. if (Input.GetMouseButton(0))
  1607. return true;
  1608. }
  1609.  
  1610. switch (type)
  1611. {
  1612. case GrabTypes.Pinch:
  1613. return grabGripAction.GetState(handType);
  1614.  
  1615. case GrabTypes.Grip:
  1616. return grabPinchAction.GetState(handType);
  1617.  
  1618. default:
  1619. return false;
  1620. }
  1621. }
  1622.  
  1623. public GrabTypes GetBestGrabbingType()
  1624. {
  1625. return GetBestGrabbingType(GrabTypes.None);
  1626. }
  1627.  
  1628. public GrabTypes GetBestGrabbingType(GrabTypes preferred, bool forcePreference = false)
  1629. {
  1630. if (noSteamVRFallbackCamera)
  1631. {
  1632. if (Input.GetMouseButton(0))
  1633. return preferred;
  1634. }
  1635.  
  1636. if (preferred == GrabTypes.Pinch)
  1637. {
  1638. if (grabPinchAction.GetState(handType))
  1639. return GrabTypes.Pinch;
  1640. else if (forcePreference)
  1641. return GrabTypes.None;
  1642. }
  1643. if (preferred == GrabTypes.Grip)
  1644. {
  1645. if (grabGripAction.GetState(handType))
  1646. return GrabTypes.Grip;
  1647. else if (forcePreference)
  1648. return GrabTypes.None;
  1649. }
  1650.  
  1651. if (grabPinchAction.GetState(handType))
  1652. return GrabTypes.Pinch;
  1653. if (grabGripAction.GetState(handType))
  1654. return GrabTypes.Grip;
  1655.  
  1656. return GrabTypes.None;
  1657. }
  1658.  
  1659.  
  1660. //-------------------------------------------------
  1661. private void InitController()
  1662. {
  1663. if (spewDebugText)
  1664. HandDebugLog("Hand " + name + " connected with type " + handType.ToString());
  1665.  
  1666. bool hadOldRendermodel = mainRenderModel != null;
  1667. EVRSkeletalMotionRange oldRM_rom = EVRSkeletalMotionRange.WithController;
  1668. if (hadOldRendermodel)
  1669. oldRM_rom = mainRenderModel.GetSkeletonRangeOfMotion;
  1670.  
  1671.  
  1672. foreach (RenderModel r in renderModels)
  1673. {
  1674. if (r != null)
  1675. Destroy(r.gameObject);
  1676. }
  1677.  
  1678. renderModels.Clear();
  1679.  
  1680. GameObject renderModelInstance = GameObject.Instantiate(renderModelPrefab);
  1681. renderModelInstance.layer = gameObject.layer;
  1682. renderModelInstance.tag = gameObject.tag;
  1683. renderModelInstance.transform.parent = this.transform;
  1684. renderModelInstance.transform.localPosition = Vector3.zero;
  1685. renderModelInstance.transform.localRotation = Quaternion.identity;
  1686. renderModelInstance.transform.localScale = renderModelPrefab.transform.localScale;
  1687.  
  1688. //TriggerHapticPulse(800); //pulse on controller init
  1689.  
  1690. int deviceIndex = trackedObject.GetDeviceIndex();
  1691.  
  1692. mainRenderModel = renderModelInstance.GetComponent<RenderModel>();
  1693. renderModels.Add(mainRenderModel);
  1694.  
  1695. if (hadOldRendermodel)
  1696. mainRenderModel.SetSkeletonRangeOfMotion(oldRM_rom);
  1697.  
  1698. this.BroadcastMessage("SetInputSource", handType, SendMessageOptions.DontRequireReceiver); // let child objects know we've initialized
  1699. this.BroadcastMessage("OnHandInitialized", deviceIndex, SendMessageOptions.DontRequireReceiver); // let child objects know we've initialized
  1700. }
  1701.  
  1702. public void SetRenderModel(GameObject prefab)
  1703. {
  1704. renderModelPrefab = prefab;
  1705.  
  1706. if (mainRenderModel != null && isPoseValid)
  1707. InitController();
  1708. }
  1709.  
  1710. public void SetHoverRenderModel(RenderModel hoverRenderModel)
  1711. {
  1712. hoverhighlightRenderModel = hoverRenderModel;
  1713. renderModels.Add(hoverRenderModel);
  1714. }
  1715.  
  1716. public int GetDeviceIndex()
  1717. {
  1718. return trackedObject.GetDeviceIndex();
  1719. }
  1720.  
  1721.  
  1722. // ADDED FOR TWO HAND INTERACTION START
  1723. public void replaceAttachedInfo(AttachedObject objInfo, GameObject obj)
  1724. {
  1725. int index = attachedObjects.FindIndex(l => l.attachedObject == obj);
  1726. if (index > -1)
  1727. {
  1728. attachedObjects[index] = objInfo;
  1729. }
  1730. }
  1731.  
  1732. public AttachedObject getAttachedObjectInfo(GameObject obj)
  1733. {
  1734. int index = attachedObjects.FindIndex(l => l.attachedObject == obj);
  1735. if (index > -1)
  1736. {
  1737. return attachedObjects[index];
  1738. }
  1739. return new AttachedObject();
  1740. }
  1741.  
  1742. protected virtual void TwoHandGrabbingUpdate(SteamVR_Behaviour_Pose updatedPose, SteamVR_Input_Sources updatedSource)
  1743. {
  1744.  
  1745. GameObject attachedObject = currentAttachedObject;
  1746.  
  1747. if (attachedObject != null && twoHandGrab)
  1748. {
  1749.  
  1750. Vector3 currentHandPosition1 = trackedObject.transform.position; // current first hand position
  1751. Vector3 currentHandPosition2 = otherHand.trackedObject.transform.position; // current second hand position
  1752.  
  1753. Vector3 handDir1 = (initialHandPosition1 - initialHandPosition2).normalized; // direction vector of initial first and second hand position
  1754. Vector3 handDir2 = (currentHandPosition1 - currentHandPosition2).normalized; // direction vector of current first and second hand position
  1755.  
  1756. Quaternion handRot = Quaternion.FromToRotation(handDir1, handDir2); // calculate rotation based on those two direction vectors
  1757.  
  1758.  
  1759. float currentGrabDistance = Vector3.Distance(currentHandPosition1, currentHandPosition2);
  1760. float initialGrabDistance = Vector3.Distance(initialHandPosition1, initialHandPosition2);
  1761. float p = (currentGrabDistance / initialGrabDistance); // percentage based on the distance of the initial positions and the new positions
  1762.  
  1763.  
  1764. Vector3 newScale = new Vector3(p * initialObjectScale.x, p * initialObjectScale.y, p * initialObjectScale.z); // calculate new object scale with p
  1765.  
  1766. attachedObject.transform.rotation = handRot * initialObjectRotation; // add rotation
  1767. attachedObject.transform.localScale = newScale; // set new scale
  1768. // set the position of the object to the center of both hands based on the original object direction relative to the new scale and rotation
  1769. attachedObject.transform.position = (0.5f * (currentHandPosition1 + currentHandPosition2)) + (handRot * (initialObjectDirection * p));
  1770.  
  1771. }
  1772.  
  1773. }
  1774. // ADDED FOR TWO HAND INTERACTION END
  1775.  
  1776. }
  1777.  
  1778.  
  1779. [System.Serializable]
  1780. public class HandEvent : UnityEvent<Hand> { }
  1781.  
  1782.  
  1783. #if UNITY_EDITOR
  1784. //-------------------------------------------------------------------------
  1785. [UnityEditor.CustomEditor(typeof(Hand))]
  1786. public class HandEditor : UnityEditor.Editor
  1787. {
  1788. //-------------------------------------------------
  1789. // Custom Inspector GUI allows us to click from within the UI
  1790. //-------------------------------------------------
  1791. public override void OnInspectorGUI()
  1792. {
  1793. DrawDefaultInspector();
  1794.  
  1795. /*
  1796. Hand hand = (Hand)target;
  1797.  
  1798. if (hand.otherHand)
  1799. {
  1800. if (hand.otherHand.otherHand != hand)
  1801. {
  1802. UnityEditor.EditorGUILayout.HelpBox("The otherHand of this Hand's otherHand is not this Hand.", UnityEditor.MessageType.Warning);
  1803. }
  1804.  
  1805. if (hand.handType == SteamVR_Input_Sources.LeftHand && hand.otherHand && hand.otherHand.handType != SteamVR_Input_Sources.RightHand)
  1806. {
  1807. UnityEditor.EditorGUILayout.HelpBox("This is a left Hand but otherHand is not a right Hand.", UnityEditor.MessageType.Warning);
  1808. }
  1809.  
  1810. if (hand.handType == SteamVR_Input_Sources.RightHand && hand.otherHand && hand.otherHand.handType != SteamVR_Input_Sources.LeftHand)
  1811. {
  1812. UnityEditor.EditorGUILayout.HelpBox("This is a right Hand but otherHand is not a left Hand.", UnityEditor.MessageType.Warning);
  1813. }
  1814.  
  1815. if (hand.handType == SteamVR_Input_Sources.Any && hand.otherHand && hand.otherHand.handType != SteamVR_Input_Sources.Any)
  1816. {
  1817. UnityEditor.EditorGUILayout.HelpBox("This is an any-handed Hand but otherHand is not an any-handed Hand.", UnityEditor.MessageType.Warning);
  1818. }
  1819. }
  1820. */ //removing for now because it conflicts with other input sources (trackers and such)
  1821. }
  1822. }
  1823. #endif
  1824. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement