#pragma once #include #include #include #include #include #include "RichText/TextStyleModifier.hpp" #include "RichText/TextBox.hpp" #include "TimePoint.hpp" #include #include #include #include #include #include "UndoManager.hpp" #include #include #include #include #include "CustomEvents.hpp" using namespace Eigen; class MainProgram; struct InputManagerCallPasteInfo { std::optional pastePosition; bool allowRichText = true; }; struct InputManager { InputManager(MainProgram& initMain); void update(); void frame_reset(const Vector2i& windowSize); // 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; struct KeyData { bool held = false; std::chrono::steady_clock::time_point lastPressTime; }; struct Mouse { void set_pos(const Vector2f& newPos); Vector2f pos = {0, 0}; bool leftDown = false; bool rightDown = false; bool middleDown = false; } mouse; struct Touch { uint8_t leftClicksSaved = 0; uint8_t fingerTapsSaved = 0; std::chrono::steady_clock::time_point lastLeftClickTime; std::chrono::steady_clock::time_point lastFingerTapTime; std::vector fingers; enum TypeOfTouchEvent { NO_TOUCH_EVENT, ONE_FINGER_EVENT, TWO_FINGER_EVENT, EVENT_DONE } touchEventType = EVENT_DONE; } touch; struct Pen { bool inProximity = false; bool isDown = false; bool isEraser = false; float pressure = 0.0f; uint8_t leftClicksSaved = 0; Vector2f previousPos; std::chrono::steady_clock::time_point lastPenLeftClickTime; std::array buttons; } pen; bool isTouchDevice = true; enum AndroidInputType : int { ANDROIDTEXT_TYPE_CLASS_DATETIME = 0x00000004, ANDROIDTEXT_TYPE_CLASS_NUMBER = 0x00000002, ANDROIDTEXT_TYPE_CLASS_PHONE = 0x00000003, ANDROIDTEXT_TYPE_CLASS_TEXT = 0x00000001, ANDROIDTEXT_TYPE_DATETIME_VARIATION_DATE = 0x00000010, ANDROIDTEXT_TYPE_DATETIME_VARIATION_NORMAL = 0x00000000, ANDROIDTEXT_TYPE_DATETIME_VARIATION_TIME = 0x00000020, ANDROIDTEXT_TYPE_MASK_CLASS = 0x0000000f, ANDROIDTEXT_TYPE_MASK_FLAGS = 0x00fff000, ANDROIDTEXT_TYPE_MASK_VARIATION = 0x00000ff0, ANDROIDTEXT_TYPE_NULL = 0x00000000, ANDROIDTEXT_TYPE_NUMBER_FLAG_DECIMAL = 0x00002000, ANDROIDTEXT_TYPE_NUMBER_FLAG_SIGNED = 0x00001000, ANDROIDTEXT_TYPE_NUMBER_VARIATION_NORMAL = 0x00000000, ANDROIDTEXT_TYPE_NUMBER_VARIATION_PASSWORD = 0x00000010, ANDROIDTEXT_TYPE_TEXT_FLAG_AUTO_COMPLETE = 0x00010000, ANDROIDTEXT_TYPE_TEXT_FLAG_AUTO_CORRECT = 0x00008000, ANDROIDTEXT_TYPE_TEXT_FLAG_CAP_CHARACTERS = 0x00001000, ANDROIDTEXT_TYPE_TEXT_FLAG_CAP_SENTENCES = 0x00004000, ANDROIDTEXT_TYPE_TEXT_FLAG_CAP_WORDS = 0x00002000, ANDROIDTEXT_TYPE_TEXT_FLAG_ENABLE_TEXT_CONVERSION_SUGGESTIONS = 0x00100000, ANDROIDTEXT_TYPE_TEXT_FLAG_ENABLE_TEXT_SUGGESTION_SELECTED = 0x00200000, ANDROIDTEXT_TYPE_TEXT_FLAG_IME_MULTI_LINE = 0x00040000, ANDROIDTEXT_TYPE_TEXT_FLAG_MULTI_LINE = 0x00020000, ANDROIDTEXT_TYPE_TEXT_FLAG_NO_SUGGESTIONS = 0x00080000, ANDROIDTEXT_TYPE_TEXT_VARIATION_EMAIL_ADDRESS = 0x00000020, ANDROIDTEXT_TYPE_TEXT_VARIATION_EMAIL_SUBJECT = 0x00000030, ANDROIDTEXT_TYPE_TEXT_VARIATION_FILTER = 0x000000b0, ANDROIDTEXT_TYPE_TEXT_VARIATION_LONG_MESSAGE = 0x00000050, ANDROIDTEXT_TYPE_TEXT_VARIATION_NORMAL = 0x00000000, ANDROIDTEXT_TYPE_TEXT_VARIATION_PASSWORD = 0x00000080, ANDROIDTEXT_TYPE_TEXT_VARIATION_PERSON_NAME = 0x00000060, ANDROIDTEXT_TYPE_TEXT_VARIATION_PHONETIC = 0x000000c0, ANDROIDTEXT_TYPE_TEXT_VARIATION_POSTAL_ADDRESS = 0x00000070, ANDROIDTEXT_TYPE_TEXT_VARIATION_SHORT_MESSAGE = 0x00000040, ANDROIDTEXT_TYPE_TEXT_VARIATION_URI = 0x00000010, ANDROIDTEXT_TYPE_TEXT_VARIATION_VISIBLE_PASSWORD = 0x00000090, ANDROIDTEXT_TYPE_TEXT_VARIATION_WEB_EDIT_TEXT = 0x000000a0, ANDROIDTEXT_TYPE_TEXT_VARIATION_WEB_EMAIL_ADDRESS = 0x000000d0, ANDROIDTEXT_TYPE_TEXT_VARIATION_WEB_PASSWORD = 0x000000e0 }; struct TextInputProperties { SDL_TextInputType inputType; SDL_Capitalization capitalization; bool autocorrect; bool multiline; int androidInputType; }; unsigned set_text_box_front(const std::optional>& textboxRect, const TextInputProperties& inputProps); unsigned set_text_box_back(const std::optional>& textboxRect, const TextInputProperties& inputProps); void remove_text_box(unsigned textboxID); struct Text { bool is_accepting_input(); std::optional current_textbox_editing_id(); private: struct TextBoxInfo { std::optional> rect; TextInputProperties textInputProperties; unsigned id; }; void update_accepting_input(SDL_Window* window); std::optional propID; std::deque textBoxes; unsigned get_id(); friend struct InputManager; } text; #ifdef __APPLE__ SDL_Keymod CTRL_MOD = SDL_KMOD_GUI; #else SDL_Keymod CTRL_MOD = SDL_KMOD_CTRL; #endif 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, KEY_PASTE_IMAGE, KEY_DRAW_TOOL_BRUSH, KEY_DRAW_TOOL_ERASER, KEY_DRAW_TOOL_ZOOM, KEY_DRAW_TOOL_PAN, KEY_DRAW_TOOL_LASSOSELECT, KEY_DRAW_TOOL_TEXTBOX, KEY_DRAW_TOOL_RECTANGLE, KEY_DRAW_TOOL_ELLIPSE, KEY_DRAW_TOOL_RECTSELECT, KEY_DRAW_TOOL_EYEDROPPER, KEY_DRAW_TOOL_SCREENSHOT, KEY_DRAW_TOOL_LINE, KEY_SHOW_METRICS, KEY_OPEN_CHAT, KEY_SHOW_PLAYER_LIST, KEY_HOLD_TO_PAN, KEY_HOLD_TO_ZOOM, KEY_DESELECT_AND_EDIT_TOOL, KEY_ASSIGNABLE_COUNT, // Not a real key // Unassignable KEY_TEXT_BACKSPACE, KEY_TEXT_DELETE, KEY_TEXT_HOME, KEY_TEXT_END, KEY_TEXT_COPY, KEY_TEXT_CUT, KEY_TEXT_PASTE, KEY_TEXT_TAB, KEY_TEXT_SELECTALL, KEY_TEXT_UNDO, KEY_TEXT_REDO, 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, KEY_COUNT }; typedef unsigned KeyCode; bool ctrl_or_meta_held(); uint32_t make_generic_key_mod(SDL_Keymod m); void set_key_up(const SDL_KeyboardEvent& e, KeyCode kCode, bool acceptingTextInput); void set_key_down(const SDL_KeyboardEvent& e, KeyCode kCode, bool acceptingTextInput); std::vector get_multiple_finger_positions(); std::vector get_multiple_finger_motions(); void touch_finger_do_mouse_down(); void touch_finger_do_mouse_up(const SDL_TouchFingerEvent& f); void touch_finger_do_mouse_motion(const SDL_TouchFingerEvent& f); void backend_open_infinipaint_file_event(); void backend_paste_event(); void backend_input_text_event(const std::string& str); void backend_drop_file_event(const SDL_DropEvent& e); void backend_drop_text_event(const SDL_DropEvent& e); 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); void backend_key_up_update(const SDL_KeyboardEvent& e); void backend_key_down_update(const SDL_KeyboardEvent& e); 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); void backend_pen_axis_update(const SDL_PenAxisEvent& e); void backend_touch_finger_down_update(const SDL_TouchFingerEvent& e); void backend_touch_finger_up_update(const SDL_TouchFingerEvent& e); void backend_touch_finger_motion_update(const SDL_TouchFingerEvent& e); void backend_window_resize_update(const SDL_WindowEvent& e); void backend_window_scale_update(const SDL_WindowEvent& e); void set_clipboard_str(std::string_view s); void set_clipboard_plain_and_richtext_pair(const std::pair& plainAndRichtextPair); std::string get_clipboard_str_SDL(); void get_clipboard_image_data_SDL(const std::function& callback); void call_paste(CustomEvents::PasteEventDataType type, const InputManagerCallPasteInfo& info = {}); void process_text_paste(const std::string& pasteStr, bool allowRichText); std::optional lastCopiedRichText; std::string key_assignment_to_str(const Vector2ui32& k) const; Vector2ui32 key_assignment_from_str(const std::string& s) const; const KeyData& key(KeyCode kCode); struct TextCallbackArgs { std::string str; }; struct KeyCallbackArgs { KeyCode key; bool down; bool repeat; }; std::unordered_map keyAssignments; std::unordered_map defaultKeyAssignments; std::array keys; enum class MouseButton : uint8_t { LEFT = 1, MIDDLE, RIGHT } button; enum class MouseDeviceType { MOUSE, PEN, TOUCH }; struct MouseButtonCallbackArgs { MouseDeviceType deviceType; MouseButton button; bool down; uint8_t clicks; Vector2f pos; }; struct MouseMotionCallbackArgs { MouseDeviceType deviceType; Vector2f pos; Vector2f move; }; struct MouseWheelCallbackArgs { Vector2f mousePos; Vector2f amount; Vector2i tickAmount; }; struct PenButtonCallbackArgs { uint8_t button; bool down; Vector2f pos; }; struct PenTouchCallbackArgs { bool down; bool eraser; Vector2f pos; }; struct PenMotionCallbackArgs { Vector2f pos; Vector2f move; }; struct PenAxisCallbackArgs { Vector2f pos; SDL_PenAxis axis; float value; }; struct DropCallbackArgs { Vector2f pos; const char* source; const char* data; }; struct MultiFingerTouchCallbackArgs { bool down; std::vector pos; }; struct MultiFingerMotionCallbackArgs { std::vector pos; std::vector move; }; struct FingerTouchCallbackArgs { SDL_FingerID fingerID; bool down; Vector2f pos; size_t fingerDownCount; int fingerTapCount; }; struct FingerMotionCallbackArgs { SDL_FingerID fingerID; Vector2f pos; Vector2f move; size_t fingerDownCount; }; struct WindowResizeCallbackArgs { Vector2i size; float density; }; struct WindowScaleCallbackArgs { float scale; }; MainProgram& main; }; 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"}, {InputManager::KEY_PASTE_IMAGE, "Paste Image"}, {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"}, {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"}, {InputManager::KEY_DRAW_TOOL_EYEDROPPER, "Color Select Tool"}, {InputManager::KEY_DRAW_TOOL_SCREENSHOT, "Take Screenshot"}, {InputManager::KEY_DRAW_TOOL_LINE, "Line Tool"}, {InputManager::KEY_SHOW_METRICS, "Show Metrics"}, {InputManager::KEY_OPEN_CHAT, "Open Chat"}, {InputManager::KEY_SHOW_PLAYER_LIST, "Show Player List"}, {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"} })