public static JointAxis GetSymmetricJointAxis(Transform jointTransform, Vector3 axis, Vector3 secondaryAxis, JointAxis jointAxis, Transform symmetricTransform, Vector3 symmetricAxis, Vector3 symmetricSecondaryAxis, Transform root) { Vector3 a = JointAxisToVector3(axis, secondaryAxis, jointAxis); Vector3 aWorld = jointTransform.rotation * a; Vector3 aWorldMirror = SymmetryTools.Mirror(aWorld, root); Vector3 aLocalMirror = Quaternion.Inverse(symmetricTransform.rotation) * aWorldMirror; Vector3 sAVector = AxisTools.GetAxisVectorToDirection(symmetricTransform, aWorldMirror); Vector3 sA = Vector3.Project(aLocalMirror, sAVector); return(GetJointAxis(symmetricAxis, symmetricSecondaryAxis, sA)); }
void OnSceneGUI() { Rigidbody[] rigidbodies = script.transform.GetComponentsInChildren <Rigidbody>(); if (rigidbodies.Length == 0) { return; } Collider[] colliders = script.transform.GetComponentsInChildren <Collider>(); if (script.selectedRigidbody == null) { script.selectedRigidbody = rigidbodies[0]; } if (script.selectedCollider == null && colliders.Length > 0) { script.selectedCollider = colliders[0]; } Rigidbody symmetricRigidbody = script.symmetry && script.selectedRigidbody != null?SymmetryTools.GetSymmetric(script.selectedRigidbody, rigidbodies, script.transform) : null; Collider symmetricCollider = script.symmetry && script.selectedCollider != null?SymmetryTools.GetSymmetric(script.selectedCollider, colliders, script.transform) : null; Joint joint = script.selectedRigidbody != null?script.selectedRigidbody.GetComponent <Joint>() : null; Joint symmetricJoint = joint != null && symmetricRigidbody != null?symmetricRigidbody.GetComponent <Joint>() : null; // Selected Transform selected = script.mode == RootMotion.Dynamics.RagdollEditor.Mode.Colliders? (script.selectedCollider != null? script.selectedCollider.transform: null): (script.selectedRigidbody != null? script.selectedRigidbody.transform: null); if (selected != null) { Handles.BeginGUI(); GUILayout.BeginVertical(new GUIContent("Ragdoll Editor", string.Empty), "Window", GUILayout.Width(200), GUILayout.Height(20)); GUILayout.BeginHorizontal(); GUILayout.Label(selected.name); if (GUILayout.Button("Select GameObject", EditorStyles.miniButton)) { Selection.activeGameObject = selected.gameObject; } GUILayout.EndHorizontal(); GUILayout.Space(10); //GUILayout.BeginVertical("Box"); GUILayout.BeginHorizontal(); GUILayout.Label("Edit Mode", GUILayout.Width(86)); script.mode = (RagdollEditor.Mode)EditorGUILayout.EnumPopup(string.Empty, script.mode, GUILayout.Width(100)); GUILayout.EndHorizontal(); GUILayout.BeginHorizontal(); GUILayout.Label("Symmetry", GUILayout.Width(86)); script.symmetry = GUILayout.Toggle(script.symmetry, string.Empty); GUILayout.EndHorizontal(); GUILayout.Space(10); // COLLIDERS if (script.mode == RagdollEditor.Mode.Colliders && selected != null) { if (script.selectedCollider is CapsuleCollider) { var capsule = script.selectedCollider as CapsuleCollider; var capsuleS = symmetricCollider != null?symmetricCollider.transform.GetComponent <CapsuleCollider>() : null; if (GUILayout.Button("Convert To Box Collider")) { ColliderTools.ConvertToBoxCollider(capsule); script.selectedCollider = selected.GetComponent <Collider>(); if (capsuleS != null) { ColliderTools.ConvertToBoxCollider(capsuleS); } return; } if (GUILayout.Button("Convert To Sphere Collider")) { ColliderTools.ConvertToSphereCollider(capsule); script.selectedCollider = selected.GetComponent <Collider>(); if (capsuleS != null) { ColliderTools.ConvertToSphereCollider(capsuleS); } return; } string capsuleDir = capsule.direction == 0? "X": (capsule.direction == 1? "Y": "Z"); if (GUILayout.Button("Direction: " + capsuleDir)) { if (capsuleS == null) { Undo.RecordObject(capsule, "Change Capsule Direction"); } else { Undo.RecordObjects(new Object[2] { capsule, capsuleS }, "Change Capsule Direction"); } capsule.direction++; if (capsule.direction > 2) { capsule.direction = 0; } if (capsuleS != null) { capsuleS.direction = capsule.direction; } } } else if (script.selectedCollider is BoxCollider) { var box = script.selectedCollider as BoxCollider; var boxS = symmetricCollider != null?symmetricCollider.transform.GetComponent <BoxCollider>() : null; if (GUILayout.Button("Convert To Capsule Collider")) { ColliderTools.ConvertToCapsuleCollider(box); script.selectedCollider = selected.GetComponent <Collider>(); if (boxS != null) { ColliderTools.ConvertToCapsuleCollider(boxS); } return; } if (GUILayout.Button("Convert To Sphere Collider")) { ColliderTools.ConvertToSphereCollider(box); script.selectedCollider = selected.GetComponent <Collider>(); if (boxS != null) { ColliderTools.ConvertToSphereCollider(boxS); } return; } if (GUILayout.Button("Rotate Collider")) { if (boxS == null) { Undo.RecordObject(box, "Rotate Collider"); } else { Undo.RecordObjects(new Object[2] { box, boxS }, "Rotate Collider"); } box.size = new Vector3(box.size.y, box.size.z, box.size.x); if (boxS != null) { boxS.size = box.size; } } } else if (script.selectedCollider is SphereCollider) { var sphere = script.selectedCollider as SphereCollider; var sphereS = symmetricCollider != null?symmetricCollider.transform.GetComponent <SphereCollider>() : null; if (GUILayout.Button("Convert To Capsule Collider")) { ColliderTools.ConvertToCapsuleCollider(sphere); script.selectedCollider = selected.GetComponent <Collider>(); if (sphereS != null) { ColliderTools.ConvertToCapsuleCollider(sphereS); } return; } if (GUILayout.Button("Convert To Box Collider")) { ColliderTools.ConvertToBoxCollider(sphere); script.selectedCollider = selected.GetComponent <Collider>(); if (sphereS != null) { ColliderTools.ConvertToBoxCollider(sphereS); } return; } } } // JOINTS if (script.mode == RagdollEditor.Mode.Joints) { if (joint != null && (joint is CharacterJoint || joint is ConfigurableJoint)) { GUILayout.BeginHorizontal(); GUILayout.Label("Connected Body"); var lastConnectedBody = joint.connectedBody; var newConnectedBody = (Rigidbody)EditorGUILayout.ObjectField(joint.connectedBody, typeof(Rigidbody), true); if (newConnectedBody != lastConnectedBody) { Undo.RecordObject(joint, "Changing Joint ConnectedBody"); joint.connectedBody = newConnectedBody; } GUILayout.EndHorizontal(); if (joint is CharacterJoint) { var j = joint as CharacterJoint; var sJ = symmetricJoint != null && symmetricJoint is CharacterJoint? symmetricJoint as CharacterJoint: null; if (GUILayout.Button("Convert to Configurable")) { JointConverter.CharacterToConfigurable(j); if (sJ != null) { JointConverter.CharacterToConfigurable(sJ); } } if (GUILayout.Button("Switch Yellow/Green")) { JointTools.SwitchXY(ref j); if (sJ != null) { JointTools.SwitchXY(ref sJ); } } if (GUILayout.Button("Switch Yellow/Blue")) { JointTools.SwitchXZ(ref j); if (sJ != null) { JointTools.SwitchXZ(ref sJ); } } if (GUILayout.Button("Switch Green/Blue")) { JointTools.SwitchYZ(ref j); if (sJ != null) { JointTools.SwitchYZ(ref sJ); } } if (GUILayout.Button("Invert Yellow")) { JointTools.InvertAxis(ref joint); if (sJ != null) { JointTools.InvertAxis(ref symmetricJoint); } } } if (joint is ConfigurableJoint) { var j = joint as ConfigurableJoint; var sJ = symmetricJoint != null && symmetricJoint is ConfigurableJoint? symmetricJoint as ConfigurableJoint: null; if (GUILayout.Button("Switch Yellow/Green")) { JointTools.SwitchXY(ref j); if (sJ != null) { JointTools.SwitchXY(ref sJ); } } if (GUILayout.Button("Switch Yellow/Blue")) { JointTools.SwitchXZ(ref j); if (sJ != null) { JointTools.SwitchXZ(ref sJ); } } if (GUILayout.Button("Switch Green/Blue")) { JointTools.SwitchYZ(ref j); if (sJ != null) { JointTools.SwitchYZ(ref sJ); } } if (GUILayout.Button("Invert Yellow")) { JointTools.InvertAxis(ref joint); if (sJ != null) { JointTools.InvertAxis(ref symmetricJoint); } } } } } GUILayout.EndVertical(); //GUILayout.EndArea(); Handles.EndGUI(); if (script.mode == RagdollEditor.Mode.Joints && joint != null) { if (joint is CharacterJoint) { var j = joint as CharacterJoint; SoftJointLimit lowTwistLimit = j.lowTwistLimit; SoftJointLimit highTwistLimit = j.highTwistLimit; SoftJointLimit swing1Limit = j.swing1Limit; SoftJointLimit swing2Limit = j.swing2Limit; CharacterJointInspector.DrawJoint(j); if (symmetricJoint != null && symmetricJoint is CharacterJoint) { var sJ = symmetricJoint as CharacterJoint; CharacterJointInspector.DrawJoint(sJ, false, 0.5f); // Low Twist if (lowTwistLimit.limit != j.lowTwistLimit.limit) { Undo.RecordObject(sJ, "Change Joint Limits"); Vector3 lowXAxisWorld = JointTools.GetLowXAxisWorld(j); Vector3 lowXAxisWorldS = JointTools.GetLowXAxisWorld(sJ); Vector3 lowXAxisWorldMirror = SymmetryTools.Mirror(lowXAxisWorld, script.transform); bool low = Vector3.Dot(lowXAxisWorldMirror, lowXAxisWorldS) < 0f; JointAxis sJointAxis = JointTools.GetSymmetricJointAxis(j, JointAxis.Primary, sJ, script.transform); float delta = j.lowTwistLimit.limit - lowTwistLimit.limit; JointTools.ApplyXDeltaToJointLimit(ref sJ, delta, sJointAxis, low); } // High Twist if (highTwistLimit.limit != j.highTwistLimit.limit) { Undo.RecordObject(sJ, "Change Joint Limits"); Vector3 highXAxisWorld = JointTools.GetHighXAxisWorld(j); Vector3 highXAxisWorldS = JointTools.GetHighXAxisWorld(sJ); Vector3 highXAxisWorldMirror = SymmetryTools.Mirror(highXAxisWorld, script.transform); bool low = Vector3.Dot(highXAxisWorldMirror, highXAxisWorldS) > 0f; JointAxis sJointAxis = JointTools.GetSymmetricJointAxis(j, JointAxis.Primary, sJ, script.transform); float delta = j.highTwistLimit.limit - highTwistLimit.limit; JointTools.ApplyXDeltaToJointLimit(ref sJ, -delta, sJointAxis, low); } // Swing 1 if (swing1Limit.limit != j.swing1Limit.limit) { Undo.RecordObject(sJ, "Change Joint Limits"); JointAxis sJointAxis = JointTools.GetSymmetricJointAxis(j, JointAxis.Secondary, sJ, script.transform); float delta = j.swing1Limit.limit - swing1Limit.limit; JointTools.ApplyDeltaToJointLimit(ref sJ, delta, sJointAxis); } // Swing 2 if (swing2Limit.limit != j.swing2Limit.limit) { Undo.RecordObject(sJ, "Change Joint Limits"); JointAxis sJointAxis = JointTools.GetSymmetricJointAxis(j, JointAxis.Tertiary, sJ, script.transform); float delta = j.swing2Limit.limit - swing2Limit.limit; JointTools.ApplyDeltaToJointLimit(ref sJ, delta, sJointAxis); } } } else if (joint is ConfigurableJoint) { var j = joint as ConfigurableJoint; SoftJointLimit lowAngularXLimit = j.lowAngularXLimit; SoftJointLimit highAngularXLimit = j.highAngularXLimit; SoftJointLimit angularYLimit = j.angularYLimit; SoftJointLimit angularZLimit = j.angularZLimit; ConfigurableJointInspector.DrawJoint(j); if (symmetricJoint != null && symmetricJoint is ConfigurableJoint) { var sJ = symmetricJoint as ConfigurableJoint; ConfigurableJointInspector.DrawJoint(sJ, false, 0.5f); // Low X if (lowAngularXLimit.limit != j.lowAngularXLimit.limit) { Undo.RecordObject(sJ, "Change Joint Limits"); Vector3 lowXAxisWorld = JointTools.GetLowXAxisWorld(j); Vector3 lowXAxisWorldS = JointTools.GetLowXAxisWorld(sJ); Vector3 lowXAxisWorldMirror = SymmetryTools.Mirror(lowXAxisWorld, script.transform); bool low = Vector3.Dot(lowXAxisWorldMirror, lowXAxisWorldS) < 0f; JointAxis sJointAxis = JointTools.GetSymmetricJointAxis(j, JointAxis.Primary, sJ, script.transform); float delta = j.lowAngularXLimit.limit - lowAngularXLimit.limit; JointTools.ApplyXDeltaToJointLimit(ref sJ, delta, sJointAxis, low); } // High X if (highAngularXLimit.limit != j.highAngularXLimit.limit) { Undo.RecordObject(sJ, "Change Joint Limits"); Vector3 highXAxisWorld = JointTools.GetHighXAxisWorld(j); Vector3 highXAxisWorldS = JointTools.GetHighXAxisWorld(sJ); Vector3 highXAxisWorldMirror = SymmetryTools.Mirror(highXAxisWorld, script.transform); bool low = Vector3.Dot(highXAxisWorldMirror, highXAxisWorldS) > 0f; JointAxis sJointAxis = JointTools.GetSymmetricJointAxis(j, JointAxis.Primary, sJ, script.transform); float delta = j.highAngularXLimit.limit - highAngularXLimit.limit; JointTools.ApplyXDeltaToJointLimit(ref sJ, -delta, sJointAxis, low); } // Y if (angularYLimit.limit != j.angularYLimit.limit) { Undo.RecordObject(sJ, "Change Joint Limits"); JointAxis sJointAxis = JointTools.GetSymmetricJointAxis(j, JointAxis.Secondary, sJ, script.transform); float delta = j.angularYLimit.limit - angularYLimit.limit; JointTools.ApplyDeltaToJointLimit(ref sJ, delta, sJointAxis); } // Z if (angularZLimit.limit != j.angularZLimit.limit) { Undo.RecordObject(sJ, "Change Joint Limits"); JointAxis sJointAxis = JointTools.GetSymmetricJointAxis(j, JointAxis.Tertiary, sJ, script.transform); float delta = j.angularZLimit.limit - angularZLimit.limit; JointTools.ApplyDeltaToJointLimit(ref sJ, delta, sJointAxis); } } } } } if (!Application.isPlaying) { foreach (Collider c in colliders) { c.enabled = script.mode == RagdollEditor.Mode.Colliders; } } // HANDLES Color color = new Color(0.2f, 0.9f, 0.5f); Handles.color = color; if (Event.current.type == EventType.MouseUp) { isDragging = false; } if (Event.current.type == EventType.MouseDown) { isDragging = false; } if (script.mode == RagdollEditor.Mode.Colliders) { // Select/move scale colliders for (int i = 0; i < colliders.Length; i++) { if (colliders[i] == script.selectedCollider) { // Moving and scaling selected colliders switch (Tools.current) { case Tool.Move: Vector3 oldPosition = ColliderTools.GetColliderCenterWorld(colliders[i]); Vector3 newPosition = Handles.PositionHandle(oldPosition, colliders[i].transform.rotation); if (newPosition != oldPosition) { if (!isDragging) { Undo.RecordObjects(SymmetryTools.GetColliderPair(colliders[i], symmetricCollider), "Move Colliders"); isDragging = true; } ColliderTools.SetColliderCenterWorld(colliders[i], symmetricCollider, newPosition, script.transform); } break; case Tool.Scale: Vector3 position = ColliderTools.GetColliderCenterWorld(colliders[i]); Vector3 oldSize = ColliderTools.GetColliderSize(colliders[i]); Vector3 oldSizeS = ColliderTools.GetColliderSize(symmetricCollider); Vector3 newSize = Handles.ScaleHandle(oldSize, position, colliders[i].transform.rotation, HandleUtility.GetHandleSize(position)); if (newSize != oldSize) { if (!isDragging) { Undo.RecordObjects(SymmetryTools.GetColliderPair(colliders[i], symmetricCollider), "Scale Colliders"); isDragging = true; } ColliderTools.SetColliderSize(colliders[i], symmetricCollider, newSize, oldSize, oldSizeS, script.transform); } Handles.color = color; break; } // Dot on selected collider if (Tools.current != Tool.Scale) { Handles.color = new Color(0.8f, 0.8f, 0.8f); Vector3 center = ColliderTools.GetColliderCenterWorld(colliders[i]); float size = GetHandleSize(center); Handles.CubeCap(0, center, colliders[i].transform.rotation, size); Handles.color = color; } } else { // Selecting colliders Vector3 center = ColliderTools.GetColliderCenterWorld(colliders[i]); float size = GetHandleSize(center); if (Handles.Button(center, Quaternion.identity, size * 0.5f, size * 0.5f, Handles.DotCap)) { Undo.RecordObject(script, "Change RagdollEditor Selection"); script.selectedCollider = colliders[i]; } } } } else { // Select joints for (int i = 0; i < rigidbodies.Length; i++) { if (rigidbodies[i] == script.selectedRigidbody) { // Dots on selected joints Handles.color = new Color(0.8f, 0.8f, 0.8f); Vector3 center = rigidbodies[i].transform.position; float size = GetHandleSize(center); Handles.CubeCap(0, center, rigidbodies[i].transform.rotation, size); Handles.color = color; } else { // Selecting joints Vector3 center = rigidbodies[i].transform.position; float size = GetHandleSize(center); if (Handles.Button(center, Quaternion.identity, size * 0.5f, size * 0.5f, Handles.DotCap)) { Undo.RecordObject(script, "Change RagdollEditor Selection"); script.selectedRigidbody = rigidbodies[i]; } } } } Handles.color = Color.white; }
public static void SetColliderCenterWorld(Collider r, Collider s, Vector3 value, Transform root) { Vector3 newCenter = r.transform.InverseTransformPoint(value); Vector3 centerWorld = Vector3.zero; Vector3 deltaWorld = Vector3.zero; if (r is BoxCollider) { var box = r as BoxCollider; centerWorld = r.transform.TransformPoint(box.center); deltaWorld = value - centerWorld; box.center = newCenter; if (s != null && s is BoxCollider) { s.transform.GetComponent <BoxCollider>().center += s.transform.InverseTransformVector(SymmetryTools.Mirror(deltaWorld, root)); } return; } if (r is CapsuleCollider) { var capsule = r as CapsuleCollider; centerWorld = r.transform.TransformPoint(capsule.center); deltaWorld = value - centerWorld; capsule.center = newCenter; if (s != null && s is CapsuleCollider) { s.transform.GetComponent <CapsuleCollider>().center += s.transform.InverseTransformVector(SymmetryTools.Mirror(deltaWorld, root)); } return; } if (r is SphereCollider) { var sphere = r as SphereCollider; centerWorld = r.transform.TransformPoint(sphere.center); deltaWorld = value - centerWorld; sphere.center = newCenter; if (s != null && s is SphereCollider) { s.transform.GetComponent <SphereCollider>().center += s.transform.InverseTransformVector(SymmetryTools.Mirror(deltaWorld, root)); } return; } }