1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681 |
- //======= Copyright (c) Valve Corporation, All rights reserved. ===============
- //
- // Purpose: The hands used by the player in the vr interaction system
- //
- //=============================================================================
- using UnityEngine;
- using System;
- using System.Collections;
- using System.Collections.Generic;
- using System.Collections.ObjectModel;
- using UnityEngine.Events;
- using System.Threading;
- namespace Valve.VR.InteractionSystem
- {
- //-------------------------------------------------------------------------
- // Links with an appropriate SteamVR controller and facilitates
- // interactions with objects in the virtual world.
- //-------------------------------------------------------------------------
- public class Hand : MonoBehaviour
- {
- // The flags used to determine how an object is attached to the hand.
- [Flags]
- public enum AttachmentFlags
- {
- SnapOnAttach = 1 << 0, // The object should snap to the position of the specified attachment point on the hand.
- DetachOthers = 1 << 1, // Other objects attached to this hand will be detached.
- DetachFromOtherHand = 1 << 2, // This object will be detached from the other hand.
- ParentToHand = 1 << 3, // The object will be parented to the hand.
- VelocityMovement = 1 << 4, // The object will attempt to move to match the position and rotation of the hand.
- TurnOnKinematic = 1 << 5, // The object will not respond to external physics.
- TurnOffGravity = 1 << 6, // The object will not respond to external physics.
- 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
- };
- public const AttachmentFlags defaultAttachmentFlags = AttachmentFlags.ParentToHand |
- AttachmentFlags.DetachOthers |
- AttachmentFlags.DetachFromOtherHand |
- AttachmentFlags.TurnOnKinematic |
- AttachmentFlags.SnapOnAttach;
- public Hand otherHand;
- public SteamVR_Input_Sources handType;
- public SteamVR_Behaviour_Pose trackedObject;
-
- public SteamVR_Action_Boolean grabPinchAction = SteamVR_Input.GetAction<SteamVR_Action_Boolean>("GrabPinch");
-
- public SteamVR_Action_Boolean grabGripAction = SteamVR_Input.GetAction<SteamVR_Action_Boolean>("GrabGrip");
-
- public SteamVR_Action_Vibration hapticAction = SteamVR_Input.GetAction<SteamVR_Action_Vibration>("Haptic");
-
- public SteamVR_Action_Boolean uiInteractAction = SteamVR_Input.GetAction<SteamVR_Action_Boolean>("InteractUI");
- public bool useHoverSphere = true;
- public Transform hoverSphereTransform;
- public float hoverSphereRadius = 0.05f;
- public LayerMask hoverLayerMask = -1;
- public float hoverUpdateInterval = 0.1f;
- public bool useControllerHoverComponent = true;
- public string controllerHoverComponent = "tip";
- public float controllerHoverRadius = 0.075f;
- public bool useFingerJointHover = true;
- public SteamVR_Skeleton_JointIndexEnum fingerJointHover = SteamVR_Skeleton_JointIndexEnum.indexTip;
- public float fingerJointHoverRadius = 0.025f;
- [Tooltip("A transform on the hand to center attached objects on")]
- public Transform objectAttachmentPoint;
- public Camera noSteamVRFallbackCamera;
- public float noSteamVRFallbackMaxDistanceNoItem = 10.0f;
- public float noSteamVRFallbackMaxDistanceWithItem = 0.5f;
- private float noSteamVRFallbackInteractorDistance = -1.0f;
- public GameObject renderModelPrefab;
- protected List<RenderModel> renderModels = new List<RenderModel>();
- protected RenderModel mainRenderModel;
- protected RenderModel hoverhighlightRenderModel;
- public bool showDebugText = false;
- public bool spewDebugText = false;
- public bool showDebugInteractables = false;
- public struct AttachedObject
- {
- public GameObject attachedObject;
- public Interactable interactable;
- public Rigidbody attachedRigidbody;
- public CollisionDetectionMode collisionDetectionMode;
- public bool attachedRigidbodyWasKinematic;
- public bool attachedRigidbodyUsedGravity;
- public GameObject originalParent;
- public bool isParentedToHand;
- public GrabTypes grabbedWithType;
- public AttachmentFlags attachmentFlags;
- public Vector3 initialPositionalOffset;
- public Quaternion initialRotationalOffset;
- public Transform attachedOffsetTransform;
- public Transform handAttachmentPointTransform;
- public Vector3 easeSourcePosition;
- public Quaternion easeSourceRotation;
- public float attachTime;
- public bool HasAttachFlag(AttachmentFlags flag)
- {
- return (attachmentFlags & flag) == flag;
- }
- }
- private List<AttachedObject> attachedObjects = new List<AttachedObject>();
- public ReadOnlyCollection<AttachedObject> AttachedObjects
- {
- get { return attachedObjects.AsReadOnly(); }
- }
- public bool hoverLocked { get; private set; }
- private Interactable _hoveringInteractable;
- private TextMesh debugText;
- private int prevOverlappingColliders = 0;
- private const int ColliderArraySize = 16;
- private Collider[] overlappingColliders;
- private Player playerInstance;
- private GameObject applicationLostFocusObject;
- private SteamVR_Events.Action inputFocusAction;
- public bool isActive
- {
- get
- {
- if (trackedObject != null)
- return trackedObject.isActive;
- return this.gameObject.activeInHierarchy;
- }
- }
- public bool isPoseValid
- {
- get
- {
- return trackedObject.isValid;
- }
- }
- //-------------------------------------------------
- // The Interactable object this Hand is currently hovering over
- //-------------------------------------------------
- public Interactable hoveringInteractable
- {
- get { return _hoveringInteractable; }
- set
- {
- if (_hoveringInteractable != value)
- {
- if (_hoveringInteractable != null)
- {
- if (spewDebugText)
- HandDebugLog("HoverEnd " + _hoveringInteractable.gameObject);
- _hoveringInteractable.SendMessage("OnHandHoverEnd", this, SendMessageOptions.DontRequireReceiver);
- //Note: The _hoveringInteractable can change after sending the OnHandHoverEnd message so we need to check it again before broadcasting this message
- if (_hoveringInteractable != null)
- {
- this.BroadcastMessage("OnParentHandHoverEnd", _hoveringInteractable, SendMessageOptions.DontRequireReceiver); // let objects attached to the hand know that a hover has ended
- }
- }
- _hoveringInteractable = value;
- if (_hoveringInteractable != null)
- {
- if (spewDebugText)
- HandDebugLog("HoverBegin " + _hoveringInteractable.gameObject);
- _hoveringInteractable.SendMessage("OnHandHoverBegin", this, SendMessageOptions.DontRequireReceiver);
- //Note: The _hoveringInteractable can change after sending the OnHandHoverBegin message so we need to check it again before broadcasting this message
- if (_hoveringInteractable != null)
- {
- this.BroadcastMessage("OnParentHandHoverBegin", _hoveringInteractable, SendMessageOptions.DontRequireReceiver); // let objects attached to the hand know that a hover has begun
- }
- }
- }
- }
- }
- //-------------------------------------------------
- // Active GameObject attached to this Hand
- //-------------------------------------------------
- public GameObject currentAttachedObject
- {
- get
- {
- CleanUpAttachedObjectStack();
- if (attachedObjects.Count > 0)
- {
- return attachedObjects[attachedObjects.Count - 1].attachedObject;
- }
- return null;
- }
- }
- public AttachedObject? currentAttachedObjectInfo
- {
- get
- {
- CleanUpAttachedObjectStack();
- if (attachedObjects.Count > 0)
- {
- return attachedObjects[attachedObjects.Count - 1];
- }
- return null;
- }
- }
- public SteamVR_Behaviour_Skeleton skeleton
- {
- get
- {
- if (mainRenderModel != null)
- return mainRenderModel.GetSkeleton();
- return null;
- }
- }
- public void ShowController(bool permanent = false)
- {
- if (mainRenderModel != null)
- mainRenderModel.SetControllerVisibility(true, permanent);
- if (hoverhighlightRenderModel != null)
- hoverhighlightRenderModel.SetControllerVisibility(true, permanent);
- }
- public void HideController(bool permanent = false)
- {
- if (mainRenderModel != null)
- mainRenderModel.SetControllerVisibility(false, permanent);
- if (hoverhighlightRenderModel != null)
- hoverhighlightRenderModel.SetControllerVisibility(false, permanent);
- }
- public void ShowSkeleton(bool permanent = false)
- {
- if (mainRenderModel != null)
- mainRenderModel.SetHandVisibility(true, permanent);
- if (hoverhighlightRenderModel != null)
- hoverhighlightRenderModel.SetHandVisibility(true, permanent);
- }
- public void HideSkeleton(bool permanent = false)
- {
- if (mainRenderModel != null)
- mainRenderModel.SetHandVisibility(false, permanent);
- if (hoverhighlightRenderModel != null)
- hoverhighlightRenderModel.SetHandVisibility(false, permanent);
- }
- public bool HasSkeleton()
- {
- return mainRenderModel != null && mainRenderModel.GetSkeleton() != null;
- }
- public void Show()
- {
- SetVisibility(true);
- }
- public void Hide()
- {
- SetVisibility(false);
- }
- public void SetVisibility(bool visible)
- {
- if (mainRenderModel != null)
- mainRenderModel.SetVisibility(visible);
- }
- public void SetSkeletonRangeOfMotion(EVRSkeletalMotionRange newRangeOfMotion, float blendOverSeconds = 0.1f)
- {
- for (int renderModelIndex = 0; renderModelIndex < renderModels.Count; renderModelIndex++)
- {
- renderModels[renderModelIndex].SetSkeletonRangeOfMotion(newRangeOfMotion, blendOverSeconds);
- }
- }
- public void SetTemporarySkeletonRangeOfMotion(SkeletalMotionRangeChange temporaryRangeOfMotionChange, float blendOverSeconds = 0.1f)
- {
- for (int renderModelIndex = 0; renderModelIndex < renderModels.Count; renderModelIndex++)
- {
- renderModels[renderModelIndex].SetTemporarySkeletonRangeOfMotion(temporaryRangeOfMotionChange, blendOverSeconds);
- }
- }
- public void ResetTemporarySkeletonRangeOfMotion(float blendOverSeconds = 0.1f)
- {
- for (int renderModelIndex = 0; renderModelIndex < renderModels.Count; renderModelIndex++)
- {
- renderModels[renderModelIndex].ResetTemporarySkeletonRangeOfMotion(blendOverSeconds);
- }
- }
- public void SetAnimationState(int stateValue)
- {
- for (int renderModelIndex = 0; renderModelIndex < renderModels.Count; renderModelIndex++)
- {
- renderModels[renderModelIndex].SetAnimationState(stateValue);
- }
- }
- public void StopAnimation()
- {
- for (int renderModelIndex = 0; renderModelIndex < renderModels.Count; renderModelIndex++)
- {
- renderModels[renderModelIndex].StopAnimation();
- }
- }
- //-------------------------------------------------
- // Attach a GameObject to this GameObject
- //
- // objectToAttach - The GameObject to attach
- // flags - The flags to use for attaching the object
- // attachmentPoint - Name of the GameObject in the hierarchy of this Hand which should act as the attachment point for this GameObject
- //-------------------------------------------------
- public void AttachObject(GameObject objectToAttach, GrabTypes grabbedWithType, AttachmentFlags flags = defaultAttachmentFlags, Transform attachmentOffset = null)
- {
- AttachedObject attachedObject = new AttachedObject();
- attachedObject.attachmentFlags = flags;
- attachedObject.attachedOffsetTransform = attachmentOffset;
- attachedObject.attachTime = Time.time;
- if (flags == 0)
- {
- flags = defaultAttachmentFlags;
- }
- //Make sure top object on stack is non-null
- CleanUpAttachedObjectStack();
- //Detach the object if it is already attached so that it can get re-attached at the top of the stack
- if(ObjectIsAttached(objectToAttach))
- DetachObject(objectToAttach);
- //Detach from the other hand if requested
- if (attachedObject.HasAttachFlag(AttachmentFlags.DetachFromOtherHand))
- {
- if (otherHand != null)
- otherHand.DetachObject(objectToAttach);
- }
- if (attachedObject.HasAttachFlag(AttachmentFlags.DetachOthers))
- {
- //Detach all the objects from the stack
- while (attachedObjects.Count > 0)
- {
- DetachObject(attachedObjects[0].attachedObject);
- }
- }
- if (currentAttachedObject)
- {
- currentAttachedObject.SendMessage("OnHandFocusLost", this, SendMessageOptions.DontRequireReceiver);
- }
- attachedObject.attachedObject = objectToAttach;
- attachedObject.interactable = objectToAttach.GetComponent<Interactable>();
- attachedObject.handAttachmentPointTransform = this.transform;
- if (attachedObject.interactable != null)
- {
- if (attachedObject.interactable.attachEaseIn)
- {
- attachedObject.easeSourcePosition = attachedObject.attachedObject.transform.position;
- attachedObject.easeSourceRotation = attachedObject.attachedObject.transform.rotation;
- attachedObject.interactable.snapAttachEaseInCompleted = false;
- }
- if (attachedObject.interactable.useHandObjectAttachmentPoint)
- attachedObject.handAttachmentPointTransform = objectAttachmentPoint;
- if (attachedObject.interactable.hideHandOnAttach)
- Hide();
- if (attachedObject.interactable.hideSkeletonOnAttach && mainRenderModel != null && mainRenderModel.displayHandByDefault)
- HideSkeleton();
- if (attachedObject.interactable.hideControllerOnAttach && mainRenderModel != null && mainRenderModel.displayControllerByDefault)
- HideController();
- if (attachedObject.interactable.handAnimationOnPickup != 0)
- SetAnimationState(attachedObject.interactable.handAnimationOnPickup);
- if (attachedObject.interactable.setRangeOfMotionOnPickup != SkeletalMotionRangeChange.None)
- SetTemporarySkeletonRangeOfMotion(attachedObject.interactable.setRangeOfMotionOnPickup);
- }
- attachedObject.originalParent = objectToAttach.transform.parent != null ? objectToAttach.transform.parent.gameObject : null;
- attachedObject.attachedRigidbody = objectToAttach.GetComponent<Rigidbody>();
- if (attachedObject.attachedRigidbody != null)
- {
- if (attachedObject.interactable.attachedToHand != null) //already attached to another hand
- {
- //if it was attached to another hand, get the flags from that hand
-
- for (int attachedIndex = 0; attachedIndex < attachedObject.interactable.attachedToHand.attachedObjects.Count; attachedIndex++)
- {
- AttachedObject attachedObjectInList = attachedObject.interactable.attachedToHand.attachedObjects[attachedIndex];
- if (attachedObjectInList.interactable == attachedObject.interactable)
- {
- attachedObject.attachedRigidbodyWasKinematic = attachedObjectInList.attachedRigidbodyWasKinematic;
- attachedObject.attachedRigidbodyUsedGravity = attachedObjectInList.attachedRigidbodyUsedGravity;
- attachedObject.originalParent = attachedObjectInList.originalParent;
- }
- }
- }
- else
- {
- attachedObject.attachedRigidbodyWasKinematic = attachedObject.attachedRigidbody.isKinematic;
- attachedObject.attachedRigidbodyUsedGravity = attachedObject.attachedRigidbody.useGravity;
- }
- }
- attachedObject.grabbedWithType = grabbedWithType;
- if (attachedObject.HasAttachFlag(AttachmentFlags.ParentToHand))
- {
- //Parent the object to the hand
- objectToAttach.transform.parent = this.transform;
- attachedObject.isParentedToHand = true;
- }
- else
- {
- attachedObject.isParentedToHand = false;
- }
- if (attachedObject.HasAttachFlag(AttachmentFlags.SnapOnAttach))
- {
- if (attachedObject.interactable != null && attachedObject.interactable.skeletonPoser != null && HasSkeleton())
- {
- SteamVR_Skeleton_PoseSnapshot pose = attachedObject.interactable.skeletonPoser.GetBlendedPose(skeleton);
- //snap the object to the center of the attach point
- objectToAttach.transform.position = this.transform.TransformPoint(pose.position);
- objectToAttach.transform.rotation = this.transform.rotation * pose.rotation;
- attachedObject.initialPositionalOffset = attachedObject.handAttachmentPointTransform.InverseTransformPoint(objectToAttach.transform.position);
- attachedObject.initialRotationalOffset = Quaternion.Inverse(attachedObject.handAttachmentPointTransform.rotation) * objectToAttach.transform.rotation;
- }
- else
- {
- if (attachmentOffset != null)
- {
- //offset the object from the hand by the positional and rotational difference between the offset transform and the attached object
- Quaternion rotDiff = Quaternion.Inverse(attachmentOffset.transform.rotation) * objectToAttach.transform.rotation;
- objectToAttach.transform.rotation = attachedObject.handAttachmentPointTransform.rotation * rotDiff;
- Vector3 posDiff = objectToAttach.transform.position - attachmentOffset.transform.position;
- objectToAttach.transform.position = attachedObject.handAttachmentPointTransform.position + posDiff;
- }
- else
- {
- //snap the object to the center of the attach point
- objectToAttach.transform.rotation = attachedObject.handAttachmentPointTransform.rotation;
- objectToAttach.transform.position = attachedObject.handAttachmentPointTransform.position;
- }
- Transform followPoint = objectToAttach.transform;
- attachedObject.initialPositionalOffset = attachedObject.handAttachmentPointTransform.InverseTransformPoint(followPoint.position);
- attachedObject.initialRotationalOffset = Quaternion.Inverse(attachedObject.handAttachmentPointTransform.rotation) * followPoint.rotation;
- }
- }
- else
- {
- if (attachedObject.interactable != null && attachedObject.interactable.skeletonPoser != null && HasSkeleton())
- {
- attachedObject.initialPositionalOffset = attachedObject.handAttachmentPointTransform.InverseTransformPoint(objectToAttach.transform.position);
- attachedObject.initialRotationalOffset = Quaternion.Inverse(attachedObject.handAttachmentPointTransform.rotation) * objectToAttach.transform.rotation;
- }
- else
- {
- if (attachmentOffset != null)
- {
- //get the initial positional and rotational offsets between the hand and the offset transform
- Quaternion rotDiff = Quaternion.Inverse(attachmentOffset.transform.rotation) * objectToAttach.transform.rotation;
- Quaternion targetRotation = attachedObject.handAttachmentPointTransform.rotation * rotDiff;
- Quaternion rotationPositionBy = targetRotation * Quaternion.Inverse(objectToAttach.transform.rotation);
- Vector3 posDiff = (rotationPositionBy * objectToAttach.transform.position) - (rotationPositionBy * attachmentOffset.transform.position);
- attachedObject.initialPositionalOffset = attachedObject.handAttachmentPointTransform.InverseTransformPoint(attachedObject.handAttachmentPointTransform.position + posDiff);
- attachedObject.initialRotationalOffset = Quaternion.Inverse(attachedObject.handAttachmentPointTransform.rotation) * (attachedObject.handAttachmentPointTransform.rotation * rotDiff);
- }
- else
- {
- attachedObject.initialPositionalOffset = attachedObject.handAttachmentPointTransform.InverseTransformPoint(objectToAttach.transform.position);
- attachedObject.initialRotationalOffset = Quaternion.Inverse(attachedObject.handAttachmentPointTransform.rotation) * objectToAttach.transform.rotation;
- }
- }
- }
- if (attachedObject.HasAttachFlag(AttachmentFlags.TurnOnKinematic))
- {
- if (attachedObject.attachedRigidbody != null)
- {
- attachedObject.collisionDetectionMode = attachedObject.attachedRigidbody.collisionDetectionMode;
- if (attachedObject.collisionDetectionMode == CollisionDetectionMode.Continuous)
- attachedObject.attachedRigidbody.collisionDetectionMode = CollisionDetectionMode.Discrete;
- attachedObject.attachedRigidbody.isKinematic = true;
- }
- }
- if (attachedObject.HasAttachFlag(AttachmentFlags.TurnOffGravity))
- {
- if (attachedObject.attachedRigidbody != null)
- {
- attachedObject.attachedRigidbody.useGravity = false;
- }
- }
- if (attachedObject.interactable != null && attachedObject.interactable.attachEaseIn)
- {
- attachedObject.attachedObject.transform.position = attachedObject.easeSourcePosition;
- attachedObject.attachedObject.transform.rotation = attachedObject.easeSourceRotation;
- }
- attachedObjects.Add(attachedObject);
- UpdateHovering();
- if (spewDebugText)
- HandDebugLog("AttachObject " + objectToAttach);
- objectToAttach.SendMessage("OnAttachedToHand", this, SendMessageOptions.DontRequireReceiver);
- }
- public bool ObjectIsAttached(GameObject go)
- {
- for (int attachedIndex = 0; attachedIndex < attachedObjects.Count; attachedIndex++)
- {
- if (attachedObjects[attachedIndex].attachedObject == go)
- return true;
- }
- return false;
- }
- public void ForceHoverUnlock()
- {
- hoverLocked = false;
- }
- //-------------------------------------------------
- // Detach this GameObject from the attached object stack of this Hand
- //
- // objectToDetach - The GameObject to detach from this Hand
- //-------------------------------------------------
- public void DetachObject(GameObject objectToDetach, bool restoreOriginalParent = true)
- {
- int index = attachedObjects.FindIndex(l => l.attachedObject == objectToDetach);
- if (index != -1)
- {
- if (spewDebugText)
- HandDebugLog("DetachObject " + objectToDetach);
- GameObject prevTopObject = currentAttachedObject;
- if (attachedObjects[index].interactable != null)
- {
- if (attachedObjects[index].interactable.hideHandOnAttach)
- Show();
- if (attachedObjects[index].interactable.hideSkeletonOnAttach && mainRenderModel != null && mainRenderModel.displayHandByDefault)
- ShowSkeleton();
- if (attachedObjects[index].interactable.hideControllerOnAttach && mainRenderModel != null && mainRenderModel.displayControllerByDefault)
- ShowController();
- if (attachedObjects[index].interactable.handAnimationOnPickup != 0)
- StopAnimation();
- if (attachedObjects[index].interactable.setRangeOfMotionOnPickup != SkeletalMotionRangeChange.None)
- ResetTemporarySkeletonRangeOfMotion();
- }
- Transform parentTransform = null;
- if (attachedObjects[index].isParentedToHand)
- {
- if (restoreOriginalParent && (attachedObjects[index].originalParent != null))
- {
- parentTransform = attachedObjects[index].originalParent.transform;
- }
- if (attachedObjects[index].attachedObject != null)
- {
- attachedObjects[index].attachedObject.transform.parent = parentTransform;
- }
- }
- if (attachedObjects[index].HasAttachFlag(AttachmentFlags.TurnOnKinematic))
- {
- if (attachedObjects[index].attachedRigidbody != null)
- {
- attachedObjects[index].attachedRigidbody.isKinematic = attachedObjects[index].attachedRigidbodyWasKinematic;
- attachedObjects[index].attachedRigidbody.collisionDetectionMode = attachedObjects[index].collisionDetectionMode;
- }
- }
- if (attachedObjects[index].HasAttachFlag(AttachmentFlags.TurnOffGravity))
- {
- if (attachedObjects[index].attachedObject != null)
- {
- if (attachedObjects[index].attachedRigidbody != null)
- attachedObjects[index].attachedRigidbody.useGravity = attachedObjects[index].attachedRigidbodyUsedGravity;
- }
- }
- if (attachedObjects[index].interactable != null && attachedObjects[index].interactable.handFollowTransform && HasSkeleton())
- {
- skeleton.transform.localPosition = Vector3.zero;
- skeleton.transform.localRotation = Quaternion.identity;
- }
- if (attachedObjects[index].attachedObject != null)
- {
- if (attachedObjects[index].interactable == null || (attachedObjects[index].interactable != null && attachedObjects[index].interactable.isDestroying == false))
- attachedObjects[index].attachedObject.SetActive(true);
- attachedObjects[index].attachedObject.SendMessage("OnDetachedFromHand", this, SendMessageOptions.DontRequireReceiver);
- }
- attachedObjects.RemoveAt(index);
- CleanUpAttachedObjectStack();
- GameObject newTopObject = currentAttachedObject;
- hoverLocked = false;
- //Give focus to the top most object on the stack if it changed
- if (newTopObject != null && newTopObject != prevTopObject)
- {
- newTopObject.SetActive(true);
- newTopObject.SendMessage("OnHandFocusAcquired", this, SendMessageOptions.DontRequireReceiver);
- }
- }
- CleanUpAttachedObjectStack();
- if (mainRenderModel != null)
- mainRenderModel.MatchHandToTransform(mainRenderModel.transform);
- if (hoverhighlightRenderModel != null)
- hoverhighlightRenderModel.MatchHandToTransform(hoverhighlightRenderModel.transform);
- }
- //-------------------------------------------------
- // Get the world velocity of the VR Hand.
- //-------------------------------------------------
- public Vector3 GetTrackedObjectVelocity(float timeOffset = 0)
- {
- if (trackedObject == null)
- {
- Vector3 velocityTarget, angularTarget;
- GetUpdatedAttachedVelocities(currentAttachedObjectInfo.Value, out velocityTarget, out angularTarget);
- return velocityTarget;
- }
- if (isActive)
- {
- if (timeOffset == 0)
- return Player.instance.trackingOriginTransform.TransformVector(trackedObject.GetVelocity());
- else
- {
- Vector3 velocity;
- Vector3 angularVelocity;
- trackedObject.GetVelocitiesAtTimeOffset(timeOffset, out velocity, out angularVelocity);
- return Player.instance.trackingOriginTransform.TransformVector(velocity);
- }
- }
- return Vector3.zero;
- }
-
- //-------------------------------------------------
- // Get the world space angular velocity of the VR Hand.
- //-------------------------------------------------
- public Vector3 GetTrackedObjectAngularVelocity(float timeOffset = 0)
- {
- if (trackedObject == null)
- {
- Vector3 velocityTarget, angularTarget;
- GetUpdatedAttachedVelocities(currentAttachedObjectInfo.Value, out velocityTarget, out angularTarget);
- return angularTarget;
- }
- if (isActive)
- {
- if (timeOffset == 0)
- return Player.instance.trackingOriginTransform.TransformDirection(trackedObject.GetAngularVelocity());
- else
- {
- Vector3 velocity;
- Vector3 angularVelocity;
- trackedObject.GetVelocitiesAtTimeOffset(timeOffset, out velocity, out angularVelocity);
- return Player.instance.trackingOriginTransform.TransformDirection(angularVelocity);
- }
- }
- return Vector3.zero;
- }
- public void GetEstimatedPeakVelocities(out Vector3 velocity, out Vector3 angularVelocity)
- {
- trackedObject.GetEstimatedPeakVelocities(out velocity, out angularVelocity);
- velocity = Player.instance.trackingOriginTransform.TransformVector(velocity);
- angularVelocity = Player.instance.trackingOriginTransform.TransformDirection(angularVelocity);
- }
- //-------------------------------------------------
- private void CleanUpAttachedObjectStack()
- {
- attachedObjects.RemoveAll(l => l.attachedObject == null);
- }
- //-------------------------------------------------
- protected virtual void Awake()
- {
- inputFocusAction = SteamVR_Events.InputFocusAction(OnInputFocus);
- if (hoverSphereTransform == null)
- hoverSphereTransform = this.transform;
- if (objectAttachmentPoint == null)
- objectAttachmentPoint = this.transform;
- applicationLostFocusObject = new GameObject("_application_lost_focus");
- applicationLostFocusObject.transform.parent = transform;
- applicationLostFocusObject.SetActive(false);
- if (trackedObject == null)
- {
- trackedObject = this.gameObject.GetComponent<SteamVR_Behaviour_Pose>();
- if (trackedObject != null)
- trackedObject.onTransformUpdatedEvent += OnTransformUpdated;
- }
- }
- protected virtual void OnDestroy()
- {
- if (trackedObject != null)
- {
- trackedObject.onTransformUpdatedEvent -= OnTransformUpdated;
- }
- }
- protected virtual void OnTransformUpdated(SteamVR_Behaviour_Pose updatedPose, SteamVR_Input_Sources updatedSource)
- {
- HandFollowUpdate();
- }
- //-------------------------------------------------
- protected virtual IEnumerator Start()
- {
- // save off player instance
- playerInstance = Player.instance;
- if (!playerInstance)
- {
- Debug.LogError("<b>[SteamVR Interaction]</b> No player instance found in Hand Start()");
- }
- // allocate array for colliders
- overlappingColliders = new Collider[ColliderArraySize];
- // We are a "no SteamVR fallback hand" if we have this camera set
- // we'll use the right mouse to look around and left mouse to interact
- // - don't need to find the device
- if (noSteamVRFallbackCamera)
- {
- yield break;
- }
- //Debug.Log( "<b>[SteamVR Interaction]</b> Hand - initializing connection routine" );
- while (true)
- {
- if (isPoseValid)
- {
- InitController();
- break;
- }
- yield return null;
- }
- }
- //-------------------------------------------------
- protected virtual void UpdateHovering()
- {
- if ((noSteamVRFallbackCamera == null) && (isActive == false))
- {
- return;
- }
- if (hoverLocked)
- return;
- if (applicationLostFocusObject.activeSelf)
- return;
- float closestDistance = float.MaxValue;
- Interactable closestInteractable = null;
- if (useHoverSphere)
- {
- float scaledHoverRadius = hoverSphereRadius * Mathf.Abs(SteamVR_Utils.GetLossyScale(hoverSphereTransform));
- CheckHoveringForTransform(hoverSphereTransform.position, scaledHoverRadius, ref closestDistance, ref closestInteractable, Color.green);
- }
- if (useControllerHoverComponent && mainRenderModel != null && mainRenderModel.IsControllerVisibile())
- {
- float scaledHoverRadius = controllerHoverRadius * Mathf.Abs(SteamVR_Utils.GetLossyScale(this.transform));
- CheckHoveringForTransform(mainRenderModel.GetControllerPosition(controllerHoverComponent), scaledHoverRadius / 2f, ref closestDistance, ref closestInteractable, Color.blue);
- }
- if (useFingerJointHover && mainRenderModel != null && mainRenderModel.IsHandVisibile())
- {
- float scaledHoverRadius = fingerJointHoverRadius * Mathf.Abs(SteamVR_Utils.GetLossyScale(this.transform));
- CheckHoveringForTransform(mainRenderModel.GetBonePosition((int)fingerJointHover), scaledHoverRadius / 2f, ref closestDistance, ref closestInteractable, Color.yellow);
- }
- // Hover on this one
- hoveringInteractable = closestInteractable;
- }
- protected virtual bool CheckHoveringForTransform(Vector3 hoverPosition, float hoverRadius, ref float closestDistance, ref Interactable closestInteractable, Color debugColor)
- {
- bool foundCloser = false;
- // null out old vals
- for (int i = 0; i < overlappingColliders.Length; ++i)
- {
- overlappingColliders[i] = null;
- }
- int numColliding = Physics.OverlapSphereNonAlloc(hoverPosition, hoverRadius, overlappingColliders, hoverLayerMask.value);
- if (numColliding == ColliderArraySize)
- 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");
- // DebugVar
- int iActualColliderCount = 0;
- // Pick the closest hovering
- for (int colliderIndex = 0; colliderIndex < overlappingColliders.Length; colliderIndex++)
- {
- Collider collider = overlappingColliders[colliderIndex];
- if (collider == null)
- continue;
- Interactable contacting = collider.GetComponentInParent<Interactable>();
- // Yeah, it's null, skip
- if (contacting == null)
- continue;
- // Ignore this collider for hovering
- IgnoreHovering ignore = collider.GetComponent<IgnoreHovering>();
- if (ignore != null)
- {
- if (ignore.onlyIgnoreHand == null || ignore.onlyIgnoreHand == this)
- {
- continue;
- }
- }
- // Can't hover over the object if it's attached
- bool hoveringOverAttached = false;
- for (int attachedIndex = 0; attachedIndex < attachedObjects.Count; attachedIndex++)
- {
- if (attachedObjects[attachedIndex].attachedObject == contacting.gameObject)
- {
- hoveringOverAttached = true;
- break;
- }
- }
- if (hoveringOverAttached)
- continue;
- // Occupied by another hand, so we can't touch it
- if (otherHand && otherHand.hoveringInteractable == contacting)
- continue;
- // Best candidate so far...
- float distance = Vector3.Distance(contacting.transform.position, hoverPosition);
- if (distance < closestDistance)
- {
- closestDistance = distance;
- closestInteractable = contacting;
- foundCloser = true;
- }
- iActualColliderCount++;
- }
- if (showDebugInteractables && foundCloser)
- {
- Debug.DrawLine(hoverPosition, closestInteractable.transform.position, debugColor, .05f, false);
- }
- if (iActualColliderCount > 0 && iActualColliderCount != prevOverlappingColliders)
- {
- prevOverlappingColliders = iActualColliderCount;
- if (spewDebugText)
- HandDebugLog("Found " + iActualColliderCount + " overlapping colliders.");
- }
- return foundCloser;
- }
- //-------------------------------------------------
- protected virtual void UpdateNoSteamVRFallback()
- {
- if (noSteamVRFallbackCamera)
- {
- Ray ray = noSteamVRFallbackCamera.ScreenPointToRay(Input.mousePosition);
- if (attachedObjects.Count > 0)
- {
- // Holding down the mouse:
- // move around a fixed distance from the camera
- transform.position = ray.origin + noSteamVRFallbackInteractorDistance * ray.direction;
- }
- else
- {
- // Not holding down the mouse:
- // cast out a ray to see what we should mouse over
- // Don't want to hit the hand and anything underneath it
- // So move it back behind the camera when we do the raycast
- Vector3 oldPosition = transform.position;
- transform.position = noSteamVRFallbackCamera.transform.forward * (-1000.0f);
- RaycastHit raycastHit;
- if (Physics.Raycast(ray, out raycastHit, noSteamVRFallbackMaxDistanceNoItem))
- {
- transform.position = raycastHit.point;
- // Remember this distance in case we click and drag the mouse
- noSteamVRFallbackInteractorDistance = Mathf.Min(noSteamVRFallbackMaxDistanceNoItem, raycastHit.distance);
- }
- else if (noSteamVRFallbackInteractorDistance > 0.0f)
- {
- // Move it around at the distance we last had a hit
- transform.position = ray.origin + Mathf.Min(noSteamVRFallbackMaxDistanceNoItem, noSteamVRFallbackInteractorDistance) * ray.direction;
- }
- else
- {
- // Didn't hit, just leave it where it was
- transform.position = oldPosition;
- }
- }
- }
- }
- //-------------------------------------------------
- private void UpdateDebugText()
- {
- if (showDebugText)
- {
- if (debugText == null)
- {
- debugText = new GameObject("_debug_text").AddComponent<TextMesh>();
- debugText.fontSize = 120;
- debugText.characterSize = 0.001f;
- debugText.transform.parent = transform;
- debugText.transform.localRotation = Quaternion.Euler(90.0f, 0.0f, 0.0f);
- }
- if (handType == SteamVR_Input_Sources.RightHand)
- {
- debugText.transform.localPosition = new Vector3(-0.05f, 0.0f, 0.0f);
- debugText.alignment = TextAlignment.Right;
- debugText.anchor = TextAnchor.UpperRight;
- }
- else
- {
- debugText.transform.localPosition = new Vector3(0.05f, 0.0f, 0.0f);
- debugText.alignment = TextAlignment.Left;
- debugText.anchor = TextAnchor.UpperLeft;
- }
- debugText.text = string.Format(
- "Hovering: {0}\n" +
- "Hover Lock: {1}\n" +
- "Attached: {2}\n" +
- "Total Attached: {3}\n" +
- "Type: {4}\n",
- (hoveringInteractable ? hoveringInteractable.gameObject.name : "null"),
- hoverLocked,
- (currentAttachedObject ? currentAttachedObject.name : "null"),
- attachedObjects.Count,
- handType.ToString());
- }
- else
- {
- if (debugText != null)
- {
- Destroy(debugText.gameObject);
- }
- }
- }
- //-------------------------------------------------
- protected virtual void OnEnable()
- {
- inputFocusAction.enabled = true;
- // Stagger updates between hands
- float hoverUpdateBegin = ((otherHand != null) && (otherHand.GetInstanceID() < GetInstanceID())) ? (0.5f * hoverUpdateInterval) : (0.0f);
- InvokeRepeating("UpdateHovering", hoverUpdateBegin, hoverUpdateInterval);
- InvokeRepeating("UpdateDebugText", hoverUpdateBegin, hoverUpdateInterval);
- }
- //-------------------------------------------------
- protected virtual void OnDisable()
- {
- inputFocusAction.enabled = false;
- CancelInvoke();
- }
-
- //-------------------------------------------------
- protected virtual void Update()
- {
- UpdateNoSteamVRFallback();
- GameObject attachedObject = currentAttachedObject;
- if (attachedObject != null)
- {
- attachedObject.SendMessage("HandAttachedUpdate", this, SendMessageOptions.DontRequireReceiver);
- }
- if (hoveringInteractable)
- {
- hoveringInteractable.SendMessage("HandHoverUpdate", this, SendMessageOptions.DontRequireReceiver);
- }
- }
- /// <summary>
- /// Returns true when the hand is currently hovering over the interactable passed in
- /// </summary>
- public bool IsStillHovering(Interactable interactable)
- {
- return hoveringInteractable == interactable;
- }
- protected virtual void HandFollowUpdate()
- {
- GameObject attachedObject = currentAttachedObject;
- if (attachedObject != null)
- {
- if (currentAttachedObjectInfo.Value.interactable != null)
- {
- SteamVR_Skeleton_PoseSnapshot pose = null;
- if (currentAttachedObjectInfo.Value.interactable.skeletonPoser != null && HasSkeleton())
- {
- pose = currentAttachedObjectInfo.Value.interactable.skeletonPoser.GetBlendedPose(skeleton);
- }
- if (currentAttachedObjectInfo.Value.interactable.handFollowTransform)
- {
- Quaternion targetHandRotation;
- Vector3 targetHandPosition;
- if (pose == null)
- {
- Quaternion offset = Quaternion.Inverse(this.transform.rotation) * currentAttachedObjectInfo.Value.handAttachmentPointTransform.rotation;
- targetHandRotation = currentAttachedObjectInfo.Value.interactable.transform.rotation * Quaternion.Inverse(offset);
- Vector3 worldOffset = (this.transform.position - currentAttachedObjectInfo.Value.handAttachmentPointTransform.position);
- Quaternion rotationDiff = mainRenderModel.GetHandRotation() * Quaternion.Inverse(this.transform.rotation);
- Vector3 localOffset = rotationDiff * worldOffset;
- targetHandPosition = currentAttachedObjectInfo.Value.interactable.transform.position + localOffset;
- }
- else
- {
- Transform objectT = currentAttachedObjectInfo.Value.attachedObject.transform;
- Vector3 oldItemPos = objectT.position;
- Quaternion oldItemRot = objectT.transform.rotation;
- objectT.position = TargetItemPosition(currentAttachedObjectInfo.Value);
- objectT.rotation = TargetItemRotation(currentAttachedObjectInfo.Value);
- Vector3 localSkelePos = objectT.InverseTransformPoint(transform.position);
- Quaternion localSkeleRot = Quaternion.Inverse(objectT.rotation) * transform.rotation;
- objectT.position = oldItemPos;
- objectT.rotation = oldItemRot;
- targetHandPosition = objectT.TransformPoint(localSkelePos);
- targetHandRotation = objectT.rotation * localSkeleRot;
- }
- if (mainRenderModel != null)
- mainRenderModel.SetHandRotation(targetHandRotation);
- if (hoverhighlightRenderModel != null)
- hoverhighlightRenderModel.SetHandRotation(targetHandRotation);
- if (mainRenderModel != null)
- mainRenderModel.SetHandPosition(targetHandPosition);
- if (hoverhighlightRenderModel != null)
- hoverhighlightRenderModel.SetHandPosition(targetHandPosition);
- }
- }
- }
- }
- protected virtual void FixedUpdate()
- {
- if (currentAttachedObject != null)
- {
- AttachedObject attachedInfo = currentAttachedObjectInfo.Value;
- if (attachedInfo.attachedObject != null)
- {
- if (attachedInfo.HasAttachFlag(AttachmentFlags.VelocityMovement))
- {
- if(attachedInfo.interactable.attachEaseIn == false || attachedInfo.interactable.snapAttachEaseInCompleted)
- UpdateAttachedVelocity(attachedInfo);
- /*if (attachedInfo.interactable.handFollowTransformPosition)
- {
- skeleton.transform.position = TargetSkeletonPosition(attachedInfo);
- skeleton.transform.rotation = attachedInfo.attachedObject.transform.rotation * attachedInfo.skeletonLockRotation;
- }*/
- }else
- {
- if (attachedInfo.HasAttachFlag(AttachmentFlags.ParentToHand))
- {
- attachedInfo.attachedObject.transform.position = TargetItemPosition(attachedInfo);
- attachedInfo.attachedObject.transform.rotation = TargetItemRotation(attachedInfo);
- }
- }
- if (attachedInfo.interactable.attachEaseIn)
- {
- float t = Util.RemapNumberClamped(Time.time, attachedInfo.attachTime, attachedInfo.attachTime + attachedInfo.interactable.snapAttachEaseInTime, 0.0f, 1.0f);
- if (t < 1.0f)
- {
- if (attachedInfo.HasAttachFlag(AttachmentFlags.VelocityMovement))
- {
- attachedInfo.attachedRigidbody.velocity = Vector3.zero;
- attachedInfo.attachedRigidbody.angularVelocity = Vector3.zero;
- }
- t = attachedInfo.interactable.snapAttachEaseInCurve.Evaluate(t);
- attachedInfo.attachedObject.transform.position = Vector3.Lerp(attachedInfo.easeSourcePosition, TargetItemPosition(attachedInfo), t);
- attachedInfo.attachedObject.transform.rotation = Quaternion.Lerp(attachedInfo.easeSourceRotation, TargetItemRotation(attachedInfo), t);
- }
- else if (!attachedInfo.interactable.snapAttachEaseInCompleted)
- {
- attachedInfo.interactable.gameObject.SendMessage("OnThrowableAttachEaseInCompleted", this, SendMessageOptions.DontRequireReceiver);
- attachedInfo.interactable.snapAttachEaseInCompleted = true;
- }
- }
- }
- }
- }
- protected const float MaxVelocityChange = 10f;
- protected const float VelocityMagic = 6000f;
- protected const float AngularVelocityMagic = 50f;
- protected const float MaxAngularVelocityChange = 20f;
- protected void UpdateAttachedVelocity(AttachedObject attachedObjectInfo)
- {
- Vector3 velocityTarget, angularTarget;
- bool success = GetUpdatedAttachedVelocities(attachedObjectInfo, out velocityTarget, out angularTarget);
- if (success)
- {
- float scale = SteamVR_Utils.GetLossyScale(currentAttachedObjectInfo.Value.handAttachmentPointTransform);
- float maxAngularVelocityChange = MaxAngularVelocityChange * scale;
- float maxVelocityChange = MaxVelocityChange * scale;
- attachedObjectInfo.attachedRigidbody.velocity = Vector3.MoveTowards(attachedObjectInfo.attachedRigidbody.velocity, velocityTarget, maxVelocityChange);
- attachedObjectInfo.attachedRigidbody.angularVelocity = Vector3.MoveTowards(attachedObjectInfo.attachedRigidbody.angularVelocity, angularTarget, maxAngularVelocityChange);
- }
- }
- protected Vector3 TargetItemPosition(AttachedObject attachedObject)
- {
- if (attachedObject.interactable != null && attachedObject.interactable.skeletonPoser != null && HasSkeleton())
- {
- Vector3 tp = attachedObject.handAttachmentPointTransform.InverseTransformPoint(transform.TransformPoint(attachedObject.interactable.skeletonPoser.GetBlendedPose(skeleton).position));
- //tp.x *= -1;
- return currentAttachedObjectInfo.Value.handAttachmentPointTransform.TransformPoint(tp);
- }
- else
- {
- return currentAttachedObjectInfo.Value.handAttachmentPointTransform.TransformPoint(attachedObject.initialPositionalOffset);
- }
- }
- protected Quaternion TargetItemRotation(AttachedObject attachedObject)
- {
- if (attachedObject.interactable != null && attachedObject.interactable.skeletonPoser != null && HasSkeleton())
- {
- Quaternion tr = Quaternion.Inverse(attachedObject.handAttachmentPointTransform.rotation) * (transform.rotation * attachedObject.interactable.skeletonPoser.GetBlendedPose(skeleton).rotation);
- return currentAttachedObjectInfo.Value.handAttachmentPointTransform.rotation * tr;
- }
- else
- {
- return currentAttachedObjectInfo.Value.handAttachmentPointTransform.rotation * attachedObject.initialRotationalOffset;
- }
- }
- protected bool GetUpdatedAttachedVelocities(AttachedObject attachedObjectInfo, out Vector3 velocityTarget, out Vector3 angularTarget)
- {
- bool realNumbers = false;
- float velocityMagic = VelocityMagic;
- float angularVelocityMagic = AngularVelocityMagic;
- Vector3 targetItemPosition = TargetItemPosition(attachedObjectInfo);
- Vector3 positionDelta = (targetItemPosition - attachedObjectInfo.attachedRigidbody.position);
- velocityTarget = (positionDelta * velocityMagic * Time.deltaTime);
- if (float.IsNaN(velocityTarget.x) == false && float.IsInfinity(velocityTarget.x) == false)
- {
- if (noSteamVRFallbackCamera)
- velocityTarget /= 10; //hacky fix for fallback
- realNumbers = true;
- }
- else
- velocityTarget = Vector3.zero;
- Quaternion targetItemRotation = TargetItemRotation(attachedObjectInfo);
- Quaternion rotationDelta = targetItemRotation * Quaternion.Inverse(attachedObjectInfo.attachedObject.transform.rotation);
- float angle;
- Vector3 axis;
- rotationDelta.ToAngleAxis(out angle, out axis);
- if (angle > 180)
- angle -= 360;
- if (angle != 0 && float.IsNaN(axis.x) == false && float.IsInfinity(axis.x) == false)
- {
- angularTarget = angle * axis * angularVelocityMagic * Time.deltaTime;
- if (noSteamVRFallbackCamera)
- angularTarget /= 10; //hacky fix for fallback
- realNumbers &= true;
- }
- else
- angularTarget = Vector3.zero;
- return realNumbers;
- }
- //-------------------------------------------------
- protected virtual void OnInputFocus(bool hasFocus)
- {
- if (hasFocus)
- {
- DetachObject(applicationLostFocusObject, true);
- applicationLostFocusObject.SetActive(false);
- UpdateHovering();
- BroadcastMessage("OnParentHandInputFocusAcquired", SendMessageOptions.DontRequireReceiver);
- }
- else
- {
- applicationLostFocusObject.SetActive(true);
- AttachObject(applicationLostFocusObject, GrabTypes.Scripted, AttachmentFlags.ParentToHand);
- BroadcastMessage("OnParentHandInputFocusLost", SendMessageOptions.DontRequireReceiver);
- }
- }
- //-------------------------------------------------
- protected virtual void OnDrawGizmos()
- {
- if (useHoverSphere && hoverSphereTransform != null)
- {
- Gizmos.color = Color.green;
- float scaledHoverRadius = hoverSphereRadius * Mathf.Abs(SteamVR_Utils.GetLossyScale(hoverSphereTransform));
- Gizmos.DrawWireSphere(hoverSphereTransform.position, scaledHoverRadius/2);
- }
- if (useControllerHoverComponent && mainRenderModel != null && mainRenderModel.IsControllerVisibile())
- {
- Gizmos.color = Color.blue;
- float scaledHoverRadius = controllerHoverRadius * Mathf.Abs(SteamVR_Utils.GetLossyScale(this.transform));
- Gizmos.DrawWireSphere(mainRenderModel.GetControllerPosition(controllerHoverComponent), scaledHoverRadius/2);
- }
- if (useFingerJointHover && mainRenderModel != null && mainRenderModel.IsHandVisibile())
- {
- Gizmos.color = Color.yellow;
- float scaledHoverRadius = fingerJointHoverRadius * Mathf.Abs(SteamVR_Utils.GetLossyScale(this.transform));
- Gizmos.DrawWireSphere(mainRenderModel.GetBonePosition((int)fingerJointHover), scaledHoverRadius/2);
- }
- }
- //-------------------------------------------------
- private void HandDebugLog(string msg)
- {
- if (spewDebugText)
- {
- Debug.Log("<b>[SteamVR Interaction]</b> Hand (" + this.name + "): " + msg);
- }
- }
- //-------------------------------------------------
- // Continue to hover over this object indefinitely, whether or not the Hand moves out of its interaction trigger volume.
- //
- // interactable - The Interactable to hover over indefinitely.
- //-------------------------------------------------
- public void HoverLock(Interactable interactable)
- {
- if (spewDebugText)
- HandDebugLog("HoverLock " + interactable);
- hoverLocked = true;
- hoveringInteractable = interactable;
- }
- //-------------------------------------------------
- // Stop hovering over this object indefinitely.
- //
- // interactable - The hover-locked Interactable to stop hovering over indefinitely.
- //-------------------------------------------------
- public void HoverUnlock(Interactable interactable)
- {
- if (spewDebugText)
- HandDebugLog("HoverUnlock " + interactable);
- if (hoveringInteractable == interactable)
- {
- hoverLocked = false;
- }
- }
- public void TriggerHapticPulse(ushort microSecondsDuration)
- {
- float seconds = (float)microSecondsDuration / 1000000f;
- hapticAction.Execute(0, seconds, 1f / seconds, 1, handType);
- }
- public void TriggerHapticPulse(float duration, float frequency, float amplitude)
- {
- hapticAction.Execute(0, duration, frequency, amplitude, handType);
- }
- public void ShowGrabHint()
- {
- ControllerButtonHints.ShowButtonHint(this, grabGripAction); //todo: assess
- }
- public void HideGrabHint()
- {
- ControllerButtonHints.HideButtonHint(this, grabGripAction); //todo: assess
- }
- public void ShowGrabHint(string text)
- {
- ControllerButtonHints.ShowTextHint(this, grabGripAction, text);
- }
- public GrabTypes GetGrabStarting(GrabTypes explicitType = GrabTypes.None)
- {
- if (explicitType != GrabTypes.None)
- {
- if (noSteamVRFallbackCamera)
- {
- if (Input.GetMouseButtonDown(0))
- return explicitType;
- }
- if (explicitType == GrabTypes.Pinch && grabPinchAction.GetStateDown(handType))
- return GrabTypes.Pinch;
- if (explicitType == GrabTypes.Grip && grabGripAction.GetStateDown(handType))
- return GrabTypes.Grip;
- }
- else
- {
- if (noSteamVRFallbackCamera)
- {
- if (Input.GetMouseButtonDown(0))
- return GrabTypes.Grip;
- }
- if (grabPinchAction.GetStateDown(handType))
- return GrabTypes.Pinch;
- if (grabGripAction.GetStateDown(handType))
- return GrabTypes.Grip;
- }
- return GrabTypes.None;
- }
- public GrabTypes GetGrabEnding(GrabTypes explicitType = GrabTypes.None)
- {
- if (explicitType != GrabTypes.None)
- {
- if (noSteamVRFallbackCamera)
- {
- if (Input.GetMouseButtonUp(0))
- return explicitType;
- }
- if (explicitType == GrabTypes.Pinch && grabPinchAction.GetStateUp(handType))
- return GrabTypes.Pinch;
- if (explicitType == GrabTypes.Grip && grabGripAction.GetStateUp(handType))
- return GrabTypes.Grip;
- }
- else
- {
- if (noSteamVRFallbackCamera)
- {
- if (Input.GetMouseButtonUp(0))
- return GrabTypes.Grip;
- }
- if (grabPinchAction.GetStateUp(handType))
- return GrabTypes.Pinch;
- if (grabGripAction.GetStateUp(handType))
- return GrabTypes.Grip;
- }
- return GrabTypes.None;
- }
- public bool IsGrabEnding(GameObject attachedObject)
- {
- for (int attachedObjectIndex = 0; attachedObjectIndex < attachedObjects.Count; attachedObjectIndex++)
- {
- if (attachedObjects[attachedObjectIndex].attachedObject == attachedObject)
- {
- return IsGrabbingWithType(attachedObjects[attachedObjectIndex].grabbedWithType) == false;
- }
- }
- return false;
- }
- public bool IsGrabbingWithType(GrabTypes type)
- {
- if (noSteamVRFallbackCamera)
- {
- if (Input.GetMouseButton(0))
- return true;
- }
- switch (type)
- {
- case GrabTypes.Pinch:
- return grabPinchAction.GetState(handType);
- case GrabTypes.Grip:
- return grabGripAction.GetState(handType);
- default:
- return false;
- }
- }
- public bool IsGrabbingWithOppositeType(GrabTypes type)
- {
- if (noSteamVRFallbackCamera)
- {
- if (Input.GetMouseButton(0))
- return true;
- }
- switch (type)
- {
- case GrabTypes.Pinch:
- return grabGripAction.GetState(handType);
- case GrabTypes.Grip:
- return grabPinchAction.GetState(handType);
- default:
- return false;
- }
- }
- public GrabTypes GetBestGrabbingType()
- {
- return GetBestGrabbingType(GrabTypes.None);
- }
- public GrabTypes GetBestGrabbingType(GrabTypes preferred, bool forcePreference = false)
- {
- if (noSteamVRFallbackCamera)
- {
- if (Input.GetMouseButton(0))
- return preferred;
- }
- if (preferred == GrabTypes.Pinch)
- {
- if (grabPinchAction.GetState(handType))
- return GrabTypes.Pinch;
- else if (forcePreference)
- return GrabTypes.None;
- }
- if (preferred == GrabTypes.Grip)
- {
- if (grabGripAction.GetState(handType))
- return GrabTypes.Grip;
- else if (forcePreference)
- return GrabTypes.None;
- }
- if (grabPinchAction.GetState(handType))
- return GrabTypes.Pinch;
- if (grabGripAction.GetState(handType))
- return GrabTypes.Grip;
- return GrabTypes.None;
- }
- //-------------------------------------------------
- private void InitController()
- {
- if (spewDebugText)
- HandDebugLog("Hand " + name + " connected with type " + handType.ToString());
- bool hadOldRendermodel = mainRenderModel != null;
- EVRSkeletalMotionRange oldRM_rom = EVRSkeletalMotionRange.WithController;
- if(hadOldRendermodel)
- oldRM_rom = mainRenderModel.GetSkeletonRangeOfMotion;
- foreach (RenderModel r in renderModels)
- {
- if (r != null)
- Destroy(r.gameObject);
- }
- renderModels.Clear();
- GameObject renderModelInstance = GameObject.Instantiate(renderModelPrefab);
- renderModelInstance.layer = gameObject.layer;
- renderModelInstance.tag = gameObject.tag;
- renderModelInstance.transform.parent = this.transform;
- renderModelInstance.transform.localPosition = Vector3.zero;
- renderModelInstance.transform.localRotation = Quaternion.identity;
- renderModelInstance.transform.localScale = renderModelPrefab.transform.localScale;
- //TriggerHapticPulse(800); //pulse on controller init
- int deviceIndex = trackedObject.GetDeviceIndex();
- mainRenderModel = renderModelInstance.GetComponent<RenderModel>();
- renderModels.Add(mainRenderModel);
- if (hadOldRendermodel)
- mainRenderModel.SetSkeletonRangeOfMotion(oldRM_rom);
- this.BroadcastMessage("SetInputSource", handType, SendMessageOptions.DontRequireReceiver); // let child objects know we've initialized
- this.BroadcastMessage("OnHandInitialized", deviceIndex, SendMessageOptions.DontRequireReceiver); // let child objects know we've initialized
- }
- public void SetRenderModel(GameObject prefab)
- {
- renderModelPrefab = prefab;
- if (mainRenderModel != null && isPoseValid)
- InitController();
- }
- public void SetHoverRenderModel(RenderModel hoverRenderModel)
- {
- hoverhighlightRenderModel = hoverRenderModel;
- renderModels.Add(hoverRenderModel);
- }
- public int GetDeviceIndex()
- {
- return trackedObject.GetDeviceIndex();
- }
- }
- [System.Serializable]
- public class HandEvent : UnityEvent<Hand> { }
- #if UNITY_EDITOR
- //-------------------------------------------------------------------------
- [UnityEditor.CustomEditor(typeof(Hand))]
- public class HandEditor : UnityEditor.Editor
- {
- //-------------------------------------------------
- // Custom Inspector GUI allows us to click from within the UI
- //-------------------------------------------------
- public override void OnInspectorGUI()
- {
- DrawDefaultInspector();
- /*
- Hand hand = (Hand)target;
- if (hand.otherHand)
- {
- if (hand.otherHand.otherHand != hand)
- {
- UnityEditor.EditorGUILayout.HelpBox("The otherHand of this Hand's otherHand is not this Hand.", UnityEditor.MessageType.Warning);
- }
- if (hand.handType == SteamVR_Input_Sources.LeftHand && hand.otherHand && hand.otherHand.handType != SteamVR_Input_Sources.RightHand)
- {
- UnityEditor.EditorGUILayout.HelpBox("This is a left Hand but otherHand is not a right Hand.", UnityEditor.MessageType.Warning);
- }
- if (hand.handType == SteamVR_Input_Sources.RightHand && hand.otherHand && hand.otherHand.handType != SteamVR_Input_Sources.LeftHand)
- {
- UnityEditor.EditorGUILayout.HelpBox("This is a right Hand but otherHand is not a left Hand.", UnityEditor.MessageType.Warning);
- }
- if (hand.handType == SteamVR_Input_Sources.Any && hand.otherHand && hand.otherHand.handType != SteamVR_Input_Sources.Any)
- {
- UnityEditor.EditorGUILayout.HelpBox("This is an any-handed Hand but otherHand is not an any-handed Hand.", UnityEditor.MessageType.Warning);
- }
- }
- */ //removing for now because it conflicts with other input sources (trackers and such)
- }
- }
- #endif
- }
|