You cannot select more than 25 topics
			Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
		
		
		
		
		
			
		
			
	
	
		
			419 lines
		
	
	
		
			15 KiB
		
	
	
	
		
			C#
		
	
		
		
			
		
	
	
			419 lines
		
	
	
		
			15 KiB
		
	
	
	
		
			C#
		
	
| 
								 
											1 year ago
										 
									 | 
							
								using UnityEditor;
							 | 
						||
| 
								 | 
							
								using UnityEngine;
							 | 
						||
| 
								 | 
							
								using System.Collections;
							 | 
						||
| 
								 | 
							
								using System;
							 | 
						||
| 
								 | 
							
								using System.Reflection;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								namespace RootMotion.FinalIK
							 | 
						||
| 
								 | 
							
								{
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    /*
							 | 
						||
| 
								 | 
							
									 * Custom inspector for RotationLimitPolygonal
							 | 
						||
| 
								 | 
							
									 * */
							 | 
						||
| 
								 | 
							
								    [CustomEditor(typeof(RotationLimitPolygonal))]
							 | 
						||
| 
								 | 
							
								    [CanEditMultipleObjects]
							 | 
						||
| 
								 | 
							
								    public class RotationLimitPolygonalInspector : RotationLimitInspector
							 | 
						||
| 
								 | 
							
								    {
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								        /*
							 | 
						||
| 
								 | 
							
										 * Used for quick symmetric editing in the scene
							 | 
						||
| 
								 | 
							
										 * */
							 | 
						||
| 
								 | 
							
								        public enum Symmetry
							 | 
						||
| 
								 | 
							
								        {
							 | 
						||
| 
								 | 
							
								            Off,
							 | 
						||
| 
								 | 
							
								            X,
							 | 
						||
| 
								 | 
							
								            Y,
							 | 
						||
| 
								 | 
							
								            Z
							 | 
						||
| 
								 | 
							
								        }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								        private RotationLimitPolygonal script { get { return target as RotationLimitPolygonal; } }
							 | 
						||
| 
								 | 
							
								        private RotationLimitPolygonal clone;
							 | 
						||
| 
								 | 
							
								        private int selectedPoint = -1, deletePoint = -1, addPoint = -1;
							 | 
						||
| 
								 | 
							
								        private float degrees = 90;
							 | 
						||
| 
								 | 
							
								        private Symmetry symmetry;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								        #region Inspector
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								        public void OnEnable()
							 | 
						||
| 
								 | 
							
								        {
							 | 
						||
| 
								 | 
							
								            // If initialized, set up the default polygon
							 | 
						||
| 
								 | 
							
								            if (script.points == null || (script.points != null && script.points.Length < 3))
							 | 
						||
| 
								 | 
							
								            {
							 | 
						||
| 
								 | 
							
								                script.ResetToDefault();
							 | 
						||
| 
								 | 
							
								                EditorUtility.SetDirty(script);
							 | 
						||
| 
								 | 
							
								            }
							 | 
						||
| 
								 | 
							
								        }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								        public override void OnInspectorGUI()
							 | 
						||
| 
								 | 
							
								        {
							 | 
						||
| 
								 | 
							
								            GUI.changed = false;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								            // Clamping values
							 | 
						||
| 
								 | 
							
								            script.twistLimit = Mathf.Clamp(script.twistLimit, 0, 180);
							 | 
						||
| 
								 | 
							
								            script.smoothIterations = Mathf.Clamp(script.smoothIterations, 0, 3);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								            DrawDefaultInspector();
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								            if (GUI.changed) EditorUtility.SetDirty(script);
							 | 
						||
| 
								 | 
							
								        }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								        #endregion Inspector
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								        #region Scene
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								        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.defaultLocalRotationOverride) script.defaultLocalRotation = script.transform.localRotation;
							 | 
						||
| 
								 | 
							
								            if (script.axis == Vector3.zero) return;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								            // Quick Editing Tools
							 | 
						||
| 
								 | 
							
								            Handles.BeginGUI();
							 | 
						||
| 
								 | 
							
								            GUILayout.BeginArea(new Rect(10, 10, 550, 140), "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");
							 | 
						||
| 
								 | 
							
								                    GUILayout.BeginArea(new Rect(10, 160, 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);
							 | 
						||
| 
								 | 
							
								        }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								        private Color GetColor(int i)
							 | 
						||
| 
								 | 
							
								        {
							 | 
						||
| 
								 | 
							
								            // Paint the polygon in red if the reach cone is invalid
							 | 
						||
| 
								 | 
							
								            return script.reachCones[i].isValid ? colorDefault : colorInvalid;
							 | 
						||
| 
								 | 
							
								        }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								        /*
							 | 
						||
| 
								 | 
							
										 * Doubles the number of Limit Points
							 | 
						||
| 
								 | 
							
										 * */
							 | 
						||
| 
								 | 
							
								        private void Smooth()
							 | 
						||
| 
								 | 
							
								        {
							 | 
						||
| 
								 | 
							
								            int length = script.points.Length;
							 | 
						||
| 
								 | 
							
								            for (int i = 0; i < length; i++)
							 | 
						||
| 
								 | 
							
								            {
							 | 
						||
| 
								 | 
							
								                AddPoint(i + i);
							 | 
						||
| 
								 | 
							
								            }
							 | 
						||
| 
								 | 
							
								        }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								        /*
							 | 
						||
| 
								 | 
							
										 * Reduces the number of Limit Points
							 | 
						||
| 
								 | 
							
										 * */
							 | 
						||
| 
								 | 
							
								        private void Optimize()
							 | 
						||
| 
								 | 
							
								        {
							 | 
						||
| 
								 | 
							
								            for (int i = 1; i < script.points.Length; i++)
							 | 
						||
| 
								 | 
							
								            {
							 | 
						||
| 
								 | 
							
								                if (script.points.Length > 3) DeletePoint(i);
							 | 
						||
| 
								 | 
							
								            }
							 | 
						||
| 
								 | 
							
								        }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								        /*
							 | 
						||
| 
								 | 
							
										 * Flips the rotation limit along the axis
							 | 
						||
| 
								 | 
							
										 * */
							 | 
						||
| 
								 | 
							
								        private void FlipLimit(int axis)
							 | 
						||
| 
								 | 
							
								        {
							 | 
						||
| 
								 | 
							
								            script.axis[axis] = -script.axis[axis];
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								            foreach (RotationLimitPolygonal.LimitPoint limitPoint in script.points) limitPoint.point[axis] = -limitPoint.point[axis];
							 | 
						||
| 
								 | 
							
								            Array.Reverse(script.points);
							 | 
						||
| 
								 | 
							
								            script.BuildReachCones();
							 | 
						||
| 
								 | 
							
								        }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								        private void RotatePoints(float degrees, Vector3 axis)
							 | 
						||
| 
								 | 
							
								        {
							 | 
						||
| 
								 | 
							
								            foreach (RotationLimitPolygonal.LimitPoint limitPoint in script.points) limitPoint.point = Quaternion.AngleAxis(degrees, axis) * limitPoint.point;
							 | 
						||
| 
								 | 
							
								            script.BuildReachCones();
							 | 
						||
| 
								 | 
							
								        }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								        /*
							 | 
						||
| 
								 | 
							
										 * Converting directions from local space to world space
							 | 
						||
| 
								 | 
							
										 * */
							 | 
						||
| 
								 | 
							
								        private Vector3 Direction(Vector3 v)
							 | 
						||
| 
								 | 
							
								        {
							 | 
						||
| 
								 | 
							
								            if (script.transform.parent == null) return script.defaultLocalRotation * v;
							 | 
						||
| 
								 | 
							
								            return script.transform.parent.rotation * (script.defaultLocalRotation * v);
							 | 
						||
| 
								 | 
							
								        }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								        /*
							 | 
						||
| 
								 | 
							
										 * Inverse of Direction(Vector3 v)
							 | 
						||
| 
								 | 
							
										 * */
							 | 
						||
| 
								 | 
							
								        private Vector3 InverseDirection(Vector3 v)
							 | 
						||
| 
								 | 
							
								        {
							 | 
						||
| 
								 | 
							
								            if (script.transform.parent == null) return Quaternion.Inverse(script.defaultLocalRotation) * v;
							 | 
						||
| 
								 | 
							
								            return Quaternion.Inverse(script.defaultLocalRotation) * Quaternion.Inverse(script.transform.parent.rotation) * v;
							 | 
						||
| 
								 | 
							
								        }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								        /*
							 | 
						||
| 
								 | 
							
										 * Removing Limit Points
							 | 
						||
| 
								 | 
							
										 * */
							 | 
						||
| 
								 | 
							
								        private void DeletePoint(int p)
							 | 
						||
| 
								 | 
							
								        {
							 | 
						||
| 
								 | 
							
								            RotationLimitPolygonal.LimitPoint[] newPoints = new RotationLimitPolygonal.LimitPoint[0];
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								            for (int i = 0; i < script.points.Length; i++)
							 | 
						||
| 
								 | 
							
								            {
							 | 
						||
| 
								 | 
							
								                if (i != p)
							 | 
						||
| 
								 | 
							
								                {
							 | 
						||
| 
								 | 
							
								                    Array.Resize(ref newPoints, newPoints.Length + 1);
							 | 
						||
| 
								 | 
							
								                    newPoints[newPoints.Length - 1] = script.points[i];
							 | 
						||
| 
								 | 
							
								                }
							 | 
						||
| 
								 | 
							
								            }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								            script.points = newPoints;
							 | 
						||
| 
								 | 
							
								            script.BuildReachCones();
							 | 
						||
| 
								 | 
							
								        }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								        /*
							 | 
						||
| 
								 | 
							
										 * Creating new Limit Points
							 | 
						||
| 
								 | 
							
										 * */
							 | 
						||
| 
								 | 
							
								        private void AddPoint(int p)
							 | 
						||
| 
								 | 
							
								        {
							 | 
						||
| 
								 | 
							
								            RotationLimitPolygonal.LimitPoint[] newPoints = new RotationLimitPolygonal.LimitPoint[script.points.Length + 1];
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								            for (int i = 0; i < p + 1; i++) newPoints[i] = script.points[i];
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								            newPoints[p + 1] = new RotationLimitPolygonal.LimitPoint();
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								            Vector3 nextPoint = Vector3.forward;
							 | 
						||
| 
								 | 
							
								            if (p < script.points.Length - 1) nextPoint = script.points[p + 1].point;
							 | 
						||
| 
								 | 
							
								            else nextPoint = script.points[0].point;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								            newPoints[p + 1].point = Vector3.Lerp(script.points[p].point, nextPoint, 0.5f);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								            for (int i = p + 2; i < newPoints.Length; i++) newPoints[i] = script.points[i - 1];
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								            script.points = newPoints;
							 | 
						||
| 
								 | 
							
								            script.BuildReachCones();
							 | 
						||
| 
								 | 
							
								        }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								        /*
							 | 
						||
| 
								 | 
							
										 * Clone properties from another RotationLimitPolygonal
							 | 
						||
| 
								 | 
							
										 * */
							 | 
						||
| 
								 | 
							
								        private void CloneLimit()
							 | 
						||
| 
								 | 
							
								        {
							 | 
						||
| 
								 | 
							
								            if (clone == null) return;
							 | 
						||
| 
								 | 
							
								            if (clone == script)
							 | 
						||
| 
								 | 
							
								            {
							 | 
						||
| 
								 | 
							
								                script.LogWarning("Can't clone from self.");
							 | 
						||
| 
								 | 
							
								                return;
							 | 
						||
| 
								 | 
							
								            }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								            script.axis = clone.axis;
							 | 
						||
| 
								 | 
							
								            script.twistLimit = clone.twistLimit;
							 | 
						||
| 
								 | 
							
								            script.smoothIterations = clone.smoothIterations;
							 | 
						||
| 
								 | 
							
								            script.points = new RotationLimitPolygonal.LimitPoint[clone.points.Length];
							 | 
						||
| 
								 | 
							
								            for (int i = 0; i < script.points.Length; i++)
							 | 
						||
| 
								 | 
							
								            {
							 | 
						||
| 
								 | 
							
								                script.points[i] = (RotationLimitPolygonal.LimitPoint)CloneObject(clone.points[i]);
							 | 
						||
| 
								 | 
							
								            }
							 | 
						||
| 
								 | 
							
								            script.BuildReachCones();
							 | 
						||
| 
								 | 
							
								        }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								        private static object CloneObject(object o)
							 | 
						||
| 
								 | 
							
								        {
							 | 
						||
| 
								 | 
							
								            Type t = o.GetType();
							 | 
						||
| 
								 | 
							
								            object clone = Activator.CreateInstance(t);
							 | 
						||
| 
								 | 
							
								            foreach (FieldInfo fi in t.GetFields())
							 | 
						||
| 
								 | 
							
								            {
							 | 
						||
| 
								 | 
							
								                fi.SetValue(clone, fi.GetValue(o));
							 | 
						||
| 
								 | 
							
								            }
							 | 
						||
| 
								 | 
							
								            return clone;
							 | 
						||
| 
								 | 
							
								        }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								        /*
							 | 
						||
| 
								 | 
							
										 * Flipping vectors for symmetry
							 | 
						||
| 
								 | 
							
										 * */
							 | 
						||
| 
								 | 
							
								        private static Vector3 Symmetrize(Vector3 v, Symmetry symmetry)
							 | 
						||
| 
								 | 
							
								        {
							 | 
						||
| 
								 | 
							
								            switch (symmetry)
							 | 
						||
| 
								 | 
							
								            {
							 | 
						||
| 
								 | 
							
								                case Symmetry.X: return new Vector3(-v.x, v.y, v.z);
							 | 
						||
| 
								 | 
							
								                case Symmetry.Y: return new Vector3(v.x, -v.y, v.z);
							 | 
						||
| 
								 | 
							
								                case Symmetry.Z: return new Vector3(v.x, v.y, -v.z);
							 | 
						||
| 
								 | 
							
								                default: return v;
							 | 
						||
| 
								 | 
							
								            }
							 | 
						||
| 
								 | 
							
								        }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								        /*
							 | 
						||
| 
								 | 
							
										 * Returns closest point to a position. Used for symmetric editing
							 | 
						||
| 
								 | 
							
										 * */
							 | 
						||
| 
								 | 
							
								        private RotationLimitPolygonal.LimitPoint GetClosestPoint(Vector3 v)
							 | 
						||
| 
								 | 
							
								        {
							 | 
						||
| 
								 | 
							
								            float closestDistace = Mathf.Infinity;
							 | 
						||
| 
								 | 
							
								            RotationLimitPolygonal.LimitPoint closestPoint = null;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								            foreach (RotationLimitPolygonal.LimitPoint limitPoint in script.points)
							 | 
						||
| 
								 | 
							
								            {
							 | 
						||
| 
								 | 
							
								                if (limitPoint.point == v) return limitPoint;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								                float d = Vector3.Distance(limitPoint.point, v);
							 | 
						||
| 
								 | 
							
								                if (d < closestDistace)
							 | 
						||
| 
								 | 
							
								                {
							 | 
						||
| 
								 | 
							
								                    closestPoint = limitPoint;
							 | 
						||
| 
								 | 
							
								                    closestDistace = d;
							 | 
						||
| 
								 | 
							
								                }
							 | 
						||
| 
								 | 
							
								            }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								            return closestPoint;
							 | 
						||
| 
								 | 
							
								        }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								        #endregion Scene
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								}
							 |