68 halp_meta(name,
"glTF Live Link")
69 halp_meta(category,
"Visuals/3D")
70 halp_meta(c_name,
"gltf_live_link")
73 "Receive a 3D scene streamed live from Blender: geometry and materials "
74 "as glTF, object transforms as they move.")
75 halp_meta(authors,
"ossia team")
77 manual_url,
"https://ossia.io/score-docs/processes/gltf-live-link.html")
78 halp_meta(uuid,
"b9446bac-dbeb-4672-a9b6-db6e6cdaef2e")
82 halp::spinbox_i32<
"Port", halp::irange{1, 65535, LiveLink::default_port}> port;
85 halp::lineedit<
"Bind address",
"127.0.0.1"> bind;
86 halp::toggle<
"Listen", halp::toggle_setup{.init =
true}> listen;
95 halp::toggle<
"Cameras", halp::toggle_setup{.init =
true}> cameras;
96 halp::toggle<
"Lights", halp::toggle_setup{.init =
true}> lights;
97 halp::toggle<
"Materials", halp::toggle_setup{.init =
true}> materials;
98 halp::toggle<
"Skinning", halp::toggle_setup{.init =
true}> skinning;
100 halp::toggle<
"Bone poses", halp::toggle_setup{.init =
true}> bone_poses;
101 halp::toggle<
"Shape keys", halp::toggle_setup{.init =
true}> shape_keys;
102 halp::toggle<
"World", halp::toggle_setup{.init =
true}> world;
105 halp::toggle<
"Move cameras", halp::toggle_setup{.init =
false}> move_cameras;
112 halp_meta(name,
"Scene");
113 ossia::scene_spec scene;
147 std::shared_ptr<LiveLink::structural_message> message;
149 using job = std::variant<glb_job, mesh_job>;
152 std::function<void(job)> request;
160 std::shared_ptr<const ossia::scene_state> parsed, uint64_t seq,
161 std::vector<std::string> material_names = {});
165 bool patch, uint64_t seq, std::shared_ptr<const ossia::scene_state> state,
166 std::vector<std::string> material_names);
174 std::shared_ptr<const ossia::scene_state> patch, uint64_t seq,
175 std::vector<std::string> material_names = {});
178 void remove_nodes(
const std::vector<std::string>& names, uint64_t seq);
182 void apply(LiveLink::inbox box);
183 void set_transform(
const LiveLink::transform_record& r, uint64_t seq);
187 std::shared_ptr<const ossia::scene_state> m_parsed_state;
188 std::shared_ptr<const ossia::scene_state> m_overridden_state;
189 std::shared_ptr<const ossia::scene_state> m_wrapped_state;
198 template <
typename Ptr>
201 const void* source{};
207 uint64_t weights_seq{};
208 std::vector<const ossia::material_component*> materials;
209 ossia::mesh_component_ptr result;
214 using mesh_key = std::pair<uint64_t, const ossia::mesh_component*>;
215 std::unordered_map<uint64_t, derived<ossia::light_component_ptr>> lights;
216 std::unordered_map<uint64_t, derived<ossia::camera_component_ptr>> cameras;
217 std::unordered_map<std::size_t, derived<ossia::material_component_ptr>> materials;
218 std::map<mesh_key, derived_mesh> meshes;
222 void restart_server();
224 void apply_pending();
225 void rebuild_lookups();
227 void rebuild_overridden_state();
228 void apply_overrides();
229 std::shared_ptr<const ossia::scene_state>
230 filter_components(std::shared_ptr<const ossia::scene_state> st);
231 void rebuild_wrapped_state();
233 std::unique_ptr<LiveLink::server> m_server;
234 std::string m_server_bind;
235 int m_server_port{-1};
236 bool m_server_failed{};
237 int m_retry_countdown{};
241 uint64_t m_scene_seq{};
242 uint64_t m_requested_scene_seq{};
246 struct pending_change
249 enum kind_t : uint8_t
257 std::shared_ptr<const ossia::scene_state> state;
259 std::vector<std::string> names;
260 LiveLink::structural_message message;
264 bool is_resource() const noexcept {
return kind == native && message.is_resource(); }
266 std::vector<pending_change> m_pending;
267 LiveLink::native_resources m_native;
268 void apply_native(LiveLink::structural_message& m);
271 std::vector<std::string> m_material_names;
272 uint64_t m_max_node_id{};
273 std::optional<LiveLink::stamped<LiveLink::environment_record>> m_environment;
274 std::optional<LiveLink::stamped<LiveLink::node_name_record>> m_active_camera;
278 LiveLink::latest<LiveLink::transform_record> m_transforms;
279 LiveLink::latest<LiveLink::joint_record> m_joints;
280 LiveLink::latest<LiveLink::weights_record> m_weights;
281 LiveLink::latest<LiveLink::visibility_record> m_visibility;
282 LiveLink::latest<LiveLink::light_record> m_lights;
283 LiveLink::latest<LiveLink::camera_record> m_cameras;
284 LiveLink::latest<LiveLink::material_record> m_materials;
287 template <
typename Record>
289 LiveLink::latest<Record>& map, std::string key, uint64_t seq, Record r,
296 std::unordered_multimap<std::string, uint64_t> m_ids_by_name;
297 std::unordered_map<std::string, uint64_t> m_ids_by_joint;
298 std::unordered_multimap<std::string, std::size_t> m_material_index;
299 bool m_overrides_dirty{};
300 uint8_t m_overrides_dirt{};
301 bool m_scene_dirty{};
303 CachedTRS m_cached_xform;
306 struct import_options
308 bool cameras, lights, materials, skinning, bone_poses, shape_keys, world,
310 bool operator==(
const import_options&)
const noexcept =
default;
312 import_options current_options() const noexcept;
313 std::optional<import_options> m_options;
317 std::unordered_map<const ossia::mesh_component*, ossia::mesh_component_ptr>
319 int64_t m_version_counter{0};
322 ossia::gpu_slot_ref m_xform_ref{};