Route quick slider preview through app core
This commit is contained in:
@@ -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,
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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);
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user