MaxValue() public static method

Return the largest element in a vector
public static MaxValue ( Vector2 v ) : float
v Vector2 /// A ///
return float
Example #1
0
    /*
     * Draw a ball at a part's location
     * */
    void DrawBall(BodyPart part, float scaleFactor)
    {
        if (part == null)
        {
            return;
        }

        Handles.SphereCap(0, part.bone.position, part.bone.rotation, _ballSize * VectorHelpers.MaxValue(part.bone.root.localScale));

        // draw a line to the parent part if it is defined
        Handles.color = linesColor;
        if (part.parentPart != null)
        {
            Handles.DrawLine(part.bone.position, part.parentPart.bone.position);
        }
    }
Example #2
0
    /*
     * Convert this part's shapeSize into the opposite part's space
     * */
    public void PasteShapeSizeToOpposite(bool applyScale)
    {
        Vector3 s = TransformPointToOpposite(shapeSize, applyScale);

        if (s.sqrMagnitude == 0f)
        {
            return;                               // early out if there is invalid scale
        }
        oppositePart.shapeSize = new Vector3(Mathf.Abs(s.x), Mathf.Abs(s.y), Mathf.Abs(s.z));
        if (oppositePart.shapeType == ShapeType.Sphere)
        {
            oppositePart.shapeSize = Vector3.one * VectorHelpers.MaxValue(oppositePart.shapeSize);
        }
        else if (oppositePart.shapeType == ShapeType.Capsule)
        {
            CapsuleDirection currentDirection = oppositePart.capsuleDirection;
            oppositePart.capsuleDirection = capsuleDirection;
            oppositePart.FlipCapsule(currentDirection);
        }
    }
Example #3
0
    /*
     * Draw custom viewport render
     * */
    void OnSceneGUI()
    {
        // only draw handles if array parts are not null, otherwise console spams crap when component is added while object is selected
        if (biped.spine != null && biped.spine.Length > 0)
        {
            // get the current scaleFactor
            Matrix4x4 matrix      = biped.transform.localToWorldMatrix;
            float     scaleFactor = Mathf.Sqrt(VectorHelpers.MaxValue(new Vector3(
                                                                          new Vector3(matrix.m00, matrix.m01, matrix.m02).sqrMagnitude,
                                                                          new Vector3(matrix.m10, matrix.m11, matrix.m12).sqrMagnitude,
                                                                          new Vector3(matrix.m20, matrix.m21, matrix.m22).sqrMagnitude)));

            // draw balls and lines for all defined parts
            Handles.color = ballsColor;
            foreach (BodyPart part in biped.allParts)
            {
                DrawBall(part, scaleFactor);
            }

            // draw a shape gizmo for each body part
            Handles.color = shapeColor;
            foreach (BodyPart part in biped.allParts)
            {
                BodyPartEditor.DrawShapeHandle(part, false);
            }

            // draw joint gizmos for all the body parts
            foreach (BodyPart part in biped.allParts)
            {
                BodyPartEditor.DrawJointHandle(part, false);
            }
        }

        // begin GUI or transform handles will be disabled
        Handles.BeginGUI();

        // create the viewport controls
        ViewportControls.BeginArea(BodyPartEditor.viewportControlsWidth, GUIAnchor.TopLeft);
        {
            // common controls for BodyParts (shape, center, joints)
            BodyPartEditor.ViewportCommonControls();
            // only update values if they change to prevent constant updating of player pref keys
            float fVal;
            GUILayout.BeginHorizontal();
            {
                GUILayout.Label(string.Format("Transform Display Size: {0:0.00}", ballSize), GUILayout.Width(BodyPartEditor.viewportControlsWidth * 0.65f));
                fVal = GUILayout.HorizontalSlider(ballSize, 0f, 1f);
                if (fVal != ballSize)
                {
                    ballSize = fVal;
                }
            }
            GUILayout.EndHorizontal();
            GUILayout.BeginHorizontal();
            {
                GUILayout.Label(string.Format("Body Mass: {0:0.00}", biped.mass), GUILayout.Width(BodyPartEditor.viewportControlsWidth * 0.65f));
                fVal = GUILayout.HorizontalSlider(biped.mass, 1f, 500f);
                if (fVal != biped.mass)
                {
                    biped.mass = fVal;
                    biped.DistributeMass();
                }
            }
            GUILayout.EndHorizontal();

            // if the editor is playing, then create testing controls
            if (Application.isPlaying)
            {
                // padding after previous controls
                GUILayout.Space(ViewportControls.viewportPadding * 2f);

                // only display ragdoll controls if minimum requirements have been met
                if (biped.ValidateMinimumRequirements())
                {
                    // if the biped is currently ragdoll, then create a button to remove the ragdoll
                    if (biped.isRagdoll)
                    {
                        if (GUILayout.Button("Remove Ragdoll"))
                        {
                            biped.RemoveRagdoll();
                        }
                    }
                    // otherwise create a button to turn the biped into a ragdoll
                    else
                    {
                        if (GUILayout.Button("Create Ragdoll"))
                        {
                            biped.CreateRagdoll(BodyPartEditor.jointResistance, 1f);
                        }
                    }

                    // only update an active ragdoll's spring value if the resistance slider changes
                    float oldResist = BodyPartEditor.jointResistance;
                    float oldForce  = BodyPartEditor.maxForce;
                    BodyPartEditor.ViewportResistanceSlider();
                    BodyPartEditor.ViewportMaxForceSlider();
                    if ((oldResist != BodyPartEditor.jointResistance || oldForce != BodyPartEditor.maxForce) && biped.isRagdoll)
                    {
                        JointDrive drive;
                        foreach (BodyPart part in biped.allParts)
                        {
                            if (part == null || part.joint == null)
                            {
                                continue;
                            }
                            drive = part.joint.slerpDrive;
                            drive.maximumForce    = BodyPartEditor.maxForce;
                            drive.positionSpring  = BodyPartEditor.jointResistance;
                            part.joint.slerpDrive = drive;
                        }
                    }

                    // if the biped is out of ragdoll, include a button to return to the snapshot
                    if (!biped.isRagdoll)
                    {
                        if (GUILayout.Button("Restore Pose to Snapshot"))
                        {
                            foreach (BodyPart part in biped.allParts)
                            {
                                if (part == null)
                                {
                                    continue;
                                }
                                part.ResetToInitialRotation();
                                part.ResetToPositionSnapshot();
                            }
                        }
                    }
                }
                else
                {
                    GUILayout.Label("Minimum biped definition not specified. Please stop the game and ensure that biped minimum requirements have been met.");
                }
            }
            // otherwise, create additional setup controls
            else
            {
                GUILayout.Label("Bone Naming Convention:");
                GUILayout.BeginVertical();
                {
                    namingConvention = (DCCApplication)GUILayout.SelectionGrid((int)namingConvention, System.Enum.GetNames(typeof(DCCApplication)), 2);
                    if (GUILayout.Button(string.Format("Set Up Biped Using {0} Names", namingConvention)))
                    {
                        biped.AutomateSetup(namingConvention);
                    }
                }
                GUILayout.EndVertical();
            }
        }
        ViewportControls.EndArea();

        // display symmetry status at the top of the viewport
        BodyPartEditor.ViewportStatus();

        // finish GUI
        Handles.EndGUI();
    }
    /*
     * Draw a collider gizmo for a specified part
     * */
    public static void DrawShapeHandle(BodyPart part, bool drawOpposite)
    {
        // early out if the part is null or the part has no shape
        if (part == null || part.shapeType == ShapeType.None || !part.isCollider)
        {
            return;
        }

        // store the current color
        Color oldColor = Handles.color;

        // set undo snapshot
        BodyPart[] parts = new BodyPart[1];
        if (isSymmetrical && part.oppositePart != null)
        {
            parts    = new BodyPart[2];
            parts[1] = part.oppositePart;
            parts[1].oppositePart = part;             // BUG: No idea why I need to do this
        }
        parts[0] = part;
        Undo.SetSnapshotTarget(parts, string.Format("Change Shape"));

        // create shape handles
        if (isShapeHandleEnabled)
        {
            // use radius if shape is capsule or sphere
            float radius = 0f;

            // compute the size to draw the shape handle based on the part's scale
            Vector3 shapeHandleSize = GetShapeHandleSize(part);

            // draw the correct handle based on shapeType
            switch (part.shapeType)
            {
            case ShapeType.Box:
                // create handles
                ShapeHandles.WireBox(ref shapeHandleSize, part.bone.TransformPoint(part.shapeCenter), part.bone.rotation, "");

                // apply the result
                DoShapeSizeThresholdTest(part, shapeHandleSize);

                // handle symmetry
                if (parts.Length > 1)
                {
                    part.PasteShapeSizeToOpposite(isScaleSymmetrical);
                    if (drawOpposite)
                    {
                        // get the opposite part's dimensions in case its local scale is different
                        shapeHandleSize = GetShapeHandleSize(parts[1]);

                        // ghost the opposite part
                        CustomHandleUtilities.SetHandleColor(oldColor, symmetryAlpha);
                        ShapeHandles.WireBox(ref shapeHandleSize, parts[1].bone.TransformPoint(parts[1].shapeCenter), parts[1].bone.rotation, "");

                        // apply the result
                        DoShapeSizeThresholdTest(parts[1], shapeHandleSize);
                        parts[1].PasteShapeSizeToOpposite(isScaleSymmetrical);
                    }
                }
                break;

            case ShapeType.Capsule:
                // get handle properties
                float      height             = 0f;
                Quaternion capsuleOrientation = Quaternion.identity;
                GetCapsuleProperties(part, ref height, ref radius, ref capsuleOrientation);

                // draw handle
                ShapeHandles.WireCapsule(ref radius, ref height, part.bone.TransformPoint(part.shapeCenter), part.bone.rotation * part.shapeRotation * capsuleOrientation, "");

                // apply result
                DoShapeSizeThresholdTest(part, CapsuleToSize(part, height, radius));

                // handle symmetry
                if (parts.Length > 1)
                {
                    part.PasteShapeSizeToOpposite(isScaleSymmetrical);
                    if (drawOpposite)
                    {
                        // get the opposite part's dimensions in case its local scale is different
                        GetCapsuleProperties(parts[1], ref height, ref radius, ref capsuleOrientation);

                        // ghost the opposite part
                        CustomHandleUtilities.SetHandleColor(oldColor, symmetryAlpha);
                        ShapeHandles.WireCapsule(ref radius, ref height, parts[1].bone.TransformPoint(parts[1].shapeCenter), parts[1].bone.rotation * parts[1].shapeRotation * capsuleOrientation, "");

                        // apply the result
                        DoShapeSizeThresholdTest(parts[1], CapsuleToSize(parts[1], height, radius));
                        parts[1].PasteShapeSizeToOpposite(isScaleSymmetrical);
                    }
                }
                break;

            case ShapeType.Sphere:
                // create a simple radius handle
                float oldRadius = Mathf.Max(
                    part.shapeSize.x * part.bone.lossyScale.x * 0.5f,
                    part.shapeSize.y * part.bone.lossyScale.y * 0.5f,
                    part.shapeSize.z * part.bone.lossyScale.z * 0.5f);
                radius = Handles.RadiusHandle(part.bone.rotation * part.shapeRotation, part.bone.TransformPoint(part.shapeCenter), oldRadius);
                if (Mathf.Abs(radius - oldRadius) > changeThreshold)
                {
                    float scaleFactor = 1f / VectorHelpers.MaxValue(part.bone.lossyScale);
                    part.shapeSize.x = 2f * radius * scaleFactor;
                    part.shapeSize.y = 2f * radius * scaleFactor;
                    part.shapeSize.z = 2f * radius * scaleFactor;
                    oldRadius        = radius;
                }

                // handle symmetry
                if (parts.Length > 1)
                {
                    part.PasteShapeSizeToOpposite(isScaleSymmetrical);
                    if (drawOpposite)
                    {
                        // ghost the opposite part
                        CustomHandleUtilities.SetHandleColor(oldColor, symmetryAlpha);
                        oldRadius = Mathf.Max(
                            parts[1].shapeSize.x * parts[1].bone.lossyScale.x * 0.5f,
                            parts[1].shapeSize.y * parts[1].bone.lossyScale.y * 0.5f,
                            parts[1].shapeSize.z * parts[1].bone.lossyScale.z * 0.5f);
                        radius = Handles.RadiusHandle(parts[1].bone.rotation * part.shapeRotation, parts[1].bone.TransformPoint(parts[1].shapeCenter), oldRadius);
                        if (Mathf.Abs(radius - oldRadius) > changeThreshold)
                        {
                            parts[1].shapeSize.x = 2f * radius;
                            parts[1].shapeSize.y = 2f * radius;
                            parts[1].shapeSize.z = 2f * radius;
                            parts[1].PasteShapeSizeToOpposite(isScaleSymmetrical);
                        }
                    }
                }
                break;
            }
        }

        // center handles
        if (isCenterHandleEnabled)
        {
            // position handle for the center
            Vector3 center = part.bone.InverseTransformPoint(Handles.PositionHandle(part.bone.TransformPoint(part.shapeCenter), part.bone.rotation * part.shapeRotation));

            // rotation handle
//			Quaternion rotation = Quaternion.Inverse(part.bone.rotation)*Handles.RotationHandle(part.bone.rotation*part.shapeRotation, part.bone.TransformPoint(part.shapeCenter));

            // handle symmetry
            if (parts.Length > 1)
            {
                center = part.TransformPointToOpposite(center, isScaleSymmetrical);
//				rotation = part.TransformRotationToOpposite(rotation);
                if (drawOpposite)
                {
                    center = parts[1].bone.InverseTransformPoint(Handles.PositionHandle(parts[1].bone.TransformPoint(center), parts[1].bone.rotation * part.shapeRotation));
//					rotation = Quaternion.Inverse(parts[1].bone.rotation)*Handles.RotationHandle(parts[1].bone.rotation*parts[1].shapeRotation, parts[1].bone.TransformPoint(parts[1].shapeCenter));
                }
                center = parts[1].TransformPointToOpposite(center, isScaleSymmetrical);
//				rotation = parts[1].TransformRotationToOpposite(rotation);
            }

            // apply results
            if ((part.shapeCenter - center).sqrMagnitude > changeThreshold * changeThreshold)
            {
                part.shapeCenter = center;
            }
//			if (Quaternion.Angle(part.shapeRotation, rotation)>changeThreshold) part.shapeRotation = rotation;
        }

        if (parts.Length > 1)
        {
            // update values
            parts[1].shapeType = part.shapeType;

            Vector3 oldValue = parts[1].shapeCenter;
            Vector3 newValue = part.TransformPointToOpposite(part.shapeCenter, isScaleSymmetrical);
            if ((oldValue - newValue).sqrMagnitude > changeThreshold * changeThreshold)
            {
                parts[1].shapeCenter = newValue;
            }

            oldValue = parts[1].shapeSize;
            part.PasteShapeSizeToOpposite(isScaleSymmetrical);
            if ((oldValue - parts[1].shapeSize).sqrMagnitude < changeThreshold * changeThreshold)
            {
                parts[1].shapeSize = oldValue;
            }

            // TODO: mirror rotation if/when collider rotation is implemented
        }

        CustomHandleUtilities.SetHandleColor(oldColor);

        foreach (BodyPart p in parts)
        {
            EditorUtility.SetDirty(p);
        }
    }