Skip to content

Commit 2d35bdb

Browse files
committed
feat: component ustructs
1 parent 3c4ec3f commit 2d35bdb

File tree

1 file changed

+161
-6
lines changed

1 file changed

+161
-6
lines changed

Source/EcsactUnrealCodegenPlugin/EcsactUnrealCodegenPlugin.cpp

Lines changed: 161 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -52,7 +52,7 @@ auto ecsact_decl_name_to_pascal(const std::string& input) -> std::string {
5252
auto capitalize_next = true;
5353

5454
for(char ch : input) {
55-
if(ch == '.') {
55+
if(ch == '.' || ch == '_') {
5656
capitalize_next = true; // Capitalize the next character after a separator
5757
} else if(capitalize_next) {
5858
result << static_cast<char>(std::toupper(ch));
@@ -93,6 +93,148 @@ auto ecsact_codegen_plugin_name() -> const char* {
9393
return "Unreal";
9494
}
9595

96+
static auto ecsact_type_to_unreal_type(
97+
ecsact::codegen_plugin_context& ctx,
98+
ecsact_builtin_type type
99+
) -> std::string {
100+
switch(type) {
101+
case ECSACT_BOOL:
102+
return "bool";
103+
case ECSACT_I8:
104+
case ECSACT_I16:
105+
case ECSACT_I32:
106+
return "int32";
107+
case ECSACT_U8:
108+
case ECSACT_U16:
109+
case ECSACT_U32:
110+
return "uint32";
111+
case ECSACT_F32:
112+
return "float";
113+
case ECSACT_ENTITY_TYPE:
114+
break;
115+
default:
116+
ctx.fatal(
117+
"Ecsact Unreal codegen plugin unknown builtin type ({}). Cannot "
118+
"proceed. Are you using the correct version of the Ecsact SDK with the "
119+
"correct version of the Ecsact Unreal codegen plugin?",
120+
static_cast<int>(type)
121+
);
122+
break;
123+
}
124+
125+
return "";
126+
}
127+
128+
static auto ecsact_type_to_unreal_type(
129+
ecsact::codegen_plugin_context& ctx,
130+
ecsact_field_type type
131+
) -> std::string {
132+
switch(type.kind) {
133+
case ECSACT_TYPE_KIND_BUILTIN:
134+
if(type.length == 1) {
135+
return ecsact_type_to_unreal_type(ctx, type.type.builtin);
136+
}
137+
ctx.fatal("Ecsact builtin array fields not supported yet");
138+
break;
139+
case ECSACT_TYPE_KIND_ENUM:
140+
ctx.fatal("Esact enum type not supported in yet");
141+
break;
142+
case ECSACT_TYPE_KIND_FIELD_INDEX:
143+
ctx.fatal("Ecsact field index not supported in unreal yet");
144+
break;
145+
default:
146+
ctx.fatal(
147+
"Ecsact Unreal codegen plugin unknown field type (kind={}). Cannot "
148+
"proceed. Are you using the correct version of the Ecsact SDK with the "
149+
"correct version of the Ecsact Unreal codegen plugin?",
150+
static_cast<int>(type.kind)
151+
);
152+
break;
153+
}
154+
155+
return "";
156+
}
157+
158+
static auto ecsact_ustruct_name(auto decl_id) -> std::string {
159+
auto name = ecsact::meta::decl_full_name(decl_id);
160+
auto pascal_name = ecsact_decl_name_to_pascal(name);
161+
return std::format("F{}", pascal_name);
162+
}
163+
164+
template<typename T>
165+
static auto uproperty_clamp_min_max() -> std::string {
166+
return std::format(
167+
R"(, Meta = (ClampMin = "{}", ClampMax = "{}"))",
168+
std::numeric_limits<T>::min(),
169+
std::numeric_limits<T>::max()
170+
);
171+
}
172+
173+
static auto print_ecsact_type_uproperty(
174+
ecsact::codegen_plugin_context& ctx,
175+
ecsact_field_type field_type
176+
) -> void {
177+
ctx.write("UPROPERTY(EditAnywhere, BlueprintReadWrite");
178+
switch(field_type.kind) {
179+
case ECSACT_TYPE_KIND_BUILTIN:
180+
switch(field_type.type.builtin) {
181+
case ECSACT_BOOL:
182+
break;
183+
case ECSACT_I8:
184+
ctx.write(uproperty_clamp_min_max<int8_t>());
185+
break;
186+
case ECSACT_U8:
187+
ctx.write(uproperty_clamp_min_max<uint8_t>());
188+
break;
189+
case ECSACT_I16:
190+
ctx.write(uproperty_clamp_min_max<int16_t>());
191+
break;
192+
case ECSACT_U16:
193+
ctx.write(uproperty_clamp_min_max<uint16_t>());
194+
break;
195+
case ECSACT_I32:
196+
break;
197+
case ECSACT_U32:
198+
break;
199+
case ECSACT_F32:
200+
break;
201+
case ECSACT_ENTITY_TYPE:
202+
break;
203+
}
204+
break;
205+
case ECSACT_TYPE_KIND_ENUM:
206+
break;
207+
case ECSACT_TYPE_KIND_FIELD_INDEX:
208+
break;
209+
}
210+
211+
ctx.write(")\n");
212+
}
213+
214+
static auto print_ustruct(ecsact::codegen_plugin_context& ctx, auto in_compo_id)
215+
-> void {
216+
auto compo_id = ecsact_id_cast<ecsact_composite_id>(in_compo_id);
217+
auto compo_name = ecsact::meta::decl_full_name(compo_id);
218+
auto compo_pascal_name = ecsact_ustruct_name(compo_id);
219+
220+
ctx.writef("USTRUCT(BlueprintType)");
221+
block(ctx, std::format("struct {}", compo_pascal_name), [&] {
222+
ctx.writef("GENERATED_BODY()\n\n");
223+
auto fields = ecsact::meta::get_field_ids(compo_id);
224+
225+
for(auto field_id : fields) {
226+
auto field_type = ecsact::meta::get_field_type(compo_id, field_id);
227+
auto field_unreal_type = ecsact_type_to_unreal_type(ctx, field_type);
228+
auto field_name = ecsact::meta::field_name(compo_id, field_id);
229+
auto field_pascal_name = ecsact_decl_name_to_pascal(field_name);
230+
231+
print_ecsact_type_uproperty(ctx, field_type);
232+
ctx.write(std::format("{} {};\n", field_unreal_type, field_pascal_name));
233+
}
234+
});
235+
ctx.writef(";\n\n");
236+
}
237+
96238
static auto generate_header(ecsact::codegen_plugin_context ctx) -> void {
97239
ctx.writef("#pragma once\n\n");
98240

@@ -107,6 +249,10 @@ static auto generate_header(ecsact::codegen_plugin_context ctx) -> void {
107249

108250
ctx.writef("\n\n");
109251

252+
for(auto comp_id : ecsact::meta::get_component_ids(ctx.package_id)) {
253+
print_ustruct(ctx, comp_id);
254+
}
255+
110256
ctx.write(std::format(
111257
"UCLASS(Blueprintable, meta = "
112258
"(DisplayName = \"Ecsact Runner Package Subsystem ({})\"))\n",
@@ -131,16 +277,22 @@ static auto generate_header(ecsact::codegen_plugin_context ctx) -> void {
131277
auto comp_type_cpp_name = cpp_identifier(comp_full_name);
132278
auto comp_name = ecsact::meta::component_name(comp_id);
133279
auto comp_pascal_name = ecsact_decl_name_to_pascal(comp_name);
280+
auto comp_ustruct_name = ecsact_ustruct_name(comp_id);
134281
ctx.write(std::format(
135282
"UFUNCTION(BlueprintNativeEvent, Category = \"Ecsact Runner\", meta "
136283
"= "
137284
"(DisplayName = \"Init {}\"))\n",
138285
comp_full_name
139286
));
140-
ctx.write(std::format("void Init{}();\n", comp_pascal_name));
141287
ctx.write(std::format(
142-
"virtual void Init{}_Implementation();\n",
143-
comp_pascal_name
288+
"void Init{0}(int32 Entity, {1} {0});\n",
289+
comp_pascal_name,
290+
comp_ustruct_name
291+
));
292+
ctx.write(std::format(
293+
"virtual void Init{0}_Implementation(int32 Entity, {1} {0});\n",
294+
comp_pascal_name,
295+
comp_ustruct_name
144296
));
145297
}
146298
}
@@ -158,13 +310,16 @@ static auto generate_source(ecsact::codegen_plugin_context ctx) -> void {
158310
auto comp_full_name = ecsact::meta::decl_full_name(comp_id);
159311
auto comp_name = ecsact::meta::component_name(comp_id);
160312
auto comp_pascal_name = ecsact_decl_name_to_pascal(comp_name);
313+
auto comp_ustruct_name = ecsact_ustruct_name(comp_id);
161314

162315
block(
163316
ctx,
164317
std::format(
165-
"void U{}EcsactRunnerSubsystem::Init{}_Implementation()",
318+
"void U{0}EcsactRunnerSubsystem::Init{1}_Implementation"
319+
"(int32 Entity, {2} {1})",
166320
package_pascal_name,
167-
comp_pascal_name
321+
comp_pascal_name,
322+
comp_ustruct_name
168323
),
169324
[&] {
170325

0 commit comments

Comments
 (0)