diff --git a/CMakeLists.txt b/CMakeLists.txt index e81faae2..82d1aa80 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -4,294 +4,14 @@ project(metal_engine CXX) set(CMAKE_CXX_STANDARD 20) set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -DVK_PROTOTYPES") -add_executable( - metal_engine - src/main.cpp - src/context/editor/EditorPanel.cpp - src/context/editor/EditorPanel.h - src/context/editor/abstract/IPanel.h - src/context/engine/EngineContext.cpp - src/context/engine/EngineContext.h - src/util/VulkanUtils.cpp - src/util/VulkanUtils.h - src/context/vulkan/VulkanContext.cpp - src/context/vulkan/VulkanContext.h - src/context/glfw/GLFWContext.cpp - src/context/glfw/GLFWContext.h - src/context/gui/GuiContext.cpp - src/context/gui/GuiContext.h - src/context/editor/dock-spaces/viewport/ViewportPanel.cpp - src/context/editor/dock-spaces/viewport/ViewportPanel.h - src/context/editor/dock-spaces/viewport/EngineFramePanel.cpp - src/context/editor/dock-spaces/viewport/EngineFramePanel.h - src/context/editor/dock-spaces/docks/AbstractDockPanel.h - src/context/ApplicationContext.cpp - src/context/ApplicationContext.h - src/context/editor/abstract/AbstractPanel.h - src/context/editor/abstract/AbstractPanel.cpp - src/common/interface/Synchornizable.h - src/service/camera/CameraService.cpp - src/service/camera/CameraService.h - src/service/camera/Camera.h - src/util/Util.h - src/common/inspection/Inspectable.h - src/common/inspection/Inspectable.cpp - src/common/inspection/InspectedField.h - src/context/editor/dock-spaces/inspector/InspectorPanel.cpp - src/context/editor/dock-spaces/inspector/InspectorPanel.h - src/context/editor/abstract/form/FormPanel.cpp - src/context/editor/abstract/form/FormPanel.h - src/context/editor/abstract/form/AccordionPanel.cpp - src/context/editor/abstract/form/AccordionPanel.h - src/enum/FieldType.h - src/common/inspection/InspectableMember.h - src/common/AbstractRuntimeComponent.h - src/context/editor/abstract/form/types/BooleanField.cpp - src/context/editor/abstract/form/types/BooleanField.h - src/context/editor/abstract/form/types/IntField.cpp - src/context/editor/abstract/form/types/IntField.h - src/context/editor/abstract/form/types/FloatField.cpp - src/context/editor/abstract/form/types/FloatField.h - src/context/editor/abstract/form/types/MethodField.cpp - src/context/editor/abstract/form/types/MethodField.h - src/util/UIUtil.h - src/context/editor/dock-spaces/header/EditorHeaderPanel.cpp - src/context/editor/dock-spaces/header/EditorHeaderPanel.h - src/context/editor/dock-spaces/header/AsyncTaskPanel.cpp - src/context/editor/dock-spaces/header/AsyncTaskPanel.h - src/common/interface/Icons.h - src/service/dock/DockService.cpp - src/service/dock/DockService.h - src/repository/dock/DockRepository.h - src/repository/dock/DockDTO.h - src/repository/dock/DockSpace.h - src/repository/dock/DockPosition.h - src/context/editor/dock-spaces/docks/DockSpacePanel.cpp - src/context/editor/dock-spaces/docks/DockSpacePanel.h - src/repository/dock/DockSpace.cpp - src/service/theme/ThemeService.cpp - src/service/theme/ThemeService.h - src/repository/editor/EditorRepository.h - src/enum/engine-definitions.h - src/context/editor/dock-spaces/files/FilesPanel.cpp - src/context/editor/dock-spaces/files/FilesPanel.h - src/context/editor/dock-spaces/files/FilesListPanel.cpp - src/context/editor/dock-spaces/files/FilesListPanel.h - src/context/editor/dock-spaces/files/FilePreviewPanel.cpp - src/context/editor/dock-spaces/files/FilePreviewPanel.h - src/context/editor/dock-spaces/console/ConsolePanel.cpp - src/context/editor/dock-spaces/console/ConsolePanel.h - src/context/editor/dock-spaces/metrics/MetricsPanel.cpp - src/context/editor/dock-spaces/metrics/MetricsPanel.h - src/service/log/LogService.cpp - src/service/log/LogService.h - src/context/editor/dock-spaces/world/WorldPanel.cpp - src/context/editor/dock-spaces/world/WorldPanel.h - src/repository/abstract/RuntimeResource.h - src/util/ShaderUtil.cpp - src/util/ShaderUtil.h - src/service/pipeline/ShaderModule.cpp - src/service/pipeline/ShaderModule.h - src/context/engine/render-pass/AbstractRenderPass.cpp - src/context/engine/render-pass/AbstractRenderPass.h - src/service/abstract/AbstractResourceService.h - src/service/framebuffer/FrameBufferAttachment.h - src/repository/abstract/AbstractCoreRepository.h - src/service/framebuffer/FrameBufferService.cpp - src/service/framebuffer/FrameBufferService.h - src/service/framebuffer/FrameBufferInstance.h - src/service/pipeline/PipelineService.cpp - src/service/pipeline/PipelineService.h - src/service/pipeline/PipelineInstance.h - src/service/buffer/BufferService.cpp - src/service/buffer/BufferService.h - src/service/descriptor/DescriptorSetService.cpp - src/service/descriptor/DescriptorSetService.h - src/service/descriptor/DescriptorInstance.h - src/dto/buffers/GlobalDataUBO.h - src/repository/runtime/RuntimeRepository.h - src/service/buffer/BufferInstance.cpp - src/service/buffer/BufferInstance.h - src/service/mesh/MeshService.cpp - src/service/mesh/MeshService.h - src/service/mesh/MeshData.h - src/service/mesh/MeshInstance.h - src/util/FilesUtil.h - src/dto/file/FSEntry.h - src/enum/EntryType.h - src/context/editor/dock-spaces/files/FilesContext.h - src/util/FileDialogUtil.h - src/context/editor/dock-spaces/files/FilesHeaderPanel.cpp - src/context/editor/dock-spaces/files/FilesHeaderPanel.h - src/service/material/MaterialImporterService.cpp - src/service/material/MaterialImporterService.h - src/service/mesh/MeshImporterService.cpp - src/service/mesh/MeshImporterService.h - src/service/mesh/SceneImporterService.cpp - src/service/mesh/SceneImporterService.h - src/service/abstract/AbstractImporter.h - src/service/texture/TextureImporterService.cpp - src/service/texture/TextureImporterService.h - src/dto/file/EntryMetadata.h - src/service/texture/TextureData.h - src/service/texture/TextureService.cpp - src/service/texture/TextureService.h - src/service/files/FilesService.cpp - src/service/files/FilesService.h - src/service/files/FileImporterService.cpp - src/service/files/FileImporterService.h - src/context/editor/dock-spaces/files/FilesContext.cpp - src/service/mesh/VertexData.h - src/context/editor/dock-spaces/viewport/CameraPositionPanel.cpp - src/context/editor/dock-spaces/viewport/CameraPositionPanel.h - src/context/engine/render-pass/impl/tools/GridPass.cpp - src/context/engine/render-pass/impl/tools/GridPass.h - src/context/engine/passes/CommandBufferRecorder.cpp - src/context/engine/passes/CommandBufferRecorder.h - src/service/camera/Camera.cpp - src/repository/world/WorldRepository.cpp - src/repository/world/WorldRepository.h - src/repository/world/impl/MetadataComponent.h - src/enum/ComponentType.cpp - src/enum/ComponentType.h - src/repository/world/impl/AbstractComponent.h - src/repository/world/components/PrimitiveComponent.h - src/repository/world/components/TransformComponent.h - src/enum/ShadingMode.h - src/context/editor/dock-spaces/world/WorldHeaderPanel.cpp - src/context/editor/dock-spaces/world/WorldHeaderPanel.h - src/service/selection/SelectionService.cpp - src/service/selection/SelectionService.h - src/repository/world/impl/MetadataComponent.cpp - src/repository/world/components/TransformComponent.cpp - src/repository/world/components/PrimitiveComponent.cpp - src/context/editor/abstract/form/types/ResourceField.cpp - src/context/editor/abstract/form/types/ResourceField.h - src/context/editor/abstract/form/types/ColorField.cpp - src/context/editor/abstract/form/types/ColorField.h - src/context/editor/abstract/form/types/Vec4Field.cpp - src/context/editor/abstract/form/types/Vec4Field.h - src/context/editor/abstract/form/types/Vec3Field.cpp - src/context/editor/abstract/form/types/Vec3Field.h - src/context/editor/abstract/form/types/Vec2Field.cpp - src/context/editor/abstract/form/types/Vec2Field.h - src/context/editor/abstract/form/types/StringField.cpp - src/context/editor/abstract/form/types/StringField.h - src/context/editor/abstract/form/types/ResourceFilesPanel.h - src/context/editor/abstract/form/types/ResourceFilesPanel.cpp - src/repository/streaming/StreamingService.cpp - src/repository/streaming/StreamingService.h - src/enum/ResourceType.h - src/context/editor/dock-spaces/viewport/GizmoPanel.cpp - src/context/editor/dock-spaces/viewport/GizmoPanel.h - src/context/editor/dock-spaces/viewport/ViewportHeaderPanel.cpp - src/context/editor/dock-spaces/viewport/ViewportHeaderPanel.h - src/context/editor/dock-spaces/viewport/GizmoSettingsPanel.cpp - src/context/editor/dock-spaces/viewport/GizmoSettingsPanel.h - src/context/editor/abstract/form/types/QuatField.cpp - src/context/editor/abstract/form/types/QuatField.h - src/service/transform/TransformService.cpp - src/service/transform/TransformService.h - src/repository/world/impl/BoundingBox.h - src/service/voxel/impl/SparseVoxelOctreeBuilder.cpp - src/service/voxel/impl/SparseVoxelOctreeBuilder.h - src/service/voxel/impl/OctreeNode.cpp - src/service/voxel/impl/OctreeNode.h - src/service/voxel/impl/VoxelData.h - src/service/mesh/SceneData.h - src/context/engine/render-pass/impl/PostProcessingPass.cpp - src/context/engine/render-pass/impl/PostProcessingPass.h - src/context/engine/compute-pass/impl/HWRayTracingPass.cpp - src/context/engine/compute-pass/impl/HWRayTracingPass.h - src/service/raytracing/RayTracingService.cpp - src/service/raytracing/RayTracingService.h - src/service/pipeline/PipelineBuilder.h - src/service/framebuffer/FrameBufferAttachment.cpp - src/repository/engine/EngineRepository.cpp - src/repository/engine/EngineRepository.h - src/util/serialization-definitions.h - src/service/notification/NotificationService.cpp - src/service/notification/NotificationService.h - src/service/notification/AsyncTaskService.cpp - src/service/notification/AsyncTaskService.h - src/dto/Notification.h - src/enum/NotificationSeverity.h - src/service/voxel/impl/SparseVoxelOctreeData.h - src/context/engine/render-pass/impl/tools/SelectionOutlinePass.cpp - src/context/engine/render-pass/impl/tools/SelectionOutlinePass.h - src/service/picking/PickingService.cpp - src/service/picking/PickingService.h - src/service/voxel/SVOInstance.h - src/dto/buffers/TileInfoUBO.h - src/dto/buffers/LightData.h - src/context/engine/render-pass/impl/tools/IconsPass.cpp - src/context/engine/render-pass/impl/tools/IconsPass.h - src/context/engine/render-pass/impl/tools/SelectionIDPass.cpp - src/context/engine/render-pass/impl/tools/SelectionIDPass.h - src/repository/editor/EditorRepository.cpp - src/dto/push-constant/GridPushConstant.h - src/context/engine/compute-pass/AbstractComputePass.cpp - src/context/engine/compute-pass/AbstractComputePass.h - src/context/engine/passes/AbstractPass.cpp - src/context/engine/passes/AbstractPass.h - src/util/ImageUtils.h - src/service/material/MaterialService.cpp - src/service/material/MaterialService.h - src/enum/LightType.h - src/service/lights/LightService.cpp - src/service/lights/LightService.h - src/repository/world/components/VolumeComponent.cpp - src/repository/world/components/VolumeComponent.h - src/service/descriptor/DescriptorBinding.h - src/service/notification/AsyncTask.h - src/service/voxel/VoxelImporterService.cpp - src/service/voxel/VoxelImporterService.h - src/dto/buffers/VolumeData.h - src/service/voxel/VoxelService.cpp - src/service/voxel/VoxelService.h - src/util/Serializable.cpp - src/context/editor/abstract/form/ChildPanel.cpp - src/context/editor/abstract/form/ChildPanel.h - src/dto/file/SceneImportSettingsDTO.h - src/context/editor/panel/NotificationsPanel.cpp - src/context/editor/panel/NotificationsPanel.h - src/context/editor/panel/FileImportModalPanel.cpp - src/context/editor/panel/FileImportModalPanel.h - src/context/engine/frame-builder/EngineFrameBuilder.cpp - src/context/engine/frame-builder/EngineFrameBuilder.h - src/context/engine/frame-builder/EngineFrame.cpp - src/context/engine/frame-builder/EngineFrame.h - src/context/engine/frame-builder/structures/FramebufferBuilder.cpp - src/context/engine/frame-builder/structures/FramebufferBuilder.h - src/context/engine/frame-builder/structures/TextureBuilder.cpp - src/context/engine/frame-builder/structures/TextureBuilder.h - src/context/engine/frame-builder/structures/BufferBuilder.cpp - src/context/engine/frame-builder/structures/BufferBuilder.h - src/context/engine/frame-builder/structures/ResourceBuilder.h - src/service/pipeline/PipelineBuilder.cpp - src/service/descriptor/DescriptorSetService.cpp - src/context/engine/frame-builder/structures/PassBuilder.cpp - src/context/engine/frame-builder/structures/CommandBufferRecorderBuilder.cpp - src/common/interface/Changeable.h - src/context/engine/compute-pass/impl/TemporalAccumulationPass.cpp - src/context/engine/compute-pass/impl/TemporalAccumulationPass.h - src/context/engine/compute-pass/impl/SpatialFilterPass.cpp - src/context/engine/compute-pass/impl/SpatialFilterPass.h - src/enum/ComponentType.cpp - src/service/mesh/SceneEntityData.h - src/context/editor/dock-spaces/repositories/RepositoriesPanel.cpp - src/context/editor/dock-spaces/repositories/RepositoriesPanel.h - src/service/volumes/VolumeService.cpp - src/service/volumes/VolumeService.h - src/repository/dock/DockRepository.cpp -) - +if (MSVC) + add_compile_options(/utf-8) +endif() # ------ LIBS find_package(glfw3 REQUIRED) find_package(glm REQUIRED) find_package(imgui REQUIRED) -find_package(spdlog CONFIG REQUIRED) find_package(nlohmann_json CONFIG REQUIRED) find_package(Vulkan) find_package(VulkanMemoryAllocator CONFIG REQUIRED) @@ -302,6 +22,7 @@ find_package(assimp CONFIG REQUIRED) find_package(meshoptimizer CONFIG REQUIRED) find_package(cereal CONFIG REQUIRED) find_package(OpenVDB CONFIG REQUIRED) +find_package(EnTT CONFIG REQUIRED) set(COMMON_LIBRARIES glfw @@ -316,24 +37,34 @@ set(COMMON_LIBRARIES glm::glm imgui::imgui imguizmo::imguizmo - spdlog::spdlog nlohmann_json::nlohmann_json + EnTT::EnTT glslang::glslang glslang::glslang-default-resource-limits glslang::SPVRemapper OpenVDB::openvdb ) -target_link_libraries(metal_engine PRIVATE ${COMMON_LIBRARIES}) + add_subdirectory(dependencies/vk-bootstrap) # ------ LIBS + +add_subdirectory(src) +enable_testing() +add_subdirectory(tests) + # ------ STATIC RESOURCES -file(COPY "${CMAKE_SOURCE_DIR}/resources" DESTINATION "${CMAKE_BINARY_DIR}/") +file(GLOB_RECURSE RESOURCE_FILES "resources/*") +add_custom_target(copy_resources ALL + COMMAND ${CMAKE_COMMAND} -E copy_directory + "${CMAKE_SOURCE_DIR}/resources" + "${CMAKE_BINARY_DIR}/resources" + DEPENDS ${RESOURCE_FILES} + COMMENT "Copying resources to build directory" +) # ------ STATIC RESOURCES # ------ VCPKG - -#set(CMAKE_TOOLCHAIN_FILE "Users/cafe/.vcpkg-clion/vcpkg/scripts/buildsystems/vcpkg.cmake") set(VCPKG_JSON_PATH "${CMAKE_CURRENT_SOURCE_DIR}/vcpkg.json") # Include vcpkg toolchain diff --git a/resources/shaders/rt/HWRayTracing.rgen b/resources/shaders/rt/HWRayTracing.rgen index c09ac1bd..69e273fc 100644 --- a/resources/shaders/rt/HWRayTracing.rgen +++ b/resources/shaders/rt/HWRayTracing.rgen @@ -1,4 +1,6 @@ #extension GL_EXT_ray_tracing: require +#define ITEM_TYPE_SPHERE 0 +#define ITEM_TYPE_PLANE 1 #include "../GlobalDataBuffer.glsl" #include "../rt/HWRayTracingPushConstant.glsl" diff --git a/resources/shaders/tools/Icon.frag b/resources/shaders/tools/Icon.frag deleted file mode 100644 index 4a281c2a..00000000 --- a/resources/shaders/tools/Icon.frag +++ /dev/null @@ -1,90 +0,0 @@ -#include "../GlobalDataBuffer.glsl" -#include "../CreateRay.glsl" - -#define LIGHT_SET 1 -#include "../LightBuffer.glsl" - -layout (location = 0) in vec2 texCoords; -layout (location = 0) out vec4 finalColor; - -float sdSphere(vec3 p, float s, in vec3 translation){ - return length(p - translation)-s; -} -float dot2(vec3 v) { - return dot(v, v); -} -float udQuad(vec3 p, vec3 a, vec3 b, vec3 c, vec3 d) -{ - vec3 ba = b - a; vec3 pa = p - a; - vec3 cb = c - b; vec3 pb = p - b; - vec3 dc = d - c; vec3 pc = p - c; - vec3 ad = a - d; vec3 pd = p - d; - vec3 nor = cross(ba, ad); - - return sqrt( - (sign(dot(cross(ba, nor), pa)) + - sign(dot(cross(cb, nor), pb)) + - sign(dot(cross(dc, nor), pc)) + - sign(dot(cross(ad, nor), pd))<3.0) - ? - min(min(min( - dot2(ba*clamp(dot(ba, pa)/dot2(ba), 0.0, 1.0)-pa), - dot2(cb*clamp(dot(cb, pb)/dot2(cb), 0.0, 1.0)-pb)), - dot2(dc*clamp(dot(dc, pc)/dot2(dc), 0.0, 1.0)-pc)), - dot2(ad*clamp(dot(ad, pd)/dot2(ad), 0.0, 1.0)-pd)) - : - dot(nor, pa)*dot(nor, pa)/dot2(nor)); -} - -bool rayMarch(vec3 ro, vec3 rd, in Light l) { - float t = 0.0; - for (int i = 0; i < 256; i++) { - vec3 p = ro + t * rd; - float d; - - switch (l.itemType){ - case ITEM_TYPE_SPHERE:{ - d = sdSphere(p, l.dataB.x, l.position); - break; - } - case ITEM_TYPE_PLANE:{ - vec3 reference = abs(l.dataA.y) > 0.999 ? vec3(1.0, 0.0, 0.0) : vec3(0.0, 1.0, 0.0); - vec3 right = normalize(cross(l.dataA, reference)); - vec3 up = normalize(cross(right, l.dataA)); - - // Use correct plane dimensions - vec3 halfRight = right * (l.dataB.z * 0.5); - vec3 halfUp = up * (l.dataB.x * 0.5); - - vec3 a = l.position - halfRight - halfUp; - vec3 b = l.position + halfRight - halfUp; - vec3 c = l.position + halfRight + halfUp; - vec3 dl = l.position - halfRight + halfUp; - d = udQuad(p, a, b, c, dl); - break; - } - default :{ - return false; - } - } - if (d < 0.001) return true; - if (t > 100.0) break; - t += d; - } - return false; -} - -void main(){ - if (globalData.lightsCount == 0){ - discard; - } - vec3 dir = createRay(texCoords, globalData.invProj, globalData.invView); - for (uint i = 0; i < globalData.lightsCount; i++){ - Light l = lightBuffer.items[i]; - if (rayMarch(globalData.cameraWorldPosition.xyz, dir, l)){ - finalColor = vec4(l.color.rgb * l.color.a, 1); - return; - } - } - discard; -} \ No newline at end of file diff --git a/resources/shaders/tools/SelectedDot.frag b/resources/shaders/tools/SelectionOutline.frag similarity index 100% rename from resources/shaders/tools/SelectedDot.frag rename to resources/shaders/tools/SelectionOutline.frag diff --git a/src/ApplicationContext.cpp b/src/ApplicationContext.cpp new file mode 100644 index 00000000..df32e882 --- /dev/null +++ b/src/ApplicationContext.cpp @@ -0,0 +1,56 @@ +#include "ApplicationContext.h" + +#define STB_IMAGE_IMPLEMENTATION +#include "stb_image.h" +#define STB_IMAGE_WRITE_IMPLEMENTATION +#include "stb_image_write.h" +#define VMA_IMPLEMENTATION +#include + +#include "common/serialization-definitions.h" +#include "common/LoggerUtil.h" + +#include "engine/EngineContext.h" +#include "core/glfw/GLFWContext.h" + +namespace Metal { + ApplicationContext::ApplicationContext(bool debugMode) : debugMode(debugMode) { + } + + void ApplicationContext::onInitialize() { + for (auto &instance: instances) { + if (instance.get() != this) { + instance->setDependencies(*this); + } + } + + for (auto &instance: instances) { + if (instance.get() != this) { + auto *init = dynamic_cast(instance.get()); + if (init) { + init->onInitialize(); + } + } + } + } + + bool ApplicationContext::isDebugMode() const { + return debugMode; + } + + void ApplicationContext::dispose() { + try { + for (auto it = instances.rbegin(); it != instances.rend(); ++it) { + if (it->get() == this) { + continue; + } + auto *disposable = dynamic_cast(it->get()); + if (disposable) { + disposable->dispose(); + } + } + } catch (std::exception &e) { + LOG_ERROR(e.what()); + } + } +} diff --git a/src/ApplicationContext.h b/src/ApplicationContext.h new file mode 100644 index 00000000..c4de96c2 --- /dev/null +++ b/src/ApplicationContext.h @@ -0,0 +1,92 @@ +#ifndef METAL_ENGINE_APPLICATIONCONTEXT_H +#define METAL_ENGINE_APPLICATIONCONTEXT_H +#define GLM_FORCE_RADIANS +#define GLM_FORCE_DEPTH_ZERO_TO_ONE + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "common/IInit.h" +#include "common/IContextMember.h" +#include "common/IDisposable.h" + +#define ENGINE_NAME "Metal Engine" + +namespace Metal { + namespace fs = std::filesystem; + + class ApplicationContext : public IContextMember, public IInit, public IDisposable { + std::unordered_map singletons; + std::vector > instances; + bool debugMode; + + template + static std::string getTypeName() { + std::string name = typeid(T).name(); + size_t lastSpace = name.find_last_of(' '); + if (lastSpace != std::string::npos) { + name = name.substr(lastSpace + 1); + } + size_t lastColon = name.find_last_of(':'); + if (lastColon != std::string::npos) { + name = name.substr(lastColon + 1); + } + std::transform(name.begin(), name.end(), name.begin(), + [](unsigned char c) { return std::tolower(c); }); + return name; + } + + public: + explicit ApplicationContext(bool debugMode); + + void onInitialize() override; + + template + void registerSingleton(std::shared_ptr instance) { + static_assert(std::is_base_of_v, "T must derive from IContextMember"); + T *ptr = instance.get(); + singletons[getTypeName()] = static_cast(ptr); + instances.push_back(std::move(instance)); + } + + template + T &getSingleton() { + auto name = getTypeName(); + auto it = singletons.find(name); + if (it == singletons.end()) { + throw std::runtime_error(std::string("Singleton not registered: ") + name); + } + return *static_cast(it->second); + } + + void *getSingletonByName(const std::string &name) { + std::string lowerName = name; + std::transform(lowerName.begin(), lowerName.end(), lowerName.begin(), + [](unsigned char c) { return std::tolower(c); }); + auto it = singletons.find(lowerName); + if (it == singletons.end()) { + throw std::runtime_error(std::string("Singleton not registered: ") + lowerName); + } + return it->second; + } + + void injectDependencies(IContextMember *member) { + std::cout << "Injecting dependencies for: " << typeid(*member).name() << std::endl; + member->setDependencies(*this); + } + + [[nodiscard]] bool isDebugMode() const; + + void dispose() override; + }; +} + +#endif diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt new file mode 100644 index 00000000..e2b3bc36 --- /dev/null +++ b/src/CMakeLists.txt @@ -0,0 +1,296 @@ +set(ENGINE_SOURCES + main.cpp + editor/EditorPanel.cpp + editor/EditorPanel.h + engine/EngineContext.cpp + engine/EngineContext.h + core/vulkan/VulkanUtils.cpp + core/vulkan/VulkanUtils.h + core/vulkan/VulkanContext.cpp + core/vulkan/VulkanContext.h + core/glfw/GLFWContext.cpp + core/glfw/GLFWContext.h + core/gui/GuiContext.cpp + core/gui/GuiContext.h + editor/dock-spaces/viewport/ViewportPanel.cpp + editor/dock-spaces/viewport/ViewportPanel.h + editor/dock-spaces/viewport/EngineFramePanel.cpp + editor/dock-spaces/viewport/EngineFramePanel.h + editor/dock-spaces/docks/AbstractDockPanel.h + ApplicationContext.cpp + ApplicationContext.h + editor/abstract/AbstractPanel.h + editor/abstract/AbstractPanel.cpp + common/ISync.h + engine/service/CameraService.cpp + engine/service/CameraService.h + engine/dto/Camera.h + editor/util/Util.h + common/Inspectable.h + common/Inspectable.cpp + common/InspectedField.h + editor/dock-spaces/inspector/InspectorPanel.cpp + editor/dock-spaces/inspector/InspectorPanel.h + editor/abstract/form/FormPanel.cpp + editor/abstract/form/FormPanel.h + editor/abstract/form/AccordionPanel.cpp + editor/abstract/form/AccordionPanel.h + common/FieldType.h + common/InspectableMember.h + editor/abstract/form/types/BooleanField.cpp + editor/abstract/form/types/BooleanField.h + editor/abstract/form/types/IntField.cpp + editor/abstract/form/types/IntField.h + editor/abstract/form/types/FloatField.cpp + editor/abstract/form/types/FloatField.h + editor/abstract/form/types/MethodField.cpp + editor/abstract/form/types/MethodField.h + editor/util/UIUtil.h + editor/dock-spaces/header/EditorHeaderPanel.cpp + editor/dock-spaces/header/EditorHeaderPanel.h + editor/dock-spaces/header/AsyncTaskPanel.cpp + editor/dock-spaces/header/AsyncTaskPanel.h + editor/dock-spaces/footer/EditorFooterPanel.cpp + editor/dock-spaces/footer/EditorFooterPanel.h + common/Icons.h + editor/service/DockService.cpp + editor/service/DockService.h + editor/dto/DockDTO.h + editor/dto/DockSpace.h + editor/dock-spaces/docks/DockSpacePanel.cpp + editor/dock-spaces/docks/DockSpacePanel.h + editor/dto/DockSpace.cpp + editor/service/ThemeService.cpp + editor/service/ThemeService.h + editor/repository/EditorRepository.h + editor/enum/engine-definitions.h + editor/dock-spaces/files/FilesPanel.cpp + editor/dock-spaces/files/FilesPanel.h + editor/dock-spaces/files/FilesListPanel.cpp + editor/dock-spaces/files/FilesListPanel.h + editor/dock-spaces/files/FilePreviewPanel.cpp + editor/dock-spaces/files/FilePreviewPanel.h + editor/dock-spaces/console/ConsolePanel.cpp + editor/dock-spaces/console/ConsolePanel.h + editor/dock-spaces/metrics/MetricsPanel.cpp + editor/dock-spaces/metrics/MetricsPanel.h + common/LoggerUtil.cpp + common/LoggerUtil.h + editor/dock-spaces/world/WorldPanel.cpp + editor/dock-spaces/world/WorldPanel.h + engine/resource/RuntimeResource.h + engine/service/ShaderService.cpp + engine/service/ShaderService.h + engine/dto/ShaderModule.cpp + engine/dto/ShaderModule.h + engine/passes/AbstractRenderPass.cpp + engine/passes/AbstractRenderPass.h + common/AbstractResourceService.h + engine/resource/FrameBufferAttachment.h + engine/service/FrameBufferService.cpp + engine/service/FrameBufferService.h + engine/resource/FrameBufferInstance.h + engine/service/PipelineService.cpp + engine/service/PipelineService.h + engine/resource/PipelineInstance.h + engine/service/BufferService.cpp + engine/service/BufferService.h + engine/service/DescriptorSetService.cpp + engine/service/DescriptorSetService.h + engine/dto/DescriptorInstance.h + engine/dto/GlobalDataUBO.h + engine/repository/RuntimeRepository.h + engine/resource/BufferInstance.cpp + engine/resource/BufferInstance.h + engine/service/MeshService.cpp + engine/service/MeshService.h + engine/dto/MeshData.h + engine/resource/MeshInstance.h + common/FilesUtil.h + editor/dto/FSEntry.h + editor/enum/EntryType.h + editor/dock-spaces/files/FilesContext.h + common/FileDialogUtil.h + editor/dock-spaces/files/FilesHeaderPanel.cpp + editor/dock-spaces/files/FilesHeaderPanel.h + editor/service/MaterialImporterService.cpp + editor/service/MaterialImporterService.h + editor/service/MeshImporterService.cpp + editor/service/MeshImporterService.h + editor/service/SceneImporterService.cpp + editor/service/SceneImporterService.h + common/AbstractImporter.h + editor/service/TextureImporterService.cpp + editor/service/TextureImporterService.h + editor/dto/EntryMetadata.h + engine/dto/TextureData.h + engine/service/TextureService.cpp + engine/service/TextureService.h + editor/service/FilesService.cpp + editor/service/FilesService.h + editor/service/FileImporterService.cpp + editor/service/FileImporterService.h + editor/dock-spaces/files/FilesContext.cpp + engine/dto/VertexData.h + editor/dock-spaces/viewport/CameraPositionPanel.cpp + editor/dock-spaces/viewport/CameraPositionPanel.h + editor/passes/GridPass.cpp + editor/passes/GridPass.h + engine/passes/CommandBufferRecorder.cpp + engine/passes/CommandBufferRecorder.h + engine/dto/Camera.cpp + engine/repository/WorldRepository.cpp + engine/repository/WorldRepository.h + engine/dto/MetadataComponent.h + engine/enum/ComponentType.cpp + engine/enum/ComponentType.h + engine/dto/AbstractComponent.h + engine/dto/PrimitiveComponent.h + engine/dto/TransformComponent.h + editor/enum/ShadingMode.h + editor/dock-spaces/world/WorldHeaderPanel.cpp + editor/dock-spaces/world/WorldHeaderPanel.h + editor/service/SelectionService.cpp + editor/service/SelectionService.h + engine/dto/MetadataComponent.cpp + engine/dto/TransformComponent.cpp + engine/dto/PrimitiveComponent.cpp + editor/abstract/form/types/ResourceField.cpp + editor/abstract/form/types/ResourceField.h + editor/abstract/form/types/ColorField.cpp + editor/abstract/form/types/ColorField.h + editor/abstract/form/types/Vec4Field.cpp + editor/abstract/form/types/Vec4Field.h + editor/abstract/form/types/Vec3Field.cpp + editor/abstract/form/types/Vec3Field.h + editor/abstract/form/types/Vec2Field.cpp + editor/abstract/form/types/Vec2Field.h + editor/abstract/form/types/StringField.cpp + editor/abstract/form/types/StringField.h + editor/abstract/form/types/ResourceFilesPanel.h + editor/abstract/form/types/ResourceFilesPanel.cpp + engine/service/StreamingService.cpp + engine/service/StreamingService.h + engine/enum/ResourceType.h + editor/dock-spaces/viewport/GizmoPanel.cpp + editor/dock-spaces/viewport/GizmoPanel.h + editor/dock-spaces/viewport/ViewportHeaderPanel.cpp + editor/dock-spaces/viewport/ViewportHeaderPanel.h + editor/dock-spaces/viewport/GizmoSettingsPanel.cpp + editor/dock-spaces/viewport/GizmoSettingsPanel.h + editor/abstract/form/types/QuatField.cpp + editor/abstract/form/types/QuatField.h + engine/service/TransformService.cpp + engine/service/TransformService.h + engine/dto/BoundingBox.h + editor/dto/SparseVoxelOctreeBuilder.cpp + editor/dto/SparseVoxelOctreeBuilder.h + editor/dto/OctreeNode.cpp + editor/dto/OctreeNode.h + engine/dto/VoxelData.h + editor/dto/SceneData.h + engine/passes/impl/PostProcessingPass.cpp + engine/passes/impl/PostProcessingPass.h + engine/passes/impl/HWRayTracingPass.cpp + engine/passes/impl/HWRayTracingPass.h + engine/service/RayTracingService.cpp + engine/service/RayTracingService.h + engine/dto/PipelineBuilder.h + engine/resource/FrameBufferAttachment.cpp + engine/repository/EngineRepository.cpp + engine/repository/EngineRepository.h + common/serialization-definitions.h + editor/service/NotificationService.cpp + editor/service/NotificationService.h + editor/service/AsyncTaskService.cpp + editor/service/AsyncTaskService.h + editor/dto/Notification.h + editor/enum/NotificationSeverity.h + engine/dto/SparseVoxelOctreeData.h + editor/passes/SelectionOutlinePass.cpp + editor/passes/SelectionOutlinePass.h + editor/service/PickingService.cpp + editor/service/PickingService.h + engine/resource/SVOInstance.h + engine/dto/LightData.h + editor/passes/SelectionIDPass.cpp + editor/passes/SelectionIDPass.h + editor/repository/EditorRepository.cpp + editor/dto/GridPushConstant.h + engine/passes/AbstractComputePass.cpp + engine/passes/AbstractComputePass.h + engine/passes/AbstractPass.cpp + engine/passes/AbstractPass.h + engine/util/ImageUtils.h + engine/service/MaterialService.cpp + engine/service/MaterialService.h + engine/service/LightService.cpp + engine/service/LightService.h + engine/dto/VolumeComponent.cpp + engine/dto/VolumeComponent.h + engine/dto/DescriptorBinding.h + editor/dto/AsyncTask.h + editor/service/VoxelImporterService.cpp + editor/service/VoxelImporterService.h + engine/dto/VolumeData.h + engine/service/VoxelService.cpp + engine/service/VoxelService.h + common/ISerialize.cpp + editor/abstract/form/ChildPanel.cpp + editor/abstract/form/ChildPanel.h + editor/dto/SceneImportSettingsDTO.h + editor/panel/NotificationsPanel.cpp + editor/panel/NotificationsPanel.h + editor/panel/FileImportModalPanel.cpp + editor/panel/FileImportModalPanel.h + engine/frame-builder/EngineFrameBuilder.cpp + engine/frame-builder/EngineFrameBuilder.h + engine/frame-builder/EngineFrame.cpp + engine/frame-builder/EngineFrame.h + engine/frame-builder/structures/FramebufferBuilder.cpp + engine/frame-builder/structures/FramebufferBuilder.h + engine/frame-builder/structures/TextureBuilder.cpp + engine/frame-builder/structures/TextureBuilder.h + engine/frame-builder/structures/BufferBuilder.cpp + engine/frame-builder/structures/BufferBuilder.h + engine/frame-builder/structures/ResourceBuilder.h + engine/dto/PipelineBuilder.cpp + engine/service/DescriptorSetService.cpp + engine/frame-builder/structures/CommandBufferRecorderBuilder.cpp + engine/passes/impl/TemporalAccumulationPass.cpp + engine/passes/impl/TemporalAccumulationPass.h + engine/passes/impl/SpatialFilterPass.cpp + engine/passes/impl/SpatialFilterPass.h + engine/enum/ComponentType.cpp + editor/dto/SceneEntityData.h + editor/dock-spaces/repositories/RepositoriesPanel.cpp + editor/dock-spaces/repositories/RepositoriesPanel.h + engine/service/VolumeService.cpp + engine/service/VolumeService.h + common/IContextMember.h + common/IService.h + common/IRepository.h + common/IContextMember.cpp + core/DirectoryService.cpp + core/DirectoryService.h + common/IDisposable.h + core/FrameService.cpp + core/FrameService.h +) + +# Extract non-main sources for testing +set(ENGINE_LIB_SOURCES ${ENGINE_SOURCES}) +list(REMOVE_ITEM ENGINE_LIB_SOURCES main.cpp) + +add_library(metal_engine_lib STATIC ${ENGINE_LIB_SOURCES}) +target_include_directories(metal_engine_lib PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}) +target_link_libraries(metal_engine_lib PUBLIC ${COMMON_LIBRARIES}) + +add_executable(metal_engine main.cpp) +target_link_libraries(metal_engine PRIVATE metal_engine_lib) +add_dependencies(metal_engine copy_resources) + +add_custom_command(TARGET metal_engine POST_BUILD + COMMAND ${CMAKE_COMMAND} -E copy_directory + "${CMAKE_BINARY_DIR}/resources" + "$/resources") diff --git a/src/service/abstract/AbstractImporter.h b/src/common/AbstractImporter.h similarity index 77% rename from src/service/abstract/AbstractImporter.h rename to src/common/AbstractImporter.h index 4998a7a4..ca3dbde0 100644 --- a/src/service/abstract/AbstractImporter.h +++ b/src/common/AbstractImporter.h @@ -4,20 +4,16 @@ #include #include -#include "../../dto/file/ImportSettingsDTO.h" -#include "../../common/AbstractRuntimeComponent.h" +#include "../editor/dto/ImportSettingsDTO.h" +#include "IService.h" namespace Metal { - class AbstractImporter : public AbstractRuntimeComponent { + class AbstractImporter : public IService { public: virtual std::vector getSupportedTypes() { return {}; } - explicit AbstractImporter() - : AbstractRuntimeComponent() { - } - virtual std::string importData(const std::string &targetDir, const std::string &pathToFile, const std::shared_ptr &settings, const std::stop_token &stopToken) { diff --git a/src/service/abstract/AbstractResourceService.h b/src/common/AbstractResourceService.h similarity index 82% rename from src/service/abstract/AbstractResourceService.h rename to src/common/AbstractResourceService.h index 0d95c189..870b12f5 100644 --- a/src/service/abstract/AbstractResourceService.h +++ b/src/common/AbstractResourceService.h @@ -4,14 +4,15 @@ #include #include -#include "../../common/AbstractRuntimeComponent.h" -#include "../../repository/abstract/RuntimeResource.h" +#include "IService.h" +#include "../ApplicationContext.h" +#include "../engine/resource/RuntimeResource.h" namespace Metal { class VulkanContext; template - class AbstractResourceService : public AbstractRuntimeComponent { + class AbstractResourceService : public IService, public IDisposable { static_assert(std::is_base_of_v, "T must be a subclass of RuntimeResource"); protected: @@ -23,6 +24,10 @@ namespace Metal { std::lock_guard lock(resourceMutex); auto *resource = new T(id, std::forward(args)...); resources[id] = resource; + ctx->injectDependencies(resource); + if (auto *initializable = dynamic_cast(resource)) { + initializable->onInitialize(); + } return resource; } @@ -52,7 +57,7 @@ namespace Metal { } } - void disposeAll() { + void dispose() override { std::lock_guard lock(resourceMutex); for (auto it = resources.begin(); it != resources.end();) { auto *r = it->second; diff --git a/src/common/AbstractRuntimeComponent.h b/src/common/AbstractRuntimeComponent.h deleted file mode 100644 index f8e18f3b..00000000 --- a/src/common/AbstractRuntimeComponent.h +++ /dev/null @@ -1,17 +0,0 @@ -#ifndef METAL_ENGINE_ABSTRACTRUNTIMECOMPONENT_H -#define METAL_ENGINE_ABSTRACTRUNTIMECOMPONENT_H - -#include "interface/Changeable.h" -#include "interface/Initializable.h" -#include "interface/Synchornizable.h" - -#define ENGINE_NAME "Metal Engine" - -namespace Metal { - class AbstractRuntimeComponent : public Changeable, public Syncronizable, public Initializable { - public: - explicit AbstractRuntimeComponent() = default; - }; -} - -#endif diff --git a/src/enum/FieldType.h b/src/common/FieldType.h similarity index 100% rename from src/enum/FieldType.h rename to src/common/FieldType.h diff --git a/src/util/FileDialogUtil.h b/src/common/FileDialogUtil.h similarity index 93% rename from src/util/FileDialogUtil.h rename to src/common/FileDialogUtil.h index 436d9966..205c261a 100644 --- a/src/util/FileDialogUtil.h +++ b/src/common/FileDialogUtil.h @@ -3,8 +3,8 @@ #include #include #include -#include "../service/log/LogService.h" -#include "../context/ApplicationContext.h" +#include "LoggerUtil.h" +#include "../ApplicationContext.h" namespace Metal:: FileDialogUtil { static std::vector PickFiles(std::vector filtersToApply) { diff --git a/src/util/FilesUtil.h b/src/common/FilesUtil.h similarity index 98% rename from src/util/FilesUtil.h rename to src/common/FilesUtil.h index 142aee2d..811fcf54 100644 --- a/src/util/FilesUtil.h +++ b/src/common/FilesUtil.h @@ -2,7 +2,7 @@ #define FILESUTIL_H #include #include -#include "../dto/file/FSEntry.h" +#include "../editor/dto/FSEntry.h" namespace fs = std::filesystem; diff --git a/src/common/IContextMember.cpp b/src/common/IContextMember.cpp new file mode 100644 index 00000000..28dae77e --- /dev/null +++ b/src/common/IContextMember.cpp @@ -0,0 +1,14 @@ +#include "IContextMember.h" +#include "../ApplicationContext.h" + +namespace Metal { + void IContextMember::setDependencies(ApplicationContext &ctx) { + this->ctx = &ctx; + for (auto &dep : getDependencies()) { + void* singleton = ctx.getSingletonByName(dep.name); + if (dep.ptr != nullptr) { + *static_cast(dep.ptr) = singleton; + } + } + } +} diff --git a/src/common/IContextMember.h b/src/common/IContextMember.h new file mode 100644 index 00000000..26b9c2eb --- /dev/null +++ b/src/common/IContextMember.h @@ -0,0 +1,34 @@ +#ifndef METAL_ENGINE_CONTEXTMEMBER_H +#define METAL_ENGINE_CONTEXTMEMBER_H +#include +#include + +namespace Metal { + class ApplicationContext; + + struct Dependency { + std::string name; + void *ptr; + }; + + class IContextMember { + public: + ApplicationContext *ctx = nullptr; + + virtual ~IContextMember() = default; + + /** + * Dependency injection. Called after all the context is created and + * will be the data used to initialize the pointers + */ + virtual std::vector getDependencies() { + return {}; + } + + /** + * Will call getDependencies and set the pointers based on the singletons returned + */ + void setDependencies(ApplicationContext &ctx); + }; +} +#endif //METAL_ENGINE_CONTEXTMEMBER_H diff --git a/src/common/IDisposable.h b/src/common/IDisposable.h new file mode 100644 index 00000000..e68d55ea --- /dev/null +++ b/src/common/IDisposable.h @@ -0,0 +1,10 @@ +#ifndef METAL_ENGINE_IDISPOSABLE_H +#define METAL_ENGINE_IDISPOSABLE_H +namespace Metal { + class IDisposable { + public: + virtual ~IDisposable() = default; + virtual void dispose() = 0; + }; +} +#endif \ No newline at end of file diff --git a/src/common/interface/Initializable.h b/src/common/IInit.h similarity index 69% rename from src/common/interface/Initializable.h rename to src/common/IInit.h index 3a3c44bb..93b6bfbd 100644 --- a/src/common/interface/Initializable.h +++ b/src/common/IInit.h @@ -2,9 +2,9 @@ #define METAL_ENGINE_INITIALIZABLE_H namespace Metal { - class Initializable { + class IInit { public: - virtual ~Initializable() = default; + virtual ~IInit() = default; virtual void onInitialize() {} }; diff --git a/src/common/IRepository.h b/src/common/IRepository.h new file mode 100644 index 00000000..88576aad --- /dev/null +++ b/src/common/IRepository.h @@ -0,0 +1,13 @@ +#ifndef METAL_ENGINE_IREPOSITORY_H +#define METAL_ENGINE_IREPOSITORY_H +#include "IContextMember.h" +#include "Inspectable.h" +#include "ISerialize.h" + +namespace Metal { + class IRepository : public IContextMember, public Inspectable, public ISerialize { + public: + virtual ~IRepository() = default; + }; +} +#endif //METAL_ENGINE_IREPOSITORY_H diff --git a/src/util/Serializable.cpp b/src/common/ISerialize.cpp similarity index 72% rename from src/util/Serializable.cpp rename to src/common/ISerialize.cpp index d7913ae7..192b3bfb 100644 --- a/src/util/Serializable.cpp +++ b/src/common/ISerialize.cpp @@ -1,19 +1,19 @@ -#include "Serializable.h" -#include "../context/ApplicationContext.h" +#include "ISerialize.h" +#include "../ApplicationContext.h" #include #include #include -#include "../service/log/LogService.h" +#include "LoggerUtil.h" namespace Metal { - void Serializable::saveToJson(const std::string &path) const { + void ISerialize::saveToJson(const std::string &path) const { std::ofstream os(path); if (os.is_open()) { os << toJson().dump(4); } } - void Serializable::loadFromJson(const std::string &path) { + void ISerialize::loadFromJson(const std::string &path) { if (std::filesystem::exists(path)) { std::ifstream is(path); if (is.is_open()) { diff --git a/src/util/Serializable.h b/src/common/ISerialize.h similarity index 84% rename from src/util/Serializable.h rename to src/common/ISerialize.h index b98f673f..d40b4922 100644 --- a/src/util/Serializable.h +++ b/src/common/ISerialize.h @@ -4,9 +4,9 @@ #include namespace Metal { - class Serializable { + class ISerialize { public: - virtual ~Serializable() = default; + virtual ~ISerialize() = default; virtual nlohmann::json toJson() const = 0; diff --git a/src/common/IService.h b/src/common/IService.h new file mode 100644 index 00000000..c880c173 --- /dev/null +++ b/src/common/IService.h @@ -0,0 +1,11 @@ +#ifndef METAL_ENGINE_ISERVICE_H +#define METAL_ENGINE_ISERVICE_H +#include "IContextMember.h" + +namespace Metal { + class IService : public IContextMember { + public: + virtual ~IService() = default; + }; +} +#endif //METAL_ENGINE_ISERVICE_H diff --git a/src/common/interface/Synchornizable.h b/src/common/ISync.h similarity index 69% rename from src/common/interface/Synchornizable.h rename to src/common/ISync.h index d5640524..9cd8af3f 100644 --- a/src/common/interface/Synchornizable.h +++ b/src/common/ISync.h @@ -2,9 +2,9 @@ #define METAL_ENGINE_SYNCHORNIZABLE_H namespace Metal { - class Syncronizable { + class ISync { public: - virtual ~Syncronizable() = default; + virtual ~ISync() = default; virtual void onSync() {} }; diff --git a/src/common/interface/Icons.h b/src/common/Icons.h similarity index 100% rename from src/common/interface/Icons.h rename to src/common/Icons.h diff --git a/src/common/inspection/Inspectable.cpp b/src/common/Inspectable.cpp similarity index 98% rename from src/common/inspection/Inspectable.cpp rename to src/common/Inspectable.cpp index 0bc87b75..e2b4a1ee 100644 --- a/src/common/inspection/Inspectable.cpp +++ b/src/common/Inspectable.cpp @@ -7,8 +7,8 @@ #include "InspectedField.h" #include "InspectedMethod.h" -#include "../../util/Util.h" -#include "../../enum/EntryType.h" +#include "../editor/util/Util.h" +#include "../editor/enum/EntryType.h" #define DECLARATION(T, V) \ std::shared_ptr> field = std::make_shared>(&v);\ diff --git a/src/common/inspection/Inspectable.h b/src/common/Inspectable.h similarity index 88% rename from src/common/inspection/Inspectable.h rename to src/common/Inspectable.h index 990de344..e5990746 100644 --- a/src/common/inspection/Inspectable.h +++ b/src/common/Inspectable.h @@ -7,15 +7,16 @@ #include #include "InspectableMember.h" -#include "../../util/Util.h" -#include "../../enum/EntryType.h" -#include "../interface/Changeable.h" +#include "../editor/util/Util.h" +#include "../editor/enum/EntryType.h" namespace Metal { - class Inspectable : public Changeable { + class Inspectable { std::string uniqueIdentifier = Util::uuidV4(); std::vector > fields{}; bool fieldsRegistered = false; + unsigned long changes = 0; + unsigned long frozenVersion = 99999; public: Inspectable &operator=(const Inspectable &other) { @@ -87,6 +88,22 @@ namespace Metal { std::string group, std::string name, bool disabled = false); public: + [[nodiscard]] unsigned long getChangeId() const { + return changes; + } + + void registerChange() { + changes++; + } + + [[nodiscard]] bool isNotFrozen() const { + return frozenVersion != getChangeId(); + } + + void freezeVersion() { + frozenVersion = getChangeId(); + } + std::vector > &getFields(); Inspectable() = default; diff --git a/src/common/inspection/InspectableMember.h b/src/common/InspectableMember.h similarity index 92% rename from src/common/inspection/InspectableMember.h rename to src/common/InspectableMember.h index dacc8336..08a7ed6e 100644 --- a/src/common/inspection/InspectableMember.h +++ b/src/common/InspectableMember.h @@ -1,7 +1,7 @@ #ifndef METAL_ENGINE_INSPECTABLEMEMBER_H #define METAL_ENGINE_INSPECTABLEMEMBER_H -#include "../../enum/FieldType.h" +#include "FieldType.h" namespace Metal { class Inspectable; diff --git a/src/common/inspection/InspectedField.h b/src/common/InspectedField.h similarity index 94% rename from src/common/inspection/InspectedField.h rename to src/common/InspectedField.h index 9c50c1ce..fdcd9155 100644 --- a/src/common/inspection/InspectedField.h +++ b/src/common/InspectedField.h @@ -4,7 +4,7 @@ #include #include "InspectableMember.h" -#include "../../enum/EntryType.h" +#include "../editor/enum/EntryType.h" namespace Metal { template diff --git a/src/common/inspection/InspectedMethod.h b/src/common/InspectedMethod.h similarity index 100% rename from src/common/inspection/InspectedMethod.h rename to src/common/InspectedMethod.h diff --git a/src/service/log/LogService.cpp b/src/common/LoggerUtil.cpp similarity index 80% rename from src/service/log/LogService.cpp rename to src/common/LoggerUtil.cpp index 28cf54e1..9f8871cb 100644 --- a/src/service/log/LogService.cpp +++ b/src/common/LoggerUtil.cpp @@ -1,15 +1,15 @@ -#include "LogService.h" +#include "LoggerUtil.h" #include #include #include #include -namespace Metal { +namespace Metal::LogService { - LogService::LogService() : AbstractRuntimeComponent() { - } + static std::vector entries; + static std::mutex logMutex; - void LogService::log(LogLevel level, const std::string &message) const { + void log(LogLevel level, const std::string &message) { auto now = std::chrono::system_clock::now(); auto in_time_t = std::chrono::system_clock::to_time_t(now); @@ -25,17 +25,17 @@ namespace Metal { std::cout << "[" << timestamp << "] [" << getLevelName(level) << "] " << message << std::endl; } - std::vector LogService::getEntriesSnapshot() const { + std::vector getEntriesSnapshot() { std::lock_guard lock(logMutex); return entries; } - void LogService::clear() { + void clear() { std::lock_guard lock(logMutex); entries.clear(); } - const char* LogService::getLevelName(LogLevel level) { + const char* getLevelName(LogLevel level) { switch (level) { case LogLevel::Trace: return "TRACE"; case LogLevel::Debug: return "DEBUG"; @@ -47,7 +47,7 @@ namespace Metal { } } - uint32_t LogService::getLevelColor(LogLevel level) { + uint32_t getLevelColor(LogLevel level) { switch (level) { case LogLevel::Trace: return 0xFF888888; // Grey case LogLevel::Debug: return 0xFFAAAAAA; // Light Grey diff --git a/src/common/LoggerUtil.h b/src/common/LoggerUtil.h new file mode 100644 index 00000000..be198cc3 --- /dev/null +++ b/src/common/LoggerUtil.h @@ -0,0 +1,44 @@ +#ifndef METAL_ENGINE_LOGSERVICE_H +#define METAL_ENGINE_LOGSERVICE_H + +#include +#include +#include + +namespace Metal { + + enum class LogLevel { + Trace, + Debug, + Info, + Warn, + Error, + Fatal + }; + + struct LogEntry { + LogLevel level; + std::string message; + std::string timestamp; + }; + + namespace LogService { + void log(LogLevel level, const std::string &message); + + [[nodiscard]] std::vector getEntriesSnapshot(); + void clear(); + + const char* getLevelName(LogLevel level); + uint32_t getLevelColor(LogLevel level); + } + +} + +#define LOG_TRACE(msg) Metal::LogService::log(Metal::LogLevel::Trace, msg) +#define LOG_DEBUG(msg) Metal::LogService::log(Metal::LogLevel::Debug, msg) +#define LOG_INFO(msg) Metal::LogService::log(Metal::LogLevel::Info, msg) +#define LOG_WARN(msg) Metal::LogService::log(Metal::LogLevel::Warn, msg) +#define LOG_ERROR(msg) Metal::LogService::log(Metal::LogLevel::Error, msg) +#define LOG_FATAL(msg) Metal::LogService::log(Metal::LogLevel::Fatal, msg) + +#endif diff --git a/src/common/interface/Changeable.h b/src/common/interface/Changeable.h deleted file mode 100644 index 8ce78c2b..00000000 --- a/src/common/interface/Changeable.h +++ /dev/null @@ -1,28 +0,0 @@ -#ifndef CHANGEABLE_H -#define CHANGEABLE_H - -namespace Metal { - class Changeable { - protected: - unsigned long changes = 0; - unsigned long frozenVersion = 99999; - - public: - [[nodiscard]] unsigned long getChangeId() const { - return changes; - } - - void registerChange() { - changes++; - } - - [[nodiscard]] bool isNotFrozen() const { - return frozenVersion != getChangeId(); - } - - void freezeVersion() { - frozenVersion = getChangeId(); - } - }; -} -#endif diff --git a/src/util/serialization-definitions.h b/src/common/serialization-definitions.h similarity index 98% rename from src/util/serialization-definitions.h rename to src/common/serialization-definitions.h index eab3426b..1a70f527 100644 --- a/src/util/serialization-definitions.h +++ b/src/common/serialization-definitions.h @@ -3,7 +3,7 @@ #include #include -#include "Serializable.h" +#include "ISerialize.h" #include #include #include diff --git a/src/context/ApplicationContext.cpp b/src/context/ApplicationContext.cpp deleted file mode 100644 index f489b20b..00000000 --- a/src/context/ApplicationContext.cpp +++ /dev/null @@ -1,136 +0,0 @@ -#include "ApplicationContext.h" - -#include -#include - -#include "../util/FilesUtil.h" -#include "../util/VulkanUtils.h" -#include "../util/serialization-definitions.h" - -#include "../util/FileDialogUtil.h" -#include - -namespace Metal { - std::unique_ptr ApplicationContext::CONTEXT = nullptr; - - ApplicationContext &ApplicationContext::Get() { - if (CONTEXT == nullptr) { - throw std::runtime_error("Context not initialized"); - } - return *CONTEXT; - } - - void ApplicationContext::Init(bool debugMode) { - CONTEXT = std::make_unique(debugMode); - } - - void ApplicationContext::updateRootPath(bool forceSelection) { - std::string cachedPath; - std::string cachePathFile = std::filesystem::current_path().string() + CACHED_PATH; - FilesUtil::ReadFile(cachePathFile.c_str(), cachedPath); - cachedPath.erase(std::ranges::remove(cachedPath, '\n').begin(), cachedPath.cend()); - if (cachedPath.empty() || forceSelection || !fs::exists(cachedPath)) { - rootDirectory = FileDialogUtil::SelectDirectory(); - rootDirectory.erase(std::ranges::remove(rootDirectory, '\n').begin(), rootDirectory.cend()); - if (rootDirectory.empty()) { - throw std::runtime_error("No directory selected."); - } - save(); - FilesUtil::WriteFile(cachePathFile.c_str(), rootDirectory.c_str()); - } else { - rootDirectory = cachedPath; - } - PARSE_TEMPLATE(editorRepository, rootDirectory + "/" + HASH_OF_CLASS_NAME(EditorRepository) + ".json") - PARSE_TEMPLATE(engineRepository, rootDirectory + "/" + HASH_OF_CLASS_NAME(EngineRepository) + ".json") - PARSE_TEMPLATE(worldRepository, rootDirectory + "/" + HASH_OF_CLASS_NAME(WorldRepository) + ".json") - - - FilesUtil::CreateDirectory(getShadersDirectory()); - FilesUtil::CreateDirectory(getAssetRefDirectory()); - FilesUtil::CreateDirectory(getAssetDirectory()); - } - - unsigned int ApplicationContext::getFrameIndex() const { - return vulkanContext.imguiVulkanWindow.FrameIndex; - } - - void ApplicationContext::dispose() { - NFD_Quit(); - try { - rayTracingService.destroyAccelerationStructures(); - asyncTaskService.endAll(); - engineContext.dispose(); - guiContext.dispose(); - vulkanContext.dispose(); - glfwContext.dispose(); - } catch (std::exception &e) { - std::cerr << e.what() << std::endl; - } - } - - void ApplicationContext::start() { - NFD_Init(); - - updateRootPath(false); - - glfwContext.onInitialize(); - if (!glfwContext.isValidContext()) { - throw std::runtime_error("Could not create window"); - } - vulkanContext.onInitialize(); - guiContext.onInitialize(); - filesService.onInitialize(); - editorPanel.onInitialize(); - engineContext.onInitialize(); - - GLFWwindow *window = glfwContext.getWindow(); - while (!glfwWindowShouldClose(window)) { - if (glfwContext.beginFrame()) { - GuiContext::BeginFrame(); - editorPanel.onSync(); - ImGui::Render(); - auto *drawData = ImGui::GetDrawData(); - const bool main_is_minimized = (drawData->DisplaySize.x <= 0.0f || drawData->DisplaySize.y <= 0.0f); - if (!main_is_minimized) { - vulkanContext.getCommandBuffers().clear(); - auto &wd = vulkanContext.imguiVulkanWindow; - VkSemaphore imageAcquiredSemaphore = wd.FrameSemaphores[wd.SemaphoreIndex].ImageAcquiredSemaphore; - VkResult err = vkAcquireNextImageKHR(vulkanContext.device.device, wd.Swapchain, UINT64_MAX, - imageAcquiredSemaphore, VK_NULL_HANDLE, - &wd.FrameIndex); - if (err == VK_ERROR_OUT_OF_DATE_KHR || err == VK_SUBOPTIMAL_KHR) { - glfwContext.setSwapChainRebuild(true); - return; - } - - VulkanUtils::CheckVKResult(err); - ImGui_ImplVulkanH_Frame *fd = &wd.Frames[getFrameIndex()]; - VulkanUtils::CheckVKResult(vkWaitForFences(vulkanContext.device.device, 1, &fd->Fence, VK_TRUE, - UINT64_MAX)); - VulkanUtils::CheckVKResult(vkResetFences(vulkanContext.device.device, 1, &fd->Fence)); - VulkanUtils::CheckVKResult(vkResetCommandPool(vulkanContext.device.device, fd->CommandPool, - VK_COMMAND_POOL_RESET_RELEASE_RESOURCES_BIT)); - engineContext.onSync(); - GuiContext::RecordImguiCommandBuffer(drawData, err, wd, fd); - vulkanContext.submitFrame(imageAcquiredSemaphore, wd.FrameSemaphores[wd.SemaphoreIndex]. - RenderCompleteSemaphore, fd); - } - if (!main_is_minimized) - glfwContext.presentFrame(); - } - } - dispose(); - } - - void ApplicationContext::save() { - try { - DUMP_TEMPLATE(rootDirectory + "/" + HASH_OF_CLASS_NAME(EditorRepository) + ".json", editorRepository) - DUMP_TEMPLATE(rootDirectory + "/" + HASH_OF_CLASS_NAME(EngineRepository) + ".json", engineRepository) - DUMP_TEMPLATE(rootDirectory + "/" + HASH_OF_CLASS_NAME(WorldRepository) + ".json", worldRepository) - notificationService.pushMessage("Project saved", NotificationSeverities::SUCCESS); - } catch (const std::exception &e) { - LOG_ERROR(e.what()); - notificationService.pushMessage("Could not save project", NotificationSeverities::ERROR); - } - } -} diff --git a/src/context/ApplicationContext.h b/src/context/ApplicationContext.h deleted file mode 100644 index aad857a1..00000000 --- a/src/context/ApplicationContext.h +++ /dev/null @@ -1,150 +0,0 @@ -#ifndef METAL_ENGINE_APPLICATIONCONTEXT_H -#define METAL_ENGINE_APPLICATIONCONTEXT_H -#define CACHED_PATH "/metal-engine-cached.txt" -#include - -#include "engine/EngineContext.h" -#include "glfw/GLFWContext.h" -#include "vulkan/VulkanContext.h" - -#include "../service/mesh/MeshService.h" -#include "../service/texture/TextureService.h" -#include "../service/framebuffer/FrameBufferService.h" -#include "../service/pipeline/PipelineService.h" -#include "../service/buffer/BufferService.h" -#include "../service/descriptor/DescriptorSetService.h" -#include "../service/theme/ThemeService.h" -#include "../service/dock/DockService.h" -#include "../service/selection/SelectionService.h" -#include "../service/mesh/SceneImporterService.h" -#include "../service/mesh/MeshImporterService.h" -#include "../service/material/MaterialImporterService.h" -#include "../service/texture/TextureImporterService.h" -#include "../service/files/FilesService.h" -#include "../service/files/FileImporterService.h" -#include "../service/camera/CameraService.h" - -#include "../repository/world/WorldRepository.h" -#include "../repository/runtime/RuntimeRepository.h" -#include "../repository/streaming/StreamingService.h" -#include "../repository/engine/EngineRepository.h" -#include "../repository/dock/DockRepository.h" -#include "../repository/editor/EditorRepository.h" -#include "../service/material/MaterialService.h" -#include "../service/passes/CommandBufferRecorderService.h" -#include "../service/notification/NotificationService.h" -#include "../service/notification/AsyncTaskService.h" -#include "../service/log/LogService.h" -#include "../service/transform/TransformService.h" -#include "../service/picking/PickingService.h" -#include "../service/volumes/VolumeService.h" -#include "../service/voxel/VoxelImporterService.h" -#include "../service/voxel/VoxelService.h" -#include "../service/lights/LightService.h" -#include "../service/raytracing/RayTracingService.h" -#include "editor/EditorPanel.h" -#include "gui/GuiContext.h" - -#define CTX Metal::ApplicationContext::Get() - -namespace Metal { - class ApplicationContext { - static std::unique_ptr CONTEXT; - bool debugMode; - EditorPanel editorPanel; - std::string rootDirectory; - - public: - explicit ApplicationContext(bool debug_mode) - : debugMode(debug_mode) { - } - - EngineContext engineContext{}; - VulkanContext vulkanContext{ debugMode}; - GuiContext guiContext{}; - GLFWContext glfwContext{}; - - // ----------- Services - NotificationService notificationService; - AsyncTaskService asyncTaskService; - LogService logService{}; - MeshService meshService{}; - MaterialService materialService{}; - TextureService textureService{}; - FrameBufferService framebufferService{}; - DescriptorSetService descriptorSetService{}; - PipelineService pipelineService{descriptorSetService}; - BufferService bufferService{}; - ThemeService themeService{}; - DockService dockService{}; - SelectionService selectionService{}; - SceneImporterService sceneImporterService{}; - MeshImporterService meshImporterService{}; - MaterialImporterService materialImporterService{}; - TextureImporterService textureImporter{}; - FilesService filesService{}; - FileImporterService fileImporterService{}; - CameraService cameraService{}; - PickingService pickingService{}; - TransformService transformService{}; - LightService lightService{}; - VolumeService volumeService{}; - RayTracingService rayTracingService{}; - CommandBufferRecorderService commandBufferRecorderService{}; - VoxelImporterService voxelImporterService{}; - VoxelService voxelService{}; - // ----------- Services - - // ----------- Repository - WorldRepository worldRepository{}; - RuntimeRepository runtimeRepository{}; - StreamingService streamingService{}; - EngineRepository engineRepository{}; - DockRepository dockRepository{}; - EditorRepository editorRepository{}; - // ----------- Repository - - - static ApplicationContext &Get(); - - static void Init(bool debugMode); - - [[nodiscard]] bool isDebugMode() const { return debugMode; } - - void updateRootPath(bool forceSelection); - - [[nodiscard]] bool isValidContext() const { - return glfwContext.isValidContext(); - } - - [[nodiscard]] const std::string &getRootDirectory() const { - return rootDirectory; - } - - [[nodiscard]] std::string getAssetRefDirectory() const { - return rootDirectory + "/assets-ref/"; - } - - [[nodiscard]] std::string getShadersDirectory() const { - return rootDirectory + "/shaders/"; - } - - [[nodiscard]] std::string getAssetDirectory() const { - return rootDirectory + "/assets/"; - } - - [[nodiscard]] std::string getVideoOutputPath() const { - return rootDirectory + "/output.mp4"; - } - - [[nodiscard]] unsigned int getFrameIndex() const; - - void dispose(); - - void start(); - - void save(); - }; -} - -#endif diff --git a/src/context/editor/EditorPanel.cpp b/src/context/editor/EditorPanel.cpp deleted file mode 100644 index bbad6c87..00000000 --- a/src/context/editor/EditorPanel.cpp +++ /dev/null @@ -1,95 +0,0 @@ -#include "EditorPanel.h" -#include "../../util/UIUtil.h" -#include "../../context/ApplicationContext.h" -#include "../../dto/Notification.h" -#include "dock-spaces/header/EditorHeaderPanel.h" -#include "panel/FileImportModalPanel.h" -#include "panel/NotificationsPanel.h" - -namespace Metal { - int EditorPanel::FLAGS = ImGuiWindowFlags_NoDocking | - ImGuiWindowFlags_NoTitleBar | - ImGuiWindowFlags_NoCollapse | - ImGuiWindowFlags_NoResize | - ImGuiWindowFlags_NoMove | - ImGuiWindowFlags_NoBringToFrontOnFocus | - ImGuiWindowFlags_NoNavFocus; - const char *EditorPanel::NAME = "##main_window"; - const char *EditorPanel::NAME_HEADER = "##header_window"; - ImVec2 EditorPanel::CENTER(0.0f, 0.0f); - float EditorPanel::HEADER_HEIGHT = 25; - - - void EditorPanel::renderDockSpaces() { - const ImGuiViewport *viewport = ImGui::GetMainViewport(); - renderHeader(viewport); - - // Begin window - { - UIUtil::AUX_VEC2.x = viewport->Pos.x; - UIUtil::AUX_VEC2.y = viewport->Pos.y + HEADER_HEIGHT; - ImGui::SetNextWindowPos(UIUtil::AUX_VEC2); - - UIUtil::AUX_VEC2.x = viewport->Size.x; - UIUtil::AUX_VEC2.y = viewport->Size.y - HEADER_HEIGHT; - ImGui::SetNextWindowSize(UIUtil::AUX_VEC2); - ImGui::SetNextWindowViewport(viewport->ID); - - SetWindowStyle(); - } - - ImGui::Begin(NAME, &UIUtil::OPEN, FLAGS); - windowId = ImGui::GetID(NAME); - - ImGui::PopStyleVar(3); - - CTX.dockService.buildViews(windowId, this); - - ImGui::PushStyleVar(ImGuiStyleVar_FrameBorderSize, 0.0f); - ImGui::DockSpace(windowId, CENTER, ImGuiDockNodeFlags_PassthruCentralNode); - ImGui::PopStyleVar(1); - - onSyncChildren(); - ImGui::End(); - } - - void EditorPanel::renderHeader(const ImGuiViewport *viewport) { - UIUtil::AUX_VEC2.x = viewport->Pos.x; - UIUtil::AUX_VEC2.y = 0; - ImGui::SetNextWindowPos(UIUtil::AUX_VEC2); - - UIUtil::AUX_VEC2.x = viewport->Size.x; - UIUtil::AUX_VEC2.y = HEADER_HEIGHT; - ImGui::SetNextWindowSize(UIUtil::AUX_VEC2); - - SetWindowStyle(); - ImGui::Begin(NAME_HEADER, &UIUtil::OPEN, FLAGS | ImGuiWindowFlags_NoScrollbar); - ImGui::PopStyleVar(3); - - headerPanel->onSync(); - ImGui::End(); - } - - void EditorPanel::SetWindowStyle() { - ImGui::PushStyleVar(ImGuiStyleVar_WindowRounding, 0.0f); - ImGui::PushStyleVar(ImGuiStyleVar_WindowBorderSize, 0.0f); - ImGui::PushStyleVar(ImGuiStyleVar_WindowPadding, UIUtil::VEC2_ZERO); - } - - void EditorPanel::onSync() { - CTX.themeService.onSync(); - renderDockSpaces(); - notificationsPanel->onSync(); - fileImportModalPanel->onSync(); - } - - void EditorPanel::onInitialize() { - headerPanel = new EditorHeaderPanel(); - headerPanel->onInitialize(); - notificationsPanel = new NotificationsPanel(); - notificationsPanel->onInitialize(); - - fileImportModalPanel = new FileImportModalPanel(); - fileImportModalPanel->onInitialize(); - } -} diff --git a/src/context/editor/abstract/AbstractPanel.h b/src/context/editor/abstract/AbstractPanel.h deleted file mode 100644 index 61ac76b6..00000000 --- a/src/context/editor/abstract/AbstractPanel.h +++ /dev/null @@ -1,32 +0,0 @@ -#ifndef METAL_ENGINE_ABSTRACTPANEL_H -#define METAL_ENGINE_ABSTRACTPANEL_H - -#include -#include - -#include "IPanel.h" - -namespace Metal { - class ApplicationContext; - - class AbstractPanel : public IPanel { - protected: - std::vector children; - const std::string id; - - virtual void onSyncChildren() const; - - public: - explicit AbstractPanel(); - - std::vector &getChildren(); - - void appendChild(AbstractPanel *panel); - - void removeAllChildren() override; - - virtual void onRemove() { - } - }; -} -#endif diff --git a/src/context/editor/abstract/IPanel.h b/src/context/editor/abstract/IPanel.h deleted file mode 100644 index 3d024efa..00000000 --- a/src/context/editor/abstract/IPanel.h +++ /dev/null @@ -1,14 +0,0 @@ -#ifndef METAL_ENGINE_IPANEL_H -#define METAL_ENGINE_IPANEL_H - -#include "../../../common/interface/Synchornizable.h" -#include "../../../common/interface/Initializable.h" - -namespace Metal { - class IPanel : public Syncronizable, public Initializable { - public: - virtual void removeAllChildren() { - } - }; -} -#endif diff --git a/src/context/editor/dock-spaces/header/EditorHeaderPanel.cpp b/src/context/editor/dock-spaces/header/EditorHeaderPanel.cpp deleted file mode 100644 index 01591466..00000000 --- a/src/context/editor/dock-spaces/header/EditorHeaderPanel.cpp +++ /dev/null @@ -1,105 +0,0 @@ -#include "EditorHeaderPanel.h" -#include "AsyncTaskPanel.h" -#include "../../../../util/UIUtil.h" -#include "../../../../context/ApplicationContext.h" - -namespace Metal { - void EditorHeaderPanel::onSync() { - renderFileTab(); - ImGui::Dummy(ImVec2(0, UIUtil::ONLY_ICON_BUTTON_SIZE)); - ImGui::Dummy(ImVec2(2, 0)); - ImGui::Separator(); - } - - void EditorHeaderPanel::onInitialize() { - appendChild(asyncTask = new AsyncTaskPanel()); - } - - void EditorHeaderPanel::renderFileTab() { - if (ImGui::BeginMainMenuBar()) { - if (UIUtil::ButtonSimple(Icons::save, UIUtil::ONLY_ICON_BUTTON_SIZE, UIUtil::ONLY_ICON_BUTTON_SIZE)) { - CTX.save(); - } - ImGui::SameLine(); - if (ImGui::BeginMenu("File")) { - if (ImGui::MenuItem("Open", "Ctrl+O")) { - CTX.engineContext.dispose(); - CTX.updateRootPath(true); - } - if (ImGui::MenuItem("Save", "Ctrl+S")) { - CTX.save(); - } - ImGui::Separator(); - if (ImGui::MenuItem("Exit")) { - exit(0); - } - ImGui::EndMenu(); - } - - // Create an "Edit" menu - if (ImGui::BeginMenu("Edit")) { - if (ImGui::MenuItem("Compile shaders")) { - CTX.engineContext.dispose(); - // TODO - CREATE NEW FRAME - } - ImGui::EndMenu(); - } - - UIUtil::LargeSpacing(); - renderShortcuts(); - UIUtil::Spacing(); - - asyncTask->onSync(); - - framerate(); - - ImGui::EndMainMenuBar(); - } - } - - void EditorHeaderPanel::framerate() { - const int framerate = static_cast(round(ImGui::GetIO().Framerate)); - if (framerate > 0) { - ImGui::Text("%i ms | %i fps", 1000 / framerate, framerate); - } - } - - void EditorHeaderPanel::renderShortcuts() { - auto &shortcuts = CTX.editorRepository.focusedShortcuts; - if (shortcuts.empty()) return; - ImGui::Text(CTX.editorRepository.focusedWindowName.c_str()); - ImGui::SameLine(); - std::string label; - for (size_t i = 0; i < std::min(shortcuts.size(), size_t(3)); ++i) { - if (i > 0) label += " | "; - label += UIUtil::GetKeyChordName(shortcuts[i].keyChord); - } - - if (ImGui::Button(label.c_str())) { - ImGui::OpenPopup("AllShortcutsPopup"); - } - - if (ImGui::BeginPopup("AllShortcutsPopup")) { - if (ImGui::BeginTable("ShortcutsTable", 2, - ImGuiTableFlags_Borders | ImGuiTableFlags_RowBg | - ImGuiTableFlags_SizingStretchProp)) { - ImGui::TableSetupColumn("Key"); - ImGui::TableSetupColumn("Action"); - ImGui::TableHeadersRow(); - - for (const auto &shortcut: shortcuts) { - ImGui::TableNextRow(); - ImGui::TableNextColumn(); - ImGui::TextUnformatted(UIUtil::GetKeyChordName(shortcut.keyChord).c_str()); - ImGui::TableNextColumn(); - if (ImGui::Selectable(shortcut.name.c_str(), false, ImGuiSelectableFlags_SpanAllColumns)) { - shortcut.callback(); - ImGui::CloseCurrentPopup(); - } - } - ImGui::EndTable(); - } - ImGui::EndPopup(); - } - } -} diff --git a/src/context/editor/dock-spaces/header/EditorHeaderPanel.h b/src/context/editor/dock-spaces/header/EditorHeaderPanel.h deleted file mode 100644 index 897cae94..00000000 --- a/src/context/editor/dock-spaces/header/EditorHeaderPanel.h +++ /dev/null @@ -1,23 +0,0 @@ -#ifndef METAL_ENGINE_EDITORHEADERPANEL_H -#define METAL_ENGINE_EDITORHEADERPANEL_H - -#include "../../abstract/AbstractPanel.h" - -namespace Metal { - class EditorHeaderPanel final : public AbstractPanel { - AbstractPanel *asyncTask = nullptr; - - void renderFileTab(); - - void renderShortcuts(); - - static void framerate(); - - public: - void onInitialize() override; - - void onSync() override; - }; -} // Metal - -#endif diff --git a/src/context/editor/dock-spaces/metrics/MetricsPanel.h b/src/context/editor/dock-spaces/metrics/MetricsPanel.h deleted file mode 100644 index 0f133b5a..00000000 --- a/src/context/editor/dock-spaces/metrics/MetricsPanel.h +++ /dev/null @@ -1,14 +0,0 @@ -#ifndef METRICSPANEL_H -#define METRICSPANEL_H - -#include "../docks/AbstractDockPanel.h" -#include "imgui.h" - -namespace Metal { - class MetricsPanel final : public AbstractDockPanel { - public: - void onSync() override; - }; -} - -#endif diff --git a/src/context/editor/dock-spaces/repositories/RepositoriesPanel.cpp b/src/context/editor/dock-spaces/repositories/RepositoriesPanel.cpp deleted file mode 100644 index 19af1c73..00000000 --- a/src/context/editor/dock-spaces/repositories/RepositoriesPanel.cpp +++ /dev/null @@ -1,22 +0,0 @@ -#include "RepositoriesPanel.h" -#include "../../abstract/form/FormPanel.h" -#include "../../../../context/ApplicationContext.h" -#include "../../../../common/inspection/Inspectable.h" - -namespace Metal { - void RepositoriesPanel::onInitialize() { - formPanel = new FormPanel(); - appendChild(formPanel); - - repositories.push_back(&CTX.editorRepository); - repositories.push_back(&CTX.engineRepository); - repositories.push_back(&CTX.worldRepository.camera); - } - - void RepositoriesPanel::onSync() { - for (auto *repo : repositories) { - formPanel->setInspection(repo); - } - formPanel->onSync(); - } -} diff --git a/src/context/editor/dock-spaces/repositories/RepositoriesPanel.h b/src/context/editor/dock-spaces/repositories/RepositoriesPanel.h deleted file mode 100644 index b566b984..00000000 --- a/src/context/editor/dock-spaces/repositories/RepositoriesPanel.h +++ /dev/null @@ -1,20 +0,0 @@ -#ifndef REPOSITORIESPANEL_H -#define REPOSITORIESPANEL_H - -#include "../docks/AbstractDockPanel.h" - -namespace Metal { - class FormPanel; - class Inspectable; - - class RepositoriesPanel final : public AbstractDockPanel { - std::vector repositories{}; - FormPanel *formPanel = nullptr; - - public: - void onInitialize() override; - void onSync() override; - }; -} - -#endif diff --git a/src/context/editor/dock-spaces/viewport/EngineFramePanel.h b/src/context/editor/dock-spaces/viewport/EngineFramePanel.h deleted file mode 100644 index cc7670bb..00000000 --- a/src/context/editor/dock-spaces/viewport/EngineFramePanel.h +++ /dev/null @@ -1,23 +0,0 @@ -#ifndef ENGINE_FRAME_PANEL_H -#define ENGINE_FRAME_PANEL_H - -#include "../../abstract/AbstractPanel.h" -#include -#include - -namespace Metal { - class EngineFrame; - - class EngineFramePanel final : public AbstractPanel { - std::unique_ptr engineFrame; - - public: - void onInitialize() override; - - void onSync() override; - - void handleViewportPicking(const ImVec2 &imageMin, const ImVec2 &imageMax) const; - }; -} // Metal - -#endif //ENGINE_FRAME_PANEL_H diff --git a/src/context/editor/dock-spaces/viewport/ViewportPanel.cpp b/src/context/editor/dock-spaces/viewport/ViewportPanel.cpp deleted file mode 100644 index 4d283a47..00000000 --- a/src/context/editor/dock-spaces/viewport/ViewportPanel.cpp +++ /dev/null @@ -1,119 +0,0 @@ -#include "ViewportPanel.h" - -#include "CameraPositionPanel.h" -#include "GizmoPanel.h" -#include "ImGuizmo.h" -#include "ViewportHeaderPanel.h" -#include "EngineFramePanel.h" -#include "../../../../context/ApplicationContext.h" -#include "../../../../service/camera/Camera.h" -#include "../../../../context/engine/frame-builder/EngineFrameBuilder.h" -#include "../../../../enum/engine-definitions.h" -#include - -namespace Metal { - void ViewportPanel::onInitialize() { - appendChild(headerPanel = new ViewportHeaderPanel()); - appendChild(engineFramePanel = new EngineFramePanel()); - appendChild(gizmoPanel = new GizmoPanel(position, size)); - appendChild(cameraPanel = new CameraPositionPanel()); - - shortcuts = { - ShortcutDTO("Change shading mode", ImGuiKey_Q, []() { - CTX.editorRepository.shadingMode = ShadingModes::ValueOfIndex( - ShadingModes::IndexOfValue(CTX.editorRepository.shadingMode) + 1); - }), - ShortcutDTO("Translate", ImGuiKey_1, []() { - CTX.editorRepository.gizmoType = ImGuizmo::OPERATION::TRANSLATE; - }), - ShortcutDTO("Scale", ImGuiKey_2, []() { - CTX.editorRepository.gizmoType = ImGuizmo::OPERATION::SCALE; - }), - ShortcutDTO("Rotate", ImGuiKey_3, []() { - CTX.editorRepository.gizmoType = ImGuizmo::OPERATION::ROTATE; - }), - ShortcutDTO("Delete", ImGuiKey_Delete, [this]() { - std::vector entities; - for (auto &entry: CTX.editorRepository.selected) { - entities.push_back(entry.first); - } - CTX.worldRepository.deleteEntities(entities); - CTX.selectionService.clearSelection(); - }), - ShortcutDTO("Select All", ImGuiMod_Ctrl | ImGuiKey_A, [this]() { - std::vector entities; - auto &storage = CTX.worldRepository.registry.storage(); - for (auto it = storage.begin(); it != storage.end(); ++it) { - auto entity = *it; - if (CTX.worldRepository.registry.all_of(entity)) { - entities.push_back(entity); - } - } - CTX.selectionService.addAllSelected(entities); - }), - ShortcutDTO("Save", ImGuiMod_Ctrl | ImGuiKey_S, [] { - CTX.save(); - }) - }; - } - - void ViewportPanel::onSync() { - updateCamera(); - updateInputs(); - - headerPanel->onSync(); - engineFramePanel->onSync(); - - gizmoPanel->onSync(); - cameraPanel->onSync(); - } - - void ViewportPanel::updateCamera() { - auto &worldRepository = CTX.worldRepository; - const auto &cameraService = CTX.cameraService; - - if (ImGui::IsWindowHovered() && !ImGuizmo::IsUsing() && ImGui::IsMouseDown(ImGuiMouseButton_Right)) { - cameraService.handleInput(isFirstMovement); - if (const auto &io = ImGui::GetIO(); io.MouseWheel != 0) { - worldRepository.camera.movementSensitivity += io.MouseWheel * 100 * CTX. - engineContext.deltaTime; - worldRepository.camera.movementSensitivity = - std::max(.1f, worldRepository.camera.movementSensitivity); - } - isFirstMovement = false; - } else { - isFirstMovement = true; - } - } - - void ViewportPanel::updateInputs() const { - auto &repo = CTX.runtimeRepository; - const ImVec2 windowSize = ImGui::GetWindowSize(); - size->x = windowSize.x; - size->y = windowSize.y; - - repo.viewportH = size->y; - repo.viewportW = size->x; - - const ImVec2 windowPos = ImGui::GetWindowPos(); - repo.viewportX = windowPos.x; - repo.viewportY = windowPos.y; - - repo.isFocused = ImGui::IsWindowHovered(); - repo.forwardPressed = ImGui::IsKeyDown(ImGuiKey_W); - repo.backwardPressed = ImGui::IsKeyDown(ImGuiKey_S); - repo.leftPressed = ImGui::IsKeyDown(ImGuiKey_A); - repo.rightPressed = ImGui::IsKeyDown(ImGuiKey_D); - repo.upPressed = ImGui::IsKeyDown(ImGuiKey_Space); - repo.downPressed = ImGui::IsKeyDown(ImGuiKey_LeftCtrl); - repo.mousePressed = ImGui::IsWindowFocused() && ImGui::IsWindowHovered() && ImGui::IsMouseDown( - ImGuiMouseButton_Left); - - const ImVec2 mousePos = ImGui::GetMousePos(); - repo.mouseX = mousePos.x; - repo.mouseY = mousePos.y; - - repo.normalizedMouseX = (repo.mouseX + repo.viewportX) / repo.viewportW; - repo.normalizedMouseY = (repo.viewportH - repo.mouseY + repo.viewportY) / repo.viewportH; - } -} diff --git a/src/context/editor/dock-spaces/viewport/ViewportPanel.h b/src/context/editor/dock-spaces/viewport/ViewportPanel.h deleted file mode 100644 index 0cc24af5..00000000 --- a/src/context/editor/dock-spaces/viewport/ViewportPanel.h +++ /dev/null @@ -1,25 +0,0 @@ -#ifndef METAL_ENGINE_VIEWPORTPANEL_H -#define METAL_ENGINE_VIEWPORTPANEL_H - -#include "../docks/AbstractDockPanel.h" - -namespace Metal { - class ViewportPanel final : public AbstractDockPanel { - bool isFirstMovement = false; - AbstractPanel *headerPanel = nullptr; - AbstractPanel *gizmoPanel = nullptr; - AbstractPanel *cameraPanel = nullptr; - AbstractPanel *engineFramePanel = nullptr; - - public: - void onInitialize() override; - - void onSync() override; - - void updateCamera(); - - void updateInputs() const; - }; -} - -#endif diff --git a/src/context/editor/panel/FileImportModalPanel.h b/src/context/editor/panel/FileImportModalPanel.h deleted file mode 100644 index 03f26316..00000000 --- a/src/context/editor/panel/FileImportModalPanel.h +++ /dev/null @@ -1,19 +0,0 @@ -#ifndef METAL_ENGINE_FILEIMPORTMODALPANEL_H -#define METAL_ENGINE_FILEIMPORTMODALPANEL_H -#include "../abstract/AbstractPanel.h" - -namespace Metal { - class FormPanel; - - class FileImportModalPanel final : public AbstractPanel { - FormPanel *formPanel = nullptr; - bool isFirst = false; - - public: - void onInitialize() override; - - void onSync() override; - }; -} // Metal - -#endif //METAL_ENGINE_FILEIMPORTMODALPANEL_H diff --git a/src/context/editor/panel/NotificationsPanel.h b/src/context/editor/panel/NotificationsPanel.h deleted file mode 100644 index 2018f3c0..00000000 --- a/src/context/editor/panel/NotificationsPanel.h +++ /dev/null @@ -1,12 +0,0 @@ -#ifndef METAL_ENGINE_NOTIFICATIONSPANEL_H -#define METAL_ENGINE_NOTIFICATIONSPANEL_H -#include "../abstract/AbstractPanel.h" - -namespace Metal { - class NotificationsPanel final : public AbstractPanel { - public: - void onSync() override; - }; -} // Metal - -#endif //METAL_ENGINE_NOTIFICATIONSPANEL_H diff --git a/src/context/engine/EngineContext.cpp b/src/context/engine/EngineContext.cpp deleted file mode 100644 index 4b8d6c85..00000000 --- a/src/context/engine/EngineContext.cpp +++ /dev/null @@ -1,87 +0,0 @@ -#include "EngineContext.h" - -#include "../../enum/EngineResourceIDs.h" -#include "../../context/ApplicationContext.h" -#include "../../service/buffer/BufferInstance.h" -#include "../../service/camera/Camera.h" -#include "../../repository/world/components/TransformComponent.h" - -namespace Metal { - void EngineContext::resetPathTracerAccumulationCount() const { - CTX.engineRepository.pathTracerAccumulationCount = 0; - } - - void EngineContext::onInitialize() { - } - - void EngineContext::updateCurrentTime() { - currentTime = Clock::now(); - std::chrono::duration delta = currentTime - previousTime; - deltaTime = delta.count(); - previousTime = currentTime; - - auto duration = std::chrono::duration_cast(currentTime.time_since_epoch()); - currentTimeMs = duration.count(); - - if (start == -1) { - start = currentTimeMs; - } - } - - void EngineContext::dispose() { - if (currentFrame != nullptr) { - currentFrame->dispose(); - } - } - - void EngineContext::onSync() { - updateCurrentTime(); - - CTX.transformService.onSync(); - CTX.streamingService.onSync(); - CTX.rayTracingService.onSync(); - CTX.cameraService.onSync(); - CTX.lightService.onSync(); - CTX.volumeService.onSync(); - - for (auto *frame: registeredFrames) { - if (frame->getShouldRender()) { - currentFrame = frame; - updateGlobalData(); - currentFrame->onSync(); - - frame->setShouldRender(false); - } - } - - setCameraUpdated(false); - setGISettingsUpdated(false); - } - - void EngineContext::updateGlobalData() { - auto &camera = CTX.worldRepository.camera; - globalDataUBO.previousProjView = globalDataUBO.projView; - globalDataUBO.viewMatrix = camera.viewMatrix; - globalDataUBO.projectionMatrix = camera.projectionMatrix; - globalDataUBO.projView = camera.projViewMatrix; - globalDataUBO.invProj = camera.invProjectionMatrix; - globalDataUBO.invView = camera.invViewMatrix; - globalDataUBO.cameraWorldPosition = camera.position; - globalDataUBO.volumeCount = CTX.volumeService.getCount(); - globalDataUBO.lightsCount = CTX.lightService.getCount(); - globalDataUBO.debugFlag = ShadingModes::IndexOfValue(CTX.editorRepository.shadingMode); - CTX.engineRepository.pathTracerAccumulationCount++; - globalDataUBO.pathTracerAccumulationCount = CTX.engineRepository.pathTracerAccumulationCount; - globalDataUBO.globalFrameCount++; - globalDataUBO.pathTracerMaxSamples = CTX.engineRepository.pathTracerMaxSamples; - globalDataUBO.denoiserEnabled = CTX.engineRepository.denoiserEnabled && ( - globalDataUBO.debugFlag == LIT || globalDataUBO.debugFlag == LIGHTING_ONLY) - ? 1 - : 0; - - CTX.lightService.computeSunInfo(); - globalDataUBO.sunPosition = CTX.lightService.getSunPosition(); - globalDataUBO.sunColor = CTX.lightService.getSunColor(); - currentFrame->getResourceAs(RID_GLOBAL_DATA)->update(&globalDataUBO); - } -} diff --git a/src/context/engine/EngineContext.h b/src/context/engine/EngineContext.h deleted file mode 100644 index 79e99f4b..00000000 --- a/src/context/engine/EngineContext.h +++ /dev/null @@ -1,69 +0,0 @@ -#ifndef METAL_ENGINE_ENGINECONTEXT_H -#define METAL_ENGINE_ENGINECONTEXT_H - -#include "frame-builder/EngineFrame.h" -#include -#include - -#include "../../dto/buffers/GlobalDataUBO.h" -#include "../../common/AbstractRuntimeComponent.h" -#include "../../dto/buffers/TileInfoUBO.h" - -using Clock = std::chrono::high_resolution_clock; -using TimePoint = std::chrono::time_point; - -namespace Metal { - class EngineContext final : public AbstractRuntimeComponent { - GlobalDataUBO globalDataUBO{}; - long long start = -1; - bool cameraUpdated = true; - bool giSettingsUpdated = true; - - public: - GlobalDataUBO &getGlobalDataUBO() { return globalDataUBO; } - - void setCameraUpdated(const bool val) { - cameraUpdated = val; - } - - bool isCameraUpdated() const { - return cameraUpdated; - } - - void setGISettingsUpdated(const bool val) { - giSettingsUpdated = val; - } - - void resetPathTracerAccumulationCount() const; - - bool isGISettingsUpdated() const { - return giSettingsUpdated; - } - - void onInitialize() override; - - void updateCurrentTime(); - - long long currentTimeMs = 0; - TimePoint currentTime; - TimePoint previousTime = Clock::now(); - float deltaTime = 0; - - std::vector registeredFrames; - EngineFrame *currentFrame = nullptr; - void updateGlobalData(); - - void registerFrame(EngineFrame *frame) { - registeredFrames.push_back(frame); - } - - void unregisterFrame(EngineFrame *frame) { - std::erase(registeredFrames, frame); - } - - void onSync() override; - - void dispose(); - }; -} -#endif diff --git a/src/context/engine/compute-pass/impl/HWRayTracingPass.h b/src/context/engine/compute-pass/impl/HWRayTracingPass.h deleted file mode 100644 index bdd574e5..00000000 --- a/src/context/engine/compute-pass/impl/HWRayTracingPass.h +++ /dev/null @@ -1,21 +0,0 @@ -#ifndef HWRAYTRACINGPASS_H -#define HWRAYTRACINGPASS_H -#include "../AbstractComputePass.h" -#include "../../../../dto/push-constant/HWRayTracingPushConstant.h" - -namespace Metal { - class HWRayTracingPass final : public AbstractComputePass { - bool isFirstRun = true; - HWRayTracingPushConstant pushConstant{}; - - public: - explicit HWRayTracingPass(const std::string &id) : AbstractComputePass(id) { - } - - void onSync() override; - - void onInitialize() override; - }; -} // Metal - -#endif //HWRAYTRACINGPASS_H diff --git a/src/context/engine/frame-builder/structures/CommandBufferRecorderBuilder.cpp b/src/context/engine/frame-builder/structures/CommandBufferRecorderBuilder.cpp deleted file mode 100644 index abb3db0f..00000000 --- a/src/context/engine/frame-builder/structures/CommandBufferRecorderBuilder.cpp +++ /dev/null @@ -1,12 +0,0 @@ -#include "CommandBufferRecorderBuilder.h" -#include "../../../ApplicationContext.h" - -namespace Metal { - RuntimeResource *CommandBufferRecorderBuilder::build() { - if (computeMode) { - return CTX.commandBufferRecorderService.createCompute(id); - } - auto *fbo = CTX.framebufferService.getResource(framebufferId); - return CTX.commandBufferRecorderService.create(id, fbo, clearBuffer); - } -} diff --git a/src/context/engine/frame-builder/structures/FramebufferBuilder.cpp b/src/context/engine/frame-builder/structures/FramebufferBuilder.cpp deleted file mode 100644 index 02d973f0..00000000 --- a/src/context/engine/frame-builder/structures/FramebufferBuilder.cpp +++ /dev/null @@ -1,32 +0,0 @@ -#include "FramebufferBuilder.h" -#include "../../../ApplicationContext.h" -#include "../../../../service/framebuffer/FrameBufferService.h" -#include "../../../../service/framebuffer/FrameBufferInstance.h" - -namespace Metal { - ResourceType FramebufferBuilder::getType() { - return ResourceType::FRAMEBUFFER; - } - - RuntimeResource* FramebufferBuilder::build() { - auto &framebufferService = CTX.framebufferService; - FrameBufferInstance* fbo = framebufferService.getResource(id); - if (fbo != nullptr) { - return fbo; - } - - fbo = framebufferService.createFrameBuffer(id, w, h, clearColor); - - for (const auto& attachment : attachments) { - framebufferService.createAttachment(attachment.format, attachment.usage, fbo); - } - - if (hasDepth) { - framebufferService.createDepthAttachment(fbo); - } - - framebufferService.createRenderPass(fbo); - - return fbo; - } -} // Metal \ No newline at end of file diff --git a/src/context/engine/frame-builder/structures/PassBuilder.cpp b/src/context/engine/frame-builder/structures/PassBuilder.cpp deleted file mode 100644 index 56ce5f6a..00000000 --- a/src/context/engine/frame-builder/structures/PassBuilder.cpp +++ /dev/null @@ -1,34 +0,0 @@ -#include "PassBuilder.h" -#include "../../render-pass/impl/PostProcessingPass.h" -#include "../../compute-pass/impl/HWRayTracingPass.h" -#include "../../compute-pass/impl/TemporalAccumulationPass.h" -#include "../../compute-pass/impl/SpatialFilterPass.h" -#include "../../render-pass/impl/tools/SelectionOutlinePass.h" -#include "../../render-pass/impl/tools/GridPass.h" -#include "../../render-pass/impl/tools/IconsPass.h" -#include "../../render-pass/impl/tools/SelectionIDPass.h" - -namespace Metal { - RuntimeResource* PassBuilder::build() { - switch (passType) { - case POST_PROCESSING: - return new PostProcessingPass(id); - case RAY_TRACING: - return new HWRayTracingPass(id); - case TEMPORAL_ACCUMULATION: - return new TemporalAccumulationPass(id); - case SPATIAL_FILTER: - return new SpatialFilterPass(id); - case SELECTION_OUTLINE: - return new SelectionOutlinePass(id); - case GRID: - return new GridPass(id); - case ICONS: - return new IconsPass(id); - case SELECTION_ID: - return new SelectionIDPass(id); - default: - return nullptr; - } - } -} diff --git a/src/context/engine/frame-builder/structures/PassBuilder.h b/src/context/engine/frame-builder/structures/PassBuilder.h deleted file mode 100644 index abba7912..00000000 --- a/src/context/engine/frame-builder/structures/PassBuilder.h +++ /dev/null @@ -1,35 +0,0 @@ -#ifndef METAL_ENGINE_PASSBUILDER_H -#define METAL_ENGINE_PASSBUILDER_H - -#include "ResourceBuilder.h" -#include "../../../../enum/PassType.h" -#include "../../../../enum/ResourceType.h" - -namespace Metal { - class PassBuilder final : public ResourceBuilder { - PassType passType; - std::string commandBufferId; - std::string framebufferId; - bool clearBuffer; - - public: - explicit PassBuilder(const std::string &id, PassType type, std::string commandBufferId, - std::string framebufferId = "", bool clearBuffer = true) - : ResourceBuilder(id), passType(type), commandBufferId(std::move(commandBufferId)), - framebufferId(std::move(framebufferId)), clearBuffer(clearBuffer) { - } - - ResourceType getType() override { - return PASS; - } - - RuntimeResource *build() override; - - [[nodiscard]] PassType getPassType() const { return passType; } - const std::string &getCommandBufferId() const { return commandBufferId; } - const std::string &getFramebufferId() const { return framebufferId; } - bool shouldClearBuffer() const { return clearBuffer; } - }; -} - -#endif diff --git a/src/context/engine/render-pass/impl/PostProcessingPass.h b/src/context/engine/render-pass/impl/PostProcessingPass.h deleted file mode 100644 index b6bb3c4b..00000000 --- a/src/context/engine/render-pass/impl/PostProcessingPass.h +++ /dev/null @@ -1,18 +0,0 @@ -#ifndef POSTPROCESSINGPASS_H -#define POSTPROCESSINGPASS_H -#include "../AbstractRenderPass.h" -#include "../../../../dto/push-constant/PostProcessingPushConstant.h" - -namespace Metal { - class PostProcessingPass final : public AbstractRenderPass { - PostProcessingPushConstant pushConstant{}; - public: - explicit PostProcessingPass(const std::string &id) : AbstractRenderPass(id) {} - - void onInitialize() override; - - void onSync() override; - }; -} // Metal - -#endif //POSTPROCESSINGPASS_H diff --git a/src/context/engine/render-pass/impl/tools/GridPass.h b/src/context/engine/render-pass/impl/tools/GridPass.h deleted file mode 100644 index e45e24f4..00000000 --- a/src/context/engine/render-pass/impl/tools/GridPass.h +++ /dev/null @@ -1,21 +0,0 @@ -#ifndef GRIDRENDERPASS_H -#define GRIDRENDERPASS_H -#include "../../AbstractRenderPass.h" -#include "../../../../../dto/push-constant/GridPushConstant.h" - -namespace Metal { - class GridPass final : public AbstractRenderPass { - GridPushConstant pushConstant{}; - - public: - explicit GridPass(const std::string &id) : AbstractRenderPass(id) {} - - void onInitialize() override; - - bool shouldRun() override; - - void onSync() override; - }; -} // Metal - -#endif //GRIDRENDERPASS_H diff --git a/src/context/engine/render-pass/impl/tools/IconsPass.cpp b/src/context/engine/render-pass/impl/tools/IconsPass.cpp deleted file mode 100644 index 8734921b..00000000 --- a/src/context/engine/render-pass/impl/tools/IconsPass.cpp +++ /dev/null @@ -1,27 +0,0 @@ -#include "IconsPass.h" - -#include "../../../../../context/ApplicationContext.h" -#include "../../../../../service/pipeline/PipelineBuilder.h" -#include "../../../../../enum/EngineResourceIDs.h" - -namespace Metal { - void IconsPass::onInitialize() { - PipelineBuilder iconPipelineBuilder = PipelineBuilder::Of( - getScopedResourceId(RID_POST_PROCESSING_FBO), - "QUAD.vert", - "tools/Icon.frag" - ) - .addBufferBinding(getScopedResourceId(RID_GLOBAL_DATA)) - .addBufferBinding(getScopedResourceId(RID_LIGHT_BUFFER)) - .setBlendEnabled(); - pipelineInstance = CTX.pipelineService.createPipeline(iconPipelineBuilder); - } - - bool IconsPass::shouldRun() { - return CTX.isDebugMode() && CTX.editorRepository.showIcons; - } - - void IconsPass::onSync() { - recordDrawSimpleInstanced(3, 1); - } -} // Metal diff --git a/src/context/engine/render-pass/impl/tools/IconsPass.h b/src/context/engine/render-pass/impl/tools/IconsPass.h deleted file mode 100644 index 604f068e..00000000 --- a/src/context/engine/render-pass/impl/tools/IconsPass.h +++ /dev/null @@ -1,18 +0,0 @@ -#ifndef ICONRENDERPASS_H -#define ICONRENDERPASS_H -#include "../../AbstractRenderPass.h" - -namespace Metal { - class IconsPass final : public AbstractRenderPass { - public: - explicit IconsPass(const std::string &id) : AbstractRenderPass(id) {} - - void onInitialize() override; - - bool shouldRun() override; - - void onSync() override; - }; -} // Metal - -#endif //ICONRENDERPASS_H diff --git a/src/context/engine/render-pass/impl/tools/SelectionIDPass.cpp b/src/context/engine/render-pass/impl/tools/SelectionIDPass.cpp deleted file mode 100644 index f34d9bee..00000000 --- a/src/context/engine/render-pass/impl/tools/SelectionIDPass.cpp +++ /dev/null @@ -1,58 +0,0 @@ -#include "SelectionIDPass.h" - -#include "../../../../../context/ApplicationContext.h" -#include "../../../../../repository/world/components/TransformComponent.h" -#include "../../../../../dto/push-constant/SelectedDotPushConstant.h" -#include "../../../../../service/pipeline/PipelineBuilder.h" -#include "../../../../../enum/EngineResourceIDs.h" - -namespace Metal { - void SelectionIDPass::onInitialize() { - PipelineBuilder builder = PipelineBuilder::Of( - getScopedResourceId(RID_SELECTION_FBO), - "tools/SelectionID.vert", - "tools/SelectionID.frag" - ) - .setPrepareForMesh() - .setCullMode(VK_CULL_MODE_NONE) - .setPushConstantsSize(sizeof(SelectedDotPushConstant)) - .addBufferBinding(getScopedResourceId(RID_GLOBAL_DATA)); - pipelineInstance = CTX.pipelineService.createPipeline(builder); - } - - bool SelectionIDPass::shouldRun() { - return !CTX.editorRepository.selected.empty(); - } - - void SelectionIDPass::onSync() { - auto &worldRepository = CTX.worldRepository; - for (auto const& [entityId, selected] : CTX.editorRepository.selected) { - if (!selected) { - continue; - } - if (!worldRepository.registry.all_of(entityId) || !worldRepository.registry.all_of(entityId)) { - continue; - } - - const auto &mesh = worldRepository.registry.get(entityId); - if (mesh.meshId.empty()) { - continue; - } - if (worldRepository.hiddenEntities.contains(entityId)) { - continue; - } - - const auto *meshInstance = CTX.meshService.stream(mesh.meshId); - if (!meshInstance) { - continue; - } - - pushConstant.model = worldRepository.registry.get(entityId).model; - pushConstant.selectionColor = glm::vec4(CTX.editorRepository.selectionColor, CTX.editorRepository.selectionOutlineThickness); - pushConstant.renderIndex = mesh.renderIndex; - - recordPushConstant(&pushConstant); - recordDrawMesh(meshInstance); - } - } -} // Metal diff --git a/src/context/engine/render-pass/impl/tools/SelectionIDPass.h b/src/context/engine/render-pass/impl/tools/SelectionIDPass.h deleted file mode 100644 index 31957bac..00000000 --- a/src/context/engine/render-pass/impl/tools/SelectionIDPass.h +++ /dev/null @@ -1,22 +0,0 @@ -#ifndef SELECTIONIDPASS_H -#define SELECTIONIDPASS_H - -#include "../../AbstractRenderPass.h" -#include "../../../../../dto/push-constant/SelectedDotPushConstant.h" - -namespace Metal { - class SelectionIDPass final : public AbstractRenderPass { - SelectedDotPushConstant pushConstant{}; - - public: - explicit SelectionIDPass(const std::string &id) : AbstractRenderPass(id) {} - - void onInitialize() override; - - bool shouldRun() override; - - void onSync() override; - }; -} // Metal - -#endif // SELECTIONIDPASS_H diff --git a/src/context/engine/render-pass/impl/tools/SelectionOutlinePass.cpp b/src/context/engine/render-pass/impl/tools/SelectionOutlinePass.cpp deleted file mode 100644 index 6e1ca4a4..00000000 --- a/src/context/engine/render-pass/impl/tools/SelectionOutlinePass.cpp +++ /dev/null @@ -1,37 +0,0 @@ -#include "SelectionOutlinePass.h" - -#include "../../../../../context/ApplicationContext.h" -#include "../../../../../repository/world/components/TransformComponent.h" -#include "../../../../../dto/push-constant/SelectedDotPushConstant.h" -#include "../../../../../service/pipeline/PipelineBuilder.h" -#include "../../../../../enum/EngineResourceIDs.h" - -namespace Metal { - void SelectionOutlinePass::onInitialize() { - PipelineBuilder builder = PipelineBuilder::Of( - getScopedResourceId(RID_POST_PROCESSING_FBO), - "QUAD.vert", - "tools/SelectedDot.frag" - ) - .setBlendEnabled() - .setPushConstantsSize(sizeof(SelectedDotPushConstant)) - .addBufferBinding(getScopedResourceId(RID_GLOBAL_DATA)) - .addFboBinding(getScopedResourceId(RID_SELECTION_FBO), 0); - pipelineInstance = CTX.pipelineService.createPipeline(builder); - } - - bool SelectionOutlinePass::shouldRun() { - return !CTX.editorRepository.selected.empty(); - } - - void SelectionOutlinePass::onSync() { - - pushConstant.selectionColor.x = CTX.editorRepository.selectionColor.x; - pushConstant.selectionColor.y = CTX.editorRepository.selectionColor.y; - pushConstant.selectionColor.z = CTX.editorRepository.selectionColor.z; - pushConstant.selectionColor.w = CTX.editorRepository.selectionOutlineThickness; - - recordPushConstant(&pushConstant); - recordDrawSimpleInstanced(3, 1); - } -} // Metal diff --git a/src/context/engine/render-pass/impl/tools/SelectionOutlinePass.h b/src/context/engine/render-pass/impl/tools/SelectionOutlinePass.h deleted file mode 100644 index 2e620341..00000000 --- a/src/context/engine/render-pass/impl/tools/SelectionOutlinePass.h +++ /dev/null @@ -1,22 +0,0 @@ -#ifndef SELECTEDDOTPASS_H -#define SELECTEDDOTPASS_H - -#include "../../AbstractRenderPass.h" -#include "../../../../../dto/push-constant/SelectedDotPushConstant.h" - -namespace Metal { - class SelectionOutlinePass final : public AbstractRenderPass { - SelectedDotPushConstant pushConstant{}; - - public: - explicit SelectionOutlinePass(const std::string &id) : AbstractRenderPass(id) {} - - void onInitialize() override; - - bool shouldRun() override; - - void onSync() override; - }; -} // Metal - -#endif // SELECTEDDOTPASS_H diff --git a/src/core/DirectoryService.cpp b/src/core/DirectoryService.cpp new file mode 100644 index 00000000..4a3bfd18 --- /dev/null +++ b/src/core/DirectoryService.cpp @@ -0,0 +1,68 @@ +#include "DirectoryService.h" +#include "../common/FileDialogUtil.h" +#include "../common/FilesUtil.h" +#include "../common/serialization-definitions.h" + +#include +#define CACHED_PATH "/metal-engine-cached.txt" +#include "../editor/repository/EditorRepository.h" +#include "../editor/service/NotificationService.h" +#include "../engine/repository/EngineRepository.h" +#include "../engine/repository/WorldRepository.h" + +namespace Metal { + void DirectoryService::onInitialize() { + NFD_Init(); + updateRootPath(false); + } + + void DirectoryService::dispose() { + NFD_Quit(); + } + + void DirectoryService::updateRootPath(bool forceSelection) { + std::string cachedPath; + std::string cachePathFile = std::filesystem::current_path().string() + CACHED_PATH; + FilesUtil::ReadFile(cachePathFile.c_str(), cachedPath); + cachedPath.erase(std::ranges::remove(cachedPath, '\n').begin(), cachedPath.cend()); + if (cachedPath.empty() || forceSelection || !fs::exists(cachedPath)) { + rootDirectory = FileDialogUtil::SelectDirectory(); + rootDirectory.erase(std::ranges::remove(rootDirectory, '\n').begin(), rootDirectory.cend()); + if (rootDirectory.empty()) { + throw std::runtime_error("No directory selected."); + } + save(); + FilesUtil::WriteFile(cachePathFile.c_str(), rootDirectory.c_str()); + } else { + rootDirectory = cachedPath; + } + + // TODO - LOOP REPOSITORY SINGLETONS AND CALL + PARSE_TEMPLATE(*editorRepository, rootDirectory + "/" + HASH_OF_CLASS_NAME(EditorRepository) + ".json") + PARSE_TEMPLATE(*engineRepository, rootDirectory + "/" + HASH_OF_CLASS_NAME(EngineRepository) + ".json") + PARSE_TEMPLATE(*worldRepository, rootDirectory + "/" + HASH_OF_CLASS_NAME(WorldRepository) + ".json") + + + FilesUtil::CreateDirectory(getShadersDirectory()); + FilesUtil::CreateDirectory(getAssetRefDirectory()); + FilesUtil::CreateDirectory(getAssetDirectory()); + } + + + void DirectoryService::save() { + try { + // TODO - LOOP REPOSITORY SINGLETONS AND CALL + + DUMP_TEMPLATE(rootDirectory + "/" + HASH_OF_CLASS_NAME(EditorRepository) + ".json", + *editorRepository) + DUMP_TEMPLATE(rootDirectory + "/" + HASH_OF_CLASS_NAME(EngineRepository) + ".json", + *engineRepository) + DUMP_TEMPLATE(rootDirectory + "/" + HASH_OF_CLASS_NAME(WorldRepository) + ".json", + *worldRepository) + notificationService->pushMessage("Project saved", NotificationSeverities::SUCCESS); + } catch (const std::exception &e) { + LOG_ERROR(e.what()); + notificationService->pushMessage("Could not save project", NotificationSeverities::ERROR); + } + } +} // Metal diff --git a/src/core/DirectoryService.h b/src/core/DirectoryService.h new file mode 100644 index 00000000..1b7c46a0 --- /dev/null +++ b/src/core/DirectoryService.h @@ -0,0 +1,60 @@ +#ifndef METAL_ENGINE_DIRECTORYSERVICE_H +#define METAL_ENGINE_DIRECTORYSERVICE_H +#include "../common/IDisposable.h" +#include "../common/IInit.h" +#include "../common/IService.h" + +namespace Metal { + struct EditorRepository; + struct EngineRepository; + struct WorldRepository; + class NotificationService; + + struct DirectoryService final : IService, IInit, IDisposable{ + EditorRepository *editorRepository = nullptr; + EngineRepository *engineRepository = nullptr; + WorldRepository *worldRepository = nullptr; + NotificationService *notificationService = nullptr; + + std::string rootDirectory; + + std::vector getDependencies() override { + return { + {"EditorRepository", &editorRepository}, + {"EngineRepository", &engineRepository}, + {"WorldRepository", &worldRepository}, + {"NotificationService", ¬ificationService} + }; + } + + void onInitialize() override; + + void dispose() override; + + void updateRootPath(bool forceSelection); + + void save(); + + [[nodiscard]] const std::string &getRootDirectory() const { + return rootDirectory; + } + + [[nodiscard]] std::string getAssetRefDirectory() const { + return rootDirectory + "/assets-ref/"; + } + + [[nodiscard]] std::string getShadersDirectory() const { + return rootDirectory + "/shaders/"; + } + + [[nodiscard]] std::string getAssetDirectory() const { + return rootDirectory + "/assets/"; + } + + [[nodiscard]] std::string getVideoOutputPath() const { + return rootDirectory + "/output.mp4"; + } + }; +} // Metal + +#endif //METAL_ENGINE_DIRECTORYSERVICE_H diff --git a/src/core/FrameService.cpp b/src/core/FrameService.cpp new file mode 100644 index 00000000..d7a96f9e --- /dev/null +++ b/src/core/FrameService.cpp @@ -0,0 +1,64 @@ +#include "FrameService.h" + +#include +#include + +#include "gui/GuiContext.h" +#include "vulkan/VulkanContext.h" +#include "glfw/GLFWContext.h" +#include "../editor/abstract/AbstractPanel.h" +#include "../engine/EngineContext.h" +#include "vulkan/VulkanUtils.h" + +namespace Metal { + unsigned int FrameService::getFrameIndex() const { + return vulkanContext->imguiVulkanWindow.FrameIndex; + } + + bool FrameService::isValidContext() const { + return glfwContext->isValidContext(); + } + + void FrameService::setPanel(AbstractPanel *panel) { + this->panel = panel; + } + + void FrameService::start() const { + GLFWwindow *window = glfwContext->getWindow(); + while (!glfwWindowShouldClose(window)) { + if (glfwContext->beginFrame()) { + GuiContext::BeginFrame(); + panel->onSync(); + ImGui::Render(); + auto *drawData = ImGui::GetDrawData(); + const bool main_is_minimized = (drawData->DisplaySize.x <= 0.0f || drawData->DisplaySize.y <= 0.0f); + if (!main_is_minimized) { + vulkanContext->getCommandBuffers().clear(); + auto &wd = vulkanContext->imguiVulkanWindow; + VkSemaphore imageAcquiredSemaphore = wd.FrameSemaphores[wd.SemaphoreIndex].ImageAcquiredSemaphore; + VkResult err = vkAcquireNextImageKHR(vulkanContext->device.device, wd.Swapchain, UINT64_MAX, + imageAcquiredSemaphore, VK_NULL_HANDLE, + &wd.FrameIndex); + if (err == VK_ERROR_OUT_OF_DATE_KHR || err == VK_SUBOPTIMAL_KHR) { + glfwContext->setSwapChainRebuild(true); + return; + } + + VulkanUtils::CheckVKResult(err); + ImGui_ImplVulkanH_Frame *fd = &wd.Frames[getFrameIndex()]; + VulkanUtils::CheckVKResult(vkWaitForFences(vulkanContext->device.device, 1, &fd->Fence, VK_TRUE, + UINT64_MAX)); + VulkanUtils::CheckVKResult(vkResetFences(vulkanContext->device.device, 1, &fd->Fence)); + VulkanUtils::CheckVKResult(vkResetCommandPool(vulkanContext->device.device, fd->CommandPool, + VK_COMMAND_POOL_RESET_RELEASE_RESOURCES_BIT)); + engineContext->onSync(); + GuiContext::RecordImguiCommandBuffer(drawData, err, wd, fd); + vulkanContext->submitFrame(imageAcquiredSemaphore, wd.FrameSemaphores[wd.SemaphoreIndex]. + RenderCompleteSemaphore, fd); + } + if (!main_is_minimized) + glfwContext->presentFrame(); + } + } + } +} // Metal diff --git a/src/core/FrameService.h b/src/core/FrameService.h new file mode 100644 index 00000000..2ed29d06 --- /dev/null +++ b/src/core/FrameService.h @@ -0,0 +1,41 @@ +#ifndef METAL_ENGINE_FRAMESERVICE_H +#define METAL_ENGINE_FRAMESERVICE_H +#include "../common/IDisposable.h" +#include "../common/IInit.h" +#include "../common/IService.h" + +namespace Metal { + class EngineContext; + class VulkanContext; + class GLFWContext; + class GuiContext; + class AbstractPanel; + + class FrameService final : public IService { + GLFWContext *glfwContext = nullptr; + VulkanContext *vulkanContext = nullptr; + EngineContext *engineContext = nullptr; + GuiContext *guiContext = nullptr; + AbstractPanel *panel = nullptr; + + public: + std::vector getDependencies() override { + return { + {"GLFWContext", &glfwContext}, + {"VulkanContext", &vulkanContext}, + {"GuiContext", &guiContext}, + {"EngineContext", &engineContext} + }; + } + + void setPanel(AbstractPanel *panel); + + void start() const; + + [[nodiscard]] bool isValidContext() const; + + [[nodiscard]] unsigned int getFrameIndex() const; + }; +} // Metal + +#endif //METAL_ENGINE_FRAMESERVICE_H diff --git a/src/context/glfw/GLFWContext.cpp b/src/core/glfw/GLFWContext.cpp similarity index 74% rename from src/context/glfw/GLFWContext.cpp rename to src/core/glfw/GLFWContext.cpp index b819dc08..7a3a6e26 100644 --- a/src/context/glfw/GLFWContext.cpp +++ b/src/core/glfw/GLFWContext.cpp @@ -1,7 +1,8 @@ #include #include "GLFWContext.h" -#include "../ApplicationContext.h" -#include "../../util/VulkanUtils.h" +#include "../../ApplicationContext.h" +#include "../vulkan/VulkanUtils.h" +#include "../vulkan/VulkanContext.h" namespace Metal { GLFWwindow *GLFWContext::getWindow() const { @@ -19,19 +20,19 @@ namespace Metal { int fb_width, fb_height; glfwGetFramebufferSize(window, &fb_width, &fb_height); if (fb_width > 0 && fb_height > 0 && - (swapChainRebuild || CTX.vulkanContext.imguiVulkanWindow.Width != + (swapChainRebuild || vulkanContext->imguiVulkanWindow.Width != fb_width || - CTX.vulkanContext.imguiVulkanWindow.Height != fb_height)) { + vulkanContext->imguiVulkanWindow.Height != fb_height)) { ImGui_ImplVulkan_SetMinImageCount(MAX_FRAMES_IN_FLIGHT); - ImGui_ImplVulkanH_CreateOrResizeWindow(CTX.vulkanContext.instance.instance, - CTX.vulkanContext.physDevice.physical_device, - CTX.vulkanContext.device.device, - &CTX.vulkanContext.imguiVulkanWindow, - CTX.vulkanContext.queueFamily, + ImGui_ImplVulkanH_CreateOrResizeWindow(vulkanContext->instance.instance, + vulkanContext->physDevice.physical_device, + vulkanContext->device.device, + &vulkanContext->imguiVulkanWindow, + vulkanContext->queueFamily, nullptr, fb_width, fb_height, MAX_FRAMES_IN_FLIGHT); - CTX.vulkanContext.imguiVulkanWindow.FrameIndex = 0; + vulkanContext->imguiVulkanWindow.FrameIndex = 0; swapChainRebuild = false; } if (glfwGetWindowAttrib(window, GLFW_ICONIFIED) != 0) { @@ -41,13 +42,13 @@ namespace Metal { return true; } - void GLFWContext::dispose() const { + void GLFWContext::disposeManually() { glfwDestroyWindow(window); glfwTerminate(); } ImGui_ImplVulkanH_Window &GLFWContext::getGUIWindow() const { - return CTX.vulkanContext.imguiVulkanWindow; + return vulkanContext->imguiVulkanWindow; } void GLFWContext::setSwapChainRebuild(const bool val) { @@ -58,7 +59,7 @@ namespace Metal { if (swapChainRebuild) { return; } - auto &wd = CTX.vulkanContext.imguiVulkanWindow; + auto &wd = vulkanContext->imguiVulkanWindow; VkSemaphore semaphore = wd.FrameSemaphores[wd.SemaphoreIndex].RenderCompleteSemaphore; VkPresentInfoKHR info = {}; info.sType = VK_STRUCTURE_TYPE_PRESENT_INFO_KHR; @@ -67,7 +68,7 @@ namespace Metal { info.swapchainCount = 1; info.pSwapchains = &wd.Swapchain; info.pImageIndices = &wd.FrameIndex; - VkResult err = vkQueuePresentKHR(CTX.vulkanContext.graphicsQueue, &info); + VkResult err = vkQueuePresentKHR(vulkanContext->graphicsQueue, &info); if (err == VK_ERROR_OUT_OF_DATE_KHR || err == VK_SUBOPTIMAL_KHR) { swapChainRebuild = true; return; @@ -85,6 +86,7 @@ namespace Metal { if (validContext) { glfwWindowHint(GLFW_CLIENT_API, GLFW_NO_API); + glfwWindowHint(GLFW_DECORATED, GLFW_FALSE); window = glfwCreateWindow(1280, 720, ENGINE_NAME, nullptr, nullptr); if (!glfwVulkanSupported()) { diff --git a/src/context/glfw/GLFWContext.h b/src/core/glfw/GLFWContext.h similarity index 67% rename from src/context/glfw/GLFWContext.h rename to src/core/glfw/GLFWContext.h index a2df6e3e..33ad1dc3 100644 --- a/src/context/glfw/GLFWContext.h +++ b/src/core/glfw/GLFWContext.h @@ -6,28 +6,34 @@ #include #include -#include "../../common/AbstractRuntimeComponent.h" + +#include "../../common/IContextMember.h" +#include "../../common/IDisposable.h" +#include "../../common/IInit.h" struct ImGui_ImplVulkanH_Window; namespace Metal { class ApplicationContext; + class VulkanContext; - class GLFWContext final : public Initializable { + class GLFWContext final : public IContextMember, public IInit { + VulkanContext *vulkanContext = nullptr; GLFWwindow *window = nullptr; bool validContext = true; - ; bool swapChainRebuild = false; ImVector instance_extensions{}; public: + std::vector getDependencies() override { + return {{"VulkanContext", &vulkanContext}}; + } + void setSwapChainRebuild(bool val); void presentFrame(); - explicit GLFWContext() = default; - [[nodiscard]] const ImVector &getInstanceExtensions() const; void onInitialize() override; @@ -38,7 +44,7 @@ namespace Metal { bool beginFrame(); - void dispose() const; + void disposeManually(); [[nodiscard]] ImGui_ImplVulkanH_Window &getGUIWindow() const; }; diff --git a/src/context/gui/GuiContext.cpp b/src/core/gui/GuiContext.cpp similarity index 77% rename from src/context/gui/GuiContext.cpp rename to src/core/gui/GuiContext.cpp index f78080aa..97c06c7c 100644 --- a/src/context/gui/GuiContext.cpp +++ b/src/core/gui/GuiContext.cpp @@ -2,18 +2,22 @@ #include #include "imgui_freetype.h" -#include "../ApplicationContext.h" -#include "../../util/VulkanUtils.h" -#include "../../service/descriptor/DescriptorInstance.h" -#include "../../service/texture/TextureInstance.h" +#include "../../ApplicationContext.h" +#include "../vulkan/VulkanUtils.h" +#include "../../engine/dto/DescriptorInstance.h" +#include "../../engine/resource/TextureInstance.h" + +#include "../vulkan/VulkanContext.h" +#include "../glfw/GLFWContext.h" +#include "../../engine/service/DescriptorSetService.h" +#include "../../editor/enum/engine-definitions.h" namespace Metal { void GuiContext::endFrame() { - } void GuiContext::renderImage(TextureInstance *texture, const float sizeX, const float sizeY) const { - CTX.descriptorSetService.setImageDescriptor(texture); + descriptorSetService->setImageDescriptor(texture); ImGui::Image(reinterpret_cast(texture->imageDescriptor->vkDescriptorSet), ImVec2{sizeX, sizeY}); } @@ -29,7 +33,8 @@ namespace Metal { info.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO; info.flags |= VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT; err = vkBeginCommandBuffer(fd->CommandBuffer, &info); - VulkanUtils::CheckVKResult(err); { + VulkanUtils::CheckVKResult(err); + { VkRenderPassBeginInfo info = {}; info.sType = VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO; info.renderPass = wd.RenderPass; @@ -61,19 +66,19 @@ namespace Metal { io.ConfigWindowsResizeFromEdges = true; // Setup Platform/Renderer backends - ImGui_ImplGlfw_InitForVulkan(CTX.glfwContext.getWindow(), true); + ImGui_ImplGlfw_InitForVulkan(glfwContext->getWindow(), true); ImGui_ImplVulkan_InitInfo init_info = {}; - init_info.Instance = CTX.vulkanContext.instance.instance; - init_info.PhysicalDevice = CTX.vulkanContext.physDevice.physical_device; - init_info.Device = CTX.vulkanContext.device.device; - init_info.QueueFamily = CTX.vulkanContext.queueFamily; - init_info.Queue = CTX.vulkanContext.graphicsQueue; - init_info.PipelineCache = CTX.vulkanContext.pipelineCache; - init_info.DescriptorPool = CTX.vulkanContext.descriptorPool; - init_info.RenderPass = CTX.vulkanContext.imguiVulkanWindow.RenderPass; + init_info.Instance = vulkanContext->instance.instance; + init_info.PhysicalDevice = vulkanContext->physDevice.physical_device; + init_info.Device = vulkanContext->device.device; + init_info.QueueFamily = vulkanContext->queueFamily; + init_info.Queue = vulkanContext->graphicsQueue; + init_info.PipelineCache = vulkanContext->pipelineCache; + init_info.DescriptorPool = vulkanContext->descriptorPool; + init_info.RenderPass = vulkanContext->imguiVulkanWindow.RenderPass; init_info.Subpass = 0; init_info.MinImageCount = MAX_FRAMES_IN_FLIGHT; - init_info.ImageCount = CTX.vulkanContext.imguiVulkanWindow.ImageCount; + init_info.ImageCount = vulkanContext->imguiVulkanWindow.ImageCount; init_info.MSAASamples = VK_SAMPLE_COUNT_1_BIT; init_info.Allocator = nullptr; init_info.CheckVkResultFn = VulkanUtils::CheckVKResult; @@ -136,17 +141,14 @@ namespace Metal { delete fontConfig; } - void GuiContext::dispose() const { - const VkResult err = vkDeviceWaitIdle(CTX.vulkanContext.device.device); + void GuiContext::disposeManually() { + const VkResult err = vkDeviceWaitIdle(vulkanContext->device.device); VulkanUtils::CheckVKResult(err); ImGui_ImplVulkan_Shutdown(); ImGui_ImplGlfw_Shutdown(); ImGui::DestroyContext(); - ImGui_ImplVulkanH_DestroyWindow(CTX.vulkanContext.instance, CTX.vulkanContext.device.device, - &CTX.glfwContext.getGUIWindow(), + ImGui_ImplVulkanH_DestroyWindow(vulkanContext->instance.instance, vulkanContext->device.device, + &glfwContext->getGUIWindow(), nullptr); } - - GuiContext::GuiContext() : AbstractRuntimeComponent() { - } } diff --git a/src/context/gui/GuiContext.h b/src/core/gui/GuiContext.h similarity index 53% rename from src/context/gui/GuiContext.h rename to src/core/gui/GuiContext.h index e360874b..7a27eb6a 100644 --- a/src/context/gui/GuiContext.h +++ b/src/core/gui/GuiContext.h @@ -1,16 +1,25 @@ #ifndef METAL_ENGINE_GUICONTEXT_H #define METAL_ENGINE_GUICONTEXT_H -#define LARGE_FONT_SIZE 38 #include #include -#include "../../common/AbstractRuntimeComponent.h" +#include "../../common/IService.h" +#include "../../common/IDisposable.h" +#include "../../common/IInit.h" namespace Metal { + class GLFWContext; struct FrameBufferAttachment; struct TextureInstance; - class GuiContext final : public AbstractRuntimeComponent { + class VulkanContext; + class DescriptorSetService; + + class GuiContext final : public IService, public IInit { + VulkanContext *vulkanContext = nullptr; + GLFWContext *glfwContext = nullptr; + DescriptorSetService *descriptorSetService = nullptr; + static void applySpacing(); void applyFonts(); @@ -19,13 +28,21 @@ namespace Metal { ImFont *largeIconsFont = nullptr; public: - explicit GuiContext(); + GuiContext() = default; + + std::vector getDependencies() override { + return { + {"VulkanContext", &vulkanContext}, + {"GLFWContext", &glfwContext}, + {"DescriptorSetService", &descriptorSetService} + }; + } [[ nodiscard]] ImFont *getLargeIconsFont() const { return largeIconsFont; } - void dispose() const; + void disposeManually(); void onInitialize() override; diff --git a/src/context/vulkan/VulkanContext.cpp b/src/core/vulkan/VulkanContext.cpp similarity index 91% rename from src/context/vulkan/VulkanContext.cpp rename to src/core/vulkan/VulkanContext.cpp index c2ef2593..68520c7d 100644 --- a/src/context/vulkan/VulkanContext.cpp +++ b/src/core/vulkan/VulkanContext.cpp @@ -1,13 +1,16 @@ #include "VulkanContext.h" - #include "VkBootstrap.h" -#include "../../util/VulkanUtils.h" -#include "../ApplicationContext.h" +#include "VulkanUtils.h" +#include "../../ApplicationContext.h" +#include "../../common/LoggerUtil.h" + +#include "../glfw/GLFWContext.h" +#include "../../engine/repository/EngineRepository.h" +#include "../../engine/service/MeshService.h" +#include "../../engine/service/TextureService.h" +#include "../../engine/service/FrameBufferService.h" namespace Metal { - VulkanContext::VulkanContext(bool debugMode) : AbstractRuntimeComponent(), - debugMode(debugMode) { - } void VulkanContext::createSwapChain() { int w{}, h{}; @@ -162,7 +165,7 @@ namespace Metal { } void VulkanContext::createPresentMode() { - VkPresentModeKHR presentModes = !CTX.engineRepository.vsync + VkPresentModeKHR presentModes = !engineRepository->vsync ? VK_PRESENT_MODE_IMMEDIATE_KHR : VK_PRESENT_MODE_FIFO_KHR; imguiVulkanWindow.PresentMode = ImGui_ImplVulkanH_SelectPresentMode( @@ -208,7 +211,7 @@ namespace Metal { const ImVector &instanceExtensions) const { if (auto sysInfoResult = vkb::SystemInfo::get_system_info(); sysInfoResult) { const auto &sysInfo = sysInfoResult.value(); - if (sysInfo.validation_layers_available && debugMode) { + if (sysInfo.validation_layers_available && ctx->isDebugMode()) { if (sysInfo.is_layer_available("VK_LAYER_LUNARG_api_dump")) { // instanceBuilder.enable_layer("VK_LAYER_LUNARG_api_dump"); } @@ -249,17 +252,17 @@ namespace Metal { } void VulkanContext::onInitialize() { + this->window = glfwContext->getWindow(); + imguiVulkanWindow.ClearValue.color.float32[0] = 0; imguiVulkanWindow.ClearValue.color.float32[1] = 0; imguiVulkanWindow.ClearValue.color.float32[2] = 0; imguiVulkanWindow.ClearValue.color.float32[3] = 1; - - this->window = CTX.glfwContext.getWindow(); vkb::InstanceBuilder instanceBuilder; // ------- CORE INITIALIZATION // ----- INSTANCE AND EXTENSIONS - addExtensions(instanceBuilder, CTX.glfwContext.getInstanceExtensions()); + addExtensions(instanceBuilder, glfwContext->getInstanceExtensions()); auto vkbResult = instanceBuilder .set_app_name(ENGINE_NAME) .set_engine_name(ENGINE_NAME) @@ -281,28 +284,22 @@ namespace Metal { createMemoryAllocator(); createCommandPool(); createDescriptorPool(); - CTX.textureService.createSampler(false, vkImageSampler, VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_BORDER); - CTX.textureService.createSampler(true, vkTextureSampler, VK_SAMPLER_ADDRESS_MODE_REPEAT); + textureService->createSampler(false, vkImageSampler, VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_BORDER); + textureService->createSampler(true, vkTextureSampler, VK_SAMPLER_ADDRESS_MODE_REPEAT); // ------- CORE INITIALIZATION } - void VulkanContext::dispose() const { - CTX.pipelineService.disposeAll(); - CTX.textureService.disposeAll(); - CTX.meshService.disposeAll(); - CTX.framebufferService.disposeAll(); - CTX.rayTracingService.destroyAccelerationStructures(); + void VulkanContext::disposeManually() { vkDestroySampler(device.device, vkImageSampler, nullptr); vkDestroySampler(device.device, vkTextureSampler, nullptr); - vkDestroyDescriptorPool(CTX.vulkanContext.device.device, descriptorPool, + vkDestroyDescriptorPool(device.device, descriptorPool, nullptr); - vkDestroyCommandPool(CTX.vulkanContext.device.device, commandPool, + vkDestroyCommandPool(device.device, commandPool, nullptr); vkDestroyDevice(device.device, nullptr); - vkDestroySurfaceKHR(instance.instance, surface, nullptr); vkb::destroy_instance(instance); } @@ -317,13 +314,14 @@ namespace Metal { VkDescriptorPoolCreateInfo poolInfo{}; poolInfo.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_POOL_CREATE_INFO; - poolInfo.poolSizeCount = sizes.size(); + poolInfo.poolSizeCount = static_cast(sizes.size()); poolInfo.pPoolSizes = sizes.data(); - poolInfo.flags = VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT | VK_DESCRIPTOR_POOL_CREATE_UPDATE_AFTER_BIND_BIT; + poolInfo.flags = VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT | + VK_DESCRIPTOR_POOL_CREATE_UPDATE_AFTER_BIND_BIT; poolInfo.maxSets = 500; VulkanUtils::CheckVKResult(vkCreateDescriptorPool(device.device, &poolInfo, - nullptr, &CTX.vulkanContext.descriptorPool)); + nullptr, const_cast(&descriptorPool))); } VkCommandBuffer VulkanContext::beginSingleTimeCommands() const { @@ -360,19 +358,19 @@ namespace Metal { void VulkanContext::submitFrame(VkSemaphore image_acquired_semaphore, VkSemaphore render_complete_semaphore, - ImGui_ImplVulkanH_Frame *fd) const { + ImGui_ImplVulkanH_Frame *fd) { VkPipelineStageFlags wait_stage = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT; VkSubmitInfo info = {}; - CTX.vulkanContext.pushCommandBuffer(fd->CommandBuffer); + pushCommandBuffer(fd->CommandBuffer); info.sType = VK_STRUCTURE_TYPE_SUBMIT_INFO; info.waitSemaphoreCount = 1; info.pWaitSemaphores = &image_acquired_semaphore; info.pWaitDstStageMask = &wait_stage; - info.commandBufferCount = CTX.vulkanContext.getCommandBuffers().size(); - info.pCommandBuffers = CTX.vulkanContext.getCommandBuffers().data(); + info.commandBufferCount = getCommandBuffers().size(); + info.pCommandBuffers = getCommandBuffers().data(); info.signalSemaphoreCount = 1; info.pSignalSemaphores = &render_complete_semaphore; VulkanUtils::CheckVKResult(vkEndCommandBuffer(fd->CommandBuffer)); - VulkanUtils::CheckVKResult(vkQueueSubmit(CTX.vulkanContext.graphicsQueue, 1, &info, fd->Fence)); + VulkanUtils::CheckVKResult(vkQueueSubmit(graphicsQueue, 1, &info, fd->Fence)); } } diff --git a/src/context/vulkan/VulkanContext.h b/src/core/vulkan/VulkanContext.h similarity index 73% rename from src/context/vulkan/VulkanContext.h rename to src/core/vulkan/VulkanContext.h index 2f74c8e4..2fe36230 100644 --- a/src/context/vulkan/VulkanContext.h +++ b/src/core/vulkan/VulkanContext.h @@ -2,17 +2,34 @@ #define METAL_ENGINE_VULKANCONTEXT_H #include "vk_mem_alloc.h" -#include #include "imgui_impl_vulkan.h" #include #include "VkBootstrap.h" -#include "../../common/AbstractRuntimeComponent.h" +#include "../../common/IInit.h" +#include "../../common/IService.h" +#include "../../common/IDisposable.h" #define VK_KHR_PORTABILITY_SUBSET_EXTENSION_NAME "VK_KHR_portability_subset" namespace Metal { - class VulkanContext final : public AbstractRuntimeComponent { + class GLFWContext; + struct EngineRepository; + class MeshService; + class TextureService; + class FrameBufferService; + class PipelineService; + class RayTracingService; + + class VulkanContext final : public IService, public IInit { + GLFWContext *glfwContext = nullptr; + EngineRepository *engineRepository = nullptr; + MeshService *meshService = nullptr; + TextureService *textureService = nullptr; + FrameBufferService *framebufferService = nullptr; + PipelineService *pipelineService = nullptr; + RayTracingService *rayTracingService = nullptr; + static VkBool32 DebugCallback(VkDebugUtilsMessageSeverityFlagBitsEXT messageSeverity, VkDebugUtilsMessageTypeFlagsEXT messageType, const VkDebugUtilsMessengerCallbackDataEXT *pCallbackData, @@ -41,7 +58,6 @@ namespace Metal { unsigned int w{}, h{}; GLFWwindow *window = nullptr; - bool debugMode = false; std::vector commandBuffers{}; public: @@ -51,7 +67,17 @@ namespace Metal { std::vector &getCommandBuffers() { return commandBuffers; } - explicit VulkanContext(bool debugMode); + std::vector getDependencies() override { + return { + {"GLFWContext", &glfwContext}, + {"EngineRepository", &engineRepository}, + {"MeshService", &meshService}, + {"TextureService", &textureService}, + {"FrameBufferService", &framebufferService}, + {"PipelineService", &pipelineService}, + {"RayTracingService", &rayTracingService} + }; + } VkPhysicalDeviceProperties physicalDeviceProperties{}; VkPhysicalDeviceMemoryProperties physicalDeviceMemoryProperties{}; @@ -81,7 +107,7 @@ namespace Metal { PFN_vkGetRayTracingShaderGroupHandlesKHR vkGetRayTracingShaderGroupHandlesKHR = nullptr; PFN_vkCmdTraceRaysKHR vkCmdTraceRaysKHR = nullptr; - void dispose() const; + void disposeManually(); void onInitialize() override; @@ -98,7 +124,7 @@ namespace Metal { void endSingleTimeCommands(VkCommandBuffer commandBuffer) const; void submitFrame(VkSemaphore image_acquired_semaphore, VkSemaphore render_complete_semaphore, - ImGui_ImplVulkanH_Frame *fd) const; + ImGui_ImplVulkanH_Frame *fd); }; } // Metal diff --git a/src/util/VulkanUtils.cpp b/src/core/vulkan/VulkanUtils.cpp similarity index 92% rename from src/util/VulkanUtils.cpp rename to src/core/vulkan/VulkanUtils.cpp index 32bdd127..9890c96a 100644 --- a/src/util/VulkanUtils.cpp +++ b/src/core/vulkan/VulkanUtils.cpp @@ -1,8 +1,8 @@ #include "VulkanUtils.h" -#include "../../dependencies/vk-bootstrap/src/VkBootstrap.h" -#include "../context/ApplicationContext.h" -#include "../service/log/LogService.h" +#include "../../../dependencies/vk-bootstrap/src/VkBootstrap.h" +#include "../../ApplicationContext.h" +#include "../../common/LoggerUtil.h" namespace Metal { void VulkanUtils::CheckVKResult(VkResult err) { diff --git a/src/util/VulkanUtils.h b/src/core/vulkan/VulkanUtils.h similarity index 100% rename from src/util/VulkanUtils.h rename to src/core/vulkan/VulkanUtils.h diff --git a/src/dto/buffers/TileInfoUBO.h b/src/dto/buffers/TileInfoUBO.h deleted file mode 100644 index f2dd1a80..00000000 --- a/src/dto/buffers/TileInfoUBO.h +++ /dev/null @@ -1,13 +0,0 @@ -#ifndef TILEINFOUBO_H -#define TILEINFOUBO_H -#include -#include - -namespace Metal { - struct TileInfoUBO final { - std::array tileCenterValid{}; - std::array voxelBufferOffset{}; - }; -} - -#endif //TILEINFOUBO_H diff --git a/src/editor/EditorPanel.cpp b/src/editor/EditorPanel.cpp new file mode 100644 index 00000000..8626f437 --- /dev/null +++ b/src/editor/EditorPanel.cpp @@ -0,0 +1,112 @@ +#include "EditorPanel.h" +#include "util/UIUtil.h" +#include "../ApplicationContext.h" +#include "service/DockService.h" +#include "service/ThemeService.h" +#include "dock-spaces/header/EditorHeaderPanel.h" +#include "dock-spaces/footer/EditorFooterPanel.h" +#include "panel/FileImportModalPanel.h" +#include "panel/NotificationsPanel.h" + +namespace Metal { + int EditorPanel::FLAGS = ImGuiWindowFlags_NoDocking | + ImGuiWindowFlags_NoTitleBar | + ImGuiWindowFlags_NoCollapse | + ImGuiWindowFlags_NoResize | + ImGuiWindowFlags_NoMove | + ImGuiWindowFlags_NoBringToFrontOnFocus | + ImGuiWindowFlags_NoNavFocus; + const char *EditorPanel::NAME = "##main_window"; + const char *EditorPanel::NAME_HEADER = "##header_window"; + const char *EditorPanel::NAME_FOOTER = "##footer_window"; + ImVec2 EditorPanel::CENTER(0.0f, 0.0f); + float EditorPanel::HEADER_HEIGHT = 25; + float EditorPanel::FOOTER_HEIGHT = 30; + + + void EditorPanel::renderDockSpaces() { + const ImGuiViewport *viewport = ImGui::GetMainViewport(); + + // Header + { + UIUtil::AUX_VEC2.x = viewport->Pos.x; + UIUtil::AUX_VEC2.y = viewport->Pos.y; + ImGui::SetNextWindowPos(UIUtil::AUX_VEC2); + + UIUtil::AUX_VEC2.x = viewport->Size.x; + UIUtil::AUX_VEC2.y = HEADER_HEIGHT; + ImGui::SetNextWindowSize(UIUtil::AUX_VEC2); + + SetWindowStyle(); + ImGui::Begin(NAME_HEADER, &UIUtil::OPEN, FLAGS | ImGuiWindowFlags_NoScrollbar); + ImGui::PopStyleVar(3); + + headerPanel->onSync(); + ImGui::End(); + } + + // Main Window (DockSpace) + { + UIUtil::AUX_VEC2.x = viewport->Pos.x; + UIUtil::AUX_VEC2.y = viewport->Pos.y + HEADER_HEIGHT; + ImGui::SetNextWindowPos(UIUtil::AUX_VEC2); + + UIUtil::AUX_VEC2.x = viewport->Size.x; + UIUtil::AUX_VEC2.y = viewport->Size.y - HEADER_HEIGHT - FOOTER_HEIGHT; + ImGui::SetNextWindowSize(UIUtil::AUX_VEC2); + ImGui::SetNextWindowViewport(viewport->ID); + + SetWindowStyle(); + ImGui::Begin(NAME, &UIUtil::OPEN, FLAGS); + windowId = ImGui::GetID(NAME); + ImGui::PopStyleVar(3); + + dockService->buildViews(windowId, this); + + ImGui::PushStyleVar(ImGuiStyleVar_FrameBorderSize, 0.0f); + ImGui::DockSpace(windowId, CENTER, ImGuiDockNodeFlags_PassthruCentralNode); + ImGui::PopStyleVar(1); + + onSyncChildren(); + ImGui::End(); + } + + // Footer + { + UIUtil::AUX_VEC2.x = viewport->Pos.x; + UIUtil::AUX_VEC2.y = viewport->Pos.y + viewport->Size.y - FOOTER_HEIGHT; + ImGui::SetNextWindowPos(UIUtil::AUX_VEC2); + + UIUtil::AUX_VEC2.x = viewport->Size.x; + UIUtil::AUX_VEC2.y = FOOTER_HEIGHT; + ImGui::SetNextWindowSize(UIUtil::AUX_VEC2); + + SetWindowStyle(); + ImGui::Begin(NAME_FOOTER, &UIUtil::OPEN, FLAGS | ImGuiWindowFlags_NoScrollbar); + ImGui::PopStyleVar(3); + + footerPanel->onSync(); + ImGui::End(); + } + } + + void EditorPanel::SetWindowStyle() { + ImGui::PushStyleVar(ImGuiStyleVar_WindowRounding, 0.0f); + ImGui::PushStyleVar(ImGuiStyleVar_WindowBorderSize, 0.0f); + ImGui::PushStyleVar(ImGuiStyleVar_WindowPadding, UIUtil::VEC2_ZERO); + } + + void EditorPanel::onSync() { + themeService->onSync(); + renderDockSpaces(); + notificationsPanel->onSync(); + fileImportModalPanel->onSync(); + } + + void EditorPanel::onInitialize() { + initializePanel(headerPanel = new EditorHeaderPanel(), false); + initializePanel(footerPanel = new EditorFooterPanel(), false); + initializePanel(notificationsPanel = new NotificationsPanel(), false); + initializePanel(fileImportModalPanel = new FileImportModalPanel(), false); + } +} diff --git a/src/context/editor/EditorPanel.h b/src/editor/EditorPanel.h similarity index 60% rename from src/context/editor/EditorPanel.h rename to src/editor/EditorPanel.h index 0a1983e7..f3a97a12 100644 --- a/src/context/editor/EditorPanel.h +++ b/src/editor/EditorPanel.h @@ -5,24 +5,38 @@ #include "abstract/AbstractPanel.h" namespace Metal { + class DockService; + class ThemeService; + class EditorPanel final : public AbstractPanel { static int FLAGS; static const char *NAME; static const char *NAME_HEADER; + static const char *NAME_FOOTER; static ImVec2 CENTER; static float HEADER_HEIGHT; + static float FOOTER_HEIGHT; ImGuiID windowId = 0; AbstractPanel *headerPanel = nullptr; + AbstractPanel *footerPanel = nullptr; AbstractPanel *notificationsPanel = nullptr; AbstractPanel *fileImportModalPanel = nullptr; + DockService *dockService = nullptr; + ThemeService *themeService = nullptr; + static void SetWindowStyle(); void renderDockSpaces(); - void renderHeader(const ImGuiViewport *viewport); - public: + std::vector getDependencies() override { + return { + {"DockService", &dockService}, + {"ThemeService", &themeService} + }; + } + void onInitialize() override; void onSync() override; diff --git a/src/context/editor/abstract/AbstractPanel.cpp b/src/editor/abstract/AbstractPanel.cpp similarity index 59% rename from src/context/editor/abstract/AbstractPanel.cpp rename to src/editor/abstract/AbstractPanel.cpp index 93beda28..d3e1f1a6 100644 --- a/src/context/editor/abstract/AbstractPanel.cpp +++ b/src/editor/abstract/AbstractPanel.cpp @@ -1,10 +1,15 @@ #include "AbstractPanel.h" -#include "../../../util/Util.h" +#include "../util/Util.h" +#include "../../ApplicationContext.h" namespace Metal { - void AbstractPanel::appendChild(AbstractPanel *panel) { + void AbstractPanel::initializePanel(AbstractPanel *panel, bool addToChildList) { + panel->ctx = ctx; + ctx->injectDependencies(panel); panel->onInitialize(); - children.emplace_back(panel); + if (addToChildList) { + children.push_back(panel); + } } void AbstractPanel::onSyncChildren() const { @@ -24,7 +29,7 @@ namespace Metal { children.clear(); } - std::vector &AbstractPanel::getChildren() { + std::vector &AbstractPanel::getChildren() { return children; } } diff --git a/src/editor/abstract/AbstractPanel.h b/src/editor/abstract/AbstractPanel.h new file mode 100644 index 00000000..651f9d6b --- /dev/null +++ b/src/editor/abstract/AbstractPanel.h @@ -0,0 +1,33 @@ +#ifndef METAL_ENGINE_ABSTRACTPANEL_H +#define METAL_ENGINE_ABSTRACTPANEL_H + +#include +#include + +#include "../../common/IContextMember.h" +#include "../../common/ISync.h" +#include "../../common/IInit.h" + +namespace Metal { + class ApplicationContext; + class AbstractPanel : public IContextMember, public ISync, public IInit { + protected: + std::vector children; + const std::string id; + + virtual void onSyncChildren() const; + + public: + explicit AbstractPanel(); + + std::vector &getChildren(); + + void initializePanel(AbstractPanel *panel, bool addToChildList = true); + + void removeAllChildren(); + + virtual void onRemove() { + } + }; +} +#endif diff --git a/src/context/editor/abstract/form/AbstractFormFieldPanel.h b/src/editor/abstract/form/AbstractFormFieldPanel.h similarity index 75% rename from src/context/editor/abstract/form/AbstractFormFieldPanel.h rename to src/editor/abstract/form/AbstractFormFieldPanel.h index 4ab21a41..f3381221 100644 --- a/src/context/editor/abstract/form/AbstractFormFieldPanel.h +++ b/src/editor/abstract/form/AbstractFormFieldPanel.h @@ -6,10 +6,20 @@ #include "../AbstractPanel.h" namespace Metal { + class ThemeService; + class AbstractFormFieldPanel : public AbstractPanel { protected: const std::string* filter = nullptr; + + ThemeService *themeService = nullptr; public: + + std::vector getDependencies() override { + return { + {"ThemeService", &themeService} + }; + } [[nodiscard]] virtual bool isVisible() const = 0; void onSyncChildren() const override { diff --git a/src/context/editor/abstract/form/AccordionPanel.cpp b/src/editor/abstract/form/AccordionPanel.cpp similarity index 89% rename from src/context/editor/abstract/form/AccordionPanel.cpp rename to src/editor/abstract/form/AccordionPanel.cpp index bf310e4b..bb3789a2 100644 --- a/src/context/editor/abstract/form/AccordionPanel.cpp +++ b/src/editor/abstract/form/AccordionPanel.cpp @@ -1,6 +1,7 @@ #include "AccordionPanel.h" #include "imgui.h" #include "../../../ApplicationContext.h" +#include "../../service/ThemeService.h" namespace Metal { void AccordionPanel::setTitle(const std::string &t) { @@ -14,7 +15,7 @@ namespace Metal { return; } - ImGui::PushStyleColor(ImGuiCol_Header, CTX.themeService.neutralPalette); + ImGui::PushStyleColor(ImGuiCol_Header, themeService->neutralPalette); bool open = ImGui::CollapsingHeader(fixedId.c_str(), ImGuiTreeNodeFlags_None); ImGui::PopStyleColor(); diff --git a/src/context/editor/abstract/form/AccordionPanel.h b/src/editor/abstract/form/AccordionPanel.h similarity index 94% rename from src/context/editor/abstract/form/AccordionPanel.h rename to src/editor/abstract/form/AccordionPanel.h index b161a2a4..65a787e4 100644 --- a/src/context/editor/abstract/form/AccordionPanel.h +++ b/src/editor/abstract/form/AccordionPanel.h @@ -4,12 +4,13 @@ #include "AbstractFormFieldPanel.h" namespace Metal { + class ThemeService; + class AccordionPanel final : public AbstractFormFieldPanel { std::string fixedId = id; std::string title; public: - void setTitle(const std::string &title); void onSync() override; diff --git a/src/context/editor/abstract/form/ChildPanel.cpp b/src/editor/abstract/form/ChildPanel.cpp similarity index 87% rename from src/context/editor/abstract/form/ChildPanel.cpp rename to src/editor/abstract/form/ChildPanel.cpp index 85f7c309..498c3971 100644 --- a/src/context/editor/abstract/form/ChildPanel.cpp +++ b/src/editor/abstract/form/ChildPanel.cpp @@ -1,6 +1,7 @@ #include "ChildPanel.h" #include "imgui.h" #include "../../../ApplicationContext.h" +#include "../../service/ThemeService.h" namespace Metal { void ChildPanel::setTitle(const std::string &t) { @@ -9,7 +10,7 @@ namespace Metal { } void ChildPanel::onSync() { - ImGui::PushStyleColor(ImGuiCol_ChildBg, CTX.themeService.palette0); + ImGui::PushStyleColor(ImGuiCol_ChildBg, themeService->palette0); if (!title.empty()) { ImGui::Spacing(); ImGui::Text(title.c_str()); diff --git a/src/context/editor/abstract/form/ChildPanel.h b/src/editor/abstract/form/ChildPanel.h similarity index 100% rename from src/context/editor/abstract/form/ChildPanel.h rename to src/editor/abstract/form/ChildPanel.h diff --git a/src/context/editor/abstract/form/FormPanel.cpp b/src/editor/abstract/form/FormPanel.cpp similarity index 94% rename from src/context/editor/abstract/form/FormPanel.cpp rename to src/editor/abstract/form/FormPanel.cpp index 3a48ef77..3600d088 100644 --- a/src/context/editor/abstract/form/FormPanel.cpp +++ b/src/editor/abstract/form/FormPanel.cpp @@ -1,8 +1,8 @@ #include "FormPanel.h" #include "AccordionPanel.h" #include "ChildPanel.h" -#include "../../../../enum/FieldType.h" -#include "../../../../common/inspection/Inspectable.h" +#include "../../../common/FieldType.h" +#include "../../../common/Inspectable.h" #include "types/IntField.h" #include "types/FloatField.h" #include "types/BooleanField.h" @@ -20,14 +20,14 @@ namespace Metal { std::unordered_map groups{}; const auto rootPanel = new ChildPanel(); rootPanel->setFilter(&searchFilter); - appendChild(rootPanel); + initializePanel(rootPanel); rootPanel->setTitle(std::string(inspection->getIcon()) + " " + inspection->getTitle()); for (const auto &field: inspection->getFields()) { if (!groups.contains(field->group)) { const auto panel = new AccordionPanel(); panel->setFilter(&searchFilter); groups[field->group] = panel; - rootPanel->appendChild(panel); + rootPanel->initializePanel(panel); } AccordionPanel *group = groups[field->group]; group->setTitle(field->group); @@ -71,7 +71,7 @@ namespace Metal { } if (fieldPanel) { fieldPanel->setFilter(&searchFilter); - group->appendChild(fieldPanel); + group->initializePanel(fieldPanel); } } } diff --git a/src/context/editor/abstract/form/FormPanel.h b/src/editor/abstract/form/FormPanel.h similarity index 100% rename from src/context/editor/abstract/form/FormPanel.h rename to src/editor/abstract/form/FormPanel.h diff --git a/src/context/editor/abstract/form/types/BooleanField.cpp b/src/editor/abstract/form/types/BooleanField.cpp similarity index 93% rename from src/context/editor/abstract/form/types/BooleanField.cpp rename to src/editor/abstract/form/types/BooleanField.cpp index 38371db1..11963c65 100644 --- a/src/context/editor/abstract/form/types/BooleanField.cpp +++ b/src/editor/abstract/form/types/BooleanField.cpp @@ -2,7 +2,7 @@ #include #include -#include "../../../../../common/inspection/Inspectable.h" +#include "../../../../common/Inspectable.h" namespace Metal { BooleanField::BooleanField(InspectedField &field) : field(field) { diff --git a/src/context/editor/abstract/form/types/BooleanField.h b/src/editor/abstract/form/types/BooleanField.h similarity index 86% rename from src/context/editor/abstract/form/types/BooleanField.h rename to src/editor/abstract/form/types/BooleanField.h index 4cab6295..b7e683f9 100644 --- a/src/context/editor/abstract/form/types/BooleanField.h +++ b/src/editor/abstract/form/types/BooleanField.h @@ -2,7 +2,7 @@ #define METAL_ENGINE_BOOLEANFIELD_H #include "../AbstractFormFieldPanel.h" -#include "../../../../../common/inspection/InspectedField.h" +#include "../../../../common/InspectedField.h" namespace Metal { class BooleanField final : public AbstractFormFieldPanel { diff --git a/src/context/editor/abstract/form/types/ColorField.cpp b/src/editor/abstract/form/types/ColorField.cpp similarity index 95% rename from src/context/editor/abstract/form/types/ColorField.cpp rename to src/editor/abstract/form/types/ColorField.cpp index 0b8cd911..b63c5967 100644 --- a/src/context/editor/abstract/form/types/ColorField.cpp +++ b/src/editor/abstract/form/types/ColorField.cpp @@ -1,7 +1,7 @@ #include "ColorField.h" #include #include -#include "../../../../../common/inspection/Inspectable.h" +#include "../../../../common/Inspectable.h" namespace Metal { ColorField::ColorField(InspectedField &field) : field(field) { diff --git a/src/context/editor/abstract/form/types/ColorField.h b/src/editor/abstract/form/types/ColorField.h similarity index 88% rename from src/context/editor/abstract/form/types/ColorField.h rename to src/editor/abstract/form/types/ColorField.h index 87d9aaac..5d4af9b2 100644 --- a/src/context/editor/abstract/form/types/ColorField.h +++ b/src/editor/abstract/form/types/ColorField.h @@ -3,7 +3,7 @@ #include #include "../AbstractFormFieldPanel.h" -#include "../../../../../common/inspection/InspectedField.h" +#include "../../../../common/InspectedField.h" namespace Metal { class ColorField final : public AbstractFormFieldPanel { diff --git a/src/context/editor/abstract/form/types/FloatField.cpp b/src/editor/abstract/form/types/FloatField.cpp similarity index 94% rename from src/context/editor/abstract/form/types/FloatField.cpp rename to src/editor/abstract/form/types/FloatField.cpp index b431fae9..c888e6d8 100644 --- a/src/context/editor/abstract/form/types/FloatField.cpp +++ b/src/editor/abstract/form/types/FloatField.cpp @@ -1,7 +1,7 @@ #include "FloatField.h" #include #include -#include "../../../../../common/inspection/Inspectable.h" +#include "../../../../common/Inspectable.h" namespace Metal { void FloatField::onSync() { diff --git a/src/context/editor/abstract/form/types/FloatField.h b/src/editor/abstract/form/types/FloatField.h similarity index 86% rename from src/context/editor/abstract/form/types/FloatField.h rename to src/editor/abstract/form/types/FloatField.h index 41e7c8cd..80443303 100644 --- a/src/context/editor/abstract/form/types/FloatField.h +++ b/src/editor/abstract/form/types/FloatField.h @@ -2,7 +2,7 @@ #define METAL_ENGINE_FLOATFIELD_H #include "../AbstractFormFieldPanel.h" -#include "../../../../../common/inspection/InspectedField.h" +#include "../../../../common/InspectedField.h" namespace Metal { diff --git a/src/context/editor/abstract/form/types/IntField.cpp b/src/editor/abstract/form/types/IntField.cpp similarity index 94% rename from src/context/editor/abstract/form/types/IntField.cpp rename to src/editor/abstract/form/types/IntField.cpp index e4187b21..a8af0903 100644 --- a/src/context/editor/abstract/form/types/IntField.cpp +++ b/src/editor/abstract/form/types/IntField.cpp @@ -1,7 +1,7 @@ #include "IntField.h" #include #include -#include "../../../../../common/inspection/Inspectable.h" +#include "../../../../common/Inspectable.h" namespace Metal { void IntField::onSync() { diff --git a/src/context/editor/abstract/form/types/IntField.h b/src/editor/abstract/form/types/IntField.h similarity index 86% rename from src/context/editor/abstract/form/types/IntField.h rename to src/editor/abstract/form/types/IntField.h index 6c414468..ffae0f01 100644 --- a/src/context/editor/abstract/form/types/IntField.h +++ b/src/editor/abstract/form/types/IntField.h @@ -2,7 +2,7 @@ #define METAL_ENGINE_INTFIELD_H #include "../AbstractFormFieldPanel.h" -#include "../../../../../common/inspection/InspectedField.h" +#include "../../../../common/InspectedField.h" namespace Metal { class IntField final : public AbstractFormFieldPanel { diff --git a/src/context/editor/abstract/form/types/MethodField.cpp b/src/editor/abstract/form/types/MethodField.cpp similarity index 100% rename from src/context/editor/abstract/form/types/MethodField.cpp rename to src/editor/abstract/form/types/MethodField.cpp diff --git a/src/context/editor/abstract/form/types/MethodField.h b/src/editor/abstract/form/types/MethodField.h similarity index 86% rename from src/context/editor/abstract/form/types/MethodField.h rename to src/editor/abstract/form/types/MethodField.h index 704a8b8c..9ef1e055 100644 --- a/src/context/editor/abstract/form/types/MethodField.h +++ b/src/editor/abstract/form/types/MethodField.h @@ -3,7 +3,7 @@ #define METAL_ENGINE_METHODFIELD_H #include "../AbstractFormFieldPanel.h" -#include "../../../../../common/inspection/InspectedMethod.h" +#include "../../../../common/InspectedMethod.h" namespace Metal { diff --git a/src/context/editor/abstract/form/types/QuatField.cpp b/src/editor/abstract/form/types/QuatField.cpp similarity index 93% rename from src/context/editor/abstract/form/types/QuatField.cpp rename to src/editor/abstract/form/types/QuatField.cpp index 24134b71..880f0f82 100644 --- a/src/context/editor/abstract/form/types/QuatField.cpp +++ b/src/editor/abstract/form/types/QuatField.cpp @@ -2,8 +2,8 @@ #include #include #include -#include "../../../../../common/inspection/Inspectable.h" -#include "../../../../../util/UIUtil.h" +#include "../../../../common/Inspectable.h" +#include "../../../util/UIUtil.h" namespace Metal { QuatField::QuatField(InspectedField &field) : field(field) { diff --git a/src/context/editor/abstract/form/types/QuatField.h b/src/editor/abstract/form/types/QuatField.h similarity index 88% rename from src/context/editor/abstract/form/types/QuatField.h rename to src/editor/abstract/form/types/QuatField.h index c2def953..833cf1cd 100644 --- a/src/context/editor/abstract/form/types/QuatField.h +++ b/src/editor/abstract/form/types/QuatField.h @@ -2,7 +2,7 @@ #define QUATFIELD_H #include #include "../AbstractFormFieldPanel.h" -#include "../../../../../common/inspection/InspectedField.h" +#include "../../../../common/InspectedField.h" namespace Metal { class QuatField final : public AbstractFormFieldPanel { diff --git a/src/context/editor/abstract/form/types/ResourceField.cpp b/src/editor/abstract/form/types/ResourceField.cpp similarity index 89% rename from src/context/editor/abstract/form/types/ResourceField.cpp rename to src/editor/abstract/form/types/ResourceField.cpp index 7bc9e88c..884eceb9 100644 --- a/src/context/editor/abstract/form/types/ResourceField.cpp +++ b/src/editor/abstract/form/types/ResourceField.cpp @@ -4,11 +4,12 @@ #include #include "ResourceFilesPanel.h" -#include "../../../../../common/interface/Icons.h" -#include "../../../../../util/UIUtil.h" -#include "../../../../../dto/file/FSEntry.h" -#include "../../../../../context/ApplicationContext.h" -#include "../../../../../common/inspection/Inspectable.h" +#include "../../../../common/Icons.h" +#include "../../../util/UIUtil.h" +#include "../../../dto/FSEntry.h" +#include "../../../../ApplicationContext.h" +#include "../../../../common/Inspectable.h" +#include "../../../service/FilesService.h" namespace Metal { constexpr ImGuiWindowFlags flags = ImGuiWindowFlags_NoDocking | @@ -18,7 +19,7 @@ namespace Metal { } void ResourceField::onInitialize() { - appendChild(new ResourceFilesPanel([this](FSEntry *file) { + initializePanel(new ResourceFilesPanel([this](FSEntry *file) { if (file == nullptr) { open = false; return; @@ -79,7 +80,7 @@ namespace Metal { void ResourceField::onSync() { if (field.field->size() > 0 && (entry == nullptr || entry->getId() != *field.field)) { - entry = CTX.filesService.getResource(*field.field); + entry = filesService->getResource(*field.field); } if (!field.disabled) { renderButton(); diff --git a/src/context/editor/abstract/form/types/ResourceField.h b/src/editor/abstract/form/types/ResourceField.h similarity index 74% rename from src/context/editor/abstract/form/types/ResourceField.h rename to src/editor/abstract/form/types/ResourceField.h index 270b78db..5c970922 100644 --- a/src/context/editor/abstract/form/types/ResourceField.h +++ b/src/editor/abstract/form/types/ResourceField.h @@ -4,18 +4,24 @@ #include #include "../AbstractFormFieldPanel.h" -#include "../../../../../common/inspection/InspectedField.h" +#include "../../../../common/InspectedField.h" #include "imgui.h" namespace Metal { + class FilesService; struct FSEntry; class ResourceField final : public AbstractFormFieldPanel { InspectedField &field; std::unique_ptr entry = nullptr; mutable bool open = false; + FilesService *filesService = nullptr; public: + std::vector getDependencies() override { + return {{"FilesService", &filesService}}; + } + void onInitialize() override; void renderButton(); diff --git a/src/context/editor/abstract/form/types/ResourceFilesPanel.cpp b/src/editor/abstract/form/types/ResourceFilesPanel.cpp similarity index 73% rename from src/context/editor/abstract/form/types/ResourceFilesPanel.cpp rename to src/editor/abstract/form/types/ResourceFilesPanel.cpp index a74cf470..b32d295c 100644 --- a/src/context/editor/abstract/form/types/ResourceFilesPanel.cpp +++ b/src/editor/abstract/form/types/ResourceFilesPanel.cpp @@ -1,8 +1,8 @@ #include "ResourceFilesPanel.h" -#include "../../../../../common/interface/Icons.h" -#include "../../../../../dto/file/FSEntry.h" -#include "../../../../../service/files/FilesService.h" +#include "../../../../common/Icons.h" +#include "../../../dto/FSEntry.h" +#include "../../../service/FilesService.h" namespace Metal { std::function ResourceFilesPanel::onAction() { @@ -18,7 +18,7 @@ namespace Metal { void ResourceFilesPanel::openResource(FSEntry *root) { if (root->type == EntryType::DIRECTORY) { filesContext.setCurrentDirectory(root); - FilesService::GetEntries(root); + filesService->GetEntries(root); filesContext.selected.clear(); } else { callback(root); diff --git a/src/context/editor/abstract/form/types/ResourceFilesPanel.h b/src/editor/abstract/form/types/ResourceFilesPanel.h similarity index 100% rename from src/context/editor/abstract/form/types/ResourceFilesPanel.h rename to src/editor/abstract/form/types/ResourceFilesPanel.h diff --git a/src/context/editor/abstract/form/types/StringField.cpp b/src/editor/abstract/form/types/StringField.cpp similarity index 89% rename from src/context/editor/abstract/form/types/StringField.cpp rename to src/editor/abstract/form/types/StringField.cpp index 082b6bbb..0a24e84a 100644 --- a/src/context/editor/abstract/form/types/StringField.cpp +++ b/src/editor/abstract/form/types/StringField.cpp @@ -1,7 +1,7 @@ #include "StringField.h" #include #include -#include "../../../../../common/inspection/Inspectable.h" +#include "../../../../common/Inspectable.h" namespace Metal { StringField::StringField(InspectedField &field) : field(field) { @@ -9,7 +9,7 @@ namespace Metal { void StringField::onSync() { if (!field.disabled) { - strcpy(buffer, field.field->c_str()); + strcpy_s(buffer, sizeof(buffer), field.field->c_str()); ImGui::Text(field.name.c_str()); if (ImGui::InputText(field.id.c_str(), buffer, sizeof(buffer))) { *field.field = buffer; diff --git a/src/context/editor/abstract/form/types/StringField.h b/src/editor/abstract/form/types/StringField.h similarity index 87% rename from src/context/editor/abstract/form/types/StringField.h rename to src/editor/abstract/form/types/StringField.h index 2b786379..f712b6c5 100644 --- a/src/context/editor/abstract/form/types/StringField.h +++ b/src/editor/abstract/form/types/StringField.h @@ -2,7 +2,7 @@ #define STRINGFIELD_H #include "../AbstractFormFieldPanel.h" -#include "../../../../../common/inspection/InspectedField.h" +#include "../../../../common/InspectedField.h" namespace Metal { diff --git a/src/context/editor/abstract/form/types/Vec2Field.cpp b/src/editor/abstract/form/types/Vec2Field.cpp similarity index 91% rename from src/context/editor/abstract/form/types/Vec2Field.cpp rename to src/editor/abstract/form/types/Vec2Field.cpp index d45d650d..99a88f7f 100644 --- a/src/context/editor/abstract/form/types/Vec2Field.cpp +++ b/src/editor/abstract/form/types/Vec2Field.cpp @@ -1,8 +1,8 @@ #include "Vec2Field.h" #include #include -#include "../../../../../common/inspection/Inspectable.h" -#include "../../../../../util/UIUtil.h" +#include "../../../../common/Inspectable.h" +#include "../../../util/UIUtil.h" namespace Metal { Vec2Field::Vec2Field(InspectedField &field) : field(field) { diff --git a/src/context/editor/abstract/form/types/Vec2Field.h b/src/editor/abstract/form/types/Vec2Field.h similarity index 88% rename from src/context/editor/abstract/form/types/Vec2Field.h rename to src/editor/abstract/form/types/Vec2Field.h index 11a57fc5..fe8d944c 100644 --- a/src/context/editor/abstract/form/types/Vec2Field.h +++ b/src/editor/abstract/form/types/Vec2Field.h @@ -4,7 +4,7 @@ #include #include "../AbstractFormFieldPanel.h" -#include "../../../../../common/inspection/InspectedField.h" +#include "../../../../common/InspectedField.h" namespace Metal { class Vec2Field final : public AbstractFormFieldPanel { diff --git a/src/context/editor/abstract/form/types/Vec3Field.cpp b/src/editor/abstract/form/types/Vec3Field.cpp similarity index 92% rename from src/context/editor/abstract/form/types/Vec3Field.cpp rename to src/editor/abstract/form/types/Vec3Field.cpp index e518b42e..de0ea9b6 100644 --- a/src/context/editor/abstract/form/types/Vec3Field.cpp +++ b/src/editor/abstract/form/types/Vec3Field.cpp @@ -1,8 +1,8 @@ #include "Vec3Field.h" #include #include -#include "../../../../../common/inspection/Inspectable.h" -#include "../../../../../util/UIUtil.h" +#include "../../../../common/Inspectable.h" +#include "../../../util/UIUtil.h" namespace Metal { Vec3Field::Vec3Field(InspectedField &field) : field(field) { diff --git a/src/context/editor/abstract/form/types/Vec3Field.h b/src/editor/abstract/form/types/Vec3Field.h similarity index 88% rename from src/context/editor/abstract/form/types/Vec3Field.h rename to src/editor/abstract/form/types/Vec3Field.h index 0bb06e56..d005b64d 100644 --- a/src/context/editor/abstract/form/types/Vec3Field.h +++ b/src/editor/abstract/form/types/Vec3Field.h @@ -4,7 +4,7 @@ #include #include "../AbstractFormFieldPanel.h" -#include "../../../../../common/inspection/InspectedField.h" +#include "../../../../common/InspectedField.h" namespace Metal { diff --git a/src/context/editor/abstract/form/types/Vec4Field.cpp b/src/editor/abstract/form/types/Vec4Field.cpp similarity index 92% rename from src/context/editor/abstract/form/types/Vec4Field.cpp rename to src/editor/abstract/form/types/Vec4Field.cpp index 07cc3dde..e39247fc 100644 --- a/src/context/editor/abstract/form/types/Vec4Field.cpp +++ b/src/editor/abstract/form/types/Vec4Field.cpp @@ -1,8 +1,8 @@ #include "Vec4Field.h" #include #include -#include "../../../../../common/inspection/Inspectable.h" -#include "../../../../../util/UIUtil.h" +#include "../../../../common/Inspectable.h" +#include "../../../util/UIUtil.h" namespace Metal { Vec4Field::Vec4Field(InspectedField &field) : field(field) { diff --git a/src/context/editor/abstract/form/types/Vec4Field.h b/src/editor/abstract/form/types/Vec4Field.h similarity index 88% rename from src/context/editor/abstract/form/types/Vec4Field.h rename to src/editor/abstract/form/types/Vec4Field.h index 751c0efa..0ce2cae9 100644 --- a/src/context/editor/abstract/form/types/Vec4Field.h +++ b/src/editor/abstract/form/types/Vec4Field.h @@ -3,7 +3,7 @@ #include #include "../AbstractFormFieldPanel.h" -#include "../../../../../common/inspection/InspectedField.h" +#include "../../../../common/InspectedField.h" namespace Metal { class Vec4Field final : public AbstractFormFieldPanel { diff --git a/src/context/editor/dock-spaces/console/ConsolePanel.cpp b/src/editor/dock-spaces/console/ConsolePanel.cpp similarity index 91% rename from src/context/editor/dock-spaces/console/ConsolePanel.cpp rename to src/editor/dock-spaces/console/ConsolePanel.cpp index c358eaea..9f2093af 100644 --- a/src/context/editor/dock-spaces/console/ConsolePanel.cpp +++ b/src/editor/dock-spaces/console/ConsolePanel.cpp @@ -2,7 +2,7 @@ #include "imgui.h" #include "../../../ApplicationContext.h" -#include "../../../../common/interface/Icons.h" +#include "../../../common/Icons.h" namespace Metal { ConsolePanel::ConsolePanel() { @@ -11,17 +11,15 @@ namespace Metal { } shortcuts = { ShortcutDTO("Clear Logs", ImGuiMod_Ctrl | ImGuiKey_L, [this]() { - CTX.logService.clear(); + LogService::clear(); }) }; } void ConsolePanel::onSync() { - LogService& logService = CTX.logService; - // Header if (ImGui::Button("Clear")) { - logService.clear(); + LogService::clear(); } ImGui::SameLine(); bool copyToClipboard = ImGui::Button("Copy"); @@ -48,7 +46,7 @@ namespace Metal { ImGui::LogToClipboard(); } - const auto entries = logService.getEntriesSnapshot(); + const auto entries = LogService::getEntriesSnapshot(); for (const auto& entry : entries) { if (!levelFilter[(int)entry.level]) continue; if (!filter.PassFilter(entry.message.c_str())) continue; diff --git a/src/context/editor/dock-spaces/console/ConsolePanel.h b/src/editor/dock-spaces/console/ConsolePanel.h similarity index 88% rename from src/context/editor/dock-spaces/console/ConsolePanel.h rename to src/editor/dock-spaces/console/ConsolePanel.h index 8417cb14..b6897524 100644 --- a/src/context/editor/dock-spaces/console/ConsolePanel.h +++ b/src/editor/dock-spaces/console/ConsolePanel.h @@ -1,7 +1,7 @@ #ifndef CONSOLEPANEL_H #define CONSOLEPANEL_H #include "../docks/AbstractDockPanel.h" -#include "../../../../service/log/LogService.h" +#include "../../../common/LoggerUtil.h" #include "imgui.h" namespace Metal { diff --git a/src/context/editor/dock-spaces/docks/AbstractDockPanel.h b/src/editor/dock-spaces/docks/AbstractDockPanel.h similarity index 93% rename from src/context/editor/dock-spaces/docks/AbstractDockPanel.h rename to src/editor/dock-spaces/docks/AbstractDockPanel.h index 3f144a8d..997ddd68 100644 --- a/src/context/editor/dock-spaces/docks/AbstractDockPanel.h +++ b/src/editor/dock-spaces/docks/AbstractDockPanel.h @@ -5,7 +5,7 @@ #include #include "../../abstract/AbstractPanel.h" -#include "../../../../dto/ShortcutDTO.h" +#include "../../dto/ShortcutDTO.h" struct ImVec2; diff --git a/src/context/editor/dock-spaces/docks/DockSpacePanel.cpp b/src/editor/dock-spaces/docks/DockSpacePanel.cpp similarity index 88% rename from src/context/editor/dock-spaces/docks/DockSpacePanel.cpp rename to src/editor/dock-spaces/docks/DockSpacePanel.cpp index e07fe1ac..60f9c479 100644 --- a/src/context/editor/dock-spaces/docks/DockSpacePanel.cpp +++ b/src/editor/dock-spaces/docks/DockSpacePanel.cpp @@ -4,11 +4,13 @@ #include #include "AbstractDockPanel.h" -#include "../../../../context/ApplicationContext.h" -#include "../../../../common/interface/Icons.h" -#include "../../../../repository/dock/DockDTO.h" -#include "../../../../util/UIUtil.h" -#include "../../../../service/log/LogService.h" +#include "../../../ApplicationContext.h" +#include "../../../common/Icons.h" +#include "../../dto/DockDTO.h" +#include "../../util/UIUtil.h" +#include "../../../common/LoggerUtil.h" +#include "../../repository/EditorRepository.h" +#include "../../service/ThemeService.h" namespace Metal { const ImVec2 DockSpacePanel::DEFAULT{-1.f, -1.f}; @@ -34,7 +36,7 @@ namespace Metal { newView->size = &size; newView->dock = selectedSpace; newView->position = &position; - appendChild(newView); + initializePanel(newView); views.emplace(selectedSpace->index, newView); view = newView; } else { @@ -52,13 +54,13 @@ namespace Metal { if (view != nullptr) { const bool isHovered = ImGui::IsWindowHovered(ImGuiHoveredFlags_RootAndChildWindows); if (isHovered) { - CTX.editorRepository.focusedShortcuts = view->getShortcuts(); - CTX.editorRepository.focusedWindowName = view->dock->name; + editorRepository->focusedShortcuts = view->getShortcuts(); + editorRepository->focusedWindowName = view->dock->name; } view->isWindowFocused = isHovered; if (view->isWindowFocused) { - for (const auto &shortcut: CTX.editorRepository.focusedShortcuts) { + for (const auto &shortcut: editorRepository->focusedShortcuts) { if (ImGui::IsKeyChordPressed(shortcut.keyChord)) { LOG_INFO("Action called: " + shortcut.name); shortcut.callback(); @@ -116,7 +118,7 @@ namespace Metal { ImGui::PushStyleVar(ImGuiStyleVar_FramePadding, headerPadding); const bool isFocused = ImGui::IsWindowFocused(ImGuiFocusedFlags_RootAndChildWindows); ImGui::PushStyleColor(ImGuiCol_TabActive, - isFocused ? CTX.editorRepository.accent : CTX.themeService.palette0); + isFocused ? editorRepository->accent : themeService->palette0); if (ImGui::BeginTabBar((id + "dockTabs").c_str(), ImGuiTabBarFlags_AutoSelectNewTabs)) { for (auto *space: dock->dockSpaces) { @@ -143,11 +145,7 @@ namespace Metal { if (ImGui::BeginPopup((id + "NewTabDropdown").c_str())) { ImGui::Text("New Tab"); ImGui::Separator(); - for (int i = 0; i <= 4; i++) { - DockSpace *option = DockSpace::GetOption(i); - if (option == nullptr) { - continue; - } + for (auto *option: DockSpace::OPTIONS_LIST) { const bool exists = hasDockSpace(option->index); const std::string label = option->icon + " " + option->name; if (ImGui::MenuItem(label.c_str(), nullptr, false, !exists)) { diff --git a/src/context/editor/dock-spaces/docks/DockSpacePanel.h b/src/editor/dock-spaces/docks/DockSpacePanel.h similarity index 83% rename from src/context/editor/dock-spaces/docks/DockSpacePanel.h rename to src/editor/dock-spaces/docks/DockSpacePanel.h index 56658704..911e94bc 100644 --- a/src/context/editor/dock-spaces/docks/DockSpacePanel.h +++ b/src/editor/dock-spaces/docks/DockSpacePanel.h @@ -11,6 +11,8 @@ namespace Metal { struct DockDTO; struct DockSpace; class AbstractDockPanel; + struct EditorRepository; + class ThemeService; class DockSpacePanel final : public AbstractPanel { ImVec2 padding{DEFAULT.x, DEFAULT.y}; @@ -26,11 +28,21 @@ namespace Metal { std::unordered_map views{}; ImVec2 headerPadding{0, 3}; + EditorRepository *editorRepository = nullptr; + ThemeService *themeService = nullptr; + DockSpace *getSelectedDockSpace() const; bool hasDockSpace(int index) const; public: + std::vector getDependencies() override { + return { + {"EditorRepository", &editorRepository}, + {"ThemeService", &themeService} + }; + } + static constexpr int FLAGS = ImGuiWindowFlags_NoCollapse | ImGuiWindowFlags_NoMove | ImGuiWindowFlags_MenuBar; static const ImVec2 DEFAULT; static const ImVec2 MAX_SIZE; diff --git a/src/context/editor/dock-spaces/files/FilePreviewPanel.cpp b/src/editor/dock-spaces/files/FilePreviewPanel.cpp similarity index 88% rename from src/context/editor/dock-spaces/files/FilePreviewPanel.cpp rename to src/editor/dock-spaces/files/FilePreviewPanel.cpp index 7c7c050b..f94c1c71 100644 --- a/src/context/editor/dock-spaces/files/FilePreviewPanel.cpp +++ b/src/editor/dock-spaces/files/FilePreviewPanel.cpp @@ -1,9 +1,11 @@ #include "FilePreviewPanel.h" #include -#include "../../../../util/UIUtil.h" -#include "../../../../dto/file/FSEntry.h" -#include "../../../../context/ApplicationContext.h" -#include "../../../../service/texture/TextureInstance.h" +#include "../../util/UIUtil.h" +#include "../../dto/FSEntry.h" +#include "../../../ApplicationContext.h" +#include "../../../engine/resource/TextureInstance.h" +#include "../../../engine/service/TextureService.h" +#include "../../../core/gui/GuiContext.h" namespace Metal { FilePreviewPanel::FilePreviewPanel(FilesContext &filesContext) : filesContext(filesContext) { @@ -21,7 +23,7 @@ namespace Metal { ImGui::Separator(); if (selected->type == EntryType::TEXTURE) { - auto *texture = CTX.textureService.stream(selected->getId()); + auto *texture = textureService->stream(selected->getId()); if (texture != nullptr) { float availWidth = ImGui::GetContentRegionAvail().x; float availHeight = ImGui::GetContentRegionAvail().y * 0.6f; // reserve space for table @@ -41,7 +43,7 @@ namespace Metal { float offsetX = (availWidth - renderWidth) * 0.5f; if (offsetX > 0) ImGui::SetCursorPosX(ImGui::GetCursorPosX() + offsetX); - CTX.guiContext.renderImage(texture, renderWidth, renderHeight); + guiContext->renderImage(texture, renderWidth, renderHeight); ImGui::Separator(); } } diff --git a/src/context/editor/dock-spaces/files/FilePreviewPanel.h b/src/editor/dock-spaces/files/FilePreviewPanel.h similarity index 52% rename from src/context/editor/dock-spaces/files/FilePreviewPanel.h rename to src/editor/dock-spaces/files/FilePreviewPanel.h index 689ac058..7486746d 100644 --- a/src/context/editor/dock-spaces/files/FilePreviewPanel.h +++ b/src/editor/dock-spaces/files/FilePreviewPanel.h @@ -5,10 +5,23 @@ #include "FilesContext.h" namespace Metal { + class TextureService; + class GuiContext; + class FilePreviewPanel final : public AbstractPanel { FilesContext &filesContext; + TextureService *textureService = nullptr; + GuiContext *guiContext = nullptr; + public: + std::vector getDependencies() override { + return { + {"TextureService", &textureService}, + {"GuiContext", &guiContext} + }; + } + explicit FilePreviewPanel(FilesContext &filesContext); void onSync() override; diff --git a/src/context/editor/dock-spaces/files/FilesContext.cpp b/src/editor/dock-spaces/files/FilesContext.cpp similarity index 91% rename from src/context/editor/dock-spaces/files/FilesContext.cpp rename to src/editor/dock-spaces/files/FilesContext.cpp index bd74434c..a85c2ef5 100644 --- a/src/context/editor/dock-spaces/files/FilesContext.cpp +++ b/src/editor/dock-spaces/files/FilesContext.cpp @@ -1,6 +1,6 @@ #include "FilesContext.h" -#include "../../../../dto/file/FSEntry.h" +#include "../../dto/FSEntry.h" #include namespace Metal { diff --git a/src/context/editor/dock-spaces/files/FilesContext.h b/src/editor/dock-spaces/files/FilesContext.h similarity index 94% rename from src/context/editor/dock-spaces/files/FilesContext.h rename to src/editor/dock-spaces/files/FilesContext.h index d50da76a..f7d32d0e 100644 --- a/src/context/editor/dock-spaces/files/FilesContext.h +++ b/src/editor/dock-spaces/files/FilesContext.h @@ -3,7 +3,7 @@ #include #include -#include "../../../../enum/EntryType.h" +#include "../../enum/EntryType.h" namespace Metal { diff --git a/src/context/editor/dock-spaces/files/FilesHeaderPanel.cpp b/src/editor/dock-spaces/files/FilesHeaderPanel.cpp similarity index 56% rename from src/context/editor/dock-spaces/files/FilesHeaderPanel.cpp rename to src/editor/dock-spaces/files/FilesHeaderPanel.cpp index 3924fb73..d687da19 100644 --- a/src/context/editor/dock-spaces/files/FilesHeaderPanel.cpp +++ b/src/editor/dock-spaces/files/FilesHeaderPanel.cpp @@ -1,18 +1,18 @@ #include "FilesHeaderPanel.h" -#include "../../../../enum/EntryType.h" -#include "../../../../dto/file/FSEntry.h" -#include "../../../../common/interface/Icons.h" -#include "../../../../util/FilesUtil.h" -#include "../../../../context/ApplicationContext.h" -#include "../../../../util/UIUtil.h" +#include "../../enum/EntryType.h" +#include "../../dto/FSEntry.h" +#include "../../../common/Icons.h" +#include "../../../ApplicationContext.h" +#include "../../service/FilesService.h" +#include "../../util/UIUtil.h" namespace Metal { void FilesHeaderPanel::onSync() { if (UIUtil::ButtonSimple(Icons::create_new_folder + id, UIUtil::ONLY_ICON_BUTTON_SIZE, UIUtil::ONLY_ICON_BUTTON_SIZE)) { - FilesService::CreateDirectory(filesContext.currentDirectory); - FilesService::GetEntries(filesContext.currentDirectory); + filesService->CreateDirectory(filesContext.currentDirectory); + filesService->GetEntries(filesContext.currentDirectory); } UIUtil::RenderTooltip("Create folder"); ImGui::SameLine(); @@ -23,12 +23,11 @@ namespace Metal { filesContext.setCurrentDirectory(filesContext.currentDirectory->parent); } UIUtil::RenderTooltip("Go to parent folder"); - } ImGui::SameLine(); if (UIUtil::ButtonSimple(Icons::refresh, UIUtil::ONLY_ICON_BUTTON_SIZE, UIUtil::ONLY_ICON_BUTTON_SIZE)) { - FilesService::GetEntries(filesContext.currentDirectory); + filesService->GetEntries(filesContext.currentDirectory); } UIUtil::RenderTooltip("Refresh"); @@ -38,9 +37,18 @@ namespace Metal { UIUtil::DynamicSpacing(200); ImGui::SetNextItemWidth(100); - editorMode = IndexOfValue(filesContext.filterType); - if (ImGui::Combo((id + "filter").c_str(), &editorMode, EntryType::Names)) { - filesContext.filterType = EntryType::ValueOfIndex(editorMode); + const auto ¤tDTO = EntryType::GetDTO(filesContext.filterType); + std::string filterLabel = currentDTO.icon + " " + currentDTO.name; + if (ImGui::Button((filterLabel + id + "filter").c_str(), ImVec2(100, 0))) { + ImGui::OpenPopup((id + "FilterPopup").c_str()); + } + if (ImGui::BeginPopup((id + "FilterPopup").c_str())) { + for (const auto &dto: EntryType::ENTRIES) { + if (ImGui::MenuItem((dto.icon + " " + dto.name).c_str())) { + filesContext.filterType = dto.type; + } + } + ImGui::EndPopup(); } ImGui::SameLine(); if (UIUtil::ButtonSimple(actionLabel + id, 100, diff --git a/src/context/editor/dock-spaces/files/FilesHeaderPanel.h b/src/editor/dock-spaces/files/FilesHeaderPanel.h similarity index 68% rename from src/context/editor/dock-spaces/files/FilesHeaderPanel.h rename to src/editor/dock-spaces/files/FilesHeaderPanel.h index c2df144c..2dd46591 100644 --- a/src/context/editor/dock-spaces/files/FilesHeaderPanel.h +++ b/src/editor/dock-spaces/files/FilesHeaderPanel.h @@ -6,14 +6,21 @@ #include "../../abstract/AbstractPanel.h" namespace Metal { + class FilesService; + class FilesHeaderPanel final : public AbstractPanel { FilesContext &filesContext; std::string actionLabel; std::function action; - int editorMode = 0; + FilesService *filesService = nullptr; + public: + std::vector getDependencies() override { + return {{"FilesService", &filesService}}; + } + explicit FilesHeaderPanel(FilesContext &files_context, const std::string &actionLabel, - std::function action) + std::function action) : filesContext(files_context), actionLabel(actionLabel), action(std::move(action)) { } diff --git a/src/context/editor/dock-spaces/files/FilesListPanel.cpp b/src/editor/dock-spaces/files/FilesListPanel.cpp similarity index 95% rename from src/context/editor/dock-spaces/files/FilesListPanel.cpp rename to src/editor/dock-spaces/files/FilesListPanel.cpp index 54f75cd0..068b328f 100644 --- a/src/context/editor/dock-spaces/files/FilesListPanel.cpp +++ b/src/editor/dock-spaces/files/FilesListPanel.cpp @@ -2,10 +2,10 @@ #include "FilesPanel.h" #include "FilesContext.h" -#include "../../../../util/UIUtil.h" -#include "../../../../context/ApplicationContext.h" -#include "../../../../dto/file//FSEntry.h" -#include "../../../../service/files/FilesService.h" +#include "../../util/UIUtil.h" +#include "../../../ApplicationContext.h" +#include "../../dto/FSEntry.h" +#include "../../service/FilesService.h" #include namespace Metal { @@ -89,7 +89,7 @@ namespace Metal { if (!ImGui::IsMouseDown(ImGuiMouseButton_Left) && onDrag != nullptr && fileEntry->type == EntryType::DIRECTORY) { - CTX.filesService.Move(onDrag, fileEntry); + filesService->Move(onDrag, fileEntry); onDrag = nullptr; } } @@ -211,7 +211,7 @@ namespace Metal { if (isDirectory && open) { if (!loadedDirectoryPaths.contains(entry->absolutePath)) { - FilesService::GetEntries(entry); + filesService->GetEntries(entry); loadedDirectoryPaths.insert(entry->absolutePath); } // After loading, children may change; keep original iteration order to avoid infinite recursion here. @@ -277,11 +277,11 @@ namespace Metal { } if (ImGui::MenuItem("Paste")) { filesContext.toCut.clear(); - FilesService::GetEntries(filesContext.currentDirectory); + filesService->GetEntries(filesContext.currentDirectory); } if (ImGui::MenuItem("Delete")) { - CTX.filesService.deleteFiles(filesContext.selected); - FilesService::GetEntries(filesContext.currentDirectory); + filesService->deleteFiles(filesContext.selected); + filesService->GetEntries(filesContext.currentDirectory); } ImGui::Separator(); if (ImGui::MenuItem("Select all")) { diff --git a/src/context/editor/dock-spaces/files/FilesListPanel.h b/src/editor/dock-spaces/files/FilesListPanel.h similarity index 74% rename from src/context/editor/dock-spaces/files/FilesListPanel.h rename to src/editor/dock-spaces/files/FilesListPanel.h index 9eda2ba8..b87f2121 100644 --- a/src/context/editor/dock-spaces/files/FilesListPanel.h +++ b/src/editor/dock-spaces/files/FilesListPanel.h @@ -10,6 +10,7 @@ namespace Metal { struct FSEntry; + class FilesService; class FilesListPanel final : public AbstractPanel { FilesContext &filesContext; @@ -27,6 +28,8 @@ namespace Metal { std::function onDoubleClick; + FilesService *filesService = nullptr; + void ensureCache(); void applySort(); @@ -45,9 +48,15 @@ namespace Metal { void renderTreeItem(FSEntry *entry); public: - explicit FilesListPanel(FilesContext &ctx, std::function onDoubleClick, + std::vector getDependencies() override { + return { + {"FilesService", &filesService} + }; + } + + explicit FilesListPanel(FilesContext &filesContext, std::function onDoubleClick, EntryType::EntryType typeFilter) - : filesContext(ctx), typeFilter(typeFilter), onDoubleClick(std::move(onDoubleClick)) { + : filesContext(filesContext), typeFilter(typeFilter), onDoubleClick(std::move(onDoubleClick)) { } void onSync() override; diff --git a/src/context/editor/dock-spaces/files/FilesPanel.cpp b/src/editor/dock-spaces/files/FilesPanel.cpp similarity index 66% rename from src/context/editor/dock-spaces/files/FilesPanel.cpp rename to src/editor/dock-spaces/files/FilesPanel.cpp index 32f0e537..2823793a 100644 --- a/src/context/editor/dock-spaces/files/FilesPanel.cpp +++ b/src/editor/dock-spaces/files/FilesPanel.cpp @@ -1,22 +1,23 @@ #include "FilesPanel.h" - - #include "FilesHeaderPanel.h" #include "FilesListPanel.h" -#include "../../../../common/interface/Icons.h" -#include "../../../../context/ApplicationContext.h" -#include "../../../../service/mesh/SceneData.h" -#include "../../../../util/UIUtil.h" -#include "../../../../dto/file/FSEntry.h" -#include "../../../../dto/file/SceneImportSettingsDTO.h" +#include "../../../common/Icons.h" +#include "../../util/UIUtil.h" +#include "../../dto/FSEntry.h" +#include "../../dto/SceneImportSettingsDTO.h" #include "FilesContext.h" -#include "../../../../util/FileDialogUtil.h" - +#include "../../../common/FileDialogUtil.h" #include "FilePreviewPanel.h" -#include "../../abstract/form/FormPanel.h" #include #include -#include "../../../../util/FilesUtil.h" +#include "../../../common/FilesUtil.h" +#include "../../service/FileImporterService.h" +#include "../../repository/EditorRepository.h" +#include "../../service/SceneImporterService.h" +#include "../../service/FilesService.h" +#include "../../service/NotificationService.h" +#include "../../../engine/repository/WorldRepository.h" +#include "../../../engine/service/VoxelService.h" namespace Metal { std::string FilesPanel::getActionLabel() { @@ -28,37 +29,37 @@ namespace Metal { auto files = FileDialogUtil::PickFiles({ { "Files", - CTX.fileImporterService.collectCompatibleFiles().c_str(), + fileImporterService->collectCompatibleFiles().c_str(), } }); if (!files.empty()) { - CTX.editorRepository.pendingImports = files; - CTX.editorRepository.importSettingsMap.clear(); - for (const auto& file : CTX.editorRepository.pendingImports) { - if (CTX.sceneImporterService.isCompatible(file)) { - CTX.editorRepository.importSettingsMap.emplace(file, std::make_shared()); + editorRepository->pendingImports = files; + editorRepository->importSettingsMap.clear(); + for (const auto& file : editorRepository->pendingImports) { + if (sceneImporterService->isCompatible(file)) { + editorRepository->importSettingsMap.emplace(file, std::make_shared()); } else { - CTX.editorRepository.importSettingsMap.emplace(file, std::make_shared()); + editorRepository->importSettingsMap.emplace(file, std::make_shared()); } } - CTX.editorRepository.selectedFileForSettings = CTX.editorRepository.pendingImports[0]; - CTX.editorRepository.targetImportDirectory = filesContext.currentDirectory; + editorRepository->selectedFileForSettings = editorRepository->pendingImports[0]; + editorRepository->targetImportDirectory = filesContext.currentDirectory; } }; } void FilesPanel::onInitialize() { - filesContext.setCurrentDirectory(CTX.filesService.getRoot()); - appendChild(filesHeader = new FilesHeaderPanel(filesContext, getActionLabel(), onAction())); + filesContext.setCurrentDirectory(filesService->getRoot()); + initializePanel(filesHeader = new FilesHeaderPanel(filesContext, getActionLabel(), onAction())); filesListPanel = new FilesListPanel( filesContext, [ this](FSEntry *entry) { openResource(entry); }, getTypeFilter()); - appendChild(filesListPanel); + initializePanel(filesListPanel); previewPanel = new FilePreviewPanel(filesContext); - appendChild(previewPanel); + initializePanel(previewPanel); shortcuts = { ShortcutDTO("Cut", ImGuiMod_Ctrl | ImGuiKey_X, [this]() { @@ -124,23 +125,23 @@ namespace Metal { void FilesPanel::openResource(FSEntry *root) { switch (root->type) { case EntryType::SCENE: { - CTX.notificationService.pushMessage("Loading scene", NotificationSeverities::SUCCESS); - CTX.worldRepository.loadScene(root->getId()); + notificationService->pushMessage("Loading scene", NotificationSeverities::SUCCESS); + worldRepository->loadScene(root->getId()); break; } case EntryType::VOLUME: { - CTX.notificationService.pushMessage("Loading volume", NotificationSeverities::SUCCESS); - CTX.voxelService.create(root->getId()); + notificationService->pushMessage("Loading volume", NotificationSeverities::SUCCESS); + voxelService->create(root->getId()); break; } case EntryType::DIRECTORY: { filesContext.setCurrentDirectory(root); - FilesService::GetEntries(root); + filesService->GetEntries(root); filesContext.selected.clear(); break; } default: - CTX.notificationService.pushMessage("Unsupported resource type", NotificationSeverities::ERROR); + notificationService->pushMessage("Unsupported resource type", NotificationSeverities::ERROR); break; } } @@ -150,7 +151,7 @@ namespace Metal { // } filesContext.toCut.clear(); - FilesService::GetEntries(filesContext.currentDirectory); + filesService->GetEntries(filesContext.currentDirectory); } void FilesPanel::openSelected() { @@ -162,7 +163,7 @@ namespace Metal { void FilesPanel::cutSelected() { filesContext.toCut.clear(); filesContext.toCut = filesContext.selected; - FilesService::GetEntries(filesContext.currentDirectory); + filesService->GetEntries(filesContext.currentDirectory); } void FilesPanel::selectAll() { @@ -174,7 +175,7 @@ namespace Metal { } void FilesPanel::deleteSelected() const { - CTX.filesService.deleteFiles(filesContext.selected); - FilesService::GetEntries(filesContext.currentDirectory); + filesService->deleteFiles(filesContext.selected); + filesService->GetEntries(filesContext.currentDirectory); } } diff --git a/src/context/editor/dock-spaces/files/FilesPanel.h b/src/editor/dock-spaces/files/FilesPanel.h similarity index 52% rename from src/context/editor/dock-spaces/files/FilesPanel.h rename to src/editor/dock-spaces/files/FilesPanel.h index 6643805e..cec10119 100644 --- a/src/context/editor/dock-spaces/files/FilesPanel.h +++ b/src/editor/dock-spaces/files/FilesPanel.h @@ -6,12 +6,19 @@ #include "FilesContext.h" #include "../docks/AbstractDockPanel.h" -#include "../../../../dto/file/ImportSettingsDTO.h" +#include "../../dto/ImportSettingsDTO.h" namespace Metal { struct FSEntry; class FilePreviewPanel; class FormPanel; + class FileImporterService; + struct EditorRepository; + class SceneImporterService; + class FilesService; + class NotificationService; + struct WorldRepository; + class VoxelService; class FilesPanel : public AbstractDockPanel { protected: @@ -21,7 +28,27 @@ namespace Metal { AbstractPanel *filesListPanel = nullptr; float previewWidth = 200.0f; + FileImporterService *fileImporterService = nullptr; + EditorRepository *editorRepository = nullptr; + SceneImporterService *sceneImporterService = nullptr; + FilesService *filesService = nullptr; + NotificationService *notificationService = nullptr; + WorldRepository *worldRepository = nullptr; + VoxelService *voxelService = nullptr; + public: + std::vector getDependencies() override { + return { + {"FileImporterService", &fileImporterService}, + {"EditorRepository", &editorRepository}, + {"SceneImporterService", &sceneImporterService}, + {"FilesService", &filesService}, + {"NotificationService", ¬ificationService}, + {"WorldRepository", &worldRepository}, + {"VoxelService", &voxelService} + }; + } + virtual bool renderPreview() { return true; } diff --git a/src/editor/dock-spaces/footer/EditorFooterPanel.cpp b/src/editor/dock-spaces/footer/EditorFooterPanel.cpp new file mode 100644 index 00000000..0a427db7 --- /dev/null +++ b/src/editor/dock-spaces/footer/EditorFooterPanel.cpp @@ -0,0 +1,67 @@ +#include "EditorFooterPanel.h" +#include "../header/AsyncTaskPanel.h" +#include "../../util/UIUtil.h" +#include "../../../ApplicationContext.h" +#include "../../repository/EditorRepository.h" + +namespace Metal { + void EditorFooterPanel::onSync() { + ImGui::Separator(); + asyncTaskPanel->onSync(); + ImGui::SameLine(); + renderShortcuts(); + framerate(); + } + + void EditorFooterPanel::onInitialize() { + initializePanel(asyncTaskPanel = new AsyncTaskPanel(), false); + } + + void EditorFooterPanel::framerate() { + const int framerate = static_cast(round(ImGui::GetIO().Framerate)); + if (framerate > 0) { + ImGui::SameLine(ImGui::GetWindowWidth() - 100); + ImGui::Text("%i ms | %i fps", 1000 / framerate, framerate); + } + } + + void EditorFooterPanel::renderShortcuts() { + auto &shortcuts = editorRepository->focusedShortcuts; + if (shortcuts.empty()) return; + + ImGui::SetCursorPosY(ImGui::GetCursorPosY() + 2); // Some padding + + std::string label; + for (size_t i = 0; i < std::min(shortcuts.size(), size_t(3)); ++i) { + if (i > 0) label += " | "; + label += UIUtil::GetKeyChordName(shortcuts[i].keyChord) + " " + shortcuts[i].name; + } + + if (ImGui::Button(label.c_str())) { + ImGui::OpenPopup("AllShortcutsPopupFooter"); + } + + if (ImGui::BeginPopup("AllShortcutsPopupFooter")) { + if (ImGui::BeginTable("ShortcutsTableFooter", 2, + ImGuiTableFlags_Borders | ImGuiTableFlags_RowBg | + ImGuiTableFlags_SizingStretchProp)) { + ImGui::TableSetupColumn("Key"); + ImGui::TableSetupColumn("Action"); + ImGui::TableHeadersRow(); + + for (const auto &shortcut: shortcuts) { + ImGui::TableNextRow(); + ImGui::TableNextColumn(); + ImGui::TextUnformatted(UIUtil::GetKeyChordName(shortcut.keyChord).c_str()); + ImGui::TableNextColumn(); + if (ImGui::Selectable(shortcut.name.c_str(), false, ImGuiSelectableFlags_SpanAllColumns)) { + shortcut.callback(); + ImGui::CloseCurrentPopup(); + } + } + ImGui::EndTable(); + } + ImGui::EndPopup(); + } + } +} diff --git a/src/editor/dock-spaces/footer/EditorFooterPanel.h b/src/editor/dock-spaces/footer/EditorFooterPanel.h new file mode 100644 index 00000000..9f4ec717 --- /dev/null +++ b/src/editor/dock-spaces/footer/EditorFooterPanel.h @@ -0,0 +1,31 @@ +#ifndef METAL_ENGINE_EDITORFOOTERPANEL_H +#define METAL_ENGINE_EDITORFOOTERPANEL_H + +#include "../../abstract/AbstractPanel.h" + +namespace Metal { + struct EditorRepository; + + class AsyncTaskPanel; + + class EditorFooterPanel final : public AbstractPanel { + EditorRepository *editorRepository = nullptr; + AsyncTaskPanel *asyncTaskPanel = nullptr; + + void renderShortcuts(); + static void framerate(); + + public: + std::vector getDependencies() override { + return { + {"EditorRepository", &editorRepository} + }; + } + + void onInitialize() override; + + void onSync() override; + }; +} + +#endif diff --git a/src/context/editor/dock-spaces/header/AsyncTaskPanel.cpp b/src/editor/dock-spaces/header/AsyncTaskPanel.cpp similarity index 50% rename from src/context/editor/dock-spaces/header/AsyncTaskPanel.cpp rename to src/editor/dock-spaces/header/AsyncTaskPanel.cpp index 80db3d2c..108824e7 100644 --- a/src/context/editor/dock-spaces/header/AsyncTaskPanel.cpp +++ b/src/editor/dock-spaces/header/AsyncTaskPanel.cpp @@ -1,42 +1,35 @@ #include "AsyncTaskPanel.h" -#include "../../../../context/ApplicationContext.h" -#include "../../../../util/UIUtil.h" +#include "../../../ApplicationContext.h" +#include "../../util/UIUtil.h" #include +#include "../../service/AsyncTaskService.h" +#include "../../dto/AsyncTask.h" namespace Metal { void AsyncTaskPanel::onSync() { - auto tasks = CTX.asyncTaskService.getActiveTasks(); - if (tasks.empty()) { - UIUtil::DynamicSpacing(90); - return; - } - UIUtil::DynamicSpacing(250); - ImGui::SameLine(); - - float time = (float)ImGui::GetTime(); - float t = 0.5f + 0.5f * std::sin(time * 3.0f); // 0.0 to 1.0 - - ImVec4 color = ImVec4( - 0.0f + t * 0.4f, - 0.2f + t * 0.5f, - 0.6f + t * 0.4f, - 1.0f - ); + auto tasks = asyncTaskService->getActiveTasks(); + bool hasTasks = !tasks.empty(); + ImGui::BeginGroup(); ImVec2 pos = ImGui::GetCursorScreenPos(); - float width = 150.0f; - float height = 10.0f; + float size = (float)UIUtil::ONLY_ICON_BUTTON_SIZE; - pos.y += (UIUtil::ONLY_ICON_BUTTON_SIZE - height) / 2.0f; + if (ImGui::InvisibleButton("##AsyncTaskIcon", ImVec2(size, size))) { + ImGui::OpenPopup("AsyncTasksPopup"); + } - ImGui::GetWindowDrawList()->AddRectFilled(pos, ImVec2(pos.x + width, pos.y + height), ImGui::ColorConvertFloat4ToU32(color), 5.0f); + ImU32 iconColor = ImGui::GetColorU32(ImGuiCol_Text); + ImGui::GetWindowDrawList()->AddText(ImGui::GetFont(), ImGui::GetFontSize(), + ImVec2(pos.x + (size - ImGui::CalcTextSize(Icons::sync.c_str()).x) / 2, + pos.y + (size - ImGui::GetFontSize()) / 2), + iconColor, Icons::sync.c_str()); - ImGui::SetCursorScreenPos(pos); - if (ImGui::InvisibleButton("##AsyncTaskLine", ImVec2(width, height))) { - ImGui::OpenPopup("AsyncTasksPopup"); + if (hasTasks) { + float circleRadius = 3.0f; + ImVec2 circlePos = ImVec2(pos.x + size / 2.0f, pos.y + size - circleRadius - 2.0f); + ImGui::GetWindowDrawList()->AddCircleFilled(circlePos, circleRadius, IM_COL32(0, 200, 255, 255)); } - ImGui::SameLine(); - ImGui::Dummy(ImVec2(0, UIUtil::ONLY_ICON_BUTTON_SIZE)); + ImGui::EndGroup(); UIUtil::RenderTooltip(Icons::sync + " " + std::to_string(tasks.size()) + " processes running..."); @@ -50,13 +43,14 @@ namespace Metal { ImGui::Text("%s", task->name.c_str()); ImVec2 p = ImGui::GetCursorScreenPos(); + float height = 10.0f; float w = ImGui::GetContentRegionAvail().x - UIUtil::ONLY_ICON_BUTTON_SIZE - ImGui::GetStyle().ItemSpacing.x; - ImGui::GetWindowDrawList()->AddRectFilled(p, ImVec2(p.x + w, p.y + height), ImGui::ColorConvertFloat4ToU32(color), 5.0f); + ImGui::GetWindowDrawList()->AddRectFilled(p, ImVec2(p.x + w, p.y + height), IM_COL32(50, 150, 255, 255), 5.0f); ImGui::Dummy(ImVec2(w, height)); ImGui::SameLine(); if (ImGui::Button((Icons::close + "##" + task->id).c_str(), ImVec2(UIUtil::ONLY_ICON_BUTTON_SIZE, UIUtil::ONLY_ICON_BUTTON_SIZE))) { - CTX.asyncTaskService.endTask(task->id, true); + asyncTaskService->endTask(task->id, true); } ImGui::EndGroup(); } diff --git a/src/context/editor/dock-spaces/header/AsyncTaskPanel.h b/src/editor/dock-spaces/header/AsyncTaskPanel.h similarity index 50% rename from src/context/editor/dock-spaces/header/AsyncTaskPanel.h rename to src/editor/dock-spaces/header/AsyncTaskPanel.h index c1e09daf..d834c713 100644 --- a/src/context/editor/dock-spaces/header/AsyncTaskPanel.h +++ b/src/editor/dock-spaces/header/AsyncTaskPanel.h @@ -4,8 +4,18 @@ #include "../../abstract/AbstractPanel.h" namespace Metal { + class AsyncTaskService; + class AsyncTaskPanel final : public AbstractPanel { + AsyncTaskService *asyncTaskService = nullptr; + public: + std::vector getDependencies() override { + return { + {"AsyncTaskService", &asyncTaskService} + }; + } + void onSync() override; }; } diff --git a/src/editor/dock-spaces/header/EditorHeaderPanel.cpp b/src/editor/dock-spaces/header/EditorHeaderPanel.cpp new file mode 100644 index 00000000..ae5ee5f4 --- /dev/null +++ b/src/editor/dock-spaces/header/EditorHeaderPanel.cpp @@ -0,0 +1,80 @@ +#include "EditorHeaderPanel.h" +#include "../../util/UIUtil.h" +#include "../../../ApplicationContext.h" +#include "../../../core/DirectoryService.h" +#include "../../../core/glfw/GLFWContext.h" +#include "../../../engine/EngineContext.h" + +namespace Metal { + void EditorHeaderPanel::onSync() { + renderFileTab(); + ImGui::Dummy(ImVec2(0, UIUtil::ONLY_ICON_BUTTON_SIZE)); + ImGui::Dummy(ImVec2(2, 0)); + ImGui::Separator(); + } + + void EditorHeaderPanel::renderWindowControls() { + ImGui::SameLine(ImGui::GetWindowWidth() - (UIUtil::ONLY_ICON_BUTTON_SIZE * 3 + 20)); + + GLFWwindow *window = glfwContext->getWindow(); + + if (UIUtil::ButtonSimple((Icons::minimize + id + "min"), UIUtil::ONLY_ICON_BUTTON_SIZE, + UIUtil::ONLY_ICON_BUTTON_SIZE)) { + glfwIconifyWindow(window); + } + ImGui::SameLine(); + + bool isMaximized = glfwGetWindowAttrib(window, GLFW_MAXIMIZED); + if (UIUtil::ButtonSimple((isMaximized ? Icons::filter_none : Icons::crop_square) + id + "max", + UIUtil::ONLY_ICON_BUTTON_SIZE, UIUtil::ONLY_ICON_BUTTON_SIZE)) { + if (isMaximized) { + glfwRestoreWindow(window); + } else { + glfwMaximizeWindow(window); + } + } + ImGui::SameLine(); + + if (UIUtil::ButtonSimple(Icons::close + id + "close", UIUtil::ONLY_ICON_BUTTON_SIZE, + UIUtil::ONLY_ICON_BUTTON_SIZE)) { + glfwSetWindowShouldClose(window, GLFW_TRUE); + } + } + + void EditorHeaderPanel::renderFileTab() { + if (ImGui::BeginMainMenuBar()) { + if (UIUtil::ButtonSimple(Icons::save, UIUtil::ONLY_ICON_BUTTON_SIZE, UIUtil::ONLY_ICON_BUTTON_SIZE)) { + directoryService->save(); + } + ImGui::SameLine(); + if (ImGui::BeginMenu("File")) { + if (ImGui::MenuItem("Open", "Ctrl+O")) { + engineContext->dispose(); + directoryService->updateRootPath(true); + } + if (ImGui::MenuItem("Save", "Ctrl+S")) { + directoryService->save(); + } + ImGui::Separator(); + if (ImGui::MenuItem("Exit")) { + exit(0); + } + ImGui::EndMenu(); + } + + // Edit menu + if (ImGui::BeginMenu("Edit")) { + if (ImGui::MenuItem("Compile shaders")) { + engineContext->dispose(); + } + ImGui::EndMenu(); + } + + + // Window controls (minimize, maximize, close) + renderWindowControls(); + + ImGui::EndMainMenuBar(); + } + } +} diff --git a/src/editor/dock-spaces/header/EditorHeaderPanel.h b/src/editor/dock-spaces/header/EditorHeaderPanel.h new file mode 100644 index 00000000..032e7ab5 --- /dev/null +++ b/src/editor/dock-spaces/header/EditorHeaderPanel.h @@ -0,0 +1,34 @@ +#ifndef METAL_ENGINE_EDITORHEADERPANEL_H +#define METAL_ENGINE_EDITORHEADERPANEL_H + +#include "../../abstract/AbstractPanel.h" +#include + +namespace Metal { + class GLFWContext; + class EngineContext; + struct DirectoryService; + + class EditorHeaderPanel final : public AbstractPanel { + GLFWContext *glfwContext = nullptr; + EngineContext *engineContext = nullptr; + DirectoryService *directoryService = nullptr; + + void renderFileTab(); + + void renderWindowControls(); + + public: + std::vector getDependencies() override { + return { + {"GLFWContext", &glfwContext}, + {"EngineContext", &engineContext}, + {"DirectoryService", &directoryService} + }; + } + + void onSync() override; + }; +} // Metal + +#endif diff --git a/src/context/editor/dock-spaces/inspector/InspectorPanel.cpp b/src/editor/dock-spaces/inspector/InspectorPanel.cpp similarity index 71% rename from src/context/editor/dock-spaces/inspector/InspectorPanel.cpp rename to src/editor/dock-spaces/inspector/InspectorPanel.cpp index 9a09e624..c6ed3c38 100644 --- a/src/context/editor/dock-spaces/inspector/InspectorPanel.cpp +++ b/src/editor/dock-spaces/inspector/InspectorPanel.cpp @@ -1,17 +1,18 @@ #include "InspectorPanel.h" - #include "../../abstract/form/FormPanel.h" -#include "../../../../util/UIUtil.h" -#include "../../../../common/inspection/Inspectable.h" -#include "../../../../context/ApplicationContext.h" -#include "../../../../repository/world/impl/MetadataComponent.h" +#include "../../util/UIUtil.h" +#include "../../../common/Inspectable.h" +#include "../../../ApplicationContext.h" +#include "../../../engine/dto/MetadataComponent.h" #include #include +#include "../../repository/EditorRepository.h" +#include "../../../engine/repository/WorldRepository.h" namespace Metal { void InspectorPanel::onInitialize() { formPanel = new FormPanel(); - appendChild(formPanel); + initializePanel(formPanel); } void InspectorPanel::onSync() { @@ -26,11 +27,11 @@ namespace Metal { if (ImGui::BeginPopup((id + "AddComponentPopup").c_str())) { for (const auto &compDef: ComponentTypes::getComponents()) { - bool hasComponent = compDef.getInspectable(CTX.worldRepository, selectedId) != nullptr; + bool hasComponent = compDef.getInspectable(*worldRepository, selectedId) != nullptr; if (!hasComponent) { if (ImGui::MenuItem( (compDef.icon + " " + compDef.name + id + "adCOmp" + compDef.name).c_str())) { - CTX.worldRepository.createComponent(selectedId, compDef.type); + worldRepository->createComponent(selectedId, compDef.type); selectedId = EMPTY_ENTITY; tick(); } @@ -42,20 +43,17 @@ namespace Metal { } void InspectorPanel::tick() { - if (auto &editorRepository = CTX.editorRepository; - editorRepository.mainSelection != selectedId) { + if (editorRepository->mainSelection != selectedId) { additionalInspection.clear(); - selectedId = editorRepository.mainSelection; + selectedId = editorRepository->mainSelection; formPanel->resetForm(); if (selectedId != EMPTY_ENTITY) { - auto &repo = CTX.worldRepository; - - selectedEntity = repo.getEntity(selectedId); + selectedEntity = worldRepository->getEntity(selectedId); if (selectedEntity != nullptr) { additionalInspection.push_back(selectedEntity); for (const auto &compDef: ComponentTypes::getComponents()) { - if (Inspectable *inspectable = compDef.getInspectable(repo, selectedId)) { + if (Inspectable *inspectable = compDef.getInspectable(*worldRepository, selectedId)) { additionalInspection.push_back(inspectable); } } diff --git a/src/context/editor/dock-spaces/inspector/InspectorPanel.h b/src/editor/dock-spaces/inspector/InspectorPanel.h similarity index 55% rename from src/context/editor/dock-spaces/inspector/InspectorPanel.h rename to src/editor/dock-spaces/inspector/InspectorPanel.h index 5d024e96..cfb45e4b 100644 --- a/src/context/editor/dock-spaces/inspector/InspectorPanel.h +++ b/src/editor/dock-spaces/inspector/InspectorPanel.h @@ -1,12 +1,14 @@ #ifndef INSPECTOR_H #define INSPECTOR_H -#include "../../../../enum/engine-definitions.h" +#include "../../enum/engine-definitions.h" #include "../docks/AbstractDockPanel.h" namespace Metal { class FormPanel; class Inspectable; + struct EditorRepository; + struct WorldRepository; class InspectorPanel final : public AbstractDockPanel { std::vector additionalInspection{}; @@ -15,7 +17,17 @@ namespace Metal { FormPanel *formPanel = nullptr; entt::entity selectedId = EMPTY_ENTITY; + EditorRepository *editorRepository = nullptr; + WorldRepository *worldRepository = nullptr; + public: + std::vector getDependencies() override { + return { + {"EditorRepository", &editorRepository}, + {"WorldRepository", &worldRepository} + }; + } + void onInitialize() override; void onSync() override; diff --git a/src/context/editor/dock-spaces/metrics/MetricsPanel.cpp b/src/editor/dock-spaces/metrics/MetricsPanel.cpp similarity index 53% rename from src/context/editor/dock-spaces/metrics/MetricsPanel.cpp rename to src/editor/dock-spaces/metrics/MetricsPanel.cpp index fc27f0e2..7e8bd984 100644 --- a/src/context/editor/dock-spaces/metrics/MetricsPanel.cpp +++ b/src/editor/dock-spaces/metrics/MetricsPanel.cpp @@ -1,6 +1,12 @@ #include "MetricsPanel.h" #include "../../../ApplicationContext.h" #include "imgui.h" +#include "../../../engine/service/MeshService.h" +#include "../../../engine/service/VoxelService.h" +#include "../../../engine/service/FrameBufferService.h" +#include "../../../engine/service/TextureService.h" +#include "../../../engine/service/PipelineService.h" +#include "../../../engine/service/BufferService.h" namespace Metal { template @@ -22,11 +28,11 @@ namespace Metal { } void MetricsPanel::onSync() { - drawResourceList("Meshes", CTX.meshService, id); - drawResourceList("Voxels", CTX.voxelService, id); - drawResourceList("Framebuffers", CTX.framebufferService, id); - drawResourceList("Textures", CTX.textureService, id); - drawResourceList("Pipelines", CTX.pipelineService, id); - drawResourceList("Buffers", CTX.bufferService, id); + if (meshService) drawResourceList("Meshes", *meshService, id); + if (voxelService) drawResourceList("Voxels", *voxelService, id); + if (framebufferService) drawResourceList("Framebuffers", *framebufferService, id); + if (textureService) drawResourceList("Textures", *textureService, id); + if (pipelineService) drawResourceList("Pipelines", *pipelineService, id); + if (bufferService) drawResourceList("Buffers", *bufferService, id); } } diff --git a/src/editor/dock-spaces/metrics/MetricsPanel.h b/src/editor/dock-spaces/metrics/MetricsPanel.h new file mode 100644 index 00000000..5a945ebb --- /dev/null +++ b/src/editor/dock-spaces/metrics/MetricsPanel.h @@ -0,0 +1,39 @@ +#ifndef METRICSPANEL_H +#define METRICSPANEL_H + +#include "../docks/AbstractDockPanel.h" +#include "imgui.h" + +namespace Metal { + class MeshService; + class VoxelService; + class FrameBufferService; + class TextureService; + class PipelineService; + class BufferService; + + class MetricsPanel final : public AbstractDockPanel { + MeshService *meshService = nullptr; + VoxelService *voxelService = nullptr; + FrameBufferService *framebufferService = nullptr; + TextureService *textureService = nullptr; + PipelineService *pipelineService = nullptr; + BufferService *bufferService = nullptr; + + public: + std::vector getDependencies() override { + return { + {"MeshService", &meshService}, + {"VoxelService", &voxelService}, + {"FrameBufferService", &framebufferService}, + {"TextureService", &textureService}, + {"PipelineService", &pipelineService}, + {"BufferService", &bufferService} + }; + } + + void onSync() override; + }; +} + +#endif diff --git a/src/editor/dock-spaces/repositories/RepositoriesPanel.cpp b/src/editor/dock-spaces/repositories/RepositoriesPanel.cpp new file mode 100644 index 00000000..74279177 --- /dev/null +++ b/src/editor/dock-spaces/repositories/RepositoriesPanel.cpp @@ -0,0 +1,26 @@ +#include "RepositoriesPanel.h" +#include "../../abstract/form/FormPanel.h" +#include "../../../ApplicationContext.h" +#include "../../../common/Inspectable.h" +#include "../../repository/EditorRepository.h" +#include "../../../engine/repository/EngineRepository.h" +#include "../../../engine/repository/WorldRepository.h" +#include "../../../engine/dto/Camera.h" + +namespace Metal { + void RepositoriesPanel::onInitialize() { + formPanel = new FormPanel(); + initializePanel(formPanel); + + repositories.push_back(editorRepository); + repositories.push_back(engineRepository); + repositories.push_back(&worldRepository->camera); + } + + void RepositoriesPanel::onSync() { + for (auto *repo : repositories) { + formPanel->setInspection(repo); + } + formPanel->onSync(); + } +} diff --git a/src/editor/dock-spaces/repositories/RepositoriesPanel.h b/src/editor/dock-spaces/repositories/RepositoriesPanel.h new file mode 100644 index 00000000..7d446362 --- /dev/null +++ b/src/editor/dock-spaces/repositories/RepositoriesPanel.h @@ -0,0 +1,36 @@ +#ifndef REPOSITORIESPANEL_H +#define REPOSITORIESPANEL_H + +#include "../docks/AbstractDockPanel.h" + +namespace Metal { + class FormPanel; + class Inspectable; + struct EditorRepository; + struct EngineRepository; + struct WorldRepository; + + class RepositoriesPanel final : public AbstractDockPanel { + std::vector repositories{}; + FormPanel *formPanel = nullptr; + + EditorRepository *editorRepository = nullptr; + EngineRepository *engineRepository = nullptr; + WorldRepository *worldRepository = nullptr; + + public: + std::vector getDependencies() override { + return { + {"EditorRepository", &editorRepository}, + {"EngineRepository", &engineRepository}, + {"WorldRepository", &worldRepository} + }; + } + + void onInitialize() override; + + void onSync() override; + }; +} + +#endif diff --git a/src/context/editor/dock-spaces/viewport/CameraPositionPanel.cpp b/src/editor/dock-spaces/viewport/CameraPositionPanel.cpp similarity index 75% rename from src/context/editor/dock-spaces/viewport/CameraPositionPanel.cpp rename to src/editor/dock-spaces/viewport/CameraPositionPanel.cpp index e84ed0b5..9ce03f4d 100644 --- a/src/context/editor/dock-spaces/viewport/CameraPositionPanel.cpp +++ b/src/editor/dock-spaces/viewport/CameraPositionPanel.cpp @@ -1,8 +1,8 @@ #include "CameraPositionPanel.h" - -#include "../../../../context/ApplicationContext.h" -#include "../../../../util/UIUtil.h" -#include "../../../../service/camera/Camera.h" +#include "../../../ApplicationContext.h" +#include "../../util/UIUtil.h" +#include "../../../engine/dto/Camera.h" +#include "../../../engine/repository/WorldRepository.h" namespace Metal { void CameraPositionPanel::onSync() { @@ -18,7 +18,7 @@ namespace Metal { ImGui::SetNextWindowBgAlpha(.4f); if (ImGui::Begin(id.c_str(), &UIUtil::OPEN, ImGuiWindowFlags_NoResize | ImGuiWindowFlags_NoTitleBar | ImGuiWindowFlags_NoMove | ImGuiWindowFlags_NoCollapse)) { - const auto &positionCamera = CTX.worldRepository.camera.position; + const auto &positionCamera = worldRepository->camera.position; ImGui::TextColored(RED, "X: %i", static_cast(positionCamera.x)); ImGui::SameLine(); ImGui::TextColored(GREEN, "Y: %i", static_cast(positionCamera.y)); @@ -27,10 +27,10 @@ namespace Metal { ImGui::SameLine(); ImGui::Text( - "Yaw: %i", static_cast(CTX.worldRepository.camera.yaw * TO_DEG)); + "Yaw: %i", static_cast(worldRepository->camera.yaw * TO_DEG)); ImGui::SameLine(); ImGui::Text("Pitch: %i", - static_cast(CTX.worldRepository.camera.pitch * TO_DEG)); + static_cast(worldRepository->camera.pitch * TO_DEG)); } ImGui::PopStyleVar(); ImGui::End(); diff --git a/src/context/editor/dock-spaces/viewport/CameraPositionPanel.h b/src/editor/dock-spaces/viewport/CameraPositionPanel.h similarity index 67% rename from src/context/editor/dock-spaces/viewport/CameraPositionPanel.h rename to src/editor/dock-spaces/viewport/CameraPositionPanel.h index eabc4a4a..4a2b4367 100644 --- a/src/context/editor/dock-spaces/viewport/CameraPositionPanel.h +++ b/src/editor/dock-spaces/viewport/CameraPositionPanel.h @@ -6,13 +6,23 @@ #include "../../abstract/AbstractPanel.h" namespace Metal { + struct WorldRepository; + class CameraPositionPanel final : public AbstractPanel { ImVec4 RED = ImVec4(1, 0, 0, 1); ImVec4 GREEN = ImVec4(0, 1, 0, 1); ImVec4 BLUE = ImVec4(0, .5f, 1, 1); float TO_DEG = 180.f / glm::pi(); + WorldRepository *worldRepository = nullptr; + public: + std::vector getDependencies() override { + return { + {"WorldRepository", &worldRepository} + }; + } + void onSync() override; }; } // Metal diff --git a/src/context/editor/dock-spaces/viewport/EngineFramePanel.cpp b/src/editor/dock-spaces/viewport/EngineFramePanel.cpp similarity index 56% rename from src/context/editor/dock-spaces/viewport/EngineFramePanel.cpp rename to src/editor/dock-spaces/viewport/EngineFramePanel.cpp index d1bdc025..12f6587c 100644 --- a/src/context/editor/dock-spaces/viewport/EngineFramePanel.cpp +++ b/src/editor/dock-spaces/viewport/EngineFramePanel.cpp @@ -1,38 +1,53 @@ #include "EngineFramePanel.h" -#include "../../../../context/ApplicationContext.h" -#include "../../../../context/engine/frame-builder/EngineFrameBuilder.h" -#include "../../../../context/engine/frame-builder/EngineFrame.h" -#include "../../../../service/descriptor/DescriptorInstance.h" -#include "../../../../service/framebuffer/FrameBufferInstance.h" -#include "../../../../service/picking/PickingService.h" -#include "../../../../enum/engine-definitions.h" -#include "../../../../enum/EngineResourceIDs.h" -#include "../../../../dto/buffers/GlobalDataUBO.h" -#include "../../../../dto/buffers/LightData.h" -#include "../../../../dto/buffers/VolumeData.h" -#include "../../../../dto/buffers/MeshMetadata.h" +#include "../../../ApplicationContext.h" +#include "../../../engine/frame-builder/EngineFrameBuilder.h" +#include "../../../engine/frame-builder/EngineFrame.h" +#include "../../../engine/dto/DescriptorInstance.h" +#include "../../../engine/resource/FrameBufferInstance.h" +#include "../../service/PickingService.h" +#include "../../enum/engine-definitions.h" +#include "../../enum/EngineResourceIDs.h" +#include "../../../engine/dto/GlobalDataUBO.h" +#include "../../../engine/dto/LightData.h" +#include "../../../engine/dto/VolumeData.h" +#include "../../../engine/dto/MeshMetadata.h" #include "ViewportHeaderPanel.h" #include "ImGuizmo.h" #include +#include "../../../engine/passes/impl/HWRayTracingPass.h" +#include "../../../engine/passes/impl/PostProcessingPass.h" +#include "../../../engine/passes/impl/SpatialFilterPass.h" +#include "../../../engine/passes/impl/TemporalAccumulationPass.h" +#include "../../passes/GridPass.h" +#include "../../passes/SelectionIDPass.h" +#include "../../passes/SelectionOutlinePass.h" +#include "../../../core/vulkan/VulkanContext.h" +#include "../../../engine/repository/EngineRepository.h" +#include "../../../engine/EngineContext.h" +#include "../../../engine/service/DescriptorSetService.h" +#include "../../service/SelectionService.h" +#include "../../../engine/resource/TextureInstance.h" namespace Metal { void EngineFramePanel::onInitialize() { - const auto gBufferW = CTX.vulkanContext.getWindowWidth() / CTX.engineRepository.shadingResInvScale; - const auto gBufferH = CTX.vulkanContext.getWindowHeight() / CTX.engineRepository.shadingResInvScale; + const auto gBufferW = vulkanContext->getWindowWidth() / engineRepository-> + shadingResInvScale; + const auto gBufferH = vulkanContext->getWindowHeight() / engineRepository + ->shadingResInvScale; - engineFrame = EngineFrameBuilder() + engineContext->createFrame(id) .addBuffer(RID_GLOBAL_DATA, sizeof(GlobalDataUBO), VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT, UNIFORM_BUFFER) .addBuffer(RID_LIGHT_BUFFER, MAX_LIGHTS * sizeof(LightData), VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT, STORAGE_BUFFER) - .addBuffer(RID_VOLUMES_BUFFER, MAX_VOLUMES * sizeof(VolumeData), - VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT, STORAGE_BUFFER) + .addBuffer(RID_VOLUMES_BUFFER, MAX_VOLUMES * sizeof(VolumeData), + VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT, STORAGE_BUFFER) .addBuffer(RID_MESH_METADATA_BUFFER, MAX_MESH_INSTANCES * sizeof(MeshMetadata), VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT, STORAGE_BUFFER) .addTexture(RID_ACCUMULATED_FRAME, gBufferW, gBufferH) .addTexture(RID_GBUFFER_POSITION_INDEX, gBufferW, gBufferH, VK_FORMAT_R32G32B32A32_SFLOAT) .addTexture(RID_GBUFFER_NORMAL, gBufferW, gBufferH, VK_FORMAT_R16G16B16A16_SFLOAT) - .addTexture(RID_PREVIOUS_POSITION_INDEX, gBufferW, gBufferH, VK_FORMAT_R32G32B32_SFLOAT) // I noticed current position is rgba32f, but let's check. + .addTexture(RID_PREVIOUS_POSITION_INDEX, gBufferW, gBufferH, VK_FORMAT_R32G32B32A32_SFLOAT) .addTexture(RID_PREVIOUS_NORMAL, gBufferW, gBufferH, VK_FORMAT_R16G16B16A16_SFLOAT) .addTexture(RID_DENOISED_FRAME, gBufferW, gBufferH, VK_FORMAT_R16G16B16A16_SFLOAT) .addTexture(RID_TEMPORAL_OUTPUT, gBufferW, gBufferH, VK_FORMAT_R16G16B16A16_SFLOAT) @@ -42,29 +57,25 @@ namespace Metal { .addFramebuffer(RID_POST_PROCESSING_FBO, gBufferW, gBufferH, glm::vec4(0, 0, 0, 0)) .addColor(VK_FORMAT_R16G16B16A16_SFLOAT, VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT) .addComputeCommandBuffer(RID_COMPUTE_CB) - .addPass(RAY_TRACING, RID_COMPUTE_CB) - .addPass(ACCUMULATION, RID_COMPUTE_CB) - .addPass(TEMPORAL_ACCUMULATION, RID_COMPUTE_CB) - .addPass(SPATIAL_FILTER, RID_COMPUTE_CB) + .addPass(std::make_unique(), RID_COMPUTE_CB) + .addPass(std::make_unique(), RID_COMPUTE_CB) + .addPass(std::make_unique(), RID_COMPUTE_CB) .addCommandBuffer(RID_SELECTION_CB, RID_SELECTION_FBO) - .addPass(SELECTION_ID, RID_SELECTION_CB) + .addPass(std::make_unique(), RID_SELECTION_CB) .addCommandBuffer(RID_POST_PROCESSING_CB, RID_POST_PROCESSING_FBO) - .addPass(POST_PROCESSING, RID_POST_PROCESSING_CB) - .addPass(SELECTION_OUTLINE, RID_POST_PROCESSING_CB) - .addPass(GRID, RID_POST_PROCESSING_CB) - .addPass(ICONS, RID_POST_PROCESSING_CB) + .addPass(std::make_unique(), RID_POST_PROCESSING_CB) + .addPass(std::make_unique(), RID_POST_PROCESSING_CB) + .addPass(std::make_unique(), RID_POST_PROCESSING_CB) .build(); - - CTX.engineContext.registerFrame(engineFrame.get()); } void EngineFramePanel::onSync() { - engineFrame->setShouldRender(true); + engineContext->setCurrentFrame(id); const ImVec2 viewportSize = ImGui::GetContentRegionAvail(); - auto *framebuffer = engineFrame->getResourceAs(RID_POST_PROCESSING_FBO); + auto *framebuffer = engineContext->currentFrame->getResourceAs(RID_POST_PROCESSING_FBO); if (framebuffer) { - CTX.descriptorSetService.setImageDescriptor(framebuffer, 0); + descriptorSetService->setImageDescriptor(framebuffer, 0); ImGui::Image(reinterpret_cast(framebuffer->attachments[0]->imageDescriptor->vkDescriptorSet), viewportSize); @@ -95,7 +106,7 @@ namespace Metal { return; } - auto *gBufferPositionIndex = engineFrame->getResourceAs(RID_GBUFFER_POSITION_INDEX); + auto *gBufferPositionIndex = engineContext->currentFrame->getResourceAs(RID_GBUFFER_POSITION_INDEX); if (!gBufferPositionIndex) { return; } @@ -105,8 +116,9 @@ namespace Metal { const uint32_t pixelX = std::min(static_cast(u * static_cast(width)), width - 1); const uint32_t pixelY = std::min(static_cast(v * static_cast(height)), height - 1); - const auto picked = CTX.pickingService.pickEntityFromGBuffer(gBufferPositionIndex, pixelX, pixelY); - CTX.selectionService.clearSelection(); - CTX.selectionService.addSelected(picked.value_or(EMPTY_ENTITY)); + const auto picked = pickingService->pickEntityFromGBuffer( + gBufferPositionIndex, pixelX, pixelY); + selectionService->clearSelection(); + selectionService->addSelected(picked.value_or(EMPTY_ENTITY)); } } // Metal diff --git a/src/editor/dock-spaces/viewport/EngineFramePanel.h b/src/editor/dock-spaces/viewport/EngineFramePanel.h new file mode 100644 index 00000000..0b7f9cba --- /dev/null +++ b/src/editor/dock-spaces/viewport/EngineFramePanel.h @@ -0,0 +1,45 @@ +#ifndef ENGINE_FRAME_PANEL_H +#define ENGINE_FRAME_PANEL_H + +#include "../../abstract/AbstractPanel.h" +#include +#include + +namespace Metal { + class EngineFrame; + class VulkanContext; + struct EngineRepository; + class EngineContext; + class DescriptorSetService; + class PickingService; + class SelectionService; + + class EngineFramePanel final : public AbstractPanel { + VulkanContext *vulkanContext = nullptr; + EngineRepository *engineRepository = nullptr; + EngineContext *engineContext = nullptr; + DescriptorSetService *descriptorSetService = nullptr; + PickingService *pickingService = nullptr; + SelectionService *selectionService = nullptr; + + public: + std::vector getDependencies() override { + return { + {"VulkanContext", &vulkanContext}, + {"EngineRepository", &engineRepository}, + {"EngineContext", &engineContext}, + {"DescriptorSetService", &descriptorSetService}, + {"PickingService", &pickingService}, + {"SelectionService", &selectionService} + }; + } + + void onInitialize() override; + + void onSync() override; + + void handleViewportPicking(const ImVec2 &imageMin, const ImVec2 &imageMax) const; + }; +} // Metal + +#endif //ENGINE_FRAME_PANEL_H diff --git a/src/context/editor/dock-spaces/viewport/GizmoPanel.cpp b/src/editor/dock-spaces/viewport/GizmoPanel.cpp similarity index 88% rename from src/context/editor/dock-spaces/viewport/GizmoPanel.cpp rename to src/editor/dock-spaces/viewport/GizmoPanel.cpp index b8585135..30f4163d 100644 --- a/src/context/editor/dock-spaces/viewport/GizmoPanel.cpp +++ b/src/editor/dock-spaces/viewport/GizmoPanel.cpp @@ -1,19 +1,19 @@ #include "GizmoPanel.h" - -#include "../../../../context/ApplicationContext.h" -#include "../../../../repository/world/components/TransformComponent.h" -#include "../../../../service/camera/Camera.h" +#include "../../../ApplicationContext.h" +#include "../../../engine/dto/TransformComponent.h" +#include "../../../engine/dto/Camera.h" #include "ImGuizmo.h" #include -#define GLM_ENABLE_EXPERIMENTAL #include +#include "../../repository/EditorRepository.h" +#include "../../../engine/repository/WorldRepository.h" +#include "../../service/SelectionService.h" namespace Metal { GizmoPanel::GizmoPanel(ImVec2 *position, glm::vec2 *size): size(size), position(position) { } void GizmoPanel::onInitialize() { - editorRepository = &CTX.editorRepository; } void GizmoPanel::onSync() { @@ -22,7 +22,7 @@ namespace Metal { localSelected = nullptr; localChangeId = 0; if (editorRepository->mainSelection != EMPTY_ENTITY) { - CTX.selectionService.updatePrimitiveSelected(); + selectionService->updatePrimitiveSelected(); } return; } @@ -40,7 +40,7 @@ namespace Metal { } recomposeMatrix(); - ImGuizmo::SetOrthographic(CTX.worldRepository.camera.isOrthographic); + ImGuizmo::SetOrthographic(worldRepository->camera.isOrthographic); ImGuizmo::SetDrawlist(); ImVec2 viewportMin = ImGui::GetItemRectMin(); ImVec2 viewportSize = ImGui::GetItemRectSize(); @@ -113,8 +113,8 @@ namespace Metal { } void GizmoPanel::recomposeMatrix() { - viewMatrixCache = glm::value_ptr(CTX.worldRepository.camera.viewMatrix); - cacheProjection = CTX.worldRepository.camera.projectionMatrix; + viewMatrixCache = glm::value_ptr(worldRepository->camera.viewMatrix); + cacheProjection = worldRepository->camera.projectionMatrix; cacheProjection[1][1] *= -1; diff --git a/src/context/editor/dock-spaces/viewport/GizmoPanel.h b/src/editor/dock-spaces/viewport/GizmoPanel.h similarity index 72% rename from src/context/editor/dock-spaces/viewport/GizmoPanel.h rename to src/editor/dock-spaces/viewport/GizmoPanel.h index 36b6ee20..12da02fc 100644 --- a/src/context/editor/dock-spaces/viewport/GizmoPanel.h +++ b/src/editor/dock-spaces/viewport/GizmoPanel.h @@ -2,6 +2,7 @@ #define GIZMOPANEL_H #include #include +#define GLM_ENABLE_EXPERIMENTAL #include #include @@ -9,6 +10,8 @@ namespace Metal { struct EditorRepository; + struct WorldRepository; + class SelectionService; } namespace Metal { @@ -31,9 +34,20 @@ namespace Metal { TransformComponent *localSelected = nullptr; int localChangeId{}; bool isGizmoOver = false; + EditorRepository *editorRepository = nullptr; + WorldRepository *worldRepository = nullptr; + SelectionService *selectionService = nullptr; public: + std::vector getDependencies() override { + return { + {"EditorRepository", &editorRepository}, + {"WorldRepository", &worldRepository}, + {"SelectionService", &selectionService} + }; + } + explicit GizmoPanel(ImVec2 *position, glm::vec2 *size); void onInitialize() override; diff --git a/src/context/editor/dock-spaces/viewport/GizmoSettingsPanel.cpp b/src/editor/dock-spaces/viewport/GizmoSettingsPanel.cpp similarity index 93% rename from src/context/editor/dock-spaces/viewport/GizmoSettingsPanel.cpp rename to src/editor/dock-spaces/viewport/GizmoSettingsPanel.cpp index 3d2638d9..9094ce19 100644 --- a/src/context/editor/dock-spaces/viewport/GizmoSettingsPanel.cpp +++ b/src/editor/dock-spaces/viewport/GizmoSettingsPanel.cpp @@ -1,11 +1,13 @@ #include "GizmoSettingsPanel.h" -#include "../../../../util/UIUtil.h" -#include "../../../../context/ApplicationContext.h" +#include "../../util/UIUtil.h" +#include "../../../ApplicationContext.h" #include "ImGuizmo.h" +#include "../../repository/EditorRepository.h" +#include "../../../engine/repository/WorldRepository.h" +#include "../../../engine/dto/MetadataComponent.h" namespace Metal { void GizmoSettingsPanel::onInitialize() { - editorRepository = &CTX.editorRepository; } void GizmoSettingsPanel::onSync() { @@ -15,9 +17,9 @@ namespace Metal { ImGui::SameLine(); gizmoGrid(); UIUtil::Spacing(); - if (selectedEntityId != editorRepository->mainSelection && CTX.worldRepository.registry.all_of( + if (selectedEntityId != editorRepository->mainSelection && worldRepository->registry.valid( editorRepository->mainSelection)) { - selectedEntity = CTX.worldRepository.getEntity(editorRepository->mainSelection); + selectedEntity = worldRepository->getEntity(editorRepository->mainSelection); selectedEntityId = editorRepository->mainSelection; } if (selectedEntity != nullptr) { @@ -119,7 +121,7 @@ namespace Metal { ImGui::SetNextItemWidth(50); if (ImGui::Combo((id + "scaleSnapAngle").c_str(), &editorRepository->gizmoSnapScaleOption, SNAP_SCALE_OPTIONS, ImGuiComboFlags_NoArrowButton)) { - editorRepository->gizmoSnapScale = SNAP_SCALE_OPTIONS[editorRepository->gizmoSnapScaleOption]; + editorRepository->gizmoSnapScale = SNAP_SCALE_OPTIONS_A[editorRepository->gizmoSnapScaleOption]; } } } // Metal diff --git a/src/context/editor/dock-spaces/viewport/GizmoSettingsPanel.h b/src/editor/dock-spaces/viewport/GizmoSettingsPanel.h similarity index 80% rename from src/context/editor/dock-spaces/viewport/GizmoSettingsPanel.h rename to src/editor/dock-spaces/viewport/GizmoSettingsPanel.h index aec3a185..7f5b13d0 100644 --- a/src/context/editor/dock-spaces/viewport/GizmoSettingsPanel.h +++ b/src/editor/dock-spaces/viewport/GizmoSettingsPanel.h @@ -3,12 +3,13 @@ #include #include -#include "../../../../enum/engine-definitions.h" +#include "../../enum/engine-definitions.h" #include "../../abstract/AbstractPanel.h" namespace Metal { struct MetadataComponent; struct EditorRepository; + struct WorldRepository; class GizmoSettingsPanel final : public AbstractPanel { static constexpr ImVec2 SPACING = ImVec2(0, 0); @@ -19,10 +20,18 @@ namespace Metal { static constexpr const char *SNAP_SCALE_OPTIONS = "0.5\0 1\0 2\0 5\0 10\0"; static constexpr std::array SNAP_SCALE_OPTIONS_A = {0.5, 1, 2, 5, 10}; EditorRepository *editorRepository = nullptr; + WorldRepository *worldRepository = nullptr; MetadataComponent *selectedEntity = nullptr; entt::entity selectedEntityId = EMPTY_ENTITY; public: + std::vector getDependencies() override { + return { + {"EditorRepository", &editorRepository}, + {"WorldRepository", &worldRepository} + }; + } + void onInitialize() override; void gizmoGrid() const; diff --git a/src/context/editor/dock-spaces/viewport/ViewportHeaderPanel.cpp b/src/editor/dock-spaces/viewport/ViewportHeaderPanel.cpp similarity index 79% rename from src/context/editor/dock-spaces/viewport/ViewportHeaderPanel.cpp rename to src/editor/dock-spaces/viewport/ViewportHeaderPanel.cpp index 945b926e..3d4cd54f 100644 --- a/src/context/editor/dock-spaces/viewport/ViewportHeaderPanel.cpp +++ b/src/editor/dock-spaces/viewport/ViewportHeaderPanel.cpp @@ -1,12 +1,13 @@ #include "ViewportHeaderPanel.h" - #include "GizmoSettingsPanel.h" -#include "../../../../context/ApplicationContext.h" -#include "../../../../util/UIUtil.h" +#include "../../../ApplicationContext.h" +#include "../../util/UIUtil.h" +#include "../../repository/EditorRepository.h" +#include "../../../engine/repository/WorldRepository.h" namespace Metal { void ViewportHeaderPanel::onInitialize() { - appendChild(gizmo = new GizmoSettingsPanel()); + initializePanel(gizmo = new GizmoSettingsPanel()); } void ViewportHeaderPanel::onSync() { @@ -33,8 +34,8 @@ namespace Metal { if (UIUtil::ButtonSimple(Icons::center_focus_strong + id + "centerCamera", UIUtil::ONLY_ICON_BUTTON_SIZE, UIUtil::ONLY_ICON_BUTTON_SIZE)) { - CTX.worldRepository.camera.position = {0, 0, 0}; - CTX.worldRepository.camera.registerChange(); + worldRepository->camera.position = {0, 0, 0}; + worldRepository->camera.registerChange(); } UIUtil::RenderTooltip("Center camera?"); @@ -44,21 +45,20 @@ namespace Metal { static float speedValues[] = {0.1f, 0.5f, 1.0f, 2.0f, 5.0f, 10.0f}; int currentSpeedIndex = 2; for (int i = 0; i < 6; i++) { - if (CTX.worldRepository.camera.movementSensitivity == speedValues[i]) { + if (worldRepository->camera.movementSensitivity == speedValues[i]) { currentSpeedIndex = i; break; } } if (ImGui::Combo((id + "speedCamera").c_str(), ¤tSpeedIndex, speeds, IM_ARRAYSIZE(speeds))) { - CTX.worldRepository.camera.movementSensitivity = speedValues[currentSpeedIndex]; + worldRepository->camera.movementSensitivity = speedValues[currentSpeedIndex]; } UIUtil::RenderTooltip("Camera speed"); } void ViewportHeaderPanel::shadingMode() { - auto &editorRepository = CTX.editorRepository; ImGui::SetNextItemWidth(150); - shadingModelOption = ShadingModes::IndexOfValue(editorRepository.shadingMode); + shadingModelOption = ShadingModes::IndexOfValue(editorRepository->shadingMode); auto currentEntry = ShadingModes::entries[shadingModelOption]; if (ImGui::BeginCombo((id + "shadingMode").c_str(), (currentEntry.icon + " " + currentEntry.label).c_str())) { @@ -67,7 +67,7 @@ namespace Metal { auto entry = ShadingModes::entries[i]; if (ImGui::Selectable((entry.icon + " " + entry.label).c_str(), is_selected)) { shadingModelOption = i; - editorRepository.shadingMode = ShadingModes::ValueOfIndex(shadingModelOption); + editorRepository->shadingMode = ShadingModes::ValueOfIndex(shadingModelOption); } if (is_selected) { ImGui::SetItemDefaultFocus(); diff --git a/src/context/editor/dock-spaces/viewport/ViewportHeaderPanel.h b/src/editor/dock-spaces/viewport/ViewportHeaderPanel.h similarity index 65% rename from src/context/editor/dock-spaces/viewport/ViewportHeaderPanel.h rename to src/editor/dock-spaces/viewport/ViewportHeaderPanel.h index ed2e51c1..eb5cf60b 100644 --- a/src/context/editor/dock-spaces/viewport/ViewportHeaderPanel.h +++ b/src/editor/dock-spaces/viewport/ViewportHeaderPanel.h @@ -5,13 +5,26 @@ #include "../../abstract/AbstractPanel.h" namespace Metal { + struct EditorRepository; + struct WorldRepository; + class ViewportHeaderPanel final : public AbstractPanel { static constexpr int FLAGS = ImGuiWindowFlags_NoResize | ImGuiWindowFlags_NoTitleBar | ImGuiWindowFlags_NoMove | ImGuiWindowFlags_NoBackground | ImGuiWindowFlags_NoCollapse; AbstractPanel *gizmo = nullptr; int shadingModelOption = 0; + EditorRepository *editorRepository = nullptr; + WorldRepository *worldRepository = nullptr; + public: + std::vector getDependencies() override { + return { + {"EditorRepository", &editorRepository}, + {"WorldRepository", &worldRepository} + }; + } + static constexpr float HEIGHT = 28; void onInitialize() override; diff --git a/src/editor/dock-spaces/viewport/ViewportPanel.cpp b/src/editor/dock-spaces/viewport/ViewportPanel.cpp new file mode 100644 index 00000000..05f00fa8 --- /dev/null +++ b/src/editor/dock-spaces/viewport/ViewportPanel.cpp @@ -0,0 +1,116 @@ +#include "ViewportPanel.h" +#include "CameraPositionPanel.h" +#include "GizmoPanel.h" +#include "ImGuizmo.h" +#include "ViewportHeaderPanel.h" +#include "EngineFramePanel.h" +#include "../../../ApplicationContext.h" +#include "../../../engine/dto/Camera.h" +#include "../../../engine/frame-builder/EngineFrameBuilder.h" +#include +#include "../../repository/EditorRepository.h" +#include "../../../engine/repository/WorldRepository.h" +#include "../../service/SelectionService.h" +#include "../../../engine/service/CameraService.h" +#include "../../../engine/repository/RuntimeRepository.h" +#include "../../../engine/EngineContext.h" +#include "../../../core/DirectoryService.h" +#include "../../../engine/dto/MetadataComponent.h" + +namespace Metal { + void ViewportPanel::onInitialize() { + initializePanel(headerPanel = new ViewportHeaderPanel()); + initializePanel(engineFramePanel = new EngineFramePanel()); + initializePanel(gizmoPanel = new GizmoPanel(position, size)); + initializePanel(cameraPanel = new CameraPositionPanel()); + + shortcuts = { + ShortcutDTO("Change shading mode", ImGuiKey_Q, [this]() { + editorRepository->shadingMode = ShadingModes::ValueOfIndex( + ShadingModes::IndexOfValue(editorRepository->shadingMode) + 1); + }), + ShortcutDTO("Translate", ImGuiKey_1, [this]() { + editorRepository->gizmoType = ImGuizmo::OPERATION::TRANSLATE; + }), + ShortcutDTO("Scale", ImGuiKey_2, [this]() { + editorRepository->gizmoType = ImGuizmo::OPERATION::SCALE; + }), + ShortcutDTO("Rotate", ImGuiKey_3, [this]() { + editorRepository->gizmoType = ImGuizmo::OPERATION::ROTATE; + }), + ShortcutDTO("Delete", ImGuiKey_Delete, [this]() { + std::vector entities; + for (auto &entry: editorRepository->selected) { + entities.push_back(entry.first); + } + worldRepository->deleteEntities(entities); + selectionService->clearSelection(); + }), + ShortcutDTO("Select All", ImGuiMod_Ctrl | ImGuiKey_A, [this]() { + std::vector entities; + auto &storage = worldRepository->registry.storage(); + for (auto it = storage.begin(); it != storage.end(); ++it) { + auto entity = *it; + if (worldRepository->registry.all_of(entity)) { + entities.push_back(entity); + } + } + selectionService->addAllSelected(entities); + }), + ShortcutDTO("Save", ImGuiMod_Ctrl | ImGuiKey_S, [this] { + directoryService->save(); + }) + }; + } + + void ViewportPanel::onSync() { + updateCamera(); + updateInputs(); + + headerPanel->onSync(); + engineFramePanel->onSync(); + + gizmoPanel->onSync(); + cameraPanel->onSync(); + } + + void ViewportPanel::updateCamera() { + if (ImGui::IsWindowHovered() && !ImGuizmo::IsUsing() && ImGui::IsMouseDown(ImGuiMouseButton_Right)) { + cameraService->handleInput(isFirstMovement); + if (const auto &io = ImGui::GetIO(); io.MouseWheel != 0) { + worldRepository->camera.movementSensitivity += io.MouseWheel * 100 * engineContext->deltaTime; + worldRepository->camera.movementSensitivity = + std::max(.1f, worldRepository->camera.movementSensitivity); + } + isFirstMovement = false; + } else { + isFirstMovement = true; + } + } + + void ViewportPanel::updateInputs() const { + runtimeRepository->viewportH = size->y; + runtimeRepository->viewportW = size->x; + + const ImVec2 windowPos = ImGui::GetWindowPos(); + runtimeRepository->viewportX = windowPos.x; + runtimeRepository->viewportY = windowPos.y; + + runtimeRepository->isFocused = ImGui::IsWindowHovered(); + runtimeRepository->forwardPressed = ImGui::IsKeyDown(ImGuiKey_W); + runtimeRepository->backwardPressed = ImGui::IsKeyDown(ImGuiKey_S); + runtimeRepository->leftPressed = ImGui::IsKeyDown(ImGuiKey_A); + runtimeRepository->rightPressed = ImGui::IsKeyDown(ImGuiKey_D); + runtimeRepository->upPressed = ImGui::IsKeyDown(ImGuiKey_Space); + runtimeRepository->downPressed = ImGui::IsKeyDown(ImGuiKey_LeftCtrl); + runtimeRepository->mousePressed = ImGui::IsWindowFocused() && ImGui::IsWindowHovered() && ImGui::IsMouseDown( + ImGuiMouseButton_Left); + + const ImVec2 mousePos = ImGui::GetMousePos(); + runtimeRepository->mouseX = mousePos.x; + runtimeRepository->mouseY = mousePos.y; + + runtimeRepository->normalizedMouseX = (runtimeRepository->mouseX + runtimeRepository->viewportX) / runtimeRepository->viewportW; + runtimeRepository->normalizedMouseY = (runtimeRepository->viewportH - runtimeRepository->mouseY + runtimeRepository->viewportY) / runtimeRepository->viewportH; + } +} diff --git a/src/editor/dock-spaces/viewport/ViewportPanel.h b/src/editor/dock-spaces/viewport/ViewportPanel.h new file mode 100644 index 00000000..5703d6fa --- /dev/null +++ b/src/editor/dock-spaces/viewport/ViewportPanel.h @@ -0,0 +1,53 @@ +#ifndef METAL_ENGINE_VIEWPORTPANEL_H +#define METAL_ENGINE_VIEWPORTPANEL_H + +#include "../docks/AbstractDockPanel.h" + +namespace Metal { + class CameraService; + class SelectionService; + struct EditorRepository; + struct WorldRepository; + struct RuntimeRepository; + class EngineContext; + struct DirectoryService; + + class ViewportPanel final : public AbstractDockPanel { + bool isFirstMovement = false; + AbstractPanel *headerPanel = nullptr; + AbstractPanel *gizmoPanel = nullptr; + AbstractPanel *cameraPanel = nullptr; + AbstractPanel *engineFramePanel = nullptr; + + CameraService *cameraService = nullptr; + SelectionService *selectionService = nullptr; + EditorRepository *editorRepository = nullptr; + WorldRepository *worldRepository = nullptr; + RuntimeRepository *runtimeRepository = nullptr; + EngineContext *engineContext = nullptr; + DirectoryService *directoryService = nullptr; + + public: + std::vector getDependencies() override { + return { + {"CameraService", &cameraService}, + {"SelectionService", &selectionService}, + {"EditorRepository", &editorRepository}, + {"WorldRepository", &worldRepository}, + {"RuntimeRepository", &runtimeRepository}, + {"EngineContext", &engineContext}, + {"DirectoryService", &directoryService} + }; + } + + void onInitialize() override; + + void onSync() override; + + void updateCamera(); + + void updateInputs() const; + }; +} + +#endif diff --git a/src/context/editor/dock-spaces/world/WorldHeaderPanel.cpp b/src/editor/dock-spaces/world/WorldHeaderPanel.cpp similarity index 86% rename from src/context/editor/dock-spaces/world/WorldHeaderPanel.cpp rename to src/editor/dock-spaces/world/WorldHeaderPanel.cpp index 98b04ce1..fba2b9f4 100644 --- a/src/context/editor/dock-spaces/world/WorldHeaderPanel.cpp +++ b/src/editor/dock-spaces/world/WorldHeaderPanel.cpp @@ -1,8 +1,8 @@ #include "WorldHeaderPanel.h" - -#include "../../../../context/ApplicationContext.h" -#include "../../../../util/UIUtil.h" -#include "../../../../enum/ComponentType.h" +#include "../../../ApplicationContext.h" +#include "../../util/UIUtil.h" +#include "../../../engine/enum/ComponentType.h" +#include "../../../engine/repository/WorldRepository.h" namespace Metal { void WorldHeaderPanel::onSync() { @@ -28,7 +28,7 @@ namespace Metal { ImGui::SameLine(); if (UIUtil::ButtonSimple(Icons::add + "##hierarchyAdd" + id, UIUtil::ONLY_ICON_BUTTON_SIZE, UIUtil::ONLY_ICON_BUTTON_SIZE)) { - CTX.worldRepository.createEntity(); + worldRepository->createEntity(); } UIUtil::RenderTooltip("Create entity"); } diff --git a/src/context/editor/dock-spaces/world/WorldHeaderPanel.h b/src/editor/dock-spaces/world/WorldHeaderPanel.h similarity index 58% rename from src/context/editor/dock-spaces/world/WorldHeaderPanel.h rename to src/editor/dock-spaces/world/WorldHeaderPanel.h index 1e9f025a..5a7134a6 100644 --- a/src/context/editor/dock-spaces/world/WorldHeaderPanel.h +++ b/src/editor/dock-spaces/world/WorldHeaderPanel.h @@ -3,8 +3,18 @@ #include "../../abstract/AbstractPanel.h" namespace Metal { + struct WorldRepository; + class WorldHeaderPanel final : public AbstractPanel { + WorldRepository *worldRepository = nullptr; + public: + std::vector getDependencies() override { + return { + {"WorldRepository", &worldRepository} + }; + } + void onSync() override; char search[512]; diff --git a/src/context/editor/dock-spaces/world/WorldPanel.cpp b/src/editor/dock-spaces/world/WorldPanel.cpp similarity index 85% rename from src/context/editor/dock-spaces/world/WorldPanel.cpp rename to src/editor/dock-spaces/world/WorldPanel.cpp index ac2265da..1b555094 100644 --- a/src/context/editor/dock-spaces/world/WorldPanel.cpp +++ b/src/editor/dock-spaces/world/WorldPanel.cpp @@ -1,26 +1,27 @@ #include "WorldPanel.h" - #include "WorldHeaderPanel.h" -#include "../../../../common/interface/Icons.h" -#include "../../../../util/UIUtil.h" -#include "../../../../context/ApplicationContext.h" -#include "../../../../repository/world/impl/MetadataComponent.h" -#include "../../../../enum/ComponentType.h" +#include "../../../common/Icons.h" +#include "../../util/UIUtil.h" +#include "../../../ApplicationContext.h" +#include "../../../engine/dto/MetadataComponent.h" +#include "../../../engine/enum/ComponentType.h" +#include "../../../engine/repository/WorldRepository.h" +#include "../../repository/EditorRepository.h" +#include "../../service/SelectionService.h" +#include "../../../core/DirectoryService.h" namespace Metal { void WorldPanel::onInitialize() { - appendChild(headerPanel = new WorldHeaderPanel()); - world = &CTX.worldRepository; - editorRepository = &CTX.editorRepository; + initializePanel(headerPanel = new WorldHeaderPanel()); shortcuts = { ShortcutDTO("Delete", ImGuiKey_Delete, [this]() { std::vector entities; - for (auto &entry: CTX.editorRepository.selected) { + for (auto &entry: editorRepository->selected) { entities.push_back(entry.first); } - CTX.worldRepository.deleteEntities(entities); - CTX.selectionService.clearSelection(); + world->deleteEntities(entities); + selectionService->clearSelection(); }), ShortcutDTO("Select All", ImGuiMod_Ctrl | ImGuiKey_A, [this]() { std::vector entities; @@ -29,10 +30,10 @@ namespace Metal { entities.push_back(entity); } } - CTX.selectionService.addAllSelected(entities); + selectionService->addAllSelected(entities); }), - ShortcutDTO("Save", ImGuiMod_Ctrl | ImGuiKey_S, [] { - CTX.save(); + ShortcutDTO("Save", ImGuiMod_Ctrl | ImGuiKey_S, [this] { + directoryService->save(); }), }; } @@ -41,11 +42,11 @@ namespace Metal { if (ImGui::BeginPopupContextItem((id + "contextMenu").c_str())) { if (ImGui::MenuItem("Delete")) { std::vector entities; - for (auto &entry: CTX.editorRepository.selected) { + for (auto &entry: editorRepository->selected) { entities.push_back(entry.first); } - CTX.worldRepository.deleteEntities(entities); - CTX.selectionService.clearSelection(); + world->deleteEntities(entities); + selectionService->clearSelection(); } ImGui::EndPopup(); } @@ -73,7 +74,7 @@ namespace Metal { ImGui::EndTable(); } - if (!CTX.editorRepository.selected.empty()) { + if (!editorRepository->selected.empty()) { contextMenu(); } } @@ -172,7 +173,7 @@ namespace Metal { const bool isVisible = !world->hiddenEntities.contains(entityId); if (UIUtil::ButtonSimple((isVisible ? Icons::visibility : Icons::visibility_off) + ("##v") + std::to_string(static_cast(entt::to_integral(entityId))) + id, 20, 15)) { - CTX.worldRepository.changeVisibility(entityId, !isVisible); + world->changeVisibility(entityId, !isVisible); } ImGui::PopStyleColor(); ImGui::PopStyleVar(2); @@ -182,9 +183,9 @@ namespace Metal { void WorldPanel::handleClick(const entt::entity entityId) const { if (ImGui::IsItemClicked()) { if (const bool isMultiSelect = ImGui::IsKeyDown(ImGuiKey_LeftCtrl); !isMultiSelect) { - CTX.selectionService.clearSelection(); + selectionService->clearSelection(); } - CTX.selectionService.addSelected(entityId); + selectionService->addSelected(entityId); } } diff --git a/src/context/editor/dock-spaces/world/WorldPanel.h b/src/editor/dock-spaces/world/WorldPanel.h similarity index 74% rename from src/context/editor/dock-spaces/world/WorldPanel.h rename to src/editor/dock-spaces/world/WorldPanel.h index a6e87e81..37a33934 100644 --- a/src/context/editor/dock-spaces/world/WorldPanel.h +++ b/src/editor/dock-spaces/world/WorldPanel.h @@ -3,8 +3,8 @@ #include #include -#include "../../../../enum/engine-definitions.h" -#include "../../../../enum/ComponentType.h" +#include "../../enum/engine-definitions.h" +#include "../../../engine/enum/ComponentType.h" #include "../docks/AbstractDockPanel.h" namespace Metal { @@ -13,6 +13,8 @@ namespace Metal { struct AbstractComponent; struct MetadataComponent; class WorldHeaderPanel; + class SelectionService; + struct DirectoryService; class WorldPanel final : public AbstractDockPanel { static constexpr auto TRANSPARENT = ImVec4(0, 0, 0, 0); @@ -26,7 +28,19 @@ namespace Metal { EditorRepository *editorRepository = nullptr; bool isSomethingHovered = false; + SelectionService *selectionService = nullptr; + DirectoryService *directoryService = nullptr; + public: + std::vector getDependencies() override { + return { + {"WorldRepository", &world}, + {"EditorRepository", &editorRepository}, + {"SelectionService", &selectionService}, + {"DirectoryService", &directoryService} + }; + } + void onInitialize() override; void contextMenu() const; diff --git a/src/service/notification/AsyncTask.h b/src/editor/dto/AsyncTask.h similarity index 100% rename from src/service/notification/AsyncTask.h rename to src/editor/dto/AsyncTask.h diff --git a/src/repository/dock/DockDTO.h b/src/editor/dto/DockDTO.h similarity index 95% rename from src/repository/dock/DockDTO.h rename to src/editor/dto/DockDTO.h index 60a8109f..1d3b84f3 100644 --- a/src/repository/dock/DockDTO.h +++ b/src/editor/dto/DockDTO.h @@ -5,8 +5,7 @@ #include #include #include "DockSpace.h" -#include "DockPosition.h" -#include "../../util/Util.h" +#include "../util/Util.h" namespace Metal { struct DockDTO { diff --git a/src/editor/dto/DockSpace.cpp b/src/editor/dto/DockSpace.cpp new file mode 100644 index 00000000..52ce8b7e --- /dev/null +++ b/src/editor/dto/DockSpace.cpp @@ -0,0 +1,39 @@ +#include "DockSpace.h" +#include "../../common/Icons.h" +#include "../dock-spaces/console/ConsolePanel.h" +#include "../dock-spaces/files/FilesPanel.h" +#include "../dock-spaces/metrics/MetricsPanel.h" +#include "../dock-spaces/repositories/RepositoriesPanel.h" +#include "../dock-spaces/inspector/InspectorPanel.h" +#include "../dock-spaces/viewport/ViewportPanel.h" +#include "../dock-spaces/world/WorldPanel.h" + +#define CB(clazz) []() { return new clazz; } + +namespace Metal { + DockSpace DockSpace::VIEWPORT{-1, "Viewport", Icons::ipublic, 0, 0,CB(ViewportPanel)}; + DockSpace DockSpace::INSPECTOR{0, "Inspector", Icons::search, 4, 4,CB(InspectorPanel)}; + DockSpace DockSpace::WORLD{1, "World", Icons::account_tree, 4, 4, CB(WorldPanel)}; + DockSpace DockSpace::CONSOLE{2, "Console", Icons::terminal, 4, 4, CB(ConsolePanel)}; + DockSpace DockSpace::FILES{3, "Files", Icons::folder_open, 4, 4, CB(FilesPanel)}; + DockSpace DockSpace::METRICS{4, "Metrics", Icons::analytics, 4, 4, CB(MetricsPanel)}; + DockSpace DockSpace::REPOSITORIES{5, "Repositories", Icons::search, 4, 4, CB(RepositoriesPanel)}; + + const std::vector DockSpace::OPTIONS_LIST = { + &INSPECTOR, + &WORLD, + &CONSOLE, + &FILES, + &METRICS, + &REPOSITORIES + }; + + DockSpace *DockSpace::GetOption(const int selected) { + for (auto *option: OPTIONS_LIST) { + if (option->index == selected) { + return option; + } + } + return nullptr; + } +} diff --git a/src/repository/dock/DockSpace.h b/src/editor/dto/DockSpace.h similarity index 94% rename from src/repository/dock/DockSpace.h rename to src/editor/dto/DockSpace.h index 25b2dcd8..98fedeb0 100644 --- a/src/repository/dock/DockSpace.h +++ b/src/editor/dto/DockSpace.h @@ -1,6 +1,7 @@ #ifndef METAL_ENGINE_DOCKSPACE_H #define METAL_ENGINE_DOCKSPACE_H +#include #include #include @@ -15,7 +16,8 @@ namespace Metal { static DockSpace FILES; static DockSpace METRICS; static DockSpace REPOSITORIES; - static const char *OPTIONS; + + static const std::vector OPTIONS_LIST; const int index; const std::string name; diff --git a/src/dto/file/EntryMetadata.h b/src/editor/dto/EntryMetadata.h similarity index 86% rename from src/dto/file/EntryMetadata.h rename to src/editor/dto/EntryMetadata.h index e16e5628..72b99a55 100644 --- a/src/dto/file/EntryMetadata.h +++ b/src/editor/dto/EntryMetadata.h @@ -2,12 +2,12 @@ #define FILEMETADATA_H #include -#include "../../util/Util.h" -#include "../../enum/EntryType.h" -#include "../../util/Serializable.h" +#include "../util/Util.h" +#include "../enum/EntryType.h" +#include "../../common//ISerialize.h" namespace Metal { - struct EntryMetadata : Serializable { + struct EntryMetadata : ISerialize { protected: std::string id = Util::uuidV4(); diff --git a/src/dto/file/FSEntry.h b/src/editor/dto/FSEntry.h similarity index 95% rename from src/dto/file/FSEntry.h rename to src/editor/dto/FSEntry.h index 099b3b1a..03cd72c4 100644 --- a/src/dto/file/FSEntry.h +++ b/src/editor/dto/FSEntry.h @@ -2,7 +2,7 @@ #define FILEENTRY_H #include -#include "../../util/Util.h" +#include "../util/Util.h" #include "EntryMetadata.h" namespace Metal { diff --git a/src/dto/push-constant/GridPushConstant.h b/src/editor/dto/GridPushConstant.h similarity index 100% rename from src/dto/push-constant/GridPushConstant.h rename to src/editor/dto/GridPushConstant.h diff --git a/src/dto/file/ImportSettingsDTO.h b/src/editor/dto/ImportSettingsDTO.h similarity index 86% rename from src/dto/file/ImportSettingsDTO.h rename to src/editor/dto/ImportSettingsDTO.h index 403ba57e..061b3a4f 100644 --- a/src/dto/file/ImportSettingsDTO.h +++ b/src/editor/dto/ImportSettingsDTO.h @@ -1,7 +1,7 @@ #ifndef IMPORTSETTINGSDTO_H #define IMPORTSETTINGSDTO_H -#include "../../common/inspection/Inspectable.h" +#include "../../common//Inspectable.h" namespace Metal { diff --git a/src/dto/Notification.h b/src/editor/dto/Notification.h similarity index 100% rename from src/dto/Notification.h rename to src/editor/dto/Notification.h diff --git a/src/service/voxel/impl/OctreeNode.cpp b/src/editor/dto/OctreeNode.cpp similarity index 100% rename from src/service/voxel/impl/OctreeNode.cpp rename to src/editor/dto/OctreeNode.cpp diff --git a/src/service/voxel/impl/OctreeNode.h b/src/editor/dto/OctreeNode.h similarity index 97% rename from src/service/voxel/impl/OctreeNode.h rename to src/editor/dto/OctreeNode.h index 134d7bb5..6844a46f 100644 --- a/src/service/voxel/impl/OctreeNode.h +++ b/src/editor/dto/OctreeNode.h @@ -3,7 +3,7 @@ #include #include -#include "VoxelData.h" +#include "../../engine/dto/VoxelData.h" namespace Metal { struct OctreeNode final { diff --git a/src/service/mesh/SceneData.h b/src/editor/dto/SceneData.h similarity index 91% rename from src/service/mesh/SceneData.h rename to src/editor/dto/SceneData.h index 852bbd8f..894b3f80 100644 --- a/src/service/mesh/SceneData.h +++ b/src/editor/dto/SceneData.h @@ -3,11 +3,11 @@ #include #include "SceneEntityData.h" -#include "../../util/Serializable.h" +#include "../../common//ISerialize.h" namespace Metal { - struct SceneData final : Serializable { + struct SceneData final : ISerialize { std::vector entities; std::string name; diff --git a/src/service/mesh/SceneEntityData.h b/src/editor/dto/SceneEntityData.h similarity index 78% rename from src/service/mesh/SceneEntityData.h rename to src/editor/dto/SceneEntityData.h index 0e60b9f8..0fbda6e6 100644 --- a/src/service/mesh/SceneEntityData.h +++ b/src/editor/dto/SceneEntityData.h @@ -1,13 +1,13 @@ #ifndef METAL_ENGINE_SCENEENTITYDATA_H #define METAL_ENGINE_SCENEENTITYDATA_H #include -#include "../../repository/world/components/PrimitiveComponent.h" -#include "../../repository/world/components/TransformComponent.h" -#include "../../repository/world/impl/MetadataComponent.h" +#include "../../engine/dto/PrimitiveComponent.h" +#include "../../engine/dto/TransformComponent.h" +#include "../../engine/dto/MetadataComponent.h" namespace Metal { - struct SceneEntityData final : Serializable { + struct SceneEntityData final : ISerialize { MetadataComponent entity; TransformComponent transform; std::optional primitive; diff --git a/src/dto/file/SceneImportSettingsDTO.h b/src/editor/dto/SceneImportSettingsDTO.h similarity index 100% rename from src/dto/file/SceneImportSettingsDTO.h rename to src/editor/dto/SceneImportSettingsDTO.h diff --git a/src/dto/push-constant/SelectedDotPushConstant.h b/src/editor/dto/SelectedDotPushConstant.h similarity index 100% rename from src/dto/push-constant/SelectedDotPushConstant.h rename to src/editor/dto/SelectedDotPushConstant.h diff --git a/src/dto/ShortcutDTO.h b/src/editor/dto/ShortcutDTO.h similarity index 100% rename from src/dto/ShortcutDTO.h rename to src/editor/dto/ShortcutDTO.h diff --git a/src/service/voxel/impl/SparseVoxelOctreeBuilder.cpp b/src/editor/dto/SparseVoxelOctreeBuilder.cpp similarity index 100% rename from src/service/voxel/impl/SparseVoxelOctreeBuilder.cpp rename to src/editor/dto/SparseVoxelOctreeBuilder.cpp diff --git a/src/service/voxel/impl/SparseVoxelOctreeBuilder.h b/src/editor/dto/SparseVoxelOctreeBuilder.h similarity index 95% rename from src/service/voxel/impl/SparseVoxelOctreeBuilder.h rename to src/editor/dto/SparseVoxelOctreeBuilder.h index 470fdd9f..d329476b 100644 --- a/src/service/voxel/impl/SparseVoxelOctreeBuilder.h +++ b/src/editor/dto/SparseVoxelOctreeBuilder.h @@ -2,7 +2,7 @@ #define SPARSEVOXELOCTREE_H #include "OctreeNode.h" -#include "../../../repository/world/impl/BoundingBox.h" +#include "../../engine/dto/BoundingBox.h" namespace Metal { class SparseVoxelOctreeBuilder; diff --git a/src/enum/EngineResourceIDs.h b/src/editor/enum/EngineResourceIDs.h similarity index 100% rename from src/enum/EngineResourceIDs.h rename to src/editor/enum/EngineResourceIDs.h diff --git a/src/editor/enum/EntryType.h b/src/editor/enum/EntryType.h new file mode 100644 index 00000000..ed82b7ea --- /dev/null +++ b/src/editor/enum/EntryType.h @@ -0,0 +1,42 @@ +#ifndef FILETYPE_H +#define FILETYPE_H + +#include +#include +#include "../../common/Icons.h" + +namespace Metal::EntryType { + enum EntryType { + SCENE, + MESH, + TEXTURE, + VOLUME, + DIRECTORY, + NONE + }; + + struct EntryTypeDTO { + EntryType type; + std::string name; + std::string icon; + }; + + static const std::vector ENTRIES = { + {SCENE, "Scene", Icons::image}, + {MESH, "Mesh", Icons::view_in_ar}, + {TEXTURE, "Texture", Icons::texture}, + {VOLUME, "Volume", Icons::view_agenda}, + {DIRECTORY, "Directory", Icons::folder}, + {NONE, "None", Icons::close} + }; + + static const EntryTypeDTO& GetDTO(EntryType type) { + for (const auto& dto : ENTRIES) { + if (dto.type == type) { + return dto; + } + } + return ENTRIES.back(); // Return NONE + } +} +#endif diff --git a/src/enum/NotificationSeverity.h b/src/editor/enum/NotificationSeverity.h similarity index 96% rename from src/enum/NotificationSeverity.h rename to src/editor/enum/NotificationSeverity.h index 53806f6d..e15d107e 100644 --- a/src/enum/NotificationSeverity.h +++ b/src/editor/enum/NotificationSeverity.h @@ -2,7 +2,7 @@ #define NOTIFICATIONSEVERITY_H #include -#include "../common/interface/Icons.h" +#include "../../common/Icons.h" namespace Metal::NotificationSeverities { enum NotificationSeverity { diff --git a/src/enum/ShadingMode.h b/src/editor/enum/ShadingMode.h similarity index 98% rename from src/enum/ShadingMode.h rename to src/editor/enum/ShadingMode.h index 4a296079..3a949993 100644 --- a/src/enum/ShadingMode.h +++ b/src/editor/enum/ShadingMode.h @@ -4,7 +4,7 @@ #include #include -#include "../common/interface/Icons.h" +#include "../../common/Icons.h" namespace Metal { enum ShadingMode { diff --git a/src/enum/engine-definitions.h b/src/editor/enum/engine-definitions.h similarity index 97% rename from src/enum/engine-definitions.h rename to src/editor/enum/engine-definitions.h index cb8984f8..a92a1a39 100644 --- a/src/enum/engine-definitions.h +++ b/src/editor/enum/engine-definitions.h @@ -4,9 +4,10 @@ #include #define MAX_VOLUMES 300 #define MAX_LIGHTS 300 -#define MAX_MATERIALS 100 #define MAX_MESH_INSTANCES 1000 #define EMPTY_ENTITY entt::null +#define LARGE_FONT_SIZE 38 + #define FILE_METADATA ".mjson" #define FILE_SCENE "-scene" #define FILE_MESH "-mesh" diff --git a/src/context/editor/panel/FileImportModalPanel.cpp b/src/editor/panel/FileImportModalPanel.cpp similarity index 72% rename from src/context/editor/panel/FileImportModalPanel.cpp rename to src/editor/panel/FileImportModalPanel.cpp index 2e22bab1..832b4828 100644 --- a/src/context/editor/panel/FileImportModalPanel.cpp +++ b/src/editor/panel/FileImportModalPanel.cpp @@ -1,27 +1,30 @@ #include "FileImportModalPanel.h" - #include #include #include "../../ApplicationContext.h" -#include "../../../util/FilesUtil.h" +#include "../../common/FilesUtil.h" #include "../abstract/form/FormPanel.h" +#include "../repository/EditorRepository.h" +#include "../service/FileImporterService.h" +#include "../service/NotificationService.h" +#include "../service/FilesService.h" +#include "../dto/FSEntry.h" namespace Metal { void FileImportModalPanel::onInitialize() { formPanel = new FormPanel(); - appendChild(formPanel); + initializePanel(formPanel); } void FileImportModalPanel::onSync() { - auto &editorRepository = CTX.editorRepository; - if (editorRepository.pendingImports.empty()) { + if (editorRepository->pendingImports.empty()) { isFirst = true; return; } if (isFirst) { formPanel->setInspection( - editorRepository.importSettingsMap.at(editorRepository.selectedFileForSettings).get()); + editorRepository->importSettingsMap.at(editorRepository->selectedFileForSettings).get()); isFirst = false; } @@ -50,16 +53,16 @@ namespace Metal { ImGui::TableSetupColumn("Size", ImGuiTableColumnFlags_WidthFixed, 80.0f); ImGui::TableHeadersRow(); - for (const auto &filePath: editorRepository.pendingImports) { + for (const auto &filePath: editorRepository->pendingImports) { std::filesystem::path p(filePath); ImGui::TableNextRow(); ImGui::TableNextColumn(); - bool isSelected = (editorRepository.selectedFileForSettings == filePath); + bool isSelected = (editorRepository->selectedFileForSettings == filePath); if (ImGui::Selectable(p.filename().string().c_str(), isSelected, ImGuiSelectableFlags_SpanAllColumns)) { - editorRepository.selectedFileForSettings = filePath; + editorRepository->selectedFileForSettings = filePath; formPanel->setInspection( - editorRepository.importSettingsMap.at(editorRepository.selectedFileForSettings). + editorRepository->importSettingsMap.at(editorRepository->selectedFileForSettings). get()); } ImGui::TableNextColumn(); @@ -76,7 +79,7 @@ namespace Metal { ImGui::TableNextColumn(); ImGui::Text("Settings: %s", - std::filesystem::path(editorRepository.selectedFileForSettings).filename().string(). + std::filesystem::path(editorRepository->selectedFileForSettings).filename().string(). c_str()); ImGui::BeginChild((id + "SettingsFormChild").c_str(), ImVec2(0, maxHeight - 180.0f), true); formPanel->onSync(); @@ -90,20 +93,20 @@ namespace Metal { ImGui::Spacing(); if (ImGui::Button(("Approve" + id + "approveImport").c_str(), ImVec2(120, 0))) { - for (const std::string &file: editorRepository.pendingImports) { - CTX.fileImporterService.importFile(editorRepository.targetImportDirectory->absolutePath, file, - editorRepository.importSettingsMap.at(file)); + for (const std::string &file: editorRepository->pendingImports) { + fileImporterService->importFile(editorRepository->targetImportDirectory->absolutePath, file, + editorRepository->importSettingsMap.at(file)); } - CTX.notificationService.pushMessage("Importing files...", NotificationSeverities::WARNING); - FilesService::GetEntries(editorRepository.targetImportDirectory); - editorRepository.pendingImports.clear(); - editorRepository.importSettingsMap.clear(); + notificationService->pushMessage("Importing files...", NotificationSeverities::WARNING); + filesService->GetEntries(editorRepository->targetImportDirectory); + editorRepository->pendingImports.clear(); + editorRepository->importSettingsMap.clear(); formPanel->resetForm(); } ImGui::SameLine(); if (ImGui::Button(("Cancel" + id + "cancel").c_str(), ImVec2(120, 0))) { - editorRepository.pendingImports.clear(); - editorRepository.importSettingsMap.clear(); + editorRepository->pendingImports.clear(); + editorRepository->importSettingsMap.clear(); formPanel->resetForm(); } } diff --git a/src/editor/panel/FileImportModalPanel.h b/src/editor/panel/FileImportModalPanel.h new file mode 100644 index 00000000..fa9a75e5 --- /dev/null +++ b/src/editor/panel/FileImportModalPanel.h @@ -0,0 +1,37 @@ +#ifndef METAL_ENGINE_FILEIMPORTMODALPANEL_H +#define METAL_ENGINE_FILEIMPORTMODALPANEL_H +#include "../abstract/AbstractPanel.h" + +namespace Metal { + class FilesService; + class FormPanel; + struct EditorRepository; + class FileImporterService; + class NotificationService; + + class FileImportModalPanel final : public AbstractPanel { + FormPanel *formPanel = nullptr; + bool isFirst = false; + + EditorRepository *editorRepository = nullptr; + FileImporterService *fileImporterService = nullptr; + NotificationService *notificationService = nullptr; + FilesService *filesService = nullptr; + + public: + std::vector getDependencies() override { + return { + {"EditorRepository", &editorRepository}, + {"FileImporterService", &fileImporterService}, + {"NotificationService", ¬ificationService}, + {"FilesService", &filesService} + }; + } + + void onInitialize() override; + + void onSync() override; + }; +} // Metal + +#endif //METAL_ENGINE_FILEIMPORTMODALPANEL_H diff --git a/src/context/editor/panel/NotificationsPanel.cpp b/src/editor/panel/NotificationsPanel.cpp similarity index 70% rename from src/context/editor/panel/NotificationsPanel.cpp rename to src/editor/panel/NotificationsPanel.cpp index 51fc259d..8e954514 100644 --- a/src/context/editor/panel/NotificationsPanel.cpp +++ b/src/editor/panel/NotificationsPanel.cpp @@ -1,23 +1,25 @@ #include "NotificationsPanel.h" #include #include "../../ApplicationContext.h" -#include "../../../util/UIUtil.h" -#include "../../../dto/Notification.h" +#include "../util/UIUtil.h" +#include "../dto/Notification.h" +#include "../service/NotificationService.h" +#include "../../engine/EngineContext.h" namespace Metal { void NotificationsPanel::onSync() { int usedIndices = 0; - for (int i = 0; i < CTX.notificationService.getNotifications().size(); i++) { - auto *notification = CTX.notificationService.getNotifications()[i]; + for (int i = 0; i < notificationService->getNotifications().size(); i++) { + auto *notification = notificationService->getNotifications()[i]; if (notification == nullptr) { continue; } if (notification->displayTime < 0) { - notification->displayTime = CTX.engineContext.currentTimeMs; + notification->displayTime = engineContext->currentTimeMs; } - if (CTX.engineContext.currentTimeMs - notification->displayTime > MESSAGE_DURATION) { + if (engineContext->currentTimeMs - notification->displayTime > MESSAGE_DURATION) { delete notification; - CTX.notificationService.getNotifications()[i] = nullptr; + notificationService->getNotifications()[i] = nullptr; continue; } ImGui::SetNextWindowPos(ImVec2(5, ImGui::GetMainViewport()->Size.y - 40 * (usedIndices + 1))); diff --git a/src/editor/panel/NotificationsPanel.h b/src/editor/panel/NotificationsPanel.h new file mode 100644 index 00000000..afdf6091 --- /dev/null +++ b/src/editor/panel/NotificationsPanel.h @@ -0,0 +1,25 @@ +#ifndef METAL_ENGINE_NOTIFICATIONSPANEL_H +#define METAL_ENGINE_NOTIFICATIONSPANEL_H +#include "../abstract/AbstractPanel.h" + +namespace Metal { + class NotificationService; + class EngineContext; + + class NotificationsPanel final : public AbstractPanel { + NotificationService *notificationService = nullptr; + EngineContext *engineContext = nullptr; + + public: + std::vector getDependencies() override { + return { + {"NotificationService", ¬ificationService}, + {"EngineContext", &engineContext} + }; + } + + void onSync() override; + }; +} // Metal + +#endif //METAL_ENGINE_NOTIFICATIONSPANEL_H diff --git a/src/context/engine/render-pass/impl/tools/GridPass.cpp b/src/editor/passes/GridPass.cpp similarity index 55% rename from src/context/engine/render-pass/impl/tools/GridPass.cpp rename to src/editor/passes/GridPass.cpp index 77eabed2..4a919feb 100644 --- a/src/context/engine/render-pass/impl/tools/GridPass.cpp +++ b/src/editor/passes/GridPass.cpp @@ -1,8 +1,8 @@ #include "GridPass.h" - -#include "../../../../../context/ApplicationContext.h" -#include "../../../../../service/pipeline/PipelineBuilder.h" -#include "../../../../../enum/EngineResourceIDs.h" +#include "../../engine/dto/PipelineBuilder.h" +#include "../../engine/service/PipelineService.h" +#include "../repository/EditorRepository.h" +#include "../enum/EngineResourceIDs.h" namespace Metal { void GridPass::onInitialize() { @@ -15,18 +15,18 @@ namespace Metal { .setPushConstantsSize(sizeof(GridPushConstant)) .addBufferBinding(getScopedResourceId(RID_GLOBAL_DATA)) .addStorageImageBinding(getScopedResourceId(RID_GBUFFER_POSITION_INDEX)); - pipelineInstance = CTX.pipelineService.createPipeline(gridPipelineBuilder); + pipelineInstance = pipelineService->createPipeline(gridPipelineBuilder); } bool GridPass::shouldRun() { - return CTX.isDebugMode() && CTX.editorRepository.showGrid; + return editorRepository->showGrid; } void GridPass::onSync() { - pushConstant.scale = CTX.editorRepository.gridScale; - pushConstant.overlayObjects = CTX.editorRepository.gridOverlayObjects; - pushConstant.threshold = CTX.editorRepository.gridThreshold; - pushConstant.thickness = CTX.editorRepository.gridThickness; + pushConstant.scale = editorRepository->gridScale; + pushConstant.overlayObjects = editorRepository->gridOverlayObjects; + pushConstant.threshold = editorRepository->gridThreshold; + pushConstant.thickness = editorRepository->gridThickness; recordPushConstant(&pushConstant); recordDrawSimpleInstanced(3, 1); } diff --git a/src/editor/passes/GridPass.h b/src/editor/passes/GridPass.h new file mode 100644 index 00000000..4be4e4c5 --- /dev/null +++ b/src/editor/passes/GridPass.h @@ -0,0 +1,32 @@ +#ifndef GRIDRENDERPASS_H +#define GRIDRENDERPASS_H +#include "../../engine/passes/AbstractRenderPass.h" +#include "../dto/GridPushConstant.h" + +namespace Metal { + class PipelineService; + struct EditorRepository; + + class GridPass final : public AbstractRenderPass { + GridPushConstant pushConstant{}; + + PipelineService *pipelineService = nullptr; + EditorRepository *editorRepository = nullptr; + + public: + std::vector getDependencies() override { + return { + {"PipelineService", &pipelineService}, + {"EditorRepository", &editorRepository} + }; + } + + void onInitialize() override; + + bool shouldRun() override; + + void onSync() override; + }; +} // Metal + +#endif //GRIDRENDERPASS_H diff --git a/src/editor/passes/SelectionIDPass.cpp b/src/editor/passes/SelectionIDPass.cpp new file mode 100644 index 00000000..9a917ae0 --- /dev/null +++ b/src/editor/passes/SelectionIDPass.cpp @@ -0,0 +1,60 @@ +#include "SelectionIDPass.h" +#include "../../engine/dto/TransformComponent.h" +#include "../../engine/dto/PrimitiveComponent.h" +#include "../dto/SelectedDotPushConstant.h" +#include "../../engine/dto/PipelineBuilder.h" +#include "../../engine/service/PipelineService.h" +#include "../repository/EditorRepository.h" +#include "../../engine/repository/WorldRepository.h" +#include "../../engine/service/MeshService.h" +#include "../enum/EngineResourceIDs.h" + +namespace Metal { + void SelectionIDPass::onInitialize() { + PipelineBuilder builder = PipelineBuilder::Of( + getScopedResourceId(RID_SELECTION_FBO), + "tools/SelectionID.vert", + "tools/SelectionID.frag" + ) + .setPrepareForMesh() + .setCullMode(VK_CULL_MODE_NONE) + .setPushConstantsSize(sizeof(SelectedDotPushConstant)) + .addBufferBinding(getScopedResourceId(RID_GLOBAL_DATA)); + pipelineInstance = pipelineService->createPipeline(builder); + } + + bool SelectionIDPass::shouldRun() { + return !editorRepository->selected.empty(); + } + + void SelectionIDPass::onSync() { + for (auto const& [entityId, selected] : editorRepository->selected) { + if (!selected) { + continue; + } + if (!worldRepository->registry.all_of(entityId) || !worldRepository->registry.all_of(entityId)) { + continue; + } + + const auto &mesh = worldRepository->registry.get(entityId); + if (mesh.meshId.empty()) { + continue; + } + if (worldRepository->hiddenEntities.contains(entityId)) { + continue; + } + + const auto *meshInstance = meshService->stream(mesh.meshId); + if (!meshInstance) { + continue; + } + + pushConstant.model = worldRepository->registry.get(entityId).model; + pushConstant.selectionColor = glm::vec4(editorRepository->selectionColor, editorRepository->selectionOutlineThickness); + pushConstant.renderIndex = mesh.renderIndex; + + recordPushConstant(&pushConstant); + recordDrawMesh(meshInstance); + } + } +} // Metal diff --git a/src/editor/passes/SelectionIDPass.h b/src/editor/passes/SelectionIDPass.h new file mode 100644 index 00000000..0bf55bf6 --- /dev/null +++ b/src/editor/passes/SelectionIDPass.h @@ -0,0 +1,39 @@ +#ifndef SELECTIONIDPASS_H +#define SELECTIONIDPASS_H + +#include "../../engine/passes/AbstractRenderPass.h" +#include "../dto/SelectedDotPushConstant.h" + +namespace Metal { + class PipelineService; + struct EditorRepository; + struct WorldRepository; + class MeshService; + + class SelectionIDPass final : public AbstractRenderPass { + SelectedDotPushConstant pushConstant{}; + + PipelineService *pipelineService = nullptr; + EditorRepository *editorRepository = nullptr; + WorldRepository *worldRepository = nullptr; + MeshService *meshService = nullptr; + + public: + std::vector getDependencies() override { + return { + {"PipelineService", &pipelineService}, + {"EditorRepository", &editorRepository}, + {"WorldRepository", &worldRepository}, + {"MeshService", &meshService} + }; + } + + void onInitialize() override; + + bool shouldRun() override; + + void onSync() override; + }; +} // Metal + +#endif // SELECTIONIDPASS_H diff --git a/src/editor/passes/SelectionOutlinePass.cpp b/src/editor/passes/SelectionOutlinePass.cpp new file mode 100644 index 00000000..7726eb9e --- /dev/null +++ b/src/editor/passes/SelectionOutlinePass.cpp @@ -0,0 +1,38 @@ +#include "SelectionOutlinePass.h" +#include "../../ApplicationContext.h" +#include "../../engine/dto/TransformComponent.h" +#include "../dto/SelectedDotPushConstant.h" +#include "../../engine/dto/PipelineBuilder.h" +#include "../../engine/service/PipelineService.h" +#include "../repository/EditorRepository.h" +#include "../enum/EngineResourceIDs.h" + +namespace Metal { + void SelectionOutlinePass::onInitialize() { + PipelineBuilder builder = PipelineBuilder::Of( + getScopedResourceId(RID_POST_PROCESSING_FBO), + "QUAD.vert", + "tools/SelectionOutline.frag" + ) + .setBlendEnabled() + .setPushConstantsSize(sizeof(SelectedDotPushConstant)) + .addBufferBinding(getScopedResourceId(RID_GLOBAL_DATA)) + .addFboBinding(getScopedResourceId(RID_SELECTION_FBO), 0); + pipelineInstance = pipelineService->createPipeline(builder); + } + + bool SelectionOutlinePass::shouldRun() { + return !editorRepository->selected.empty(); + } + + void SelectionOutlinePass::onSync() { + + pushConstant.selectionColor.x = editorRepository->selectionColor.x; + pushConstant.selectionColor.y = editorRepository->selectionColor.y; + pushConstant.selectionColor.z = editorRepository->selectionColor.z; + pushConstant.selectionColor.w = editorRepository->selectionOutlineThickness; + + recordPushConstant(&pushConstant); + recordDrawSimpleInstanced(3, 1); + } +} // Metal diff --git a/src/editor/passes/SelectionOutlinePass.h b/src/editor/passes/SelectionOutlinePass.h new file mode 100644 index 00000000..8a9ccac5 --- /dev/null +++ b/src/editor/passes/SelectionOutlinePass.h @@ -0,0 +1,33 @@ +#ifndef SELECTEDDOTPASS_H +#define SELECTEDDOTPASS_H + +#include "../../engine/passes/AbstractRenderPass.h" +#include "../dto/SelectedDotPushConstant.h" + +namespace Metal { + class PipelineService; + struct EditorRepository; + + class SelectionOutlinePass final : public AbstractRenderPass { + SelectedDotPushConstant pushConstant{}; + + PipelineService *pipelineService = nullptr; + EditorRepository *editorRepository = nullptr; + + public: + std::vector getDependencies() override { + return { + {"PipelineService", &pipelineService}, + {"EditorRepository", &editorRepository} + }; + } + + void onInitialize() override; + + bool shouldRun() override; + + void onSync() override; + }; +} // Metal + +#endif // SELECTEDDOTPASS_H diff --git a/src/repository/editor/EditorRepository.cpp b/src/editor/repository/EditorRepository.cpp similarity index 94% rename from src/repository/editor/EditorRepository.cpp rename to src/editor/repository/EditorRepository.cpp index 84c7cea2..aff132b3 100644 --- a/src/repository/editor/EditorRepository.cpp +++ b/src/editor/repository/EditorRepository.cpp @@ -1,5 +1,5 @@ #include "EditorRepository.h" -#include "../../common/interface/Icons.h" +#include "../../common/Icons.h" namespace Metal { const char *EditorRepository::getTitle() { @@ -35,14 +35,14 @@ namespace Metal { j["gizmoUseSnapRotate"] = gizmoUseSnapRotate; j["gizmoUseSnapScale"] = gizmoUseSnapScale; j["showOnlyEntitiesHierarchy"] = showOnlyEntitiesHierarchy; - j["mainSelection"] = static_cast(entt::to_integral(mainSelection)); + j["mainSelection"] = entt::to_integral(mainSelection); j["selected"] = nlohmann::json::array(); for (auto const& [key, val] : selected) { - j["selected"].push_back(static_cast(entt::to_integral(key))); + j["selected"].push_back(entt::to_integral(key)); } j["copied"] = nlohmann::json::array(); for (auto const& entity : copied) { - j["copied"].push_back(static_cast(entt::to_integral(entity))); + j["copied"].push_back(entt::to_integral(entity)); } j["shadingMode"] = shadingMode; return j; diff --git a/src/repository/editor/EditorRepository.h b/src/editor/repository/EditorRepository.h similarity index 88% rename from src/repository/editor/EditorRepository.h rename to src/editor/repository/EditorRepository.h index 95ae4ac5..f3133dac 100644 --- a/src/repository/editor/EditorRepository.h +++ b/src/editor/repository/EditorRepository.h @@ -6,18 +6,17 @@ #include #include -#include "../../dto/ShortcutDTO.h" -#include "../../enum/engine-definitions.h" -#include "../../enum/ShadingMode.h" -#include "../../common/inspection/Inspectable.h" -#include "../../util/Serializable.h" +#include "../dto/ShortcutDTO.h" +#include "../enum/engine-definitions.h" +#include "../enum/ShadingMode.h" +#include "../../common/IRepository.h" namespace Metal { struct TransformComponent; struct FSEntry; struct ImportSettingsDTO; - struct EditorRepository final : Inspectable, Serializable { + struct EditorRepository final : IRepository { ImVec4 accent{}; ImU32 accentU32 = 0; diff --git a/src/service/notification/AsyncTaskService.cpp b/src/editor/service/AsyncTaskService.cpp similarity index 93% rename from src/service/notification/AsyncTaskService.cpp rename to src/editor/service/AsyncTaskService.cpp index 334b3c42..eb03ec42 100644 --- a/src/service/notification/AsyncTaskService.cpp +++ b/src/editor/service/AsyncTaskService.cpp @@ -1,8 +1,8 @@ #include "AsyncTaskService.h" #include #include -#include "../../util/Util.h" -#include "AsyncTask.h" +#include "../util/Util.h" +#include "../dto/AsyncTask.h" namespace Metal { std::string AsyncTaskService::registerTask(const std::string &name, std::function cancel) { @@ -40,7 +40,7 @@ namespace Metal { return !tasks.empty(); } - void AsyncTaskService::endAll() { + void AsyncTaskService::dispose() { for (std::shared_ptr &task: tasksArray) { endTask(task->id, true); } diff --git a/src/service/notification/AsyncTaskService.h b/src/editor/service/AsyncTaskService.h similarity index 75% rename from src/service/notification/AsyncTaskService.h rename to src/editor/service/AsyncTaskService.h index f95581b0..5ca1a64d 100644 --- a/src/service/notification/AsyncTaskService.h +++ b/src/editor/service/AsyncTaskService.h @@ -4,12 +4,14 @@ #include #include #include -#include #include -#include "AsyncTask.h" + +#include "../../common/IDisposable.h" +#include "../../common/IService.h" +#include "../dto/AsyncTask.h" namespace Metal { - class AsyncTaskService { + class AsyncTaskService final : public IService, IDisposable{ std::unordered_map > tasks; std::vector > tasksArray; mutable std::mutex tasksMutex; @@ -23,7 +25,7 @@ namespace Metal { bool hasActiveTasks(); - void endAll(); + void dispose() override; }; } diff --git a/src/service/dock/DockService.cpp b/src/editor/service/DockService.cpp similarity index 74% rename from src/service/dock/DockService.cpp rename to src/editor/service/DockService.cpp index ee1ab8e4..cf2f9182 100644 --- a/src/service/dock/DockService.cpp +++ b/src/editor/service/DockService.cpp @@ -1,22 +1,43 @@ #include #include #include "DockService.h" -#include "../../repository/dock/DockDTO.h" -#include "../../context/editor/abstract/AbstractPanel.h" -#include "../../context/editor/dock-spaces/docks/AbstractDockPanel.h" -#include "../../context/editor/dock-spaces/docks/DockSpacePanel.h" -#include "../../context/ApplicationContext.h" +#include "../dto/DockDTO.h" +#include "../abstract/AbstractPanel.h" +#include "../dock-spaces/docks/AbstractDockPanel.h" +#include "../dock-spaces/docks/DockSpacePanel.h" +#include "../../ApplicationContext.h" namespace Metal { - void DockService::buildViews(ImGuiID windowId, AbstractPanel *panel) const { + void DockService::onInitialize() { + auto *rightT = new DockDTO{&DockSpace::WORLD}; + auto *leftTop = new DockDTO{&DockSpace::REPOSITORIES}; + auto *leftDown = new DockDTO{&DockSpace::INSPECTOR}; + auto *downLeft = new DockDTO{&DockSpace::CONSOLE}; + auto *downRight = new DockDTO{&DockSpace::FILES}; + + center.sizeRatioForNodeAtDir = 0.5f; + rightT->sizeRatioForNodeAtDir = 0.25f; + leftTop->sizeRatioForNodeAtDir = 0.2f; + leftDown->sizeRatioForNodeAtDir = 0.5f; + downLeft->sizeRatioForNodeAtDir = 0.25f; + downRight->sizeRatioForNodeAtDir = 0.5f; + + right.push_back(rightT); + left.push_back(leftTop); + left.push_back(leftDown); + + bottom.push_back(downLeft); + bottom.push_back(downRight); + } + + void DockService::buildViews(ImGuiID windowId, AbstractPanel *panel) { if (ImGui::GetIO().ConfigFlags & ImGuiConfigFlags_DockingEnable) { - DockRepository &dockRepository = CTX.dockRepository; - if (dockRepository.isInitialized) { + if (isInitialized) { return; } - dockRepository.isInitialized = true; + isInitialized = true; - std::vector toKeep{}; + std::vector toKeep{}; for (auto *child: panel->getChildren()) { auto *p = dynamic_cast(child); if (p == nullptr) { @@ -37,7 +58,6 @@ namespace Metal { ImGui::DockBuilderAddNode(windowId, ImGuiDockNodeFlags_NoTabBar); ImGui::DockBuilderSetNodeSize(windowId, ImGui::GetMainViewport()->Size); - const auto &left = dockRepository.left; for (size_t i = 0; i < left.size(); i++) { DockDTO *dockSpace = left[i]; if (i == 0) { @@ -54,7 +74,6 @@ namespace Metal { addWindow(dockSpace, panel); } - const auto &right = dockRepository.right; for (size_t i = 0; i < right.size(); i++) { DockDTO *dockSpace = right[i]; if (i == 0) { @@ -71,7 +90,6 @@ namespace Metal { addWindow(dockSpace, panel); } - const auto &bottom = dockRepository.bottom; for (size_t i = 0, bottomSize = bottom.size(); i < bottomSize; i++) { DockDTO *dockSpace = bottom[i]; if (i == 0) { @@ -88,10 +106,10 @@ namespace Metal { addWindow(dockSpace, panel); } - dockRepository.center.nodeId = windowId; - addWindow(&dockRepository.center, panel); + center.nodeId = windowId; + addWindow(¢er, panel); - ImGui::DockBuilderDockWindow(dockRepository.center.internalId.c_str(), windowId); + ImGui::DockBuilderDockWindow(center.internalId.c_str(), windowId); ImGui::DockBuilderFinish(windowId); } } @@ -117,10 +135,10 @@ namespace Metal { ImGui::DockBuilderDockWindow(d->internalId.c_str(), d->nodeId); for (auto *l: panel->getChildren()) { if (dynamic_cast(l)) { - panel->appendChild(new DockSpacePanel(dynamic_cast(l), d)); + panel->initializePanel(new DockSpacePanel(dynamic_cast(l), d)); return; } } - panel->appendChild(new DockSpacePanel(nullptr, d)); + panel->initializePanel(new DockSpacePanel(nullptr, d)); } } diff --git a/src/editor/service/DockService.h b/src/editor/service/DockService.h new file mode 100644 index 00000000..c8b8de89 --- /dev/null +++ b/src/editor/service/DockService.h @@ -0,0 +1,32 @@ +#ifndef METAL_ENGINE_DOCKSERVICE_H +#define METAL_ENGINE_DOCKSERVICE_H + +#include "imgui.h" +#include "../dto/DockDTO.h" +#include "../dock-spaces/docks/DockSpacePanel.h" +#include "../../common/IService.h" + +namespace Metal { + class AbstractPanel; + + class DockService final : public IService, public IInit { + DockDTO center{&DockSpace::VIEWPORT}; + std::vector bottom; + std::vector left; + std::vector right; + + + bool isInitialized = false; + + public: + void onInitialize() override; + + void buildViews(ImGuiID windowId, AbstractPanel *panel); + + static void createDockSpace(DockDTO *dockSpace, ImGuiID *dockMainId); + + static void addWindow(DockDTO *d, AbstractPanel *panel); + }; +} // Metal + +#endif diff --git a/src/service/files/FileImporterService.cpp b/src/editor/service/FileImporterService.cpp similarity index 56% rename from src/service/files/FileImporterService.cpp rename to src/editor/service/FileImporterService.cpp index 84244490..55c3d6cd 100644 --- a/src/service/files/FileImporterService.cpp +++ b/src/editor/service/FileImporterService.cpp @@ -1,7 +1,10 @@ #include "FileImporterService.h" - -#include "../../context/ApplicationContext.h" -#include "../log/LogService.h" +#include "SceneImporterService.h" +#include "TextureImporterService.h" +#include "VoxelImporterService.h" +#include "NotificationService.h" +#include "AsyncTaskService.h" +#include "../../common/LoggerUtil.h" #include #include @@ -11,30 +14,30 @@ namespace Metal { const std::shared_ptr &settings) { std::string fileName = file.substr(file.find_last_of(std::filesystem::path::preferred_separator) + 1); runAsync("Import file: " + fileName, - [targetDir, file, fileName, settings](const std::stop_token &token) { + [this, targetDir, file, fileName, settings](const std::stop_token &token) { try { LOG_INFO("Starting file processing: " + fileName); - if (CTX.sceneImporterService.isCompatible(file)) { - CTX.sceneImporterService.importData(targetDir, + if (sceneImporterService->isCompatible(file)) { + sceneImporterService->importData(targetDir, file, settings, token); - } else if (CTX.textureImporter.isCompatible(file)) { - CTX.textureImporter.importData(targetDir, file, settings, token); - } else if (CTX.voxelImporterService.isCompatible(file)) { - CTX.voxelImporterService.importData(targetDir, file, settings, token); + } else if (textureImporterService->isCompatible(file)) { + textureImporterService->importData(targetDir, file, settings, token); + } else if (voxelImporterService->isCompatible(file)) { + voxelImporterService->importData(targetDir, file, settings, token); } LOG_INFO("Successfully imported file: " + fileName); - CTX.notificationService.pushMessage("Successfully imported file: " + fileName, + notificationService->pushMessage("Successfully imported file: " + fileName, NotificationSeverities::SUCCESS); } catch (std::exception &e) { - CTX.notificationService.pushMessage(e.what(), NotificationSeverities::ERROR); + notificationService->pushMessage(e.what(), NotificationSeverities::ERROR); } }); } std::string FileImporterService::runAsync(const std::string &taskName, const LoadingTask &task) const { std::stop_source stopSource; - std::string taskId = CTX.asyncTaskService.registerTask(taskName, [stopSource]() mutable { + std::string taskId = asyncTaskService->registerTask(taskName, [stopSource]() mutable { stopSource.request_stop(); }); @@ -46,7 +49,7 @@ namespace Metal { } catch (...) { LOG_ERROR("Loading task failed with unknown error."); } - CTX.asyncTaskService.endTask(taskId, stopToken.stop_requested()); + asyncTaskService->endTask(taskId, stopToken.stop_requested()); }).detach(); return taskId; @@ -54,13 +57,13 @@ namespace Metal { std::string FileImporterService::collectCompatibleFiles() const { std::string outStr = ""; - for (std::string type: CTX.sceneImporterService.getSupportedTypes()) { + for (std::string type: sceneImporterService->getSupportedTypes()) { outStr += type + ","; }; - for (std::string type: CTX.textureImporter.getSupportedTypes()) { + for (std::string type: textureImporterService->getSupportedTypes()) { outStr += type + ","; }; - for (std::string type: CTX.voxelImporterService.getSupportedTypes()) { + for (std::string type: voxelImporterService->getSupportedTypes()) { outStr += type + ","; }; return outStr; diff --git a/src/editor/service/FileImporterService.h b/src/editor/service/FileImporterService.h new file mode 100644 index 00000000..4df01d4a --- /dev/null +++ b/src/editor/service/FileImporterService.h @@ -0,0 +1,46 @@ +#ifndef METAL_ENGINE_LOADINGSERVICE_H +#define METAL_ENGINE_LOADINGSERVICE_H + +#include +#include +#include + +#include "../dto/ImportSettingsDTO.h" +#include "../../common/IService.h" + +namespace Metal { + class SceneImporterService; + class TextureImporterService; + class VoxelImporterService; + class NotificationService; + class AsyncTaskService; + + class FileImporterService final : public IService { + SceneImporterService *sceneImporterService = nullptr; + TextureImporterService *textureImporterService = nullptr; + VoxelImporterService *voxelImporterService = nullptr; + NotificationService *notificationService = nullptr; + AsyncTaskService *asyncTaskService = nullptr; + + public: + std::vector getDependencies() override { + return { + {"SceneImporterService", &sceneImporterService}, + {"TextureImporterService", &textureImporterService}, + {"VoxelImporterService", &voxelImporterService}, + {"NotificationService", ¬ificationService}, + {"AsyncTaskService", &asyncTaskService} + }; + } + + using LoadingTask = std::function; + + void importFile(std::string targetDir, std::string file, const std::shared_ptr &settings); + + std::string runAsync(const std::string &taskName, const LoadingTask &task) const; + + std::string collectCompatibleFiles() const; + }; +} + +#endif diff --git a/src/service/files/FilesService.cpp b/src/editor/service/FilesService.cpp similarity index 83% rename from src/service/files/FilesService.cpp rename to src/editor/service/FilesService.cpp index 9d6af371..8813ccaf 100644 --- a/src/service/files/FilesService.cpp +++ b/src/editor/service/FilesService.cpp @@ -1,33 +1,34 @@ #include "FilesService.h" -#include "../../dto/file/FSEntry.h" -#include "../../enum/EntryType.h" -#include "../../enum/engine-definitions.h" -#include "../../util/FilesUtil.h" -#include "../../context/ApplicationContext.h" -#include "../log/LogService.h" +#include "NotificationService.h" +#include "../dto/FSEntry.h" +#include "../enum/EntryType.h" +#include "../enum/engine-definitions.h" +#include "../../common/FilesUtil.h" +#include "../../common/LoggerUtil.h" #include #include #include #include #include -#include "../../util/serialization-definitions.h" +#include "../../common/serialization-definitions.h" +#include "../../core/DirectoryService.h" namespace fs = std::filesystem; -#define DELETE_F(F)\ +#define DELETE_F(F, rootDir)\ std::filesystem::remove_all(entry.second->absolutePath);\ -std::filesystem::remove_all(CTX.getAssetDirectory() + F(entry.second->getId())); +std::filesystem::remove_all(rootDir + "/assets/" + F(entry.second->getId())); -#define DELETE_S(F)\ +#define DELETE_S(F, rootDir)\ std::filesystem::remove_all(entry.second->absolutePath);\ -std::filesystem::remove_all(CTX.getAssetDirectory() + F(entry.second->getId())); +std::filesystem::remove_all(rootDir + "/assets/" + F(entry.second->getId())); #define DATA \ std::filesystem::file_time_type ftime = last_write_time(entry); namespace Metal { void FilesService::onInitialize() { - root = new FSEntry(nullptr, CTX.getAssetRefDirectory(), ""); + root = new FSEntry(nullptr, directoryService->getAssetRefDirectory(), ""); root->type = EntryType::DIRECTORY; root->name = "Files"; GetEntries(root); @@ -60,7 +61,7 @@ namespace Metal { for (auto &entry: selected) { switch (entry.second->type) { case EntryType::DIRECTORY: { - FilesService::GetEntries(entry.second); + GetEntries(entry.second); std::unordered_map files; for (auto *f: entry.second->children) { files.insert({f->getId(), f}); @@ -70,19 +71,19 @@ namespace Metal { break; } case EntryType::MESH: { - DELETE_F(FORMAT_FILE_MESH) + DELETE_F(FORMAT_FILE_MESH, directoryService->getRootDirectory()) break; } case EntryType::TEXTURE: { - DELETE_F(FORMAT_FILE_TEXTURE) + DELETE_F(FORMAT_FILE_TEXTURE, directoryService->getRootDirectory()) break; } case EntryType::SCENE: { - DELETE_S(FORMAT_FILE_SCENE) + DELETE_S(FORMAT_FILE_SCENE, directoryService->getRootDirectory()) break; } case EntryType::VOLUME: { - DELETE_S(FORMAT_FILE_VOLUME) + DELETE_S(FORMAT_FILE_VOLUME, directoryService->getRootDirectory()) break; } default: break;; @@ -116,7 +117,7 @@ namespace Metal { fs::rename(sourcePath, targetPath); } catch (const fs::filesystem_error &e) { LOG_ERROR("Could not move file"); - CTX.notificationService.pushMessage("Could not move entry", NotificationSeverities::ERROR); + notificationService->pushMessage("Could not move entry", NotificationSeverities::ERROR); return; } @@ -162,4 +163,5 @@ namespace Metal { } } } + } // Metal diff --git a/src/editor/service/FilesService.h b/src/editor/service/FilesService.h new file mode 100644 index 00000000..c0228b93 --- /dev/null +++ b/src/editor/service/FilesService.h @@ -0,0 +1,46 @@ +#ifndef FILESSERVICE_H +#define FILESSERVICE_H +#include +#include +#include + +#include "../../common/IInit.h" +#include "../../common/IService.h" + +namespace Metal { + struct DirectoryService; + struct FSEntry; + + class NotificationService; + + class FilesService final : public IService, public IInit { + FSEntry *root = nullptr; + DirectoryService *directoryService = nullptr; + NotificationService *notificationService = nullptr; + + public: + std::vector getDependencies() override { + return { + {"DirectoryService", &directoryService}, + {"NotificationService", ¬ificationService}}; + } + + FSEntry *getRoot() const { + return root; + } + + void onInitialize() override; + + std::unique_ptr getResource(const std::string &id); + + void deleteFiles(const std::unordered_map &files_context); + + void Move(FSEntry *toMove, FSEntry *targetDir); + + void CreateDirectory(FSEntry *currentDirectory); + + void GetEntries(FSEntry *root); + }; +} // Metal + +#endif //FILESSERVICE_H diff --git a/src/service/material/MaterialImporterService.cpp b/src/editor/service/MaterialImporterService.cpp similarity index 91% rename from src/service/material/MaterialImporterService.cpp rename to src/editor/service/MaterialImporterService.cpp index 35d659ff..6aa6009c 100644 --- a/src/service/material/MaterialImporterService.cpp +++ b/src/editor/service/MaterialImporterService.cpp @@ -1,7 +1,8 @@ #include "MaterialImporterService.h" -#include "../../context/ApplicationContext.h" -#include "../../enum/engine-definitions.h" -#include "../../repository/world/components/PrimitiveComponent.h" +#include "TextureImporterService.h" +#include "../../common/LoggerUtil.h" +#include "../enum/engine-definitions.h" +#include "../../engine/dto/PrimitiveComponent.h" #include #include @@ -21,7 +22,7 @@ namespace Metal { try { const unsigned int embeddedIndex = static_cast(std::stoul(p.substr(1))); if (scene && embeddedIndex < scene->mNumTextures) { - return CTX.textureImporter.importEmbeddedTexture( + return textureImporterService->importEmbeddedTexture( targetDir, scene->mTextures[embeddedIndex], nameHint); } } catch (std::exception &e) { @@ -37,7 +38,7 @@ namespace Metal { } resolved = resolved.lexically_normal(); try { - return CTX.textureImporter.importData(targetDir, resolved.string(), nullptr, stopToken); + return textureImporterService->importData(targetDir, resolved.string(), nullptr, stopToken); } catch (std::exception &e) { LOG_ERROR("Failed to import texture " + resolved.string() + ": " + e.what()); return ""; diff --git a/src/service/material/MaterialImporterService.h b/src/editor/service/MaterialImporterService.h similarity index 58% rename from src/service/material/MaterialImporterService.h rename to src/editor/service/MaterialImporterService.h index 52c9aedd..ae2596cc 100644 --- a/src/service/material/MaterialImporterService.h +++ b/src/editor/service/MaterialImporterService.h @@ -2,17 +2,26 @@ #define MATERIALIMPORTERSERVICE_H #include -#include #include #include -#include "../abstract/AbstractResourceService.h" +#include "../../common/IService.h" namespace Metal { struct PrimitiveComponent; - class MaterialImporterService final : public AbstractRuntimeComponent { + class TextureImporterService; + + class MaterialImporterService final : public IService { + TextureImporterService *textureImporterService = nullptr; + public: + std::vector getDependencies() override { + return { + {"TextureImporterService", &textureImporterService} + }; + } + void importMaterial(const std::string &targetDir, const aiMaterial *material, const aiScene *scene, const std::string &rootDirectory, PrimitiveComponent &primitive, const std::stop_token &stopToken = {}) const; diff --git a/src/service/mesh/MeshImporterService.cpp b/src/editor/service/MeshImporterService.cpp similarity index 88% rename from src/service/mesh/MeshImporterService.cpp rename to src/editor/service/MeshImporterService.cpp index f8c2a980..4a500d42 100644 --- a/src/service/mesh/MeshImporterService.cpp +++ b/src/editor/service/MeshImporterService.cpp @@ -1,13 +1,13 @@ #include "MeshImporterService.h" -#include "MeshData.h" -#include "VertexData.h" -#include "../../dto/file/EntryMetadata.h" -#include "../../enum/engine-definitions.h" -#include "../../util/FilesUtil.h" -#include "../../context/ApplicationContext.h" +#include "../../core/DirectoryService.h" +#include "../../common/LoggerUtil.h" +#include "../../engine/dto/MeshData.h" +#include "../../engine/dto/VertexData.h" +#include "../dto/EntryMetadata.h" +#include "../enum/engine-definitions.h" +#include "../../common/FilesUtil.h" #include -#include -#include "../../util/serialization-definitions.h" +#include "../../common/serialization-definitions.h" namespace Metal { std::string MeshImporterService::persistMesh(const std::string &targetDir, const MeshData &mesh) const { @@ -18,7 +18,7 @@ namespace Metal { metadata.name = metadata.name.substr(0, metadata.name.find_last_of('.')); } - std::string lod0Path = CTX.getAssetDirectory() + FORMAT_FILE_MESH(metadata.getId()); + std::string lod0Path = directoryService->getAssetDirectory() + FORMAT_FILE_MESH(metadata.getId()); { std::ofstream output(lod0Path, std::ios::binary); cereal::BinaryOutputArchive archive(output); diff --git a/src/service/mesh/MeshImporterService.h b/src/editor/service/MeshImporterService.h similarity index 67% rename from src/service/mesh/MeshImporterService.h rename to src/editor/service/MeshImporterService.h index 7e707e86..364c8764 100644 --- a/src/service/mesh/MeshImporterService.h +++ b/src/editor/service/MeshImporterService.h @@ -1,7 +1,7 @@ #ifndef MESHIMPORTERSERVICE_H #define MESHIMPORTERSERVICE_H -#include "../abstract/AbstractResourceService.h" +#include "../../common/IService.h" #include #include #include @@ -9,14 +9,23 @@ #include namespace Metal { + struct DirectoryService; + struct MeshId { std::string id; glm::vec3 gizmoCenter; }; struct MeshData; - class MeshImporterService final : public AbstractRuntimeComponent { + class MeshImporterService final : public IService { + DirectoryService *directoryService = nullptr; + public: + std::vector getDependencies() override { + return { + {"DirectoryService", &directoryService} + }; + } void persistAllMeshes(const std::string &targetDir, const aiScene *scene, std::unordered_map &meshMap, diff --git a/src/service/notification/NotificationService.cpp b/src/editor/service/NotificationService.cpp similarity index 95% rename from src/service/notification/NotificationService.cpp rename to src/editor/service/NotificationService.cpp index 92a21c0b..ed0b6a93 100644 --- a/src/service/notification/NotificationService.cpp +++ b/src/editor/service/NotificationService.cpp @@ -1,5 +1,5 @@ #include "NotificationService.h" -#include "../../dto/Notification.h" +#include "../dto/Notification.h" namespace Metal { void NotificationService::pushMessage(const std::string &message, NotificationSeverities::NotificationSeverity severity) { diff --git a/src/service/notification/NotificationService.h b/src/editor/service/NotificationService.h similarity index 81% rename from src/service/notification/NotificationService.h rename to src/editor/service/NotificationService.h index 32737dc5..f76ebba9 100644 --- a/src/service/notification/NotificationService.h +++ b/src/editor/service/NotificationService.h @@ -2,7 +2,8 @@ #define TOASTERSERVICE_H #include #include -#include "../../enum/NotificationSeverity.h" +#include "../enum/NotificationSeverity.h" +#include "../../common/IService.h" #define MAX_notifications 4 #define MESSAGE_DURATION 3000 @@ -10,7 +11,7 @@ namespace Metal { struct Notification; - class NotificationService { + class NotificationService : public IService { std::array notifications{}; public: diff --git a/src/service/picking/PickingService.cpp b/src/editor/service/PickingService.cpp similarity index 73% rename from src/service/picking/PickingService.cpp rename to src/editor/service/PickingService.cpp index 235ac849..1d1495df 100644 --- a/src/service/picking/PickingService.cpp +++ b/src/editor/service/PickingService.cpp @@ -1,19 +1,24 @@ #include "PickingService.h" -#include "../buffer/BufferInstance.h" -#include "../texture/TextureInstance.h" -#include "../../context/ApplicationContext.h" +#include "../../engine/resource/BufferInstance.h" +#include "../../engine/resource/TextureInstance.h" +#include "../../ApplicationContext.h" +#include "../../core/vulkan/VulkanContext.h" +#include "../../engine/service/BufferService.h" +#include "../../engine/repository/WorldRepository.h" +#include "../../engine/dto/PrimitiveComponent.h" +#include "../../engine/dto/TransformComponent.h" namespace Metal { std::optional PickingService::pickEntityFromGBuffer(TextureInstance *attachment, const uint32_t pixelX, const uint32_t pixelY) const { constexpr VkDeviceSize imageSize = 4 * sizeof(float); - auto stagingBuffer = CTX.bufferService.createBuffer("stagingBuffer", imageSize, VK_BUFFER_USAGE_TRANSFER_DST_BIT, + auto stagingBuffer = bufferService->createBuffer("stagingBuffer", imageSize, VK_BUFFER_USAGE_TRANSFER_DST_BIT, VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT); - VkCommandBuffer commandBuffer = CTX.vulkanContext.beginSingleTimeCommands(); + VkCommandBuffer commandBuffer = vulkanContext->beginSingleTimeCommands(); VkImageMemoryBarrier barrier = {}; barrier.sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER; @@ -51,14 +56,14 @@ namespace Metal { vkCmdPipelineBarrier(commandBuffer, VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT, 0, 0, nullptr, 0, nullptr, 1, &barrier); - CTX.vulkanContext.endSingleTimeCommands(commandBuffer); + vulkanContext->endSingleTimeCommands(commandBuffer); void *data = nullptr; - vkMapMemory(CTX.vulkanContext.device.device, stagingBuffer->vkDeviceMemory, 0, imageSize, 0, &data); + vkMapMemory(vulkanContext->device.device, stagingBuffer->vkDeviceMemory, 0, imageSize, 0, &data); const auto *pixel = static_cast(data); const float idValue = pixel[3]; // Render index is in the A channel (index 3) - vkUnmapMemory(CTX.vulkanContext.device.device, stagingBuffer->vkDeviceMemory); - CTX.bufferService.dispose("stagingBuffer"); + vkUnmapMemory(vulkanContext->device.device, stagingBuffer->vkDeviceMemory); + bufferService->dispose("stagingBuffer"); if (idValue <= 0.0f) { return std::nullopt; @@ -66,9 +71,10 @@ namespace Metal { const unsigned int renderIndex = static_cast(idValue + 0.5f) - 1; - auto view = CTX.worldRepository.registry.view(); + auto ®istry = worldRepository->registry; + auto view = registry.view(); for (auto entity: view) { - auto &mesh = view.get(entity); + auto &mesh = registry.get(entity); if (mesh.renderIndex == renderIndex) { return entity; } diff --git a/src/editor/service/PickingService.h b/src/editor/service/PickingService.h new file mode 100644 index 00000000..d7e2e842 --- /dev/null +++ b/src/editor/service/PickingService.h @@ -0,0 +1,32 @@ +#ifndef PICKINGSERVICE_H +#define PICKINGSERVICE_H + +#include "../../common/IService.h" +#include "../enum/engine-definitions.h" +#include + +namespace Metal { + struct TextureInstance; + class VulkanContext; + class BufferService; + struct WorldRepository; + + class PickingService final : public IService { + VulkanContext *vulkanContext = nullptr; + BufferService *bufferService = nullptr; + WorldRepository *worldRepository = nullptr; + + public: + std::vector getDependencies() override { + return { + {"VulkanContext", &vulkanContext}, + {"BufferService", &bufferService}, + {"WorldRepository", &worldRepository} + }; + } + + [[nodiscard]] std::optional pickEntityFromGBuffer(TextureInstance *attachment, uint32_t pixelX, uint32_t pixelY) const; + }; +} // Metal + +#endif // PICKINGSERVICE_H diff --git a/src/service/mesh/SceneImporterService.cpp b/src/editor/service/SceneImporterService.cpp similarity index 83% rename from src/service/mesh/SceneImporterService.cpp rename to src/editor/service/SceneImporterService.cpp index 08144c8a..ce925d01 100644 --- a/src/service/mesh/SceneImporterService.cpp +++ b/src/editor/service/SceneImporterService.cpp @@ -1,19 +1,21 @@ #include "SceneImporterService.h" - -#include "../../dto/file/FSEntry.h" -#include "MeshData.h" -#include "SceneData.h" -#include "../material/MaterialImporterService.h" +#include "MeshImporterService.h" +#include "MaterialImporterService.h" +#include "../../common/LoggerUtil.h" +#include "../dto/FSEntry.h" +#include "../../engine/dto/MeshData.h" +#include "../dto/SceneData.h" +#include "MaterialImporterService.h" #include #include #include #include -#include "../../util/FilesUtil.h" -#include "../../dto/file/EntryMetadata.h" -#include "../../enum/engine-definitions.h" -#include "../../context/ApplicationContext.h" -#include "../../util/serialization-definitions.h" -#include "../../dto/file/SceneImportSettingsDTO.h" +#include "../../common/FilesUtil.h" +#include "../dto/EntryMetadata.h" +#include "../enum/engine-definitions.h" +#include "../../common/serialization-definitions.h" +#include "../../core/DirectoryService.h" +#include "../dto/SceneImportSettingsDTO.h" namespace Metal { std::string SceneImporterService::importData(const std::string &targetDir, const std::string &pathToFile, @@ -49,7 +51,7 @@ namespace Metal { sceneMetadata.name = sceneData.name = scene->mName.length > 0 ? scene->mName.data : scene->mRootNode->mName.data; - std::string sceneBlobPath = CTX.getAssetDirectory() + FORMAT_FILE_SCENE(sceneMetadata.getId()); + std::string sceneBlobPath = directoryService->getAssetDirectory() + FORMAT_FILE_SCENE(sceneMetadata.getId()); std::unordered_map meshMap{}; @@ -57,7 +59,7 @@ namespace Metal { throw std::runtime_error("Import cancelled"); } - CTX.meshImporterService.persistAllMeshes(targetDir, scene, meshMap, stopToken); + meshImporterService->persistAllMeshes(targetDir, scene, meshMap, stopToken); if (stopToken.stop_requested()) { throw std::runtime_error("Import cancelled"); @@ -66,7 +68,7 @@ namespace Metal { fs::path absolutePath = fs::absolute(pathToFile); std::string directoryPath = absolutePath.parent_path().string(); - ProcessNode(sceneData, scene, scene->mRootNode, targetDir, directoryPath, meshMap, stopToken); + processNode(sceneData, scene, scene->mRootNode, targetDir, directoryPath, meshMap, stopToken); ProcessLights(sceneData, scene); if (stopToken.stop_requested()) { @@ -88,10 +90,10 @@ namespace Metal { return sceneMetadata.getId(); } - void SceneImporterService::ProcessNode(SceneData &scene, const aiScene *aiScene, const aiNode *node, + void SceneImporterService::processNode(SceneData &scene, const aiScene *aiScene, const aiNode *node, const std::string &targetDir, const std::string &rootDirectory, const std::unordered_map &meshMap, - const std::stop_token &stopToken) { + const std::stop_token &stopToken) const { if (stopToken.stop_requested()) return; auto ¤tNode = scene.entities.emplace_back(); @@ -105,17 +107,17 @@ namespace Metal { currentNode.transform.rotation = {rotation.w, rotation.x, rotation.y, rotation.z}; currentNode.transform.scale = {scaling.x, scaling.y, scaling.z}; - ProcessMeshes(scene, aiScene, node, targetDir, rootDirectory, meshMap, stopToken); + processMeshes(scene, aiScene, node, targetDir, rootDirectory, meshMap, stopToken); for (unsigned int i = 0; i < node->mNumChildren; ++i) { - ProcessNode(scene, aiScene, node->mChildren[i], targetDir, rootDirectory, meshMap, stopToken); + processNode(scene, aiScene, node->mChildren[i], targetDir, rootDirectory, meshMap, stopToken); } } - void SceneImporterService::ProcessMeshes(SceneData &scene, const aiScene *aiScene, const aiNode *node, + void SceneImporterService::processMeshes(SceneData &scene, const aiScene *aiScene, const aiNode *node, const std::string &targetDir, const std::string &rootDirectory, const std::unordered_map &meshMap, - const std::stop_token &stopToken) { + const std::stop_token &stopToken) const { for (unsigned int i = 0; i < node->mNumMeshes; ++i) { if (stopToken.stop_requested()) return; unsigned int meshIndex = node->mMeshes[i]; @@ -131,7 +133,7 @@ namespace Metal { childMeshNode.entity.name = assimpMesh->mName.length > 0 ? assimpMesh->mName.data : "Mesh"; const aiMaterial *material = aiScene->mMaterials[assimpMesh->mMaterialIndex]; - CTX.materialImporterService.importMaterial(targetDir, material, aiScene, rootDirectory, + materialImporterService->importMaterial(targetDir, material, aiScene, rootDirectory, *childMeshNode.primitive, stopToken); } } diff --git a/src/editor/service/SceneImporterService.h b/src/editor/service/SceneImporterService.h new file mode 100644 index 00000000..daea86d0 --- /dev/null +++ b/src/editor/service/SceneImporterService.h @@ -0,0 +1,54 @@ +#ifndef MESHIMPORTER_H +#define MESHIMPORTER_H + +#include + +#include "../../common/AbstractImporter.h" +#include +#include + +namespace Metal { + struct DirectoryService; + struct MeshId; + struct MaterialData; + struct MeshData; + struct SceneData; + + class MeshImporterService; + class MaterialImporterService; + + class SceneImporterService final : public AbstractImporter { + MeshImporterService *meshImporterService = nullptr; + MaterialImporterService *materialImporterService = nullptr; + DirectoryService *directoryService = nullptr; + + public: + std::vector getDependencies() override { + return { + {"MeshImporterService", &meshImporterService}, + {"MaterialImporterService", &materialImporterService}, + {"DirectoryService", &directoryService} + }; + } + + std::string importData(const std::string &targetDir, const std::string &pathToFile, + const std::shared_ptr &settings, + const std::stop_token &stopToken) override; + + void processNode(SceneData &scene, const aiScene *aiScene, const aiNode *node, + const std::string &targetDir, const std::string &rootDirectory, + const std::unordered_map &meshMap, + const std::stop_token &stopToken) const; + + void processMeshes(SceneData &scene, const aiScene *aiScene, const aiNode *node, + const std::string &targetDir, const std::string &rootDirectory, + const std::unordered_map &meshMap, + const std::stop_token &stopToken) const; + + static void ProcessLights(SceneData &scene, const aiScene *aiScene); + + std::vector getSupportedTypes() override; + }; +} // Metal + +#endif //MESHIMPORTER_H diff --git a/src/editor/service/SelectionService.cpp b/src/editor/service/SelectionService.cpp new file mode 100644 index 00000000..de66ed82 --- /dev/null +++ b/src/editor/service/SelectionService.cpp @@ -0,0 +1,47 @@ +#include "SelectionService.h" +#include "../../editor/repository/EditorRepository.h" +#include "../../engine/repository/WorldRepository.h" +#include "../../engine/dto/TransformComponent.h" + +namespace Metal { + void SelectionService::addSelected(entt::entity entity) const { + if (editorRepository->selected.empty() || entity == EMPTY_ENTITY) { + editorRepository->mainSelection = entity; + if (editorRepository->mainSelection != EMPTY_ENTITY) { + updatePrimitiveSelected(); + } + } + if (entity != EMPTY_ENTITY) { + editorRepository->selected.insert({entity, true}); + } + } + + void SelectionService::clearSelection() const { + editorRepository->selected.clear(); + editorRepository->mainSelection = EMPTY_ENTITY; + editorRepository->primitiveSelected = nullptr; + } + + void SelectionService::addAllSelected(const std::vector &all) const { + editorRepository->selected.clear(); + const entt::entity first = all.size() > 0 ? all[0] : EMPTY_ENTITY; + editorRepository->mainSelection = first; + updatePrimitiveSelected(); + for (auto a: all) { + editorRepository->selected.insert({a, true}); + } + } + + void SelectionService::updatePrimitiveSelected() const { + const auto entityId = editorRepository->mainSelection; + + if (entityId == EMPTY_ENTITY || !worldRepository->registry.valid(entityId)) { + return; + } + + if (worldRepository->registry.all_of(entityId)) { + editorRepository->primitiveSelected = &worldRepository->registry.get(entityId); + } + } + +} // Metal diff --git a/src/editor/service/SelectionService.h b/src/editor/service/SelectionService.h new file mode 100644 index 00000000..f3d7a7d0 --- /dev/null +++ b/src/editor/service/SelectionService.h @@ -0,0 +1,34 @@ +#ifndef SELECTIONSERVICE_H +#define SELECTIONSERVICE_H +#include + +#include "../../common/IService.h" +#include "../enum/engine-definitions.h" + +namespace Metal { + struct WorldRepository; + struct EditorRepository; + + class SelectionService final : public IService { + EditorRepository *editorRepository = nullptr; + WorldRepository *worldRepository = nullptr; + + public: + std::vector getDependencies() override { + return { + {"EditorRepository", &editorRepository}, + {"WorldRepository", &worldRepository} + }; + } + + void addSelected(entt::entity entity) const; + + void clearSelection() const; + + void addAllSelected(const std::vector &all) const; + + void updatePrimitiveSelected() const; + }; +} // Metal + +#endif //SELECTIONSERVICE_H diff --git a/src/service/texture/TextureImporterService.cpp b/src/editor/service/TextureImporterService.cpp similarity index 89% rename from src/service/texture/TextureImporterService.cpp rename to src/editor/service/TextureImporterService.cpp index d5f3d5f5..0c6b7009 100644 --- a/src/service/texture/TextureImporterService.cpp +++ b/src/editor/service/TextureImporterService.cpp @@ -1,16 +1,18 @@ #include "TextureImporterService.h" +#include "../../core/DirectoryService.h" +#include "../../common/LoggerUtil.h" +#include "../enum/engine-definitions.h" -#include "../../../dependencies/stb/stb_image.h" -#include "../../../dependencies/stb/stb_image_write.h" +#include "../../../../dependencies/stb/stb_image.h" +#include "../../../../dependencies/stb/stb_image_write.h" #include #include -#include "../../util/serialization-definitions.h" +#include "../../common/serialization-definitions.h" -#include "../../dto/file/EntryMetadata.h" -#include "../../enum/EntryType.h" -#include "../../util/FilesUtil.h" -#include "../../context/ApplicationContext.h" -#include "TextureData.h" +#include "../dto/EntryMetadata.h" +#include "../enum/EntryType.h" +#include "../../common/FilesUtil.h" +#include "../../engine/dto/TextureData.h" namespace fs = std::filesystem; @@ -103,7 +105,7 @@ namespace Metal { size_t TextureImporterService::saveImage(const std::string &fileId, const TextureData &textureData) const { - std::string texturePath = CTX.getAssetDirectory() + FORMAT_FILE_TEXTURE(fileId); + std::string texturePath = directoryService->getAssetDirectory() + FORMAT_FILE_TEXTURE(fileId); if (!stbi_write_png(texturePath.c_str(), textureData.width, textureData.height, textureData.channels, textureData.data, textureData.width * textureData.channels)) { diff --git a/src/service/texture/TextureImporterService.h b/src/editor/service/TextureImporterService.h similarity index 74% rename from src/service/texture/TextureImporterService.h rename to src/editor/service/TextureImporterService.h index 9cfa4085..6daa7cc9 100644 --- a/src/service/texture/TextureImporterService.h +++ b/src/editor/service/TextureImporterService.h @@ -1,16 +1,21 @@ #ifndef TEXTUREIMPORTER_H #define TEXTUREIMPORTER_H -#include "../abstract/AbstractImporter.h" +#include "../../common/AbstractImporter.h" struct aiTexture; namespace Metal { + class DirectoryService; struct TextureData; class TextureImporterService final : public AbstractImporter { + DirectoryService *directoryService = nullptr; + public: - explicit TextureImporterService() - : AbstractImporter() { + std::vector getDependencies() override { + return { + {"DirectoryService", &directoryService} + }; } std::vector getSupportedTypes() override { diff --git a/src/service/theme/ThemeService.cpp b/src/editor/service/ThemeService.cpp similarity index 73% rename from src/service/theme/ThemeService.cpp rename to src/editor/service/ThemeService.cpp index c206b8a2..d508d959 100644 --- a/src/service/theme/ThemeService.cpp +++ b/src/editor/service/ThemeService.cpp @@ -1,22 +1,23 @@ #include "ThemeService.h" -#include "../../context/ApplicationContext.h" +#include + +#include "../repository/EditorRepository.h" namespace Metal { glm::vec3 ThemeService::BACKGROUND_COLOR = glm::vec3(0.f); void ThemeService::onSync() { - EditorRepository &editorRepository = CTX.editorRepository; - if (previousTheme == editorRepository.isDarkMode && glm::length(editorRepository.accentColor) == prevLength) { + if (previousTheme == editorRepository->isDarkMode && glm::length(editorRepository->accentColor) == prevLength) { return; } - prevLength = glm::length(editorRepository.accentColor); - previousTheme = editorRepository.isDarkMode; + prevLength = glm::length(editorRepository->accentColor); + previousTheme = editorRepository->isDarkMode; ImGuiStyle &style = ImGui::GetStyle(); auto &colors = style.Colors; - if (!editorRepository.isDarkMode) { + if (!editorRepository->isDarkMode) { ImGui::StyleColorsLight(); setLightMode(); } else { @@ -61,24 +62,24 @@ namespace Metal { colors[ImGuiCol_NavWindowingDimBg] = palette2; colors[ImGuiCol_ModalWindowDimBg] = palette2; - editorRepository.accent.y = editorRepository.accentColor.y; - editorRepository.accent.z = editorRepository.accentColor.z; - editorRepository.accent.x = editorRepository.accentColor.x; - editorRepository.accent.w = 1; - editorRepository.accentU32 = ImGui::GetColorU32(editorRepository.accent); + editorRepository->accent.y = editorRepository->accentColor.y; + editorRepository->accent.z = editorRepository->accentColor.z; + editorRepository->accent.x = editorRepository->accentColor.x; + editorRepository->accent.w = 1; + editorRepository->accentU32 = ImGui::GetColorU32(editorRepository->accent); - colors[ImGuiCol_FrameBgHovered] = editorRepository.accent; - colors[ImGuiCol_FrameBgActive] = editorRepository.accent; - colors[ImGuiCol_CheckMark] = editorRepository.accent; - colors[ImGuiCol_SliderGrabActive] = editorRepository.accent; + colors[ImGuiCol_FrameBgHovered] = editorRepository->accent; + colors[ImGuiCol_FrameBgActive] = editorRepository->accent; + colors[ImGuiCol_CheckMark] = editorRepository->accent; + colors[ImGuiCol_SliderGrabActive] = editorRepository->accent; colors[ImGuiCol_Button] = palette3; - colors[ImGuiCol_ButtonHovered] = editorRepository.accent; - colors[ImGuiCol_Header] = editorRepository.accent; - colors[ImGuiCol_HeaderHovered] = editorRepository.accent; - colors[ImGuiCol_HeaderActive] = editorRepository.accent; - colors[ImGuiCol_ResizeGripHovered] = editorRepository.accent; - colors[ImGuiCol_ResizeGripActive] = editorRepository.accent; - colors[ImGuiCol_TextSelectedBg] = editorRepository.accent; + colors[ImGuiCol_ButtonHovered] = editorRepository->accent; + colors[ImGuiCol_Header] = editorRepository->accent; + colors[ImGuiCol_HeaderHovered] = editorRepository->accent; + colors[ImGuiCol_HeaderActive] = editorRepository->accent; + colors[ImGuiCol_ResizeGripHovered] = editorRepository->accent; + colors[ImGuiCol_ResizeGripActive] = editorRepository->accent; + colors[ImGuiCol_TextSelectedBg] = editorRepository->accent; BACKGROUND_COLOR[0] = colors[ImGuiCol_WindowBg].x; BACKGROUND_COLOR[1] = colors[ImGuiCol_WindowBg].y; diff --git a/src/service/theme/ThemeService.h b/src/editor/service/ThemeService.h similarity index 64% rename from src/service/theme/ThemeService.h rename to src/editor/service/ThemeService.h index e9d5f603..4ccf93a6 100644 --- a/src/service/theme/ThemeService.h +++ b/src/editor/service/ThemeService.h @@ -2,11 +2,14 @@ #define THEMESERVICE_H #include #include -#include "../../common/AbstractRuntimeComponent.h" +#include "../../common/IService.h" +#include "../../common/ISync.h" namespace Metal { - class ThemeService final : public AbstractRuntimeComponent { + struct EditorRepository; + class ThemeService final : public IService, public ISync { + EditorRepository *editorRepository = nullptr; public: ImVec4 neutralPalette{}; ImVec4 palette0{}; @@ -21,14 +24,15 @@ namespace Metal { bool previousTheme = false; float prevLength = 0.0f; - explicit ThemeService() : AbstractRuntimeComponent() { - } - void setDarkMode(); void setLightMode(); void onSync() override; + + std::vector getDependencies() override { + return {{"EditorRepository", &editorRepository}}; + } }; } // Metal diff --git a/src/service/voxel/VoxelImporterService.cpp b/src/editor/service/VoxelImporterService.cpp similarity index 93% rename from src/service/voxel/VoxelImporterService.cpp rename to src/editor/service/VoxelImporterService.cpp index 6923f58e..65d7546a 100644 --- a/src/service/voxel/VoxelImporterService.cpp +++ b/src/editor/service/VoxelImporterService.cpp @@ -1,20 +1,20 @@ #include "VoxelImporterService.h" +#include "../../core/DirectoryService.h" #include -#include "../../util/serialization-definitions.h" +#include "../../common/serialization-definitions.h" -#include "../../context/ApplicationContext.h" -#include "../../dto/file/EntryMetadata.h" -#include "../../enum/EntryType.h" -#include "../../enum/engine-definitions.h" -#include "../../service/log/LogService.h" +#include "../dto/EntryMetadata.h" +#include "../enum/EntryType.h" +#include "../enum/engine-definitions.h" +#include "../../common/LoggerUtil.h" #include #include #include #include -#include "impl/SparseVoxelOctreeData.h" +#include "../../engine/dto/SparseVoxelOctreeData.h" namespace fs = std::filesystem; @@ -29,7 +29,7 @@ namespace Metal { metadata.name = metadata.name.substr(0, metadata.name.find_last_of('.')); - std::string outPath = CTX.getAssetDirectory() + FORMAT_FILE_VOLUME(metadata.getId()); + std::string outPath = directoryService->getAssetDirectory() + FORMAT_FILE_VOLUME(metadata.getId()); metadata.size = convertToSVO(pathToFile, outPath, stopToken); DUMP_TEMPLATE(targetDir + '/' + FORMAT_FILE_METADATA(metadata.getId()), metadata) diff --git a/src/service/voxel/VoxelImporterService.h b/src/editor/service/VoxelImporterService.h similarity index 75% rename from src/service/voxel/VoxelImporterService.h rename to src/editor/service/VoxelImporterService.h index 57ed9bac..4221e448 100644 --- a/src/service/voxel/VoxelImporterService.h +++ b/src/editor/service/VoxelImporterService.h @@ -1,15 +1,23 @@ #ifndef METAL_ENGINE_VOLUMEIMPORTERSERVICE_H #define METAL_ENGINE_VOLUMEIMPORTERSERVICE_H -#include "../abstract/AbstractImporter.h" -#include "impl/SparseVoxelOctreeBuilder.h" -#include "impl/SparseVoxelOctreeData.h" +#include "../../common/AbstractImporter.h" +#include "../dto/SparseVoxelOctreeBuilder.h" +#include "../../engine/dto/SparseVoxelOctreeData.h" namespace Metal { + class DirectoryService; struct SVOInstance; class VoxelImporterService final : public AbstractImporter { + DirectoryService *directoryService = nullptr; public: + std::vector getDependencies() override { + return { + {"DirectoryService", &directoryService} + }; + } + std::vector getSupportedTypes() override; size_t convertToSVO(const std::string &sourcePath, const std::string &outPath, diff --git a/src/util/UIUtil.h b/src/editor/util/UIUtil.h similarity index 99% rename from src/util/UIUtil.h rename to src/editor/util/UIUtil.h index 48312985..dc10a0a2 100644 --- a/src/util/UIUtil.h +++ b/src/editor/util/UIUtil.h @@ -5,7 +5,7 @@ #include #include "../enum/EntryType.h" -#include "../common/interface/Icons.h" +#include "../../common/Icons.h" namespace Metal::UIUtil { static constexpr ImVec4 DIRECTORY_COLOR{188 / 255.f, 128 / 255.f, 78 / 255.f, 1}; diff --git a/src/util/Util.h b/src/editor/util/Util.h similarity index 100% rename from src/util/Util.h rename to src/editor/util/Util.h diff --git a/src/engine/EngineContext.cpp b/src/engine/EngineContext.cpp new file mode 100644 index 00000000..057569a9 --- /dev/null +++ b/src/engine/EngineContext.cpp @@ -0,0 +1,107 @@ +#include "EngineContext.h" + +#include "../ApplicationContext.h" +#include "service/TransformService.h" +#include "service/StreamingService.h" +#include "service/RayTracingService.h" +#include "service/CameraService.h" +#include "service/LightService.h" +#include "service/VolumeService.h" +#include "repository/WorldRepository.h" +#include "repository/EngineRepository.h" +#include "../editor/repository/EditorRepository.h" + +#include "../editor/enum/EngineResourceIDs.h" +#include "resource/BufferInstance.h" +#include "dto/TransformComponent.h" + +namespace Metal { + void EngineContext::resetPathTracerAccumulationCount() const { + engineRepository->pathTracerAccumulationCount = 0; + } + + void EngineContext::updateCurrentTime() { + currentTime = Clock::now(); + std::chrono::duration delta = currentTime - previousTime; + deltaTime = delta.count(); + previousTime = currentTime; + + auto duration = std::chrono::duration_cast(currentTime.time_since_epoch()); + currentTimeMs = duration.count(); + + if (start == -1) { + start = currentTimeMs; + } + } + + EngineFrameBuilder EngineContext::createFrame(const std::string &id) { + EngineFrameBuilder frameBuilder(id); + ctx->injectDependencies(&frameBuilder); + return frameBuilder; + } + + void EngineContext::setCurrentFrame(const std::string &id) { + for (auto *frame: registeredFrames) { + if (frame->getId() == id) { + currentFrame = frame; + currentFrame->setShouldRender(true); + return; + } + } + throw std::runtime_error("Frame not found"); + } + + void EngineContext::dispose() { + } + + void EngineContext::onSync() { + updateCurrentTime(); + + transformService->onSync(); + streamingService->onSync(); + rayTracingService->onSync(); + cameraService->onSync(); + lightService->onSync(); + volumeService->onSync(); + + for (auto *frame: registeredFrames) { + if (frame->getShouldRender()) { + currentFrame = frame; + updateGlobalData(); + currentFrame->onSync(); + + frame->setShouldRender(false); + } + } + + setCameraUpdated(false); + setGISettingsUpdated(false); + } + + void EngineContext::updateGlobalData() { + auto &camera = worldRepository->camera; + globalDataUBO.previousProjView = globalDataUBO.projView; + globalDataUBO.viewMatrix = camera.viewMatrix; + globalDataUBO.projectionMatrix = camera.projectionMatrix; + globalDataUBO.projView = camera.projViewMatrix; + globalDataUBO.invProj = camera.invProjectionMatrix; + globalDataUBO.invView = camera.invViewMatrix; + globalDataUBO.cameraWorldPosition = camera.position; + globalDataUBO.volumeCount = volumeService->getCount(); + globalDataUBO.lightsCount = lightService->getCount(); + globalDataUBO.debugFlag = ShadingModes::IndexOfValue(editorRepository->shadingMode); + engineRepository->pathTracerAccumulationCount++; + globalDataUBO.pathTracerAccumulationCount = engineRepository->pathTracerAccumulationCount; + globalDataUBO.globalFrameCount++; + globalDataUBO.pathTracerMaxSamples = engineRepository->pathTracerMaxSamples; + globalDataUBO.denoiserEnabled = engineRepository->denoiserEnabled && ( + globalDataUBO.debugFlag == LIT || globalDataUBO.debugFlag == LIGHTING_ONLY) + ? 1 + : 0; + + lightService->computeSunInfo(); + globalDataUBO.sunPosition = lightService->getSunPosition(); + globalDataUBO.sunColor = lightService->getSunColor(); + currentFrame->getResourceAs(RID_GLOBAL_DATA)->update(&globalDataUBO); + } +} diff --git a/src/engine/EngineContext.h b/src/engine/EngineContext.h new file mode 100644 index 00000000..a630a405 --- /dev/null +++ b/src/engine/EngineContext.h @@ -0,0 +1,110 @@ +#ifndef METAL_ENGINE_ENGINECONTEXT_H +#define METAL_ENGINE_ENGINECONTEXT_H + +#include +#include + +#include "dto/GlobalDataUBO.h" +#include "../common/IService.h" +#include "../common/IDisposable.h" +#include "../common/ISync.h" +#include "frame-builder/EngineFrame.h" +#include "frame-builder/EngineFrameBuilder.h" + +using Clock = std::chrono::high_resolution_clock; +using TimePoint = std::chrono::time_point; + +namespace Metal { + class TransformService; + class StreamingService; + class RayTracingService; + class CameraService; + class LightService; + class VolumeService; + struct WorldRepository; + struct EditorRepository; + struct EngineRepository; + class EngineFrame; + class EngineFrameBuilder; + + class EngineContext final : public IService, public ISync, public IDisposable { + TransformService *transformService = nullptr; + StreamingService *streamingService = nullptr; + RayTracingService *rayTracingService = nullptr; + CameraService *cameraService = nullptr; + LightService *lightService = nullptr; + VolumeService *volumeService = nullptr; + WorldRepository *worldRepository = nullptr; + EditorRepository *editorRepository = nullptr; + EngineRepository *engineRepository = nullptr; + + GlobalDataUBO globalDataUBO{}; + long long start = -1; + bool cameraUpdated = true; + bool giSettingsUpdated = true; + + public: + std::vector getDependencies() override { + return { + {"TransformService", &transformService}, + {"StreamingService", &streamingService}, + {"RayTracingService", &rayTracingService}, + {"CameraService", &cameraService}, + {"LightService", &lightService}, + {"VolumeService", &volumeService}, + {"WorldRepository", &worldRepository}, + {"EditorRepository", &editorRepository}, + {"EngineRepository", &engineRepository} + }; + } + + GlobalDataUBO &getGlobalDataUBO() { return globalDataUBO; } + + void setCameraUpdated(const bool val) { + cameraUpdated = val; + } + + bool isCameraUpdated() const { + return cameraUpdated; + } + + void setGISettingsUpdated(const bool val) { + giSettingsUpdated = val; + } + + void resetPathTracerAccumulationCount() const; + + bool isGISettingsUpdated() const { + return giSettingsUpdated; + } + + void updateCurrentTime(); + + EngineFrameBuilder createFrame(const std::string &id); + + void setCurrentFrame(const std::string & id); + + long long currentTimeMs = 0; + TimePoint currentTime; + TimePoint previousTime = Clock::now(); + float deltaTime = 0; + + std::vector registeredFrames; + EngineFrame *currentFrame = nullptr; + + void updateGlobalData(); + + void registerFrame(EngineFrame *frame) { + registeredFrames.push_back(frame); + } + + void unregisterFrame(EngineFrame *frame) { + std::erase(registeredFrames, frame); + } + + void onSync() override; + + void dispose() override; + }; +} +#endif diff --git a/src/repository/world/impl/AbstractComponent.h b/src/engine/dto/AbstractComponent.h similarity index 89% rename from src/repository/world/impl/AbstractComponent.h rename to src/engine/dto/AbstractComponent.h index b9ab3ebb..5f8db038 100644 --- a/src/repository/world/impl/AbstractComponent.h +++ b/src/engine/dto/AbstractComponent.h @@ -1,7 +1,7 @@ #ifndef ABSTRACTCOMPONENT_H #define ABSTRACTCOMPONENT_H -#include "../../../common/inspection/Inspectable.h" -#include "../../../enum/ComponentType.h" +#include "../../common/Inspectable.h" +#include "../enum/ComponentType.h" namespace Metal { struct AbstractComponent : Inspectable { diff --git a/src/dto/push-constant/AccumulationPushConstant.h b/src/engine/dto/AccumulationPushConstant.h similarity index 100% rename from src/dto/push-constant/AccumulationPushConstant.h rename to src/engine/dto/AccumulationPushConstant.h diff --git a/src/repository/world/impl/BoundingBox.h b/src/engine/dto/BoundingBox.h similarity index 94% rename from src/repository/world/impl/BoundingBox.h rename to src/engine/dto/BoundingBox.h index 94ea7dea..74fdbb0a 100644 --- a/src/repository/world/impl/BoundingBox.h +++ b/src/engine/dto/BoundingBox.h @@ -1,10 +1,10 @@ #ifndef BOUNDINGBOX_H #define BOUNDINGBOX_H #include -#include "../../../util/Serializable.h" +#include "../../common/ISerialize.h" namespace Metal { - struct BoundingBox final : Serializable { + struct BoundingBox final : ISerialize { glm::vec3 min = glm::vec3(std::numeric_limits::max()); glm::vec3 max = glm::vec3(std::numeric_limits::lowest()); glm::vec3 center = glm::vec3(0.0f); diff --git a/src/service/camera/Camera.cpp b/src/engine/dto/Camera.cpp similarity index 98% rename from src/service/camera/Camera.cpp rename to src/engine/dto/Camera.cpp index 75fe8e20..91260a28 100644 --- a/src/service/camera/Camera.cpp +++ b/src/engine/dto/Camera.cpp @@ -1,6 +1,6 @@ #include "Camera.h" -#include "../../common/interface/Icons.h" +#include "../../common/Icons.h" namespace Metal { void Camera::extractFrustumPlanes(glm::mat4x4 m) { diff --git a/src/service/camera/Camera.h b/src/engine/dto/Camera.h similarity index 97% rename from src/service/camera/Camera.h rename to src/engine/dto/Camera.h index 6afad882..ac38f427 100644 --- a/src/service/camera/Camera.h +++ b/src/engine/dto/Camera.h @@ -6,12 +6,12 @@ #include #include -#include "../../common/inspection/Inspectable.h" -#include "../../util/Serializable.h" +#include "../../common/Inspectable.h" +#include "../../common/ISerialize.h" namespace Metal { - struct Camera final : Inspectable, Serializable { + struct Camera final : Inspectable, ISerialize { float rotationSensitivity = 1; float movementSensitivity = 1.0f; float zoomSensitivity = 1.0f; diff --git a/src/dto/push-constant/DenoiserPushConstant.h b/src/engine/dto/DenoiserPushConstant.h similarity index 100% rename from src/dto/push-constant/DenoiserPushConstant.h rename to src/engine/dto/DenoiserPushConstant.h diff --git a/src/service/descriptor/DescriptorBinding.h b/src/engine/dto/DescriptorBinding.h similarity index 100% rename from src/service/descriptor/DescriptorBinding.h rename to src/engine/dto/DescriptorBinding.h diff --git a/src/service/descriptor/DescriptorInstance.h b/src/engine/dto/DescriptorInstance.h similarity index 87% rename from src/service/descriptor/DescriptorInstance.h rename to src/engine/dto/DescriptorInstance.h index f2069c62..c924f7e5 100644 --- a/src/service/descriptor/DescriptorInstance.h +++ b/src/engine/dto/DescriptorInstance.h @@ -2,8 +2,8 @@ #define DESCRIPTORINSTANCE_H #include -#include "../../repository/abstract/RuntimeResource.h" -#include "./DescriptorBinding.h" +#include "../resource/RuntimeResource.h" +#include "DescriptorBinding.h" namespace Metal { struct BufferInstance; diff --git a/src/dto/buffers/GlobalDataUBO.h b/src/engine/dto/GlobalDataUBO.h similarity index 100% rename from src/dto/buffers/GlobalDataUBO.h rename to src/engine/dto/GlobalDataUBO.h diff --git a/src/dto/push-constant/HWRayTracingPushConstant.h b/src/engine/dto/HWRayTracingPushConstant.h similarity index 100% rename from src/dto/push-constant/HWRayTracingPushConstant.h rename to src/engine/dto/HWRayTracingPushConstant.h diff --git a/src/dto/buffers/LightData.h b/src/engine/dto/LightData.h similarity index 100% rename from src/dto/buffers/LightData.h rename to src/engine/dto/LightData.h diff --git a/src/service/mesh/MeshData.h b/src/engine/dto/MeshData.h similarity index 93% rename from src/service/mesh/MeshData.h rename to src/engine/dto/MeshData.h index f5dfb639..2a24bd4c 100644 --- a/src/service/mesh/MeshData.h +++ b/src/engine/dto/MeshData.h @@ -3,7 +3,7 @@ #include #include #include "VertexData.h" -#include "../../util/serialization-definitions.h" +#include "../../common/serialization-definitions.h" namespace Metal { struct MeshData final { diff --git a/src/dto/buffers/MeshMetadata.h b/src/engine/dto/MeshMetadata.h similarity index 100% rename from src/dto/buffers/MeshMetadata.h rename to src/engine/dto/MeshMetadata.h diff --git a/src/repository/world/impl/MetadataComponent.cpp b/src/engine/dto/MetadataComponent.cpp similarity index 77% rename from src/repository/world/impl/MetadataComponent.cpp rename to src/engine/dto/MetadataComponent.cpp index bd5dc915..7726da77 100644 --- a/src/repository/world/impl/MetadataComponent.cpp +++ b/src/engine/dto/MetadataComponent.cpp @@ -1,6 +1,4 @@ #include "MetadataComponent.h" -#include "../../../common/interface/Icons.h" -#include "../../../util/UIUtil.h" namespace Metal { void MetadataComponent::registerFields() { diff --git a/src/repository/world/impl/MetadataComponent.h b/src/engine/dto/MetadataComponent.h similarity index 76% rename from src/repository/world/impl/MetadataComponent.h rename to src/engine/dto/MetadataComponent.h index 4923e86e..14848c28 100644 --- a/src/repository/world/impl/MetadataComponent.h +++ b/src/engine/dto/MetadataComponent.h @@ -4,13 +4,13 @@ #include #include "AbstractComponent.h" -#include "../../../enum/engine-definitions.h" -#include "../../../enum/ComponentType.h" -#include "../../../common/inspection/Inspectable.h" -#include "../../../util/Serializable.h" +#include "../../editor/enum/engine-definitions.h" +#include "../enum/ComponentType.h" +#include "../../common/Inspectable.h" +#include "../../common/ISerialize.h" namespace Metal { - struct MetadataComponent final : AbstractComponent, Serializable { + struct MetadataComponent final : AbstractComponent, ISerialize { std::string name = "New entity"; glm::vec3 color{1,1,1}; diff --git a/src/service/pipeline/PipelineBuilder.cpp b/src/engine/dto/PipelineBuilder.cpp similarity index 99% rename from src/service/pipeline/PipelineBuilder.cpp rename to src/engine/dto/PipelineBuilder.cpp index 27f0f363..5bd8a621 100644 --- a/src/service/pipeline/PipelineBuilder.cpp +++ b/src/engine/dto/PipelineBuilder.cpp @@ -1,5 +1,5 @@ #include "PipelineBuilder.h" -#include "../texture/TextureInstance.h" +#include "../resource/TextureInstance.h" namespace Metal { PipelineBuilder PipelineBuilder::Of(std::string frameBufferId, const char *vertexShader, diff --git a/src/service/pipeline/PipelineBuilder.h b/src/engine/dto/PipelineBuilder.h similarity index 98% rename from src/service/pipeline/PipelineBuilder.h rename to src/engine/dto/PipelineBuilder.h index 14c8095c..cdb39b5e 100644 --- a/src/service/pipeline/PipelineBuilder.h +++ b/src/engine/dto/PipelineBuilder.h @@ -3,7 +3,7 @@ #include #include #include -#include "../descriptor/DescriptorBinding.h" +#include "DescriptorBinding.h" namespace Metal { struct DescriptorInstance; diff --git a/src/dto/push-constant/PostProcessingPushConstant.h b/src/engine/dto/PostProcessingPushConstant.h similarity index 100% rename from src/dto/push-constant/PostProcessingPushConstant.h rename to src/engine/dto/PostProcessingPushConstant.h diff --git a/src/repository/world/components/PrimitiveComponent.cpp b/src/engine/dto/PrimitiveComponent.cpp similarity index 77% rename from src/repository/world/components/PrimitiveComponent.cpp rename to src/engine/dto/PrimitiveComponent.cpp index 26bf57c4..519167ca 100644 --- a/src/repository/world/components/PrimitiveComponent.cpp +++ b/src/engine/dto/PrimitiveComponent.cpp @@ -1,7 +1,7 @@ #include "PrimitiveComponent.h" -#include "../../../context/ApplicationContext.h" -#include "../../../enum/EntryType.h" -#include "../../../service/mesh/MeshData.h" +#include "../../ApplicationContext.h" +#include "../../editor/enum/EntryType.h" +#include "MeshData.h" namespace Metal { void PrimitiveComponent::registerFields() { @@ -19,17 +19,18 @@ namespace Metal { } void PrimitiveComponent::onUpdate(InspectableMember *member) { - if (member != nullptr && member->name == "meshId") { - MeshData *data = CTX.meshService.loadMeshData(meshId); - if (data != nullptr) { - if (CTX.worldRepository.registry.all_of(entityId)) { - CTX.worldRepository.registry.get(entityId).gizmoCenter = data->gizmoCenter; - } - delete data; - } - } - CTX.engineContext.setGISettingsUpdated(true); - CTX.rayTracingService.setNeedsMaterialUpdate(true); + // TODO - EVENT SYSTEM + // if (member != nullptr && member->name == "meshId") { + // MeshData *data = CTX.meshService.loadMeshData(meshId); + // if (data != nullptr) { + // if (CTX.worldRepository.registry.all_of(entityId)) { + // CTX.worldRepository.registry.get(entityId).gizmoCenter = data->gizmoCenter; + // } + // delete data; + // } + // } + // CTX.engineContext.setGISettingsUpdated(true); + // CTX.rayTracingService.setNeedsMaterialUpdate(true); } ComponentType PrimitiveComponent::getType() { diff --git a/src/repository/world/components/PrimitiveComponent.h b/src/engine/dto/PrimitiveComponent.h similarity index 83% rename from src/repository/world/components/PrimitiveComponent.h rename to src/engine/dto/PrimitiveComponent.h index d5229ac4..3f6e80ef 100644 --- a/src/repository/world/components/PrimitiveComponent.h +++ b/src/engine/dto/PrimitiveComponent.h @@ -1,12 +1,12 @@ #ifndef PRIMITIVE_COMPONENT_H #define PRIMITIVE_COMPONENT_H -#include "../impl/AbstractComponent.h" -#include "../../../util/Serializable.h" +#include "AbstractComponent.h" +#include "../../common/ISerialize.h" #include namespace Metal { - struct PrimitiveComponent final : AbstractComponent, Serializable { + struct PrimitiveComponent final : AbstractComponent, ISerialize { std::string meshId; std::string albedo; diff --git a/src/service/pipeline/ShaderModule.cpp b/src/engine/dto/ShaderModule.cpp similarity index 85% rename from src/service/pipeline/ShaderModule.cpp rename to src/engine/dto/ShaderModule.cpp index bbcdfe88..2149f95a 100644 --- a/src/service/pipeline/ShaderModule.cpp +++ b/src/engine/dto/ShaderModule.cpp @@ -1,6 +1,6 @@ #include "ShaderModule.h" -#include "../../context/vulkan/VulkanContext.h" +#include "../../core/vulkan/VulkanContext.h" namespace Metal { void ShaderModule::initialize(glslang_program_t *program) { diff --git a/src/service/pipeline/ShaderModule.h b/src/engine/dto/ShaderModule.h similarity index 100% rename from src/service/pipeline/ShaderModule.h rename to src/engine/dto/ShaderModule.h diff --git a/src/service/voxel/impl/SparseVoxelOctreeData.h b/src/engine/dto/SparseVoxelOctreeData.h similarity index 87% rename from src/service/voxel/impl/SparseVoxelOctreeData.h rename to src/engine/dto/SparseVoxelOctreeData.h index dac7a84b..8799a44e 100644 --- a/src/service/voxel/impl/SparseVoxelOctreeData.h +++ b/src/engine/dto/SparseVoxelOctreeData.h @@ -4,10 +4,10 @@ #include #include -#include "../../../util/Serializable.h" +#include "../../common/ISerialize.h" namespace Metal { - struct SparseVoxelOctreeData final : Serializable { + struct SparseVoxelOctreeData final : ISerialize { std::vector data{}; unsigned int voxelBufferOffset; diff --git a/src/service/texture/TextureData.h b/src/engine/dto/TextureData.h similarity index 100% rename from src/service/texture/TextureData.h rename to src/engine/dto/TextureData.h diff --git a/src/repository/world/components/TransformComponent.cpp b/src/engine/dto/TransformComponent.cpp similarity index 97% rename from src/repository/world/components/TransformComponent.cpp rename to src/engine/dto/TransformComponent.cpp index 73104008..a929c214 100644 --- a/src/repository/world/components/TransformComponent.cpp +++ b/src/engine/dto/TransformComponent.cpp @@ -1,6 +1,6 @@ #include "TransformComponent.h" #include "VolumeComponent.h" -#include "../../../context/ApplicationContext.h" +#include "../../ApplicationContext.h" #define ROTATION "Rotation" diff --git a/src/repository/world/components/TransformComponent.h b/src/engine/dto/TransformComponent.h similarity index 83% rename from src/repository/world/components/TransformComponent.h rename to src/engine/dto/TransformComponent.h index 3315bcfd..b6b4ab0b 100644 --- a/src/repository/world/components/TransformComponent.h +++ b/src/engine/dto/TransformComponent.h @@ -5,12 +5,12 @@ #include #include -#include "../impl/AbstractComponent.h" -#include "../../../util/Serializable.h" +#include "AbstractComponent.h" +#include "../../common/ISerialize.h" namespace Metal { - struct TransformComponent final : AbstractComponent, Serializable { + struct TransformComponent final : AbstractComponent, ISerialize { glm::mat4x4 model = glm::identity(); glm::vec3 translation{}; glm::vec3 rotationEuler = {0, 0, 0}; diff --git a/src/service/mesh/VertexData.h b/src/engine/dto/VertexData.h similarity index 96% rename from src/service/mesh/VertexData.h rename to src/engine/dto/VertexData.h index 5c366199..b9468cfb 100644 --- a/src/service/mesh/VertexData.h +++ b/src/engine/dto/VertexData.h @@ -4,7 +4,7 @@ #include #include -#include "../../util/serialization-definitions.h" +#include "../../common/serialization-definitions.h" namespace Metal { struct VertexData final { diff --git a/src/repository/world/components/VolumeComponent.cpp b/src/engine/dto/VolumeComponent.cpp similarity index 90% rename from src/repository/world/components/VolumeComponent.cpp rename to src/engine/dto/VolumeComponent.cpp index e0f7b99d..56829e59 100644 --- a/src/repository/world/components/VolumeComponent.cpp +++ b/src/engine/dto/VolumeComponent.cpp @@ -1,5 +1,5 @@ #include "VolumeComponent.h" -#include "../../../context/ApplicationContext.h" +#include "../../ApplicationContext.h" namespace Metal { void VolumeComponent::registerFields() { diff --git a/src/repository/world/components/VolumeComponent.h b/src/engine/dto/VolumeComponent.h similarity index 88% rename from src/repository/world/components/VolumeComponent.h rename to src/engine/dto/VolumeComponent.h index 4ea910c8..f77d5742 100644 --- a/src/repository/world/components/VolumeComponent.h +++ b/src/engine/dto/VolumeComponent.h @@ -1,12 +1,12 @@ #ifndef VOLUMECOMPONENT_H #define VOLUMECOMPONENT_H -#include "../impl/AbstractComponent.h" -#include "../../../util/Serializable.h" +#include "AbstractComponent.h" +#include "../../common/ISerialize.h" #include namespace Metal { - struct VolumeComponent final : AbstractComponent, Serializable { + struct VolumeComponent final : AbstractComponent, ISerialize { glm::vec3 albedo = glm::vec3(1.0f); float density = 1; float g = 0; diff --git a/src/dto/buffers/VolumeData.h b/src/engine/dto/VolumeData.h similarity index 100% rename from src/dto/buffers/VolumeData.h rename to src/engine/dto/VolumeData.h diff --git a/src/service/voxel/impl/VoxelData.h b/src/engine/dto/VoxelData.h similarity index 100% rename from src/service/voxel/impl/VoxelData.h rename to src/engine/dto/VoxelData.h diff --git a/src/enum/ComponentType.cpp b/src/engine/enum/ComponentType.cpp similarity index 86% rename from src/enum/ComponentType.cpp rename to src/engine/enum/ComponentType.cpp index 7dfbe93e..14bed4bc 100644 --- a/src/enum/ComponentType.cpp +++ b/src/engine/enum/ComponentType.cpp @@ -1,6 +1,13 @@ #include "ComponentType.h" -#include "../repository/world/WorldRepository.h" -#include "../context/ApplicationContext.h" + +#include "../EngineContext.h" +#include "../repository/WorldRepository.h" +#include "../service/RayTracingService.h" +#include "../../ApplicationContext.h" +#include "../dto/TransformComponent.h" +#include "../dto/PrimitiveComponent.h" +#include "../dto/VolumeComponent.h" +#include "../dto/MetadataComponent.h" #define DEFINE_COMPONENT(TYPE, NAME, JSON_KEY, ICON, DEPS, CLASS, CREATOR) \ { \ @@ -31,7 +38,7 @@ namespace Metal::ComponentTypes { [](WorldRepository &repo, entt::entity entityId) { auto &mesh = repo.registry.emplace_or_replace(entityId); mesh.setEntityId(entityId); - CTX.rayTracingService.markDirty(); + repo.rayTracingService->markDirty(); } ), DEFINE_COMPONENT( @@ -55,7 +62,7 @@ namespace Metal::ComponentTypes { [](WorldRepository &repo, entt::entity entityId) { auto &atmo = repo.registry.emplace_or_replace(entityId); atmo.setEntityId(entityId); - CTX.engineContext.setGISettingsUpdated(true); + repo.ctx->getSingleton().setGISettingsUpdated(true); } ) }; diff --git a/src/enum/ComponentType.h b/src/engine/enum/ComponentType.h similarity index 96% rename from src/enum/ComponentType.h rename to src/engine/enum/ComponentType.h index 6a5433d3..1b1350ad 100644 --- a/src/enum/ComponentType.h +++ b/src/engine/enum/ComponentType.h @@ -5,9 +5,9 @@ #include #include #include -#include "../common/interface/Icons.h" namespace Metal { + class ApplicationContext; class Inspectable; struct WorldRepository; diff --git a/src/enum/ResourceType.h b/src/engine/enum/ResourceType.h similarity index 82% rename from src/enum/ResourceType.h rename to src/engine/enum/ResourceType.h index a2ebd28c..c29f3423 100644 --- a/src/enum/ResourceType.h +++ b/src/engine/enum/ResourceType.h @@ -8,8 +8,7 @@ namespace Metal { PIPELINE, BUFFER, DESCRIPTOR_SET, - COMMAND_BUFFER_RECORDER, - PASS + COMMAND_BUFFER_RECORDER }; } diff --git a/src/context/engine/frame-builder/EngineFrame.cpp b/src/engine/frame-builder/EngineFrame.cpp similarity index 63% rename from src/context/engine/frame-builder/EngineFrame.cpp rename to src/engine/frame-builder/EngineFrame.cpp index 6f714a1b..66e5bb4a 100644 --- a/src/context/engine/frame-builder/EngineFrame.cpp +++ b/src/engine/frame-builder/EngineFrame.cpp @@ -12,10 +12,9 @@ namespace Metal { } } - - void EngineFrame::addPass(CommandBufferRecorder *recorder, const std::vector &p) { + void EngineFrame::addPass(CommandBufferRecorder *recorder, std::vector> p) { if (recorder) { - passes.emplace_back(recorder, p); + passes.emplace_back(recorder, std::move(p)); } } @@ -25,16 +24,6 @@ namespace Metal { } } - void EngineFrame::dispose() { - for (auto &pair: passes) { - delete pair.first; - for (auto *pass: pair.second) { - delete pass; - } - } - passes.clear(); - } - std::string EngineFrame::getScopedResourceId(const std::string &resourceId) const { return id + "_" + resourceId; } diff --git a/src/context/engine/frame-builder/EngineFrame.h b/src/engine/frame-builder/EngineFrame.h similarity index 75% rename from src/context/engine/frame-builder/EngineFrame.h rename to src/engine/frame-builder/EngineFrame.h index b86e3edc..992c611a 100644 --- a/src/context/engine/frame-builder/EngineFrame.h +++ b/src/engine/frame-builder/EngineFrame.h @@ -4,7 +4,7 @@ #include #include #include -#include "../../../repository/abstract/RuntimeResource.h" +#include "../resource/RuntimeResource.h" #include "../passes/CommandBufferRecorder.h" #include "../passes/AbstractPass.h" @@ -16,7 +16,7 @@ namespace Metal { std::string id; bool shouldRender = false; std::unordered_map resources; - std::vector > > passes; + std::vector > > > passes; public: explicit EngineFrame(std::string id); @@ -38,20 +38,10 @@ namespace Metal { return nullptr; } - void addPass(CommandBufferRecorder *recorder, const std::vector &p); - - [[nodiscard]] const std::vector > > & - getPasses() const { - return passes; - } + void addPass(CommandBufferRecorder *recorder, std::vector> p); void onSync(); - void dispose(); - - void destroy() { - } - [[nodiscard]] std::string getScopedResourceId(const std::string &resourceId) const; }; } diff --git a/src/context/engine/frame-builder/EngineFrameBuilder.cpp b/src/engine/frame-builder/EngineFrameBuilder.cpp similarity index 69% rename from src/context/engine/frame-builder/EngineFrameBuilder.cpp rename to src/engine/frame-builder/EngineFrameBuilder.cpp index 9b870737..7693f009 100644 --- a/src/context/engine/frame-builder/EngineFrameBuilder.cpp +++ b/src/engine/frame-builder/EngineFrameBuilder.cpp @@ -3,12 +3,11 @@ #include "structures/FramebufferBuilder.h" #include "structures/TextureBuilder.h" #include "structures/BufferBuilder.h" -#include "structures/PassBuilder.h" #include "structures/CommandBufferRecorderBuilder.h" #include "EngineFrame.h" #include "../../ApplicationContext.h" #include "../passes/CommandBufferRecorder.h" -#include "../render-pass/impl/tools/SelectionOutlinePass.h" +#include "../EngineContext.h" namespace Metal { EngineFrameBuilder::EngineFrameBuilder(std::string frameId) : frameId(std::move(frameId)) { @@ -17,7 +16,7 @@ namespace Metal { EngineFrameBuilder &EngineFrameBuilder::addFramebuffer(std::string id, const unsigned w, const unsigned h, glm::vec4 clearColor) { currentBuilder = std::make_shared(frameId + "_" + id, w, h, clearColor); - builders.push_back(currentBuilder); + storeBuilder(); return *this; } @@ -40,7 +39,7 @@ namespace Metal { EngineFrameBuilder &EngineFrameBuilder::addTexture(const std::string &id, unsigned w, unsigned h, VkFormat format) { currentBuilder = std::make_shared(frameId + "_" + id, w, h, format); - builders.push_back(currentBuilder); + storeBuilder(); return *this; } @@ -58,7 +57,7 @@ namespace Metal { ? VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT : VK_BUFFER_USAGE_STORAGE_BUFFER_BIT, properties, type); - builders.push_back(currentBuilder); + storeBuilder(); return *this; } @@ -73,19 +72,24 @@ namespace Metal { const bool clearBuffer) { currentBuilder = std::make_shared( frameId + "_" + id, frameId + "_" + framebufferId, clearBuffer); - builders.push_back(currentBuilder); + storeBuilder(); return *this; } + void EngineFrameBuilder::storeBuilder() { + ctx->injectDependencies(currentBuilder.get()); + builders.push_back(currentBuilder); + } + EngineFrameBuilder &EngineFrameBuilder::addComputeCommandBuffer(const std::string &id) { currentBuilder = std::make_shared(frameId + "_" + id); - builders.push_back(currentBuilder); + storeBuilder(); return *this; } - EngineFrameBuilder &EngineFrameBuilder::addPass(PassType type, const std::string &commandBufferId) { - currentBuilder = std::make_shared(Util::uuidV4(), type, frameId + "_" + commandBufferId); - builders.push_back(currentBuilder); + EngineFrameBuilder &EngineFrameBuilder::addPass(std::unique_ptr pass, + const std::string &commandBufferId) { + passes.emplace_back(std::move(pass), frameId + "_" + commandBufferId); return *this; } @@ -99,46 +103,38 @@ namespace Metal { return false; } - std::unique_ptr EngineFrameBuilder::build() { - auto frame = std::make_unique(frameId); + void EngineFrameBuilder::build() { + auto *frame = new EngineFrame(frameId); + engineContext->registerFrame(frame); std::unordered_map builtResources; for (const auto &builder: builders) { - auto *resource = builder->build(); - if (resource) { + if (auto *resource = builder->build()) { frame->addResource(resource); builtResources[builder->getId()] = resource; } } - std::unordered_map > recorderToPasses; + std::unordered_map > > recorderToPasses; std::vector recorderOrder; - for (const auto &builder: builders) { - if (auto *passBuilder = dynamic_cast(builder.get())) { - const auto cbId = passBuilder->getCommandBufferId(); - if (std::find(recorderOrder.begin(), recorderOrder.end(), cbId) == recorderOrder.end()) { - recorderOrder.push_back(cbId); - } + for (auto &pass: passes) { + recorderOrder.push_back(pass.commandBufferId); - if (builtResources.contains(builder->getId())) { - auto *pass = dynamic_cast(builtResources.at(builder->getId())); - if (pass) { - pass->frame = frame.get(); - pass->onInitialize(); - recorderToPasses[cbId].push_back(pass); - } - } - } + pass.pass->frame = frame; + ctx->injectDependencies(pass.pass.get()); + pass.pass->onInitialize(); + recorderToPasses[pass.commandBufferId].push_back(std::move(pass.pass)); } for (const auto &cbId: recorderOrder) { - auto *recorder = CTX.commandBufferRecorderService.getResource(cbId); - if (recorder) { - frame->addPass(recorder, recorderToPasses[cbId]); + if (auto *recorder = dynamic_cast(builtResources.at(cbId))) { + auto it = recorderToPasses.find(cbId); + if (it != recorderToPasses.end() && !it->second.empty()) { + frame->addPass(recorder, std::move(it->second)); + } } } - return frame; } } // Metal diff --git a/src/context/engine/frame-builder/EngineFrameBuilder.h b/src/engine/frame-builder/EngineFrameBuilder.h similarity index 63% rename from src/context/engine/frame-builder/EngineFrameBuilder.h rename to src/engine/frame-builder/EngineFrameBuilder.h index fd42fc69..fa72b744 100644 --- a/src/context/engine/frame-builder/EngineFrameBuilder.h +++ b/src/engine/frame-builder/EngineFrameBuilder.h @@ -1,30 +1,43 @@ #ifndef METAL_ENGINE_ENGINEFRAMEBUILDER_H #define METAL_ENGINE_ENGINEFRAMEBUILDER_H -#include #include #include #include #include #include +#include "../../common/IContextMember.h" #include "structures/ResourceBuilder.h" -#include "../../../enum/PassType.h" -#include "../../../service/buffer/BufferInstance.h" +#include "../resource/BufferInstance.h" namespace Metal { + class EngineContext; + class AbstractPass; class CommandBufferRecorder; struct FrameBufferInstance; struct DescriptorBinding; class ResourceBuilder; class EngineFrame; - class EngineFrameBuilder final { + struct PassData { + std::unique_ptr pass; + std::string commandBufferId; + }; + + class EngineFrameBuilder final : public IContextMember { std::string frameId; std::vector > builders{}; + std::vector passes{}; std::shared_ptr currentBuilder{}; + EngineContext *engineContext = nullptr; public: + std::vector getDependencies() override { + return {{"EngineContext", &engineContext}}; + } + explicit EngineFrameBuilder(std::string frameId = Util::uuidV4()); + EngineFrameBuilder &addFramebuffer(std::string id, unsigned w, unsigned h, glm::vec4 clearColor); EngineFrameBuilder &addFramebuffer(const std::string &id); @@ -33,7 +46,8 @@ namespace Metal { EngineFrameBuilder &addDepth(); - EngineFrameBuilder &addTexture(const std::string &id, unsigned w, unsigned h, VkFormat format = VK_FORMAT_R16G16B16A16_SFLOAT); + EngineFrameBuilder &addTexture(const std::string &id, unsigned w, unsigned h, + VkFormat format = VK_FORMAT_R16G16B16A16_SFLOAT); EngineFrameBuilder &addTexture(const std::string &id); @@ -42,15 +56,18 @@ namespace Metal { EngineFrameBuilder &addBuffer(const std::string &id); - EngineFrameBuilder &addCommandBuffer(const std::string &id, const std::string &framebufferId, bool clearBuffer = true); + EngineFrameBuilder &addCommandBuffer(const std::string &id, const std::string &framebufferId, + bool clearBuffer = true); + + void storeBuilder(); EngineFrameBuilder &addComputeCommandBuffer(const std::string &id); - EngineFrameBuilder &addPass(PassType type, const std::string &commandBufferId); + EngineFrameBuilder &addPass(std::unique_ptr pass, const std::string &commandBufferId); bool tryMatch(const std::string &id, ResourceType type); - std::unique_ptr build(); + void build(); }; } // Metal diff --git a/src/context/engine/frame-builder/structures/BufferBuilder.cpp b/src/engine/frame-builder/structures/BufferBuilder.cpp similarity index 53% rename from src/context/engine/frame-builder/structures/BufferBuilder.cpp rename to src/engine/frame-builder/structures/BufferBuilder.cpp index fd2ff11a..950d8ee9 100644 --- a/src/context/engine/frame-builder/structures/BufferBuilder.cpp +++ b/src/engine/frame-builder/structures/BufferBuilder.cpp @@ -1,20 +1,20 @@ #include "BufferBuilder.h" #include "../../../ApplicationContext.h" -#include "../../../../service/buffer/BufferInstance.h" -#include "../../../../service/buffer/BufferService.h" +#include "../../resource/BufferInstance.h" +#include "../../service/BufferService.h" namespace Metal { ResourceType BufferBuilder::getType() { - return ResourceType::BUFFER; + return BUFFER; } RuntimeResource *BufferBuilder::build() { - auto *buffer = CTX.bufferService.getResource(id); + auto *buffer = bufferService->getResource(id); if (buffer != nullptr) { return buffer; } - buffer = CTX.bufferService.createBuffer(id, size, usage, properties, type); + buffer = bufferService->createBuffer(id, size, usage, properties, type); buffer->setAsNoDisposal(); return buffer; diff --git a/src/context/engine/frame-builder/structures/BufferBuilder.h b/src/engine/frame-builder/structures/BufferBuilder.h similarity index 76% rename from src/context/engine/frame-builder/structures/BufferBuilder.h rename to src/engine/frame-builder/structures/BufferBuilder.h index 2620383c..acb66359 100644 --- a/src/context/engine/frame-builder/structures/BufferBuilder.h +++ b/src/engine/frame-builder/structures/BufferBuilder.h @@ -4,16 +4,23 @@ #include "ResourceBuilder.h" #include -#include "../../../../service/buffer/BufferInstance.h" +#include "../../resource/BufferInstance.h" namespace Metal { + class BufferService; + class BufferBuilder final : public ResourceBuilder { VkDeviceSize size; VkBufferUsageFlags usage; VkMemoryPropertyFlags properties; BufferType type; + BufferService *bufferService = nullptr; public: + std::vector getDependencies() override { + return {{"BufferService", &bufferService}}; + } + explicit BufferBuilder(const std::string &id, VkDeviceSize size, VkBufferUsageFlags usage, VkMemoryPropertyFlags properties, BufferType type) : ResourceBuilder(id), size(size), usage(usage), properties(properties), type(type) { diff --git a/src/engine/frame-builder/structures/CommandBufferRecorderBuilder.cpp b/src/engine/frame-builder/structures/CommandBufferRecorderBuilder.cpp new file mode 100644 index 00000000..ea77203c --- /dev/null +++ b/src/engine/frame-builder/structures/CommandBufferRecorderBuilder.cpp @@ -0,0 +1,13 @@ +#include "CommandBufferRecorderBuilder.h" +#include "../../service/CommandBufferRecorderService.h" +#include "../../service/FrameBufferService.h" + +namespace Metal { + RuntimeResource *CommandBufferRecorderBuilder::build() { + if (computeMode) { + return commandBufferRecorderService->createCompute(id); + } + auto *fbo = framebufferService->getResource(framebufferId); + return commandBufferRecorderService->create(id, fbo, clearBuffer); + } +} diff --git a/src/context/engine/frame-builder/structures/CommandBufferRecorderBuilder.h b/src/engine/frame-builder/structures/CommandBufferRecorderBuilder.h similarity index 62% rename from src/context/engine/frame-builder/structures/CommandBufferRecorderBuilder.h rename to src/engine/frame-builder/structures/CommandBufferRecorderBuilder.h index 22c7af72..19a3b56c 100644 --- a/src/context/engine/frame-builder/structures/CommandBufferRecorderBuilder.h +++ b/src/engine/frame-builder/structures/CommandBufferRecorderBuilder.h @@ -4,14 +4,27 @@ #include "ResourceBuilder.h" namespace Metal { + class CommandBufferRecorderService; + class FrameBufferService; + class CommandBufferRecorderBuilder final : public ResourceBuilder { std::string framebufferId; bool clearBuffer; bool computeMode; + FrameBufferService *framebufferService = nullptr; + CommandBufferRecorderService *commandBufferRecorderService = nullptr; public: + std::vector getDependencies() override { + return { + {"FrameBufferService", &framebufferService}, + {"CommandBufferRecorderService", &commandBufferRecorderService} + }; + } + explicit CommandBufferRecorderBuilder(const std::string &id, std::string framebufferId, bool clearBuffer = true) - : ResourceBuilder(id), framebufferId(std::move(framebufferId)), clearBuffer(clearBuffer), computeMode(false) { + : ResourceBuilder(id), framebufferId(std::move(framebufferId)), clearBuffer(clearBuffer), + computeMode(false) { } explicit CommandBufferRecorderBuilder(const std::string &id) @@ -23,9 +36,9 @@ namespace Metal { } RuntimeResource *build() override; - + bool isComputeMode() const { return computeMode; } - const std::string& getFramebufferId() const { return framebufferId; } + const std::string &getFramebufferId() const { return framebufferId; } bool shouldClearBuffer() const { return clearBuffer; } }; } diff --git a/src/engine/frame-builder/structures/FramebufferBuilder.cpp b/src/engine/frame-builder/structures/FramebufferBuilder.cpp new file mode 100644 index 00000000..63adbdf7 --- /dev/null +++ b/src/engine/frame-builder/structures/FramebufferBuilder.cpp @@ -0,0 +1,31 @@ +#include "FramebufferBuilder.h" +#include "../../../ApplicationContext.h" +#include "../../service/FrameBufferService.h" +#include "../../resource/FrameBufferInstance.h" + +namespace Metal { + ResourceType FramebufferBuilder::getType() { + return FRAMEBUFFER; + } + + RuntimeResource *FramebufferBuilder::build() { + FrameBufferInstance *fbo = frameBufferService->getResource(id); + if (fbo != nullptr) { + return fbo; + } + + fbo = frameBufferService->createFrameBuffer(id, w, h, clearColor); + + for (const auto &attachment: attachments) { + frameBufferService->createAttachment(attachment.format, attachment.usage, fbo); + } + + if (hasDepth) { + frameBufferService->createDepthAttachment(fbo); + } + + frameBufferService->createRenderPass(fbo); + + return fbo; + } +} // Metal diff --git a/src/context/engine/frame-builder/structures/FramebufferBuilder.h b/src/engine/frame-builder/structures/FramebufferBuilder.h similarity index 84% rename from src/context/engine/frame-builder/structures/FramebufferBuilder.h rename to src/engine/frame-builder/structures/FramebufferBuilder.h index f5ebead5..d1b4807d 100644 --- a/src/context/engine/frame-builder/structures/FramebufferBuilder.h +++ b/src/engine/frame-builder/structures/FramebufferBuilder.h @@ -6,6 +6,7 @@ #include "ResourceBuilder.h" namespace Metal { + class FrameBufferService; struct FrameBufferInstance; struct FramebufferAttachmentBuilder { @@ -20,8 +21,12 @@ namespace Metal { glm::vec4 clearColor; std::vector attachments; bool hasDepth = false; - + FrameBufferService *frameBufferService = nullptr; public: + std::vector getDependencies() override { + return {{"FrameBufferService", &frameBufferService}}; + } + explicit FramebufferBuilder(const std::string &id, const unsigned w, const unsigned h, glm::vec4 clearColor) : ResourceBuilder(id), clearColor(clearColor), w(w), h(h) { } diff --git a/src/context/engine/frame-builder/structures/ResourceBuilder.h b/src/engine/frame-builder/structures/ResourceBuilder.h similarity index 73% rename from src/context/engine/frame-builder/structures/ResourceBuilder.h rename to src/engine/frame-builder/structures/ResourceBuilder.h index ee26de66..1a5c8ba0 100644 --- a/src/context/engine/frame-builder/structures/ResourceBuilder.h +++ b/src/engine/frame-builder/structures/ResourceBuilder.h @@ -1,11 +1,13 @@ #ifndef METAL_ENGINE_RESOURCEBUILDER_H #define METAL_ENGINE_RESOURCEBUILDER_H #include -#include "../../../../enum/ResourceType.h" +#include "../../enum/ResourceType.h" +#include "../../../common/IContextMember.h" namespace Metal { class RuntimeResource; - class ResourceBuilder { + + class ResourceBuilder : public IContextMember { protected: std::string id; @@ -16,9 +18,10 @@ namespace Metal { [[nodiscard]] std::string getId() const { return id; } + virtual ~ResourceBuilder() = default; - virtual RuntimeResource* build() = 0; + virtual RuntimeResource *build() = 0; virtual ResourceType getType() = 0; }; diff --git a/src/context/engine/frame-builder/structures/TextureBuilder.cpp b/src/engine/frame-builder/structures/TextureBuilder.cpp similarity index 52% rename from src/context/engine/frame-builder/structures/TextureBuilder.cpp rename to src/engine/frame-builder/structures/TextureBuilder.cpp index 72d776a6..7b03b40e 100644 --- a/src/context/engine/frame-builder/structures/TextureBuilder.cpp +++ b/src/engine/frame-builder/structures/TextureBuilder.cpp @@ -1,19 +1,19 @@ #include "TextureBuilder.h" -#include "../../../ApplicationContext.h" -#include "../../../../service/texture/TextureInstance.h" +#include "../../resource/TextureInstance.h" +#include "../../service/TextureService.h" namespace Metal { ResourceType TextureBuilder::getType() { - return ResourceType::TEXTURE; + return TEXTURE; } RuntimeResource *TextureBuilder::build() { - auto *texture = CTX.textureService.getResource(id); + auto *texture = textureService->getResource(id); if (texture != nullptr) { return texture; } - texture = CTX.textureService.createForCompute(id, w, h, format); + texture = textureService->createForCompute(id, w, h, format); texture->setAsNoDisposal(); return texture; diff --git a/src/context/engine/frame-builder/structures/TextureBuilder.h b/src/engine/frame-builder/structures/TextureBuilder.h similarity index 75% rename from src/context/engine/frame-builder/structures/TextureBuilder.h rename to src/engine/frame-builder/structures/TextureBuilder.h index 1015fdae..09618bf9 100644 --- a/src/context/engine/frame-builder/structures/TextureBuilder.h +++ b/src/engine/frame-builder/structures/TextureBuilder.h @@ -5,12 +5,18 @@ #include "ResourceBuilder.h" namespace Metal { + class TextureService; + class TextureBuilder final : public ResourceBuilder { unsigned w; unsigned h; VkFormat format; - + TextureService *textureService = nullptr; public: + std::vector getDependencies() override { + return {{"TextureService", &textureService}}; + } + explicit TextureBuilder(const std::string &id, unsigned w, unsigned h, VkFormat format = VK_FORMAT_R16G16B16A16_SFLOAT) : ResourceBuilder(id), w(w), h(h), format(format) { } diff --git a/src/context/engine/compute-pass/AbstractComputePass.cpp b/src/engine/passes/AbstractComputePass.cpp similarity index 95% rename from src/context/engine/compute-pass/AbstractComputePass.cpp rename to src/engine/passes/AbstractComputePass.cpp index 1bc48f6d..bed92677 100644 --- a/src/context/engine/compute-pass/AbstractComputePass.cpp +++ b/src/engine/passes/AbstractComputePass.cpp @@ -1,11 +1,11 @@ #include "AbstractComputePass.h" -#include "../../../context/ApplicationContext.h" -#include "../../../service/pipeline/PipelineInstance.h" -#include "../../../service/texture/TextureInstance.h" -#include "../../../util/ImageUtils.h" +#include "../../ApplicationContext.h" +#include "../resource/PipelineInstance.h" +#include "../resource/TextureInstance.h" +#include "../util/ImageUtils.h" namespace Metal { - AbstractComputePass::AbstractComputePass(const std::string &id) : AbstractPass(id, true) { + AbstractComputePass::AbstractComputePass() : AbstractPass(true) { } void AbstractComputePass::recordDispatch(const unsigned int groupX, const unsigned int groupY, diff --git a/src/context/engine/compute-pass/AbstractComputePass.h b/src/engine/passes/AbstractComputePass.h similarity index 90% rename from src/context/engine/compute-pass/AbstractComputePass.h rename to src/engine/passes/AbstractComputePass.h index 8075789c..20cd53c2 100644 --- a/src/context/engine/compute-pass/AbstractComputePass.h +++ b/src/engine/passes/AbstractComputePass.h @@ -2,7 +2,7 @@ #define ABSTRACTCOMPUTEPASS_H #include -#include "../passes/AbstractPass.h" +#include "AbstractPass.h" namespace Metal { struct WorldRepository; @@ -13,7 +13,7 @@ namespace Metal { class AbstractComputePass : public AbstractPass { public: - explicit AbstractComputePass(const std::string &id); + explicit AbstractComputePass(); void recordDispatch(unsigned int groupX, unsigned int groupY, unsigned int groupZ) const; diff --git a/src/context/engine/passes/AbstractPass.cpp b/src/engine/passes/AbstractPass.cpp similarity index 84% rename from src/context/engine/passes/AbstractPass.cpp rename to src/engine/passes/AbstractPass.cpp index 31c60932..367c8fad 100644 --- a/src/context/engine/passes/AbstractPass.cpp +++ b/src/engine/passes/AbstractPass.cpp @@ -1,17 +1,10 @@ #include "AbstractPass.h" #include "../frame-builder/EngineFrame.h" -#include "../../../context/ApplicationContext.h" -#include "../../../service/pipeline/PipelineInstance.h" +#include "../../ApplicationContext.h" +#include "../resource/PipelineInstance.h" namespace Metal { - AbstractPass::AbstractPass(const std::string &id, bool isComputePass) : RuntimeResource(id), - isComputePass(isComputePass) { - } - - AbstractPass::~AbstractPass() { - if (pipelineInstance != nullptr) { - CTX.pipelineService.dispose(pipelineInstance->getId()); - } + AbstractPass::AbstractPass(bool isComputePass) : isComputePass(isComputePass) { } void AbstractPass::recordPushConstant(const void *data) { diff --git a/src/context/engine/passes/AbstractPass.h b/src/engine/passes/AbstractPass.h similarity index 73% rename from src/context/engine/passes/AbstractPass.h rename to src/engine/passes/AbstractPass.h index 549a49f5..2cd69f9f 100644 --- a/src/context/engine/passes/AbstractPass.h +++ b/src/engine/passes/AbstractPass.h @@ -3,8 +3,11 @@ #include #include #include -#include "../../../common/AbstractRuntimeComponent.h" -#include "../../../repository/abstract/RuntimeResource.h" + +#include "../../common/IContextMember.h" +#include "../../common/ISync.h" +#include "../../common/IInit.h" +#include "../resource/RuntimeResource.h" namespace Metal { class EngineFrame; @@ -13,7 +16,7 @@ namespace Metal { class StreamingService; struct PipelineInstance; - class AbstractPass : public AbstractRuntimeComponent, public RuntimeResource { + class AbstractPass : public IContextMember, public ISync, public IInit { bool isComputePass; public: @@ -21,13 +24,7 @@ namespace Metal { VkCommandBuffer vkCommandBuffer = VK_NULL_HANDLE; PipelineInstance *pipelineInstance = nullptr; - explicit AbstractPass(const std::string &id, bool isComputePass); - - virtual ~AbstractPass() override; - - ResourceType resourceType() override { - return PASS; - } + explicit AbstractPass( bool isComputePass); void recordPushConstant(const void *data); @@ -39,7 +36,7 @@ namespace Metal { this->vkCommandBuffer = vkCommandBuffer; } - PipelineInstance *getPipeline() { + PipelineInstance *getPipeline() const { return pipelineInstance; } diff --git a/src/context/engine/render-pass/AbstractRenderPass.cpp b/src/engine/passes/AbstractRenderPass.cpp similarity index 73% rename from src/context/engine/render-pass/AbstractRenderPass.cpp rename to src/engine/passes/AbstractRenderPass.cpp index 48d82395..15708631 100644 --- a/src/context/engine/render-pass/AbstractRenderPass.cpp +++ b/src/engine/passes/AbstractRenderPass.cpp @@ -1,11 +1,10 @@ #include "AbstractRenderPass.h" -#include "../../../context/ApplicationContext.h" -#include "../../../service/pipeline/PipelineInstance.h" -#include "../../../service/mesh/MeshInstance.h" -#include "../../../service/buffer/BufferInstance.h" +#include "../../ApplicationContext.h" +#include "../resource/MeshInstance.h" +#include "../resource/BufferInstance.h" namespace Metal { - AbstractRenderPass::AbstractRenderPass(const std::string &id) : AbstractPass(id, false) { + AbstractRenderPass::AbstractRenderPass() : AbstractPass(false) { } void AbstractRenderPass::recordDrawSimpleInstanced(const unsigned int vertexCount, const unsigned int instanceCount) const { diff --git a/src/context/engine/render-pass/AbstractRenderPass.h b/src/engine/passes/AbstractRenderPass.h similarity index 83% rename from src/context/engine/render-pass/AbstractRenderPass.h rename to src/engine/passes/AbstractRenderPass.h index 39b4203c..e751c57c 100644 --- a/src/context/engine/render-pass/AbstractRenderPass.h +++ b/src/engine/passes/AbstractRenderPass.h @@ -1,7 +1,7 @@ #ifndef ABSTRACTRENDERPASS_H #define ABSTRACTRENDERPASS_H -#include "../passes/AbstractPass.h" +#include "AbstractPass.h" #include "vulkan/vulkan.h" namespace Metal { @@ -12,7 +12,7 @@ namespace Metal { class AbstractRenderPass : public AbstractPass { public: - explicit AbstractRenderPass(const std::string &id); + explicit AbstractRenderPass(); void recordDrawSimpleInstanced(unsigned int vertexCount, unsigned int instanceCount) const; diff --git a/src/context/engine/passes/CommandBufferRecorder.cpp b/src/engine/passes/CommandBufferRecorder.cpp similarity index 80% rename from src/context/engine/passes/CommandBufferRecorder.cpp rename to src/engine/passes/CommandBufferRecorder.cpp index 90bc3f73..326f9765 100644 --- a/src/context/engine/passes/CommandBufferRecorder.cpp +++ b/src/engine/passes/CommandBufferRecorder.cpp @@ -1,24 +1,24 @@ #include "CommandBufferRecorder.h" #include -#include -#include "../../../service/descriptor/DescriptorInstance.h" -#include "../../../service/framebuffer/FrameBufferInstance.h" -#include "../../../service/pipeline/PipelineInstance.h" +#include "../resource/FrameBufferInstance.h" +#include "../resource/PipelineInstance.h" #include "../../ApplicationContext.h" -#include "../render-pass/AbstractRenderPass.h" -#include "../../../util/VulkanUtils.h" +#include "AbstractRenderPass.h" +#include "../../core/vulkan/VulkanUtils.h" +#include "../../core/vulkan/VulkanContext.h" +#include "../../core/FrameService.h" namespace Metal { - void CommandBufferRecorder::createCommandBuffer() { + void CommandBufferRecorder::onInitialize() { VkCommandBufferAllocateInfo allocInfo{}; allocInfo.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO; - allocInfo.commandPool = CTX.vulkanContext.commandPool; + allocInfo.commandPool = vulkanContext->commandPool; allocInfo.level = VK_COMMAND_BUFFER_LEVEL_PRIMARY; allocInfo.commandBufferCount = MAX_FRAMES_IN_FLIGHT; VulkanUtils::CheckVKResult( - vkAllocateCommandBuffers(CTX.vulkanContext.device.device, &allocInfo, + vkAllocateCommandBuffers(vulkanContext->device.device, &allocInfo, _commandBuffers.data())); } @@ -36,12 +36,10 @@ namespace Metal { scissor.extent.width = frameBuffer->bufferWidth; scissor.extent.height = frameBuffer->bufferHeight; - createCommandBuffer(); computePassMode = false; } - CommandBufferRecorder::CommandBufferRecorder(std::string id) : RuntimeResource(std::move(id)) { - createCommandBuffer(); + CommandBufferRecorder::CommandBufferRecorder(const std::string &id) : RuntimeResource(id) { computePassMode = true; } @@ -72,8 +70,8 @@ namespace Metal { } void CommandBufferRecorder::recordCommands( - const std::vector &passes) const { - auto vkCommandBuffer = _commandBuffers[CTX.getFrameIndex()]; + const std::vector> &passes) const { + auto vkCommandBuffer = _commandBuffers[frameService->getFrameIndex()]; VkCommandBufferBeginInfo beginInfo{}; beginInfo.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO; vkBeginCommandBuffer(vkCommandBuffer, &beginInfo); @@ -89,11 +87,11 @@ namespace Metal { } vkEndCommandBuffer(vkCommandBuffer); - CTX.vulkanContext.pushCommandBuffer(vkCommandBuffer); + vulkanContext->pushCommandBuffer(vkCommandBuffer); } void CommandBufferRecorder::RecordCommandsInternal( - const std::vector &passes, + const std::vector> &passes, VkCommandBuffer vkCommandBuffer) { for (auto &pass: passes) { pass->setCommandBuffer(vkCommandBuffer); diff --git a/src/context/engine/passes/CommandBufferRecorder.h b/src/engine/passes/CommandBufferRecorder.h similarity index 56% rename from src/context/engine/passes/CommandBufferRecorder.h rename to src/engine/passes/CommandBufferRecorder.h index ad428c13..95a3733d 100644 --- a/src/context/engine/passes/CommandBufferRecorder.h +++ b/src/engine/passes/CommandBufferRecorder.h @@ -1,34 +1,44 @@ #ifndef RENDERPASS_H #define RENDERPASS_H -#include "../../../repository/abstract/RuntimeResource.h" +#include "../resource/RuntimeResource.h" #include #include -#include "../../../service/pipeline/PipelineInstance.h" -#include "../../../util/VulkanUtils.h" + +#include "../../common/IInit.h" +#include "../resource/PipelineInstance.h" +#include "../../core/vulkan/VulkanUtils.h" namespace Metal { + class FrameService; class AbstractPass; class ApplicationContext; struct FrameBufferInstance; - class CommandBufferRecorder final : public RuntimeResource { + class CommandBufferRecorder final : public RuntimeResource, public IInit { std::array _commandBuffers{}; VkViewport viewport{}; VkRect2D scissor{}; VkRenderPassBeginInfo renderPassInfo{}; std::vector clearColors{}; bool computePassMode; + FrameService *frameService = nullptr; static void RecordCommandsInternal( - const std::vector &passes, + const std::vector > &passes, VkCommandBuffer vkCommandBuffer); void createRenderPassInfo(const FrameBufferInstance *frameBuffer, bool clearBuffer); public: + std::vector getDependencies() override { + return {{"FrameService", &frameService}, {"VulkanContext", &vulkanContext}}; + } + + void onInitialize() override; + explicit CommandBufferRecorder(std::string id, FrameBufferInstance *frameBuffer, bool clearBuffer = true); - explicit CommandBufferRecorder(std::string id); + explicit CommandBufferRecorder(const std::string &id); ResourceType resourceType() override { return COMMAND_BUFFER_RECORDER; @@ -36,7 +46,7 @@ namespace Metal { void createCommandBuffer(); - void recordCommands(const std::vector &passes) const; + void recordCommands(const std::vector > &passes) const; }; } // Metal diff --git a/src/context/engine/compute-pass/impl/HWRayTracingPass.cpp b/src/engine/passes/impl/HWRayTracingPass.cpp similarity index 55% rename from src/context/engine/compute-pass/impl/HWRayTracingPass.cpp rename to src/engine/passes/impl/HWRayTracingPass.cpp index dcba2bfa..af2574ea 100644 --- a/src/context/engine/compute-pass/impl/HWRayTracingPass.cpp +++ b/src/engine/passes/impl/HWRayTracingPass.cpp @@ -1,11 +1,13 @@ -#include "./HWRayTracingPass.h" -#include "../../../ApplicationContext.h" -#include "../../../../service/framebuffer/FrameBufferInstance.h" -#include "../../../../service/pipeline/PipelineBuilder.h" -#include "../../../../service/pipeline/PipelineInstance.h" -#include "../../../../service/texture/TextureInstance.h" -#include "../../../../service/raytracing/RayTracingService.h" -#include "../../../../enum/EngineResourceIDs.h" +#include "HWRayTracingPass.h" +#include "../../dto/PipelineBuilder.h" +#include "../../resource/PipelineInstance.h" +#include "../../resource/TextureInstance.h" +#include "../../service/RayTracingService.h" +#include "../../service/PipelineService.h" +#include "../../../core/vulkan/VulkanContext.h" +#include "../../../engine/EngineContext.h" +#include "../../../engine/repository/EngineRepository.h" +#include "../../../editor/enum/EngineResourceIDs.h" namespace Metal { void HWRayTracingPass::onInitialize() { @@ -15,16 +17,16 @@ namespace Metal { "rt/HWRayTracing.rchit") .setPushConstantsSize(sizeof(HWRayTracingPushConstant)) .addBufferBinding(getScopedResourceId(RID_GLOBAL_DATA)) - .addAccelerationStructureBinding(CTX.rayTracingService.getTLAS()) + .addAccelerationStructureBinding(rayTracingService->getTLAS()) .addStorageImageBinding(getScopedResourceId(RID_ACCUMULATED_FRAME)) .addStorageImageBinding(getScopedResourceId(RID_GBUFFER_POSITION_INDEX)) .addStorageImageBinding(getScopedResourceId(RID_GBUFFER_NORMAL)) .addBufferBinding(getScopedResourceId(RID_LIGHT_BUFFER)) .addBufferBinding(getScopedResourceId(RID_VOLUMES_BUFFER)) .addBufferBinding(getScopedResourceId(RID_MESH_METADATA_BUFFER)) - .addCombinedImageSamplerBinding(CTX.vulkanContext.vkImageSampler, VK_NULL_HANDLE, + .addCombinedImageSamplerBinding(vulkanContext->vkImageSampler, VK_NULL_HANDLE, VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL, 1000); - pipelineInstance = CTX.pipelineService.createPipeline(builder); + pipelineInstance = pipelineService->createPipeline(builder); } void HWRayTracingPass::onSync() { @@ -34,9 +36,9 @@ namespace Metal { auto *previousPositionIndex = frame->getResourceAs(RID_PREVIOUS_POSITION_INDEX); auto *previousNormal = frame->getResourceAs(RID_PREVIOUS_NORMAL); - if (isFirstRun || CTX.engineContext.isCameraUpdated() || CTX.engineContext.isGISettingsUpdated()) { + if (isFirstRun || engineContext->isCameraUpdated() || engineContext->isGISettingsUpdated()) { clearTexture(accumulatedFrame->vkImage); - CTX.engineContext.resetPathTracerAccumulationCount(); + engineContext->resetPathTracerAccumulationCount(); isFirstRun = false; } @@ -47,24 +49,24 @@ namespace Metal { startWriting(gBufferNormal->vkImage); // Trace rays - pushConstant.pathTracerMultiplier = CTX.engineRepository.pathTracerMultiplier; - pushConstant.volumeShadowSteps = CTX.engineRepository.volumeShadowSteps; - pushConstant.isAtmosphereEnabled = CTX.engineRepository.atmosphereEnabled; + pushConstant.pathTracerMultiplier = engineRepository->pathTracerMultiplier; + pushConstant.volumeShadowSteps = engineRepository->volumeShadowSteps; + pushConstant.isAtmosphereEnabled = engineRepository->atmosphereEnabled; - pushConstant.multipleImportanceSampling = CTX.engineRepository.multipleImportanceSampling; - pushConstant.pathTracerSamples = CTX.engineRepository.pathTracerSamples; - pushConstant.pathTracerBounces = CTX.engineRepository.pathTracerBounces; - pushConstant.pathTracingEmissiveFactor = CTX.engineRepository.pathTracingEmissiveFactor; - pushConstant.shouldTrace = CTX.rayTracingService.isReady(); + pushConstant.multipleImportanceSampling = engineRepository->multipleImportanceSampling; + pushConstant.pathTracerSamples = engineRepository->pathTracerSamples; + pushConstant.pathTracerBounces = engineRepository->pathTracerBounces; + pushConstant.pathTracingEmissiveFactor = engineRepository->pathTracingEmissiveFactor; + pushConstant.shouldTrace = rayTracingService->isReady(); - pushConstant.dofEnabled = CTX.engineRepository.dofEnabled; - pushConstant.dofFocusDistance = CTX.engineRepository.dofFocusDistance; - pushConstant.dofAperture = CTX.engineRepository.dofAperture; - pushConstant.dofFocalLength = CTX.engineRepository.dofFocalLength; + pushConstant.dofEnabled = engineRepository->dofEnabled; + pushConstant.dofFocusDistance = engineRepository->dofFocusDistance; + pushConstant.dofAperture = engineRepository->dofAperture; + pushConstant.dofFocalLength = engineRepository->dofFocalLength; recordPushConstant(&pushConstant); - CTX.vulkanContext.vkCmdTraceRaysKHR( + vulkanContext->vkCmdTraceRaysKHR( vkCommandBuffer, &pipelineInstance->raygenRegion, &pipelineInstance->missRegion, diff --git a/src/engine/passes/impl/HWRayTracingPass.h b/src/engine/passes/impl/HWRayTracingPass.h new file mode 100644 index 00000000..9774c65d --- /dev/null +++ b/src/engine/passes/impl/HWRayTracingPass.h @@ -0,0 +1,40 @@ +#ifndef HWRAYTRACINGPASS_H +#define HWRAYTRACINGPASS_H +#include "../AbstractComputePass.h" +#include "../../dto/HWRayTracingPushConstant.h" + +namespace Metal { + class RayTracingService; + class PipelineService; + class VulkanContext; + class EngineContext; + struct EngineRepository; + + class HWRayTracingPass final : public AbstractComputePass { + bool isFirstRun = true; + HWRayTracingPushConstant pushConstant{}; + + RayTracingService *rayTracingService = nullptr; + PipelineService *pipelineService = nullptr; + VulkanContext *vulkanContext = nullptr; + EngineContext *engineContext = nullptr; + EngineRepository *engineRepository = nullptr; + + public: + std::vector getDependencies() override { + return { + {"RayTracingService", &rayTracingService}, + {"PipelineService", &pipelineService}, + {"VulkanContext", &vulkanContext}, + {"EngineContext", &engineContext}, + {"EngineRepository", &engineRepository} + }; + } + + void onSync() override; + + void onInitialize() override; + }; +} // Metal + +#endif //HWRAYTRACINGPASS_H diff --git a/src/context/engine/render-pass/impl/PostProcessingPass.cpp b/src/engine/passes/impl/PostProcessingPass.cpp similarity index 61% rename from src/context/engine/render-pass/impl/PostProcessingPass.cpp rename to src/engine/passes/impl/PostProcessingPass.cpp index db325602..f16d3d5d 100644 --- a/src/context/engine/render-pass/impl/PostProcessingPass.cpp +++ b/src/engine/passes/impl/PostProcessingPass.cpp @@ -1,9 +1,11 @@ #include "PostProcessingPass.h" - -#include "../../../../context/ApplicationContext.h" - -#include "../../../../service/pipeline/PipelineBuilder.h" -#include "../../../../enum/EngineResourceIDs.h" +#include "../../dto/PipelineBuilder.h" +#include "../../service/PipelineService.h" +#include "../../../core/vulkan/VulkanContext.h" +#include "../../../engine/repository/WorldRepository.h" +#include "../../../editor/enum/EngineResourceIDs.h" +#include "../../frame-builder/EngineFrame.h" +#include "../../resource/TextureInstance.h" namespace Metal { @@ -14,12 +16,12 @@ namespace Metal { "PostProcessing.frag" ) .setPushConstantsSize(sizeof(PostProcessingPushConstant)) - .addCombinedImageSamplerBinding(CTX.vulkanContext.vkImageSampler, frame->getResourceAs(RID_DENOISED_FRAME)->vkImageView); - pipelineInstance = CTX.pipelineService.createPipeline(ppPipelineBuilder); + .addCombinedImageSamplerBinding(vulkanContext->vkImageSampler, frame->getResourceAs(RID_DENOISED_FRAME)->vkImageView); + pipelineInstance = pipelineService->createPipeline(ppPipelineBuilder); } void PostProcessingPass::onSync() { - auto &camera = CTX.worldRepository.camera; + auto &camera = worldRepository->camera; pushConstant.distortionIntensity = camera.distortionIntensity; pushConstant.chromaticAberrationIntensity = camera.chromaticAberrationIntensity; pushConstant.distortionEnabled = camera.distortionEnabled; diff --git a/src/engine/passes/impl/PostProcessingPass.h b/src/engine/passes/impl/PostProcessingPass.h new file mode 100644 index 00000000..15b31a27 --- /dev/null +++ b/src/engine/passes/impl/PostProcessingPass.h @@ -0,0 +1,33 @@ +#ifndef POSTPROCESSINGPASS_H +#define POSTPROCESSINGPASS_H +#include "../AbstractRenderPass.h" +#include "../../dto/PostProcessingPushConstant.h" + +namespace Metal { + class VulkanContext; + class PipelineService; + struct WorldRepository; + + class PostProcessingPass final : public AbstractRenderPass { + PostProcessingPushConstant pushConstant{}; + + VulkanContext *vulkanContext = nullptr; + PipelineService *pipelineService = nullptr; + WorldRepository *worldRepository = nullptr; + + public: + std::vector getDependencies() override { + return { + {"VulkanContext", &vulkanContext}, + {"PipelineService", &pipelineService}, + {"WorldRepository", &worldRepository} + }; + } + + void onInitialize() override; + + void onSync() override; + }; +} // Metal + +#endif //POSTPROCESSINGPASS_H diff --git a/src/context/engine/compute-pass/impl/SpatialFilterPass.cpp b/src/engine/passes/impl/SpatialFilterPass.cpp similarity index 78% rename from src/context/engine/compute-pass/impl/SpatialFilterPass.cpp rename to src/engine/passes/impl/SpatialFilterPass.cpp index f59bc568..ee34a76f 100644 --- a/src/context/engine/compute-pass/impl/SpatialFilterPass.cpp +++ b/src/engine/passes/impl/SpatialFilterPass.cpp @@ -1,8 +1,9 @@ #include "SpatialFilterPass.h" -#include "../../../ApplicationContext.h" -#include "../../../../service/pipeline/PipelineBuilder.h" -#include "../../../../service/texture/TextureInstance.h" -#include "../../../../enum/EngineResourceIDs.h" +#include "../../dto/PipelineBuilder.h" +#include "../../resource/TextureInstance.h" +#include "../../service/PipelineService.h" +#include "../../frame-builder/EngineFrame.h" +#include "../../../editor/enum/EngineResourceIDs.h" namespace Metal { void SpatialFilterPass::onInitialize() { @@ -12,7 +13,7 @@ namespace Metal { .addStorageImageBinding(getScopedResourceId(RID_DENOISED_FRAME)) .addStorageImageBinding(getScopedResourceId(RID_GBUFFER_POSITION_INDEX)) .addStorageImageBinding(getScopedResourceId(RID_GBUFFER_NORMAL)); - pipelineInstance = CTX.pipelineService.createPipeline(spatialBuilder); + pipelineInstance = pipelineService->createPipeline(spatialBuilder); } void SpatialFilterPass::onSync() { diff --git a/src/context/engine/compute-pass/impl/SpatialFilterPass.h b/src/engine/passes/impl/SpatialFilterPass.h similarity index 57% rename from src/context/engine/compute-pass/impl/SpatialFilterPass.h rename to src/engine/passes/impl/SpatialFilterPass.h index ef66e4b3..515cca51 100644 --- a/src/context/engine/compute-pass/impl/SpatialFilterPass.h +++ b/src/engine/passes/impl/SpatialFilterPass.h @@ -3,9 +3,16 @@ #include "../AbstractComputePass.h" namespace Metal { + class PipelineService; + class SpatialFilterPass final : public AbstractComputePass { + PipelineService *pipelineService = nullptr; + public: - explicit SpatialFilterPass(const std::string &id) : AbstractComputePass(id) { + std::vector getDependencies() override { + return { + {"PipelineService", &pipelineService} + }; } void onSync() override; diff --git a/src/context/engine/compute-pass/impl/TemporalAccumulationPass.cpp b/src/engine/passes/impl/TemporalAccumulationPass.cpp similarity index 79% rename from src/context/engine/compute-pass/impl/TemporalAccumulationPass.cpp rename to src/engine/passes/impl/TemporalAccumulationPass.cpp index 3a885a0a..68c751aa 100644 --- a/src/context/engine/compute-pass/impl/TemporalAccumulationPass.cpp +++ b/src/engine/passes/impl/TemporalAccumulationPass.cpp @@ -1,8 +1,9 @@ #include "TemporalAccumulationPass.h" -#include "../../../ApplicationContext.h" -#include "../../../../service/pipeline/PipelineBuilder.h" -#include "../../../../service/texture/TextureInstance.h" -#include "../../../../enum/EngineResourceIDs.h" +#include "../../dto/PipelineBuilder.h" +#include "../../resource/TextureInstance.h" +#include "../../service/PipelineService.h" +#include "../../frame-builder/EngineFrame.h" +#include "../../../editor/enum/EngineResourceIDs.h" namespace Metal { void TemporalAccumulationPass::onInitialize() { @@ -15,7 +16,7 @@ namespace Metal { .addStorageImageBinding(getScopedResourceId(RID_PREVIOUS_POSITION_INDEX)) .addStorageImageBinding(getScopedResourceId(RID_GBUFFER_NORMAL)) .addStorageImageBinding(getScopedResourceId(RID_PREVIOUS_NORMAL)); - pipelineInstance = CTX.pipelineService.createPipeline(temporalBuilder); + pipelineInstance = pipelineService->createPipeline(temporalBuilder); } void TemporalAccumulationPass::onSync() { diff --git a/src/context/engine/compute-pass/impl/TemporalAccumulationPass.h b/src/engine/passes/impl/TemporalAccumulationPass.h similarity index 59% rename from src/context/engine/compute-pass/impl/TemporalAccumulationPass.h rename to src/engine/passes/impl/TemporalAccumulationPass.h index e9d61531..f2ed2798 100644 --- a/src/context/engine/compute-pass/impl/TemporalAccumulationPass.h +++ b/src/engine/passes/impl/TemporalAccumulationPass.h @@ -3,9 +3,16 @@ #include "../AbstractComputePass.h" namespace Metal { + class PipelineService; + class TemporalAccumulationPass final : public AbstractComputePass { + PipelineService *pipelineService = nullptr; + public: - explicit TemporalAccumulationPass(const std::string &id) : AbstractComputePass(id) { + std::vector getDependencies() override { + return { + {"PipelineService", &pipelineService} + }; } void onSync() override; diff --git a/src/repository/engine/EngineRepository.cpp b/src/engine/repository/EngineRepository.cpp similarity index 92% rename from src/repository/engine/EngineRepository.cpp rename to src/engine/repository/EngineRepository.cpp index 1add07b1..6d4aa4d2 100644 --- a/src/repository/engine/EngineRepository.cpp +++ b/src/engine/repository/EngineRepository.cpp @@ -1,9 +1,8 @@ #include "EngineRepository.h" -#include "../../common/interface/Icons.h" -#include "../../context/ApplicationContext.h" +#include "../../common/Icons.h" +#include "../../ApplicationContext.h" -#define LEVEL_OF_DETAIL "Level of detail" #define PATH_TRACER "Path tracer" #define ATMOSPHERE "Atmosphere" #define SUN "Sun" @@ -42,10 +41,11 @@ namespace Metal { } void EngineRepository::onUpdate(InspectableMember *member) { - if (member != nullptr && (member->group == PATH_TRACER || member->group == ATMOSPHERE || member->group - == SUN || member->group == DEPTH_OF_FIELD)) { - CTX.engineContext.setGISettingsUpdated(true); - } + // TODO - EVENT + // if (member != nullptr && (member->group == PATH_TRACER || member->group == ATMOSPHERE || member->group + // == SUN || member->group == DEPTH_OF_FIELD)) { + // engineContext.setGISettingsUpdated(true); + // } } nlohmann::json EngineRepository::toJson() const { diff --git a/src/repository/engine/EngineRepository.h b/src/engine/repository/EngineRepository.h similarity index 89% rename from src/repository/engine/EngineRepository.h rename to src/engine/repository/EngineRepository.h index de4db803..77f3cab7 100644 --- a/src/repository/engine/EngineRepository.h +++ b/src/engine/repository/EngineRepository.h @@ -1,11 +1,11 @@ #ifndef ENGINEREPO_H #define ENGINEREPO_H -#include "../../common/inspection/Inspectable.h" #include -#include "../../util/Serializable.h" + +#include "../../common/IRepository.h" namespace Metal { - struct EngineRepository final : Inspectable, Serializable { + struct EngineRepository final : IRepository { bool vsync = true; bool denoiserEnabled = false; diff --git a/src/repository/abstract/ResourceRepository.h b/src/engine/repository/ResourceRepository.h similarity index 83% rename from src/repository/abstract/ResourceRepository.h rename to src/engine/repository/ResourceRepository.h index bebf7cfb..20ec9f5d 100644 --- a/src/repository/abstract/ResourceRepository.h +++ b/src/engine/repository/ResourceRepository.h @@ -2,7 +2,7 @@ #define RESOURCEREPOSITORY_H #include -#include "RuntimeResource.h" +#include "../repository/abstract/RuntimeResource.h" namespace Metal { struct ResourceRepository final { diff --git a/src/repository/runtime/RuntimeRepository.h b/src/engine/repository/RuntimeRepository.h similarity index 93% rename from src/repository/runtime/RuntimeRepository.h rename to src/engine/repository/RuntimeRepository.h index 37215d86..f7c87003 100644 --- a/src/repository/runtime/RuntimeRepository.h +++ b/src/engine/repository/RuntimeRepository.h @@ -3,8 +3,7 @@ #include namespace Metal { - struct RuntimeRepository { - + struct RuntimeRepository : IContextMember { bool isFocused; int displayW; int displayH; diff --git a/src/repository/world/WorldRepository.cpp b/src/engine/repository/WorldRepository.cpp similarity index 92% rename from src/repository/world/WorldRepository.cpp rename to src/engine/repository/WorldRepository.cpp index fd9a1cc9..eb2457d6 100644 --- a/src/repository/world/WorldRepository.cpp +++ b/src/engine/repository/WorldRepository.cpp @@ -1,9 +1,10 @@ #include "WorldRepository.h" +#include "../service/RayTracingService.h" -#include "../../context/ApplicationContext.h" -#include "../../enum/ComponentType.h" -#include "../../service/mesh/SceneData.h" -#include "../../util/serialization-definitions.h" +#include "../enum/ComponentType.h" +#include "../../editor/dto/SceneData.h" +#include "../../common/serialization-definitions.h" +#include "../../core/DirectoryService.h" namespace Metal { entt::entity WorldRepository::createEntity() { @@ -35,7 +36,7 @@ namespace Metal { registry.destroy(entityId); } - CTX.rayTracingService.markDirty(); + rayTracingService->markDirty(); } void WorldRepository::changeVisibility(entt::entity entity, bool isVisible) { @@ -45,12 +46,12 @@ namespace Metal { } else { hiddenEntities.insert({entity, true}); } - CTX.rayTracingService.markDirty(); + rayTracingService->markDirty(); } void WorldRepository::loadScene(const std::string &sceneId) { SceneData sceneData; - const auto pathToFile = CTX.getAssetDirectory() + FORMAT_FILE_SCENE(sceneId); + const auto pathToFile = directoryService->getAssetDirectory() + FORMAT_FILE_SCENE(sceneId); PARSE_TEMPLATE(sceneData, pathToFile) for (auto &entityData: sceneData.entities) { @@ -86,7 +87,7 @@ namespace Metal { } } - CTX.rayTracingService.markDirty(); + rayTracingService->markDirty(); } void WorldRepository::createComponent(const entt::entity entityId, ComponentType type) { diff --git a/src/repository/world/WorldRepository.h b/src/engine/repository/WorldRepository.h similarity index 61% rename from src/repository/world/WorldRepository.h rename to src/engine/repository/WorldRepository.h index 2088eff3..8f62fa62 100644 --- a/src/repository/world/WorldRepository.h +++ b/src/engine/repository/WorldRepository.h @@ -1,30 +1,35 @@ #ifndef WORLDREPOSITORY_H #define WORLDREPOSITORY_H -#include #include #include -#include - -#include "../../common/AbstractRuntimeComponent.h" -#include "../../util/Serializable.h" -#include "../../enum/engine-definitions.h" -#include "../../service/camera/Camera.h" -#include "impl/MetadataComponent.h" -#include "../../enum/ComponentType.h" -#include "components/TransformComponent.h" -#include "components/PrimitiveComponent.h" -#include "components/VolumeComponent.h" + +#include "../../common/IRepository.h" +#include "../dto/Camera.h" +#include "../enum/ComponentType.h" namespace Metal { + struct MetadataComponent; class Inspectable; + class RayTracingService; + class DirectoryService; + + struct WorldRepository final : IRepository { + RayTracingService *rayTracingService = nullptr; + DirectoryService *directoryService = nullptr; - struct WorldRepository final : AbstractRuntimeComponent, Serializable { Camera camera{-(glm::pi() / 4), glm::pi() / 4, {10, 10, 10}}; entt::registry registry{}; std::unordered_map culled{}; std::unordered_map hiddenEntities{}; + std::vector getDependencies() override { + return { + {"RayTracingService", &rayTracingService}, + {"DirectoryService", &directoryService} + }; + } + void createComponent(entt::entity entity, ComponentType type); entt::entity createEntity(); @@ -40,7 +45,6 @@ namespace Metal { nlohmann::json toJson() const override; void fromJson(const nlohmann::json &j) override; - }; } // Metal diff --git a/src/service/buffer/BufferInstance.cpp b/src/engine/resource/BufferInstance.cpp similarity index 66% rename from src/service/buffer/BufferInstance.cpp rename to src/engine/resource/BufferInstance.cpp index 53e2b27f..e2144325 100644 --- a/src/service/buffer/BufferInstance.cpp +++ b/src/engine/resource/BufferInstance.cpp @@ -1,11 +1,5 @@ #include "BufferInstance.h" -#include -#include "../../service/log/LogService.h" -#include "../../context/ApplicationContext.h" -#include "../../context/vulkan/VulkanContext.h" -#include "../../util/VulkanUtils.h" - namespace Metal { BufferType BufferInstance::getBufferType() { return bufferType; diff --git a/src/service/buffer/BufferInstance.h b/src/engine/resource/BufferInstance.h similarity index 93% rename from src/service/buffer/BufferInstance.h rename to src/engine/resource/BufferInstance.h index 1cd66932..175a1cbd 100644 --- a/src/service/buffer/BufferInstance.h +++ b/src/engine/resource/BufferInstance.h @@ -3,7 +3,7 @@ #include -#include "../../repository/abstract/RuntimeResource.h" +#include "RuntimeResource.h" namespace Metal { enum BufferType { diff --git a/src/engine/resource/FrameBufferAttachment.cpp b/src/engine/resource/FrameBufferAttachment.cpp new file mode 100644 index 00000000..c580b7b8 --- /dev/null +++ b/src/engine/resource/FrameBufferAttachment.cpp @@ -0,0 +1,11 @@ +#include "FrameBufferAttachment.h" +#include "../service/DescriptorSetService.h" +#include "../../core/vulkan/VulkanContext.h" + +namespace Metal { + void FrameBufferAttachment::dispose() const { + vkDestroyImage(vulkanContext->device.device, vkImage, nullptr); + vkDestroyImageView(vulkanContext->device.device, vkImageView, nullptr); + vkFreeMemory(vulkanContext->device.device, vkImageMemory, nullptr); + } +} diff --git a/src/engine/resource/FrameBufferAttachment.h b/src/engine/resource/FrameBufferAttachment.h new file mode 100644 index 00000000..9f33e11e --- /dev/null +++ b/src/engine/resource/FrameBufferAttachment.h @@ -0,0 +1,31 @@ +#ifndef FRAMEBUFFERATTACHMENT_H +#define FRAMEBUFFERATTACHMENT_H +#include "../dto/DescriptorInstance.h" + +namespace Metal { + class DescriptorSetService; + + struct FrameBufferAttachment final : IContextMember { + VkImage vkImage = VK_NULL_HANDLE; + VkDeviceMemory vkImageMemory = VK_NULL_HANDLE; + VkImageView vkImageView = VK_NULL_HANDLE; + VkFormat format = VK_FORMAT_MAX_ENUM; + DescriptorInstance *imageDescriptor = nullptr; + bool depth = false; + + void dispose() const; + + std::vector getDependencies() override { + return { + {"VulkanContext", &vulkanContext}, + {"DescriptorSetService", &descriptorSetService} + }; + } + + private: + VulkanContext *vulkanContext = nullptr; + DescriptorSetService *descriptorSetService = nullptr; + }; +} + +#endif diff --git a/src/service/framebuffer/FrameBufferInstance.h b/src/engine/resource/FrameBufferInstance.h similarity index 92% rename from src/service/framebuffer/FrameBufferInstance.h rename to src/engine/resource/FrameBufferInstance.h index 9de1a0e7..3587924e 100644 --- a/src/service/framebuffer/FrameBufferInstance.h +++ b/src/engine/resource/FrameBufferInstance.h @@ -1,7 +1,7 @@ #ifndef FRAMEBUFFER_INSTANCE_H #define FRAMEBUFFER_INSTANCE_H -#include "../../repository/abstract/RuntimeResource.h" +#include "RuntimeResource.h" #include #include #include "FrameBufferAttachment.h" diff --git a/src/service/mesh/MeshInstance.h b/src/engine/resource/MeshInstance.h similarity index 88% rename from src/service/mesh/MeshInstance.h rename to src/engine/resource/MeshInstance.h index d869a3bd..6321e421 100644 --- a/src/service/mesh/MeshInstance.h +++ b/src/engine/resource/MeshInstance.h @@ -1,6 +1,6 @@ #ifndef MESHINSTANCE_H #define MESHINSTANCE_H -#include "../../repository/abstract/RuntimeResource.h" +#include "RuntimeResource.h" namespace Metal { struct BufferInstance; diff --git a/src/service/pipeline/PipelineInstance.h b/src/engine/resource/PipelineInstance.h similarity index 92% rename from src/service/pipeline/PipelineInstance.h rename to src/engine/resource/PipelineInstance.h index b9361236..321f10c9 100644 --- a/src/service/pipeline/PipelineInstance.h +++ b/src/engine/resource/PipelineInstance.h @@ -2,8 +2,8 @@ #define PIPELINEINSTANCE_H #include -#include "../../repository/abstract/RuntimeResource.h" -#include "../descriptor/DescriptorInstance.h" +#include "RuntimeResource.h" +#include "../dto/DescriptorInstance.h" #include namespace Metal { diff --git a/src/repository/abstract/RuntimeResource.h b/src/engine/resource/RuntimeResource.h similarity index 68% rename from src/repository/abstract/RuntimeResource.h rename to src/engine/resource/RuntimeResource.h index 045a102f..16c485f2 100644 --- a/src/repository/abstract/RuntimeResource.h +++ b/src/engine/resource/RuntimeResource.h @@ -1,23 +1,32 @@ #ifndef IGPURESOURCE_H #define IGPURESOURCE_H -#include "../../enum/ResourceType.h" -#include "../../util/Util.h" +#include "../enum/ResourceType.h" +#include "../../editor/util/Util.h" #include +#include "../../common/IContextMember.h" + using Clock = std::chrono::high_resolution_clock; using TimePoint = std::chrono::time_point; namespace Metal { class VulkanContext; - class RuntimeResource { + class RuntimeResource : public IContextMember { const std::string id; bool noDisposal = false; - std::vector empty{}; + + protected: + VulkanContext *vulkanContext = nullptr; + public: + std::vector getDependencies() override { + return {{"VulkanContext", &vulkanContext}}; + } + virtual ~RuntimeResource() = default; - explicit RuntimeResource(const std::string &id = Util::uuidV4()): id(std::move(id)) { + explicit RuntimeResource(const std::string &id = Util::uuidV4()) : id(id) { } [[nodiscard]] std::string getId() const { @@ -35,10 +44,6 @@ namespace Metal { virtual ResourceType resourceType() { throw std::runtime_error("Not implemented"); } - - virtual std::vector &getDependencies() { - return empty; - } }; } #endif diff --git a/src/service/voxel/SVOInstance.h b/src/engine/resource/SVOInstance.h similarity index 80% rename from src/service/voxel/SVOInstance.h rename to src/engine/resource/SVOInstance.h index 954d3296..6c13542f 100644 --- a/src/service/voxel/SVOInstance.h +++ b/src/engine/resource/SVOInstance.h @@ -1,7 +1,7 @@ #ifndef SVOINSTANCE_H #define SVOINSTANCE_H -#include "../../repository/abstract/RuntimeResource.h" -#include "../../service/buffer/BufferInstance.h" +#include "RuntimeResource.h" +#include "BufferInstance.h" namespace Metal { struct DescriptorInstance; diff --git a/src/service/texture/TextureInstance.h b/src/engine/resource/TextureInstance.h similarity index 79% rename from src/service/texture/TextureInstance.h rename to src/engine/resource/TextureInstance.h index 31bdd44a..e77fbafd 100644 --- a/src/service/texture/TextureInstance.h +++ b/src/engine/resource/TextureInstance.h @@ -1,10 +1,8 @@ #ifndef TEXTUREINSTANCE_H #define TEXTUREINSTANCE_H -#include -#include "../descriptor/DescriptorInstance.h" -#include "../../repository/abstract/RuntimeResource.h" -#include "../../context/vulkan/VulkanContext.h" +#include "../dto/DescriptorInstance.h" +#include "RuntimeResource.h" namespace Metal { struct TextureInstance final : RuntimeResource { diff --git a/src/service/buffer/BufferService.cpp b/src/engine/service/BufferService.cpp similarity index 73% rename from src/service/buffer/BufferService.cpp rename to src/engine/service/BufferService.cpp index fa569bfd..3078cd54 100644 --- a/src/service/buffer/BufferService.cpp +++ b/src/engine/service/BufferService.cpp @@ -1,16 +1,18 @@ #include "BufferService.h" -#include "../../context/ApplicationContext.h" -#include "../../util/VulkanUtils.h" -#include "BufferInstance.h" +#include "../../core/vulkan/VulkanContext.h" +#include "../../core/vulkan/VulkanUtils.h" +#include "../resource/BufferInstance.h" namespace Metal { + + BufferInstance *BufferService::createBuffer(const std::string &id, VkDeviceSize bufferSize, VkBufferUsageFlags usageFlags, VkMemoryPropertyFlags memoryPropertyFlags, BufferType type) { BufferInstance *buffer = createResourceInstance(id, bufferSize, type); createVkBuffer(usageFlags, memoryPropertyFlags, buffer); - vkMapMemory(CTX.vulkanContext.device.device, buffer->vkDeviceMemory, 0, bufferSize, 0, &buffer->mapped); + vkMapMemory(vulkanContext->device.device, buffer->vkDeviceMemory, 0, bufferSize, 0, &buffer->mapped); return buffer; } @@ -23,10 +25,10 @@ namespace Metal { createVkBuffer(VK_BUFFER_USAGE_TRANSFER_SRC_BIT, VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT, stagingBuffer); - vkMapMemory(CTX.vulkanContext.device.device, stagingBuffer->vkDeviceMemory, 0, dataSize, 0, + vkMapMemory(vulkanContext->device.device, stagingBuffer->vkDeviceMemory, 0, dataSize, 0, &stagingBuffer->mapped); memcpy(stagingBuffer->mapped, bufferData, dataSize); - vkUnmapMemory(CTX.vulkanContext.device.device, stagingBuffer->vkDeviceMemory); + vkUnmapMemory(vulkanContext->device.device, stagingBuffer->vkDeviceMemory); createVkBuffer(VK_BUFFER_USAGE_TRANSFER_DST_BIT | usageFlags, VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT, finalBuffer); @@ -38,8 +40,8 @@ namespace Metal { } unsigned int BufferService::findMemoryType(unsigned int typeFilter, VkMemoryPropertyFlags properties) const { - for (unsigned int i = 0; i < CTX.vulkanContext.physicalDeviceMemoryProperties.memoryTypeCount; i++) { - if ((typeFilter & (1 << i)) && (CTX.vulkanContext.physicalDeviceMemoryProperties.memoryTypes[i]. + for (unsigned int i = 0; i < vulkanContext->physicalDeviceMemoryProperties.memoryTypeCount; i++) { + if ((typeFilter & (1 << i)) && (vulkanContext->physicalDeviceMemoryProperties.memoryTypes[i]. propertyFlags & properties) == properties) { return i; @@ -57,31 +59,31 @@ namespace Metal { bufferInfo.usage = usage; bufferInfo.sharingMode = VK_SHARING_MODE_EXCLUSIVE; - VulkanUtils::CheckVKResult(vkCreateBuffer(CTX.vulkanContext.device.device, &bufferInfo, nullptr, + VulkanUtils::CheckVKResult(vkCreateBuffer(vulkanContext->device.device, &bufferInfo, nullptr, &buffer->vkBuffer)); VkMemoryRequirements memRequirements; - vkGetBufferMemoryRequirements(CTX.vulkanContext.device.device, buffer->vkBuffer, &memRequirements); + vkGetBufferMemoryRequirements(vulkanContext->device.device, buffer->vkBuffer, &memRequirements); VkMemoryAllocateInfo allocInfo{}; allocInfo.sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO; allocInfo.allocationSize = memRequirements.size; allocInfo.memoryTypeIndex = findMemoryType(memRequirements.memoryTypeBits, properties); - VulkanUtils::CheckVKResult(vkAllocateMemory(CTX.vulkanContext.device.device, &allocInfo, nullptr, + VulkanUtils::CheckVKResult(vkAllocateMemory(vulkanContext->device.device, &allocInfo, nullptr, &buffer->vkDeviceMemory)); - vkBindBufferMemory(CTX.vulkanContext.device.device, buffer->vkBuffer, buffer->vkDeviceMemory, 0); + vkBindBufferMemory(vulkanContext->device.device, buffer->vkBuffer, buffer->vkDeviceMemory, 0); } void BufferService::copyBuffer(const BufferInstance *srcBuffer, const BufferInstance *dstBuffer) const { - VkCommandBuffer commandBuffer = CTX.vulkanContext.beginSingleTimeCommands(); + VkCommandBuffer commandBuffer = vulkanContext->beginSingleTimeCommands(); VkBufferCopy copyRegion{}; copyRegion.size = dstBuffer->dataSize; vkCmdCopyBuffer(commandBuffer, srcBuffer->vkBuffer, dstBuffer->vkBuffer, 1, ©Region); - CTX.vulkanContext.endSingleTimeCommands(commandBuffer); + vulkanContext->endSingleTimeCommands(commandBuffer); } BufferInstance *BufferService::createBuffer(const std::string &id, VkDeviceSize bufferSize, @@ -99,11 +101,11 @@ namespace Metal { } bufferInfo.sharingMode = VK_SHARING_MODE_EXCLUSIVE; - VulkanUtils::CheckVKResult(vkCreateBuffer(CTX.vulkanContext.device.device, &bufferInfo, nullptr, + VulkanUtils::CheckVKResult(vkCreateBuffer(vulkanContext->device.device, &bufferInfo, nullptr, &buffer->vkBuffer)); VkMemoryRequirements memRequirements; - vkGetBufferMemoryRequirements(CTX.vulkanContext.device.device, buffer->vkBuffer, &memRequirements); + vkGetBufferMemoryRequirements(vulkanContext->device.device, buffer->vkBuffer, &memRequirements); VkMemoryAllocateInfo allocInfo{}; allocInfo.sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO; @@ -117,12 +119,12 @@ namespace Metal { allocInfo.pNext = &allocFlagsInfo; } - VulkanUtils::CheckVKResult(vkAllocateMemory(CTX.vulkanContext.device.device, &allocInfo, nullptr, + VulkanUtils::CheckVKResult(vkAllocateMemory(vulkanContext->device.device, &allocInfo, nullptr, &buffer->vkDeviceMemory)); - vkBindBufferMemory(CTX.vulkanContext.device.device, buffer->vkBuffer, buffer->vkDeviceMemory, 0); + vkBindBufferMemory(vulkanContext->device.device, buffer->vkBuffer, buffer->vkDeviceMemory, 0); if (memoryPropertyFlags & VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT) { - vkMapMemory(CTX.vulkanContext.device.device, buffer->vkDeviceMemory, 0, bufferSize, 0, &buffer->mapped); + vkMapMemory(vulkanContext->device.device, buffer->vkDeviceMemory, 0, bufferSize, 0, &buffer->mapped); } return buffer; @@ -137,10 +139,10 @@ namespace Metal { createVkBuffer(VK_BUFFER_USAGE_TRANSFER_SRC_BIT, VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT, stagingBuffer); - vkMapMemory(CTX.vulkanContext.device.device, stagingBuffer->vkDeviceMemory, 0, dataSize, 0, + vkMapMemory(vulkanContext->device.device, stagingBuffer->vkDeviceMemory, 0, dataSize, 0, &stagingBuffer->mapped); memcpy(stagingBuffer->mapped, bufferData, dataSize); - vkUnmapMemory(CTX.vulkanContext.device.device, stagingBuffer->vkDeviceMemory); + vkUnmapMemory(vulkanContext->device.device, stagingBuffer->vkDeviceMemory); auto *finalBuffer = createBuffer(id, dataSize, VK_BUFFER_USAGE_TRANSFER_DST_BIT | usageFlags, @@ -153,9 +155,7 @@ namespace Metal { } void BufferService::disposeResource(BufferInstance *resource) { - LOG_INFO("Disposing of buffer instance " + resource->getId()); - - vkDestroyBuffer(CTX.vulkanContext.device.device, resource->vkBuffer, nullptr); - vkFreeMemory(CTX.vulkanContext.device.device, resource->vkDeviceMemory, nullptr); + vkDestroyBuffer(vulkanContext->device.device, resource->vkBuffer, nullptr); + vkFreeMemory(vulkanContext->device.device, resource->vkDeviceMemory, nullptr); } } // Metal diff --git a/src/service/buffer/BufferService.h b/src/engine/service/BufferService.h similarity index 86% rename from src/service/buffer/BufferService.h rename to src/engine/service/BufferService.h index 54c920cf..4fac84e6 100644 --- a/src/service/buffer/BufferService.h +++ b/src/engine/service/BufferService.h @@ -3,8 +3,8 @@ #include #include -#include "../abstract/AbstractResourceService.h" -#include "BufferInstance.h" +#include "../../common/AbstractResourceService.h" +#include "../resource/BufferInstance.h" #include "vulkan/vulkan.h" namespace Metal { @@ -12,6 +12,8 @@ namespace Metal { class VulkanContext; class BufferService final : public AbstractResourceService { + VulkanContext *vulkanContext = nullptr; + void copyBuffer(const BufferInstance *srcBuffer, const BufferInstance *dstBuffer) const; @@ -19,6 +21,12 @@ namespace Metal { BufferInstance *buffer) const; public: + std::vector getDependencies() override { + return { + {"VulkanContext", &vulkanContext} + }; + } + [[nodiscard]] unsigned int findMemoryType(unsigned int typeFilter, VkMemoryPropertyFlags properties) const; BufferInstance *createBuffer(const std::string &id, VkDeviceSize bufferSize, diff --git a/src/service/camera/CameraService.cpp b/src/engine/service/CameraService.cpp similarity index 85% rename from src/service/camera/CameraService.cpp rename to src/engine/service/CameraService.cpp index 723c06d6..37dff1aa 100644 --- a/src/service/camera/CameraService.cpp +++ b/src/engine/service/CameraService.cpp @@ -1,28 +1,29 @@ #include "CameraService.h" -#include "Camera.h" -#include "../../context/ApplicationContext.h" +#include "../dto/Camera.h" +#include "../../ApplicationContext.h" +#include "../EngineContext.h" +#include "../repository/WorldRepository.h" +#include "../repository/RuntimeRepository.h" namespace Metal { // Per frame // TODO - EVENT SYSTEM void CameraService::onSync() { - camera = &CTX.worldRepository.camera; + camera = &worldRepository->camera; if (camera != nullptr) { updateAspectRatio(); if (camera->isNotFrozen()) { updateMatrices(); - CTX.engineContext.setCameraUpdated(true); + engineContext->setCameraUpdated(true); camera->freezeVersion(); } } } void CameraService::updateAspectRatio() const { - const auto &runtimeRepository = CTX.runtimeRepository; - const float prevAspect = camera->aspectRatio; - camera->aspectRatio = runtimeRepository.viewportW / runtimeRepository.viewportH; + camera->aspectRatio = runtimeRepository->viewportW / runtimeRepository->viewportH; if (prevAspect != camera->aspectRatio) { camera->registerChange(); } @@ -56,12 +57,7 @@ namespace Metal { camera->invProjectionMatrix = glm::inverse(camera->projectionMatrix); } - CameraService::CameraService() : AbstractRuntimeComponent() { - } - void CameraService::handleInputInternal() const { - const auto &runtimeRepository = CTX.runtimeRepository; - glm::vec3 forward( -std::sin(camera->yaw) * std::cos(camera->pitch), std::sin(camera->pitch), @@ -76,16 +72,16 @@ namespace Metal { right = glm::normalize(right); const float multiplier = 10 * camera->movementSensitivity * - CTX.engineContext.deltaTime; - if (runtimeRepository.leftPressed) { + engineContext->deltaTime; + if (runtimeRepository->leftPressed) { camera->position += right * multiplier; camera->registerChange(); } - if (runtimeRepository.rightPressed) { + if (runtimeRepository->rightPressed) { camera->position -= right * multiplier; camera->registerChange(); } - if (runtimeRepository.backwardPressed) { + if (runtimeRepository->backwardPressed) { if (camera->isOrthographic) { camera->orthographicProjectionSize += multiplier; } else { @@ -93,7 +89,7 @@ namespace Metal { } camera->registerChange(); } - if (runtimeRepository.forwardPressed) { + if (runtimeRepository->forwardPressed) { if (camera->isOrthographic) { camera->orthographicProjectionSize -= multiplier; } else { @@ -118,9 +114,8 @@ namespace Metal { } void CameraService::updateDelta(const bool isFirstMovement) const { - const auto &runtimeRepository = CTX.runtimeRepository; - const float mouseX = runtimeRepository.mouseX; - const float mouseY = runtimeRepository.mouseY; + const float mouseX = runtimeRepository->mouseX; + const float mouseY = runtimeRepository->mouseY; if (isFirstMovement) { camera->lastMouseX = mouseX; diff --git a/src/service/camera/CameraService.h b/src/engine/service/CameraService.h similarity index 57% rename from src/service/camera/CameraService.h rename to src/engine/service/CameraService.h index 967f3a1c..c4552745 100644 --- a/src/service/camera/CameraService.h +++ b/src/engine/service/CameraService.h @@ -1,10 +1,12 @@ #ifndef CAMERASYSTEM_H #define CAMERASYSTEM_H -#include "../../common/AbstractRuntimeComponent.h" +#include "../../common/ISync.h" #include #include +#include "../../common/IService.h" + constexpr float PI_OVER_2 = glm::pi() / 2.0f; constexpr float PI_2 = glm::pi() * 2.0f; constexpr float MIN_MAX_PITCH = glm::radians(89.0f); @@ -13,7 +15,16 @@ namespace Metal { class ApplicationContext; struct Camera; - class CameraService final : public AbstractRuntimeComponent { + class EngineContext; + struct WorldRepository; + struct RuntimeRepository; + struct Camera; + + class CameraService final : public IService, public ISync { + EngineContext *engineContext = nullptr; + WorldRepository *worldRepository = nullptr; + RuntimeRepository *runtimeRepository = nullptr; + Camera *camera = nullptr; glm::vec3 xAxis{0.0f}; glm::vec3 yAxis{0.0f}; @@ -38,7 +49,13 @@ namespace Metal { public: void handleInput(bool isFirstMovement) const; - explicit CameraService(); + std::vector getDependencies() override { + return { + {"EngineContext", &engineContext}, + {"WorldRepository", &worldRepository}, + {"RuntimeRepository", &runtimeRepository} + }; + } void onSync() override; }; diff --git a/src/service/passes/CommandBufferRecorderService.h b/src/engine/service/CommandBufferRecorderService.h similarity index 85% rename from src/service/passes/CommandBufferRecorderService.h rename to src/engine/service/CommandBufferRecorderService.h index c05d1d50..c741b512 100644 --- a/src/service/passes/CommandBufferRecorderService.h +++ b/src/engine/service/CommandBufferRecorderService.h @@ -1,8 +1,8 @@ #ifndef COMMANDBUFFERRECORDERSERVICE_H #define COMMANDBUFFERRECORDERSERVICE_H -#include "../abstract/AbstractResourceService.h" -#include "../../context/engine/passes/CommandBufferRecorder.h" +#include "../../common/AbstractResourceService.h" +#include "../passes/CommandBufferRecorder.h" namespace Metal { class CommandBufferRecorderService final : public AbstractResourceService { diff --git a/src/service/descriptor/DescriptorSetService.cpp b/src/engine/service/DescriptorSetService.cpp similarity index 83% rename from src/service/descriptor/DescriptorSetService.cpp rename to src/engine/service/DescriptorSetService.cpp index 81f7093a..e1ea7d22 100644 --- a/src/service/descriptor/DescriptorSetService.cpp +++ b/src/engine/service/DescriptorSetService.cpp @@ -1,18 +1,22 @@ #include "DescriptorSetService.h" -#include "../../service/pipeline/PipelineBuilder.h" -#include "../../service/buffer/BufferInstance.h" -#include "../../service/log/LogService.h" -#include "../../context/ApplicationContext.h" -#include "../framebuffer/FrameBufferAttachment.h" -#include "../framebuffer/FrameBufferInstance.h" -#include "../texture/TextureInstance.h" -#include "../../util/VulkanUtils.h" +#include "../dto/PipelineBuilder.h" +#include "../resource/BufferInstance.h" +#include "../../common/LoggerUtil.h" +#include "../../core/vulkan/VulkanContext.h" +#include "FrameBufferService.h" +#include "BufferService.h" +#include "TextureService.h" +#include "../resource/FrameBufferAttachment.h" +#include "../resource/FrameBufferInstance.h" +#include "../resource/TextureInstance.h" +#include "../../core/vulkan/VulkanUtils.h" namespace Metal { - DescriptorInstance *DescriptorSetService::createDescriptor(const PipelineBuilder &pipelineBuilder, const std::string &id, VkShaderStageFlags stageFlags) { + DescriptorInstance *DescriptorSetService::createDescriptor(const PipelineBuilder &pipelineBuilder, + const std::string &id, VkShaderStageFlags stageFlags) { auto *descriptorInstance = createResourceInstance(id); - for (auto &builder : pipelineBuilder.resourceBindings) { + for (auto &builder: pipelineBuilder.resourceBindings) { DescriptorBinding binding{}; binding.bindingPoint = builder.bindingPoint; binding.descriptorCount = builder.descriptorCount; @@ -27,13 +31,13 @@ namespace Metal { binding.attachmentIndex = builder.attachmentIndex; if (builder.type == DescriptorBindingType::FBO_ATTACHMENT) { - auto *fbo = CTX.framebufferService.getResource(binding.frameBufferId); + auto *fbo = framebufferService->getResource(binding.frameBufferId); if (fbo == nullptr) { throw std::runtime_error("Framebuffer not found: " + binding.frameBufferId); } binding.view = fbo->attachments[binding.attachmentIndex]->vkImageView; if (binding.sampler == VK_NULL_HANDLE) { - binding.sampler = CTX.vulkanContext.vkImageSampler; + binding.sampler = vulkanContext->vkImageSampler; } } @@ -42,7 +46,7 @@ namespace Metal { binding.descriptorType = VK_DESCRIPTOR_TYPE_ACCELERATION_STRUCTURE_KHR; break; case DescriptorBindingType::BUFFER: { - BufferInstance *buffer = CTX.bufferService.getResource(binding.bufferId); + BufferInstance *buffer = bufferService->getResource(binding.bufferId); if (buffer != nullptr) { binding.descriptorType = buffer->getBufferType() == BufferType::UNIFORM_BUFFER @@ -58,7 +62,7 @@ namespace Metal { binding.descriptorType = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER; break; case DescriptorBindingType::STORAGE_IMAGE: { - auto *texture = CTX.textureService.getResource(binding.storageImageId); + auto *texture = textureService->getResource(binding.storageImageId); if (texture == nullptr) { throw std::runtime_error("Storage image texture not found: " + binding.storageImageId); } @@ -77,26 +81,27 @@ namespace Metal { void DescriptorSetService::disposeResource(DescriptorInstance *resource) { LOG_INFO("Disposing of descriptor set resource"); - vkDestroyDescriptorSetLayout(CTX.vulkanContext.device.device, resource->vkDescriptorSetLayout, nullptr); + vkDestroyDescriptorSetLayout(vulkanContext->device.device, resource->vkDescriptorSetLayout, nullptr); } std::vector DescriptorSetService::getAllDescriptors() const { std::vector descriptors; std::lock_guard lock(resourceMutex); - for (auto const& [id, descriptor] : resources) { + for (auto const &[id, descriptor]: resources) { descriptors.emplace_back(descriptor); } return descriptors; } void DescriptorSetService::setImageDescriptor(const FrameBufferInstance *framebuffer, - unsigned int attachmentIndex) { + unsigned int attachmentIndex) { auto attachment = framebuffer->attachments[attachmentIndex]; if (attachment->imageDescriptor == nullptr) { - attachment->imageDescriptor = createResourceInstance(framebuffer->getId() + std::to_string(attachmentIndex)); + attachment->imageDescriptor = + createResourceInstance(framebuffer->getId() + std::to_string(attachmentIndex)); attachment->imageDescriptor->bindings.push_back(DescriptorBinding::Of(VK_SHADER_STAGE_FRAGMENT_BIT, VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, 0, - CTX.vulkanContext.vkImageSampler, + vulkanContext->vkImageSampler, attachment->vkImageView)); updateDescriptor(attachment->imageDescriptor); } @@ -106,14 +111,15 @@ namespace Metal { if (texture->imageDescriptor == nullptr) { texture->imageDescriptor = createResourceInstance(texture->getId() + "_descriptor"); texture->imageDescriptor->bindings.push_back(DescriptorBinding::Of(VK_SHADER_STAGE_FRAGMENT_BIT, - VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, - 0, - texture->vkSampler, - texture->vkImageView + VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, + 0, + texture->vkSampler, + texture->vkImageView )); updateDescriptor(texture->imageDescriptor); } } + void DescriptorSetService::updateDescriptor(DescriptorInstance *descriptor) { if (descriptor->bindings.empty()) { throw std::runtime_error("No descriptor layout sets were created"); @@ -131,7 +137,8 @@ namespace Metal { samplerLayoutBinding.pImmutableSamplers = nullptr; if (binding.descriptorCount > 1) { - bindingFlags.push_back(VK_DESCRIPTOR_BINDING_PARTIALLY_BOUND_BIT | VK_DESCRIPTOR_BINDING_UPDATE_AFTER_BIND_BIT); + bindingFlags.push_back( + VK_DESCRIPTOR_BINDING_PARTIALLY_BOUND_BIT | VK_DESCRIPTOR_BINDING_UPDATE_AFTER_BIND_BIT); } else { bindingFlags.push_back(0); } @@ -150,17 +157,18 @@ namespace Metal { layoutInfo.flags = VK_DESCRIPTOR_SET_LAYOUT_CREATE_UPDATE_AFTER_BIND_POOL_BIT_EXT; layoutInfo.pNext = &flagsInfo; - VulkanUtils::CheckVKResult(vkCreateDescriptorSetLayout(CTX.vulkanContext.device.device, &layoutInfo, + VulkanUtils::CheckVKResult(vkCreateDescriptorSetLayout(vulkanContext->device.device, &layoutInfo, nullptr, &descriptor->vkDescriptorSetLayout)); VkDescriptorSetAllocateInfo allocInfo = {}; allocInfo.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_ALLOCATE_INFO; - allocInfo.descriptorPool = CTX.vulkanContext.descriptorPool; // Created during setup + allocInfo.descriptorPool = vulkanContext->descriptorPool; // Created during setup allocInfo.descriptorSetCount = 1; allocInfo.pSetLayouts = &descriptor->vkDescriptorSetLayout; - VulkanUtils::CheckVKResult(vkAllocateDescriptorSets(CTX.vulkanContext.device.device, &allocInfo, &descriptor->vkDescriptorSet)); + VulkanUtils::CheckVKResult( + vkAllocateDescriptorSets(vulkanContext->device.device, &allocInfo, &descriptor->vkDescriptorSet)); // WRITE Write(descriptor->vkDescriptorSet, descriptor->bindings); @@ -174,7 +182,7 @@ namespace Metal { const std::vector &bindings) { std::vector writeDescriptorSets; std::vector bufferInfos; - std::vector> imageInfosPool; + std::vector > imageInfosPool; std::vector asInfos; bufferInfos.reserve(bindings.size()); @@ -204,7 +212,7 @@ namespace Metal { writeDescriptorSets.push_back(descriptorWrite); } } else if (!binding.bufferId.empty()) { - BufferInstance *buffer = CTX.bufferService.getResource(binding.bufferId); + BufferInstance *buffer = bufferService->getResource(binding.bufferId); if (buffer == nullptr) { LOG_ERROR("DescriptorSetService Buffer not found: " + binding.bufferId); @@ -258,7 +266,7 @@ namespace Metal { if (writeDescriptorSets.empty()) return; - vkUpdateDescriptorSets(CTX.vulkanContext.device.device, + vkUpdateDescriptorSets(vulkanContext->device.device, static_cast(writeDescriptorSets.size()), writeDescriptorSets.data(), 0, diff --git a/src/engine/service/DescriptorSetService.h b/src/engine/service/DescriptorSetService.h new file mode 100644 index 00000000..d0ff4df0 --- /dev/null +++ b/src/engine/service/DescriptorSetService.h @@ -0,0 +1,51 @@ +#ifndef DESCRIPTORSETSERVICE_H +#define DESCRIPTORSETSERVICE_H + +#include "../../common/AbstractResourceService.h" +#include "../dto/DescriptorInstance.h" + +namespace Metal { + struct PipelineBuilder; + struct TextureInstance; + struct FrameBufferInstance; + class VulkanContext; + class FrameBufferService; + class BufferService; + class TextureService; + + class DescriptorSetService final : public AbstractResourceService { + VulkanContext *vulkanContext = nullptr; + FrameBufferService *framebufferService = nullptr; + BufferService *bufferService = nullptr; + TextureService *textureService = nullptr; + + public: + std::vector getDependencies() override { + return { + {"VulkanContext", &vulkanContext}, + {"FrameBufferService", &framebufferService}, + {"BufferService", &bufferService}, + {"TextureService", &textureService} + }; + } + + DescriptorInstance *createDescriptor(const PipelineBuilder &pipelineBuilder, const std::string &id, + VkShaderStageFlags stageFlags); + + void disposeResource(DescriptorInstance *resource) override; + + std::vector getAllDescriptors() const; + + void setImageDescriptor(const FrameBufferInstance *framebuffer, unsigned int attachmentIndex); + + void setImageDescriptor(TextureInstance *texture); + + void updateDescriptor(DescriptorInstance *descriptor); + + void write(DescriptorInstance *descriptor); + + void Write(const VkDescriptorSet &vkDescriptorSet, const std::vector &bindings); + }; +} + +#endif //DESCRIPTORSETSERVICE_H diff --git a/src/service/framebuffer/FrameBufferService.cpp b/src/engine/service/FrameBufferService.cpp similarity index 87% rename from src/service/framebuffer/FrameBufferService.cpp rename to src/engine/service/FrameBufferService.cpp index 3cb4a0ff..a47cb814 100644 --- a/src/service/framebuffer/FrameBufferService.cpp +++ b/src/engine/service/FrameBufferService.cpp @@ -1,13 +1,14 @@ #include "FrameBufferService.h" #include -#include #include -#include "FrameBufferInstance.h" -#include "../../util/VulkanUtils.h" -#include "FrameBufferAttachment.h" -#include "../../context/ApplicationContext.h" +#include "../resource/FrameBufferInstance.h" +#include "../../core/vulkan/VulkanContext.h" +#include "../../core/vulkan/VulkanUtils.h" +#include "../resource/FrameBufferAttachment.h" +#include "../../ApplicationContext.h" +#include "../../common/LoggerUtil.h" namespace Metal { @@ -22,7 +23,7 @@ namespace Metal { } void FrameBufferService::createDepthAttachment(FrameBufferInstance *framebuffer) const { - VkFormat depthFormat = VulkanUtils::GetValidDepthFormat(CTX.vulkanContext.physDevice.physical_device); + VkFormat depthFormat = VulkanUtils::GetValidDepthFormat(vulkanContext->physDevice.physical_device); const auto att = createAttachmentInternal(depthFormat, VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT, framebuffer); att->depth = true; @@ -41,6 +42,7 @@ namespace Metal { VkImageUsageFlagBits usage, FrameBufferInstance *framebuffer) const { std::shared_ptr attachment = std::make_shared(); + ctx->injectDependencies(attachment.get()); framebuffer->attachments.push_back(attachment); attachment->format = format; @@ -72,20 +74,20 @@ namespace Metal { image.sharingMode = VK_SHARING_MODE_EXCLUSIVE; VulkanUtils::CheckVKResult( - vkCreateImage(CTX.vulkanContext.device.device, &image, nullptr, &attachment->vkImage)); + vkCreateImage(vulkanContext->device.device, &image, nullptr, &attachment->vkImage)); VkMemoryAllocateInfo memAlloc{}; VkMemoryRequirements memReqs; - vkGetImageMemoryRequirements(CTX.vulkanContext.device.device, attachment->vkImage, &memReqs); + vkGetImageMemoryRequirements(vulkanContext->device.device, attachment->vkImage, &memReqs); memAlloc.allocationSize = memReqs.size; - memAlloc.memoryTypeIndex = VulkanUtils::GetMemTypeIndex(CTX.vulkanContext.physicalDeviceMemoryProperties, + memAlloc.memoryTypeIndex = VulkanUtils::GetMemTypeIndex(vulkanContext->physicalDeviceMemoryProperties, memReqs.memoryTypeBits, VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT); - VulkanUtils::CheckVKResult(vkAllocateMemory(CTX.vulkanContext.device.device, &memAlloc, nullptr, + VulkanUtils::CheckVKResult(vkAllocateMemory(vulkanContext->device.device, &memAlloc, nullptr, &attachment->vkImageMemory)); VulkanUtils::CheckVKResult( - vkBindImageMemory(CTX.vulkanContext.device.device, attachment->vkImage, attachment->vkImageMemory, 0)); + vkBindImageMemory(vulkanContext->device.device, attachment->vkImage, attachment->vkImageMemory, 0)); VkImageViewCreateInfo imageView{}; imageView.viewType = VK_IMAGE_VIEW_TYPE_2D; @@ -97,7 +99,7 @@ namespace Metal { imageView.subresourceRange.baseArrayLayer = 0; imageView.subresourceRange.layerCount = 1; imageView.image = attachment->vkImage; - VulkanUtils::CheckVKResult(vkCreateImageView(CTX.vulkanContext.device.device, &imageView, nullptr, + VulkanUtils::CheckVKResult(vkCreateImageView(vulkanContext->device.device, &imageView, nullptr, &attachment->vkImageView)); return attachment; } @@ -109,6 +111,7 @@ namespace Metal { for (unsigned int i = 0; i < framebuffer->attachments.size(); i++) { VkAttachmentDescription &attachmentDescription = attachmentDescriptions.emplace_back(); const std::shared_ptr fbAttachment = framebuffer->attachments[i]; + ctx->injectDependencies(fbAttachment.get()); attachmentDescription.samples = VK_SAMPLE_COUNT_1_BIT; attachmentDescription.loadOp = VK_ATTACHMENT_LOAD_OP_CLEAR; attachmentDescription.storeOp = VK_ATTACHMENT_STORE_OP_STORE; @@ -166,7 +169,7 @@ namespace Metal { renderPassInfo.dependencyCount = dependencies.size(); renderPassInfo.pDependencies = dependencies.data(); - VulkanUtils::CheckVKResult(vkCreateRenderPass(CTX.vulkanContext.device.device, + VulkanUtils::CheckVKResult(vkCreateRenderPass(vulkanContext->device.device, &renderPassInfo, nullptr, &framebuffer->vkRenderPass)); @@ -195,14 +198,14 @@ namespace Metal { framebufferInfo.height = framebuffer->bufferHeight; framebufferInfo.layers = 1; - vkCreateFramebuffer(CTX.vulkanContext.device.device, &framebufferInfo, nullptr, + vkCreateFramebuffer(vulkanContext->device.device, &framebufferInfo, nullptr, &framebuffer->vkFramebuffer); } void FrameBufferService::disposeResource(FrameBufferInstance *resource) { LOG_INFO("Disposing framebuffer instance"); - vkDestroyFramebuffer(CTX.vulkanContext.device.device, resource->vkFramebuffer, nullptr); - vkDestroyRenderPass(CTX.vulkanContext.device.device, resource->vkRenderPass, nullptr); + vkDestroyFramebuffer(vulkanContext->device.device, resource->vkFramebuffer, nullptr); + vkDestroyRenderPass(vulkanContext->device.device, resource->vkRenderPass, nullptr); for (int i = 0; i < resource->attachments.size(); i++) { LOG_INFO("Disposing of attachment instance " + std::to_string(i)); diff --git a/src/service/framebuffer/FrameBufferService.h b/src/engine/service/FrameBufferService.h similarity index 81% rename from src/service/framebuffer/FrameBufferService.h rename to src/engine/service/FrameBufferService.h index 15fab167..5c077a77 100644 --- a/src/service/framebuffer/FrameBufferService.h +++ b/src/engine/service/FrameBufferService.h @@ -5,14 +5,18 @@ #include #include -#include "../abstract/AbstractResourceService.h" -#include "FrameBufferInstance.h" +#include "../../common/AbstractResourceService.h" +#include "../resource/FrameBufferInstance.h" namespace Metal { struct FrameBufferAttachment; struct FrameBufferInstance; + class VulkanContext; + class FrameBufferService final : public AbstractResourceService { + VulkanContext *vulkanContext = nullptr; + std::shared_ptr createAttachmentInternal(VkFormat format, VkImageUsageFlagBits usage, FrameBufferInstance *framebuffer) const; @@ -20,6 +24,10 @@ namespace Metal { void createVKFrameBuffer(FrameBufferInstance *framebuffer) const; public: + std::vector getDependencies() override { + return {{"VulkanContext", &vulkanContext}}; + } + FrameBufferInstance *createFrameBuffer(const std::string &id, unsigned int w, unsigned int h, glm::vec4 clearColor = glm::vec4(0.0f)); diff --git a/src/service/lights/LightService.cpp b/src/engine/service/LightService.cpp similarity index 65% rename from src/service/lights/LightService.cpp rename to src/engine/service/LightService.cpp index 2ce80c93..de69de89 100644 --- a/src/service/lights/LightService.cpp +++ b/src/engine/service/LightService.cpp @@ -1,7 +1,9 @@ #include "LightService.h" -#include "../../context/ApplicationContext.h" -#include "../buffer/BufferInstance.h" -#include "../../enum/EngineResourceIDs.h" +#include "../../ApplicationContext.h" +#include "../resource/BufferInstance.h" +#include "../../editor/enum/EngineResourceIDs.h" +#include "../EngineContext.h" +#include "../repository/EngineRepository.h" namespace Metal { void LightService::registerLights() { @@ -15,19 +17,18 @@ namespace Metal { registerLights(); if (!items.empty()) { - CTX.engineContext.currentFrame->getResourceAs(RID_LIGHT_BUFFER)->update(items.data()); + engineContext->currentFrame->getResourceAs(RID_LIGHT_BUFFER)->update(items.data()); } } void LightService::computeSunInfo() { sunPosition = glm::vec3(0, - std::cos(CTX.engineRepository.elapsedTime), - std::sin(CTX.engineRepository.elapsedTime)) * CTX.engineRepository - .sunDistance; + std::cos(engineRepository->elapsedTime), + std::sin(engineRepository->elapsedTime)) * engineRepository->sunDistance; sunColor = LightService::CalculateSunColor( - sunPosition.y / CTX.engineRepository.sunDistance, - CTX.engineRepository.nightColor, CTX.engineRepository.dawnColor, - CTX.engineRepository.middayColor); + sunPosition.y / engineRepository->sunDistance, + engineRepository->nightColor, engineRepository->dawnColor, + engineRepository->middayColor); } glm::vec3 LightService::CalculateSunColor(const float elevation, glm::vec3 &nightColor, glm::vec3 &dawnColor, diff --git a/src/service/lights/LightService.h b/src/engine/service/LightService.h similarity index 62% rename from src/service/lights/LightService.h rename to src/engine/service/LightService.h index 35a71ace..9764b680 100644 --- a/src/service/lights/LightService.h +++ b/src/engine/service/LightService.h @@ -2,11 +2,18 @@ #define LIGHTSSERVICE_H #include -#include "../../common/AbstractRuntimeComponent.h" -#include "../../dto/buffers/LightData.h" +#include "../../common/IService.h" +#include "../../common/ISync.h" +#include "../dto/LightData.h" namespace Metal { - class LightService final : public AbstractRuntimeComponent { + class EngineContext; + struct EngineRepository; + + class LightService final : public IService, public ISync{ + EngineContext *engineContext = nullptr; + EngineRepository *engineRepository = nullptr; + std::vector items{}; glm::vec3 sunColor{}; glm::vec3 sunPosition{}; @@ -19,6 +26,13 @@ namespace Metal { static glm::vec3 BlendColors(glm::vec3 &c1, glm::vec3 &c2, float t); public: + std::vector getDependencies() override { + return { + {"EngineContext", &engineContext}, + {"EngineRepository", &engineRepository} + }; + } + void onSync() override; void computeSunInfo(); diff --git a/src/service/material/MaterialService.cpp b/src/engine/service/MaterialService.cpp similarity index 59% rename from src/service/material/MaterialService.cpp rename to src/engine/service/MaterialService.cpp index 80c72174..ef66308c 100644 --- a/src/service/material/MaterialService.cpp +++ b/src/engine/service/MaterialService.cpp @@ -1,12 +1,12 @@ #include "MaterialService.h" -#include "../../util/serialization-definitions.h" -#include "../../dto/buffers/MeshMetadata.h" - -#include "../../context/ApplicationContext.h" - +#include "../../common/serialization-definitions.h" +#include "../dto/MeshMetadata.h" +#include "TextureService.h" +#include "../dto/PrimitiveComponent.h" namespace Metal { + void MaterialService::load(MeshMetadata &materialData, PrimitiveComponent &data) { materialData.albedo = data.albedoColor; materialData.roughness = data.roughnessFactor; @@ -21,21 +21,21 @@ namespace Metal { materialData.metallicTextureId = 0; if (!data.albedo.empty()) { - auto *tex = CTX.textureService.stream(data.albedo); + auto *tex = textureService->stream(data.albedo); if (tex != nullptr) { - materialData.albedoTextureId = CTX.textureService.getTextureIndex(data.albedo); + materialData.albedoTextureId = textureService->getTextureIndex(data.albedo); } } if (!data.roughness.empty()) { - auto *tex = CTX.textureService.stream(data.roughness); + auto *tex = textureService->stream(data.roughness); if (tex != nullptr) { - materialData.roughnessTextureId = CTX.textureService.getTextureIndex(data.roughness); + materialData.roughnessTextureId = textureService->getTextureIndex(data.roughness); } } if (!data.metallic.empty()) { - auto *tex = CTX.textureService.stream(data.metallic); + auto *tex = textureService->stream(data.metallic); if (tex != nullptr) { - materialData.metallicTextureId = CTX.textureService.getTextureIndex(data.metallic); + materialData.metallicTextureId = textureService->getTextureIndex(data.metallic); } } } diff --git a/src/engine/service/MaterialService.h b/src/engine/service/MaterialService.h new file mode 100644 index 00000000..1656406f --- /dev/null +++ b/src/engine/service/MaterialService.h @@ -0,0 +1,24 @@ +#ifndef MATERIALSERVICE_H +#define MATERIALSERVICE_H +#include "../../common/IService.h" + +namespace Metal { + struct PrimitiveComponent; + struct MeshMetadata; + class TextureService; + + class MaterialService final : public IService { + TextureService *textureService = nullptr; + + public: + std::vector getDependencies() override { + return { + {"TextureService", &textureService} + }; + } + + void load(MeshMetadata &data, PrimitiveComponent &component); + }; +} // Metal + +#endif //MATERIALSERVICE_H diff --git a/src/service/mesh/MeshService.cpp b/src/engine/service/MeshService.cpp similarity index 70% rename from src/service/mesh/MeshService.cpp rename to src/engine/service/MeshService.cpp index cf7fbe17..4394c482 100644 --- a/src/service/mesh/MeshService.cpp +++ b/src/engine/service/MeshService.cpp @@ -1,20 +1,23 @@ #include "MeshService.h" -#include "MeshInstance.h" -#include "MeshData.h" -#include "SceneData.h" +#include "../resource/MeshInstance.h" +#include "../dto/MeshData.h" +#include "../../editor/dto/SceneData.h" -#include "../../context/vulkan/VulkanContext.h" -#include "../../util/FilesUtil.h" -#include "../../util/serialization-definitions.h" +#include "../../core/vulkan/VulkanContext.h" +#include "../../common/FilesUtil.h" +#include "../../common/LoggerUtil.h" +#include "../../core/DirectoryService.h" #include #include +#include -#include "../../context/ApplicationContext.h" -#include "../../repository/world/components/PrimitiveComponent.h" -#include "../../repository/world/components/TransformComponent.h" +#include "../../ApplicationContext.h" +#include "BufferService.h" +#include "RayTracingService.h" namespace Metal { + MeshInstance *MeshService::create(const std::string &id) { MeshData *data = loadMeshData(id); if (data == nullptr) { @@ -25,14 +28,14 @@ namespace Metal { instance->indexCount = data->indices.size(); instance->vertexCount = data->data.size(); - instance->dataBuffer = CTX.bufferService.createBuffer( + instance->dataBuffer = bufferService->createBuffer( id + "_data", sizeof(VertexData) * data->data.size(), VK_BUFFER_USAGE_VERTEX_BUFFER_BIT | VK_BUFFER_USAGE_ACCELERATION_STRUCTURE_BUILD_INPUT_READ_ONLY_BIT_KHR | VK_BUFFER_USAGE_SHADER_DEVICE_ADDRESS_BIT, data->data.data(), true); - instance->indexBuffer = CTX.bufferService.createBuffer( + instance->indexBuffer = bufferService->createBuffer( id + "_indices", sizeof(unsigned int) * data->indices.size(), VK_BUFFER_USAGE_INDEX_BUFFER_BIT | VK_BUFFER_USAGE_ACCELERATION_STRUCTURE_BUILD_INPUT_READ_ONLY_BIT_KHR | VK_BUFFER_USAGE_SHADER_DEVICE_ADDRESS_BIT, @@ -56,7 +59,7 @@ namespace Metal { } MeshData *MeshService::loadMeshData(const std::string &id) const { - auto pathToFile = CTX.getAssetDirectory() + FORMAT_FILE_MESH(id); + auto pathToFile = directoryService->getRootDirectory() + "/assets/" + FORMAT_FILE_MESH(id); if (std::filesystem::exists(pathToFile)) { auto *data = new MeshData; std::ifstream input(pathToFile, std::ios::binary); @@ -69,8 +72,8 @@ namespace Metal { void MeshService::disposeResource(MeshInstance *resource) { LOG_INFO("Disposing of mesh instance"); - CTX.rayTracingService.markDirty(); - CTX.bufferService.dispose(resource->indexBuffer->getId()); - CTX.bufferService.dispose(resource->dataBuffer->getId()); + rayTracingService->markDirty(); + bufferService->dispose(resource->indexBuffer->getId()); + bufferService->dispose(resource->dataBuffer->getId()); } } // Metal diff --git a/src/engine/service/MeshService.h b/src/engine/service/MeshService.h new file mode 100644 index 00000000..0fa3241b --- /dev/null +++ b/src/engine/service/MeshService.h @@ -0,0 +1,42 @@ +#ifndef MESHSERVICE_H +#define MESHSERVICE_H +#include "../../common/AbstractResourceService.h" +#include "../resource/MeshInstance.h" +#include "../../editor/enum/engine-definitions.h" + +namespace Metal { + struct MeshData; + struct MeshInstance; + struct EntityAssetData; + + class BufferService; + class RayTracingService; + class DirectoryService; + + class MeshService final : public AbstractResourceService { + BufferService *bufferService = nullptr; + RayTracingService *rayTracingService = nullptr; + DirectoryService *directoryService = nullptr; + + public: + MeshService() = default; + + std::vector getDependencies() override { + return { + {"BufferService", &bufferService}, + {"RayTracingService", &rayTracingService}, + {"DirectoryService", &directoryService} + }; + } + + MeshInstance *create(const std::string &id); + + MeshInstance *stream(const std::string &id); + + MeshData *loadMeshData(const std::string &id) const; + + void disposeResource(MeshInstance *resource) override; + }; +} // Metal + +#endif //MESHSERVICE_H diff --git a/src/service/pipeline/PipelineService.cpp b/src/engine/service/PipelineService.cpp similarity index 84% rename from src/service/pipeline/PipelineService.cpp rename to src/engine/service/PipelineService.cpp index beff6a04..0697bf19 100644 --- a/src/service/pipeline/PipelineService.cpp +++ b/src/engine/service/PipelineService.cpp @@ -1,16 +1,19 @@ #include "PipelineService.h" - -#include "PipelineBuilder.h" -#include "../../util/ShaderUtil.h" -#include "../../context/ApplicationContext.h" -#include "../../util/VulkanUtils.h" -#include "../framebuffer/FrameBufferInstance.h" -#include "../pipeline/PipelineInstance.h" -#include "../mesh/MeshData.h" -#include "../mesh/VertexData.h" -#include "../descriptor/DescriptorInstance.h" -#include "../framebuffer/FrameBufferAttachment.h" -#include "../buffer/BufferInstance.h" +#include "../dto/PipelineBuilder.h" +#include "ShaderService.h" +#include "../../core/vulkan/VulkanContext.h" +#include "../../core/vulkan/VulkanUtils.h" +#include "FrameBufferService.h" +#include "BufferService.h" +#include "../resource/FrameBufferInstance.h" +#include "../resource/PipelineInstance.h" +#include "../dto/MeshData.h" +#include "../dto/VertexData.h" +#include "../dto/DescriptorInstance.h" +#include "../resource/FrameBufferAttachment.h" +#include "../resource/BufferInstance.h" +#include "../../ApplicationContext.h" +#include "../../common/LoggerUtil.h" namespace Metal { void PipelineService::createPipelineLayout( @@ -35,7 +38,7 @@ namespace Metal { layoutInfo.pPushConstantRanges = &pushConstantRange; } - VulkanUtils::CheckVKResult(vkCreatePipelineLayout(CTX.vulkanContext.device.device, &layoutInfo, nullptr, + VulkanUtils::CheckVKResult(vkCreatePipelineLayout(vulkanContext->device.device, &layoutInfo, nullptr, &pipeline->vkPipelineLayout)); } @@ -55,7 +58,7 @@ namespace Metal { stageFlags = VK_SHADER_STAGE_VERTEX_BIT | VK_SHADER_STAGE_FRAGMENT_BIT; } - pipeline->descriptor = descriptorSetService.createDescriptor(pipelineBuilder, id + "_descriptor", stageFlags); + pipeline->descriptor = descriptorSetService->createDescriptor(pipelineBuilder, id + "_descriptor", stageFlags); } if (pipelineBuilder.isRayTracing) { @@ -71,7 +74,7 @@ namespace Metal { PipelineInstance *pipeline) { pipeline->isCompute = true; pipeline->pushConstantsSize = pipelineBuilder.pushConstantsSize; - VkShaderModule computeShaderModule = ShaderUtil::CreateShaderModule(pipelineBuilder.computeShader); + VkShaderModule computeShaderModule = shaderService->createShaderModule(pipelineBuilder.computeShader); VkPipelineShaderStageCreateInfo computeShaderStageInfo{}; computeShaderStageInfo.sType = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO; computeShaderStageInfo.stage = VK_SHADER_STAGE_COMPUTE_BIT; @@ -85,12 +88,12 @@ namespace Metal { pipelineInfo.layout = pipeline->vkPipelineLayout; pipelineInfo.stage = computeShaderStageInfo; - if (vkCreateComputePipelines(CTX.vulkanContext.device.device, VK_NULL_HANDLE, 1, &pipelineInfo, nullptr, + if (vkCreateComputePipelines(vulkanContext->device.device, VK_NULL_HANDLE, 1, &pipelineInfo, nullptr, &pipeline->vkPipeline) != VK_SUCCESS) { throw std::runtime_error("failed to create compute pipeline!"); } - vkDestroyShaderModule(CTX.vulkanContext.device.device, computeShaderModule, nullptr); + vkDestroyShaderModule(vulkanContext->device.device, computeShaderModule, nullptr); return pipeline; } @@ -99,8 +102,8 @@ namespace Metal { auto meshDescriptions = VertexData::GetAttributeDescriptions(); pipeline->pushConstantsSize = pipelineBuilder.pushConstantsSize; - auto fragmentShaderModule = ShaderUtil::CreateShaderModule(pipelineBuilder.fragmentShader); - auto vertexShaderModule = ShaderUtil::CreateShaderModule(pipelineBuilder.vertexShader); + auto fragmentShaderModule = shaderService->createShaderModule(pipelineBuilder.fragmentShader); + auto vertexShaderModule = shaderService->createShaderModule(pipelineBuilder.vertexShader); createPipelineLayout(pipelineBuilder.pushConstantsSize, pipeline); std::array shaderStages{}; @@ -155,7 +158,7 @@ namespace Metal { multisampling.sampleShadingEnable = VK_FALSE; multisampling.rasterizationSamples = VK_SAMPLE_COUNT_1_BIT; - auto *frameBuffer = CTX.framebufferService.getResource(pipelineBuilder.frameBufferId); + auto *frameBuffer = framebufferService->getResource(pipelineBuilder.frameBufferId); if (!frameBuffer) { throw std::runtime_error("Framebuffer not found: " + pipelineBuilder.frameBufferId); } @@ -226,13 +229,13 @@ namespace Metal { pipelineInfo.subpass = 0; pipelineInfo.basePipelineHandle = VK_NULL_HANDLE; - VulkanUtils::CheckVKResult(vkCreateGraphicsPipelines(CTX.vulkanContext.device.device, VK_NULL_HANDLE, 1, + VulkanUtils::CheckVKResult(vkCreateGraphicsPipelines(vulkanContext->device.device, VK_NULL_HANDLE, 1, &pipelineInfo, nullptr, &pipeline->vkPipeline)); - vkDestroyShaderModule(CTX.vulkanContext.device.device, fragmentShaderModule, nullptr); - vkDestroyShaderModule(CTX.vulkanContext.device.device, vertexShaderModule, nullptr); + vkDestroyShaderModule(vulkanContext->device.device, fragmentShaderModule, nullptr); + vkDestroyShaderModule(vulkanContext->device.device, vertexShaderModule, nullptr); return pipeline; } @@ -250,9 +253,9 @@ namespace Metal { pipeline->pushConstantsSize = pipelineBuilder.pushConstantsSize; // Create shader modules - auto rayGenModule = ShaderUtil::CreateShaderModule(pipelineBuilder.rayGenShader); - auto missModule = ShaderUtil::CreateShaderModule(pipelineBuilder.missShader); - auto closestHitModule = ShaderUtil::CreateShaderModule(pipelineBuilder.closestHitShader); + auto rayGenModule = shaderService->createShaderModule(pipelineBuilder.rayGenShader); + auto missModule = shaderService->createShaderModule(pipelineBuilder.missShader); + auto closestHitModule = shaderService->createShaderModule(pipelineBuilder.closestHitShader); // Shader stages: 0=raygen, 1=miss, 2=closesthit std::array shaderStages{}; @@ -309,12 +312,12 @@ namespace Metal { rtPipelineInfo.layout = pipeline->vkPipelineLayout; VulkanUtils::CheckVKResult( - CTX.vulkanContext.vkCreateRayTracingPipelinesKHR( - CTX.vulkanContext.device.device, VK_NULL_HANDLE, VK_NULL_HANDLE, + vulkanContext->vkCreateRayTracingPipelinesKHR( + vulkanContext->device.device, VK_NULL_HANDLE, VK_NULL_HANDLE, 1, &rtPipelineInfo, nullptr, &pipeline->vkPipeline)); // Build Shader Binding Table - const auto &rtProps = CTX.vulkanContext.rayTracingPipelineProperties; + const auto &rtProps = vulkanContext->rayTracingPipelineProperties; const uint32_t handleSize = rtProps.shaderGroupHandleSize; const uint32_t handleAlignment = rtProps.shaderGroupHandleAlignment; const uint32_t baseAlignment = rtProps.shaderGroupBaseAlignment; @@ -324,14 +327,14 @@ namespace Metal { const uint32_t sbtSize = groupCount * handleSizeAligned; std::vector shaderHandleStorage(sbtSize); VulkanUtils::CheckVKResult( - CTX.vulkanContext.vkGetRayTracingShaderGroupHandlesKHR( - CTX.vulkanContext.device.device, pipeline->vkPipeline, + vulkanContext->vkGetRayTracingShaderGroupHandlesKHR( + vulkanContext->device.device, pipeline->vkPipeline, 0, groupCount, sbtSize, shaderHandleStorage.data())); // Create SBT buffers - each needs baseAlignment auto createSBTBuffer = [&](uint32_t groupIndex, const std::string &sbtType) -> BufferInstance * { const uint32_t sbtBufferSize = (handleSizeAligned + baseAlignment - 1) & ~(baseAlignment - 1); - auto *buf = CTX.bufferService.createBuffer( + auto *buf = bufferService->createBuffer( pipeline->getId() + "_sbt_" + sbtType, sbtBufferSize, VK_BUFFER_USAGE_SHADER_BINDING_TABLE_BIT_KHR | VK_BUFFER_USAGE_TRANSFER_DST_BIT, @@ -346,8 +349,8 @@ namespace Metal { pipeline->hitSBT = createSBTBuffer(2, "hit"); auto getAddr = [&](const BufferInstance *buf) { - return getBufferDeviceAddress(CTX.vulkanContext.device.device, buf->vkBuffer, - CTX.vulkanContext.vkGetBufferDeviceAddressKHR); + return getBufferDeviceAddress(vulkanContext->device.device, buf->vkBuffer, + vulkanContext->vkGetBufferDeviceAddressKHR); }; pipeline->raygenRegion.deviceAddress = getAddr(pipeline->raygenSBT); @@ -364,9 +367,9 @@ namespace Metal { pipeline->callableRegion = {}; // unused - vkDestroyShaderModule(CTX.vulkanContext.device.device, rayGenModule, nullptr); - vkDestroyShaderModule(CTX.vulkanContext.device.device, missModule, nullptr); - vkDestroyShaderModule(CTX.vulkanContext.device.device, closestHitModule, nullptr); + vkDestroyShaderModule(vulkanContext->device.device, rayGenModule, nullptr); + vkDestroyShaderModule(vulkanContext->device.device, missModule, nullptr); + vkDestroyShaderModule(vulkanContext->device.device, closestHitModule, nullptr); return pipeline; } @@ -375,14 +378,14 @@ namespace Metal { LOG_INFO("Disposing of pipeline instance"); if (resource->descriptor != nullptr) { - descriptorSetService.dispose(resource->getId()); + descriptorSetService->dispose(resource->getId()); } - vkDestroyPipelineLayout(CTX.vulkanContext.device.device, resource->vkPipelineLayout, nullptr); - vkDestroyPipeline(CTX.vulkanContext.device.device, resource->vkPipeline, nullptr); + vkDestroyPipelineLayout(vulkanContext->device.device, resource->vkPipelineLayout, nullptr); + vkDestroyPipeline(vulkanContext->device.device, resource->vkPipeline, nullptr); } std::vector PipelineService::getAllDescriptors() const { - return descriptorSetService.getAllDescriptors(); + return descriptorSetService->getAllDescriptors(); } } // Metal diff --git a/src/service/pipeline/PipelineService.h b/src/engine/service/PipelineService.h similarity index 53% rename from src/service/pipeline/PipelineService.h rename to src/engine/service/PipelineService.h index 9ac16eaa..2c134925 100644 --- a/src/service/pipeline/PipelineService.h +++ b/src/engine/service/PipelineService.h @@ -2,19 +2,40 @@ #define PIPELINESERVICE_H #include -#include "../abstract/AbstractResourceService.h" -#include "../descriptor/DescriptorSetService.h" -#include "PipelineInstance.h" +#include "../../common/AbstractResourceService.h" +#include "DescriptorSetService.h" +#include "../resource/PipelineInstance.h" namespace Metal { + class ShaderService; struct PipelineBuilder; struct FrameBufferInstance; struct PipelineInstance; struct DescriptorInstance; + class VulkanContext; + class FrameBufferService; + class BufferService; + class PipelineService final : public AbstractResourceService { + VulkanContext *vulkanContext = nullptr; + FrameBufferService *framebufferService = nullptr; + BufferService *bufferService = nullptr; + DescriptorSetService *descriptorSetService = nullptr; + ShaderService *shaderService = nullptr; + public: - explicit PipelineService(DescriptorSetService &descriptorSetService) : descriptorSetService(descriptorSetService) {} + PipelineService() = default; + + std::vector getDependencies() override { + return { + {"VulkanContext", &vulkanContext}, + {"FramebufferService", &framebufferService}, + {"BufferService", &bufferService}, + {"DescriptorSetService", &descriptorSetService}, + {"ShaderService", &shaderService} + }; + } PipelineInstance *createPipeline(PipelineBuilder &pipelineBuilder); @@ -23,8 +44,6 @@ namespace Metal { std::vector getAllDescriptors() const; private: - DescriptorSetService &descriptorSetService; - PipelineInstance *createComputePipeline(const PipelineBuilder &pipelineBuilder, PipelineInstance *pipeline); PipelineInstance *createRenderingPipeline(PipelineBuilder &pipelineBuilder, PipelineInstance *pipeline); diff --git a/src/service/raytracing/RayTracingService.cpp b/src/engine/service/RayTracingService.cpp similarity index 69% rename from src/service/raytracing/RayTracingService.cpp rename to src/engine/service/RayTracingService.cpp index fd2b6de0..a0c103f6 100644 --- a/src/service/raytracing/RayTracingService.cpp +++ b/src/engine/service/RayTracingService.cpp @@ -1,24 +1,35 @@ #include "RayTracingService.h" -#include "../../context/ApplicationContext.h" -#include "../buffer/BufferInstance.h" -#include "../descriptor/DescriptorInstance.h" -#include "../descriptor/DescriptorBinding.h" -#include "../mesh/MeshInstance.h" -#include "../mesh/VertexData.h" -#include "../../util/VulkanUtils.h" -#include "../../enum/EngineResourceIDs.h" +#include "../../ApplicationContext.h" +#include "../resource/BufferInstance.h" +#include "../dto/DescriptorInstance.h" +#include "../dto/DescriptorBinding.h" +#include "../resource/MeshInstance.h" +#include "../dto/VertexData.h" +#include "../../core/vulkan/VulkanUtils.h" +#include "../../editor/enum/EngineResourceIDs.h" +#include "../../core/vulkan/VulkanContext.h" +#include "../../common/LoggerUtil.h" +#include "../dto/TransformComponent.h" +#include "../dto/PrimitiveComponent.h" +#include "PipelineService.h" +#include "../repository/WorldRepository.h" +#include "MeshService.h" +#include "MaterialService.h" +#include "DescriptorSetService.h" +#include "BufferService.h" +#include "../EngineContext.h" #include namespace Metal { - static VkDeviceAddress getDeviceAddress(const VulkanContext &ctx, VkBuffer buffer) { + VkDeviceAddress RayTracingService::getDeviceAddress(VkBuffer buffer) { VkBufferDeviceAddressInfo info{}; info.sType = VK_STRUCTURE_TYPE_BUFFER_DEVICE_ADDRESS_INFO; info.buffer = buffer; - return ctx.vkGetBufferDeviceAddressKHR(ctx.device.device, &info); + return vulkanContext->vkGetBufferDeviceAddressKHR(vulkanContext->device.device, &info); } void RayTracingService::updateDescriptorSets(VkAccelerationStructureKHR asHandle) { - auto descriptors = CTX.pipelineService.getAllDescriptors(); + auto descriptors = pipelineService->getAllDescriptors(); for (auto *descriptor: descriptors) { bool needsUpdate = false; for (auto &binding: descriptor->bindings) { @@ -29,7 +40,7 @@ namespace Metal { } if (needsUpdate) { - DescriptorSetService::Write(descriptor->vkDescriptorSet, descriptor->bindings); + descriptorSetService->Write(descriptor->vkDescriptorSet, descriptor->bindings); } } } @@ -45,12 +56,12 @@ namespace Metal { } anyMeshes = false; // Check if any mesh is present and streamed - auto view = CTX.worldRepository.registry.view(); + auto view = worldRepository->registry.view(); for (auto entity: view) { - if (CTX.worldRepository.hiddenEntities.contains(entity)) continue; + if (worldRepository->hiddenEntities.contains(entity)) continue; auto &meshComp = view.get(entity); if (meshComp.meshId.empty()) continue; - auto *instance = CTX.meshService.stream(meshComp.meshId); + auto *instance = meshService->stream(meshComp.meshId); if (instance != nullptr && instance->dataBuffer != nullptr && instance->indexBuffer != nullptr) { anyMeshes = true; break; @@ -59,7 +70,7 @@ namespace Metal { if (!anyMeshes) { // No meshes – destroy all structures and set descriptor to null - destroyAccelerationStructures(); // destroys BLAS and TLAS (waits for idle) + dispose(); // destroys BLAS and TLAS (waits for idle) updateDescriptorSets(VK_NULL_HANDLE); accelerationStructureBuilt = false; needsRebuild = false; @@ -67,9 +78,9 @@ namespace Metal { } // At least one mesh exists: rebuild acceleration structures safely - destroyTLAS(); // Destroy old TLAS (waits for idle) before modifying BLAS - buildBLAS(); // Rebuild BLAS (incremental, safe because TLAS is gone) - buildTLAS(); // Build new TLAS + destroyTLAS(); // Destroy old TLAS (waits for idle) before modifying BLAS + buildBLAS(); // Rebuild BLAS (incremental, safe because TLAS is gone) + buildTLAS(); // Build new TLAS if (tlas != VK_NULL_HANDLE) { LOG_INFO("Updating acceleration structures"); @@ -89,21 +100,21 @@ namespace Metal { void RayTracingService::updateMeshMaterials() { bool changed = false; - auto view = CTX.worldRepository.registry.view(); + auto view = worldRepository->registry.view(); for (auto entity: view) { - if (CTX.worldRepository.hiddenEntities.contains(entity)) continue; + if (worldRepository->hiddenEntities.contains(entity)) continue; auto &meshComp = view.get(entity); if (meshComp.meshId.empty()) continue; if (meshComp.renderIndex < meshMetadata.size()) { - CTX.materialService.load(meshMetadata[meshComp.renderIndex], meshComp); + materialService->load(meshMetadata[meshComp.renderIndex], meshComp); changed = true; } } if (changed) { - for (auto *frame : CTX.engineContext.registeredFrames) { + for (auto *frame: engineContext->registeredFrames) { auto *meshMetadataBuffer = frame->getResourceAs(RID_MESH_METADATA_BUFFER); if (meshMetadataBuffer != nullptr) { meshMetadataBuffer->update(meshMetadata.data()); @@ -113,26 +124,25 @@ namespace Metal { } void RayTracingService::destroyTLAS() { - auto &vulkan = CTX.vulkanContext; - if (vulkan.device.device != VK_NULL_HANDLE) { - vkDeviceWaitIdle(vulkan.device.device); + if (vulkanContext->device.device != VK_NULL_HANDLE) { + vkDeviceWaitIdle(vulkanContext->device.device); } if (tlas != VK_NULL_HANDLE) { - vulkan.vkDestroyAccelerationStructureKHR(vulkan.device.device, tlas, nullptr); + vulkanContext->vkDestroyAccelerationStructureKHR(vulkanContext->device.device, tlas, nullptr); tlas = VK_NULL_HANDLE; } if (tlasBuffer) { - CTX.bufferService.dispose("tlas_buffer"); + bufferService->dispose("tlas_buffer"); tlasBuffer = nullptr; } if (instancesBuffer) { - CTX.bufferService.dispose("tlas_instances"); + bufferService->dispose("tlas_instances"); instancesBuffer = nullptr; } if (tlasScratchBuffer) { - CTX.bufferService.dispose("tlas_scratch"); + bufferService->dispose("tlas_scratch"); tlasScratchBuffer = nullptr; } @@ -140,18 +150,18 @@ namespace Metal { } void RayTracingService::buildBLAS() { - auto &vulkan = CTX.vulkanContext; + auto &vulkan = vulkanContext; std::unordered_map uniqueMeshes; - auto view = CTX.worldRepository.registry.view(); + auto view = worldRepository->registry.view(); for (auto entity: view) { - if (CTX.worldRepository.hiddenEntities.contains(entity)) continue; + if (worldRepository->hiddenEntities.contains(entity)) continue; auto &meshComp = view.get(entity); if (meshComp.meshId.empty()) continue; if (uniqueMeshes.contains(meshComp.meshId)) continue; - auto *instance = CTX.meshService.stream(meshComp.meshId); + auto *instance = meshService->stream(meshComp.meshId); if (instance == nullptr || instance->dataBuffer == nullptr || instance->indexBuffer == nullptr) { continue; } @@ -168,18 +178,19 @@ namespace Metal { } // If mesh buffers changed, we need to rebuild this BLAS // For now, let's just destroy and re-create below by removing it - if (vulkan.device.device != VK_NULL_HANDLE) { - vulkan.vkDestroyAccelerationStructureKHR(vulkan.device.device, existing.accelerationStructure, - nullptr); + if (vulkanContext->device.device != VK_NULL_HANDLE) { + vulkanContext->vkDestroyAccelerationStructureKHR(vulkanContext->device.device, + existing.accelerationStructure, + nullptr); } if (existing.buffer) - CTX.bufferService.dispose("blas_" + meshId); + bufferService->dispose("blas_" + meshId); if (existing.scratchBuffer) - CTX.bufferService.dispose("blas_scratch_" + meshId); + bufferService->dispose("blas_scratch_" + meshId); blasEntries.erase(meshId); } - VkDeviceAddress vertexAddress = getDeviceAddress(vulkan, instance->dataBuffer->vkBuffer); - VkDeviceAddress indexAddress = getDeviceAddress(vulkan, instance->indexBuffer->vkBuffer); + VkDeviceAddress vertexAddress = getDeviceAddress(instance->dataBuffer->vkBuffer); + VkDeviceAddress indexAddress = getDeviceAddress(instance->indexBuffer->vkBuffer); VkAccelerationStructureGeometryKHR geometry{}; geometry.sType = VK_STRUCTURE_TYPE_ACCELERATION_STRUCTURE_GEOMETRY_KHR; @@ -206,22 +217,22 @@ namespace Metal { VkAccelerationStructureBuildSizesInfoKHR sizeInfo{}; sizeInfo.sType = VK_STRUCTURE_TYPE_ACCELERATION_STRUCTURE_BUILD_SIZES_INFO_KHR; - vulkan.vkGetAccelerationStructureBuildSizesKHR( - vulkan.device.device, + vulkanContext->vkGetAccelerationStructureBuildSizesKHR( + vulkanContext->device.device, VK_ACCELERATION_STRUCTURE_BUILD_TYPE_DEVICE_KHR, &buildInfo, &primitiveCount, &sizeInfo); BLASEntry entry; - entry.buffer = CTX.bufferService.createBuffer( + entry.buffer = bufferService->createBuffer( "blas_" + meshId, sizeInfo.accelerationStructureSize, VK_BUFFER_USAGE_ACCELERATION_STRUCTURE_STORAGE_BIT_KHR, VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT, true); - entry.scratchBuffer = CTX.bufferService.createBuffer( + entry.scratchBuffer = bufferService->createBuffer( "blas_scratch_" + meshId, sizeInfo.buildScratchSize, VK_BUFFER_USAGE_STORAGE_BUFFER_BIT, @@ -234,11 +245,11 @@ namespace Metal { createInfo.size = sizeInfo.accelerationStructureSize; createInfo.type = VK_ACCELERATION_STRUCTURE_TYPE_BOTTOM_LEVEL_KHR; VulkanUtils::CheckVKResult( - vulkan.vkCreateAccelerationStructureKHR(vulkan.device.device, &createInfo, nullptr, - &entry.accelerationStructure)); + vulkanContext->vkCreateAccelerationStructureKHR(vulkanContext->device.device, &createInfo, nullptr, + &entry.accelerationStructure)); buildInfo.dstAccelerationStructure = entry.accelerationStructure; - buildInfo.scratchData.deviceAddress = getDeviceAddress(vulkan, entry.scratchBuffer->vkBuffer); + buildInfo.scratchData.deviceAddress = getDeviceAddress(entry.scratchBuffer->vkBuffer); VkAccelerationStructureBuildRangeInfoKHR rangeInfo{}; rangeInfo.primitiveCount = primitiveCount; @@ -247,9 +258,9 @@ namespace Metal { rangeInfo.transformOffset = 0; const VkAccelerationStructureBuildRangeInfoKHR *pRangeInfo = &rangeInfo; - VkCommandBuffer cmd = vulkan.beginSingleTimeCommands(); - vulkan.vkCmdBuildAccelerationStructuresKHR(cmd, 1, &buildInfo, &pRangeInfo); - vulkan.endSingleTimeCommands(cmd); + VkCommandBuffer cmd = vulkanContext->beginSingleTimeCommands(); + vulkanContext->vkCmdBuildAccelerationStructuresKHR(cmd, 1, &buildInfo, &pRangeInfo); + vulkanContext->endSingleTimeCommands(cmd); entry.vertexData = instance->dataBuffer; entry.indexData = instance->indexBuffer; @@ -258,16 +269,15 @@ namespace Metal { } void RayTracingService::buildTLAS() { - auto &vulkan = CTX.vulkanContext; meshMetadata.clear(); if (blasEntries.empty()) return; - if (vulkan.device.device != VK_NULL_HANDLE) { - vkDeviceWaitIdle(vulkan.device.device); + if (vulkanContext->device.device != VK_NULL_HANDLE) { + vkDeviceWaitIdle(vulkanContext->device.device); } std::vector instances; - auto view = CTX.worldRepository.registry.view(); + auto view = worldRepository->registry.view(); unsigned int currentInstanceIndex = 0; for (auto entity: view) { @@ -275,7 +285,7 @@ namespace Metal { LOG_ERROR("Max mesh instances reached for ray tracing: " + std::to_string(MAX_MESH_INSTANCES)); break; } - if (CTX.worldRepository.hiddenEntities.contains(entity)) continue; + if (worldRepository->hiddenEntities.contains(entity)) continue; auto &meshComp = view.get(entity); if (meshComp.meshId.empty()) continue; @@ -286,12 +296,12 @@ namespace Metal { VkAccelerationStructureDeviceAddressInfoKHR addressInfo{}; addressInfo.sType = VK_STRUCTURE_TYPE_ACCELERATION_STRUCTURE_DEVICE_ADDRESS_INFO_KHR; addressInfo.accelerationStructure = it->second.accelerationStructure; - VkDeviceAddress blasAddress = vulkan.vkGetAccelerationStructureDeviceAddressKHR( - vulkan.device.device, &addressInfo); + VkDeviceAddress blasAddress = vulkanContext->vkGetAccelerationStructureDeviceAddressKHR( + vulkanContext->device.device, &addressInfo); glm::mat4 model = glm::mat4(1.0f); - if (CTX.worldRepository.registry.all_of(entity)) { - model = CTX.worldRepository.registry.get(entity).model; + if (worldRepository->registry.all_of(entity)) { + model = worldRepository->registry.get(entity).model; } VkTransformMatrixKHR transform{}; @@ -301,8 +311,8 @@ namespace Metal { } } - VkDeviceAddress vertexAddress = getDeviceAddress(vulkan, it->second.vertexData->vkBuffer); - VkDeviceAddress indexAddress = getDeviceAddress(vulkan, it->second.indexData->vkBuffer); + VkDeviceAddress vertexAddress = getDeviceAddress(it->second.vertexData->vkBuffer); + VkDeviceAddress indexAddress = getDeviceAddress(it->second.indexData->vkBuffer); meshComp.renderIndex = currentInstanceIndex; meshMetadata.push_back({meshComp.renderIndex, vertexAddress, indexAddress}); @@ -324,14 +334,14 @@ namespace Metal { updateMeshMaterials(); - instancesBuffer = CTX.bufferService.createBuffer( + instancesBuffer = bufferService->createBuffer( "tlas_instances", sizeof(VkAccelerationStructureInstanceKHR) * instances.size(), VK_BUFFER_USAGE_ACCELERATION_STRUCTURE_BUILD_INPUT_READ_ONLY_BIT_KHR, instances.data(), true); - VkDeviceAddress instancesAddress = getDeviceAddress(vulkan, instancesBuffer->vkBuffer); + VkDeviceAddress instancesAddress = getDeviceAddress(instancesBuffer->vkBuffer); VkAccelerationStructureGeometryKHR tlasGeometry{}; tlasGeometry.sType = VK_STRUCTURE_TYPE_ACCELERATION_STRUCTURE_GEOMETRY_KHR; @@ -353,14 +363,14 @@ namespace Metal { VkAccelerationStructureBuildSizesInfoKHR sizeInfo{}; sizeInfo.sType = VK_STRUCTURE_TYPE_ACCELERATION_STRUCTURE_BUILD_SIZES_INFO_KHR; - vulkan.vkGetAccelerationStructureBuildSizesKHR( - vulkan.device.device, + vulkanContext->vkGetAccelerationStructureBuildSizesKHR( + vulkanContext->device.device, VK_ACCELERATION_STRUCTURE_BUILD_TYPE_DEVICE_KHR, &buildInfo, &instanceCount, &sizeInfo); - tlasBuffer = CTX.bufferService.createBuffer( + tlasBuffer = bufferService->createBuffer( "tlas_buffer", sizeInfo.accelerationStructureSize, VK_BUFFER_USAGE_ACCELERATION_STRUCTURE_STORAGE_BIT_KHR, @@ -373,9 +383,9 @@ namespace Metal { createInfo.size = sizeInfo.accelerationStructureSize; createInfo.type = VK_ACCELERATION_STRUCTURE_TYPE_TOP_LEVEL_KHR; VulkanUtils::CheckVKResult( - vulkan.vkCreateAccelerationStructureKHR(vulkan.device.device, &createInfo, nullptr, &tlas)); + vulkanContext->vkCreateAccelerationStructureKHR(vulkanContext->device.device, &createInfo, nullptr, &tlas)); - tlasScratchBuffer = CTX.bufferService.createBuffer( + tlasScratchBuffer = bufferService->createBuffer( "tlas_scratch", sizeInfo.buildScratchSize, VK_BUFFER_USAGE_STORAGE_BUFFER_BIT, @@ -383,23 +393,20 @@ namespace Metal { true); buildInfo.dstAccelerationStructure = tlas; - buildInfo.scratchData.deviceAddress = getDeviceAddress(vulkan, tlasScratchBuffer->vkBuffer); + buildInfo.scratchData.deviceAddress = getDeviceAddress(tlasScratchBuffer->vkBuffer); VkAccelerationStructureBuildRangeInfoKHR rangeInfo{}; rangeInfo.primitiveCount = instanceCount; const VkAccelerationStructureBuildRangeInfoKHR *pRangeInfo = &rangeInfo; - VkCommandBuffer cmd = vulkan.beginSingleTimeCommands(); - vulkan.vkCmdBuildAccelerationStructuresKHR(cmd, 1, &buildInfo, &pRangeInfo); - vulkan.endSingleTimeCommands(cmd); + VkCommandBuffer cmd = vulkanContext->beginSingleTimeCommands(); + vulkanContext->vkCmdBuildAccelerationStructuresKHR(cmd, 1, &buildInfo, &pRangeInfo); + vulkanContext->endSingleTimeCommands(cmd); } - void RayTracingService::destroyAccelerationStructures() { - LOG_INFO("Destroying acceleration structures"); - auto &vulkan = CTX.vulkanContext; - - if (vulkan.device.device != VK_NULL_HANDLE) { - vkDeviceWaitIdle(vulkan.device.device); + void RayTracingService::dispose() { + if (vulkanContext->device.device != VK_NULL_HANDLE) { + vkDeviceWaitIdle(vulkanContext->device.device); } // Destroy TLAS and its buffers @@ -408,13 +415,14 @@ namespace Metal { // Destroy all BLAS entries for (auto &[meshId, entry]: blasEntries) { if (entry.accelerationStructure != VK_NULL_HANDLE) { - vulkan.vkDestroyAccelerationStructureKHR(vulkan.device.device, entry.accelerationStructure, nullptr); + vulkanContext->vkDestroyAccelerationStructureKHR(vulkanContext->device.device, + entry.accelerationStructure, nullptr); entry.accelerationStructure = VK_NULL_HANDLE; } if (entry.buffer) - CTX.bufferService.dispose("blas_" + meshId); + bufferService->dispose("blas_" + meshId); if (entry.scratchBuffer) - CTX.bufferService.dispose("blas_scratch_" + meshId); + bufferService->dispose("blas_scratch_" + meshId); } blasEntries.clear(); diff --git a/src/service/raytracing/RayTracingService.h b/src/engine/service/RayTracingService.h similarity index 51% rename from src/service/raytracing/RayTracingService.h rename to src/engine/service/RayTracingService.h index bfa42ac6..cec2bca4 100644 --- a/src/service/raytracing/RayTracingService.h +++ b/src/engine/service/RayTracingService.h @@ -1,19 +1,36 @@ #ifndef RAYTRACINGSERVICE_H #define RAYTRACINGSERVICE_H -#include "../../dto/buffers/MeshMetadata.h" -#include "../../enum/engine-definitions.h" -#include +#include "../dto/MeshMetadata.h" #include #include #include #include -#include "../../common/AbstractRuntimeComponent.h" +#include "../../common/IService.h" +#include "../../common/ISync.h" +#include "../../common/IDisposable.h" namespace Metal { - struct BufferInstance; + class DescriptorSetService; + class BufferInstance; + class VulkanContext; + class PipelineService; + struct WorldRepository; + class MeshService; + class MaterialService; + class BufferService; + class EngineContext; + + class RayTracingService final : public IService, public ISync, public IDisposable { + VulkanContext *vulkanContext = nullptr; + PipelineService *pipelineService = nullptr; + WorldRepository *worldRepository = nullptr; + MeshService *meshService = nullptr; + MaterialService *materialService = nullptr; + BufferService *bufferService = nullptr; + EngineContext *engineContext = nullptr; + DescriptorSetService *descriptorSetService = nullptr; - class RayTracingService final : public AbstractRuntimeComponent { struct BLASEntry { VkAccelerationStructureKHR accelerationStructure = VK_NULL_HANDLE; BufferInstance *buffer = nullptr; @@ -21,6 +38,7 @@ namespace Metal { BufferInstance *vertexData = nullptr; BufferInstance *indexData = nullptr; }; + bool anyMeshes = false; // One BLAS per unique mesh ID @@ -40,6 +58,8 @@ namespace Metal { bool needsRebuild = true; bool needsMaterialUpdate = false; + VkDeviceAddress getDeviceAddress(VkBuffer buffer); + void updateDescriptorSets(VkAccelerationStructureKHR asHandle); void buildBLAS(); @@ -51,12 +71,26 @@ namespace Metal { void updateMeshMaterials(); public: + RayTracingService() = default; + + std::vector getDependencies() override { + return { + {"VulkanContext", &vulkanContext}, + {"PipelineService", &pipelineService}, + {"WorldRepository", &worldRepository}, + {"MeshService", &meshService}, + {"MaterialService", &materialService}, + {"BufferService", &bufferService}, + {"EngineContext", &engineContext}, + {"DescriptorSetService", &descriptorSetService} + }; + } void setNeedsMaterialUpdate(bool val) { needsMaterialUpdate = val; } - void destroyAccelerationStructures(); + void dispose() override; void onSync() override; diff --git a/src/util/ShaderUtil.cpp b/src/engine/service/ShaderService.cpp similarity index 83% rename from src/util/ShaderUtil.cpp rename to src/engine/service/ShaderService.cpp index e75c5148..8fc26d80 100644 --- a/src/util/ShaderUtil.cpp +++ b/src/engine/service/ShaderService.cpp @@ -1,22 +1,26 @@ -#include "ShaderUtil.h" +#include "ShaderService.h" #include #include - -#include "../service/pipeline/ShaderModule.h" -#include "../util/VulkanUtils.h" -#include "../util/Util.h" -#include "../context/ApplicationContext.h" -#include "FilesUtil.h" -#include "../service/log/LogService.h" -#include "../enum/LightType.h" -#include "../enum/ShadingMode.h" +#include +#include +#include + +#include "../dto/ShaderModule.h" +#include "../../core/vulkan/VulkanUtils.h" +#include "../../editor/util/Util.h" +#include "../../ApplicationContext.h" +#include "../../common/FilesUtil.h" +#include "../../common/LoggerUtil.h" +#include "../../editor/enum/ShadingMode.h" #include "glslang/Include/glslang_c_interface.h" #include "glslang/Public/resource_limits_c.h" +#include "../../core/DirectoryService.h" +#include "../../core/vulkan/VulkanContext.h" #define BASE_PATH "../resources/shaders/" namespace Metal { - void ShaderUtil::CheckShaderCompilation(glslang_shader_t *shader) { + void ShaderService::CheckShaderCompilation(glslang_shader_t *shader) { const char *infoLog = glslang_shader_get_info_log(shader); const char *debugLog = glslang_shader_get_info_debug_log(shader); const char *shaderCode = glslang_shader_get_preprocessed_code(shader); @@ -29,8 +33,8 @@ namespace Metal { } } - bool ShaderUtil::CompileShader(glslang_stage_t stage, const char *pShaderCode, - ShaderModule *shaderModule) { + bool ShaderService::CompileShader(glslang_stage_t stage, const char *pShaderCode, + ShaderModule *shaderModule) const { const glslang_input_t input = { .language = GLSLANG_SOURCE_GLSL, .stage = stage, @@ -79,7 +83,7 @@ namespace Metal { shaderCreateInfo.codeSize = shaderModule->SPIRV.size() * sizeof(unsigned int); shaderCreateInfo.pCode = static_cast(shaderModule->SPIRV.data()); - VulkanUtils::CheckVKResult(vkCreateShaderModule(CTX.vulkanContext.device.device, &shaderCreateInfo, + VulkanUtils::CheckVKResult(vkCreateShaderModule(vulkanContext->device.device, &shaderCreateInfo, nullptr, &shaderModule->vkShaderModule)); glslang_program_delete(program); @@ -88,7 +92,7 @@ namespace Metal { return !shaderModule->SPIRV.empty(); } - glslang_stage_t ShaderUtil::ShaderStageFromFilename(const char *pFilename) { + glslang_stage_t ShaderService::ShaderStageFromFilename(const char *pFilename) { const std::string s(pFilename); if (s.ends_with(".vert")) { @@ -129,7 +133,7 @@ namespace Metal { throw std::runtime_error("Unknown shader stage in file"); } - std::string ShaderUtil::ProcessIncludes(const std::string &input) { + std::string ShaderService::ProcessIncludes(const std::string &input) { std::string result = input; std::regex includePattern(R"(#include\s+"(.+))"); std::smatch match; @@ -155,32 +159,28 @@ namespace Metal { return result; } - std::string ShaderUtil::ProcessShader(const std::string &file) { + std::string ShaderService::ProcessShader(const std::string &file) { std::string source; FilesUtil::ReadFile(file.c_str(), source); return ProcessIncludes(source); } - VkShaderModule ShaderUtil::CreateShaderModule(const std::string &pFilename) { - const std::string basePath = CTX.getShadersDirectory(); + VkShaderModule ShaderService::createShaderModule(const std::string &pFilename) { std::string source = ProcessShader(BASE_PATH + pFilename); - if (CTX.isDebugMode()) { + if (ctx->isDebugMode()) { source = "#define DEBUG\n" + source; } for (auto &entry: ShadingModes::getShaderEntries()) { source = "#define " + entry.first + " " + std::to_string(entry.second) + "\n" + source; } - for (auto &entry: LightTypes::getEntries()) { - source = "#define " + entry.first + " " + std::to_string(entry.second) + "\n" + source; - } source = "#define PI_2 6.28318530718\n" + source; source = "#define PI 3.14159265\n" + source; const size_t sourceHash = std::hash{}(source); const std::string part(BASE_PATH + pFilename); const std::string shaderName = part.substr(part.find_last_of('/') + 1, part.size()); - const std::string binaryFilename = basePath + shaderName + ".spv"; - const std::string hashFilename = basePath + shaderName + ".hash"; + const std::string binaryFilename = directoryService->getShadersDirectory() + shaderName + ".spv"; + const std::string hashFilename = directoryService->getShadersDirectory() + shaderName + ".hash"; ShaderModule shader{}; @@ -197,7 +197,7 @@ namespace Metal { shaderCreateInfo.codeSize = shader.SPIRV.size() * sizeof(unsigned int); shaderCreateInfo.pCode = static_cast(shader.SPIRV.data()); - if (vkCreateShaderModule(CTX.vulkanContext.device.device, &shaderCreateInfo, + if (vkCreateShaderModule(vulkanContext->device.device, &shaderCreateInfo, nullptr, &shader.vkShaderModule) == VK_SUCCESS) { needsCompilation = false; LOG_INFO("Loaded cached shader: " + shaderName); diff --git a/src/engine/service/ShaderService.h b/src/engine/service/ShaderService.h new file mode 100644 index 00000000..98f5b929 --- /dev/null +++ b/src/engine/service/ShaderService.h @@ -0,0 +1,41 @@ +#ifndef SHADERSERVICE_H +#define SHADERSERVICE_H +#include +#include "../dto/ShaderModule.h" +#include "../../common/IService.h" + +namespace Metal { + class VulkanContext; + + class DirectoryService; + + class ShaderService final : public IService { + VulkanContext *vulkanContext = nullptr; + DirectoryService *directoryService = nullptr; + + static void CheckShaderCompilation(glslang_shader_t *shader); + + bool CompileShader(glslang_stage_t stage, const char *pShaderCode, + ShaderModule *shaderModule) const; + + static glslang_stage_t ShaderStageFromFilename(const char *pFilename); + + std::string ProcessIncludes(const std::string &input); + + std::string ProcessShader(const std::string &file); + + public: + ShaderService() = default; + + std::vector getDependencies() override { + return { + {"VulkanContext", &vulkanContext}, + {"DirectoryService", &directoryService} + }; + } + + VkShaderModule createShaderModule(const std::string &pFilename); + }; +} // Metal + +#endif diff --git a/src/engine/service/StreamingService.cpp b/src/engine/service/StreamingService.cpp new file mode 100644 index 00000000..1b1cabb8 --- /dev/null +++ b/src/engine/service/StreamingService.cpp @@ -0,0 +1,63 @@ +#include "StreamingService.h" + +#include "../EngineContext.h" +#include "../repository/WorldRepository.h" +#include "MeshService.h" +#include "TextureService.h" +#include "VoxelService.h" +#include "../../ApplicationContext.h" + +#include "../resource/SVOInstance.h" +#include "../resource/MeshInstance.h" +#include "../resource/TextureInstance.h" +#include "../../common/LoggerUtil.h" + +#include "../dto/PrimitiveComponent.h" + +namespace Metal { + static constexpr int MAX_TIMEOUT = 10000; + + template + void disposeResources(AbstractResourceService *service, std::unordered_map &lastUse, EngineContext *engineContext) { + auto &resources = service->getResources(); + for (auto it = resources.begin(); it != resources.end();) { + if (lastUse.contains(it->second->getId()) && !it->second->isNoDisposal() && ( + engineContext->currentTimeMs - lastUse.at(it->second->getId())) >= MAX_TIMEOUT) { + LOG_DEBUG( + "Disposing of " + it->first + " Since last use: " + std::to_string(engineContext->currentTimeMs - + lastUse.at(it->second->getId()))); + std::string id = it->first; + ++it; + service->dispose(id); + } else { + ++it; + } + } + } + + void StreamingService::onSync() { + auto view = worldRepository->registry.view(); + for (auto entity: view) { + auto &meshComp = view.get(entity); + if (!meshComp.meshId.empty()) { + lastUse[meshComp.meshId] = engineContext->currentTimeMs; + } + if (!meshComp.albedo.empty()) { + lastUse[meshComp.albedo] = engineContext->currentTimeMs; + } + if (!meshComp.roughness.empty()) { + lastUse[meshComp.roughness] = engineContext->currentTimeMs; + } + if (!meshComp.metallic.empty()) { + lastUse[meshComp.metallic] = engineContext->currentTimeMs; + } + } + + if ((engineContext->currentTime - sinceLastCleanup).count() >= MAX_TIMEOUT) { + sinceLastCleanup = engineContext->currentTime; + disposeResources(meshService, lastUse, engineContext); + disposeResources(textureService, lastUse, engineContext); + disposeResources(voxelService, lastUse, engineContext); + } + } +} diff --git a/src/engine/service/StreamingService.h b/src/engine/service/StreamingService.h new file mode 100644 index 00000000..2eecf222 --- /dev/null +++ b/src/engine/service/StreamingService.h @@ -0,0 +1,48 @@ +#ifndef STREAMINGREPOSITORY_H +#define STREAMINGREPOSITORY_H +#include +#include +#include + +#include "../../common/IService.h" +#include "../../common/ISync.h" + +using Clock = std::chrono::high_resolution_clock; +using TimePoint = std::chrono::time_point; + +namespace Metal { + struct MeshInstance; + struct TextureInstance; + struct SVOInstance; + class EngineContext; + struct WorldRepository; + class MeshService; + class TextureService; + class VoxelService; + + class StreamingService final : public IService, public ISync { + std::unordered_map lastUse{}; + TimePoint sinceLastCleanup; + + EngineContext *engineContext = nullptr; + WorldRepository *worldRepository = nullptr; + MeshService *meshService = nullptr; + TextureService *textureService = nullptr; + VoxelService *voxelService = nullptr; + + public: + std::vector getDependencies() override { + return { + {"EngineContext", &engineContext}, + {"WorldRepository", &worldRepository}, + {"MeshService", &meshService}, + {"TextureService", &textureService}, + {"VoxelService", &voxelService} + }; + } + + void onSync() override; + }; +} // Metal + +#endif //STREAMINGREPOSITORY_H diff --git a/src/service/texture/TextureService.cpp b/src/engine/service/TextureService.cpp similarity index 86% rename from src/service/texture/TextureService.cpp rename to src/engine/service/TextureService.cpp index d5eacf08..707322dc 100644 --- a/src/service/texture/TextureService.cpp +++ b/src/engine/service/TextureService.cpp @@ -1,21 +1,31 @@ #include "TextureService.h" #include +#include -#include "../../util/ImageUtils.h" +#include "../util/ImageUtils.h" +#include "../../editor/enum/engine-definitions.h" +#include "../../ApplicationContext.h" #include #include -#include "TextureData.h" -#include "../../context/ApplicationContext.h" -#include "../../service/texture/TextureInstance.h" -#include "../../service/buffer/BufferInstance.h" +#include "../dto/TextureData.h" +#include "../../core/vulkan/VulkanContext.h" +#include "../../core/vulkan/VulkanUtils.h" +#include "../resource/TextureInstance.h" +#include "../resource/BufferInstance.h" +#include "BufferService.h" +#include "PipelineService.h" +#include "DescriptorSetService.h" +#include "../../core/DirectoryService.h" +#include "../../common/LoggerUtil.h" namespace Metal { + void TextureService::copyBufferToImage(const VkBuffer &vkBuffer, const TextureInstance *image, const int layerCount) const { - VkCommandBuffer commandBuffer = CTX.vulkanContext.beginSingleTimeCommands(); + VkCommandBuffer commandBuffer = vulkanContext->beginSingleTimeCommands(); VkBufferImageCopy region{}; region.bufferOffset = 0; @@ -37,31 +47,31 @@ namespace Metal { VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, 1, ®ion); - CTX.vulkanContext.endSingleTimeCommands(commandBuffer); + vulkanContext->endSingleTimeCommands(commandBuffer); } void TextureService::createImageWithInfo(const VkImageCreateInfo &imageInfo, VkMemoryPropertyFlagBits vkMemoryProperties, TextureInstance *image) const { - if (vkCreateImage(CTX.vulkanContext.device.device, &imageInfo, nullptr, &image->vkImage) != VK_SUCCESS) { + if (vkCreateImage(vulkanContext->device.device, &imageInfo, nullptr, &image->vkImage) != VK_SUCCESS) { throw std::runtime_error("failed to create image!"); } VkMemoryRequirements memRequirements; - vkGetImageMemoryRequirements(CTX.vulkanContext.device.device, image->vkImage, &memRequirements); + vkGetImageMemoryRequirements(vulkanContext->device.device, image->vkImage, &memRequirements); VkMemoryAllocateInfo allocInfo{}; allocInfo.sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO; allocInfo.allocationSize = memRequirements.size; - allocInfo.memoryTypeIndex = CTX.bufferService.findMemoryType( + allocInfo.memoryTypeIndex = bufferService->findMemoryType( memRequirements.memoryTypeBits, vkMemoryProperties); - if (vkAllocateMemory(CTX.vulkanContext.device.device, &allocInfo, nullptr, &image->vkImageMemory) != + if (vkAllocateMemory(vulkanContext->device.device, &allocInfo, nullptr, &image->vkImageMemory) != VK_SUCCESS) { throw std::runtime_error("failed to allocate image memory!"); } - if (vkBindImageMemory(CTX.vulkanContext.device.device, image->vkImage, image->vkImageMemory, 0) != + if (vkBindImageMemory(vulkanContext->device.device, image->vkImage, image->vkImageMemory, 0) != VK_SUCCESS) { throw std::runtime_error("failed to bind image memory!"); } @@ -84,7 +94,7 @@ namespace Metal { samplerInfo.anisotropyEnable = VK_TRUE; samplerInfo.borderColor = VK_BORDER_COLOR_FLOAT_OPAQUE_WHITE; - vkCreateSampler(CTX.vulkanContext.device.device, &samplerInfo, nullptr, &image->vkSampler); + vkCreateSampler(vulkanContext->device.device, &samplerInfo, nullptr, &image->vkSampler); } void TextureService::createImageView(VkFormat imageFormat, TextureInstance *image) const { @@ -102,7 +112,7 @@ namespace Metal { imageViewInfo.subresourceRange.levelCount = image->mipLevels; imageViewInfo.image = image->vkImage; - vkCreateImageView(CTX.vulkanContext.device.device, &imageViewInfo, nullptr, &image->vkImageView); + vkCreateImageView(vulkanContext->device.device, &imageViewInfo, nullptr, &image->vkImageView); } void TextureService::createImage(VkFormat imageFormat, TextureInstance *image, const int width, @@ -125,7 +135,7 @@ namespace Metal { } TextureData *TextureService::loadTextureData(const std::string &id) const { - auto pathToFile = CTX.getAssetDirectory() + FORMAT_FILE_TEXTURE(id); + auto pathToFile = directoryService->getAssetDirectory() + FORMAT_FILE_TEXTURE(id); if (std::filesystem::exists(pathToFile)) { int width, height, channels; unsigned char *data = stbi_load(pathToFile.c_str(), &width, &height, &channels, 0); @@ -163,7 +173,7 @@ namespace Metal { image->vkFormat = imageFormat; LOG_INFO("Loading texture " + id + " from " + pathToImage); LOG_INFO("Texture data: Width " + std::to_string(image->width) + " Height " + std::to_string(image->height)); - BufferInstance *stagingBuffer = CTX.bufferService.createBuffer( + BufferInstance *stagingBuffer = bufferService->createBuffer( id + "_staging", image->width * image->height * 4, VK_BUFFER_USAGE_TRANSFER_SRC_BIT, VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT); @@ -184,7 +194,7 @@ namespace Metal { void TextureService::transitionImageLayout(const TextureInstance *image, VkImageLayout oldLayout, VkImageLayout newLayout) const { - VkCommandBuffer commandBuffer = CTX.vulkanContext.beginSingleTimeCommands(); + VkCommandBuffer commandBuffer = vulkanContext->beginSingleTimeCommands(); VkImageMemoryBarrier barrier{}; barrier.sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER; barrier.oldLayout = oldLayout; @@ -235,19 +245,19 @@ namespace Metal { 0, nullptr, 1, &barrier); - CTX.vulkanContext.endSingleTimeCommands(commandBuffer); + vulkanContext->endSingleTimeCommands(commandBuffer); } void TextureService::generateMipmaps(const TextureInstance *image) const { VkFormatProperties formatProperties; - vkGetPhysicalDeviceFormatProperties(CTX.vulkanContext.physDevice.physical_device, image->vkFormat, + vkGetPhysicalDeviceFormatProperties(vulkanContext->physDevice.physical_device, image->vkFormat, &formatProperties); if (!(formatProperties.optimalTilingFeatures & VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_LINEAR_BIT)) { throw std::runtime_error("texture image format does not support linear blitting!"); } - VkCommandBuffer commandBuffer = CTX.vulkanContext.beginSingleTimeCommands(); + VkCommandBuffer commandBuffer = vulkanContext->beginSingleTimeCommands(); VkImageMemoryBarrier barrier{}; barrier.sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER; @@ -310,11 +320,11 @@ namespace Metal { vkCmdPipelineBarrier(commandBuffer, VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT, 0, 0, nullptr, 0, nullptr, 1, &barrier); - CTX.vulkanContext.endSingleTimeCommands(commandBuffer); + vulkanContext->endSingleTimeCommands(commandBuffer); } TextureInstance *TextureService::create(const std::string &id) { - auto pathToFile = CTX.getAssetDirectory() + FORMAT_FILE_TEXTURE(id); + auto pathToFile = directoryService->getAssetDirectory() + FORMAT_FILE_TEXTURE(id); if (std::filesystem::exists(pathToFile)) { auto *instance = loadTexture(id, pathToFile, true, VK_FORMAT_R8G8B8A8_UNORM); if (instance != nullptr) { @@ -363,7 +373,7 @@ namespace Metal { textureIndices[id] = index; // Update all descriptors that contain a texture array - auto descriptors = CTX.pipelineService.getAllDescriptors(); + auto descriptors = pipelineService->getAllDescriptors(); for (auto *descriptor: descriptors) { for (auto &binding: descriptor->bindings) { if (binding.descriptorType == VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER && binding.descriptorCount > 1) { @@ -376,12 +386,12 @@ namespace Metal { write.descriptorCount = 1; VkDescriptorImageInfo imageInfo{}; - imageInfo.sampler = CTX.vulkanContext.vkTextureSampler; + imageInfo.sampler = vulkanContext->vkTextureSampler; imageInfo.imageView = texture->vkImageView; imageInfo.imageLayout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL; write.pImageInfo = &imageInfo; - vkUpdateDescriptorSets(CTX.vulkanContext.device.device, 1, &write, 0, nullptr); + vkUpdateDescriptorSets(vulkanContext->device.device, 1, &write, 0, nullptr); } } } @@ -392,13 +402,13 @@ namespace Metal { } void TextureService::disposeResource(TextureInstance *resource) { - vkDestroyImage(CTX.vulkanContext.device.device, resource->vkImage, nullptr); - vkFreeMemory(CTX.vulkanContext.device.device, resource->vkImageMemory, nullptr); - vkDestroyImageView(CTX.vulkanContext.device.device, resource->vkImageView, nullptr); - vkDestroySampler(CTX.vulkanContext.device.device, resource->vkSampler, nullptr); + vkDestroyImage(vulkanContext->device.device, resource->vkImage, nullptr); + vkFreeMemory(vulkanContext->device.device, resource->vkImageMemory, nullptr); + vkDestroyImageView(vulkanContext->device.device, resource->vkImageView, nullptr); + vkDestroySampler(vulkanContext->device.device, resource->vkSampler, nullptr); if (resource->imageDescriptor != nullptr) { - CTX.descriptorSetService.disposeResource(resource->imageDescriptor); + descriptorSetService->disposeResource(resource->imageDescriptor); } } @@ -418,7 +428,7 @@ namespace Metal { samplerCreateInfo.maxAnisotropy = 8; samplerCreateInfo.anisotropyEnable = VK_TRUE; samplerCreateInfo.borderColor = VK_BORDER_COLOR_FLOAT_TRANSPARENT_BLACK; - VulkanUtils::CheckVKResult(vkCreateSampler(CTX.vulkanContext.device.device, &samplerCreateInfo, nullptr, + VulkanUtils::CheckVKResult(vkCreateSampler(vulkanContext->device.device, &samplerCreateInfo, nullptr, &vkImageSampler)); } diff --git a/src/service/texture/TextureService.h b/src/engine/service/TextureService.h similarity index 68% rename from src/service/texture/TextureService.h rename to src/engine/service/TextureService.h index 40d00e1f..abc1bd26 100644 --- a/src/service/texture/TextureService.h +++ b/src/engine/service/TextureService.h @@ -4,14 +4,25 @@ #include #include -#include "TextureData.h" -#include "../abstract/AbstractResourceService.h" -#include "TextureInstance.h" +#include "../dto/TextureData.h" +#include "../../common/AbstractResourceService.h" +#include "../resource/TextureInstance.h" namespace Metal { struct TextureInstance; + class VulkanContext; + class BufferService; + class PipelineService; + class DescriptorSetService; + class DirectoryService; class TextureService final : public AbstractResourceService { + VulkanContext *vulkanContext = nullptr; + BufferService *bufferService = nullptr; + PipelineService *pipelineService = nullptr; + DescriptorSetService *descriptorSetService = nullptr; + DirectoryService *directoryService = nullptr; + unsigned int nextTextureIndex = 1; std::unordered_map textureIndices{}; @@ -32,6 +43,16 @@ namespace Metal { void generateMipmaps(const TextureInstance *image) const; public: + std::vector getDependencies() override { + return { + {"VulkanContext", &vulkanContext}, + {"BufferService", &bufferService}, + {"PipelineService", &pipelineService}, + {"DescriptorSetService", &descriptorSetService}, + {"DirectoryService", &directoryService} + }; + } + [[nodiscard]] TextureData *loadTextureData(const std::string &id) const; TextureInstance *stream(const std::string &id); diff --git a/src/service/transform/TransformService.cpp b/src/engine/service/TransformService.cpp similarity index 66% rename from src/service/transform/TransformService.cpp rename to src/engine/service/TransformService.cpp index e977dc2f..bc08a257 100644 --- a/src/service/transform/TransformService.cpp +++ b/src/engine/service/TransformService.cpp @@ -2,14 +2,19 @@ #include #include #include +#include "../../common/LoggerUtil.h" -#include "../../context/ApplicationContext.h" -#include "../../repository/world/components/TransformComponent.h" +#include "../../ApplicationContext.h" +#include "../dto/TransformComponent.h" +#include "../repository/WorldRepository.h" +#include "../dto/TransformComponent.h" +#include "../dto/PrimitiveComponent.h" +#include "RayTracingService.h" namespace Metal { void TransformService::onSync() { - for (auto entity : CTX.worldRepository.registry.view()) { - TransformComponent &st = CTX.worldRepository.registry.get(entity); + for (auto entity : worldRepository->registry.view()) { + TransformComponent &st = worldRepository->registry.get(entity); if (st.isNotFrozen()) { transform(&st, nullptr); st.freezeVersion(); @@ -36,8 +41,8 @@ namespace Metal { st->model = auxMat4 * auxMat42; st->freezeVersion(); - if (CTX.worldRepository.registry.all_of(st->getEntityId())) { - CTX.rayTracingService.markDirty(); + if (worldRepository->registry.all_of(st->getEntityId())) { + rayTracingService->markDirty(); } } } // Metal diff --git a/src/engine/service/TransformService.h b/src/engine/service/TransformService.h new file mode 100644 index 00000000..bab96925 --- /dev/null +++ b/src/engine/service/TransformService.h @@ -0,0 +1,39 @@ +#ifndef TRANSFORMSERVICE_H +#define TRANSFORMSERVICE_H +#include +#include +#include + +#include "../../common/ISync.h" +#include "../../common/IService.h" + +namespace Metal { + struct TransformComponent; + + struct WorldRepository; + class RayTracingService; + + class TransformService final : public IService, public ISync { + WorldRepository *worldRepository = nullptr; + RayTracingService *rayTracingService = nullptr; + + glm::vec3 distanceAux{}; + glm::mat4x4 auxMat4{}; + glm::vec3 translation{}; + glm::mat4x4 auxMat42{}; + + public: + std::vector getDependencies() override { + return { + {"WorldRepository", &worldRepository}, + {"RayTracingService", &rayTracingService} + }; + } + + void onSync() override; + + void transform(TransformComponent *st, const TransformComponent *parentTransform); + }; +} // Metal + +#endif diff --git a/src/engine/service/VolumeService.cpp b/src/engine/service/VolumeService.cpp new file mode 100644 index 00000000..52d3b3b8 --- /dev/null +++ b/src/engine/service/VolumeService.cpp @@ -0,0 +1,46 @@ +#include "VolumeService.h" +#include "../../ApplicationContext.h" +#include "../dto/VolumeComponent.h" +#include "../resource/BufferInstance.h" +#include "../../editor/enum/EngineResourceIDs.h" +#include "../repository/WorldRepository.h" +#include "../dto/TransformComponent.h" +#include "../dto/VolumeComponent.h" +#include "../EngineContext.h" + +namespace Metal { + void VolumeService::registerVolumes() { + auto ®istry = worldRepository->registry; + auto view = registry.view(); + for (auto entityId: view) { + if (!registry.all_of(entityId)) { + continue; + } + auto &l = registry.get(entityId); + auto &t = registry.get(entityId); + if (worldRepository->hiddenEntities.contains(entityId)) { + continue; + } + + auto &translation = t.translation; + + items.push_back(VolumeData( + glm::vec4(l.albedo, l.samples), + translation, + t.scale, + glm::vec3(l.density, l.scatteringAlbedo, l.g) + )); + } + } + + // TODO - ADD EVENT SYSTEM THAT TRIGGERS THIS UPDATE + void VolumeService::onSync() { + items.clear(); + + registerVolumes(); + + if (!items.empty()) { + engineContext->currentFrame->getResourceAs(RID_VOLUMES_BUFFER)->update(items.data()); + } + } +} // Metal diff --git a/src/engine/service/VolumeService.h b/src/engine/service/VolumeService.h new file mode 100644 index 00000000..70ff3a1e --- /dev/null +++ b/src/engine/service/VolumeService.h @@ -0,0 +1,37 @@ +#ifndef VOLUME_SERVICE_H +#define VOLUME_SERVICE_H +#include + +#include "../../common/IService.h" +#include "../../common/ISync.h" +#include "../dto/VolumeData.h" + +namespace Metal { + + struct WorldRepository; + class EngineContext; + + class VolumeService final : public IService, public ISync { + WorldRepository *worldRepository = nullptr; + EngineContext *engineContext = nullptr; + + std::vector items{}; + + void registerVolumes(); + public: + std::vector getDependencies() override { + return { + {"WorldRepository", &worldRepository}, + {"EngineContext", &engineContext} + }; + } + + void onSync() override; + + unsigned int getCount() const { + return items.size(); + } + }; +} // Metal + +#endif //LIGHTSSERVICE_H diff --git a/src/service/voxel/VoxelService.cpp b/src/engine/service/VoxelService.cpp similarity index 94% rename from src/service/voxel/VoxelService.cpp rename to src/engine/service/VoxelService.cpp index 8991b5b9..d1db5046 100644 --- a/src/service/voxel/VoxelService.cpp +++ b/src/engine/service/VoxelService.cpp @@ -1,10 +1,6 @@ -// -// Created by russi on 2/18/2026. -// - #include "VoxelService.h" -#include "SVOInstance.h" +#include "../resource/SVOInstance.h" namespace Metal { diff --git a/src/service/voxel/VoxelService.h b/src/engine/service/VoxelService.h similarity index 83% rename from src/service/voxel/VoxelService.h rename to src/engine/service/VoxelService.h index cd5450dc..aab1bf57 100644 --- a/src/service/voxel/VoxelService.h +++ b/src/engine/service/VoxelService.h @@ -1,8 +1,8 @@ #ifndef METAL_ENGINE_VOXELSERVICE_H #define METAL_ENGINE_VOXELSERVICE_H -#include "../abstract/AbstractResourceService.h" -#include "SVOInstance.h" +#include "../../common/AbstractResourceService.h" +#include "../resource/SVOInstance.h" namespace Metal { struct SVOInstance; diff --git a/src/util/ImageUtils.h b/src/engine/util/ImageUtils.h similarity index 100% rename from src/util/ImageUtils.h rename to src/engine/util/ImageUtils.h diff --git a/src/enum/EntryType.h b/src/enum/EntryType.h deleted file mode 100644 index ea1790a7..00000000 --- a/src/enum/EntryType.h +++ /dev/null @@ -1,57 +0,0 @@ -#ifndef FILETYPE_H -#define FILETYPE_H - -namespace Metal::EntryType { - enum EntryType { - SCENE, - MESH, - TEXTURE, - VOLUME, - DIRECTORY, - NONE - }; - - static const char *Names = "Scene\0Mesh\0Texture\0Volume\0Directory\0None\0"; - - static EntryType ValueOfIndex(const int option) { - if (option == 0) { - return EntryType::SCENE; - } - if (option == 1) { - return EntryType::MESH; - } - if (option == 2) { - return EntryType::TEXTURE; - } - if (option == 3) { - return EntryType::VOLUME; - } - if (option == 4) { - return EntryType::DIRECTORY; - } - return EntryType::NONE; - } - - static int IndexOfValue(const EntryType mode) { - if (mode == SCENE) { - return 0; - } - if (mode == MESH) { - return 1; - } - if (mode == TEXTURE) { - return 2; - } - if (mode == VOLUME) { - return 3; - } - if (mode == DIRECTORY) { - return 4; - } - if (mode == NONE) { - return 6; - } - return 6; - } -} -#endif diff --git a/src/enum/LightType.h b/src/enum/LightType.h deleted file mode 100644 index 4333562b..00000000 --- a/src/enum/LightType.h +++ /dev/null @@ -1,19 +0,0 @@ -#ifndef LIGHTTYPE_H -#define LIGHTTYPE_H -#include -#include - -namespace Metal::LightTypes{ - enum LightType { - SPHERE, - PLANE - }; - - inline std::unordered_map getEntries() { - std::unordered_map entries; - entries["ITEM_TYPE_SPHERE"] = SPHERE; - entries["ITEM_TYPE_PLANE"] = PLANE; - return entries; - } -} -#endif //LIGHTTYPE_H diff --git a/src/enum/PassType.h b/src/enum/PassType.h deleted file mode 100644 index d0c67489..00000000 --- a/src/enum/PassType.h +++ /dev/null @@ -1,18 +0,0 @@ -#ifndef PASS_TYPE_H -#define PASS_TYPE_H - -namespace Metal { - enum PassType { - RAY_TRACING, - ACCUMULATION, - TEMPORAL_ACCUMULATION, - SPATIAL_FILTER, - POST_PROCESSING, - SELECTION_OUTLINE, - GRID, - ICONS, - SELECTION_ID - }; -} - -#endif //PASS_TYPE_H diff --git a/src/main.cpp b/src/main.cpp index 6ba7dc50..8e452fdc 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -1,19 +1,114 @@ -#define STB_IMAGE_IMPLEMENTATION -#include "stb_image.h" -#define STB_IMAGE_WRITE_IMPLEMENTATION -#include "stb_image_write.h" -#define VMA_IMPLEMENTATION -#define GLM_FORCE_RADIANS -#define GLM_FORCE_DEPTH_ZERO_TO_ONE -#include "context/ApplicationContext.h" +#include "ApplicationContext.h" +#include "core/DirectoryService.h" +#include "core/FrameService.h" +#include "core/glfw/GLFWContext.h" +#include "core/gui/GuiContext.h" +#include "core/vulkan/VulkanContext.h" +#include "editor/EditorPanel.h" +#include "editor/service/AsyncTaskService.h" +#include "editor/service/DockService.h" +#include "editor/service/FileImporterService.h" +#include "editor/service/FilesService.h" +#include "editor/service/MaterialImporterService.h" +#include "editor/service/MeshImporterService.h" +#include "editor/service/NotificationService.h" +#include "editor/service/PickingService.h" +#include "editor/service/SceneImporterService.h" +#include "editor/service/SelectionService.h" +#include "editor/service/TextureImporterService.h" +#include "editor/service/ThemeService.h" +#include "editor/service/VoxelImporterService.h" +#include "editor/repository/EditorRepository.h" + +#include "engine/repository/EngineRepository.h" +#include "engine/repository/RuntimeRepository.h" +#include "engine/repository/WorldRepository.h" + +#include "engine/service/BufferService.h" +#include "engine/service/CameraService.h" +#include "engine/service/CommandBufferRecorderService.h" +#include "engine/service/DescriptorSetService.h" +#include "engine/service/FrameBufferService.h" +#include "engine/service/LightService.h" +#include "engine/service/MaterialService.h" +#include "engine/service/MeshService.h" +#include "engine/service/PipelineService.h" +#include "engine/service/RayTracingService.h" +#include "engine/service/ShaderService.h" +#include "engine/service/StreamingService.h" +#include "engine/service/TextureService.h" +#include "engine/service/TransformService.h" +#include "engine/service/VolumeService.h" +#include "engine/service/VoxelService.h" +#include "engine/EngineContext.h" int main(int, char **) { - Metal::ApplicationContext::Init(true); + std::shared_ptr context = std::make_shared(false); + + // --- ORDER MATTERS + context->registerSingleton(context); + context->registerSingleton(std::make_shared()); + context->registerSingleton(std::make_shared()); + context->registerSingleton(std::make_shared()); + context->registerSingleton(std::make_shared()); + // --- ORDER MATTERS + + context->registerSingleton(std::make_shared()); + context->registerSingleton(std::make_shared()); + context->registerSingleton(std::make_shared()); + context->registerSingleton(std::make_shared()); + context->registerSingleton(std::make_shared()); + context->registerSingleton(std::make_shared()); + context->registerSingleton(std::make_shared()); + context->registerSingleton(std::make_shared()); + context->registerSingleton(std::make_shared()); + context->registerSingleton(std::make_shared()); + context->registerSingleton(std::make_shared()); + context->registerSingleton(std::make_shared()); + context->registerSingleton(std::make_shared()); + context->registerSingleton(std::make_shared()); + context->registerSingleton(std::make_shared()); + context->registerSingleton(std::make_shared()); + context->registerSingleton(std::make_shared()); + context->registerSingleton(std::make_shared()); + context->registerSingleton(std::make_shared()); - if (!CTX.isValidContext()) { + context->registerSingleton(std::make_shared()); + context->registerSingleton(std::make_shared()); + context->registerSingleton(std::make_shared()); + context->registerSingleton(std::make_shared()); + context->registerSingleton(std::make_shared()); + context->registerSingleton(std::make_shared()); + context->registerSingleton(std::make_shared()); + context->registerSingleton(std::make_shared()); + context->registerSingleton(std::make_shared()); + context->registerSingleton(std::make_shared()); + context->registerSingleton(std::make_shared()); + context->registerSingleton(std::make_shared()); + + context->registerSingleton(std::make_shared()); + context->registerSingleton(std::make_shared()); + context->registerSingleton(std::make_shared()); + context->registerSingleton(std::make_shared()); + + context->onInitialize(); + auto &frameService = context->getSingleton(); + auto &directoryService = context->getSingleton(); + directoryService.updateRootPath(false); + Metal::EditorPanel editor{}; + context->injectDependencies(&editor); + editor.onInitialize(); + + frameService.setPanel(&editor); + if (!frameService.isValidContext()) { printf("GLFW: Vulkan Not Supported\n"); return 1; } - CTX.start(); + frameService.start(); + context->dispose(); + context->getSingleton().disposeManually(); + context->getSingleton().disposeManually(); + context->getSingleton().disposeManually(); + return 0; } diff --git a/src/repository/abstract/AbstractCoreRepository.h b/src/repository/abstract/AbstractCoreRepository.h deleted file mode 100644 index 30369685..00000000 --- a/src/repository/abstract/AbstractCoreRepository.h +++ /dev/null @@ -1,17 +0,0 @@ -#ifndef ABSTRACTCOREREPOSITORY_H -#define ABSTRACTCOREREPOSITORY_H -#include "../../common/AbstractRuntimeComponent.h" - -namespace Metal { - class VulkanContext; - class FrameBufferService; - class BufferService; - class PipelineService; - - class AbstractCoreRepository : public AbstractRuntimeComponent { - }; - - -} // Metal - -#endif //ABSTRACTCOREREPOSITORY_H diff --git a/src/repository/dock/DockPosition.h b/src/repository/dock/DockPosition.h deleted file mode 100644 index b0b3ae35..00000000 --- a/src/repository/dock/DockPosition.h +++ /dev/null @@ -1,14 +0,0 @@ -#ifndef METAL_ENGINE_DOCKPOSITION_H -#define METAL_ENGINE_DOCKPOSITION_H - -namespace Metal { - enum DockPosition { - TOP, - RIGHT_BOTTOM, - RIGHT_TOP, - LEFT_TOP, - LEFT_BOTTOM, - BOTTOM - }; -} -#endif //METAL_ENGINE_DOCKPOSITION_H diff --git a/src/repository/dock/DockRepository.cpp b/src/repository/dock/DockRepository.cpp deleted file mode 100644 index 560f31d7..00000000 --- a/src/repository/dock/DockRepository.cpp +++ /dev/null @@ -1,25 +0,0 @@ -#include "DockRepository.h" - -namespace Metal { - DockRepository::DockRepository() : AbstractRuntimeComponent() { - auto *rightT = new DockDTO{&DockSpace::WORLD}; - auto *leftTop = new DockDTO{&DockSpace::REPOSITORIES}; - auto *leftDown = new DockDTO{&DockSpace::INSPECTOR}; - auto *downLeft = new DockDTO{&DockSpace::CONSOLE}; - auto *downRight = new DockDTO{&DockSpace::FILES}; - - center.sizeRatioForNodeAtDir = 0.5f; - rightT->sizeRatioForNodeAtDir = 0.25f; - leftTop->sizeRatioForNodeAtDir = 0.2f; - leftDown->sizeRatioForNodeAtDir = 0.5f; - downLeft->sizeRatioForNodeAtDir = 0.25f; - downRight->sizeRatioForNodeAtDir = 0.5f; - - right.push_back(rightT); - left.push_back(leftTop); - left.push_back(leftDown); - - bottom.push_back(downLeft); - bottom.push_back(downRight); - } -} // Metal diff --git a/src/repository/dock/DockRepository.h b/src/repository/dock/DockRepository.h deleted file mode 100644 index dfbd6d79..00000000 --- a/src/repository/dock/DockRepository.h +++ /dev/null @@ -1,21 +0,0 @@ -#ifndef METAL_ENGINE_DOCKREPOSITORY_H -#define METAL_ENGINE_DOCKREPOSITORY_H - -#include -#include "DockDTO.h" -#include "../../common/AbstractRuntimeComponent.h" - -namespace Metal { - struct DockRepository final : AbstractRuntimeComponent { - DockDTO center{&DockSpace::VIEWPORT}; - std::vector bottom; - std::vector left; - std::vector right; - - bool isInitialized = false; - - explicit DockRepository(); - }; -} // Metal - -#endif diff --git a/src/repository/dock/DockSpace.cpp b/src/repository/dock/DockSpace.cpp deleted file mode 100644 index ce757cbc..00000000 --- a/src/repository/dock/DockSpace.cpp +++ /dev/null @@ -1,42 +0,0 @@ -#include "DockSpace.h" -#include "../../common/interface/Icons.h" -#include "../../context/editor/dock-spaces/console/ConsolePanel.h" -#include "../../context/editor/dock-spaces/files/FilesPanel.h" -#include "../../context/editor/dock-spaces/metrics/MetricsPanel.h" -#include "../../context/editor/dock-spaces/repositories/RepositoriesPanel.h" -#include "../../context/editor/dock-spaces/inspector/InspectorPanel.h" -#include "../../context/editor/dock-spaces/viewport/ViewportPanel.h" -#include "../../context/editor/dock-spaces/world/WorldPanel.h" - -#define CB(clazz) []() { return new clazz; } - -namespace Metal { - DockSpace DockSpace::VIEWPORT{-1, "Viewport", Icons::ipublic, 0, 0,CB(ViewportPanel)}; - DockSpace DockSpace::INSPECTOR{0, "Inspector", Icons::search, 4, 4,CB(InspectorPanel)}; - DockSpace DockSpace::WORLD{1, "World", Icons::account_tree, 4, 4, CB(WorldPanel)}; - DockSpace DockSpace::CONSOLE{2, "Console", Icons::terminal, 4, 4, CB(ConsolePanel)}; - DockSpace DockSpace::FILES{3, "Files", Icons::folder_open, 4, 4, CB(FilesPanel)}; - DockSpace DockSpace::METRICS{4, "Metrics", Icons::analytics, 4, 4, CB(MetricsPanel)}; - DockSpace DockSpace::REPOSITORIES{5, "Repositories", Icons::search, 4, 4, CB(RepositoriesPanel)}; - const char *DockSpace::OPTIONS = "Inspector\0World\0Console\0Files\0Metrics\0Repositories\0"; - - - DockSpace *DockSpace::GetOption(const int selected) { - switch (selected) { - case 0: - return &INSPECTOR; - case 1: - return &WORLD; - case 2: - return &CONSOLE; - case 3: - return &FILES; - case 4: - return &METRICS; - case 5: - return &REPOSITORIES; - default: - return nullptr; - } - } -} diff --git a/src/repository/streaming/StreamingService.cpp b/src/repository/streaming/StreamingService.cpp deleted file mode 100644 index a3c3667d..00000000 --- a/src/repository/streaming/StreamingService.cpp +++ /dev/null @@ -1,56 +0,0 @@ -#include "StreamingService.h" - -#include "../../context/ApplicationContext.h" -#include "../../service/voxel/SVOInstance.h" -#include "../../service/mesh/MeshInstance.h" -#include "../../service/texture/TextureInstance.h" - -#include "../../repository/world/components/PrimitiveComponent.h" - -namespace Metal { - static constexpr int MAX_TIMEOUT = 10000; - - template - void disposeResources(AbstractResourceService &service, std::unordered_map &lastUse) { - auto &resources = service.getResources(); - for (auto it = resources.begin(); it != resources.end();) { - if (lastUse.contains(it->second->getId()) && !it->second->isNoDisposal() && ( - CTX.engineContext.currentTimeMs - lastUse.at(it->second->getId())) >= MAX_TIMEOUT) { - LOG_DEBUG( - "Disposing of " + it->first + " Since last use: " + std::to_string(CTX.engineContext.currentTimeMs - - lastUse.at(it->second->getId()))); - std::string id = it->first; - ++it; - service.dispose(id); - } else { - ++it; - } - } - } - - void StreamingService::onSync() { - auto view = CTX.worldRepository.registry.view(); - for (auto entity: view) { - auto &meshComp = view.get(entity); - if (!meshComp.meshId.empty()) { - lastUse[meshComp.meshId] = CTX.engineContext.currentTimeMs; - } - if (!meshComp.albedo.empty()) { - lastUse[meshComp.albedo] = CTX.engineContext.currentTimeMs; - } - if (!meshComp.roughness.empty()) { - lastUse[meshComp.roughness] = CTX.engineContext.currentTimeMs; - } - if (!meshComp.metallic.empty()) { - lastUse[meshComp.metallic] = CTX.engineContext.currentTimeMs; - } - } - - if ((CTX.engineContext.currentTime - sinceLastCleanup).count() >= MAX_TIMEOUT) { - sinceLastCleanup = CTX.engineContext.currentTime; - disposeResources(CTX.meshService, lastUse); - disposeResources(CTX.textureService, lastUse); - disposeResources(CTX.voxelService, lastUse); - } - } -} diff --git a/src/repository/streaming/StreamingService.h b/src/repository/streaming/StreamingService.h deleted file mode 100644 index 2fcba091..00000000 --- a/src/repository/streaming/StreamingService.h +++ /dev/null @@ -1,28 +0,0 @@ -#ifndef STREAMINGREPOSITORY_H -#define STREAMINGREPOSITORY_H -#include -#include -#include - -#include "../../service/abstract/AbstractResourceService.h" -#include "../abstract/AbstractCoreRepository.h" -#include "../abstract/RuntimeResource.h" - -using Clock = std::chrono::high_resolution_clock; -using TimePoint = std::chrono::time_point; - -namespace Metal { - struct MeshInstance; - struct TextureInstance; - struct SVOInstance; - - class StreamingService final : public AbstractRuntimeComponent { - std::unordered_map lastUse{}; - TimePoint sinceLastCleanup; - - public: - void onSync() override; - }; -} // Metal - -#endif //STREAMINGREPOSITORY_H diff --git a/src/service/descriptor/DescriptorSetService.h b/src/service/descriptor/DescriptorSetService.h deleted file mode 100644 index c11de27e..00000000 --- a/src/service/descriptor/DescriptorSetService.h +++ /dev/null @@ -1,32 +0,0 @@ -#ifndef DESCRIPTORSETSERVICE_H -#define DESCRIPTORSETSERVICE_H - -#include "../abstract/AbstractResourceService.h" -#include "DescriptorInstance.h" - -namespace Metal { - struct PipelineBuilder; - struct TextureInstance; - struct FrameBufferInstance; - - class DescriptorSetService final : public AbstractResourceService { - public: - DescriptorInstance *createDescriptor(const PipelineBuilder &pipelineBuilder, const std::string &id, VkShaderStageFlags stageFlags); - - void disposeResource(DescriptorInstance *resource) override; - - std::vector getAllDescriptors() const; - - void setImageDescriptor(const FrameBufferInstance *framebuffer, unsigned int attachmentIndex); - - void setImageDescriptor(TextureInstance *texture); - - void updateDescriptor(DescriptorInstance *descriptor); - - void write(DescriptorInstance *descriptor); - - static void Write(const VkDescriptorSet &vkDescriptorSet, const std::vector &bindings); - }; -} - -#endif //DESCRIPTORSETSERVICE_H diff --git a/src/service/dock/DockService.h b/src/service/dock/DockService.h deleted file mode 100644 index fe3c9cfd..00000000 --- a/src/service/dock/DockService.h +++ /dev/null @@ -1,22 +0,0 @@ -#ifndef METAL_ENGINE_DOCKSERVICE_H -#define METAL_ENGINE_DOCKSERVICE_H - -#include "imgui.h" -#include "../../repository/dock/DockDTO.h" -#include "../../context/editor/dock-spaces/docks/DockSpacePanel.h" -#include "../../common/AbstractRuntimeComponent.h" - -namespace Metal { - class AbstractPanel; - - class DockService final : public AbstractRuntimeComponent { - public: - void buildViews(ImGuiID windowId, AbstractPanel *panel) const; - - static void createDockSpace(DockDTO *dockSpace, ImGuiID *dockMainId); - - static void addWindow(DockDTO *d, AbstractPanel *panel); - }; -} // Metal - -#endif diff --git a/src/service/files/FileImporterService.h b/src/service/files/FileImporterService.h deleted file mode 100644 index 2df8abd7..00000000 --- a/src/service/files/FileImporterService.h +++ /dev/null @@ -1,25 +0,0 @@ -#ifndef METAL_ENGINE_LOADINGSERVICE_H -#define METAL_ENGINE_LOADINGSERVICE_H - -#include -#include -#include - -#include "../../dto/file/ImportSettingsDTO.h" -#include "../../common/AbstractRuntimeComponent.h" - -namespace Metal { - class FileImporterService final : public AbstractRuntimeComponent { - public: - - using LoadingTask = std::function; - - void importFile(std::string targetDir, std::string file, const std::shared_ptr &settings); - - std::string runAsync(const std::string &taskName, const LoadingTask &task) const; - - std::string collectCompatibleFiles() const; - }; -} - -#endif diff --git a/src/service/files/FilesService.h b/src/service/files/FilesService.h deleted file mode 100644 index c2906941..00000000 --- a/src/service/files/FilesService.h +++ /dev/null @@ -1,38 +0,0 @@ -#ifndef FILESSERVICE_H -#define FILESSERVICE_H -#include -#include -#include - -#include "../../common/AbstractRuntimeComponent.h" - -namespace Metal { - struct FSEntry; - - class FilesService final : public AbstractRuntimeComponent { - FSEntry *root = nullptr; - - public: - explicit FilesService() - : AbstractRuntimeComponent() { - } - - FSEntry *getRoot() { - return root; - } - - void onInitialize() override; - - std::unique_ptr getResource(const std::string &id); - - void deleteFiles(const std::unordered_map &files_context); - - void Move(FSEntry *toMove, FSEntry *targetDir); - - static void CreateDirectory(FSEntry *currentDirectory); - - static void GetEntries(FSEntry *root); - }; -} // Metal - -#endif //FILESSERVICE_H diff --git a/src/service/framebuffer/FrameBufferAttachment.cpp b/src/service/framebuffer/FrameBufferAttachment.cpp deleted file mode 100644 index e04d3983..00000000 --- a/src/service/framebuffer/FrameBufferAttachment.cpp +++ /dev/null @@ -1,16 +0,0 @@ -#include "FrameBufferAttachment.h" - - -#include "../../context/ApplicationContext.h" - -namespace Metal { - void FrameBufferAttachment::dispose() const { - vkDestroyImage(CTX.vulkanContext.device.device, vkImage, nullptr); - vkDestroyImageView(CTX.vulkanContext.device.device, vkImageView, nullptr); - vkFreeMemory(CTX.vulkanContext.device.device, vkImageMemory, nullptr); - - if (imageDescriptor != nullptr) { - CTX.descriptorSetService.disposeResource(imageDescriptor); - } - } -} diff --git a/src/service/framebuffer/FrameBufferAttachment.h b/src/service/framebuffer/FrameBufferAttachment.h deleted file mode 100644 index 1c865e8f..00000000 --- a/src/service/framebuffer/FrameBufferAttachment.h +++ /dev/null @@ -1,18 +0,0 @@ -#ifndef FRAMEBUFFERATTACHMENT_H -#define FRAMEBUFFERATTACHMENT_H -#include "../descriptor/DescriptorInstance.h" - -namespace Metal { - struct FrameBufferAttachment final { - VkImage vkImage = VK_NULL_HANDLE; - VkDeviceMemory vkImageMemory = VK_NULL_HANDLE; - VkImageView vkImageView = VK_NULL_HANDLE; - VkFormat format = VK_FORMAT_MAX_ENUM; - DescriptorInstance *imageDescriptor = nullptr; - bool depth = false; - - void dispose() const; - }; -} - -#endif diff --git a/src/service/log/LogService.h b/src/service/log/LogService.h deleted file mode 100644 index 94254087..00000000 --- a/src/service/log/LogService.h +++ /dev/null @@ -1,52 +0,0 @@ -#ifndef METAL_ENGINE_LOGSERVICE_H -#define METAL_ENGINE_LOGSERVICE_H - -#include -#include -#include -#include "../../common/AbstractRuntimeComponent.h" - -namespace Metal { - - enum class LogLevel { - Trace, - Debug, - Info, - Warn, - Error, - Fatal - }; - - struct LogEntry { - LogLevel level; - std::string message; - std::string timestamp; - }; - - class LogService : public AbstractRuntimeComponent { - public: - explicit LogService(); - - void log(LogLevel level, const std::string &message) const; - - [[nodiscard]] std::vector getEntriesSnapshot() const; - void clear(); - - static const char* getLevelName(LogLevel level); - static uint32_t getLevelColor(LogLevel level); - - private: - mutable std::vector entries; - mutable std::mutex logMutex; - }; - -} - -#define LOG_TRACE(msg) CTX.logService.log(Metal::LogLevel::Trace, msg) -#define LOG_DEBUG(msg) CTX.logService.log(Metal::LogLevel::Debug, msg) -#define LOG_INFO(msg) CTX.logService.log(Metal::LogLevel::Info, msg) -#define LOG_WARN(msg) CTX.logService.log(Metal::LogLevel::Warn, msg) -#define LOG_ERROR(msg) CTX.logService.log(Metal::LogLevel::Error, msg) -#define LOG_FATAL(msg) CTX.logService.log(Metal::LogLevel::Fatal, msg) - -#endif diff --git a/src/service/material/MaterialService.h b/src/service/material/MaterialService.h deleted file mode 100644 index fce5458e..00000000 --- a/src/service/material/MaterialService.h +++ /dev/null @@ -1,14 +0,0 @@ -#ifndef MATERIALSERVICE_H -#define MATERIALSERVICE_H - -namespace Metal { - struct PrimitiveComponent; - struct MeshMetadata; - - class MaterialService final { - public: - void load(MeshMetadata &data, PrimitiveComponent &component); - }; -} // Metal - -#endif //MATERIALSERVICE_H diff --git a/src/service/mesh/MeshService.h b/src/service/mesh/MeshService.h deleted file mode 100644 index 68535a20..00000000 --- a/src/service/mesh/MeshService.h +++ /dev/null @@ -1,25 +0,0 @@ -#ifndef MESHSERVICE_H -#define MESHSERVICE_H -#include "../../service/abstract/AbstractResourceService.h" -#include "MeshInstance.h" -#include "../../enum/engine-definitions.h" - -namespace Metal { - struct MeshData; - struct MeshInstance; - struct EntityAssetData; - - class MeshService final : public AbstractResourceService { - public: - MeshInstance *create(const std::string &id); - - MeshInstance *stream(const std::string &id); - - MeshData *loadMeshData(const std::string &id) const; - - void disposeResource(MeshInstance *resource) override; - - }; -} // Metal - -#endif //MESHSERVICE_H diff --git a/src/service/mesh/SceneImporterService.h b/src/service/mesh/SceneImporterService.h deleted file mode 100644 index 39b6d495..00000000 --- a/src/service/mesh/SceneImporterService.h +++ /dev/null @@ -1,38 +0,0 @@ -#ifndef MESHIMPORTER_H -#define MESHIMPORTER_H - -#include - -#include "../abstract/AbstractImporter.h" -#include -#include - -namespace Metal { - struct MeshId; - struct MaterialData; - struct MeshData; - struct SceneData; - - class SceneImporterService final : public AbstractImporter { - static void ProcessNode(SceneData &scene, const aiScene *aiScene, const aiNode *node, - const std::string &targetDir, const std::string &rootDirectory, - const std::unordered_map &meshMap, - const std::stop_token &stopToken); - - static void ProcessMeshes(SceneData &scene, const aiScene *aiScene, const aiNode *node, - const std::string &targetDir, const std::string &rootDirectory, - const std::unordered_map &meshMap, - const std::stop_token &stopToken); - - static void ProcessLights(SceneData &scene, const aiScene *aiScene); - - public: - std::string importData(const std::string &targetDir, const std::string &pathToFile, - const std::shared_ptr &settings, - const std::stop_token &stopToken) override; - - std::vector getSupportedTypes() override; - }; -} // Metal - -#endif //MESHIMPORTER_H diff --git a/src/service/picking/PickingService.h b/src/service/picking/PickingService.h deleted file mode 100644 index d86177d0..00000000 --- a/src/service/picking/PickingService.h +++ /dev/null @@ -1,16 +0,0 @@ -#ifndef PICKINGSERVICE_H -#define PICKINGSERVICE_H - -#include "../abstract/AbstractResourceService.h" -#include "../../enum/engine-definitions.h" -#include - -namespace Metal { - struct TextureInstance; - class PickingService final : public AbstractRuntimeComponent { - public: - [[nodiscard]] std::optional pickEntityFromGBuffer(TextureInstance *attachment, uint32_t pixelX, uint32_t pixelY) const; - }; -} // Metal - -#endif // PICKINGSERVICE_H diff --git a/src/service/selection/SelectionService.cpp b/src/service/selection/SelectionService.cpp deleted file mode 100644 index 23d4c8ff..00000000 --- a/src/service/selection/SelectionService.cpp +++ /dev/null @@ -1,52 +0,0 @@ -#include "SelectionService.h" - -#include "../../context/ApplicationContext.h" -#include "../../repository/world/components/TransformComponent.h" - -namespace Metal { - void SelectionService::addSelected(entt::entity entity) const { - auto &editorRepository = CTX.editorRepository; - if (editorRepository.selected.empty() || entity == EMPTY_ENTITY) { - editorRepository.mainSelection = entity; - if (editorRepository.mainSelection != EMPTY_ENTITY) { - updatePrimitiveSelected(); - } - } - if (entity != EMPTY_ENTITY) { - editorRepository.selected.insert({entity, true}); - } - } - - void SelectionService::clearSelection() const { - auto &editorRepository = CTX.editorRepository; - editorRepository.selected.clear(); - editorRepository.mainSelection = EMPTY_ENTITY; - editorRepository.primitiveSelected = nullptr; - } - - void SelectionService::addAllSelected(const std::vector &all) const { - auto &editorRepository = CTX.editorRepository; - editorRepository.selected.clear(); - const entt::entity first = all.size() > 0 ? all[0] : EMPTY_ENTITY; - editorRepository.mainSelection = first; - updatePrimitiveSelected(); - for (auto a: all) { - editorRepository.selected.insert({a, true}); - } - } - - void SelectionService::updatePrimitiveSelected() const { - auto &editorRepository = CTX.editorRepository; - auto &repo = CTX.worldRepository; - const auto entityId = editorRepository.mainSelection; - - if (entityId == EMPTY_ENTITY || !repo.registry.valid(entityId)) { - return; - } - - if (repo.registry.all_of(entityId)) { - editorRepository.primitiveSelected = &repo.registry.get(entityId); - } - } - -} // Metal diff --git a/src/service/selection/SelectionService.h b/src/service/selection/SelectionService.h deleted file mode 100644 index 60cb3dd8..00000000 --- a/src/service/selection/SelectionService.h +++ /dev/null @@ -1,24 +0,0 @@ -#ifndef SELECTIONSERVICE_H -#define SELECTIONSERVICE_H -#include - -#include "../../common/AbstractRuntimeComponent.h" -#include "../../enum/engine-definitions.h" - -namespace Metal { - struct WorldRepository; - struct EditorRepository; - - class SelectionService final : public AbstractRuntimeComponent { - public: - void addSelected(entt::entity entity) const; - - void clearSelection() const; - - void addAllSelected(const std::vector &all) const; - - void updatePrimitiveSelected() const; - }; -} // Metal - -#endif //SELECTIONSERVICE_H diff --git a/src/service/transform/TransformService.h b/src/service/transform/TransformService.h deleted file mode 100644 index 37ea9b5a..00000000 --- a/src/service/transform/TransformService.h +++ /dev/null @@ -1,27 +0,0 @@ -#ifndef TRANSFORMSERVICE_H -#define TRANSFORMSERVICE_H -#include -#include -#include - -#include "../../enum/engine-definitions.h" -#include "../../common/AbstractRuntimeComponent.h" - -namespace Metal { - struct TransformComponent; - - class TransformService final : AbstractRuntimeComponent { - glm::vec3 distanceAux{}; - glm::mat4x4 auxMat4{}; - glm::vec3 translation{}; - glm::mat4x4 auxMat42{}; - - public: - - void onSync() override; - - void transform(TransformComponent *st, const TransformComponent *parentTransform); - }; -} // Metal - -#endif diff --git a/src/service/volumes/VolumeService.cpp b/src/service/volumes/VolumeService.cpp deleted file mode 100644 index 5c03305b..00000000 --- a/src/service/volumes/VolumeService.cpp +++ /dev/null @@ -1,36 +0,0 @@ -#include "VolumeService.h" -#include "../../context/ApplicationContext.h" -#include "../../repository/world/components/VolumeComponent.h" -#include "../buffer/BufferInstance.h" -#include "../../enum/EngineResourceIDs.h" - -namespace Metal { - void VolumeService::registerVolumes() { - auto view = CTX.worldRepository.registry.view(); - for (auto [entityId, l, t]: view.each()) { - if (CTX.worldRepository.hiddenEntities.contains(entityId)) { - continue; - } - - auto &translation = t.translation; - - items.push_back(VolumeData( - glm::vec4(l.albedo, l.samples), - translation, - t.scale, - glm::vec3(l.density, l.scatteringAlbedo, l.g) - )); - } - } - - // TODO - ADD EVENT SYSTEM THAT TRIGGERS THIS UPDATE - void VolumeService::onSync() { - items.clear(); - - registerVolumes(); - - if (!items.empty()) { - CTX.engineContext.currentFrame->getResourceAs(RID_VOLUMES_BUFFER)->update(items.data()); - } - } -} // Metal diff --git a/src/service/volumes/VolumeService.h b/src/service/volumes/VolumeService.h deleted file mode 100644 index c2377b45..00000000 --- a/src/service/volumes/VolumeService.h +++ /dev/null @@ -1,24 +0,0 @@ -#ifndef VOLUME_SERVICE_H -#define VOLUME_SERVICE_H -#include - -#include "../../common/AbstractRuntimeComponent.h" -#include "../../dto/buffers/VolumeData.h" - -namespace Metal { - - class VolumeService final : public AbstractRuntimeComponent { - std::vector items{}; - - void registerVolumes(); - public: - - void onSync() override; - - unsigned int getCount() const { - return items.size(); - } - }; -} // Metal - -#endif //LIGHTSSERVICE_H diff --git a/src/util/ShaderUtil.h b/src/util/ShaderUtil.h deleted file mode 100644 index ad777b65..00000000 --- a/src/util/ShaderUtil.h +++ /dev/null @@ -1,27 +0,0 @@ -#ifndef SHADERSERVICE_H -#define SHADERSERVICE_H -#include -#include -#include - -#include "../service/pipeline/ShaderModule.h" - -namespace Metal { - class ShaderUtil final { - static void CheckShaderCompilation(glslang_shader_t *shader); - - static bool CompileShader(glslang_stage_t stage, const char *pShaderCode, - ShaderModule *shaderModule); - - static glslang_stage_t ShaderStageFromFilename(const char *pFilename); - - static std::string ProcessIncludes(const std::string &input); - - static std::string ProcessShader(const std::string &file); - - public: - static VkShaderModule CreateShaderModule(const std::string &pFilename); - }; -} // Metal - -#endif diff --git a/tests/ApplicationContextTest.cpp b/tests/ApplicationContextTest.cpp new file mode 100644 index 00000000..699f0f04 --- /dev/null +++ b/tests/ApplicationContextTest.cpp @@ -0,0 +1,39 @@ +#include +#include +#include "../src/ApplicationContext.h" +#include "../src/common/IContextMember.h" +#include + +using namespace Metal; + +class MockContextMember : public IContextMember { +public: + int value = 0; +}; + +TEST(ApplicationContextTest, RegisterAndGetSingleton) { + ApplicationContext ctx(true); + auto member = std::make_shared(); + member->value = 42; + + ctx.registerSingleton(member); + + MockContextMember& retrieved = ctx.getSingleton(); + EXPECT_EQ(retrieved.value, 42); +} + +TEST(ApplicationContextTest, GetSingletonByName) { + ApplicationContext ctx(true); + auto member = std::make_shared(); + + ctx.registerSingleton(member); + + void* ptr = ctx.getSingletonByName("MockContextMember"); + EXPECT_NE(ptr, nullptr); + EXPECT_EQ(static_cast(ptr), member.get()); +} + +TEST(ApplicationContextTest, ThrowsWhenSingletonNotFound) { + ApplicationContext ctx(true); + EXPECT_THROW(ctx.getSingleton(), std::runtime_error); +} diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt new file mode 100644 index 00000000..a80f315c --- /dev/null +++ b/tests/CMakeLists.txt @@ -0,0 +1,21 @@ +find_package(GTest REQUIRED) + +add_executable(metal_engine_tests + ApplicationContextTest.cpp + WorldRepositoryTest.cpp +) + +target_link_libraries(metal_engine_tests + PRIVATE + metal_engine_lib + GTest::gtest_main +) +add_dependencies(metal_engine_tests copy_resources) + +add_custom_command(TARGET metal_engine_tests POST_BUILD + COMMAND ${CMAKE_COMMAND} -E copy_directory + "${CMAKE_BINARY_DIR}/resources" + "$/resources") + +include(GoogleTest) +gtest_discover_tests(metal_engine_tests) diff --git a/tests/WorldRepositoryTest.cpp b/tests/WorldRepositoryTest.cpp new file mode 100644 index 00000000..efc8a4b9 --- /dev/null +++ b/tests/WorldRepositoryTest.cpp @@ -0,0 +1,64 @@ +#include +#include +#include "../src/ApplicationContext.h" +#include "../src/engine/repository/WorldRepository.h" +#include "../src/engine/dto/MetadataComponent.h" +#include "../src/engine/service/RayTracingService.h" +#include "../src/core/DirectoryService.h" +#include "../src/engine/EngineContext.h" +#include + +using namespace Metal; + +class WorldRepositoryTest : public ::testing::Test { +protected: + std::unique_ptr context; + WorldRepository* repo; + + void SetUp() override { + context = std::make_unique(true); + + auto worldRepo = std::make_shared(); + auto rayTracingService = std::make_shared(); + auto directoryService = std::make_shared(); + auto engineContext = std::make_shared(); + + context->registerSingleton(worldRepo); + context->registerSingleton(rayTracingService); + context->registerSingleton(directoryService); + context->registerSingleton(engineContext); + + context->injectDependencies(worldRepo.get()); + + repo = worldRepo.get(); + } +}; + +TEST_F(WorldRepositoryTest, CreateEntity) { + entt::entity entity = repo->createEntity(); + EXPECT_NE(entity, static_cast(entt::null)); + EXPECT_TRUE(repo->registry.valid(entity)); +} + +TEST_F(WorldRepositoryTest, GetEntityMetadata) { + entt::entity entity = repo->createEntity(); + MetadataComponent* metadata = repo->getEntity(entity); + EXPECT_NE(metadata, nullptr); +} + +TEST_F(WorldRepositoryTest, DeleteEntity) { + entt::entity entity = repo->createEntity(); + repo->deleteEntities({entity}); + EXPECT_FALSE(repo->registry.valid(entity)); +} + +TEST_F(WorldRepositoryTest, ChangeVisibility) { + entt::entity entity = repo->createEntity(); + + repo->changeVisibility(entity, false); + EXPECT_EQ(repo->hiddenEntities.count(entity), 1); + EXPECT_TRUE(repo->hiddenEntities.at(entity)); + + repo->changeVisibility(entity, true); + EXPECT_EQ(repo->hiddenEntities.count(entity), 0); +} diff --git a/vcpkg.json b/vcpkg.json index e5abb844..5b0cea8f 100644 --- a/vcpkg.json +++ b/vcpkg.json @@ -18,9 +18,6 @@ }, { "name" : "glm", "version>=" : "1.0.1#3" - }, { - "name" : "spdlog", - "version>=" : "1.15.0#1" }, { "name" : "spirv-tools", "version>=" : "1.3.296.0" @@ -51,5 +48,8 @@ }, { "name" : "entt", "version>=" : "3.16.0" - } ] + }, { + "name" : "gtest", + "version>=" : "1.15.2" + }] } \ No newline at end of file