Refactored step 1: Core Architecture Setup
This commit is contained in:
252
src/graphics/RenderManager.cpp
Normal file
252
src/graphics/RenderManager.cpp
Normal file
@ -0,0 +1,252 @@
|
||||
#include "RenderManager.h"
|
||||
#include <SDL3/SDL.h>
|
||||
#include <algorithm>
|
||||
|
||||
RenderManager::RenderManager() = default;
|
||||
|
||||
RenderManager::~RenderManager() {
|
||||
if (m_initialized) {
|
||||
shutdown();
|
||||
}
|
||||
}
|
||||
|
||||
bool RenderManager::initialize(int width, int height, const std::string& title) {
|
||||
if (m_initialized) {
|
||||
SDL_LogWarn(SDL_LOG_CATEGORY_RENDER, "RenderManager already initialized");
|
||||
return true;
|
||||
}
|
||||
|
||||
SDL_LogInfo(SDL_LOG_CATEGORY_RENDER, "Initializing RenderManager (%dx%d)", width, height);
|
||||
|
||||
// Create window
|
||||
m_window = SDL_CreateWindow(
|
||||
title.c_str(),
|
||||
width, height,
|
||||
SDL_WINDOW_RESIZABLE
|
||||
);
|
||||
|
||||
if (!m_window) {
|
||||
SDL_LogError(SDL_LOG_CATEGORY_RENDER, "Failed to create window: %s", SDL_GetError());
|
||||
return false;
|
||||
}
|
||||
|
||||
// Create renderer
|
||||
m_renderer = SDL_CreateRenderer(m_window, nullptr);
|
||||
if (!m_renderer) {
|
||||
SDL_LogError(SDL_LOG_CATEGORY_RENDER, "Failed to create renderer: %s", SDL_GetError());
|
||||
SDL_DestroyWindow(m_window);
|
||||
m_window = nullptr;
|
||||
return false;
|
||||
}
|
||||
|
||||
// Enable VSync
|
||||
SDL_SetRenderVSync(m_renderer, 1);
|
||||
|
||||
// Store window dimensions
|
||||
m_windowWidth = width;
|
||||
m_windowHeight = height;
|
||||
m_logicalWidth = width;
|
||||
m_logicalHeight = height;
|
||||
|
||||
// Set initial logical size
|
||||
setLogicalSize(width, height);
|
||||
|
||||
m_initialized = true;
|
||||
SDL_LogInfo(SDL_LOG_CATEGORY_RENDER, "RenderManager initialized successfully");
|
||||
return true;
|
||||
}
|
||||
|
||||
void RenderManager::shutdown() {
|
||||
if (!m_initialized) {
|
||||
return;
|
||||
}
|
||||
|
||||
SDL_LogInfo(SDL_LOG_CATEGORY_RENDER, "Shutting down RenderManager");
|
||||
|
||||
if (m_renderer) {
|
||||
SDL_DestroyRenderer(m_renderer);
|
||||
m_renderer = nullptr;
|
||||
}
|
||||
|
||||
if (m_window) {
|
||||
SDL_DestroyWindow(m_window);
|
||||
m_window = nullptr;
|
||||
}
|
||||
|
||||
m_initialized = false;
|
||||
SDL_LogInfo(SDL_LOG_CATEGORY_RENDER, "RenderManager shutdown complete");
|
||||
}
|
||||
|
||||
void RenderManager::beginFrame() {
|
||||
if (!m_initialized || !m_renderer) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Clear the screen
|
||||
clear(12, 12, 16, 255); // Dark background similar to original
|
||||
}
|
||||
|
||||
void RenderManager::endFrame() {
|
||||
if (!m_initialized || !m_renderer) {
|
||||
return;
|
||||
}
|
||||
|
||||
SDL_RenderPresent(m_renderer);
|
||||
}
|
||||
|
||||
void RenderManager::setLogicalSize(int width, int height) {
|
||||
if (!m_initialized || !m_renderer) {
|
||||
return;
|
||||
}
|
||||
|
||||
m_logicalWidth = width;
|
||||
m_logicalHeight = height;
|
||||
updateLogicalScale();
|
||||
}
|
||||
|
||||
void RenderManager::setViewport(int x, int y, int width, int height) {
|
||||
if (!m_initialized || !m_renderer) {
|
||||
return;
|
||||
}
|
||||
|
||||
SDL_Rect viewport = { x, y, width, height };
|
||||
SDL_SetRenderViewport(m_renderer, &viewport);
|
||||
}
|
||||
|
||||
void RenderManager::setScale(float scaleX, float scaleY) {
|
||||
if (!m_initialized || !m_renderer) {
|
||||
return;
|
||||
}
|
||||
|
||||
m_scaleX = scaleX;
|
||||
m_scaleY = scaleY;
|
||||
SDL_SetRenderScale(m_renderer, scaleX, scaleY);
|
||||
}
|
||||
|
||||
void RenderManager::resetViewport() {
|
||||
if (!m_initialized || !m_renderer) {
|
||||
return;
|
||||
}
|
||||
|
||||
SDL_SetRenderViewport(m_renderer, nullptr);
|
||||
updateLogicalScale();
|
||||
}
|
||||
|
||||
void RenderManager::clear(Uint8 r, Uint8 g, Uint8 b, Uint8 a) {
|
||||
if (!m_initialized || !m_renderer) {
|
||||
return;
|
||||
}
|
||||
|
||||
SDL_SetRenderDrawColor(m_renderer, r, g, b, a);
|
||||
SDL_RenderClear(m_renderer);
|
||||
}
|
||||
|
||||
void RenderManager::renderTexture(SDL_Texture* texture, const SDL_FRect* src, const SDL_FRect* dst) {
|
||||
if (!m_initialized || !m_renderer || !texture) {
|
||||
return;
|
||||
}
|
||||
|
||||
SDL_RenderTexture(m_renderer, texture, src, dst);
|
||||
}
|
||||
|
||||
void RenderManager::renderTexture(SDL_Texture* texture, float x, float y) {
|
||||
if (!texture) {
|
||||
return;
|
||||
}
|
||||
|
||||
float w, h;
|
||||
SDL_GetTextureSize(texture, &w, &h);
|
||||
SDL_FRect dst = { x, y, w, h };
|
||||
renderTexture(texture, nullptr, &dst);
|
||||
}
|
||||
|
||||
void RenderManager::renderTexture(SDL_Texture* texture, float x, float y, float w, float h) {
|
||||
if (!texture) {
|
||||
return;
|
||||
}
|
||||
|
||||
SDL_FRect dst = { x, y, w, h };
|
||||
renderTexture(texture, nullptr, &dst);
|
||||
}
|
||||
|
||||
void RenderManager::renderRect(const SDL_FRect& rect, Uint8 r, Uint8 g, Uint8 b, Uint8 a) {
|
||||
if (!m_initialized || !m_renderer) {
|
||||
return;
|
||||
}
|
||||
|
||||
SDL_SetRenderDrawColor(m_renderer, r, g, b, a);
|
||||
SDL_RenderFillRect(m_renderer, &rect);
|
||||
}
|
||||
|
||||
void RenderManager::renderLine(float x1, float y1, float x2, float y2, Uint8 r, Uint8 g, Uint8 b, Uint8 a) {
|
||||
if (!m_initialized || !m_renderer) {
|
||||
return;
|
||||
}
|
||||
|
||||
SDL_SetRenderDrawColor(m_renderer, r, g, b, a);
|
||||
SDL_RenderLine(m_renderer, x1, y1, x2, y2);
|
||||
}
|
||||
|
||||
void RenderManager::renderPoint(float x, float y, Uint8 r, Uint8 g, Uint8 b, Uint8 a) {
|
||||
if (!m_initialized || !m_renderer) {
|
||||
return;
|
||||
}
|
||||
|
||||
SDL_SetRenderDrawColor(m_renderer, r, g, b, a);
|
||||
SDL_RenderPoint(m_renderer, x, y);
|
||||
}
|
||||
|
||||
void RenderManager::handleWindowResize(int newWidth, int newHeight) {
|
||||
if (!m_initialized) {
|
||||
return;
|
||||
}
|
||||
|
||||
SDL_LogInfo(SDL_LOG_CATEGORY_RENDER, "Window resized to %dx%d", newWidth, newHeight);
|
||||
|
||||
m_windowWidth = newWidth;
|
||||
m_windowHeight = newHeight;
|
||||
updateLogicalScale();
|
||||
}
|
||||
|
||||
void RenderManager::setFullscreen(bool fullscreen) {
|
||||
if (!m_initialized || !m_window) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (m_isFullscreen == fullscreen) {
|
||||
return;
|
||||
}
|
||||
|
||||
SDL_SetWindowFullscreen(m_window, fullscreen ? SDL_WINDOW_FULLSCREEN : 0);
|
||||
m_isFullscreen = fullscreen;
|
||||
|
||||
// Update window size after fullscreen change
|
||||
SDL_GetWindowSize(m_window, &m_windowWidth, &m_windowHeight);
|
||||
updateLogicalScale();
|
||||
}
|
||||
|
||||
void RenderManager::getWindowSize(int& width, int& height) const {
|
||||
width = m_windowWidth;
|
||||
height = m_windowHeight;
|
||||
}
|
||||
|
||||
void RenderManager::updateLogicalScale() {
|
||||
if (!m_initialized || !m_renderer) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Calculate scale to fit logical size into window
|
||||
float scaleX = static_cast<float>(m_windowWidth) / static_cast<float>(m_logicalWidth);
|
||||
float scaleY = static_cast<float>(m_windowHeight) / static_cast<float>(m_logicalHeight);
|
||||
|
||||
// Use uniform scaling to maintain aspect ratio
|
||||
float scale = std::min(scaleX, scaleY);
|
||||
if (scale <= 0.0f) {
|
||||
scale = 1.0f;
|
||||
}
|
||||
|
||||
setScale(scale, scale);
|
||||
|
||||
// Set viewport to fill the entire window
|
||||
setViewport(0, 0, m_windowWidth, m_windowHeight);
|
||||
}
|
||||
79
src/graphics/RenderManager.h
Normal file
79
src/graphics/RenderManager.h
Normal file
@ -0,0 +1,79 @@
|
||||
#pragma once
|
||||
|
||||
#include <SDL3/SDL.h>
|
||||
#include <string>
|
||||
|
||||
/**
|
||||
* RenderManager - Abstracts SDL rendering functionality
|
||||
*
|
||||
* Responsibilities:
|
||||
* - Manage SDL_Window and SDL_Renderer lifecycle
|
||||
* - Provide high-level rendering interface
|
||||
* - Handle viewport and scaling logic
|
||||
* - Abstract SDL-specific details from game code
|
||||
*/
|
||||
class RenderManager {
|
||||
public:
|
||||
RenderManager();
|
||||
~RenderManager();
|
||||
|
||||
// Initialization and cleanup
|
||||
bool initialize(int width, int height, const std::string& title);
|
||||
void shutdown();
|
||||
|
||||
// Frame management
|
||||
void beginFrame();
|
||||
void endFrame();
|
||||
|
||||
// Viewport and scaling
|
||||
void setLogicalSize(int width, int height);
|
||||
void setViewport(int x, int y, int width, int height);
|
||||
void setScale(float scaleX, float scaleY);
|
||||
void resetViewport();
|
||||
|
||||
// Basic rendering operations
|
||||
void clear(Uint8 r = 0, Uint8 g = 0, Uint8 b = 0, Uint8 a = 255);
|
||||
|
||||
// Texture rendering
|
||||
void renderTexture(SDL_Texture* texture, const SDL_FRect* src, const SDL_FRect* dst);
|
||||
void renderTexture(SDL_Texture* texture, float x, float y);
|
||||
void renderTexture(SDL_Texture* texture, float x, float y, float w, float h);
|
||||
|
||||
// Primitive rendering
|
||||
void renderRect(const SDL_FRect& rect, Uint8 r, Uint8 g, Uint8 b, Uint8 a = 255);
|
||||
void renderLine(float x1, float y1, float x2, float y2, Uint8 r, Uint8 g, Uint8 b, Uint8 a = 255);
|
||||
void renderPoint(float x, float y, Uint8 r, Uint8 g, Uint8 b, Uint8 a = 255);
|
||||
|
||||
// Window management
|
||||
void handleWindowResize(int newWidth, int newHeight);
|
||||
void setFullscreen(bool fullscreen);
|
||||
void getWindowSize(int& width, int& height) const;
|
||||
|
||||
// Direct access to SDL objects (temporary, will be removed later)
|
||||
SDL_Renderer* getSDLRenderer() const { return m_renderer; }
|
||||
SDL_Window* getSDLWindow() const { return m_window; }
|
||||
|
||||
// State queries
|
||||
bool isInitialized() const { return m_initialized; }
|
||||
bool isFullscreen() const { return m_isFullscreen; }
|
||||
|
||||
private:
|
||||
// SDL objects
|
||||
SDL_Window* m_window = nullptr;
|
||||
SDL_Renderer* m_renderer = nullptr;
|
||||
|
||||
// Window properties
|
||||
int m_windowWidth = 0;
|
||||
int m_windowHeight = 0;
|
||||
int m_logicalWidth = 0;
|
||||
int m_logicalHeight = 0;
|
||||
float m_scaleX = 1.0f;
|
||||
float m_scaleY = 1.0f;
|
||||
|
||||
// State
|
||||
bool m_initialized = false;
|
||||
bool m_isFullscreen = false;
|
||||
|
||||
// Helper methods
|
||||
void updateLogicalScale();
|
||||
};
|
||||
Reference in New Issue
Block a user