#include "pch.h" #include "log.h" #include "node_panel_layer.h" #include "canvas.h" #include "node_combobox.h" Node* NodeLayer::clone_instantiate() const { return new NodeLayer(); } void NodeLayer::clone_children(Node* dest) const { NodeBorder::clone_children(dest); NodeLayer* n = static_cast(dest); n->m_label = n->find("label"); n->m_visibility = n->find("cb"); } void NodeLayer::clone_copy(Node* dest) const { NodeBorder::clone_copy(dest); NodeLayer* n = (NodeLayer*)dest; n->m_selected = m_selected; n->m_label_text = m_label_text; } void NodeLayer::init() { const auto& m_template = (NodeBorder*)init_template("tpl-layer"); m_color = m_template->m_color; m_border_color = m_template->m_border_color; m_thinkness = m_template->m_thinkness; m_label = find("label"); m_visibility = find("cb"); } void NodeLayer::parse_attributes(kAttribute ka, const tinyxml2::XMLAttribute* attr) { NodeBorder::parse_attributes(ka, attr); switch (ka) { case kAttribute::Text: m_label_text = attr->Value(); break; case kAttribute::Selected: m_selected = attr->BoolValue(); default: break; } } void NodeLayer::loaded() { NodeBorder::loaded(); if (!m_label_text.empty()) m_label->set_text(m_label_text.c_str()); m_visibility->on_value_changed = [this](Node*, bool checked) { if (on_visibility_changed) on_visibility_changed(this, checked); }; } kEventResult NodeLayer::handle_event(Event* e) { NodeBorder::handle_event(e); switch (e->m_type) { case kEventType::MouseEnter: break; case kEventType::MouseLeave: break; case kEventType::MouseDownL: m_selected = true; if (on_selected) on_selected(this); if (on_highlight) on_highlight(this, true); mouse_capture(); break; case kEventType::MouseUpL: if (on_highlight) on_highlight(this, false); mouse_release(); break; default: return kEventResult::Available; break; } return kEventResult::Consumed; } void NodeLayer::draw() { auto c = m_selected ? m_color_selected : m_color_normal; m_thinkness = m_selected ? 1.f : 0.f; m_color = m_mouse_inside ? m_color_hover : c; NodeBorder::draw(); } void NodeLayer::set_name(const char* s) { m_label_text = s; m_label->set_text(s); } Node* NodePanelLayer::clone_instantiate() const { return new NodePanelLayer(); } void NodePanelLayer::init() { init_template("tpl-panel-layers"); m_layers_container = find("layers-container"); btn_add = find("btn-add"); btn_remove = find("btn-remove"); btn_up = find("btn-up"); btn_down = find("btn-down"); btn_duplicate = find("btn-duplicate"); btn_duplicate->on_click = [this](Node*) { std::string next = m_current_layer->m_label_text + "01"; std::regex r(R"(([^\d]*)(\d+)$)"); std::smatch m; if (std::regex_search(m_current_layer->m_label_text, m, r)) { auto num = m[2].str(); int count = atoi(num.c_str()) + 1; char tmp[128]; sprintf(tmp, "%s%0*d", m[1].str().c_str(), num.length(), count); next = tmp; } int source_index = m_layers_container->get_child_index(m_current_layer); add_layer(next.c_str()); if (on_layer_duplicate) on_layer_duplicate(this, source_index); if (on_layer_change) on_layer_change(this, -1, m_layers_container->get_child_index(m_current_layer)); update_attributes(); }; btn_add->on_click = [this](Node*) { add_layer(); if (on_layer_add) on_layer_add(this); if (on_layer_change) on_layer_change(this, -1, m_layers_container->get_child_index(m_current_layer)); update_attributes(); }; btn_remove->on_click = [this](Node*) { if (m_layers.size() == 1) return; // dont' delete the last layer remove_layer(m_current_layer); }; btn_up->on_click = [this](Node*) { int old_idx = m_layers_container->get_child_index(m_current_layer); m_layers_container->move_child_offset(m_current_layer, -1); int new_idx = m_layers_container->get_child_index(m_current_layer); if (on_layer_order && old_idx != new_idx) { on_layer_order(this, old_idx, new_idx); } }; btn_down->on_click = [this](Node*) { int old_idx = m_layers_container->get_child_index(m_current_layer); m_layers_container->move_child_offset(m_current_layer, +1); int new_idx = m_layers_container->get_child_index(m_current_layer); if (on_layer_order && old_idx != new_idx) { on_layer_order(this, old_idx, new_idx); } }; m_opacity = find("opacity"); m_opacity->on_value_changed = [this](Node*, float value) { handle_layer_opacity(m_current_layer, value); }; m_alpha_lock = find("alpha-lock"); m_alpha_lock->on_value_changed = [this](Node*, bool locked) { handle_layer_alpha_lock(m_current_layer, locked); }; m_blend_mode = find("blend-mode"); m_blend_mode->on_select = [this](Node*, int index) { handle_layer_blend_mode(m_current_layer, index); }; } NodeLayer* NodePanelLayer::add_layer(const char* name) { NodeLayer* l = new NodeLayer; m_layers_container->add_child(l); l->init(); l->create(); l->loaded(); l->set_name(name); l->m_visibility->set_value(true); l->on_selected = std::bind(&NodePanelLayer::handle_layer_selected, this, std::placeholders::_1); l->on_visibility_changed = std::bind(&NodePanelLayer::handle_layer_visibility, this, std::placeholders::_1, std::placeholders::_2); l->on_highlight = std::bind(&NodePanelLayer::handle_layer_highlight, this, std::placeholders::_1, std::placeholders::_2); if (m_current_layer) m_current_layer->m_selected = false; m_current_layer = l; m_current_layer->m_selected = true; m_layers.push_back(l); update_attributes(); return l; } void NodePanelLayer::add_layer() { static char s[64]; sprintf(s, "Layer-%d", id_counter++); add_layer(s); } NodeLayer* NodePanelLayer::get_layer_at(int index) { return static_cast(m_layers_container->get_child_at(index)); } void NodePanelLayer::remove_layer(NodeLayer* layer) { auto it = std::find(m_layers.begin(), m_layers.end(), m_current_layer); auto i = m_layers_container->get_child_index(m_current_layer); int old_idx = i;// (int)std::distance(m_layers.begin(), it); m_layers_container->remove_child(m_current_layer); m_layers.erase(it); i = std::min(i, (int)m_layers.size() - 1); m_current_layer = (NodeLayer*)m_layers_container->get_child_at(i); m_current_layer->m_selected = true; if (on_layer_delete) on_layer_delete(this, old_idx); if (on_layer_change) on_layer_change(this, -1, i); update_attributes(); } void NodePanelLayer::handle_layer_opacity(NodeLayer* target, float value) { if (on_layer_opacity_changed) on_layer_opacity_changed(this, m_layers_container->get_child_index(target), value); } void NodePanelLayer::handle_layer_highlight(NodeLayer* target, bool highlight) { if (on_layer_highlight_changed) on_layer_highlight_changed(this, m_layers_container->get_child_index(target), highlight); } void NodePanelLayer::handle_layer_visibility(NodeLayer* target, bool visible) { if (on_layer_visibility_changed) on_layer_visibility_changed(this, m_layers_container->get_child_index(target), visible); } void NodePanelLayer::handle_layer_alpha_lock(NodeLayer* target, bool locked) { if (on_layer_alpha_lock_changed) on_layer_alpha_lock_changed(this, m_layers_container->get_child_index(target), locked); } void NodePanelLayer::handle_layer_blend_mode(NodeLayer* target, int mode) { if (on_layer_blend_mode_changed) on_layer_blend_mode_changed(this, m_layers_container->get_child_index(target), mode); } void NodePanelLayer::handle_layer_selected(NodeLayer* target) { if (m_current_layer) m_current_layer->m_selected = false; m_current_layer = target; m_current_layer->m_selected = true; if (on_layer_change) on_layer_change(this, -1, m_layers_container->get_child_index(m_current_layer)); update_attributes(); } void NodePanelLayer::clear() { m_layers_container->remove_all_children(); m_layers.clear(); m_current_layer = nullptr; } void NodePanelLayer::update_attributes() { auto& l = Canvas::I->m_layers[Canvas::I->m_current_layer_idx]; m_opacity->set_value(l->m_opacity); m_alpha_lock->set_value(l->m_alpha_locked); m_blend_mode->set_index(l->m_blend_mode); }