326 lines
12 KiB
C++
326 lines
12 KiB
C++
#include "pch.h"
|
|
#include "node_panel_quick.h"
|
|
#include "node_stroke_preview.h"
|
|
#include "node_image.h"
|
|
#include "app.h"
|
|
|
|
Node* NodePanelQuick::clone_instantiate() const
|
|
{
|
|
return new this_class;
|
|
}
|
|
|
|
void NodePanelQuick::clone_finalize(Node* dest) const
|
|
{
|
|
parent::clone_finalize(dest);
|
|
auto n = static_cast<this_class*>(dest);
|
|
n->init_controls();
|
|
}
|
|
|
|
void NodePanelQuick::init()
|
|
{
|
|
parent::init();
|
|
init_template("tpl-panel-quick");
|
|
init_controls();
|
|
}
|
|
|
|
void NodePanelQuick::set_color(glm::vec3 color)
|
|
{
|
|
m_button_color_current_inner->m_color = glm::vec4(color, 1.f);
|
|
}
|
|
|
|
int NodePanelQuick::get_selected_brush_index() const
|
|
{
|
|
auto it = std::find(m_button_brushes.begin(), m_button_brushes.end(), m_button_brush_current);
|
|
return std::distance(m_button_brushes.begin(), it);
|
|
}
|
|
|
|
void NodePanelQuick::set_selected_brush_index(int idx, bool fire_event /*= false*/)
|
|
{
|
|
if (m_button_brush_current)
|
|
m_button_brush_current->set_active(false);
|
|
m_button_brush_current = m_button_brushes[idx];
|
|
m_button_brush_current->set_active(true);
|
|
m_button_brush_current_preview = static_cast<NodeStrokePreview*>(m_button_brush_current->m_children[0].get());
|
|
if (fire_event && on_brush_change)
|
|
on_brush_change(this, m_button_brush_current_preview->m_brush);
|
|
}
|
|
|
|
int NodePanelQuick::get_selected_color_index() const
|
|
{
|
|
auto it = std::find(m_button_colors.begin(), m_button_colors.end(), m_button_color_current);
|
|
return std::distance(m_button_colors.begin(), it);
|
|
}
|
|
|
|
void NodePanelQuick::set_selected_color_index(int idx, bool fire_event /*= false*/)
|
|
{
|
|
if (m_button_color_current)
|
|
m_button_color_current->set_active(false);
|
|
m_button_color_current = m_button_colors[idx];
|
|
m_button_color_current->set_active(true);
|
|
m_button_color_current_inner = static_cast<NodeBorder*>(m_button_color_current->m_children[0].get());
|
|
if (fire_event && on_color_change)
|
|
on_color_change(this, m_button_color_current_inner->m_color);
|
|
}
|
|
|
|
NodePanelQuick::MiniState NodePanelQuick::get_state() const
|
|
{
|
|
MiniState s;
|
|
s.brush_index = get_selected_brush_index();
|
|
s.color_index = get_selected_color_index();
|
|
for (int i = 0; i < 3; i++)
|
|
{
|
|
s.brushes[i] = static_cast<NodeStrokePreview*>(m_button_brushes[i]->m_children[0].get())->m_brush;
|
|
s.colors[i] = static_cast<NodeBorder*>(m_button_color_current->m_children[0].get())->m_color;
|
|
}
|
|
return s;
|
|
}
|
|
|
|
void NodePanelQuick::set_state(const MiniState& state, bool fire_event /*= false*/)
|
|
{
|
|
for (int i = 0; i < 3; i++)
|
|
{
|
|
auto b = static_cast<NodeStrokePreview*>(m_button_brushes[i]->m_children[0].get());
|
|
b->m_brush = state.brushes[i];
|
|
b->draw_stroke();
|
|
auto c = static_cast<NodeBorder*>(m_button_color_current->m_children[0].get());
|
|
c->m_color = state.colors[i];
|
|
}
|
|
set_selected_color_index(state.color_index, fire_event);
|
|
set_selected_brush_index(state.brush_index, fire_event);
|
|
}
|
|
|
|
void NodePanelQuick::reset_state(bool fire_event /*= false*/)
|
|
{
|
|
for (int i = 0; i < 3; i++)
|
|
{
|
|
auto b = static_cast<NodeStrokePreview*>(m_button_brushes[i]->m_children[0].get());
|
|
b->m_brush = std::make_shared<Brush>();
|
|
b->m_brush->load_tip("data/brushes/Round-Hard.png", "data/brushes/thumbs/Round-Hard.png");
|
|
b->draw_stroke();
|
|
auto c = static_cast<NodeBorder*>(m_button_color_current->m_children[0].get());
|
|
c->m_color = glm::vec4(0, 0, 0, 1);
|
|
}
|
|
set_selected_brush_index(0, fire_event);
|
|
set_selected_color_index(0, fire_event);
|
|
}
|
|
|
|
void NodePanelQuick::init_controls()
|
|
{
|
|
m_picker = std::make_shared<NodeColorPicker>();
|
|
m_picker->m_manager = m_manager;
|
|
m_picker->init();
|
|
m_picker->create();
|
|
m_picker->loaded();
|
|
m_picker->m_mouse_ignore = false;
|
|
m_picker->m_flood_events = true;
|
|
m_picker->m_capture_children = false;
|
|
m_picker->SetWidth(300);
|
|
|
|
m_slider_size = find<NodeSliderV>("quick-size");
|
|
m_slider_size->on_value_changed = [this](Node* target, float value) {
|
|
float off = m_slider_flow->m_pos.x > App::I.width / 2.f ? -100.f : 100.f;
|
|
auto newpos = (m_slider_flow->m_pos + glm::vec2(off, m_slider_flow->m_size.y / 2.f)) * App::I.zoom;
|
|
if (auto m = dynamic_cast<CanvasModePen*>(Canvas::I->modes[(int)Canvas::I->m_current_mode][0]))
|
|
{
|
|
m->m_cur_pos = newpos;
|
|
m->m_draw_tip = true;
|
|
m->m_draw_outline = false;
|
|
}
|
|
if (auto m = dynamic_cast<CanvasModeLine*>(Canvas::I->modes[(int)Canvas::I->m_current_mode][0]))
|
|
{
|
|
m->m_cur_pos = newpos;
|
|
m->m_draw_tip = true;
|
|
}
|
|
m_button_brush_current_preview->draw_stroke();
|
|
if (on_size_change)
|
|
on_size_change(target, value);
|
|
};
|
|
m_slider_flow = find<NodeSliderV>("quick-flow");
|
|
m_slider_flow->on_value_changed = [this](Node* target, float value) {
|
|
float off = m_slider_flow->m_pos.x > App::I.width / 2.f ? -100.f : 100.f;
|
|
auto newpos = (m_slider_flow->m_pos + glm::vec2(off, m_slider_flow->m_size.y / 2.f)) * App::I.zoom;
|
|
if (auto m = dynamic_cast<CanvasModePen*>(Canvas::I->modes[(int)Canvas::I->m_current_mode][0]))
|
|
{
|
|
m->m_cur_pos = newpos;
|
|
m->m_draw_tip = true;
|
|
m->m_draw_outline = false;
|
|
}
|
|
if (auto m = dynamic_cast<CanvasModeLine*>(Canvas::I->modes[(int)Canvas::I->m_current_mode][0]))
|
|
{
|
|
m->m_cur_pos = newpos;
|
|
m->m_draw_tip = true;
|
|
}
|
|
m_button_brush_current_preview->draw_stroke();
|
|
if (on_flow_change)
|
|
on_flow_change(target, value);
|
|
};
|
|
|
|
for (int i = 0; i < m_button_colors.size(); i++)
|
|
{
|
|
m_button_colors[i] = find<NodeButtonCustom>(fmt::format("quick-color{}", i + 1).c_str());
|
|
m_button_colors[i]->on_click = std::bind(&this_class::handle_button_color_click, this, std::placeholders::_1);
|
|
m_button_colors[i]->color_active = { 0, 0, 0, 0.5f };
|
|
m_button_colors[i]->set_color({ 0, 0, 0, 0 });
|
|
}
|
|
m_button_color_current = m_button_colors[0];
|
|
m_button_color_current->set_active(true);
|
|
m_button_color_current_inner = static_cast<NodeBorder*>(m_button_color_current->m_children[0].get());
|
|
|
|
for (int i = 0; i < m_button_brushes.size(); i++)
|
|
m_button_brushes[i] = init_button_brush(fmt::format("quick-brush{}", i + 1));
|
|
m_button_brush_current = m_button_brushes[0];
|
|
m_button_brush_current->set_active(true);
|
|
m_button_brush_current_preview = static_cast<NodeStrokePreview*>(m_button_brush_current->m_children[0].get());
|
|
}
|
|
|
|
NodeButtonCustom* NodePanelQuick::init_button_brush(const std::string& name)
|
|
{
|
|
auto button = find<NodeButtonCustom>(name.c_str());
|
|
button->on_click = std::bind(&this_class::handle_button_brush_click, this, std::placeholders::_1);
|
|
auto pr = static_cast<NodeStrokePreview*>(button->m_children[0].get());
|
|
pr->m_brush = std::make_shared<Brush>();;
|
|
pr->m_brush->load_tip("data/brushes/Round-Hard.png", "data/brushes/thumbs/Round-Hard.png");
|
|
pr->m_max_size = 20;
|
|
pr->m_pad_override = 0;
|
|
pr->m_draw_first = true;
|
|
pr->draw_stroke();
|
|
return button;
|
|
}
|
|
|
|
void NodePanelQuick::handle_button_brush_click(Node* button)
|
|
{
|
|
// the first time select the box
|
|
if (m_button_brush_current != button)
|
|
{
|
|
auto b = static_cast<NodeButtonCustom*>(button);
|
|
b->set_active(true);
|
|
m_button_brush_current->set_active(false);
|
|
m_button_brush_current = b;
|
|
m_button_brush_current_preview = static_cast<NodeStrokePreview*>(button->m_children[0].get());
|
|
if (on_brush_change)
|
|
on_brush_change(this, m_button_brush_current_preview->m_brush);
|
|
return;
|
|
}
|
|
|
|
// if the box is already selected show the popup
|
|
|
|
auto popup = App::I.presets;
|
|
auto screen = root()->m_size;
|
|
glm::vec2 tick_sz = { 16, 32 };
|
|
glm::vec2 tick_pos = button->m_pos + glm::vec2(button->m_size.x, 0);
|
|
glm::vec2 popup_pos = { tick_pos.x + tick_sz.x, tick_pos.y };
|
|
|
|
auto tick = root()->add_child<NodeImage>();
|
|
tick->SetPositioning(YGPositionTypeAbsolute);
|
|
tick->SetPosition(tick_pos.x, tick_pos.y + (button->m_size.y - tick_sz.y) * 0.5f);
|
|
tick->SetSize(tick_sz);
|
|
tick->set_image("data/ui/popup-tick.png");
|
|
tick->m_scale = { 1, 1 };
|
|
|
|
float hh = popup->m_container->m_children.size() > 10 ? (screen.y - 90.f) : 400.f;
|
|
popup->SetHeight(glm::max(hh, 400.f));
|
|
popup->SetPositioning(YGPositionTypeAbsolute);
|
|
popup->SetPosition(popup_pos);
|
|
root()->add_child(popup);
|
|
|
|
root()->update();
|
|
popup->tick(0);
|
|
popup->update();
|
|
|
|
if (tick_pos.x + popup->m_size.x > screen.x)
|
|
{
|
|
tick_pos = button->m_pos - glm::vec2(tick_sz.x, 0);
|
|
popup_pos = { tick_pos.x - popup->GetWidth(), tick_pos.y };
|
|
tick->m_scale.x = -1.f;
|
|
}
|
|
popup_pos = glm::clamp(popup_pos, { 0, 0 }, screen - popup->m_size);
|
|
popup->SetPosition(popup_pos);
|
|
tick->SetPosition(tick_pos.x, tick_pos.y + (button->m_size.y - tick_sz.y) * 0.5f);
|
|
popup->update();
|
|
|
|
popup->m_mouse_ignore = false;
|
|
popup->m_flood_events = true;
|
|
popup->m_capture_children = false;
|
|
popup->mouse_capture();
|
|
|
|
popup->on_popup_close = [this, tick](Node*) {
|
|
tick->destroy();
|
|
};
|
|
|
|
popup->on_brush_changed = [this, button](Node* target, std::shared_ptr<Brush>& b) {
|
|
auto pr = static_cast<NodeStrokePreview*>(button->m_children[0].get());
|
|
*pr->m_brush = *b;
|
|
pr->m_brush->load();
|
|
pr->draw_stroke();
|
|
if (on_brush_change)
|
|
on_brush_change(button, pr->m_brush);
|
|
};
|
|
}
|
|
|
|
void NodePanelQuick::handle_button_color_click(Node* target)
|
|
{
|
|
// the first time select the box
|
|
if (m_button_color_current != target)
|
|
{
|
|
auto button = static_cast<NodeButtonCustom*>(target);
|
|
button->set_active(true);
|
|
m_button_color_current->set_active(false);
|
|
m_button_color_current = button;
|
|
m_button_color_current_inner = static_cast<NodeBorder*>(m_button_color_current->m_children[0].get());
|
|
if (on_color_change)
|
|
on_color_change(this, m_button_color_current_inner->m_color);
|
|
return;
|
|
}
|
|
|
|
// if the box is already selected show the popup
|
|
auto popup = m_picker;
|
|
auto screen = root()->m_size;
|
|
glm::vec2 tick_sz = { 16, 32 };
|
|
glm::vec2 tick_pos = target->m_pos + glm::vec2(target->m_size.x, 0);
|
|
glm::vec2 popup_pos = { tick_pos.x + tick_sz.x, tick_pos.y - 140.f };
|
|
|
|
auto tick = root()->add_child<NodeImage>();
|
|
tick->SetPositioning(YGPositionTypeAbsolute);
|
|
tick->SetPosition(tick_pos.x, tick_pos.y + (target->m_size.y - tick_sz.y) * 0.5f);
|
|
tick->SetSize(tick_sz);
|
|
tick->set_image("data/ui/popup-tick.png");
|
|
tick->m_scale = { 1, 1 };
|
|
|
|
//float hh = popup->m_container->m_children.size() > 10 ? (screen.y / App::I.zoom - 90.f) : 400.f;
|
|
//popup->SetHeight(glm::max(hh, 400.f));
|
|
popup->SetPositioning(YGPositionTypeAbsolute);
|
|
popup->SetPosition(popup_pos);
|
|
root()->add_child(popup);
|
|
|
|
root()->update();
|
|
popup->tick(0);
|
|
popup->update();
|
|
|
|
if (tick_pos.x + popup->m_size.x > screen.x)
|
|
{
|
|
tick_pos = target->m_pos - glm::vec2(tick_sz.x, 0);
|
|
popup_pos = { tick_pos.x - popup->GetWidth(), tick_pos.y - 140.f };
|
|
tick->m_scale.x = -1.f;
|
|
}
|
|
popup_pos = glm::clamp(popup_pos, { 0, 0 }, screen - popup->m_size);
|
|
popup->SetPosition(popup_pos);
|
|
tick->SetPosition(tick_pos.x, tick_pos.y + (target->m_size.y - tick_sz.y) * 0.5f);
|
|
popup->update();
|
|
|
|
popup->m_mouse_ignore = false;
|
|
popup->m_flood_events = true;
|
|
popup->m_capture_children = false;
|
|
popup->mouse_capture();
|
|
|
|
auto c = static_cast<NodeBorder*>(target->m_children[0].get());
|
|
m_picker->set_color(c->m_color);
|
|
m_picker->on_popup_close = [this, tick](Node*) {
|
|
tick->destroy();
|
|
};
|
|
m_picker->on_color_change = [this, c](Node*, glm::vec3 rgb) {
|
|
c->m_color = glm::vec4(rgb, 1.f);
|
|
if (on_color_change)
|
|
on_color_change(this, rgb);
|
|
};
|
|
}
|