@@ -101,8 +101,8 @@ static auto write_context_get_decl(
101
101
std::string_view sys_like_full_name,
102
102
const std::set<ecsact_component_like_id>& gettable_components
103
103
) -> void {
104
- ctx.writef (" template<typename T>\n " );
105
- block (ctx, " auto get() -> T" , [&] {
104
+ ctx.writef (" template<typename T, typename... AssocFields >\n " );
105
+ block (ctx, " auto get(AssocFields&&... assoc_fields ) -> T" , [&] {
106
106
write_context_method_error_body (
107
107
ctx,
108
108
std::format (
@@ -121,18 +121,24 @@ static auto write_context_update_decl(
121
121
std::string_view sys_like_full_name,
122
122
const std::set<ecsact_component_like_id>& updatable_components
123
123
) -> void {
124
- ctx.writef (" template<typename T>\n " );
125
- block (ctx, " auto update(const T& updated_component) -> void" , [&] {
126
- write_context_method_error_body (
127
- ctx,
128
- std::format (
129
- " {} context.update<T> may only be called with a component writable by "
130
- " the system. Did you forget to add readwrite capabilities?" ,
131
- sys_like_full_name
132
- ),
133
- updatable_components
134
- );
135
- });
124
+ ctx.writef (" template<typename T, typename... AssocFields>\n " );
125
+ block (
126
+ ctx,
127
+ " auto update(const T& updated_component, AssocFields&&... assoc_fields) -> "
128
+ " void" ,
129
+ [&] {
130
+ write_context_method_error_body (
131
+ ctx,
132
+ std::format (
133
+ " {} context.update<T> may only be called with a component writable "
134
+ " by "
135
+ " the system. Did you forget to add readwrite capabilities?" ,
136
+ sys_like_full_name
137
+ ),
138
+ updatable_components
139
+ );
140
+ }
141
+ );
136
142
ctx.writef (" \n\n " );
137
143
}
138
144
@@ -176,8 +182,8 @@ static auto write_context_remove_decl(
176
182
std::string_view sys_like_full_name,
177
183
const std::set<ecsact_component_like_id>& removable_components
178
184
) -> void {
179
- ctx.writef (" template<typename T>\n " );
180
- block (ctx, " auto remove() -> void" , [&] {
185
+ ctx.writef (" template<typename T, typename... AssocFields >\n " );
186
+ block (ctx, " auto remove(AssocFields&&... assoc_fields ) -> void" , [&] {
181
187
write_context_method_error_body (
182
188
ctx,
183
189
std::format (
@@ -196,8 +202,8 @@ static auto write_context_has_decl(
196
202
std::string_view sys_like_full_name,
197
203
const std::set<ecsact_component_like_id>& optional_components
198
204
) -> void {
199
- ctx.writef (" template<typename T>\n " );
200
- block (ctx, " auto has() -> bool" , [&] {
205
+ ctx.writef (" template<typename T, typename... AssocFields >\n " );
206
+ block (ctx, " auto has(AssocFields&&... assoc_fields ) -> bool" , [&] {
201
207
write_context_method_error_body (
202
208
ctx,
203
209
std::format (
@@ -216,19 +222,25 @@ static auto write_context_stream_toggle_decl(
216
222
std::string_view sys_like_full_name,
217
223
const std::set<ecsact_component_like_id>& stream_components
218
224
) -> void {
219
- ctx.write (" template<typename T>\n " );
220
- block (ctx, " auto stream_toggle(bool stream_enable) -> void" , [&] {
221
- write_context_method_error_body (
222
- ctx,
223
- std::format (
224
- " {} context.stream_toggle<T> may only be called with stream components "
225
- " declared by the system. Did you forget to add stream toggle "
226
- " capabilities?" ,
227
- sys_like_full_name
228
- ),
229
- stream_components
230
- );
231
- });
225
+ ctx.write (" template<typename T, typename... AssocFields>\n " );
226
+ block (
227
+ ctx,
228
+ " auto stream_toggle(bool stream_enable, AssocFields&&... assoc_fields) -> "
229
+ " void" ,
230
+ [&] {
231
+ write_context_method_error_body (
232
+ ctx,
233
+ std::format (
234
+ " {} context.stream_toggle<T> may only be called with stream "
235
+ " components "
236
+ " declared by the system. Did you forget to add stream toggle "
237
+ " capabilities?" ,
238
+ sys_like_full_name
239
+ ),
240
+ stream_components
241
+ );
242
+ }
243
+ );
232
244
ctx.write (" \n\n " );
233
245
}
234
246
@@ -285,6 +297,77 @@ static void write_context_entity(ecsact::codegen_plugin_context& ctx) {
285
297
ctx.writef (" \n " );
286
298
}
287
299
300
+ template <typename CompositeID>
301
+ static auto assoc_field_ids ( //
302
+ CompositeID compo_id
303
+ ) -> std::vector<ecsact_field_id> {
304
+ auto result = std::vector<ecsact_field_id>{};
305
+ for (auto field_id : ecsact::meta::get_field_ids (compo_id)) {
306
+ auto field_type = ecsact::meta::get_field_type (compo_id, field_id);
307
+
308
+ if (field_type.kind == ECSACT_TYPE_KIND_BUILTIN) {
309
+ if (field_type.type .builtin == ECSACT_ENTITY_TYPE) {
310
+ result.push_back (field_id);
311
+ continue ;
312
+ }
313
+ }
314
+
315
+ if (field_type.kind == ECSACT_TYPE_KIND_FIELD_INDEX) {
316
+ result.push_back (field_id);
317
+ continue ;
318
+ }
319
+ }
320
+ return result;
321
+ }
322
+
323
+ template <typename CompositeID>
324
+ static auto assoc_field_names_only_str (CompositeID compo_id) -> std::string {
325
+ auto result = std::string{};
326
+ for (auto field_id : assoc_field_ids (compo_id)) {
327
+ auto field_type = ecsact::meta::get_field_type (compo_id, field_id);
328
+ auto field_name = ecsact::meta::field_name (compo_id, field_id);
329
+ auto cpp_field_type_name =
330
+ ecsact::cc_lang_support::cpp_field_type_name (field_type);
331
+ result +=
332
+ std::format (" std::forward<{0}>({1}), " , cpp_field_type_name, field_name);
333
+ }
334
+ if (!result.empty ()) {
335
+ result = result.substr (0 , result.size () - 2 ); // strip off ", "
336
+ }
337
+ return result;
338
+ }
339
+
340
+ template <typename CompositeID>
341
+ static auto assoc_field_types_only_str (CompositeID compo_id) -> std::string {
342
+ auto result = std::string{};
343
+ for (auto field_id : assoc_field_ids (compo_id)) {
344
+ auto field_type = ecsact::meta::get_field_type (compo_id, field_id);
345
+ auto cpp_field_type_name =
346
+ ecsact::cc_lang_support::cpp_field_type_name (field_type);
347
+ result += std::format (" {}, " , cpp_field_type_name);
348
+ }
349
+ if (!result.empty ()) {
350
+ result = result.substr (0 , result.size () - 2 ); // strip off ", "
351
+ }
352
+ return result;
353
+ }
354
+
355
+ template <typename CompositeID>
356
+ static auto assoc_fields_str (CompositeID compo_id) -> std::string {
357
+ auto result = std::string{};
358
+ for (auto field_id : assoc_field_ids (compo_id)) {
359
+ auto field_type = ecsact::meta::get_field_type (compo_id, field_id);
360
+ auto field_name = ecsact::meta::field_name (compo_id, field_id);
361
+ auto cpp_field_type_name =
362
+ ecsact::cc_lang_support::cpp_field_type_name (field_type);
363
+ result += std::format (" {}&& {}, " , cpp_field_type_name, field_name);
364
+ }
365
+ if (!result.empty ()) {
366
+ result = result.substr (0 , result.size () - 2 ); // strip off ", "
367
+ }
368
+ return result;
369
+ }
370
+
288
371
static void write_context_get_specialize (
289
372
ecsact::codegen_plugin_context& ctx,
290
373
ecsact_component_like_id comp_id
@@ -294,11 +377,30 @@ static void write_context_get_specialize(
294
377
auto decl_id = ecsact_id_cast<ecsact_decl_id>(comp_id);
295
378
auto full_name = ecsact_meta_decl_full_name (decl_id);
296
379
auto cpp_full_name = cpp_identifier (full_name);
380
+ auto assoc_fields = assoc_fields_str (comp_id);
381
+ auto assoc_field_types_only = assoc_field_types_only_str (comp_id);
382
+ auto assoc_field_names_only = assoc_field_names_only_str (comp_id);
383
+
384
+ if (!assoc_field_types_only.empty ()) {
385
+ assoc_field_types_only = " , " + assoc_field_types_only;
386
+ }
297
387
298
388
block (
299
389
ctx,
300
- std::format (" template<> auto get<{0}>() -> {0}" , cpp_full_name),
301
- [&] { ctx.writef (" return _ctx.get<{}>();" , cpp_full_name); }
390
+ std::format (
391
+ " template<> auto get<{0}{1}>({2}) -> {0}" ,
392
+ cpp_full_name,
393
+ assoc_field_types_only,
394
+ assoc_fields
395
+ ),
396
+ [&] {
397
+ ctx.writef (
398
+ " return _ctx.get<{0}{1}>({2});" ,
399
+ cpp_full_name,
400
+ assoc_field_types_only,
401
+ assoc_field_names_only
402
+ );
403
+ }
302
404
);
303
405
304
406
ctx.writef (" \n " );
@@ -341,14 +443,38 @@ static auto write_context_update_specialize(
341
443
auto decl_id = ecsact_id_cast<ecsact_decl_id>(comp_id);
342
444
auto full_name = ecsact_meta_decl_full_name (decl_id);
343
445
auto cpp_full_name = cpp_identifier (full_name);
446
+ auto assoc_fields = assoc_fields_str (comp_id);
447
+ auto assoc_field_types_only = assoc_field_types_only_str (comp_id);
448
+ auto assoc_field_names_only = assoc_field_names_only_str (comp_id);
449
+
450
+ if (!assoc_field_types_only.empty ()) {
451
+ assoc_field_types_only = " , " + assoc_field_types_only;
452
+ }
453
+
454
+ if (!assoc_fields.empty ()) {
455
+ assoc_fields = " , " + assoc_fields;
456
+ }
457
+
458
+ if (!assoc_field_names_only.empty ()) {
459
+ assoc_field_names_only = " , " + assoc_field_names_only;
460
+ }
344
461
345
462
block (
346
463
ctx,
347
464
std::format (
348
- " template<> auto update<{0}>(const {0}& updated_component) -> void" ,
349
- cpp_full_name
465
+ " template<> auto update<{0}{1}>(const {0}& updated_component{2}) -> "
466
+ " void" ,
467
+ cpp_full_name,
468
+ assoc_field_types_only,
469
+ assoc_fields
350
470
),
351
- [&] { ctx.writef (" _ctx.update<{}>(updated_component);" , cpp_full_name); }
471
+ [&] {
472
+ ctx.writef (
473
+ " _ctx.update<{0}>(updated_component{1});" ,
474
+ cpp_full_name,
475
+ assoc_field_names_only
476
+ );
477
+ }
352
478
);
353
479
ctx.writef (" \n " );
354
480
}
0 commit comments