Merge 945e435ad521734ddebc2c88a5a56acf6f71af26 into 7cfc30970b6cd86e8271dbb057783de9ccf46f39

This commit is contained in:
Vraiment 2017-07-27 04:47:32 +00:00 committed by GitHub
commit fc9611ea6f
9 changed files with 606 additions and 0 deletions

View File

@ -126,6 +126,8 @@ SET(LIBRARY_SOURCES
SDL2pp/AudioLock.cc
SDL2pp/AudioSpec.cc
SDL2pp/Color.cc
SDL2pp/EventPolling.cc
SDL2pp/EventWait.cc
SDL2pp/Exception.cc
SDL2pp/Point.cc
SDL2pp/RWops.cc
@ -145,6 +147,8 @@ SET(LIBRARY_HEADERS
SDL2pp/AudioSpec.hh
SDL2pp/Color.hh
SDL2pp/ContainerRWops.hh
SDL2pp/EventPolling.hh
SDL2pp/EventWait.hh
SDL2pp/Exception.hh
SDL2pp/Optional.hh
SDL2pp/Point.hh

60
SDL2pp/EventPolling.cc Normal file
View File

@ -0,0 +1,60 @@
/*
libSDL2pp - C++11 bindings/wrapper for SDL2
Copyright (C) 2017 Vraiment <jemc44@gmail.com>
This software is provided 'as-is', without any express or implied
warranty. In no event will the authors be held liable for any damages
arising from the use of this software.
Permission is granted to anyone to use this software for any purpose,
including commercial applications, and to alter it and redistribute it
freely, subject to the following restrictions:
1. The origin of this software must not be misrepresented; you must not
claim that you wrote the original software. If you use this software
in a product, an acknowledgment in the product documentation would be
appreciated but is not required.
2. Altered source versions must be plainly marked as such, and must not be
misrepresented as being the original software.
3. This notice may not be removed or altered from any source distribution.
*/
#include <SDL2pp/EventPolling.hh>
using std::function;
namespace SDL2pp {
namespace Event {
bool PollEvent() {
SDL_Event event;
auto result = SDL_PollEvent(&event);
return result;
}
bool PollEvent(function<void(const SDL_Event &)> eventHandler) {
SDL_Event event;
if (!SDL_PollEvent(&event)) {
return false;
}
eventHandler(event);
return true;
}
int PollAllEvents() {
int result;
for (result = 0; PollEvent(); result++);
return result;
}
int PollAllEvents(function<void(const SDL_Event &)> eventHandler) {
int result;
for (result = 0; PollEvent(eventHandler); result++);
return result;
}
}
}

144
SDL2pp/EventPolling.hh Normal file
View File

@ -0,0 +1,144 @@
/*
libSDL2pp - C++11 bindings/wrapper for SDL2
Copyright (C) 2017 Vraiment <jemc44@gmail.com>
This software is provided 'as-is', without any express or implied
warranty. In no event will the authors be held liable for any damages
arising from the use of this software.
Permission is granted to anyone to use this software for any purpose,
including commercial applications, and to alter it and redistribute it
freely, subject to the following restrictions:
1. The origin of this software must not be misrepresented; you must not
claim that you wrote the original software. If you use this software
in a product, an acknowledgment in the product documentation would be
appreciated but is not required.
2. Altered source versions must be plainly marked as such, and must not be
misrepresented as being the original software.
3. This notice may not be removed or altered from any source distribution.
*/
#ifndef SDL2PP_EVENTPOLLING_HH
#define SDL2PP_EVENTPOLLING_HH
#include <SDL_events.h>
#include <SDL2pp/Export.hh>
#include <functional>
namespace SDL2pp {
namespace Event {
////////////////////////////////////////////////////////////
/// \brief Polls a single event
///
/// This function tries to poll a single event from the event
/// queue using SDL_PollEvent(). If an event was polled it
/// returns true, if not it returns false.
///
/// \ingroup events
///
/// \headerfile SDL2pp/EventPolling.hh
///
/// \returns True if an event was polled, false otherwise
///
/// \see https://wiki.libsdl.org/SDL_PollEvent
///
////////////////////////////////////////////////////////////
SDL2PP_EXPORT bool PollEvent();
////////////////////////////////////////////////////////////
/// \brief Polls and handles a single event
///
/// This function tries to poll a single event from the event
/// queue using SDL_PollEvent(). If an event was polled the
/// event handler is called using the retrieved SDL_Event as an
/// argument then this function returns true. If no event was
/// retrieved the event handler is not called and this function
/// returns false.
///
/// This function accepts free functions, lambdas and callable objects.
///
/// If an instance of a callable struct/class needs to be passed
/// by reference, std::ref() needs to be used:
/// \code
/// struct EventHandler {
/// void operator()(const SDL_Event &);
/// };
///
/// EventHandler myEventHandler;
/// PollEvent(std::ref(myEventHandler));
/// \endcode
///
/// \ingroup events
///
/// \headerfile SDL2pp/EventPolling.hh
///
/// \param[in] eventHandler Object that can be used as eventHandler(event)
/// where event is an instance of SDL_Event
///
/// \returns True if an event was polled, false otherwise
///
/// \see https://wiki.libsdl.org/SDL_Event
/// \see https://wiki.libsdl.org/SDL_PollEvent
///
////////////////////////////////////////////////////////////
SDL2PP_EXPORT bool PollEvent(std::function<void(const SDL_Event &)> eventHandler);
////////////////////////////////////////////////////////////
/// \brief Polls all the events from the event queue
///
/// This function calls SDL_PollEvent() until the event queue is empty.
/// Returns the amount of events that were polled from the queue.
///
/// \ingroup events
///
/// \headerfile SDL2pp/EventPolling.hh
///
/// \returns The amount of polled events (can be zero)
///
/// \see https://wiki.libsdl.org/SDL_PollEvent
///
////////////////////////////////////////////////////////////
SDL2PP_EXPORT int PollAllEvents();
////////////////////////////////////////////////////////////
/// \brief Polls and handles all the events from the event queue
///
/// This function calls SDL_PollEvent() until the event queue is empty.
/// Then for each event that was polled the event handler is called
/// using the polled event as an argument. This function returns the
/// amount of events that were polled.
///
/// This function accepts free functions, lambdas and callable objects.
///
/// If an instance of a callable struct/class needs to be passed
/// by reference, std::ref() needs to be used:
/// \code
/// struct EventHandler {
/// void operator()(const SDL_Event &);
/// };
///
/// EventHandler myEventHandler;
/// PollAllEvents(std::ref(myEventHandler));
/// \endcode
///
/// \ingroup events
///
/// \headerfile SDL2pp/EventPolling.hh
///
/// \param[in] eventHandler Object that can be used as eventHandler(event)
/// where event is an instance of SDL_Event
///
/// \returns The amount of polled events (can be zero)
///
/// \see https://wiki.libsdl.org/SDL_Event
/// \see https://wiki.libsdl.org/SDL_PollEvent
///
////////////////////////////////////////////////////////////
SDL2PP_EXPORT int PollAllEvents(std::function<void(const SDL_Event &)> eventHandler);
}
}
#endif

53
SDL2pp/EventWait.cc Normal file
View File

@ -0,0 +1,53 @@
/*
libSDL2pp - C++11 bindings/wrapper for SDL2
Copyright (C) 2017 Vraiment <jemc44@gmail.com>
This software is provided 'as-is', without any express or implied
warranty. In no event will the authors be held liable for any damages
arising from the use of this software.
Permission is granted to anyone to use this software for any purpose,
including commercial applications, and to alter it and redistribute it
freely, subject to the following restrictions:
1. The origin of this software must not be misrepresented; you must not
claim that you wrote the original software. If you use this software
in a product, an acknowledgment in the product documentation would be
appreciated but is not required.
2. Altered source versions must be plainly marked as such, and must not be
misrepresented as being the original software.
3. This notice may not be removed or altered from any source distribution.
*/
#include <SDL2pp/EventWait.hh>
#include <SDL2pp/Exception.hh>
namespace SDL2pp {
namespace Event {
SDL_Event WaitEvent() {
SDL_Event result;
if (SDL_WaitEvent(&result) == 0) {
throw Exception("SDL_WaitEvent");
}
return result;
}
Optional<SDL_Event> WaitEvent(int timeout) {
SDL_Event result;
SDL_ClearError(); // Necessary to ensure SDL_WaitEventTimeout
// returned with no errors
if (SDL_WaitEventTimeout(&result, timeout) == 0) {
auto error = SDL_GetError();
// Check if the error message is empty
if (*error == 0) {
return Optional<SDL_Event>();
} else {
throw Exception("SDL_WaitEventTimeout");
}
}
return result;
}
}
}

77
SDL2pp/EventWait.hh Normal file
View File

@ -0,0 +1,77 @@
/*
libSDL2pp - C++11 bindings/wrapper for SDL2
Copyright (C) 2017 Vraiment <jemc44@gmail.com>
This software is provided 'as-is', without any express or implied
warranty. In no event will the authors be held liable for any damages
arising from the use of this software.
Permission is granted to anyone to use this software for any purpose,
including commercial applications, and to alter it and redistribute it
freely, subject to the following restrictions:
1. The origin of this software must not be misrepresented; you must not
claim that you wrote the original software. If you use this software
in a product, an acknowledgment in the product documentation would be
appreciated but is not required.
2. Altered source versions must be plainly marked as such, and must not be
misrepresented as being the original software.
3. This notice may not be removed or altered from any source distribution.
*/
#ifndef SDL2PP_EVENTWAIT_HH
#define SDL2PP_EVENTWAIT_HH
#include <SDL_events.h>
#include <SDL2pp/Export.hh>
#include <SDL2pp/Optional.hh>
namespace SDL2pp {
namespace Event {
////////////////////////////////////////////////////////////
/// \brief Waits indefinitely for an event
///
/// This function waits for the next available event. This
/// function WILL STOP the program execution until an event
/// is available.
///
/// \ingroup events
///
/// \headerfile SDL2pp/EventWait.hh
///
/// \returns The event that was available
///
/// \throws SDL2pp::Exception
///
/// \see https://wiki.libsdl.org/SDL_WaitEvent
///
////////////////////////////////////////////////////////////
SDL2PP_EXPORT SDL_Event WaitEvent();
////////////////////////////////////////////////////////////
/// \brief Waits a given amount of time for an event
///
/// This function waits for the next available event for
/// specified amount of time. This function WILL STOP the
/// program execution until the given amount of time runs out
/// or an event is available.
///
/// \ingroup events
///
/// \headerfile SDL2pp/EventWait.hh
///
/// \param[in] timeout The amount of time to wait for an event
///
/// \returns The last event that was available
///
/// \throws SDL2pp::Exception
///
/// \see https://wiki.libsdl.org/SDL_WaitEvent
///
////////////////////////////////////////////////////////////
SDL2PP_EXPORT Optional<SDL_Event> WaitEvent(int timeout);
}
}
#endif

View File

@ -97,6 +97,15 @@
#include <SDL2pp/ContainerRWops.hh>
#include <SDL2pp/StreamRWops.hh>
////////////////////////////////////////////////////////////
/// \defgroup events Event handling
///
/// \brief Functions and classes to easily manage SDL events
///
////////////////////////////////////////////////////////////
#include <SDL2pp/EventPolling.hh>
#include <SDL2pp/EventWait.hh>
#ifdef SDL2PP_WITH_TTF
////////////////////////////////////////////////////////////
/// \defgroup ttf SDL_ttf

View File

@ -2,6 +2,8 @@
SET(CLI_TESTS
test_color
test_color_constexpr
test_eventpolling
test_eventwait
test_error
test_optional
test_pointrect

213
tests/test_eventpolling.cc Normal file
View File

@ -0,0 +1,213 @@
#include <SDL_main.h>
#include <SDL2pp/EventPolling.hh>
#include <SDL2pp/Exception.hh>
#include "testing.h"
#include <vector>
using namespace SDL2pp;
using namespace SDL2pp::Event;
using namespace std;
inline SDL_Event PushUserEvent(Sint32 userCode = 0, void *data1 = nullptr, void *data2 = nullptr) {
SDL_Event event;
event.type = SDL_USEREVENT;
event.user.code = userCode;
event.user.data1 = data1;
event.user.data2 = data2;
if (SDL_PushEvent(&event) < 0) {
throw Exception("SDL_PushEvent");
}
return event;
}
namespace StaticEventHandler {
vector<SDL_Event> events;
inline void EventHandler(const SDL_Event& event) {
events.push_back(event);
}
}
struct CallableEventHandler {
vector<SDL_Event> events;
void operator()(const SDL_Event& event) {
events.push_back(event);
}
};
BEGIN_TEST(int, char*[])
// With no callback and no polled event
{
EXPECT_TRUE(PollEvent() == false);
}
// With no callback and a polled event
{
PushUserEvent();
EXPECT_TRUE(PollEvent() == true);
EXPECT_TRUE(PollEvent() == false);
}
// With function as an event handler
{
StaticEventHandler::events.clear();
const SDL_Event expected = PushUserEvent(15);
EXPECT_TRUE(PollEvent(StaticEventHandler::EventHandler) == true);
EXPECT_TRUE(StaticEventHandler::events.size() == 1);
const SDL_Event result = StaticEventHandler::events[0];
EXPECT_TRUE(result.type == expected.type);
EXPECT_TRUE(result.user.code == expected.user.code);
// Verify no further events
EXPECT_TRUE(PollEvent(StaticEventHandler::EventHandler) == false);
EXPECT_TRUE(StaticEventHandler::events.size() == 1);
}
// With lambda as an event handler
{
vector<SDL_Event> events;
const SDL_Event expectedEvent = PushUserEvent(22);
EXPECT_TRUE(PollEvent([&events](const SDL_Event& event) {
events.push_back(event);
}) == true);
EXPECT_TRUE(events.size() == 1);
const SDL_Event result = events[0];
EXPECT_TRUE(result.type == expectedEvent.type);
EXPECT_TRUE(result.user.code == expectedEvent.user.code);
// Verify no further events
EXPECT_TRUE(PollEvent([&events](const SDL_Event& event) {
events.push_back(event);
}) == false);
EXPECT_TRUE(events.size() == 1);
}
// With callable object
{
CallableEventHandler eventHandler;
const SDL_Event expectedEvent = PushUserEvent(45);
EXPECT_TRUE(PollEvent(std::ref(eventHandler)) == true);
EXPECT_TRUE(eventHandler.events.size() == 1);
const SDL_Event result = eventHandler.events[0];
EXPECT_TRUE(result.type == expectedEvent.type);
EXPECT_TRUE(result.user.code == expectedEvent.user.code);
// Verify no further events
EXPECT_TRUE(PollEvent(eventHandler) == false);
EXPECT_TRUE(eventHandler.events.size() == 1);
}
// With no callback and no polled events
{
EXPECT_TRUE(PollAllEvents() == 0);
}
// With no callback and several polled events
{
constexpr int totalEvents = 5;
for (int n = 0; n < totalEvents; ++n) {
PushUserEvent();
}
EXPECT_TRUE(PollAllEvents() == totalEvents);
// Verify no further events
EXPECT_TRUE(PollEvent() == false);
}
// With function as an event handler
{
StaticEventHandler::events.clear();
vector<SDL_Event> expectedEvents;
for (const auto eventCode : { 15, 32, 99, 85 }) {
expectedEvents.push_back(PushUserEvent(eventCode));
}
int totalExpectedEvents = static_cast<int>(expectedEvents.size());
EXPECT_TRUE(PollAllEvents(StaticEventHandler::EventHandler) == totalExpectedEvents);
EXPECT_TRUE(StaticEventHandler::events.size() == expectedEvents.size());
for (int n = 0; n < totalExpectedEvents; n++) {
const SDL_Event result = StaticEventHandler::events[n];
const SDL_Event expected = expectedEvents[n];
EXPECT_TRUE(result.type == expected.type);
EXPECT_TRUE(result.user.code == expected.user.code);
}
// Verify no further events
EXPECT_TRUE(PollEvent(StaticEventHandler::EventHandler) == false);
EXPECT_TRUE(StaticEventHandler::events.size() == expectedEvents.size());
}
// With lambda as an event handler
{
vector<SDL_Event> handledEvents;
vector<SDL_Event> expectedEvents;
for (const auto eventCode : { 37, 88, 42, 63, 23, 19 }) {
expectedEvents.push_back(PushUserEvent(eventCode));
}
int totalExpectedEvents = static_cast<int>(expectedEvents.size());
EXPECT_TRUE(PollAllEvents([&handledEvents](const SDL_Event& event) {
handledEvents.push_back(event);
}) == totalExpectedEvents);
EXPECT_TRUE(handledEvents.size() == expectedEvents.size());
for (int n = 0; n < totalExpectedEvents; n++) {
const SDL_Event result = handledEvents[n];
const SDL_Event expected = expectedEvents[n];
EXPECT_TRUE(result.type == expected.type);
EXPECT_TRUE(result.user.code == expected.user.code);
}
// Verify no further events
EXPECT_TRUE(PollEvent([&handledEvents](const SDL_Event& event) {
handledEvents.push_back(event);
}) == false);
EXPECT_TRUE(handledEvents.size() == expectedEvents.size());
}
// With callable object as an event handler
{
CallableEventHandler eventHandler;
vector<SDL_Event> expectedEvents;
for (const auto eventCode : { 11, 98, 62, 35, 71 }) {
expectedEvents.push_back(PushUserEvent(eventCode));
}
int totalExpectedEvents = static_cast<int>(expectedEvents.size());
EXPECT_TRUE(PollAllEvents(std::ref(eventHandler)) == totalExpectedEvents);
EXPECT_TRUE(eventHandler.events.size() == expectedEvents.size());
for (int n = 0; n < totalExpectedEvents; n++) {
const SDL_Event result = eventHandler.events[n];
const SDL_Event expected = expectedEvents[n];
EXPECT_TRUE(result.type == expected.type);
EXPECT_TRUE(result.user.code == expected.user.code);
}
// Verify no further events
EXPECT_TRUE(PollEvent(eventHandler) == false);
EXPECT_TRUE(eventHandler.events.size() == expectedEvents.size());
}
END_TEST()

44
tests/test_eventwait.cc Normal file
View File

@ -0,0 +1,44 @@
#include <SDL.h>
#include <SDL2pp/SDL.hh>
#include <SDL2pp/EventWait.hh>
#include "testing.h"
using namespace SDL2pp;
using namespace SDL2pp::Event;
BEGIN_TEST(int, char*[])
const SDL sdl(SDL_INIT_EVENTS);
// Test wait event with no timeout
{
SDL_Event expected;
expected.type = SDL_USEREVENT;
expected.user.code = 99;
SDL_PushEvent(&expected);
auto result = WaitEvent();
EXPECT_TRUE(result.type == expected.type);
EXPECT_TRUE(result.user.code == expected.user.code);
}
// Test wait event with timeout and with event
{
SDL_Event expected;
expected.type = SDL_USEREVENT;
expected.user.code = 32;
SDL_PushEvent(&expected);
auto result = WaitEvent(10);
EXPECT_TRUE(!(result == NullOpt));
EXPECT_TRUE(result->type == expected.type);
EXPECT_TRUE(result->user.code == expected.user.code);
}
// Test wait event with timeout and no event
{
auto result = WaitEvent(10);
EXPECT_TRUE(result == NullOpt);
}
END_TEST()