Unravel Engine C++ Reference
Loading...
Searching...
No Matches
script_system.cpp
Go to the documentation of this file.
1#include "script_system.h"
5#include <engine/ecs/ecs.h>
6#include <engine/engine.h>
7#include <engine/events.h>
12
13#include <monopp/mono_exception.h>
14#include <monopp/mono_field_invoker.h>
15#include <monopp/mono_internal_call.h>
16#include <monopp/mono_method_invoker.h>
17#include <monopp/mono_property_invoker.h>
18
21#include <logging/logging.h>
22#include <seq/seq.h>
24
25namespace unravel
26{
27namespace
28{
29
30enum class recompile_command : int
31{
32 none,
33 compile_at_schedule,
34 compile_now,
35};
36
37std::chrono::milliseconds check_interval(50);
38std::atomic_bool initted{};
39
40std::atomic<recompile_command> needs_recompile{};
41std::mutex container_mutex;
42std::vector<std::string> needs_to_recompile;
43std::atomic<uint64_t> compilation_version{};
44
45std::atomic_bool debug_mode{true};
46
47auto print_assembly_info(const mono::mono_assembly& assembly)
48{
49 std::stringstream ss;
50 auto refs = assembly.dump_references();
51
52 ss << fmt::format(" ----- References -----");
53
54 for(const auto& ref : refs)
55 {
56 ss << fmt::format("\n{}", ref);
57 }
58
59 APPLOG_TRACE("\n{}", ss.str());
60
61 auto types = assembly.get_types();
62
63 ss = {};
64 ss << fmt::format(" ----- Types -----");
65
66 for(const auto& type : types)
67 {
68 ss << fmt::format("\n{}", type.get_fullname());
69 ss << fmt::format("\n sizeof {}", type.get_sizeof());
70 ss << fmt::format("\n alignof {}", type.get_alignof());
71
72 {
73 auto attribs = type.get_attributes();
74 for(const auto& attrib : attribs)
75 {
76 ss << fmt::format("\n - Attribute : {}", attrib.get_type().get_fullname());
77 }
78 }
79
80 auto fields = type.get_fields();
81 for(const auto& field : fields)
82 {
83 ss << fmt::format("\n - Field : {}", field.get_name());
84
85 auto attribs = field.get_attributes();
86 for(const auto& attrib : attribs)
87 {
88 ss << fmt::format("\n -- Attribute : {}", attrib.get_type().get_fullname());
89 }
90 }
91
92 auto properties = type.get_properties();
93 for(const auto& prop : properties)
94 {
95 ss << fmt::format("\n - Property : {}", prop.get_name());
96
97 auto attribs = prop.get_attributes();
98 for(const auto& attrib : attribs)
99 {
100 ss << fmt::format("\n -- Attribute : {}", attrib.get_type().get_fullname());
101 }
102 }
103 }
104 APPLOG_TRACE("\n{}", ss.str());
105}
106
107} // namespace
108
109void script_system::log_exception(const mono::mono_exception& e, const hpp::source_location& loc)
110{
111 auto frame = mono::extract_relevant_stack_frame(e.what());
112 if(!frame.file_name.empty())
113 {
114 APPLOG_ERROR_LOC(frame.file_name.c_str(), frame.line, frame.function_name.c_str(), e.what());
115 }
116 else
117 {
118 APPLOG_ERROR_LOC(loc.file_name(), int(loc.line()), loc.function_name(), e.what());
119 }
120}
121
122void script_system::copy_compiled_lib(const fs::path& from, const fs::path& to)
123{
124 auto from_debug_info = from;
125 from_debug_info.concat(".mdb");
126 auto from_comments_xml = from;
127 from_comments_xml.replace_extension(".xml");
128
129 auto to_debug_info = to;
130 to_debug_info.concat(".mdb");
131 auto to_comments_xml = to;
132 to_comments_xml.replace_extension(".xml");
133
134 fs::error_code er;
135 fs::copy_file(from, to, fs::copy_options::overwrite_existing, er);
136 fs::copy_file(from_debug_info, to_debug_info, fs::copy_options::overwrite_existing, er);
137 fs::copy_file(from_comments_xml, to_comments_xml, fs::copy_options::overwrite_existing, er);
138
139 fs::remove(from, er);
140 fs::remove(from_debug_info, er);
141 fs::remove(from_comments_xml, er);
142}
143
144auto script_system::find_mono(const rtti::context& ctx) -> mono::compiler_paths
145{
146 bool is_deploy_mode = ctx.has<deploy>();
147
148 mono::compiler_paths result;
149
150 if(is_deploy_mode)
151 {
152 auto mono_dir = fs::resolve_protocol("engine:/mono");
153 result.assembly_dir = fs::absolute(mono_dir / "lib").string();
154 result.config_dir = fs::absolute(mono_dir / "etc").string();
155 }
156 else
157 {
158 const auto& names = mono::get_common_library_names();
159 const auto& library_paths = mono::get_common_library_paths();
160 const auto& config_paths = mono::get_common_config_paths();
161
162 for(size_t i = 0; i < library_paths.size(); ++i)
163 {
164 const auto& library_path = library_paths.at(i);
165 const auto& config_path = config_paths.at(i);
166 std::vector<std::string> paths{library_path};
167 auto found_library = fs::find_library(names, paths);
168
169 if(!found_library.empty())
170 {
171 result.assembly_dir = fs::path(library_path).make_preferred().string();
172 result.config_dir = fs::path(config_path).make_preferred().string();
173
174 break;
175 }
176 }
177 }
178
179 {
180 const auto& names = mono::get_common_executable_names();
181 const auto& paths = mono::get_common_executable_paths();
182
183 result.msc_executable = fs::find_program(names, paths).make_preferred().string();
184 }
185
186 APPLOG_TRACE("MONO_PATHS:");
187 APPLOG_TRACE("Assembly path - {}", result.assembly_dir);
188 APPLOG_TRACE("Config path - {}", result.config_dir);
189
190 return result;
191}
192
193auto validate_paths(const mono::compiler_paths& paths) -> bool
194{
195 return !paths.assembly_dir.empty() && !paths.config_dir.empty();
196}
197
199{
200 APPLOG_TRACE("{}::{}", hpp::type_name_str(*this), __func__);
201
202 auto& ev = ctx.get_cached<events>();
203 ev.on_frame_update.connect(sentinel_, this, &script_system::on_frame_update);
204 ev.on_frame_fixed_update.connect(sentinel_, this, &script_system::on_frame_fixed_update);
205 ev.on_frame_update.connect(sentinel_, -100000, this, &script_system::on_frame_late_update);
206 ev.on_play_begin.connect(sentinel_, -1000, this, &script_system::on_play_begin);
207 ev.on_play_end.connect(sentinel_, 1000, this, &script_system::on_play_end);
208 ev.on_pause.connect(sentinel_, 100, this, &script_system::on_pause);
209 ev.on_resume.connect(sentinel_, -100, this, &script_system::on_resume);
210 ev.on_skip_next_frame.connect(sentinel_, -100, this, &script_system::on_skip_next_frame);
211
212 auto mono_paths = find_mono(ctx);
213
214 if(!validate_paths(mono_paths))
215 {
216 auto& error = ctx.add<init_error>();
217 error.category = "Mono C#";
218 error.msg = "Failed to locate Mono C#. Please install it from - https://www.mono-project.com/download/stable/";
219
220 return false;
221 }
222
223 debug_config_.enable_debugging = true;
224
225 if(mono::init(mono_paths, debug_config_))
226 {
227 bind_internal_calls(ctx);
228
229 mono::mono_domain::set_assemblies_path(fs::resolve_protocol(ex::get_compiled_directory("engine")).string());
230
231 try
232 {
233 if(!load_engine_domain(ctx, true))
234 {
235 return false;
236 }
237 }
238 catch(const mono::mono_exception& e)
239 {
240 log_exception(e);
241 return false;
242 }
243
244 initted = true;
245 return true;
246 }
247
248 auto& error = ctx.add<init_error>();
249 error.category = "Mono C#";
250 error.msg = "Failed to initialize Mono C#. Please install it from - https://www.mono-project.com/download/stable/";
251
252 return false;
253}
254
256{
257 APPLOG_TRACE("{}::{}", hpp::type_name_str(*this), __func__);
258
259 unload_app_domain();
260 unload_engine_domain();
261
262 mono::shutdown();
263
264 return true;
265}
266
267void script_system::set_debug_config(const std::string& address, uint32_t port, uint32_t loglevel)
268{
269 debug_config_.address = address;
270 debug_config_.port = port;
271 debug_config_.loglevel = loglevel;
272}
273
274auto script_system::load_engine_domain(rtti::context& ctx, bool recompile) -> bool
275{
276 bool is_deploy_mode = ctx.has<deploy>();
277
278 if(!is_deploy_mode && recompile)
279 {
280 bool debug = false;
281#ifndef NDEBUG
282 debug = true;
283#endif
284
285 if(!create_compilation_job(ctx, "engine", debug).get())
286 {
287 return false;
288 }
289 }
290
291 domain_ = std::make_unique<mono::mono_domain>("Ace.Engine");
292 mono::mono_domain::set_current_domain(domain_.get());
293
294 auto engine_script_lib = fs::resolve_protocol(get_lib_compiled_key("engine"));
295 auto engine_script_lib_temp = fs::resolve_protocol(get_lib_temp_compiled_key("engine"));
296
297 copy_compiled_lib(engine_script_lib_temp, engine_script_lib);
298
299 auto assembly = domain_->get_assembly(engine_script_lib.string());
300 domain_->name_assembly(engine_script_lib.string(), "Unravel.Engine");
301 // print_assembly_info(assembly);
302
303 cache_.update_manager_type = assembly.get_type("Unravel.Core", "SystemManager");
304
305 return true;
306}
308{
309 cache_ = {};
310 domain_.reset();
311 mono::mono_domain::set_current_domain(nullptr);
312}
313
314auto script_system::load_app_domain(rtti::context& ctx, bool recompile) -> bool
315{
316 bool is_deploy_mode = ctx.has<deploy>();
317
318 bool result = true;
319
320 if(!is_deploy_mode && recompile)
321 {
322 result &= create_compilation_job(ctx, "app", get_script_debug_mode()).get();
323
324 has_compilation_errors_ = !result;
325 }
326
327 app_domain_ = std::make_unique<mono::mono_domain>("Ace.App");
328 mono::mono_domain::set_current_domain(app_domain_.get());
329
330 auto app_script_lib = fs::resolve_protocol(get_lib_compiled_key("app"));
331 auto app_script_lib_temp = fs::resolve_protocol(get_lib_temp_compiled_key("app"));
332
333 copy_compiled_lib(app_script_lib_temp, app_script_lib);
334
335 if(!is_deploy_mode)
336 {
337 auto& am = ctx.get_cached<asset_manager>();
338 auto assets = am.get_assets<script>("app");
339 // assets include the empty asset
340 if(assets.size() <= 1)
341 {
342 return result;
343 }
344 }
345
346 try
347 {
348 auto assembly = app_domain_->get_assembly(app_script_lib.string());
349 app_domain_->name_assembly(app_script_lib.string(), "Ace.App");
350 // print_assembly_info(assembly);
351
352 auto engine_script_lib = fs::resolve_protocol(get_lib_compiled_key("engine"));
353 auto engine_assembly = domain_->get_assembly(engine_script_lib.string());
354
355 auto comp_type = engine_assembly.get_type("Unravel.Core", "ScriptComponent");
356
357 app_cache_.scriptable_component_types.clear();
358 if(!has_compilation_errors_)
359 {
360 app_cache_.scriptable_component_types = assembly.get_types_derived_from(comp_type);
361 }
362 }
363 catch(const mono::mono_exception& e)
364 {
365 log_exception(e);
366 result = false;
367 }
368
369 return result;
370}
372{
373 app_cache_ = {};
374 app_domain_.reset();
375 mono::mono_domain::set_current_domain(domain_.get());
376}
377
378void script_system::on_create_component(entt::registry& r, entt::entity e)
379{
380}
381void script_system::on_destroy_component(entt::registry& r, entt::entity e)
382{
383 auto& comp = r.get<script_component>(e);
384 comp.destroy();
385}
386
387void script_system::on_create_active_component(entt::registry& r, entt::entity e)
388{
389 if(auto comp = r.try_get<script_component>(e))
390 {
391 comp->enable();
392 }
393}
394void script_system::on_destroy_active_component(entt::registry& r, entt::entity e)
395{
396 if(auto comp = r.try_get<script_component>(e))
397 {
398 comp->disable();
399 }
400}
401
402void script_system::on_play_begin(hpp::span<const entt::handle> entities)
403{
404 if(!app_domain_ || !domain_)
405 {
406 return;
407 }
408 try
409 {
410 create_call_ = call_progress::started;
411
412 for(auto entity : entities)
413 {
414 if(auto comp = entity.try_get<script_component>())
415 {
416 comp->create();
417 }
418 }
419 create_call_ = call_progress::finished;
420
421 for(auto entity : entities)
422 {
423 if(auto comp = entity.try_get<script_component>())
424 {
425 if(entity.all_of<active_component>())
426 {
427 comp->enable();
428 }
429 else
430 {
431 comp->disable();
432 }
433 }
434 }
435 }
436 catch(const mono::mono_exception& e)
437 {
438 log_exception(e);
439 }
440}
441
442void script_system::on_play_begin(entt::registry& entities)
443{
444 if(!app_domain_ || !domain_)
445 {
446 return;
447 }
448 try
449 {
450 create_call_ = call_progress::started;
451
452 entities.view<script_component>().each(
453 [&](auto e, auto&& comp)
454 {
455 comp.create();
456 });
457
458 create_call_ = call_progress::finished;
459
460 entities.view<script_component>().each(
461 [&](auto e, auto&& comp)
462 {
463 if(entities.all_of<active_component>(e))
464 {
465 comp.enable();
466 }
467 else
468 {
469 comp.disable();
470 }
471 });
472 }
473 catch(const mono::mono_exception& e)
474 {
475 log_exception(e);
476 }
477}
478
480{
481 APPLOG_TRACE("{}::{}", hpp::type_name_str(*this), __func__);
482
483 if(!app_domain_ || !domain_)
484 {
485 return;
486 }
487
488 auto& ec = ctx.get_cached<ecs>();
489 auto& scn = ec.get_scene();
490 auto& registry = *scn.registry;
491
492 registry.on_construct<script_component>().connect<&on_create_component>();
493 registry.on_destroy<script_component>().connect<&on_destroy_component>();
494
495 registry.on_construct<active_component>().connect<&on_create_active_component>();
496 registry.on_destroy<active_component>().connect<&on_destroy_active_component>();
497
498 on_play_begin(registry);
499}
500
501void script_system::on_play_end(rtti::context& ctx)
502{
503 APPLOG_TRACE("{}::{}", hpp::type_name_str(*this), __func__);
504
505 auto& ec = ctx.get_cached<ecs>();
506 auto& scn = ec.get_scene();
507 auto& registry = *scn.registry;
508
509 seq::scope::stop_all("script");
510
511 try
512 {
513 registry.view<script_component>().each(
514 [&](auto e, auto&& comp)
515 {
516 comp.destroy();
517 });
518 }
519 catch(const mono::mono_exception& e)
520 {
521 log_exception(e);
522 }
523
524 registry.on_construct<active_component>().disconnect<&on_create_active_component>();
525 registry.on_destroy<active_component>().disconnect<&on_destroy_active_component>();
526
527 registry.on_construct<script_component>().disconnect<&on_create_component>();
528 registry.on_destroy<script_component>().disconnect<&on_destroy_component>();
529}
530
531void script_system::on_pause(rtti::context& ctx)
532{
533}
534
535void script_system::on_resume(rtti::context& ctx)
536{
537}
538
539void script_system::on_skip_next_frame(rtti::context& ctx)
540{
541 delta_t step(1.0f / 60.0f);
542 on_frame_update(ctx, step);
543}
544void script_system::on_frame_update(rtti::context& ctx, delta_t dt)
545{
546 APP_SCOPE_PERF("Script/System Update");
547
548 auto& ev = ctx.get_cached<events>();
549 if(!ev.is_playing)
550 {
551 check_for_recompile(ctx, dt, true);
552 }
553
554 is_updating_ = true;
555
556 try
557 {
558 if(!app_domain_ || !domain_)
559 {
560 return;
561 }
562
563 auto& ec = ctx.get_cached<ecs>();
564 auto& scn = ec.get_scene();
565 auto& registry = *scn.registry;
566
567 registry.view<script_component>().each(
568 [&](auto e, auto&& comp)
569 {
570 comp.process_pending_deletions();
571
572 if(ev.is_playing && registry.all_of<active_component>(e))
573 {
574 comp.start();
575 }
576 });
577
578 struct update_data
579 {
580 float delta_time{};
581 float time_scale{};
582 uint64_t frame_count{};
583 };
584
585 if(ev.is_playing)
586 {
587 auto& sim = ctx.get_cached<simulation>();
588 auto time_scale = sim.get_time_scale();
589
590 update_data data;
591 data.delta_time = dt.count();
592 data.time_scale = time_scale;
593 data.frame_count = sim.get_frame();
594 auto method_thunk =
595 mono::make_method_invoker<void(update_data)>(cache_.update_manager_type, "internal_n2m_update");
596 method_thunk(data);
597 }
598 }
599 catch(const mono::mono_exception& e)
600 {
601 log_exception(e);
602 }
603 is_updating_ = false;
604}
605
606void script_system::on_frame_fixed_update(rtti::context& ctx, delta_t dt)
607{
608 //APP_SCOPE_PERF("Script/System Fixed Update");
609
610 auto& ev = ctx.get_cached<events>();
611
612 try
613 {
614 if(!app_domain_ || !domain_)
615 {
616 return;
617 }
618
619 auto& ec = ctx.get_cached<ecs>();
620 auto& scn = ec.get_scene();
621 auto& registry = *scn.registry;
622
623 registry.view<script_component>().each(
624 [&](auto e, auto&& comp)
625 {
626 comp.process_pending_deletions();
627 });
628
629 struct update_data
630 {
631 float fixed_delta_time{};
632 };
633
634 if(ev.is_playing && dt > delta_t::zero())
635 {
636 auto& sim = ctx.get_cached<simulation>();
637 auto time_scale = sim.get_time_scale();
638
639 update_data data;
640 data.fixed_delta_time = dt.count();
641 auto method_thunk =
642 mono::make_method_invoker<void(update_data)>(cache_.update_manager_type, "internal_n2m_fixed_update");
643 method_thunk(data);
644 }
645 }
646 catch(const mono::mono_exception& e)
647 {
648 log_exception(e);
649 }
650}
651
652void script_system::on_frame_late_update(rtti::context& ctx, delta_t dt)
653{
654 APP_SCOPE_PERF("Script/System Late Update");
655
656 auto& ev = ctx.get_cached<events>();
657
658 try
659 {
660 if(!app_domain_ || !domain_)
661 {
662 return;
663 }
664
665 auto& ec = ctx.get_cached<ecs>();
666 auto& scn = ec.get_scene();
667 auto& registry = *scn.registry;
668
669 if(ev.is_playing && dt > delta_t::zero())
670 {
671 auto method_thunk =
672 mono::make_method_invoker<void()>(cache_.update_manager_type, "internal_n2m_late_update");
673 method_thunk();
674 }
675 }
676 catch(const mono::mono_exception& e)
677 {
678 log_exception(e);
679 }
680}
681
682auto script_system::get_all_scriptable_components() const -> const std::vector<mono::mono_type>&
683{
684 return app_cache_.scriptable_component_types;
685}
686
687auto script_system::get_engine_assembly() const -> mono::mono_assembly
688{
689 auto engine_script_lib = fs::resolve_protocol(get_lib_compiled_key("engine"));
690 return domain_->get_assembly(engine_script_lib.string());
691}
692
693auto script_system::get_app_assembly() const -> mono::mono_assembly
694{
695 auto app_script_lib = fs::resolve_protocol(get_lib_compiled_key("app"));
696 return app_domain_->get_assembly(app_script_lib.string());
697}
698
700{
701 return create_call_ == call_progress::finished;
702}
704{
705 return is_updating_;
706}
707
709{
710 return mono::is_debugger_attached();
711}
712
713void script_system::check_for_recompile(rtti::context& ctx, delta_t dt, bool emit_callback)
714{
715 time_since_last_check_ += dt;
716
717 if(time_since_last_check_ >= check_interval || needs_recompile == recompile_command::compile_now)
718 {
719 time_since_last_check_ = {};
720
721 recompile_command should_recompile = needs_recompile.exchange(recompile_command::none);
722
723 if(should_recompile != recompile_command::none)
724 {
725 auto container = []()
726 {
727 std::lock_guard<std::mutex> lock(container_mutex);
728 auto result = std::move(needs_to_recompile);
729 return result;
730 }();
731
732 compilation_jobs_.clear();
733
734 compilation_version++;
735
736 auto current_version = compilation_version.load();
737 for(const auto& protocol : container)
738 {
739 auto job = create_compilation_job(ctx, protocol, get_script_debug_mode())
740 .then(tpp::this_thread::get_id(),
741 [this, &ctx, protocol, emit_callback, current_version](auto f)
742 {
743 if(!emit_callback)
744 {
745 return;
746 }
747 auto& ev = ctx.get_cached<events>();
748
749 if(ev.is_playing)
750 {
751 return;
752 }
753
754 if(compilation_version > current_version)
755 {
756 return;
757 }
758
759 has_compilation_errors_ = !f.get();
760 if(!has_compilation_errors_)
761 {
762 ev.on_script_recompile(ctx, protocol, current_version);
763 }
764 });
765
766 compilation_jobs_.emplace_back(std::move(job));
767 }
768 }
769 }
770}
771
773{
774 APPLOG_TRACE("Waiting for script compilation...");
775
776 check_for_recompile(ctx, 100s, false);
777
778 auto jobs = std::move(compilation_jobs_);
779
780 for(auto& job : jobs)
781 {
782 job.wait();
783 }
784}
785
786auto script_system::create_compilation_job(rtti::context& ctx, const std::string& protocol, bool debug)
787 -> tpp::job_future<bool>
788{
789 uint32_t flags = 0;
790 if(debug)
791 {
793 }
794
795 auto& thr = ctx.get_cached<threader>();
796 auto& am = ctx.get_cached<asset_manager>();
797
798
799
800 return thr.pool->schedule(
801 "Compiling " + ex::get_type<script_library>(),
802 [&am, flags, protocol]()
803 {
804 auto key = get_lib_data_key(protocol);
805 auto output = get_lib_temp_compiled_key(protocol);
806
808 });
809}
810void script_system::set_needs_recompile(const std::string& protocol, bool now)
811{
812 if(!initted)
813 {
814 return;
815 }
816 needs_recompile = now ? recompile_command::compile_now : recompile_command::compile_at_schedule;
817 {
818 std::lock_guard<std::mutex> lock(container_mutex);
819 if(std::find(std::begin(needs_to_recompile), std::end(needs_to_recompile), protocol) ==
820 std::end(needs_to_recompile))
821 {
822 needs_to_recompile.emplace_back(protocol);
823 }
824 }
825}
826
828{
829 return debug_mode;
830}
831
833{
834 debug_mode = debug;
835}
836
837auto script_system::get_lib_name(const std::string& protocol) -> std::string
838{
839 return protocol + "-script.dll";
840}
841
842auto script_system::get_lib_data_key(const std::string& protocol) -> std::string
843{
844 std::string output = get_lib_name(protocol + ex::get_data_directory() + "/" + protocol);
845 return output;
846}
847
848auto script_system::get_lib_temp_compiled_key(const std::string& protocol) -> std::string
849{
850 std::string output = get_lib_name(protocol + ex::get_compiled_directory() + "/temp-" + protocol);
851 return output;
852}
853
854auto script_system::get_lib_compiled_key(const std::string& protocol) -> std::string
855{
856 std::string output = get_lib_name(protocol + ex::get_compiled_directory() + "/" + protocol);
857 return output;
858}
859
860void script_system::on_sensor_enter(entt::handle sensor, entt::handle other)
861{
862 if(!other || !sensor)
863 {
864 return;
865 }
866 auto comp = sensor.try_get<script_component>();
867 if(!comp)
868 {
869 return;
870 }
871
872 try
873 {
874 comp->on_sensor_enter(other);
875 }
876 catch(const mono::mono_exception& e)
877 {
878 log_exception(e);
879 }
880}
881
882void script_system::on_sensor_exit(entt::handle sensor, entt::handle other)
883{
884 if(!other || !sensor)
885 {
886 return;
887 }
888
889 auto comp = sensor.try_get<script_component>();
890 if(!comp)
891 {
892 return;
893 }
894
895 try
896 {
897 comp->on_sensor_exit(other);
898 }
899 catch(const mono::mono_exception& e)
900 {
901 log_exception(e);
902 }
903}
904
905void script_system::on_collision_enter(entt::handle a, entt::handle b, const std::vector<manifold_point>& manifolds)
906{
907 if(!a || !b)
908 {
909 return;
910 }
911
912 try
913 {
914 {
915 auto comp = a.try_get<script_component>();
916 if(comp)
917 {
918 comp->on_collision_enter(b, manifolds, true);
919 }
920 }
921
922 {
923 auto comp = b.try_get<script_component>();
924 if(comp)
925 {
926 comp->on_collision_enter(a, manifolds, false);
927 }
928 }
929 }
930 catch(const mono::mono_exception& e)
931 {
932 log_exception(e);
933 }
934}
935
936void script_system::on_collision_exit(entt::handle a, entt::handle b, const std::vector<manifold_point>& manifolds)
937{
938 if(!a || !b)
939 {
940 return;
941 }
942
943 try
944 {
945 {
946 auto comp = a.try_get<script_component>();
947 if(comp)
948 {
949 comp->on_collision_exit(b, manifolds, true);
950 }
951 }
952
953 {
954 auto comp = b.try_get<script_component>();
955 if(comp)
956 {
957 comp->on_collision_exit(a, manifolds, false);
958 }
959 }
960 }
961 catch(const mono::mono_exception& e)
962 {
963 log_exception(e);
964 }
965}
966
968{
969 return has_compilation_errors_;
970}
971
972} // namespace unravel
entt::handle b
manifold_type type
entt::handle a
Manages assets, including loading, unloading, and storage.
auto get_assets(const std::string &group={}) const -> std::vector< asset_handle< T > >
Gets all assets in a specified group.
Class that contains core data for audio listeners. There can only be one instance of it per scene.
std::chrono::duration< float > delta_t
uint32_t frame
Definition graphics.cpp:21
bool initted
Definition graphics.cpp:20
#define APPLOG_ERROR_LOC(FILE_LOC, LINE_LOC, FUNC_LOC,...)
Definition logging.h:38
#define APPLOG_TRACE(...)
Definition logging.h:17
auto get_data_directory(const std::string &prefix={}) -> std::string
auto get_type() -> const std::string &
auto get_compiled_directory(const std::string &prefix={}) -> std::string
path resolve_protocol(const path &_path)
Given the specified path/filename, resolve the final full filename. This will be based on either the ...
void stop_all(const std::string &scope)
Stops all actions within the specified scope.
Definition seq.cpp:154
auto compile< script_library >(asset_manager &am, const fs::path &key, const fs::path &output, uint32_t flags) -> bool
auto validate_paths(const mono::compiler_paths &paths) -> bool
#define APP_SCOPE_PERF(name)
Create a scoped performance timer that only accepts string literals.
Definition profiler.h:160
entt::entity entity
auto get_cached() -> T &
Definition context.hpp:49
Manages the entity-component-system (ECS) operations for the ACE framework.
Definition ecs.h:12
auto get_scene() -> scene &
Gets the current scene.
Definition ecs.cpp:30
hpp::event< void(rtti::context &, delta_t)> on_frame_update
Definition events.h:16
std::string category
Definition engine.h:13
static auto is_debugger_attached() -> bool
static auto get_lib_name(const std::string &protocol) -> std::string
auto is_create_called() const -> bool
static auto get_lib_data_key(const std::string &protocol) -> std::string
static auto get_script_debug_mode() -> bool
auto is_update_called() const -> bool
static auto get_lib_compiled_key(const std::string &protocol) -> std::string
static auto get_lib_temp_compiled_key(const std::string &protocol) -> std::string
static void set_script_debug_mode(bool debug)
auto load_engine_domain(rtti::context &ctx, bool recompile) -> bool
auto get_app_assembly() const -> mono::mono_assembly
auto has_compilation_errors() const -> bool
void on_collision_enter(entt::handle a, entt::handle b, const std::vector< manifold_point > &manifolds)
auto init(rtti::context &ctx) -> bool
static void on_create_component(entt::registry &r, entt::entity e)
Called when a physics component is created.
static void set_needs_recompile(const std::string &protocol, bool now=false)
void set_debug_config(const std::string &address, uint32_t port, uint32_t loglevel)
static void copy_compiled_lib(const fs::path &from, const fs::path &to)
static void on_destroy_active_component(entt::registry &r, entt::entity e)
auto load_app_domain(rtti::context &ctx, bool recompile) -> bool
static auto find_mono(const rtti::context &ctx) -> mono::compiler_paths
void on_sensor_exit(entt::handle sensor, entt::handle other)
void on_sensor_enter(entt::handle sensor, entt::handle other)
static void log_exception(const mono::mono_exception &e, const hpp::source_location &loc=hpp::source_location::current())
auto get_engine_assembly() const -> mono::mono_assembly
static void on_create_active_component(entt::registry &r, entt::entity e)
void on_play_begin(rtti::context &ctx)
Called when playback begins.
auto deinit(rtti::context &ctx) -> bool
auto get_all_scriptable_components() const -> const std::vector< mono::mono_type > &
void on_collision_exit(entt::handle a, entt::handle b, const std::vector< manifold_point > &manifolds)
void wait_for_jobs_to_finish(rtti::context &ctx)
static void on_destroy_component(entt::registry &r, entt::entity e)
Called when a physics component is destroyed.