Skip to content

Commit

Permalink
[Canvas] Improved input handling for Canvas interface.
Browse files Browse the repository at this point in the history
- Added "EventAction" enum to public interface to distinguish pan gestures (Began/Changed/Ended).
- Handle Android app events: APP_CMD_TERM_WINDOW, APP_CMD_WINDOW_REDRAW_NEEDED, and APP_CMD_WINDOW_RESIZED.
- Deprecated old version of OnPanGesture(); Use new version with EventAction parameter.

Breaking change:
  Input::GetMousePosition() and Input::GetMouseMotion() does not return a constant reference anymore.
  This should be negligible as long as no program kept a reference to those fields.
  • Loading branch information
LukasBanana committed Aug 3, 2024
1 parent d1e3dec commit 13ca37d
Show file tree
Hide file tree
Showing 9 changed files with 233 additions and 90 deletions.
13 changes: 11 additions & 2 deletions include/LLGL/Canvas.h
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
#include <LLGL/Surface.h>
#include <LLGL/Types.h>
#include <LLGL/Key.h>
#include <LLGL/Deprecated.h>
#include <memory>


Expand Down Expand Up @@ -64,9 +65,13 @@ class LLGL_EXPORT Canvas : public Surface
//! Sent when a tap gesture has been recognized only including the location within the canvas.
virtual void OnTapGesture(Canvas& sender, const Offset2D& position, std::uint32_t numTouches);

//! Sent when a pan gesture has been recognized. Includes X and Y deltas for movement.
//! \deprecated Since 0.04b; Use the second version of OnPanGesture() with the EventAction parameter instead!
LLGL_DEPRECATED("This version of OnPanGesture() is deprecated since 0.04b; Use the second version with the EventAction parameter instead!")
virtual void OnPanGesture(Canvas& sender, const Offset2D& position, std::uint32_t numTouches, float dx, float dy);

//! Sent when a pan gesture has been recognized. Includes X and Y deltas for movement.
virtual void OnPanGesture(Canvas& sender, const Offset2D& position, std::uint32_t numTouches, float dx, float dy, EventAction action);

};

public:
Expand Down Expand Up @@ -151,11 +156,15 @@ class LLGL_EXPORT Canvas : public Surface
*/
void PostTapGesture(const Offset2D& position, std::uint32_t numTouches);

//! \deprecated Since 0.04b; Use the second version of PostPanGesture() with the EventAction parameter instead!
LLGL_DEPRECATED("This version of PostPanGesture() is deprecated since 0.04b; Use the second version with the EventAction parameter instead!")
void PostPanGesture(const Offset2D& position, std::uint32_t numTouches, float dx, float dy);

/**
\brief Posts a pan gesture event to all event listeners.
\see EventListener::OnPanGesture
*/
void PostPanGesture(const Offset2D& position, std::uint32_t numTouches, float dx, float dy);
void PostPanGesture(const Offset2D& position, std::uint32_t numTouches, float dx, float dy, EventAction action);

protected:

Expand Down
12 changes: 12 additions & 0 deletions include/LLGL/CanvasFlags.h
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,18 @@ namespace LLGL
{


/**
\brief Motion event action enumeration.
\see Canvas::EventListener::OnPanGesture
\see Canvas::PostPanGesture
*/
enum class EventAction
{
Began, //!< Action when a gesture began.
Changed, //!< Action when a gesture changed/moved.
Ended, //!< Action when a gesture ended.
};

/**
\brief Canvas creation flags.
\see CanvasDescriptor::flags
Expand Down
4 changes: 2 additions & 2 deletions include/LLGL/Utils/Input.h
Original file line number Diff line number Diff line change
Expand Up @@ -84,10 +84,10 @@ class LLGL_EXPORT Input : public Interface
bool KeyDoubleClick(Key keyCode) const;

//! Returns the local mouse position.
const Offset2D& GetMousePosition() const;
Offset2D GetMousePosition() const;

//! Returns the global mouse motion.
const Offset2D& GetMouseMotion() const;
Offset2D GetMouseMotion() const;

//! Returns the mouse wheel motion.
int GetWheelMotion() const;
Expand Down
147 changes: 93 additions & 54 deletions sources/Core/Input.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
#include <vector>
#include <algorithm>
#include <memory>
#include <math.h>


namespace LLGL
Expand Down Expand Up @@ -80,6 +81,12 @@ struct EventListenerSurfacePair
Surface* surface;
};

// Returns the input value with zeroing out the integral part.
static float ZeroIntegralPart(float val)
{
return (val < 0.0f ? val + ::floorf(-val) : val - ::floorf(val));
}

struct Input::Pimpl
{
KeyStateArray keyPressed;
Expand All @@ -93,7 +100,7 @@ struct Input::Pimpl
KeyTracker keyUpTracker;

Offset2D mousePosition;
Offset2D mouseMotion;
float motionVector[2] = { 0.0f, 0.0f };

int wheelMotion = 0;
unsigned anyKeyCount = 0;
Expand All @@ -109,7 +116,8 @@ struct Input::Pimpl
{
/* Reset all input states to make room for next recordings */
wheelMotion = 0;
mouseMotion = { 0, 0 };
motionVector[0] = ZeroIntegralPart(motionVector[0]);
motionVector[1] = ZeroIntegralPart(motionVector[1]);

keyDownTracker.Reset(keyDown);
keyDownRepeatedTracker.Reset(keyDownRepeated);
Expand All @@ -119,6 +127,64 @@ struct Input::Pimpl

chars.clear();
}

void OnKeyDown(Key keyCode)
{
const std::uint8_t idx = KEY_IDX(keyCode);

if (!keyPressed[idx])
{
/* Increase 'any'-key counter and store key state */
if (anyKeyCount++ == 0)
{
/* Store key state for 'any'-key */
keyDown[KEY_IDX(Key::Any)] = true;
keyDownTracker.Add(Key::Any);
keyPressed[KEY_IDX(Key::Any)] = true;
}

/* Store key hit state */
keyDown[idx] = true;
keyDownTracker.Add(keyCode);
}

/* Store key pressed state */
keyPressed[idx] = true;

/* Store repeated key hit state */
keyDownRepeated[idx] = true;
keyDownRepeatedTracker.Add(keyCode);
}

void OnKeyUp(Key keyCode)
{
const std::uint8_t idx = KEY_IDX(keyCode);

/* Store key released state */
keyUp[idx] = true;
keyUpTracker.Add(keyCode);

/* Store key released state for 'any'-key */
keyUp[KEY_IDX(Key::Any)] = true;
keyUpTracker.Add(Key::Any);

/* Increase 'any'-key counter and store key state */
if (anyKeyCount > 0)
{
anyKeyCount--;
if (anyKeyCount == 0)
keyPressed[KEY_IDX(Key::Any)] = false;
}

/* Reset key pressed state */
keyPressed[idx] = false;
}

void OnMotion(float dx, float dy)
{
motionVector[0] += dx;
motionVector[1] += dy;
}
};


Expand All @@ -140,54 +206,12 @@ class Input::WindowEventListener final : public Window::EventListener

void OnKeyDown(Window& /*sender*/, Key keyCode) override
{
const std::uint8_t idx = KEY_IDX(keyCode);

if (!data_.keyPressed[idx])
{
/* Increase 'any'-key counter and store key state */
if (data_.anyKeyCount++ == 0)
{
/* Store key state for 'any'-key */
data_.keyDown[KEY_IDX(Key::Any)] = true;
data_.keyDownTracker.Add(Key::Any);
data_.keyPressed[KEY_IDX(Key::Any)] = true;
}

/* Store key hit state */
data_.keyDown[idx] = true;
data_.keyDownTracker.Add(keyCode);
}

/* Store key pressed state */
data_.keyPressed[idx] = true;

/* Store repeated key hit state */
data_.keyDownRepeated[idx] = true;
data_.keyDownRepeatedTracker.Add(keyCode);
data_.OnKeyDown(keyCode);
}

void OnKeyUp(Window& /*sender*/, Key keyCode) override
{
const std::uint8_t idx = KEY_IDX(keyCode);

/* Store key released state */
data_.keyUp[idx] = true;
data_.keyUpTracker.Add(keyCode);

/* Store key released state for 'any'-key */
data_.keyUp[KEY_IDX(Key::Any)] = true;
data_.keyUpTracker.Add(Key::Any);

/* Increase 'any'-key counter and store key state */
if (data_.anyKeyCount > 0)
{
data_.anyKeyCount--;
if (data_.anyKeyCount == 0)
data_.keyPressed[KEY_IDX(Key::Any)] = false;
}

/* Reset key pressed state */
data_.keyPressed[idx] = false;
data_.OnKeyUp(keyCode);
}

void OnDoubleClick(Window& /*sender*/, Key keyCode) override
Expand Down Expand Up @@ -225,8 +249,7 @@ class Input::WindowEventListener final : public Window::EventListener

void OnGlobalMotion(Window& /*sender*/, const Offset2D& motion) override
{
data_.mouseMotion.x += motion.x;
data_.mouseMotion.y += motion.y;
data_.OnMotion(static_cast<float>(motion.x), static_cast<float>(motion.y));
}

void OnLostFocus(Window& /*sender*/) override
Expand Down Expand Up @@ -263,11 +286,23 @@ class Input::CanvasEventListener final : public Canvas::EventListener
//TODO
}

void OnPanGesture(Canvas& /*sender*/, const Offset2D& /*position*/, std::uint32_t /*numTouches*/, float dx, float dy) override
void OnPanGesture(Canvas& /*sender*/, const Offset2D& /*position*/, std::uint32_t /*numTouches*/, float dx, float dy, EventAction action) override
{
//TODO: Use separate field
data_.mouseMotion.x = static_cast<std::int32_t>(dx * 0.1f);
data_.mouseMotion.y = static_cast<std::int32_t>(dy * 0.1f);
switch (action)
{
case EventAction::Began:
data_.OnKeyDown(Key::LButton);
break;

case EventAction::Changed:
data_.OnMotion(dx, dy);
break;

case EventAction::Ended:
data_.OnKeyUp(Key::LButton);
break;
}
}

private:
Expand Down Expand Up @@ -411,14 +446,18 @@ bool Input::KeyDoubleClick(Key keyCode) const
return false;
}

const Offset2D& Input::GetMousePosition() const
Offset2D Input::GetMousePosition() const
{
return pimpl_->mousePosition;
}

const Offset2D& Input::GetMouseMotion() const
Offset2D Input::GetMouseMotion() const
{
return pimpl_->mouseMotion;
return Offset2D
{
static_cast<std::int32_t>(pimpl_->motionVector[0]),
static_cast<std::int32_t>(pimpl_->motionVector[1])
};
}

int Input::GetWheelMotion() const
Expand Down
15 changes: 12 additions & 3 deletions sources/Platform/Android/AndroidApp.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -84,9 +84,18 @@ static void WaitUntilNativeWindowIsInitialized(android_app* app)
}
}

/* Restore client data */
app->userData = init.clientUserData;
app->onAppCmd = init.clientOnAppCmd;
if (init.clientOnAppCmd != nullptr)
{
/* Restore client data if it was previously specified */
app->userData = init.clientUserData;
app->onAppCmd = init.clientOnAppCmd;
}
else
{
/* ... Otherwise, use LLGL specific callback to handle window resize/rotation */
app->userData = nullptr;
app->onAppCmd = AndroidCanvas::OnAndroidAppCommand;
}
}

AndroidApp& AndroidApp::Get()
Expand Down
Loading

0 comments on commit 13ca37d

Please sign in to comment.