/// <summary> /// Init based on an existing Skeleton_Pose /// </summary> public SkeletonBlendablePose(SteamVR_Skeleton_Pose p) { pose = p; snapshotR = new SteamVR_Skeleton_PoseSnapshot(p.rightHand.bonePositions.Length, SteamVR_Input_Sources.RightHand); snapshotL = new SteamVR_Skeleton_PoseSnapshot(p.leftHand.bonePositions.Length, SteamVR_Input_Sources.LeftHand); }
public override void OnInspectorGUI() { bool createNew = false; serializedObject.Update(); if (Application.isPlaying) { EditorGUILayout.LabelField("Cannot modify pose while in play mode."); return; } LoadDefaultPreviewHands(); if (skeletonPoseProperty.objectReferenceValue == null) { EditorGUILayout.BeginHorizontal(); EditorGUILayout.PropertyField(skeletonPoseProperty); createNew = GUILayout.Button("Create"); EditorGUILayout.EndHorizontal(); } else { EditorGUILayout.PropertyField(skeletonPoseProperty); EditorGUILayout.Space(); UpdatePreviewHand(previewLeftInstanceProperty, showLeftPreviewProperty, previewLeftHandPrefab, poser.skeletonPose.leftHand); UpdatePreviewHand(previewRightInstanceProperty, showRightPreviewProperty, previewRightHandPrefab, poser.skeletonPose.rightHand); DrawSaveButtons(); } serializedObject.ApplyModifiedProperties(); if (createNew) { string fullPath = EditorUtility.SaveFilePanelInProject("Create New Skeleton Pose", "newPose", "asset", "Save file"); if (string.IsNullOrEmpty(fullPath) == false) { SteamVR_Skeleton_Pose newPose = ScriptableObject.CreateInstance <SteamVR_Skeleton_Pose>(); AssetDatabase.CreateAsset(newPose, fullPath); AssetDatabase.SaveAssets(); skeletonPoseProperty.objectReferenceValue = newPose; serializedObject.ApplyModifiedProperties(); } } }
void CopyPoseSelect() { string selected = EditorUtility.OpenFilePanel("Open Skeleton Pose ScriptableObject", Application.dataPath, "asset"); selected = selected.Replace(Application.dataPath, "Assets"); if (selected == null) { return; } SteamVR_Skeleton_Pose newPose = (SteamVR_Skeleton_Pose)AssetDatabase.LoadAssetAtPath(selected, typeof(SteamVR_Skeleton_Pose)); if (newPose == null) { EditorUtility.DisplayDialog("WARNING", "Asset could not be loaded. Is it not a SteamVR_Skeleton_Pose?", "ok"); return; } DeepCopyPose(newPose, activePose); }
protected void Awake() { if (previewLeftInstance != null) { DestroyImmediate(previewLeftInstance); } if (previewRightInstance != null) { DestroyImmediate(previewRightInstance); } blendPoses = new SkeletonBlendablePose[skeletonAdditionalPoses.Count + 1]; for (int i = 0; i < blendPoseCount; i++) { SteamVR_Skeleton_Pose iterPose = GetPoseByIndex(i); // ValheimVR Mod Edit: Potentially need to initialize here // to workaround serialized data not traveling with AssetBundle if (iterPose.leftHand.bonePositions == null) { Debug.Log("Initializing Left Hand Pose Data for index : " + i); HandResourceInitializer.Initialize_SteamVR_Skeleton_Pose_Hand(ref iterPose.leftHand, i, HandResourceInitializer.LEFT_HAND); } if (iterPose.rightHand.bonePositions == null) { Debug.Log("Initializing Right Hand Pose Data for index : " + i); HandResourceInitializer.Initialize_SteamVR_Skeleton_Pose_Hand(ref iterPose.rightHand, i, HandResourceInitializer.RIGHT_HAND); } blendPoses[i] = new SkeletonBlendablePose(iterPose); blendPoses[i].PoseToSnapshots(); } boneCount = skeletonMainPose.leftHand.bonePositions.Length; // NOTE: Is there a better way to get the bone count? idk blendedSnapshotL = new SteamVR_Skeleton_PoseSnapshot(boneCount, SteamVR_Input_Sources.LeftHand); blendedSnapshotR = new SteamVR_Skeleton_PoseSnapshot(boneCount, SteamVR_Input_Sources.RightHand); }
protected void UpdatePreviewHand(SerializedProperty instanceProperty, SerializedProperty showPreviewProperty, GameObject previewPrefab, SteamVR_Skeleton_Pose_Hand handData, SteamVR_Skeleton_Pose sourcePose, bool forceUpdate) { GameObject preview = instanceProperty.objectReferenceValue as GameObject; //EditorGUILayout.PropertyField(showPreviewProperty); if (showPreviewProperty.boolValue) { if (forceUpdate && preview != null) { DestroyImmediate(preview); } if (preview == null) { preview = Instantiate <GameObject>(previewPrefab); preview.transform.localScale = Vector3.one * poserScale.floatValue; preview.transform.parent = poser.transform; preview.transform.localPosition = Vector3.zero; preview.transform.localRotation = Quaternion.identity; SteamVR_Behaviour_Skeleton previewSkeleton = null; if (preview != null) { previewSkeleton = preview.GetComponent <SteamVR_Behaviour_Skeleton>(); } if (previewSkeleton != null) { if (handData.bonePositions == null || handData.bonePositions.Length == 0) { SteamVR_Skeleton_Pose poseResource = (SteamVR_Skeleton_Pose)Resources.Load("ReferencePose_OpenHand"); DeepCopyPose(poseResource, sourcePose); EditorUtility.SetDirty(sourcePose); } preview.transform.localPosition = Vector3.zero; preview.transform.localRotation = Quaternion.identity; preview.transform.parent = null; preview.transform.localScale = Vector3.one * poserScale.floatValue; preview.transform.parent = poser.transform; preview.transform.localRotation = Quaternion.Inverse(handData.rotation); preview.transform.position = preview.transform.TransformPoint(-handData.position); for (int boneIndex = 0; boneIndex < handData.bonePositions.Length; boneIndex++) { Transform bone = previewSkeleton.GetBone(boneIndex); bone.localPosition = handData.bonePositions[boneIndex]; bone.localRotation = handData.boneRotations[boneIndex]; } } SceneView.RepaintAll(); instanceProperty.objectReferenceValue = preview; } } else { if (preview != null) { DestroyImmediate(preview); SceneView.RepaintAll(); } } }
void DrawPoseEditorMenu() { if (Application.isPlaying) { EditorGUILayout.LabelField("Cannot modify pose while in play mode."); } else { bool createNew = false; LoadDefaultPreviewHands(); activePoseIndex = previewPoseSelection.intValue; if (activePoseIndex == 0) { activePoseProp = skeletonMainPoseProperty; } else { activePoseProp = skeletonAdditionalPosesProperty.GetArrayElementAtIndex(activePoseIndex - 1); } //box containing all pose editing controls GUILayout.BeginVertical("box"); poseEditorExpanded.boolValue = IndentedFoldoutHeader(poseEditorExpanded.boolValue, "Pose Editor"); if (poseEditorExpanded.boolValue) { //show selectable menu of all poses, highlighting the one that is selected EditorGUILayout.Space(); poser.poseNames = new string[skeletonAdditionalPosesProperty.arraySize + 1]; for (int i = 0; i < skeletonAdditionalPosesProperty.arraySize + 1; i++) { if (i == 0) { // main pose special case poser.poseNames[i] = skeletonMainPoseProperty.objectReferenceValue == null ? "[not set]" : skeletonMainPoseProperty.objectReferenceValue.name + " (MAIN)"; } else { // additional poses from array poser.poseNames[i] = skeletonAdditionalPosesProperty.GetArrayElementAtIndex(i - 1).objectReferenceValue == null ? "[not set]" : skeletonAdditionalPosesProperty.GetArrayElementAtIndex(i - 1).objectReferenceValue.name; } } EditorGUILayout.BeginHorizontal(); int poseSelected = GUILayout.Toolbar(activePoseIndex, poser.poseNames); if (poseSelected != activePoseIndex) { forceUpdateHands = true; activePoseIndex = poseSelected; PoseChanged = true; previewPoseSelection.intValue = activePoseIndex; serializedObject.ApplyModifiedProperties(); } EditorGUILayout.BeginVertical(GUILayout.MaxWidth(32)); if (GUILayout.Button("+", GUILayout.MaxWidth(32))) { skeletonAdditionalPosesProperty.InsertArrayElementAtIndex(skeletonAdditionalPosesProperty.arraySize); } //only allow deletion of additional poses EditorGUI.BeginDisabledGroup(skeletonAdditionalPosesProperty.arraySize == 0 || activePoseIndex == 0); if (GUILayout.Button("-", GUILayout.MaxWidth(32)) && skeletonAdditionalPosesProperty.arraySize > 0) { skeletonAdditionalPosesProperty.DeleteArrayElementAtIndex(activePoseIndex - 1); skeletonAdditionalPosesProperty.DeleteArrayElementAtIndex(activePoseIndex - 1); if (activePoseIndex >= skeletonAdditionalPosesProperty.arraySize + 1) { activePoseIndex = skeletonAdditionalPosesProperty.arraySize; previewPoseSelection.intValue = activePoseIndex; return; } } EditorGUI.EndDisabledGroup(); EditorGUILayout.EndVertical(); GUILayout.FlexibleSpace(); EditorGUILayout.EndHorizontal(); GUILayout.BeginVertical("box"); // sides of pose editor GUILayout.BeginHorizontal(); //pose controls GUILayout.BeginVertical(GUILayout.MaxWidth(200)); GUILayout.Label("Current Pose:"); if (PoseChanged) { PoseChanged = false; forceUpdateHands = true; if (activePoseIndex == 0) { activePoseProp = skeletonMainPoseProperty; } else { activePoseProp = skeletonAdditionalPosesProperty.GetArrayElementAtIndex(activePoseIndex - 1); } activePose = (SteamVR_Skeleton_Pose)activePoseProp.objectReferenceValue; } activePose = (SteamVR_Skeleton_Pose)activePoseProp.objectReferenceValue; if (activePoseProp.objectReferenceValue == null) { if (previewLeftInstanceProperty.objectReferenceValue != null) { DestroyImmediate(previewLeftInstanceProperty.objectReferenceValue); } if (previewRightInstanceProperty.objectReferenceValue != null) { DestroyImmediate(previewRightInstanceProperty.objectReferenceValue); } EditorGUILayout.BeginHorizontal(); activePoseProp.objectReferenceValue = EditorGUILayout.ObjectField(activePoseProp.objectReferenceValue, typeof(SteamVR_Skeleton_Pose), false); if (GUILayout.Button("Create")) { createNew = true; } EditorGUILayout.EndHorizontal(); if (createNew) { string fullPath = EditorUtility.SaveFilePanelInProject("Create New Skeleton Pose", "newPose", "asset", "Save file"); if (string.IsNullOrEmpty(fullPath) == false) { SteamVR_Skeleton_Pose newPose = CreateInstance <SteamVR_Skeleton_Pose>(); AssetDatabase.CreateAsset(newPose, fullPath); AssetDatabase.SaveAssets(); activePoseProp.objectReferenceValue = newPose; serializedObject.ApplyModifiedProperties(); } } } else { activePoseProp.objectReferenceValue = EditorGUILayout.ObjectField(activePoseProp.objectReferenceValue, typeof(SteamVR_Skeleton_Pose), false); DrawPoseControlButtons(); UpdatePreviewHand(previewLeftInstanceProperty, showLeftPreviewProperty, SteamVR_Settings.instance.previewHandLeft, activePose.leftHand, activePose, forceUpdateHands); UpdatePreviewHand(previewRightInstanceProperty, showRightPreviewProperty, SteamVR_Settings.instance.previewHandRight, activePose.rightHand, activePose, forceUpdateHands); forceUpdateHands = false; GUILayout.EndVertical(); GUILayout.Space(10); if (handTexL == null) { handTexL = (Texture)EditorGUIUtility.Load("Assets/SteamVR/Input/Editor/Resources/Icons/HandLeftIcon.png"); } if (handTexR == null) { handTexR = (Texture)EditorGUIUtility.Load("Assets/SteamVR/Input/Editor/Resources/Icons/HandRightIcon.png"); } //Left Hand GUILayout.Space(32); EditorGUILayout.BeginVertical(); EditorGUILayout.BeginVertical("box"); EditorGUILayout.BeginHorizontal(); GUI.color = new Color(1, 1, 1, showLeftPreviewProperty.boolValue ? 1 : 0.25f); if (GUILayout.Button(handTexL, GUI.skin.label, GUILayout.Width(64), GUILayout.Height(64))) { showLeftPreviewProperty.boolValue = !showLeftPreviewProperty.boolValue; //forceUpdateHands = true; } GUI.color = Color.white; EditorGUIUtility.labelWidth = 48; EditorGUILayout.LabelField("Left Hand", EditorStyles.boldLabel); EditorGUIUtility.labelWidth = 0; GUILayout.FlexibleSpace(); EditorGUILayout.EndHorizontal(); bool showLeft = showLeftPreviewProperty.boolValue; DrawHand(showLeft, activePose.leftHand, activePose.rightHand, getLeftFromOpposite, showLeftPreviewProperty); EditorGUILayout.EndVertical(); EditorGUI.BeginDisabledGroup((showLeftPreviewProperty.boolValue && showRightPreviewProperty.boolValue) == false); getRightFromOpposite = GUILayout.Button("Copy Left pose to Right hand"); EditorGUI.EndDisabledGroup(); EditorGUILayout.EndVertical(); EditorGUILayout.BeginVertical(); EditorGUILayout.BeginVertical("box"); EditorGUILayout.BeginHorizontal(); GUILayout.FlexibleSpace(); EditorGUIUtility.labelWidth = 48; EditorGUILayout.LabelField("Right Hand", EditorStyles.boldLabel); EditorGUIUtility.labelWidth = 0; GUI.color = new Color(1, 1, 1, showRightPreviewProperty.boolValue ? 1 : 0.25f); if (GUILayout.Button(handTexR, GUI.skin.label, GUILayout.Width(64), GUILayout.Height(64))) { showRightPreviewProperty.boolValue = !showRightPreviewProperty.boolValue; //forceUpdateHands = true; } GUI.color = Color.white; EditorGUILayout.EndHorizontal(); bool showRight = showLeftPreviewProperty.boolValue; DrawHand(showRight, activePose.rightHand, activePose.leftHand, getRightFromOpposite, showRightPreviewProperty); EditorGUILayout.EndVertical(); EditorGUI.BeginDisabledGroup((showLeftPreviewProperty.boolValue && showRightPreviewProperty.boolValue) == false); getLeftFromOpposite = GUILayout.Button("Copy Right pose to Left hand"); EditorGUI.EndDisabledGroup(); } /* * * * * * if (activePoseProp.objectReferenceValue == null) * { * EditorGUILayout.BeginHorizontal(); * EditorGUILayout.PropertyField(activePoseProp); * createNew = GUILayout.Button("Create"); * EditorGUILayout.EndHorizontal(); * } * else * { * EditorGUILayout.PropertyField(activePoseProp); * * DrawDivider(); * * * DrawSaveButtons(); * * if (PoseChanged) * { * PoseChanged = false; * forceUpdateHands = true; * } * * UpdatePreviewHand(previewLeftInstanceProperty, showLeftPreviewProperty, previewLeftHandPrefab, activePose.leftHand, forceUpdateHands); * UpdatePreviewHand(previewRightInstanceProperty, showRightPreviewProperty, previewRightHandPrefab, activePose.rightHand, forceUpdateHands); * * } * * activePoseProp.objectReferenceValue = newPose; * serializedObject.ApplyModifiedProperties(); * } * } */ GUILayout.EndVertical(); EditorGUILayout.EndVertical(); GUILayout.EndHorizontal(); EditorGUI.BeginChangeCheck(); EditorGUILayout.BeginHorizontal(); EditorGUIUtility.labelWidth = 120; poserScale.floatValue = EditorGUILayout.FloatField("Preview Pose Scale", poserScale.floatValue); if (poserScale.floatValue <= 0) { poserScale.floatValue = 1; } EditorGUIUtility.labelWidth = 0; GUILayout.FlexibleSpace(); EditorGUILayout.EndHorizontal(); if (EditorGUI.EndChangeCheck()) { forceUpdateHands = true; } } GUILayout.EndVertical(); } }
void DeepCopyPose(SteamVR_Skeleton_Pose source, SteamVR_Skeleton_Pose dest) { int boneNum = SteamVR_Action_Skeleton.numBones; if (dest.rightHand.bonePositions == null) { dest.rightHand.bonePositions = new Vector3[boneNum]; } if (dest.rightHand.boneRotations == null) { dest.rightHand.boneRotations = new Quaternion[boneNum]; } if (dest.leftHand.bonePositions == null) { dest.leftHand.bonePositions = new Vector3[boneNum]; } if (dest.leftHand.boneRotations == null) { dest.leftHand.boneRotations = new Quaternion[boneNum]; } EditorUtility.SetDirty(dest); // RIGHT HAND COPY dest.rightHand.position = source.rightHand.position; dest.rightHand.rotation = source.rightHand.rotation; for (int boneIndex = 0; boneIndex < boneNum; boneIndex++) { dest.rightHand.bonePositions[boneIndex] = source.rightHand.bonePositions[boneIndex]; dest.rightHand.boneRotations[boneIndex] = source.rightHand.boneRotations[boneIndex]; EditorUtility.DisplayProgressBar("Copying...", "Copying right hand pose", (float)boneIndex / (float)boneNum / 2f); } dest.rightHand.thumbFingerMovementType = source.rightHand.thumbFingerMovementType; dest.rightHand.indexFingerMovementType = source.rightHand.indexFingerMovementType; dest.rightHand.middleFingerMovementType = source.rightHand.middleFingerMovementType; dest.rightHand.ringFingerMovementType = source.rightHand.ringFingerMovementType; dest.rightHand.pinkyFingerMovementType = source.rightHand.pinkyFingerMovementType; // LEFT HAND COPY dest.leftHand.position = source.leftHand.position; dest.leftHand.rotation = source.leftHand.rotation; for (int boneIndex = 0; boneIndex < boneNum; boneIndex++) { dest.leftHand.bonePositions[boneIndex] = source.leftHand.bonePositions[boneIndex]; dest.leftHand.boneRotations[boneIndex] = source.leftHand.boneRotations[boneIndex]; EditorUtility.DisplayProgressBar("Copying...", "Copying left hand pose", (float)boneIndex / (float)boneNum / 2f); } dest.leftHand.thumbFingerMovementType = source.leftHand.thumbFingerMovementType; dest.leftHand.indexFingerMovementType = source.leftHand.indexFingerMovementType; dest.leftHand.middleFingerMovementType = source.leftHand.middleFingerMovementType; dest.leftHand.ringFingerMovementType = source.leftHand.ringFingerMovementType; dest.leftHand.pinkyFingerMovementType = source.leftHand.pinkyFingerMovementType; EditorUtility.SetDirty(dest); forceUpdateHands = true; EditorUtility.ClearProgressBar(); }
protected void DrawPoseControlButtons() { GameObject leftInstance = previewLeftInstanceProperty.objectReferenceValue as GameObject; leftSkeleton = null; if (leftInstance != null) { leftSkeleton = leftInstance.GetComponent <SteamVR_Behaviour_Skeleton>(); } GameObject rightInstance = previewRightInstanceProperty.objectReferenceValue as GameObject; rightSkeleton = null; if (rightInstance != null) { rightSkeleton = rightInstance.GetComponent <SteamVR_Behaviour_Skeleton>(); } //only allow saving if a hand is opened for editing EditorGUI.BeginDisabledGroup(showRightPreviewProperty.boolValue == false && showLeftPreviewProperty.boolValue == false); GUI.color = new Color(0.9f, 1.0f, 0.9f); // save both hands at once, or whichever are being edited bool save = GUILayout.Button(string.Format("Save Pose")); if (save) { if (showRightPreviewProperty.boolValue) { SaveHandData(activePose.rightHand, rightSkeleton); } if (showLeftPreviewProperty.boolValue) { SaveHandData(activePose.leftHand, leftSkeleton); } } GUI.color = Color.white; EditorGUI.EndDisabledGroup(); //MIRRORING //only allow mirroring if both hands are opened for editing EditorGUI.BeginDisabledGroup(showRightPreviewProperty.boolValue == false || showLeftPreviewProperty.boolValue == false); EditorGUILayout.Space(); if (GUILayout.Button("Import Pose")) { CopyPoseSelect(); } EditorGUI.EndDisabledGroup(); GUILayout.Space(32); GUILayout.Label("Reference Pose:"); EditorGUILayout.Space(); forceToReferencePose = (EVRSkeletalReferencePose)EditorGUILayout.EnumPopup(forceToReferencePose); GUI.color = new Color(1.0f, 0.73f, 0.7f); bool forcePose = GUILayout.Button("RESET TO REFERENCE POSE"); GUI.color = Color.white; if (forcePose) { bool confirm = EditorUtility.DisplayDialog("SteamVR", string.Format("This will overwrite your current skeleton data. (with data from the {0} reference pose)", forceToReferencePose.ToString()), "Overwrite", "Cancel"); if (confirm) { if (forceToReferencePose == EVRSkeletalReferencePose.GripLimit) { // grip limit is controller-specific, the rest use a baked pose if (showLeftPreviewProperty.boolValue) { leftSkeleton.ForceToReferencePose(forceToReferencePose); } if (showRightPreviewProperty.boolValue) { rightSkeleton.ForceToReferencePose(forceToReferencePose); } } else { SteamVR_Skeleton_Pose poseResource = null; if (forceToReferencePose == EVRSkeletalReferencePose.OpenHand) { poseResource = (SteamVR_Skeleton_Pose)Resources.Load("ReferencePose_OpenHand"); } if (forceToReferencePose == EVRSkeletalReferencePose.Fist) { poseResource = (SteamVR_Skeleton_Pose)Resources.Load("ReferencePose_Fist"); } if (forceToReferencePose == EVRSkeletalReferencePose.BindPose) { poseResource = (SteamVR_Skeleton_Pose)Resources.Load("ReferencePose_BindPose"); } DeepCopyPose(poseResource, activePose); } } } }
/// <summary> /// Blend from the current skeletonBlend amount to pose animation. (skeletonBlend = 0) /// Note: This will ignore the root position and rotation of the pose. /// </summary> /// <param name="overTime">How long you want the blend to take (in seconds)</param> /// <param name="attachToTransform">If you have a positiona and rotation offset for your pose you can attach it to a particular transform</param> public void BlendToPose(SteamVR_Skeleton_Pose pose, Transform attachToTransform, float overTime = 0.1f) { blendToPose = pose.GetHand(inputSource); BlendTo(0, overTime); }