diff --git a/.github/workflows/cmake.yml b/.github/workflows/cmake.yml index 4f8b700e..e8dd45f9 100644 --- a/.github/workflows/cmake.yml +++ b/.github/workflows/cmake.yml @@ -4,71 +4,68 @@ on: push: branches: - master + - development - c-i pull_request: branches: - master -env: - # Customize the CMake build type here (Release, Debug, RelWithDebInfo, etc.) - BUILD_TYPE: Release + - development jobs: build: - # The CMake configure and build commands are platform agnostic and should work equally - # well on Windows or Mac. You can convert this to a matrix build if you need - # cross-platform coverage. - # See: https://docs.github.com/en/free-pro-team@latest/actions/learn-github-actions/managing-complex-workflows#using-a-build-matrix + name: build-${{ matrix.os }} runs-on: ${{ matrix.os }} strategy: + fail-fast: false matrix: - os: [windows-latest] - + os: [windows-latest, ubuntu-latest] + env: + BUILD_TYPE: Release steps: - - uses: actions/checkout@v2 - - - name: Linux dev lib + - uses: actions/checkout@v4 + + - name: Install Linux dependencies if: runner.os == 'Linux' - run: | - sudo apt-get update - sudo add-apt-repository ppa:ubuntu-toolchain-r/test - sudo apt-get update - sudo apt-get install -y gcc-10 g++-10 - sudo apt-get install -y libxrandr-dev xorg-dev libglu1-mesa-dev - sudo apt-get install -y libgtk-3-dev - export CC=gcc-10 - export CXX=g++-10 + run: | + sudo apt-get update + sudo apt-get install -y libxrandr-dev xorg-dev libglu1-mesa-dev libgtk-3-dev - sudo apt-get install libgtest-dev - cd /usr/src/gtest - sudo mkdir build - cd build - sudo cmake .. - sudo make - - - name: Create Build Environment - # Some projects don't allow in-source building, so create a separate build directory - # We'll use this as our working directory for all subsequent commands - run: cmake -E make_directory ${{runner.workspace}}/build - name: Configure CMake - # Use a bash shell so we can use the same syntax for environment variable - # access regardless of the host operating system - shell: bash - working-directory: ${{runner.workspace}}/build - # Note the current convention is to use the -S and -B options here to specify source - # and build directories, but this is only available with CMake 3.13 and higher. - # The CMake binaries on the Github Actions machines are (as of this writing) 3.12 - run: cmake $GITHUB_WORKSPACE -DCMAKE_BUILD_TYPE=$BUILD_TYPE + run: cmake -S . -B build -DCMAKE_BUILD_TYPE=${{ env.BUILD_TYPE }} - name: Build - working-directory: ${{runner.workspace}}/build - shell: bash - # Execute the build. You can specify a specific target with "--target " - run: cmake --build . --config $BUILD_TYPE + run: cmake --build build --config ${{ env.BUILD_TYPE }} - name: Test - working-directory: ${{runner.workspace}}/build - shell: bash - # Execute tests defined by the CMake configuration. - # See https://cmake.org/cmake/help/latest/manual/ctest.1.html for more detail - run: ctest -C $BUILD_TYPE --rerun-failed --output-on-failure + working-directory: build + run: ctest -C ${{ env.BUILD_TYPE }} --output-on-failure + + sanitizers: + name: asan-ubsan (ubuntu) + runs-on: ubuntu-latest + env: + BUILD_TYPE: Debug + CC: clang + CXX: clang++ + CXXFLAGS: -fsanitize=address,undefined -fno-omit-frame-pointer + LDFLAGS: -fsanitize=address,undefined + steps: + - uses: actions/checkout@v4 + + - name: Install Linux dependencies + run: | + sudo apt-get update + sudo apt-get install -y libxrandr-dev xorg-dev libglu1-mesa-dev libgtk-3-dev + - name: Configure CMake + run: cmake -S . -B build -DCMAKE_BUILD_TYPE=${{ env.BUILD_TYPE }} + + - name: Build + run: cmake --build build --config ${{ env.BUILD_TYPE }} + + - name: Test + working-directory: build + env: + ASAN_OPTIONS: detect_leaks=1:halt_on_error=0 + UBSAN_OPTIONS: print_stacktrace=1 + run: ctest -C ${{ env.BUILD_TYPE }} --output-on-failure diff --git a/.gitignore b/.gitignore index 2b3529aa..244bd5cb 100644 --- a/.gitignore +++ b/.gitignore @@ -6,3 +6,5 @@ build/ .vscode/ /.vs + +docs/REMEDIATION_PLAN.md diff --git a/CMakeLists.txt b/CMakeLists.txt index 5088feec..a851729e 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,14 +1,17 @@ cmake_minimum_required(VERSION 3.19) project(ICE_ROOT) -set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++20") set(CMAKE_CXX_STANDARD 20) +set(CMAKE_CXX_STANDARD_REQUIRED ON) +set(CMAKE_CXX_EXTENSIONS OFF) -include(cmake/fetch_dependencies.cmake) -enable_testing() set(GLFW_INSTALL OFF CACHE BOOL "" FORCE) set(GLFW_BUILD_DOCS OFF CACHE BOOL "" FORCE) set(GLFW_BUILD_TESTS OFF CACHE BOOL "" FORCE) set(GLFW_BUILD_EXAMPLES OFF CACHE BOOL "" FORCE) +set(BUILD_IMXML_EXAMPLE OFF CACHE BOOL "" FORCE) +include(cmake/fetch_dependencies.cmake) +enable_testing() + if(APPLE) find_library(COCOA_LIBRARY Cocoa REQUIRED) diff --git a/ICE/Assets/CMakeLists.txt b/ICE/Assets/CMakeLists.txt index f977a7d5..3800b05f 100644 --- a/ICE/Assets/CMakeLists.txt +++ b/ICE/Assets/CMakeLists.txt @@ -15,11 +15,10 @@ target_sources(${PROJECT_NAME} PRIVATE src/GPURegistry.cpp src/Texture.cpp) -target_link_libraries(${PROJECT_NAME} - PUBLIC - graphics +target_link_libraries(${PROJECT_NAME} + PUBLIC + graphics util - io storage math ) diff --git a/ICE/Assets/include/AssetBank.h b/ICE/Assets/include/AssetBank.h index f9492ca7..4fed8d15 100644 --- a/ICE/Assets/include/AssetBank.h +++ b/ICE/Assets/include/AssetBank.h @@ -32,6 +32,14 @@ class AssetBank { public: AssetBank(); + // Registration seam for asset loaders. The concrete loaders live in the `io` + // module; the composition layer wires them in via this method so that `assets` + // does not depend on `io` (see registerDefaultLoaders in the io module). + template + void addLoader(const std::shared_ptr>& asset_loader) { + loader.AddLoader(asset_loader); + } + template std::shared_ptr getAsset(AssetUID uid) { return dynamic_pointer_cast(getAsset(uid)); diff --git a/ICE/IO/include/IAssetLoader.h b/ICE/Assets/include/IAssetLoader.h similarity index 100% rename from ICE/IO/include/IAssetLoader.h rename to ICE/Assets/include/IAssetLoader.h diff --git a/ICE/Assets/src/AssetBank.cpp b/ICE/Assets/src/AssetBank.cpp index 3665be7e..67ba4a37 100644 --- a/ICE/Assets/src/AssetBank.cpp +++ b/ICE/Assets/src/AssetBank.cpp @@ -4,25 +4,11 @@ #include "AssetBank.h" -#include -#include - -#include "MaterialLoader.h" -#include "MeshLoader.h" -#include "ModelLoader.h" -#include "ShaderLoader.h" -#include "TextureLoader.h" - namespace ICE { -AssetBank::AssetBank() { - loader.AddLoader(std::make_shared()); - loader.AddLoader(std::make_shared()); - loader.AddLoader(std::make_shared(*this)); - loader.AddLoader(std::make_shared()); - loader.AddLoader(std::make_shared()); - loader.AddLoader(std::make_shared()); -} +// Loaders are registered by the composition layer (io::registerDefaultLoaders), +// not here, so that the `assets` module does not depend on `io`. +AssetBank::AssetBank() = default; bool AssetBank::nameInUse(const AssetPath &name) { return !(nameMapping.find(name) == nameMapping.end()); diff --git a/ICE/CMakeLists.txt b/ICE/CMakeLists.txt index 294fb2be..5cfd5429 100644 --- a/ICE/CMakeLists.txt +++ b/ICE/CMakeLists.txt @@ -13,6 +13,7 @@ add_subdirectory(Graphics) add_subdirectory(GraphicsAPI) add_subdirectory(IO) add_subdirectory(Math) +add_subdirectory(Multithreading) add_subdirectory(Platform) add_subdirectory(Scene) add_subdirectory(Storage) @@ -38,20 +39,21 @@ elseif(WIN32) ${ICE_LIBS} ) else() - find_package(GTK REQUIRED) - include_directories(${GTK3_INCLUDE_DIRS}) - link_directories(${GTK3_LIBRARY_DIRS}) + find_package(PkgConfig REQUIRED) - add_definitions(${GTK3_CFLAGS_OTHER}) + pkg_check_modules(GTK3 REQUIRED gtk+-3.0) find_package(OpenGL REQUIRED) - include_directories(${OPENGL_INCLUDE_DIRS}) - target_link_libraries(${PROJECT_NAME} - INTERFACE - glfw - ${GTK3_LIBRARIES} - ${OPENGL_LIBRARIES} + target_include_directories(${PROJECT_NAME} INTERFACE ${GTK3_INCLUDE_DIRS} ${OPENGL_INCLUDE_DIRS}) + target_compile_options(${PROJECT_NAME} INTERFACE ${GTK3_CFLAGS_OTHER}) + + target_link_libraries(${PROJECT_NAME} + INTERFACE + glfw + ${GTK3_LIBRARIES} + ${OPENGL_LIBRARIES} stdc++fs + ${ICE_LIBS} ) endif() diff --git a/ICE/Components/include/RenderComponent.h b/ICE/Components/include/RenderComponent.h index e5e44d36..479dc437 100644 --- a/ICE/Components/include/RenderComponent.h +++ b/ICE/Components/include/RenderComponent.h @@ -11,9 +11,10 @@ namespace ICE { struct RenderComponent : public Component { + RenderComponent() = default; RenderComponent(AssetUID mesh_id, AssetUID material_id) : mesh(mesh_id), material(material_id) {} - AssetUID mesh; - AssetUID material; + AssetUID mesh = NO_ASSET_ID; + AssetUID material = NO_ASSET_ID; }; } // namespace ICE diff --git a/ICE/Components/include/TransformComponent.h b/ICE/Components/include/TransformComponent.h index eca7a7ad..9c1af307 100644 --- a/ICE/Components/include/TransformComponent.h +++ b/ICE/Components/include/TransformComponent.h @@ -14,8 +14,10 @@ struct TransformComponent : public Component { m_rotation(rot), m_scale(sca) {} - TransformComponent(const Eigen::Vector3f& pos = Eigen::Vector3f::Zero(), const Eigen::Vector3f& rot = Eigen::Vector3f::Zero(), - const Eigen::Vector3f& sca = Eigen::Vector3f::Ones()) + // Euler-rotation overload: pos and rot are required (no defaults) so that the + // zero- and single-Vector3f-argument cases resolve unambiguously to the + // quaternion-rotation constructor above. + TransformComponent(const Eigen::Vector3f& pos, const Eigen::Vector3f& rot, const Eigen::Vector3f& sca = Eigen::Vector3f::Ones()) : m_position(pos), m_scale(sca) { setRotationEulerDeg(rot); diff --git a/ICE/Entity/include/Entity.h b/ICE/Entity/include/Entity.h index 23246a8e..b2bd605a 100644 --- a/ICE/Entity/include/Entity.h +++ b/ICE/Entity/include/Entity.h @@ -6,6 +6,7 @@ #define ICE_ENTITY_H #include +#include #include #include #include diff --git a/ICE/Graphics/include/ForwardRenderer.h b/ICE/Graphics/include/ForwardRenderer.h index 16769fa5..f0c4d41a 100644 --- a/ICE/Graphics/include/ForwardRenderer.h +++ b/ICE/Graphics/include/ForwardRenderer.h @@ -9,6 +9,7 @@ #include #include +#include #include #include "Camera.h" @@ -23,13 +24,13 @@ namespace ICE { class ForwardRenderer : public Renderer { public: - ForwardRenderer(const std::shared_ptr& api, const std::shared_ptr& factory); + ForwardRenderer(const std::shared_ptr &api, const std::shared_ptr &factory); - void submitSkybox(const Skybox& e) override; - void submitDrawable(const Drawable& e) override; - void submitLight(const Light& e) override; + void submitSkybox(const Skybox &e) override; + void submitDrawable(const Drawable &e) override; + void submitLight(const Light &e) override; - void prepareFrame(Camera& camera) override; + void prepareFrame(Camera &camera) override; std::shared_ptr render() override; @@ -52,7 +53,7 @@ class ForwardRenderer : public Renderer { std::optional m_skybox; std::vector m_drawables; std::vector m_lights; - + // Instance batching storage std::unordered_map> m_instance_batches; diff --git a/ICE/GraphicsAPI/OpenGL/include/OpenGLShader.h b/ICE/GraphicsAPI/OpenGL/include/OpenGLShader.h index 2b68236b..caf29ba2 100644 --- a/ICE/GraphicsAPI/OpenGL/include/OpenGLShader.h +++ b/ICE/GraphicsAPI/OpenGL/include/OpenGLShader.h @@ -41,7 +41,7 @@ class OpenGLShader : public ShaderProgram { void compileAndAttachStage(ShaderStage stage, const std::string &source); - constexpr GLenum stageToGLStage(ShaderStage stage); + GLenum stageToGLStage(ShaderStage stage); uint32_t m_programID; std::unordered_map m_locations; diff --git a/ICE/GraphicsAPI/OpenGL/src/OpenGLShader.cpp b/ICE/GraphicsAPI/OpenGL/src/OpenGLShader.cpp index 8b637a2b..414203cd 100644 --- a/ICE/GraphicsAPI/OpenGL/src/OpenGLShader.cpp +++ b/ICE/GraphicsAPI/OpenGL/src/OpenGLShader.cpp @@ -110,7 +110,7 @@ void OpenGLShader::compileAndAttachStage(ShaderStage stage, const std::string &s } -constexpr GLenum OpenGLShader::stageToGLStage(ShaderStage stage) { +GLenum OpenGLShader::stageToGLStage(ShaderStage stage) { switch (stage) { case ShaderStage::Vertex: return GL_VERTEX_SHADER; diff --git a/ICE/IO/CMakeLists.txt b/ICE/IO/CMakeLists.txt index aef7310b..be3906ff 100644 --- a/ICE/IO/CMakeLists.txt +++ b/ICE/IO/CMakeLists.txt @@ -7,6 +7,7 @@ add_library(${PROJECT_NAME} STATIC) target_sources(${PROJECT_NAME} PRIVATE src/EngineConfig.cpp + src/DefaultLoaders.cpp src/Project.cpp src/MaterialExporter.cpp src/TextureLoader.cpp diff --git a/ICE/IO/include/DefaultLoaders.h b/ICE/IO/include/DefaultLoaders.h new file mode 100644 index 00000000..5d676af9 --- /dev/null +++ b/ICE/IO/include/DefaultLoaders.h @@ -0,0 +1,11 @@ +#pragma once + +namespace ICE { +class AssetBank; + +// Registers the engine's built-in asset loaders (mesh, model, material, shader, +// textures) onto the given bank. Lives in the `io` module because that is where +// the concrete loaders (and their Assimp/JSON dependencies) live; keeping this +// out of AssetBank's constructor is what breaks the assets <-> io dependency cycle. +void registerDefaultLoaders(AssetBank &bank); +} // namespace ICE diff --git a/ICE/IO/include/ModelLoader.h b/ICE/IO/include/ModelLoader.h index c1b0135c..3d45bced 100644 --- a/ICE/IO/include/ModelLoader.h +++ b/ICE/IO/include/ModelLoader.h @@ -36,7 +36,7 @@ class ModelLoader : public IAssetLoader { Eigen::Vector3f aiVec3ToEigen(const aiVector3D &vec); Eigen::Quaternionf aiQuatToEigen(const aiQuaternion &q); - constexpr TextureFormat getTextureFormat(aiTextureType type, int channels); + TextureFormat getTextureFormat(aiTextureType type, int channels); AssetBank &ref_bank; }; diff --git a/ICE/IO/include/ShaderExporter.h b/ICE/IO/include/ShaderExporter.h index 05fe1ecf..5b6c0d3e 100644 --- a/ICE/IO/include/ShaderExporter.h +++ b/ICE/IO/include/ShaderExporter.h @@ -10,7 +10,7 @@ class ShaderExporter : public AssetExporter { void writeToJson(const std::filesystem::path &path, const Shader &object) override; void writeToBin(const std::filesystem::path &path, const Shader &object) override; - constexpr std::string stageToString(ShaderStage stage) { + std::string stageToString(ShaderStage stage) { switch (stage) { case ShaderStage::Vertex: return "vertex"; diff --git a/ICE/IO/include/ShaderLoader.h b/ICE/IO/include/ShaderLoader.h index 408552d1..217aaba2 100644 --- a/ICE/IO/include/ShaderLoader.h +++ b/ICE/IO/include/ShaderLoader.h @@ -16,6 +16,6 @@ class ShaderLoader : public IAssetLoader { ShaderLoader() = default; std::shared_ptr load(const std::vector &file) override; std::string readAndResolveIncludes(const std::filesystem::path &file); - constexpr ShaderStage stageFromString(const std::string &str); + ShaderStage stageFromString(const std::string &str); }; } // namespace ICE diff --git a/ICE/IO/src/DefaultLoaders.cpp b/ICE/IO/src/DefaultLoaders.cpp new file mode 100644 index 00000000..5b993091 --- /dev/null +++ b/ICE/IO/src/DefaultLoaders.cpp @@ -0,0 +1,21 @@ +#include "DefaultLoaders.h" + +#include + +#include "AssetBank.h" +#include "MaterialLoader.h" +#include "MeshLoader.h" +#include "ModelLoader.h" +#include "ShaderLoader.h" +#include "TextureLoader.h" + +namespace ICE { +void registerDefaultLoaders(AssetBank &bank) { + bank.addLoader(std::make_shared()); + bank.addLoader(std::make_shared()); + bank.addLoader(std::make_shared(bank)); + bank.addLoader(std::make_shared()); + bank.addLoader(std::make_shared()); + bank.addLoader(std::make_shared()); +} +} // namespace ICE diff --git a/ICE/IO/src/ModelLoader.cpp b/ICE/IO/src/ModelLoader.cpp index 09560e69..9efaef4a 100644 --- a/ICE/IO/src/ModelLoader.cpp +++ b/ICE/IO/src/ModelLoader.cpp @@ -349,7 +349,7 @@ Eigen::Quaternionf ModelLoader::aiQuatToEigen(const aiQuaternion &q) { return quat; } -constexpr TextureFormat ModelLoader::getTextureFormat(aiTextureType type, int channels) { +TextureFormat ModelLoader::getTextureFormat(aiTextureType type, int channels) { switch (type) { case aiTextureType_METALNESS: case aiTextureType_AMBIENT_OCCLUSION: diff --git a/ICE/IO/src/Project.cpp b/ICE/IO/src/Project.cpp index b90e0726..17453714 100644 --- a/ICE/IO/src/Project.cpp +++ b/ICE/IO/src/Project.cpp @@ -15,6 +15,7 @@ #include #include +#include "DefaultLoaders.h" #include "MaterialExporter.h" #include "ShaderExporter.h" @@ -24,6 +25,7 @@ Project::Project(const fs::path &base_directory, const std::string &m_name) m_name(m_name), m_asset_bank(std::make_shared()), m_gpu_registry(std::make_shared(std::make_shared(), m_asset_bank)) { + registerDefaultLoaders(*m_asset_bank); cameraPosition.setZero(); cameraRotation.setZero(); constexpr std::string_view assets_folder = "Assets"; diff --git a/ICE/IO/src/ShaderLoader.cpp b/ICE/IO/src/ShaderLoader.cpp index c8f1ab36..cdc2a740 100644 --- a/ICE/IO/src/ShaderLoader.cpp +++ b/ICE/IO/src/ShaderLoader.cpp @@ -37,7 +37,7 @@ std::shared_ptr ShaderLoader::load(const std::vector + $) + +enable_testing() +#add_subdirectory(test) diff --git a/ICE/Multithreading/include/ThreadSafeQueue.h b/ICE/Multithreading/include/ThreadSafeQueue.h index 8b9b7953..71e7b15f 100644 --- a/ICE/Multithreading/include/ThreadSafeQueue.h +++ b/ICE/Multithreading/include/ThreadSafeQueue.h @@ -1,7 +1,10 @@ +#pragma once + #include #include #include #include +#include namespace ICE { template diff --git a/ICE/Platform/CMakeLists.txt b/ICE/Platform/CMakeLists.txt index 90bf3e8b..bfe55cbe 100644 --- a/ICE/Platform/CMakeLists.txt +++ b/ICE/Platform/CMakeLists.txt @@ -10,9 +10,14 @@ if(APPLE) elseif(WIN32) set(EXTRA_SRC Win32/dialog.cpp) else() - link_libraries(-lstdc++fs) set(EXTRA_SRC Linux/dialog.cpp) - set(EXTRA_INC ${GTK3_INCLUDE_DIRS}) + # GTK3 headers live under /usr/include/gtk-3.0 (+ glib/cairo/pango) and are + # only discoverable through pkg-config; resolve them here so dialog.cpp compiles. + find_package(PkgConfig REQUIRED) + pkg_check_modules(GTK3 REQUIRED gtk+-3.0) + set(EXTRA_INC ${GTK3_INCLUDE_DIRS}) + set(EXTRA_LIBS ${GTK3_LIBRARIES} stdc++fs) + set(EXTRA_LIBDIRS ${GTK3_LIBRARY_DIRS}) endif() target_sources(${PROJECT_NAME} PRIVATE @@ -20,9 +25,14 @@ target_sources(${PROJECT_NAME} PRIVATE ${EXTRA_SRC} ) -target_link_libraries(${PROJECT_NAME} +if(EXTRA_LIBDIRS) + target_link_directories(${PROJECT_NAME} PUBLIC ${EXTRA_LIBDIRS}) +endif() + +target_link_libraries(${PROJECT_NAME} PUBLIC util + ${EXTRA_LIBS} ) target_include_directories(${PROJECT_NAME} PUBLIC diff --git a/ICE/Platform/Linux/dialog.cpp b/ICE/Platform/Linux/dialog.cpp index 816a8ae1..1aeb4956 100644 --- a/ICE/Platform/Linux/dialog.cpp +++ b/ICE/Platform/Linux/dialog.cpp @@ -2,9 +2,12 @@ // Created by Thomas Ibanez on 10.12.20. // -#include #include +#include + +#include "dialog.h" + const std::string open_native_dialog(const std::vector &filters) { GtkWidget *dialog; @@ -20,16 +23,18 @@ const std::string open_native_dialog(const std::vector &filters) { "_Open", GTK_RESPONSE_ACCEPT, NULL); + std::string result; if (gtk_dialog_run(GTK_DIALOG(dialog)) == GTK_RESPONSE_ACCEPT) { - char *filename; - filename = gtk_file_chooser_get_filename(GTK_FILE_CHOOSER(dialog)); - gtk_widget_destroy(dialog); - return std::string(filename); + char *filename = gtk_file_chooser_get_filename(GTK_FILE_CHOOSER(dialog)); + if (filename != NULL) { + result = filename; + g_free(filename); + } } gtk_widget_destroy(dialog); - return std::string(""); + return result; } const std::string open_native_folder_dialog() { @@ -47,14 +52,16 @@ const std::string open_native_folder_dialog() { "_Open", GTK_RESPONSE_ACCEPT, NULL); + std::string result; if (gtk_dialog_run(GTK_DIALOG(dialog)) == GTK_RESPONSE_ACCEPT) { - char *filename; - filename = gtk_file_chooser_get_filename(GTK_FILE_CHOOSER(dialog)); - gtk_widget_destroy(dialog); - return std::string(filename); + char *filename = gtk_file_chooser_get_filename(GTK_FILE_CHOOSER(dialog)); + if (filename != NULL) { + result = filename; + g_free(filename); + } } gtk_widget_destroy(dialog); - return std::string(""); + return result; } \ No newline at end of file diff --git a/ICE/System/CMakeLists.txt b/ICE/System/CMakeLists.txt index 635a5a86..cf361e64 100644 --- a/ICE/System/CMakeLists.txt +++ b/ICE/System/CMakeLists.txt @@ -22,4 +22,4 @@ target_include_directories(${PROJECT_NAME} PUBLIC $) enable_testing() -#add_subdirectory(test) +add_subdirectory(test) diff --git a/ICE/System/test/CMakeLists.txt b/ICE/System/test/CMakeLists.txt new file mode 100644 index 00000000..3b643f7d --- /dev/null +++ b/ICE/System/test/CMakeLists.txt @@ -0,0 +1,20 @@ +cmake_minimum_required(VERSION 3.19) +project(system-tests) + +message(STATUS "Building ${PROJECT_NAME} suite") +include(CTest) + +add_executable(SystemTestSuite + ECSTest.cpp +) + +add_test(NAME SystemTestSuite + COMMAND SystemTestSuite + WORKING_DIRECTORY $) + +target_link_libraries(SystemTestSuite + PRIVATE + gtest_main + system + components +) diff --git a/ICE/System/test/ECSTest.cpp b/ICE/System/test/ECSTest.cpp new file mode 100644 index 00000000..59457850 --- /dev/null +++ b/ICE/System/test/ECSTest.cpp @@ -0,0 +1,4 @@ +// +// gtest translation unit for the ECS test cases declared in ECSTest.h. +// +#include "ECSTest.h" diff --git a/ICE/System/test/ECSTest.h b/ICE/System/test/ECSTest.h index 5a1a5fe8..5488465e 100644 --- a/ICE/System/test/ECSTest.h +++ b/ICE/System/test/ECSTest.h @@ -5,6 +5,8 @@ #include #include +using namespace ICE; + TEST(ECSTest, FirstEntityIs1) { Registry reg = Registry(); diff --git a/ICE/Util/test/FrustumCullingTests.cpp b/ICE/Util/test/FrustumCullingTests.cpp index a81ff449..00203a14 100644 --- a/ICE/Util/test/FrustumCullingTests.cpp +++ b/ICE/Util/test/FrustumCullingTests.cpp @@ -57,7 +57,7 @@ TEST_F(FrustumCullingTest, AABBInFrustum_CompletelyInside) { Frustum frustum = extractFrustumPlanes(pv); // Create a small AABB at the origin (center of view) - AABB box({Eigen::Vector3f(-0.5f, -0.5f, -0.5f), Eigen::Vector3f(0.5f, 0.5f, 0.5f)}); + AABB box(std::vector{Eigen::Vector3f(-0.5f, -0.5f, -0.5f), Eigen::Vector3f(0.5f, 0.5f, 0.5f)}); EXPECT_TRUE(isAABBInFrustum(frustum, box)); } @@ -70,7 +70,7 @@ TEST_F(FrustumCullingTest, AABBInFrustum_PartiallyInside) { Frustum frustum = extractFrustumPlanes(pv); // Create an AABB that straddles the near plane - AABB box({Eigen::Vector3f(-1.0f, -1.0f, -0.05f), Eigen::Vector3f(1.0f, 1.0f, -0.5f)}); + AABB box(std::vector{Eigen::Vector3f(-1.0f, -1.0f, -0.05f), Eigen::Vector3f(1.0f, 1.0f, -0.5f)}); EXPECT_TRUE(isAABBInFrustum(frustum, box)); } @@ -83,7 +83,7 @@ TEST_F(FrustumCullingTest, AABBInFrustum_FarPlane) { Frustum frustum = extractFrustumPlanes(pv); // Create an AABB beyond the far plane - AABB box({Eigen::Vector3f(-1.0f, -1.0f, -101.0f), Eigen::Vector3f(1.0f, 1.0f, -102.0f)}); + AABB box(std::vector{Eigen::Vector3f(-1.0f, -1.0f, -101.0f), Eigen::Vector3f(1.0f, 1.0f, -102.0f)}); EXPECT_FALSE(isAABBInFrustum(frustum, box)); } @@ -96,7 +96,7 @@ TEST_F(FrustumCullingTest, AABBInFrustum_OutsideLeftPlane) { Frustum frustum = extractFrustumPlanes(pv); // Create an AABB to the far left, outside the frustum - AABB box({Eigen::Vector3f(-100.0f, -1.0f, -5.0f), Eigen::Vector3f(-50.0f, 1.0f, -3.0f)}); + AABB box(std::vector{Eigen::Vector3f(-100.0f, -1.0f, -5.0f), Eigen::Vector3f(-50.0f, 1.0f, -3.0f)}); EXPECT_FALSE(isAABBInFrustum(frustum, box)); } @@ -188,7 +188,7 @@ TEST_F(FrustumCullingTest, AABBInFrustum_VerySmallBox) { Frustum frustum = extractFrustumPlanes(pv); - AABB box({Eigen::Vector3f(0, 0, -10), Eigen::Vector3f(0.001f, 0.001f, -10.001f)}); + AABB box(std::vector{Eigen::Vector3f(0, 0, -10), Eigen::Vector3f(0.001f, 0.001f, -10.001f)}); EXPECT_TRUE(isAABBInFrustum(frustum, box)); } diff --git a/ICEBERG/UI/MaterialEditDialog.h b/ICEBERG/UI/MaterialEditDialog.h index e4e232bd..d7a9dc5d 100644 --- a/ICEBERG/UI/MaterialEditDialog.h +++ b/ICEBERG/UI/MaterialEditDialog.h @@ -7,6 +7,7 @@ #include #include +#include #include #include diff --git a/ICEBERG/UI/ShaderEditDialog.h b/ICEBERG/UI/ShaderEditDialog.h index 82da2c8d..193126fc 100644 --- a/ICEBERG/UI/ShaderEditDialog.h +++ b/ICEBERG/UI/ShaderEditDialog.h @@ -7,6 +7,7 @@ #include #include +#include #include #include @@ -25,7 +26,7 @@ class ShaderEditDialog : public Dialog, ImXML::XMLEventHandler { void setShader(const std::shared_ptr& shader, const std::string& name, const std::filesystem::path& shader_base_folder) { m_shader_base_folder = shader_base_folder; m_widgets.clear(); - strncpy_s(m_shader_name, name.c_str(), 512); + std::snprintf(m_shader_name, sizeof(m_shader_name), "%s", name.c_str()); if (shader) { for (const auto& [stage, source] : shader->getStageSources()) { m_shader_base_folder = shader->getSources().at(0).parent_path(); diff --git a/ICEBERG/UI/ShaderStageEditWidget.h b/ICEBERG/UI/ShaderStageEditWidget.h index d0e1b4b0..00342a2c 100644 --- a/ICEBERG/UI/ShaderStageEditWidget.h +++ b/ICEBERG/UI/ShaderStageEditWidget.h @@ -7,6 +7,7 @@ #include #include +#include #include #include @@ -26,13 +27,13 @@ class ShaderStageEditWidget : public Widget, ImXML::XMLEventHandler { void setShaderSource(const std::pair& source, const std::filesystem::path& parent_path) { m_parent_path = parent_path; - strncpy_s(m_shader_file, source.first.c_str(), 512); + std::snprintf(m_shader_file, sizeof(m_shader_file), "%s", source.first.c_str()); std::ifstream file(parent_path / source.first); std::stringstream buffer; buffer << file.rdbuf(); - strncpy_s(m_shader_source, buffer.str().c_str(), 65535); + std::snprintf(m_shader_source, sizeof(m_shader_source), "%s", buffer.str().c_str()); } void onNodeBegin(ImXML::XMLNode& node) override { @@ -50,7 +51,7 @@ class ShaderStageEditWidget : public Widget, ImXML::XMLEventHandler { if (file.is_open()) { std::stringstream buffer; buffer << file.rdbuf(); - strncpy_s(m_shader_source, buffer.str().c_str(), 65535); + std::snprintf(m_shader_source, sizeof(m_shader_source), "%s", buffer.str().c_str()); } } else if (node.arg("id") == "btn_delete_stage") { ImGui::SetTabItemClosed(m_stage.c_str()); diff --git a/cmake/fetch_dependencies.cmake b/cmake/fetch_dependencies.cmake index 74efc9c7..c35895a9 100644 --- a/cmake/fetch_dependencies.cmake +++ b/cmake/fetch_dependencies.cmake @@ -12,25 +12,25 @@ FetchContent_MakeAvailable(googletest) set(gtest_force_shared_crt ON CACHE BOOL "" FORCE) message(STATUS "Fetching GLFW") -include(FetchContent) FetchContent_Declare( GLFW GIT_REPOSITORY https://github.com/glfw/glfw.git - GIT_TAG master -) + GIT_TAG 3.4 + GIT_SHALLOW TRUE) FetchContent_MakeAvailable(GLFW) message(STATUS "Fetching Assimp") -include(FetchContent) FetchContent_Declare( Assimp GIT_REPOSITORY https://github.com/assimp/assimp.git - GIT_TAG master -) + GIT_TAG v6.0.5 + GIT_SHALLOW TRUE) FetchContent_MakeAvailable(Assimp) message(STATUS "Fetching DearImXML") -include(FetchContent) +# Don't build DearImXML's example app: it links imgui_impl_glfw which needs X11 +# libs that its example target doesn't request, breaking the Linux build. +set(BUILD_IMXML_EXAMPLE OFF CACHE BOOL "" FORCE) FetchContent_Declare( DearImXML GIT_REPOSITORY https://github.com/ProtectedVariable/DearImXML.git @@ -43,7 +43,7 @@ set(JSON_BuildTests OFF CACHE INTERNAL "") FetchContent_Declare( json GIT_REPOSITORY https://github.com/nlohmann/json - GIT_TAG v3.11.2 + GIT_TAG v3.12.0 GIT_SHALLOW TRUE GIT_PROGRESS TRUE) FetchContent_MakeAvailable(json)