From 467e83b69e2bb66a786c99bc4d4db29b2ea19618 Mon Sep 17 00:00:00 2001 From: omigamedev Date: Fri, 18 Oct 2019 22:53:17 +0200 Subject: [PATCH] fix scroll node, improve animation panel --- data/dialogs/panel-animation.xml | 23 +++--- src/app.cpp | 6 +- src/node.cpp | 9 ++- src/node.h | 2 + src/node_panel_animation.cpp | 30 +++---- src/node_panel_animation.h | 33 +++++++- src/node_scroll.cpp | 134 +++++++++++++++++++++++-------- src/node_scroll.h | 6 +- 8 files changed, 176 insertions(+), 67 deletions(-) diff --git a/data/dialogs/panel-animation.xml b/data/dialogs/panel-animation.xml index 1b71df1..31fd38d 100644 --- a/data/dialogs/panel-animation.xml +++ b/data/dialogs/panel-animation.xml @@ -15,21 +15,26 @@ - - - - - + + + + + + + - - - - + + + + + + + diff --git a/src/app.cpp b/src/app.cpp index 0b4fc9f..d123b21 100644 --- a/src/app.cpp +++ b/src/app.cpp @@ -538,13 +538,15 @@ bool App::update_ui_observer(Node *n) float pl = YGNodeLayoutGetPadding(p->y_node, YGEdgeLeft); glm::vec2 off_p(pl, pt); glm::vec2 off_s(pr, pb); - glm::vec4 pclip = { xy(p->m_clip_uncut) + off_p, zw(p->m_clip_uncut) - off_s - off_p }; + glm::vec2 parent_offset = p->m_parent ? -p->m_parent->m_pos_offset_childred : glm::vec2(0.f); + glm::vec4 pclip = { xy(p->m_clip_uncut) + off_p, zw(p->m_clip_uncut) - off_s - off_p + parent_offset }; box = rect_intersection(box, pclip); p = p->m_parent; } //auto box = n->m_clip; //glm::ivec4 c = glm::vec4((int)box.x - 1, (int)(height / zoom - box.y - box.w) - 1, (int)box.z + 2, (int)box.w + 2) * zoom; - if (box.z <= 0.f || box.w <= 0.f) + glm::vec2 parent_offset = n->m_parent ? n->m_parent->m_pos_offset_childred : glm::vec2(0.f); + if (box.z <= parent_offset.x || box.w <= parent_offset.y) { if (n->m_on_screen) { diff --git a/src/node.cpp b/src/node.cpp index 2dfe695..d173fff 100644 --- a/src/node.cpp +++ b/src/node.cpp @@ -566,7 +566,12 @@ glm::vec4 Node::get_children_rect() const for (auto& c : m_children) { if (c->m_display) + { ret = rect_union(ret, c->m_clip_uncut); + auto r = c->get_children_rect(); + if (r.w > 0 && r.z > 0) + ret = rect_union(ret, r); + } } return ret; } @@ -1088,9 +1093,9 @@ void Node::update_internal(const glm::vec2& origin, const glm::mat4& proj, float float pl = YGNodeLayoutGetPadding(m_parent->y_node, YGEdgeLeft); glm::vec2 off_p(pl, pt); glm::vec2 off_s(pr, pb); - glm::vec4 pclip = { xy(m_parent->m_clip) + off_p, zw(m_parent->m_clip) - (off_s + off_p)}; + glm::vec4 pclip = { xy(m_parent->m_clip) + off_p, zw(m_parent->m_clip) - (off_s + off_p) }; m_clip_uncut = glm::vec4(m_pos - glm::vec2(1), m_size + glm::vec2(2)); - m_clip = rect_intersection(m_clip_uncut, m_parent->m_clip); + m_clip = rect_intersection(m_clip_uncut, m_parent->m_clip) + glm::vec4(0, 0, -parent_offset); } else { diff --git a/src/node.h b/src/node.h index 70e68d5..3583641 100644 --- a/src/node.h +++ b/src/node.h @@ -49,6 +49,7 @@ enum class kAttribute : uint16_t AutoSize = const_hash("autosize"), MouseCapture = const_hash("mouse-capture"), ScrollColor = const_hash("scroll-color"), + ScrollDir = const_hash("scroll-dir"), Multiline = const_hash("multiline"), TextAlign = const_hash("text-align"), TextVerticalAlign = const_hash("text-vertical-align"), @@ -116,6 +117,7 @@ public: glm::mat4 m_proj; glm::mat4 m_mvp; + glm::mat4 m_mvp_visible; bool m_mouse_focus = false; bool m_mouse_inside = false; bool m_flood_events = false; diff --git a/src/node_panel_animation.cpp b/src/node_panel_animation.cpp index 91eb1b0..15eee27 100644 --- a/src/node_panel_animation.cpp +++ b/src/node_panel_animation.cpp @@ -26,7 +26,8 @@ void NodePanelAnimation::init() void NodePanelAnimation::init_controls() { - m_container = find("container"); + m_layers_container = find("layers"); + m_frames_container = find("frames"); m_timeline = find("timeline"); btn_add = find("btn-add"); btn_remove = find("btn-remove"); @@ -62,23 +63,30 @@ void NodePanelAnimation::load_layers() { if (!added_to_root()) return; - m_container->remove_all_children(); + m_layers_container->remove_all_children(); + m_frames_container->remove_all_children(); auto& layers = Canvas::I->m_layers; m_selected_frame = nullptr; + float max_width = 0; for (int i = 0; i < layers.size(); i++) { - auto l = m_container->add_child(); + auto l = m_layers_container->add_child(); l->set_text(layers[i]->m_name); 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); for (int fi = 0; fi < layers[i]->m_frames.size(); fi++) { - auto b = l->add_frame(layers[i]->m_frames[fi].m_duration); + auto b = film->add_frame(layers[i]->m_frames[fi].m_duration); + if (m_selected_frame_layer_id == layers[i]->id && m_selected_frame_index == fi) { b->set_active(true); m_selected_frame = b.get(); } + b->on_click = [this, fi, lid=layers[i]->id, i] (Node* target) { auto frame = static_cast(target); if (m_selected_frame) @@ -91,6 +99,7 @@ void NodePanelAnimation::load_layers() }; } } + m_timeline->SetWidth(max_width); } void NodePanelAnimation::added(Node* parent) @@ -124,7 +133,6 @@ void NodeAnimationLayer::init_controls() { m_label = find("label"); m_visibility = find("cb"); - m_container = find("container"); } void NodeAnimationLayer::draw() @@ -135,15 +143,9 @@ void NodeAnimationLayer::draw() parent::draw(); } -std::shared_ptr NodeAnimationLayer::add_frame(int duration) -{ - auto b = m_container->add_child_ref(); - b->SetWidth(30 * duration + 5 * (duration - 1)); - //b->SetFlexGrow(duration); - b->SetHeightP(100); - b->SetMargin(0, 5, 0, 0); - return b; -} +////////////////////////////////////////////////////////////////////////// + + ////////////////////////////////////////////////////////////////////////// diff --git a/src/node_panel_animation.h b/src/node_panel_animation.h index 931ae41..5c2864f 100644 --- a/src/node_panel_animation.h +++ b/src/node_panel_animation.h @@ -48,7 +48,8 @@ class NodePanelAnimation : public Node NodeButtonCustom* btn_up = nullptr; NodeButtonCustom* btn_down = nullptr; NodeButtonCustom* btn_duplicate = nullptr; - NodeScroll* m_container = nullptr; + Node* m_layers_container = nullptr; + Node* m_frames_container = nullptr; NodeAnimationFrame* m_selected_frame = nullptr; NodeAnimationTimeline* m_timeline = nullptr; int m_selected_frame_index = -1; @@ -68,6 +69,32 @@ public: ////////////////////////////////////////////////////////////////////////// +class NodeAnimationFilm : public NodeBorder +{ +public: + using this_class = NodeAnimationFilm; + using parent = NodeBorder; + + virtual Node* clone_instantiate() const override { return new this_class; } + virtual void init() override + { + parent::init(); + init_template_file("data/dialogs/panel-animation.xml", "tpl-film"); + } + + std::shared_ptr add_frame(int duration) + { + auto b = add_child_ref(); + b->SetWidth(30 * duration + 5 * (duration - 1)); + //b->SetFlexGrow(duration); + b->SetHeightP(100); + b->SetMargin(0, 5, 0, 0); + return b; + } +}; + +////////////////////////////////////////////////////////////////////////// + class NodeAnimationLayer : public NodeBorder { bool m_selected = false; @@ -76,7 +103,6 @@ class NodeAnimationLayer : public NodeBorder glm::vec4 m_color_hover = glm::vec4(.5, .5, .5, 1); NodeText* m_label = nullptr; NodeCheckBox* m_visibility = nullptr; - NodeScroll* m_container = nullptr; public: std::function on_selected; std::function on_visibility_changed; @@ -91,8 +117,7 @@ public: virtual void draw() override; void init_controls(); - std::shared_ptr add_frame(int duration); void set_text(const std::string& text) { m_label->set_text(text.c_str()); } void set_selected(bool selected) { m_selected = selected; } void set_chekcbox(bool checked) { m_visibility->set_value(checked); } -}; \ No newline at end of file +}; diff --git a/src/node_scroll.cpp b/src/node_scroll.cpp index a63d1f0..aa72aca 100644 --- a/src/node_scroll.cpp +++ b/src/node_scroll.cpp @@ -4,14 +4,6 @@ #include "event.h" #include "shader.h" -NodeScroll::NodeScroll() -{ - m_drag_start = glm::vec2(0); - m_offset_start = glm::vec2(0); - m_offset = glm::vec2(0); - m_mask = glm::vec2(0, 1); -} - Node* NodeScroll::clone_instantiate() const { return new NodeScroll; @@ -22,8 +14,15 @@ void NodeScroll::fix_scroll() auto pad = GetPadding(); glm::vec2 padoff = { pad.y + pad.w, pad.x + pad.z }; auto rect = get_children_rect(); - m_offset = glm::clamp(m_offset, - zw(rect) + zw(m_clip_uncut) - padoff, { 0, 0 }); - m_pos_offset_childred = m_offset; + if (rect.w > 0 && rect.z > 0) + { + m_offset = glm::clamp(m_offset, -zw(rect) + zw(m_clip_uncut) - padoff, { 0, 0 }); + m_pos_offset_childred = m_offset; + } + else + { + m_pos_offset_childred = m_offset = { 0, 0 }; + } } void NodeScroll::clone_copy(Node* dest) const @@ -31,6 +30,8 @@ void NodeScroll::clone_copy(Node* dest) const NodeBorder::clone_copy(dest); auto n = static_cast(dest); n->m_scrollbar_color = m_scrollbar_color; + n->m_mask = m_mask; + n->m_direction = m_direction; } void NodeScroll::parse_attributes(kAttribute ka, const tinyxml2::XMLAttribute* attr) @@ -48,6 +49,18 @@ void NodeScroll::parse_attributes(kAttribute ka, const tinyxml2::XMLAttribute* a m_scrollbar_color = col; break; } + case kAttribute::ScrollDir: + if (strcmpi(attr->Value(), "vertical") == 0 || strcmpi(attr->Value(), "v") == 0) + { + m_direction = kScrollDirection::Vertical; + m_mask = { 0, 1 }; + } + else if (strcmpi(attr->Value(), "horizontal") == 0 || strcmpi(attr->Value(), "h") == 0) + { + m_direction = kScrollDirection::Horizontal; + m_mask = { 1, 0 }; + } + break; default: break; } @@ -57,13 +70,33 @@ void NodeScroll::on_tick(float dt) { auto pad = GetPadding(); auto rect = get_children_rect(); - // fix scrollbar - float sz = m_size.y - (pad[0] + pad[2]); - float new_pad = rect.w == 0 || rect.w <= sz + 2 ? 5 : 35; - if (pad[1] != new_pad) + if (rect.w > 0 && rect.z > 0) { - YGNodeStyleSetPadding(y_node, YGEdgeRight, new_pad); - app_redraw(); + // fix scrollbar + if (m_direction == kScrollDirection::Vertical) + { + float szv = m_size.y - (pad[0] + pad[2]); + float new_padv = rect.w == 0 || rect.w <= szv + 2 ? 5 : 35; + if (pad[1] != new_padv) + { + YGNodeStyleSetPadding(y_node, YGEdgeRight, new_padv); + app_redraw(); + } + } + else + { + float szh = m_size.x - (pad[3] + pad[1]); + float new_padh = rect.z == 0 || rect.z <= szh + 2 ? 5 : 35; + if (pad[2] != new_padh) + { + YGNodeStyleSetPadding(y_node, YGEdgeBottom, new_padh); + app_redraw(); + } + } + } + else + { + SetPadding(0, 0, 0, 0); } } @@ -71,21 +104,42 @@ void NodeScroll::draw() { NodeBorder::draw(); fix_scroll(); + glm::vec4 rect = get_children_rect(); glm::vec4 pad = GetPadding(); - float sz = m_size.y - (pad[0] + pad[2]); - float h = glm::max(30.f, sz / rect.w * sz); - float offset_percent = m_offset.y / (rect.w - sz); - float pr = YGNodeLayoutGetPadding(y_node, YGEdgeRight) - 5; - glDisable(GL_BLEND); - ShaderManager::use(kShader::Color); - ShaderManager::u_mat4(kShaderUniform::MVP, m_proj - * glm::translate(glm::vec3(m_pos.x + m_size.x - pr, m_pos.y - offset_percent * (sz - h) + pad[0], 0)) - * glm::scale(glm::vec3(pr, h, 1)) - * glm::translate(glm::vec3(.5, .5, 0)) - ); - ShaderManager::u_vec4(kShaderUniform::Col, m_scrollbar_color); - m_plane.draw_fill(); + + if (rect.w > 0 && rect.z > 0) + { + glDisable(GL_BLEND); + ShaderManager::use(kShader::Color); + + if (m_direction == kScrollDirection::Vertical) + { + float sz = m_size.y - (pad[0] + pad[2]); + float h = glm::max(30.f, sz / rect.w * sz); + float offset_percent = m_offset.y / (rect.w - sz); + float pr = YGNodeLayoutGetPadding(y_node, YGEdgeRight) - 5; + ShaderManager::u_mat4(kShaderUniform::MVP, m_proj + * glm::translate(glm::vec3(m_pos.x + m_size.x - pr, m_pos.y - offset_percent * (sz - h) + pad[0], 0)) + * glm::scale(glm::vec3(pr, h, 1)) + * glm::translate(glm::vec3(.5, .5, 0)) + ); + } + else + { + float sz = m_size.x - (pad[3] + pad[1]); + float h = glm::max(30.f, sz / rect.z * sz); + float offset_percent = m_offset.x / (rect.z - sz); + float pr = YGNodeLayoutGetPadding(y_node, YGEdgeBottom) - 5; + ShaderManager::u_mat4(kShaderUniform::MVP, m_proj + * glm::translate(glm::vec3(m_pos.x - offset_percent * (sz - h) + pad[3], m_pos.y + m_size.y - pr, 0)) + * glm::scale(glm::vec3(h, pr, 1)) + * glm::translate(glm::vec3(.5, .5, 0)) + ); + } + ShaderManager::u_vec4(kShaderUniform::Col, m_scrollbar_color); + m_plane.draw_fill(); + } } kEventResult NodeScroll::handle_event(Event* e) @@ -101,7 +155,10 @@ kEventResult NodeScroll::handle_event(Event* e) m_drag_start = me->m_pos; m_offset_start = m_offset; // if click on the scroll area use scrolling direction, otherwise natural - m_scroll_dir = (me->m_pos.x - m_pos.x) > (m_size.x - YGNodeLayoutGetPadding(y_node, YGEdgeRight)) ? -1 : 1; + if (m_direction == kScrollDirection::Vertical) + m_drag_dir = (me->m_pos.x - m_pos.x) > (m_size.x - YGNodeLayoutGetPadding(y_node, YGEdgeRight)) ? -1 : 1; + else + m_drag_dir = (me->m_pos.y - m_pos.y) > (m_size.y - YGNodeLayoutGetPadding(y_node, YGEdgeBottom)) ? -1 : 1; mouse_capture(); break; case kEventType::MouseMove: @@ -109,9 +166,20 @@ kEventResult NodeScroll::handle_event(Event* e) { glm::vec4 rect = get_children_rect(); glm::vec4 pad = GetPadding(); - float speed = m_scroll_dir < 0 ? rect.w / (m_size.y - (pad[0] + pad[2])) : 1; - m_offset = m_offset_start + (me->m_pos - m_drag_start) * m_mask * m_scroll_dir * speed; - fix_scroll(); + if (rect.w > 0 && rect.z > 0) + { + if (m_direction == kScrollDirection::Vertical) + { + float speed = m_drag_dir < 0 ? rect.w / (m_size.y - (pad[0] + pad[2])) : 1; + m_offset = m_offset_start + (me->m_pos - m_drag_start) * m_mask * m_drag_dir * speed; + } + else + { + float speed = m_drag_dir < 0 ? rect.z / (m_size.x - (pad[3] + pad[1])) : 1; + m_offset = m_offset_start + (me->m_pos - m_drag_start) * m_mask * m_drag_dir * speed; + } + fix_scroll(); + } } break; case kEventType::MouseUpL: diff --git a/src/node_scroll.h b/src/node_scroll.h index 96f33b5..725c5ec 100644 --- a/src/node_scroll.h +++ b/src/node_scroll.h @@ -4,14 +4,14 @@ class NodeScroll : public NodeBorder { bool m_dragging = false; - float m_scroll_dir = 1.f; + float m_drag_dir = 1.f; glm::vec2 m_drag_start = glm::vec2(0); glm::vec2 m_offset_start = glm::vec2(0); glm::vec2 m_offset = glm::vec2(0); - glm::vec2 m_mask = glm::vec2(1, 0); + glm::vec2 m_mask = glm::vec2(0, 1); glm::vec4 m_scrollbar_color = { .3, .3, .3, 1 }; public: - NodeScroll(); + enum class kScrollDirection : uint8_t { Vertical, Horizontal } m_direction; virtual Node* clone_instantiate() const override; virtual void clone_copy(Node* dest) const override; virtual kEventResult handle_event(Event* e) override;