#pragma once #include "Gallery_Capture_Json.h" #include "Gallery_Observer_Adminive.h" #include "Gallery_Renderables.h" #include #include #include #include #include #include #include #include #include #include #include #include #include namespace renderive::web { class Gallery_Controls final { public: using Json = nlohmann::json; template void add(Object& object) { const auto descriptor = adminive::Type_Descriptor::get(); add(descriptor.name(), descriptor.label(), object); } template void add(std::string id, Object& object) { add(std::move(id), adminive::Type_Descriptor::get().label(), object); } [[nodiscard]] Json resources() const { Json result = Json::array(); for (const auto& entry : entries_) { Json resource = entry.resource(); resource["target"] = entry.id; resource["view"]["title"] = entry.title; result.push_back(std::move(resource)); } return result; } [[nodiscard]] Json observers(const Scene_Base& scene) const { Json result = Json::array(); const auto topology = scene.topology_snapshot(); for (std::size_t index = 0; index < topology.renderables.size(); ++index) { const auto* renderable = dynamic_cast(topology.renderables[index].get()); if (!renderable) continue; const Entry* entry = find(renderable); std::string title = entry ? entry->title : renderable->object_name(); if (title.empty()) title = "渲染节点 " + std::to_string(index + 1); Json resource{ {"descriptor", adminive::to_descriptor_json< Json, renderive::Renderable_Observation>()}, {"data", adminive::to_frontend_json(renderable->observation())}, {"target", entry ? entry->id : node_id(index)}, {"title", std::move(title)} }; result.push_back(std::move(resource)); } return result; } [[nodiscard]] Json render_plan(const Scene_Base& scene) const { return gallery_render_plan_json(scene); } [[nodiscard]] adminive::Update_Result apply(std::string_view target, const Json& patch) const { for (const auto& entry : entries_) { if (entry.id == target) return entry.apply(patch); } adminive::Update_Result result; result.success = false; result.message = "unknown gallery control target: " + std::string(target); return result; } private: struct Entry { std::string id; std::string title; std::function resource; std::function apply; renderive::Renderable* renderable{}; }; template void add(std::string id, std::string title, Object& object) { using Model = adminive::Object_Model_Type; auto* target = &object; renderive::Renderable* renderable{}; if constexpr (std::derived_from) renderable = target; entries_.push_back({ std::move(id), std::move(title), [target] { return Json{ {"descriptor", adminive::to_descriptor_json()}, {"view", adminive::to_view_json( adminive::describe_edit_view())}, {"data", adminive::to_frontend_json(*target)} }; }, [target](const Json& patch) { return adminive::apply_frontend_patch(*target, patch); }, renderable }); } [[nodiscard]] const Entry* find(const Renderable_Base* renderable) const noexcept { const auto found = std::find_if(entries_.begin(), entries_.end(), [renderable](const Entry& entry) { return entry.renderable == renderable; }); return found == entries_.end() ? nullptr : &*found; } static std::string node_id(std::size_t index) { return "renderable-" + std::to_string(index); } std::vector entries_; }; } // namespace renderive::web