更新三缓冲 彻底
This commit is contained in:
@@ -291,7 +291,9 @@ nlohmann::json generate_2d_data(Object& object, const Json& input) {
|
||||
std::vector<Frequency_Trace_Sample> samples(count);
|
||||
for (std::size_t index = 0; index < count; ++index)
|
||||
samples[index] = {static_cast<Plot_Time_Tick>(index * tick_step), distribution(engine)};
|
||||
for (const auto& sample : samples) object.append_sample(sample.tick, sample.value);
|
||||
for (const auto& sample : samples)
|
||||
object.template submit_stream<Frequency_Trace_Stream_Tag>(sample);
|
||||
object.template mark_dirty<Prepare_Data_Tag>();
|
||||
generated_count = count;
|
||||
} else if constexpr (std::same_as<Definition, Sweep_Spectrum>) {
|
||||
const auto block_count = generator_count(input, "block_count", 65'536);
|
||||
@@ -305,7 +307,10 @@ nlohmann::json generate_2d_data(Object& object, const Json& input) {
|
||||
std::ranges::copy_n(complete.begin() + block * width, width, blocks[block].begin());
|
||||
object.template set<&Sweep_Spectrum::Prop::bins_per_block>(width);
|
||||
object.template set<&Sweep_Spectrum::Prop::block_count>(block_count);
|
||||
for (auto& block : blocks) object.append_block(block);
|
||||
for (auto& block : blocks)
|
||||
object.template submit_stream<Sweep_Spectrum_Stream_Tag>(
|
||||
std::make_shared<const std::vector<Plot_Value>>(std::move(block)));
|
||||
object.template mark_dirty<Prepare_Data_Tag>();
|
||||
generated_count = block_count * width;
|
||||
} else if constexpr (std::same_as<Definition, Afterglow>) {
|
||||
const auto row_count = generator_count(input, "history_count", 4096);
|
||||
@@ -317,7 +322,10 @@ nlohmann::json generate_2d_data(Object& object, const Json& input) {
|
||||
const auto noise_stddev = generator_number(input, "noise_stddev");
|
||||
for (std::size_t row = 0; row < row_count; ++row)
|
||||
generate_spectral_row(spectra[row], row, signal_count, minimum, maximum, noise_stddev, engine);
|
||||
for (auto& spectrum : spectra) object.append_spectrum(spectrum);
|
||||
for (auto& spectrum : spectra)
|
||||
object.template submit_stream<Afterglow_Stream_Tag>(
|
||||
std::make_shared<const std::vector<Plot_Value>>(std::move(spectrum)));
|
||||
object.template mark_dirty<Prepare_Data_Tag>();
|
||||
generated_count = row_count * width;
|
||||
} else if constexpr (std::same_as<Definition, Waterfall>) {
|
||||
const auto row_count = generator_count(input, "row_count", 4096);
|
||||
@@ -334,7 +342,10 @@ nlohmann::json generate_2d_data(Object& object, const Json& input) {
|
||||
rows.push_back({static_cast<Plot_Time_Tick>(row), std::move(row_values)});
|
||||
}
|
||||
object.template set<&Waterfall::Prop::frequency_bin_count>(width);
|
||||
for (auto& row : rows) object.append_row(row.tick, row.values);
|
||||
for (auto& row : rows)
|
||||
object.template submit_stream<Waterfall_Stream_Tag>(
|
||||
std::make_shared<const Waterfall_Row>(std::move(row)));
|
||||
object.template mark_dirty<Prepare_Data_Tag>();
|
||||
generated_count = row_count * width;
|
||||
} else if constexpr (std::same_as<Definition, Constellation_Diagram>) {
|
||||
const auto count = generator_count(input, "point_count");
|
||||
@@ -345,7 +356,9 @@ nlohmann::json generate_2d_data(Object& object, const Json& input) {
|
||||
const auto submitted = monotonic_milliseconds();
|
||||
for (std::size_t index = 0; index < count; ++index)
|
||||
points[index] = {{i_distribution(engine), q_distribution(engine)}, submitted};
|
||||
for (const auto& point : points) object.append_point(point.point);
|
||||
for (const auto& point : points)
|
||||
object.template submit_stream<Constellation_Stream_Tag>(point);
|
||||
object.template mark_dirty<Prepare_Data_Tag>();
|
||||
generated_count = count;
|
||||
} else if constexpr (std::same_as<Definition, Selection_Rectangle_Overlay>) {
|
||||
const auto count = generator_count(input, "region_count");
|
||||
@@ -614,16 +627,15 @@ std::shared_ptr<Plot> make_frequency_trace_plot(asio::any_io_executor executor)
|
||||
static_cast<std::int64_t>(
|
||||
std::fmod(std::max(0.0, event.time_milliseconds), day_milliseconds))
|
||||
});
|
||||
raw->append_sample(tick,
|
||||
std::sin(event.time_milliseconds * 0.0025) * 0.8
|
||||
+ std::sin(event.time_milliseconds * 0.0007) * 0.2);
|
||||
raw->template submit_stream<Frequency_Trace_Stream_Tag>(Frequency_Trace_Sample{
|
||||
tick, std::sin(event.time_milliseconds * 0.0025) * 0.8
|
||||
+ std::sin(event.time_milliseconds * 0.0007) * 0.2});
|
||||
raw->template mark_dirty<Prepare_Data_Tag>();
|
||||
};
|
||||
auto view = make_scene_view<
|
||||
Prop_Field<&Frequency_Trace::Prop::partition_count, "partition_count", "Number of partitions used to prepare the time-ordered trace.">,
|
||||
Prop_Field<&Frequency_Trace::Prop::pen, "pen", "Stroke style used to draw the frequency trace.">,
|
||||
Prop_Field<&Frequency_Trace::Prop::partition_mode, "partition_mode", "Selects how trace samples are divided between preparation tasks.">,
|
||||
State_Field<Frequency_Trace, &Frequency_Trace::State::sample_count, "sample_count", "Number of samples retained by the current trace.">,
|
||||
State_Field<Frequency_Trace, &Frequency_Trace::State::rendered_point_count, "rendered_point_count", "Number of points emitted for the latest trace frame.">>(
|
||||
Prop_Field<&Frequency_Trace::Prop::partition_mode, "partition_mode", "Selects how trace samples are divided between preparation tasks.">>(
|
||||
*trace, *scene, std::move(update), std::move(time), std::move(vertical), std::move(trace), std::move(selection));
|
||||
return std::make_shared<Plot>(std::move(executor), std::move(scene), std::move(view));
|
||||
}
|
||||
@@ -658,7 +670,9 @@ std::shared_ptr<Plot> make_sweep_spectrum_plot(asio::any_io_executor executor) {
|
||||
const auto sweep_index = block_index * values.size() + i;
|
||||
values[i] = -90.0 + 35.0 * std::sin(sweep_index * 0.08 + event.time_milliseconds * 0.002);
|
||||
}
|
||||
raw->append_block(values);
|
||||
raw->template submit_stream<Sweep_Spectrum_Stream_Tag>(
|
||||
std::make_shared<const std::vector<Plot_Value>>(std::move(values)));
|
||||
raw->template mark_dirty<Prepare_Data_Tag>();
|
||||
};
|
||||
auto view = make_scene_view<
|
||||
Prop_Field<&Sweep_Spectrum::Prop::bins_per_block, "bins_per_block", "Number of frequency bins stored in each incoming sweep block.">,
|
||||
@@ -669,10 +683,7 @@ std::shared_ptr<Plot> make_sweep_spectrum_plot(asio::any_io_executor executor) {
|
||||
Prop_Field<&Sweep_Spectrum::Prop::partition_mode, "partition_mode", "Selects how sweep blocks are divided between preparation tasks.">,
|
||||
Prop_Field<&Sweep_Spectrum::Prop::pen, "pen", "Stroke style used for the completed sweep curve.">,
|
||||
Prop_Field<&Sweep_Spectrum::Prop::current_frequency_pen, "current_frequency_pen", "Stroke style used for the current sweep-frequency indicator.">,
|
||||
Prop_Field<&Sweep_Spectrum::Prop::interpolation_mode, "interpolation_mode", "Selects interpolation between adjacent sweep bins.">,
|
||||
State_Field<Sweep_Spectrum, &Sweep_Spectrum::State::stored_block_count, "stored_block_count", "Number of frequency segments that currently contain data.">,
|
||||
State_Field<Sweep_Spectrum, &Sweep_Spectrum::State::stored_point_count, "stored_point_count", "Total number of points retained by the single composite sweep curve.">,
|
||||
State_Field<Sweep_Spectrum, &Sweep_Spectrum::State::rendered_point_count, "rendered_point_count", "Number of points emitted for the single composite sweep curve.">>(
|
||||
Prop_Field<&Sweep_Spectrum::Prop::interpolation_mode, "interpolation_mode", "Selects interpolation between adjacent sweep bins.">>(
|
||||
*sweep, *scene, std::move(update), std::move(frequency), std::move(vertical), std::move(sweep), std::move(selection));
|
||||
return std::make_shared<Plot>(std::move(executor), std::move(scene), std::move(view));
|
||||
}
|
||||
@@ -703,7 +714,9 @@ std::shared_ptr<Plot> make_afterglow_plot(asio::any_io_executor executor) {
|
||||
values[i] = -95.0 + 62.0 * std::exp(-220.0 * std::pow(
|
||||
static_cast<double>(i) / values.size() - 0.5
|
||||
- 0.18 * std::sin(event.time_milliseconds * 0.0008), 2.0));
|
||||
raw->append_spectrum(values);
|
||||
raw->template submit_stream<Afterglow_Stream_Tag>(
|
||||
std::make_shared<const std::vector<Plot_Value>>(values.begin(), values.end()));
|
||||
raw->template mark_dirty<Prepare_Data_Tag>();
|
||||
};
|
||||
auto view = make_scene_view<
|
||||
Prop_Field<&Afterglow::Prop::frequency_point_size, "frequency_point_size", "Number of frequency cells allocated across each afterglow row.">,
|
||||
@@ -714,10 +727,7 @@ std::shared_ptr<Plot> make_afterglow_plot(asio::any_io_executor executor) {
|
||||
Prop_Field<&Afterglow::Prop::frequency_range, "frequency_range", "Maps input samples onto the afterglow frequency axis.">,
|
||||
Prop_Field<&Afterglow::Prop::power_range, "power_range", "Defines the minimum and maximum power represented by the color grid.">,
|
||||
Prop_Field<&Afterglow::Prop::partition_mode, "partition_mode", "Selects how afterglow cells are divided between preparation tasks.">,
|
||||
Prop_Field<&Afterglow::Prop::color_map, "color_map", "Maps accumulated energy values to rendered colors.">,
|
||||
State_Field<Afterglow, &Afterglow::State::history_count, "history_count", "Number of spectrum frames retained in afterglow history.">,
|
||||
State_Field<Afterglow, &Afterglow::State::latest_spectrum_point_count, "latest_spectrum_point_count", "Number of samples in the most recently appended spectrum.">,
|
||||
State_Field<Afterglow, &Afterglow::State::rendered_cell_count, "rendered_cell_count", "Number of colored cells emitted for the latest frame.">>(
|
||||
Prop_Field<&Afterglow::Prop::color_map, "color_map", "Maps accumulated energy values to rendered colors.">>(
|
||||
*afterglow, *scene, std::move(update), std::move(frequency), std::move(vertical), std::move(afterglow), std::move(selection));
|
||||
return std::make_shared<Plot>(std::move(executor), std::move(scene), std::move(view));
|
||||
}
|
||||
@@ -752,7 +762,10 @@ std::shared_ptr<Plot> make_waterfall_plot(asio::any_io_executor executor) {
|
||||
static_cast<std::int64_t>(
|
||||
std::fmod(std::max(0.0, event.time_milliseconds), day_milliseconds))
|
||||
});
|
||||
raw->append_row(tick, values);
|
||||
raw->template submit_stream<Waterfall_Stream_Tag>(
|
||||
std::make_shared<const Waterfall_Row>(Waterfall_Row{
|
||||
tick, {values.begin(), values.end()}}));
|
||||
raw->template mark_dirty<Prepare_Data_Tag>();
|
||||
};
|
||||
auto view = make_scene_view<
|
||||
Prop_Field<&Waterfall::Prop::tooltip_enabled, "tooltip_enabled", "Enables value inspection tooltips over waterfall cells.">,
|
||||
@@ -766,10 +779,7 @@ std::shared_ptr<Plot> make_waterfall_plot(asio::any_io_executor executor) {
|
||||
Prop_Field<&Waterfall::Prop::power_range, "power_range", "Defines the power interval mapped through the waterfall color map.">,
|
||||
Prop_Field<&Waterfall::Prop::partition_mode, "partition_mode", "Selects how waterfall rows are divided between preparation tasks.">,
|
||||
Prop_Field<&Waterfall::Prop::interpolation_mode, "interpolation_mode", "Selects interpolation when samples are mapped to raster cells.">,
|
||||
Prop_Field<&Waterfall::Prop::color_map, "color_map", "Maps sample power values to waterfall colors.">,
|
||||
State_Field<Waterfall, &Waterfall::State::row_count, "row_count", "Number of waterfall rows currently retained.">,
|
||||
State_Field<Waterfall, &Waterfall::State::stored_point_count, "stored_point_count", "Total number of spectrum points retained across all rows.">,
|
||||
State_Field<Waterfall, &Waterfall::State::rendered_cell_count, "rendered_cell_count", "Number of raster cells emitted for the latest frame.">>(
|
||||
Prop_Field<&Waterfall::Prop::color_map, "color_map", "Maps sample power values to waterfall colors.">>(
|
||||
*waterfall, *scene, std::move(update), std::move(frequency), std::move(time), std::move(waterfall), std::move(selection));
|
||||
return std::make_shared<Plot>(std::move(executor), std::move(scene), std::move(view));
|
||||
}
|
||||
@@ -806,11 +816,12 @@ std::shared_ptr<Plot> make_constellation_plot(asio::any_io_executor executor) {
|
||||
+ 0.012 * std::cos(phase * 23.0 + index * 0.61);
|
||||
const double noise_q = 0.025 * std::cos(phase * 13.0 + index * 1.37)
|
||||
+ 0.012 * std::sin(phase * 19.0 + index * 0.47);
|
||||
raw->append_point({
|
||||
raw->template submit_stream<Constellation_Stream_Tag>(Constellation_Point{{
|
||||
state.i_range.center() + std::cos(angle) * radius + noise_i,
|
||||
state.q_range.center() + std::sin(angle) * radius + noise_q
|
||||
});
|
||||
}, monotonic_milliseconds()});
|
||||
}
|
||||
raw->template mark_dirty<Prepare_Data_Tag>();
|
||||
};
|
||||
auto view = make_scene_view<
|
||||
Prop_Field<&Constellation_Diagram::Prop::point_lifetime_ms, "point_lifetime_ms", "Time in milliseconds that an appended constellation point remains visible.">,
|
||||
@@ -819,8 +830,7 @@ std::shared_ptr<Plot> make_constellation_plot(asio::any_io_executor executor) {
|
||||
Prop_Field<&Constellation_Diagram::Prop::i_range, "i_range", "Defines the horizontal in-phase coordinate interval.">,
|
||||
Prop_Field<&Constellation_Diagram::Prop::q_range, "q_range", "Defines the vertical quadrature coordinate interval.">,
|
||||
Prop_Field<&Constellation_Diagram::Prop::point_color, "point_color", "Color used to render received I/Q samples.">,
|
||||
Prop_Field<&Constellation_Diagram::Prop::anchor_color, "anchor_color", "Color used to render ideal modulation anchors.">,
|
||||
State_Field<Constellation_Diagram, &Constellation_Diagram::State::point_count, "point_count", "Number of constellation samples currently retained.">>(
|
||||
Prop_Field<&Constellation_Diagram::Prop::anchor_color, "anchor_color", "Color used to render ideal modulation anchors.">>(
|
||||
*constellation, *scene, std::move(update), std::move(horizontal), std::move(vertical), std::move(constellation), std::move(selection));
|
||||
return std::make_shared<Plot>(std::move(executor), std::move(scene), std::move(view));
|
||||
}
|
||||
|
||||
+12
-2
@@ -242,7 +242,9 @@ void dispatch_plot_input(Scene_Object& scene, const Plot_Input_Event& input,
|
||||
Plot::Input_Handler handler) {
|
||||
Web_Input_Metadata metadata{input, std::move(handler),
|
||||
std::chrono::steady_clock::now()};
|
||||
const auto dispatch = [&](auto event) { scene.dispatch_event(std::move(event)); };
|
||||
const auto dispatch = [&](auto event) {
|
||||
scene.template submit_stream<aethera::Scene_Event_Stream_Tag>(std::move(event));
|
||||
};
|
||||
const auto apply_pointer = [&](auto& event) {
|
||||
event.position = input.position;
|
||||
event.global_position = input.global_position;
|
||||
@@ -539,7 +541,15 @@ void Plot::Private::render_frame(Plot_Render_Tick tick) {
|
||||
|
||||
void Plot::Private::complete_event_reports(Frame_Identity rendered_identity) {
|
||||
aethera::Scene::Event_Report_Batch reports = std::visit(
|
||||
[](auto& value) { return value->take_event_reports(); }, scene);
|
||||
[](auto& value) {
|
||||
return value->template access_query_stream<aethera::Scene_Event_Stream_Tag>(
|
||||
[&](std::span<const aethera::Scene::Event_Pointer> events) {
|
||||
aethera::Scene::Event_Report_Batch result{value->memory_resource()};
|
||||
result.reserve(events.size());
|
||||
for (const auto& event : events) result.push_back(event);
|
||||
return result;
|
||||
});
|
||||
}, scene);
|
||||
pending_event_reports.insert(pending_event_reports.end(),
|
||||
std::make_move_iterator(reports.begin()),
|
||||
std::make_move_iterator(reports.end()));
|
||||
|
||||
Reference in New Issue
Block a user