mirror of
https://github.com/GeWuYou/GFramework.git
synced 2026-05-09 01:54:30 +08:00
- 新增 AdditionalTextGeneratorTestDriver 用于源生成器测试 - 添加 AutoLoadAttribute 特性支持 AutoLoad 类型映射 - 扩展项目构建目标,支持自定义 project.godot 路径验证 - 创建完整 Godot 集成教程文档,涵盖节点生命周期、信号系统等功能 - 添加源代码生成器测试项目配置和相关依赖包引用
173 lines
4.3 KiB
Markdown
173 lines
4.3 KiB
Markdown
# Godot 项目元数据生成器
|
||
|
||
> 从 `project.godot` 生成 AutoLoad 与 Input Action 的强类型访问入口。
|
||
|
||
## 概述
|
||
|
||
`GFramework.Godot.SourceGenerators` 会读取 Godot 项目根目录下的 `project.godot`,并把其中最常用的项目级元数据暴露为稳定的编译期
|
||
API。
|
||
|
||
当前覆盖:
|
||
|
||
- `[autoload]` 段:生成 `GFramework.Godot.Generated.AutoLoads`
|
||
- `[input]` 段:生成 `GFramework.Godot.Generated.InputActions`
|
||
|
||
这项能力的目标不是替代场景级生成器,而是把 Godot 工程配置和 C# 代码之间的字符串约定收敛到编译期。
|
||
|
||
## 接入方式
|
||
|
||
### NuGet 引用
|
||
|
||
当项目通过 NuGet 引用 `GeWuYou.GFramework.Godot.SourceGenerators` 时,生成器会默认把项目根目录下的 `project.godot` 加入
|
||
`AdditionalFiles`。
|
||
|
||
如需覆盖默认路径,可以设置:
|
||
|
||
- 可以改成项目根目录下的其他相对路径
|
||
- 文件名必须仍然是 `project.godot`,否则生成器会给出警告并忽略该文件
|
||
|
||
```xml
|
||
<PropertyGroup>
|
||
<GFrameworkGodotProjectFile>Config/project.godot</GFrameworkGodotProjectFile>
|
||
</PropertyGroup>
|
||
```
|
||
|
||
### 仓库内直接引用生成器
|
||
|
||
如果你通过 `ProjectReference(OutputItemType=Analyzer)` 直接引用生成器项目,则需要手动加入:
|
||
|
||
```xml
|
||
<ItemGroup>
|
||
<AdditionalFiles Include="project.godot" />
|
||
</ItemGroup>
|
||
```
|
||
|
||
## AutoLoad 访问层
|
||
|
||
### 基础行为
|
||
|
||
假设 `project.godot` 中声明了:
|
||
|
||
```ini
|
||
[autoload]
|
||
GameServices="*res://autoload/game_services.tscn"
|
||
AudioBus="*res://autoload/audio_bus.gd"
|
||
```
|
||
|
||
生成器会产出:
|
||
|
||
```csharp
|
||
using GFramework.Godot.Generated;
|
||
|
||
var gameServices = AutoLoads.GameServices;
|
||
|
||
if (AutoLoads.TryGetAudioBus(out var audioBus))
|
||
{
|
||
}
|
||
```
|
||
|
||
- 对于能唯一映射到 C# 节点类型的条目,属性会是强类型的
|
||
- 对于无法映射或对应非 C# 脚本的条目,属性会退化为 `Godot.Node`
|
||
- 生成器通过 `Godot.Engine.GetMainLoop()` 与当前 `SceneTree.Root` 解析 `/root/<AutoLoadName>` 节点
|
||
|
||
### 显式映射
|
||
|
||
当 AutoLoad 名称无法仅靠类名唯一推断时,可以使用 `[AutoLoad]` 明确指定:
|
||
|
||
```csharp
|
||
using GFramework.Godot.SourceGenerators.Abstractions;
|
||
using Godot;
|
||
|
||
[AutoLoad("GameServices")]
|
||
public partial class GameServices : Node
|
||
{
|
||
}
|
||
```
|
||
|
||
规则如下:
|
||
|
||
- 显式 `[AutoLoad]` 映射优先于隐式类名推断
|
||
- 标记了 `[AutoLoad]` 的类型必须继承 `Godot.Node`
|
||
- 若多个类型映射到同一个 AutoLoad,生成器会报告诊断,并退化为 `Godot.Node` 访问器,直到映射唯一
|
||
|
||
## Input Action 常量
|
||
|
||
### 基础行为
|
||
|
||
假设 `project.godot` 中有:
|
||
|
||
```ini
|
||
[input]
|
||
move_up={
|
||
}
|
||
ui_cancel={
|
||
}
|
||
```
|
||
|
||
生成器会产出:
|
||
|
||
```csharp
|
||
using GFramework.Godot.Generated;
|
||
|
||
if (Input.IsActionJustPressed(InputActions.MoveUp))
|
||
{
|
||
}
|
||
```
|
||
|
||
转换规则:
|
||
|
||
- `move_up` -> `MoveUp`
|
||
- `ui_cancel` -> `UiCancel`
|
||
- 非法字符会被清理后再转换为 PascalCase
|
||
- 如果多个动作名落到同一个标识符,生成器会追加稳定数字后缀,例如 `MoveUp_2`
|
||
|
||
## 与现有 Godot 生成器的关系
|
||
|
||
这项能力和现有的场景级生成器是互补的:
|
||
|
||
- `AutoLoads` / `InputActions` 解决的是项目级元数据访问
|
||
- `[GetNode]` 解决的是场景节点引用注入
|
||
- `[BindNodeSignal]` 解决的是节点事件订阅样板
|
||
|
||
推荐组合方式:
|
||
|
||
```csharp
|
||
using GFramework.Godot.Generated;
|
||
using GFramework.Godot.SourceGenerators.Abstractions;
|
||
using Godot;
|
||
|
||
public partial class MainHud : Control
|
||
{
|
||
[GetNode]
|
||
private Button _startButton = null!;
|
||
|
||
public override void _Ready()
|
||
{
|
||
__InjectGetNodes_Generated();
|
||
|
||
if (Input.IsActionPressed(InputActions.UiCancel))
|
||
{
|
||
}
|
||
|
||
var services = AutoLoads.GameServices;
|
||
}
|
||
}
|
||
```
|
||
|
||
## 诊断与约束
|
||
|
||
当前会重点报告以下问题:
|
||
|
||
- `[AutoLoad]` 标记在非 `Godot.Node` 类型上
|
||
- 多个类型映射到同一个 AutoLoad 名称
|
||
- 不同 AutoLoad 名称或 Input Action 名称在清洗后发生标识符冲突
|
||
- `project.godot` 内部重复声明同名 AutoLoad 或 Input Action
|
||
|
||
这些诊断的目的不是阻断所有生成,而是在可能的情况下保留稳定输出,同时把不确定性显式暴露出来。
|
||
|
||
## 相关文档
|
||
|
||
- [GetNode 生成器](./get-node-generator)
|
||
- [BindNodeSignal 生成器](./bind-node-signal-generator)
|
||
- [Godot 集成教程](../tutorials/godot-integration)
|