5
5
#include < map>
6
6
#include < functional>
7
7
#include < optional>
8
+ #include < cassert>
8
9
#include " ecsact/runtime/core.h"
9
10
10
11
namespace ecsact ::core {
@@ -173,10 +174,37 @@ private:
173
174
std::vector<ecsact_action> actions;
174
175
};
175
176
177
+ class any_component_view {
178
+ ecsact_component_id _component_id;
179
+ const void * _component_data;
180
+
181
+ public:
182
+ inline any_component_view (ecsact_component_id id, const void * data)
183
+ : _component_id(id), _component_data(data) {
184
+ }
185
+
186
+ inline any_component_view (const any_component_view&) = default;
187
+ inline ~any_component_view () = default ;
188
+
189
+ template <typename C>
190
+ auto is () const -> bool {
191
+ return _component_id == C::id;
192
+ }
193
+
194
+ template <typename C>
195
+ auto as () const -> const C& {
196
+ assert (is<C>());
197
+ return *static_cast <const C*>(_component_data);
198
+ }
199
+ };
200
+
176
201
template <
177
202
template <class R , class ... Args> typename CallbackContainer = std::function>
178
203
class execution_events_collector {
179
204
public:
205
+ using any_component_callback_t =
206
+ CallbackContainer<void (ecsact_entity_id, any_component_view)>;
207
+
180
208
template <typename C>
181
209
using init_component_callback_t =
182
210
CallbackContainer<void (ecsact_entity_id, const C&)>;
@@ -202,6 +230,7 @@ public:
202
230
auto set_init_callback ( //
203
231
init_component_callback_t <C> callback
204
232
) -> execution_events_collector& {
233
+ _current_init_callback = &execution_events_collector::typed_init_callback;
205
234
_init_cb[C::id] = //
206
235
[callback = std::move (callback)](
207
236
ecsact_entity_id entity,
@@ -219,6 +248,8 @@ public:
219
248
auto set_update_callback ( //
220
249
update_component_callback_t <C> callback
221
250
) -> execution_events_collector& {
251
+ _current_update_callback =
252
+ &execution_events_collector::typed_update_callback;
222
253
_update_cb[C::id] = //
223
254
[callback = std::move (callback)](
224
255
ecsact_entity_id entity,
@@ -236,6 +267,8 @@ public:
236
267
auto set_remove_callback ( //
237
268
remove_component_callback_t <C> callback
238
269
) -> execution_events_collector& {
270
+ _current_remove_callback =
271
+ &execution_events_collector::typed_remove_callback;
239
272
_remove_cb[C::id] = //
240
273
[callback = std::move (callback)](
241
274
ecsact_entity_id entity,
@@ -259,20 +292,77 @@ public:
259
292
return *this ;
260
293
}
261
294
295
+ /* *
296
+ * Set the init callback for when _any_ component is initialized. Overwrites
297
+ * existing init callbacks, including the typed ones.
298
+ *
299
+ * NOTE: You should prefer @ref set_init_callback over this function.
300
+ */
301
+ auto set_any_init_callback ( //
302
+ any_component_callback_t callback
303
+ ) -> execution_events_collector& {
304
+ if constexpr (std::is_convertible_v<any_component_callback_t , bool >) {
305
+ if (!callback) {
306
+ return ;
307
+ }
308
+ }
309
+ _current_init_callback = &execution_events_collector::any_init_callback;
310
+ _any_init_component_cb = callback;
311
+ return *this ;
312
+ }
313
+
314
+ /* *
315
+ * Set the update callback for when _any_ component is updated. Overwrites
316
+ * existing update callbacks, including the typed ones.
317
+ *
318
+ * NOTE: You should prefer @ref set_update_callback over this function.
319
+ */
320
+ auto set_any_update_callback ( //
321
+ any_component_callback_t callback
322
+ ) -> execution_events_collector& {
323
+ if constexpr (std::is_convertible_v<any_component_callback_t , bool >) {
324
+ if (!callback) {
325
+ return ;
326
+ }
327
+ }
328
+ _current_update_callback = &execution_events_collector::any_update_callback;
329
+ _any_update_component_cb = callback;
330
+ return *this ;
331
+ }
332
+
333
+ /* *
334
+ * Set the remove callback for when _any_ component is removed. Overwrites
335
+ * existing remove callbacks, including the typed ones.
336
+ *
337
+ * NOTE: You should prefer @ref set_remove_callback over this function.
338
+ */
339
+ auto set_any_remove_callback ( //
340
+ any_component_callback_t callback
341
+ ) -> execution_events_collector& {
342
+ if constexpr (std::is_convertible_v<any_component_callback_t , bool >) {
343
+ if (!callback) {
344
+ return ;
345
+ }
346
+ }
347
+ _current_remove_callback = &execution_events_collector::any_remove_callback;
348
+ _any_remove_component_cb = callback;
349
+ return *this ;
350
+ }
351
+
262
352
auto c () const -> const ecsact_execution_events_collector {
263
353
auto evc = ecsact_execution_events_collector{};
264
354
auto user_data =
265
355
static_cast <void *>(const_cast <execution_events_collector*>(this ));
266
356
267
- if (!_init_cb. empty () ) {
357
+ if (_current_init_callback != nullptr ) {
268
358
evc.init_callback = &execution_events_collector::init_callback;
269
359
evc.init_callback_user_data = user_data;
270
360
}
271
- if (!_update_cb. empty () ) {
361
+ if (_current_update_callback != nullptr ) {
272
362
evc.update_callback = &execution_events_collector::update_callback;
273
363
evc.update_callback_user_data = user_data;
274
364
}
275
- if (!_remove_cb. empty () ) {
365
+ if (_current_remove_callback != nullptr ) {
276
366
evc.remove_callback = &execution_events_collector::remove_callback;
277
367
evc.remove_callback_user_data = user_data;
278
368
}
@@ -291,6 +381,9 @@ public:
291
381
}
292
382
293
383
auto clear () -> void {
384
+ _current_init_callback = nullptr ;
385
+ _current_remove_callback = nullptr ;
386
+ _current_update_callback = nullptr ;
294
387
_init_cb.clear ();
295
388
_update_cb.clear ();
296
389
_remove_cb.clear ();
@@ -299,34 +392,129 @@ public:
299
392
}
300
393
301
394
auto empty () const noexcept -> bool {
302
- return _init_cb.empty () && _update_cb.empty () && _remove_cb.empty () &&
303
- !_entity_created_cb.has_value () && !_entity_destroyed_cb.has_value ();
395
+ return _current_init_callback == nullptr &&
396
+ _current_remove_callback == nullptr &&
397
+ _current_update_callback == nullptr && !_entity_created_cb.has_value () &&
398
+ !_entity_destroyed_cb.has_value ();
304
399
}
305
400
306
401
private:
307
402
// std::function is used here explicitly for type erasure
308
403
using _component_cb_t =
309
404
std::function<void (ecsact_entity_id, ecsact_component_id, const void *)>;
310
405
using _component_cb_map_t = std::map<ecsact_component_id, _component_cb_t >;
406
+
407
+ void (execution_events_collector::*_current_init_callback)(
408
+ ecsact_entity_id entity_id,
409
+ ecsact_component_id component_id,
410
+ const void * component_data
411
+ ) = nullptr ;
412
+
413
+ void (execution_events_collector::*_current_update_callback)(
414
+ ecsact_entity_id entity_id,
415
+ ecsact_component_id component_id,
416
+ const void * component_data
417
+ ) = nullptr ;
418
+
419
+ void (execution_events_collector::*_current_remove_callback)(
420
+ ecsact_entity_id entity_id,
421
+ ecsact_component_id component_id,
422
+ const void * component_data
423
+ ) = nullptr ;
424
+
425
+ any_component_callback_t _any_init_component_cb;
426
+ any_component_callback_t _any_update_component_cb;
427
+ any_component_callback_t _any_remove_component_cb;
428
+
311
429
_component_cb_map_t _init_cb;
312
430
_component_cb_map_t _update_cb;
313
431
_component_cb_map_t _remove_cb;
314
432
315
433
std::optional<entity_created_callback_t > _entity_created_cb;
316
434
std::optional<entity_destroyed_callback_t > _entity_destroyed_cb;
317
435
436
+ auto typed_init_callback (
437
+ ecsact_entity_id entity_id,
438
+ ecsact_component_id component_id,
439
+ const void * component_data
440
+ ) -> void {
441
+ auto itr = _init_cb.find (component_id);
442
+ if (itr != _init_cb.end ()) {
443
+ itr->second (entity_id, component_id, component_data);
444
+ }
445
+ }
446
+
447
+ auto any_init_callback (
448
+ ecsact_entity_id entity_id,
449
+ ecsact_component_id component_id,
450
+ const void * component_data
451
+ ) -> void {
452
+ _any_init_component_cb (
453
+ entity_id,
454
+ any_component_view{component_id, component_data}
455
+ );
456
+ }
457
+
458
+ auto typed_update_callback (
459
+ ecsact_entity_id entity_id,
460
+ ecsact_component_id component_id,
461
+ const void * component_data
462
+ ) -> void {
463
+ auto itr = _update_cb.find (component_id);
464
+ if (itr != _update_cb.end ()) {
465
+ itr->second (entity_id, component_id, component_data);
466
+ }
467
+ }
468
+
469
+ auto any_update_callback (
470
+ ecsact_entity_id entity_id,
471
+ ecsact_component_id component_id,
472
+ const void * component_data
473
+ ) -> void {
474
+ _any_update_component_cb (
475
+ entity_id,
476
+ any_component_view{component_id, component_data}
477
+ );
478
+ }
479
+
480
+ auto typed_remove_callback (
481
+ ecsact_entity_id entity_id,
482
+ ecsact_component_id component_id,
483
+ const void * component_data
484
+ ) -> void {
485
+ auto itr = _remove_cb.find (component_id);
486
+ if (itr != _remove_cb.end ()) {
487
+ itr->second (entity_id, component_id, component_data);
488
+ }
489
+ }
490
+
491
+ auto any_remove_callback (
492
+ ecsact_entity_id entity_id,
493
+ ecsact_component_id component_id,
494
+ const void * component_data
495
+ ) -> void {
496
+ _any_remove_component_cb (
497
+ entity_id,
498
+ any_component_view{component_id, component_data}
499
+ );
500
+ }
501
+
318
502
static void init_callback (
319
- ecsact_event event ,
503
+ ecsact_event,
320
504
ecsact_entity_id entity_id,
321
505
ecsact_component_id component_id,
322
506
const void * component_data,
323
507
void * callback_user_data
324
508
) {
325
509
auto self = static_cast <execution_events_collector*>(callback_user_data);
326
-
327
- auto itr = self->_init_cb .find (component_id);
328
- if (itr != self->_init_cb .end ()) {
329
- itr->second (entity_id, component_id, component_data);
510
+ if (self->_current_init_callback ) {
511
+ std::invoke (
512
+ self->_current_init_callback ,
513
+ *self,
514
+ entity_id,
515
+ component_id,
516
+ component_data
517
+ );
330
518
}
331
519
}
332
520
@@ -338,10 +526,14 @@ private:
338
526
void * callback_user_data
339
527
) {
340
528
auto self = static_cast <execution_events_collector*>(callback_user_data);
341
-
342
- auto itr = self->_update_cb .find (component_id);
343
- if (itr != self->_update_cb .end ()) {
344
- itr->second (entity_id, component_id, component_data);
529
+ if (self->_current_update_callback ) {
530
+ std::invoke (
531
+ self->_current_update_callback ,
532
+ *self,
533
+ entity_id,
534
+ component_id,
535
+ component_data
536
+ );
345
537
}
346
538
}
347
539
@@ -353,10 +545,14 @@ private:
353
545
void * callback_user_data
354
546
) {
355
547
auto self = static_cast <execution_events_collector*>(callback_user_data);
356
-
357
- auto itr = self->_remove_cb .find (component_id);
358
- if (itr != self->_remove_cb .end ()) {
359
- itr->second (entity_id, component_id, component_data);
548
+ if (self->_current_remove_callback ) {
549
+ std::invoke (
550
+ self->_current_remove_callback ,
551
+ *self,
552
+ entity_id,
553
+ component_id,
554
+ component_data
555
+ );
360
556
}
361
557
}
362
558
0 commit comments