commit 50e314be56de8b27b15f45fa301e0b74bd1a93f9 Author: Romain BOULLARD Date: Mon Aug 17 01:14:21 2026 +0200 Initial commit diff --git a/.clang-format b/.clang-format new file mode 100644 index 0000000..e93c306 --- /dev/null +++ b/.clang-format @@ -0,0 +1,122 @@ +--- +AlignAfterOpenBracket: Align +AlignArrayOfStructures: None +AccessModifierOffset: -2 +AlignConsecutiveBitFields: + Enabled: true + AcrossEmptyLines: false + AcrossComments: true + AlignCompound: true + PadOperators: true +AlignConsecutiveMacros: + Enabled: true + AcrossEmptyLines: false + AcrossComments: true + AlignCompound: true + PadOperators: true +AlignConsecutiveShortCaseStatements: + Enabled: true + AcrossEmptyLines: true + AcrossComments: true + AlignCaseColons: true +AlignEscapedNewlines: Right +AlignOperands: Align +AlignTrailingComments: + Kind: Always + OverEmptyLines: 2 +AllowAllArgumentsOnNextLine: false +AllowAllParametersOfDeclarationOnNextLine: false +AllowShortBlocksOnASingleLine: Empty +AllowShortCaseLabelsOnASingleLine: false +AllowShortEnumsOnASingleLine: false +AllowShortFunctionsOnASingleLine: Empty +AllowShortIfStatementsOnASingleLine: Never +AllowShortLambdasOnASingleLine: Empty +AllowShortLoopsOnASingleLine: false +AlwaysBreakAfterReturnType: None +AlwaysBreakBeforeMultilineStrings: false +AlwaysBreakTemplateDeclarations: Yes +BinPackArguments: false +BinPackParameters: false +BitFieldColonSpacing: After +BreakBeforeBraces: Custom +BracedInitializerIndentWidth: 2 +BreakAfterAttributes: Always +BreakArrays: false +BreakBeforeTernaryOperators: true +BreakConstructorInitializers: AfterColon +BreakInheritanceList: BeforeComma +BreakStringLiterals: true +CompactNamespaces: false +Cpp11BracedListStyle: true +EmptyLineBeforeAccessModifier: Always +FixNamespaceComments: true +IncludeBlocks: Preserve +IndentCaseBlocks: true +IndentCaseLabels: false +IndentPPDirectives: None +IndentRequiresClause: true +IndentWidth: 4 +IndentWrappedFunctionNames: true +InsertBraces: true +InsertNewlineAtEOF: true +IntegerLiteralSeparator: + Binary: -1 + Decimal: 3 + DecimalMinDigits: 5 + Hex: -1 +LambdaBodyIndentation: Signature +Language: Cpp +NamespaceIndentation: None +PointerAlignment: Left +QualifierAlignment: Leave +ReferenceAlignment: Left +UseTab: Never +Standard: Auto +BraceWrapping: + AfterNamespace: true + AfterCaseLabel: true + AfterClass: true + AfterControlStatement: Always + AfterEnum: true + AfterFunction: true + AfterStruct: true + AfterUnion: true + BeforeElse: true + BeforeLambdaBody: true + BeforeWhile: false + IndentBraces: false + SplitEmptyFunction: true + SplitEmptyRecord: true + SplitEmptyNamespace: true +ColumnLimit: 120 +SpaceAfterTemplateKeyword: false +SortIncludes: CaseSensitive +PenaltyReturnTypeOnItsOwnLine: 500 +SpaceBeforeAssignmentOperators: true +SpaceBeforeCaseColon: false +SpaceBeforeCtorInitializerColon: false +SpaceBeforeInheritanceColon: false +SpaceBeforeRangeBasedForLoopColon: false +SpaceBeforeSquareBrackets: false +SpacesInAngles: Never +SpacesInConditionalStatement: false +SpaceBeforeParens: ControlStatements +SpacesInContainerLiterals: false +SpacesInSquareBrackets: false +SpacesBeforeTrailingComments: 3 +PackConstructorInitializers: Never +SeparateDefinitionBlocks: Always +MaxEmptyLinesToKeep: 1 +BreakBeforeBinaryOperators: None +AlignConsecutiveAssignments: + Enabled: false + AcrossEmptyLines: false + AcrossComments: true + AlignCompound: true + PadOperators: true +SpaceAroundPointerQualifiers: Default +SpaceBeforeCpp11BracedList: true +SpaceInEmptyBlock: true +PenaltyBreakAssignment: 200 +KeepEmptyLinesAtTheStartOfBlocks: false \ No newline at end of file diff --git a/.clang-tidy b/.clang-tidy new file mode 100644 index 0000000..d28ed7a --- /dev/null +++ b/.clang-tidy @@ -0,0 +1,22 @@ +# .clang-tidy +--- +Checks: > + -*, + bugprone-*, + clang-analyzer-*, + cppcoreguidelines-*, + modernize-*, + performance-*, + readability-*, + portability-*, + + -modernize-use-trailing-return-type, + -readability-avoid-const-params-in-decls, + -cppcoreguidelines-macro-usage, + -cppcoreguidelines-avoid-do-while + +ExcludeHeaderFilterRegex: '_generated.*' + +CheckOptions: + - key: readability-implicit-bool-conversion.AllowPointerConditions + value: true \ No newline at end of file diff --git a/.devcontainer/devcontainer.json b/.devcontainer/devcontainer.json new file mode 100644 index 0000000..46a94d4 --- /dev/null +++ b/.devcontainer/devcontainer.json @@ -0,0 +1,4 @@ +{ + "name": "Bigfoot", + "image": "git.romainboullard.com/bigfootdev/linuxbigfootbuilder:main" +} diff --git a/.gitattributes b/.gitattributes new file mode 100644 index 0000000..5dc46e6 --- /dev/null +++ b/.gitattributes @@ -0,0 +1,3 @@ +* text=auto eol=lf +*.{cmd,[cC][mM][dD]} text eol=crlf +*.{bat,[bB][aA][tT]} text eol=crlf \ No newline at end of file diff --git a/.gitea/workflows/ci.yml b/.gitea/workflows/ci.yml new file mode 100644 index 0000000..8c52204 --- /dev/null +++ b/.gitea/workflows/ci.yml @@ -0,0 +1,65 @@ +name: Bigfoot + +on: + push: + branches: + - '**' + workflow_dispatch: + +env: + CCACHE_BASEDIR: ${{ github.workspace }} + +jobs: + build-and-test: + runs-on: ubuntu-latest + timeout-minutes: 120 + container: + image: git.romainboullard.com/bigfootdev/linuxbigfootbuilder:main + strategy: + matrix: + build_type: ["Debug", "RelWithDebInfo", "Release"] + unity_build: ["ON", "OFF"] + name: "Build & Test ${{ matrix.build_type }} (Unity Build: ${{ matrix.unity_build }})" + steps: + - name: Install Node.js + run: apt-get update && apt-get install -y nodejs + + - name: Checkout repository + uses: actions/checkout@v6 + with: + submodules: recursive + + - name: Show ccache stats before + run: ccache --zero-stats + + - name: Build + run: | + conan install . --deployer=full_deploy --deployer-folder=build --remote=bigfootpackages -pr:h=clang -pr:b=clang --build=missing -s build_type=${{ matrix.build_type }} -o bigfoot/*:build_tests=True -o bigfoot/*:tracy=False -o bigfoot/*:build_tools=True -o bigfoot/*:vulkan=True -o bigfoot/*:build_benchmarks=True + cmake -S . -B ./build/${{ matrix.build_type }} --toolchain ./build/${{ matrix.build_type }}/generators/conan_toolchain.cmake -DCMAKE_BUILD_TYPE=${{ matrix.build_type }} -DCMAKE_UNITY_BUILD=${{ matrix.unity_build }} -G "Ninja" + cmake --build build/${{ matrix.build_type }} --parallel $(nproc) + + - name: Show ccache stats after + run: ccache --show-stats + + - name: Unit Tests + run: | + cd ./build/${{ matrix.build_type }} + xvfb-run ctest . --output-on-failure + + clang-format: + runs-on: ubuntu-latest + timeout-minutes: 120 + container: + image: git.romainboullard.com/bigfootdev/linuxbigfootbuilder:main + name: "Clang Format Checks" + steps: + - name: Install Node.js + run: apt-get update && apt-get install -y nodejs + + - name: Checkout repository + uses: actions/checkout@v6 + with: + submodules: recursive + + - name: Clang Format Checks + run: chmod +x format.sh && ./format.sh --check Bigfoot \ No newline at end of file diff --git a/.gitea/workflows/sonarqube.yml b/.gitea/workflows/sonarqube.yml new file mode 100644 index 0000000..6e8c798 --- /dev/null +++ b/.gitea/workflows/sonarqube.yml @@ -0,0 +1,47 @@ +name: Bigfoot + +on: + push: + branches: + - main + - Development + +jobs: + build-and-test: + runs-on: ubuntu-latest + timeout-minutes: 120 + container: + image: git.romainboullard.com/bigfootdev/linuxbigfootbuilder:main + name: "Sonarqube" + steps: + - name: Install Node.js + run: apt-get update && apt-get install -y nodejs + + - name: Checkout repository + uses: actions/checkout@v6 + with: + fetch-depth: 0 + submodules: recursive + + - name: Generate + run: | + conan install . --deployer=full_deploy --deployer-folder=build --remote=bigfootpackages -pr:h=clang_coverage -pr:b=clang_coverage --build=missing -s build_type=Debug -o bigfoot/*:build_tests=True -o bigfoot/*:tracy=False -o bigfoot/*:build_tools=True -o bigfoot/*:vulkan=True -o bigfoot/*:build_benchmarks=True + cmake -S . -B ./build/Debug --toolchain ./build/Debug/generators/conan_toolchain.cmake -DCMAKE_BUILD_TYPE=Debug -G "Ninja" + cmake --build build/Debug --parallel $(nproc) + + - name: Clang-Tidy + run: run-clang-tidy -p ./build/Debug/ >> tidy_result.txt + + - name: Infer + run: infer run --compilation-database build/Debug/compile_commands.json + + - name: SonarQube Scan + if: github.head_ref == 'main' || github.ref_name == 'main' + uses: SonarSource/sonarqube-scan-action@v7.0.0 + with: + args: > + -Dsonar.cxx.jsonCompilationDatabase=./build/Debug/compile_commands.json + -Dsonar.verbose=true + env: + SONAR_TOKEN: ${{ secrets.SONAR_TOKEN }} + SONAR_HOST_URL: ${{ secrets.SONAR_HOST }} \ No newline at end of file diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..129a851 --- /dev/null +++ b/.gitignore @@ -0,0 +1,21 @@ +[Bb]uild* +Environment/output +*.generated.h + +.scannerwork + +SonarqubeResult +*.profraw + +conan_imports_manifest.txt +CMakeUserPresets.json +conan.lock +conanbuildinfo.txt +conaninfo.txt +graph_info.json + +.idea + +test_package/Vendor + +graphviz \ No newline at end of file diff --git a/.inferconfig b/.inferconfig new file mode 100644 index 0000000..0e0dcd2 --- /dev/null +++ b/.inferconfig @@ -0,0 +1,3 @@ +{ + +} \ No newline at end of file diff --git a/Bigfoot/Sources/CMakeLists.txt b/Bigfoot/Sources/CMakeLists.txt new file mode 100644 index 0000000..8eca193 --- /dev/null +++ b/Bigfoot/Sources/CMakeLists.txt @@ -0,0 +1,3 @@ +add_subdirectory(${CMAKE_CURRENT_SOURCE_DIR}/Utils) +add_subdirectory(${CMAKE_CURRENT_SOURCE_DIR}/System) +add_subdirectory(${CMAKE_CURRENT_SOURCE_DIR}/Engine) \ No newline at end of file diff --git a/Bigfoot/Sources/Engine/BigFile/BigFileSchema.sql b/Bigfoot/Sources/Engine/BigFile/BigFileSchema.sql new file mode 100644 index 0000000..e307f48 --- /dev/null +++ b/Bigfoot/Sources/Engine/BigFile/BigFileSchema.sql @@ -0,0 +1,41 @@ +PRAGMA journal_mode=WAL; +PRAGMA foreign_keys = ON; + +DROP TABLE IF EXISTS AssetHeader; +CREATE TABLE IF NOT EXISTS AssetHeader ( + UUID BLOB NOT NULL UNIQUE, + Name TEXT NOT NULL UNIQUE, + TypeID INTEGER NOT NULL, + TypeName TEXT NOT NULL, + + CreateTime INTEGER NOT NULL DEFAULT(CAST(unixepoch('subsec') AS INTEGER) * 1000000), + ModificationTime INTEGER NOT NULL DEFAULT(CAST(unixepoch('subsec') AS INTEGER) * 1000000), + + PRIMARY KEY(UUID) +); + +CREATE TRIGGER IF NOT EXISTS AssetHeader_UpdateTime +AFTER UPDATE OF Name, TypeID, TypeName ON AssetHeader FOR EACH ROW +BEGIN + UPDATE AssetHeader + SET ModificationTime = CAST(unixepoch('subsec') AS INTEGER) * 1000000 + WHERE UUID = NEW.UUID; +END; + +DROP TABLE IF EXISTS Asset; +CREATE TABLE IF NOT EXISTS Asset ( + UUID BLOB NOT NULL UNIQUE, + + Asset BLOB NOT NULL, + + PRIMARY KEY(UUID), + FOREIGN KEY(UUID) REFERENCES AssetHeader(UUID) ON DELETE CASCADE +); + +CREATE TRIGGER IF NOT EXISTS Asset_UpdateTime +AFTER UPDATE OF Asset ON Asset FOR EACH ROW +BEGIN + UPDATE AssetHeader + SET ModificationTime = CAST(unixepoch('subsec') AS INTEGER) * 1000000 + WHERE UUID = NEW.UUID; +END; \ No newline at end of file diff --git a/Bigfoot/Sources/Engine/CMakeLists.txt b/Bigfoot/Sources/Engine/CMakeLists.txt new file mode 100644 index 0000000..943596b --- /dev/null +++ b/Bigfoot/Sources/Engine/CMakeLists.txt @@ -0,0 +1,25 @@ +get_filename_component(PackageName ${CMAKE_CURRENT_SOURCE_DIR} NAME) +project(${PackageName}) + +set(PublicDependencies + SQLite::SQLite3) +set(PrivateDependencies) +set(BigfootPublicDependencies + System + Utils) +set(BigfootPrivateDependencies) + +set(BIGFOOT_MAJOR 0) +set(BIGFOOT_MINOR 1) +set(BIGFOOT_PATCH 0) +set(BIGFOOT_NAME "Bigfoot") +configure_file(${CMAKE_CURRENT_SOURCE_DIR}/Include/Engine/EngineInfo_generated.hpp.in ${CMAKE_CURRENT_SOURCE_DIR}/Include/Engine/EngineInfo_generated.hpp @ONLY) + +bigfoot_create_logger() + +bigfoot_create_package_lib( + "${PublicDependencies}" + "${PrivateDependencies}" + "${BigfootPublicDependencies}" + "${BigfootPrivateDependencies}" + "") \ No newline at end of file diff --git a/Bigfoot/Sources/Engine/Include/Engine/BigFile/BigFileInfo_generated.hpp.in b/Bigfoot/Sources/Engine/Include/Engine/BigFile/BigFileInfo_generated.hpp.in new file mode 100644 index 0000000..66f4d7e --- /dev/null +++ b/Bigfoot/Sources/Engine/Include/Engine/BigFile/BigFileInfo_generated.hpp.in @@ -0,0 +1,19 @@ +@AUTO_GENERATED_COMMENT@ + +/********************************************************************* + * \file BigFileInfo.generated.hpp + * + *********************************************************************/ +#ifndef BIGFOOT_@BIGFILE_NAME@_BIGFILEINFO_GENERATED_HPP +#define BIGFOOT_@BIGFILE_NAME@_BIGFILEINFO_GENERATED_HPP + +#include + +namespace Bigfoot +{ +/* + * BigFile location + */ +constexpr eastl::string_view BIGFILE_@BIGFILE_NAME@_LOCATION {"@BIGFILE_LOCATION@"}; +} // namespace Bigfoot +#endif \ No newline at end of file diff --git a/Bigfoot/Sources/Engine/Include/Engine/EngineAssertHandler.hpp b/Bigfoot/Sources/Engine/Include/Engine/EngineAssertHandler.hpp new file mode 100644 index 0000000..1c969a7 --- /dev/null +++ b/Bigfoot/Sources/Engine/Include/Engine/EngineAssertHandler.hpp @@ -0,0 +1,60 @@ +/********************************************************************* + * \file EngineAssertHandler.hpp + * + * \author Romain BOULLARD + * \date December 2025 + *********************************************************************/ +#ifndef BIGFOOT_ENGINE_ENGINEASSERTHANDLER_HPP +#define BIGFOOT_ENGINE_ENGINEASSERTHANDLER_HPP +#include + +#include + +#if defined BIGFOOT_NOT_OPTIMIZED +#include + +#include +#include +#include + +namespace Bigfoot +{ +class EngineAssertHandler +{ + public: + EngineAssertHandler() = delete; + + EngineAssertHandler(const EngineAssertHandler& p_handler) = delete; + EngineAssertHandler(EngineAssertHandler&& p_handler) = delete; + + ~EngineAssertHandler() = delete; + + /** + * Handle an assertion. + * + * \param p_location Location of the assertion. + * \param p_stacktrace The stack trace + * \param p_format Format string for the assertion message. + * \param p_args Arguments for the format string. + */ + template + static void Handle(const std::source_location& p_location, + const std::string_view p_stacktrace, + std::format_string p_format, + ARGS&&... p_args) + { + BIGFOOT_LOG_FATAL(ENGINE_LOGGER, + "Assert: {} (File:{}, Line:{}, Function:{}\n{}", + std::format(p_format, eastl::forward(p_args)...), + p_location.file_name(), + p_location.line(), + p_location.function_name(), + p_stacktrace); + } + + EngineAssertHandler& operator=(const EngineAssertHandler& p_handler) = delete; + EngineAssertHandler& operator=(EngineAssertHandler&& p_handler) = delete; +}; +} // namespace Bigfoot +#endif +#endif diff --git a/Bigfoot/Sources/Engine/Include/Engine/EngineInfo_generated.hpp b/Bigfoot/Sources/Engine/Include/Engine/EngineInfo_generated.hpp new file mode 100644 index 0000000..9c95d8f --- /dev/null +++ b/Bigfoot/Sources/Engine/Include/Engine/EngineInfo_generated.hpp @@ -0,0 +1,25 @@ +// AUTO-GENERATED DO NOT TOUCH + +/********************************************************************* + * \file EngineInfo_generated.hpp + * + *********************************************************************/ +#ifndef BIGFOOT_ENGINE_ENGINEINFO_GENERATED_HPP +#define BIGFOOT_ENGINE_ENGINEINFO_GENERATED_HPP +#include + +#include + +namespace Bigfoot +{ +/* + * Engine version + */ +constexpr Version BIGFOOT_VERSION {0, 1, 0}; + +/* + * Engine name + */ +constexpr eastl::string_view BIGFOOT_NAME {"Bigfoot"}; +} // namespace Bigfoot +#endif diff --git a/Bigfoot/Sources/Engine/Include/Engine/EngineInfo_generated.hpp.in b/Bigfoot/Sources/Engine/Include/Engine/EngineInfo_generated.hpp.in new file mode 100644 index 0000000..17110bc --- /dev/null +++ b/Bigfoot/Sources/Engine/Include/Engine/EngineInfo_generated.hpp.in @@ -0,0 +1,25 @@ +@AUTO_GENERATED_COMMENT@ + +/********************************************************************* + * \file EngineInfo_generated.hpp + * + *********************************************************************/ +#ifndef BIGFOOT_ENGINE_ENGINEINFO_GENERATED_HPP +#define BIGFOOT_ENGINE_ENGINEINFO_GENERATED_HPP +#include + +#include + +namespace Bigfoot +{ +/* + * Engine version + */ +constexpr Version BIGFOOT_VERSION {@BIGFOOT_MAJOR@, @BIGFOOT_MINOR@, @BIGFOOT_PATCH@}; + +/* + * Engine name + */ +constexpr eastl::string_view BIGFOOT_NAME {"@BIGFOOT_NAME@"}; +} // namespace Bigfoot +#endif \ No newline at end of file diff --git a/Bigfoot/Sources/Engine/Include/Engine/EngineLogger_generated.hpp b/Bigfoot/Sources/Engine/Include/Engine/EngineLogger_generated.hpp new file mode 100644 index 0000000..e3e58e9 --- /dev/null +++ b/Bigfoot/Sources/Engine/Include/Engine/EngineLogger_generated.hpp @@ -0,0 +1,21 @@ +// AUTO-GENERATED DO NOT TOUCH + +/********************************************************************* + * \file EngineLogger.generated.hpp + * + *********************************************************************/ +#ifndef BIGFOOT_ENGINELOGGER_GENERATED_HPP +#define BIGFOOT_ENGINELOGGER_GENERATED_HPP +#include + +#if defined BIGFOOT_NOT_OPTIMIZED + +namespace Bigfoot +{ +/* + * Logger + */ +inline Log::LoggerInfo ENGINE_LOGGER {"ENGINE_LOGGER", Flat::LogLevel::Trace}; +} // namespace Bigfoot +#endif +#endif diff --git a/Bigfoot/Sources/Engine/touch.cpp b/Bigfoot/Sources/Engine/touch.cpp new file mode 100644 index 0000000..cc4afd9 --- /dev/null +++ b/Bigfoot/Sources/Engine/touch.cpp @@ -0,0 +1 @@ +// to delete when an actual source is in Engine diff --git a/Bigfoot/Sources/System/CMakeLists.txt b/Bigfoot/Sources/System/CMakeLists.txt new file mode 100644 index 0000000..e25e7e0 --- /dev/null +++ b/Bigfoot/Sources/System/CMakeLists.txt @@ -0,0 +1,28 @@ +get_filename_component(PackageName ${CMAKE_CURRENT_SOURCE_DIR} NAME) +project(${PackageName}) + +set(PublicDependencies + $<$:quill::quill> + mimalloc + stduuid::stduuid) +set(PrivateDependencies) +set(BigfootPublicDependencies + Utils) +set(BigfootPrivateDependencies) + +bigfoot_create_package_lib( + "${PublicDependencies}" + "${PrivateLibraries}" + "${BigfootPublicDependencies}" + "${BigfootPrivateDependencies}" + "") + +bigfoot_create_logger() + +target_compile_definitions(${PROJECT_NAME} + PUBLIC $<$:QUILL_NO_EXCEPTIONS> + PUBLIC $<$:QUILL_DISABLE_NON_PREFIXED_MACROS> + + PUBLIC MI_SHARED_LIB) +set_source_files_properties(${CMAKE_CURRENT_SOURCE_DIR}/MimallocImpl.cpp PROPERTIES SKIP_UNITY_BUILD_INCLUSION ON) + diff --git a/Bigfoot/Sources/System/File.cpp b/Bigfoot/Sources/System/File.cpp new file mode 100644 index 0000000..ff57db3 --- /dev/null +++ b/Bigfoot/Sources/System/File.cpp @@ -0,0 +1,66 @@ +/********************************************************************* + * \file File.cpp + * + * \author Romain BOULLARD + * \date December 2025 + *********************************************************************/ +#include + +namespace Bigfoot +{ +File::File(const eastl::string_view p_path): + m_path(p_path.data()), + m_pathString(p_path) +{ +} + +/****************************************************************************************/ + +bool File::IsAbsolute() const +{ + return m_path.is_absolute(); +} + +/****************************************************************************************/ + +bool File::IsRelative() const +{ + return m_path.is_relative(); +} + +/****************************************************************************************/ + +bool File::Exists() const +{ + return std::filesystem::exists(m_path); +} + +/****************************************************************************************/ + +eastl::string_view File::Path() const +{ + return m_pathString; +} + +/****************************************************************************************/ + +File File::Absolute() const +{ + return File {std::filesystem::absolute(m_path)}; +} + +/****************************************************************************************/ + +File File::Relative() const +{ + return File {std::filesystem::relative(m_path)}; +} + +/****************************************************************************************/ + +File::File(const std::filesystem::path& p_path): + m_path(p_path), + m_pathString(m_path.string().c_str()) +{ +} +} // namespace Bigfoot diff --git a/Bigfoot/Sources/System/Include/System/File.hpp b/Bigfoot/Sources/System/Include/System/File.hpp new file mode 100644 index 0000000..0c67f62 --- /dev/null +++ b/Bigfoot/Sources/System/Include/System/File.hpp @@ -0,0 +1,103 @@ +/********************************************************************* + * \file File.hpp + * + * \author Romain BOULLARD + * \date December 2025 + *********************************************************************/ +#ifndef BIGFOOT_SYSTEM_FILE_HPP +#define BIGFOOT_SYSTEM_FILE_HPP + +#include +#include + +#include + +namespace Bigfoot +{ +class File +{ + public: + /** + * Constructor + * + * \param p_path The path + */ + File(const eastl::string_view p_path); + + File(const File& p_path) = default; + File(File&& p_path) = default; + + /** + * Check if the file is relative to the current executable + * + * \return True if the file is relative, false otherwise + */ + [[nodiscard]] + bool IsRelative() const; + + /** + * Check if the file is absolute + * + * \return True if the file is absolute, false otherwise + */ + [[nodiscard]] + bool IsAbsolute() const; + + /** + * Check if the file exists + * + * \return True if it exists, false otherwise + */ + [[nodiscard]] + bool Exists() const; + + /** + * Get the file path + * + * \return The path + */ + [[nodiscard]] + eastl::string_view Path() const; + + /** + * Get the same file, relative to the current executable + * + * \return The relative file + */ + [[nodiscard]] + File Relative() const; + + /** + * Get the same file, with an absolute path + * + * \return The absolute file + */ + [[nodiscard]] + File Absolute() const; + + ~File() = default; + + File& operator=(const File& p_path) = default; + File& operator=(File&& p_path) = default; + + private: + /** + * Constructor + * + * \param p_path The path + */ + File(const std::filesystem::path& p_path); + + /** + * The path + */ + std::filesystem::path m_path; + + /* + * The path as a string + */ + eastl::string m_pathString; +}; +} // namespace Bigfoot + +#endif diff --git a/Bigfoot/Sources/System/Include/System/Log/EASTLFormatters.hpp b/Bigfoot/Sources/System/Include/System/Log/EASTLFormatters.hpp new file mode 100644 index 0000000..8d2411c --- /dev/null +++ b/Bigfoot/Sources/System/Include/System/Log/EASTLFormatters.hpp @@ -0,0 +1,95 @@ +/********************************************************************* + * \file EASTLFormatters.hpp + * + * \author Romain BOULLARD + * \date December 2025 + *********************************************************************/ +#ifndef BIGFOOT_SYSTEM_EASTLFORMATTERS_HPP +#define BIGFOOT_SYSTEM_EASTLFORMATTERS_HPP +#include + +#if defined(BIGFOOT_NOT_OPTIMIZED) +#include +#endif + +#include + +#include +#include + +// STRING + +template<> +struct std::formatter +{ + constexpr auto parse(std::format_parse_context& ctx) + { + return ctx.begin(); + } + + template + auto format(const eastl::string& p_string, FormatContext& ctx) const + { + return std::format_to(ctx.out(), "{}", p_string.c_str()); + } +}; + +#if defined BIGFOOT_NOT_OPTIMIZED +template<> +struct fmtquill::formatter +{ + constexpr auto parse(format_parse_context& ctx) + { + return ctx.begin(); + } + + auto format(const eastl::string& p_string, format_context& ctx) const + { + return fmtquill::format_to(ctx.out(), "{}", p_string.c_str()); + } +}; + +template<> +struct quill::Codec: quill::DeferredFormatCodec +{ +}; +#endif + +// STRING_VIEW + +template<> +struct std::formatter +{ + constexpr auto parse(std::format_parse_context& ctx) + { + return ctx.begin(); + } + + template + auto format(const eastl::string_view& p_stringView, FormatContext& ctx) const + { + return std::format_to(ctx.out(), "{}", p_stringView.data()); + } +}; + +#if defined BIGFOOT_NOT_OPTIMIZED +template<> +struct fmtquill::formatter +{ + constexpr auto parse(format_parse_context& ctx) + { + return ctx.begin(); + } + + auto format(const eastl::string_view& p_stringView, format_context& ctx) const + { + return fmtquill::format_to(ctx.out(), "{}", p_stringView.data()); + } +}; + +template<> +struct quill::Codec: quill::DeferredFormatCodec +{ +}; +#endif +#endif diff --git a/Bigfoot/Sources/System/Include/System/Log/Log.fbs b/Bigfoot/Sources/System/Include/System/Log/Log.fbs new file mode 100644 index 0000000..727798b --- /dev/null +++ b/Bigfoot/Sources/System/Include/System/Log/Log.fbs @@ -0,0 +1,16 @@ +namespace Bigfoot.Flat; + +enum LogSinkType: byte +{ + Console +} + +enum LogLevel: byte +{ + Debug, + Trace, + Info, + Warn, + Error, + Critical +} \ No newline at end of file diff --git a/Bigfoot/Sources/System/Include/System/Log/Log.hpp b/Bigfoot/Sources/System/Include/System/Log/Log.hpp new file mode 100644 index 0000000..37c7800 --- /dev/null +++ b/Bigfoot/Sources/System/Include/System/Log/Log.hpp @@ -0,0 +1,182 @@ +/********************************************************************* + * \file Log.hpp + * + * \author Romain BOULLARD + * \date October 2025 + *********************************************************************/ +#ifndef BIGFOOT_SYSTEM_LOG_HPP +#define BIGFOOT_SYSTEM_LOG_HPP +#include + +#if defined BIGFOOT_NOT_OPTIMIZED +#include + +#include + +#include + +#ifdef BIGFOOT_WINDOWS +#pragma warning(disable: 4702) +#endif +#include +#include +#include +#include +#include +#if defined BIGFOOT_WINDOWS +#pragma warning(default: 4702) +#endif + +namespace Bigfoot +{ +class Log +{ + public: + struct LoggerInfo + { + std::string m_name; + Flat::LogLevel m_level; + }; + + Log(); + + Log(const Log& p_logger) = delete; + Log(Log&& p_logger) = delete; + + /** + * Register a logger. + * + * \param p_loggerInfo The logger to register + */ + [[nodiscard]] + quill::Logger* RegisterLogger(const LoggerInfo& p_loggerInfo); + + /** + * Register a logger. + * + * \param p_loggerInfo The logger to get + * \return The logger, nullptr if it does not exist + */ + [[nodiscard]] + quill::Logger* GetLogger(const LoggerInfo& p_loggerInfo); + + /** + * Changes the loglevel of a Logger. + * + * \param p_loggerInfo The logger to change + * \param p_level The new level + */ + void ChangeLoggerLogLevel(LoggerInfo& p_loggerInfo, const Flat::LogLevel p_level); + + ~Log(); + + Log& operator=(const Log& p_logger) = delete; + Log& operator=(Log&& p_logger) = delete; + + private: + /** + * Set the LogLevel of a logger + * + * \param p_loggerInfo The logger to set + */ + void SetLoggerLevel(const LoggerInfo& p_loggerInfo); + + /* + * The sinks + */ + eastl::array, 1> m_sinks; +}; +} // namespace Bigfoot + +#define BIGFOOT_LOG_DEBUG(loggerName, fmt, ...) \ + do \ + { \ + if (quill::Logger* logger = Bigfoot::Singleton::Instance().GetLogger(loggerName)) \ + { \ + QUILL_LOG_DEBUG(logger, fmt __VA_OPT__(, ) __VA_ARGS__); \ + } \ + else \ + { \ + QUILL_LOG_DEBUG(Bigfoot::Singleton::Instance().RegisterLogger(loggerName), \ + fmt __VA_OPT__(, ) __VA_ARGS__); \ + } \ + } while (0) + +#define BIGFOOT_LOG_TRACE(loggerName, fmt, ...) \ + do \ + { \ + if (quill::Logger* logger = Bigfoot::Singleton::Instance().GetLogger(loggerName)) \ + { \ + QUILL_LOG_TRACE_L3(logger, fmt __VA_OPT__(, ) __VA_ARGS__); \ + } \ + else \ + { \ + QUILL_LOG_TRACE_L3(Bigfoot::Singleton::Instance().RegisterLogger(loggerName), \ + fmt __VA_OPT__(, ) __VA_ARGS__); \ + } \ + } while (0) + +#define BIGFOOT_LOG_INFO(loggerName, fmt, ...) \ + do \ + { \ + if (quill::Logger* logger = Bigfoot::Singleton::Instance().GetLogger(loggerName)) \ + { \ + QUILL_LOG_INFO(logger, fmt __VA_OPT__(, ) __VA_ARGS__); \ + } \ + else \ + { \ + QUILL_LOG_INFO(Bigfoot::Singleton::Instance().RegisterLogger(loggerName), \ + fmt __VA_OPT__(, ) __VA_ARGS__); \ + } \ + } while (0) + +#define BIGFOOT_LOG_WARN(loggerName, fmt, ...) \ + do \ + { \ + if (quill::Logger* logger = Bigfoot::Singleton::Instance().GetLogger(loggerName)) \ + { \ + QUILL_LOG_WARNING(logger, fmt __VA_OPT__(, ) __VA_ARGS__); \ + } \ + else \ + { \ + QUILL_LOG_WARNING(Bigfoot::Singleton::Instance().RegisterLogger(loggerName), \ + fmt __VA_OPT__(, ) __VA_ARGS__); \ + } \ + } while (0) + +#define BIGFOOT_LOG_ERROR(loggerName, fmt, ...) \ + do \ + { \ + if (quill::Logger* logger = Bigfoot::Singleton::Instance().GetLogger(loggerName)) \ + { \ + QUILL_LOG_ERROR(logger, fmt __VA_OPT__(, ) __VA_ARGS__); \ + } \ + else \ + { \ + QUILL_LOG_ERROR(Bigfoot::Singleton::Instance().RegisterLogger(loggerName), \ + fmt __VA_OPT__(, ) __VA_ARGS__); \ + } \ + } while (0) + +#define BIGFOOT_LOG_FATAL(loggerName, fmt, ...) \ + do \ + { \ + if (quill::Logger* logger = Bigfoot::Singleton::Instance().GetLogger(loggerName)) \ + { \ + QUILL_LOG_CRITICAL(logger, fmt __VA_OPT__(, ) __VA_ARGS__); \ + } \ + else \ + { \ + QUILL_LOG_CRITICAL(Bigfoot::Singleton::Instance().RegisterLogger(loggerName), \ + fmt __VA_OPT__(, ) __VA_ARGS__); \ + } \ + } while (0) +#else +#define BIGFOOT_LOG_DEBUG(loggerName, fmt, ...) +#define BIGFOOT_LOG_TRACE(loggerName, fmt, ...) +#define BIGFOOT_LOG_INFO(loggerName, fmt, ...) +#define BIGFOOT_LOG_WARN(loggerName, fmt, ...) +#define BIGFOOT_LOG_ERROR(loggerName, fmt, ...) +#define BIGFOOT_LOG_FATAL(loggerName, fmt, ...) +#endif +#endif diff --git a/Bigfoot/Sources/System/Include/System/Log/Log_generated.hpp b/Bigfoot/Sources/System/Include/System/Log/Log_generated.hpp new file mode 100644 index 0000000..016228b --- /dev/null +++ b/Bigfoot/Sources/System/Include/System/Log/Log_generated.hpp @@ -0,0 +1,136 @@ +// automatically generated by the FlatBuffers compiler, do not modify + + +#ifndef FLATBUFFERS_GENERATED_LOG_BIGFOOT_FLAT_H_ +#define FLATBUFFERS_GENERATED_LOG_BIGFOOT_FLAT_H_ + +#include "flatbuffers/flatbuffers.h" + +// Ensure the included flatbuffers.h is the same version as when this file was +// generated, otherwise it may not be compatible. +static_assert(FLATBUFFERS_VERSION_MAJOR == 25 && + FLATBUFFERS_VERSION_MINOR == 12 && + FLATBUFFERS_VERSION_REVISION == 19, + "Non-compatible flatbuffers version included"); + +#include "EASTL/unique_ptr.h" +#include "EASTL/string.h" + +namespace Bigfoot { +namespace Flat { + +enum class LogSinkType : int8_t { + Console = 0, + MIN = Console, + MAX = Console +}; + +inline const LogSinkType (&EnumValuesLogSinkType())[1] { + static const LogSinkType values[] = { + LogSinkType::Console + }; + return values; +} + +inline const char * const *EnumNamesLogSinkType() { + static const char * const names[2] = { + "Console", + nullptr + }; + return names; +} + +inline const char *EnumNameLogSinkType(LogSinkType e) { + if (::flatbuffers::IsOutRange(e, LogSinkType::Console, LogSinkType::Console)) return ""; + const size_t index = static_cast(e); + return EnumNamesLogSinkType()[index]; +} + +enum class LogLevel : int8_t { + Debug = 0, + Trace = 1, + Info = 2, + Warn = 3, + Error = 4, + Critical = 5, + MIN = Debug, + MAX = Critical +}; + +inline const LogLevel (&EnumValuesLogLevel())[6] { + static const LogLevel values[] = { + LogLevel::Debug, + LogLevel::Trace, + LogLevel::Info, + LogLevel::Warn, + LogLevel::Error, + LogLevel::Critical + }; + return values; +} + +inline const char * const *EnumNamesLogLevel() { + static const char * const names[7] = { + "Debug", + "Trace", + "Info", + "Warn", + "Error", + "Critical", + nullptr + }; + return names; +} + +inline const char *EnumNameLogLevel(LogLevel e) { + if (::flatbuffers::IsOutRange(e, LogLevel::Debug, LogLevel::Critical)) return ""; + const size_t index = static_cast(e); + return EnumNamesLogLevel()[index]; +} + +inline const ::flatbuffers::TypeTable *LogSinkTypeTypeTable() { + static const ::flatbuffers::TypeCode type_codes[] = { + { ::flatbuffers::ET_CHAR, 0, 0 } + }; + static const ::flatbuffers::TypeFunction type_refs[] = { + Bigfoot::Flat::LogSinkTypeTypeTable + }; + static const char * const names[] = { + "Console" + }; + static const ::flatbuffers::TypeTable tt = { + ::flatbuffers::ST_ENUM, 1, type_codes, type_refs, nullptr, nullptr, names + }; + return &tt; +} + +inline const ::flatbuffers::TypeTable *LogLevelTypeTable() { + static const ::flatbuffers::TypeCode type_codes[] = { + { ::flatbuffers::ET_CHAR, 0, 0 }, + { ::flatbuffers::ET_CHAR, 0, 0 }, + { ::flatbuffers::ET_CHAR, 0, 0 }, + { ::flatbuffers::ET_CHAR, 0, 0 }, + { ::flatbuffers::ET_CHAR, 0, 0 }, + { ::flatbuffers::ET_CHAR, 0, 0 } + }; + static const ::flatbuffers::TypeFunction type_refs[] = { + Bigfoot::Flat::LogLevelTypeTable + }; + static const char * const names[] = { + "Debug", + "Trace", + "Info", + "Warn", + "Error", + "Critical" + }; + static const ::flatbuffers::TypeTable tt = { + ::flatbuffers::ST_ENUM, 6, type_codes, type_refs, nullptr, nullptr, names + }; + return &tt; +} + +} // namespace Flat +} // namespace Bigfoot + +#endif // FLATBUFFERS_GENERATED_LOG_BIGFOOT_FLAT_H_ diff --git a/Bigfoot/Sources/System/Include/System/Log/TargetLogger_generated.hpp.in b/Bigfoot/Sources/System/Include/System/Log/TargetLogger_generated.hpp.in new file mode 100644 index 0000000..fbfa751 --- /dev/null +++ b/Bigfoot/Sources/System/Include/System/Log/TargetLogger_generated.hpp.in @@ -0,0 +1,21 @@ +@AUTO_GENERATED_COMMENT@ + +/********************************************************************* + * \file @LOGGER_FILENAME@.generated.hpp + * + *********************************************************************/ +#ifndef BIGFOOT_@LOGGER_FILENAME_UPPER@_GENERATED_HPP +#define BIGFOOT_@LOGGER_FILENAME_UPPER@_GENERATED_HPP +#include + +#if defined BIGFOOT_NOT_OPTIMIZED + +namespace Bigfoot +{ +/* + * Logger + */ +inline Log::LoggerInfo @LOGGER_NAME@ {"@LOGGER_NAME@", Flat::LogLevel::Trace}; +} // namespace Bigfoot +#endif +#endif \ No newline at end of file diff --git a/Bigfoot/Sources/System/Include/System/Profiler.hpp b/Bigfoot/Sources/System/Include/System/Profiler.hpp new file mode 100644 index 0000000..0c02d30 --- /dev/null +++ b/Bigfoot/Sources/System/Include/System/Profiler.hpp @@ -0,0 +1,64 @@ +/********************************************************************* + * \file Profiler.hpp + * + * \author Romain BOULLARD + * \date October 2025 + *********************************************************************/ +#ifndef BIGFOOT_CONCAT_PROFILER_HPP +#define BIGFOOT_CONCAT_PROFILER_HPP + +#ifdef TRACY +#include +#define BIGFOOT_PROFILER_THREADNAME(p_name) tracy::SetThreadName(p_name) + +#define BIGFOOT_PROFILER_FRAME() FrameMark +#define BIGFOOT_PROFILER_FRAME_START(p_name) FrameMarkStart(p_name) +#define BIGFOOT_PROFILER_FRAME_STOP(p_name) FrameMarkEnd(p_name) + +#define BIGFOOT_PROFILER_PROFILE_FUNCTION() ZoneScoped +#define BIGFOOT_PROFILER_PROFILE(p_name) ZoneScopedN(p_name) + +#define BIGFOOT_PROFILER_TEXT(p_text, p_size) ZoneText(p_text, p_size) + +#define BIGFOOT_PROFILER_MEMORY_ALLOC(p_ptr, p_size) TracyAlloc(p_ptr, p_size) +#define BIGFOOT_PROFILER_MEMORY_FREE(p_ptr) TracyFree(p_ptr) + +#define BIGFOOT_PROFILER_LOCKABLE(p_type, p_name) TracyLockable(p_type, p_name) +#define BIGFOOT_PROFILER_LOCK(p_name) LockMark(p_name) + +#define BIGFOOT_PROFILER_APPINFO(p_text, p_size) TracyAppInfo(p_text, p_size) + +#define BIGFOOT_PROFILER_ATTACH_FRAME_IMAGE(p_imageData, p_width, p_height, p_offset) \ + FrameImage(p_imageData, p_width, p_height, p_offset, false) + +#define BIGFOOT_PROFILER + +#define BIGFOOT_PROFILER_ONLY(...) __VA_ARGS__ +// TODO: profile GPU +#else +#define BIGFOOT_PROFILER_THREADNAME(p_name) + +#define BIGFOOT_PROFILER_FRAME() +#define BIGFOOT_PROFILER_FRAME_START(p_name) +#define BIGFOOT_PROFILER_FRAME_STOP(p_name) + +#define BIGFOOT_PROFILER_PROFILE_FUNCTION() +#define BIGFOOT_PROFILER_PROFILE(p_name) + +#define BIGFOOT_PROFILER_TEXT_FUNCTION(p_text, p_size) +#define BIGFOOT_PROFILER_TEXT(p_text, p_size) + +#define BIGFOOT_PROFILER_MEMORY_ALLOC(p_ptr, p_size) +#define BIGFOOT_PROFILER_MEMORY_FREE(p_ptr) + +#define BIGFOOT_PROFILER_LOCKABLE(p_type, p_name) p_type p_name +#define BIGFOOT_PROFILER_LOCK(p_name) + +#define BIGFOOT_PROFILER_APPINFO(p_text, p_size) + +#define BIGFOOT_PROFILER_ATTACH_FRAME_IMAGE(p_imageData, p_width, p_height, p_offset) + +#define BIGFOOT_PROFILER_ONLY(...) +// TODO: profile GPU +#endif +#endif diff --git a/Bigfoot/Sources/System/Include/System/SystemAssertHandler.hpp b/Bigfoot/Sources/System/Include/System/SystemAssertHandler.hpp new file mode 100644 index 0000000..6e58208 --- /dev/null +++ b/Bigfoot/Sources/System/Include/System/SystemAssertHandler.hpp @@ -0,0 +1,60 @@ +/********************************************************************* + * \file SystemAssertHandler.hpp + * + * \author Romain BOULLARD + * \date January 2026 + *********************************************************************/ +#ifndef BIGFOOT_SYSTEM_SYSTEMASSERTHANDLER_HPP +#define BIGFOOT_SYSTEM_SYSTEMASSERTHANDLER_HPP +#include + +#include + +#if defined BIGFOOT_NOT_OPTIMIZED +#include + +#include +#include +#include + +namespace Bigfoot +{ +class SystemAssertHandler +{ + public: + SystemAssertHandler() = delete; + + SystemAssertHandler(const SystemAssertHandler& p_handler) = delete; + SystemAssertHandler(SystemAssertHandler&& p_handler) = delete; + + ~SystemAssertHandler() = delete; + + /** + * Handle an assertion. + * + * \param p_location Location of the assertion. + * \param p_stacktrace The stack trace + * \param p_format Format string for the assertion message. + * \param p_args Arguments for the format string. + */ + template + static void Handle(const std::source_location& p_location, + const std::string_view p_stacktrace, + std::format_string p_format, + ARGS&&... p_args) + { + BIGFOOT_LOG_FATAL(SYSTEM_LOGGER, + "Assert: {} (File:{}, Line:{}, Function:{}\n{}", + std::format(p_format, eastl::forward(p_args)...), + p_location.file_name(), + p_location.line(), + p_location.function_name(), + p_stacktrace); + } + + SystemAssertHandler& operator=(const SystemAssertHandler& p_handler) = delete; + SystemAssertHandler& operator=(SystemAssertHandler&& p_handler) = delete; +}; +} // namespace Bigfoot +#endif +#endif diff --git a/Bigfoot/Sources/System/Include/System/SystemLogger_generated.hpp b/Bigfoot/Sources/System/Include/System/SystemLogger_generated.hpp new file mode 100644 index 0000000..dcdf934 --- /dev/null +++ b/Bigfoot/Sources/System/Include/System/SystemLogger_generated.hpp @@ -0,0 +1,21 @@ +// AUTO-GENERATED DO NOT TOUCH + +/********************************************************************* + * \file SystemLogger.generated.hpp + * + *********************************************************************/ +#ifndef BIGFOOT_SYSTEMLOGGER_GENERATED_HPP +#define BIGFOOT_SYSTEMLOGGER_GENERATED_HPP +#include + +#if defined BIGFOOT_NOT_OPTIMIZED + +namespace Bigfoot +{ +/* + * Logger + */ +inline Log::LoggerInfo SYSTEM_LOGGER {"SYSTEM_LOGGER", Flat::LogLevel::Trace}; +} // namespace Bigfoot +#endif +#endif diff --git a/Bigfoot/Sources/System/Include/System/Time.hpp b/Bigfoot/Sources/System/Include/System/Time.hpp new file mode 100644 index 0000000..fa14d24 --- /dev/null +++ b/Bigfoot/Sources/System/Include/System/Time.hpp @@ -0,0 +1,68 @@ +/********************************************************************* + * \file Time.hpp + * + * \author Romain BOULLARD + * \date December 2025 + *********************************************************************/ +#ifndef BIGFOOT_SYSTEM_TIME_HPP +#define BIGFOOT_SYSTEM_TIME_HPP +#include +#include +#include + +namespace Bigfoot +{ +class Time +{ + public: + Time(const std::uint64_t p_epoch); + + Time(const Time& p_time) = default; + Time(Time&& p_time) = default; + + [[nodiscard]] + std::uint32_t Year() const; + + [[nodiscard]] + std::uint32_t Month() const; + + [[nodiscard]] + std::uint32_t Day() const; + + [[nodiscard]] + std::uint32_t Hour() const; + + [[nodiscard]] + std::uint32_t Minute() const; + + [[nodiscard]] + std::uint32_t Second() const; + + [[nodiscard]] + std::uint32_t Microsecond() const; + + [[nodiscard]] + std::uint64_t Epoch() const; + + ~Time() = default; + + Time& operator=(const Time& p_time) = default; + Time& operator=(Time&& p_time) = default; + + [[nodiscard]] + auto operator<=>(const Time& p_other) const + { + return m_epoch <=> p_other.m_epoch; + } + + [[nodiscard]] + static Time Now(); + + private: + std::uint64_t m_epoch; + std::tm m_timeInfo; + std::chrono::microseconds m_microseconds; +}; +} // namespace Bigfoot + +#endif diff --git a/Bigfoot/Sources/System/Include/System/UUID/FlatUUID.hpp b/Bigfoot/Sources/System/Include/System/UUID/FlatUUID.hpp new file mode 100644 index 0000000..d8e7f7d --- /dev/null +++ b/Bigfoot/Sources/System/Include/System/UUID/FlatUUID.hpp @@ -0,0 +1,18 @@ +/********************************************************************* + * \file FlatUUID.hpp + * + * \author Romain BOULLARD + * \date December 2025 + *********************************************************************/ +#ifndef BIGFOOT_SYSTEM_FLATUUID_HPP +#define BIGFOOT_SYSTEM_FLATUUID_HPP +#include +#include + +namespace flatbuffers +{ +Bigfoot::Flat::UUID Pack(const Bigfoot::UUID& p_uuid); +Bigfoot::UUID UnPack(const Bigfoot::Flat::UUID& p_flatUUID); +} // namespace flatbuffers + +#endif diff --git a/Bigfoot/Sources/System/Include/System/UUID/UUID.fbs b/Bigfoot/Sources/System/Include/System/UUID/UUID.fbs new file mode 100644 index 0000000..c622b85 --- /dev/null +++ b/Bigfoot/Sources/System/Include/System/UUID/UUID.fbs @@ -0,0 +1,8 @@ +native_include "System/UUID/FlatUUID.hpp"; + +namespace Bigfoot.Flat; + +struct UUID (native_type: "::Bigfoot::UUID") +{ + bytes:[ubyte:16]; +} \ No newline at end of file diff --git a/Bigfoot/Sources/System/Include/System/UUID/UUID.hpp b/Bigfoot/Sources/System/Include/System/UUID/UUID.hpp new file mode 100644 index 0000000..21ff3b1 --- /dev/null +++ b/Bigfoot/Sources/System/Include/System/UUID/UUID.hpp @@ -0,0 +1,144 @@ +/********************************************************************* + * \file UUID.hpp + * + * \author Romain BOULLARD + * \date October 2025 + *********************************************************************/ +#ifndef BIGFOOT_SYSTEM_UUID_HPP +#define BIGFOOT_SYSTEM_UUID_HPP + +#include + +namespace Bigfoot +{ +class UUID +{ + public: + static constexpr std::uint32_t UUID_BYTE_SIZE = 16; + + UUID(); + + /** + * Constructor. + * + * \param p_string String to create the UUID, should be a UUID V4 + */ + explicit UUID(const std::string_view p_string); + + /** + * Constructor + * + * \param p_raw The raw UUID + */ + explicit UUID(const std::span p_raw); + + UUID(const UUID& p_uuid) = default; + UUID(UUID&& p_uuid) noexcept = default; + + ~UUID() = default; + + operator std::span() const; + operator std::string() const; + operator bool() const; + + UUID& operator=(const UUID& p_uuid) = default; + UUID& operator=(UUID&& p_uuid) noexcept = default; + + [[nodiscard]] + bool operator==(const UUID& p_uuid) const = default; + [[nodiscard]] + bool operator!=(const UUID& p_uuid) const = default; + [[nodiscard]] + bool operator<(const UUID& p_uuid) const; + + private: + /** + * Get a random generator + * + * \return A random generator + */ + static std::mt19937 GetRandomGenerator(); + + /** + * Get a UUID generator + * + * \return A UUID generator + */ + static uuids::uuid_random_generator GetUUIDGenerator(); + + public: + /** + * Null UUID. + */ + static UUID NULL_UUID; + + private: + friend struct std::hash; + + /** + * The uuid. + */ + uuids::uuid m_uuid; + + /** + * Random generator for the UUID + */ + inline static std::mt19937 ms_randomGenerator = GetRandomGenerator(); + + /** + * UUID generator + */ + inline static uuids::uuid_random_generator ms_uuidGenerator = GetUUIDGenerator(); +}; +} // namespace Bigfoot + +/****************************************************************************************/ + +template<> +struct std::hash +{ + std::size_t operator()(const Bigfoot::UUID& p_uuid) const noexcept + { + return std::hash()(p_uuid.m_uuid); + } +}; + +template<> +struct std::formatter +{ + constexpr auto parse(std::format_parse_context& ctx) + { + return ctx.begin(); + } + + template + auto format(const Bigfoot::UUID& p_uuid, FormatContext& ctx) const + { + return std::format_to(ctx.out(), "{}", static_cast(p_uuid)); + } +}; + +#if defined BIGFOOT_NOT_OPTIMIZED +#include + +template<> +struct fmtquill::formatter +{ + constexpr auto parse(format_parse_context& ctx) + { + return ctx.begin(); + } + + auto format(const Bigfoot::UUID& p_uuid, format_context& ctx) const + { + return fmtquill::format_to(ctx.out(), "{}", static_cast(p_uuid)); + } +}; + +template<> +struct quill::Codec: quill::DeferredFormatCodec +{ +}; +#endif + +#endif diff --git a/Bigfoot/Sources/System/Include/System/UUID/UUID_generated.hpp b/Bigfoot/Sources/System/Include/System/UUID/UUID_generated.hpp new file mode 100644 index 0000000..f02e7fa --- /dev/null +++ b/Bigfoot/Sources/System/Include/System/UUID/UUID_generated.hpp @@ -0,0 +1,74 @@ +// automatically generated by the FlatBuffers compiler, do not modify + + +#ifndef FLATBUFFERS_GENERATED_UUID_BIGFOOT_FLAT_H_ +#define FLATBUFFERS_GENERATED_UUID_BIGFOOT_FLAT_H_ + +#include "flatbuffers/flatbuffers.h" + +// Ensure the included flatbuffers.h is the same version as when this file was +// generated, otherwise it may not be compatible. +static_assert(FLATBUFFERS_VERSION_MAJOR == 25 && + FLATBUFFERS_VERSION_MINOR == 12 && + FLATBUFFERS_VERSION_REVISION == 19, + "Non-compatible flatbuffers version included"); + +#include "System/UUID/FlatUUID.hpp" + +#include "EASTL/unique_ptr.h" +#include "EASTL/string.h" + +namespace Bigfoot { +namespace Flat { + +struct UUID; + +inline const ::flatbuffers::TypeTable *UUIDTypeTable(); + +FLATBUFFERS_MANUALLY_ALIGNED_STRUCT(1) UUID FLATBUFFERS_FINAL_CLASS { + private: + uint8_t bytes_[16]; + + public: + struct Traits; + static const ::flatbuffers::TypeTable *MiniReflectTypeTable() { + return UUIDTypeTable(); + } + static FLATBUFFERS_CONSTEXPR_CPP11 const char *GetFullyQualifiedName() { + return "Bigfoot.Flat.UUID"; + } + UUID() + : bytes_() { + } + UUID(::flatbuffers::span _bytes) { + ::flatbuffers::CastToArray(bytes_).CopyFromSpan(_bytes); + } + const ::flatbuffers::Array *bytes() const { + return &::flatbuffers::CastToArray(bytes_); + } +}; +FLATBUFFERS_STRUCT_END(UUID, 16); + +struct UUID::Traits { + using type = UUID; +}; + +inline const ::flatbuffers::TypeTable *UUIDTypeTable() { + static const ::flatbuffers::TypeCode type_codes[] = { + { ::flatbuffers::ET_UCHAR, 1, -1 } + }; + static const int16_t array_sizes[] = { 16, }; + static const int64_t values[] = { 0, 16 }; + static const char * const names[] = { + "bytes" + }; + static const ::flatbuffers::TypeTable tt = { + ::flatbuffers::ST_STRUCT, 1, type_codes, nullptr, array_sizes, values, names + }; + return &tt; +} + +} // namespace Flat +} // namespace Bigfoot + +#endif // FLATBUFFERS_GENERATED_UUID_BIGFOOT_FLAT_H_ diff --git a/Bigfoot/Sources/System/Log/Log.cpp b/Bigfoot/Sources/System/Log/Log.cpp new file mode 100644 index 0000000..4162610 --- /dev/null +++ b/Bigfoot/Sources/System/Log/Log.cpp @@ -0,0 +1,92 @@ +/******************************************************************* + * \file Log.cpp + * + * \author Romain BOULLARD + * \date October 2025 + *********************************************************************/ +#include + +#if defined BIGFOOT_NOT_OPTIMIZED + +namespace Bigfoot +{ +Log::Log() +{ + quill::Backend::start(); + + m_sinks[static_cast(Flat::LogSinkType::Console)] = + quill::Frontend::create_or_get_sink( + std::string {Flat::EnumNameLogSinkType(Flat::LogSinkType::Console)}); +} + +/****************************************************************************************/ + +quill::Logger* Log::RegisterLogger(const LoggerInfo& p_loggerInfo) +{ + quill::Logger* logger = quill::Frontend::create_or_get_logger( + p_loggerInfo.m_name, + m_sinks[static_cast(Flat::LogSinkType::Console)]); + SetLoggerLevel(p_loggerInfo); + + return logger; +} + +/****************************************************************************************/ + +quill::Logger* Log::GetLogger(const LoggerInfo& p_loggerInfo) +{ + return quill::Frontend::get_logger(p_loggerInfo.m_name); +} + +/****************************************************************************************/ + +void Log::ChangeLoggerLogLevel(LoggerInfo& p_loggerInfo, const Flat::LogLevel p_level) +{ + p_loggerInfo.m_level = p_level; + SetLoggerLevel(p_loggerInfo); +} + +/****************************************************************************************/ + +void Log::SetLoggerLevel(const LoggerInfo& p_loggerInfo) +{ + constexpr auto logLevelToQuillLogLevel = [](const Flat::LogLevel p_level) constexpr -> quill::LogLevel + { + switch (p_level) + { + case Flat::LogLevel::Debug: + return quill::LogLevel::Debug; + case Flat::LogLevel::Trace: + return quill::LogLevel::TraceL3; + case Flat::LogLevel::Info: + return quill::LogLevel::Info; + case Flat::LogLevel::Warn: + return quill::LogLevel::Warning; + case Flat::LogLevel::Error: + return quill::LogLevel::Error; + case Flat::LogLevel::Critical: + return quill::LogLevel::Critical; + } + + return quill::LogLevel::TraceL3; + }; + + if (quill::Logger* logger = GetLogger(p_loggerInfo)) + { + logger->set_log_level(logLevelToQuillLogLevel(p_loggerInfo.m_level)); + } +} + +/****************************************************************************************/ + +Log::~Log() +{ + for (quill::Logger* logger: quill::Frontend::get_all_loggers()) + { + quill::Frontend::remove_logger(logger); + } + + quill::Backend::stop(); +} +} // namespace Bigfoot +#endif diff --git a/Bigfoot/Sources/System/MimallocImpl.cpp b/Bigfoot/Sources/System/MimallocImpl.cpp new file mode 100644 index 0000000..35093e8 --- /dev/null +++ b/Bigfoot/Sources/System/MimallocImpl.cpp @@ -0,0 +1,98 @@ +/********************************************************************* + * \file MimallocImpl.cpp + * + * \author Romain BOULLARD + * \date October 2025 + *********************************************************************/ +#include + +#if defined BIGFOOT_WINDOWS +#pragma comment(linker, "/include:mi_version") +#pragma warning(disable: 4100 4559) +#elif defined BIGFOOT_LINUX +#if defined(__GNUC__) && !defined(__llvm__) && !defined(__INTEL_COMPILER) +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wunused-parameter" +#else +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wunused-parameter" +#endif +#endif + +// Taken from mimalloc-new-delete.h + +// clang-format off + +// ---------------------------------------------------------------------------- +// This header provides convenient overrides for the new and +// delete operations in C++. +// +// This header should be included in only one source file! +// +// On Windows, or when linking dynamically with mimalloc, these +// can be more performant than the standard new-delete operations. +// See +// --------------------------------------------------------------------------- +#if defined(__cplusplus) + #include + #include + + #if defined(_MSC_VER) && defined(_Ret_notnull_) && defined(_Post_writable_byte_size_) + // stay consistent with VCRT definitions + #define mi_decl_new(n) mi_decl_nodiscard mi_decl_restrict _Ret_notnull_ _Post_writable_byte_size_(n) + #define mi_decl_new_nothrow(n) mi_decl_nodiscard mi_decl_restrict _Ret_maybenull_ _Success_(return != NULL) _Post_writable_byte_size_(n) + #else + #define mi_decl_new(n) mi_decl_nodiscard mi_decl_restrict + #define mi_decl_new_nothrow(n) mi_decl_nodiscard mi_decl_restrict + #endif + + void operator delete(void* p) noexcept { mi_free(p); BIGFOOT_PROFILER_MEMORY_FREE(p); }; + void operator delete[](void* p) noexcept { mi_free(p); BIGFOOT_PROFILER_MEMORY_FREE(p); }; + + void operator delete (void* p, const std::nothrow_t&) noexcept { mi_free(p); BIGFOOT_PROFILER_MEMORY_FREE(p); } + void operator delete[](void* p, const std::nothrow_t&) noexcept { mi_free(p); BIGFOOT_PROFILER_MEMORY_FREE(p); } + + mi_decl_new(n) void* operator new(std::size_t n) noexcept(false) { void* p = mi_new(n); BIGFOOT_PROFILER_MEMORY_ALLOC(p, n); return p; } + mi_decl_new(n) void* operator new[](std::size_t n) noexcept(false) { void* p = mi_new(n); BIGFOOT_PROFILER_MEMORY_ALLOC(p, n); return p; } + + mi_decl_new_nothrow(n) void* operator new (std::size_t n, const std::nothrow_t& tag) noexcept { (void)(tag); void* p = mi_new_nothrow(n); BIGFOOT_PROFILER_MEMORY_ALLOC(p, n); return p; } + mi_decl_new_nothrow(n) void* operator new[](std::size_t n, const std::nothrow_t& tag) noexcept { (void)(tag); void* p = mi_new_nothrow(n); BIGFOOT_PROFILER_MEMORY_ALLOC(p, n); return p; } + + // Not from mimalloc-new-delete.h, but necessary for EASTL + void* operator new[](size_t size, const char* name, int flags, unsigned debugFlags, const char* file, int line) noexcept(false) { void* p = mi_new(size); BIGFOOT_PROFILER_MEMORY_ALLOC(p, size); return p; } + + #if (__cplusplus >= 201402L || _MSC_VER >= 1916) + void operator delete (void* p, std::size_t n) noexcept { mi_free_size(p,n); BIGFOOT_PROFILER_MEMORY_FREE(p); }; + void operator delete[](void* p, std::size_t n) noexcept { mi_free_size(p,n); BIGFOOT_PROFILER_MEMORY_FREE(p); }; + #endif + + #if (__cplusplus > 201402L || defined(__cpp_aligned_new)) + void operator delete (void* p, std::align_val_t al) noexcept { mi_free_aligned(p, static_cast(al)); BIGFOOT_PROFILER_MEMORY_FREE(p); } + void operator delete[](void* p, std::align_val_t al) noexcept { mi_free_aligned(p, static_cast(al)); BIGFOOT_PROFILER_MEMORY_FREE(p); } + void operator delete (void* p, std::size_t n, std::align_val_t al) noexcept { mi_free_size_aligned(p, n, static_cast(al)); BIGFOOT_PROFILER_MEMORY_FREE(p); }; + void operator delete[](void* p, std::size_t n, std::align_val_t al) noexcept { mi_free_size_aligned(p, n, static_cast(al)); BIGFOOT_PROFILER_MEMORY_FREE(p); }; + void operator delete (void* p, std::align_val_t al, const std::nothrow_t&) noexcept { mi_free_aligned(p, static_cast(al)); BIGFOOT_PROFILER_MEMORY_FREE(p); } + void operator delete[](void* p, std::align_val_t al, const std::nothrow_t&) noexcept { mi_free_aligned(p, static_cast(al)); BIGFOOT_PROFILER_MEMORY_FREE(p); } + + void* operator new (std::size_t n, std::align_val_t al) noexcept(false) { void* p = mi_new_aligned(n, static_cast(al)); BIGFOOT_PROFILER_MEMORY_ALLOC(p, n); return p; } + void* operator new[](std::size_t n, std::align_val_t al) noexcept(false) { void* p = mi_new_aligned(n, static_cast(al)); BIGFOOT_PROFILER_MEMORY_ALLOC(p, n); return p; } + void* operator new (std::size_t n, std::align_val_t al, const std::nothrow_t&) noexcept { void* p = mi_new_aligned_nothrow(n, static_cast(al)); BIGFOOT_PROFILER_MEMORY_ALLOC(p, n); return p; } + void* operator new[](std::size_t n, std::align_val_t al, const std::nothrow_t&) noexcept { void* p = mi_new_aligned_nothrow(n, static_cast(al)); BIGFOOT_PROFILER_MEMORY_ALLOC(p, n); return p; } + + // Not from mimalloc-new-delete.h, but necessary for EASTL + void* operator new[](size_t size, size_t alignment, size_t alignmentOffset, const char* pName, int flags, unsigned debugFlags, const char* file, int line) noexcept(false) { void* p = mi_new_aligned(size, alignment); BIGFOOT_PROFILER_MEMORY_ALLOC(p, size); return p; } + #endif + +#endif + +// clang-format on + +#if defined BIGFOOT_WINDOWS +#pragma warning(default: 4100 4559) +#elif defined BIGFOOT_LINUX +#if defined(__GNUC__) && !defined(__llvm__) && !defined(__INTEL_COMPILER) +#pragma GCC diagnostic pop +#else +#pragma clang diagnostic pop +#endif +#endif diff --git a/Bigfoot/Sources/System/Time.cpp b/Bigfoot/Sources/System/Time.cpp new file mode 100644 index 0000000..672f027 --- /dev/null +++ b/Bigfoot/Sources/System/Time.cpp @@ -0,0 +1,121 @@ +/********************************************************************* + * \file Time.cpp + * + * \author Romain BOULLARD + * \date December 2025 + *********************************************************************/ +#include + +#include + +namespace +{ +[[nodiscard]] +std::tm GetTimeInfo(const std::time_t& p_time) +{ + std::tm timeInfo {}; +#ifdef BIGFOOT_WINDOWS + [[maybe_unused]] + const errno_t error = gmtime_s(&timeInfo, &p_time); + if (error != 0) + { + char errnoStr[256]; + strerror_s(errnoStr, error); + + CRITICAL_ASSERT(Bigfoot::SystemAssertHandler, + false, + "Failed to convert epoch time to calendar time. {}", + errnoStr); + } +#elif BIGFOOT_LINUX + [[maybe_unused]] + const std::tm* error = gmtime_r(&p_time, &timeInfo); + CRITICAL_ASSERT(Bigfoot::SystemAssertHandler, error, "Failed to convert epoch time to calendar time"); +#else + static_assert(false, "not implemented"); +#endif + + return timeInfo; +} +} // namespace + +namespace Bigfoot +{ +Time::Time(const std::uint64_t p_epoch): + m_epoch(p_epoch), + m_timeInfo(GetTimeInfo(std::chrono::system_clock::to_time_t( + std::chrono::time_point {std::chrono::microseconds {m_epoch}}))), + m_microseconds(std::chrono::duration_cast( + std::chrono::duration_cast(std::chrono::time_point { + std::chrono::microseconds {m_epoch}}.time_since_epoch()) % + std::chrono::seconds(1))) +{ +} + +/****************************************************************************************/ + +std::uint32_t Time::Year() const +{ + return m_timeInfo.tm_year + 1900; +} + +/****************************************************************************************/ + +std::uint32_t Time::Month() const +{ + return m_timeInfo.tm_mon + 1; +} + +/****************************************************************************************/ + +std::uint32_t Time::Day() const +{ + return m_timeInfo.tm_mday; +} + +/****************************************************************************************/ + +std::uint32_t Time::Hour() const +{ + return m_timeInfo.tm_hour; +} + +/****************************************************************************************/ + +std::uint32_t Time::Minute() const +{ + return m_timeInfo.tm_min; +} + +/****************************************************************************************/ + +std::uint32_t Time::Second() const +{ + return m_timeInfo.tm_sec; +} + +/****************************************************************************************/ + +std::uint32_t Time::Microsecond() const +{ + return static_cast(m_microseconds.count()); +} + +/****************************************************************************************/ + +std::uint64_t Time::Epoch() const +{ + return m_epoch; +} + +/****************************************************************************************/ + +Time Time::Now() +{ + const std::chrono::time_point time = std::chrono::system_clock::now(); + const std::uint64_t epochInMicroSeconds = + std::chrono::duration_cast(time.time_since_epoch()).count(); + + return Time {epochInMicroSeconds}; +} +} // namespace Bigfoot diff --git a/Bigfoot/Sources/System/UUID/FlatUUID.cpp b/Bigfoot/Sources/System/UUID/FlatUUID.cpp new file mode 100644 index 0000000..78bfeb9 --- /dev/null +++ b/Bigfoot/Sources/System/UUID/FlatUUID.cpp @@ -0,0 +1,27 @@ +/********************************************************************* + * \file FlatUUID.cpp + * + * \author Romain BOULLARD + * \date December 2025 + *********************************************************************/ +#include + +namespace flatbuffers +{ +Bigfoot::Flat::UUID Pack(const Bigfoot::UUID& p_uuid) +{ + const std::span bytes = p_uuid; + return Bigfoot::Flat::UUID { + std::span {reinterpret_cast(bytes.data()), + bytes.size()}}; +} + +/****************************************************************************************/ + +Bigfoot::UUID UnPack(const Bigfoot::Flat::UUID& p_flatUUID) +{ + const std::span bytesView {p_flatUUID.bytes()->data(), + p_flatUUID.bytes()->size()}; + return Bigfoot::UUID {std::as_bytes(bytesView)}; +} +} // namespace flatbuffers diff --git a/Bigfoot/Sources/System/UUID/UUID.cpp b/Bigfoot/Sources/System/UUID/UUID.cpp new file mode 100644 index 0000000..cd87cb6 --- /dev/null +++ b/Bigfoot/Sources/System/UUID/UUID.cpp @@ -0,0 +1,87 @@ +/********************************************************************* + * \file UUID.cpp + * + * \author Romain BOULLARD + * \date October 2025 + *********************************************************************/ +#include + +namespace Bigfoot +{ +UUID UUID::NULL_UUID {"00000000-0000-0000-0000-000000000000"}; + +/****************************************************************************************/ + +UUID::UUID(): + m_uuid(ms_uuidGenerator()) +{ +} + +/****************************************************************************************/ + +UUID::UUID(const std::string_view p_string): + UUID(NULL_UUID) +{ + if (const std::optional value = uuids::uuid::from_string(p_string); value.has_value()) + { + m_uuid = value.value(); + } +} + +/****************************************************************************************/ + +UUID::UUID(const std::span p_raw) +{ + const std::span raw { + const_cast(std::bit_cast(p_raw.data())), + UUID_BYTE_SIZE}; + + m_uuid = uuids::uuid {raw}; +} + +/****************************************************************************************/ + +UUID::operator std::span() const +{ + return m_uuid.as_bytes(); +} + +/****************************************************************************************/ + +UUID::operator std::string() const +{ + return uuids::to_string(m_uuid); +} + +/****************************************************************************************/ + +UUID::operator bool() const +{ + return *this != NULL_UUID; +} + +/****************************************************************************************/ + +bool UUID::operator<(const UUID& p_uuid) const +{ + return m_uuid < p_uuid.m_uuid; +} + +/****************************************************************************************/ + +std::mt19937 UUID::GetRandomGenerator() +{ + std::random_device randomDevice; + std::array seed {}; + std::generate(seed.begin(), seed.end(), std::reference_wrapper {randomDevice}); + std::seed_seq seedSeq(seed.begin(), seed.end()); + return std::mt19937 {seedSeq}; +} + +/****************************************************************************************/ + +uuids::uuid_random_generator UUID::GetUUIDGenerator() +{ + return uuids::uuid_random_generator {ms_randomGenerator}; +} +} // namespace Bigfoot diff --git a/Bigfoot/Sources/Utils/CMakeLists.txt b/Bigfoot/Sources/Utils/CMakeLists.txt new file mode 100644 index 0000000..f12f19a --- /dev/null +++ b/Bigfoot/Sources/Utils/CMakeLists.txt @@ -0,0 +1,15 @@ +get_filename_component(PackageName ${CMAKE_CURRENT_SOURCE_DIR} NAME) +project(${PackageName}) + +set(PublicDependencies + $<$:cpptrace::cpptrace>) +set(PrivateDependencies) +set(BigfootPublicDependencies) +set(BigfootPrivateDependencies) + +bigfoot_create_package_lib( + "${PublicDependencies}" + "${PrivateLibraries}" + "${BigfootPublicDependencies}" + "${BigfootPrivateDependencies}" + "") \ No newline at end of file diff --git a/Bigfoot/Sources/Utils/Include/Utils/Assert.hpp b/Bigfoot/Sources/Utils/Include/Utils/Assert.hpp new file mode 100644 index 0000000..4bdefc2 --- /dev/null +++ b/Bigfoot/Sources/Utils/Include/Utils/Assert.hpp @@ -0,0 +1,94 @@ +/********************************************************************* + * \file Assert.hpp + * + * \author Romain BOULLARD + * \date October 2025 + *********************************************************************/ +#ifndef BIGFOOT_UTILS_ASSERT_HPP +#define BIGFOOT_UTILS_ASSERT_HPP + +#if defined BIGFOOT_NOT_OPTIMIZED + +#include + +#include +#include + +#if defined BIGFOOT_LINUX +#include +#endif + +#if defined BIGFOOT_WINDOWS +#define BREAK \ + do \ + { \ + __debugbreak(); \ + } while (false) +#elif defined BIGFOOT_LINUX +#define BREAK \ + do \ + { \ + std::raise(SIGTRAP); \ + } while (false) +#endif + +#define ASSERT(HANDLER, p_assert, p_message, ...) \ + do \ + { \ + constexpr std::source_location location = std::source_location::current(); \ + if (!(p_assert)) [[unlikely]] \ + { \ + constexpr auto stacktrace = []() -> std::string \ + { \ + const cpptrace::stacktrace stacktrace = cpptrace::generate_trace(); \ + return stacktrace.to_string(); \ + }; \ + \ + HANDLER::Handle(location, stacktrace(), p_message __VA_OPT__(, ) __VA_ARGS__); \ + BREAK; \ + } \ + } while (false) + +#define SOFT_ASSERT(HANDLER, p_assert, p_message, ...) \ + do \ + { \ + constexpr std::source_location location = std::source_location::current(); \ + if (!(p_assert)) [[unlikely]] \ + { \ + constexpr auto stacktrace = []() -> std::string \ + { \ + const cpptrace::stacktrace stacktrace = cpptrace::generate_trace(); \ + return stacktrace.to_string(); \ + }; \ + \ + HANDLER::Handle(location, stacktrace(), p_message __VA_OPT__(, ) __VA_ARGS__); \ + BREAK; \ + } \ + } while (false) + +#define CRITICAL_ASSERT(HANDLER, p_assert, p_message, ...) \ + do \ + { \ + constexpr std::source_location location = std::source_location::current(); \ + if (!(p_assert)) [[unlikely]] \ + { \ + constexpr auto stacktrace = []() -> std::string \ + { \ + const cpptrace::stacktrace stacktrace = cpptrace::generate_trace(); \ + return stacktrace.to_string(); \ + }; \ + \ + HANDLER::Handle(location, stacktrace(), p_message __VA_OPT__(, ) __VA_ARGS__); \ + BREAK; \ + std::abort(); \ + } \ + } while (false) + +#else +#define ASSERT(HANDLER, p_assert, p_message, ...) + +#define SOFT_ASSERT(HANDLER, p_assert, p_message, ...) + +#define CRITICAL_ASSERT(HANDLER, p_assert, p_message, ...) +#endif +#endif diff --git a/Bigfoot/Sources/Utils/Include/Utils/Caster.hpp b/Bigfoot/Sources/Utils/Include/Utils/Caster.hpp new file mode 100644 index 0000000..635a149 --- /dev/null +++ b/Bigfoot/Sources/Utils/Include/Utils/Caster.hpp @@ -0,0 +1,49 @@ +/********************************************************************* + * \file Caster.hpp + * + * \author Romain BOULLARD + * \date October 2025 + *********************************************************************/ +#ifndef BIGFOOT_UTILS_CASTER_HPP +#define BIGFOOT_UTILS_CASTER_HPP +#include + +namespace Bigfoot +{ +template || eastl::is_base_of_v, bool> = true> +constexpr TO* Cast(FROM* p_object) +{ + return static_cast(p_object); +} + +template || eastl::is_base_of_v, bool> = true> +constexpr const TO* Cast(const FROM* p_object) +{ + return static_cast(p_object); +} + +template || eastl::is_base_of_v, bool> = true> +constexpr TO& Cast(FROM& p_object) +{ + return static_cast(p_object); +} + +template || eastl::is_base_of_v, bool> = true> +constexpr const TO& Cast(const FROM& p_object) +{ + return static_cast(p_object); +} +} // namespace Bigfoot + +#define BIGFOOT_NUMERIC_CAST(p_to, p_data) Bigfoot::NumericCast(p_data) + +#define BIGFOOT_OBJECT_CAST(p_to, p_object) Bigfoot::Cast(p_object) +#endif diff --git a/Bigfoot/Sources/Utils/Include/Utils/Concat.h b/Bigfoot/Sources/Utils/Include/Utils/Concat.h new file mode 100644 index 0000000..ef4beae --- /dev/null +++ b/Bigfoot/Sources/Utils/Include/Utils/Concat.h @@ -0,0 +1,17 @@ +/********************************************************************* + * \file Concat.h + * + * \author Romain BOULLARD + * \date October 2025 + *********************************************************************/ +#ifndef BIGFOOT_UTILS_CONCAT_H +#define BIGFOOT_UTILS_CONCAT_H + +#define CONCAT_IMPL(a, b) a b +#define CONCAT(a, b) CONCAT_IMPL(a, b) + +#define UNIQUE_IMPL(prefix, line) prefix##_##line +#define UNIQUE(prefix, line) UNIQUE_IMPL(prefix, line) +#define MAKE_UNIQUE_VARIABLE_NAME(prefix) UNIQUE(prefix, __LINE__) + +#endif diff --git a/Bigfoot/Sources/Utils/Include/Utils/Singleton.hpp b/Bigfoot/Sources/Utils/Include/Utils/Singleton.hpp new file mode 100644 index 0000000..1d6fa9f --- /dev/null +++ b/Bigfoot/Sources/Utils/Include/Utils/Singleton.hpp @@ -0,0 +1,108 @@ +/********************************************************************* + * \file Singleton.hpp + * + * \author Romain BOULLARD + * \date October 2025 + *********************************************************************/ +#ifndef BIGFOOT_UTILS_SINGLETON_HPP +#define BIGFOOT_UTILS_SINGLETON_HPP + +#include +#include +#include +#include + +namespace Bigfoot +{ +template +class Singleton +{ + public: + Singleton() = delete; + + Singleton(const Singleton& p_singleton) = delete; + Singleton(Singleton&& p_singleton) = delete; + + ~Singleton() = delete; + + /** + * Get the instance. + * + * \return The instance + */ + static constexpr TYPE& Instance() + { + return *eastl::bit_cast(ms_instance.data()); + } + + class Lifetime + { + public: + /** + * Constructor. + * + * \param p_args Arguments for the singleton + */ + template> || ...)>> + explicit Lifetime(ARGS&&... p_args) + { + Initialize(eastl::forward(p_args)...); + } + + Lifetime(const Lifetime& p_lifetime) = delete; + Lifetime(Lifetime&& p_lifetime) = delete; + + ~Lifetime() + { + Finalize(); + } + + [[nodiscard]] + Lifetime& operator=(const Lifetime& p_lifetime) = delete; + [[nodiscard]] + Lifetime& operator=(Lifetime&& p_lifetime) = delete; + }; + + [[nodiscard]] + Singleton& operator=(const Singleton& p_singleton) = delete; + [[nodiscard]] + Singleton& operator=(Singleton&& p_singleton) = delete; + + private: + /** + * Initialize the singleton. + * + * \param p_args Arguments for the singleton + */ + template + static void Initialize(ARGS&&... p_args) + { + new (ms_instance.data()) TYPE(eastl::forward(p_args)...); + + ms_initialized = true; + } + + /** + * Finalize the singleton. + * + */ + static void Finalize() + { + eastl::bit_cast(ms_instance.data())->~TYPE(); + + ms_initialized = false; + } + + /** + * The singleton. + */ + alignas(alignof(TYPE)) inline static eastl::array ms_instance; + + /** + * Is the singleton initialized? + */ + inline static bool ms_initialized = false; +}; +} // namespace Bigfoot +#endif diff --git a/Bigfoot/Sources/Utils/Include/Utils/TaggedType.hpp b/Bigfoot/Sources/Utils/Include/Utils/TaggedType.hpp new file mode 100644 index 0000000..a020837 --- /dev/null +++ b/Bigfoot/Sources/Utils/Include/Utils/TaggedType.hpp @@ -0,0 +1,131 @@ +/********************************************************************* + * \file TaggedType.h + * + * \author Romain BOULLARD + * \date December 2025 + *********************************************************************/ +#ifndef BIGFOOT_UTILS_TAGGEDTYPE_H +#define BIGFOOT_UTILS_TAGGEDTYPE_H + +#include + +namespace Bigfoot +{ +template +class TaggedType +{ + public: + constexpr TaggedType() = default; + + constexpr explicit TaggedType(TYPE p_value): + m_value(p_value) + { + } + + constexpr TaggedType(const TaggedType& p_taggedType) = default; + constexpr TaggedType(TaggedType&& p_taggedType) noexcept = default; + + ~TaggedType() = default; + + constexpr TaggedType& operator=(const TaggedType& p_taggedType) = default; + constexpr TaggedType& operator=(TaggedType&& p_taggedType) noexcept = default; + + constexpr TaggedType& operator=(const TYPE& p_value) + { + m_value = p_value; + return *this; + } + + constexpr explicit operator TYPE() const + { + return m_value; + } + + constexpr TYPE Get() const + { + return m_value; + } + + constexpr auto operator<=>(const TaggedType& p_other) const = default; + + constexpr TaggedType& operator+=(const TYPE& p_value) + { + m_value += p_value; + return *this; + } + + constexpr TaggedType& operator-=(const TYPE& p_value) + { + m_value -= p_value; + return *this; + } + + constexpr TaggedType& operator*=(const TYPE& p_value) + { + m_value *= p_value; + return *this; + } + + constexpr TaggedType& operator/=(const TYPE& p_value) + { + m_value /= p_value; + return *this; + } + + constexpr TaggedType& operator+=(const TaggedType& p_other) + { + m_value += p_other.m_value; + return *this; + } + + constexpr TaggedType& operator-=(const TaggedType& p_other) + { + m_value -= p_other.m_value; + return *this; + } + + constexpr TaggedType& operator*=(const TaggedType& p_other) + { + m_value *= p_other.m_value; + return *this; + } + + constexpr TaggedType& operator/=(const TaggedType& p_other) + { + m_value /= p_other.m_value; + return *this; + } + + template + friend constexpr TaggedType operator+(L p_left, R p_right) + { + return p_left += p_right; + } + + template + friend constexpr TaggedType operator-(L p_left, R p_right) + { + return p_left -= p_right; + } + + template + friend constexpr TaggedType operator*(L p_left, R p_right) + { + return p_left *= p_right; + } + + template + friend constexpr TaggedType operator/(L p_left, R p_right) + { + return p_left /= p_right; + } + + private: + /** + * The value + */ + TYPE m_value {}; +}; +} // namespace Bigfoot + +#endif diff --git a/Bigfoot/Sources/Utils/Include/Utils/TargetMacros.h b/Bigfoot/Sources/Utils/Include/Utils/TargetMacros.h new file mode 100644 index 0000000..3a95305 --- /dev/null +++ b/Bigfoot/Sources/Utils/Include/Utils/TargetMacros.h @@ -0,0 +1,21 @@ +/********************************************************************* + * \file TargetMacros.h + * + * \author Romain BOULLARD + * \date October 2025 + *********************************************************************/ +#ifndef BIGFOOT_UTILS_TARGETMACROS_H +#define BIGFOOT_UTILS_TARGETMACROS_H + +#if defined BIGFOOT_OPTIMIZED +#define BIGFOOT_OPTIMIZED_ONLY(...) __VA_ARGS__ +#define BIGFOOT_NOT_OPTIMIZED_ONLY(...) +#define BIGFOOT_OPTIMIZED_OR_NOT(p_optimized, p_notOptimized) p_optimized +#endif + +#if defined BIGFOOT_NOT_OPTIMIZED +#define BIGFOOT_OPTIMIZED_ONLY(...) +#define BIGFOOT_NOT_OPTIMIZED_ONLY(...) __VA_ARGS__ +#define BIGFOOT_OPTIMIZED_OR_NOT(p_optimized, p_notOptimized) p_notOptimized +#endif +#endif diff --git a/Bigfoot/Sources/Utils/Include/Utils/Version.hpp b/Bigfoot/Sources/Utils/Include/Utils/Version.hpp new file mode 100644 index 0000000..68e0bfa --- /dev/null +++ b/Bigfoot/Sources/Utils/Include/Utils/Version.hpp @@ -0,0 +1,158 @@ +/********************************************************************* + * \file Version.hpp + * + * \author Romain BOULLARD + * \date October 2025 + *********************************************************************/ +#ifndef BIGFOOT_UTILS_VERSION_HPP +#define BIGFOOT_UTILS_VERSION_HPP +#include +#include + +#include +#include +#include + +namespace Bigfoot +{ +class Version +{ + public: + Version() = default; + + /** + * Constructor. + * + * \param p_combined The combined version. + */ + explicit constexpr Version(const std::uint32_t p_combined): + m_combined(p_combined) + { + } + + /** + * Constructor. + * + * \param p_major Major + * \param p_minor Minor + * \param p_patch Patch + */ + constexpr Version(const std::uint8_t p_major, const std::uint8_t p_minor, const std::uint8_t p_patch): + m_combined((p_major << 16) | (p_minor << 8) | p_patch) + { + } + + Version(const Version& p_version) = default; + Version(Version&& p_version) = default; + + ~Version() = default; + + /** + * Get the major part of the version. + * + * \return The major part of the version. + */ + [[nodiscard]] + constexpr std::uint8_t Major() const + { + constexpr std::uint32_t mask = 0b00000000111111110000000000000000; + + return static_cast((m_combined & mask) >> 16); + } + + /** + * Get the minor part of the version. + * + * \return The minor part of the version. + */ + [[nodiscard]] + constexpr std::uint8_t Minor() const + { + constexpr std::uint32_t mask = 0b00000000000000001111111100000000; + + return static_cast((m_combined & mask) >> 8); + } + + /** + * Get the patch part of the version. + * + * \return The patch part of the version. + */ + [[nodiscard]] + constexpr std::uint8_t Patch() const + { + constexpr std::uint32_t mask = 0b00000000000000000000000011111111; + + return static_cast(m_combined & mask); + } + + [[nodiscard]] + constexpr operator std::uint32_t() const + { + return m_combined; + } + + operator std::string() const; + + constexpr Version& operator=(const Version& p_version) = default; + + constexpr Version& operator=(Version&& p_version) = default; + + [[nodiscard]] + constexpr bool operator>(const Version& p_version) const + { + return m_combined > p_version.m_combined; + } + + [[nodiscard]] + constexpr bool operator<(const Version& p_version) const + { + return m_combined < p_version.m_combined; + } + + [[nodiscard]] + constexpr bool operator>=(const Version& p_version) const + { + return m_combined >= p_version.m_combined; + } + + [[nodiscard]] + constexpr bool operator<=(const Version& p_version) const + { + return m_combined <= p_version.m_combined; + } + + [[nodiscard]] + constexpr bool operator==(const Version& p_version) const = default; + + [[nodiscard]] + constexpr bool operator!=(const Version& p_version) const = default; + + private: + /** + * The combined version. + */ + std::uint32_t m_combined = 0; +}; +} // namespace Bigfoot + +/****************************************************************************************/ + +#if defined BIGFOOT_NOT_OPTIMIZED +template<> +struct std::formatter +{ + template + constexpr auto parse(ParseContext& p_context) + { + return p_context.begin(); + } + + template + auto format(const Bigfoot::Version& p_version, FormatContext& p_context) const + { + return std::format_to(p_context.out(), "{}", static_cast(p_version)); + } +}; +#endif +#endif diff --git a/Bigfoot/Sources/Utils/Version.cpp b/Bigfoot/Sources/Utils/Version.cpp new file mode 100644 index 0000000..678b2fc --- /dev/null +++ b/Bigfoot/Sources/Utils/Version.cpp @@ -0,0 +1,15 @@ +/********************************************************************* + * \file Version.cpp + * + * \author Romain BOULLARD + * \date January 2023 + *********************************************************************/ +#include + +namespace Bigfoot +{ +Version::operator std::string() const +{ + return std::format("{}.{}.{}", Major(), Minor(), Patch()); +} +} // namespace Bigfoot diff --git a/Bigfoot/Tests/CMakeLists.txt b/Bigfoot/Tests/CMakeLists.txt new file mode 100644 index 0000000..bdd68d7 --- /dev/null +++ b/Bigfoot/Tests/CMakeLists.txt @@ -0,0 +1,3 @@ +add_subdirectory(${CMAKE_CURRENT_SOURCE_DIR}/System) +add_subdirectory(${CMAKE_CURRENT_SOURCE_DIR}/Utils) +add_subdirectory(${CMAKE_CURRENT_SOURCE_DIR}/Engine) \ No newline at end of file diff --git a/Bigfoot/Tests/Engine/CMakeLists.txt b/Bigfoot/Tests/Engine/CMakeLists.txt new file mode 100644 index 0000000..36652b4 --- /dev/null +++ b/Bigfoot/Tests/Engine/CMakeLists.txt @@ -0,0 +1,15 @@ +get_filename_component(PackageName ${CMAKE_CURRENT_SOURCE_DIR} NAME) +project(${PackageName}Tests) + +set(BigfootDependencies + Engine + System + Utils) + +bigfoot_create_bigfile("Tests/Bigfoot") + +bigfoot_create_package_tests( + "" + "${BigfootDependencies}") + +bigfoot_setup_dependencies("Tests/Bigfoot") \ No newline at end of file diff --git a/Bigfoot/Tests/Engine/Include/EngineTests/BigFileInfo_generated.hpp b/Bigfoot/Tests/Engine/Include/EngineTests/BigFileInfo_generated.hpp new file mode 100644 index 0000000..a1f0510 --- /dev/null +++ b/Bigfoot/Tests/Engine/Include/EngineTests/BigFileInfo_generated.hpp @@ -0,0 +1,19 @@ +// AUTO-GENERATED DO NOT TOUCH + +/********************************************************************* + * \file BigFileInfo.generated.hpp + * + *********************************************************************/ +#ifndef BIGFOOT_ENGINETESTS_BIGFILEINFO_GENERATED_HPP +#define BIGFOOT_ENGINETESTS_BIGFILEINFO_GENERATED_HPP + +#include + +namespace Bigfoot +{ +/* + * BigFile location + */ +constexpr eastl::string_view BIGFILE_ENGINETESTS_LOCATION {"./EngineTests-bigfile.db"}; +} // namespace Bigfoot +#endif diff --git a/Bigfoot/Tests/Engine/touch.cpp b/Bigfoot/Tests/Engine/touch.cpp new file mode 100644 index 0000000..38a47cf --- /dev/null +++ b/Bigfoot/Tests/Engine/touch.cpp @@ -0,0 +1 @@ +// to delete when an actual test is in EngineTests diff --git a/Bigfoot/Tests/System/CMakeLists.txt b/Bigfoot/Tests/System/CMakeLists.txt new file mode 100644 index 0000000..7b130e0 --- /dev/null +++ b/Bigfoot/Tests/System/CMakeLists.txt @@ -0,0 +1,14 @@ +get_filename_component(PackageName ${CMAKE_CURRENT_SOURCE_DIR} NAME) +project(${PackageName}Tests) + +set(BigfootDependencies + System + Utils) + +bigfoot_create_package_tests( + "" + "${BigfootDependencies}") + +bigfoot_create_logger() + +bigfoot_setup_dependencies("Tests/Bigfoot") \ No newline at end of file diff --git a/Bigfoot/Tests/System/File.cpp b/Bigfoot/Tests/System/File.cpp new file mode 100644 index 0000000..850afe6 --- /dev/null +++ b/Bigfoot/Tests/System/File.cpp @@ -0,0 +1,80 @@ +/********************************************************************* + * \file File.cpp + * + * \author Romain BOULLARD + * \date December 2025 + *********************************************************************/ +#include + +#include + +namespace Bigfoot +{ +class FileFixture: public ::testing::Test +{ + public: + File m_file {eastl::string_view {"Fixture/file"}}; + File m_nonExistent {eastl::string_view {"Fixture/bigfoot"}}; +}; + +/****************************************************************************************/ + +TEST_F(FileFixture, IsRelative_ShouldReturnTrueOnRelativeFile) +{ + EXPECT_TRUE(m_file.IsRelative()); +} + +/****************************************************************************************/ + +TEST_F(FileFixture, IsRelative_ShouldReturnFalseOnAbsoluteFile) +{ + EXPECT_FALSE(m_file.Absolute().IsRelative()); +} + +/****************************************************************************************/ + +TEST_F(FileFixture, IsAbsolute_ShouldReturnTrueOnAbsoluteFile) +{ + EXPECT_TRUE(m_file.Absolute().IsAbsolute()); +} + +TEST_F(FileFixture, IsAbsolute_ShouldReturnFalseOnRelativeFile) +{ + EXPECT_FALSE(m_file.IsAbsolute()); +} + +/****************************************************************************************/ + +TEST_F(FileFixture, Exists_ShouldReturnTrueOnExistingFile) +{ + EXPECT_TRUE(m_file.Exists()); +} + +/****************************************************************************************/ + +TEST_F(FileFixture, Exists_ShouldReturnFalseOnNonExistingFile) +{ + EXPECT_FALSE(m_nonExistent.Exists()); +} + +/****************************************************************************************/ + +TEST_F(FileFixture, Path_ShouldReturnThePath) +{ + EXPECT_STREQ(m_file.Path().data(), "Fixture/file"); +} + +/****************************************************************************************/ + +TEST_F(FileFixture, Absolute_ShouldReturnTheAbsolutePath) +{ + EXPECT_STREQ(std::filesystem::absolute("Fixture/file").string().c_str(), m_file.Absolute().Path().data()); +} + +/****************************************************************************************/ + +TEST_F(FileFixture, Relative_ShouldReturnTheRelativePath) +{ + EXPECT_STREQ(std::filesystem::relative("Fixture/file").string().c_str(), m_file.Relative().Path().data()); +} +} // namespace Bigfoot diff --git a/Bigfoot/Tests/System/Fixture/file b/Bigfoot/Tests/System/Fixture/file new file mode 100644 index 0000000..e69de29 diff --git a/Bigfoot/Tests/System/Include/SystemTests/SystemTestsLogger_generated.hpp b/Bigfoot/Tests/System/Include/SystemTests/SystemTestsLogger_generated.hpp new file mode 100644 index 0000000..abe35cd --- /dev/null +++ b/Bigfoot/Tests/System/Include/SystemTests/SystemTestsLogger_generated.hpp @@ -0,0 +1,21 @@ +// AUTO-GENERATED DO NOT TOUCH + +/********************************************************************* + * \file SystemTestsLogger.generated.hpp + * + *********************************************************************/ +#ifndef BIGFOOT_SYSTEMTESTSLOGGER_GENERATED_HPP +#define BIGFOOT_SYSTEMTESTSLOGGER_GENERATED_HPP +#include + +#if defined BIGFOOT_NOT_OPTIMIZED + +namespace Bigfoot +{ +/* + * Logger + */ +inline Log::LoggerInfo SYSTEMTESTS_LOGGER {"SYSTEMTESTS_LOGGER", Flat::LogLevel::Trace}; +} // namespace Bigfoot +#endif +#endif diff --git a/Bigfoot/Tests/System/Log/Log.cpp b/Bigfoot/Tests/System/Log/Log.cpp new file mode 100644 index 0000000..49a2e21 --- /dev/null +++ b/Bigfoot/Tests/System/Log/Log.cpp @@ -0,0 +1,138 @@ +/********************************************************************* + * \file Log.cpp + * + * \author Romain BOULLARD + * \date December 2022 + *********************************************************************/ +#include + +#include + +#include + +#if defined BIGFOOT_NOT_OPTIMIZED + +#include + +namespace Bigfoot +{ +class LogFixture: public ::testing::Test +{ + protected: + void SetUp() override + { + SYSTEMTESTS_LOGGER = {"UTILSTESTS_LOGGER", Flat::LogLevel::Trace}; + } + + static constexpr Flat::LogLevel QuillLogLevelToLogLevel(const quill::LogLevel p_level) + { + switch (p_level) + { + case quill::LogLevel::Debug: + return Flat::LogLevel::Debug; + case quill::LogLevel::TraceL3: + return Flat::LogLevel::Trace; + case quill::LogLevel::Info: + return Flat::LogLevel::Info; + case quill::LogLevel::Warning: + return Flat::LogLevel::Warn; + case quill::LogLevel::Error: + return Flat::LogLevel::Error; + case quill::LogLevel::Critical: + return Flat::LogLevel::Critical; + default: + break; + } + + return Flat::LogLevel::Trace; + } + + Log m_log; +}; + +/****************************************************************************************/ + +TEST_F(LogFixture, RegisterLogger_ShouldRegisterTheLogger) +{ + const quill::Logger* logger = m_log.RegisterLogger(SYSTEMTESTS_LOGGER); + EXPECT_TRUE(logger); + EXPECT_EQ(logger, m_log.GetLogger(SYSTEMTESTS_LOGGER)); + EXPECT_EQ(logger->get_logger_name(), SYSTEMTESTS_LOGGER.m_name); + EXPECT_EQ(QuillLogLevelToLogLevel(logger->get_log_level()), SYSTEMTESTS_LOGGER.m_level); +} + +/****************************************************************************************/ + +TEST_F(LogFixture, GetLogger_ShouldReturnNullptrIfTheLoggerDoesNotExist) +{ + EXPECT_FALSE(m_log.GetLogger(SYSTEMTESTS_LOGGER)); +} + +/****************************************************************************************/ + +TEST_F(LogFixture, GetLogger_ShouldReturnTheLoggerIfItExists) +{ + [[maybe_unused]] + const quill::Logger* logger = m_log.RegisterLogger(SYSTEMTESTS_LOGGER); + EXPECT_TRUE(m_log.GetLogger(SYSTEMTESTS_LOGGER)); +} + +/****************************************************************************************/ + +TEST_F(LogFixture, ChangeLoggerLogLevel_ShouldChangeTheLoggerLogLevel) +{ + const quill::Logger* logger = m_log.RegisterLogger(SYSTEMTESTS_LOGGER); + + m_log.ChangeLoggerLogLevel(SYSTEMTESTS_LOGGER, Flat::LogLevel::Critical); + EXPECT_EQ(QuillLogLevelToLogLevel(logger->get_log_level()), Flat::LogLevel::Critical); +} + +/****************************************************************************************/ + +TEST_F(LogFixture, LogDebug) +{ + Singleton::Lifetime singletonLifetime; + BIGFOOT_LOG_DEBUG(SYSTEMTESTS_LOGGER, "Hello"); +} + +/****************************************************************************************/ + +TEST_F(LogFixture, LogTrace) +{ + Singleton::Lifetime singletonLifetime; + BIGFOOT_LOG_TRACE(SYSTEMTESTS_LOGGER, "Hello"); +} + +/****************************************************************************************/ + +TEST_F(LogFixture, LogInfo) +{ + Singleton::Lifetime singletonLifetime; + BIGFOOT_LOG_INFO(SYSTEMTESTS_LOGGER, "Hello"); +} + +/****************************************************************************************/ + +TEST_F(LogFixture, LogWarn) +{ + Singleton::Lifetime singletonLifetime; + BIGFOOT_LOG_WARN(SYSTEMTESTS_LOGGER, "Hello"); +} + +/****************************************************************************************/ + +TEST_F(LogFixture, LogError) +{ + Singleton::Lifetime singletonLifetime; + BIGFOOT_LOG_ERROR(SYSTEMTESTS_LOGGER, "Hello"); +} + +/****************************************************************************************/ + +TEST_F(LogFixture, LogFatal) +{ + Singleton::Lifetime singletonLifetime; + BIGFOOT_LOG_FATAL(SYSTEMTESTS_LOGGER, "Hello"); +} +} // namespace Bigfoot +#endif diff --git a/Bigfoot/Tests/System/Time.cpp b/Bigfoot/Tests/System/Time.cpp new file mode 100644 index 0000000..6a9b602 --- /dev/null +++ b/Bigfoot/Tests/System/Time.cpp @@ -0,0 +1,67 @@ +/********************************************************************* + * \file Time.cpp + * + * \author Romain BOULLARD + * \date December 2025 + *********************************************************************/ +#include + +#include + +namespace Bigfoot +{ +class TimeFixture: public ::testing::Test +{ + public: + Time m_time {1'767'643'746'680'609}; +}; + +/****************************************************************************************/ + +TEST_F(TimeFixture, Year_ShouldReturnTheYear) +{ + EXPECT_EQ(m_time.Year(), 2026); +} + +/****************************************************************************************/ + +TEST_F(TimeFixture, Month_ShouldReturnTheMonth) +{ + EXPECT_EQ(m_time.Month(), 1); +} + +/****************************************************************************************/ + +TEST_F(TimeFixture, Day_ShouldReturnTheDay) +{ + EXPECT_EQ(m_time.Day(), 5); +} + +/****************************************************************************************/ + +TEST_F(TimeFixture, Hour_ShouldReturnTheHour) +{ + EXPECT_EQ(m_time.Hour(), 20); +} + +/****************************************************************************************/ + +TEST_F(TimeFixture, Minute_ShouldReturnTheMinute) +{ + EXPECT_EQ(m_time.Minute(), 9); +} + +/****************************************************************************************/ + +TEST_F(TimeFixture, Second_ShouldReturnTheSecond) +{ + EXPECT_EQ(m_time.Second(), 6); +} + +/****************************************************************************************/ + +TEST_F(TimeFixture, Microsecond_ShouldReturnTheMicrosecond) +{ + EXPECT_EQ(m_time.Microsecond(), 680'609); +} +} // namespace Bigfoot diff --git a/Bigfoot/Tests/System/UUID/UUID.cpp b/Bigfoot/Tests/System/UUID/UUID.cpp new file mode 100644 index 0000000..8f978d9 --- /dev/null +++ b/Bigfoot/Tests/System/UUID/UUID.cpp @@ -0,0 +1,182 @@ +/********************************************************************* + * \file UUID.cpp + * + * \author Romain BOULLARD + * \date October 2025 + *********************************************************************/ +#include + +#include + +#include + +namespace Bigfoot +{ +class UUIDFixture: public ::testing::Test +{ + protected: + UUID m_a; + UUID m_b {"47183823-2574-4bfd-b411-99ed177d3e43"}; + UUID m_c {"4bfd-b411-99ed177d3e43"}; + + std::array m_raw { + std::byte {0}, + std::byte {1}, + std::byte {2}, + std::byte {3}, + std::byte {4}, + std::byte {5}, + std::byte {6}, + std::byte {7}, + std::byte {8}, + std::byte {9}, + std::byte {10}, + std::byte {11}, + std::byte {12}, + std::byte {13}, + std::byte {14}, + std::byte {15}, + }; + UUID m_d {m_raw}; +}; + +/****************************************************************************************/ + +TEST_F(UUIDFixture, DumpingRawAndConstructAnUUIDWithItShouldGiveTheSameUUID) +{ + std::span raw = m_a; + EXPECT_EQ(m_a, UUID {raw}); + + raw = m_b; + EXPECT_EQ(m_b, UUID {raw}); + + raw = m_d; + EXPECT_EQ(m_d, UUID {raw}); +} + +/****************************************************************************************/ + +TEST_F(UUIDFixture, ValidIDFromStringShouldBeEqualToString) +{ + EXPECT_EQ(static_cast(m_b), "47183823-2574-4bfd-b411-99ed177d3e43"); +} + +/****************************************************************************************/ + +TEST_F(UUIDFixture, InvalidIDFromStringShouldNotBeEqualToString) +{ + EXPECT_NE(static_cast(m_c), "4bfd-b411-99ed177d3e43"); +} + +/****************************************************************************************/ + +TEST_F(UUIDFixture, NullIDStringShouldBeEqualToNullIDString) +{ + EXPECT_EQ(static_cast(UUID::NULL_UUID), "00000000-0000-0000-0000-000000000000"); +} + +/****************************************************************************************/ + +TEST_F(UUIDFixture, DefaultConstructedIDShouldBeValid) +{ + EXPECT_TRUE(m_a); +} + +/****************************************************************************************/ + +TEST_F(UUIDFixture, StringConstructedIDFromAValidStringShouldBeValid) +{ + EXPECT_TRUE(m_b); +} + +/****************************************************************************************/ + +TEST_F(UUIDFixture, StringConstructedIDFromAnInvalidStringShouldBeInvalid) +{ + EXPECT_FALSE(m_c); +} + +/****************************************************************************************/ + +TEST_F(UUIDFixture, RawConstructedIDShouldBeValid) +{ + EXPECT_TRUE(m_d); +} + +/****************************************************************************************/ + +TEST_F(UUIDFixture, ConstructingFromRawShouldAlwaysGiveTheSameUUID) +{ + EXPECT_EQ(m_d, UUID {"00010203-0405-0607-0809-0a0b0c0d0e0f"}); +} + +/****************************************************************************************/ + +TEST_F(UUIDFixture, NullIDShouldNotBeValid) +{ + EXPECT_FALSE(UUID::NULL_UUID); +} + +/****************************************************************************************/ + +TEST_F(UUIDFixture, IDShouldBeEqualToItself) +{ + EXPECT_EQ(m_a, m_a); +} + +/****************************************************************************************/ + +TEST_F(UUIDFixture, IDConstructedFromOtherIDShouldBeEqual) +{ + EXPECT_EQ(m_a, UUID {m_a}); +} + +/****************************************************************************************/ + +TEST_F(UUIDFixture, IDCopiedFromOtherIDShouldBeEqual) +{ + const UUID m_aDuplicate = m_a; + EXPECT_EQ(m_a, m_aDuplicate); +} + +/****************************************************************************************/ + +TEST_F(UUIDFixture, ValidIDsShouldNotBeEqualToNullID) +{ + EXPECT_NE(m_a, UUID::NULL_UUID); + EXPECT_NE(m_b, UUID::NULL_UUID); + EXPECT_NE(m_d, UUID::NULL_UUID); +} + +/****************************************************************************************/ + +TEST_F(UUIDFixture, InvalidIDsShouldBeEqualToNullID) +{ + EXPECT_EQ(m_c, UUID::NULL_UUID); +} + +/****************************************************************************************/ + +TEST_F(UUIDFixture, GeneratingFiveMillionUniqueID) +{ + ankerl::unordered_dense::set m_ids; + + for (std::uint32_t index = 0; index < 5'000'000; ++index) + { + EXPECT_TRUE(m_ids.insert(UUID {}).second); + } +} + +/****************************************************************************************/ + +TEST_F(UUIDFixture, Raw_ShouldGiveBackTheRawDataOfTheID) +{ + std::span d = m_d; + std::span raw = m_raw; + + for (std::uint32_t i = 0; i < UUID::UUID_BYTE_SIZE; ++i) + { + EXPECT_EQ(d[i], raw[i]); + } +} +} // namespace Bigfoot diff --git a/Bigfoot/Tests/Utils/CMakeLists.txt b/Bigfoot/Tests/Utils/CMakeLists.txt new file mode 100644 index 0000000..47c3d4b --- /dev/null +++ b/Bigfoot/Tests/Utils/CMakeLists.txt @@ -0,0 +1,11 @@ +get_filename_component(PackageName ${CMAKE_CURRENT_SOURCE_DIR} NAME) +project(${PackageName}Tests) + +set(BigfootDependencies + Utils) + +bigfoot_create_package_tests( + "" + "${BigfootDependencies}") + +bigfoot_setup_dependencies("Tests/Bigfoot") \ No newline at end of file diff --git a/Bigfoot/Tests/Utils/Caster.cpp b/Bigfoot/Tests/Utils/Caster.cpp new file mode 100644 index 0000000..0d2392a --- /dev/null +++ b/Bigfoot/Tests/Utils/Caster.cpp @@ -0,0 +1,102 @@ +/********************************************************************* + * \file Caster.cpp + * + * \author Romain BOULLARD + * \date October 2025 + *********************************************************************/ +#include + +#include + +namespace Bigfoot +{ +class Parent +{ + public: + Parent(const std::uint32_t p_value): + m_value(p_value) + { + } + + virtual ~Parent() = default; + + std::uint32_t GetParentValue() const + { + return m_value; + } + + virtual std::uint32_t GetChildValue() const = 0; + + private: + std::uint32_t m_value; +}; + +/****************************************************************************************/ + +class ChildA final: public Parent +{ + public: + ChildA(const std::uint32_t p_value): + Parent(28), + m_value(p_value) + { + } + + ~ChildA() override = default; + + std::uint32_t GetChildValue() const override + { + return m_value; + } + + private: + std::uint32_t m_value; +}; + +/****************************************************************************************/ + +class ChildB final: public Parent +{ + public: + ChildB(const std::uint32_t p_value): + Parent(34), + m_value(p_value) + { + } + + ~ChildB() override = default; + + std::uint32_t GetChildValue() const override + { + return m_value; + } + + private: + std::uint32_t m_value; +}; + +/****************************************************************************************/ + +class CasterFixture: public ::testing::Test +{ + protected: + std::unique_ptr m_a = std::make_unique(42); + ChildB m_b {12}; +}; + +/****************************************************************************************/ + +TEST_F(CasterFixture, ObjectCast) +{ + EXPECT_EQ(m_a->GetParentValue(), 28); + EXPECT_EQ(m_a->GetChildValue(), 42); + const ChildA* child = BIGFOOT_OBJECT_CAST(ChildA, m_a.get()); + EXPECT_EQ(child->GetParentValue(), 28); + EXPECT_EQ(child->GetChildValue(), 42); + + EXPECT_EQ(m_b.GetParentValue(), 34); + EXPECT_EQ(m_b.GetChildValue(), 12); + const Parent& parent = BIGFOOT_OBJECT_CAST(Parent, m_b); + EXPECT_EQ(parent.GetParentValue(), 34); +} +} // namespace Bigfoot diff --git a/Bigfoot/Tests/Utils/Concat.cpp b/Bigfoot/Tests/Utils/Concat.cpp new file mode 100644 index 0000000..dda8833 --- /dev/null +++ b/Bigfoot/Tests/Utils/Concat.cpp @@ -0,0 +1,36 @@ +/********************************************************************* + * \file Concat.cpp + * + * \author Romain BOULLARD + * \date October 2025 + *********************************************************************/ +#include + +#include + +namespace Bigfoot +{ +class ConcatFixture: public ::testing::Test +{ +}; + +/****************************************************************************************/ + +TEST_F(ConcatFixture, ShouldConcatTheTwoStrings) +{ + constexpr std::string_view result = CONCAT("a", "b"); + EXPECT_STREQ(result.data(), "ab"); +} + +/****************************************************************************************/ + +TEST_F(ConcatFixture, UniqueName) +{ + // this looks wrong, but this should expand to test_30 and test_31 + constexpr std::uint32_t MAKE_UNIQUE_VARIABLE_NAME(test) = 1; + constexpr std::uint32_t MAKE_UNIQUE_VARIABLE_NAME(test) = 2; + + EXPECT_EQ(test_30, 1); + EXPECT_EQ(test_31, 2); +} +} // namespace Bigfoot diff --git a/Bigfoot/Tests/Utils/Singleton.cpp b/Bigfoot/Tests/Utils/Singleton.cpp new file mode 100644 index 0000000..4f089b3 --- /dev/null +++ b/Bigfoot/Tests/Utils/Singleton.cpp @@ -0,0 +1,102 @@ +/********************************************************************* + * \file Singleton.cpp + * + * \author Romain BOULLARD + * \date October 2025 + *********************************************************************/ +#include + +#include +#include + +namespace Bigfoot +{ +class SingletonMock +{ + public: + virtual ~SingletonMock() = default; + virtual void Construct() = 0; + virtual void Destruct() = 0; +}; + +class SingletonTest +{ + public: + inline static SingletonMock* ms_mock = nullptr; + + explicit SingletonTest(std::uint32_t p_data): + m_data(p_data) + { + if (ms_mock) + { + ms_mock->Construct(); + } + } + + ~SingletonTest() + { + if (ms_mock) + { + ms_mock->Destruct(); + } + } + + [[nodiscard]] + std::uint32_t Data() const + { + return m_data; + } + + private: + std::uint32_t m_data; +}; + +/****************************************************************************************/ + +class SingletonFixture: public ::testing::Test +{ + protected: + class SingletonMockImpl: public SingletonMock + { + public: + MOCK_METHOD(void, Construct, (), (override)); + MOCK_METHOD(void, Destruct, (), (override)); + }; + + std::unique_ptr m_mock; + + void SetUp() override + { + m_mock = std::make_unique<::testing::NiceMock>(); + SingletonTest::ms_mock = m_mock.get(); + } + + void TearDown() override + { + SingletonTest::ms_mock = nullptr; + m_mock.reset(); + } +}; + +/****************************************************************************************/ + +TEST_F(SingletonFixture, ConstructorAndDestructorShouldBeCalled) +{ + ::testing::InSequence seq; + + EXPECT_CALL(*m_mock, Construct()); + EXPECT_CALL(*m_mock, Destruct()); + + Singleton::Lifetime singleton {42}; +} + +/****************************************************************************************/ + +TEST_F(SingletonFixture, Instance_ShouldReturnTheInstance) +{ + Singleton::Lifetime singleton {42}; + + EXPECT_EQ(Singleton::Instance().Data(), 42); +} + +} // namespace Bigfoot diff --git a/Bigfoot/Tests/Utils/TargetMacros.cpp b/Bigfoot/Tests/Utils/TargetMacros.cpp new file mode 100644 index 0000000..72f1aae --- /dev/null +++ b/Bigfoot/Tests/Utils/TargetMacros.cpp @@ -0,0 +1,26 @@ +/********************************************************************* + * \file TargetMacros.cpp + * + * \author Romain BOULLARD + * \date October 2025 + *********************************************************************/ +#include + +#include + +namespace Bigfoot +{ +class TargetMacrosFixture: public ::testing::Test +{ +}; + +/****************************************************************************************/ + +TEST_F(TargetMacrosFixture, OptimizedOrNot) +{ + constexpr std::uint32_t value = BIGFOOT_OPTIMIZED_OR_NOT(1, 2); + BIGFOOT_NOT_OPTIMIZED_ONLY(EXPECT_EQ(value, 2);) + BIGFOOT_OPTIMIZED_ONLY(EXPECT_EQ(value, 1);) +} + +} // namespace Bigfoot diff --git a/Bigfoot/Tests/Utils/Version.cpp b/Bigfoot/Tests/Utils/Version.cpp new file mode 100644 index 0000000..d2e6912 --- /dev/null +++ b/Bigfoot/Tests/Utils/Version.cpp @@ -0,0 +1,73 @@ +/********************************************************************* + * \file Version.cpp + * + * \author Romain BOULLARD + * \date October 2025 + *********************************************************************/ +#include + +#include + +namespace Bigfoot +{ +class VersionFixture: public ::testing::Test +{ + protected: + const Version m_detailed {1, 2, 3}; + const Version m_combined {(1 << 16) | (2 << 8) | 3}; +}; + +/****************************************************************************************/ + +TEST_F(VersionFixture, string) +{ + EXPECT_STREQ(static_cast(m_detailed).data(), "1.2.3"); + EXPECT_STREQ(static_cast(m_combined).data(), "1.2.3"); +} + +/****************************************************************************************/ + +TEST_F(VersionFixture, uint32_t) +{ + EXPECT_EQ(static_cast(m_detailed), (1 << 16) | (2 << 8) | 3); + EXPECT_EQ(static_cast(m_combined), (1 << 16) | (2 << 8) | 3); +} + +/****************************************************************************************/ + +TEST_F(VersionFixture, Major_ShouldBeEqualToTheMajorPartOfTheVersion) +{ + EXPECT_EQ(m_detailed.Major(), 1); + EXPECT_EQ(m_combined.Major(), 1); +} + +/****************************************************************************************/ + +TEST_F(VersionFixture, Minor_ShouldBeEqualToTheMinorPartOfTheVersion) +{ + EXPECT_EQ(m_detailed.Minor(), 2); + EXPECT_EQ(m_combined.Minor(), 2); +} + +/****************************************************************************************/ + +TEST_F(VersionFixture, Patch_ShouldBeEqualToThePatchPartOfTheVersion) +{ + EXPECT_EQ(m_detailed.Patch(), 3); + EXPECT_EQ(m_combined.Patch(), 3); +} + +/****************************************************************************************/ + +TEST_F(VersionFixture, Comparisons) +{ + constexpr Version other {2, 6, 4}; + + EXPECT_GT(other, m_detailed); + EXPECT_GE(other, other); + EXPECT_LT(m_detailed, other); + EXPECT_LE(other, other); + EXPECT_EQ(other, other); + EXPECT_NE(other, m_detailed); +} +} // namespace Bigfoot diff --git a/CMake/FindDependencies.cmake b/CMake/FindDependencies.cmake new file mode 100644 index 0000000..b56d7f0 --- /dev/null +++ b/CMake/FindDependencies.cmake @@ -0,0 +1,64 @@ +find_package(Python3 COMPONENTS Interpreter Development) + +if(CMAKE_SYSTEM_NAME STREQUAL "Linux") + set(THREADS_PREFER_PTHREAD_FLAG ON) + find_package(Threads REQUIRED) +endif() + +find_package(EASTL REQUIRED) +find_package(unordered_dense REQUIRED) +find_package(mimalloc REQUIRED) +find_package(stduuid REQUIRED) +find_package(SQLite3 REQUIRED) +find_package(CLI11 REQUIRED) +find_package(rapidhash REQUIRED) +find_package(effolkronium_random REQUIRED) +find_package(flatbuffers CONFIG REQUIRED) + +if(TRACY) + find_package(Tracy REQUIRED) +endif() + +if(${IS_MULTI_CONFIG}) + find_package(quill REQUIRED) + find_package(cpptrace REQUIRED) +elseif(${CMAKE_BUILD_TYPE} STREQUAL "Debug" OR ${CMAKE_BUILD_TYPE} STREQUAL "RelWithDebInfo") + find_package(quill REQUIRED) + find_package(cpptrace REQUIRED) +endif() + + +find_package(glm REQUIRED) +find_package(lodepng REQUIRED) +find_package(imgui REQUIRED) + +if(VULKAN) + find_package(VulkanHeaders REQUIRED) + if(${IS_MULTI_CONFIG}) + find_package(vulkan-validationlayers REQUIRED) + elseif(${CMAKE_BUILD_TYPE} STREQUAL "Debug" OR ${CMAKE_BUILD_TYPE} STREQUAL "RelWithDebInfo") + find_package(vulkan-validationlayers REQUIRED) + endif() + find_package(vulkan-memory-allocator REQUIRED) +endif() + +if(BUILD_BENCHMARKS OR BUILD_TESTS OR SAMPLE_APP) + find_package(glfw3 REQUIRED) +endif() + +if(BUILD_TESTS) + find_package(GTest REQUIRED) + find_package(pixelmatch-cpp17 REQUIRED) +endif() + +if(BUILD_TOOLS) + find_package(spirv-cross REQUIRED) + find_package(shaderc REQUIRED) + find_package(assimp REQUIRED) + find_package(meshoptimizer REQUIRED) + find_package(libsquish REQUIRED) +endif() + +if(BUILD_BENCHMARKS) + find_package(benchmark REQUIRED) +endif() \ No newline at end of file diff --git a/CMake/Package.cmake b/CMake/Package.cmake new file mode 100644 index 0000000..ed86db9 --- /dev/null +++ b/CMake/Package.cmake @@ -0,0 +1,97 @@ +function(bigfoot_create_package_lib PackagePublicDependencies PackagePrivateDependencies PackageBigfootPublicDependencies PackageBigfootPrivateDependencies ParentFolder) + add_library(${PROJECT_NAME} STATIC) + set_target_properties(${PROJECT_NAME} PROPERTIES LINKER_LANGUAGE CXX) + + target_include_directories(${PROJECT_NAME} PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}/Include) + + bigfoot_compile_flatbuffers("${PackageBigfootPublicDependencies}") + + # collect sources (reconfigure when files are added/removed) + file(GLOB_RECURSE _BF_SOURCES + CONFIGURE_DEPENDS + ${CMAKE_CURRENT_SOURCE_DIR}/*.h + ${CMAKE_CURRENT_SOURCE_DIR}/*.hpp + ${CMAKE_CURRENT_SOURCE_DIR}/*.hpp.in + ${CMAKE_CURRENT_SOURCE_DIR}/*.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/*.fbs + ${CMAKE_CURRENT_SOURCE_DIR}/*.sql + ) + + target_sources(${PROJECT_NAME} + PRIVATE + ${_BF_SOURCES} + ) + + target_compile_options(${PROJECT_NAME} PRIVATE ${BIGFOOT_CXX_FLAGS}) + + target_link_libraries(${PROJECT_NAME} PUBLIC unordered_dense::unordered_dense EASTL::EASTL flatbuffers::flatbuffers rapidhash::rapidhash) + target_link_libraries(${PROJECT_NAME} PRIVATE ${CMAKE_DL_LIBS}) + + target_link_libraries(${PROJECT_NAME} PUBLIC ${PackagePublicDependencies}) + target_link_libraries(${PROJECT_NAME} PRIVATE ${PackagePrivateDependencies}) + target_link_libraries(${PROJECT_NAME} PUBLIC $) + target_link_libraries(${PROJECT_NAME} PRIVATE $) + + source_group(TREE ${CMAKE_CURRENT_SOURCE_DIR} PREFIX Src FILES ${_BF_SOURCES}) + + set_target_properties(${PROJECT_NAME} PROPERTIES FOLDER Bigfoot/${ParentFolder}) +endfunction() + +function(bigfoot_create_package_tests ParentFolder BigfootDependencies) + add_executable(${PROJECT_NAME}) + set_target_properties(${PROJECT_NAME} PROPERTIES LINKER_LANGUAGE CXX) + + bigfoot_compile_flatbuffers("${BigfootDependencies}") + + file(GLOB_RECURSE _BF_TEST_SOURCES + CONFIGURE_DEPENDS + ${CMAKE_CURRENT_SOURCE_DIR}/*.h + ${CMAKE_CURRENT_SOURCE_DIR}/*.hpp + ${CMAKE_CURRENT_SOURCE_DIR}/*.hpp.in + ${CMAKE_CURRENT_SOURCE_DIR}/*.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/*.fbs + ) + + target_sources(${PROJECT_NAME} + PRIVATE + ${_BF_TEST_SOURCES} + ) + + target_compile_options(${PROJECT_NAME} PRIVATE ${BIGFOOT_CXX_FLAGS}) + target_link_options(${PROJECT_NAME} PRIVATE ${BIGFOOT_EXE_LINK_FLAGS}) + + target_include_directories(${PROJECT_NAME} PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}/Include) + + target_link_libraries(${PROJECT_NAME} PRIVATE $) + target_link_libraries(${PROJECT_NAME} PRIVATE gtest::gtest) + + include(GoogleTest) + gtest_discover_tests(${PROJECT_NAME} XML_OUTPUT_DIR ${CMAKE_BINARY_DIR}/TestResults/) + + source_group(TREE ${CMAKE_CURRENT_SOURCE_DIR} PREFIX Src/ FILES ${_BF_TEST_SOURCES}) + + set_target_properties(${PROJECT_NAME} PROPERTIES FOLDER Tests/Bigfoot/${ParentFolder}) + + ##################COPY FIXTURE FOLDER################### + + if(NOT EXISTS ${CMAKE_CURRENT_SOURCE_DIR}/Fixture) + file(MAKE_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/Fixture) + endif() + + # Track all fixture files + file(GLOB_RECURSE FIXTURE_FILES + CONFIGURE_DEPENDS + ${CMAKE_CURRENT_SOURCE_DIR}/Fixture/* + ) + + add_custom_target(${PROJECT_NAME}Fixture + COMMAND ${CMAKE_COMMAND} -E remove_directory $/Fixture + COMMAND ${CMAKE_COMMAND} -E copy_directory ${CMAKE_CURRENT_SOURCE_DIR}/Fixture $/Fixture + DEPENDS ${FIXTURE_FILES} + COMMENT "Copying Fixture folder for ${PROJECT_NAME}" + ) + + add_dependencies(${PROJECT_NAME} ${PROJECT_NAME}Fixture) + + set_target_properties(${PROJECT_NAME}Fixture PROPERTIES FOLDER UtilityTargets/Tests/Bigfoot/${ParentFolder}) +endfunction() \ No newline at end of file diff --git a/CMake/Utils.cmake b/CMake/Utils.cmake new file mode 100644 index 0000000..9841ed8 --- /dev/null +++ b/CMake/Utils.cmake @@ -0,0 +1,145 @@ +function(bigfoot_create_logger) + set(LOGGER_FILENAME ${PROJECT_NAME}Logger) + string(TOUPPER ${PROJECT_NAME}_Logger LOGGER_NAME) + string(TOUPPER ${LOGGER_FILENAME} LOGGER_FILENAME_UPPER) + configure_file( ${CMAKE_SOURCE_DIR}/Bigfoot/Sources/System/Include/System/Log/TargetLogger_generated.hpp.in + ${CMAKE_CURRENT_SOURCE_DIR}/Include/${PROJECT_NAME}/${LOGGER_FILENAME}_generated.hpp + @ONLY) +endfunction() + +function(bigfoot_create_bigfile ParentFolder) + set(OUTPUT_PATH_BIGFILE "${CMAKE_CURRENT_BINARY_DIR}/${CMAKE_CFG_INTDIR}/${PROJECT_NAME}-bigfile.db") + get_filename_component(OUTPUT_PATH_BIGFILE_ABSOLUTE ${OUTPUT_PATH_BIGFILE} ABSOLUTE) + get_filename_component(OUTPUT_PATH_BIGFILE_DIRECTORY ${OUTPUT_PATH_BIGFILE_ABSOLUTE} DIRECTORY) + + add_custom_command( + OUTPUT ${OUTPUT_PATH_BIGFILE_ABSOLUTE}.bftimestamp ${OUTPUT_PATH_BIGFILE_ABSOLUTE} + DEPENDS ${CMAKE_SOURCE_DIR}/Bigfoot/Sources/Engine/BigFile/BigFileSchema.sql + COMMAND ${CMAKE_COMMAND} -E make_directory ${OUTPUT_PATH_BIGFILE_DIRECTORY} + COMMAND ${SQLITE3_EXECUTABLE} ${OUTPUT_PATH_BIGFILE_ABSOLUTE} < ${CMAKE_SOURCE_DIR}/Bigfoot/Sources/Engine/BigFile/BigFileSchema.sql + COMMAND ${CMAKE_COMMAND} -E touch ${OUTPUT_PATH_BIGFILE_ABSOLUTE}.bftimestamp + COMMENT "Creating Bigfile ${OUTPUT_PATH_BIGFILE_ABSOLUTE}" + ) + list(APPEND BIGFILE_SOURCES ${OUTPUT_PATH_BIGFILE_ABSOLUTE}.bftimestamp) + + add_custom_target(${PROJECT_NAME}BigFile ALL DEPENDS ${BIGFILE_SOURCES}) + set_target_properties(${PROJECT_NAME}BigFile PROPERTIES FOLDER UtilityTargets/${ParentFolder}) + add_dependencies(${PROJECT_NAME}BigFile ${PROJECT_NAME}) + + target_sources(${PROJECT_NAME}BigFile PRIVATE ${BIGFILE_SOURCES}) + + string(TOUPPER ${PROJECT_NAME} BIGFILE_NAME) + set(BIGFILE_LOCATION "./${PROJECT_NAME}-bigfile.db") + configure_file( ${CMAKE_SOURCE_DIR}/Bigfoot/Sources/Engine/Include/Engine/BigFile/BigFileInfo_generated.hpp.in + ${CMAKE_CURRENT_SOURCE_DIR}/Include/${PROJECT_NAME}/BigFileInfo_generated.hpp + @ONLY) +endfunction() + +function(bigfoot_compile_flatbuffers BigfootDependencies) + set(IncludeFolders "") + + get_target_property(CurrentTargetDependencyInclude ${PROJECT_NAME} INCLUDE_DIRECTORIES) + if(CurrentTargetDependencyInclude) + list(APPEND IncludeFolders ${CurrentTargetDependencyInclude}) + endif() + + foreach(Dependency IN LISTS BigfootDependencies) + get_target_property(DependencyInclude ${Dependency} INCLUDE_DIRECTORIES) + if(DependencyInclude) + list(APPEND IncludeFolders ${DependencyInclude}) + endif() + endforeach() + + set(IncludeFlags "") + foreach(folder IN LISTS IncludeFolders) + list(APPEND IncludeFlags -I "${folder}") + endforeach() + + file(GLOB_RECURSE SOURCES "${CMAKE_CURRENT_SOURCE_DIR}/Include/*.fbs") + foreach(SOURCE_FILE IN LISTS SOURCES) + get_filename_component(SOURCE_DIRECTORY ${SOURCE_FILE} DIRECTORY) + + set_property(DIRECTORY APPEND PROPERTY CMAKE_CONFIGURE_DEPENDS ${SOURCE_FILE}) + + execute_process( + COMMAND ${FLATBUFFERS_FLATC_EXECUTABLE} + --cpp + ${IncludeFlags} + --keep-prefix + --filename-ext "hpp" + --reflect-types + --cpp-std c++17 + --reflect-names + --gen-name-strings + --gen-object-api + --cpp-str-flex-ctor + --no-cpp-direct-copy + --force-empty + --cpp-ptr-type "eastl::unique_ptr" + --cpp-str-type "eastl::string" + --cpp-include "EASTL/unique_ptr.h" + --cpp-include "EASTL/string.h" + -o "${SOURCE_DIRECTORY}" + "${SOURCE_FILE}" + ) + endforeach() +endfunction() + +function(bigfoot_setup_dependencies ParentFolder) + set(CONAN_DEPLOYER_DIR "${CMAKE_SOURCE_DIR}/build/full_deploy/host") + + if(EXISTS ${CONAN_DEPLOYER_DIR}) + if(CMAKE_SYSTEM_NAME STREQUAL "Windows") + file(GLOB_RECURSE SHARED_BINARIES ${CONAN_DEPLOYER_DIR}/*mimalloc*.dll) + elseif(CMAKE_SYSTEM_NAME STREQUAL "Linux") + file(GLOB_RECURSE SHARED_BINARIES ${CONAN_DEPLOYER_DIR}/*mimalloc*.so*) + endif() + + if(${IS_MULTI_CONFIG}) + foreach(CONFIG ${CMAKE_CONFIGURATION_TYPES}) + foreach(file ${SHARED_BINARIES}) + if(file MATCHES "/${CONFIG}/") + list(APPEND SHARED_BINARIES_${CONFIG} ${file}) + endif() + endforeach() + endforeach() + + add_custom_target(${PROJECT_NAME}CopySharedBinaries + ALL DEPENDS SHARED_BINARIES + COMMAND ${CMAKE_COMMAND} -E make_directory $ + COMMAND ${CMAKE_COMMAND} -E $,copy_if_different,true> ${SHARED_BINARIES_Debug} $ + COMMAND ${CMAKE_COMMAND} -E $,copy_if_different,true> ${SHARED_BINARIES_Release} $ + COMMAND ${CMAKE_COMMAND} -E $,copy_if_different,true> ${SHARED_BINARIES_RelWithDebInfo} $ + COMMENT "Copy shared binaries for ${PROJECT_NAME}" + ) + add_dependencies(${PROJECT_NAME} ${PROJECT_NAME}CopySharedBinaries) + set_target_properties(${PROJECT_NAME}CopySharedBinaries PROPERTIES FOLDER UtilityTargets/${ParentFolder}) + + else() + foreach(file ${SHARED_BINARIES}) + if(file MATCHES "/${CMAKE_BUILD_TYPE}/") + list(APPEND SHARED_BINARIES_${CMAKE_BUILD_TYPE} ${file}) + endif() + endforeach() + + add_custom_target(${PROJECT_NAME}CopySharedBinaries ALL + DEPENDS ${SHARED_BINARIES_${CMAKE_BUILD_TYPE}} + COMMAND ${CMAKE_COMMAND} -E make_directory $ + COMMAND ${CMAKE_COMMAND} -E copy_if_different ${SHARED_BINARIES_${CMAKE_BUILD_TYPE}} $ + COMMENT "Copy shared binaries for ${PROJECT_NAME}" + ) + add_dependencies(${PROJECT_NAME} ${PROJECT_NAME}CopySharedBinaries) + set_target_properties(${PROJECT_NAME}CopySharedBinaries PROPERTIES FOLDER UtilityTargets/${ParentFolder}) + endif() + endif() + + if(CMAKE_SYSTEM_NAME STREQUAL "Windows") + add_custom_target(${PROJECT_NAME}PatchMinject ALL + COMMAND ${MINJECT_EXECUTABLE} -i -f $ + COMMENT "Patching ${PROJECT_NAME} to ensure mimalloc dynamic override" + ) + add_dependencies(${PROJECT_NAME}PatchMinject ${PROJECT_NAME}) + set_target_properties(${PROJECT_NAME}PatchMinject PROPERTIES FOLDER "UtilityTargets/${ParentFolder}") + endif() + +endfunction() \ No newline at end of file diff --git a/CMakeLists.txt b/CMakeLists.txt new file mode 100644 index 0000000..665a2ff --- /dev/null +++ b/CMakeLists.txt @@ -0,0 +1,63 @@ +cmake_minimum_required(VERSION 3.24) + +# CMake sets this flag by default, we don't use exception in bigfoot, we can remove it +string(REPLACE "/EHsc" "" CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS}") + +project(Bigfoot VERSION 0.1.0 + DESCRIPTION "The Bigfoot engine" + LANGUAGES CXX) + +set(CMAKE_CXX_STANDARD 20) +set(CMAKE_CXX_STANDARD_REQUIRED True) + +set(CMAKE_POLICY_DEFAULT_CMP0077 NEW) + +get_property(IS_MULTI_CONFIG GLOBAL PROPERTY GENERATOR_IS_MULTI_CONFIG) +set(CMAKE_CONFIGURATION_TYPES "Release;RelWithDebInfo;Debug" CACHE STRING "" FORCE) + +option(BUILD_TESTS OFF) +option(TRACY ON) +option(BUILD_TOOLS ON) +option(VULKAN ON) +option(BUILD_BENCHMARKS OFF) + +set(AUTO_GENERATED_COMMENT "// AUTO-GENERATED DO NOT TOUCH") + +include(${CMAKE_SOURCE_DIR}/CMake/FindDependencies.cmake) +include(${CMAKE_SOURCE_DIR}/CMake/Utils.cmake) +include(${CMAKE_SOURCE_DIR}/CMake/Package.cmake) + +find_program(FLATBUFFERS_FLATC_EXECUTABLE NAMES flatc) +find_program(SQLITE3_EXECUTABLE NAMES sqlite3) +find_program(MINJECT_EXECUTABLE NAMES minject) + +set(CMAKE_EXPORT_COMPILE_COMMANDS ON) +set(CMAKE_OPTIMIZE_DEPENDENCIES 1) + +add_compile_definitions( + $<$:NOMINMAX> + $<$:WIN32_LEAN_AND_MEAN> + $<$:BIGFOOT_WINDOWS> + $<$:BIGFOOT_LINUX> + $<$:BIGFOOT_OPTIMIZED> + $<$:BIGFOOT_NOT_OPTIMIZED>) + +if(BUILD_TESTS) + enable_testing() +endif() + +set_property(GLOBAL PROPERTY USE_FOLDERS ON) + +SET(CMAKE_SKIP_BUILD_RPATH FALSE) +SET(CMAKE_BUILD_WITH_INSTALL_RPATH TRUE) +SET(CMAKE_INSTALL_RPATH "\${ORIGIN}") + +add_subdirectory(${CMAKE_CURRENT_SOURCE_DIR}/Bigfoot/Sources) +if(${BUILD_TESTS}) + add_subdirectory(${CMAKE_CURRENT_SOURCE_DIR}/Bigfoot/Tests) +endif() + +add_custom_target(NatVis SOURCES + ${CMAKE_CURRENT_SOURCE_DIR}/Vendor/NatVis/EASTL/EASTL.natvis + ${CMAKE_CURRENT_SOURCE_DIR}/Vendor/NatVis/VulkanHpp/VulkanHpp.natvis + ${CMAKE_CURRENT_SOURCE_DIR}/Vendor/NatVis/GLM/GLM.natvis) \ No newline at end of file diff --git a/LICENSE b/LICENSE new file mode 100644 index 0000000..782de7c --- /dev/null +++ b/LICENSE @@ -0,0 +1,21 @@ +MIT License + +Copyright (c) 2022-2025 Romain BOULLARD + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/README.md b/README.md new file mode 100644 index 0000000..5a66607 --- /dev/null +++ b/README.md @@ -0,0 +1,65 @@ +# Bigfoot + +A multiplatform 3D game engine + +# Goals + +The goal is to build a multiplatform, API agnostic, 3D engine. Since this is a learning project, I don't aim to provide a viable option to build actual commercial games with it. This also means that I am providing the project as is, with no support whatsoever. + +# Building + +### Requirements + +1. [ConanV2](https://conan.io/) +3. [Vulkan SDK](https://www.lunarg.com/vulkan-sdk/) (If you target Vulkan) +4. [CMake](https://cmake.org/) +5. [Git](https://git-scm.com/) +7. [Python3](https://www.python.org/) + +#### Additional requirements for Linux + +1. [Clang](https://clang.llvm.org/) (Version 18) +2. [Mold](https://github.com/rui314/mold) +3. [Ninja](https://github.com/ninja-build/ninja) +4. [CCache](https://ccache.dev/) (Not a requirement, but nice to have) + +Note: you can modify the conan profile used to overcome these requirements. But I provide no support for anything else than what's listed here + +#### Additional requirements for Windows + +1. MSVC + +Note: you can modify the conan profile used to overcome these requirements. But I provide no support for anything else than what's listed here + +### Generating the dependencies for Bigfoot + +Use generate_dependencies.sh or generate_dependencies.bat (depending on your platform). These scripts will download/build/install any necessary dependency, using Conan. The recipes used will come from [my own conan recipe center](packages.bigfootengine.com) + +You will need to provide the 'force' or 'missing' parameters to these scripts. I'd recommand for a first run to use 'force' to build all dependencies, and on subsequent runs to use 'missing' to build only missing parameters + +``` +./generate_dependencies.sh force +or +./generate_dependencies.sh missing +``` + +You can customize these scripts to opt-out of some Bigfoot features + +'Just' modify these lines to disable them (I promise to one day modify the script to do it from the command line) + +``` +-o bigfoot/*:build_tests=True -o bigfoot/*:tracy=True -o bigfoot/*:build_tools=True -o bigfoot/*:vulkan=True -o bigfoot/*:build_benchmarks=True +``` + +1. build_tests: Enable/Disable the tests +2. tracy: Enable/Disable profiling using [Tracy](https://github.com/wolfpld/tracy) +3. build_tools: Enable/Disable the tools (I'd absolutely recommand not disabling this) +4. vulkan: Enable/Disable Vulkan renderer (No point disabling it, since for now only Vulkan is available in Bigfoot) +5. build_benchmarks: Enable/Disable the benchmarks + + +### Generating Bigfoot + +Use generate_bigfoot.sh or generate_bigfoot.bat (depending on your platform) to generate the build files for Bigfoot. + +You will then be able to use either Visual Studio (Windows) or Ninja (Linux) to build BigFoot \ No newline at end of file diff --git a/Vendor/NatVis/EASTL/EASTL.natvis b/Vendor/NatVis/EASTL/EASTL.natvis new file mode 100644 index 0000000..e1ec96d --- /dev/null +++ b/Vendor/NatVis/EASTL/EASTL.natvis @@ -0,0 +1,761 @@ + + + + + + + + ({(void*)mPair.mFirst} = {*mPair.mFirst}) + ({nullptr}) + + (void*)mPair.mFirst + *mPair.mFirst + + + + + ({(void*)mpValue} = {*mpValue}) + ({nullptr}) + + (void*)mpValue + *mpValue + mpRefCount->mRefCount + mpRefCount->mWeakRefCount + + + + + {((mpRefCount && mpRefCount->mRefCount) ? mpValue : nullptr)} + + mpRefCount && mpRefCount->mRefCount ? mpValue : nullptr + + + + + [{$T2}] {{}} + [{$T2}] {{ {*mValue} }} + [{$T2}] {{ {*mValue}, {*(mValue+1)} }} + [{$T2}] {{ {*mValue}, {*(mValue+1)}, {*(mValue+2)} }} + [{$T2}] {{ {*mValue}, {*(mValue+1)}, {*(mValue+2)}, {*(mValue+3)} }} + [{$T2}] {{ {*mValue}, {*(mValue+1)}, {*(mValue+2)}, {*(mValue+3)}, {*(mValue+4)} }} + [{$T2}] {{ {*mValue}, {*(mValue+1)}, {*(mValue+2)}, {*(mValue+3)}, {*(mValue+4)}, {*(mValue+5)} }} + [{$T2}] {{ {*mValue}, {*(mValue+1)}, {*(mValue+2)}, {*(mValue+3)}, {*(mValue+4)}, {*(mValue+5)}, ... }} + + $T2 + + $T2 + mValue + + + + + + "{mPair.mFirst.heap.mpBegin,sb}" + "{mPair.mFirst.sso.mData,sb}" + + mPair.mFirst.heap.mnSize + (mPair.mFirst.heap.mnCapacity & ~kHeapMask) + mPair.mFirst.heap.mpBegin,sb + + (SSOLayout::SSO_CAPACITY - mPair.mFirst.sso.mRemainingSizeField.mnRemainingSize) + SSOLayout::SSO_CAPACITY + mPair.mFirst.sso.mData,sb + + !!(mPair.mFirst.sso.mRemainingSizeField.mnRemainingSize & kSSOMask) + + + + + + {mPair.mFirst.heap.mpBegin,su} + {mPair.mFirst.sso.mData,su} + + mPair.mFirst.heap.mnSize + (mPair.mFirst.heap.mnCapacity & ~kHeapMask) + mPair.mFirst.heap.mpBegin,su + + (SSOLayout::SSO_CAPACITY - mPair.mFirst.sso.mRemainingSizeField.mnRemainingSize) + SSOLayout::SSO_CAPACITY + mPair.mFirst.sso.mData,su + + !!(mPair.mFirst.sso.mRemainingSizeField.mnRemainingSize & kSSOMask) + + + + + ({first}, {second}) + + first + second + + + + + [{mnSize}] {{}} + [{mnSize}] {{ {*mpData} }} + [{mnSize}] {{ {*mpData}, {*(mpData+1)} }} + [{mnSize}] {{ {*mpData}, {*(mpData+1)}, {*(mpData+2)} }} + [{mnSize}] {{ {*mpData}, {*(mpData+1)}, {*(mpData+2)}, {*(mpData+3)} }} + [{mnSize}] {{ {*mpData}, {*(mpData+1)}, {*(mpData+2)}, {*(mpData+3)}, {*(mpData+4)} }} + [{mnSize}] {{ {*mpData}, {*(mpData+1)}, {*(mpData+2)}, {*(mpData+3)}, {*(mpData+4)}, {*(mpData+5)} }} + [{mnSize}] {{ {*mpData}, {*(mpData+1)}, {*(mpData+2)}, {*(mpData+3)}, {*(mpData+4)}, {*(mpData+5)}, ... }} + + mnSize + + mnSize + mpData + + + + + + [{mpEnd - mpBegin}] {{}} + [{mpEnd - mpBegin}] {{ {*mpBegin} }} + [{mpEnd - mpBegin}] {{ {*mpBegin}, {*(mpBegin+1)} }} + [{mpEnd - mpBegin}] {{ {*mpBegin}, {*(mpBegin+1)}, {*(mpBegin+2)} }} + [{mpEnd - mpBegin}] {{ {*mpBegin}, {*(mpBegin+1)}, {*(mpBegin+2)}, {*(mpBegin+3)} }} + [{mpEnd - mpBegin}] {{ {*mpBegin}, {*(mpBegin+1)}, {*(mpBegin+2)}, {*(mpBegin+3)}, {*(mpBegin+4)} }} + [{mpEnd - mpBegin}] {{ {*mpBegin}, {*(mpBegin+1)}, {*(mpBegin+2)}, {*(mpBegin+3)}, {*(mpBegin+4)}, {*(mpBegin+5)} }} + [{mpEnd - mpBegin}] {{ {*mpBegin}, {*(mpBegin+1)}, {*(mpBegin+2)}, {*(mpBegin+3)}, {*(mpBegin+4)}, {*(mpBegin+5)}, ... }} + + mpEnd - mpBegin + mCapacityAllocator.mFirst - mpBegin + + mpEnd - mpBegin + mpBegin + + + + + + + [0] {{}} + + + [1] {{ {*mItBegin.mpCurrent} }} + + + [{(mItEnd.mpCurrentArrayPtr - mItBegin.mpCurrentArrayPtr) * $T3 + (mItEnd.mpCurrent-mItEnd.mpBegin) - (mItBegin.mpCurrent-mItBegin.mpBegin)}] + {{ + {*mItBegin.mpCurrent}, + ... + }} + + + (mItEnd.mpCurrentArrayPtr - mItBegin.mpCurrentArrayPtr) * $T3 + (mItEnd.mpCurrent-mItEnd.mpBegin) - (mItBegin.mpCurrent-mItBegin.mpBegin) + + (mItEnd.mpCurrentArrayPtr - mItBegin.mpCurrentArrayPtr) * $T3 + (mItEnd.mpCurrent-mItEnd.mpBegin) - (mItBegin.mpCurrent-mItBegin.mpBegin) + mItBegin.mpCurrentArrayPtr[(mItBegin.mpCurrent-mItBegin.mpBegin + $i) / $T3][(mItBegin.mpCurrent-mItBegin.mpBegin + $i) % $T3] + + + + + + {*mpCurrent} + + *mpCurrent + *(*(mpCurrentArrayPtr-1) + (mpEnd-mpBegin) - 1) + *(mpCurrent-1) + **(mpCurrentArrayPtr+1) + *(mpCurrent+1) + mpCurrent == mpBegin + mpCurrent+1 == mpEnd + + + + + + + {c} + + c + + + + + + [0] {{}} + + + [1] {{ {((eastl::ListNode<$T1>*)mNodeAllocator.mFirst.mpNext)->mValue} }} + + + [2] + {{ + {((eastl::ListNode<$T1>*)mNodeAllocator.mFirst.mpNext)->mValue}, + {((eastl::ListNode<$T1>*)mNodeAllocator.mFirst.mpNext->mpNext)->mValue} + }} + + + [?] + {{ + {((eastl::ListNode<$T1>*)mNodeAllocator.mFirst.mpNext)->mValue}, + {((eastl::ListNode<$T1>*)mNodeAllocator.mFirst.mpNext->mpNext)->mValue}, + ... + }} + + + + Content of lists will repeat indefinitely. Keep that in mind! + + + mNodeAllocator.mFirst.mpNext + mpNext + ((eastl::ListNode<$T1>*)this)->mValue + + + + + + {mValue} + + mValue + *(eastl::ListNode<$T1>*)mpNext + *(eastl::ListNode<$T1>*)mpPrev + + Content of lists will repeat indefinitely. Keep that in mind! + + + The rest of the list follows: + + + (eastl::ListNode<$T1>*)mpNext->mpNext + (eastl::ListNode<$T1>*)mpNext + mValue + + + + + + {*mpNode} + + *(eastl::ListNode<$T1>*)mpNode + + + + + + [0] {{}} + + + [1] + {{ + {((eastl::SListNode<$T1>*)mNode.mpNext)->mValue} + }} + + + [2] + {{ + {((eastl::SListNode<$T1>*)mNode.mpNext)->mValue}, + {((eastl::SListNode<$T1>*)mNode.mpNext->mpNext)->mValue} + }} + + + [?] + {{ + {((eastl::SListNode<$T1>*)mNode.mpNext)->mValue}, + {((eastl::SListNode<$T1>*)mNode.mpNext->mpNext)->mValue}, + ... + }} + + + + mNode.mpNext + mpNext + ((eastl::SListNode<$T1>*)this)->mValue + + + + + + {mValue} + + mValue + *(eastl::SListNode<$T1>*)mpNext + + The rest of the list follows: + + + mpNext == nullptr ? nullptr : (eastl::SListNode<$T1>*)mpNext->mpNext + (eastl::SListNode<$T1>*)mpNext + mValue + + + + + + {*mpNode} + + *(eastl::SListNode<$T1>*)mpNode + + + + + [0] {{}} + [1] {{ {mAnchor.mpNext} }} + [?] {{ {mAnchor.mpNext}, ... }} + + + Content of intrusive lists will repeat indefinitely. Keep that in mind! + + + mAnchor.mpNext + mpNext + *this + + + + + + {*($T1*)mpNode} + + *($T1*)mpNode + + + + + + + [0] {{}} + + + [1] + {{ + {((eastl::rbtree_node<$T1>*)mAnchor.mpNodeLeft)->mValue} + }} + + + [{mnSize}] + {{ + {((eastl::rbtree_node<$T1>*)mAnchor.mpNodeLeft)->mValue}, + ... + }} + + + mnSize + + mnSize + mAnchor.mpNodeParent + mpNodeLeft + mpNodeRight + ((eastl::rbtree_node<$T1>*)this)->mValue + + + + + + + [0] {{}} + + + [1] + {{ + {((eastl::rbtree_node<$T2>*)mAnchor.mpNodeLeft)->mValue} + }} + + + [{mnSize}] + {{ + {((eastl::rbtree_node<$T2>*)mAnchor.mpNodeLeft)->mValue}, + ... + }} + + + mnSize + + mnSize + mAnchor.mpNodeParent + mpNodeLeft + mpNodeRight + ((eastl::rbtree_node<$T2>*)this)->mValue + + + + + + {mValue} + + mValue + + It is possible to expand parents that do not exist. + + *(eastl::rbtree_node<$T1>*)mpNodeParent + *(eastl::rbtree_node<$T1>*)mpNodeLeft + *(eastl::rbtree_node<$T1>*)mpNodeRight + + + + + {*(eastl::rbtree_node<$T1>*)mpNode} + + *(eastl::rbtree_node<$T1>*)mpNode + + + + + + [{mnElementCount}] {{}} + [{mnElementCount}] {{ ... }} + + + mnBucketCount + mpBucketArray + + + + + + entry->mValue + + entry = entry->mpNext + + + bucketIndex++ + + entry = mpBucketArray[bucketIndex] + + + + + + + + + [{mnElementCount}] {{}} + [{mnElementCount}] {{ ... }} + + + + + + entry->mValue.second + + entry = entry->mpNext + + + bucketIndex++ + + entry = mpBucketArray[bucketIndex] + + + + + + + + {mValue}, {*mpNext} + {mValue} + + + + this + mpNext + mValue + + + + + + {mpNode->mValue} + + mpNode->mValue + + + + + {*(mIterator-1)} + + mIterator-1 + + + + + {{count = {kSize}}} + + kSize + + + + + + kSize + + + bBitValue = ((mWord[iWord] >> iBitInWord) % 2) != 0 ? true : false + bBitValue + iBitInWord++ + + iWord++ + iBitInWord = 0 + + + + + + + + {c} + + c + + + + + {mpBegin,[mnCount]} + mpBegin,[mnCount] + + + + ({mFirst}, {mSecond}) + ({mSecond}) + ({mFirst}) + (empty) + (empty) + ({mFirst}, {mSecond}) + + + + + nullopt + {value()} + + value() + + + + + {$T1} to {$T2}} + + + + + {mRep} nanoseconds + + + + {mRep} microseconds + + + + {mRep} milliseconds + + + + {mRep} seconds + + + + {mRep} minutes + + + + {mRep} hours + + + + {mRep} duration with ratio = [{$T2} : {$T3}] + + + + + + empty + {mInvokeFuncPtr} + + + + + {*val} + + + + + empty + {m_storage.external_storage} + + + + + {mAtomic} + + mAtomic + + + + + {mFlag.mAtomic} + + + + + [valueless_by_exception] + {{ index=0, value={($T1*)mStorage.mBuffer.mCharData}} + {{ index=1, value={($T2*)mStorage.mBuffer.mCharData}} + {{ index=2, value={($T3*)mStorage.mBuffer.mCharData}} + {{ index=3, value={($T4*)mStorage.mBuffer.mCharData}} + {{ index=4, value={($T5*)mStorage.mBuffer.mCharData}} + {{ index=5, value={($T6*)mStorage.mBuffer.mCharData}} + {{ index=6, value={($T7*)mStorage.mBuffer.mCharData}} + {{ index=7, value={($T8*)mStorage.mBuffer.mCharData}} + {{ index=8, value={($T9*)mStorage.mBuffer.mCharData}} + {{ index=9, value={($T10*)mStorage.mBuffer.mCharData}} + {{ index=10, value={($T11*)mStorage.mBuffer.mCharData}} + {{ index=11, value={($T12*)mStorage.mBuffer.mCharData}} + {{ index=12, value={($T13*)mStorage.mBuffer.mCharData}} + {{ index=13, value={($T14*)mStorage.mBuffer.mCharData}} + {{ index=14, value={($T15*)mStorage.mBuffer.mCharData}} + {{ index=15, value={($T16*)mStorage.mBuffer.mCharData}} + {{ index=16, value={($T17*)mStorage.mBuffer.mCharData}} + {{ index=17, value={($T18*)mStorage.mBuffer.mCharData}} + {{ index=18, value={($T19*)mStorage.mBuffer.mCharData}} + {{ index=19, value={($T20*)mStorage.mBuffer.mCharData}} + {{ index=20, value={($T21*)mStorage.mBuffer.mCharData}} + {{ index=21, value={($T22*)mStorage.mBuffer.mCharData}} + {{ index=22, value={($T23*)mStorage.mBuffer.mCharData}} + {{ index=23, value={($T24*)mStorage.mBuffer.mCharData}} + {{ index=24, value={($T25*)mStorage.mBuffer.mCharData}} + {{ index=25, value={($T26*)mStorage.mBuffer.mCharData}} + {{ index=26, value={($T27*)mStorage.mBuffer.mCharData}} + {{ index=27, value={($T28*)mStorage.mBuffer.mCharData}} + {{ index=28, value={($T29*)mStorage.mBuffer.mCharData}} + {{ index=29, value={($T30*)mStorage.mBuffer.mCharData}} + {{ index=30, value={($T31*)mStorage.mBuffer.mCharData}} + + index() + ($T1*)mStorage.mBuffer.mCharData + ($T2*)mStorage.mBuffer.mCharData + ($T3*)mStorage.mBuffer.mCharData + ($T4*)mStorage.mBuffer.mCharData + ($T5*)mStorage.mBuffer.mCharData + ($T6*)mStorage.mBuffer.mCharData + ($T7*)mStorage.mBuffer.mCharData + ($T8*)mStorage.mBuffer.mCharData + ($T9*)mStorage.mBuffer.mCharData + ($T10*)mStorage.mBuffer.mCharData + ($T11*)mStorage.mBuffer.mCharData + ($T12*)mStorage.mBuffer.mCharData + ($T13*)mStorage.mBuffer.mCharData + ($T14*)mStorage.mBuffer.mCharData + ($T15*)mStorage.mBuffer.mCharData + ($T16*)mStorage.mBuffer.mCharData + ($T17*)mStorage.mBuffer.mCharData + ($T18*)mStorage.mBuffer.mCharData + ($T19*)mStorage.mBuffer.mCharData + ($T20*)mStorage.mBuffer.mCharData + ($T21*)mStorage.mBuffer.mCharData + ($T22*)mStorage.mBuffer.mCharData + ($T23*)mStorage.mBuffer.mCharData + ($T24*)mStorage.mBuffer.mCharData + ($T25*)mStorage.mBuffer.mCharData + ($T26*)mStorage.mBuffer.mCharData + ($T27*)mStorage.mBuffer.mCharData + ($T28*)mStorage.mBuffer.mCharData + ($T29*)mStorage.mBuffer.mCharData + ($T30*)mStorage.mBuffer.mCharData + ($T31*)mStorage.mBuffer.mCharData + + + + + + + ({*this,view(noparens)}) + + + + + {(*((eastl::Internal::TupleLeaf<0,$T1,0>*)&mImpl)).mValue} + ({*this,view(noparens)}) + + (*((eastl::Internal::TupleLeaf<0,$T1,0>*)&mImpl)).mValue + + + + + {(*((eastl::Internal::TupleLeaf<0,$T1,0>*)&mImpl)).mValue}, {(*((eastl::Internal::TupleLeaf<1,$T2,0>*)&mImpl)).mValue} + ({*this,view(noparens)}) + + (*((eastl::Internal::TupleLeaf<0,$T1,0>*)&mImpl)).mValue + (*((eastl::Internal::TupleLeaf<1,$T2,0>*)&mImpl)).mValue + + + + + {(*((eastl::Internal::TupleLeaf<0,$T1,0>*)&mImpl)).mValue}, {(*((eastl::Internal::TupleLeaf<1,$T2,0>*)&mImpl)).mValue}, {(*((eastl::Internal::TupleLeaf<2,$T3,0>*)&mImpl)).mValue} + ({*this,view(noparens)}) + + (*((eastl::Internal::TupleLeaf<0,$T1,0>*)&mImpl)).mValue + (*((eastl::Internal::TupleLeaf<1,$T2,0>*)&mImpl)).mValue + (*((eastl::Internal::TupleLeaf<2,$T3,0>*)&mImpl)).mValue + + + + + {(*((eastl::Internal::TupleLeaf<0,$T1,0>*)&mImpl)).mValue}, {(*((eastl::Internal::TupleLeaf<1,$T2,0>*)&mImpl)).mValue}, {(*((eastl::Internal::TupleLeaf<2,$T3,0>*)&mImpl)).mValue}, {(*((eastl::Internal::TupleLeaf<3,$T4,0>*)&mImpl)).mValue} + ({*this,view(noparens)}) + + (*((eastl::Internal::TupleLeaf<0,$T1,0>*)&mImpl)).mValue + (*((eastl::Internal::TupleLeaf<1,$T2,0>*)&mImpl)).mValue + (*((eastl::Internal::TupleLeaf<2,$T3,0>*)&mImpl)).mValue + (*((eastl::Internal::TupleLeaf<3,$T4,0>*)&mImpl)).mValue + + + + + {(*((eastl::Internal::TupleLeaf<0,$T1,0>*)&mImpl)).mValue}, {(*((eastl::Internal::TupleLeaf<1,$T2,0>*)&mImpl)).mValue}, {(*((eastl::Internal::TupleLeaf<2,$T3,0>*)&mImpl)).mValue}, {(*((eastl::Internal::TupleLeaf<3,$T4,0>*)&mImpl)).mValue}, {(*((eastl::Internal::TupleLeaf<4,$T5,0>*)&mImpl)).mValue} + ({*this,view(noparens)}) + + (*((eastl::Internal::TupleLeaf<0,$T1,0>*)&mImpl)).mValue + (*((eastl::Internal::TupleLeaf<1,$T2,0>*)&mImpl)).mValue + (*((eastl::Internal::TupleLeaf<2,$T3,0>*)&mImpl)).mValue + (*((eastl::Internal::TupleLeaf<3,$T4,0>*)&mImpl)).mValue + (*((eastl::Internal::TupleLeaf<4,$T5,0>*)&mImpl)).mValue + + + + + {(*((eastl::Internal::TupleLeaf<0,$T1,0>*)&mImpl)).mValue}, {(*((eastl::Internal::TupleLeaf<1,$T2,0>*)&mImpl)).mValue}, {(*((eastl::Internal::TupleLeaf<2,$T3,0>*)&mImpl)).mValue}, {(*((eastl::Internal::TupleLeaf<3,$T4,0>*)&mImpl)).mValue}, {(*((eastl::Internal::TupleLeaf<4,$T5,0>*)&mImpl)).mValue}, {(*((eastl::Internal::TupleLeaf<5,$T6,0>*)&mImpl)).mValue} + ({*this,view(noparens)}) + + (*((eastl::Internal::TupleLeaf<0,$T1,0>*)&mImpl)).mValue + (*((eastl::Internal::TupleLeaf<1,$T2,0>*)&mImpl)).mValue + (*((eastl::Internal::TupleLeaf<2,$T3,0>*)&mImpl)).mValue + (*((eastl::Internal::TupleLeaf<3,$T4,0>*)&mImpl)).mValue + (*((eastl::Internal::TupleLeaf<4,$T5,0>*)&mImpl)).mValue + (*((eastl::Internal::TupleLeaf<5,$T6,0>*)&mImpl)).mValue + + + + + {(*((eastl::Internal::TupleLeaf<0,$T1,0>*)&mImpl)).mValue}, {(*((eastl::Internal::TupleLeaf<1,$T2,0>*)&mImpl)).mValue}, {(*((eastl::Internal::TupleLeaf<2,$T3,0>*)&mImpl)).mValue}, {(*((eastl::Internal::TupleLeaf<3,$T4,0>*)&mImpl)).mValue}, {(*((eastl::Internal::TupleLeaf<4,$T5,0>*)&mImpl)).mValue}, {(*((eastl::Internal::TupleLeaf<5,$T6,0>*)&mImpl)).mValue}, {(*((eastl::Internal::TupleLeaf<6,$T7,0>*)&mImpl)).mValue} + ({*this,view(noparens)}) + + (*((eastl::Internal::TupleLeaf<0,$T1,0>*)&mImpl)).mValue + (*((eastl::Internal::TupleLeaf<1,$T2,0>*)&mImpl)).mValue + (*((eastl::Internal::TupleLeaf<2,$T3,0>*)&mImpl)).mValue + (*((eastl::Internal::TupleLeaf<3,$T4,0>*)&mImpl)).mValue + (*((eastl::Internal::TupleLeaf<4,$T5,0>*)&mImpl)).mValue + (*((eastl::Internal::TupleLeaf<5,$T6,0>*)&mImpl)).mValue + (*((eastl::Internal::TupleLeaf<6,$T7,0>*)&mImpl)).mValue + + + + + diff --git a/Vendor/NatVis/GLM/GLM.natvis b/Vendor/NatVis/GLM/GLM.natvis new file mode 100644 index 0000000..018be8d --- /dev/null +++ b/Vendor/NatVis/GLM/GLM.natvis @@ -0,0 +1,555 @@ + + + + + + + + [{x,g}] + + x,g + + + + + [{x,g} {y,g}] + + x,g + y,g + + + + + [{x,g} {y,g} {z,g}] + + x,g + y,g + z,g + + + + + [{x,g} {y,g} {z,g} {w,g}] + + x,g + y,g + z,g + w,g + + + + + [{(int)x}] + + x + + + + + [{(int)x} {(int)y}] + + x + y + + + + + [{(int)x,g} {(int)y,g} {(int)z,g}] + + x + y + z + + + + + [{(int)x,g} {(int)y,g} {(int)z,g} {(int)w,g}] + + x + y + z + w + + + + + [{x,g} {y,g}] + + + + + + + + k = *(float *)&i + k = k * (1.5f - (n * k * k)) + k = k * (1.5f - (n * k * k)) + k = k * (1.5f - (n * k * k)) + 1/k,g + + + 0.0f,g + + + x,g + y,g + + + + + [{x,g} {y,g} {z,g}] + + + + + + + + k = *(float *)&i + k = k * (1.5f - (n * k * k)) + k = k * (1.5f - (n * k * k)) + k = k * (1.5f - (n * k * k)) + 1/k,g + + + 0.0f,g + + + + + + #{ + (unsigned((x<0?0:(x>1?1:x))*255.5f) << 24) | + (unsigned((y<0?0:(y>1?1:y))*255.5f) << 16) | + (unsigned((z<0?0:(z>1?1:z))*255.5f) << 8) | 0xFF,Xb + } + + + x,g + y,g + z,g + + + + + [{x,g} {y,g} {z,g} {w,g}] + + + + + + + + k = *(float *)&i + k = k * (1.5f - (n * k * k)) + k = k * (1.5f - (n * k * k)) + k = k * (1.5f - (n * k * k)) + 1/k,g + + + 0.0f,g + + + + + + #{ + (unsigned((x<0?0:(x>1?1:x))*255.5f) << 24) | + (unsigned((y<0?0:(y>1?1:y))*255.5f) << 16) | + (unsigned((z<0?0:(z>1?1:z))*255.5f) << 8) | + (unsigned((w<0?0:(w>1?1:w))*255.5f) << 0),Xb + } + + + x,g + y,g + z,g + w,g + + + + + [{x,g} {y,g}] + + + + + + + + k = *(double *)&i + k = k * (1.5 - (n * k * k)) + k = k * (1.5 - (n * k * k)) + k = k * (1.5 - (n * k * k)) + 1/k,g + + + 0.0,g + + + x,g + y,g + + + + + [{x,g} {y,g} {z,g}] + + + + + + + + k = *(double *)&i + k = k * (1.5 - (n * k * k)) + k = k * (1.5 - (n * k * k)) + k = k * (1.5 - (n * k * k)) + 1/k,g + + + 0.0,g + + + x,g + y,g + z,g + + + + + [{x,g} {y,g} {z,g} {w,g}] + + + + + + + + k = *(double *)&i + k = k * (1.5 - (n * k * k)) + k = k * (1.5 - (n * k * k)) + k = k * (1.5 - (n * k * k)) + 1/k,g + + + 0.0,g + + + x,g + y,g + z,g + w,g + + + + + {w,g} + {x,g}i + {y,g}j + {z,g}k + + x,g + y,g + z,g + w,g + + + + + {w,g} + {x,g}i + {y,g}j + {z,g}k + + + + + + + + k = *(float *)&i + k = k * (1.5f - (n * k * k)) + k = k * (1.5f - (n * k * k)) + k = k * (1.5f - (n * k * k)) + 1/k,g + + + 0.0f,g + + + x,g + y,g + z,g + w,g + + + + + {w,g} + {x,g}i + {y,g}j + {z,g}k + + + + + + + + k = *(double *)&i + k = k * (1.5 - (n * k * k)) + k = k * (1.5 - (n * k * k)) + k = k * (1.5 - (n * k * k)) + 1/k,g + + + 0.0,g + + + x,g + y,g + z,g + w,g + + + + + [{value[0]} {value[1]}] + + + + [{value[0].x,g} {value[1].x,g}] + + + [{value[0].y,g} {value[1].y,g}] + + + + value[0] + value[1] + + + + + + + [{value[0]} {value[1]}] + + + + [{value[0].x,g} {value[1].x,g}] + + + [{value[0].y,g} {value[1].y,g}] + + + [{value[0].z,g} {value[1].z,g}] + + + + value[0] + value[1] + + + + + + + [{value[0]} {value[1]}] + + + + [{value[0].x,g} {value[1].x,g}] + + + [{value[0].y,g} {value[1].y,g}] + + + [{value[0].z,g} {value[1].z,g}] + + + [{value[0].w,g} {value[1].w,g}] + + + + value[0] + value[1] + + + + + + + [{value[0]} {value[1]} {value[2]}] + + + + [{value[0].x,g} {value[1].x,g} {value[2].x,g}] + + + [{value[0].y,g} {value[1].y,g} {value[2].y,g}] + + + + value[0] + value[1] + value[2] + + + + + + + [{value[0]} {value[1]} {value[2]}] + + + + [{value[0].x,g} {value[1].x,g} {value[2].x,g}] + + + [{value[0].y,g} {value[1].y,g} {value[2].y,g}] + + + [{value[0].z,g} {value[1].z,g} {value[2].z,g}] + + + + value[0] + value[1] + value[2] + + + + + + + [{value[0]} {value[1]} {value[2]}] + + + + [{value[0].x,g} {value[1].x,g} {value[2].x,g}] + + + [{value[0].y,g} {value[1].y,g} {value[2].y,g}] + + + [{value[0].z,g} {value[1].z,g} {value[2].z,g}] + + + [{value[0].w,g} {value[1].w,g} {value[2].w,g}] + + + + value[0] + value[1] + value[2] + + + + + + + [{value[0]} {value[1]} {value[2]} {value[3]}] + + + + [{value[0].x,g} {value[1].x,g} {value[2].x,g} {value[3].x,g}] + + + [{value[0].y,g} {value[1].y,g} {value[2].y,g} {value[3].y,g}] + + + + value[0] + value[1] + value[2] + value[3] + + + + + + + [{value[0]} {value[1]} {value[2]} {value[3]}] + + + + [{value[0].x,g} {value[1].x,g} {value[2].x,g} {value[3].x,g}] + + + [{value[0].y,g} {value[1].y,g} {value[2].y,g} {value[3].y,g}] + + + [{value[0].z,g} {value[1].z,g} {value[2].z,g} {value[3].z,g}] + + + + value[0] + value[1] + value[2] + value[3] + + + + + + + [{value[0]} {value[1]} {value[2]} {value[3]}] + + + + [{value[0].x,g} {value[1].x,g} {value[2].x,g} {value[3].x,g}] + + + [{value[0].y,g} {value[1].y,g} {value[2].y,g} {value[3].y,g}] + + + [{value[0].z,g} {value[1].z,g} {value[2].z,g} {value[3].z,g}] + + + [{value[0].w,g} {value[1].w,g} {value[2].w,g} {value[3].w,g}] + + + + value[0] + value[1] + value[2] + value[3] + + + + + + + [r: {real}] [d: {dual}] + + real + dual + + + + \ No newline at end of file diff --git a/Vendor/NatVis/VulkanHpp/VulkanHpp.natvis b/Vendor/NatVis/VulkanHpp/VulkanHpp.natvis new file mode 100644 index 0000000..f167984 --- /dev/null +++ b/Vendor/NatVis/VulkanHpp/VulkanHpp.natvis @@ -0,0 +1,10 @@ + + + + [{($T1)m_mask}] + + + {_Elems,s} + _Elems,s + + \ No newline at end of file diff --git a/Vendor/Tools/Tracy0.12.2/tracy-capture.exe b/Vendor/Tools/Tracy0.12.2/tracy-capture.exe new file mode 100644 index 0000000..2243190 Binary files /dev/null and b/Vendor/Tools/Tracy0.12.2/tracy-capture.exe differ diff --git a/Vendor/Tools/Tracy0.12.2/tracy-csvexport.exe b/Vendor/Tools/Tracy0.12.2/tracy-csvexport.exe new file mode 100644 index 0000000..f2b3aff Binary files /dev/null and b/Vendor/Tools/Tracy0.12.2/tracy-csvexport.exe differ diff --git a/Vendor/Tools/Tracy0.12.2/tracy-import-chrome.exe b/Vendor/Tools/Tracy0.12.2/tracy-import-chrome.exe new file mode 100644 index 0000000..afeaf73 Binary files /dev/null and b/Vendor/Tools/Tracy0.12.2/tracy-import-chrome.exe differ diff --git a/Vendor/Tools/Tracy0.12.2/tracy-import-fuchsia.exe b/Vendor/Tools/Tracy0.12.2/tracy-import-fuchsia.exe new file mode 100644 index 0000000..2ebc7c5 Binary files /dev/null and b/Vendor/Tools/Tracy0.12.2/tracy-import-fuchsia.exe differ diff --git a/Vendor/Tools/Tracy0.12.2/tracy-profiler.exe b/Vendor/Tools/Tracy0.12.2/tracy-profiler.exe new file mode 100644 index 0000000..a44284a Binary files /dev/null and b/Vendor/Tools/Tracy0.12.2/tracy-profiler.exe differ diff --git a/Vendor/Tools/Tracy0.12.2/tracy-update.exe b/Vendor/Tools/Tracy0.12.2/tracy-update.exe new file mode 100644 index 0000000..27b536a Binary files /dev/null and b/Vendor/Tools/Tracy0.12.2/tracy-update.exe differ diff --git a/conanfile.py b/conanfile.py new file mode 100644 index 0000000..ffad6ab --- /dev/null +++ b/conanfile.py @@ -0,0 +1,124 @@ +from conan import ConanFile +from conan.tools.cmake import CMakeToolchain, CMake, cmake_layout +from conan.tools.files import copy +import os + +required_conan_version = ">=1.33.0" + +class Bigfoot(ConanFile): + name = "bigfoot" + homepage = "https://git.romainboullard.com/BigfootDev/Bigfoot" + description = "Bigfoot is a 3D game engine written in C++" + topics = ("game engine", "3d") + license = "MIT" + version = "0.1.0" + + # Binary configuration + settings = "os", "compiler", "build_type", "arch" + options = { + "shared": [True, False], + "fPIC": [True, False], + "build_tests": [True, False], + "tracy": [True, False], + "build_tools": [True, False], + "vulkan": [True, False], + "build_benchmarks": [True, False], + } + default_options = { + "shared": False, + "fPIC": True, + "build_tests": False, + "tracy": False, + "build_tools": True, + "vulkan": True, + "build_benchmarks": False, + } + + generators = "CMakeDeps" + + def layout(self): + cmake_layout(self) + + def configure(self): + if self.settings.os == "Windows": + del self.options.fPIC + + self.options['mimalloc'].override = True + self.options['mimalloc'].shared = True + if(self.settings.os == "Windows"): + self.options["mimalloc"].win_redirect = True + + self.options['stduuid'].with_cxx20_span = True + self.options['flatbuffers'].header_only = True + + if(self.options.tracy): + self.options["tracy"].on_demand = True + + if(self.options.vulkan): + self.options["spirv-cross"].exceptions = False + + if(self.options.build_benchmarks): + self.options["benchmark"].enable_exceptions = False + self.options["benchmark"].enable_lto = True + + def requirements(self): + self.requires("eastl/3.27.01@bigfootdev/main", transitive_headers=True) + self.requires("unordered_dense/4.8.1@bigfootdev/main", transitive_headers=True) + self.requires("mimalloc/3.1.5@bigfootdev/main", transitive_headers=True) + self.requires("stduuid/1.2.3@bigfootdev/main", transitive_headers=True) + self.requires("sqlite3/3.51.0@bigfootdev/main", transitive_headers=True) + self.requires("cli11/2.6.0") + self.requires("rapidhash/3.0@bigfootdev/main", transitive_headers=True) + self.requires("effolkronium-random/1.5.0", transitive_headers=True) + self.requires("flatbuffers/25.12.19@bigfootdev/main", transitive_headers=True) + + if(self.settings.build_type == "RelWithDebInfo" or self.settings.build_type == "Debug"): + self.requires("quill/11.0.2", transitive_headers=True) + self.requires("cpptrace/1.0.4", transitive_headers=True) + + if(self.options.tracy): + self.requires("tracy/0.12.2", transitive_headers=True) + + self.requires("glm/1.0.1", transitive_headers=True) + self.requires("lodepng/cci.20250727@bigfootdev/main", transitive_headers=True) + self.requires("imgui/1.92.5-docking", transitive_headers=True) + + if(self.options.vulkan): + self.requires("vulkan-headers/1.4.313.0") + if(self.settings.build_type == "RelWithDebInfo" or self.settings.build_type == "Debug"): + self.requires("vulkan-validationlayers/1.4.313.0@bigfootdev/main") + self.requires("vulkan-memory-allocator/3.3.0@bigfootdev/main") + + if(self.options.build_tests or self.options.build_benchmarks): + self.requires("glfw/3.4") + + if(self.options.build_tests): + self.test_requires("gtest/1.17.0") + self.test_requires("pixelmatch-cpp17/1.0.3@bigfootdev/main") + + if(self.options.build_tools): + self.requires("spirv-cross/1.4.313.0") + self.requires("shaderc/2025.3@bigfootdev/main") + self.requires("stb/cci.20240531", override=True) + self.requires("assimp/6.0.2") + self.requires("meshoptimizer/1.0@bigfootdev/main") + self.requires("libsquish/1.15") + + if(self.options.build_benchmarks): + self.requires("benchmark/1.9.4") + + def generate(self): + tc = CMakeToolchain(self) + + tc.variables["BUILD_TESTS"] = self.options.build_tests + tc.variables["TRACY"] = self.options.tracy + tc.variables["BUILD_TOOLS"] = self.options.build_tools + tc.variables["VULKAN"] = self.options.vulkan + tc.variables["BUILD_BENCHMARKS"] = self.options.build_benchmarks + + tc.generate() + + def build(self): + cmake = CMake(self) + cmake.configure() + cmake.build() \ No newline at end of file diff --git a/format.bat b/format.bat new file mode 100644 index 0000000..54d904f --- /dev/null +++ b/format.bat @@ -0,0 +1,71 @@ +@echo off +SETLOCAL ENABLEDELAYEDEXPANSION + +REM ========================= +REM Variables +REM ========================= +SET FMT=clang-format +SET MODE= +SET EXIT_CODE=0 + +REM ========================= +REM Parse arguments +REM ========================= +:parse_args +IF "%~1"=="" GOTO end_parse_args +IF "%~1"=="--check" ( + SET MODE=check +) ELSE IF "%~1"=="--fix" ( + SET MODE=fix +) ELSE ( + REM Accumulate directories + SET DIRS=!DIRS! "%~1" +) +SHIFT +GOTO parse_args +:end_parse_args + +IF "%MODE%"=="" ( + ECHO Usage: %~nx0 --check|--fix [ ...] + EXIT /B 1 +) + +IF "%DIRS%"=="" ( + ECHO Please provide at least one directory. + EXIT /B 1 +) + +REM ========================= +REM Iterate over directories +REM ========================= +FOR %%D IN (%DIRS%) DO ( + IF NOT EXIST "%%~D" ( + ECHO %%~D is not a valid directory. + SET EXIT_CODE=1 + GOTO :continue_dirs + ) + + REM Recursively find source files + FOR /R "%%~D" %%F IN (*.h *.hpp *.c *.cpp *.m *.mm) DO ( + SET FILE=%%F + REM Skip *_generated* files + ECHO !FILE! | FINDSTR /I "_generated" >nul + IF ERRORLEVEL 1 ( + IF "%MODE%"=="fix" ( + ECHO Formatting !FILE! + %FMT% -i "!FILE!" + ) ELSE ( + ECHO Checking !FILE! + %FMT% --dry-run --Werror "!FILE!" 2>nul + IF ERRORLEVEL 1 ( + REM clang-format will already print diagnostics + SET EXIT_CODE=1 + ) + ) + ) + ) + + :continue_dirs +) + +EXIT /B %EXIT_CODE% diff --git a/format.sh b/format.sh new file mode 100644 index 0000000..eb8f665 --- /dev/null +++ b/format.sh @@ -0,0 +1,68 @@ +#!/bin/bash +set -euo pipefail + +FMT="clang-format" +MODE="" +DIRS=() +EXIT_CODE=0 + +# ========================= +# Parse arguments +# ========================= +for arg in "$@"; do + case "$arg" in + --check) + MODE="check" + ;; + --fix) + MODE="fix" + ;; + *) + DIRS+=("$arg") + ;; + esac +done + +# Ensure mode is set +if [[ -z "$MODE" ]]; then + echo "Usage: $0 --check|--fix [ ...]" + exit 1 +fi + +# Ensure at least one directory +if [[ ${#DIRS[@]} -eq 0 ]]; then + echo "Please provide at least one directory." + exit 1 +fi + +# ========================= +# Process directories +# ========================= +for DIR in "${DIRS[@]}"; do + if [[ ! -d "$DIR" ]]; then + echo "$DIR is not a valid directory." + EXIT_CODE=1 + continue + fi + + # Find all source files safely (null-separated) + while IFS= read -r -d '' FILE; do + [[ "$FILE" == *_generated* ]] && continue + + if [[ "$MODE" == "fix" ]]; then + echo "Formatting $FILE" + "$FMT" -i "$FILE" + else + echo "Checking $FILE" + # Check mode: clang-format diagnostic only + if ! "$FMT" --dry-run --Werror "$FILE"; then + # clang-format prints: file:line:col: error ... + EXIT_CODE=1 + fi + fi + done < <( + find "$DIR" \( -name '*.h' -o -name '*.hpp' -o -name '*.c' -o -name '*.cpp' -o -name '*.m' -o -name '*.mm' \) -print0 + ) +done + +exit $EXIT_CODE diff --git a/generate_bigfoot.bat b/generate_bigfoot.bat new file mode 100644 index 0000000..0f4298f --- /dev/null +++ b/generate_bigfoot.bat @@ -0,0 +1 @@ +cmake -S . -B build --toolchain build/generators/conan_toolchain.cmake --graphviz=graphviz/graph.dot \ No newline at end of file diff --git a/generate_bigfoot.sh b/generate_bigfoot.sh new file mode 100644 index 0000000..1b72527 --- /dev/null +++ b/generate_bigfoot.sh @@ -0,0 +1,3 @@ +cmake -S . -B build/Debug --toolchain build/build/Debug/generators/conan_toolchain.cmake -DCMAKE_BUILD_TYPE="Debug" -G "Ninja" --graphviz=graphviz/Debug/graph.dot +cmake -S . -B build/Release --toolchain build/build/Release/generators/conan_toolchain.cmake -DCMAKE_BUILD_TYPE="Release" -G "Ninja" --graphviz=graphviz/Release/graph.dot +cmake -S . -B build/RelWithDebInfo --toolchain build/build/RelWithDebInfo/generators/conan_toolchain.cmake -DCMAKE_BUILD_TYPE="RelWithDebInfo" -G "Ninja" --graphviz=graphviz/RelWithDebInfo/graph.dot \ No newline at end of file diff --git a/generate_dependencies.bat b/generate_dependencies.bat new file mode 100644 index 0000000..f7de8c6 --- /dev/null +++ b/generate_dependencies.bat @@ -0,0 +1,33 @@ +@echo off +setlocal + +REM Check if the correct number of arguments is provided +if "%~1"=="" ( + echo Usage: %0 "[force|missing]" + exit /b 1 +) + +REM Set the build option based on the argument +set build_option= +if "%~1"=="force" ( + set build_option=--build="*" +) else if "%~1"=="missing" ( + set build_option=--build=missing +) else ( + echo Invalid argument: %~1 + echo Usage: %0 "[force|missing]" + exit /b 1 +) + +REM Add the remote +conan remote add bigfootpackages https://conan.romainboullard.com/artifactory/api/conan/BigfootPackages + +REM Install the conan configuration +conan config install https://git.romainboullard.com/BigfootDev/ConanProfiles.git + +REM Install dependencies with the specified build option +conan install . --deployer=full_deploy --remote=bigfootpackages -pr:h=msvc -pr:b=msvc %build_option% -of build -s build_type=Release -o bigfoot/*:build_tests=True -o bigfoot/*:tracy=True -o bigfoot/*:build_tools=True -o bigfoot/*:vulkan=True -o bigfoot/*:build_benchmarks=True +conan install . --deployer=full_deploy --remote=bigfootpackages -pr:h=msvcd -pr:b=msvcd %build_option% -of build -s build_type=RelWithDebInfo -o bigfoot/*:build_tests=True -o bigfoot/*:tracy=True -o bigfoot/*:build_tools=True -o bigfoot/*:vulkan=True -o bigfoot/*:build_benchmarks=True +conan install . --deployer=full_deploy --remote=bigfootpackages -pr:h=msvcd -pr:b=msvcd %build_option% -of build -s build_type=Debug -o bigfoot/*:build_tests=True -o bigfoot/*:tracy=True -o bigfoot/*:build_tools=True -o bigfoot/*:vulkan=True -o bigfoot/*:build_benchmarks=True + +endlocal diff --git a/generate_dependencies.sh b/generate_dependencies.sh new file mode 100644 index 0000000..6d90476 --- /dev/null +++ b/generate_dependencies.sh @@ -0,0 +1,28 @@ +#!/bin/bash + +# Check if the correct number of arguments is provided +if [ -z "$1" ]; then + echo "Usage: $0 [force|missing]" + exit 1 +fi + +# Add the remote +conan remote add bigfootpackages https://conan.romainboullard.com/artifactory/api/conan/BigfootPackages + +# Install the conan configuration +conan config install https://git.romainboullard.com/BigfootDev/ConanProfiles.git + +# Set the build option based on the argument +if [ "$1" == "force" ]; then + conan install . --deployer=full_deploy --remote=bigfootpackages -pr:h=clang -pr:b=clang --build='*' -of build -s build_type=Release -o bigfoot/*:build_tests=True -o bigfoot/*:tracy=True -o bigfoot/*:build_tools=True -o bigfoot/*:vulkan=True -o bigfoot/*:build_benchmarks=True + conan install . --deployer=full_deploy --remote=bigfootpackages -pr:h=clangd -pr:b=clangd --build='*' -of build -s build_type=RelWithDebInfo -o bigfoot/*:build_tests=True -o bigfoot/*:tracy=True -o bigfoot/*:build_tools=True -o bigfoot/*:vulkan=True -o bigfoot/*:build_benchmarks=True + conan install . --deployer=full_deploy --remote=bigfootpackages -pr:h=clangd -pr:b=clangd --build='*' -of build -s build_type=Debug -o bigfoot/*:build_tests=True -o bigfoot/*:tracy=True -o bigfoot/*:build_tools=True -o bigfoot/*:vulkan=True -o bigfoot/*:build_benchmarks=True +elif [ "$1" == "missing" ]; then + conan install . --deployer=full_deploy --remote=bigfootpackages -pr:h=clang -pr:b=clang --build=missing -of build -s build_type=Release -o bigfoot/*:build_tests=True -o bigfoot/*:tracy=True -o bigfoot/*:build_tools=True -o bigfoot/*:vulkan=True -o bigfoot/*:build_benchmarks=True + conan install . --deployer=full_deploy --remote=bigfootpackages -pr:h=clangd -pr:b=clangd --build=missing -of build -s build_type=RelWithDebInfo -o bigfoot/*:build_tests=True -o bigfoot/*:tracy=True -o bigfoot/*:build_tools=True -o bigfoot/*:vulkan=True -o bigfoot/*:build_benchmarks=True + conan install . --deployer=full_deploy --remote=bigfootpackages -pr:h=clangd -pr:b=clangd --build=missing -of build -s build_type=Debug -o bigfoot/*:build_tests=True -o bigfoot/*:tracy=True -o bigfoot/*:build_tools=True -o bigfoot/*:vulkan=True -o bigfoot/*:build_benchmarks=True +else + echo "Invalid argument: $1" + echo "Usage: $0 [force|missing]" + exit 1 +fi diff --git a/sonar-project.properties b/sonar-project.properties new file mode 100644 index 0000000..6ff664b --- /dev/null +++ b/sonar-project.properties @@ -0,0 +1,14 @@ +sonar.projectKey=Bigfoot + +sonar.projectVersion=0.1.0 + +sonar.sourceEncoding=UTF-8 + +sonar.sources=Bigfoot/Sources +sonar.tests=Bigfoot/Tests + +sonar.cxx.file.suffixes=.hpp,.cpp,.h +sonar.cxx.clangtidy.reportPaths=tidy_result.txt +sonar.cxx.infer.reportPaths=infer-out/report.json + +sonar.cxx.jsonCompilationDatabase.analyzeOnlyContainedFiles=True