【a】可视化剧本编辑器 10.StoryEditor
This commit is contained in:
8
Assets/10.StoryEditor/Editor/Graph.meta
Normal file
8
Assets/10.StoryEditor/Editor/Graph.meta
Normal file
@@ -0,0 +1,8 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 7418c79b3f95ac9428a8836bccd4cb7a
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
193
Assets/10.StoryEditor/Editor/Graph/GraphCreateWindow.cs
Normal file
193
Assets/10.StoryEditor/Editor/Graph/GraphCreateWindow.cs
Normal file
@@ -0,0 +1,193 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using UnityEditor;
|
||||
using UnityEngine;
|
||||
// ReSharper disable Unity.PerformanceCriticalCodeInvocation
|
||||
|
||||
namespace Stary.Evo.StoryEditor.Editor
|
||||
{
|
||||
public class GraphCreateWindow : EditorWindow
|
||||
{
|
||||
private int _selectedIndex;
|
||||
private string _scriptName = "graph";
|
||||
private bool _showTip;
|
||||
private string _tip;
|
||||
|
||||
private string[] _options = Array.Empty<string>();
|
||||
private Dictionary<string, string> _paths = new();
|
||||
|
||||
[MenuItem("Evo/剧本编辑器/创建剧本")]
|
||||
private static void Open()
|
||||
{
|
||||
// 打开一个浮动窗口
|
||||
GetWindow<GraphCreateWindow>( "创建配置" ) ;
|
||||
}
|
||||
|
||||
private void OnEnable()
|
||||
{
|
||||
minSize = maxSize = new Vector2(300, 200);
|
||||
_options = GetPackages();
|
||||
}
|
||||
|
||||
private void OnGUI()
|
||||
{
|
||||
GUILayout.Space(15);
|
||||
EditorGUILayout.BeginHorizontal();
|
||||
GUILayout.Space(10);
|
||||
EditorGUILayout.BeginVertical();
|
||||
|
||||
// Package选项
|
||||
EditorGUILayout.LabelField( "请选择剧本所在的Package:" , EditorStyles.boldLabel ) ;
|
||||
var newIndex = EditorGUILayout.Popup( _selectedIndex , _options ) ;
|
||||
_selectedIndex = newIndex;
|
||||
|
||||
GUILayout.Space(15);
|
||||
|
||||
EditorGUILayout.LabelField( "请输入剧本名称" , EditorStyles.boldLabel ) ;
|
||||
var newName = EditorGUILayout.TextField(_scriptName);
|
||||
if (_scriptName != newName)
|
||||
{
|
||||
_scriptName = newName;
|
||||
_showTip = false;
|
||||
}
|
||||
|
||||
if (_showTip)
|
||||
{
|
||||
GUIStyle redBold = new GUIStyle(EditorStyles.boldLabel)
|
||||
{
|
||||
normal = { textColor = Color.red }
|
||||
};
|
||||
EditorGUILayout.LabelField(_tip, redBold) ;
|
||||
}
|
||||
|
||||
GUILayout.Space(15);
|
||||
|
||||
// 创建按钮
|
||||
if (GUILayout.Button("创建剧本"))
|
||||
{
|
||||
try
|
||||
{
|
||||
CreateScriptGraph(_options[newIndex]);
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
Debug.LogException(e);
|
||||
}
|
||||
}
|
||||
|
||||
EditorGUILayout.EndVertical();
|
||||
GUILayout.Space(10);
|
||||
EditorGUILayout.EndHorizontal();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 获取所有Module Package
|
||||
/// </summary>
|
||||
private string[] GetPackages()
|
||||
{
|
||||
// 查找Modules目录
|
||||
List<string> modules = new();
|
||||
GetDirectoryPaths(Application.dataPath, modules, "Modules");
|
||||
if (modules.Count == 0)
|
||||
{
|
||||
Debug.LogError("未找到任何Modules目录");
|
||||
return Array.Empty<string>();
|
||||
}
|
||||
|
||||
// 查找package
|
||||
List<string> packages = new();
|
||||
GetDirectoryPaths(modules[0], packages, "com.");
|
||||
if (packages.Count == 0)
|
||||
{
|
||||
Debug.LogError("未找到任何Package");
|
||||
return Array.Empty<string>();
|
||||
}
|
||||
|
||||
// 记录Package地址并返回选项
|
||||
_paths.Clear();
|
||||
packages.ForEach(path => _paths.Add(Path.GetFileName(path), path));
|
||||
return _paths.Keys.ToArray();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 获取符合条件的目录
|
||||
/// </summary>
|
||||
/// <param name="root">查找起始目录</param>
|
||||
/// <param name="result">查找结果</param>
|
||||
/// <param name="title">筛选条件(title)</param>
|
||||
/// <param name="tail">筛选条件(tail)</param>
|
||||
private static void GetDirectoryPaths(string root, List<string> result, string title = null, string tail = null)
|
||||
{
|
||||
foreach (var dir in Directory.GetDirectories(root))
|
||||
{
|
||||
// ReSharper disable once ReplaceWithSingleAssignment.True
|
||||
var check = true;
|
||||
|
||||
// 匹配文件头
|
||||
if (!string.IsNullOrEmpty(title) && !Path.GetFileName(dir).StartsWith(title))
|
||||
{
|
||||
check = false;
|
||||
}
|
||||
// 匹配文件尾
|
||||
if (!string.IsNullOrEmpty(tail) && !Path.GetFileName(dir).EndsWith(tail))
|
||||
{
|
||||
check = false;
|
||||
}
|
||||
|
||||
if(check)
|
||||
result.Add(dir.Replace('\\', '/'));
|
||||
|
||||
// 继续往下找
|
||||
GetDirectoryPaths(dir, result, title);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 创建剧本
|
||||
/// </summary>
|
||||
/// <param name="packageID">包体ID</param>
|
||||
private void CreateScriptGraph(string packageID)
|
||||
{
|
||||
// 检查剧本名称是否有效
|
||||
if (string.IsNullOrEmpty(_scriptName))
|
||||
{
|
||||
_tip = "剧本名称不能为空";
|
||||
_showTip = true;
|
||||
return;
|
||||
}
|
||||
|
||||
if (_paths.TryGetValue(packageID, out var path))
|
||||
{
|
||||
// 包体目录排空
|
||||
var graphDir = Path.Combine(path, "Main","Res","Graphs");
|
||||
if (!Directory.Exists(graphDir))
|
||||
Directory.CreateDirectory(graphDir);
|
||||
|
||||
// 检查资源存在性
|
||||
var graphPath = Path.Combine(graphDir, $"{_scriptName}.asset").Replace(Application.dataPath, "").Replace('\\', '/');
|
||||
graphPath = graphPath[1..];
|
||||
var graphFilePath = Path.Combine("Assets", graphPath);
|
||||
var existAsset = AssetDatabase.LoadAssetAtPath<ScriptGraph>(graphFilePath);
|
||||
if (existAsset)
|
||||
{
|
||||
_tip = "该名称的剧本已存在";
|
||||
_showTip = true;
|
||||
return;
|
||||
}
|
||||
|
||||
// 创建剧本图表
|
||||
var graph = CreateInstance<ScriptGraph>();
|
||||
graph.packageID = packageID;
|
||||
graph.graphPath = graphPath;
|
||||
|
||||
AssetDatabase.CreateAsset(graph, graphFilePath);
|
||||
}
|
||||
else
|
||||
{
|
||||
Debug.LogError($"未记录Package路径:{packageID}");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
11
Assets/10.StoryEditor/Editor/Graph/GraphCreateWindow.cs.meta
Normal file
11
Assets/10.StoryEditor/Editor/Graph/GraphCreateWindow.cs.meta
Normal file
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: f7ef12db2a2d4ab4d869971023fcd175
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
14
Assets/10.StoryEditor/Editor/Graph/ScriptGraphEditor.cs
Normal file
14
Assets/10.StoryEditor/Editor/Graph/ScriptGraphEditor.cs
Normal file
@@ -0,0 +1,14 @@
|
||||
using XNodeEditor;
|
||||
|
||||
namespace Stary.Evo.StoryEditor.Editor
|
||||
{
|
||||
[CustomNodeGraphEditor(typeof(ScriptGraph))]
|
||||
public class ScriptGraphEditor : NodeGraphEditor
|
||||
{
|
||||
public override void OnOpen()
|
||||
{
|
||||
base.OnOpen();
|
||||
NodeEditorWindow.current.panOffset = new(-350, -75);
|
||||
}
|
||||
}
|
||||
}
|
||||
11
Assets/10.StoryEditor/Editor/Graph/ScriptGraphEditor.cs.meta
Normal file
11
Assets/10.StoryEditor/Editor/Graph/ScriptGraphEditor.cs.meta
Normal file
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 0280f1b09f736a549a585dfe16f0b7da
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
8
Assets/10.StoryEditor/Editor/Node.meta
Normal file
8
Assets/10.StoryEditor/Editor/Node.meta
Normal file
@@ -0,0 +1,8 @@
|
||||
fileFormatVersion: 2
|
||||
guid: b06721b22b647a540a75c6f31a275c04
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
19
Assets/10.StoryEditor/Editor/Node/BeginNodeEditor.cs
Normal file
19
Assets/10.StoryEditor/Editor/Node/BeginNodeEditor.cs
Normal file
@@ -0,0 +1,19 @@
|
||||
using UnityEditor;
|
||||
using XNodeEditor;
|
||||
|
||||
namespace Stary.Evo.StoryEditor.Editor
|
||||
{
|
||||
[CustomNodeEditor(typeof(BeginNode))]
|
||||
public class BeginNodeEditor : NodeEditor
|
||||
{
|
||||
public override void OnBodyGUI()
|
||||
{
|
||||
serializedObject.Update();
|
||||
|
||||
EditorGUILayout.LabelField("剧本开始");
|
||||
base.OnBodyGUI();
|
||||
|
||||
serializedObject.ApplyModifiedProperties();
|
||||
}
|
||||
}
|
||||
}
|
||||
11
Assets/10.StoryEditor/Editor/Node/BeginNodeEditor.cs.meta
Normal file
11
Assets/10.StoryEditor/Editor/Node/BeginNodeEditor.cs.meta
Normal file
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 8ec8ed12f5fca194db8bf75ce458fb23
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
19
Assets/10.StoryEditor/Editor/Node/EndNodeEditor.cs
Normal file
19
Assets/10.StoryEditor/Editor/Node/EndNodeEditor.cs
Normal file
@@ -0,0 +1,19 @@
|
||||
using UnityEditor;
|
||||
using XNodeEditor;
|
||||
|
||||
namespace Stary.Evo.StoryEditor.Editor
|
||||
{
|
||||
[CustomNodeEditor(typeof(EndNode))]
|
||||
public class EndNodeEditor : NodeEditor
|
||||
{
|
||||
public override void OnBodyGUI()
|
||||
{
|
||||
serializedObject.Update();
|
||||
|
||||
EditorGUILayout.LabelField("剧本结束");
|
||||
base.OnBodyGUI();
|
||||
|
||||
serializedObject.ApplyModifiedProperties();
|
||||
}
|
||||
}
|
||||
}
|
||||
11
Assets/10.StoryEditor/Editor/Node/EndNodeEditor.cs.meta
Normal file
11
Assets/10.StoryEditor/Editor/Node/EndNodeEditor.cs.meta
Normal file
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 3651de4913e805c459198efe5e22e685
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
Reference in New Issue
Block a user