Unravel Engine C++ Reference
Loading...
Searching...
No Matches
asset_watcher.cpp
Go to the documentation of this file.
1#include "asset_watcher.h"
2#include "engine/ui/ui_tree.h"
9#include <engine/ecs/ecs.h>
10#include <engine/ecs/prefab.h>
11#include <engine/events.h>
19
22
25
26#include <filesystem/watcher.h>
27#include <graphics/graphics.h>
28#include <logging/logging.h>
29
30#include <fstream>
31#include <set>
32
33namespace unravel
34{
35namespace
36{
37using namespace std::literals;
38
39template<typename T>
40auto get_job_name() -> std::string
41{
42 return fmt::format("Compiling {}", ex::get_type<T>());
43}
44
45template<typename T>
46auto checking_dependencies_job_name() -> std::string
47{
48 return fmt::format("Checking dependencies of {}", ex::get_type<T>());
49}
50
51template<typename T>
52void resolve_includes(const fs::path& file_path, std::set<fs::path>& processed_files)
53{
54
55}
56
57
58template<>
59void resolve_includes<gfx::shader>(const fs::path& file_path, std::set<fs::path>& processed_files)
60{
61 if(!processed_files.insert(file_path).second)
62 {
63 return; // Avoid processing the same file multiple times
64 }
65
66 std::ifstream file(file_path);
67 if(!file.is_open())
68 {
69 // std::cerr << "Failed to open file: " << filePath << '\n';
70 return;
71 }
72
73 const std::string include_keyword = "#include";
74 const std::string bgfx_include_path = "/path/to/bgfx/include"; // Assuming bgfx include path is known
75
76 std::string line;
77 while(std::getline(file, line))
78 {
79 // Trim leading whitespace
80 line.erase(0, line.find_first_not_of(" \t"));
81
82 // Check for #include directive
83 if(line.compare(0, include_keyword.length(), include_keyword) == 0)
84 {
85 // Find the start and end of the include path
86 size_t start = line.find_first_of("\"<") + 1;
87 size_t end = line.find_last_of("\">");
88
89 if(start == std::string::npos || end == std::string::npos || start >= end)
90 {
91 // std::cerr << "Invalid include directive: " << line << '\n';
92 continue;
93 }
94
95 std::string include_path = line.substr(start, end - start);
96 fs::path resolved_path;
97
98 if(line[start - 1] == '<' && line[end] == '>')
99 {
100 // Resolve system include path (e.g., bgfx_shader.sh)
101 // resolvedPath = fs::path(bgfxIncludePath) / includePath;
102 continue;
103 }
104 else
105 {
106 // Resolve local include path relative to the current file
107 resolved_path = file_path.parent_path() / include_path;
108 }
109
110 resolved_path = fs::absolute(resolved_path);
111 // std::cout << "Resolved include: " << resolvedPath << '\n';
112
113 // Recurse into the included file
114 resolve_includes<gfx::shader>(resolved_path, processed_files);
115 }
116 }
117}
118
119auto extract_href_from_link_tag(hpp::string_view link_tag) -> hpp::string_view
120{
121 size_t href_pos = link_tag.find("href=");
122 if(href_pos == std::string::npos)
123 {
124 return {};
125 }
126
127 href_pos += 5; // Move past "href="
128
129 // Find the quote character (either " or ')
130 char quote_char = link_tag[href_pos];
131 if(quote_char != '"' && quote_char != '\'')
132 {
133 return {};
134 }
135
136 href_pos++; // Move past the opening quote
137 size_t href_end = link_tag.find(quote_char, href_pos);
138 if(href_end == std::string::npos)
139 {
140 return {};
141 }
142
143 return link_tag.substr(href_pos, href_end - href_pos);
144}
145
146auto resolve_ui_tree_dependency_path(const fs::path& href_value, const fs::path& base_file_path) -> fs::path
147{
148 if(fs::has_known_protocol(href_value))
149 {
150 // Handle protocol paths like "engine:/data/ui/rml.rcss"
151 return fs::resolve_protocol(href_value);
152 }
153
154 // Resolve relative path
155 return fs::absolute(base_file_path.parent_path() / href_value);
156}
157
158template<>
159void resolve_includes<ui_tree>(const fs::path& file_path, std::set<fs::path>& processed_files)
160{
161 if(!processed_files.insert(file_path).second)
162 {
163 return; // Avoid processing the same file multiple times
164 }
165
166 std::ifstream file(file_path);
167 if(!file.is_open())
168 {
169 return;
170 }
171
172 std::string content_str((std::istreambuf_iterator<char>(file)), std::istreambuf_iterator<char>());
173 hpp::string_view content(content_str);
174 // Parse HTML/RML content to find <link> tags with href attributes
175 size_t pos = 0;
176 while((pos = content.find("<link", pos)) != std::string::npos)
177 {
178 // Find the end of the link tag
179 size_t tag_end = content.find('>', pos);
180 if(tag_end == std::string::npos)
181 {
182 break;
183 }
184
185 hpp::string_view link_tag = content.substr(pos, tag_end - pos + 1);
186 hpp::string_view href_value = extract_href_from_link_tag(link_tag);
187
188 if(!href_value.empty())
189 {
190 fs::path resolved_path = resolve_ui_tree_dependency_path(fs::path(href_value), file_path);
191
192 // Recurse into the included file if it's a supported dependency format
193 const auto& supported_deps = ex::get_suported_dependencies_formats<ui_tree>();
194 auto extension = resolved_path.extension().string();
195 if(std::find(supported_deps.begin(), supported_deps.end(), extension) != supported_deps.end())
196 {
197 resolve_includes<ui_tree>(resolved_path, processed_files);
198 }
199 }
200
201 pos = tag_end + 1;
202 }
203}
204
205template<typename T>
206auto has_depencency(const fs::path& file, const fs::path& dep_to_check) -> bool
207{
208 std::set<fs::path> dependecies;
209 resolve_includes<T>(file, dependecies);
210
211 return dependecies.contains(dep_to_check);
212}
213
214auto remove_meta_tag(const fs::path& synced_path) -> fs::path
215{
216 return fs::replace(synced_path, ".meta", "");
217}
218
219auto remove_meta_tag(const std::vector<fs::path>& synced_paths) -> std::vector<fs::path>
220{
221 std::decay_t<decltype(synced_paths)> reduced;
222 reduced.reserve(synced_paths.size());
223 for(const auto& synced_path : synced_paths)
224 {
225 reduced.emplace_back(remove_meta_tag(synced_path));
226 }
227 return reduced;
228}
229
230void unwatch(std::vector<uint64_t>& watchers)
231{
232 for(const auto& id : watchers)
233 {
235 }
236 watchers.clear();
237}
238
239auto get_asset_key(const fs::path& path) -> std::string
240{
242 auto data_key = fs::convert_to_protocol(p);
243 auto key = fs::replace(data_key.generic_string(), ex::get_compiled_directory(), ex::get_data_directory()).generic_string();
244 return key;
245}
246
247auto get_meta_key(const fs::path& path) -> std::string
248{
250 auto data_key = fs::convert_to_protocol(p);
251 auto key = fs::replace(data_key.generic_string(), ex::get_compiled_directory(), ex::get_meta_directory()).generic_string();
252 return key + ".meta";
253}
254
255auto check_files_integrity(const std::string& key, const fs::path& entry_path) -> bool
256{
257 fs::error_code ec;
258 auto key_path = fs::resolve_protocol(key);
259
260 if(!fs::exists(key_path, ec))
261 {
262 APPLOG_WARNING("{} does not exist. Cleaning up cached...", key);
263 fs::remove(entry_path, ec);
264
265 auto meta = get_meta_key(entry_path);
266 auto meta_path = fs::resolve_protocol(meta);
267 if(fs::exists(meta_path, ec))
268 {
269 APPLOG_WARNING("{} does not exist. Cleaning up meta...", key);
270 fs::remove(meta_path, ec);
271 }
272
273 return false;
274 }
275
276 return true;
277}
278
279template<typename T>
280auto watch_assets(rtti::context& ctx, const fs::path& dir, const fs::pattern_filter& filter, bool reload_async) -> uint64_t
281{
282 auto& am = ctx.get_cached<asset_manager>();
283 auto& ts = ctx.get_cached<threader>();
284 auto& tm = ctx.get_cached<thumbnail_manager>();
285 auto& em = ctx.get_cached<editing_manager>();
286
287 fs::path watch_dir = fs::path(dir).make_preferred();
288
289 auto callback = [&am, &ts, &tm, &em](const auto& entries, bool is_initial_list)
290 {
291 std::set<hpp::uuid> changed;
292 std::set<hpp::uuid> removed;
293
294 for(const auto& entry : entries)
295 {
296 auto key = get_asset_key(entry.path);
297
299
300 if(entry.type == fs::file_type::regular)
301 {
303 {
304 removed.emplace(am.get_asset<T>(key).uid());
305 am.unload_asset<T>(key);
306
307 if constexpr(std::is_same<T, script>::value)
308 {
310 }
311 }
313 {
314 auto old_key = get_asset_key(entry.last_path);
315 am.rename_asset<T>(old_key, key);
316
317 if constexpr(std::is_same<T, script>::value)
318 {
320 }
321 }
322 else // created or modified
323 {
324 if(check_files_integrity(key, entry.path))
325 {
326 load_flags flags = is_initial_list ? load_flags::standard : load_flags::reload;
327 auto asset = am.get_asset<T>(key, flags);
328
329 changed.emplace(asset.uid());
330 }
331
332 if constexpr(std::is_same<T, script>::value)
333 {
335 }
336 }
337 }
338 }
339
340 if(!changed.empty() || !removed.empty())
341 {
342 tpp::invoke(tpp::main_thread::get_id(),
343 [&tm, &em, &am, changed, removed]()
344 {
345 for(const auto& uid : removed)
346 {
347 tm.remove_thumbnail(uid);
348 }
349
350 for(const auto& uid : changed)
351 {
352 tm.regenerate_thumbnail(uid);
353
354 if constexpr(std::is_same<T, prefab>::value)
355 {
356 auto asset = am.get_asset<T>(uid);
357 em.on_prefab_updated(asset);
358 }
359 }
360 });
361 }
362 };
363
364 return fs::watcher::watch(watch_dir, filter, true, true, 500ms, callback);
365}
366
367template<typename T>
368auto watch_assets_depenencies(rtti::context& ctx, const fs::path& dir, const fs::pattern_filter& filter) -> uint64_t
369{
370 auto& am = ctx.get_cached<asset_manager>();
371 auto& ts = ctx.get_cached<threader>();
372
373 fs::path watch_dir = fs::path(dir).make_preferred();
374
375 auto callback = [&am, &ts](const auto& entries, bool is_initial_list)
376 {
377 if(is_initial_list)
378 {
379 return;
380 }
381
382 for(const auto& entry : entries)
383 {
385
386 if(entry.type == fs::file_type::regular)
387 {
389 {
390 }
392 {
393 }
394 else // created or modified
395 {
396 auto task = ts.pool->schedule(checking_dependencies_job_name<T>(),
397 [&am, entry]()
398 {
399 auto assets = am.get_assets<T>();
400 for(const auto& asset : assets)
401 {
402 auto meta = am.get_metadata(asset.uid());
403 auto absolute_path = fs::resolve_protocol(meta.location);
404
405 if(has_depencency<T>(absolute_path, entry.path))
406 {
407 fs::watcher::touch(absolute_path, false);
408 }
409 }
410 });
411 }
412 }
413 }
414 };
415
416 return fs::watcher::watch(watch_dir, filter, true, true, 500ms, callback);
417}
418
419template<typename T>
420static void add_to_syncer(rtti::context& ctx,
421 fs::syncer& syncer,
422 const fs::syncer::on_entry_removed_t& on_removed,
423 const fs::syncer::on_entry_renamed_t& on_renamed)
424{
425 auto& ts = ctx.get_cached<threader>();
426 auto& am = ctx.get_cached<asset_manager>();
427
428 auto on_modified =
429 [&ts, &am](const std::string& ext, const auto& ref_path, const auto& synced_paths, bool is_initial_listing)
430 {
431 auto paths = remove_meta_tag(synced_paths);
432
433 for(const auto& output : paths)
434 {
435 fs::error_code err;
436 if(is_initial_listing && fs::exists(output, err))
437 {
438 continue;
439 }
440 auto key = get_asset_key(output);
441 if(check_files_integrity(key, output))
442 {
443 auto task = ts.pool->schedule(get_job_name<T>(),
444 [&am, ref_path, output]()
445 {
446 asset_compiler::compile<T>(am, ref_path, output);
447 });
448 }
449 }
450 };
451
452 for(const auto& type : ex::get_suported_formats<T>())
453 {
454 syncer.set_mapping(type + ".meta", {".asset"}, on_modified, on_modified, on_removed, on_renamed);
455 }
456}
457
458template<typename T>
459static void watch_synced(rtti::context& ctx, std::vector<uint64_t>& watchers, const fs::path& dir)
460{
461 for(const auto& type : ex::get_suported_formats<T>())
462 {
463 const auto watch_id = watch_assets<T>(ctx, dir, fs::pattern_filter("*" + type + ".asset"), true);
464 watchers.push_back(watch_id);
465 }
466}
467
468template<>
469void add_to_syncer<gfx::shader>(rtti::context& ctx,
470 fs::syncer& syncer,
471 const fs::syncer::on_entry_removed_t& on_removed,
472 const fs::syncer::on_entry_renamed_t& on_renamed)
473{
474 auto& ts = ctx.get_cached<threader>();
475 auto& am = ctx.get_cached<asset_manager>();
476
477 auto on_modified =
478 [&ts, &am](const std::string& ext, const auto& ref_path, const auto& synced_paths, bool is_initial_listing)
479 {
480 auto paths = remove_meta_tag(synced_paths);
481 if(paths.empty())
482 {
483 return;
484 }
485 const auto& platform_supported = gfx::get_renderer_platform_supported_filename_extensions();
486
487 for(const auto& output : paths)
488 {
489 auto it =
490 std::find(std::begin(platform_supported), std::end(platform_supported), output.extension().string());
491
492 if(it == std::end(platform_supported))
493 {
494 continue;
495 }
496
497 fs::error_code err;
498 if(is_initial_listing && fs::exists(output, err))
499 {
500 continue;
501 }
502
503 auto key = get_asset_key(output);
504 if(check_files_integrity(key, output))
505 {
506 auto task = ts.pool->schedule(get_job_name<gfx::shader>(),
507 [&am, ref_path, output]()
508 {
509 asset_compiler::compile<gfx::shader>(am, ref_path, output);
510 });
511 }
512 }
513 };
514
516 {
517 syncer.set_mapping(type + ".meta",
518 {".asset.dx11", ".asset.dx12", ".asset.gl", ".asset.spirv"},
519 on_modified,
520 on_modified,
521 on_removed,
522 on_renamed);
523 }
524}
525
526template<>
527void watch_synced<gfx::shader>(rtti::context& ctx, std::vector<uint64_t>& watchers, const fs::path& dir)
528{
529 const auto& renderer_extension = gfx::get_current_renderer_filename_extension();
531 {
532 const auto watch_id = watch_assets<gfx::shader>(ctx, dir, fs::pattern_filter("*" + type + ".asset" + renderer_extension), true);
533 watchers.push_back(watch_id);
534 }
535}
536
537
538} // namespace
539
540void asset_watcher::setup_directory(rtti::context& ctx, fs::syncer& syncer)
541{
542 const auto on_dir_modified =
543 [](const std::string& ext, const auto& /*ref_path*/, const auto& /*synced_paths*/, bool /*is_initial_listing*/)
544 {
545
546 };
547 const auto on_dir_removed = [](const std::string& ext, const auto& /*ref_path*/, const auto& synced_paths)
548 {
549 for(const auto& synced_path : synced_paths)
550 {
551 fs::error_code err;
552 fs::remove_all(synced_path, err);
553 }
554 };
555
556 const auto on_dir_renamed = [](const std::string& ext, const auto& /*ref_path*/, const auto& synced_paths)
557 {
558 for(const auto& synced_path : synced_paths)
559 {
560 fs::error_code err;
561 fs::rename(synced_path.first, synced_path.second, err);
562 }
563 };
564 syncer.set_directory_mapping(on_dir_modified, on_dir_modified, on_dir_removed, on_dir_renamed);
565}
566
567void asset_watcher::setup_meta_syncer(rtti::context& ctx,
568 std::vector<uint64_t>& watchers,
569 fs::syncer& syncer,
570 const fs::path& data_dir,
571 const fs::path& meta_dir,
572 bool wait)
573{
574 setup_directory(ctx, syncer);
575 auto& am = ctx.get_cached<asset_manager>();
576
577 const auto on_file_removed = [&am](const std::string& ext, const auto& ref_path, const auto& synced_paths)
578 {
579 for(const auto& synced_path : synced_paths)
580 {
581 fs::error_code err;
582 fs::remove_all(synced_path, err);
583
584 am.remove_asset_info_for_path(ref_path);
585 }
586 };
587
588 const auto on_file_renamed = [](const std::string& ext, const auto& /*ref_path*/, const auto& synced_paths)
589 {
590 for(const auto& synced_path : synced_paths)
591 {
592 fs::error_code err;
593 fs::rename(synced_path.first, synced_path.second, err);
594 }
595 };
596
597 const auto on_file_modified =
598 [&am](const std::string& ext, const auto& ref_path, const auto& synced_paths, bool is_initial_listing)
599 {
600 for(const auto& synced_path : synced_paths)
601 {
602 asset_meta meta;
603 fs::error_code err;
604 if(fs::exists(synced_path, err))
605 {
606 load_from_file(synced_path.string(), meta);
607 }
608
609 if(meta.uid.is_nil())
610 {
611 auto key = fs::convert_to_protocol(ref_path).generic_string();
612 meta = am.generate_metadata(key);
613 }
614 meta.uid = am.add_asset_info_for_path(ref_path, meta, true);
615
616 save_to_file(synced_path.string(), meta);
617 }
618 };
619
620 for(const auto& asset_set : ex::get_all_formats())
621 {
622 for(const auto& type : asset_set)
623 {
624 syncer.set_mapping(type, {".meta"}, on_file_modified, on_file_modified, on_file_removed, on_file_renamed);
625 }
626 }
627
629 {
630 auto id = watch_assets_depenencies<gfx::shader>(ctx, data_dir, fs::pattern_filter("*" + dep_ex));
631 watchers.emplace_back(id);
632 }
633
634 for(const auto& dep_ex : ex::get_suported_dependencies_formats<ui_tree>())
635 {
636 auto id = watch_assets_depenencies<ui_tree>(ctx, data_dir, fs::pattern_filter("*" + dep_ex));
637 watchers.emplace_back(id);
638 }
639
640 syncer.sync(data_dir, meta_dir);
641
642 if(wait)
643 {
644 auto& ts = ctx.get_cached<threader>();
645 ts.pool->wait_all();
646 }
647}
648
649void asset_watcher::setup_cache_syncer(rtti::context& ctx,
650 std::vector<uint64_t>& watchers,
651 fs::syncer& syncer,
652 const fs::path& meta_dir,
653 const fs::path& cache_dir,
654 bool wait)
655{
656 setup_directory(ctx, syncer);
657
658 auto on_removed = [](const std::string& ext, const auto& /*ref_path*/, const auto& synced_paths)
659 {
660 for(const auto& synced_path : synced_paths)
661 {
662 auto synced_asset = remove_meta_tag(synced_path);
663 fs::error_code err;
664 fs::remove_all(synced_asset, err);
665 }
666 };
667
668 auto on_renamed = [](const std::string& ext, const auto& /*ref_path*/, const auto& synced_paths)
669 {
670 for(const auto& synced_path : synced_paths)
671 {
672 auto synced_old_asset = remove_meta_tag(synced_path.first);
673 auto synced_new_asset = remove_meta_tag(synced_path.second);
674 fs::error_code err;
675 fs::rename(synced_old_asset, synced_new_asset, err);
676 }
677 };
678
679 add_to_syncer<gfx::texture>(ctx, syncer, on_removed, on_renamed);
680 add_to_syncer<gfx::shader>(ctx, syncer, on_removed, on_renamed);
681 add_to_syncer<mesh>(ctx, syncer, on_removed, on_renamed);
682 add_to_syncer<material>(ctx, syncer, on_removed, on_renamed);
683 add_to_syncer<animation_clip>(ctx, syncer, on_removed, on_renamed);
684 add_to_syncer<prefab>(ctx, syncer, on_removed, on_renamed);
685 add_to_syncer<scene_prefab>(ctx, syncer, on_removed, on_renamed);
686 add_to_syncer<physics_material>(ctx, syncer, on_removed, on_renamed);
687 add_to_syncer<audio_clip>(ctx, syncer, on_removed, on_renamed);
688 add_to_syncer<font>(ctx, syncer, on_removed, on_renamed);
689 add_to_syncer<script>(ctx, syncer, on_removed, on_renamed);
690 add_to_syncer<ui_tree>(ctx, syncer, on_removed, on_renamed);
691 add_to_syncer<style_sheet>(ctx, syncer, on_removed, on_renamed);
692
693 syncer.sync(meta_dir, cache_dir);
694
695 if(wait)
696 {
697 auto& ts = ctx.get_cached<threader>();
698 ts.pool->wait_all();
699 }
700
701 watch_synced<gfx::texture>(ctx, watchers, cache_dir);
702 watch_synced<gfx::shader>(ctx, watchers, cache_dir);
703 watch_synced<mesh>(ctx, watchers, cache_dir);
704 watch_synced<material>(ctx, watchers, cache_dir);
705 watch_synced<animation_clip>(ctx, watchers, cache_dir);
706 watch_synced<prefab>(ctx, watchers, cache_dir);
707 watch_synced<scene_prefab>(ctx, watchers, cache_dir);
708 watch_synced<physics_material>(ctx, watchers, cache_dir);
709 watch_synced<audio_clip>(ctx, watchers, cache_dir);
710 watch_synced<font>(ctx, watchers, cache_dir);
711 watch_synced<script>(ctx, watchers, cache_dir);
712 watch_synced<ui_tree>(ctx, watchers, cache_dir);
713 watch_synced<style_sheet>(ctx, watchers, cache_dir);
714}
715
719
723
724void asset_watcher::on_os_event(rtti::context& ctx, os::event& e)
725{
726 if(e.type == os::events::window)
727 {
728
729 if(e.window.type == os::window_event_id::focus_lost)
730 {
731 if(!os::window::is_any_focused())
732 {
733 // APPLOG_TRACE("Application lost focus");
735 }
736 }
737 if(e.window.type == os::window_event_id::focus_gained)
738 {
739 if(os::window::is_any_focused())
740 {
741 // APPLOG_TRACE("Application gained focus");
743 }
744 }
745 }
746}
747
749{
750 APPLOG_TRACE("{}::{}", hpp::type_name_str(*this), __func__);
751
752 auto& ev = ctx.get_cached<events>();
753 ev.on_os_event.connect(sentinel_, 1000, this, &asset_watcher::on_os_event);
754
755 watch_assets(ctx, "engine:/", true);
756
757 return true;
758}
759
761{
762 APPLOG_TRACE("{}::{}", hpp::type_name_str(*this), __func__);
763
764 unwatch_assets(ctx, "engine:/");
765 return true;
766}
767
768void asset_watcher::watch_assets(rtti::context& ctx, const std::string& protocol, bool wait)
769{
770 auto& w = watched_protocols_[protocol];
771
772 auto data_protocol = ex::get_data_directory_no_slash(protocol);
773 auto meta_protocol = ex::get_meta_directory_no_slash(protocol);
774 auto cache_protocol = ex::get_compiled_directory_no_slash(protocol);
775
776 setup_meta_syncer(ctx,
777 w.watchers,
778 w.meta_syncer,
779 fs::resolve_protocol(data_protocol),
780 fs::resolve_protocol(meta_protocol),
781 wait);
782
783 setup_cache_syncer(ctx,
784 w.watchers,
785 w.cache_syncer,
786 fs::resolve_protocol(meta_protocol),
787 fs::resolve_protocol(cache_protocol),
788 wait);
789}
790
791void asset_watcher::unwatch_assets(rtti::context& ctx, const std::string& protocol)
792{
793 auto& w = watched_protocols_[protocol];
794
795 unwatch(w.watchers);
796 w.meta_syncer.unsync();
797 w.cache_syncer.unsync();
798
799 watched_protocols_.erase(protocol);
800
801 auto& am = ctx.get_cached<asset_manager>();
802 am.unload_group(protocol);
803}
804
805} // namespace unravel
manifold_type type
A filter that combines include and exclude patterns for file/directory filtering.
void set_mapping(const std::string &ref_ext, const std::vector< std::string > &synced_ext, on_entry_created_t on_entry_created, on_entry_modified_t on_entry_modified, on_entry_removed_t on_entry_removed, on_entry_renamed_t on_entry_renamed)
Remaps a specific extension of the reference directory to extensions of the synced directory....
Definition syncer.cpp:24
std::function< void(const std::string &, const rename_pair_t &, const std::vector< rename_pair_t > &)> on_entry_renamed_t
Definition syncer.h:21
void sync(const fs::path &reference_dir, const fs::path &synced_dir)
Start syncing the synced_dir with reference to the reference_dir i.e changes that occur in the refere...
Definition syncer.cpp:90
void set_directory_mapping(on_entry_created_t on_entry_created, on_entry_modified_t on_entry_modified, on_entry_removed_t on_entry_removed, on_entry_renamed_t on_entry_renamed)
Definition syncer.cpp:40
std::function< void(const std::string &, const fs::path &, const std::vector< fs::path > &)> on_entry_removed_t
Definition syncer.h:20
static void unwatch(std::uint64_t key)
Un-watches a previously registered file or directory.
Definition watcher.cpp:426
static void resume()
Definition watcher.cpp:491
static void pause()
Definition watcher.cpp:475
static void touch(const fs::path &path, bool recursive, fs::file_time_type time=fs::now())
Sets the last modification time of a file or directory. by default sets the time to the current time.
Definition watcher.cpp:436
static auto watch(const fs::path &path, const pattern_filter &filter, bool recursive, bool initial_list, clock_t::duration poll_interval, notify_callback callback) -> std::uint64_t
Watches a file or directory for modification and call back the specified std::function....
Definition watcher.cpp:416
Manages assets, including loading, unloading, and storage.
void unload_group(const std::string &group)
Unloads all assets in a specified group.
auto deinit(rtti::context &ctx) -> bool
void watch_assets(rtti::context &ctx, const std::string &protocol, bool wait=false)
auto init(rtti::context &ctx) -> bool
void unwatch_assets(rtti::context &ctx, const std::string &protocol)
#define APPLOG_WARNING(...)
Definition logging.h:19
#define APPLOG_TRACE(...)
Definition logging.h:17
auto get_suported_formats< gfx::shader >() -> const std::vector< std::string > &
auto get_all_formats() -> const std::vector< std::vector< std::string > > &
auto get_compiled_directory_no_slash(const std::string &prefix={}) -> std::string
auto get_data_directory(const std::string &prefix={}) -> std::string
auto get_type() -> const std::string &
auto get_meta_directory_no_slash(const std::string &prefix={}) -> std::string
auto get_compiled_directory(const std::string &prefix={}) -> std::string
auto get_suported_dependencies_formats< gfx::shader >() -> const std::vector< std::string > &
auto get_meta_directory(const std::string &prefix={}) -> std::string
auto get_suported_formats() -> const std::vector< std::string > &
auto get_data_directory_no_slash(const std::string &prefix={}) -> std::string
auto get_suported_dependencies_formats() -> const std::vector< std::string > &
path extract_protocol(const path &_path)
Given the specified path/filename, resolve the final full filename. This will be based on either the ...
path reduce_trailing_extensions(const path &_path)
another.
path resolve_protocol(const path &_path)
Given the specified path/filename, resolve the final full filename. This will be based on either the ...
bool has_known_protocol(const path &_path)
Checks whether the path has a known protocol.
path replace(const path &_path, const path &_sequence, const path &_new_sequence)
Replacing any occurences of the specified path sequence with another.
auto to_string(const watcher::entry &e) -> std::string
Definition watcher.cpp:617
path convert_to_protocol(const path &_path)
Oposite of the resolve_protocol this function tries to convert to protocol path from an absolute one.
auto get_renderer_platform_supported_filename_extensions() -> const std::vector< std::string > &
auto get_current_renderer_filename_extension() -> const std::string &
void end(encoder *_encoder)
Definition graphics.cpp:270
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 compile< gfx::shader >(asset_manager &am, const fs::path &key, const fs::path &output, uint32_t flags) -> bool
auto compile(asset_manager &am, const fs::path &key, const fs::path &output_key, uint32_t flags=0) -> bool
auto get_job_name() -> std::string
void load_from_file(const std::string &absolute_path, animation_clip &obj)
void save_to_file(const std::string &absolute_path, const animation_clip &obj)
auto get_cached() -> T &
Definition context.hpp:49
hpp::event< void(rtti::context &, os::event &e)> on_os_event
os events
Definition events.h:34
static void set_needs_recompile(const std::string &protocol, bool now=false)