/* * Draws the scene view helpers for IKSolverFullBody * */ public static void AddScene(UnityEngine.Object target, IKSolverFullBody solver, Color color, bool modifiable, ref int selectedEffector, float size) { if (!modifiable) { return; } if (!solver.initiated) { return; } if (!Application.isPlaying && !solver.IsValid()) { return; } // Effectors for (int i = 0; i < solver.effectors.Length; i++) { bool rotate = solver.effectors[i].isEndEffector; float weight = rotate? Mathf.Max(solver.effectors[i].positionWeight, solver.effectors[i].rotationWeight): solver.effectors[i].positionWeight; if (weight > 0 && selectedEffector != i) { Handles.color = color; if (rotate) { if (Inspector.DotButton(solver.effectors[i].position, solver.effectors[i].rotation, size * 0.5f, size * 0.5f)) { selectedEffector = i; return; } } else { if (Inspector.SphereButton(solver.effectors[i].position, solver.effectors[i].rotation, size, size)) { selectedEffector = i; return; } } } } for (int i = 0; i < solver.effectors.Length; i++) { IKEffectorInspector.AddScene(solver.effectors[i], color, modifiable && i == selectedEffector, size); } if (GUI.changed) { EditorUtility.SetDirty(target); } }
private static void SelectChain(FABRIKChain[] chain, ref FABRIKChain selected, Color color) { foreach (FABRIKChain c in chain) { if (c.ik.solver.IKPositionWeight > 0 && selected != c) { Handles.color = GetChainColor(c, color); if (Inspector.DotButton(c.ik.solver.GetIKPosition(), Quaternion.identity, GetHandleSize(c.ik.solver.GetIKPosition()), GetHandleSize(c.ik.solver.GetIKPosition()))) { selected = c; return; } } } }
// Scene view handles to help with limb setup private static void AddLimbHelper(FBIKChain chain, float size, Transform root = null) { Vector3 cross = Vector3.Cross((chain.nodes[1].transform.position - chain.nodes[0].transform.position).normalized, (chain.nodes[2].transform.position - chain.nodes[0].transform.position).normalized); Vector3 bendDirection = -Vector3.Cross(cross.normalized, (chain.nodes[2].transform.position - chain.nodes[0].transform.position).normalized); if (bendDirection != Vector3.zero) { Color c = Handles.color; bool inverted = root != null && Vector3.Dot(root.forward, bendDirection.normalized) < 0f; // Inverted bend direction if (inverted) { GUI.color = new Color(1f, 0.75f, 0.75f); Handles.color = Color.yellow; if (Inspector.DotButton(chain.nodes[1].transform.position, Quaternion.identity, size * 0.5f, size)) { Warning.logged = false; Warning.Log("The bend direction of this limb appears to be inverted. Please rotate this bone so that the limb is bent in it's natural bending direction. If this limb is supposed to be bent in the direction pointed by the arrow, ignore this warning.", root, true); } } Inspector.ArrowCap(0, chain.nodes[1].transform.position, Quaternion.LookRotation(bendDirection), size * 2f); GUI.color = Color.white; Handles.color = c; } else { // The limb is completely stretched out Color c = Handles.color; Handles.color = Color.red; GUI.color = new Color(1f, 0.75f, 0.75f); if (Inspector.DotButton(chain.nodes[1].transform.position, Quaternion.identity, size * 0.5f, size)) { Warning.logged = false; Warning.Log("The limb is completely stretched out. Full Body Biped IK does not know which way the limb should be bent. Please rotate this bone slightly in it's bending direction.", root, true); } GUI.color = Color.white; Handles.color = c; } }
/* * Draws the scene view helpers for BipedIK.Solvers * */ public static void AddScene(BipedIKSolvers solvers, ref int selected) { // Draw limbs for (int i = 0; i < solvers.limbs.Length; i++) { IKSolverLimbInspector.AddScene(solvers.limbs[i] as IKSolverLimb, GetSolverColor(i), selected == i); } // Draw spine IKSolverHeuristicInspector.AddScene(solvers.spine, GetSolverColor(4), selected == 4); // Draw look at IKSolverLookAtInspector.AddScene(solvers.lookAt, GetSolverColor(5), selected == 5); // Draw aim IKSolverAimInspector.AddScene(solvers.aim, GetSolverColor(6), selected == 6); // Draw constraints ConstraintsInspector.AddScene(solvers.pelvis, GetSolverColor(7), selected == 7); // Selecting solvers if (Application.isPlaying) { for (int i = 0; i < solvers.ikSolvers.Length; i++) { Handles.color = GetSolverColor(i); if (solvers.ikSolvers[i].GetIKPositionWeight() > 0 && selected != i && solvers.ikSolvers[i].initiated) { if (Inspector.DotButton(solvers.ikSolvers[i].GetIKPosition(), Quaternion.identity, GetHandleSize(solvers.ikSolvers[i].GetIKPosition()), GetHandleSize(solvers.ikSolvers[i].GetIKPosition()))) { selected = i; } } } if ((solvers.pelvis.positionWeight > 0 || solvers.pelvis.rotationWeight > 0) && selected != solvers.ikSolvers.Length) { Handles.color = GetSolverColor(7); if (Inspector.DotButton(solvers.pelvis.position, Quaternion.identity, GetHandleSize(solvers.pelvis.position), GetHandleSize(solvers.pelvis.position))) { selected = solvers.ikSolvers.Length; } } } }
public void OnSceneGUI() { GUI.changed = false; // Set defaultLocalRotation so that the initial local rotation will be the zero point for the rotation limit if (!Application.isPlaying) { script.defaultLocalRotation = script.transform.localRotation; } if (script.axis == Vector3.zero) { return; } // Quick Editing Tools Handles.BeginGUI(); GUILayout.BeginArea(new Rect(10, Screen.height - 180, 550, 130), "Rotation Limit Polygonal", "Window"); // Cloning values from another RotationLimitPolygonal EditorGUILayout.BeginHorizontal(); if (Inspector.Button("Clone From", "Make this rotation limit identical to another", script, GUILayout.Width(220))) { CloneLimit(); } clone = (RotationLimitPolygonal)EditorGUILayout.ObjectField("", clone, typeof(RotationLimitPolygonal), true); EditorGUILayout.EndHorizontal(); // Symmetry symmetry = (Symmetry)EditorGUILayout.EnumPopup("Symmetry", symmetry, GUILayout.Width(220)); // Flipping EditorGUILayout.BeginHorizontal(); if (Inspector.Button("Flip X", "Flip points along local X axis", script, GUILayout.Width(100))) { FlipLimit(0); } if (Inspector.Button("Flip Y", "Flip points along local Y axis", script, GUILayout.Width(100))) { FlipLimit(1); } if (Inspector.Button("Flip Z", "Flip points along local Z axis", script, GUILayout.Width(100))) { FlipLimit(2); } GUILayout.Label("Flip everything along axis"); EditorGUILayout.EndHorizontal(); // Rotating EditorGUILayout.BeginHorizontal(); if (Inspector.Button("Rotate X", "Rotate points along X axis by Degrees", script, GUILayout.Width(100))) { RotatePoints(degrees, Vector3.right); } if (Inspector.Button("Rotate Y", "Rotate points along Y axis by Degrees", script, GUILayout.Width(100))) { RotatePoints(degrees, Vector3.up); } if (Inspector.Button("Rotate Z", "Rotate points along Z axis by Degrees", script, GUILayout.Width(100))) { RotatePoints(degrees, Vector3.forward); } degrees = EditorGUILayout.FloatField("Degrees", degrees, GUILayout.Width(200)); EditorGUILayout.EndHorizontal(); // Smooth/Optimize EditorGUILayout.BeginHorizontal(); if (Inspector.Button("Smooth", "Double the points", script)) { Smooth(); } if (Inspector.Button("Optimize", "Delete every second point", script)) { Optimize(); } EditorGUILayout.EndHorizontal(); GUILayout.EndArea(); Handles.EndGUI(); // Rebuild reach cones script.BuildReachCones(); // Draw a white transparent sphere DrawRotationSphere(script.transform.position); // Draw Axis DrawArrow(script.transform.position, Direction(script.axis), colorDefault, "Axis", 0.02f); // Display limit points for (int i = 0; i < script.points.Length; i++) { Color color = GetColor(i); // Paint the point in green or red if it belongs to an invalid reach cone Handles.color = color; GUI.color = color; // Line from the center to the point and the label Handles.DrawLine(script.transform.position, script.transform.position + Direction(script.points[i].point)); Handles.Label(script.transform.position + Direction(script.points[i].point + new Vector3(-0.02f, 0, 0)), " " + i.ToString()); // Selecting points Handles.color = colorHandles; if (Inspector.DotButton(script.transform.position + Direction(script.points[i].point), script.transform.rotation, 0.02f, 0.02f)) { selectedPoint = i; } Handles.color = Color.white; GUI.color = Color.white; // Limit point GUI if (i == selectedPoint) { Handles.BeginGUI(); GUILayout.BeginArea(new Rect(Screen.width - 240, Screen.height - 180, 230, 130), "Limit Point " + i.ToString(), "Window"); if (Inspector.Button("Delete", "Delete this point", script)) { if (script.points.Length > 3) { // Using the deletePoint index here because we dont want to delete points from the array that we are iterating deletePoint = i; } else if (!Warning.logged) { script.LogWarning("Polygonal Rotation Limit should have at least 3 limit points"); } } if (Inspector.Button("Add Point", "Add a new point next to this one", script)) { addPoint = i; } // Store point for undo Vector3 oldPoint = script.points[i].point; // Manual input for the point position Inspector.AddVector3(ref script.points[i].point, "Point", script, GUILayout.Width(210)); EditorGUILayout.Space(); // Tangent weight Inspector.AddFloat(ref script.points[i].tangentWeight, "Tangent Weight", "Weight of this point's tangent. Used in smoothing.", script, -Mathf.Infinity, Mathf.Infinity, GUILayout.Width(150)); GUILayout.EndArea(); Handles.EndGUI(); // Moving Points Vector3 pointWorld = Handles.PositionHandle(script.transform.position + Direction(script.points[i].point), Quaternion.identity); Vector3 newPoint = InverseDirection(pointWorld - script.transform.position); if (newPoint != script.points[i].point) { if (!Application.isPlaying) { Undo.RecordObject(script, "Move Limit Point"); } script.points[i].point = newPoint; } // Symmetry if (symmetry != Symmetry.Off && script.points.Length > 3 && oldPoint != script.points[i].point) { RotationLimitPolygonal.LimitPoint symmetryPoint = GetClosestPoint(Symmetrize(oldPoint, symmetry)); if (symmetryPoint != script.points[i]) { symmetryPoint.point = Symmetrize(script.points[i].point, symmetry); } } } // Normalize the point script.points[i].point = script.points[i].point.normalized; } // Display smoothed polygon for (int i = 0; i < script.P.Length; i++) { Color color = GetColor(i); // Smoothed triangles are transparent Handles.color = new Color(color.r, color.g, color.b, 0.25f); Handles.DrawLine(script.transform.position, script.transform.position + Direction(script.P[i])); Handles.color = color; if (i < script.P.Length - 1) { Handles.DrawLine(script.transform.position + Direction(script.P[i]), script.transform.position + Direction(script.P[i + 1])); } else { Handles.DrawLine(script.transform.position + Direction(script.P[i]), script.transform.position + Direction(script.P[0])); } Handles.color = Color.white; } // Deleting points if (deletePoint != -1) { DeletePoint(deletePoint); selectedPoint = -1; deletePoint = -1; } // Adding points if (addPoint != -1) { AddPoint(addPoint); addPoint = -1; } if (GUI.changed) { EditorUtility.SetDirty(script); } }
void OnSceneGUI() { if (!script.enabled) { return; } string message = string.Empty; if (!script.IsValid(ref message)) { return; } if (Application.isPlaying && !script.initiated) { return; } Color color = Color.cyan; color.a = script.weight; Handles.color = color; GUI.color = color; // Display the bones if (!Application.isPlaying) { for (int i = 0; i < script.fingers.Length; i++) { Handles.DrawLine(script.fingers[i].bone1.position, script.fingers[i].bone2.position); Inspector.SphereCap(0, script.fingers[i].bone1.position, Quaternion.identity, IKSolverInspector.GetHandleSize(script.fingers[i].bone1.position) * 0.5f); Inspector.SphereCap(0, script.fingers[i].bone2.position, Quaternion.identity, IKSolverInspector.GetHandleSize(script.fingers[i].bone2.position) * 0.5f); if (script.fingers[i].bone3 != null) { Handles.DrawLine(script.fingers[i].bone2.position, script.fingers[i].bone3.position); Handles.DrawLine(script.fingers[i].bone3.position, script.fingers[i].tip.position); Inspector.SphereCap(0, script.fingers[i].bone3.position, Quaternion.identity, IKSolverInspector.GetHandleSize(script.fingers[i].bone3.position) * 0.5f); } else { Handles.DrawLine(script.fingers[i].bone2.position, script.fingers[i].tip.position); } Inspector.SphereCap(0, script.fingers[i].tip.position, Quaternion.identity, IKSolverInspector.GetHandleSize(script.fingers[i].tip.position) * 0.5f); } } // Selecting solvers if (Application.isPlaying) { if (selected >= 0 && selected < script.fingers.Length) { if (script.fingers[selected].weight > 0f) { color.a = script.weight * script.fingers[selected].weight; Handles.color = color; float size = IKSolverInspector.GetHandleSize(script.fingers[selected].IKPosition); Inspector.CubeCap(0, script.fingers[selected].IKPosition, script.fingers[selected].IKRotation, size); if (script.fingers[selected].target == null) { switch (Tools.current) { case Tool.Move: script.fingers[selected].IKPosition = Handles.PositionHandle(script.fingers[selected].IKPosition, Tools.pivotRotation == PivotRotation.Local? script.fingers[selected].IKRotation: Quaternion.identity); break; case Tool.Rotate: script.fingers[selected].IKRotation = Handles.RotationHandle(script.fingers[selected].IKRotation, script.fingers[selected].IKPosition); break; } } } } for (int i = 0; i < script.fingers.Length; i++) { color.a = script.weight * script.fingers[i].weight; Handles.color = color; Handles.DrawLine(script.fingers[i].tip.position, script.fingers[i].IKPosition); if (script.fingers[i].weight > 0 && selected != i && script.fingers[i].initiated) { float size = IKSolverInspector.GetHandleSize(script.fingers[i].IKPosition) * 0.5f; if (Inspector.DotButton(script.fingers[i].IKPosition, Quaternion.identity, size, size)) { selected = i; } } } } Handles.color = Color.white; GUI.color = Color.white; }
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); Inspector.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 (Inspector.DotButton(center, Quaternion.identity, size * 0.5f, size * 0.5f)) { 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); Inspector.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 (Inspector.DotButton(center, Quaternion.identity, size * 0.5f, size * 0.5f)) { Undo.RecordObject(script, "Change RagdollEditor Selection"); script.selectedRigidbody = rigidbodies[i]; } } } } Handles.color = Color.white; }