Add animation playback toggle boundary
This commit is contained in:
@@ -21,6 +21,7 @@ enum class DocumentAnimationOperation {
|
||||
goto_next,
|
||||
goto_previous,
|
||||
playback_step,
|
||||
toggle_playback,
|
||||
set_onion_size,
|
||||
};
|
||||
|
||||
@@ -36,11 +37,15 @@ struct DocumentAnimationOperationPlan {
|
||||
int onion_size = 1;
|
||||
int layer_index = 0;
|
||||
std::uint32_t layer_id = 0;
|
||||
int playback_idle_ms = 100;
|
||||
bool requires_selected_frame = false;
|
||||
bool mutates_document = false;
|
||||
bool reloads_animation_layers = false;
|
||||
bool updates_canvas_animation = false;
|
||||
bool marks_unsaved = false;
|
||||
bool playback_was_active = false;
|
||||
bool playback_active = false;
|
||||
bool resets_playback_timer = false;
|
||||
};
|
||||
|
||||
class DocumentAnimationServices {
|
||||
@@ -57,6 +62,12 @@ public:
|
||||
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 capture_playback_restore_mode() = 0;
|
||||
virtual void enter_playback_camera_mode() = 0;
|
||||
virtual void restore_playback_canvas_mode() = 0;
|
||||
virtual void set_playback_active(bool active) = 0;
|
||||
virtual void reset_playback_timer() = 0;
|
||||
virtual void set_playback_idle_ms(int idle_ms) = 0;
|
||||
virtual void update_canvas_animation() = 0;
|
||||
virtual void update_frame_status() = 0;
|
||||
virtual void reload_animation_layers() = 0;
|
||||
@@ -343,6 +354,18 @@ public:
|
||||
return pp::foundation::Result<DocumentAnimationOperationPlan>::success(plan);
|
||||
}
|
||||
|
||||
[[nodiscard]] inline pp::foundation::Result<DocumentAnimationOperationPlan> plan_animation_playback_toggle(
|
||||
bool playback_active)
|
||||
{
|
||||
DocumentAnimationOperationPlan plan;
|
||||
plan.operation = DocumentAnimationOperation::toggle_playback;
|
||||
plan.playback_was_active = playback_active;
|
||||
plan.playback_active = !playback_active;
|
||||
plan.playback_idle_ms = playback_active ? 100 : 10;
|
||||
plan.resets_playback_timer = !playback_active;
|
||||
return pp::foundation::Result<DocumentAnimationOperationPlan>::success(plan);
|
||||
}
|
||||
|
||||
[[nodiscard]] inline pp::foundation::Result<DocumentAnimationOperationPlan> plan_animation_onion_size(int onion_size)
|
||||
{
|
||||
if (onion_size < 0) {
|
||||
@@ -419,6 +442,18 @@ public:
|
||||
}
|
||||
return validate_animation_frame_index(plan.frame_count, plan.target_frame);
|
||||
|
||||
case DocumentAnimationOperation::toggle_playback:
|
||||
if (plan.playback_active == plan.playback_was_active) {
|
||||
return pp::foundation::Status::invalid_argument("animation playback toggle must change state");
|
||||
}
|
||||
if (plan.playback_idle_ms <= 0) {
|
||||
return pp::foundation::Status::invalid_argument("animation playback idle interval must be positive");
|
||||
}
|
||||
if (plan.playback_active && !plan.resets_playback_timer) {
|
||||
return pp::foundation::Status::invalid_argument("animation playback start must reset timer");
|
||||
}
|
||||
return pp::foundation::Status::success();
|
||||
|
||||
case DocumentAnimationOperation::set_onion_size:
|
||||
if (plan.onion_size < 0) {
|
||||
return pp::foundation::Status::invalid_argument("animation onion size must not be negative");
|
||||
@@ -517,6 +552,20 @@ public:
|
||||
services.update_frame_status();
|
||||
return pp::foundation::Status::success();
|
||||
|
||||
case DocumentAnimationOperation::toggle_playback:
|
||||
if (plan.playback_active) {
|
||||
services.capture_playback_restore_mode();
|
||||
services.enter_playback_camera_mode();
|
||||
if (plan.resets_playback_timer) {
|
||||
services.reset_playback_timer();
|
||||
}
|
||||
} else {
|
||||
services.restore_playback_canvas_mode();
|
||||
}
|
||||
services.set_playback_active(plan.playback_active);
|
||||
services.set_playback_idle_ms(plan.playback_idle_ms);
|
||||
return pp::foundation::Status::success();
|
||||
|
||||
case DocumentAnimationOperation::set_onion_size:
|
||||
services.set_onion_size(plan.onion_size);
|
||||
if (plan.updates_canvas_animation) {
|
||||
|
||||
@@ -96,6 +96,36 @@ void NodePanelAnimation::execute_animation_plan(const pp::app::DocumentAnimation
|
||||
panel_.m_timeline->m_onion_size = onion_size;
|
||||
}
|
||||
|
||||
void capture_playback_restore_mode() override
|
||||
{
|
||||
playback_restore_mode() = Canvas::I->m_current_mode;
|
||||
}
|
||||
|
||||
void enter_playback_camera_mode() override
|
||||
{
|
||||
Canvas::set_mode(kCanvasMode::Camera);
|
||||
}
|
||||
|
||||
void restore_playback_canvas_mode() override
|
||||
{
|
||||
Canvas::set_mode(playback_restore_mode());
|
||||
}
|
||||
|
||||
void set_playback_active(bool active) override
|
||||
{
|
||||
panel_.btn_play->set_active(active);
|
||||
}
|
||||
|
||||
void reset_playback_timer() override
|
||||
{
|
||||
panel_.m_playback_timer = 0;
|
||||
}
|
||||
|
||||
void set_playback_idle_ms(int idle_ms) override
|
||||
{
|
||||
App::I->idle_ms = idle_ms;
|
||||
}
|
||||
|
||||
void update_canvas_animation() override
|
||||
{
|
||||
Canvas::I->anim_update();
|
||||
@@ -117,6 +147,12 @@ void NodePanelAnimation::execute_animation_plan(const pp::app::DocumentAnimation
|
||||
}
|
||||
|
||||
private:
|
||||
static kCanvasMode& playback_restore_mode()
|
||||
{
|
||||
static auto mode = Canvas::I->m_current_mode;
|
||||
return mode;
|
||||
}
|
||||
|
||||
NodePanelAnimation& panel_;
|
||||
Layer* layer_ = nullptr;
|
||||
};
|
||||
@@ -258,23 +294,10 @@ void NodePanelAnimation::init_controls()
|
||||
return;
|
||||
execute_animation_plan(plan.value());
|
||||
};
|
||||
btn_play->on_click = [this] (Node* target) {
|
||||
static auto mode = Canvas::I->m_current_mode;
|
||||
auto b = static_cast<NodeButtonCustom*>(target);
|
||||
if (b->is_active())
|
||||
{
|
||||
Canvas::set_mode(mode);
|
||||
b->set_active(false);
|
||||
App::I->idle_ms = 100;
|
||||
}
|
||||
else
|
||||
{
|
||||
mode = Canvas::I->m_current_mode;
|
||||
Canvas::set_mode(kCanvasMode::Camera);
|
||||
m_playback_timer = 0;
|
||||
b->set_active(true);
|
||||
App::I->idle_ms = 10;
|
||||
}
|
||||
btn_play->on_click = [this] (Node*) {
|
||||
const auto plan = pp::app::plan_animation_playback_toggle(btn_play->is_active());
|
||||
if (plan)
|
||||
execute_animation_plan(plan.value());
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user