Extend animation panel frame dispatch
This commit is contained in:
@@ -16,9 +16,11 @@ enum class DocumentAnimationOperation {
|
||||
remove_frame,
|
||||
adjust_duration,
|
||||
move_frame,
|
||||
select_frame,
|
||||
goto_frame,
|
||||
goto_next,
|
||||
goto_previous,
|
||||
playback_step,
|
||||
set_onion_size,
|
||||
};
|
||||
|
||||
@@ -32,6 +34,8 @@ struct DocumentAnimationOperationPlan {
|
||||
int duration_delta = 0;
|
||||
int move_offset = 0;
|
||||
int onion_size = 1;
|
||||
int layer_index = 0;
|
||||
std::uint32_t layer_id = 0;
|
||||
bool requires_selected_frame = false;
|
||||
bool mutates_document = false;
|
||||
bool reloads_animation_layers = false;
|
||||
@@ -48,9 +52,13 @@ public:
|
||||
virtual void remove_frame(int selected_frame, int target_frame) = 0;
|
||||
virtual void set_frame_duration(int selected_frame, int duration) = 0;
|
||||
virtual int move_frame(int selected_frame, int move_offset) = 0;
|
||||
virtual void select_frame(std::uint32_t layer_id, int layer_index, int selected_frame) = 0;
|
||||
virtual void select_layer(int layer_index) = 0;
|
||||
virtual void goto_frame(int target_frame) = 0;
|
||||
virtual void set_timeline_frame(int target_frame) = 0;
|
||||
virtual void set_onion_size(int onion_size) = 0;
|
||||
virtual void update_canvas_animation() = 0;
|
||||
virtual void update_frame_status() = 0;
|
||||
virtual void reload_animation_layers() = 0;
|
||||
virtual void mark_unsaved() = 0;
|
||||
};
|
||||
@@ -236,6 +244,34 @@ public:
|
||||
return pp::foundation::Result<DocumentAnimationOperationPlan>::success(plan);
|
||||
}
|
||||
|
||||
[[nodiscard]] inline pp::foundation::Result<DocumentAnimationOperationPlan> plan_animation_select_frame(
|
||||
int frame_count,
|
||||
int layer_index,
|
||||
std::uint32_t layer_id,
|
||||
int selected_frame)
|
||||
{
|
||||
const auto index_status = validate_animation_frame_index(frame_count, selected_frame);
|
||||
if (!index_status.ok()) {
|
||||
return pp::foundation::Result<DocumentAnimationOperationPlan>::failure(index_status);
|
||||
}
|
||||
|
||||
if (layer_index < 0) {
|
||||
return pp::foundation::Result<DocumentAnimationOperationPlan>::failure(
|
||||
pp::foundation::Status::out_of_range("animation layer index must not be negative"));
|
||||
}
|
||||
|
||||
DocumentAnimationOperationPlan plan;
|
||||
plan.operation = DocumentAnimationOperation::select_frame;
|
||||
plan.frame_count = frame_count;
|
||||
plan.selected_frame = selected_frame;
|
||||
plan.target_frame = selected_frame;
|
||||
plan.layer_index = layer_index;
|
||||
plan.layer_id = layer_id;
|
||||
plan.requires_selected_frame = true;
|
||||
plan.updates_canvas_animation = true;
|
||||
return pp::foundation::Result<DocumentAnimationOperationPlan>::success(plan);
|
||||
}
|
||||
|
||||
[[nodiscard]] inline pp::foundation::Result<DocumentAnimationOperationPlan> plan_animation_goto_frame(
|
||||
int total_duration,
|
||||
int frame)
|
||||
@@ -290,6 +326,23 @@ public:
|
||||
return pp::foundation::Result<DocumentAnimationOperationPlan>::success(plan);
|
||||
}
|
||||
|
||||
[[nodiscard]] inline pp::foundation::Result<DocumentAnimationOperationPlan> plan_animation_playback_step(
|
||||
int total_duration,
|
||||
int current_frame,
|
||||
int offset)
|
||||
{
|
||||
const auto step = plan_animation_step_frame(total_duration, current_frame, offset);
|
||||
if (!step) {
|
||||
return pp::foundation::Result<DocumentAnimationOperationPlan>::failure(step.status());
|
||||
}
|
||||
|
||||
auto plan = step.value();
|
||||
plan.operation = DocumentAnimationOperation::playback_step;
|
||||
plan.move_offset = offset;
|
||||
plan.reloads_animation_layers = false;
|
||||
return pp::foundation::Result<DocumentAnimationOperationPlan>::success(plan);
|
||||
}
|
||||
|
||||
[[nodiscard]] inline pp::foundation::Result<DocumentAnimationOperationPlan> plan_animation_onion_size(int onion_size)
|
||||
{
|
||||
if (onion_size < 0) {
|
||||
@@ -342,12 +395,28 @@ public:
|
||||
}
|
||||
return validate_animation_frame_index(plan.frame_count, plan.selected_frame);
|
||||
|
||||
case DocumentAnimationOperation::select_frame:
|
||||
if (!plan.requires_selected_frame || !plan.updates_canvas_animation || plan.layer_index < 0) {
|
||||
return pp::foundation::Status::invalid_argument("animation frame select plan has invalid state");
|
||||
}
|
||||
{
|
||||
const auto index_status = validate_animation_frame_index(plan.frame_count, plan.selected_frame);
|
||||
if (!index_status.ok()) {
|
||||
return index_status;
|
||||
}
|
||||
}
|
||||
return validate_animation_frame_index(plan.frame_count, plan.target_frame);
|
||||
|
||||
case DocumentAnimationOperation::goto_frame:
|
||||
case DocumentAnimationOperation::goto_next:
|
||||
case DocumentAnimationOperation::goto_previous:
|
||||
case DocumentAnimationOperation::playback_step:
|
||||
if (!plan.updates_canvas_animation) {
|
||||
return pp::foundation::Status::invalid_argument("animation goto plan must update canvas animation");
|
||||
}
|
||||
if (plan.operation == DocumentAnimationOperation::playback_step && plan.move_offset == 0) {
|
||||
return pp::foundation::Status::invalid_argument("animation playback step offset must not be zero");
|
||||
}
|
||||
return validate_animation_frame_index(plan.frame_count, plan.target_frame);
|
||||
|
||||
case DocumentAnimationOperation::set_onion_size:
|
||||
@@ -434,6 +503,20 @@ public:
|
||||
}
|
||||
return pp::foundation::Status::success();
|
||||
|
||||
case DocumentAnimationOperation::select_frame:
|
||||
services.select_frame(plan.layer_id, plan.layer_index, plan.selected_frame);
|
||||
if (plan.updates_canvas_animation) {
|
||||
services.goto_frame(plan.target_frame);
|
||||
}
|
||||
services.select_layer(plan.layer_index);
|
||||
return pp::foundation::Status::success();
|
||||
|
||||
case DocumentAnimationOperation::playback_step:
|
||||
services.goto_frame(plan.target_frame);
|
||||
services.set_timeline_frame(plan.target_frame);
|
||||
services.update_frame_status();
|
||||
return pp::foundation::Status::success();
|
||||
|
||||
case DocumentAnimationOperation::set_onion_size:
|
||||
services.set_onion_size(plan.onion_size);
|
||||
if (plan.updates_canvas_animation) {
|
||||
|
||||
@@ -69,11 +69,28 @@ void NodePanelAnimation::execute_animation_plan(const pp::app::DocumentAnimation
|
||||
return panel_.m_selected_frame_index;
|
||||
}
|
||||
|
||||
void select_frame(std::uint32_t layer_id, int layer_index, int selected_frame) override
|
||||
{
|
||||
panel_.m_selected_frame_layer_id = layer_id;
|
||||
panel_.m_selected_frame_index = selected_frame;
|
||||
panel_.m_timeline->m_frame = selected_frame;
|
||||
}
|
||||
|
||||
void select_layer(int layer_index) override
|
||||
{
|
||||
App::I->layers->handle_layer_selected(App::I->layers->get_layer_at(layer_index));
|
||||
}
|
||||
|
||||
void goto_frame(int target_frame) override
|
||||
{
|
||||
Canvas::I->anim_goto_frame(target_frame);
|
||||
}
|
||||
|
||||
void set_timeline_frame(int target_frame) override
|
||||
{
|
||||
panel_.m_timeline->m_frame = target_frame;
|
||||
}
|
||||
|
||||
void set_onion_size(int onion_size) override
|
||||
{
|
||||
panel_.m_timeline->m_onion_size = onion_size;
|
||||
@@ -84,6 +101,11 @@ void NodePanelAnimation::execute_animation_plan(const pp::app::DocumentAnimation
|
||||
Canvas::I->anim_update();
|
||||
}
|
||||
|
||||
void update_frame_status() override
|
||||
{
|
||||
panel_.update_frames();
|
||||
}
|
||||
|
||||
void reload_animation_layers() override
|
||||
{
|
||||
panel_.load_layers();
|
||||
@@ -288,11 +310,13 @@ void NodePanelAnimation::load_layers()
|
||||
m_selected_frame->set_active(false);
|
||||
frame->set_active(true);
|
||||
m_selected_frame = frame;
|
||||
m_selected_frame_layer_id = lid;
|
||||
m_selected_frame_index = fi;
|
||||
m_timeline->m_frame = fi;
|
||||
Canvas::I->anim_goto_frame(fi);
|
||||
App::I->layers->handle_layer_selected(App::I->layers->get_layer_at(i));
|
||||
const auto plan = pp::app::plan_animation_select_frame(
|
||||
Canvas::I->m_layers[i]->frames_count(),
|
||||
i,
|
||||
lid,
|
||||
fi);
|
||||
if (plan)
|
||||
execute_animation_plan(plan.value(), Canvas::I->m_layers[i].get());
|
||||
};
|
||||
}
|
||||
}
|
||||
@@ -317,13 +341,12 @@ void NodePanelAnimation::on_tick(float dt)
|
||||
if (m_playback_timer > (1.f / m_fps->get_float()))
|
||||
{
|
||||
m_playback_timer = 0;
|
||||
const auto plan = pp::app::plan_animation_step_frame(Canvas::I->anim_duration(), Canvas::I->m_anim_frame, 1);
|
||||
const auto plan = pp::app::plan_animation_playback_step(
|
||||
Canvas::I->anim_duration(),
|
||||
Canvas::I->m_anim_frame,
|
||||
1);
|
||||
if (plan)
|
||||
{
|
||||
Canvas::I->anim_goto_frame(plan.value().target_frame);
|
||||
m_timeline->m_frame = Canvas::I->m_anim_frame;
|
||||
update_frames();
|
||||
}
|
||||
execute_animation_plan(plan.value());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user