Compare commits
No commits in common. "main" and "c246da98ff9bef4ccfec8c4de6894dae4585aaea" have entirely different histories.
main
...
c246da98ff
8
.gitignore
vendored
@ -1,13 +1,7 @@
|
|||||||
# ---> C++
|
# ---> C++
|
||||||
# Prerequisites
|
# Prerequisites
|
||||||
*.d
|
*.d
|
||||||
cmake-build-*/
|
|
||||||
.idea/
|
|
||||||
*.o
|
|
||||||
*.obj
|
|
||||||
*.exe
|
|
||||||
*.out
|
|
||||||
build/
|
|
||||||
# Compiled Object files
|
# Compiled Object files
|
||||||
*.slo
|
*.slo
|
||||||
*.lo
|
*.lo
|
||||||
|
|||||||
3
.gitmodules
vendored
@ -1,3 +0,0 @@
|
|||||||
[submodule "external/NetworkCore"]
|
|
||||||
path = external/NetworkCore
|
|
||||||
url = git@git.fawkes100.de:sebastian/JsonTCPServer.git
|
|
||||||
@ -1,2 +1,8 @@
|
|||||||
<?xml version="1.0" encoding="UTF-8"?>
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
<module classpath="CIDR" type="CPP_MODULE" version="4" />
|
<module type="CPP_MODULE" version="4">
|
||||||
|
<component name="NewModuleRootManager">
|
||||||
|
<content url="file://$MODULE_DIR$" />
|
||||||
|
<orderEntry type="inheritedJdk" />
|
||||||
|
<orderEntry type="sourceFolder" forTests="false" />
|
||||||
|
</component>
|
||||||
|
</module>
|
||||||
356
CMakeLists.txt
@ -1,358 +1,6 @@
|
|||||||
cmake_minimum_required(VERSION 4.2)
|
cmake_minimum_required(VERSION 4.2)
|
||||||
project(ColorRace)
|
project(ColorRace)
|
||||||
|
|
||||||
set(CMAKE_CXX_STANDARD 20)
|
set(CMAKE_CXX_STANDARD 20)
|
||||||
set(CMAKE_CXX_STANDARD_REQUIRED ON)
|
|
||||||
|
|
||||||
# --- CPM.cmake Bootstrap ---
|
add_executable(ColorRace main.cpp)
|
||||||
set(CPM_DOWNLOAD_VERSION 0.40.2)
|
|
||||||
set(CPM_DOWNLOAD_LOCATION "${CMAKE_BINARY_DIR}/cmake/CPM_${CPM_DOWNLOAD_VERSION}.cmake")
|
|
||||||
if(NOT EXISTS ${CPM_DOWNLOAD_LOCATION})
|
|
||||||
file(DOWNLOAD
|
|
||||||
https://github.com/cpm-cmake/CPM.cmake/releases/download/v${CPM_DOWNLOAD_VERSION}/CPM.cmake
|
|
||||||
${CPM_DOWNLOAD_LOCATION}
|
|
||||||
)
|
|
||||||
endif()
|
|
||||||
include(${CPM_DOWNLOAD_LOCATION})
|
|
||||||
|
|
||||||
# --- OpenGL (systemseitig, kein CPM nötig) ---
|
|
||||||
find_package(OpenGL REQUIRED)
|
|
||||||
|
|
||||||
# --- GLFW ---
|
|
||||||
CPMAddPackage(
|
|
||||||
NAME glfw
|
|
||||||
GITHUB_REPOSITORY glfw/glfw
|
|
||||||
GIT_TAG 3.4
|
|
||||||
OPTIONS
|
|
||||||
"GLFW_BUILD_EXAMPLES OFF"
|
|
||||||
"GLFW_BUILD_TESTS OFF"
|
|
||||||
"GLFW_BUILD_DOCS OFF"
|
|
||||||
"GLFW_INSTALL OFF"
|
|
||||||
)
|
|
||||||
|
|
||||||
# --- GLM (header-only) ---
|
|
||||||
CPMAddPackage(
|
|
||||||
NAME glm
|
|
||||||
GITHUB_REPOSITORY g-truc/glm
|
|
||||||
GIT_TAG 1.0.1
|
|
||||||
)
|
|
||||||
|
|
||||||
# --- tinyobjloader ---
|
|
||||||
CPMAddPackage(
|
|
||||||
NAME tinyobjloader
|
|
||||||
GITHUB_REPOSITORY tinyobjloader/tinyobjloader
|
|
||||||
GIT_TAG v2.0.0rc13
|
|
||||||
)
|
|
||||||
|
|
||||||
# --- stb_image (kein CMake-Projekt, nur Header) ---
|
|
||||||
CPMAddPackage(
|
|
||||||
NAME stb
|
|
||||||
GITHUB_REPOSITORY nothings/stb
|
|
||||||
GIT_TAG master
|
|
||||||
DOWNLOAD_ONLY YES
|
|
||||||
)
|
|
||||||
add_library(stb_image STATIC third_party/stb_image_impl.cpp)
|
|
||||||
target_include_directories(stb_image PUBLIC ${stb_SOURCE_DIR})
|
|
||||||
|
|
||||||
# --- Dear ImGui (Core + GLFW/OpenGL3 Backend) ---
|
|
||||||
CPMAddPackage(
|
|
||||||
NAME imgui
|
|
||||||
GITHUB_REPOSITORY ocornut/imgui
|
|
||||||
GIT_TAG v1.91.5
|
|
||||||
DOWNLOAD_ONLY YES
|
|
||||||
)
|
|
||||||
|
|
||||||
CPMAddPackage(
|
|
||||||
NAME spdlog
|
|
||||||
GITHUB_REPOSITORY gabime/spdlog
|
|
||||||
GIT_TAG v1.15.3
|
|
||||||
)
|
|
||||||
|
|
||||||
# --- GoogleTest ---
|
|
||||||
CPMAddPackage(
|
|
||||||
NAME googletest
|
|
||||||
GITHUB_REPOSITORY google/googletest
|
|
||||||
GIT_TAG v1.15.2
|
|
||||||
OPTIONS
|
|
||||||
"INSTALL_GTEST OFF"
|
|
||||||
"gtest_force_shared_crt ON"
|
|
||||||
)
|
|
||||||
|
|
||||||
enable_testing()
|
|
||||||
|
|
||||||
add_library(imgui STATIC
|
|
||||||
${imgui_SOURCE_DIR}/imgui.cpp
|
|
||||||
${imgui_SOURCE_DIR}/imgui_draw.cpp
|
|
||||||
${imgui_SOURCE_DIR}/imgui_tables.cpp
|
|
||||||
${imgui_SOURCE_DIR}/imgui_widgets.cpp
|
|
||||||
${imgui_SOURCE_DIR}/imgui_demo.cpp
|
|
||||||
${imgui_SOURCE_DIR}/backends/imgui_impl_glfw.cpp
|
|
||||||
${imgui_SOURCE_DIR}/backends/imgui_impl_opengl3.cpp
|
|
||||||
)
|
|
||||||
target_include_directories(imgui PUBLIC ${imgui_SOURCE_DIR} ${imgui_SOURCE_DIR}/backends)
|
|
||||||
target_link_libraries(imgui PUBLIC glfw glad)
|
|
||||||
|
|
||||||
# --- GLAD (manuell generiert, siehe README/Hinweis unten) ---
|
|
||||||
add_library(glad STATIC third_party/glad/src/glad.c)
|
|
||||||
target_include_directories(glad PUBLIC third_party/glad/include)
|
|
||||||
|
|
||||||
# --- OpenAL-Soft ---
|
|
||||||
CPMAddPackage(
|
|
||||||
NAME openal-soft
|
|
||||||
GITHUB_REPOSITORY kcat/openal-soft
|
|
||||||
GIT_TAG 1.24.3
|
|
||||||
OPTIONS
|
|
||||||
"LIBTYPE STATIC"
|
|
||||||
"ALSOFT_UTILS OFF"
|
|
||||||
"ALSOFT_EXAMPLES OFF"
|
|
||||||
"ALSOFT_TESTS OFF"
|
|
||||||
"ALSOFT_INSTALL OFF"
|
|
||||||
)
|
|
||||||
|
|
||||||
# --- dr_libs (dr_wav.h, dr_mp3.h – header-only) ---
|
|
||||||
CPMAddPackage(
|
|
||||||
NAME dr_libs
|
|
||||||
GITHUB_REPOSITORY mackron/dr_libs
|
|
||||||
GIT_TAG master
|
|
||||||
DOWNLOAD_ONLY YES
|
|
||||||
)
|
|
||||||
|
|
||||||
message(STATUS "dr_libs_SOURCE_DIR = ${dr_libs_SOURCE_DIR}")
|
|
||||||
|
|
||||||
add_subdirectory(external/NetworkCore)
|
|
||||||
|
|
||||||
# Engine als statische Lib
|
|
||||||
add_library(Engine STATIC
|
|
||||||
engine/src/core/Window.h
|
|
||||||
engine/src/core/Window.cpp
|
|
||||||
engine/src/core/Application.cpp
|
|
||||||
engine/src/core/Application.h
|
|
||||||
engine/src/core/EngineConfig.h
|
|
||||||
engine/src/utils/openglWrapper/GLStateCache.cpp
|
|
||||||
engine/src/utils/openglWrapper/GLStateCache.h
|
|
||||||
engine/src/utils/openglWrapper/GLRenderState.cpp
|
|
||||||
engine/src/utils/openglWrapper/GLRenderState.h
|
|
||||||
engine/src/utils/openglWrapper/openglObjects/Attribute.cpp
|
|
||||||
engine/src/utils/openglWrapper/openglObjects/Attribute.h
|
|
||||||
engine/src/utils/openglWrapper/openglObjects/Vbo.cpp
|
|
||||||
engine/src/utils/openglWrapper/openglObjects/Vbo.h
|
|
||||||
engine/src/utils/openglWrapper/openglObjects/Vao.cpp
|
|
||||||
engine/src/utils/openglWrapper/openglObjects/Vao.h
|
|
||||||
engine/src/utils/openglWrapper/shader/ShaderProgram.cpp
|
|
||||||
engine/src/utils/openglWrapper/shader/ShaderProgram.h
|
|
||||||
engine/src/renderer/primitives/SphereFactory.cpp
|
|
||||||
engine/src/renderer/primitives/SphereFactory.h
|
|
||||||
engine/src/utils/openglWrapper/shader/Uniform.cpp
|
|
||||||
engine/src/utils/openglWrapper/shader/Uniform.h
|
|
||||||
engine/src/utils/openglWrapper/shader/UniformValue.cpp
|
|
||||||
engine/src/utils/openglWrapper/shader/UniformValue.h
|
|
||||||
engine/src/layer/Scene.cpp
|
|
||||||
engine/src/layer/Scene.h
|
|
||||||
engine/src/loader/AssetLoader.cpp
|
|
||||||
engine/src/loader/AssetLoader.h
|
|
||||||
engine/src/loader/assets/AssetTypes.h
|
|
||||||
engine/src/loader/assets/AssetRequests.h
|
|
||||||
engine/src/loader/assets/AssetRequests.cpp
|
|
||||||
engine/src/loader/assets/RawAssetData.h
|
|
||||||
engine/src/loader/assets/AssetFormatters.h
|
|
||||||
engine/src/loader/textures/TextureUploader.cpp
|
|
||||||
engine/src/loader/textures/TextureUploader.h
|
|
||||||
engine/src/loader/textures/TextureImporter.cpp
|
|
||||||
engine/src/loader/textures/TextureImporter.h
|
|
||||||
engine/src/loader/textures/Texture2D.cpp
|
|
||||||
engine/src/loader/textures/Texture2D.h
|
|
||||||
engine/src/loader/models/ModelImporter.cpp
|
|
||||||
engine/src/loader/models/ModelImporter.h
|
|
||||||
engine/src/loader/models/ModelUploader.cpp
|
|
||||||
engine/src/loader/models/ModelUploader.h
|
|
||||||
engine/src/loader/models/Material.cpp
|
|
||||||
engine/src/loader/models/Material.h
|
|
||||||
engine/src/loader/assets/LoadedAssets.h
|
|
||||||
engine/src/loader/models/Model.cpp
|
|
||||||
engine/src/loader/models/Model.h
|
|
||||||
engine/src/loader/models/MeshSection.cpp
|
|
||||||
engine/src/loader/models/MeshSection.h
|
|
||||||
engine/src/loader/assets/AssetManager.cpp
|
|
||||||
engine/src/loader/assets/AssetManager.h
|
|
||||||
engine/src/renderer/entities/PointLight.cpp
|
|
||||||
engine/src/renderer/entities/PointLight.h
|
|
||||||
engine/src/core/inputsOutputs/inputs/MouseButton.h
|
|
||||||
engine/src/core/inputsOutputs/inputs/Mouse.cpp
|
|
||||||
engine/src/core/inputsOutputs/inputs/Mouse.h
|
|
||||||
engine/src/core/inputsOutputs/inputs/Keyboard.cpp
|
|
||||||
engine/src/core/inputsOutputs/inputs/Keyboard.h
|
|
||||||
engine/src/core/inputsOutputs/context/InputContextStack.cpp
|
|
||||||
engine/src/core/inputsOutputs/context/InputContextStack.h
|
|
||||||
engine/src/core/inputsOutputs/controller/CameraController.cpp
|
|
||||||
engine/src/core/inputsOutputs/controller/CameraController.h
|
|
||||||
engine/src/game/GameState.cpp
|
|
||||||
engine/src/game/GameState.h
|
|
||||||
engine/src/game/GameMode.cpp
|
|
||||||
engine/src/game/GameMode.h
|
|
||||||
engine/src/game/TurnBasedGameMode.cpp
|
|
||||||
engine/src/game/TurnBasedGameMode.h
|
|
||||||
engine/src/ecs/standardComponents/PickableComponent.h
|
|
||||||
engine/src/ecs/systems/PickingSystem.cpp
|
|
||||||
engine/src/ecs/systems/PickingSystem.h
|
|
||||||
engine/src/ui/ImGuiContext.cpp
|
|
||||||
engine/src/ui/ImGuiContext.h
|
|
||||||
engine/src/renderer/shader/BoundingDebugShader.cpp
|
|
||||||
engine/src/renderer/shader/BoundingDebugShader.h
|
|
||||||
engine/src/renderer/DebugRenderer.cpp
|
|
||||||
engine/src/renderer/DebugRenderer.h
|
|
||||||
engine/src/layer/DebugLayer.cpp
|
|
||||||
engine/src/layer/DebugLayer.h
|
|
||||||
engine/src/loader/models/AABB.cpp
|
|
||||||
engine/src/loader/models/AABB.h
|
|
||||||
engine/src/loader/models/Ray.h
|
|
||||||
engine/src/ecs/standardComponents/HighlightComponent.h
|
|
||||||
third_party/audio_impl.cpp
|
|
||||||
engine/src/core/audio/AudioDevice.cpp
|
|
||||||
engine/src/core/audio/AudioDevice.h
|
|
||||||
engine/src/core/audio/SoundBuffer.cpp
|
|
||||||
engine/src/core/audio/SoundBuffer.h
|
|
||||||
engine/src/core/audio/SoundSource.cpp
|
|
||||||
engine/src/core/audio/SoundSource.h
|
|
||||||
engine/src/loader/sounds/SoundUploader.cpp
|
|
||||||
engine/src/loader/sounds/SoundUploader.h
|
|
||||||
engine/src/core/animation/components/TransformAnimationComponent.h
|
|
||||||
engine/src/core/animation/AnimationSystem.cpp
|
|
||||||
engine/src/core/animation/AnimationSystem.h
|
|
||||||
engine/src/renderer/shader/StaticShader.cpp
|
|
||||||
engine/src/renderer/shader/StaticShader.h
|
|
||||||
engine/src/renderer/entities/Camera.cpp
|
|
||||||
engine/src/renderer/entities/Camera.h
|
|
||||||
engine/src/ecs/EntityRegistry.cpp
|
|
||||||
engine/src/ecs/EntityRegistry.h
|
|
||||||
engine/src/ecs/Entity.cpp
|
|
||||||
engine/src/ecs/Entity.h
|
|
||||||
engine/src/ecs/ComponentPool.cpp
|
|
||||||
engine/src/ecs/ComponentPool.h
|
|
||||||
engine/src/ecs/standardComponents/TransformComponent.h
|
|
||||||
engine/src/ecs/standardComponents/MeshComponent.h
|
|
||||||
engine/src/ecs/EntitySystem.cpp
|
|
||||||
engine/src/ecs/EntitySystem.h
|
|
||||||
engine/src/renderer/RenderSystem.cpp
|
|
||||||
engine/src/renderer/RenderSystem.h
|
|
||||||
engine/src/renderer/RenderQueue.cpp
|
|
||||||
engine/src/renderer/RenderQueue.h
|
|
||||||
engine/src/renderer/MeshRenderSystem.cpp
|
|
||||||
engine/src/renderer/MeshRenderSystem.h
|
|
||||||
engine/src/renderer/MeshRenderer.cpp
|
|
||||||
engine/src/renderer/MeshRenderer.h
|
|
||||||
engine/src/layer/Layer.cpp
|
|
||||||
engine/src/layer/Layer.h
|
|
||||||
engine/src/core/inputsOutputs/context/InputContext.cpp
|
|
||||||
engine/src/core/inputsOutputs/context/InputContext.h
|
|
||||||
engine/src/layer/SceneManager.cpp
|
|
||||||
engine/src/layer/SceneManager.h
|
|
||||||
engine/src/core/events/EventBus.cpp
|
|
||||||
engine/src/core/events/EventBus.h
|
|
||||||
engine/src/core/audio/ecs/PlaySoundComponent.h
|
|
||||||
engine/src/core/animation/events/AnimationMarkerEvent.h
|
|
||||||
engine/src/core/animation/components/BlockingAnimationComponent.h
|
|
||||||
engine/src/core/audio/ecs/AudioSystem.cpp
|
|
||||||
engine/src/core/audio/ecs/AudioSystem.h
|
|
||||||
engine/src/core/audio/ecs/BlockingSoundComponent.h
|
|
||||||
engine/src/renderer/shader/GuiShader.cpp
|
|
||||||
engine/src/renderer/shader/GuiShader.h
|
|
||||||
engine/src/renderer/primitives/QuadFactory.cpp
|
|
||||||
engine/src/renderer/primitives/QuadFactory.h
|
|
||||||
engine/src/loader/models/SimpleTexturedMesh.cpp
|
|
||||||
engine/src/loader/models/SimpleTexturedMesh.h
|
|
||||||
engine/src/loader/models/Mesh.cpp
|
|
||||||
engine/src/loader/models/Mesh.h
|
|
||||||
engine/src/renderer/GuiRenderer.cpp
|
|
||||||
engine/src/renderer/GuiRenderer.h
|
|
||||||
engine/src/renderer/ui/GUITexture.cpp
|
|
||||||
engine/src/renderer/ui/GUITexture.h
|
|
||||||
engine/src/core/events/ApplicationEvents.h
|
|
||||||
engine/src/core/events/EventChannels.cpp
|
|
||||||
engine/src/core/events/EventChannels.h
|
|
||||||
engine/src/core/events/ApplicationEvents.cpp
|
|
||||||
)
|
|
||||||
target_include_directories(Engine PUBLIC engine/src ${dr_libs_SOURCE_DIR})
|
|
||||||
target_link_libraries(Engine PUBLIC OpenGL::GL glfw glad glm::glm imgui spdlog::spdlog tinyobjloader stb_image OpenAL::OpenAL NetworkCore)
|
|
||||||
|
|
||||||
# --- GameLib: Spiel-Logik, unabhängig von main.cpp testbar ---
|
|
||||||
add_library(GameLib STATIC
|
|
||||||
game/src/ColorRaceApp.cpp
|
|
||||||
game/src/ColorRaceApp.h
|
|
||||||
game/src/gameLayer/GameLayer.cpp
|
|
||||||
game/src/gameLayer/GameLayer.h
|
|
||||||
game/src/GameScene.cpp
|
|
||||||
game/src/GameScene.h
|
|
||||||
game/src/ludo/LudoGameState.cpp
|
|
||||||
game/src/ludo/LudoGameState.h
|
|
||||||
game/src/ludo/LudoTypes.h
|
|
||||||
game/src/ludo/LudoGameMode.cpp
|
|
||||||
game/src/ludo/LudoGameMode.h
|
|
||||||
game/src/ludo/BoardLayout.cpp
|
|
||||||
game/src/ludo/BoardLayout.h
|
|
||||||
game/src/ludo/PiecePresenter.cpp
|
|
||||||
game/src/ludo/PiecePresenter.h
|
|
||||||
game/src/ludo/LudoAiController.cpp
|
|
||||||
game/src/ludo/LudoAiController.h
|
|
||||||
game/src/ludo/ecs/highlight/HighlightSystem.cpp
|
|
||||||
game/src/ludo/ecs/highlight/HighlightSystem.h
|
|
||||||
game/src/AudioLayer.cpp
|
|
||||||
game/src/AudioLayer.h
|
|
||||||
game/src/ludo/DiceSource.cpp
|
|
||||||
game/src/ludo/DiceSource.h
|
|
||||||
game/src/ludo/PresentationGameState.cpp
|
|
||||||
game/src/ludo/PresentationGameState.h
|
|
||||||
game/src/gameLayer/GameRenderer.cpp
|
|
||||||
game/src/gameLayer/GameRenderer.h
|
|
||||||
game/src/gameLayer/gameController/LudoGameController.cpp
|
|
||||||
game/src/gameLayer/gameController/LudoGameController.h
|
|
||||||
game/src/gameLayer/LudoHud.cpp
|
|
||||||
game/src/gameLayer/LudoHud.h
|
|
||||||
game/src/gameLayer/GameInput.cpp
|
|
||||||
game/src/gameLayer/GameInput.h
|
|
||||||
game/src/gameLayer/gameController/LudoGameControllerContext.h
|
|
||||||
game/src/ludo/gameMode/LudoRules.cpp
|
|
||||||
game/src/ludo/gameMode/LudoRules.h
|
|
||||||
game/src/ludo/gameMode/PiecePathBuilder.cpp
|
|
||||||
game/src/ludo/gameMode/PiecePathBuilder.h
|
|
||||||
game/src/ludo/gameMode/PathNode.h
|
|
||||||
game/src/mainMenu/MainMenuScene.cpp
|
|
||||||
game/src/mainMenu/MainMenuScene.h
|
|
||||||
)
|
|
||||||
target_include_directories(GameLib PUBLIC game/src)
|
|
||||||
target_link_libraries(GameLib PUBLIC Engine)
|
|
||||||
|
|
||||||
add_subdirectory(server)
|
|
||||||
|
|
||||||
# --- Executable ---
|
|
||||||
add_executable(ColorRace
|
|
||||||
game/src/main.cpp
|
|
||||||
game/src/mainMenu/layer/MainMenuUiLayer.cpp
|
|
||||||
game/src/mainMenu/layer/MainMenuUiLayer.h
|
|
||||||
game/src/multiplayer/LudoGameClient.cpp
|
|
||||||
game/src/multiplayer/LudoGameClient.h
|
|
||||||
game/src/multiplayer/LudoNetworkEvents.h
|
|
||||||
game/src/multiplayer/lobby/LobbyScene.cpp
|
|
||||||
game/src/multiplayer/lobby/LobbyScene.h
|
|
||||||
game/src/multiplayer/lobby/LobbyUiLayer.cpp
|
|
||||||
game/src/multiplayer/lobby/LobbyUiLayer.h
|
|
||||||
)
|
|
||||||
|
|
||||||
target_link_libraries(ColorRace PRIVATE
|
|
||||||
Engine
|
|
||||||
GameLib
|
|
||||||
)
|
|
||||||
|
|
||||||
# --- Tests ---
|
|
||||||
add_executable(ColorRaceTests
|
|
||||||
tests/LoduGameMode.cpp
|
|
||||||
tests/helpers/SequenceDiceSource.cpp
|
|
||||||
tests/helpers/SequenceDiceSource.h
|
|
||||||
)
|
|
||||||
|
|
||||||
target_link_libraries(ColorRaceTests PRIVATE
|
|
||||||
GameLib
|
|
||||||
GTest::gtest
|
|
||||||
GTest::gtest_main
|
|
||||||
)
|
|
||||||
|
|
||||||
include(GoogleTest)
|
|
||||||
gtest_discover_tests(ColorRaceTests)
|
|
||||||
|
|||||||
@ -1,62 +0,0 @@
|
|||||||
# Blender 5.2.0 LTS MTL File: 'GameBoard.blend'
|
|
||||||
# www.blender.org
|
|
||||||
|
|
||||||
newmtl Background
|
|
||||||
Ns 250.000000
|
|
||||||
Ka 1.000000 1.000000 1.000000
|
|
||||||
Ks 0.500000 0.500000 0.500000
|
|
||||||
Ke 0.000000 0.000000 0.000000
|
|
||||||
Ni 1.500000
|
|
||||||
d 1.000000
|
|
||||||
illum 2
|
|
||||||
map_Kd gameboard_brackground.png
|
|
||||||
|
|
||||||
newmtl Blue
|
|
||||||
Ns 250.000000
|
|
||||||
Ka 1.000000 1.000000 1.000000
|
|
||||||
Ks 0.500000 0.500000 0.500000
|
|
||||||
Ke 0.000000 0.000000 0.000000
|
|
||||||
Ni 1.500000
|
|
||||||
d 1.000000
|
|
||||||
illum 2
|
|
||||||
map_Kd chess_blue.png
|
|
||||||
|
|
||||||
newmtl Green
|
|
||||||
Ns 250.000000
|
|
||||||
Ka 1.000000 1.000000 1.000000
|
|
||||||
Ks 0.500000 0.500000 0.500000
|
|
||||||
Ke 0.000000 0.000000 0.000000
|
|
||||||
Ni 1.500000
|
|
||||||
d 1.000000
|
|
||||||
illum 2
|
|
||||||
map_Kd chess_green.png
|
|
||||||
|
|
||||||
newmtl Material
|
|
||||||
Ns 250.000000
|
|
||||||
Ka 1.000000 1.000000 1.000000
|
|
||||||
Ks 0.500000 0.500000 0.500000
|
|
||||||
Ke 0.000000 0.000000 0.000000
|
|
||||||
Ni 1.500000
|
|
||||||
d 1.000000
|
|
||||||
illum 2
|
|
||||||
map_Kd track.jpg
|
|
||||||
|
|
||||||
newmtl Red
|
|
||||||
Ns 250.000000
|
|
||||||
Ka 1.000000 1.000000 1.000000
|
|
||||||
Ks 0.500000 0.500000 0.500000
|
|
||||||
Ke 0.000000 0.000000 0.000000
|
|
||||||
Ni 1.500000
|
|
||||||
d 1.000000
|
|
||||||
illum 2
|
|
||||||
map_Kd chess_red.png
|
|
||||||
|
|
||||||
newmtl Yellow
|
|
||||||
Ns 250.000000
|
|
||||||
Ka 1.000000 1.000000 1.000000
|
|
||||||
Ks 0.500000 0.500000 0.500000
|
|
||||||
Ke 0.000000 0.000000 0.000000
|
|
||||||
Ni 1.500000
|
|
||||||
d 1.000000
|
|
||||||
illum 2
|
|
||||||
map_Kd chess_yellow.png
|
|
||||||
@ -1,12 +0,0 @@
|
|||||||
# Blender 5.2.0 LTS MTL File: 'None'
|
|
||||||
# www.blender.org
|
|
||||||
|
|
||||||
newmtl Material.002
|
|
||||||
Ns 735.817688
|
|
||||||
Ka 1.000000 1.000000 1.000000
|
|
||||||
Ks 0.500000 0.500000 0.500000
|
|
||||||
Ke 0.000000 0.000000 0.000000
|
|
||||||
Ni 1.450000
|
|
||||||
d 1.000000
|
|
||||||
illum 2
|
|
||||||
map_Kd chess_blue.png
|
|
||||||
@ -1,12 +0,0 @@
|
|||||||
# Blender 5.2.0 LTS MTL File: 'None'
|
|
||||||
# www.blender.org
|
|
||||||
|
|
||||||
newmtl Material.002
|
|
||||||
Ns 735.817688
|
|
||||||
Ka 1.000000 1.000000 1.000000
|
|
||||||
Ks 0.500000 0.500000 0.500000
|
|
||||||
Ke 0.000000 0.000000 0.000000
|
|
||||||
Ni 1.450000
|
|
||||||
d 1.000000
|
|
||||||
illum 2
|
|
||||||
map_Kd chess_blue.png
|
|
||||||
|
Before Width: | Height: | Size: 367 B |
@ -1,12 +0,0 @@
|
|||||||
# Blender 5.2.0 LTS MTL File: 'None'
|
|
||||||
# www.blender.org
|
|
||||||
|
|
||||||
newmtl Material.002
|
|
||||||
Ns 735.817688
|
|
||||||
Ka 1.000000 1.000000 1.000000
|
|
||||||
Ks 0.500000 0.500000 0.500000
|
|
||||||
Ke 0.000000 0.000000 0.000000
|
|
||||||
Ni 1.450000
|
|
||||||
d 1.000000
|
|
||||||
illum 2
|
|
||||||
map_Kd chess_green.png
|
|
||||||
|
Before Width: | Height: | Size: 368 B |
@ -1,12 +0,0 @@
|
|||||||
# Blender 5.2.0 LTS MTL File: 'None'
|
|
||||||
# www.blender.org
|
|
||||||
|
|
||||||
newmtl Material.002
|
|
||||||
Ns 735.817688
|
|
||||||
Ka 1.000000 1.000000 1.000000
|
|
||||||
Ks 0.500000 0.500000 0.500000
|
|
||||||
Ke 0.000000 0.000000 0.000000
|
|
||||||
Ni 1.450000
|
|
||||||
d 1.000000
|
|
||||||
illum 2
|
|
||||||
map_Kd chess_red.png
|
|
||||||
|
Before Width: | Height: | Size: 366 B |
@ -1,12 +0,0 @@
|
|||||||
# Blender 5.2.0 LTS MTL File: 'None'
|
|
||||||
# www.blender.org
|
|
||||||
|
|
||||||
newmtl Material.002
|
|
||||||
Ns 735.817688
|
|
||||||
Ka 1.000000 1.000000 1.000000
|
|
||||||
Ks 0.500000 0.500000 0.500000
|
|
||||||
Ke 0.000000 0.000000 0.000000
|
|
||||||
Ni 1.450000
|
|
||||||
d 1.000000
|
|
||||||
illum 2
|
|
||||||
map_Kd chess_yellow.png
|
|
||||||
|
Before Width: | Height: | Size: 367 B |
|
Before Width: | Height: | Size: 369 B |
|
Before Width: | Height: | Size: 351 KiB |
@ -1,41 +0,0 @@
|
|||||||
#version 460 core
|
|
||||||
|
|
||||||
in vec2 pass_textureCoords;
|
|
||||||
in vec3 surfaceNormal;
|
|
||||||
in vec3 worldPos;
|
|
||||||
|
|
||||||
uniform sampler2D diffuseSampler;
|
|
||||||
uniform float opacity;
|
|
||||||
uniform float shininess;
|
|
||||||
|
|
||||||
uniform vec3 lightPosition;
|
|
||||||
uniform vec3 lightColor;
|
|
||||||
uniform vec3 cameraPosition;
|
|
||||||
|
|
||||||
uniform vec3 highlightColor;
|
|
||||||
uniform float highlightIntensity;
|
|
||||||
|
|
||||||
out vec4 fragColor;
|
|
||||||
|
|
||||||
|
|
||||||
void main() {
|
|
||||||
vec3 normal = normalize(surfaceNormal);
|
|
||||||
vec3 lightDir = normalize(lightPosition - worldPos);
|
|
||||||
vec3 camDir = normalize(cameraPosition - worldPos);
|
|
||||||
vec3 reflectDir = reflect(-lightDir, normal);
|
|
||||||
|
|
||||||
vec3 ambient = 0.1 * lightColor;
|
|
||||||
|
|
||||||
float diff = max(dot(normal, lightDir) , 0.0f);
|
|
||||||
vec3 diffuse = diff * lightColor;
|
|
||||||
|
|
||||||
float spec = pow(max(dot(camDir, reflectDir), 0.0), max(shininess, 1.0f));
|
|
||||||
vec3 specular = 0.5 * spec * lightColor;
|
|
||||||
|
|
||||||
vec4 texColor = texture(diffuseSampler, pass_textureCoords);
|
|
||||||
fragColor = vec4((ambient + diffuse + specular) * texColor.rgb, texColor.a * opacity);
|
|
||||||
|
|
||||||
float intensity = clamp(highlightIntensity, 0.0, 1.0);
|
|
||||||
|
|
||||||
fragColor.rgb += highlightColor * intensity;
|
|
||||||
}
|
|
||||||
@ -1,22 +0,0 @@
|
|||||||
#version 460 core
|
|
||||||
layout(location = 0) in vec3 position;
|
|
||||||
layout(location = 1) in vec3 normal;
|
|
||||||
layout(location = 2) in vec2 textureCoords;
|
|
||||||
|
|
||||||
uniform mat4 transformationMatrix;
|
|
||||||
uniform mat4 projectionMatrix;
|
|
||||||
uniform mat4 viewMatrix;
|
|
||||||
|
|
||||||
out vec2 pass_textureCoords;
|
|
||||||
out vec3 surfaceNormal;
|
|
||||||
out vec3 worldPos;
|
|
||||||
|
|
||||||
void main() {
|
|
||||||
vec4 worldPosition = transformationMatrix * vec4(position, 1.0f);
|
|
||||||
gl_Position = projectionMatrix * viewMatrix * worldPosition;
|
|
||||||
pass_textureCoords = textureCoords;
|
|
||||||
|
|
||||||
surfaceNormal = mat3(transpose(inverse(transformationMatrix))) * normal;
|
|
||||||
worldPos = worldPosition.xyz;
|
|
||||||
|
|
||||||
}
|
|
||||||
@ -1,8 +0,0 @@
|
|||||||
#version 460 core
|
|
||||||
|
|
||||||
uniform vec3 color;
|
|
||||||
|
|
||||||
out vec4 fragColor;
|
|
||||||
void main() {
|
|
||||||
fragColor = vec4(color, 1.0f);
|
|
||||||
}
|
|
||||||
@ -1,14 +0,0 @@
|
|||||||
#version 460 core
|
|
||||||
layout(location = 0) in vec3 position;
|
|
||||||
layout(location = 1) in vec3 normal;
|
|
||||||
layout(location = 2) in vec2 textureCoords;
|
|
||||||
|
|
||||||
uniform mat4 transformationMatrix;
|
|
||||||
uniform mat4 projectionMatrix;
|
|
||||||
uniform mat4 viewMatrix;
|
|
||||||
|
|
||||||
void main() {
|
|
||||||
vec4 worldPosition = transformationMatrix * vec4(position, 1.0f);
|
|
||||||
gl_Position = projectionMatrix * viewMatrix * worldPosition;
|
|
||||||
|
|
||||||
}
|
|
||||||
@ -1,11 +0,0 @@
|
|||||||
#version 460 core
|
|
||||||
|
|
||||||
in vec2 textureCoords;
|
|
||||||
|
|
||||||
out vec4 color;
|
|
||||||
|
|
||||||
uniform sampler2D guiTexture;
|
|
||||||
|
|
||||||
void main() {
|
|
||||||
color = texture(guiTexture, textureCoords);
|
|
||||||
}
|
|
||||||
@ -1,12 +0,0 @@
|
|||||||
#version 460 core
|
|
||||||
|
|
||||||
layout(location = 0) in vec2 position;
|
|
||||||
|
|
||||||
out vec2 textureCoords;
|
|
||||||
|
|
||||||
uniform mat4 transformationMatrix;
|
|
||||||
|
|
||||||
void main() {
|
|
||||||
gl_Position = transformationMatrix * vec4(position, 0.0, 1.0);
|
|
||||||
textureCoords = vec2((position.x + 1.0) / 2.0, (position.y + 1.0) / 2.0);
|
|
||||||
}
|
|
||||||
|
Before Width: | Height: | Size: 1.8 MiB |
|
Before Width: | Height: | Size: 1.8 MiB |
|
Before Width: | Height: | Size: 1.8 MiB |
|
Before Width: | Height: | Size: 1.7 MiB |
@ -1,60 +0,0 @@
|
|||||||
//
|
|
||||||
// Created by sebastian on 29.07.26.
|
|
||||||
//
|
|
||||||
|
|
||||||
#include "Application.h"
|
|
||||||
#include <glad/glad.h>
|
|
||||||
#include <GLFW/glfw3.h>
|
|
||||||
|
|
||||||
#include "utils/openglWrapper/GLStateCache.h"
|
|
||||||
|
|
||||||
namespace engine {
|
|
||||||
Application::Application(const EngineConfig& config)
|
|
||||||
: m_config(config),
|
|
||||||
m_window(std::make_unique<Window>(config)),
|
|
||||||
m_inputContextStack(),
|
|
||||||
m_keyboard(*m_window),
|
|
||||||
m_mouse(*m_window),
|
|
||||||
m_sceneManager(m_inputContextStack),
|
|
||||||
m_applicationEventBus(std::make_shared<EventBus<ApplicationEvents>>()) {
|
|
||||||
m_applicationEventBus->subscribe([this](ApplicationEvents& event) {
|
|
||||||
std::visit([this](auto&& e) {
|
|
||||||
using T = std::decay_t<decltype(e)>;
|
|
||||||
if constexpr (std::is_same_v<T, QuitRequested>) {
|
|
||||||
m_window->requestWindowClose();
|
|
||||||
} else if constexpr (std::is_same_v<T, SceneSwitchRequested>) {
|
|
||||||
m_sceneManager.switchTo(std::move(e.nextScene), std::move(e.onSceneLoaded));
|
|
||||||
}
|
|
||||||
}, event);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
Application::~Application() = default;
|
|
||||||
|
|
||||||
void Application::run() {
|
|
||||||
auto lastTime = static_cast<float>(glfwGetTime());
|
|
||||||
|
|
||||||
while (!m_window->shouldClose()) {
|
|
||||||
const auto currentTime = static_cast<float>(glfwGetTime());
|
|
||||||
const float deltaTime = currentTime - lastTime;
|
|
||||||
lastTime = currentTime;
|
|
||||||
|
|
||||||
m_window->pollEvents();
|
|
||||||
|
|
||||||
|
|
||||||
m_imguiContext.beginFrame();
|
|
||||||
|
|
||||||
onUpdate(deltaTime);
|
|
||||||
|
|
||||||
GLStateCache::clearFrameBuffer(m_config.clearColor);
|
|
||||||
|
|
||||||
onRender();
|
|
||||||
|
|
||||||
m_imguiContext.endFrame();
|
|
||||||
m_window->swapBuffers();
|
|
||||||
|
|
||||||
m_keyboard.update();
|
|
||||||
m_mouse.update();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@ -1,57 +0,0 @@
|
|||||||
//
|
|
||||||
// Created by sebastian on 29.07.26.
|
|
||||||
//
|
|
||||||
|
|
||||||
#ifndef COLORRACE_APPLICATION_H
|
|
||||||
#define COLORRACE_APPLICATION_H
|
|
||||||
#include <memory>
|
|
||||||
#include <string>
|
|
||||||
|
|
||||||
#include "EngineConfig.h"
|
|
||||||
|
|
||||||
#include "Window.h"
|
|
||||||
#include "audio/AudioDevice.h"
|
|
||||||
#include "events/ApplicationEvents.h"
|
|
||||||
#include "inputsOutputs/context/InputContextStack.h"
|
|
||||||
#include "inputsOutputs/inputs/Keyboard.h"
|
|
||||||
#include "inputsOutputs/inputs/Mouse.h"
|
|
||||||
#include "layer/SceneManager.h"
|
|
||||||
#include "ui/ImGuiContext.h"
|
|
||||||
|
|
||||||
|
|
||||||
namespace engine {
|
|
||||||
class Application {
|
|
||||||
public:
|
|
||||||
Application(const EngineConfig& config);
|
|
||||||
virtual ~Application();
|
|
||||||
|
|
||||||
void run();
|
|
||||||
void requestClose();
|
|
||||||
|
|
||||||
protected:
|
|
||||||
virtual void onUpdate(float deltaTime) {}
|
|
||||||
virtual void onRender() {}
|
|
||||||
InputContextStack& getInputContextStack() { return m_inputContextStack; }
|
|
||||||
SceneManager& getSceneManager() { return m_sceneManager; }
|
|
||||||
Keyboard& getKeyboard() { return m_keyboard; }
|
|
||||||
Mouse& getMouse() { return m_mouse; }
|
|
||||||
|
|
||||||
std::shared_ptr<EventBus<ApplicationEvents>> m_applicationEventBus;
|
|
||||||
private:
|
|
||||||
EngineConfig m_config;
|
|
||||||
std::unique_ptr<Window> m_window;
|
|
||||||
InputContextStack m_inputContextStack;
|
|
||||||
Keyboard m_keyboard{*m_window}; // braucht Window& im Konstruktor
|
|
||||||
Mouse m_mouse{*m_window};
|
|
||||||
SceneManager m_sceneManager{m_inputContextStack};
|
|
||||||
ImGuiContext m_imguiContext{*m_window}; // neu
|
|
||||||
engine::audio::AudioDevice m_audioDevice;
|
|
||||||
|
|
||||||
};
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
#endif //COLORRACE_APPLICATION_H
|
|
||||||
@ -1,28 +0,0 @@
|
|||||||
//
|
|
||||||
// Created by sebastian on 29.07.26.
|
|
||||||
//
|
|
||||||
|
|
||||||
#ifndef COLORRACE_ENGINECONFIG_H
|
|
||||||
#define COLORRACE_ENGINECONFIG_H
|
|
||||||
#include <string>
|
|
||||||
|
|
||||||
#include "glm/vec4.hpp"
|
|
||||||
|
|
||||||
namespace engine {
|
|
||||||
struct EngineConfig {
|
|
||||||
int windowWidth = 1280;
|
|
||||||
int windowHeight = 720;
|
|
||||||
std::string windowTitle = "Engine";
|
|
||||||
|
|
||||||
bool fullscreen = false;
|
|
||||||
bool vsync = true;
|
|
||||||
bool msaa = true;
|
|
||||||
int msaaSamples = 4;
|
|
||||||
|
|
||||||
glm::vec4 clearColor = {0.1f, 0.1f, 0.15f, 1.0f};
|
|
||||||
|
|
||||||
bool debugContext = true; // GL_DEBUG_OUTPUT an/aus
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
#endif //COLORRACE_ENGINECONFIG_H
|
|
||||||
@ -1,91 +0,0 @@
|
|||||||
//
|
|
||||||
// Created by sebastian on 29.07.26.
|
|
||||||
//
|
|
||||||
|
|
||||||
#include "Window.h"
|
|
||||||
|
|
||||||
#include <iostream>
|
|
||||||
|
|
||||||
#include "EngineConfig.h"
|
|
||||||
#include "glad/glad.h"
|
|
||||||
#include "GLFW/glfw3.h"
|
|
||||||
#include "utils/openglWrapper/GLStateCache.h"
|
|
||||||
|
|
||||||
namespace engine {
|
|
||||||
static void GLAPIENTRY DebugCallback(GLenum source, GLenum type, GLuint id,
|
|
||||||
GLenum severity, GLsizei length,
|
|
||||||
const GLchar* message, const void* userParam) {
|
|
||||||
if (severity == GL_DEBUG_SEVERITY_NOTIFICATION) return; // Spam raus
|
|
||||||
std::cerr << "[GL DEBUG] " << message << "\n";
|
|
||||||
}
|
|
||||||
|
|
||||||
Window::Window(const EngineConfig& config) {
|
|
||||||
if (!glfwInit()) throw std::runtime_error("GLFW init failed");
|
|
||||||
|
|
||||||
glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 4);
|
|
||||||
glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 6);
|
|
||||||
glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);
|
|
||||||
glfwWindowHint(GLFW_OPENGL_DEBUG_CONTEXT, config.debugContext ? GLFW_TRUE : GLFW_FALSE);
|
|
||||||
|
|
||||||
if (config.msaa) {
|
|
||||||
glfwWindowHint(GLFW_SAMPLES, config.msaaSamples);
|
|
||||||
}
|
|
||||||
|
|
||||||
GLFWmonitor* monitor = config.fullscreen ? glfwGetPrimaryMonitor() : nullptr;
|
|
||||||
m_handle = glfwCreateWindow(config.windowWidth, config.windowHeight, config.windowTitle.c_str(), monitor, nullptr);
|
|
||||||
if (!m_handle) {
|
|
||||||
glfwTerminate();
|
|
||||||
throw std::runtime_error("Window creation failed");
|
|
||||||
}
|
|
||||||
|
|
||||||
glfwMakeContextCurrent(m_handle);
|
|
||||||
glfwSwapInterval(config.vsync ? 1 : 0); // VSync
|
|
||||||
|
|
||||||
if (!gladLoadGLLoader((GLADloadproc)glfwGetProcAddress)) {
|
|
||||||
throw std::runtime_error("GLAD init failed");
|
|
||||||
}
|
|
||||||
|
|
||||||
GLStateCache::init();
|
|
||||||
|
|
||||||
if (config.debugContext) {
|
|
||||||
std::cout << "Debug Context should be enabled" << std::endl;
|
|
||||||
glEnable(GL_DEBUG_OUTPUT);
|
|
||||||
glEnable(GL_DEBUG_OUTPUT_SYNCHRONOUS);
|
|
||||||
glDebugMessageCallback(DebugCallback, nullptr);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (config.msaa) {
|
|
||||||
glEnable(GL_MULTISAMPLE);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
glViewport(0, 0, config.windowWidth, config.windowHeight);
|
|
||||||
glfwSetWindowUserPointer(m_handle, &m_callbackTarget);
|
|
||||||
}
|
|
||||||
|
|
||||||
Window::~Window() {
|
|
||||||
glfwDestroyWindow(m_handle);
|
|
||||||
glfwTerminate();
|
|
||||||
}
|
|
||||||
|
|
||||||
bool Window::shouldClose() const { return glfwWindowShouldClose(m_handle); }
|
|
||||||
void Window::swapBuffers() { glfwSwapBuffers(m_handle); }
|
|
||||||
void Window::pollEvents() { glfwPollEvents(); }
|
|
||||||
|
|
||||||
int Window::getWidth() const {
|
|
||||||
int width, height;
|
|
||||||
glfwGetFramebufferSize(m_handle, &width, &height);
|
|
||||||
return width;
|
|
||||||
}
|
|
||||||
|
|
||||||
int Window::getHeight() const {
|
|
||||||
int width, height;
|
|
||||||
glfwGetFramebufferSize(m_handle, &width, &height);
|
|
||||||
return height;
|
|
||||||
}
|
|
||||||
|
|
||||||
void Window::requestWindowClose() {
|
|
||||||
glfwSetWindowShouldClose(m_handle, true);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@ -1,51 +0,0 @@
|
|||||||
//
|
|
||||||
// Created by sebastian on 29.07.26.
|
|
||||||
//
|
|
||||||
|
|
||||||
#ifndef COLORRACE_WINDOW_H
|
|
||||||
#define COLORRACE_WINDOW_H
|
|
||||||
|
|
||||||
#pragma once
|
|
||||||
#include <string>
|
|
||||||
|
|
||||||
#include "EngineConfig.h"
|
|
||||||
|
|
||||||
|
|
||||||
struct GLFWwindow;
|
|
||||||
|
|
||||||
namespace engine {
|
|
||||||
class Keyboard;
|
|
||||||
class Mouse;
|
|
||||||
|
|
||||||
class Window {
|
|
||||||
public:
|
|
||||||
struct CallbackTarget {
|
|
||||||
Mouse* mouse = nullptr;
|
|
||||||
Keyboard* keyboard = nullptr;
|
|
||||||
};
|
|
||||||
Window(const EngineConfig& config);
|
|
||||||
~Window();
|
|
||||||
|
|
||||||
bool shouldClose() const;
|
|
||||||
void swapBuffers();
|
|
||||||
void pollEvents();
|
|
||||||
|
|
||||||
[[nodiscard]] GLFWwindow* getHandle() const { return m_handle; }
|
|
||||||
[[nodiscard]] int getWidth() const;
|
|
||||||
[[nodiscard]] int getHeight() const;
|
|
||||||
|
|
||||||
void setMouse(Mouse* mouse) { m_callbackTarget.mouse = mouse; }
|
|
||||||
void setKeyboard(Keyboard* keyboard) { m_callbackTarget.keyboard = keyboard; }
|
|
||||||
|
|
||||||
void requestWindowClose();
|
|
||||||
private:
|
|
||||||
GLFWwindow* m_handle;
|
|
||||||
CallbackTarget m_callbackTarget;
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
#endif //COLORRACE_WINDOW_H
|
|
||||||
@ -1,53 +0,0 @@
|
|||||||
//
|
|
||||||
// Created by sebastian on 04.08.26.
|
|
||||||
//
|
|
||||||
|
|
||||||
#include "AnimationSystem.h"
|
|
||||||
|
|
||||||
#include <map>
|
|
||||||
|
|
||||||
#include "components/TransformAnimationComponent.h"
|
|
||||||
#include "ecs/standardComponents/TransformComponent.h"
|
|
||||||
|
|
||||||
namespace engine::animation {
|
|
||||||
void animation::AnimationSystem::update(float deltaTime) {
|
|
||||||
std::vector<engine::Entity> toRemove;
|
|
||||||
for (auto& [entity, animation] : m_registry.getPool<TransformAnimationComponent>()) {
|
|
||||||
animation.time += deltaTime;
|
|
||||||
|
|
||||||
while (animation.nextMarkerIndex < animation.markers.size() && animation.markers[animation.nextMarkerIndex].time <= animation.time) {
|
|
||||||
animation.markers[animation.nextMarkerIndex].callback();
|
|
||||||
animation.nextMarkerIndex++;
|
|
||||||
}
|
|
||||||
|
|
||||||
auto& transform = m_registry.getComponent<TransformComponent>(entity);
|
|
||||||
|
|
||||||
if (!animation.position.keys.empty()) {
|
|
||||||
transform.m_position = evaluate(animation.position, animation.time);
|
|
||||||
}
|
|
||||||
if (!animation.rotation.keys.empty()) {
|
|
||||||
transform.m_rotation = evaluate(animation.rotation, animation.time);
|
|
||||||
}
|
|
||||||
if (!animation.scale.keys.empty()) {
|
|
||||||
transform.m_scale = evaluate(animation.scale, animation.time);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (animation.time >= animation.duration) {
|
|
||||||
if (animation.loop) {
|
|
||||||
animation.time = 0.f;
|
|
||||||
animation.nextMarkerIndex = 0;
|
|
||||||
} else {
|
|
||||||
if (animation.onFinished) {
|
|
||||||
animation.onFinished();
|
|
||||||
}
|
|
||||||
animation.finished = true;
|
|
||||||
toRemove.push_back(entity);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
for (auto entity : toRemove) {
|
|
||||||
m_registry.removeComponent<TransformAnimationComponent>(entity);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} // engine
|
|
||||||
@ -1,60 +0,0 @@
|
|||||||
//
|
|
||||||
// Created by sebastian on 04.08.26.
|
|
||||||
//
|
|
||||||
|
|
||||||
#ifndef COLORRACE_ANIMATIONSYSTEM_H
|
|
||||||
#define COLORRACE_ANIMATIONSYSTEM_H
|
|
||||||
#include "components/TransformAnimationComponent.h"
|
|
||||||
#include "ecs/EntityRegistry.h"
|
|
||||||
#include "glm/glm.hpp"
|
|
||||||
namespace engine::animation {
|
|
||||||
class AnimationSystem {
|
|
||||||
public:
|
|
||||||
explicit AnimationSystem(EntityRegistry& registry) : m_registry(registry) {}
|
|
||||||
void update(float deltaTime);
|
|
||||||
private:
|
|
||||||
EntityRegistry& m_registry;
|
|
||||||
|
|
||||||
template<typename T>
|
|
||||||
T evaluate(const AnimationTrack<T>& track, float time) {
|
|
||||||
Keyframe<T> a;
|
|
||||||
Keyframe<T> b;
|
|
||||||
findSurroundingKeys(track, time, a, b);
|
|
||||||
|
|
||||||
if (a.time == b.time) return a.value;
|
|
||||||
|
|
||||||
float localT = (time - a.time) / (b.time - a.time);
|
|
||||||
float easedT = a.easingFunction(localT);
|
|
||||||
return glm::mix(a.value, b.value, easedT);
|
|
||||||
}
|
|
||||||
|
|
||||||
template<typename T>
|
|
||||||
void findSurroundingKeys(const AnimationTrack<T>& track, float time, Keyframe<T>& a, Keyframe<T>& b) {
|
|
||||||
if (track.keys.size() == 1) {
|
|
||||||
a = b = track.keys.front();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (time <= track.keys.front().time) {
|
|
||||||
a = b = track.keys.front();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (time >= track.keys.back().time) {
|
|
||||||
a = b = track.keys.back();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
for (size_t i = 1; i < track.keys.size(); ++i) {
|
|
||||||
if (track.keys[i - 1].time <= time && track.keys[i].time >= time) {
|
|
||||||
a = track.keys[i - 1];
|
|
||||||
b = track.keys[i];
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
};
|
|
||||||
} // engine
|
|
||||||
|
|
||||||
#endif //COLORRACE_ANIMATIONSYSTEM_H
|
|
||||||
@ -1,11 +0,0 @@
|
|||||||
//
|
|
||||||
// Created by sebastian on 05.08.26.
|
|
||||||
//
|
|
||||||
|
|
||||||
#ifndef COLORRACE_BLOCKINGANIMATIONCOMPONENT_H
|
|
||||||
#define COLORRACE_BLOCKINGANIMATIONCOMPONENT_H
|
|
||||||
namespace engine::animation {
|
|
||||||
struct BlockingAnimationComponent {
|
|
||||||
};
|
|
||||||
}
|
|
||||||
#endif //COLORRACE_BLOCKINGANIMATIONCOMPONENT_H
|
|
||||||
@ -1,51 +0,0 @@
|
|||||||
//
|
|
||||||
// Created by sebastian on 04.08.26.
|
|
||||||
//
|
|
||||||
|
|
||||||
#ifndef COLORRACE_TRANSFORMANIMATIONCOMPONENT_H
|
|
||||||
#define COLORRACE_TRANSFORMANIMATIONCOMPONENT_H
|
|
||||||
|
|
||||||
#include <functional>
|
|
||||||
|
|
||||||
#include "glm/glm.hpp"
|
|
||||||
namespace engine::animation {
|
|
||||||
using EasingFunction = std::function<float(float)>;
|
|
||||||
|
|
||||||
template<typename T>
|
|
||||||
struct Keyframe {
|
|
||||||
float time;
|
|
||||||
T value;
|
|
||||||
|
|
||||||
EasingFunction easingFunction = [](float t) {
|
|
||||||
return t;
|
|
||||||
};
|
|
||||||
};
|
|
||||||
|
|
||||||
struct AnimationMarker {
|
|
||||||
float time;
|
|
||||||
std::function<void()> callback;
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
template<typename T>
|
|
||||||
struct AnimationTrack {
|
|
||||||
std::vector<Keyframe<T>> keys;
|
|
||||||
};
|
|
||||||
|
|
||||||
struct TransformAnimationComponent {
|
|
||||||
float time = 0.0f;
|
|
||||||
float duration = 0.0f;
|
|
||||||
|
|
||||||
AnimationTrack<glm::vec3> position;
|
|
||||||
AnimationTrack<glm::vec3> rotation;
|
|
||||||
AnimationTrack<glm::vec3> scale;
|
|
||||||
|
|
||||||
std::vector<AnimationMarker> markers;
|
|
||||||
size_t nextMarkerIndex = 0;
|
|
||||||
|
|
||||||
std::function<void()> onFinished;
|
|
||||||
bool loop = false;
|
|
||||||
bool finished = false;
|
|
||||||
};
|
|
||||||
}
|
|
||||||
#endif //COLORRACE_TRANSFORMANIMATIONCOMPONENT_H
|
|
||||||
@ -1,18 +0,0 @@
|
|||||||
//
|
|
||||||
// Created by sebastian on 05.08.26.
|
|
||||||
//
|
|
||||||
|
|
||||||
#ifndef COLORRACE_ANIMATIONMARKEREVENT_H
|
|
||||||
#define COLORRACE_ANIMATIONMARKEREVENT_H
|
|
||||||
#include <string>
|
|
||||||
|
|
||||||
#include "ecs/Entity.h"
|
|
||||||
|
|
||||||
namespace engine::animation {
|
|
||||||
struct AnimationMarkerEvent {
|
|
||||||
engine::Entity entity;
|
|
||||||
std::string tag;
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
#endif //COLORRACE_ANIMATIONMARKEREVENT_H
|
|
||||||
@ -1,24 +0,0 @@
|
|||||||
//
|
|
||||||
// Created by sebastian on 04.08.26.
|
|
||||||
//
|
|
||||||
|
|
||||||
#include "AudioDevice.h"
|
|
||||||
|
|
||||||
engine::audio::AudioDevice::AudioDevice() {
|
|
||||||
m_device = alcOpenDevice(nullptr);
|
|
||||||
if (!m_device) {
|
|
||||||
throw std::runtime_error("Kein Audio-Device gefunden");
|
|
||||||
}
|
|
||||||
|
|
||||||
m_context = alcCreateContext(m_device, nullptr);
|
|
||||||
if (!m_context) {
|
|
||||||
throw std::runtime_error("Kein Audio-Context gefunden");
|
|
||||||
}
|
|
||||||
alcMakeContextCurrent(m_context);
|
|
||||||
}
|
|
||||||
|
|
||||||
engine::audio::AudioDevice::~AudioDevice() {
|
|
||||||
alcMakeContextCurrent(nullptr);
|
|
||||||
if (m_context) alcDestroyContext(m_context);
|
|
||||||
if (m_device) alcCloseDevice(m_device);
|
|
||||||
}
|
|
||||||
@ -1,37 +0,0 @@
|
|||||||
//
|
|
||||||
// Created by sebastian on 04.08.26.
|
|
||||||
//
|
|
||||||
|
|
||||||
#ifndef COLORRACE_AUDIODEVICE_H
|
|
||||||
#define COLORRACE_AUDIODEVICE_H
|
|
||||||
#include <iostream>
|
|
||||||
#include <ostream>
|
|
||||||
|
|
||||||
#include "al.h"
|
|
||||||
#include "alc.h"
|
|
||||||
|
|
||||||
|
|
||||||
namespace engine::audio {
|
|
||||||
class AudioDevice {
|
|
||||||
public:
|
|
||||||
AudioDevice();
|
|
||||||
|
|
||||||
~AudioDevice();
|
|
||||||
// Kein Kopieren/Verschieben nötig für den Anfang
|
|
||||||
AudioDevice(const AudioDevice&) = delete;
|
|
||||||
AudioDevice& operator=(const AudioDevice&) = delete;
|
|
||||||
private:
|
|
||||||
ALCdevice* m_device = nullptr;
|
|
||||||
ALCcontext* m_context = nullptr;
|
|
||||||
};
|
|
||||||
|
|
||||||
inline void checkAlError(const char* location) {
|
|
||||||
ALenum err = alGetError();
|
|
||||||
if (err != AL_NO_ERROR) {
|
|
||||||
std::cerr << "OpenAL Error: " << alGetString(err) << " at " << location << std::endl;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
#endif //COLORRACE_AUDIODEVICE_H
|
|
||||||
@ -1,31 +0,0 @@
|
|||||||
//
|
|
||||||
// Created by sebastian on 04.08.26.
|
|
||||||
//
|
|
||||||
|
|
||||||
#include "SoundBuffer.h"
|
|
||||||
|
|
||||||
#include <dr_wav.h>
|
|
||||||
#include <stdexcept>
|
|
||||||
|
|
||||||
#include "AudioDevice.h"
|
|
||||||
|
|
||||||
namespace engine::audio {
|
|
||||||
SoundBuffer::~SoundBuffer() {
|
|
||||||
if (m_bufferID) alDeleteBuffers(1, &m_bufferID);
|
|
||||||
}
|
|
||||||
|
|
||||||
SoundBuffer::SoundBuffer(SoundBuffer &&other) noexcept : m_bufferID(other.m_bufferID) {
|
|
||||||
other.m_bufferID = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
SoundBuffer & SoundBuffer::operator=(SoundBuffer &&other) noexcept {
|
|
||||||
if (this != &other) {
|
|
||||||
release();
|
|
||||||
|
|
||||||
m_bufferID = other.m_bufferID;
|
|
||||||
other.m_bufferID = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
return *this;
|
|
||||||
}
|
|
||||||
} // engine
|
|
||||||
@ -1,39 +0,0 @@
|
|||||||
//
|
|
||||||
// Created by sebastian on 04.08.26.
|
|
||||||
//
|
|
||||||
|
|
||||||
#ifndef COLORRACE_SOUNDBUFFER_H
|
|
||||||
#define COLORRACE_SOUNDBUFFER_H
|
|
||||||
#include <string>
|
|
||||||
|
|
||||||
#include "al.h"
|
|
||||||
|
|
||||||
namespace engine::audio {
|
|
||||||
class SoundBuffer {
|
|
||||||
public:
|
|
||||||
explicit SoundBuffer(ALuint bufferID) : m_bufferID(bufferID) {}
|
|
||||||
~SoundBuffer();
|
|
||||||
|
|
||||||
SoundBuffer(const SoundBuffer&) = delete;
|
|
||||||
|
|
||||||
SoundBuffer& operator=(const SoundBuffer&) = delete;
|
|
||||||
|
|
||||||
SoundBuffer(SoundBuffer&& other) noexcept;
|
|
||||||
SoundBuffer& operator=(SoundBuffer&& other) noexcept;
|
|
||||||
|
|
||||||
ALuint id() const {
|
|
||||||
return m_bufferID;
|
|
||||||
}
|
|
||||||
private:
|
|
||||||
ALuint m_bufferID = 0;
|
|
||||||
|
|
||||||
void release() {
|
|
||||||
if (m_bufferID != 0) {
|
|
||||||
alDeleteBuffers(1, &m_bufferID);
|
|
||||||
m_bufferID = 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
} // engine
|
|
||||||
|
|
||||||
#endif //COLORRACE_SOUNDBUFFER_H
|
|
||||||
@ -1,8 +0,0 @@
|
|||||||
//
|
|
||||||
// Created by sebastian on 04.08.26.
|
|
||||||
//
|
|
||||||
|
|
||||||
#include "SoundSource.h"
|
|
||||||
|
|
||||||
namespace engine {
|
|
||||||
} // engine
|
|
||||||
@ -1,90 +0,0 @@
|
|||||||
//
|
|
||||||
// Created by sebastian on 04.08.26.
|
|
||||||
//
|
|
||||||
|
|
||||||
#ifndef COLORRACE_SOUNDSOURCE_H
|
|
||||||
#define COLORRACE_SOUNDSOURCE_H
|
|
||||||
#include "al.h"
|
|
||||||
#include "AudioDevice.h"
|
|
||||||
#include "SoundBuffer.h"
|
|
||||||
|
|
||||||
namespace engine::audio {
|
|
||||||
|
|
||||||
class SoundSource {
|
|
||||||
public:
|
|
||||||
SoundSource() {
|
|
||||||
alGenSources(1, &m_source);
|
|
||||||
}
|
|
||||||
|
|
||||||
~SoundSource() {
|
|
||||||
if (m_source) alDeleteSources(1, &m_source);
|
|
||||||
}
|
|
||||||
|
|
||||||
SoundSource(const SoundSource&) = delete;
|
|
||||||
SoundSource& operator=(const SoundSource&) = delete;
|
|
||||||
|
|
||||||
SoundSource(SoundSource&& other) noexcept
|
|
||||||
: m_source(other.m_source)
|
|
||||||
{
|
|
||||||
other.m_source = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
SoundSource& operator=(SoundSource&& other) noexcept
|
|
||||||
{
|
|
||||||
if (this != &other) {
|
|
||||||
release();
|
|
||||||
|
|
||||||
m_source = other.m_source;
|
|
||||||
other.m_source = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
return *this;
|
|
||||||
}
|
|
||||||
|
|
||||||
void setBuffer(const SoundBuffer& buffer) {
|
|
||||||
alSourcei(m_source, AL_BUFFER, static_cast<ALint>(buffer.id()));
|
|
||||||
checkAlError("alSourcei(AL_BUFFER)");
|
|
||||||
}
|
|
||||||
|
|
||||||
void setPosition(float x, float y, float z) {
|
|
||||||
alSource3f(m_source, AL_POSITION, x, y, z);
|
|
||||||
}
|
|
||||||
|
|
||||||
void setGain(float gain) {
|
|
||||||
alSourcef(m_source, AL_GAIN, gain);
|
|
||||||
}
|
|
||||||
|
|
||||||
void setLooping(bool loop) {
|
|
||||||
alSourcei(m_source, AL_LOOPING, loop ? AL_TRUE : AL_FALSE);
|
|
||||||
}
|
|
||||||
|
|
||||||
void play() { alSourcePlay(m_source); }
|
|
||||||
void stop() { alSourceStop(m_source); }
|
|
||||||
|
|
||||||
bool isPlaying() const {
|
|
||||||
ALint state;
|
|
||||||
alGetSourcei(m_source, AL_SOURCE_STATE, &state);
|
|
||||||
return state == AL_PLAYING;
|
|
||||||
}
|
|
||||||
private:
|
|
||||||
ALuint m_source = 0;
|
|
||||||
|
|
||||||
void release()
|
|
||||||
{
|
|
||||||
if (m_source != 0) {
|
|
||||||
alDeleteSources(1, &m_source);
|
|
||||||
m_source = 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
inline void updateListener(float px, float py, float pz,
|
|
||||||
float fx, float fy, float fz,
|
|
||||||
float ux, float uy, float uz) {
|
|
||||||
alListener3f(AL_POSITION, px, py, pz);
|
|
||||||
ALfloat orientation[] = { fx, fy, fz, ux, uy, uz };
|
|
||||||
alListenerfv(AL_ORIENTATION, orientation);
|
|
||||||
}
|
|
||||||
} // engine
|
|
||||||
|
|
||||||
#endif //COLORRACE_SOUNDSOURCE_H
|
|
||||||
@ -1,34 +0,0 @@
|
|||||||
//
|
|
||||||
// Created by sebastian on 05.08.26.
|
|
||||||
//
|
|
||||||
|
|
||||||
#include "AudioSystem.h"
|
|
||||||
|
|
||||||
#include "BlockingSoundComponent.h"
|
|
||||||
#include "PlaySoundComponent.h"
|
|
||||||
#include "core/audio/SoundSource.h"
|
|
||||||
|
|
||||||
void engine::audio::AudioSystem::update(float deltaTime) const {
|
|
||||||
std::vector<Entity> toRemove;
|
|
||||||
|
|
||||||
for (auto& [entity, playSound] : m_registry.getPool<PlaySoundComponent>()) {
|
|
||||||
auto& source = m_registry.getComponent<SoundSource>(entity);
|
|
||||||
if (!playSound.started) {
|
|
||||||
source.setGain(playSound.gain);
|
|
||||||
source.play();
|
|
||||||
playSound.started = true;
|
|
||||||
} else if (!source.isPlaying()) {
|
|
||||||
if (playSound.onFinished) {
|
|
||||||
playSound.onFinished();
|
|
||||||
}
|
|
||||||
toRemove.push_back(entity);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
for (auto entity : toRemove) {
|
|
||||||
m_registry.removeComponent<PlaySoundComponent>(entity);
|
|
||||||
if (m_registry.hasComponent<BlockingSoundComponent>(entity)) {
|
|
||||||
m_registry.removeComponent<BlockingSoundComponent>(entity);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@ -1,20 +0,0 @@
|
|||||||
//
|
|
||||||
// Created by sebastian on 05.08.26.
|
|
||||||
//
|
|
||||||
|
|
||||||
#ifndef COLORRACE_AUDIOSYSTEM_H
|
|
||||||
#define COLORRACE_AUDIOSYSTEM_H
|
|
||||||
#include "ecs/EntityRegistry.h"
|
|
||||||
|
|
||||||
|
|
||||||
namespace engine::audio {
|
|
||||||
class AudioSystem {
|
|
||||||
public:
|
|
||||||
explicit AudioSystem(EntityRegistry& registry) : m_registry(registry) {}
|
|
||||||
void update(float deltaTime) const;
|
|
||||||
private:
|
|
||||||
EntityRegistry& m_registry;
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
#endif //COLORRACE_AUDIOSYSTEM_H
|
|
||||||
@ -1,10 +0,0 @@
|
|||||||
//
|
|
||||||
// Created by sebastian on 05.08.26.
|
|
||||||
//
|
|
||||||
|
|
||||||
#ifndef COLORRACE_BLOCKINGSOUNDCOMPONENT_H
|
|
||||||
#define COLORRACE_BLOCKINGSOUNDCOMPONENT_H
|
|
||||||
namespace engine::audio {
|
|
||||||
struct BlockingSoundComponent {};
|
|
||||||
}
|
|
||||||
#endif //COLORRACE_BLOCKINGSOUNDCOMPONENT_H
|
|
||||||
@ -1,21 +0,0 @@
|
|||||||
//
|
|
||||||
// Created by sebastian on 05.08.26.
|
|
||||||
//
|
|
||||||
|
|
||||||
#ifndef COLORRACE_PLAYSOUNDCOMPONENT_H
|
|
||||||
#define COLORRACE_PLAYSOUNDCOMPONENT_H
|
|
||||||
#include <functional>
|
|
||||||
#include <memory>
|
|
||||||
|
|
||||||
#include "../SoundBuffer.h"
|
|
||||||
|
|
||||||
namespace engine::audio {
|
|
||||||
struct PlaySoundComponent {
|
|
||||||
float gain = 1.f;
|
|
||||||
bool started = false;
|
|
||||||
bool blocking = false;
|
|
||||||
std::function<void()> onFinished;
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
#endif //COLORRACE_PLAYSOUNDCOMPONENT_H
|
|
||||||
@ -1,14 +0,0 @@
|
|||||||
//
|
|
||||||
// Created by sebastian on 07.08.26.
|
|
||||||
//
|
|
||||||
#include "ApplicationEvents.h"
|
|
||||||
#include "layer/Scene.h" // hier ist Scene vollständig bekannt
|
|
||||||
|
|
||||||
SceneSwitchRequested::SceneSwitchRequested() = default;
|
|
||||||
|
|
||||||
SceneSwitchRequested::SceneSwitchRequested(std::unique_ptr<engine::Scene> scene, std::function<void()> callback) : nextScene(std::move(scene)), onSceneLoaded(std::move(callback)){
|
|
||||||
}
|
|
||||||
|
|
||||||
SceneSwitchRequested::~SceneSwitchRequested() = default;
|
|
||||||
SceneSwitchRequested::SceneSwitchRequested(SceneSwitchRequested&&) noexcept = default;
|
|
||||||
SceneSwitchRequested& SceneSwitchRequested::operator=(SceneSwitchRequested&&) noexcept = default;
|
|
||||||
@ -1,31 +0,0 @@
|
|||||||
//
|
|
||||||
// Created by sebastian on 06.08.26.
|
|
||||||
//
|
|
||||||
|
|
||||||
#ifndef COLORRACE_APPLICATIONEVENTS_H
|
|
||||||
#define COLORRACE_APPLICATIONEVENTS_H
|
|
||||||
#include <functional>
|
|
||||||
#include <memory>
|
|
||||||
#include <variant>
|
|
||||||
|
|
||||||
|
|
||||||
namespace engine {
|
|
||||||
class Scene;
|
|
||||||
}
|
|
||||||
|
|
||||||
struct QuitRequested {};
|
|
||||||
|
|
||||||
struct SceneSwitchRequested {
|
|
||||||
std::unique_ptr<engine::Scene> nextScene;
|
|
||||||
std::function<void()> onSceneLoaded;
|
|
||||||
|
|
||||||
SceneSwitchRequested();
|
|
||||||
SceneSwitchRequested(std::unique_ptr<engine::Scene> scene, std::function<void()> callback);
|
|
||||||
~SceneSwitchRequested();
|
|
||||||
SceneSwitchRequested(SceneSwitchRequested&&) noexcept;
|
|
||||||
SceneSwitchRequested& operator=(SceneSwitchRequested&&) noexcept;
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
using ApplicationEvents = std::variant<QuitRequested, SceneSwitchRequested>;
|
|
||||||
#endif //COLORRACE_APPLICATIONEVENTS_H
|
|
||||||
@ -1,8 +0,0 @@
|
|||||||
//
|
|
||||||
// Created by sebastian on 05.08.26.
|
|
||||||
//
|
|
||||||
|
|
||||||
#include "EventBus.h"
|
|
||||||
|
|
||||||
namespace engine {
|
|
||||||
} // engine
|
|
||||||
@ -1,42 +0,0 @@
|
|||||||
//
|
|
||||||
// Created by sebastian on 05.08.26.
|
|
||||||
//
|
|
||||||
|
|
||||||
#ifndef COLORRACE_EVENTBUS_H
|
|
||||||
#define COLORRACE_EVENTBUS_H
|
|
||||||
#include <functional>
|
|
||||||
#include <mutex>
|
|
||||||
|
|
||||||
namespace engine {
|
|
||||||
class IEventBus {
|
|
||||||
public:
|
|
||||||
virtual ~IEventBus() = default;
|
|
||||||
};
|
|
||||||
|
|
||||||
template<typename Event>
|
|
||||||
class EventBus {
|
|
||||||
public:
|
|
||||||
using Handler = std::function<void(Event&)>;
|
|
||||||
|
|
||||||
void subscribe(Handler handler) {
|
|
||||||
std::lock_guard<std::mutex> lock(m_mutex);
|
|
||||||
m_handlers.push_back(handler);
|
|
||||||
}
|
|
||||||
|
|
||||||
void publish(Event& event) const {
|
|
||||||
std::vector<Handler> handlersCopy;
|
|
||||||
{
|
|
||||||
std::lock_guard<std::mutex> lock(m_mutex);
|
|
||||||
handlersCopy = m_handlers;
|
|
||||||
}
|
|
||||||
for (const auto& handler : handlersCopy) {
|
|
||||||
handler(event);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
private:
|
|
||||||
mutable std::mutex m_mutex;
|
|
||||||
std::vector<Handler> m_handlers;
|
|
||||||
};
|
|
||||||
} // engine
|
|
||||||
|
|
||||||
#endif //COLORRACE_EVENTBUS_H
|
|
||||||
@ -1,5 +0,0 @@
|
|||||||
//
|
|
||||||
// Created by sebastian on 06.08.26.
|
|
||||||
//
|
|
||||||
|
|
||||||
#include "EventChannels.h"
|
|
||||||
@ -1,43 +0,0 @@
|
|||||||
//
|
|
||||||
// Created by sebastian on 06.08.26.
|
|
||||||
//
|
|
||||||
|
|
||||||
#ifndef COLORRACE_EVENTCHANNELS_H
|
|
||||||
#define COLORRACE_EVENTCHANNELS_H
|
|
||||||
#include <memory>
|
|
||||||
#include <typeindex>
|
|
||||||
|
|
||||||
#include "EventBus.h"
|
|
||||||
|
|
||||||
|
|
||||||
namespace engine {
|
|
||||||
class EventChannels {
|
|
||||||
public:
|
|
||||||
template<typename Event>
|
|
||||||
void subscribe(typename EventBus<Event>::Handler handler) {
|
|
||||||
getBus<Event>().subscribe(std::move(handler));
|
|
||||||
}
|
|
||||||
|
|
||||||
template<typename Event>
|
|
||||||
void publish(Event& event) {
|
|
||||||
getBus<Event>().publish(event);
|
|
||||||
}
|
|
||||||
|
|
||||||
template<typename Event>
|
|
||||||
EventBus<Event>& getBus() {
|
|
||||||
auto key = std::type_index(typeid(Event));
|
|
||||||
auto it = m_buses.find(key);
|
|
||||||
if (it == m_buses.end()) {
|
|
||||||
auto bus = std::make_unique<EventBus<Event>>();
|
|
||||||
auto* ptr = bus.get();
|
|
||||||
m_buses.emplace(key, std::move(bus));
|
|
||||||
return *ptr;
|
|
||||||
}
|
|
||||||
return static_cast<EventBus<Event>&>(*it->second);
|
|
||||||
}
|
|
||||||
private:
|
|
||||||
std::unordered_map<std::type_index, std::unique_ptr<IEventBus>> m_buses;
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
#endif //COLORRACE_EVENTCHANNELS_H
|
|
||||||
@ -1,5 +0,0 @@
|
|||||||
//
|
|
||||||
// Created by sebastian on 02.08.26.
|
|
||||||
//
|
|
||||||
|
|
||||||
#include "InputContext.h"
|
|
||||||
@ -1,19 +0,0 @@
|
|||||||
//
|
|
||||||
// Created by sebastian on 02.08.26.
|
|
||||||
//
|
|
||||||
|
|
||||||
#ifndef COLORRACE_INPUTCONTEXT_H
|
|
||||||
#define COLORRACE_INPUTCONTEXT_H
|
|
||||||
|
|
||||||
|
|
||||||
namespace engine {
|
|
||||||
class InputContext {
|
|
||||||
public:
|
|
||||||
virtual ~InputContext() = default;
|
|
||||||
virtual void onActivate() {};
|
|
||||||
virtual void onDeactivate() {};
|
|
||||||
};
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
#endif //COLORRACE_INPUTCONTEXT_H
|
|
||||||
@ -1,24 +0,0 @@
|
|||||||
//
|
|
||||||
// Created by sebastian on 02.08.26.
|
|
||||||
//
|
|
||||||
|
|
||||||
#include "InputContextStack.h"
|
|
||||||
|
|
||||||
|
|
||||||
void engine::InputContextStack::push(std::shared_ptr<InputContext> context) {
|
|
||||||
if (!m_stack.empty()) m_stack.back()->onDeactivate();
|
|
||||||
context->onActivate();
|
|
||||||
m_stack.push_back(std::move(context));
|
|
||||||
}
|
|
||||||
|
|
||||||
void engine::InputContextStack::pop() {
|
|
||||||
if (m_stack.empty()) return;
|
|
||||||
m_stack.back()->onDeactivate();
|
|
||||||
m_stack.pop_back();
|
|
||||||
if (!m_stack.empty()) m_stack.back()->onActivate();
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
bool engine::InputContextStack::isActive(const InputContext &context) const {
|
|
||||||
return !m_stack.empty() && m_stack.back().get() == &context;
|
|
||||||
}
|
|
||||||
@ -1,25 +0,0 @@
|
|||||||
//
|
|
||||||
// Created by sebastian on 02.08.26.
|
|
||||||
//
|
|
||||||
|
|
||||||
#ifndef COLORRACE_INPUTCONTEXTSTACK_H
|
|
||||||
#define COLORRACE_INPUTCONTEXTSTACK_H
|
|
||||||
#include <memory>
|
|
||||||
#include <vector>
|
|
||||||
|
|
||||||
#include "InputContext.h"
|
|
||||||
|
|
||||||
|
|
||||||
namespace engine {
|
|
||||||
class InputContextStack {
|
|
||||||
public:
|
|
||||||
void push(std::shared_ptr<InputContext> context);
|
|
||||||
void pop();
|
|
||||||
[[nodiscard]] bool isActive(const InputContext& context) const;
|
|
||||||
private:
|
|
||||||
std::vector<std::shared_ptr<InputContext>> m_stack;
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
#endif //COLORRACE_INPUTCONTEXTSTACK_H
|
|
||||||
@ -1,23 +0,0 @@
|
|||||||
//
|
|
||||||
// Created by sebastian on 02.08.26.
|
|
||||||
//
|
|
||||||
|
|
||||||
#include "CameraController.h"
|
|
||||||
|
|
||||||
#include <iostream>
|
|
||||||
#include <ostream>
|
|
||||||
|
|
||||||
#include "GLFW/glfw3.h"
|
|
||||||
#include "glm/vec3.hpp"
|
|
||||||
#include "renderer/entities/Camera.h"
|
|
||||||
|
|
||||||
void engine::CameraController::update(const Keyboard &keyboard, Camera &camera, float deltaTime) {
|
|
||||||
if (!m_stack.isActive(*m_gameContext.get())) return;
|
|
||||||
|
|
||||||
|
|
||||||
if (keyboard.isKeyDown(GLFW_KEY_W)) camera.moveRelative(glm::vec3(0.0f, 0.0f, 1.0f), 10.0f, deltaTime);
|
|
||||||
if (keyboard.isKeyDown(GLFW_KEY_S)) camera.moveRelative(glm::vec3(0.0f, 0.0f, -1.0f), 10.0f, deltaTime);
|
|
||||||
if (keyboard.isKeyDown(GLFW_KEY_A)) camera.moveRelative(glm::vec3(-1.0f, 0.0f, 0.0f), 10.0f, deltaTime);
|
|
||||||
if (keyboard.isKeyDown(GLFW_KEY_D)) camera.moveRelative(glm::vec3(1.0f, 0.0f, 0.0f), 10.0f, deltaTime);
|
|
||||||
if (keyboard.isKeyDown(GLFW_KEY_SPACE)) camera.moveRelative(glm::vec3(0.0f, 1.0f, 0.0f), 10.0f, deltaTime);
|
|
||||||
}
|
|
||||||
@ -1,25 +0,0 @@
|
|||||||
//
|
|
||||||
// Created by sebastian on 02.08.26.
|
|
||||||
//
|
|
||||||
|
|
||||||
#ifndef COLORRACE_CAMERACONTROLLER_H
|
|
||||||
#define COLORRACE_CAMERACONTROLLER_H
|
|
||||||
#include "core/inputsOutputs/context/InputContextStack.h"
|
|
||||||
#include "core/inputsOutputs/inputs/Keyboard.h"
|
|
||||||
|
|
||||||
|
|
||||||
namespace engine {
|
|
||||||
class Camera;
|
|
||||||
|
|
||||||
class CameraController {
|
|
||||||
public:
|
|
||||||
CameraController(InputContextStack& stack, std::shared_ptr<InputContext> gameContext) : m_stack(stack), m_gameContext(std::move(gameContext)) {}
|
|
||||||
void update(const Keyboard& keyboard, Camera& camera, float deltaTime);
|
|
||||||
private:
|
|
||||||
InputContextStack& m_stack;
|
|
||||||
std::shared_ptr<InputContext> m_gameContext;
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
#endif //COLORRACE_CAMERACONTROLLER_H
|
|
||||||
@ -1,82 +0,0 @@
|
|||||||
//
|
|
||||||
// Created by sebastian on 02.08.26.
|
|
||||||
//
|
|
||||||
|
|
||||||
#include "Keyboard.h"
|
|
||||||
|
|
||||||
#include "imgui_impl_glfw.h"
|
|
||||||
#include "core/Window.h"
|
|
||||||
#include "GLFW/glfw3.h"
|
|
||||||
|
|
||||||
engine::Keyboard::Keyboard(engine::Window &window) {
|
|
||||||
window.setKeyboard(this);
|
|
||||||
addKeyListener(window);
|
|
||||||
addTextListener(window);
|
|
||||||
}
|
|
||||||
|
|
||||||
void engine::Keyboard::update() {
|
|
||||||
keysPressedThisFrame.clear();
|
|
||||||
keysRepeatedThisFrame.clear();
|
|
||||||
charsThisFrame.clear();
|
|
||||||
keysReleasedThisFrame.clear();
|
|
||||||
}
|
|
||||||
|
|
||||||
bool engine::Keyboard::isKeyDown(const int key) const {
|
|
||||||
return keysDown.contains(key);
|
|
||||||
}
|
|
||||||
|
|
||||||
const std::vector<int> & engine::Keyboard::getCharsThisFrame() {
|
|
||||||
return charsThisFrame;
|
|
||||||
}
|
|
||||||
|
|
||||||
auto engine::Keyboard::keyPressEvent(const int key) const -> bool {
|
|
||||||
return keysPressedThisFrame.contains(key);
|
|
||||||
}
|
|
||||||
|
|
||||||
auto engine::Keyboard::keyPressEvent(const int key, bool checkRepeats) const -> bool {
|
|
||||||
return keysPressedThisFrame.contains(key) || (checkRepeats && keysRepeatedThisFrame.contains(key));
|
|
||||||
}
|
|
||||||
|
|
||||||
bool engine::Keyboard::keyReleaseEvent(const int key) const {
|
|
||||||
return keysReleasedThisFrame.contains(key);
|
|
||||||
}
|
|
||||||
|
|
||||||
void engine::Keyboard::addTextListener(Window &window) {
|
|
||||||
glfwSetCharCallback(window.getHandle(), [](GLFWwindow* handle, unsigned int key) {
|
|
||||||
ImGui_ImplGlfw_CharCallback(handle, key);
|
|
||||||
auto* target = static_cast<Window::CallbackTarget*>(glfwGetWindowUserPointer(handle));
|
|
||||||
if (!target || !target->keyboard) return;
|
|
||||||
|
|
||||||
target->keyboard->reportChar(key);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
void engine::Keyboard::addKeyListener(Window &window) {
|
|
||||||
glfwSetKeyCallback(window.getHandle(), [](GLFWwindow* handle, int key, int scancode, int action, int mods) {
|
|
||||||
ImGui_ImplGlfw_KeyCallback(handle, key, scancode, action, mods);
|
|
||||||
auto* target = static_cast<Window::CallbackTarget*>(glfwGetWindowUserPointer(handle));
|
|
||||||
if (!target || !target->keyboard) return;
|
|
||||||
|
|
||||||
if (action == GLFW_PRESS) target->keyboard->reportKeyPress(key);
|
|
||||||
else if (action == GLFW_RELEASE) target->keyboard->reportKeyRelease(key);
|
|
||||||
else if (action == GLFW_REPEAT) target->keyboard->reportKeyRepeat(key);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
void engine::Keyboard::reportKeyPress(int key) {
|
|
||||||
keysDown.insert(key);
|
|
||||||
keysPressedThisFrame.insert(key);
|
|
||||||
}
|
|
||||||
|
|
||||||
void engine::Keyboard::reportKeyRelease(int key) {
|
|
||||||
keysDown.erase(key);
|
|
||||||
keysReleasedThisFrame.insert(key);
|
|
||||||
}
|
|
||||||
|
|
||||||
void engine::Keyboard::reportKeyRepeat(int key) {
|
|
||||||
keysRepeatedThisFrame.insert(key);
|
|
||||||
}
|
|
||||||
|
|
||||||
void engine::Keyboard::reportChar(int key) {
|
|
||||||
charsThisFrame.push_back(key);
|
|
||||||
}
|
|
||||||
@ -1,46 +0,0 @@
|
|||||||
//
|
|
||||||
// Created by sebastian on 02.08.26.
|
|
||||||
//
|
|
||||||
|
|
||||||
#ifndef COLORRACE_KEYBOARD_H
|
|
||||||
#define COLORRACE_KEYBOARD_H
|
|
||||||
#include <unordered_set>
|
|
||||||
#include <vector>
|
|
||||||
|
|
||||||
namespace engine {
|
|
||||||
class Window;
|
|
||||||
}
|
|
||||||
|
|
||||||
namespace engine {
|
|
||||||
|
|
||||||
class Keyboard {
|
|
||||||
public:
|
|
||||||
explicit Keyboard(engine::Window& window);
|
|
||||||
|
|
||||||
void update();
|
|
||||||
bool isKeyDown(int key) const;
|
|
||||||
|
|
||||||
const std::vector<int> &getCharsThisFrame();
|
|
||||||
|
|
||||||
bool keyPressEvent(int key) const;
|
|
||||||
bool keyPressEvent(int key, bool checkRepeats) const;
|
|
||||||
bool keyReleaseEvent(int key) const;
|
|
||||||
private:
|
|
||||||
std::unordered_set<int> keysPressedThisFrame;
|
|
||||||
std::unordered_set<int> keysRepeatedThisFrame;
|
|
||||||
std::unordered_set<int> keysReleasedThisFrame;
|
|
||||||
std::unordered_set<int> keysDown;
|
|
||||||
std::vector<int> charsThisFrame;
|
|
||||||
|
|
||||||
void addTextListener(Window& window);
|
|
||||||
|
|
||||||
void addKeyListener(Window& window);
|
|
||||||
void reportKeyPress(int key);
|
|
||||||
void reportKeyRelease(int key);
|
|
||||||
void reportKeyRepeat(int key);
|
|
||||||
void reportChar(int key);
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
#endif //COLORRACE_KEYBOARD_H
|
|
||||||
@ -1,124 +0,0 @@
|
|||||||
//
|
|
||||||
// Created by sebastian on 02.08.26.
|
|
||||||
//
|
|
||||||
|
|
||||||
#include "Mouse.h"
|
|
||||||
|
|
||||||
#include "imgui_impl_glfw.h"
|
|
||||||
#include "core/Window.h"
|
|
||||||
#include "GLFW/glfw3.h"
|
|
||||||
#include "spdlog/spdlog.h"
|
|
||||||
|
|
||||||
engine::Mouse::Mouse(Window &window) {
|
|
||||||
window.setMouse(this);
|
|
||||||
addClickListener(window);
|
|
||||||
addMoveListener(window);
|
|
||||||
addScrollListener(window);
|
|
||||||
}
|
|
||||||
|
|
||||||
bool engine::Mouse::isButtonDown(const MouseButton button) const {
|
|
||||||
return buttonsDown.contains(MouseButtonToInt(button));
|
|
||||||
}
|
|
||||||
|
|
||||||
bool engine::Mouse::isClickEvent(const MouseButton button) const {
|
|
||||||
return buttonsClickedThisFrame.contains(MouseButtonToInt(button));
|
|
||||||
}
|
|
||||||
|
|
||||||
bool engine::Mouse::isReleaseEvent(const MouseButton button) const {
|
|
||||||
return buttonsReleasedThisFrame.contains(MouseButtonToInt(button));
|
|
||||||
}
|
|
||||||
|
|
||||||
float engine::Mouse::getX(const bool ndc) const {
|
|
||||||
return ndc ? 2 * x - 1 : x;
|
|
||||||
}
|
|
||||||
|
|
||||||
float engine::Mouse::getY(const bool ndc) const {
|
|
||||||
return ndc ? 1 - 2 * y : y;
|
|
||||||
}
|
|
||||||
|
|
||||||
float engine::Mouse::getDX() const {
|
|
||||||
return dx;
|
|
||||||
}
|
|
||||||
|
|
||||||
float engine::Mouse::getDY() const {
|
|
||||||
return dy;
|
|
||||||
}
|
|
||||||
|
|
||||||
float engine::Mouse::getScroll() const {
|
|
||||||
return scroll;
|
|
||||||
}
|
|
||||||
|
|
||||||
void engine::Mouse::update() {
|
|
||||||
updateDetlas();
|
|
||||||
scroll = 0;
|
|
||||||
|
|
||||||
buttonsClickedThisFrame.clear();
|
|
||||||
buttonsReleasedThisFrame.clear();
|
|
||||||
}
|
|
||||||
|
|
||||||
glm::vec2 engine::Mouse::getXY(bool ndc) const {
|
|
||||||
return {getX(ndc), getY(ndc)};
|
|
||||||
}
|
|
||||||
|
|
||||||
void engine::Mouse::reportButtonClick(int button) {
|
|
||||||
spdlog::debug("Button {} clicked", button);
|
|
||||||
buttonsDown.insert(button);
|
|
||||||
buttonsClickedThisFrame.insert(button);
|
|
||||||
}
|
|
||||||
|
|
||||||
void engine::Mouse::reportButtonRelease(int button) {
|
|
||||||
buttonsDown.erase(button);
|
|
||||||
buttonsReleasedThisFrame.insert(button);
|
|
||||||
}
|
|
||||||
|
|
||||||
void engine::Mouse::updateDetlas() {
|
|
||||||
dx = x - lastX;
|
|
||||||
dy = y - lastY;
|
|
||||||
lastX = x;
|
|
||||||
lastY = y;
|
|
||||||
}
|
|
||||||
|
|
||||||
void engine::Mouse::addMoveListener(Window &window) {
|
|
||||||
glfwSetCursorPosCallback(window.getHandle(), [](GLFWwindow* handle, double xPos, double yPos) {
|
|
||||||
ImGui_ImplGlfw_CursorPosCallback(handle, xPos, yPos);
|
|
||||||
|
|
||||||
auto* target = static_cast<Window::CallbackTarget*>(glfwGetWindowUserPointer(handle));
|
|
||||||
if (!target || !target->mouse) return;
|
|
||||||
|
|
||||||
int width, height;
|
|
||||||
glfwGetFramebufferSize(handle, &width, &height);
|
|
||||||
target->mouse->x = static_cast<float>(xPos / width);
|
|
||||||
target->mouse->y = static_cast<float>(yPos / height);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
void engine::Mouse::addScrollListener(Window &window) {
|
|
||||||
glfwSetScrollCallback(window.getHandle(), [](GLFWwindow* handle, double xoff, double yoff) {
|
|
||||||
ImGui_ImplGlfw_ScrollCallback(handle, xoff, yoff);
|
|
||||||
|
|
||||||
auto* target = static_cast<Window::CallbackTarget*>(glfwGetWindowUserPointer(handle));
|
|
||||||
if (target && target->mouse) target->mouse->scroll = static_cast<float>(yoff);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
void engine::Mouse::addClickListener(Window &window) {
|
|
||||||
glfwSetMouseButtonCallback(window.getHandle(), [](GLFWwindow* handle, int button, int action, int mods) {
|
|
||||||
ImGui_ImplGlfw_MouseButtonCallback(handle, button, action, mods);
|
|
||||||
|
|
||||||
auto* target = static_cast<Window::CallbackTarget*>(glfwGetWindowUserPointer(handle));
|
|
||||||
if (!target || !target->mouse) return;
|
|
||||||
|
|
||||||
if (action == GLFW_PRESS) target->mouse->reportButtonClick(button);
|
|
||||||
else if (action == GLFW_RELEASE) target->mouse->reportButtonRelease(button);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
int engine::Mouse::MouseButtonToInt(MouseButton button) {
|
|
||||||
int glfwButton = 0;
|
|
||||||
switch (button) {
|
|
||||||
case MouseButton::LEFT: glfwButton = GLFW_MOUSE_BUTTON_LEFT; break;
|
|
||||||
case MouseButton::RIGHT: glfwButton = GLFW_MOUSE_BUTTON_RIGHT; break;
|
|
||||||
case MouseButton::MIDDLE: glfwButton = GLFW_MOUSE_BUTTON_MIDDLE; break;
|
|
||||||
}
|
|
||||||
return glfwButton;
|
|
||||||
}
|
|
||||||
@ -1,52 +0,0 @@
|
|||||||
//
|
|
||||||
// Created by sebastian on 02.08.26.
|
|
||||||
//
|
|
||||||
|
|
||||||
#ifndef COLORRACE_MOUSE_H
|
|
||||||
#define COLORRACE_MOUSE_H
|
|
||||||
#include <unordered_set>
|
|
||||||
|
|
||||||
#include "MouseButton.h"
|
|
||||||
#include "glm/vec2.hpp"
|
|
||||||
|
|
||||||
|
|
||||||
namespace engine {
|
|
||||||
class Window;
|
|
||||||
|
|
||||||
class Mouse {
|
|
||||||
public:
|
|
||||||
explicit Mouse(Window& window);
|
|
||||||
bool isButtonDown(MouseButton button) const;
|
|
||||||
bool isClickEvent(MouseButton button) const;
|
|
||||||
bool isReleaseEvent(MouseButton button) const;
|
|
||||||
float getX(bool ndc) const;
|
|
||||||
float getY(bool ndc) const;
|
|
||||||
float getDX() const;
|
|
||||||
float getDY() const;
|
|
||||||
float getScroll() const;
|
|
||||||
void update();
|
|
||||||
glm::vec2 getXY(bool ndc) const;
|
|
||||||
private:
|
|
||||||
std::unordered_set<int> buttonsDown;
|
|
||||||
std::unordered_set<int> buttonsClickedThisFrame;
|
|
||||||
std::unordered_set<int> buttonsReleasedThisFrame;
|
|
||||||
|
|
||||||
float x = 0.0f, y = 0.0f;
|
|
||||||
float dx = 0.0f, dy = 0.0f;
|
|
||||||
float scroll = 0.0f;
|
|
||||||
float lastX = 0.0f, lastY = 0.0f;
|
|
||||||
|
|
||||||
void reportButtonClick(int button);
|
|
||||||
void reportButtonRelease(int button);
|
|
||||||
void updateDetlas();
|
|
||||||
|
|
||||||
static void addMoveListener(Window& window);
|
|
||||||
static void addScrollListener(Window& window);
|
|
||||||
static void addClickListener(Window& window);
|
|
||||||
|
|
||||||
static int MouseButtonToInt(MouseButton button);
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
#endif //COLORRACE_MOUSE_H
|
|
||||||
@ -1,14 +0,0 @@
|
|||||||
//
|
|
||||||
// Created by sebastian on 02.08.26.
|
|
||||||
//
|
|
||||||
|
|
||||||
#ifndef COLORRACE_MOUSEBUTTON_H
|
|
||||||
#define COLORRACE_MOUSEBUTTON_H
|
|
||||||
namespace engine {
|
|
||||||
enum class MouseButton {
|
|
||||||
LEFT,
|
|
||||||
RIGHT,
|
|
||||||
MIDDLE
|
|
||||||
};
|
|
||||||
}
|
|
||||||
#endif //COLORRACE_MOUSEBUTTON_H
|
|
||||||
@ -1,5 +0,0 @@
|
|||||||
//
|
|
||||||
// Created by sebastian on 29.07.26.
|
|
||||||
//
|
|
||||||
|
|
||||||
#include "ComponentPool.h"
|
|
||||||
@ -1,50 +0,0 @@
|
|||||||
//
|
|
||||||
// Created by sebastian on 29.07.26.
|
|
||||||
//
|
|
||||||
|
|
||||||
#ifndef COLORRACE_COMPONENTPOOL_H
|
|
||||||
#define COLORRACE_COMPONENTPOOL_H
|
|
||||||
#include "Entity.h"
|
|
||||||
|
|
||||||
|
|
||||||
namespace engine {
|
|
||||||
class IComponentPool {
|
|
||||||
public:
|
|
||||||
virtual ~IComponentPool() = default;
|
|
||||||
virtual void remove(Entity entity) = 0;
|
|
||||||
virtual size_t size() = 0;
|
|
||||||
};
|
|
||||||
|
|
||||||
template<typename T>
|
|
||||||
class ComponentPool : public IComponentPool {
|
|
||||||
public:
|
|
||||||
void remove(Entity entity) override {
|
|
||||||
m_components.erase(entity);
|
|
||||||
}
|
|
||||||
|
|
||||||
void insert(Entity entity, T component) {
|
|
||||||
m_components[entity] = std::move(component);
|
|
||||||
}
|
|
||||||
|
|
||||||
[[nodiscard]] bool has(Entity entity) const {
|
|
||||||
return m_components.contains(entity);
|
|
||||||
}
|
|
||||||
|
|
||||||
T& get(Entity entity) {
|
|
||||||
return m_components.at(entity);
|
|
||||||
}
|
|
||||||
|
|
||||||
size_t size() override {
|
|
||||||
return m_components.size();
|
|
||||||
}
|
|
||||||
|
|
||||||
// Für Iteration in Systemen
|
|
||||||
auto begin() { return m_components.begin(); }
|
|
||||||
auto end() { return m_components.end(); }
|
|
||||||
|
|
||||||
private:
|
|
||||||
std::unordered_map<Entity, T> m_components;
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
#endif //COLORRACE_COMPONENTPOOL_H
|
|
||||||
@ -1,5 +0,0 @@
|
|||||||
//
|
|
||||||
// Created by sebastian on 29.07.26.
|
|
||||||
//
|
|
||||||
|
|
||||||
#include "Entity.h"
|
|
||||||
@ -1,39 +0,0 @@
|
|||||||
//
|
|
||||||
// Created by sebastian on 29.07.26.
|
|
||||||
//
|
|
||||||
|
|
||||||
#ifndef COLORRACE_ENTITY_H
|
|
||||||
#define COLORRACE_ENTITY_H
|
|
||||||
#include <cstdint>
|
|
||||||
#include <limits>
|
|
||||||
#include <functional> // <- das hier fehlt vermutlich
|
|
||||||
|
|
||||||
namespace engine {
|
|
||||||
class Entity {
|
|
||||||
public:
|
|
||||||
constexpr Entity() noexcept = default;
|
|
||||||
constexpr explicit Entity(std::uint32_t id) noexcept : m_id(id) {}
|
|
||||||
|
|
||||||
[[nodiscard]] constexpr std::uint32_t value() const noexcept { return m_id; }
|
|
||||||
|
|
||||||
constexpr bool operator==(const Entity&) const = default;
|
|
||||||
|
|
||||||
static constexpr Entity null() noexcept {
|
|
||||||
return Entity{std::numeric_limits<std::uint32_t>::max()};
|
|
||||||
}
|
|
||||||
|
|
||||||
private:
|
|
||||||
std::uint32_t m_id = std::numeric_limits<std::uint32_t>::max();
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
// Damit Entity in unordered_map als Key funktioniert
|
|
||||||
template<>
|
|
||||||
struct std::hash<engine::Entity> {
|
|
||||||
std::size_t operator()(const engine::Entity& e) const noexcept {
|
|
||||||
return std::hash<std::uint32_t>{}(e.value());
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
#endif //COLORRACE_ENTITY_H
|
|
||||||
@ -1,5 +0,0 @@
|
|||||||
//
|
|
||||||
// Created by sebastian on 29.07.26.
|
|
||||||
//
|
|
||||||
|
|
||||||
#include "EntityRegistry.h"
|
|
||||||
@ -1,70 +0,0 @@
|
|||||||
//
|
|
||||||
// Created by sebastian on 29.07.26.
|
|
||||||
//
|
|
||||||
|
|
||||||
#ifndef COLORRACE_ENTITYREGISTRY_H
|
|
||||||
#define COLORRACE_ENTITYREGISTRY_H
|
|
||||||
#include <cstdint>
|
|
||||||
#include <memory>
|
|
||||||
#include <typeindex>
|
|
||||||
#include <unordered_map>
|
|
||||||
|
|
||||||
#include "ComponentPool.h"
|
|
||||||
|
|
||||||
|
|
||||||
namespace engine {
|
|
||||||
class EntityRegistry {
|
|
||||||
public:
|
|
||||||
Entity createEntity() {
|
|
||||||
return Entity{m_nextId++};
|
|
||||||
}
|
|
||||||
|
|
||||||
void destroyEntity(Entity entity) {
|
|
||||||
for (auto& [type, pool] : m_pools) {
|
|
||||||
pool->remove(entity);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
template<typename T>
|
|
||||||
void addComponent(Entity entity, T component) {
|
|
||||||
getPool<T>().insert(entity, std::move(component));
|
|
||||||
}
|
|
||||||
|
|
||||||
template<typename T>
|
|
||||||
void removeComponent(Entity entity) {
|
|
||||||
getPool<T>().remove(entity);
|
|
||||||
}
|
|
||||||
|
|
||||||
template<typename T>
|
|
||||||
[[nodiscard]] bool hasComponent(Entity entity) {
|
|
||||||
auto key = std::type_index(typeid(T));
|
|
||||||
auto it = m_pools.find(key);
|
|
||||||
if (it == m_pools.end()) return false;
|
|
||||||
return static_cast<ComponentPool<T>&>(*it->second).has(entity);
|
|
||||||
}
|
|
||||||
|
|
||||||
template<typename T>
|
|
||||||
T& getComponent(Entity entity) {
|
|
||||||
return getPool<T>().get(entity);
|
|
||||||
}
|
|
||||||
|
|
||||||
template<typename T>
|
|
||||||
ComponentPool<T>& getPool() {
|
|
||||||
auto key = std::type_index(typeid(T));
|
|
||||||
auto it = m_pools.find(key);
|
|
||||||
if (it == m_pools.end()) {
|
|
||||||
auto pool = std::make_unique<ComponentPool<T>>();
|
|
||||||
auto* ptr = pool.get();
|
|
||||||
m_pools.emplace(key, std::move(pool));
|
|
||||||
return *ptr;
|
|
||||||
}
|
|
||||||
return static_cast<ComponentPool<T>&>(*it->second);
|
|
||||||
}
|
|
||||||
private:
|
|
||||||
std::uint32_t m_nextId = 0;
|
|
||||||
std::pmr::unordered_map<std::type_index, std::unique_ptr<IComponentPool>> m_pools;
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
#endif //COLORRACE_ENTITYREGISTRY_H
|
|
||||||
@ -1,5 +0,0 @@
|
|||||||
//
|
|
||||||
// Created by sebastian on 29.07.26.
|
|
||||||
//
|
|
||||||
|
|
||||||
#include "EntitySystem.h"
|
|
||||||
@ -1,18 +0,0 @@
|
|||||||
//
|
|
||||||
// Created by sebastian on 29.07.26.
|
|
||||||
//
|
|
||||||
|
|
||||||
#ifndef COLORRACE_ENTITYSYSTEM_H
|
|
||||||
#define COLORRACE_ENTITYSYSTEM_H
|
|
||||||
#include "EntityRegistry.h"
|
|
||||||
|
|
||||||
|
|
||||||
class EntitySystem {
|
|
||||||
public:
|
|
||||||
virtual ~EntitySystem() = default;
|
|
||||||
|
|
||||||
virtual void update(engine::EntityRegistry& registry, float deltaTime) = 0;
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
#endif //COLORRACE_ENTITYSYSTEM_H
|
|
||||||
@ -1,16 +0,0 @@
|
|||||||
//
|
|
||||||
// Created by sebastian on 04.08.26.
|
|
||||||
//
|
|
||||||
|
|
||||||
#ifndef COLORRACE_HIGHLIGHTCOMPONENT_H
|
|
||||||
#define COLORRACE_HIGHLIGHTCOMPONENT_H
|
|
||||||
#include "glm/glm.hpp"
|
|
||||||
|
|
||||||
namespace engine {
|
|
||||||
struct HighlightComponent {
|
|
||||||
glm::vec3 highlightColor;
|
|
||||||
float intensity;
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
#endif //COLORRACE_HIGHLIGHTCOMPONENT_H
|
|
||||||
@ -1,16 +0,0 @@
|
|||||||
//
|
|
||||||
// Created by sebastian on 29.07.26.
|
|
||||||
//
|
|
||||||
|
|
||||||
#ifndef COLORRACE_MESHCOMPONENT_H
|
|
||||||
#define COLORRACE_MESHCOMPONENT_H
|
|
||||||
#include <memory>
|
|
||||||
|
|
||||||
#include "loader/models/Model.h"
|
|
||||||
|
|
||||||
namespace engine {
|
|
||||||
struct MeshComponent {
|
|
||||||
std::shared_ptr<Model> model;
|
|
||||||
};
|
|
||||||
}
|
|
||||||
#endif //COLORRACE_MESHCOMPONENT_H
|
|
||||||
@ -1,15 +0,0 @@
|
|||||||
//
|
|
||||||
// Created by sebastian on 02.08.26.
|
|
||||||
//
|
|
||||||
|
|
||||||
#ifndef COLORRACE_PICKABLECOMPONENT_H
|
|
||||||
#define COLORRACE_PICKABLECOMPONENT_H
|
|
||||||
|
|
||||||
|
|
||||||
namespace engine {
|
|
||||||
struct PickableComponent {
|
|
||||||
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
#endif //COLORRACE_PICKABLECOMPONENT_H
|
|
||||||
@ -1,28 +0,0 @@
|
|||||||
//
|
|
||||||
// Created by sebastian on 29.07.26.
|
|
||||||
//
|
|
||||||
|
|
||||||
#ifndef COLORRACE_TRANSFORMCOMPONENT_H
|
|
||||||
#define COLORRACE_TRANSFORMCOMPONENT_H
|
|
||||||
#include "glm/glm.hpp"
|
|
||||||
#include <glm/gtc/matrix_transform.hpp>
|
|
||||||
|
|
||||||
namespace engine {
|
|
||||||
struct TransformComponent {
|
|
||||||
glm::vec3 m_position;
|
|
||||||
glm::vec3 m_rotation;
|
|
||||||
glm::vec3 m_scale;
|
|
||||||
|
|
||||||
[[nodiscard]] glm::mat4 computeModelMatrix() const {
|
|
||||||
auto modelMatrix = glm::mat4(1.0f);
|
|
||||||
modelMatrix = glm::translate(modelMatrix, m_position);
|
|
||||||
modelMatrix = glm::rotate(modelMatrix, glm::radians(m_rotation.x), {1.0f, 0.0f, 0.0f});
|
|
||||||
modelMatrix = glm::rotate(modelMatrix, glm::radians(m_rotation.y), {0.0f, 1.0f, 0.0f});
|
|
||||||
modelMatrix = glm::rotate(modelMatrix, glm::radians(m_rotation.z), {0.0f, 0.0f, 1.0f});
|
|
||||||
modelMatrix = glm::scale(modelMatrix, m_scale);
|
|
||||||
return modelMatrix;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
}
|
|
||||||
#endif //COLORRACE_TRANSFORMCOMPONENT_H
|
|
||||||
@ -1,27 +0,0 @@
|
|||||||
//
|
|
||||||
// Created by sebastian on 02.08.26.
|
|
||||||
//
|
|
||||||
|
|
||||||
#include "PickingSystem.h"
|
|
||||||
|
|
||||||
std::pair<glm::vec3, glm::vec3> engine::PickingSystem::screenToRay(const glm::vec2 &ndc, const Camera &camera) {
|
|
||||||
glm::mat4 invVP = glm::inverse(camera.getProjectionMatrix() * camera.getViewMatrix());
|
|
||||||
glm::vec4 nearPoint = invVP * glm::vec4(ndc.x, ndc.y, -1.0f, 1.0f); // Y invertiert (Screen vs. NDC)
|
|
||||||
glm::vec4 farPoint = invVP * glm::vec4(ndc.x, ndc.y, 1.0f, 1.0f);
|
|
||||||
nearPoint /= nearPoint.w;
|
|
||||||
farPoint /= farPoint.w;
|
|
||||||
auto origin = glm::vec3(nearPoint);
|
|
||||||
glm::vec3 dir = glm::normalize(glm::vec3(farPoint) - glm::vec3(nearPoint));
|
|
||||||
return {origin, dir};
|
|
||||||
}
|
|
||||||
|
|
||||||
bool engine::PickingSystem::raySphereIntersect(const glm::vec3 &origin, const glm::vec3 &dir, const glm::vec3 ¢er,
|
|
||||||
float radius, float &t) {
|
|
||||||
glm::vec3 oc = origin - center;
|
|
||||||
float b = glm::dot(oc, dir);
|
|
||||||
float c = glm::dot(oc, oc) - radius * radius;
|
|
||||||
float discriminant = b * b - c;
|
|
||||||
if (discriminant < 0.0f) return false;
|
|
||||||
t = -b - std::sqrt(discriminant);
|
|
||||||
return t >= 0.0f;
|
|
||||||
}
|
|
||||||
@ -1,66 +0,0 @@
|
|||||||
//
|
|
||||||
// Created by sebastian on 02.08.26.
|
|
||||||
//
|
|
||||||
|
|
||||||
#ifndef COLORRACE_PICKINGSYSTEM_H
|
|
||||||
#define COLORRACE_PICKINGSYSTEM_H
|
|
||||||
#include <optional>
|
|
||||||
|
|
||||||
#include "imgui.h"
|
|
||||||
#include "core/inputsOutputs/inputs/Mouse.h"
|
|
||||||
#include "core/inputsOutputs/inputs/MouseButton.h"
|
|
||||||
#include "ecs/EntityRegistry.h"
|
|
||||||
#include "ecs/standardComponents/PickableComponent.h"
|
|
||||||
#include "ecs/standardComponents/TransformComponent.h"
|
|
||||||
#define GLM_ENABLE_EXPERIMENTAL
|
|
||||||
#include <iostream>
|
|
||||||
|
|
||||||
#include "ecs/standardComponents/MeshComponent.h"
|
|
||||||
|
|
||||||
#include "renderer/entities/Camera.h"
|
|
||||||
#include "spdlog/spdlog.h"
|
|
||||||
|
|
||||||
|
|
||||||
namespace engine {
|
|
||||||
class Mouse;
|
|
||||||
|
|
||||||
class PickingSystem {
|
|
||||||
public:
|
|
||||||
explicit PickingSystem(Camera& camera) : m_camera(camera) {}
|
|
||||||
|
|
||||||
std::optional<Entity> update(const Mouse& mouse, EntityRegistry& registry) {
|
|
||||||
|
|
||||||
//if (ImGui::GetIO().WantCaptureMouse) return std::nullopt;
|
|
||||||
if (!mouse.isClickEvent(MouseButton::LEFT)) return std::nullopt;
|
|
||||||
auto [origin, dir] = screenToRay(mouse.getXY(/*ndc=*/true), m_camera);
|
|
||||||
|
|
||||||
float closestT = std::numeric_limits<float>::max();
|
|
||||||
std::optional<Entity> hit;
|
|
||||||
|
|
||||||
for (const auto& [entity, pickable] : registry.getPool<PickableComponent>()) {
|
|
||||||
const auto transform = registry.getComponent<TransformComponent>(entity);
|
|
||||||
const auto mesh = registry.getComponent<MeshComponent>(entity);
|
|
||||||
|
|
||||||
AABB transformedAABB = mesh.model->getAABB().transformed(transform.computeModelMatrix());
|
|
||||||
Ray ray = Ray(origin, dir);
|
|
||||||
std::optional<RayHit> ray_hit = transformedAABB.intersects(ray, closestT);
|
|
||||||
if (ray_hit.has_value()) {
|
|
||||||
spdlog::info(std::format("Hit: {} {}", entity.value(), std::to_string(ray_hit.value().distance)));
|
|
||||||
closestT = ray_hit.value().distance;
|
|
||||||
hit = entity;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return hit;
|
|
||||||
}
|
|
||||||
|
|
||||||
static std::pair<glm::vec3, glm::vec3> screenToRay(const glm::vec2& screenPos, const Camera& camera);
|
|
||||||
|
|
||||||
static bool raySphereIntersect(const glm::vec3& origin, const glm::vec3& dir, const glm::vec3& center, float radius, float& t);
|
|
||||||
private:
|
|
||||||
Camera& m_camera;
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
#endif //COLORRACE_PICKINGSYSTEM_H
|
|
||||||
@ -1,5 +0,0 @@
|
|||||||
//
|
|
||||||
// Created by sebastian on 02.08.26.
|
|
||||||
//
|
|
||||||
|
|
||||||
#include "GameMode.h"
|
|
||||||
@ -1,28 +0,0 @@
|
|||||||
//
|
|
||||||
// Created by sebastian on 02.08.26.
|
|
||||||
//
|
|
||||||
|
|
||||||
#ifndef COLORRACE_GAMEMODE_H
|
|
||||||
#define COLORRACE_GAMEMODE_H
|
|
||||||
#include <type_traits>
|
|
||||||
#include <vector>
|
|
||||||
|
|
||||||
#include "GameState.h"
|
|
||||||
|
|
||||||
|
|
||||||
namespace engine {
|
|
||||||
template <typename Command, typename Event, typename State>
|
|
||||||
class GameMode {
|
|
||||||
public:
|
|
||||||
static_assert(std::is_base_of_v<GameState, State>, "State must be derived from GameState");
|
|
||||||
|
|
||||||
virtual ~GameMode() = default;
|
|
||||||
|
|
||||||
virtual void sendCommand(const Command& command) = 0;
|
|
||||||
virtual std::vector<Event> pollEvents() = 0;
|
|
||||||
[[nodiscard]] virtual const State& getState() const = 0;
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
#endif //COLORRACE_GAMEMODE_H
|
|
||||||
@ -1,5 +0,0 @@
|
|||||||
//
|
|
||||||
// Created by sebastian on 02.08.26.
|
|
||||||
//
|
|
||||||
|
|
||||||
#include "GameState.h"
|
|
||||||
@ -1,17 +0,0 @@
|
|||||||
//
|
|
||||||
// Created by sebastian on 02.08.26.
|
|
||||||
//
|
|
||||||
|
|
||||||
#ifndef COLORRACE_GAMESTATE_H
|
|
||||||
#define COLORRACE_GAMESTATE_H
|
|
||||||
|
|
||||||
|
|
||||||
namespace engine {
|
|
||||||
class GameState {
|
|
||||||
public:
|
|
||||||
virtual ~GameState() = default;
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
}
|
|
||||||
#endif //COLORRACE_GAMESTATE_H
|
|
||||||
@ -1,5 +0,0 @@
|
|||||||
//
|
|
||||||
// Created by sebastian on 02.08.26.
|
|
||||||
//
|
|
||||||
|
|
||||||
#include "TurnBasedGameMode.h"
|
|
||||||
@ -1,33 +0,0 @@
|
|||||||
//
|
|
||||||
// Created by sebastian on 02.08.26.
|
|
||||||
//
|
|
||||||
|
|
||||||
#ifndef COLORRACE_TURNBASEDGAMEMODE_H
|
|
||||||
#define COLORRACE_TURNBASEDGAMEMODE_H
|
|
||||||
#include <cstdint>
|
|
||||||
|
|
||||||
#include "GameMode.h"
|
|
||||||
|
|
||||||
|
|
||||||
namespace engine {
|
|
||||||
using PlayerID = uint32_t;
|
|
||||||
|
|
||||||
template<typename Command, typename Event, typename State>
|
|
||||||
class TurnBasedGameMode : public GameMode<Command, Event, State> {
|
|
||||||
public:
|
|
||||||
explicit TurnBasedGameMode(std::vector<PlayerID> playerOrder) : m_playerOrder(std::move(playerOrder)) {}
|
|
||||||
[[nodiscard]] PlayerID getCurrentPlayer() const { return m_playerOrder[m_currentPlayerIndex]; }
|
|
||||||
[[nodiscard]] bool isCurrentPlayer(PlayerID playerID) const { return getCurrentPlayer() == playerID; }
|
|
||||||
[[nodiscard]] std::vector<PlayerID> getPlayerOrder() const { return m_playerOrder; }
|
|
||||||
protected:
|
|
||||||
void endTurn(bool extraTurn = false) {
|
|
||||||
if (!extraTurn) m_currentPlayerIndex = (m_currentPlayerIndex + 1) % m_playerOrder.size();
|
|
||||||
}
|
|
||||||
|
|
||||||
private:
|
|
||||||
std::vector<PlayerID> m_playerOrder;
|
|
||||||
size_t m_currentPlayerIndex = 0;
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
#endif //COLORRACE_TURNBASEDGAMEMODE_H
|
|
||||||
@ -1,53 +0,0 @@
|
|||||||
//
|
|
||||||
// Created by sebastian on 04.08.26.
|
|
||||||
//
|
|
||||||
|
|
||||||
#include "DebugLayer.h"
|
|
||||||
|
|
||||||
#include "ecs/standardComponents/MeshComponent.h"
|
|
||||||
#include "ecs/standardComponents/PickableComponent.h"
|
|
||||||
#include "ecs/standardComponents/TransformComponent.h"
|
|
||||||
#include "GLFW/glfw3.h"
|
|
||||||
#include "renderer/RenderQueue.h"
|
|
||||||
#include "renderer/primitives/SphereFactory.h"
|
|
||||||
#include "spdlog/spdlog.h"
|
|
||||||
|
|
||||||
|
|
||||||
void engine::DebugLayer::onUpdate(float deltaTime) {
|
|
||||||
Layer::onUpdate(deltaTime);
|
|
||||||
if (getKeyboard().isKeyDown(GLFW_KEY_H)) {
|
|
||||||
m_showDebugInfo = !m_showDebugInfo;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void engine::DebugLayer::onRender() {
|
|
||||||
Layer::onRender();
|
|
||||||
if (m_showDebugInfo) {
|
|
||||||
auto pickablePool = m_entityRegistry.getPool<PickableComponent>();
|
|
||||||
auto transforms = m_entityRegistry.getPool<engine::TransformComponent>();
|
|
||||||
for (auto& [entity, pickableComponent] : pickablePool) {
|
|
||||||
if (transforms.has(entity)) {
|
|
||||||
auto meshComponent = m_entityRegistry.getComponent<engine::MeshComponent>(entity);
|
|
||||||
glm::vec3 halfExtent = meshComponent.model.get()->getAABB().getHalfExtent();
|
|
||||||
//spdlog::info(std::to_string(halfExtent.x) + " " + std::to_string(halfExtent.y) + " " + std::to_string(halfExtent.z));
|
|
||||||
|
|
||||||
AABB transformedAABB = meshComponent.model->getAABB().transformed(transforms.get(entity).computeModelMatrix());
|
|
||||||
const auto sphereTransformComp = TransformComponent(transforms.get(entity).m_position, {0,0,0}, transformedAABB.getHalfExtent());
|
|
||||||
glm::mat4 modelMatrix = sphereTransformComp.computeModelMatrix();
|
|
||||||
|
|
||||||
RenderCommand renderCommand(m_sphereModel, modelMatrix);
|
|
||||||
m_renderQueue.submit(renderCommand);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
m_debugRenderer.render(m_renderQueue, m_camera);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void engine::DebugLayer::onAttachImpl() {
|
|
||||||
Layer::onAttachImpl();
|
|
||||||
}
|
|
||||||
|
|
||||||
void engine::DebugLayer::onDetachImpl() {
|
|
||||||
Layer::onDetachImpl();
|
|
||||||
}
|
|
||||||
@ -1,40 +0,0 @@
|
|||||||
//
|
|
||||||
// Created by sebastian on 04.08.26.
|
|
||||||
//
|
|
||||||
|
|
||||||
#ifndef COLORRACE_DEBUGLAYER_H
|
|
||||||
#define COLORRACE_DEBUGLAYER_H
|
|
||||||
#include "Layer.h"
|
|
||||||
#include "renderer/DebugRenderer.h"
|
|
||||||
#include "renderer/RenderQueue.h"
|
|
||||||
|
|
||||||
namespace engine {
|
|
||||||
class Model;
|
|
||||||
|
|
||||||
class DebugLayer: public Layer {
|
|
||||||
public:
|
|
||||||
DebugLayer(engine::EventBus<animation::AnimationMarkerEvent>& animationEventbus, Camera& camera, engine::EntityRegistry& registry, Keyboard &keyboard, Mouse &mouse, std::shared_ptr<Model> sphereModel)
|
|
||||||
: Layer(keyboard, mouse, animationEventbus), m_entityRegistry(registry), m_sphereModel(std::move(sphereModel)), m_camera(camera) {
|
|
||||||
}
|
|
||||||
|
|
||||||
void onUpdate(float deltaTime) override;
|
|
||||||
void onRender() override;
|
|
||||||
protected:
|
|
||||||
|
|
||||||
void onAttachImpl() override;
|
|
||||||
void onDetachImpl() override;
|
|
||||||
|
|
||||||
private:
|
|
||||||
engine::EntityRegistry& m_entityRegistry;
|
|
||||||
bool m_showDebugInfo = true;
|
|
||||||
|
|
||||||
std::shared_ptr<engine::Model> m_sphereModel;
|
|
||||||
RenderQueue m_renderQueue;
|
|
||||||
DebugRenderer m_debugRenderer;
|
|
||||||
|
|
||||||
Camera& m_camera;
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
}
|
|
||||||
#endif //COLORRACE_DEBUGLAYER_H
|
|
||||||
@ -1,17 +0,0 @@
|
|||||||
//
|
|
||||||
// Created by sebastian on 29.07.26.
|
|
||||||
//
|
|
||||||
|
|
||||||
#include "Layer.h"
|
|
||||||
|
|
||||||
void engine::Layer::onAttach(InputContextStack &inputStack) {
|
|
||||||
m_inputStack = &inputStack;
|
|
||||||
m_context = std::make_shared<InputContext>();
|
|
||||||
inputStack.push(m_context);
|
|
||||||
onAttachImpl();
|
|
||||||
}
|
|
||||||
|
|
||||||
void engine::Layer::onDetach(InputContextStack &inputStack) {
|
|
||||||
inputStack.pop();
|
|
||||||
onDetachImpl();
|
|
||||||
}
|
|
||||||
@ -1,48 +0,0 @@
|
|||||||
//
|
|
||||||
// Created by sebastian on 29.07.26.
|
|
||||||
//
|
|
||||||
|
|
||||||
#ifndef COLORRACE_LAYER_H
|
|
||||||
#define COLORRACE_LAYER_H
|
|
||||||
#include "core/animation/events/AnimationMarkerEvent.h"
|
|
||||||
#include "core/events/ApplicationEvents.h"
|
|
||||||
#include "core/events/EventBus.h"
|
|
||||||
#include "core/inputsOutputs/context/InputContextStack.h"
|
|
||||||
#include "core/inputsOutputs/inputs/Keyboard.h"
|
|
||||||
#include "core/inputsOutputs/inputs/Mouse.h"
|
|
||||||
#include "ecs/EntityRegistry.h"
|
|
||||||
|
|
||||||
|
|
||||||
namespace engine {
|
|
||||||
class Layer {
|
|
||||||
public:
|
|
||||||
Layer(Keyboard& keyboard, Mouse& mouse, EventBus<animation::AnimationMarkerEvent>& animationEventBus) : m_keyboard(keyboard), m_mouse(mouse), m_animationEventBus(animationEventBus){};
|
|
||||||
Layer(Keyboard& keyboard, Mouse& mouse, EventBus<animation::AnimationMarkerEvent>& animationEventBus, std::shared_ptr<EventBus<ApplicationEvents>> applicationEventBus) : m_keyboard(keyboard), m_mouse(mouse), m_animationEventBus(animationEventBus), m_applicationEventBus(std::move(applicationEventBus)){};
|
|
||||||
virtual ~Layer() = default;
|
|
||||||
void onAttach(InputContextStack& inputStack);
|
|
||||||
void onDetach(InputContextStack& inputStack);
|
|
||||||
virtual void onUpdate(float deltaTime) {}
|
|
||||||
virtual void onRender() {}
|
|
||||||
protected:
|
|
||||||
virtual void onAttachImpl() {}
|
|
||||||
virtual void onDetachImpl() {}
|
|
||||||
std::shared_ptr<InputContext>& getInputContext() { return m_context; }
|
|
||||||
InputContextStack& getInputStack() { return *m_inputStack; }
|
|
||||||
Keyboard& getKeyboard() { return m_keyboard; }
|
|
||||||
Mouse& getMouse() { return m_mouse; }
|
|
||||||
EventBus<animation::AnimationMarkerEvent>& getAnimationEventBus() { return m_animationEventBus; }
|
|
||||||
|
|
||||||
std::shared_ptr<EventBus<ApplicationEvents>> m_applicationEventBus;
|
|
||||||
private:
|
|
||||||
std::shared_ptr<InputContext> m_context;
|
|
||||||
InputContextStack* m_inputStack = nullptr;
|
|
||||||
|
|
||||||
engine::Keyboard& m_keyboard;
|
|
||||||
engine::Mouse& m_mouse;
|
|
||||||
engine::EventBus<animation::AnimationMarkerEvent>& m_animationEventBus;
|
|
||||||
};
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
#endif //COLORRACE_LAYER_H
|
|
||||||
@ -1,34 +0,0 @@
|
|||||||
//
|
|
||||||
// Created by sebastian on 30.07.26.
|
|
||||||
//
|
|
||||||
|
|
||||||
#include "Scene.h"
|
|
||||||
|
|
||||||
#include <iostream>
|
|
||||||
#include <ostream>
|
|
||||||
#include <utility>
|
|
||||||
|
|
||||||
#include "core/inputsOutputs/context/InputContextStack.h"
|
|
||||||
|
|
||||||
void engine::Scene::onUpdate(float deltaTime) {
|
|
||||||
for (const auto& layer : m_layers) {
|
|
||||||
layer->onUpdate(deltaTime);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void engine::Scene::onRender() {
|
|
||||||
for (const auto& layer : m_layers) {
|
|
||||||
layer->onRender();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void engine::Scene::onRegisterLoadedAsset(LoadedAsset loadedAsset) {
|
|
||||||
std::cout << "Loaded asset: " << std::endl;
|
|
||||||
assetManager->insertAsset(std::move(loadedAsset));
|
|
||||||
}
|
|
||||||
|
|
||||||
void engine::Scene::addLayer(std::unique_ptr<Layer> layer) {
|
|
||||||
layer->onAttach(m_inputStack);
|
|
||||||
m_layers.push_back(std::move(layer));
|
|
||||||
|
|
||||||
}
|
|
||||||
@ -1,63 +0,0 @@
|
|||||||
//
|
|
||||||
// Created by sebastian on 30.07.26.
|
|
||||||
//
|
|
||||||
|
|
||||||
#ifndef COLORRACE_SCENE_H
|
|
||||||
#define COLORRACE_SCENE_H
|
|
||||||
#include <memory>
|
|
||||||
#include <vector>
|
|
||||||
|
|
||||||
#include "Layer.h"
|
|
||||||
#include "core/animation/events/AnimationMarkerEvent.h"
|
|
||||||
#include "core/events/ApplicationEvents.h"
|
|
||||||
#include "core/events/EventBus.h"
|
|
||||||
#include "loader/assets/AssetManager.h"
|
|
||||||
#include "loader/assets/AssetRequests.h"
|
|
||||||
#include "loader/assets/LoadedAssets.h"
|
|
||||||
#include "renderer/entities/Camera.h"
|
|
||||||
|
|
||||||
|
|
||||||
namespace engine {
|
|
||||||
class Keyboard;
|
|
||||||
class Mouse;
|
|
||||||
class InputContextStack;
|
|
||||||
|
|
||||||
class Scene {
|
|
||||||
public:
|
|
||||||
explicit Scene(std::shared_ptr<engine::EventBus<ApplicationEvents>> applicationEventbus, engine::InputContextStack& inputStack, engine::Keyboard& keyboard, engine::Mouse& mouse):
|
|
||||||
assetManager(std::make_unique<AssetManager>()), m_inputStack(inputStack), m_keyboard(keyboard), m_mouse(mouse), m_applicationEventBus(std::move(applicationEventbus)) {}
|
|
||||||
virtual ~Scene() = default;
|
|
||||||
virtual void onEnter() {}
|
|
||||||
virtual void onExit() {
|
|
||||||
for (const auto& layer : m_layers) {
|
|
||||||
layer->onDetach(m_inputStack);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void onUpdate(float deltaTime);
|
|
||||||
void onRender();
|
|
||||||
|
|
||||||
void onRegisterLoadedAsset(LoadedAsset loadedAsset);
|
|
||||||
|
|
||||||
virtual std::vector<AssetRequest> getRequiredAssets() const { return {}; }
|
|
||||||
protected:
|
|
||||||
std::vector<std::unique_ptr<Layer>> m_layers;
|
|
||||||
EventBus<animation::AnimationMarkerEvent>& getAnimationEventBus() { return m_animationMarkerEventBus; }
|
|
||||||
|
|
||||||
void addLayer(std::unique_ptr<Layer> layer);
|
|
||||||
|
|
||||||
engine::EntityRegistry entityRegistry;
|
|
||||||
std::unique_ptr<AssetManager> assetManager;
|
|
||||||
InputContextStack& m_inputStack;
|
|
||||||
|
|
||||||
engine::Keyboard& m_keyboard;
|
|
||||||
engine::Mouse& m_mouse;
|
|
||||||
std::shared_ptr<engine::EventBus<ApplicationEvents>> m_applicationEventBus;
|
|
||||||
private:
|
|
||||||
EventBus<animation::AnimationMarkerEvent> m_animationMarkerEventBus;
|
|
||||||
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
#endif //COLORRACE_SCENE_H
|
|
||||||
@ -1,64 +0,0 @@
|
|||||||
//
|
|
||||||
// Created by sebastian on 30.07.26.
|
|
||||||
//
|
|
||||||
|
|
||||||
#include "SceneManager.h"
|
|
||||||
|
|
||||||
#include <iostream>
|
|
||||||
|
|
||||||
#include "spdlog/spdlog.h"
|
|
||||||
|
|
||||||
void engine::SceneManager::switchTo(std::unique_ptr<Scene> scene, std::function<void()> onSceneLoaded) {
|
|
||||||
onSceneLoaded = std::move(onSceneLoaded);
|
|
||||||
nextScene = std::move(scene);
|
|
||||||
|
|
||||||
std::vector<AssetRequest> requestedAssets = nextScene->getRequiredAssets();
|
|
||||||
spdlog::debug("Requested Assets: {}", requestedAssets.size());
|
|
||||||
|
|
||||||
for (AssetRequest & request : requestedAssets) {
|
|
||||||
assetLoader.scheduleAsset(request);
|
|
||||||
}
|
|
||||||
|
|
||||||
assetLoader.start();
|
|
||||||
}
|
|
||||||
|
|
||||||
void engine::SceneManager::update(float deltaTime) {
|
|
||||||
if (nextScene) {
|
|
||||||
auto uploadedAssets = assetLoader.processUploadQueue(2);
|
|
||||||
std::cout << "Uploaded Assets: " << uploadedAssets.size() << std::endl;
|
|
||||||
for (const auto& asset : uploadedAssets) {
|
|
||||||
nextScene->onRegisterLoadedAsset(asset);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (assetLoader.getProgress().isDone()) {
|
|
||||||
if (currentScene) {
|
|
||||||
currentScene->onExit();
|
|
||||||
}
|
|
||||||
|
|
||||||
currentScene = std::move(nextScene);
|
|
||||||
nextScene = nullptr;
|
|
||||||
currentScene->onEnter();
|
|
||||||
|
|
||||||
assetLoader.stop();
|
|
||||||
|
|
||||||
if (onSceneLoaded) {
|
|
||||||
onSceneLoaded();
|
|
||||||
onSceneLoaded = nullptr;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (currentScene) {
|
|
||||||
currentScene->onUpdate(deltaTime);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void engine::SceneManager::render() const {
|
|
||||||
if (currentScene) {
|
|
||||||
currentScene->onRender();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
float engine::SceneManager::getTransitionProgress() const {
|
|
||||||
return assetLoader.getProgress().fraction();
|
|
||||||
}
|
|
||||||
@ -1,36 +0,0 @@
|
|||||||
//
|
|
||||||
// Created by sebastian on 30.07.26.
|
|
||||||
//
|
|
||||||
|
|
||||||
#ifndef COLORRACE_SCENEMANAGER_H
|
|
||||||
#define COLORRACE_SCENEMANAGER_H
|
|
||||||
#include <memory>
|
|
||||||
|
|
||||||
#include "Scene.h"
|
|
||||||
#include "core/inputsOutputs/context/InputContextStack.h"
|
|
||||||
#include "loader/AssetLoader.h"
|
|
||||||
|
|
||||||
|
|
||||||
namespace engine {
|
|
||||||
class SceneManager {
|
|
||||||
public:
|
|
||||||
explicit SceneManager(InputContextStack& inputStack) :m_inputStack(inputStack) {}
|
|
||||||
void switchTo(std::unique_ptr<Scene> scene, std::function<void()> onSceneLoaded = nullptr);
|
|
||||||
void update(float deltaTime);
|
|
||||||
void render() const;
|
|
||||||
~SceneManager() = default;
|
|
||||||
|
|
||||||
[[nodiscard]] float getTransitionProgress() const;
|
|
||||||
private:
|
|
||||||
std::unique_ptr<Scene> currentScene;
|
|
||||||
std::unique_ptr<Scene> nextScene;
|
|
||||||
bool isTransitioning = false;
|
|
||||||
std::function<void()> onSceneLoaded;
|
|
||||||
AssetLoader assetLoader;
|
|
||||||
|
|
||||||
InputContextStack& m_inputStack;
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
}
|
|
||||||
#endif //COLORRACE_SCENEMANAGER_H
|
|
||||||
@ -1,180 +0,0 @@
|
|||||||
//
|
|
||||||
// Created by sebastian on 30.07.26.
|
|
||||||
//
|
|
||||||
|
|
||||||
#include "AssetLoader.h"
|
|
||||||
|
|
||||||
#include <dr_wav.h>
|
|
||||||
#include <iostream>
|
|
||||||
|
|
||||||
#include "models/ModelImporter.h"
|
|
||||||
#include "models/ModelUploader.h"
|
|
||||||
#include "sounds/SoundUploader.h"
|
|
||||||
#include "spdlog/spdlog.h"
|
|
||||||
#include "textures/TextureImporter.h"
|
|
||||||
#include "textures/TextureUploader.h"
|
|
||||||
|
|
||||||
void engine::AssetLoader::scheduleAsset(const AssetRequest &request) {
|
|
||||||
{
|
|
||||||
std::lock_guard<std::mutex> lock(pendingMutex);
|
|
||||||
pendingQueue.push(request);
|
|
||||||
++total;
|
|
||||||
}
|
|
||||||
pendingCondition.notify_one();
|
|
||||||
std::visit([]<typename T>(const T& req) -> void {
|
|
||||||
using Type = std::decay_t<T>;
|
|
||||||
if constexpr (std::is_same_v<Type, TextureRequest>) {
|
|
||||||
spdlog::debug("Scheduled Texture Request: {} -> {}", req.name, req.path);
|
|
||||||
} else if constexpr (std::is_same_v<Type, ModelRequest>) {
|
|
||||||
spdlog::debug("Scheduled Model Request: {} -> {}", req.name, req.path);
|
|
||||||
} else if constexpr (std::is_same_v<Type, SoundRequest>) {
|
|
||||||
spdlog::debug("Scheduled Sound Request: {} -> {}", req.name, req.path);
|
|
||||||
}
|
|
||||||
}, request);
|
|
||||||
}
|
|
||||||
|
|
||||||
void engine::AssetLoader::start() {
|
|
||||||
if (!running) {
|
|
||||||
running = true;
|
|
||||||
loadingThread = std::thread(&AssetLoader::loadingThreadFunc, this);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void engine::AssetLoader::stop() {
|
|
||||||
running = false;
|
|
||||||
pendingCondition.notify_all();
|
|
||||||
if (loadingThread.joinable()) {
|
|
||||||
loadingThread.join();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
std::vector<engine::LoadedAsset> engine::AssetLoader::processUploadQueue(int maxPerFrame) {
|
|
||||||
std::vector<LoadedAsset> result;
|
|
||||||
auto uploadQueue = determineUploadQueue(maxPerFrame);
|
|
||||||
std::cout << "Upload Queue: " << uploadQueue.size() << std::endl;
|
|
||||||
for (const auto& asset : uploadQueue) {
|
|
||||||
std::visit([&result]<typename T0>(T0& rawData) -> void {
|
|
||||||
using T = std::decay_t<T0>;
|
|
||||||
if constexpr (std::is_same_v<T, RawTextureData>) {
|
|
||||||
Texture2D texture = TextureUploader::upload(rawData);
|
|
||||||
result.emplace_back(LoadedTexture{rawData.name, std::make_shared<Texture2D>(std::move(texture))});
|
|
||||||
} else if constexpr (std::is_same_v<T, RawModelBundle>) {
|
|
||||||
std::cout << "Uploading model " << rawData.model.name << std::endl;
|
|
||||||
auto modelAssets = ModelUploader::upload(rawData, rawData.model.splitPolicy);
|
|
||||||
std::cout << "Moddel Assets" << modelAssets.size() << std::endl;
|
|
||||||
result.insert(result.end(), modelAssets.begin(), modelAssets.end());
|
|
||||||
std::cout << "Result size" << result.size() << std::endl;
|
|
||||||
} else if constexpr (std::is_same_v<T, RawSoundData>) {
|
|
||||||
auto soundAsset = SoundUploader::upload(rawData);
|
|
||||||
result.emplace_back(LoadedSound{rawData.name, std::make_shared<audio::SoundBuffer>(std::move(soundAsset))});
|
|
||||||
} else {
|
|
||||||
static_assert(
|
|
||||||
always_false<T>,
|
|
||||||
"Unhandled asset type in AssetLoader::processUploadQueue"
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}, asset);
|
|
||||||
++loaded;
|
|
||||||
}
|
|
||||||
|
|
||||||
std::cout << "Loaded Assets: " << result.size() << std::endl;
|
|
||||||
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
engine::LoadingProgress engine::AssetLoader::getProgress() const {
|
|
||||||
return {total.load(), loaded.load()};
|
|
||||||
}
|
|
||||||
|
|
||||||
void engine::AssetLoader::loadingThreadFunc() {
|
|
||||||
while (running) {
|
|
||||||
AssetRequest request;
|
|
||||||
{
|
|
||||||
std::unique_lock lock(pendingMutex);
|
|
||||||
pendingCondition.wait(lock, [this] {
|
|
||||||
return !pendingQueue.empty() || !running;
|
|
||||||
});
|
|
||||||
|
|
||||||
if (!running && pendingQueue.empty()) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
request = pendingQueue.front();
|
|
||||||
pendingQueue.pop();
|
|
||||||
}
|
|
||||||
|
|
||||||
IntermediateAsset result = std::visit([]<typename T0>(T0& req) -> IntermediateAsset {
|
|
||||||
using T = std::decay_t<T0>;
|
|
||||||
if constexpr (std::is_same_v<T, TextureRequest>) {
|
|
||||||
return processTextureRequest(req);
|
|
||||||
} else if constexpr (std::is_same_v<T, ModelRequest>) {
|
|
||||||
return processModelRequest(req);
|
|
||||||
} else if constexpr (std::is_same_v<T, SoundRequest>) {
|
|
||||||
return processSoundRequest(req);
|
|
||||||
} else {
|
|
||||||
static_assert(always_false<T>, "Unhandled asset type in AssetLoader::loadingThreadFunc");
|
|
||||||
}
|
|
||||||
}, request);
|
|
||||||
|
|
||||||
{
|
|
||||||
std::lock_guard lock(readyMutex);
|
|
||||||
readyQueue.push(std::move(result));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
engine::RawTextureData engine::AssetLoader::processTextureRequest(const TextureRequest &request) {
|
|
||||||
spdlog::debug("Processing Texture Request: {} -> {}", request.name, request.path);
|
|
||||||
RawTextureData textureData = TextureImporter::import(request.path, request.flipY);
|
|
||||||
textureData.name = request.name;
|
|
||||||
return textureData;
|
|
||||||
}
|
|
||||||
|
|
||||||
engine::RawModelBundle engine::AssetLoader::processModelRequest(const ModelRequest &request) {
|
|
||||||
spdlog::debug("Processing Model Request: {} -> {}", request.name, request.path);
|
|
||||||
RawModelBundle modelData = ModelImporter::importFromFile(request.path, request.splitPolicy);
|
|
||||||
modelData.model.name = request.name;
|
|
||||||
return modelData;
|
|
||||||
}
|
|
||||||
|
|
||||||
engine::RawSoundData engine::AssetLoader::processSoundRequest(const SoundRequest &request) {
|
|
||||||
RawSoundData soundData;
|
|
||||||
unsigned int channels, sampleRate;
|
|
||||||
drwav_uint64 frameCount;
|
|
||||||
|
|
||||||
drwav_int16* pcmData = drwav_open_file_and_read_pcm_frames_s16(
|
|
||||||
request.path.c_str(), &channels, &sampleRate, &frameCount, nullptr
|
|
||||||
);
|
|
||||||
|
|
||||||
if (!pcmData) {
|
|
||||||
throw std::runtime_error("Failed to load sound file: " + request.path);
|
|
||||||
}
|
|
||||||
|
|
||||||
soundData.name = request.name;
|
|
||||||
soundData.channels = channels;
|
|
||||||
soundData.sampleRate = sampleRate;
|
|
||||||
soundData.bitsPerSample = 16;
|
|
||||||
size_t dataSize = frameCount * channels * sizeof(drwav_int16);
|
|
||||||
soundData.pcmData.resize(dataSize);
|
|
||||||
std::memcpy(
|
|
||||||
soundData.pcmData.data(),
|
|
||||||
pcmData,
|
|
||||||
dataSize
|
|
||||||
);
|
|
||||||
drwav_free(pcmData, nullptr);
|
|
||||||
|
|
||||||
return soundData;
|
|
||||||
}
|
|
||||||
|
|
||||||
std::vector<engine::IntermediateAsset> engine::AssetLoader::determineUploadQueue(int maxPerFrame) {
|
|
||||||
std::vector<IntermediateAsset> result;
|
|
||||||
std::lock_guard lock(readyMutex);
|
|
||||||
for (int i = 0; i < maxPerFrame && !readyQueue.empty(); ++i) {
|
|
||||||
result.push_back(std::move(readyQueue.front()));
|
|
||||||
readyQueue.pop();
|
|
||||||
}
|
|
||||||
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
@ -1,68 +0,0 @@
|
|||||||
//
|
|
||||||
// Created by sebastian on 30.07.26.
|
|
||||||
//
|
|
||||||
|
|
||||||
#ifndef COLORRACE_ASSETLOADER_H
|
|
||||||
#define COLORRACE_ASSETLOADER_H
|
|
||||||
#include <condition_variable>
|
|
||||||
#include <format>
|
|
||||||
#include <mutex>
|
|
||||||
#include <queue>
|
|
||||||
#include <string>
|
|
||||||
#include <unordered_map>
|
|
||||||
#include <variant>
|
|
||||||
#include <vector>
|
|
||||||
|
|
||||||
#include "assets/AssetRequests.h"
|
|
||||||
#include "assets/LoadedAssets.h"
|
|
||||||
#include "assets/RawAssetData.h"
|
|
||||||
|
|
||||||
namespace engine {
|
|
||||||
struct LoadingProgress {
|
|
||||||
int total;
|
|
||||||
int loaded;
|
|
||||||
float fraction() const {
|
|
||||||
return total > 0 ? static_cast<float>(loaded) / total : 1.f;
|
|
||||||
}
|
|
||||||
bool isDone() const {
|
|
||||||
return loaded >= total;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
template<typename>
|
|
||||||
inline constexpr bool always_false = false;
|
|
||||||
|
|
||||||
class AssetLoader {
|
|
||||||
public:
|
|
||||||
void scheduleAsset(const AssetRequest& request);
|
|
||||||
void start();
|
|
||||||
void stop();
|
|
||||||
|
|
||||||
std::vector<LoadedAsset> processUploadQueue(int maxPerFrame);
|
|
||||||
LoadingProgress getProgress() const;
|
|
||||||
|
|
||||||
private:
|
|
||||||
void loadingThreadFunc();
|
|
||||||
|
|
||||||
static RawTextureData processTextureRequest(const TextureRequest& request);
|
|
||||||
static RawModelBundle processModelRequest(const ModelRequest& request);
|
|
||||||
static RawSoundData processSoundRequest(const SoundRequest& request);
|
|
||||||
std::vector<IntermediateAsset> determineUploadQueue(int maxPerFrame);
|
|
||||||
|
|
||||||
std::queue<AssetRequest> pendingQueue;
|
|
||||||
std::mutex pendingMutex;
|
|
||||||
std::condition_variable pendingCondition;
|
|
||||||
|
|
||||||
std::queue<IntermediateAsset> readyQueue;
|
|
||||||
std::mutex readyMutex;
|
|
||||||
|
|
||||||
std::atomic<int> total{0};
|
|
||||||
std::atomic<int> loaded{0};
|
|
||||||
|
|
||||||
std::thread loadingThread;
|
|
||||||
std::atomic<bool> running{false};
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
#endif //COLORRACE_ASSETLOADER_H
|
|
||||||
@ -1,59 +0,0 @@
|
|||||||
//
|
|
||||||
// Created by sebastian on 30.07.26.
|
|
||||||
//
|
|
||||||
|
|
||||||
#ifndef COLORRACE_ASSETFORMATTERS_H
|
|
||||||
#define COLORRACE_ASSETFORMATTERS_H
|
|
||||||
#pragma once
|
|
||||||
|
|
||||||
#include "AssetRequests.h"
|
|
||||||
#include "AssetTypes.h"
|
|
||||||
|
|
||||||
#include <format>
|
|
||||||
|
|
||||||
|
|
||||||
template<>
|
|
||||||
struct std::formatter<engine::AssetRequest>
|
|
||||||
{
|
|
||||||
constexpr auto parse(
|
|
||||||
std::format_parse_context& ctx)
|
|
||||||
{
|
|
||||||
return ctx.begin();
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
auto format(
|
|
||||||
const engine::AssetRequest& request,
|
|
||||||
std::format_context& ctx) const
|
|
||||||
{
|
|
||||||
return std::format_to(
|
|
||||||
ctx.out(),
|
|
||||||
"{}",
|
|
||||||
engine::assetRequestToString(request)
|
|
||||||
);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
template<>
|
|
||||||
struct std::formatter<engine::TextureType>
|
|
||||||
{
|
|
||||||
constexpr auto parse(
|
|
||||||
std::format_parse_context& ctx)
|
|
||||||
{
|
|
||||||
return ctx.begin();
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
auto format(
|
|
||||||
engine::TextureType type,
|
|
||||||
std::format_context& ctx) const
|
|
||||||
{
|
|
||||||
return std::format_to(
|
|
||||||
ctx.out(),
|
|
||||||
"{}",
|
|
||||||
engine::toString(type)
|
|
||||||
);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
#endif //COLORRACE_ASSETFORMATTERS_H
|
|
||||||
@ -1,86 +0,0 @@
|
|||||||
//
|
|
||||||
// Created by sebastian on 30.07.26.
|
|
||||||
//
|
|
||||||
|
|
||||||
#include "AssetManager.h"
|
|
||||||
|
|
||||||
#include <iostream>
|
|
||||||
#include <ostream>
|
|
||||||
|
|
||||||
std::shared_ptr<engine::Model> engine::AssetManager::getModel(const std::string &name) const {
|
|
||||||
auto it = m_models.find(name);
|
|
||||||
if (it == m_models.end()) {
|
|
||||||
throw std::runtime_error("Model not found: " + name);
|
|
||||||
}
|
|
||||||
return it->second;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool engine::AssetManager::hasModel(const std::string &name) const {
|
|
||||||
return m_models.contains(name);
|
|
||||||
}
|
|
||||||
|
|
||||||
void engine::AssetManager::insertAsset(LoadedAsset loadedAsset) {
|
|
||||||
std::cout << "Inserting asset: " << std::endl;
|
|
||||||
std::visit([this](const auto& loaded) {
|
|
||||||
using T = std::decay_t<decltype(loaded)>;
|
|
||||||
|
|
||||||
if constexpr (std::is_same_v<T, LoadedModel>) {
|
|
||||||
insertModel(loaded.name, loaded.model);
|
|
||||||
} else if constexpr (std::is_same_v<T, LoadedTexture>) {
|
|
||||||
insertTexture(loaded.name, loaded.texture);
|
|
||||||
} else if constexpr (std::is_same_v<T, LoadedSound>) {
|
|
||||||
insertSound(loaded.name, loaded.sound);
|
|
||||||
}
|
|
||||||
}, loadedAsset);
|
|
||||||
}
|
|
||||||
|
|
||||||
void engine::AssetManager::insertModel(const std::string &name, std::shared_ptr<Model> model) {
|
|
||||||
std::cout << "Inserting model " << name << std::endl;
|
|
||||||
m_models[name] = std::move(model);
|
|
||||||
}
|
|
||||||
|
|
||||||
void engine::AssetManager::unloadModel(const std::string &name) {
|
|
||||||
m_models.erase(name);
|
|
||||||
}
|
|
||||||
|
|
||||||
std::shared_ptr<engine::Texture2D> engine::AssetManager::getTexture(const std::string &name) const {
|
|
||||||
auto it = m_textures.find(name);
|
|
||||||
if (it == m_textures.end()) {
|
|
||||||
throw std::runtime_error("Texture not found: " + name);
|
|
||||||
}
|
|
||||||
return it->second;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool engine::AssetManager::hasTexture(const std::string &name) const {
|
|
||||||
return m_textures.contains(name);
|
|
||||||
}
|
|
||||||
|
|
||||||
void engine::AssetManager::insertTexture(const std::string &name, std::shared_ptr<Texture2D> texture) {
|
|
||||||
std::cout << "Inserting texture " << name << std::endl;
|
|
||||||
m_textures[name] = std::move(texture);
|
|
||||||
}
|
|
||||||
|
|
||||||
void engine::AssetManager::unloadTexture(const std::string &name) {
|
|
||||||
m_textures.erase(name);
|
|
||||||
}
|
|
||||||
|
|
||||||
std::shared_ptr<engine::audio::SoundBuffer> engine::AssetManager::getSound(const std::string &name) const {
|
|
||||||
auto it = m_loadedAssets.find(name);
|
|
||||||
if (it == m_loadedAssets.end()) {
|
|
||||||
throw std::runtime_error("Sound not found: " + name);
|
|
||||||
}
|
|
||||||
return it->second;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool engine::AssetManager::hasSound(const std::string &name) const {
|
|
||||||
return m_loadedAssets.contains(name);
|
|
||||||
}
|
|
||||||
|
|
||||||
void engine::AssetManager::insertSound(const std::string &name, std::shared_ptr<audio::SoundBuffer> sound) {
|
|
||||||
std::cout << "Inserting sound " << name << std::endl;
|
|
||||||
m_loadedAssets[name] = std::move(sound);
|
|
||||||
}
|
|
||||||
|
|
||||||
void engine::AssetManager::unloadSound(const std::string &name) {
|
|
||||||
m_loadedAssets.erase(name);
|
|
||||||
}
|
|
||||||
@ -1,45 +0,0 @@
|
|||||||
//
|
|
||||||
// Created by sebastian on 30.07.26.
|
|
||||||
//
|
|
||||||
|
|
||||||
#ifndef COLORRACE_ASSETMANAGER_H
|
|
||||||
#define COLORRACE_ASSETMANAGER_H
|
|
||||||
#include <string>
|
|
||||||
#include <unordered_map>
|
|
||||||
|
|
||||||
#include "LoadedAssets.h"
|
|
||||||
#include "loader/models/Model.h"
|
|
||||||
#include "loader/textures/Texture2D.h"
|
|
||||||
|
|
||||||
|
|
||||||
namespace engine {
|
|
||||||
class AssetManager {
|
|
||||||
public:
|
|
||||||
AssetManager() = default;
|
|
||||||
~AssetManager() = default;
|
|
||||||
|
|
||||||
std::shared_ptr<Model> getModel(const std::string& name) const;
|
|
||||||
bool hasModel(const std::string& name) const;
|
|
||||||
void insertAsset(LoadedAsset loadedAsset);
|
|
||||||
void insertModel(const std::string& name, std::shared_ptr<Model> model);
|
|
||||||
void unloadModel(const std::string& name);
|
|
||||||
|
|
||||||
std::shared_ptr<Texture2D> getTexture(const std::string& name) const;
|
|
||||||
bool hasTexture(const std::string& name) const;
|
|
||||||
void insertTexture(const std::string& name, std::shared_ptr<Texture2D> texture);
|
|
||||||
void unloadTexture(const std::string& name);
|
|
||||||
|
|
||||||
std::shared_ptr<audio::SoundBuffer> getSound(const std::string& name) const;
|
|
||||||
bool hasSound(const std::string& name) const;
|
|
||||||
void insertSound(const std::string& name, std::shared_ptr<audio::SoundBuffer> sound);
|
|
||||||
void unloadSound(const std::string& name);
|
|
||||||
|
|
||||||
|
|
||||||
private:
|
|
||||||
std::unordered_map<std::string, std::shared_ptr<Texture2D>> m_textures;
|
|
||||||
std::unordered_map<std::string, std::shared_ptr<Model>> m_models;
|
|
||||||
std::unordered_map<std::string, std::shared_ptr<audio::SoundBuffer>> m_loadedAssets;
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
#endif //COLORRACE_ASSETMANAGER_H
|
|
||||||
@ -1,50 +0,0 @@
|
|||||||
//
|
|
||||||
// Created by sebastian on 30.07.26.
|
|
||||||
//
|
|
||||||
// AssetRequests.cpp
|
|
||||||
|
|
||||||
#include "AssetRequests.h"
|
|
||||||
|
|
||||||
#include <format>
|
|
||||||
#include <type_traits>
|
|
||||||
|
|
||||||
#include "RawAssetData.h"
|
|
||||||
#include "loader/AssetLoader.h"
|
|
||||||
|
|
||||||
|
|
||||||
namespace engine {
|
|
||||||
|
|
||||||
std::string assetRequestToString(
|
|
||||||
const AssetRequest& request)
|
|
||||||
{
|
|
||||||
return std::visit(
|
|
||||||
[](auto const& req)
|
|
||||||
{
|
|
||||||
using Type = std::decay_t<decltype(req)>;
|
|
||||||
|
|
||||||
|
|
||||||
if constexpr(std::is_same_v<Type, TextureRequest>)
|
|
||||||
{
|
|
||||||
return std::format(
|
|
||||||
"TextureRequest{{name='{}', path='{}'}}",
|
|
||||||
req.name,
|
|
||||||
req.path
|
|
||||||
);
|
|
||||||
} else if constexpr(std::is_same_v<Type, ModelRequest>)
|
|
||||||
{
|
|
||||||
return std::format(
|
|
||||||
"ModelRequest{{name='{}', path='{}'}}",
|
|
||||||
req.name,
|
|
||||||
req.path
|
|
||||||
);
|
|
||||||
} else if constexpr(std::is_same_v<Type, SoundRequest>){
|
|
||||||
return std::format(
|
|
||||||
"SoundRequest{{name='{}', path='{}'}}",
|
|
||||||
req.name,
|
|
||||||
req.path);
|
|
||||||
}
|
|
||||||
},
|
|
||||||
request);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||