diff --git a/CMakeLists.txt b/CMakeLists.txt index fb04198..e2814be 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -100,6 +100,7 @@ SET(LIBRARY_SOURCES SDL2pp/AudioDevice.cc SDL2pp/AudioLock.cc SDL2pp/AudioSpec.cc + SDL2pp/Cursor.cc SDL2pp/Exception.cc SDL2pp/Point.cc SDL2pp/RWops.cc @@ -118,6 +119,7 @@ SET(LIBRARY_HEADERS SDL2pp/AudioDevice.hh SDL2pp/AudioSpec.hh SDL2pp/ContainerRWops.hh + SDL2pp/Cursor.hh SDL2pp/Exception.hh SDL2pp/Optional.hh SDL2pp/Point.hh diff --git a/SDL2pp/Cursor.cc b/SDL2pp/Cursor.cc new file mode 100644 index 0000000..e4f9651 --- /dev/null +++ b/SDL2pp/Cursor.cc @@ -0,0 +1,79 @@ +/* + libSDL2pp - C++11 bindings/wrapper for SDL2 + Copyright (C) 2015 Dmitry Marakasov + + 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 +#include +#include + +namespace SDL2pp { + +Cursor::Cursor(SDL_Cursor* cursor) : cursor_(cursor) { +} + +Cursor Cursor::CreateSystemCursor(SDL_SystemCursor id) { + SDL_Cursor* cursor = SDL_CreateSystemCursor(id); + if (cursor == nullptr) + throw Exception("SDL_CreateSystemCursor failed"); + return Cursor(cursor); +} + +Cursor Cursor::CreateCursor(const Uint8* data, const Uint8* mask, int w, int h, int hot_x, int hot_y) { + SDL_Cursor* cursor = SDL_CreateCursor(data, mask, w, h, hot_x, hot_y); + if (cursor == nullptr) + throw Exception("SDL_CreateCursor failed"); + return Cursor(cursor); +} + +Cursor Cursor::CreateColorCursor(const Surface& surface, int hot_x, int hot_y) { + SDL_Cursor* cursor = SDL_CreateColorCursor(surface.Get(), hot_x, hot_y); + if (cursor == nullptr) + throw Exception("SDL_CreateColorCursor failed"); + return Cursor(cursor); +} + +Cursor::~Cursor() { + if (cursor_ != nullptr) + SDL_FreeCursor(cursor_); +} + +Cursor::Cursor(Cursor&& other) noexcept : cursor_(other.cursor_) { + other.cursor_ = nullptr; +} + +Cursor& Cursor::operator=(Cursor&& other) noexcept { + if (&other == this) + return *this; + if (cursor_ != nullptr) + SDL_FreeCursor(cursor_); + cursor_ = other.cursor_; + other.cursor_ = nullptr; + return *this; +} + +SDL_Cursor* Cursor::Get() const { + return cursor_; +} + +void Cursor::Set() { + SDL_SetCursor(cursor_); +} + +} diff --git a/SDL2pp/Cursor.hh b/SDL2pp/Cursor.hh new file mode 100644 index 0000000..233dc66 --- /dev/null +++ b/SDL2pp/Cursor.hh @@ -0,0 +1,144 @@ +/* + libSDL2pp - C++11 bindings/wrapper for SDL2 + Copyright (C) 2015 Dmitry Marakasov + + 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_CURSOR_HH +#define SDL2PP_CURSOR_HH + +#include + +namespace SDL2pp { + +class Surface; + +//////////////////////////////////////////////////////////// +/// \brief Mouse pointer image +/// +/// \ingroup windows +/// +/// \headerfile SDL2pp/Cursor.hh +/// +//////////////////////////////////////////////////////////// +class Cursor { +private: + SDL_Cursor* cursor_; ///< Contained SDL_Cursor structure + +public: + //////////////////////////////////////////////////////////// + /// \brief Construct from existing SDL_Cursor structure + /// + /// \param texture Existing SDL_Cursor to manage + /// + //////////////////////////////////////////////////////////// + Cursor(SDL_Cursor* cursor); + + //////////////////////////////////////////////////////////// + /// \brief Create system cursor + /// + /// \param id System cursor enum value + /// + /// \throws SDL2pp::Exception + /// + /// \see http://wiki.libsdl.org/SDL_CreateSystemCursor + /// + //////////////////////////////////////////////////////////// + static Cursor CreateSystemCursor(SDL_SystemCursor id); + + //////////////////////////////////////////////////////////// + /// \brief Create a cursor using the specified bitmap data and mask (in MSB format) + /// + /// \param data Color value for each pixel of the cursor + /// \param mask Mask value for each pixel of the cursor + /// \param w Width of the cursor + /// \param h Height of the cursor + /// \param hot_x X-axis location of the upper left corner of the cursor relative to the actual mouse position + /// \param hot_x Y-axis location of the upper left corner of the cursor relative to the actual mouse position + /// + /// \throws SDL2pp::Exception + /// + /// \see http://wiki.libsdl.org/SDL_CreateCursor + /// + //////////////////////////////////////////////////////////// + static Cursor CreateCursor(const Uint8* data, const Uint8* mask, int w, int h, int hot_x, int hot_y); + + //////////////////////////////////////////////////////////// + /// \brief Create a cursor using the specified bitmap data and mask (in MSB format) + /// + /// \param surface SDL2pp::Surface representing the cursor image + /// \param hot_x X position of the cursor hot spot + /// \param hot_y Y position of the cursor hot spot + /// + /// \throws SDL2pp::Exception + /// + /// \see http://wiki.libsdl.org/SDL_CreateColorCursor + /// + //////////////////////////////////////////////////////////// + static Cursor CreateColorCursor(const Surface& surface, int hot_x, int hot_y); + + //////////////////////////////////////////////////////////// + /// \brief Destructor + /// + /// \see http://wiki.libsdl.org/SDL_FreeCursor + /// + //////////////////////////////////////////////////////////// + virtual ~Cursor(); + + //////////////////////////////////////////////////////////// + /// \brief Move constructor + /// + /// \param other SDL2pp::Cursor object to move data from + /// + //////////////////////////////////////////////////////////// + Cursor(Cursor&& other) noexcept; + + //////////////////////////////////////////////////////////// + /// \brief Move assignment + /// + /// \param other SDL2pp::Cursor object to move data from + /// + /// \returns Reference to self + /// + //////////////////////////////////////////////////////////// + Cursor& operator=(Cursor&& other) noexcept; + + // Deleted copy constructor and assignment + Cursor(const Cursor& other) = delete; + Cursor& operator=(const Cursor& other) = delete; + + //////////////////////////////////////////////////////////// + /// \brief Get pointer to contained SDL_Cursor structure + /// + /// \returns Pointer to contained SDL_Cursor structure + /// + //////////////////////////////////////////////////////////// + SDL_Cursor* Get() const; + + //////////////////////////////////////////////////////////// + /// \brief Set the active cursor + /// + /// \see http://wiki.libsdl.org/SDL_SetCursor + /// + //////////////////////////////////////////////////////////// + void Set(); +}; + +} + +#endif diff --git a/examples/CMakeLists.txt b/examples/CMakeLists.txt index 257a976..009c12e 100644 --- a/examples/CMakeLists.txt +++ b/examples/CMakeLists.txt @@ -15,6 +15,9 @@ TARGET_LINK_LIBRARIES(audio_sine SDL2pp) ADD_EXECUTABLE(audio_wav audio_wav.cc) TARGET_LINK_LIBRARIES(audio_wav SDL2pp) +ADD_EXECUTABLE(cursor cursor.cc) +TARGET_LINK_LIBRARIES(cursor SDL2pp) + IF(SDL2PP_WITH_IMAGE) ADD_EXECUTABLE(image image.cc) TARGET_LINK_LIBRARIES(image SDL2pp) diff --git a/examples/cursor.cc b/examples/cursor.cc new file mode 100644 index 0000000..24dde81 --- /dev/null +++ b/examples/cursor.cc @@ -0,0 +1,96 @@ +/* + libSDL2pp - C++11 bindings/wrapper for SDL2 + Copyright (C) 2015 Dmitry Marakasov + + 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 + +#include + +#include +#include +#include +#include +#include +#include +#include + +using namespace SDL2pp; + +Uint8 cursor_data[8] = { 0x38, 0x28, 0xEE, 0x82, 0xEE, 0x28, 0x38, 0x00 }; +Uint8 cursor_mask[8] = { 0x38, 0x38, 0xFE, 0xFE, 0xFE, 0x38, 0x38, 0x00 }; + +Cursor GenCursor(int mode) { + switch (mode % 4) { + default: + return Cursor::CreateSystemCursor(SDL_SYSTEM_CURSOR_ARROW); + case 1: + return Cursor::CreateSystemCursor(SDL_SYSTEM_CURSOR_HAND); + case 2: + return Cursor::CreateCursor(cursor_data, cursor_mask, 8, 8, 3, 3); + case 3: + { + Surface surf(TESTDATA_DIR "/test.png"); + return Cursor::CreateColorCursor(surf, surf.GetWidth() / 2, surf.GetHeight() / 2); + } + } +} + +int Run() { + SDL sdl(SDL_INIT_VIDEO); + Window window("libSDL2pp demo: cursors", SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED, 640, 480, SDL_WINDOW_RESIZABLE); + Renderer render(window, -1, SDL_RENDERER_ACCELERATED); + + int cursormode = 0; + Optional cur; + + while (1) { + SDL_Event event; + while (SDL_PollEvent(&event)) { + if (event.type == SDL_QUIT || (event.type == SDL_KEYDOWN && (event.key.keysym.sym == SDLK_ESCAPE || event.key.keysym.sym == SDLK_q))) { + return 0; + } else if (event.type == SDL_MOUSEBUTTONDOWN) { + cur = GenCursor(++cursormode); + cur->Set(); + } + } + + // Clear screen + render.SetDrawColor(0, 32, 32); + render.Clear(); + + render.Present(); + + SDL_Delay(1); + } + + return 0; +} + +int main() { + try { + return Run(); + } catch (Exception& e) { + std::cerr << "Error: " << e.what() << " (" << e.GetSDLError() << ")" << std::endl; + } catch (std::exception& e) { + std::cerr << "Error: " << e.what() << std::endl; + } + + return -1; +}