diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index b15244d6..41f434cf 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -1,69 +1,69 @@ -name: Build and Test - -on: - push: - branches: [ main, bazel-setup ] - paths-ignore: - - 'projs/docs/**' - - 'specs/**' - -jobs: - build: - runs-on: windows-latest - steps: - - name: Checkout - uses: actions/checkout@v2 - with: - submodules: recursive - - - - name: Install bazelisk - run: | - choco install bazelisk - - - name: Add msbuild to PATH - uses: microsoft/setup-msbuild@v1.1 - - - name: Build - run: | - bazel build //... - - - name: use cache - uses: actions/cache@v2 - with: - path: "./bazel-bin/projs" - key: ${{ runner.os }}-${{ github.run_id }} - - - name: Upload shadow-engine artifact - uses: actions/upload-artifact@v3 - with: - name: ${{ needs.update.outputs.old_version_name }}-${{ needs.update.outputs.new_version_name }}-patch - path: './bazel-bin/projs/shadow-engine/**/*' - - test-sff: - runs-on: windows-latest - needs: build - permissions: - contents: read - issues: read - checks: write - pull-requests: write - steps: - - name: use cache - uses: actions/cache@v2 - with: - path: "./bazel-bin/projs" - key: ${{ runner.os }}-${{ github.run_id }} - - - name: Make output folder - run: mkdir ./test-results - - - name: Test shadow-file-format - run: ./bazel-bin/projs/shadow-file-format/test.exe -r junit -o ./test-results/shadow-file-format-test.xml - - - name: Publish Test Results - uses: EnricoMi/publish-unit-test-result-action/composite@v1 - if: always() - with: - files: "test-results/**/*.xml" - +name: Build and Test + +on: + push: + branches: [ main, bazel-setup ] + paths-ignore: + - 'projs/docs/**' + - 'specs/**' + +jobs: + build: + runs-on: windows-latest + steps: + - name: Checkout + uses: actions/checkout@v2 + with: + submodules: recursive + + + - name: Install bazelisk + run: | + choco install bazelisk + + - name: Add msbuild to PATH + uses: microsoft/setup-msbuild@v1.1 + + - name: Build + run: | + bazel build //... + + - name: use cache + uses: actions/cache@v2 + with: + path: "./bazel-bin/projs" + key: ${{ runner.os }}-${{ github.run_id }} + + - name: Upload shadow-engine artifact + uses: actions/upload-artifact@v3 + with: + name: ${{ needs.update.outputs.old_version_name }}-${{ needs.update.outputs.new_version_name }}-patch + path: './bazel-bin/projs/shadow-engine/**/*' + + test-sff: + runs-on: windows-latest + needs: build + permissions: + contents: read + issues: read + checks: write + pull-requests: write + steps: + - name: use cache + uses: actions/cache@v2 + with: + path: "./bazel-bin/projs" + key: ${{ runner.os }}-${{ github.run_id }} + + - name: Make output folder + run: mkdir ./test-results + + - name: Test shadow-file-format + run: ./bazel-bin/projs/shadow-file-format/test.exe -r junit -o ./test-results/shadow-file-format-test.xml + + - name: Publish Test Results + uses: EnricoMi/publish-unit-test-result-action/composite@v1 + if: always() + with: + files: "test-results/**/*.xml" + diff --git a/.gitignore b/.gitignore index 5c3c8719..16c3fc7d 100644 --- a/.gitignore +++ b/.gitignore @@ -1,16 +1,14 @@ -bin/ -obj/ -/packages/ -riderModule.iml -/_ReSharper.Caches/ - - -test-results -cmake-build-vs-debug/ -cmake-build-debug/ -cmake-build-debug-msvc/ -cmake-build-debug-msvc-vs/ -out/ -.vs/ -/.idea/ -/cmake-build-debug-mingw/ +bin/ +obj/ +/packages/ +riderModule.iml +/_ReSharper.Caches/ + + +test-results +cmake-build-vs-debug/ +cmake-build-debug/ +cmake-build-debug-msvc/ +cmake-build-debug-msvc-vs/ +out/ +.vs/ \ No newline at end of file diff --git a/.gitmodules b/.gitmodules index e69de29b..3fc45167 100644 --- a/.gitmodules +++ b/.gitmodules @@ -0,0 +1,21 @@ +[submodule "projs/shadow/extern/spdlog"] + path = projs/shadow/extern/spdlog + url = https://github.com/gabime/spdlog.git +[submodule "projs/shadow/extern/imgui"] + path = projs/shadow/extern/imgui + url = https://github.com/ocornut/imgui +[submodule "projs/shadow/extern/dxmath"] + path = projs/shadow/extern/dxmath + url = https://github.com/microsoft/DirectXMath.git +[submodule "projs/shadow/extern/catch2"] + path = projs/shadow/extern/catch2 + url = https://github.com/catchorg/Catch2.git +[submodule "projs/shadow/extern/glm"] + path = projs/shadow/extern/glm + url = https://github.com/g-truc/glm.git +[submodule "projs/shadow/extern/dylib"] + path = projs/shadow/extern/dylib + url = https://github.com/martin-olivier/dylib +[submodule "projs/shadow/extern/vulkan_memory_allocator"] + path = projs/shadow/extern/vulkan_memory_allocator + url = https://github.com/GPUOpen-LibrariesAndSDKs/VulkanMemoryAllocator.git \ No newline at end of file diff --git a/.idea/.gitignore b/.idea/.gitignore new file mode 100644 index 00000000..1c2fda56 --- /dev/null +++ b/.idea/.gitignore @@ -0,0 +1,8 @@ +# Default ignored files +/shelf/ +/workspace.xml +# Editor-based HTTP Client requests +/httpRequests/ +# Datasource local storage ignored files +/dataSources/ +/dataSources.local.xml diff --git a/.idea/cmake.xml b/.idea/cmake.xml new file mode 100644 index 00000000..06c4f7ee --- /dev/null +++ b/.idea/cmake.xml @@ -0,0 +1,10 @@ + + + + + + + + + + \ No newline at end of file diff --git a/.idea/codeStyles/Project.xml b/.idea/codeStyles/Project.xml new file mode 100644 index 00000000..345d3c23 --- /dev/null +++ b/.idea/codeStyles/Project.xml @@ -0,0 +1,73 @@ + + + + + + + + + + + + \ No newline at end of file diff --git a/.idea/codeStyles/codeStyleConfig.xml b/.idea/codeStyles/codeStyleConfig.xml new file mode 100644 index 00000000..307554b7 --- /dev/null +++ b/.idea/codeStyles/codeStyleConfig.xml @@ -0,0 +1,5 @@ + + + + \ No newline at end of file diff --git a/.idea/customTargets.xml b/.idea/customTargets.xml new file mode 100644 index 00000000..93656d6a --- /dev/null +++ b/.idea/customTargets.xml @@ -0,0 +1,8 @@ + + + + + + + + \ No newline at end of file diff --git a/.idea/encodings.xml b/.idea/encodings.xml new file mode 100644 index 00000000..08cfc443 --- /dev/null +++ b/.idea/encodings.xml @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/.idea/fileTemplates/Shadow Entitiy Header.h b/.idea/fileTemplates/Shadow Entitiy Header.h new file mode 100644 index 00000000..3273bb65 --- /dev/null +++ b/.idea/fileTemplates/Shadow Entitiy Header.h @@ -0,0 +1,13 @@ +#pragma once + +#include "Entity.h" +#include "TransformEntity.h" + +class ${NAME} : public ShadowEngine::Entities::TransformEntity{ + SHObject_Base(${NAME}); + + Entity_Base(${NAME}, TransformEntity); + +public: + void Build() override; +}; diff --git a/.idea/fileTemplates/Shadow Entitiy.cpp b/.idea/fileTemplates/Shadow Entitiy.cpp new file mode 100644 index 00000000..a927cdc6 --- /dev/null +++ b/.idea/fileTemplates/Shadow Entitiy.cpp @@ -0,0 +1 @@ +void ${NAME}::Build() \ No newline at end of file diff --git a/.idea/fileTemplates/internal/C++ Class Header.h b/.idea/fileTemplates/internal/C++ Class Header.h new file mode 100644 index 00000000..c84aecdc --- /dev/null +++ b/.idea/fileTemplates/internal/C++ Class Header.h @@ -0,0 +1,10 @@ +#pragma once + +${NAMESPACES_OPEN} + +class ${NAME} { + +}; + +${NAMESPACES_CLOSE} + diff --git a/.idea/fileTemplates/internal/C++ Class.cc b/.idea/fileTemplates/internal/C++ Class.cc new file mode 100644 index 00000000..f40c5f55 --- /dev/null +++ b/.idea/fileTemplates/internal/C++ Class.cc @@ -0,0 +1,4 @@ +#[[#include]]# "${HEADER_FILENAME}" + +${NAMESPACES_OPEN_CPP} +${NAMESPACES_CLOSE_CPP} \ No newline at end of file diff --git a/.idea/inspectionProfiles/Project_Default.xml b/.idea/inspectionProfiles/Project_Default.xml new file mode 100644 index 00000000..a98f236b --- /dev/null +++ b/.idea/inspectionProfiles/Project_Default.xml @@ -0,0 +1,9 @@ + + + + \ No newline at end of file diff --git a/.idea/misc.xml b/.idea/misc.xml new file mode 100644 index 00000000..bf4aebe5 --- /dev/null +++ b/.idea/misc.xml @@ -0,0 +1,15 @@ + + + + + + + + + + + + + + \ No newline at end of file diff --git a/.idea/modules.xml b/.idea/modules.xml new file mode 100644 index 00000000..7e527079 --- /dev/null +++ b/.idea/modules.xml @@ -0,0 +1,8 @@ + + + + + + + + \ No newline at end of file diff --git a/.idea/runConfigurations/test_game.xml b/.idea/runConfigurations/test_game.xml new file mode 100644 index 00000000..7c9a8be7 --- /dev/null +++ b/.idea/runConfigurations/test_game.xml @@ -0,0 +1,7 @@ + + + + + + \ No newline at end of file diff --git a/.idea/runConfigurations/test_game_EDITOR.xml b/.idea/runConfigurations/test_game_EDITOR.xml new file mode 100644 index 00000000..a2a3fc81 --- /dev/null +++ b/.idea/runConfigurations/test_game_EDITOR.xml @@ -0,0 +1,9 @@ + + + + + + \ No newline at end of file diff --git a/.idea/scopes/shadow.xml b/.idea/scopes/shadow.xml new file mode 100644 index 00000000..8e551766 --- /dev/null +++ b/.idea/scopes/shadow.xml @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/.idea/statistic.xml b/.idea/statistic.xml new file mode 100644 index 00000000..06d20e2e --- /dev/null +++ b/.idea/statistic.xml @@ -0,0 +1,10 @@ + + + + + + \ No newline at end of file diff --git a/.idea/umbra.iml b/.idea/umbra.iml new file mode 100644 index 00000000..6d70257c --- /dev/null +++ b/.idea/umbra.iml @@ -0,0 +1,2 @@ + + \ No newline at end of file diff --git a/.idea/vcs.xml b/.idea/vcs.xml new file mode 100644 index 00000000..6b0b8b1b --- /dev/null +++ b/.idea/vcs.xml @@ -0,0 +1,13 @@ + + + + + + + + + + + + + \ No newline at end of file diff --git a/CMakeLists.txt b/CMakeLists.txt index 91bc0425..bd47a83e 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,84 +1,24 @@ -cmake_minimum_required(VERSION 3.24) - -Include(FetchContent) - -# Fetch SDL for the runtime -FetchContent_Declare( - SDL2 - URL https://www.libsdl.org/release/SDL2-devel-2.24.0-VC.zip -) -FetchContent_MakeAvailable(SDL2) -set(SDL2_DIR ${sdl2_SOURCE_DIR}) -list(PREPEND CMAKE_PREFIX_PATH "${sdl2_SOURCE_DIR}/cmake") - -# Fetch Catch2 for the file format tests -FetchContent_Declare( - Catch2 - GIT_REPOSITORY https://github.com/catchorg/Catch2.git - GIT_TAG v2.13.9 # or a later release -) -FetchContent_MakeAvailable(Catch2) -list(APPEND CMAKE_MODULE_PATH ${catch2_SOURCE_DIR}/extras) - -list(APPEND CMAKE_MODULE_PATH "${Catch2_SOURCE_DIR}/contrib") - -# Fetch GLM for the renderer -FetchContent_Declare( - glm - GIT_REPOSITORY https://github.com/g-truc/glm.git - GIT_TAG 0.9.9.2 -) - -FetchContent_GetProperties(glm) -if(NOT glm_POPULATED) - FetchContent_Populate(glm) - set(GLM_TEST_ENABLE OFF CACHE BOOL "" FORCE) - add_subdirectory(${glm_SOURCE_DIR} ${glm_BINARY_DIR}) -endif() - -# Fetch SpdLog for.. loggin -FetchContent_Declare( - spdlog - GIT_REPOSITORY https://github.com/gabime/spdlog.git - GIT_TAG v1.10.0 -) - -FetchContent_GetProperties(spdlog) -if(NOT spdlog_POPULATED) - FetchContent_Populate(spdlog) - add_subdirectory(${spdlog_SOURCE_DIR} ${spdlog_BINARY_DIR}) -endif() - -FetchContent_Declare( - imgui - GIT_REPOSITORY https://github.com/ocornut/imgui - GIT_TAG 71a0701920dbc83155f718182f01132d1ec2d51e -) - -FetchContent_MakeAvailable(imgui) - -FetchContent_Declare( - dylib - GIT_REPOSITORY "https://github.com/martin-olivier/dylib" - GIT_TAG "v2.1.0" -) - -FetchContent_MakeAvailable(dylib) - -# Import some find files -list(APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_LIST_DIR}/cmake") - -project(umbra) - -set(CMAKE_STATIC_LIBRARY_PREFIX "") -set(CMAKE_SHARED_LIBRARY_PREFIX "") - -# Core engine -add_subdirectory(projs/shadow/shadow-engine) - -# Runtime executable -add_subdirectory(projs/shadow/shadow-runtime) - -add_subdirectory(projs/shadow/shadow-editor) - +cmake_minimum_required(VERSION 3.25) + +set_property(GLOBAL PROPERTY GLOBAL_DEPENDS_DEBUG_MODE 1) + +#if (MSVC) +# add_compile_options(-Zc:externC /permissive- /Zc:__cplusplus /Zc:inline /Zc:preprocessor /Zc:lambda /Zc:templateScope) +#endif () +if (MINGW OR LINUX) + #add_compile_options(-fpermissive) +endif () + +# Import some find files +list(APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_LIST_DIR}/cmake") + +project(umbra) + +include(shadow-modules.cmake) + +set(CMAKE_STATIC_LIBRARY_PREFIX "") +set(CMAKE_SHARED_LIBRARY_PREFIX "") + +add_subdirectory(projs/shadow) + add_subdirectory(projs/test-game) \ No newline at end of file diff --git a/README.md b/README.md index 047291c1..02021624 100644 --- a/README.md +++ b/README.md @@ -1 +1 @@ -# umbra +# umbra diff --git a/cmake/FindD3D12.cmake b/cmake/FindD3D12.cmake new file mode 100644 index 00000000..1926bb2d --- /dev/null +++ b/cmake/FindD3D12.cmake @@ -0,0 +1,14 @@ + +SET(D3D12_BIN_DIR ${dx12agility_SOURCE_DIR}/build/native/bin/x64) + +SET(D3D12_INCLUDE_DIRS ${dx12agility_SOURCE_DIR}/build/native/include) +SET(D3D12_BINARY_DIRS ${D3D12_BIN_DIR}) + + +function(add_dx12 target) + add_custom_command(TARGET ${target} POST_BUILD + COMMAND ${CMAKE_COMMAND} -E copy ${D3D12_BINARY_DIRS}/D3D12Core.dll ${CMAKE_CURRENT_BINARY_DIR}/D3D12/D3D12Core.dll + COMMAND_EXPAND_LISTS + ) + target_link_libraries(${target} PRIVATE d3d12.dll) +endfunction() \ No newline at end of file diff --git a/cmake/FindDirectXMath.cmake b/cmake/FindDirectXMath.cmake new file mode 100644 index 00000000..4ed0447d --- /dev/null +++ b/cmake/FindDirectXMath.cmake @@ -0,0 +1,4 @@ +set(CMAKE_CXX_STANDARD 20) + +FILE(GLOB_RECURSE DirectXMath_HEADERS ${DirectXMath_SOURCE_DIR}/Inc/*.h) +SET(DirectXMath_INCLUDE_DIRS ${DirectXMath_SOURCE_DIR}/Inc) \ No newline at end of file diff --git a/cmake/FindImGui.cmake b/cmake/FindImGui.cmake index 4a031a39..5a1b308b 100644 --- a/cmake/FindImGui.cmake +++ b/cmake/FindImGui.cmake @@ -1,27 +1,34 @@ -set(CMAKE_CXX_STANDARD 20) -find_package(SDL2 REQUIRED) -find_package(Vulkan REQUIRED) - -FILE(GLOB_RECURSE SOURCES ${imgui_SOURCE_DIR}/*.cpp) -FILE(GLOB_RECURSE HEADERS ${imgui_SOURCE_DIR}/*.h) - -FILE(GLOB_RECURSE HEADERS ${imgui_SOURCE_DIR}/backends/imgui_impl_vulkan.h) -FILE(GLOB_RECURSE SOURCES ${imgui_SOURCE_DIR}/backends/imgui_impl_vulkan.cpp) - -add_library(imgui OBJECT - ${imgui_SOURCE_DIR}/imgui.cpp - ${imgui_SOURCE_DIR}/imgui_demo.cpp - ${imgui_SOURCE_DIR}/imgui_draw.cpp - ${imgui_SOURCE_DIR}/imgui_tables.cpp - ${imgui_SOURCE_DIR}/imgui_widgets.cpp - ${imgui_SOURCE_DIR}/backends/imgui_impl_sdl.cpp - ${imgui_SOURCE_DIR}/backends/imgui_impl_vulkan.cpp - ) - -target_include_directories(imgui - PUBLIC - ${SDL2_INCLUDE_DIRS} - ${imgui_SOURCE_DIR} - ${imgui_SOURCE_DIR}/backends - ) -target_link_libraries(imgui PRIVATE SDL2::SDL2 Vulkan::Vulkan) \ No newline at end of file +set(CMAKE_CXX_STANDARD 20) +find_package(SDL2 REQUIRED) +find_package(Vulkan REQUIRED) + +SET(imgui_SOURCE_DIR ${CMAKE_SOURCE_DIR}/projs/shadow/extern/imgui) + +FILE(GLOB_RECURSE SOURCES ${imgui_SOURCE_DIR}/*.cpp) +FILE(GLOB_RECURSE HEADERS ${imgui_SOURCE_DIR}/*.h) + +FILE(GLOB_RECURSE HEADERS ${imgui_SOURCE_DIR}/backends/imgui_impl_vulkan.h) +FILE(GLOB_RECURSE SOURCES ${imgui_SOURCE_DIR}/backends/imgui_impl_vulkan.cpp) + +add_library(ImGui STATIC + ${imgui_SOURCE_DIR}/imgui.cpp + ${imgui_SOURCE_DIR}/imgui_demo.cpp + ${imgui_SOURCE_DIR}/imgui_draw.cpp + ${imgui_SOURCE_DIR}/imgui_tables.cpp + ${imgui_SOURCE_DIR}/imgui_widgets.cpp + # ${imgui_SOURCE_DIR}/backends/imgui_impl_sdl2.cpp + # ${imgui_SOURCE_DIR}/backends/imgui_impl_vulkan.cpp +) + +target_include_directories(ImGui + PRIVATE + ${SDL2_INCLUDE_DIRS} + PUBLIC + ${imgui_SOURCE_DIR} + ${imgui_SOURCE_DIR}/backends +) +target_link_libraries(ImGui + # PRIVATE SDL2::SDL2 Vulkan::Vulkan +) + +target_compile_options(ImGui PRIVATE -fPIC) \ No newline at end of file diff --git a/imgui.ini b/imgui.ini deleted file mode 100644 index 7162e922..00000000 --- a/imgui.ini +++ /dev/null @@ -1,41 +0,0 @@ -[Window][Debug##Default] -Pos=876,8 -Size=315,195 -Collapsed=0 -DockId=0x00000008,0 - -[Window][Dear ImGui Demo] -Pos=1193,178 -Size=62,25 -Collapsed=0 -DockId=0x00000007,0 - -[Window][Game module window] -Pos=1193,8 -Size=62,50 -Collapsed=0 -DockId=0x00000004,0 - -[Window][Time] -Pos=1193,60 -Size=62,49 -Collapsed=0 -DockId=0x00000005,0 - -[Window][Active Modules] -Pos=1193,111 -Size=62,65 -Collapsed=0 -DockId=0x00000006,0 - -[Docking][Data] -DockNode ID=0x00000001 Pos=1196,188 Size=379,195 Split=X - DockNode ID=0x00000008 Parent=0x00000001 SizeRef=652,419 HiddenTabBar=1 Selected=0x55954704 - DockNode ID=0x00000009 Parent=0x00000001 SizeRef=129,419 Split=Y - DockNode ID=0x00000002 Parent=0x00000009 SizeRef=219,34 Split=Y Selected=0xFC1D20C0 - DockNode ID=0x00000004 Parent=0x00000002 SizeRef=219,64 Selected=0xFC1D20C0 - DockNode ID=0x00000005 Parent=0x00000002 SizeRef=219,62 Selected=0xE75A179E - DockNode ID=0x00000003 Parent=0x00000009 SizeRef=219,31 Split=Y Selected=0xEE305C78 - DockNode ID=0x00000006 Parent=0x00000003 SizeRef=219,142 Selected=0xEE305C78 - DockNode ID=0x00000007 Parent=0x00000003 SizeRef=219,55 Selected=0xE87781F4 - diff --git a/projs/docs/diagrams/architecture.plantuml b/projs/docs/diagrams/architecture.plantuml index d0f86e70..b704af71 100644 --- a/projs/docs/diagrams/architecture.plantuml +++ b/projs/docs/diagrams/architecture.plantuml @@ -1,26 +1,26 @@ -@startuml - -class ShadowApplication <> { - -ModuleManager module_manager - ~void packagePrivateMethod() - #{abstract} char protectedMethod(int param) -} - -class ModuleManager <> { - -vector moduels - --- - +void AddModule(Module* mo) -} - -abstract class Module { - +string domain - --- - +void Init() - +void Update() - +void ShutDown() -} - - - - +@startuml + +class ShadowApplication <> { + -ModuleManager module_manager + ~void packagePrivateMethod() + #{abstract} char protectedMethod(int param) +} + +class ModuleManager <> { + -vector moduels + --- + +void AddModule(Module* mo) +} + +abstract class Module { + +string domain + --- + +void Init() + +void Update() + +void ShutDown() +} + + + + @enduml \ No newline at end of file diff --git a/projs/docs/diagrams/project-layout.plantuml b/projs/docs/diagrams/project-layout.plantuml index 1326df56..7dca967d 100644 --- a/projs/docs/diagrams/project-layout.plantuml +++ b/projs/docs/diagrams/project-layout.plantuml @@ -1,31 +1,31 @@ -@startuml -[shadow-light] <> as editor - - [shadow-entity] <> as shentity - [shadow-file-format] <> as shff - [shadow-reflection] <> as shreflection - [shadow-renderer] <> as shrenderer - [shadow-utilty] <> as shutitily - - [shadow-engine] <> as shengine - - shentity --* shengine - shff --* shengine - shreflection --* shengine - shrenderer --* shengine - shutitily --* shengine - - -[shadow-runner] <> as runner - -[test-game] <> as game - -shengine <- editor -runner -> shengine - -game ..> shengine : uses - -runner --> game : loads -editor --> game : loads - +@startuml +[shadow-light] <> as editor + + [shadow-entity] <> as shentity + [shadow-file-format] <> as shff + [shadow-reflection] <> as shreflection + [shadow-renderer] <> as shrenderer + [shadow-utilty] <> as shutitily + + [shadow-engine] <> as shengine + + shentity --* shengine + shff --* shengine + shreflection --* shengine + shrenderer --* shengine + shutitily --* shengine + + +[shadow-runner] <> as runner + +[test-game] <> as game + +shengine <- editor +runner -> shengine + +game ..> shengine : uses + +runner --> game : loads +editor --> game : loads + @enduml \ No newline at end of file diff --git a/projs/docs/diagrams/startup.puml b/projs/docs/diagrams/startup.puml index 9997fb38..045a0b51 100644 --- a/projs/docs/diagrams/startup.puml +++ b/projs/docs/diagrams/startup.puml @@ -1,54 +1,54 @@ -@startuml -!include - -autoactivate on -autonumber - -participant main as "int main(args)" - -participant app as "ShadowApplication" <<(O,#ADD1B2) singleton>> - -participant moduleMg as "ModuleManager" <<(O,#ADD1B2) singleton>> - - -'participant gameDll as "longName" : <$ma_file{scale=0.5}> <> - -participant "Game DLL" as dll <<$ma_file{scale=0.5}>> #LightGray <> - --> main -main -> app ** : create -activate app -app -> moduleMg ** : create -return app - -main -> app : LoadGame - -app -> app : load -app -> dll ** : create -return - -app -> dll : sh_main - -loop for each needed module - dll -> moduleMg : AddModule() - return -end - -return - -return - -main -> app : Init() -app -> moduleMg : Init() - -loop module in modules - collections module as "Module" <<(O,#ADD1B2)entity>> - moduleMg -> module : Init() - return -end -return - -return - - - +@startuml +!include + +autoactivate on +autonumber + +participant main as "int main(args)" + +participant app as "ShadowApplication" <<(O,#ADD1B2) singleton>> + +participant moduleMg as "ModuleManager" <<(O,#ADD1B2) singleton>> + + +'participant gameDll as "longName" : <$ma_file{scale=0.5}> <> + +participant "Game DLL" as dll <<$ma_file{scale=0.5}>> #LightGray <> + +-> main +main -> app ** : create +activate app +app -> moduleMg ** : create +return app + +main -> app : LoadGame + +app -> app : load +app -> dll ** : create +return + +app -> dll : sh_main + +loop for each needed module + dll -> moduleMg : AddModule() + return +end + +return + +return + +main -> app : Init() +app -> moduleMg : Init() + +loop module in modules + collections module as "Module" <<(O,#ADD1B2)entity>> + moduleMg -> module : Init() + return +end +return + +return + + + diff --git a/projs/docs/thesis/common/includes/declaration.tex b/projs/docs/thesis/common/includes/declaration.tex index d371f9a4..922220a0 100644 --- a/projs/docs/thesis/common/includes/declaration.tex +++ b/projs/docs/thesis/common/includes/declaration.tex @@ -1,31 +1,31 @@ -\selectlanguage{magyar} -\pagenumbering{gobble} -%-------------------------------------------------------------------------------------- -% Nyilatkozat -%-------------------------------------------------------------------------------------- -\begin{center} -\large -\textbf{HALLGATÓI NYILATKOZAT}\\ -\end{center} - -Alulírott \emph{\vikszerzoVezeteknev{} \vikszerzoKeresztnev}, szigorló hallgató kijelentem, hogy ezt a \vikmunkatipusat{} meg nem engedett segítség nélkül, saját magam készítettem, csak a megadott forrásokat (szakirodalom, eszközök stb.) használtam fel. Minden olyan részt, melyet szó szerint, vagy azonos értelemben, de átfogalmazva más forrásból átvettem, egyértelműen, a forrás megadásával megjelöltem. - -Hozzájárulok, hogy a jelen munkám alapadatait (szerző(k), cím, angol és magyar nyelvű tartalmi kivonat, készítés éve, konzulens(ek) neve) a BME VIK nyilvánosan hozzáférhető elektronikus formában, a munka teljes szövegét pedig az egyetem belső hálózatán keresztül (vagy autentikált felhasználók számára) közzétegye. Kijelentem, hogy a benyújtott munka és annak elektronikus verziója megegyezik. Dékáni engedéllyel titkosított diplomatervek esetén a dolgozat szövege csak 3 év eltelte után válik hozzáférhetővé. - -\begin{flushleft} -\vspace*{1cm} -Budapest, \today -\end{flushleft} - -\begin{flushright} - \vspace*{1cm} - \makebox[7cm]{\rule{6cm}{.4pt}}\\ - \makebox[7cm]{\emph{\vikszerzoVezeteknev{} \vikszerzoKeresztnev}}\\ - \makebox[7cm]{hallgató} -\end{flushright} -\thispagestyle{empty} - -\vfill -\cleardoublepage - -\selectthesislanguage +\selectlanguage{magyar} +\pagenumbering{gobble} +%-------------------------------------------------------------------------------------- +% Nyilatkozat +%-------------------------------------------------------------------------------------- +\begin{center} +\large +\textbf{HALLGATÓI NYILATKOZAT}\\ +\end{center} + +Alulírott \emph{\vikszerzoVezeteknev{} \vikszerzoKeresztnev}, szigorló hallgató kijelentem, hogy ezt a \vikmunkatipusat{} meg nem engedett segítség nélkül, saját magam készítettem, csak a megadott forrásokat (szakirodalom, eszközök stb.) használtam fel. Minden olyan részt, melyet szó szerint, vagy azonos értelemben, de átfogalmazva más forrásból átvettem, egyértelműen, a forrás megadásával megjelöltem. + +Hozzájárulok, hogy a jelen munkám alapadatait (szerző(k), cím, angol és magyar nyelvű tartalmi kivonat, készítés éve, konzulens(ek) neve) a BME VIK nyilvánosan hozzáférhető elektronikus formában, a munka teljes szövegét pedig az egyetem belső hálózatán keresztül (vagy autentikált felhasználók számára) közzétegye. Kijelentem, hogy a benyújtott munka és annak elektronikus verziója megegyezik. Dékáni engedéllyel titkosított diplomatervek esetén a dolgozat szövege csak 3 év eltelte után válik hozzáférhetővé. + +\begin{flushleft} +\vspace*{1cm} +Budapest, \today +\end{flushleft} + +\begin{flushright} + \vspace*{1cm} + \makebox[7cm]{\rule{6cm}{.4pt}}\\ + \makebox[7cm]{\emph{\vikszerzoVezeteknev{} \vikszerzoKeresztnev}}\\ + \makebox[7cm]{hallgató} +\end{flushright} +\thispagestyle{empty} + +\vfill +\cleardoublepage + +\selectthesislanguage diff --git a/projs/docs/thesis/common/includes/guideline.tex b/projs/docs/thesis/common/includes/guideline.tex index 86e3f94f..4bbe4e20 100644 --- a/projs/docs/thesis/common/includes/guideline.tex +++ b/projs/docs/thesis/common/includes/guideline.tex @@ -1,54 +1,54 @@ -\selecthungarian -%-------------------------------------------------------------------------------------- -% Rovid formai es tartalmi tajekoztato -%-------------------------------------------------------------------------------------- - -\footnotesize -\begin{center} -\large -\textbf{\Large Általános információk, a diplomaterv szerkezete}\\ -\end{center} - -A diplomaterv szerkezete a BME Villamosmérnöki és Informatikai Karán: -\begin{enumerate} -\item Diplomaterv feladatkiírás -\item Címoldal -\item Tartalomjegyzék -\item A diplomatervező nyilatkozata az önálló munkáról és az elektronikus adatok kezeléséről -\item Tartalmi összefoglaló magyarul és angolul -\item Bevezetés: a feladat értelmezése, a tervezés célja, a feladat indokoltsága, a diplomaterv felépítésének rövid összefoglalása -\item A feladatkiírás pontosítása és részletes elemzése -\item Előzmények (irodalomkutatás, hasonló alkotások), az ezekből levonható következtetések -\item A tervezés részletes leírása, a döntési lehetőségek értékelése és a választott megoldások indoklása -\item A megtervezett műszaki alkotás értékelése, kritikai elemzése, továbbfejlesztési lehetőségek -\item Esetleges köszönetnyilvánítások -\item Részletes és pontos irodalomjegyzék -\item Függelék(ek) -\end{enumerate} - -Felhasználható a következő oldaltól kezdődő \LaTeX diplomatervsablon dokumentum tartalma. - -A diplomaterv szabványos méretű A4-es lapokra kerüljön. Az oldalak tükörmargóval készüljenek (mindenhol 2,5~cm, baloldalon 1~cm-es kötéssel). Az alapértelmezett betűkészlet a 12 pontos Times New Roman, másfeles sorközzel, de ettől kismértékben el lehet térni, ill. más betűtípus használata is megengedett. - -Minden oldalon -- az első négy szerkezeti elem kivételével -- szerepelnie kell az oldalszámnak. - -A fejezeteket decimális beosztással kell ellátni. Az ábrákat a megfelelő helyre be kell illeszteni, fejezetenként decimális számmal és kifejező címmel kell ellátni. A fejezeteket decimális aláosztással számozzuk, maximálisan 3 aláosztás mélységben (pl. 2.3.4.1.). Az ábrákat, táblázatokat és képleteket célszerű fejezetenként külön számozni (pl. 2.4. ábra, 4.2. táblázat vagy képletnél (3.2)). A fejezetcímeket igazítsuk balra, a normál szövegnél viszont használjunk sorkiegyenlítést. Az ábrákat, táblázatokat és a hozzájuk tartozó címet igazítsuk középre. A cím a jelölt rész alatt helyezkedjen el. - -A képeket lehetőleg rajzoló programmal készítsék el, az egyenleteket egyenlet-szerkesztő segítségével írják le (A \LaTeX~ehhez kézenfekvő megoldásokat nyújt). - -Az irodalomjegyzék szövegközi hivatkozása történhet sorszámozva (ez a preferált megoldás) vagy a Harvard-rendszerben (a szerző és az évszám megadásával). A teljes lista névsor szerinti sorrendben a szöveg végén szerepeljen (sorszámozott irodalmi hivatkozások esetén hivatkozási sorrendben). A szakirodalmi források címeit azonban mindig az eredeti nyelven kell megadni, esetleg zárójelben a fordítással. A listában szereplő valamennyi publikációra hivatkozni kell a szövegben (a \LaTeX-sablon a Bib\TeX~segítségével mindezt automatikusan kezeli). Minden publikáció a szerzők után a következő adatok szerepelnek: folyóirat cikkeknél a pontos cím, a folyóirat címe, évfolyam, szám, oldalszám tól-ig. A folyóiratok címét csak akkor rövidítsük, ha azok nagyon közismertek vagy nagyon hosszúak. Internetes hivatkozások megadásakor fontos, hogy az elérési út előtt megadjuk az oldal tulajdonosát és tartalmát (mivel a link egy idő után akár elérhetetlenné is válhat), valamint az elérés időpontját. - -\vspace{5mm} -Fontos: -\begin{itemize} - \item A szakdolgozatkészítő / diplomatervező nyilatkozata (a jelen sablonban szereplő szövegtartalommal) kötelező előírás, Karunkon ennek hiányában a szakdolgozat/diplomaterv nem bírálható és nem védhető! - \item Mind a dolgozat, mind a melléklet maximálisan 15~MB méretű lehet! -\end{itemize} - -\vspace{5mm} -\begin{center} -Jó munkát, sikeres szakdolgozatkészítést, ill. diplomatervezést kívánunk! -\end{center} - -\normalsize -\selectthesislanguage +\selecthungarian +%-------------------------------------------------------------------------------------- +% Rovid formai es tartalmi tajekoztato +%-------------------------------------------------------------------------------------- + +\footnotesize +\begin{center} +\large +\textbf{\Large Általános információk, a diplomaterv szerkezete}\\ +\end{center} + +A diplomaterv szerkezete a BME Villamosmérnöki és Informatikai Karán: +\begin{enumerate} +\item Diplomaterv feladatkiírás +\item Címoldal +\item Tartalomjegyzék +\item A diplomatervező nyilatkozata az önálló munkáról és az elektronikus adatok kezeléséről +\item Tartalmi összefoglaló magyarul és angolul +\item Bevezetés: a feladat értelmezése, a tervezés célja, a feladat indokoltsága, a diplomaterv felépítésének rövid összefoglalása +\item A feladatkiírás pontosítása és részletes elemzése +\item Előzmények (irodalomkutatás, hasonló alkotások), az ezekből levonható következtetések +\item A tervezés részletes leírása, a döntési lehetőségek értékelése és a választott megoldások indoklása +\item A megtervezett műszaki alkotás értékelése, kritikai elemzése, továbbfejlesztési lehetőségek +\item Esetleges köszönetnyilvánítások +\item Részletes és pontos irodalomjegyzék +\item Függelék(ek) +\end{enumerate} + +Felhasználható a következő oldaltól kezdődő \LaTeX diplomatervsablon dokumentum tartalma. + +A diplomaterv szabványos méretű A4-es lapokra kerüljön. Az oldalak tükörmargóval készüljenek (mindenhol 2,5~cm, baloldalon 1~cm-es kötéssel). Az alapértelmezett betűkészlet a 12 pontos Times New Roman, másfeles sorközzel, de ettől kismértékben el lehet térni, ill. más betűtípus használata is megengedett. + +Minden oldalon -- az első négy szerkezeti elem kivételével -- szerepelnie kell az oldalszámnak. + +A fejezeteket decimális beosztással kell ellátni. Az ábrákat a megfelelő helyre be kell illeszteni, fejezetenként decimális számmal és kifejező címmel kell ellátni. A fejezeteket decimális aláosztással számozzuk, maximálisan 3 aláosztás mélységben (pl. 2.3.4.1.). Az ábrákat, táblázatokat és képleteket célszerű fejezetenként külön számozni (pl. 2.4. ábra, 4.2. táblázat vagy képletnél (3.2)). A fejezetcímeket igazítsuk balra, a normál szövegnél viszont használjunk sorkiegyenlítést. Az ábrákat, táblázatokat és a hozzájuk tartozó címet igazítsuk középre. A cím a jelölt rész alatt helyezkedjen el. + +A képeket lehetőleg rajzoló programmal készítsék el, az egyenleteket egyenlet-szerkesztő segítségével írják le (A \LaTeX~ehhez kézenfekvő megoldásokat nyújt). + +Az irodalomjegyzék szövegközi hivatkozása történhet sorszámozva (ez a preferált megoldás) vagy a Harvard-rendszerben (a szerző és az évszám megadásával). A teljes lista névsor szerinti sorrendben a szöveg végén szerepeljen (sorszámozott irodalmi hivatkozások esetén hivatkozási sorrendben). A szakirodalmi források címeit azonban mindig az eredeti nyelven kell megadni, esetleg zárójelben a fordítással. A listában szereplő valamennyi publikációra hivatkozni kell a szövegben (a \LaTeX-sablon a Bib\TeX~segítségével mindezt automatikusan kezeli). Minden publikáció a szerzők után a következő adatok szerepelnek: folyóirat cikkeknél a pontos cím, a folyóirat címe, évfolyam, szám, oldalszám tól-ig. A folyóiratok címét csak akkor rövidítsük, ha azok nagyon közismertek vagy nagyon hosszúak. Internetes hivatkozások megadásakor fontos, hogy az elérési út előtt megadjuk az oldal tulajdonosát és tartalmát (mivel a link egy idő után akár elérhetetlenné is válhat), valamint az elérés időpontját. + +\vspace{5mm} +Fontos: +\begin{itemize} + \item A szakdolgozatkészítő / diplomatervező nyilatkozata (a jelen sablonban szereplő szövegtartalommal) kötelező előírás, Karunkon ennek hiányában a szakdolgozat/diplomaterv nem bírálható és nem védhető! + \item Mind a dolgozat, mind a melléklet maximálisan 15~MB méretű lehet! +\end{itemize} + +\vspace{5mm} +\begin{center} +Jó munkát, sikeres szakdolgozatkészítést, ill. diplomatervezést kívánunk! +\end{center} + +\normalsize +\selectthesislanguage diff --git a/projs/docs/thesis/common/includes/packages.tex b/projs/docs/thesis/common/includes/packages.tex index 96971237..038a2c0c 100644 --- a/projs/docs/thesis/common/includes/packages.tex +++ b/projs/docs/thesis/common/includes/packages.tex @@ -1,67 +1,67 @@ -% thanks to http://tex.stackexchange.com/a/47579/71109 -\usepackage{ifxetex} -\usepackage{ifluatex} -\newif\ifxetexorluatex % a new conditional starts as false -\ifnum 0\ifxetex 1\fi\ifluatex 1\fi>0 - \xetexorluatextrue -\fi - -\ifxetexorluatex - \usepackage{fontspec} -\else - \usepackage[T1]{fontenc} - \usepackage[utf8]{inputenc} - \usepackage[lighttt]{lmodern} - \ttfamily\DeclareFontShape{T1}{lmtt}{m}{it}{<->sub*lmtt/m/sl}{} -\fi - -\usepackage[english,magyar]{babel} % Alapértelmezés szerint utoljára definiált nyelv lesz aktív, de később külön beállítjuk az aktív nyelvet. - -\usepackage{emptypage} % omit page number on empty pages - -%\usepackage{cmap} -\usepackage{amsfonts,amsmath,amssymb} % Mathematical symbols. -%\usepackage[ruled,boxed,resetcount,linesnumbered]{algorithm2e} % For pseudocodes. % beware: this is not compatible with LuaLaTeX, see http://tex.stackexchange.com/questions/34814/lualatex-and-algorithm2e -\usepackage{booktabs} % For publication quality tables for LaTeX -\usepackage{graphicx} - -%\usepackage{fancyhdr} -%\usepackage{lastpage} - -\usepackage{geometry} -%\usepackage{sectsty} -\usepackage{setspace} % For setting line spacing - -\usepackage[unicode]{hyperref} % For hyperlinks in the generated document. -\usepackage{xcolor} -\usepackage{listings} % For source code snippets. - -\usepackage[amsmath,thmmarks]{ntheorem} % Theorem-like environments. - -\usepackage[hang]{caption} - -\singlespacing - -\newcommand{\selecthungarian}{ - \selectlanguage{magyar} - \setlength{\parindent}{2em} - \setlength{\parskip}{0em} - \frenchspacing -} - -\newcommand{\selectenglish}{ - \selectlanguage{english} - \setlength{\parindent}{0em} - \setlength{\parskip}{0.5em} - \nonfrenchspacing - \renewcommand{\figureautorefname}{Figure} - \renewcommand{\tableautorefname}{Table} - \renewcommand{\partautorefname}{Part} - \renewcommand{\chapterautorefname}{Chapter} - \renewcommand{\sectionautorefname}{Section} - \renewcommand{\subsectionautorefname}{Section} - \renewcommand{\subsubsectionautorefname}{Section} -} - -\usepackage[numbers]{natbib} -\usepackage{xspace} +% thanks to http://tex.stackexchange.com/a/47579/71109 +\usepackage{ifxetex} +\usepackage{ifluatex} +\newif\ifxetexorluatex % a new conditional starts as false +\ifnum 0\ifxetex 1\fi\ifluatex 1\fi>0 + \xetexorluatextrue +\fi + +\ifxetexorluatex + \usepackage{fontspec} +\else + \usepackage[T1]{fontenc} + \usepackage[utf8]{inputenc} + \usepackage[lighttt]{lmodern} + \ttfamily\DeclareFontShape{T1}{lmtt}{m}{it}{<->sub*lmtt/m/sl}{} +\fi + +\usepackage[english,magyar]{babel} % Alapértelmezés szerint utoljára definiált nyelv lesz aktív, de később külön beállítjuk az aktív nyelvet. + +\usepackage{emptypage} % omit page number on empty pages + +%\usepackage{cmap} +\usepackage{amsfonts,amsmath,amssymb} % Mathematical symbols. +%\usepackage[ruled,boxed,resetcount,linesnumbered]{algorithm2e} % For pseudocodes. % beware: this is not compatible with LuaLaTeX, see http://tex.stackexchange.com/questions/34814/lualatex-and-algorithm2e +\usepackage{booktabs} % For publication quality tables for LaTeX +\usepackage{graphicx} + +%\usepackage{fancyhdr} +%\usepackage{lastpage} + +\usepackage{geometry} +%\usepackage{sectsty} +\usepackage{setspace} % For setting line spacing + +\usepackage[unicode]{hyperref} % For hyperlinks in the generated document. +\usepackage{xcolor} +\usepackage{listings} % For source code snippets. + +\usepackage[amsmath,thmmarks]{ntheorem} % Theorem-like environments. + +\usepackage[hang]{caption} + +\singlespacing + +\newcommand{\selecthungarian}{ + \selectlanguage{magyar} + \setlength{\parindent}{2em} + \setlength{\parskip}{0em} + \frenchspacing +} + +\newcommand{\selectenglish}{ + \selectlanguage{english} + \setlength{\parindent}{0em} + \setlength{\parskip}{0.5em} + \nonfrenchspacing + \renewcommand{\figureautorefname}{Figure} + \renewcommand{\tableautorefname}{Table} + \renewcommand{\partautorefname}{Part} + \renewcommand{\chapterautorefname}{Chapter} + \renewcommand{\sectionautorefname}{Section} + \renewcommand{\subsectionautorefname}{Section} + \renewcommand{\subsubsectionautorefname}{Section} +} + +\usepackage[numbers]{natbib} +\usepackage{xspace} diff --git a/projs/docs/thesis/common/includes/preamble.tex b/projs/docs/thesis/common/includes/preamble.tex index 863aabc0..b03292fe 100644 --- a/projs/docs/thesis/common/includes/preamble.tex +++ b/projs/docs/thesis/common/includes/preamble.tex @@ -1,120 +1,120 @@ -%-------------------------------------------------------------------------------------- -% Page layout setup -%-------------------------------------------------------------------------------------- -% we need to redefine the pagestyle plain -% another possibility is to use the body of this command without \fancypagestyle -% and use \pagestyle{fancy} but in that case the special pages -% (like the ToC, the References, and the Chapter pages)remain in plane style - -\pagestyle{plain} -\geometry{inner=35mm, outer=25mm, top=28mm, bottom=25mm} - -\setcounter{tocdepth}{3} -%\sectionfont{\large\upshape\bfseries} -\setcounter{secnumdepth}{3} - -\sloppy % Margón túllógó sorok tiltása. -\widowpenalty=10000 \clubpenalty=10000 %A fattyú- és árvasorok elkerülése -\def\hyph{-\penalty0\hskip0pt\relax} % Kötőjeles szavak elválasztásának engedélyezése - - -%-------------------------------------------------------------------------------------- -% Setup hyperref package -%-------------------------------------------------------------------------------------- -\hypersetup{ - % bookmarks=true, % show bookmarks bar? - unicode=true, % non-Latin characters in Acrobat's bookmarks - pdftitle={\vikcim}, % title - pdfauthor={\szerzoMeta}, % author - pdfsubject={\vikdoktipus}, % subject of the document - pdfcreator={\szerzoMeta}, % creator of the document - pdfproducer={}, % producer of the document - pdfkeywords={}, % list of keywords (separate then by comma) - pdfnewwindow=true, % links in new window - colorlinks=true, % false: boxed links; true: colored links - linkcolor=black, % color of internal links - citecolor=black, % color of links to bibliography - filecolor=black, % color of file links - urlcolor=black % color of external links -} - - -%-------------------------------------------------------------------------------------- -% Set up listings -%-------------------------------------------------------------------------------------- -\definecolor{lightgray}{rgb}{0.95,0.95,0.95} -\lstset{ - basicstyle=\scriptsize\ttfamily, % print whole listing small - keywordstyle=\color{black}\bfseries, % bold black keywords - identifierstyle=, % nothing happens - % default behavior: comments in italic, to change use - % commentstyle=\color{green}, % for e.g. green comments - stringstyle=\scriptsize, - showstringspaces=false, % no special string spaces - aboveskip=3pt, - belowskip=3pt, - backgroundcolor=\color{lightgray}, - columns=flexible, - keepspaces=true, - escapeinside={(*@}{@*)}, - captionpos=b, - breaklines=true, - frame=single, - float=!ht, - tabsize=2, - literate=* - {á}{{\'a}}1 {é}{{\'e}}1 {í}{{\'i}}1 {ó}{{\'o}}1 {ö}{{\"o}}1 {ő}{{\H{o}}}1 {ú}{{\'u}}1 {ü}{{\"u}}1 {ű}{{\H{u}}}1 - {Á}{{\'A}}1 {É}{{\'E}}1 {Í}{{\'I}}1 {Ó}{{\'O}}1 {Ö}{{\"O}}1 {Ő}{{\H{O}}}1 {Ú}{{\'U}}1 {Ü}{{\"U}}1 {Ű}{{\H{U}}}1 -} - - -%-------------------------------------------------------------------------------------- -% Set up theorem-like environments -%-------------------------------------------------------------------------------------- -% Using ntheorem package -- see http://www.math.washington.edu/tex-archive/macros/latex/contrib/ntheorem/ntheorem.pdf - -\theoremstyle{plain} -\theoremseparator{.} -\newtheorem{example}{\pelda} - -\theoremseparator{.} -%\theoremprework{\bigskip\hrule\medskip} -%\theorempostwork{\hrule\bigskip} -\theorembodyfont{\upshape} -\theoremsymbol{{\large \ensuremath{\centerdot}}} -\newtheorem{definition}{\definicio} - -\theoremseparator{.} -%\theoremprework{\bigskip\hrule\medskip} -%\theorempostwork{\hrule\bigskip} -\newtheorem{theorem}{\tetel} - - -%-------------------------------------------------------------------------------------- -% Some new commands and declarations -%-------------------------------------------------------------------------------------- -\newcommand{\code}[1]{{\upshape\ttfamily\scriptsize\indent #1}} -\newcommand{\doi}[1]{DOI: \href{http://dx.doi.org/\detokenize{#1}}{\raggedright{\texttt{\detokenize{#1}}}}} % A hivatkozások közt így könnyebb DOI-t megadni. - -\DeclareMathOperator*{\argmax}{arg\,max} -%\DeclareMathOperator*[1]{\floor}{arg\,max} -\DeclareMathOperator{\sign}{sgn} -\DeclareMathOperator{\rot}{rot} - - -%-------------------------------------------------------------------------------------- -% Setup captions -%-------------------------------------------------------------------------------------- -\captionsetup[figure]{aboveskip=10pt} - -\renewcommand{\captionlabelfont}{\bf} -%\renewcommand{\captionfont}{\footnotesize\it} - -%-------------------------------------------------------------------------------------- -% Hyphenation exceptions -%-------------------------------------------------------------------------------------- -\hyphenation{Shakes-peare Mar-seilles ár-víz-tű-rő tü-kör-fú-ró-gép} - - -\author{\vikszerzo} -\title{\viktitle} +%-------------------------------------------------------------------------------------- +% Page layout setup +%-------------------------------------------------------------------------------------- +% we need to redefine the pagestyle plain +% another possibility is to use the body of this command without \fancypagestyle +% and use \pagestyle{fancy} but in that case the special pages +% (like the ToC, the References, and the Chapter pages)remain in plane style + +\pagestyle{plain} +\geometry{inner=35mm, outer=25mm, top=28mm, bottom=25mm} + +\setcounter{tocdepth}{3} +%\sectionfont{\large\upshape\bfseries} +\setcounter{secnumdepth}{3} + +\sloppy % Margón túllógó sorok tiltása. +\widowpenalty=10000 \clubpenalty=10000 %A fattyú- és árvasorok elkerülése +\def\hyph{-\penalty0\hskip0pt\relax} % Kötőjeles szavak elválasztásának engedélyezése + + +%-------------------------------------------------------------------------------------- +% Setup hyperref package +%-------------------------------------------------------------------------------------- +\hypersetup{ + % bookmarks=true, % show bookmarks bar? + unicode=true, % non-Latin characters in Acrobat's bookmarks + pdftitle={\vikcim}, % title + pdfauthor={\szerzoMeta}, % author + pdfsubject={\vikdoktipus}, % subject of the document + pdfcreator={\szerzoMeta}, % creator of the document + pdfproducer={}, % producer of the document + pdfkeywords={}, % list of keywords (separate then by comma) + pdfnewwindow=true, % links in new window + colorlinks=true, % false: boxed links; true: colored links + linkcolor=black, % color of internal links + citecolor=black, % color of links to bibliography + filecolor=black, % color of file links + urlcolor=black % color of external links +} + + +%-------------------------------------------------------------------------------------- +% Set up listings +%-------------------------------------------------------------------------------------- +\definecolor{lightgray}{rgb}{0.95,0.95,0.95} +\lstset{ + basicstyle=\scriptsize\ttfamily, % print whole listing small + keywordstyle=\color{black}\bfseries, % bold black keywords + identifierstyle=, % nothing happens + % default behavior: comments in italic, to change use + % commentstyle=\color{green}, % for e.g. green comments + stringstyle=\scriptsize, + showstringspaces=false, % no special string spaces + aboveskip=3pt, + belowskip=3pt, + backgroundcolor=\color{lightgray}, + columns=flexible, + keepspaces=true, + escapeinside={(*@}{@*)}, + captionpos=b, + breaklines=true, + frame=single, + float=!ht, + tabsize=2, + literate=* + {á}{{\'a}}1 {é}{{\'e}}1 {í}{{\'i}}1 {ó}{{\'o}}1 {ö}{{\"o}}1 {ő}{{\H{o}}}1 {ú}{{\'u}}1 {ü}{{\"u}}1 {ű}{{\H{u}}}1 + {Á}{{\'A}}1 {É}{{\'E}}1 {Í}{{\'I}}1 {Ó}{{\'O}}1 {Ö}{{\"O}}1 {Ő}{{\H{O}}}1 {Ú}{{\'U}}1 {Ü}{{\"U}}1 {Ű}{{\H{U}}}1 +} + + +%-------------------------------------------------------------------------------------- +% Set up theorem-like environments +%-------------------------------------------------------------------------------------- +% Using ntheorem package -- see http://www.math.washington.edu/tex-archive/macros/latex/contrib/ntheorem/ntheorem.pdf + +\theoremstyle{plain} +\theoremseparator{.} +\newtheorem{example}{\pelda} + +\theoremseparator{.} +%\theoremprework{\bigskip\hrule\medskip} +%\theorempostwork{\hrule\bigskip} +\theorembodyfont{\upshape} +\theoremsymbol{{\large \ensuremath{\centerdot}}} +\newtheorem{definition}{\definicio} + +\theoremseparator{.} +%\theoremprework{\bigskip\hrule\medskip} +%\theorempostwork{\hrule\bigskip} +\newtheorem{theorem}{\tetel} + + +%-------------------------------------------------------------------------------------- +% Some new commands and declarations +%-------------------------------------------------------------------------------------- +\newcommand{\code}[1]{{\upshape\ttfamily\scriptsize\indent #1}} +\newcommand{\doi}[1]{DOI: \href{http://dx.doi.org/\detokenize{#1}}{\raggedright{\texttt{\detokenize{#1}}}}} % A hivatkozások közt így könnyebb DOI-t megadni. + +\DeclareMathOperator*{\argmax}{arg\,max} +%\DeclareMathOperator*[1]{\floor}{arg\,max} +\DeclareMathOperator{\sign}{sgn} +\DeclareMathOperator{\rot}{rot} + + +%-------------------------------------------------------------------------------------- +% Setup captions +%-------------------------------------------------------------------------------------- +\captionsetup[figure]{aboveskip=10pt} + +\renewcommand{\captionlabelfont}{\bf} +%\renewcommand{\captionfont}{\footnotesize\it} + +%-------------------------------------------------------------------------------------- +% Hyphenation exceptions +%-------------------------------------------------------------------------------------- +\hyphenation{Shakes-peare Mar-seilles ár-víz-tű-rő tü-kör-fú-ró-gép} + + +\author{\vikszerzo} +\title{\viktitle} diff --git a/projs/docs/thesis/common/includes/project.tex b/projs/docs/thesis/common/includes/project.tex index 313cc4ed..251eda78 100644 --- a/projs/docs/thesis/common/includes/project.tex +++ b/projs/docs/thesis/common/includes/project.tex @@ -1,10 +1,10 @@ -%-------------------------------------------------------------------------------------- -% Feladatkiiras (a tanszeken atveheto, kinyomtatott valtozat) -%-------------------------------------------------------------------------------------- -\clearpage -\begin{center} -\large -\textbf{FELADATKIÍRÁS}\\ -\end{center} - -A feladatkiírást a tanszéki adminisztrációban lehet átvenni, és a leadott munkába eredeti, tanszéki pecséttel ellátott és a tanszékvezető által aláírt lapot kell belefűzni (ezen oldal \emph{helyett}, ez az oldal csak útmutatás). Az elektronikusan feltöltött dolgozatban már nem kell beleszerkeszteni ezt a feladatkiírást. +%-------------------------------------------------------------------------------------- +% Feladatkiiras (a tanszeken atveheto, kinyomtatott valtozat) +%-------------------------------------------------------------------------------------- +\clearpage +\begin{center} +\large +\textbf{FELADATKIÍRÁS}\\ +\end{center} + +A feladatkiírást a tanszéki adminisztrációban lehet átvenni, és a leadott munkába eredeti, tanszéki pecséttel ellátott és a tanszékvezető által aláírt lapot kell belefűzni (ezen oldal \emph{helyett}, ez az oldal csak útmutatás). Az elektronikusan feltöltött dolgozatban már nem kell beleszerkeszteni ezt a feladatkiírást. diff --git a/projs/docs/thesis/common/includes/tdk-variables.tex b/projs/docs/thesis/common/includes/tdk-variables.tex index 3408e12d..3f315598 100644 --- a/projs/docs/thesis/common/includes/tdk-variables.tex +++ b/projs/docs/thesis/common/includes/tdk-variables.tex @@ -1,11 +1,11 @@ -%-------------------------------------------------------------------------------------- -% TDK-specifikus változók -%-------------------------------------------------------------------------------------- -\newcommand{\tdkszerzoB}{Második Szerző} % Második szerző neve; hagyd üresen, ha egyedül írtad a TDK-t. -\newcommand{\tdkev}{2014} % A dolgozat írásának éve (pl. "2014") (Ez OTDK-nál eltérhet az aktuális évtől.) - -% További adatok az OTDK címlaphoz (BME-s TDK-hoz nem kell kitölteni) -\newcommand{\tdkevfolyamA}{IV} % Első szerző évfolyama, római számmal (pl. IV). -\newcommand{\tdkevfolyamB}{III} % Második szerző évfolyama, római számmal (pl. III). -\newcommand{\tdkkonzulensbeosztasA}{egyetemi tanár} % Első konzulens beosztása (pl. egyetemi docens) -\newcommand{\tdkkonzulensbeosztasB}{doktorandusz} % Második konzulens beosztása (pl. egyetemi docens) +%-------------------------------------------------------------------------------------- +% TDK-specifikus változók +%-------------------------------------------------------------------------------------- +\newcommand{\tdkszerzoB}{Második Szerző} % Második szerző neve; hagyd üresen, ha egyedül írtad a TDK-t. +\newcommand{\tdkev}{2014} % A dolgozat írásának éve (pl. "2014") (Ez OTDK-nál eltérhet az aktuális évtől.) + +% További adatok az OTDK címlaphoz (BME-s TDK-hoz nem kell kitölteni) +\newcommand{\tdkevfolyamA}{IV} % Első szerző évfolyama, római számmal (pl. IV). +\newcommand{\tdkevfolyamB}{III} % Második szerző évfolyama, római számmal (pl. III). +\newcommand{\tdkkonzulensbeosztasA}{egyetemi tanár} % Első konzulens beosztása (pl. egyetemi docens) +\newcommand{\tdkkonzulensbeosztasB}{doktorandusz} % Második konzulens beosztása (pl. egyetemi docens) diff --git a/projs/docs/thesis/common/includes/thesis-en.tex b/projs/docs/thesis/common/includes/thesis-en.tex index c61650e3..6bb612e1 100644 --- a/projs/docs/thesis/common/includes/thesis-en.tex +++ b/projs/docs/thesis/common/includes/thesis-en.tex @@ -1,56 +1,56 @@ -%-------------------------------------------------------------------------------------- -% Elnevezések -%-------------------------------------------------------------------------------------- -\newcommand{\bme}{Budapest University of Technology and Economics} -\newcommand{\vik}{Faculty of Electrical Engineering and Informatics} - -\newcommand{\bmemit}{Department of Measurement and Information Systems} - -\newcommand{\keszitette}{Author} -\newcommand{\konzulens}{Advisor} - -\newcommand{\bsc}{Bachelor's Thesis} -\newcommand{\msc}{Master's Thesis} -\newcommand{\tdk}{Scientific Students' Association Report} -\newcommand{\bsconlab}{BSc Project Laboratory} -\newcommand{\msconlabi}{MSc Project Laboratory 1} -\newcommand{\msconlabii}{MSc Project Laboratory 2} - -\newcommand{\pelda}{Example} -\newcommand{\definicio}{Definition} -\newcommand{\tetel}{Theorem} - -\newcommand{\bevezetes}{Introduction} -\newcommand{\koszonetnyilvanitas}{Acknowledgements} -\newcommand{\fuggelek}{Appendix} - -% Optional custom titles -%\addto\captionsenglish{% -%\renewcommand*{\listfigurename}{Your list of figures title} -%\renewcommand*{\listtablename}{Your list of tables title} -%\renewcommand*{\bibname}{Your bibliography title} -%} - -\newcommand{\szerzo}{\vikszerzoKeresztnev{} \vikszerzoVezeteknev} -\newcommand{\vikkonzulensA}{\vikkonzulensAMegszolitas\vikkonzulensAKeresztnev{} \vikkonzulensAVezeteknev} -\newcommand{\vikkonzulensB}{\vikkonzulensBMegszolitas\vikkonzulensBKeresztnev{} \vikkonzulensBVezeteknev} -\newcommand{\vikkonzulensC}{\vikkonzulensCMegszolitas\vikkonzulensCKeresztnev{} \vikkonzulensCVezeteknev} - -\newcommand{\selectthesislanguage}{\selectenglish} - -\bibliographystyle{plainnat} - -\newcommand{\ie}{i.e.\@\xspace} -\newcommand{\Ie}{I.e.\@\xspace} -\newcommand{\eg}{e.g.\@\xspace} -\newcommand{\Eg}{E.g.\@\xspace} -\newcommand{\etal}{et al.\@\xspace} -\newcommand{\etc}{etc.\@\xspace} -\newcommand{\vs}{vs.\@\xspace} -\newcommand{\viz}{viz.\@\xspace} % videlicet -\newcommand{\cf}{cf.\@\xspace} % confer -\newcommand{\Cf}{Cf.\@\xspace} -\newcommand{\wrt}{w.r.t.\@\xspace} % with respect to -\newcommand{\approximately}{approx.\@\xspace} - -\newcommand{\appendixnumber}{1} % a fofejezet-szamlalo az angol ABC 1. betuje (A) lesz +%-------------------------------------------------------------------------------------- +% Elnevezések +%-------------------------------------------------------------------------------------- +\newcommand{\bme}{Budapest University of Technology and Economics} +\newcommand{\vik}{Faculty of Electrical Engineering and Informatics} + +\newcommand{\bmemit}{Department of Measurement and Information Systems} + +\newcommand{\keszitette}{Author} +\newcommand{\konzulens}{Advisor} + +\newcommand{\bsc}{Bachelor's Thesis} +\newcommand{\msc}{Master's Thesis} +\newcommand{\tdk}{Scientific Students' Association Report} +\newcommand{\bsconlab}{BSc Project Laboratory} +\newcommand{\msconlabi}{MSc Project Laboratory 1} +\newcommand{\msconlabii}{MSc Project Laboratory 2} + +\newcommand{\pelda}{Example} +\newcommand{\definicio}{Definition} +\newcommand{\tetel}{Theorem} + +\newcommand{\bevezetes}{Introduction} +\newcommand{\koszonetnyilvanitas}{Acknowledgements} +\newcommand{\fuggelek}{Appendix} + +% Optional custom titles +%\addto\captionsenglish{% +%\renewcommand*{\listfigurename}{Your list of figures title} +%\renewcommand*{\listtablename}{Your list of tables title} +%\renewcommand*{\bibname}{Your bibliography title} +%} + +\newcommand{\szerzo}{\vikszerzoKeresztnev{} \vikszerzoVezeteknev} +\newcommand{\vikkonzulensA}{\vikkonzulensAMegszolitas\vikkonzulensAKeresztnev{} \vikkonzulensAVezeteknev} +\newcommand{\vikkonzulensB}{\vikkonzulensBMegszolitas\vikkonzulensBKeresztnev{} \vikkonzulensBVezeteknev} +\newcommand{\vikkonzulensC}{\vikkonzulensCMegszolitas\vikkonzulensCKeresztnev{} \vikkonzulensCVezeteknev} + +\newcommand{\selectthesislanguage}{\selectenglish} + +\bibliographystyle{plainnat} + +\newcommand{\ie}{i.e.\@\xspace} +\newcommand{\Ie}{I.e.\@\xspace} +\newcommand{\eg}{e.g.\@\xspace} +\newcommand{\Eg}{E.g.\@\xspace} +\newcommand{\etal}{et al.\@\xspace} +\newcommand{\etc}{etc.\@\xspace} +\newcommand{\vs}{vs.\@\xspace} +\newcommand{\viz}{viz.\@\xspace} % videlicet +\newcommand{\cf}{cf.\@\xspace} % confer +\newcommand{\Cf}{Cf.\@\xspace} +\newcommand{\wrt}{w.r.t.\@\xspace} % with respect to +\newcommand{\approximately}{approx.\@\xspace} + +\newcommand{\appendixnumber}{1} % a fofejezet-szamlalo az angol ABC 1. betuje (A) lesz diff --git a/projs/docs/thesis/common/includes/thesis-hu.tex b/projs/docs/thesis/common/includes/thesis-hu.tex index c6b728a6..8fb483eb 100644 --- a/projs/docs/thesis/common/includes/thesis-hu.tex +++ b/projs/docs/thesis/common/includes/thesis-hu.tex @@ -1,45 +1,45 @@ -%-------------------------------------------------------------------------------------- -% Elnevezések -%-------------------------------------------------------------------------------------- -\newcommand{\bme}{Budapesti Műszaki és Gazdaságtudományi Egyetem} -\newcommand{\vik}{Villamosmérnöki és Informatikai Kar} - -\newcommand{\bmemit}{Méréstechnika és Információs Rendszerek Tanszék} - -\newcommand{\keszitette}{Készítette} -\newcommand{\konzulens}{Konzulens} - -\newcommand{\bsc}{Szakdolgozat} -\newcommand{\msc}{Diplomaterv} -\newcommand{\tdk}{TDK dolgozat} -\newcommand{\bsconlab}{BSc Önálló laboratórium} -\newcommand{\msconlabi}{MSc Önálló laboratórium 1.} -\newcommand{\msconlabii}{MSc Önálló laboratórium 2.} - -\newcommand{\pelda}{Példa} -\newcommand{\definicio}{Definíció} -\newcommand{\tetel}{Tétel} - -\newcommand{\bevezetes}{Bevezetés} -\newcommand{\koszonetnyilvanitas}{Köszönetnyilvánítás} -\newcommand{\fuggelek}{Függelék} - -% Opcionálisan átnevezhető címek -%\addto\captionsmagyar{% -%\renewcommand{\listfigurename}{Saját ábrajegyzék cím} -%\renewcommand{\listtablename}{Saját táblázatjegyzék cím} -%\renewcommand{\bibname}{Saját irodalomjegyzék név} -%} - -\newcommand{\szerzo}{\vikszerzoVezeteknev{} \vikszerzoKeresztnev} -\newcommand{\vikkonzulensA}{\vikkonzulensAMegszolitas\vikkonzulensAVezeteknev{} \vikkonzulensAKeresztnev} -\newcommand{\vikkonzulensB}{\vikkonzulensBMegszolitas\vikkonzulensBVezeteknev{} \vikkonzulensBKeresztnev} -\newcommand{\vikkonzulensC}{\vikkonzulensCMegszolitas\vikkonzulensCVezeteknev{} \vikkonzulensCKeresztnev} - -\newcommand{\selectthesislanguage}{\selecthungarian} - -\bibliographystyle{huplain} - -\def\lstlistingname{lista} - -\newcommand{\appendixnumber}{6} % a fofejezet-szamlalo az angol ABC 6. betuje (F) lesz +%-------------------------------------------------------------------------------------- +% Elnevezések +%-------------------------------------------------------------------------------------- +\newcommand{\bme}{Budapesti Műszaki és Gazdaságtudományi Egyetem} +\newcommand{\vik}{Villamosmérnöki és Informatikai Kar} + +\newcommand{\bmemit}{Méréstechnika és Információs Rendszerek Tanszék} + +\newcommand{\keszitette}{Készítette} +\newcommand{\konzulens}{Konzulens} + +\newcommand{\bsc}{Szakdolgozat} +\newcommand{\msc}{Diplomaterv} +\newcommand{\tdk}{TDK dolgozat} +\newcommand{\bsconlab}{BSc Önálló laboratórium} +\newcommand{\msconlabi}{MSc Önálló laboratórium 1.} +\newcommand{\msconlabii}{MSc Önálló laboratórium 2.} + +\newcommand{\pelda}{Példa} +\newcommand{\definicio}{Definíció} +\newcommand{\tetel}{Tétel} + +\newcommand{\bevezetes}{Bevezetés} +\newcommand{\koszonetnyilvanitas}{Köszönetnyilvánítás} +\newcommand{\fuggelek}{Függelék} + +% Opcionálisan átnevezhető címek +%\addto\captionsmagyar{% +%\renewcommand{\listfigurename}{Saját ábrajegyzék cím} +%\renewcommand{\listtablename}{Saját táblázatjegyzék cím} +%\renewcommand{\bibname}{Saját irodalomjegyzék név} +%} + +\newcommand{\szerzo}{\vikszerzoVezeteknev{} \vikszerzoKeresztnev} +\newcommand{\vikkonzulensA}{\vikkonzulensAMegszolitas\vikkonzulensAVezeteknev{} \vikkonzulensAKeresztnev} +\newcommand{\vikkonzulensB}{\vikkonzulensBMegszolitas\vikkonzulensBVezeteknev{} \vikkonzulensBKeresztnev} +\newcommand{\vikkonzulensC}{\vikkonzulensCMegszolitas\vikkonzulensCVezeteknev{} \vikkonzulensCKeresztnev} + +\newcommand{\selectthesislanguage}{\selecthungarian} + +\bibliographystyle{huplain} + +\def\lstlistingname{lista} + +\newcommand{\appendixnumber}{6} % a fofejezet-szamlalo az angol ABC 6. betuje (F) lesz diff --git a/projs/docs/thesis/common/includes/titlepage-otdk.tex b/projs/docs/thesis/common/includes/titlepage-otdk.tex index 54ecb054..d8cfacdb 100644 --- a/projs/docs/thesis/common/includes/titlepage-otdk.tex +++ b/projs/docs/thesis/common/includes/titlepage-otdk.tex @@ -1,58 +1,58 @@ -%% OTDK külső címlap -\begin{titlepage} - $\;$ - \vspace{5cm} - - \begin{center} - \Huge - \textbf{TDK-dolgozat}\let\thefootnote\relax\footnote{A dolgozat bemutatását a XXXXXXXXX ``Lorem ipsum dolor sit amet'' című program támogatta.} - \end{center} - - \vspace{13cm} - - \Large - \hspace{8cm} \szerzo - - \hspace{8cm} \tdkszerzoB - - \hspace{8cm} \tdkev. -\end{titlepage} - -\newpage -\thispagestyle{empty} - - -%% OTDK belső címlap -\begin{titlepage} - \begin{center} - \includegraphics[width=7cm]{./figures/bme_logo.pdf} - \vspace{0.3cm} - - \bme \\ - \vik \\ - \viktanszek \\ - \vspace{3.5cm} - - \huge {\vikcim} - \vspace{1.5cm} - - \large {\textbf{\vikdoktipus}} - \vfill - - {\Large - {\large \keszitette:} \\ \vspace{0.2cm} - \szerzo \\ \tdkevfolyamA. évfolyam \\ - \vspace{0.5cm} - \tdkszerzoB \\ \tdkevfolyamB. évfolyam \\ - \vspace{1.5cm} - {\large \konzulens:} \\ \vspace{0.2cm} - \vikkonzulensA,\\ \tdkkonzulensbeosztasA \\ - \vspace{0.5cm} - \vikkonzulensB,\\ \tdkkonzulensbeosztasB \\ - } - - \vspace{2cm} - \large {\tdkev.} - - \end{center} +%% OTDK külső címlap +\begin{titlepage} + $\;$ + \vspace{5cm} + + \begin{center} + \Huge + \textbf{TDK-dolgozat}\let\thefootnote\relax\footnote{A dolgozat bemutatását a XXXXXXXXX ``Lorem ipsum dolor sit amet'' című program támogatta.} + \end{center} + + \vspace{13cm} + + \Large + \hspace{8cm} \szerzo + + \hspace{8cm} \tdkszerzoB + + \hspace{8cm} \tdkev. +\end{titlepage} + +\newpage +\thispagestyle{empty} + + +%% OTDK belső címlap +\begin{titlepage} + \begin{center} + \includegraphics[width=7cm]{./figures/bme_logo.pdf} + \vspace{0.3cm} + + \bme \\ + \vik \\ + \viktanszek \\ + \vspace{3.5cm} + + \huge {\vikcim} + \vspace{1.5cm} + + \large {\textbf{\vikdoktipus}} + \vfill + + {\Large + {\large \keszitette:} \\ \vspace{0.2cm} + \szerzo \\ \tdkevfolyamA. évfolyam \\ + \vspace{0.5cm} + \tdkszerzoB \\ \tdkevfolyamB. évfolyam \\ + \vspace{1.5cm} + {\large \konzulens:} \\ \vspace{0.2cm} + \vikkonzulensA,\\ \tdkkonzulensbeosztasA \\ + \vspace{0.5cm} + \vikkonzulensB,\\ \tdkkonzulensbeosztasB \\ + } + + \vspace{2cm} + \large {\tdkev.} + + \end{center} \end{titlepage} \ No newline at end of file diff --git a/projs/docs/thesis/common/includes/titlepage-tdk.tex b/projs/docs/thesis/common/includes/titlepage-tdk.tex index fdd3bb3f..f20e78e1 100644 --- a/projs/docs/thesis/common/includes/titlepage-tdk.tex +++ b/projs/docs/thesis/common/includes/titlepage-tdk.tex @@ -1,32 +1,32 @@ -%% TDK címlap -\begin{titlepage} - \begin{center} - \includegraphics[width=7cm]{./figures/bme_logo.pdf} - \vspace{0.3cm} - - \bme \\ - \vik \\ - \viktanszek \\ - \vspace{5cm} - - \huge {\vikcim} - \vspace{1.5cm} - - \large {\textbf{\tdk}} - \vfill - - {\Large - \keszitette: \\ \vspace{0.3cm} - \szerzo \\ - \tdkszerzoB \\ - \vspace{1.5cm} - \konzulens: \\ \vspace{0.3cm} - \vikkonzulensA \\ - \vikkonzulensB \\ - } - - \vspace{2cm} - \large {\tdkev} - \end{center} -\end{titlepage} -%% Címlap vége +%% TDK címlap +\begin{titlepage} + \begin{center} + \includegraphics[width=7cm]{./figures/bme_logo.pdf} + \vspace{0.3cm} + + \bme \\ + \vik \\ + \viktanszek \\ + \vspace{5cm} + + \huge {\vikcim} + \vspace{1.5cm} + + \large {\textbf{\tdk}} + \vfill + + {\Large + \keszitette: \\ \vspace{0.3cm} + \szerzo \\ + \tdkszerzoB \\ + \vspace{1.5cm} + \konzulens: \\ \vspace{0.3cm} + \vikkonzulensA \\ + \vikkonzulensB \\ + } + + \vspace{2cm} + \large {\tdkev} + \end{center} +\end{titlepage} +%% Címlap vége diff --git a/projs/docs/thesis/common/includes/titlepage.tex b/projs/docs/thesis/common/includes/titlepage.tex index b7835dd7..0a996d31 100644 --- a/projs/docs/thesis/common/includes/titlepage.tex +++ b/projs/docs/thesis/common/includes/titlepage.tex @@ -1,33 +1,33 @@ -\hypersetup{pageanchor=false} -%-------------------------------------------------------------------------------------- -% The title page -%-------------------------------------------------------------------------------------- -\begin{titlepage} -\begin{center} -\includegraphics[width=60mm,keepaspectratio]{figures/bme_logo.pdf}\\ -\vspace{0.3cm} -\textbf{\bme}\\ -\textmd{\vik}\\ -\textmd{\viktanszek}\\[5cm] - -\vspace{0.4cm} -{\huge \bfseries \vikcim}\\[0.8cm] -\vspace{0.5cm} -\textsc{\Large \vikdoktipus}\\[4cm] - -{ - \renewcommand{\arraystretch}{0.85} - \begin{tabular}{cc} - \makebox[7cm]{\emph{\keszitette}} & \makebox[7cm]{\emph{\konzulens}} \\ \noalign{\smallskip} - \makebox[7cm]{\szerzo} & \makebox[7cm]{\vikkonzulensA} \\ - & \makebox[7cm]{\vikkonzulensB} \\ - & \makebox[7cm]{\vikkonzulensC} \\ - \end{tabular} -} - -\vfill -{\large \today} -\end{center} -\end{titlepage} -\hypersetup{pageanchor=false} - +\hypersetup{pageanchor=false} +%-------------------------------------------------------------------------------------- +% The title page +%-------------------------------------------------------------------------------------- +\begin{titlepage} +\begin{center} +\includegraphics[width=60mm,keepaspectratio]{figures/bme_logo.pdf}\\ +\vspace{0.3cm} +\textbf{\bme}\\ +\textmd{\vik}\\ +\textmd{\viktanszek}\\[5cm] + +\vspace{0.4cm} +{\huge \bfseries \vikcim}\\[0.8cm] +\vspace{0.5cm} +\textsc{\Large \vikdoktipus}\\[4cm] + +{ + \renewcommand{\arraystretch}{0.85} + \begin{tabular}{cc} + \makebox[7cm]{\emph{\keszitette}} & \makebox[7cm]{\emph{\konzulens}} \\ \noalign{\smallskip} + \makebox[7cm]{\szerzo} & \makebox[7cm]{\vikkonzulensA} \\ + & \makebox[7cm]{\vikkonzulensB} \\ + & \makebox[7cm]{\vikkonzulensC} \\ + \end{tabular} +} + +\vfill +{\large \today} +\end{center} +\end{titlepage} +\hypersetup{pageanchor=false} + diff --git a/projs/docs/thesis/plan/src/bib/mybib.bib b/projs/docs/thesis/plan/src/bib/mybib.bib index b413396c..f2fa78f5 100644 --- a/projs/docs/thesis/plan/src/bib/mybib.bib +++ b/projs/docs/thesis/plan/src/bib/mybib.bib @@ -1,79 +1,79 @@ -@book{Wettl04, - author = {Ferenc Wettl and Gyula Mayer and Péter Szabó}, - publisher = {Panem Könyvkiadó}, - title = {\LaTeX~kézikönyv}, - year = {2004}, -} - -@article{Candy86, - author = {James C. Candy}, - journaltitle = {{IEEE} Trans.\ on Communications}, - month = {01}, - note = {\doi{10.1109/TCOM.1986.1096432}}, - number = {1}, - pages = {72--76}, - title = {Decimation for Sigma Delta Modulation}, - volume = {34}, - year = {1986}, -} - -@inproceedings{Lee87, - author = {Wai L. Lee and Charles G. Sodini}, - booktitle = {Proc.\ of the IEEE International Symposium on Circuits and Systems}, - location = {Philadelphia, PA, USA}, - month = {05~4--7}, - pages = {459--462}, - title = {A Topology for Higher Order Interpolative Coders}, - vol = {2}, - year = {1987}, -} - -@thesis{KissPhD, - author = {Peter Kiss}, - institution = {Technical University of Timi\c{s}oara, Romania}, - month = {04}, - title = {Adaptive Digital Compensation of Analog Circuit Imperfections for Cascaded Delta-Sigma Analog-to-Digital Converters}, - type = {phdthesis}, - year = {2000}, -} - -@manual{Schreier00, - author = {Richard Schreier}, - month = {01}, - note = {\url{http://www.mathworks.com/matlabcentral/fileexchange/}}, - organization = {Oregon State University}, - title = {The Delta-Sigma Toolbox v5.2}, - year = {2000}, -} - -@misc{DipPortal, - author = {{Budapesti Műszaki és Gazdaságtudományi Egyetem Villamosmérnöki és Informatikai Kar}}, - howpublished = {\url{http://diplomaterv.vik.bme.hu/}}, - title = {Diplomaterv portál (2011. február 26.)}, -} - -@incollection{Mkrtychev:1997, - author = {Mkrtychev, Alexey}, - booktitle = {Logical Foundations of Computer Science}, - doi = {10.1007/3-540-63045-7_27}, - editor = {Adian, Sergei and Nerode, Anil}, - isbn = {978-3-540-63045-6}, - pages = {266-275}, - publisher = {Springer Berlin Heidelberg}, - series = {Lecture Notes in Computer Science}, - title = {Models for the logic of proofs}, - url = {http://dx.doi.org/10.1007/3-540-63045-7_27}, - volume = {1234}, - year = {1997}, -} - -@report{Jeney, - author = {Jeney, Gábor}, - institution = {Budapesti Műszaki és Gazdaságtudományi Egyetem, Híradástechnikai Tanszék}, - location = {Budapest}, - note = {\url{http://www.mcl.hu/~jeneyg/kinezet.pdf}}, - title = {Hogyan néz ki egy igényes dokumentum? {N}éhány szóban az alapvető tipográfiai szabályokról}, - type = {techreport}, - year = {2014}, -} - +@book{Wettl04, + author = {Ferenc Wettl and Gyula Mayer and Péter Szabó}, + publisher = {Panem Könyvkiadó}, + title = {\LaTeX~kézikönyv}, + year = {2004}, +} + +@article{Candy86, + author = {James C. Candy}, + journaltitle = {{IEEE} Trans.\ on Communications}, + month = {01}, + note = {\doi{10.1109/TCOM.1986.1096432}}, + number = {1}, + pages = {72--76}, + title = {Decimation for Sigma Delta Modulation}, + volume = {34}, + year = {1986}, +} + +@inproceedings{Lee87, + author = {Wai L. Lee and Charles G. Sodini}, + booktitle = {Proc.\ of the IEEE International Symposium on Circuits and Systems}, + location = {Philadelphia, PA, USA}, + month = {05~4--7}, + pages = {459--462}, + title = {A Topology for Higher Order Interpolative Coders}, + vol = {2}, + year = {1987}, +} + +@thesis{KissPhD, + author = {Peter Kiss}, + institution = {Technical University of Timi\c{s}oara, Romania}, + month = {04}, + title = {Adaptive Digital Compensation of Analog Circuit Imperfections for Cascaded Delta-Sigma Analog-to-Digital Converters}, + type = {phdthesis}, + year = {2000}, +} + +@manual{Schreier00, + author = {Richard Schreier}, + month = {01}, + note = {\url{http://www.mathworks.com/matlabcentral/fileexchange/}}, + organization = {Oregon State University}, + title = {The Delta-Sigma Toolbox v5.2}, + year = {2000}, +} + +@misc{DipPortal, + author = {{Budapesti Műszaki és Gazdaságtudományi Egyetem Villamosmérnöki és Informatikai Kar}}, + howpublished = {\url{http://diplomaterv.vik.bme.hu/}}, + title = {Diplomaterv portál (2011. február 26.)}, +} + +@incollection{Mkrtychev:1997, + author = {Mkrtychev, Alexey}, + booktitle = {Logical Foundations of Computer Science}, + doi = {10.1007/3-540-63045-7_27}, + editor = {Adian, Sergei and Nerode, Anil}, + isbn = {978-3-540-63045-6}, + pages = {266-275}, + publisher = {Springer Berlin Heidelberg}, + series = {Lecture Notes in Computer Science}, + title = {Models for the logic of proofs}, + url = {http://dx.doi.org/10.1007/3-540-63045-7_27}, + volume = {1234}, + year = {1997}, +} + +@report{Jeney, + author = {Jeney, Gábor}, + institution = {Budapesti Műszaki és Gazdaságtudományi Egyetem, Híradástechnikai Tanszék}, + location = {Budapest}, + note = {\url{http://www.mcl.hu/~jeneyg/kinezet.pdf}}, + title = {Hogyan néz ki egy igényes dokumentum? {N}éhány szóban az alapvető tipográfiai szabályokról}, + type = {techreport}, + year = {2014}, +} + diff --git a/projs/docs/thesis/plan/src/content/description.tex b/projs/docs/thesis/plan/src/content/description.tex index 41bc0cb5..3d46b236 100644 --- a/projs/docs/thesis/plan/src/content/description.tex +++ b/projs/docs/thesis/plan/src/content/description.tex @@ -1,47 +1,47 @@ -\chapter{Disclaimer} - -This document only describes the ideas that I plan to explore in my thesis. -This is not the final project description for the thesis. - -\chapter{Overview} - -The idea behind the project is to establish the base for a game engine. -What this means is that the end product is not something that can compete with the likes of Unity and Unreal engine. -The goal is to lay the foundation for something that could compete in the future. -This means that the project will need to make crutial decisions on what frameworks libraries to use, and how the core of the engine should be architected. - -The planned engine is the spiritual successor to my old engine called ShadowEngine. -This means that some parts of the old codebase will be used but every line will have to be rigorously checked. -This project is not a one person project, I'm planning on involving friends of mine. My responsibilities and the code that I write will constitute as the thesis. - -\section{Technical information} -The project will be mainly written in C++, but some higher level functionality might be implemented in C# For windowing and interacting with the OS it will use SDL2. -The rendering API is going to be Vulkan. -Our main focus initially is Windows both for development and for running, as that is what all planned participants have access to. - -\chapter{Main tasks} -\section{Build system} -The first question that needs decision for the project is what build system to use. -There are many different C++ build systems. The most common is Cmake and MSBuild. These are both quite capable. -\subsection{Cmake} -Cmake is an old powerful build system. it is capable of building almost anything. It is a generator for make files witch are even older. -Make files and in turn Cmake is highly organized around the actual compilation commands that get run in the end. -This makes them harder to configure. -(Magical strings and bad docs) - -\subsection{MSbuild} -MSbuild is Microsoft's build system, it is quite powerful and has really good integration with Visual Studio. -It is also capable of integrating C# projects to the same workspace. -Sadly MSbuild can only build C++ on Windows witch means we can't support other platforms in the future. -MSbuild is also not supported by other IDEs like Clion meaning it would be a total vendor lock in. - -\subsection{Bazel} -Bazel is a little known build system as it is mostly used by large projects. -It was developed for Google's internal repository, as they keep all of their code in a single monolithic repository. -This means the Bazel is capable of building basically any language (C/C++, Java C# JS/TS, etc.). -Bazel is also capable of managing project dependencies without using Git Submodules. - -\subsection{Decision} -After trying both Msbuild and Bazel the decision was to use Bazel. -Sadly the Clion Bazel plugin has problems on windows, +\chapter{Disclaimer} + +This document only describes the ideas that I plan to explore in my thesis. +This is not the final project description for the thesis. + +\chapter{Overview} + +The idea behind the project is to establish the base for a game engine. +What this means is that the end product is not something that can compete with the likes of Unity and Unreal engine. +The goal is to lay the foundation for something that could compete in the future. +This means that the project will need to make crutial decisions on what frameworks libraries to use, and how the core of the engine should be architected. + +The planned engine is the spiritual successor to my old engine called ShadowEngine. +This means that some parts of the old codebase will be used but every line will have to be rigorously checked. +This project is not a one person project, I'm planning on involving friends of mine. My responsibilities and the code that I write will constitute as the thesis. + +\section{Technical information} +The project will be mainly written in C++, but some higher level functionality might be implemented in C# For windowing and interacting with the OS it will use SDL2. +The rendering API is going to be Vulkan. +Our main focus initially is Windows both for development and for running, as that is what all planned participants have access to. + +\chapter{Main tasks} +\section{Build system} +The first question that needs decision for the project is what build system to use. +There are many different C++ build systems. The most common is Cmake and MSBuild. These are both quite capable. +\subsection{Cmake} +Cmake is an old powerful build system. it is capable of building almost anything. It is a generator for make files witch are even older. +Make files and in turn Cmake is highly organized around the actual compilation commands that get run in the end. +This makes them harder to configure. +(Magical strings and bad docs) + +\subsection{MSbuild} +MSbuild is Microsoft's build system, it is quite powerful and has really good integration with Visual Studio. +It is also capable of integrating C# projects to the same workspace. +Sadly MSbuild can only build C++ on Windows witch means we can't support other platforms in the future. +MSbuild is also not supported by other IDEs like Clion meaning it would be a total vendor lock in. + +\subsection{Bazel} +Bazel is a little known build system as it is mostly used by large projects. +It was developed for Google's internal repository, as they keep all of their code in a single monolithic repository. +This means the Bazel is capable of building basically any language (C/C++, Java C# JS/TS, etc.). +Bazel is also capable of managing project dependencies without using Git Submodules. + +\subsection{Decision} +After trying both Msbuild and Bazel the decision was to use Bazel. +Sadly the Clion Bazel plugin has problems on windows, but theses might be fixable with a few PRs or just shipping our own version of the plugin, as it is available on Github \ No newline at end of file diff --git a/projs/docs/thesis/plan/src/main.tex b/projs/docs/thesis/plan/src/main.tex index 70f50e0a..0944ddaf 100644 --- a/projs/docs/thesis/plan/src/main.tex +++ b/projs/docs/thesis/plan/src/main.tex @@ -1,99 +1,99 @@ -\documentclass[11pt,a4paper,oneside]{report} % Single-side -%\documentclass[11pt,a4paper,twoside,openright]{report} % Duplex - -\input{includes/packages} - -%TODO Set the main variables -\newcommand{\vikszerzoVezeteknev}{Gipsz} -\newcommand{\vikszerzoKeresztnev}{Jakab} - -\newcommand{\vikkonzulensAMegszolitas}{dr.~} -\newcommand{\vikkonzulensAVezeteknev}{Konzulens} -\newcommand{\vikkonzulensAKeresztnev}{Egy} - -\newcommand{\vikkonzulensBMegszolitas}{} -\newcommand{\vikkonzulensBVezeteknev}{Konzulens} -\newcommand{\vikkonzulensBKeresztnev}{Kettő} - -\newcommand{\vikkonzulensCMegszolitas}{} -\newcommand{\vikkonzulensCVezeteknev}{} -\newcommand{\vikkonzulensCKeresztnev}{} - -\newcommand{\vikcim}{Shadow game engine} % Cím -\newcommand{\viktanszek}{\bmemit} % Tanszék -\newcommand{\vikdoktipus}{\bsc} % Dokumentum típusa (\bsc vagy \msc) -\newcommand{\vikmunkatipusat}{szakdolgozatot} % a "hallgató nyilatkozat" részhez: szakdolgozatot vagy diplomatervet - -\input{includes/tdk-variables} -\newcommand{\szerzoMeta}{\vikszerzoVezeteknev{} \vikszerzoKeresztnev} % egy szerző esetén -%\newcommand{\szerzoMeta}{\vikszerzoVezeteknev{} \vikszerzoKeresztnev, \tdkszerzoB} % két szerző esetén - -%TODO Language configuration -- choose one -% Beállítások magyar nyelvű dolgozathoz -%\input{includes/thesis-hu} -% Settings for English documents -\input{includes/thesis-en} - -\input{includes/preamble} - -%-------------------------------------------------------------------------------------- -% Table of contents and the main text -%-------------------------------------------------------------------------------------- -\begin{document} - -\pagenumbering{gobble} - -\selectthesislanguage - -%TODO Titlepage -- choose one from below -%~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -\include{includes/titlepage} % Szakdolgozat/Diplomaterv címlap -%\include{include/titlepage-tdk} % TDK címlap -%\include{include/titlepage-otdk} % OTDK címlap - - -% Table of Contents -%~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -\tableofcontents\cleardoublepage - - -% Declaration and Abstract -%~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -\include{includes/declaration} %TODO Hallgatói nyilatkozat -- TDK és OTDK esetén törlendő! -%\include{content/abstract} %TODO Összefoglaló -- TDK és OTDK esetén nem kötelező - - -% The main part of the thesis -%~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -\pagenumbering{arabic} - -%TODO import your own content -\include{content/description} -%\include{content/latex-tools} -%\include{content/thesis-format} -%\include{content/template-usage} - - -% Acknowledgements -%~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -%\include{content/acknowledgement} - - -% List of Figures, Tables -%~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -%\listoffigures\addcontentsline{toc}{chapter}{\listfigurename} -%\listoftables\addcontentsline{toc}{chapter}{\listtablename} - - -% Bibliography -%~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -%\addcontentsline{toc}{chapter}{\bibname} -%\bibliography{bib/mybib} - - -% Appendix -%~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -%\include{content/appendices} - -%\label{page:last} -\end{document} +\documentclass[11pt,a4paper,oneside]{report} % Single-side +%\documentclass[11pt,a4paper,twoside,openright]{report} % Duplex + +\input{includes/packages} + +%TODO Set the main variables +\newcommand{\vikszerzoVezeteknev}{Gipsz} +\newcommand{\vikszerzoKeresztnev}{Jakab} + +\newcommand{\vikkonzulensAMegszolitas}{dr.~} +\newcommand{\vikkonzulensAVezeteknev}{Konzulens} +\newcommand{\vikkonzulensAKeresztnev}{Egy} + +\newcommand{\vikkonzulensBMegszolitas}{} +\newcommand{\vikkonzulensBVezeteknev}{Konzulens} +\newcommand{\vikkonzulensBKeresztnev}{Kettő} + +\newcommand{\vikkonzulensCMegszolitas}{} +\newcommand{\vikkonzulensCVezeteknev}{} +\newcommand{\vikkonzulensCKeresztnev}{} + +\newcommand{\vikcim}{Shadow game engine} % Cím +\newcommand{\viktanszek}{\bmemit} % Tanszék +\newcommand{\vikdoktipus}{\bsc} % Dokumentum típusa (\bsc vagy \msc) +\newcommand{\vikmunkatipusat}{szakdolgozatot} % a "hallgató nyilatkozat" részhez: szakdolgozatot vagy diplomatervet + +\input{includes/tdk-variables} +\newcommand{\szerzoMeta}{\vikszerzoVezeteknev{} \vikszerzoKeresztnev} % egy szerző esetén +%\newcommand{\szerzoMeta}{\vikszerzoVezeteknev{} \vikszerzoKeresztnev, \tdkszerzoB} % két szerző esetén + +%TODO Language configuration -- choose one +% Beállítások magyar nyelvű dolgozathoz +%\input{includes/thesis-hu} +% Settings for English documents +\input{includes/thesis-en} + +\input{includes/preamble} + +%-------------------------------------------------------------------------------------- +% Table of contents and the main text +%-------------------------------------------------------------------------------------- +\begin{document} + +\pagenumbering{gobble} + +\selectthesislanguage + +%TODO Titlepage -- choose one from below +%~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +\include{includes/titlepage} % Szakdolgozat/Diplomaterv címlap +%\include{include/titlepage-tdk} % TDK címlap +%\include{include/titlepage-otdk} % OTDK címlap + + +% Table of Contents +%~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +\tableofcontents\cleardoublepage + + +% Declaration and Abstract +%~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +\include{includes/declaration} %TODO Hallgatói nyilatkozat -- TDK és OTDK esetén törlendő! +%\include{content/abstract} %TODO Összefoglaló -- TDK és OTDK esetén nem kötelező + + +% The main part of the thesis +%~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +\pagenumbering{arabic} + +%TODO import your own content +\include{content/description} +%\include{content/latex-tools} +%\include{content/thesis-format} +%\include{content/template-usage} + + +% Acknowledgements +%~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +%\include{content/acknowledgement} + + +% List of Figures, Tables +%~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +%\listoffigures\addcontentsline{toc}{chapter}{\listfigurename} +%\listoftables\addcontentsline{toc}{chapter}{\listtablename} + + +% Bibliography +%~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +%\addcontentsline{toc}{chapter}{\bibname} +%\bibliography{bib/mybib} + + +% Appendix +%~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +%\include{content/appendices} + +%\label{page:last} +\end{document} diff --git a/projs/shadow/CMakeLists.txt b/projs/shadow/CMakeLists.txt new file mode 100644 index 00000000..40eaa234 --- /dev/null +++ b/projs/shadow/CMakeLists.txt @@ -0,0 +1,33 @@ +project(shadow) + +include(FetchContent) + +# External code +add_subdirectory(extern/dxmath) +add_subdirectory(extern/glm) +SET(SPDLOG_BUILD_PIC true) +add_subdirectory(extern/spdlog) +add_subdirectory(extern/dylib) +add_subdirectory(extern/vulkan_memory_allocator) +add_subdirectory(extern/catch2) + +if (WIN32) + # Fetch SDL for the runtime + FetchContent_Declare( + SDL2 + URL https://www.libsdl.org/release/SDL2-devel-2.26.5-VC.zip + ) + FetchContent_MakeAvailable(SDL2) + set(SDL2_DIR ${sdl2_SOURCE_DIR}) + list(PREPEND CMAKE_PREFIX_PATH "${sdl2_SOURCE_DIR}/cmake") + +endif () + +# Core engine +add_subdirectory(shadow-engine) + +# Runtime executable +add_subdirectory(shadow-runtime) + +# Editor executable +add_subdirectory(shadow-editor) \ No newline at end of file diff --git a/projs/shadow/README.md b/projs/shadow/README.md new file mode 100644 index 00000000..9f36073b --- /dev/null +++ b/projs/shadow/README.md @@ -0,0 +1,23 @@ +# Shadow Engine + + +## Folder structure +``` +/shadow +|- /extern +| |- /catch2 +| |- /dxmath +| |- /dylib +| |- /glm +| |- /imgui +| |- /spdlog +| |- /vulkan_memory_allocators +|- /platforms +| |- /dx12 Files needed for dx12 agility pack [1] +|- /shadow-editor +| |- /inc +| |- /src +|- /shadow-engine +| |- files for each bigger module +|- /shadow-runtime +``` \ No newline at end of file diff --git a/projs/shadow/extern/catch2 b/projs/shadow/extern/catch2 new file mode 160000 index 00000000..9c541ca7 --- /dev/null +++ b/projs/shadow/extern/catch2 @@ -0,0 +1 @@ +Subproject commit 9c541ca72e7857dec71d8a41b97e42c2f1c92602 diff --git a/projs/shadow/extern/dxmath b/projs/shadow/extern/dxmath new file mode 160000 index 00000000..58f045a6 --- /dev/null +++ b/projs/shadow/extern/dxmath @@ -0,0 +1 @@ +Subproject commit 58f045a6caaaad6ce15049bba3cd075ed419c85e diff --git a/projs/shadow/extern/dylib b/projs/shadow/extern/dylib new file mode 160000 index 00000000..c5b46c65 --- /dev/null +++ b/projs/shadow/extern/dylib @@ -0,0 +1 @@ +Subproject commit c5b46c650a252bcda0dd94a102cdfc85907b9022 diff --git a/projs/shadow/extern/glm b/projs/shadow/extern/glm new file mode 160000 index 00000000..47585fde --- /dev/null +++ b/projs/shadow/extern/glm @@ -0,0 +1 @@ +Subproject commit 47585fde0c49fa77a2bf2fb1d2ead06999fd4b6e diff --git a/projs/shadow/extern/imgui b/projs/shadow/extern/imgui new file mode 160000 index 00000000..762ec445 --- /dev/null +++ b/projs/shadow/extern/imgui @@ -0,0 +1 @@ +Subproject commit 762ec445e63a95c1545b18b28d528f8ce38a9afd diff --git a/projs/shadow/extern/spdlog b/projs/shadow/extern/spdlog new file mode 160000 index 00000000..cedfeeb9 --- /dev/null +++ b/projs/shadow/extern/spdlog @@ -0,0 +1 @@ +Subproject commit cedfeeb95f3af11df7d3b1e7e0d3b86b334dc23b diff --git a/projs/shadow/extern/vulkan_memory_allocator b/projs/shadow/extern/vulkan_memory_allocator new file mode 160000 index 00000000..e88fff95 --- /dev/null +++ b/projs/shadow/extern/vulkan_memory_allocator @@ -0,0 +1 @@ +Subproject commit e88fff957b94f4b541ccac67a4290f07e52aa610 diff --git a/projs/shadow/platforms/dx12/dx12_agility.cpp b/projs/shadow/platforms/dx12/dx12_agility.cpp new file mode 100644 index 00000000..3cf4b33a --- /dev/null +++ b/projs/shadow/platforms/dx12/dx12_agility.cpp @@ -0,0 +1,6 @@ + +#include + +extern "C" { __declspec(dllexport) extern const uint32_t D3D12SDKVersion = 4; } + +extern "C" { __declspec(dllexport) extern const char8_t *D3D12SDKPath = u8".\\D3D12\\"; } \ No newline at end of file diff --git a/projs/shadow/shadow-editor/CMakeLists.txt b/projs/shadow/shadow-editor/CMakeLists.txt index c98bf417..d84ef22e 100644 --- a/projs/shadow/shadow-editor/CMakeLists.txt +++ b/projs/shadow/shadow-editor/CMakeLists.txt @@ -1,21 +1,38 @@ -set(CMAKE_CXX_STANDARD 20) -find_package(SDL2 CONFIG REQUIRED) - -FILE(GLOB_RECURSE SOURCES src/*.cpp inc/*.h) - -add_executable(shadow-editor ${SOURCES}) - -target_include_directories(shadow-editor - PUBLIC inc/ - PRIVATE ${SDL2_INCLUDE_DIRS}) -target_link_libraries(shadow-editor PRIVATE SDL2::SDL2main PUBLIC shadow-engine) - -add_custom_command(TARGET shadow-editor POST_BUILD - COMMAND ${CMAKE_COMMAND} -E copy $ $ - COMMAND_EXPAND_LISTS - ) - -add_custom_command(TARGET shadow-editor - POST_BUILD - COMMAND ${CMAKE_COMMAND} -E copy_directory ${CMAKE_CURRENT_SOURCE_DIR}/vlkx-resources ${CMAKE_CURRENT_BINARY_DIR}/vlkx-resources - ) \ No newline at end of file +set(CMAKE_CXX_STANDARD 20) +find_package(SDL2 CONFIG REQUIRED) + +add_executable(shadow-editor) +add_executable(shadow::editor ALIAS shadow-editor) + + +FILE(GLOB_RECURSE SOURCES + src/*.cpp +) + +target_sources(shadow-editor PUBLIC ${SOURCES}) + +target_include_directories(shadow-editor + PUBLIC inc/ + PRIVATE ${SDL2_INCLUDE_DIRS}) + +target_link_libraries(shadow-editor + PRIVATE SDL2::SDL2main + PUBLIC shadow-engine +) + +target_link_options(shadow-editor + PRIVATE -Wl,--export-dynamic +) + +add_custom_command(TARGET shadow-editor + POST_BUILD + COMMAND ${CMAKE_COMMAND} -E copy_directory ${CMAKE_CURRENT_SOURCE_DIR}/vlkx-resources ${CMAKE_CURRENT_BINARY_DIR}/vlkx-resources +) + +if (WIN32) + add_custom_command(TARGET shadow-editor + POST_BUILD + COMMAND ${CMAKE_COMMAND} -E copy $ $ + COMMAND_EXPAND_LISTS + ) +endif () \ No newline at end of file diff --git a/projs/shadow/shadow-editor/inc/EditorModule.h b/projs/shadow/shadow-editor/inc/EditorModule.h index c8fafca5..0ec2e3f1 100644 --- a/projs/shadow/shadow-editor/inc/EditorModule.h +++ b/projs/shadow/shadow-editor/inc/EditorModule.h @@ -1,36 +1,36 @@ -#pragma once - -#include "core/Module.h" -#include "EditorWindow.h" -#include "core/ShadowApplication.h" - -#include - -namespace ShadowEngine::Editor { - - class Menu { - public: - std::function clk; - }; - - class EditorModule : public ShadowEngine::Module { - SHObject_Base(EditorModule) - - std::vector> windows; - - std::map menus; - - public: - EditorModule() {} - - void RegisterMenu(std::string path, Menu m); - - void OverlayRender(SH::Events::OverlayRender &); - - void DrawMenu(); - - private: - void Init() override; - - }; +#pragma once + +#include "shadow/core/Module.h" +#include "EditorWindow.h" +#include "shadow/core/ShadowApplication.h" + +#include + +namespace SH::Editor { + + class Menu { + public: + std::function clk; + }; + + class EXPORT EditorModule : public SH::Module { + SHObject_Base(EditorModule) + + std::vector> windows; + + std::map menus; + + public: + EditorModule() {} + + void RegisterMenu(std::string path, Menu m); + + void OverlayRender(SH::Events::OverlayRender &); + + void DrawMenu(); + + private: + void Init() override; + + }; } \ No newline at end of file diff --git a/projs/shadow/shadow-editor/inc/EditorWindow.h b/projs/shadow/shadow-editor/inc/EditorWindow.h index b2c51bea..2c043edf 100644 --- a/projs/shadow/shadow-editor/inc/EditorWindow.h +++ b/projs/shadow/shadow-editor/inc/EditorWindow.h @@ -1,16 +1,16 @@ -// -// Created by dpete on 07/12/2022. -// -#pragma once - -#include "SHObject.h" - -namespace ShadowEngine::Editor { - - class EditorWindow : public ShadowEngine::SHObject{ - SHObject_Base(EditorWindow) - public: - virtual void Draw()= 0; - }; - -} +// +// Created by dpete on 07/12/2022. +// +#pragma once + +#include "shadow/SHObject.h" + +namespace SH::Editor { + + class EditorWindow : public SH::SHObject{ + SHObject_Base(EditorWindow) + public: + virtual void Draw()= 0; + }; + +} diff --git a/projs/shadow/shadow-editor/inc/windows/DebugWindows.h b/projs/shadow/shadow-editor/inc/windows/DebugWindows.h index c0e6bf61..f33517bc 100644 --- a/projs/shadow/shadow-editor/inc/windows/DebugWindows.h +++ b/projs/shadow/shadow-editor/inc/windows/DebugWindows.h @@ -1,20 +1,20 @@ - -#pragma once - -#include "../EditorWindow.h" -#include "debug/DebugModule.h" - -namespace ShadowEngine::Editor { - - class DebugWindows : public EditorWindow { - SHObject_Base(DebugWindows) - - std::weak_ptr debugModule; - - public: - DebugWindows(); - - void Draw() override; - }; - -} + +#pragma once + +#include "../EditorWindow.h" +#include "shadow/debug/DebugModule.h" + +namespace SH::Editor { + + class DebugWindows : public EditorWindow { + SHObject_Base(DebugWindows) + + std::weak_ptr debugModule; + + public: + DebugWindows(); + + void Draw() override; + }; + +} diff --git a/projs/shadow/shadow-editor/inc/windows/SceneView.h b/projs/shadow/shadow-editor/inc/windows/SceneView.h index a3711b48..f0edba52 100644 --- a/projs/shadow/shadow-editor/inc/windows/SceneView.h +++ b/projs/shadow/shadow-editor/inc/windows/SceneView.h @@ -1,19 +1,20 @@ -#pragma once - -#include "../EditorWindow.h" -#include "vlkx/vulkan/VulkanModule.h" - -namespace ShadowEngine::Editor { - - class SceneView : public EditorWindow{ - SHObject_Base(SceneView) - - VulkanModule* renderer; - - public: - SceneView(); - - void Draw() override; - }; - +#pragma once + +#include +#include "../EditorWindow.h" +#include "shadow/renderer/vlkx/vulkan/VulkanModule.h" + +namespace SH::Editor { + + class SceneView : public EditorWindow{ + SHObject_Base(SceneView) + + std::shared_ptr renderer; + + public: + SceneView(); + + void Draw() override; + }; + } \ No newline at end of file diff --git a/projs/shadow/shadow-editor/src/EditorModule.cpp b/projs/shadow/shadow-editor/src/EditorModule.cpp index a8c76f43..fb2aa73f 100644 --- a/projs/shadow/shadow-editor/src/EditorModule.cpp +++ b/projs/shadow/shadow-editor/src/EditorModule.cpp @@ -1,93 +1,93 @@ -#include "../inc/EditorModule.h" -#include -#include - -#include "windows/SceneView.h" -#include "windows/DebugWindows.h" -#include "string-helpers.h" -#include "core/module-manager-v2.h" - -namespace ShadowEngine::Editor { - - SHObject_Base_Impl(EditorModule) - - MODULE_ENTRY(ShadowEngine::Editor::EditorModule, EditorModule) - - void EditorModule::OverlayRender(SH::Events::OverlayRender &) { - static bool dockspaceOpen = true; - - ImGuiWindowFlags window_flags = ImGuiWindowFlags_MenuBar | ImGuiWindowFlags_NoDocking; - static ImGuiDockNodeFlags dockspace_flags = ImGuiDockNodeFlags_None; - - ImGuiViewport *viewport = ImGui::GetMainViewport(); - ImGui::SetNextWindowPos(viewport->Pos); - ImGui::SetNextWindowSize(viewport->Size); - ImGui::SetNextWindowViewport(viewport->ID); - ImGui::PushStyleVar(ImGuiStyleVar_WindowRounding, 0.0f); - ImGui::PushStyleVar(ImGuiStyleVar_WindowBorderSize, 0.0f); - window_flags |= ImGuiWindowFlags_NoTitleBar | ImGuiWindowFlags_NoCollapse | ImGuiWindowFlags_NoResize - | ImGuiWindowFlags_NoMove; - window_flags |= ImGuiWindowFlags_NoBringToFrontOnFocus | ImGuiWindowFlags_NoNavFocus; - - ImGui::PushStyleVar(ImGuiStyleVar_WindowPadding, ImVec2(0.0f, 0.0f)); - ImGui::Begin("DockSpace Demo", &dockspaceOpen, window_flags); - ImGui::PopStyleVar(3); - - // DockSpace - ImGuiIO &io = ImGui::GetIO(); - ImGuiStyle &style = ImGui::GetStyle(); - float minWinSizeX = style.WindowMinSize.x; - style.WindowMinSize.x = 370.0f; - if (io.ConfigFlags & ImGuiConfigFlags_DockingEnable) { - ImGuiID dockspace_id = ImGui::GetID("MyDockSpace"); - ImGui::DockSpace(dockspace_id, ImVec2(0.0f, 0.0f), dockspace_flags); - } - - if (ImGui::BeginMenuBar()) { - DrawMenu(); - - ImGui::EndMenuBar(); - } - - for (int i = 0; i < windows.size(); ++i) { - windows[i]->Draw(); - } - - ImGui::End(); - } - - void EditorModule::DrawMenu() { - - for (const auto &menu : this->menus) { - std::vector menu_path = - explode(menu.first, '/'); - - int depth = 0; - for (; depth < menu_path.size() - 1; ++depth) { - if (!ImGui::BeginMenu(menu_path[depth].c_str())) { - break; - } - } - if (depth == menu_path.size() - 1) - if (ImGui::MenuItem(menu_path.back().c_str())) - menu.second.clk(); - - for (; depth > 0; depth--) { - ImGui::EndMenu(); - } - } - } - - void EditorModule::Init() { - ShadowEngine::ShadowApplication::Get().GetEventBus() - .subscribe(this, &EditorModule::OverlayRender); - - windows.push_back(std::make_shared()); - windows.push_back(std::make_shared()); - } - - void EditorModule::RegisterMenu(std::string path, Menu m) { - menus.emplace(path, m); - } - +#include "../inc/EditorModule.h" +#include +#include + +#include "windows/SceneView.h" +#include "windows/DebugWindows.h" +#include "shadow/util/string-helpers.h" +#include "shadow/core/module-manager-v2.h" + +namespace SH::Editor { + + SHObject_Base_Impl(EditorModule) + + MODULE_ENTRY(SH::Editor::EditorModule, EditorModule) + + void EditorModule::OverlayRender(SH::Events::OverlayRender &) { + static bool dockspaceOpen = true; + + ImGuiWindowFlags window_flags = ImGuiWindowFlags_MenuBar | ImGuiWindowFlags_NoDocking; + static ImGuiDockNodeFlags dockspace_flags = ImGuiDockNodeFlags_None; + + ImGuiViewport *viewport = ImGui::GetMainViewport(); + ImGui::SetNextWindowPos(viewport->Pos); + ImGui::SetNextWindowSize(viewport->Size); + ImGui::SetNextWindowViewport(viewport->ID); + ImGui::PushStyleVar(ImGuiStyleVar_WindowRounding, 0.0f); + ImGui::PushStyleVar(ImGuiStyleVar_WindowBorderSize, 0.0f); + window_flags |= ImGuiWindowFlags_NoTitleBar | ImGuiWindowFlags_NoCollapse | ImGuiWindowFlags_NoResize + | ImGuiWindowFlags_NoMove; + window_flags |= ImGuiWindowFlags_NoBringToFrontOnFocus | ImGuiWindowFlags_NoNavFocus; + + ImGui::PushStyleVar(ImGuiStyleVar_WindowPadding, ImVec2(0.0f, 0.0f)); + ImGui::Begin("DockSpace Demo", &dockspaceOpen, window_flags); + ImGui::PopStyleVar(3); + + // DockSpace + ImGuiIO &io = ImGui::GetIO(); + ImGuiStyle &style = ImGui::GetStyle(); + float minWinSizeX = style.WindowMinSize.x; + style.WindowMinSize.x = 370.0f; + if (io.ConfigFlags & ImGuiConfigFlags_DockingEnable) { + ImGuiID dockspace_id = ImGui::GetID("MyDockSpace"); + ImGui::DockSpace(dockspace_id, ImVec2(0.0f, 0.0f), dockspace_flags); + } + + if (ImGui::BeginMenuBar()) { + DrawMenu(); + + ImGui::EndMenuBar(); + } + + for (int i = 0; i < windows.size(); ++i) { + windows[i]->Draw(); + } + + ImGui::End(); + } + + void EditorModule::DrawMenu() { + + for (const auto &menu : this->menus) { + std::vector menu_path = + SH::Util::Str::explode(menu.first, '/'); + + int depth = 0; + for (; depth < menu_path.size() - 1; ++depth) { + if (!ImGui::BeginMenu(menu_path[depth].c_str())) { + break; + } + } + if (depth == menu_path.size() - 1) + if (ImGui::MenuItem(menu_path.back().c_str())) + menu.second.clk(); + + for (; depth > 0; depth--) { + ImGui::EndMenu(); + } + } + } + + void EditorModule::Init() { + SH::ShadowApplication::Get().GetEventBus() + .subscribe(this, &EditorModule::OverlayRender); + + windows.push_back(std::make_shared()); + windows.push_back(std::make_shared()); + } + + void EditorModule::RegisterMenu(std::string path, Menu m) { + menus.emplace(path, m); + } + } \ No newline at end of file diff --git a/projs/shadow/shadow-editor/src/EditorWindow.cpp b/projs/shadow/shadow-editor/src/EditorWindow.cpp index 20d1a95a..81755388 100644 --- a/projs/shadow/shadow-editor/src/EditorWindow.cpp +++ b/projs/shadow/shadow-editor/src/EditorWindow.cpp @@ -1,5 +1,5 @@ -#include "../inc/EditorWindow.h" - -namespace ShadowEngine::Editor { - SHObject_Base_Impl(EditorWindow) +#include "../inc/EditorWindow.h" + +namespace SH::Editor { + SHObject_Base_Impl(EditorWindow) } \ No newline at end of file diff --git a/projs/shadow/shadow-editor/src/main.cpp b/projs/shadow/shadow-editor/src/main.cpp index 03605154..d92a638d 100644 --- a/projs/shadow/shadow-editor/src/main.cpp +++ b/projs/shadow/shadow-editor/src/main.cpp @@ -1,36 +1,46 @@ -#include "core/ShadowApplication.h" -#include "../inc/EditorModule.h" - -#include -#include -#include - -int main(int argc, char *argv[]) { - std::cout << "argc == " << argc << '\n'; - - for (int ndx{}; ndx != argc; ++ndx) { - std::cout << "argv[" << ndx << "] == " << std::quoted(argv[ndx]) << '\n'; - } - std::cout << "argv[" << argc << "] == " << static_cast(argv[argc]) << '\n'; - /*...*/ - - ShadowEngine::ShadowApplication app(argc, argv); - app.GetModuleManager().AddAssembly({.id="assembly:/shadow-editor", .path="shadow-editor.exe", .type=ShadowEngine::AssemblyType::EXE}); - app.GetModuleManager().LoadModulesFromAssembly("assembly:/shadow-editor"); - app.Init(); - app.Start(); - - return argc == 3 ? EXIT_SUCCESS : EXIT_FAILURE; // optional return value -} - -extern "C" { -void assembly_entry(ShadowEngine::ModuleManager &m) { - m.AddDescriptors({ - .id="module:/editor", - .name = "Editor", - .class_name = "EditorModule", - .assembly="assembly:/shadow-editor", - .dependencies={"module:/platform/sdl2"}, - }); -} -} \ No newline at end of file +#include "shadow/core/ShadowApplication.h" +#include "runtime/Runtime.h" + +#include "EditorModule.h" + +#include +#include +#include + +int main(int argc, char *argv[]) { + RUNTIME_BOOT(); + + std::cout << "CWD: " << (char *) std::filesystem::current_path().c_str() << '\n'; + + std::cout << "argc == " << argc << '\n'; + + for (int ndx{}; ndx != argc; ++ndx) { + std::cout << "argv[" << ndx << "] == " << std::quoted(argv[ndx]) << '\n'; + } + std::cout << "argv[" << argc << "] == " << static_cast(argv[argc]) << '\n'; + /*...*/ + + SH::ShadowApplication app(argc, argv); + app.GetModuleManager().LoadModulesFromAssembly("assembly:/shadow-editor"_id); + app.Init(); + app.Start(); + + return argc == 3 ? EXIT_SUCCESS : EXIT_FAILURE; // optional return value +} + +extern "C" { +#pragma clang diagnostic push +#pragma ide diagnostic ignored "OCInconsistentNamingInspection" +[[maybe_unused]] EXPORT void assembly_entry(SH::ModuleManager &m) { + m.AddDescriptors({ + .id="module:/editor", + .name = "Editor", + .class_name = "EditorModule", + .assembly="assembly:/shadow-editor"_id, + .dependencies={"module:/platform/sdl2"}, + }); +} +#pragma clang diagnostic pop +} + + diff --git a/projs/shadow/shadow-editor/src/windows/DebugWindows.cpp b/projs/shadow/shadow-editor/src/windows/DebugWindows.cpp index fbdc5c53..4ed3e0f9 100644 --- a/projs/shadow/shadow-editor/src/windows/DebugWindows.cpp +++ b/projs/shadow/shadow-editor/src/windows/DebugWindows.cpp @@ -1,40 +1,40 @@ -#include "../../inc/windows/DebugWindows.h" -#include "imgui.h" -#include "core/ShadowApplication.h" -#include "../../inc/EditorModule.h" - -namespace ShadowEngine::Editor { - - SHObject_Base_Impl(DebugWindows) - - DebugWindows::DebugWindows() { - ShadowApplication &application = ShadowEngine::ShadowApplication::Get(); - - debugModule = application.GetModuleManager().GetById("module:/debug"); - - auto e = application.GetModuleManager().GetById("module:/editor"); - if (e.expired()) - return; - - auto editormodule = e.lock(); - - editormodule->RegisterMenu("Windows/Modules List", Menu{ - .clk=[this]() { - debugModule.lock()->w_modules = true; - }}); - editormodule->RegisterMenu("Windows/Time info", Menu{ - .clk=[this]() { - debugModule.lock()->w_time = true; - }}); - editormodule->RegisterMenu("Windows/ImGUI Demo", Menu{ - .clk=[this]() { - debugModule.lock()->w_imguiDemo = true; - }}); - } - - void DebugWindows::Draw() { - debugModule.lock()->DrawModuleWindow(); - debugModule.lock()->DrawTimeWindow(); - debugModule.lock()->DrawImguiDemo(); - } +#include "../../inc/windows/DebugWindows.h" +#include "imgui.h" +#include "shadow/core/ShadowApplication.h" +#include "../../inc/EditorModule.h" + +namespace SH::Editor { + + SHObject_Base_Impl(DebugWindows) + + DebugWindows::DebugWindows() { + ShadowApplication &application = SH::ShadowApplication::Get(); + + debugModule = application.GetModuleManager().GetById("module:/debug"); + + auto e = application.GetModuleManager().GetById("module:/editor"); + if (e.expired()) + return; + + auto editormodule = e.lock(); + + editormodule->RegisterMenu("Windows/Modules List", Menu{ + .clk=[this]() { + debugModule.lock()->w_modules = true; + }}); + editormodule->RegisterMenu("Windows/Time info", Menu{ + .clk=[this]() { + debugModule.lock()->w_time = true; + }}); + editormodule->RegisterMenu("Windows/ImGUI Demo", Menu{ + .clk=[this]() { + debugModule.lock()->w_imguiDemo = true; + }}); + } + + void DebugWindows::Draw() { + debugModule.lock()->DrawModuleWindow(); + debugModule.lock()->DrawTimeWindow(); + debugModule.lock()->DrawImguiDemo(); + } } \ No newline at end of file diff --git a/projs/shadow/shadow-editor/src/windows/SceneView.cpp b/projs/shadow/shadow-editor/src/windows/SceneView.cpp index 51925b07..0c2f0b6f 100644 --- a/projs/shadow/shadow-editor/src/windows/SceneView.cpp +++ b/projs/shadow/shadow-editor/src/windows/SceneView.cpp @@ -1,32 +1,32 @@ -#include "../../inc/windows/SceneView.h" -#include "imgui.h" -#include "core/ShadowApplication.h" -#include "vlkx/vulkan/VulkanModule.h" -#include "glm/vec2.hpp" - -namespace ShadowEngine::Editor { - - SHObject_Base_Impl(SceneView) - - SceneView::SceneView() { - //renderer = ShadowEngine::ShadowApplication::Get().GetModuleManager().GetModuleByType(); - } - - void SceneView::Draw() { - static bool active = false; - if (ImGui::Begin("Game View", &active, ImGuiWindowFlags_None)) { - /* - ImVec2 viewportPanelSize = ImGui::GetContentRegionAvail(); - glm::vec2 m_ViewportSize = {viewportPanelSize.x, viewportPanelSize.y}; - - ImGui::Image((ImTextureID) renderer->getEditorRenderPlanes(), - ImVec2{m_ViewportSize.x, m_ViewportSize.y}, - ImVec2{0, 0}, - ImVec2{1, 1}); - */ - } - - ImGui::End(); - } - +#include "../../inc/windows/SceneView.h" +#include "imgui.h" +#include "shadow/core/ShadowApplication.h" +#include "shadow/renderer/vlkx/vulkan/VulkanModule.h" +#include "glm/vec2.hpp" + +namespace SH::Editor { + + SHObject_Base_Impl(SceneView) + + SceneView::SceneView() { + renderer = SH::ShadowApplication::Get().GetModuleManager().GetById("module:/renderer/vulkan").lock(); + } + + void SceneView::Draw() { + static bool active = false; + if (ImGui::Begin("Game View", &active, ImGuiWindowFlags_None)) { + + ImVec2 viewportPanelSize = ImGui::GetContentRegionAvail(); + glm::vec2 m_ViewportSize = {viewportPanelSize.x, viewportPanelSize.y}; + + ImGui::Image((ImTextureID) renderer->getEditorRenderPlanes(), + ImVec2{m_ViewportSize.x, m_ViewportSize.y}, + ImVec2{0, 0}, + ImVec2{1, 1}); + + } + + ImGui::End(); + } + } \ No newline at end of file diff --git a/projs/shadow/shadow-editor/vlkx-resources/shader/basic.frag b/projs/shadow/shadow-editor/vlkx-resources/shader/basic.frag index db7f6f58..65ae8c54 100644 --- a/projs/shadow/shadow-editor/vlkx-resources/shader/basic.frag +++ b/projs/shadow/shadow-editor/vlkx-resources/shader/basic.frag @@ -1,9 +1,9 @@ -#version 450 -#extension GL_ARB_separate_shader_objects : enable - -layout (location = 0) in vec3 fragColor; -layout (location = 0) out vec4 outColor; - -void main() { - outColor = vec4(fragColor, 1.0f); +#version 450 +#extension GL_ARB_separate_shader_objects : enable + +layout (location = 0) in vec3 fragColor; +layout (location = 0) out vec4 outColor; + +void main() { + outColor = vec4(fragColor, 1.0f); } \ No newline at end of file diff --git a/projs/shadow/shadow-editor/vlkx-resources/shader/basic.vert b/projs/shadow/shadow-editor/vlkx-resources/shader/basic.vert index 64500f83..0569d2ba 100644 --- a/projs/shadow/shadow-editor/vlkx-resources/shader/basic.vert +++ b/projs/shadow/shadow-editor/vlkx-resources/shader/basic.vert @@ -1,20 +1,20 @@ -#version 450 -#extension GL_ARB_separate_shader_objects : enable - -layout (binding = 0) uniform UniformBufferObject{ - mat4 model; - mat4 view; - mat4 proj; -} ubo; - -layout (location = 0) in vec3 inPosition; -layout (location = 1) in vec3 inNormal; -layout (location = 2) in vec3 inColor; -layout (location = 3) in vec2 inUV; - -layout (location = 0) out vec3 fragColor; - -void main() { - gl_Position = ubo.proj * ubo.view * ubo.model * vec4(inPosition, 1.0); - fragColor = inColor; +#version 450 +#extension GL_ARB_separate_shader_objects : enable + +layout (binding = 0) uniform UniformBufferObject{ + mat4 model; + mat4 view; + mat4 proj; +} ubo; + +layout (location = 0) in vec3 inPosition; +layout (location = 1) in vec3 inNormal; +layout (location = 2) in vec3 inColor; +layout (location = 3) in vec2 inUV; + +layout (location = 0) out vec3 fragColor; + +void main() { + gl_Position = ubo.proj * ubo.view * ubo.model * vec4(inPosition, 1.0); + fragColor = inColor; } \ No newline at end of file diff --git a/projs/shadow/shadow-editor/vlkx-resources/shader/compileShaders.bat b/projs/shadow/shadow-editor/vlkx-resources/shader/compileShaders.bat index 5a918616..32767c20 100644 --- a/projs/shadow/shadow-editor/vlkx-resources/shader/compileShaders.bat +++ b/projs/shadow/shadow-editor/vlkx-resources/shader/compileShaders.bat @@ -1,5 +1,5 @@ -@echo off -echo Compiling GLSL shaders to SPIR-V Binary -for /r %%i in (*.vert;*.frag) do %VULKAN_SDK%\Bin\glslangValidator.exe -V "%%i" -o "%%~dpiSPIRV\%%~nxi".spv - +@echo off +echo Compiling GLSL shaders to SPIR-V Binary +for /r %%i in (*.vert;*.frag) do %VULKAN_SDK%\Bin\glslangValidator.exe -V "%%i" -o "%%~dpiSPIRV\%%~nxi".spv + PAUSE \ No newline at end of file diff --git a/projs/shadow/shadow-editor/vlkx-resources/x64/VFFEdit/vlkx-resources.exe.recipe b/projs/shadow/shadow-editor/vlkx-resources/x64/VFFEdit/vlkx-resources.exe.recipe index d2f27938..76f3794f 100644 --- a/projs/shadow/shadow-editor/vlkx-resources/x64/VFFEdit/vlkx-resources.exe.recipe +++ b/projs/shadow/shadow-editor/vlkx-resources/x64/VFFEdit/vlkx-resources.exe.recipe @@ -1,11 +1,11 @@ - - - - - C:\Users\nurgi\Documents\vlkx\x64\VFFEdit\vlkx-resources.exe - - - - - + + + + + C:\Users\nurgi\Documents\vlkx\x64\VFFEdit\vlkx-resources.exe + + + + + \ No newline at end of file diff --git a/projs/shadow/shadow-editor/vlkx-resources/x64/VFFEdit/vlkx-resources.log b/projs/shadow/shadow-editor/vlkx-resources/x64/VFFEdit/vlkx-resources.log index 9fcb4743..6f650eb4 100644 --- a/projs/shadow/shadow-editor/vlkx-resources/x64/VFFEdit/vlkx-resources.log +++ b/projs/shadow/shadow-editor/vlkx-resources/x64/VFFEdit/vlkx-resources.log @@ -1,7 +1,7 @@ - "{0} -> {1} (Partial -> Full PDB)" - System.FormatException: Index (zero based) must be greater than or equal to zero and less than the size of the argument list. - at System.Text.StringBuilder.AppendFormatHelper(IFormatProvider provider, String format, ParamsArray args) - at System.String.FormatHelper(IFormatProvider provider, String format, ParamsArray args) - at System.String.Format(IFormatProvider provider, String format, Object[] args) - at Microsoft.Build.Framework.LazyFormattedBuildEventArgs.FormatString(CultureInfo culture, String unformatted, Object[] args) -EXEC : fatal error CMF1106: failed to open input PDB file for reading (PDB error code = 4) + "{0} -> {1} (Partial -> Full PDB)" + System.FormatException: Index (zero based) must be greater than or equal to zero and less than the size of the argument list. + at System.Text.StringBuilder.AppendFormatHelper(IFormatProvider provider, String format, ParamsArray args) + at System.String.FormatHelper(IFormatProvider provider, String format, ParamsArray args) + at System.String.Format(IFormatProvider provider, String format, Object[] args) + at Microsoft.Build.Framework.LazyFormattedBuildEventArgs.FormatString(CultureInfo culture, String unformatted, Object[] args) +EXEC : fatal error CMF1106: failed to open input PDB file for reading (PDB error code = 4) diff --git a/projs/shadow/shadow-editor/vlkx-resources/x64/VFFEdit/vlkx-resources.tlog/vlkx-resources.lastbuildstate b/projs/shadow/shadow-editor/vlkx-resources/x64/VFFEdit/vlkx-resources.tlog/vlkx-resources.lastbuildstate index b878071d..6a18dda4 100644 --- a/projs/shadow/shadow-editor/vlkx-resources/x64/VFFEdit/vlkx-resources.tlog/vlkx-resources.lastbuildstate +++ b/projs/shadow/shadow-editor/vlkx-resources/x64/VFFEdit/vlkx-resources.tlog/vlkx-resources.lastbuildstate @@ -1,2 +1,2 @@ -PlatformToolSet=v143:VCToolArchitecture=Native64Bit:VCToolsVersion=14.30.30705:TargetPlatformVersion=10.0.19041.0: -VFFEdit|x64|C:\Users\nurgi\Documents\vlkx\| +PlatformToolSet=v143:VCToolArchitecture=Native64Bit:VCToolsVersion=14.30.30705:TargetPlatformVersion=10.0.19041.0: +VFFEdit|x64|C:\Users\nurgi\Documents\vlkx\| diff --git a/projs/shadow/shadow-engine/CMakeLists.txt b/projs/shadow/shadow-engine/CMakeLists.txt index 09f64707..51ba1c38 100644 --- a/projs/shadow/shadow-engine/CMakeLists.txt +++ b/projs/shadow/shadow-engine/CMakeLists.txt @@ -1,65 +1,71 @@ -find_package(Vulkan REQUIRED) -find_package(SDL2 CONFIG REQUIRED) -find_package(imgui REQUIRED) - -set(CMAKE_CXX_STANDARD 20) -#set(CMAKE_WINDOWS_EXPORT_ALL_SYMBOLS ON) - -FILE(GLOB_RECURSE SOURCES - core/src/**/*.cpp - shadow-assets/src/*.cpp - shadow-entity/src/*.cpp - shadow-renderer/src/*.cpp - shadow-reflection/src/*.cpp - shadow-utility/src/*.cpp - shadow-math/src/*.cpp - ) -list(FILTER SOURCES EXCLUDE REGEX ".*.test.cpp$") - -SET(IncludeDirs - core/inc - shadow-assets/inc - shadow-entity/inc - shadow-renderer/inc - shadow-reflection/inc - shadow-utility/inc - shadow-math/inc - ) - - -add_library(shadow-engine SHARED ${SOURCES} $) - -target_include_directories(shadow-engine - PRIVATE ${SDL2_INCLUDE_DIRS} - PUBLIC ${IncludeDirs} - ${glm_SOURCE_DIR} - INTERFACE - ${imgui_SOURCE_DIR} - ${imgui_SOURCE_DIR}/backends) - -target_link_libraries(shadow-engine - PUBLIC Vulkan::Vulkan SDL2::SDL2 spdlog dylib imgui - PRIVATE -static-libgcc -static-libstdc++ - ) - -target_compile_definitions(shadow-engine PRIVATE "EXPORTING_SH_ENGINE") - -target_link_options(shadow-engine PUBLIC -Wl,--export-all-symbols) - - -add_executable(tests ${TEST_SOURCES} ${SOURCES} $) -target_link_libraries(tests PRIVATE Catch2::Catch2 PUBLIC Vulkan::Vulkan SDL2::SDL2 spdlog dylib imgui) -target_include_directories(tests - PUBLIC ${IncludeDirs} - PRIVATE ${SDL2_INCLUDE_DIRS} ${glm_SOURCE_DIR} - INTERFACE - ${imgui_SOURCE_DIR} - ${imgui_SOURCE_DIR}/backends - ) -target_compile_definitions(tests PRIVATE "EXPORTING_SH_ENGINE") - - -# Enable testing on the executable -include(CTest) -include(Catch) -catch_discover_tests(tests) \ No newline at end of file +find_package(SDL2 CONFIG REQUIRED) +find_package(ImGui REQUIRED) +find_package(Vulkan REQUIRED COMPONENTS dxc) + +set(CMAKE_CXX_STANDARD 20) +set(CMAKE_WINDOWS_EXPORT_ALL_SYMBOLS ON) + +add_library(shadow-engine SHARED) +add_library(shadow::engine ALIAS shadow-engine) + +add_executable(shadow-engine-tests) +target_link_libraries(shadow-engine-tests + Catch2::Catch2 + shadow::engine +) + +add_subdirectory(assets) +add_subdirectory(core) +add_subdirectory(entity) +add_subdirectory(math) +add_subdirectory(platforms) +add_subdirectory(reflection) +add_subdirectory(renderer) +add_subdirectory(utility) +add_subdirectory(tests) + +target_link_libraries(shadow-engine + PUBLIC + DirectXMath + SDL2::SDL2 + glm::glm + spdlog::spdlog + dylib + # ImGui + GPUOpen::VulkanMemoryAllocator + Vulkan::Vulkan + Vulkan::dxc_lib +) + +target_compile_definitions(shadow-engine + PRIVATE + EXPORTING_SH_ENGINE +) + +if (TRUE) + + target_sources(shadow-engine PRIVATE + ${imgui_SOURCE_DIR}/imgui.cpp + ${imgui_SOURCE_DIR}/imgui_demo.cpp + ${imgui_SOURCE_DIR}/imgui_draw.cpp + ${imgui_SOURCE_DIR}/imgui_tables.cpp + ${imgui_SOURCE_DIR}/imgui_widgets.cpp + ${imgui_SOURCE_DIR}/backends/imgui_impl_sdl2.cpp + ${imgui_SOURCE_DIR}/backends/imgui_impl_vulkan.cpp + ) + + target_include_directories(shadow-engine + PUBLIC + ${imgui_SOURCE_DIR} + ${imgui_SOURCE_DIR}/backends + ) + + target_compile_definitions(shadow-engine + PRIVATE + IMGUI_USER_CONFIG="shadow/imguiConf.h" + ) + +endif () + + + diff --git a/projs/shadow/shadow-engine/README.md b/projs/shadow/shadow-engine/README.md new file mode 100644 index 00000000..5e60a033 --- /dev/null +++ b/projs/shadow/shadow-engine/README.md @@ -0,0 +1,18 @@ +# Shadow Engine Core + +The Shadow Engine Core is the heart of the Shadow Engine project. +It contains the core functionality of the engine, such as the main loop, the window, the renderer, the input system, etc. + +## Parts + +The Shadow Engine Core is split into multiple parts, each of which is a module in the project. + +- Assets +- Core +- Entity +- Math +- Platforms +- Reflection +- Renderer +- Tests +- Utils \ No newline at end of file diff --git a/projs/shadow/shadow-engine/assets/CMakeLists.txt b/projs/shadow/shadow-engine/assets/CMakeLists.txt new file mode 100644 index 00000000..73460bfa --- /dev/null +++ b/projs/shadow/shadow-engine/assets/CMakeLists.txt @@ -0,0 +1,9 @@ + +FILE(GLOB_RECURSE SOURCES + ${CMAKE_CURRENT_LIST_DIR}/src/*.cpp +) + +target_shadow_module(shadow-engine + SOURCES ${SOURCES} + INCLUDE_DIR ${CMAKE_CURRENT_LIST_DIR}/inc/ +) \ No newline at end of file diff --git a/projs/shadow/shadow-engine/assets/SFFElement.natvis b/projs/shadow/shadow-engine/assets/SFFElement.natvis new file mode 100644 index 00000000..80399624 --- /dev/null +++ b/projs/shadow/shadow-engine/assets/SFFElement.natvis @@ -0,0 +1,24 @@ + + + + {{Name = {name} Parent={parent->name} Children={children} }} + {{Name = {name} Children={children} }} + + + + parent + name + isBlock + + + children._Mypair._Myval2._Myval2._Mysize + children._Mypair._Myval2._Myval2._Myhead->_Parent + _Left + _Right + _Myval.second,view(MapHelper) + + + + + + \ No newline at end of file diff --git a/projs/shadow/shadow-engine/assets/cmake/Catch.cmake b/projs/shadow/shadow-engine/assets/cmake/Catch.cmake new file mode 100644 index 00000000..1d31c0ab --- /dev/null +++ b/projs/shadow/shadow-engine/assets/cmake/Catch.cmake @@ -0,0 +1,90 @@ +# Distributed under the OSI-approved BSD 3-Clause License. See accompanying +# file Copyright.txt or https://cmake.org/licensing for details. + +#----------------------------------------------------------------------------- + +function(catch_discover_tests TARGET) + cmake_parse_arguments( + "" + "" + "TEST_PREFIX;TEST_SUFFIX;WORKING_DIRECTORY;TEST_LIST;REPORTER;OUTPUT_DIR;OUTPUT_PREFIX;OUTPUT_SUFFIX" + "TEST_SPEC;EXTRA_ARGS;PROPERTIES" + ${ARGN} + ) + + if(NOT _WORKING_DIRECTORY) + set(_WORKING_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}") + endif() + if(NOT _TEST_LIST) + set(_TEST_LIST ${TARGET}_TESTS) + endif() + + ## Generate a unique name based on the extra arguments + string(SHA1 args_hash "${_TEST_SPEC} ${_EXTRA_ARGS} ${_REPORTER} ${_OUTPUT_DIR} ${_OUTPUT_PREFIX} ${_OUTPUT_SUFFIX}") + string(SUBSTRING ${args_hash} 0 7 args_hash) + + # Define rule to generate test list for aforementioned test executable + set(ctest_include_file "${CMAKE_CURRENT_BINARY_DIR}/${TARGET}_include-${args_hash}.cmake") + set(ctest_tests_file "${CMAKE_CURRENT_BINARY_DIR}/${TARGET}_tests-${args_hash}.cmake") + get_property(crosscompiling_emulator + TARGET ${TARGET} + PROPERTY CROSSCOMPILING_EMULATOR + ) + add_custom_command( + TARGET ${TARGET} POST_BUILD + BYPRODUCTS "${ctest_tests_file}" + COMMAND "${CMAKE_COMMAND}" + -D "TEST_TARGET=${TARGET}" + -D "TEST_EXECUTABLE=$" + -D "TEST_EXECUTOR=${crosscompiling_emulator}" + -D "TEST_WORKING_DIR=${_WORKING_DIRECTORY}" + -D "TEST_SPEC=${_TEST_SPEC}" + -D "TEST_EXTRA_ARGS=${_EXTRA_ARGS}" + -D "TEST_PROPERTIES=${_PROPERTIES}" + -D "TEST_PREFIX=${_TEST_PREFIX}" + -D "TEST_SUFFIX=${_TEST_SUFFIX}" + -D "TEST_LIST=${_TEST_LIST}" + -D "TEST_REPORTER=${_REPORTER}" + -D "TEST_OUTPUT_DIR=${_OUTPUT_DIR}" + -D "TEST_OUTPUT_PREFIX=${_OUTPUT_PREFIX}" + -D "TEST_OUTPUT_SUFFIX=${_OUTPUT_SUFFIX}" + -D "CTEST_FILE=${ctest_tests_file}" + -P "${_CATCH_DISCOVER_TESTS_SCRIPT}" + VERBATIM + ) + + file(WRITE "${ctest_include_file}" + "if(EXISTS \"${ctest_tests_file}\")\n" + " include(\"${ctest_tests_file}\")\n" + "else()\n" + " add_test(${TARGET}_NOT_BUILT-${args_hash} ${TARGET}_NOT_BUILT-${args_hash})\n" + "endif()\n" + ) + + if(NOT ${CMAKE_VERSION} VERSION_LESS "3.10.0") + # Add discovered tests to directory TEST_INCLUDE_FILES + set_property(DIRECTORY + APPEND PROPERTY TEST_INCLUDE_FILES "${ctest_include_file}" + ) + else() + # Add discovered tests as directory TEST_INCLUDE_FILE if possible + get_property(test_include_file_set DIRECTORY PROPERTY TEST_INCLUDE_FILE SET) + if (NOT ${test_include_file_set}) + set_property(DIRECTORY + PROPERTY TEST_INCLUDE_FILE "${ctest_include_file}" + ) + else() + message(FATAL_ERROR + "Cannot set more than one TEST_INCLUDE_FILE" + ) + endif() + endif() + +endfunction() + +############################################################################### + +set(_CATCH_DISCOVER_TESTS_SCRIPT + CatchAddTests.cmake + CACHE INTERNAL "Catch2 full path to CatchAddTests.cmake helper file" + ) \ No newline at end of file diff --git a/projs/shadow/shadow-engine/assets/cmake/CatchAddTests.cmake b/projs/shadow/shadow-engine/assets/cmake/CatchAddTests.cmake new file mode 100644 index 00000000..6ba6a042 --- /dev/null +++ b/projs/shadow/shadow-engine/assets/cmake/CatchAddTests.cmake @@ -0,0 +1,135 @@ +# Distributed under the OSI-approved BSD 3-Clause License. See accompanying +# file Copyright.txt or https://cmake.org/licensing for details. + +set(prefix "${TEST_PREFIX}") +set(suffix "${TEST_SUFFIX}") +set(spec ${TEST_SPEC}) +set(extra_args ${TEST_EXTRA_ARGS}) +set(properties ${TEST_PROPERTIES}) +set(reporter ${TEST_REPORTER}) +set(output_dir ${TEST_OUTPUT_DIR}) +set(output_prefix ${TEST_OUTPUT_PREFIX}) +set(output_suffix ${TEST_OUTPUT_SUFFIX}) +set(script) +set(suite) +set(tests) + +function(add_command NAME) + set(_args "") + # use ARGV* instead of ARGN, because ARGN splits arrays into multiple arguments + math(EXPR _last_arg ${ARGC}-1) + foreach(_n RANGE 1 ${_last_arg}) + set(_arg "${ARGV${_n}}") + if(_arg MATCHES "[^-./:a-zA-Z0-9_]") + set(_args "${_args} [==[${_arg}]==]") # form a bracket_argument + else() + set(_args "${_args} ${_arg}") + endif() + endforeach() + set(script "${script}${NAME}(${_args})\n" PARENT_SCOPE) +endfunction() + +# Run test executable to get list of available tests +if(NOT EXISTS "${TEST_EXECUTABLE}") + message(FATAL_ERROR + "Specified test executable '${TEST_EXECUTABLE}' does not exist" + ) +endif() +execute_process( + COMMAND ${TEST_EXECUTOR} "${TEST_EXECUTABLE}" ${spec} --list-test-names-only + OUTPUT_VARIABLE output + RESULT_VARIABLE result + WORKING_DIRECTORY "${TEST_WORKING_DIR}" +) +# Catch --list-test-names-only reports the number of tests, so 0 is... surprising +if(${result} EQUAL 0) + message(WARNING + "Test executable '${TEST_EXECUTABLE}' contains no tests!\n" + ) +elseif(${result} LESS 0) + message(FATAL_ERROR + "Error running test executable '${TEST_EXECUTABLE}':\n" + " Result: ${result}\n" + " Output: ${output}\n" + ) +endif() + +string(REPLACE "\n" ";" output "${output}") + +# Run test executable to get list of available reporters +execute_process( + COMMAND ${TEST_EXECUTOR} "${TEST_EXECUTABLE}" ${spec} --list-reporters + OUTPUT_VARIABLE reporters_output + RESULT_VARIABLE reporters_result + WORKING_DIRECTORY "${TEST_WORKING_DIR}" +) +if(${reporters_result} EQUAL 0) + message(WARNING + "Test executable '${TEST_EXECUTABLE}' contains no reporters!\n" + ) +elseif(${reporters_result} LESS 0) + message(FATAL_ERROR + "Error running test executable '${TEST_EXECUTABLE}':\n" + " Result: ${reporters_result}\n" + " Output: ${reporters_output}\n" + ) +endif() +string(FIND "${reporters_output}" "${reporter}" reporter_is_valid) +if(reporter AND ${reporter_is_valid} EQUAL -1) + message(FATAL_ERROR + "\"${reporter}\" is not a valid reporter!\n" + ) +endif() + +# Prepare reporter +if(reporter) + set(reporter_arg "--reporter ${reporter}") +endif() + +# Prepare output dir +if(output_dir AND NOT IS_ABSOLUTE ${output_dir}) + set(output_dir "${TEST_WORKING_DIR}/${output_dir}") + if(NOT EXISTS ${output_dir}) + file(MAKE_DIRECTORY ${output_dir}) + endif() +endif() + +# Parse output +foreach(line ${output}) + set(../test ${line}) + # Escape characters in test case names that would be parsed by Catch2 + set(test_name ${test}) + #foreach(char , [ ]) + #string(REPLACE ${char} "\\${char}" test_name ${test_name}) + #endforeach(char) + # ...add output dir + if(output_dir) + string(REGEX REPLACE "[^A-Za-z0-9_]" "_" test_name_clean ${test_name}) + set(output_dir_arg "--out ${output_dir}/${output_prefix}${test_name_clean}${output_suffix}") + endif() + + # ...and add to script + add_command(add_test + "${prefix}${test}${suffix}" + ${TEST_EXECUTOR} + "${TEST_EXECUTABLE}" + "${test_name}" + ${extra_args} + "${reporter_arg}" + "${output_dir_arg}" + ) + add_command(set_tests_properties + "${prefix}${test}${suffix}" + PROPERTIES + WORKING_DIRECTORY "${TEST_WORKING_DIR}" + ${properties} + ) + list(APPEND tests "${prefix}${test}${suffix}") +endforeach() + +# Create a list of all discovered tests, which users may use to e.g. set +# properties on the tests +add_command(set ${TEST_LIST} ${tests}) + +# Write CTest script +file(WRITE "${CTEST_FILE}" "${script}") \ No newline at end of file diff --git a/projs/shadow/shadow-engine/assets/inc/shadow/assets/fs/file.h b/projs/shadow/shadow-engine/assets/inc/shadow/assets/fs/file.h new file mode 100644 index 00000000..2ca86bc4 --- /dev/null +++ b/projs/shadow/shadow-engine/assets/inc/shadow/assets/fs/file.h @@ -0,0 +1,117 @@ +#pragma once +#include +#include +#include +#include + +#include "shadow/util/Delegate.h" + +namespace SH { + + // An input stream that can read a file on disk. + struct FileInput final : InputStream { + FileInput(); + ~FileInput() = default; + + [[nodiscard]] bool open(std::string path); + void close(); + + using InputStream::read; + [[nodiscard]] bool read(void* data, size_t size) override; + const void* getBuffer() const override { return nullptr; } + + size_t size() const override; + size_t pos(); + + [[nodiscard]] bool seek(size_t pos); + + private: + void* handle; + }; + + // An output stream that can write to a file on disk. + struct FileOutput final : OutputStream { + FileOutput(); + ~FileOutput() = default; + + [[nodiscard]] bool open(std::string path); + void close(); + void flush(); + bool errored() const { return error; } + using OutputStream::write; + [[nodiscard]] bool write(const void* data, size_t size) override; + + private: + FileOutput(const FileOutput&) = delete; + void* handle; + bool error; + }; + + struct FileInfo { + bool directory; + std::string filename; + }; + + + /** + * A generic Filesystem API. + * Allows interacting with files on disk the same as files in our Virtual Package Format. + */ + struct FileSystem { + // A function called when the data of a file is updated, such as when an asynchronous operation completes. + using ContentCallback = Delegate; + using Path = SH::Path; + // A handle for asynchronous data movement; such as reading or writing a file. + struct AsyncHandle { + static AsyncHandle invalid() { return AsyncHandle(0xffffffff); } + explicit AsyncHandle(uint32_t val) : value(val) {} + + [[nodiscard]] bool valid() const { return value != 0xffffffff; } + + uint32_t value; + }; + + // Start a Filesystem that interacts with files on disk. + static std::unique_ptr createDiskFS(const std::string& basePath); + // Start a Virtual Filesystem based on the given path. + static std::unique_ptr createVFS(const std::string& basePath); + + virtual ~FileSystem() = default; + + // Open a file for reading. + virtual bool open(std::string& path, FileInput& input) = 0; + // Open a file for writing. + virtual bool open(std::string& path, FileOutput& output) = 0; + // Check whether a file exists at the given path. + virtual bool fileExists(std::string& path) = 0; + // Get the time a file at the given path was last modified. + virtual size_t getLastModified(std::string& path) = 0; + // Copy a file from one path to another. + virtual bool copyFile(std::string& from, std::string& to) = 0; + // Move a file from one path to another. + virtual bool moveFile(std::string& from, std::string& to) = 0; + // Disassociate any files at the given path (not an immediate delete) + virtual bool deleteFile(std::string& path) = 0; + + // Get the path that this FileSystem originates at. The default is "/" for VFS, and whatever the Executable Path is for Disk FS. + virtual std::string const& getBasePath() const = 0; + // Set a new base path for the FileSystem. Any operations involving file paths will be relative to this new path. + virtual void setBasePath(std::string& path) = 0; + + // Process all the callbacks for async file operations. + virtual void processCallbacks() = 0; + // Check whether there are any outstanding async operations that need work. + virtual bool hasWork() = 0; + + // Write new content to a file synchronously. The thread will be blocked when doing this. + virtual bool saveSync(const Path& file, const uint8_t* content, size_t size) = 0; + // Read content from a file synchronously. The thread will be blocked when doing this. + virtual bool readSync(const Path& file, OutputMemoryStream& content) = 0; + virtual bool readSync(const Path& file, std::vector& buf) = 0; + + // Read a file asynchronously. The given callback will be called with the file content once it is available. + virtual AsyncHandle readAsync(const Path& file, const ContentCallback& callback) = 0; + // Cancel an asynchronous operation, if it is not already complete. The associated callback will be called with a special flag. + virtual void cancelAsync(AsyncHandle& handle) = 0; + }; +} \ No newline at end of file diff --git a/projs/shadow/shadow-engine/assets/inc/shadow/assets/fs/iostream.h b/projs/shadow/shadow-engine/assets/inc/shadow/assets/fs/iostream.h new file mode 100644 index 00000000..2c50d11b --- /dev/null +++ b/projs/shadow/shadow-engine/assets/inc/shadow/assets/fs/iostream.h @@ -0,0 +1,132 @@ +#pragma once +#include +#include + +namespace SH { + // A custom OutputStream that can be implemented to output to any arbitrary data structure. + // The idea is that it can write to a file, or into memory, or into a temporary buffer that is copied to both. + // As opposed to the hardcoded streams that exist in C++, which have a single purpose for their entire lifetime. + struct OutputStream { + virtual bool write(const void* data, size_t size) = 0; + + OutputStream& operator<< (std::string& str); + OutputStream& operator<< (const char* str); + OutputStream& operator<< (size_t val); + OutputStream& operator<< (int64_t val); + OutputStream& operator<< (uint32_t val); + OutputStream& operator<< (int32_t val); + OutputStream& operator<< (float val); + OutputStream& operator<< (double val); + template bool write(const T& val); + }; + + // A custom InputStream that can be implemented to read from any arbitrary data structure. + // The idea is that it can read from a file, or from memory, or from a temporary buffer that is merged from both. + // As opposed to the hardcoded streams that exist in C++, which have a single purpose for their entire lifetime. + struct InputStream { + virtual bool read(void* buffer, size_t size) = 0; + virtual const void* getBuffer() const = 0; + virtual size_t size() const = 0; + + template void read(T& val) { read(&val, sizeof(T)); } + template T read(); + }; + + // A custom OutputStream that writes to memory. + struct OutputMemoryStream final : OutputStream { + + OutputMemoryStream() : buffer(nullptr), capacity(0), usage(0) {}; + OutputMemoryStream(void* data, size_t size); + OutputMemoryStream(OutputMemoryStream&& str) noexcept; + OutputMemoryStream(const OutputMemoryStream& rhs) noexcept; + ~OutputMemoryStream(); + + OutputMemoryStream& operator= (const OutputMemoryStream& rhs) noexcept; + OutputMemoryStream& operator= (OutputMemoryStream&& rhs) noexcept; + + uint8_t operator[] (size_t index) const; + uint8_t& operator[] (size_t index); + OutputMemoryStream& operator+= (size_t index); + OutputMemoryStream& operator++ (); + + bool write(const void* data, size_t size) override; + + uint8_t* release(); + void resize(size_t size); + void reserve(size_t size); + const uint8_t* data() const { return buffer; }; + uint8_t* dataMut() { return buffer; }; + size_t size() const { return usage; }; + void clear(); + void* skip(size_t size); + bool empty() const { return usage == 0; }; + void free(); + + void write(std::string& str); + template void write(const T& val); + + private: + uint8_t* buffer; + size_t capacity; + size_t usage; + }; + + template void OutputMemoryStream::write(const T& val){ + write(&val, sizeof(T)); + } + + + template <> inline void OutputMemoryStream::write(const bool& val) { + uint8_t v = val; + write(&v, sizeof(v)); + } + + // A custom InputStream that writes from memory. + struct InputMemoryStream final : InputStream { + InputMemoryStream(const void* data, size_t size); + explicit InputMemoryStream(const OutputMemoryStream& blob); + + void set(const void* data, size_t size); + bool read(void* data, size_t size) override; + std::string readString(); + const void* skip(size_t size); + const void* getData() const { return data; }; + const void* getBuffer() const override { return data; }; + size_t size() const override { return capacity; }; + size_t pos() const { return position; }; + void setPos(size_t pos) { position = pos; }; + void restart() { position = 0; }; + uint8_t readChar() { position++; return data[position-1]; }; + + template + T getAs() const { + static_assert(position + sizeof(T) < capacity); + return *(T*)(data + position); + } + + using InputStream::read; + + private: + const uint8_t* data; + size_t capacity; + size_t position; + }; + + template + T InputStream::read() { + T v; + read(&v, sizeof(T)); + return v; + } + + template<> inline bool InputStream::read() { + uint8_t v; + read(&v, sizeof(bool)); + return v; + } + + template + bool OutputStream::write(const T &val) { + return write(&val, sizeof(T)); + } +} \ No newline at end of file diff --git a/projs/shadow/shadow-engine/assets/inc/shadow/assets/fs/xxhash.h b/projs/shadow/shadow-engine/assets/inc/shadow/assets/fs/xxhash.h new file mode 100644 index 00000000..e75b9c9c --- /dev/null +++ b/projs/shadow/shadow-engine/assets/inc/shadow/assets/fs/xxhash.h @@ -0,0 +1,182 @@ +#pragma once +#include // for uint32_t and uint64_t + +class XXHash64 +{ +public: + /// create new XXHash (64 bit) + /** @param seed your seed value, even zero is a valid seed **/ + explicit XXHash64(uint64_t seed) + { + state[0] = seed + Prime1 + Prime2; + state[1] = seed + Prime2; + state[2] = seed; + state[3] = seed - Prime1; + bufferSize = 0; + totalLength = 0; + } + + /// add a chunk of bytes + /** @param input pointer to a continuous block of data + @param length number of bytes + @return false if parameters are invalid / zero **/ + bool add(const void* input, uint64_t length) + { + // no data ? + if (!input || length == 0) + return false; + + totalLength += length; + // byte-wise access + const unsigned char* data = (const unsigned char*)input; + + // unprocessed old data plus new data still fit in temporary buffer ? + if (bufferSize + length < MaxBufferSize) + { + // just add new data + while (length-- > 0) + buffer[bufferSize++] = *data++; + return true; + } + + // point beyond last byte + const unsigned char* stop = data + length; + const unsigned char* stopBlock = stop - MaxBufferSize; + + // some data left from previous update ? + if (bufferSize > 0) + { + // make sure temporary buffer is full (16 bytes) + while (bufferSize < MaxBufferSize) + buffer[bufferSize++] = *data++; + + // process these 32 bytes (4x8) + process(buffer, state[0], state[1], state[2], state[3]); + } + + // copying state to local variables helps optimizer A LOT + uint64_t s0 = state[0], s1 = state[1], s2 = state[2], s3 = state[3]; + // 32 bytes at once + while (data <= stopBlock) + { + // local variables s0..s3 instead of state[0]..state[3] are much faster + process(data, s0, s1, s2, s3); + data += 32; + } + // copy back + state[0] = s0; state[1] = s1; state[2] = s2; state[3] = s3; + + // copy remainder to temporary buffer + bufferSize = stop - data; + for (uint64_t i = 0; i < bufferSize; i++) + buffer[i] = data[i]; + + // done + return true; + } + + /// get current hash + /** @return 64 bit XXHash **/ + uint64_t hash() const + { + // fold 256 bit state into one single 64 bit value + uint64_t result; + if (totalLength >= MaxBufferSize) + { + result = rotateLeft(state[0], 1) + + rotateLeft(state[1], 7) + + rotateLeft(state[2], 12) + + rotateLeft(state[3], 18); + result = (result ^ processSingle(0, state[0])) * Prime1 + Prime4; + result = (result ^ processSingle(0, state[1])) * Prime1 + Prime4; + result = (result ^ processSingle(0, state[2])) * Prime1 + Prime4; + result = (result ^ processSingle(0, state[3])) * Prime1 + Prime4; + } + else + { + // internal state wasn't set in add(), therefore original seed is still stored in state2 + result = state[2] + Prime5; + } + + result += totalLength; + + // process remaining bytes in temporary buffer + const unsigned char* data = buffer; + // point beyond last byte + const unsigned char* stop = data + bufferSize; + + // at least 8 bytes left ? => eat 8 bytes per step + for (; data + 8 <= stop; data += 8) + result = rotateLeft(result ^ processSingle(0, *(uint64_t*)data), 27) * Prime1 + Prime4; + + // 4 bytes left ? => eat those + if (data + 4 <= stop) + { + result = rotateLeft(result ^ (*(uint32_t*)data) * Prime1, 23) * Prime2 + Prime3; + data += 4; + } + + // take care of remaining 0..3 bytes, eat 1 byte per step + while (data != stop) + result = rotateLeft(result ^ (*data++) * Prime5, 11) * Prime1; + + // mix bits + result ^= result >> 33; + result *= Prime2; + result ^= result >> 29; + result *= Prime3; + result ^= result >> 32; + return result; + } + + + /// combine constructor, add() and hash() in one static function (C style) + /** @param input pointer to a continuous block of data + @param length number of bytes + @param seed your seed value, e.g. zero is a valid seed + @return 64 bit XXHash **/ + static uint64_t hash(const void* input, uint64_t length, uint64_t seed) + { + XXHash64 hasher(seed); + hasher.add(input, length); + return hasher.hash(); + } + +private: + /// magic constants :-) + static const uint64_t Prime1 = 11400714785074694791ULL; + static const uint64_t Prime2 = 14029467366897019727ULL; + static const uint64_t Prime3 = 1609587929392839161ULL; + static const uint64_t Prime4 = 9650029242287828579ULL; + static const uint64_t Prime5 = 2870177450012600261ULL; + + /// temporarily store up to 31 bytes between multiple add() calls + static const uint64_t MaxBufferSize = 31+1; + + uint64_t state[4]; + unsigned char buffer[MaxBufferSize]; + uint64_t bufferSize; + uint64_t totalLength; + + /// rotate bits, should compile to a single CPU instruction (ROL) + static inline uint64_t rotateLeft(uint64_t x, unsigned char bits) + { + return (x << bits) | (x >> (64 - bits)); + } + + /// process a single 64 bit value + static inline uint64_t processSingle(uint64_t previous, uint64_t input) + { + return rotateLeft(previous + input * Prime2, 31) * Prime1; + } + + /// process a block of 4x4 bytes, this is the main part of the XXHash32 algorithm + static inline void process(const void* data, uint64_t& state0, uint64_t& state1, uint64_t& state2, uint64_t& state3) + { + const uint64_t* block = (const uint64_t*) data; + state0 = processSingle(state0, block[0]); + state1 = processSingle(state1, block[1]); + state2 = processSingle(state2, block[2]); + state3 = processSingle(state3, block[3]); + } +}; \ No newline at end of file diff --git a/projs/shadow/shadow-engine/assets/inc/shadow/assets/resource/Resource.h b/projs/shadow/shadow-engine/assets/inc/shadow/assets/resource/Resource.h new file mode 100644 index 00000000..944d6daf --- /dev/null +++ b/projs/shadow/shadow-engine/assets/inc/shadow/assets/resource/Resource.h @@ -0,0 +1,142 @@ +#pragma once + +#include +#include +#include +#include + +#include + +namespace SH { + + /** + * A runtime-only struct that determines the type of a resource - whether it be a texture, mesh, animation, or other data. + * Provides some specializations for living in a map. + */ + struct ResourceType { + ResourceType() = default; + explicit ResourceType(const std::string& name); + bool operator!=(const ResourceType& o) const { return o.hash != hash; } + bool operator==(const ResourceType& o) const { return o.hash == hash; } + bool operator< (const ResourceType& o) const { return o.hash.getHash() < hash.getHash(); } + bool isValid() const { return hash.getHash() != 0; } + + SH::HeapHash hash; + }; + + // A Resource Type that is guaranteed to be invalid. + static std::string empty; + const ResourceType INVALID_RESOURCE(empty); + + // A specialization of HashFunc for ResourceTypes, since they already have a HeapHash within. + template<> struct HashFunc { + static uint32_t get(const ResourceType& key) { return HashFunc::get(key.hash); } + }; + +#pragma pack(1) + struct ResourceHeader { + static const uint32_t MAGIC; + uint32_t magic = MAGIC; // VXI Package header + uint32_t version = 0; + uint32_t flags = 0; + uint32_t padding = 0; + uint32_t decompressedSize = 0; + }; +#pragma pack() + + /** + * A basic Resource type. + * Represents a single file loaded from disk. + * May have dependencies on other Resources, and other Resources may depend on this. + * Resources are reference-counted, and are removed when they go out of usage. + */ + + struct Resource { + + friend struct ResourceTypeManager; + friend struct ResourceManager; + + enum class State : uint32_t { + EMPTY = 0, + READY, + FAILED + }; + + using Observer = DelegateList; + + virtual ~Resource(); + virtual ResourceType getType() const = 0; + State getState() const { return state; } + + bool isEmpty() const { return state == State::EMPTY; } + bool isReady() const { return state == State::READY; } + bool isFailure() const { return state == State::FAILED; } + + uint32_t getReferenceCount() const { return references; } + + Observer const& getCallback() const { return callback; } + size_t getSize() const { return size; } + + const SH::Path& getPath() const { return path; } + + struct ResourceTypeManager& getManager() { return manager; } + + uint32_t decreaseReferences(); + uint32_t increaseReferences() { return references++; } + + bool toInitialize() const { return desiredState == State::READY; } + bool isHooked() const { return hooked; } + + template void onLoaded(C* instance) { + callback.bind(instance); + if (isReady()) (instance->*Function)(State::READY, State::READY, *this); + } + + protected: + Resource(SH::Path path, ResourceTypeManager& manager); + + virtual void onReadying() {} + virtual void unload() = 0; + virtual bool load(size_t size, const uint8_t* mem) = 0; + + void onCreated(State newState); + void performUnload(); + void addDependency(Resource& dependent); + void removeDependency(Resource& dependent); + void checkState(); + void refresh(); + + State desiredState; + uint16_t emptyDependencies; + ResourceTypeManager& manager; + + private: + + void doLoad(); + void fileLoaded(size_t fileSize, const uint8_t* mem, bool success); + void stateChanged(State old, State newState, Resource&); + + Resource(const Resource&) = delete; + void operator=(const Resource&) = delete; + + Observer callback; + size_t size; + SH::Path path; + uint32_t references; + uint16_t failedDependencies; + FileSystem::AsyncHandle handle; + State state; + bool hooked = false; + }; + + struct PrefabResource : Resource { + PrefabResource(const SH::Path& path, ResourceTypeManager& resource_manager); + ResourceType getType() const override; + void unload() override; + bool load(size_t size, const uint8_t* data) override; + + OutputMemoryStream data; + SH::StableHash hash; + static const ResourceType TYPE; + }; +} \ No newline at end of file diff --git a/projs/shadow/shadow-engine/assets/inc/shadow/assets/resource/ResourceManager.h b/projs/shadow/shadow-engine/assets/inc/shadow/assets/resource/ResourceManager.h new file mode 100644 index 00000000..0fe5421c --- /dev/null +++ b/projs/shadow/shadow-engine/assets/inc/shadow/assets/resource/ResourceManager.h @@ -0,0 +1,94 @@ +#pragma once +#include +#include + +namespace SH { + + /** + * Handles all of the Resources of a single Type. + * Handles reference counting, hot reloading, and etc. + */ + + struct ResourceTypeManager { + friend struct Resource; + friend struct ResourceManager; + + using ResourceTable = std::map; + + void create(struct ResourceType type, struct ResourceManager& manager); + void destroy(); + + void setUnloadable(bool status); + + void removeUnreferencedResources(); + + void reload(const SH::Path& path); + void reload(Resource& resource); + + ResourceTable& getResources() { return resources; } + + ResourceTypeManager(); + virtual ~ResourceTypeManager(); + ResourceManager& getOwner() const { return *owner; } + + protected: + Resource* load(const SH::Path& path); + virtual Resource* createResource(const SH::Path& path) = 0; + virtual void destroyResource(Resource& res) = 0; + Resource* get(const SH::Path& path); + + ResourceTable resources; + ResourceManager* owner; + bool unloadEnabled; + }; + + /** + * Handles all of the ResourceTypeManagers, for every ResourceType with at least one applicable Resource + */ + struct ResourceManager { + using ResourceTypeManagers = std::map; + + struct LoadHook { + enum class Action { IMMEDIATE, DEFERRED }; + virtual ~LoadHook(); + virtual Action load(Resource& res) = 0; + void continueLoad(Resource& res); + }; + + static ResourceManager& Get(); + ResourceManager(); + ~ResourceManager(); + ResourceManager(const ResourceManager& o) = delete; + + void init(struct FileSystem& fs); + + ResourceTypeManager* get(ResourceType); + const ResourceTypeManagers& getAll() const { return managers; } + + template + R* load(const SH::Path& path) { + return static_cast(load(R::TYPE, path)); + } + + Resource* load(ResourceTypeManager& manager, const SH::Path& path); + Resource* load(ResourceType type, const SH::Path& path); + + void setLoadHook(LoadHook* hook); + bool isHooked() const { return hook; } + LoadHook::Action onLoad(Resource& res) const; + void add(ResourceType, ResourceTypeManager* manager); + void remove(ResourceType type); + void reload(const SH::Path& path); + void reloadAll(); + void removeUnreferenced(); + void setUnloadable(bool enable); + + FileSystem& getFileSystem() { return *filesystem; } + + private: + ResourceTypeManagers managers; + FileSystem* filesystem; + LoadHook* hook; + + }; +} \ No newline at end of file diff --git a/projs/shadow/shadow-engine/assets/src/SFFElement.cpp b/projs/shadow/shadow-engine/assets/src/SFFElement.cpp new file mode 100644 index 00000000..841d95b6 --- /dev/null +++ b/projs/shadow/shadow-engine/assets/src/SFFElement.cpp @@ -0,0 +1,35 @@ +#include "SFFElement.h" + + + namespace Shadow::SFF { + + SFFElement* SFFElement::GetFirstChild() + { + return children.size() > 0 ? children.begin()->second : nullptr; + } + + SFFElement* SFFElement::GetChildByIndex(int index) + { + SFFElement::ChildrenMap::iterator it = children.begin(); + if (it == children.end()) + return nullptr; + + for (size_t i = 0; i < index; i++) + { + it++; + } + return it->second; + } + + SFFElement* SFFElement::GetChildByName(std::string name) + { + SFFElement::ChildrenMap::iterator it = children.find(name); + if (it != children.end()) { + return it->second; + } + return nullptr; + } + + SFFElement::~SFFElement(){} + +} \ No newline at end of file diff --git a/projs/shadow/shadow-engine/assets/src/SFFElement.h b/projs/shadow/shadow-engine/assets/src/SFFElement.h new file mode 100644 index 00000000..bf8946dc --- /dev/null +++ b/projs/shadow/shadow-engine/assets/src/SFFElement.h @@ -0,0 +1,36 @@ +#pragma once + +#include +#include +#include + + + namespace Shadow::SFF { + + class SFFElement + { + public: + SFFElement* parent; + + std::string name; + + bool isBlock; + + std::string value; + typedef std::map ChildrenMap; + + ChildrenMap children; + + std::string GetStringProperty(std::string name); + + SFFElement* GetFirstChild(); + + SFFElement* GetChildByIndex(int index); + + SFFElement* GetChildByName(std::string name); + + ~SFFElement(); + + }; + +} \ No newline at end of file diff --git a/projs/shadow/shadow-engine/assets/src/SFFParser.cpp b/projs/shadow/shadow-engine/assets/src/SFFParser.cpp new file mode 100644 index 00000000..700b67d6 --- /dev/null +++ b/projs/shadow/shadow-engine/assets/src/SFFParser.cpp @@ -0,0 +1,128 @@ +#include "SFFParser.h" +#include "shadow/util/string-helpers.h" + +#include + +namespace Shadow::SFF { + + SFFElement* SFFParser::ReadFromStream(std::istream& stream) + { + auto version = ReadVersionFromHeader(stream); + if (version.invalid) { + //SH_CORE_WARN("Shadow File is invalid"); + return nullptr; + } + + + //The current node that we are building + auto* context = new SFFElement; + context->name = "root"; + + //Top level Element + SFFElement* base = context; + + //The new node that will be a child of the context + SFFElement* current = nullptr; + + + std::string buffer; + + char c; + while (!stream.eof()) + { + stream.get(c); + + switch (c) { + case ':': + //The stuff in the buffer is a parameter name + //std::cout << "Name: " << buffer; + current = new SFFElement; + current->name = buffer; + current->parent = context; + + buffer = ""; + break; + + case '{': + //Start of a new block + current->isBlock = true; + context = current; + + current = nullptr; + break; + + case ',': + // End of a property + if (!current->isBlock) { + //The stuff is the value + current->value = buffer; + current->parent = context; + current->isBlock = false; + } + buffer = ""; + + context->children[current->name] = current; + + current = nullptr; + break; + + case '}': + if (current != nullptr) { + // End of a block + current->parent = context; + context->children[current->name] = current; + } + current = context; + context = current->parent; + + break; + + default: + if (std::isspace(c) == 0) + { + buffer += c; + } + break; + } + + } + + //std::cout << "END" << std::endl; + + return base; + } + + SFFVersion SFFParser::ReadVersionFromHeader(std::istream& stream) { + std::string line; + std::getline(stream, line); + auto parts = SH::Util::Str::explode(line, '_'); + if (parts[0] != "ShadowFileFormat") { + return SFFVersion(-1, -1, -1); + } + else { + int mayor = std::stoi(parts[1]); + int minor = std::stoi(parts[2]); + int patch = std::stoi(parts[3]); + return SFFVersion(mayor, minor, patch); + } + + } + + + + SFFElement* SFFParser::ReadFromFile(std::string path) + { + std::ifstream inputFileStream(path); + + if (errno) + { + //SH_CORE_ERROR("Error: {0} | File: {1}", strerror(errno), path); + //std::cerr << "Error: " << strerror(errno) << std::endl; + //std::cerr << "File: " << path << std::endl; + return nullptr; + } + + return ReadFromStream(inputFileStream); + } +} + diff --git a/projs/shadow/shadow-engine/assets/src/SFFParser.h b/projs/shadow/shadow-engine/assets/src/SFFParser.h new file mode 100644 index 00000000..d6aa8a3a --- /dev/null +++ b/projs/shadow/shadow-engine/assets/src/SFFParser.h @@ -0,0 +1,22 @@ +#pragma once + +#include +#include + +#include "SFFElement.h" +#include "SFFVersion.h" + +namespace Shadow::SFF { + + class SFFParser + { + public: + + static SFFElement* ReadFromStream(std::istream& stream); + + static SFFVersion ReadVersionFromHeader(std::istream& stream); + + static SFFElement* ReadFromFile(std::string path); + }; + +} diff --git a/projs/shadow/shadow-engine/assets/src/SFFVersion.h b/projs/shadow/shadow-engine/assets/src/SFFVersion.h new file mode 100644 index 00000000..136b0bf6 --- /dev/null +++ b/projs/shadow/shadow-engine/assets/src/SFFVersion.h @@ -0,0 +1,28 @@ +#pragma once + +namespace Shadow::SFF { + + struct SFFVersion { + public: + int mayor; + int minor; + int patch; + + bool invalid; + + SFFVersion(int ma, int mi, int pa) + { + this->mayor = ma; + this->minor = mi; + this->patch = pa; + + if (ma >= 0 && mi >= 0 && pa >= 0) { + this->invalid = false; + } + else + { + invalid = true; + } + } + }; +} \ No newline at end of file diff --git a/projs/shadow/shadow-engine/assets/src/SFFWriter.cpp b/projs/shadow/shadow-engine/assets/src/SFFWriter.cpp new file mode 100644 index 00000000..22056139 --- /dev/null +++ b/projs/shadow/shadow-engine/assets/src/SFFWriter.cpp @@ -0,0 +1,48 @@ +#include "SFFWriter.h" + + +namespace Shadow::SFF { + + void SFFWriter::WriteFile(SFFElement& root, std::string path) + { + std::ofstream writer(path); + writer << "ShadowFileFormat_1_0_0" << std::endl; + + int depth = 0; + WriteElement(writer, root, depth); + + writer.flush(); + } + + void SFFWriter::WriteElement(std::ostream& w, SFFElement& e, int &depth) + { + std::string head = (e.name + (e.isBlock ? ":{" : ":")); + //head = head.PadLeft(depth + head.Length, '\t'); + head.insert(head.begin(), depth, '\t'); + w << head << std::endl; + + if (e.isBlock) + { + depth += 1; + w << std::endl; + for(auto& prop : e.children) + { + WriteElement(w, *prop.second, depth); + } + + std::string close = "}"; + close.insert(head.begin(), depth, '\t'); + w << close; + depth -= 1; + } + else + { + w << e.value << ","; + } + + + } + +} + + diff --git a/projs/shadow/shadow-engine/assets/src/SFFWriter.h b/projs/shadow/shadow-engine/assets/src/SFFWriter.h new file mode 100644 index 00000000..2ee034ac --- /dev/null +++ b/projs/shadow/shadow-engine/assets/src/SFFWriter.h @@ -0,0 +1,26 @@ +#pragma once + +#include +#include +#include + +#include "SFFElement.h" +#include "SFFVersion.h" + +namespace Shadow::SFF { + + class SFFWriter + { + public: + + static void WriteFile(SFFElement& root, std::string path); + + static void WriteElement(std::ostream& w, SFFElement& e, int &depth); + + + + }; + +} + + diff --git a/projs/shadow/shadow-engine/assets/src/Shadow.FileFormat.ixx b/projs/shadow/shadow-engine/assets/src/Shadow.FileFormat.ixx new file mode 100644 index 00000000..2ae94031 --- /dev/null +++ b/projs/shadow/shadow-engine/assets/src/Shadow.FileFormat.ixx @@ -0,0 +1,6 @@ +export module Shadow.FileFormat; + +export import :SFFElement; +export import :SFFParser; +export import :SFFWriter; +export import :SFFVersion; \ No newline at end of file diff --git a/projs/shadow/shadow-engine/assets/src/fs/file.cpp b/projs/shadow/shadow-engine/assets/src/fs/file.cpp new file mode 100644 index 00000000..2f97f1c5 --- /dev/null +++ b/projs/shadow/shadow-engine/assets/src/fs/file.cpp @@ -0,0 +1,337 @@ +#include +#include +#include +#include +#include +#include +#include + +namespace SH { + // Because fuck Linux? Need platform-specific source files! +#ifdef _WIN32 + +#define WIN32_LEAN_AND_MEAN +#include +#include + + FileInput::FileInput() { + handle = (void*) INVALID_HANDLE_VALUE; + } + + FileOutput::FileOutput() { + error = false; + handle = (void*) INVALID_HANDLE_VALUE; + } + + bool FileOutput::open(std::string path) { + handle = (HANDLE) CreateFile(path.c_str(), GENERIC_READ, FILE_SHARE_READ, nullptr, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, nullptr); + return INVALID_HANDLE_VALUE != handle; + } + + bool FileInput::open(std::string path) { + handle = (HANDLE) CreateFile(path.c_str(), GENERIC_READ, FILE_SHARE_READ, nullptr, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, nullptr); + return INVALID_HANDLE_VALUE != handle; + } + + void FileInput::close() { + if (INVALID_HANDLE_VALUE != (HANDLE) handle) { + CloseHandle((HANDLE) handle); + handle = (void*) INVALID_HANDLE_VALUE; + } + } + + void FileOutput::close() { + if (INVALID_HANDLE_VALUE != (HANDLE) handle) { + CloseHandle((HANDLE) handle); + handle = (void*) INVALID_HANDLE_VALUE; + } + } + + size_t FileInput::size() const { + assert(INVALID_HANDLE_VALUE != handle); + return GetFileSize((HANDLE) handle, 0); + } + + size_t FileInput::pos() { + assert(INVALID_HANDLE_VALUE != handle); + return SetFilePointer((HANDLE) handle, 0, nullptr, FILE_CURRENT); + } + + bool FileInput::seek(size_t pos) { + assert(INVALID_HANDLE_VALUE != handle); + LARGE_INTEGER distance; + distance.QuadPart = pos; + return SetFilePointer((HANDLE) handle, distance.u.LowPart, &distance.u.HighPart, FILE_BEGIN) != INVALID_SET_FILE_POINTER; + } + + bool FileInput::read(void* data, size_t size) { + assert(INVALID_HANDLE_VALUE != handle); + DWORD read = 0; + BOOL success = ReadFile((HANDLE) handle, data, (DWORD) size, (LPDWORD) &read, nullptr); + return success && size == read; + } + + void FileOutput::flush() { + assert(handle != nullptr); + FlushFileBuffers((HANDLE) handle); + } + + bool FileOutput::write(const void* data, size_t size) { + assert(handle != INVALID_HANDLE_VALUE); + size_t written = 0; + WriteFile((HANDLE) handle, data, (DWORD) size, (LPDWORD) &written, nullptr); + error = error | size != written; + return !error; + } + +#endif + + /** + * An async operation to be performed. + * For reading files from disk into memory. + */ + + struct AsyncRead { + enum class Flags : uint32_t { + FAILED = 0, // The read failed due to some error. + CANCELLED // The read was cancelled due to the resource not being needed any more. + }; + + AsyncRead() : data() {} + + bool isFailed() const { return flags == Flags::FAILED; } + bool isCancelled() const { return flags == Flags::CANCELLED; } + + FileSystem::ContentCallback callback; + OutputMemoryStream data; + std::string path; + uint32_t id = 0; + Flags flags; + }; + + // The FileSystem that operates on raw on-disk files. + struct DiskFS; + + struct DiskFS : FileSystem { + + explicit DiskFS(const std::string& path) : sem(0, 0xffff) { + setBasePath(const_cast(path)); + } + + bool hasWork() override { + return workCounter != 0; + } + + std::string const& getBasePath() const override { return basePath; } + void setBasePath(std::string& path) final { + basePath = Path::normalise(path); + if (!basePath.ends_with('/') && !basePath.ends_with('\\')) + basePath.append("/"); + } + + bool saveSync(const Path& path, const uint8_t* data, const size_t size) override { + FileOutput file; + std::string fullPath(basePath.append(path.c_str())); + + if (!file.open(fullPath)) return false; + bool res = file.write(data, size); + file.close(); + + return res; + } + + bool readSync(const Path& path, struct OutputMemoryStream& content) override { + FileInput file; + std::string fullPath(basePath.append(path.c_str())); + + if (!file.open(fullPath)) return false; + + content.resize(file.size()); + if (!file.read(content.dataMut(), content.size())) { + file.close(); + return false; + } + + file.close(); + return true; + } + + bool readSync(const Path& path, std::vector& buf) override { + FileInput file; + std::string fullPath(basePath.append(path.c_str())); + + if (!file.open(fullPath)) return false; + + buf.resize(file.size()); + if (!file.read(buf.data(), buf.size())) { + file.close(); + return false; + } + + file.close(); + return true; + } + + AsyncHandle readAsync(const Path& file, const ContentCallback& callback) override { + if (!file.isEmpty()) return AsyncHandle::invalid(); + + MutexGuard lock(mutex); + workCounter++; + + AsyncRead& read = queue.emplace_back(); + if (++lastID == 0) lastID++; + + read.id = lastID; + read.path = file.c_str(); + read.callback = callback; + sem.raise(); + + return AsyncHandle(read.id); + } + + void cancelAsync(AsyncHandle& handle) override { + MutexGuard lock(mutex); + + for (AsyncRead& read : queue) { + if (read.id == handle.value) { + read.flags = AsyncRead::Flags::CANCELLED; + workCounter--; + return; + } + } + + for (AsyncRead& read : finished) { + if (read.id == handle.value) { + read.flags = AsyncRead::Flags::CANCELLED; + return; + } + } + } + + bool open(std::string& path, FileInput& file) override { + return file.open(basePath.append(path)); + } + + bool open(std::string& path, FileOutput& file) override { + return file.open(basePath.append(path)); + } + + bool deleteFile(std::string& path) override { + return std::remove((basePath.append(path).c_str())); + } + + bool moveFile(std::string& from, std::string& to) override { + try { + std::rename(basePath.append(from).c_str(), basePath.append(to).c_str()); + } catch (std::filesystem::filesystem_error& e) { + return false; + } + return true; + } + + bool copyFile(std::string& from, std::string& to) override { + try { + std::filesystem::copy(basePath.append(from).c_str(), basePath.append(to).c_str()); + } catch (std::filesystem::filesystem_error& e) { + return false; + } + + return true; + } + + bool fileExists(std::string& path) override { + return std::filesystem::exists(path); + } + + size_t getLastModified(std::string& path) override { + return std::filesystem::last_write_time(path).time_since_epoch().count(); + } + + // TODO: File iterators + + void processCallbacks() override { + // TODO: Timeout this function! + for (;;) { + mutex.enter(); + if (finished.empty() || workCounter == 0) { + mutex.exit(); + break; + } + + AsyncRead item = finished[0]; + finished.erase(finished.begin()); + --workCounter; + + mutex.exit(); + + if (!item.isCancelled()) + item.callback.invoke(item.data.size(), (const uint8_t*) item.data.data(), !item.isFailed()); + } + } + + // TODO: Run Management + std::string basePath; + std::vector queue; + uint64_t workCounter; + std::vector finished; + Mutex mutex; + Semaphore sem; + + uint32_t lastID; + + }; + + struct VFS : DiskFS { + VFS(const std::string& root_pack_path) : DiskFS((std::string &) "vfs:/") { + if (!pack.open(const_cast(root_pack_path))) { + spdlog::error("Unable to open " + root_pack_path + ", please check paths"); + return; + } + + const auto count = pack.read(); + for (size_t i = 0; i < count; i++) { + const auto hash = pack.read(); + PackFile& file = packFiles[hash]; + file.offset = pack.read(); + file.size = pack.read(); + } + } + + ~VFS() { pack.close(); } + + bool readSync(const Path& path, OutputMemoryStream& content) override { + std::string basename = Path::getFilename(const_cast(path.get())); + SH::PathHash hash = path.getHash(); + + auto i = packFiles.find(hash); + if (i == packFiles.end()) return false; + + content.resize(i->second.size); + MutexGuard lock(mutex); + + const size_t headerSize = sizeof(uint32_t) + packFiles.size() * (3 * sizeof(size_t)); + if (pack.seek(i->second.offset + headerSize) || !pack.read(content.dataMut(), content.size())) { + spdlog::error("Could not read file " + path.get() + " from the pack file."); + return false; + } + + return true; + } + + struct PackFile { + size_t offset; + size_t size; + }; + + std::map packFiles; + FileInput pack; + }; + + std::unique_ptr FileSystem::createDiskFS(const std::string& basePath) { + return std::make_unique(basePath); + } + + std::unique_ptr FileSystem::createVFS(const std::string& basePath) { + return std::make_unique(basePath); + } +} \ No newline at end of file diff --git a/projs/shadow/shadow-engine/assets/src/fs/iostream.cpp b/projs/shadow/shadow-engine/assets/src/fs/iostream.cpp new file mode 100644 index 00000000..14aeed36 --- /dev/null +++ b/projs/shadow/shadow-engine/assets/src/fs/iostream.cpp @@ -0,0 +1,227 @@ +#include +#include + +namespace SH { + + OutputMemoryStream::OutputMemoryStream(void *data, size_t size) + : buffer(static_cast(data)), capacity(size), usage(0) {} + + OutputMemoryStream::OutputMemoryStream(OutputMemoryStream &&str) noexcept { + capacity = str.capacity; + buffer = str.buffer; + usage = str.usage; + + str.free(); + } + + OutputMemoryStream& OutputMemoryStream::operator=(OutputMemoryStream &&str) noexcept { + capacity = str.capacity; + buffer = str.buffer; + usage = str.usage; + + str.free(); + return *this; + } + + OutputMemoryStream& OutputMemoryStream::operator=(const OutputMemoryStream &rhs) noexcept { + usage = rhs.usage; + + if (rhs.capacity > 0) { + buffer = (uint8_t*)malloc(rhs.capacity); + memcpy(buffer, rhs.buffer, rhs.capacity); + capacity = rhs.capacity; + } else { + buffer = nullptr; + capacity = 0; + } + + return *this; + } + + OutputMemoryStream::OutputMemoryStream(const OutputMemoryStream &rhs) noexcept { + usage = rhs.usage; + + if (rhs.capacity > 0) { + buffer = (uint8_t*)malloc(rhs.capacity); + memcpy(buffer, rhs.buffer, rhs.capacity); + capacity = rhs.capacity; + } else { + buffer = nullptr; + capacity = 0; + } + } + + + OutputMemoryStream::~OutputMemoryStream() = default; + + OutputStream &OutputStream::operator<<(std::string &str) { + write(str.data(), str.length()); + return *this; + } + + OutputStream &OutputStream::operator<<(const char* str) { + write(str, strlen(str)); + return *this; + } + + OutputStream &OutputStream::operator<<(uint32_t val) { + std::string str = std::to_string(val); + write(str.c_str(), str.length()); + return *this; + } + + OutputStream &OutputStream::operator<<(int32_t val) { + std::string str = std::to_string(val); + write(str.c_str(), str.length()); + return *this; + } + + OutputStream &OutputStream::operator<<(uint64_t val) { + std::string str = std::to_string(val); + write(str.c_str(), str.length()); + return *this; + } + + OutputStream &OutputStream::operator<<(int64_t val) { + std::string str = std::to_string(val); + write(str.c_str(), str.length()); + return *this; + } + + OutputStream &OutputStream::operator<<(float val) { + std::string str = std::to_string(val); + write(str.c_str(), str.length()); + return *this; + } + + OutputStream &OutputStream::operator<<(double val) { + std::string str = std::to_string(val); + write(str.c_str(), str.length()); + return *this; + } + + void OutputMemoryStream::write(std::string &str) { + write(str.c_str(), str.length()); + } + + void *OutputMemoryStream::skip(size_t size) { + if (size + usage > capacity) { + reserve((size + usage) << 1); + } + + void* ret = (uint8_t*)buffer + usage; + usage += size; + return ret; + } + + OutputMemoryStream& OutputMemoryStream::operator+=(size_t size) { + skip(size); + return *this; + } + + OutputMemoryStream& OutputMemoryStream::operator++() { + skip(1); + return *this; + } + + uint8_t OutputMemoryStream::operator[](size_t index) const { + return buffer[index]; + } + + uint8_t &OutputMemoryStream::operator[](size_t index) { + return buffer[index]; + } + + bool OutputMemoryStream::write(const void *data, size_t size) { + if (!size) return true; + + if (usage + size > capacity) { + reserve((usage + size) << 1); + } + + memcpy((uint8_t*)data + usage, data, size); + usage += size; + return true; + } + + void OutputMemoryStream::clear() { usage = 0; } + + void OutputMemoryStream::free() { + usage = 0; + capacity = 0; + delete[] buffer; + buffer = nullptr; + } + + void OutputMemoryStream::reserve(size_t size) { + if (size < capacity) return; + + auto* temp = static_cast(malloc(size)); + memcpy(temp, buffer, capacity); + delete[] buffer; + buffer = temp; + capacity = size; + } + + uint8_t *OutputMemoryStream::release() { + auto* temp = static_cast(malloc(usage)); + memcpy(temp, buffer, usage); + free(); + return temp; + } + + void OutputMemoryStream::resize(size_t size) { + usage = size; + if (usage <= capacity) return; + + uint8_t* temp = (uint8_t*) malloc(size); + memcpy(temp, buffer, capacity); + delete buffer; + buffer = temp; + capacity = size; + } + + InputMemoryStream::InputMemoryStream(const void *data, size_t size) + : data(static_cast(data)), capacity(size), position(0) {} + + InputMemoryStream::InputMemoryStream(const OutputMemoryStream &blob) + : data(blob.data()), capacity(blob.size()), position(0) {} + + void InputMemoryStream::set(const void *newData, size_t size) { + data = (uint8_t*) newData; capacity = size; position = 0; + } + + const void *InputMemoryStream::skip(size_t size) { + auto* pos = data + position; + position += size; + if (position > capacity) { + position = capacity; + } + + return (const void*) pos; + } + + bool InputMemoryStream::read(void *out, size_t size) { + if (position + (uint32_t) size > capacity) { + for (int32_t i = 0; i < size; i++) + ((unsigned char*)out)[i] = 0; + return false; + } + + if (size) { + memcpy(out, ((char*)data) + position, capacity); + } + + position += size; + + return true; + } + + std::string InputMemoryStream::readString() { + const char* ret = (const char*) data + position; + while (position < capacity && data[position]) ++position; + ++position; + + return { ret }; + } +} \ No newline at end of file diff --git a/projs/shadow/shadow-engine/assets/src/resource/Resource.cpp b/projs/shadow/shadow-engine/assets/src/resource/Resource.cpp new file mode 100644 index 00000000..28d1b306 --- /dev/null +++ b/projs/shadow/shadow-engine/assets/src/resource/Resource.cpp @@ -0,0 +1,197 @@ +#include "shadow/assets/resource/Resource.h" +#include "shadow/assets/fs/file.h" +#include +#include + +#include + +namespace SH { + const uint32_t ResourceHeader::MAGIC = 'VXIP'; + + ResourceType::ResourceType(const std::string& name) { + hash = HeapHash(name); + } + + Resource::Resource(Path path, ResourceTypeManager &manager) + : references(0), + emptyDependencies(0), + failedDependencies(0), + state(State::EMPTY), + desiredState(State::EMPTY), + path(std::move(path)), + size(), + callback(), + manager(manager), + handle(FileSystem::AsyncHandle::invalid()) { + } + + Resource::~Resource() = default; + + void Resource::refresh() { + if (state == State::EMPTY) return; + + const State old = state; + state = State::EMPTY; + callback.invoke(old, state, *this); + checkState(); + } + + void Resource::checkState() { + State old = state; + if (failedDependencies > 0 && state != State::FAILED) { + state = State::FAILED; + } else if (failedDependencies == 0) { + if (emptyDependencies > 0 && state != State::EMPTY) + state = State::EMPTY; + + if (emptyDependencies == 0 && state != State::READY && desiredState != State::EMPTY) { + onReadying(); + + if (emptyDependencies != 0 || state == State::READY || desiredState == State::EMPTY) + return; + + if (failedDependencies != 0) { + checkState(); + return; + } + + state = State::READY; + } + } + callback.invoke(old, state, *this); + } + + void Resource::fileLoaded(size_t fileSize, const uint8_t *mem, bool success) { + handle = FileSystem::AsyncHandle::invalid(); + if (desiredState != State::READY) return; + + if (!success) { + ResourceManager& owner = getManager().getOwner(); + if (!hooked && owner.isHooked()) { + if (owner.onLoad(*this) == ResourceManager::LoadHook::Action::DEFERRED) { + hooked = true; + desiredState = State::READY; + increaseReferences(); + return; + } + } + + --emptyDependencies; + ++failedDependencies; + checkState(); + handle = FileSystem::AsyncHandle::invalid(); + return; + } + + const auto* header = (const ResourceHeader*) mem; + + if (size < sizeof(*header)) { + spdlog::error("Invalid resource: ", path.get(), ": size mismatch. Expected ", fileSize, ", got " , sizeof(*header)); + failedDependencies++; + } else if (header->magic != ResourceHeader::MAGIC) { + spdlog::error("Invalid resource: " , path.get(), ": magic number mismatch. Expected " , ResourceHeader::MAGIC, ", got ", header->magic); + failedDependencies++; + } else if (header->version > 0) { + spdlog::error("Invalid resource: ", path.get(), ": verison mismatch. Expected 0, got ", header->version); + failedDependencies++; + } else { + // TODO: Compression? + if (!load(size - sizeof(*header), mem + sizeof(*header))) + failedDependencies++; + size = header->decompressedSize; + } + + emptyDependencies--; + checkState(); + handle = FileSystem::AsyncHandle::invalid(); + } + + void Resource::performUnload() { + if (handle.valid()) { + FileSystem& fs = manager.getOwner().getFileSystem(); + fs.cancelAsync(handle); + handle = FileSystem::AsyncHandle::invalid(); + } + + hooked = false; + desiredState = State::EMPTY; + unload(); + + size = 0; + emptyDependencies = 1; + failedDependencies = 0; + checkState(); + } + + void Resource::onCreated(State newState) { + state = newState; + desiredState = State::READY; + failedDependencies = state == State::FAILED ? 1 : 0; + emptyDependencies = 0; + } + + void Resource::doLoad() { + if (desiredState == State::READY) return; + desiredState = State::READY; + + if (handle.valid()) return; + + FileSystem& fs = manager.getOwner().getFileSystem(); + FileSystem::ContentCallback cb = makeDelegate<&Resource::fileLoaded>(this); + + const PathHash hash = path.getHash(); + Path resourcePath("./resources/" + std::to_string(hash.getHash()) + ".res"); + handle = fs.readAsync(resourcePath, cb); + } + + void Resource::addDependency(Resource &dependent) { + dependent.callback.bind<&Resource::stateChanged>(this); + if (dependent.isEmpty()) emptyDependencies++; + if (dependent.isFailure()) failedDependencies++; + + checkState(); + } + + void Resource::removeDependency(Resource &dependent) { + dependent.callback.unbind<&Resource::stateChanged>(this); + if (dependent.isEmpty()) --emptyDependencies; + if (dependent.isFailure()) --failedDependencies; + + checkState(); + } + + uint32_t Resource::decreaseReferences() { + --references; + if (references == 0 && manager.unloadEnabled) + performUnload(); + + return references; + } + + void Resource::stateChanged(State old, State newState, + Resource &) { + if (old == State::EMPTY) --emptyDependencies; + if (old == State::FAILED) --failedDependencies; + + if (newState == State::EMPTY) ++emptyDependencies; + if (newState == State::FAILED) ++failedDependencies; + + checkState(); + } + + const ResourceType PrefabResource::TYPE("prefab"); + + PrefabResource::PrefabResource(const Path &path, + ResourceTypeManager &resource_manager) : Resource(path, resource_manager) {} + + ResourceType PrefabResource::getType() const { return TYPE; } + + void PrefabResource::unload() { data.clear(); } + + bool PrefabResource::load(size_t size, const uint8_t *mem) { + data.resize(size); + memcpy(data.dataMut(), mem, size); + hash = StableHash(mem, size); + return true; + } +} \ No newline at end of file diff --git a/projs/shadow/shadow-engine/assets/src/resource/ResourceManager.cpp b/projs/shadow/shadow-engine/assets/src/resource/ResourceManager.cpp new file mode 100644 index 00000000..5b9a9c7c --- /dev/null +++ b/projs/shadow/shadow-engine/assets/src/resource/ResourceManager.cpp @@ -0,0 +1,200 @@ +#include "shadow/assets/resource/ResourceManager.h" +#include "shadow/assets/resource/Resource.h" +#include "spdlog/spdlog.h" + +namespace SH { + + ResourceManager* manager; + + void ResourceTypeManager::create(struct ResourceType type, struct ResourceManager &manager) { + manager.add(type, this); + owner = &manager; + } + + void ResourceTypeManager::destroy() { + for (auto iter = resources.begin(), end = resources.end(); iter != end; ++iter) { + Resource* res = iter->second; + if (!res->isEmpty()) + spdlog::error("Resource Type Manager destruction leaks ", res->path.get()); + + destroyResource(*res); + } + resources.clear(); + } + + Resource* ResourceTypeManager::get(const Path& path) { + auto it = resources.find(path.getHash()); + if (it != resources.end()) return it->second; + return nullptr; + } + + Resource* ResourceTypeManager::load(const Path &path) { + if (path.isEmpty()) return nullptr; + Resource* res = get(path); + if (res == nullptr) { + res = createResource(path); + resources[path.getHash()] = res; + } + + if (res->isEmpty() && res->desiredState == Resource::State::EMPTY) { + if (owner->onLoad(*res) == ResourceManager::LoadHook::Action::DEFERRED) { + res->hooked = true; + res->desiredState = Resource::State::READY; + res->increaseReferences(); + res->increaseReferences(); + return res; + } + + res->doLoad(); + } + + res->increaseReferences(); + return res; + } + + void ResourceTypeManager::removeUnreferencedResources() { + if (!unloadEnabled) return; + + std::vector toRemove; + for (auto i : resources) + if (i.second->getReferenceCount() == 0) toRemove.push_back(i.second); + + for (auto i : toRemove) { + auto iter = resources.find(i->getPath().getHash()); + if (iter->second->isReady()) iter->second->performUnload(); + } + } + + void ResourceTypeManager::reload(const Path &path) { + Resource* res = get(path); + if (res) reload(*res); + } + + void ResourceTypeManager::reload(Resource& res) { + if (res.state != Resource::State::EMPTY) + res.performUnload(); + else if (res.desiredState == Resource::State::READY) + return; + + if (owner->onLoad(res) == ResourceManager::LoadHook::Action::DEFERRED) { + res.hooked = true; + res.desiredState = Resource::State::READY; + res.increaseReferences(); + res.increaseReferences(); + } else { + res.performUnload(); + } + } + + void ResourceTypeManager::setUnloadable(bool status) { + unloadEnabled = status; + if (!unloadEnabled) return; + + for (auto res : resources) + if (res.second->getReferenceCount() == 0) + res.second->performUnload(); + } + + ResourceTypeManager::ResourceTypeManager() : + resources(), + owner(nullptr), + unloadEnabled(true) { + + } + + ResourceTypeManager::~ResourceTypeManager() { + + } + + ResourceManager::ResourceManager() : + managers(), + hook(nullptr), + filesystem(nullptr) { + manager = this; + } + + ResourceManager& ResourceManager::Get() { + return *manager; + } + + ResourceManager::~ResourceManager() = default; + + void ResourceManager::init(FileSystem &fs) { + filesystem = &fs; + } + + Resource* ResourceManager::load(ResourceType type, const Path& path) { + ResourceTypeManager* manager = get(type); + if (!manager) return nullptr; + return load(*manager, path); + } + + Resource* ResourceManager::load(ResourceTypeManager& manager, const Path& path) { + return manager.load(path); + } + + ResourceTypeManager* ResourceManager::get(ResourceType type) { + auto iter = managers.find(type); + if (iter == managers.end()) return nullptr; + return iter->second; + } + + void ResourceManager::LoadHook::continueLoad(Resource &res) { + res.decreaseReferences(); + res.hooked = false; + res.desiredState = Resource::State::EMPTY; + res.doLoad(); + } + + void ResourceManager::setLoadHook(LoadHook *loadHook) { + hook = loadHook; + + if (hook) + for (auto manager : managers) + for (auto res : manager.second->getResources()) + if (res.second->isFailure()) + manager.second->reload(*res.second); + } + + ResourceManager::LoadHook::Action ResourceManager::onLoad(Resource &res) const { + return hook ? hook->load(res) : LoadHook::Action::IMMEDIATE; + } + + void ResourceManager::add(ResourceType type, ResourceTypeManager* manager) { + managers[type] = manager; + } + + void ResourceManager::remove(ResourceType type) { + managers.erase(type); + } + + void ResourceManager::removeUnreferenced() { + for (auto manager : managers) + manager.second->removeUnreferencedResources(); + } + + void ResourceManager::setUnloadable(bool enable) { + for (auto manager : managers) + manager.second->setUnloadable(enable); + } + + void ResourceManager::reloadAll() { + while (filesystem->hasWork()) filesystem->processCallbacks(); + + std::vector toReload; + for (auto manager : managers) { + ResourceTypeManager::ResourceTable& resources = manager.second->getResources(); + for (auto res : resources) { + if (res.second->isReady()) { + res.second->performUnload(); + toReload.push_back(res.second); + } + } + } + } + + void ResourceManager::reload(const Path& path) { + for (auto manager : managers) + manager.second->reload(path); + } +} \ No newline at end of file diff --git a/projs/shadow/shadow-engine/assets/test/Catch2Test.cpp b/projs/shadow/shadow-engine/assets/test/Catch2Test.cpp new file mode 100644 index 00000000..11727edd --- /dev/null +++ b/projs/shadow/shadow-engine/assets/test/Catch2Test.cpp @@ -0,0 +1,6 @@ +#define CATCH_CONFIG_MAIN +#include "catch2/catch.hpp" + +TEST_CASE("15 is less than 20", "[numbers]") { + REQUIRE(15 < 20); +} \ No newline at end of file diff --git a/projs/shadow/shadow-engine/assets/test/catch2/catch.hpp b/projs/shadow/shadow-engine/assets/test/catch2/catch.hpp new file mode 100644 index 00000000..0e6f70b6 --- /dev/null +++ b/projs/shadow/shadow-engine/assets/test/catch2/catch.hpp @@ -0,0 +1,17970 @@ +/* + * Catch v2.13.9 + * Generated: 2022-04-12 22:37:23.260201 + * ---------------------------------------------------------- + * This file has been merged from multiple headers. Please don't edit it directly + * Copyright (c) 2022 Two Blue Cubes Ltd. All rights reserved. + * + * Distributed under the Boost Software License, Version 1.0. (See accompanying + * file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + */ +#ifndef TWOBLUECUBES_SINGLE_INCLUDE_CATCH_HPP_INCLUDED +#define TWOBLUECUBES_SINGLE_INCLUDE_CATCH_HPP_INCLUDED +// start catch.hpp + + +#define CATCH_VERSION_MAJOR 2 +#define CATCH_VERSION_MINOR 13 +#define CATCH_VERSION_PATCH 9 + +#ifdef __clang__ +# pragma clang system_header +#elif defined __GNUC__ +# pragma GCC system_header +#endif + +// start catch_suppress_warnings.h + +#ifdef __clang__ +# ifdef __ICC // icpc defines the __clang__ macro +# pragma warning(push) +# pragma warning(disable: 161 1682) +# else // __ICC +# pragma clang diagnostic push +# pragma clang diagnostic ignored "-Wpadded" +# pragma clang diagnostic ignored "-Wswitch-enum" +# pragma clang diagnostic ignored "-Wcovered-switch-default" +# endif +#elif defined __GNUC__ + // Because REQUIREs trigger GCC's -Wparentheses, and because still + // supported version of g++ have only buggy support for _Pragmas, + // Wparentheses have to be suppressed globally. +# pragma GCC diagnostic ignored "-Wparentheses" // See #674 for details + +# pragma GCC diagnostic push +# pragma GCC diagnostic ignored "-Wunused-variable" +# pragma GCC diagnostic ignored "-Wpadded" +#endif +// end catch_suppress_warnings.h +#if defined(CATCH_CONFIG_MAIN) || defined(CATCH_CONFIG_RUNNER) +# define CATCH_IMPL +# define CATCH_CONFIG_ALL_PARTS +#endif + +// In the impl file, we want to have access to all parts of the headers +// Can also be used to sanely support PCHs +#if defined(CATCH_CONFIG_ALL_PARTS) +# define CATCH_CONFIG_EXTERNAL_INTERFACES +# if defined(CATCH_CONFIG_DISABLE_MATCHERS) +# undef CATCH_CONFIG_DISABLE_MATCHERS +# endif +# if !defined(CATCH_CONFIG_ENABLE_CHRONO_STRINGMAKER) +# define CATCH_CONFIG_ENABLE_CHRONO_STRINGMAKER +# endif +#endif + +#if !defined(CATCH_CONFIG_IMPL_ONLY) +// start catch_platform.h + +// See e.g.: +// https://opensource.apple.com/source/CarbonHeaders/CarbonHeaders-18.1/TargetConditionals.h.auto.html +#ifdef __APPLE__ +# include +# if (defined(TARGET_OS_OSX) && TARGET_OS_OSX == 1) || \ + (defined(TARGET_OS_MAC) && TARGET_OS_MAC == 1) +# define CATCH_PLATFORM_MAC +# elif (defined(TARGET_OS_IPHONE) && TARGET_OS_IPHONE == 1) +# define CATCH_PLATFORM_IPHONE +# endif + +#elif defined(linux) || defined(__linux) || defined(__linux__) +# define CATCH_PLATFORM_LINUX + +#elif defined(WIN32) || defined(__WIN32__) || defined(_WIN32) || defined(_MSC_VER) || defined(__MINGW32__) +# define CATCH_PLATFORM_WINDOWS +#endif + +// end catch_platform.h + +#ifdef CATCH_IMPL +# ifndef CLARA_CONFIG_MAIN +# define CLARA_CONFIG_MAIN_NOT_DEFINED +# define CLARA_CONFIG_MAIN +# endif +#endif + +// start catch_user_interfaces.h + +namespace Catch { + unsigned int rngSeed(); +} + +// end catch_user_interfaces.h +// start catch_tag_alias_autoregistrar.h + +// start catch_common.h + +// start catch_compiler_capabilities.h + +// Detect a number of compiler features - by compiler +// The following features are defined: +// +// CATCH_CONFIG_COUNTER : is the __COUNTER__ macro supported? +// CATCH_CONFIG_WINDOWS_SEH : is Windows SEH supported? +// CATCH_CONFIG_POSIX_SIGNALS : are POSIX signals supported? +// CATCH_CONFIG_DISABLE_EXCEPTIONS : Are exceptions enabled? +// **************** +// Note to maintainers: if new toggles are added please document them +// in configuration.md, too +// **************** + +// In general each macro has a _NO_ form +// (e.g. CATCH_CONFIG_NO_POSIX_SIGNALS) which disables the feature. +// Many features, at point of detection, define an _INTERNAL_ macro, so they +// can be combined, en-mass, with the _NO_ forms later. + +#ifdef __cplusplus + +# if (__cplusplus >= 201402L) || (defined(_MSVC_LANG) && _MSVC_LANG >= 201402L) +# define CATCH_CPP14_OR_GREATER +# endif + +# if (__cplusplus >= 201703L) || (defined(_MSVC_LANG) && _MSVC_LANG >= 201703L) +# define CATCH_CPP17_OR_GREATER +# endif + +#endif + +// Only GCC compiler should be used in this block, so other compilers trying to +// mask themselves as GCC should be ignored. +#if defined(__GNUC__) && !defined(__clang__) && !defined(__ICC) && !defined(__CUDACC__) && !defined(__LCC__) +# define CATCH_INTERNAL_START_WARNINGS_SUPPRESSION _Pragma( "GCC diagnostic push" ) +# define CATCH_INTERNAL_STOP_WARNINGS_SUPPRESSION _Pragma( "GCC diagnostic pop" ) + +# define CATCH_INTERNAL_IGNORE_BUT_WARN(...) (void)__builtin_constant_p(__VA_ARGS__) + +#endif + +#if defined(__clang__) + +# define CATCH_INTERNAL_START_WARNINGS_SUPPRESSION _Pragma( "clang diagnostic push" ) +# define CATCH_INTERNAL_STOP_WARNINGS_SUPPRESSION _Pragma( "clang diagnostic pop" ) + +// As of this writing, IBM XL's implementation of __builtin_constant_p has a bug +// which results in calls to destructors being emitted for each temporary, +// without a matching initialization. In practice, this can result in something +// like `std::string::~string` being called on an uninitialized value. +// +// For example, this code will likely segfault under IBM XL: +// ``` +// REQUIRE(std::string("12") + "34" == "1234") +// ``` +// +// Therefore, `CATCH_INTERNAL_IGNORE_BUT_WARN` is not implemented. +# if !defined(__ibmxl__) && !defined(__CUDACC__) +# define CATCH_INTERNAL_IGNORE_BUT_WARN(...) (void)__builtin_constant_p(__VA_ARGS__) /* NOLINT(cppcoreguidelines-pro-type-vararg, hicpp-vararg) */ +# endif + +# define CATCH_INTERNAL_SUPPRESS_GLOBALS_WARNINGS \ + _Pragma( "clang diagnostic ignored \"-Wexit-time-destructors\"" ) \ + _Pragma( "clang diagnostic ignored \"-Wglobal-constructors\"") + +# define CATCH_INTERNAL_SUPPRESS_PARENTHESES_WARNINGS \ + _Pragma( "clang diagnostic ignored \"-Wparentheses\"" ) + +# define CATCH_INTERNAL_SUPPRESS_UNUSED_WARNINGS \ + _Pragma( "clang diagnostic ignored \"-Wunused-variable\"" ) + +# define CATCH_INTERNAL_SUPPRESS_ZERO_VARIADIC_WARNINGS \ + _Pragma( "clang diagnostic ignored \"-Wgnu-zero-variadic-macro-arguments\"" ) + +# define CATCH_INTERNAL_SUPPRESS_UNUSED_TEMPLATE_WARNINGS \ + _Pragma( "clang diagnostic ignored \"-Wunused-template\"" ) + +#endif // __clang__ + +//////////////////////////////////////////////////////////////////////////////// +// Assume that non-Windows platforms support posix signals by default +#if !defined(CATCH_PLATFORM_WINDOWS) + #define CATCH_INTERNAL_CONFIG_POSIX_SIGNALS +#endif + +//////////////////////////////////////////////////////////////////////////////// +// We know some environments not to support full POSIX signals +#if defined(__CYGWIN__) || defined(__QNX__) || defined(__EMSCRIPTEN__) || defined(__DJGPP__) + #define CATCH_INTERNAL_CONFIG_NO_POSIX_SIGNALS +#endif + +#ifdef __OS400__ +# define CATCH_INTERNAL_CONFIG_NO_POSIX_SIGNALS +# define CATCH_CONFIG_COLOUR_NONE +#endif + +//////////////////////////////////////////////////////////////////////////////// +// Android somehow still does not support std::to_string +#if defined(__ANDROID__) +# define CATCH_INTERNAL_CONFIG_NO_CPP11_TO_STRING +# define CATCH_INTERNAL_CONFIG_ANDROID_LOGWRITE +#endif + +//////////////////////////////////////////////////////////////////////////////// +// Not all Windows environments support SEH properly +#if defined(__MINGW32__) +# define CATCH_INTERNAL_CONFIG_NO_WINDOWS_SEH +#endif + +//////////////////////////////////////////////////////////////////////////////// +// PS4 +#if defined(__ORBIS__) +# define CATCH_INTERNAL_CONFIG_NO_NEW_CAPTURE +#endif + +//////////////////////////////////////////////////////////////////////////////// +// Cygwin +#ifdef __CYGWIN__ + +// Required for some versions of Cygwin to declare gettimeofday +// see: http://stackoverflow.com/questions/36901803/gettimeofday-not-declared-in-this-scope-cygwin +# define _BSD_SOURCE +// some versions of cygwin (most) do not support std::to_string. Use the libstd check. +// https://gcc.gnu.org/onlinedocs/gcc-4.8.2/libstdc++/api/a01053_source.html line 2812-2813 +# if !((__cplusplus >= 201103L) && defined(_GLIBCXX_USE_C99) \ + && !defined(_GLIBCXX_HAVE_BROKEN_VSWPRINTF)) + +# define CATCH_INTERNAL_CONFIG_NO_CPP11_TO_STRING + +# endif +#endif // __CYGWIN__ + +//////////////////////////////////////////////////////////////////////////////// +// Visual C++ +#if defined(_MSC_VER) + +// Universal Windows platform does not support SEH +// Or console colours (or console at all...) +# if defined(WINAPI_FAMILY) && (WINAPI_FAMILY == WINAPI_FAMILY_APP) +# define CATCH_CONFIG_COLOUR_NONE +# else +# define CATCH_INTERNAL_CONFIG_WINDOWS_SEH +# endif + +# if !defined(__clang__) // Handle Clang masquerading for msvc + +// MSVC traditional preprocessor needs some workaround for __VA_ARGS__ +// _MSVC_TRADITIONAL == 0 means new conformant preprocessor +// _MSVC_TRADITIONAL == 1 means old traditional non-conformant preprocessor +# if !defined(_MSVC_TRADITIONAL) || (defined(_MSVC_TRADITIONAL) && _MSVC_TRADITIONAL) +# define CATCH_INTERNAL_CONFIG_TRADITIONAL_MSVC_PREPROCESSOR +# endif // MSVC_TRADITIONAL + +// Only do this if we're not using clang on Windows, which uses `diagnostic push` & `diagnostic pop` +# define CATCH_INTERNAL_START_WARNINGS_SUPPRESSION __pragma( warning(push) ) +# define CATCH_INTERNAL_STOP_WARNINGS_SUPPRESSION __pragma( warning(pop) ) +# endif // __clang__ + +#endif // _MSC_VER + +#if defined(_REENTRANT) || defined(_MSC_VER) +// Enable async processing, as -pthread is specified or no additional linking is required +# define CATCH_INTERNAL_CONFIG_USE_ASYNC +#endif // _MSC_VER + +//////////////////////////////////////////////////////////////////////////////// +// Check if we are compiled with -fno-exceptions or equivalent +#if defined(__EXCEPTIONS) || defined(__cpp_exceptions) || defined(_CPPUNWIND) +# define CATCH_INTERNAL_CONFIG_EXCEPTIONS_ENABLED +#endif + +//////////////////////////////////////////////////////////////////////////////// +// DJGPP +#ifdef __DJGPP__ +# define CATCH_INTERNAL_CONFIG_NO_WCHAR +#endif // __DJGPP__ + +//////////////////////////////////////////////////////////////////////////////// +// Embarcadero C++Build +#if defined(__BORLANDC__) + #define CATCH_INTERNAL_CONFIG_POLYFILL_ISNAN +#endif + +//////////////////////////////////////////////////////////////////////////////// + +// Use of __COUNTER__ is suppressed during code analysis in +// CLion/AppCode 2017.2.x and former, because __COUNTER__ is not properly +// handled by it. +// Otherwise all supported compilers support COUNTER macro, +// but user still might want to turn it off +#if ( !defined(__JETBRAINS_IDE__) || __JETBRAINS_IDE__ >= 20170300L ) + #define CATCH_INTERNAL_CONFIG_COUNTER +#endif + +//////////////////////////////////////////////////////////////////////////////// + +// RTX is a special version of Windows that is real time. +// This means that it is detected as Windows, but does not provide +// the same set of capabilities as real Windows does. +#if defined(UNDER_RTSS) || defined(RTX64_BUILD) + #define CATCH_INTERNAL_CONFIG_NO_WINDOWS_SEH + #define CATCH_INTERNAL_CONFIG_NO_ASYNC + #define CATCH_CONFIG_COLOUR_NONE +#endif + +#if !defined(_GLIBCXX_USE_C99_MATH_TR1) +#define CATCH_INTERNAL_CONFIG_GLOBAL_NEXTAFTER +#endif + +// Various stdlib support checks that require __has_include +#if defined(__has_include) + // Check if string_view is available and usable + #if __has_include() && defined(CATCH_CPP17_OR_GREATER) + # define CATCH_INTERNAL_CONFIG_CPP17_STRING_VIEW + #endif + + // Check if optional is available and usable + # if __has_include() && defined(CATCH_CPP17_OR_GREATER) + # define CATCH_INTERNAL_CONFIG_CPP17_OPTIONAL + # endif // __has_include() && defined(CATCH_CPP17_OR_GREATER) + + // Check if byte is available and usable + # if __has_include() && defined(CATCH_CPP17_OR_GREATER) + # include + # if defined(__cpp_lib_byte) && (__cpp_lib_byte > 0) + # define CATCH_INTERNAL_CONFIG_CPP17_BYTE + # endif + # endif // __has_include() && defined(CATCH_CPP17_OR_GREATER) + + // Check if variant is available and usable + # if __has_include() && defined(CATCH_CPP17_OR_GREATER) + # if defined(__clang__) && (__clang_major__ < 8) + // work around clang bug with libstdc++ https://bugs.llvm.org/show_bug.cgi?id=31852 + // fix should be in clang 8, workaround in libstdc++ 8.2 + # include + # if defined(__GLIBCXX__) && defined(_GLIBCXX_RELEASE) && (_GLIBCXX_RELEASE < 9) + # define CATCH_CONFIG_NO_CPP17_VARIANT + # else + # define CATCH_INTERNAL_CONFIG_CPP17_VARIANT + # endif // defined(__GLIBCXX__) && defined(_GLIBCXX_RELEASE) && (_GLIBCXX_RELEASE < 9) + # else + # define CATCH_INTERNAL_CONFIG_CPP17_VARIANT + # endif // defined(__clang__) && (__clang_major__ < 8) + # endif // __has_include() && defined(CATCH_CPP17_OR_GREATER) +#endif // defined(__has_include) + +#if defined(CATCH_INTERNAL_CONFIG_COUNTER) && !defined(CATCH_CONFIG_NO_COUNTER) && !defined(CATCH_CONFIG_COUNTER) +# define CATCH_CONFIG_COUNTER +#endif +#if defined(CATCH_INTERNAL_CONFIG_WINDOWS_SEH) && !defined(CATCH_CONFIG_NO_WINDOWS_SEH) && !defined(CATCH_CONFIG_WINDOWS_SEH) && !defined(CATCH_INTERNAL_CONFIG_NO_WINDOWS_SEH) +# define CATCH_CONFIG_WINDOWS_SEH +#endif +// This is set by default, because we assume that linux compilers are posix-signal-compatible by default. +#if defined(CATCH_INTERNAL_CONFIG_POSIX_SIGNALS) && !defined(CATCH_INTERNAL_CONFIG_NO_POSIX_SIGNALS) && !defined(CATCH_CONFIG_NO_POSIX_SIGNALS) && !defined(CATCH_CONFIG_POSIX_SIGNALS) +# define CATCH_CONFIG_POSIX_SIGNALS +#endif +// This is set by default, because we assume that compilers with no wchar_t support are just rare exceptions. +#if !defined(CATCH_INTERNAL_CONFIG_NO_WCHAR) && !defined(CATCH_CONFIG_NO_WCHAR) && !defined(CATCH_CONFIG_WCHAR) +# define CATCH_CONFIG_WCHAR +#endif + +#if !defined(CATCH_INTERNAL_CONFIG_NO_CPP11_TO_STRING) && !defined(CATCH_CONFIG_NO_CPP11_TO_STRING) && !defined(CATCH_CONFIG_CPP11_TO_STRING) +# define CATCH_CONFIG_CPP11_TO_STRING +#endif + +#if defined(CATCH_INTERNAL_CONFIG_CPP17_OPTIONAL) && !defined(CATCH_CONFIG_NO_CPP17_OPTIONAL) && !defined(CATCH_CONFIG_CPP17_OPTIONAL) +# define CATCH_CONFIG_CPP17_OPTIONAL +#endif + +#if defined(CATCH_INTERNAL_CONFIG_CPP17_STRING_VIEW) && !defined(CATCH_CONFIG_NO_CPP17_STRING_VIEW) && !defined(CATCH_CONFIG_CPP17_STRING_VIEW) +# define CATCH_CONFIG_CPP17_STRING_VIEW +#endif + +#if defined(CATCH_INTERNAL_CONFIG_CPP17_VARIANT) && !defined(CATCH_CONFIG_NO_CPP17_VARIANT) && !defined(CATCH_CONFIG_CPP17_VARIANT) +# define CATCH_CONFIG_CPP17_VARIANT +#endif + +#if defined(CATCH_INTERNAL_CONFIG_CPP17_BYTE) && !defined(CATCH_CONFIG_NO_CPP17_BYTE) && !defined(CATCH_CONFIG_CPP17_BYTE) +# define CATCH_CONFIG_CPP17_BYTE +#endif + +#if defined(CATCH_CONFIG_EXPERIMENTAL_REDIRECT) +# define CATCH_INTERNAL_CONFIG_NEW_CAPTURE +#endif + +#if defined(CATCH_INTERNAL_CONFIG_NEW_CAPTURE) && !defined(CATCH_INTERNAL_CONFIG_NO_NEW_CAPTURE) && !defined(CATCH_CONFIG_NO_NEW_CAPTURE) && !defined(CATCH_CONFIG_NEW_CAPTURE) +# define CATCH_CONFIG_NEW_CAPTURE +#endif + +#if !defined(CATCH_INTERNAL_CONFIG_EXCEPTIONS_ENABLED) && !defined(CATCH_CONFIG_DISABLE_EXCEPTIONS) +# define CATCH_CONFIG_DISABLE_EXCEPTIONS +#endif + +#if defined(CATCH_INTERNAL_CONFIG_POLYFILL_ISNAN) && !defined(CATCH_CONFIG_NO_POLYFILL_ISNAN) && !defined(CATCH_CONFIG_POLYFILL_ISNAN) +# define CATCH_CONFIG_POLYFILL_ISNAN +#endif + +#if defined(CATCH_INTERNAL_CONFIG_USE_ASYNC) && !defined(CATCH_INTERNAL_CONFIG_NO_ASYNC) && !defined(CATCH_CONFIG_NO_USE_ASYNC) && !defined(CATCH_CONFIG_USE_ASYNC) +# define CATCH_CONFIG_USE_ASYNC +#endif + +#if defined(CATCH_INTERNAL_CONFIG_ANDROID_LOGWRITE) && !defined(CATCH_CONFIG_NO_ANDROID_LOGWRITE) && !defined(CATCH_CONFIG_ANDROID_LOGWRITE) +# define CATCH_CONFIG_ANDROID_LOGWRITE +#endif + +#if defined(CATCH_INTERNAL_CONFIG_GLOBAL_NEXTAFTER) && !defined(CATCH_CONFIG_NO_GLOBAL_NEXTAFTER) && !defined(CATCH_CONFIG_GLOBAL_NEXTAFTER) +# define CATCH_CONFIG_GLOBAL_NEXTAFTER +#endif + +// Even if we do not think the compiler has that warning, we still have +// to provide a macro that can be used by the code. +#if !defined(CATCH_INTERNAL_START_WARNINGS_SUPPRESSION) +# define CATCH_INTERNAL_START_WARNINGS_SUPPRESSION +#endif +#if !defined(CATCH_INTERNAL_STOP_WARNINGS_SUPPRESSION) +# define CATCH_INTERNAL_STOP_WARNINGS_SUPPRESSION +#endif +#if !defined(CATCH_INTERNAL_SUPPRESS_PARENTHESES_WARNINGS) +# define CATCH_INTERNAL_SUPPRESS_PARENTHESES_WARNINGS +#endif +#if !defined(CATCH_INTERNAL_SUPPRESS_GLOBALS_WARNINGS) +# define CATCH_INTERNAL_SUPPRESS_GLOBALS_WARNINGS +#endif +#if !defined(CATCH_INTERNAL_SUPPRESS_UNUSED_WARNINGS) +# define CATCH_INTERNAL_SUPPRESS_UNUSED_WARNINGS +#endif +#if !defined(CATCH_INTERNAL_SUPPRESS_ZERO_VARIADIC_WARNINGS) +# define CATCH_INTERNAL_SUPPRESS_ZERO_VARIADIC_WARNINGS +#endif + +// The goal of this macro is to avoid evaluation of the arguments, but +// still have the compiler warn on problems inside... +#if !defined(CATCH_INTERNAL_IGNORE_BUT_WARN) +# define CATCH_INTERNAL_IGNORE_BUT_WARN(...) +#endif + +#if defined(__APPLE__) && defined(__apple_build_version__) && (__clang_major__ < 10) +# undef CATCH_INTERNAL_SUPPRESS_UNUSED_TEMPLATE_WARNINGS +#elif defined(__clang__) && (__clang_major__ < 5) +# undef CATCH_INTERNAL_SUPPRESS_UNUSED_TEMPLATE_WARNINGS +#endif + +#if !defined(CATCH_INTERNAL_SUPPRESS_UNUSED_TEMPLATE_WARNINGS) +# define CATCH_INTERNAL_SUPPRESS_UNUSED_TEMPLATE_WARNINGS +#endif + +#if defined(CATCH_CONFIG_DISABLE_EXCEPTIONS) +#define CATCH_TRY if ((true)) +#define CATCH_CATCH_ALL if ((false)) +#define CATCH_CATCH_ANON(type) if ((false)) +#else +#define CATCH_TRY try +#define CATCH_CATCH_ALL catch (...) +#define CATCH_CATCH_ANON(type) catch (type) +#endif + +#if defined(CATCH_INTERNAL_CONFIG_TRADITIONAL_MSVC_PREPROCESSOR) && !defined(CATCH_CONFIG_NO_TRADITIONAL_MSVC_PREPROCESSOR) && !defined(CATCH_CONFIG_TRADITIONAL_MSVC_PREPROCESSOR) +#define CATCH_CONFIG_TRADITIONAL_MSVC_PREPROCESSOR +#endif + +// end catch_compiler_capabilities.h +#define INTERNAL_CATCH_UNIQUE_NAME_LINE2( name, line ) name##line +#define INTERNAL_CATCH_UNIQUE_NAME_LINE( name, line ) INTERNAL_CATCH_UNIQUE_NAME_LINE2( name, line ) +#ifdef CATCH_CONFIG_COUNTER +# define INTERNAL_CATCH_UNIQUE_NAME( name ) INTERNAL_CATCH_UNIQUE_NAME_LINE( name, __COUNTER__ ) +#else +# define INTERNAL_CATCH_UNIQUE_NAME( name ) INTERNAL_CATCH_UNIQUE_NAME_LINE( name, __LINE__ ) +#endif + +#include +#include +#include + +// We need a dummy global operator<< so we can bring it into Catch namespace later +struct Catch_global_namespace_dummy {}; +std::ostream& operator<<(std::ostream&, Catch_global_namespace_dummy); + +namespace Catch { + + struct CaseSensitive { enum Choice { + Yes, + No + }; }; + + class NonCopyable { + NonCopyable( NonCopyable const& ) = delete; + NonCopyable( NonCopyable && ) = delete; + NonCopyable& operator = ( NonCopyable const& ) = delete; + NonCopyable& operator = ( NonCopyable && ) = delete; + + protected: + NonCopyable(); + virtual ~NonCopyable(); + }; + + struct SourceLineInfo { + + SourceLineInfo() = delete; + SourceLineInfo( char const* _file, std::size_t _line ) noexcept + : file( _file ), + line( _line ) + {} + + SourceLineInfo( SourceLineInfo const& other ) = default; + SourceLineInfo& operator = ( SourceLineInfo const& ) = default; + SourceLineInfo( SourceLineInfo&& ) noexcept = default; + SourceLineInfo& operator = ( SourceLineInfo&& ) noexcept = default; + + bool empty() const noexcept { return file[0] == '\0'; } + bool operator == ( SourceLineInfo const& other ) const noexcept; + bool operator < ( SourceLineInfo const& other ) const noexcept; + + char const* file; + std::size_t line; + }; + + std::ostream& operator << ( std::ostream& os, SourceLineInfo const& info ); + + // Bring in operator<< from global namespace into Catch namespace + // This is necessary because the overload of operator<< above makes + // lookup stop at namespace Catch + using ::operator<<; + + // Use this in variadic streaming macros to allow + // >> +StreamEndStop + // as well as + // >> stuff +StreamEndStop + struct StreamEndStop { + std::string operator+() const; + }; + template + T const& operator + ( T const& value, StreamEndStop ) { + return value; + } +} + +#define CATCH_INTERNAL_LINEINFO \ + ::Catch::SourceLineInfo( __FILE__, static_cast( __LINE__ ) ) + +// end catch_common.h +namespace Catch { + + struct RegistrarForTagAliases { + RegistrarForTagAliases( char const* alias, char const* tag, SourceLineInfo const& lineInfo ); + }; + +} // end namespace Catch + +#define CATCH_REGISTER_TAG_ALIAS( alias, spec ) \ + CATCH_INTERNAL_START_WARNINGS_SUPPRESSION \ + CATCH_INTERNAL_SUPPRESS_GLOBALS_WARNINGS \ + namespace{ Catch::RegistrarForTagAliases INTERNAL_CATCH_UNIQUE_NAME( AutoRegisterTagAlias )( alias, spec, CATCH_INTERNAL_LINEINFO ); } \ + CATCH_INTERNAL_STOP_WARNINGS_SUPPRESSION + +// end catch_tag_alias_autoregistrar.h +// start catch_test_registry.h + +// start catch_interfaces_testcase.h + +#include + +namespace Catch { + + class TestSpec; + + struct ITestInvoker { + virtual void invoke () const = 0; + virtual ~ITestInvoker(); + }; + + class TestCase; + struct IConfig; + + struct ITestCaseRegistry { + virtual ~ITestCaseRegistry(); + virtual std::vector const& getAllTests() const = 0; + virtual std::vector const& getAllTestsSorted( IConfig const& config ) const = 0; + }; + + bool isThrowSafe( TestCase const& testCase, IConfig const& config ); + bool matchTest( TestCase const& testCase, TestSpec const& testSpec, IConfig const& config ); + std::vector filterTests( std::vector const& testCases, TestSpec const& testSpec, IConfig const& config ); + std::vector const& getAllTestCasesSorted( IConfig const& config ); + +} + +// end catch_interfaces_testcase.h +// start catch_stringref.h + +#include +#include +#include +#include + +namespace Catch { + + /// A non-owning string class (similar to the forthcoming std::string_view) + /// Note that, because a StringRef may be a substring of another string, + /// it may not be null terminated. + class StringRef { + public: + using size_type = std::size_t; + using const_iterator = const char*; + + private: + static constexpr char const* const s_empty = ""; + + char const* m_start = s_empty; + size_type m_size = 0; + + public: // construction + constexpr StringRef() noexcept = default; + + StringRef( char const* rawChars ) noexcept; + + constexpr StringRef( char const* rawChars, size_type size ) noexcept + : m_start( rawChars ), + m_size( size ) + {} + + StringRef( std::string const& stdString ) noexcept + : m_start( stdString.c_str() ), + m_size( stdString.size() ) + {} + + explicit operator std::string() const { + return std::string(m_start, m_size); + } + + public: // operators + auto operator == ( StringRef const& other ) const noexcept -> bool; + auto operator != (StringRef const& other) const noexcept -> bool { + return !(*this == other); + } + + auto operator[] ( size_type index ) const noexcept -> char { + assert(index < m_size); + return m_start[index]; + } + + public: // named queries + constexpr auto empty() const noexcept -> bool { + return m_size == 0; + } + constexpr auto size() const noexcept -> size_type { + return m_size; + } + + // Returns the current start pointer. If the StringRef is not + // null-terminated, throws std::domain_exception + auto c_str() const -> char const*; + + public: // substrings and searches + // Returns a substring of [start, start + length). + // If start + length > size(), then the substring is [start, size()). + // If start > size(), then the substring is empty. + auto substr( size_type start, size_type length ) const noexcept -> StringRef; + + // Returns the current start pointer. May not be null-terminated. + auto data() const noexcept -> char const*; + + constexpr auto isNullTerminated() const noexcept -> bool { + return m_start[m_size] == '\0'; + } + + public: // iterators + constexpr const_iterator begin() const { return m_start; } + constexpr const_iterator end() const { return m_start + m_size; } + }; + + auto operator += ( std::string& lhs, StringRef const& sr ) -> std::string&; + auto operator << ( std::ostream& os, StringRef const& sr ) -> std::ostream&; + + constexpr auto operator "" _sr( char const* rawChars, std::size_t size ) noexcept -> StringRef { + return StringRef( rawChars, size ); + } +} // namespace Catch + +constexpr auto operator "" _catch_sr( char const* rawChars, std::size_t size ) noexcept -> Catch::StringRef { + return Catch::StringRef( rawChars, size ); +} + +// end catch_stringref.h +// start catch_preprocessor.hpp + + +#define CATCH_RECURSION_LEVEL0(...) __VA_ARGS__ +#define CATCH_RECURSION_LEVEL1(...) CATCH_RECURSION_LEVEL0(CATCH_RECURSION_LEVEL0(CATCH_RECURSION_LEVEL0(__VA_ARGS__))) +#define CATCH_RECURSION_LEVEL2(...) CATCH_RECURSION_LEVEL1(CATCH_RECURSION_LEVEL1(CATCH_RECURSION_LEVEL1(__VA_ARGS__))) +#define CATCH_RECURSION_LEVEL3(...) CATCH_RECURSION_LEVEL2(CATCH_RECURSION_LEVEL2(CATCH_RECURSION_LEVEL2(__VA_ARGS__))) +#define CATCH_RECURSION_LEVEL4(...) CATCH_RECURSION_LEVEL3(CATCH_RECURSION_LEVEL3(CATCH_RECURSION_LEVEL3(__VA_ARGS__))) +#define CATCH_RECURSION_LEVEL5(...) CATCH_RECURSION_LEVEL4(CATCH_RECURSION_LEVEL4(CATCH_RECURSION_LEVEL4(__VA_ARGS__))) + +#ifdef CATCH_CONFIG_TRADITIONAL_MSVC_PREPROCESSOR +#define INTERNAL_CATCH_EXPAND_VARGS(...) __VA_ARGS__ +// MSVC needs more evaluations +#define CATCH_RECURSION_LEVEL6(...) CATCH_RECURSION_LEVEL5(CATCH_RECURSION_LEVEL5(CATCH_RECURSION_LEVEL5(__VA_ARGS__))) +#define CATCH_RECURSE(...) CATCH_RECURSION_LEVEL6(CATCH_RECURSION_LEVEL6(__VA_ARGS__)) +#else +#define CATCH_RECURSE(...) CATCH_RECURSION_LEVEL5(__VA_ARGS__) +#endif + +#define CATCH_REC_END(...) +#define CATCH_REC_OUT + +#define CATCH_EMPTY() +#define CATCH_DEFER(id) id CATCH_EMPTY() + +#define CATCH_REC_GET_END2() 0, CATCH_REC_END +#define CATCH_REC_GET_END1(...) CATCH_REC_GET_END2 +#define CATCH_REC_GET_END(...) CATCH_REC_GET_END1 +#define CATCH_REC_NEXT0(test, next, ...) next CATCH_REC_OUT +#define CATCH_REC_NEXT1(test, next) CATCH_DEFER ( CATCH_REC_NEXT0 ) ( test, next, 0) +#define CATCH_REC_NEXT(test, next) CATCH_REC_NEXT1(CATCH_REC_GET_END test, next) + +#define CATCH_REC_LIST0(f, x, peek, ...) , f(x) CATCH_DEFER ( CATCH_REC_NEXT(peek, CATCH_REC_LIST1) ) ( f, peek, __VA_ARGS__ ) +#define CATCH_REC_LIST1(f, x, peek, ...) , f(x) CATCH_DEFER ( CATCH_REC_NEXT(peek, CATCH_REC_LIST0) ) ( f, peek, __VA_ARGS__ ) +#define CATCH_REC_LIST2(f, x, peek, ...) f(x) CATCH_DEFER ( CATCH_REC_NEXT(peek, CATCH_REC_LIST1) ) ( f, peek, __VA_ARGS__ ) + +#define CATCH_REC_LIST0_UD(f, userdata, x, peek, ...) , f(userdata, x) CATCH_DEFER ( CATCH_REC_NEXT(peek, CATCH_REC_LIST1_UD) ) ( f, userdata, peek, __VA_ARGS__ ) +#define CATCH_REC_LIST1_UD(f, userdata, x, peek, ...) , f(userdata, x) CATCH_DEFER ( CATCH_REC_NEXT(peek, CATCH_REC_LIST0_UD) ) ( f, userdata, peek, __VA_ARGS__ ) +#define CATCH_REC_LIST2_UD(f, userdata, x, peek, ...) f(userdata, x) CATCH_DEFER ( CATCH_REC_NEXT(peek, CATCH_REC_LIST1_UD) ) ( f, userdata, peek, __VA_ARGS__ ) + +// Applies the function macro `f` to each of the remaining parameters, inserts commas between the results, +// and passes userdata as the first parameter to each invocation, +// e.g. CATCH_REC_LIST_UD(f, x, a, b, c) evaluates to f(x, a), f(x, b), f(x, c) +#define CATCH_REC_LIST_UD(f, userdata, ...) CATCH_RECURSE(CATCH_REC_LIST2_UD(f, userdata, __VA_ARGS__, ()()(), ()()(), ()()(), 0)) + +#define CATCH_REC_LIST(f, ...) CATCH_RECURSE(CATCH_REC_LIST2(f, __VA_ARGS__, ()()(), ()()(), ()()(), 0)) + +#define INTERNAL_CATCH_EXPAND1(param) INTERNAL_CATCH_EXPAND2(param) +#define INTERNAL_CATCH_EXPAND2(...) INTERNAL_CATCH_NO## __VA_ARGS__ +#define INTERNAL_CATCH_DEF(...) INTERNAL_CATCH_DEF __VA_ARGS__ +#define INTERNAL_CATCH_NOINTERNAL_CATCH_DEF +#define INTERNAL_CATCH_STRINGIZE(...) INTERNAL_CATCH_STRINGIZE2(__VA_ARGS__) +#ifndef CATCH_CONFIG_TRADITIONAL_MSVC_PREPROCESSOR +#define INTERNAL_CATCH_STRINGIZE2(...) #__VA_ARGS__ +#define INTERNAL_CATCH_STRINGIZE_WITHOUT_PARENS(param) INTERNAL_CATCH_STRINGIZE(INTERNAL_CATCH_REMOVE_PARENS(param)) +#else +// MSVC is adding extra space and needs another indirection to expand INTERNAL_CATCH_NOINTERNAL_CATCH_DEF +#define INTERNAL_CATCH_STRINGIZE2(...) INTERNAL_CATCH_STRINGIZE3(__VA_ARGS__) +#define INTERNAL_CATCH_STRINGIZE3(...) #__VA_ARGS__ +#define INTERNAL_CATCH_STRINGIZE_WITHOUT_PARENS(param) (INTERNAL_CATCH_STRINGIZE(INTERNAL_CATCH_REMOVE_PARENS(param)) + 1) +#endif + +#define INTERNAL_CATCH_MAKE_NAMESPACE2(...) ns_##__VA_ARGS__ +#define INTERNAL_CATCH_MAKE_NAMESPACE(name) INTERNAL_CATCH_MAKE_NAMESPACE2(name) + +#define INTERNAL_CATCH_REMOVE_PARENS(...) INTERNAL_CATCH_EXPAND1(INTERNAL_CATCH_DEF __VA_ARGS__) + +#ifndef CATCH_CONFIG_TRADITIONAL_MSVC_PREPROCESSOR +#define INTERNAL_CATCH_MAKE_TYPE_LIST2(...) decltype(get_wrapper()) +#define INTERNAL_CATCH_MAKE_TYPE_LIST(...) INTERNAL_CATCH_MAKE_TYPE_LIST2(INTERNAL_CATCH_REMOVE_PARENS(__VA_ARGS__)) +#else +#define INTERNAL_CATCH_MAKE_TYPE_LIST2(...) INTERNAL_CATCH_EXPAND_VARGS(decltype(get_wrapper())) +#define INTERNAL_CATCH_MAKE_TYPE_LIST(...) INTERNAL_CATCH_EXPAND_VARGS(INTERNAL_CATCH_MAKE_TYPE_LIST2(INTERNAL_CATCH_REMOVE_PARENS(__VA_ARGS__))) +#endif + +#define INTERNAL_CATCH_MAKE_TYPE_LISTS_FROM_TYPES(...)\ + CATCH_REC_LIST(INTERNAL_CATCH_MAKE_TYPE_LIST,__VA_ARGS__) + +#define INTERNAL_CATCH_REMOVE_PARENS_1_ARG(_0) INTERNAL_CATCH_REMOVE_PARENS(_0) +#define INTERNAL_CATCH_REMOVE_PARENS_2_ARG(_0, _1) INTERNAL_CATCH_REMOVE_PARENS(_0), INTERNAL_CATCH_REMOVE_PARENS_1_ARG(_1) +#define INTERNAL_CATCH_REMOVE_PARENS_3_ARG(_0, _1, _2) INTERNAL_CATCH_REMOVE_PARENS(_0), INTERNAL_CATCH_REMOVE_PARENS_2_ARG(_1, _2) +#define INTERNAL_CATCH_REMOVE_PARENS_4_ARG(_0, _1, _2, _3) INTERNAL_CATCH_REMOVE_PARENS(_0), INTERNAL_CATCH_REMOVE_PARENS_3_ARG(_1, _2, _3) +#define INTERNAL_CATCH_REMOVE_PARENS_5_ARG(_0, _1, _2, _3, _4) INTERNAL_CATCH_REMOVE_PARENS(_0), INTERNAL_CATCH_REMOVE_PARENS_4_ARG(_1, _2, _3, _4) +#define INTERNAL_CATCH_REMOVE_PARENS_6_ARG(_0, _1, _2, _3, _4, _5) INTERNAL_CATCH_REMOVE_PARENS(_0), INTERNAL_CATCH_REMOVE_PARENS_5_ARG(_1, _2, _3, _4, _5) +#define INTERNAL_CATCH_REMOVE_PARENS_7_ARG(_0, _1, _2, _3, _4, _5, _6) INTERNAL_CATCH_REMOVE_PARENS(_0), INTERNAL_CATCH_REMOVE_PARENS_6_ARG(_1, _2, _3, _4, _5, _6) +#define INTERNAL_CATCH_REMOVE_PARENS_8_ARG(_0, _1, _2, _3, _4, _5, _6, _7) INTERNAL_CATCH_REMOVE_PARENS(_0), INTERNAL_CATCH_REMOVE_PARENS_7_ARG(_1, _2, _3, _4, _5, _6, _7) +#define INTERNAL_CATCH_REMOVE_PARENS_9_ARG(_0, _1, _2, _3, _4, _5, _6, _7, _8) INTERNAL_CATCH_REMOVE_PARENS(_0), INTERNAL_CATCH_REMOVE_PARENS_8_ARG(_1, _2, _3, _4, _5, _6, _7, _8) +#define INTERNAL_CATCH_REMOVE_PARENS_10_ARG(_0, _1, _2, _3, _4, _5, _6, _7, _8, _9) INTERNAL_CATCH_REMOVE_PARENS(_0), INTERNAL_CATCH_REMOVE_PARENS_9_ARG(_1, _2, _3, _4, _5, _6, _7, _8, _9) +#define INTERNAL_CATCH_REMOVE_PARENS_11_ARG(_0, _1, _2, _3, _4, _5, _6, _7, _8, _9, _10) INTERNAL_CATCH_REMOVE_PARENS(_0), INTERNAL_CATCH_REMOVE_PARENS_10_ARG(_1, _2, _3, _4, _5, _6, _7, _8, _9, _10) + +#define INTERNAL_CATCH_VA_NARGS_IMPL(_0, _1, _2, _3, _4, _5, _6, _7, _8, _9, _10, N, ...) N + +#define INTERNAL_CATCH_TYPE_GEN\ + template struct TypeList {};\ + template\ + constexpr auto get_wrapper() noexcept -> TypeList { return {}; }\ + template class...> struct TemplateTypeList{};\ + template class...Cs>\ + constexpr auto get_wrapper() noexcept -> TemplateTypeList { return {}; }\ + template\ + struct append;\ + template\ + struct rewrap;\ + template class, typename...>\ + struct create;\ + template class, typename>\ + struct convert;\ + \ + template \ + struct append { using type = T; };\ + template< template class L1, typename...E1, template class L2, typename...E2, typename...Rest>\ + struct append, L2, Rest...> { using type = typename append, Rest...>::type; };\ + template< template class L1, typename...E1, typename...Rest>\ + struct append, TypeList, Rest...> { using type = L1; };\ + \ + template< template class Container, template class List, typename...elems>\ + struct rewrap, List> { using type = TypeList>; };\ + template< template class Container, template class List, class...Elems, typename...Elements>\ + struct rewrap, List, Elements...> { using type = typename append>, typename rewrap, Elements...>::type>::type; };\ + \ + template