290 lines
8.9 KiB
C++
290 lines
8.9 KiB
C++
#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<NodeLayer*>(dest);
|
|
n->m_label = n->find<NodeText>("label");
|
|
n->m_visibility = n->find<NodeCheckBox>("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<NodeText>("label");
|
|
m_visibility = find<NodeCheckBox>("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<NodeBorder>("layers-container");
|
|
btn_add = find<NodeButtonCustom>("btn-add");
|
|
btn_remove = find<NodeButtonCustom>("btn-remove");
|
|
btn_up = find<NodeButtonCustom>("btn-up");
|
|
btn_down = find<NodeButtonCustom>("btn-down");
|
|
btn_duplicate = find<NodeButtonCustom>("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<NodeSliderH>("opacity");
|
|
m_opacity->on_value_changed = [this](Node*, float value) {
|
|
handle_layer_opacity(m_current_layer, value);
|
|
};
|
|
m_alpha_lock = find<NodeCheckBox>("alpha-lock");
|
|
m_alpha_lock->on_value_changed = [this](Node*, bool locked) {
|
|
handle_layer_alpha_lock(m_current_layer, locked);
|
|
};
|
|
m_blend_mode = find<NodeComboBox>("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<NodeLayer*>(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<int>(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);
|
|
}
|