using System.Collections; using System.Collections.Generic; using UnityEngine; namespace BNG { public class GrabPoint : MonoBehaviour { [Header("Hand Pose")] public HandPoseType handPoseType = HandPoseType.HandPose; [Tooltip("If HandPoseType = 'HandPose', this HandPose object will be applied to the hand when this grab point is in use")] public HandPose SelectedHandPose; /// /// Set to Default to inherit Grabbable's HandPose. Otherwise this HandPose will be used /// [Tooltip("If HandPoseType = 'AnimatorID', this id will be set on the hand animator when grabbed. Set to 'Default' to inherit the Grabbable's HandPose. Otherwise this HandPose ID will be used.")] public HandPoseId HandPose; [Header("Valid Hands")] [Tooltip("Can this Grab Point be used by a left-handed Grabber?")] public bool LeftHandIsValid = true; [Tooltip("Can this Grab Point be used by a right-handed Grabber?")] public bool RightHandIsValid = true; [Header("Parent to")] /// /// If specified, the Hand Model will be placed here when snapped /// [Tooltip("If specified, the Hand Model will be parented here when snapped")] public Transform HandPosition; [Header("Angle Restriction")] /// /// GrabPoint is not considered valid if the angle between the GrabPoint and Grabber is greater than this amount /// [Tooltip("GrabPoint is not considered valid if the angle between the GrabPoint and Grabber is greater than this amount")] [Range(0.0f, 360.0f)] public float MaxDegreeDifferenceAllowed = 360; [Header("Finger Blending")] [Tooltip("Minimum value Hand Animator will blend to. Example : If IndexBlendMin = 0.4 and Trigger button is not held down, the LayerWeight will be set to 0.4")] [Range(0.0f, 1.0f)] public float IndexBlendMin = 0; [Tooltip("Maximum value Hand Animator will blend to. Example : If IndexBlendMax = 0.6 and Trigger button is held all the way down, the LayerWeight will be set to 0.6")] [Range(0.0f, 1.0f)] public float IndexBlendMax = 0; [Tooltip("Minimum value Hand Animator will blend to if thumb control is not being touched.")] [Range(0.0f, 1.0f)] public float ThumbBlendMin = 0; [Tooltip("Maximum value Hand Animator will blend to if thumb control is being touched.")] [Range(0.0f, 1.0f)] public float ThumbBlendMax = 0; // Taken from defaults in Demo - offset between "Models" and Grabber Vector3 previewModelOffsetLeft = new Vector3(0.007f, -0.0179f, 0.0071f);// Old Offset = new Vector3(0.007f, -0.0179f, 0.0071f); Vector3 previewModelOffsetRight = new Vector3(-0.029f, 0.0328f, 0.044f);// Old Offset = new Vector3(-0.01f, -0.0179f, 0.0071f); [Header("Editor")] [Tooltip("Show a green arc in the Scene view representing MaxDegreeDifferenceAllowed")] public bool ShowAngleGizmo = true; #region Editor #if UNITY_EDITOR // Make sure animators update in the editor mode to show hand positions // By using OnDrawGizmosSelected we only call this function if the object is selected in the editor void OnDrawGizmosSelected() { DrawEditorArc(); UpdatePreviews(); //if (!Application.isPlaying) { // UpdatePreviews(); //} } // Update preview transform in editor in play mode as well //void Update() { // UpdatePreviews(); //} public void UpdatePreviews() { UpdateChildAnimators(); UpdatePreviewTransforms(); UpdateHandPosePreview(); UpdateAutoPoserPreview(); } /// /// Draw an arc in the editor representing MaxDegreeDifferenceAllowed /// public void DrawEditorArc() { // Draw arc representing the MaxDegreeDifferenceAllowed of the Grab Point if (ShowAngleGizmo && MaxDegreeDifferenceAllowed != 0 && MaxDegreeDifferenceAllowed != 360) { Vector3 from = Quaternion.AngleAxis(-0.5f * MaxDegreeDifferenceAllowed, transform.up) * (-transform.forward - Vector3.Dot(-transform.forward, transform.up) * transform.up); UnityEditor.Handles.color = new Color(0, 1, 0, 0.1f); UnityEditor.Handles.DrawSolidArc(transform.position, transform.up, from, MaxDegreeDifferenceAllowed, 0.05f); } } #endif bool offsetFound = false; public void UpdatePreviewTransforms() { Transform leftHandPreview = transform.Find("LeftHandModelsEditorPreview"); Transform rightHandPreview = transform.Find("RightHandModelsEditorPreview"); if(!offsetFound) { // If there is a Hand in the scene, use that offset instead of our defaults if (GameObject.Find("LeftController/Grabber") != null) { Grabber LeftGrabber = GameObject.Find("LeftController/Grabber").GetComponent(); previewModelOffsetLeft = Vector3.zero - LeftGrabber.transform.localPosition; // offsetFound = true; } if (GameObject.Find("RightController/Grabber") != null) { Grabber RightGrabber = GameObject.Find("RightController/Grabber").GetComponent(); previewModelOffsetRight = Vector3.zero - RightGrabber.transform.localPosition; // offsetFound = true; } } if (leftHandPreview) { leftHandPreview.localPosition = previewModelOffsetLeft; leftHandPreview.localEulerAngles = Vector3.zero; } if(rightHandPreview) { rightHandPreview.localPosition = previewModelOffsetRight; rightHandPreview.localEulerAngles = Vector3.zero; } } public void UpdateHandPosePreview() { if(handPoseType == HandPoseType.HandPose) { Transform leftHandPreview = transform.Find("LeftHandModelsEditorPreview"); Transform rightHandPreview = transform.Find("RightHandModelsEditorPreview"); if (leftHandPreview) { HandPoser hp = leftHandPreview.GetComponentInChildren(); if (hp != null) { hp.CurrentPose = SelectedHandPose; } } if (rightHandPreview) { HandPoser hp = rightHandPreview.GetComponentInChildren(); if (hp != null) { hp.CurrentPose = SelectedHandPose; } } } } public void UpdateAutoPoserPreview() { if (handPoseType == HandPoseType.AutoPoseContinuous || handPoseType == HandPoseType.AutoPoseOnce) { Transform leftHandPreview = transform.Find("LeftHandModelsEditorPreview"); Transform rightHandPreview = transform.Find("RightHandModelsEditorPreview"); // Update in editor if (leftHandPreview) { AutoPoser ap = leftHandPreview.GetComponentInChildren(); if (ap != null) { ap.UpdateContinuously = true; } } if (rightHandPreview) { AutoPoser ap = rightHandPreview.GetComponentInChildren(); if (ap != null) { ap.UpdateContinuously = true; } } } else { Transform leftHandPreview = transform.Find("LeftHandModelsEditorPreview"); Transform rightHandPreview = transform.Find("RightHandModelsEditorPreview"); // Update in editor if (leftHandPreview) { AutoPoser ap = leftHandPreview.GetComponentInChildren(); if (ap != null) { ap.UpdateContinuously = false; } } if (rightHandPreview) { AutoPoser ap = rightHandPreview.GetComponentInChildren(); if (ap != null) { ap.UpdateContinuously = false; } } } } public void UpdateChildAnimators() { var animators = transform.GetComponentsInChildren(true); for (int x = 0; x < animators.Length; x++) { if(handPoseType == HandPoseType.AnimatorID) { animators[x].enabled = true; if(animators[x].isActiveAndEnabled) { animators[x].Update(Time.deltaTime); } #if UNITY_EDITOR // Only set dirty if not in prefab mode if (UnityEditor.SceneManagement.PrefabStageUtility.GetCurrentPrefabStage() == null) { UnityEditor.EditorUtility.SetDirty(animators[x].gameObject); } #endif } // Disable the animator in editor mode if using handpose else if (handPoseType == HandPoseType.HandPose && SelectedHandPose != null) { animators[x].enabled = false; } // Disable the animator in editor mode if using auto pose else if (handPoseType == HandPoseType.AutoPoseOnce || handPoseType == HandPoseType.AutoPoseContinuous) { animators[x].enabled = false; } } } #endregion } }