version 2.3.0

This commit is contained in:
Sean Lu(呂祥榮)
2024-05-15 14:09:18 +08:00
parent 45b4e46f74
commit 7f2a459592
289 changed files with 116381 additions and 5440 deletions

View File

@@ -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 HTCs 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

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: c01f88bc88bb27849a723888721c96f4
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,246 @@
// "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 HTCs 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;
using UnityEditorInternal;
namespace VIVE.OpenXR.Toolkits.RealisticHandInteraction
{
[CustomEditor(typeof(HandGrabInteractable))]
public class HandGrabInteractableEditor : UnityEditor.Editor
{
private SerializedProperty m_IsGrabbable, m_ForceMovable, m_FingerRequirement, m_GrabPoses, m_ShowAllIndicator;
private SerializedProperty grabPoseName, gestureThumbPose, gestureIndexPose, gestureMiddlePose, gestureRingPose, gesturePinkyPose,
recordedGrabRotations, isLeft, enableIndicator, autoIndicator, indicatorObject, grabOffset;
private ReorderableList grabPoses;
private bool showGrabPoses = false;
private void OnEnable()
{
m_IsGrabbable = serializedObject.FindProperty("m_IsGrabbable");
m_ForceMovable = serializedObject.FindProperty("m_ForceMovable");
m_FingerRequirement = serializedObject.FindProperty("m_FingerRequirement");
m_GrabPoses = serializedObject.FindProperty("m_GrabPoses");
m_ShowAllIndicator = serializedObject.FindProperty("m_ShowAllIndicator");
#region ReorderableList
grabPoses = new ReorderableList(serializedObject, m_GrabPoses, true, true, true, true);
grabPoses.drawHeaderCallback = (Rect rect) =>
{
EditorGUI.LabelField(rect, "Grab Pose List");
};
grabPoses.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 gestureRect = new Rect(rect.x, rect.y, rect.width, EditorGUIUtility.singleLineHeight);
grabPoseName.stringValue = EditorGUI.TextField(gestureRect, grabPoseName.stringValue);
if (recordedGrabRotations.arraySize == 0)
{
// Draw GrabGesture fields
gestureRect.y += EditorGUIUtility.singleLineHeight + EditorGUIUtility.standardVerticalSpacing;
EditorGUI.PropertyField(gestureRect, gestureThumbPose);
gestureRect.y += EditorGUIUtility.singleLineHeight + EditorGUIUtility.standardVerticalSpacing;
EditorGUI.PropertyField(gestureRect, gestureIndexPose);
gestureRect.y += EditorGUIUtility.singleLineHeight + EditorGUIUtility.standardVerticalSpacing;
EditorGUI.PropertyField(gestureRect, gestureMiddlePose);
gestureRect.y += EditorGUIUtility.singleLineHeight + EditorGUIUtility.standardVerticalSpacing;
EditorGUI.PropertyField(gestureRect, gestureRingPose);
gestureRect.y += EditorGUIUtility.singleLineHeight + EditorGUIUtility.standardVerticalSpacing;
EditorGUI.PropertyField(gestureRect, gesturePinkyPose);
}
// Draw Handness fields
gestureRect.y += EditorGUIUtility.singleLineHeight + EditorGUIUtility.standardVerticalSpacing;
bool isToggle = EditorGUI.Toggle(gestureRect, "Is Left", isLeft.boolValue);
if (isToggle != isLeft.boolValue)
{
isLeft.boolValue = isToggle;
SwitchRotations(ref recordedGrabRotations);
}
// Draw Indicator fields
gestureRect.y += EditorGUIUtility.singleLineHeight + EditorGUIUtility.standardVerticalSpacing;
enableIndicator.boolValue = EditorGUI.Toggle(gestureRect, "Show Indicator", enableIndicator.boolValue);
if (enableIndicator.boolValue)
{
gestureRect.y += EditorGUIUtility.singleLineHeight + EditorGUIUtility.standardVerticalSpacing;
autoIndicator.boolValue = EditorGUI.Toggle(gestureRect, "Auto Generator Indicator", autoIndicator.boolValue);
if (!autoIndicator.boolValue)
{
gestureRect.y += EditorGUIUtility.singleLineHeight + EditorGUIUtility.standardVerticalSpacing;
indicatorObject.objectReferenceValue = (GameObject)EditorGUI.ObjectField(gestureRect, "Indicator", (GameObject)indicatorObject.objectReferenceValue, typeof(GameObject), true);
}
}
else
{
m_ShowAllIndicator.boolValue = false;
}
// Draw Mirror Pose fields
gestureRect.y += EditorGUIUtility.singleLineHeight + EditorGUIUtility.standardVerticalSpacing;
Rect labelRect = new Rect(gestureRect.x, gestureRect.y, EditorGUIUtility.labelWidth, gestureRect.height);
EditorGUI.PrefixLabel(labelRect, GUIUtility.GetControlID(FocusType.Passive), new GUIContent("Mirror Pose"));
Rect buttonRect1 = new Rect(gestureRect.x + EditorGUIUtility.labelWidth + EditorGUIUtility.standardVerticalSpacing, gestureRect.y, (gestureRect.width - EditorGUIUtility.labelWidth - EditorGUIUtility.standardVerticalSpacing * 4) / 3, gestureRect.height);
Rect buttonRect2 = new Rect(buttonRect1.x + buttonRect1.width + EditorGUIUtility.standardVerticalSpacing, gestureRect.y, buttonRect1.width, gestureRect.height);
Rect buttonRect3 = new Rect(buttonRect2.x + buttonRect2.width + EditorGUIUtility.standardVerticalSpacing, gestureRect.y, buttonRect1.width, gestureRect.height);
if (GUI.Button(buttonRect1, "Align X axis"))
{
MirrorPose(ref grabOffset, Vector3.right);
}
if (GUI.Button(buttonRect2, "Align Y axis"))
{
MirrorPose(ref grabOffset, Vector3.up);
}
if (GUI.Button(buttonRect3, "Align Z axis"))
{
MirrorPose(ref grabOffset, Vector3.forward);
}
// Draw Position fields
gestureRect.y += EditorGUIUtility.singleLineHeight + EditorGUIUtility.standardVerticalSpacing;
EditorGUI.PropertyField(gestureRect, grabOffset.FindPropertyRelative("position"));
// Draw Rotation fields
SerializedProperty rotationProperty = grabOffset.FindPropertyRelative("rotation");
Vector4 rotationVector = new Vector4(rotationProperty.quaternionValue.x, rotationProperty.quaternionValue.y, rotationProperty.quaternionValue.z, rotationProperty.quaternionValue.w);
gestureRect.y += EditorGUIUtility.singleLineHeight + EditorGUIUtility.standardVerticalSpacing;
rotationVector = EditorGUI.Vector4Field(gestureRect, "Rotation", rotationVector);
rotationProperty.quaternionValue = new Quaternion(rotationVector.x, rotationVector.y, rotationVector.z, rotationVector.w);
};
grabPoses.elementHeightCallback = (int index) =>
{
if (!UpdateGrabPose(m_GrabPoses.GetArrayElementAtIndex(index))) { return EditorGUIUtility.singleLineHeight; }
// Including Title, Handness, Show Indicator, Mirror Pose, Position, Rotation
int minHeight = 6;
// 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 + 2);
};
grabPoses.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_IsGrabbable);
EditorGUILayout.PropertyField(m_ForceMovable);
EditorGUILayout.PropertyField(m_FingerRequirement);
showGrabPoses = EditorGUILayout.Foldout(showGrabPoses, "Grab Pose Settings");
if (showGrabPoses)
{
if(m_GrabPoses.arraySize == 0)
{
grabPoses.elementHeight = EditorGUIUtility.singleLineHeight;
}
grabPoses.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;
}
}
}
}
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;
}
/// <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 sourcePos = pose.FindPropertyRelative("position").vector3Value;
Quaternion sourceRot = pose.FindPropertyRelative("rotation").quaternionValue;
Vector3 sourceFwd = sourceRot * Vector3.forward;
Vector3 sourceUp = sourceRot * Vector3.up;
// Calculate the mirrored position using Vector3.Reflect along the specified mirror axis.
Vector3 mirroredPosition = Vector3.Reflect(sourcePos, mirrorAxis);
// Calculate the mirrored rotation using Quaternion.LookRotation and Vector3.Reflect for the forward and up vectors.
Quaternion mirroredRotation = Quaternion.LookRotation(Vector3.Reflect(sourceFwd, mirrorAxis), Vector3.Reflect(sourceUp, mirrorAxis));
pose.FindPropertyRelative("position").vector3Value = mirroredPosition;
pose.FindPropertyRelative("rotation").quaternionValue = mirroredRotation;
}
}
}
#endif

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 7ba007edb5befc349a95aa1cfa7cb6c9
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,69 @@
using UnityEngine;
#if UNITY_EDITOR
using UnityEditor;
namespace VIVE.OpenXR.Toolkits.RealisticHandInteraction
{
[CustomEditor(typeof(HandMeshManager))]
public class HandMeshManagerEditor : Editor
{
private HandMeshManager m_HandJointManager;
private SerializedProperty m_Handedness, m_HandGrabber, m_RootJointType, m_HandRootJoint, m_HandJoints;
private bool showJoints = false;
public static readonly GUIContent findJoints = EditorGUIUtility.TrTextContent("Find Joints");
public static readonly GUIContent clearJoints = EditorGUIUtility.TrTextContent("Clear");
private void OnEnable()
{
m_Handedness = serializedObject.FindProperty("m_Handedness");
m_HandGrabber = serializedObject.FindProperty("m_HandGrabber");
m_RootJointType = serializedObject.FindProperty("m_RootJointType");
m_HandRootJoint = serializedObject.FindProperty("m_HandRootJoint");
m_HandJoints = serializedObject.FindProperty("m_HandJoints");
}
public override void OnInspectorGUI()
{
serializedObject.Update();
EditorGUILayout.PropertyField(m_Handedness);
EditorGUILayout.PropertyField(m_HandGrabber);
EditorGUILayout.HelpBox("Without HandGrabber, it still works but won't stop when colliding with Immovable objects.", MessageType.Info);
EditorGUILayout.PropertyField(m_RootJointType);
EditorGUILayout.PropertyField(m_HandRootJoint);
showJoints = EditorGUILayout.Foldout(showJoints, "Hand Joints");
if (showJoints)
{
for (int i = 0; i < m_HandJoints.arraySize; i++)
{
SerializedProperty joint = m_HandJoints.GetArrayElementAtIndex(i);
JointType jointType = (JointType)i;
EditorGUILayout.PropertyField(joint, new GUIContent(jointType.ToString()));
}
using (new EditorGUILayout.HorizontalScope())
{
m_HandJointManager = target as HandMeshManager;
using (new EditorGUI.DisabledScope())
{
if (GUILayout.Button(findJoints))
{
m_HandJointManager.FindJoints();
}
}
using (new EditorGUI.DisabledScope())
{
if (GUILayout.Button(clearJoints))
{
m_HandJointManager.ClearJoints();
}
}
}
}
serializedObject.ApplyModifiedProperties();
}
}
}
#endif

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: d606d68d81c647241b90f1060786476c
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant: