Files

261 lines
9.3 KiB
C#
Raw Permalink 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 UnityEditor;
using UnityEngine;
using System.Collections.Generic;
using System.IO;
using System.Text.RegularExpressions;
namespace ChillConnect.Editor
{
/// <summary>
/// 第三方关卡配置批量转换工具
/// 输入:文件夹内所有第三方单关JSON
/// 输出:对应转换后的我方格式单关JSON
/// </summary>
public class LevelBatchConverter : EditorWindow
{
#region 数据结构定义
// 第三方单关结构(只声明需要的字段,多余自动忽略)
[System.Serializable]
private class ThirdPartyLevel
{
public Vector2Int size;
public string name;
public List<ThirdPartyArrow> arrows;
}
[System.Serializable]
private class ThirdPartyArrow
{
public List<Vector2Int> nodes;
public int color;
}
// 我方单关结构(和运行时对齐)
[System.Serializable]
public class ArrowConfig
{
public int id;
public int startPoint;
public List<string> path = new List<string>();
}
[System.Serializable]
public class LevelConfig
{
public int levelId;
public string levelName;
public int gridRows;
public int gridCols;
public int pointSpacing = 60;
public List<ArrowConfig> arrows = new List<ArrowConfig>();
}
#endregion
private string _inputFolder = "";
private string _outputFolder = "";
private int _pointSpacing = 60;
private Vector2 _scrollPos;
private List<string> _logList = new List<string>();
[MenuItem("Window/Arrow Game/批量关卡转换工具")]
public static void ShowWindow()
{
var window = GetWindow<LevelBatchConverter>("批量关卡转换");
window.minSize = new Vector2(500, 400);
}
private void OnGUI()
{
EditorGUILayout.Space(10);
// 输入文件夹
EditorGUILayout.LabelField("输入文件夹(第三方单关JSON", EditorStyles.boldLabel);
EditorGUILayout.BeginHorizontal();
_inputFolder = EditorGUILayout.TextField(_inputFolder);
if (GUILayout.Button("选择", GUILayout.Width(60)))
{
string path = EditorUtility.OpenFolderPanel("选择输入文件夹", Application.dataPath, "");
if (!string.IsNullOrEmpty(path))
_inputFolder = path;
}
EditorGUILayout.EndHorizontal();
EditorGUILayout.Space(8);
// 输出文件夹
EditorGUILayout.LabelField("输出文件夹(转换后JSON", EditorStyles.boldLabel);
EditorGUILayout.BeginHorizontal();
_outputFolder = EditorGUILayout.TextField(_outputFolder);
if (GUILayout.Button("选择", GUILayout.Width(60)))
{
string path = EditorUtility.OpenFolderPanel("选择输出文件夹", Application.dataPath, "");
if (!string.IsNullOrEmpty(path))
_outputFolder = path;
}
EditorGUILayout.EndHorizontal();
EditorGUILayout.Space(8);
// 基础配置
_pointSpacing = EditorGUILayout.IntField("默认点间距", _pointSpacing);
EditorGUILayout.Space(10);
// 转换按钮
if (GUILayout.Button("开始批量转换", GUILayout.Height(30)))
{
BatchConvert();
}
EditorGUILayout.Space(10);
// 日志区域
EditorGUILayout.LabelField("转换日志", EditorStyles.boldLabel);
_scrollPos = EditorGUILayout.BeginScrollView(_scrollPos, GUILayout.ExpandHeight(true));
foreach (string log in _logList)
{
EditorGUILayout.LabelField(log);
}
EditorGUILayout.EndScrollView();
}
/// <summary>
/// 批量转换核心逻辑
/// </summary>
private void BatchConvert()
{
_logList.Clear();
if (string.IsNullOrEmpty(_inputFolder) || !Directory.Exists(_inputFolder))
{
_logList.Add("❌ 输入文件夹不存在");
return;
}
if (string.IsNullOrEmpty(_outputFolder))
{
_logList.Add("❌ 请选择输出文件夹");
return;
}
// 创建输出目录
if (!Directory.Exists(_outputFolder))
{
Directory.CreateDirectory(_outputFolder);
}
// 获取所有json文件
string[] files = Directory.GetFiles(_inputFolder, "*.json", SearchOption.TopDirectoryOnly);
if (files.Length == 0)
{
_logList.Add("⚠️ 输入文件夹内未找到JSON文件");
return;
}
_logList.Add($"找到 {files.Length} 个JSON文件,开始转换...");
int successCount = 0;
int failCount = 0;
for (int i = 0; i < files.Length; i++)
{
string filePath = files[i];
string fileName = Path.GetFileNameWithoutExtension(filePath);
try
{
// 1. 读取并解析第三方配置
string json = File.ReadAllText(filePath);
ThirdPartyLevel thirdLevel = JsonUtility.FromJson<ThirdPartyLevel>(json);
if (thirdLevel == null || thirdLevel.arrows == null)
{
_logList.Add($"❌ {fileName}:解析失败,格式不匹配");
failCount++;
continue;
}
// 2. 转换为我方格式
LevelConfig level = ConvertLevel(thirdLevel, fileName, i + 1);
// 3. 导出到输出文件夹
string outJson = JsonUtility.ToJson(level, true);
string outPath = Path.Combine(_outputFolder, $"{fileName}.json");
File.WriteAllText(outPath, outJson);
_logList.Add($"✅ {fileName}:转换成功 | {level.gridCols}×{level.gridRows} | {level.arrows.Count}个箭头");
successCount++;
}
catch (System.Exception e)
{
_logList.Add($"❌ {fileName}:转换异常 - {e.Message}");
failCount++;
}
}
_logList.Add("");
_logList.Add($"===== 转换完成 =====");
_logList.Add($"成功:{successCount} 个");
_logList.Add($"失败:{failCount} 个");
_logList.Add($"输出路径:{_outputFolder}");
EditorUtility.DisplayDialog("批量转换完成",
$"成功:{successCount}\n失败:{failCount}\n输出路径:{_outputFolder}",
"确定");
AssetDatabase.Refresh();
}
/// <summary>
/// 单个关卡转换逻辑(和之前编辑器内转换完全一致)
/// </summary>
private LevelConfig ConvertLevel(ThirdPartyLevel thirdLevel, string fileName, int index)
{
LevelConfig level = new LevelConfig
{
levelId = index,
levelName = string.IsNullOrEmpty(thirdLevel.name) ? fileName : thirdLevel.name,
gridCols = thirdLevel.size.x,
gridRows = thirdLevel.size.y,
pointSpacing = _pointSpacing,
arrows = new List<ArrowConfig>()
};
for (int i = 0; i < thirdLevel.arrows.Count; i++)
{
var thirdArrow = thirdLevel.arrows[i];
if (thirdArrow.nodes == null || thirdArrow.nodes.Count == 0)
continue;
ArrowConfig arrow = new ArrowConfig
{
id = i + 1,
path = new List<string>()
};
// 起点转换:(x,y) → 点ID = y * 列数 + x
Vector2Int startNode = thirdArrow.nodes[0];
arrow.startPoint = startNode.y * level.gridCols + startNode.x;
// 路径转换:相邻节点计算方向
for (int j = 1; j < thirdArrow.nodes.Count; j++)
{
Vector2Int prev = thirdArrow.nodes[j - 1];
Vector2Int cur = thirdArrow.nodes[j];
int dx = cur.x - prev.x;
int dy = cur.y - prev.y;
if (dx == 1) arrow.path.Add("right");
else if (dx == -1) arrow.path.Add("left");
else if (dy == 1) arrow.path.Add("down");
else if (dy == -1) arrow.path.Add("up");
}
level.arrows.Add(arrow);
}
return level;
}
}
}