Add animation panel action planner
This commit is contained in:
@@ -25,6 +25,20 @@ enum class DocumentAnimationOperation {
|
||||
set_onion_size,
|
||||
};
|
||||
|
||||
enum class DocumentAnimationPanelAction {
|
||||
goto_frame,
|
||||
next_frame,
|
||||
previous_frame,
|
||||
playback_step,
|
||||
toggle_playback,
|
||||
};
|
||||
|
||||
struct DocumentAnimationPanelState {
|
||||
int total_duration = 1;
|
||||
int current_frame = 0;
|
||||
bool playback_active = false;
|
||||
};
|
||||
|
||||
struct DocumentAnimationOperationPlan {
|
||||
DocumentAnimationOperation operation = DocumentAnimationOperation::goto_frame;
|
||||
int frame_count = 1;
|
||||
@@ -380,6 +394,32 @@ public:
|
||||
return pp::foundation::Result<DocumentAnimationOperationPlan>::success(plan);
|
||||
}
|
||||
|
||||
[[nodiscard]] inline pp::foundation::Result<DocumentAnimationOperationPlan> plan_animation_panel_action(
|
||||
DocumentAnimationPanelAction action,
|
||||
const DocumentAnimationPanelState& state,
|
||||
int target_frame = 0)
|
||||
{
|
||||
switch (action) {
|
||||
case DocumentAnimationPanelAction::goto_frame:
|
||||
return plan_animation_goto_frame(state.total_duration, target_frame);
|
||||
|
||||
case DocumentAnimationPanelAction::next_frame:
|
||||
return plan_animation_step_frame(state.total_duration, state.current_frame, 1);
|
||||
|
||||
case DocumentAnimationPanelAction::previous_frame:
|
||||
return plan_animation_step_frame(state.total_duration, state.current_frame, -1);
|
||||
|
||||
case DocumentAnimationPanelAction::playback_step:
|
||||
return plan_animation_playback_step(state.total_duration, state.current_frame, 1);
|
||||
|
||||
case DocumentAnimationPanelAction::toggle_playback:
|
||||
return plan_animation_playback_toggle(state.playback_active);
|
||||
}
|
||||
|
||||
return pp::foundation::Result<DocumentAnimationOperationPlan>::failure(
|
||||
pp::foundation::Status::invalid_argument("unknown animation panel action"));
|
||||
}
|
||||
|
||||
[[nodiscard]] inline pp::foundation::Status validate_animation_operation_plan(
|
||||
const DocumentAnimationOperationPlan& plan) noexcept
|
||||
{
|
||||
|
||||
@@ -163,6 +163,15 @@ void NodePanelAnimation::execute_animation_plan(const pp::app::DocumentAnimation
|
||||
LOG("Animation panel action failed: %s", status.message);
|
||||
}
|
||||
|
||||
pp::app::DocumentAnimationPanelState NodePanelAnimation::animation_panel_state() const
|
||||
{
|
||||
return pp::app::DocumentAnimationPanelState {
|
||||
.total_duration = Canvas::I->anim_duration(),
|
||||
.current_frame = Canvas::I->m_anim_frame,
|
||||
.playback_active = btn_play->is_active(),
|
||||
};
|
||||
}
|
||||
|
||||
void NodePanelAnimation::init_controls()
|
||||
{
|
||||
m_layers_container = find<NodeScroll>("layers");
|
||||
@@ -275,7 +284,10 @@ void NodePanelAnimation::init_controls()
|
||||
};
|
||||
|
||||
m_timeline->on_frame_changed = [this] (NodeAnimationTimeline* target, int frame) {
|
||||
const auto plan = pp::app::plan_animation_goto_frame(Canvas::I->anim_duration(), frame);
|
||||
const auto plan = pp::app::plan_animation_panel_action(
|
||||
pp::app::DocumentAnimationPanelAction::goto_frame,
|
||||
animation_panel_state(),
|
||||
frame);
|
||||
if (!plan)
|
||||
return;
|
||||
LOG("goto frame %d", plan.value().target_frame);
|
||||
@@ -283,19 +295,25 @@ void NodePanelAnimation::init_controls()
|
||||
};
|
||||
|
||||
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);
|
||||
const auto plan = pp::app::plan_animation_panel_action(
|
||||
pp::app::DocumentAnimationPanelAction::next_frame,
|
||||
animation_panel_state());
|
||||
if (!plan)
|
||||
return;
|
||||
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);
|
||||
const auto plan = pp::app::plan_animation_panel_action(
|
||||
pp::app::DocumentAnimationPanelAction::previous_frame,
|
||||
animation_panel_state());
|
||||
if (!plan)
|
||||
return;
|
||||
execute_animation_plan(plan.value());
|
||||
};
|
||||
btn_play->on_click = [this] (Node*) {
|
||||
const auto plan = pp::app::plan_animation_playback_toggle(btn_play->is_active());
|
||||
const auto plan = pp::app::plan_animation_panel_action(
|
||||
pp::app::DocumentAnimationPanelAction::toggle_playback,
|
||||
animation_panel_state());
|
||||
if (plan)
|
||||
execute_animation_plan(plan.value());
|
||||
};
|
||||
@@ -364,10 +382,9 @@ 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_playback_step(
|
||||
Canvas::I->anim_duration(),
|
||||
Canvas::I->m_anim_frame,
|
||||
1);
|
||||
const auto plan = pp::app::plan_animation_panel_action(
|
||||
pp::app::DocumentAnimationPanelAction::playback_step,
|
||||
animation_panel_state());
|
||||
if (plan)
|
||||
execute_animation_plan(plan.value());
|
||||
}
|
||||
|
||||
@@ -10,6 +10,7 @@
|
||||
class Layer;
|
||||
|
||||
namespace pp::app {
|
||||
struct DocumentAnimationPanelState;
|
||||
struct DocumentAnimationOperationPlan;
|
||||
}
|
||||
|
||||
@@ -73,6 +74,7 @@ class NodePanelAnimation : public Node
|
||||
float m_playback_timer = 0;
|
||||
|
||||
void execute_animation_plan(const pp::app::DocumentAnimationOperationPlan& plan, Layer* layer = nullptr);
|
||||
[[nodiscard]] pp::app::DocumentAnimationPanelState animation_panel_state() const;
|
||||
public:
|
||||
using this_class = NodePanelAnimation;
|
||||
using parent = Node;
|
||||
|
||||
Reference in New Issue
Block a user