Route canvas cursor visibility through app core
This commit is contained in:
@@ -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)
|
||||
|
||||
@@ -258,6 +258,54 @@ pp::app::CanvasHotkeyKey canvas_hotkey_key(kKey key) noexcept
|
||||
}
|
||||
}
|
||||
|
||||
pp::app::CanvasToolMode canvas_tool_mode(kCanvasMode mode) noexcept
|
||||
{
|
||||
switch (mode) {
|
||||
case kCanvasMode::Draw:
|
||||
return pp::app::CanvasToolMode::draw;
|
||||
case kCanvasMode::Erase:
|
||||
return pp::app::CanvasToolMode::erase;
|
||||
case kCanvasMode::Line:
|
||||
return pp::app::CanvasToolMode::line;
|
||||
case kCanvasMode::Camera:
|
||||
return pp::app::CanvasToolMode::camera;
|
||||
case kCanvasMode::Grid:
|
||||
return pp::app::CanvasToolMode::grid;
|
||||
case kCanvasMode::Copy:
|
||||
return pp::app::CanvasToolMode::copy;
|
||||
case kCanvasMode::Cut:
|
||||
return pp::app::CanvasToolMode::cut;
|
||||
case kCanvasMode::Fill:
|
||||
return pp::app::CanvasToolMode::fill;
|
||||
case kCanvasMode::MaskFree:
|
||||
return pp::app::CanvasToolMode::mask_free;
|
||||
case kCanvasMode::MaskLine:
|
||||
return pp::app::CanvasToolMode::mask_line;
|
||||
case kCanvasMode::FloodFill:
|
||||
return pp::app::CanvasToolMode::flood_fill;
|
||||
case kCanvasMode::COUNT:
|
||||
return pp::app::CanvasToolMode::draw;
|
||||
}
|
||||
|
||||
return pp::app::CanvasToolMode::draw;
|
||||
}
|
||||
|
||||
pp::app::CanvasCursorVisibilityMode canvas_cursor_visibility_mode(NodeCanvas::kCursorVisibility mode) noexcept
|
||||
{
|
||||
switch (mode) {
|
||||
case NodeCanvas::kCursorVisibility::Never:
|
||||
return pp::app::CanvasCursorVisibilityMode::never;
|
||||
case NodeCanvas::kCursorVisibility::SmallBrush:
|
||||
return pp::app::CanvasCursorVisibilityMode::small_brush;
|
||||
case NodeCanvas::kCursorVisibility::NotPainting:
|
||||
return pp::app::CanvasCursorVisibilityMode::not_painting;
|
||||
case NodeCanvas::kCursorVisibility::Always:
|
||||
return pp::app::CanvasCursorVisibilityMode::always;
|
||||
}
|
||||
|
||||
return pp::app::CanvasCursorVisibilityMode::never;
|
||||
}
|
||||
|
||||
pp::app::CanvasHotkeyState canvas_hotkey_state(bool mouse_focused, int touch_finger_count = 0) noexcept
|
||||
{
|
||||
pp::app::CanvasHotkeyState state;
|
||||
@@ -961,24 +1009,24 @@ void NodeCanvas::set_cursor_visibility(kCursorVisibility mode)
|
||||
|
||||
void NodeCanvas::update_cursor()
|
||||
{
|
||||
bool visible = true;
|
||||
if (m_canvas->m_current_mode == kCanvasMode::Draw ||
|
||||
m_canvas->m_current_mode == kCanvasMode::Erase)
|
||||
{
|
||||
if (m_cursor_visibility == kCursorVisibility::Always)
|
||||
visible = true;
|
||||
if (m_cursor_visibility == kCursorVisibility::Never)
|
||||
visible = false;
|
||||
if (m_cursor_visibility == kCursorVisibility::SmallBrush)
|
||||
visible = m_canvas->m_current_brush->m_tip_size < 10;
|
||||
if (m_cursor_visibility == kCursorVisibility::NotPainting)
|
||||
visible = !m_canvas->get_mode<CanvasModePen>()->m_drawing;
|
||||
if (App::I->keys[(int)kKey::KeyAlt] ||
|
||||
m_canvas->get_mode<CanvasModePen>()->m_resizing ||
|
||||
m_canvas->get_mode<CanvasModePen>()->m_picking)
|
||||
visible = true;
|
||||
auto* pen_mode = m_canvas->get_mode<CanvasModePen>();
|
||||
const auto plan = pp::app::plan_canvas_cursor_visibility(pp::app::CanvasCursorVisibilityInput {
|
||||
.mode = canvas_tool_mode(m_canvas->m_current_mode),
|
||||
.visibility_mode = canvas_cursor_visibility_mode(m_cursor_visibility),
|
||||
.has_current_brush = m_canvas->m_current_brush != nullptr,
|
||||
.brush_tip_size = m_canvas->m_current_brush ? m_canvas->m_current_brush->m_tip_size : 0.0F,
|
||||
.pen_is_drawing = pen_mode && pen_mode->m_drawing,
|
||||
.alt_down = App::I && App::I->keys[(int)kKey::KeyAlt],
|
||||
.pen_is_resizing = pen_mode && pen_mode->m_resizing,
|
||||
.pen_is_picking = pen_mode && pen_mode->m_picking,
|
||||
});
|
||||
if (!plan) {
|
||||
LOG("Canvas cursor visibility planning failed: %s", plan.status().message);
|
||||
App::I->show_cursor();
|
||||
return;
|
||||
}
|
||||
visible ? App::I->show_cursor() : App::I->hide_cursor();
|
||||
|
||||
plan.value().visible ? App::I->show_cursor() : App::I->hide_cursor();
|
||||
}
|
||||
|
||||
void NodeCanvas::on_tick(float dt)
|
||||
|
||||
Reference in New Issue
Block a user