From 27576443cac33b95560062a92a602e1aff6e8f37 Mon Sep 17 00:00:00 2001 From: omigamedev Date: Sat, 19 Oct 2019 22:30:44 +0200 Subject: [PATCH] improve animation panel --- data/dialogs/panel-animation.xml | 30 +++++++++--- src/app.cpp | 2 +- src/app_layout.cpp | 1 + src/canvas.cpp | 6 +++ src/canvas.h | 3 +- src/canvas_layer.cpp | 6 +++ src/canvas_layer.h | 1 + src/node_canvas.cpp | 6 +-- src/node_combobox.cpp | 5 ++ src/node_combobox.h | 1 + src/node_panel_animation.cpp | 78 ++++++++++++++++++++++++++------ src/node_panel_animation.h | 6 +++ 12 files changed, 120 insertions(+), 25 deletions(-) diff --git a/data/dialogs/panel-animation.xml b/data/dialogs/panel-animation.xml index 8d4bfe4..969dbab 100644 --- a/data/dialogs/panel-animation.xml +++ b/data/dialogs/panel-animation.xml @@ -20,7 +20,7 @@ - + @@ -28,28 +28,38 @@ - + - - + + + + - + + + + + + + + + @@ -63,10 +73,16 @@ + + + + - - + + + + diff --git a/src/app.cpp b/src/app.cpp index 6bc384d..12c06bd 100644 --- a/src/app.cpp +++ b/src/app.cpp @@ -562,7 +562,7 @@ bool App::update_ui_observer(Node *n) n->handle_on_screen(false, true); n->m_on_screen = true; } - glm::ivec4 c = glm::vec4(box.x - 1, (height / zoom - box.y - box.w - 1), box.z + 2, box.w + 2) * zoom; + glm::ivec4 c = glm::vec4(box.x /*- 1*/, (height / zoom - box.y - box.w /*- 1*/), box.z /*+ 2*/, box.w /*+ 2*/) * zoom; glScissor(floorf(c.x + off_x), floorf(c.y + off_y), ceilf(c.z), ceilf(c.w)); n->draw(); return true; diff --git a/src/app_layout.cpp b/src/app_layout.cpp index 51cf626..38a0509 100644 --- a/src/app_layout.cpp +++ b/src/app_layout.cpp @@ -1447,6 +1447,7 @@ void App::initLayout() //layout_designer[main_id]->add_child(layout_designer.instantiate("tpl-panel-animation")); auto p = layout_designer[main_id]->add_child(); p->SetPosition(300, 300); + p->SetSize(600, 400); p->m_container->add_child(); }; //layout_designer.load("data/dialogs/panel-animation.xml"); diff --git a/src/canvas.cpp b/src/canvas.cpp index eee3c89..3e5d673 100644 --- a/src/canvas.cpp +++ b/src/canvas.cpp @@ -1358,6 +1358,12 @@ void Canvas::anim_goto_next() noexcept anim_goto_frame((m_anim_frame + 1) % anim_duration()); } +void Canvas::anim_goto_prev() noexcept +{ + int k = anim_duration(); + anim_goto_frame((m_anim_frame - 1 + k) % k); +} + void Canvas::flood_fill(int layer, int plane, std::vector pos, FloodData& plane_data, float threshold, glm::vec4 dest_color, std::unique_ptr& source_color) { diff --git a/src/canvas.h b/src/canvas.h index d75d40d..091eefa 100644 --- a/src/canvas.h +++ b/src/canvas.h @@ -112,7 +112,7 @@ public: std::unique_ptr m_dual_stroke; bool m_show_tmp = false; std::vector> m_layers; - int m_anim_frame = 1; + int m_anim_frame = 0; Layer m_layers_merge; std::vector m_plane_shape[6]; // screen space projection of the plane glm::mat4 m_plane_unproject[6] = SIXPLETTE(glm::mat4(1)); @@ -189,6 +189,7 @@ public: int anim_duration() const noexcept; void anim_goto_frame(int frame) noexcept; void anim_goto_next() noexcept; + void anim_goto_prev() noexcept; void flood_fill(int layer, int plane, std::vector pos, FloodData& plane_data, float threshold, glm::vec4 dest_color, std::unique_ptr& source_color); void stroke_start(glm::vec3 point, float pressure); diff --git a/src/canvas_layer.cpp b/src/canvas_layer.cpp index b728060..84946f6 100644 --- a/src/canvas_layer.cpp +++ b/src/canvas_layer.cpp @@ -238,6 +238,12 @@ bool Layer::add_frame() return m_frames.back().create(w, h); } +void Layer::remove_frame(int frame) +{ + m_frames.erase(m_frames.begin() + frame); + m_frame_index = glm::clamp(m_frame_index, 0, (int)m_frames.size() - 1); +} + int Layer::total_duration() const noexcept { int duration = 0; diff --git a/src/canvas_layer.h b/src/canvas_layer.h index 7ff3c92..d773620 100644 --- a/src/canvas_layer.h +++ b/src/canvas_layer.h @@ -61,6 +61,7 @@ public: void resize(int width, int height); bool create(int width, int height, std::string name); bool add_frame(); + void remove_frame(int frame); 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_canvas.cpp b/src/node_canvas.cpp index 553b311..0741cef 100644 --- a/src/node_canvas.cpp +++ b/src/node_canvas.cpp @@ -214,10 +214,10 @@ void NodeCanvas::draw() auto layer_index = i; for (int plane_index = 0; plane_index < 6; plane_index++) { - int onion_size = 1; + int onion_size = App::I->animation->get_onion_size(); int frame_current = m_canvas->m_layers[layer_index]->m_frame_index; - int frame_start = glm::max(frame_current - 1, 0); - int frame_end = glm::min(frame_current + 1, m_canvas->m_layers[layer_index]->m_frames.size() - 1); + int frame_start = glm::max(frame_current - onion_size, 0); + int frame_end = glm::min(frame_current + onion_size, m_canvas->m_layers[layer_index]->m_frames.size() - 1); bool faces = false; for (int frame = frame_start; frame <= frame_end; frame++) faces |= m_canvas->m_layers[layer_index]->face(plane_index, frame); diff --git a/src/node_combobox.cpp b/src/node_combobox.cpp index 6a4b813..7fba2fb 100644 --- a/src/node_combobox.cpp +++ b/src/node_combobox.cpp @@ -119,3 +119,8 @@ float NodeComboBox::get_float() const noexcept { return std::stof(m_data[m_current_index]); } + +int NodeComboBox::get_int() const noexcept +{ + return std::stoi(m_data[m_current_index]); +} diff --git a/src/node_combobox.h b/src/node_combobox.h index 60ef833..6b0edcd 100644 --- a/src/node_combobox.h +++ b/src/node_combobox.h @@ -16,4 +16,5 @@ public: void set_index(int index); float get_float(int index) const noexcept; float get_float() const noexcept; + int get_int() const noexcept; }; diff --git a/src/node_panel_animation.cpp b/src/node_panel_animation.cpp index 4ea0235..08becf0 100644 --- a/src/node_panel_animation.cpp +++ b/src/node_panel_animation.cpp @@ -38,11 +38,17 @@ void NodePanelAnimation::init_controls() btn_prev = find("btn-prev"); btn_play = find("btn-play"); m_fps = find("fps"); + m_onion = find("onion"); + m_frame_label = find("frame-index"); btn_add->on_click = [this](Node*) { Canvas::I->layer().add_frame(); load_layers(); }; + btn_remove->on_click = [this](Node*) { + Canvas::I->layer_with_id(m_selected_frame_layer_id)->remove_frame(m_selected_frame_index); + load_layers(); + }; btn_up->on_click = [this](Node*) { if (auto layer = Canvas::I->layer_with_id(m_selected_frame_layer_id)) layer->m_frames[m_selected_frame_index].m_duration = @@ -56,12 +62,24 @@ void NodePanelAnimation::init_controls() load_layers(); }; + m_onion->on_select = [this] (Node* target, int index) { + m_timeline->m_onion_size = m_onion->get_int(); + }; + m_timeline->on_frame_changed = [this] (NodeAnimationTimeline* target, int frame) { LOG("goto frame %d", frame); Canvas::I->anim_goto_frame(frame); load_layers(); }; + btn_next->on_click = [this] (Node* target) { + Canvas::I->anim_goto_next(); + load_layers(); + }; + btn_prev->on_click = [this](Node* target) { + Canvas::I->anim_goto_prev(); + load_layers(); + }; btn_play->on_click = [this] (Node* target) { static auto mode = Canvas::I->m_current_mode; auto b = static_cast(target); @@ -90,7 +108,11 @@ void NodePanelAnimation::load_layers() m_frames_container->remove_all_children(); auto& layers = Canvas::I->m_layers; m_selected_frame = nullptr; - float max_width = 0; + + float max_width = find("hscroll")->GetWidth() - 2; + for (int i = 0; i < layers.size(); i++) + max_width = glm::max(max_width, layers[i]->total_duration() * 35.f); + for (int i = 0; i < layers.size(); i++) { auto l = m_layers_container->add_child(); @@ -98,8 +120,8 @@ void NodePanelAnimation::load_layers() l->set_selected(Canvas::I->m_current_layer_idx == i); l->set_chekcbox(layers[i]->m_visible); auto film = m_frames_container->add_child_ref(); - film->SetWidth(layers[i]->total_duration() * 35.f); - max_width = glm::max(max_width, layers[i]->total_duration() * 35.f); + //film->m_color = glm::vec4(glm::vec3(i % 2 ? .8 : .7), 1); + film->SetWidth(max_width - 5); for (int fi = 0; fi < layers[i]->m_frames.size(); fi++) { auto b = film->add_frame(layers[i]->m_frames[fi].m_duration); @@ -118,11 +140,35 @@ void NodePanelAnimation::load_layers() 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)); }; } } - m_timeline->SetWidth(max_width); + m_timeline->SetWidth(max_width - 4); + m_timeline->m_frame = Canvas::I->m_anim_frame; + m_timeline->m_onion_size = m_onion->get_int(); + update_frames(); +} + +void NodePanelAnimation::update_frames() +{ + int total_frames = Canvas::I->anim_duration(); + int digits = (int)floor(glm::log(total_frames)); + m_frame_label->set_text_format("%0*d/%d", digits, m_timeline->m_frame + 1, total_frames); +} + +void NodePanelAnimation::handle_resize(glm::vec2 old_size, glm::vec2 new_size, float zoom) +{ + parent::handle_resize(old_size, new_size, zoom); + auto& layers = Canvas::I->m_layers; + float max_width = find("hscroll")->GetWidth() - 2; + for (int i = 0; i < layers.size(); i++) + max_width = glm::max(max_width, layers[i]->total_duration() * 35.f); + for (auto& film : m_frames_container->m_children) + film->SetWidth(max_width - 5); + m_timeline->SetWidth(max_width - 4); } void NodePanelAnimation::on_tick(float dt) @@ -136,6 +182,7 @@ void NodePanelAnimation::on_tick(float dt) m_playback_timer = 0; Canvas::I->anim_goto_next(); m_timeline->m_frame = Canvas::I->m_anim_frame; + update_frames(); } } } @@ -181,17 +228,12 @@ void NodeAnimationLayer::draw() parent::draw(); } -////////////////////////////////////////////////////////////////////////// - - - ////////////////////////////////////////////////////////////////////////// void NodeAnimationTimeline::draw() { parent::draw(); ShaderManager::use(kShader::Color); - ShaderManager::u_vec4(kShaderUniform::Col, m_cursor_color); glDisable(GL_BLEND); float step = 35.f; @@ -199,21 +241,31 @@ void NodeAnimationTimeline::draw() m_pos.x + step * m_frame + step * 0.5f, m_pos.y + m_size.y * 0.5f }; + + ShaderManager::u_vec4(kShaderUniform::Col, glm::vec4(glm::vec3(m_cursor_color) * 0.5f, 1.f)); + ShaderManager::u_mat4(kShaderUniform::MVP, m_proj * glm::translate(glm::vec3(cur_pos, 0)) - * glm::scale(glm::vec3(step * 0.25f, m_size.y * 0.5f, 1)) + * glm::scale(glm::vec3(step * m_onion_size * 2.f, m_size.y * 0.5f, 1)) ); m_plane.draw_fill(); - //bool scissor = glIsEnabled(GL_SCISSOR_TEST); - //glDisable(GL_SCISSOR_TEST); + ShaderManager::u_vec4(kShaderUniform::Col, m_cursor_color); + + ShaderManager::u_mat4(kShaderUniform::MVP, m_proj + * glm::translate(glm::vec3(cur_pos, 0)) + * glm::scale(glm::vec3(step * 0.25f, m_size.y * 0.75f, 1)) + ); + m_plane.draw_fill(); + +/* ShaderManager::u_mat4(kShaderUniform::MVP, m_proj * glm::translate(glm::vec3(cur_pos, 0)) * glm::scale(glm::vec3(step * 0.15f, m_size.y * 0.5f, 1)) * glm::translate(glm::vec3(0, .5, 0)) ); m_plane.draw_fill(); - //scissor ? glEnable(GL_SCISSOR_TEST) : glDisable(GL_SCISSOR_TEST); +*/ } kEventResult NodeAnimationTimeline::handle_event(Event* e) diff --git a/src/node_panel_animation.h b/src/node_panel_animation.h index af26936..a54e18d 100644 --- a/src/node_panel_animation.h +++ b/src/node_panel_animation.h @@ -33,6 +33,7 @@ public: int m_frames_count = 1; int m_frame = 0; + int m_onion_size = 1; glm::vec4 m_cursor_color = { 1, 0, 0, 1 }; virtual Node* clone_instantiate() const override { return new this_class; } @@ -57,6 +58,8 @@ class NodePanelAnimation : public Node NodeAnimationFrame* m_selected_frame = nullptr; NodeAnimationTimeline* m_timeline = nullptr; NodeComboBox* m_fps = nullptr; + NodeComboBox* m_onion = nullptr; + NodeText* m_frame_label = nullptr; int m_selected_frame_index = -1; uint32_t m_selected_frame_layer_id = 0; float m_playback_timer = 0; @@ -69,9 +72,12 @@ public: virtual void init() override; virtual void added(Node* parent) override; virtual void on_tick(float dt) override; + virtual void handle_resize(glm::vec2 old_size, glm::vec2 new_size, float zoom) override; void init_controls(); void load_layers(); + void update_frames(); + int get_onion_size() const noexcept { return m_onion->get_int(); } }; //////////////////////////////////////////////////////////////////////////