diff --git a/inc/engine/opengl.hpp b/inc/engine/opengl.hpp new file mode 100644 index 0000000..fa0bee3 --- /dev/null +++ b/inc/engine/opengl.hpp @@ -0,0 +1,28 @@ +#ifndef OPENGL_HPP +#define OPENGL_HPP + +// Includes +#include +#include "engine/sdl.hpp" + +// OpenGL Context Class +class OpenGLContext { +public: + OpenGLContext(SDLWindow& window); + ~OpenGLContext(); + + bool isInitialized() const; + void makeCurrent(); + void swapBuffers(); + float getFrameTime(); + +private: + SDLWindow& window; + SDL_GLContext glContext; + + Uint32 lastTime; + float frameTime; + +}; + +#endif diff --git a/inc/engine/sdl.hpp b/inc/engine/sdl.hpp new file mode 100644 index 0000000..a22cc4f --- /dev/null +++ b/inc/engine/sdl.hpp @@ -0,0 +1,28 @@ +#ifndef SDL_HPP +#define SDL_HPP + +// Includes +#include + +// Classes +class SDLWindow { +public: + SDLWindow(const char* title, int width, int height, SDL_WindowFlags flags = SDL_WINDOW_OPENGL | SDL_WINDOW_HIGH_PIXEL_DENSITY | SDL_WINDOW_HIDDEN); + ~SDLWindow(); + + void setEventCallback(void (*callback)(const SDL_Event&)); + void pollEvents(); + bool isRunning() const; + void showWindow(); + void hideWindow(); + void setPosition(int x, int y); + SDL_Window* getSDLWindow() const; + +private: + SDL_Window* window; + SDL_Event event; + bool running; + void (*eventCallback)(const SDL_Event&) = nullptr; +}; + +#endif diff --git a/makefile b/makefile index 77e418a..f2ee5ed 100644 --- a/makefile +++ b/makefile @@ -3,26 +3,32 @@ INCLUDE_DIR = inc SRC_DIR = src BUILD_DIR = build -# imgui bs +# imgui IMGUI_DIR = lib/imgui INCLUDE_DIR += $(IMGUI_DIR) $(IMGUI_DIR)/backends # Compiler, flags and libraries -CXX = g++ +CXX = g++ CXXFLAGS = -std=c++17 LIBS = -lGL -lglm `pkg-config --libs sdl3 sdl3-image` -# =============================== Don't touch below pwease :3 =============================== - -# Compiler and linker settings +# Include dirs in compiler flags CXXFLAGS += $(addprefix -I, $(INCLUDE_DIR)) -# Source files -SRC = $(wildcard $(SRC_DIR)/*.cpp) +# Source files (app + subdirs) +SRC := $(wildcard $(SRC_DIR)/*.cpp) $(wildcard $(SRC_DIR)/*/*.cpp) -# Imgui specific stuff -SRC += $(IMGUI_DIR)/imgui.cpp $(IMGUI_DIR)/imgui_demo.cpp $(IMGUI_DIR)/imgui_draw.cpp $(IMGUI_DIR)/imgui_tables.cpp $(IMGUI_DIR)/imgui_widgets.cpp -SRC += $(IMGUI_DIR)/backends/imgui_impl_sdl3.cpp $(IMGUI_DIR)/backends/imgui_impl_opengl3.cpp +# ImGui specific sources (explicit list) +IMGUI_SRC := \ + $(IMGUI_DIR)/imgui.cpp \ + $(IMGUI_DIR)/imgui_demo.cpp \ + $(IMGUI_DIR)/imgui_draw.cpp \ + $(IMGUI_DIR)/imgui_tables.cpp \ + $(IMGUI_DIR)/imgui_widgets.cpp \ + $(IMGUI_DIR)/backends/imgui_impl_sdl3.cpp \ + $(IMGUI_DIR)/backends/imgui_impl_opengl3.cpp + +SRC += $(IMGUI_SRC) # Target executable UNAME := $(shell uname -s) @@ -30,8 +36,13 @@ BUILD_DIR := $(BUILD_DIR)/$(UNAME) OBJ_DIR := $(BUILD_DIR)/objs BIN = $(BUILD_DIR)/main + +# Note: I have no clue how this works, copilot made it for me cus my usual makefile didn't like the directory structure :P # Object files corresponding to the source files -OBJS = $(addprefix $(OBJ_DIR)/, $(addsuffix .o, $(basename $(notdir $(SRC))))) +# Map source paths to object paths so subdirectories are preserved. +# - Files under `$(SRC_DIR)` become `$(OBJ_DIR)//name.o` +# - ImGui files (in `$(IMGUI_DIR)` and its `backends`) become `$(OBJ_DIR)/name.o` +OBJS := $(foreach f,$(SRC),$(if $(filter $(SRC_DIR)/%,$(f)),$(patsubst $(SRC_DIR)/%.cpp,$(OBJ_DIR)/%.o,$(f)),$(if $(filter $(IMGUI_DIR)/backends/%,$(f)),$(patsubst $(IMGUI_DIR)/backends/%.cpp,$(OBJ_DIR)/%.o,$(f)),$(patsubst $(IMGUI_DIR)/%.cpp,$(OBJ_DIR)/%.o,$(f)))) ) # black magic wizardry below this line (pwease don't touch i beg you) dev: CXXFLAGS += -g -Wall -Wformat @@ -43,6 +54,8 @@ release: all dirs: @mkdir -p $(BUILD_DIR) @mkdir -p $(OBJ_DIR) + # create any required subdirectories for object files + @mkdir -p $(sort $(dir $(OBJS))) # Even more imgui specific stuff >:( $(OBJ_DIR)/%.o: $(IMGUI_DIR)/%.cpp @@ -58,7 +71,9 @@ all: dirs $(BIN) @echo Build complete $(BIN): $(OBJS) - $(CXX) -o $@ $^ $(CXXFLAGS) $(LIBS) + $(CXX) $(CXXFLAGS) -o $@ $^ $(LIBS) + +.PHONY: all dev release clean dirs clean: rm -rf $(BUILD_DIR) \ No newline at end of file diff --git a/src/engine/opengl.cpp b/src/engine/opengl.cpp new file mode 100644 index 0000000..89aa85f --- /dev/null +++ b/src/engine/opengl.cpp @@ -0,0 +1,44 @@ +#include "engine/opengl.hpp" + +// OpenGLContext Constructor +OpenGLContext::OpenGLContext(SDLWindow& window): window(window), lastTime(SDL_GetTicks()), frameTime(0.0f) { + glContext = SDL_GL_CreateContext(window.getSDLWindow()); + if (!glContext) { + // Handle context creation error + SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "Failed to create OpenGL context: %s", SDL_GetError()); + return; + } + SDL_GL_MakeCurrent(window.getSDLWindow(), glContext); +} + +// OpenGLContext Destructor +OpenGLContext::~OpenGLContext() { + if (glContext) { + SDL_GL_DestroyContext(glContext); + } +} + +// Check if Initialized +bool OpenGLContext::isInitialized() const { + return glContext != nullptr; +} + +// Make Context Current +void OpenGLContext::makeCurrent() { + SDL_GL_MakeCurrent(window.getSDLWindow(), glContext); +} + +// Swap Buffers +void OpenGLContext::swapBuffers() { + SDL_GL_SwapWindow(window.getSDLWindow()); + + // Update frame time + Uint32 currentTime = SDL_GetTicks(); + frameTime = (currentTime - lastTime) / 1000.0f; + lastTime = currentTime; +} + +// Get Frame Time +float OpenGLContext::getFrameTime() { + return frameTime; +} \ No newline at end of file diff --git a/src/engine/sdl.cpp b/src/engine/sdl.cpp new file mode 100644 index 0000000..215f714 --- /dev/null +++ b/src/engine/sdl.cpp @@ -0,0 +1,72 @@ +#include "engine/sdl.hpp" + +// SDLWindow Constructor +SDLWindow::SDLWindow(const char* title, int width, int height, SDL_WindowFlags flags): running(true) { + if (!SDL_Init(SDL_INIT_VIDEO)) { + // Handle initialization error + SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "Failed to initialize SDL: %s", SDL_GetError()); + running = false; + return; + } + + window = SDL_CreateWindow(title, width, height, flags); + if (!window) { + // Handle window creation error + SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "Failed to create SDL window: %s", SDL_GetError()); + SDL_Quit(); + running = false; + } + + return; +} + +// SDLWindow Destructor +SDLWindow::~SDLWindow() +{ + if (window) { + SDL_DestroyWindow(window); + } + SDL_Quit(); +} + +// Poll Events +void SDLWindow::pollEvents() { + while (SDL_PollEvent(&event)) { + if (event.type == SDL_EVENT_QUIT) { + running = false; + } + if (eventCallback) { + eventCallback(event); + } + } +} + +// Set Event Callback +void SDLWindow::setEventCallback(void (*callback)(const SDL_Event&)) { + eventCallback = callback; +} + +// Check if Window is Running +bool SDLWindow::isRunning() const { + return running; +} + +// Show Window +void SDLWindow::showWindow() { + SDL_ShowWindow(window); +} + +// Hide Window +void SDLWindow::hideWindow() { + SDL_HideWindow(window); +} + +// Set Window Position +void SDLWindow::setPosition(int x, int y) { + SDL_SetWindowPosition(window, x, y); +} + +// Return raw SDL_Window pointer +SDL_Window* SDLWindow::getSDLWindow() const { + return window; +} \ No newline at end of file diff --git a/src/main.cpp b/src/main.cpp index e69de29..7464472 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -0,0 +1,19 @@ +#include "engine/sdl.hpp" +#include "engine/opengl.hpp" + +int main(int argc, char* argv[]) { + SDLWindow window("My SDL Application", 800, 600); + if (!window.isRunning()) { return -1; } + OpenGLContext glContext(window); + if (!glContext.isInitialized()) { return -1; } + + window.setPosition(SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED); + window.showWindow(); + while (window.isRunning()) { + window.pollEvents(); + // Application logic and rendering would go here + glContext.swapBuffers(); + } + + return 0; +} \ No newline at end of file