using System.IO;
using System.Collections.Generic;
using UnityEditor;
using UnityEngine;
using Newtonsoft.Json.Linq;
namespace SLSUtilities.Narrative.Editor
{
///
/// Yarn Spinner 自动 YSLS 合并器。
/// 自动将来自不同程序集(Assembly-CSharp、SLSUtilities等)生成的多个 YSLS 声明文件
/// 合并成一个单一的 combined.ysls.json 文件,输出到项目根目录下,
/// 从而完美解决 VS Code 中 Yarn Spinner 插件只能同时加载一个 definitions 文件的限制!
///
[InitializeOnLoad]
public static class YslsMerger
{
static YslsMerger()
{
// 每次 Unity 重新编译、资源导入或启动时自动运行
EditorApplication.delayCall += MergeYslsFiles;
}
[MenuItem("Tools/Yarn Spinner/Merge YSLS Files")]
public static void MergeYslsFiles()
{
string packagePath = Path.Combine(Directory.GetCurrentDirectory(), "ProjectSettings", "Packages", "dev.yarnspinner");
if (!Directory.Exists(packagePath))
{
return;
}
string combinedFileName = "combined.ysls.json";
string outputRootPath = Path.Combine(packagePath, combinedFileName);
try
{
// 搜索所有以 -generated.ysls.json 结尾的声明文件
string[] files = Directory.GetFiles(packagePath, "*-generated.ysls.json");
if (files.Length == 0)
{
return;
}
JArray allCommands = new JArray();
JArray allFunctions = new JArray();
int version = 2;
foreach (string file in files)
{
if (Path.GetFileName(file) == combinedFileName) continue;
string json = File.ReadAllText(file);
if (string.IsNullOrEmpty(json)) continue;
JObject root = JObject.Parse(json);
if (root.TryGetValue("version", out JToken vToken))
{
version = Mathf.Max(version, vToken.Value());
}
if (root.TryGetValue("commands", out JToken cToken) && cToken is JArray commandsArray)
{
foreach (var cmd in commandsArray)
{
allCommands.Add(cmd);
}
}
if (root.TryGetValue("functions", out JToken fToken) && fToken is JArray functionsArray)
{
foreach (var func in functionsArray)
{
allFunctions.Add(func);
}
}
}
// 组装合并后的 JObject
JObject combined = new JObject
{
["version"] = version,
["commands"] = allCommands,
["functions"] = allFunctions
};
// 写入项目根目录
File.WriteAllText(outputRootPath, combined.ToString(Newtonsoft.Json.Formatting.Indented));
Debug.Log($"[YSLS Merger] 成功将 {files.Length} 个 YSLS 声明文件合并至: '{outputRootPath}'。现在您可以在 VS Code 中一键加载此合并文件!");
}
catch (System.Exception ex)
{
// 自动合并失败通常发生在初始无缓存时,作警告处理,不中断编辑体验
Debug.LogWarning($"[YSLS Merger] 自动合并 YSLS 文件失败(这通常是由于 Yarn Spinner 尚未生成初始的 ysls 缓存文件导致的,属于正常现象):{ex.Message}");
}
}
}
}