diff --git a/SDLU/CMakeLists.txt b/SDLU/CMakeLists.txt index 0cb67e4..e25dabd 100644 --- a/SDLU/CMakeLists.txt +++ b/SDLU/CMakeLists.txt @@ -2,7 +2,7 @@ set(PNAME SDLU) add_library(${PNAME} alibi.cpp SDLU.hpp Util.hpp - "structures/Color.cpp" "structures/Mouse.cpp") + "structures/Color.cpp" "structures/Mouse.cpp" "structures/Window.cpp") set_property(TARGET ${PNAME} PROPERTY CXX_STANDARD 17) diff --git a/SDLU/structures/CMakeLists.txt b/SDLU/structures/CMakeLists.txt index 1f7d68f..3a7198c 100644 --- a/SDLU/structures/CMakeLists.txt +++ b/SDLU/structures/CMakeLists.txt @@ -4,4 +4,6 @@ target_sources(${PNAME} PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/Color.cpp ${CMAKE_CURRENT_SOURCE_DIR}/Mouse.hpp ${CMAKE_CURRENT_SOURCE_DIR}/Mouse.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/Window.hpp + ${CMAKE_CURRENT_SOURCE_DIR}/Window.cpp ) \ No newline at end of file diff --git a/SDLU/structures/Window.cpp b/SDLU/structures/Window.cpp new file mode 100644 index 0000000..aea07ce --- /dev/null +++ b/SDLU/structures/Window.cpp @@ -0,0 +1,240 @@ +#include "Window.hpp" + +#include + +#include + +namespace sdlu +{ + Window::Window() : + window(nullptr) + { + // Empty + } + + Window::Window(Vector2u dimension, const std::string& title, Uint32 windowFlags) : + Window() + { + Create(dimension, title, windowFlags); + } + + Window::~Window() + { + Close(); + } + + void Window::Create(Vector2u dimension, const std::string& title, Uint32 windowFlags) + { + // Don't create a window when it already exists + RETURN_IF_NOT_NULLPTR(window); + + window = SDL_CreateWindow(title.c_str(), + SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED, + dimension.x, dimension.y, + windowFlags); + + THROW_IF(IS_NULLPTR(window), + ObjectCreationException("Failed to create SDL_Window. \nSDL_GetError(): " + std::string(SDL_GetError()))); + + OnCreate(); + } + + void Window::Close() + { + // Don't destroy a window that doesn't exist + RETURN_IF_NULLPTR(window); + + SDL_DestroyWindow(window); + window = nullptr; + + OnClose(); + } + + bool Window::IsOpen() const + { + RETURN_IF_NULLPTR(window, false); + return (!SDL_GetWindowID(window) ? false : true); + } + + bool Window::PollEvent(SDL_Event* event) + { + RETURN_IF_NULLPTR(window, false); + // Handle events before the user in case a derived + // class decides to block the event. + while (SDL_PollEvent(event)) + { + switch (event->window.event) + { + case SDL_WINDOWEVENT_RESIZED: if (!OnResize()) return true; break; + default: return true; + } + } + + event = NULL; + return false; + } + + bool Window::WaitEvent(SDL_Event* event) + { + while (!PollEvent(event)) continue; + return true; + } + + Vector2i Window::GetPosition() const + { + RETURN_IF_NULLPTR(window, Vector2i()); + + int x = 0, y = 0; + SDL_GetWindowPosition(window, &x, &y); + return Vector2i(x, y); + } + + void Window::SetPosition(Vector2i position) + { + RETURN_IF_NULLPTR(window); + + SDL_SetWindowPosition(window, position.x, position.y); + } + + void Window::SetPosition(int x, int y) + { + RETURN_IF_NULLPTR(window); + + SDL_SetWindowPosition(window, x, y); + } + + Vector2u Window::GetSize() const + { + RETURN_IF_NULLPTR(window, Vector2u()); + + int x = 0, y = 0; + SDL_GetWindowSize(window, &x, &y); + return Vector2u(x, y); + } + + void Window::SetSize(Vector2u size) + { + RETURN_IF_NULLPTR(window); + + SDL_SetWindowSize(window, size.x, size.y); + } + + void Window::SetSize(unsigned int width, unsigned int height) + { + RETURN_IF_NULLPTR(window); + + SDL_SetWindowSize(window, width, height); + } + + std::string Window::GetTitle() const + { + RETURN_IF_NULLPTR(window, ""); + + return SDL_GetWindowTitle(window); + } + + void Window::SetTitle(std::string title) + { + RETURN_IF_NULLPTR(window); + + SDL_SetWindowTitle(window, title.c_str()); + } + + SDL_Window* const Window::GetWindow() const + { + return window; + } + + void Window::SetVisible(bool visible) + { + RETURN_IF_NULLPTR(window); + if (visible) + SDL_ShowWindow(window); + else + SDL_HideWindow(window); + } + + void Window::SetVsync(bool vsync) + { + // SDL actually doesn't allow you to change the VSync + // flag of a Renderer after it's been created. This + // Changes it globally for all other windows + SDL_GL_SetSwapInterval(vsync); + } + + void Window::SetMouseCursorVisible(bool visible) + { + SDL_ShowCursor(visible); + } + + void Window::SetMouseCursorGrabbed(bool grabbed) + { + SDL_SetWindowGrab(window, grabbed ? SDL_TRUE : SDL_FALSE); + } + + void Window::SetIcon(Uint32 width, Uint32 height, const Uint8* pixels) + { + size_t size = static_cast(width) * static_cast(height) * 4; + void* _pixels = malloc(size); + memcpy(_pixels, pixels, size); + SDL_Surface* surface = SDL_CreateRGBSurfaceWithFormatFrom(_pixels, + width, height, 32, 32 * width, + SDL_PIXELFORMAT_RGBA8888); + + SDL_SetWindowIcon(window, surface); + } + + void Window::SetIcon(Uint32 width, Uint32 height, const Uint32* pixels) + { + size_t size = static_cast(width) * static_cast(height) * 4; + void* _pixels = malloc(size); + memcpy(_pixels, pixels, size); + SDL_Surface* surface = SDL_CreateRGBSurfaceWithFormatFrom(_pixels, + width, height, 32, 4 * width, + SDL_PIXELFORMAT_RGBA8888); + + SDL_SetWindowIcon(window, surface); + } + + void Window::SetIcon(SDL_Surface* icon) + { + SDL_SetWindowIcon(window, icon); + } + + void Window::SetMouseCursor(SDL_Cursor* cursor) + { + SDL_SetCursor(cursor); + } + + void Window::SetMouseCursor(SDL_SystemCursor cursor) + { + SDL_Cursor* _cursor = SDL_CreateSystemCursor(cursor); + SDL_SetCursor(_cursor); + } + + void Window::SetMouseCursor(SDL_Surface* surface, Vector2u clickspot) + { + SDL_Cursor* _cursor = SDL_CreateColorCursor(surface, clickspot.x, clickspot.y); + SDL_SetCursor(_cursor); + } + + void Window::SetMouseCursor(const Uint8* pixels, Vector2u size, Vector2u clickspot) + { + size_t _size = static_cast(size.x) * static_cast(size.y) * 4; + void* _pixels = malloc(_size); + memcpy(_pixels, pixels, _size); + SDL_Surface* surface = SDL_CreateRGBSurfaceWithFormatFrom(_pixels, + size.x, size.y, 32, 8 * size.x, SDL_PIXELFORMAT_RGBA8888); + this->SetMouseCursor(surface, clickspot); + } + + void Window::SetMouseCursor(const Uint32* pixels, Vector2u size, Vector2u clickspot) + { + size_t _size = static_cast(size.x) * static_cast(size.y) * 4; + void* _pixels = malloc(_size); + memcpy(_pixels, pixels, _size); + SDL_Surface* surface = SDL_CreateRGBSurfaceWithFormatFrom(_pixels, + size.x, size.y, 32, 8 * size.x, SDL_PIXELFORMAT_RGBA32); + this->SetMouseCursor(surface, clickspot); + } +} \ No newline at end of file diff --git a/SDLU/structures/Window.hpp b/SDLU/structures/Window.hpp new file mode 100644 index 0000000..1d27661 --- /dev/null +++ b/SDLU/structures/Window.hpp @@ -0,0 +1,269 @@ +/** + * @file Window.hpp + * @brief Contains window related objects + * @author Lauchmelder23 + * @date 20.05.20 + */ +#pragma once +#include +#include + +#include + +#include +#include + + +namespace sdlu +{ + /** + * @brief Stores information about a window. You probably want RenderWindow. + */ + class Window + { + public: + /** + * @brief Default Constructor. No window is created. + */ + Window(); + + /** + * @brief Creates a window with the given parameters + * + * @param[in] dimension A vector containing the width and height + * @param[in] title The title of the create window + */ + Window(Vector2u dimension, const std::string& title, + Uint32 windowFlags); + + Window(const Window& other) = delete; + Window(Window&& other) = delete; + + virtual ~Window(); + + /** + * @brief Creates the window. + * + * This function creates the SDL_Window object. If + * they were already created the function does nothing and returns. + * If it fails to create either, an ObjectCreationException is thrown. + * + * @param[in] dimension A vector containing the width and height + * @param[in] title The title of the create window + */ + void Create(Vector2u dimension, const std::string& title, + Uint32 windowFlags); + + /** + * @brief Destroys the window. + */ + void Close(); + + /** + * @brief Wether or not the window object is created + * + * @return True if the window is open, False if not + */ + bool IsOpen() const; + + /** + * @brief A non-blocking event polling function + * + * @param[out] event An object to write the latest event to + * @return True if there was an event, False if there wasn't + */ + bool PollEvent(SDL_Event* event); + + /** + * @brief A blocking event polling function + * + * @param[out] event An object to write the latest event to + * @return True if an event was polled + */ + bool WaitEvent(SDL_Event* event); + + + /** + * @brief Returns the current position of the window + * + * @return A vector with the current position relative to the top left corner of the display + */ + Vector2i GetPosition() const; + + /** + * @brief Sets a new window position + * + * @param[in] position A vector with the new position + */ + void SetPosition(Vector2i position); + + /** + * @brief Sets a new window position + * + * @param[in] x The new x position + * @param[in] y The new y position + */ + void SetPosition(int x, int y); + + + /** + * @brief Gets the current window size + * + * @return A vector with the windows size + */ + Vector2u GetSize() const; + + /** + * @brief Sets a new window size + * + * @param[in] size A vector with the new size + */ + void SetSize(Vector2u size); + + /** + * @brief Sets a new window size + * + * @param[in] width The new width of the window + * @param[in] height The new height of the window + */ + void SetSize(unsigned int width, unsigned int height); + + + /** + * @brief Gets the current window title + * + * @return The title of the widnow + */ + std::string GetTitle() const; + + /** + * @brief Sets a new window title + * + * @param[in] title The new window title + */ + void SetTitle(std::string title); + + /** + * @brief Returns a constant pointer to the SDL_Window + * + * @return A constant pointer to SDL_Window + */ + SDL_Window* const GetWindow() const; + + /** + * @brief Set the windows visibility + * + * @param[in] visible The new visibility setting + */ + void SetVisible(bool visible); + + /** + * @brief (De)activates VSync !globally! + * + * @param[in] vsync Wether to enable or disable vsync + */ + void SetVsync(bool vsync); + + /** + * @brief Hides/Shows the mouse cursor inside the windos + * + * @param[in] visible The new visibility of the cursor + */ + void SetMouseCursorVisible(bool visible); + + /** + * @brief Traps the mouse cursor inside the window + * + * @param[in] grabbed Wether to (un)trap the cursor + */ + void SetMouseCursorGrabbed(bool grabbed); + + /** + * @brief Sets the window icon to an array of RGBA values + * + * @param[in] width Width of the icon (in px) + * @param[in] height Height of the icon (in px) + * @param[in] pixels Array of color data (RGBA as seperate 8-Bit integer values) + */ + void SetIcon(Uint32 width, Uint32 height, const Uint8* pixels); + + /** + * @brief Sets the window icon to an array of RGBA values + * + * @param[in] width Width of the icon (in px) + * @param[in] height Height of the icon (in px) + * @param[in] pixels Array of color data (RGBA as one 32-Bit integer value) + */ + void SetIcon(Uint32 width, Uint32 height, const Uint32* pixels); + + /** + * @brief Sets the window icon to a SDL_Surface + * + * @param[in] icon A SDL_Surface* holding the icon data + */ + void SetIcon(SDL_Surface* icon); + + /** + * @brief Changes the mouse cursor + * + * @param[in] cursor A pointer to a SDL_Cursor containing cursor data + */ + void SetMouseCursor(SDL_Cursor* cursor); + + /** + * @brief Changes the mouse cursor + * + * @param[in] cursor An enum for a system cursor + */ + void SetMouseCursor(SDL_SystemCursor cursor); + + /** + * @brief Changes the mouse cursor + * + * @param[in] surface A pointer to a SDL_Surface containing sprite data + * @param[in] clickspot The effective position of the cursor relative to the top left of the sprite + */ + void SetMouseCursor(SDL_Surface* surface, Vector2u clickspot); + + /** + * @brief Changes the mouse cursor + * + * @param[in] pixels An array of color data (RGBA as seperate 8-bit values) + * @param[in] size Size of the cursor + * @param[in] clickspot The effective position of the cursor relative to the top left of the sprite + */ + void SetMouseCursor(const Uint8* pixels, Vector2u size, Vector2u clickspot); + + /** + * @brief Changes the mouse cursor + * + * @param[in] pixels An array of color data (RGBA as one 32-bit value) + * @param[in] size Size of the cursor + * @param[in] clickspot The effective position of the cursor relative to the top left of the sprite + */ + void SetMouseCursor(const Uint32* pixels, Vector2u size, Vector2u clickspot); + + protected: + SDL_Window* window; + + protected: + /** + * @brief This function is called after Create() finishes + */ + virtual void OnCreate(); + + /** + * @brief This function is called after a SDL_WINDOWEVENT_RESIZED is polled. + * (PollEvent() must be called for this to work) + * + * @return True if the resize event should be popped from the event queue before + returning the polled event to the user + */ + virtual bool OnResize(); + + /** + * @brief This function is called after Close() finishes. + */ + virtual void OnClose(); + }; +} \ No newline at end of file