From ade89fdab1977267c9c45912fde0d09e671169fc Mon Sep 17 00:00:00 2001 From: Tomas Maly Date: Tue, 30 Jan 2024 10:10:25 +0100 Subject: [PATCH] rewrite inputs --- sources/include/cage-core/any.h | 30 +- sources/include/cage-core/entities.h | 2 +- sources/include/cage-core/entitiesVisitor.h | 2 - sources/include/cage-core/typeIndex.h | 2 +- sources/include/cage-engine/core.h | 1 - sources/include/cage-engine/guiBuilder.h | 41 +- sources/include/cage-engine/guiComponents.h | 16 +- sources/include/cage-engine/inputs.h | 428 ++++++++++--------- sources/include/cage-engine/window.h | 2 +- sources/libengine/gui/events.cpp | 54 ++- sources/libengine/gui/gui.cpp | 11 - sources/libengine/gui/guiBuilder.cpp | 2 +- sources/libengine/gui/private.h | 24 +- sources/libengine/gui/tooltips.cpp | 2 +- sources/libengine/gui/widgets/input.cpp | 20 +- sources/libengine/inputs.cpp | 314 -------------- sources/libengine/virtualReality/openxr.cpp | 27 +- sources/libengine/window/gamepad.cpp | 10 +- sources/libengine/window/window.cpp | 242 +++++------ sources/libsimple/fpsCamera.cpp | 39 +- sources/libsimple/fullscreenSwitcher.cpp | 24 +- sources/libsimple/guiInWorld.cpp | 8 +- sources/libsimple/statisticsGui.cpp | 8 +- sources/test-core/installConsistentPaths.cpp | 12 +- 24 files changed, 492 insertions(+), 829 deletions(-) delete mode 100644 sources/libengine/inputs.cpp diff --git a/sources/include/cage-core/any.h b/sources/include/cage-core/any.h index 488e3a3b..42d67f98 100644 --- a/sources/include/cage-core/any.h +++ b/sources/include/cage-core/any.h @@ -7,18 +7,18 @@ namespace cage { namespace detail { - template + template + concept AnyValueConcept = std::is_trivially_copyable_v && std::is_trivially_destructible_v && std::is_same_v, T> && sizeof(T) <= MaxSize && sizeof(T) > 0; + + template struct alignas(16) AnyBase { AnyBase() = default; AnyBase(const AnyBase &) = default; - template + template T> CAGE_FORCE_INLINE AnyBase(const T &v) noexcept { - static_assert(std::is_trivially_copyable_v); - static_assert(sizeof(T) <= MaxSize); - static_assert(sizeof(T) > 0); detail::typeIndex(); // detect hash collisions detail::memcpy(data_, &v, sizeof(T)); type_ = detail::typeHash(); @@ -26,28 +26,32 @@ namespace cage AnyBase &operator=(const AnyBase &) = default; - template + template T> CAGE_FORCE_INLINE AnyBase &operator=(const T &v) noexcept { return *this = AnyBase(v); } - CAGE_FORCE_INLINE void clear() noexcept { type_ = m; } - CAGE_FORCE_INLINE uint32 typeHash() const noexcept { return type_; } - CAGE_FORCE_INLINE explicit operator bool() const noexcept { return type_ != m; } + template T> + CAGE_FORCE_INLINE bool has() const noexcept + { + return detail::typeHash() == type_; + } - template + template T> T get() const { - static_assert(std::is_trivially_copyable_v); - static_assert(sizeof(T) <= MaxSize); - static_assert(sizeof(T) > 0); CAGE_ASSERT(detail::typeHash() == type_); T tmp; detail::memcpy(&tmp, data_, sizeof(T)); return tmp; } + CAGE_FORCE_INLINE void clear() noexcept { type_ = m; } + CAGE_FORCE_INLINE uint32 typeHash() const noexcept { return type_; } + CAGE_FORCE_INLINE explicit operator bool() const noexcept { return type_ != m; } + static constexpr uint32 MaxSize = MaxSize_; + private: char data_[MaxSize]; uint32 type_ = m; diff --git a/sources/include/cage-core/entities.h b/sources/include/cage-core/entities.h index ca87e535..91d683d3 100644 --- a/sources/include/cage-core/entities.h +++ b/sources/include/cage-core/entities.h @@ -11,7 +11,7 @@ namespace cage class Entity; template - concept ComponentConcept = std::is_trivially_copyable_v && std::is_trivially_destructible_v; + concept ComponentConcept = std::is_trivially_copyable_v && std::is_trivially_destructible_v && std::is_same_v, T>; class CAGE_CORE_API EntityManager : private Immovable { diff --git a/sources/include/cage-core/entitiesVisitor.h b/sources/include/cage-core/entitiesVisitor.h index 04d938c8..77b80251 100644 --- a/sources/include/cage-core/entitiesVisitor.h +++ b/sources/include/cage-core/entitiesVisitor.h @@ -16,8 +16,6 @@ namespace cage template struct DecomposeLambda { - using Return = R; - using Class = T; using Params = std::tuple; }; diff --git a/sources/include/cage-core/typeIndex.h b/sources/include/cage-core/typeIndex.h index 61ccabb9..db12017a 100644 --- a/sources/include/cage-core/typeIndex.h +++ b/sources/include/cage-core/typeIndex.h @@ -11,7 +11,7 @@ namespace cage constexpr PointerRange typeName() noexcept { static_assert(std::is_same_v, T>); - static_assert(std::is_same_v>, T>); + static_assert(std::is_same_v, T>); #ifdef _MSC_VER return __FUNCSIG__; #else diff --git a/sources/include/cage-engine/core.h b/sources/include/cage-engine/core.h index 9effca38..3f14ab9f 100644 --- a/sources/include/cage-engine/core.h +++ b/sources/include/cage-engine/core.h @@ -22,7 +22,6 @@ namespace cage enum class CheckBoxStateEnum : uint32; enum class InputButtonsPlacementModeEnum : uint32; enum class GuiElementTypeEnum : uint32; - enum class InputClassEnum : uint32; enum class LightTypeEnum : uint32; enum class WindowFlags : uint32; diff --git a/sources/include/cage-engine/guiBuilder.h b/sources/include/cage-engine/guiBuilder.h index 2f12cef1..3ccbc8c2 100644 --- a/sources/include/cage-engine/guiBuilder.h +++ b/sources/include/cage-engine/guiBuilder.h @@ -6,19 +6,6 @@ namespace cage { - class EntityManager; - class Entity; - - namespace privat - { - template - CAGE_FORCE_INLINE bool guiActionWrapper(Entity *) - { - (F)(); - return StopPropagation; - } - } - namespace guiBuilder { class GuiBuilder; @@ -50,34 +37,8 @@ namespace cage BuilderItem skin(uint32 index = m); BuilderItem disabled(bool disable = true); - BuilderItem event(Delegate ev); - template - BuilderItem event() - { - return event(Delegate().bind()); - } - template - BuilderItem event(D d) - { - return event(Delegate().bind(d)); - } - template - BuilderItem event() - { - return event(Delegate().bind<&privat::guiActionWrapper>()); - } - + BuilderItem event(Delegate ev); BuilderItem update(Delegate u); - template - BuilderItem update() - { - return update(Delegate().bind()); - } - template - BuilderItem update(D d) - { - return update(Delegate().bind(d)); - } BuilderItem tooltip(const GuiTooltipComponent &t); template diff --git a/sources/include/cage-engine/guiComponents.h b/sources/include/cage-engine/guiComponents.h index 9cb6b3db..ef098ce7 100644 --- a/sources/include/cage-engine/guiComponents.h +++ b/sources/include/cage-engine/guiComponents.h @@ -2,7 +2,7 @@ #define guard_guiComponents_sdf1gh45hk485aws #include -#include +#include namespace cage { @@ -74,11 +74,14 @@ namespace cage struct CAGE_ENGINE_API GuiEventComponent { - Delegate event; + Delegate event; }; struct CAGE_ENGINE_API GuiUpdateComponent { + // called periodically from the gui itself + // useful for updating text, image, format, etc. + // do NOT use for adding/removing entities Delegate update; }; @@ -201,12 +204,9 @@ namespace cage { // input box and text area None = 0, - //ReadOnly = 1 << 0, - //SelectAllOnFocusGain = 1 << 1, - GoToEndOnFocusGain = 1 << 2, - ShowArrowButtons = 1 << 3, - AlwaysRoundValueToStep = 1 << 4, - //AcceptTabs = 1 << 5, // tab key will write tab rather than skip to next widget + ShowArrowButtons = 1 << 1, + AlwaysRoundValueToStep = 1 << 2, + GoToEndOnFocusGain = 1 << 3, }; struct CAGE_ENGINE_API GuiInputComponent diff --git a/sources/include/cage-engine/inputs.h b/sources/include/cage-engine/inputs.h index f4ea6dd8..f0a1ea42 100644 --- a/sources/include/cage-engine/inputs.h +++ b/sources/include/cage-engine/inputs.h @@ -12,242 +12,246 @@ namespace cage class VirtualReality; class VirtualRealityController; class GuiManager; + class Entity; - enum class InputClassEnum : uint32 + namespace input { - None = 0, - FocusGain, - FocusLose, - WindowClose, - WindowShow, - WindowHide, // InputWindow - WindowMove, - WindowResize, // InputWindowValue - MouseMove, - MousePress, - MouseDoublePress, - MouseRelease, // InputMouse - MouseWheel, // InputMouseWheel - KeyPress, - KeyRelease, - KeyRepeat, - KeyChar, // InputKey - GamepadConnected, - GamepadDisconnected, // InputGamepadState - GamepadPress, - GamepadRelease, // InputGamepadKey - GamepadAxis, // InputGamepadAxis - HeadsetConnected, - HeadsetDisconnected, // InputHeadsetState - HeadsetPose, // InputHeadsetPose - ControllerConnected, - ControllerDisconnected, // InputControllerState - ControllerPose, // InputControllerPose - ControllerPress, - ControllerRelease, // InputControllerKey - ControllerAxis, // InputControllerAxis - GuiWidget, // InputGuiWidget - Custom = 1000, - }; - - struct InputWindow - { - Window *window = nullptr; - }; + // window - struct InputWindowValue - { - Window *window = nullptr; - Vec2i value; - }; + namespace privat + { + struct BaseWindow + { + Window *window = nullptr; + }; + } + struct WindowFocusGain : privat::BaseWindow + {}; + struct WindowFocusLose : privat::BaseWindow + {}; + struct WindowClose : privat::BaseWindow + {}; + struct WindowShow : privat::BaseWindow + {}; + struct WindowHide : privat::BaseWindow + {}; + struct WindowMove + { + Window *window = nullptr; + Vec2i position; + }; + struct WindowResize + { + Window *window = nullptr; + Vec2i size; + }; - struct InputMouse - { - Window *window = nullptr; - Vec2 position; - MouseButtonsFlags buttons = MouseButtonsFlags::None; - ModifiersFlags mods = ModifiersFlags::None; - }; + // mouse - struct InputMouseWheel - { - Window *window = nullptr; - Vec2 position; - Real wheel; - ModifiersFlags mods = ModifiersFlags::None; - }; + namespace privat + { + struct BaseMouse + { + Window *window = nullptr; + Vec2 position; + MouseButtonsFlags buttons = MouseButtonsFlags::None; + ModifiersFlags mods = ModifiersFlags::None; + }; + } + struct MouseMove : privat::BaseMouse + {}; + struct MousePress : privat::BaseMouse + {}; + struct MouseDoublePress : privat::BaseMouse + {}; + struct MouseRelease : privat::BaseMouse + {}; + struct MouseWheel + { + Window *window = nullptr; + Vec2 position; + Real wheel; + ModifiersFlags mods = ModifiersFlags::None; + }; - struct InputKey - { - Window *window = nullptr; - uint32 key = 0; // glfw key or utf-32 character - ModifiersFlags mods = ModifiersFlags::None; - }; + // keyboard - struct InputGamepadState - { - Gamepad *gamepad = nullptr; - }; + namespace privat + { + struct BaseKey + { + Window *window = nullptr; + uint32 key = 0; // glfw key or utf-32 character + ModifiersFlags mods = ModifiersFlags::None; + }; + } + struct KeyPress : privat::BaseKey + {}; + struct KeyRelease : privat::BaseKey + {}; + struct KeyRepeat : privat::BaseKey + {}; + struct Character + { + Window *window = nullptr; + uint32 character = 0; // utf-32 character + ModifiersFlags mods = ModifiersFlags::None; + }; - struct InputGamepadKey - { - Gamepad *gamepad = nullptr; - uint32 key = 0; - }; + // gamepad - struct InputGamepadAxis - { - Gamepad *gamepad = nullptr; - uint32 axis = 0; - Real value; - }; + namespace privat + { + struct BaseGamepad + { + Gamepad *gamepad = nullptr; + }; + struct BaseGamepadKey + { + Gamepad *gamepad = nullptr; + uint32 key = 0; + }; + } + struct GamepadConnected : privat::BaseGamepad + {}; + struct GamepadDisconnected : privat::BaseGamepad + {}; + struct GamepadPress : privat::BaseGamepadKey + {}; + struct GamepadRelease : privat::BaseGamepadKey + {}; + struct GamepadAxis + { + Gamepad *gamepad = nullptr; + uint32 axis = 0; + Real value; + }; - struct InputHeadsetState - { - VirtualReality *headset = nullptr; - }; + // headset - struct InputHeadsetPose - { - Transform pose; // in local space of the virtual reality - VirtualReality *headset = nullptr; - }; + namespace privat + { + struct BaseHeadset + { + VirtualReality *headset = nullptr; + }; + } + struct HeadsetConnected : privat::BaseHeadset + {}; + struct HeadsetDisconnected : privat::BaseHeadset + {}; + struct HeadsetPose + { + Transform pose; // in local space of the virtual reality + VirtualReality *headset = nullptr; + }; - struct InputControllerState - { - VirtualRealityController *controller = nullptr; - }; + // controller - struct InputControllerPose - { - Transform pose; // grip pose in local space of the virtual reality - VirtualRealityController *controller = nullptr; - }; + namespace privat + { + struct BaseController + { + VirtualRealityController *controller = nullptr; + }; + struct BaseControllerKey + { + VirtualRealityController *controller = nullptr; + uint32 key = 0; + }; + } + struct ControllerConnected : privat::BaseController + {}; + struct ControllerDisconnected : privat::BaseController + {}; + struct ControllerPose + { + Transform pose; // grip pose in local space of the virtual reality + VirtualRealityController *controller = nullptr; + }; + struct ControllerPress : privat::BaseControllerKey + {}; + struct ControllerRelease : privat::BaseControllerKey + {}; + struct ControllerAxis + { + VirtualRealityController *controller = nullptr; + uint32 axis = 0; + Real value; + }; - struct InputControllerKey - { - VirtualRealityController *controller = nullptr; - uint32 key = 0; - }; + // gui - struct InputControllerAxis - { - VirtualRealityController *controller = nullptr; - uint32 axis = 0; - Real value; - }; + struct GuiValue + { + GuiManager *manager = nullptr; + Entity *entity = nullptr; + }; - struct InputGuiWidget - { - GuiManager *manager = nullptr; - uint32 widget = 0; - }; + struct GuiInputConfirm + { + GuiManager *manager = nullptr; + Entity *entity = nullptr; + }; + } - struct GenericInput - { - using Any = detail::AnyBase<44>; - Any data; - InputClassEnum type = InputClassEnum::None; - }; + using GenericInput = detail::AnyBase<44>; - struct CAGE_ENGINE_API InputsGeneralizer - { - bool focusGain(InputWindow); - bool focusLose(InputWindow); - bool windowClose(InputWindow); - bool windowShow(InputWindow); - bool windowHide(InputWindow); - bool windowMove(InputWindowValue); - bool windowResize(InputWindowValue); - bool mouseMove(InputMouse); - bool mousePress(InputMouse); - bool mouseDoublePress(InputMouse); - bool mouseRelease(InputMouse); - bool mouseWheel(InputMouseWheel); - bool keyPress(InputKey); - bool keyRelease(InputKey); - bool keyRepeat(InputKey); - bool keyChar(InputKey); - bool gamepadConnected(InputGamepadState); - bool gamepadDisconnected(InputGamepadState); - bool gamepadPress(InputGamepadKey); - bool gamepadRelease(InputGamepadKey); - bool gamepadAxis(InputGamepadAxis); - bool headsetConnected(InputHeadsetState); - bool headsetDisconnected(InputHeadsetState); - bool headsetPose(InputHeadsetPose); - bool controllerConnected(InputControllerState); - bool controllerDisconnected(InputControllerState); - bool controllerPose(InputControllerPose); - bool controllerPress(InputControllerKey); - bool controllerRelease(InputControllerKey); - bool controllerAxis(InputControllerAxis); - bool guiWidget(InputGuiWidget); - bool custom(const GenericInput::Any &); - bool unknown(const GenericInput &); - - EventDispatcher dispatcher; - }; - - struct CAGE_ENGINE_API InputsDispatchers - { - EventDispatcher focusGain, focusLose, windowClose, windowShow, windowHide; - EventDispatcher windowMove, windowResize; - EventDispatcher mouseMove, mousePress, mouseDoublePress, mouseRelease; - EventDispatcher mouseWheel; - EventDispatcher keyPress, keyRelease, keyRepeat, keyChar; - EventDispatcher gamepadConnected, gamepadDisconnected; - EventDispatcher gamepadPress, gamepadRelease; - EventDispatcher gamepadAxis; - EventDispatcher headsetConnected, headsetDisconnected; - EventDispatcher headsetPose; - EventDispatcher controllerConnected, controllerDisconnected; - EventDispatcher controllerPose; - EventDispatcher controllerPress, controllerRelease; - EventDispatcher controllerAxis; - EventDispatcher guiWidget; - EventDispatcher custom; - EventDispatcher unknown; - - bool dispatch(const GenericInput &input); - }; - - struct CAGE_ENGINE_API InputsListeners - { - EventListener focusGain, focusLose, windowClose, windowShow, windowHide; - EventListener windowMove, windowResize; - EventListener mouseMove, mousePress, mouseDoublePress, mouseRelease; - EventListener mouseWheel; - EventListener keyPress, keyRelease, keyRepeat, keyChar; - EventListener gamepadConnected, gamepadDisconnected; - EventListener gamepadPress, gamepadRelease; - EventListener gamepadAxis; - EventListener headsetConnected, headsetDisconnected; - EventListener headsetPose; - EventListener controllerConnected, controllerDisconnected; - EventListener controllerPose; - EventListener controllerPress, controllerRelease; - EventListener controllerAxis; - EventListener guiWidget; - EventListener custom; - EventListener unknown; - - void attach(InputsDispatchers *dispatchers, sint32 order = 0); - void bind(InputsGeneralizer *generalizer); - }; - - template - requires(std::is_invocable_r_v || std::is_invocable_r_v) - auto inputListener(Callable &&callable) + template + concept InputFilterConcept = detail::AnyValueConcept; + + template + requires((std::is_invocable_r_v || std::is_invocable_r_v) && !std::is_same_v) + auto inputFilter(Callable &&callable) { - return [cl = std::move(callable)](const GenericInput &in) + return [cl = std::move(callable)](GenericInput in) -> bool { - if (in.type == C) - return cl(in.data.get()); + if (!in.has()) + return false; if constexpr (std::is_same_v, bool>) + return cl(in.get()); + else + { + cl(in.get()); return false; + } }; } + + namespace privat + { + template + struct ExtractParam; + template + struct ExtractParam + { + using Param = P; + }; + template + struct ExtractParam + { + using Param = P; + }; + template + struct ExtractParam + { + using Param = P; + }; + } + + template + auto inputFilter(Callable &&callable) + { + using Param = typename privat::ExtractParam::Param; + return inputFilter(std::move(callable)); + } + + template + auto inputFilter(Func *func) + { + using Param = typename privat::ExtractParam::Param; + return inputFilter([func](Param in) { return func(in); }); + } } #endif // guard_inputs_juhgf98ser4g diff --git a/sources/include/cage-engine/window.h b/sources/include/cage-engine/window.h index c5c278a3..67977f29 100644 --- a/sources/include/cage-engine/window.h +++ b/sources/include/cage-engine/window.h @@ -26,7 +26,7 @@ namespace cage bool isFocused() const; bool isFullscreen() const; bool isMaximized() const; - bool isWindowed() const; // not hidden, not minimized, not maximized and not fullscreen + bool isWindowed() const; // visible, not maximized, and not fullscreen bool isMinimized() const; bool isHidden() const; bool isVisible() const; // not hidden and not minimized diff --git a/sources/libengine/gui/events.cpp b/sources/libengine/gui/events.cpp index 74d4638e..f01a29da 100644 --- a/sources/libengine/gui/events.cpp +++ b/sources/libengine/gui/events.cpp @@ -89,32 +89,50 @@ namespace cage bool GuiManager::handleInput(const GenericInput &in) { GuiImpl *impl = (GuiImpl *)this; - return impl->inputsDispatchers.dispatch(in); + if (in.has()) + return impl->mousePress(in.get()); + if (in.has()) + return impl->mouseDoublePress(in.get()); + if (in.has()) + return impl->mouseRelease(in.get()); + if (in.has()) + return impl->mouseMove(in.get()); + if (in.has()) + return impl->mouseWheel(in.get()); + if (in.has()) + return impl->keyPress(in.get()); + if (in.has()) + return impl->keyRepeat(in.get()); + if (in.has()) + return impl->keyRelease(in.get()); + if (in.has()) + return impl->keyChar(in.get()); + return false; } - bool GuiImpl::mousePress(InputMouse in) + bool GuiImpl::mousePress(input::MousePress in) { focusName = 0; return passMouseEvent(this, in.buttons, in.mods, in.position); } - bool GuiImpl::mouseDoublePress(InputMouse in) + bool GuiImpl::mouseDoublePress(input::MouseDoublePress in) { return passMouseEvent(this, in.buttons, in.mods, in.position); } - bool GuiImpl::mouseRelease(InputMouse in) + bool GuiImpl::mouseRelease(input::MouseRelease in) { return passMouseEvent(this, in.buttons, in.mods, in.position); } - bool GuiImpl::mouseMove(InputMouse in) + bool GuiImpl::mouseMove(input::MouseMove in) { ttMouseMove(in); return passMouseEvent(this, in.buttons, in.mods, in.position); } - bool GuiImpl::mouseWheel(InputMouseWheel in) + bool GuiImpl::mouseWheel(input::MouseWheel in) { Vec2 pt; if (!eventPoint(in.position, pt)) @@ -130,22 +148,22 @@ namespace cage return false; } - bool GuiImpl::keyPress(InputKey in) + bool GuiImpl::keyPress(input::KeyPress in) { return passKeyEvent<&WidgetItem::keyPress>(this, in.key, in.mods); } - bool GuiImpl::keyRepeat(InputKey in) + bool GuiImpl::keyRepeat(input::KeyRepeat in) { return passKeyEvent<&WidgetItem::keyRepeat>(this, in.key, in.mods); } - bool GuiImpl::keyRelease(InputKey in) + bool GuiImpl::keyRelease(input::KeyRelease in) { return passKeyEvent<&WidgetItem::keyRelease>(this, in.key, in.mods); } - bool GuiImpl::keyChar(InputKey in) + bool GuiImpl::keyChar(input::Character in) { Vec2 dummy; if (!eventPoint(inputMouse, dummy)) @@ -153,26 +171,28 @@ namespace cage bool res = false; for (auto f : focused(this)) { - if (f->widgetState.disabled || f->keyChar(in.key)) + if (f->widgetState.disabled || f->keyChar(in.character)) res = true; } return res; } - void HierarchyItem::fireWidgetEvent() const + void HierarchyItem::fireWidgetEvent(GenericInput in) const { if (ent->has()) { GuiEventComponent &v = ent->value(); if (v.event) { - if (v.event(ent)) + if (v.event(in)) return; } } - InputGuiWidget e; - e.manager = impl; - e.widget = ent->name(); - impl->widgetEvent.dispatch({ e, InputClassEnum::GuiWidget }); + impl->widgetEvent.dispatch(in); + } + + void HierarchyItem::fireWidgetEvent() const + { + fireWidgetEvent(input::GuiValue{ impl, ent }); } } diff --git a/sources/libengine/gui/gui.cpp b/sources/libengine/gui/gui.cpp index 21cb0dd9..6c9ad9db 100644 --- a/sources/libengine/gui/gui.cpp +++ b/sources/libengine/gui/gui.cpp @@ -21,17 +21,6 @@ namespace cage CAGE_EVAL_SMALL(CAGE_EXPAND_ARGS(GCHL_GENERATE, GCHL_GUI_COMMON_COMPONENTS, GCHL_GUI_WIDGET_COMPONENTS, GCHL_GUI_LAYOUT_COMPONENTS)); #undef GCHL_GENERATE - inputsListeners.attach(&inputsDispatchers); - inputsListeners.mousePress.bind([this](InputMouse in) { return this->mousePress(in); }); - inputsListeners.mouseDoublePress.bind([this](InputMouse in) { return this->mouseDoublePress(in); }); - inputsListeners.mouseRelease.bind([this](InputMouse in) { return this->mouseRelease(in); }); - inputsListeners.mouseMove.bind([this](InputMouse in) { return this->mouseMove(in); }); - inputsListeners.mouseWheel.bind([this](InputMouseWheel in) { return this->mouseWheel(in); }); - inputsListeners.keyPress.bind([this](InputKey in) { return this->keyPress(in); }); - inputsListeners.keyRepeat.bind([this](InputKey in) { return this->keyRepeat(in); }); - inputsListeners.keyRelease.bind([this](InputKey in) { return this->keyRelease(in); }); - inputsListeners.keyChar.bind([this](InputKey in) { return this->keyChar(in); }); - skins.reserve(config.skinsCount); for (uint32 i = 0; i < config.skinsCount; i++) { diff --git a/sources/libengine/gui/guiBuilder.cpp b/sources/libengine/gui/guiBuilder.cpp index e033355c..e7bedea4 100644 --- a/sources/libengine/gui/guiBuilder.cpp +++ b/sources/libengine/gui/guiBuilder.cpp @@ -174,7 +174,7 @@ namespace cage return *this; } - BuilderItem BuilderItem::event(Delegate ev) + BuilderItem BuilderItem::event(Delegate ev) { (*this)->value().event = ev; return *this; diff --git a/sources/libengine/gui/private.h b/sources/libengine/gui/private.h index 8afe79c4..27bb6164 100644 --- a/sources/libengine/gui/private.h +++ b/sources/libengine/gui/private.h @@ -78,6 +78,7 @@ namespace cage // helpers void moveToWindow(bool horizontal, bool vertical); HierarchyItem *findParentOf(HierarchyItem *item); + void fireWidgetEvent(GenericInput in) const; void fireWidgetEvent() const; }; @@ -313,18 +314,15 @@ namespace cage } graphicsData; RenderQueue *activeQueue = nullptr; - bool mouseMove(InputMouse); - bool mousePress(InputMouse); - bool mouseDoublePress(InputMouse); - bool mouseRelease(InputMouse); - bool mouseWheel(InputMouseWheel); - bool keyPress(InputKey); - bool keyRelease(InputKey); - bool keyRepeat(InputKey); - bool keyChar(InputKey); - - InputsDispatchers inputsDispatchers; - InputsListeners inputsListeners; + bool mouseMove(input::MouseMove); + bool mousePress(input::MousePress); + bool mouseDoublePress(input::MouseDoublePress); + bool mouseRelease(input::MouseRelease); + bool mouseWheel(input::MouseWheel); + bool keyPress(input::KeyPress); + bool keyRelease(input::KeyRelease); + bool keyRepeat(input::KeyRepeat); + bool keyChar(input::Character); std::vector mouseEventReceivers; bool eventsEnabled = false; @@ -339,7 +337,7 @@ namespace cage sint32 ttNextOrder = 0; std::vector ttData; EventListener ttRemovedListener; - void ttMouseMove(InputMouse in); + void ttMouseMove(input::MouseMove in); void updateTooltips(); void clearTooltips(); bool tooltipRemoved(Entity *e); diff --git a/sources/libengine/gui/tooltips.cpp b/sources/libengine/gui/tooltips.cpp index 099d67c5..3a8d0581 100644 --- a/sources/libengine/gui/tooltips.cpp +++ b/sources/libengine/gui/tooltips.cpp @@ -2,7 +2,7 @@ namespace cage { - void GuiImpl::ttMouseMove(InputMouse in) + void GuiImpl::ttMouseMove(input::MouseMove in) { Vec2 pt; if (!eventPoint(in.position, pt)) diff --git a/sources/libengine/gui/widgets/input.cpp b/sources/libengine/gui/widgets/input.cpp index b4584fe4..fcc65bee 100644 --- a/sources/libengine/gui/widgets/input.cpp +++ b/sources/libengine/gui/widgets/input.cpp @@ -85,7 +85,7 @@ namespace cage template T consolidate(T value, T a, T b, T s) { - if ((data.style & InputStyleFlags::AlwaysRoundValueToStep) == InputStyleFlags::AlwaysRoundValueToStep && (value % s) != 0) + if (any(data.style & InputStyleFlags::AlwaysRoundValueToStep) && (value % s) != 0) value -= value % s; return clamp(value, a, b); } @@ -136,8 +136,8 @@ namespace cage } else data.valid = false; + break; } - break; case InputTypeEnum::Real: { if (isReal(data.value)) @@ -148,8 +148,8 @@ namespace cage } else data.valid = false; + break; } - break; case InputTypeEnum::Email: // todo break; @@ -316,14 +316,14 @@ namespace cage { if (cursor > 0) cursor--; + break; } - break; case 262: // right { if (cursor < len) cursor++; + break; } - break; case 259: // backspace { if (len == 0 || cursor == 0) @@ -333,8 +333,8 @@ namespace cage data.value = utf32to8string(utf32); validate(); hierarchy->fireWidgetEvent(); + break; } - break; case 261: // delete { if (cursor == len) @@ -343,8 +343,14 @@ namespace cage data.value = utf32to8string(utf32); validate(); hierarchy->fireWidgetEvent(); + break; + } + case 257: // enter + { + if (data.valid) + hierarchy->fireWidgetEvent(input::GuiInputConfirm{ hierarchy->impl, hierarchy->ent }); + break; } - break; } return true; } diff --git a/sources/libengine/inputs.cpp b/sources/libengine/inputs.cpp deleted file mode 100644 index 3c41121c..00000000 --- a/sources/libengine/inputs.cpp +++ /dev/null @@ -1,314 +0,0 @@ -#include - -namespace cage -{ - static_assert(sizeof(GenericInput) == 64); - -#define GENERALIZER(CLASS) \ - GenericInput g; \ - g.data = in; \ - g.type = InputClassEnum::CLASS; \ - return dispatcher.dispatch(g); - - bool InputsGeneralizer::focusGain(InputWindow in) - { - GENERALIZER(FocusGain); - } - - bool InputsGeneralizer::focusLose(InputWindow in) - { - GENERALIZER(FocusLose); - } - - bool InputsGeneralizer::windowClose(InputWindow in) - { - GENERALIZER(WindowClose); - } - - bool InputsGeneralizer::windowShow(InputWindow in) - { - GENERALIZER(WindowShow); - } - - bool InputsGeneralizer::windowHide(InputWindow in) - { - GENERALIZER(WindowHide); - } - - bool InputsGeneralizer::windowMove(InputWindowValue in) - { - GENERALIZER(WindowMove); - } - - bool InputsGeneralizer::windowResize(InputWindowValue in) - { - GENERALIZER(WindowResize); - } - - bool InputsGeneralizer::mouseMove(InputMouse in) - { - GENERALIZER(MouseMove); - } - - bool InputsGeneralizer::mousePress(InputMouse in) - { - GENERALIZER(MousePress); - } - - bool InputsGeneralizer::mouseDoublePress(InputMouse in) - { - GENERALIZER(MouseDoublePress); - } - - bool InputsGeneralizer::mouseRelease(InputMouse in) - { - GENERALIZER(MouseRelease); - } - - bool InputsGeneralizer::mouseWheel(InputMouseWheel in) - { - GENERALIZER(MouseWheel); - } - - bool InputsGeneralizer::keyPress(InputKey in) - { - GENERALIZER(KeyPress); - } - - bool InputsGeneralizer::keyRelease(InputKey in) - { - GENERALIZER(KeyRelease); - } - - bool InputsGeneralizer::keyRepeat(InputKey in) - { - GENERALIZER(KeyRepeat); - } - - bool InputsGeneralizer::keyChar(InputKey in) - { - GENERALIZER(KeyChar); - } - - bool InputsGeneralizer::gamepadConnected(InputGamepadState in) - { - GENERALIZER(GamepadConnected); - } - - bool InputsGeneralizer::gamepadDisconnected(InputGamepadState in) - { - GENERALIZER(GamepadDisconnected); - } - - bool InputsGeneralizer::gamepadPress(InputGamepadKey in) - { - GENERALIZER(GamepadPress); - } - - bool InputsGeneralizer::gamepadRelease(InputGamepadKey in) - { - GENERALIZER(GamepadRelease); - } - - bool InputsGeneralizer::gamepadAxis(InputGamepadAxis in) - { - GENERALIZER(GamepadAxis); - } - - bool InputsGeneralizer::headsetConnected(InputHeadsetState in) - { - GENERALIZER(HeadsetConnected); - } - - bool InputsGeneralizer::headsetDisconnected(InputHeadsetState in) - { - GENERALIZER(HeadsetDisconnected); - } - - bool InputsGeneralizer::headsetPose(InputHeadsetPose in) - { - GENERALIZER(ControllerDisconnected); - } - - bool InputsGeneralizer::controllerConnected(InputControllerState in) - { - GENERALIZER(ControllerConnected); - } - - bool InputsGeneralizer::controllerDisconnected(InputControllerState in) - { - GENERALIZER(ControllerDisconnected); - } - - bool InputsGeneralizer::controllerPose(InputControllerPose in) - { - GENERALIZER(ControllerDisconnected); - } - - bool InputsGeneralizer::controllerPress(InputControllerKey in) - { - GENERALIZER(ControllerPress); - } - - bool InputsGeneralizer::controllerRelease(InputControllerKey in) - { - GENERALIZER(ControllerRelease); - } - - bool InputsGeneralizer::controllerAxis(InputControllerAxis in) - { - GENERALIZER(ControllerAxis); - } - - bool InputsGeneralizer::guiWidget(InputGuiWidget in) - { - GENERALIZER(GuiWidget); - } - - bool InputsGeneralizer::custom(const GenericInput::Any &in) - { - GENERALIZER(Custom); - } - - bool InputsGeneralizer::unknown(const GenericInput &in) - { - return dispatcher.dispatch(in); - } - -#undef GENERALIZER - - bool InputsDispatchers::dispatch(const GenericInput &in) - { -#define EVENT(CLASS, NAME, TYPE) \ - if (in.type == InputClassEnum::CLASS && in.data.typeHash() == detail::typeHash()) \ - return NAME.dispatch(in.data.get()); - - EVENT(FocusGain, focusGain, InputWindow); - EVENT(FocusLose, focusLose, InputWindow); - EVENT(WindowClose, windowClose, InputWindow); - EVENT(WindowShow, windowShow, InputWindow); - EVENT(WindowHide, windowHide, InputWindow); - EVENT(WindowMove, windowMove, InputWindowValue); - EVENT(WindowResize, windowResize, InputWindowValue); - EVENT(MouseMove, mouseMove, InputMouse); - EVENT(MousePress, mousePress, InputMouse); - EVENT(MouseDoublePress, mouseDoublePress, InputMouse); - EVENT(MouseRelease, mouseRelease, InputMouse); - EVENT(MouseWheel, mouseWheel, InputMouseWheel); - EVENT(KeyPress, keyPress, InputKey); - EVENT(KeyRelease, keyRelease, InputKey); - EVENT(KeyRepeat, keyRepeat, InputKey); - EVENT(KeyChar, keyChar, InputKey); - EVENT(GamepadConnected, gamepadConnected, InputGamepadState); - EVENT(GamepadDisconnected, gamepadDisconnected, InputGamepadState); - EVENT(GamepadPress, gamepadPress, InputGamepadKey); - EVENT(GamepadRelease, gamepadRelease, InputGamepadKey); - EVENT(GamepadAxis, gamepadAxis, InputGamepadAxis); - EVENT(HeadsetConnected, headsetConnected, InputHeadsetState); - EVENT(HeadsetDisconnected, headsetDisconnected, InputHeadsetState); - EVENT(HeadsetPose, headsetPose, InputHeadsetPose); - EVENT(ControllerConnected, controllerConnected, InputControllerState); - EVENT(ControllerDisconnected, controllerDisconnected, InputControllerState); - EVENT(ControllerPose, controllerPose, InputControllerPose); - EVENT(ControllerPress, controllerPress, InputControllerKey); - EVENT(ControllerRelease, controllerRelease, InputControllerKey); - EVENT(ControllerAxis, controllerAxis, InputControllerAxis); - EVENT(GuiWidget, guiWidget, InputGuiWidget); -#undef EVENT - - if (in.type == InputClassEnum::Custom) - return custom.dispatch(in.data); - - return unknown.dispatch(in); - } - - void InputsListeners::attach(InputsDispatchers *dispatchers, sint32 order) - { -#define EVENT(CLASS, NAME, TYPE) \ - if (dispatchers) \ - NAME.attach(dispatchers->NAME, order); \ - else \ - NAME.detach(); - - EVENT(FocusGain, focusGain, InputWindow); - EVENT(FocusLose, focusLose, InputWindow); - EVENT(WindowClose, windowClose, InputWindow); - EVENT(WindowShow, windowShow, InputWindow); - EVENT(WindowHide, windowHide, InputWindow); - EVENT(WindowMove, windowMove, InputWindowValue); - EVENT(WindowResize, windowResize, InputWindowValue); - EVENT(MouseMove, mouseMove, InputMouse); - EVENT(MousePress, mousePress, InputMouse); - EVENT(MouseDoublePress, mouseDoublePress, InputMouse); - EVENT(MouseRelease, mouseRelease, InputMouse); - EVENT(MouseWheel, mouseWheel, InputMouseWheel); - EVENT(KeyPress, keyPress, InputKey); - EVENT(KeyRelease, keyRelease, InputKey); - EVENT(KeyRepeat, keyRepeat, InputKey); - EVENT(KeyChar, keyChar, InputKey); - EVENT(GamepadConnected, gamepadConnected, InputGamepadState); - EVENT(GamepadDisconnected, gamepadDisconnected, InputGamepadState); - EVENT(GamepadPress, gamepadPress, InputGamepadKey); - EVENT(GamepadRelease, gamepadRelease, InputGamepadKey); - EVENT(GamepadAxis, gamepadAxis, InputGamepadAxis); - EVENT(HeadsetConnected, headsetConnected, InputHeadsetState); - EVENT(HeadsetDisconnected, headsetDisconnected, InputHeadsetState); - EVENT(HeadsetPose, headsetPose, InputHeadsetPose); - EVENT(ControllerConnected, controllerConnected, InputControllerState); - EVENT(ControllerDisconnected, controllerDisconnected, InputControllerState); - EVENT(ControllerPose, controllerPose, InputControllerPose); - EVENT(ControllerPress, controllerPress, InputControllerKey); - EVENT(ControllerRelease, controllerRelease, InputControllerKey); - EVENT(ControllerAxis, controllerAxis, InputControllerAxis); - EVENT(GuiWidget, guiWidget, InputGuiWidget); - - EVENT(Custom, custom, const GenericInput::Any &); - EVENT(Unknown, unknown, const GenericInput &); -#undef EVENT - } - - void InputsListeners::bind(InputsGeneralizer *generalizer) - { -#define EVENT(CLASS, NAME, TYPE) \ - if (generalizer) \ - NAME.bind([generalizer](TYPE in) { return generalizer->NAME(in); }); \ - else \ - NAME.clear(); - - EVENT(FocusGain, focusGain, InputWindow); - EVENT(FocusLose, focusLose, InputWindow); - EVENT(WindowClose, windowClose, InputWindow); - EVENT(WindowShow, windowShow, InputWindow); - EVENT(WindowHide, windowHide, InputWindow); - EVENT(WindowMove, windowMove, InputWindowValue); - EVENT(WindowResize, windowResize, InputWindowValue); - EVENT(MouseMove, mouseMove, InputMouse); - EVENT(MousePress, mousePress, InputMouse); - EVENT(MouseDoublePress, mouseDoublePress, InputMouse); - EVENT(MouseRelease, mouseRelease, InputMouse); - EVENT(MouseWheel, mouseWheel, InputMouseWheel); - EVENT(KeyPress, keyPress, InputKey); - EVENT(KeyRelease, keyRelease, InputKey); - EVENT(KeyRepeat, keyRepeat, InputKey); - EVENT(KeyChar, keyChar, InputKey); - EVENT(GamepadConnected, gamepadConnected, InputGamepadState); - EVENT(GamepadDisconnected, gamepadDisconnected, InputGamepadState); - EVENT(GamepadPress, gamepadPress, InputGamepadKey); - EVENT(GamepadRelease, gamepadRelease, InputGamepadKey); - EVENT(GamepadAxis, gamepadAxis, InputGamepadAxis); - EVENT(HeadsetConnected, headsetConnected, InputHeadsetState); - EVENT(HeadsetDisconnected, headsetDisconnected, InputHeadsetState); - EVENT(HeadsetPose, headsetPose, InputHeadsetPose); - EVENT(ControllerConnected, controllerConnected, InputControllerState); - EVENT(ControllerDisconnected, controllerDisconnected, InputControllerState); - EVENT(ControllerPose, controllerPose, InputControllerPose); - EVENT(ControllerPress, controllerPress, InputControllerKey); - EVENT(ControllerRelease, controllerRelease, InputControllerKey); - EVENT(ControllerAxis, controllerAxis, InputControllerAxis); - EVENT(GuiWidget, guiWidget, InputGuiWidget); - - EVENT(Custom, custom, const GenericInput::Any &); - EVENT(Unknown, unknown, const GenericInput &); -#undef EVENT - } -} diff --git a/sources/libengine/virtualReality/openxr.cpp b/sources/libengine/virtualReality/openxr.cpp index da334abe..563eb3b6 100644 --- a/sources/libengine/virtualReality/openxr.cpp +++ b/sources/libengine/virtualReality/openxr.cpp @@ -569,8 +569,13 @@ namespace cage check(xrLocateSpace(viewSpace, localSpace, time, &location)); headTransform = poseToTranform(location.pose); if (valueChange(tracking, (location.locationFlags & TrackingMask) == TrackingMask)) - eventsQueue.push_back(GenericInput{ InputHeadsetState{ this }, tracking ? InputClassEnum::HeadsetConnected : InputClassEnum::HeadsetDisconnected }); - eventsQueue.push_back(GenericInput{ InputHeadsetPose{ headTransform, this }, InputClassEnum::HeadsetPose }); + { + if (tracking) + eventsQueue.push_back(input::HeadsetConnected{ this }); + else + eventsQueue.push_back(input::HeadsetDisconnected{ this }); + } + eventsQueue.push_back(input::HeadsetPose{ headTransform, this }); } for (VirtualRealityControllerImpl &cntrl : controllers) @@ -594,8 +599,13 @@ namespace cage } if (valueChange(cntrl.tracking, nextTracking)) - eventsQueue.push_back(GenericInput{ InputControllerState{ &cntrl }, nextTracking ? InputClassEnum::ControllerConnected : InputClassEnum::ControllerDisconnected }); - eventsQueue.push_back(GenericInput{ InputControllerPose{ cntrl.grip.transform, &cntrl }, InputClassEnum::ControllerPose }); + { + if (nextTracking) + eventsQueue.push_back(input::ControllerConnected{ &cntrl }); + else + eventsQueue.push_back(input::ControllerDisconnected{ &cntrl }); + } + eventsQueue.push_back(input::ControllerPose{ cntrl.grip.transform, &cntrl }); for (uint32 i = 0; i < cntrl.axes.size(); i++) { @@ -609,7 +619,7 @@ namespace cage check(xrGetActionStateFloat(session, &info, &state)); cntrl.axes[i] = state.currentState; if (state.changedSinceLastSync) - eventsQueue.push_back(GenericInput{ InputControllerAxis{ &cntrl, i, state.currentState }, InputClassEnum::ControllerAxis }); + eventsQueue.push_back(input::ControllerAxis{ &cntrl, i, state.currentState }); } for (uint32 i = 0; i < cntrl.buts.size(); i++) @@ -624,7 +634,12 @@ namespace cage check(xrGetActionStateBoolean(session, &info, &state)); cntrl.buts[i] = state.currentState; if (state.changedSinceLastSync) - eventsQueue.push_back(GenericInput{ InputControllerKey{ &cntrl, i }, state.currentState ? InputClassEnum::ControllerPress : InputClassEnum::ControllerRelease }); + { + if (state.currentState) + eventsQueue.push_back(input::ControllerPress{ &cntrl, i }); + else + eventsQueue.push_back(input::ControllerRelease{ &cntrl, i }); + } } } diff --git a/sources/libengine/window/gamepad.cpp b/sources/libengine/window/gamepad.cpp index 9decf548..0fbf50cb 100644 --- a/sources/libengine/window/gamepad.cpp +++ b/sources/libengine/window/gamepad.cpp @@ -101,15 +101,15 @@ namespace cage if (abs(a) < deadzone) a = 0; if (a != axes2[i]) - eventsQueue.push(GenericInput{ InputGamepadAxis{ this, i, axes1[i] }, InputClassEnum::GamepadAxis }); + eventsQueue.push(input::GamepadAxis{ this, i, axes1[i] }); } for (uint32 i = 0; i < buts1.size(); i++) { if (buts1[i] && !buts2[i]) - eventsQueue.push(GenericInput{ InputGamepadKey{ this, i }, InputClassEnum::GamepadPress }); + eventsQueue.push(input::GamepadPress{ this, i }); else if (!buts1[i] && buts2[i]) - eventsQueue.push(GenericInput{ InputGamepadKey{ this, i }, InputClassEnum::GamepadRelease }); + eventsQueue.push(input::GamepadRelease{ this, i }); } axes2 = axes1; @@ -143,7 +143,7 @@ namespace cage { GamepadImpl *g = d.used[jid]; g->connected = true; - g->eventsQueue.push(GenericInput{ InputGamepadState{ g }, InputClassEnum::GamepadConnected }); + g->eventsQueue.push(input::GamepadConnected{ g }); } else d.available.insert(jid); @@ -155,7 +155,7 @@ namespace cage { GamepadImpl *g = d.used[jid]; g->connected = false; - g->eventsQueue.push(GenericInput{ InputGamepadState{ g }, InputClassEnum::GamepadDisconnected }); + g->eventsQueue.push(input::GamepadDisconnected{ g }); } else d.available.erase(jid); diff --git a/sources/libengine/window/window.cpp b/sources/libengine/window/window.cpp index f2a27545..384c587f 100644 --- a/sources/libengine/window/window.cpp +++ b/sources/libengine/window/window.cpp @@ -101,10 +101,7 @@ namespace cage glfwSetCursorPos(window, x, y); MouseOffset off; off.off = -d; - GenericInput e; - e.type = InputClassEnum::Custom; - e.data = off; - eventsQueue.push(e); + eventsQueue.push(off); } threadSleep(5000); @@ -188,13 +185,12 @@ namespace cage void initializeEvents(); - bool determineMouseDoubleClick(InputMouse in) + bool determineMouseDoubleClick(MouseButtonsFlags buttons, Vec2 cp) { - CAGE_ASSERT((uint32)in.buttons < sizeof(lastMouseButtonPressTimes) / sizeof(lastMouseButtonPressTimes[0])); + CAGE_ASSERT((uint32)buttons < array_size(lastMouseButtonPressTimes)); const uint64 ct = applicationTime(); - const Vec2 cp = in.position; - uint64 < = lastMouseButtonPressTimes[(uint32)in.buttons]; - Vec2 &lp = lastMouseButtonPressPositions[(uint32)in.buttons]; + uint64 < = lastMouseButtonPressTimes[(uint32)buttons]; + Vec2 &lp = lastMouseButtonPressPositions[(uint32)buttons]; if (ct - lt < 300000 && distance(cp, lp) < 5) { lt = 0; @@ -217,71 +213,64 @@ namespace cage return stateMousePosition; } - void offsetMousePositionApi(GenericInput in) + template + void offsetMousePositionApiImpl(GenericInput in) { - if (in.type == InputClassEnum::MouseWheel) - { - InputMouseWheel i = in.data.get(); - i.position = offsetMousePositionApi(i.position); - in.data = i; - } - else + if (in.has()) { - InputMouse i = in.data.get(); + T i = in.get(); i.position = offsetMousePositionApi(i.position); - in.data = i; + events.dispatch(i); } - events.dispatch(in); + } + + void offsetMousePositionApi(GenericInput in) + { + offsetMousePositionApiImpl(in); + offsetMousePositionApiImpl(in); + offsetMousePositionApiImpl(in); + offsetMousePositionApiImpl(in); + offsetMousePositionApiImpl(in); } }; void windowCloseEvent(GLFWwindow *w) { WindowImpl *impl = (WindowImpl *)glfwGetWindowUserPointer(w); - InputWindow e; - e.window = impl; - impl->eventsQueue.push({ e, InputClassEnum::WindowClose }); + impl->eventsQueue.push(input::WindowClose{ impl }); } void windowKeyCallback(GLFWwindow *w, int key, int, int action, int mods) { WindowImpl *impl = (WindowImpl *)glfwGetWindowUserPointer(w); - InputClassEnum type; + const ModifiersFlags ms = getKeyModifiers(mods); switch (action) { case GLFW_PRESS: - type = InputClassEnum::KeyPress; + impl->eventsQueue.push(input::KeyPress{ impl, (uint32)key, ms }); break; case GLFW_REPEAT: - type = InputClassEnum::KeyRepeat; + impl->eventsQueue.push(input::KeyRepeat{ impl, (uint32)key, ms }); break; case GLFW_RELEASE: - type = InputClassEnum::KeyRelease; + impl->eventsQueue.push(input::KeyRelease{ impl, (uint32)key, ms }); break; default: CAGE_THROW_CRITICAL(Exception, "invalid key action"); } - InputKey e; - e.window = impl; - e.mods = getKeyModifiers(mods); - e.key = key; - impl->eventsQueue.push({ e, type }); } void windowCharCallback(GLFWwindow *w, unsigned int codepoint) { WindowImpl *impl = (WindowImpl *)glfwGetWindowUserPointer(w); - InputKey e; - e.window = impl; - e.mods = getKeyModifiers(w); - e.key = codepoint; - impl->eventsQueue.push({ e, InputClassEnum::KeyChar }); + const ModifiersFlags ms = getKeyModifiers(w); + impl->eventsQueue.push(input::Character{ impl, (uint32)codepoint, ms }); } void windowMouseMove(GLFWwindow *w, double xpos, double ypos) { WindowImpl *impl = (WindowImpl *)glfwGetWindowUserPointer(w); - InputMouse e; + input::MouseMove e; e.window = impl; e.mods = getKeyModifiers(w); e.position[0] = xpos; @@ -292,105 +281,100 @@ namespace cage e.buttons |= MouseButtonsFlags::Right; if (glfwGetMouseButton(w, GLFW_MOUSE_BUTTON_MIDDLE)) e.buttons |= MouseButtonsFlags::Middle; - impl->eventsQueue.push({ e, InputClassEnum::MouseMove }); + impl->eventsQueue.push(e); } void windowMouseButtonCallback(GLFWwindow *w, int button, int action, int mods) { WindowImpl *impl = (WindowImpl *)glfwGetWindowUserPointer(w); - InputClassEnum type; - switch (action) - { - case GLFW_PRESS: - type = InputClassEnum::MousePress; - break; - case GLFW_RELEASE: - type = InputClassEnum::MouseRelease; - break; - default: - CAGE_THROW_CRITICAL(Exception, "invalid mouse action"); - } - InputMouse e; - e.window = impl; - e.mods = getKeyModifiers(mods); + const ModifiersFlags ms = getKeyModifiers(mods); + MouseButtonsFlags bf = MouseButtonsFlags::None; switch (button) { case GLFW_MOUSE_BUTTON_LEFT: - e.buttons = MouseButtonsFlags::Left; + bf = MouseButtonsFlags::Left; break; case GLFW_MOUSE_BUTTON_RIGHT: - e.buttons = MouseButtonsFlags::Right; + bf = MouseButtonsFlags::Right; break; case GLFW_MOUSE_BUTTON_MIDDLE: - e.buttons = MouseButtonsFlags::Middle; + bf = MouseButtonsFlags::Middle; break; default: return; // ignore other keys } - double xpos, ypos; - glfwGetCursorPos(w, &xpos, &ypos); - e.position[0] = xpos; - e.position[1] = ypos; - const bool doubleClick = type == InputClassEnum::MousePress && impl->determineMouseDoubleClick(e); - impl->eventsQueue.push({ e, type }); - if (doubleClick) - impl->eventsQueue.push({ e, InputClassEnum::MouseDoublePress }); + Vec2 pos; + { + double xpos, ypos; + glfwGetCursorPos(w, &xpos, &ypos); + pos[0] = xpos; + pos[1] = ypos; + } + + switch (action) + { + case GLFW_PRESS: + impl->eventsQueue.push(input::MousePress{ impl, pos, bf, ms }); + break; + case GLFW_RELEASE: + impl->eventsQueue.push(input::MouseRelease{ impl, pos, bf, ms }); + break; + default: + CAGE_THROW_CRITICAL(Exception, "invalid mouse action"); + } + + if (action == GLFW_PRESS && impl->determineMouseDoubleClick(bf, pos)) + impl->eventsQueue.push(input::MouseDoublePress{ impl, pos, bf, ms }); } void windowMouseWheel(GLFWwindow *w, double, double yoffset) { WindowImpl *impl = (WindowImpl *)glfwGetWindowUserPointer(w); - InputMouseWheel e; - e.window = impl; - e.mods = getKeyModifiers(w); - double xpos, ypos; - glfwGetCursorPos(w, &xpos, &ypos); - e.position[0] = xpos; - e.position[1] = ypos; - e.wheel = yoffset; - impl->eventsQueue.push({ e, InputClassEnum::MouseWheel }); + const ModifiersFlags ms = getKeyModifiers(w); + Vec2 pos; + { + double xpos, ypos; + glfwGetCursorPos(w, &xpos, &ypos); + pos[0] = xpos; + pos[1] = ypos; + } + impl->eventsQueue.push(input::MouseWheel{ impl, pos, Real(yoffset), ms }); } void windowResizeCallback(GLFWwindow *w, int width, int height) { WindowImpl *impl = (WindowImpl *)glfwGetWindowUserPointer(w); - InputWindowValue e; - e.window = impl; - e.value = Vec2i(width, height); - impl->eventsQueue.push({ e, InputClassEnum::WindowResize }); + impl->eventsQueue.push(input::WindowResize{ impl, Vec2i(width, height) }); } void windowMoveCallback(GLFWwindow *w, int xpos, int ypos) { WindowImpl *impl = (WindowImpl *)glfwGetWindowUserPointer(w); - InputWindowValue e; - e.window = impl; - e.value = Vec2i(xpos, ypos); - impl->eventsQueue.push({ e, InputClassEnum::WindowMove }); + impl->eventsQueue.push(input::WindowMove{ impl, Vec2i(xpos, ypos) }); } void windowIconifiedCallback(GLFWwindow *w, int iconified) { WindowImpl *impl = (WindowImpl *)glfwGetWindowUserPointer(w); - InputWindow e; - e.window = impl; - impl->eventsQueue.push({ e, iconified ? InputClassEnum::WindowHide : InputClassEnum::WindowShow }); + if (iconified) + impl->eventsQueue.push(input::WindowHide{ impl }); + else + impl->eventsQueue.push(input::WindowShow{ impl }); } void windowMaximizedCallback(GLFWwindow *w, int maximized) { WindowImpl *impl = (WindowImpl *)glfwGetWindowUserPointer(w); - InputWindow e; - e.window = impl; - impl->eventsQueue.push({ e, InputClassEnum::WindowShow }); // window is visible when both maximized or restored + impl->eventsQueue.push(input::WindowShow{ impl }); // window is visible when both maximized or restored } void windowFocusCallback(GLFWwindow *w, int focused) { WindowImpl *impl = (WindowImpl *)glfwGetWindowUserPointer(w); - InputWindow e; - e.window = impl; - impl->eventsQueue.push({ e, focused ? InputClassEnum::FocusGain : InputClassEnum::FocusLose }); + if (focused) + impl->eventsQueue.push(input::WindowFocusGain{ impl }); + else + impl->eventsQueue.push(input::WindowFocusLose{ impl }); } void WindowImpl::initializeEvents() @@ -574,62 +558,66 @@ namespace cage GenericInput e; while (impl->eventsQueue.tryPop(e)) { - if (e.data.typeHash() == detail::typeHash()) - impl->stateMods = e.data.get().mods; - if (e.data.typeHash() == detail::typeHash()) - impl->stateMods = e.data.get().mods; - if (e.data.typeHash() == detail::typeHash()) - impl->stateMods = e.data.get().mods; - - switch (e.type) + switch (e.typeHash()) { - case InputClassEnum::WindowClose: - case InputClassEnum::WindowResize: - case InputClassEnum::WindowMove: - case InputClassEnum::WindowShow: - case InputClassEnum::WindowHide: - case InputClassEnum::KeyChar: - case InputClassEnum::KeyRepeat: - events.dispatch(e); + case detail::typeHash(): + impl->stateMods = e.get().mods; + impl->offsetMousePositionApi(e); break; - case InputClassEnum::MouseMove: - case InputClassEnum::MouseDoublePress: - case InputClassEnum::MouseWheel: + case detail::typeHash(): + impl->stateButtons |= e.get().buttons; + impl->stateMods = e.get().mods; impl->offsetMousePositionApi(e); break; - case InputClassEnum::KeyPress: - impl->stateKeys.insert(e.data.get().key); - events.dispatch(e); - e.type = InputClassEnum::KeyRepeat; + case detail::typeHash(): + impl->stateButtons &= ~e.get().buttons; + impl->stateMods = e.get().mods; + impl->offsetMousePositionApi(e); + break; + case detail::typeHash(): + impl->stateMods = e.get().mods; + impl->offsetMousePositionApi(e); + break; + case detail::typeHash(): + impl->stateMods = e.get().mods; + impl->offsetMousePositionApi(e); + break; + case detail::typeHash(): + impl->stateKeys.insert(e.get().key); + impl->stateMods = e.get().mods; events.dispatch(e); + events.dispatch(input::KeyRepeat(e.get())); break; - case InputClassEnum::KeyRelease: + case detail::typeHash(): + impl->stateKeys.erase(e.get().key); + impl->stateMods = e.get().mods; events.dispatch(e); - impl->stateKeys.erase(e.data.get().key); break; - case InputClassEnum::MousePress: - impl->stateButtons |= e.data.get().buttons; - impl->offsetMousePositionApi(e); + case detail::typeHash(): + impl->stateKeys.insert(e.get().key); + impl->stateMods = e.get().mods; + events.dispatch(e); break; - case InputClassEnum::MouseRelease: - impl->offsetMousePositionApi(e); - impl->stateButtons &= ~e.data.get().buttons; + case detail::typeHash(): + impl->stateMods = e.get().mods; + events.dispatch(e); break; - case InputClassEnum::FocusGain: + case detail::typeHash(): impl->focus = true; events.dispatch(e); break; - case InputClassEnum::FocusLose: + case detail::typeHash(): impl->focus = false; events.dispatch(e); break; #ifdef GCHL_WINDOWS_THREAD - case InputClassEnum::Custom: - impl->mouseOffsetApi += e.data.get().off; + case detail::typeHash(): + impl->mouseOffsetApi += e.get().off; break; #endif default: - CAGE_THROW_CRITICAL(Exception, "invalid window event type"); + events.dispatch(e); + break; } } } diff --git a/sources/libsimple/fpsCamera.cpp b/sources/libsimple/fpsCamera.cpp index 18c30de6..c66a508e 100644 --- a/sources/libsimple/fpsCamera.cpp +++ b/sources/libsimple/fpsCamera.cpp @@ -12,9 +12,7 @@ namespace cage class FpsCameraImpl : public FpsCamera { public: - InputsDispatchers dispatchers; - InputsListeners listeners; - const EventListener windowListener = engineWindow()->events.listen([this](const GenericInput &in) { return this->dispatchers.dispatch(in); }); + const EventListener windowListener = engineWindow()->events.listen([this](const GenericInput &in) { return this->event(in); }); const EventListener updateListener = controlThread().update.listen([this]() { return this->update(); }); VariableSmoothingBuffer mouseSmoother; VariableSmoothingBuffer moveSmoother; @@ -26,15 +24,7 @@ namespace cage Entity *ent = nullptr; bool keysPressedArrows[6] = {}; // wsadeq - FpsCameraImpl(Entity *ent) : ent(ent) - { - listeners.attach(&dispatchers); - listeners.mousePress.bind([this](InputMouse in) { return this->mousePress(in); }); - listeners.mouseMove.bind([this](InputMouse in) { return this->mouseMove(in); }); - listeners.mouseWheel.bind([this](InputMouseWheel in) { return this->mouseWheel(in); }); - listeners.keyPress.bind([this](InputKey in) { return this->keyPress(in); }); - listeners.keyRelease.bind([this](InputKey in) { return this->keyRelease(in); }); - } + FpsCameraImpl(Entity *ent) : ent(ent) {} Vec2 centerMouse() { @@ -48,14 +38,14 @@ namespace cage bool mouseEnabled(MouseButtonsFlags buttons) { return !!ent && engineWindow()->isFocused() && (mouseButton == MouseButtonsFlags::None || (buttons & mouseButton) == mouseButton); } - bool mousePress(InputMouse in) + bool mousePress(input::MousePress in) { if (mouseEnabled(in.buttons)) centerMouse(); return false; } - bool mouseMove(InputMouse in) + bool mouseMove(input::MouseMove in) { if (!mouseEnabled(in.buttons)) return false; @@ -65,7 +55,7 @@ namespace cage return false; } - bool mouseWheel(InputMouseWheel in) + bool mouseWheel(input::MouseWheel in) { if (!ent) return false; @@ -121,9 +111,24 @@ namespace cage return false; } - bool keyPress(InputKey in) { return setKey(in.key, true); } + bool keyPress(input::KeyPress in) { return setKey(in.key, true); } + + bool keyRelease(input::KeyRelease in) { return setKey(in.key, false); } - bool keyRelease(InputKey in) { return setKey(in.key, false); } + bool event(GenericInput in) + { + if (in.has()) + return mousePress(in.get()); + if (in.has()) + return mouseMove(in.get()); + if (in.has()) + return mouseWheel(in.get()); + if (in.has()) + return keyPress(in.get()); + if (in.has()) + return keyRelease(in.get()); + return false; + } void update() { diff --git a/sources/libsimple/fullscreenSwitcher.cpp b/sources/libsimple/fullscreenSwitcher.cpp index 9cddac46..828ba5bf 100644 --- a/sources/libsimple/fullscreenSwitcher.cpp +++ b/sources/libsimple/fullscreenSwitcher.cpp @@ -24,9 +24,9 @@ namespace cage { public: Window *const window = nullptr; - const EventListener windowMoveListener = window->events.listen(inputListener([this](InputWindowValue in) { return this->windowMove(in); }), -13665); - const EventListener windowResizeListener = window->events.listen(inputListener([this](InputWindowValue in) { return this->windowResize(in); }), -13666); - const EventListener keyListener = window->events.listen(inputListener([this](InputKey in) { return this->keyRelease(in); }), -13667); + const EventListener windowMoveListener = window->events.listen(inputFilter([this](input::WindowMove in) { return this->windowMove(in); }), -13665); + const EventListener windowResizeListener = window->events.listen(inputFilter([this](input::WindowResize in) { return this->windowResize(in); }), -13666); + const EventListener keyListener = window->events.listen(inputFilter([this](input::KeyRelease in) { return this->keyRelease(in); }), -13667); ConfigBool confFullscreenEnabled; ConfigBool confWindowMaximized; @@ -78,34 +78,34 @@ namespace cage window->setMaximized(); } - void windowMove(InputWindowValue in) + void windowMove(input::WindowMove in) { confScreen = window->screenId(); if (window->isWindowed()) { - confWindowLeft = in.value[0]; - confWindowTop = in.value[1]; + confWindowLeft = in.position[0]; + confWindowTop = in.position[1]; } } - void windowResize(InputWindowValue in) + void windowResize(input::WindowResize in) { confScreen = window->screenId(); if ((confFullscreenEnabled = window->isFullscreen())) { - confFullscreenWidth = in.value[0]; - confFullscreenHeight = in.value[1]; + confFullscreenWidth = in.size[0]; + confFullscreenHeight = in.size[1]; return; } if (window->isWindowed()) { - confWindowWidth = in.value[0]; - confWindowHeight = in.value[1]; + confWindowWidth = in.size[0]; + confWindowHeight = in.size[1]; } confWindowMaximized = window->isMaximized(); } - bool keyRelease(InputKey in) + bool keyRelease(input::KeyRelease in) { if (in.mods == keyModifiers && in.key == keyToggleFullscreen) { diff --git a/sources/libsimple/guiInWorld.cpp b/sources/libsimple/guiInWorld.cpp index 4e515968..7b7f3ba6 100644 --- a/sources/libsimple/guiInWorld.cpp +++ b/sources/libsimple/guiInWorld.cpp @@ -79,16 +79,16 @@ namespace cage { if (interact) { - guiMan->handleInput(GenericInput{ InputMouse{ .position = i.gp, .buttons = MouseButtonsFlags::Left }, InputClassEnum::MousePress }); - guiMan->handleInput(GenericInput{ InputMouse{ .position = i.gp, .buttons = MouseButtonsFlags::Left }, InputClassEnum::MouseRelease }); + guiMan->handleInput(input::MousePress{ { .position = i.gp, .buttons = MouseButtonsFlags::Left } }); + guiMan->handleInput(input::MouseRelease{ { .position = i.gp, .buttons = MouseButtonsFlags::Left } }); } else - guiMan->handleInput(GenericInput{ InputMouse{ .position = i.gp }, InputClassEnum::MouseMove }); + guiMan->handleInput(input::MouseMove{ { .position = i.gp } }); } else { guiMan->focus(0); - guiMan->handleInput(GenericInput{ InputMouse{ .position = Vec2(-1) }, InputClassEnum::MouseMove }); + guiMan->handleInput(input::MouseMove{ { .position = Vec2(-1) } }); } auto q = guiMan->finish(); diff --git a/sources/libsimple/statisticsGui.cpp b/sources/libsimple/statisticsGui.cpp index 58a59442..aeb6b733 100644 --- a/sources/libsimple/statisticsGui.cpp +++ b/sources/libsimple/statisticsGui.cpp @@ -18,8 +18,8 @@ namespace cage class StatisticsGuiImpl : public StatisticsGui { public: - const EventListener keyPressListener = engineWindow()->events.listen(inputListener([this](InputKey in) { return this->keyPress(in); })); - const EventListener keyRepeatListener = engineWindow()->events.listen(inputListener([this](InputKey in) { return this->keyRepeat(in); })); + const EventListener keyPressListener = engineWindow()->events.listen(inputFilter([this](input::KeyPress in) { return this->keyPress(in); })); + const EventListener keyRepeatListener = engineWindow()->events.listen(inputFilter([this](input::KeyRepeat in) { return this->keyRepeat(in); })); const EventListener updateListener = controlThread().update.listen([this]() { this->update(); }); uint32 rootName = 0; @@ -91,7 +91,7 @@ namespace cage } } - bool keyPress(InputKey in) + bool keyPress(input::KeyPress in) { if (in.mods == keyModifiers) { @@ -161,7 +161,7 @@ namespace cage return false; } - bool keyRepeat(InputKey in) + bool keyRepeat(input::KeyRepeat in) { if (in.mods == keyModifiers) { diff --git a/sources/test-core/installConsistentPaths.cpp b/sources/test-core/installConsistentPaths.cpp index d26f6a54..1a6cb785 100644 --- a/sources/test-core/installConsistentPaths.cpp +++ b/sources/test-core/installConsistentPaths.cpp @@ -16,14 +16,6 @@ namespace { bool closing = false; -#ifdef CAGE_ENGINE_API - void windowEvent(const GenericInput &in) - { - if (in.type == InputClassEnum::WindowClose) - closing = true; - } -#endif // !CAGE_ENGINE_API - void testColony() { plf::colony colony; @@ -47,9 +39,7 @@ void testCageInstallConsistentPaths() #ifdef CAGE_ENGINE_API CAGE_LOG(SeverityEnum::Info, "test", Stringizer() + "creating window"); Holder window = newWindow({}); - EventListener windowEventsListener; - windowEventsListener.attach(window->events); - windowEventsListener.bind(&windowEvent); + const auto closeListener = window->events.listen(inputFilter([](input::WindowClose) { closing = true; })); window->setWindowed(); window->windowedSize(Vec2i(400, 300)); window->title("cage-test-install");