This commit is contained in:
meishibiezb
2026-06-04 21:37:53 +08:00
parent b0d2a0e2e7
commit 29a3f77908
63 changed files with 4068 additions and 1 deletions

View File

@@ -0,0 +1,72 @@
# EDialogPresentationScriptCommandParamType
## 基本信息
- **类型**: UENUM(BlueprintType)
- **父类**: uint8
- **源文件**: Plugins/Dialog/Source/Dialog/Public/DialogPresentationScript.h
- **模块**: Dialog
## 功能概述
对话脚本命令参数类型的枚举None、Number、String、Boolean、Array、Object。在 FDialogPresentationScriptParam 中作为类型标签使用,实现带标签的联合体语义。
## 设计用意
由于 USTRUCT 无法持有变体值,因此需要显式的类型鉴别机制。运行时代码通过 switch 该枚举值来读取正确的字段。Array 和 Object 类型以序列化的 JSON 字符串形式存储,以兼容蓝图。
## 职责范围
类型标签枚举。被 FDialogPresentationScriptParam 和 UPresentationJsonLibrary 引用,用于 JSON 解析和分发。
## 项目内依赖
| 依赖项 | 关系 | 源文件 |
|--------|------|--------|
(无项目内依赖)
## 对外接口
BlueprintType 枚举,作为 `FDialogPresentationScriptParam``Type` 字段的类型标签。消费者通过 switch 该枚举来决定读取哪个值字段。
枚举值:
- **None**: 无类型/空值。构造函数默认值JSON 解析失败时也为 None。
- **Number**: 对应 JSON Number 类型,值存储在 `FDialogPresentationScriptParam::NumberValue` (float)。
- **String**: 对应 JSON String 类型,值存储在 `FDialogPresentationScriptParam::StringValue`
- **Boolean**: 对应 JSON Boolean 类型,值存储在 `FDialogPresentationScriptParam::BooleanValue`
- **Array**: 对应 JSON Array 类型,整个数组序列化为 JSON 字符串存储在 `FDialogPresentationScriptParam::ArrayValue`
- **Object**: 对应 JSON Object 类型,整个对象序列化为 JSON 字符串存储在 `FDialogPresentationScriptParam::ObjectValue`
注意Array 和 Object 以序列化 JSON 字符串形式存储,而非嵌套结构体。消费者需要在蓝图或 C++ 中自行反序列化。
## 使用方法
在 JSON 解析中按值类型分发:
```cpp
// Plugins/Dialog/Source/Dialog/Private/DialogPresentationScript.cpp:163-196
switch (JsonValue->Type)
{
case EJson::String:
Param.Type = EDialogPresentationScriptCommandParamType::String;
Param.StringValue = JsonValue->AsString();
break;
case EJson::Number:
Param.Type = EDialogPresentationScriptCommandParamType::Number;
Param.NumberValue = static_cast<float>(JsonValue->AsNumber());
break;
// ... Boolean, Array, Object cases ...
}
```
在 JSON 序列化中按类型标签写入:
```cpp
// Plugins/Dialog/Source/Dialog/Private/DialogPresentationScript.cpp:353-389
switch (Param.Type)
{
case EDialogPresentationScriptCommandParamType::String:
return FString::Printf(TEXT("\"%s\""), *lambda(Param.StringValue));
case EDialogPresentationScriptCommandParamType::Number:
return FString::SanitizeFloat(Param.NumberValue);
// ... Boolean, Array, Object, default cases ...
}
```
## 用例
| 文件 | 行号 | 用途 |
|------|------|------|
| Plugins/Dialog/Source/Dialog/Public/DialogPresentationScript.h | 43-51,61,69 | 枚举定义FDialogPresentationScriptParam 构造函数默认值 (None);字段声明 |
| Plugins/Dialog/Source/Dialog/Private/DialogPresentationScript.cpp | 155-195 | JsonValueToParam 中按 JSON 类型分发到对应枚举值 |
| Plugins/Dialog/Source/Dialog/Private/DialogPresentationScript.cpp | 355-389 | ParamToJson 中按枚举值序列化到 JSON 字符串 |

View File

@@ -0,0 +1,68 @@
# FDialogPresentationScriptCommand
## 基本信息
- **类型**: USTRUCT(BlueprintType)
- **父类**: (无)
- **源文件**: Plugins/Dialog/Source/Dialog/Public/DialogPresentationScript.h
- **模块**: Dialog
## 功能概述
对话表现脚本中的单条可执行命令。包含 CommandName例如 "SetSpeaker"、"PlayAnimation")和一个有序的 FDialogPresentationScriptParam 数组。CommandName 作为策略路由的分发键。
## 设计用意
命令抽象用于策略模式的分发。CommandName 是路由键——每个 IPresentationStrategyPlugin 检查自己是否能处理该名称。Params 数组是通用的;每个策略知道自己期望的参数格式。将数据(做什么)与执行器(怎么做)分离。
## 职责范围
单条命令的数据容器。传递给 IPresentationStrategyPlugin::PerformCommand。自身不执行命令。
## 项目内依赖
| 依赖项 | 关系 | 源文件 |
|--------|------|--------|
| FDialogPresentationScriptParam | 包含TArray成员 | Plugins/Dialog/Source/Dialog/Public/DialogPresentationScript.h |
## 对外接口
BlueprintType 结构体,代表对话脚本中的单条可执行命令。外部代码(策略插件)通过 `IPresentationStrategyPlugin::PerformCommand` 接口接收此结构体。
关键字段:
- **CommandName** (FName): 命令名称作为策略路由的分发键。IPresentationScriptExecutor 根据此名称将命令分发给对应的 IPresentationStrategyPlugin。
- **Params** (TArray<FDialogPresentationScriptParam>): 命令参数数组。各策略插件知道如何解释自身命令的参数格式和类型。
典型流程:
1. `UPresentationJsonLibrary``FDialogPresentationScriptData::PresentationScript` JSON 中解析出命令数组。
2. 执行器遍历命令,根据 `CommandName` 找到对应策略。
3. 策略插件的 `PerformCommand` 接收该命令,按 Type 逐个解析 Params 中的参数。
## 使用方法
在编辑器对话图节点中编辑命令:
```cpp
// Plugins/Dialog/Source/DialogEditor/Public/DialogGraphNode.h:31
TArray<FDialogPresentationScriptCommand> PresentationScriptCommands;
```
在编辑器中通过 UPresentationJsonLibrary 将命令数组序列化为 JSON
```cpp
// Plugins/Dialog/Source/DialogEditor/Private/DialogGraphDataAsset.cpp:478
auto ScriptString = UPresentationJsonLibrary::PresentationScriptToJson(DialogNode->PresentationScriptCommands);
```
在 UPresentationJsonLibrary 内部将命令序列化为 JSON
```cpp
// Plugins/Dialog/Source/Dialog/Private/DialogPresentationScript.cpp:392-402
FString Result = TEXT("[");
Result += FString::Printf(TEXT("\"%s\""), *Command.CommandName.ToString());
for (const FDialogPresentationScriptParam& Param : Command.Params)
{
Result += TEXT(",") + ParamToJson(Param);
}
Result += TEXT("]");
```
## 用例
| 文件 | 行号 | 用途 |
|------|------|------|
| Plugins/Dialog/Source/Dialog/Public/DialogPresentationScript.h | 88-98 | 结构体定义 |
| Plugins/Dialog/Source/DialogEditor/Public/DialogGraphNode.h | 31 | 编辑器对话图节点中存储可编辑的命令列表 |
| Plugins/Dialog/Source/DialogEditor/Private/DialogGraphDataAsset.cpp | 478 | 编辑器导出时将节点命令序列化为 JSON |
| Plugins/Dialog/Source/Dialog/Private/DialogPresentationScript.cpp | 279-290 | PresentationScriptToJson 遍历命令数组并序列化 |
| Plugins/Dialog/Source/Dialog/Private/DialogPresentationScript.cpp | 392-402 | CommandToJson 将单条命令序列化为 JSON |
| Plugins/Dialog/Source/Dialog/Public/PresentationStrategyPlugin.h | 26 | IPresentationStrategyPlugin::PerformCommand 接收此类型参数 |

View File

@@ -0,0 +1,57 @@
# FDialogPresentationScriptData
## 基本信息
- **类型**: USTRUCT(BlueprintType)
- **父类**: FTableRowBase
- **源文件**: Plugins/Dialog/Source/Dialog/Public/DialogPresentationScript.h
- **模块**: Dialog
## 功能概述
DataTable 行结构体,用于存储单个对话脚本条目。包含 ChoicesJSON 数组存储选项标识符、PresentationScriptJSON 数组存储命令序列、Comment设计者注释和 ScriptID运行时填充的标识符。命令以 JSON 编码的 [CommandName, param1, param2, ...] 数组形式存储。
## 设计用意
将对话数据与执行逻辑解耦。JSON 格式使数据紧凑、便于外部工具编辑,且支持任意长度的参数列表而无需修改结构体定义。继承 FTableRowBase 使其能够存储在 UDataTable 中。
## 职责范围
单个对话节点的脚本数据容器。ScriptID 由 UDialogPresentationSubsystem 在查找时注入。结构体自身不解析或执行其 JSON 数据(解析工作由 UPresentationJsonLibrary 负责)。
## 项目内依赖
| 依赖项 | 关系 | 源文件 |
|--------|------|--------|
(无项目内依赖)
## 对外接口
作为 DataTable 行结构体,供外部代码通过 `UDataTable::FindRow<FDialogPresentationScriptData>()` 读取。
关键字段:
- **Choices** (FString): JSON 数组字符串,存储对话选项的标识符名称列表,如 `["Choice_A","Choice_B"]`
- **PresentationScript** (FString): JSON 命令数组字符串,每个命令为 `[CommandName, param1, param2, ...]` 格式的 JSON 数组。
- **Comment** (FText): 设计者注释,可通过 `UPresentationJsonLibrary::GetPresentationScriptComment` 读取。
- **ScriptID** (FName): 运行时由 `UDialogPresentationSubsystem::GetDialogPresentationScriptData` 自动填充,值为传入的行查找键名 (StructID)。
外部代码不应直接解析 Choices 和 PresentationScript 的 JSON 字符串,而应通过 `UPresentationJsonLibrary` 的静态方法(如 `GetPresentationScriptChoicesNum``GetPresentationScriptCommandName` 等)来访问其中数据。
## 使用方法
在 C++ 中通过子系统查找行数据:
```cpp
// Plugins/Dialog/Source/Dialog/Private/DialogPresentationSubsystem.cpp:30
FDialogPresentationScriptData* ScriptData = Table->FindRow<FDialogPresentationScriptData>(StructID, TEXT("DialogPresentationSubsystem"));
```
在编辑器工具中构造行数据并写入 DataTable
```cpp
// Plugins/Dialog/Source/DialogEditor/Private/DialogGraphDataAsset.cpp:481-487
FDialogPresentationScriptData RowData;
FName RowName = DialogNode->NodeID;
RowData.Choices = Result;
RowData.Comment = CommentText;
RowData.PresentationScript = ScriptString;
NewTable->AddRow(RowName, RowData);
```
## 用例
| 文件 | 行号 | 用途 |
|------|------|------|
| Plugins/Dialog/Source/Dialog/Private/DialogPresentationSubsystem.cpp | 30 | 从已注册的 DataTable 中按 StructID 查找并返回脚本行数据 |
| Plugins/Dialog/Source/Dialog/Private/DialogPresentationScript.cpp | 6,11,24,50,63,98,201,246 | UPresentationJsonLibrary 解析 Choices/PresentationScript JSON 字段 |
| Plugins/Dialog/Source/DialogEditor/Private/DialogGraphDataAsset.cpp | 481-487,489 | 编辑器从对话图节点导出 DataTable 时构造行数据 |

View File

@@ -0,0 +1,63 @@
# FDialogPresentationScriptParam
## 基本信息
- **类型**: USTRUCT(BlueprintType)
- **父类**: (无)
- **源文件**: Plugins/Dialog/Source/Dialog/Public/DialogPresentationScript.h
- **模块**: Dialog
## 功能概述
用于单个命令参数的带标签联合体值类型。包含一个 Type 枚举和多个值字段String、Numberfloat、Boolean、ArrayJSON 字符串、ObjectJSON 字符串)。显式构造函数初始化为 None/0.0/false。
## 设计用意
采用带标签的联合体模式来处理异构命令参数。使得单一灵活的命令系统成为可能,各策略根据类型解释参数。对蓝图可用。
## 职责范围
单个命令参数的值容器。消费者通过 switch Type 来读取正确的值字段。不解释或执行参数值。
## 项目内依赖
| 依赖项 | 关系 | 源文件 |
|--------|------|--------|
| EDialogPresentationScriptCommandParamType | 成员类型 | Plugins/Dialog/Source/Dialog/Public/DialogPresentationScript.h |
## 对外接口
BlueprintType 结构体,作为对话脚本命令参数的带标签联合体值类型。
关键字段:
- **Type** (EDialogPresentationScriptCommandParamType): 类型标签,指示哪个值字段有效。消费者应先检查此字段,然后读取对应的值字段。
- **StringValue** (FString): 字符串值,当 Type == String 时有效。
- **NumberValue** (float): 数值,当 Type == Number 时有效。
- **BooleanValue** (bool): 布尔值,当 Type == Boolean 时有效。
- **ArrayValue** (FString): JSON 数组的序列化字符串,当 Type == Array 时有效。需自行解析为 TArray。
- **ObjectValue** (FString): JSON 对象的序列化字符串,当 Type == Object 时有效。需自行解析为 TSharedPtr<FJsonObject>。
构造函数行为:
- Type 默认为 `EDialogPresentationScriptCommandParamType::None`
- NumberValue 默认为 `0.0f`
- BooleanValue 默认为 `false`
- StringValue、ArrayValue、ObjectValue 默认为空字符串FString 默认构造)
## 使用方法
从 FDialogPresentationScriptData 获取单个参数:
```cpp
// Plugins/Dialog/Source/Dialog/Private/DialogPresentationScript.cpp:201-225
FDialogPresentationScriptParam Param = UPresentationJsonLibrary::GetPresentationScriptCommandParaAt(Data, CommandIndex, ParaIndex);
```
从字符串构建参数对象:
```cpp
// Plugins/Dialog/Source/Dialog/Private/DialogPresentationScript.cpp:228-243
FDialogPresentationScriptParam Param = UPresentationJsonLibrary::BuildPresentationScriptCommandParaFromStr(SourceString);
```
消费者按 Type 分发读取正确的值字段,参见 `ParamToJson` 中的 switch 分发模式DialogPresentationScript.cpp:353-389
## 用例
| 文件 | 行号 | 用途 |
|------|------|------|
| Plugins/Dialog/Source/Dialog/Public/DialogPresentationScript.h | 54-85 | 结构体定义,包含所有字段和构造函数 |
| Plugins/Dialog/Source/Dialog/Private/DialogPresentationScript.cpp | 150-198 | JsonValueToParam 解析 JSON 值并填充字段 |
| Plugins/Dialog/Source/Dialog/Private/DialogPresentationScript.cpp | 201-225 | GetPresentationScriptCommandParaAt 获取指定命令的指定参数 |
| Plugins/Dialog/Source/Dialog/Private/DialogPresentationScript.cpp | 228-243 | BuildPresentationScriptCommandParaFromStr 从字符串构建参数 |
| Plugins/Dialog/Source/Dialog/Private/DialogPresentationScript.cpp | 246-276 | GetPresentationScriptCommandParams 获取某命令的所有参数数组 |
| Plugins/Dialog/Source/Dialog/Private/DialogPresentationScript.cpp | 351-389 | ParamToJson 按 Type 序列化为 JSON |

View File

@@ -0,0 +1,70 @@
# FDialogTextData
## 基本信息
- **类型**: USTRUCT(BlueprintType)
- **父类**: FTableRowBase
- **源文件**: Plugins/Dialog/Source/Dialog/Public/DialogPresentationScript.h
- **模块**: Dialog
## 功能概述
DataTable 行结构体,用于存储本地化对话文本。包含 bIsChoice 标志、Source/Target 标识符、DialogText 正文和 ChoiceText 标签。当 bIsChoice 为 true 时表示一个玩家选项。Source 和 Target 组成复合键,用于子系统索引构建。
## 设计用意
将对话内容说了什么与表现逻辑如何展示分离。DataTable 存储方式支持本地化和独立编辑。同一结构体通过 bIsChoice 标志同时服务于对话行和选项两种用途。复合键Source|Target用于对相关行进行分组。
## 职责范围
单条对话文本的数据容器。由 UDialogPresentationSubsystem 索引到 DialogTextIndex按 Source 索引)或 ChoiceTextIndex按 Source|Target 索引)中。不执行任何查找操作。
## 项目内依赖
| 依赖项 | 关系 | 源文件 |
|--------|------|--------|
(无项目内依赖)
## 对外接口
作为 DataTable 行结构体,供外部代码通过 `UDataTable::FindRow<FDialogTextData>()` 读取。
关键字段:
- **bIsChoice** (bool): 标识该行是普通对话文本 (false) 还是玩家选项文本 (true)。该标志决定行数据在 `BuildIndexes()` 中被索引到 `DialogTextIndex` 还是 `ChoiceTextIndex`
- **Source** (FName): 源节点 ID即对话所属节点的标识符。在 `DialogTextIndex` 中作为单键,在 `ChoiceTextIndex` 中与 Target 组成复合键。
- **DialogText** (FText): 对话正文。仅当 `bIsChoice == false` 时有意义。可通过 `UPresentationJsonLibrary::GetDialogText``UDialogPresentationSubsystem::GetDialogTextFromMapTable` 读取。
- **Target** (FName): 目标节点 ID即该选项跳转到的节点。仅当 `bIsChoice == true` 时有意义。
- **ChoiceText** (FText): 选项显示文本。仅当 `bIsChoice == true` 时有意义。可通过 `UPresentationJsonLibrary::GetChoicesText``UDialogPresentationSubsystem::GetChoiceTextFromMapTable` 读取。
外部代码建议通过 `UDialogPresentationSubsystem` 的查询方法(`GetDialogTextFromMapTable` / `GetChoiceTextFromMapTable`)来获取文本,而不是直接遍历 DataTable。
## 使用方法
在编辑器中构造对话文本行并写入 DataTable
```cpp
// Plugins/Dialog/Source/DialogEditor/Private/DialogGraphDataAsset.cpp:500-505
FDialogTextData DialogTextRowData;
FName DialogTextRowName = FName(*FString::Printf(TEXT("%s_%d"), *DialogNode->NodeID.ToString(), RowNameSuffix++));
DialogTextRowData.bIsChoice = false;
DialogTextRowData.Source = DialogNode->NodeID;
DialogTextRowData.DialogText = DialogNode->DialogText;
NewTable->AddRow(DialogTextRowName, DialogTextRowData);
```
编辑器中构造选项文本行:
```cpp
// Plugins/Dialog/Source/DialogEditor/Private/DialogGraphDataAsset.cpp:523-529
FDialogTextData ChoiceTextRowData;
ChoiceTextRowData.bIsChoice = true;
ChoiceTextRowData.Source = DialogNode->NodeID;
ChoiceTextRowData.ChoiceText = ChoiceIndex >= 0 && ChoiceIndex < DialogNode->ChoicePinValue.Num() ? DialogNode->ChoicePinValue[ChoiceIndex++] : FText::GetEmpty();
ChoiceTextRowData.Target = LinkedNode->NodeID;
NewTable->AddRow(ChoiceTextRowName, ChoiceTextRowData);
```
运行时通过子系统查询:
```cpp
// Plugins/Dialog/Source/Dialog/Private/DialogPresentationSubsystem.cpp:76
FDialogTextData* Result = DialogTextIndex.Find(Source);
```
## 用例
| 文件 | 行号 | 用途 |
|------|------|------|
| Plugins/Dialog/Source/Dialog/Private/DialogPresentationSubsystem.cpp | 71,76,84,90,109-122 | 在 DialogTextIndex/ChoiceTextIndex 中索引和查找文本行 |
| Plugins/Dialog/Source/Dialog/Private/DialogPresentationScript.cpp | 135-148 | UPresentationJsonLibrary 的 GetDialogText/GetChoicesText 直接读取字段 |
| Plugins/Dialog/Source/DialogEditor/Private/DialogGraphDataAsset.cpp | 500-533 | 编辑器从对话图节点导出 MapTable 时构造文本行数据 |
| Plugins/Dialog/Source/Dialog/Public/DialogPresentationSubsystem.h | 19,50,53,64 | FHelperArray 的 Data 成员类型;子系统查询方法返回类型 |

View File

@@ -0,0 +1,54 @@
# FHelperArray
## 基本信息
- **类型**: USTRUCT(BlueprintType)
- **父类**: (无)
- **源文件**: Plugins/Dialog/Source/Dialog/Public/DialogPresentationSubsystem.h
- **模块**: Dialog
## 功能概述
简单的包装结构体,持有 TArray<FDialogTextData>。仅因 Unreal 的 TMap 无法将裸 TArray 作为 UPROPERTY 值类型而存在。用作 ChoiceTextIndex 中的 Map 值类型。
## 设计用意
UE 引擎限制的变通方案。将数组包装在 USTRUCT 中使其成为有效的 TMap 值类型,以满足 GC 追踪要求。无其他用途。
## 职责范围
技术性包装结构体。仅在 UDialogPresentationSubsystem 的 ChoiceTextIndex Map 中使用。单一 UPROPERTY 成员TArray<FDialogTextData> Data。
## 项目内依赖
| 依赖项 | 关系 | 源文件 |
|--------|------|--------|
| FDialogTextData | 包含TArray成员 | Plugins/Dialog/Source/Dialog/Public/DialogPresentationScript.h |
## 对外接口
BlueprintType 结构体,纯粹的技术性包装器,唯一用途是使 `TArray<FDialogTextData>` 能够作为 `TMap` 的值类型。
唯一字段:
- **Data** (TArray<FDialogTextData>): 被包装的 FDialogTextData 数组。
外部代码通过 `UDialogPresentationSubsystem::GetChoiceTextFromMapTable` 获取 `TArray<FDialogTextData>`,通常不会直接操作此结构体。该结构体仅在 `ChoiceTextIndex` 内部使用,作为 `TMap<FName, FHelperArray>` 的值类型。
## 使用方法
子系统内部索引构建时查找或创建键值对:
```cpp
// Plugins/Dialog/Source/Dialog/Private/DialogPresentationSubsystem.cpp:120-121
FName Key = FName(*FString::Printf(TEXT("%s|%s"), *Row->Source.ToString(), *Row->Target.ToString()));
ChoiceTextIndex.FindOrAdd(Key).Data.Add(*Row);
```
子系统内部查询时解包数组:
```cpp
// Plugins/Dialog/Source/Dialog/Private/DialogPresentationSubsystem.cpp:90-92
if (FHelperArray* Result = ChoiceTextIndex.Find(Key))
{
return Result->Data; // O(1) 返回
}
```
## 用例
| 文件 | 行号 | 用途 |
|------|------|------|
| Plugins/Dialog/Source/Dialog/Public/DialogPresentationSubsystem.h | 15-20 | 结构体定义,位于子系统头文件中 |
| Plugins/Dialog/Source/Dialog/Public/DialogPresentationSubsystem.h | 66 | ChoiceTextIndex 的 Map 值类型:`TMap<FName, FHelperArray>` |
| Plugins/Dialog/Source/Dialog/Private/DialogPresentationSubsystem.cpp | 90-92 | GetChoiceTextFromMapTable 中解包返回 Data 数组 |
| Plugins/Dialog/Source/Dialog/Private/DialogPresentationSubsystem.cpp | 121 | BuildIndexes 中通过 FindOrAdd 追加选项行到对应复合键的数组 |

View File

@@ -0,0 +1,64 @@
# IPresentationScriptExecutor
## 基本信息
- **类型**: UINTERFACE + C++ 接口
- **父类**: UInterface
- **源文件**: Plugins/Dialog/Source/Dialog/Public/PresentationScriptExecutor.h
- **模块**: Dialog
## 功能概述
对话表现系统的协调器接口。方法ExecutePresentationScript运行脚本、PlugStrategyIn/UnplugStrategy按名称管理策略注册表。所有方法均为 BlueprintNativeEvent。
## 设计用意
门面/协调器模式。将"执行什么"FDialogPresentationScriptData与"谁执行"(策略插件)分离。作为接口与框架无关——可与任何 UI 系统配合使用。UDialogPresentationSubsystem 在脚本查找后调用 ExecutePresentationScript。
## 职责范围
编排对话脚本执行。管理策略插件注册表。由 UDialogPresentationSubsystem::ShowDialog 调用。不存储对话数据,也不解析 JSON。
## 项目内依赖
| 依赖项 | 关系 | 源文件 |
|--------|------|--------|
| FDialogPresentationScriptData | 前向声明(参数) | Plugins/Dialog/Source/Dialog/Public/PresentationScriptExecutor.h:26 |
| IPresentationStrategyPlugin | 前向声明(参数) | Plugins/Dialog/Source/Dialog/Public/PresentationScriptExecutor.h:28 |
## 对外接口
UInterface / C++ 接口,供蓝图或 C++ 类实现。作为对话表现系统的协调器/门面,负责编排脚本执行和管理策略插件注册表。所有方法均为 BlueprintNativeEvent可蓝图重写
三个方法:
- **ExecutePresentationScript** (BlueprintNativeEvent, BlueprintCallable): 接收 `const FDialogPresentationScriptData& ScriptStruct`(无返回值)。
-`UDialogPresentationSubsystem::ShowDialog` 调用。
- 实现者应解析 ScriptStruct 中的脚本数据,按顺序执行命令,将每条命令通过 CommandName 路由到已注册的 IPresentationStrategyPlugin。
- **PlugStrategyIn** (BlueprintNativeEvent, BlueprintCallable): 接收 `FName StrategyName``const TScriptInterface<IPresentationStrategyPlugin>& NewStrategy`
- 按名称注册一个策略插件。后续执行脚本时根据 CommandName 查找对应策略并调用其 PerformCommand。
- **UnplugStrategy** (BlueprintNativeEvent, BlueprintCallable): 接收 `FName StrategyName`
- 按名称注销一个策略插件。
典型实现者UI Widget如 WBP_TestUI它既是显示层也是执行协调器。
## 使用方法
在蓝图中实现此接口。典型调用链:
```cpp
// Plugins/Dialog/Source/Dialog/Private/DialogPresentationSubsystem.cpp:8-17
void UDialogPresentationSubsystem::ShowDialog(const TScriptInterface<IPresentationScriptExecutor> Executor, const FName StructID)
{
UObject* ExecutorObject = Executor.GetObject();
if (!ExecutorObject)
{
UE_LOG(LogTemp, Warning, TEXT("ShowDialog failed: Executor does not implement IPresentationScriptExecutor interface."));
return;
}
IPresentationScriptExecutor::Execute_ExecutePresentationScript(ExecutorObject, GetDialogPresentationScriptData(StructID));
}
```
子系统查找脚本数据、注入 ScriptID 后,通过 `Execute_ExecutePresentationScript` 静态方法调用蓝图实现的接口函数。
## 用例
| 文件 | 行号 | 用途 |
|------|------|------|
| Plugins/Dialog/Source/Dialog/Public/PresentationScriptExecutor.h | 19-31 | 接口定义UInterface 包装类 + C++ 接口类含三个方法声明 |
| Plugins/Dialog/Source/Dialog/Public/DialogPresentationSubsystem.h | 32 | UDialogPresentationSubsystem::ShowDialog 以此接口的 TScriptInterface 为参数 |
| Plugins/Dialog/Source/Dialog/Private/DialogPresentationSubsystem.cpp | 8-17 | ShowDialog 实现:先校验接口,再调用 Execute_ExecutePresentationScript |
| Plugins/Dialog/Source/Dialog/Private/PresentationScriptExecutor.cpp | 6 | 接口默认实现占位文件 |
| Document/Content/Blueprints/WBP_TestUI.md | 10 | WBP_TestUI蓝图 Widget实现此接口接收并执行脚本

View File

@@ -0,0 +1,56 @@
# IPresentationStrategyPlugin
## 基本信息
- **类型**: UINTERFACE + C++ 接口
- **父类**: UInterface
- **源文件**: Plugins/Dialog/Source/Dialog/Public/PresentationStrategyPlugin.h
- **模块**: Dialog
## 功能概述
用于处理对话表现命令的策略接口。单一方法 PerformCommand 接收 FDialogPresentationScriptCommand返回 booltrue 表示已处理。BlueprintNativeEvent支持蓝图实现。
## 设计用意
策略模式,支持多个独立的对话表现插件。一个策略处理 "SetSpeaker",另一个处理 "PlayAnimation"。布尔返回值支持回退路由。可扩展——新的表现能力只需添加新策略,无需修改核心代码。
## 职责范围
处理特定命名命令。按名称注册到 IPresentationScriptExecutor 中。不管理策略注册表,也不编排执行流程。
## 项目内依赖
| 依赖项 | 关系 | 源文件 |
|--------|------|--------|
| FDialogPresentationScriptCommand | 参数类型 | Plugins/Dialog/Source/Dialog/Public/DialogPresentationScript.h |
## 对外接口
UInterface / C++ 接口,供蓝图或 C++ 类实现,用于处理特定命名类别的对话脚本命令。
单一方法:
- **PerformCommand** (BlueprintNativeEvent, BlueprintCallable): 接收 `const FDialogPresentationScriptCommand& InCommand`,返回 `bool`
- 返回 `true` 表示该策略识别并成功处理了此命令。
- 返回 `false` 表示未处理(可用于回退路由链)。
设计模式:策略模式。每个策略实现负责一个命令名称空间(如 "SetSpeaker"、"PlayAnimation")。策略通过 `IPresentationScriptExecutor::PlugStrategyIn` 按名称注册到执行器。执行器根据 `CommandName` 将命令路由到对应策略。
注意:策略自身不管理注册,不决定何时被调用。注册和调度由实现 `IPresentationScriptExecutor` 的类负责。
## 使用方法
在 C++ 或蓝图中实现此接口。蓝图中可 override `PerformCommand` 事件:
1. 检查 `InCommand.CommandName` 是否为自己能处理的命令。
2. 读取 `InCommand.Params`,按 Type 字段分发读取正确的值。
3. 执行相应的游戏逻辑(设置角色、播放动画等)。
4. 返回 `true` 表示已处理,或 `false` 表示不处理。
策略类通过执行器的 `PlugStrategyIn(StrategyName, StrategyObject)` 注册自身:
```cpp
// Plugins/Dialog/Source/Dialog/Public/PresentationScriptExecutor.h:28
void PlugStrategyIn(FName StrategyName, const TScriptInterface<class IPresentationStrategyPlugin>& NewStrategy);
```
## 用例
| 文件 | 行号 | 用途 |
|------|------|------|
| Plugins/Dialog/Source/Dialog/Public/PresentationStrategyPlugin.h | 19-27 | 接口定义UInterface 包装类 + C++ 接口类含 PerformCommand 声明 |
| Plugins/Dialog/Source/Dialog/Public/PresentationScriptExecutor.h | 28 | IPresentationScriptExecutor::PlugStrategyIn 以此接口的 TScriptInterface 为参数 |
| Document/Content/Blueprints/WBP_TestUI.md | 10 | WBP_TestUI 实现 IPresentationScriptExecutor负责将命令分发给对应的策略插件 |
注:`PerformCommand` 在 Dialog 插件源码中仅有声明PresentationStrategyPlugin.h:26无 C++ 调用实现;调用发生在实现 `IPresentationScriptExecutor` 的蓝图/运行时中。搜索 `PerformCommand` 仅匹配到接口声明行。

View File

@@ -0,0 +1,85 @@
# UDialogPresentationSubsystem
## 基本信息
- **类型**: UCLASS
- **父类**: UGameInstanceSubsystem
- **源文件**: Plugins/Dialog/Source/Dialog/Public/DialogPresentationSubsystem.h
- **模块**: Dialog
## 功能概述
GameInstance 级别的对话数据中心注册表。管理脚本数据FDialogPresentationScriptData和映射表FDialogTextData的 DataTable 注册。构建 O(1) 文本查找索引。ShowDialog 将所有环节串联起来:通过 StructID 查找脚本、注入 ScriptID、调用执行器的 ExecutePresentationScript。
## 设计用意
对话系统的数据访问层。使用 UGameInstanceSubsystem 以获得持久生命周期。支持多个 DataTable按章节、按 NPC 等)。通过预构建的哈希映射实现 O(1) 文本查找,满足频繁的游戏查询需求。将数据与执行解耦。
## 职责范围
对话数据中心注册表与查找。注册/注销 DataTable。构建文本索引。通过 StructID 解析脚本。不执行脚本(委托给执行器),也不解析 JSON使用 UPresentationJsonLibrary
## 项目内依赖
| 依赖项 | 关系 | 源文件 |
|--------|------|--------|
| FDialogTextData | 前向声明 | Plugins/Dialog/Source/Dialog/Public/DialogPresentationSubsystem.h:11 |
| IPresentationScriptExecutor | 前向声明(参数) | Plugins/Dialog/Source/Dialog/Public/DialogPresentationSubsystem.h:32 |
| FDialogPresentationScriptData | #include(在 .cpp 中) | Plugins/Dialog/Source/Dialog/Public/DialogPresentationScript.h |
## 对外接口
UGameInstanceSubsystem 派生类,所有方法均为 UFUNCTION(BlueprintCallable),可从 C++ 和蓝图调用。UE 引擎自动创建实例(每个 GameInstance 一个),无需手动实例化。
脚本执行:
- **ShowDialog(const TScriptInterface<IPresentationScriptExecutor> Executor, const FName StructID)**: 核心入口。在所有已注册的 DataTable 中按 StructID 查找 FDialogPresentationScriptData注入 ScriptID然后调用 Executor 的 ExecutePresentationScript 接口方法。
数据查询:
- **GetDialogPresentationScriptData(const FName StructID)**: 遍历 RegisteredDataTables返回第一个匹配 StructID 的行。返回时会注入 ScriptID 字段。
- **GetDialogTextFromMapTable(FName Source)**: 从 DialogTextIndex 中按 Source 查找对话文本O(1) 复杂度。首次调用时若索引未构建则自动触发 BuildIndexes()。
- **GetChoiceTextFromMapTable(FName Source, FName Target)**: 从 ChoiceTextIndex 中按复合键 `Source|Target` 查找选项文本数组O(1) 复杂度。首次调用时若索引未构建则自动触发 BuildIndexes()。
DataTable 管理:
- **RegisterDataTable(const FName TableName, UDataTable* DataTable)**: 注册脚本 DataTable。TableName 仅供标识,查找时遍历所有已注册表。
- **UnregisterDataTable(const FName TableName)**: 注销脚本 DataTable。
- **RegisterMapTable(const FName TableName, UDataTable* DataTable)**: 注册文本映射 DataTableFDialogTextData。注册时自动调用 BuildIndexes() 重建索引。
- **UnregisterMapTable(const FName TableName)**: 注销文本映射 DataTable 并重建索引。
内部状态(对外不可见):
- RegisteredDataTables (TMap<FName, UDataTable*>): 已注册的脚本 DataTable。
- RegisteredMapTables (TMap<FName, UDataTable*>): 已注册的文本映射 DataTable。
- DialogTextIndex (TMap<FName, FDialogTextData>): 按 Source 索引的对话文本映射。
- ChoiceTextIndex (TMap<FName, FHelperArray>): 按 `Source|Target` 复合键索引的选项文本映射。
## 使用方法
通过 GameInstance 获取子系统实例:
```cpp
UGameInstance* GI = GetGameInstance();
UDialogPresentationSubsystem* DialogSubsystem = GI->GetSubsystem<UDialogPresentationSubsystem>();
```
调用 ShowDialog 触发脚本执行:
```cpp
// Plugins/Dialog/Source/Dialog/Private/DialogPresentationSubsystem.cpp:8-17
DialogSubsystem->ShowDialog(ExecutorWidget, FName("StartNode"));
```
注册 DataTable 和 MapTable
```cpp
// Plugins/Dialog/Source/Dialog/Private/DialogPresentationSubsystem.cpp:43,56
DialogSubsystem->RegisterDataTable(FName("Chapter1"), ScriptTable);
DialogSubsystem->RegisterMapTable(FName("Chapter1"), MapTable);
```
查询对话文本:
```cpp
// Plugins/Dialog/Source/Dialog/Private/DialogPresentationSubsystem.cpp:71-81
FDialogTextData Text = DialogSubsystem->GetDialogTextFromMapTable(FName("Node_01"));
```
## 用例
| 文件 | 行号 | 用途 |
|------|------|------|
| Plugins/Dialog/Source/Dialog/Public/DialogPresentationSubsystem.h | 26-70 | 类定义:所有公共方法声明和私有成员 |
| Plugins/Dialog/Source/Dialog/Private/DialogPresentationSubsystem.cpp | 8-17 | ShowDialog 实现:校验接口 + 调用 Execute_ExecutePresentationScript |
| Plugins/Dialog/Source/Dialog/Private/DialogPresentationSubsystem.cpp | 20-41 | GetDialogPresentationScriptData 实现:遍历已注册表查找行 |
| Plugins/Dialog/Source/Dialog/Private/DialogPresentationSubsystem.cpp | 43-53 | RegisterDataTable / UnregisterDataTable 实现 |
| Plugins/Dialog/Source/Dialog/Private/DialogPresentationSubsystem.cpp | 56-68 | RegisterMapTable / UnregisterMapTable 实现(含自动索引重建) |
| Plugins/Dialog/Source/Dialog/Private/DialogPresentationSubsystem.cpp | 71-81 | GetDialogTextFromMapTable 实现O(1) 查找 |
| Plugins/Dialog/Source/Dialog/Private/DialogPresentationSubsystem.cpp | 84-96 | GetChoiceTextFromMapTable 实现:按复合键 O(1) 查找 |
| Plugins/Dialog/Source/Dialog/Private/DialogPresentationSubsystem.cpp | 98-127 | BuildIndexes 实现:遍历 MapTable 构建 DialogTextIndex 和 ChoiceTextIndex |
| Document/Content/Blueprints/WBP_TestUI.md | 16,24 | WBP_TestUI 通过 UDialogPresentationSubsystem 管理 DataTable |

View File

@@ -0,0 +1,70 @@
# UPresentationJsonLibrary
## 基本信息
- **类型**: UCLASSBlueprintFunctionLibrary
- **父类**: UBlueprintFunctionLibrary
- **源文件**: Plugins/Dialog/Source/Dialog/Public/DialogPresentationScript.h
- **模块**: Dialog
## 功能概述
用于对话脚本 JSON 解析和序列化的静态函数库。解析 Choices JSON 数组和 PresentationScript JSON 命令数组。提供获取命令数量、指定索引处的命令名称、参数数量、指定索引处的参数的函数。同时支持将命令序列化回 JSON。所有方法均为静态 UFUNCTION。
## 设计用意
蓝图与 JSON 对话数据之间的桥梁。FDialogPresentationScriptData 将命令存储为原始 JSON 字符串本库负责解析它们。BlueprintFunctionLibrary 使所有方法无需实例即可从蓝图中调用。私有辅助函数处理带正确转义的递归 JSON 值序列化。
## 职责范围
对话脚本的 JSON 与结构体之间的转换。将 FDialogPresentationScriptData 字段解析为类型化的访问接口。将 TArray<FDialogPresentationScriptCommand> 序列化回 JSON。不执行命令。
## 项目内依赖
| 依赖项 | 关系 | 源文件 |
|--------|------|--------|
| FDialogPresentationScriptData | 参数类型 | Plugins/Dialog/Source/Dialog/Public/DialogPresentationScript.h |
| FDialogPresentationScriptCommand | 参数/返回类型 | Plugins/Dialog/Source/Dialog/Public/DialogPresentationScript.h |
| FDialogPresentationScriptParam | 内部创建/解析 | Plugins/Dialog/Source/Dialog/Public/DialogPresentationScript.h |
| FDialogTextData | 参数类型 | Plugins/Dialog/Source/Dialog/Public/DialogPresentationScript.h |
## 对外接口
BlueprintFunctionLibrary所有方法均为静态 UFUNCTION(BlueprintCallable),可从 C++ 和蓝图调用。提供两大类功能:脚本数据解析和文本数据访问。
脚本数据解析(参数均为 FDialogPresentationScriptData
- **GetPresentationScriptComment**: 返回 Data.Comment设计者注释
- **GetPresentationScriptChoicesNum**: 解析 Data.Choices JSON 数组,返回选项数量;解析失败返回 -1。
- **GetPresentationScriptChoiceAt**: 解析 Data.Choices返回指定索引处的选项名称 (FName);越界或失败返回空 FName。
- **GetPresentationScriptCommandsNum**: 解析 Data.Choices JSON 数组,返回元素数量(注意:此函数存在已知 bug应解析 Data.PresentationScript 而非 Data.Choices参见 `DialogPresentationScript.cpp:53`)。
- **GetPresentationScriptCommandName**: 解析 Data.PresentationScript返回第 Index 条命令的名称 (FName)。
- **GetPresentationScriptCommandParaNum**: 解析 Data.PresentationScript返回第 Index 条命令的参数数量(总元素数减 1
- **GetPresentationScriptCommandParaAt**: 解析 Data.PresentationScript返回第 CommandIndex 条命令的第 ParaIndex 个参数 (FDialogPresentationScriptParam)。
- **BuildPresentationScriptCommandParaFromStr**: 从单字符串解析 JSON 值并构建 FDialogPresentationScriptParam。
- **GetPresentationScriptCommandParams**: 解析 Data.PresentationScript返回第 CommandIndex 条命令的所有参数 (TArray<FDialogPresentationScriptParam>)。
- **PresentationScriptToJson**: 将命令数组反向序列化为 JSON 字符串(编辑器导出用)。
文本数据访问:
- **GetDialogText**: 返回 FDialogTextData 的 DialogText 字段。
- **GetChoicesText**: 遍历 TArray<FDialogTextData>,提取每个元素的 ChoiceText 字段组成 TArray<FText>。
已知 bug`GetPresentationScriptChoicesNum``GetPresentationScriptCommandsNum` 的实现都解析了 `Data.Choices` 而非分别解析 Choices 和 PresentationScript参见 `DialogPresentationScript.cpp:14``DialogPresentationScript.cpp:53`)。调用时需注意此行为。
## 使用方法
在 C++ 中解析脚本命令:
```cpp
int NumCommands = UPresentationJsonLibrary::GetPresentationScriptCommandsNum(ScriptData);
for (int i = 0; i < NumCommands; i++)
{
FName CmdName = UPresentationJsonLibrary::GetPresentationScriptCommandName(ScriptData, i);
TArray<FDialogPresentationScriptParam> Params = UPresentationJsonLibrary::GetPresentationScriptCommandParams(ScriptData, i);
// 根据 CmdName 分发处理...
}
```
在编辑器中序列化命令数组为 JSON
```cpp
// Plugins/Dialog/Source/DialogEditor/Private/DialogGraphDataAsset.cpp:478
auto ScriptString = UPresentationJsonLibrary::PresentationScriptToJson(DialogNode->PresentationScriptCommands);
```
## 用例
| 文件 | 行号 | 用途 |
|------|------|------|
| Plugins/Dialog/Source/Dialog/Public/DialogPresentationScript.h | 101-145 | 类声明,包含所有公共静态方法签名 |
| Plugins/Dialog/Source/Dialog/Private/DialogPresentationScript.cpp | 6-402 | 全部方法实现JSON 解析、参数构建、反序列化 |
| Plugins/Dialog/Source/DialogEditor/Private/DialogGraphDataAsset.cpp | 478 | 调用 PresentationScriptToJson 将编辑器命令数组序列化为 JSON |

View File

@@ -0,0 +1,21 @@
# Dialog 插件依赖关系
## 文件间引用关系
| 源文件 | 引用方式 | 目标文件 | 目标单位 |
|--------|---------|---------|---------|
| DialogPresentationScript.cpp | #include | DialogPresentationScript.h | FDialogPresentationScriptData, FDialogTextData, EDialogPresentationScriptCommandParamType, FDialogPresentationScriptParam, FDialogPresentationScriptCommand, UPresentationJsonLibrary |
| PresentationStrategyPlugin.h | forward-declare | (inline) | FDialogPresentationScriptCommand |
| PresentationScriptExecutor.h | forward-declare | (inline) | FDialogPresentationScriptData, IPresentationStrategyPlugin |
| DialogPresentationSubsystem.h | forward-declare | (inline) | FDialogTextData, IPresentationScriptExecutor |
| DialogPresentationSubsystem.cpp | #include | DialogPresentationScript.h | FDialogPresentationScriptData, FDialogTextData, UPresentationJsonLibrary |
| DialogPresentationSubsystem.cpp | #include | PresentationScriptExecutor.h | IPresentationScriptExecutor |
| DialogPresentationScript.cpp | #include (Json module) | DialogPresentationScript.h | All structs from DialogPresentationScript.h |
## 关键依赖链
1. Dialog Execution: UDialogPresentationSubsystem::ShowDialog → GetDialogPresentationScriptData → FDialogPresentationScriptData → IPresentationScriptExecutor::ExecutePresentationScript
2. Text Lookup: UDialogPresentationSubsystem::GetDialogTextFromMapTable → DialogTextIndex (TMap<FName, FDialogTextData>)
3. Choice Lookup: UDialogPresentationSubsystem::GetChoiceTextFromMapTable → ChoiceTextIndex (TMap<FName, FHelperArray>) → TArray<FDialogTextData>
4. JSON Parsing: FDialogPresentationScriptData::PresentationScript → UPresentationJsonLibrary (parses) → parses individual FDialogPresentationScriptCommand → FDialogPresentationScriptParam
5. Strategy Dispatch: IPresentationScriptExecutor → IPresentationStrategyPlugin::PerformCommand(FDialogPresentationScriptCommand)