181 lines
5.7 KiB
C++
181 lines
5.7 KiB
C++
#pragma once
|
|
|
|
#include "foundation/result.h"
|
|
|
|
namespace pp::app {
|
|
|
|
enum class CanvasToolOperation {
|
|
select_mode,
|
|
toggle_picking,
|
|
toggle_touch_lock,
|
|
};
|
|
|
|
enum class CanvasToolMode {
|
|
draw,
|
|
erase,
|
|
line,
|
|
camera,
|
|
grid,
|
|
copy,
|
|
cut,
|
|
fill,
|
|
mask_free,
|
|
mask_line,
|
|
flood_fill,
|
|
};
|
|
|
|
enum class CanvasToolTransformAction {
|
|
none,
|
|
copy,
|
|
cut,
|
|
};
|
|
|
|
struct CanvasToolPlan {
|
|
CanvasToolOperation operation = CanvasToolOperation::select_mode;
|
|
CanvasToolMode mode = CanvasToolMode::draw;
|
|
CanvasToolTransformAction transform_action = CanvasToolTransformAction::none;
|
|
bool selects_toolbar_button = false;
|
|
bool updates_canvas_mode = false;
|
|
bool toggles_picking = false;
|
|
bool toggles_touch_lock = false;
|
|
bool requires_draw_mode = false;
|
|
bool no_op = false;
|
|
};
|
|
|
|
struct CanvasToolButtonState {
|
|
CanvasToolMode mode = CanvasToolMode::draw;
|
|
bool pick_active = false;
|
|
bool touch_lock_active = false;
|
|
bool pen_active = false;
|
|
bool erase_active = false;
|
|
bool line_active = false;
|
|
bool camera_active = false;
|
|
bool grid_active = false;
|
|
bool copy_active = false;
|
|
bool cut_active = false;
|
|
bool fill_active = false;
|
|
bool mask_free_active = false;
|
|
bool mask_line_active = false;
|
|
bool flood_fill_active = false;
|
|
};
|
|
|
|
class CanvasToolServices {
|
|
public:
|
|
virtual ~CanvasToolServices() = default;
|
|
|
|
virtual void select_toolbar_button(CanvasToolMode mode) = 0;
|
|
virtual void set_transform_action(CanvasToolTransformAction action) = 0;
|
|
virtual void set_canvas_mode(CanvasToolMode mode) = 0;
|
|
virtual void toggle_picking() = 0;
|
|
virtual void toggle_touch_lock() = 0;
|
|
};
|
|
|
|
[[nodiscard]] inline constexpr CanvasToolTransformAction transform_action_for_mode(CanvasToolMode mode) noexcept
|
|
{
|
|
if (mode == CanvasToolMode::copy) {
|
|
return CanvasToolTransformAction::copy;
|
|
}
|
|
if (mode == CanvasToolMode::cut) {
|
|
return CanvasToolTransformAction::cut;
|
|
}
|
|
return CanvasToolTransformAction::none;
|
|
}
|
|
|
|
[[nodiscard]] inline constexpr CanvasToolPlan plan_canvas_tool_select(CanvasToolMode mode) noexcept
|
|
{
|
|
CanvasToolPlan plan;
|
|
plan.operation = CanvasToolOperation::select_mode;
|
|
plan.mode = mode;
|
|
plan.transform_action = transform_action_for_mode(mode);
|
|
plan.selects_toolbar_button = true;
|
|
plan.updates_canvas_mode = true;
|
|
return plan;
|
|
}
|
|
|
|
[[nodiscard]] inline constexpr CanvasToolPlan plan_canvas_tool_pick_toggle(bool current_mode_is_draw) noexcept
|
|
{
|
|
CanvasToolPlan plan;
|
|
plan.operation = CanvasToolOperation::toggle_picking;
|
|
plan.mode = CanvasToolMode::draw;
|
|
plan.requires_draw_mode = true;
|
|
plan.toggles_picking = current_mode_is_draw;
|
|
plan.no_op = !current_mode_is_draw;
|
|
return plan;
|
|
}
|
|
|
|
[[nodiscard]] inline constexpr CanvasToolPlan plan_canvas_tool_touch_lock_toggle() noexcept
|
|
{
|
|
CanvasToolPlan plan;
|
|
plan.operation = CanvasToolOperation::toggle_touch_lock;
|
|
plan.toggles_touch_lock = true;
|
|
return plan;
|
|
}
|
|
|
|
[[nodiscard]] inline constexpr CanvasToolButtonState plan_canvas_tool_button_state(
|
|
CanvasToolMode mode,
|
|
bool picking,
|
|
bool touch_lock) noexcept
|
|
{
|
|
CanvasToolButtonState state;
|
|
state.mode = mode;
|
|
state.pick_active = mode == CanvasToolMode::draw && picking;
|
|
state.touch_lock_active = touch_lock;
|
|
state.pen_active = mode == CanvasToolMode::draw;
|
|
state.erase_active = mode == CanvasToolMode::erase;
|
|
state.line_active = mode == CanvasToolMode::line;
|
|
state.camera_active = mode == CanvasToolMode::camera;
|
|
state.grid_active = mode == CanvasToolMode::grid;
|
|
state.copy_active = mode == CanvasToolMode::copy;
|
|
state.cut_active = mode == CanvasToolMode::cut;
|
|
state.fill_active = mode == CanvasToolMode::fill;
|
|
state.mask_free_active = mode == CanvasToolMode::mask_free;
|
|
state.mask_line_active = mode == CanvasToolMode::mask_line;
|
|
state.flood_fill_active = mode == CanvasToolMode::flood_fill;
|
|
return state;
|
|
}
|
|
|
|
[[nodiscard]] inline pp::foundation::Status execute_canvas_tool_plan(
|
|
const CanvasToolPlan& plan,
|
|
CanvasToolServices& services)
|
|
{
|
|
switch (plan.operation) {
|
|
case CanvasToolOperation::select_mode:
|
|
if (!plan.selects_toolbar_button || !plan.updates_canvas_mode) {
|
|
return pp::foundation::Status::invalid_argument("canvas tool select plan must select toolbar and update mode");
|
|
}
|
|
if (plan.transform_action != transform_action_for_mode(plan.mode)) {
|
|
return pp::foundation::Status::invalid_argument("canvas tool select plan has mismatched transform action");
|
|
}
|
|
services.select_toolbar_button(plan.mode);
|
|
if (plan.transform_action != CanvasToolTransformAction::none) {
|
|
services.set_transform_action(plan.transform_action);
|
|
}
|
|
services.set_canvas_mode(plan.mode);
|
|
return pp::foundation::Status::success();
|
|
|
|
case CanvasToolOperation::toggle_picking:
|
|
if (!plan.requires_draw_mode) {
|
|
return pp::foundation::Status::invalid_argument("canvas pick plan must require draw mode");
|
|
}
|
|
if (plan.no_op) {
|
|
return pp::foundation::Status::success();
|
|
}
|
|
if (!plan.toggles_picking) {
|
|
return pp::foundation::Status::invalid_argument("canvas pick plan must toggle picking or be a no-op");
|
|
}
|
|
services.toggle_picking();
|
|
return pp::foundation::Status::success();
|
|
|
|
case CanvasToolOperation::toggle_touch_lock:
|
|
if (!plan.toggles_touch_lock || plan.no_op) {
|
|
return pp::foundation::Status::invalid_argument("canvas touch-lock plan must toggle touch lock");
|
|
}
|
|
services.toggle_touch_lock();
|
|
return pp::foundation::Status::success();
|
|
}
|
|
|
|
return pp::foundation::Status::invalid_argument("unknown canvas tool operation");
|
|
}
|
|
|
|
} // namespace pp::app
|