// From: https://wiki.unity3d.com/index.php?title=CreateScriptableObjectAsset public static void CreateAsset(string path, List <Vector3> nodes) { ZestSplineSettings asset = AssetDatabase.LoadAssetAtPath(path.Replace(Application.dataPath, "Assets"), typeof(ZestSplineSettings)) as ZestSplineSettings; if (asset != null) { asset.Nodes = nodes; } else { asset = ScriptableObject.CreateInstance <ZestSplineSettings>(); asset.Nodes = nodes; AssetDatabase.CreateAsset(asset, path); } AssetDatabase.SaveAssets(); AssetDatabase.Refresh(); EditorUtility.FocusProjectWindow(); Selection.activeObject = asset; }
private void saveAsScriptableObject(string path) { ZestSplineSettings.CreateAsset(path, _target.nodes); }
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) { ZestSplineSettings asset = AssetDatabase.LoadAssetAtPath(path.Replace(Application.dataPath, "Assets"), typeof(ZestSplineSettings)) as ZestSplineSettings; 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(); } }