Files
ApexSurgery/Assets/Oculus/Interaction/Editor/Grab/HandGrab/HandGrabPoseEditor.cs
T
2025-07-04 20:33:06 +03:00

274 lines
8.8 KiB
C#

/*
* Copyright (c) Meta Platforms, Inc. and affiliates.
* All rights reserved.
*
* Licensed under the Oculus SDK License Agreement (the "License");
* you may not use the Oculus SDK except in compliance with the License,
* which is provided at the time of installation or download, or which
* otherwise accompanies this software in either electronic or hard copy form.
*
* You may obtain a copy of the License at
*
* https://developer.oculus.com/licenses/oculussdk/
*
* Unless required by applicable law or agreed to in writing, the Oculus SDK
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
using Oculus.Interaction.Editor;
using Oculus.Interaction.HandGrab.Visuals;
using Oculus.Interaction.Input;
using System.Collections.Generic;
using UnityEditor;
using UnityEngine;
namespace Oculus.Interaction.HandGrab.Editor
{
[CustomEditor(typeof(HandGrabPose))]
public class HandGrabPoseEditor : UnityEditor.Editor
{
private HandGrabPose _handGrabPose;
private HandGhostProvider _ghostVisualsProvider;
private HandGhost _handGhost;
private Handedness _lastHandedness;
private Transform _relativeTo;
private int _editMode = 0;
private SerializedProperty _handPoseProperty;
private SerializedProperty _relativeToProperty;
private const float GIZMO_SCALE = 0.005f;
private static readonly string[] EDIT_MODES = new string[] { "Edit fingers", "Follow Surface" };
private void Awake()
{
_handGrabPose = target as HandGrabPose;
}
private void OnEnable()
{
_handPoseProperty = serializedObject.FindProperty("_handPose");
_relativeToProperty = serializedObject.FindProperty("_relativeTo");
AssignMissingGhostProvider();
}
private void OnDisable()
{
DestroyGhost();
}
public override void OnInspectorGUI()
{
base.OnInspectorGUI();
_relativeTo = _relativeToProperty.objectReferenceValue as Transform;
if (_handGrabPose.UsesHandPose())
{
EditorGUILayout.PropertyField(_handPoseProperty);
}
GUIStyle boldStyle = new GUIStyle(GUI.skin.label) { fontStyle = FontStyle.Bold };
EditorGUILayout.LabelField("Interactive Edition (Editor only)", boldStyle);
if (_handGrabPose.UsesHandPose())
{
DrawGhostMenu(_handGrabPose.HandPose);
}
else
{
DestroyGhost();
}
serializedObject.ApplyModifiedProperties();
}
private void DrawGhostMenu(HandPose handPose)
{
HandGhostProvider provider = EditorGUILayout.ObjectField("Ghost Provider", _ghostVisualsProvider, typeof(HandGhostProvider), false) as HandGhostProvider;
if (_handGhost == null
|| _ghostVisualsProvider != provider
|| _lastHandedness != handPose.Handedness)
{
RegenerateGhost(provider);
}
_ghostVisualsProvider = provider;
_lastHandedness = handPose.Handedness;
if (_handGrabPose.SnapSurface == null)
{
_editMode = 0;
}
else
{
_editMode = GUILayout.Toolbar(_editMode, EDIT_MODES);
}
}
public void OnSceneGUI()
{
if (SceneView.currentDrawingSceneView == null)
{
return;
}
if (_handGhost == null)
{
return;
}
if (_editMode == 0)
{
GhostEditFingers();
}
else if (_editMode == 1)
{
GhostFollowSurface();
}
}
#region ghost
private void AssignMissingGhostProvider()
{
if (_ghostVisualsProvider != null)
{
return;
}
HandGhostProviderUtils.TryGetDefaultProvider(out _ghostVisualsProvider);
}
private void RegenerateGhost(HandGhostProvider provider)
{
DestroyGhost();
CreateGhost();
}
private void CreateGhost()
{
if (_ghostVisualsProvider == null)
{
return;
}
Transform relativeTo = _handGrabPose.RelativeTo;
HandGhost ghostPrototype = _ghostVisualsProvider.GetHand(_handGrabPose.HandPose.Handedness);
_handGhost = GameObject.Instantiate(ghostPrototype, _handGrabPose.transform);
_handGhost.gameObject.hideFlags = HideFlags.HideAndDontSave;
Pose relativePose = _handGrabPose.RelativePose;
Pose pose = PoseUtils.GlobalPoseScaled(relativeTo, relativePose);
_handGhost.SetPose(_handGrabPose.HandPose, pose);
}
private void DestroyGhost()
{
if (_handGhost == null)
{
return;
}
GameObject.DestroyImmediate(_handGhost.gameObject);
}
private void GhostFollowSurface()
{
if (_handGhost == null)
{
return;
}
Pose ghostTargetPose = _handGrabPose.RelativePose;
if (_handGrabPose.SnapSurface != null)
{
Vector3 mousePosition = Event.current.mousePosition;
Ray ray = HandleUtility.GUIPointToWorldRay(mousePosition);
if (_handGrabPose.SnapSurface.CalculateBestPoseAtSurface(ray, out Pose poseInSurface, _relativeTo))
{
ghostTargetPose = PoseUtils.DeltaScaled(_relativeTo, poseInSurface);
}
}
_handGhost.SetRootPose(ghostTargetPose, _relativeTo);
Handles.color = EditorConstants.PRIMARY_COLOR_DISABLED;
Handles.DrawSolidDisc(_handGhost.transform.position, _handGhost.transform.right, 0.01f);
}
private void GhostEditFingers()
{
HandPuppet puppet = _handGhost.GetComponent<HandPuppet>();
if (puppet != null && puppet.JointMaps != null)
{
DrawBonesRotator(puppet.JointMaps);
}
}
private void DrawBonesRotator(List<HandJointMap> bones)
{
bool anyChanged = false;
for (int i = 0; i < FingersMetadata.HAND_JOINT_IDS.Length; i++)
{
bool changed = false;
HandJointId joint = FingersMetadata.HAND_JOINT_IDS[i];
HandFinger finger = FingersMetadata.JOINT_TO_FINGER[(int)joint];
if (_handGrabPose.HandPose.FingersFreedom[(int)finger] == JointFreedom.Free)
{
continue;
}
HandJointMap jointMap = bones.Find(b => b.id == joint);
if (jointMap == null)
{
continue;
}
Transform transform = jointMap.transform;
transform.localRotation = jointMap.RotationOffset * _handGrabPose.HandPose.JointRotations[i];
float scale = GIZMO_SCALE * _handGrabPose.transform.lossyScale.x;
Handles.color = EditorConstants.PRIMARY_COLOR;
Quaternion entryRotation = transform.rotation;
Quaternion rotation = Handles.Disc(entryRotation, transform.position,
transform.forward, scale, false, 0);
if (rotation != entryRotation)
{
changed = true;
}
if (FingersMetadata.HAND_JOINT_CAN_SPREAD[i])
{
Handles.color = EditorConstants.SECONDARY_COLOR;
Quaternion curlRotation = rotation;
rotation = Handles.Disc(curlRotation, transform.position,
transform.up, scale, false, 0);
if (rotation != curlRotation)
{
changed = true;
}
}
if (!changed)
{
continue;
}
transform.rotation = rotation;
Undo.RecordObject(_handGrabPose, "Bone Rotation");
_handGrabPose.HandPose.JointRotations[i] = jointMap.TrackedRotation;
anyChanged = true;
}
if (anyChanged)
{
EditorUtility.SetDirty(_handGrabPose);
}
}
#endregion
}
}