Route quick slider preview through app core

This commit is contained in:
2026-06-05 01:26:02 +02:00
parent 31c26c3127
commit e95861e9b7
9 changed files with 324 additions and 32 deletions

View File

@@ -2,6 +2,8 @@
#include "foundation/result.h"
#include <cmath>
namespace pp::app {
enum class QuickUiSlotKind {
@@ -35,6 +37,27 @@ struct QuickUiPlan {
bool mutates_quick_state = false;
};
struct QuickSliderPreviewInput {
bool ui_rtl = false;
float slider_x = 0.0F;
float slider_y = 0.0F;
float slider_height = 0.0F;
float zoom = 1.0F;
bool has_pen_mode = false;
bool has_line_mode = false;
};
struct QuickSliderPreviewPlan {
float cursor_x = 0.0F;
float cursor_y = 0.0F;
bool updates_pen_mode = false;
bool updates_line_mode = false;
bool draws_tip = false;
bool disables_pen_outline = false;
bool redraws_brush_preview = false;
bool invokes_change_callback = false;
};
class QuickUiServices {
public:
virtual ~QuickUiServices() = default;
@@ -45,6 +68,15 @@ public:
virtual void reset_state(bool fire_event) = 0;
};
[[nodiscard]] inline pp::foundation::Status validate_quick_slider_float(float value) noexcept
{
if (!std::isfinite(value)) {
return pp::foundation::Status::invalid_argument("quick slider preview value must be finite");
}
return pp::foundation::Status::success();
}
[[nodiscard]] inline pp::foundation::Status validate_quick_slot_count(int slot_count) noexcept
{
if (slot_count <= 0) {
@@ -68,6 +100,47 @@ public:
return pp::foundation::Status::success();
}
[[nodiscard]] inline pp::foundation::Result<QuickSliderPreviewPlan> plan_quick_slider_preview(
const QuickSliderPreviewInput& input)
{
const auto x_status = validate_quick_slider_float(input.slider_x);
if (!x_status.ok()) {
return pp::foundation::Result<QuickSliderPreviewPlan>::failure(x_status);
}
const auto y_status = validate_quick_slider_float(input.slider_y);
if (!y_status.ok()) {
return pp::foundation::Result<QuickSliderPreviewPlan>::failure(y_status);
}
const auto height_status = validate_quick_slider_float(input.slider_height);
if (!height_status.ok()) {
return pp::foundation::Result<QuickSliderPreviewPlan>::failure(height_status);
}
if (input.slider_height < 0.0F) {
return pp::foundation::Result<QuickSliderPreviewPlan>::failure(
pp::foundation::Status::invalid_argument("quick slider preview height must not be negative"));
}
const auto zoom_status = validate_quick_slider_float(input.zoom);
if (!zoom_status.ok()) {
return pp::foundation::Result<QuickSliderPreviewPlan>::failure(zoom_status);
}
if (input.zoom <= 0.0F) {
return pp::foundation::Result<QuickSliderPreviewPlan>::failure(
pp::foundation::Status::invalid_argument("quick slider preview zoom must be positive"));
}
const float offset = input.ui_rtl ? -100.0F : 100.0F;
QuickSliderPreviewPlan plan;
plan.cursor_x = (input.slider_x + offset) * input.zoom;
plan.cursor_y = (input.slider_y + input.slider_height * 0.5F) * input.zoom;
plan.updates_pen_mode = input.has_pen_mode;
plan.updates_line_mode = input.has_line_mode;
plan.draws_tip = input.has_pen_mode || input.has_line_mode;
plan.disables_pen_outline = input.has_pen_mode;
plan.redraws_brush_preview = true;
plan.invokes_change_callback = true;
return pp::foundation::Result<QuickSliderPreviewPlan>::success(plan);
}
[[nodiscard]] inline pp::foundation::Result<QuickUiPlan> plan_quick_slot_click(
QuickUiSlotKind slot_kind,
int current_index,

View File

@@ -121,39 +121,13 @@ void NodePanelQuick::init_controls()
m_slider_size = find<NodeSliderV>("quick-size");
m_slider_size->on_value_changed = [this](Node* target, float value) {
float off = App::I->ui_rtl ? -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();
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) {
float off = App::I->ui_rtl ? -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();
update_slider_preview();
if (on_flow_change)
on_flow_change(target, value);
};
@@ -199,6 +173,45 @@ NodeButtonCustom* NodePanelQuick::init_button_brush(const std::string& name, boo
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);

View File

@@ -51,6 +51,7 @@ public:
private:
void init_controls();
NodeButtonCustom* init_button_brush(const std::string& name, bool szp, bool flp);
void update_slider_preview();
void handle_button_brush_click(Node* target);
void handle_button_color_click(Node* target);
};