Files
aibis-dream/Assets/Editor/Window/JsonEditWindow.cs
T

1049 lines
39 KiB
C#
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using AibisDream.Editor;
using AibisDream.Utility;
using Newtonsoft.Json.Linq;
using UnityEditor;
using UnityEngine;
namespace AibisDream.SystemEditor
{
public class JsonEditWindow : EditorWindow
{
// === 布局变量(可调整) ===
private float _fileListWidth = 220f;
private float _keyListWidth = 180f;
private bool _isDraggingFileSplitter = false;
private bool _isDraggingKeySplitter = false;
// === 核心数据 ===
private string _rootPath = "Assets/StreamingAssets";
private List<string> _jsonFileList = new List<string>();
private string _selectedFile;
private JObject _jsonData;
private JArray _jsonArray; // Array格式的JSON数据
private bool _isArrayFormat = false; // 标识当前是否为Array格式
private List<string> _firstLevelKeys = new List<string>();
private string _selectedKey;
private bool _editModeTree = true; // true=树形编辑, false=文本编辑
// === 状态 ===
private Vector2 _scrollPosFiles;
private Vector2 _scrollPosKeys;
private Vector2 _scrollPosEditor;
private string _searchString = "";
private string _newFileName = "";
private string _jsonTextContent = "";
private string _validationError = "";
private Dictionary<string, float> _keyPositions = new Dictionary<string, float>();
private Dictionary<string, bool> _expandedNodes = new Dictionary<string, bool>();
private bool _showDeleteButton = false; // 是否显示JSON编辑器中的删除按钮(默认隐藏)
[MenuItem(AibisEditorMenus.JsonEditor)]
public static void ShowWindow()
{
GetWindow<JsonEditWindow>("JSON Editor");
}
private void OnEnable()
{
_rootPath = EditorPrefs.GetString("JsonEditWindow_RootPath", "Assets/StreamingAssets");
_selectedFile = EditorPrefs.GetString("JsonEditWindow_SelectedFile", "");
_showDeleteButton = EditorPrefs.GetBool("JsonEditWindow_ShowDeleteButton", false);
_fileListWidth = EditorPrefs.GetFloat("JsonEditWindow_FileListWidth", 220f);
_keyListWidth = EditorPrefs.GetFloat("JsonEditWindow_KeyListWidth", 180f);
RefreshFileList();
if (!string.IsNullOrEmpty(_selectedFile) && File.Exists(_selectedFile))
{
LoadJsonFile(_selectedFile);
}
}
private void OnDisable()
{
EditorPrefs.SetString("JsonEditWindow_RootPath", _rootPath);
EditorPrefs.SetString("JsonEditWindow_SelectedFile", _selectedFile ?? "");
EditorPrefs.SetBool("JsonEditWindow_ShowDeleteButton", _showDeleteButton);
EditorPrefs.SetFloat("JsonEditWindow_FileListWidth", _fileListWidth);
EditorPrefs.SetFloat("JsonEditWindow_KeyListWidth", _keyListWidth);
}
private void OnGUI()
{
DrawTopBar();
EditorGUILayout.BeginHorizontal();
{
DrawFileList();
DrawSplitter(ref _fileListWidth, ref _isDraggingFileSplitter);
DrawKeyList();
DrawSplitter(ref _keyListWidth, ref _isDraggingKeySplitter);
DrawEditor();
}
EditorGUILayout.EndHorizontal();
}
// ------------------------------------------------------------------------
// UI 绘制函数
// ------------------------------------------------------------------------
private void DrawTopBar()
{
EditorGUILayout.BeginHorizontal("box", GUILayout.Height(30));
{
GUILayout.Label("资源路径:", GUILayout.Width(60));
_rootPath = EditorGUILayout.TextField(_rootPath, GUILayout.Width(200));
if (GUILayout.Button("...", EditorStyles.miniButton, GUILayout.Width(25)))
{
string path = EditorUtility.OpenFolderPanel("选择根目录", Application.dataPath, "");
if (!string.IsNullOrEmpty(path) && path.StartsWith(Application.dataPath))
{
_rootPath = "Assets" + path.Substring(Application.dataPath.Length);
RefreshFileList();
}
}
GUILayout.Space(20);
if (GUILayout.Button("刷新", EditorStyles.toolbarButton, GUILayout.Width(60)))
{
AssetDatabase.Refresh();
RefreshFileList();
}
if (GUILayout.Button("验证", EditorStyles.toolbarButton, GUILayout.Width(60)))
{
ValidateJson();
}
if (GUILayout.Button("格式化", EditorStyles.toolbarButton, GUILayout.Width(60)))
{
FormatJson();
}
if (!string.IsNullOrEmpty(_validationError))
{
GUI.color = Color.red;
GUILayout.Label(_validationError, EditorStyles.miniLabel);
GUI.color = Color.white;
}
GUILayout.FlexibleSpace();
}
EditorGUILayout.EndHorizontal();
}
private void DrawSplitter(ref float width, ref bool isDragging)
{
Rect rect = GUILayoutUtility.GetRect(5f, EditorGUIUtility.singleLineHeight, GUILayout.Width(5f), GUILayout.ExpandHeight(true));
// 绘制分割条
Color splitterColor = EditorGUIUtility.isProSkin ? new Color(0.3f, 0.3f, 0.3f) : new Color(0.6f, 0.6f, 0.6f);
EditorGUI.DrawRect(rect, splitterColor);
// 检测鼠标事件
Event e = Event.current;
int controlID = GUIUtility.GetControlID(FocusType.Passive);
switch (e.type)
{
case EventType.MouseDown:
if (rect.Contains(e.mousePosition))
{
isDragging = true;
GUIUtility.hotControl = controlID;
e.Use();
}
break;
case EventType.MouseDrag:
if (isDragging && GUIUtility.hotControl == controlID)
{
float delta = e.delta.x;
width = Mathf.Clamp(width + delta, 100f, 500f);
e.Use();
Repaint();
}
break;
case EventType.MouseUp:
if (isDragging)
{
isDragging = false;
GUIUtility.hotControl = 0;
e.Use();
}
break;
}
// 改变鼠标光标
if (rect.Contains(e.mousePosition) || isDragging)
{
EditorGUIUtility.AddCursorRect(rect, MouseCursor.ResizeHorizontal);
}
}
private void DrawFileList()
{
EditorGUILayout.BeginVertical("box", GUILayout.Width(_fileListWidth), GUILayout.ExpandHeight(true));
GUILayout.Label("文件列表", EditorStyles.boldLabel);
GUILayout.Space(5);
EditorGUILayout.BeginHorizontal();
{
GUILayout.Label("搜索:", GUILayout.Width(40));
string newSearch = EditorGUILayout.TextField(_searchString, EditorStyles.toolbarSearchField);
if (newSearch != _searchString)
{
_searchString = newSearch;
RefreshFileList();
}
}
EditorGUILayout.EndHorizontal();
GUILayout.Space(5);
EditorGUILayout.BeginHorizontal();
{
GUILayout.Label("新文件:", GUILayout.Width(50));
_newFileName = EditorGUILayout.TextField(_newFileName, GUILayout.Width(100));
if (GUILayout.Button("创建", EditorStyles.miniButton, GUILayout.Width(50)))
{
CreateJsonFile();
}
}
EditorGUILayout.EndHorizontal();
GUILayout.Space(5);
_scrollPosFiles = EditorGUILayout.BeginScrollView(_scrollPosFiles);
if (_jsonFileList != null && _jsonFileList.Count > 0)
{
foreach (var filePath in _jsonFileList)
{
if (filePath == null) continue;
string fileName = Path.GetFileName(filePath);
bool isSelected = _selectedFile == filePath;
EditorGUILayout.BeginHorizontal("box");
{
if (isSelected) GUI.backgroundColor = new Color(0.6f, 0.8f, 1f);
if (GUILayout.Button(fileName, EditorStyles.label, GUILayout.Height(22)))
{
SelectFile(filePath);
}
GUI.backgroundColor = Color.white;
// 定位按钮
if (GUILayout.Button(EditorGUIUtility.IconContent("d_ViewToolOrbit"), EditorStyles.iconButton, GUILayout.Width(22)))
{
string assetPath = filePath.Replace(Application.dataPath, "Assets").Replace("\\", "/");
var asset = AssetDatabase.LoadAssetAtPath<UnityEngine.Object>(assetPath);
if (asset != null)
EditorGUIUtility.PingObject(asset);
}
// 删除按钮
if (GUILayout.Button(EditorGUIUtility.IconContent("TreeEditor.Trash"), EditorStyles.iconButton, GUILayout.Width(22)))
{
if (EditorUtility.DisplayDialog("删除确认", $"确定删除 {fileName} 吗?", "删除", "取消"))
{
DeleteFile(filePath);
GUIUtility.ExitGUI();
}
}
}
EditorGUILayout.EndHorizontal();
}
}
else
{
GUILayout.Label("没有找到JSON文件", EditorStyles.centeredGreyMiniLabel);
}
EditorGUILayout.EndScrollView();
EditorGUILayout.EndVertical();
}
private void DrawKeyList()
{
EditorGUILayout.BeginVertical("box", GUILayout.Width(_keyListWidth), GUILayout.ExpandHeight(true));
GUILayout.Label("第一层Key", EditorStyles.boldLabel);
GUILayout.Space(5);
_scrollPosKeys = EditorGUILayout.BeginScrollView(_scrollPosKeys);
if (_isArrayFormat)
{
// Array格式,Key栏置空
GUILayout.FlexibleSpace();
GUILayout.Label("Array格式\n无Key列表", EditorStyles.centeredGreyMiniLabel);
GUILayout.FlexibleSpace();
}
else if (_jsonData != null && _firstLevelKeys != null && _firstLevelKeys.Count > 0)
{
foreach (var key in _firstLevelKeys)
{
bool isSelected = (_selectedKey == key);
if (isSelected) GUI.backgroundColor = new Color(0.6f, 0.8f, 1f);
string displayText = key;
if (_jsonData[key] != null)
{
JToken token = _jsonData[key];
if (token.Type == JTokenType.Object)
displayText = $"{{}} {key}";
else if (token.Type == JTokenType.Array)
displayText = $"[] {key}";
else
displayText = $"{GetValueTypeIcon(token)} {key}";
}
if (GUILayout.Button(displayText, EditorStyles.miniButton, GUILayout.Height(24)))
{
SelectKey(key);
}
GUI.backgroundColor = Color.white;
}
}
else
{
GUILayout.Label("<< 请选择文件", EditorStyles.centeredGreyMiniLabel);
}
EditorGUILayout.EndScrollView();
EditorGUILayout.EndVertical();
}
private void DrawEditor()
{
EditorGUILayout.BeginVertical("box", GUILayout.ExpandWidth(true), GUILayout.ExpandHeight(true));
if (_jsonData != null || _jsonArray != null)
{
EditorGUILayout.BeginHorizontal();
{
GUILayout.Label("JSON编辑器", EditorStyles.boldLabel);
if (_isArrayFormat)
{
GUI.color = new Color(0.6f, 0.8f, 1f);
GUILayout.Label("Array格式", EditorStyles.miniLabel);
GUI.color = Color.white;
}
else if (!string.IsNullOrEmpty(_selectedKey))
{
GUI.color = new Color(0.6f, 0.8f, 1f);
GUILayout.Label($"当前Key: {_selectedKey}", EditorStyles.miniLabel);
GUI.color = Color.white;
if (GUILayout.Button("显示全部", EditorStyles.miniButton, GUILayout.Width(70)))
{
_selectedKey = null;
}
}
GUILayout.FlexibleSpace();
_showDeleteButton = GUILayout.Toggle(_showDeleteButton, "显示删除", EditorStyles.toolbarButton, GUILayout.Width(70));
_editModeTree = GUILayout.Toggle(_editModeTree, "树形编辑", EditorStyles.toolbarButton);
_editModeTree = !GUILayout.Toggle(!_editModeTree, "文本编辑", EditorStyles.toolbarButton);
}
EditorGUILayout.EndHorizontal();
GUILayout.Space(5);
EditorGUILayout.BeginHorizontal();
{
EditorGUI.BeginDisabledGroup(string.IsNullOrEmpty(_selectedFile));
if (GUILayout.Button("保存", EditorStyles.miniButton, GUILayout.Width(60)))
{
SaveJsonFile();
}
EditorGUI.EndDisabledGroup();
EditorGUI.BeginDisabledGroup(string.IsNullOrEmpty(_selectedFile));
if (GUILayout.Button("重新加载", EditorStyles.miniButton, GUILayout.Width(70)))
{
if (!string.IsNullOrEmpty(_selectedFile))
LoadJsonFile(_selectedFile);
}
EditorGUI.EndDisabledGroup();
GUILayout.FlexibleSpace();
if (!string.IsNullOrEmpty(_validationError))
{
GUI.color = Color.red;
GUILayout.Label(_validationError, EditorStyles.miniLabel);
GUI.color = Color.white;
}
}
EditorGUILayout.EndHorizontal();
GUILayout.Space(5);
_scrollPosEditor = EditorGUILayout.BeginScrollView(_scrollPosEditor);
if (_editModeTree)
{
if (_isArrayFormat)
{
DrawArrayTreeEditor();
}
else
{
DrawTreeEditor();
}
}
else
{
DrawTextEditor();
}
EditorGUILayout.EndScrollView();
}
else
{
GUILayout.FlexibleSpace();
GUILayout.Label("<< 请选择JSON文件", EditorStyles.centeredGreyMiniLabel);
GUILayout.FlexibleSpace();
}
EditorGUILayout.EndVertical();
}
private void DrawTreeEditor()
{
if (_jsonData == null) return;
_keyPositions.Clear();
// 如果选中了Key,只显示该Key对应的部分
if (!string.IsNullOrEmpty(_selectedKey) && _jsonData[_selectedKey] != null)
{
JToken selectedToken = _jsonData[_selectedKey];
DrawJToken(selectedToken, _selectedKey, 0, _selectedKey);
}
else
{
// 显示完整的JSON
foreach (var prop in _jsonData.Properties())
{
DrawJToken(prop.Value, prop.Name, 0, prop.Name);
}
}
}
private void DrawArrayTreeEditor()
{
if (_jsonArray == null) return;
EditorGUILayout.BeginHorizontal();
{
GUILayout.Space(15);
if (GUILayout.Button("+ 添加元素", EditorStyles.miniButton, GUILayout.Width(100)))
{
_jsonArray.Add("");
}
}
EditorGUILayout.EndHorizontal();
GUILayout.Space(5);
var indicesToRemove = new List<int>();
for (int i = 0; i < _jsonArray.Count; i++)
{
if (_showDeleteButton)
{
EditorGUILayout.BeginHorizontal();
GUILayout.Space(15);
if (GUILayout.Button("×", EditorStyles.miniButton, GUILayout.Width(20)))
{
indicesToRemove.Add(i);
}
EditorGUILayout.EndHorizontal();
}
DrawJToken(_jsonArray[i], $"[{i}]", 0, $"[{i}]");
}
// 删除元素(从后往前删除,避免索引问题)
for (int i = indicesToRemove.Count - 1; i >= 0; i--)
{
_jsonArray.RemoveAt(indicesToRemove[i]);
}
}
private void DrawJToken(JToken token, string key, int indent, string path = "")
{
if (token == null) return;
string nodePath = string.IsNullOrEmpty(path) ? key : $"{path}.{key}";
float startY = GUILayoutUtility.GetRect(0, 0).y;
EditorGUILayout.BeginHorizontal();
GUILayout.Space(indent * 15);
if (token.Type == JTokenType.Object)
{
JObject obj = (JObject)token;
if (!_expandedNodes.ContainsKey(nodePath))
_expandedNodes[nodePath] = true;
bool expanded = _expandedNodes[nodePath];
expanded = EditorGUILayout.Foldout(expanded, $"{key}: {{}} ({obj.Count})", true);
_expandedNodes[nodePath] = expanded;
if (GUILayout.Button("+", EditorStyles.miniButtonLeft, GUILayout.Width(20)))
{
string newKey = "newKey";
obj[newKey] = "";
}
EditorGUILayout.EndHorizontal();
if (expanded)
{
var propsToRemove = new List<string>();
foreach (var prop in obj.Properties().ToList())
{
if (_showDeleteButton)
{
EditorGUILayout.BeginHorizontal();
GUILayout.Space(15);
if (GUILayout.Button("×", EditorStyles.miniButton, GUILayout.Width(20)))
{
propsToRemove.Add(prop.Name);
}
EditorGUILayout.EndHorizontal();
}
DrawJToken(prop.Value, prop.Name, indent + 1, nodePath);
}
foreach (var keyToRemove in propsToRemove)
{
obj.Remove(keyToRemove);
}
}
}
else if (token.Type == JTokenType.Array)
{
JArray arr = (JArray)token;
if (!_expandedNodes.ContainsKey(nodePath))
_expandedNodes[nodePath] = true;
bool expanded = _expandedNodes[nodePath];
expanded = EditorGUILayout.Foldout(expanded, $"{key}: [{arr.Count}]", true);
_expandedNodes[nodePath] = expanded;
if (GUILayout.Button("+", EditorStyles.miniButtonLeft, GUILayout.Width(20)))
{
arr.Add("");
}
EditorGUILayout.EndHorizontal();
if (expanded)
{
var indicesToRemove = new List<int>();
for (int i = 0; i < arr.Count; i++)
{
if (_showDeleteButton)
{
EditorGUILayout.BeginHorizontal();
GUILayout.Space(15);
if (GUILayout.Button("×", EditorStyles.miniButton, GUILayout.Width(20)))
{
indicesToRemove.Add(i);
}
EditorGUILayout.EndHorizontal();
}
DrawJToken(arr[i], $"[{i}]", indent + 1, nodePath);
}
for (int i = indicesToRemove.Count - 1; i >= 0; i--)
{
arr.RemoveAt(indicesToRemove[i]);
}
}
}
else
{
// 值类型
string valueStr = token.ToString();
if (token.Type == JTokenType.String)
valueStr = $"\"{valueStr}\"";
EditorGUILayout.LabelField($"{key}:", GUILayout.Width(100));
string newValue = EditorGUILayout.TextField(valueStr);
if (newValue != valueStr)
{
try
{
if (token.Type == JTokenType.String)
{
string trimmed = newValue.Trim('"');
token.Replace(trimmed);
}
else if (token.Type == JTokenType.Integer)
{
if (long.TryParse(newValue, out long longVal))
token.Replace(longVal);
}
else if (token.Type == JTokenType.Float)
{
if (double.TryParse(newValue, out double doubleVal))
token.Replace(doubleVal);
}
else if (token.Type == JTokenType.Boolean)
{
if (bool.TryParse(newValue, out bool boolVal))
token.Replace(boolVal);
}
else
{
token.Replace(newValue);
}
}
catch { }
}
EditorGUILayout.EndHorizontal();
}
if (indent == 0 && !string.IsNullOrEmpty(key))
{
float endY = GUILayoutUtility.GetRect(0, 0).y;
_keyPositions[key] = startY;
}
}
private void DrawTextEditor()
{
string displayText = _jsonTextContent;
// 如果选中了Key,只显示该Key对应的部分
if (!string.IsNullOrEmpty(_selectedKey) && _jsonData != null && _jsonData[_selectedKey] != null)
{
JToken selectedToken = _jsonData[_selectedKey];
displayText = selectedToken.ToString(Newtonsoft.Json.Formatting.Indented);
}
EditorGUI.BeginChangeCheck();
displayText = EditorGUILayout.TextArea(displayText, GUILayout.ExpandHeight(true));
if (EditorGUI.EndChangeCheck())
{
try
{
// 如果只编辑选中的Key部分,需要更新整个JSON
if (!string.IsNullOrEmpty(_selectedKey) && _jsonData != null)
{
JToken newToken = JToken.Parse(displayText);
_jsonData[_selectedKey] = newToken;
_jsonTextContent = _jsonData.ToString(Newtonsoft.Json.Formatting.Indented);
}
else if (_isArrayFormat)
{
// Array格式
_jsonArray = JArray.Parse(displayText);
_jsonTextContent = displayText;
}
else
{
// Object格式
_jsonData = JObject.Parse(displayText);
_jsonTextContent = displayText;
_firstLevelKeys = _jsonData.Properties().Select(p => p.Name).ToList();
}
_validationError = "";
}
catch (Exception e)
{
_validationError = $"JSON格式错误: {e.Message}";
}
}
}
// ------------------------------------------------------------------------
// 逻辑处理
// ------------------------------------------------------------------------
private void RefreshFileList()
{
_jsonFileList.Clear();
if (string.IsNullOrEmpty(_rootPath)) return;
string fullPath = _rootPath;
if (!Path.IsPathRooted(fullPath))
{
fullPath = Path.Combine(Application.dataPath.Replace("Assets", ""), _rootPath).Replace("\\", "/");
Debug.Log("fullPath: " + fullPath);
}
Debug.Log("fullPath: " + Directory.Exists(fullPath));
if (!Directory.Exists(fullPath)) return;
string[] files = Directory.GetFiles(fullPath, "*.json", SearchOption.AllDirectories);
foreach (var file in files)
{
string relativePath = file.Replace(Application.dataPath, "Assets");
if (string.IsNullOrEmpty(_searchString) ||
Path.GetFileName(file).ToLower().Contains(_searchString.ToLower()))
{
_jsonFileList.Add(file);
}
}
_jsonFileList.Sort();
}
private void SelectFile(string filePath)
{
_selectedFile = filePath;
_selectedKey = null; // 切换文件时清除选中的Key,显示完整JSON
_isArrayFormat = false; // 重置格式标识
LoadJsonFile(filePath);
GUI.FocusControl(null);
}
private void SelectKey(string key)
{
_selectedKey = key;
// 选中Key时,重置滚动位置到顶部(因为只显示该Key的内容)
_scrollPosEditor.y = 0;
Repaint();
}
private void LoadJsonFile(string filePath)
{
try
{
string jsonText = File.ReadAllText(filePath, System.Text.Encoding.UTF8);
JToken rootToken = JToken.Parse(jsonText);
// 判断是Object还是Array
if (rootToken.Type == JTokenType.Array)
{
_jsonArray = (JArray)rootToken;
_jsonData = null;
_isArrayFormat = true;
_firstLevelKeys.Clear();
_jsonTextContent = _jsonArray.ToString(Newtonsoft.Json.Formatting.Indented);
}
else if (rootToken.Type == JTokenType.Object)
{
_jsonData = (JObject)rootToken;
_jsonArray = null;
_isArrayFormat = false;
_firstLevelKeys = _jsonData.Properties().Select(p => p.Name).ToList();
_jsonTextContent = _jsonData.ToString(Newtonsoft.Json.Formatting.Indented);
}
else
{
throw new Exception("JSON格式必须是Object或Array");
}
_selectedKey = null;
_validationError = "";
_expandedNodes.Clear();
_keyPositions.Clear();
}
catch (Exception e)
{
_validationError = $"加载失败: {e.Message}";
_jsonData = null;
_jsonArray = null;
_isArrayFormat = false;
_firstLevelKeys.Clear();
}
}
private void SaveJsonFile()
{
if (string.IsNullOrEmpty(_selectedFile)) return;
if (_jsonData == null && _jsonArray == null) return;
try
{
string jsonText;
if (_isArrayFormat && _jsonArray != null)
{
jsonText = _jsonArray.ToString(Newtonsoft.Json.Formatting.Indented);
}
else if (_jsonData != null)
{
jsonText = _jsonData.ToString(Newtonsoft.Json.Formatting.Indented);
}
else
{
return;
}
File.WriteAllText(_selectedFile, jsonText, System.Text.Encoding.UTF8);
_jsonTextContent = jsonText;
_validationError = "";
AssetDatabase.Refresh();
EditorUtility.DisplayDialog("保存成功", "JSON文件已保存", "确定");
}
catch (Exception e)
{
_validationError = $"保存失败: {e.Message}";
EditorUtility.DisplayDialog("保存失败", e.Message, "确定");
}
}
private void CreateJsonFile()
{
if (string.IsNullOrEmpty(_newFileName)) return;
string fullPath = _rootPath;
if (!Path.IsPathRooted(fullPath))
{
fullPath = Path.Combine(Application.dataPath, _rootPath.Replace("Assets/", ""));
}
if (!Directory.Exists(fullPath))
{
Directory.CreateDirectory(fullPath);
}
string fileName = JsonUtil.FormatAsJsonPath(_newFileName);
string filePath = Path.Combine(fullPath, fileName);
filePath = GetUniqueFilePath(filePath);
JObject newJson = new JObject();
File.WriteAllText(filePath, newJson.ToString(Newtonsoft.Json.Formatting.Indented), System.Text.Encoding.UTF8);
AssetDatabase.Refresh();
RefreshFileList();
SelectFile(filePath);
_newFileName = "";
}
private void DeleteFile(string filePath)
{
try
{
File.Delete(filePath);
if (File.Exists(filePath + ".meta"))
File.Delete(filePath + ".meta");
AssetDatabase.Refresh();
if (_selectedFile == filePath)
{
_selectedFile = null;
_jsonData = null;
_jsonArray = null;
_isArrayFormat = false;
_firstLevelKeys.Clear();
}
RefreshFileList();
}
catch (Exception e)
{
EditorUtility.DisplayDialog("删除失败", e.Message, "确定");
}
}
private void DuplicateFile(string filePath)
{
try
{
string dir = Path.GetDirectoryName(filePath);
string fileName = Path.GetFileNameWithoutExtension(filePath);
string ext = Path.GetExtension(filePath);
string newPath = Path.Combine(dir, fileName + "_copy" + ext);
newPath = GetUniqueFilePath(newPath);
File.Copy(filePath, newPath);
AssetDatabase.Refresh();
RefreshFileList();
}
catch (Exception e)
{
EditorUtility.DisplayDialog("复制失败", e.Message, "确定");
}
}
private void ValidateJson()
{
if (string.IsNullOrEmpty(_selectedFile) && _jsonData == null && _jsonArray == null)
{
// 验证文本编辑器中的内容
if (!string.IsNullOrEmpty(_jsonTextContent))
{
try
{
JToken.Parse(_jsonTextContent);
_validationError = "";
EditorUtility.DisplayDialog("验证成功", "JSON格式正确", "确定");
}
catch (Exception e)
{
_validationError = $"验证失败: {e.Message}";
EditorUtility.DisplayDialog("验证失败", e.Message, "确定");
}
}
return;
}
try
{
string jsonText;
if (_jsonArray != null)
jsonText = _jsonArray.ToString();
else if (_jsonData != null)
jsonText = _jsonData.ToString();
else
jsonText = File.ReadAllText(_selectedFile, System.Text.Encoding.UTF8);
JToken.Parse(jsonText);
_validationError = "";
EditorUtility.DisplayDialog("验证成功", "JSON格式正确", "确定");
}
catch (Exception e)
{
_validationError = $"验证失败: {e.Message}";
EditorUtility.DisplayDialog("验证失败", e.Message, "确定");
}
}
private void FormatJson()
{
if (_jsonData == null && _jsonArray == null)
{
// 如果当前是文本模式,尝试从文本格式化
if (!string.IsNullOrEmpty(_jsonTextContent))
{
try
{
JToken rootToken = JToken.Parse(_jsonTextContent);
if (rootToken.Type == JTokenType.Array)
{
_jsonArray = (JArray)rootToken;
_jsonData = null;
_isArrayFormat = true;
_firstLevelKeys.Clear();
}
else
{
_jsonData = (JObject)rootToken;
_jsonArray = null;
_isArrayFormat = false;
_firstLevelKeys = _jsonData.Properties().Select(p => p.Name).ToList();
}
string formatted = rootToken.ToString(Newtonsoft.Json.Formatting.Indented);
_jsonTextContent = formatted;
_validationError = "";
return;
}
catch (Exception e)
{
_validationError = $"格式化失败: {e.Message}";
return;
}
}
return;
}
try
{
string formatted;
if (_isArrayFormat && _jsonArray != null)
{
formatted = _jsonArray.ToString(Newtonsoft.Json.Formatting.Indented);
_jsonArray = JArray.Parse(formatted);
}
else if (_jsonData != null)
{
formatted = _jsonData.ToString(Newtonsoft.Json.Formatting.Indented);
_jsonData = JObject.Parse(formatted);
_firstLevelKeys = _jsonData.Properties().Select(p => p.Name).ToList();
}
else
{
return;
}
_jsonTextContent = formatted;
_validationError = "";
}
catch (Exception e)
{
_validationError = $"格式化失败: {e.Message}";
}
}
private void RenameFile(string filePath, string newName)
{
try
{
string dir = Path.GetDirectoryName(filePath);
string ext = Path.GetExtension(filePath);
string newPath = Path.Combine(dir, newName + ext);
if (File.Exists(newPath))
{
EditorUtility.DisplayDialog("重命名失败", "文件已存在", "确定");
return;
}
File.Move(filePath, newPath);
if (File.Exists(filePath + ".meta"))
{
File.Move(filePath + ".meta", newPath + ".meta");
}
AssetDatabase.Refresh();
if (_selectedFile == filePath)
{
_selectedFile = newPath;
}
RefreshFileList();
}
catch (Exception e)
{
EditorUtility.DisplayDialog("重命名失败", e.Message, "确定");
}
}
private string GetUniqueFilePath(string filePath)
{
if (!File.Exists(filePath)) return filePath;
string dir = Path.GetDirectoryName(filePath);
string fileName = Path.GetFileNameWithoutExtension(filePath);
string ext = Path.GetExtension(filePath);
int counter = 1;
string newPath;
do
{
newPath = Path.Combine(dir, $"{fileName}_{counter}{ext}");
counter++;
} while (File.Exists(newPath));
return newPath;
}
private string GetValueTypeIcon(JToken token)
{
switch (token.Type)
{
case JTokenType.String: return "\"\"";
case JTokenType.Integer: return "123";
case JTokenType.Float: return "1.0";
case JTokenType.Boolean: return token.Value<bool>() ? "true" : "false";
case JTokenType.Null: return "null";
default: return "?";
}
}
}
}