feat: Add WorldStateFlagAttribute and custom property drawer for enhanced dialogue management

- Implemented WorldStateFlagAttribute to mark string fields as world state flags.
- Created NarrativeNPCEditor for custom inspector to visualize dialogue version activation states.
- Developed WorldStateFlagDrawer to provide dropdown menu for known flags in the inspector.
- Introduced ActorModule for managing DialogueActorSO assets, including viewing, creating, and deleting actors.
- Added DialogueModule for managing DialogueSequenceSO assets with detailed previews and action bars.
- Established QuestModule for managing QuestSO assets, including objectives and branches.
- Implemented QuestManagerPostprocessor to automatically refresh QuestManager's quest list on asset changes.
This commit is contained in:
2026-05-24 00:36:11 +08:00
parent 520f84999b
commit 446fd5dcd0
22 changed files with 1908 additions and 101 deletions

View File

@@ -122,7 +122,64 @@ namespace BaseGames.Localization
public static string Get(string key, string table = "UI")
=> ServiceLocator.GetOrDefault<ILocalizationService>()?.Get(key, table) ?? key;
// ── 内部 ─────────────────────────────────────────────────────────────
// ── 编辑器预览(不依赖 ServiceLocator 实例)────────────────────────────
#if UNITY_EDITOR
// 编辑器预览缓存:"{language}/{table}" → (key → value)
// 生命周期与编辑器进程相同域重载时自动清空static 字段随域重载重置)。
private static readonly System.Collections.Generic.Dictionary<
string,
System.Collections.Generic.Dictionary<string, string>> s_editorPreviewCache = new();
/// <summary>
/// 编辑器工具专用:不依赖运行时服务实例,直接从 Resources 读取本地化文本。
/// 结果缓存在静态字典中,同一编辑器会话内同一表只加载一次。
/// 找不到时返回 null区别于运行时的 key 回退,便于调用方判断是否显示 key
/// </summary>
public static string GetEditorPreview(string key, string table = "UI",
Language language = Language.ChineseSimplified)
{
if (string.IsNullOrEmpty(key)) return null;
var dict = GetEditorTable(language, table)
?? GetEditorTable(Language.English, table); // 中文缺失时英文回退
if (dict == null) return null;
dict.TryGetValue(key, out var value);
return value; // 找不到 key 时返回 null
}
private static System.Collections.Generic.Dictionary<string, string> GetEditorTable(
Language language, string table)
{
string cacheKey = $"{language}/{table}";
if (s_editorPreviewCache.TryGetValue(cacheKey, out var cached))
return cached; // 已缓存(可能是 null 占位,表示文件不存在)
string path = $"Localization/{language}/{table}";
var asset = Resources.Load<TextAsset>(path);
if (asset == null)
{
s_editorPreviewCache[cacheKey] = null; // 记录"不存在",避免重复尝试
return null;
}
var parsed = JsonUtility.FromJson<StringTableJson>(asset.text);
if (parsed?.entries == null)
{
s_editorPreviewCache[cacheKey] = null;
return null;
}
var dict = new System.Collections.Generic.Dictionary<string, string>(
parsed.entries.Count, System.StringComparer.Ordinal);
foreach (var entry in parsed.entries)
if (!string.IsNullOrEmpty(entry.key))
dict[entry.key] = entry.value ?? string.Empty;
s_editorPreviewCache[cacheKey] = dict;
return dict;
}
#endif
private bool TryGetFromTable(Language language, string table, string key, out string value)
{
var cacheKey = $"{language}/{table}";