Add animation panel service boundary

This commit is contained in:
2026-06-03 14:04:36 +02:00
parent 9c7c89fed4
commit 93f3037410
6 changed files with 457 additions and 78 deletions

View File

@@ -26,6 +26,85 @@ void NodePanelAnimation::init()
init_controls();
}
void NodePanelAnimation::execute_animation_plan(const pp::app::DocumentAnimationOperationPlan& plan, Layer* layer)
{
class LegacyAnimationServices final : public pp::app::DocumentAnimationServices {
public:
LegacyAnimationServices(NodePanelAnimation& panel, Layer* layer) noexcept
: panel_(panel)
, layer_(layer)
{
}
void add_frame() override
{
Canvas::I->layer().add_frame();
}
void duplicate_frame(int selected_frame) override
{
if (layer_)
layer_->duplicate_frame(selected_frame);
}
void remove_frame(int selected_frame, int target_frame) override
{
if (!layer_)
return;
layer_->remove_frame(selected_frame);
panel_.m_selected_frame_index = target_frame;
}
void set_frame_duration(int selected_frame, int duration) override
{
if (layer_)
layer_->set_frame_duration(selected_frame, duration);
}
int move_frame(int selected_frame, int move_offset) override
{
if (!layer_)
return selected_frame;
panel_.m_selected_frame_index = layer_->move_frame_offset(selected_frame, move_offset);
return panel_.m_selected_frame_index;
}
void goto_frame(int target_frame) override
{
Canvas::I->anim_goto_frame(target_frame);
}
void set_onion_size(int onion_size) override
{
panel_.m_timeline->m_onion_size = onion_size;
}
void update_canvas_animation() override
{
Canvas::I->anim_update();
}
void reload_animation_layers() override
{
panel_.load_layers();
}
void mark_unsaved() override
{
Canvas::I->m_unsaved = true;
}
private:
NodePanelAnimation& panel_;
Layer* layer_ = nullptr;
};
LegacyAnimationServices services(*this, layer);
const auto status = pp::app::execute_animation_operation_plan(plan, services);
if (!status.ok())
LOG("Animation panel action failed: %s", status.message);
}
void NodePanelAnimation::init_controls()
{
m_layers_container = find<NodeScroll>("layers");
@@ -51,13 +130,7 @@ void NodePanelAnimation::init_controls()
Canvas::I->m_anim_frame);
if (!plan)
return;
Canvas::I->layer().add_frame();
if (plan.value().marks_unsaved)
Canvas::I->m_unsaved = true;
if (plan.value().updates_canvas_animation)
Canvas::I->anim_update();
if (plan.value().reloads_animation_layers)
load_layers();
execute_animation_plan(plan.value());
};
btn_duplicate->on_click = [this](Node*) {
if (auto layer = Canvas::I->layer_with_id(m_selected_frame_layer_id))
@@ -67,13 +140,7 @@ void NodePanelAnimation::init_controls()
m_selected_frame_index);
if (!plan)
return;
layer->duplicate_frame(plan.value().selected_frame);
if (plan.value().marks_unsaved)
Canvas::I->m_unsaved = true;
if (plan.value().updates_canvas_animation)
Canvas::I->anim_update();
if (plan.value().reloads_animation_layers)
load_layers();
execute_animation_plan(plan.value(), layer.get());
}
};
btn_remove->on_click = [this](Node*) {
@@ -84,24 +151,12 @@ void NodePanelAnimation::init_controls()
m_selected_frame_index);
if (!plan)
return;
layer->remove_frame(plan.value().selected_frame);
m_selected_frame_index = plan.value().target_frame;
if (plan.value().marks_unsaved)
Canvas::I->m_unsaved = true;
if (plan.value().updates_canvas_animation)
Canvas::I->anim_goto_frame(plan.value().target_frame);
if (plan.value().reloads_animation_layers)
load_layers();
execute_animation_plan(plan.value(), layer.get());
}
};
btn_up->on_click = [this](Node*) {
if (auto layer = Canvas::I->layer_with_id(m_selected_frame_layer_id))
{
const auto index_status = pp::app::validate_animation_frame_index(
layer->frames_count(),
m_selected_frame_index);
if (!index_status.ok())
return;
const auto plan = pp::app::plan_animation_adjust_duration(
layer->frames_count(),
m_selected_frame_index,
@@ -109,23 +164,12 @@ void NodePanelAnimation::init_controls()
1);
if (!plan)
return;
layer->set_frame_duration(plan.value().selected_frame, plan.value().frame_duration);
if (plan.value().marks_unsaved)
Canvas::I->m_unsaved = true;
if (plan.value().updates_canvas_animation)
Canvas::I->anim_update();
if (plan.value().reloads_animation_layers)
load_layers();
execute_animation_plan(plan.value(), layer.get());
}
};
btn_down->on_click = [this](Node*) {
if (auto layer = Canvas::I->layer_with_id(m_selected_frame_layer_id))
{
const auto index_status = pp::app::validate_animation_frame_index(
layer->frames_count(),
m_selected_frame_index);
if (!index_status.ok())
return;
const auto plan = pp::app::plan_animation_adjust_duration(
layer->frames_count(),
m_selected_frame_index,
@@ -133,13 +177,7 @@ void NodePanelAnimation::init_controls()
-1);
if (!plan)
return;
layer->set_frame_duration(plan.value().selected_frame, plan.value().frame_duration);
if (plan.value().marks_unsaved)
Canvas::I->m_unsaved = true;
if (plan.value().updates_canvas_animation)
Canvas::I->anim_update();
if (plan.value().reloads_animation_layers)
load_layers();
execute_animation_plan(plan.value(), layer.get());
}
};
btn_left->on_click = [this](Node*) {
@@ -153,13 +191,7 @@ void NodePanelAnimation::init_controls()
-1);
if (!plan)
return;
m_selected_frame_index = layer->move_frame_offset(plan.value().selected_frame, plan.value().move_offset);
if (plan.value().marks_unsaved)
Canvas::I->m_unsaved = true;
if (plan.value().updates_canvas_animation)
Canvas::I->anim_goto_frame(m_selected_frame_index);
if (plan.value().reloads_animation_layers)
load_layers();
execute_animation_plan(plan.value(), layer.get());
}
};
btn_right->on_click = [this](Node*) {
@@ -173,13 +205,7 @@ void NodePanelAnimation::init_controls()
1);
if (!plan)
return;
m_selected_frame_index = layer->move_frame_offset(plan.value().selected_frame, plan.value().move_offset);
if (plan.value().marks_unsaved)
Canvas::I->m_unsaved = true;
if (plan.value().updates_canvas_animation)
Canvas::I->anim_goto_frame(m_selected_frame_index);
if (plan.value().reloads_animation_layers)
load_layers();
execute_animation_plan(plan.value(), layer.get());
}
};
@@ -187,9 +213,7 @@ void NodePanelAnimation::init_controls()
const auto plan = pp::app::plan_animation_onion_size(m_onion->get_int());
if (!plan)
return;
m_timeline->m_onion_size = plan.value().onion_size;
if (plan.value().updates_canvas_animation)
Canvas::I->anim_update();
execute_animation_plan(plan.value());
};
m_timeline->on_frame_changed = [this] (NodeAnimationTimeline* target, int frame) {
@@ -197,29 +221,20 @@ void NodePanelAnimation::init_controls()
if (!plan)
return;
LOG("goto frame %d", plan.value().target_frame);
if (plan.value().updates_canvas_animation)
Canvas::I->anim_goto_frame(plan.value().target_frame);
if (plan.value().reloads_animation_layers)
load_layers();
execute_animation_plan(plan.value());
};
btn_next->on_click = [this] (Node* target) {
const auto plan = pp::app::plan_animation_step_frame(Canvas::I->anim_duration(), Canvas::I->m_anim_frame, 1);
if (!plan)
return;
if (plan.value().updates_canvas_animation)
Canvas::I->anim_goto_frame(plan.value().target_frame);
if (plan.value().reloads_animation_layers)
load_layers();
execute_animation_plan(plan.value());
};
btn_prev->on_click = [this](Node* target) {
const auto plan = pp::app::plan_animation_step_frame(Canvas::I->anim_duration(), Canvas::I->m_anim_frame, -1);
if (!plan)
return;
if (plan.value().updates_canvas_animation)
Canvas::I->anim_goto_frame(plan.value().target_frame);
if (plan.value().reloads_animation_layers)
load_layers();
execute_animation_plan(plan.value());
};
btn_play->on_click = [this] (Node* target) {
static auto mode = Canvas::I->m_current_mode;