Unravel Engine C++ Reference
Loading...
Searching...
No Matches
script_glue.cpp
Go to the documentation of this file.
1#include "monopp/mono_array.h"
2#include "script_interop.h"
3#include "script_system.h"
4#include <engine/ecs/ecs.h>
5#include <engine/events.h>
6
7#include <engine/engine.h>
8#include <monopp/mono_exception.h>
9#include <monopp/mono_internal_call.h>
10#include <monopp/mono_jit.h>
11#include <monort/mono_pod_wrapper.h>
12#include <monort/monort.h>
13
16#include <engine/input/input.h>
27#include <graphics/debugdraw.h>
28
29// RmlUi includes
30#include <RmlUi/Core/Element.h>
31#include <RmlUi/Core/ElementDocument.h>
32#include <RmlUi/Core/Variant.h>
33#include <RmlUi/Core/EventListener.h>
34#include <RmlUi/Core/Event.h>
35
36// Mono includes for method invocation
37#include <monopp/mono_method_invoker.h>
38
41#include <logging/logging.h>
42#include <seq/seq.h>
43#include <string_utils/utils.h>
44
45namespace unravel
46{
47namespace
48{
49
50auto get_material_properties(const material::sptr& material) -> mono::managed_interface::material_properties
51{
52 using converter = mono::managed_interface::converter;
53
55
56 if(material->is<pbr_material>())
57 {
58 const auto pbr = std::static_pointer_cast<pbr_material>(material);
59 props.base_color = converter::convert<math::color, mono::managed_interface::color>(pbr->get_base_color());
60 props.emissive_color =
61 converter::convert<math::color, mono::managed_interface::color>(pbr->get_emissive_color());
62 props.tiling = converter::convert<math::vec2, mono::managed_interface::vector2>(pbr->get_tiling());
63 props.roughness = pbr->get_roughness();
64 props.metalness = pbr->get_metalness();
65 props.bumpiness = pbr->get_bumpiness();
66 props.valid = true;
67 }
68
69 return props;
70}
71
72void set_material_properties(const material::sptr& material, const mono::managed_interface::material_properties& props)
73{
74 using converter = mono::managed_interface::converter;
75
76 if(material->is<pbr_material>())
77 {
78 auto pbr = std::static_pointer_cast<pbr_material>(material);
79 auto base_color = converter::convert<mono::managed_interface::color, math::color>(props.base_color);
80 pbr->set_base_color(base_color);
81
82 auto emissive_color = converter::convert<mono::managed_interface::color, math::color>(props.emissive_color);
83 pbr->set_emissive_color(emissive_color);
84
85 auto tiling = converter::convert<mono::managed_interface::vector2, math::vec2>(props.tiling);
86 pbr->set_tiling(tiling);
87
88 pbr->set_metalness(props.metalness);
89
90 pbr->set_bumpiness(props.bumpiness);
91 }
92}
93
94struct mono_asset
95{
96 virtual auto get_asset_uuid(const hpp::uuid& uid) const -> hpp::uuid = 0;
97 virtual auto get_asset_uuid(const std::string& key) const -> hpp::uuid = 0;
98};
99
100template<typename T>
101struct mono_asset_impl : mono_asset
102{
103 auto get_asset_uuid(const hpp::uuid& uid) const -> hpp::uuid override
104 {
105 auto& ctx = engine::context();
106 auto& am = ctx.get_cached<asset_manager>();
107
108 auto asset = am.get_asset<T>(uid);
109 return asset.uid();
110 }
111
112 auto get_asset_uuid(const std::string& key) const -> hpp::uuid override
113 {
114 auto& ctx = engine::context();
115 auto& am = ctx.get_cached<asset_manager>();
116
117 auto asset = am.get_asset<T>(key);
118 return asset.uid();
119 }
120};
121
122auto get_mono_asset(size_t type_hash) -> const mono_asset*
123{
124 // clang-format off
125 static std::map<size_t, std::shared_ptr<mono_asset>> reg =
126 {
127 {mono::mono_type::get_hash("Unravel.Core.Texture"), std::make_shared<mono_asset_impl<gfx::texture>>()},
128 {mono::mono_type::get_hash("Unravel.Core.Material"), std::make_shared<mono_asset_impl<material>>()},
129 {mono::mono_type::get_hash("Unravel.Core.Mesh"), std::make_shared<mono_asset_impl<mesh>>()},
130 {mono::mono_type::get_hash("Unravel.Core.AnimationClip"), std::make_shared<mono_asset_impl<animation_clip>>()},
131 {mono::mono_type::get_hash("Unravel.Core.Prefab"), std::make_shared<mono_asset_impl<prefab>>()},
132 {mono::mono_type::get_hash("Unravel.Core.Scene"), std::make_shared<mono_asset_impl<scene_prefab>>()},
133 {mono::mono_type::get_hash("Unravel.Core.PhysicsMaterial"), std::make_shared<mono_asset_impl<physics_material>>()},
134 {mono::mono_type::get_hash("Unravel.Core.AudioClip"), std::make_shared<mono_asset_impl<audio_clip>>()},
135 {mono::mono_type::get_hash("Unravel.Core.Font"), std::make_shared<mono_asset_impl<font>>()}
136 };
137 // clang-format on
138
139 auto it = reg.find(type_hash);
140 if(it != reg.end())
141 {
142 return it->second.get();
143 }
144 static const mono_asset* empty{};
145 return empty;
146};
147
148auto get_entity_from_id(entt::entity id) -> entt::handle
149{
150 if(id == entt::entity(0))
151 {
152 return {};
153 }
154
155 auto& ctx = engine::context();
156 auto& ec = ctx.get_cached<ecs>();
157
158 return ec.get_scene().create_handle(id);
159}
160
161void raise_invalid_entity_exception()
162{
163 mono::raise_exception("System", "Exception", "Entity is invalid.");
164}
165
166template<typename T>
167void raise_missing_component_exception()
168{
169 mono::raise_exception("System",
170 "Exception",
171 fmt::format("Entity does not have component of type {}.", hpp::type_name_str<T>()));
172}
173
174template<typename T>
175auto safe_get_component(entt::entity id) -> T*
176{
177 auto e = get_entity_from_id(id);
178 if(!e)
179 {
180 raise_invalid_entity_exception();
181 return nullptr;
182 }
183 auto comp = e.try_get<T>();
184
185 if(!comp)
186 {
187 raise_missing_component_exception<T>();
188 return nullptr;
189 }
190
191 return comp;
192}
193
194void internal_m2n_load_scene(const std::string& key)
195{
196 auto delay = seq::delay(1ms);
197 delay.on_end.connect(
198 [key]()
199 {
200 auto& ctx = engine::context();
201 auto& ec = ctx.get_cached<ecs>();
202 auto& am = ctx.get_cached<asset_manager>();
203
204 ec.get_scene().load_from(am.get_asset<scene_prefab>(key));
205 });
206
207 seq::start(delay, "script");
208}
209
210void internal_m2n_load_scene_uid(const hpp::uuid& uid)
211{
212 auto delay = seq::delay(1ms);
213 delay.on_end.connect(
214 [uid]()
215 {
216 auto& ctx = engine::context();
217 auto& ec = ctx.get_cached<ecs>();
218 auto& am = ctx.get_cached<asset_manager>();
219
220 ec.get_scene().load_from(am.get_asset<scene_prefab>(uid));
221 });
222
223 seq::start(delay, "script");
224}
225
226void internal_m2n_create_scene(const mono::mono_object& this_ptr)
227{
228 mono::ignore(this_ptr);
229}
230
231void internal_m2n_destroy_scene(const mono::mono_object& this_ptr)
232{
233 mono::ignore(this_ptr);
234}
235
236auto internal_m2n_create_entity(const std::string& tag) -> entt::entity
237{
238 auto& ctx = engine::context();
239 auto& ec = ctx.get_cached<ecs>();
240
241 auto e = ec.get_scene().create_entity(tag);
242
243 return e.entity();
244}
245
246auto internal_m2n_create_entity_from_prefab_uid(const hpp::uuid& uid) -> entt::entity
247{
248 auto& ctx = engine::context();
249 auto& ec = ctx.get_cached<ecs>();
250 auto& am = ctx.get_cached<asset_manager>();
251
252 auto pfb = am.get_asset<prefab>(uid);
253 auto e = ec.get_scene().instantiate(pfb);
254
255 return e.entity();
256}
257
258auto internal_m2n_create_entity_from_prefab_key(const std::string& key) -> entt::entity
259{
260 auto& ctx = engine::context();
261 auto& ec = ctx.get_cached<ecs>();
262 auto& am = ctx.get_cached<asset_manager>();
263
264 auto pfb = am.get_asset<prefab>(key);
265 auto e = ec.get_scene().instantiate(pfb);
266
267 return e.entity();
268}
269
270auto internal_m2n_clone_entity(entt::entity id) -> entt::entity
271{
272 auto e = get_entity_from_id(id);
273 if(e)
274 {
275 auto& ctx = engine::context();
276 auto& ec = ctx.get_cached<ecs>();
277
278 auto cloned = ec.get_scene().clone_entity(e);
279 return cloned.entity();
280 }
281
282 entt::handle invalid;
283 return invalid.entity();
284}
285
286auto internal_m2n_destroy_entity_immediate(entt::entity id) -> bool
287{
288 auto e = get_entity_from_id(id);
289 if(e)
290 {
291 e.destroy();
292 return true;
293 }
294 return false;
295}
296
297auto internal_m2n_destroy_entity(entt::entity id, float seconds) -> bool
298{
299 seconds = std::max(0.0001f, seconds);
300
301 delta_t secs(seconds);
302 auto dur = std::chrono::duration_cast<seq::duration_t>(secs);
303
304 auto delay = seq::delay(dur);
305 delay.on_end.connect(
306 [id]()
307 {
308 internal_m2n_destroy_entity_immediate(id);
309 });
310
311 seq::start(delay, "script");
312
313 return true;
314}
315
316auto internal_m2n_is_entity_valid(entt::entity id) -> bool
317{
318 auto e = get_entity_from_id(id);
319 bool valid = e.valid();
320 return valid;
321}
322
323auto internal_m2n_find_entity_by_name(const std::string& name) -> entt::entity
324{
325 auto& ctx = engine::context();
326 auto& ec = ctx.get_cached<ecs>();
327 auto& scn = ec.get_scene();
328 auto& registry = *scn.registry;
329
330 auto view = registry.view<tag_component>();
331
332 for(const auto& e : view)
333 {
334 if(registry.get<tag_component>(e).name == name)
335 {
336 return e;
337 }
338 }
339
340 const entt::handle invalid;
341 return invalid.entity();
342}
343
344auto internal_m2n_find_entities_by_name(const std::string& name) -> hpp::small_vector<entt::entity>
345{
346 auto& ctx = engine::context();
347 auto& ec = ctx.get_cached<ecs>();
348 auto& scn = ec.get_scene();
349 auto& registry = *scn.registry;
350
351 auto view = registry.view<tag_component>();
352
353 hpp::small_vector<entt::entity> result;
354 for(const auto& e : view)
355 {
356 if(registry.get<tag_component>(e).name == name)
357 {
358 result.emplace_back(e);
359 }
360 }
361
362 return result;
363}
364
365auto internal_m2n_find_entity_by_tag(const std::string& tag) -> entt::entity
366{
367 auto& ctx = engine::context();
368 auto& ec = ctx.get_cached<ecs>();
369 auto& scn = ec.get_scene();
370 auto& registry = *scn.registry;
371
372 auto view = registry.view<tag_component>();
373
374 for(const auto& e : view)
375 {
376 if(registry.get<tag_component>(e).tag == tag)
377 {
378 return e;
379 }
380 }
381
382 const entt::handle invalid;
383 return invalid.entity();
384}
385
386auto internal_m2n_find_entities_by_tag(const std::string& tag) -> hpp::small_vector<entt::entity>
387{
388 auto& ctx = engine::context();
389 auto& ec = ctx.get_cached<ecs>();
390 auto& scn = ec.get_scene();
391 auto& registry = *scn.registry;
392
393 auto view = registry.view<tag_component>();
394
395 hpp::small_vector<entt::entity> result;
396 for(const auto& e : view)
397 {
398 if(registry.get<tag_component>(e).tag == tag)
399 {
400 result.emplace_back(e);
401 }
402 }
403
404 return result;
405}
406
407struct native_comp_lut
408{
409 auto is_valid() const -> bool
410 {
411 return add_native != nullptr;
412 }
413 std::function<bool(size_t type_hash, entt::handle e)> add_native;
414 std::function<bool(size_t type_hash, entt::handle e)> has_native;
415 std::function<bool(size_t type_hash, entt::handle e)> remove_native;
416
417 static auto get_registry() -> std::unordered_map<size_t, native_comp_lut>&
418 {
419 static std::unordered_map<size_t, native_comp_lut> lut;
420 return lut;
421 }
422
423 static auto get_action_table(size_t type_hash) -> const native_comp_lut&
424 {
425 const auto& registry = get_registry();
426 auto it = registry.find(type_hash);
427 if(it != registry.end())
428 {
429 return it->second;
430 }
431
432 static const native_comp_lut empty;
433 return empty;
434 }
435
436 template<typename T>
437 static auto register_native_component(const std::string& name)
438 {
439 size_t hash = mono::mono_type::get_hash(name);
440 native_comp_lut lut;
441 lut.add_native = [hash](size_t type_hash, entt::handle e)
442 {
443 if(type_hash == hash)
444 {
445 auto& native = e.get_or_emplace<T>();
446 return true;
447 }
448
449 return false;
450 };
451
452 lut.has_native = [hash](size_t type_hash, entt::handle e)
453 {
454 if(type_hash == hash)
455 {
456 return e.all_of<T>();
457 }
458
459 return false;
460 };
461
462 lut.remove_native = [hash](size_t type_hash, entt::handle e)
463 {
464 if(type_hash == hash)
465 {
466 return e.remove<T>() > 0;
467 }
468
469 return false;
470 };
471
472 get_registry()[hash] = lut;
473 }
474};
475
476int register_componetns = []()
477{
478 native_comp_lut::register_native_component<transform_component>("Unravel.Core.TransformComponent");
479 native_comp_lut::register_native_component<id_component>("Unravel.Core.IdComponent");
480 native_comp_lut::register_native_component<model_component>("Unravel.Core.ModelComponent");
481 native_comp_lut::register_native_component<camera_component>("Unravel.Core.CameraComponent");
482 native_comp_lut::register_native_component<light_component>("Unravel.Core.LightComponent");
483 native_comp_lut::register_native_component<reflection_probe_component>("Unravel.Core.ReflectionProbeComponent");
484 native_comp_lut::register_native_component<physics_component>("Unravel.Core.PhysicsComponent");
485 native_comp_lut::register_native_component<animation_component>("Unravel.Core.AnimationComponent");
486 native_comp_lut::register_native_component<audio_listener_component>("Unravel.Core.AudioListenerComponent");
487 native_comp_lut::register_native_component<audio_source_component>("Unravel.Core.AudioSourceComponent");
488 native_comp_lut::register_native_component<bone_component>("Unravel.Core.BoneComponent");
489 native_comp_lut::register_native_component<submesh_component>("Unravel.Core.SubmeshComponent");
490 native_comp_lut::register_native_component<text_component>("Unravel.Core.TextComponent");
491 native_comp_lut::register_native_component<particle_emitter_component>("Unravel.Core.ParticleEmitterComponent");
492 native_comp_lut::register_native_component<ui_document_component>("Unravel.Core.UIDocumentComponent");
493
494 return 0;
495}();
496
497auto internal_add_native_component(const mono::mono_type& type, entt::handle e, script_component& script_comp)
498 -> mono::mono_object
499{
500 // TODO OPTIMIZE
501
502 const auto& type_hash = type.get_hash();
503 bool add = false;
504
505 const auto& lut = native_comp_lut::get_action_table(type_hash);
506 if(lut.is_valid())
507 {
508 add = lut.add_native(type_hash, e);
509 }
510
511 if(add)
512 {
513 auto comp = script_comp.get_native_component(type);
514
515 if(!comp.scoped)
516 {
517 comp = script_comp.add_native_component(type);
518 }
519 return static_cast<mono::mono_object&>(comp.scoped->object);
520 }
521
522 return {};
523}
524
525auto internal_get_native_component_impl(const mono::mono_type& type,
526 entt::handle e,
527 script_component& script_comp,
528 bool exists) -> mono::mono_object
529{
530 auto comp = script_comp.get_native_component(type);
531 if(exists)
532 {
533 if(!comp.scoped)
534 {
535 comp = script_comp.add_native_component(type);
536 }
537 return static_cast<mono::mono_object&>(comp.scoped->object);
538 }
539
540 if(comp.scoped)
541 {
542 script_comp.remove_native_component(comp.scoped->object);
543 }
544
545 return {};
546}
547
548auto internal_get_native_component(const mono::mono_type& type, entt::handle e, script_component& script_comp)
549 -> mono::mono_object
550{
551 const auto& type_hash = type.get_hash();
552
553 // TODO OPTIMIZE
554 bool native = false;
555 bool has = false;
556
557 const auto& lut = native_comp_lut::get_action_table(type_hash);
558 if(lut.is_valid())
559 {
560 has = lut.has_native(type_hash, e);
561 native = true;
562 }
563
564 if(native)
565 {
566 return internal_get_native_component_impl(type, e, script_comp, has);
567 }
568
569 return {};
570}
571
572auto internal_remove_native_component(const mono::mono_object& obj, entt::handle e, script_component& script_comp)
573 -> bool
574{
575 const auto& type = obj.get_type();
576 const auto& type_hash = type.get_hash();
577
578 // TODO OPTIMIZE
579
580 bool removed = false;
581 const auto& lut = native_comp_lut::get_action_table(type_hash);
582 if(lut.is_valid())
583 {
584 removed = lut.remove_native(type_hash, e);
585 }
586
587 if(removed)
588 {
589 return script_comp.remove_native_component(obj);
590 }
591
592 return false;
593}
594
595auto internal_remove_native_component(const mono::mono_type& type, entt::handle e, script_component& script_comp)
596 -> bool
597{
598 const auto& type_hash = type.get_hash();
599
600 // TODO OPTIMIZE
601
602 bool removed = false;
603 const auto& lut = native_comp_lut::get_action_table(type_hash);
604 if(lut.is_valid())
605 {
606 removed = lut.remove_native(type_hash, e);
607 }
608
609 if(removed)
610 {
611 return script_comp.remove_native_component(type);
612 }
613
614 return false;
615}
616
617auto internal_m2n_add_component(entt::entity id, const mono::mono_type& type) -> mono::mono_object
618{
619 auto e = get_entity_from_id(id);
620 if(!e)
621 {
622 raise_invalid_entity_exception();
623 return {};
624 }
625 auto& script_comp = e.get_or_emplace<script_component>();
626
627 if(auto native_comp = internal_add_native_component(type, e, script_comp))
628 {
629 return native_comp;
630 }
631
632 auto component = script_comp.add_script_component(type);
633 return static_cast<mono::mono_object&>(component.scoped->object);
634}
635
636auto internal_m2n_get_component(entt::entity id, const mono::mono_type& type) -> mono::mono_object
637{
638 auto e = get_entity_from_id(id);
639 if(!e)
640 {
641 raise_invalid_entity_exception();
642 return {};
643 }
644
645 auto& script_comp = e.get_or_emplace<script_component>();
646
647 if(auto native_comp = internal_get_native_component(type, e, script_comp))
648 {
649 return native_comp;
650 }
651
652 auto component = script_comp.get_script_component(type);
653
654 if(component.scoped)
655 {
656 return static_cast<mono::mono_object&>(component.scoped->object);
657 }
658
659 return {};
660}
661
662
663auto internal_m2n_get_components_impl(entt::entity id, const mono::mono_type& type) -> std::vector<mono::mono_object>
664{
665 auto e = get_entity_from_id(id);
666 if(!e)
667 {
668 raise_invalid_entity_exception();
669 return {};
670 }
671
672 auto& script_comp = e.get_or_emplace<script_component>();
673
674 if(auto native_comp = internal_get_native_component(type, e, script_comp))
675 {
676 return {native_comp};
677 }
678
679 return script_comp.get_script_components(type);
680}
681
682auto internal_m2n_get_components(entt::entity id, const mono::mono_type& type) -> mono::mono_array<mono::mono_object>
683{
684 auto components = internal_m2n_get_components_impl(id, type);
685 return mono::mono_array<mono::mono_object>(components, type);
686}
687
688auto internal_m2n_get_component_in_children(entt::entity id, const mono::mono_type& type) -> mono::mono_object
689{
690 auto comp = internal_m2n_get_component(id, type);
691 if(comp.valid())
692 {
693 return comp;
694 }
695 if(auto comp = safe_get_component<transform_component>(id))
696 {
697 const auto& children = comp->get_children();
698 for(const auto& child : children)
699 {
700 if(auto result = internal_m2n_get_component(child, type))
701 {
702 return result;
703 }
704 }
705 }
706
707 return {};
708}
709
710auto internal_m2n_get_components_in_children(entt::entity id, const mono::mono_type& type)
711 -> mono::mono_array<mono::mono_object>
712{
713 auto components = internal_m2n_get_components_impl(id, type);
714 if(auto comp = safe_get_component<transform_component>(id))
715 {
716 const auto& children = comp->get_children();
717 for(const auto& child : children)
718 {
719 auto child_components = internal_m2n_get_components_impl(child, type);
720 std::move(child_components.begin(), child_components.end(), std::back_inserter(components));
721 }
722 }
723 return mono::mono_array<mono::mono_object>(components, type);
724}
725
726auto internal_m2n_get_transform_component(entt::entity id, const mono::mono_type& type) -> mono::mono_object
727{
728 auto e = get_entity_from_id(id);
729 if(!e)
730 {
731 raise_invalid_entity_exception();
732 return {};
733 }
734
735 auto& script_comp = e.get_or_emplace<script_component>();
736 return internal_get_native_component_impl(type, e, script_comp, true);
737}
738
739auto internal_m2n_get_name(entt::entity id) -> const std::string&
740{
741 if(auto comp = safe_get_component<tag_component>(id))
742 {
743 return comp->name;
744 }
745
746 static const std::string empty;
747 return empty;
748}
749
750void internal_m2n_set_name(entt::entity id, const std::string& name)
751{
752 if(auto comp = safe_get_component<tag_component>(id))
753 {
754 comp->name = name;
755 }
756}
757
758auto internal_m2n_get_tag(entt::entity id) -> const std::string&
759{
760 if(auto comp = safe_get_component<tag_component>(id))
761 {
762 return comp->tag;
763 }
764
765 static const std::string empty;
766 return empty;
767}
768
769void internal_m2n_set_tag(entt::entity id, const std::string& tag)
770{
771 if(auto comp = safe_get_component<tag_component>(id))
772 {
773 comp->tag = tag;
774 }
775}
776
777auto internal_m2n_get_layers(entt::entity id) -> int
778{
779 if(auto comp = safe_get_component<layer_component>(id))
780 {
781 return comp->layers.mask;
782 }
783
785}
786
787void internal_m2n_set_layers(entt::entity id, int mask)
788{
789 if(auto comp = safe_get_component<layer_component>(id))
790 {
791 comp->layers.mask = mask;
792 }
793}
794
795auto internal_m2n_get_active_global(entt::entity id) -> bool
796{
797 if(auto comp = safe_get_component<transform_component>(id))
798 {
799 return comp->is_active_global();
800 }
801
802 return false;
803}
804
805auto internal_m2n_get_active_local(entt::entity id) -> bool
806{
807 if(auto comp = safe_get_component<transform_component>(id))
808 {
809 return comp->is_active();
810 }
811
812 return false;
813}
814
815void internal_m2n_set_active_local(entt::entity id, bool active)
816{
817 if(auto comp = safe_get_component<transform_component>(id))
818 {
819 comp->set_active(active);
820 }
821}
822
823auto internal_m2n_has_component(entt::entity id, const mono::mono_type& type) -> bool
824{
825 auto comp = internal_m2n_get_component(id, type);
826
827 return comp.valid();
828}
829
830auto internal_m2n_find_entities_with_component(const mono::mono_type& component_type) -> hpp::small_vector<entt::entity>
831{
832 auto& ctx = engine::context();
833 auto& ec = ctx.get_cached<ecs>();
834 auto& scn = ec.get_scene();
835 auto& registry = *scn.registry;
836
837 hpp::small_vector<entt::entity> result;
838
839 // Iterate through all entities using the storage directly
840 for(auto [entity] : registry.storage<entt::entity>().each())
841 {
842 if(registry.valid(entity))
843 {
844 // Check if entity has the component using the same logic as internal_m2n_has_component
845 auto comp = internal_m2n_get_component(entity, component_type);
846 if(comp.valid())
847 {
848 result.emplace_back(entity);
849 }
850 }
851 }
852
853 return result;
854}
855
856auto internal_m2n_find_entities_with_components(const std::vector<mono::mono_type>& component_types) -> hpp::small_vector<entt::entity>
857{
858 auto& ctx = engine::context();
859 auto& ec = ctx.get_cached<ecs>();
860 auto& scn = ec.get_scene();
861 auto& registry = *scn.registry;
862
863 hpp::small_vector<entt::entity> result;
864
865 if(component_types.empty())
866 {
867 return result;
868 }
869
870 // Iterate through all entities using the storage directly
871 for(auto [entity] : registry.storage<entt::entity>().each())
872 {
873 if(registry.valid(entity))
874 {
875 bool has_all_components = true;
876
877 // Check if entity has all required components
878 for(const auto& component_type : component_types)
879 {
880 auto comp = internal_m2n_get_component(entity, component_type);
881 if(!comp.valid())
882 {
883 has_all_components = false;
884 break;
885 }
886 }
887
888 if(has_all_components)
889 {
890 result.emplace_back(entity);
891 }
892 }
893 }
894
895 return result;
896}
897
898auto internal_m2n_remove_component_instance(entt::entity id, const mono::mono_object& comp) -> bool
899{
900 auto e = get_entity_from_id(id);
901 if(!e)
902 {
903 raise_invalid_entity_exception();
904 return false;
905 }
906 auto& script_comp = e.get_or_emplace<script_component>();
907
908 if(internal_remove_native_component(comp, e, script_comp))
909 {
910 return true;
911 }
912
913 return script_comp.remove_script_component(comp);
914}
915
916auto internal_m2n_remove_component_instance_delay(entt::entity id, const mono::mono_object& comp, float seconds_delay)
917 -> bool
918{
919 delta_t secs(seconds_delay);
920 auto dur = std::chrono::duration_cast<seq::duration_t>(secs);
921
922 auto delay = seq::delay(dur);
923 delay.on_end.connect(
924 [id, comp]()
925 {
926 internal_m2n_remove_component_instance(id, comp);
927 });
928
929 seq::start(delay, "script");
930
931 return true;
932}
933
934auto internal_m2n_remove_component(entt::entity id, const mono::mono_type& type) -> bool
935{
936 auto e = get_entity_from_id(id);
937 if(!e)
938 {
939 raise_invalid_entity_exception();
940 return false;
941 }
942 auto& script_comp = e.get_or_emplace<script_component>();
943
944 if(internal_remove_native_component(type, e, script_comp))
945 {
946 return true;
947 }
948
949 return script_comp.remove_script_component(type);
950}
951
952auto internal_m2n_remove_component_delay(entt::entity id, const mono::mono_type& type, float seconds_delay) -> bool
953{
954 delta_t secs(seconds_delay);
955 auto dur = std::chrono::duration_cast<seq::duration_t>(secs);
956
957 auto delay = seq::delay(dur);
958 delay.on_end.connect(
959 [id, type]()
960 {
961 internal_m2n_remove_component(id, type);
962 });
963
964 seq::start(delay, "script");
965
966 return true;
967}
968
969//-------------------------------------------------------------------------
970/*
971
972 _ ____ _____
973 | | / __ \ / ____|
974 | | | | | | | __
975 | | | | | | | |_ |
976 | |___| |__| | |__| |
977 |______\____/ \_____|
978
979
980*/
981//-------------------------------------------------------------------------
982
983void internal_m2n_log_trace(const std::string& message, const std::string& func, const std::string& file, int line)
984{
985 APPLOG_TRACE_LOC(file.c_str(), line, func.c_str(), message);
986}
987
988void internal_m2n_log_info(const std::string& message, const std::string& func, const std::string& file, int line)
989{
990 APPLOG_INFO_LOC(file.c_str(), line, func.c_str(), message);
991}
992
993void internal_m2n_log_warning(const std::string& message, const std::string& func, const std::string& file, int line)
994{
995 APPLOG_WARNING_LOC(file.c_str(), line, func.c_str(), message);
996}
997
998void internal_m2n_log_error(const std::string& message, const std::string& func, const std::string& file, int line)
999{
1000 APPLOG_ERROR_LOC(file.c_str(), line, func.c_str(), message);
1001}
1002
1003//-------------------------------------------------------------------------
1004
1005void internal_m2n_application_quit()
1006{
1007 auto delay = seq::delay(1ms);
1008 delay.on_end.connect(
1009 []()
1010 {
1011 auto& ctx = engine::context();
1012 auto& ev = ctx.get_cached<events>();
1013 ev.set_play_mode(ctx, false);
1014 });
1015
1016 seq::start(delay, "script");
1017}
1018
1019void internal_m2n_set_time_scale(float scale)
1020{
1021 auto& ctx = engine::context();
1022 auto& sim = ctx.get_cached<simulation>();
1023 sim.set_time_scale(scale);
1024}
1025
1026//-------------------------------------------------------------------------
1027/*
1028
1029 _______ _____ _ _ _____ ______ ____ _____ __ __
1030 |__ __| __ \ /\ | \ | |/ ____| ____/ __ \| __ \| \/ |
1031 | | | |__) | / \ | \| | (___ | |__ | | | | |__) | \ / |
1032 | | | _ / / /\ \ | . ` |\___ \| __|| | | | _ /| |\/| |
1033 | | | | \ \ / ____ \| |\ |____) | | | |__| | | \ \| | | |
1034 |_| |_| \_\/_/ \_\_| \_|_____/|_| \____/|_| \_\_| |_|
1035
1036
1037*/
1038//-------------------------------------------------------------------------
1039auto internal_m2n_get_children(entt::entity id) -> hpp::small_vector<entt::entity>
1040{
1041 if(auto comp = safe_get_component<transform_component>(id))
1042 {
1043 const auto& children = comp->get_children();
1044 hpp::small_vector<entt::entity> children_id;
1045 children_id.reserve(children.size());
1046 for(const auto& child : children)
1047 {
1048 children_id.emplace_back(child.entity());
1049 }
1050 return children_id;
1051 }
1052
1053 return {};
1054}
1055
1056// Helper structure carrying an entity and the count of path segments matched so far.
1057struct node_candidate
1058{
1059 entt::entity entity;
1060 size_t matched_index{}; // number of path segments matched so far
1061};
1062
1063auto internal_m2n_get_child(entt::entity id, const std::string& path, bool recursive) -> entt::entity
1064{
1065 auto root = get_entity_from_id(id);
1066 if(!root || path.empty())
1067 return entt::null;
1068
1069 // Tokenize the path once.
1070 const auto parts = string_utils::tokenize(path, "/");
1071 if(parts.empty())
1072 return entt::null;
1073
1074 // Use a vector as a queue to reduce dynamic allocations.
1075 hpp::small_vector<node_candidate> queue;
1076 queue.reserve(4); // Reserve a reasonable number based on expected hierarchy size.
1077 queue.push_back({root, 0});
1078
1079 // Process the vector as a queue.
1080 for(size_t idx = 0; idx < queue.size(); ++idx)
1081 {
1082 auto candidate = queue[idx];
1083 bool advanced = false;
1084
1085 // Try matching current candidate.
1086 if(candidate.matched_index < parts.size())
1087 {
1088 if(auto tag_comp = safe_get_component<tag_component>(candidate.entity))
1089 {
1090 if(tag_comp->name == parts[candidate.matched_index])
1091 {
1092 candidate.matched_index++;
1093 advanced = true;
1094 if(candidate.matched_index == parts.size())
1095 {
1096 return candidate.entity;
1097 }
1098 }
1099 }
1100 }
1101
1102 // Determine if we should enqueue children.
1103 // For recursive mode: allow children if no match yet or just advanced.
1104 // For non-recursive mode: allow children only if no match has started.
1105 bool should_enqueue = recursive ? (candidate.matched_index == 0 || advanced) : (candidate.matched_index == 0);
1106
1107 if(should_enqueue)
1108 {
1109 if(auto trans_comp = safe_get_component<transform_component>(candidate.entity))
1110 {
1111 for(const auto& child : trans_comp->get_children())
1112 {
1113 queue.push_back({child.entity(), candidate.matched_index});
1114 }
1115 }
1116 }
1117 }
1118 // No matching entity found.
1119 return entt::null;
1120}
1121
1122auto internal_m2n_get_parent(entt::entity id) -> entt::entity
1123{
1124 if(auto comp = safe_get_component<transform_component>(id))
1125 {
1126 return comp->get_parent().entity();
1127 }
1128
1129 return {};
1130}
1131
1132void internal_m2n_set_parent(entt::entity id, entt::entity new_parent, bool global_stays)
1133{
1134 if(auto comp = safe_get_component<transform_component>(id))
1135 {
1136 auto parent = get_entity_from_id(new_parent);
1137 comp->set_parent(parent, global_stays);
1138 }
1139}
1140
1141auto internal_m2n_get_position_global(entt::entity id) -> math::vec3
1142{
1143 if(auto comp = safe_get_component<transform_component>(id))
1144 {
1145 return comp->get_position_global();
1146 }
1147
1148 return {};
1149}
1150
1151void internal_m2n_set_position_global(entt::entity id, const math::vec3& value)
1152{
1153 if(auto comp = safe_get_component<transform_component>(id))
1154 {
1155 comp->set_position_global(value);
1156 }
1157}
1158
1159void internal_m2n_move_by_global(entt::entity id, const math::vec3& value)
1160{
1161 if(auto comp = safe_get_component<transform_component>(id))
1162 {
1163 comp->move_by_global(value);
1164 }
1165}
1166
1167auto internal_m2n_get_position_local(entt::entity id) -> math::vec3
1168{
1169 if(auto comp = safe_get_component<transform_component>(id))
1170 {
1171 return comp->get_position_local();
1172 }
1173
1174 return {};
1175}
1176
1177void internal_m2n_set_position_local(entt::entity id, const math::vec3& value)
1178{
1179 if(auto comp = safe_get_component<transform_component>(id))
1180 {
1181 comp->set_position_local(value);
1182 }
1183}
1184
1185void internal_m2n_move_by_local(entt::entity id, const math::vec3& value)
1186{
1187 if(auto comp = safe_get_component<transform_component>(id))
1188 {
1189 comp->move_by_local(value);
1190 }
1191}
1192
1193//--------------------------------------------------
1194auto internal_m2n_get_rotation_euler_global(entt::entity id) -> math::vec3
1195{
1196 if(auto comp = safe_get_component<transform_component>(id))
1197 {
1198 return comp->get_rotation_euler_global();
1199 }
1200
1201 return {};
1202}
1203
1204void internal_m2n_rotate_by_euler_global(entt::entity id, const math::vec3& amount)
1205{
1206 if(auto comp = safe_get_component<transform_component>(id))
1207 {
1208 comp->rotate_by_euler_global(amount);
1209 }
1210}
1211
1212void internal_m2n_rotate_axis_global(entt::entity id, float degrees, const math::vec3& axis)
1213{
1214 if(auto comp = safe_get_component<transform_component>(id))
1215 {
1216 comp->rotate_axis_global(degrees, axis);
1217 }
1218}
1219
1220auto internal_m2n_transform_vector_global(entt::entity id, const math::vec3& coord) -> math::vec3
1221{
1222 if(auto comp = safe_get_component<transform_component>(id))
1223 {
1224 const auto& global = comp->get_transform_global();
1225 return global.transform_coord(coord);
1226 }
1227
1228 return {};
1229}
1230
1231auto internal_m2n_inverse_transform_vector_global(entt::entity id, const math::vec3& coord) -> math::vec3
1232{
1233 if(auto comp = safe_get_component<transform_component>(id))
1234 {
1235 const auto& global = comp->get_transform_global();
1236 return global.inverse_transform_coord(coord);
1237 }
1238
1239 return {};
1240}
1241
1242auto internal_m2n_transform_direction_global(entt::entity id, const math::vec3& direction) -> math::vec3
1243{
1244 if(auto comp = safe_get_component<transform_component>(id))
1245 {
1246 const auto& global = comp->get_transform_global();
1247 return global.transform_normal(direction);
1248 }
1249
1250 return {};
1251}
1252
1253auto internal_m2n_inverse_transform_direction_global(entt::entity id, const math::vec3& direction) -> math::vec3
1254{
1255 if(auto comp = safe_get_component<transform_component>(id))
1256 {
1257 const auto& global = comp->get_transform_global();
1258 return global.inverse_transform_normal(direction);
1259 }
1260
1261 return {};
1262}
1263
1264void internal_m2n_look_at(entt::entity id, const math::vec3& point, const math::vec3& up)
1265{
1266 if(auto comp = safe_get_component<transform_component>(id))
1267 {
1268 comp->look_at(point, up);
1269 }
1270}
1271
1272void internal_m2n_set_rotation_euler_global(entt::entity id, const math::vec3& value)
1273{
1274 if(auto comp = safe_get_component<transform_component>(id))
1275 {
1276 comp->set_rotation_euler_global(value);
1277 }
1278}
1279
1280auto internal_m2n_get_rotation_euler_local(entt::entity id) -> math::vec3
1281{
1282 if(auto comp = safe_get_component<transform_component>(id))
1283 {
1284 return comp->get_rotation_euler_local();
1285 }
1286
1287 return {};
1288}
1289
1290void internal_m2n_set_rotation_euler_local(entt::entity id, const math::vec3& value)
1291{
1292 if(auto comp = safe_get_component<transform_component>(id))
1293 {
1294 comp->set_rotation_euler_local(value);
1295 }
1296}
1297
1298void internal_m2n_rotate_by_euler_local(entt::entity id, const math::vec3& amount)
1299{
1300 if(auto comp = safe_get_component<transform_component>(id))
1301 {
1302 comp->rotate_by_euler_local(amount);
1303 }
1304}
1305
1306auto internal_m2n_get_rotation_global(entt::entity id) -> math::quat
1307{
1308 if(auto comp = safe_get_component<transform_component>(id))
1309 {
1310 return comp->get_rotation_global();
1311 }
1312
1313 return {};
1314}
1315
1316void internal_m2n_set_rotation_global(entt::entity id, const math::quat& value)
1317{
1318 if(auto comp = safe_get_component<transform_component>(id))
1319 {
1320 comp->set_rotation_global(value);
1321 }
1322}
1323
1324void internal_m2n_rotate_by_global(entt::entity id, const math::quat& amount)
1325{
1326 if(auto comp = safe_get_component<transform_component>(id))
1327 {
1328 comp->rotate_by_global(amount);
1329 }
1330}
1331
1332auto internal_m2n_get_rotation_local(entt::entity id) -> math::quat
1333{
1334 if(auto comp = safe_get_component<transform_component>(id))
1335 {
1336 return comp->get_rotation_local();
1337 }
1338
1339 return {};
1340}
1341
1342void internal_m2n_set_rotation_local(entt::entity id, const math::quat& value)
1343{
1344 if(auto comp = safe_get_component<transform_component>(id))
1345 {
1346 comp->set_rotation_local(value);
1347 }
1348}
1349
1350void internal_m2n_rotate_by_local(entt::entity id, const math::quat& amount)
1351{
1352 if(auto comp = safe_get_component<transform_component>(id))
1353 {
1354 comp->rotate_by_local(amount);
1355 }
1356}
1357
1358//--------------------------------------------------
1359auto internal_m2n_get_scale_global(entt::entity id) -> math::vec3
1360{
1361 if(auto comp = safe_get_component<transform_component>(id))
1362 {
1363 return comp->get_scale_global();
1364 }
1365
1366 return {};
1367}
1368
1369void internal_m2n_set_scale_global(entt::entity id, const math::vec3& value)
1370{
1371 if(auto comp = safe_get_component<transform_component>(id))
1372 {
1373 comp->set_scale_global(value);
1374 }
1375}
1376
1377void internal_m2n_scale_by_global(entt::entity id, const math::vec3& amount)
1378{
1379 if(auto comp = safe_get_component<transform_component>(id))
1380 {
1381 comp->scale_by_global(amount);
1382 }
1383}
1384
1385auto internal_m2n_get_scale_local(entt::entity id) -> math::vec3
1386{
1387 if(auto comp = safe_get_component<transform_component>(id))
1388 {
1389 return comp->get_scale_local();
1390 }
1391
1392 return {};
1393}
1394
1395void internal_m2n_set_scale_local(entt::entity id, const math::vec3& value)
1396{
1397 if(auto comp = safe_get_component<transform_component>(id))
1398 {
1399 comp->set_scale_local(value);
1400 }
1401}
1402
1403void internal_m2n_scale_by_local(entt::entity id, const math::vec3& amount)
1404{
1405 if(auto comp = safe_get_component<transform_component>(id))
1406 {
1407 comp->scale_by_local(amount);
1408 }
1409}
1410
1411//--------------------------------------------------
1412auto internal_m2n_get_skew_global(entt::entity id) -> math::vec3
1413{
1414 if(auto comp = safe_get_component<transform_component>(id))
1415 {
1416 return comp->get_skew_global();
1417 }
1418
1419 return {};
1420}
1421
1422void internal_m2n_setl_skew_globa(entt::entity id, const math::vec3& value)
1423{
1424 if(auto comp = safe_get_component<transform_component>(id))
1425 {
1426 comp->set_skew_global(value);
1427 }
1428}
1429
1430auto internal_m2n_get_skew_local(entt::entity id) -> math::vec3
1431{
1432 if(auto comp = safe_get_component<transform_component>(id))
1433 {
1434 return comp->get_skew_local();
1435 }
1436
1437 return {};
1438}
1439
1440void internal_m2n_set_skew_local(entt::entity id, const math::vec3& value)
1441{
1442 if(auto comp = safe_get_component<transform_component>(id))
1443 {
1444 comp->set_skew_local(value);
1445 }
1446}
1447
1448//------------------------------
1449
1450void internal_m2n_physics_apply_explosion_force(entt::entity id,
1451 float explosion_force,
1452 const math::vec3& explosion_position,
1453 float explosion_radius,
1454 float upwards_modifier,
1455 force_mode mode)
1456{
1457 if(auto comp = safe_get_component<physics_component>(id))
1458 {
1459 comp->apply_explosion_force(explosion_force, explosion_position, explosion_radius, upwards_modifier, mode);
1460 }
1461}
1462void internal_m2n_physics_apply_force(entt::entity id, const math::vec3& value, force_mode mode)
1463{
1464 if(auto comp = safe_get_component<physics_component>(id))
1465 {
1466 comp->apply_force(value, mode);
1467 }
1468}
1469
1470void internal_m2n_physics_apply_torque(entt::entity id, const math::vec3& value, force_mode mode)
1471{
1472 if(auto comp = safe_get_component<physics_component>(id))
1473 {
1474 comp->apply_torque(value, mode);
1475 }
1476}
1477
1478auto internal_m2n_physics_get_velocity(entt::entity id) -> math::vec3
1479{
1480 if(auto comp = safe_get_component<physics_component>(id))
1481 {
1482 return comp->get_velocity();
1483 }
1484
1485 return {};
1486}
1487
1488void internal_m2n_physics_set_velocity(entt::entity id, const math::vec3& velocity)
1489{
1490 if(auto comp = safe_get_component<physics_component>(id))
1491 {
1492 comp->set_velocity(velocity);
1493 }
1494}
1495
1496auto internal_m2n_physics_get_angular_velocity(entt::entity id) -> math::vec3
1497{
1498 if(auto comp = safe_get_component<physics_component>(id))
1499 {
1500 return comp->get_angular_velocity();
1501 }
1502
1503 return {};
1504}
1505
1506void internal_m2n_physics_set_angular_velocity(entt::entity id, const math::vec3& velocity)
1507{
1508 if(auto comp = safe_get_component<physics_component>(id))
1509 {
1510 comp->set_angular_velocity(velocity);
1511 }
1512}
1513
1514auto internal_m2n_physics_get_include_layers(entt::entity id) -> layer_mask
1515{
1516 if(auto comp = safe_get_component<physics_component>(id))
1517 {
1518 return comp->get_collision_include_mask();
1519 }
1520
1521 return {};
1522}
1523
1524void internal_m2n_physics_set_include_layers(entt::entity id, layer_mask mask)
1525{
1526 if(auto comp = safe_get_component<physics_component>(id))
1527 {
1528 comp->set_collision_include_mask(mask);
1529 }
1530}
1531
1532auto internal_m2n_physics_get_exclude_layers(entt::entity id) -> layer_mask
1533{
1534 if(auto comp = safe_get_component<physics_component>(id))
1535 {
1536 return comp->get_collision_exclude_mask();
1537 }
1538
1539 return {};
1540}
1541
1542void internal_m2n_physics_set_exclude_layers(entt::entity id, layer_mask mask)
1543{
1544 if(auto comp = safe_get_component<physics_component>(id))
1545 {
1546 comp->set_collision_exclude_mask(mask);
1547 }
1548}
1549
1550auto internal_m2n_physics_get_collision_layers(entt::entity id) -> layer_mask
1551{
1552 if(auto comp = safe_get_component<physics_component>(id))
1553 {
1554 return comp->get_collision_mask();
1555 }
1556
1557 return {};
1558}
1559//------------------------------
1560
1561void internal_m2n_animation_blend(entt::entity id, int layer, hpp::uuid guid, float seconds, bool loop, bool phase_sync)
1562{
1563 if(auto comp = safe_get_component<animation_component>(id))
1564 {
1565 auto& ctx = engine::context();
1566 auto& am = ctx.get_cached<asset_manager>();
1567
1568 auto asset = am.get_asset<animation_clip>(guid);
1569 comp->get_player().blend_to(layer, asset, animation_player::seconds_t(seconds), loop, phase_sync);
1570 }
1571}
1572
1573void internal_m2n_animation_play(entt::entity id)
1574{
1575 if(auto comp = safe_get_component<animation_component>(id))
1576 {
1577 comp->get_player().play();
1578 }
1579}
1580
1581void internal_m2n_animation_pause(entt::entity id)
1582{
1583 if(auto comp = safe_get_component<animation_component>(id))
1584 {
1585 comp->get_player().pause();
1586 }
1587}
1588
1589void internal_m2n_animation_resume(entt::entity id)
1590{
1591 if(auto comp = safe_get_component<animation_component>(id))
1592 {
1593 comp->get_player().resume();
1594 }
1595}
1596
1597void internal_m2n_animation_stop(entt::entity id)
1598{
1599 if(auto comp = safe_get_component<animation_component>(id))
1600 {
1601 comp->get_player().stop();
1602 }
1603}
1604
1605void internal_m2n_animation_set_speed(entt::entity id, float speed)
1606{
1607 if(auto comp = safe_get_component<animation_component>(id))
1608 {
1609 comp->set_speed(speed);
1610 }
1611}
1612
1613auto internal_m2n_animation_get_speed(entt::entity id) -> float
1614{
1615 if(auto comp = safe_get_component<animation_component>(id))
1616 {
1617 return comp->get_speed();
1618 }
1619 return 1.0f;
1620}
1621
1622//------------------------------
1623auto internal_m2n_camera_screen_point_to_ray(entt::entity id,
1624 const math::vec2& origin,
1625 mono::managed_interface::ray* managed_ray) -> bool
1626{
1627 if(auto comp = safe_get_component<camera_component>(id))
1628 {
1629 math::vec3 ray_origin{};
1630 math::vec3 ray_dir{};
1631 bool result = comp->get_camera().viewport_to_ray(origin, ray_origin, ray_dir);
1632 if(result)
1633 {
1634 using converter = mono::managed_interface::converter;
1635 managed_ray->origin = converter::convert<math::vec3, mono::managed_interface::vector3>(ray_origin);
1636 managed_ray->direction = converter::convert<math::vec3, mono::managed_interface::vector3>(ray_dir);
1637 }
1638 return result;
1639 }
1640
1641 return false;
1642}
1643//------------------------------
1644auto internal_m2n_model_get_enabled(entt::entity id) -> bool
1645{
1646 if(auto comp = safe_get_component<model_component>(id))
1647 {
1648 return comp->is_enabled();
1649 }
1650
1651 return false;
1652}
1653
1654void internal_m2n_model_set_enabled(entt::entity id, bool enabled)
1655{
1656 if(auto comp = safe_get_component<model_component>(id))
1657 {
1658 comp->set_enabled(enabled);
1659 }
1660}
1661
1662auto internal_m2n_model_get_shared_material(entt::entity id, uint32_t index) -> hpp::uuid
1663{
1664 if(auto comp = safe_get_component<model_component>(id))
1665 {
1666 return comp->get_model().get_material(index).uid();
1667 }
1668
1669 return {};
1670}
1671
1672auto internal_m2n_model_get_shared_material_count(entt::entity id) -> int
1673{
1674 if(auto comp = safe_get_component<model_component>(id))
1675 {
1676 return comp->get_model().get_materials().size();
1677 }
1678
1679 return {};
1680}
1681
1682auto internal_m2n_model_get_material_instance(entt::entity id, uint32_t index)
1684{
1685 if(auto comp = safe_get_component<model_component>(id))
1686 {
1687 auto instance = comp->get_model().get_material_instance(index);
1688 return get_material_properties(instance);
1689 }
1690
1691 return {};
1692}
1693
1694void internal_m2n_model_set_shared_material(entt::entity id, const hpp::uuid& uid, uint32_t index)
1695{
1696 if(auto comp = safe_get_component<model_component>(id))
1697 {
1698 auto& ctx = engine::context();
1699 auto& am = ctx.get_cached<asset_manager>();
1700 auto asset = am.get_asset<material>(uid);
1701
1702 auto model = comp->get_model();
1703 model.set_material(asset, index);
1704 comp->set_model(model);
1705 }
1706}
1707
1708void internal_m2n_model_set_material_instance(entt::entity id,
1710 uint32_t index)
1711{
1712 using converter = mono::managed_interface::converter;
1713
1714 if(auto comp = safe_get_component<model_component>(id))
1715 {
1716 auto model = comp->get_model();
1717
1718 if(props.valid)
1719 {
1720 auto material = model.get_or_emplace_material_instance(index);
1721 set_material_properties(material, props);
1722 model.set_material_instance(material, index);
1723 }
1724 else
1725 {
1726 model.set_material_instance(nullptr, index);
1727 }
1728 comp->set_model(model);
1729 }
1730}
1731
1732auto internal_m2n_model_get_material_instance_count(entt::entity id) -> int
1733{
1734 if(auto comp = safe_get_component<model_component>(id))
1735 {
1736 return comp->get_model().get_material_instances().size();
1737 }
1738
1739 return {};
1740}
1741
1742//------------------------------
1743// Particle Emitter Component Functions
1744//------------------------------
1745
1746auto internal_m2n_particle_emitter_get_enabled(entt::entity id) -> bool
1747{
1748 if(auto comp = safe_get_component<particle_emitter_component>(id))
1749 {
1750 return comp->is_enabled();
1751 }
1752 return false;
1753}
1754
1755void internal_m2n_particle_emitter_set_enabled(entt::entity id, bool enabled)
1756{
1757 if(auto comp = safe_get_component<particle_emitter_component>(id))
1758 {
1759 comp->set_enabled(enabled);
1760 }
1761}
1762
1763auto internal_m2n_particle_emitter_get_max_particles(entt::entity id) -> uint32_t
1764{
1765 if(auto comp = safe_get_component<particle_emitter_component>(id))
1766 {
1767 return comp->get_max_particles();
1768 }
1769 return 0;
1770}
1771
1772void internal_m2n_particle_emitter_set_max_particles(entt::entity id, uint32_t max_particles)
1773{
1774 if(auto comp = safe_get_component<particle_emitter_component>(id))
1775 {
1776 comp->set_max_particles(max_particles);
1777 }
1778}
1779
1780auto internal_m2n_particle_emitter_get_shape(entt::entity id) -> int
1781{
1782 if(auto comp = safe_get_component<particle_emitter_component>(id))
1783 {
1784 return static_cast<int>(comp->get_shape());
1785 }
1786 return 0;
1787}
1788
1789void internal_m2n_particle_emitter_set_shape(entt::entity id, int shape)
1790{
1791 if(auto comp = safe_get_component<particle_emitter_component>(id))
1792 {
1793 comp->set_shape(static_cast<EmitterShape::Enum>(shape));
1794 }
1795}
1796
1797auto internal_m2n_particle_emitter_get_direction(entt::entity id) -> int
1798{
1799 if(auto comp = safe_get_component<particle_emitter_component>(id))
1800 {
1801 return static_cast<int>(comp->get_direction());
1802 }
1803 return 0;
1804}
1805
1806void internal_m2n_particle_emitter_set_direction(entt::entity id, int direction)
1807{
1808 if(auto comp = safe_get_component<particle_emitter_component>(id))
1809 {
1810 comp->set_direction(static_cast<EmitterDirection::Enum>(direction));
1811 }
1812}
1813
1814auto internal_m2n_particle_emitter_get_gravity_scale(entt::entity id) -> float
1815{
1816 if(auto comp = safe_get_component<particle_emitter_component>(id))
1817 {
1818 return comp->get_gravity_scale();
1819 }
1820 return 0.0f;
1821}
1822
1823void internal_m2n_particle_emitter_set_gravity_scale(entt::entity id, float scale)
1824{
1825 if(auto comp = safe_get_component<particle_emitter_component>(id))
1826 {
1827 comp->set_gravity_scale(scale);
1828 }
1829}
1830
1831auto internal_m2n_particle_emitter_get_emission_rate(entt::entity id) -> float
1832{
1833 if(auto comp = safe_get_component<particle_emitter_component>(id))
1834 {
1835 return comp->get_emission_rate();
1836 }
1837 return 0.0f;
1838}
1839
1840void internal_m2n_particle_emitter_set_emission_rate(entt::entity id, float rate)
1841{
1842 if(auto comp = safe_get_component<particle_emitter_component>(id))
1843 {
1844 comp->set_emission_rate(rate);
1845 }
1846}
1847
1848auto internal_m2n_particle_emitter_get_temporal_motion(entt::entity id) -> float
1849{
1850 if(auto comp = safe_get_component<particle_emitter_component>(id))
1851 {
1852 return comp->get_temporal_motion();
1853 }
1854 return 0.0f;
1855}
1856
1857void internal_m2n_particle_emitter_set_temporal_motion(entt::entity id, float motion)
1858{
1859 if(auto comp = safe_get_component<particle_emitter_component>(id))
1860 {
1861 comp->set_temporal_motion(motion);
1862 }
1863}
1864
1865auto internal_m2n_particle_emitter_get_velocity_damping(entt::entity id) -> float
1866{
1867 if(auto comp = safe_get_component<particle_emitter_component>(id))
1868 {
1869 return comp->get_velocity_damping();
1870 }
1871 return 0.0f;
1872}
1873
1874void internal_m2n_particle_emitter_set_velocity_damping(entt::entity id, float damping)
1875{
1876 if(auto comp = safe_get_component<particle_emitter_component>(id))
1877 {
1878 comp->set_velocity_damping(damping);
1879 }
1880}
1881
1882auto internal_m2n_particle_emitter_get_blend_multiplier(entt::entity id) -> float
1883{
1884 if(auto comp = safe_get_component<particle_emitter_component>(id))
1885 {
1886 return comp->get_blend_multiplier();
1887 }
1888 return 1.0f;
1889}
1890
1891void internal_m2n_particle_emitter_set_blend_multiplier(entt::entity id, float multiplier)
1892{
1893 if(auto comp = safe_get_component<particle_emitter_component>(id))
1894 {
1895 comp->set_blend_multiplier(multiplier);
1896 }
1897}
1898
1899auto internal_m2n_particle_emitter_get_force_over_lifetime(entt::entity id) -> math::vec3
1900{
1901 if(auto comp = safe_get_component<particle_emitter_component>(id))
1902 {
1903 return comp->get_force_over_lifetime();
1904 }
1905 return math::vec3{0.0f, 0.0f, 0.0f};
1906}
1907
1908void internal_m2n_particle_emitter_set_force_over_lifetime(entt::entity id, const math::vec3& force)
1909{
1910 if(auto comp = safe_get_component<particle_emitter_component>(id))
1911 {
1912 comp->set_force_over_lifetime(force);
1913 }
1914}
1915
1916auto internal_m2n_particle_emitter_get_emission_shape_scale(entt::entity id) -> math::vec3
1917{
1918 if(auto comp = safe_get_component<particle_emitter_component>(id))
1919 {
1920 return comp->get_emission_shape_scale();
1921 }
1922 return math::vec3{1.0f, 1.0f, 1.0f};
1923}
1924
1925void internal_m2n_particle_emitter_set_emission_shape_scale(entt::entity id, const math::vec3& scale)
1926{
1927 if(auto comp = safe_get_component<particle_emitter_component>(id))
1928 {
1929 comp->set_emission_shape_scale(scale);
1930 }
1931}
1932
1933auto internal_m2n_particle_emitter_get_emission_lifetime(entt::entity id) -> float
1934{
1935 if(auto comp = safe_get_component<particle_emitter_component>(id))
1936 {
1937 return comp->get_emission_lifetime().count();
1938 }
1939 return 0.0f;
1940}
1941
1942void internal_m2n_particle_emitter_set_emission_lifetime(entt::entity id, float lifetime)
1943{
1944 if(auto comp = safe_get_component<particle_emitter_component>(id))
1945 {
1946 comp->set_emission_lifetime(std::chrono::duration<float>(lifetime));
1947 }
1948}
1949
1950auto internal_m2n_particle_emitter_get_lifetime(entt::entity id) -> float
1951{
1952 if(auto comp = safe_get_component<particle_emitter_component>(id))
1953 {
1954 return comp->get_lifetime().count();
1955 }
1956 return 0.0f;
1957}
1958
1959void internal_m2n_particle_emitter_set_lifetime(entt::entity id, float lifetime)
1960{
1961 if(auto comp = safe_get_component<particle_emitter_component>(id))
1962 {
1963 comp->set_lifetime(std::chrono::duration<float>(lifetime));
1964 }
1965}
1966
1967auto internal_m2n_particle_emitter_get_position_easing(entt::entity id) -> int
1968{
1969 if(auto comp = safe_get_component<particle_emitter_component>(id))
1970 {
1971 return static_cast<int>(comp->get_position_easing());
1972 }
1973 return 0;
1974}
1975
1976void internal_m2n_particle_emitter_set_position_easing(entt::entity id, int easing)
1977{
1978 if(auto comp = safe_get_component<particle_emitter_component>(id))
1979 {
1980 comp->set_position_easing(static_cast<bx::Easing::Enum>(easing));
1981 }
1982}
1983
1984auto internal_m2n_particle_emitter_get_num_particles(entt::entity id) -> uint32_t
1985{
1986 if(auto comp = safe_get_component<particle_emitter_component>(id))
1987 {
1988 return comp->get_num_particles();
1989 }
1990 return 0;
1991}
1992
1993auto internal_m2n_particle_emitter_is_playing(entt::entity id) -> bool
1994{
1995 if(auto comp = safe_get_component<particle_emitter_component>(id))
1996 {
1997 return comp->is_playing();
1998 }
1999 return false;
2000}
2001
2002auto internal_m2n_particle_emitter_is_paused(entt::entity id) -> bool
2003{
2004 if(auto comp = safe_get_component<particle_emitter_component>(id))
2005 {
2006 return comp->is_paused();
2007 }
2008 return false;
2009}
2010
2011auto internal_m2n_particle_emitter_get_texture(entt::entity id) -> hpp::uuid
2012{
2013 if(auto comp = safe_get_component<particle_emitter_component>(id))
2014 {
2015 return comp->get_texture().uid();
2016 }
2017 return hpp::uuid{};
2018}
2019
2020void internal_m2n_particle_emitter_set_texture(entt::entity id, const hpp::uuid& texture)
2021{
2022 if(auto comp = safe_get_component<particle_emitter_component>(id))
2023 {
2024 auto& ctx = engine::context();
2025 auto& am = ctx.get_cached<asset_manager>();
2026 auto handle = am.get_asset<gfx::texture>(texture);
2027 comp->set_texture(handle);
2028 }
2029}
2030
2031void internal_m2n_particle_emitter_play(entt::entity id)
2032{
2033 if(auto comp = safe_get_component<particle_emitter_component>(id))
2034 {
2035 comp->play();
2036 }
2037}
2038
2039void internal_m2n_particle_emitter_stop(entt::entity id)
2040{
2041 if(auto comp = safe_get_component<particle_emitter_component>(id))
2042 {
2043 comp->stop();
2044 }
2045}
2046
2047void internal_m2n_particle_emitter_stop_and_reset(entt::entity id)
2048{
2049 if(auto comp = safe_get_component<particle_emitter_component>(id))
2050 {
2051 comp->stop_and_reset();
2052 }
2053}
2054
2055void internal_m2n_particle_emitter_pause(entt::entity id)
2056{
2057 if(auto comp = safe_get_component<particle_emitter_component>(id))
2058 {
2059 comp->pause();
2060 }
2061}
2062
2063void internal_m2n_particle_emitter_resume(entt::entity id)
2064{
2065 if(auto comp = safe_get_component<particle_emitter_component>(id))
2066 {
2067 comp->resume();
2068 }
2069}
2070
2071void internal_m2n_particle_emitter_reset_emitter(entt::entity id)
2072{
2073 if(auto comp = safe_get_component<particle_emitter_component>(id))
2074 {
2075 comp->reset_emitter();
2076 }
2077}
2078
2079auto internal_m2n_particle_emitter_get_loop(entt::entity id) -> bool
2080{
2081 if(auto comp = safe_get_component<particle_emitter_component>(id))
2082 {
2083 return comp->is_loop();
2084 }
2085 return true; // Default to true
2086}
2087
2088void internal_m2n_particle_emitter_set_loop(entt::entity id, bool loop)
2089{
2090 if(auto comp = safe_get_component<particle_emitter_component>(id))
2091 {
2092 comp->set_loop(loop);
2093 }
2094}
2095
2096//------------------------------
2097auto internal_m2n_text_get_text(entt::entity id) -> const std::string&
2098{
2099 if(auto comp = safe_get_component<text_component>(id))
2100 {
2101 return comp->get_text();
2102 }
2103
2104 static const std::string empty;
2105 return empty;
2106}
2107
2108void internal_m2n_text_set_text(entt::entity id, const std::string& text)
2109{
2110 if(auto comp = safe_get_component<text_component>(id))
2111 {
2112 comp->set_text(text);
2113 }
2114}
2115
2116auto internal_m2n_text_get_buffer_type(entt::entity id) -> text_component::buffer_type
2117{
2118 if(auto comp = safe_get_component<text_component>(id))
2119 {
2120 return comp->get_buffer_type();
2121 }
2122
2124}
2125
2126void internal_m2n_text_set_buffer_type(entt::entity id, text_component::buffer_type type)
2127{
2128 if(auto comp = safe_get_component<text_component>(id))
2129 {
2130 comp->set_buffer_type(type);
2131 }
2132}
2133
2134auto internal_m2n_text_get_overflow_type(entt::entity id) -> text_component::overflow_type
2135{
2136 if(auto comp = safe_get_component<text_component>(id))
2137 {
2138 return comp->get_overflow_type();
2139 }
2140
2142}
2143
2144void internal_m2n_text_set_overflow_type(entt::entity id, text_component::overflow_type type)
2145{
2146 if(auto comp = safe_get_component<text_component>(id))
2147 {
2148 comp->set_overflow_type(type);
2149 }
2150}
2151
2152auto internal_m2n_text_get_font(entt::entity id) -> hpp::uuid
2153{
2154 if(auto comp = safe_get_component<text_component>(id))
2155 {
2156 return comp->get_font().uid();
2157 }
2158
2159 return hpp::uuid{};
2160}
2161
2162void internal_m2n_text_set_font(entt::entity id, hpp::uuid uid)
2163{
2164 if(auto comp = safe_get_component<text_component>(id))
2165 {
2166 auto& ctx = engine::context();
2167 auto& am = ctx.get_cached<asset_manager>();
2168
2169 auto asset = am.get_asset<font>(uid);
2170 comp->set_font(asset);
2171 }
2172}
2173
2174auto internal_m2n_text_get_font_size(entt::entity id) -> uint32_t
2175{
2176 if(auto comp = safe_get_component<text_component>(id))
2177 {
2178 return comp->get_font_size();
2179 }
2180
2181 return 0;
2182}
2183
2184void internal_m2n_text_set_font_size(entt::entity id, uint32_t font_size)
2185{
2186 if(auto comp = safe_get_component<text_component>(id))
2187 {
2188 comp->set_font_size(font_size);
2189 }
2190}
2191
2192auto internal_m2n_text_get_render_font_size(entt::entity id) -> uint32_t
2193{
2194 if(auto comp = safe_get_component<text_component>(id))
2195 {
2196 return comp->get_render_font_size();
2197 }
2198
2199 return 0;
2200}
2201
2202auto internal_m2n_text_get_auto_size(entt::entity id) -> bool
2203{
2204 if(auto comp = safe_get_component<text_component>(id))
2205 {
2206 return comp->get_auto_size();
2207 }
2208
2209 return false;
2210}
2211
2212void internal_m2n_text_set_auto_size(entt::entity id, bool auto_size)
2213{
2214 if(auto comp = safe_get_component<text_component>(id))
2215 {
2216 comp->set_auto_size(auto_size);
2217 }
2218}
2219auto internal_m2n_text_get_auto_size_range(entt::entity id) -> urange32_t
2220{
2221 if(auto comp = safe_get_component<text_component>(id))
2222 {
2223 return comp->get_auto_size_range();
2224 }
2225
2226 return {};
2227}
2228
2229void internal_m2n_text_set_auto_size_range(entt::entity id, urange32_t range)
2230{
2231 if(auto comp = safe_get_component<text_component>(id))
2232 {
2233 comp->set_auto_size_range(range);
2234 }
2235}
2236
2237auto internal_m2n_text_get_area(entt::entity id) -> math::vec2
2238{
2239 if(auto comp = safe_get_component<text_component>(id))
2240 {
2241 auto area = comp->get_area();
2242 return {area.width, area.height};
2243 }
2244
2245 return {};
2246}
2247
2248void internal_m2n_text_set_area(entt::entity id, math::vec2 area)
2249{
2250 if(auto comp = safe_get_component<text_component>(id))
2251 {
2252 comp->set_area({area.x, area.y});
2253 }
2254}
2255
2256auto internal_m2n_text_get_render_area(entt::entity id) -> math::vec2
2257{
2258 if(auto comp = safe_get_component<text_component>(id))
2259 {
2260 auto area = comp->get_render_area();
2261 return {area.width, area.height};
2262 }
2263
2264 return {};
2265}
2266
2267auto internal_m2n_text_get_is_rich_text(entt::entity id) -> bool
2268{
2269 if(auto comp = safe_get_component<text_component>(id))
2270 {
2271 return comp->get_is_rich_text();
2272 }
2273
2274 return false;
2275}
2276
2277void internal_m2n_text_set_is_rich_text(entt::entity id, bool rich)
2278{
2279 if(auto comp = safe_get_component<text_component>(id))
2280 {
2281 comp->set_is_rich_text(rich);
2282 }
2283}
2284
2285auto internal_m2n_text_get_alignment(entt::entity id) -> uint32_t
2286{
2287 if(auto comp = safe_get_component<text_component>(id))
2288 {
2289 return comp->get_alignment().flags;
2290 }
2291
2292 return alignment{}.flags;
2293}
2294
2295void internal_m2n_text_set_alignment(entt::entity id, uint32_t alignment_flags)
2296{
2297 if(auto comp = safe_get_component<text_component>(id))
2298 {
2299 comp->set_alignment({alignment_flags});
2300 }
2301}
2302
2303auto internal_m2n_text_get_bounds(entt::entity id) -> math::bbox
2304{
2305 if(auto comp = safe_get_component<text_component>(id))
2306 {
2307 return comp->get_bounds();
2308 }
2309
2310 return math::bbox::empty;
2311}
2312
2313auto internal_m2n_text_get_render_bounds(entt::entity id) -> math::bbox
2314{
2315 if(auto comp = safe_get_component<text_component>(id))
2316 {
2317 return comp->get_render_bounds();
2318 }
2319
2320 return math::bbox::empty;
2321}
2322
2323// ==== Text Style Functions ====
2324
2325void internal_m2n_text_set_opacity(entt::entity id, float opacity)
2326{
2327 if(auto comp = safe_get_component<text_component>(id))
2328 {
2329 auto style = comp->get_style();
2330 style.set_opacity(opacity);
2331 comp->set_style(style);
2332 }
2333}
2334
2335auto internal_m2n_text_get_opacity(entt::entity id) -> float
2336{
2337 if(auto comp = safe_get_component<text_component>(id))
2338 {
2339 return comp->get_style().get_opacity();
2340 }
2341 return 1.0f;
2342}
2343
2344void internal_m2n_text_set_text_color(entt::entity id, math::color color)
2345{
2346 if(auto comp = safe_get_component<text_component>(id))
2347 {
2348 auto style = comp->get_style();
2349 style.set_text_color(color);
2350 comp->set_style(style);
2351 }
2352}
2353
2354auto internal_m2n_text_get_text_color(entt::entity id) -> math::color
2355{
2356 if(auto comp = safe_get_component<text_component>(id))
2357 {
2358 return comp->get_style().get_text_color();
2359 }
2360 return math::color::white();
2361}
2362
2363void internal_m2n_text_set_background_color(entt::entity id, math::color color)
2364{
2365 if(auto comp = safe_get_component<text_component>(id))
2366 {
2367 auto style = comp->get_style();
2368 style.set_background_color(color);
2369 comp->set_style(style);
2370 }
2371}
2372
2373auto internal_m2n_text_get_background_color(entt::entity id) -> math::color
2374{
2375 if(auto comp = safe_get_component<text_component>(id))
2376 {
2377 return comp->get_style().get_background_color();
2378 }
2379 return math::color::transparent();
2380}
2381
2382void internal_m2n_text_set_foreground_color(entt::entity id, math::color color)
2383{
2384 if(auto comp = safe_get_component<text_component>(id))
2385 {
2386 auto style = comp->get_style();
2387 style.set_foreground_color(color);
2388 comp->set_style(style);
2389 }
2390}
2391
2392auto internal_m2n_text_get_foreground_color(entt::entity id) -> math::color
2393{
2394 if(auto comp = safe_get_component<text_component>(id))
2395 {
2396 return comp->get_style().get_foreground_color();
2397 }
2398 return math::color::transparent();
2399}
2400
2401void internal_m2n_text_set_overline_color(entt::entity id, math::color color)
2402{
2403 if(auto comp = safe_get_component<text_component>(id))
2404 {
2405 auto style = comp->get_style();
2406 style.set_overline_color(color);
2407 comp->set_style(style);
2408 }
2409}
2410
2411auto internal_m2n_text_get_overline_color(entt::entity id) -> math::color
2412{
2413 if(auto comp = safe_get_component<text_component>(id))
2414 {
2415 return comp->get_style().get_overline_color();
2416 }
2417 return math::color::white();
2418}
2419
2420void internal_m2n_text_set_underline_color(entt::entity id, math::color color)
2421{
2422 if(auto comp = safe_get_component<text_component>(id))
2423 {
2424 auto style = comp->get_style();
2425 style.set_underline_color(color);
2426 comp->set_style(style);
2427 }
2428}
2429
2430auto internal_m2n_text_get_underline_color(entt::entity id) -> math::color
2431{
2432 if(auto comp = safe_get_component<text_component>(id))
2433 {
2434 return comp->get_style().get_underline_color();
2435 }
2436 return math::color::white();
2437}
2438
2439void internal_m2n_text_set_strike_color(entt::entity id, math::color color)
2440{
2441 if(auto comp = safe_get_component<text_component>(id))
2442 {
2443 auto style = comp->get_style();
2444 style.set_strike_color(color);
2445 comp->set_style(style);
2446 }
2447}
2448
2449auto internal_m2n_text_get_strike_color(entt::entity id) -> math::color
2450{
2451 if(auto comp = safe_get_component<text_component>(id))
2452 {
2453 return comp->get_style().get_strike_color();
2454 }
2455 return math::color::white();
2456}
2457
2458void internal_m2n_text_set_outline_color(entt::entity id, math::color color)
2459{
2460 if(auto comp = safe_get_component<text_component>(id))
2461 {
2462 auto style = comp->get_style();
2463 style.set_outline_color(color);
2464 comp->set_style(style);
2465 }
2466}
2467
2468auto internal_m2n_text_get_outline_color(entt::entity id) -> math::color
2469{
2470 if(auto comp = safe_get_component<text_component>(id))
2471 {
2472 return comp->get_style().get_outline_color();
2473 }
2474 return math::color::black();
2475}
2476
2477void internal_m2n_text_set_outline_width(entt::entity id, float width)
2478{
2479 if(auto comp = safe_get_component<text_component>(id))
2480 {
2481 auto style = comp->get_style();
2482 style.outline_width = width;
2483 comp->set_style(style);
2484 }
2485}
2486
2487auto internal_m2n_text_get_outline_width(entt::entity id) -> float
2488{
2489 if(auto comp = safe_get_component<text_component>(id))
2490 {
2491 return comp->get_style().outline_width;
2492 }
2493 return 0.0f;
2494}
2495
2496void internal_m2n_text_set_shadow_offsets(entt::entity id, math::vec2 offsets)
2497{
2498 if(auto comp = safe_get_component<text_component>(id))
2499 {
2500 auto style = comp->get_style();
2501 style.shadow_offsets = offsets;
2502 comp->set_style(style);
2503 }
2504}
2505
2506auto internal_m2n_text_get_shadow_offsets(entt::entity id) -> math::vec2
2507{
2508 if(auto comp = safe_get_component<text_component>(id))
2509 {
2510 return comp->get_style().shadow_offsets;
2511 }
2512 return {0.0f, 0.0f};
2513}
2514
2515void internal_m2n_text_set_shadow_color(entt::entity id, math::color color)
2516{
2517 if(auto comp = safe_get_component<text_component>(id))
2518 {
2519 auto style = comp->get_style();
2520 style.set_shadow_color(color);
2521 comp->set_style(style);
2522 }
2523}
2524
2525auto internal_m2n_text_get_shadow_color(entt::entity id) -> math::color
2526{
2527 if(auto comp = safe_get_component<text_component>(id))
2528 {
2529 return comp->get_style().get_shadow_color();
2530 }
2531 return math::color::black();
2532}
2533
2534void internal_m2n_text_set_shadow_softener(entt::entity id, float softener)
2535{
2536 if(auto comp = safe_get_component<text_component>(id))
2537 {
2538 auto style = comp->get_style();
2539 style.shadow_softener = softener;
2540 comp->set_style(style);
2541 }
2542}
2543
2544auto internal_m2n_text_get_shadow_softener(entt::entity id) -> float
2545{
2546 if(auto comp = safe_get_component<text_component>(id))
2547 {
2548 return comp->get_style().shadow_softener;
2549 }
2550 return 1.0f;
2551}
2552
2553void internal_m2n_text_set_style_flags(entt::entity id, uint32_t flags)
2554{
2555 if(auto comp = safe_get_component<text_component>(id))
2556 {
2557 auto style = comp->get_style();
2558 style.set_style_flags({flags});
2559 comp->set_style(style);
2560 }
2561}
2562
2563auto internal_m2n_text_get_style_flags(entt::entity id) -> uint32_t
2564{
2565 if(auto comp = safe_get_component<text_component>(id))
2566 {
2567 return comp->get_style().get_style_flags().flags;
2568 }
2569 return gfx::style_normal;
2570}
2571
2572//------------------------------
2573
2574void internal_m2n_light_set_color(entt::entity id, const math::color& color)
2575{
2576 if(auto comp = safe_get_component<light_component>(id))
2577 {
2578 auto l = comp->get_light();
2579 l.color = color;
2580 comp->set_light(l);
2581 }
2582}
2583
2584auto internal_m2n_light_get_color(entt::entity id) -> math::color
2585{
2586 if(auto comp = safe_get_component<light_component>(id))
2587 {
2588 return comp->get_light().color;
2589 }
2590
2591 return math::color::white();
2592}
2593//------------------------------
2594
2595auto internal_m2n_from_euler_rad(const math::vec3& euler) -> math::quat
2596{
2597 return {euler};
2598}
2599
2600auto internal_m2n_to_euler_rad(const math::quat& euler) -> math::vec3
2601{
2602 return math::eulerAngles(euler);
2603}
2604
2605auto internal_m2n_angle_axis(float angle, const math::vec3& axis) -> math::quat
2606{
2607 return math::angleAxis(angle, axis);
2608}
2609
2610auto internal_m2n_look_rotation(const math::vec3& forward, const math::vec3& up) -> math::quat
2611{
2612 return math::look_rotation(forward, up);
2613}
2614
2615auto internal_m2n_from_to_rotation(const math::vec3& from, const math::vec3& to) -> math::quat
2616{
2617 return math::from_to_rotation(from, to);
2618}
2619
2620auto internal_m2n_get_asset_by_uuid(const hpp::uuid& uid, const mono::mono_type& type) -> hpp::uuid
2621{
2622 if(auto asset = get_mono_asset(type.get_hash()))
2623 {
2624 return asset->get_asset_uuid(uid);
2625 }
2626
2627 return {};
2628}
2629
2630auto internal_m2n_get_asset_by_key(const std::string& key, const mono::mono_type& type) -> hpp::uuid
2631{
2632 if(auto asset = get_mono_asset(type.get_hash()))
2633 {
2634 return asset->get_asset_uuid(key);
2635 }
2636
2637 return {};
2638}
2639
2640auto internal_m2n_get_material_properties(const hpp::uuid& uid) -> mono::managed_interface::material_properties
2641{
2642 using converter = mono::managed_interface::converter;
2643
2644 auto& ctx = engine::context();
2645 auto& am = ctx.get_cached<asset_manager>();
2646
2648 auto asset = am.get_asset<material>(uid);
2649 if(!asset)
2650 {
2651 return props;
2652 }
2653 auto material = asset.get();
2654
2655 return get_material_properties(material);
2656}
2657
2658auto internal_m2n_audio_clip_get_length(const hpp::uuid& uid) -> float
2659{
2660 auto& ctx = engine::context();
2661 auto& am = ctx.get_cached<asset_manager>();
2662
2663 auto asset = am.get_asset<audio_clip>(uid);
2664
2665 if(asset.is_valid())
2666 {
2667 if(auto clip = asset.get())
2668 {
2669 float secs = clip->get_info().duration.count();
2670 return secs;
2671 }
2672 }
2673
2674 return 0.0f;
2675}
2676auto m2n_test_uuid(const hpp::uuid& uid) -> hpp::uuid
2677{
2678 APPLOG_INFO("{}:: From C# {}", __func__, hpp::to_string(uid));
2679
2680 auto newuid = generate_uuid();
2681 APPLOG_INFO("{}:: New C++ {}", __func__, hpp::to_string(newuid));
2682
2683 return newuid;
2684}
2685
2686void internal_m2n_gizmos_add_sphere(const math::color& color, const math::vec3& position, float radius)
2687{
2688 auto& ctx = engine::context();
2689 auto& path = ctx.get_cached<rendering_system>();
2690 path.add_debugdraw_call(
2691 [color, position, radius](gfx::dd_raii& dd)
2692 {
2694 dd.encoder.setColor(color);
2695 dd.encoder.setWireframe(true);
2696
2697 bx::Sphere sphere;
2698 sphere.center.x = position.x;
2699 sphere.center.y = position.y;
2700 sphere.center.z = position.z;
2701 sphere.radius = radius;
2702 dd.encoder.draw(sphere);
2703 });
2704}
2705
2706void internal_m2n_gizmos_add_ray(const math::color& color,
2707 const math::vec3& position,
2708 const math::vec3& direction,
2709 float max_distance)
2710{
2711 auto& ctx = engine::context();
2712 auto& path = ctx.get_cached<rendering_system>();
2713 path.add_debugdraw_call(
2714 [color, position, direction, max_distance](gfx::dd_raii& dd)
2715 {
2717 dd.encoder.setColor(color);
2718 dd.encoder.setWireframe(true);
2719
2720 bx::Ray ray;
2721 ray.pos.x = position.x;
2722 ray.pos.y = position.y;
2723 ray.pos.z = position.z;
2724
2725 ray.dir.x = direction.x;
2726 ray.dir.y = direction.y;
2727 ray.dir.z = direction.z;
2728
2729 dd.encoder.push();
2730 dd.encoder.moveTo(ray.pos);
2731 dd.encoder.lineTo(bx::mul(ray.dir, max_distance));
2732 dd.encoder.pop();
2733 });
2734}
2735
2736auto internal_m2n_layers_layer_to_name(int layer) -> const std::string&
2737{
2738 auto& ctx = engine::context();
2739 auto& csettings = ctx.get<settings>();
2740
2741 if(layer >= csettings.layer.layers.size())
2742 {
2743 mono::raise_exception("System", "Exception", fmt::format("Layer index {} is out of bounds.", layer));
2744
2745 static const std::string empty;
2746 return empty;
2747 }
2748 return csettings.layer.layers[layer];
2749}
2750
2751auto internal_m2n_layers_name_to_layer(const std::string& name) -> int
2752{
2753 auto& ctx = engine::context();
2754 auto& csettings = ctx.get<settings>();
2755
2756 auto it = std::find(csettings.layer.layers.begin(), csettings.layer.layers.end(), name);
2757 if(it != csettings.layer.layers.end())
2758 {
2759 return static_cast<int>(std::distance(csettings.layer.layers.begin(), it));
2760 }
2761
2762 return -1;
2763}
2764
2765auto internal_m2n_input_get_analog_value(const std::string& name) -> float
2766{
2767 auto& ctx = engine::context();
2768 auto& input = ctx.get_cached<input_system>();
2769 return input.get_analog_value(name);
2770}
2771
2772auto internal_m2n_input_get_digital_value(const std::string& name) -> bool
2773{
2774 auto& ctx = engine::context();
2775 auto& input = ctx.get_cached<input_system>();
2776 return input.get_digital_value(name);
2777}
2778
2779auto internal_m2n_input_is_pressed(const std::string& name) -> bool
2780{
2781 auto& ctx = engine::context();
2782 auto& input = ctx.get_cached<input_system>();
2783 return input.is_pressed(name);
2784}
2785
2786auto internal_m2n_input_is_released(const std::string& name) -> bool
2787{
2788 auto& ctx = engine::context();
2789 auto& input = ctx.get_cached<input_system>();
2790 return input.is_released(name);
2791}
2792
2793auto internal_m2n_input_is_down(const std::string& name) -> bool
2794{
2795 auto& ctx = engine::context();
2796 auto& input = ctx.get_cached<input_system>();
2797 return input.is_down(name);
2798}
2799
2800auto internal_m2n_input_is_key_pressed(input::key_code code) -> bool
2801{
2802 auto& ctx = engine::context();
2803 auto& input = ctx.get_cached<input_system>();
2804 return input.manager.get_keyboard().is_pressed(code);
2805}
2806
2807auto internal_m2n_input_is_key_released(input::key_code code) -> bool
2808{
2809 auto& ctx = engine::context();
2810 auto& input = ctx.get_cached<input_system>();
2811 return input.manager.get_keyboard().is_released(code);
2812}
2813
2814auto internal_m2n_input_is_key_down(input::key_code code) -> bool
2815{
2816 auto& ctx = engine::context();
2817 auto& input = ctx.get_cached<input_system>();
2818 return input.manager.get_keyboard().is_down(code);
2819}
2820
2821auto internal_m2n_input_is_mouse_button_pressed(int32_t button) -> bool
2822{
2823 auto& ctx = engine::context();
2824 auto& input = ctx.get_cached<input_system>();
2825 return input.manager.get_mouse().is_pressed(button);
2826}
2827
2828auto internal_m2n_input_is_mouse_button_released(int32_t button) -> bool
2829{
2830 auto& ctx = engine::context();
2831 auto& input = ctx.get_cached<input_system>();
2832 return input.manager.get_mouse().is_released(button);
2833}
2834
2835auto internal_m2n_input_is_mouse_button_down(int32_t button) -> bool
2836{
2837 auto& ctx = engine::context();
2838 auto& input = ctx.get_cached<input_system>();
2839 return input.manager.get_mouse().is_down(button);
2840}
2841
2842auto internal_m2n_input_get_mouse_position() -> math::vec2
2843{
2844 auto& ctx = engine::context();
2845 auto& input = ctx.get_cached<input_system>();
2846 auto coord = input.manager.get_mouse().get_position();
2847 return {coord.x, coord.y};
2848}
2849
2850//-------------------------------------------------
2851
2852auto internal_m2n_physics_ray_cast(mono::managed_interface::raycast_hit* hit,
2853 const math::vec3& origin,
2854 const math::vec3& direction,
2855 float max_distance,
2856 int layer_mask,
2857 bool query_sensors) -> bool
2858{
2859 auto& ctx = engine::context();
2860 auto& physics = ctx.get_cached<physics_system>();
2861
2862 auto ray_hit = physics.ray_cast(origin, direction, max_distance, layer_mask, query_sensors);
2863
2864 using converter = mono::managed_interface::converter;
2865
2866 if(ray_hit)
2867 {
2868 hit->entity = ray_hit->entity;
2869 hit->point = converter::convert<math::vec3, mono::managed_interface::vector3>(ray_hit->point);
2870 hit->normal = converter::convert<math::vec3, mono::managed_interface::vector3>(ray_hit->normal);
2871 hit->distance = ray_hit->distance;
2872 }
2873
2874 return ray_hit.has_value();
2875}
2876
2877auto internal_m2n_physics_ray_cast_all(const math::vec3& origin,
2878 const math::vec3& direction,
2879 float max_distance,
2880 int layer_mask,
2881 bool query_sensors) -> hpp::small_vector<mono::managed_interface::raycast_hit>
2882{
2883 auto& ctx = engine::context();
2884 auto& physics = ctx.get_cached<physics_system>();
2885
2886 auto ray_hits = physics.ray_cast_all(origin, direction, max_distance, layer_mask, query_sensors);
2887
2888 hpp::small_vector<mono::managed_interface::raycast_hit> hits;
2889
2890 using converter = mono::managed_interface::converter;
2891 for(const auto& ray_hit : ray_hits)
2892 {
2893 auto& hit = hits.emplace_back();
2894 hit.entity = ray_hit.entity;
2895 hit.point = converter::convert<math::vec3, mono::managed_interface::vector3>(ray_hit.point);
2896 hit.normal = converter::convert<math::vec3, mono::managed_interface::vector3>(ray_hit.normal);
2897 hit.distance = ray_hit.distance;
2898 }
2899
2900 return hits;
2901}
2902
2903auto internal_m2n_physics_sphere_cast(mono::managed_interface::raycast_hit* hit,
2904 const math::vec3& origin,
2905 const math::vec3& direction,
2906 float radius,
2907 float max_distance,
2908 int layer_mask,
2909 bool query_sensors) -> bool
2910{
2911 auto& ctx = engine::context();
2912 auto& physics = ctx.get_cached<physics_system>();
2913
2914 auto ray_hit = physics.sphere_cast(origin, direction, radius, max_distance, layer_mask, query_sensors);
2915
2916 using converter = mono::managed_interface::converter;
2917
2918 if(ray_hit)
2919 {
2920 hit->entity = ray_hit->entity;
2921 hit->point = converter::convert<math::vec3, mono::managed_interface::vector3>(ray_hit->point);
2922 hit->normal = converter::convert<math::vec3, mono::managed_interface::vector3>(ray_hit->normal);
2923 hit->distance = ray_hit->distance;
2924 }
2925
2926 return ray_hit.has_value();
2927}
2928
2929auto internal_m2n_physics_sphere_cast_all(const math::vec3& origin,
2930 const math::vec3& direction,
2931 float radius,
2932 float max_distance,
2933 int layer_mask,
2934 bool query_sensors) -> hpp::small_vector<mono::managed_interface::raycast_hit>
2935{
2936 auto& ctx = engine::context();
2937 auto& physics = ctx.get_cached<physics_system>();
2938
2939 auto ray_hits = physics.sphere_cast_all(origin, direction, radius, max_distance, layer_mask, query_sensors);
2940
2941 hpp::small_vector<mono::managed_interface::raycast_hit> hits;
2942
2943 using converter = mono::managed_interface::converter;
2944 for(const auto& ray_hit : ray_hits)
2945 {
2946 auto& hit = hits.emplace_back();
2947 hit.entity = ray_hit.entity;
2948 hit.point = converter::convert<math::vec3, mono::managed_interface::vector3>(ray_hit.point);
2949 hit.normal = converter::convert<math::vec3, mono::managed_interface::vector3>(ray_hit.normal);
2950 hit.distance = ray_hit.distance;
2951 }
2952
2953 return hits;
2954}
2955
2956auto internal_m2n_physics_sphere_overlap(const math::vec3& origin, float radius, int layer_mask, bool query_sensors)
2958{
2959 auto& ctx = engine::context();
2960 auto& physics = ctx.get_cached<physics_system>();
2961
2962 auto hits = physics.sphere_overlap(origin, radius, layer_mask, query_sensors);
2963
2964 return hits;
2965}
2966
2967//-------------------------------------------------
2968
2969auto internal_m2n_audio_source_get_loop(entt::entity id) -> bool
2970{
2971 if(auto comp = safe_get_component<audio_source_component>(id))
2972 {
2973 return comp->is_looping();
2974 }
2975
2976 return {};
2977}
2978
2979//-------------------------------------------------
2980
2981void internal_m2n_utils_set_ik_posiiton_ccd(entt::entity id,
2982 const math::vec3& target,
2983 int num_bones_in_chain,
2984 float threshold,
2985 int max_iterations)
2986{
2987 auto e = get_entity_from_id(id);
2988
2989 ik_set_position_ccd(e, target, num_bones_in_chain, threshold, max_iterations);
2990}
2991
2992void internal_m2n_utils_set_ik_posiiton_fabrik(entt::entity id,
2993 const math::vec3& target,
2994 int num_bones_in_chain,
2995 float threshold,
2996 int max_iterations)
2997{
2998 auto e = get_entity_from_id(id);
2999
3000 ik_set_position_fabrik(e, target, num_bones_in_chain, threshold, max_iterations);
3001}
3002
3003void internal_m2n_utils_set_ik_posiiton_two_bone(entt::entity id,
3004 const math::vec3& target,
3005 const math::vec3& forward,
3006 float weight,
3007 float soften,
3008 int max_iterations)
3009{
3010 auto e = get_entity_from_id(id);
3011
3012 ik_set_position_two_bone(e, target, forward, weight, soften, max_iterations);
3013}
3014
3015void internal_m2n_utils_set_ik_look_at_posiiton(entt::entity id, const math::vec3& target, float weight)
3016{
3017 auto e = get_entity_from_id(id);
3018
3019 ik_look_at_position(e, target, weight);
3020}
3021
3022void internal_m2n_audio_source_set_loop(entt::entity id, bool loop)
3023{
3024 if(auto comp = safe_get_component<audio_source_component>(id))
3025 {
3026 comp->set_loop(loop);
3027 }
3028}
3029
3030auto internal_m2n_audio_source_get_volume(entt::entity id) -> float
3031{
3032 if(auto comp = safe_get_component<audio_source_component>(id))
3033 {
3034 return comp->get_volume();
3035 }
3036
3037 return {};
3038}
3039
3040void internal_m2n_audio_source_set_volume(entt::entity id, float volume)
3041{
3042 if(auto comp = safe_get_component<audio_source_component>(id))
3043 {
3044 comp->set_volume(volume);
3045 }
3046}
3047
3048auto internal_m2n_audio_source_get_pitch(entt::entity id) -> float
3049{
3050 if(auto comp = safe_get_component<audio_source_component>(id))
3051 {
3052 return comp->get_pitch();
3053 }
3054
3055 return {};
3056}
3057
3058void internal_m2n_audio_source_set_pitch(entt::entity id, float pitch)
3059{
3060 if(auto comp = safe_get_component<audio_source_component>(id))
3061 {
3062 comp->set_pitch(pitch);
3063 }
3064}
3065
3066auto internal_m2n_audio_source_get_volume_rolloff(entt::entity id) -> float
3067{
3068 if(auto comp = safe_get_component<audio_source_component>(id))
3069 {
3070 return comp->get_volume_rolloff();
3071 }
3072
3073 return {};
3074}
3075
3076void internal_m2n_audio_source_set_volume_rolloff(entt::entity id, float rolloff)
3077{
3078 if(auto comp = safe_get_component<audio_source_component>(id))
3079 {
3080 comp->set_volume_rolloff(rolloff);
3081 }
3082}
3083
3084auto internal_m2n_audio_source_get_min_distance(entt::entity id) -> float
3085{
3086 if(auto comp = safe_get_component<audio_source_component>(id))
3087 {
3088 return comp->get_range().min;
3089 }
3090
3091 return {};
3092}
3093
3094void internal_m2n_audio_source_set_min_distance(entt::entity id, float distance)
3095{
3096 if(auto comp = safe_get_component<audio_source_component>(id))
3097 {
3098 auto range = comp->get_range();
3099 range.min = distance;
3100 comp->set_range(range);
3101 }
3102}
3103
3104auto internal_m2n_audio_source_get_max_distance(entt::entity id) -> float
3105{
3106 if(auto comp = safe_get_component<audio_source_component>(id))
3107 {
3108 return comp->get_range().max;
3109 }
3110
3111 return {};
3112}
3113
3114void internal_m2n_audio_source_set_max_distance(entt::entity id, float distance)
3115{
3116 if(auto comp = safe_get_component<audio_source_component>(id))
3117 {
3118 auto range = comp->get_range();
3119 range.max = distance;
3120 comp->set_range(range);
3121 }
3122}
3123
3124auto internal_m2n_audio_source_get_mute(entt::entity id) -> bool
3125{
3126 if(auto comp = safe_get_component<audio_source_component>(id))
3127 {
3128 return comp->is_muted();
3129 }
3130
3131 return {};
3132}
3133
3134void internal_m2n_audio_source_set_mute(entt::entity id, bool mute)
3135{
3136 if(auto comp = safe_get_component<audio_source_component>(id))
3137 {
3138 comp->set_mute(mute);
3139 }
3140}
3141
3142auto internal_m2n_audio_source_get_time(entt::entity id) -> float
3143{
3144 if(auto comp = safe_get_component<audio_source_component>(id))
3145 {
3146 return float(comp->get_playback_position().count());
3147 }
3148
3149 return {};
3150}
3151
3152void internal_m2n_audio_source_set_time(entt::entity id, float seconds)
3153{
3154 if(auto comp = safe_get_component<audio_source_component>(id))
3155 {
3156 comp->set_playback_position(audio::duration_t(seconds));
3157 }
3158}
3159
3160auto internal_m2n_audio_source_is_playing(entt::entity id) -> bool
3161{
3162 if(auto comp = safe_get_component<audio_source_component>(id))
3163 {
3164 return comp->is_playing();
3165 }
3166
3167 return {};
3168}
3169
3170auto internal_m2n_audio_source_is_paused(entt::entity id) -> bool
3171{
3172 if(auto comp = safe_get_component<audio_source_component>(id))
3173 {
3174 return comp->is_paused();
3175 }
3176
3177 return {};
3178}
3179
3180void internal_m2n_audio_source_play(entt::entity id)
3181{
3182 if(auto comp = safe_get_component<audio_source_component>(id))
3183 {
3184 comp->play();
3185 }
3186}
3187
3188void internal_m2n_audio_source_stop(entt::entity id)
3189{
3190 if(auto comp = safe_get_component<audio_source_component>(id))
3191 {
3192 comp->stop();
3193 }
3194}
3195
3196void internal_m2n_audio_source_pause(entt::entity id)
3197{
3198 if(auto comp = safe_get_component<audio_source_component>(id))
3199 {
3200 comp->pause();
3201 }
3202}
3203
3204void internal_m2n_audio_source_resume(entt::entity id)
3205{
3206 if(auto comp = safe_get_component<audio_source_component>(id))
3207 {
3208 comp->resume();
3209 }
3210}
3211
3212auto internal_m2n_audio_source_get_audio_clip(entt::entity id) -> hpp::uuid
3213{
3214 if(auto comp = safe_get_component<audio_source_component>(id))
3215 {
3216 return comp->get_clip().uid();
3217 }
3218
3219 return {};
3220}
3221
3222void internal_m2n_audio_source_set_audio_clip(entt::entity id, hpp::uuid uid)
3223{
3224 if(auto comp = safe_get_component<audio_source_component>(id))
3225 {
3226 auto& ctx = engine::context();
3227 auto& am = ctx.get_cached<asset_manager>();
3228
3229 auto asset = am.get_asset<audio_clip>(uid);
3230 comp->set_clip(asset);
3231 }
3232}
3233
3234//--------------------------------------------------
3235
3236//-------------------------------------------------------------------------
3237/*
3238
3239 _ _ _____ _____ _____ _ _ __ __ ______ _ _ _______
3240 | | | |_ _| | __ \ /\ / ____| | | | \/ | ____| \ | |__ __|
3241 | | | | | | | | | | / \ | | | | | | \ / | |__ | \| | | |
3242 | | | | | | | | | |/ /\ \ | | | | | | |\/| | __| | . ` | | |
3243 | |__| |_| |_ | |__| / ____ \| |____| |__| | | | | |____| |\ | | |
3244 \____/|_____| |_____/_/ \_\\_____|\____/|_| |_|______|_| \_| |_|
3245
3246
3247*/
3248//-------------------------------------------------------------------------
3249
3250auto internal_m2n_ui_document_get_asset(entt::entity id) -> hpp::uuid
3251{
3252 if(auto comp = safe_get_component<ui_document_component>(id))
3253 {
3254 return comp->asset.uid();
3255 }
3256
3257 return {};
3258}
3259
3260void internal_m2n_ui_document_set_asset(entt::entity id, const hpp::uuid& uid)
3261{
3262 if(auto comp = safe_get_component<ui_document_component>(id))
3263 {
3264 auto& ctx = engine::context();
3265 auto& am = ctx.get_cached<asset_manager>();
3266
3267 auto asset = am.get_asset<ui_tree>(uid);
3268 comp->asset = asset;
3269 }
3270}
3271
3272auto internal_m2n_ui_document_is_loaded(entt::entity id) -> bool
3273{
3274 if(auto comp = safe_get_component<ui_document_component>(id))
3275 {
3276 return comp->is_loaded();
3277 }
3278
3279 return false;
3280}
3281
3282auto internal_m2n_ui_document_is_enabled(entt::entity id) -> bool
3283{
3284 if(auto comp = safe_get_component<ui_document_component>(id))
3285 {
3286 return comp->is_enabled();
3287 }
3288
3289 return false;
3290}
3291
3292void internal_m2n_ui_document_set_enabled(entt::entity id, bool enabled)
3293{
3294 if(auto comp = safe_get_component<ui_document_component>(id))
3295 {
3296 comp->set_enabled(enabled);
3297 }
3298}
3299void internal_m2n_ui_document_close(entt::entity id)
3300{
3301 if(auto comp = safe_get_component<ui_document_component>(id))
3302 {
3303 if(comp->document)
3304 {
3305 comp->document->Close();
3306 comp->document = nullptr;
3307 }
3308 }
3309}
3310
3311auto internal_m2n_ui_document_get_title(entt::entity id) -> const std::string&
3312{
3313 if(auto comp = safe_get_component<ui_document_component>(id))
3314 {
3315 if(comp->document)
3316 {
3317 return comp->document->GetTitle();
3318 }
3319 }
3320
3321 static const std::string empty;
3322 return empty;
3323}
3324
3325void internal_m2n_ui_document_set_title(entt::entity id, const std::string& title)
3326{
3327 if(auto comp = safe_get_component<ui_document_component>(id))
3328 {
3329 if(comp->document)
3330 {
3331 comp->document->SetTitle(title);
3332 }
3333 }
3334}
3335
3336//-------------------------------------------------------------------------
3337/*
3338
3339 ______ _ ______ __ __ ______ _ _ _______
3340 | ____| | | ____| \/ | ____| \ | |__ __|
3341 | |__ | | | |__ | \ / | |__ | \| | | |
3342 | __| | | | __| | |\/| | __| | . ` | | |
3343 | |____| |____| |____| | | | |____| |\ | | |
3344 |______|______|______|_| |_|______|_| \_| |_|
3345
3346
3347*/
3348//-------------------------------------------------------------------------
3349
3350// Helper function to get UI element safely
3351auto get_ui_element_safe(entt::entity entity_id, const std::string& element_id) -> Rml::Element*
3352{
3353 if(auto comp = safe_get_component<ui_document_component>(entity_id))
3354 {
3355 if(comp->document)
3356 {
3357 return comp->document->GetElementById(element_id);
3358 }
3359 }
3360 return nullptr;
3361}
3362
3363
3364//-------------------------------------------------------------------------
3365/*
3366
3367 ______ _ _ ______ _ _ _______ _____ _ _ ____ _____ _ __ _____
3368 | ____| | | | ____| \ | |__ __| / ____| /\ | | | | | _ \ /\ / ____| |/ // ____|
3369 | |__ | | | | |__ | \| | | | | | / \ | | | | | |_) | / \ | | | ' /| (___
3370 | __| | | | | __| | . ` | | | | | / /\ \ | | | | | _ < / /\ \| | | < \___ \
3371 | |____| |__| | |____| |\ | | | | |____ / ____ \| |____| |____| |_) / ____ \ |____| . \ ____) |
3372 |______|\____/|______|_| \_| |_| \_____/_/ \_\______|______|____/_/ \_\_____|_|\_\_____/
3373
3374
3375*/
3376//-------------------------------------------------------------------------
3377
3378template<typename T>
3379void dispatch_ui_event_to_manager(const T& event_data)
3380{
3381 try
3382 {
3383 auto& ctx = engine::context();
3384 auto& script_sys = ctx.get<script_system>();
3385 auto assembly = script_sys.get_engine_assembly();
3386
3387 // Get the UIEventManager type
3388 auto ui_event_manager_type = assembly.get_type("Unravel.Core", "UIEventManager");
3389 if (!ui_event_manager_type.valid())
3390 {
3391 APPLOG_ERROR("UIEventManager type not found in assembly");
3392 return;
3393 }
3394
3395 // Get the InternalDispatchEvent method
3396 auto dispatch_method = ui_event_manager_type.get_method("InternalDispatchEvent");
3397 if (!dispatch_method.valid())
3398 {
3399 APPLOG_ERROR("UIEventManager.InternalDispatchEvent method not found");
3400 return;
3401 }
3402
3403 // Create method invoker and call it
3404 auto method_invoker = mono::make_method_invoker<void(const T&)>(dispatch_method, true);
3405 if (method_invoker.valid())
3406 {
3407 method_invoker(event_data);
3408 }
3409 else
3410 {
3411 APPLOG_ERROR("Failed to create method invoker for UIEventManager.InternalDispatchEvent");
3412 }
3413 }
3414 catch (const mono::mono_exception& e)
3415 {
3416 APPLOG_ERROR("Mono exception dispatching UI event: {}", e.what());
3417 }
3418 catch (const std::exception& e)
3419 {
3420 APPLOG_ERROR("Error dispatching UI event: {}", e.what());
3421 }
3422}
3423
3424
3425
3426// UI Event Type Classification
3427enum class ui_event_type
3428{
3429 unknown,
3430 key,
3431 textinput,
3432 pointer,
3433 change,
3434 value
3435};
3436
3437// Determine UI event type for efficient dispatch
3438auto get_ui_event_type(const Rml::Event& event) -> ui_event_type
3439{
3440 const auto event_id = event.GetId();
3441
3442 // Check key events first (most common check)
3443 if (event_id == Rml::EventId::Keydown || event_id == Rml::EventId::Keyup)
3444 {
3445 return ui_event_type::key;
3446 }
3447
3448 // Check text input events
3449 if (event_id == Rml::EventId::Textinput)
3450 {
3451 return ui_event_type::textinput;
3452 }
3453
3454 // Check pointer events
3455 if (event_id == Rml::EventId::Click || event_id == Rml::EventId::Mousedown || event_id == Rml::EventId::Mouseup ||
3456 event_id == Rml::EventId::Mousemove || event_id == Rml::EventId::Mouseover || event_id == Rml::EventId::Mouseout ||
3457 event_id == Rml::EventId::Mousescroll || event_id == Rml::EventId::Dblclick || event_id == Rml::EventId::Drag ||
3458 event_id == Rml::EventId::Dragstart || event_id == Rml::EventId::Dragover || event_id == Rml::EventId::Dragdrop)
3459 {
3460 return ui_event_type::pointer;
3461 }
3462
3463 // Check change events (need to examine the event more closely)
3464 if (event_id == Rml::EventId::Change)
3465 {
3466 auto value_str = event.GetParameter<std::string>("value", "");
3467 if (!value_str.empty())
3468 {
3469 // If the element doesn't have min/max attributes, it's likely a text input or similar (change event)
3470 if (auto* element = event.GetCurrentElement())
3471 {
3472 if (!element->HasAttribute("min") && !element->HasAttribute("max"))
3473 {
3474 return ui_event_type::change;
3475 }
3476 else
3477 {
3478 // Has min/max attributes, likely a slider (value event)
3479 return ui_event_type::value;
3480 }
3481 }
3482 }
3483 }
3484
3485 return ui_event_type::unknown;
3486}
3487
3488
3489// Fill base event data common to all event types
3490void fill_base_event_data(mono::managed_interface::ui_event_base& event_data,
3491 const Rml::Event& event,
3492 Rml::Element* target_element,
3493 Rml::Element* current_element)
3494{
3495 event_data.native_ptr = reinterpret_cast<std::intptr_t>(&event);
3496 event_data.target_element_id = target_element->GetId();
3497 event_data.target_element_ptr = reinterpret_cast<std::intptr_t>(target_element);
3498 event_data.current_element_id = current_element->GetId();
3499 event_data.current_element_ptr = reinterpret_cast<std::intptr_t>(current_element);
3500 event_data.event_type = event.GetType();
3501 event_data.phase = static_cast<int>(event.GetPhase());
3502}
3503
3504// Dispatch key event to C# UIEventManager
3505void dispatch_key_event_to_manager(const Rml::Event& event,
3506 Rml::Element* target_element,
3507 Rml::Element* current_element)
3508{
3509
3510 // Create key event data
3512 fill_base_event_data(key_event_data, event, target_element, current_element);
3513
3514 // Fill key-specific data based on actual RmlUi parameters
3515 auto key_identifier = event.GetParameter<int>("key_identifier", 0);
3516 key_event_data.key_code = RmlEngine::convert_rml_key_to_input(static_cast<Rml::Input::KeyIdentifier>(key_identifier));
3517 key_event_data.ctrl_key = event.GetParameter<int>("ctrl_key", 0) > 0;
3518 key_event_data.shift_key = event.GetParameter<int>("shift_key", 0) > 0;
3519 key_event_data.alt_key = event.GetParameter<int>("alt_key", 0) > 0;
3520 key_event_data.meta_key = event.GetParameter<int>("meta_key", 0) > 0;
3521
3522 dispatch_ui_event_to_manager(key_event_data);
3523}
3524
3525// Dispatch pointer event to C# UIEventManager
3526void dispatch_pointer_event_to_manager(const Rml::Event& event,
3527 Rml::Element* target_element,
3528 Rml::Element* current_element)
3529{
3530
3531 // Create pointer event data
3533 fill_base_event_data(pointer_event_data, event, target_element, current_element);
3534
3535 // Fill pointer-specific data based on actual RmlUi parameters
3536 pointer_event_data.x = event.GetParameter<float>("mouse_x", 0.0f);
3537 pointer_event_data.y = event.GetParameter<float>("mouse_y", 0.0f);
3538 pointer_event_data.button = event.GetParameter<int>("button", -1);
3539 pointer_event_data.ctrl_key = event.GetParameter<int>("ctrl_key", 0) > 0;
3540 pointer_event_data.shift_key = event.GetParameter<int>("shift_key", 0) > 0;
3541 pointer_event_data.alt_key = event.GetParameter<int>("alt_key", 0) > 0;
3542 pointer_event_data.meta_key = event.GetParameter<int>("meta_key", 0) > 0;
3543 pointer_event_data.delta_x = event.GetParameter<float>("wheel_delta_x", 0.0f);
3544 pointer_event_data.delta_y = event.GetParameter<float>("wheel_delta_y", 0.0f);
3545
3546 dispatch_ui_event_to_manager(pointer_event_data);
3547
3548}
3549
3550// Dispatch text input event to C# UIEventManager
3551void dispatch_textinput_event_to_manager(const Rml::Event& event,
3552 Rml::Element* target_element,
3553 Rml::Element* current_element)
3554{
3555 // Create text input event data
3557 fill_base_event_data(textinput_event_data, event, target_element, current_element);
3558
3559
3560 // Fill text input-specific data
3561 textinput_event_data.text = event.GetParameter<std::string>("text", "");
3562 textinput_event_data.ctrl_key = event.GetParameter<int>("ctrl_key", 0) > 0;
3563 textinput_event_data.shift_key = event.GetParameter<int>("shift_key", 0) > 0;
3564 textinput_event_data.alt_key = event.GetParameter<int>("alt_key", 0) > 0;
3565 textinput_event_data.meta_key = event.GetParameter<int>("meta_key", 0) > 0;
3566
3567
3568 dispatch_ui_event_to_manager(textinput_event_data);
3569}
3570
3571// Dispatch value event to C# UIEventManager
3572void dispatch_value_event_to_manager(const Rml::Event& event,
3573 Rml::Element* target_element,
3574 Rml::Element* current_element)
3575{
3576
3577 // Create value event data
3579 fill_base_event_data(value_event_data, event, target_element, current_element);
3580
3581 // Fill value-specific data
3582 value_event_data.value = event.GetParameter<float>("value", 0);
3583
3584 if(auto* slider_element = event.GetCurrentElement())
3585 {
3586 value_event_data.min_value = slider_element->GetAttribute<float>("min", 0);
3587 value_event_data.max_value = slider_element->GetAttribute<float>("max", 0);
3588 value_event_data.step = slider_element->GetAttribute<float>("step", 0);
3589 }
3590
3591 dispatch_ui_event_to_manager(value_event_data);
3592}
3593
3594// Dispatch change event to C# UIEventManager
3595void dispatch_change_event_to_manager(const Rml::Event& event,
3596 Rml::Element* target_element,
3597 Rml::Element* current_element)
3598{
3599
3600 // Create change event data
3602 fill_base_event_data(change_event_data, event, target_element, current_element);
3603
3604 // Fill change-specific data
3605 change_event_data.value = event.GetParameter<std::string>("value", "");
3606
3607 dispatch_ui_event_to_manager(change_event_data);
3608
3609}
3610
3611// Dispatch base event to C# UIEventManager (fallback)
3612void dispatch_base_event_to_manager(const Rml::Event& event,
3613 Rml::Element* target_element,
3614 Rml::Element* current_element)
3615{
3617 fill_base_event_data(event_data, event, target_element, current_element);
3618 dispatch_ui_event_to_manager(event_data);
3619}
3620
3621// Global event listener that dispatches all UI events to C# UIEventManager
3622class ui_global_event_listener : public Rml::EventListener
3623{
3624 Rml::Event* current_event_ = nullptr;
3625public:
3626 void ProcessEvent(Rml::Event& event) override
3627 {
3628 current_event_ = &event;
3629 try
3630 {
3631 // Get event information
3632 auto* target_element = event.GetTargetElement();
3633 if (!target_element)
3634 {
3635 return;
3636 }
3637
3638 auto* current_element = event.GetCurrentElement();
3639 if (!current_element)
3640 {
3641 return;
3642 }
3643
3644 // Determine event type and dispatch accordingly using efficient switch
3645 const auto event_type = get_ui_event_type(event);
3646
3647 switch (event_type)
3648 {
3649 case ui_event_type::key:
3650 dispatch_key_event_to_manager(event, target_element, current_element);
3651 break;
3652
3653 case ui_event_type::textinput:
3654 dispatch_textinput_event_to_manager(event, target_element, current_element);
3655 break;
3656
3657 case ui_event_type::pointer:
3658 dispatch_pointer_event_to_manager(event, target_element, current_element);
3659 break;
3660
3661 case ui_event_type::change:
3662 dispatch_change_event_to_manager(event, target_element, current_element);
3663 break;
3664
3665 case ui_event_type::value:
3666 dispatch_value_event_to_manager(event, target_element, current_element);
3667 break;
3668
3669 case ui_event_type::unknown:
3670 default:
3671 // Fallback to base event for unknown types
3672 dispatch_base_event_to_manager(event, target_element, current_element);
3673 break;
3674 }
3675 }
3676 catch (const std::exception& e)
3677 {
3678 APPLOG_ERROR("Error processing UI event: {}", e.what());
3679 }
3680 current_event_ = nullptr;
3681 }
3682
3683 // Allow access to current event for propagation control
3684 auto get_current_event() const -> Rml::Event*
3685 {
3686 return current_event_;
3687 }
3688};
3689
3690// Global event listener instance
3691ui_global_event_listener g_ui_global_listener;
3692
3693// Ensure a native event listener is attached to the element for the given event type
3694void internal_m2n_ui_ensure_native_event_listener(std::intptr_t element_ptr, const std::string& event_type)
3695{
3696 if (element_ptr == 0)
3697 {
3698 return;
3699 }
3700
3701 try
3702 {
3703 auto* element = reinterpret_cast<Rml::Element*>(element_ptr);
3704
3705 // Add event listener to the element
3706 // Note: RmlUi handles duplicate listeners internally, so it's safe to call this multiple times
3707 element->AddEventListener(event_type, &g_ui_global_listener);
3708
3709 APPLOG_TRACE("Ensured native UI event listener: element='{}', event='{}'", element->GetId(), event_type);
3710 }
3711 catch (const mono::mono_exception& e)
3712 {
3713 APPLOG_ERROR("Mono exception ensuring native UI event listener: {}", e.what());
3714 }
3715 catch (const std::exception& e)
3716 {
3717 APPLOG_ERROR("Error ensuring native UI event listener: {}", e.what());
3718 }
3719}
3720
3721// Stop event propagation - called from C# UIEventBase.StopPropagation()
3722void internal_m2n_ui_stop_propagation(std::intptr_t native_ptr)
3723{
3724 try
3725 {
3726
3727 auto* current_event = g_ui_global_listener.get_current_event();
3728 if (current_event && current_event == reinterpret_cast<Rml::Event*>(native_ptr))
3729 {
3730 current_event->StopPropagation();
3731 }
3732 else
3733 {
3734 APPLOG_WARNING("No current UI event to stop propagation on");
3735 }
3736
3737 }
3738 catch (const std::exception& e)
3739 {
3740 APPLOG_ERROR("Error stopping UI event propagation: {}", e.what());
3741 }
3742}
3743
3744// Stop immediate event propagation - called from C# UIEventBase.StopImmediatePropagation()
3745void internal_m2n_ui_stop_immediate_propagation(std::intptr_t native_ptr)
3746{
3747 try
3748 {
3749 auto* current_event = g_ui_global_listener.get_current_event();
3750 if (current_event)
3751 {
3752 current_event->StopImmediatePropagation();
3753 }
3754 else
3755 {
3756 APPLOG_WARNING("No current UI event to stop immediate propagation on");
3757 }
3758 }
3759 catch (const std::exception& e)
3760 {
3761 APPLOG_ERROR("Error stopping UI event immediate propagation: {}", e.what());
3762 }
3763}
3764
3765//-------------------------------------------------------------------------
3766/*
3767
3768 _ _ _____ __ _______ _____ _____ ______ _____ _____
3769 | | | |_ _| \ \ / / __ \ /\ | __ \| __ \| ____| __ \ / ____|
3770 | | | | | | \ \ /\ / /| |__) | / \ | |__) | |__) | |__ | |__) || (___
3771 | | | | | | \ \/ \/ / | _ / / /\ \ | ___/| ___/| __| | _ / \___ \
3772 | |__| |_| |_ \ /\ / | | \ \ / ____ \ | | | | | |____| | \ \ ____) |
3773 \____/|_____| \/ \/ |_| \_\/_/ \_\|_| |_| |______|_| \_\|_____/
3774
3775
3776*/
3777//-------------------------------------------------------------------------
3778
3779// Helper function to validate element pointer by checking if it exists in the owner entity's UI document
3780auto validate_ui_element_wrapper(std::intptr_t element_ptr, entt::entity owner_entity) -> bool
3781{
3782 if (element_ptr == 0)
3783 {
3784 return false;
3785 }
3786
3787 auto* element = reinterpret_cast<Rml::Element*>(element_ptr);
3788
3789 // Check if this element exists in the owner entity's UI document
3790 if (auto comp = safe_get_component<ui_document_component>(owner_entity))
3791 {
3792 if (comp->document)
3793 {
3794 // Check if this element belongs to this document
3795 return comp->document->Contains(element);
3796 }
3797 }
3798
3799 return false;
3800}
3801
3802// Helper function to validate document pointer by checking if it matches the owner entity's UI component
3803auto validate_ui_document_wrapper(std::intptr_t document_ptr, entt::entity owner_entity) -> bool
3804{
3805 if (document_ptr == 0)
3806 {
3807 return false;
3808 }
3809
3810 auto* document = reinterpret_cast<Rml::ElementDocument*>(document_ptr);
3811
3812 // Check if this document exists in the owner entity's UI component
3813 if (auto comp = safe_get_component<ui_document_component>(owner_entity))
3814 {
3815 if (comp->document && comp->document == document)
3816 {
3817 return true;
3818 }
3819 }
3820
3821 return false;
3822}
3823
3824//-------------------------------------------------------------------------
3825// UI Document Wrapper Functions
3826//-------------------------------------------------------------------------
3827
3828auto internal_m2n_ui_document_get_wrapper(entt::entity entity_id) -> std::intptr_t
3829{
3830 if (auto comp = safe_get_component<ui_document_component>(entity_id))
3831 {
3832 if (comp->document)
3833 {
3834 return reinterpret_cast<std::intptr_t>(comp->document);
3835 }
3836 }
3837 return 0;
3838}
3839
3840auto internal_m2n_ui_document_get_element_wrapper_by_id(std::intptr_t document_ptr, entt::entity owner_entity, const std::string& element_id) -> std::intptr_t
3841{
3842 if (!validate_ui_document_wrapper(document_ptr, owner_entity))
3843 {
3844 return 0;
3845 }
3846
3847 auto* document = reinterpret_cast<Rml::ElementDocument*>(document_ptr);
3848 auto* element = document->GetElementById(element_id);
3849 return reinterpret_cast<std::intptr_t>(element);
3850}
3851
3852auto internal_m2n_ui_document_query_selector_wrapper(std::intptr_t document_ptr, entt::entity owner_entity, const std::string& selector) -> std::intptr_t
3853{
3854 if (!validate_ui_document_wrapper(document_ptr, owner_entity))
3855 {
3856 return 0;
3857 }
3858
3859 auto* document = reinterpret_cast<Rml::ElementDocument*>(document_ptr);
3860 auto element = document->QuerySelector(selector);
3861 if (element)
3862 {
3863 return reinterpret_cast<std::intptr_t>(element);
3864 }
3865
3866 return 0;
3867}
3868
3869// Get element ID from element pointer
3870auto internal_m2n_ui_element_wrapper_get_id(std::intptr_t element_ptr, entt::entity owner_entity) -> std::string
3871{
3872 if (!validate_ui_element_wrapper(element_ptr, owner_entity))
3873 {
3874 return "";
3875 }
3876
3877 auto* element = reinterpret_cast<Rml::Element*>(element_ptr);
3878 return element->GetId();
3879}
3880
3881//-------------------------------------------------------------------------
3882// UI Document Wrapper Methods
3883//-------------------------------------------------------------------------
3884
3885auto internal_m2n_ui_document_wrapper_is_valid(std::intptr_t document_ptr, entt::entity owner_entity) -> bool
3886{
3887 return validate_ui_document_wrapper(document_ptr, owner_entity);
3888}
3889
3890auto internal_m2n_ui_document_wrapper_get_title(std::intptr_t document_ptr, entt::entity owner_entity) -> std::string
3891{
3892 if (!validate_ui_document_wrapper(document_ptr, owner_entity))
3893 {
3894 return "";
3895 }
3896
3897 auto* document = reinterpret_cast<Rml::ElementDocument*>(document_ptr);
3898 return document->GetTitle();
3899}
3900
3901void internal_m2n_ui_document_wrapper_set_title(std::intptr_t document_ptr, entt::entity owner_entity, const std::string& title)
3902{
3903 if (!validate_ui_document_wrapper(document_ptr, owner_entity))
3904 {
3905 return;
3906 }
3907
3908 auto* document = reinterpret_cast<Rml::ElementDocument*>(document_ptr);
3909 document->SetTitle(title);
3910}
3911
3912auto internal_m2n_ui_document_wrapper_is_visible(std::intptr_t document_ptr, entt::entity owner_entity) -> bool
3913{
3914 if (!validate_ui_document_wrapper(document_ptr, owner_entity))
3915 {
3916 return false;
3917 }
3918
3919 auto* document = reinterpret_cast<Rml::ElementDocument*>(document_ptr);
3920 return document->IsVisible();
3921}
3922
3923void internal_m2n_ui_document_wrapper_show(std::intptr_t document_ptr, entt::entity owner_entity)
3924{
3925 if (!validate_ui_document_wrapper(document_ptr, owner_entity))
3926 {
3927 return;
3928 }
3929
3930 auto* document = reinterpret_cast<Rml::ElementDocument*>(document_ptr);
3931 document->Show();
3932}
3933
3934void internal_m2n_ui_document_wrapper_hide(std::intptr_t document_ptr, entt::entity owner_entity)
3935{
3936 if (!validate_ui_document_wrapper(document_ptr, owner_entity))
3937 {
3938 return;
3939 }
3940
3941 auto* document = reinterpret_cast<Rml::ElementDocument*>(document_ptr);
3942 document->Hide();
3943}
3944
3945void internal_m2n_ui_document_wrapper_close(std::intptr_t document_ptr, entt::entity owner_entity)
3946{
3947 if (!validate_ui_document_wrapper(document_ptr, owner_entity))
3948 {
3949 return;
3950 }
3951
3952 auto* document = reinterpret_cast<Rml::ElementDocument*>(document_ptr);
3953 document->Close();
3954}
3955
3956//-------------------------------------------------------------------------
3957// UI Element Wrapper Methods
3958//-------------------------------------------------------------------------
3959
3960auto internal_m2n_ui_element_wrapper_is_valid(std::intptr_t element_ptr, entt::entity owner_entity) -> bool
3961{
3962 return validate_ui_element_wrapper(element_ptr, owner_entity);
3963}
3964
3965auto internal_m2n_ui_element_wrapper_get_inner_rml(std::intptr_t element_ptr, entt::entity owner_entity) -> std::string
3966{
3967 if (!validate_ui_element_wrapper(element_ptr, owner_entity))
3968 {
3969 return "";
3970 }
3971
3972 auto* element = reinterpret_cast<Rml::Element*>(element_ptr);
3973 return element->GetInnerRML();
3974}
3975
3976void internal_m2n_ui_element_wrapper_set_inner_rml(std::intptr_t element_ptr, entt::entity owner_entity, const std::string& rml)
3977{
3978 if (!validate_ui_element_wrapper(element_ptr, owner_entity))
3979 {
3980 return;
3981 }
3982
3983 auto* element = reinterpret_cast<Rml::Element*>(element_ptr);
3984 element->SetInnerRML(rml);
3985}
3986
3987auto internal_m2n_ui_element_wrapper_is_visible(std::intptr_t element_ptr, entt::entity owner_entity) -> bool
3988{
3989 if (!validate_ui_element_wrapper(element_ptr, owner_entity))
3990 {
3991 return false;
3992 }
3993
3994 auto* element = reinterpret_cast<Rml::Element*>(element_ptr);
3995 return element->IsVisible();
3996}
3997
3998void internal_m2n_ui_element_wrapper_set_visible(std::intptr_t element_ptr, entt::entity owner_entity, bool visible)
3999{
4000 if (!validate_ui_element_wrapper(element_ptr, owner_entity))
4001 {
4002 return;
4003 }
4004
4005 auto* element = reinterpret_cast<Rml::Element*>(element_ptr);
4006 if (visible)
4007 {
4008 element->SetProperty("display", "block");
4009 }
4010 else
4011 {
4012 element->SetProperty("display", "none");
4013 }
4014}
4015
4016auto internal_m2n_ui_element_wrapper_get_attribute(std::intptr_t element_ptr, entt::entity owner_entity, const std::string& attribute_name) -> std::string
4017{
4018 if (!validate_ui_element_wrapper(element_ptr, owner_entity))
4019 {
4020 return "";
4021 }
4022
4023 auto* element = reinterpret_cast<Rml::Element*>(element_ptr);
4024 return element->GetAttribute<Rml::String>(attribute_name, "");
4025}
4026
4027void internal_m2n_ui_element_wrapper_set_attribute(std::intptr_t element_ptr, entt::entity owner_entity, const std::string& attribute_name, const std::string& value)
4028{
4029 if (!validate_ui_element_wrapper(element_ptr, owner_entity))
4030 {
4031 return;
4032 }
4033
4034 auto* element = reinterpret_cast<Rml::Element*>(element_ptr);
4035 element->SetAttribute(attribute_name, value);
4036}
4037
4038void internal_m2n_ui_element_wrapper_remove_attribute(std::intptr_t element_ptr, entt::entity owner_entity, const std::string& attribute_name)
4039{
4040 if (!validate_ui_element_wrapper(element_ptr, owner_entity))
4041 {
4042 return;
4043 }
4044
4045 auto* element = reinterpret_cast<Rml::Element*>(element_ptr);
4046 element->RemoveAttribute(attribute_name);
4047}
4048
4049auto internal_m2n_ui_element_wrapper_has_attribute(std::intptr_t element_ptr, entt::entity owner_entity, const std::string& attribute_name) -> bool
4050{
4051 if (!validate_ui_element_wrapper(element_ptr, owner_entity))
4052 {
4053 return false;
4054 }
4055
4056 auto* element = reinterpret_cast<Rml::Element*>(element_ptr);
4057 return element->HasAttribute(attribute_name);
4058}
4059
4060void internal_m2n_ui_element_wrapper_set_class(std::intptr_t element_ptr, entt::entity owner_entity, const std::string& class_name, bool activate)
4061{
4062 if (!validate_ui_element_wrapper(element_ptr, owner_entity))
4063 {
4064 return;
4065 }
4066
4067 auto* element = reinterpret_cast<Rml::Element*>(element_ptr);
4068 element->SetClass(class_name, activate);
4069}
4070
4071auto internal_m2n_ui_element_wrapper_is_class_set(std::intptr_t element_ptr, entt::entity owner_entity, const std::string& class_name) -> bool
4072{
4073 if (!validate_ui_element_wrapper(element_ptr, owner_entity))
4074 {
4075 return false;
4076 }
4077
4078 auto* element = reinterpret_cast<Rml::Element*>(element_ptr);
4079 return element->IsClassSet(class_name);
4080}
4081
4082void internal_m2n_ui_element_wrapper_focus(std::intptr_t element_ptr, entt::entity owner_entity)
4083{
4084 if (!validate_ui_element_wrapper(element_ptr, owner_entity))
4085 {
4086 return;
4087 }
4088
4089 auto* element = reinterpret_cast<Rml::Element*>(element_ptr);
4090 element->Focus();
4091}
4092
4093void internal_m2n_ui_element_wrapper_blur(std::intptr_t element_ptr, entt::entity owner_entity)
4094{
4095 if (!validate_ui_element_wrapper(element_ptr, owner_entity))
4096 {
4097 return;
4098 }
4099
4100 auto* element = reinterpret_cast<Rml::Element*>(element_ptr);
4101 element->Blur();
4102}
4103
4104void internal_m2n_ui_element_wrapper_click(std::intptr_t element_ptr, entt::entity owner_entity)
4105{
4106 if (!validate_ui_element_wrapper(element_ptr, owner_entity))
4107 {
4108 return;
4109 }
4110
4111 auto* element = reinterpret_cast<Rml::Element*>(element_ptr);
4112 element->Click();
4113}
4114
4115void internal_m2n_ui_element_wrapper_scroll_into_view(std::intptr_t element_ptr, entt::entity owner_entity, bool align_with_top)
4116{
4117 if (!validate_ui_element_wrapper(element_ptr, owner_entity))
4118 {
4119 return;
4120 }
4121
4122 auto* element = reinterpret_cast<Rml::Element*>(element_ptr);
4123 element->ScrollIntoView(align_with_top);
4124}
4125
4126
4127//--------------------------------------------------
4128} // namespace
4129
4130auto script_system::bind_internal_calls(rtti::context& ctx) -> bool
4131{
4132 APPLOG_TRACE("{}::{}", hpp::type_name_str(*this), __func__);
4133
4134 {
4135 auto reg = mono::internal_call_registry("Unravel.Core.Log");
4136 reg.add_internal_call("internal_m2n_log_trace", internal_call(internal_m2n_log_trace));
4137 reg.add_internal_call("internal_m2n_log_info", internal_call(internal_m2n_log_info));
4138 reg.add_internal_call("internal_m2n_log_warning", internal_call(internal_m2n_log_warning));
4139 reg.add_internal_call("internal_m2n_log_error", internal_call(internal_m2n_log_error));
4140 }
4141
4142 {
4143 auto reg = mono::internal_call_registry("Unravel.Core.Scene");
4144 reg.add_internal_call("internal_m2n_load_scene", internal_call(internal_m2n_load_scene));
4145 reg.add_internal_call("internal_m2n_load_scene_uid", internal_call(internal_m2n_load_scene_uid));
4146 reg.add_internal_call("internal_m2n_create_scene", internal_call(internal_m2n_create_scene));
4147 reg.add_internal_call("internal_m2n_destroy_scene", internal_call(internal_m2n_destroy_scene));
4148 reg.add_internal_call("internal_m2n_create_entity", internal_call(internal_m2n_create_entity));
4149 reg.add_internal_call("internal_m2n_create_entity_from_prefab_uid",
4150 internal_call(internal_m2n_create_entity_from_prefab_uid));
4151 reg.add_internal_call("internal_m2n_create_entity_from_prefab_key",
4152 internal_call(internal_m2n_create_entity_from_prefab_key));
4153 reg.add_internal_call("internal_m2n_clone_entity", internal_call(internal_m2n_clone_entity));
4154 reg.add_internal_call("internal_m2n_destroy_entity", internal_call(internal_m2n_destroy_entity));
4155 reg.add_internal_call("internal_m2n_destroy_entity_immediate",
4156 internal_call(internal_m2n_destroy_entity_immediate));
4157
4158 reg.add_internal_call("internal_m2n_is_entity_valid", internal_call(internal_m2n_is_entity_valid));
4159 reg.add_internal_call("internal_m2n_find_entity_by_name", internal_call(internal_m2n_find_entity_by_name));
4160 reg.add_internal_call("internal_m2n_find_entities_by_name", internal_call(internal_m2n_find_entities_by_name));
4161 reg.add_internal_call("internal_m2n_find_entity_by_tag", internal_call(internal_m2n_find_entity_by_tag));
4162 reg.add_internal_call("internal_m2n_find_entities_by_tag", internal_call(internal_m2n_find_entities_by_tag));
4163 reg.add_internal_call("internal_m2n_find_entities_with_component", internal_call(internal_m2n_find_entities_with_component));
4164 reg.add_internal_call("internal_m2n_find_entities_with_components", internal_call(internal_m2n_find_entities_with_components));
4165 }
4166
4167 {
4168 auto reg = mono::internal_call_registry("Unravel.Core.Entity");
4169 reg.add_internal_call("internal_m2n_add_component", internal_call(internal_m2n_add_component));
4170 reg.add_internal_call("internal_m2n_get_component", internal_call(internal_m2n_get_component));
4171 reg.add_internal_call("internal_m2n_get_component_in_children",
4172 internal_call(internal_m2n_get_component_in_children));
4173 reg.add_internal_call("internal_m2n_has_component", internal_call(internal_m2n_has_component));
4174 reg.add_internal_call("internal_m2n_get_components", internal_call(internal_m2n_get_components));
4175 reg.add_internal_call("internal_m2n_get_components_in_children",
4176 internal_call(internal_m2n_get_components_in_children));
4177
4178 reg.add_internal_call("internal_m2n_remove_component_instance",
4179 internal_call(internal_m2n_remove_component_instance));
4180 reg.add_internal_call("internal_m2n_remove_component_instance_delay",
4181 internal_call(internal_m2n_remove_component_instance_delay));
4182
4183 reg.add_internal_call("internal_m2n_remove_component", internal_call(internal_m2n_remove_component));
4184 reg.add_internal_call("internal_m2n_remove_component_delay",
4185 internal_call(internal_m2n_remove_component_delay));
4186
4187 reg.add_internal_call("internal_m2n_get_transform_component",
4188 internal_call(internal_m2n_get_transform_component));
4189 reg.add_internal_call("internal_m2n_get_name", internal_call(internal_m2n_get_name));
4190 reg.add_internal_call("internal_m2n_set_name", internal_call(internal_m2n_set_name));
4191 reg.add_internal_call("internal_m2n_get_tag", internal_call(internal_m2n_get_tag));
4192 reg.add_internal_call("internal_m2n_set_tag", internal_call(internal_m2n_set_tag));
4193 reg.add_internal_call("internal_m2n_get_layers", internal_call(internal_m2n_get_layers));
4194 reg.add_internal_call("internal_m2n_set_layers", internal_call(internal_m2n_set_layers));
4195
4196 reg.add_internal_call("internal_m2n_get_active_global", internal_call(internal_m2n_get_active_global));
4197 reg.add_internal_call("internal_m2n_get_active_local", internal_call(internal_m2n_get_active_local));
4198 reg.add_internal_call("internal_m2n_set_active_local", internal_call(internal_m2n_set_active_local));
4199 }
4200
4201 {
4202 auto reg = mono::internal_call_registry("Unravel.Core.TransformComponent");
4203 reg.add_internal_call("internal_m2n_get_children", internal_call(internal_m2n_get_children));
4204 reg.add_internal_call("internal_m2n_get_child", internal_call(internal_m2n_get_child));
4205 reg.add_internal_call("internal_m2n_get_parent", internal_call(internal_m2n_get_parent));
4206 reg.add_internal_call("internal_m2n_set_parent", internal_call(internal_m2n_set_parent));
4207
4208 reg.add_internal_call("internal_m2n_get_position_global", internal_call(internal_m2n_get_position_global));
4209 reg.add_internal_call("internal_m2n_set_position_global", internal_call(internal_m2n_set_position_global));
4210 reg.add_internal_call("internal_m2n_move_by_global", internal_call(internal_m2n_move_by_global));
4211
4212 reg.add_internal_call("internal_m2n_get_position_local", internal_call(internal_m2n_get_position_local));
4213 reg.add_internal_call("internal_m2n_set_position_local", internal_call(internal_m2n_set_position_local));
4214 reg.add_internal_call("internal_m2n_move_by_local", internal_call(internal_m2n_move_by_local));
4215
4216 // Euler
4217 reg.add_internal_call("internal_m2n_get_rotation_euler_global",
4218 internal_call(internal_m2n_get_rotation_euler_global));
4219 reg.add_internal_call("internal_m2n_set_rotation_euler_global",
4220 internal_call(internal_m2n_set_rotation_euler_global));
4221 reg.add_internal_call("internal_m2n_rotate_by_euler_global",
4222 internal_call(internal_m2n_rotate_by_euler_global));
4223
4224 reg.add_internal_call("internal_m2n_get_rotation_euler_local",
4225 internal_call(internal_m2n_get_rotation_euler_local));
4226 reg.add_internal_call("internal_m2n_set_rotation_euler_local",
4227 internal_call(internal_m2n_set_rotation_euler_local));
4228 reg.add_internal_call("internal_m2n_rotate_by_euler_local", internal_call(internal_m2n_rotate_by_euler_local));
4229
4230 // Quat
4231 reg.add_internal_call("internal_m2n_get_rotation_global", internal_call(internal_m2n_get_rotation_global));
4232 reg.add_internal_call("internal_m2n_set_rotation_global", internal_call(internal_m2n_set_rotation_global));
4233 reg.add_internal_call("internal_m2n_rotate_by_global", internal_call(internal_m2n_rotate_by_global));
4234
4235 reg.add_internal_call("internal_m2n_get_rotation_local", internal_call(internal_m2n_get_rotation_local));
4236 reg.add_internal_call("internal_m2n_set_rotation_local", internal_call(internal_m2n_set_rotation_local));
4237 reg.add_internal_call("internal_m2n_rotate_by_local", internal_call(internal_m2n_rotate_by_local));
4238
4239 // Other
4240 reg.add_internal_call("internal_m2n_rotate_axis_global", internal_call(internal_m2n_rotate_axis_global));
4241 reg.add_internal_call("internal_m2n_look_at", internal_call(internal_m2n_look_at));
4242 reg.add_internal_call("internal_m2n_transform_vector_global",
4243 internal_call(internal_m2n_transform_vector_global));
4244 reg.add_internal_call("internal_m2n_inverse_transform_vector_global",
4245 internal_call(internal_m2n_inverse_transform_vector_global));
4246
4247 reg.add_internal_call("internal_m2n_transform_direction_global",
4248 internal_call(internal_m2n_transform_direction_global));
4249 reg.add_internal_call("internal_m2n_inverse_transform_direction_global",
4250 internal_call(internal_m2n_inverse_transform_direction_global));
4251
4252 // Scale
4253 reg.add_internal_call("internal_m2n_get_scale_global", internal_call(internal_m2n_get_scale_global));
4254 reg.add_internal_call("internal_m2n_set_scale_global", internal_call(internal_m2n_set_scale_global));
4255 reg.add_internal_call("internal_m2n_scale_by_global", internal_call(internal_m2n_scale_by_local));
4256
4257 reg.add_internal_call("internal_m2n_get_scale_local", internal_call(internal_m2n_get_scale_local));
4258 reg.add_internal_call("internal_m2n_set_scale_local", internal_call(internal_m2n_set_scale_local));
4259 reg.add_internal_call("internal_m2n_scale_by_local", internal_call(internal_m2n_scale_by_local));
4260
4261 // Skew
4262 reg.add_internal_call("internal_m2n_get_skew_global", internal_call(internal_m2n_get_skew_global));
4263 reg.add_internal_call("internal_m2n_set_skew_globa", internal_call(internal_m2n_setl_skew_globa));
4264 reg.add_internal_call("internal_m2n_get_skew_local", internal_call(internal_m2n_get_skew_local));
4265 reg.add_internal_call("internal_m2n_set_skew_local", internal_call(internal_m2n_set_skew_local));
4266 }
4267
4268 {
4269 auto reg = mono::internal_call_registry("Unravel.Core.PhysicsComponent");
4270 reg.add_internal_call("internal_m2n_physics_apply_explosion_force",
4271 internal_call(internal_m2n_physics_apply_explosion_force));
4272 reg.add_internal_call("internal_m2n_physics_apply_force", internal_call(internal_m2n_physics_apply_force));
4273 reg.add_internal_call("internal_m2n_physics_apply_torque", internal_call(internal_m2n_physics_apply_torque));
4274 reg.add_internal_call("internal_m2n_physics_get_velocity", internal_call(internal_m2n_physics_get_velocity));
4275 reg.add_internal_call("internal_m2n_physics_set_velocity", internal_call(internal_m2n_physics_set_velocity));
4276 reg.add_internal_call("internal_m2n_physics_get_angular_velocity",
4277 internal_call(internal_m2n_physics_get_angular_velocity));
4278 reg.add_internal_call("internal_m2n_physics_set_angular_velocity",
4279 internal_call(internal_m2n_physics_set_angular_velocity));
4280
4281 reg.add_internal_call("internal_m2n_physics_get_include_layers",
4282 internal_call(internal_m2n_physics_get_include_layers));
4283 reg.add_internal_call("internal_m2n_physics_set_include_layers",
4284 internal_call(internal_m2n_physics_set_include_layers));
4285 reg.add_internal_call("internal_m2n_physics_get_exclude_layers",
4286 internal_call(internal_m2n_physics_get_exclude_layers));
4287 reg.add_internal_call("internal_m2n_physics_set_exclude_layers",
4288 internal_call(internal_m2n_physics_set_exclude_layers));
4289 reg.add_internal_call("internal_m2n_physics_get_collision_layers",
4290 internal_call(internal_m2n_physics_get_collision_layers));
4291 }
4292
4293 {
4294 auto reg = mono::internal_call_registry("Unravel.Core.AnimationComponent");
4295 reg.add_internal_call("internal_m2n_animation_blend", internal_call(internal_m2n_animation_blend));
4296 reg.add_internal_call("internal_m2n_animation_play", internal_call(internal_m2n_animation_play));
4297 reg.add_internal_call("internal_m2n_animation_pause", internal_call(internal_m2n_animation_pause));
4298 reg.add_internal_call("internal_m2n_animation_resume", internal_call(internal_m2n_animation_resume));
4299 reg.add_internal_call("internal_m2n_animation_stop", internal_call(internal_m2n_animation_stop));
4300 reg.add_internal_call("internal_m2n_animation_set_speed", internal_call(internal_m2n_animation_set_speed));
4301 reg.add_internal_call("internal_m2n_animation_get_speed", internal_call(internal_m2n_animation_get_speed));
4302 }
4303
4304 {
4305 auto reg = mono::internal_call_registry("Unravel.Core.CameraComponent");
4306 reg.add_internal_call("internal_m2n_camera_screen_point_to_ray",
4307 internal_call(internal_m2n_camera_screen_point_to_ray));
4308 }
4309
4310 {
4311 auto reg = mono::internal_call_registry("Unravel.Core.ModelComponent");
4312 reg.add_internal_call("internal_m2n_model_get_enabled", internal_call(internal_m2n_model_get_enabled));
4313 reg.add_internal_call("internal_m2n_model_set_enabled", internal_call(internal_m2n_model_set_enabled));
4314 reg.add_internal_call("internal_m2n_model_get_shared_material",
4315 internal_call(internal_m2n_model_get_shared_material));
4316 reg.add_internal_call("internal_m2n_model_get_shared_material_count",
4317 internal_call(internal_m2n_model_get_shared_material_count));
4318 reg.add_internal_call("internal_m2n_model_set_shared_material",
4319 internal_call(internal_m2n_model_set_shared_material));
4320 reg.add_internal_call("internal_m2n_model_set_material_instance",
4321 internal_call(internal_m2n_model_set_material_instance));
4322 reg.add_internal_call("internal_m2n_model_get_material_instance",
4323 internal_call(internal_m2n_model_get_material_instance));
4324 reg.add_internal_call("internal_m2n_model_get_material_instance_count",
4325 internal_call(internal_m2n_model_get_material_instance_count));
4326 }
4327
4328 {
4329 auto reg = mono::internal_call_registry("Unravel.Core.ParticleEmitterComponent");
4330 reg.add_internal_call("internal_m2n_particle_emitter_get_enabled",
4331 internal_call(internal_m2n_particle_emitter_get_enabled));
4332 reg.add_internal_call("internal_m2n_particle_emitter_set_enabled",
4333 internal_call(internal_m2n_particle_emitter_set_enabled));
4334 reg.add_internal_call("internal_m2n_particle_emitter_get_max_particles",
4335 internal_call(internal_m2n_particle_emitter_get_max_particles));
4336 reg.add_internal_call("internal_m2n_particle_emitter_set_max_particles",
4337 internal_call(internal_m2n_particle_emitter_set_max_particles));
4338 reg.add_internal_call("internal_m2n_particle_emitter_get_shape",
4339 internal_call(internal_m2n_particle_emitter_get_shape));
4340 reg.add_internal_call("internal_m2n_particle_emitter_set_shape",
4341 internal_call(internal_m2n_particle_emitter_set_shape));
4342 reg.add_internal_call("internal_m2n_particle_emitter_get_direction",
4343 internal_call(internal_m2n_particle_emitter_get_direction));
4344 reg.add_internal_call("internal_m2n_particle_emitter_set_direction",
4345 internal_call(internal_m2n_particle_emitter_set_direction));
4346 reg.add_internal_call("internal_m2n_particle_emitter_get_gravity_scale",
4347 internal_call(internal_m2n_particle_emitter_get_gravity_scale));
4348 reg.add_internal_call("internal_m2n_particle_emitter_set_gravity_scale",
4349 internal_call(internal_m2n_particle_emitter_set_gravity_scale));
4350 reg.add_internal_call("internal_m2n_particle_emitter_get_emission_rate",
4351 internal_call(internal_m2n_particle_emitter_get_emission_rate));
4352 reg.add_internal_call("internal_m2n_particle_emitter_set_emission_rate",
4353 internal_call(internal_m2n_particle_emitter_set_emission_rate));
4354 reg.add_internal_call("internal_m2n_particle_emitter_get_temporal_motion",
4355 internal_call(internal_m2n_particle_emitter_get_temporal_motion));
4356 reg.add_internal_call("internal_m2n_particle_emitter_set_temporal_motion",
4357 internal_call(internal_m2n_particle_emitter_set_temporal_motion));
4358 reg.add_internal_call("internal_m2n_particle_emitter_get_velocity_damping",
4359 internal_call(internal_m2n_particle_emitter_get_velocity_damping));
4360 reg.add_internal_call("internal_m2n_particle_emitter_set_velocity_damping",
4361 internal_call(internal_m2n_particle_emitter_set_velocity_damping));
4362 reg.add_internal_call("internal_m2n_particle_emitter_get_blend_multiplier",
4363 internal_call(internal_m2n_particle_emitter_get_blend_multiplier));
4364 reg.add_internal_call("internal_m2n_particle_emitter_set_blend_multiplier",
4365 internal_call(internal_m2n_particle_emitter_set_blend_multiplier));
4366 reg.add_internal_call("internal_m2n_particle_emitter_get_force_over_lifetime",
4367 internal_call(internal_m2n_particle_emitter_get_force_over_lifetime));
4368 reg.add_internal_call("internal_m2n_particle_emitter_set_force_over_lifetime",
4369 internal_call(internal_m2n_particle_emitter_set_force_over_lifetime));
4370 reg.add_internal_call("internal_m2n_particle_emitter_get_emission_shape_scale",
4371 internal_call(internal_m2n_particle_emitter_get_emission_shape_scale));
4372 reg.add_internal_call("internal_m2n_particle_emitter_set_emission_shape_scale",
4373 internal_call(internal_m2n_particle_emitter_set_emission_shape_scale));
4374 reg.add_internal_call("internal_m2n_particle_emitter_get_emission_lifetime",
4375 internal_call(internal_m2n_particle_emitter_get_emission_lifetime));
4376 reg.add_internal_call("internal_m2n_particle_emitter_set_emission_lifetime",
4377 internal_call(internal_m2n_particle_emitter_set_emission_lifetime));
4378 reg.add_internal_call("internal_m2n_particle_emitter_get_lifetime",
4379 internal_call(internal_m2n_particle_emitter_get_lifetime));
4380 reg.add_internal_call("internal_m2n_particle_emitter_set_lifetime",
4381 internal_call(internal_m2n_particle_emitter_set_lifetime));
4382 reg.add_internal_call("internal_m2n_particle_emitter_get_position_easing",
4383 internal_call(internal_m2n_particle_emitter_get_position_easing));
4384 reg.add_internal_call("internal_m2n_particle_emitter_set_position_easing",
4385 internal_call(internal_m2n_particle_emitter_set_position_easing));
4386 reg.add_internal_call("internal_m2n_particle_emitter_get_num_particles",
4387 internal_call(internal_m2n_particle_emitter_get_num_particles));
4388 reg.add_internal_call("internal_m2n_particle_emitter_is_playing",
4389 internal_call(internal_m2n_particle_emitter_is_playing));
4390 reg.add_internal_call("internal_m2n_particle_emitter_is_paused",
4391 internal_call(internal_m2n_particle_emitter_is_paused));
4392 reg.add_internal_call("internal_m2n_particle_emitter_get_texture",
4393 internal_call(internal_m2n_particle_emitter_get_texture));
4394 reg.add_internal_call("internal_m2n_particle_emitter_set_texture",
4395 internal_call(internal_m2n_particle_emitter_set_texture));
4396 reg.add_internal_call("internal_m2n_particle_emitter_play",
4397 internal_call(internal_m2n_particle_emitter_play));
4398 reg.add_internal_call("internal_m2n_particle_emitter_stop",
4399 internal_call(internal_m2n_particle_emitter_stop));
4400 reg.add_internal_call("internal_m2n_particle_emitter_stop_and_reset",
4401 internal_call(internal_m2n_particle_emitter_stop_and_reset));
4402 reg.add_internal_call("internal_m2n_particle_emitter_pause",
4403 internal_call(internal_m2n_particle_emitter_pause));
4404 reg.add_internal_call("internal_m2n_particle_emitter_resume",
4405 internal_call(internal_m2n_particle_emitter_resume));
4406 reg.add_internal_call("internal_m2n_particle_emitter_reset_emitter",
4407 internal_call(internal_m2n_particle_emitter_reset_emitter));
4408 reg.add_internal_call("internal_m2n_particle_emitter_get_loop",
4409 internal_call(internal_m2n_particle_emitter_get_loop));
4410 reg.add_internal_call("internal_m2n_particle_emitter_set_loop",
4411 internal_call(internal_m2n_particle_emitter_set_loop));
4412 }
4413
4414 {
4415 auto reg = mono::internal_call_registry("Unravel.Core.TextComponent");
4416 reg.add_internal_call("internal_m2n_text_get_text", internal_call(internal_m2n_text_get_text));
4417 reg.add_internal_call("internal_m2n_text_set_text", internal_call(internal_m2n_text_set_text));
4418 reg.add_internal_call("internal_m2n_text_get_buffer_type", internal_call(internal_m2n_text_get_buffer_type));
4419 reg.add_internal_call("internal_m2n_text_set_buffer_type", internal_call(internal_m2n_text_set_buffer_type));
4420 reg.add_internal_call("internal_m2n_text_get_overflow_type",
4421 internal_call(internal_m2n_text_get_overflow_type));
4422 reg.add_internal_call("internal_m2n_text_set_overflow_type",
4423 internal_call(internal_m2n_text_set_overflow_type));
4424 reg.add_internal_call("internal_m2n_text_get_font", internal_call(internal_m2n_text_get_font));
4425 reg.add_internal_call("internal_m2n_text_set_font", internal_call(internal_m2n_text_set_font));
4426
4427 reg.add_internal_call("internal_m2n_text_get_font_size", internal_call(internal_m2n_text_get_font_size));
4428 reg.add_internal_call("internal_m2n_text_set_font_size", internal_call(internal_m2n_text_set_font_size));
4429 reg.add_internal_call("internal_m2n_text_get_render_font_size",
4430 internal_call(internal_m2n_text_get_render_font_size));
4431
4432 reg.add_internal_call("internal_m2n_text_get_auto_size", internal_call(internal_m2n_text_get_auto_size));
4433 reg.add_internal_call("internal_m2n_text_set_auto_size", internal_call(internal_m2n_text_set_auto_size));
4434
4435 reg.add_internal_call("internal_m2n_text_get_auto_size_range",
4436 internal_call(internal_m2n_text_get_auto_size_range));
4437 reg.add_internal_call("internal_m2n_text_set_auto_size_range",
4438 internal_call(internal_m2n_text_set_auto_size_range));
4439
4440 reg.add_internal_call("internal_m2n_text_get_area", internal_call(internal_m2n_text_get_area));
4441 reg.add_internal_call("internal_m2n_text_set_area", internal_call(internal_m2n_text_set_area));
4442 reg.add_internal_call("internal_m2n_text_get_render_area", internal_call(internal_m2n_text_get_render_area));
4443
4444 reg.add_internal_call("internal_m2n_text_get_is_rich_text", internal_call(internal_m2n_text_get_is_rich_text));
4445 reg.add_internal_call("internal_m2n_text_set_is_rich_text", internal_call(internal_m2n_text_set_is_rich_text));
4446
4447 reg.add_internal_call("internal_m2n_text_get_alignment", internal_call(internal_m2n_text_get_alignment));
4448 reg.add_internal_call("internal_m2n_text_set_alignment", internal_call(internal_m2n_text_set_alignment));
4449
4450 reg.add_internal_call("internal_m2n_text_get_bounds", internal_call(internal_m2n_text_get_bounds));
4451 reg.add_internal_call("internal_m2n_text_get_render_bounds", internal_call(internal_m2n_text_get_render_bounds));
4452
4453 // Text Style Functions
4454 reg.add_internal_call("internal_m2n_text_set_opacity", internal_call(internal_m2n_text_set_opacity));
4455 reg.add_internal_call("internal_m2n_text_get_opacity", internal_call(internal_m2n_text_get_opacity));
4456 reg.add_internal_call("internal_m2n_text_set_text_color", internal_call(internal_m2n_text_set_text_color));
4457 reg.add_internal_call("internal_m2n_text_get_text_color", internal_call(internal_m2n_text_get_text_color));
4458 reg.add_internal_call("internal_m2n_text_set_background_color", internal_call(internal_m2n_text_set_background_color));
4459 reg.add_internal_call("internal_m2n_text_get_background_color", internal_call(internal_m2n_text_get_background_color));
4460 reg.add_internal_call("internal_m2n_text_set_foreground_color", internal_call(internal_m2n_text_set_foreground_color));
4461 reg.add_internal_call("internal_m2n_text_get_foreground_color", internal_call(internal_m2n_text_get_foreground_color));
4462 reg.add_internal_call("internal_m2n_text_set_overline_color", internal_call(internal_m2n_text_set_overline_color));
4463 reg.add_internal_call("internal_m2n_text_get_overline_color", internal_call(internal_m2n_text_get_overline_color));
4464 reg.add_internal_call("internal_m2n_text_set_underline_color", internal_call(internal_m2n_text_set_underline_color));
4465 reg.add_internal_call("internal_m2n_text_get_underline_color", internal_call(internal_m2n_text_get_underline_color));
4466 reg.add_internal_call("internal_m2n_text_set_strike_color", internal_call(internal_m2n_text_set_strike_color));
4467 reg.add_internal_call("internal_m2n_text_get_strike_color", internal_call(internal_m2n_text_get_strike_color));
4468 reg.add_internal_call("internal_m2n_text_set_outline_color", internal_call(internal_m2n_text_set_outline_color));
4469 reg.add_internal_call("internal_m2n_text_get_outline_color", internal_call(internal_m2n_text_get_outline_color));
4470 reg.add_internal_call("internal_m2n_text_set_outline_width", internal_call(internal_m2n_text_set_outline_width));
4471 reg.add_internal_call("internal_m2n_text_get_outline_width", internal_call(internal_m2n_text_get_outline_width));
4472 reg.add_internal_call("internal_m2n_text_set_shadow_offsets", internal_call(internal_m2n_text_set_shadow_offsets));
4473 reg.add_internal_call("internal_m2n_text_get_shadow_offsets", internal_call(internal_m2n_text_get_shadow_offsets));
4474 reg.add_internal_call("internal_m2n_text_set_shadow_color", internal_call(internal_m2n_text_set_shadow_color));
4475 reg.add_internal_call("internal_m2n_text_get_shadow_color", internal_call(internal_m2n_text_get_shadow_color));
4476 reg.add_internal_call("internal_m2n_text_set_shadow_softener", internal_call(internal_m2n_text_set_shadow_softener));
4477 reg.add_internal_call("internal_m2n_text_get_shadow_softener", internal_call(internal_m2n_text_get_shadow_softener));
4478 reg.add_internal_call("internal_m2n_text_set_style_flags", internal_call(internal_m2n_text_set_style_flags));
4479 reg.add_internal_call("internal_m2n_text_get_style_flags", internal_call(internal_m2n_text_get_style_flags));
4480 }
4481
4482 {
4483 auto reg = mono::internal_call_registry("Unravel.Core.LightComponent");
4484 reg.add_internal_call("internal_m2n_light_get_color", internal_call(internal_m2n_light_get_color));
4485 reg.add_internal_call("internal_m2n_light_set_color", internal_call(internal_m2n_light_set_color));
4486 }
4487
4488 {
4489 auto reg = mono::internal_call_registry("Unravel.Core.Assets");
4490 reg.add_internal_call("internal_m2n_get_asset_by_uuid", internal_call(internal_m2n_get_asset_by_uuid));
4491 reg.add_internal_call("internal_m2n_get_asset_by_key", internal_call(internal_m2n_get_asset_by_key));
4492 reg.add_internal_call("internal_m2n_get_material_properties",
4493 internal_call(internal_m2n_get_material_properties));
4494 }
4495
4496 {
4497 auto reg = mono::internal_call_registry("Unravel.Core.AudioClip");
4498 reg.add_internal_call("internal_m2n_audio_clip_get_length", internal_call(internal_m2n_audio_clip_get_length));
4499 }
4500
4501 {
4502 auto reg = mono::internal_call_registry("Quaternion");
4503 reg.add_internal_call("internal_m2n_from_euler_rad", internal_call(internal_m2n_from_euler_rad));
4504 reg.add_internal_call("internal_m2n_to_euler_rad", internal_call(internal_m2n_to_euler_rad));
4505 reg.add_internal_call("internal_m2n_from_to_rotation", internal_call(internal_m2n_from_to_rotation));
4506 reg.add_internal_call("internal_m2n_angle_axis", internal_call(internal_m2n_angle_axis));
4507 reg.add_internal_call("internal_m2n_look_rotation", internal_call(internal_m2n_look_rotation));
4508 }
4509
4510 {
4511 auto reg = mono::internal_call_registry("Unravel.Core.Gizmos");
4512 reg.add_internal_call("internal_m2n_gizmos_add_sphere", internal_call(internal_m2n_gizmos_add_sphere));
4513 reg.add_internal_call("internal_m2n_gizmos_add_ray", internal_call(internal_m2n_gizmos_add_ray));
4514 }
4515
4516 {
4517 auto reg = mono::internal_call_registry("Unravel.Core.Tests");
4518 reg.add_internal_call("m2n_test_uuid", internal_call(m2n_test_uuid));
4519 }
4520
4521 {
4522 auto reg = mono::internal_call_registry("Unravel.Core.LayerMask");
4523 reg.add_internal_call("internal_m2n_layers_layer_to_name", internal_call(internal_m2n_layers_layer_to_name));
4524 reg.add_internal_call("internal_m2n_layers_name_to_layer", internal_call(internal_m2n_layers_name_to_layer));
4525 }
4526
4527 {
4528 auto reg = mono::internal_call_registry("Unravel.Core.Input");
4529 reg.add_internal_call("internal_m2n_input_get_analog_value",
4530 internal_call(internal_m2n_input_get_analog_value));
4531 reg.add_internal_call("internal_m2n_input_get_digital_value",
4532 internal_call(internal_m2n_input_get_analog_value));
4533 reg.add_internal_call("internal_m2n_input_is_pressed", internal_call(internal_m2n_input_is_pressed));
4534 reg.add_internal_call("internal_m2n_input_is_released", internal_call(internal_m2n_input_is_released));
4535 reg.add_internal_call("internal_m2n_input_is_down", internal_call(internal_m2n_input_is_down));
4536 reg.add_internal_call("internal_m2n_input_is_key_pressed", internal_call(internal_m2n_input_is_key_pressed));
4537 reg.add_internal_call("internal_m2n_input_is_key_released", internal_call(internal_m2n_input_is_key_released));
4538 reg.add_internal_call("internal_m2n_input_is_key_down", internal_call(internal_m2n_input_is_key_down));
4539 reg.add_internal_call("internal_m2n_input_is_mouse_button_pressed",
4540 internal_call(internal_m2n_input_is_mouse_button_pressed));
4541 reg.add_internal_call("internal_m2n_input_is_mouse_button_released",
4542 internal_call(internal_m2n_input_is_mouse_button_released));
4543 reg.add_internal_call("internal_m2n_input_is_mouse_button_down",
4544 internal_call(internal_m2n_input_is_mouse_button_down));
4545 reg.add_internal_call("internal_m2n_input_get_mouse_position",
4546 internal_call(internal_m2n_input_get_mouse_position));
4547 }
4548
4549 {
4550 auto reg = mono::internal_call_registry("Unravel.Core.Physics");
4551 reg.add_internal_call("internal_m2n_physics_ray_cast", internal_call(internal_m2n_physics_ray_cast));
4552 reg.add_internal_call("internal_m2n_physics_ray_cast_all", internal_call(internal_m2n_physics_ray_cast_all));
4553 reg.add_internal_call("internal_m2n_physics_sphere_cast", internal_call(internal_m2n_physics_sphere_cast));
4554 reg.add_internal_call("internal_m2n_physics_sphere_cast_all",
4555 internal_call(internal_m2n_physics_sphere_cast_all));
4556 reg.add_internal_call("internal_m2n_physics_sphere_overlap",
4557 internal_call(internal_m2n_physics_sphere_overlap));
4558 }
4559
4560 {
4561 auto reg = mono::internal_call_registry("Unravel.Core.IK");
4562 reg.add_internal_call("internal_m2n_utils_set_ik_posiiton_ccd",
4563 internal_call(internal_m2n_utils_set_ik_posiiton_ccd));
4564 reg.add_internal_call("internal_m2n_utils_set_ik_posiiton_fabrik",
4565 internal_call(internal_m2n_utils_set_ik_posiiton_fabrik));
4566 reg.add_internal_call("internal_m2n_utils_set_ik_posiiton_two_bone",
4567 internal_call(internal_m2n_utils_set_ik_posiiton_two_bone));
4568
4569 reg.add_internal_call("internal_m2n_utils_set_ik_look_at_posiiton",
4570 internal_call(internal_m2n_utils_set_ik_look_at_posiiton));
4571 }
4572
4573 {
4574 auto reg = mono::internal_call_registry("Unravel.Core.AudioSourceComponent");
4575 reg.add_internal_call("internal_m2n_audio_source_get_loop", internal_call(internal_m2n_audio_source_get_loop));
4576 reg.add_internal_call("internal_m2n_audio_source_set_loop", internal_call(internal_m2n_audio_source_set_loop));
4577 reg.add_internal_call("internal_m2n_audio_source_get_volume",
4578 internal_call(internal_m2n_audio_source_get_volume));
4579 reg.add_internal_call("internal_m2n_audio_source_set_volume",
4580 internal_call(internal_m2n_audio_source_set_volume));
4581 reg.add_internal_call("internal_m2n_audio_source_get_pitch",
4582 internal_call(internal_m2n_audio_source_get_pitch));
4583 reg.add_internal_call("internal_m2n_audio_source_set_pitch",
4584 internal_call(internal_m2n_audio_source_set_pitch));
4585 reg.add_internal_call("internal_m2n_audio_source_get_volume_rolloff",
4586 internal_call(internal_m2n_audio_source_get_volume_rolloff));
4587 reg.add_internal_call("internal_m2n_audio_source_set_volume_rolloff",
4588 internal_call(internal_m2n_audio_source_set_volume_rolloff));
4589 reg.add_internal_call("internal_m2n_audio_source_get_min_distance",
4590 internal_call(internal_m2n_audio_source_get_min_distance));
4591 reg.add_internal_call("internal_m2n_audio_source_set_min_distance",
4592 internal_call(internal_m2n_audio_source_set_min_distance));
4593 reg.add_internal_call("internal_m2n_audio_source_get_max_distance",
4594 internal_call(internal_m2n_audio_source_get_max_distance));
4595 reg.add_internal_call("internal_m2n_audio_source_set_max_distance",
4596 internal_call(internal_m2n_audio_source_set_max_distance));
4597 reg.add_internal_call("internal_m2n_audio_source_get_mute", internal_call(internal_m2n_audio_source_get_mute));
4598
4599 reg.add_internal_call("internal_m2n_audio_source_set_mute", internal_call(internal_m2n_audio_source_set_mute));
4600
4601 reg.add_internal_call("internal_m2n_audio_source_is_playing",
4602 internal_call(internal_m2n_audio_source_is_playing));
4603 reg.add_internal_call("internal_m2n_audio_source_is_paused",
4604 internal_call(internal_m2n_audio_source_is_paused));
4605 reg.add_internal_call("internal_m2n_audio_source_play", internal_call(internal_m2n_audio_source_play));
4606 reg.add_internal_call("internal_m2n_audio_source_stop", internal_call(internal_m2n_audio_source_stop));
4607
4608 reg.add_internal_call("internal_m2n_audio_source_pause", internal_call(internal_m2n_audio_source_pause));
4609 reg.add_internal_call("internal_m2n_audio_source_resume", internal_call(internal_m2n_audio_source_resume));
4610 reg.add_internal_call("internal_m2n_audio_source_get_audio_clip",
4611 internal_call(internal_m2n_audio_source_get_audio_clip));
4612 reg.add_internal_call("internal_m2n_audio_source_set_audio_clip",
4613 internal_call(internal_m2n_audio_source_set_audio_clip));
4614 }
4615
4616 {
4617 auto reg = mono::internal_call_registry("Unravel.Core.UIDocumentComponent");
4618 reg.add_internal_call("internal_m2n_ui_document_get_asset", internal_call(internal_m2n_ui_document_get_asset));
4619 reg.add_internal_call("internal_m2n_ui_document_set_asset", internal_call(internal_m2n_ui_document_set_asset));
4620 reg.add_internal_call("internal_m2n_ui_document_is_loaded", internal_call(internal_m2n_ui_document_is_loaded));
4621 reg.add_internal_call("internal_m2n_ui_document_is_enabled", internal_call(internal_m2n_ui_document_is_enabled));
4622 reg.add_internal_call("internal_m2n_ui_document_set_enabled", internal_call(internal_m2n_ui_document_set_enabled));
4623 reg.add_internal_call("internal_m2n_ui_document_close", internal_call(internal_m2n_ui_document_close));
4624 reg.add_internal_call("internal_m2n_ui_document_get_title", internal_call(internal_m2n_ui_document_get_title));
4625 reg.add_internal_call("internal_m2n_ui_document_set_title", internal_call(internal_m2n_ui_document_set_title));
4626 reg.add_internal_call("internal_m2n_ui_document_get_wrapper", internal_call(internal_m2n_ui_document_get_wrapper));
4627 }
4628
4629
4630 {
4631 auto reg = mono::internal_call_registry("Unravel.Core.UIDocument");
4632 reg.add_internal_call("internal_m2n_ui_document_wrapper_is_valid", internal_call(internal_m2n_ui_document_wrapper_is_valid));
4633 reg.add_internal_call("internal_m2n_ui_document_wrapper_get_title", internal_call(internal_m2n_ui_document_wrapper_get_title));
4634 reg.add_internal_call("internal_m2n_ui_document_wrapper_set_title", internal_call(internal_m2n_ui_document_wrapper_set_title));
4635 reg.add_internal_call("internal_m2n_ui_document_wrapper_is_visible", internal_call(internal_m2n_ui_document_wrapper_is_visible));
4636 reg.add_internal_call("internal_m2n_ui_document_wrapper_show", internal_call(internal_m2n_ui_document_wrapper_show));
4637 reg.add_internal_call("internal_m2n_ui_document_wrapper_hide", internal_call(internal_m2n_ui_document_wrapper_hide));
4638 reg.add_internal_call("internal_m2n_ui_document_wrapper_close", internal_call(internal_m2n_ui_document_wrapper_close));
4639 reg.add_internal_call("internal_m2n_ui_document_wrapper_get_element_by_id", internal_call(internal_m2n_ui_document_get_element_wrapper_by_id));
4640 reg.add_internal_call("internal_m2n_ui_document_wrapper_query_selector", internal_call(internal_m2n_ui_document_query_selector_wrapper));
4641 reg.add_internal_call("internal_m2n_ui_document_wrapper_query_selector_all", internal_call(internal_m2n_ui_document_query_selector_wrapper));
4642 }
4643
4644 {
4645 auto reg = mono::internal_call_registry("Unravel.Core.UIElement");
4646 reg.add_internal_call("internal_m2n_ui_element_wrapper_is_valid", internal_call(internal_m2n_ui_element_wrapper_is_valid));
4647 reg.add_internal_call("internal_m2n_ui_element_wrapper_get_inner_rml", internal_call(internal_m2n_ui_element_wrapper_get_inner_rml));
4648 reg.add_internal_call("internal_m2n_ui_element_wrapper_set_inner_rml", internal_call(internal_m2n_ui_element_wrapper_set_inner_rml));
4649 reg.add_internal_call("internal_m2n_ui_element_wrapper_is_visible", internal_call(internal_m2n_ui_element_wrapper_is_visible));
4650 reg.add_internal_call("internal_m2n_ui_element_wrapper_set_visible", internal_call(internal_m2n_ui_element_wrapper_set_visible));
4651 reg.add_internal_call("internal_m2n_ui_element_wrapper_get_attribute", internal_call(internal_m2n_ui_element_wrapper_get_attribute));
4652 reg.add_internal_call("internal_m2n_ui_element_wrapper_set_attribute", internal_call(internal_m2n_ui_element_wrapper_set_attribute));
4653 reg.add_internal_call("internal_m2n_ui_element_wrapper_remove_attribute", internal_call(internal_m2n_ui_element_wrapper_remove_attribute));
4654 reg.add_internal_call("internal_m2n_ui_element_wrapper_has_attribute", internal_call(internal_m2n_ui_element_wrapper_has_attribute));
4655 reg.add_internal_call("internal_m2n_ui_element_wrapper_set_class", internal_call(internal_m2n_ui_element_wrapper_set_class));
4656 reg.add_internal_call("internal_m2n_ui_element_wrapper_is_class_set", internal_call(internal_m2n_ui_element_wrapper_is_class_set));
4657 reg.add_internal_call("internal_m2n_ui_element_wrapper_focus", internal_call(internal_m2n_ui_element_wrapper_focus));
4658 reg.add_internal_call("internal_m2n_ui_element_wrapper_blur", internal_call(internal_m2n_ui_element_wrapper_blur));
4659 reg.add_internal_call("internal_m2n_ui_element_wrapper_click", internal_call(internal_m2n_ui_element_wrapper_click));
4660 reg.add_internal_call("internal_m2n_ui_element_wrapper_scroll_into_view", internal_call(internal_m2n_ui_element_wrapper_scroll_into_view));
4661 reg.add_internal_call("internal_m2n_ui_element_wrapper_get_id", internal_call(internal_m2n_ui_element_wrapper_get_id));
4662 }
4663
4664 {
4665 auto reg = mono::internal_call_registry("Unravel.Core.UIEventManager");
4666 reg.add_internal_call("internal_m2n_ui_ensure_native_event_listener", internal_call(internal_m2n_ui_ensure_native_event_listener));
4667 }
4668
4669 {
4670 auto reg = mono::internal_call_registry("Unravel.Core.UIEventBase");
4671 reg.add_internal_call("internal_m2n_ui_stop_propagation", internal_call(internal_m2n_ui_stop_propagation));
4672 reg.add_internal_call("internal_m2n_ui_stop_immediate_propagation", internal_call(internal_m2n_ui_stop_immediate_propagation));
4673 }
4674
4675 {
4676 auto reg = mono::internal_call_registry("Unravel.Core.Application");
4677 reg.add_internal_call("internal_m2n_application_quit", internal_call(internal_m2n_application_quit));
4678 }
4679
4680 {
4681 auto reg = mono::internal_call_registry("Unravel.Core.Time");
4682 reg.add_internal_call("internal_m2n_set_time_scale", internal_call(internal_m2n_set_time_scale));
4683 }
4684
4685 {
4686 auto reg = mono::internal_call_registry("Unravel.Core.GCMonitor");
4687 reg.add_internal_call("internal_m2n_get_mono_heap_size", internal_call(mono::gc_get_heap_size));
4688 reg.add_internal_call("internal_m2n_get_mono_used_size", internal_call(mono::gc_get_used_size));
4689 }
4690
4691 // mono::managed_interface::init(assembly);
4692
4693 return true;
4694}
4695
4696} // namespace unravel
manifold_type type
int layer_mask
bool query_sensors
event_type event
unravel::physics_vector< hit_info > hits
animation_clip::seconds_t seconds_t
std::shared_ptr< material > sptr
Definition material.h:36
std::chrono::duration< float > delta_t
float scale
Definition hub.cpp:25
ImGui::Font::Enum font
Definition hub.cpp:24
std::string name
Definition hub.cpp:27
std::string tag
Definition hub.cpp:26
#define APPLOG_WARNING(...)
Definition logging.h:19
#define APPLOG_ERROR(...)
Definition logging.h:20
#define APPLOG_INFO(...)
Definition logging.h:18
#define APPLOG_INFO_LOC(FILE_LOC, LINE_LOC, FUNC_LOC,...)
Definition logging.h:34
#define APPLOG_WARNING_LOC(FILE_LOC, LINE_LOC, FUNC_LOC,...)
Definition logging.h:36
#define APPLOG_ERROR_LOC(FILE_LOC, LINE_LOC, FUNC_LOC,...)
Definition logging.h:38
#define APPLOG_TRACE_LOC(FILE_LOC, LINE_LOC, FUNC_LOC,...)
Definition logging.h:32
#define APPLOG_TRACE(...)
Definition logging.h:17
auto look_rotation(const glm::vec3 &forward, const glm::vec3 &upwards) -> glm::quat
auto from_to_rotation(const glm::vec3 &from, const glm::vec3 &to) -> glm::quat
key_code
Definition key.hpp:6
auto start(seq_action action, const seq_scope_policy &scope_policy, hpp::source_location location) -> seq_id_t
Starts a new action.
Definition seq.cpp:8
auto delay(const duration_t &duration, const sentinel_t &sentinel) -> seq_action
Creates a delay action.
Definition seq_core.cpp:182
auto tokenize(const std::string &str, const std::string &delimiters) -> string_tokens_t
Definition utils.cpp:153
auto convert_rml_key_to_input(Rml::Input::KeyIdentifier rml_key) -> input::key_code
Convert RmlUi key identifier to engine input key code.
auto ik_set_position_ccd(entt::handle end_effector, const math::vec3 &target, size_t num_bones_in_chain, float threshold, int max_iterations) -> bool
auto generate_uuid() -> hpp::uuid
Definition uuid.cpp:25
@ nothing_layer
Definition layer_mask.h:13
@ sphere
Sphere type reflection probe.
auto ik_set_position_two_bone(entt::handle end_effector, const math::vec3 &target, const math::vec3 &forward, float weight, float soften, int max_iterations) -> bool
hpp::small_vector< T, SmallSizeCapacity > physics_vector
auto ik_set_position_fabrik(entt::handle end_effector, const math::vec3 &target, size_t num_bones_in_chain, float threshold, int max_iterations) -> bool
auto ik_look_at_position(entt::handle end_effector, const math::vec3 &target, float weight) -> bool
bool is_valid(octet_iterator start, octet_iterator end)
Definition core.h:467
const text_vector< size_t > * offsets
std::function< bool(size_t type_hash, entt::handle e)> has_native
entt::entity entity
size_t matched_index
std::function< bool(size_t type_hash, entt::handle e)> remove_native
std::function< bool(size_t type_hash, entt::handle e)> add_native
float distance
void draw(const bx::Aabb &_aabb)
void lineTo(float _x, float _y, float _z=0.0f)
void setColor(uint32_t _abgr)
void setWireframe(bool _wireframe)
void moveTo(float _x, float _y, float _z=0.0f)
DebugDrawEncoder encoder
Definition debugdraw.h:15
Storage for box vector values and wraps up common functionality.
Definition bbox.h:21
static bbox empty
An empty bounding box.
Definition bbox.h:316
static color white()
Definition color.h:13
static color black()
Definition color.h:18
static color transparent()
Definition color.h:23
static auto context() -> rtti::context &
Definition engine.cpp:116
gfx::uniform_handle handle
Definition uniform.cpp:9