Files
aibis-dream/Assets/Scripts/UI/Panel/DeveloperMode/DeveloperVariableSnapshot.cs
T
2026-07-20 14:29:47 +08:00

145 lines
4.7 KiB
C#

using System;
using System.Collections.Generic;
using System.Linq;
using Yarn.Unity;
namespace AibisDream.UI
{
internal readonly struct DeveloperVariableRecord
{
public readonly string Name;
public readonly string Type;
public readonly string Value;
public readonly string Kind;
public readonly bool IsGlobal;
public readonly bool HasRuntimeOverride;
public DeveloperVariableRecord(
string name,
string type,
object value,
string kind,
bool isGlobal,
bool hasRuntimeOverride)
{
Name = name;
Type = type;
Value = FormatValue(value);
Kind = kind;
IsGlobal = isGlobal;
HasRuntimeOverride = hasRuntimeOverride;
}
private static string FormatValue(object value)
{
if (value == null) return "null";
if (value is bool boolean) return boolean ? "true" : "false";
if (value is float number) return number.ToString("0.###");
if (value is double doubleNumber) return doubleNumber.ToString("0.###");
return value.ToString();
}
}
internal static class DeveloperVariableSnapshot
{
public static DeveloperVariableRecord[] Capture(YarnVariableStorage storage, YarnProject project)
{
if (storage == null)
{
return Array.Empty<DeveloperVariableRecord>();
}
var values = new Dictionary<string, object>(StringComparer.Ordinal);
var runtimeNames = new HashSet<string>(StringComparer.Ordinal);
try
{
if (project?.InitialValues != null)
{
foreach (var pair in project.InitialValues)
{
values[pair.Key] = pair.Value;
}
}
}
catch
{
// YarnProject 正在切换或尚未编译完成时仍显示运行时覆盖值。
}
var runtime = storage.GetAllVariables();
AddRuntime(runtime.FloatVariables, values, runtimeNames);
AddRuntime(runtime.StringVariables, values, runtimeNames);
AddRuntime(runtime.BoolVariables, values, runtimeNames);
var result = new List<DeveloperVariableRecord>(values.Count);
foreach (var pair in values.OrderBy(item => item.Key, StringComparer.Ordinal))
{
var effectiveValue = ResolveEffectiveValue(storage, pair.Key, pair.Value);
var type = effectiveValue switch
{
bool => "Bool",
string => "String",
float or double or int or long => "Number",
_ => effectiveValue?.GetType().Name ?? "Unknown"
};
string kind;
try
{
kind = storage.GetVariableKind(pair.Key).ToString();
}
catch
{
kind = "Unknown";
}
result.Add(new DeveloperVariableRecord(
pair.Key,
type,
effectiveValue,
kind,
pair.Key.StartsWith("$global_", StringComparison.Ordinal),
runtimeNames.Contains(pair.Key)));
}
return result.ToArray();
}
private static void AddRuntime<T>(
Dictionary<string, T> source,
IDictionary<string, object> values,
ISet<string> runtimeNames)
{
if (source == null) return;
foreach (var pair in source)
{
values[pair.Key] = pair.Value;
runtimeNames.Add(pair.Key);
}
}
private static object ResolveEffectiveValue(YarnVariableStorage storage, string name, object fallback)
{
try
{
switch (fallback)
{
case bool when storage.TryGetValue(name, out bool boolean):
return boolean;
case string when storage.TryGetValue(name, out string text):
return text;
case float or double or int or long when storage.TryGetValue(name, out float number):
return number;
default:
return fallback;
}
}
catch
{
return fallback;
}
}
}
}