Updated CmakeList

This commit is contained in:
2026-03-15 19:39:35 +01:00
commit e152bf93b3
20 changed files with 566 additions and 0 deletions

2
.gitignore vendored Normal file
View File

@@ -0,0 +1,2 @@
Build
build

12
.gitmodules vendored Normal file
View File

@@ -0,0 +1,12 @@
[submodule "libs/imgui"]
path = libs/imgui
url = https://github.com/htamas1210/imgui.git
[submodule "libs/catch2"]
path = libs/catch2
url = https://github.com/htamas1210/Catch2.git
[submodule "libs/spdlog"]
path = libs/spdlog
url = https://github.com/htamas1210/spdlog.git
[submodule "libs/sdl"]
path = libs/sdl3
url = https://github.com/htamas1210/SDL.git

133
CMakeLists.txt Normal file
View File

@@ -0,0 +1,133 @@
# Require a modern version of CMake
cmake_minimum_required(VERSION 3.15)
# Define the Core Library project
project(SakuraCore LANGUAGES CXX)
# ------------------------------------------------------------------------------
# Default Build Type Configuration
# ------------------------------------------------------------------------------
if(NOT CMAKE_BUILD_TYPE AND NOT CMAKE_CONFIGURATION_TYPES)
message(STATUS "Setting default build type to 'Debug'")
set(CMAKE_BUILD_TYPE "Debug" CACHE STRING "Choose the type of build." FORCE)
set_property(CACHE CMAKE_BUILD_TYPE PROPERTY STRINGS "Debug" "Release" "MinSizeRel" "RelWithDebInfo")
endif()
# Enforce C++20 globally
set(CMAKE_CXX_STANDARD 20)
set(CMAKE_CXX_STANDARD_REQUIRED ON)
set(CMAKE_CXX_EXTENSIONS OFF)
# ------------------------------------------------------------------------------
# Output Directory Configuration
# ------------------------------------------------------------------------------
set(OUTPUT_DIR_SUFFIX "$<CONFIG>-${CMAKE_SYSTEM_NAME}-${CMAKE_SYSTEM_PROCESSOR}")
set(CMAKE_RUNTIME_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/bin/${OUTPUT_DIR_SUFFIX}")
set(CMAKE_LIBRARY_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/bin/${OUTPUT_DIR_SUFFIX}")
set(CMAKE_ARCHIVE_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/bin/${OUTPUT_DIR_SUFFIX}")
# ------------------------------------------------------------------------------
# Dependencies
# ------------------------------------------------------------------------------
# 1. SDL3
set(SDL_TESTS OFF CACHE BOOL "Disable SDL3 tests" FORCE)
set(SDL_EXAMPLES OFF CACHE BOOL "Disable SDL3 examples" FORCE)
add_subdirectory(libs/sdl3)
# 2. spdlog
set(SPDLOG_BUILD_COMPILED ON CACHE BOOL "Build spdlog as a compiled library" FORCE)
set(SPDLOG_BUILD_EXAMPLE OFF CACHE BOOL "Disable spdlog examples" FORCE)
set(SPDLOG_BUILD_TESTS OFF CACHE BOOL "Disable spdlog tests" FORCE)
add_subdirectory(libs/spdlog)
# 3. ImGui (Standard UI for debug menus/core rendering)
add_subdirectory(libs/imgui)
# 4. Catch2 (Only in Debug)
if(CMAKE_BUILD_TYPE STREQUAL "Debug" OR NOT CMAKE_BUILD_TYPE)
add_subdirectory(libs/catch2)
endif()
# ------------------------------------------------------------------------------
# Source Gathering
# ------------------------------------------------------------------------------
file(GLOB_RECURSE SAKURA_CORE_SRCS "SakuraCore/src/*.cpp" "SakuraCore/src/*.h")
# ------------------------------------------------------------------------------
# SakuraCore STATIC Library Target
# ------------------------------------------------------------------------------
add_library(SakuraCore STATIC ${SAKURA_CORE_SRCS})
target_include_directories(SakuraCore PUBLIC
"${CMAKE_CURRENT_SOURCE_DIR}/src"
"libs/spdlog/include"
"libs/imgui"
"libs/imgui/misc"
"libs/imgui/backends"
"libs/sdl3/include"
)
target_link_libraries(SakuraCore PUBLIC
ImGui
SDL3::SDL3
spdlog::spdlog
)
# ------------------------------------------------------------------------------
# Tests Executable Target
# ------------------------------------------------------------------------------
if(CMAKE_BUILD_TYPE STREQUAL "Debug" OR NOT CMAKE_BUILD_TYPE)
# The tests executable just needs its own test.cpp file
add_executable(tests "SakuraCore/test/test.cpp")
# Link Catch2 and our newly created SakuraCore library!
# Because SakuraCore is PUBLIC above, 'tests' automatically gets SDL3, ImGui, etc.
target_include_directories(tests PRIVATE
"SakuraCore/src"
"libs/spdlog/include"
"libs/imgui"
"libs/imgui/misc"
"libs/imgui/backends"
"libs/sdl3/include"
)
target_link_libraries(tests PRIVATE
Catch2::Catch2WithMain
SakuraCore
)
endif()
# ------------------------------------------------------------------------------
# Platform & Configuration Filters
# ------------------------------------------------------------------------------
if(WIN32)
target_compile_definitions(SakuraCore PUBLIC PLATFORM_WINDOWS)
target_link_options(SakuraCore PUBLIC "/NODEFAULTLIB:MSVCRT")
if(TARGET tests)
target_compile_definitions(tests PRIVATE PLATFORM_WINDOWS)
target_link_options(tests PRIVATE "/NODEFAULTLIB:MSVCRT")
endif()
elseif(UNIX AND NOT APPLE)
target_compile_definitions(SakuraCore PUBLIC PLATFORM_LINUX)
target_link_libraries(SakuraCore PUBLIC dl pthread)
if(TARGET tests)
target_compile_definitions(tests PRIVATE PLATFORM_LINUX)
target_link_libraries(tests PRIVATE dl pthread)
endif()
endif()
# Debug vs Release definitions
target_compile_definitions(SakuraCore PUBLIC
$<$<CONFIG:Debug>:DEBUG>
$<$<CONFIG:Release>:RELEASE>
)
if(TARGET tests)
target_compile_definitions(tests PRIVATE
$<$<CONFIG:Debug>:DEBUG>
$<$<CONFIG:Release>:RELEASE>
)
endif()

View File

@@ -0,0 +1,166 @@
#include "Application.h"
#include "Event.h"
#include "Log.h"
#include "SDL3/SDL_render.h"
#include "imgui.h"
#include "imgui_impl_sdl3.h"
#include "imgui_impl_sdlrenderer3.h"
Application::Application() : m_Window(nullptr), m_Renderer(nullptr), m_Surface(nullptr), m_isRunning(false) {}
Application::~Application() { Shutdown(); }
bool Application::Init() {
SetRunningState(true);
SakuraVNE::Log::Init();
LOG_INFO("Initialized logger library");
LOG_INFO("window width: {0}, height: {1}", GetWindowData().width, GetWindowData().height);
// Init sdl
if (SDL_Init(SDL_INIT_VIDEO | SDL_INIT_EVENTS) == 0) {
LOG_ERROR("SDL could not be initialized! {0}", SDL_GetError());
Shutdown();
return false;
}
SDL_WindowFlags windowFlags = (SDL_WindowFlags)(SDL_WINDOW_RESIZABLE);
m_Window = SDL_CreateWindow(GetWindowData().title, GetWindowData().width, GetWindowData().height, windowFlags);
if (!m_Window) {
LOG_ERROR("SDL window could not be created! {0}", SDL_GetError());
Shutdown();
return false;
} else {
LOG_INFO("SDl window created");
}
if (GetWindowData().pos_x != -1 && GetWindowData().pos_y != -1) {
if (!SDL_SetWindowPosition(m_Window, GetWindowData().pos_x, GetWindowData().pos_y)) {
LOG_ERROR("Failed to set SDL_Window position {0}", SDL_GetError());
} else {
LOG_INFO("SDL window position set to the initial value: x {0}, y {1}", GetWindowData().pos_x, GetWindowData().pos_y);
}
} else {
LOG_WARN("SDL window position not set. Will not attempt to set window position.");
}
LOG_INFO("Available renderer drivers:");
for (int i = 0; i < SDL_GetNumRenderDrivers(); i++) {
LOG_INFO("{0}. {1}", i + 1, SDL_GetRenderDriver(i));
}
m_Renderer = SDL_CreateRenderer(m_Window, nullptr);
if (!m_Renderer) {
LOG_ERROR("Renderer could not be created! {0}", SDL_GetError());
} else {
LOG_INFO("SDL renderer created");
LOG_INFO("Renderer: {0}", SDL_GetRendererName(m_Renderer));
}
SDL_SetRenderVSync(m_Renderer, 1);
// Imgui init
IMGUI_CHECKVERSION();
ImGui::CreateContext();
ImGuiIO &io = ImGui::GetIO();
io.ConfigFlags |= ImGuiConfigFlags_NavEnableKeyboard;
ImGui::StyleColorsDark();
ImGui_ImplSDL3_InitForSDLRenderer(m_Window, m_Renderer);
ImGui_ImplSDLRenderer3_Init(m_Renderer);
return true;
}
void Application::Run() {
bool demoWindowShow = false;
bool showOtherWindow = false;
ImVec4 clearColor = ImVec4(0.45f, 0.55f, 0.60f, 1.00f);
ImGuiIO &io = ImGui::GetIO();
while (GetRunningState()) {
SDL_Event event;
while (SDL_PollEvent(&event)) {
ImGui_ImplSDL3_ProcessEvent(&event);
if (event.type == SDL_EVENT_QUIT) {
SetRunningState(false);
LOG_INFO("Running state: {0}", GetRunningState());
}
if (event.type == SDL_EVENT_WINDOW_CLOSE_REQUESTED && event.window.windowID == SDL_GetWindowID(GetSDLWindow())) {
SetRunningState(false);
}
if (event.type == SDL_EVENT_WINDOW_RESIZED) {
SDL_GetWindowSize(GetSDLWindow(), &GetWindowData().width, &GetWindowData().height);
SetSDLWindowSurface(SDL_GetWindowSurface(GetSDLWindow()));
}
}
ImGui_ImplSDLRenderer3_NewFrame();
ImGui_ImplSDL3_NewFrame();
ImGui::NewFrame();
if (demoWindowShow) {
ImGui::ShowDemoWindow(&demoWindowShow);
}
// imgui demo window stuff or frame stuff
static float f = 0.0f;
static int counter = 0;
ImGui::Begin("Hello World!"); // creates window and add later stuff to it
ImGui::Text("text stuff");
ImGui::Checkbox("Demo checkbox", &showOtherWindow);
ImGui::SliderFloat("float", &f, 0.0f, 1.0f);
ImGui::ColorEdit3("clear color edit", (float *)&clearColor);
if (ImGui::Button("Button"))
counter++;
ImGui::SameLine();
ImGui::Text("counter = %d", counter);
ImGui::Text("Application avg %.3f ms/frame (%.1f FPS)", 1000.0f / io.Framerate, io.Framerate);
if (ImGui::Button("Quit")) {
SetRunningState(false);
}
ImGui::End();
// Rendering
ImGui::Render();
SDL_SetRenderScale(m_Renderer, io.DisplayFramebufferScale.x, io.DisplayFramebufferScale.y);
SDL_SetRenderDrawColor(m_Renderer, (Uint8)(clearColor.x * 255), (Uint8)(clearColor.y * 255), (Uint8)(clearColor.z * 255), (Uint8)(clearColor.w * 255));
SDL_RenderClear(m_Renderer);
ImGui_ImplSDLRenderer3_RenderDrawData(ImGui::GetDrawData(), m_Renderer);
SDL_RenderPresent(m_Renderer);
}
}
void Application::Shutdown() {
LOG_WARN("Shutting down the application!");
ImGui_ImplSDLRenderer3_Shutdown();
ImGui_ImplSDL3_Shutdown();
ImGui::DestroyContext();
SDL_DestroyRenderer(m_Renderer);
// Destroy window
SDL_DestroyWindow(m_Window);
// Quit SDL subsystems
SDL_Quit();
}

View File

@@ -0,0 +1,38 @@
#pragma once
#include "SDL3/SDL.h"
struct WindowData {
int width = 1280;
int height = 720;
int pos_x = -1;
int pos_y = -1;
const char *title = "Sakura Visual Novel Engine";
};
class Application {
public:
Application();
~Application();
bool Init();
void Run();
void Shutdown();
inline WindowData &GetWindowData() { return m_WindowData; }
inline SDL_Window *GetSDLWindow() { return m_Window; }
inline SDL_Surface *GetSDLWindowSurface() { return m_Surface; }
inline void SetSDLWindowSurface(SDL_Surface *newSurface) { m_Surface = newSurface; }
bool &GetRunningState() { return m_isRunning; }
void SetRunningState(bool isRunning) { m_isRunning = isRunning; }
private:
SDL_Window *m_Window;
SDL_Surface *m_Surface;
SDL_Renderer *m_Renderer;
WindowData m_WindowData;
bool m_isRunning;
};

6
SakuraCore/src/Event.cpp Normal file
View File

@@ -0,0 +1,6 @@
#include "Event.h"
#include "Application.h"
#include "Log.h"
#include "SDL3/SDL.h"
void SakuraVNE::ProcessEvents() {}

3
SakuraCore/src/Event.h Normal file
View File

@@ -0,0 +1,3 @@
namespace SakuraVNE{
void ProcessEvents();
}

6
SakuraCore/src/Layer.cpp Normal file
View File

@@ -0,0 +1,6 @@
#include "Layer.h"
#include <string>
namespace SakuraVNE {
Layer::Layer(const std::string &name) : m_LayerName(name) {}
} // namespace SakuraVNE

23
SakuraCore/src/Layer.h Normal file
View File

@@ -0,0 +1,23 @@
#pragma once
#include <string>
namespace SakuraVNE {
class Layer {
public:
Layer(const std::string &name = "Layer");
virtual ~Layer() = default;
virtual void OnStart() {}
virtual void OnFrame(float timestamp) {}
virtual void OnEnd() {}
virtual void OnEvent() {}
virtual void OnAttach() {}
virtual void OnDetach() {}
const std::string &GetName() const { return m_LayerName; }
protected:
std::string m_LayerName;
};
} // namespace SakuraVNE

View File

@@ -0,0 +1,37 @@
#include "LayerStack.h"
#include <algorithm>
#include <vector>
namespace SakuraVNE {
LayerStack::~LayerStack() {
for (Layer *layer : m_LayerStack) {
layer->OnDetach();
delete layer;
}
}
void LayerStack::PushLayer(Layer *layer) {
m_LayerStack.emplace(m_LayerStack.begin() + m_LayerIndex, layer);
m_LayerIndex++;
}
void LayerStack::PopLayer(Layer *layer) {
auto match = std::find(m_LayerStack.begin(), m_LayerStack.begin() + m_LayerIndex, layer);
if (match != m_LayerStack.begin() + m_LayerIndex) {
layer->OnDetach();
m_LayerStack.erase(match);
m_LayerIndex--;
}
}
void LayerStack::PushOverLay(Layer *layer) { m_LayerStack.emplace_back(layer); }
void LayerStack::PopOverlay(Layer *layer) {
auto match = std::find(m_LayerStack.begin() + m_LayerIndex, m_LayerStack.end(), layer);
if (match != m_LayerStack.end()) {
layer->OnDetach();
m_LayerStack.erase(match);
}
}
} // namespace SakuraVNE

View File

@@ -0,0 +1,25 @@
#pragma once
#include "Layer.h"
#include <vector>
namespace SakuraVNE {
class LayerStack {
public:
LayerStack() = default;
~LayerStack();
void PushLayer(Layer *layer);
void PopLayer(Layer *layer);
void PushOverLay(Layer *layer);
void PopOverlay(Layer *layer);
#ifdef DEBUG
// this is only used for the tests for now, so it will be taken out of the release build
inline const std::vector<Layer *> &GetLayers() const { return m_LayerStack; }
#endif
private:
std::vector<Layer *> m_LayerStack;
unsigned int m_LayerIndex = 0;
};
} // namespace SakuraVNE

16
SakuraCore/src/Log.cpp Normal file
View File

@@ -0,0 +1,16 @@
#include "Log.h"
#include "spdlog/sinks/stdout_color_sinks.h"
namespace SakuraVNE{
std::shared_ptr<spdlog::logger> Log::m_Logger;
void Log::Init(){
spdlog::set_pattern("%^[%T] %n: %v%$");
m_Logger = spdlog::stdout_color_mt("Sakura");
m_Logger->set_level(spdlog::level::trace);
}
}

23
SakuraCore/src/Log.h Normal file
View File

@@ -0,0 +1,23 @@
#pragma once
#include "spdlog/spdlog.h"
#include "spdlog/fmt/ostr.h"
#include <memory>
namespace SakuraVNE
{
class Log
{
public:
static void Init();
inline static std::shared_ptr<spdlog::logger>& GetLogger() {return m_Logger;}
private:
static std::shared_ptr<spdlog::logger> m_Logger;
};
}
#define LOG_INFO(...) ::SakuraVNE::Log::GetLogger()->info(__VA_ARGS__)
#define LOG_WARN(...) ::SakuraVNE::Log::GetLogger()->warn(__VA_ARGS__)
#define LOG_ERROR(...) ::SakuraVNE::Log::GetLogger()->error(__VA_ARGS__)

53
SakuraCore/test/test.cpp Normal file
View File

@@ -0,0 +1,53 @@
#include <catch2/catch_test_macros.hpp>
#include "Layer.h"
#include "LayerStack.h"
#include <iostream>
#include <vector>
TEST_CASE("Layer operations", "[Layer]") {
SakuraVNE::LayerStack lstack;
const auto &layers = lstack.GetLayers();
SakuraVNE::Layer *layer1 = new SakuraVNE::Layer("layer1");
lstack.PushLayer(layer1);
SECTION("PushLayer should make the size 2") {
SakuraVNE::Layer *layer2 = new SakuraVNE::Layer("layer2");
lstack.PushLayer(layer2);
REQUIRE(layers.size() == 2);
REQUIRE(layers[1]->GetName() == "layer2");
}
SECTION("PopLayer should make the size 0") {
lstack.PopLayer(layer1);
REQUIRE(layers.size() == 0);
}
SECTION("PushOverlay should always put at the end of the list and should always be after the last fence index") {
SakuraVNE::Layer *layer2 = new SakuraVNE::Layer("layer2");
lstack.PushOverLay(layer2);
REQUIRE(layers[1]->GetName() == "layer2");
SakuraVNE::Layer *layer3 = new SakuraVNE::Layer("layer3");
lstack.PushLayer(layer3);
REQUIRE(layers[1]->GetName() == "layer3");
REQUIRE(layers[2]->GetName() == "layer2");
}
SECTION("Pop overlay") {
SakuraVNE::Layer *layer6 = new SakuraVNE::Layer("layer6");
lstack.PushOverLay(layer6);
REQUIRE(layers[1]->GetName() == "layer6");
lstack.PopOverlay(layer6);
bool hasLayer2InVec = false;
for (auto layer : layers) {
if (layer->GetName() == "layer6") {
hasLayer2InVec = true;
}
}
REQUIRE(hasLayer2InVec == false);
}
}

11
generate.bat Normal file
View File

@@ -0,0 +1,11 @@
echo Generating vs2026 project files...
where cmake >target 2>nul
if %ERRORLEVEL% neq 0 (
echo HIBA: A CMake nincs telepitve, vagy nincs hozzaadva a PATH-hoz.
pause
exit /b 1
)
cmake -G "Visual Studio 18 2026" -A x64
echo Done
PAUSE

8
generate.sh Executable file
View File

@@ -0,0 +1,8 @@
#!/bin/bash
echo "Generating Makefiles..."
cmake -B build -DCMAKE_BUILD_TYPE=Debug -DCMAKE_EXPORT_COMPILE_COMMANDS=ON
echo "Generating compile_commands.json for clangd..."
ln -sf build/compile_commands.json compile_commands.json
echo "Done!"
echo "To compile run:\n cmake --build build -j":

1
libs/catch2 Submodule

Submodule libs/catch2 added at ccc49ba664

1
libs/imgui Submodule

Submodule libs/imgui added at 5ffba73d97

1
libs/sdl3 Submodule

Submodule libs/sdl3 added at 5f78ded319

1
libs/spdlog Submodule

Submodule libs/spdlog added at 45b67eee66