145 lines
4.7 KiB
C#
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;
|
|
}
|
|
}
|
|
}
|
|
}
|