137 lines
4.5 KiB
C++
137 lines
4.5 KiB
C++
#pragma once
|
|
|
|
#include "Gallery_Capture_Json.h"
|
|
#include "Gallery_Observer_Adminive.h"
|
|
#include "Gallery_Renderables.h"
|
|
|
|
#include <renderive/scene/base/Scene_Base.hpp>
|
|
|
|
#include <nlohmann/json.hpp>
|
|
|
|
#include <algorithm>
|
|
#include <array>
|
|
#include <charconv>
|
|
#include <concepts>
|
|
#include <functional>
|
|
#include <stdexcept>
|
|
#include <string>
|
|
#include <string_view>
|
|
#include <unordered_map>
|
|
#include <utility>
|
|
#include <vector>
|
|
|
|
namespace renderive::web {
|
|
|
|
class Gallery_Controls final {
|
|
public:
|
|
using Json = nlohmann::json;
|
|
|
|
template <class Object>
|
|
void add(Object& object) {
|
|
const auto descriptor = adminive::Type_Descriptor<Object>::get();
|
|
add(descriptor.name(), descriptor.label(), object);
|
|
}
|
|
|
|
template <class Object>
|
|
void add(std::string id, Object& object) {
|
|
add(std::move(id), adminive::Type_Descriptor<Object>::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<const renderive::Renderable*>(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<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<Json()> resource;
|
|
std::function<adminive::Update_Result(const Json&)> apply;
|
|
renderive::Renderable* renderable{};
|
|
};
|
|
|
|
template <class Object>
|
|
void add(std::string id, std::string title, Object& object) {
|
|
using Model = adminive::Object_Model_Type<Object>;
|
|
auto* target = &object;
|
|
renderive::Renderable* renderable{};
|
|
if constexpr (std::derived_from<Object, renderive::Renderable>)
|
|
renderable = target;
|
|
entries_.push_back({
|
|
std::move(id), std::move(title),
|
|
[target] {
|
|
return Json{
|
|
{"descriptor", adminive::to_descriptor_json<Json, Object>()},
|
|
{"view", adminive::to_view_json<Json, Model>(
|
|
adminive::describe_edit_view<Model>())},
|
|
{"data", adminive::to_frontend_json<Json>(*target)}
|
|
};
|
|
},
|
|
[target](const Json& patch) {
|
|
return adminive::apply_frontend_patch<Json>(*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<Entry> entries_;
|
|
};
|
|
|
|
} // namespace renderive::web
|