Unravel Engine C++ Reference
Loading...
Searching...
No Matches
asset_dependency_graph.cpp
Go to the documentation of this file.
2
3#include "asset_manager.h"
4
7
8#include <algorithm>
9#include <deque>
10#include <unordered_set>
11
13{
14
15namespace
16{
17
18//------------------------------------------------------------------------------
19// Append the handle's UUID to `out` unless it's nil. Centralises the nil
20// filter so call sites stay terse.
21//------------------------------------------------------------------------------
22template<typename T>
23void push_if_set(std::vector<hpp::uuid>& out, const asset_handle<T>& handle)
24{
25 const auto& uid = handle.uid();
26 if(!uid.is_nil())
27 {
28 out.push_back(uid);
29 }
30}
31
32} // namespace
33
34//------------------------------------------------------------------------------
35// material → up to six texture maps.
36//
37// Only `pbr_material` carries texture slots today; the base `material` class
38// is abstract / has no maps. We dynamic-cast rather than make this virtual to
39// keep the dep-graph concern out of the material interface.
40//------------------------------------------------------------------------------
41auto get_referenced_uids(const material& m) -> std::vector<hpp::uuid>
42{
43 std::vector<hpp::uuid> result;
44 if(m.is<pbr_material>())
45 {
46 const auto& pbr = static_cast<const pbr_material&>(m);
47
48 result.reserve(6);
49 push_if_set(result, pbr.get_color_map());
50 push_if_set(result, pbr.get_normal_map());
51 push_if_set(result, pbr.get_roughness_map());
52 push_if_set(result, pbr.get_metalness_map());
53 push_if_set(result, pbr.get_ao_map());
54 push_if_set(result, pbr.get_emissive_map());
55 }
56 return result;
57}
58
59//------------------------------------------------------------------------------
60// mesh → the materials it was imported with.
61//
62// We read the raw UUIDs (not `get_imported_materials()`), which would force a
63// load via `asset_manager::get_asset<material>(uid)` — we just want
64// references, not loaded objects.
65//------------------------------------------------------------------------------
66auto get_referenced_uids(const mesh& m) -> std::vector<hpp::uuid>
67{
68 const auto& uids = m.get_default_material_uids();
69 std::vector<hpp::uuid> result;
70 result.reserve(uids.size());
71 for(const auto& uid : uids)
72 {
73 if(!uid.is_nil())
74 {
75 result.push_back(uid);
76 }
77 }
78 return result;
79}
80
81//------------------------------------------------------------------------------
82// Walks the loaded set of `T` and appends the UUID of every asset whose
83// reference list contains `target`. Skips assets that aren't currently
84// resident (`peek()` returns nullptr) — they have no in-memory thumbnail to
85// invalidate, and will be re-rendered fresh on the next request.
86//
87// Lives at file scope (not as a lambda) so we can inline-template it cleanly
88// over multiple types without copy-pasting the body.
89//------------------------------------------------------------------------------
90template<typename T>
92 const hpp::uuid& target,
93 std::vector<hpp::uuid>& out)
94{
95 am.for_each_asset<T>(
96 [&](const auto& kvp) -> void
97 {
98 const auto& handle = kvp.second;
99 if(handle.uid().is_nil())
100 {
101 return;
102 }
103
104 auto loaded = handle.peek();
105 if(!loaded)
106 {
107 return;
108 }
109
110 const auto deps = get_referenced_uids(*loaded);
111 if(std::find(deps.begin(), deps.end(), target) != deps.end())
112 {
113 out.push_back(handle.uid());
114 }
115 });
116}
117
118auto find_loaded_dependents(asset_manager& am, const hpp::uuid& uid) -> std::vector<hpp::uuid>
119{
120 std::vector<hpp::uuid> result;
121
122 collect_dependents<material>(am, uid, result);
123 collect_dependents<mesh>(am, uid, result);
124
125 return result;
126}
127
128auto find_transitive_loaded_dependents(asset_manager& am, const hpp::uuid& root)
129 -> std::vector<hpp::uuid>
130{
131 std::vector<hpp::uuid> result;
132 if(root.is_nil())
133 {
134 return result;
135 }
136
137 std::unordered_set<hpp::uuid> visited;
138 std::deque<hpp::uuid> queue;
139 visited.insert(root);
140 queue.push_back(root);
141
142 while(!queue.empty())
143 {
144 const auto current = queue.front();
145 queue.pop_front();
146
147 for(const auto& dep : find_loaded_dependents(am, current))
148 {
149 if(visited.insert(dep).second)
150 {
151 result.push_back(dep);
152 queue.push_back(dep);
153 }
154 }
155 }
156
157 return result;
158}
159
160} // namespace unravel::asset_deps
Manages assets, including loading, unloading, and storage.
void for_each_asset(F &&callback)
Applies a callback function to each asset.
Base class for materials used in rendering.
Definition material.h:44
Main class representing a 3D mesh with support for different LODs, submeshes, and skinning.
Definition mesh.h:323
Class for physically-based rendering (PBR) materials.
Definition material.h:112
auto find_transitive_loaded_dependents(asset_manager &am, const hpp::uuid &root) -> std::vector< hpp::uuid >
void collect_dependents(asset_manager &am, const hpp::uuid &target, std::vector< hpp::uuid > &out)
auto find_loaded_dependents(asset_manager &am, const hpp::uuid &uid) -> std::vector< hpp::uuid >
auto get_referenced_uids(const material &m) -> std::vector< hpp::uuid >
Thread-safe handle to an asset.
gfx::uniform_handle handle
Definition uniform.cpp:9