Pulp 1.88.0
Cross-platform audio plugin framework
Loading...
Searching...
No Matches
motion.hpp
Go to the documentation of this file.
1#pragma once
2
10
12
13#include <cstdint>
14#include <functional>
15#include <memory>
16#include <string>
17#include <utility>
18#include <vector>
19
20namespace pulp::view {
21
22class FrameClock;
23class ScrollView;
24class View;
25
26namespace motion {
27
28// ── Geometry taxonomy ────────────────────────────────────────────────
29
34
41
47
48// ── Scroll taxonomy ──────────────────────────────────────────────────
49//
50// Properties readable from a `pulp::view::ScrollView` — content offset,
51// visible (viewport) rect, content size, content insets, and the max
52// scrollable extent on each axis. ScrollView does not currently expose
53// per-edge content insets; the four Inset* properties always report 0.0
54// and remain on the enum so callers can wire them once insets land
55// without breaking the API surface.
63
64// ── Trace options ────────────────────────────────────────────────────
65
67 int fps = 15;
68};
69
70// ── Provenance envelope ───────────────────────────────────────────────
71//
72// Opaque metadata describing *where* a trace came from. Carried on
73// TraceStarted (trace-level) and on burst Start events (burst-level).
74// Animation surfaces (Tween / CSS / AnimatorSet / JS rAF / design-import)
75// can fill this envelope to make offline traces explainable.
76
77struct Provenance {
78 std::string source_kind;
80 std::string source_id;
82 std::string source_file;
83 int source_line = 0;
84
85 bool is_set() const noexcept {
86 return !source_kind.empty() || !source_id.empty() ||
87 !source_file.empty() || source_line != 0;
88 }
89};
90
91// ── Sample event ─────────────────────────────────────────────────────
92//
93// Per-tick or per-publish event in a motion stream. Schema v2 carries
94// stable identifiers (trace_id / metric_id / burst_id) so fixtures can
95// be compared by identity instead of position — reordered identical
96// bursts no longer false-fail an `assert_matches`.
97
113
115 std::string view_name;
116 std::string metric_name;
117 double t_seconds = 0.0;
118 std::uint64_t frame = 0;
119 int precision = 3;
120
121 // Stable identifiers (schema v2). Sampler-driven traces get a
122 // positive `trace_id` from `register_trace`; publishes use 0 to
123 // signal the publish channel. `metric_id` is the metric's index
124 // within its trace (or 0 for publish). `burst_id` increments at
125 // each Start within a given (trace_id, metric_id).
126 int trace_id = 0;
127 int metric_id = 0;
128 int burst_id = 0;
129
131
132 std::vector<std::pair<std::string, double>> components;
133 std::vector<std::pair<std::string, double>> deltas;
134
135 // ── Input fields (populated only when `kind == Input`) ───────────
136 //
137 // `input_kind` is one of `"click"`, `"drag"`, `"hover"`. `view_id`
138 // is the recorded target's `View::id()` (empty when the recorder
139 // captured an event that didn't land on an id-bearing view). The
140 // Root-space coordinates ride on `components`. Click and drag also
141 // carry `button`, `modifiers`, `pointer_id`, `pointer_type`, and
142 // `pressure`; hover remains coordinate-only:
143 // - click: `{ "button": ..., "modifiers": ..., "pointer_id": ...,
144 // "pointer_type": ..., "pressure": ..., "x": ..., "y": ... }`
145 // - drag : `{ "button": ..., "end_x": ..., "end_y": ...,
146 // "modifiers": ..., "pointer_id": ..., "pointer_type": ...,
147 // "pressure": ..., "start_x": ..., "start_y": ...,
148 // "steps": ... }`
149 // - hover: `{ "x": ..., "y": ... }`
150 // (Sorted by name, same as every other event.) The optional name
151 // ride along with `view_name` set to "input" by convention so
152 // `format_line` and existing groupers don't trip on an empty view.
153 std::string input_kind;
154 std::string view_id;
155};
156
158std::string format_line(const SampleEvent& e);
159
160// ── Publish channel ──────────────────────────────────────────────────
161//
162// `publish_value()` is the entry point for any code that wants to make
163// its scalar / structured values observable without taking a
164// FrameClock sampler subscription. Typical callers are animation
165// primitives — a `Tween`, a CSS `TransitionSpec`, a JS rAF callback —
166// that already advance once per frame; calling publish at the same
167// tick site avoids the doubled-sampling cost.
168//
169// Routing:
170// - When `Coordinator::tracing_enabled()` is false, publish is a
171// no-op (cheap, branch-predictable; safe to leave in hot paths).
172// - When `Coordinator::firehose()` is true, the published value fans
173// out as a Sample event to every installed sink, with the same
174// epsilon / Start/End burst semantics as sampler-driven traces.
175// - When `firehose()` is false and no subscription is wired, publish
176// is also a no-op.
177//
178// The publish channel is the underlying primitive for trace subscribers
179// and firehose-style diagnostics.
180
182 int precision = 3;
183 double epsilon = 0.0001;
189};
190
192void publish_value(std::string view_name,
193 std::string metric_name,
194 double value,
195 PublishOptions opts = {});
196
199void publish_components(std::string view_name,
200 std::string metric_name,
201 std::vector<std::pair<std::string, double>> components,
202 PublishOptions opts = {});
203
204// ── Ambient provenance ───────────────────────────────────────────────
205//
206// Some animation surfaces (JS rAF, design-import codegen) don't easily
207// thread a `PublishOptions{ .provenance = ... }` through every call site.
208// For those, the publish channel offers a process-wide "ambient"
209// provenance slot — `set_ambient_provenance(p)` is sticky until cleared
210// (or replaced). When a publish call carries an empty `opts.provenance`,
211// the coordinator stamps the ambient provenance instead. When both are
212// set, the explicit `opts.provenance` wins.
213//
214// Ambient state is intended for single-threaded scripted contexts (one
215// JS engine per bridge). Tests should call `clear_ambient_provenance()`
216// between scenarios so leftover state doesn't bleed across.
220
221// ── Record / replay fixtures ─────────────────────────────────────────
222//
223// A fixture is the on-disk form of a motion stream — one JSONL event
224// per line, preceded by a header line carrying the schema version. The
225// format is deliberately stable so checked-in goldens survive long
226// after the recording session.
227//
228// Layered intent:
229// - `make_fixture_sink(path)` is a Sink that writes events to disk
230// as they're emitted. Plug it into the Coordinator's sink set to
231// record everything an active trace produces.
232// - `replay_fixture(path, sink)` re-emits a fixture's events to any
233// sink without running the original UI. Lets analyzers /
234// assertions work offline on a captured run.
235// - `assert_matches(golden, captured, opts)` compares two fixtures
236// and returns a structured diff agents can act on.
237//
238// Fixture schema v2 header:
239// {"motion_fixture_version":2,
240// "policy":"full|reduced|off",
241// "duration_scale":1.0}
242//
243// `policy` / `duration_scale` are optional. When absent, the loader
244// defaults `policy` to `"full"` and `duration_scale` to `1.0` —
245// earlier v2 fixtures still load. When `make_fixture_sink` writes a fresh
246// fixture it snapshots `MotionPreferences::current()` /
247// `current_duration_scale()` at first event.
248
249constexpr int kFixtureSchemaVersion = 2;
255
262 std::string policy = "full";
264 double duration_scale = 1.0;
265};
266
267// (`make_fixture_sink` and `replay_fixture` are declared below
268// alongside the other Sink helpers so the `using Sink = …` typedef is
269// visible at their declaration site.)
270
273std::vector<SampleEvent> load_fixture(const std::string& path);
274
278
282 struct Item {
283 std::string kind;
285 std::string view_name;
286 std::string metric_name;
287 std::string component_name;
288 std::string detail;
289 double observed = 0.0;
290 double expected = 0.0;
291 };
292 std::vector<Item> differences;
293 bool matches() const noexcept { return differences.empty(); }
294};
295
308
309FixtureDiff assert_matches(const std::vector<SampleEvent>& golden,
310 const std::vector<SampleEvent>& captured,
311 FixtureMatchOptions opts = {});
312
318 const std::vector<SampleEvent>& golden,
319 const FixtureHeader& captured_header,
320 const std::vector<SampleEvent>& captured,
321 FixtureMatchOptions opts = {});
322
323// ── Assertion helpers ────────────────────────────────────────────────
324//
325// Each helper operates on a flat sequence of scalars extracted from
326// the captured events. Use `extract_scalar(events, view, metric, comp)`
327// to pull the time-ordered series, then pass it to the assertion.
328// Helpers favor explicit semantics over heuristics — `is_monotonic` is
329// strictly monotonic (with epsilon), `settling_time_seconds` is "time
330// from first change to final stable value", etc.
331
335struct ScalarSample { double t = 0.0; double value = 0.0; };
336std::vector<ScalarSample> extract_scalar(
337 const std::vector<SampleEvent>& events,
338 std::string_view view_name,
339 std::string_view metric_name,
340 std::string_view component_name = "value");
341
345bool is_monotonic(const std::vector<ScalarSample>& samples,
346 double epsilon = 1e-6);
347
350double settling_time_seconds(const std::vector<ScalarSample>& samples,
351 double epsilon = 1e-6);
352
356double overshoot(const std::vector<ScalarSample>& samples,
357 double epsilon = 1e-6);
358
360double start_delay_seconds(const std::vector<ScalarSample>& samples,
361 double epsilon = 1e-6);
362
365double frame_jitter_seconds(const std::vector<ScalarSample>& samples);
366
368double final_value(const std::vector<ScalarSample>& samples);
369
383 const std::vector<ScalarSample>& samples,
384 std::size_t window_radius = 3,
385 double epsilon = 1e-9);
386
387// ── Sinks ────────────────────────────────────────────────────────────
388
389using Sink = std::function<void(const SampleEvent&)>;
390
393
396Sink make_buffer_sink(std::vector<SampleEvent>* buffer);
397
403
406int replay_fixture(const std::string& path, const Sink& sink);
407
408// ── Input recording / replay ─────────────────────────────────────────
409//
410// `View::simulate_click` / `simulate_drag` / `simulate_hover` can feed the same
411// fixture stream that carries motion samples. Recording is opt-in: nothing
412// changes about simulate_* until a caller installs a recorder, after which every
413// simulate_* dispatch emits an `Input` `SampleEvent` to the Coordinator's sinks
414// (so the already-installed `make_fixture_sink(path)` captures inputs alongside
415// samples). Replay reads the fixture, walks the view tree by `id()` to reattach
416// each input to a live target, and re-invokes the matching `View::simulate_*`.
417// The motion fixture that emerges from the replay — when paired with the same
418// animation primitives — matches the originally-recorded one.
419//
420// Layered intent:
421// - `make_input_recorder(path)` is a one-call companion to
422// `make_fixture_sink(path)`: it installs a fixture sink AND turns
423// on simulate_* recording, returning a handle whose destructor
424// turns recording back off. Off by default everywhere else.
425// - `replay_inputs(path, root_view, frame_clock)` reads the fixture
426// and re-dispatches each `Input` event by `view_id` against
427// `root_view`. The `frame_clock` is advanced between inputs to
428// reproduce the original timing (FrameClock-relative).
429
433public:
434 InputRecorder() noexcept = default;
436 InputRecorder& operator=(InputRecorder&&) noexcept;
437 InputRecorder(const InputRecorder&) = delete;
438 InputRecorder& operator=(const InputRecorder&) = delete;
440
442 void stop();
443
444 bool is_recording() const noexcept { return sink_id_ != 0; }
445
446private:
448 explicit InputRecorder(int sink_id) noexcept : sink_id_(sink_id) {}
449 int sink_id_ = 0;
450};
451
457
467int replay_inputs(const std::string& path,
468 View& root_view,
469 FrameClock& frame_clock);
470
475void record_simulated_input(const std::string& input_kind,
476 const std::string& view_id,
477 std::vector<std::pair<std::string, double>> coords);
478
483
484// ── Forward declarations ─────────────────────────────────────────────
485
486class Coordinator;
487class TraceBuilder;
488
489// ── Trace handle (RAII) ──────────────────────────────────────────────
490
492public:
493 TraceHandle() noexcept = default;
494 TraceHandle(TraceHandle&& other) noexcept;
495 TraceHandle& operator=(TraceHandle&& other) noexcept;
496 TraceHandle(const TraceHandle&) = delete;
497 TraceHandle& operator=(const TraceHandle&) = delete;
499
501 void detach();
502
503 bool is_attached() const noexcept { return coord_ != nullptr; }
504 int id() const noexcept { return id_; }
505
506private:
507 friend class Coordinator;
508 friend class TraceBuilder;
509 TraceHandle(int id, Coordinator* coord) noexcept
510 : id_(id), coord_(coord) {}
511
512 int id_ = 0;
513 Coordinator* coord_ = nullptr;
514};
515
516// ── Trace builder DSL ────────────────────────────────────────────────
517
518class TraceBuilder {
519public:
520 using ValueSampler = std::function<double()>;
521 using Component = std::pair<std::string, ValueSampler>;
522
524 TraceBuilder& value(std::string name, ValueSampler sampler,
525 int precision = 3, double epsilon = 0.0001);
526
529 TraceBuilder& multi(std::string name, std::vector<Component> components,
530 int precision = 3, double epsilon = 0.0001);
531
534 TraceBuilder& geometry(std::string name,
535 pulp::view::View& target,
536 std::vector<GeometryProperty> props
541 int precision = 2, double epsilon = 0.1);
542
550 TraceBuilder& scroll_geometry(
551 std::string name,
553 std::vector<ScrollProperty> props = {
556 },
557 int precision = 2, double epsilon = 0.1);
558
562
565
569 struct Spec;
570
571private:
572 friend class Coordinator;
573 TraceBuilder(Coordinator* coord, std::string view_name, TraceOptions opts);
574
575 std::shared_ptr<Spec> spec_;
576 Coordinator* coord_ = nullptr;
577};
578
579// ── Coordinator ──────────────────────────────────────────────────────
580
585class Coordinator {
586public:
588 static Coordinator& instance();
589
593
595 void unbind();
596
597 bool is_bound() const noexcept;
598
600 int add_sink(Sink sink);
601 void remove_sink(int sink_id);
603
606
609 bool tracing_enabled() const noexcept;
610
613 void set_firehose(bool on);
614 bool firehose() const noexcept;
615
617 TraceBuilder trace(std::string view_name, TraceOptions opts = {});
618
620 void detach(int trace_id);
621
623 void reset();
624
625 std::size_t active_trace_count() const noexcept;
626
628 std::size_t emitted_event_count() const noexcept;
629
630 // ── Publish-channel internals ─────────────────────────────────────
635 void publish_internal(std::string view_name,
636 std::string metric_name,
637 std::vector<std::pair<std::string, double>> components,
638 PublishOptions opts);
639
640 // ── Ambient provenance internals ──────────────────────────────────
645
646 // ── Input recording dispatch ──────────────────────────────────────
650
651private:
652 Coordinator();
653 ~Coordinator();
654 Coordinator(const Coordinator&) = delete;
655 Coordinator& operator=(const Coordinator&) = delete;
656
657 void on_tick(float dt);
658 int register_trace(std::shared_ptr<TraceBuilder::Spec> spec);
659 friend class TraceBuilder;
660
661 struct State;
662 std::unique_ptr<State> state_;
663};
664
665} // namespace motion
666} // namespace pulp::view
Definition frame_clock.hpp:14
Scrollable container that clips and scrolls its content.
Definition ui_components.hpp:494
Definition view.hpp:73
Process-wide singleton that owns one FrameClock subscription, holds the active trace set,...
Definition motion.hpp:585
void dispatch_input_event(SampleEvent e)
Stamp e with the bound FrameClock's t/frame and dispatch it to every installed sink.
bool firehose() const noexcept
void publish_internal(std::string view_name, std::string metric_name, std::vector< std::pair< std::string, double > > components, PublishOptions opts)
Called by publish_value / publish_components.
TraceBuilder trace(std::string view_name, TraceOptions opts={})
Start building a trace.
static Coordinator & instance()
Process-wide instance. Bound to a FrameClock via bind().
void detach(int trace_id)
Remove a trace by id (called automatically by TraceHandle destruction).
Provenance current_ambient_provenance_internal() const
std::size_t active_trace_count() const noexcept
bool is_bound() const noexcept
bool tracing_enabled() const noexcept
std::size_t emitted_event_count() const noexcept
Cumulative count of SampleEvents dispatched since reset(). For tests.
int add_sink(Sink sink)
Add a sink and return its id (for later removal).
void set_firehose(bool on)
Filter-scope firehose toggle.
void unbind()
Drop the FrameClock subscription. No effect if not bound.
int install_default_log_sink()
Convenience: add the default make_log_sink() and return its id.
void set_tracing_enabled(bool on)
Global tracing toggle. Off by default. When off, on_tick is a no-op.
void reset()
Reset all state (binding, sinks, traces, counters). For tests.
friend class TraceBuilder
Definition motion.hpp:659
void set_ambient_provenance_internal(Provenance p)
Called by set_ambient_provenance / clear_ambient_provenance.
void bind(pulp::view::FrameClock &clock)
Bind the coordinator's single tick subscription to a FrameClock.
Recording handle returned by make_input_recorder.
Definition motion.hpp:432
InputRecorder() noexcept=default
friend InputRecorder make_input_recorder(std::string path)
Install a fixture sink at path and enable simulate_* recording.
bool is_recording() const noexcept
Definition motion.hpp:444
void stop()
Stop recording inputs and close the fixture sink. Idempotent.
Definition motion.hpp:518
std::pair< std::string, ValueSampler > Component
Definition motion.hpp:521
TraceBuilder & multi(std::string name, std::vector< Component > components, int precision=3, double epsilon=0.0001)
Multi-component metric (e.g., a 2D point).
TraceHandle attach()
Register the trace with the coordinator and return an owning handle.
std::function< double()> ValueSampler
Definition motion.hpp:520
TraceBuilder & value(std::string name, ValueSampler sampler, int precision=3, double epsilon=0.0001)
Single-scalar metric. The sampler is invoked once per sampler tick.
friend class Coordinator
Definition motion.hpp:572
TraceBuilder & geometry(std::string name, pulp::view::View &target, std::vector< GeometryProperty > props={GeometryProperty::MinX, GeometryProperty::MinY, GeometryProperty::Width, GeometryProperty::Height}, GeometrySpace space=GeometrySpace::Window, GeometrySource source=GeometrySource::Layout, int precision=2, double epsilon=0.1)
Geometry metric over a target view.
TraceBuilder & with_provenance(Provenance p)
Attach a provenance envelope to the trace.
TraceBuilder & scroll_geometry(std::string name, pulp::view::ScrollView &target, std::vector< ScrollProperty > props={ ScrollProperty::ContentOffsetX, ScrollProperty::ContentOffsetY, ScrollProperty::VisibleRectMinY, ScrollProperty::VisibleRectHeight, }, int precision=2, double epsilon=0.1)
Scroll-geometry metric over a ScrollView.
Definition motion.hpp:491
bool is_attached() const noexcept
Definition motion.hpp:503
void detach()
Remove the trace from its coordinator. Idempotent.
int id() const noexcept
Definition motion.hpp:504
TraceHandle() noexcept=default
friend class TraceBuilder
Definition motion.hpp:508
friend class Coordinator
Definition motion.hpp:507
Definition child_process_manager.hpp:18
Definition motion.hpp:26
GeometrySource
Definition motion.hpp:30
@ Presentation
After paint_all() composition; currently falls back to Layout.
Definition motion.hpp:32
@ Layout
Yoga-computed bounds, ignoring paint-time transforms.
Definition motion.hpp:31
Sink make_log_sink()
Sink that writes one log line per event via pulp::runtime::log_debug.
InputRecorder make_input_recorder(std::string path)
Install a fixture sink at path and enable simulate_* recording.
Sink make_fixture_sink(std::string path)
Sink that appends each SampleEvent as a JSONL line to path.
GeometryProperty
Definition motion.hpp:42
@ MaxY
Definition motion.hpp:43
@ Width
Definition motion.hpp:45
@ MinX
Definition motion.hpp:43
@ MinY
Definition motion.hpp:43
@ MidY
Definition motion.hpp:44
@ MaxX
Definition motion.hpp:43
@ Height
Definition motion.hpp:45
@ MidX
Definition motion.hpp:44
double start_delay_seconds(const std::vector< ScalarSample > &samples, double epsilon=1e-6)
Time from t0 to the first change above epsilon.
constexpr int kFixtureSchemaVersion
Definition motion.hpp:249
int replay_inputs(const std::string &path, View &root_view, FrameClock &frame_clock)
Read a fixture file, find each Input event, resolve view_id from root_view for diagnostics,...
Provenance current_ambient_provenance()
void publish_components(std::string view_name, std::string metric_name, std::vector< std::pair< std::string, double > > components, PublishOptions opts={})
Multi-component publish (e.g., a 2D point or a geometry rect).
void set_ambient_provenance(Provenance p)
int replay_fixture(const std::string &path, const Sink &sink)
Read a fixture file from disk and dispatch each event to sink.
std::vector< ScalarSample > extract_scalar(const std::vector< SampleEvent > &events, std::string_view view_name, std::string_view metric_name, std::string_view component_name="value")
void publish_value(std::string view_name, std::string metric_name, double value, PublishOptions opts={})
Single-component publish.
double final_value(const std::vector< ScalarSample > &samples)
Returns the last sample's value, or NaN when empty.
constexpr int kInvalidFixtureSchemaVersion
Sentinel for a default-constructed / unrecognised fixture header.
Definition motion.hpp:254
double overshoot(const std::vector< ScalarSample > &samples, double epsilon=1e-6)
Overshoot relative to the final value: max excursion beyond the final value's direction from the firs...
std::string format_line(const SampleEvent &e)
Render the canonical [PulpMotion][view][metric] ... line for a sample event.
Sink make_buffer_sink(std::vector< SampleEvent > *buffer)
Sink that appends events to a caller-owned buffer.
FixtureDiff assert_matches(const std::vector< SampleEvent > &golden, const std::vector< SampleEvent > &captured, FixtureMatchOptions opts={})
double frame_jitter_seconds(const std::vector< ScalarSample > &samples)
Standard deviation of inter-sample intervals — proxy for frame-pacing jitter when the sampler is run ...
GeometrySpace
Definition motion.hpp:35
@ Screen
Currently same as ViewGlobal; reserved for screen offset.
Definition motion.hpp:39
@ ViewLocal
Origin at the target view's top-left, in its own frame.
Definition motion.hpp:36
@ ViewGlobal
Root-view coordinate space.
Definition motion.hpp:37
@ Window
Currently same as ViewGlobal; reserved for window origin.
Definition motion.hpp:38
bool input_recording_enabled() noexcept
True while at least one InputRecorder is alive.
void clear_ambient_provenance()
std::vector< SampleEvent > load_fixture(const std::string &path)
Load a fixture file into memory.
FixtureHeader load_fixture_header(const std::string &path)
Load a fixture's header (schema version + policy + duration_scale).
bool is_monotonic(const std::vector< ScalarSample > &samples, double epsilon=1e-6)
Strict monotonicity check with epsilon.
ScrollProperty
Definition motion.hpp:56
@ VisibleRectHeight
Definition motion.hpp:58
@ VisibleRectMinX
Definition motion.hpp:58
@ InsetLeft
Definition motion.hpp:60
@ VisibleRectMinY
Definition motion.hpp:58
@ ContentSizeWidth
Definition motion.hpp:59
@ ContentOffsetY
Definition motion.hpp:57
@ ContentSizeHeight
Definition motion.hpp:59
@ InsetRight
Definition motion.hpp:60
@ ContentOffsetX
Definition motion.hpp:57
@ ScrollableMaxY
Definition motion.hpp:61
@ ScrollableMaxX
Definition motion.hpp:61
@ VisibleRectWidth
Definition motion.hpp:58
@ InsetTop
Definition motion.hpp:60
@ InsetBottom
Definition motion.hpp:60
std::function< void(const SampleEvent &)> Sink
Definition motion.hpp:389
double local_step_outlier_ratio(const std::vector< ScalarSample > &samples, std::size_t window_radius=3, double epsilon=1e-9)
Local-step outlier ratio.
void record_simulated_input(const std::string &input_kind, const std::string &view_id, std::vector< std::pair< std::string, double > > coords)
Process-wide entry point called by View::simulate_* when input recording is active.
double settling_time_seconds(const std::vector< ScalarSample > &samples, double epsilon=1e-6)
Time from first change above epsilon to last change above epsilon.
Hover-cursor tracking for platform window hosts.
Definition fwd.hpp:27
@ path
Definition anchor_strategy.hpp:42
@ value
the widget's primary value (Knob, Fader, RangeSlider, Toggle, ProgressBar)
Definition binding_diagnostics.hpp:19
@ p
Definition input_events.hpp:40
@ e
Definition input_events.hpp:39
@ space
Definition input_events.hpp:58
@ on
Definition accessibility.hpp:132
STL namespace.
Definition motion.hpp:282
std::string metric_name
Definition motion.hpp:286
double observed
Definition motion.hpp:289
std::string detail
Definition motion.hpp:288
double expected
Definition motion.hpp:290
std::string component_name
Definition motion.hpp:287
std::string view_name
Definition motion.hpp:285
std::string kind
"missing-event", "extra-event", "component-drift", "timing-drift"
Definition motion.hpp:283
Comparison result from assert_matches.
Definition motion.hpp:281
bool matches() const noexcept
Definition motion.hpp:293
std::vector< Item > differences
Definition motion.hpp:292
Header metadata recorded once at the top of a fixture file.
Definition motion.hpp:257
double duration_scale
Duration scale in effect when the fixture was recorded.
Definition motion.hpp:264
std::string policy
Policy in effect when the fixture was recorded.
Definition motion.hpp:262
int version
Definition motion.hpp:258
double timing_epsilon_seconds
Definition motion.hpp:298
bool require_same_event_count
Definition motion.hpp:299
bool require_matching_policy
When true (default), assert_matches_headers will flag a "policy-mismatch" diff item if the two fixtur...
Definition motion.hpp:305
double component_epsilon
Definition motion.hpp:297
double duration_scale_epsilon
Definition motion.hpp:306
Definition motion.hpp:77
std::string source_file
Optional, e.g. FILE at attach site.
Definition motion.hpp:82
std::string source_kind
"tween" | "css-transition" | "animator-set" | "rAF" | "design-import" | "user" | "publish"
Definition motion.hpp:78
int source_line
Optional, e.g. LINE at attach site.
Definition motion.hpp:83
bool is_set() const noexcept
Definition motion.hpp:85
std::string source_id
Free-form id, e.g.
Definition motion.hpp:80
Definition motion.hpp:181
double epsilon
Definition motion.hpp:183
Provenance provenance
Optional Provenance envelope.
Definition motion.hpp:188
int precision
Definition motion.hpp:182
Definition motion.hpp:98
std::string view_id
Definition motion.hpp:154
double t_seconds
Monotonic FrameClock::time().
Definition motion.hpp:117
std::string view_name
Definition motion.hpp:115
int metric_id
Definition motion.hpp:127
int burst_id
Definition motion.hpp:128
int trace_id
Definition motion.hpp:126
int precision
Definition motion.hpp:119
std::vector< std::pair< std::string, double > > components
Sorted by name.
Definition motion.hpp:132
Kind
Definition motion.hpp:99
@ Input
Recorded View::simulate_* interaction.
Definition motion.hpp:107
@ End
Burst closed (value stabilized). Carries deltas.
Definition motion.hpp:106
@ TraceStarted
Emitted once per trace registration.
Definition motion.hpp:100
@ Baseline
First sample of a metric.
Definition motion.hpp:102
@ Start
Burst opened (value drifted off baseline / last stable).
Definition motion.hpp:104
@ Sample
Value sample within a change burst.
Definition motion.hpp:103
Provenance provenance
Populated on TraceStarted; empty otherwise.
Definition motion.hpp:130
std::string input_kind
Definition motion.hpp:153
std::string metric_name
Definition motion.hpp:116
Kind kind
Definition motion.hpp:114
std::uint64_t frame
Monotonic FrameClock::frame().
Definition motion.hpp:118
std::vector< std::pair< std::string, double > > deltas
End events only.
Definition motion.hpp:133
Flatten a fixture's events into a (time, value) series for one (view, metric, component) triple.
Definition motion.hpp:335
double value
Definition motion.hpp:335
double t
Definition motion.hpp:335
Definition motion.hpp:66
int fps
Definition motion.hpp:67