2025-01-05 13:17:26 +00:00
|
|
|
|
#include <GL/glew.h> // Include GLEW before <SDL2/SDL.h>?
|
2025-01-05 01:30:18 +00:00
|
|
|
|
#include "sdl.hpp"
|
|
|
|
|
#include <iostream>
|
|
|
|
|
|
|
|
|
|
SdlWindow::SdlWindow(const char* title, int width, int height)
|
|
|
|
|
: m_window(nullptr),
|
|
|
|
|
m_renderer(nullptr),
|
|
|
|
|
m_isRunning(false),
|
|
|
|
|
m_isFullscreen(false),
|
|
|
|
|
m_width(width),
|
2025-01-05 02:27:36 +00:00
|
|
|
|
m_height(height),
|
2025-01-05 13:17:26 +00:00
|
|
|
|
m_glContext(nullptr),
|
|
|
|
|
m_windowedWidth(width),
|
|
|
|
|
m_windowedHeight(height)
|
2025-01-05 01:30:18 +00:00
|
|
|
|
{
|
2025-01-05 02:27:36 +00:00
|
|
|
|
// 1. Set attributes
|
|
|
|
|
SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, 3);
|
|
|
|
|
SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, 3);
|
|
|
|
|
SDL_GL_SetAttribute(SDL_GL_CONTEXT_PROFILE_MASK, SDL_GL_CONTEXT_PROFILE_CORE);
|
2025-01-05 01:30:18 +00:00
|
|
|
|
|
2025-01-05 02:41:40 +00:00
|
|
|
|
// 2. Create the window with OpenGL flag
|
|
|
|
|
m_window = SDL_CreateWindow(title,
|
|
|
|
|
SDL_WINDOWPOS_CENTERED,
|
|
|
|
|
SDL_WINDOWPOS_CENTERED,
|
|
|
|
|
width,
|
|
|
|
|
height,
|
2025-01-05 02:52:38 +00:00
|
|
|
|
SDL_WINDOW_OPENGL | SDL_WINDOW_SHOWN| SDL_WINDOW_RESIZABLE);
|
2025-01-05 02:41:40 +00:00
|
|
|
|
|
2025-01-05 01:30:18 +00:00
|
|
|
|
if (!m_window) {
|
|
|
|
|
std::cerr << "Failed to create window: " << SDL_GetError() << std::endl;
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
2025-01-05 02:41:40 +00:00
|
|
|
|
// 3. Create OpenGL context
|
|
|
|
|
m_glContext = SDL_GL_CreateContext(m_window);
|
|
|
|
|
if (!m_glContext) {
|
|
|
|
|
std::cerr << "Failed to create GL context: " << SDL_GetError() << std::endl;
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
// 4. Optionally init GLEW (if not on macOS core profile)
|
|
|
|
|
#ifndef __APPLE__
|
|
|
|
|
glewExperimental = GL_TRUE;
|
2025-01-05 13:17:26 +00:00
|
|
|
|
GLenum glewErr = glewInit();
|
2025-01-05 02:41:40 +00:00
|
|
|
|
if (glewInit() != GLEW_OK) {
|
2025-01-05 13:17:26 +00:00
|
|
|
|
std::cerr << "Failed to init GLEW" << glewGetErrorString(glewErr) << std::endl;
|
2025-01-05 02:41:40 +00:00
|
|
|
|
return;
|
2025-01-05 01:30:18 +00:00
|
|
|
|
}
|
2025-01-05 13:17:26 +00:00
|
|
|
|
glGetError();
|
2025-01-05 02:41:40 +00:00
|
|
|
|
#endif
|
2025-01-05 01:30:18 +00:00
|
|
|
|
|
2025-01-05 02:41:40 +00:00
|
|
|
|
// 5. Set vsync (optional)
|
|
|
|
|
SDL_GL_SetSwapInterval(1);
|
|
|
|
|
|
|
|
|
|
// 6. Mark as running
|
|
|
|
|
m_isRunning = true;
|
2025-01-05 13:51:33 +00:00
|
|
|
|
|
2025-01-05 14:12:28 +00:00
|
|
|
|
float positions[6] = { // vertex for a triangle
|
|
|
|
|
//x,y
|
2025-01-05 13:51:33 +00:00
|
|
|
|
-0.5f, -0.5f,
|
|
|
|
|
0.0f, 0.5f,
|
|
|
|
|
0.5f, -0.5f
|
|
|
|
|
};
|
2025-01-05 14:12:28 +00:00
|
|
|
|
//vertex buffer
|
2025-01-05 13:51:33 +00:00
|
|
|
|
unsigned int buffer;
|
|
|
|
|
glGenBuffers(1, &buffer);
|
|
|
|
|
glBindBuffer(GL_ARRAY_BUFFER, buffer); //select buffer called 'buffer'
|
|
|
|
|
glBufferData(GL_ARRAY_BUFFER, 6 * sizeof(float), positions, GL_STATIC_DRAW); // assigne buffer size, static as we use many times, but does not change
|
2025-01-05 14:12:28 +00:00
|
|
|
|
//vertext attributes / layout
|
|
|
|
|
glEnableVertexAttribArray(0);
|
|
|
|
|
glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, sizeof(float) * 2, 0);
|
|
|
|
|
|
|
|
|
|
|
2025-01-05 01:30:18 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
SdlWindow::~SdlWindow() {
|
2025-01-05 02:41:40 +00:00
|
|
|
|
// If using SDL Renderer, destroy it. But if you’re purely using OpenGL, you might remove it.
|
2025-01-05 01:30:18 +00:00
|
|
|
|
if (m_renderer) {
|
2025-01-05 02:41:40 +00:00
|
|
|
|
SDL_DestroyRenderer(m_renderer);
|
|
|
|
|
m_renderer = nullptr;
|
2025-01-05 01:30:18 +00:00
|
|
|
|
}
|
2025-01-05 02:41:40 +00:00
|
|
|
|
|
|
|
|
|
// Delete the OpenGL context
|
|
|
|
|
if (m_glContext) {
|
|
|
|
|
SDL_GL_DeleteContext(m_glContext);
|
|
|
|
|
m_glContext = nullptr;
|
|
|
|
|
}
|
|
|
|
|
|
2025-01-05 01:30:18 +00:00
|
|
|
|
if (m_window) {
|
2025-01-05 02:41:40 +00:00
|
|
|
|
SDL_DestroyWindow(m_window);
|
|
|
|
|
m_window = nullptr;
|
2025-01-05 01:30:18 +00:00
|
|
|
|
}
|
2025-01-05 02:41:40 +00:00
|
|
|
|
|
2025-01-05 01:30:18 +00:00
|
|
|
|
SDL_Quit();
|
|
|
|
|
}
|
|
|
|
|
|
2025-01-05 02:41:40 +00:00
|
|
|
|
|
2025-01-05 01:30:18 +00:00
|
|
|
|
void SdlWindow::run() {
|
|
|
|
|
while (m_isRunning) {
|
|
|
|
|
processEvents();
|
|
|
|
|
update();
|
|
|
|
|
render();
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void SdlWindow::processEvents() {
|
|
|
|
|
SDL_Event event;
|
|
|
|
|
while (SDL_PollEvent(&event)) {
|
|
|
|
|
if (event.type == SDL_QUIT) {
|
|
|
|
|
m_isRunning = false;
|
|
|
|
|
}
|
|
|
|
|
// Handle other events (keyboard, mouse, etc.) here if needed
|
|
|
|
|
else if (event.type == SDL_KEYDOWN) {
|
|
|
|
|
// Check if the key pressed is Enter/Return
|
|
|
|
|
if (event.key.keysym.sym == SDLK_RETURN) {
|
|
|
|
|
std::cout << "input detected" << std::endl;
|
|
|
|
|
}
|
|
|
|
|
if (event.key.keysym.sym == SDLK_SPACE) {
|
|
|
|
|
std::cout << "Full screen togled!" << std::endl;
|
|
|
|
|
setFullscreen(!m_isFullscreen);
|
|
|
|
|
}
|
|
|
|
|
if (event.key.keysym.sym == SDLK_ESCAPE) {
|
|
|
|
|
std::cout << "Bye!" << std::endl;
|
|
|
|
|
m_isRunning = false; //exit application
|
|
|
|
|
}
|
|
|
|
|
}
|
2025-01-05 02:52:38 +00:00
|
|
|
|
else if (event.type == SDL_WINDOWEVENT) {
|
|
|
|
|
if (event.window.event == SDL_WINDOWEVENT_RESIZED) {
|
|
|
|
|
// SDL gives the new width/height in event.window.data1/data2
|
|
|
|
|
int newWidth = event.window.data1;
|
|
|
|
|
int newHeight = event.window.data2;
|
|
|
|
|
|
|
|
|
|
// Update your internal width/height (if you keep track)
|
|
|
|
|
m_width = newWidth;
|
|
|
|
|
m_height = newHeight;
|
2025-01-05 13:17:26 +00:00
|
|
|
|
// If we are in windowed mode, update the "windowed" size.
|
|
|
|
|
if (!m_isFullscreen) {
|
|
|
|
|
m_windowedWidth = newWidth;
|
|
|
|
|
m_windowedHeight = newHeight;
|
|
|
|
|
}
|
2025-01-05 02:52:38 +00:00
|
|
|
|
|
|
|
|
|
// Update the OpenGL viewport
|
|
|
|
|
glViewport(0, 0, newWidth, newHeight);
|
|
|
|
|
|
|
|
|
|
// (Optional) If you have a projection matrix, update it here as well
|
|
|
|
|
// e.g., recalc the aspect ratio for a perspective projection
|
|
|
|
|
}
|
|
|
|
|
}
|
2025-01-05 01:30:18 +00:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void SdlWindow::update() {
|
|
|
|
|
// Update game/application logic here
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void SdlWindow::render() {
|
2025-01-05 02:41:40 +00:00
|
|
|
|
// Use GL calls instead of SDL’s renderer
|
|
|
|
|
glClearColor(0.0f, 0.0f, 0.0f, 1.0f);
|
|
|
|
|
glClear(GL_COLOR_BUFFER_BIT);
|
2025-01-05 01:30:18 +00:00
|
|
|
|
|
2025-01-05 02:41:40 +00:00
|
|
|
|
// TODO: Draw with OpenGL here (shaders, triangles, etc.)
|
2025-01-05 13:51:33 +00:00
|
|
|
|
glDrawArrays(GL_TRIANGLES, 0, 3);
|
2025-01-05 01:30:18 +00:00
|
|
|
|
|
2025-01-05 02:41:40 +00:00
|
|
|
|
// Swap buffers
|
|
|
|
|
SDL_GL_SwapWindow(m_window);
|
2025-01-05 01:30:18 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void SdlWindow::setFullscreen(bool fullscreen) {
|
|
|
|
|
if (m_window) {
|
|
|
|
|
m_isFullscreen = fullscreen;
|
|
|
|
|
if (m_isFullscreen) {
|
2025-01-05 13:17:26 +00:00
|
|
|
|
// Going TO fullscreen:
|
|
|
|
|
// (Optional) store the current size again, in case it changed
|
|
|
|
|
m_windowedWidth = m_width;
|
|
|
|
|
m_windowedHeight = m_height;
|
|
|
|
|
|
2025-01-05 01:30:18 +00:00
|
|
|
|
SDL_SetWindowFullscreen(m_window, SDL_WINDOW_FULLSCREEN_DESKTOP);
|
|
|
|
|
} else {
|
2025-01-05 13:17:26 +00:00
|
|
|
|
// Returning FROM fullscreen:
|
2025-01-05 01:30:18 +00:00
|
|
|
|
SDL_SetWindowFullscreen(m_window, 0); // return to windowed
|
2025-01-05 13:17:26 +00:00
|
|
|
|
// Now restore the window’s old size
|
|
|
|
|
SDL_SetWindowSize(m_window, m_windowedWidth, m_windowedHeight);
|
|
|
|
|
|
|
|
|
|
// Update m_width, m_height so they reflect the new (restored) size
|
|
|
|
|
m_width = m_windowedWidth;
|
|
|
|
|
m_height = m_windowedHeight;
|
2025-01-05 01:30:18 +00:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
2025-01-05 13:17:26 +00:00
|
|
|
|
|