diff --git a/src/app_layout.cpp b/src/app_layout.cpp index ea7f1a5..7e0152f 100644 --- a/src/app_layout.cpp +++ b/src/app_layout.cpp @@ -508,7 +508,7 @@ void App::init_menu_file() { menu_file->on_click = [=](Node*) { glm::vec2 pos = menu_file->m_pos + glm::vec2(0, menu_file->m_size.y); - auto popup = (NodePopupMenu*)layout[const_hash("file-menu")]->m_children[0]->clone(); + auto popup = layout[const_hash("file-menu")]->m_children[0]->clone(); popup->update(); if (YGNodeStyleGetDirection(layout[main_id]->y_node) == YGDirectionRTL) pos.x = pos.x - popup->m_size.x + menu_file->m_size.x; @@ -613,7 +613,7 @@ void App::init_menu_file() if (auto b = popup->find("file-export-tick")) b->on_click = [this, b, popup](Node*) { glm::vec2 pos = b->m_pos + glm::vec2(b->m_size.x, 0); - auto subpopup = (NodePopupMenu*)layout[const_hash("file-submenu-export")]->m_children[0]->clone(); + auto subpopup = layout[const_hash("file-submenu-export")]->m_children[0]->clone(); subpopup->update(); if (YGNodeStyleGetDirection(layout[main_id]->y_node) == YGDirectionRTL) pos.x = pos.x - subpopup->m_size.x + b->m_size.x; @@ -688,7 +688,7 @@ void App::init_menu_edit() { menu_file->on_click = [=](Node*) { glm::vec2 pos = menu_file->m_pos + glm::vec2(0, menu_file->m_size.y); - auto popup = (NodePopupMenu*)layout[const_hash("edit-menu")]->m_children[0]->clone(); + auto popup = layout[const_hash("edit-menu")]->m_children[0]->clone(); popup->update(); if (YGNodeStyleGetDirection(layout[main_id]->y_node) == YGDirectionRTL) pos.x = pos.x - popup->m_size.x + menu_file->m_size.x; @@ -712,7 +712,7 @@ void App::init_menu_tools() { menu_exp->on_click = [this, menu_exp, main](Node*) { glm::vec2 pos = menu_exp->m_pos + glm::vec2(0, menu_exp->m_size.y); - auto popup_exp = (NodePopupMenu*)layout[const_hash("tools-menu")]->m_children[0]->clone(); + auto popup_exp = layout[const_hash("tools-menu")]->m_children[0]->clone(); popup_exp->update(); if (YGNodeStyleGetDirection(layout[main_id]->y_node) == YGDirectionRTL) pos.x = pos.x - popup_exp->m_size.x + menu_exp->m_size.x; @@ -730,7 +730,7 @@ void App::init_menu_tools() if (auto menu_time = popup_exp->find("tools-timelapse")) { glm::vec2 pos = b->m_pos + glm::vec2(b->m_size.x, 0); - auto popup_time = (NodePopupMenu*)layout[const_hash("timelapse-menu")]->m_children[0]->clone(); + auto popup_time = layout[const_hash("timelapse-menu")]->m_children[0]->clone(); popup_time->update(); if (YGNodeStyleGetDirection(layout[main_id]->y_node) == YGDirectionRTL) pos.x = pos.x - popup_time->m_size.x + b->m_size.x; @@ -776,7 +776,7 @@ void App::init_menu_tools() if (auto menu_time = popup_exp->find("tools-panels")) { glm::vec2 pos = b->m_pos + glm::vec2(b->m_size.x, 0); - auto popup_time = (NodePopupMenu*)layout[const_hash("panels-menu")]->m_children[0]->clone(); + auto popup_time = layout[const_hash("panels-menu")]->m_children[0]->clone(); popup_time->update(); if (YGNodeStyleGetDirection(layout[main_id]->y_node) == YGDirectionRTL) pos.x = pos.x - popup_time->m_size.x + b->m_size.x; @@ -1042,7 +1042,7 @@ void App::init_menu_about() { menu_file->on_click = [=](Node*) { glm::vec2 pos = menu_file->m_pos + glm::vec2(0, menu_file->m_size.y); - auto popup = (NodePopupMenu*)layout[const_hash("about-menu")]->m_children[0]->clone(); + auto popup = layout[const_hash("about-menu")]->m_children[0]->clone(); popup->update(); if (YGNodeStyleGetDirection(layout[main_id]->y_node) == YGDirectionRTL) pos.x = pos.x - popup->m_size.x + menu_file->m_size.x; @@ -1163,7 +1163,7 @@ void App::init_menu_layer() { menu_file->on_click = [=](Node*) { glm::vec2 pos = menu_file->m_pos + glm::vec2(0, menu_file->m_size.y); - auto popup = (NodePopupMenu*)layout[const_hash("layers-menu")]->m_children[0]->clone(); + auto popup = layout[const_hash("layers-menu")]->m_children[0]->clone(); popup->update(); if (YGNodeStyleGetDirection(layout[main_id]->y_node) == YGDirectionRTL) pos.x = pos.x - popup->m_size.x + menu_file->m_size.x; diff --git a/src/layout.cpp b/src/layout.cpp index a5c89b9..0bcb361 100644 --- a/src/layout.cpp +++ b/src/layout.cpp @@ -9,7 +9,7 @@ void LayoutManager::unload() { for (auto& l : m_layouts) - l.second->destroy_immediate(); + l.second->destroy(); m_layouts.clear(); } diff --git a/src/node.cpp b/src/node.cpp index 47b182b..297a3e2 100644 --- a/src/node.cpp +++ b/src/node.cpp @@ -61,17 +61,23 @@ void Node::destroy() m_destroyed = true; mouse_release(); key_release(); -} - -void Node::destroy_immediate() -{ - for (auto c : m_children) - c->destroy_immediate(); + for (auto& c : m_children) + c->destroy(); + for (auto p = m_parent; p; p = p->m_parent) + if (p->child_mouse_focus.get() == this) + p->child_mouse_focus = nullptr; + //App::I->ui_task([&] + //{ + // auto cp = m_children; + // for (auto& c : cp) + // c->destroy(); + // remove_all_children(); + // remove_from_parent(); + //}); } Node* Node::root() { - Node* ret = this; while (ret->m_parent) ret = ret->m_parent; @@ -137,7 +143,7 @@ kEventResult Node::on_event(Event* e) if (e->m_cat == kEventCategory::MouseEvent && child_mouse_focus.get() != it->get()) { MouseEvent* me = static_cast(e); - if (child_mouse_focus) + if (child_mouse_focus && !child_mouse_focus->m_destroyed) { MouseEvent e2 = *me; e2.m_type = kEventType::MouseUnfocus; @@ -147,8 +153,15 @@ kEventResult Node::on_event(Event* e) MouseEvent e2 = *me; e2.m_type = kEventType::MouseFocus; (*it)->handle_event(&e2); - child_mouse_focus = *it; - child_mouse_focus->m_mouse_focus = true; + if (!(*it)->m_destroyed) + { + child_mouse_focus = *it; + child_mouse_focus->m_mouse_focus = true; + } + //else + //{ + // child_mouse_focus = nullptr; + //} } ret = kEventResult::Consumed; break; @@ -298,7 +311,9 @@ void Node::added(Node* parent) void Node::removed(Node* parent) { - + for (auto p = m_parent; p; p = p->m_parent) + if (p->child_mouse_focus.get() == this) + p->child_mouse_focus = nullptr; } const Node* Node::init_template(const char* id) @@ -332,6 +347,7 @@ void Node::add_child(Node* n) m_children.emplace_back(n); n->m_parent = this; n->m_manager = m_manager; + n->m_destroyed = false; YGNodeInsertChild(y_node, n->y_node, YGNodeGetChildCount(y_node)); n->added(this); on_child_added(n); @@ -347,6 +363,7 @@ void Node::add_child(Node* n, int index) m_children.emplace_back(n); n->m_parent = this; n->m_manager = m_manager; + n->m_destroyed = false; YGNodeInsertChild(y_node, n->y_node, index); n->added(this); on_child_added(n); @@ -362,6 +379,7 @@ void Node::add_child(std::shared_ptr n) m_children.push_back(n); n->m_parent = this; n->m_manager = m_manager; + n->m_destroyed = false; YGNodeInsertChild(y_node, n->y_node, YGNodeGetChildCount(y_node)); n->added(this); on_child_added(n.get()); @@ -377,6 +395,7 @@ void Node::add_child(std::shared_ptr n, int index) m_children.insert(m_children.begin() + index, n); n->m_parent = this; n->m_manager = m_manager; + n->m_destroyed = false; YGNodeInsertChild(y_node, n->y_node, index); n->added(this); on_child_added(n.get()); @@ -1009,16 +1028,6 @@ void Node::update_internal(const glm::vec2& origin, const glm::mat4& proj, float m_mvp = proj * pos * scale * pivot * prescale; m_proj = proj; - for (int i = 0; i < m_children.size(); i++) - { - if (m_children[i]->m_destroyed) - { - m_children[i]->destroy_immediate(); - remove_child(m_children[i].get()); - i--; - } - } - if (m_size != old_size || m_zoom != zoom) { m_zoom = zoom; @@ -1029,6 +1038,9 @@ void Node::update_internal(const glm::vec2& origin, const glm::mat4& proj, float for (auto& c : m_children) c->update_internal(m_pos, proj, zoom); + + m_children.erase(std::remove_if(m_children.begin(), m_children.end(), + [](const auto& n) { return n->m_destroyed; }), m_children.end()); } void Node::tick(float dt) @@ -1334,15 +1346,6 @@ void Node::draw() } -Node* Node::clone() -{ - Node* n = clone_instantiate(); - clone_copy(n); - clone_children(n); - clone_finalize(n); - return n; -} - Node* Node::clone_instantiate() const { return new Node(); @@ -1384,8 +1387,8 @@ void Node::clone_children(Node* dest) const { for (auto& c : m_children) { - Node* cn = c->clone(); - dest->m_children.emplace_back(cn); + std::shared_ptr cn = c->clone(); + dest->m_children.push_back(cn); cn->m_parent = dest; cn->m_manager = dest->m_manager; cn->loaded(); diff --git a/src/node.h b/src/node.h index 2b25c5b..3ca96c4 100644 --- a/src/node.h +++ b/src/node.h @@ -195,16 +195,24 @@ public: virtual void parse_attributes(kAttribute ka, const tinyxml2::XMLAttribute* attr); void load_internal(const tinyxml2::XMLElement* x_node); virtual void draw(); - Node* clone(); virtual Node* clone_instantiate() const; virtual void clone_copy(Node* dest) const; virtual void clone_children(Node* dest) const; virtual void clone_finalize(Node* dest) const;; void watch(std::function observer); - void destroy(); - virtual void destroy_immediate(); + virtual void destroy(); Node* root(); + + template std::shared_ptr clone() + { + std::shared_ptr n = std::shared_ptr((T*)clone_instantiate()); + clone_copy(n.get()); + clone_children(n.get()); + clone_finalize(n.get()); + return n; + } + template T* find(const char* ids) { uint16_t id = const_hash(ids); diff --git a/src/node_about.cpp b/src/node_about.cpp index 4bd079d..ae4e875 100644 --- a/src/node_about.cpp +++ b/src/node_about.cpp @@ -14,7 +14,7 @@ void NodeAbout::init() SetWidthP(100); SetHeightP(100); SetPositioning(YGPositionTypeAbsolute); - m_template = (*m_manager)[const_hash("about")]->m_children[0]->clone(); + auto m_template = (*m_manager)[const_hash("about")]->m_children[0]->clone(); add_child(m_template); btn_ok = m_template->find("btn-ok"); btn_ok->on_click = [&](Node*) { destroy(); }; diff --git a/src/node_about.h b/src/node_about.h index efbdba2..ea77202 100644 --- a/src/node_about.h +++ b/src/node_about.h @@ -4,7 +4,6 @@ class NodeAbout : public Node { - Node* m_template; NodeButton* btn_ok; public: virtual Node* clone_instantiate() const override; diff --git a/src/node_canvas.cpp b/src/node_canvas.cpp index 1cf2194..a21d322 100644 --- a/src/node_canvas.cpp +++ b/src/node_canvas.cpp @@ -649,9 +649,8 @@ void NodeCanvas::on_tick(float dt) m_outline_pan = glm::fract(m_outline_pan + dt * 0.01f); } -void NodeCanvas::destroy_immediate() +void NodeCanvas::destroy() { - Node::destroy_immediate(); m_blender_rtt.destroy(); m_cache_rtt.destroy(); m_rtt.destroy(); @@ -659,4 +658,5 @@ void NodeCanvas::destroy_immediate() m_face_plane.destroy(); m_line.destroy(); m_grid.destroy(); + Node::destroy(); } diff --git a/src/node_canvas.h b/src/node_canvas.h index 9c45c6c..a067e40 100644 --- a/src/node_canvas.h +++ b/src/node_canvas.h @@ -27,7 +27,7 @@ public: virtual void draw() override; virtual void handle_resize(glm::vec2 old_size, glm::vec2 new_size, float zoom) override; virtual kEventResult handle_event(Event* e) override; - virtual void destroy_immediate() override; + virtual void destroy() override; virtual void on_tick(float dt) override; void reset_camera(); void create_buffers(); diff --git a/src/node_changelog.cpp b/src/node_changelog.cpp index de8bf14..0d41c85 100644 --- a/src/node_changelog.cpp +++ b/src/node_changelog.cpp @@ -14,7 +14,7 @@ void NodeChangelog::init() SetWidthP(100); SetHeightP(100); SetPositioning(YGPositionTypeAbsolute); - m_template = (*m_manager)[const_hash("changelog")]->m_children[0]->clone(); + auto m_template = (*m_manager)[const_hash("changelog")]->m_children[0]->clone(); add_child(m_template); btn_ok = m_template->find("btn-ok"); btn_ok->on_click = [&](Node*) { destroy(); }; diff --git a/src/node_changelog.h b/src/node_changelog.h index 1a981b1..53774ae 100644 --- a/src/node_changelog.h +++ b/src/node_changelog.h @@ -4,7 +4,6 @@ class NodeChangelog : public Node { - Node* m_template; NodeButton* btn_ok; public: virtual Node* clone_instantiate() const override; diff --git a/src/node_message_box.cpp b/src/node_message_box.cpp index d387159..b76780c 100644 --- a/src/node_message_box.cpp +++ b/src/node_message_box.cpp @@ -14,7 +14,7 @@ void NodeMessageBox::init() SetWidthP(100); SetHeightP(100); SetPositioning(YGPositionTypeAbsolute); - m_template = (*m_manager)[const_hash("message-box")]->m_children[0]->clone(); + auto m_template = (*m_manager)[const_hash("message-box")]->m_children[0]->clone(); add_child(m_template); m_title = m_template->find("title"); m_message = m_template->find("message"); diff --git a/src/node_message_box.h b/src/node_message_box.h index 95fede9..9e1a269 100644 --- a/src/node_message_box.h +++ b/src/node_message_box.h @@ -7,7 +7,6 @@ class NodeMessageBox : public Node { public: std::function on_submit = nullptr; - Node* m_template; NodeButton* btn_ok; NodeButton* btn_cancel; NodeText* m_message; diff --git a/src/node_settings.cpp b/src/node_settings.cpp index 28f0599..82bca93 100644 --- a/src/node_settings.cpp +++ b/src/node_settings.cpp @@ -14,7 +14,7 @@ void NodeSettings::init() SetWidthP(100); SetHeightP(100); SetPositioning(YGPositionTypeAbsolute); - m_template = (*m_manager)[const_hash("settings")]->m_children[0]->clone(); + auto m_template = (*m_manager)[const_hash("settings")]->m_children[0]->clone(); add_child(m_template); btnOk = m_template->find("btn-ok"); btnOk->on_click = [&](Node*) { destroy(); }; diff --git a/src/node_settings.h b/src/node_settings.h index 33f6039..914b6f3 100644 --- a/src/node_settings.h +++ b/src/node_settings.h @@ -4,7 +4,6 @@ class NodeSettings : public Node { - Node* m_template; NodeButton* btnOk; public: virtual Node* clone_instantiate() const override; diff --git a/src/node_stroke_preview.cpp b/src/node_stroke_preview.cpp index 0a14701..3923d33 100644 --- a/src/node_stroke_preview.cpp +++ b/src/node_stroke_preview.cpp @@ -589,10 +589,10 @@ void NodeStrokePreview::handle_resize(glm::vec2 old_size, glm::vec2 new_size, fl draw_stroke(); } -void NodeStrokePreview::destroy_immediate() +void NodeStrokePreview::destroy() { - Node::destroy_immediate(); m_tex_preview.destroy(); + Node::destroy(); } void NodeStrokePreview::handle_on_screen(bool old_visibility, bool new_visibility) diff --git a/src/node_stroke_preview.h b/src/node_stroke_preview.h index 85be498..43def90 100644 --- a/src/node_stroke_preview.h +++ b/src/node_stroke_preview.h @@ -54,6 +54,6 @@ public: void draw_stroke_immediate(); virtual void draw() override; virtual void handle_resize(glm::vec2 old_size, glm::vec2 new_size, float zoom) override; - virtual void destroy_immediate() override; + virtual void destroy() override; virtual void handle_on_screen(bool old_visibility, bool new_visibility) override; }; diff --git a/src/node_usermanual.cpp b/src/node_usermanual.cpp index 18121d8..fc87760 100644 --- a/src/node_usermanual.cpp +++ b/src/node_usermanual.cpp @@ -14,7 +14,7 @@ void NodeUserManual::init() SetWidthP(100); SetHeightP(100); SetPositioning(YGPositionTypeAbsolute); - m_template = (*m_manager)[const_hash("usermanual")]->m_children[0]->clone(); + auto m_template = (*m_manager)[const_hash("usermanual")]->m_children[0]->clone(); add_child(m_template); btn_ok = m_template->find("btn-ok"); btn_ok->on_click = [&](Node*) { destroy(); }; diff --git a/src/node_usermanual.h b/src/node_usermanual.h index a65828d..53b9e04 100644 --- a/src/node_usermanual.h +++ b/src/node_usermanual.h @@ -4,7 +4,6 @@ class NodeUserManual : public Node { - Node* m_template; NodeButton* btn_ok; public: virtual Node* clone_instantiate() const override;