diff --git a/data/dialogs/panel-animation.xml b/data/dialogs/panel-animation.xml
index f6cc878..be43dc9 100644
--- a/data/dialogs/panel-animation.xml
+++ b/data/dialogs/panel-animation.xml
@@ -57,7 +57,13 @@
-
+
+
+
+
+
+
+
diff --git a/src/canvas_layer.cpp b/src/canvas_layer.cpp
index 2e884fe..54cbae7 100644
--- a/src/canvas_layer.cpp
+++ b/src/canvas_layer.cpp
@@ -228,10 +228,11 @@ bool Layer::create(int width, int height, std::string name)
return true;
}
-bool Layer::add_frame()
+bool Layer::add_frame(int index /*= -1*/)
{
- m_frames.emplace_back();
- m_frames.back().create(w, h);
+ auto pos = index == -1 ? m_frames.end() : m_frames.begin() + index;
+ auto it = m_frames.emplace(pos);
+ it->create(w, h);
frames_gpu_update();
return true;
}
@@ -267,6 +268,21 @@ void Layer::frames_gpu_update()
});
}
+int Layer::move_frame_offset(int frame, int offset) noexcept
+{
+ int new_pos = glm::clamp(frame + offset, 0, (int)m_frames.size() - 1);
+ auto from = m_frames.begin() + frame;
+ auto to = m_frames.begin() + new_pos;
+
+ if (new_pos < frame)
+ std::rotate(to, from, from + 1);
+ if (new_pos > frame)
+ std::rotate(from, from + 1, to + 1);
+
+ frames_gpu_update();
+ return new_pos;
+}
+
int Layer::total_duration() const noexcept
{
int duration = 0;
diff --git a/src/canvas_layer.h b/src/canvas_layer.h
index edcf757..85ad666 100644
--- a/src/canvas_layer.h
+++ b/src/canvas_layer.h
@@ -69,13 +69,14 @@ public:
LayerFrame& frame(int frame = -1);
void resize(int width, int height);
bool create(int width, int height, std::string name);
- bool add_frame();
+ bool add_frame(int index = -1);
void remove_frame(int frame);
void duplicate_frame(int frame);
void frames_gpu_update();
int frames_count() const noexcept { return m_frames.size(); }
int frame_duration(int frame) const noexcept { return m_frames[frame].m_duration; }
void set_frame_duration(int frame, int duration) noexcept { m_frames[frame].m_duration = duration; }
+ int move_frame_offset(int frame, int offset) noexcept;
int total_duration() const noexcept;
void goto_frame(int frame) noexcept;
void clear(const glm::vec4& c, int frame = -1);
diff --git a/src/node_panel_animation.cpp b/src/node_panel_animation.cpp
index 16eb7aa..aae04a3 100644
--- a/src/node_panel_animation.cpp
+++ b/src/node_panel_animation.cpp
@@ -33,6 +33,8 @@ void NodePanelAnimation::init_controls()
btn_remove = find("btn-remove");
btn_up = find("btn-up");
btn_down = find("btn-down");
+ btn_left = find("btn-left");
+ btn_right = find("btn-right");
btn_duplicate = find("btn-duplicate");
btn_next = find("btn-next");
btn_prev = find("btn-prev");
@@ -63,6 +65,22 @@ void NodePanelAnimation::init_controls()
layer->set_frame_duration(m_selected_frame_index, glm::max(layer->frame_duration(m_selected_frame_index) - 1, 1));
load_layers();
};
+ btn_left->on_click = [this](Node*) {
+ if (!m_selected_frame)
+ return;
+ if (auto layer = Canvas::I->layer_with_id(m_selected_frame_layer_id))
+ m_selected_frame_index = layer->move_frame_offset(m_selected_frame_index, -1);
+ Canvas::I->anim_goto_frame(m_selected_frame_index);
+ load_layers();
+ };
+ btn_right->on_click = [this](Node*) {
+ if (!m_selected_frame)
+ return;
+ if (auto layer = Canvas::I->layer_with_id(m_selected_frame_layer_id))
+ m_selected_frame_index = layer->move_frame_offset(m_selected_frame_index, +1);
+ Canvas::I->anim_goto_frame(m_selected_frame_index);
+ load_layers();
+ };
m_onion->on_select = [this] (Node* target, int index) {
m_timeline->m_onion_size = m_onion->get_int();
diff --git a/src/node_panel_animation.h b/src/node_panel_animation.h
index 55fdf7b..aa5cd9b 100644
--- a/src/node_panel_animation.h
+++ b/src/node_panel_animation.h
@@ -52,6 +52,8 @@ class NodePanelAnimation : public Node
NodeButtonCustom* btn_remove = nullptr;
NodeButtonCustom* btn_up = nullptr;
NodeButtonCustom* btn_down = nullptr;
+ NodeButtonCustom* btn_left = nullptr;
+ NodeButtonCustom* btn_right = nullptr;
NodeButtonCustom* btn_duplicate = nullptr;
Node* m_layers_container = nullptr;
Node* m_frames_container = nullptr;