private void DoDriveInspector(SerializedProperty drive, ArticulationDofLock dofLock) { // If lockedMotion - don't render any drive inspector fields if (dofLock == ArticulationDofLock.LockedMotion) { return; } EditorGUILayout.LabelField(drive.displayName); EditorGUI.indentLevel++; // Display limit fields only if drive is LimitedMotion if (dofLock == ArticulationDofLock.LimitedMotion) { EditorGUILayout.PropertyField(drive.FindPropertyRelative("lowerLimit"), Styles.lowerLimit); EditorGUILayout.PropertyField(drive.FindPropertyRelative("upperLimit"), Styles.upperLimit); } // Always display fields EditorGUILayout.PropertyField(drive.FindPropertyRelative("stiffness"), Styles.stiffness); EditorGUILayout.PropertyField(drive.FindPropertyRelative("damping"), Styles.damping); EditorGUILayout.PropertyField(drive.FindPropertyRelative("forceLimit"), Styles.forceLimit); EditorGUILayout.PropertyField(drive.FindPropertyRelative("target"), Styles.target); EditorGUILayout.PropertyField(drive.FindPropertyRelative("targetVelocity"), Styles.targetVelocity); EditorGUI.indentLevel--; EditorGUILayout.Space(); }
public override void OnInspectorGUI() { serializedObject.Update(); ArticulationBody body = (ArticulationBody)target; if (!body.isRoot) { using (new EditorGUI.DisabledScope(body.gameObject.activeInHierarchy == false)) { EditorGUILayout.EditorToolbarForTarget(EditorGUIUtility.TrTempContent("Edit Joints"), target); } } EditorGUILayout.Space(5); EditorGUILayout.PropertyField(m_Mass, Styles.mass); EditorGUILayout.PropertyField(m_UseGravity, Styles.useGravity); if (body.isRoot) { EditorGUILayout.PropertyField(m_Immovable, Styles.immovable); if (!m_Immovable.boolValue) { EditorGUILayout.PropertyField(m_LinearDamping, Styles.linearDamping); EditorGUILayout.PropertyField(m_AngularDamping, Styles.angularDamping); } EditorGUILayout.PropertyField(m_CollisionDetectionMode, Styles.collisionDetectionMode); EditorGUILayout.HelpBox("This is the root body of the articulation.", MessageType.Info); } else { EditorGUILayout.PropertyField(m_LinearDamping, Styles.linearDamping); EditorGUILayout.PropertyField(m_AngularDamping, Styles.angularDamping); EditorGUILayout.PropertyField(m_JointFriction, Styles.jointFriction); EditorGUILayout.PropertyField(m_CollisionDetectionMode, Styles.collisionDetectionMode); EditorGUILayout.PropertyField(m_MatchAnchors, Styles.matchAnchors); // Show anchor edit fields and set to joint if changed // The reason we have change checks here is because in AwakeFromLoad we won't overwrite anchors // If we were to do that, simulation would drift caused by anchors reset relative to current poses EditorGUI.BeginChangeCheck(); EditorGUILayout.PropertyField(m_AnchorPosition, Styles.anchorPosition); EditorGUILayout.PropertyField(m_AnchorRotation, Styles.anchorRotation); if (EditorGUI.EndChangeCheck()) { Undo.RecordObject(target, "Changing Articulation body anchor position/rotation"); body.anchorPosition = m_AnchorPosition.vector3Value; body.anchorRotation = m_AnchorRotation.quaternionValue; if (m_MatchAnchors.boolValue) { // setting child anchors in this mode will also change the parent ones // lets fetch them back otherwise ApplyModifiedProperties overwrites them m_ParentAnchorPosition.vector3Value = body.parentAnchorPosition; m_ParentAnchorRotation.quaternionValue = body.parentAnchorRotation; } } // parent anchors if (!m_MatchAnchors.boolValue) { EditorGUI.BeginChangeCheck(); EditorGUILayout.PropertyField(m_ParentAnchorPosition, Styles.parentAnchorPosition); EditorGUILayout.PropertyField(m_ParentAnchorRotation, Styles.parentAnchorRotation); if (EditorGUI.EndChangeCheck()) { Undo.RecordObject(target, "Changing Articulation body parent anchor position/rotation"); body.parentAnchorPosition = m_ParentAnchorPosition.vector3Value; body.parentAnchorRotation = m_ParentAnchorRotation.quaternionValue; } } if (GUILayout.Button("Snap anchor to closest contact")) { Undo.RecordObject(body, "Changing anchor position/rotation to match closest contact."); body.SnapAnchorToClosestContact(); } EditorGUILayout.PropertyField(m_ArticulationJointType); // the tooltip for this is still in the header switch (body.jointType) { case ArticulationJointType.FixedJoint: break; case ArticulationJointType.PrismaticJoint: // work out joint settings LinearDof linearDof = LinearDof.X; // x by default ArticulationDofLock dofLockSetting = ArticulationDofLock.FreeMotion; if (body.linearLockX != ArticulationDofLock.LockedMotion) { linearDof = LinearDof.X; dofLockSetting = body.linearLockX; } else if (body.linearLockY != ArticulationDofLock.LockedMotion) { linearDof = LinearDof.Y; dofLockSetting = body.linearLockY; } else if (body.linearLockZ != ArticulationDofLock.LockedMotion) { linearDof = LinearDof.Z; dofLockSetting = body.linearLockZ; } int dofCount = 0; if (body.linearLockX != ArticulationDofLock.LockedMotion) { dofCount++; } if (body.linearLockY != ArticulationDofLock.LockedMotion) { dofCount++; } if (body.linearLockZ != ArticulationDofLock.LockedMotion) { dofCount++; } bool overrideDof = (dofCount != 1); EditorGUI.BeginChangeCheck(); EditorGUILayout.Space(); linearDof = (LinearDof)EditorGUILayout.EnumPopup(Styles.prismaticAxis, linearDof); NonLockedMotion motion = (dofLockSetting == ArticulationDofLock.FreeMotion) ? NonLockedMotion.Free : NonLockedMotion.Limited; motion = (NonLockedMotion)EditorGUILayout.EnumPopup(Styles.unlockedMotionType, motion); if (EditorGUI.EndChangeCheck() || overrideDof) { m_LinearX.enumValueIndex = (linearDof == LinearDof.X) ? (int)motion : 0; m_LinearY.enumValueIndex = (linearDof == LinearDof.Y) ? (int)motion : 0; m_LinearZ.enumValueIndex = (linearDof == LinearDof.Z) ? (int)motion : 0; } EditorGUILayout.Space(); DoDriveInspector(m_YDrive, (ArticulationDofLock)m_LinearY.enumValueIndex); DoDriveInspector(m_ZDrive, (ArticulationDofLock)m_LinearZ.enumValueIndex); DoDriveInspector(m_XDrive, (ArticulationDofLock)m_LinearX.enumValueIndex); break; case ArticulationJointType.RevoluteJoint: ArticulationDofLock serialisedDofLock = (ArticulationDofLock)m_Twist.enumValueIndex; NonLockedMotion revoluteMotion = serialisedDofLock == ArticulationDofLock.LimitedMotion ? NonLockedMotion.Limited : NonLockedMotion.Free; EditorGUILayout.Space(); motion = (NonLockedMotion)EditorGUILayout.EnumPopup(Styles.unlockedMotionType, revoluteMotion); ArticulationDofLock newDofLock = (ArticulationDofLock)motion; if (newDofLock != serialisedDofLock) { m_Twist.enumValueIndex = (int)newDofLock; } EditorGUILayout.Space(); DoDriveInspector(m_XDrive, newDofLock); break; case ArticulationJointType.SphericalJoint: EditorGUILayout.Space(); // here we just need to make sure we disable getting into an invalid configuration SphericalJointMotionSetting(m_SwingY); SphericalJointMotionSetting(m_SwingZ); SphericalJointMotionSetting(m_Twist); EditorGUILayout.Space(); DoDriveInspector(m_YDrive, body.swingYLock); DoDriveInspector(m_ZDrive, body.swingZLock); DoDriveInspector(m_XDrive, body.twistLock); break; } } ClampDriveLimits(m_YDrive, body.yDrive); ClampDriveLimits(m_ZDrive, body.zDrive); ClampDriveLimits(m_XDrive, body.xDrive); serializedObject.ApplyModifiedProperties(); }
public override void OnInspectorGUI() { serializedObject.Update(); ArticulationBody body = (ArticulationBody)target; ArticulationBody parentBody = FindParentBody(body); EditorGUILayout.PropertyField(m_Mass); if (body.isRoot) { EditorGUILayout.PropertyField(m_Immovable); EditorGUILayout.PropertyField(m_UseGravity); EditorGUILayout.HelpBox("This is the root body of the articulation.", MessageType.Info); } else { EditorGUILayout.PropertyField(m_UseGravity); EditorGUILayout.PropertyField(m_ComputeParentAnchor); // Render anchor handle display button only if editor scene view has Move, Rotate or Transform tool mode selected if (IsEditToolModeForAnchorDisplay()) { if (m_DisplayParentAnchor) { m_DisplayParentAnchor = !GUILayout.Button("Show anchor handle"); } else { m_DisplayParentAnchor = GUILayout.Button("Show parent anchor handle"); } } // Show anchor edit fields and set to joint if changed // The reason we have change checks here is because in AwakeFromLoad we won't overwrite anchors // If we were to do that, simulation would drift caused by anchors reset relative to current poses EditorGUI.BeginChangeCheck(); EditorGUILayout.PropertyField(m_AnchorPosition); QuaternionAsEulerAnglesPropertyField("Anchor Rotation", m_AnchorRotation, body.anchorRotation); if (EditorGUI.EndChangeCheck()) { body.anchorPosition = m_AnchorPosition.vector3Value; body.anchorRotation = m_AnchorRotation.quaternionValue; if (m_ComputeParentAnchor.boolValue) { // setting child anchors in this mode will also change the parent ones // lets fetch them back otherwise ApplyModifiedProperties overwrites them m_ParentAnchorPosition.vector3Value = body.parentAnchorPosition; m_ParentAnchorRotation.quaternionValue = body.parentAnchorRotation; } } // parent anchors if (!m_ComputeParentAnchor.boolValue) { EditorGUI.BeginChangeCheck(); EditorGUILayout.PropertyField(m_ParentAnchorPosition); QuaternionAsEulerAnglesPropertyField("Parent Anchor Rotation", m_ParentAnchorRotation, body.parentAnchorRotation); if (EditorGUI.EndChangeCheck()) { body.parentAnchorPosition = m_ParentAnchorPosition.vector3Value; body.parentAnchorRotation = m_ParentAnchorRotation.quaternionValue; } } if (GUILayout.Button("Snap anchor to closest contact")) { Undo.RecordObject(body, "Changing anchor position/rotation to match closest contact."); Vector3 com = parentBody.centerOfMass; Vector3 closestOnSurface = body.GetClosestPoint(com); body.anchorPosition = body.transform.InverseTransformPoint(closestOnSurface); body.anchorRotation = Quaternion.FromToRotation(Vector3.right, body.transform.InverseTransformDirection(com - closestOnSurface).normalized); } EditorGUILayout.PropertyField(m_ArticulationJointType); EditorGUILayout.PropertyField(m_LinearDamping); EditorGUILayout.PropertyField(m_AngularDamping); EditorGUILayout.PropertyField(m_JointFriction); switch (body.jointType) { case ArticulationJointType.FixedJoint: break; case ArticulationJointType.PrismaticJoint: // work out joint settings LinearDof linearDof = LinearDof.X; // x by default ArticulationDofLock dofLockSetting = ArticulationDofLock.FreeMotion; if (body.linearLockX != ArticulationDofLock.LockedMotion) { linearDof = LinearDof.X; dofLockSetting = body.linearLockX; } else if (body.linearLockY != ArticulationDofLock.LockedMotion) { linearDof = LinearDof.Y; dofLockSetting = body.linearLockY; } else if (body.linearLockZ != ArticulationDofLock.LockedMotion) { linearDof = LinearDof.Z; dofLockSetting = body.linearLockZ; } int dofCount = 0; if (body.linearLockX != ArticulationDofLock.LockedMotion) { dofCount++; } if (body.linearLockY != ArticulationDofLock.LockedMotion) { dofCount++; } if (body.linearLockZ != ArticulationDofLock.LockedMotion) { dofCount++; } bool overrideDof = (dofCount != 1); EditorGUI.BeginChangeCheck(); EditorGUILayout.Space(); linearDof = (LinearDof)EditorGUILayout.EnumPopup("Axis", linearDof); NonLockedMotion motion = (dofLockSetting == ArticulationDofLock.FreeMotion) ? NonLockedMotion.Free : NonLockedMotion.Limited; motion = (NonLockedMotion)EditorGUILayout.EnumPopup("Motion", motion); if (EditorGUI.EndChangeCheck() || overrideDof) { m_LinearX.enumValueIndex = (linearDof == LinearDof.X) ? (int)motion : 0; m_LinearY.enumValueIndex = (linearDof == LinearDof.Y) ? (int)motion : 0; m_LinearZ.enumValueIndex = (linearDof == LinearDof.Z) ? (int)motion : 0; } EditorGUILayout.Space(); DoDriveInspector(m_YDrive, (ArticulationDofLock)m_LinearY.enumValueIndex); DoDriveInspector(m_ZDrive, (ArticulationDofLock)m_LinearZ.enumValueIndex); DoDriveInspector(m_XDrive, (ArticulationDofLock)m_LinearX.enumValueIndex); break; case ArticulationJointType.RevoluteJoint: ArticulationDofLock serialisedDofLock = (ArticulationDofLock)m_Twist.enumValueIndex; NonLockedMotion revoluteMotion = serialisedDofLock == ArticulationDofLock.LimitedMotion ? NonLockedMotion.Limited : NonLockedMotion.Free; EditorGUILayout.Space(); motion = (NonLockedMotion)EditorGUILayout.EnumPopup("Motion", revoluteMotion); ArticulationDofLock newDofLock = (ArticulationDofLock)motion; if (newDofLock != serialisedDofLock) { m_Twist.enumValueIndex = (int)newDofLock; } EditorGUILayout.Space(); DoDriveInspector(m_XDrive, newDofLock); break; case ArticulationJointType.SphericalJoint: EditorGUILayout.Space(); // here we just need to make sure we disable getting into an invalid configuration SphericalJointMotionSetting(m_SwingY); SphericalJointMotionSetting(m_SwingZ); SphericalJointMotionSetting(m_Twist); EditorGUILayout.Space(); DoDriveInspector(m_YDrive, body.swingYLock); DoDriveInspector(m_ZDrive, body.swingZLock); DoDriveInspector(m_XDrive, body.twistLock); break; } } serializedObject.ApplyModifiedProperties(); ShowBodyInfoProperties(); }