248 lines
9.0 KiB
C++
248 lines
9.0 KiB
C++
#include "pch.h"
|
|
#include "app_core/quick_ui.h"
|
|
#include "legacy_quick_ui_services.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_file("data/dialogs/panel-quick.xml", "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 static_cast<int>(std::distance(m_button_brushes.begin(), it));
|
|
}
|
|
|
|
void NodePanelQuick::set_selected_brush_index(int idx, bool fire_event /*= false*/)
|
|
{
|
|
if (!pp::app::validate_quick_slot_index(idx, static_cast<int>(m_button_brushes.size())).ok())
|
|
return;
|
|
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 static_cast<int>(std::distance(m_button_colors.begin(), it));
|
|
}
|
|
|
|
void NodePanelQuick::set_selected_color_index(int idx, bool fire_event /*= false*/)
|
|
{
|
|
if (!pp::app::validate_quick_slot_index(idx, static_cast<int>(m_button_colors.size())).ok())
|
|
return;
|
|
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_colors[i]->m_children[0].get())->m_color;
|
|
}
|
|
return s;
|
|
}
|
|
|
|
void NodePanelQuick::set_state(const MiniState& state, bool fire_event /*= false*/)
|
|
{
|
|
const auto plan = pp::app::plan_quick_state_restore(
|
|
state.brush_index,
|
|
state.color_index,
|
|
static_cast<int>(m_button_brushes.size()),
|
|
fire_event);
|
|
if (!plan)
|
|
return;
|
|
|
|
const auto status = pp::panopainter::execute_legacy_quick_ui_plan(*this, plan.value(), &state);
|
|
if (!status.ok())
|
|
LOG("Quick restore action failed: %s", status.message);
|
|
}
|
|
|
|
void NodePanelQuick::reset_state(bool fire_event /*= false*/)
|
|
{
|
|
const auto plan = pp::app::plan_quick_state_reset(static_cast<int>(m_button_brushes.size()), fire_event);
|
|
if (!plan)
|
|
return;
|
|
|
|
const auto status = pp::panopainter::execute_legacy_quick_ui_plan(*this, plan.value());
|
|
if (!status.ok())
|
|
LOG("Quick reset action failed: %s", status.message);
|
|
}
|
|
|
|
void NodePanelQuick::init_controls()
|
|
{
|
|
m_picker = std::make_shared<NodeColorPicker>();
|
|
m_picker->set_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) {
|
|
update_slider_preview();
|
|
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) {
|
|
update_slider_preview();
|
|
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());
|
|
|
|
m_button_brushes[0] = init_button_brush("quick-brush1", true, false);
|
|
m_button_brushes[1] = init_button_brush("quick-brush2", false, true);
|
|
m_button_brushes[2] = init_button_brush("quick-brush3", false, false);
|
|
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, bool szp, bool flp)
|
|
{
|
|
LOG("init_button_brush %s", name.c_str());
|
|
auto button = find<NodeButtonCustom>(name.c_str());
|
|
if (!button) {
|
|
LOG("couldn't find button %s", name.c_str());
|
|
return nullptr;
|
|
}
|
|
button->on_click = std::bind(&this_class::handle_button_brush_click, this, std::placeholders::_1);
|
|
LOG("button has %d children", static_cast<int>(button->m_children.size()));
|
|
auto pr = static_cast<NodeStrokePreview*>(button->m_children[0].get());
|
|
pr->m_brush = std::make_shared<Brush>();
|
|
pr->m_brush->m_tip_size_pressure = szp;
|
|
pr->m_brush->m_tip_flow_pressure = flp;
|
|
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::update_slider_preview()
|
|
{
|
|
if (!App::I || !Canvas::I || !Canvas::I->m_mode || Canvas::I->m_mode->empty() || !m_slider_flow || !m_button_brush_current_preview)
|
|
return;
|
|
|
|
auto* mode = (*Canvas::I->m_mode)[0];
|
|
auto* pen_mode = dynamic_cast<CanvasModePen*>(mode);
|
|
auto* line_mode = dynamic_cast<CanvasModeLine*>(mode);
|
|
|
|
const auto plan = pp::app::plan_quick_slider_preview(pp::app::QuickSliderPreviewInput {
|
|
.ui_rtl = App::I->ui_rtl,
|
|
.slider_x = m_slider_flow->m_pos.x,
|
|
.slider_y = m_slider_flow->m_pos.y,
|
|
.slider_height = m_slider_flow->m_size.y,
|
|
.zoom = App::I->zoom,
|
|
.has_pen_mode = pen_mode != nullptr,
|
|
.has_line_mode = line_mode != nullptr,
|
|
});
|
|
if (!plan) {
|
|
LOG("Quick slider preview failed: %s", plan.status().message);
|
|
return;
|
|
}
|
|
|
|
const glm::vec2 cursor(plan.value().cursor_x, plan.value().cursor_y);
|
|
if (plan.value().updates_pen_mode && pen_mode)
|
|
{
|
|
pen_mode->m_cur_pos = cursor;
|
|
pen_mode->m_draw_tip = plan.value().draws_tip;
|
|
pen_mode->m_draw_outline = !plan.value().disables_pen_outline;
|
|
}
|
|
if (plan.value().updates_line_mode && line_mode)
|
|
{
|
|
line_mode->m_cur_pos = cursor;
|
|
line_mode->m_draw_tip = plan.value().draws_tip;
|
|
}
|
|
if (plan.value().redraws_brush_preview)
|
|
m_button_brush_current_preview->draw_stroke();
|
|
}
|
|
|
|
void NodePanelQuick::handle_button_brush_click(Node* button)
|
|
{
|
|
const auto clicked = std::find(m_button_brushes.begin(), m_button_brushes.end(), button);
|
|
const int clicked_index = static_cast<int>(std::distance(m_button_brushes.begin(), clicked));
|
|
const auto plan = pp::app::plan_quick_slot_click(
|
|
pp::app::QuickUiSlotKind::brush,
|
|
get_selected_brush_index(),
|
|
clicked_index,
|
|
static_cast<int>(m_button_brushes.size()));
|
|
if (!plan)
|
|
return;
|
|
|
|
const auto status = pp::panopainter::execute_legacy_quick_ui_plan(*this, plan.value());
|
|
if (!status.ok())
|
|
LOG("Quick brush action failed: %s", status.message);
|
|
}
|
|
|
|
void NodePanelQuick::handle_button_color_click(Node* target)
|
|
{
|
|
const auto clicked = std::find(m_button_colors.begin(), m_button_colors.end(), target);
|
|
const int clicked_index = static_cast<int>(std::distance(m_button_colors.begin(), clicked));
|
|
const auto plan = pp::app::plan_quick_slot_click(
|
|
pp::app::QuickUiSlotKind::color,
|
|
get_selected_color_index(),
|
|
clicked_index,
|
|
static_cast<int>(m_button_colors.size()));
|
|
if (!plan)
|
|
return;
|
|
|
|
const auto status = pp::panopainter::execute_legacy_quick_ui_plan(*this, plan.value());
|
|
if (!status.ok())
|
|
LOG("Quick color action failed: %s", status.message);
|
|
}
|