SDLU/SDLU/graphics/RenderWindow.cpp
2020-05-18 19:32:48 +02:00

285 lines
7.9 KiB
C++

#include "RenderWindow.hpp"
#include <exceptions/Exceptions.hpp>
#include <Util.hpp>
namespace sdlu
{
RenderWindow::RenderWindow() :
m_pWindow(nullptr), m_pRenderer(nullptr),
m_oFramerate(0), m_oTimeSinceLastDisplay(std::chrono::steady_clock::now())
{
}
RenderWindow::RenderWindow(Vector2u dimension, const std::string& title,
Uint32 windowFlags, Uint32 rendererFlags) :
RenderWindow()
{
Create(dimension, title, windowFlags, rendererFlags);
}
RenderWindow::~RenderWindow()
{
Close();
}
void RenderWindow::Create(Vector2u dimension, const std::string& title,
Uint32 windowFlags, Uint32 rendererFlags)
{
// Don't create a window when it already exists
RETURN_IF_NOT_NULLPTR(m_pWindow);
m_pWindow = SDL_CreateWindow(title.c_str(),
SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED,
dimension.x, dimension.y,
windowFlags);
THROW_IF(IS_NULLPTR(m_pWindow),
ObjectCreationException("Failed to create SDL_Window."));
m_pRenderer = SDL_CreateRenderer(m_pWindow, -1, rendererFlags);
THROW_IF(IS_NULLPTR(m_pRenderer),
ObjectCreationException("Failed to create SDL_Renderer."));
OnCreate();
}
void RenderWindow::Close()
{
// Don't destroy a window that doesn't exist
RETURN_IF_NULLPTR(m_pWindow);
SDL_DestroyRenderer(m_pRenderer);
m_pRenderer = nullptr;
SDL_DestroyWindow(m_pWindow);
m_pWindow = nullptr;
OnClose();
}
bool RenderWindow::IsOpen()
{
RETURN_IF_NULLPTR_ARG(m_pWindow, false);
return (!SDL_GetWindowID(m_pWindow) ? false : true);
}
bool RenderWindow::PollEvent(SDL_Event* event)
{
RETURN_IF_NULLPTR_ARG(m_pWindow, 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 RenderWindow::WaitEvent(SDL_Event* event)
{
while (!PollEvent(event)) continue;
return true;
}
Vector2i RenderWindow::GetPosition()
{
RETURN_IF_NULLPTR_ARG(m_pWindow, Vector2i());
int x = 0, y = 0;
SDL_GetWindowPosition(m_pWindow, &x, &y);
return Vector2i(x, y);
}
void RenderWindow::SetPosition(Vector2i position)
{
RETURN_IF_NULLPTR(m_pWindow);
SDL_SetWindowPosition(m_pWindow, position.x, position.y);
}
void RenderWindow::SetPosition(int x, int y)
{
RETURN_IF_NULLPTR(m_pWindow);
SDL_SetWindowPosition(m_pWindow, x, y);
}
Vector2u RenderWindow::GetSize()
{
RETURN_IF_NULLPTR_ARG(m_pWindow, Vector2u());
int x = 0, y = 0;
SDL_GetWindowSize(m_pWindow, &x, &y);
return Vector2u(x, y);
}
void RenderWindow::SetSize(Vector2u size)
{
RETURN_IF_NULLPTR(m_pWindow);
SDL_SetWindowSize(m_pWindow, size.x, size.y);
}
void RenderWindow::SetSize(unsigned int width, unsigned int height)
{
RETURN_IF_NULLPTR(m_pWindow);
SDL_SetWindowSize(m_pWindow, width, height);
}
std::string RenderWindow::GetTitle()
{
RETURN_IF_NULLPTR_ARG(m_pWindow, "");
return SDL_GetWindowTitle(m_pWindow);
}
void RenderWindow::SetTitle(std::string title)
{
RETURN_IF_NULLPTR(m_pWindow);
SDL_SetWindowTitle(m_pWindow, title.c_str());
}
SDL_Window* const RenderWindow::GetWindow()
{
return m_pWindow;
}
SDL_Renderer* const RenderWindow::GetRenderer()
{
return m_pRenderer;
}
void RenderWindow::Clear(const Color& color)
{
RETURN_IF_NULLPTR(m_pWindow);
SDL_SetRenderDrawColor(m_pRenderer, color.r, color.g, color.b, color.a);
SDL_RenderClear(m_pRenderer);
}
void RenderWindow::Display()
{
RETURN_IF_NULLPTR(m_pWindow);
SDL_RenderPresent(m_pRenderer);
if (m_oFramerate != 0)
{
Uint64 diff = std::chrono::duration_cast<std::chrono::milliseconds>(
std::chrono::steady_clock::now() - m_oTimeSinceLastDisplay).count();
if (diff < 1000 / m_oFramerate)
{
SDL_Delay(1000 / m_oFramerate - diff);
}
}
m_oTimeSinceLastDisplay = std::chrono::steady_clock::now();
}
void RenderWindow::SetVisible(bool visible)
{
RETURN_IF_NULLPTR(m_pWindow);
if (visible)
SDL_ShowWindow(m_pWindow);
else
SDL_HideWindow(m_pWindow);
}
void RenderWindow::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 RenderWindow::SetMouseCursorVisible(bool visible)
{
SDL_ShowCursor(visible);
}
void RenderWindow::SetMouseCursorGrabbed(bool grabbed)
{
SDL_SetWindowGrab(m_pWindow, grabbed ? SDL_TRUE : SDL_FALSE);
}
void RenderWindow::SetIcon(Uint32 width, Uint32 height, const Uint8* pixels)
{
size_t size = static_cast<size_t>(width) * static_cast<size_t>(height) * 4;
void* _pixels = malloc(size);
std::memcpy(_pixels, pixels, size);
SDL_Surface* surface = SDL_CreateRGBSurfaceWithFormatFrom(_pixels,
width, height, 32, 32 * width,
SDL_PIXELFORMAT_RGBA8888);
SDL_SetWindowIcon(m_pWindow, surface);
}
void RenderWindow::SetIcon(Uint32 width, Uint32 height, const Uint32* pixels)
{
size_t size = static_cast<size_t>(width) * static_cast<size_t>(height) * 4;
void* _pixels = malloc(size);
std::memcpy(_pixels, pixels, size);
SDL_Surface* surface = SDL_CreateRGBSurfaceWithFormatFrom(_pixels,
width, height, 32, 4 * width,
SDL_PIXELFORMAT_RGBA8888);
SDL_SetWindowIcon(m_pWindow, surface);
}
void RenderWindow::SetIcon(SDL_Surface* icon)
{
SDL_SetWindowIcon(m_pWindow, icon);
}
void RenderWindow::SetMaxFramerate(Uint32 max)
{
m_oFramerate = max;
}
void RenderWindow::SetMouseCursor(SDL_Cursor* cursor)
{
SDL_SetCursor(cursor);
}
void RenderWindow::SetMouseCursor(SDL_SystemCursor cursor)
{
SDL_Cursor* _cursor = SDL_CreateSystemCursor(cursor);
SDL_SetCursor(_cursor);
}
void RenderWindow::SetMouseCursor(SDL_Surface* surface, Vector2u clickspot)
{
SDL_Cursor* _cursor = SDL_CreateColorCursor(surface, clickspot.x, clickspot.y);
SDL_SetCursor(_cursor);
}
void RenderWindow::SetMouseCursor(const Uint8* pixels, Vector2u size, Vector2u clickspot)
{
size_t _size = static_cast<size_t>(size.x) * static_cast<size_t>(size.y) * 4;
void* _pixels = malloc(_size);
std::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 RenderWindow::SetMouseCursor(const Uint32* pixels, Vector2u size, Vector2u clickspot)
{
size_t _size = static_cast<size_t>(size.x) * static_cast<size_t>(size.y) * 4;
void* _pixels = malloc(_size);
std::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);
}
}