Skip to content

Commit 23323e8

Browse files
author
flashpoint493
committed
feat: add complete Blueprint translation with variable and component support
Add Translate Entire Blueprint toolbar command for batch translation Add full support for Blueprint-level variables, local variables, and component overrides Add ClassItSelf graph type for class structure generation Improve Map key type extraction from Blueprint pin types Enhance component parent-child relationship detection Expand CodeGen_CPP.md with detailed guidance Update README with new features and improvements Fix compilation error: remove incorrect return statement in SaveGraphFilesOriginal
1 parent cb1483a commit 23323e8

20 files changed

+3591
-40
lines changed
Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
// Example file implementation: Reference context for Node to Code, not included in compilation
2+
// Purpose: Demonstrate splitting Blueprint events into separate C++ methods
3+
4+
#include "N2C_EventStyleGuide.h"
5+
6+
// Override engine event BeginPlay, call Super::BeginPlay()
7+
void AN2C_EventStyleGuideActor::BeginPlay()
8+
{
9+
Super::BeginPlay();
10+
11+
// Example logic: Trigger event dispatcher once
12+
InternalCounter = 1;
13+
OnSomethingHappened.Broadcast(InternalCounter);
14+
}
15+
16+
// Override engine event Tick, call Super::Tick(DeltaTime)
17+
void AN2C_EventStyleGuideActor::Tick(float DeltaTime)
18+
{
19+
Super::Tick(DeltaTime);
20+
21+
// Example logic: Increment counter
22+
InternalCounter += 1;
23+
}
24+
25+
// Custom event implementation, maintain one-to-one correspondence with Blueprint "Custom Event"
26+
void AN2C_EventStyleGuideActor::MyCustomEvent()
27+
{
28+
// Example logic: Broadcast event
29+
OnSomethingHappened.Broadcast(InternalCounter);
30+
}
Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
#pragma once
2+
3+
// Example file: Reference context for Node to Code, not included in compilation
4+
// Purpose: Demonstrate to LLM the expected style of splitting events into separate C++ methods
5+
6+
#include "CoreMinimal.h"
7+
#include "GameFramework/Actor.h"
8+
9+
// Event dispatcher example: Dynamic multicast delegate
10+
// Demonstrates how to declare an event dispatcher
11+
DECLARE_DYNAMIC_MULTICAST_DELEGATE_OneParam(FOnSomethingHappened, int32, Count);
12+
13+
// Demonstrates event splitting rules (overriding engine events + custom events)
14+
class AN2C_EventStyleGuideActor : public AActor
15+
{
16+
GENERATED_BODY()
17+
18+
public:
19+
// Override engine events, must use override and call Super::
20+
virtual void BeginPlay() override;
21+
virtual void Tick(float DeltaTime) override;
22+
23+
// Custom events should be generated as Blueprint-callable UFUNCTIONs, do not merge multiple events into one function
24+
UFUNCTION(BlueprintCallable, Category="N2C|Events")
25+
void MyCustomEvent();
26+
27+
// Demonstrates event dispatcher declaration and usage
28+
UPROPERTY(BlueprintAssignable, Category="N2C|Events")
29+
FOnSomethingHappened OnSomethingHappened;
30+
31+
private:
32+
// Example data only
33+
int32 InternalCounter = 0;
34+
};

Content/Prompting/CodeGen_CPP.md

Lines changed: 185 additions & 2 deletions
Large diffs are not rendered by default.

Content/README_N2C_Config.md

Lines changed: 189 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,189 @@
1+
# NodeToCode 配置层优化变更说明
2+
3+
本文件记录针对 NodeToCode 生成结果进行的“配置层”优化,以实现:
4+
1) 蓝图事件拆分为独立 C++ 方法,而非汇总到单一大函数;
5+
2) 自动生成类成员变量声明(含 UPROPERTY 修饰符);
6+
3) 输出必要的 `#include` 与蓝图/资产的伪 include 注释。
7+
8+
## 变更内容
9+
- 编辑 Prompt:`Plugins/NodeToCode/Content/Prompting/CodeGen_CPP.md`
10+
- 新增章节:`Event Structure Preservation - STRICT`
11+
- 每个蓝图事件对应独立 C++ 方法,禁止合并为单一大函数。
12+
- 引擎事件以 `override` 形式生成并调用 `Super::`
13+
- 自定义事件以 `UFUNCTION(BlueprintCallable)` 形式生成,参数与引脚一一对应。
14+
- 事件分发器使用 `DECLARE_DYNAMIC_*``UPROPERTY(BlueprintAssignable)`,通过 `.Broadcast(...)` 触发。
15+
- `.h``.cpp` 分别生成声明与实现。
16+
- 新增章节:`Variable Declaration Synthesis - STRICT`
17+
- 基于 Blueprint 使用自动推断并在 `.h` 中生成 `UPROPERTY(...)` 成员(精确类型、容器、TODO 注释)。
18+
- 新增章节:`UPROPERTY Specifiers Mapping - STRICT`
19+
- 基于使用语义选择 `EditAnywhere/VisibleAnywhere/BlueprintReadWrite/Transient/SaveGame` 等修饰符与 `meta` 标签。
20+
- 新增章节:`Includes and External References - STRICT`
21+
- 在实现顶部输出必要 `#include`;为蓝图/资产输出 `// include: /Game/...` 伪包含注释;未知头文件输出占位注释。
22+
- 新增章节:`Networking & Replication - STRICT`
23+
- 变量:`UPROPERTY(Replicated)` / `UPROPERTY(ReplicatedUsing=OnRep_Var)``OnRep_Var()` 生成;构造函数 `SetIsReplicatedByDefault(true)`
24+
- 生命周期:声明并实现 `GetLifetimeReplicatedProps(...)`,在 `.cpp` 使用 `DOREPLIFETIME(ThisClass, Var)`;包含 `#include "Net/UnrealNetwork.h"`
25+
- RPC:按语义生成 `UFUNCTION(Server|Client|NetMulticast, Reliable|Unreliable)`,并在实现中添加必要的权限校验(如 `HasAuthority()`)。
26+
27+
- 新增参考源文件(仅用于 LLM 参考上下文,不参与编译):
28+
- `Plugins/NodeToCode/Content/NodeToCode_Refs/N2C_EventStyleGuide.h`
29+
- `Plugins/NodeToCode/Content/NodeToCode_Refs/N2C_EventStyleGuide.cpp`
30+
31+
## 使用步骤
32+
1. 在 Project Settings → Plugins → Node to Code 中:
33+
-`Target Language` 设为 `C++`
34+
-`Max Translation Depth`(TranslationDepth)调至 `1``2`
35+
- 根据偏好选择 Provider/Model(建议:Anthropic Sonnet 或 OpenAI o4-mini)
36+
-`Reference Source Files` 中添加:
37+
- `Plugins/NodeToCode/Content/NodeToCode_Refs/N2C_EventStyleGuide.h`
38+
- `Plugins/NodeToCode/Content/NodeToCode_Refs/N2C_EventStyleGuide.cpp`
39+
40+
2. 重新执行翻译,并在输出目录(默认 `Saved/NodeToCode/Translations` 或自定义目录)对比结果结构。
41+
42+
## 期望效果
43+
- 多个蓝图事件将被转换为多个独立的 C++ 方法(引擎事件 `BeginPlay`/`Tick` 等为 `override`,自定义事件为 `UFUNCTION`)。
44+
- 事件分发器将正确以动态多播代理形式生成与触发。
45+
- 带网络语义的变量与调用会自动输出:`Replicated/ReplicatedUsing``OnRep_``GetLifetimeReplicatedProps`(含 `DOREPLIFETIME`)、必要的 `#include "Net/UnrealNetwork.h"`,以及 Server/Client/Multicast RPC 声明与实现骨架。
46+
- Blueprint 成员变量会在模型输入中以集中列表的形式提供,便于在同一个 `.h`/`.cpp` 片段中统一生成变量声明,而不是为每个变量拆散成多个脚本片段。
47+
- 函数局部变量现在也会被包含在模型中,以确保正确的声明和默认值。
48+
49+
## Translate Entire Blueprint 行为说明
50+
51+
- 使用工具栏上的 `Translate Entire Blueprint` 时,现在会按「图」拆分为多次请求:
52+
- 事件图、每个函数图、每个宏图分别序列化为独立的 N2C JSON。
53+
- 每个 JSON 单独发送给 LLM 服务,降低单次请求的上下文长度,避免触发 DeepSeek/OpenAI 等 Provider 的最大上下文限制错误。
54+
- 输出落盘行为调整为“同一批次集中在一个时间戳目录下”:
55+
- 每次执行 `Translate Entire Blueprint` 会为当前 Blueprint 生成一个带时间戳的根目录(例如 `Saved/NodeToCode/Translations/MyBP_2025-11-23-16.30.00/`)。
56+
- 这一轮批次内的所有图(事件图/函数图/宏图)翻译结果都会写入该目录下的子文件夹中(按图名划分子目录),便于统一查看和管理。
57+
- C++ 生成时的文件命名规则:
58+
- 每个图依然有自己的子目录:`<时间戳根目录>/<GraphName>/`
59+
- 但当目标语言为 C++ 且图类型为 `EventGraph` 时,会使用 Blueprint 类名(`GraphClass`/`metadata.BlueprintClass`)作为 `.h/.cpp` 文件名:
60+
- 例如:`AMyActor.h` / `AMyActor.cpp`,其中会集中放置:类声明、UPROPERTY 成员、组件声明与构造、构造函数/析构函数等。
61+
- 其他图(函数图/宏图等)仍旧以图名作为文件前缀,保持原有拆分粒度不变。
62+
63+
## Blueprint 组件(Components)默认值覆盖
64+
65+
- 从现在开始,N2C JSON 顶层会额外包含一个 `components[]` 数组,用于描述当前 Blueprint 中挂载的组件实例,以及**相对于组件类默认值被修改过的属性**
66+
- `ComponentName`:该组件在 Blueprint 中的变量名(例如 `MyMesh`)。
67+
- `ComponentClassName`:组件的类名(例如 `StaticMeshComponent`)。
68+
- `AttachParentName`:可选,挂载到的父组件/根(例如 `RootComponent` 或某个 SceneComponent 名)。
69+
- `OverriddenProperties[]`:只包含那些**被蓝图修改过**的属性,结构与 `variables[]` 类似(`Name / Type / TypeName / DefaultValue` 等)。
70+
- 生成 C++ 时,LLM 会参考 `components[]`
71+
- 在构造函数中使用 `CreateDefaultSubobject` 创建对应组件,并按 `AttachParentName``SetupAttachment`
72+
- 对每个组件仅对 `OverriddenProperties[]` 中出现的属性生成赋值代码(例如位置、旋转、布尔开关等),不会尝试覆盖所有引擎默认值;
73+
- 这样可以在保持上下文体积可控的前提下,尽量复现 Blueprint 中对组件默认参数的修改。
74+
75+
## C++ 生成约定补充(构造函数 / 析构函数 / override)
76+
77+
- 在 CodeGen 的 Prompt 中,新增了针对 C++ 类骨架的强约束:
78+
- 对于每个 Blueprint Class(例如 `AMCMagicCardBase`),要求 LLM 在生成 C++ 时:
79+
- 为该类补全/生成默认构造函数,用于创建组件(`CreateDefaultSubobject`)并初始化成员变量;
80+
- 在合适的情况下生成虚析构函数,保证继承链安全;
81+
- 对于引擎事件(`BeginPlay` / `Tick` / `OnConstruction` 等),使用 `override` 关键字声明,并在实现中调用 `Super::Xxx(...)`
82+
- 对 Blueprint 自定义函数,使用 `UFUNCTION(BlueprintCallable, Category="Auto")` 等 native 方式声明,必要时在重写父类虚函数时同样加上 `override`
83+
- 当用户提供已有的 .h/.cpp 文件时,LLM 会按 Prompt 要求将这些声明/实现**合并进现有类**,而不是重新定义一个重复的类。
84+
85+
## 备注
86+
- `Reference Source Files` 的示例文件仅用于提示 LLM 遵循风格,不会影响项目编译逻辑。
87+
- 如果已有你自己的事件风格示例,建议优先加入你自己的 .h/.cpp 作为参考上下文。
88+
89+
## C++ 生成增强方案与设计说明(对社区贡献摘要)
90+
91+
本节用于向社区简要说明当前针对 Blueprint → C++ 的增强设计与实现状态,便于在开源仓库中讨论与演进。
92+
93+
### 1. N2C JSON 模型扩展:components[](已实现)
94+
95+
-`FN2CBlueprint` 顶层新增 `components[]` 数组,描述 Blueprint 中挂载的组件实例以及**相对于组件类默认值被修改过的属性**
96+
- `ComponentName`:组件在 Blueprint 中的变量名。
97+
- `ComponentClassName`:组件类名(如 `StaticMeshComponent``TextRenderComponent` 等)。
98+
- `AttachParentName`:可选,挂载到的父组件/根名称(某些版本可能为空)。
99+
- `OverriddenProperties[]`:仅包含相对于对应组件类 CDO 被修改过的属性,结构沿用 `variables[]``Name / Type / TypeName / DefaultValue` 等)。
100+
-`FN2CNodeTranslator::CollectComponentOverrides` 中:
101+
- 遍历 Blueprint 的 `SimpleConstructionScript`,对每个 `USCS_Node``ComponentTemplate` 与类 CDO 做属性对比。
102+
- 仅当某个属性相对 CDO 发生变更时,才将其写入 `OverriddenProperties[]`,从而控制上下文长度并聚焦“真正被修改过的默认值”。
103+
104+
### 2. Prompt 侧 C++ 生成约束(已实现)
105+
106+
对应文件:`Content/Prompting/CodeGen_CPP.md`
107+
108+
- **事件与函数结构(Event Structure Preservation - STRICT)**
109+
- 每个 Blueprint 事件转为独立 C++ 方法,禁止合并为单一大函数。
110+
- 引擎事件统一以 `override` 形式声明并在实现中调用 `Super::Xxx(...)`
111+
- 自定义事件 / Blueprint 函数以 `UFUNCTION(BlueprintCallable, Category="Auto")` 等 native 风格声明。
112+
- 事件分发器使用 `DECLARE_DYNAMIC_*` + `UPROPERTY(BlueprintAssignable)`,并通过 `.Broadcast(...)` 触发。
113+
- `.h` 只放声明、`.cpp` 只放实现,保持 Unreal 代码风格。
114+
115+
- **类骨架 / 构造 / 析构(Class Skeleton, Constructor, and Destructor - STRICT)**
116+
- 对每个 Blueprint 类(`metadata.BlueprintClass`),要求生成或补全对应的 C++ 类:
117+
- 默认构造函数:用于创建组件并初始化成员变量。
118+
- 适当的虚析构函数:保证继承链安全(AActor/APawn/UObject 子类)。
119+
-`graph_type == "EventGraph"` 对应的翻译视为**该 Blueprint 类的主 C++ 类骨架承载者**
120+
-`graphDeclaration` 必须包含:
121+
- `UCLASS()` 宏。
122+
- `class <BlueprintClass> : public <BaseClass>` 声明。
123+
- 成员字段,包括:
124+
- 由顶层 `variables[]` 推断出的 UPROPERTY 成员。
125+
-`components[]` 推断出的组件 UPROPERTY 成员。
126+
- 所有事件 / 函数的 UFUNCTION 声明。
127+
-`graphImplementation` 必须包含:
128+
- 构造函数实现(组件 `CreateDefaultSubobject``SetupAttachment`、成员初始化)。
129+
- 需要时的析构函数实现。
130+
- 与类级别初始化相关的其它逻辑。
131+
- 当用户提供参考 `.h/.cpp` 时:
132+
- 不新建重复类,而是将上述声明/实现合并进既有类体和 `.cpp` 文件中,并补齐缺失的构造/析构/方法声明。
133+
134+
- **变量与组件映射(Variable + Component Synthesis - STRICT)**
135+
- 顶层 `variables[]`
136+
- 视为类成员变量,在 `.h` 中生成统一的 UPROPERTY 成员区块,而不是为每个变量拆开多个脚本片段。
137+
- `graphs[i].LocalVariables[]`
138+
- 视为函数局部变量,在 `graphImplementation` 中的函数体前部声明,并尽可能根据 `DefaultValue` 进行安全初始化。
139+
- `components[]`
140+
- `.h` 中声明组件 UPROPERTY 成员(`USceneComponent*` / `UStaticMeshComponent*` / `UTextRenderComponent*` 等)。
141+
- 构造函数中使用 `CreateDefaultSubobject` 创建组件并根据 `AttachParentName` 调用 `SetupAttachment`,必要时退化为挂到 `RootComponent`
142+
- 仅对 `OverriddenProperties[]` 中出现的属性生成赋值代码,优先使用语义化 `SetXxx` 接口,其次直接属性赋值。
143+
144+
- **网络与包含(Networking & Includes)**
145+
- 根据语义推断自动生成:
146+
- `UPROPERTY(Replicated)` / `UPROPERTY(ReplicatedUsing=OnRep_)`
147+
- `OnRep_` 函数及实现。
148+
- `GetLifetimeReplicatedProps` + `DOREPLIFETIME(ThisClass, Var)`
149+
- RPC:`UFUNCTION(Server|Client|NetMulticast, Reliable|Unreliable)` + 权限检查逻辑。
150+
- 保证 `.cpp` 包含 `#include "Net/UnrealNetwork.h"`,并在文件顶部集中输出伪 include 注释,便于后续人工补完头文件。
151+
152+
### 3. 输出目录与 C++ 文件命名(已实现)
153+
154+
- **批次根目录**
155+
- `Translate Entire Blueprint` 时,仍按图拆分为多个请求,每个图各自生成一份 N2C JSON。
156+
- 同一轮请求的所有图共享一个带时间戳的根目录,例如:
157+
- `Saved/NodeToCode/Translations/MyBP_2025-11-23-16.30.00/`
158+
- 从实现层面看,会先对整个 Blueprint 调用一次 `GenerateFromBlueprint` 生成完整的 `FN2CBlueprint`(包含所有图以及合成出来的 `ClassItSelf` 图),然后按图切片构造“每图一个 Blueprint 视图”的 N2C JSON 发送给 LLM,因此 ClassItSelf 也会参与整蓝图批量翻译流程。
159+
160+
- **每个图的子目录与文件名**
161+
- 每个 graph 有自己的子目录:`<时间戳根目录>/<GraphName>/`,内部存放该图的 `.h/.cpp` 以及 `_Notes.txt` 等辅助文件。
162+
- 实际写盘时会对 `GraphName` 做一次**轻量的文件名安全清洗**
163+
- 去掉首尾空格;
164+
- 将 Windows 不支持的文件名字符(如 `< > : " / \\ | ? *` 等)替换为下划线 `_`
165+
- JSON 中的 `graph_name` 保持原样不变,仅文件系统路径使用清洗后的名字。
166+
- 当前实现中,无论图类型(EventGraph/Function/Macro 等),生成的 C++ 文件均使用**清洗后的 `GraphName`** 作为文件名前缀:
167+
- 例如:`EventGraph/EventGraph.h``SomeFunction/SomeFunction.cpp`
168+
- 对于 C++ 的 `ClassItSelf` 图(`graph_type == "ClassItSelf"`)且其 `graph_class` 非空时,除了按图输出 `ClassItSelf/ClassItSelf.*` 以外,还会额外生成一对以类名命名的脚本:
169+
- `<时间戳根目录>/<GraphClass>/<GraphClass>.h`
170+
- `<时间戳根目录>/<GraphClass>/<GraphClass>.cpp`
171+
- 这两份类名脚本仅承载类骨架:
172+
- UCLASS 与完整 class 声明;
173+
- 所有 Blueprint 变量对应的 UPROPERTY 成员;
174+
- 所有 Blueprint 组件(来自 `components[]`)对应的 UPROPERTY 组件指针成员;
175+
- 构造/析构函数声明与实现;
176+
- 在构造函数中通过 `CreateDefaultSubobject` 创建组件、根据 `AttachParentName` 调用 `SetupAttachment`、以及对 `OverriddenProperties[]` 中属性的初始化逻辑。
177+
- 组件的 UPROPERTY 成员与构造阶段的创建/挂接/属性初始化**只会出现在 `<GraphClass>.h/.cpp` 这对类骨架文件中**,不会出现在 `EventGraph` 等其他按图拆分的 `.h/.cpp` 里;
178+
- `EventGraph` 图本身只负责事件/函数的声明与实现,不再在类目录下生成额外副本,从而保持“类结构 + 组件 + 构造/析构”和“事件逻辑”在输出层面上的清晰分离。
179+
180+
### 4. override/native 风格可配置化(规划中)
181+
182+
- 目前 Prompt 中对事件与函数声明风格是“写死”的:
183+
- 引擎事件统一使用 `override`
184+
- 自定义函数统一使用 `UFUNCTION(BlueprintCallable, Category="Auto")` 等 native 风格。
185+
- 计划在 `UN2CSettings` 中增加配置项(例如 `bUseNativeOverrideStyleForFunctions``EN2CFunctionStyle`),并在 Prompt 组装时读取:
186+
- 开启:维持当前“强 native + override”风格。
187+
- 关闭:使用更简化的函数声明风格,弱化 `override`/`UFUNCTION` 约束,方便某些项目做轻量级迁移。
188+
189+
这一系列设计在不改变 NodeToCode 核心数据模型(`FN2CBlueprint`/`FN2CGraph`)的前提下,通过 Prompt 约定与落盘命名策略,将“类骨架 + 组件 + 构造/析构”聚合到以 Blueprint 类名命名的 C++ 脚本中,同时保留按图拆分的优势,便于后续社区在此基础上迭代。

0 commit comments

Comments
 (0)