删除plot_core
This commit is contained in:
@@ -88,19 +88,19 @@ struct Type_Descriptor<Manual_Refresh_Strategy<Scene_Frame, Mutex, Observer>> {
|
||||
using renderive::web::gallery_action;
|
||||
return object<T>(type_metadata(
|
||||
gallery_action("mode_prepare", "准备帧",
|
||||
"Manual_Refresh_Strategy::acquire_painter / Plot_Core::prepare_frame",
|
||||
"Manual_Refresh_Strategy::acquire_painter / Basic_Scene2D::prepare_frame",
|
||||
"Manual_Refresh_Strategy"),
|
||||
gallery_action("mode_refresh", "提交手动刷新",
|
||||
"Manual_Refresh_Strategy::refresh / Plot_Core::refresh_manual_frame",
|
||||
"Manual_Refresh_Strategy::refresh / Basic_Scene2D::refresh_manual_frame",
|
||||
"Manual_Refresh_Strategy"),
|
||||
gallery_action("mode_render", "渲染已刷新帧",
|
||||
"Manual_Refresh_Strategy::acquire_renderer / Plot_Core::render_prepared_frame",
|
||||
"Manual_Refresh_Strategy::acquire_renderer / Basic_Scene2D::render_prepared_frame",
|
||||
"Manual_Refresh_Strategy", {}, {}, {}, 0.0, true),
|
||||
gallery_action("mode_discard", "丢弃待刷新帧",
|
||||
"Plot_Core::discard_pending_frame",
|
||||
"Basic_Scene2D::discard_pending_frame",
|
||||
"Manual_Refresh_Strategy"),
|
||||
gallery_action("mode_cycle", "执行完整手动帧周期",
|
||||
"Plot_Core::render_frame", "Manual_Refresh_Strategy",
|
||||
"Basic_Scene2D::render_frame", "Manual_Refresh_Strategy",
|
||||
{}, {}, {}, 0.0, true)));
|
||||
}
|
||||
};
|
||||
@@ -112,15 +112,15 @@ struct Type_Descriptor<Low_Latency_Strategy<Scene_Frame, Mutex, Observer>> {
|
||||
using renderive::web::gallery_action;
|
||||
return object<T>(type_metadata(
|
||||
gallery_action("mode_prepare", "发布低延迟帧",
|
||||
"Low_Latency_Strategy::acquire_painter / Plot_Core::prepare_frame",
|
||||
"Low_Latency_Strategy::acquire_painter / Basic_Scene2D::prepare_frame",
|
||||
"Low_Latency_Strategy"),
|
||||
gallery_action("mode_render", "消费最新帧",
|
||||
"Low_Latency_Strategy::acquire_renderer / Plot_Core::render_prepared_frame",
|
||||
"Low_Latency_Strategy::acquire_renderer / Basic_Scene2D::render_prepared_frame",
|
||||
"Low_Latency_Strategy", {}, {}, {}, 0.0, true),
|
||||
gallery_action("mode_discard", "丢弃陈旧帧",
|
||||
"Plot_Core::discard_pending_frame", "Low_Latency_Strategy"),
|
||||
"Basic_Scene2D::discard_pending_frame", "Low_Latency_Strategy"),
|
||||
gallery_action("mode_cycle", "执行低延迟帧周期",
|
||||
"Plot_Core::render_frame", "Low_Latency_Strategy",
|
||||
"Basic_Scene2D::render_frame", "Low_Latency_Strategy",
|
||||
{}, {}, {}, 0.0, true)));
|
||||
}
|
||||
};
|
||||
@@ -132,16 +132,16 @@ struct Type_Descriptor<Flow_Refresh_Strategy<Scene_Frame, Mutex, Observer>> {
|
||||
using renderive::web::gallery_action;
|
||||
return object<T>(type_metadata(
|
||||
gallery_action("mode_enqueue", "压入一帧",
|
||||
"Flow_Refresh_Strategy::acquire_painter / Plot_Core::prepare_frame",
|
||||
"Flow_Refresh_Strategy::acquire_painter / Basic_Scene2D::prepare_frame",
|
||||
"Flow_Refresh_Strategy"),
|
||||
gallery_action("mode_enqueue_burst", "批量压入回放队列",
|
||||
"Flow_Refresh_Strategy::acquire_painter / Plot_Core::prepare_frame x N",
|
||||
"Flow_Refresh_Strategy::acquire_painter / Basic_Scene2D::prepare_frame x N",
|
||||
"Flow_Refresh_Strategy", {}, "number", "帧数", 8.0),
|
||||
gallery_action("mode_dequeue", "消费队首帧",
|
||||
"Flow_Refresh_Strategy::acquire_renderer / Plot_Core::render_prepared_frame",
|
||||
"Flow_Refresh_Strategy::acquire_renderer / Basic_Scene2D::render_prepared_frame",
|
||||
"Flow_Refresh_Strategy", {}, {}, {}, 0.0, true),
|
||||
gallery_action("mode_cycle", "执行回放帧周期",
|
||||
"Plot_Core::render_frame", "Flow_Refresh_Strategy",
|
||||
"Basic_Scene2D::render_frame", "Flow_Refresh_Strategy",
|
||||
{}, {}, {}, 0.0, true)));
|
||||
}
|
||||
};
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
#pragma once
|
||||
|
||||
#include "Gallery_Enum.h"
|
||||
#include "render_2D/plot/Plot_Core.h"
|
||||
#include "render_2D/scene/Scene.h"
|
||||
#include "render_2D/renderable/Renderable.h"
|
||||
|
||||
#include "adminive/adminive.hpp"
|
||||
|
||||
@@ -77,21 +77,32 @@ std::optional<double> action_number(const Gallery_Action_Request& request) {
|
||||
return std::nullopt;
|
||||
return std::get<double>(*request.argument);
|
||||
}
|
||||
Frame_Control_Mode core_frame_mode(Gallery_Frame_Mode mode) {
|
||||
const auto result = magic_enum::enum_cast<Frame_Control_Mode>(
|
||||
magic_enum::enum_name(mode));
|
||||
if (!result)
|
||||
throw std::logic_error("Gallery frame mode has no Kernel strategy");
|
||||
return *result;
|
||||
}
|
||||
} // namespace
|
||||
class Gallery_Scene final {
|
||||
class Gallery_Scene_Interface {
|
||||
public:
|
||||
Gallery_Scene(std::uint64_t session_id, std::string case_id,
|
||||
Gallery_Frame_Mode frame_mode, bool automatic_low_latency)
|
||||
: session_id_(session_id), case_id_(std::move(case_id)),
|
||||
frame_mode_(frame_mode), automatic_low_latency_(automatic_low_latency),
|
||||
plot_(core_frame_mode(frame_mode)), performance_started_(std::chrono::steady_clock::now()) {
|
||||
virtual ~Gallery_Scene_Interface() = default;
|
||||
[[nodiscard]] virtual const std::string& case_id() const noexcept = 0;
|
||||
[[nodiscard]] virtual nlohmann::json controls() const = 0;
|
||||
[[nodiscard]] virtual Gallery_Frame_Mode frame_mode() const noexcept = 0;
|
||||
virtual void reset_monitoring() = 0;
|
||||
[[nodiscard]] virtual bool can_render_automatically() const noexcept = 0;
|
||||
[[nodiscard]] virtual std::uint64_t kernel_refresh_interval_ns() const = 0;
|
||||
virtual void set_client_metrics(Gallery_Client_Performance metrics) noexcept = 0;
|
||||
[[nodiscard]] virtual adminive::Update_Result apply_patch(std::string_view target, const nlohmann::json& patch) = 0;
|
||||
virtual void resize(Size size) = 0;
|
||||
virtual void dispatch(const Event& event) = 0;
|
||||
virtual bool render_latest_frame() = 0;
|
||||
[[nodiscard]] virtual std::optional<std::string> encode_latest_pixels() = 0;
|
||||
virtual void record_pixel_response(std::chrono::steady_clock::time_point request_started, std::chrono::steady_clock::time_point encode_started, std::chrono::steady_clock::time_point encode_finished, std::size_t pixel_bytes) = 0;
|
||||
[[nodiscard]] virtual std::string action(const Gallery_Action_Request& request, bool& recognized) = 0;
|
||||
virtual void record_action_notice_if_empty(std::string_view notice) = 0;
|
||||
[[nodiscard]] virtual std::string telemetry_json() const = 0;
|
||||
};
|
||||
template <class Scene_Type>
|
||||
class Gallery_Scene final : public Gallery_Scene_Interface {
|
||||
public:
|
||||
Gallery_Scene(std::uint64_t session_id, std::string case_id, Gallery_Frame_Mode frame_mode, bool automatic_low_latency)
|
||||
: session_id_(session_id), case_id_(std::move(case_id)), frame_mode_(frame_mode), automatic_low_latency_(automatic_low_latency), performance_started_(std::chrono::steady_clock::now()) {
|
||||
plot_.init();
|
||||
plot_.set_viewport_size({560, 320});
|
||||
root_ = plot_.root_renderable();
|
||||
@@ -104,7 +115,7 @@ public:
|
||||
build_axes();
|
||||
build_primary();
|
||||
apply_layout();
|
||||
session_control_ = std::make_unique<Gallery_Session_Control>(
|
||||
session_control_ = std::make_unique<Gallery_Session_Control<Scene_Type>>(
|
||||
plot_, *primary_, feedback_policy_);
|
||||
register_controls();
|
||||
set_performance_plot_name(plot_, case_id_ + "/" + gallery_enum_id(frame_mode_));
|
||||
@@ -1236,9 +1247,9 @@ private:
|
||||
std::string case_id_;
|
||||
Gallery_Frame_Mode frame_mode_ = Gallery_Frame_Mode::Low_Latency;
|
||||
bool automatic_low_latency_{};
|
||||
Plot_Core plot_;
|
||||
Scene_Type plot_;
|
||||
Gallery_Feedback_Policy feedback_policy_;
|
||||
std::unique_ptr<Gallery_Session_Control> session_control_;
|
||||
std::unique_ptr<Gallery_Session_Control<Scene_Type>> session_control_;
|
||||
Gallery_Controls controls_;
|
||||
std::chrono::steady_clock::time_point performance_started_;
|
||||
std::chrono::steady_clock::time_point last_performance_log_;
|
||||
@@ -1280,6 +1291,17 @@ private:
|
||||
bool rendered_since_last_pixel_{};
|
||||
std::string last_action_result_;
|
||||
};
|
||||
std::unique_ptr<Gallery_Scene_Interface> make_gallery_scene(std::uint64_t session_id, std::string case_id, Gallery_Frame_Mode mode, bool automatic_low_latency) {
|
||||
switch (mode) {
|
||||
case Gallery_Frame_Mode::Manual:
|
||||
return std::make_unique<Gallery_Scene<Manual_Scene2D>>(session_id, std::move(case_id), mode, automatic_low_latency);
|
||||
case Gallery_Frame_Mode::Low_Latency:
|
||||
return std::make_unique<Gallery_Scene<Scene2D>>(session_id, std::move(case_id), mode, automatic_low_latency);
|
||||
case Gallery_Frame_Mode::Playback:
|
||||
return std::make_unique<Gallery_Scene<Playback_Scene2D>>(session_id, std::move(case_id), mode, automatic_low_latency);
|
||||
}
|
||||
throw std::invalid_argument("unknown gallery frame mode");
|
||||
}
|
||||
struct Gallery_Plot_Session::Impl {
|
||||
explicit Impl(bool enable_automatic_low_latency)
|
||||
: automatic_low_latency(enable_automatic_low_latency),
|
||||
@@ -1433,7 +1455,7 @@ struct Gallery_Plot_Session::Impl {
|
||||
},
|
||||
event);
|
||||
}
|
||||
std::unique_ptr<Gallery_Scene> scene;
|
||||
std::unique_ptr<Gallery_Scene_Interface> scene;
|
||||
std::mutex mutex;
|
||||
std::condition_variable scheduler_condition;
|
||||
std::uint64_t scheduler_revision{};
|
||||
@@ -1452,8 +1474,7 @@ struct Gallery_Plot_Session::Impl {
|
||||
Web_Response_Type::Json,
|
||||
Gallery_Protocol::error_json("未知的 gallery case 或 frame_mode", "case")
|
||||
};
|
||||
scene = std::make_unique<Gallery_Scene>(
|
||||
session_id, open->case_id, open->frame_mode, automatic_low_latency);
|
||||
scene = make_gallery_scene(session_id, open->case_id, open->frame_mode, automatic_low_latency);
|
||||
++scene_generation;
|
||||
if (scene->frame_mode() == Gallery_Frame_Mode::Low_Latency)
|
||||
ensure_render_worker();
|
||||
@@ -1538,8 +1559,7 @@ struct Gallery_Plot_Session::Impl {
|
||||
if (action->id == "reset") {
|
||||
const std::string id = scene->case_id();
|
||||
const auto mode = scene->frame_mode();
|
||||
scene = std::make_unique<Gallery_Scene>(
|
||||
session_id, id, mode, automatic_low_latency);
|
||||
scene = make_gallery_scene(session_id, id, mode, automatic_low_latency);
|
||||
++scene_generation;
|
||||
return Web_Response{
|
||||
Web_Response_Type::Json,
|
||||
|
||||
@@ -64,13 +64,38 @@ const Case_Model* find_case(std::string_view id) {
|
||||
return found == all.end() ? nullptr : &*found;
|
||||
}
|
||||
|
||||
void append_session_actions(Gallery_Frame_Mode frame_mode,
|
||||
std::vector<Action_Model>& result) {
|
||||
switch (frame_mode) {
|
||||
case Gallery_Frame_Mode::Manual:
|
||||
append_gallery_actions<Gallery_Session_Control<Manual_Scene2D>>(result);
|
||||
return;
|
||||
case Gallery_Frame_Mode::Low_Latency:
|
||||
append_gallery_actions<Gallery_Session_Control<Scene2D>>(result);
|
||||
return;
|
||||
case Gallery_Frame_Mode::Playback:
|
||||
append_gallery_actions<Gallery_Session_Control<Playback_Scene2D>>(result);
|
||||
return;
|
||||
}
|
||||
throw std::invalid_argument("unknown gallery frame mode");
|
||||
}
|
||||
std::size_t session_control_count(Gallery_Frame_Mode frame_mode) {
|
||||
switch (frame_mode) {
|
||||
case Gallery_Frame_Mode::Manual:
|
||||
return gallery_control_count<Gallery_Session_Control<Manual_Scene2D>>();
|
||||
case Gallery_Frame_Mode::Low_Latency:
|
||||
return gallery_control_count<Gallery_Session_Control<Scene2D>>();
|
||||
case Gallery_Frame_Mode::Playback:
|
||||
return gallery_control_count<Gallery_Session_Control<Playback_Scene2D>>();
|
||||
}
|
||||
throw std::invalid_argument("unknown gallery frame mode");
|
||||
}
|
||||
std::vector<Action_Model> registered_actions(std::string_view case_id,
|
||||
Gallery_Frame_Mode frame_mode) {
|
||||
std::vector<Action_Model> result;
|
||||
append_gallery_actions<Gallery_Session_Control>(result);
|
||||
for (auto& action : gallery_frame_actions(frame_mode)) {
|
||||
append_session_actions(frame_mode, result);
|
||||
for (auto& action : gallery_frame_actions(frame_mode))
|
||||
result.push_back(std::move(action));
|
||||
}
|
||||
append_gallery_renderable_actions(case_id, result);
|
||||
return result;
|
||||
}
|
||||
@@ -492,10 +517,11 @@ std::string Gallery_Protocol::catalog_json() {
|
||||
Json entry = adminive::to_frontend_json<Json>(item);
|
||||
entry["control_count_by_mode"] = Json::object();
|
||||
entry["action_count_by_mode"] = Json::object();
|
||||
const std::size_t controls = gallery_control_count<Gallery_Session_Control>() +
|
||||
gallery_renderable_control_count(item.id);
|
||||
const std::size_t renderable_controls = gallery_renderable_control_count(item.id);
|
||||
for (const auto mode : frame_modes) {
|
||||
const std::string key = gallery_enum_id(mode);
|
||||
const std::size_t controls =
|
||||
gallery_detail::session_control_count(mode) + renderable_controls;
|
||||
const std::size_t actions =
|
||||
gallery_detail::registered_actions(item.id, mode).size();
|
||||
entry["control_count_by_mode"][key] = controls;
|
||||
@@ -503,7 +529,9 @@ std::string Gallery_Protocol::catalog_json() {
|
||||
controls_total += controls;
|
||||
actions_total += actions;
|
||||
}
|
||||
entry["control_count"] = controls;
|
||||
entry["control_count"] =
|
||||
gallery_detail::session_control_count(Gallery_Frame_Mode::Low_Latency) +
|
||||
renderable_controls;
|
||||
entry["action_count"] =
|
||||
gallery_detail::registered_actions(
|
||||
item.id, Gallery_Frame_Mode::Low_Latency).size();
|
||||
|
||||
@@ -1,43 +1,32 @@
|
||||
#pragma once
|
||||
|
||||
#include "render_2D/plot/Plot_Core.h"
|
||||
#include "render_2D/plottable/Performance_Overlay.h"
|
||||
#include "render_2D/renderable/Renderable.h"
|
||||
|
||||
#include "render_2D/scene/Scene.h"
|
||||
#include <memory>
|
||||
#include <string>
|
||||
|
||||
namespace adminive {
|
||||
template <class T>
|
||||
struct Type_Descriptor;
|
||||
}
|
||||
|
||||
namespace renderive::web {
|
||||
|
||||
struct Gallery_Feedback_Policy {
|
||||
bool enabled{true};
|
||||
bool pixel{};
|
||||
bool presentation{true};
|
||||
bool manual{};
|
||||
double manual_fps{60.0};
|
||||
|
||||
friend bool operator==(const Gallery_Feedback_Policy&,
|
||||
const Gallery_Feedback_Policy&) = default;
|
||||
friend bool operator==(const Gallery_Feedback_Policy&, const Gallery_Feedback_Policy&) = default;
|
||||
};
|
||||
|
||||
template <class Scene_Type>
|
||||
class Gallery_Session_Control final {
|
||||
public:
|
||||
Gallery_Session_Control(Plot_Core& plot, Renderable& renderable,
|
||||
Gallery_Feedback_Policy& feedback) noexcept
|
||||
: plot_(plot), renderable_(renderable), feedback_(feedback) {}
|
||||
|
||||
Gallery_Session_Control(Scene_Type& scene, Renderable& renderable, Gallery_Feedback_Policy& feedback) noexcept
|
||||
: scene_(scene), renderable_(renderable), feedback_(feedback) {}
|
||||
private:
|
||||
Plot_Core& plot_;
|
||||
Scene_Type& scene_;
|
||||
Renderable& renderable_;
|
||||
Gallery_Feedback_Policy& feedback_;
|
||||
|
||||
template <class T>
|
||||
friend struct ::adminive::Type_Descriptor;
|
||||
};
|
||||
|
||||
} // namespace renderive::web
|
||||
}
|
||||
|
||||
@@ -38,28 +38,28 @@ struct Type_Descriptor<renderive::web::Gallery_Feedback_Policy> {
|
||||
}
|
||||
};
|
||||
|
||||
template <>
|
||||
struct Type_Descriptor<renderive::web::Gallery_Session_Control> {
|
||||
template <class Scene_Type>
|
||||
struct Type_Descriptor<renderive::web::Gallery_Session_Control<Scene_Type>> {
|
||||
static auto get() {
|
||||
using T = renderive::web::Gallery_Session_Control;
|
||||
using T = renderive::web::Gallery_Session_Control<Scene_Type>;
|
||||
using namespace renderive::web::gallery_adminive;
|
||||
const auto dirty = [](T& value) { value.plot_.notify_model_dirty(); };
|
||||
const auto dirty = [](T& value) { value.scene_.notify_model_dirty(); };
|
||||
return adminive::object<T>("scene", "场景",
|
||||
callback_property<T, renderive::Color>(
|
||||
"background_color", "背景颜色", Field_Control::color,
|
||||
[](const T& value) { return value.plot_.background_color(); },
|
||||
[](const T& value) { return value.scene_.background_color(); },
|
||||
[dirty](T& value, renderive::Color color) {
|
||||
value.plot_.set_background_color(color);
|
||||
value.scene_.set_background_color(color);
|
||||
dirty(value);
|
||||
}),
|
||||
callback_property<T, bool>(
|
||||
"performance_overlay", "性能叠加层", Field_Control::boolean,
|
||||
[](const T& value) {
|
||||
const auto overlay = value.plot_.performance_overlay();
|
||||
const auto overlay = value.scene_.performance_overlay();
|
||||
return overlay && overlay->enabled();
|
||||
},
|
||||
[dirty](T& value, bool enabled) {
|
||||
renderive::set_performance_overlay_enabled(value.plot_, enabled);
|
||||
renderive::set_performance_overlay_enabled(value.scene_, enabled);
|
||||
dirty(value);
|
||||
}),
|
||||
callback_property<T, bool>(
|
||||
@@ -76,8 +76,8 @@ struct Type_Descriptor<renderive::web::Gallery_Session_Control> {
|
||||
value.renderable_.set_cache_mode(mode);
|
||||
dirty(value);
|
||||
})
|
||||
.enum_label<renderive::Renderable_Cache_Mode::Direct>("直接绘制")
|
||||
.enum_label<renderive::Renderable_Cache_Mode::Local_Pixel>("本地像素缓存"),
|
||||
.template enum_label<renderive::Renderable_Cache_Mode::Direct>("直接绘制")
|
||||
.template enum_label<renderive::Renderable_Cache_Mode::Local_Pixel>("本地像素缓存"),
|
||||
callback_property<T, std::string>(
|
||||
"object_name", "对象名称", Field_Control::text,
|
||||
[](const T& value) { return value.renderable_.object_name(); },
|
||||
@@ -87,25 +87,25 @@ struct Type_Descriptor<renderive::web::Gallery_Session_Control> {
|
||||
}),
|
||||
callback_property<T, bool>(
|
||||
"frequency_limit_enabled", "启用帧率限制", Field_Control::boolean,
|
||||
[](const T& value) { return value.plot_.max_render_fps() > 0.0; },
|
||||
[](const T& value) { return value.scene_.max_render_fps() > 0.0; },
|
||||
[dirty](T& value, bool enabled) {
|
||||
if (enabled) {
|
||||
if (value.plot_.max_render_fps() <= 0.0)
|
||||
value.plot_.set_max_render_fps(30.0);
|
||||
if (value.scene_.max_render_fps() <= 0.0)
|
||||
value.scene_.set_max_render_fps(30.0);
|
||||
} else {
|
||||
value.plot_.clear_max_render_fps();
|
||||
value.scene_.clear_max_render_fps();
|
||||
}
|
||||
dirty(value);
|
||||
}),
|
||||
callback_property<T, double>(
|
||||
"max_render_fps", "最大渲染帧率", Field_Control::number,
|
||||
[](const T& value) {
|
||||
const double fps = value.plot_.max_render_fps();
|
||||
const double fps = value.scene_.max_render_fps();
|
||||
return fps > 0.0 ? fps : 30.0;
|
||||
},
|
||||
[dirty](T& value, double fps) {
|
||||
if (value.plot_.max_render_fps() > 0.0)
|
||||
value.plot_.set_max_render_fps(fps);
|
||||
if (value.scene_.max_render_fps() > 0.0)
|
||||
value.scene_.set_max_render_fps(fps);
|
||||
dirty(value);
|
||||
}),
|
||||
callback_property<T, renderive::web::Gallery_Feedback_Policy>(
|
||||
@@ -118,22 +118,20 @@ struct Type_Descriptor<renderive::web::Gallery_Session_Control> {
|
||||
}
|
||||
};
|
||||
|
||||
static_assert(Described_Type<renderive::web::Gallery_Session_Control>);
|
||||
static_assert(Direct_Described_Object<renderive::web::Gallery_Session_Control>);
|
||||
|
||||
} // namespace adminive
|
||||
|
||||
namespace structive {
|
||||
|
||||
template <>
|
||||
struct Type_Descriptor<renderive::web::Gallery_Session_Control> {
|
||||
template <class Scene_Type>
|
||||
struct Type_Descriptor<renderive::web::Gallery_Session_Control<Scene_Type>> {
|
||||
static auto get() {
|
||||
using T = renderive::web::Gallery_Session_Control;
|
||||
using T = renderive::web::Gallery_Session_Control<Scene_Type>;
|
||||
using renderive::web::gallery_action;
|
||||
return object<T>(type_metadata(
|
||||
gallery_action("reset", "恢复本图默认值", "Gallery_Scene::rebuild", "场景"),
|
||||
gallery_action("toggle_view", "切换 View 生命周期",
|
||||
"Plot_Core::activate_view / deactivate_view", "场景"),
|
||||
"Basic_Scene2D::activate_view / deactivate_view", "场景"),
|
||||
gallery_action("capture_next_frame", "Capture next frame",
|
||||
"Scene_Base::capture_next_frame", "Performance Capture",
|
||||
"Capture the next completed render frame", {}, {}, 0.0, true),
|
||||
|
||||
@@ -49,7 +49,7 @@ double gaussian(double x, double center, double width) {
|
||||
}
|
||||
} // namespace
|
||||
struct Web_Plot_Session::Impl {
|
||||
Plot_Core plot;
|
||||
Scene2D plot;
|
||||
std::shared_ptr<Frequency_Axis> spectrum_frequency_axis;
|
||||
std::shared_ptr<Axis> spectrum_power_axis;
|
||||
std::shared_ptr<Frequency_Axis> waterfall_frequency_axis;
|
||||
|
||||
Reference in New Issue
Block a user