Example #1
0
 /// <summary>
 /// generates an arc from start to end with the arc axis perpendicular to start and end points
 /// </summary>
 /// <returns>The arc.</returns>
 /// <param name="start">Start.</param>
 /// <param name="end">End.</param>
 /// <param name="curvature">how far away from the line from start to end the arc extends</param>
 public static Spline GenerateArc(Vector3 start, Vector3 end, float curvature)
 {
     return(Spline.GenerateArc(start, end, curvature, Vector3.Cross(start, end)));
 }
Example #2
0
 /// <summary>
 /// generates an arc from start to end with the arc axis curvatureAxis
 /// </summary>
 /// <returns>The arc.</returns>
 /// <param name="start">Start.</param>
 /// <param name="end">End.</param>
 /// <param name="curvature">how far away from the line from start to end the arc extends</param>
 /// <param name="curvatureAxis">the axis which the arc should extend into</param>
 public static Spline GenerateArc(Vector3 start, Vector3 end, float curvature, Vector3 curvatureAxis)
 {
     curvatureAxis.Normalize();
     return(Spline.GenerateArc(start, end, curvature, curvatureAxis, curvatureAxis));
 }
Example #3
0
        public override void OnInspectorGUI()
        {
            showEditModeToggle();

            if (!_target.IsInEditMode)
            {
                DrawInstructions();
                return;
            }

            if (_target.UseBezier && _target.Nodes.Count < 4)
            {
                _target.UseBezier = false;
            }

            // what kind of handles shall we use?
            EditorGUILayout.BeginHorizontal();
            EditorGUILayout.PrefixLabel("Use Standard Handles");
            _target.UseStandardHandles = EditorGUILayout.Toggle(_target.UseStandardHandles);
            EditorGUILayout.EndHorizontal();

            // path name:
            EditorGUILayout.BeginHorizontal();
            EditorGUILayout.PrefixLabel("Route Name");
            _target.PathName = EditorGUILayout.TextField(_target.PathName);
            EditorGUILayout.EndHorizontal();

            if (_target.PathName == string.Empty)
            {
                _target.PathName = "route" + Random.Range(1, 100000);
            }

            // path color:
            EditorGUILayout.BeginHorizontal();
            EditorGUILayout.PrefixLabel("Route Color");
            _target.PathColor = EditorGUILayout.ColorField(_target.PathColor);
            EditorGUILayout.EndHorizontal();

            // force bezier:
            GUI.enabled = !_target.ForceStraightLinePath;
            EditorGUILayout.BeginHorizontal();
            EditorGUILayout.PrefixLabel("Use Bezier Path");
            EditorGUI.BeginChangeCheck();
            _target.UseBezier = EditorGUILayout.Toggle(_target.UseBezier);
            if (EditorGUI.EndChangeCheck() && _target.UseBezier)
            {
                // validate
                // make sure we have enough nodes to use a bezier.  nodeCount - 1 must be divisible by 3
                if (_target.Nodes.Count < 4)
                {
                    Debug.LogError("there must be at least 4 nodes to use a bezier");
                    _target.UseBezier = false;
                }
                else
                {
                    var excessNodes = (_target.Nodes.Count - 1) % 3;
                    if (excessNodes > 0)
                    {
                        _target.Nodes.RemoveRange(_target.Nodes.Count - excessNodes, excessNodes);
                        Debug.LogWarning("trimming " + excessNodes + " from the node list to make a proper bezier spline");
                    }
                }
            }
            EditorGUILayout.EndHorizontal();
            GUI.enabled = true;

            // force straight lines:
            GUI.enabled = !_target.UseBezier;
            EditorGUILayout.BeginHorizontal();
            EditorGUILayout.PrefixLabel("Force Straight Line Path");
            _target.ForceStraightLinePath = EditorGUILayout.Toggle(_target.ForceStraightLinePath);
            EditorGUILayout.EndHorizontal();
            GUI.enabled = true;

            // close path. only relevant for node counts greater than 5
            if (_target.Nodes.Count < 5)
            {
                GUI.enabled = false;
            }

            EditorGUILayout.BeginHorizontal();
            EditorGUILayout.PrefixLabel("Close Path");
            EditorGUI.BeginChangeCheck();
            _target.ClosePath = EditorGUILayout.Toggle(_target.ClosePath);
            if (EditorGUI.EndChangeCheck())
            {
                if (_target.ClosePath)
                {
                    closeRoute();
                }
            }
            EditorGUILayout.EndHorizontal();
            GUI.enabled = true;

            // resolution
            EditorGUILayout.BeginHorizontal();
            EditorGUILayout.PrefixLabel("Editor Drawing Resolution");
            _target.PathResolution = EditorGUILayout.IntSlider(_target.PathResolution, 2, 100);
            EditorGUILayout.EndHorizontal();

            EditorGUILayout.Separator();

            // insert node - we need 3 or more nodes for insert to make sense
            if (_target.Nodes.Count > 2)
            {
                EditorGUILayout.BeginHorizontal();

                GUI.enabled = _selectedNodeIndex != 0 && _selectedNodeIndex != -1;
                if (GUILayout.Button("Insert Node Before Selected"))
                {
                    insertNodeAtIndex(_selectedNodeIndex, false);
                }

                GUI.enabled = _selectedNodeIndex != _target.Nodes.Count - 1 && _selectedNodeIndex != -1;
                if (GUILayout.Button("Insert Node After Selected"))
                {
                    insertNodeAtIndex(_selectedNodeIndex, true);
                }

                GUI.enabled = true;

                EditorGUILayout.EndHorizontal();
            }

            // shift the start point to the origin
            if (GUILayout.Button("Shift Path to Start at Origin"))
            {
                Undo.RecordObject(_target, "Path Vector Changed");

                var offset = Vector3.zero;

                // see what kind of path we are. the simplest case is just a straight line
                var path = new Spline(_target.Nodes, _target.UseBezier, _target.ForceStraightLinePath);
                if (path.SplineType == SplineType.StraightLine || path.SplineType == SplineType.Bezier || _target.Nodes.Count < 5)
                {
                    offset = Vector3.zero - _target.Nodes[0];
                }
                else
                {
                    offset = Vector3.zero - _target.Nodes[1];
                }

                for (var i = 0; i < _target.Nodes.Count; i++)
                {
                    _target.Nodes[i] += offset;
                }

                GUI.changed = true;
            }

            // reverse
            if (GUILayout.Button("Reverse Path"))
            {
                Undo.RecordObject(_target, "Path Vector Changed");
                _target.Nodes.Reverse();
                GUI.changed = true;
            }

            // shifters. thse only make sense for straight line and catmull rom
            if (_target.ForceStraightLinePath || (_target.Nodes.Count > 4 && !_target.UseBezier))
            {
                GUILayout.BeginHorizontal();

                if (GUILayout.Button("Shift Nodes Left"))
                {
                    Undo.RecordObject(_target, "Path Vector Changed");

                    var firstItem = _target.Nodes[0];
                    _target.Nodes.RemoveAt(0);
                    _target.Nodes.Add(firstItem);

                    GUI.changed = true;
                }

                if (GUILayout.Button("Shift Nodes Right"))
                {
                    Undo.RecordObject(_target, "Path Vector Changed");

                    var lastItem = _target.Nodes[_target.Nodes.Count - 1];
                    _target.Nodes.RemoveAt(_target.Nodes.Count - 1);
                    _target.Nodes.Insert(0, lastItem);

                    GUI.changed = true;
                }

                GUILayout.EndHorizontal();
            }

            if (GUILayout.Button("Clear Path"))
            {
                Undo.RecordObject(_target, "Path Vector Changed");
                _target.Nodes.Clear();
                _target.Nodes.Add(_target.transform.position);
                _target.Nodes.Add(_target.transform.position + new Vector3(5f, 5f));

                GUI.changed = true;
            }

            if (GUILayout.Button("Move z-axis Values to 0"))
            {
                Undo.RecordObject(_target, "Path Vector Changed");

                for (var i = 0; i < _target.Nodes.Count; i++)
                {
                    _target.Nodes[i] = new Vector3(_target.Nodes[i].x, _target.Nodes[i].y, 0f);
                }

                GUI.changed = true;
            }

            // persist to disk
            EditorGUILayout.Space();
            EditorGUILayout.LabelField("Save to/Read from Disk");

            // Should we save it as a ScriptableObject instead?
            EditorGUILayout.Space();
            EditorGUILayout.BeginHorizontal();
            EditorGUILayout.PrefixLabel("Save As Scriptable Object");
            _saveAsScriptableObject = EditorGUILayout.Toggle(_saveAsScriptableObject);
            EditorGUILayout.EndHorizontal();

            EditorGUILayout.Space();
            EditorGUILayout.BeginHorizontal();
            EditorGUILayout.PrefixLabel("Serialize and Save Path");
            if (GUILayout.Button("Save"))
            {
                if (_saveAsScriptableObject)
                {
                    if (_saveAsScriptableObject)
                    {
                        var folderPath = EditorUtility.OpenFolderPanel("Save Folder", Application.dataPath, "");
                        if (folderPath != string.Empty)
                        {
                            saveAsScriptableObject(folderPath.Replace(Application.dataPath, "Assets") + "/" + _target.PathName + ".asset");
                        }
                    }
                }
                else
                {
                    var path = EditorUtility.SaveFilePanel("Save path", Application.dataPath + "/StreamingAssets", _target.PathName + ".asset", "asset");
                    if (path != string.Empty)
                    {
                        persistRouteToDisk(path);

                        // fetch the filename and set it as the routeName
                        _target.PathName = Path.GetFileName(path).Replace(".asset", string.Empty);
                    }
                }

                GUI.changed = true;
            }
            EditorGUILayout.EndHorizontal();

            EditorGUILayout.Space();
            EditorGUILayout.BeginHorizontal();
            EditorGUILayout.PrefixLabel("Load From Scriptable Object");
            _loadFromScriptableObject = EditorGUILayout.Toggle(_loadFromScriptableObject);
            EditorGUILayout.EndHorizontal();

            // load from disk
            EditorGUILayout.BeginHorizontal();
            EditorGUILayout.PrefixLabel("Load saved path");
            if (GUILayout.Button("Load"))
            {
                if (_loadFromScriptableObject)
                {
                    var path = EditorUtility.OpenFilePanel("Choose path to load", Path.Combine(Application.dataPath, "Asset"), "asset");
                    if (path != string.Empty)
                    {
                        MrTweenSplineSettings asset = AssetDatabase.LoadAssetAtPath(path.Replace(Application.dataPath, "Assets"), typeof(MrTweenSplineSettings)) as MrTweenSplineSettings;
                        if (asset != null)
                        {
                            _target.Nodes    = asset.Nodes;
                            _target.PathName = Path.GetFileName(path).Replace(".asset", string.Empty);
                        }
                        else
                        {
                            EditorUtility.DisplayDialog("Incorrect file selected", "File selected does not contain a valid path",
                                                        "Close");
                        }
                    }
                }
                else
                {
                    var path = EditorUtility.OpenFilePanel("Choose path to load",
                                                           Path.Combine(Application.dataPath, "StreamingAssets"), "asset");
                    if (path != string.Empty)
                    {
                        if (!File.Exists(path))
                        {
                            EditorUtility.DisplayDialog("File does not exist", "Path couldn't find the file you specified",
                                                        "Close");
                        }
                        else
                        {
                            _target.Nodes    = SplineAssetUtils.BytesToVector3List(File.ReadAllBytes(path));
                            _target.PathName = Path.GetFileName(path).Replace(".asset", string.Empty);
                        }
                    }
                    GUI.changed = true;
                }
            }
            EditorGUILayout.EndHorizontal();

            // node display
            EditorGUILayout.Space();
            _showNodeDetails = EditorGUILayout.Foldout(_showNodeDetails, "Show Node Values");
            if (_showNodeDetails)
            {
                EditorGUI.indentLevel++;
                for (int i = 0; i < _target.Nodes.Count; i++)
                {
                    _target.Nodes[i] = EditorGUILayout.Vector3Field("Node " + (i + 1), _target.Nodes[i]);
                }
                EditorGUI.indentLevel--;
            }

            DrawInstructions();

            // update and redraw:
            if (GUI.changed)
            {
                EditorUtility.SetDirty(_target);
                Repaint();
            }
        }