Skip to content

Commit

Permalink
add pointer input source (mouse or touch), which is used to track if …
Browse files Browse the repository at this point in the history
…mouse released events must be handling in new gui frame
  • Loading branch information
cklosters committed Dec 19, 2022
1 parent 9423d51 commit ab898a4
Show file tree
Hide file tree
Showing 6 changed files with 75 additions and 44 deletions.
20 changes: 15 additions & 5 deletions modules/napimgui/src/imguiservice.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -981,16 +981,19 @@ namespace nap
{
io.MouseDown[i] = context.mMousePressed[i];

// If a mouse button was released this frame -> disable the press for next frame
// This ensures that buttons that are pressed and released within the same frame are always registered
if (context.mMouseRelease[i])
// If the mouse button was released this frame -> disable the press for next frame.
// This ensures that buttons that are pressed and released within the same frame are always registered.
// If the button press is from a mouse (instead of touch), take into account current press state.
// This is required because the user can release the button outside of SDL window bounds, in which case no release event is generated.
if (context.mMouseRelease[i] || (context.mMousePressed[i] &&
context.mMouseSource[i] == GUIContext::ESource::Mouse && (SDL_GetMouseState(nullptr, nullptr) & SDL_BUTTON(i+1)) == 0))
{
context.mMousePressed[i] = false;
context.mMouseRelease[i] = false;
}
}

// Tell the system which keys are pressed, we copy block of memory because iterating over
// Tell the system which keys are pressed, we copy block of memory because iterating over every element is wasteful
memcpy(io.KeysDown, context.mKeyPressed.data(), sizeof(bool) * 512);
for (const auto& key : context.mKeyRelease)
{
Expand Down Expand Up @@ -1105,7 +1108,9 @@ namespace nap
const auto& press_event = static_cast<const nap::PointerPressEvent&>(pointerEvent);
if (press_event.mButton != EMouseButton::UNKNOWN)
{
context.mMousePressed[static_cast<int>(press_event.mButton)] = true;
int btn_id = static_cast<int>(press_event.mButton);
context.mMousePressed[btn_id] = true;
context.mMouseSource[btn_id] = pointerEvent.mSource;
}
}

Expand Down Expand Up @@ -1136,11 +1141,16 @@ namespace nap

// Handle touch press
if (touchEvent.get_type().is_derived_from(RTTI_OF(nap::TouchPressEvent)))
{
context.mMousePressed[0] = true;
context.mMouseSource[0] = GUIContext::ESource::Touch;
}

// Handle touch release
if (touchEvent.get_type().is_derived_from(RTTI_OF(nap::TouchReleaseEvent)))
{
context.mMouseRelease[0] = true;
}
}


Expand Down
28 changes: 15 additions & 13 deletions modules/napimgui/src/imguiservice.h
Original file line number Diff line number Diff line change
Expand Up @@ -345,19 +345,21 @@ namespace nap
GUIContext(ImGuiContext* context, ImGuiStyle* style);
~GUIContext();

std::array<bool,3> mMousePressed = { false }; ///< If the mouse was pressed this frame
std::array<bool,3> mMouseRelease = { false }; ///< If the mouse was released this frame
std::array<bool,3> mModPressed = { false }; ///< If the ctrl (0), alt (1) or shift (2) modifier key is pressed
std::array<bool,3> mModRelease = { false }; ///< If the ctrl (0), alt (1) or shift (2) modifier key is released
std::array<bool, 512> mKeyPressed = { false }; ///< The keys that were pressed this frame
std::vector<int> mKeyRelease; ///< The keys that were released this frame
glm::ivec2 mMousePosition = { 0, 0 }; ///< Last known mouse position
float mMouseWheel = 0.0f; ///< Mouse wheel
float mScale = 1.0f; ///< GUI Scale
const Display* mDisplay = nullptr; ///< Current display
ImGuiContext* mContext = nullptr; ///< Associated ImGUI context
ImGuiContext* mPreviousContext = nullptr; ///< Context active before this one
ImGuiStyle* mStyle = nullptr; ///< Style of context
using ESource = PointerEvent::ESource;
std::array<bool,3> mMousePressed = { false }; ///< If the mouse was pressed this frame
std::array<bool,3> mMouseRelease = { false }; ///< If the mouse was released this frame
std::array<bool,3> mModPressed = { false }; ///< If the ctrl (0), alt (1) or shift (2) modifier key is pressed
std::array<bool,3> mModRelease = { false }; ///< If the ctrl (0), alt (1) or shift (2) modifier key is released
std::array<ESource, 3> mMouseSource = { ESource::Mouse}; ///< Pointer input source
std::array<bool, 512> mKeyPressed = { false }; ///< The keys that were pressed this frame
std::vector<int> mKeyRelease; ///< The keys that were released this frame
glm::ivec2 mMousePosition = { 0, 0 }; ///< Last known mouse position
float mMouseWheel = 0.0f; ///< Mouse wheel
float mScale = 1.0f; ///< GUI Scale
const Display* mDisplay = nullptr; ///< Current display
ImGuiContext* mContext = nullptr; ///< Associated ImGUI context
ImGuiContext* mPreviousContext = nullptr; ///< Context active before this one
ImGuiStyle* mStyle = nullptr; ///< Style of context

// Activates current context
void activate();
Expand Down
7 changes: 3 additions & 4 deletions modules/napinput/src/inputevent.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@

#include <inputevent.h>

// RTTI Definitions
RTTI_DEFINE_BASE(nap::InputEvent)
RTTI_DEFINE_BASE(nap::WindowInputEvent)
RTTI_DEFINE_BASE(nap::ControllerEvent)
Expand All @@ -23,15 +22,15 @@ RTTI_BEGIN_CLASS_NO_DEFAULT_CONSTRUCTOR(nap::KeyReleaseEvent)
RTTI_END_CLASS

RTTI_BEGIN_CLASS_NO_DEFAULT_CONSTRUCTOR(nap::PointerPressEvent)
RTTI_CONSTRUCTOR(int, int, nap::EMouseButton, int, int)
RTTI_CONSTRUCTOR(int, int, nap::EMouseButton, int, nap::PointerEvent::ESource)
RTTI_END_CLASS

RTTI_BEGIN_CLASS_NO_DEFAULT_CONSTRUCTOR(nap::PointerReleaseEvent)
RTTI_CONSTRUCTOR(int, int, nap::EMouseButton, int, int)
RTTI_CONSTRUCTOR(int, int, nap::EMouseButton, int, nap::PointerEvent::ESource)
RTTI_END_CLASS

RTTI_BEGIN_CLASS_NO_DEFAULT_CONSTRUCTOR(nap::PointerMoveEvent)
RTTI_CONSTRUCTOR(int, int, int, int, int, int)
RTTI_CONSTRUCTOR(int, int, int, int, int, nap::PointerEvent::ESource)
RTTI_END_CLASS

RTTI_BEGIN_CLASS_NO_DEFAULT_CONSTRUCTOR(nap::MouseWheelEvent)
Expand Down
42 changes: 25 additions & 17 deletions modules/napinput/src/inputevent.h
Original file line number Diff line number Diff line change
Expand Up @@ -107,26 +107,34 @@ namespace nap


//////////////////////////////////////////////////////////////////////////
// Mouse Input Events, always associated with a with a window
// Pointer Input Events, always associated with a with a window
//////////////////////////////////////////////////////////////////////////

/**
* Contains all relevant information for pointer specific interaction
* Can also be used to signal multi touch gestures (therefore the id)
*/
*/
class NAPAPI PointerEvent : public WindowInputEvent
{
RTTI_ENABLE(WindowInputEvent)
public:
PointerEvent(int inX, int inY, int window = 0, int inId = 0) : WindowInputEvent(window),
mX(inX),
mY(inY),
mId(inId)

/**
* Possible pointer input sources
*/
enum class ESource : int8
{
Mouse = 0, ///< Pointer event from mouse input
Touch = 1 ///< Pointer event from touch input
};

PointerEvent(int inX, int inY, int window = 0, ESource origin = ESource::Mouse) :
WindowInputEvent(window), mX(inX), mY(inY), mSource(origin)
{ }

int mX; ///< horizontal window pixel coordinate
int mY; ///< vertical window pixel coordinate
int mId; ///< device id
int mX; ///< horizontal window coordinate
int mY; ///< vertical window coordinate
ESource mSource = ESource::Mouse; ///< input device
};


Expand All @@ -137,8 +145,8 @@ namespace nap
{
RTTI_ENABLE(PointerEvent)
public:
PointerClickEvent(int inX, int inY, EMouseButton inButton, int window = 0, int inId = 0) :
PointerEvent(inX, inY, window, inId),
PointerClickEvent(int inX, int inY, EMouseButton inButton, int window = 0, ESource source = ESource::Mouse) :
PointerEvent(inX, inY, window, source),
mButton(inButton)
{ }

Expand All @@ -153,8 +161,8 @@ namespace nap
{
RTTI_ENABLE(PointerClickEvent)
public:
PointerPressEvent(int inX, int inY, EMouseButton inButton, int window=0, int inId = 0) :
PointerClickEvent(inX, inY, inButton, window, inId)
PointerPressEvent(int inX, int inY, EMouseButton inButton, int window=0, ESource source = ESource::Mouse) :
PointerClickEvent(inX, inY, inButton, window, source)
{ }
};

Expand All @@ -166,8 +174,8 @@ namespace nap
{
RTTI_ENABLE(PointerClickEvent)
public:
PointerReleaseEvent (int inX, int inY, EMouseButton inButton, int window=0, int inId = 0) :
PointerClickEvent(inX, inY, inButton, window, inId)
PointerReleaseEvent (int inX, int inY, EMouseButton inButton, int window=0, ESource source = ESource::Mouse) :
PointerClickEvent(inX, inY, inButton, window, source)
{ }
};

Expand All @@ -179,8 +187,8 @@ namespace nap
{
RTTI_ENABLE(PointerEvent)
public:
PointerMoveEvent(int relX, int relY, int inAbsX, int inAbsY, int window=0, int inId = 0) :
PointerEvent(inAbsX, inAbsY, window, inId),
PointerMoveEvent(int relX, int relY, int inAbsX, int inAbsY, int window=0, ESource source = ESource::Mouse) :
PointerEvent(inAbsX, inAbsY, window, source),
mRelX(relX),
mRelY(relY)
{ }
Expand Down
4 changes: 2 additions & 2 deletions modules/napinput/src/mouse.h
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@
namespace nap
{
/**
* Enum describing a list of all possible mouse buttons
* All possible mouse buttons
*/
enum class EMouseButton : int
{
Expand All @@ -18,4 +18,4 @@ namespace nap
MIDDLE = 1,
RIGHT = 2
};
}
}
18 changes: 15 additions & 3 deletions modules/napsdlinput/src/sdleventconverter.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -350,11 +350,21 @@ namespace nap
return EMouseButton::MIDDLE;
case SDL_BUTTON_RIGHT:
return EMouseButton::RIGHT;
default:
return EMouseButton::UNKNOWN;
}
}

return EMouseButton::UNKNOWN;

/**
* Helper function to convert an SDL mouse source to nap pointer source
*/
static nap::PointerEvent::ESource toNapMouseSource(uint32_t source)
{
return source == SDL_TOUCH_MOUSEID ? PointerEvent::ESource::Touch : PointerEvent::ESource::Mouse;
}


static nap::EControllerAxis toNapAxis(uint8_t axis)
{
switch (axis)
Expand Down Expand Up @@ -420,6 +430,7 @@ namespace nap
{
// Get window
int window_id = static_cast<int>(sdlEvent.window.windowID);

SDL_Window* window = SDL_GetWindowFromID(window_id);
if (window == nullptr)
return nullptr;
Expand All @@ -442,7 +453,8 @@ namespace nap
SDL_GetWindowSize(window, &sx, &sy);
int px = sdlEvent.motion.x;
int py = sy - 1 - sdlEvent.motion.y;
mouse_event = eventType.create<InputEvent>({ px, py, toNapMouseButton(sdlEvent.button.button), window_id, 0 });
PointerEvent::ESource source = sdlEvent.motion.which == SDL_TOUCH_MOUSEID ? PointerEvent::ESource::Touch : PointerEvent::ESource::Mouse;
mouse_event = eventType.create<InputEvent>({ px, py, toNapMouseButton(sdlEvent.button.button), window_id, toNapMouseSource(sdlEvent.motion.which)});
break;
}
case SDL_MOUSEMOTION:
Expand All @@ -454,7 +466,7 @@ namespace nap
int py = sy - 1 - static_cast<int>(sdlEvent.motion.y);
int rx = static_cast<int>(sdlEvent.motion.xrel);
int ry = static_cast<int>(-sdlEvent.motion.yrel);
mouse_event = eventType.create<InputEvent>({ rx, ry, px, py, window_id, 0 });
mouse_event = eventType.create<InputEvent>({ rx, ry, px, py, window_id, toNapMouseSource(sdlEvent.motion.which) });
break;
}
default:
Expand Down

0 comments on commit ab898a4

Please sign in to comment.