#include "Web_Plot_Session.h" #include "Pixel_Frame.h" #include "render_2D/scene/Render_Scene_2D.h" #include #include #include #include namespace renderive::web { struct Web_Plot_Session::Impl { Size viewport{960, 600}; std::uint64_t sequence{}; std::unique_ptr scene; Impl() { rebuild(); } void rebuild() { auto built_scene = Render_Scene_2D::Builder( std::make_shared()) .set<&Render_Scene_2D::Properties::viewport>(viewport) .build(); if (!built_scene) ::renderive::error::unexpected( "web plot scene topology validation failed"); scene = std::move(*built_scene); scene->activate_view(); } std::optional encode_frame() { std::string pixels; scene->with_frame([&](Image_View image) { pixels = encode_pixel_frame(image, ++sequence); }); if (pixels.empty()) return std::nullopt; return Web_Response{Web_Response_Type::Pixels, std::move(pixels)}; } std::optional handle(const Web_Event& event) { return std::visit([this](const auto& value) -> std::optional { using T = std::decay_t; if constexpr (std::same_as) { const auto result = scene->render_frame(); if (!result || scene->wait_for_render() != Scene_Render_Result::none) return std::nullopt; return encode_frame(); } else if constexpr (std::same_as) { viewport = value.size; rebuild(); } else if constexpr (std::derived_from) { scene->dispatch_event(value); } return std::nullopt; }, event); } void async_handle(const Web_Event& event, Web_Response_Completion completion) { if (!std::holds_alternative(event)) { completion({handle(event), {}}); return; } const auto result = scene->render_frame( [this, completion](Scene_Render_Result render_result, std::exception_ptr exception) mutable { if (exception) { completion({{}, std::move(exception)}); return; } if (render_result != Scene_Render_Result::none) { completion({}); return; } try { completion({encode_frame(), {}}); } catch (...) { completion({{}, std::current_exception()}); } }); if (!result || *result != Plot_Render_Status::rendered) completion({}); } }; Web_Plot_Session::Web_Plot_Session() : impl_(std::make_unique()) {} Web_Plot_Session::~Web_Plot_Session() = default; std::optional Web_Plot_Session::handle(const Web_Event& event) { return impl_->handle(event); } void Web_Plot_Session::async_handle(const Web_Event& event, Web_Response_Completion completion) { impl_->async_handle(event, std::move(completion)); } } // namespace renderive::web