infinipaint/src/InputManager.hpp

340 lines
10 KiB
C++
Raw Normal View History

2025-07-06 20:43:53 +03:00
#pragma once
#include <Eigen/Dense>
#include <array>
#include "RichText/TextStyleModifier.hpp"
#include "RichText/TextBox.hpp"
2025-07-06 20:43:53 +03:00
#include "TimePoint.hpp"
#include <Helpers/Hashes.hpp>
#include <unordered_map>
#include <nlohmann/json.hpp>
#include <queue>
#include <Helpers/CallbackManager.hpp>
2025-11-12 11:36:14 +03:00
#include "UndoManager.hpp"
2025-07-06 20:43:53 +03:00
#include <SDL3/SDL.h>
#include <SDL3/SDL_events.h>
#include <SDL3/SDL_keycode.h>
using namespace Eigen;
2026-03-01 17:28:43 +03:00
class MainProgram;
2025-07-06 20:43:53 +03:00
struct InputManager {
2026-03-01 17:28:43 +03:00
InputManager(MainProgram& initMain);
2025-07-06 20:43:53 +03:00
void frame_reset(const Vector2i& windowSize);
2025-07-06 20:43:53 +03:00
// Just renamed SDL3 cursor types, but if we need to change to a different backend we can
// translate this enum to different commands in main.cpp
enum class SystemCursorType : unsigned {
DEFAULT = 0,
TEXT,
WAIT,
CROSSHAIR,
PROGRESS,
NWSE_RESIZE,
NESW_RESIZE,
EW_RESIZE,
NS_RESIZE,
MOVE,
NOT_ALLOWED,
POINTER,
NW_RESIZE,
N_RESIZE,
NE_RESIZE,
E_RESIZE,
SE_RESIZE,
S_RESIZE,
SW_RESIZE,
W_RESIZE
} cursorIcon;
bool hideCursor = false;
bool toggleFullscreen = false;
struct KeyData {
bool pressed = false;
bool held = false;
bool repeat = false;
std::chrono::steady_clock::time_point lastPressTime;
};
struct Mouse {
void set_pos(const Vector2f& newPos);
Vector2f scrollAmount = {0, 0};
Vector2f pos = {0, 0};
Vector2f previousPos = {0, 0};
Vector2f move = {0, 0};
bool leftDown = false;
bool rightDown = false;
bool middleDown = false;
uint8_t leftClicks = 0;
uint8_t rightClicks = 0;
uint8_t middleClicks = 0;
Vector2f lastPos = {0, 0};
} mouse;
2026-02-27 16:16:51 +03:00
struct Touch {
bool isDown = false;
int leftClicksSaved = 0;
std::chrono::steady_clock::time_point lastLeftClickTime;
} touch;
2025-07-06 20:43:53 +03:00
struct Pen {
bool inProximity = false;
bool isDown = false;
bool isEraser = false;
float pressure = 0.0f;
2025-09-29 17:05:53 +03:00
int leftClicksSaved = 0;
2026-03-03 14:59:18 +03:00
Vector2f previousPos;
2025-09-29 17:05:53 +03:00
std::chrono::steady_clock::time_point lastPenLeftClickTime;
2025-07-06 20:43:53 +03:00
std::array<KeyData, 256> buttons;
} pen;
void set_rich_text_box_input_front(const std::shared_ptr<RichText::TextBox>& nTextBox, const std::shared_ptr<RichText::TextBox::Cursor>& nCursor, bool isRichTextBox, const std::optional<RichText::TextStyleModifier::ModifierMap>& nModMap = std::nullopt);
void set_rich_text_box_input_back(const std::shared_ptr<RichText::TextBox>& nTextBox, const std::shared_ptr<RichText::TextBox::Cursor>& nCursor, bool isRichTextBox, const std::optional<RichText::TextStyleModifier::ModifierMap>& nModMap = std::nullopt);
void remove_rich_text_box_input(const std::shared_ptr<RichText::TextBox>& nTextBox);
2025-07-06 20:43:53 +03:00
struct Text {
bool is_accepting_input();
2025-07-06 20:43:53 +03:00
void add_text_to_textbox(const std::string& inputText);
2025-11-12 14:54:46 +03:00
void add_textbox_undo(const RichText::TextBox::Cursor& prevCursor, const RichText::TextData& prevRichText);
void do_textbox_operation_with_undo(const std::function<void()>& func);
2025-11-12 11:36:14 +03:00
2025-11-12 14:54:46 +03:00
private:
struct TextBoxInfo {
bool isRichTextBox;
std::shared_ptr<RichText::TextBox> textBox;
std::shared_ptr<RichText::TextBox::Cursor> cursor;
std::optional<RichText::TextStyleModifier::ModifierMap> modMap;
UndoManager textboxUndo;
};
void set_accepting_input(SDL_Window* window, bool newAcceptingInputVal);
2025-11-12 11:36:14 +03:00
bool isNextPasteRich = false;
2025-07-06 20:43:53 +03:00
bool acceptingInput = false;
std::deque<TextBoxInfo> textBoxes;
2025-07-06 20:43:53 +03:00
friend struct InputManager;
} text;
#ifdef __APPLE__
SDL_Keymod CTRL_MOD = SDL_KMOD_GUI;
#else
SDL_Keymod CTRL_MOD = SDL_KMOD_CTRL;
#endif
int stopKeyInput = 0;
std::optional<Vector2ui32> lastPressedKeybind;
enum KeyCodeEnum : unsigned {
// Assignable
KEY_CAMERA_ROTATE_CLOCKWISE = 0,
KEY_CAMERA_ROTATE_COUNTERCLOCKWISE,
KEY_DRAW_DELETE,
KEY_UNDO,
KEY_REDO,
KEY_NOGUI,
KEY_FULLSCREEN,
KEY_SAVE,
KEY_SAVE_AS,
KEY_COPY,
KEY_CUT,
KEY_PASTE,
2026-01-06 19:06:44 +03:00
KEY_PASTE_IMAGE,
2025-07-06 20:43:53 +03:00
KEY_DRAW_TOOL_BRUSH,
KEY_DRAW_TOOL_ERASER,
KEY_DRAW_TOOL_ZOOM,
KEY_DRAW_TOOL_PAN,
KEY_DRAW_TOOL_LASSOSELECT,
2025-07-06 20:43:53 +03:00
KEY_DRAW_TOOL_TEXTBOX,
KEY_DRAW_TOOL_RECTANGLE,
KEY_DRAW_TOOL_ELLIPSE,
KEY_DRAW_TOOL_RECTSELECT,
2025-08-05 12:11:50 +03:00
KEY_DRAW_TOOL_EYEDROPPER,
2025-07-06 20:43:53 +03:00
KEY_DRAW_TOOL_SCREENSHOT,
2026-01-08 11:19:48 +03:00
KEY_DRAW_TOOL_LINE,
2025-07-06 20:43:53 +03:00
KEY_SHOW_METRICS,
KEY_OPEN_CHAT,
KEY_SHOW_PLAYER_LIST,
KEY_HOLD_TO_PAN,
2026-01-07 10:34:51 +03:00
KEY_HOLD_TO_ZOOM,
KEY_DESELECT_AND_EDIT_TOOL,
2025-07-06 20:43:53 +03:00
KEY_ASSIGNABLE_COUNT, // Not a real key
// Unassignable
KEY_TEXT_DOWN,
KEY_TEXT_UP,
KEY_TEXT_LEFT,
KEY_TEXT_RIGHT,
KEY_TEXT_BACKSPACE,
KEY_TEXT_DELETE,
KEY_TEXT_HOME,
KEY_TEXT_END,
2025-07-06 20:43:53 +03:00
KEY_TEXT_SHIFT,
KEY_TEXT_COPY,
KEY_TEXT_CUT,
KEY_TEXT_PASTE,
KEY_TEXT_ENTER,
KEY_TEXT_TAB,
2025-07-06 20:43:53 +03:00
KEY_TEXT_CTRL,
KEY_TEXT_META,
2025-07-06 20:43:53 +03:00
KEY_TEXT_SELECTALL,
2025-11-12 11:36:14 +03:00
KEY_TEXT_UNDO,
KEY_TEXT_REDO,
2026-03-04 12:15:24 +03:00
KEY_TEXT_ESCAPE,
KEY_GENERIC_UP,
KEY_GENERIC_DOWN,
KEY_GENERIC_LEFT,
KEY_GENERIC_RIGHT,
KEY_GENERIC_ENTER,
KEY_GENERIC_ESCAPE,
KEY_GENERIC_LSHIFT,
KEY_GENERIC_LALT,
KEY_GENERIC_LCTRL,
KEY_GENERIC_LMETA,
2025-07-06 20:43:53 +03:00
KEY_COUNT
};
typedef unsigned KeyCode;
bool ctrl_or_meta_held();
2025-07-06 20:43:53 +03:00
void stop_key_input();
uint32_t make_generic_key_mod(SDL_Keymod m);
void set_key_up(const SDL_KeyboardEvent& e, KeyCode kCode);
void set_key_down(const SDL_KeyboardEvent& e, KeyCode kCode);
2026-03-03 14:59:18 +03:00
void backend_drop_file_event(const SDL_DropEvent& e);
void backend_drop_text_event(const SDL_DropEvent& e);
2026-03-01 17:28:43 +03:00
void backend_mouse_button_up_update(const SDL_MouseButtonEvent& e);
void backend_mouse_button_down_update(const SDL_MouseButtonEvent& e);
void backend_mouse_motion_update(const SDL_MouseMotionEvent& e);
void backend_mouse_wheel_update(const SDL_MouseWheelEvent& e);
2025-07-06 20:43:53 +03:00
void backend_key_up_update(const SDL_KeyboardEvent& e);
void backend_key_down_update(const SDL_KeyboardEvent& e);
2026-03-03 14:59:18 +03:00
void backend_pen_button_down_update(const SDL_PenButtonEvent& e);
void backend_pen_button_up_update(const SDL_PenButtonEvent& e);
void backend_pen_touch_down_update(const SDL_PenTouchEvent& e);
void backend_pen_touch_up_update(const SDL_PenTouchEvent& e);
void backend_pen_motion_update(const SDL_PenMotionEvent& e);
2026-03-03 16:01:21 +03:00
void backend_pen_axis_update(const SDL_PenAxisEvent& e);
2025-07-06 20:43:53 +03:00
void set_clipboard_str(std::string_view s);
void set_clipboard_plain_and_richtext_pair(const std::pair<std::string, RichText::TextData>& plainAndRichtextPair);
2025-12-02 09:53:03 +03:00
std::string get_clipboard_str_SDL();
void get_clipboard_image_data_SDL(const std::function<void(std::string_view data)>& callback);
2025-12-02 09:53:03 +03:00
void call_text_paste(bool isRichTextPaste);
void process_text_paste(const std::string& plainClipboardStr);
2025-07-06 20:43:53 +03:00
std::optional<RichText::TextData> lastCopiedRichText;
2025-07-06 20:43:53 +03:00
std::string key_assignment_to_str(const Vector2ui32& k);
Vector2ui32 key_assignment_from_str(const std::string& s);
const KeyData& key(KeyCode kCode);
struct KeyCallbackArgs {
KeyCode key;
bool down;
bool repeat;
};
2025-07-06 20:43:53 +03:00
std::unordered_map<Vector2ui32, KeyCode> keyAssignments;
std::unordered_map<Vector2ui32, KeyCode> defaultKeyAssignments;
std::array<KeyData, KEY_COUNT> keys;
2026-03-02 23:09:48 +03:00
enum class MouseButton : uint8_t {
LEFT = 1,
MIDDLE,
RIGHT
} button;
2026-03-01 17:28:43 +03:00
struct MouseButtonCallbackArgs {
2026-03-02 23:09:48 +03:00
MouseButton button;
2026-03-01 17:28:43 +03:00
bool down;
uint8_t clicks;
Vector2f pos;
};
struct MouseMotionCallbackArgs {
Vector2f pos;
Vector2f move;
};
struct MouseWheelCallbackArgs {
2026-03-02 23:09:48 +03:00
Vector2f mousePos;
2026-03-01 17:28:43 +03:00
Vector2f amount;
2026-03-02 23:09:48 +03:00
Vector2i tickAmount;
2026-03-01 17:28:43 +03:00
};
2026-03-03 14:59:18 +03:00
struct PenButtonCallbackArgs {
uint8_t button;
bool down;
Vector2f pos;
};
struct PenTouchCallbackArgs {
bool down;
bool eraser;
Vector2f pos;
};
struct PenMotionCallbackArgs {
Vector2f pos;
Vector2f move;
};
2026-03-03 16:01:21 +03:00
struct PenAxisCallbackArgs {
Vector2f pos;
SDL_PenAxis axis;
float value;
};
struct DropCallbackArgs {
Vector2f pos;
const char* source;
const char* data;
};
2026-03-01 17:28:43 +03:00
MainProgram& main;
2025-07-06 20:43:53 +03:00
};
NLOHMANN_JSON_SERIALIZE_ENUM(InputManager::KeyCodeEnum, {
{InputManager::KEY_CAMERA_ROTATE_CLOCKWISE, "Rotate Canvas CW"},
{InputManager::KEY_CAMERA_ROTATE_COUNTERCLOCKWISE, "Rotate Canvas CCW"},
{InputManager::KEY_DRAW_DELETE, "Delete Selection"},
{InputManager::KEY_UNDO, "Undo"},
{InputManager::KEY_REDO, "Redo"},
{InputManager::KEY_NOGUI, "Toggle GUI"},
{InputManager::KEY_FULLSCREEN, "Toggle Fullscreen"},
{InputManager::KEY_SAVE, "Save"},
{InputManager::KEY_SAVE_AS, "Save As"},
{InputManager::KEY_COPY, "Copy"},
{InputManager::KEY_CUT, "Cut"},
{InputManager::KEY_PASTE, "Paste"},
2026-01-06 19:06:44 +03:00
{InputManager::KEY_PASTE_IMAGE, "Paste Image"},
2025-07-06 20:43:53 +03:00
{InputManager::KEY_DRAW_TOOL_BRUSH, "Brush Tool"},
{InputManager::KEY_DRAW_TOOL_ERASER, "Eraser Tool"},
{InputManager::KEY_DRAW_TOOL_ZOOM, "Zoom Tool"},
{InputManager::KEY_DRAW_TOOL_LASSOSELECT, "Lasso Select Tool"},
{InputManager::KEY_DRAW_TOOL_PAN, "Pan Tool"},
2025-07-06 20:43:53 +03:00
{InputManager::KEY_DRAW_TOOL_TEXTBOX, "Textbox Tool"},
{InputManager::KEY_DRAW_TOOL_RECTANGLE, "Rectangle Tool"},
{InputManager::KEY_DRAW_TOOL_ELLIPSE, "Ellipse Tool"},
{InputManager::KEY_DRAW_TOOL_RECTSELECT, "Rect Select Tool"},
2025-08-05 12:11:50 +03:00
{InputManager::KEY_DRAW_TOOL_EYEDROPPER, "Color Select Tool"},
2026-01-08 11:19:48 +03:00
{InputManager::KEY_DRAW_TOOL_SCREENSHOT, "Take Screenshot"},
{InputManager::KEY_DRAW_TOOL_LINE, "Line Tool"},
2025-07-06 20:43:53 +03:00
{InputManager::KEY_SHOW_METRICS, "Show Metrics"},
{InputManager::KEY_OPEN_CHAT, "Open Chat"},
{InputManager::KEY_SHOW_PLAYER_LIST, "Show Player List"},
2026-01-07 10:34:51 +03:00
{InputManager::KEY_HOLD_TO_PAN, "Hold to Pan"},
{InputManager::KEY_HOLD_TO_ZOOM, "Hold to Zoom"},
{InputManager::KEY_DESELECT_AND_EDIT_TOOL, "Deselect selection / Edit Tool"}
2025-07-06 20:43:53 +03:00
})