Route canvas cursor visibility through app core

This commit is contained in:
2026-06-05 01:39:36 +02:00
parent e95861e9b7
commit f42a6540be
8 changed files with 447 additions and 23 deletions

View File

@@ -2,6 +2,8 @@
#include "foundation/result.h"
#include <cmath>
namespace pp::app {
enum class CanvasToolOperation {
@@ -30,6 +32,13 @@ enum class CanvasToolTransformAction {
cut,
};
enum class CanvasCursorVisibilityMode {
never,
small_brush,
not_painting,
always,
};
struct CanvasToolPlan {
CanvasToolOperation operation = CanvasToolOperation::select_mode;
CanvasToolMode mode = CanvasToolMode::draw;
@@ -59,6 +68,25 @@ struct CanvasToolButtonState {
bool flood_fill_active = false;
};
struct CanvasCursorVisibilityInput {
CanvasToolMode mode = CanvasToolMode::draw;
CanvasCursorVisibilityMode visibility_mode = CanvasCursorVisibilityMode::never;
bool has_current_brush = true;
float brush_tip_size = 0.0F;
bool pen_is_drawing = false;
bool alt_down = false;
bool pen_is_resizing = false;
bool pen_is_picking = false;
};
struct CanvasCursorVisibilityPlan {
bool visible = true;
bool paint_mode = false;
bool uses_brush_size = false;
bool uses_pen_state = false;
bool forced_visible_by_modifier_or_tool = false;
};
class CanvasToolServices {
public:
virtual ~CanvasToolServices() = default;
@@ -134,6 +162,54 @@ public:
return state;
}
[[nodiscard]] inline constexpr bool canvas_tool_mode_is_paint(CanvasToolMode mode) noexcept
{
return mode == CanvasToolMode::draw || mode == CanvasToolMode::erase;
}
[[nodiscard]] inline pp::foundation::Result<CanvasCursorVisibilityPlan> plan_canvas_cursor_visibility(
const CanvasCursorVisibilityInput& input)
{
CanvasCursorVisibilityPlan plan;
plan.paint_mode = canvas_tool_mode_is_paint(input.mode);
if (!plan.paint_mode) {
plan.visible = true;
return pp::foundation::Result<CanvasCursorVisibilityPlan>::success(plan);
}
switch (input.visibility_mode) {
case CanvasCursorVisibilityMode::always:
plan.visible = true;
break;
case CanvasCursorVisibilityMode::never:
plan.visible = false;
break;
case CanvasCursorVisibilityMode::small_brush:
if (!input.has_current_brush) {
return pp::foundation::Result<CanvasCursorVisibilityPlan>::failure(
pp::foundation::Status::invalid_argument("canvas cursor small-brush mode requires a current brush"));
}
if (!std::isfinite(input.brush_tip_size) || input.brush_tip_size < 0.0F) {
return pp::foundation::Result<CanvasCursorVisibilityPlan>::failure(
pp::foundation::Status::invalid_argument("canvas cursor brush size must be finite and non-negative"));
}
plan.visible = input.brush_tip_size < 10.0F;
plan.uses_brush_size = true;
break;
case CanvasCursorVisibilityMode::not_painting:
plan.visible = !input.pen_is_drawing;
plan.uses_pen_state = true;
break;
}
if (input.alt_down || input.pen_is_resizing || input.pen_is_picking) {
plan.visible = true;
plan.forced_visible_by_modifier_or_tool = true;
}
return pp::foundation::Result<CanvasCursorVisibilityPlan>::success(plan);
}
[[nodiscard]] inline pp::foundation::Status execute_canvas_tool_plan(
const CanvasToolPlan& plan,
CanvasToolServices& services)