Add animation playback toggle boundary

This commit is contained in:
2026-06-03 16:47:02 +02:00
parent 5752bc6ae9
commit 603bb0c4e7
7 changed files with 217 additions and 26 deletions

View File

@@ -92,6 +92,44 @@ public:
call_order += "onion;";
}
void capture_playback_restore_mode() override
{
playback_restore_captures += 1;
call_order += "capture-mode;";
}
void enter_playback_camera_mode() override
{
playback_camera_entries += 1;
call_order += "camera-mode;";
}
void restore_playback_canvas_mode() override
{
playback_mode_restores += 1;
call_order += "restore-mode;";
}
void set_playback_active(bool active) override
{
playback_active_sets += 1;
last_playback_active = active;
call_order += active ? "play-active;" : "play-inactive;";
}
void reset_playback_timer() override
{
playback_timer_resets += 1;
call_order += "reset-timer;";
}
void set_playback_idle_ms(int idle_ms) override
{
playback_idle_sets += 1;
last_playback_idle_ms = idle_ms;
call_order += "idle;";
}
void update_canvas_animation() override
{
canvas_updates += 1;
@@ -126,6 +164,12 @@ public:
int gotos = 0;
int timeline_sets = 0;
int onion_sets = 0;
int playback_restore_captures = 0;
int playback_camera_entries = 0;
int playback_mode_restores = 0;
int playback_active_sets = 0;
int playback_timer_resets = 0;
int playback_idle_sets = 0;
int canvas_updates = 0;
int frame_status_updates = 0;
int reloads = 0;
@@ -137,7 +181,9 @@ public:
int last_move_offset = 0;
int last_onion_size = -1;
int last_layer_index = -1;
int last_playback_idle_ms = 0;
std::uint32_t last_layer_id = 0;
bool last_playback_active = false;
int move_result = 0;
std::string call_order;
};
@@ -263,6 +309,25 @@ void frame_selection_and_playback_plans_keep_ui_refresh_scoped(pp::tests::Harnes
PP_EXPECT(harness, !pp::app::plan_animation_playback_step(3, 0, 0));
}
void playback_toggle_plans_capture_start_and_stop_intent(pp::tests::Harness& harness)
{
const auto start = pp::app::plan_animation_playback_toggle(false);
PP_REQUIRE(harness, start);
PP_EXPECT(harness, start.value().operation == pp::app::DocumentAnimationOperation::toggle_playback);
PP_EXPECT(harness, !start.value().playback_was_active);
PP_EXPECT(harness, start.value().playback_active);
PP_EXPECT(harness, start.value().resets_playback_timer);
PP_EXPECT(harness, start.value().playback_idle_ms == 10);
const auto stop = pp::app::plan_animation_playback_toggle(true);
PP_REQUIRE(harness, stop);
PP_EXPECT(harness, stop.value().operation == pp::app::DocumentAnimationOperation::toggle_playback);
PP_EXPECT(harness, stop.value().playback_was_active);
PP_EXPECT(harness, !stop.value().playback_active);
PP_EXPECT(harness, !stop.value().resets_playback_timer);
PP_EXPECT(harness, stop.value().playback_idle_ms == 100);
}
void onion_size_updates_canvas_without_document_mutation(pp::tests::Harness& harness)
{
const auto plan = pp::app::plan_animation_onion_size(2);
@@ -339,6 +404,14 @@ void executor_dispatches_timeline_and_parameter_operations(pp::tests::Harness& h
PP_REQUIRE(harness, playback);
PP_EXPECT(harness, pp::app::execute_animation_operation_plan(playback.value(), services).ok());
const auto play_start = pp::app::plan_animation_playback_toggle(false);
PP_REQUIRE(harness, play_start);
PP_EXPECT(harness, pp::app::execute_animation_operation_plan(play_start.value(), services).ok());
const auto play_stop = pp::app::plan_animation_playback_toggle(true);
PP_REQUIRE(harness, play_stop);
PP_EXPECT(harness, pp::app::execute_animation_operation_plan(play_stop.value(), services).ok());
PP_EXPECT(harness, services.duration_sets == 1);
PP_EXPECT(harness, services.last_duration == 5);
PP_EXPECT(harness, services.moves == 1);
@@ -357,11 +430,20 @@ void executor_dispatches_timeline_and_parameter_operations(pp::tests::Harness& h
PP_EXPECT(harness, services.canvas_updates == 2);
PP_EXPECT(harness, services.frame_status_updates == 1);
PP_EXPECT(harness, services.reloads == 3);
PP_EXPECT(harness, services.playback_restore_captures == 1);
PP_EXPECT(harness, services.playback_camera_entries == 1);
PP_EXPECT(harness, services.playback_mode_restores == 1);
PP_EXPECT(harness, services.playback_active_sets == 2);
PP_EXPECT(harness, services.playback_timer_resets == 1);
PP_EXPECT(harness, services.playback_idle_sets == 2);
PP_EXPECT(harness, !services.last_playback_active);
PP_EXPECT(harness, services.last_playback_idle_ms == 100);
PP_EXPECT(
harness,
services.call_order
== "duration;unsaved;update;reload;move;unsaved;goto;reload;goto;reload;onion;update;"
"select-frame;goto;select-layer;goto;timeline;frame-status;");
"select-frame;goto;select-layer;goto;timeline;frame-status;"
"capture-mode;camera-mode;reset-timer;play-active;idle;restore-mode;play-inactive;idle;");
}
void executor_rejects_malformed_animation_plans(pp::tests::Harness& harness)
@@ -396,6 +478,14 @@ void executor_rejects_malformed_animation_plans(pp::tests::Harness& harness)
playback.move_offset = 0;
PP_EXPECT(harness, !pp::app::execute_animation_operation_plan(playback, services).ok());
auto toggle = pp::app::plan_animation_playback_toggle(false).value();
toggle.playback_active = false;
PP_EXPECT(harness, !pp::app::execute_animation_operation_plan(toggle, services).ok());
toggle = pp::app::plan_animation_playback_toggle(false).value();
toggle.playback_idle_ms = 0;
PP_EXPECT(harness, !pp::app::execute_animation_operation_plan(toggle, services).ok());
PP_EXPECT(harness, services.adds == 0);
PP_EXPECT(harness, services.duration_sets == 0);
PP_EXPECT(harness, services.gotos == 0);
@@ -411,6 +501,7 @@ int main()
harness.run("duration plans clamp floor and reject overflow", duration_plans_clamp_floor_and_reject_overflow);
harness.run("move and timeline plans handle edges", move_and_timeline_plans_handle_edges);
harness.run("frame selection and playback plans keep ui refresh scoped", frame_selection_and_playback_plans_keep_ui_refresh_scoped);
harness.run("playback toggle plans capture start and stop intent", playback_toggle_plans_capture_start_and_stop_intent);
harness.run("onion size updates canvas without document mutation", onion_size_updates_canvas_without_document_mutation);
harness.run("executor dispatches mutating frame operations", executor_dispatches_mutating_frame_operations);
harness.run("executor dispatches timeline and parameter operations", executor_dispatches_timeline_and_parameter_operations);