261 lines
9.3 KiB
C#
261 lines
9.3 KiB
C#
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;
|
||
}
|
||
}
|
||
} |