code integration
This commit is contained in:
15
quokka_gfx/quokka_gfx.h
Normal file
15
quokka_gfx/quokka_gfx.h
Normal file
@@ -0,0 +1,15 @@
|
||||
/**
|
||||
* QuokkaGFX - Lightweight SDL3 wrapper - umbrella header
|
||||
*
|
||||
* Single header include for easy integration.
|
||||
* Usage: #include "quokka_gfx/quokka_gfx.h"
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "quokka_gfx/Application.h"
|
||||
#include "quokka_gfx/Window/Window.h"
|
||||
#include "utils/Colors.h"
|
||||
#include "utils/Coords.h"
|
||||
|
||||
#include <SDL3/SDL.h>
|
||||
48
quokka_gfx/quokka_gfx/Application.cpp
Normal file
48
quokka_gfx/quokka_gfx/Application.cpp
Normal file
@@ -0,0 +1,48 @@
|
||||
#include "Application.h"
|
||||
|
||||
#include <SDL3/SDL.h>
|
||||
#include <algorithm>
|
||||
|
||||
using namespace std;
|
||||
using namespace quokka_gfx;
|
||||
//--------------------------------------------------------------
|
||||
/* Default constructor */
|
||||
Application::Application()
|
||||
: m_eventManager(*this)
|
||||
{
|
||||
// Initialize SDL context
|
||||
m_sdlContext = SDLContext::GetContext();
|
||||
}
|
||||
//--------------------------------------------------------------
|
||||
/* Get the WindowManager instance */
|
||||
WindowManager *Application::GetWindowManager() noexcept
|
||||
{
|
||||
return &m_windowManager;
|
||||
}
|
||||
//--------------------------------------------------------------
|
||||
/* Start the main event loop */
|
||||
void Application::Run() const
|
||||
{
|
||||
// Main loop
|
||||
bool running = true;
|
||||
uint64_t lastTime = SDL_GetTicksNS();
|
||||
|
||||
while (running && m_windowManager.HasAnyWindow())
|
||||
{
|
||||
// Calculate delta time
|
||||
const uint64_t currentTime = SDL_GetTicksNS();
|
||||
float dt = static_cast<float>(currentTime - lastTime) / 1e9f; // Convert nanoseconds to seconds
|
||||
lastTime = currentTime;
|
||||
dt = std::max(dt, 0.00001f); // Avoid zero or negative delta time
|
||||
|
||||
// Poll and process events
|
||||
const auto result = m_eventManager.ProcessEvents();
|
||||
if (result == EventManager::PollingResult::Quit)
|
||||
running = false;
|
||||
|
||||
// Update and Render all windows
|
||||
m_windowManager.Update(dt);
|
||||
m_windowManager.Render();
|
||||
}
|
||||
}
|
||||
//--------------------------------------------------------------
|
||||
36
quokka_gfx/quokka_gfx/Application.h
Normal file
36
quokka_gfx/quokka_gfx/Application.h
Normal file
@@ -0,0 +1,36 @@
|
||||
#pragma once
|
||||
|
||||
#include "Input/EventManager.h"
|
||||
#include "Input/InputManager.h"
|
||||
#include "SDLContext.h"
|
||||
#include "Window/WindowManager.h"
|
||||
|
||||
namespace quokka_gfx
|
||||
{
|
||||
//--------------------------------------------------------------
|
||||
class Application
|
||||
{
|
||||
friend class EventManager;
|
||||
friend class WindowManager;
|
||||
friend class Window;
|
||||
|
||||
public:
|
||||
Application(); // Default constructor
|
||||
virtual ~Application() = default; // Default destructor
|
||||
Application(const Application &obj) = delete; // Copy constructor
|
||||
Application(Application &&obj) noexcept = delete; // Move constructor
|
||||
Application &operator=(const Application &obj) = delete; // Copy assignment operator
|
||||
Application &operator=(Application &&obj) noexcept = delete; // Move assignment operator
|
||||
|
||||
[[nodiscard]] WindowManager *GetWindowManager() noexcept; // Get the WindowManager instance
|
||||
|
||||
void Run() const; // Start the main event loop
|
||||
|
||||
protected:
|
||||
SDLContext::pContext m_sdlContext = nullptr; // SDLContext instance
|
||||
EventManager m_eventManager; // EventManager instance
|
||||
InputManager m_inputManager; // InputManager instance
|
||||
WindowManager m_windowManager; // WindowManager instance
|
||||
};
|
||||
//--------------------------------------------------------------
|
||||
} // namespace quokka_gfx
|
||||
70
quokka_gfx/quokka_gfx/Input/EventManager.cpp
Normal file
70
quokka_gfx/quokka_gfx/Input/EventManager.cpp
Normal file
@@ -0,0 +1,70 @@
|
||||
#include "EventManager.h"
|
||||
|
||||
#include "../Application.h"
|
||||
#include "../Window/WindowManager.h"
|
||||
#include "InputManager.h"
|
||||
|
||||
using namespace std;
|
||||
using namespace quokka_gfx;
|
||||
//--------------------------------------------------------------
|
||||
/* Constructor */
|
||||
EventManager::EventManager(Application &appManager)
|
||||
: m_appManager(appManager)
|
||||
{
|
||||
// Nothing to do
|
||||
}
|
||||
//--------------------------------------------------------------
|
||||
/* Set the global event handler function */
|
||||
void EventManager::SetGlobalEventHandler(const GlobalEventHandler &globalEventHandler)
|
||||
{
|
||||
m_globalEventHandler = globalEventHandler;
|
||||
}
|
||||
//--------------------------------------------------------------
|
||||
/* Poll and process SDL events */
|
||||
EventManager::PollingResult EventManager::ProcessEvents() const
|
||||
{
|
||||
// Update the input states at the beginning of a new frame (before processing events)
|
||||
m_appManager.m_inputManager.updateStates();
|
||||
|
||||
// Handle events
|
||||
SDL_Event event;
|
||||
while (SDL_PollEvent(&event))
|
||||
{
|
||||
// Process events
|
||||
if (event.type == SDL_EVENT_QUIT)
|
||||
return PollingResult::Quit;
|
||||
|
||||
// Call the global event handler if it is set
|
||||
if (m_globalEventHandler)
|
||||
{
|
||||
const EventResult result = m_globalEventHandler(event);
|
||||
if (result == EventResult::Veto)
|
||||
continue;
|
||||
}
|
||||
|
||||
// Update input states based on the event
|
||||
m_appManager.m_inputManager.processEvent(event);
|
||||
|
||||
// Handle event for all windows
|
||||
switch (event.type)
|
||||
{
|
||||
case SDL_EVENT_WINDOW_FOCUS_GAINED: // Update the focused window ID when a window gains focus
|
||||
case SDL_EVENT_WINDOW_FOCUS_LOST: // Update the focused window ID when a window loses focus
|
||||
case SDL_EVENT_WINDOW_MOUSE_ENTER: // Update the hovered window ID when the mouse enters a window
|
||||
case SDL_EVENT_WINDOW_MOUSE_LEAVE: // Update the hovered window ID when the mouse leaves a window
|
||||
case SDL_EVENT_KEY_DOWN: // Update the current key state when a key is pressed
|
||||
case SDL_EVENT_KEY_UP: // Update the current key state when a key is released
|
||||
case SDL_EVENT_MOUSE_MOTION: // Update the current mouse position when the mouse is moved
|
||||
case SDL_EVENT_MOUSE_BUTTON_DOWN: // Update the current mouse button state when a mouse button is pressed
|
||||
case SDL_EVENT_MOUSE_BUTTON_UP: // Update the current mouse button state when a mouse button is released
|
||||
case SDL_EVENT_MOUSE_WHEEL: // Update the current mouse wheel state when the mouse wheel is scrolled
|
||||
// Input events are already processed by InputManager, no need to handle them here
|
||||
break;
|
||||
default:
|
||||
m_appManager.m_windowManager.OnEvent(&event);
|
||||
}
|
||||
}
|
||||
|
||||
return PollingResult::Continue;
|
||||
}
|
||||
//--------------------------------------------------------------
|
||||
46
quokka_gfx/quokka_gfx/Input/EventManager.h
Normal file
46
quokka_gfx/quokka_gfx/Input/EventManager.h
Normal file
@@ -0,0 +1,46 @@
|
||||
#pragma once
|
||||
|
||||
#include <SDL3/SDL.h>
|
||||
#include <functional>
|
||||
|
||||
namespace quokka_gfx
|
||||
{
|
||||
class Application;
|
||||
//--------------------------------------------------------------
|
||||
class EventManager
|
||||
{
|
||||
public:
|
||||
enum class PollingResult : uint8_t
|
||||
{
|
||||
Continue = 0, // Continue processing the event in the next handler
|
||||
Quit, // Quit the event loop, do not process it and stop further processing
|
||||
};
|
||||
|
||||
enum class EventResult : uint8_t
|
||||
{
|
||||
Skip = 0, // Skip the event, continue processing it in the next handler
|
||||
Veto, // Veto the event, do not process it and stop further processing
|
||||
};
|
||||
using GlobalEventHandler = std::function<EventResult(SDL_Event &event)>; // Function type for global event handlers
|
||||
|
||||
public:
|
||||
EventManager() = delete; // Default constructor
|
||||
virtual ~EventManager() = default; // Default destructor
|
||||
EventManager(const EventManager &obj) = delete; // Copy constructor
|
||||
EventManager(EventManager &&obj) noexcept = delete; // Move constructor
|
||||
EventManager &operator=(const EventManager &obj) = delete; // Copy assignment operator
|
||||
EventManager &operator=(EventManager &&obj) noexcept = delete; // Move assignment operator
|
||||
|
||||
explicit EventManager(Application &appManager); // Constructor
|
||||
|
||||
void SetGlobalEventHandler(const GlobalEventHandler &globalEventHandler); // Set the global event handler function
|
||||
|
||||
PollingResult ProcessEvents() const; // Poll and process SDL events
|
||||
|
||||
protected:
|
||||
Application &m_appManager; // Reference to the Application instance
|
||||
|
||||
GlobalEventHandler m_globalEventHandler; // Global event handler function
|
||||
};
|
||||
//--------------------------------------------------------------
|
||||
} // namespace quokka_gfx
|
||||
232
quokka_gfx/quokka_gfx/Input/InputManager.cpp
Normal file
232
quokka_gfx/quokka_gfx/Input/InputManager.cpp
Normal file
@@ -0,0 +1,232 @@
|
||||
#include "InputManager.h"
|
||||
|
||||
#include <ranges>
|
||||
|
||||
using namespace std;
|
||||
using namespace quokka_gfx;
|
||||
//--------------------------------------------------------------
|
||||
/* Check if a key is being held down */
|
||||
bool InputManager::isKeyDown(const SDL_Scancode code) const
|
||||
{
|
||||
if (!m_currentKeys.contains(code))
|
||||
return false;
|
||||
return m_currentKeys.at(code);
|
||||
}
|
||||
//--------------------------------------------------------------
|
||||
/* Check if a key is pressed (transition from up to down on this frame) */
|
||||
bool InputManager::isKeyPressed(const SDL_Scancode code) const
|
||||
{
|
||||
if (!isKeyDown(code))
|
||||
return false;
|
||||
|
||||
if (!m_previousKeys.contains(code))
|
||||
return true;
|
||||
|
||||
return !m_previousKeys.at(code);
|
||||
}
|
||||
//--------------------------------------------------------------
|
||||
/* Check if a key is released (transition from down to up on this frame) */
|
||||
bool InputManager::isKeyReleased(const SDL_Scancode code) const
|
||||
{
|
||||
if (isKeyDown(code))
|
||||
return false;
|
||||
|
||||
if (!m_previousKeys.contains(code))
|
||||
return false;
|
||||
|
||||
return m_previousKeys.at(code);
|
||||
}
|
||||
//--------------------------------------------------------------
|
||||
/* Get a list of keys that are currently being held down */
|
||||
void InputManager::getHoldingKeys(KeyList &keyList) const
|
||||
{
|
||||
keyList.clear();
|
||||
|
||||
// Create a view of the keys that are currently held down
|
||||
auto holdingView = m_currentKeys | views::filter([](const auto &pair)
|
||||
{ return pair.second; }) |
|
||||
views::keys;
|
||||
|
||||
// Copy the keys from the view to the keyList
|
||||
ranges::copy(holdingView, back_inserter(keyList));
|
||||
}
|
||||
//--------------------------------------------------------------
|
||||
/* Get a list of keys that were pressed in the current frame */
|
||||
void InputManager::getPressedKeys(KeyList &keyList) const
|
||||
{
|
||||
keyList.clear();
|
||||
|
||||
auto pressedView = m_currentKeys | views::filter([this](const auto &pair)
|
||||
{
|
||||
const auto& [scancode, isDown] = pair;
|
||||
if (!isDown)
|
||||
return false;
|
||||
|
||||
auto it = m_previousKeys.find(scancode);
|
||||
const bool wasDown = (it != m_previousKeys.end()) ? it->second : false;
|
||||
return !wasDown; }) |
|
||||
views::keys;
|
||||
|
||||
ranges::copy(pressedView, back_inserter(keyList));
|
||||
}
|
||||
//--------------------------------------------------------------
|
||||
/* Get a list of keys that were released in the current frame */
|
||||
void InputManager::getReleasedKeys(KeyList &keyList) const
|
||||
{
|
||||
keyList.clear();
|
||||
|
||||
auto releasedView = m_previousKeys | std::views::filter([this](const auto &pair)
|
||||
{
|
||||
const auto& [scancode, wasDown] = pair;
|
||||
if (!wasDown)
|
||||
return false;
|
||||
|
||||
auto it = m_currentKeys.find(scancode);
|
||||
const bool isDown = (it != m_currentKeys.end()) ? it->second : false;
|
||||
return !isDown; }) |
|
||||
std::views::keys;
|
||||
|
||||
std::ranges::copy(releasedView, back_inserter(keyList));
|
||||
}
|
||||
//--------------------------------------------------------------
|
||||
/* Get the current mouse position */
|
||||
FPos InputManager::getMousePosition() const
|
||||
{
|
||||
return m_mousePosition;
|
||||
}
|
||||
//--------------------------------------------------------------
|
||||
/* Check if a mouse button is being held down */
|
||||
bool InputManager::isMouseButtonDown(const MouseButton button) const
|
||||
{
|
||||
const auto it = m_currentMouseButtons.find(button);
|
||||
return (it != m_currentMouseButtons.end()) ? it->second : false;
|
||||
}
|
||||
//--------------------------------------------------------------
|
||||
/* Check if a mouse button is pressed (transition from up to down on this frame) */
|
||||
bool InputManager::isMouseButtonPressed(const MouseButton button) const
|
||||
{
|
||||
if (!isMouseButtonDown(button))
|
||||
return false;
|
||||
|
||||
if (!m_previousMouseButtons.contains(button))
|
||||
return true;
|
||||
|
||||
return !m_previousMouseButtons.at(button);
|
||||
}
|
||||
//--------------------------------------------------------------
|
||||
/* Check if a mouse button is released (transition from down to up on this frame) */
|
||||
bool InputManager::isMouseButtonReleased(const MouseButton button) const
|
||||
{
|
||||
if (isMouseButtonDown(button))
|
||||
return false;
|
||||
|
||||
if (!m_previousMouseButtons.contains(button))
|
||||
return false;
|
||||
|
||||
return m_previousMouseButtons.at(button);
|
||||
}
|
||||
//--------------------------------------------------------------
|
||||
/* Check if the mouse wheel has been scrolled in the current frame */
|
||||
bool InputManager::isMouseWheeling() const
|
||||
{
|
||||
return (m_wheelX != 0.0f || m_wheelY != 0.0f);
|
||||
}
|
||||
//--------------------------------------------------------------
|
||||
/* Get the mouse wheel delta for horizontal scrolling */
|
||||
float InputManager::getMouseWheelX() const
|
||||
{
|
||||
return m_wheelX;
|
||||
}
|
||||
//--------------------------------------------------------------
|
||||
/* Get the mouse wheel delta for vertical scrolling */
|
||||
float InputManager::getMouseWheelY() const
|
||||
{
|
||||
return m_wheelY;
|
||||
}
|
||||
//--------------------------------------------------------------
|
||||
/* Get the ID of the window currently focused for keyboard input */
|
||||
uint32_t InputManager::getFocusedWindowID() const
|
||||
{
|
||||
return m_focusedWindowID;
|
||||
}
|
||||
//--------------------------------------------------------------
|
||||
/* Get the ID of the window currently hovered by the mouse */
|
||||
uint32_t InputManager::getHoveredWindowID() const
|
||||
{
|
||||
return m_hoveredWindowID;
|
||||
}
|
||||
//--------------------------------------------------------------
|
||||
/* Update the input states (to be called each frame) */
|
||||
void InputManager::updateStates()
|
||||
{
|
||||
// Clear the mouse wheel delta for the current frame
|
||||
clearWheelDelta();
|
||||
|
||||
// Update the previous key states to the current key states for the next frame
|
||||
m_previousKeys = m_currentKeys;
|
||||
|
||||
// Update the previous mouse button states to the current mouse button states for the next frame
|
||||
m_previousMouseButtons = m_currentMouseButtons;
|
||||
}
|
||||
//--------------------------------------------------------------
|
||||
/* Process an SDL event to update input states */
|
||||
void InputManager::processEvent(const SDL_Event &event)
|
||||
{
|
||||
// Process events
|
||||
if (event.type == SDL_EVENT_WINDOW_FOCUS_GAINED)
|
||||
{
|
||||
m_focusedWindowID = event.window.windowID;
|
||||
}
|
||||
if (event.type == SDL_EVENT_WINDOW_FOCUS_LOST)
|
||||
{
|
||||
if (m_focusedWindowID == event.window.windowID)
|
||||
m_focusedWindowID = 0;
|
||||
}
|
||||
else if (event.type == SDL_EVENT_WINDOW_MOUSE_ENTER)
|
||||
{
|
||||
m_hoveredWindowID = event.window.windowID;
|
||||
}
|
||||
else if (event.type == SDL_EVENT_WINDOW_MOUSE_LEAVE)
|
||||
{
|
||||
m_hoveredWindowID = 0;
|
||||
}
|
||||
else if (event.type == SDL_EVENT_KEY_DOWN)
|
||||
{
|
||||
m_currentKeys[event.key.scancode] = true;
|
||||
}
|
||||
else if (event.type == SDL_EVENT_KEY_UP)
|
||||
{
|
||||
m_currentKeys[event.key.scancode] = false;
|
||||
}
|
||||
else if (event.type == SDL_EVENT_MOUSE_MOTION)
|
||||
{
|
||||
m_mousePosition = { .x = event.motion.x, .y = event.motion.y };
|
||||
}
|
||||
else if (event.type == SDL_EVENT_MOUSE_BUTTON_DOWN)
|
||||
{
|
||||
m_currentMouseButtons[static_cast<MouseButton>(event.button.button)] = true;
|
||||
}
|
||||
else if (event.type == SDL_EVENT_MOUSE_BUTTON_UP)
|
||||
{
|
||||
m_currentMouseButtons[static_cast<MouseButton>(event.button.button)] = false;
|
||||
}
|
||||
else if (event.type == SDL_EVENT_MOUSE_WHEEL)
|
||||
{
|
||||
processWheelEvent(event.wheel);
|
||||
}
|
||||
}
|
||||
//--------------------------------------------------------------
|
||||
/* Clear the mouse wheel delta */
|
||||
void InputManager::clearWheelDelta()
|
||||
{
|
||||
m_wheelX = 0.0f;
|
||||
m_wheelY = 0.0f;
|
||||
}
|
||||
//--------------------------------------------------------------
|
||||
/* Process a mouse wheel event to update the wheel delta */
|
||||
void InputManager::processWheelEvent(const SDL_MouseWheelEvent &event)
|
||||
{
|
||||
m_wheelX = event.x; // Positive value for scrolling right, negative for scrolling left
|
||||
m_wheelY = event.y; // Positive value for scrolling up, negative for scrolling down
|
||||
}
|
||||
//--------------------------------------------------------------
|
||||
82
quokka_gfx/quokka_gfx/Input/InputManager.h
Normal file
82
quokka_gfx/quokka_gfx/Input/InputManager.h
Normal file
@@ -0,0 +1,82 @@
|
||||
#pragma once
|
||||
|
||||
#include "utils/Coords.h"
|
||||
|
||||
#include <SDL3/SDL.h>
|
||||
#include <unordered_map>
|
||||
#include <vector>
|
||||
|
||||
namespace quokka_gfx
|
||||
{
|
||||
//--------------------------------------------------------------
|
||||
class InputManager
|
||||
{
|
||||
friend class WindowManager;
|
||||
friend class Window;
|
||||
friend class EventManager;
|
||||
|
||||
public:
|
||||
enum class MouseButton : uint8_t
|
||||
{
|
||||
Left = SDL_BUTTON_LEFT, // Left mouse button
|
||||
Middle = SDL_BUTTON_MIDDLE, // Middle mouse button
|
||||
Right = SDL_BUTTON_RIGHT, // Right mouse button
|
||||
X1 = SDL_BUTTON_X1, // Extra mouse button 1
|
||||
X2 = SDL_BUTTON_X2 // Extra mouse button 2
|
||||
};
|
||||
|
||||
using KeyList = std::vector<SDL_Scancode>; // List of SDL scancodes representing keys
|
||||
|
||||
public:
|
||||
InputManager() = default; // Default constructor
|
||||
virtual ~InputManager() = default; // Default destructor
|
||||
InputManager(const InputManager &obj) = delete; // Copy constructor
|
||||
InputManager(InputManager &&obj) noexcept = delete; // Move constructor
|
||||
InputManager &operator=(const InputManager &obj) = delete; // Copy assignment operator
|
||||
InputManager &operator=(InputManager &&obj) noexcept = delete; // Move assignment operator
|
||||
|
||||
// Key state query functions
|
||||
[[nodiscard]] bool isKeyDown(SDL_Scancode code) const; // Check if a key is being held down
|
||||
[[nodiscard]] bool isKeyPressed(SDL_Scancode code) const; // Check if a key is pressed (transition from up to down on this frame)
|
||||
[[nodiscard]] bool isKeyReleased(SDL_Scancode code) const; // Check if a key is released (transition from down to up on this frame)
|
||||
void getHoldingKeys(KeyList &keyList) const; // Get a list of keys that are currently being held down
|
||||
void getPressedKeys(KeyList &keyList) const; // Get a list of keys that were pressed in the current frame
|
||||
void getReleasedKeys(KeyList &keyList) const; // Get a list of keys that were released in the current frame
|
||||
|
||||
// Mouse state query functions
|
||||
[[nodiscard]] FPos getMousePosition() const; // Get the current mouse position
|
||||
[[nodiscard]] bool isMouseButtonDown(MouseButton button) const; // Check if a mouse button is being held down
|
||||
[[nodiscard]] bool isMouseButtonPressed(MouseButton button) const; // Check if a mouse button is pressed (transition from up to down on this frame)
|
||||
[[nodiscard]] bool isMouseButtonReleased(MouseButton button) const; // Check if a mouse button is released (transition from down to up on this frame)
|
||||
|
||||
[[nodiscard]] bool isMouseWheeling() const; // Check if the mouse wheel has been scrolled in the current frame
|
||||
[[nodiscard]] float getMouseWheelX() const; // Get the mouse wheel delta for horizontal scrolling
|
||||
[[nodiscard]] float getMouseWheelY() const; // Get the mouse wheel delta for vertical scrolling
|
||||
|
||||
// Window state query functions
|
||||
[[nodiscard]] uint32_t getFocusedWindowID() const; // Get the ID of the window currently focused for keyboard input
|
||||
[[nodiscard]] uint32_t getHoveredWindowID() const; // Get the ID of the window currently hovered by the mouse
|
||||
|
||||
protected:
|
||||
void updateStates(); // Update the input states (to be called each frame)
|
||||
void processEvent(const SDL_Event &event); // Process an SDL event to update input states
|
||||
|
||||
// States
|
||||
std::unordered_map<SDL_Scancode, bool> m_currentKeys;
|
||||
std::unordered_map<SDL_Scancode, bool> m_previousKeys;
|
||||
uint32_t m_focusedWindowID = 0; // Keyboard focus window ID
|
||||
|
||||
std::unordered_map<MouseButton, bool> m_currentMouseButtons;
|
||||
std::unordered_map<MouseButton, bool> m_previousMouseButtons;
|
||||
FPos m_mousePosition;
|
||||
uint32_t m_hoveredWindowID = 0; // Mouse hover window ID
|
||||
|
||||
float m_wheelX = 0.0f; // Mouse wheel delta for horizontal scrolling
|
||||
float m_wheelY = 0.0f; // Mouse wheel delta for vertical scrolling
|
||||
|
||||
private:
|
||||
void clearWheelDelta(); // Clear the mouse wheel delta
|
||||
void processWheelEvent(const SDL_MouseWheelEvent &event); // Process a mouse wheel event to update the wheel delta
|
||||
};
|
||||
//--------------------------------------------------------------
|
||||
} // namespace quokka_gfx
|
||||
75
quokka_gfx/quokka_gfx/Renderer/Renderer.cpp
Normal file
75
quokka_gfx/quokka_gfx/Renderer/Renderer.cpp
Normal file
@@ -0,0 +1,75 @@
|
||||
#include "Renderer.h"
|
||||
|
||||
#include "../Window/Window.h"
|
||||
|
||||
#include <stdexcept>
|
||||
|
||||
using namespace std;
|
||||
using namespace quokka_gfx;
|
||||
//--------------------------------------------------------------
|
||||
/* Constructor */
|
||||
Renderer::Renderer(const Window &window)
|
||||
: m_owner(window)
|
||||
{
|
||||
// Create the native SDL renderer associated with the window
|
||||
m_nativeRenderer = SDL_CreateRenderer(m_owner.GetNativeWindow(), nullptr);
|
||||
|
||||
if (!m_nativeRenderer)
|
||||
{
|
||||
throw std::runtime_error("Failed to create SDL renderer: " + std::string(SDL_GetError()));
|
||||
}
|
||||
|
||||
// Enable VSync for the renderer to synchronize rendering with the display's refresh rate
|
||||
SDL_SetRenderVSync(m_nativeRenderer, 1);
|
||||
}
|
||||
//--------------------------------------------------------------
|
||||
/* Default destructor */
|
||||
Renderer::~Renderer()
|
||||
{
|
||||
if (m_nativeRenderer)
|
||||
SDL_DestroyRenderer(m_nativeRenderer);
|
||||
}
|
||||
//--------------------------------------------------------------
|
||||
/* Get the native SDL renderer */
|
||||
SDL_Renderer *Renderer::getNativeRenderer() const noexcept
|
||||
{
|
||||
return m_nativeRenderer;
|
||||
}
|
||||
//--------------------------------------------------------------
|
||||
/* Clear the rendering target */
|
||||
void Renderer::clear() const
|
||||
{
|
||||
SDL_RenderClear(m_nativeRenderer);
|
||||
}
|
||||
//--------------------------------------------------------------
|
||||
/* Present the rendered content to the window */
|
||||
void Renderer::present() const
|
||||
{
|
||||
SDL_RenderPresent(m_nativeRenderer);
|
||||
}
|
||||
//--------------------------------------------------------------
|
||||
void Renderer::setDrawColor(const Color &color) const
|
||||
{
|
||||
SDL_SetRenderDrawColor(m_nativeRenderer, color.r, color.g, color.b, color.a);
|
||||
}
|
||||
//--------------------------------------------------------------
|
||||
/* Draw a line */
|
||||
void Renderer::drawLine(const FPos &start, const FPos &end) const
|
||||
{
|
||||
SDL_RenderLine(m_nativeRenderer, start.x, start.y, end.x, end.y);
|
||||
}
|
||||
//--------------------------------------------------------------
|
||||
/* Draw a rectangle outline */
|
||||
void Renderer::drawRect(const FPos &start, const FSize &size) const
|
||||
{
|
||||
const SDL_FRect rect{ start.x, start.y, size.w, size.h };
|
||||
SDL_RenderRect(m_nativeRenderer, &rect);
|
||||
}
|
||||
//--------------------------------------------------------------
|
||||
/* Draw a filled rectangle */
|
||||
void Renderer::fillRect(const FPos &start, const FSize &size) const
|
||||
{
|
||||
const SDL_FRect rect{ start.x, start.y, size.w, size.h };
|
||||
SDL_RenderFillRect(m_nativeRenderer, &rect);
|
||||
}
|
||||
//--------------------------------------------------------------
|
||||
49
quokka_gfx/quokka_gfx/Renderer/Renderer.h
Normal file
49
quokka_gfx/quokka_gfx/Renderer/Renderer.h
Normal file
@@ -0,0 +1,49 @@
|
||||
#pragma once
|
||||
|
||||
#include "utils/Colors.h"
|
||||
#include "utils/Coords.h"
|
||||
|
||||
#include <SDL3/SDL.h>
|
||||
#include <memory>
|
||||
|
||||
namespace quokka_gfx
|
||||
{
|
||||
class Window;
|
||||
//--------------------------------------------------------------
|
||||
class Renderer
|
||||
{
|
||||
public:
|
||||
using pRenderer = std::unique_ptr<Renderer>; // Unique pointer type for Renderer
|
||||
|
||||
public:
|
||||
Renderer() = delete; // Default constructor
|
||||
virtual ~Renderer(); // Default destructor
|
||||
Renderer(const Renderer &obj) = delete; // Copy constructor
|
||||
Renderer(Renderer &&obj) noexcept = delete; // Move constructor
|
||||
Renderer &operator=(const Renderer &obj) = delete; // Copy assignment operator
|
||||
Renderer &operator=(Renderer &&obj) noexcept = delete; // Move assignment operator
|
||||
|
||||
explicit Renderer(const Window &window); // Constructor
|
||||
|
||||
// Accessors
|
||||
[[nodiscard]] SDL_Renderer *getNativeRenderer() const noexcept; // Get the native SDL renderer
|
||||
|
||||
// Rendering cycle functions
|
||||
void clear() const; // Clear the rendering target
|
||||
void present() const; // Present the rendered content to the window
|
||||
|
||||
// Setting functions
|
||||
void setDrawColor(const Color &color) const; // Set the drawing color (default to white)
|
||||
|
||||
// Drawing functions
|
||||
void drawLine(const FPos &start, const FPos &end) const; // Draw a line
|
||||
void drawRect(const FPos &start, const FSize &size) const; // Draw a rectangle outline
|
||||
void fillRect(const FPos &start, const FSize &size) const; // Draw a filled rectangle
|
||||
|
||||
protected:
|
||||
const Window &m_owner; // Reference to the owner window
|
||||
|
||||
SDL_Renderer *m_nativeRenderer = nullptr; // Native SDL renderer pointer
|
||||
};
|
||||
//--------------------------------------------------------------
|
||||
} // namespace quokka_gfx
|
||||
52
quokka_gfx/quokka_gfx/SDLContext.h
Normal file
52
quokka_gfx/quokka_gfx/SDLContext.h
Normal file
@@ -0,0 +1,52 @@
|
||||
#pragma once
|
||||
|
||||
#include <SDL3/SDL.h>
|
||||
#include <memory>
|
||||
#include <stdexcept>
|
||||
|
||||
namespace quokka_gfx
|
||||
{
|
||||
//--------------------------------------------------------------
|
||||
class SDLContext
|
||||
{
|
||||
public:
|
||||
using pContext = std::shared_ptr<SDLContext>; // Shared pointer type for SDLContext
|
||||
static pContext GetContext(); // Get (create if necessary) the static singleton instance of SDLContext
|
||||
|
||||
public:
|
||||
virtual ~SDLContext(); // Default destructor
|
||||
SDLContext(const SDLContext &obj) = default; // Copy constructor
|
||||
SDLContext(SDLContext &&obj) noexcept = default; // Move constructor
|
||||
SDLContext &operator=(const SDLContext &obj) = default; // Copy assignment operator
|
||||
SDLContext &operator=(SDLContext &&obj) noexcept = default; // Move assignment operator
|
||||
|
||||
protected:
|
||||
SDLContext(); // Default constructor
|
||||
static inline pContext m_singleton = nullptr; // Shared pointer to the singleton instance of SDLContext
|
||||
};
|
||||
//--------------------------------------------------------------
|
||||
/* Get (create if necessary) the static singleton instance of SDLContext */
|
||||
inline SDLContext::pContext SDLContext::GetContext()
|
||||
{
|
||||
if (!m_singleton)
|
||||
m_singleton = pContext(new SDLContext());
|
||||
|
||||
return m_singleton;
|
||||
}
|
||||
//--------------------------------------------------------------
|
||||
/* Default constructor */
|
||||
inline SDLContext::SDLContext()
|
||||
{
|
||||
// Initialize SDL with audio, video, and events subsystems
|
||||
if (!SDL_Init(SDL_INIT_AUDIO | SDL_INIT_VIDEO | SDL_INIT_EVENTS))
|
||||
throw std::runtime_error(SDL_GetError());
|
||||
}
|
||||
//--------------------------------------------------------------
|
||||
/* Default destructor */
|
||||
inline SDLContext::~SDLContext()
|
||||
{
|
||||
// Quit SDL subsystems
|
||||
SDL_Quit();
|
||||
}
|
||||
//--------------------------------------------------------------
|
||||
} // namespace quokka_gfx
|
||||
114
quokka_gfx/quokka_gfx/Window/Window.cpp
Normal file
114
quokka_gfx/quokka_gfx/Window/Window.cpp
Normal file
@@ -0,0 +1,114 @@
|
||||
#include "Window.h"
|
||||
|
||||
#include "../Application.h"
|
||||
|
||||
#include <stdexcept>
|
||||
|
||||
using namespace std;
|
||||
using namespace quokka_gfx;
|
||||
//--------------------------------------------------------------
|
||||
/* Constructor */
|
||||
Window::Window(Application &app, const std::string &title, const Size &size, const uint64_t flags)
|
||||
: m_appOwner(app)
|
||||
{
|
||||
// Create the native SDL window with the specified title, size, and flags
|
||||
m_nativeWindow = SDL_CreateWindow(
|
||||
title.data(), // Window title
|
||||
size.w, // Window w
|
||||
size.h, // Window h
|
||||
SDL_WINDOW_HIGH_PIXEL_DENSITY | SDL_WINDOW_HIDDEN | flags // Window flags: High pixel density for better rendering on high-DPI displays
|
||||
);
|
||||
if (!m_nativeWindow)
|
||||
throw runtime_error("Failed to create SDL window: " + string(SDL_GetError()));
|
||||
|
||||
// Create the renderer instance associated with this window
|
||||
m_renderer = make_unique<Renderer>(*this);
|
||||
|
||||
// Register the window with the application's WindowManager
|
||||
m_appOwner.GetWindowManager()->RegisterWindow(this);
|
||||
}
|
||||
//--------------------------------------------------------------
|
||||
/* Default destructor */
|
||||
Window::~Window()
|
||||
{
|
||||
if (m_nativeWindow)
|
||||
SDL_DestroyWindow(m_nativeWindow);
|
||||
}
|
||||
//--------------------------------------------------------------
|
||||
/* Get the native SDL window */
|
||||
SDL_Window *Window::GetNativeWindow() const noexcept
|
||||
{
|
||||
return m_nativeWindow;
|
||||
}
|
||||
//--------------------------------------------------------------
|
||||
/* Get the renderer instance */
|
||||
const Renderer *Window::GetRenderer() const noexcept
|
||||
{
|
||||
return m_renderer.get();
|
||||
}
|
||||
//--------------------------------------------------------------
|
||||
/* Get the InputManager instance */
|
||||
const InputManager *Window::GetInputManager() const noexcept
|
||||
{
|
||||
return &m_appOwner.m_inputManager;
|
||||
}
|
||||
//--------------------------------------------------------------
|
||||
/* Show or hide the window */
|
||||
void Window::Show(const bool show) const
|
||||
{
|
||||
if (show)
|
||||
SDL_ShowWindow(m_nativeWindow);
|
||||
else
|
||||
SDL_HideWindow(m_nativeWindow);
|
||||
}
|
||||
//--------------------------------------------------------------
|
||||
/* Hide the window */
|
||||
void Window::Hide() const
|
||||
{
|
||||
Show(false);
|
||||
}
|
||||
//--------------------------------------------------------------
|
||||
/* Close the window */
|
||||
void Window::Close()
|
||||
{
|
||||
m_appOwner.GetWindowManager()->CloseWindow(this);
|
||||
}
|
||||
//--------------------------------------------------------------
|
||||
/* Set the minimum size of the window */
|
||||
void Window::SetMinSize(const Size &size) const
|
||||
{
|
||||
SDL_SetWindowMinimumSize(m_nativeWindow, size.w, size.h);
|
||||
}
|
||||
//--------------------------------------------------------------
|
||||
/* Handle event */
|
||||
void Window::OnEvent(SDL_Event *event) {}
|
||||
//--------------------------------------------------------------
|
||||
/* Update the window state */
|
||||
void Window::Update(const float dt)
|
||||
{
|
||||
// Nothing to do
|
||||
}
|
||||
//--------------------------------------------------------------
|
||||
/* Draw the window content (returns true if the window content was drawn, false otherwise) */
|
||||
bool Window::Draw()
|
||||
{
|
||||
return false;
|
||||
}
|
||||
//--------------------------------------------------------------
|
||||
/* Render the window */
|
||||
void Window::Render()
|
||||
{
|
||||
if (!m_renderer)
|
||||
return;
|
||||
|
||||
// Set the drawing color to black and clear the rendering target
|
||||
(void)m_renderer->setDrawColor(Color::Black);
|
||||
(void)m_renderer->clear();
|
||||
|
||||
// Draw the window content
|
||||
Draw();
|
||||
|
||||
// Present the rendered content to the window (swap the back buffer to the front)
|
||||
m_renderer->present();
|
||||
}
|
||||
//--------------------------------------------------------------
|
||||
60
quokka_gfx/quokka_gfx/Window/Window.h
Normal file
60
quokka_gfx/quokka_gfx/Window/Window.h
Normal file
@@ -0,0 +1,60 @@
|
||||
#pragma once
|
||||
|
||||
#include "../Input/InputManager.h"
|
||||
#include "../Renderer/Renderer.h"
|
||||
#include "utils/Coords.h"
|
||||
|
||||
#include <SDL3/SDL.h>
|
||||
#include <memory>
|
||||
#include <string>
|
||||
|
||||
namespace quokka_gfx
|
||||
{
|
||||
class Application; // Forward declaration of the Application class
|
||||
//--------------------------------------------------------------
|
||||
class Window
|
||||
{
|
||||
friend class WindowManager;
|
||||
|
||||
public:
|
||||
using pWindow = std::unique_ptr<Window>; // Unique pointer type for Window
|
||||
|
||||
public:
|
||||
Window() = delete; // Default constructor
|
||||
virtual ~Window(); // Default destructor
|
||||
Window(const Window &obj) = delete; // Copy constructor
|
||||
Window(Window &&obj) noexcept = default; // Move constructor
|
||||
Window &operator=(const Window &obj) = delete; // Copy assignment operator
|
||||
Window &operator=(Window &&obj) noexcept = delete; // Move assignment operator
|
||||
|
||||
explicit Window(Application &app, // Constructor
|
||||
const std::string &title,
|
||||
const Size &size,
|
||||
uint64_t flags);
|
||||
|
||||
// Accessors
|
||||
[[nodiscard]] SDL_Window *GetNativeWindow() const noexcept; // Get the native SDL window
|
||||
[[nodiscard]] const Renderer *GetRenderer() const noexcept; // Get the renderer instance
|
||||
[[nodiscard]] const InputManager *GetInputManager() const noexcept; // Get the InputManager instance
|
||||
|
||||
// Show or hide the window
|
||||
void Show(bool show = true) const; // Show or hide the window
|
||||
void Hide() const; // Hide the window
|
||||
|
||||
void Close(); // Close the window
|
||||
void SetMinSize(const Size &size) const; // Set the minimum size of the window
|
||||
|
||||
// Window lifecycle functions
|
||||
virtual void OnEvent(SDL_Event *event); // Handle event
|
||||
virtual void Update(float dt); // Update the window state
|
||||
virtual bool Draw(); // Draw the window content
|
||||
void Render(); // Render the window
|
||||
|
||||
protected:
|
||||
Application &m_appOwner; // Reference to the owning Application instance
|
||||
SDL_Window *m_nativeWindow = nullptr; // Native SDL window pointer
|
||||
|
||||
Renderer::pRenderer m_renderer; // Renderer instance for this window
|
||||
};
|
||||
//--------------------------------------------------------------
|
||||
} // namespace quokka_gfx
|
||||
80
quokka_gfx/quokka_gfx/Window/WindowManager.cpp
Normal file
80
quokka_gfx/quokka_gfx/Window/WindowManager.cpp
Normal file
@@ -0,0 +1,80 @@
|
||||
#include "WindowManager.h"
|
||||
|
||||
#include "../Application.h"
|
||||
|
||||
using namespace std;
|
||||
using namespace quokka_gfx;
|
||||
//--------------------------------------------------------------
|
||||
/* Register an existing window with the WindowManager */
|
||||
void WindowManager::RegisterWindow(Window *window)
|
||||
{
|
||||
if (m_windows.empty())
|
||||
window->m_appOwner.m_inputManager.m_focusedWindowID = SDL_GetWindowID(window->GetNativeWindow());
|
||||
|
||||
m_windows.push_back(window);
|
||||
}
|
||||
//--------------------------------------------------------------
|
||||
/* Close a window by its SDL window ID */
|
||||
void WindowManager::CloseWindow(uint32_t windowId)
|
||||
{
|
||||
const auto it = ranges::find_if(m_windows, [windowId](const auto &win)
|
||||
{ return SDL_GetWindowID(win->GetNativeWindow()) == windowId; });
|
||||
if (it != m_windows.end())
|
||||
{
|
||||
delete *it; // Delete the window instance
|
||||
m_windows.erase(it); // Remove the window from the vector
|
||||
}
|
||||
}
|
||||
//--------------------------------------------------------------
|
||||
/* Close a window by its pointer */
|
||||
void WindowManager::CloseWindow(Window *window)
|
||||
{
|
||||
const auto it = ranges::find_if(m_windows, [window](const auto &win)
|
||||
{ return win == window; });
|
||||
if (it != m_windows.end())
|
||||
{
|
||||
delete *it; // Delete the window instance
|
||||
m_windows.erase(it); // Remove the window from the vector
|
||||
}
|
||||
}
|
||||
//--------------------------------------------------------------
|
||||
/* Get the vector of windows instances */
|
||||
const WindowManager::WindowList &WindowManager::GetWindows() const noexcept
|
||||
{
|
||||
return m_windows;
|
||||
}
|
||||
//--------------------------------------------------------------
|
||||
/* Check if there are any windows managed by the WindowManager */
|
||||
bool WindowManager::HasAnyWindow() const noexcept
|
||||
{
|
||||
return !m_windows.empty();
|
||||
}
|
||||
//--------------------------------------------------------------
|
||||
/* Handle event for all windows */
|
||||
void WindowManager::OnEvent(SDL_Event *event)
|
||||
{
|
||||
// Handle window close events
|
||||
if (event->type == SDL_EVENT_WINDOW_CLOSE_REQUESTED)
|
||||
CloseWindow(event->window.windowID);
|
||||
|
||||
// Propagate the event to all registered windows
|
||||
for (const auto &window : m_windows)
|
||||
window->OnEvent(event);
|
||||
}
|
||||
//--------------------------------------------------------------
|
||||
/* Update all windows */
|
||||
void WindowManager::Update(const float dt) const
|
||||
{
|
||||
// Propagate the Update call to all registered windows
|
||||
for (const auto &window : m_windows)
|
||||
window->Update(dt);
|
||||
}
|
||||
//--------------------------------------------------------------
|
||||
/* Render all windows */
|
||||
void WindowManager::Render() const
|
||||
{
|
||||
// Propagate the Render call to all registered windows
|
||||
for (const auto &window : m_windows)
|
||||
window->Render();
|
||||
}
|
||||
//--------------------------------------------------------------
|
||||
41
quokka_gfx/quokka_gfx/Window/WindowManager.h
Normal file
41
quokka_gfx/quokka_gfx/Window/WindowManager.h
Normal file
@@ -0,0 +1,41 @@
|
||||
#pragma once
|
||||
#include "../Window/Window.h"
|
||||
|
||||
#include <SDL3/SDL.h>
|
||||
#include <vector>
|
||||
|
||||
namespace quokka_gfx
|
||||
{
|
||||
//--------------------------------------------------------------
|
||||
class WindowManager
|
||||
{
|
||||
friend class Application;
|
||||
friend class EventManager;
|
||||
|
||||
public:
|
||||
using WindowList = std::vector<Window *>; // Vector to store pointers to Window instances
|
||||
|
||||
public:
|
||||
WindowManager() = default; // Default constructor
|
||||
virtual ~WindowManager() = default; // Default destructor
|
||||
WindowManager(const WindowManager &obj) = delete; // Copy constructor
|
||||
WindowManager(WindowManager &&obj) noexcept = delete; // Move constructor
|
||||
WindowManager &operator=(const WindowManager &obj) = delete; // Copy assignment operator
|
||||
WindowManager &operator=(WindowManager &&obj) noexcept = delete; // Move assignment operator
|
||||
|
||||
void RegisterWindow(Window *window); // Register an existing window with the WindowManager
|
||||
void CloseWindow(uint32_t windowId); // Close a window by its SDL window ID
|
||||
void CloseWindow(Window *window); // Close a window by its pointer
|
||||
|
||||
[[nodiscard]] const WindowList &GetWindows() const noexcept; // Get the vector of windows instances
|
||||
[[nodiscard]] bool HasAnyWindow() const noexcept; // Check if there are any windows managed by the WindowManager
|
||||
|
||||
protected:
|
||||
WindowList m_windows; // Vector to store unique pointers to windows
|
||||
|
||||
void OnEvent(SDL_Event *event); // Handle event for all windows
|
||||
void Update(float dt) const; // Update all windows
|
||||
void Render() const; // Render all windows
|
||||
};
|
||||
//--------------------------------------------------------------
|
||||
} // namespace quokka_gfx
|
||||
68
quokka_gfx/utils/Colors.cpp
Normal file
68
quokka_gfx/utils/Colors.cpp
Normal file
@@ -0,0 +1,68 @@
|
||||
#include "Colors.h"
|
||||
|
||||
using namespace quokka_gfx;
|
||||
//--------------------------------------------------------------
|
||||
const Color Color::Black{ 0, 0, 0, 255 };
|
||||
const Color Color::White{ 255, 255, 255, 255 };
|
||||
const Color Color::Red{ 255, 0, 0, 255 };
|
||||
const Color Color::Green{ 0, 255, 0, 255 };
|
||||
const Color Color::Blue{ 0, 0, 255, 255 };
|
||||
const Color Color::Yellow{ 255, 255, 0, 255 };
|
||||
const Color Color::Magenta{ 255, 0, 255, 255 };
|
||||
const Color Color::Cyan{ 0, 255, 255, 255 };
|
||||
const Color Color::Transparent{ 0, 0, 0, 0 };
|
||||
//--------------------------------------------------------------
|
||||
/* Constructor */
|
||||
constexpr Color::Color(const uint8_t red, const uint8_t green, const uint8_t blue, const uint8_t alpha)
|
||||
: r(red)
|
||||
, g(green)
|
||||
, b(blue)
|
||||
, a(alpha)
|
||||
{
|
||||
}
|
||||
//--------------------------------------------------------------
|
||||
/* Constructor */
|
||||
constexpr Color::Color(const uint32_t hexColor)
|
||||
: r((hexColor >> 16) & 0xFF)
|
||||
, g((hexColor >> 8) & 0xFF)
|
||||
, b(hexColor & 0xFF)
|
||||
, a((hexColor >> 24) & 0xFF ? (hexColor >> 24) & 0xFF : 255)
|
||||
{
|
||||
}
|
||||
//--------------------------------------------------------------
|
||||
/* Convert Color to SDL_Color */
|
||||
constexpr Color::operator SDL_Color() const
|
||||
{
|
||||
return toSDL_Color();
|
||||
}
|
||||
//--------------------------------------------------------------
|
||||
/* Convert Color to SDL_FColor */
|
||||
constexpr Color::operator SDL_FColor() const
|
||||
{
|
||||
return toSDL_FColor();
|
||||
}
|
||||
//--------------------------------------------------------------
|
||||
/* Convert Color to hex representation */
|
||||
constexpr uint32_t Color::toHex() const
|
||||
{
|
||||
return (static_cast<uint32_t>(a) << 24) |
|
||||
(static_cast<uint32_t>(r) << 16) |
|
||||
(static_cast<uint32_t>(g) << 8) |
|
||||
static_cast<uint32_t>(b);
|
||||
}
|
||||
//--------------------------------------------------------------
|
||||
/* Convert Color to SDL_Color */
|
||||
constexpr SDL_Color Color::toSDL_Color() const
|
||||
{
|
||||
return SDL_Color{ r, g, b, a };
|
||||
}
|
||||
//--------------------------------------------------------------
|
||||
/* Convert Color to SDL_FColor */
|
||||
constexpr SDL_FColor Color::toSDL_FColor() const
|
||||
{
|
||||
return SDL_FColor{ static_cast<float>(r) / 255.0f,
|
||||
static_cast<float>(g) / 255.0f,
|
||||
static_cast<float>(b) / 255.0f,
|
||||
static_cast<float>(a) / 255.0f };
|
||||
}
|
||||
//--------------------------------------------------------------
|
||||
91
quokka_gfx/utils/Colors.h
Normal file
91
quokka_gfx/utils/Colors.h
Normal file
@@ -0,0 +1,91 @@
|
||||
#pragma once
|
||||
|
||||
#include <SDL3/SDL.h>
|
||||
#include <compare>
|
||||
|
||||
namespace quokka_gfx
|
||||
{
|
||||
//--------------------------------------------------------------
|
||||
struct Color
|
||||
{
|
||||
uint8_t r = 255;
|
||||
uint8_t g = 255;
|
||||
uint8_t b = 255;
|
||||
uint8_t a = 255;
|
||||
|
||||
constexpr Color() = default; // Default Constructor
|
||||
constexpr Color(uint8_t red, uint8_t green, uint8_t blue, uint8_t alpha = 255); // Constructor
|
||||
explicit constexpr Color(uint32_t hexColor); // Constructor
|
||||
|
||||
[[nodiscard]] constexpr auto operator<=>(const Color &) const = default; // Three-way comparison operator
|
||||
[[nodiscard]] constexpr operator SDL_Color() const; // Convert Color to SDL_Color
|
||||
[[nodiscard]] constexpr operator SDL_FColor() const; // Convert Color to SDL_FColor
|
||||
|
||||
[[nodiscard]] constexpr uint32_t toHex() const; // Convert Color to hex representation
|
||||
[[nodiscard]] constexpr SDL_Color toSDL_Color() const; // Convert Color to SDL_Color
|
||||
[[nodiscard]] constexpr SDL_FColor toSDL_FColor() const; // Convert Color to SDL_FColor
|
||||
|
||||
// Predefined Colors
|
||||
static const Color Black;
|
||||
static const Color White;
|
||||
static const Color Red;
|
||||
static const Color Green;
|
||||
static const Color Blue;
|
||||
static const Color Yellow;
|
||||
static const Color Magenta;
|
||||
static const Color Cyan;
|
||||
static const Color Transparent;
|
||||
};
|
||||
//--------------------------------------------------------------
|
||||
///* Constructor */
|
||||
// inline constexpr Color::Color(const uint8_t red, const uint8_t green, const uint8_t blue, const uint8_t alpha)
|
||||
// : r(red)
|
||||
// , g(green)
|
||||
// , b(blue)
|
||||
// , a(alpha)
|
||||
//{
|
||||
// }
|
||||
////--------------------------------------------------------------
|
||||
///* Constructor */
|
||||
// inline constexpr Color::Color(const uint32_t hexColor)
|
||||
// : r((hexColor >> 16) & 0xFF)
|
||||
// , g((hexColor >> 8) & 0xFF)
|
||||
// , b(hexColor & 0xFF)
|
||||
// , a((hexColor >> 24) & 0xFF ? (hexColor >> 24) & 0xFF : 255)
|
||||
//{
|
||||
// }
|
||||
////--------------------------------------------------------------
|
||||
///* Convert Color to SDL_Color */
|
||||
// inline constexpr Color::operator SDL_Color() const
|
||||
//{
|
||||
// return toSDL_Color();
|
||||
// }
|
||||
////--------------------------------------------------------------
|
||||
///* Convert Color to SDL_FColor */
|
||||
// inline constexpr Color::operator SDL_FColor() const
|
||||
//{
|
||||
// return toSDL_FColor();
|
||||
// }
|
||||
////--------------------------------------------------------------
|
||||
///* Convert Color to hex representation */
|
||||
// inline constexpr uint32_t Color::toHex() const
|
||||
//{
|
||||
// return (static_cast<uint32_t>(a) << 24) |
|
||||
// (static_cast<uint32_t>(r) << 16) |
|
||||
// (static_cast<uint32_t>(g) << 8) |
|
||||
// static_cast<uint32_t>(b);
|
||||
// }
|
||||
////--------------------------------------------------------------
|
||||
///* Convert Color to SDL_Color */
|
||||
// inline constexpr SDL_Color Color::toSDL_Color() const
|
||||
//{
|
||||
// return SDL_Color{ r, g, b, a };
|
||||
// }
|
||||
////--------------------------------------------------------------
|
||||
///* Convert Color to SDL_FColor */
|
||||
// inline constexpr SDL_FColor Color::toSDL_FColor() const
|
||||
//{
|
||||
// return SDL_FColor{ r / 255.0f, g / 255.0f, b / 255.0f, a / 255.0f };
|
||||
// }
|
||||
//--------------------------------------------------------------
|
||||
} // namespace quokka_gfx
|
||||
32
quokka_gfx/utils/Coords.h
Normal file
32
quokka_gfx/utils/Coords.h
Normal file
@@ -0,0 +1,32 @@
|
||||
#pragma once
|
||||
|
||||
#include <SDL3/SDL.h>
|
||||
|
||||
namespace quokka_gfx
|
||||
{
|
||||
//--------------------------------------------------------------
|
||||
struct Size
|
||||
{
|
||||
int w = 0;
|
||||
int h = 0;
|
||||
};
|
||||
//--------------------------------------------------------------
|
||||
struct FSize
|
||||
{
|
||||
float w = 0.0f;
|
||||
float h = 0.0f;
|
||||
};
|
||||
//--------------------------------------------------------------
|
||||
struct Pos
|
||||
{
|
||||
int x = 0;
|
||||
int y = 0;
|
||||
};
|
||||
//--------------------------------------------------------------
|
||||
struct FPos
|
||||
{
|
||||
float x = 0.0f;
|
||||
float y = 0.0f;
|
||||
};
|
||||
//--------------------------------------------------------------
|
||||
} // namespace quokka_gfx
|
||||
Reference in New Issue
Block a user