version 2.4.0
This commit is contained in:
+44
@@ -0,0 +1,44 @@
|
||||
// "Wave SDK
|
||||
// © 2020 HTC Corporation. All Rights Reserved.
|
||||
//
|
||||
// Unless otherwise required by copyright law and practice,
|
||||
// upon the execution of HTC SDK license agreement,
|
||||
// HTC grants you access to and use of the Wave SDK(s).
|
||||
// You shall fully comply with all of HTC’s SDK license agreement terms and
|
||||
// conditions signed by you and all SDK and API requirements,
|
||||
// specifications, and documentation provided by HTC to You."
|
||||
|
||||
using UnityEngine;
|
||||
|
||||
#if UNITY_EDITOR
|
||||
using UnityEditor;
|
||||
namespace VIVE.OpenXR.Toolkits.RealisticHandInteraction
|
||||
{
|
||||
[CustomEditor(typeof(CustomGrabPose))]
|
||||
public class CustomGrabPoseEditor : UnityEditor.Editor
|
||||
{
|
||||
private CustomGrabPose m_GrabPoseDesigner;
|
||||
|
||||
private void Awake()
|
||||
{
|
||||
m_GrabPoseDesigner = target as CustomGrabPose;
|
||||
}
|
||||
|
||||
public override void OnInspectorGUI()
|
||||
{
|
||||
base.OnInspectorGUI();
|
||||
GUILayout.Space(10f);
|
||||
ShowGrabPosesMenu();
|
||||
}
|
||||
|
||||
private void ShowGrabPosesMenu()
|
||||
{
|
||||
if (GUILayout.Button("Save HandGrab Pose"))
|
||||
{
|
||||
m_GrabPoseDesigner.FindNearInteractable();
|
||||
m_GrabPoseDesigner.SavePoseWithCandidate();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
+11
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: c01f88bc88bb27849a723888721c96f4
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
+382
@@ -0,0 +1,382 @@
|
||||
// "Wave SDK
|
||||
// © 2020 HTC Corporation. All Rights Reserved.
|
||||
//
|
||||
// Unless otherwise required by copyright law and practice,
|
||||
// upon the execution of HTC SDK license agreement,
|
||||
// HTC grants you access to and use of the Wave SDK(s).
|
||||
// You shall fully comply with all of HTC’s SDK license agreement terms and
|
||||
// conditions signed by you and all SDK and API requirements,
|
||||
// specifications, and documentation provided by HTC to You."
|
||||
|
||||
using UnityEngine;
|
||||
using System;
|
||||
|
||||
#if UNITY_EDITOR
|
||||
using UnityEditor;
|
||||
using UnityEditorInternal;
|
||||
namespace VIVE.OpenXR.Toolkits.RealisticHandInteraction
|
||||
{
|
||||
[CustomEditor(typeof(HandGrabInteractable))]
|
||||
public class HandGrabInteractableEditor : UnityEditor.Editor
|
||||
{
|
||||
private static HandGrabInteractable activeGrabbable = null;
|
||||
private HandGrabInteractable handGrabbable = null;
|
||||
private SerializedProperty m_IsGrabbable, m_FingerRequirement, m_Rigidbody, m_GrabPoses, m_ShowAllIndicator, m_OnBeginGrabbed, m_OnEndGrabbed,
|
||||
m_OneHandContraintMovement, m_PreviewIndex, grabPoseName, gestureThumbPose, gestureIndexPose, gestureMiddlePose, gestureRingPose, gesturePinkyPose,
|
||||
recordedGrabRotations, isLeft, enableIndicator, autoIndicator, indicatorObject, grabOffset;
|
||||
private ReorderableList grabPoseList;
|
||||
private bool showGrabPoses = false;
|
||||
private bool showConstraint = false;
|
||||
private bool showEvent = false;
|
||||
|
||||
private void OnEnable()
|
||||
{
|
||||
handGrabbable = target as HandGrabInteractable;
|
||||
|
||||
m_IsGrabbable = serializedObject.FindProperty("m_IsGrabbable");
|
||||
m_FingerRequirement = serializedObject.FindProperty("m_FingerRequirement");
|
||||
m_Rigidbody = serializedObject.FindProperty("m_Rigidbody");
|
||||
m_GrabPoses = serializedObject.FindProperty("m_GrabPoses");
|
||||
m_ShowAllIndicator = serializedObject.FindProperty("m_ShowAllIndicator");
|
||||
m_OnBeginGrabbed = serializedObject.FindProperty("m_OnBeginGrabbed");
|
||||
m_OnEndGrabbed = serializedObject.FindProperty("m_OnEndGrabbed");
|
||||
m_OneHandContraintMovement = serializedObject.FindProperty("m_OneHandContraintMovement");
|
||||
m_PreviewIndex = serializedObject.FindProperty("m_PreviewIndex");
|
||||
|
||||
#region ReorderableList
|
||||
grabPoseList = new ReorderableList(serializedObject, m_GrabPoses, true, true, true, true);
|
||||
|
||||
grabPoseList.drawHeaderCallback = (Rect rect) =>
|
||||
{
|
||||
EditorGUI.LabelField(rect, "Grab Pose List");
|
||||
};
|
||||
|
||||
grabPoseList.drawElementCallback = (Rect rect, int index, bool isActive, bool isFocused) =>
|
||||
{
|
||||
if (!UpdateGrabPose(m_GrabPoses.GetArrayElementAtIndex(index))) { return; }
|
||||
|
||||
if (string.IsNullOrEmpty(grabPoseName.stringValue))
|
||||
{
|
||||
grabPoseName.stringValue = $"Grab Pose {index + 1}";
|
||||
}
|
||||
|
||||
Rect elementRect = new Rect(rect.x, rect.y, rect.width, EditorGUIUtility.singleLineHeight);
|
||||
grabPoseName.stringValue = EditorGUI.TextField(elementRect, grabPoseName.stringValue);
|
||||
|
||||
DrawGrabGesture(ref elementRect);
|
||||
DrawHandedness(ref elementRect);
|
||||
DrawIndicator(ref elementRect);
|
||||
DrawMirrorButton(ref elementRect);
|
||||
DrawPoseOffset(ref elementRect);
|
||||
DrawFineTune(ref elementRect, index);
|
||||
};
|
||||
|
||||
grabPoseList.elementHeightCallback = (int index) =>
|
||||
{
|
||||
if (!UpdateGrabPose(m_GrabPoses.GetArrayElementAtIndex(index))) { return EditorGUIUtility.singleLineHeight; }
|
||||
|
||||
// Including Title, Handness, Show Indicator, Mirror Pose, Position, Rotation, Fine Tune
|
||||
int minHeight = 7;
|
||||
// To Show GrabGesture
|
||||
if (recordedGrabRotations.arraySize == 0)
|
||||
{
|
||||
minHeight += 5;
|
||||
}
|
||||
if (enableIndicator.boolValue)
|
||||
{
|
||||
// To Show Auto Indicator
|
||||
minHeight += 1;
|
||||
// To Show Indicator Gameobject
|
||||
if (!autoIndicator.boolValue)
|
||||
{
|
||||
minHeight += 1;
|
||||
}
|
||||
}
|
||||
return EditorGUIUtility.singleLineHeight * minHeight + EditorGUIUtility.standardVerticalSpacing * minHeight;
|
||||
};
|
||||
|
||||
grabPoseList.onAddCallback = (ReorderableList list) =>
|
||||
{
|
||||
m_GrabPoses.arraySize++;
|
||||
if (UpdateGrabPose(m_GrabPoses.GetArrayElementAtIndex(list.count - 1)))
|
||||
{
|
||||
grabPoseName.stringValue = $"Grab Pose {list.count}";
|
||||
}
|
||||
};
|
||||
#endregion
|
||||
}
|
||||
|
||||
public override void OnInspectorGUI()
|
||||
{
|
||||
serializedObject.Update();
|
||||
EditorGUILayout.PropertyField(m_Rigidbody);
|
||||
EditorGUILayout.PropertyField(m_IsGrabbable);
|
||||
EditorGUILayout.PropertyField(m_FingerRequirement);
|
||||
showGrabPoses = EditorGUILayout.Foldout(showGrabPoses, "Grab Pose Settings");
|
||||
if (showGrabPoses)
|
||||
{
|
||||
if (m_GrabPoses.arraySize == 0)
|
||||
{
|
||||
grabPoseList.elementHeight = EditorGUIUtility.singleLineHeight;
|
||||
}
|
||||
grabPoseList.DoLayoutList();
|
||||
|
||||
bool isToggle = EditorGUILayout.Toggle("Show All Indicator", m_ShowAllIndicator.boolValue);
|
||||
if (isToggle != m_ShowAllIndicator.boolValue)
|
||||
{
|
||||
m_ShowAllIndicator.boolValue = isToggle;
|
||||
for (int i = 0; i < m_GrabPoses.arraySize; i++)
|
||||
{
|
||||
if (UpdateGrabPose(m_GrabPoses.GetArrayElementAtIndex(i)))
|
||||
{
|
||||
enableIndicator.boolValue = m_ShowAllIndicator.boolValue;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
showEvent = EditorGUILayout.Foldout(showEvent, "Grabbed Event");
|
||||
if (showEvent)
|
||||
{
|
||||
EditorGUILayout.PropertyField(m_OnBeginGrabbed);
|
||||
EditorGUILayout.PropertyField(m_OnEndGrabbed);
|
||||
}
|
||||
|
||||
showConstraint = EditorGUILayout.Foldout(showConstraint, "Constraint Movement (Optional)");
|
||||
if (showConstraint)
|
||||
{
|
||||
EditorGUILayout.PropertyField(m_OneHandContraintMovement);
|
||||
}
|
||||
serializedObject.ApplyModifiedProperties();
|
||||
}
|
||||
|
||||
private bool UpdateGrabPose(SerializedProperty grabPose)
|
||||
{
|
||||
SerializedProperty indicator = grabPose.FindPropertyRelative("indicator");
|
||||
if (grabPose == null || indicator == null) { return false; }
|
||||
|
||||
grabPoseName = grabPose.FindPropertyRelative("grabPoseName");
|
||||
gestureThumbPose = grabPose.FindPropertyRelative("handGrabGesture.thumbPose");
|
||||
gestureIndexPose = grabPose.FindPropertyRelative("handGrabGesture.indexPose");
|
||||
gestureMiddlePose = grabPose.FindPropertyRelative("handGrabGesture.middlePose");
|
||||
gestureRingPose = grabPose.FindPropertyRelative("handGrabGesture.ringPose");
|
||||
gesturePinkyPose = grabPose.FindPropertyRelative("handGrabGesture.pinkyPose");
|
||||
recordedGrabRotations = grabPose.FindPropertyRelative("recordedGrabRotations");
|
||||
isLeft = grabPose.FindPropertyRelative("isLeft");
|
||||
enableIndicator = indicator.FindPropertyRelative("enableIndicator");
|
||||
autoIndicator = indicator.FindPropertyRelative("autoIndicator");
|
||||
indicatorObject = indicator.FindPropertyRelative("target");
|
||||
grabOffset = grabPose.FindPropertyRelative("grabOffset");
|
||||
return true;
|
||||
}
|
||||
|
||||
private void AddElementHeight(ref Rect rect)
|
||||
{
|
||||
rect.y += EditorGUIUtility.singleLineHeight + EditorGUIUtility.standardVerticalSpacing;
|
||||
}
|
||||
|
||||
private void DrawGrabGesture(ref Rect rect)
|
||||
{
|
||||
if (recordedGrabRotations.arraySize == 0)
|
||||
{
|
||||
AddElementHeight(ref rect);
|
||||
EditorGUI.PropertyField(rect, gestureThumbPose);
|
||||
AddElementHeight(ref rect);
|
||||
EditorGUI.PropertyField(rect, gestureIndexPose);
|
||||
AddElementHeight(ref rect);
|
||||
EditorGUI.PropertyField(rect, gestureMiddlePose);
|
||||
AddElementHeight(ref rect);
|
||||
EditorGUI.PropertyField(rect, gestureRingPose);
|
||||
AddElementHeight(ref rect);
|
||||
EditorGUI.PropertyField(rect, gesturePinkyPose);
|
||||
}
|
||||
}
|
||||
|
||||
private void DrawHandedness(ref Rect rect)
|
||||
{
|
||||
AddElementHeight(ref rect);
|
||||
bool isToggle = EditorGUI.Toggle(rect, "Is Left", isLeft.boolValue);
|
||||
if (isToggle != isLeft.boolValue)
|
||||
{
|
||||
isLeft.boolValue = isToggle;
|
||||
SwitchRotations(ref recordedGrabRotations);
|
||||
}
|
||||
}
|
||||
|
||||
private void DrawIndicator(ref Rect rect)
|
||||
{
|
||||
AddElementHeight(ref rect);
|
||||
enableIndicator.boolValue = EditorGUI.Toggle(rect, "Show Indicator", enableIndicator.boolValue);
|
||||
if (enableIndicator.boolValue)
|
||||
{
|
||||
AddElementHeight(ref rect);
|
||||
autoIndicator.boolValue = EditorGUI.Toggle(rect, "Auto Generator Indicator", autoIndicator.boolValue);
|
||||
if (!autoIndicator.boolValue)
|
||||
{
|
||||
AddElementHeight(ref rect);
|
||||
indicatorObject.objectReferenceValue = (GameObject)EditorGUI.ObjectField(rect, "Indicator", (GameObject)indicatorObject.objectReferenceValue, typeof(GameObject), true);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
m_ShowAllIndicator.boolValue = false;
|
||||
}
|
||||
}
|
||||
|
||||
private void DrawMirrorButton(ref Rect rect)
|
||||
{
|
||||
AddElementHeight(ref rect);
|
||||
Rect labelRect = new Rect(rect.x, rect.y, EditorGUIUtility.labelWidth, rect.height);
|
||||
EditorGUI.PrefixLabel(labelRect, GUIUtility.GetControlID(FocusType.Passive), new GUIContent("Mirror Pose"));
|
||||
|
||||
Rect mirrorXRect = new Rect(rect.x + EditorGUIUtility.labelWidth + EditorGUIUtility.standardVerticalSpacing, rect.y,
|
||||
(rect.width - EditorGUIUtility.labelWidth - EditorGUIUtility.standardVerticalSpacing * 4) / 3, rect.height);
|
||||
Rect mirrorYRect = new Rect(mirrorXRect.x + mirrorXRect.width + EditorGUIUtility.standardVerticalSpacing, rect.y, mirrorXRect.width, rect.height);
|
||||
Rect mirrorZRect = new Rect(mirrorYRect.x + mirrorYRect.width + EditorGUIUtility.standardVerticalSpacing, rect.y, mirrorYRect.width, rect.height);
|
||||
if (GUI.Button(mirrorXRect, "Align X axis"))
|
||||
{
|
||||
MirrorPose(ref grabOffset, Vector3.right);
|
||||
}
|
||||
if (GUI.Button(mirrorYRect, "Align Y axis"))
|
||||
{
|
||||
MirrorPose(ref grabOffset, Vector3.up);
|
||||
}
|
||||
if (GUI.Button(mirrorZRect, "Align Z axis"))
|
||||
{
|
||||
MirrorPose(ref grabOffset, Vector3.forward);
|
||||
}
|
||||
}
|
||||
|
||||
private void DrawPoseOffset(ref Rect rect)
|
||||
{
|
||||
SerializedProperty srcPos = grabOffset.FindPropertyRelative("sourcePosition");
|
||||
SerializedProperty srcRot = grabOffset.FindPropertyRelative("sourceRotation");
|
||||
SerializedProperty tgtPos = grabOffset.FindPropertyRelative("targetPosition");
|
||||
SerializedProperty tgtRot = grabOffset.FindPropertyRelative("targetRotation");
|
||||
AddElementHeight(ref rect);
|
||||
EditorGUI.Vector3Field(rect, "Position Offset", tgtPos.vector3Value - srcPos.vector3Value);
|
||||
AddElementHeight(ref rect);
|
||||
Vector3 rotEulerAngles = (Quaternion.Inverse(srcRot.quaternionValue) * tgtRot.quaternionValue).eulerAngles;
|
||||
for (int i = 0; i < 3; i++)
|
||||
{
|
||||
if (rotEulerAngles[i] > 180)
|
||||
{
|
||||
rotEulerAngles[i] = 360.0f - rotEulerAngles[i];
|
||||
}
|
||||
}
|
||||
EditorGUI.Vector3Field(rect, "Rotation Offset", rotEulerAngles);
|
||||
}
|
||||
|
||||
private void DrawFineTune(ref Rect rect, int index)
|
||||
{
|
||||
AddElementHeight(ref rect);
|
||||
Rect labelRect = new Rect(rect.x, rect.y, EditorGUIUtility.labelWidth, rect.height);
|
||||
EditorGUI.PrefixLabel(labelRect, GUIUtility.GetControlID(FocusType.Passive), new GUIContent("Fine Tune"));
|
||||
|
||||
Rect previewRect = new Rect(rect.x + EditorGUIUtility.labelWidth + EditorGUIUtility.standardVerticalSpacing, rect.y,
|
||||
(rect.width - EditorGUIUtility.labelWidth - EditorGUIUtility.standardVerticalSpacing * 4) / 2, rect.height);
|
||||
Rect updateRect = new Rect(previewRect.x + previewRect.width + EditorGUIUtility.standardVerticalSpacing, rect.y, previewRect.width, rect.height);
|
||||
if (GUI.Button(previewRect, "Preview Grab Pose") && Application.isPlaying)
|
||||
{
|
||||
activeGrabbable = handGrabbable;
|
||||
m_PreviewIndex.intValue = index;
|
||||
ShowMeshHandPose();
|
||||
}
|
||||
GUI.enabled = activeGrabbable == handGrabbable && m_PreviewIndex.intValue == index;
|
||||
if (GUI.Button(updateRect, "Update Grab Pose"))
|
||||
{
|
||||
UpdateGrabPose();
|
||||
}
|
||||
GUI.enabled = true;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Convert the rotation of joints of the current hand into those of another hand.
|
||||
/// </summary>
|
||||
/// <param name="rotations">Rotation of joints of the current hand.</param>
|
||||
private void SwitchRotations(ref SerializedProperty rotations)
|
||||
{
|
||||
for (int i = 0; i < rotations.arraySize; i++)
|
||||
{
|
||||
Quaternion rotation = rotations.GetArrayElementAtIndex(i).quaternionValue;
|
||||
Quaternion newRotation = Quaternion.Euler(rotation.eulerAngles.x, -rotation.eulerAngles.y, -rotation.eulerAngles.z);
|
||||
rotations.GetArrayElementAtIndex(i).quaternionValue = newRotation;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Mirrors the pose properties (position and rotation) of a serialized object along a specified mirror axis.
|
||||
/// </summary>
|
||||
/// <param name="pose">The serialized property representing the pose to be mirrored.</param>
|
||||
/// <param name="mirrorAxis">The axis along which the mirroring should occur.</param>
|
||||
private void MirrorPose(ref SerializedProperty pose, Vector3 mirrorAxis)
|
||||
{
|
||||
Vector3 sourcePosition = grabOffset.FindPropertyRelative("sourcePosition").vector3Value;
|
||||
Quaternion sourceRotation = grabOffset.FindPropertyRelative("sourceRotation").quaternionValue;
|
||||
Vector3 targetPosition = grabOffset.FindPropertyRelative("targetPosition").vector3Value;
|
||||
Quaternion targetRotation = grabOffset.FindPropertyRelative("targetRotation").quaternionValue;
|
||||
Vector3 reflectNormal = targetRotation * mirrorAxis;
|
||||
|
||||
Vector3 diffPos = sourcePosition - targetPosition;
|
||||
Vector3 mirrorPosition = targetPosition + Vector3.Reflect(diffPos, reflectNormal);
|
||||
pose.FindPropertyRelative("sourcePosition").vector3Value = mirrorPosition;
|
||||
|
||||
Vector3 sourceForward = sourceRotation * Vector3.forward;
|
||||
Vector3 sourceUp = sourceRotation * Vector3.up;
|
||||
Quaternion mirroredRotation = Quaternion.LookRotation(Vector3.Reflect(sourceForward, reflectNormal), Vector3.Reflect(sourceUp, reflectNormal));
|
||||
pose.FindPropertyRelative("sourceRotation").quaternionValue = mirroredRotation;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Obtain the MeshHand and set its position and rotation based on the grabOffset of grabpose.
|
||||
/// </summary>
|
||||
private void ShowMeshHandPose()
|
||||
{
|
||||
HandPose handPose = HandPoseProvider.GetHandPose(isLeft.boolValue ? HandPoseType.MESH_LEFT : HandPoseType.MESH_RIGHT);
|
||||
if (handPose != null && handPose is MeshHandPose meshHandPose)
|
||||
{
|
||||
GrabOffset grabOffsetObj = handGrabbable.grabPoses[m_PreviewIndex.intValue].grabOffset;
|
||||
Quaternion handRot = handGrabbable.transform.rotation * Quaternion.Inverse(grabOffsetObj.rotOffset);
|
||||
Quaternion handRotDiff = handRot * Quaternion.Inverse(grabOffsetObj.sourceRotation);
|
||||
Vector3 handPos = handGrabbable.transform.position - handRotDiff * grabOffsetObj.posOffset;
|
||||
meshHandPose.SetJointPose(JointType.Wrist, new Pose(handPos, handRot));
|
||||
|
||||
foreach (JointType joint in Enum.GetValues(typeof(JointType)))
|
||||
{
|
||||
if (joint == JointType.Wrist || joint == JointType.Count) { continue; }
|
||||
|
||||
meshHandPose.GetPosition(joint, out Vector3 pos, local: true);
|
||||
Quaternion rot = recordedGrabRotations.GetArrayElementAtIndex((int)joint).quaternionValue;
|
||||
meshHandPose.SetJointPose(joint, new Pose(pos, rot), local: true);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Update the grabpose based on position and rotation of the MeshHand and Object.
|
||||
/// </summary>
|
||||
private void UpdateGrabPose()
|
||||
{
|
||||
HandPose handPose = HandPoseProvider.GetHandPose(isLeft.boolValue ? HandPoseType.MESH_LEFT : HandPoseType.MESH_RIGHT);
|
||||
if (handPose != null && handPose is MeshHandPose meshHandPose)
|
||||
{
|
||||
meshHandPose.GetPosition(JointType.Wrist, out Vector3 wristPosition);
|
||||
meshHandPose.GetRotation(JointType.Wrist, out Quaternion wristRotation);
|
||||
|
||||
Quaternion[] fingerJointRotation = new Quaternion[(int)JointType.Count];
|
||||
for (int i = 0; i < fingerJointRotation.Length; i++)
|
||||
{
|
||||
meshHandPose.GetRotation((JointType)i, out Quaternion jointRotation, local: true);
|
||||
fingerJointRotation[i] = jointRotation;
|
||||
}
|
||||
|
||||
GrabPose grabPose = handGrabbable.grabPoses[m_PreviewIndex.intValue];
|
||||
grabPose.Update(grabPoseName.stringValue, fingerJointRotation, isLeft.boolValue);
|
||||
grabPose.grabOffset.Update(wristPosition, wristRotation, handGrabbable.transform.position, handGrabbable.transform.rotation);
|
||||
handGrabbable.grabPoses[m_PreviewIndex.intValue] = grabPose;
|
||||
GrabbablePoseRecorder.SaveChanges();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
+11
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 7ba007edb5befc349a95aa1cfa7cb6c9
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
+37
@@ -0,0 +1,37 @@
|
||||
using UnityEngine;
|
||||
|
||||
#if UNITY_EDITOR
|
||||
using UnityEditor;
|
||||
namespace VIVE.OpenXR.Toolkits.RealisticHandInteraction
|
||||
{
|
||||
[CustomEditor(typeof(HandGrabInteractor))]
|
||||
public class HandGrabInteractorEditor : UnityEditor.Editor
|
||||
{
|
||||
private SerializedProperty m_Handedness, m_GrabDistance, m_OnBeginGrab, m_OnEndGrab;
|
||||
private bool showEvent = false;
|
||||
|
||||
private void OnEnable()
|
||||
{
|
||||
m_Handedness = serializedObject.FindProperty("m_Handedness");
|
||||
m_GrabDistance = serializedObject.FindProperty("m_GrabDistance");
|
||||
m_OnBeginGrab = serializedObject.FindProperty("m_OnBeginGrab");
|
||||
m_OnEndGrab = serializedObject.FindProperty("m_OnEndGrab");
|
||||
}
|
||||
|
||||
public override void OnInspectorGUI()
|
||||
{
|
||||
serializedObject.Update();
|
||||
EditorGUILayout.PropertyField(m_Handedness);
|
||||
EditorGUILayout.PropertyField(m_GrabDistance);
|
||||
showEvent = EditorGUILayout.Foldout(showEvent, "Grab Event");
|
||||
if (showEvent)
|
||||
{
|
||||
EditorGUILayout.PropertyField(m_OnBeginGrab);
|
||||
EditorGUILayout.PropertyField(m_OnEndGrab);
|
||||
|
||||
}
|
||||
serializedObject.ApplyModifiedProperties();
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
+11
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: a8e7c213fed939e4b859638cde97a31c
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
+85
@@ -0,0 +1,85 @@
|
||||
using UnityEngine;
|
||||
|
||||
#if UNITY_EDITOR
|
||||
using UnityEditor;
|
||||
namespace VIVE.OpenXR.Toolkits.RealisticHandInteraction
|
||||
{
|
||||
[CustomEditor(typeof(HandMeshManager))]
|
||||
public class HandMeshManagerEditor : Editor
|
||||
{
|
||||
private HandMeshManager m_HandMesh;
|
||||
private SerializedProperty m_Handedness, m_EnableCollider, m_HandJoints;
|
||||
|
||||
private bool showJoints = false;
|
||||
public static readonly GUIContent findJoints = EditorGUIUtility.TrTextContent("Find Joints");
|
||||
public static readonly GUIContent clearJoints = EditorGUIUtility.TrTextContent("All Clear");
|
||||
|
||||
private void OnEnable()
|
||||
{
|
||||
m_HandMesh = target as HandMeshManager;
|
||||
m_Handedness = serializedObject.FindProperty("m_Handedness");
|
||||
m_EnableCollider = serializedObject.FindProperty("m_EnableCollider");
|
||||
m_HandJoints = serializedObject.FindProperty("m_HandJoints");
|
||||
}
|
||||
|
||||
public override void OnInspectorGUI()
|
||||
{
|
||||
serializedObject.Update();
|
||||
EditorGUILayout.LabelField("Settings", EditorStyles.boldLabel);
|
||||
|
||||
EditorGUILayout.HelpBox("Please check if your model is used to bind left hand poses", MessageType.None);
|
||||
EditorGUILayout.PropertyField(m_Handedness, new GUIContent("Handedness"));
|
||||
|
||||
EditorGUILayout.HelpBox("Please check if you want the hand model with collision enabled.", MessageType.None);
|
||||
EditorGUILayout.PropertyField(m_EnableCollider, new GUIContent("Enable Collider"));
|
||||
|
||||
showJoints = EditorGUILayout.Foldout(showJoints, "Hand Bones Reference");
|
||||
if (showJoints)
|
||||
{
|
||||
EditorGUILayout.HelpBox("Please change rotation to make sure your model should palm faces forward and fingers points up in global axis.", MessageType.Info);
|
||||
|
||||
using (new EditorGUILayout.HorizontalScope())
|
||||
{
|
||||
using (new EditorGUI.DisabledScope())
|
||||
{
|
||||
if (GUILayout.Button(findJoints))
|
||||
{
|
||||
m_HandMesh.FindJoints();
|
||||
}
|
||||
}
|
||||
|
||||
using (new EditorGUI.DisabledScope())
|
||||
{
|
||||
if (GUILayout.Button(clearJoints))
|
||||
{
|
||||
m_HandMesh.ClearJoints();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool isDetected = false;
|
||||
for (int i = 0; i < m_HandJoints.arraySize; i++)
|
||||
{
|
||||
SerializedProperty bone = m_HandJoints.GetArrayElementAtIndex(i);
|
||||
Transform boneTransform = (Transform)bone.objectReferenceValue;
|
||||
if (boneTransform != null)
|
||||
{
|
||||
isDetected = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (isDetected)
|
||||
{
|
||||
for (int i = 0; i < m_HandJoints.arraySize; i++)
|
||||
{
|
||||
SerializedProperty bone = m_HandJoints.GetArrayElementAtIndex(i);
|
||||
EditorGUILayout.PropertyField(bone, new GUIContent(((JointType)i).ToString()));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
serializedObject.ApplyModifiedProperties();
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
+11
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: d606d68d81c647241b90f1060786476c
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
Reference in New Issue
Block a user