From 9883690c7ce1b16522cb3d45231f4b489cd6baca Mon Sep 17 00:00:00 2001 From: SpinnerX Date: Sat, 10 Jan 2026 14:22:52 -0800 Subject: [PATCH 01/68] WIP migrating to cpp modules --- CMakeLists.txt | 128 ++++++++++++++--- atlas-modules/atlas.cppm | 6 + atlas-modules/core/api.cppm | 12 ++ atlas-modules/core/application.cppm | 185 +++++++++++++++++++++++++ atlas-modules/core/common.cppm | 77 +++++++++++ atlas-modules/core/core.cppm | 9 ++ atlas-modules/core/logger.cppm | 206 ++++++++++++++++++++++++++++ atlas-modules/core/main.cpp | 16 +++ atlas-modules/core/window.cppm | 121 ++++++++++++++++ conanfile.py | 11 +- 10 files changed, 742 insertions(+), 29 deletions(-) create mode 100644 atlas-modules/atlas.cppm create mode 100644 atlas-modules/core/api.cppm create mode 100644 atlas-modules/core/application.cppm create mode 100644 atlas-modules/core/common.cppm create mode 100644 atlas-modules/core/core.cppm create mode 100644 atlas-modules/core/logger.cppm create mode 100644 atlas-modules/core/main.cpp create mode 100644 atlas-modules/core/window.cppm diff --git a/CMakeLists.txt b/CMakeLists.txt index 7d56cfc1..b86afa08 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,5 +1,10 @@ -cmake_minimum_required(VERSION 3.27) -project(atlas C CXX) +cmake_minimum_required(VERSION 4.0) + +# Generate compile commands for anyone using our libraries. +set(CMAKE_EXPORT_COMPILE_COMMANDS ON) +set(CMAKE_COLOR_DIAGNOSTICS ON) + +project(atlas LANGUAGES CXX) set(ENGINE_INCLUDE_DIR ${CMAKE_CURRENT_LIST_DIR}/atlas) # TODO: Remove this once shaderc in the github CI is fixed @@ -25,32 +30,111 @@ else() message(STATUS "ENABLE_TESTS_ONLY macro not enabled") endif() -build_core_library( - DIRECTORIES src +# build_core_library( +# DIRECTORIES src editor + +# ENABLE_TESTS ${ENABLE_TESTS_ONLY} + +# UNIT_TEST_SOURCES - ENABLE_TESTS ${ENABLE_TESTS_ONLY} +# tests/main.test.cpp +# tests/basic_add.test.cpp +# tests/entity_component_system.test.cpp +# tests/math.test.cpp +# tests/scene.test.cpp +# tests/jolt_type_conversion.test.cpp +# tests/jolt_engine.test.cpp - UNIT_TEST_SOURCES +# PACKAGES +# tinyobjloader +# ${SHADERC_PACKAGE} +# watcher +# vulkan-cpp` +# nfd - tests/main.test.cpp - tests/basic_add.test.cpp - tests/entity_component_system.test.cpp - tests/math.test.cpp - tests/scene.test.cpp - tests/jolt_type_conversion.test.cpp - tests/jolt_engine.test.cpp +# LINK_PACKAGES +# tinyobjloader::tinyobjloader +# ${SHADERC_LINK_PACKAGE} +# watcher::watcher +# vulkan-cpp +# nfd::nfd +# ) + +add_library(${PROJECT_NAME} STATIC) +add_subdirectory(editor_modules) + +set_packages( + ENABLE_TESTS OFF PACKAGES - tinyobjloader - ${SHADERC_PACKAGE} - watcher - vulkan-cpp + glfw3 + Vulkan + glm + spdlog + # imguidocking + # Jolt + # yaml-cpp + # stb + # flecs + + # tinyobjloader + # ${SHADERC_PACKAGE} + # watcher + # vulkan-cpp + # nfd LINK_PACKAGES - tinyobjloader::tinyobjloader - ${SHADERC_LINK_PACKAGE} - watcher::watcher - vulkan-cpp::vulkan-cpp + glfw + Vulkan::Vulkan + glm::glm + spdlog::spdlog + # imguidocking::imguidocking + + # Jolt::Jolt + # yaml-cpp + # stb::stb + # flecs::flecs_static + # tinyobjloader::tinyobjloader + # ${SHADERC_LINK_PACKAGE} + # watcher::watcher + # vulkan-cpp + # nfd::nfd ) -install(TARGETS ${PROJECT_NAME}) +target_sources(${PROJECT_NAME} PUBLIC + FILE_SET CXX_MODULES + TYPE CXX_MODULES + FILES + atlas-modules/atlas.cppm + atlas-modules/core/api.cppm + atlas-modules/core/common.cppm + atlas-modules/core/core.cppm + atlas-modules/core/application.cppm + atlas-modules/core/window.cppm + atlas-modules/core/logger.cppm +) + +# target_sources(${PROJECT_NAME} PUBLIC +# FILE_SET CXX_MODULES +# TYPE CXX_MODULES +# PRIVATE atlas-modules/core/main.cpp +# ) + +target_compile_features(${PROJECT_NAME} PUBLIC cxx_std_23) + +# install(TARGETS ${PROJECT_NAME}) +install( + TARGETS ${PROJECT_NAME} + EXPORT atlas_targets + FILE_SET CXX_MODULES DESTINATION "." + LIBRARY DESTINATION "lib" + ARCHIVE DESTINATION "lib" + CXX_MODULES_BMI DESTINATION "bmi" +) + +install( + EXPORT atlas_targets + FILE "atlas-config.cmake" + DESTINATION "lib/cmake" + CXX_MODULES_DIRECTORY "cxx-modules" +) diff --git a/atlas-modules/atlas.cppm b/atlas-modules/atlas.cppm new file mode 100644 index 00000000..12344c01 --- /dev/null +++ b/atlas-modules/atlas.cppm @@ -0,0 +1,6 @@ +export module atlas; + +export import core; + +export namespace atlas { +}; \ No newline at end of file diff --git a/atlas-modules/core/api.cppm b/atlas-modules/core/api.cppm new file mode 100644 index 00000000..294a03b4 --- /dev/null +++ b/atlas-modules/core/api.cppm @@ -0,0 +1,12 @@ +module; + +#include + +export module core:api; + + +export namespace atlas { + enum class graphics_api : uint8_t { + vulkan, dx11, fx12, undefined + }; +}; \ No newline at end of file diff --git a/atlas-modules/core/application.cppm b/atlas-modules/core/application.cppm new file mode 100644 index 00000000..6c744083 --- /dev/null +++ b/atlas-modules/core/application.cppm @@ -0,0 +1,185 @@ +module; + +#include +#include +#include +#include +#include + +export module core:application; + +export import :common; +export import :api; +export import :window; + +export namespace atlas { + + + /** + * @brief application properties settings for the window + */ + struct application_settings { + std::string name = "Undefined"; + uint32_t width = 0; + uint32_t height = 0; + glm::vec4 background_color = { 1.f, 0.5f, 0.5f, 1.f }; + }; + + /** + * @brief represents a single application that gets created by the engine + * internally + * + * There is only ever going to be one application tied to the engine's + * runtime. As the application is given responsibilities of preloading, + * pre-initialization any sort of utilities required by the engine, and any + * form of post-cleanup when the user requests the application to close. + * + */ + class application { + public: + /** + * @brief constructs a new application + * @param p_settings is the specific application settings to configure + * how the application may be setup + */ + application(const application_settings& p_settings) { + std::println("application(const application_settings&) initialized!!!"); + + if(m_window == nullptr) { + std::println("m_window == nullptr!"); + } + + s_instance = this; + } + + ~application() { + destroy(); + } + + /** + * @return the delta time as a float for giving you the timestep every + * frame + */ + static float delta_time() { + // return s_instance->m_delta_time; + } + + /** + * TODO: Need to remove this as it is not needed here + * + * Originally was used to handle the fixed physics timestep, but that + * can be handled else where. + */ + static float physics_step() { + return 0.f; + } + + /** + * @brief Explicitly is used to execute the application's mainloop + */ + void execute() { + // execute + std::println("Executing game mainloop!!!"); + } + + /** + * @brief Performs any post cleanup when user requests the application + * to close + */ + void post_destroy() { + std::println("Executing post cleanup!!!"); + } + + /** + * @brief we only ever have one window + * + * This static function was a means to getting access to the window to + * perform any operations or request any data the window may have to + * provide + */ + // static window& get_window() { return *s_instance->m_window; } + + /* Retrieves the current selected graphics API */ + /** + * @return the currently specified API. + */ + static graphics_api current_api() { + return graphics_api::vulkan; + } + + /* Returns the currently selected swapchain */ + /** + * @brief gives you the current swapchain handle + * + * TODO: This is not actually needed, and should be removed + */ + VkSwapchainKHR get_current_swapchain() { + return nullptr; + } + + /** + * @brief destroys the application completely + * + * TODO: Not make this static because you should not allow for this to + * be a direct calls users can have access to + */ + static void destroy() { + } + + /** + * @brief gives you the current aspect ratio based on the dimensions of + * the window + * + * @return a float which is just a static_cast(width / height); + */ + static float aspect_ratio() { + return 0.f; + } + + /** + * @brief Gives you the current frame index which is used for the Vulkan + * renderer + * + * Provides information such as what is the current frame index to + * correcly index the commands that get submitted to the GPU for + * processing commands (tasks) + * + * @return uint32_t + */ + static uint32_t current_frame() { + return 0; + } + + /** + * @brief Intended to get the image size so when you use current_frame() + * to get thje frame index, that you are not making an attempt at + * accessing anything outside of the frame. + * + * @return uint32_t + */ + static uint32_t image_size() { + return 0; + } + + protected: + // [[nodiscard]] ref renderer_instance() const { + // return m_renderer; + // } + + private: + void set_current_api(graphics_api api) { + } + + private: + float m_delta_time = 0.f; + ref m_window; + // ref m_renderer = nullptr; + glm::mat4 m_proj_view; + uint32_t m_current_frame_index = -1; + // vk::imgui_context m_ui_context; + static application* s_instance; + }; +}; + + +atlas::application* atlas::application::s_instance = nullptr; \ No newline at end of file diff --git a/atlas-modules/core/common.cppm b/atlas-modules/core/common.cppm new file mode 100644 index 00000000..469bbef2 --- /dev/null +++ b/atlas-modules/core/common.cppm @@ -0,0 +1,77 @@ +module; + +#include +#include + +export module core:common; + + +export namespace atlas { + /** + * @brief alias to atlas::memory::strong_ptr + */ + // template + // using strong_ref = memory::strong_ptr; + + // /** + // * @brief construct strong_ptr through + // * atlas::memory::create_strong_ptr(...); + // * + // * @tparam ...Args is a template pack for packing in parameters + // * @tparam T is the type of object to construct strong_ptr with + // * @param p_allocator is a polymorphic allocator when creating strong_ptr's. + // * @param ...Args is an argument pack for packing to deduce the types that + // * is specified by object of type T + // */ + // template + // strong_ref create_strong_ref( + // std::pmr::polymorphic_allocator<> p_allocator, + // Args&&... args) { + // return memory::make_strong_ptr(p_allocator, + // std::forward(args)...); + // } + + /** + * @brief alias to memory::optional_ptr + */ + // template + // using optional_ref = memory::optional_ptr; + + /** + * @brief alias to std::shared_ptr + */ + template + using ref = std::shared_ptr; + + /** + * @brief construct std::make_shared(...); + * + * @tparam ...Args is a template pack for packing in parameters + * @tparam T is the type of object to construct strong_ptr with + * @param ...Args is an argument pack for packing to deduce the types that + * is specified by object of type T + */ + template + constexpr ref create_ref(Args&&... args) { + return std::make_shared(std::forward(args)...); + } + + /** + * @brief alias to std::unique_ptr + */ + template + using scope = std::unique_ptr; + + /** + * @brief construct std::make_unique(...); + * + * @tparam ...Args is a template pack for packing in parameters + * @tparam T is the type of object to construct strong_ptr with + * @param ...Args is an argument pack for packing to deduce the types that + * is specified by object of type T + */ + template + constexpr scope create_scope(Args&&... args) { + return std::make_unique(std::forward(args)...); + } +}; \ No newline at end of file diff --git a/atlas-modules/core/core.cppm b/atlas-modules/core/core.cppm new file mode 100644 index 00000000..05702be2 --- /dev/null +++ b/atlas-modules/core/core.cppm @@ -0,0 +1,9 @@ +export module core; + +export import :api; +export import :common; +export import :application; + + +export namespace atlas { +}; \ No newline at end of file diff --git a/atlas-modules/core/logger.cppm b/atlas-modules/core/logger.cppm new file mode 100644 index 00000000..382f6fdf --- /dev/null +++ b/atlas-modules/core/logger.cppm @@ -0,0 +1,206 @@ +module; + +#include +#include +#include +#include + +#include +#include + +export module core:logger; +export import :common; + +static std::string g_current_pattern_for_logs = "Undefined Pattern Specified"; + +export namespace atlas { + /** + * @brief logger for logging messages to stdout on the console + * + * Manages the logger instances and patterns for setting up with the loggers + * when writing logs + */ + class console_log_manager { + public: + /** + * @brief initializes the console_log_manager + * + * TODO: Revisit the logger and do some refactoring because the way this + * works should be changed, as I'd prob do this differently now. + */ + static void initialize_logger_manager(const std::string& pattern = "%^[%T] %n: %v%$") { + g_current_pattern_for_logs = pattern; + + //! @note Setting up logs for different log stdout's + //! @note Logs for p_tag is logs specific to the game. + // s_loggers.insert({ "engine3d", spdlog::stdout_color_mt("atlas") }); + // s_loggers.insert({ "physics", spdlog::stdout_color_mt("physics") }); + // s_loggers.insert({ "vulkan", spdlog::stdout_color_mt("vulkan") }); + // s_loggers.insert( + // { "assert", spdlog::stdout_color_mt("core assertion") }); + + // s_loggers["engine3d"]->set_pattern(pattern); + // s_loggers["engine3d"]->set_level(spdlog::level::trace); + + // s_loggers["physics"]->set_level(spdlog::level::trace); + // s_loggers["physics"]->set_pattern(pattern); + + // s_loggers["vulkan"]->set_level(spdlog::level::trace); + // s_loggers["vulkan"]->set_pattern(pattern); + + // s_loggers["assert"]->set_level(spdlog::level::trace); + // s_loggers["assert"]->set_pattern(pattern); + } + + /** + * @brief sets what the current logger to write to the console with + */ + static void set_current_logger(const std::string& p_tag = "Undefined g_Tag in console_logger") { + #ifndef ENABLE_TESTS_ONLY + //! @note Setting up logs for different log stdout's + //! @note Logs for p_tag is logs specific to the game + // s_loggers[p_tag] = spdlog::stdout_color_mt(p_tag); + // s_loggers[p_tag]->set_level(spdlog::level::trace); + // s_loggers[p_tag]->set_pattern(g_current_pattern_for_logs); + #endif + } + + /** + * @brief constructs a new spdlog::logger to write to the console + */ + static void create_new_logger(const std::string& p_tag = "Undefined Tag") { + #ifndef ENABLE_TESTS_ONLY + // s_loggers[p_tag] = spdlog::stdout_color_mt(p_tag); + // s_loggers[p_tag]->set_level(spdlog::level::trace); + // s_loggers[p_tag]->set_pattern(g_current_pattern_for_logs); + #endif + } + + /** + * @brief retrieves that specific logger if it has been constructed + * + * @return ref if found, otherwise return nullptr + * + * TODO: Should have this throw an exception rather then returning + * nullptr + */ + static std::shared_ptr get(const std::string& p_tag) { + return s_loggers[p_tag]; + } + + private: + // Using an unordered_map to specify through a string what logger to + // retrieve to log messages + static std::unordered_map> s_loggers; + }; +}; + +export { +//! @note Console Loggers (These are loggers that write specifically to the +//! console, terminal console) +//! @note TODO --- Specify that engine3d will have it's own console terminal +//! that these will be written to. +template +inline void +console_log_trace([[maybe_unused]] spdlog::format_string_t fmt, + [[maybe_unused]] T&&... args) { +#ifndef ENABLE_TESTS_ONLY + atlas::console_log_manager::get("engine3d") + ->trace(fmt, std::forward(args)...); +#endif +} + +template +inline void +console_log_warn([[maybe_unused]] spdlog::format_string_t fmt, + [[maybe_unused]] T&&... args) { +#ifndef ENABLE_TESTS_ONLY + atlas::console_log_manager::get("engine3d") + ->warn(fmt, std::forward(args)...); +#endif +} + +template +inline void +console_log_info([[maybe_unused]] spdlog::format_string_t fmt, + [[maybe_unused]] T&&... args) { +#ifndef ENABLE_TESTS_ONLY + atlas::console_log_manager::get("engine3d") + ->info(fmt, std::forward(args)...); +#endif +} + +template +inline void +console_log_error([[maybe_unused]] spdlog::format_string_t fmt, + [[maybe_unused]] T&&... args) { +#ifndef ENABLE_TESTS_ONLY + atlas::console_log_manager::get("engine3d") + ->error(fmt, std::forward(args)...); +#endif +} + +template +inline void +console_log_fatal([[maybe_unused]] spdlog::format_string_t fmt, + [[maybe_unused]] T&&... args) { +#ifndef ENABLE_TESTS_ONLY + atlas::console_log_manager::get("engine3d") + ->critical(fmt, std::forward(args)...); +#endif +} + +///////////////////////////////////////// +///////////////////////////////////////// +///////////////////////////////////////// +template +inline void +console_log_trace_tagged([[maybe_unused]] const std::string& p_tag, + [[maybe_unused]] spdlog::format_string_t fmt, + [[maybe_unused]] T&&... args) { +#ifndef ENABLE_TESTS_ONLY + atlas::console_log_manager::get(p_tag)->trace(fmt, + std::forward(args)...); +#endif +} + +template +inline void +console_log_info_tagged([[maybe_unused]] const std::string& p_tag, + [[maybe_unused]] spdlog::format_string_t fmt, + [[maybe_unused]] T&&... args) { +#ifndef ENABLE_TESTS_ONLY + atlas::console_log_manager::get(p_tag)->info(fmt, std::forward(args)...); +#endif +} + +template +inline void +console_log_warn_tagged([[maybe_unused]] const std::string& p_tag, + [[maybe_unused]] spdlog::format_string_t fmt, + [[maybe_unused]] T&&... args) { + atlas::console_log_manager::get(p_tag)->warn(fmt, std::forward(args)...); +} + +template +inline void +console_log_error_tagged([[maybe_unused]] const std::string& p_tag, + [[maybe_unused]] spdlog::format_string_t fmt, + [[maybe_unused]] T&&... args) { +#ifndef ENABLE_TESTS_ONLY + atlas::console_log_manager::get(p_tag)->error(fmt, + std::forward(args)...); +#endif +} + +template +inline void +console_log_fatal_tagged([[maybe_unused]] const std::string& p_tag, + [[maybe_unused]] spdlog::format_string_t fmt, + [[maybe_unused]] T&&... args) { +#ifndef ENABLE_TESTS_ONLY + atlas::console_log_manager::get(p_tag)->critical(fmt, + std::forward(args)...); +#endif +} +} \ No newline at end of file diff --git a/atlas-modules/core/main.cpp b/atlas-modules/core/main.cpp new file mode 100644 index 00000000..314cfbbc --- /dev/null +++ b/atlas-modules/core/main.cpp @@ -0,0 +1,16 @@ +import atlas; +#include +#include + +int main() { + auto app = atlas::initialize_application(); + + if(app == nullptr) { + std::println("Initialize App Failed!!!"); + } + else { + std::println("App Initialized Successful!!!"); + } + + return 0; +} \ No newline at end of file diff --git a/atlas-modules/core/window.cppm b/atlas-modules/core/window.cppm new file mode 100644 index 00000000..f59a9108 --- /dev/null +++ b/atlas-modules/core/window.cppm @@ -0,0 +1,121 @@ +module; + +#include +#include +#include + +export module core:window; + +export import :common; +export import :api; + +export namespace atlas { + struct window_params { + uint32_t width; + uint32_t height; + std::string name=""; + }; + + class window { + public: + virtual ~window() = default; + + /** + * @brief Returns the width dimension of the window + */ + [[nodiscard]] uint32_t width() const; + + /** + * @brief Returns the height dimension of the window + */ + [[nodiscard]] uint32_t height() const; + + /** + * @brief Checks if window is available to close + */ + [[nodiscard]] bool available() const; + + /** + * @brief Returns the aspect ratio of the current window + */ + [[nodiscard]] float aspect_ratio() const; + + /** + * @brief gives you the next presentable image to use and the index to + * retrieving that image + * + * @return uint32_t + */ + [[nodiscard]] uint32_t acquired_next_frame() { + return read_acquired_next_frame(); + } + + /** + * @brief Returns the window's currently selected swapchain + */ + // [[nodiscard]] vk::vk_swapchain current_swapchain() const { + // return window_swapchain(); + // } + + /** + * @brief retrieves the current command buffer using the current frame + * index to ensure we are processing commands to the right command + * buffer in our current frame + * + * @return command buffer to actively record commands to + */ + // ::vk::command_buffer active_command(uint32_t p_frame_index) { + // return current_active_command(p_frame_index); + // } + + /** + * @brief operator overload for treating atlas::window as a GLFWwindow + * handle + */ + operator GLFWwindow*() const { return native_window(); } + + /** + * @brief operator overload for treating atlas::window as a GLFWwindow + * handle + */ + operator GLFWwindow*() { return native_window(); } + + /** + * @brief Closing the window operation + */ + void close(); + + /** + * @brief does the presentation operation that is operated internally + * with the vulkan swapchain + * + * @param p_current_frame_idx is current frame index to currently + * process an image in the current frame + */ + void present(const uint32_t& p_current_frame_idx); + + protected: + // [[nodiscard]] virtual window_settings settings() const = 0; + [[nodiscard]] virtual GLFWwindow* native_window() const = 0; + [[nodiscard]] virtual uint32_t read_acquired_next_frame() = 0; + // [[nodiscard]] virtual vk::vk_swapchain window_swapchain() const = 0; + + // [[nodiscard]] virtual ::vk::command_buffer current_active_command(uint32_t p_frame_idx) = 0; + + virtual void presentation_process(const uint32_t& p_current_frame) = 0; + }; + + /** + * @brief constructs an atlas::window + * + * There should only ever be one window constructed throughout the entire + * application + * + * @param p_settings is the window settings to construct the window with + * + * @return shared_ptr + */ + ref create_window(const window_params& p_params, graphics_api p_api) { + return nullptr; + } +}; \ No newline at end of file diff --git a/conanfile.py b/conanfile.py index e3006948..36fcc636 100644 --- a/conanfile.py +++ b/conanfile.py @@ -22,15 +22,15 @@ class AtlasRecipe(ConanFile): def build_requirements(self): - self.tool_requires("make/4.4.1") self.tool_requires("cmake/4.1.1") + self.tool_requires("ninja/1.13.1") self.tool_requires("engine3d-cmake-utils/4.0") def requirements(self): self.requires("joltphysics/5.2.0") if self.options.enable_shaderc: self.requires("shaderc/2025.3") - self.requires("imguidocking/2.0") + self.requires("imguidocking/3.0") self.requires("flecs/4.0.4") self.requires("glfw/3.4") self.requires("spdlog/1.16.0") @@ -38,12 +38,11 @@ def requirements(self): self.requires("yaml-cpp/0.8.0") # Vulkan-related headers and includes packages - self.requires("vulkan-headers/1.3.290.0") - self.requires("vulkan-cpp/3.0") + self.requires("vulkan-cpp/4.0") self.requires("tinyobjloader/2.0.0-rc10") self.requires("stb/cci.20230920") - self.requires("nfd/1.0") + self.requires("nfd/2.0") self.requires("watcher/0.12.0") self.requires("boost-ext-ut/2.3.1") @@ -51,8 +50,6 @@ def export_sources(self): copy(self,"CMakeLists.txt", self.recipe_folder, self.export_sources_folder) copy(self,"src/CMakeLists.txt", self.recipe_folder, self.export_sources_folder) copy(self,"*.hpp", self.recipe_folder, self.export_sources_folder) - copy(self,"*.h", self.recipe_folder, self.export_sources_folder) - copy(self,"*.h", self.recipe_folder, self.export_sources_folder) copy(self,"*.cpp", self.recipe_folder, self.export_sources_folder) copy(self, "shader_ubo_tutorial", self.recipe_folder, self.export_sources_folder) From 4e54a9aa8626d551e017d14f9deb118206c76dab Mon Sep 17 00:00:00 2001 From: SpinnerX Date: Sat, 10 Jan 2026 14:45:56 -0800 Subject: [PATCH 02/68] WIP modules migration and re-adding logger --- CMakeLists.txt | 46 ++++++++++++++-------------- atlas-modules/core/core.cppm | 1 + atlas-modules/core/logger.cppm | 55 +++++++++++++++++----------------- 3 files changed, 52 insertions(+), 50 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index b86afa08..dbf4226f 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -71,34 +71,34 @@ set_packages( Vulkan glm spdlog - # imguidocking - # Jolt - # yaml-cpp - # stb - # flecs - - # tinyobjloader - # ${SHADERC_PACKAGE} - # watcher - # vulkan-cpp - # nfd + imguidocking + Jolt + yaml-cpp + stb + flecs + + tinyobjloader + ${SHADERC_PACKAGE} + watcher + vulkan-cpp + nfd LINK_PACKAGES glfw Vulkan::Vulkan glm::glm spdlog::spdlog - # imguidocking::imguidocking - - # Jolt::Jolt - # yaml-cpp - # stb::stb - # flecs::flecs_static - # tinyobjloader::tinyobjloader - # ${SHADERC_LINK_PACKAGE} - # watcher::watcher - # vulkan-cpp - # nfd::nfd + imguidocking::imguidocking + + Jolt::Jolt + yaml-cpp + stb::stb + flecs::flecs_static + tinyobjloader::tinyobjloader + ${SHADERC_LINK_PACKAGE} + watcher::watcher + vulkan-cpp + nfd::nfd ) target_sources(${PROJECT_NAME} PUBLIC @@ -109,9 +109,9 @@ target_sources(${PROJECT_NAME} PUBLIC atlas-modules/core/api.cppm atlas-modules/core/common.cppm atlas-modules/core/core.cppm + atlas-modules/core/logger.cppm atlas-modules/core/application.cppm atlas-modules/core/window.cppm - atlas-modules/core/logger.cppm ) # target_sources(${PROJECT_NAME} PUBLIC diff --git a/atlas-modules/core/core.cppm b/atlas-modules/core/core.cppm index 05702be2..3dc5444e 100644 --- a/atlas-modules/core/core.cppm +++ b/atlas-modules/core/core.cppm @@ -3,6 +3,7 @@ export module core; export import :api; export import :common; export import :application; +export import :logger; export namespace atlas { diff --git a/atlas-modules/core/logger.cppm b/atlas-modules/core/logger.cppm index 382f6fdf..1a3425cb 100644 --- a/atlas-modules/core/logger.cppm +++ b/atlas-modules/core/logger.cppm @@ -6,6 +6,7 @@ module; #include #include +#include #include export module core:logger; @@ -28,28 +29,28 @@ export namespace atlas { * TODO: Revisit the logger and do some refactoring because the way this * works should be changed, as I'd prob do this differently now. */ - static void initialize_logger_manager(const std::string& pattern = "%^[%T] %n: %v%$") { + static void initialize_logger_manager(const std::string& pattern = "%^[%n] [%T]: %v%$") { g_current_pattern_for_logs = pattern; //! @note Setting up logs for different log stdout's //! @note Logs for p_tag is logs specific to the game. - // s_loggers.insert({ "engine3d", spdlog::stdout_color_mt("atlas") }); - // s_loggers.insert({ "physics", spdlog::stdout_color_mt("physics") }); - // s_loggers.insert({ "vulkan", spdlog::stdout_color_mt("vulkan") }); - // s_loggers.insert( - // { "assert", spdlog::stdout_color_mt("core assertion") }); + s_loggers.insert({ "atlas", spdlog::stdout_color_mt("atlas") }); + s_loggers.insert({ "physics", spdlog::stdout_color_mt("physics") }); + s_loggers.insert({ "vulkan", spdlog::stdout_color_mt("vulkan") }); + s_loggers.insert( + { "assert", spdlog::stdout_color_mt("core assertion") }); - // s_loggers["engine3d"]->set_pattern(pattern); - // s_loggers["engine3d"]->set_level(spdlog::level::trace); + s_loggers["atlas"]->set_pattern(pattern); + s_loggers["atlas"]->set_level(spdlog::level::trace); - // s_loggers["physics"]->set_level(spdlog::level::trace); - // s_loggers["physics"]->set_pattern(pattern); + s_loggers["physics"]->set_level(spdlog::level::trace); + s_loggers["physics"]->set_pattern(pattern); - // s_loggers["vulkan"]->set_level(spdlog::level::trace); - // s_loggers["vulkan"]->set_pattern(pattern); + s_loggers["vulkan"]->set_level(spdlog::level::trace); + s_loggers["vulkan"]->set_pattern(pattern); - // s_loggers["assert"]->set_level(spdlog::level::trace); - // s_loggers["assert"]->set_pattern(pattern); + s_loggers["assert"]->set_level(spdlog::level::trace); + s_loggers["assert"]->set_pattern(pattern); } /** @@ -59,9 +60,9 @@ export namespace atlas { #ifndef ENABLE_TESTS_ONLY //! @note Setting up logs for different log stdout's //! @note Logs for p_tag is logs specific to the game - // s_loggers[p_tag] = spdlog::stdout_color_mt(p_tag); - // s_loggers[p_tag]->set_level(spdlog::level::trace); - // s_loggers[p_tag]->set_pattern(g_current_pattern_for_logs); + s_loggers[p_tag] = spdlog::stdout_color_mt(p_tag); + s_loggers[p_tag]->set_level(spdlog::level::trace); + s_loggers[p_tag]->set_pattern(g_current_pattern_for_logs); #endif } @@ -70,9 +71,9 @@ export namespace atlas { */ static void create_new_logger(const std::string& p_tag = "Undefined Tag") { #ifndef ENABLE_TESTS_ONLY - // s_loggers[p_tag] = spdlog::stdout_color_mt(p_tag); - // s_loggers[p_tag]->set_level(spdlog::level::trace); - // s_loggers[p_tag]->set_pattern(g_current_pattern_for_logs); + s_loggers[p_tag] = spdlog::stdout_color_mt(p_tag); + s_loggers[p_tag]->set_level(spdlog::level::trace); + s_loggers[p_tag]->set_pattern(g_current_pattern_for_logs); #endif } @@ -93,19 +94,19 @@ export namespace atlas { // retrieve to log messages static std::unordered_map> s_loggers; }; + + std::unordered_map> console_log_manager::s_loggers; }; export { //! @note Console Loggers (These are loggers that write specifically to the //! console, terminal console) -//! @note TODO --- Specify that engine3d will have it's own console terminal -//! that these will be written to. template inline void console_log_trace([[maybe_unused]] spdlog::format_string_t fmt, [[maybe_unused]] T&&... args) { #ifndef ENABLE_TESTS_ONLY - atlas::console_log_manager::get("engine3d") + atlas::console_log_manager::get("atlas") ->trace(fmt, std::forward(args)...); #endif } @@ -115,7 +116,7 @@ inline void console_log_warn([[maybe_unused]] spdlog::format_string_t fmt, [[maybe_unused]] T&&... args) { #ifndef ENABLE_TESTS_ONLY - atlas::console_log_manager::get("engine3d") + atlas::console_log_manager::get("atlas") ->warn(fmt, std::forward(args)...); #endif } @@ -125,7 +126,7 @@ inline void console_log_info([[maybe_unused]] spdlog::format_string_t fmt, [[maybe_unused]] T&&... args) { #ifndef ENABLE_TESTS_ONLY - atlas::console_log_manager::get("engine3d") + atlas::console_log_manager::get("atlas") ->info(fmt, std::forward(args)...); #endif } @@ -135,7 +136,7 @@ inline void console_log_error([[maybe_unused]] spdlog::format_string_t fmt, [[maybe_unused]] T&&... args) { #ifndef ENABLE_TESTS_ONLY - atlas::console_log_manager::get("engine3d") + atlas::console_log_manager::get("atlas") ->error(fmt, std::forward(args)...); #endif } @@ -145,7 +146,7 @@ inline void console_log_fatal([[maybe_unused]] spdlog::format_string_t fmt, [[maybe_unused]] T&&... args) { #ifndef ENABLE_TESTS_ONLY - atlas::console_log_manager::get("engine3d") + atlas::console_log_manager::get("atlas") ->critical(fmt, std::forward(args)...); #endif } From 50ec735fd3e754da8ea269cbe4630ffed5053e7b Mon Sep 17 00:00:00 2001 From: SpinnerX Date: Sun, 11 Jan 2026 14:55:45 -0800 Subject: [PATCH 03/68] WIP continuing modules relationships --- CMakeLists.txt | 5 + atlas-modules/atlas.cppm | 7 + atlas-modules/core/api.cppm | 2 +- atlas-modules/core/application.cppm | 13 +- atlas-modules/core/common.cppm | 2 +- atlas-modules/core/core.cppm | 6 +- atlas-modules/core/logger.cppm | 4 +- atlas-modules/core/window.cppm | 45 ++-- atlas-modules/drivers/drivers.cppm | 5 + .../drivers/vulkan/instance_context.cppm | 210 ++++++++++++++++++ atlas-modules/drivers/vulkan/utilities.cppm | 21 ++ atlas-modules/drivers/vulkan/vulkan.cppm | 5 + .../drivers/vulkan/window_context.cppm | 89 ++++++++ 13 files changed, 383 insertions(+), 31 deletions(-) create mode 100644 atlas-modules/drivers/drivers.cppm create mode 100644 atlas-modules/drivers/vulkan/instance_context.cppm create mode 100644 atlas-modules/drivers/vulkan/utilities.cppm create mode 100644 atlas-modules/drivers/vulkan/vulkan.cppm create mode 100644 atlas-modules/drivers/vulkan/window_context.cppm diff --git a/CMakeLists.txt b/CMakeLists.txt index dbf4226f..b170abb4 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -112,6 +112,11 @@ target_sources(${PROJECT_NAME} PUBLIC atlas-modules/core/logger.cppm atlas-modules/core/application.cppm atlas-modules/core/window.cppm + + atlas-modules/drivers/vulkan/vulkan.cppm + atlas-modules/drivers/vulkan/utilities.cppm + atlas-modules/drivers/vulkan/instance_context.cppm + atlas-modules/drivers/vulkan/window_context.cppm ) # target_sources(${PROJECT_NAME} PUBLIC diff --git a/atlas-modules/atlas.cppm b/atlas-modules/atlas.cppm index 12344c01..0862f9b4 100644 --- a/atlas-modules/atlas.cppm +++ b/atlas-modules/atlas.cppm @@ -1,6 +1,13 @@ export module atlas; export import core; +export import vulkan; + +export import atlas.logger; + +// atlas.subsystem_type_name - this is for anything that is globally needed throughout TheAtlasEngine,like loggers, utilities, etc. +// import :internal_stuff - is used for implementation-specific details such as (implementing API-agnostic implementation specific to subsystems) +// Example: Like API-agnostic renderer and API-agnostic physics system. export namespace atlas { }; \ No newline at end of file diff --git a/atlas-modules/core/api.cppm b/atlas-modules/core/api.cppm index 294a03b4..0b01700b 100644 --- a/atlas-modules/core/api.cppm +++ b/atlas-modules/core/api.cppm @@ -2,7 +2,7 @@ module; #include -export module core:api; +export module atlas.graphics_api; export namespace atlas { diff --git a/atlas-modules/core/application.cppm b/atlas-modules/core/application.cppm index 6c744083..a874e303 100644 --- a/atlas-modules/core/application.cppm +++ b/atlas-modules/core/application.cppm @@ -5,12 +5,13 @@ module; #include #include #include +#include export module core:application; -export import :common; -export import :api; -export import :window; +import atlas.common; +import atlas.graphics_api; +import atlas.window; export namespace atlas { @@ -49,6 +50,8 @@ export namespace atlas { std::println("m_window == nullptr!"); } + // m_instance_handle_test = std::make_optional(); + s_instance = this; } @@ -61,7 +64,7 @@ export namespace atlas { * frame */ static float delta_time() { - // return s_instance->m_delta_time; + return s_instance->m_delta_time; } /** @@ -173,6 +176,8 @@ export namespace atlas { private: float m_delta_time = 0.f; ref m_window; + // vulkan::instance_context m_instance_handle_test; + // std::optional m_instance_handle_test; // ref m_renderer = nullptr; glm::mat4 m_proj_view; uint32_t m_current_frame_index = -1; diff --git a/atlas-modules/core/common.cppm b/atlas-modules/core/common.cppm index 469bbef2..d4a18e84 100644 --- a/atlas-modules/core/common.cppm +++ b/atlas-modules/core/common.cppm @@ -3,7 +3,7 @@ module; #include #include -export module core:common; +export module atlas.common; export namespace atlas { diff --git a/atlas-modules/core/core.cppm b/atlas-modules/core/core.cppm index 3dc5444e..dfbbb91b 100644 --- a/atlas-modules/core/core.cppm +++ b/atlas-modules/core/core.cppm @@ -1,10 +1,8 @@ export module core; -export import :api; -export import :common; +// export import :common; export import :application; -export import :logger; - +// export import :logger; export namespace atlas { }; \ No newline at end of file diff --git a/atlas-modules/core/logger.cppm b/atlas-modules/core/logger.cppm index 1a3425cb..55238cde 100644 --- a/atlas-modules/core/logger.cppm +++ b/atlas-modules/core/logger.cppm @@ -9,8 +9,8 @@ module; #include #include -export module core:logger; -export import :common; +export module atlas.logger; +export import atlas.common; static std::string g_current_pattern_for_logs = "Undefined Pattern Specified"; diff --git a/atlas-modules/core/window.cppm b/atlas-modules/core/window.cppm index f59a9108..632b331c 100644 --- a/atlas-modules/core/window.cppm +++ b/atlas-modules/core/window.cppm @@ -4,10 +4,12 @@ module; #include #include -export module core:window; +export module atlas.window; + +// export import :common; +import atlas.common; +import atlas.graphics_api; -export import :common; -export import :api; export namespace atlas { struct window_params { @@ -20,25 +22,23 @@ export namespace atlas { public: virtual ~window() = default; - /** - * @brief Returns the width dimension of the window - */ - [[nodiscard]] uint32_t width() const; - - /** - * @brief Returns the height dimension of the window - */ - [[nodiscard]] uint32_t height() const; + [[nodiscard]] window_params data() const { + return get_params(); + } /** * @brief Checks if window is available to close */ - [[nodiscard]] bool available() const; + [[nodiscard]] bool available() const { + return !glfwWindowShouldClose(native_window()); + } /** * @brief Returns the aspect ratio of the current window */ - [[nodiscard]] float aspect_ratio() const; + // [[nodiscard]] float aspect_ratio() const { + // (float)get_params().width / (float)get_params().height; + // } /** * @brief gives you the next presentable image to use and the index to @@ -83,7 +83,9 @@ export namespace atlas { /** * @brief Closing the window operation */ - void close(); + void close() { + glfwSetWindowShouldClose(native_window(), true); + } /** * @brief does the presentation operation that is operated internally @@ -95,7 +97,7 @@ export namespace atlas { void present(const uint32_t& p_current_frame_idx); protected: - // [[nodiscard]] virtual window_settings settings() const = 0; + [[nodiscard]] virtual window_params get_params() const = 0; [[nodiscard]] virtual GLFWwindow* native_window() const = 0; [[nodiscard]] virtual uint32_t read_acquired_next_frame() = 0; // [[nodiscard]] virtual vk::vk_swapchain window_swapchain() const = 0; @@ -115,7 +117,12 @@ export namespace atlas { * * @return shared_ptr */ - ref create_window(const window_params& p_params, graphics_api p_api) { - return nullptr; - } + // ref create_window(const window_params& p_params, graphics_api p_api) { + // switch(p_api) { + // case graphics_api::vulkan: + // return nullptr; + // default: + // return nullptr; + // } + // } }; \ No newline at end of file diff --git a/atlas-modules/drivers/drivers.cppm b/atlas-modules/drivers/drivers.cppm new file mode 100644 index 00000000..91123ed9 --- /dev/null +++ b/atlas-modules/drivers/drivers.cppm @@ -0,0 +1,5 @@ +module; + +export module drivers; + +export namespace atlas {}; \ No newline at end of file diff --git a/atlas-modules/drivers/vulkan/instance_context.cppm b/atlas-modules/drivers/vulkan/instance_context.cppm new file mode 100644 index 00000000..6facd97b --- /dev/null +++ b/atlas-modules/drivers/vulkan/instance_context.cppm @@ -0,0 +1,210 @@ +module; + +#include +#include +#include +#include +#include + +export module vulkan:instance_context; + +import :utilities; + +import atlas.logger; + +namespace atlas::vulkan { + std::vector initialize_instance_extensions() { + std::vector extension_names; + + extension_names.emplace_back(VK_KHR_SURFACE_EXTENSION_NAME); + extension_names.emplace_back(VK_EXT_DEBUG_UTILS_EXTENSION_NAME); + + // An additional surface extension needs to be loaded. This extension is + // platform-specific so needs to be selected based on the platform the + // example is going to be deployed to. Preprocessor directives are used + // here to select the correct platform. +#ifdef VK_USE_PLATFORM_WIN32_KHR + extension_names.emplace_back(VK_KHR_WIN32_SURFACE_EXTENSION_NAME); +#endif +#ifdef VK_USE_PLATFORM_XLIB_KHR + extensionNames.emplace_back(VK_KHR_XLIB_SURFACE_EXTENSION_NAME); +#endif +#ifdef VK_USE_PLATFORM_XCB_KHR + extensionNames.emplace_back(VK_KHR_XCB_SURFACE_EXTENSION_NAME); +#endif +#ifdef VK_USE_PLATFORM_ANDROID_KHR + extensionNames.emplace_back(VK_KHR_ANDROID_SURFACE_EXTENSION_NAME); +#endif +#ifdef VK_USE_PLATFORM_WAYLAND_KHR + extensionNames.emplace_back(VK_KHR_WAYLAND_SURFACE_EXTENSION_NAME); +#endif +#ifdef VK_USE_PLATFORM_MACOS_MVK + extensionNames.emplace_back(VK_MVK_MACOS_SURFACE_EXTENSION_NAME); +#endif +#ifdef USE_PLATFORM_NULLWS + extensionNames.emplace_back(VK_KHR_DISPLAY_EXTENSION_NAME); +#endif + + return extension_names; + } + +#ifdef _DEBUG + const std::vector validation_layers = { + "VK_LAYER_KHRONOS_validation", + "VK_LAYER_KHRONOS_synchronization2" + }; + + static VKAPI_ATTR VkBool32 VKAPI_CALL debug_callback( + [[maybe_unused]] VkDebugUtilsMessageSeverityFlagBitsEXT + p_message_severity, + [[maybe_unused]] VkDebugUtilsMessageTypeFlagsEXT p_message_type, + const VkDebugUtilsMessengerCallbackDataEXT* p_callback_data, + [[maybe_unused]] void* p_user_data) { + console_log_trace("validation layer:\t\t{}", p_callback_data->pMessage); + return false; + } +#endif + + class instance_context { + public: + instance_context(const std::string& p_name) { + console_log_manager::create_new_logger(p_name); + VkApplicationInfo app_info = { + .sType = VK_STRUCTURE_TYPE_APPLICATION_INFO, + .pNext = nullptr, + .applicationVersion = 1, + .pEngineName = "TheAtlasEngine", + .engineVersion = 1, + .apiVersion = VK_API_VERSION_1_3, + }; + + VkInstanceCreateInfo create_info = { + .sType = VK_STRUCTURE_TYPE_INSTANCE_CREATE_INFO, + .pNext = nullptr, + .flags = 0, + .pApplicationInfo = &app_info + }; + + //! @note Setting up the required extensions for vulkan + std::vector extensions = initialize_instance_extensions(); + #if _DEBUG + extensions.push_back("VK_EXT_debug_utils"); + #endif + create_info.enabledExtensionCount = + static_cast(extensions.size()); + create_info.ppEnabledExtensionNames = extensions.data(); + #ifdef _DEBUG + // by default we enable validation layers used for debugging! + create_info.enabledLayerCount = + static_cast(validation_layers.size()); + create_info.ppEnabledLayerNames = validation_layers.data(); + + // printing out available validation layers + uint32_t layer_count; + std::vector available_validation_layers; + vkEnumerateInstanceLayerProperties(&layer_count, nullptr); + + available_validation_layers.resize(layer_count); + vkEnumerateInstanceLayerProperties(&layer_count, + available_validation_layers.data()); + + console_log_trace("================================================"); + console_log_trace("\tValidation Layers Available"); + console_log_trace("================================================"); + for (VkLayerProperties properties : available_validation_layers) { + console_log_trace("Validation Layer:\t\t{}", properties.layerName); + console_log_trace("Description\t\t{}", properties.description); + console_log_trace("Version\t\t\t{}", (int)properties.specVersion); + } + + console_log_trace("\n"); + console_log_trace("================================================\n"); + + VkDebugUtilsMessengerCreateInfoEXT debug_create_info = { + .sType = VK_STRUCTURE_TYPE_DEBUG_UTILS_MESSENGER_CREATE_INFO_EXT, + .messageSeverity = VK_DEBUG_UTILS_MESSAGE_SEVERITY_VERBOSE_BIT_EXT | + VK_DEBUG_UTILS_MESSAGE_SEVERITY_WARNING_BIT_EXT | + VK_DEBUG_UTILS_MESSAGE_SEVERITY_ERROR_BIT_EXT, + .messageType = VK_DEBUG_UTILS_MESSAGE_TYPE_GENERAL_BIT_EXT | + VK_DEBUG_UTILS_MESSAGE_TYPE_VALIDATION_BIT_EXT | + VK_DEBUG_UTILS_MESSAGE_TYPE_PERFORMANCE_BIT_EXT, + .pfnUserCallback = debug_callback, + }; + + create_info.pNext = + (VkDebugUtilsMessengerCreateInfoEXT*)&debug_create_info; + #else + create_info.enabledLayerCount = 0; + create_info.ppEnabledLayerNames = nullptr; + create_info.pNext = nullptr; + #endif + vk_check(vkCreateInstance(&create_info, nullptr, &m_instance_handler), + "vkCreateInstance"); + + #if _DEBUG + // This needs to be created after the VkInstance is or else it wont be + // applied the debug information during validation layer error message + // execution + m_vk_set_debug_utils_object_name_ext = + reinterpret_cast( + vkGetInstanceProcAddr(m_instance_handler, + "vkSetDebugUtilsObjectNameEXT")); + #endif + s_instance = this; + } + + static VkInstance handle() { + return s_instance->m_instance_handler; + } + + /** + * @brief returns function pointer to allow for setting debug object + * name + * + * + * This allows for utilizing vkSetDebugUtilsObjectNameEXT during debug + * builds + * + * This allows for setting up object names that is useful to the + * programmer when a validation layer error message occurs unexpectedly + * + */ + static PFN_vkSetDebugUtilsObjectNameEXT get_debug_object_name() { + return s_instance->m_vk_set_debug_utils_object_name_ext; + } + + /** + * @brief used for providing a way to submit all vulkan metaobjects + * before the destruction of the vulkan logical device + * + * Per vulkan specification, it is required to have all object handles + * created with the logical device to be destroyed before the logical + * device itself gets destroyed during post cleanup + * + * This function was a means to ensure that the destruction of those + * vulkan child objects are handled in that order correctly + */ + static void submit_resource_free(std::function&& p_resource) { + s_instance->m_resources_free.push_back(p_resource); + } + + + void destroy_context() { + for (auto& callback : m_resources_free) { + callback(); + } + + // m_driver.destroy(); + } + + private: + + private: + static instance_context* s_instance; + VkInstance m_instance_handler=nullptr; + std::deque> m_resources_free{}; + PFN_vkSetDebugUtilsObjectNameEXT m_vk_set_debug_utils_object_name_ext; + }; + + instance_context* instance_context::s_instance = nullptr; +}; \ No newline at end of file diff --git a/atlas-modules/drivers/vulkan/utilities.cppm b/atlas-modules/drivers/vulkan/utilities.cppm new file mode 100644 index 00000000..2b78e4a3 --- /dev/null +++ b/atlas-modules/drivers/vulkan/utilities.cppm @@ -0,0 +1,21 @@ +module; + +#include +#include + +export module vulkan:utilities; + +import atlas.logger; +import core; + +export namespace atlas { + namespace vulkan { + + void vk_check(const VkResult& p_result, + const std::string& p_name) { + if (p_result != VK_SUCCESS) { + console_log_error_tagged("vulkan", "{} VkResult returned: {}", p_name, (int)p_result); + } + } + }; +}; \ No newline at end of file diff --git a/atlas-modules/drivers/vulkan/vulkan.cppm b/atlas-modules/drivers/vulkan/vulkan.cppm new file mode 100644 index 00000000..ee4a9cd7 --- /dev/null +++ b/atlas-modules/drivers/vulkan/vulkan.cppm @@ -0,0 +1,5 @@ +export module vulkan; + +export import :instance_context; +export import :window_context; +export import :utilities; \ No newline at end of file diff --git a/atlas-modules/drivers/vulkan/window_context.cppm b/atlas-modules/drivers/vulkan/window_context.cppm new file mode 100644 index 00000000..80382a21 --- /dev/null +++ b/atlas-modules/drivers/vulkan/window_context.cppm @@ -0,0 +1,89 @@ +module; + +#include +#include + +export module vulkan:window_context; + +import core; +import atlas.logger; +import atlas.window; + +export namespace atlas { + namespace vulkan { + /** + * @brief vulkan-backend implementation of the application-window + */ + class window_context : public window { + public: + window_context(const window_params& p_params) : m_params(p_params) { + if(!glfwVulkanSupported()) { + console_log_error("GLFW: Vulkan is not supported!!!"); + return; + } + + glfwWindowHint(GLFW_CLIENT_API, GLFW_NO_API); + glfwWindowHint(GLFW_RESIZABLE, GLFW_TRUE); + + m_window_handle = glfwCreateWindow(static_cast(m_params.width), static_cast(m_params.height), m_params.name.c_str(), nullptr, nullptr); + + glfwMakeContextCurrent(m_window_handle); + } + + virtual ~window_context() = default; + + + protected: + [[nodiscard]] window_params get_params() const override { + return m_params; + } + + [[nodiscard]] GLFWwindow* native_window() const override { + return m_window_handle; + } + + [[nodiscard]] uint32_t read_acquired_next_frame() override { + return 0; + } + + private: + void center_window() { + GLFWmonitor* monitor = glfwGetPrimaryMonitor(); + const GLFWvidmode* mode = glfwGetVideoMode(monitor); + uint32_t width = (mode->width / 2) - (m_params.width / 2); + uint32_t height = (mode->height / 2) - (m_params.height / 2); + glfwSetWindowPos(m_window_handle, static_cast(width), static_cast(height)); + } + + private: + GLFWwindow* m_window_handle=nullptr; + window_params m_params; + }; + }; +}; + + +// /* + + + + +// core: module that is partitioned associated with +// logger +// import logger; +// drivers: +// vulkan: module that is partitioned associated with +// import vulkan; +// internal: export module vulkan:* +// jolt_cpp: module that is partitioned associated with +// import jolt_cpp +// internal: export module jolt_cpp:* + + +// atlas: global module unit +// export import core; +// export import vulkan; +// export import jolt_cpp + + +// */ \ No newline at end of file From e71eff1b7e123cbbc2dab24d59b311db086f4c46 Mon Sep 17 00:00:00 2001 From: SpinnerX Date: Sun, 11 Jan 2026 15:31:01 -0800 Subject: [PATCH 04/68] WIP in re-implementing the editor with modules --- editor_modules/CMakeLists.txt | 29 ++++++++++++++++++++ editor_modules/application.cpp | 49 ++++++++++++++++++++++++++++++++++ 2 files changed, 78 insertions(+) create mode 100644 editor_modules/CMakeLists.txt create mode 100644 editor_modules/application.cpp diff --git a/editor_modules/CMakeLists.txt b/editor_modules/CMakeLists.txt new file mode 100644 index 00000000..4ef33432 --- /dev/null +++ b/editor_modules/CMakeLists.txt @@ -0,0 +1,29 @@ +cmake_minimum_required(VERSION 3.27) +project(editor CXX) + +# build_application( +# SOURCES +# application.cpp + +# PACKAGES +# glfw3 +# Vulkan +# glm +# spdlog + + +# LINK_PACKAGES +# atlas +# glfw +# Vulkan::Vulkan +# glm::glm +# spdlog::spdlog +# ) + +add_executable(${PROJECT_NAME} application.cpp) + +find_package(glfw3 REQUIRED) +find_package(Vulkan REQUIRED) +find_package(glm REQUIRED) +find_package(spdlog REQUIRED) +target_link_libraries(${PROJECT_NAME} PUBLIC glfw Vulkan::Vulkan spdlog::spdlog glm::glm atlas) \ No newline at end of file diff --git a/editor_modules/application.cpp b/editor_modules/application.cpp new file mode 100644 index 00000000..511ddc85 --- /dev/null +++ b/editor_modules/application.cpp @@ -0,0 +1,49 @@ +import atlas; +#include +#include + + +class test_application : public atlas::application { +public: + test_application(const atlas::application_settings& p_settings) : atlas::application(p_settings) { + std::println("test_application initialized!!!"); + console_log_warn("test_application + logger initialized!!!"); + } +}; + + +// /* +// atlas/* +// core/* +// import atlas.core; +// drivers/ +// vulkan +// import atlas.vulkan +// jolt_cpp +// import atlas.jolt_cpp +// .... +// physics +// import atlas.physics +// renderer +// import atlas.renderer + + + +// */ + +int main() { + atlas::console_log_manager::initialize_logger_manager(); + atlas::ref context = atlas::initialize_context(atlas::graphics_api::vulkan); + atlas::application_settings settings = { + .name = "Editor", + .width = 1900, + .height = 600, + .background_color = {1.f, 1.f, 1.f, 1.f}, + }; + std::shared_ptr app = std::make_shared(settings); + + app->execute(); + + app->post_destroy(); + return 0; +} \ No newline at end of file From 6fd98ec7aa92070e5da06e3801a3d8f503e94c21 Mon Sep 17 00:00:00 2001 From: SpinnerX Date: Sun, 11 Jan 2026 17:31:13 -0800 Subject: [PATCH 05/68] WIP in re-adding vulkan instance initialization --- CMakeLists.txt | 3 + atlas-modules/atlas.cppm | 7 +- atlas-modules/core/logger.cppm | 72 ++++++------------- atlas-modules/core/window.cppm | 27 ++----- atlas-modules/drivers/drivers.cppm | 53 +++++++++++++- atlas-modules/drivers/graphics_context.cppm | 24 +++++++ .../drivers/vulkan/instance_context.cppm | 18 +++-- atlas-modules/drivers/vulkan/utilities.cppm | 2 +- atlas-modules/drivers/vulkan/vulkan.cppm | 8 +-- .../drivers/vulkan/window_context.cppm | 35 ++------- editor_modules/application.cpp | 56 +++++++++++---- 11 files changed, 175 insertions(+), 130 deletions(-) create mode 100644 atlas-modules/drivers/graphics_context.cppm diff --git a/CMakeLists.txt b/CMakeLists.txt index b170abb4..8a063ba7 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -112,6 +112,9 @@ target_sources(${PROJECT_NAME} PUBLIC atlas-modules/core/logger.cppm atlas-modules/core/application.cppm atlas-modules/core/window.cppm + + atlas-modules/drivers/drivers.cppm + atlas-modules/drivers/graphics_context.cppm atlas-modules/drivers/vulkan/vulkan.cppm atlas-modules/drivers/vulkan/utilities.cppm diff --git a/atlas-modules/atlas.cppm b/atlas-modules/atlas.cppm index 0862f9b4..d694cbf7 100644 --- a/atlas-modules/atlas.cppm +++ b/atlas-modules/atlas.cppm @@ -1,9 +1,14 @@ export module atlas; export import core; -export import vulkan; +// export import vulkan; export import atlas.logger; +export import atlas.graphics_api; + +export import atlas.drivers; +export import atlas.drivers.graphics_context; +export import atlas.drivers.vulkan; // atlas.subsystem_type_name - this is for anything that is globally needed throughout TheAtlasEngine,like loggers, utilities, etc. // import :internal_stuff - is used for implementation-specific details such as (implementing API-agnostic implementation specific to subsystems) diff --git a/atlas-modules/core/logger.cppm b/atlas-modules/core/logger.cppm index 55238cde..4bb1c093 100644 --- a/atlas-modules/core/logger.cppm +++ b/atlas-modules/core/logger.cppm @@ -8,12 +8,11 @@ module; #include #include #include +#include export module atlas.logger; export import atlas.common; -static std::string g_current_pattern_for_logs = "Undefined Pattern Specified"; - export namespace atlas { /** * @brief logger for logging messages to stdout on the console @@ -23,58 +22,29 @@ export namespace atlas { */ class console_log_manager { public: - /** - * @brief initializes the console_log_manager - * - * TODO: Revisit the logger and do some refactoring because the way this - * works should be changed, as I'd prob do this differently now. - */ - static void initialize_logger_manager(const std::string& pattern = "%^[%n] [%T]: %v%$") { - g_current_pattern_for_logs = pattern; - + console_log_manager(const std::string& p_pattern = "%^[%n] [%T]: %v%$") { + std::println("Constructing console_log_manager!"); + //! @note Setting up logs for different log stdout's //! @note Logs for p_tag is logs specific to the game. - s_loggers.insert({ "atlas", spdlog::stdout_color_mt("atlas") }); - s_loggers.insert({ "physics", spdlog::stdout_color_mt("physics") }); - s_loggers.insert({ "vulkan", spdlog::stdout_color_mt("vulkan") }); - s_loggers.insert( + m_loggers.insert({ "atlas", spdlog::stdout_color_mt("atlas") }); + m_loggers.insert({ "physics", spdlog::stdout_color_mt("physics") }); + m_loggers.insert({ "vulkan", spdlog::stdout_color_mt("vulkan") }); + m_loggers.insert( { "assert", spdlog::stdout_color_mt("core assertion") }); - s_loggers["atlas"]->set_pattern(pattern); - s_loggers["atlas"]->set_level(spdlog::level::trace); - - s_loggers["physics"]->set_level(spdlog::level::trace); - s_loggers["physics"]->set_pattern(pattern); + m_loggers["atlas"]->set_pattern(p_pattern); + m_loggers["atlas"]->set_level(spdlog::level::trace); - s_loggers["vulkan"]->set_level(spdlog::level::trace); - s_loggers["vulkan"]->set_pattern(pattern); + m_loggers["physics"]->set_level(spdlog::level::trace); + m_loggers["physics"]->set_pattern(p_pattern); - s_loggers["assert"]->set_level(spdlog::level::trace); - s_loggers["assert"]->set_pattern(pattern); - } + m_loggers["vulkan"]->set_level(spdlog::level::trace); + m_loggers["vulkan"]->set_pattern(p_pattern); - /** - * @brief sets what the current logger to write to the console with - */ - static void set_current_logger(const std::string& p_tag = "Undefined g_Tag in console_logger") { - #ifndef ENABLE_TESTS_ONLY - //! @note Setting up logs for different log stdout's - //! @note Logs for p_tag is logs specific to the game - s_loggers[p_tag] = spdlog::stdout_color_mt(p_tag); - s_loggers[p_tag]->set_level(spdlog::level::trace); - s_loggers[p_tag]->set_pattern(g_current_pattern_for_logs); - #endif - } - - /** - * @brief constructs a new spdlog::logger to write to the console - */ - static void create_new_logger(const std::string& p_tag = "Undefined Tag") { - #ifndef ENABLE_TESTS_ONLY - s_loggers[p_tag] = spdlog::stdout_color_mt(p_tag); - s_loggers[p_tag]->set_level(spdlog::level::trace); - s_loggers[p_tag]->set_pattern(g_current_pattern_for_logs); - #endif + m_loggers["assert"]->set_level(spdlog::level::trace); + m_loggers["assert"]->set_pattern(p_pattern); + s_instance = this; } /** @@ -86,16 +56,18 @@ export namespace atlas { * nullptr */ static std::shared_ptr get(const std::string& p_tag) { - return s_loggers[p_tag]; + return s_instance->m_loggers[p_tag]; } private: + static console_log_manager* s_instance; // Using an unordered_map to specify through a string what logger to // retrieve to log messages - static std::unordered_map> s_loggers; + std::unordered_map> m_loggers; }; - std::unordered_map> console_log_manager::s_loggers; + // std::unordered_map> console_log_manager::s_loggers; + console_log_manager* console_log_manager::s_instance = nullptr; }; export { diff --git a/atlas-modules/core/window.cppm b/atlas-modules/core/window.cppm index 632b331c..c0ac1245 100644 --- a/atlas-modules/core/window.cppm +++ b/atlas-modules/core/window.cppm @@ -6,11 +6,9 @@ module; export module atlas.window; -// export import :common; import atlas.common; import atlas.graphics_api; - export namespace atlas { struct window_params { uint32_t width; @@ -94,7 +92,9 @@ export namespace atlas { * @param p_current_frame_idx is current frame index to currently * process an image in the current frame */ - void present(const uint32_t& p_current_frame_idx); + void present(const uint32_t& p_current_frame_idx) { + return present_frame(p_current_frame_idx); + } protected: [[nodiscard]] virtual window_params get_params() const = 0; @@ -104,25 +104,6 @@ export namespace atlas { // [[nodiscard]] virtual ::vk::command_buffer current_active_command(uint32_t p_frame_idx) = 0; - virtual void presentation_process(const uint32_t& p_current_frame) = 0; + virtual void present_frame(const uint32_t& p_current_frame) = 0; }; - - /** - * @brief constructs an atlas::window - * - * There should only ever be one window constructed throughout the entire - * application - * - * @param p_settings is the window settings to construct the window with - * - * @return shared_ptr - */ - // ref create_window(const window_params& p_params, graphics_api p_api) { - // switch(p_api) { - // case graphics_api::vulkan: - // return nullptr; - // default: - // return nullptr; - // } - // } }; \ No newline at end of file diff --git a/atlas-modules/drivers/drivers.cppm b/atlas-modules/drivers/drivers.cppm index 91123ed9..d9508eb8 100644 --- a/atlas-modules/drivers/drivers.cppm +++ b/atlas-modules/drivers/drivers.cppm @@ -1,5 +1,54 @@ module; -export module drivers; +#include +#include -export namespace atlas {}; \ No newline at end of file +export module atlas.drivers; + +import atlas.common; +// import atlas.vulkan.window_context; +import atlas.drivers.vulkan; +import atlas.graphics_api; +import atlas.drivers.vulkan.window_context; +import atlas.drivers.vulkan.instance_context; +import atlas.logger; + +/** + * @brief This drivers.cppm will contain API-agnostic implementation that may be widely implemented differently. + * + * Such as Window contexts, graphics API-agnostic implementation, renderers, etc. +*/ + +export namespace atlas { + /** + * @brief constructs an atlas::window + * + * There should only ever be one window constructed throughout the entire + * application + * + * @param p_settings is the window settings to construct the window with + * + * @return shared_ptr + */ + ref create_window(const window_params& p_params, graphics_api p_api) { + switch(p_api) { + case graphics_api::vulkan: + return create_ref(p_params); + default: + return nullptr; + } + } + + /** + * @brief construct a new graphics context and initializes that API + * @return shared_ptr + */ + ref initialize_context(const std::string& p_name, graphics_api p_api) { + switch(p_api) { + case graphics_api::vulkan: + return create_ref(p_name); + default: + return nullptr; + } + } +}; \ No newline at end of file diff --git a/atlas-modules/drivers/graphics_context.cppm b/atlas-modules/drivers/graphics_context.cppm new file mode 100644 index 00000000..1e76029f --- /dev/null +++ b/atlas-modules/drivers/graphics_context.cppm @@ -0,0 +1,24 @@ +module; + +#include + +export module atlas.drivers.graphics_context; + + + + +export namespace atlas { + + class graphics_context { + public: + virtual ~graphics_context() = default; + + void destroy() { + return destroy_context(); + } + + protected: + virtual void destroy_context() = 0; + }; + +}; \ No newline at end of file diff --git a/atlas-modules/drivers/vulkan/instance_context.cppm b/atlas-modules/drivers/vulkan/instance_context.cppm index 6facd97b..02e93b0a 100644 --- a/atlas-modules/drivers/vulkan/instance_context.cppm +++ b/atlas-modules/drivers/vulkan/instance_context.cppm @@ -6,12 +6,13 @@ module; #include #include -export module vulkan:instance_context; - -import :utilities; +export module atlas.drivers.vulkan.instance_context; import atlas.logger; +export import atlas.drivers.graphics_context; +import atlas.drivers.vulkan.utilities; + namespace atlas::vulkan { std::vector initialize_instance_extensions() { std::vector extension_names; @@ -65,10 +66,9 @@ namespace atlas::vulkan { } #endif - class instance_context { + export class instance_context : public graphics_context { public: instance_context(const std::string& p_name) { - console_log_manager::create_new_logger(p_name); VkApplicationInfo app_info = { .sType = VK_STRUCTURE_TYPE_APPLICATION_INFO, .pNext = nullptr, @@ -150,9 +150,12 @@ namespace atlas::vulkan { vkGetInstanceProcAddr(m_instance_handler, "vkSetDebugUtilsObjectNameEXT")); #endif + console_log_info("vulkan::instance_context finished being initialized!!!"); s_instance = this; } + virtual ~instance_context() = default; + static VkInstance handle() { return s_instance->m_instance_handler; } @@ -188,8 +191,9 @@ namespace atlas::vulkan { s_instance->m_resources_free.push_back(p_resource); } - - void destroy_context() { + protected: + void destroy_context() override { + console_log_info("destroy_context!"); for (auto& callback : m_resources_free) { callback(); } diff --git a/atlas-modules/drivers/vulkan/utilities.cppm b/atlas-modules/drivers/vulkan/utilities.cppm index 2b78e4a3..b002218f 100644 --- a/atlas-modules/drivers/vulkan/utilities.cppm +++ b/atlas-modules/drivers/vulkan/utilities.cppm @@ -3,7 +3,7 @@ module; #include #include -export module vulkan:utilities; +export module atlas.drivers.vulkan.utilities; import atlas.logger; import core; diff --git a/atlas-modules/drivers/vulkan/vulkan.cppm b/atlas-modules/drivers/vulkan/vulkan.cppm index ee4a9cd7..01c253ea 100644 --- a/atlas-modules/drivers/vulkan/vulkan.cppm +++ b/atlas-modules/drivers/vulkan/vulkan.cppm @@ -1,5 +1,5 @@ -export module vulkan; +export module atlas.drivers.vulkan; -export import :instance_context; -export import :window_context; -export import :utilities; \ No newline at end of file +// export import :instance_context; +// export import :utilities; +export import atlas.drivers.vulkan.utilities; \ No newline at end of file diff --git a/atlas-modules/drivers/vulkan/window_context.cppm b/atlas-modules/drivers/vulkan/window_context.cppm index 80382a21..3e7e4aed 100644 --- a/atlas-modules/drivers/vulkan/window_context.cppm +++ b/atlas-modules/drivers/vulkan/window_context.cppm @@ -3,11 +3,11 @@ module; #include #include -export module vulkan:window_context; +export module atlas.drivers.vulkan.window_context; import core; import atlas.logger; -import atlas.window; +export import atlas.window; export namespace atlas { namespace vulkan { @@ -46,6 +46,9 @@ export namespace atlas { return 0; } + void present_frame(const uint32_t& p_current_frame) override { + } + private: void center_window() { GLFWmonitor* monitor = glfwGetPrimaryMonitor(); @@ -60,30 +63,4 @@ export namespace atlas { window_params m_params; }; }; -}; - - -// /* - - - - -// core: module that is partitioned associated with -// logger -// import logger; -// drivers: -// vulkan: module that is partitioned associated with -// import vulkan; -// internal: export module vulkan:* -// jolt_cpp: module that is partitioned associated with -// import jolt_cpp -// internal: export module jolt_cpp:* - - -// atlas: global module unit -// export import core; -// export import vulkan; -// export import jolt_cpp - - -// */ \ No newline at end of file +}; \ No newline at end of file diff --git a/editor_modules/application.cpp b/editor_modules/application.cpp index 511ddc85..53db15ed 100644 --- a/editor_modules/application.cpp +++ b/editor_modules/application.cpp @@ -1,17 +1,27 @@ import atlas; #include #include +#include class test_application : public atlas::application { public: test_application(const atlas::application_settings& p_settings) : atlas::application(p_settings) { - std::println("test_application initialized!!!"); - console_log_warn("test_application + logger initialized!!!"); } }; +atlas::ref initialize_application() { + atlas::application_settings settings = { + .name = "Editor", + .width = 1900, + .height = 600, + .background_color = {1.f, 1.f, 1.f, 1.f}, + }; + return create_ref(settings); +} + + // /* // atlas/* // core/* @@ -26,24 +36,44 @@ class test_application : public atlas::application { // import atlas.physics // renderer // import atlas.renderer +// */ - - +// /* +// core: module that is partitioned associated with +// logger +// import logger; +// drivers: +// vulkan: module that is partitioned associated with +// import vulkan; +// internal: export module vulkan:* +// jolt_cpp: module that is partitioned associated with +// import jolt_cpp +// internal: export module jolt_cpp:* +// atlas: global module unit +// export import core; +// export import vulkan; +// export import jolt_cpp // */ int main() { - atlas::console_log_manager::initialize_logger_manager(); - atlas::ref context = atlas::initialize_context(atlas::graphics_api::vulkan); - atlas::application_settings settings = { - .name = "Editor", - .width = 1900, - .height = 600, - .background_color = {1.f, 1.f, 1.f, 1.f}, - }; - std::shared_ptr app = std::make_shared(settings); + atlas::console_log_manager manager = atlas::console_log_manager(); + + // atlas::application_settings settings = { + // .name = "Editor", + // .width = 1900, + // .height = 600, + // .background_color = {1.f, 1.f, 1.f, 1.f}, + // }; + // atlas::ref app = atlas::create_ref(settings); + + atlas::ref app = initialize_application(); + + atlas::ref context = atlas::initialize_context("vulkan", atlas::graphics_api::vulkan); app->execute(); app->post_destroy(); + + context->destroy(); return 0; } \ No newline at end of file From 98a786525d683c30910ffa4f975c4b46cdd9caf1 Mon Sep 17 00:00:00 2001 From: SpinnerX Date: Sun, 11 Jan 2026 18:05:59 -0800 Subject: [PATCH 06/68] WIP windowing and GLFW initialization! --- atlas-modules/atlas.cppm | 5 +--- atlas-modules/core/application.cppm | 22 ++++++++++-------- atlas-modules/drivers/drivers.cppm | 6 ++--- atlas-modules/drivers/vulkan/utilities.cppm | 2 -- .../drivers/vulkan/window_context.cppm | 18 +++++++++++++-- editor_modules/application.cpp | 23 ++++++++++++++++--- 6 files changed, 53 insertions(+), 23 deletions(-) diff --git a/atlas-modules/atlas.cppm b/atlas-modules/atlas.cppm index d694cbf7..48cc703d 100644 --- a/atlas-modules/atlas.cppm +++ b/atlas-modules/atlas.cppm @@ -1,14 +1,11 @@ export module atlas; export import core; -// export import vulkan; -export import atlas.logger; export import atlas.graphics_api; +export import atlas.logger; export import atlas.drivers; -export import atlas.drivers.graphics_context; -export import atlas.drivers.vulkan; // atlas.subsystem_type_name - this is for anything that is globally needed throughout TheAtlasEngine,like loggers, utilities, etc. // import :internal_stuff - is used for implementation-specific details such as (implementing API-agnostic implementation specific to subsystems) diff --git a/atlas-modules/core/application.cppm b/atlas-modules/core/application.cppm index a874e303..db093593 100644 --- a/atlas-modules/core/application.cppm +++ b/atlas-modules/core/application.cppm @@ -9,9 +9,12 @@ module; export module core:application; -import atlas.common; import atlas.graphics_api; +import atlas.logger; +import atlas.common; +// import atlas.drivers.vulkan.window_context; import atlas.window; +import atlas.drivers; export namespace atlas { @@ -43,14 +46,15 @@ export namespace atlas { * @param p_settings is the specific application settings to configure * how the application may be setup */ - application(const application_settings& p_settings) { - std::println("application(const application_settings&) initialized!!!"); - - if(m_window == nullptr) { - std::println("m_window == nullptr!"); - } - - // m_instance_handle_test = std::make_optional(); + application(const application_settings& p_params) { + console_log_info("application(const application_settings&) initialized!!!"); + + window_params params = { + .width = p_params.width, + .height = p_params.height, + .name = p_params.name, + }; + m_window = initialize_window(params, graphics_api::vulkan); s_instance = this; } diff --git a/atlas-modules/drivers/drivers.cppm b/atlas-modules/drivers/drivers.cppm index d9508eb8..dfc802e7 100644 --- a/atlas-modules/drivers/drivers.cppm +++ b/atlas-modules/drivers/drivers.cppm @@ -7,11 +7,11 @@ export module atlas.drivers; import atlas.common; // import atlas.vulkan.window_context; -import atlas.drivers.vulkan; +// import atlas.drivers.vulkan; import atlas.graphics_api; +import atlas.logger; import atlas.drivers.vulkan.window_context; import atlas.drivers.vulkan.instance_context; -import atlas.logger; /** * @brief This drivers.cppm will contain API-agnostic implementation that may be widely implemented differently. @@ -30,7 +30,7 @@ export namespace atlas { * * @return shared_ptr */ - ref create_window(const window_params& p_params, graphics_api p_api) { + ref initialize_window(const window_params& p_params, graphics_api p_api) { switch(p_api) { case graphics_api::vulkan: return create_ref(p_params); diff --git a/atlas-modules/drivers/vulkan/utilities.cppm b/atlas-modules/drivers/vulkan/utilities.cppm index b002218f..4536cc07 100644 --- a/atlas-modules/drivers/vulkan/utilities.cppm +++ b/atlas-modules/drivers/vulkan/utilities.cppm @@ -6,8 +6,6 @@ module; export module atlas.drivers.vulkan.utilities; import atlas.logger; -import core; - export namespace atlas { namespace vulkan { diff --git a/atlas-modules/drivers/vulkan/window_context.cppm b/atlas-modules/drivers/vulkan/window_context.cppm index 3e7e4aed..97676593 100644 --- a/atlas-modules/drivers/vulkan/window_context.cppm +++ b/atlas-modules/drivers/vulkan/window_context.cppm @@ -1,11 +1,21 @@ module; -#include #include +#define GLFW_INCLUDE_VULKAN +#if _WIN32 +#define VK_USE_PLATFORM_WIN32_KHR +#include +#define GLFW_EXPOSE_NATIVE_WIN32 +#include +#include +#else +#include +#include +#endif + export module atlas.drivers.vulkan.window_context; -import core; import atlas.logger; export import atlas.window; @@ -17,8 +27,12 @@ export namespace atlas { class window_context : public window { public: window_context(const window_params& p_params) : m_params(p_params) { + + console_log_info("window_context constructed!!!"); + if(!glfwVulkanSupported()) { console_log_error("GLFW: Vulkan is not supported!!!"); + console_log_error("GLFW: Vulkan Supported = {}", static_cast(glfwVulkanSupported())); return; } diff --git a/editor_modules/application.cpp b/editor_modules/application.cpp index 53db15ed..d7f35466 100644 --- a/editor_modules/application.cpp +++ b/editor_modules/application.cpp @@ -1,7 +1,14 @@ -import atlas; +// import atlas; +import core; +import atlas.common; +import atlas.logger; +import atlas.graphics_api; +import atlas.drivers.graphics_context; +import atlas.drivers; #include #include #include +#include class test_application : public atlas::application { @@ -11,6 +18,12 @@ class test_application : public atlas::application { }; +/* + +TODO: Pre-defined this in TheAtlasEngine +* Then to have the implemented by the application + +*/ atlas::ref initialize_application() { atlas::application_settings settings = { .name = "Editor", @@ -58,6 +71,11 @@ atlas::ref initialize_application() { int main() { atlas::console_log_manager manager = atlas::console_log_manager(); + if(!glfwInit()) { + console_log_fatal("GLFW: Initialization failed!!"); + return -1; + } + // atlas::application_settings settings = { // .name = "Editor", // .width = 1900, @@ -65,11 +83,10 @@ int main() { // .background_color = {1.f, 1.f, 1.f, 1.f}, // }; // atlas::ref app = atlas::create_ref(settings); + atlas::ref context = atlas::initialize_context("vulkan", atlas::graphics_api::vulkan); atlas::ref app = initialize_application(); - atlas::ref context = atlas::initialize_context("vulkan", atlas::graphics_api::vulkan); - app->execute(); app->post_destroy(); From 5a506877ef12578c933b88295fa4a6761bdf40e4 Mon Sep 17 00:00:00 2001 From: SpinnerX Date: Sun, 11 Jan 2026 18:11:56 -0800 Subject: [PATCH 07/68] WIP ensuring the vulkan instances and windowing system are cleaned up properly --- atlas-modules/core/application.cppm | 7 +++++++ atlas-modules/core/event/event.cppm | 12 ++++++++++++ atlas-modules/drivers/vulkan/instance_context.cppm | 4 +++- atlas-modules/drivers/vulkan/window_context.cppm | 4 +++- 4 files changed, 25 insertions(+), 2 deletions(-) create mode 100644 atlas-modules/core/event/event.cppm diff --git a/atlas-modules/core/application.cppm b/atlas-modules/core/application.cppm index db093593..75ee5b92 100644 --- a/atlas-modules/core/application.cppm +++ b/atlas-modules/core/application.cppm @@ -15,6 +15,7 @@ import atlas.common; // import atlas.drivers.vulkan.window_context; import atlas.window; import atlas.drivers; +import atlas.core.event; export namespace atlas { @@ -87,6 +88,12 @@ export namespace atlas { void execute() { // execute std::println("Executing game mainloop!!!"); + + + while(m_window->available()) { + flush_events(); + } + } /** diff --git a/atlas-modules/core/event/event.cppm b/atlas-modules/core/event/event.cppm new file mode 100644 index 00000000..6de80c20 --- /dev/null +++ b/atlas-modules/core/event/event.cppm @@ -0,0 +1,12 @@ +module; + +#include + +export module atlas.core.event; + + +export namespace atlas { + void flush_events() { + glfwPollEvents(); + } +}; \ No newline at end of file diff --git a/atlas-modules/drivers/vulkan/instance_context.cppm b/atlas-modules/drivers/vulkan/instance_context.cppm index 02e93b0a..6b78c64a 100644 --- a/atlas-modules/drivers/vulkan/instance_context.cppm +++ b/atlas-modules/drivers/vulkan/instance_context.cppm @@ -154,7 +154,9 @@ namespace atlas::vulkan { s_instance = this; } - virtual ~instance_context() = default; + virtual ~instance_context() { + vkDestroyInstance(m_instance_handler, nullptr); + } static VkInstance handle() { return s_instance->m_instance_handler; diff --git a/atlas-modules/drivers/vulkan/window_context.cppm b/atlas-modules/drivers/vulkan/window_context.cppm index 97676593..e5e1d9ab 100644 --- a/atlas-modules/drivers/vulkan/window_context.cppm +++ b/atlas-modules/drivers/vulkan/window_context.cppm @@ -44,7 +44,9 @@ export namespace atlas { glfwMakeContextCurrent(m_window_handle); } - virtual ~window_context() = default; + virtual ~window_context() { + glfwDestroyWindow(m_window_handle); + } protected: From b087b34c58b0ff94148fc707cd30a0a53a3710e7 Mon Sep 17 00:00:00 2001 From: SpinnerX Date: Sun, 11 Jan 2026 18:14:12 -0800 Subject: [PATCH 08/68] WIP re-added event.cppm to target_sources in project cmake --- CMakeLists.txt | 2 ++ 1 file changed, 2 insertions(+) diff --git a/CMakeLists.txt b/CMakeLists.txt index 8a063ba7..f614870c 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -112,6 +112,8 @@ target_sources(${PROJECT_NAME} PUBLIC atlas-modules/core/logger.cppm atlas-modules/core/application.cppm atlas-modules/core/window.cppm + + atlas-modules/core/event/event.cppm atlas-modules/drivers/drivers.cppm atlas-modules/drivers/graphics_context.cppm From a4283897758c9dd0a19c0fe052299b75070bde46 Mon Sep 17 00:00:00 2001 From: SpinnerX Date: Mon, 12 Jan 2026 00:03:31 -0800 Subject: [PATCH 09/68] WIP in re-adding vulkan device handles and fixed includes for specifying platform-specific vulkan extensions --- CMakeLists.txt | 2 + atlas-modules/core/application.cppm | 21 +- atlas-modules/core/window.cppm | 6 +- atlas-modules/drivers/drivers.cppm | 2 + atlas-modules/drivers/vulkan/device.cppm | 211 +++++++++++++++++ .../drivers/vulkan/instance_context.cppm | 23 +- .../drivers/vulkan/physical_device.cppm | 218 ++++++++++++++++++ .../drivers/vulkan/window_context.cppm | 20 +- 8 files changed, 479 insertions(+), 24 deletions(-) create mode 100644 atlas-modules/drivers/vulkan/device.cppm create mode 100644 atlas-modules/drivers/vulkan/physical_device.cppm diff --git a/CMakeLists.txt b/CMakeLists.txt index f614870c..9ea58196 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -122,6 +122,8 @@ target_sources(${PROJECT_NAME} PUBLIC atlas-modules/drivers/vulkan/utilities.cppm atlas-modules/drivers/vulkan/instance_context.cppm atlas-modules/drivers/vulkan/window_context.cppm + atlas-modules/drivers/vulkan/physical_device.cppm + atlas-modules/drivers/vulkan/device.cppm ) # target_sources(${PROJECT_NAME} PUBLIC diff --git a/atlas-modules/core/application.cppm b/atlas-modules/core/application.cppm index 75ee5b92..5683f720 100644 --- a/atlas-modules/core/application.cppm +++ b/atlas-modules/core/application.cppm @@ -12,7 +12,6 @@ export module core:application; import atlas.graphics_api; import atlas.logger; import atlas.common; -// import atlas.drivers.vulkan.window_context; import atlas.window; import atlas.drivers; import atlas.core.event; @@ -72,22 +71,11 @@ export namespace atlas { return s_instance->m_delta_time; } - /** - * TODO: Need to remove this as it is not needed here - * - * Originally was used to handle the fixed physics timestep, but that - * can be handled else where. - */ - static float physics_step() { - return 0.f; - } - /** * @brief Explicitly is used to execute the application's mainloop */ void execute() { - // execute - std::println("Executing game mainloop!!!"); + console_log_info("Executing game mainloop!!!"); while(m_window->available()) { @@ -101,7 +89,7 @@ export namespace atlas { * to close */ void post_destroy() { - std::println("Executing post cleanup!!!"); + console_log_info("Executing post cleanup!!!"); } /** @@ -138,6 +126,7 @@ export namespace atlas { * be a direct calls users can have access to */ static void destroy() { + s_instance->m_window->close(); } /** @@ -180,10 +169,6 @@ export namespace atlas { // return m_renderer; // } - private: - void set_current_api(graphics_api api) { - } - private: float m_delta_time = 0.f; ref m_window; diff --git a/atlas-modules/core/window.cppm b/atlas-modules/core/window.cppm index c0ac1245..2bcbe374 100644 --- a/atlas-modules/core/window.cppm +++ b/atlas-modules/core/window.cppm @@ -34,9 +34,9 @@ export namespace atlas { /** * @brief Returns the aspect ratio of the current window */ - // [[nodiscard]] float aspect_ratio() const { - // (float)get_params().width / (float)get_params().height; - // } + [[nodiscard]] float aspect_ratio() const { + return static_cast(get_params().width) / static_cast(get_params().height); + } /** * @brief gives you the next presentable image to use and the index to diff --git a/atlas-modules/drivers/drivers.cppm b/atlas-modules/drivers/drivers.cppm index dfc802e7..25a40911 100644 --- a/atlas-modules/drivers/drivers.cppm +++ b/atlas-modules/drivers/drivers.cppm @@ -10,6 +10,8 @@ import atlas.common; // import atlas.drivers.vulkan; import atlas.graphics_api; import atlas.logger; +import atlas.window; +import atlas.drivers.graphics_context; import atlas.drivers.vulkan.window_context; import atlas.drivers.vulkan.instance_context; diff --git a/atlas-modules/drivers/vulkan/device.cppm b/atlas-modules/drivers/vulkan/device.cppm new file mode 100644 index 00000000..7c85b9b7 --- /dev/null +++ b/atlas-modules/drivers/vulkan/device.cppm @@ -0,0 +1,211 @@ +module; + +#include + +#define GLFW_INCLUDE_VULKAN +#if _WIN32 +#define VK_USE_PLATFORM_WIN32_KHR +#include +#define GLFW_EXPOSE_NATIVE_WIN32 +#include +#include +#else +#include +#include +#endif + +#include +#include + +export module atlas.drivers.vulkan.device; + +import atlas.logger; + +import atlas.drivers.vulkan.utilities; +import atlas.drivers.vulkan.physical_device; + +namespace atlas::vulkan { + static VkFormat search_supported_depth_format( + const VkPhysicalDevice& p_physical, + std::span p_formats, + VkImageTiling p_tiling, + VkFormatFeatureFlags p_feature_flag) { + VkFormat format = VK_FORMAT_UNDEFINED; + + for (size_t i = 0; i < p_formats.size(); i++) { + VkFormat current_format = p_formats[i]; + VkFormatProperties format_properties; + vkGetPhysicalDeviceFormatProperties( + p_physical, current_format, &format_properties); + + if (p_tiling == VK_IMAGE_TILING_LINEAR) { + if (format_properties.linearTilingFeatures & p_feature_flag) { + format = current_format; + } + } + else if (p_tiling == VK_IMAGE_TILING_OPTIMAL and + format_properties.optimalTilingFeatures & p_feature_flag) { + format = current_format; + } + } + + return format; + } + + static VkFormat search_depth_format(const VkPhysicalDevice& p_physical) { + std::vector candidate_formats = { + VK_FORMAT_D32_SFLOAT, + VK_FORMAT_D32_SFLOAT_S8_UINT, + VK_FORMAT_D24_UNORM_S8_UINT + }; + + VkFormat format = search_supported_depth_format( + p_physical, + candidate_formats, + VK_IMAGE_TILING_OPTIMAL, + VK_FORMAT_FEATURE_DEPTH_STENCIL_ATTACHMENT_BIT); + return format; + } + + /** + * @brief logical device implementation wrapper around the VkDevice + * + * This class was a wrapper around VKDevice, that provided you with other + * API's to do with that particular logical device. + * + * Logical devices are representation of virtual software ways to interact + * with the GPU through Vulkan specifications + * + * TODO: Out-of-date. Using vulkan-cpp ::vk::device class to provide API's + * that allow you to do more queries on specific attributes the logical + * device gives you. + */ + export class device { + struct device_queue_family { + VkQueue graphics_queue; + VkQueue transfer_queue; + VkQueue compute_queue; + }; + + public: + device() = default; + + /** + * @brief construct a new logical device + * @param p_physical is the physical device required for the creation of + * the logical device + */ + device(const physical_device& p_physical) : m_physical(p_physical) { + m_depth_format_selected = search_depth_format(m_physical); + + float queue_priority[1] = { 0.0f }; + + std::vector device_extension = { + VK_KHR_SWAPCHAIN_EXTENSION_NAME + }; + + uint32_t graphics_index = + m_physical.read_queue_family_indices().graphics; + + VkDeviceQueueCreateInfo queue_create_info = { + .sType = VK_STRUCTURE_TYPE_DEVICE_QUEUE_CREATE_INFO, + .pNext = nullptr, + .flags = 0, + .queueFamilyIndex = graphics_index, + .queueCount = 1, + .pQueuePriorities = queue_priority, + }; + + VkDeviceCreateInfo create_info = { + .sType = VK_STRUCTURE_TYPE_DEVICE_CREATE_INFO, + .pNext = nullptr, + .flags = 0, + .queueCreateInfoCount = 1, + .pQueueCreateInfos = &queue_create_info, + .enabledLayerCount = 0, + .ppEnabledLayerNames = nullptr, + .enabledExtensionCount = + static_cast(device_extension.size()), + .ppEnabledExtensionNames = device_extension.data(), + }; + + VkPhysicalDeviceFeatures features; + vkGetPhysicalDeviceFeatures(m_physical, &features); + features.robustBufferAccess = false; + create_info.pEnabledFeatures = &features; + + vk_check(vkCreateDevice(m_physical, &create_info, nullptr, &m_driver), + "vkCreateDevice"); + + vkGetDeviceQueue( + m_driver, graphics_index, 0, &m_device_queues.graphics_queue); + + console_log_warn("vulkan::device constructed successfully!!!"); + } + + ~device(){ + destroy(); + } + + /** + * @brief returns the specified graphics queue from this logical device + */ + [[nodiscard]] VkQueue graphics_queue() const { + return m_device_queues.graphics_queue; + } + + /** + * @return -1 if there are no flags available/compatible/valid + */ + uint32_t select_memory_type(uint32_t p_type_filter, VkMemoryPropertyFlags p_property_flag) { + VkPhysicalDeviceMemoryProperties mem_props; + vkGetPhysicalDeviceMemoryProperties(m_physical, &mem_props); + + for (uint32_t i = 0; i < mem_props.memoryTypeCount; i++) { + if ((p_type_filter & (1 << i)) and + (mem_props.memoryTypes[i].propertyFlags & p_property_flag) == + p_property_flag) { + return i; + } + } + + return -1; + } + + void destroy() { + vkDeviceWaitIdle(m_driver); + vkDestroyDevice(m_driver, nullptr); + } + + /** + * @brief gives you the depth format from the logical device + * + * @return VkFormat + */ + [[nodiscard]] VkFormat depth_format() const { + return m_depth_format_selected; + } + + /** + * @brief allows to treat vk_driver as a VkDevice handle + * + * For vulkan API's that accept only taking in VKDevice, this simplifies + * the need to not have a getter API + */ + operator VkDevice() const { return m_driver; } + + /** + * @brief allows to treat vk_driver as a VkDevice handle + * + * For vulkan API's that accept only taking in VKDevice, this simplifies + * the need to not have a getter API + */ + operator VkDevice() { return m_driver; } + + private: + physical_device m_physical{}; + VkDevice m_driver = nullptr; + device_queue_family m_device_queues{}; + VkFormat m_depth_format_selected; + }; +}; \ No newline at end of file diff --git a/atlas-modules/drivers/vulkan/instance_context.cppm b/atlas-modules/drivers/vulkan/instance_context.cppm index 6b78c64a..c4ec4abb 100644 --- a/atlas-modules/drivers/vulkan/instance_context.cppm +++ b/atlas-modules/drivers/vulkan/instance_context.cppm @@ -4,17 +4,30 @@ module; #include #include #include + +#define GLFW_INCLUDE_VULKAN +#if _WIN32 +#define VK_USE_PLATFORM_WIN32_KHR +#include +#define GLFW_EXPOSE_NATIVE_WIN32 +#include +#include +#else +#include #include +#endif export module atlas.drivers.vulkan.instance_context; import atlas.logger; -export import atlas.drivers.graphics_context; +import atlas.drivers.graphics_context; import atlas.drivers.vulkan.utilities; +import atlas.drivers.vulkan.physical_device; +import atlas.drivers.vulkan.device; namespace atlas::vulkan { - std::vector initialize_instance_extensions() { + static std::vector initialize_instance_extensions() { std::vector extension_names; extension_names.emplace_back(VK_KHR_SURFACE_EXTENSION_NAME); @@ -151,6 +164,10 @@ namespace atlas::vulkan { "vkSetDebugUtilsObjectNameEXT")); #endif console_log_info("vulkan::instance_context finished being initialized!!!"); + + m_physical = physical_device(m_instance_handler); + m_device = device(m_physical); + s_instance = this; } @@ -210,6 +227,8 @@ namespace atlas::vulkan { VkInstance m_instance_handler=nullptr; std::deque> m_resources_free{}; PFN_vkSetDebugUtilsObjectNameEXT m_vk_set_debug_utils_object_name_ext; + physical_device m_physical; + device m_device; }; instance_context* instance_context::s_instance = nullptr; diff --git a/atlas-modules/drivers/vulkan/physical_device.cppm b/atlas-modules/drivers/vulkan/physical_device.cppm new file mode 100644 index 00000000..6176dcd9 --- /dev/null +++ b/atlas-modules/drivers/vulkan/physical_device.cppm @@ -0,0 +1,218 @@ +module; + +#include +#include + +#define GLFW_INCLUDE_VULKAN +#if _WIN32 +#define VK_USE_PLATFORM_WIN32_KHR +#include +#define GLFW_EXPOSE_NATIVE_WIN32 +#include +#include +#else +#include +#include +#endif + +export module atlas.drivers.vulkan.physical_device; + +import atlas.logger; +import atlas.drivers.vulkan.utilities; + +export namespace atlas::vulkan { + struct surface_properties { + VkSurfaceCapabilitiesKHR surface_capabilities; + VkSurfaceFormatKHR surface_format; + }; + + /** + * @brief vulkan-specific implementation wrapper around VkPhysicalDevice + * + * Wrapper that constructs a single physical device that provides API's that + * can be used to query specific information for your specific physical + * device + * + * A physical device represents your current hardware GPU and allows for the + * ability to enumerate information to check for compatibility on the + * current GPU + */ + class physical_device { + struct queue_family_indices { + uint32_t graphics = -1; + uint32_t compute = -1; + uint32_t transfer = -1; + }; + + public: + physical_device() = default; + + /** + * @brief constructs a new vulkan physical device + * + * @param p_instance requires a VkInstance to create a VkPhysicalDevice + * handle + */ + physical_device(const VkInstance& p_instance) { + uint32_t device_count = 0; + vkEnumeratePhysicalDevices(p_instance, &device_count, nullptr); + + if (device_count == 0) { + console_log_fatal("Device Count is {} and no devices found!!!", + device_count); + return; + } + + std::vector physical_drivers(device_count); + vkEnumeratePhysicalDevices( + p_instance, &device_count, physical_drivers.data()); + + for (const auto& device : physical_drivers) { + VkPhysicalDeviceProperties device_properties; + VkPhysicalDeviceFeatures device_features; + vkGetPhysicalDeviceProperties(device, &device_properties); + vkGetPhysicalDeviceFeatures(device, &device_features); + if (device_properties.deviceType == + VK_PHYSICAL_DEVICE_TYPE_DISCRETE_GPU) { + m_physical_driver = device; + break; + } + } + + uint32_t queue_family_count = 0; + vkGetPhysicalDeviceQueueFamilyProperties( + m_physical_driver, &queue_family_count, nullptr); + m_queue_family_properties.resize(queue_family_count); + + vkGetPhysicalDeviceQueueFamilyProperties( + m_physical_driver, + &queue_family_count, + m_queue_family_properties.data()); + + m_queue_indices = select_queue_family_indices(); + + console_log_warn("vulkan::physical_device constructed successful!!!"); + } + + ~physical_device() = default; + + /** + * @brief gives you the queue families that are supported + * + * @return queue_family_indices are the indices of the specific queue's + * that are compatible on current hardware specifications + */ + [[nodiscard]] queue_family_indices read_queue_family_indices() const { + return m_queue_indices; + } + + [[nodiscard]] VkPhysicalDeviceMemoryProperties memory_properties() const { + VkPhysicalDeviceMemoryProperties physical_memory_properties; + vkGetPhysicalDeviceMemoryProperties(m_physical_driver, + &physical_memory_properties); + return physical_memory_properties; + } + + /** + * @return uint32_t is the index to the presentation index of the + * specific presentation queue + */ + [[nodiscard]] uint32_t read_presentation_index(const VkSurfaceKHR& p_surface) { + uint32_t presentation_index = -1; + VkBool32 compatible = VK_FALSE; + uint32_t i = 0; + for (const auto& queue_family : m_queue_family_properties) { + if (queue_family.queueFlags & VK_QUEUE_GRAPHICS_BIT) { + vk_check(vkGetPhysicalDeviceSurfaceSupportKHR( + m_physical_driver, i, p_surface, &compatible), + "vkGetPhysicalDeviceSurfaceSupportKHR"); + + if (compatible) { + presentation_index = i; + } + } + i++; + } + + return presentation_index; + } + + /** + * @brief querying surface properties based on the currently specified + * VkSurfaceKHR handle created + */ + [[nodiscard]] surface_properties get_surface_properties(const VkSurfaceKHR& p_surface) { + vk_check(vkGetPhysicalDeviceSurfaceCapabilitiesKHR( + m_physical_driver, + p_surface, + &m_surface_properties.surface_capabilities), + "vkGetPhysicalDeviceSurfaceCapabilitiesKHR"); + + uint32_t format_count = 0; + std::vector formats; + vk_check(vkGetPhysicalDeviceSurfaceFormatsKHR( + m_physical_driver, p_surface, &format_count, nullptr), + "vkGetPhysicalDeviceSurfaceFormatsKHR"); + + formats.resize(format_count); + + vk_check(vkGetPhysicalDeviceSurfaceFormatsKHR( + m_physical_driver, p_surface, &format_count, formats.data()), + "vkGetPhysicalDeviceSurfaceFormatsKHR"); + + for (const auto& format : formats) { + if (format.format == VK_FORMAT_B8G8R8A8_SRGB && + format.colorSpace == VK_COLOR_SPACE_SRGB_NONLINEAR_KHR) { + m_surface_properties.surface_format = format; + } + } + + m_surface_properties.surface_format = formats[0]; + + return m_surface_properties; + } + + /** + * @brief Allows for treating vk_physical_device as a VkPhysicalDevice + * handle + * + * Simplifies using this same class for creating other vulkan + * metaobjects + */ + operator VkPhysicalDevice() { return m_physical_driver; } + + /** + * @brief Allows for treating vk_physical_device as a VkPhysicalDevice + * handle + * + * Simplifies using this same class for creating other vulkan + * metaobjects + */ + operator VkPhysicalDevice() const { return m_physical_driver; } + + private: + queue_family_indices select_queue_family_indices() { + VkPhysicalDeviceMemoryProperties physical_device_memory_properties; + vkGetPhysicalDeviceMemoryProperties(m_physical_driver, + &physical_device_memory_properties); + physical_device::queue_family_indices indices; + int i = 0; + + for (const auto& queue_family : m_queue_family_properties) { + if (queue_family.queueFlags & VK_QUEUE_GRAPHICS_BIT) { + indices.graphics = i; + break; + } + i++; + } + + return indices; + } + + private: + VkPhysicalDevice m_physical_driver = nullptr; + queue_family_indices m_queue_indices{}; + std::vector m_queue_family_properties{}; + surface_properties m_surface_properties{}; + }; +}; \ No newline at end of file diff --git a/atlas-modules/drivers/vulkan/window_context.cppm b/atlas-modules/drivers/vulkan/window_context.cppm index e5e1d9ab..19c349bc 100644 --- a/atlas-modules/drivers/vulkan/window_context.cppm +++ b/atlas-modules/drivers/vulkan/window_context.cppm @@ -16,8 +16,10 @@ module; export module atlas.drivers.vulkan.window_context; +import atlas.window; import atlas.logger; -export import atlas.window; +import atlas.drivers.vulkan.instance_context; +import atlas.drivers.vulkan.utilities; export namespace atlas { namespace vulkan { @@ -39,12 +41,26 @@ export namespace atlas { glfwWindowHint(GLFW_CLIENT_API, GLFW_NO_API); glfwWindowHint(GLFW_RESIZABLE, GLFW_TRUE); + m_instance = instance_context::handle(); + m_window_handle = glfwCreateWindow(static_cast(m_params.width), static_cast(m_params.height), m_params.name.c_str(), nullptr, nullptr); glfwMakeContextCurrent(m_window_handle); + + console_log_info("m_instance = {}", (m_instance == nullptr)); + + vk_check( + glfwCreateWindowSurface( + m_instance, m_window_handle, nullptr, &m_window_surface), + "glfwCreateWindowSurface"); + + center_window(); } virtual ~window_context() { + if(m_window_surface != nullptr) { + vkDestroySurfaceKHR(m_instance, m_window_surface, nullptr); + } glfwDestroyWindow(m_window_handle); } @@ -76,7 +92,9 @@ export namespace atlas { private: GLFWwindow* m_window_handle=nullptr; + VkSurfaceKHR m_window_surface=nullptr; window_params m_params; + VkInstance m_instance=nullptr; }; }; }; \ No newline at end of file From 9d4160e9c94aaac3f9747cf657af083413fb5bc4 Mon Sep 17 00:00:00 2001 From: SpinnerX Date: Mon, 12 Jan 2026 00:27:44 -0800 Subject: [PATCH 10/68] WIP in re-adding registration callbacks + more work to do in getting vulkan implementation working again --- atlas-modules/core/application.cppm | 3 + atlas-modules/core/utilities/poll_state.cppm | 107 ++++++++++++ atlas-modules/core/utilities/state.cppm | 173 +++++++++++++++++++ editor_modules/application.cpp | 4 + 4 files changed, 287 insertions(+) create mode 100644 atlas-modules/core/utilities/poll_state.cppm create mode 100644 atlas-modules/core/utilities/state.cppm diff --git a/atlas-modules/core/application.cppm b/atlas-modules/core/application.cppm index 5683f720..9ad48d96 100644 --- a/atlas-modules/core/application.cppm +++ b/atlas-modules/core/application.cppm @@ -15,6 +15,7 @@ import atlas.common; import atlas.window; import atlas.drivers; import atlas.core.event; +import atlas.core.utilities.poll_state; export namespace atlas { @@ -80,6 +81,8 @@ export namespace atlas { while(m_window->available()) { flush_events(); + + invoke_on_update(); } } diff --git a/atlas-modules/core/utilities/poll_state.cppm b/atlas-modules/core/utilities/poll_state.cppm new file mode 100644 index 00000000..3f85cb0c --- /dev/null +++ b/atlas-modules/core/utilities/poll_state.cppm @@ -0,0 +1,107 @@ +module; + +#include +#include + +export module atlas.core.utilities.poll_state; + + +export namespace atlas { + inline std::unordered_map> s_update{}; + inline std::unordered_map> + s_defer_update{}; + inline std::unordered_map> s_ui_update{}; + inline std::unordered_map> + s_physica_update{}; + inline std::unordered_map> s_start{}; + + // TODO: Look into a different way of doing this + void poll_update(void* p_address,const std::function& p_callback) { + s_update.emplace(p_address, p_callback); + } + + void poll_defer_update(void* p_address, const std::function& p_callback) { + s_defer_update.emplace(p_address, p_callback); + } + + void poll_physics_update(void* p_address, const std::function& p_callback) { + s_physica_update.emplace(p_address, p_callback); + } + + void poll_ui_update(void* p_address, const std::function& p_callback) { + s_ui_update.emplace(p_address, p_callback); + } + + void poll_start(void* p_address, const std::function& p_callback) { + s_start.emplace(p_address, p_callback); + } + + // TEMP: This is a temporary solution, should look into doing this + // differently + void remove_update(void* p_address) { + s_update.erase(p_address); + } + + void remove_defer_update(void* p_address) { + s_defer_update.erase(p_address); + } + + void remove_physics_update(void* p_address) { + s_physica_update.erase(p_address); + } + + void remove_ui_update(void* p_address) { + s_ui_update.erase(p_address); + } + + void remove_start(void* p_address) { + s_start.erase(p_address); + } + + /** + * @brief detail namespace is used for any internals that should not be + * accessed by the user + * + * @note When switching to C++'s modules, hopefully this removes the + * needs for having to represent namespaces in this way. + * + * Any invoke_* function is an internal detail that handles where those + * behaviorial state callbacks get handled into their respective state + * queue's + * + * Where the state queue will call those arbitrary callbacks at their + * respective point in each of the frame. + * + * As thesse are intended for invoking those queue's directly. + * + */ + void invoke_on_update() { + for (auto& [address, on_update] : s_update) { + on_update(); + } + } + + void invoke_defer_update() { + for (auto& [address, on_update] : s_defer_update) { + on_update(); + } + } + + void invoke_physics_update() { + for (auto& [address, on_update] : s_physica_update) { + on_update(); + } + } + + void invoke_ui_update() { + for (auto& [address, on_update] : s_ui_update) { + on_update(); + } + } + + void invoke_start() { + for (auto& [address, on_update] : s_start) { + on_update(); + } + } +}; \ No newline at end of file diff --git a/atlas-modules/core/utilities/state.cppm b/atlas-modules/core/utilities/state.cppm new file mode 100644 index 00000000..6633b8f1 --- /dev/null +++ b/atlas-modules/core/utilities/state.cppm @@ -0,0 +1,173 @@ +module; + +#include +#include + +export module atlas.core.utilities.state; + +import atlas.core.utilities.poll_state; + +export namespace atlas { + /** + * @brief preloading any behavior that may be required of the users game + * objects, such as pre-loading assets or any metadata after construction of + * the objects. During engine's preloading stage. + * + * This is very useful for spawning or not initiating any pre-load logic + * that does not happen during the construction of your object itself + * + * Ideally I would like to expand this to allow for level transitioning of + * pointing to start registration for transitioning various preloading logic + * + * @tparam UObject is the specific object to point to the specified callback + * @tparam UCallback is the arbitrary type of the callback that contains the + * game logic itself + * @param p_instance is a pointer that points where the callback is coming + * from + * @param p_callable is the callback of arbitrary logic that then gets + * executed and is used alongside p_instance + * + * Example Usage: + * + * ```C++ + * atlas::register_start(this, &level_scene::preload); + * ``` + */ + template + void register_start(UObject* p_instance, const UCallback& p_callable) { + static_assert(std::is_member_pointer_v, + "Cannot register a function that is not a member " + "function of a class object"); + poll_start(p_instance, [p_instance, p_callable]() { + (p_instance->*p_callable)(); + }); + } + + /** + * @brief Used for executing user-defined game logic during every framerate. + * + * This API allows you to register your game logic to be executed during + * every frame call. + * + * This is useful for any kind of game logic that is related to game inputs. + * + * @tparam UObject is the specific object to point to the specified callback + * @tparam UCallback is the arbitrary type of the callback that contains the + * game logic itself + * @param p_instance is a pointer that points where the callback is coming + * from + * @param p_callable is the callback of arbitrary logic that then gets + * executed and is used alongside p_instance + * + * Example Usage: + * + * ```C++ + * atlas::register_update(this, &level_scene::update_logic); + * ``` + */ + template + void register_update(UObject* p_instance, const UCallback& p_callable) { + static_assert(std::is_member_pointer_v, + "Cannot register a function that is not a member " + "function of a class object"); + poll_update(p_instance, [p_instance, p_callable]() { + (p_instance->*p_callable)(); + }); + } + + /** + * @brief Primarily used for executing physics game logic during the physics + * fixed framerate + * + * This API rather allows for explicit control over where to execute your + * callback to the physics fixed framerate + * @tparam UObject is the specific object to point to the specified callback + * @tparam UCallback is the arbitrary type of the callback that contains the + * game logic itself + * @param p_instance is a pointer that points where the callback is coming + * from + * @param p_callable is the callback of arbitrary logic that then gets + * executed and is used alongside p_instance + * + * Example Usage: + * + * ```C++ + * atlas::register_physics(this, &level_scene::on_physics); + * ``` + */ + template + void register_physics(UObject* p_instance, const UCallback& p_callable) { + static_assert(std::is_member_pointer_v, + "Cannot register a function that is not a member " + "function of a class object"); + poll_physics_update(p_instance, [p_instance, p_callable]() { + (p_instance->*p_callable)(); + }); + } + + /** + * @brief Intended to be used to specify game logic to be executed at the + * last possible moment in your game + * + * Intended to be used for game object logic that needs to be resolved at + * the last-moment in the frame. + * + * @tparam UObject is the specific object to point to the specified callback + * @tparam UCallback is the arbitrary type of the callback that contains the + * game logic itself + * @param p_instance is a pointer that points where the callback is coming + * from + * @param p_callable is the callback of arbitrary logic that then gets + * executed and is used alongside p_instance + * + * Example Usage: + * + * ```C++ + * atlas::register_deferred(this, &level_scene::late_update); + * ``` + * + */ + template + void register_deferred(UObject* p_instance, const UCallback& p_callable) { + static_assert(std::is_member_pointer_v, + "Cannot register a function that is not a member " + "function of a class object"); + poll_defer_update(p_instance, [p_instance, p_callable]() { + (p_instance->*p_callable)(); + }); + } + + /** + * @brief This is just for registering UI logic for handling editorial UI + * logic such as widgets modification to entity transform components + * + * Intended for containing logic widgets may be used in. + * + * TODO: This might be redundant and may actually consider either removing + * this or simplify by just using register_deferred instead. + * + * @tparam UObject is the specific object to point to the specified callback + * @tparam UCallback is the arbitrary type of the callback that contains the + * game logic itself + * @param p_instance is a pointer that points where the callback is coming + * from + * @param p_callable is the callback of arbitrary logic that then gets + * executed and is used alongside p_instance + * + * Example Usage: + * + * ```C++ + * atlas::register_ui(this, &level_scene::late_update); + * ``` + * + */ + template + void register_ui(UObject* p_instance, const UCallback& p_callable) { + static_assert(std::is_member_pointer_v, + "Cannot register a function that is not a member " + "function of a class object"); + poll_ui_update(p_instance, [p_instance, p_callable]() { + (p_instance->*p_callable)(); + }); + } +}; \ No newline at end of file diff --git a/editor_modules/application.cpp b/editor_modules/application.cpp index d7f35466..30f1ec07 100644 --- a/editor_modules/application.cpp +++ b/editor_modules/application.cpp @@ -3,6 +3,9 @@ import core; import atlas.common; import atlas.logger; import atlas.graphics_api; + +import atlas.core.utilities.state; + import atlas.drivers.graphics_context; import atlas.drivers; #include @@ -14,6 +17,7 @@ import atlas.drivers; class test_application : public atlas::application { public: test_application(const atlas::application_settings& p_settings) : atlas::application(p_settings) { + atlas::register_update(this, &test_application::on_update); } }; From 3c82d5f09837433af73d83ae14d3689465b9b59b Mon Sep 17 00:00:00 2001 From: SpinnerX Date: Mon, 12 Jan 2026 00:35:02 -0800 Subject: [PATCH 11/68] WIP in re-adding in the game state API's and fixed the logical device cleanup to be correct --- atlas-modules/core/application.cppm | 9 +++++++++ atlas-modules/drivers/vulkan/device.cppm | 5 ++--- atlas-modules/drivers/vulkan/instance_context.cppm | 2 +- editor_modules/application.cpp | 2 +- 4 files changed, 13 insertions(+), 5 deletions(-) diff --git a/atlas-modules/core/application.cppm b/atlas-modules/core/application.cppm index 9ad48d96..89047bff 100644 --- a/atlas-modules/core/application.cppm +++ b/atlas-modules/core/application.cppm @@ -79,10 +79,19 @@ export namespace atlas { console_log_info("Executing game mainloop!!!"); + invoke_start(); + + while(m_window->available()) { flush_events(); invoke_on_update(); + + invoke_physics_update(); + + invoke_defer_update(); + + invoke_ui_update(); } } diff --git a/atlas-modules/drivers/vulkan/device.cppm b/atlas-modules/drivers/vulkan/device.cppm index 7c85b9b7..c6d0269b 100644 --- a/atlas-modules/drivers/vulkan/device.cppm +++ b/atlas-modules/drivers/vulkan/device.cppm @@ -143,9 +143,8 @@ namespace atlas::vulkan { console_log_warn("vulkan::device constructed successfully!!!"); } - ~device(){ - destroy(); - } + // Use .destroy to explicitly invoke when to do proper vulkan cleanup + ~device() = default; /** * @brief returns the specified graphics queue from this logical device diff --git a/atlas-modules/drivers/vulkan/instance_context.cppm b/atlas-modules/drivers/vulkan/instance_context.cppm index c4ec4abb..4d520248 100644 --- a/atlas-modules/drivers/vulkan/instance_context.cppm +++ b/atlas-modules/drivers/vulkan/instance_context.cppm @@ -217,7 +217,7 @@ namespace atlas::vulkan { callback(); } - // m_driver.destroy(); + m_device.destroy(); } private: diff --git a/editor_modules/application.cpp b/editor_modules/application.cpp index 30f1ec07..653d7d18 100644 --- a/editor_modules/application.cpp +++ b/editor_modules/application.cpp @@ -17,8 +17,8 @@ import atlas.drivers; class test_application : public atlas::application { public: test_application(const atlas::application_settings& p_settings) : atlas::application(p_settings) { - atlas::register_update(this, &test_application::on_update); } + }; From 6496c47635092520d35a0d81b5268d12192dd735 Mon Sep 17 00:00:00 2001 From: SpinnerX Date: Mon, 12 Jan 2026 02:36:48 -0800 Subject: [PATCH 12/68] WIP -- re-adding handling event inputs --- atlas-modules/atlas.cppm | 3 +- atlas-modules/core/application.cppm | 11 +- atlas-modules/core/core.cppm | 3 +- atlas-modules/core/event/event.cppm | 87 ++++++- atlas-modules/core/event/keys.cppm | 281 ++++++++++++++++++++++ atlas-modules/core/event/mouse_codes.cppm | 40 +++ atlas-modules/core/main.cpp | 11 - editor_modules/application.cpp | 16 +- 8 files changed, 431 insertions(+), 21 deletions(-) create mode 100644 atlas-modules/core/event/keys.cppm create mode 100644 atlas-modules/core/event/mouse_codes.cppm diff --git a/atlas-modules/atlas.cppm b/atlas-modules/atlas.cppm index 48cc703d..ae99a65a 100644 --- a/atlas-modules/atlas.cppm +++ b/atlas-modules/atlas.cppm @@ -1,6 +1,7 @@ export module atlas; -export import core; +// export import core; +// export import atlas.core.application; export import atlas.graphics_api; export import atlas.logger; diff --git a/atlas-modules/core/application.cppm b/atlas-modules/core/application.cppm index 89047bff..9a0cc8d7 100644 --- a/atlas-modules/core/application.cppm +++ b/atlas-modules/core/application.cppm @@ -6,8 +6,9 @@ module; #include #include #include +#include -export module core:application; +export module atlas.application; import atlas.graphics_api; import atlas.logger; @@ -56,7 +57,7 @@ export namespace atlas { .name = p_params.name, }; m_window = initialize_window(params, graphics_api::vulkan); - + event::set_window_size(static_cast(*m_window)); s_instance = this; } @@ -83,7 +84,7 @@ export namespace atlas { while(m_window->available()) { - flush_events(); + event::flush_events(); invoke_on_update(); @@ -176,6 +177,10 @@ export namespace atlas { return 0; } + static window& get_window() { + return *s_instance->m_window; + } + protected: // [[nodiscard]] ref renderer_instance() const { // return m_renderer; diff --git a/atlas-modules/core/core.cppm b/atlas-modules/core/core.cppm index dfbbb91b..52e1229f 100644 --- a/atlas-modules/core/core.cppm +++ b/atlas-modules/core/core.cppm @@ -1,7 +1,8 @@ export module core; // export import :common; -export import :application; +export import atlas.common; +// export import :application; // export import :logger; export namespace atlas { diff --git a/atlas-modules/core/event/event.cppm b/atlas-modules/core/event/event.cppm index 6de80c20..5d4ddf2d 100644 --- a/atlas-modules/core/event/event.cppm +++ b/atlas-modules/core/event/event.cppm @@ -1,12 +1,91 @@ module; #include +#include +#include +#include +#include export module atlas.core.event; +namespace atlas { + + /** + * @name event.hpp + * @note Actual input polling system to poll in differeny sets of key/mouse + * actions + * @param UpdateEvents handles making sure that all of our events we handle + * have been successfully updated. + * @param GetMousePos just returns the position of our mouse cursor + */ + enum input_state { None, Idle, Pressed, Released }; + + struct joystick_button { + int ID = -1; + std::string Name = ""; + input_state ButtonState = input_state::None; + input_state PreviousButtonState = input_state::None; + }; + + struct joystick_info { + int ID = -1; + std::string JoystickName = "Default"; + std::map Buttons; + std::map ButtonsDown; + std::map AxesOfController; + }; + + static std::map s_controllers; + + using button_id = int; + using controller_id = int; + static GLFWwindow* s_window_address; + + export namespace event { + void flush_events() { + glfwPollEvents(); + } + + bool is_key_pressed(int p_key) { + + // GLFWwindow* window = application::get_window(); + GLFWwindow* window = s_window_address; + + auto state = glfwGetKey(window, static_cast(p_key)); + return (state == GLFW_PRESS); + } + + bool is_key_released(int p_key) {} + + bool is_mouse_pressed(int p_mouse_code) {} + bool is_mouse_released(int p_mouse_code) {} + + glm::vec2 cursor_position() {} + + // joystic-specific functions + bool is_joystic_present(int p_controller_id) {} + + const char* is_joystick_guid(int p_controller_id) {} + + float get_joystic_axis(int p_controller_id, int p_button) {} + + // bool is_button_pressed(int p_button_id, int p_controller_id); + + // bool is_button_released(int p_button_id, int p_controller_id); + + //! @note FIXME: Make button later + bool is_joystick_button_pressed(int p_button) {} + + bool is_joystick_button_released(int p_button) {} + + // specific for listening events + void update_events() {} + + void wait_for_events() {} + + void set_window_size(GLFWwindow* p_window) { + s_window_address = p_window; + } + }; -export namespace atlas { - void flush_events() { - glfwPollEvents(); - } }; \ No newline at end of file diff --git a/atlas-modules/core/event/keys.cppm b/atlas-modules/core/event/keys.cppm new file mode 100644 index 00000000..60167c88 --- /dev/null +++ b/atlas-modules/core/event/keys.cppm @@ -0,0 +1,281 @@ +module; + +#include + +export module atlas.core.event.keys; + + +export namespace atlas::event { + enum Key : uint32_t { + // From glfw3.h + Space = 32, + Apostrophe = 39, /* ' */ + Comma = 44, /* , */ + Minus = 45, /* - */ + Period = 46, /* . */ + Slash = 47, /* / */ + + D0 = 48, /* 0 */ + D1 = 49, /* 1 */ + D2 = 50, /* 2 */ + D3 = 51, /* 3 */ + D4 = 52, /* 4 */ + D5 = 53, /* 5 */ + D6 = 54, /* 6 */ + D7 = 55, /* 7 */ + D8 = 56, /* 8 */ + D9 = 57, /* 9 */ + + Semicolon = 59, /* ; */ + Equal = 61, /* = */ + + A = 65, + B = 66, + C = 67, + D = 68, + E = 69, + F = 70, + G = 71, + H = 72, + I = 73, + J = 74, + K = 75, + L = 76, + M = 77, + N = 78, + O = 79, + P = 80, + Q = 81, + R = 82, + S = 83, + T = 84, + U = 85, + V = 86, + W = 87, + X = 88, + Y = 89, + Z = 90, + + LeftBracket = 91, /* [ */ + Backslash = 92, /* \ */ + RightBracket = 93, /* ] */ + GraveAccent = 96, /* ` */ + + World1 = 161, /* non-US #1 */ + World2 = 162, /* non-US #2 */ + + /* Function keys */ + Escape = 256, + Enter = 257, + Tab = 258, + Backspace = 259, + Insert = 260, + Delete = 261, + Right = 262, + Left = 263, + Down = 264, + Up = 265, + PageUp = 266, + PageDown = 267, + Home = 268, + End = 269, + CapsLock = 280, + ScrollLock = 281, + NumLock = 282, + PrintScreen = 283, + Pause = 284, + F1 = 290, + F2 = 291, + F3 = 292, + F4 = 293, + F5 = 294, + F6 = 295, + F7 = 296, + F8 = 297, + F9 = 298, + F10 = 299, + F11 = 300, + F12 = 301, + F13 = 302, + F14 = 303, + F15 = 304, + F16 = 305, + F17 = 306, + F18 = 307, + F19 = 308, + F20 = 309, + F21 = 310, + F22 = 311, + F23 = 312, + F24 = 313, + F25 = 314, + + /* Keypad */ + KP0 = 320, + KP1 = 321, + KP2 = 322, + KP3 = 323, + KP4 = 324, + KP5 = 325, + KP6 = 326, + KP7 = 327, + KP8 = 328, + KP9 = 329, + KPDecimal = 330, + KPDivide = 331, + KPMultiply = 332, + KPSubtract = 333, + KPAdd = 334, + KPEnter = 335, + KPEqual = 336, + + LeftShift = 340, + LeftControl = 341, + LeftAlt = 342, + Leftsuper = 343, + RightShift = 344, + RightControl = 345, + RightAlt = 346, + Rightsuper = 347, + Menu = 348 + }; +} + +// From glfw3.h + + +export { +inline constexpr uint32_t key_space = ::atlas::event::Key::Space; +inline constexpr uint32_t key_apostrophe = + ::atlas::event::Key::Apostrophe; /* ' */ +inline constexpr uint32_t key_comma = ::atlas::event::Key::Comma; /* , */ +inline constexpr uint32_t key_minus = ::atlas::event::Key::Minus; /* - */ +inline constexpr uint32_t key_period = ::atlas::event::Key::Period; /* . */ +inline constexpr uint32_t key_slash = ::atlas::event::Key::Slash; /* / */ +inline constexpr uint32_t key_0 = ::atlas::event::Key::D0; +inline constexpr uint32_t key_1 = ::atlas::event::Key::D1; +inline constexpr uint32_t key_2 = ::atlas::event::Key::D2; +inline constexpr uint32_t key_3 = ::atlas::event::Key::D3; +inline constexpr uint32_t key_4 = ::atlas::event::Key::D4; +inline constexpr uint32_t key_5 = ::atlas::event::Key::D5; +inline constexpr uint32_t key_6 = ::atlas::event::Key::D6; +inline constexpr uint32_t key_7 = ::atlas::event::Key::D7; +inline constexpr uint32_t key_8 = ::atlas::event::Key::D8; +inline constexpr uint32_t key_9 = ::atlas::event::Key::D9; +inline constexpr uint32_t key_semicolon = + ::atlas::event::Key::Semicolon; /* ; */ +inline constexpr uint32_t key_equal = ::atlas::event::Key::Equal; /* = */ +inline constexpr uint32_t key_a = ::atlas::event::Key::A; +inline constexpr uint32_t key_b = ::atlas::event::Key::B; +inline constexpr uint32_t key_c = ::atlas::event::Key::C; +inline constexpr uint32_t key_d = ::atlas::event::Key::D; +inline constexpr uint32_t key_e = ::atlas::event::Key::E; +inline constexpr uint32_t key_f = ::atlas::event::Key::F; +inline constexpr uint32_t key_g = ::atlas::event::Key::G; +inline constexpr uint32_t key_h = ::atlas::event::Key::H; +inline constexpr uint32_t key_i = ::atlas::event::Key::I; +inline constexpr uint32_t key_j = ::atlas::event::Key::J; +inline constexpr uint32_t key_k = ::atlas::event::Key::K; +inline constexpr uint32_t key_l = ::atlas::event::Key::L; +inline constexpr uint32_t key_m = ::atlas::event::Key::M; +inline constexpr uint32_t key_n = ::atlas::event::Key::N; +inline constexpr uint32_t key_o = ::atlas::event::Key::O; +inline constexpr uint32_t key_p = ::atlas::event::Key::P; +inline constexpr uint32_t key_q = ::atlas::event::Key::Q; +inline constexpr uint32_t key_r = ::atlas::event::Key::R; +inline constexpr uint32_t key_s = ::atlas::event::Key::S; +// inline constexpr uint32_t key_t = ::atlas::event::Key::T; +inline constexpr uint32_t key_u = ::atlas::event::Key::U; +inline constexpr uint32_t key_v = ::atlas::event::Key::V; +inline constexpr uint32_t key_w = ::atlas::event::Key::W; +inline constexpr uint32_t key_x = ::atlas::event::Key::X; +inline constexpr uint32_t key_y = ::atlas::event::Key::Y; +inline constexpr uint32_t key_z = ::atlas::event::Key::Z; +inline constexpr uint32_t key_left_bracket = + ::atlas::event::Key::LeftBracket; /* [ */ +inline constexpr uint32_t key_backslash = + ::atlas::event::Key::Backslash; /* \ */ +inline constexpr uint32_t key_right_bracket = + ::atlas::event::Key::RightBracket; /* ] */ +inline constexpr uint32_t key_gravity_accent = + ::atlas::event::Key::GraveAccent; /* ` */ +inline constexpr uint32_t key_world_1 = + ::atlas::event::Key::World1; /* non-US #1 */ +inline constexpr uint32_t key_world_2 = + ::atlas::event::Key::World2; /* non-US #2 */ + +/* Function keys */ +inline constexpr uint32_t key_escape = ::atlas::event::Key::Escape; +inline constexpr uint32_t key_enter = ::atlas::event::Key::Enter; +inline constexpr uint32_t key_tab = ::atlas::event::Key::Tab; +inline constexpr uint32_t key_backspace = ::atlas::event::Key::Backspace; +inline constexpr uint32_t key_insert = ::atlas::event::Key::Insert; +inline constexpr uint32_t key_delete = ::atlas::event::Key::Delete; +inline constexpr uint32_t key_right = ::atlas::event::Key::Right; +inline constexpr uint32_t key_left = ::atlas::event::Key::Left; +inline constexpr uint32_t key_down = ::atlas::event::Key::Down; +inline constexpr uint32_t key_up = ::atlas::event::Key::Up; +inline constexpr uint32_t key_page_up = ::atlas::event::Key::PageUp; +inline constexpr uint32_t key_page_down = ::atlas::event::Key::PageDown; +inline constexpr uint32_t key_home = ::atlas::event::Key::Home; +inline constexpr uint32_t key_end = ::atlas::event::Key::End; +inline constexpr uint32_t key_caps_lock = ::atlas::event::Key::CapsLock; +inline constexpr uint32_t key_scroll_lock = ::atlas::event::Key::ScrollLock; +inline constexpr uint32_t key_num_lock = ::atlas::event::Key::NumLock; +inline constexpr uint32_t key_print_screen = ::atlas::event::Key::PrintScreen; +inline constexpr uint32_t key_pause = ::atlas::event::Key::Pause; +inline constexpr uint32_t key_f1 = ::atlas::event::Key::F1; +inline constexpr uint32_t key_f2 = ::atlas::event::Key::F2; +inline constexpr uint32_t key_f3 = ::atlas::event::Key::F3; +inline constexpr uint32_t key_f4 = ::atlas::event::Key::F4; +inline constexpr uint32_t key_f5 = ::atlas::event::Key::F5; +inline constexpr uint32_t key_f6 = ::atlas::event::Key::F6; +inline constexpr uint32_t key_f7 = ::atlas::event::Key::F7; +inline constexpr uint32_t key_f8 = ::atlas::event::Key::F8; +inline constexpr uint32_t key_f9 = ::atlas::event::Key::F9; +inline constexpr uint32_t key_f10 = ::atlas::event::Key::F10; +inline constexpr uint32_t key_f11 = ::atlas::event::Key::F11; +inline constexpr uint32_t key_f12 = ::atlas::event::Key::F12; +inline constexpr uint32_t key_f13 = ::atlas::event::Key::F13; +inline constexpr uint32_t key_f14 = ::atlas::event::Key::F14; +inline constexpr uint32_t key_f15 = ::atlas::event::Key::F15; +inline constexpr uint32_t key_f16 = ::atlas::event::Key::F16; +inline constexpr uint32_t key_f17 = ::atlas::event::Key::F17; +inline constexpr uint32_t key_f18 = ::atlas::event::Key::F18; +inline constexpr uint32_t key_f19 = ::atlas::event::Key::F19; +inline constexpr uint32_t key_f20 = ::atlas::event::Key::F20; +inline constexpr uint32_t key_f21 = ::atlas::event::Key::F21; +inline constexpr uint32_t key_f22 = ::atlas::event::Key::F22; +inline constexpr uint32_t key_f23 = ::atlas::event::Key::F23; +inline constexpr uint32_t key_f24 = ::atlas::event::Key::F24; +inline constexpr uint32_t key_f25 = ::atlas::event::Key::F25; + +/* Keypad */ +inline constexpr uint32_t key_kp_0 = ::atlas::event::Key::KP0; +inline constexpr uint32_t key_kp_1 = ::atlas::event::Key::KP1; +inline constexpr uint32_t key_kp_2 = ::atlas::event::Key::KP2; +inline constexpr uint32_t key_kp_3 = ::atlas::event::Key::KP3; +inline constexpr uint32_t key_kp_4 = ::atlas::event::Key::KP4; +inline constexpr uint32_t key_kp_5 = ::atlas::event::Key::KP5; +inline constexpr uint32_t key_kp_6 = ::atlas::event::Key::KP6; +inline constexpr uint32_t key_kp_7 = ::atlas::event::Key::KP7; +inline constexpr uint32_t key_kp_8 = ::atlas::event::Key::KP8; +inline constexpr uint32_t key_kp_9 = ::atlas::event::Key::KP9; +inline constexpr uint32_t key_kp_decimal = ::atlas::event::Key::KPDecimal; +inline constexpr uint32_t key_kp_divide = ::atlas::event::Key::KPDivide; +inline constexpr uint32_t key_kp_multiply = ::atlas::event::Key::KPMultiply; +inline constexpr uint32_t key_kp_subtract = ::atlas::event::Key::KPSubtract; +inline constexpr uint32_t key_kp_add = ::atlas::event::Key::KPAdd; +inline constexpr uint32_t key_kp_enter = ::atlas::event::Key::KPEnter; +inline constexpr uint32_t key_kp_equal = ::atlas::event::Key::KPEqual; + +inline constexpr uint32_t key_left_shift = ::atlas::event::Key::LeftShift; +inline constexpr uint32_t key_left_control = ::atlas::event::Key::LeftControl; +inline constexpr uint32_t key_left_alt = ::atlas::event::Key::LeftAlt; +inline constexpr uint32_t key_left_super = ::atlas::event::Key::Leftsuper; +inline constexpr uint32_t key_right_shift = ::atlas::event::Key::RightShift; +inline constexpr uint32_t key_right_control = ::atlas::event::Key::RightControl; +inline constexpr uint32_t key_right_alt = ::atlas::event::Key::RightAlt; +inline constexpr uint32_t key_right_super = ::atlas::event::Key::Rightsuper; +inline constexpr uint32_t key_menu = ::atlas::event::Key::Menu; +}; \ No newline at end of file diff --git a/atlas-modules/core/event/mouse_codes.cppm b/atlas-modules/core/event/mouse_codes.cppm new file mode 100644 index 00000000..b989fd19 --- /dev/null +++ b/atlas-modules/core/event/mouse_codes.cppm @@ -0,0 +1,40 @@ +module; + +#include + +export module atlas.core.event.mouse_codes; + +namespace atlas::event { + enum Mouse : uint32_t { + // From glfw3.h + Button0 = 0, + Button1 = 1, + Button2 = 2, + Button3 = 3, + Button4 = 4, + Button5 = 5, + Button6 = 6, + Button7 = 7, + + ButtonLast = Button7, + ButtonLeft = Button0, + ButtonRight = Button1, + ButtonMiddle = Button2 + }; + +} // namespace atlas + +inline constexpr uint32_t mouse_button_0 = ::atlas::event::Mouse::Button0; +inline constexpr uint32_t mouse_button_1 = ::atlas::event::Mouse::Button1; +inline constexpr uint32_t mouse_button_2 = ::atlas::event::Mouse::Button2; +inline constexpr uint32_t mouse_button_3 = ::atlas::event::Mouse::Button3; +inline constexpr uint32_t mouse_button_4 = ::atlas::event::Mouse::Button4; +inline constexpr uint32_t mouse_button_5 = ::atlas::event::Mouse::Button5; +inline constexpr uint32_t mouse_button_6 = ::atlas::event::Mouse::Button6; +inline constexpr uint32_t mouse_button_7 = ::atlas::event::Mouse::Button7; +inline constexpr uint32_t mouse_button_last = ::atlas::event::Mouse::ButtonLast; +inline constexpr uint32_t mouse_button_left = ::atlas::event::Mouse::ButtonLeft; +inline constexpr uint32_t mouse_button_right = + ::atlas::event::Mouse::ButtonRight; +inline constexpr uint32_t mouse_button_middle = + ::atlas::event::Mouse::ButtonMiddle; \ No newline at end of file diff --git a/atlas-modules/core/main.cpp b/atlas-modules/core/main.cpp index 314cfbbc..d21db9b8 100644 --- a/atlas-modules/core/main.cpp +++ b/atlas-modules/core/main.cpp @@ -1,16 +1,5 @@ -import atlas; #include #include int main() { - auto app = atlas::initialize_application(); - - if(app == nullptr) { - std::println("Initialize App Failed!!!"); - } - else { - std::println("App Initialized Successful!!!"); - } - - return 0; } \ No newline at end of file diff --git a/editor_modules/application.cpp b/editor_modules/application.cpp index 653d7d18..78eccfdc 100644 --- a/editor_modules/application.cpp +++ b/editor_modules/application.cpp @@ -1,5 +1,5 @@ // import atlas; -import core; +import atlas.application; import atlas.common; import atlas.logger; import atlas.graphics_api; @@ -8,6 +8,9 @@ import atlas.core.utilities.state; import atlas.drivers.graphics_context; import atlas.drivers; +import atlas.core.event; +import atlas.core.event.keys; + #include #include #include @@ -17,8 +20,19 @@ import atlas.drivers; class test_application : public atlas::application { public: test_application(const atlas::application_settings& p_settings) : atlas::application(p_settings) { + atlas::register_update(this, &test_application::on_update); + } + + + void on_update() { + if(atlas::event::is_key_pressed(key_escape)) { + atlas::application::destroy(); + } } + + + }; From ffef98f6ac043d60e30c73f4cbce59c4f68bcea7 Mon Sep 17 00:00:00 2001 From: SpinnerX Date: Mon, 12 Jan 2026 14:02:22 -0800 Subject: [PATCH 13/68] WIP -- re-adding more events implementations --- CMakeLists.txt | 8 +++ atlas-modules/atlas.cppm | 2 +- atlas-modules/core/event/bus.cppm | 69 ++++++++++++++++++++ atlas-modules/core/event/event.cppm | 2 + atlas-modules/core/event/joystick_codes.cppm | 62 ++++++++++++++++++ atlas-modules/core/event/listener.cppm | 40 ++++++++++++ atlas-modules/core/event/types.cppm | 33 ++++++++++ atlas-modules/core/main.cpp | 5 -- 8 files changed, 215 insertions(+), 6 deletions(-) create mode 100644 atlas-modules/core/event/bus.cppm create mode 100644 atlas-modules/core/event/joystick_codes.cppm create mode 100644 atlas-modules/core/event/listener.cppm create mode 100644 atlas-modules/core/event/types.cppm delete mode 100644 atlas-modules/core/main.cpp diff --git a/CMakeLists.txt b/CMakeLists.txt index 9ea58196..6d7f10f0 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -113,7 +113,15 @@ target_sources(${PROJECT_NAME} PUBLIC atlas-modules/core/application.cppm atlas-modules/core/window.cppm + atlas-modules/core/utilities/state.cppm + atlas-modules/core/utilities/poll_state.cppm + atlas-modules/core/event/event.cppm + atlas-modules/core/event/bus.cppm + atlas-modules/core/event/listener.cppm + atlas-modules/core/event/keys.cppm + atlas-modules/core/event/mouse_codes.cppm + atlas-modules/core/event/joystick_codes.cppm atlas-modules/drivers/drivers.cppm atlas-modules/drivers/graphics_context.cppm diff --git a/atlas-modules/atlas.cppm b/atlas-modules/atlas.cppm index ae99a65a..a35f512f 100644 --- a/atlas-modules/atlas.cppm +++ b/atlas-modules/atlas.cppm @@ -1,7 +1,7 @@ export module atlas; // export import core; -// export import atlas.core.application; +// export import atlas.application; export import atlas.graphics_api; export import atlas.logger; diff --git a/atlas-modules/core/event/bus.cppm b/atlas-modules/core/event/bus.cppm new file mode 100644 index 00000000..8e15d61a --- /dev/null +++ b/atlas-modules/core/event/bus.cppm @@ -0,0 +1,69 @@ +module; + + +#include +#include +#include +#include + +export module atlas.core.event.bus; + +import atlas.core.event.listener; + +namespace atlas::event { + /** + * @brief Event bus that holds the responsibility to reroute events to the + * subscribers of those particular event. + */ + class bus { + public: + bus() = default; + + template + void create_listener() { + size_t id = type_id(); + if (m_event_listeners.contains(id)) { + return; + } + m_event_listeners.emplace(id, listener()); + } + + template + void subscribe(UObject* p_instance, const UCallback& p_callback) { + size_t id = type_id(); + + if (!m_event_listeners.contains(id)) { + create_listener(); + return; + } + + std::any_cast&>( + m_event_listeners.at(id)) + .subscribe(p_instance, p_callback); + + // return listener().subscribe(p_instance, p_callback); + } + + template + void publish(UEvent& p_event) { + size_t id = type_id(); + + if (!m_event_listeners.contains(id)) { + return; + } + + std::any_cast&>( + m_event_listeners.at(id)) + .notify_all(p_event); + } + + private: + template + size_t type_id() { + return typeid(UEvent).hash_code(); + } + + private: + std::unordered_map m_event_listeners; + }; +}; \ No newline at end of file diff --git a/atlas-modules/core/event/event.cppm b/atlas-modules/core/event/event.cppm index 5d4ddf2d..36db3542 100644 --- a/atlas-modules/core/event/event.cppm +++ b/atlas-modules/core/event/event.cppm @@ -39,6 +39,8 @@ namespace atlas { using button_id = int; using controller_id = int; + + // TODO: Probably make this into std::map s_window_viewports? static GLFWwindow* s_window_address; export namespace event { diff --git a/atlas-modules/core/event/joystick_codes.cppm b/atlas-modules/core/event/joystick_codes.cppm new file mode 100644 index 00000000..ba7239c8 --- /dev/null +++ b/atlas-modules/core/event/joystick_codes.cppm @@ -0,0 +1,62 @@ +module; + +#include + +export module atlas.core.event.joystick_codes; + +namespace atlas::event { + enum JoystickCodes : int { + Joystick1 = 0, + + Joystick2 = 1, + + Joystick3 = 2, + + Joystick4 = 3, + + Joystick5 = 4, + + Joystick6 = 5, + + Joystick7 = 6, + + Joystick8 = 7, + + Joystick9 = 8, + + Joystick10 = 9, + + Joystick11 = 10, + + Joystick12 = 11, + + Joystick13 = 12, + + Joystick14 = 13, + + Joystick15 = 14, + + Joystick16 = 15, + + JoystickLAST = Joystick16, + }; +}; // namespace atlas + +inline constexpr int joystick_1 = ::atlas::event::JoystickCodes::Joystick1; +inline constexpr int joystick_2 = ::atlas::event::JoystickCodes::Joystick2; +inline constexpr int joystick_3 = ::atlas::event::JoystickCodes::Joystick3; +inline constexpr int joystick_4 = ::atlas::event::JoystickCodes::Joystick4; +inline constexpr int joystick_5 = ::atlas::event::JoystickCodes::Joystick5; +inline constexpr int joystick_6 = ::atlas::event::JoystickCodes::Joystick6; +inline constexpr int joystick_7 = ::atlas::event::JoystickCodes::Joystick7; +inline constexpr int joystick_8 = ::atlas::event::JoystickCodes::Joystick8; +inline constexpr int joystick_9 = ::atlas::event::JoystickCodes::Joystick9; +inline constexpr int joystick_10 = ::atlas::event::JoystickCodes::Joystick10; +inline constexpr int joystick_11 = ::atlas::event::JoystickCodes::Joystick11; +inline constexpr int joystick_12 = ::atlas::event::JoystickCodes::Joystick12; +inline constexpr int joystick_13 = ::atlas::event::JoystickCodes::Joystick13; +inline constexpr int joystick_14 = ::atlas::event::JoystickCodes::Joystick14; +inline constexpr int joystick_15 = ::atlas::event::JoystickCodes::Joystick15; +inline constexpr int joystick_16 = ::atlas::event::JoystickCodes::Joystick16; +inline constexpr int joystick_last = + ::atlas::event::JoystickCodes::JoystickLAST; \ No newline at end of file diff --git a/atlas-modules/core/event/listener.cppm b/atlas-modules/core/event/listener.cppm new file mode 100644 index 00000000..0c845d4b --- /dev/null +++ b/atlas-modules/core/event/listener.cppm @@ -0,0 +1,40 @@ +module; + +#include +#include + +export module atlas.core.event.listener; + +export namespace atlas::event { + /** + * @brief Generic event listener of event type UEvent + * + * Listener that can have a different representation of a specific type of + * UEvent that gets specified to this listener + */ + template + class listener { + using event = std::function; + + public: + listener() = default; + + template + void subscribe(UObject* p_instance, const UCallback& p_callback) { + m_event_handlers.push_back( + [p_instance, p_callback](UEvent& p_event) { + (p_instance->*p_callback)(p_event); + }); + } + + // Notify all subscribers to this particular event listener + void notify_all(UEvent& p_event) { + for (const auto& callback : m_event_handlers) { + callback(p_event); + } + } + + private: + std::deque m_event_handlers; + }; +}; \ No newline at end of file diff --git a/atlas-modules/core/event/types.cppm b/atlas-modules/core/event/types.cppm new file mode 100644 index 00000000..d1566e74 --- /dev/null +++ b/atlas-modules/core/event/types.cppm @@ -0,0 +1,33 @@ +module; + +#include + +export module atlas.core.event.types; +namespace atlas::event { + + struct collision_enter { + uint64_t entity1; + uint64_t entity2; + }; + + struct collision_persisted { + uint64_t entity1; + uint64_t entity2; + }; + + struct collision_exit { + uint64_t entity1; + uint64_t entity2; + }; + + /** + * @brief event to trigger when to transition specific scenes + * + * @param from_scene is the current scene that is being transitioned from + * @param to_scene is the new scene that is going to be transitioned to + */ + struct scene_transition { + const void* from_scene; + const void* to_scene; + }; +}; \ No newline at end of file diff --git a/atlas-modules/core/main.cpp b/atlas-modules/core/main.cpp deleted file mode 100644 index d21db9b8..00000000 --- a/atlas-modules/core/main.cpp +++ /dev/null @@ -1,5 +0,0 @@ -#include -#include - -int main() { -} \ No newline at end of file From 8439e4e0d6f5239ddd5276286272f89d7c721016 Mon Sep 17 00:00:00 2001 From: SpinnerX Date: Mon, 12 Jan 2026 14:46:11 -0800 Subject: [PATCH 14/68] WIP -- re-added swapchain implementation --- CMakeLists.txt | 2 + atlas-modules/core/application.cppm | 1 + atlas-modules/core/utilities/types.cppm | 22 ++ atlas-modules/core/window.cppm | 6 +- atlas-modules/drivers/drivers.cppm | 1 + .../drivers/vulkan/instance_context.cppm | 9 + atlas-modules/drivers/vulkan/swapchain.cppm | 337 ++++++++++++++++++ .../drivers/vulkan/window_context.cppm | 14 +- 8 files changed, 386 insertions(+), 6 deletions(-) create mode 100644 atlas-modules/core/utilities/types.cppm create mode 100644 atlas-modules/drivers/vulkan/swapchain.cppm diff --git a/CMakeLists.txt b/CMakeLists.txt index 6d7f10f0..84f4783c 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -108,6 +108,7 @@ target_sources(${PROJECT_NAME} PUBLIC atlas-modules/atlas.cppm atlas-modules/core/api.cppm atlas-modules/core/common.cppm + atlas-modules/core/utilities/types.cppm atlas-modules/core/core.cppm atlas-modules/core/logger.cppm atlas-modules/core/application.cppm @@ -132,6 +133,7 @@ target_sources(${PROJECT_NAME} PUBLIC atlas-modules/drivers/vulkan/window_context.cppm atlas-modules/drivers/vulkan/physical_device.cppm atlas-modules/drivers/vulkan/device.cppm + atlas-modules/drivers/vulkan/swapchain.cppm ) # target_sources(${PROJECT_NAME} PUBLIC diff --git a/atlas-modules/core/application.cppm b/atlas-modules/core/application.cppm index 9a0cc8d7..f9c1e3b2 100644 --- a/atlas-modules/core/application.cppm +++ b/atlas-modules/core/application.cppm @@ -12,6 +12,7 @@ export module atlas.application; import atlas.graphics_api; import atlas.logger; +import atlas.core.utilities.types; import atlas.common; import atlas.window; import atlas.drivers; diff --git a/atlas-modules/core/utilities/types.cppm b/atlas-modules/core/utilities/types.cppm new file mode 100644 index 00000000..e62206fd --- /dev/null +++ b/atlas-modules/core/utilities/types.cppm @@ -0,0 +1,22 @@ +module; + +#include +#include +#include + +export module atlas.core.utilities.types; + + +export namespace atlas { + struct window_params { + uint32_t width; + uint32_t height; + std::string name=""; + }; + + // TODO: Move this into atlas.drivers.vulkan.utilities + struct surface_properties { + VkSurfaceCapabilitiesKHR surface_capabilities; + VkSurfaceFormatKHR surface_format; + }; +}; \ No newline at end of file diff --git a/atlas-modules/core/window.cppm b/atlas-modules/core/window.cppm index 2bcbe374..976bd069 100644 --- a/atlas-modules/core/window.cppm +++ b/atlas-modules/core/window.cppm @@ -8,13 +8,9 @@ export module atlas.window; import atlas.common; import atlas.graphics_api; +import atlas.core.utilities.types; export namespace atlas { - struct window_params { - uint32_t width; - uint32_t height; - std::string name=""; - }; class window { public: diff --git a/atlas-modules/drivers/drivers.cppm b/atlas-modules/drivers/drivers.cppm index 25a40911..0e79a89f 100644 --- a/atlas-modules/drivers/drivers.cppm +++ b/atlas-modules/drivers/drivers.cppm @@ -6,6 +6,7 @@ module; export module atlas.drivers; import atlas.common; +import atlas.core.utilities.types; // import atlas.vulkan.window_context; // import atlas.drivers.vulkan; import atlas.graphics_api; diff --git a/atlas-modules/drivers/vulkan/instance_context.cppm b/atlas-modules/drivers/vulkan/instance_context.cppm index 4d520248..ea2ffef6 100644 --- a/atlas-modules/drivers/vulkan/instance_context.cppm +++ b/atlas-modules/drivers/vulkan/instance_context.cppm @@ -210,6 +210,15 @@ namespace atlas::vulkan { s_instance->m_resources_free.push_back(p_resource); } + + static physical_device physical_driver() { + return s_instance->m_physical; + } + + static device logical_device() { + return s_instance->m_device; + } + protected: void destroy_context() override { console_log_info("destroy_context!"); diff --git a/atlas-modules/drivers/vulkan/swapchain.cppm b/atlas-modules/drivers/vulkan/swapchain.cppm new file mode 100644 index 00000000..ecdc3fc8 --- /dev/null +++ b/atlas-modules/drivers/vulkan/swapchain.cppm @@ -0,0 +1,337 @@ +module; + +#include +#include +#include + +export module atlas.drivers.vulkan.swapchain; + +import vk; + +import atlas.logger; + +import atlas.core.utilities.types; +import atlas.drivers.vulkan.instance_context; +import atlas.drivers.vulkan.physical_device; +import atlas.drivers.vulkan.device; +import atlas.drivers.vulkan.utilities; + +export namespace atlas::vulkan { + /** + * @name vk_swapchain + * @brief High-level abstraction of a vulkan swapchain + * @brief ref will return the vk_swapchain directly + * @brief ref returning vk_swapchain will need to be changed + */ + class swapchain { + public: + swapchain() = default; + + /** + * @brief Constructs a new vulkan swapchain with a window settings to + * apply to this swapchain + * @param p_surface passing in the surface handler for swapchain uses + */ + swapchain(const VkSurfaceKHR& p_surface, const window_params& p_params) : m_current_surface_handler(p_surface), m_window_params(p_params), m_current_surface(p_surface) { + m_physical = instance_context::physical_driver(); + m_driver = instance_context::logical_device(); + + create(); + + console_log_info_tagged("vulkan", "swapchain created successfully!!!"); + } + + //! @return uint32_t the next available image to present acquired + uint32_t read_acquired_image() { + m_present_to_queue.wait_idle(); + + // uint32_t frame_idx = m_present_to_queue.acquired_frame(); + uint32_t frame_idx = m_present_to_queue.acquire_next_image(); + if (m_present_to_queue.out_of_date()) { + invalidate(); + m_present_to_queue.out_of_date(false); + frame_idx = m_present_to_queue.acquire_next_image(); + } + + return frame_idx; + } + + //! @return current active command buffer being processed + [[nodiscard]] vk::command_buffer active_command(uint32_t p_frame_index) { + return m_swapchain_command_buffers[p_frame_index]; + } + + [[nodiscard]] VkFramebuffer active_framebuffer(uint32_t p_frame) const { + return m_swapchain_framebuffers[p_frame]; + } + + [[nodiscard]] VkRenderPass swapchain_renderpass() const { + return m_final_renderpass; + } + + [[nodiscard]] window_params settings() const { + return m_window_params; + } + + [[nodiscard]] uint32_t image_size() const { return m_image_size; } + + [[nodiscard]] surface_properties data() const { + return m_surface_properties; + } + + void destroy() { + vkDeviceWaitIdle(m_driver); + + for (size_t i = 0; i < m_swapchain_framebuffers.size(); i++) { + m_swapchain_framebuffers[i].destroy(); + } + + m_final_renderpass.destroy(); + + m_present_to_queue.destroy(); + + for (size_t i = 0; i < m_swapchain_command_buffers.size(); i++) { + m_swapchain_command_buffers[i].destroy(); + } + + for (uint32_t i = 0; i < m_swapchain_depth_images.size(); i++) { + m_swapchain_depth_images[i].destroy(); + } + + for (uint32_t i = 0; i < m_swapchain_images.size(); i++) { + m_swapchain_images[i].destroy(); + } + + vkDestroySwapchainKHR(m_driver, m_swapchain_handler, nullptr); + } + + void submit(std::span p_commands) { + m_present_to_queue.submit_async(p_commands); + } + + [[nodiscard]] ::vk::sample_image active_image(uint32_t p_index) const { + return m_swapchain_images[p_index]; + } + + operator VkSwapchainKHR() const { return m_swapchain_handler; } + + operator VkSwapchainKHR() { return m_swapchain_handler; } + + void present(const uint32_t& p_current_frame) { + m_present_to_queue.present_frame(p_current_frame); + if (m_present_to_queue.out_of_date()) { + invalidate(); + m_present_to_queue.out_of_date(false); + } + } + + private: + void invalidate() { + destroy(); + create(); + } + + void create() { + // surface properties are always updated from the physical device + // so they are valid should the swapchain be recreated + m_surface_properties = + m_physical.get_surface_properties(m_current_surface); + m_window_params.width = + m_surface_properties.surface_capabilities.currentExtent.width; + m_window_params.height = + m_surface_properties.surface_capabilities.currentExtent.height; + + //! @note Setting up presentation stuff + // request what our minimum image count is + uint32_t request_min_image_count = + select_images_size(m_surface_properties.surface_capabilities); + + m_swapchain_extent = + m_surface_properties.surface_capabilities.currentExtent; + + // setting our presentation properties + uint32_t present_index = + m_physical.read_presentation_index(m_current_surface_handler); + + VkSwapchainCreateInfoKHR swapchain_ci = { + .sType = VK_STRUCTURE_TYPE_SWAPCHAIN_CREATE_INFO_KHR, + .surface = m_current_surface_handler, + .minImageCount = request_min_image_count, + .imageFormat = m_surface_properties.surface_format.format, + .imageColorSpace = m_surface_properties.surface_format.colorSpace, + // use physical device surface formats to getting the right formats + // in vulkan + .imageExtent = m_swapchain_extent, + .imageArrayLayers = 1, + .imageUsage = (VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | + VK_IMAGE_USAGE_TRANSFER_DST_BIT), + .queueFamilyIndexCount = 1, + .pQueueFamilyIndices = &present_index, + .preTransform = + m_surface_properties.surface_capabilities.currentTransform, + .compositeAlpha = VK_COMPOSITE_ALPHA_OPAQUE_BIT_KHR, + .presentMode = VK_PRESENT_MODE_IMMEDIATE_KHR, + .clipped = true + }; + + vk_check(vkCreateSwapchainKHR( + m_driver, &swapchain_ci, nullptr, &m_swapchain_handler), + "vkCreateSwapchainKHR"); + + //!@brief querying images available + uint32_t image_count = 0; + vkGetSwapchainImagesKHR(m_driver, + m_swapchain_handler, + &image_count, + nullptr); // used to get the amount of images + std::vector images(image_count); + vkGetSwapchainImagesKHR(m_driver, + m_swapchain_handler, + &image_count, + images.data()); // used to store in the images + + // Creating Images + m_swapchain_images.resize(image_count); + m_image_size = image_count; + m_swapchain_depth_images.resize(image_count); + + VkFormat depth_format = m_driver.depth_format(); + + for (uint32_t i = 0; i < m_swapchain_images.size(); i++) { + ::vk::image_params color_image_config = { + .extent = { m_swapchain_extent.width, + m_swapchain_extent.height, }, + .format = m_surface_properties.surface_format.format, + .aspect = ::vk::image_aspect_flags::color_bit, + .usage = VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT, + .mip_levels = 1, + .layer_count = 1, + .phsyical_memory_properties = m_physical.memory_properties(), + + }; + + m_swapchain_images[i] = + ::vk::sample_image(m_driver, images[i], color_image_config); + + ::vk::image_params depth_image_config = { + .extent = { m_swapchain_extent.width, + m_swapchain_extent.height, }, + .format = depth_format, + .aspect = ::vk::image_aspect_flags::depth_bit, + .usage = VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT, + .mip_levels = 1, + .layer_count = 1, + .phsyical_memory_properties = m_physical.memory_properties(), + }; + + m_swapchain_depth_images[i] = + ::vk::sample_image(m_driver, depth_image_config); + } + + // command buffers + + m_swapchain_command_buffers.resize(image_count); + + for (size_t i = 0; i < m_swapchain_command_buffers.size(); i++) { + ::vk::command_params settings = { + .levels = ::vk::command_levels::primary, + // .queue_index = enumerate_swapchain_settings.present_index, + .queue_index = 0, + .flags = ::vk::command_pool_flags::reset, + }; + + m_swapchain_command_buffers[i] = + ::vk::command_buffer(m_driver, settings); + } + + std::array<::vk::attachment, 2> renderpass_attachments = { + ::vk::attachment{ + .format = m_surface_properties.surface_format.format, + .layout = ::vk::image_layout::color_optimal, + .samples = ::vk::sample_bit::count_1, + .load = ::vk::attachment_load::clear, + .store = ::vk::attachment_store::store, + .stencil_load = ::vk::attachment_load::clear, + .stencil_store = ::vk::attachment_store::dont_care, + .initial_layout = ::vk::image_layout::undefined, + .final_layout = ::vk::image_layout::present_src_khr, + }, + ::vk::attachment{ + .format = depth_format, + .layout = ::vk::image_layout::depth_stencil_optimal, + .samples = ::vk::sample_bit::count_1, + .load = ::vk::attachment_load::clear, + .store = ::vk::attachment_store::dont_care, + .stencil_load = ::vk::attachment_load::dont_care, + .stencil_store = ::vk::attachment_store::dont_care, + .initial_layout = ::vk::image_layout::undefined, + .final_layout = ::vk::image_layout::depth_stencil_optimal, + }, + }; + m_final_renderpass = ::vk::renderpass(m_driver, renderpass_attachments); + + // creating framebuffers + m_swapchain_framebuffers.resize(m_swapchain_images.size()); + + for (uint32_t i = 0; i < m_swapchain_images.size(); i++) { + + std::array + image_attachments = { m_swapchain_images[i].image_view(), + m_swapchain_depth_images[i].image_view() }; + + vk::framebuffer_params framebuffer_info = { + .renderpass = m_final_renderpass, + .views = image_attachments, + .extent = m_swapchain_extent + }; + m_swapchain_framebuffers[i] = + vk::framebuffer(m_driver, framebuffer_info); + } + + vk::queue_params present_queue_params{ + .family = 0, + .index = 0, + }; + m_present_to_queue = ::vk::device_present_queue( + m_driver, m_swapchain_handler, present_queue_params); + } + + uint32_t select_images_size(const VkSurfaceCapabilitiesKHR& p_surface_capabilities) { + uint32_t requested_images = p_surface_capabilities.minImageCount + 1; + uint32_t final_image_count = 0; + + if ((p_surface_capabilities.maxImageCount > 0) and + (requested_images > p_surface_capabilities.maxImageCount)) { + final_image_count = p_surface_capabilities.maxImageCount; + } + else { + final_image_count = requested_images; + } + + return final_image_count; + } + + private: + physical_device m_physical{}; + device m_driver{}; + VkSurfaceKHR m_current_surface_handler = nullptr; + VkSwapchainKHR m_swapchain_handler = nullptr; + VkExtent2D m_swapchain_extent{}; + window_params m_window_params{}; + + uint32_t m_image_size = 0; + + VkSurfaceKHR m_current_surface = nullptr; + surface_properties m_surface_properties{}; + std::vector m_swapchain_command_buffers{}; + std::vector m_swapchain_framebuffers; + + //! @brief setting up images + std::vector m_swapchain_images; + std::vector m_swapchain_depth_images; + + vk::renderpass m_final_renderpass; + + vk::device_present_queue m_present_to_queue; + }; +}; \ No newline at end of file diff --git a/atlas-modules/drivers/vulkan/window_context.cppm b/atlas-modules/drivers/vulkan/window_context.cppm index 19c349bc..a8e52632 100644 --- a/atlas-modules/drivers/vulkan/window_context.cppm +++ b/atlas-modules/drivers/vulkan/window_context.cppm @@ -20,6 +20,9 @@ import atlas.window; import atlas.logger; import atlas.drivers.vulkan.instance_context; import atlas.drivers.vulkan.utilities; +import atlas.core.utilities.types; + +import atlas.drivers.vulkan.swapchain; export namespace atlas { namespace vulkan { @@ -55,6 +58,13 @@ export namespace atlas { "glfwCreateWindowSurface"); center_window(); + + m_window_swapchain = swapchain(m_window_surface, m_params); + + instance_context::submit_resource_free([this](){ + console_log_info("vulkan::window_context submit_resource_free invokation!"); + m_window_swapchain.destroy(); + }); } virtual ~window_context() { @@ -75,10 +85,11 @@ export namespace atlas { } [[nodiscard]] uint32_t read_acquired_next_frame() override { - return 0; + return m_window_swapchain.read_acquired_image(); } void present_frame(const uint32_t& p_current_frame) override { + m_window_swapchain.present(p_current_frame); } private: @@ -95,6 +106,7 @@ export namespace atlas { VkSurfaceKHR m_window_surface=nullptr; window_params m_params; VkInstance m_instance=nullptr; + swapchain m_window_swapchain; }; }; }; \ No newline at end of file From 786a0b356d850d45855b4a4a68665662f6db6841 Mon Sep 17 00:00:00 2001 From: SpinnerX Date: Mon, 12 Jan 2026 15:05:37 -0800 Subject: [PATCH 15/68] WIP -- finishing up swapchain and window_context implementation --- atlas-modules/core/application.cppm | 11 +++++++++++ atlas-modules/core/window.cppm | 18 ++++++++++-------- atlas-modules/drivers/vulkan/swapchain.cppm | 5 +++-- .../drivers/vulkan/window_context.cppm | 9 +++++++++ 4 files changed, 33 insertions(+), 10 deletions(-) diff --git a/atlas-modules/core/application.cppm b/atlas-modules/core/application.cppm index f9c1e3b2..f8f41992 100644 --- a/atlas-modules/core/application.cppm +++ b/atlas-modules/core/application.cppm @@ -7,6 +7,7 @@ module; #include #include #include +#include export module atlas.application; @@ -18,6 +19,7 @@ import atlas.window; import atlas.drivers; import atlas.core.event; import atlas.core.utilities.poll_state; +import atlas.logger; export namespace atlas { @@ -80,13 +82,22 @@ export namespace atlas { void execute() { console_log_info("Executing game mainloop!!!"); + auto start_time = std::chrono::high_resolution_clock::now(); invoke_start(); while(m_window->available()) { + auto current_time = std::chrono::high_resolution_clock::now(); + m_delta_time = std::chrono::duration(current_time - start_time).count(); + start_time = current_time; + event::flush_events(); + // m_current_frame_index = m_window->acquired_next_frame(); + + console_log_info("current_frame = {}", m_current_frame_index); + invoke_on_update(); invoke_physics_update(); diff --git a/atlas-modules/core/window.cppm b/atlas-modules/core/window.cppm index 976bd069..2e007be2 100644 --- a/atlas-modules/core/window.cppm +++ b/atlas-modules/core/window.cppm @@ -9,6 +9,8 @@ export module atlas.window; import atlas.common; import atlas.graphics_api; import atlas.core.utilities.types; +import atlas.drivers.vulkan.swapchain; +import vk; export namespace atlas { @@ -47,9 +49,9 @@ export namespace atlas { /** * @brief Returns the window's currently selected swapchain */ - // [[nodiscard]] vk::vk_swapchain current_swapchain() const { - // return window_swapchain(); - // } + [[nodiscard]] vulkan::swapchain current_swapchain() const { + return window_swapchain(); + } /** * @brief retrieves the current command buffer using the current frame @@ -58,9 +60,9 @@ export namespace atlas { * * @return command buffer to actively record commands to */ - // ::vk::command_buffer active_command(uint32_t p_frame_index) { - // return current_active_command(p_frame_index); - // } + vk::command_buffer active_command(uint32_t p_frame_index) { + return current_active_command(p_frame_index); + } /** * @brief operator overload for treating atlas::window as a GLFWwindow @@ -96,9 +98,9 @@ export namespace atlas { [[nodiscard]] virtual window_params get_params() const = 0; [[nodiscard]] virtual GLFWwindow* native_window() const = 0; [[nodiscard]] virtual uint32_t read_acquired_next_frame() = 0; - // [[nodiscard]] virtual vk::vk_swapchain window_swapchain() const = 0; + [[nodiscard]] virtual vulkan::swapchain window_swapchain() const = 0; - // [[nodiscard]] virtual ::vk::command_buffer current_active_command(uint32_t p_frame_idx) = 0; + [[nodiscard]] virtual vk::command_buffer current_active_command(uint32_t p_frame_idx) = 0; virtual void present_frame(const uint32_t& p_current_frame) = 0; }; diff --git a/atlas-modules/drivers/vulkan/swapchain.cppm b/atlas-modules/drivers/vulkan/swapchain.cppm index ecdc3fc8..bdf08ae9 100644 --- a/atlas-modules/drivers/vulkan/swapchain.cppm +++ b/atlas-modules/drivers/vulkan/swapchain.cppm @@ -292,8 +292,9 @@ export namespace atlas::vulkan { .family = 0, .index = 0, }; - m_present_to_queue = ::vk::device_present_queue( - m_driver, m_swapchain_handler, present_queue_params); + m_present_to_queue = ::vk::device_present_queue(m_driver, m_swapchain_handler, present_queue_params); + console_log_info("m_present_to_queue initialized!!!"); + console_log_info("m_presesnt_to_queue.alive() = {}", (m_present_to_queue != nullptr)); } uint32_t select_images_size(const VkSurfaceCapabilitiesKHR& p_surface_capabilities) { diff --git a/atlas-modules/drivers/vulkan/window_context.cppm b/atlas-modules/drivers/vulkan/window_context.cppm index a8e52632..b5d07e32 100644 --- a/atlas-modules/drivers/vulkan/window_context.cppm +++ b/atlas-modules/drivers/vulkan/window_context.cppm @@ -23,6 +23,7 @@ import atlas.drivers.vulkan.utilities; import atlas.core.utilities.types; import atlas.drivers.vulkan.swapchain; +import vk; export namespace atlas { namespace vulkan { @@ -88,6 +89,14 @@ export namespace atlas { return m_window_swapchain.read_acquired_image(); } + [[nodiscard]] vulkan::swapchain window_swapchain() const override{ + return m_window_swapchain; + } + + [[nodiscard]] vk::command_buffer current_active_command(uint32_t p_frame_idx) override { + return m_window_swapchain.active_command(p_frame_idx); + } + void present_frame(const uint32_t& p_current_frame) override { m_window_swapchain.present(p_current_frame); } From 8c915d9478812abc61af0a9299aac1ca1aad6213 Mon Sep 17 00:00:00 2001 From: SpinnerX Date: Mon, 12 Jan 2026 15:27:59 -0800 Subject: [PATCH 16/68] WIP -- re-added math functions, and the scene system --- CMakeLists.txt | 7 + atlas-modules/core/event/bus.cppm | 2 +- atlas-modules/core/math/math.cppm | 86 ++++++++++ atlas-modules/core/scene/components.cppm | 129 +++++++++++++++ atlas-modules/core/scene/game_object.cppm | 95 +++++++++++ atlas-modules/core/scene/scene.cppm | 182 ++++++++++++++++++++++ atlas-modules/core/scene/world.cppm | 81 ++++++++++ 7 files changed, 581 insertions(+), 1 deletion(-) create mode 100644 atlas-modules/core/math/math.cppm create mode 100644 atlas-modules/core/scene/components.cppm create mode 100644 atlas-modules/core/scene/game_object.cppm create mode 100644 atlas-modules/core/scene/scene.cppm create mode 100644 atlas-modules/core/scene/world.cppm diff --git a/CMakeLists.txt b/CMakeLists.txt index 84f4783c..e6c25fef 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -114,6 +114,13 @@ target_sources(${PROJECT_NAME} PUBLIC atlas-modules/core/application.cppm atlas-modules/core/window.cppm + atlas-modules/core/math/math.cppm + + atlas-modules/core/scene/components.cppm + atlas-modules/core/scene/game_object.cppm + atlas-modules/core/scene/scene.cppm + atlas-modules/core/scene/world.cppm + atlas-modules/core/utilities/state.cppm atlas-modules/core/utilities/poll_state.cppm diff --git a/atlas-modules/core/event/bus.cppm b/atlas-modules/core/event/bus.cppm index 8e15d61a..f5aa4311 100644 --- a/atlas-modules/core/event/bus.cppm +++ b/atlas-modules/core/event/bus.cppm @@ -10,7 +10,7 @@ export module atlas.core.event.bus; import atlas.core.event.listener; -namespace atlas::event { +export namespace atlas::event { /** * @brief Event bus that holds the responsibility to reroute events to the * subscribers of those particular event. diff --git a/atlas-modules/core/math/math.cppm b/atlas-modules/core/math/math.cppm new file mode 100644 index 00000000..dcd61daf --- /dev/null +++ b/atlas-modules/core/math/math.cppm @@ -0,0 +1,86 @@ +module; + +#define GLM_ENABLE_EXPERIMENTAL +#include + +export module atlas.core.math; + +export namespace atlas { + + //! @brief converts vec4 to quaterion + glm::quat to_quat(const glm::vec4& p_values) { + return glm::quat({ + p_values.w, + p_values.x, + p_values.y, + p_values.z, + }); + } + + //! @brief converts vec3 to quaterion + glm::highp_vec4 from_quat(const glm::vec3& p_values) { + // converts glm::vec3 rotation to a quaternion returning the + // quaternion-converted values to glm::highp_vec4 + auto quaternion = glm::quat(p_values); + return glm::vec4( + { quaternion.x, quaternion.y, quaternion.z, quaternion.w }); + } + + //! @brief converts glm::vec3 to glm::vec4 + glm::quat to_quat(const glm::vec3& p_values) { + return glm::quat(p_values); + } + + glm::quat to_quathp(const glm::highp_vec4& p_values) { + return glm::quat({ + p_values.w, + p_values.x, + p_values.y, + p_values.z, + }); + } + + namespace math { + //! @brief shorthand for glm::vec3(0.f, 0.f, 0.f) + glm::vec3 zeroes() { + return glm::vec3(0.f); + } + + //! @brief shorthand for glm::vec3(1.f, 1.f, 1.f) + glm::vec3 ones() { + return glm::vec3(1.f); + } + + //! @brief rotation equivalent of a zero-vector + // sets to glm::quat(1.f, 0.f, 0.f, 0.f) + glm::quat identity() { + return glm::quat_identity(); + } + + //! @brief shorthand for glm::vec3(0.f, 0.f, 1.f) + glm::vec3 forward() { + return glm::vec3(0.f, 0.f, 1.f); + } + + //! @brief shorthand for glm::vec3(0.f, 0.f, -1.f) + glm::vec3 backward() { + return glm::vec3(0.f, 0.f, -1.f); + } + + //! @brief shorthand for glm::vec3(1.f, 0.f, 0.f) + glm::vec3 right(); + + //! @brief shorthand for glm::vec3(-1.f, 0.f, 0.f) + glm::vec3 left(); + + //! @brief shorthand for glm::vec3(0.f, 1.f, 0.f) + glm::vec3 up() { + return glm::vec3(0.f, 1.f, 0.f); + } + + //! @brief shorthand for glm::vec3(0.f, -1.f, 0.f) + glm::vec3 down() { + return glm::vec3(0.f, -1.f, 0.f); + } + } +}; \ No newline at end of file diff --git a/atlas-modules/core/scene/components.cppm b/atlas-modules/core/scene/components.cppm new file mode 100644 index 00000000..1b21a647 --- /dev/null +++ b/atlas-modules/core/scene/components.cppm @@ -0,0 +1,129 @@ +module; + +#include +#include +#include +#include + + +export module atlas.core.scene.components; + +import atlas.core.math; + +export namespace atlas { + + struct transform { + glm::highp_vec3 position{ 0.f }; + glm::highp_vec4 quaternion{ 0.f, 0, 0, 1 }; + glm::highp_vec3 rotation{ 0.f }; + glm::highp_vec3 scale{ 1.f }; + + //! @brief sets rotation and automatically converts rotation glm::vec3 + //! to quaternion + void set_rotation(const glm::highp_vec3& p_value) { + rotation = p_value; + quaternion = from_quat(rotation); + } + }; + + struct material_metadata { + glm::vec4 ambient{ 0.2f }; + glm::vec4 diffuse{ 0.5f }; + glm::vec4 specular{ 1.f }; + float shininess = 0.5f; + }; + struct directional_light { + glm::vec3 direction{ 0.f }; + glm::vec3 view_position{ 0.f }; + // {x, y, z, w: intensity} + glm::vec4 ambient{ 1.f }; + glm::vec4 diffuse{ 1.f }; + // {x, y, z, w: intensity} + glm::vec4 specular{ 1.f, 1.f, 0.f, 0.f }; + glm::vec4 color{ 1.f }; + }; + + struct point_light { + glm::vec3 position; // this is provided by the transform + glm::vec4 color = { 1.f, 1.f, 1.f, 1.f }; + float attenuation = 1.f; + float constant = 1.f; + float linear = 1.f; + float quadratic = 1.f; + + glm::vec4 ambient = glm::vec4(1.f); + glm::vec4 diffuse = glm::vec4(1.f); + glm::vec4 specular = glm::vec4(1.f); + }; + + /** + * @brief Loads a mesh source + * + * @param color is the albedo color values + * @param model_path is the specified path to the 3d model asset path + * @param texture_path is the specified path to the specific texture to load + */ + struct mesh_source { + bool flip = false; // this is for flipping the texture coordinates + glm::vec4 color{ 1.f }; + std::string model_path = ""; + std::string diffuse = ""; + std::string specular = ""; + }; + + /** + * @brief define a game object to have a perspective camera that can + * correspond to it + */ + struct perspective_camera { + // represented as {near: x, far: y} + glm::vec2 plane{ 0.f }; + + // Activate to be the current camera + bool is_active = false; + + // Defaults to 45.0f in radians + float field_of_view = glm::radians(45.f); + }; + + /** + * @brief specialized namespace tag to use for specifying operations used + * with flecs in using tags + * + * Tags can be handled for specifying queries for specific archetypes (list + * of those entities) + * + * Example Usage: + * + * ```C++ + * m_entity.add>(); + * ``` + */ + namespace tag { + + //! @brief to indicate which entities are editor-only + struct editor {}; + + //! @brief to tag entities to serialize through the serializer + struct serialize { + bool enable = false; + }; + }; + + //! TODO: Consider either relocating where this is and how it gets handled. + + /** + * @brief struct for attaching a projection/view matrix to your game object + * + * This should only be used if you know your object is going to add + * atlas::perspective_camera to work + * + * TODO: Consider adding this automatically in a way we can represent + * multiple cameras in a given scene. Which is something to think about + */ + struct projection_view { + glm::mat4 projection; + glm::mat4 view; + }; + +}; // namespace atlas \ No newline at end of file diff --git a/atlas-modules/core/scene/game_object.cppm b/atlas-modules/core/scene/game_object.cppm new file mode 100644 index 00000000..5d32cab8 --- /dev/null +++ b/atlas-modules/core/scene/game_object.cppm @@ -0,0 +1,95 @@ +module; + +#include +#include + +export module atlas.core.scene.game_object; +import atlas.core.scene.components; + +export namespace atlas { + /** + * @brief Creates a pointer wrapper which extends capabilities of + * flecs::entity + * + * Provides our own construct of API's that handles any workload around some + * of the raw flecs API's that can still be used by other flecs API's + * without completely interacting touching raw flecs API + */ + class game_object : public flecs::entity { + public: + //! @brief Should not construct a scene object not created through + //! flecs::world + game_object() = delete; + + game_object(flecs::world_t* p_registry, flecs::entity_t p_id) : flecs::entity(p_registry, p_id) { + add(); + } + + game_object(const flecs::entity& p_base) : flecs::entity(p_base) { + add(); + } + + explicit game_object(flecs::entity& p_base) : flecs::entity(p_base) { + add(); + } + + /** + * @brief sets the entity to be a parent of the specified entity + * + * @param p_entity is the specified entity to specify as the parent. + * + * + * Example Usage: + * + * ```C++ + * + * atlas::game_object obj1 = entity("Parent"); + * + * atlas::game_object obj2 = entity("Chlid"); + * + * // obj2 is the child of obj1 + * // As obj1 is a parent node + * obj2.child_of(obj1); + * + * ``` + * + */ + void child_of(const std::optional& p_parent) { + add(flecs::ChildOf, p_parent.value()); + } + + /** + * @brief iterates through all children entities if the given entity is + * a parent of any given entities + * + * Example Usage: + * + * + * ```C++ + * atlas::game_object obj1 = entity("Parent Node"); + * atlas::game_object obj2 = entity("Chlid Node"); + * + * // obj1 is the parent of obj2. + * obj2.child_of(parent); + * + * // iteration should only include for "Child Node" + * obj1.children([](flecs::entity p_child){ + * // do stuff with the child entity + * }); + * + * ``` + */ + template + void children(UFunction&& p_callback) { + children(p_callback); + } + }; + + /** + * @brief Alias to std::optional + * + * This alias serves as a representation of game objects users can create + * and manage components with + */ + using game_object_optional = std::optional; +}; \ No newline at end of file diff --git a/atlas-modules/core/scene/scene.cppm b/atlas-modules/core/scene/scene.cppm new file mode 100644 index 00000000..a2957ed1 --- /dev/null +++ b/atlas-modules/core/scene/scene.cppm @@ -0,0 +1,182 @@ +module; + +#include +#include + +export module atlas.core.scene; + +import atlas.common; +import atlas.core.event.bus; +import atlas.core.scene.game_object; + + + +export namespace atlas { + /** + * @brief Constructs a scene that defines an area where game objects are + * part of contained within an atlas::world + * + * Scenes are fundamentally building blocks that a game object may reside + * in. Composing of variety of properties such as sky lights, game objects, + * cameras, etc. + * + * Which can represent corresponding resources that can be related to + * specific levels/scenes. + * + * Scenes are apart of another container referred to as the world which + * helps manages these scenes and consider them as contexts that can be + * switched/toggled based on users transforms. + */ + class scene { + public: + /** + * @param p_name is the name given to this scene + * @param p_bus is the globalized event bus that is given access to the + * scene to subscribe events to it. + */ + scene(const std::string& p_name, event::bus& p_bus) : m_name(p_name), m_bus(&p_bus) { + } + + virtual ~scene() = default; + + /** + * @brief Retrieves if an entity already exists within the registry, + * create new entity otherwise + * + * @param p_name is a string to set the name of the entity + */ + game_object entity(std::string_view p_name) { + return game_object(m_registry.entity(p_name.data())); + } + + /** + * @brief Retrieves if an entity already exists within the registry, + * create new entity otherwise + * + * @param p_entity_id is the ID to retrieve an entity if it exists, + * otherwise returns a new entity. + */ + game_object entity(uint64_t p_id) { + return game_object(m_registry.entity(p_id)); + } + + /** + * @brief subscribes an event to the event::bus to get invoked when + * publishers notify all subscribers when an update is incoming + * + * @tparam UEventType + * @tparam UObject + * @tparam UCallback + * @param p_instance is the object instance to specify where the + * callback belongs to + * @param p_callback is the callback that contains an arbitrary task + * that gets invoked when incoming updates occur from the publisher + * + */ + template + void subscribe(UObject* p_instance, const UCallback& p_callback) { + m_bus->subscribe(p_instance, p_callback); + } + + /** + * @brief queries components, returning entities (game objects) that + * contain those components queried with. + * + * Queries are a feature flecs allows us to do. Which query component + * parameters and gives us archetypes back. + * + * Archetypes are list of entities that contain those list of parameters + * + * @tparam ...Comps + * @tparam ...Args + * @param ... args + * @return flecs::query_builder + * + * Example Usage: + * ```C++ + * auto query_physics = query_builder().build(); + * + * query_physics.each([](flecs::entity, atlas::transform&, + * atlas::physics_body&){ + * // do stuff + * }); + * ``` + */ + template + flecs::query_builder query_builder(Args&&... args) const { + return flecs::query_builder(m_registry, + std::forward(args)...); + } + + /** + * @return the number of children entities + * + * Example Usage: + * + * + * ```C++ + * + * atlas::scene scene("New Scene"); + * + * // creating obj1 (parent) and obj2 (child) + * atlas::game_object obj1 = scene.create("Parent"); + * + * atlas::game_object obj2 = scene.create("Chlid"); + * + * // obj2 is the child of obj1 + * // As obj1 is a parent node + * + * obj2.child_of(obj1); + * + * // Returns 1 + * uint32_t obj1_children = scene.children_count(obj1); + * + * ``` + */ + uint32_t children_count(const game_object& p_parent) { + return query_builder().with(flecs::ChildOf, p_parent).build().count(); + } + + /** + * @brief Defer operations until end of frame. + * When this operation is invoked while iterating, operations + * inbetween the defer_begin() and defer_end() operations are executed + * at the end of the frame. + * + * This operation is thread safe. + * + * @return true if world changed from non-deferred mode to deferred + * mode. + */ + bool defer_begin() { return m_registry.defer_begin(); } + + /** + * End block of operations to defer. + * See defer_begin(). + * + * This operation is thread safe. + * + * @return true if world changed from deferred mode to non-deferred + * mode. + */ + bool defer_end() { return m_registry.defer_end(); } + + //! @return the name of the scene + [[nodiscard]] std::string name() const { return m_name; } + + //! @return the event::bus handle for subscribing events + [[nodiscard]] event::bus* event_handle() const { return m_bus; } + + /** + * @brief Requires to return flecs::world is returned by reference to + * prevent making copies of flecs::world + */ + operator flecs::world&() { return m_registry; } + + private: + flecs::world m_registry; + std::string m_name; + event::bus* m_bus = nullptr; + }; +}; \ No newline at end of file diff --git a/atlas-modules/core/scene/world.cppm b/atlas-modules/core/scene/world.cppm new file mode 100644 index 00000000..f61278e1 --- /dev/null +++ b/atlas-modules/core/scene/world.cppm @@ -0,0 +1,81 @@ +module; + +#include +#include +#include +#include + + +export module atlas.core.scene.world; + +import atlas.common; +import atlas.core.scene; + +namespace atlas { + /** + * @brief world represents a larger scope of areas that manages the scene + * contexts + * + * The world is responsible for providing a self-containment of scenes and + * managing which scenes are current. Based on current scenes are details + * the world can know about. + * + * Details such as through player transform or navigation that can be done + * through the world, providing useful information on where a game object in + * those scenes/levels. + * + * The world responsibility act as the based container of any scene that can + * be created by the user through editor. + * + * + */ + class world { + public: + world() = delete; + + /** + * @brief construct a new world with a specified name associated + * with it + */ + world(const std::string& p_name) : m_name(p_name) { + } + + virtual ~world() = default; + + //! @return the name of world + [[nodiscard]] std::string name() const { return m_name; } + + /** + * @brief Creating a scene, then we add that scene onto this world + * + * @warning TODO: This is not how we want to currently create and add + * scenes as this is quite problematic. Should direct attention to this + * soon. + */ + void add_scene(const ref& p_scene_context) { + m_scene_container.emplace(p_scene_context->name(), p_scene_context); + } + + /** + * @brief get_scene allows for specifically querying for current scenes + * + * TODO: Eventually this is going to be something defined whether its + * through the player's navigation system for the world to track where + * the player is in within the world, then provide the current scene + * based on that information + */ + ref get_scene(const std::string& p_tag) { + if (!m_scene_container.contains(p_tag)) { + throw std::runtime_error( + "Could not access ref from " + "world::get_scene(const string& p_tag)!!!"); + } + return m_scene_container[p_tag]; + } + + private: + std::map> m_scene_container; + ref m_world_shared_instance; + std::string m_name = "Undefined Tag"; + }; +}; \ No newline at end of file From 005be81bc159150c7120577fedcd28236f60fff5 Mon Sep 17 00:00:00 2001 From: SpinnerX Date: Mon, 12 Jan 2026 21:53:43 -0800 Subject: [PATCH 17/68] WIP -- re-added the vulkan implementation-specific renderer back with modules applied --- CMakeLists.txt | 9 + atlas-modules/drivers/renderer_system.cppm | 94 +++ atlas-modules/drivers/vulkan/hash.cppm | 41 ++ atlas-modules/drivers/vulkan/mesh.cppm | 254 +++++++ .../drivers/vulkan/render_system.cppm | 635 ++++++++++++++++++ .../drivers/vulkan/shader_resource_group.cppm | 418 ++++++++++++ atlas-modules/drivers/vulkan/uniforms.cppm | 76 +++ atlas-modules/renderer/renderer.cppm | 24 + 8 files changed, 1551 insertions(+) create mode 100644 atlas-modules/drivers/renderer_system.cppm create mode 100644 atlas-modules/drivers/vulkan/hash.cppm create mode 100644 atlas-modules/drivers/vulkan/mesh.cppm create mode 100644 atlas-modules/drivers/vulkan/render_system.cppm create mode 100644 atlas-modules/drivers/vulkan/shader_resource_group.cppm create mode 100644 atlas-modules/drivers/vulkan/uniforms.cppm create mode 100644 atlas-modules/renderer/renderer.cppm diff --git a/CMakeLists.txt b/CMakeLists.txt index e6c25fef..abce8f14 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -130,10 +130,19 @@ target_sources(${PROJECT_NAME} PUBLIC atlas-modules/core/event/keys.cppm atlas-modules/core/event/mouse_codes.cppm atlas-modules/core/event/joystick_codes.cppm + + atlas-modules/renderer/renderer.cppm atlas-modules/drivers/drivers.cppm atlas-modules/drivers/graphics_context.cppm + atlas-modules/drivers/renderer_system.cppm + atlas-modules/drivers/vulkan/hash.cppm + atlas-modules/drivers/vulkan/mesh.cppm + atlas-modules/drivers/vulkan/shader_resource_group.cppm + atlas-modules/drivers/vulkan/render_system.cppm + atlas-modules/drivers/vulkan/uniforms.cppm + atlas-modules/drivers/vulkan/vulkan.cppm atlas-modules/drivers/vulkan/utilities.cppm atlas-modules/drivers/vulkan/instance_context.cppm diff --git a/atlas-modules/drivers/renderer_system.cppm b/atlas-modules/drivers/renderer_system.cppm new file mode 100644 index 00000000..f5b93b79 --- /dev/null +++ b/atlas-modules/drivers/renderer_system.cppm @@ -0,0 +1,94 @@ +module; + +#include +#include +#include + +export module atlas.drivers.renderer_system; + +import vk; +import atlas.core.utilities.types; +import atlas.common; +import atlas.core.scene; + +export namespace atlas { + /** + * @brief is an interface that defines a graphics APi-agnostic renderer + * + * This context allows for communication from the the internal engine logic + * to API-agnostic implementation of the renderers. + * + * This class is at the renderer-level of configurations. That relies on + * atlas::graphics_context for setting up the agnostic-graphics API's + * directly + */ + class renderer_system { + public: + virtual ~renderer_system() = default; + + /** + * @brief responsibility is to preload any data that is necessary to be + * loaded before being rendered + */ + void preload(const VkRenderPass& p_renderpass) { + return preload_assets(p_renderpass); + } + + /** + * @brief indicator of when the start of the frame is + * + * Semantically is used to indicate this is when we start recording + * operations to the GPU + * + * @param p_current is the current command buffer for recording + * @param p_settings is the current window settings that are currently + * applied + * @param p_renderpass is the main renderpass for doing the rendering + * operations + * @param p_framebuffer is the framebuffer handle required and passed to + * the renderpass + * @param p_proj_view is the (proj * view) camera matrices that is used + * by the game objects being rendered and passed as a shader uniform + */ + void begin_frame(const vk::command_buffer& p_current, + const window_params& p_params, + const VkRenderPass& p_renderpass, + const VkFramebuffer& p_framebuffer, + const glm::mat4& p_proj_view) { + return start_frame( + p_current, p_params, p_renderpass, p_framebuffer, p_proj_view); + } + + /** + * @brief Intended to use to indicate when to end recording to the GPU + * in the current frame + */ + void end_frame() { return post_frame(); } + + /** + * @brief sets the background color and request that change to the + * graphics API + */ + void set_background_color(const std::array& p_color) { + return background_color(p_color); + } + + void current_scene_context(ref p_scene) { + return current_scene(std::move(p_scene)); + } + + private: + virtual void preload_assets(const VkRenderPass& p_renderpass) = 0; + + virtual void start_frame(const vk::command_buffer& p_current, + const window_params& p_params, + const VkRenderPass& p_renderpass, + const VkFramebuffer& p_framebuffer, + const glm::mat4& p_proj_view) = 0; + virtual void post_frame() = 0; + + virtual void background_color(const std::array& p_color) = 0; + + virtual void current_scene(ref) = 0; + }; +}; \ No newline at end of file diff --git a/atlas-modules/drivers/vulkan/hash.cppm b/atlas-modules/drivers/vulkan/hash.cppm new file mode 100644 index 00000000..20435c12 --- /dev/null +++ b/atlas-modules/drivers/vulkan/hash.cppm @@ -0,0 +1,41 @@ +module; + +#define GLM_ENABLE_EXPERIMENTAL +#include + +export module atlas.drivers.vulkan.hash; + +import vk; + +export namespace atlas { + template + void hash_combine(size_t& seed, const T& v, const Rest&... rest) { + seed ^= std::hash()(v) + 0x9e3779b9 + (seed << 6) + (seed << 2); + (hash_combine(seed, rest), ...); + } + +}; + +export namespace std { + + // template<> + // struct hash { + // size_t operator()(const atlas::vk::vertex_input& vertex) const { + // size_t seed = 0; + // atlas::hash_combine( + // seed, vertex.position, vertex.color, vertex.normals, + // vertex.uv); + // return seed; + // } + // }; + template<> + struct hash { + size_t operator()(const vk::vertex_input& vertex) const { + size_t seed = 0; + atlas::hash_combine( + seed, vertex.position, vertex.color, vertex.normals, vertex.uv); + return seed; + } + }; + +} \ No newline at end of file diff --git a/atlas-modules/drivers/vulkan/mesh.cppm b/atlas-modules/drivers/vulkan/mesh.cppm new file mode 100644 index 00000000..e473e8ba --- /dev/null +++ b/atlas-modules/drivers/vulkan/mesh.cppm @@ -0,0 +1,254 @@ +module; + +#include +#include +#define STB_IMAGE_IMPLEMENTATION +#define STB_IMAGE_WRITE_IMPLEMENTATION +#include +#include +#include +#include + +export module atlas.drivers.vulkan.mesh; +import vk; + +import atlas.logger; +import atlas.drivers.vulkan.instance_context; +import atlas.drivers.vulkan.physical_device; +import atlas.drivers.vulkan.device; +import atlas.drivers.vulkan.hash; + + +export namespace atlas::vulkan { + /** + * @brief mesh class specifically defined with vulkan implementations for + * specific primitives + * TODO: Whenever we load in a texture that will be laucnhed asyncronously + * + * @brief mesh class will contain metadata needed by vulkan specifications + * Ways to communicate through vulkan by only supplying information needed + * to update this mesh + * + * @brief Represents a renderable object -- supporting various material + * types, etc + * TODO - For now we have a map, this should + * be expanded to a proper material system for blending various materials + */ + class mesh { + public: + mesh() = default; + mesh(std::span p_vertices, std::span p_indices) { + m_physical = instance_context::physical_driver(); + m_device = instance_context::logical_device(); + + vk::vertex_params vbo_settings = { .phsyical_memory_properties = + m_physical.memory_properties(), + .vertices = p_vertices }; + vk::index_params ibo_settings = { .phsyical_memory_properties = + m_physical.memory_properties(), + .indices = p_indices }; + m_vbo = vk::vertex_buffer(m_device, vbo_settings); + m_ibo = vk::index_buffer(m_device, ibo_settings); + } + + mesh(const std::filesystem::path& p_filename, bool p_flip = false) { + m_physical = instance_context::physical_driver(); + m_device = instance_context::logical_device(); + reload_mesh(p_filename); + } + + //! @brief Reload mesh vertices and indices when requested + void reload_mesh(const std::filesystem::path& p_filename) { + load_obj(p_filename); + } + + void draw(const VkCommandBuffer& p_command_buffer) { + m_vbo.bind(p_command_buffer); + if (m_ibo.size() > 0) { + m_ibo.bind(p_command_buffer); + vkCmdDrawIndexed(p_command_buffer, m_ibo.size(), 1, 0, 0, 0); + } + else { + vkCmdDraw(p_command_buffer, m_vbo.size(), 1, 0, 0); + } + } + + void destroy() { + m_vbo.destroy(); + m_ibo.destroy(); + + m_diffuse.destroy(); + m_specular.destroy(); + m_geoemtry_ubo.destroy(); + m_material_ubo.destroy(); + } + + //! @brief Loading single texture with specified std::filesystem::path + void add_diffuse(const std::filesystem::path& p_path) { + ::vk::texture_info config_texture = { + .phsyical_memory_properties = m_physical.memory_properties(), + .filepath = p_path, + }; + m_diffuse = ::vk::texture(m_device, config_texture); + + if (!m_diffuse.loaded()) { + console_log_info("Diffuse Texture {} is NOT loaded!!!", + p_path.string()); + return; + } + } + + void add_specular(const std::filesystem::path& p_path) { + vk::texture_info config_texture = { + .phsyical_memory_properties = m_physical.memory_properties(), + .filepath = p_path, + }; + m_specular = vk::texture(m_device, config_texture); + + if (!m_specular.loaded()) { + console_log_error("Specular Texture {} is NOT loaded!!!", + p_path.string()); + return; + } + } + + [[nodiscard]] ::vk::sample_image diffuse() const { + return m_diffuse.image(); + } + [[nodiscard]] ::vk::sample_image specular() const { + return m_specular.image(); + } + + //! @return true if mesh geometry model loaded succesfully + [[nodiscard]] bool loaded() const { return m_model_loaded; } + + [[nodiscard]] bool diffuse_loaded() const { return m_diffuse.loaded(); } + + [[nodiscard]] bool specular_loaded() const { + return m_specular.loaded(); + } + + void set_flip(bool p_flip) { m_flip = p_flip; } + + private: + void load_obj(const std::filesystem::path& p_filename) { + tinyobj::attrib_t attrib; + std::vector shapes; + std::vector materials; + std::string warn, err; + + //! @note If we return the constructor then we can check if the mesh + //! loaded successfully + //! @note We also receive hints if the loading is successful! + //! @note Return default constructor automatically returns false means + //! that mesh will return the boolean as false because it wasnt + //! successful + if (!tinyobj::LoadObj(&attrib, + &shapes, + &materials, + &warn, + &err, + p_filename.string().c_str())) { + console_log_warn("Could not load model from path {}", + p_filename.string()); + m_model_loaded = false; + return; + } + + std::vector vertices; + std::vector indices; + std::unordered_map unique_vertices{}; + + // for (const auto& shape : shapes) { + for (size_t i = 0; i < shapes.size(); i++) { + auto shape = shapes[i]; + // for (const auto& index : shape.mesh.indices) { + for (size_t j = 0; j < shape.mesh.indices.size(); j++) { + auto index = shape.mesh.indices[j]; + vk::vertex_input vertex{}; + + if (!unique_vertices.contains(vertex)) { + unique_vertices[vertex] = + static_cast(vertices.size()); + vertices.push_back(vertex); + } + + if (index.vertex_index >= 0) { + vertex.position = { + attrib.vertices[3 * index.vertex_index + 0], + attrib.vertices[3 * index.vertex_index + 1], + attrib.vertices[3 * index.vertex_index + 2] + }; + + vertex.color = { + attrib.colors[3 * index.vertex_index + 0], + attrib.colors[3 * index.vertex_index + 1], + attrib.colors[3 * index.vertex_index + 2] + }; + } + + if (!attrib.normals.empty()) { + vertex.normals = { + attrib.normals[3 * index.normal_index + 0], + attrib.normals[3 * index.normal_index + 1], + attrib.normals[3 * index.normal_index + 2] + }; + } + if (!attrib.texcoords.empty()) { + glm::vec2 flipped_uv = { + attrib.texcoords + [static_cast(index.texcoord_index) * 2], + 1.0f - attrib.texcoords[static_cast( + index.texcoord_index) * + 2 + + 1], + }; + + glm::vec2 original_uv = { + attrib.texcoords + [static_cast(index.texcoord_index) * 2], + attrib.texcoords + [static_cast(index.texcoord_index) * 2 + + 1], + }; + + vertex.uv = m_flip ? flipped_uv : original_uv; + } + else { + vertex.uv = glm::vec2(0.f, 0.f); + } + + if (!unique_vertices.contains(vertex)) { + unique_vertices[vertex] = + static_cast(vertices.size()); + vertices.push_back(vertex); + } + + indices.push_back(unique_vertices[vertex]); + } + } + + ::vk::vertex_params vbo_settings = { .phsyical_memory_properties = + m_physical.memory_properties(), + .vertices = vertices }; + ::vk::index_params ibo_settings = { .phsyical_memory_properties = + m_physical.memory_properties(), + .indices = indices }; + m_vbo = ::vk::vertex_buffer(m_device, vbo_settings); + m_ibo = ::vk::index_buffer(m_device, ibo_settings); + m_model_loaded = true; + } + + private: + physical_device m_physical; + VkDevice m_device = nullptr; + vk::texture m_diffuse; + vk::texture m_specular; + vk::vertex_buffer m_vbo{}; + vk::index_buffer m_ibo{}; + vk::uniform_buffer m_geoemtry_ubo; + vk::uniform_buffer m_material_ubo; + bool m_model_loaded = false; + bool m_flip = false; + }; +}; \ No newline at end of file diff --git a/atlas-modules/drivers/vulkan/render_system.cppm b/atlas-modules/drivers/vulkan/render_system.cppm new file mode 100644 index 00000000..eb2a092a --- /dev/null +++ b/atlas-modules/drivers/vulkan/render_system.cppm @@ -0,0 +1,635 @@ +module; + +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +export module atlas.drivers.vulkan.render_system; + +import atlas.logger; +import atlas.common; +import atlas.drivers.renderer_system; +import vk; +import atlas.core.utilities.types; +import atlas.common; +import atlas.core.scene; +import atlas.drivers.vulkan.instance_context; +import atlas.drivers.vulkan.physical_device; +import atlas.drivers.vulkan.device; +import atlas.drivers.vulkan.mesh; +import atlas.drivers.vulkan.shader_resource_group; +import atlas.core.scene.world; +import atlas.core.scene; +import atlas.drivers.vulkan.uniforms; +import atlas.drivers.vulkan.mesh; +import atlas.core.scene.components; +import atlas.application; + +export namespace atlas::vulkan { + /** + * @brief Something to consider for mesh loading. + * + * How will meshes get loaded? + * + * There are a few ways for considering for the base approach, which are: + * TODO: These are things to think about how this may happen because I want + * to make this lightweight in the sense the data isnt continuously being + * modified. Taking a looking at minimizing the loading state of vulkan + * implementation-specific meshes + * * While also making the way how mesh components are being added the + * same as before + * - Something to avoid is the entities containing the geometry data itself + * but being able to reference to their respective geometry data that are + * getting submitted to the GPU + * + * * Batching ID's into hash table that contains the actual geometry data + * * Using ID to search up the mesh loaded and cached into the map, then + * reuse that geometry whenever the uniforms are changed + * * This way we aren't reloading in the same mesh multiple times, treating + * the hash table as a slot of the mesh contained within that scene + * * Potentially std::map> m_geometries + * * Idea is the std::string is the geometries within this scene, the + * data format is: > + */ + class render_system : public renderer_system { + public: + render_system(const window_params& p_params, uint32_t p_image_size, const std::string& p_tag) { + m_device = instance_context::logical_device(); + m_physical = instance_context::physical_driver(); + m_window_extent = p_params; + m_image_count = p_image_size; + +#ifdef USE_SHADERC + std::array<::vk::shader_source, 2> shader_sources = { + ::vk::shader_source{ + "experimental-shaders/test.vert", + ::vk::shader_stage::vertex, + }, + ::vk::shader_source{ + "experimental-shaders/test.frag", + ::vk::shader_stage::fragment, + } + }; +#else + std::array<::vk::shader_source, 2> shader_sources = { + ::vk::shader_source{ + "experimental-shaders/test.vert.spv", + ::vk::shader_stage::vertex, + }, + ::vk::shader_source{ + "experimental-shaders/test.frag.spv", + ::vk::shader_stage::fragment, + } + }; +#endif + std::array<::vk::vertex_attribute_entry, 4> attribute_entries = { + ::vk::vertex_attribute_entry{ + .location = 0, + .format = ::vk::format::rgb32_sfloat, + .stride = offsetof(vk::vertex_input, position), + }, + ::vk::vertex_attribute_entry{ + .location = 1, + .format = ::vk::format::rgb32_sfloat, + .stride = offsetof(vk::vertex_input, color), + }, + ::vk::vertex_attribute_entry{ + .location = 2, + .format = ::vk::format::rgb32_sfloat, + .stride = offsetof(vk::vertex_input, normals), + }, + ::vk::vertex_attribute_entry{ + .location = 3, + .format = ::vk::format::rg32_sfloat, + .stride = offsetof(vk::vertex_input, uv), + } + }; + + std::array<::vk::vertex_attribute, 1> attribute = { + ::vk::vertex_attribute{ + // layout (set = 0, binding = 0) + .binding = 0, + .entries = attribute_entries, + .stride = sizeof(vk::vertex_input), + .input_rate = ::vk::input_rate::vertex, + }, + }; + + ::vk::shader_resource_info shader_info = { + .sources = shader_sources, + }; + + try { + m_shader_group = shader_resource_group(m_device, shader_info); + m_shader_group.vertex_attributes(attribute); + } + catch (std::runtime_error& e) { + console_log_error("Compilation Error!!"); + console_log_error("{}", e.what()); + } + // Setting global descriptor set 0 + std::vector<::vk::descriptor_entry> set0_entries = { + ::vk::descriptor_entry{ + // specifies "layout (set = 0, binding = 0) uniform GlobalUbo" + .type = ::vk::buffer::uniform, + .binding_point = { + .binding = 0, + .stage = ::vk::shader_stage::vertex, + }, + .descriptor_count = 1, + }, + ::vk::descriptor_entry{ + // specifies "layout (set = 0, binding = 1) uniform light_ubo" + .type = ::vk::buffer::uniform, + .binding_point = { + .binding = 1, + .stage = ::vk::shader_stage::fragment, + }, + .descriptor_count = 1, + }, + }; + + // uint32_t image_count = image_count; + ::vk::descriptor_layout set0_layout = { + .slot = 0, + .max_sets = m_image_count, + .entries = set0_entries, + }; + m_global_descriptors = ::vk::descriptor_resource(m_device, set0_layout); + + ::vk::uniform_params global_info = { + .phsyical_memory_properties = m_physical.memory_properties(), + .size_bytes = sizeof(global_ubo), + .debug_name = "\nm_global_uniforms\n", + .vkSetDebugUtilsObjectNameEXT = instance_context::get_debug_object_name() + }; + m_global_uniforms = ::vk::uniform_buffer(m_device, global_info); + + // setting up our light uniforms as the global uniforms rather then + // per-object basis + ::vk::uniform_params light_ubo_params = { + .phsyical_memory_properties = m_physical.memory_properties(), + .size_bytes = sizeof(light_scene_ubo), + }; + m_point_light_uniforms = + ::vk::uniform_buffer(m_device, light_ubo_params); + + std::array<::vk::write_buffer, 1> binding0_uniforms = { + ::vk::write_buffer{ + .buffer = m_global_uniforms, + .offset = 0, + .range = m_global_uniforms.size_bytes(), + }, + }; + + std::array<::vk::write_buffer, 1> binding1_uniforms = { + ::vk::write_buffer{ + .buffer = m_point_light_uniforms, + .offset = 0, + .range = m_point_light_uniforms.size_bytes(), + }, + }; + + std::array<::vk::write_buffer_descriptor, 2> set0_write_buffers = { + ::vk::write_buffer_descriptor{ + .dst_binding = 0, + .uniforms = binding0_uniforms, + }, + ::vk::write_buffer_descriptor{ + .dst_binding = 1, + .uniforms = binding1_uniforms, + } + }; + m_global_descriptors.update(set0_write_buffers); + + m_sets_layouts = { + m_global_descriptors.layout(), + }; + + ::vk::image_extent extent = { + .width = 1, + .height = 1, + }; + m_white_texture = + ::vk::texture(m_device, extent, m_physical.memory_properties()); + + instance_context::submit_resource_free([this]() { + m_white_texture.destroy(); + m_shader_group.destroy(); + m_global_descriptors.destroy(); + m_global_uniforms.destroy(); + m_point_light_uniforms.destroy(); + for (auto& [id, mesh] : m_cached_meshes) { + console_log_trace("Entity \"{}\" Destroyed in vk_renderer!!!", + id); + mesh.destroy(); + } + + for (auto& [id, uniform] : m_mesh_geometry_set) { + uniform.destroy(); + } + + for (auto& [id, material_uniform] : m_mesh_material_set) { + material_uniform.destroy(); + } + + for (auto& [key, descriptor_map] : m_mesh_descriptors) { + for (auto& [descriptor_type, descriptor] : descriptor_map) { + descriptor.destroy(); + } + } + m_main_pipeline.destroy(); + }); + } + + ~render_system() override = default; + + private: + void preload_assets(const VkRenderPass& p_renderpass) override { + m_final_renderpass = p_renderpass; + // set 1 -- material uniforms + // ref current_world = system_registry::get_world("Editor + // World"); ref current_scene = + // current_world->get_scene("LevelScene"); + + flecs::query<> caching = + m_current_scene->query_builder().build(); + + caching.each([this](flecs::entity p_entity) { + const mesh_source* target = p_entity.get(); + mesh new_mesh(std::filesystem::path(target->model_path), + target->flip); + + // we do a check if the geometry uniform associated with this game + // object is valid + if (!m_mesh_geometry_set.contains(p_entity.id())) { + ::vk::uniform_params geo_info = { + .phsyical_memory_properties = + m_physical.memory_properties(), + .size_bytes = sizeof(material_uniform), + }; + m_mesh_geometry_set[p_entity.id()] = + ::vk::uniform_buffer(m_device, geo_info); + } + + // check if material is already associated with this particular game + // object + if (!m_mesh_material_set.contains(p_entity.id())) { + ::vk::uniform_params mat_info = { + .phsyical_memory_properties = + m_physical.memory_properties(), + .size_bytes = sizeof(material_metadata), + }; + m_mesh_material_set[p_entity.id()] = + ::vk::uniform_buffer(m_device, mat_info); + } + + new_mesh.add_diffuse(std::filesystem::path(target->diffuse)); + new_mesh.add_specular(std::filesystem::path(target->specular)); + + if (new_mesh.loaded()) { + m_cached_meshes.emplace(p_entity.id(), new_mesh); + + std::vector<::vk::descriptor_entry> set1_entries = { + ::vk::descriptor_entry{ + // specifies "layout (set = 1, binding = 0) uniform geometry_uniform" + .type = ::vk::buffer::uniform, + .binding_point = { + .binding = 0, + .stage = ::vk::shader_stage::vertex, + }, + .descriptor_count = 1, + }, + ::vk::descriptor_entry{ + // specifies "layout (set = 1, binding = 1) uniform sampler2D diffuse_texture" + .type = ::vk::buffer::combined_image_sampler, + .binding_point = { + .binding = 1, + .stage = ::vk::shader_stage::fragment, + }, + .descriptor_count = 1, + }, + ::vk::descriptor_entry{ + // specifies "layout (set = 1, binding = 2) uniform sampler2D specular_texture" + .type = ::vk::buffer::combined_image_sampler, + .binding_point = { + .binding = 2, + .stage = ::vk::shader_stage::fragment, + }, + .descriptor_count = 1, + }, + ::vk::descriptor_entry{ + // specifies "layout (set = 1, binding = 3) uniform sampler2D material_ubo" + .type = ::vk::buffer::uniform, + .binding_point = { + .binding = 3, + .stage = ::vk::shader_stage::fragment, + }, + .descriptor_count = 1, + }, + }; + + ::vk::descriptor_layout set1_layout = { + .slot = 1, + .max_sets = m_image_count, + .entries = set1_entries, + }; + + m_mesh_descriptors[p_entity.id()].emplace( + "materials", + ::vk::descriptor_resource(m_device, set1_layout)); + + // specify to the vk::write_descriptor_buffer + std::array<::vk::write_buffer, 1> binding0_buffers = { + ::vk::write_buffer{ + .buffer = m_mesh_geometry_set[p_entity.id()], + .offset = 0, + .range = m_mesh_geometry_set[p_entity.id()].size_bytes(), + } + }; + + std::array<::vk::write_buffer, 1> binding3_buffers = { + ::vk::write_buffer{ + .buffer = m_mesh_material_set[p_entity.id()], + .offset = 0, + .range = m_mesh_material_set[p_entity.id()].size_bytes(), + } + }; + + std::vector<::vk::write_buffer_descriptor> material_uniforms = { + // layout(set= 1, binding = 0) geometry_ubo + ::vk::write_buffer_descriptor{ + .dst_binding = 0, + .uniforms = binding0_buffers, + }, + // layout(set= 1, binding = 3) material_ubo + ::vk::write_buffer_descriptor{ + .dst_binding = 3, + .uniforms = binding3_buffers, + }, + }; + + // layout(set = 1, binding = 1) + // If the texture loaded successfully then we use that texture, + // otherwise utilize the default white texture + ::vk::sample_image diffuse = + m_cached_meshes[p_entity.id()].diffuse_loaded() + ? m_cached_meshes[p_entity.id()].diffuse() + : m_white_texture.image(); + + // layout(set = 1, binding = 2) + ::vk::sample_image specular = + m_cached_meshes[p_entity.id()].specular_loaded() + ? m_cached_meshes[p_entity.id()].specular() + : m_white_texture.image(); + + // writes to texture at layout(set = 1, binding = 1) + std::array<::vk::write_image, 1> + binding1_images = { ::vk::write_image{ + .sampler = diffuse.sampler(), + .view = diffuse.image_view(), + // .image_layout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL, + .layout = ::vk::image_layout::shader_read_only_optimal, + } }; + + // writes to texture at layout(set = 1, binding = 2) + std::array<::vk::write_image, 1> + binding2_images = { ::vk::write_image{ + .sampler = specular.sampler(), + .view = specular.image_view(), + // .image_layout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL, + .layout = ::vk::image_layout::shader_read_only_optimal, + } }; + + // vulkan image descriptors are for writing textures + std::vector<::vk::write_image_descriptor> material_textures = { + // layout(set = 1, binding = 1) uniform sampler2D + ::vk::write_image_descriptor{ + .dst_binding = 1, + .sample_images = binding1_images, + }, + // layout(set = 1, binding = 2) uniform sampler2D + ::vk::write_image_descriptor{ + .dst_binding = 2, + .sample_images = binding2_images, + }, + }; + + m_mesh_descriptors[p_entity.id()]["materials"].update( + material_uniforms, material_textures); + + m_sets_layouts.push_back( + m_mesh_descriptors[p_entity.id()]["materials"].layout()); + } + }); + + std::vector<::vk::shader_handle> modules = m_shader_group.handles(); + + ::vk::pipeline_settings pipeline_configuration = { + .renderpass = m_final_renderpass, + .shader_modules = modules, + .vertex_attributes = m_shader_group.vertex_attributes(), + .vertex_bind_attributes = m_shader_group.vertex_bind_attributes(), + .descriptor_layouts = m_sets_layouts + }; + m_main_pipeline = ::vk::pipeline(m_device, pipeline_configuration); + } + + void start_frame(const ::vk::command_buffer& p_current, const window_params& p_settings, const VkRenderPass& p_renderpass, const VkFramebuffer& p_framebuffer, const glm::mat4& p_proj_view) override { + m_proj_view = p_proj_view; + m_current_frame = application::current_frame(); + m_final_renderpass = p_renderpass; + + std::array clear_values = {}; + + clear_values[0].color = m_color; + clear_values[1].depthStencil = { 1.f, 0 }; + m_window_extent = p_settings; + + VkRenderPassBeginInfo renderpass_begin_info = { + .sType = VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO, + .pNext = nullptr, + .renderPass = p_renderpass, + .renderArea = { + .offset = { + .x = 0, + .y = 0 + }, + .extent = { + .width = p_settings.width, + .height = p_settings.height + }, + }, + .clearValueCount = static_cast(clear_values.size()), + .pClearValues = clear_values.data() + }; + + m_current_command_buffer = p_current; + m_current_command_buffer.begin( + ::vk::command_usage::simulatneous_use_bit); + + VkViewport viewport = { + .x = 0.0f, + .y = 0.0f, + .width = static_cast(m_window_extent.width), + .height = static_cast(m_window_extent.height), + .minDepth = 0.0f, + .maxDepth = 1.0f, + }; + + vkCmdSetViewport(m_current_command_buffer, 0, 1, &viewport); + + VkRect2D scissor = { + .offset = { 0, 0 }, + .extent = { m_window_extent.width, m_window_extent.height }, + }; + + vkCmdSetScissor(m_current_command_buffer, 0, 1, &scissor); + + renderpass_begin_info.framebuffer = p_framebuffer; + + vkCmdBeginRenderPass(m_current_command_buffer, + &renderpass_begin_info, + VK_SUBPASS_CONTENTS_INLINE); + } + + void background_color(const std::array& p_color) override { + m_color = { + { p_color.at(0), p_color.at(1), p_color.at(2), p_color.at(3) } + }; + } + + void post_frame() override { + // For now, using this. Will need to remove this before vulkan + // integration merging into dev This is for testing and to hopefully + // have a global_ubo for globalized uniforms + global_ubo global_frame_ubo = { .mvp = m_proj_view }; + + // TODO: Make to_bytes be part of utilities. This can be useful in + // sending the amount of bytes in batches for batch-rendering + // std::span bytes_data = to_bytes(global_frame_ubo); + // m_global_uniforms.update(bytes_data.data()); + m_global_uniforms.update(&global_frame_ubo); + + // ref current_world = system_registry::get_world("Editor World"); + // ref current_scene = current_world->get_scene("LevelScene"); + + + // query all entities that have a point light + flecs::query query_point_lights = + m_current_scene->query_builder().build(); + + light_scene_ubo test_light = {}; + uint32_t index = 0; + query_point_lights.each( + [&index, &test_light](flecs::entity p_entity, point_light& p_light) { + const transform* t = p_entity.get(); + p_light.position = t->position; + + test_light.light_sources[index] = { + .position = glm::vec4(p_light.position, 1.f), + .color = p_light.color, + .attenuation = p_light.attenuation, + .constant = p_light.constant, + .linear = p_light.linear, + .quadratic = p_light.quadratic, + .ambient = p_light.ambient, + .diffuse = p_light.diffuse, + .specular = p_light.specular, + }; + index += 1; + }); + test_light.num_lights = index; + + m_point_light_uniforms.update(&test_light); + + // query all objects with a specified 3d mesh source + flecs::query<> query_targets = + m_current_scene->query_builder().build(); + + m_main_pipeline.bind(m_current_command_buffer); + + // Bind global camera data here + m_global_descriptors.bind(m_current_command_buffer, + m_main_pipeline.layout()); + query_targets.each([this](flecs::entity p_entity) { + const transform* transform_component = p_entity.get(); + const mesh_source* material_component = p_entity.get(); + m_model = glm::mat4(1.f); + m_model = glm::translate(m_model, transform_component->position); + m_model = glm::scale(m_model, transform_component->scale); + glm::mat4 rotation_mat4 = + glm::mat4(glm::quat(transform_component->rotation)); + + m_model *= rotation_mat4; + + // Mesh used for viking_room - replaced with std::map equivalent + geometry_uniform mesh_ubo = { .model = m_model, + .color = material_component->color }; + + if (m_cached_meshes[p_entity.id()].loaded()) { + m_mesh_geometry_set[p_entity.id()].update(&mesh_ubo); + + material_metadata data = {}; + + if (p_entity.has()) { + data = *p_entity.get(); + } + m_mesh_material_set[p_entity.id()].update(&data); + + m_mesh_descriptors[p_entity.id()]["materials"].bind( + m_current_command_buffer, m_main_pipeline.layout()); + + m_cached_meshes[p_entity.id()].draw(m_current_command_buffer); + } + }); + + vkCmdEndRenderPass(m_current_command_buffer); + m_current_command_buffer.end(); + } + + void current_scene(ref p_scene_ctx) override { + m_current_scene = p_scene_ctx; + } + + private: + VkDevice m_device = nullptr; + physical_device m_physical; + glm::mat4 m_proj_view; + VkRenderPass m_final_renderpass = nullptr; + window_params m_window_extent; + vk::command_buffer m_current_command_buffer{}; + VkClearColorValue m_color; + + uint32_t m_image_count = 0; + shader_resource_group m_shader_group; + vk::pipeline m_main_pipeline; + vk::descriptor_resource m_global_descriptors; + std::vector m_sets_layouts; + + std::map m_cached_meshes; + vk::uniform_buffer m_global_uniforms; + vk::uniform_buffer m_point_light_uniforms; + + // game object-specific meshes + std::map m_mesh_geometry_set; + // TODO: Make this into a material system, eventually + std::map m_mesh_material_set; + std::map> + m_mesh_descriptors; + uint32_t m_current_frame = 0; + glm::mat4 m_model = { 1.f }; + + vk::texture m_white_texture; + + ref m_current_scene; + }; +}; \ No newline at end of file diff --git a/atlas-modules/drivers/vulkan/shader_resource_group.cppm b/atlas-modules/drivers/vulkan/shader_resource_group.cppm new file mode 100644 index 00000000..631cf54a --- /dev/null +++ b/atlas-modules/drivers/vulkan/shader_resource_group.cppm @@ -0,0 +1,418 @@ +module; + +#include +#include +#include +#include +#include + +export module atlas.drivers.vulkan.shader_resource_group; + +import atlas.logger; +import vk; + +namespace atlas::vulkan { + // Reading the raw .spv binaries + static std::vector read_raw_spirv(const std::string& p_file) { + std::vector out_buffer; + std::ifstream ins(p_file, std::ios::ate | std::ios::binary); + + if (!ins) { + throw std::runtime_error("Cannot load in .spv files!!"); + } + + uint32_t file_size = (uint32_t)ins.tellg(); + out_buffer.resize(file_size); + ins.seekg(0); + ins.read(out_buffer.data(), file_size); + return out_buffer; + } + + //! @brief Ensure file reads are valid before reading raw .spv binaries + static std::vector compile_binary_shader_source( + const ::vk::shader_source& p_shader_source) { + + if (!std::filesystem::is_regular_file(p_shader_source.filename)) { + throw std::runtime_error("Cannot load .spv file"); + } + + return read_raw_spirv(p_shader_source.filename); + } + + static std::string read_shader_source_code(const std::string& p_filename) { + std::ifstream ins(p_filename, std::ios::ate | std::ios::binary); + + if (!ins.is_open()) { + console_log_warn("Could not open filename = {}", p_filename); + return { 'a' }; + } + + size_t file_size = (size_t)ins.tellg(); + std::string output; + output.resize(file_size); + ins.seekg(0); + ins.read(output.data(), static_cast(file_size)); + + return output; + } + + /** + * compiles source code from the shader directly without needing manual + * recompilation + * + * shaderc requires these parameters to compile + * text_source_code: the std::string version of the entire source code to + * compile type: shader stage this shader corresponds to filename: input + * filename text entry_point: the entry point to this shader options: + * compiler-specific options to enable when compiling the shader sources + */ +#ifdef ENABLE_SHADERC + static std::vector compile_source_from_file( + const ::vk::shader_source& p_shader_source) { + shaderc::CompileOptions options; + options.SetTargetEnvironment(shaderc_target_env_vulkan, + shaderc_env_version_vulkan_1_3); + options.SetWarningsAsErrors(); + + shaderc_shader_kind type; + + switch (p_shader_source.stage) { + case ::vk::shader_stage::vertex: + type = shaderc_glsl_vertex_shader; + break; + case ::vk::shader_stage::fragment: + type = shaderc_glsl_fragment_shader; + break; + default: + throw std::runtime_error("shader_stage unspecified!~!!"); + } + + shaderc::Compiler compiler; + std::string text_source_code = + read_shader_source_code(p_shader_source.filename); + + // Prints out the text of the shader source code + // console_log_warn("Source Text Code!!!"); + // console_log_info("{}", text_source_code); + shaderc::CompilationResult result = + compiler.CompileGlslToSpv(text_source_code, + type, + p_shader_source.filename.c_str(), + "main", + options); + + std::vector blob; + + if (result.GetCompilationStatus() != + shaderc_compilation_status_success) { + throw std::runtime_error( + std::format("Shader Compilation Error! Failed with reason {}\n{}", + p_shader_source.filename, + result.GetErrorMessage()) + .c_str()); + } + + for (auto blob_chunk : result) { + blob.push_back(blob_chunk); + } + + return blob; + } +#endif + /** + * @brief resource group for loading shader sources that give you back + * VkShaderModule handles + * + * Responsibility is to load stages of shader sources whether that be + * through precompiler .spv files or through shaderc runtime shader + * compilation + * + * Responsibility is loading and streaming the amount of bytes from the + * compiled shader sources into the vulkan shader module handles + * + * resource groups up the creation and management of vulkan shader modules. + */ + export class shader_resource_group { + public: + shader_resource_group() = default; + /** + * @brief constructs a new shader_resource_group + * + * @param p_device is the logical device required to creating the vulkan + * shader module + * @param p_info has the properties such as specified shader sources to + * load/compile + */ + shader_resource_group(const VkDevice& p_device, const ::vk::shader_resource_info& p_info) : m_device(p_device) { + + // We go through all of the specified shader source and their specific + // stage Compile them through shader compiler or if provided a .spv, + // then we compile and read in the stream of bytes directly + for (size_t i = 0; i < p_info.sources.size(); i++) { + const vk::shader_source shader_src = p_info.sources[i]; + std::filesystem::path filepath = + std::filesystem::path(shader_src.filename); +#ifndef ENABLE_SHADERC + if (filepath.extension().string() == ".spv") { + std::vector blob = + compile_binary_shader_source(shader_src); + + if (blob.empty()) { + m_resource_valid = false; + throw std::runtime_error("Cannot load in vector " + "blob of compiled down data!!!"); + } + + create_module(blob, shader_src); + } +#endif + +#if ENABLE_SHADERC + if (filepath.extension().string() != ".spv") { + std::string text_source_code = + read_shader_source_code(filepath.string()); + std::vector blob = + compile_source_from_file(shader_src); + create_module(blob, shader_src); + } +#endif + } + + } + + ~shader_resource_group() = default; + + /** + * @return true if resources are valid, otherwise return false + */ + [[nodiscard]] bool valid() const { return m_resource_valid; } + + /** + * @brief sets the vertex attributes with the shader modules that gets + * used by ::vk::pipeline (graphics pipeline) + * + * @param p_attributes is the high-level specifications for setting up + * vertex attributes that correspond with these shaders + */ + void vertex_attributes(std::span p_attributes) { + /* + -- These comments are a reminder to myself -- + - this function simplifies the need to separately define vertex + attributes and the vertex binding attributes as shown below: + + - vertex attributes specify the types of data within the vertex + + - vertex binding attribute specifies the rate of reading that data + layout specified by the vertex attributes + + - Interpret the following vertex attributes below with this shader + code with `layout(location = n)` specified where by default these are + set to binding zero by the shader + + layout(location = 0) in vec3 inPosition; + layout(location = 1) in vec3 inColor; + layout(location = 2) in vec3 inNormals; + layout(location = 3) in vec2 inTexCoords; + + m_shader_group.set_vertex_attributes(VkVertexInputAttributeDescription{ + { .location = 0, .binding = 0, .format = + VK_FORMAT_R32G32B32_SFLOAT, .offset = offsetof(vk::vertex, position), + }, { .location = 1, .binding = 0, .format = + VK_FORMAT_R32G32B32_SFLOAT, .offset = offsetof(vk::vertex, color), }, + { .location = 2, .binding = 0, .format = + VK_FORMAT_R32G32B32_SFLOAT, .offset = offsetof(vk::vertex, normals), + }, { .location = 3, .binding = 0, .format = VK_FORMAT_R32G32_SFLOAT, + .offset = offsetof(vk::vertex, uv), }, + }); + + m_shader_group.set_vertex_bind_attributes(VkVertexInputBindingDescription{ + {.binding = 0, .stride = sizeof(vk::vertex), .inputRate = + VK_VERTEX_INPUT_RATE_VERTEX,}, + }); + + Which gets handled in specifying the following below + */ + + m_vertex_binding_attributes.resize(p_attributes.size()); + + for (size_t i = 0; i < m_vertex_binding_attributes.size(); i++) { + // setting up vertex binding + const ::vk::vertex_attribute attribute = p_attributes[i]; + m_vertex_attributes.resize(attribute.entries.size()); + m_vertex_binding_attributes[i] = { .binding = attribute.binding, + .stride = attribute.stride, + .inputRate = to_input_rate( + attribute.input_rate) }; + + // then setting up the vertex attributes for the vertex data layouts + for (size_t j = 0; j < attribute.entries.size(); j++) { + const ::vk::vertex_attribute_entry entry = attribute.entries[j]; + m_vertex_attributes[j] = { .location = entry.location, + .binding = attribute.binding, + .format = static_cast( + entry.format), + .offset = entry.stride }; + } + } + } + + /** + * @brief this gives you back the shader module handles along with each + * of their stages they have been compiled with + * + * Returns the vector to retain the shader modules that are needed by + * the graphics pipeline. + * + * It is required by vulkan specs the graphics pipeline to contain valid + * shader modules of the compiled shaders + * + * @return vector<::vk::shader_handle> + */ + [[nodiscard]] std::vector<::vk::shader_handle> handles() const { + return map_to_vector(); + } + + /** + * @return span + */ + [[nodiscard]] std::span + vertex_attributes() const { + return m_vertex_attributes; + } + + /** + * @return span + */ + [[nodiscard]] std::span + vertex_bind_attributes() const { + return m_vertex_binding_attributes; + } + + /** + * @brief explicit cleanup to the VkShaderModule handles created with + * this particular resource group + */ + void destroy() { + for (auto& [filename, shader_handle] : m_modules) { + if (shader_handle.module != nullptr) { + vkDestroyShaderModule(m_device, shader_handle.module, nullptr); + } + } + } + + /** + * @brief ideally used for requesting for reload + * + * Planning to use this for invalidation when for runtime shader + * hot-reloading + * + * @note this is not used at the moment as shader runtime hot reloading + * is currently not supported. + */ + [[nodiscard]] bool reload_requested() const { + return m_reload_requested; + } + + private: + /** + * converts unordered_map to + * vector + */ + [[nodiscard]] std::vector<::vk::shader_handle> map_to_vector() const { + // Using C++'s std::views to extract all of the values in + // unordered_map to a vector + // that gets passed to graphics pipeline + return (m_modules | std::views::values | + std::ranges::to()); + } + + void create_module(std::span p_blob, const ::vk::shader_source& p_source) { + VkShaderModuleCreateInfo shader_module_ci = { + .sType = VK_STRUCTURE_TYPE_SHADER_MODULE_CREATE_INFO, + .pNext = nullptr, + .codeSize = p_blob.size(), + .pCode = reinterpret_cast(p_blob.data()) + }; + + std::filesystem::path filepath(p_source.filename); + std::string filename = filepath.filename().string(); + + // Setting m_shader_module_handlers[i]'s stage and the VkShaderModule + // handle altogether construct this beforehand and then we are going set + // that shader module + m_modules.emplace(filename, ::vk::shader_handle{}); + ::vk::vk_check( + vkCreateShaderModule( + m_device, &shader_module_ci, nullptr, &m_modules[filename].module), + "vkCreateShaderModule"); + m_modules[filename].stage = p_source.stage; + } + + void create_module(std::span p_blob, const ::vk::shader_source& p_source) { + VkShaderModuleCreateInfo shader_module_ci = { + .sType = VK_STRUCTURE_TYPE_SHADER_MODULE_CREATE_INFO, + .pNext = nullptr, + .codeSize = p_blob.size_bytes(), + .pCode = p_blob.data() + }; + + // console_log_info("map key = {}", p_source.filename); + std::filesystem::path filepath(p_source.filename); + + std::string filename = filepath.filename().string(); + + console_log_info("Key = {}", filename); + + // Setting m_shader_module_handlers[i]'s stage and the VkShaderModule + // handle altogether construct this beforehand and then we are going set + // that shader module + m_modules.emplace(filename, ::vk::shader_handle{}); + ::vk::vk_check( + vkCreateShaderModule( + m_device, &shader_module_ci, nullptr, &m_modules[filename].module), + "vkCreateShaderModule"); + m_modules[filename].stage = p_source.stage; + } + + /* + // TODO: Re-add this when shaderc works again. + void reload_shader(const ::vk::shader_source& p_source) { + console_log_info("p_source.filename = {}", p_source.filename); + if (m_modules[p_source.filename].module != nullptr) { + vkDestroyShaderModule( + m_device, m_modules[p_source.filename].module, nullptr); + } + + auto& handle = m_modules[p_source.filename]; + + std::filesystem::path filepath(p_source.filename); + std::string text_source_code = + read_shader_source_code(filepath.string()); + std::vector blob = compile_source_from_file(p_source); + std::span view_blob(blob.data(), blob.size()); + // create_module(blob, p_source); + VkShaderModuleCreateInfo shader_module_ci = { + .sType = VK_STRUCTURE_TYPE_SHADER_MODULE_CREATE_INFO, + .pNext = nullptr, + .codeSize = view_blob.size_bytes(), + .pCode = view_blob.data() + }; + + ::vk::vk_check(vkCreateShaderModule( + m_device, &shader_module_ci, nullptr, &handle.module), + "vkCreateShaderModule"); + } + */ + + private: + VkDevice m_device = nullptr; + std::vector m_vertex_attributes; + std::vector + m_vertex_binding_attributes; + bool m_resource_valid = false; + // shader module handles + std::unordered_map m_modules; + // ref m_watcher; + bool m_reload_requested = false; + }; +}; \ No newline at end of file diff --git a/atlas-modules/drivers/vulkan/uniforms.cppm b/atlas-modules/drivers/vulkan/uniforms.cppm new file mode 100644 index 00000000..a5f27c1e --- /dev/null +++ b/atlas-modules/drivers/vulkan/uniforms.cppm @@ -0,0 +1,76 @@ +module; + +#include + +export module atlas.drivers.vulkan.uniforms; + +import vk; + +export namespace atlas::vulkan { + struct vertex_input { + glm::vec3 position; + glm::vec3 color; + glm::vec3 normals; + glm::vec2 uv; + + bool operator==(const vertex_input& other) const { + return position == other.position and color == other.color and + uv == other.uv and normals == other.normals; + } + }; + + //! @brief Going to remove this + //! @brief This is being used by descriptor sets and vk_renderer + //! TODO: Modify vk_descriptor_set and vk_renderer and add uniforms.hpp + //! inside renderer/ (dir) for used across vk_renderer and the renderer + struct camera_ubo { + glm::mat4 projection{ 1.f }; + glm::mat4 view{ 1.f }; + }; + + //! @brief Just for testing purposes for sending this struct over to the + //! shader + struct global_ubo { + glm::mat4 mvp = { 1.f }; + }; + + /** + * @brief material is going to define properties about how a scene object + * itself gets rendered + * + */ + struct geometry_uniform { + glm::mat4 model{ 1.f }; + glm::vec4 color{ 1.f }; + // std::vector texture_paths; + }; + + /** + * @brief Represents a vulkan specific mateiral to pass in two textures and + * offset for handling shininess + */ + struct material_uniform { + float shininess = 1.f; + vk::texture diffuse; + vk::texture specular; + }; + + struct point_light_ubo { + glm::vec4 position; // this is provided by the transform + glm::vec4 color = { 1.f, 1.f, 1.f, 1.f }; + float attenuation = 1.f; + float constant = 1.f; + float linear = 1.f; + float quadratic = 1.f; + + glm::vec4 ambient = glm::vec4(1.f); + glm::vec4 diffuse = glm::vec4(1.f); + glm::vec4 specular = glm::vec4(1.f); + }; + + struct light_scene_ubo { + alignas(16) uint32_t num_lights; + // alignas(16) std::array light_sources; + alignas(16) point_light_ubo light_sources[10]; + }; +}; \ No newline at end of file diff --git a/atlas-modules/renderer/renderer.cppm b/atlas-modules/renderer/renderer.cppm new file mode 100644 index 00000000..529a27a5 --- /dev/null +++ b/atlas-modules/renderer/renderer.cppm @@ -0,0 +1,24 @@ +module; + +#include +#include + +export module atlas.renderer; + +import atlas.common; +import atlas.drivers.renderer_system; +import atlas.drivers.vulkan.render_system; +import atlas.common; +import atlas.graphics_api; +import atlas.core.utilities.types; + +export namespace atlas { + ref initialize_renderer(graphics_api p_api, const window_params& p_window_extent, uint32_t p_image_size, const std::string& p_name) { + switch(p_api) { + case graphics_api::vulkan: + return create_ref(p_window_extent, p_image_size, p_name); + default: + return nullptr; + } + } +}; \ No newline at end of file From a3dbd00e8cac00b95dcf12fa0d67c3a89997fcd0 Mon Sep 17 00:00:00 2001 From: SpinnerX Date: Mon, 12 Jan 2026 23:22:16 -0800 Subject: [PATCH 18/68] WIP -- getting level scene to work like normal and getting the renderer to work again --- CMakeLists.txt | 2 + atlas-modules/core/application.cppm | 26 +- atlas-modules/core/event/types.cppm | 3 +- atlas-modules/core/scene/system_registry.cppm | 94 +++++++ atlas-modules/core/scene/world.cppm | 2 +- atlas-modules/drivers/renderer_system.cppm | 8 +- .../drivers/vulkan/render_system.cppm | 26 +- editor_modules/CMakeLists.txt | 10 +- editor_modules/application.cpp | 27 +- editor_modules/editor_world.cppm | 37 +++ editor_modules/level_scene.cppm | 234 ++++++++++++++++++ 11 files changed, 446 insertions(+), 23 deletions(-) create mode 100644 atlas-modules/core/scene/system_registry.cppm create mode 100644 editor_modules/editor_world.cppm create mode 100644 editor_modules/level_scene.cppm diff --git a/CMakeLists.txt b/CMakeLists.txt index abce8f14..c63be930 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -120,6 +120,7 @@ target_sources(${PROJECT_NAME} PUBLIC atlas-modules/core/scene/game_object.cppm atlas-modules/core/scene/scene.cppm atlas-modules/core/scene/world.cppm + atlas-modules/core/scene/system_registry.cppm atlas-modules/core/utilities/state.cppm atlas-modules/core/utilities/poll_state.cppm @@ -130,6 +131,7 @@ target_sources(${PROJECT_NAME} PUBLIC atlas-modules/core/event/keys.cppm atlas-modules/core/event/mouse_codes.cppm atlas-modules/core/event/joystick_codes.cppm + atlas-modules/core/event/types.cppm atlas-modules/renderer/renderer.cppm diff --git a/atlas-modules/core/application.cppm b/atlas-modules/core/application.cppm index f8f41992..e10714c1 100644 --- a/atlas-modules/core/application.cppm +++ b/atlas-modules/core/application.cppm @@ -20,6 +20,9 @@ import atlas.drivers; import atlas.core.event; import atlas.core.utilities.poll_state; import atlas.logger; +import atlas.drivers.renderer_system; +import atlas.renderer; +import atlas.drivers.vulkan.instance_context; export namespace atlas { @@ -61,6 +64,17 @@ export namespace atlas { }; m_window = initialize_window(params, graphics_api::vulkan); event::set_window_size(static_cast(*m_window)); + + m_renderer = initialize_renderer(graphics_api::vulkan, params, m_window->current_swapchain().image_size(), "Renderer"); + m_renderer->set_background_color({ + p_params.background_color.x, + p_params.background_color.y, + p_params.background_color.z, + p_params.background_color.w, + }); + + // instance_context::submit_resource_free([this](){ + // }); s_instance = this; } @@ -83,6 +97,8 @@ export namespace atlas { console_log_info("Executing game mainloop!!!"); auto start_time = std::chrono::high_resolution_clock::now(); + m_renderer->preload( + m_window->current_swapchain().swapchain_renderpass()); invoke_start(); @@ -96,7 +112,7 @@ export namespace atlas { // m_current_frame_index = m_window->acquired_next_frame(); - console_log_info("current_frame = {}", m_current_frame_index); + // console_log_info("current_frame = {}", m_current_frame_index); invoke_on_update(); @@ -194,16 +210,16 @@ export namespace atlas { } protected: - // [[nodiscard]] ref renderer_instance() const { - // return m_renderer; - // } + [[nodiscard]] ref renderer_instance() const { + return m_renderer; + } private: float m_delta_time = 0.f; ref m_window; // vulkan::instance_context m_instance_handle_test; // std::optional m_instance_handle_test; - // ref m_renderer = nullptr; + ref m_renderer = nullptr; glm::mat4 m_proj_view; uint32_t m_current_frame_index = -1; // vk::imgui_context m_ui_context; diff --git a/atlas-modules/core/event/types.cppm b/atlas-modules/core/event/types.cppm index d1566e74..2cfb2406 100644 --- a/atlas-modules/core/event/types.cppm +++ b/atlas-modules/core/event/types.cppm @@ -3,7 +3,8 @@ module; #include export module atlas.core.event.types; -namespace atlas::event { + +export namespace atlas::event { struct collision_enter { uint64_t entity1; diff --git a/atlas-modules/core/scene/system_registry.cppm b/atlas-modules/core/scene/system_registry.cppm new file mode 100644 index 00000000..44239cd2 --- /dev/null +++ b/atlas-modules/core/scene/system_registry.cppm @@ -0,0 +1,94 @@ +module; + +#include +#include + +export module atlas.core.scene.system_registry; + +import atlas.common; +import atlas.core.scene.world; + +export namespace atlas { + /** + * @brief system registry acts as a utility for managing creation of game + * worlds initially + * + * Initially utilized to manage lifetimes of worlds and allow for by default + * setting to world #0, where we use few functions to get access to specific + * contexts + * + * + * TODO: This is going to be replaced with a level streaming manager that + * will help manage, maintain, and default creationg of a world and a scene. + * With additional responsibilities in how the world context gets created. + */ + class system_registry { + public: + /** + * @brief construct a new system registry + * + * @param p_name is for specifying a name to give this registry + */ + system_registry(const std::string& p_name) : m_tag(p_name) { + + s_instance = this; + } + + ~system_registry() = default; + + /** + * @note system_registry does the following: + * 1. Creates world scopes + * 2. Manages Lifetimes of world objects + * 3. Keeps tracks of the refcounting of references to these world + * objects + * 4. Provide globalized access to other worlds + */ + + /** + * @brief constructs a new world + * + * Initially this was used to create a world with a specified name + * associated with it + * + * This was used for getting world to be maintained implicitly by + * system_registry, though this will be changing. + */ + static ref create_world(const std::string& p_tag) { + return s_instance->append_world_and_get(create_ref(p_tag)); + } + + //! @brief Searches and returns world if found + //! @brief Returns nullptr if world not found + + /** + * @brief searches in getting the world and looks up based on its + * specified name + * + * @return nullptr if not found, otherwise return + * shared_ptr + */ + static ref get_world(const std::string& p_tag) { + return s_instance->m_world_registered[p_tag]; + } + + private: + ref search_world(const std::string& p_tag) { + return m_world_registered[p_tag]; + } + + // void append_world(const ref& p_world); + + ref append_world_and_get(const ref& p_world) { + m_world_registered.emplace(p_world->name(), p_world); + return m_world_registered[p_world->name()]; + } + + private: + static system_registry* s_instance; + std::string m_tag = "Undefined"; + std::map> m_world_registered; + }; + + system_registry* system_registry::s_instance = nullptr; +}; \ No newline at end of file diff --git a/atlas-modules/core/scene/world.cppm b/atlas-modules/core/scene/world.cppm index f61278e1..14221834 100644 --- a/atlas-modules/core/scene/world.cppm +++ b/atlas-modules/core/scene/world.cppm @@ -11,7 +11,7 @@ export module atlas.core.scene.world; import atlas.common; import atlas.core.scene; -namespace atlas { +export namespace atlas { /** * @brief world represents a larger scope of areas that manages the scene * contexts diff --git a/atlas-modules/drivers/renderer_system.cppm b/atlas-modules/drivers/renderer_system.cppm index f5b93b79..548c7ef0 100644 --- a/atlas-modules/drivers/renderer_system.cppm +++ b/atlas-modules/drivers/renderer_system.cppm @@ -54,9 +54,10 @@ export namespace atlas { const window_params& p_params, const VkRenderPass& p_renderpass, const VkFramebuffer& p_framebuffer, - const glm::mat4& p_proj_view) { + const glm::mat4& p_proj_view, + uint32_t p_current_frame) { return start_frame( - p_current, p_params, p_renderpass, p_framebuffer, p_proj_view); + p_current, p_params, p_renderpass, p_framebuffer, p_proj_view, p_current_frame); } /** @@ -84,7 +85,8 @@ export namespace atlas { const window_params& p_params, const VkRenderPass& p_renderpass, const VkFramebuffer& p_framebuffer, - const glm::mat4& p_proj_view) = 0; + const glm::mat4& p_proj_view, + uint32_t p_current_frame) = 0; virtual void post_frame() = 0; virtual void background_color(const std::array& p_color) = 0; diff --git a/atlas-modules/drivers/vulkan/render_system.cppm b/atlas-modules/drivers/vulkan/render_system.cppm index eb2a092a..3f7bfbbd 100644 --- a/atlas-modules/drivers/vulkan/render_system.cppm +++ b/atlas-modules/drivers/vulkan/render_system.cppm @@ -12,10 +12,10 @@ module; #include export module atlas.drivers.vulkan.render_system; +import atlas.drivers.renderer_system; import atlas.logger; import atlas.common; -import atlas.drivers.renderer_system; import vk; import atlas.core.utilities.types; import atlas.common; @@ -30,7 +30,6 @@ import atlas.core.scene; import atlas.drivers.vulkan.uniforms; import atlas.drivers.vulkan.mesh; import atlas.core.scene.components; -import atlas.application; export namespace atlas::vulkan { /** @@ -63,11 +62,14 @@ export namespace atlas::vulkan { public: render_system(const window_params& p_params, uint32_t p_image_size, const std::string& p_tag) { m_device = instance_context::logical_device(); + + console_log_info("m_device = {}", (m_device != nullptr)); m_physical = instance_context::physical_driver(); m_window_extent = p_params; m_image_count = p_image_size; #ifdef USE_SHADERC + console_log_info("shaderc enabled!!"); std::array<::vk::shader_source, 2> shader_sources = { ::vk::shader_source{ "experimental-shaders/test.vert", @@ -79,6 +81,7 @@ export namespace atlas::vulkan { } }; #else + console_log_info("shaderc disabled!!"); std::array<::vk::shader_source, 2> shader_sources = { ::vk::shader_source{ "experimental-shaders/test.vert.spv", @@ -222,6 +225,7 @@ export namespace atlas::vulkan { ::vk::texture(m_device, extent, m_physical.memory_properties()); instance_context::submit_resource_free([this]() { + console_log_info("vulkan::render_system destructin invoked!!"); m_white_texture.destroy(); m_shader_group.destroy(); m_global_descriptors.destroy(); @@ -248,6 +252,9 @@ export namespace atlas::vulkan { } m_main_pipeline.destroy(); }); + + + console_log_info("Vulkan-specific implementation constructed successfully!!!"); } ~render_system() override = default; @@ -259,6 +266,14 @@ export namespace atlas::vulkan { // ref current_world = system_registry::get_world("Editor // World"); ref current_scene = // current_world->get_scene("LevelScene"); + + if(m_current_scene == nullptr) { + console_log_error("m_current_scene == nullptr!"); + return; + } + else { + console_log_error("m_current_scene != nullptr!"); + } flecs::query<> caching = m_current_scene->query_builder().build(); @@ -441,11 +456,14 @@ export namespace atlas::vulkan { .descriptor_layouts = m_sets_layouts }; m_main_pipeline = ::vk::pipeline(m_device, pipeline_configuration); + + console_log_warn("graphics pipeline = {}", m_main_pipeline.alive()); } - void start_frame(const ::vk::command_buffer& p_current, const window_params& p_settings, const VkRenderPass& p_renderpass, const VkFramebuffer& p_framebuffer, const glm::mat4& p_proj_view) override { + void start_frame(const ::vk::command_buffer& p_current, const window_params& p_settings, const VkRenderPass& p_renderpass, const VkFramebuffer& p_framebuffer, const glm::mat4& p_proj_view, uint32_t p_current_frame) override { m_proj_view = p_proj_view; - m_current_frame = application::current_frame(); + // m_current_frame = application::current_frame(); + m_current_frame = p_current_frame; m_final_renderpass = p_renderpass; std::array clear_values = {}; diff --git a/editor_modules/CMakeLists.txt b/editor_modules/CMakeLists.txt index 4ef33432..520e5015 100644 --- a/editor_modules/CMakeLists.txt +++ b/editor_modules/CMakeLists.txt @@ -26,4 +26,12 @@ find_package(glfw3 REQUIRED) find_package(Vulkan REQUIRED) find_package(glm REQUIRED) find_package(spdlog REQUIRED) -target_link_libraries(${PROJECT_NAME} PUBLIC glfw Vulkan::Vulkan spdlog::spdlog glm::glm atlas) \ No newline at end of file +target_link_libraries(${PROJECT_NAME} PUBLIC glfw Vulkan::Vulkan spdlog::spdlog glm::glm atlas) + +target_sources(${PROJECT_NAME} PUBLIC + FILE_SET CXX_MODULES + TYPE CXX_MODULES + FILES + editor_world.cppm + level_scene.cppm +) \ No newline at end of file diff --git a/editor_modules/application.cpp b/editor_modules/application.cpp index 78eccfdc..c6c85396 100644 --- a/editor_modules/application.cpp +++ b/editor_modules/application.cpp @@ -1,4 +1,9 @@ // import atlas; +#include +#include +#include +#include + import atlas.application; import atlas.common; import atlas.logger; @@ -10,17 +15,19 @@ import atlas.drivers.graphics_context; import atlas.drivers; import atlas.core.event; import atlas.core.event.keys; - -#include -#include -#include -#include - +import editor_world; +import atlas.core.scene.system_registry; class test_application : public atlas::application { public: test_application(const atlas::application_settings& p_settings) : atlas::application(p_settings) { - atlas::register_update(this, &test_application::on_update); + // atlas::register_update(this, &test_application::on_update);std::pmr::monotonic_buffer_resource resource{ 4096 }; + // m_allocator.construct(&resource); + + // TODO -- this is going to be changed with the use of the level + // streamer API + console_log_info("renderer_instance = {}", (renderer_instance() != nullptr)); + m_world = atlas::create_ref("Editor World", renderer_instance()); } @@ -31,7 +38,9 @@ class test_application : public atlas::application { } - +private: + // std::pmr::polymorphic_allocator m_allocator; + atlas::ref m_world; }; @@ -101,6 +110,8 @@ int main() { // .background_color = {1.f, 1.f, 1.f, 1.f}, // }; // atlas::ref app = atlas::create_ref(settings); + + atlas::ref system = atlas::create_ref("system"); atlas::ref context = atlas::initialize_context("vulkan", atlas::graphics_api::vulkan); atlas::ref app = initialize_application(); diff --git a/editor_modules/editor_world.cppm b/editor_modules/editor_world.cppm new file mode 100644 index 00000000..545237a5 --- /dev/null +++ b/editor_modules/editor_world.cppm @@ -0,0 +1,37 @@ +module; + +#include + +export module editor_world; + +import atlas.common; +import atlas.logger; +import atlas.core.scene.world; +import atlas.core.event.bus; +import atlas.core.scene.system_registry; +import atlas.core.event.types; +import atlas.drivers.renderer_system; +import level_scene; + +export class editor_world { +public: + editor_world(const std::string& p_tag, atlas::ref p_renderer_instance) : m_renderer(p_renderer_instance) { + m_main_world = atlas::system_registry::create_world(p_tag); + + m_bus.create_listener(); + m_bus.create_listener(); + m_bus.create_listener(); + + atlas::ref first_scene = atlas::create_ref("LevelScene", m_bus); + m_renderer->current_scene_context(first_scene); + m_main_world->add_scene(first_scene); + + console_log_error("editor_world initialized successfully!~!!"); + } + +private: + atlas::ref m_main_world; + + atlas::event::bus m_bus; + atlas::ref m_renderer; +}; \ No newline at end of file diff --git a/editor_modules/level_scene.cppm b/editor_modules/level_scene.cppm new file mode 100644 index 00000000..6fe5e9dc --- /dev/null +++ b/editor_modules/level_scene.cppm @@ -0,0 +1,234 @@ +module; + +#include +#include + +export module level_scene; + +import atlas.core.event.types; +import atlas.core.scene; +import atlas.core.scene.game_object; +import atlas.core.event.bus; +import atlas.core.scene.components; +import atlas.core.utilities.state; + +export class level_scene final : public atlas::scene { +public: + level_scene(const std::string& p_name, atlas::event::bus& p_bus) : atlas::scene(p_name, p_bus) { + auto editor_camera = entity("Editor Camera"); + editor_camera + .add>(); + editor_camera.set({ + .position = { 3.50f, 4.90f, 36.40f }, + .scale{ 1.f }, + }); + editor_camera.set({ + .plane = { 0.1f, 5000.f }, + .is_active = true, + .field_of_view = 45.f, + }); + + atlas::game_object bob_object = entity("Bob"); + + bob_object.add(); + + // @brief For now adding this in + // because we do not have a way to handle empty scenes + // so we are adding this in just to have a specific mesh associated with the renderer for the time being, just to make sure it works. + atlas::game_object viking_room = entity("Viking Room"); + viking_room.add(); + viking_room.set({ + .position = { -2.70f, 2.70, -8.30f }, + .rotation = { 2.30f, 95.90f, 91.80f }, + .scale{ 1.f }, + }); + viking_room.set({ + .model_path = "assets/models/cube.obj", + .diffuse = "assets/models/wood.png", + }); + + // viking_room.set({ + // .radius = 1.0f, + // }); + + // viking_room.set({ + // .friction = 15.f, + // .restitution = 0.3f, + // .body_movement_type = atlas::dynamic, + // }); + + // atlas::game_object cube = entity("Aircraft"); + + // cube.set({ + // .position = { 0.f, 2.10f, -7.30f }, + // .scale = { 0.9f, 0.9f, 0.9f }, + // }); + + // cube.set({ + // .color = { 1.f, 1.f, 1.f, 1.f }, + // // .model_path = "assets/models/E 45 Aircraft_obj.obj", + // .model_path = "assets/backpack/backpack.obj", + // .diffuse = "assets/backpack/diffuse.jpg", + // .specular = "assets/backpack/specular.jpg" + // // .diffuse = "assets/models/E-45-steel detail_2_col.jpg", + // }); + + // atlas::game_object robot_model = entity("Cube"); + // robot_model.add(); + // // robot_model.add(); + // robot_model.set({ + // .position = { -2.70, 3.50f, 4.10f }, + // .scale = { 1.f, 1.f, 1.f }, + // }); + + // robot_model.set( + // { .color = { 1.f, 1.f, 1.f, 1.f }, + // .model_path = "assets/models/cube.obj", + // .diffuse = "assets/models/container_diffuse.png", + // .specular = "assets/models/container_specular.png" }); + + // robot_model.set({ + // .half_extent = { 1.f, 1.f, 1.f }, + // }); + // robot_model.set({ + // // .restitution = 1.f, + // .body_movement_type = atlas::dynamic, + // }); + + // atlas::game_object platform = entity("Platform"); + + // platform.set({ + // .scale = { 15.f, 0.30f, 10.0f }, + // }); + // platform.set({ + // .model_path = "assets/models/cube.obj", + // .diffuse = "assets/models/wood.png", + // }); + // platform.set({ + // .body_movement_type = atlas::fixed, + // }); + // platform.set({ + // .half_extent = { 15.f, 0.30f, 10.0f }, + // }); + + // atlas::game_object point_light = entity("Point Light 1"); + // point_light.set({ + // .position = { 0.f, 2.10f, -7.30f }, + // .scale = { 0.9f, 0.9f, 0.9f }, + // }); + + // point_light.set({ + // .model_path = "assets/models/cube.obj", + // .diffuse = "assets/models/wood.png", + // }); + // point_light.add(); + + // benchmark + + // auto start = std::chrono::high_resolution_clock::now(); + // TEMP Code + // [[maybe_unused]] atlas::game_object point_light_test = entity("Point + // Light 1"); auto end = std::chrono::high_resolution_clock::now(); auto + // duration = (end - start); + + // auto seconds = + // std::chrono::duration_cast(duration).count(); auto + // nanoseconds = + // std::chrono::duration_cast(duration).count(); + // auto microseconds = + // std::chrono::duration_cast(duration).count(); + + // console_log_fatal("Seconds = {:.1f}", static_cast(seconds)); + // console_log_fatal("Nanoseconds = {:.1f}", + // static_cast(nanoseconds)); console_log_fatal("Microseconds = + // {:.1f}", static_cast(microseconds)); + + // for(size_t i = 0; i < 26; i++) { + // auto obj = entity(std::format("Object #{}", i)); + // obj->set({ + // .restitution = 1.25f, + // .body_movement_type = atlas::dynamic, + // }); + + // obj->set( + // { + // .radius = 1.0f, + // }); + + // glm::vec3 pos = {float(0*1.4),float(0 * 1.4),float(0 * -3) }; + + // obj->set({ + // .position = pos, + // .rotation = {.3f, 0.0f, 0.0f}, + // }); + + // obj->set({ + // .model_path = "assets/models/Ball OBJ.obj", + // .diffuse = "assets/models/clear.png", + // }); + // } + + // atlas::game_object gerald = entity("Gerald"); + // gerald.add(); + + // TODO: Move this outside of level_scene + // m_deserializer_test = atlas::serializer(); + + subscribe(this, + &level_scene::collision_enter); + + atlas::register_start(this, &level_scene::start); + atlas::register_physics(this, &level_scene::physics_update); + atlas::register_update(this, &level_scene::on_update); + atlas::register_ui(this, &level_scene::on_ui_update); + } + + ~level_scene() override = default; + + void start() { + } + + void on_update() { + } + + void on_ui_update() { + } + + void physics_update() { + } + + void runtime_start() { + } + + void runtime_stop() { + } + + void reset_objects() { + } + +private: + void collision_enter(atlas::event::collision_enter& p_event) { + } + + void collision_persisted(atlas::event::collision_persisted& p_event) { + } + +private: + // atlas::serializer m_deserializer_test; + // flecs::entity m_selected_entity; + + // atlas::game_object_optional m_current_entity; + // float m_movement_speed = 10.f; + + // Setting physics system + // TODO -- when refactoring this would be at atlas::world level + // atlas::physics::physics_engine m_physics_engine; + + // bool m_physics_runtime = false; + + // atlas::ui::dockspace m_editor_dockspace; + // atlas::ui::menu_item m_editor_menu; + + // Note -- Added this temporarily + // ImFont* m_font; +}; \ No newline at end of file From eaa1730ded36bfdc03c353852d120fbb2e7de5b0 Mon Sep 17 00:00:00 2001 From: SpinnerX Date: Tue, 13 Jan 2026 00:01:08 -0800 Subject: [PATCH 19/68] WIP -- level scene working again --- atlas-modules/core/application.cppm | 158 ++++++++++++++++++++-- atlas-modules/core/event/event.cppm | 146 +++++++++++++++++--- atlas-modules/core/event/mouse_codes.cppm | 5 +- atlas-modules/core/math/math.cppm | 8 +- editor_modules/application.cpp | 13 +- editor_modules/level_scene.cppm | 85 ++++++++++-- 6 files changed, 366 insertions(+), 49 deletions(-) diff --git a/atlas-modules/core/application.cppm b/atlas-modules/core/application.cppm index e10714c1..461aea87 100644 --- a/atlas-modules/core/application.cppm +++ b/atlas-modules/core/application.cppm @@ -1,13 +1,17 @@ module; #include -#include +// #include +#include +#define GLM_ENABLE_EXPERIMENTAL +#include #include #include #include #include #include #include +#include export module atlas.application; @@ -23,6 +27,12 @@ import atlas.logger; import atlas.drivers.renderer_system; import atlas.renderer; import atlas.drivers.vulkan.instance_context; +import atlas.core.scene; +import atlas.core.scene.world; +import atlas.core.scene.system_registry; +import atlas.core.scene.components; +import atlas.core.math; +import vk; export namespace atlas { @@ -97,11 +107,73 @@ export namespace atlas { console_log_info("Executing game mainloop!!!"); auto start_time = std::chrono::high_resolution_clock::now(); - m_renderer->preload( - m_window->current_swapchain().swapchain_renderpass()); + m_renderer->preload(m_window->current_swapchain().swapchain_renderpass()); invoke_start(); + ref current_world = system_registry::get_world("Editor World"); + ref current_scene = current_world->get_scene("LevelScene"); + flecs::world current_world_scope = *current_scene; + + /* + - flecs::system is how your able to schedule changes for given + portions of data in this case the projection/view matrices are only + being changed when flecs::world::progress(g_delta_time) is being + invoked within the mainloop + current_world_scope.system() + + - When users do object->add>(), this automatically gets invoked by the + .system<...> that gets invoked by the mainloop. + */ + current_world_scope + .system, + transform, + perspective_camera>() + .each([&](flecs::pair p_pair, + transform& p_transform, + perspective_camera& p_camera) { + float aspect_ratio = m_window->aspect_ratio(); + if (!p_camera.is_active) { + return; + } + + p_pair->projection = glm::mat4(1.f); + + p_pair->projection = + glm::perspective(glm::radians(p_camera.field_of_view), + aspect_ratio, + p_camera.plane.x, + p_camera.plane.y); + p_pair->projection[1][1] *= -1; + p_pair->view = glm::mat4(1.f); + + // This is converting a glm::highp_vec4 to a glm::quat + glm::quat quaternion = to_quat(p_transform.quaternion); + + p_pair->view = + glm::translate(p_pair->view, p_transform.position) * + glm::mat4_cast(quaternion); + + p_pair->view = glm::inverse(p_pair->view); + }); + + /* + - Currently how this works is we query with anything that has a + flecs::pair + - This tells the ecs flecs what to do query for in regards to + specific objects that are a camera + - in the tag:: namespace, this is to imply components that are empty + and just represent tags, to specify their uses. + */ + auto query_camera_objects = + current_scene + ->query_builder, + perspective_camera>() + .build(); + + while(m_window->available()) { auto current_time = std::chrono::high_resolution_clock::now(); @@ -110,17 +182,85 @@ export namespace atlas { event::flush_events(); - // m_current_frame_index = m_window->acquired_next_frame(); - - // console_log_info("current_frame = {}", m_current_frame_index); + // Progresses the flecs::world by one tick (or replaced with using + // the delta time) + // This also invokes the following system call before the + // mainloop + current_world_scope.progress(m_delta_time); + + m_current_frame_index = m_window->acquired_next_frame(); + + // Current commands that are going to be iterated through + // Prevents things like stalling so the CPU doesnt have to wait for + // the GPU to fully complete before starting on the next frame + // Command buffer uses this to track the frames to process its + // commands currently_active_frame = (m_current_frame_index + 1) % + // m_window->current_swapchain().settings().frames_in_flight; + // TODO: Going to need to figure out where to put this + // Added this here because to ensure the handlers being used by the + // renderer is in sync when swapchain is resized + ::vk::command_buffer currently_active = m_window->active_command(m_current_frame_index); invoke_on_update(); invoke_physics_update(); invoke_defer_update(); - + // We want this to be called after late update + // This queries all camera objects within the camera system + // Update -- going to be removing camera system in replacement of + // just simply using flecs::system to keep it simple for the time + query_camera_objects.each( + [&](flecs::entity, + flecs::pair p_pair, + perspective_camera& p_camera) { + if (!p_camera.is_active) { + return; + } + + m_proj_view = p_pair->projection * p_pair->view; + }); + + // TODO: Introduce scene renderer that will make use of the + // begin/end semantics for setting up tasks during pre-frame + // operations + // renderer begin to indicate when a start of the frame to start + // processing specific tasks that either need to be computed or + // pre-defined before the renderer does something with it. + // TODO: Add scene_manager to coordinate what to process + // before frame preparation + auto current_framebuffer =m_window->current_swapchain().active_framebuffer(m_current_frame_index); + + m_renderer->begin_frame( + currently_active, + m_window->current_swapchain().settings(), + m_window->current_swapchain().swapchain_renderpass(), + current_framebuffer, + m_proj_view, + m_current_frame_index); + + // execute UI logic invoke_ui_update(); + + m_renderer->end_frame(); + + /* + TODO -- have m_window present this to the screen, eventually + m_renderer should just fetch the images in the order to offload + to the swapchain for rendering. + + Where each image has gone through different phases of the + renderpass onto the final image + */ + + std::array commands = { + currently_active, + }; + m_window->current_swapchain().submit(commands); + // Presents to the swapchain to display to screen + // m_renderer->present(m_current_frame_index); + m_window->present(m_current_frame_index); + } } @@ -157,7 +297,7 @@ export namespace atlas { * TODO: This is not actually needed, and should be removed */ VkSwapchainKHR get_current_swapchain() { - return nullptr; + return m_window->current_swapchain(); } /** @@ -202,7 +342,7 @@ export namespace atlas { * @return uint32_t */ static uint32_t image_size() { - return 0; + return s_instance->m_window->current_swapchain().image_size(); } static window& get_window() { diff --git a/atlas-modules/core/event/event.cppm b/atlas-modules/core/event/event.cppm index 36db3542..b29de79b 100644 --- a/atlas-modules/core/event/event.cppm +++ b/atlas-modules/core/event/event.cppm @@ -44,9 +44,6 @@ namespace atlas { static GLFWwindow* s_window_address; export namespace event { - void flush_events() { - glfwPollEvents(); - } bool is_key_pressed(int p_key) { @@ -57,37 +54,152 @@ namespace atlas { return (state == GLFW_PRESS); } - bool is_key_released(int p_key) {} + bool is_key_released(int p_key) { + GLFWwindow* window = s_window_address; + + auto state = glfwGetKey(window, static_cast(p_key)); + return (state == GLFW_RELEASE); + } + + bool is_mouse_pressed(int p_mouse_code) { + GLFWwindow* window = s_window_address; + + auto state = glfwGetMouseButton(window, static_cast(p_mouse_code)); + return (state == GLFW_PRESS); + } + + bool is_mouse_released(int p_mouse_code) { + GLFWwindow* window = s_window_address; - bool is_mouse_pressed(int p_mouse_code) {} - bool is_mouse_released(int p_mouse_code) {} + auto state = glfwGetMouseButton(window, static_cast(p_mouse_code)); + return (state == GLFW_RELEASE); + } - glm::vec2 cursor_position() {} + glm::vec2 cursor_position() { + GLFWwindow* window = s_window_address; + + double x_pos, y_pos; + glfwGetCursorPos(window, &x_pos, &y_pos); + + return { x_pos, y_pos }; + } // joystic-specific functions - bool is_joystic_present(int p_controller_id) {} + bool is_joystic_present(int p_controller_id) { + return s_controllers.contains(p_controller_id); + } - const char* is_joystick_guid(int p_controller_id) {} + const char* is_joystick_guid(int p_controller_id) { + return glfwGetJoystickGUID(p_controller_id); + } + + float get_joystic_axis(int p_controller_id, int p_button) { + int count; + const float axes = glfwGetJoystickAxes(p_controller_id, &count)[p_button]; - float get_joystic_axis(int p_controller_id, int p_button) {} + if (count < p_button) { + return 0.0f; + } + else { + return axes; + } + } - // bool is_button_pressed(int p_button_id, int p_controller_id); + // bool is_button_pressed(int p_button_id, int p_controller_id) { + // auto controller = s_controllers[p_controller_id]; + // return (controller.Buttons[p_button_id].ButtonState == GLFW_RELEASE); + // } - // bool is_button_released(int p_button_id, int p_controller_id); + // bool is_button_released(button_id p_button, controller_id p_controller) { + // auto selected_controller = s_controllers[p_controller]; + // return (selected_controller.Buttons[p_button].ButtonState == + // input_state::Pressed); + // } //! @note FIXME: Make button later - bool is_joystick_button_pressed(int p_button) {} - - bool is_joystick_button_released(int p_button) {} + bool is_joystick_button_pressed(int p_button) { + return p_button == GLFW_PRESS; + } - // specific for listening events - void update_events() {} + bool is_joystick_button_released(int p_button) { + return p_button == GLFW_RELEASE; + } void wait_for_events() {} void set_window_size(GLFWwindow* p_window) { s_window_address = p_window; } + + // specfying listening for events + void flush_events() { + glfwPollEvents(); + + // updating joysticks here + // .... + //! @note Must be called per input updated events. In the case either + //! game console disconnects or reconnects + //! @note This will continously check. + //! @note By default GLFW check's up to a total of 16 joystick ID's that + //! are available + //! @note We iterate all 16 joysticks, only using the joystic ID's that + //! are connected + //! @note Then checking for any events from the connected joystick has + //! occurred + // 1 is the first joystick. + // 16 is the last joystick + for (int joystick_id = 0; joystick_id < 16; joystick_id++) { + if (glfwJoystickPresent(joystick_id) == GLFW_TRUE) { + auto& joystick = s_controllers[joystick_id]; + joystick.ID = joystick_id; + joystick.JoystickName = glfwGetJoystickName(joystick_id); + + //! @note We always check how many buttons the joysticks that + //! are connected contain. + int amount_of_buttons = -1; + const unsigned char* buttons = + glfwGetJoystickButtons(joystick_id, &amount_of_buttons); + + // ConsoleLogWarn("Button Size = {}", amount_of_buttons); + + for (int i = 0; i < amount_of_buttons; i++) { + // ConsoleLogFatal("Button {} is ===> {}", i, buttons[i]); + // if(buttons[i] == GLFW_PRESS && !joystick.ButtonsDown[i]){ + if (is_joystick_button_pressed(buttons[i]) && + !joystick.ButtonsDown[i]) { + joystick.Buttons[i].ButtonState = input_state::Pressed; + } + // else if(buttons[i] == GLFW_RELEASE and + // joystick.ButtonsDown[i]){ + else if (is_joystick_button_released(buttons[i]) and + joystick.ButtonsDown[i]) { + joystick.Buttons[i].ButtonState = input_state::Released; + } + + // joystick.ButtonsDown[i] = (buttons[i] == GLFW_PRESS); + joystick.ButtonsDown[i] = + is_joystick_button_pressed(buttons[i]); + } + + int amount_of_axes = -1; + const float* axes = + glfwGetJoystickAxes(joystick_id, &amount_of_axes); + joystick.AxesOfController[joystick_id] = axes; + // ConsoleLogFatal("Axes at for-loop i = {} and Axes value = + // {:.3f}", 0, axes[0]); ConsoleLogFatal("Axes at for-loop i = + // {} and Axes value = {:.3f}", 1, axes[1]); for(int i = 0; i < + // amount_of_axes; i++){ + // ConsoleLogFatal("Axes at for-loop i = {} and Axes value = + // {:.3f}", i, axes[i]); + // } + } + else { + if (is_joystic_present(joystick_id)) { + s_controllers.erase(joystick_id); + } + } + } + } }; }; \ No newline at end of file diff --git a/atlas-modules/core/event/mouse_codes.cppm b/atlas-modules/core/event/mouse_codes.cppm index b989fd19..c357a868 100644 --- a/atlas-modules/core/event/mouse_codes.cppm +++ b/atlas-modules/core/event/mouse_codes.cppm @@ -24,6 +24,7 @@ namespace atlas::event { } // namespace atlas +export { inline constexpr uint32_t mouse_button_0 = ::atlas::event::Mouse::Button0; inline constexpr uint32_t mouse_button_1 = ::atlas::event::Mouse::Button1; inline constexpr uint32_t mouse_button_2 = ::atlas::event::Mouse::Button2; @@ -37,4 +38,6 @@ inline constexpr uint32_t mouse_button_left = ::atlas::event::Mouse::ButtonLeft; inline constexpr uint32_t mouse_button_right = ::atlas::event::Mouse::ButtonRight; inline constexpr uint32_t mouse_button_middle = - ::atlas::event::Mouse::ButtonMiddle; \ No newline at end of file + ::atlas::event::Mouse::ButtonMiddle; + +}; \ No newline at end of file diff --git a/atlas-modules/core/math/math.cppm b/atlas-modules/core/math/math.cppm index dcd61daf..580bb924 100644 --- a/atlas-modules/core/math/math.cppm +++ b/atlas-modules/core/math/math.cppm @@ -68,10 +68,14 @@ export namespace atlas { } //! @brief shorthand for glm::vec3(1.f, 0.f, 0.f) - glm::vec3 right(); + glm::vec3 right() { + return glm::vec3(1.f, 0.f, 0.f); + } //! @brief shorthand for glm::vec3(-1.f, 0.f, 0.f) - glm::vec3 left(); + glm::vec3 left() { + return glm::vec3(-1.f, 0.f, 0.f); + } //! @brief shorthand for glm::vec3(0.f, 1.f, 0.f) glm::vec3 up() { diff --git a/editor_modules/application.cpp b/editor_modules/application.cpp index c6c85396..59f40b43 100644 --- a/editor_modules/application.cpp +++ b/editor_modules/application.cpp @@ -31,13 +31,6 @@ class test_application : public atlas::application { } - void on_update() { - if(atlas::event::is_key_pressed(key_escape)) { - atlas::application::destroy(); - } - } - - private: // std::pmr::polymorphic_allocator m_allocator; atlas::ref m_world; @@ -54,9 +47,9 @@ TODO: Pre-defined this in TheAtlasEngine atlas::ref initialize_application() { atlas::application_settings settings = { .name = "Editor", - .width = 1900, - .height = 600, - .background_color = {1.f, 1.f, 1.f, 1.f}, + .width = 1200, + .height = 800, + .background_color = { 0.f, 0.f, 0.f, 0.f }, }; return create_ref(settings); } diff --git a/editor_modules/level_scene.cppm b/editor_modules/level_scene.cppm index 6fe5e9dc..8137d629 100644 --- a/editor_modules/level_scene.cppm +++ b/editor_modules/level_scene.cppm @@ -2,6 +2,13 @@ module; #include #include +#include +#define GLM_ENABLE_EXPERIMENTAL +#include + +#include +#include +#include export module level_scene; @@ -11,25 +18,28 @@ import atlas.core.scene.game_object; import atlas.core.event.bus; import atlas.core.scene.components; import atlas.core.utilities.state; +import atlas.core.math; +import atlas.core.event; +import atlas.core.event.keys; +import atlas.core.event.mouse_codes; +import atlas.application; export class level_scene final : public atlas::scene { public: level_scene(const std::string& p_name, atlas::event::bus& p_bus) : atlas::scene(p_name, p_bus) { auto editor_camera = entity("Editor Camera"); - editor_camera - .add>(); + editor_camera.add>(); editor_camera.set({ - .position = { 3.50f, 4.90f, 36.40f }, - .scale{ 1.f }, + .position = { 3.50f, 4.90f, 36.40f }, + .scale{ 1.f }, }); editor_camera.set({ - .plane = { 0.1f, 5000.f }, - .is_active = true, - .field_of_view = 45.f, + .plane = { 0.1f, 5000.f }, + .is_active = true, + .field_of_view = 45.f, }); atlas::game_object bob_object = entity("Bob"); - bob_object.add(); // @brief For now adding this in @@ -189,6 +199,61 @@ public: } void on_update() { + auto query_cameras = query_builder().build(); + + query_cameras.each([this](atlas::perspective_camera& p_camera, + atlas::transform& p_transform) { + if (!p_camera.is_active) { + return; + } + + float dt = atlas::application::delta_time(); + float default_speed = 10.f; // current default movement speed that does + // not applied modified speed + float rotation_speed = 1.f; + float velocity = default_speed * dt; + if (atlas::event::is_mouse_pressed(mouse_button_middle)) { + velocity = m_movement_speed * dt; + } + float rotation_velocity = rotation_speed * dt; + + glm::quat to_quaternion = atlas::to_quat(p_transform.quaternion); + + glm::vec3 up = glm::rotate(to_quaternion, atlas::math::up()); + glm::vec3 forward = glm::rotate(to_quaternion, atlas::math::backward()); + glm::vec3 right = glm::rotate(to_quaternion, atlas::math::right()); + + if (atlas::event::is_key_pressed(key_left_shift)) { + p_transform.position += up * velocity; + } + + if (atlas::event::is_key_pressed(key_space)) { + p_transform.position -= up * velocity; + } + + if (atlas::event::is_key_pressed(key_w)) { + p_transform.position += forward * velocity; + } + if (atlas::event::is_key_pressed(key_s)) { + p_transform.position -= forward * velocity; + } + + if (atlas::event::is_key_pressed(key_d)) { + p_transform.position += right * velocity; + } + if (atlas::event::is_key_pressed(key_a)) { + p_transform.position -= right * velocity; + } + + if (atlas::event::is_key_pressed(key_q)) { + p_transform.rotation.y += rotation_velocity; + } + if (atlas::event::is_key_pressed(key_e)) { + p_transform.rotation.y -= rotation_velocity; + } + + p_transform.set_rotation(p_transform.rotation); + }); } void on_ui_update() { @@ -215,10 +280,10 @@ private: private: // atlas::serializer m_deserializer_test; - // flecs::entity m_selected_entity; + flecs::entity m_selected_entity; // atlas::game_object_optional m_current_entity; - // float m_movement_speed = 10.f; + float m_movement_speed = 10.f; // Setting physics system // TODO -- when refactoring this would be at atlas::world level From 06cb85a3433166ed0f41873d75bcaef26ebaaf8c Mon Sep 17 00:00:00 2001 From: SpinnerX Date: Tue, 13 Jan 2026 00:32:59 -0800 Subject: [PATCH 20/68] WIP -- re- added physics components --- atlas-modules/core/application.cppm | 16 +-- atlas-modules/core/scene/components.cppm | 67 ++++++++++ editor_modules/level_scene.cppm | 148 +++++++++++------------ 3 files changed, 142 insertions(+), 89 deletions(-) diff --git a/atlas-modules/core/application.cppm b/atlas-modules/core/application.cppm index 461aea87..3540badb 100644 --- a/atlas-modules/core/application.cppm +++ b/atlas-modules/core/application.cppm @@ -257,8 +257,8 @@ export namespace atlas { currently_active, }; m_window->current_swapchain().submit(commands); + // Presents to the swapchain to display to screen - // m_renderer->present(m_current_frame_index); m_window->present(m_current_frame_index); } @@ -320,20 +320,6 @@ export namespace atlas { return 0.f; } - /** - * @brief Gives you the current frame index which is used for the Vulkan - * renderer - * - * Provides information such as what is the current frame index to - * correcly index the commands that get submitted to the GPU for - * processing commands (tasks) - * - * @return uint32_t - */ - static uint32_t current_frame() { - return 0; - } - /** * @brief Intended to get the image size so when you use current_frame() * to get thje frame index, that you are not making an attempt at diff --git a/atlas-modules/core/scene/components.cppm b/atlas-modules/core/scene/components.cppm index 1b21a647..1760f81c 100644 --- a/atlas-modules/core/scene/components.cppm +++ b/atlas-modules/core/scene/components.cppm @@ -126,4 +126,71 @@ export namespace atlas { glm::mat4 view; }; + /** + * @brief static is represented as fixed + */ + enum body_type : uint8_t { + fixed = 0, + kinematic = 1, + dynamic = 2, + bodynum, + }; + + /** + * @param non_moving is used for static objects that saves for not using the + * collider component + * @param moving is used for dynamic, kinematic, and character objects that + * will be used + */ + enum body_layer : uint8_t { + non_moving = 0, + moving = 1, + layer_num, + }; + + enum activation : uint8_t { activate, deactivate }; + + /** + * @brief physics body data-driven representative + * + * TODO: Add parameters for force, impulse, and torque + */ + struct physics_body { + glm::vec3 linear_velocity = glm::vec3(0.0); + glm::vec3 angular_velocity = glm::vec3(0.0f); + + glm::vec3 force = glm::vec3(0.0f); + glm::vec3 impulse = glm::vec3(0.0f); + glm::vec3 torque = glm::vec3(0.0f); + + float mass_factor = 1.0f; + glm::vec3 center_mass_position = glm::vec3(0.0f); + float linear_damping = 0.0f; + float angular_damping = 0.0f; + + float gravity_factor = 1.0f; + float friction = 0.8f; + float restitution = 0.2f; + + //! @brief body_type::fixed means this physics body is static + uint8_t body_movement_type = body_type::fixed; + + //! @brief body_layer (object layers) refer to the rules of the + //! collision system specified in JoltPhysics + uint8_t body_layer_type = body_layer::moving; + }; + + struct box_collider { + glm::vec3 half_extent = glm::vec3(0.5f); + }; + + struct capsule_collider { + float radius = 0.5f; + float half_height = 0.5f; + }; + + struct sphere_collider { + float radius = 0.5f; + }; + }; // namespace atlas \ No newline at end of file diff --git a/editor_modules/level_scene.cppm b/editor_modules/level_scene.cppm index 8137d629..e358b812 100644 --- a/editor_modules/level_scene.cppm +++ b/editor_modules/level_scene.cppm @@ -57,81 +57,81 @@ public: .diffuse = "assets/models/wood.png", }); - // viking_room.set({ - // .radius = 1.0f, - // }); - - // viking_room.set({ - // .friction = 15.f, - // .restitution = 0.3f, - // .body_movement_type = atlas::dynamic, - // }); - - // atlas::game_object cube = entity("Aircraft"); - - // cube.set({ - // .position = { 0.f, 2.10f, -7.30f }, - // .scale = { 0.9f, 0.9f, 0.9f }, - // }); - - // cube.set({ - // .color = { 1.f, 1.f, 1.f, 1.f }, - // // .model_path = "assets/models/E 45 Aircraft_obj.obj", - // .model_path = "assets/backpack/backpack.obj", - // .diffuse = "assets/backpack/diffuse.jpg", - // .specular = "assets/backpack/specular.jpg" - // // .diffuse = "assets/models/E-45-steel detail_2_col.jpg", - // }); - - // atlas::game_object robot_model = entity("Cube"); + viking_room.set({ + .radius = 1.0f, + }); + + viking_room.set({ + .friction = 15.f, + .restitution = 0.3f, + .body_movement_type = atlas::dynamic, + }); + + atlas::game_object cube = entity("Aircraft"); + + cube.set({ + .position = { 0.f, 2.10f, -7.30f }, + .scale = { 0.9f, 0.9f, 0.9f }, + }); + + cube.set({ + .color = { 1.f, 1.f, 1.f, 1.f }, + // .model_path = "assets/models/E 45 Aircraft_obj.obj", + .model_path = "assets/backpack/backpack.obj", + .diffuse = "assets/backpack/diffuse.jpg", + .specular = "assets/backpack/specular.jpg" + // .diffuse = "assets/models/E-45-steel detail_2_col.jpg", + }); + + atlas::game_object robot_model = entity("Cube"); + robot_model.add(); // robot_model.add(); - // // robot_model.add(); - // robot_model.set({ - // .position = { -2.70, 3.50f, 4.10f }, - // .scale = { 1.f, 1.f, 1.f }, - // }); - - // robot_model.set( - // { .color = { 1.f, 1.f, 1.f, 1.f }, - // .model_path = "assets/models/cube.obj", - // .diffuse = "assets/models/container_diffuse.png", - // .specular = "assets/models/container_specular.png" }); - - // robot_model.set({ - // .half_extent = { 1.f, 1.f, 1.f }, - // }); - // robot_model.set({ - // // .restitution = 1.f, - // .body_movement_type = atlas::dynamic, - // }); - - // atlas::game_object platform = entity("Platform"); - - // platform.set({ - // .scale = { 15.f, 0.30f, 10.0f }, - // }); - // platform.set({ - // .model_path = "assets/models/cube.obj", - // .diffuse = "assets/models/wood.png", - // }); - // platform.set({ - // .body_movement_type = atlas::fixed, - // }); - // platform.set({ - // .half_extent = { 15.f, 0.30f, 10.0f }, - // }); - - // atlas::game_object point_light = entity("Point Light 1"); - // point_light.set({ - // .position = { 0.f, 2.10f, -7.30f }, - // .scale = { 0.9f, 0.9f, 0.9f }, - // }); - - // point_light.set({ - // .model_path = "assets/models/cube.obj", - // .diffuse = "assets/models/wood.png", - // }); - // point_light.add(); + robot_model.set({ + .position = { -2.70, 3.50f, 4.10f }, + .scale = { 1.f, 1.f, 1.f }, + }); + + robot_model.set( + { .color = { 1.f, 1.f, 1.f, 1.f }, + .model_path = "assets/models/cube.obj", + .diffuse = "assets/models/container_diffuse.png", + .specular = "assets/models/container_specular.png" }); + + robot_model.set({ + .half_extent = { 1.f, 1.f, 1.f }, + }); + robot_model.set({ + // .restitution = 1.f, + .body_movement_type = atlas::dynamic, + }); + + atlas::game_object platform = entity("Platform"); + + platform.set({ + .scale = { 15.f, 0.30f, 10.0f }, + }); + platform.set({ + .model_path = "assets/models/cube.obj", + .diffuse = "assets/models/wood.png", + }); + platform.set({ + .body_movement_type = atlas::fixed, + }); + platform.set({ + .half_extent = { 15.f, 0.30f, 10.0f }, + }); + + atlas::game_object point_light = entity("Point Light 1"); + point_light.set({ + .position = { 0.f, 2.10f, -7.30f }, + .scale = { 0.9f, 0.9f, 0.9f }, + }); + + point_light.set({ + .model_path = "assets/models/cube.obj", + .diffuse = "assets/models/wood.png", + }); + point_light.add(); // benchmark From 78b762ea8e731ff4f987dc8d57be5b9c389d56b5 Mon Sep 17 00:00:00 2001 From: SpinnerX Date: Tue, 13 Jan 2026 01:39:14 -0800 Subject: [PATCH 21/68] WIP -- re-added the UI API's and fixed aspect ratio for window resizing, and added the editor logic for UI --- CMakeLists.txt | 8 + atlas-modules/core/application.cppm | 23 +- atlas-modules/core/editor/dockspace.cppm | 68 +++ atlas-modules/core/editor/menu_item.cppm | 67 +++ .../core/filesystem/file_dialog.cppm | 43 ++ atlas-modules/core/ui/widgets.cppm | 525 ++++++++++++++++++ .../drivers/vulkan/imgui_context.cppm | 220 ++++++++ .../drivers/vulkan/window_context.cppm | 2 +- editor_modules/level_scene.cppm | 390 ++++++++++++- 9 files changed, 1335 insertions(+), 11 deletions(-) create mode 100644 atlas-modules/core/editor/dockspace.cppm create mode 100644 atlas-modules/core/editor/menu_item.cppm create mode 100644 atlas-modules/core/filesystem/file_dialog.cppm create mode 100644 atlas-modules/core/ui/widgets.cppm create mode 100644 atlas-modules/drivers/vulkan/imgui_context.cppm diff --git a/CMakeLists.txt b/CMakeLists.txt index c63be930..a78a3ae8 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -133,6 +133,12 @@ target_sources(${PROJECT_NAME} PUBLIC atlas-modules/core/event/joystick_codes.cppm atlas-modules/core/event/types.cppm + # editor + atlas-modules/core/editor/dockspace.cppm + atlas-modules/core/editor/menu_item.cppm + atlas-modules/core/ui/widgets.cppm + atlas-modules/core/filesystem/file_dialog.cppm + atlas-modules/renderer/renderer.cppm atlas-modules/drivers/drivers.cppm @@ -145,6 +151,8 @@ target_sources(${PROJECT_NAME} PUBLIC atlas-modules/drivers/vulkan/render_system.cppm atlas-modules/drivers/vulkan/uniforms.cppm + atlas-modules/drivers/vulkan/imgui_context.cppm + atlas-modules/drivers/vulkan/vulkan.cppm atlas-modules/drivers/vulkan/utilities.cppm atlas-modules/drivers/vulkan/instance_context.cppm diff --git a/atlas-modules/core/application.cppm b/atlas-modules/core/application.cppm index 3540badb..11636cfc 100644 --- a/atlas-modules/core/application.cppm +++ b/atlas-modules/core/application.cppm @@ -32,6 +32,7 @@ import atlas.core.scene.world; import atlas.core.scene.system_registry; import atlas.core.scene.components; import atlas.core.math; +import atlas.drivers.vulkan.imgui_context; import vk; export namespace atlas { @@ -83,8 +84,11 @@ export namespace atlas { p_params.background_color.w, }); - // instance_context::submit_resource_free([this](){ - // }); + m_ui_context = vulkan::imgui_context(m_window); + + vulkan::instance_context::submit_resource_free([this](){ + m_ui_context.destroy(); + }); s_instance = this; } @@ -238,10 +242,15 @@ export namespace atlas { current_framebuffer, m_proj_view, m_current_frame_index); + + // TODO: vk:imgui_context will have its own renderpass, command + // buffers, and framebuffers specifically for UI-widgets + viewport + m_ui_context.begin(currently_active, m_current_frame_index); // execute UI logic invoke_ui_update(); + m_ui_context.end(); m_renderer->end_frame(); /* @@ -257,7 +266,7 @@ export namespace atlas { currently_active, }; m_window->current_swapchain().submit(commands); - + // Presents to the swapchain to display to screen m_window->present(m_current_frame_index); @@ -317,7 +326,7 @@ export namespace atlas { * @return a float which is just a static_cast(width / height); */ static float aspect_ratio() { - return 0.f; + return s_instance->m_window->aspect_ratio(); } /** @@ -331,8 +340,8 @@ export namespace atlas { return s_instance->m_window->current_swapchain().image_size(); } - static window& get_window() { - return *s_instance->m_window; + static window_params params() { + return s_instance->m_window->current_swapchain().settings(); } protected: @@ -348,7 +357,7 @@ export namespace atlas { ref m_renderer = nullptr; glm::mat4 m_proj_view; uint32_t m_current_frame_index = -1; - // vk::imgui_context m_ui_context; + vulkan::imgui_context m_ui_context; static application* s_instance; }; }; diff --git a/atlas-modules/core/editor/dockspace.cppm b/atlas-modules/core/editor/dockspace.cppm new file mode 100644 index 00000000..ced6c3b5 --- /dev/null +++ b/atlas-modules/core/editor/dockspace.cppm @@ -0,0 +1,68 @@ +module; + +#include +#include +#include + +#include + +export module atlas.core.editor.dockspace; + +export namespace atlas::ui { + /** + * @brief dockspace window using imgui + */ + class dockspace { + public: + dockspace() = default; + + void fullscreen(bool p_fullscreen) { + m_fullscreen_enabled = p_fullscreen; + } + + void dockspace_open(bool p_dockspace_open) { + m_is_dockspace_open = p_dockspace_open; + } + + void begin() { + ImGuiDockNodeFlags dockspace_flags = ImGuiDockNodeFlags_None; + ImGuiWindowFlags window_flags = + ImGuiWindowFlags_MenuBar | ImGuiWindowFlags_NoDocking; + + if (m_fullscreen_enabled) { + ImGuiViewport* viewport = ImGui::GetMainViewport(); + ImGui::SetNextWindowPos(viewport->Pos); + ImGui::SetNextWindowSize(viewport->Size); + ImGui::SetNextWindowViewport(viewport->ID); + window_flags |= ImGuiWindowFlags_NoTitleBar | + ImGuiWindowFlags_NoCollapse | + ImGuiWindowFlags_NoResize | ImGuiWindowFlags_NoMove; + window_flags |= ImGuiWindowFlags_NoBringToFrontOnFocus | + ImGuiWindowFlags_NoNavFocus; + } + + if (dockspace_flags & ImGuiDockNodeFlags_PassthruCentralNode) { + window_flags |= ImGuiWindowFlags_NoBackground; + } + ImGui::PushStyleVar(ImGuiStyleVar_WindowPadding, ImVec2(0.0f, 0.0f)); + ImGui::Begin("Dockspace Demo", &m_is_dockspace_open, window_flags); + ImGui::PopStyleVar(); + + // Dockspace + ImGuiIO& io = ImGui::GetIO(); + if (io.ConfigFlags & ImGuiConfigFlags_DockingEnable) { + ImGuiID dockspace_id = ImGui::GetID("MyDockspace"); + ImGui::DockSpace(dockspace_id, ImVec2(0.f, 0.f), dockspace_flags); + } + } + + void end() { + ImGui::End(); + } + + private: + bool m_fullscreen_enabled = false; + bool m_is_dockspace_open = false; + }; + +}; \ No newline at end of file diff --git a/atlas-modules/core/editor/menu_item.cppm b/atlas-modules/core/editor/menu_item.cppm new file mode 100644 index 00000000..5a47c81d --- /dev/null +++ b/atlas-modules/core/editor/menu_item.cppm @@ -0,0 +1,67 @@ +module; + +#include +#include +#include +#include +#include + +export module atlas.core.editor.menu_item; + +export namespace atlas::ui { + struct block { + const char* data = nullptr; + }; + + class menu_bar_exception { + public: + menu_bar_exception(const char* p_data) + : m_data(p_data) {} + + [[nodiscard]] const char* what() const { return m_data.data; } + + private: + block m_data; + }; + + /** + * @brief UI wrapper around setting up a menu item group + * + * + * ```C++ + * + * atlas::ui::menu_item menu; + * + * menu.begin(); + * + * menu.add_child("Save", [](){ + * // do some operation related to saving + * // perhaps saving the scene... + * }); + * + * menu.end(); + * + * ``` + */ + class menu_item { + public: + menu_item() = default; + + void begin() { + if (!ImGui::BeginMenuBar()) { + throw menu_bar_exception("ImGui::BeginMenuBar failed!"); + } + } + + void end() { + ImGui::EndMenuBar(); + } + + void add_child(const std::string& p_name, const std::function& p_callback) { + if (ImGui::MenuItem(p_name.c_str())) { + p_callback(); + } + ImGui::Separator(); + } + }; +}; \ No newline at end of file diff --git a/atlas-modules/core/filesystem/file_dialog.cppm b/atlas-modules/core/filesystem/file_dialog.cppm new file mode 100644 index 00000000..083b0cca --- /dev/null +++ b/atlas-modules/core/filesystem/file_dialog.cppm @@ -0,0 +1,43 @@ +module; + +#include +#include +#include + +export module atlas.core.filesystem.file_dialog; + +import atlas.logger; + +export namespace atlas::filesystem { + std::string load_from_file_dialog( + const std::string& p_filter, + const std::filesystem::path& p_default_path = "Untitled.engine") { + char* output_path = nullptr; + + nfdresult_t result = NFD_OpenDialog( + p_filter.c_str(), p_default_path.string().c_str(), &output_path); + + // if (result == NFD_OKAY) { + // return std::string(output_path); + // } + + // console_log_fatal("Error Loading File!"); + // return ""; + return (result == NFD_OKAY) ? std::string(output_path) : ""; + } + + std::string save_to_file(const std::string& p_filter, + const std::filesystem::path& p_default_path = "Untitled.engine") { + char* output_path = nullptr; + nfdresult_t result = NFD_SaveDialog( + p_filter.c_str(), p_default_path.string().c_str(), &output_path); + + // if(result == NFD_ERROR){ + // return std::string(); + // } + + // return std::string(output_path); + + return (result == NFD_OKAY) ? std::string(output_path) : std::string(); + } +}; \ No newline at end of file diff --git a/atlas-modules/core/ui/widgets.cppm b/atlas-modules/core/ui/widgets.cppm new file mode 100644 index 00000000..9cf44872 --- /dev/null +++ b/atlas-modules/core/ui/widgets.cppm @@ -0,0 +1,525 @@ +module; + +#include // Used to include "PushMultiItemsWidths" +#include +#include +#include +#include +#include + +export module atlas.core.ui.widgets; + +import atlas.core.filesystem.file_dialog; +import atlas.core.scene.components; + +export namespace atlas::ui { + using ::ImGui::InputText; + + /** + * @brief This is a free-standing function around + * ImGui::BeginPopupContextWindow + * + * It is primarily used to check if your mouse cursor is hovering over any + * items and to opening items based on if the mouse is specifically hovering + * over that particular item + * + * + * @param p_name is the string ID that is needed to be specified by imgui + * @param p_mb is the mouse button identifier that is an int to represent if + * the presses were (0=left, 1=right, 2=middle) + * @param p_over_items is a boolean to check if the mouse cursor has + * hoivered over that particular item specified by the string ID + * + * @return true if successful, otherwise return false + * + */ + bool begin_popup_context_window(const char* str_id, + ImGuiMouseButton mb, + bool over_items) { + return ImGui::BeginPopupContextWindow( + str_id, mb | (over_items ? 0 : ImGuiPopupFlags_NoOpenOverItems)); + } + + /** + * @brief UI render glm::vec3 values to imgui + * + * @param p_name is the specified name ID to associate with + * @param p_value is the value parameter to modify through this widget + * @param p_reset_value is the reset value to set the glm::vec3 + */ + void draw_vec3(const std::string& p_tag, + glm::vec3& p_position, + float p_reset_value=0.f) { + // ImGuiIO& io = ImGui::GetIO(); + ImGui::PushID(p_tag.c_str()); + + float column_width = 125.0f; + + ImGui::Columns(2); + ImGui::SetColumnWidth(0, column_width); + ImGui::Text("%s", p_tag.c_str()); + ImGui::NextColumn(); + + ImGui::PushMultiItemsWidths(3, ImGui::CalcItemWidth()); + ImGui::PushStyleVar(ImGuiStyleVar_ItemSpacing, ImVec2{ 0, 0 }); + + float line_height = + ImGui::GetFontSize() + ImGui::GetStyle().FramePadding.y * 2.0f; + ImVec2 button_size = { line_height + 3.0f, line_height }; + + ImGui::PushStyleColor(ImGuiCol_Button, + ImVec4{ 0.8, 0.1f, 0.15f, 1.0f }); + ImGui::PushStyleColor(ImGuiCol_ButtonHovered, + ImVec4{ 0.3f, 0.8f, 0.3f, 1.0f }); + ImGui::PushStyleColor(ImGuiCol_ButtonActive, + ImVec4{ 0.2, 0.1f, 0.2f, 1.0f }); + + if (ImGui::Button("X", button_size)) { + p_position.x = p_reset_value; + // ImGui::End(); + } + + // ImGui::PopFont(); + ImGui::PopStyleColor(3); + + ImGui::SameLine(); + ImGui::DragFloat("##X", &p_position.x, 0.1f, 0.0f, 0.0f, "%.2f"); + ImGui::PopItemWidth(); + ImGui::SameLine(); + + // Setting up for the Y button + ImGui::PushStyleColor(ImGuiCol_Button, ImVec4{ 0.2, 0.7f, 0.2f, 1.0f }); + ImGui::PushStyleColor(ImGuiCol_ButtonHovered, + ImVec4{ 0.3f, 0.8f, 0.3f, 1.0f }); + ImGui::PushStyleColor(ImGuiCol_ButtonActive, + ImVec4{ 0.2, 0.1f, 0.2f, 1.0f }); + + if (ImGui::Button("Y", button_size)) { + p_position.y = p_reset_value; + // ImGui::End(); + } + + // ImGui::PopFont(); + ImGui::PopStyleColor(3); + ImGui::SameLine(); + ImGui::DragFloat("##Y", &p_position.y, 0.1f, 0.0f, 0.0f, "%.2f"); + ImGui::PopItemWidth(); + ImGui::SameLine(); + + // Setting up for the Z button + ImGui::PushStyleColor(ImGuiCol_Button, + ImVec4{ 0.1, 0.25f, 0.8f, 1.0f }); + ImGui::PushStyleColor(ImGuiCol_ButtonHovered, + ImVec4{ 0.2f, 0.35f, 0.9f, 1.0f }); + ImGui::PushStyleColor(ImGuiCol_ButtonActive, + ImVec4{ 0.8, 0.1f, 0.15f, 1.0f }); + if (ImGui::Button("Z", button_size)) { + p_position.z = p_reset_value; + // ImGui::End(); + } + + // ImGui::PopFont(); + ImGui::PopStyleColor(3); + ImGui::SameLine(); + ImGui::DragFloat("##Z", &p_position.z, 0.1f, 0.0f, 0.0f, "%.2f"); + ImGui::PopItemWidth(); + + ImGui::PopStyleVar(); + + ImGui::Columns(1); + + ImGui::PopID(); + } + + /** + * @brief UI render glm::vec4 values to imgui + * + * @param p_name is the specified name ID to associate with + * @param p_value is the value parameter to modify through this widget + * @param p_reset_value is the reset value to set the glm::vec3 + */ + void draw_vec4(const std::string& p_tag, + glm::vec4& p_value, + float p_reset_value=0.f) { + // ImGuiIO& io = ImGui::GetIO(); + ImGui::PushID(p_tag.c_str()); + + float column_width = 100.0f; + + ImGui::Columns(2); + ImGui::SetColumnWidth(0, column_width); + ImGui::Text("%s", p_tag.c_str()); + ImGui::NextColumn(); + + ImGui::PushMultiItemsWidths(3, ImGui::CalcItemWidth()); + ImGui::PushStyleVar(ImGuiStyleVar_ItemSpacing, ImVec2{ 0, 0 }); + + float line_height = + ImGui::GetFontSize() + ImGui::GetStyle().FramePadding.y * 2.0f; + ImVec2 button_size = { line_height + 3.0f, line_height }; + + ImGui::PushStyleColor(ImGuiCol_Button, + ImVec4{ 0.8, 0.1f, 0.15f, 1.0f }); + ImGui::PushStyleColor(ImGuiCol_ButtonHovered, + ImVec4{ 0.3f, 0.8f, 0.3f, 1.0f }); + ImGui::PushStyleColor(ImGuiCol_ButtonActive, + ImVec4{ 0.2, 0.1f, 0.2f, 1.0f }); + + if (ImGui::Button("X", button_size)) { + p_value.x = p_reset_value; + // ImGui::End(); + } + + // ImGui::PopFont(); + ImGui::PopStyleColor(3); + + ImGui::SameLine(); + ImGui::DragFloat("##X", &p_value.x, 0.1f, 0.0f, 0.0f, "%.2f"); + ImGui::PopItemWidth(); + ImGui::SameLine(); + + // Setting up for the Y button + ImGui::PushStyleColor(ImGuiCol_Button, ImVec4{ 0.2, 0.7f, 0.2f, 1.0f }); + ImGui::PushStyleColor(ImGuiCol_ButtonHovered, + ImVec4{ 0.3f, 0.8f, 0.3f, 1.0f }); + ImGui::PushStyleColor(ImGuiCol_ButtonActive, + ImVec4{ 0.2, 0.1f, 0.2f, 1.0f }); + + if (ImGui::Button("Y", button_size)) { + p_value.y = p_reset_value; + // ImGui::End(); + } + + // ImGui::PopFont(); + ImGui::PopStyleColor(3); + ImGui::SameLine(); + ImGui::DragFloat("##Y", &p_value.y, 0.1f, 0.0f, 0.0f, "%.2f"); + ImGui::PopItemWidth(); + ImGui::SameLine(); + + // Setting up for the Z button + ImGui::PushStyleColor(ImGuiCol_Button, + ImVec4{ 0.1, 0.25f, 0.8f, 1.0f }); + ImGui::PushStyleColor(ImGuiCol_ButtonHovered, + ImVec4{ 0.2f, 0.35f, 0.9f, 1.0f }); + ImGui::PushStyleColor(ImGuiCol_ButtonActive, + ImVec4{ 0.8, 0.1f, 0.15f, 1.0f }); + if (ImGui::Button("Z", button_size)) { + p_value.z = p_reset_value; + // ImGui::End(); + } + + // ImGui::PopFont(); + ImGui::PopStyleColor(3); + ImGui::SameLine(); + ImGui::DragFloat("##Z", &p_value.z, 0.1f, 0.0f, 0.0f, "%.2f"); + ImGui::PopItemWidth(); + + ImGui::PopStyleVar(); + + ImGui::Columns(1); + + ImGui::PopID(); + } + + /** + * @brief UI render glm::vec4 values to imgui + * + * @param p_name is the specified name ID to associate with + * @param p_value is the value parameter to modify through this widget + * @param p_reset_value is the reset value to set the glm::vec3 + */ + void draw_float(const std::string& p_tag, + float& p_value, + float reset_value=0.f) { + ImGui::PushID(p_tag.c_str()); + + float column_width = 100.0f; + + ImGui::Columns(2); + + ImGui::SetColumnWidth(0, column_width); + ImGui::Text("%s", p_tag.c_str()); + ImGui::NextColumn(); + + ImGui::PushItemWidth(ImGui::CalcItemWidth()); + // ImGui::PushMultiItemsWidths(3, ImGui::CalcItemWidth()); + ImGui::PushStyleVar(ImGuiStyleVar_ItemSpacing, ImVec2{ 0, 0 }); + ImGui::PushStyleColor(ImGuiCol_Button, + ImVec4{ 0.8, 0.1f, 0.15f, 1.0f }); + ImGui::PushStyleColor(ImGuiCol_ButtonHovered, + ImVec4{ 0.3f, 0.8f, 0.3f, 1.0f }); + ImGui::PushStyleColor(ImGuiCol_ButtonActive, + ImVec4{ 0.2, 0.1f, 0.2f, 1.0f }); + + if (ImGui::Button(p_tag.c_str())) { + p_value = reset_value; + // ImGui::End(); + } + + // ImGui::PopFont(); + ImGui::PopStyleColor(3); + + ImGui::SameLine(); + ImGui::DragFloat("##X", &p_value, 0.1f, 0.0f, 0.0f, "%.2f"); + ImGui::PopItemWidth(); + ImGui::SameLine(); + + ImGui::PopStyleVar(); + + ImGui::Columns(1); + + ImGui::PopID(); + } + + /** + * @brief UI rendering input text + * + * + * @param p_dst is the destination string to be changed + * @param p_src is the original string that was previously given + */ + void draw_input_text(std::string& p_dst, std::string& p_src) { + std::string input_buffer = p_src; + + ImGuiInputTextFlags flags = ImGuiInputTextFlags_EnterReturnsTrue; + input_buffer.resize(255); // resize to allocate for 255 in the char + // array since this should be long enough + + if (ImGui::InputText("##Name", + (char*)input_buffer.c_str(), + input_buffer.size() + 1, + flags)) { + p_dst = input_buffer; + } + + if (p_dst.empty()) { + p_dst = p_src; + return; + } + + if (p_dst == p_src) { + p_dst = p_src; + return; + } + } + + /** + * @brief For UI rendering text to display and not input + * + * @param p_value is specified string for drawing text to imgui's UI + */ + void draw_text(const std::string& p_value) { + ImGui::Text("%s", p_value.data()); + } + + /** + * @brief Creates a panel that can be used to attach list of properties or + * other widgets too + * + * @tparam UComponent is the type of component or type to assoociate with + * this panel too + * @tparam UFunction is the callback that contains an arbitrary task related + * to the specified UComponent + * @param p_name is the name to give this panel + * @param p_entity is the entity that is being modified by this specific + * panel + * @param p_callback is a callback that is given an arbitrary task + * + * + * Example Usage: + * + * ```C++ + * draw_panel_component("transform", [](atlas::transform* + * p_transform){ + * // do some drawing with that transform + * }); + * ``` + */ + template + void draw_panel_component(const std::string& p_name, + flecs::entity& p_entity, + const UFunction& p_callback) { + const ImGuiTreeNodeFlags tree_node_flags = + ImGuiTreeNodeFlags_DefaultOpen | ImGuiTreeNodeFlags_Framed | + ImGuiTreeNodeFlags_SpanAvailWidth | + ImGuiTreeNodeFlags_AllowItemOverlap | ImGuiTreeNodeFlags_FramePadding; + + ImVec2 content_region = ImGui::GetContentRegionAvail(); + ImGui::PushStyleVar(ImGuiStyleVar_FramePadding, ImVec2{ 4, 4 }); + + float line_height = + ImGui::GetFontSize() + ImGui::GetStyle().FramePadding.y * 2.0f; + ImGui::Separator(); + + bool opened = ImGui::TreeNodeEx((void*)typeid(UComponent).hash_code(), + tree_node_flags, + "%s", + p_name.c_str()); + ImGui::PopStyleVar(); + + ImGui::SameLine(content_region.x - line_height * 0.05f); + + if (ImGui::Button("+", ImVec2(line_height, line_height))) { + ImGui::OpenPopup("ComponentSettings"); + } + + bool remove_component = false; // @note for deferring when to + // delete component. + if (ImGui::BeginPopup("ComponentSettings")) { + if (ImGui::MenuItem("Remove Component")) { + remove_component = true; + } + + ImGui::EndPopup(); + } + + if (remove_component) { + p_entity.remove(); + } + + if (opened) { + p_callback(p_entity.get_mut()); + ImGui::TreePop(); + } + } + + /** + * @brief used for creating a main dockspace for the editor + * + * TODO: This should be removed because this will be added into a separate + * atlas/editor/ toolchain module + */ + void dockspace_window(GLFWwindow* p_window) { + + bool dockspace_open = true; + static bool opt_fullscreen_persistant = true; + bool opt_fullscreen = opt_fullscreen_persistant; + static ImGuiDockNodeFlags dockspace_flags = ImGuiDockNodeFlags_None; + + ImGuiWindowFlags window_flags = + ImGuiWindowFlags_MenuBar | ImGuiWindowFlags_NoDocking; + + if (opt_fullscreen) { + ImGuiViewport* viewport = ImGui::GetMainViewport(); + ImGui::SetNextWindowPos(viewport->Pos); + ImGui::SetNextWindowSize(viewport->Size); + ImGui::SetNextWindowViewport(viewport->ID); + window_flags |= ImGuiWindowFlags_NoTitleBar | + ImGuiWindowFlags_NoCollapse | + ImGuiWindowFlags_NoResize | ImGuiWindowFlags_NoMove; + window_flags |= ImGuiWindowFlags_NoBringToFrontOnFocus | + ImGuiWindowFlags_NoNavFocus; + } + + if (dockspace_flags & ImGuiDockNodeFlags_PassthruCentralNode) { + window_flags |= ImGuiWindowFlags_NoBackground; + } + + ImGui::PushStyleVar(ImGuiStyleVar_WindowPadding, ImVec2(0.0f, 0.0f)); + ImGui::Begin("Dockspace Demo", &dockspace_open, window_flags); + ImGui::PopStyleVar(); + + if (opt_fullscreen) { + ImGui::PopStyleVar(2); + } + + // Dockspace + ImGuiIO& io = ImGui::GetIO(); + if (io.ConfigFlags & ImGuiConfigFlags_DockingEnable) { + ImGuiID dockspace_id = ImGui::GetID("MyDockspace"); + ImGui::DockSpace(dockspace_id, ImVec2(0.f, 0.f), dockspace_flags); + } + + if (ImGui::BeginMenuBar()) { + if (ImGui::MenuItem("Exit")) { + glfwSetWindowShouldClose(p_window, true); + } + + ImGui::EndMenuBar(); + } + + ImGui::End(); + } + + /** + draw panel component + + ImGui Renders individual sections that is per-component section + @param T is the specified component + @param p_entity is the entity to do operations with + @param UFunction is callback to logic for setting up those specific data + properties + */ + template + void draw_component(const std::string& p_tag, + flecs::entity& p_entity, + const UFunction& p_callable) { + const ImGuiTreeNodeFlags tree_node_flags = + ImGuiTreeNodeFlags_DefaultOpen | ImGuiTreeNodeFlags_Framed | + ImGuiTreeNodeFlags_SpanAvailWidth | + ImGuiTreeNodeFlags_AllowItemOverlap | ImGuiTreeNodeFlags_FramePadding; + + if (!p_entity.has()) { + return; + } + + T* component = p_entity.get_mut(); + + ImVec2 content_region = ImGui::GetContentRegionAvail(); + ImGui::PushStyleVar(ImGuiStyleVar_FramePadding, ImVec2{ 4, 4 }); + + float line_height = + ImGui::GetFontSize() + ImGui::GetStyle().FramePadding.y * 2.0f; + ImGui::Separator(); + + bool opened = ImGui::TreeNodeEx( + (void*)typeid(T).hash_code(), tree_node_flags, "%s", p_tag.c_str()); + ImGui::PopStyleVar(); + + ImGui::SameLine(content_region.x - line_height * 0.05f); + + if (ImGui::Button("+", ImVec2(line_height, line_height))) { + ImGui::OpenPopup("ComponentSettings"); + } + + bool remove_component = false; // @note for deferring when to + // delete component. + if (ImGui::BeginPopup("ComponentSettings")) { + if (ImGui::MenuItem("Remove Component")) { + remove_component = true; + } + + ImGui::EndPopup(); + } + + if (opened) { + p_callable(component); + ImGui::TreePop(); + } + + if (remove_component and !std::is_same_v) { + p_entity.remove(); + } + } + + /** + * @brief opens up a file dialog that uses imgui's button widget to make + * this happen + * + * This uses ImGui::Button to allow for when a click occurs it opens up the + * platform-specific file dialog to save or load in a particular file + * + * @param p_name is the specified name ID to pass into imgui + * @param p_filepath is the path of the file + * @param p_filter is the specific filter for file extensions to allow + * displaying in the fild dialog + */ + void button_open_file_dialog(const std::string& p_tag, + std::string& p_filename, + const std::string& p_filter = "obj;glftf;fbx") { + if (ImGui::Button(p_tag.c_str())) { + p_filename = filesystem::load_from_file_dialog(p_filter); + } + } +}; \ No newline at end of file diff --git a/atlas-modules/drivers/vulkan/imgui_context.cppm b/atlas-modules/drivers/vulkan/imgui_context.cppm new file mode 100644 index 00000000..732d23e7 --- /dev/null +++ b/atlas-modules/drivers/vulkan/imgui_context.cppm @@ -0,0 +1,220 @@ +module; + +#include +#include +#include +#include +#include +#include +#include + +export module atlas.drivers.vulkan.imgui_context; + +import atlas.common; +import vk; +import atlas.window; + +import atlas.drivers.vulkan.instance_context; +import atlas.drivers.vulkan.physical_device; +import atlas.drivers.vulkan.device; + +namespace atlas::vulkan { + static void im_gui_layout_color_modification() { + auto& colors = ImGui::GetStyle().Colors; // @note Colors is ImVec4 + + colors[ImGuiCol_WindowBg] = ImVec4{ 0.1f, 0.105f, 0.11f, 1.0f }; + + // Headers + colors[ImGuiCol_Header] = ImVec4{ 0.2f, 0.205f, 0.21f, 1.0f }; + colors[ImGuiCol_HeaderHovered] = ImVec4{ 0.3f, 0.305f, 0.31f, 1.0f }; + colors[ImGuiCol_HeaderActive] = ImVec4{ 0.15f, 0.1505f, 0.151f, 1.0f }; + + // Buttons + colors[ImGuiCol_Button] = ImVec4{ 0.2f, 0.205f, 0.21f, 1.0f }; + colors[ImGuiCol_ButtonHovered] = ImVec4{ 0.3f, 0.305f, 0.31f, 1.0f }; + colors[ImGuiCol_ButtonActive] = ImVec4{ 0.15f, 0.1505f, 0.151f, 1.0f }; + + // Frame BG + colors[ImGuiCol_FrameBg] = ImVec4{ 0.2f, 0.205f, 0.21f, 1.0f }; + colors[ImGuiCol_FrameBgHovered] = ImVec4{ 0.3f, 0.305f, 0.31f, 1.0f }; + colors[ImGuiCol_FrameBgActive] = ImVec4{ 0.15f, 0.1505f, 0.151f, 1.0f }; + + // Tabs + colors[ImGuiCol_Tab] = ImVec4{ 0.15f, 0.1505f, 0.151f, 1.0f }; + colors[ImGuiCol_TabHovered] = ImVec4{ 0.38f, 0.3805f, 0.381f, 1.0f }; + colors[ImGuiCol_TabActive] = ImVec4{ 0.28f, 0.2805f, 0.281f, 1.0f }; + colors[ImGuiCol_TabUnfocused] = ImVec4{ 0.15f, 0.1505f, 0.15f, 1.0f }; + colors[ImGuiCol_TabUnfocusedActive] = + ImVec4{ 0.2f, 0.205f, 0.21f, 1.0f }; + + // Titles + colors[ImGuiCol_TitleBg] = ImVec4{ 0.15f, 0.1505f, 0.151f, 1.0f }; + colors[ImGuiCol_TitleBgActive] = ImVec4{ 0.15f, 0.1505f, 0.15f, 1.0f }; + colors[ImGuiCol_TitleBgCollapsed] = + ImVec4{ 0.1f, 0.150f, 0.951f, 1.0f }; + } + + export class imgui_context { + public: + imgui_context() = default; + + imgui_context(const ref& p_window_ctx) { + m_instance = instance_context::handle(); + m_physical = instance_context::physical_driver(); + m_driver = instance_context::logical_device(); + + m_current_swapchain_handler = p_window_ctx->current_swapchain(); + + // Setting up imgui + IMGUI_CHECKVERSION(); + ImGui::CreateContext(); + ImGuiIO& io = ImGui::GetIO(); + + io.ConfigFlags |= + ImGuiConfigFlags_NavEnableKeyboard; // Enable Keyboard Controls + // io.ConfigFlags |= ImGuiConfigFlags_NavEnableGamepad; // Enable + // Gamepad Controls + io.ConfigFlags |= ImGuiConfigFlags_DockingEnable; // Enable Docking + io.ConfigFlags |= + ImGuiConfigFlags_ViewportsEnable; // Enable Multi-Viewport / Platform + // Windows + + // io.ConfigViewportsNoAutoMerge = true; + // io.ConfigViewportsNoAutoMerge = true; + // io.ConfigViewportsNoTaskBarIcon = true; + + // Setup Dear ImGui style + // ImGui::StyleColorsDark(); + // ImGui::StyleColorsClassic(); + im_gui_layout_color_modification(); + + ImGuiStyle& style = ImGui::GetStyle(); + if (io.ConfigFlags & ImGuiConfigFlags_ViewportsEnable) { + style.WindowRounding = 0.0f; + style.Colors[ImGuiCol_WindowBg].w = 1.0f; + } + + m_viewport_command_buffers.resize( + p_window_ctx->current_swapchain().image_size()); + + for (size_t i = 0; i < m_viewport_command_buffers.size(); i++) { + ::vk::command_params settings = { + .levels = ::vk::command_levels::primary, + // .queue_index = enumerate_swapchain_settings.present_index, + .queue_index = 0, + .flags = ::vk::command_pool_flags::reset, + }; + m_viewport_command_buffers[i] = + ::vk::command_buffer(m_driver, settings); + } + + // ::vk::descriptor_res + // m_imgui_descriptor = ::vk::descriptor_resource(m_driver, {}); + // 1: create descriptor pool for IMGUI + // the size of the pool is very oversize, but it's copied from imgui + // demo itself. + std::array pool_sizes = { + VkDescriptorPoolSize{ VK_DESCRIPTOR_TYPE_SAMPLER, 100 }, + VkDescriptorPoolSize{ VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, + 100 }, + VkDescriptorPoolSize{ VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE, 100 }, + VkDescriptorPoolSize{ VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, 100 }, + VkDescriptorPoolSize{ VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER, + 100 }, + VkDescriptorPoolSize{ VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER, + 100 }, + VkDescriptorPoolSize{ VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, 100 }, + VkDescriptorPoolSize{ VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, 100 }, + VkDescriptorPoolSize{ VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC, + 100 }, + VkDescriptorPoolSize{ VK_DESCRIPTOR_TYPE_STORAGE_BUFFER_DYNAMIC, + 100 }, + VkDescriptorPoolSize{ VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT, 100 } + }; + + VkDescriptorPoolCreateInfo desc_pool_create_info = { + .sType = VK_STRUCTURE_TYPE_DESCRIPTOR_POOL_CREATE_INFO, + .pNext = nullptr, + .flags = VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT, + .maxSets = static_cast(1000 * pool_sizes.size()), + // .poolSizeCount = (uint32_t)std::size(pool_sizes), + .poolSizeCount = static_cast(pool_sizes.size()), + .pPoolSizes = pool_sizes.data() + }; + + // VkDescriptorPool imgui_pool; + vk::vk_check(vkCreateDescriptorPool( + m_driver, &desc_pool_create_info, nullptr, &m_desc_pool), + "vkCreateDescriptorPool"); + + create(*p_window_ctx, + p_window_ctx->current_swapchain().image_size(), + p_window_ctx->current_swapchain().swapchain_renderpass()); + } + + void create(GLFWwindow* p_window_handler, const uint32_t& p_image_size, const VkRenderPass& p_current_renderpass) { + ImGui_ImplGlfw_InitForVulkan(p_window_handler, true); + ImGui_ImplVulkan_InitInfo init_info = {}; + init_info.Instance = m_instance; + init_info.PhysicalDevice = m_physical; + init_info.Device = m_driver; + init_info.Queue = m_driver.graphics_queue(); + init_info.RenderPass = p_current_renderpass; + init_info.PipelineCache = nullptr; + init_info.DescriptorPool = m_desc_pool; + init_info.MinImageCount = 2; + init_info.ImageCount = p_image_size; + init_info.UseDynamicRendering = false; + init_info.MSAASamples = VK_SAMPLE_COUNT_1_BIT; + ImGui_ImplVulkan_Init(&init_info); + } + + void begin(const VkCommandBuffer& p_current, const uint32_t& p_frame_index) { + ImGui_ImplVulkan_NewFrame(); + ImGui_ImplGlfw_NewFrame(); + ImGui::NewFrame(); + + m_current_frame_index = p_frame_index; + m_current = p_current; + } + + void end() { + ImGui::Render(); + + ImDrawData* draw_data = ImGui::GetDrawData(); + ImGui_ImplVulkan_RenderDrawData(draw_data, m_current); + + ImGuiIO& io = ImGui::GetIO(); + if (io.ConfigFlags & ImGuiConfigFlags_ViewportsEnable) { + ImGui::UpdatePlatformWindows(); + ImGui::RenderPlatformWindowsDefault(); + } + } + + [[nodiscard]] ::vk::command_buffer imgui_active_command() const { + return m_viewport_command_buffers[m_current_frame_index]; + } + + void destroy() { + ImGui_ImplVulkan_Shutdown(); + vkDestroyDescriptorPool(m_driver, m_desc_pool, nullptr); + + for (auto& command_buffer : m_viewport_command_buffers) { + command_buffer.destroy(); + } + + ImGui_ImplGlfw_Shutdown(); + ImGui::DestroyContext(); + } + + private: + VkInstance m_instance = nullptr; + VkPhysicalDevice m_physical = nullptr; + device m_driver{}; + uint32_t m_current_frame_index = 0; + VkSwapchainKHR m_current_swapchain_handler = nullptr; + VkDescriptorPool m_desc_pool = nullptr; + VkCommandBuffer m_current = nullptr; + std::vector<::vk::command_buffer> m_viewport_command_buffers; + }; +}; \ No newline at end of file diff --git a/atlas-modules/drivers/vulkan/window_context.cppm b/atlas-modules/drivers/vulkan/window_context.cppm index b5d07e32..544fe778 100644 --- a/atlas-modules/drivers/vulkan/window_context.cppm +++ b/atlas-modules/drivers/vulkan/window_context.cppm @@ -78,7 +78,7 @@ export namespace atlas { protected: [[nodiscard]] window_params get_params() const override { - return m_params; + return m_window_swapchain.settings(); } [[nodiscard]] GLFWwindow* native_window() const override { diff --git a/editor_modules/level_scene.cppm b/editor_modules/level_scene.cppm index e358b812..e0d57028 100644 --- a/editor_modules/level_scene.cppm +++ b/editor_modules/level_scene.cppm @@ -10,8 +10,13 @@ module; #include #include +#include +#include +#include + export module level_scene; +import atlas.application; import atlas.core.event.types; import atlas.core.scene; import atlas.core.scene.game_object; @@ -22,7 +27,87 @@ import atlas.core.math; import atlas.core.event; import atlas.core.event.keys; import atlas.core.event.mouse_codes; +import atlas.core.editor.dockspace; import atlas.application; +import atlas.core.ui.widgets; +import atlas.core.editor.menu_item; + +static void ui_component_list(flecs::entity& p_selected_entity) { + std::string entity_name = p_selected_entity.name().c_str(); + std::string new_entity_name = ""; + atlas::ui::draw_input_text(new_entity_name, entity_name); + + p_selected_entity.set_name(new_entity_name.c_str()); + + ImGui::SameLine(); + ImGui::PushItemWidth(-1); + if (ImGui::Button("Add Component")) { + ImGui::OpenPopup("Add Component"); + } + + if (ImGui::BeginPopup("Add Component")) { + if (!p_selected_entity.has()) { + if (ImGui::MenuItem("Perspective Camera")) { + p_selected_entity.add< + flecs::pair>(); + p_selected_entity.add(); + ImGui::CloseCurrentPopup(); + } + } + + if (!p_selected_entity.has()) { + if (ImGui::MenuItem("Mesh Source")) { + p_selected_entity.add(); + ImGui::CloseCurrentPopup(); + } + } + + if (!p_selected_entity.has()) { + if (ImGui::MenuItem("Point Light")) { + p_selected_entity.add(); + ImGui::CloseCurrentPopup(); + } + } + + if (!p_selected_entity.has()) { + if (ImGui::MenuItem("Serialize")) { + p_selected_entity.add(); + ImGui::CloseCurrentPopup(); + } + } + + if (!p_selected_entity.has()) { + if (ImGui::MenuItem("Physics Body")) { + p_selected_entity.add(); + ImGui::CloseCurrentPopup(); + } + } + + if (!p_selected_entity.has()) { + if (ImGui::MenuItem("Box Collider")) { + p_selected_entity.add(); + ImGui::CloseCurrentPopup(); + } + } + + if (!p_selected_entity.has()) { + if (ImGui::MenuItem("Sphere Collider")) { + p_selected_entity.add(); + ImGui::CloseCurrentPopup(); + } + } + + if (!p_selected_entity.has()) { + if (ImGui::MenuItem("Capsule Collider")) { + p_selected_entity.add(); + ImGui::CloseCurrentPopup(); + } + } + ImGui::EndPopup(); + } + + ImGui::PopItemWidth(); +} export class level_scene final : public atlas::scene { public: @@ -257,6 +342,305 @@ public: } void on_ui_update() { + // setting up the dockspace UI widgets at the window toolbar + m_editor_dockspace.begin(); + + try { + m_editor_menu.begin(); + } + catch (const atlas::ui::menu_bar_exception& e) { + } + + if (ImGui::BeginMenu("File")) { + if (ImGui::MenuItem("Save")) { + // m_deserializer_test.save("LevelScene"); + } + + ImGui::Separator(); + + if (ImGui::MenuItem("Exit")) { + // glfwSetWindowShouldClose(atlas::application::close(), true); + } + + ImGui::EndMenu(); + } + + m_editor_menu.end(); + + if (ImGui::Begin("Viewport")) { + glm::vec2 viewport_panel_size = + glm::vec2{ atlas::application::params().width, + atlas::application::params().height }; + + ImGui::End(); + } + + defer_begin(); + auto query_builder = this->query_builder().build(); + + if (ImGui::Begin("Scene Heirarchy")) { + // @note right click on blank space + // @param string_id + // @param popup_flags - will be the mouse flag (0=right, 1=left) + if (atlas::ui::begin_popup_context_window(nullptr, 1, false)) { + if (ImGui::MenuItem("Create Empty Entity")) { + m_current_entity = entity("Empty Entity"); + } + ImGui::EndPopup(); + } + + query_builder.each([&](flecs::entity p_entity, atlas::transform&) { + // We set the imgui flags for our scene heirarchy panel + // TODO -- Make the scene heirarchy panel a separate class that is + // used for specify the layout and other UI elements here + ImGuiTreeNodeFlags flags = + ((m_selected_entity == p_entity) ? ImGuiTreeNodeFlags_Selected + : 0) | + ImGuiTreeNodeFlags_OpenOnArrow; + flags |= ImGuiTreeNodeFlags_SpanAvailWidth; + flags |= ImGuiWindowFlags_Popup; + flags |= ImGuiTreeNodeFlags_AllowItemOverlap; + + bool opened = ImGui::TreeNodeEx(p_entity.name().c_str(), flags); + + if (ImGui::IsItemClicked()) { + m_selected_entity = p_entity; + } + + bool delete_entity = false; + if (ImGui::BeginPopupContextItem()) { + if (ImGui::MenuItem("Delete Entity")) { + delete_entity = true; + } + ImGui::EndPopup(); + } + + if (delete_entity) { + m_selected_entity.destruct(); + } + + ImGui::SameLine(); + ImGui::TextDisabled("(%llu)", p_entity.id()); + + if (opened) { + flags = ImGuiTreeNodeFlags_OpenOnArrow | + ImGuiTreeNodeFlags_SpanAvailWidth; + auto query_children_builder = + this->query_builder().with(flecs::ChildOf, p_entity).build(); + int32_t child_count = query_children_builder.count(); + + // // Only show children in scene heirarchy panel if there are + // children entities + if (child_count > 0) { + m_selected_entity.children([&](flecs::entity p_child) { + opened = + ImGui::TreeNodeEx(p_child.name().c_str(), flags); + if (opened) { + if (ImGui::IsItemClicked()) { + m_selected_entity = p_child; + } + ImGui::TreePop(); + } + }); + } + + ImGui::TreePop(); + } + }); + + defer_end(); + ImGui::End(); + } + + if (ImGui::Begin("Properties")) { + if (m_selected_entity.is_alive()) { + ui_component_list(m_selected_entity); + + atlas::ui::draw_component( + "transform", + m_selected_entity, + [](atlas::transform* p_transform) { + atlas::ui::draw_vec3("Position", p_transform->position); + atlas::ui::draw_vec3("Scale", p_transform->scale); + atlas::ui::draw_vec3("Rotation", p_transform->rotation); + }); + + atlas::ui::draw_component( + "camera", + m_selected_entity, + [this](atlas::perspective_camera* p_camera) { + atlas::ui::draw_float("field of view", + p_camera->field_of_view); + ImGui::Checkbox("is_active", &p_camera->is_active); + ImGui::DragFloat("Speed", &m_movement_speed); + }); + + atlas::ui::draw_component( + "atlas::mesh_source", + m_selected_entity, + [](atlas::mesh_source* p_source) { + std::string mesh_src = p_source->model_path; + atlas::ui::draw_input_text(p_source->model_path, mesh_src); + atlas::ui::draw_vec4("Color", p_source->color); + }); + + atlas::ui::draw_component( + "material", + m_selected_entity, + [](atlas::material_metadata* p_source) { + float speed = 0.01f; + ImGui::DragFloat4( + "Ambient", glm::value_ptr(p_source->ambient), speed); + ImGui::DragFloat4( + "Diffuse", glm::value_ptr(p_source->diffuse), speed); + ImGui::DragFloat4( + "Specular", glm::value_ptr(p_source->specular), speed); + atlas::ui::draw_float("Shininess", p_source->shininess); + }); + + /* + atlas::ui::draw_component("Directional + Light", m_selected_entity, [](atlas::directional_light* + p_dir_light){ ImGui::DragFloat4("Direction", + glm::value_ptr(p_dir_light->direction)); ImGui::DragFloat4("View + Pos", glm::value_ptr(p_dir_light->view_position)); + ImGui::DragFloat4("Color", glm::value_ptr(p_dir_light->color)); + ImGui::DragFloat4("Ambient", + glm::value_ptr(p_dir_light->ambient)); ImGui::DragFloat4("Diffuse", + glm::value_ptr(p_dir_light->diffuse)); ImGui::DragFloat4("Specular", + glm::value_ptr(p_dir_light->specular)); + }); + */ + + atlas::ui::draw_component( + "Point Light", + m_selected_entity, + [](atlas::point_light* p_dir_light) { + ImGui::DragFloat4( + "Color", glm::value_ptr(p_dir_light->color), 0.01); + ImGui::DragFloat( + "Attenuation", &p_dir_light->attenuation, 0.001); + ImGui::DragFloat4( + "Ambient", glm::value_ptr(p_dir_light->ambient), 0.01); + ImGui::DragFloat4( + "Diffuse", glm::value_ptr(p_dir_light->diffuse), 0.01); + ImGui::DragFloat4( + "Specular", glm::value_ptr(p_dir_light->specular), 0.01); + ImGui::DragFloat("Constant", &p_dir_light->constant, 0.01); + ImGui::DragFloat("Linear", &p_dir_light->linear, 0.01); + ImGui::DragFloat("Quadratic", &p_dir_light->quadratic, 0.01); + }); + + atlas::ui::draw_component( + "Physics Body", + m_selected_entity, + [](atlas::physics_body* p_body) { + std::array items = { + "Static", + "Kinematic", + "Dynamic", + }; + std::string combo_preview = items[p_body->body_movement_type]; + + // Begin the combo box + if (ImGui::BeginCombo("Body Type", combo_preview.data())) { + for (int n = 0; n < 3; n++) { + // Check if the current item is selected + const bool is_selected = + (p_body->body_movement_type == n); + if (ImGui::Selectable(items[n].data(), is_selected)) { + // Update the current type when a new item is + // selected + p_body->body_movement_type = + static_cast(n); + } + + // Set the initial focus when the combo box is first + // opened + if (is_selected) { + ImGui::SetItemDefaultFocus(); + } + } + ImGui::EndCombo(); + } + + // physics body parameters + atlas::ui::draw_vec3("Linear Velocity", + p_body->linear_velocity); + atlas::ui::draw_vec3("Angular Velocity", + p_body->angular_velocity); + atlas::ui::draw_vec3("Force", p_body->force); + atlas::ui::draw_vec3("Impulse", p_body->impulse); + atlas::ui::draw_vec3("Torque", p_body->torque); + atlas::ui::draw_vec3("Center Mass", + p_body->center_mass_position); + }); + + atlas::ui::draw_component( + "Box Collider", + m_selected_entity, + [](atlas::box_collider* p_collider) { + atlas::ui::draw_vec3("Half Extent", p_collider->half_extent); + }); + + atlas::ui::draw_component( + "Box Collider", + m_selected_entity, + [](atlas::sphere_collider* p_collider) { + atlas::ui::draw_float("Radius", p_collider->radius); + }); + + atlas::ui::draw_component( + "Box Collider", + m_selected_entity, + [](atlas::capsule_collider* p_collider) { + atlas::ui::draw_float("Half Height", p_collider->half_height); + atlas::ui::draw_float("Radius", p_collider->radius); + }); + + atlas::ui::draw_component( + "Serialize", + m_selected_entity, + [](atlas::tag::serialize* p_serialize) { + ImGui::Checkbox("Enable", &p_serialize->enable); + }); + } + + ImGui::End(); + + // Note --- just added this temporarily for testing + // auto time = atlas::application::delta_time(); + + // if((int)(time * 10.0f) % 8 > 4) { + // m_blink = !m_blink; + // } + + // auto width = atlas::application::get_window().width(); + // auto height = atlas::application::get_window().height(); + + // ImGui::SetNextWindowPos(ImVec2(static_cast(width) * 0.5f, + // static_cast(height) * 0.5f), ImGuiCond_Always, ImVec2(0.5f, + // 0.5f)); ImGui::SetNextWindowSize(ImVec2(200, 20), ImGuiCond_Always); + // ImGuiWindowFlags flags = ImGuiWindowFlags_NoDecoration | + // ImGuiWindowFlags_NoBackground | ImGuiWindowFlags_NoInputs; + // ImGui::SetNextWindowBgAlpha(0.f); + + // if(ImGui::Begin("Testing", nullptr, flags)) { + // ImGui::ProgressBar(10.f); + + // auto pos = ImGui::GetWindowPos(); + // pos.x += (float)width * 0.5f - 300.0f; + // pos.y += 50.0f; + // if(m_blink){ + // ImGui::GetForegroundDrawList()->AddText(m_font, 120.0f, + // pos, 0xffffffff, "Click to Play!"); + // } + + // ImGui::End(); + // } + } + + m_editor_dockspace.end(); } void physics_update() { @@ -282,7 +666,7 @@ private: // atlas::serializer m_deserializer_test; flecs::entity m_selected_entity; - // atlas::game_object_optional m_current_entity; + atlas::game_object_optional m_current_entity; float m_movement_speed = 10.f; // Setting physics system @@ -291,8 +675,8 @@ private: // bool m_physics_runtime = false; - // atlas::ui::dockspace m_editor_dockspace; - // atlas::ui::menu_item m_editor_menu; + atlas::ui::dockspace m_editor_dockspace; + atlas::ui::menu_item m_editor_menu; // Note -- Added this temporarily // ImFont* m_font; From 4b89fb9c0bfe60ea6842c379233c5860c909212b Mon Sep 17 00:00:00 2001 From: SpinnerX Date: Tue, 13 Jan 2026 02:30:10 -0800 Subject: [PATCH 22/68] WIP -- re-added serialization system for loading/saving scenes --- CMakeLists.txt | 4 + atlas-modules/core/serialize/serializer.cppm | 256 ++++++++++ atlas-modules/core/serialize/types.cppm | 493 +++++++++++++++++++ editor_modules/level_scene.cppm | 24 +- 4 files changed, 766 insertions(+), 11 deletions(-) create mode 100644 atlas-modules/core/serialize/serializer.cppm create mode 100644 atlas-modules/core/serialize/types.cppm diff --git a/CMakeLists.txt b/CMakeLists.txt index a78a3ae8..c7f88b0b 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -139,6 +139,10 @@ target_sources(${PROJECT_NAME} PUBLIC atlas-modules/core/ui/widgets.cppm atlas-modules/core/filesystem/file_dialog.cppm + # serialize + atlas-modules/core/serialize/types.cppm + atlas-modules/core/serialize/serializer.cppm + atlas-modules/renderer/renderer.cppm atlas-modules/drivers/drivers.cppm diff --git a/atlas-modules/core/serialize/serializer.cppm b/atlas-modules/core/serialize/serializer.cppm new file mode 100644 index 00000000..c77f2425 --- /dev/null +++ b/atlas-modules/core/serialize/serializer.cppm @@ -0,0 +1,256 @@ +module; + +// #include +// #include +#include +#include +#include +#include +#include +#include +#include + +export module atlas.core.serialize; + +import atlas.common; +import atlas.core.scene; +import atlas.core.serialize.types; +import atlas.core.scene.components; + + +namespace atlas { + // used to serialize entities + // TODO -- expand on this to stream_reader and stream_writer + static void serialize_entity(YAML::Emitter& output, + const flecs::entity& p_entity) { + output << YAML::BeginMap; + + output << YAML::Key << "Entity" << YAML::Value << p_entity.name(); + + if (p_entity.has()) { + output << p_entity.get(); + } + + if (p_entity.has()) { + output << p_entity.get(); + } + + if (p_entity.has()) { + output << p_entity.get(); + } + + if (p_entity.has()) { + output << p_entity.get(); + } + + if (p_entity.has()) { + output << p_entity.get(); + } + + if (p_entity.has()) { + output << p_entity.get(); + } + + if (p_entity.has()) { + output << p_entity.get(); + } + + if (p_entity.has()) { + output << p_entity.get(); + } + + // serialize entity childrens -- TODO + // output << YAML::Key << "Children" << YAML::Value << YAML::BeginSeq; + // p_entity.children([&](flecs::entity p_child_entity){ + // serialize_entity(output, p_child_entity); + // }); + + output << YAML::EndMap; + } + + static void deserialize_entity(YAML::iterator::value_type p_entity_value, + flecs::entity& p_deserialize_to_object) { + if (p_entity_value["Transform"]) { + auto transform_data = p_entity_value["Transform"]; + p_deserialize_to_object.set({ + .position = transform_data["Position"].as(), + .quaternion = transform_data["Quaternion"].as(), + .rotation = transform_data["Rotation"].as(), + .scale = transform_data["Scale"].as(), + }); + } + + // Deserialize atlas::perspective_camera component + if (p_entity_value["PerspectiveCamera"]) { + auto perspective_camera_data = p_entity_value["PerspectiveCamera"]; + p_deserialize_to_object.set({ + .plane = perspective_camera_data["Plane"].as(), + .is_active = perspective_camera_data["Active"].as(), + .field_of_view = + perspective_camera_data["Field of View"].as(), + }); + } + + // Deserialize atlas::material component + if (p_entity_value["Mesh Source"]) { + auto perspective_camera_data = p_entity_value["Mesh Source"]; + p_deserialize_to_object.set({ + .model_path = + perspective_camera_data["Model Path"].as(), + .diffuse = perspective_camera_data["Diffuse"].as(), + .specular = perspective_camera_data["Specular"].as(), + }); + } + + if (p_entity_value["Point Light"]) { + auto point_light = p_entity_value["Point Light"]; + p_deserialize_to_object.set({ + .color = point_light["Color"].as(), + .attenuation = point_light["Attenuation"].as(), + .constant = 1.f, + .linear = 1.f, + .quadratic = 1.f, + .ambient = point_light["Ambient"].as(), + .diffuse = point_light["Diffuse"].as(), + .specular = point_light["Specular"].as(), + }); + } + + // deserialize physics body + if (p_entity_value["Physics Body"]) { + auto body = p_entity_value["Physics Body"]; + p_deserialize_to_object.set( + { .linear_velocity = body["Linear Velocity"].as(), + .angular_velocity = body["Angular Velocity"].as(), + .force = body["Force"].as(), + .impulse = body["Impulse"].as(), + .torque = body["Torque"].as(), + .center_mass_position = + body["Center Mass Position"].as(), + .friction = body["Friction"].as(), + .restitution = body["Restitution"].as(), + .body_movement_type = + static_cast(body["Body Movement Type"].as()), + .body_layer_type = + static_cast(body["Body Layer Type"].as()) }); + } + + if (p_entity_value["Box Collider"]) { + auto collider = p_entity_value["Box Collider"]; + p_deserialize_to_object.set({ + .half_extent = collider["Half Extent"].as(), + }); + } + + if (p_entity_value["Sphere Collider"]) { + auto collider = p_entity_value["Sphere Collider"]; + p_deserialize_to_object.set({ + .radius = collider["Radius"].as(), + }); + } + + if (p_entity_value["Capsule Collider"]) { + auto collider = p_entity_value["Capsule Collider"]; + p_deserialize_to_object.set({ + .radius = collider["Half Height"].as(), + .half_height = collider["Half Height"].as(), + }); + } + } + + /** + * @brief serializer is responsible for saving/loading scenes + * + * This class excepts a scene context with the purpose of serializing with + * the entities that reside within that specific scene context + * + * Which also provide an API for loading in a scene from disk for + * deserialization. + */ + export class serializer { + public: + serializer() = default; + + /** + * @brief constructs a new serializer with a requirement to specify a + * scene to serialize + * @param p_scene_ctx is the current scene to perform + * serialization/deserialization to + */ + serializer(const ref& p_scene_ctx) : m_current_scene_ctx(p_scene_ctx) {} + + /** + * @param p_filepath is the specified path to save the file + */ + void save(const std::filesystem::path& p_filepath) { + YAML::Emitter output; + output << YAML::BeginMap; + output << YAML::Key << "Scene" << YAML::Value + << m_current_scene_ctx->name(); + output << YAML::Key << "Entities" << YAML::Value << YAML::BeginSeq; + + //! @note Queries in flecs the ecs framework are how we can query all + //! entities that the engine (user creates through our API) + // ref world_object = + // system_registry::get_world("Editor World"); + // ref current_scene = + // world_object->get_scene("LevelScene"); + + // flecs::query<> q = + // current_scene->query_builder().with().build(); + + // query all entities with a serialized tag specified + // while specifying to not query entities that also have the tag::editor + // specified + flecs::query<> q = m_current_scene_ctx->query_builder() + .with() + .without() + .build(); + + q.each([&output](flecs::entity p_entity_id) { + serialize_entity(output, p_entity_id); + }); + + std::ofstream output_file(p_filepath.string()); + output_file << output.c_str(); + } + + /** + * @param p_filepath is the specified path to loading in the saved file + * from + * @param p_registry is the current scene registry to load/create the + * entities through that registry + * @return true if loading was successful, otherwise will return false + */ + bool load(const std::filesystem::path& p_filepath, const flecs::world& p_registry) { + std::ifstream ins(p_filepath.string()); + std::stringstream ss; + ss << ins.rdbuf(); + + YAML::Node data = YAML::Load(ss.str()); + + if (!data["Scene"]) { + return false; + } + + YAML::Node entity_objects = data["Entities"]; + + if (entity_objects) { + for (YAML::iterator::value_type entity : entity_objects) { + std::string name = entity["Entity"].as(); + flecs::entity deserialize_to_object = + p_registry.entity(name.c_str()); + + // Deserialize atlas::transform component + deserialize_entity(entity, deserialize_to_object); + } + } + + return true; + } + + private: + ref m_current_scene_ctx; + }; + +}; // namespace atlas \ No newline at end of file diff --git a/atlas-modules/core/serialize/types.cppm b/atlas-modules/core/serialize/types.cppm new file mode 100644 index 00000000..67dc3be6 --- /dev/null +++ b/atlas-modules/core/serialize/types.cppm @@ -0,0 +1,493 @@ +module; + +#include +#include + +export module atlas.core.serialize.types; +import atlas.core.scene.components; + + +namespace YAML { + /** + * @brief Custom specialized classes from yaml-cpp to specialize to take in + * a glm::vec2 specifically + * + * Specialization is used for converting glm::vec2 to yaml-cpp syntax when + * saving glm::vec2 data to disk + */ + template<> + struct convert { + static Node encode(const glm::vec2& rhs) { + Node node; + node.push_back(rhs.x); + node.push_back(rhs.y); + + return node; + } + + static bool decode(const Node& node, glm::vec2& rhs) { + if (!node.IsSequence() || node.size() != 2) + return false; + + rhs.x = node[0].as(); + rhs.y = node[1].as(); + + return true; + } + }; + + /** + * @brief Custom specialized classes from yaml-cpp to specialize to take in + * a glm::vec3 specifically + * + * Specialization is used for converting glm::vec3 to yaml-cpp syntax when + * saving glm::vec3 data to disk + */ + template<> + struct convert { + static Node encode(const glm::vec3& rhs) { + Node node; + node.push_back(rhs.x); + node.push_back(rhs.y); + node.push_back(rhs.z); + + return node; + } + + static bool decode(const Node& node, glm::vec3& rhs) { + if (!node.IsSequence() || node.size() != 3) + return false; + + rhs.x = node[0].as(); + rhs.y = node[1].as(); + rhs.z = node[2].as(); + + return true; + } + }; + + /** + * @brief Custom specialized classes from yaml-cpp to specialize to take in + * a glm::vec4 specifically + * + * Specialization is used for converting glm::vec4 to yaml-cpp syntax when + * saving glm::vec4 data to disk + */ + template<> + struct convert { + + static Node encode(const glm::vec4& rhs) { + Node node; + node.push_back(rhs.x); + node.push_back(rhs.y); + node.push_back(rhs.z); + node.push_back(rhs.w); + + return node; + } + + static bool decode(const Node& node, glm::vec4& rhs) { + if (!node.IsSequence() || node.size() != 4) { + return false; + } + + rhs.x = node[0].as(); + rhs.y = node[1].as(); + rhs.z = node[2].as(); + rhs.w = node[3].as(); + return true; + } + }; + + template<> + struct convert { + + static Node encode(const atlas::mesh_source& rhs) { + Node node; + // Encode glm::vec3 members + node["Model"] = rhs.model_path; + node["Color"] = rhs.color; + node["Diffuse"] = rhs.diffuse; + node["Specular"] = rhs.specular; + return node; + } + + static bool decode(const Node& node, atlas::mesh_source& rhs) { + if (!node.IsMap()) { + return false; + } + + rhs.model_path = node["Model"].as(); + rhs.color = node["Angular Velocity"].as(); + rhs.diffuse = node["Force"].as(); + rhs.specular = node["Impulse"].as(); + return true; + } + }; + + template<> + struct convert { + + static Node encode(const atlas::point_light& rhs) { + Node node; + // Encode glm::vec3 members + node["Color"] = rhs.color; + node["Attenuation"] = rhs.attenuation; + node["Ambient"] = rhs.ambient; + node["Diffuse"] = rhs.diffuse; + node["Specular"] = rhs.specular; + return node; + } + + static bool decode(const Node& node, atlas::point_light& rhs) { + if (!node.IsMap()) { + return false; + } + + rhs.color = node["Color"].as(); + rhs.attenuation = node["Attenuation"].as(); + rhs.ambient = node["Ambient"].as(); + rhs.diffuse = node["Diffuse"].as(); + rhs.specular = node["Specular"].as(); + return true; + } + }; + + /** + * @brief Custom specialized classes from yaml-cpp to specialize to take in + * a atlas::body_type specifically + * + * Specialization is used for converting atlas::body_type to yaml-cpp syntax + * when saving atlas::body_type data to disk + */ + template<> + struct convert { + static Node encode(const atlas::body_type& rhs) { + Node node; + node.push_back(static_cast(rhs)); + return node; + } + + static bool decode(const Node& node, atlas::body_type& rhs) { + if (!node.IsScalar()) { + return false; + } + rhs = static_cast(node.as()); + return true; + } + }; + + /** + * @brief Custom specialized classes from yaml-cpp to specialize to take in + * a atlas::body_layer specifically + * + * Specialization is used for converting atlas::body_layer to yaml-cpp + * syntax when saving atlas::body_layer data to disk + */ + template<> + struct convert { + static Node encode(const atlas::body_layer& rhs) { + Node node; + node.push_back(static_cast(rhs)); + return node; + } + + static bool decode(const Node& node, atlas::body_layer& rhs) { + if (!node.IsScalar()) { + return false; + } + rhs = static_cast(node.as()); + return true; + } + }; + + /** + * @brief Custom specialized classes from yaml-cpp to specialize to take in + * a atlas::physics_body specifically + * + * Specialization is used for converting atlas::physics_body to yaml-cpp + * syntax when saving atlas::physics_body data to disk + */ + template<> + struct convert { + + static Node encode(const atlas::physics_body& rhs) { + Node node; + // Encode glm::vec3 members + node["Linear Velocity"] = rhs.linear_velocity; + node["Angular Velocity"] = rhs.angular_velocity; + node["Force"] = rhs.force; + node["Impulse"] = rhs.impulse; + node["Torque"] = rhs.torque; + node["Mass Factor"] = rhs.mass_factor; + node["Center Mass Position"] = rhs.center_mass_position; + // node["Gravity Enabled"] = rhs.use_gravity; + node["Gravity Factor"] = rhs.gravity_factor; + // node["Body Type"] = rhs.body_type; + node["Friction"] = rhs.friction; + node["Restitution"] = rhs.restitution; + node["Body Movement Type"] = rhs.body_movement_type; + node["Body Layer Type"] = rhs.body_layer_type; + + return node; + } + + static bool decode(const Node& node, atlas::physics_body& rhs) { + if (!node.IsMap()) { + return false; + } + + rhs.linear_velocity = node["Linear Velocity"].as(); + rhs.angular_velocity = node["Angular Velocity"].as(); + rhs.force = node["Force"].as(); + rhs.impulse = node["Impulse"].as(); + rhs.torque = node["Torque"].as(); + rhs.mass_factor = node["Mass Factor"].as(); + rhs.center_mass_position = + node["Center Mass Position"].as(); + rhs.gravity_factor = node["Gravity Factor"].as(); + rhs.friction = node["Friction"].as(); + rhs.restitution = node["Restitution"].as(); + rhs.body_movement_type = node["Body Movement Type"].as(); + rhs.body_layer_type = node["Body Layer Type"].as(); + return true; + } + }; + + /** + * @brief Custom specialized classes from yaml-cpp to specialize to take in + * a atlas::box_collider specifically + * + * Specialization is used for converting atlas::box_collider to yaml-cpp + * syntax when saving atlas::box_collider data to disk + */ + template<> + struct convert { + + static Node encode(const atlas::box_collider& rhs) { + Node node; + // Encode glm::vec3 members + node["Half Extent"] = rhs.half_extent; + + return node; + } + + static bool decode(const Node& node, atlas::box_collider& rhs) { + if (!node.IsMap()) { + return false; + } + + rhs.half_extent = node["half Extent"].as(); + return true; + } + }; + + /** + * @brief Custom specialized classes from yaml-cpp to specialize to take in + * a atlas::sphere_collider specifically + * + * Specialization is used for converting atlas::sphere_collider to yaml-cpp + * syntax when saving atlas::sphere_collider data to disk + */ + template<> + struct convert { + + static Node encode(const atlas::sphere_collider& rhs) { + Node node; + // Encode glm::vec3 members + node["Radius"] = rhs.radius; + + return node; + } + + static bool decode(const Node& node, atlas::sphere_collider& rhs) { + if (!node.IsMap()) { + return false; + } + + rhs.radius = node["Radius"].as(); + return true; + } + }; + + /** + * @brief Custom specialized classes from yaml-cpp to specialize to take in + * a atlas::capsule_collider specifically + * + * Specialization is used for converting atlas::capsule_collider to yaml-cpp + * syntax when saving atlas::capsule_collider data to disk + */ + template<> + struct convert { + + static Node encode(const atlas::capsule_collider& rhs) { + Node node; + // Encode glm::vec3 members + node["Half Height"] = rhs.half_height; + node["Radius"] = rhs.radius; + + return node; + } + + static bool decode(const Node& node, atlas::capsule_collider& rhs) { + if (!node.IsMap()) { + return false; + } + + rhs.radius = node["Radius"].as(); + rhs.half_height = node["Half height"].as(); + return true; + } + }; +}; + +export namespace atlas { + //! @brief from yaml-cpp, saving glm::highp_vec2 values to disk + YAML::Emitter& operator<<(YAML::Emitter& p_out, const glm::highp_vec2& p_values) { + p_out << YAML::Flow; + p_out << YAML::BeginSeq << p_values.x << p_values.y << YAML::EndSeq; + return p_out; + } + + //! @brief from yaml-cpp, saving glm::highp_vec3 values to disk + YAML::Emitter& operator<<(YAML::Emitter& p_out, const glm::highp_vec3& p_values) { + p_out << YAML::Flow; + p_out << YAML::BeginSeq << p_values.x << p_values.y << p_values.z + << YAML::EndSeq; + return p_out; + } + + //! @brief from yaml-cpp, saving glm::highp_vec4 values to disk + YAML::Emitter& operator<<(YAML::Emitter& p_out, const glm::highp_vec4& p_values) { + p_out << YAML::Flow; + p_out << YAML::BeginSeq << p_values.x << p_values.y << p_values.z + << p_values.w << YAML::EndSeq; + return p_out; + } + + //! @brief from yaml-cpp, saving transform values to disk + YAML::Emitter& operator<<(YAML::Emitter& p_output, const transform* p_transform) { + p_output << YAML::Key << "Transform"; + + p_output << YAML::BeginMap; + p_output << YAML::Key << "Position" << YAML::Value + << p_transform->position; + p_output << YAML::Key << "Scale" << YAML::Value << p_transform->scale; + p_output << YAML::Key << "Rotation" << YAML::Value + << p_transform->rotation; + p_output << YAML::Key << "Quaternion" << YAML::Value + << p_transform->quaternion; + p_output << YAML::EndMap; + return p_output; + } + + //! @brief from yaml-cpp, saving perspective_camera values to disk + YAML::Emitter& operator<<(YAML::Emitter& p_output, const perspective_camera* p_camera) { + p_output << YAML::Key << "PerspectiveCamera"; + + p_output << YAML::BeginMap; + p_output << YAML::Key << "Plane" << YAML::Value << p_camera->plane; + p_output << YAML::Key << "Active" << YAML::Value << p_camera->is_active; + p_output << YAML::Key << "Field of View" << YAML::Value + << p_camera->field_of_view; + p_output << YAML::EndMap; + return p_output; + } + + //! @brief from yaml-cpp, saving mesh_source values to disk + YAML::Emitter& operator<<(YAML::Emitter& p_output, const mesh_source* p_material) { + p_output << YAML::Key << "Mesh Source"; + + p_output << YAML::BeginMap; + p_output << YAML::Key << "Model Path" << YAML::Value + << p_material->model_path; + p_output << YAML::Key << "Diffuse" << YAML::Value + << p_material->diffuse; + p_output << YAML::Key << "Specular" << YAML::Value + << p_material->specular; + p_output << YAML::EndMap; + return p_output; + } + + //! @brief from yaml-cpp, saving mesh_source values to disk + YAML::Emitter& operator<<(YAML::Emitter& p_output, const point_light* p_material) { + p_output << YAML::Key << "Point Light"; + + p_output << YAML::BeginMap; + p_output << YAML::Key << "Color" << YAML::Value << p_material->color; + p_output << YAML::Key << "Attenuation" << YAML::Value + << p_material->attenuation; + p_output << YAML::Key << "Ambient" << YAML::Value + << p_material->ambient; + p_output << YAML::Key << "Diffuse" << YAML::Value + << p_material->diffuse; + p_output << YAML::Key << "Specular" << YAML::Value + << p_material->specular; + p_output << YAML::EndMap; + return p_output; + } + + //! @brief from yaml-cpp, saving physics_body values to disk + YAML::Emitter& operator<<(YAML::Emitter& p_output, const physics_body* p_body) { + p_output << YAML::Key << "Physics Body"; + + p_output << YAML::BeginMap; + p_output << YAML::Key << "Linear Velocity" << YAML::Value + << p_body->linear_velocity; + p_output << YAML::Key << "Angular Velocity" << YAML::Value + << p_body->angular_velocity; + p_output << YAML::Key << "Force" << YAML::Value << p_body->force; + p_output << YAML::Key << "Impulse" << YAML::Value << p_body->impulse; + p_output << YAML::Key << "Torque" << YAML::Value << p_body->torque; + p_output << YAML::Key << "Mass Factor" << YAML::Value + << p_body->mass_factor; + p_output << YAML::Key << "Center Mass Position" << YAML::Value + << p_body->center_mass_position; + p_output << YAML::Key << "Friction" << YAML::Value << p_body->friction; + p_output << YAML::Key << "Restitution" << YAML::Value + << p_body->restitution; + p_output << YAML::Key << "Body Movement Type" << YAML::Value + << static_cast(p_body->body_movement_type); + p_output << YAML::Key << "Body Layer Type" << YAML::Value + << static_cast(p_body->body_layer_type); + p_output << YAML::EndMap; + return p_output; + } + + //! @brief from yaml-cpp, saving box_collider values to disk + YAML::Emitter& operator<<(YAML::Emitter& p_output, const box_collider* p_body) { + // Tag this specific serialization values to the box collider + p_output << YAML::Key << "Box Collider"; + + p_output << YAML::BeginMap; + p_output << YAML::Key << "Half Extent" << YAML::Value + << p_body->half_extent; + p_output << YAML::EndMap; + + return p_output; + } + + //! @brief from yaml-cpp, saving sphere_collider values to disk + YAML::Emitter& operator<<(YAML::Emitter& p_output, const sphere_collider* p_body) { + p_output << YAML::Key << "Sphere Collider"; + + p_output << YAML::BeginMap; + p_output << YAML::Key << "Radius" << YAML::Value << p_body->radius; + + p_output << YAML::EndMap; + + return p_output; + } + + //! @brief from yaml-cpp, saving capsule_collider values to disk + YAML::Emitter& operator<<(YAML::Emitter& p_output, const capsule_collider* p_body) { + p_output << YAML::Key << "Capsule Collider"; + p_output << YAML::BeginMap; + p_output << YAML::Key << "Radius" << YAML::Value << p_body->radius; + p_output << YAML::Key << "Half Height" << YAML::Value + << p_body->half_height; + p_output << YAML::EndMap; + + return p_output; + } +}; \ No newline at end of file diff --git a/editor_modules/level_scene.cppm b/editor_modules/level_scene.cppm index e0d57028..e088fdfe 100644 --- a/editor_modules/level_scene.cppm +++ b/editor_modules/level_scene.cppm @@ -31,6 +31,8 @@ import atlas.core.editor.dockspace; import atlas.application; import atlas.core.ui.widgets; import atlas.core.editor.menu_item; +import atlas.core.serialize; +import atlas.logger; static void ui_component_list(flecs::entity& p_selected_entity) { std::string entity_name = p_selected_entity.name().c_str(); @@ -137,10 +139,6 @@ public: .rotation = { 2.30f, 95.90f, 91.80f }, .scale{ 1.f }, }); - viking_room.set({ - .model_path = "assets/models/cube.obj", - .diffuse = "assets/models/wood.png", - }); viking_room.set({ .radius = 1.0f, @@ -211,11 +209,6 @@ public: .position = { 0.f, 2.10f, -7.30f }, .scale = { 0.9f, 0.9f, 0.9f }, }); - - point_light.set({ - .model_path = "assets/models/cube.obj", - .diffuse = "assets/models/wood.png", - }); point_light.add(); // benchmark @@ -267,7 +260,7 @@ public: // gerald.add(); // TODO: Move this outside of level_scene - // m_deserializer_test = atlas::serializer(); + m_deserializer_test = atlas::serializer(); subscribe(this, &level_scene::collision_enter); @@ -281,6 +274,11 @@ public: ~level_scene() override = default; void start() { + m_deserializer_test = atlas::serializer(); + + if (!m_deserializer_test.load("LevelScene", *this)) { + console_log_error("Could not load yaml file LevelScene!!!"); + } } void on_update() { @@ -650,9 +648,13 @@ public: } void runtime_stop() { + reset_objects(); } void reset_objects() { + if (!m_deserializer_test.load("LevelScene", *this)) { + console_log_error("Could not load yaml file LevelScene!!!"); + } } private: @@ -663,7 +665,7 @@ private: } private: - // atlas::serializer m_deserializer_test; + atlas::serializer m_deserializer_test; flecs::entity m_selected_entity; atlas::game_object_optional m_current_entity; From 1ed71211fef14aa5dea8da3ccc6bc9c51a87bb3b Mon Sep 17 00:00:00 2001 From: SpinnerX Date: Tue, 13 Jan 2026 12:47:09 -0800 Subject: [PATCH 23/68] WIP -- re-added physics simulation to work again --- CMakeLists.txt | 20 + atlas-modules/core/math/types.cppm | 203 +++++++ .../drivers/jolt_cpp/broad_phase.cppm | 195 +++++++ .../drivers/jolt_cpp/contact_listener.cppm | 136 +++++ atlas-modules/drivers/jolt_cpp/context.cppm | 504 ++++++++++++++++++ atlas-modules/drivers/jolt_cpp/math.cppm | 70 +++ atlas-modules/drivers/physics_context.cppm | 289 ++++++++++ atlas-modules/physics/physics_engine.cppm | 204 +++++++ atlas-modules/physics/types.cppm | 217 ++++++++ editor_modules/level_scene.cppm | 77 ++- 10 files changed, 1911 insertions(+), 4 deletions(-) create mode 100644 atlas-modules/core/math/types.cppm create mode 100644 atlas-modules/drivers/jolt_cpp/broad_phase.cppm create mode 100644 atlas-modules/drivers/jolt_cpp/contact_listener.cppm create mode 100644 atlas-modules/drivers/jolt_cpp/context.cppm create mode 100644 atlas-modules/drivers/jolt_cpp/math.cppm create mode 100644 atlas-modules/drivers/physics_context.cppm create mode 100644 atlas-modules/physics/physics_engine.cppm create mode 100644 atlas-modules/physics/types.cppm diff --git a/CMakeLists.txt b/CMakeLists.txt index c7f88b0b..55fa7564 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -101,6 +101,12 @@ set_packages( nfd::nfd ) +target_compile_options( + ${PROJECT_NAME} + PUBLIC + -g -Wall -Wextra -Wno-missing-field-initializers -Wshadow -msse4.1 -mavx +) + target_sources(${PROJECT_NAME} PUBLIC FILE_SET CXX_MODULES TYPE CXX_MODULES @@ -114,6 +120,8 @@ target_sources(${PROJECT_NAME} PUBLIC atlas-modules/core/application.cppm atlas-modules/core/window.cppm + # math + atlas-modules/core/math/types.cppm atlas-modules/core/math/math.cppm atlas-modules/core/scene/components.cppm @@ -157,6 +165,18 @@ target_sources(${PROJECT_NAME} PUBLIC atlas-modules/drivers/vulkan/imgui_context.cppm + # physics + atlas-modules/drivers/physics_context.cppm + atlas-modules/physics/types.cppm + atlas-modules/physics/physics_engine.cppm + + # jolt_cpp + atlas-modules/drivers/jolt_cpp/math.cppm + atlas-modules/drivers/jolt_cpp/broad_phase.cppm + atlas-modules/drivers/jolt_cpp/contact_listener.cppm + atlas-modules/drivers/jolt_cpp/context.cppm + + atlas-modules/drivers/vulkan/vulkan.cppm atlas-modules/drivers/vulkan/utilities.cppm atlas-modules/drivers/vulkan/instance_context.cppm diff --git a/atlas-modules/core/math/types.cppm b/atlas-modules/core/math/types.cppm new file mode 100644 index 00000000..330b18bc --- /dev/null +++ b/atlas-modules/core/math/types.cppm @@ -0,0 +1,203 @@ +module; + +#include +#include + +export module atlas.core.math.types; + +export namespace atlas { + + /** + * @brief vector2 is to define as a centralized mathematical + * representation of types such as glm::vec2, but can be defined based to + * the needs of specific mathematical types. + * + * Representing a 2-component values mathematical type + * + * @tparam T is the specified vector2 type specific to the mathematical + * frameworks representation, such as it can be glm::vec2. + * + */ + template + struct vector2; + + /** + * @brief vector3 is to define a centralized wrapper as a mathematical + * representaiton for communicating vector3 types from frameworks to + * glm::vec3 + * + * Representing a 3-component value mathematical type + * + * @tparam T is the type of vector2 such as glm::vec3 + * + * Example Usage: + * + * ```C++ + * auto jolt_vec3 = RVec3::zeros(); + * glm::vec3 pos_values = atlas::vector3(jolt_vec3); + * ``` + */ + template + struct vector3 { + vector3() = default; + + vector3(const T& p_other) + : m_value(p_other) {} + + vector3(float x, float y, float z) + : m_value(x, y, z) {} + vector3(const std::initializer_list& values) + : m_value(*values.begin(), *values.begin() + 1, *values.begin() + 2) { + } + + operator glm::vec3() { return m_value; } + + glm::vec3 operator=(const T& p_other) { return p_other; } + + bool operator==(const glm::vec3& p_other) { + return (m_value.x == p_other.x and m_value.y == p_other.y and + m_value.z == p_other.z); + } + + private: + glm::vec3 m_value; + }; + + /** + * @brief vector4 is to define a centralized wrapper as a mathematical + * representaiton for communicating vector3 types from frameworks to + * glm::vec3 + * + * vector4 is for a 4-component value that represents a vector 4 type + * + * @tparam T is the type of vector4 that would represent such type as + * glm::vec4 + * + * Example Usage: + * + * ```C++ + * auto jolt_vec4 = RVec4::zeros(); + * glm::vec4 pos_values = atlas::vector4(jolt_vec4); + * ``` + */ + template + struct vector4 { + vector4() = default; + + vector4(const T& p_other) + : m_value(p_other) {} + + vector4(float x, float y, float z, float w) + : m_value(x, y, z, w) {} + + operator glm::vec4() { return m_value; } + + glm::vec4 operator=(const T& p_other) { return p_other; } + + bool operator==(const glm::vec4& p_other) { + return (m_value.x == p_other.x and m_value.y == p_other.y and + m_value.z == p_other.z and m_value.w == p_other.w); + } + + private: + glm::vec4 m_value; + }; + + template<> + struct vector2 { + vector2() = default; + + vector2(const glm::highp_vec2& p_other) + : m_value(p_other) {} + + operator glm::highp_vec2() { return m_value; } + + glm::highp_vec2 operator=(const glm::highp_vec2& p_other) { + return p_other; + } + + bool operator==(const glm::vec4& p_other) { + return (m_value.x == p_other.x and m_value.y == p_other.y); + } + + private: + glm::highp_vec2 m_value; + }; + + template<> + struct vector3 { + vector3() = default; + + vector3(const glm::highp_vec3& p_other) + : m_value(p_other) {} + + operator glm::highp_vec3() { return m_value; } + + glm::highp_vec3 operator=(const glm::highp_vec3& p_other) { + return p_other; + } + + bool operator==(const glm::highp_vec3& p_other) { + return (m_value.x == p_other.x and m_value.y == p_other.y and + m_value.z == p_other.z); + } + + private: + glm::highp_vec3 m_value; + }; + + template<> + struct vector4 { + vector4() = default; + + vector4(const glm::highp_vec4& p_other) + : m_value(p_other) {} + + operator glm::highp_vec4() { return m_value; } + + glm::highp_vec4 operator=(const glm::highp_vec4& p_other) { + return p_other; + } + + bool operator==(const glm::highp_vec4& p_other) { + return (m_value.x == p_other.x and m_value.y == p_other.y and + m_value.z == p_other.z and m_value.w == p_other.w); + } + + private: + glm::highp_vec4 m_value; + }; + + //! @brief generics to specialize to their mathematical definition of + //! matrices types + template + struct math_generic; + + template + struct matrix2; + + template + struct matrix3; + + template + struct matrix4; + + //! @brief By default we use the glm math types therefore we create all of + //! our default math types to glm's mathematical type + template + using vec = math_generic>; + using vec2 = vector2; + using vec3 = vector3; + using vec4 = vector4; + + using highp_vec2 = vector2; + using highp_vec3 = vector3; + using highp_vec4 = vector4; + + template + using mat = math_generic>; + + using mat2 = matrix2; + using mat3 = matrix3; + using mat4 = matrix4; +}; // namespace atlas \ No newline at end of file diff --git a/atlas-modules/drivers/jolt_cpp/broad_phase.cppm b/atlas-modules/drivers/jolt_cpp/broad_phase.cppm new file mode 100644 index 00000000..3d126942 --- /dev/null +++ b/atlas-modules/drivers/jolt_cpp/broad_phase.cppm @@ -0,0 +1,195 @@ +module; + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#include +#include +#include +#include +#include +#include + +#include + +// jolt's math includes +#include +#include +#include + +export module atlas.drivers.jolt_cpp.broad_phase; + +import atlas.common; + +export namespace atlas::physics { + + /** + * @brief This contains a few important comparisons having to do with + * setting up the oct-trees correctly as well as the filtering and collision + * interaction. + * + * @warning Most of these contain implicit conversions which might lead to + * unexpected behavior. This should probably be fixed or atleast checked + * eventually. + */ + + // This should eventually have a pipeline for the user to create masks. + enum class ObjectLayer : std::uint8_t { + NonMoving = 0, + Moving = 1, + NumLayers + }; + + enum class BroadPhaseLayers : std::uint8_t { + NonMoving = 0, + Moving = 1, + NumLayers + }; + + /** + * @brief This class is made to control the broadphase layer. Filters can be + * added to it to create a better and more organized broadphase. Ass well as + * giving some control to the user on how the broadphase should be + * organized. This requires dynamic masking however, which is not currently + * running. + * + */ + class broad_phase_layer_interface final + : public JPH::BroadPhaseLayerInterface { + public: + broad_phase_layer_interface() = default; + + /** + * @brief Get the Number of layers that exsist in the current context. + * Static for now. + * + * @return uint32_t + */ + [[nodiscard]] uint32_t GetNumBroadPhaseLayers() const override { + return (uint32_t)(BroadPhaseLayers::NumLayers); + } + + /** + * @brief Gives the caller access to the broadphase object. Allowing for + * some manipulation on how those interactions may go. Including but not + * limited to changing the filtering of the broadphase or reorganizing + * the oct-tree. + * + * @param p_in_layer The layer that the player wants. + * @return JPH::BroadPhaseLayer Object to organize and manipulate the + * oct-tree for that layer. + */ + [[nodiscard]] JPH::BroadPhaseLayer GetBroadPhaseLayer( + JPH::ObjectLayer p_in_layer) const override { + JPH_ASSERT(p_in_layer < (JPH::ObjectLayer)ObjectLayer::NumLayers); + return m_object_to_broadphase[p_in_layer]; + } + +#if defined(JPH_EXTERNAL_PROFILE) || defined(JPH_PROFILE_ENABLED) + /** + * @brief Only exsists for testing contexts or debug mode. Is made to + * return the names of the layers. Will be very helpful when the layers + * become dynamically created. + * + * @param p_in_layer The layer that the player wants as a name. + * @return const char* Name of the layer. + */ + [[nodiscard]] const char* GetBroadPhaseLayerName( + JPH::BroadPhaseLayer p_in_layer) const override { + switch (p_in_layer.GetValue()) { + case (JPH::BroadPhaseLayer::Type)(BroadPhaseLayers::NonMoving): + return "NonMoving"; + case (JPH::BroadPhaseLayer::Type)(BroadPhaseLayers::Moving): + return "Moving"; + default: + JPH_ASSERT(false); + return "Unknown"; + } + } +#endif + + private: + // The list of organizational layers + std::vector m_object_to_broadphase{ + JPH::BroadPhaseLayer((uint8_t)(BroadPhaseLayers::NonMoving)), + JPH::BroadPhaseLayer((uint8_t)(BroadPhaseLayers::Moving)) + + }; + }; + + /** + * @brief This is used to tell Jolt what can or cannot collide. As of right + * now the list is static therfore the layers do not need a dynamic set up. + * This will change when the object layers become user definable. + * + * @remark To give an example, there might exist something like this in the + * config of the editor: + * + * Dynamic Kenmatic Static + * Dynamic ✅ ✅ ✅ + * Kenmatic ✅ ✅ + * Static ✅ + * + * Where the interactions can partially be defined and controlled by the + * developer of the game. + */ + class object_vs_broadphase_layer final + : public JPH::ObjectVsBroadPhaseLayerFilter { + public: + [[nodiscard]] bool ShouldCollide( + JPH::ObjectLayer p_in_layer1, + JPH::BroadPhaseLayer p_in_layer2) const override { + switch (p_in_layer1) { + case (int)(ObjectLayer::NonMoving): + return p_in_layer2 == + JPH::BroadPhaseLayer((JPH::BroadPhaseLayer::Type)( + BroadPhaseLayers::Moving)); + case (int)ObjectLayer::Moving: + return true; + default: + JPH_ASSERT(false); + return false; + } + } + }; + + /** + * @brief This goes into more detailed ways of filtering, where the object + * collisions may be defined be what the other object is. In this case a + * static setup allows static object to trigger collision only when it is + * touched by a dynamic target. + * + */ + class object_layer_pair_filter final : public JPH::ObjectLayerPairFilter { + public: + [[nodiscard]] bool ShouldCollide( + JPH::ObjectLayer p_in_object1, + JPH::ObjectLayer p_in_object2) const override { + switch (p_in_object1) { + case (int)(ObjectLayer::NonMoving): + return p_in_object2 == (int)(ObjectLayer::Moving); + case (int)(ObjectLayer::Moving): + return true; + default: + JPH_ASSERT(false); + return false; + } + } + }; + +} \ No newline at end of file diff --git a/atlas-modules/drivers/jolt_cpp/contact_listener.cppm b/atlas-modules/drivers/jolt_cpp/contact_listener.cppm new file mode 100644 index 00000000..6a7dd005 --- /dev/null +++ b/atlas-modules/drivers/jolt_cpp/contact_listener.cppm @@ -0,0 +1,136 @@ +module; + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#include +#include +#include +#include +#include +#include + +#include + +// jolt's math includes +#include +#include +#include + +export module atlas.drivers.jolt_cpp.contact_listener; +import atlas.logger; +import atlas.core.event.bus; +import atlas.core.event.types; + +export namespace atlas::physics { + /** + * @brief implementation of Jolt's contact listener for collisions + * + * contact_listener gets set to Jolt's Physics System to allow for + * collisions to happen + */ + class contact_listener : public JPH::ContactListener { + public: + contact_listener(event::bus& p_bus) : m_bus(&p_bus) {} + + private: + /** + * @brief This allows us to make sure that the contacts are valid and + * not something that went wrong. It plays the role of both sanity check + * and saftey gaurd since if collisions were to be wrong you would not + * want that to crash the whole game. + * + * @param in_body1 is ID of the object1 who collided + * @param in_body2 is ID of object2 who object1 collided with + * @param in_base_offset for telling how far apart the center of the + * objects are + * @param in_collision_result The details about the collision + * @return JPH::ValidateResult + */ + JPH::ValidateResult OnContactValidate( + const JPH::Body& in_body1, + const JPH::Body& in_body2, + JPH::RVec3Arg in_base_offset, + const JPH::CollideShapeResult& in_collision_result) override { + return JPH::ValidateResult::AcceptAllContactsForThisBodyPair; + } + + /** + * @brief This gets triggered each time a collision comes into contact. + * It is only called once and then removed. + * + * @param body1 Body that called + * @param body2 Target body + * @param manifold This class has a lot of stuff including heights, + * directions, offset etc... + * @param settings This has some of the body settings these objects + * have. + */ + void OnContactAdded(const JPH::Body& p_body1, + const JPH::Body& p_body2, + const JPH::ContactManifold& manifold, + JPH::ContactSettings& settings) override { + event::collision_enter begin_event = { + .entity1 = static_cast(p_body1.GetUserData()), + .entity2 = static_cast(p_body2.GetUserData()) + }; + + // Publishes to all subscribers that this collision_enter event has + // occurred + m_bus->publish(begin_event); + } + + /** + * @brief This gets called multiple times. It is not in use yet. + * + * @param in_body1 Body that called + * @param in_body2 Target body + * @param in_manifold This class has a lot of stuff including heights, + * directions, offset etc... + * @param io_settings This specifically descibes the settings that + * contacts should have. + * FIXME: Still needs to be implemented + */ + void OnContactPersisted(const JPH::Body& p_body1, + const JPH::Body& p_body2, + const JPH::ContactManifold& in_manifold, + JPH::ContactSettings& io_settings) override { + event::collision_persisted persisted_event = { + .entity1 = static_cast(p_body1.GetUserData()), + .entity2 = static_cast(p_body2.GetUserData()) + }; + + m_bus->publish(persisted_event); + } + + /** + * @brief This is used to clean to shapes and call exiting functions for + * contact. + * + * @param in_sub_shape_pair The pair of shapes that no longer touch. + * FIXME: Still needs to be implemented + */ + void OnContactRemoved(const JPH::SubShapeIDPair& p_sub_shape_pair) override { + console_log_info("Collisions Removed!"); + // For Event system to handle when collision ends + } + + private: + event::bus* m_bus; + }; +}; \ No newline at end of file diff --git a/atlas-modules/drivers/jolt_cpp/context.cppm b/atlas-modules/drivers/jolt_cpp/context.cppm new file mode 100644 index 00000000..5ef59c6b --- /dev/null +++ b/atlas-modules/drivers/jolt_cpp/context.cppm @@ -0,0 +1,504 @@ +module; + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#include +#include +#include +#include +#include +#include + +#include + +// jolt's math includes +#include +#include +#include +#include +#include +#include + +export module atlas.drivers.jolt_cpp.context; + +import atlas.logger; +import atlas.common; +import atlas.core.scene.components; + +import atlas.drivers.jolt_cpp.broad_phase; +import atlas.drivers.jolt_cpp.contact_listener; + +import atlas.drivers.jolt_cpp.types; +import atlas.drivers.physics_context; +import atlas.core.event.bus; +import atlas.drivers.jolt_cpp.types; + +namespace atlas::physics { + + static void trace_impl(const char* p_in_fmt, ...) { + va_list list; + va_start(list, p_in_fmt); + char buffer[1024]; + vsnprintf(buffer, sizeof(buffer), p_in_fmt, list); + va_end(list); + console_log_error("{}", buffer); + } + + [[maybe_unused]] static bool assert_failed_impl(const char* p_in_expression, + const char* p_in_message, + const char* p_in_file, + unsigned int p_in_line) { + + console_log_error("{}:{}: ({}) {}", + p_in_file, + p_in_line, + p_in_expression, + (p_in_message != nullptr ? p_in_message : "")); + + return true; + }; + + /** + * @brief jolt_context is the backend implementation of physics context + * + * This is the jolt specific implementation of the physics context + * + * Represents the external abstraction that is defined through the the + * engine-specific parameters. + */ + export class jolt_context : public physics_context { + public: + /** + * @brief construct a new physics context with jolt implemented as its + * backend + * + * @param p_settings are the configuration parameters for initiating + * JoltPhysics + * @param p_bus is the event::bus that allows for publishing physics + * events to the subscribers of those said events + */ + jolt_context(const jolt_settings& p_settings, event::bus& p_bus) : m_contact_listener(p_bus) { + JPH::RegisterDefaultAllocator(); + + JPH::Trace = trace_impl; + JPH_IF_ENABLE_ASSERTS(JPH::AssertFailed = assert_failed_impl;) + + JPH::Factory::sInstance = new JPH::Factory(); + JPH::RegisterTypes(); + + m_temp_allocator = + create_ref(p_settings.allocation_amount); + + // This just sets up the JoltPhysics system and any listeners + m_physics_system = create_ref(); + m_broad_phase_layer_interface = + create_ref(); + m_object_vs_broadphase_filter = + create_ref(); + m_object_layer_pair_filter = create_ref(); + + if (p_settings.thread_type == thread_type::default_system) { + + m_thread_system = create_scope( + // Max jobs must be a power of 2, otherwise jph crashes. + // Bianary tree must be fully balanced + std::pow(2, p_settings.max_jobs_power), + p_settings.max_barriers, + p_settings.physics_threads); + } + else { + console_log_error("Unsupported custom job system"); + assert(false); + } + + m_physics_system->Init(p_settings.max_bodies, + 0, + p_settings.max_body_pairs, + p_settings.max_contact_constraints, + *m_broad_phase_layer_interface, + *m_object_vs_broadphase_filter, + *m_object_layer_pair_filter); + + // Default contact listener impl and can change during runtime + m_physics_system->SetContactListener(&m_contact_listener); + } + + ~jolt_context() override = default; + + private: + void prepare_and_finalize() override { + using namespace JPH; + + //! @brief We actually do not need to pass in the body ID's into + //! std::vector. Though we may need ways to store JPH::BodyID for + //! modifying specific bodies + JPH::BodyIDVector all_body_ids; + m_physics_system->GetBodies(all_body_ids); + + auto& body_interface = m_physics_system->GetBodyInterface(); + auto state = body_interface.AddBodiesPrepare( + all_body_ids.data(), static_cast(all_body_ids.size())); + body_interface.AddBodiesFinalize(all_body_ids.data(), + static_cast(all_body_ids.size()), + state, + JPH::EActivation::Activate); + } + + void update_simulation(float p_delta_time) override { + float fixed_time_step = 1.0f / 60.0f; + int time_step = 1 + (int)(60 * fixed_time_step); + m_physics_system->Update(p_delta_time, + time_step, + m_temp_allocator.get(), + m_thread_system.get()); + } + + /** + * @brief Performs any specific cleanup needed by Jolt + */ + void destroy_bodies() override { + auto& body_interface = m_physics_system->GetBodyInterface(); + + // Retrieve all body ID's to ensure that we do proper deactivation and + // post cleanup for the physics simulation + JPH::BodyIDVector all_body_ids; + m_physics_system->GetBodies(all_body_ids); + + if (!all_body_ids.empty()) { + + body_interface.DeactivateBodies( + all_body_ids.data(), static_cast(all_body_ids.size())); + + body_interface.RemoveBodies(all_body_ids.data(), + static_cast(all_body_ids.size())); + + body_interface.DestroyBodies(all_body_ids.data(), + static_cast(all_body_ids.size())); + + m_cached_body_ids.clear(); + } + } + + protected: + void emplace_box_collider(uint32_t p_entity_id, + const transform* p_transform, + const physics_body* p_body, + const box_collider* p_collider) override { + using namespace JPH; + auto& body_interface = m_physics_system->GetBodyInterface(); + + // Creating our box shape and specifying half_extent that is a glm::vec3 + // conversion to JPH::Vec3 half_extents must be 0.5f or else it can get + // an invalid convex radius + BoxShapeSettings shape_settings(jolt::to_vec3(p_collider->half_extent)); + auto result = shape_settings.Create(); + + if (result.HasError()) { + console_log_error("Box shape creation error: {}", + result.GetError()); + return; + } + EMotionType motion_type = EMotionType::Static; + switch (p_body->body_movement_type) { + case body_type::fixed: + motion_type = EMotionType::Static; + break; + case body_type::dynamic: + motion_type = EMotionType::Dynamic; + break; + case body_type::kinematic: + motion_type = EMotionType::Kinematic; + break; + } + + auto& box = result.Get(); + BodyCreationSettings body_settings( + box, + jolt::to_vec3(p_transform->position), + jolt::to_quat(p_transform->quaternion), + motion_type, + p_body->body_layer_type); + + // NOTE TO SELF ------ This is setting some pointer to the entity ID + // WE CAN USE THIS TO TELL THE EVENT SYSTEM WHICH FLECS ENTITY COLLIDED + // WITH EACH OTHER!!!!!!!! Because each contact listener allows you to + // take a pointer from the physics bodies that are just blocks of + // data!!! + body_settings.mUserData = static_cast(p_entity_id); + body_settings.mFriction = p_body->friction; + body_settings.mRestitution = p_body->restitution; + body_settings.mLinearVelocity = jolt::to_vec3(p_body->linear_velocity); + body_settings.mAngularVelocity = + jolt::to_vec3(p_body->angular_velocity); + + Body* body = body_interface.CreateBody(body_settings); + m_cached_body_ids.emplace(p_entity_id, body->GetID()); + } + + void emplace_sphere_collider( + uint32_t p_entity_id, + const transform* p_transform, + const physics_body* p_body, + const sphere_collider* p_collider) override { + using namespace JPH; + auto& body_interface = m_physics_system->GetBodyInterface(); + // ensure that the half_extent of the box shape always matches the + // object and reference that information through the transform + SphereShapeSettings shape_settings(p_collider->radius); + auto result = shape_settings.Create(); + + if (result.HasError()) { + console_log_error("Sphere shape creation error: {}", + result.GetError()); + return; + } + EMotionType motion_type = EMotionType::Static; + switch (p_body->body_movement_type) { + case body_type::fixed: { + motion_type = EMotionType::Static; + } break; + case body_type::dynamic: { + motion_type = EMotionType::Dynamic; + } break; + case body_type::kinematic: { + motion_type = EMotionType::Kinematic; + } break; + } + + auto& box = result.Get(); + BodyCreationSettings body_settings( + box, + jolt::to_vec3(p_transform->position), + jolt::to_quat(p_transform->quaternion), + motion_type, + p_body->body_layer_type); + + // Assigning the entity ID as the user data + // Fetched when collision happens + body_settings.mUserData = static_cast(p_entity_id); + body_settings.mFriction = p_body->friction; + body_settings.mRestitution = p_body->restitution; + body_settings.mLinearVelocity = jolt::to_vec3(p_body->linear_velocity); + body_settings.mAngularVelocity = + jolt::to_vec3(p_body->angular_velocity); + Body* body = body_interface.CreateBody(body_settings); + + // body_interface.AddForce(body->GetID(), + // jolt::to_vec3(p_body->cumulative_force)); + m_cached_body_ids.emplace(p_entity_id, body->GetID()); + } + + void emplace_capsule_collider( + uint32_t p_entity_id, + const transform* p_transform, + const physics_body* p_body, + const capsule_collider* p_collider) override { + using namespace JPH; + auto& body_interface = m_physics_system->GetBodyInterface(); + // ensure that the half_extent of the box shape always matches the + // object and reference that information through the transform + CapsuleShapeSettings shape_settings(p_collider->half_height, + p_collider->radius); + auto result = shape_settings.Create(); + + if (result.HasError()) { + console_log_error("Capsule shape creation error: {}", + result.GetError()); + return; + } + EMotionType motion_type = EMotionType::Static; + switch (p_body->body_movement_type) { + case body_type::fixed: { + motion_type = EMotionType::Static; + } break; + case body_type::dynamic: { + motion_type = EMotionType::Dynamic; + } break; + case body_type::kinematic: { + motion_type = EMotionType::Kinematic; + } break; + } + + auto& box = result.Get(); + BodyCreationSettings body_settings( + box, + jolt::to_vec3(p_transform->position), + jolt::to_quat(p_transform->quaternion), + motion_type, + p_body->body_layer_type); + body_settings.mFriction = p_body->friction; + body_settings.mRestitution = p_body->restitution; + body_settings.mLinearVelocity = jolt::to_vec3(p_body->linear_velocity); + body_settings.mAngularVelocity = + jolt::to_vec3(p_body->angular_velocity); + body_settings.mUserData = static_cast(p_entity_id); + + Body* body = body_interface.CreateBody(body_settings); + m_cached_body_ids.emplace(p_entity_id, body->GetID()); + } + + // void set_position_rotation(flecs::entity p_entity, const + // physics_body* p_body, const box_collider* p_collider, const + // transform* p_transform) override; + transform context_read_transform(uint32_t p_id) override { + using namespace JPH; + transform new_transform{}; + auto& body_interface = m_physics_system->GetBodyInterface(); + + BodyID body_id = m_cached_body_ids[p_id]; + JPH::Vec3 pos = body_interface.GetPosition(body_id); + JPH::Quat rot = body_interface.GetRotation(body_id); + JPH::Vec3 rot_euler = rot.GetEulerAngles(); + + new_transform.position = to_vec3(pos); + new_transform.quaternion = to_vec4(rot); + new_transform.rotation = to_vec3(rot_euler); + + return new_transform; + } + + physics_body context_read_physics_body(uint32_t p_id) override { + using namespace JPH; + auto& body_interface = m_physics_system->GetBodyInterface(); + + // TODO: Will need to change this because if this entity doesn't exist + // then it will be set to zeroes, gotta be careful about this + if (!m_cached_body_ids.contains(p_id)) { + return {}; + } + + auto body_id = m_cached_body_ids.at(p_id); + + physics_body body = { + .linear_velocity = + to_vec3(body_interface.GetLinearVelocity(body_id)), + .angular_velocity = + to_vec3(body_interface.GetAngularVelocity(body_id)), + .center_mass_position = + to_vec3(body_interface.GetCenterOfMassPosition(body_id)), + .gravity_factor = body_interface.GetGravityFactor(body_id), + .friction = body_interface.GetFriction(body_id), + .restitution = body_interface.GetRestitution(body_id), + }; + + return body; + } + + void linear_velocity(uint64_t p_id, + const glm::vec3& p_linear_velocity) override { + using namespace JPH; + auto& body_interface = m_physics_system->GetBodyInterface(); + + body_interface.SetLinearVelocity(m_cached_body_ids.at(p_id), + jolt::to_vec3(p_linear_velocity)); + } + + void angular_velocity(uint64_t p_id, + const glm::vec3& p_angular_velocity) override { + using namespace JPH; + auto& body_interface = m_physics_system->GetBodyInterface(); + BodyID body_id(p_id); + + body_interface.SetAngularVelocity(m_cached_body_ids.at(p_id), + jolt::to_vec3(p_angular_velocity)); + } + + void force(uint64_t p_id, const glm::vec3& p_force) override { + using namespace JPH; + auto& body_interface = m_physics_system->GetBodyInterface(); + BodyID body_id(p_id); + + body_interface.AddForce(m_cached_body_ids.at(p_id), + jolt::to_vec3(p_force)); + } + + void add_force_and_torque(uint64_t p_id, + const glm::vec3& p_force, + const glm::vec3& p_torque) override { + using namespace JPH; + auto& body_interface = m_physics_system->GetBodyInterface(); + + body_interface.AddForceAndTorque(m_cached_body_ids.at(p_id), + jolt::to_vec3(p_force), + jolt::to_vec3(p_torque)); + } + + void add_impulse(uint64_t p_id, const glm::vec3& p_impulse) override { + using namespace JPH; + auto& body_interface = m_physics_system->GetBodyInterface(); + + body_interface.AddImpulse(m_cached_body_ids.at(p_id), + jolt::to_vec3(p_impulse)); + } + + private: + //! @note Must be defined before physics can be initialized otherwise + //! jolt cannot be created properly. + jolt_settings m_settings; + + /** + * @brief Creates a static allocation of all data + * + */ + ref m_temp_allocator; + + /** + * @brief Sets up a thread system, either jolts or custom based on + * thread settings in m_settings + * + */ + scope m_thread_system; + + /** + * @brief Creates filtering for the quad tree in terms of movement + * + */ + ref m_broad_phase_layer_interface; + + /** + * @brief Creates a filter for the quad tree in terms of objects types + * + */ + ref m_object_vs_broadphase_filter; + + /** + * @brief Creates a filter for pairs of collisions + * + */ + ref m_object_layer_pair_filter; + + /** + * @brief Creates a way to recognize collisions + * + */ + // ref m_contact_listener; + contact_listener m_contact_listener; + + /** + * @brief Gives access to the physics system. Is given to jolt_api as + * well. This is to allow us to give seperation of concerns. However, + * may change now do to Jolt conflict and unhandled dangling pointers + * within jolt_api. + * + */ + ref m_physics_system; + + std::map m_cached_body_ids; + }; +}; \ No newline at end of file diff --git a/atlas-modules/drivers/jolt_cpp/math.cppm b/atlas-modules/drivers/jolt_cpp/math.cppm new file mode 100644 index 00000000..828b3a56 --- /dev/null +++ b/atlas-modules/drivers/jolt_cpp/math.cppm @@ -0,0 +1,70 @@ +module; + +#include +// jolt's math includes +#include +#include +#include + +#include +#define GLM_ENABLE_EXPERIMENTAL +#include +export module atlas.drivers.jolt_cpp.types; +import atlas.core.math.types; + +export namespace atlas { + template<> + struct vector3 { + vector3() = default; + + vector3(const JPH::Vec3& p_other) { + m_value = { p_other.GetX(), p_other.GetY(), p_other.GetZ() }; + } + + operator glm::vec3() { return m_value; } + + glm::vec3 operator=(const JPH::Vec3& p_other) { + return { p_other.GetX(), p_other.GetY(), p_other.GetZ() }; + } + + bool operator==(const glm::vec3& p_other) { + return (m_value.x == p_other.x and m_value.y == p_other.y and + m_value.z == p_other.z); + } + + private: + glm::vec3 m_value; + }; + + namespace jolt { + JPH::RVec3 to_rvec3(const glm::vec3& p_values) { + return { p_values.x, p_values.y, p_values.z }; + } + + JPH::Vec3 to_vec3(const glm::vec3& p_values) { + return { p_values.x, p_values.y, p_values.z }; + } + + JPH::Quat to_quat(const glm::vec4& q) { + return { q.x, q.y, q.z, q.w }; + } + + JPH::Quat to_quat(glm::quat& p_values) { + return JPH::Quat(p_values.w, p_values.x, p_values.y, p_values.z); + } + }; + + glm::quat to_quat(const JPH::Quat& p_values) { + return glm::quat( + p_values.GetW(), p_values.GetX(), p_values.GetY(), p_values.GetZ()); + } + + glm::vec3 to_vec3(const JPH::Vec3& p_values) { + return vector3(p_values); + } + + glm::vec4 to_vec4(const JPH::Quat& p_values) { + return glm::vec4( + p_values.GetX(), p_values.GetY(), p_values.GetZ(), p_values.GetW()); + } +}; \ No newline at end of file diff --git a/atlas-modules/drivers/physics_context.cppm b/atlas-modules/drivers/physics_context.cppm new file mode 100644 index 00000000..44bec3ec --- /dev/null +++ b/atlas-modules/drivers/physics_context.cppm @@ -0,0 +1,289 @@ +module; + +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#include +#include +#include +#include +#include +#include + +#include + +// jolt's math includes +#include +#include +#include +#include + +export module atlas.drivers.physics_context; + +import atlas.common; +import atlas.core.scene.components; +import atlas.core.event.bus; + + + +namespace atlas::physics { + export enum thread_type : uint8_t { + default_system = 0, + job_system = 1, + }; + + /** + * @brief Used to keep global data for player access and use. + * Tells how physics bodies should act within a given scene by + * default. + */ + struct jolt_config { + // Global gravity vector for all in scene + glm::vec3 gravity = glm::vec3(0.0f, -9.80665f, 0.0f); + + //! @brief In seconds + float time_before_sleep = 5.0f; + + // What 1 unit refers to in meters + float world_unit_scale = 1.0f; + + // Helps stop the lauching of objects during numerical/flaoting point + // errors when collision happen bertween to objects. + float contact_bias_factor = 0.2f; + float restitution_threshold = 1.0f; + + bool enable_constraints = true; + bool enable_collision_callbacks = true; + }; + + /** + * @brief Jolt-specific context configurations + * These are going to be internally integrated to jolt_context + * + * As these parameters currently are going to be specific to Jolt. + * + * These parameters are also only specific to the construction-level, not + * initiation level of the API's + * + * @remark Min and max world bounds are values that are artbitrary (in other + * words limit the simulation space) as JoltPhysics has a limit on distance + * for its limitation in simulation space + */ + export struct jolt_settings { + + uint32_t allocation_amount = 10 * 1024 * 1024; + + //! @brief Specifying which threading system to use for Jolt. + thread_type thread_type = thread_type::default_system; + + uint32_t physics_threads = + std::max(1u, std::thread::hardware_concurrency() - 2); + + uint32_t max_jobs_power = 10; + uint32_t max_barriers = physics_threads * 16; + bool enable_multithread = true; + + // Max memory size per scene + uint32_t max_bodies = 16384; + uint32_t max_body_pairs = 32768; + uint32_t max_contact_constraints = 8192; + }; + + // This might be able to be generalized eventually but we will have to + // create our own manifold before that happens. + struct contact_event { + uint64_t entity_a = 0; + uint64_t entity_b = 0; + JPH::ContactManifold manifold; + JPH::ContactSettings settings; + }; + + + /** + * @brief The context is the way to interact with specific backend context + * implementation such as JoltPhysics as our specific implementation-backend + * + * Provides API's to interact with the implemented physics context to run + * its simulation + * + */ + export class physics_context { + public: + virtual ~physics_context() = default; + + //! @brief Performs cleanup when simulation stops + void destroy() { return destroy_bodies(); } + + //! @brief updates our simulation using delta time and works with a + //! fixed timestep + void update(float p_delta_time) { + return update_simulation(p_delta_time); + } + + /** + * @brief As soon all physics bodies/colliders are created + * + * prepare() will be called to finalize all creation and apply them to + * the physics system for simulation + */ + void prepare() { return prepare_and_finalize(); } + + /** + * @param p_entity_id is the entity ID to associate with adding the + * sphere collider + * @param p_transform provide the location of the entity when creating + * this entity + * @param p_physics_body provide the actual physics body representation + * @param p_collider provides the actual sphere collider + */ + void add_box_collider(uint32_t p_entity_id, + const transform* p_transform, + const physics_body* p_body, + const box_collider* p_collider) { + return emplace_box_collider( + p_entity_id, p_transform, p_body, p_collider); + } + + /** + * @param p_entity_id is the entity ID to associate with adding the + * sphere collider + * @param p_transform provide the location of the entity when creating + * this entity + * @param p_physics_body provide the actual physics body representation + * @param p_collider provides the actual sphere collider + */ + void add_sphere_collider(uint32_t p_entity_id, + const transform* p_transform, + const physics_body* p_body, + const sphere_collider* p_collider) { + return emplace_sphere_collider( + p_entity_id, p_transform, p_body, p_collider); + } + + /** + * @param p_entity_id is the entity ID to associate with adding the + * sphere collider + * @param p_transform provide the location of the entity when creating + * this entity + * @param p_physics_body provide the actual physics body representation + * @param p_collider provides the actual capsule collider + */ + void add_capsule_collider(uint32_t p_entity_id, + const transform* p_transform, + const physics_body* p_body, + const capsule_collider* p_collider) { + return emplace_capsule_collider( + p_entity_id, p_transform, p_body, p_collider); + } + + /** + * @param p_id is the entity ID that is required to specifiy which + * entity this transform in physics simulation to return to + * @return transform back to the entity after its modification + */ + transform read_transform(uint32_t p_id) { + return context_read_transform(p_id); + } + + /** + * @param p_id is the entity ID that is required to specifiy which + * entity this transform in physics simulation to return to + * @return physics body back to the entity after its modification + */ + physics_body read_physics_body(uint32_t p_id) { + return context_read_physics_body(p_id); + } + + void set_linear_velocity(uint64_t p_id, + const glm::vec3& p_linear_velocity) { + return linear_velocity(p_id, p_linear_velocity); + } + + void set_angular_velocity(uint64_t p_id, + const glm::vec3& p_angular_velocity) { + return angular_velocity(p_id, p_angular_velocity); + } + + void set_force(uint64_t p_id, const glm::vec3& p_force) { + return force(p_id, p_force); + } + + void set_force_and_torque(uint64_t p_id, + const glm::vec3& p_force, + const glm::vec3& p_torque) { + add_force_and_torque(p_id, p_force, p_torque); + } + + void set_impulse(uint64_t p_id, const glm::vec3& p_impulse) { + add_impulse(p_id, p_impulse); + } + + private: + virtual void destroy_bodies() = 0; + + /** + * @brief Any emplace_* specific function are specific collider + * implementation-specific to the backend (context) API's they are + * implemented with + * + * Since colliders have specific parameters that define them. It would + * simplify what parameter-access they have when adding these specific + * colliders to the physics system + */ + virtual void emplace_box_collider(uint32_t p_entity_id, + const transform* p_transform, + const physics_body* p_body, + const box_collider* p_collider) = 0; + + virtual void emplace_sphere_collider( + uint32_t p_entity_id, + const transform* p_transform, + const physics_body* p_body, + const sphere_collider* p_collider) = 0; + + virtual void emplace_capsule_collider( + uint32_t p_entity_id, + const transform* p_transform, + const physics_body* p_body, + const capsule_collider* p_collider) = 0; + + virtual transform context_read_transform(uint32_t p_id) = 0; + + virtual physics_body context_read_physics_body(uint32_t p_id) = 0; + + virtual void prepare_and_finalize() = 0; + + virtual void update_simulation(float p_delta_time) = 0; + + virtual void linear_velocity(uint64_t p_id, const glm::vec3&) = 0; + + virtual void angular_velocity(uint64_t p_id, const glm::vec3&) = 0; + + virtual void force(uint64_t p_id, + const glm::vec3& p_cumulative_force) = 0; + + virtual void add_force_and_torque(uint64_t p_id, + const glm::vec3& p_force, + const glm::vec3& p_torque) = 0; + + virtual void add_impulse(uint64_t p_id, const glm::vec3& p_impulse) = 0; + }; +}; \ No newline at end of file diff --git a/atlas-modules/physics/physics_engine.cppm b/atlas-modules/physics/physics_engine.cppm new file mode 100644 index 00000000..f4e81745 --- /dev/null +++ b/atlas-modules/physics/physics_engine.cppm @@ -0,0 +1,204 @@ +module; + +#include +#include + +export module atlas.physics.engine; + +import atlas.common; +import atlas.core.scene.components; +import atlas.core.event.bus; +import atlas.drivers.physics_context; +import atlas.drivers.physics_context; +import atlas.drivers.jolt_cpp.context; + +namespace atlas::physics { + + //! @brief initializes the physics backend. SHOULD have an API associated + //! with but for now, we assume we only have JoltPhysics as our only physics + //! backend + ref initialize_physics_context(const jolt_settings& p_settings, event::bus& p_bus) { + return create_ref(p_settings, p_bus); + } + + /** + * @brief The manager class for all physics engines. Manages the physics + * contexts and the collision engines. + * + */ + export class engine { + public: + // Required by maps but should not be used in anyother circumstance. + engine() = default; + engine(flecs::world& p_registry, + event::bus& p_bus, + const jolt_settings& p_settings={}) : m_registry(&p_registry), m_bus(&p_bus) { + m_physics_context = initialize_physics_context(p_settings, *m_bus); + + // This may change, but for now we want to ensure that we only want to + // create a single physics body with a specific collider Rather then + // having multiple colliders be associated to a single physics body + // itself. + m_query_box_collider = + m_registry->query_builder() + .without() + .build(); + m_query_sphere_collider = + m_registry->query_builder() + .without() + .build(); + m_query_capsule_collider = + m_registry->query_builder() + .without() + .build(); + + m_physics_bodies = m_registry->query_builder().build(); + } + + /** + * @brief The runtime is specifically the way to start the physics, + * utilizing defined data from level_scene and eventually any scene to + * create a physics scene and manage physics step. + * + */ + void start() { + // At the start of every simulation we create physics bodies to run + // simulation on those physics bodies with the specific colliders + // associated with them + m_query_box_collider.each([this](flecs::entity p_entity, + transform& p_transform, + physics_body& p_body, + box_collider& p_collider) { + m_physics_context->add_box_collider( + p_entity.id(), &p_transform, &p_body, &p_collider); + }); + + m_query_sphere_collider.each([this](flecs::entity p_entity, + transform& p_transform, + physics_body& p_body, + sphere_collider& p_collider) { + m_physics_context->add_sphere_collider( + p_entity.id(), &p_transform, &p_body, &p_collider); + }); + + m_query_capsule_collider.each([this](flecs::entity p_entity, + transform& p_transform, + physics_body& p_body, + capsule_collider& p_collider) { + m_physics_context->add_capsule_collider( + p_entity.id(), &p_transform, &p_body, &p_collider); + }); + m_physics_context->prepare(); + } + + /** + * @brief Runs a single frame of the simulation. Should at minimum be + * called 60 fps. If below, it must be called twice. + * + */ + void update(float p_delta_time) { + using namespace JPH; + + m_physics_bodies.each( + [this](flecs::entity p_entity, physics_body& p_body) { + m_physics_context->set_force_and_torque( + p_entity.id(), p_body.force, p_body.torque); + m_physics_context->set_linear_velocity(p_entity.id(), + p_body.linear_velocity); + m_physics_context->set_angular_velocity(p_entity.id(), + p_body.angular_velocity); + m_physics_context->set_impulse(p_entity.id(), p_body.impulse); + }); + // This will ensure all physics bodies with which colliders they are + // associated with are update with the simulation, and their parameters + // are modified + m_physics_context->update(p_delta_time); + + m_query_box_collider.each([&](flecs::entity p_entity, + transform& p_transform, + physics_body& p_body, + box_collider&) { + // updating transform + transform t = m_physics_context->read_transform(p_entity.id()); + p_transform.position = t.position; + p_transform.rotation = t.rotation; + p_transform.quaternion = t.quaternion; + + // physics bodies parameters + auto body = m_physics_context->read_physics_body(p_entity.id()); + p_body.linear_damping = body.linear_damping; + p_body.linear_velocity = body.linear_velocity; + p_body.angular_velocity = body.angular_velocity; + p_body.gravity_factor = body.gravity_factor; + p_body.center_mass_position = body.center_mass_position; + p_body.friction = body.friction; + p_body.restitution = body.restitution; + p_body.angular_velocity = body.angular_velocity; + p_body.linear_velocity = body.linear_velocity; + }); + + // updating sphere collider + m_query_sphere_collider.each([this](flecs::entity p_entity, + transform& p_transform, + physics_body& p_body, + sphere_collider&) { + // updating transform + transform t = m_physics_context->read_transform(p_entity.id()); + p_transform.position = t.position; + p_transform.rotation = t.rotation; + p_transform.quaternion = t.quaternion; + + // updating physics body + auto body = m_physics_context->read_physics_body(p_entity.id()); + p_body.linear_damping = body.linear_damping; + p_body.linear_velocity = body.linear_velocity; + p_body.angular_velocity = body.angular_velocity; + p_body.gravity_factor = body.gravity_factor; + p_body.center_mass_position = body.center_mass_position; + p_body.friction = body.friction; + p_body.restitution = body.restitution; + }); + + // updating capsule collider + m_query_capsule_collider.each([this](flecs::entity p_entity, + transform& p_transform, + physics_body& p_body, + capsule_collider&) { + transform t = m_physics_context->read_transform(p_entity.id()); + p_transform.position = t.position; + p_transform.rotation = t.rotation; + p_transform.quaternion = t.quaternion; + + auto body = m_physics_context->read_physics_body(p_entity.id()); + p_body.linear_damping = body.linear_damping; + p_body.linear_velocity = body.linear_velocity; + p_body.angular_velocity = body.angular_velocity; + p_body.gravity_factor = body.gravity_factor; + p_body.center_mass_position = body.center_mass_position; + p_body.friction = body.friction; + p_body.restitution = body.restitution; + }); + } + + /** + * @brief Deletes all physics bodies and shapes. Preps itself for + * runtime to be called again. + * + */ + void stop() { + m_physics_context->destroy(); + } + + private: + flecs::world* m_registry; + ref m_physics_context; + flecs::query m_physics_bodies; + flecs::query + m_query_box_collider; + flecs::query + m_query_sphere_collider; + flecs::query + m_query_capsule_collider; + event::bus* m_bus; + }; +}; \ No newline at end of file diff --git a/atlas-modules/physics/types.cppm b/atlas-modules/physics/types.cppm new file mode 100644 index 00000000..8640ab85 --- /dev/null +++ b/atlas-modules/physics/types.cppm @@ -0,0 +1,217 @@ +module; +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#include +#include +#include +#include +#include +#include + +#include + +// jolt's math includes +#include +#include +#include + +export module atlas.physics.types; + +export namespace atlas::physics { + + template + struct vector3; + + template<> + struct vector3 { + vector3() = default; + + vector3(const JPH::Vec3& v) { + m_value = { v.GetX(), v.GetY(), v.GetZ() }; + } + + operator glm::vec3() const { return m_value; } + + glm::vec3 operator=(const JPH::Vec3& v) { + m_value = { v.GetX(), v.GetY(), v.GetZ() }; + return m_value; + } + + bool operator==(const glm::vec3& other) const { + return m_value == other; + } + + private: + glm::vec3 m_value; + }; + + template<> + struct vector3 { + vector3() = default; + + vector3(const JPH::Float3& v) { m_value = { v.x, v.y, v.z }; } + + operator glm::vec3() const { return m_value; } + + glm::vec3 operator=(const JPH::Float3& v) { + m_value = { v.x, v.y, v.z }; + return m_value; + } + + bool operator==(const glm::vec3& other) const { + return m_value == other; + } + + private: + glm::vec3 m_value; + }; + + template<> + struct vector3 { + vector3() = default; + + vector3(const JPH::DVec3& v) { + m_value = { v.GetX(), v.GetY(), v.GetZ() }; + } + + operator glm::dvec3() const { return m_value; } + + glm::dvec3 operator=(const JPH::DVec3& v) { + m_value = { v.GetX(), v.GetY(), v.GetZ() }; + return m_value; + } + + bool operator==(const glm::dvec3& other) const { + return m_value == other; + } + + private: + glm::dvec3 m_value; + }; + + template<> + struct vector3 { + vector3() = default; + + vector3(const JPH::Double3& v) { m_value = { v.x, v.y, v.z }; } + + operator glm::dvec3() const { return m_value; } + + glm::dvec3 operator=(const JPH::Double3& v) { + m_value = { v.x, v.y, v.z }; + return m_value; + } + + bool operator==(const glm::dvec3& other) const { + return m_value == other; + } + + private: + glm::dvec3 m_value; + }; + + template + struct vector4; + + template<> + struct vector4 { + vector4() = default; + + vector4(const JPH::Vec4& v) { + m_value = { v.GetX(), v.GetY(), v.GetZ(), v.GetW() }; + } + + operator glm::vec4() const { return m_value; } + + glm::vec4 operator=(const JPH::Vec4& v) { + m_value = { v.GetX(), v.GetY(), v.GetZ(), v.GetW() }; + return m_value; + } + + bool operator==(const glm::vec4& other) const { + return m_value == other; + } + + private: + glm::vec4 m_value; + }; + + template<> + struct vector4 { + vector4() = default; + + vector4(const JPH::Float4& v) { m_value = { v.x, v.y, v.z, v.w }; } + + operator glm::vec4() const { return m_value; } + + glm::vec4 operator=(const JPH::Float4& v) { + m_value = { v.x, v.y, v.z, v.w }; + return m_value; + } + + bool operator==(const glm::vec4& other) const { + return m_value == other; + } + + private: + glm::vec4 m_value; + }; + + // === QUATERNION ADAPTER === + template + struct quaternion; + + // === MATRIX4 ADAPTER === + template + struct matrix4; + + template<> + struct matrix4 { + matrix4() = default; + + matrix4(const JPH::Mat44& m) { + for (int i = 0; i < 4; ++i) { + const auto col = m.GetColumn4(i); + m_value[i] = + glm::vec4(col.GetX(), col.GetY(), col.GetZ(), col.GetW()); + } + } + + operator glm::mat4() const { return m_value; } + + glm::mat4 operator=(const JPH::Mat44& m) { + for (int i = 0; i < 4; ++i) { + const auto col = m.GetColumn4(i); + m_value[i] = + glm::vec4(col.GetX(), col.GetY(), col.GetZ(), col.GetW()); + } + return m_value; + } + + bool operator==(const glm::mat4& other) const { + return m_value == other; + } + + private: + glm::mat4 m_value; + }; +}; \ No newline at end of file diff --git a/editor_modules/level_scene.cppm b/editor_modules/level_scene.cppm index e088fdfe..8d75f62f 100644 --- a/editor_modules/level_scene.cppm +++ b/editor_modules/level_scene.cppm @@ -33,6 +33,7 @@ import atlas.core.ui.widgets; import atlas.core.editor.menu_item; import atlas.core.serialize; import atlas.logger; +import atlas.physics.engine; static void ui_component_list(flecs::entity& p_selected_entity) { std::string entity_name = p_selected_entity.name().c_str(); @@ -279,18 +280,21 @@ public: if (!m_deserializer_test.load("LevelScene", *this)) { console_log_error("Could not load yaml file LevelScene!!!"); } + + flecs::world registry = *this; + m_physics_engine = atlas::physics::engine(registry, *event_handle()); } void on_update() { auto query_cameras = query_builder().build(); + float dt = atlas::application::delta_time(); - query_cameras.each([this](atlas::perspective_camera& p_camera, + query_cameras.each([this, dt](atlas::perspective_camera& p_camera, atlas::transform& p_transform) { if (!p_camera.is_active) { return; } - float dt = atlas::application::delta_time(); float default_speed = 10.f; // current default movement speed that does // not applied modified speed float rotation_speed = 1.f; @@ -337,6 +341,14 @@ public: p_transform.set_rotation(p_transform.rotation); }); + + if (m_physics_runtime) { + m_physics_engine.update(dt); + } + + if (atlas::event::is_key_pressed(key_l) and m_physics_runtime) { + runtime_stop(); + } } void on_ui_update() { @@ -642,12 +654,57 @@ public: } void physics_update() { + float dt = atlas::application::delta_time(); + if (atlas::event::is_key_pressed(key_r) and !m_physics_runtime) { + runtime_start(); + } + + auto viking_room = entity("Viking Room"); + + atlas::physics_body* sphere_body = + viking_room.get_mut(); + // U = +up + // J = -up + // H = +left + // L = -Left + if (atlas::event::is_key_pressed(key_space)) { + glm::vec3 linear_velocity = { 0.f, 10.0f, 0.f }; + sphere_body->linear_velocity = linear_velocity; + sphere_body->impulse = linear_velocity; + } + + if (atlas::event::is_key_pressed(key_j)) { + glm::vec3 angular_vel = { -10.f, 0.f, 0.f }; + sphere_body->angular_velocity = angular_vel; + } + + if (atlas::event::is_key_pressed(key_h)) { + glm::vec3 angular_vel = { 10.f, 0.f, 0.f }; + sphere_body->angular_velocity = angular_vel; + } + + if (atlas::event::is_key_pressed(key_l)) { + glm::vec3 angular_vel = { -0.1f, 0.f, 0.f }; + sphere_body->angular_velocity = angular_vel; + } + + if (m_physics_runtime) { + m_physics_engine.update(dt); + } + + if (atlas::event::is_key_pressed(key_l) and m_physics_runtime) { + runtime_stop(); + } } void runtime_start() { + m_physics_runtime = true; + m_physics_engine.start(); } void runtime_stop() { + m_physics_runtime = false; + m_physics_engine.stop(); reset_objects(); } @@ -659,9 +716,21 @@ public: private: void collision_enter(atlas::event::collision_enter& p_event) { + console_log_warn("collision_enter event!!!"); + atlas::game_object e1 = entity(p_event.entity1); + atlas::game_object e2 = entity(p_event.entity2); + + console_log_warn("Entity1 = {}", e1.name().c_str()); + console_log_warn("Entity2 = {}", e2.name().c_str()); } void collision_persisted(atlas::event::collision_persisted& p_event) { + console_log_warn("collision_persisted(p_event) invoked!!"); + atlas::game_object e1 = entity(p_event.entity1); + atlas::game_object e2 = entity(p_event.entity2); + + console_log_warn("Entity1 = {}", e1.name().c_str()); + console_log_warn("Entity2 = {}", e2.name().c_str()); } private: @@ -673,9 +742,9 @@ private: // Setting physics system // TODO -- when refactoring this would be at atlas::world level - // atlas::physics::physics_engine m_physics_engine; + atlas::physics::engine m_physics_engine; - // bool m_physics_runtime = false; + bool m_physics_runtime = false; atlas::ui::dockspace m_editor_dockspace; atlas::ui::menu_item m_editor_menu; From 222baa8dadbbcc29a779b86ee7d147f5ff5607a8 Mon Sep 17 00:00:00 2001 From: SpinnerX Date: Tue, 13 Jan 2026 12:52:09 -0800 Subject: [PATCH 24/68] WIP -- added another game object to level_scene --- editor_modules/level_scene.cppm | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/editor_modules/level_scene.cppm b/editor_modules/level_scene.cppm index 8d75f62f..1d623d4b 100644 --- a/editor_modules/level_scene.cppm +++ b/editor_modules/level_scene.cppm @@ -257,8 +257,8 @@ public: // }); // } - // atlas::game_object gerald = entity("Gerald"); - // gerald.add(); + atlas::game_object gerald = entity("Gerald"); + gerald.add(); // TODO: Move this outside of level_scene m_deserializer_test = atlas::serializer(); From 1e705d7d065a6ee5056db16ff3e9aafc70650054 Mon Sep 17 00:00:00 2001 From: SpinnerX Date: Tue, 13 Jan 2026 13:01:55 -0800 Subject: [PATCH 25/68] WIP -- made the entry point automated to be internal --- CMakeLists.txt | 9 ++ atlas-modules/core/entry_point/main.cpp | 81 +++++++++++++++ editor_modules/application.cpp | 126 ++++++++++++------------ 3 files changed, 153 insertions(+), 63 deletions(-) create mode 100644 atlas-modules/core/entry_point/main.cpp diff --git a/CMakeLists.txt b/CMakeLists.txt index 55fa7564..54aafb23 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -184,6 +184,15 @@ target_sources(${PROJECT_NAME} PUBLIC atlas-modules/drivers/vulkan/physical_device.cppm atlas-modules/drivers/vulkan/device.cppm atlas-modules/drivers/vulkan/swapchain.cppm + + # entry point + # atlas-modules/core/entry_point/main.cppm +) + +target_sources(${PROJECT_NAME} PUBLIC + FILE_SET CXX_MODULES + TYPE CXX_MODULES + PRIVATE atlas-modules/core/entry_point/main.cpp ) # target_sources(${PROJECT_NAME} PUBLIC diff --git a/atlas-modules/core/entry_point/main.cpp b/atlas-modules/core/entry_point/main.cpp new file mode 100644 index 00000000..0f84ba70 --- /dev/null +++ b/atlas-modules/core/entry_point/main.cpp @@ -0,0 +1,81 @@ + +#include +import atlas.application; +import atlas.common; +import atlas.logger; +import atlas.graphics_api; + +import atlas.core.utilities.state; + +// expose visibility to ref +import atlas.drivers.graphics_context; + +// this includes initialize_context +import atlas.drivers; +import atlas.core.scene.system_registry; + +// Defined in the user-application side +[[nodiscard]] atlas::ref initialize_application(); + + +// /* +// atlas/* +// core/* +// import atlas.core; +// drivers/ +// vulkan +// import atlas.vulkan +// jolt_cpp +// import atlas.jolt_cpp +// .... +// physics +// import atlas.physics +// renderer +// import atlas.renderer +// */ + +// /* +// core: module that is partitioned associated with +// logger +// import logger; +// drivers: +// vulkan: module that is partitioned associated with +// import vulkan; +// internal: export module vulkan:* +// jolt_cpp: module that is partitioned associated with +// import jolt_cpp +// internal: export module jolt_cpp:* +// atlas: global module unit +// export import core; +// export import vulkan; +// export import jolt_cpp +// */ + +int main() { + atlas::console_log_manager manager = atlas::console_log_manager(); + + if(!glfwInit()) { + console_log_fatal("GLFW: Initialization failed!!"); + return -1; + } + + // atlas::application_settings settings = { + // .name = "Editor", + // .width = 1900, + // .height = 600, + // .background_color = {1.f, 1.f, 1.f, 1.f}, + // }; + // atlas::ref app = atlas::create_ref(settings); + + atlas::ref system = atlas::create_ref("system"); + atlas::ref context = atlas::initialize_context("vulkan", atlas::graphics_api::vulkan); + + atlas::ref app = initialize_application(); + + app->execute(); + + app->post_destroy(); + + context->destroy(); + return 0; +} \ No newline at end of file diff --git a/editor_modules/application.cpp b/editor_modules/application.cpp index 59f40b43..e967885e 100644 --- a/editor_modules/application.cpp +++ b/editor_modules/application.cpp @@ -38,12 +38,12 @@ class test_application : public atlas::application { }; -/* +// /* -TODO: Pre-defined this in TheAtlasEngine -* Then to have the implemented by the application +// TODO: Pre-defined this in TheAtlasEngine +// * Then to have the implemented by the application -*/ +// */ atlas::ref initialize_application() { atlas::application_settings settings = { .name = "Editor", @@ -55,64 +55,64 @@ atlas::ref initialize_application() { } -// /* -// atlas/* -// core/* -// import atlas.core; -// drivers/ -// vulkan -// import atlas.vulkan -// jolt_cpp -// import atlas.jolt_cpp -// .... -// physics -// import atlas.physics -// renderer -// import atlas.renderer -// */ - -// /* -// core: module that is partitioned associated with -// logger -// import logger; -// drivers: -// vulkan: module that is partitioned associated with -// import vulkan; -// internal: export module vulkan:* -// jolt_cpp: module that is partitioned associated with -// import jolt_cpp -// internal: export module jolt_cpp:* -// atlas: global module unit -// export import core; -// export import vulkan; -// export import jolt_cpp -// */ - -int main() { - atlas::console_log_manager manager = atlas::console_log_manager(); - - if(!glfwInit()) { - console_log_fatal("GLFW: Initialization failed!!"); - return -1; - } - - // atlas::application_settings settings = { - // .name = "Editor", - // .width = 1900, - // .height = 600, - // .background_color = {1.f, 1.f, 1.f, 1.f}, - // }; - // atlas::ref app = atlas::create_ref(settings); - - atlas::ref system = atlas::create_ref("system"); - atlas::ref context = atlas::initialize_context("vulkan", atlas::graphics_api::vulkan); - - atlas::ref app = initialize_application(); - - app->execute(); +// // /* +// // atlas/* +// // core/* +// // import atlas.core; +// // drivers/ +// // vulkan +// // import atlas.vulkan +// // jolt_cpp +// // import atlas.jolt_cpp +// // .... +// // physics +// // import atlas.physics +// // renderer +// // import atlas.renderer +// // */ + +// // /* +// // core: module that is partitioned associated with +// // logger +// // import logger; +// // drivers: +// // vulkan: module that is partitioned associated with +// // import vulkan; +// // internal: export module vulkan:* +// // jolt_cpp: module that is partitioned associated with +// // import jolt_cpp +// // internal: export module jolt_cpp:* +// // atlas: global module unit +// // export import core; +// // export import vulkan; +// // export import jolt_cpp +// // */ + +// int main() { +// atlas::console_log_manager manager = atlas::console_log_manager(); + +// if(!glfwInit()) { +// console_log_fatal("GLFW: Initialization failed!!"); +// return -1; +// } + +// // atlas::application_settings settings = { +// // .name = "Editor", +// // .width = 1900, +// // .height = 600, +// // .background_color = {1.f, 1.f, 1.f, 1.f}, +// // }; +// // atlas::ref app = atlas::create_ref(settings); + +// atlas::ref system = atlas::create_ref("system"); +// atlas::ref context = atlas::initialize_context("vulkan", atlas::graphics_api::vulkan); + +// atlas::ref app = initialize_application(); + +// app->execute(); - app->post_destroy(); +// app->post_destroy(); - context->destroy(); - return 0; -} \ No newline at end of file +// context->destroy(); +// return 0; +// } \ No newline at end of file From a959a6c976a77eeebde54a8650b65db91f71b4d8 Mon Sep 17 00:00:00 2001 From: SpinnerX Date: Tue, 13 Jan 2026 13:04:44 -0800 Subject: [PATCH 26/68] WIP -- cleaned up editor/application.cpp --- editor_modules/application.cpp | 86 +--------------------------------- 1 file changed, 1 insertion(+), 85 deletions(-) diff --git a/editor_modules/application.cpp b/editor_modules/application.cpp index e967885e..ba72fb14 100644 --- a/editor_modules/application.cpp +++ b/editor_modules/application.cpp @@ -1,20 +1,7 @@ -// import atlas; -#include -#include -#include -#include - import atlas.application; import atlas.common; import atlas.logger; -import atlas.graphics_api; - -import atlas.core.utilities.state; -import atlas.drivers.graphics_context; -import atlas.drivers; -import atlas.core.event; -import atlas.core.event.keys; import editor_world; import atlas.core.scene.system_registry; @@ -26,7 +13,6 @@ class test_application : public atlas::application { // TODO -- this is going to be changed with the use of the level // streamer API - console_log_info("renderer_instance = {}", (renderer_instance() != nullptr)); m_world = atlas::create_ref("Editor World", renderer_instance()); } @@ -37,13 +23,6 @@ class test_application : public atlas::application { }; - -// /* - -// TODO: Pre-defined this in TheAtlasEngine -// * Then to have the implemented by the application - -// */ atlas::ref initialize_application() { atlas::application_settings settings = { .name = "Editor", @@ -52,67 +31,4 @@ atlas::ref initialize_application() { .background_color = { 0.f, 0.f, 0.f, 0.f }, }; return create_ref(settings); -} - - -// // /* -// // atlas/* -// // core/* -// // import atlas.core; -// // drivers/ -// // vulkan -// // import atlas.vulkan -// // jolt_cpp -// // import atlas.jolt_cpp -// // .... -// // physics -// // import atlas.physics -// // renderer -// // import atlas.renderer -// // */ - -// // /* -// // core: module that is partitioned associated with -// // logger -// // import logger; -// // drivers: -// // vulkan: module that is partitioned associated with -// // import vulkan; -// // internal: export module vulkan:* -// // jolt_cpp: module that is partitioned associated with -// // import jolt_cpp -// // internal: export module jolt_cpp:* -// // atlas: global module unit -// // export import core; -// // export import vulkan; -// // export import jolt_cpp -// // */ - -// int main() { -// atlas::console_log_manager manager = atlas::console_log_manager(); - -// if(!glfwInit()) { -// console_log_fatal("GLFW: Initialization failed!!"); -// return -1; -// } - -// // atlas::application_settings settings = { -// // .name = "Editor", -// // .width = 1900, -// // .height = 600, -// // .background_color = {1.f, 1.f, 1.f, 1.f}, -// // }; -// // atlas::ref app = atlas::create_ref(settings); - -// atlas::ref system = atlas::create_ref("system"); -// atlas::ref context = atlas::initialize_context("vulkan", atlas::graphics_api::vulkan); - -// atlas::ref app = initialize_application(); - -// app->execute(); - -// app->post_destroy(); - -// context->destroy(); -// return 0; -// } \ No newline at end of file +} \ No newline at end of file From 5fba87246f1510ce0ff05066915d07a454d22e8d Mon Sep 17 00:00:00 2001 From: SpinnerX Date: Tue, 13 Jan 2026 13:05:16 -0800 Subject: [PATCH 27/68] Removed old atlas headers project structure --- atlas/core/api.hpp | 6 - atlas/core/application.hpp | 145 -- atlas/core/common.hpp | 26 - atlas/core/core.hpp | 76 - atlas/core/editor/dockspace.hpp | 29 - atlas/core/editor/menu_item.hpp | 50 - atlas/core/engine_logger.hpp | 162 -- atlas/core/event/event.hpp | 64 - atlas/core/event/event_bus.hpp | 64 - atlas/core/event/event_listener.hpp | 40 - atlas/core/event/joystick_codes.hpp | 59 - atlas/core/event/key_codes.hpp | 274 --- atlas/core/event/mouse_codes.hpp | 37 - atlas/core/event/types.hpp | 31 - atlas/core/filesystem/file_dialog.hpp | 19 - atlas/core/geometry/mesh.hpp | 11 - atlas/core/image/stb_image.hpp | 2 - atlas/core/math/math.hpp | 37 - atlas/core/math/types.hpp | 200 -- atlas/core/math/utilities.hpp | 46 - atlas/core/scene/components.hpp | 124 -- atlas/core/scene/exceptions.hpp | 23 - atlas/core/scene/game_object.hpp | 84 - atlas/core/scene/scene.hpp | 169 -- atlas/core/scene/world.hpp | 73 - atlas/core/serialize/serializer.hpp | 48 - atlas/core/serialize/types.hpp | 385 ---- atlas/core/system/registry.hpp | 74 - atlas/core/ui/widgets.hpp | 237 --- atlas/core/utilities/hash.hpp | 12 - atlas/core/utilities/memory.hpp | 1665 ----------------- atlas/core/utilities/state.hpp | 224 --- atlas/core/utilities/types.hpp | 15 - atlas/core/window.hpp | 119 -- atlas/drivers/graphics_context.hpp | 28 - atlas/drivers/jolt-cpp/jolt-imports.hpp | 35 - atlas/drivers/jolt-cpp/jolt_broad_phase.hpp | 161 -- atlas/drivers/jolt-cpp/jolt_components.hpp | 82 - .../jolt-cpp/jolt_contact_listener.hpp | 84 - atlas/drivers/jolt-cpp/jolt_context.hpp | 136 -- atlas/drivers/jolt-cpp/types.hpp | 47 - atlas/drivers/renderer_context.hpp | 92 - atlas/drivers/vulkan-cpp/hash.hpp | 38 - atlas/drivers/vulkan-cpp/mesh.hpp | 79 - .../vulkan-cpp/shader_resource_group.hpp | 128 -- .../vulkan-cpp/shader_source_reader.hpp | 3 - atlas/drivers/vulkan-cpp/uniforms.hpp | 52 - atlas/drivers/vulkan-cpp/utilities.hpp | 19 - atlas/drivers/vulkan-cpp/vk_context.hpp | 77 - atlas/drivers/vulkan-cpp/vk_driver.hpp | 83 - atlas/drivers/vulkan-cpp/vk_imgui.hpp | 89 - .../drivers/vulkan-cpp/vk_physical_driver.hpp | 97 - atlas/drivers/vulkan-cpp/vk_renderer.hpp | 96 - atlas/drivers/vulkan-cpp/vk_swapchain.hpp | 102 - atlas/drivers/vulkan-cpp/vk_window.hpp | 42 - atlas/drivers/vulkan-cpp/vulkan-imports.hpp | 13 - atlas/physics/components.hpp | 72 - atlas/physics/math_types.hpp | 191 -- atlas/physics/physics_context.hpp | 188 -- atlas/physics/physics_engine.hpp | 56 - atlas/renderer/renderer.hpp | 48 - atlas/renderer/uniforms.hpp | 25 - src/CMakeLists.txt | 75 - src/atlas/core/application.cpp | 256 --- src/atlas/core/editor/dockspace.cpp | 42 - src/atlas/core/editor/menu_item.cpp | 23 - src/atlas/core/engine_logger.cpp | 59 - src/atlas/core/event/event.cpp | 163 -- src/atlas/core/filesystem/file_dialog.cpp | 37 - src/atlas/core/image/stb_image.cpp | 4 - src/atlas/core/math/utilities.cpp | 76 - src/atlas/core/platforms/main.cpp | 16 - src/atlas/core/platforms/win32.cpp | 20 - src/atlas/core/scene/game_object.cpp | 25 - src/atlas/core/scene/scene.cpp | 20 - src/atlas/core/scene/world.cpp | 18 - src/atlas/core/serialize/serializer.cpp | 213 --- src/atlas/core/serialize/types.cpp | 157 -- src/atlas/core/system/registry.cpp | 32 - src/atlas/core/timer.cpp | 4 - src/atlas/core/ui/widgets.cpp | 313 ---- src/atlas/core/utilities/state.cpp | 98 - src/atlas/core/window.cpp | 44 - src/atlas/drivers/graphics_context.cpp | 14 - .../jolt-cpp/jolt_contact_listener.cpp | 51 - src/atlas/drivers/jolt-cpp/jolt_context.cpp | 376 ---- src/atlas/drivers/jolt-cpp/types.cpp | 36 - src/atlas/drivers/render_context.cpp | 19 - src/atlas/drivers/vulkan-cpp/mesh.cpp | 192 -- .../vulkan-cpp/shader_resource_group.cpp | 346 ---- src/atlas/drivers/vulkan-cpp/utilities.cpp | 25 - src/atlas/drivers/vulkan-cpp/vk_context.cpp | 170 -- src/atlas/drivers/vulkan-cpp/vk_driver.cpp | 123 -- src/atlas/drivers/vulkan-cpp/vk_imgui.cpp | 294 --- .../drivers/vulkan-cpp/vk_physical_driver.cpp | 128 -- src/atlas/drivers/vulkan-cpp/vk_renderer.cpp | 561 ------ src/atlas/drivers/vulkan-cpp/vk_swapchain.cpp | 261 --- src/atlas/drivers/vulkan-cpp/vk_window.cpp | 78 - src/atlas/physics/physics_context.cpp | 15 - src/atlas/physics/physics_engine.cpp | 154 -- src/atlas/renderer/renderer.cpp | 37 - 101 files changed, 11368 deletions(-) delete mode 100644 atlas/core/api.hpp delete mode 100644 atlas/core/application.hpp delete mode 100644 atlas/core/common.hpp delete mode 100644 atlas/core/core.hpp delete mode 100644 atlas/core/editor/dockspace.hpp delete mode 100644 atlas/core/editor/menu_item.hpp delete mode 100644 atlas/core/engine_logger.hpp delete mode 100644 atlas/core/event/event.hpp delete mode 100644 atlas/core/event/event_bus.hpp delete mode 100644 atlas/core/event/event_listener.hpp delete mode 100644 atlas/core/event/joystick_codes.hpp delete mode 100644 atlas/core/event/key_codes.hpp delete mode 100644 atlas/core/event/mouse_codes.hpp delete mode 100644 atlas/core/event/types.hpp delete mode 100644 atlas/core/filesystem/file_dialog.hpp delete mode 100644 atlas/core/geometry/mesh.hpp delete mode 100644 atlas/core/image/stb_image.hpp delete mode 100644 atlas/core/math/math.hpp delete mode 100644 atlas/core/math/types.hpp delete mode 100644 atlas/core/math/utilities.hpp delete mode 100644 atlas/core/scene/components.hpp delete mode 100644 atlas/core/scene/exceptions.hpp delete mode 100644 atlas/core/scene/game_object.hpp delete mode 100644 atlas/core/scene/scene.hpp delete mode 100644 atlas/core/scene/world.hpp delete mode 100644 atlas/core/serialize/serializer.hpp delete mode 100644 atlas/core/serialize/types.hpp delete mode 100644 atlas/core/system/registry.hpp delete mode 100644 atlas/core/ui/widgets.hpp delete mode 100644 atlas/core/utilities/hash.hpp delete mode 100644 atlas/core/utilities/memory.hpp delete mode 100644 atlas/core/utilities/state.hpp delete mode 100644 atlas/core/utilities/types.hpp delete mode 100644 atlas/core/window.hpp delete mode 100644 atlas/drivers/graphics_context.hpp delete mode 100644 atlas/drivers/jolt-cpp/jolt-imports.hpp delete mode 100644 atlas/drivers/jolt-cpp/jolt_broad_phase.hpp delete mode 100644 atlas/drivers/jolt-cpp/jolt_components.hpp delete mode 100644 atlas/drivers/jolt-cpp/jolt_contact_listener.hpp delete mode 100644 atlas/drivers/jolt-cpp/jolt_context.hpp delete mode 100644 atlas/drivers/jolt-cpp/types.hpp delete mode 100644 atlas/drivers/renderer_context.hpp delete mode 100644 atlas/drivers/vulkan-cpp/hash.hpp delete mode 100644 atlas/drivers/vulkan-cpp/mesh.hpp delete mode 100644 atlas/drivers/vulkan-cpp/shader_resource_group.hpp delete mode 100644 atlas/drivers/vulkan-cpp/shader_source_reader.hpp delete mode 100644 atlas/drivers/vulkan-cpp/uniforms.hpp delete mode 100644 atlas/drivers/vulkan-cpp/utilities.hpp delete mode 100644 atlas/drivers/vulkan-cpp/vk_context.hpp delete mode 100644 atlas/drivers/vulkan-cpp/vk_driver.hpp delete mode 100644 atlas/drivers/vulkan-cpp/vk_imgui.hpp delete mode 100644 atlas/drivers/vulkan-cpp/vk_physical_driver.hpp delete mode 100644 atlas/drivers/vulkan-cpp/vk_renderer.hpp delete mode 100644 atlas/drivers/vulkan-cpp/vk_swapchain.hpp delete mode 100644 atlas/drivers/vulkan-cpp/vk_window.hpp delete mode 100644 atlas/drivers/vulkan-cpp/vulkan-imports.hpp delete mode 100644 atlas/physics/components.hpp delete mode 100644 atlas/physics/math_types.hpp delete mode 100644 atlas/physics/physics_context.hpp delete mode 100644 atlas/physics/physics_engine.hpp delete mode 100644 atlas/renderer/renderer.hpp delete mode 100644 atlas/renderer/uniforms.hpp delete mode 100644 src/CMakeLists.txt delete mode 100644 src/atlas/core/application.cpp delete mode 100644 src/atlas/core/editor/dockspace.cpp delete mode 100644 src/atlas/core/editor/menu_item.cpp delete mode 100644 src/atlas/core/engine_logger.cpp delete mode 100644 src/atlas/core/event/event.cpp delete mode 100644 src/atlas/core/filesystem/file_dialog.cpp delete mode 100644 src/atlas/core/image/stb_image.cpp delete mode 100644 src/atlas/core/math/utilities.cpp delete mode 100644 src/atlas/core/platforms/main.cpp delete mode 100644 src/atlas/core/platforms/win32.cpp delete mode 100644 src/atlas/core/scene/game_object.cpp delete mode 100644 src/atlas/core/scene/scene.cpp delete mode 100644 src/atlas/core/scene/world.cpp delete mode 100644 src/atlas/core/serialize/serializer.cpp delete mode 100644 src/atlas/core/serialize/types.cpp delete mode 100644 src/atlas/core/system/registry.cpp delete mode 100644 src/atlas/core/timer.cpp delete mode 100644 src/atlas/core/ui/widgets.cpp delete mode 100644 src/atlas/core/utilities/state.cpp delete mode 100644 src/atlas/core/window.cpp delete mode 100644 src/atlas/drivers/graphics_context.cpp delete mode 100644 src/atlas/drivers/jolt-cpp/jolt_contact_listener.cpp delete mode 100644 src/atlas/drivers/jolt-cpp/jolt_context.cpp delete mode 100644 src/atlas/drivers/jolt-cpp/types.cpp delete mode 100644 src/atlas/drivers/render_context.cpp delete mode 100644 src/atlas/drivers/vulkan-cpp/mesh.cpp delete mode 100644 src/atlas/drivers/vulkan-cpp/shader_resource_group.cpp delete mode 100644 src/atlas/drivers/vulkan-cpp/utilities.cpp delete mode 100644 src/atlas/drivers/vulkan-cpp/vk_context.cpp delete mode 100644 src/atlas/drivers/vulkan-cpp/vk_driver.cpp delete mode 100644 src/atlas/drivers/vulkan-cpp/vk_imgui.cpp delete mode 100644 src/atlas/drivers/vulkan-cpp/vk_physical_driver.cpp delete mode 100644 src/atlas/drivers/vulkan-cpp/vk_renderer.cpp delete mode 100644 src/atlas/drivers/vulkan-cpp/vk_swapchain.cpp delete mode 100644 src/atlas/drivers/vulkan-cpp/vk_window.cpp delete mode 100644 src/atlas/physics/physics_context.cpp delete mode 100644 src/atlas/physics/physics_engine.cpp delete mode 100644 src/atlas/renderer/renderer.cpp diff --git a/atlas/core/api.hpp b/atlas/core/api.hpp deleted file mode 100644 index 986c853f..00000000 --- a/atlas/core/api.hpp +++ /dev/null @@ -1,6 +0,0 @@ -#pragma once - -namespace atlas { - enum api { vulkan, dx11, fx12, undefined }; - -}; \ No newline at end of file diff --git a/atlas/core/application.hpp b/atlas/core/application.hpp deleted file mode 100644 index 840ef1d7..00000000 --- a/atlas/core/application.hpp +++ /dev/null @@ -1,145 +0,0 @@ -#pragma once -#include -#include -#include -#include -#include - -namespace atlas { - - /** - * @brief application properties settings for the window - */ - struct application_settings { - std::string name = "Undefined"; - uint32_t width = 0; - uint32_t height = 0; - glm::vec4 background_color = { 1.f, 0.5f, 0.5f, 1.f }; - }; - - /** - * @brief represents a single application that gets created by the engine - * internally - * - * There is only ever going to be one application tied to the engine's - * runtime. As the application is given responsibilities of preloading, - * pre-initialization any sort of utilities required by the engine, and any - * form of post-cleanup when the user requests the application to close. - * - */ - class application { - public: - /** - * @brief constructs a new application - * @param p_settings is the specific application settings to configure - * how the application may be setup - */ - application(const application_settings& p_settings); - - ~application(); - - /** - * @return the delta time as a float for giving you the timestep every - * frame - */ - static float delta_time(); - - /** - * TODO: Need to remove this as it is not needed here - * - * Originally was used to handle the fixed physics timestep, but that - * can be handled else where. - */ - static float physics_step(); - - /** - * @brief Explicitly is used to execute the application's mainloop - */ - void execute(); - - /** - * @brief Performs any post cleanup when user requests the application - * to close - */ - void post_destroy(); - - /** - * @brief we only ever have one window - * - * This static function was a means to getting access to the window to - * perform any operations or request any data the window may have to - * provide - */ - static window& get_window() { return *s_instance->m_window; } - - /* Retrieves the current selected graphics API */ - /** - * @return the currently specified API. - */ - static api current_api(); - - /* Returns the currently selected swapchain */ - /** - * @brief gives you the current swapchain handle - * - * TODO: This is not actually needed, and should be removed - */ - VkSwapchainKHR get_current_swapchain(); - - /** - * @brief destroys the application completely - * - * TODO: Not make this static because you should not allow for this to - * be a direct calls users can have access to - */ - static void destroy(); - - /** - * @brief gives you the current aspect ratio based on the dimensions of - * the window - * - * @return a float which is just a static_cast(width / height); - */ - static float aspect_ratio(); - - /** - * @brief Gives you the current frame index which is used for the Vulkan - * renderer - * - * Provides information such as what is the current frame index to - * correcly index the commands that get submitted to the GPU for - * processing commands (tasks) - * - * @return uint32_t - */ - static uint32_t current_frame(); - - /** - * @brief Intended to get the image size so when you use current_frame() - * to get thje frame index, that you are not making an attempt at - * accessing anything outside of the frame. - * - * @return uint32_t - */ - static uint32_t image_size(); - - protected: - [[nodiscard]] ref renderer_instance() const { - return m_renderer; - } - - private: - void set_current_api(api api); - - private: - float m_delta_time = 0.f; - ref m_window; - ref m_renderer = nullptr; - glm::mat4 m_proj_view; - uint32_t m_current_frame_index = -1; - vk::imgui_context m_ui_context; - static application* s_instance; - }; - - ref initialize_application(); -}; \ No newline at end of file diff --git a/atlas/core/common.hpp b/atlas/core/common.hpp deleted file mode 100644 index 32407a51..00000000 --- a/atlas/core/common.hpp +++ /dev/null @@ -1,26 +0,0 @@ -#pragma once - -// core includes -#include -#include -#include -#include -#include - -#include - -// imgui UI widgets -#include - -#define GLM_ENABLE_EXPERIMENTAL -#include - -#include -#include -#include - -#include - -#include -#include -#include \ No newline at end of file diff --git a/atlas/core/core.hpp b/atlas/core/core.hpp deleted file mode 100644 index f71ceb87..00000000 --- a/atlas/core/core.hpp +++ /dev/null @@ -1,76 +0,0 @@ -#pragma once -#include -#include -#include - -namespace atlas { - - /** - * @brief alias to atlas::memory::strong_ptr - */ - template - using strong_ref = memory::strong_ptr; - - /** - * @brief construct strong_ptr through - * atlas::memory::create_strong_ptr(...); - * - * @tparam ...Args is a template pack for packing in parameters - * @tparam T is the type of object to construct strong_ptr with - * @param p_allocator is a polymorphic allocator when creating strong_ptr's. - * @param ...Args is an argument pack for packing to deduce the types that - * is specified by object of type T - */ - template - strong_ref create_strong_ref( - std::pmr::polymorphic_allocator<> p_allocator, - Args&&... args) { - return memory::make_strong_ptr(p_allocator, - std::forward(args)...); - } - - /** - * @brief alias to memory::optional_ptr - */ - template - using optional_ref = memory::optional_ptr; - - /** - * @brief alias to std::shared_ptr - */ - template - using ref = std::shared_ptr; - - /** - * @brief construct std::make_shared(...); - * - * @tparam ...Args is a template pack for packing in parameters - * @tparam T is the type of object to construct strong_ptr with - * @param ...Args is an argument pack for packing to deduce the types that - * is specified by object of type T - */ - template - constexpr ref create_ref(Args&&... args) { - return std::make_shared(std::forward(args)...); - } - - /** - * @brief alias to std::unique_ptr - */ - template - using scope = std::unique_ptr; - - /** - * @brief construct std::make_unique(...); - * - * @tparam ...Args is a template pack for packing in parameters - * @tparam T is the type of object to construct strong_ptr with - * @param ...Args is an argument pack for packing to deduce the types that - * is specified by object of type T - */ - template - constexpr scope create_scope(Args&&... args) { - return std::make_unique(std::forward(args)...); - } - -}; \ No newline at end of file diff --git a/atlas/core/editor/dockspace.hpp b/atlas/core/editor/dockspace.hpp deleted file mode 100644 index d00ab1a2..00000000 --- a/atlas/core/editor/dockspace.hpp +++ /dev/null @@ -1,29 +0,0 @@ -#pragma once -#include - -namespace atlas::ui { - - /** - * @brief dockspace window using imgui - */ - class dockspace { - public: - dockspace() = default; - - void fullscreen(bool p_fullscreen) { - m_fullscreen_enabled = p_fullscreen; - } - - void dockspace_open(bool p_dockspace_open) { - m_is_dockspace_open = p_dockspace_open; - } - - void begin(); - - void end(); - - private: - bool m_fullscreen_enabled = false; - bool m_is_dockspace_open = false; - }; -}; \ No newline at end of file diff --git a/atlas/core/editor/menu_item.hpp b/atlas/core/editor/menu_item.hpp deleted file mode 100644 index 355efb42..00000000 --- a/atlas/core/editor/menu_item.hpp +++ /dev/null @@ -1,50 +0,0 @@ -#pragma once -#include -#include - -namespace atlas::ui { - struct block { - const char* data = nullptr; - }; - - class menu_bar_exception { - public: - menu_bar_exception(const char* p_data) - : m_data(p_data) {} - - [[nodiscard]] const char* what() const { return m_data.data; } - - private: - block m_data; - }; - /** - * @brief UI wrapper around setting up a menu item group - * - * - * ```C++ - * - * atlas::ui::menu_item menu; - * - * menu.begin(); - * - * menu.add_child("Save", [](){ - * // do some operation related to saving - * // perhaps saving the scene... - * }); - * - * menu.end(); - * - * ``` - */ - class menu_item { - public: - menu_item() = default; - - void begin(); - - void end(); - - void add_child(const std::string& p_name, - const std::function& p_callback); - }; -}; \ No newline at end of file diff --git a/atlas/core/engine_logger.hpp b/atlas/core/engine_logger.hpp deleted file mode 100644 index d6089889..00000000 --- a/atlas/core/engine_logger.hpp +++ /dev/null @@ -1,162 +0,0 @@ -#pragma once -#include -#include -#include -#include -#include -#include - -namespace atlas { - /** - * @brief logger for logging messages to stdout on the console - * - * Manages the logger instances and patterns for setting up with the loggers - * when writing logs - */ - class console_log_manager { - public: - /** - * @brief initializes the console_log_manager - * - * TODO: Revisit the logger and do some refactoring because the way this - * works should be changed, as I'd prob do this differently now. - */ - static void initialize_logger_manager( - const std::string& pattern = "%^[%T] %n: %v%$"); - - /** - * @brief sets what the current logger to write to the console with - */ - static void set_current_logger( - const std::string& p_tag = "Undefined g_Tag in console_logger"); - - /** - * @brief constructs a new spdlog::logger to write to the console - */ - static void create_new_logger( - const std::string& p_tag = "Undefined Tag"); - - /** - * @brief retrieves that specific logger if it has been constructed - * - * @return ref if found, otherwise return nullptr - * - * TODO: Should have this throw an exception rather then returning - * nullptr - */ - static ref get(const std::string& p_tag); - - private: - // Using an unordered_map to specify through a string what logger to - // retrieve to log messages - static std::unordered_map> s_loggers; - }; -}; - -//! @note Console Loggers (These are loggers that write specifically to the -//! console, terminal console) -//! @note TODO --- Specify that engine3d will have it's own console terminal -//! that these will be written to. -template -inline void -console_log_trace([[maybe_unused]] spdlog::format_string_t fmt, - [[maybe_unused]] T&&... args) { -#ifndef ENABLE_TESTS_ONLY - atlas::console_log_manager::get("engine3d") - ->trace(fmt, std::forward(args)...); -#endif -} - -template -inline void -console_log_warn([[maybe_unused]] spdlog::format_string_t fmt, - [[maybe_unused]] T&&... args) { -#ifndef ENABLE_TESTS_ONLY - atlas::console_log_manager::get("engine3d") - ->warn(fmt, std::forward(args)...); -#endif -} - -template -inline void -console_log_info([[maybe_unused]] spdlog::format_string_t fmt, - [[maybe_unused]] T&&... args) { -#ifndef ENABLE_TESTS_ONLY - atlas::console_log_manager::get("engine3d") - ->info(fmt, std::forward(args)...); -#endif -} - -template -inline void -console_log_error([[maybe_unused]] spdlog::format_string_t fmt, - [[maybe_unused]] T&&... args) { -#ifndef ENABLE_TESTS_ONLY - atlas::console_log_manager::get("engine3d") - ->error(fmt, std::forward(args)...); -#endif -} - -template -inline void -console_log_fatal([[maybe_unused]] spdlog::format_string_t fmt, - [[maybe_unused]] T&&... args) { -#ifndef ENABLE_TESTS_ONLY - atlas::console_log_manager::get("engine3d") - ->critical(fmt, std::forward(args)...); -#endif -} - -///////////////////////////////////////// -///////////////////////////////////////// -///////////////////////////////////////// -template -inline void -console_log_trace_tagged([[maybe_unused]] const std::string& p_tag, - [[maybe_unused]] spdlog::format_string_t fmt, - [[maybe_unused]] T&&... args) { -#ifndef ENABLE_TESTS_ONLY - atlas::console_log_manager::get(p_tag)->trace(fmt, - std::forward(args)...); -#endif -} - -template -inline void -console_log_info_tagged([[maybe_unused]] const std::string& p_tag, - [[maybe_unused]] spdlog::format_string_t fmt, - [[maybe_unused]] T&&... args) { -#ifndef ENABLE_TESTS_ONLY - atlas::console_log_manager::get(p_tag)->info(fmt, std::forward(args)...); -#endif -} - -template -inline void -console_log_warn_tagged([[maybe_unused]] const std::string& p_tag, - [[maybe_unused]] spdlog::format_string_t fmt, - [[maybe_unused]] T&&... args) { - atlas::console_log_manager::get(p_tag)->warn(fmt, std::forward(args)...); -} - -template -inline void -console_log_error_tagged([[maybe_unused]] const std::string& p_tag, - [[maybe_unused]] spdlog::format_string_t fmt, - [[maybe_unused]] T&&... args) { -#ifndef ENABLE_TESTS_ONLY - atlas::console_log_manager::get(p_tag)->error(fmt, - std::forward(args)...); -#endif -} - -template -inline void -console_log_fatal_tagged([[maybe_unused]] const std::string& p_tag, - [[maybe_unused]] spdlog::format_string_t fmt, - [[maybe_unused]] T&&... args) { -#ifndef ENABLE_TESTS_ONLY - atlas::console_log_manager::get(p_tag)->critical(fmt, - std::forward(args)...); -#endif -} \ No newline at end of file diff --git a/atlas/core/event/event.hpp b/atlas/core/event/event.hpp deleted file mode 100644 index 9e500658..00000000 --- a/atlas/core/event/event.hpp +++ /dev/null @@ -1,64 +0,0 @@ -#pragma once -#include -#include -#include -#include -#include - -namespace atlas::event { - /** - * @name event.hpp - * @note Actual input polling system to poll in differeny sets of key/mouse - * actions - * @param UpdateEvents handles making sure that all of our events we handle - * have been successfully updated. - * @param GetMousePos just returns the position of our mouse cursor - */ - enum input_state { None, Idle, Pressed, Released }; - - struct joystick_button { - int ID = -1; - std::string Name = ""; - input_state ButtonState = input_state::None; - input_state PreviousButtonState = input_state::None; - }; - - struct joystick_info { - int ID = -1; - std::string JoystickName = "Default"; - std::map Buttons; - std::map ButtonsDown; - std::map AxesOfController; - }; - - bool is_key_pressed(int p_key); - - bool is_key_released(int p_key); - - bool is_mouse_pressed(int p_mouse_code); - bool is_mouse_released(int p_mouse_code); - - glm::vec2 cursor_position(); - - // joystic-specific functions - - bool is_joystic_present(int p_controller_id); - - const char* is_joystick_guid(int p_controller_id); - - float get_joystic_axis(int p_controller_id, int p_button); - - // bool is_button_pressed(int p_button_id, int p_controller_id); - - // bool is_button_released(int p_button_id, int p_controller_id); - - //! @note FIXME: Make button later - bool is_joystick_button_pressed(int p_button); - - bool is_joystick_button_released(int p_button); - - // specific for listening events - void update_events(); - - void wait_for_events(); -}; // namespace atlas::event \ No newline at end of file diff --git a/atlas/core/event/event_bus.hpp b/atlas/core/event/event_bus.hpp deleted file mode 100644 index 901e14df..00000000 --- a/atlas/core/event/event_bus.hpp +++ /dev/null @@ -1,64 +0,0 @@ -#pragma once -#include -#include -#include -#include - -namespace atlas::event { - - /** - * @brief Event bus that holds the responsibility to reroute events to the - * subscribers of those particular event. - */ - class event_bus { - public: - event_bus() = default; - - template - void create_listener() { - size_t id = type_id(); - if (m_event_listeners.contains(id)) { - return; - } - m_event_listeners.emplace(id, listener()); - } - - template - void subscribe(UObject* p_instance, const UCallback& p_callback) { - size_t id = type_id(); - - if (!m_event_listeners.contains(id)) { - create_listener(); - return; - } - - std::any_cast&>( - m_event_listeners.at(id)) - .subscribe(p_instance, p_callback); - - // return listener().subscribe(p_instance, p_callback); - } - - template - void publish(UEvent& p_event) { - size_t id = type_id(); - - if (!m_event_listeners.contains(id)) { - return; - } - - std::any_cast&>( - m_event_listeners.at(id)) - .notify_all(p_event); - } - - private: - template - size_t type_id() { - return typeid(UEvent).hash_code(); - } - - private: - std::unordered_map m_event_listeners; - }; -}; \ No newline at end of file diff --git a/atlas/core/event/event_listener.hpp b/atlas/core/event/event_listener.hpp deleted file mode 100644 index fefe9d16..00000000 --- a/atlas/core/event/event_listener.hpp +++ /dev/null @@ -1,40 +0,0 @@ -#pragma once -#include -#include -#include -#include - -namespace atlas::event { - - /** - * @brief Generic event listener of event type UEvent - * - * Listener that can have a different representation of a specific type of - * UEvent that gets specified to this listener - */ - template - class listener { - using event = std::function; - - public: - listener() = default; - - template - void subscribe(UObject* p_instance, const UCallback& p_callback) { - m_event_handlers.push_back( - [p_instance, p_callback](UEvent& p_event) { - (p_instance->*p_callback)(p_event); - }); - } - - // Notify all subscribers to this particular event listener - void notify_all(UEvent& p_event) { - for (const auto& callback : m_event_handlers) { - callback(p_event); - } - } - - private: - std::deque m_event_handlers; - }; -}; \ No newline at end of file diff --git a/atlas/core/event/joystick_codes.hpp b/atlas/core/event/joystick_codes.hpp deleted file mode 100644 index 07d08f3e..00000000 --- a/atlas/core/event/joystick_codes.hpp +++ /dev/null @@ -1,59 +0,0 @@ -#pragma once -#include - -namespace atlas::event { - enum JoystickCodes : int { - Joystick1 = 0, - - Joystick2 = 1, - - Joystick3 = 2, - - Joystick4 = 3, - - Joystick5 = 4, - - Joystick6 = 5, - - Joystick7 = 6, - - Joystick8 = 7, - - Joystick9 = 8, - - Joystick10 = 9, - - Joystick11 = 10, - - Joystick12 = 11, - - Joystick13 = 12, - - Joystick14 = 13, - - Joystick15 = 14, - - Joystick16 = 15, - - JoystickLAST = Joystick16, - }; -}; // namespace atlas - -inline constexpr int joystick_1 = ::atlas::event::JoystickCodes::Joystick1; -inline constexpr int joystick_2 = ::atlas::event::JoystickCodes::Joystick2; -inline constexpr int joystick_3 = ::atlas::event::JoystickCodes::Joystick3; -inline constexpr int joystick_4 = ::atlas::event::JoystickCodes::Joystick4; -inline constexpr int joystick_5 = ::atlas::event::JoystickCodes::Joystick5; -inline constexpr int joystick_6 = ::atlas::event::JoystickCodes::Joystick6; -inline constexpr int joystick_7 = ::atlas::event::JoystickCodes::Joystick7; -inline constexpr int joystick_8 = ::atlas::event::JoystickCodes::Joystick8; -inline constexpr int joystick_9 = ::atlas::event::JoystickCodes::Joystick9; -inline constexpr int joystick_10 = ::atlas::event::JoystickCodes::Joystick10; -inline constexpr int joystick_11 = ::atlas::event::JoystickCodes::Joystick11; -inline constexpr int joystick_12 = ::atlas::event::JoystickCodes::Joystick12; -inline constexpr int joystick_13 = ::atlas::event::JoystickCodes::Joystick13; -inline constexpr int joystick_14 = ::atlas::event::JoystickCodes::Joystick14; -inline constexpr int joystick_15 = ::atlas::event::JoystickCodes::Joystick15; -inline constexpr int joystick_16 = ::atlas::event::JoystickCodes::Joystick16; -inline constexpr int joystick_last = - ::atlas::event::JoystickCodes::JoystickLAST; \ No newline at end of file diff --git a/atlas/core/event/key_codes.hpp b/atlas/core/event/key_codes.hpp deleted file mode 100644 index 57046a0b..00000000 --- a/atlas/core/event/key_codes.hpp +++ /dev/null @@ -1,274 +0,0 @@ -#pragma once -#include - -namespace atlas::event { - enum Key : uint32_t { - // From glfw3.h - Space = 32, - Apostrophe = 39, /* ' */ - Comma = 44, /* , */ - Minus = 45, /* - */ - Period = 46, /* . */ - Slash = 47, /* / */ - - D0 = 48, /* 0 */ - D1 = 49, /* 1 */ - D2 = 50, /* 2 */ - D3 = 51, /* 3 */ - D4 = 52, /* 4 */ - D5 = 53, /* 5 */ - D6 = 54, /* 6 */ - D7 = 55, /* 7 */ - D8 = 56, /* 8 */ - D9 = 57, /* 9 */ - - Semicolon = 59, /* ; */ - Equal = 61, /* = */ - - A = 65, - B = 66, - C = 67, - D = 68, - E = 69, - F = 70, - G = 71, - H = 72, - I = 73, - J = 74, - K = 75, - L = 76, - M = 77, - N = 78, - O = 79, - P = 80, - Q = 81, - R = 82, - S = 83, - T = 84, - U = 85, - V = 86, - W = 87, - X = 88, - Y = 89, - Z = 90, - - LeftBracket = 91, /* [ */ - Backslash = 92, /* \ */ - RightBracket = 93, /* ] */ - GraveAccent = 96, /* ` */ - - World1 = 161, /* non-US #1 */ - World2 = 162, /* non-US #2 */ - - /* Function keys */ - Escape = 256, - Enter = 257, - Tab = 258, - Backspace = 259, - Insert = 260, - Delete = 261, - Right = 262, - Left = 263, - Down = 264, - Up = 265, - PageUp = 266, - PageDown = 267, - Home = 268, - End = 269, - CapsLock = 280, - ScrollLock = 281, - NumLock = 282, - PrintScreen = 283, - Pause = 284, - F1 = 290, - F2 = 291, - F3 = 292, - F4 = 293, - F5 = 294, - F6 = 295, - F7 = 296, - F8 = 297, - F9 = 298, - F10 = 299, - F11 = 300, - F12 = 301, - F13 = 302, - F14 = 303, - F15 = 304, - F16 = 305, - F17 = 306, - F18 = 307, - F19 = 308, - F20 = 309, - F21 = 310, - F22 = 311, - F23 = 312, - F24 = 313, - F25 = 314, - - /* Keypad */ - KP0 = 320, - KP1 = 321, - KP2 = 322, - KP3 = 323, - KP4 = 324, - KP5 = 325, - KP6 = 326, - KP7 = 327, - KP8 = 328, - KP9 = 329, - KPDecimal = 330, - KPDivide = 331, - KPMultiply = 332, - KPSubtract = 333, - KPAdd = 334, - KPEnter = 335, - KPEqual = 336, - - LeftShift = 340, - LeftControl = 341, - LeftAlt = 342, - Leftsuper = 343, - RightShift = 344, - RightControl = 345, - RightAlt = 346, - Rightsuper = 347, - Menu = 348 - }; -} - -// From glfw3.h - -inline constexpr uint32_t key_space = ::atlas::event::Key::Space; -inline constexpr uint32_t key_apostrophe = - ::atlas::event::Key::Apostrophe; /* ' */ -inline constexpr uint32_t key_comma = ::atlas::event::Key::Comma; /* , */ -inline constexpr uint32_t key_minus = ::atlas::event::Key::Minus; /* - */ -inline constexpr uint32_t key_period = ::atlas::event::Key::Period; /* . */ -inline constexpr uint32_t key_slash = ::atlas::event::Key::Slash; /* / */ -inline constexpr uint32_t key_0 = ::atlas::event::Key::D0; -inline constexpr uint32_t key_1 = ::atlas::event::Key::D1; -inline constexpr uint32_t key_2 = ::atlas::event::Key::D2; -inline constexpr uint32_t key_3 = ::atlas::event::Key::D3; -inline constexpr uint32_t key_4 = ::atlas::event::Key::D4; -inline constexpr uint32_t key_5 = ::atlas::event::Key::D5; -inline constexpr uint32_t key_6 = ::atlas::event::Key::D6; -inline constexpr uint32_t key_7 = ::atlas::event::Key::D7; -inline constexpr uint32_t key_8 = ::atlas::event::Key::D8; -inline constexpr uint32_t key_9 = ::atlas::event::Key::D9; -inline constexpr uint32_t key_semicolon = - ::atlas::event::Key::Semicolon; /* ; */ -inline constexpr uint32_t key_equal = ::atlas::event::Key::Equal; /* = */ -inline constexpr uint32_t key_a = ::atlas::event::Key::A; -inline constexpr uint32_t key_b = ::atlas::event::Key::B; -inline constexpr uint32_t key_c = ::atlas::event::Key::C; -inline constexpr uint32_t key_d = ::atlas::event::Key::D; -inline constexpr uint32_t key_e = ::atlas::event::Key::E; -inline constexpr uint32_t key_f = ::atlas::event::Key::F; -inline constexpr uint32_t key_g = ::atlas::event::Key::G; -inline constexpr uint32_t key_h = ::atlas::event::Key::H; -inline constexpr uint32_t key_i = ::atlas::event::Key::I; -inline constexpr uint32_t key_j = ::atlas::event::Key::J; -inline constexpr uint32_t key_k = ::atlas::event::Key::K; -inline constexpr uint32_t key_l = ::atlas::event::Key::L; -inline constexpr uint32_t key_m = ::atlas::event::Key::M; -inline constexpr uint32_t key_n = ::atlas::event::Key::N; -inline constexpr uint32_t key_o = ::atlas::event::Key::O; -inline constexpr uint32_t key_p = ::atlas::event::Key::P; -inline constexpr uint32_t key_q = ::atlas::event::Key::Q; -inline constexpr uint32_t key_r = ::atlas::event::Key::R; -inline constexpr uint32_t key_s = ::atlas::event::Key::S; -// inline constexpr uint32_t key_t = ::atlas::event::Key::T; -inline constexpr uint32_t key_u = ::atlas::event::Key::U; -inline constexpr uint32_t key_v = ::atlas::event::Key::V; -inline constexpr uint32_t key_w = ::atlas::event::Key::W; -inline constexpr uint32_t key_x = ::atlas::event::Key::X; -inline constexpr uint32_t key_y = ::atlas::event::Key::Y; -inline constexpr uint32_t key_z = ::atlas::event::Key::Z; -inline constexpr uint32_t key_left_bracket = - ::atlas::event::Key::LeftBracket; /* [ */ -inline constexpr uint32_t key_backslash = - ::atlas::event::Key::Backslash; /* \ */ -inline constexpr uint32_t key_right_bracket = - ::atlas::event::Key::RightBracket; /* ] */ -inline constexpr uint32_t key_gravity_accent = - ::atlas::event::Key::GraveAccent; /* ` */ -inline constexpr uint32_t key_world_1 = - ::atlas::event::Key::World1; /* non-US #1 */ -inline constexpr uint32_t key_world_2 = - ::atlas::event::Key::World2; /* non-US #2 */ - -/* Function keys */ -inline constexpr uint32_t key_escape = ::atlas::event::Key::Escape; -inline constexpr uint32_t key_enter = ::atlas::event::Key::Enter; -inline constexpr uint32_t key_tab = ::atlas::event::Key::Tab; -inline constexpr uint32_t key_backspace = ::atlas::event::Key::Backspace; -inline constexpr uint32_t key_insert = ::atlas::event::Key::Insert; -inline constexpr uint32_t key_delete = ::atlas::event::Key::Delete; -inline constexpr uint32_t key_right = ::atlas::event::Key::Right; -inline constexpr uint32_t key_left = ::atlas::event::Key::Left; -inline constexpr uint32_t key_down = ::atlas::event::Key::Down; -inline constexpr uint32_t key_up = ::atlas::event::Key::Up; -inline constexpr uint32_t key_page_up = ::atlas::event::Key::PageUp; -inline constexpr uint32_t key_page_down = ::atlas::event::Key::PageDown; -inline constexpr uint32_t key_home = ::atlas::event::Key::Home; -inline constexpr uint32_t key_end = ::atlas::event::Key::End; -inline constexpr uint32_t key_caps_lock = ::atlas::event::Key::CapsLock; -inline constexpr uint32_t key_scroll_lock = ::atlas::event::Key::ScrollLock; -inline constexpr uint32_t key_num_lock = ::atlas::event::Key::NumLock; -inline constexpr uint32_t key_print_screen = ::atlas::event::Key::PrintScreen; -inline constexpr uint32_t key_pause = ::atlas::event::Key::Pause; -inline constexpr uint32_t key_f1 = ::atlas::event::Key::F1; -inline constexpr uint32_t key_f2 = ::atlas::event::Key::F2; -inline constexpr uint32_t key_f3 = ::atlas::event::Key::F3; -inline constexpr uint32_t key_f4 = ::atlas::event::Key::F4; -inline constexpr uint32_t key_f5 = ::atlas::event::Key::F5; -inline constexpr uint32_t key_f6 = ::atlas::event::Key::F6; -inline constexpr uint32_t key_f7 = ::atlas::event::Key::F7; -inline constexpr uint32_t key_f8 = ::atlas::event::Key::F8; -inline constexpr uint32_t key_f9 = ::atlas::event::Key::F9; -inline constexpr uint32_t key_f10 = ::atlas::event::Key::F10; -inline constexpr uint32_t key_f11 = ::atlas::event::Key::F11; -inline constexpr uint32_t key_f12 = ::atlas::event::Key::F12; -inline constexpr uint32_t key_f13 = ::atlas::event::Key::F13; -inline constexpr uint32_t key_f14 = ::atlas::event::Key::F14; -inline constexpr uint32_t key_f15 = ::atlas::event::Key::F15; -inline constexpr uint32_t key_f16 = ::atlas::event::Key::F16; -inline constexpr uint32_t key_f17 = ::atlas::event::Key::F17; -inline constexpr uint32_t key_f18 = ::atlas::event::Key::F18; -inline constexpr uint32_t key_f19 = ::atlas::event::Key::F19; -inline constexpr uint32_t key_f20 = ::atlas::event::Key::F20; -inline constexpr uint32_t key_f21 = ::atlas::event::Key::F21; -inline constexpr uint32_t key_f22 = ::atlas::event::Key::F22; -inline constexpr uint32_t key_f23 = ::atlas::event::Key::F23; -inline constexpr uint32_t key_f24 = ::atlas::event::Key::F24; -inline constexpr uint32_t key_f25 = ::atlas::event::Key::F25; - -/* Keypad */ -inline constexpr uint32_t key_kp_0 = ::atlas::event::Key::KP0; -inline constexpr uint32_t key_kp_1 = ::atlas::event::Key::KP1; -inline constexpr uint32_t key_kp_2 = ::atlas::event::Key::KP2; -inline constexpr uint32_t key_kp_3 = ::atlas::event::Key::KP3; -inline constexpr uint32_t key_kp_4 = ::atlas::event::Key::KP4; -inline constexpr uint32_t key_kp_5 = ::atlas::event::Key::KP5; -inline constexpr uint32_t key_kp_6 = ::atlas::event::Key::KP6; -inline constexpr uint32_t key_kp_7 = ::atlas::event::Key::KP7; -inline constexpr uint32_t key_kp_8 = ::atlas::event::Key::KP8; -inline constexpr uint32_t key_kp_9 = ::atlas::event::Key::KP9; -inline constexpr uint32_t key_kp_decimal = ::atlas::event::Key::KPDecimal; -inline constexpr uint32_t key_kp_divide = ::atlas::event::Key::KPDivide; -inline constexpr uint32_t key_kp_multiply = ::atlas::event::Key::KPMultiply; -inline constexpr uint32_t key_kp_subtract = ::atlas::event::Key::KPSubtract; -inline constexpr uint32_t key_kp_add = ::atlas::event::Key::KPAdd; -inline constexpr uint32_t key_kp_enter = ::atlas::event::Key::KPEnter; -inline constexpr uint32_t key_kp_equal = ::atlas::event::Key::KPEqual; - -inline constexpr uint32_t key_left_shift = ::atlas::event::Key::LeftShift; -inline constexpr uint32_t key_left_control = ::atlas::event::Key::LeftControl; -inline constexpr uint32_t key_left_alt = ::atlas::event::Key::LeftAlt; -inline constexpr uint32_t key_left_super = ::atlas::event::Key::Leftsuper; -inline constexpr uint32_t key_right_shift = ::atlas::event::Key::RightShift; -inline constexpr uint32_t key_right_control = ::atlas::event::Key::RightControl; -inline constexpr uint32_t key_right_alt = ::atlas::event::Key::RightAlt; -inline constexpr uint32_t key_right_super = ::atlas::event::Key::Rightsuper; -inline constexpr uint32_t key_menu = ::atlas::event::Key::Menu; \ No newline at end of file diff --git a/atlas/core/event/mouse_codes.hpp b/atlas/core/event/mouse_codes.hpp deleted file mode 100644 index 2533d773..00000000 --- a/atlas/core/event/mouse_codes.hpp +++ /dev/null @@ -1,37 +0,0 @@ -#pragma once -#include - -namespace atlas::event { - enum Mouse : uint32_t { - // From glfw3.h - Button0 = 0, - Button1 = 1, - Button2 = 2, - Button3 = 3, - Button4 = 4, - Button5 = 5, - Button6 = 6, - Button7 = 7, - - ButtonLast = Button7, - ButtonLeft = Button0, - ButtonRight = Button1, - ButtonMiddle = Button2 - }; - -} // namespace atlas - -inline constexpr uint32_t mouse_button_0 = ::atlas::event::Mouse::Button0; -inline constexpr uint32_t mouse_button_1 = ::atlas::event::Mouse::Button1; -inline constexpr uint32_t mouse_button_2 = ::atlas::event::Mouse::Button2; -inline constexpr uint32_t mouse_button_3 = ::atlas::event::Mouse::Button3; -inline constexpr uint32_t mouse_button_4 = ::atlas::event::Mouse::Button4; -inline constexpr uint32_t mouse_button_5 = ::atlas::event::Mouse::Button5; -inline constexpr uint32_t mouse_button_6 = ::atlas::event::Mouse::Button6; -inline constexpr uint32_t mouse_button_7 = ::atlas::event::Mouse::Button7; -inline constexpr uint32_t mouse_button_last = ::atlas::event::Mouse::ButtonLast; -inline constexpr uint32_t mouse_button_left = ::atlas::event::Mouse::ButtonLeft; -inline constexpr uint32_t mouse_button_right = - ::atlas::event::Mouse::ButtonRight; -inline constexpr uint32_t mouse_button_middle = - ::atlas::event::Mouse::ButtonMiddle; \ No newline at end of file diff --git a/atlas/core/event/types.hpp b/atlas/core/event/types.hpp deleted file mode 100644 index a1167e1b..00000000 --- a/atlas/core/event/types.hpp +++ /dev/null @@ -1,31 +0,0 @@ -#pragma once -#include - -namespace atlas::event { - - struct collision_enter { - uint64_t entity1; - uint64_t entity2; - }; - - struct collision_persisted { - uint64_t entity1; - uint64_t entity2; - }; - - struct collision_exit { - uint64_t entity1; - uint64_t entity2; - }; - - /** - * @brief event to trigger when to transition specific scenes - * - * @param from_scene is the current scene that is being transitioned from - * @param to_scene is the new scene that is going to be transitioned to - */ - struct scene_transition { - const void* from_scene; - const void* to_scene; - }; -}; \ No newline at end of file diff --git a/atlas/core/filesystem/file_dialog.hpp b/atlas/core/filesystem/file_dialog.hpp deleted file mode 100644 index 10d32359..00000000 --- a/atlas/core/filesystem/file_dialog.hpp +++ /dev/null @@ -1,19 +0,0 @@ -#pragma once -#include -#include - -namespace atlas::filesystem { - /** - * @param filter - * @note Defines the filter of items to pick from the file dialog - * @example passing "obj;jpg" will only allow to select these files with - * those extensions - */ - std::string load_from_file_dialog( - const std::string& p_filter, - const std::filesystem::path& p_default_path = "Untitled.engine"); - - std::string save_to_file( - const std::string& p_filter, - const std::filesystem::path& p_default_path = "Untitled.engine"); -}; // namespace atlas::filesystem \ No newline at end of file diff --git a/atlas/core/geometry/mesh.hpp b/atlas/core/geometry/mesh.hpp deleted file mode 100644 index 7c724278..00000000 --- a/atlas/core/geometry/mesh.hpp +++ /dev/null @@ -1,11 +0,0 @@ -#pragma once -#include - -namespace atlas { - class mesh { - public: - mesh() = default; - // TODO: Change this because UNUSED!!! - mesh(const std::string& p_filepath); - }; -}; \ No newline at end of file diff --git a/atlas/core/image/stb_image.hpp b/atlas/core/image/stb_image.hpp deleted file mode 100644 index 7125f333..00000000 --- a/atlas/core/image/stb_image.hpp +++ /dev/null @@ -1,2 +0,0 @@ -#pragma once -#include \ No newline at end of file diff --git a/atlas/core/math/math.hpp b/atlas/core/math/math.hpp deleted file mode 100644 index aab50a39..00000000 --- a/atlas/core/math/math.hpp +++ /dev/null @@ -1,37 +0,0 @@ -#include -#include -#include - -namespace atlas { - - class interpolation { - public: - template - static T linear_interpolate(T start, - T end, - const std::function& function, - float t) { - float l_adjusted_time = 0.0f; - if (!function) { - l_adjusted_time = t; - } - else { - const float f = function(t); - l_adjusted_time = f; - } - if (l_adjusted_time < 0) { - l_adjusted_time = 0.0f; - } - if (l_adjusted_time > 1.0f) { - l_adjusted_time = 1.0f; - } - - float time_dif = 1.0f - l_adjusted_time; - - return start * time_dif + end * l_adjusted_time; - } - - private: - interpolation() = default; - }; -}; // namespace atlas \ No newline at end of file diff --git a/atlas/core/math/types.hpp b/atlas/core/math/types.hpp deleted file mode 100644 index e8b58849..00000000 --- a/atlas/core/math/types.hpp +++ /dev/null @@ -1,200 +0,0 @@ -#pragma once -#include -#include - -namespace atlas { - - /** - * @brief vector2 is to define as a centralized mathematical - * representation of types such as glm::vec2, but can be defined based to - * the needs of specific mathematical types. - * - * Representing a 2-component values mathematical type - * - * @tparam T is the specified vector2 type specific to the mathematical - * frameworks representation, such as it can be glm::vec2. - * - */ - template - struct vector2; - - /** - * @brief vector3 is to define a centralized wrapper as a mathematical - * representaiton for communicating vector3 types from frameworks to - * glm::vec3 - * - * Representing a 3-component value mathematical type - * - * @tparam T is the type of vector2 such as glm::vec3 - * - * Example Usage: - * - * ```C++ - * auto jolt_vec3 = RVec3::zeros(); - * glm::vec3 pos_values = atlas::vector3(jolt_vec3); - * ``` - */ - template - struct vector3 { - vector3() = default; - - vector3(const T& p_other) - : m_value(p_other) {} - - vector3(float x, float y, float z) - : m_value(x, y, z) {} - vector3(const std::initializer_list& values) - : m_value(*values.begin(), *values.begin() + 1, *values.begin() + 2) { - } - - operator glm::vec3() { return m_value; } - - glm::vec3 operator=(const T& p_other) { return p_other; } - - bool operator==(const glm::vec3& p_other) { - return (m_value.x == p_other.x and m_value.y == p_other.y and - m_value.z == p_other.z); - } - - private: - glm::vec3 m_value; - }; - - /** - * @brief vector4 is to define a centralized wrapper as a mathematical - * representaiton for communicating vector3 types from frameworks to - * glm::vec3 - * - * vector4 is for a 4-component value that represents a vector 4 type - * - * @tparam T is the type of vector4 that would represent such type as - * glm::vec4 - * - * Example Usage: - * - * ```C++ - * auto jolt_vec4 = RVec4::zeros(); - * glm::vec4 pos_values = atlas::vector4(jolt_vec4); - * ``` - */ - template - struct vector4 { - vector4() = default; - - vector4(const T& p_other) - : m_value(p_other) {} - - vector4(float x, float y, float z, float w) - : m_value(x, y, z, w) {} - - operator glm::vec4() { return m_value; } - - glm::vec4 operator=(const T& p_other) { return p_other; } - - bool operator==(const glm::vec4& p_other) { - return (m_value.x == p_other.x and m_value.y == p_other.y and - m_value.z == p_other.z and m_value.w == p_other.w); - } - - private: - glm::vec4 m_value; - }; - - template<> - struct vector2 { - vector2() = default; - - vector2(const glm::highp_vec2& p_other) - : m_value(p_other) {} - - operator glm::highp_vec2() { return m_value; } - - glm::highp_vec2 operator=(const glm::highp_vec2& p_other) { - return p_other; - } - - bool operator==(const glm::vec4& p_other) { - return (m_value.x == p_other.x and m_value.y == p_other.y); - } - - private: - glm::highp_vec2 m_value; - }; - - template<> - struct vector3 { - vector3() = default; - - vector3(const glm::highp_vec3& p_other) - : m_value(p_other) {} - - operator glm::highp_vec3() { return m_value; } - - glm::highp_vec3 operator=(const glm::highp_vec3& p_other) { - return p_other; - } - - bool operator==(const glm::highp_vec3& p_other) { - return (m_value.x == p_other.x and m_value.y == p_other.y and - m_value.z == p_other.z); - } - - private: - glm::highp_vec3 m_value; - }; - - template<> - struct vector4 { - vector4() = default; - - vector4(const glm::highp_vec4& p_other) - : m_value(p_other) {} - - operator glm::highp_vec4() { return m_value; } - - glm::highp_vec4 operator=(const glm::highp_vec4& p_other) { - return p_other; - } - - bool operator==(const glm::highp_vec4& p_other) { - return (m_value.x == p_other.x and m_value.y == p_other.y and - m_value.z == p_other.z and m_value.w == p_other.w); - } - - private: - glm::highp_vec4 m_value; - }; - - //! @brief generics to specialize to their mathematical definition of - //! matrices types - template - struct math_generic; - - template - struct matrix2; - - template - struct matrix3; - - template - struct matrix4; - - //! @brief By default we use the glm math types therefore we create all of - //! our default math types to glm's mathematical type - template - using vec = math_generic>; - using vec2 = vector2; - using vec3 = vector3; - using vec4 = vector4; - - using highp_vec2 = vector2; - using highp_vec3 = vector3; - using highp_vec4 = vector4; - - template - using mat = math_generic>; - - using mat2 = matrix2; - using mat3 = matrix3; - using mat4 = matrix4; -}; // namespace atlas \ No newline at end of file diff --git a/atlas/core/math/utilities.hpp b/atlas/core/math/utilities.hpp deleted file mode 100644 index e5b4cd16..00000000 --- a/atlas/core/math/utilities.hpp +++ /dev/null @@ -1,46 +0,0 @@ -#pragma once -#include - -namespace atlas { - - //! @brief converts vec4 to quaterion - glm::quat to_quat(const glm::vec4& p_values); - - //! @brief converts vec3 to quaterion - glm::quat to_quat(const glm::vec3& p_values); - - //! @brief converts glm::vec3 to glm::vec4 - glm::highp_vec4 from_quat(const glm::vec3& p_values); - - glm::quat to_quathp(const glm::highp_vec4& p_values); - - namespace math { - //! @brief shorthand for glm::vec3(0.f, 0.f, 0.f) - glm::vec3 zeroes(); - - //! @brief shorthand for glm::vec3(1.f, 1.f, 1.f) - glm::vec3 ones(); - - //! @brief rotation equivalent of a zero-vector - // sets to glm::quat(1.f, 0.f, 0.f, 0.f) - glm::quat identity(); - - //! @brief shorthand for glm::vec3(0.f, 0.f, 1.f) - glm::vec3 forward(); - - //! @brief shorthand for glm::vec3(0.f, 0.f, -1.f) - glm::vec3 backward(); - - //! @brief shorthand for glm::vec3(1.f, 0.f, 0.f) - glm::vec3 right(); - - //! @brief shorthand for glm::vec3(-1.f, 0.f, 0.f) - glm::vec3 left(); - - //! @brief shorthand for glm::vec3(0.f, 1.f, 0.f) - glm::vec3 up(); - - //! @brief shorthand for glm::vec3(0.f, -1.f, 0.f) - glm::vec3 down(); - } -}; \ No newline at end of file diff --git a/atlas/core/scene/components.hpp b/atlas/core/scene/components.hpp deleted file mode 100644 index eaccdeda..00000000 --- a/atlas/core/scene/components.hpp +++ /dev/null @@ -1,124 +0,0 @@ -#pragma once -#include -#include -#include -#include -#include - -namespace atlas { - - struct transform { - glm::highp_vec3 position{ 0.f }; - glm::highp_vec4 quaternion{ 0.f, 0, 0, 1 }; - glm::highp_vec3 rotation{ 0.f }; - glm::highp_vec3 scale{ 1.f }; - - //! @brief sets rotation and automatically converts rotation glm::vec3 - //! to quaternion - void set_rotation(const glm::highp_vec3& p_value) { - rotation = p_value; - quaternion = from_quat(rotation); - } - }; - - struct material_metadata { - glm::vec4 ambient{ 0.2f }; - glm::vec4 diffuse{ 0.5f }; - glm::vec4 specular{ 1.f }; - float shininess = 0.5f; - }; - struct directional_light { - glm::vec3 direction{ 0.f }; - glm::vec3 view_position{ 0.f }; - // {x, y, z, w: intensity} - glm::vec4 ambient{ 1.f }; - glm::vec4 diffuse{ 1.f }; - // {x, y, z, w: intensity} - glm::vec4 specular{ 1.f, 1.f, 0.f, 0.f }; - glm::vec4 color{ 1.f }; - }; - - struct point_light { - glm::vec3 position; // this is provided by the transform - glm::vec4 color = { 1.f, 1.f, 1.f, 1.f }; - float attenuation = 1.f; - float constant = 1.f; - float linear = 1.f; - float quadratic = 1.f; - - glm::vec4 ambient = glm::vec4(1.f); - glm::vec4 diffuse = glm::vec4(1.f); - glm::vec4 specular = glm::vec4(1.f); - }; - - /** - * @brief Loads a mesh source - * - * @param color is the albedo color values - * @param model_path is the specified path to the 3d model asset path - * @param texture_path is the specified path to the specific texture to load - */ - struct mesh_source { - bool flip = false; // this is for flipping the texture coordinates - glm::vec4 color{ 1.f }; - std::string model_path = ""; - std::string diffuse = ""; - std::string specular = ""; - }; - - /** - * @brief define a game object to have a perspective camera that can - * correspond to it - */ - struct perspective_camera { - // represented as {near: x, far: y} - glm::vec2 plane{ 0.f }; - - // Activate to be the current camera - bool is_active = false; - - // Defaults to 45.0f in radians - float field_of_view = glm::radians(45.f); - }; - - /** - * @brief specialized namespace tag to use for specifying operations used - * with flecs in using tags - * - * Tags can be handled for specifying queries for specific archetypes (list - * of those entities) - * - * Example Usage: - * - * ```C++ - * m_entity.add>(); - * ``` - */ - namespace tag { - - //! @brief to indicate which entities are editor-only - struct editor {}; - - //! @brief to tag entities to serialize through the serializer - struct serialize { - bool enable = false; - }; - }; - - //! TODO: Consider either relocating where this is and how it gets handled. - - /** - * @brief struct for attaching a projection/view matrix to your game object - * - * This should only be used if you know your object is going to add - * atlas::perspective_camera to work - * - * TODO: Consider adding this automatically in a way we can represent - * multiple cameras in a given scene. Which is something to think about - */ - struct projection_view { - glm::mat4 projection; - glm::mat4 view; - }; - -}; // namespace atlas \ No newline at end of file diff --git a/atlas/core/scene/exceptions.hpp b/atlas/core/scene/exceptions.hpp deleted file mode 100644 index bbacc037..00000000 --- a/atlas/core/scene/exceptions.hpp +++ /dev/null @@ -1,23 +0,0 @@ -#pragma once -#include - -namespace atlas { - struct exception_block { - const char* data = nullptr; - }; - - class invalid_access_exception : public std::exception { - public: - invalid_access_exception() = default; - invalid_access_exception(const char* p_data) - : m_block(p_data) {} - - //! @return message given when this exception gets triggered - [[nodiscard]] const char* what() const noexcept override { - return m_block.data; - } - - private: - exception_block m_block; - }; -}; \ No newline at end of file diff --git a/atlas/core/scene/game_object.hpp b/atlas/core/scene/game_object.hpp deleted file mode 100644 index 972a33b0..00000000 --- a/atlas/core/scene/game_object.hpp +++ /dev/null @@ -1,84 +0,0 @@ -#pragma once -#include -#include - -namespace atlas { - - /** - * @brief Creates a pointer wrapper which extends capabilities of - * flecs::entity - * - * Provides our own construct of API's that handles any workload around some - * of the raw flecs API's that can still be used by other flecs API's - * without completely interacting touching raw flecs API - */ - class game_object : public flecs::entity { - public: - //! @brief Should not construct a scene object not created through - //! flecs::world - game_object() = delete; - - game_object(flecs::world_t* p_registry, flecs::entity_t p_id); - - game_object(const flecs::entity& p_base); - - explicit game_object(flecs::entity& p_base); - - /** - * @brief sets the entity to be a parent of the specified entity - * - * @param p_entity is the specified entity to specify as the parent. - * - * - * Example Usage: - * - * ```C++ - * - * atlas::game_object obj1 = entity("Parent"); - * - * atlas::game_object obj2 = entity("Chlid"); - * - * // obj2 is the child of obj1 - * // As obj1 is a parent node - * obj2.child_of(obj1); - * - * ``` - * - */ - void child_of(const std::optional& p_parent); - - /** - * @brief iterates through all children entities if the given entity is - * a parent of any given entities - * - * Example Usage: - * - * - * ```C++ - * atlas::game_object obj1 = entity("Parent Node"); - * atlas::game_object obj2 = entity("Chlid Node"); - * - * // obj1 is the parent of obj2. - * obj2.child_of(parent); - * - * // iteration should only include for "Child Node" - * obj1.children([](flecs::entity p_child){ - * // do stuff with the child entity - * }); - * - * ``` - */ - template - void children(UFunction&& p_callback) { - children(p_callback); - } - }; - - /** - * @brief Alias to std::optional - * - * This alias serves as a representation of game objects users can create - * and manage components with - */ - using game_object_optional = std::optional; -}; \ No newline at end of file diff --git a/atlas/core/scene/scene.hpp b/atlas/core/scene/scene.hpp deleted file mode 100644 index 68f67083..00000000 --- a/atlas/core/scene/scene.hpp +++ /dev/null @@ -1,169 +0,0 @@ -#pragma once -#include -#include -#include -#include - -namespace atlas { - - /** - * @brief Constructs a scene that defines an area where game objects are - * part of contained within an atlas::world - * - * Scenes are fundamentally building blocks that a game object may reside - * in. Composing of variety of properties such as sky lights, game objects, - * cameras, etc. - * - * Which can represent corresponding resources that can be related to - * specific levels/scenes. - * - * Scenes are apart of another container referred to as the world which - * helps manages these scenes and consider them as contexts that can be - * switched/toggled based on users transforms. - */ - class scene { - public: - /** - * @param p_name is the name given to this scene - * @param p_bus is the globalized event bus that is given access to the - * scene to subscribe events to it. - */ - scene(const std::string& p_name, event::event_bus& p_bus); - - virtual ~scene() = default; - - /** - * @brief Retrieves if an entity already exists within the registry, - * create new entity otherwise - * - * @param p_name is a string to set the name of the entity - */ - game_object entity(std::string_view p_name); - - /** - * @brief Retrieves if an entity already exists within the registry, - * create new entity otherwise - * - * @param p_entity_id is the ID to retrieve an entity if it exists, - * otherwise returns a new entity. - */ - game_object entity(uint64_t p_id); - - /** - * @brief subscribes an event to the event::bus to get invoked when - * publishers notify all subscribers when an update is incoming - * - * @tparam UEventType - * @tparam UObject - * @tparam UCallback - * @param p_instance is the object instance to specify where the - * callback belongs to - * @param p_callback is the callback that contains an arbitrary task - * that gets invoked when incoming updates occur from the publisher - * - */ - template - void subscribe(UObject* p_instance, const UCallback& p_callback) { - m_bus->subscribe(p_instance, p_callback); - } - - /** - * @brief queries components, returning entities (game objects) that - * contain those components queried with. - * - * Queries are a feature flecs allows us to do. Which query component - * parameters and gives us archetypes back. - * - * Archetypes are list of entities that contain those list of parameters - * - * @tparam ...Comps - * @tparam ...Args - * @param ... args - * @return flecs::query_builder - * - * Example Usage: - * ```C++ - * auto query_physics = query_builder().build(); - * - * query_physics.each([](flecs::entity, atlas::transform&, - * atlas::physics_body&){ - * // do stuff - * }); - * ``` - */ - template - flecs::query_builder query_builder(Args&&... args) const { - return flecs::query_builder(m_registry, - std::forward(args)...); - } - - /** - * @return the number of children entities - * - * Example Usage: - * - * - * ```C++ - * - * atlas::scene scene("New Scene"); - * - * // creating obj1 (parent) and obj2 (child) - * atlas::game_object obj1 = scene.create("Parent"); - * - * atlas::game_object obj2 = scene.create("Chlid"); - * - * // obj2 is the child of obj1 - * // As obj1 is a parent node - * - * obj2.child_of(obj1); - * - * // Returns 1 - * uint32_t obj1_children = scene.children_count(obj1); - * - * ``` - */ - uint32_t children_count(const game_object& p_parent); - - /** - * @brief Defer operations until end of frame. - * When this operation is invoked while iterating, operations - * inbetween the defer_begin() and defer_end() operations are executed - * at the end of the frame. - * - * This operation is thread safe. - * - * @return true if world changed from non-deferred mode to deferred - * mode. - */ - bool defer_begin() { return m_registry.defer_begin(); } - - /** - * End block of operations to defer. - * See defer_begin(). - * - * This operation is thread safe. - * - * @return true if world changed from deferred mode to non-deferred - * mode. - */ - bool defer_end() { return m_registry.defer_end(); } - - //! @return the name of the scene - [[nodiscard]] std::string name() const { return m_name; } - - //! @return the event::bus handle for subscribing events - [[nodiscard]] event::event_bus* event_handle() const { return m_bus; } - - /** - * @brief Requires to return flecs::world is returned by reference to - * prevent making copies of flecs::world - */ - operator flecs::world&() { return m_registry; } - - private: - flecs::world m_registry; - std::string m_name; - event::event_bus* m_bus = nullptr; - }; -}; // namespace atlas \ No newline at end of file diff --git a/atlas/core/scene/world.hpp b/atlas/core/scene/world.hpp deleted file mode 100644 index f8fd96fb..00000000 --- a/atlas/core/scene/world.hpp +++ /dev/null @@ -1,73 +0,0 @@ -#pragma once -#include -#include -#include -#include -#include - -namespace atlas { - - /** - * @brief world represents a larger scope of areas that manages the scene - * contexts - * - * The world is responsible for providing a self-containment of scenes and - * managing which scenes are current. Based on current scenes are details - * the world can know about. - * - * Details such as through player transform or navigation that can be done - * through the world, providing useful information on where a game object in - * those scenes/levels. - * - * The world responsibility act as the based container of any scene that can - * be created by the user through editor. - * - * - */ - class world { - public: - world() = delete; - - /** - * @brief construct a new world with a specified name associated - * with it - */ - world(const std::string& p_name); - - virtual ~world() = default; - - //! @return the name of world - [[nodiscard]] std::string name() const { return m_name; } - - /** - * @brief Creating a scene, then we add that scene onto this world - * - * @warning TODO: This is not how we want to currently create and add - * scenes as this is quite problematic. Should direct attention to this - * soon. - */ - void add_scene(const ref& p_scene_context); - - /** - * @brief get_scene allows for specifically querying for current scenes - * - * TODO: Eventually this is going to be something defined whether its - * through the player's navigation system for the world to track where - * the player is in within the world, then provide the current scene - * based on that information - */ - ref get_scene(const std::string& p_tag) { - if (!m_scene_container.contains(p_tag)) { - throw std::runtime_error( - "Could not access ref from " - "world::get_scene(const string& p_tag)!!!"); - } - return m_scene_container[p_tag]; - } - - private: - std::map> m_scene_container; - ref m_world_shared_instance; - std::string m_name = "Undefined Tag"; - }; -}; // namespace atlas \ No newline at end of file diff --git a/atlas/core/serialize/serializer.hpp b/atlas/core/serialize/serializer.hpp deleted file mode 100644 index ac5c09ba..00000000 --- a/atlas/core/serialize/serializer.hpp +++ /dev/null @@ -1,48 +0,0 @@ -#pragma once -#include -#include -#include -#include - -namespace atlas { - /** - * @brief serializer is responsible for saving/loading scenes - * - * This class excepts a scene context with the purpose of serializing with - * the entities that reside within that specific scene context - * - * Which also provide an API for loading in a scene from disk for - * deserialization. - */ - class serializer { - public: - serializer() = default; - - /** - * @brief constructs a new serializer with a requirement to specify a - * scene to serialize - * @param p_scene_ctx is the current scene to perform - * serialization/deserialization to - */ - serializer(const ref& p_scene_ctx); - - /** - * @param p_filepath is the specified path to save the file - */ - void save(const std::filesystem::path& p_filepath); - - /** - * @param p_filepath is the specified path to loading in the saved file - * from - * @param p_registry is the current scene registry to load/create the - * entities through that registry - * @return true if loading was successful, otherwise will return false - */ - bool load(const std::filesystem::path& p_filepath, - const flecs::world& p_registry); - - private: - ref m_current_scene_ctx; - }; - -}; // namespace atlas \ No newline at end of file diff --git a/atlas/core/serialize/types.hpp b/atlas/core/serialize/types.hpp deleted file mode 100644 index f7c3b46d..00000000 --- a/atlas/core/serialize/types.hpp +++ /dev/null @@ -1,385 +0,0 @@ -#pragma once -#include -#include -#include -#include - -namespace YAML { - /** - * @brief Custom specialized classes from yaml-cpp to specialize to take in - * a glm::vec2 specifically - * - * Specialization is used for converting glm::vec2 to yaml-cpp syntax when - * saving glm::vec2 data to disk - */ - template<> - struct convert { - static Node encode(const glm::vec2& rhs) { - Node node; - node.push_back(rhs.x); - node.push_back(rhs.y); - - return node; - } - - static bool decode(const Node& node, glm::vec2& rhs) { - if (!node.IsSequence() || node.size() != 2) - return false; - - rhs.x = node[0].as(); - rhs.y = node[1].as(); - - return true; - } - }; - - /** - * @brief Custom specialized classes from yaml-cpp to specialize to take in - * a glm::vec3 specifically - * - * Specialization is used for converting glm::vec3 to yaml-cpp syntax when - * saving glm::vec3 data to disk - */ - template<> - struct convert { - static Node encode(const glm::vec3& rhs) { - Node node; - node.push_back(rhs.x); - node.push_back(rhs.y); - node.push_back(rhs.z); - - return node; - } - - static bool decode(const Node& node, glm::vec3& rhs) { - if (!node.IsSequence() || node.size() != 3) - return false; - - rhs.x = node[0].as(); - rhs.y = node[1].as(); - rhs.z = node[2].as(); - - return true; - } - }; - - /** - * @brief Custom specialized classes from yaml-cpp to specialize to take in - * a glm::vec4 specifically - * - * Specialization is used for converting glm::vec4 to yaml-cpp syntax when - * saving glm::vec4 data to disk - */ - template<> - struct convert { - - static Node encode(const glm::vec4& rhs) { - Node node; - node.push_back(rhs.x); - node.push_back(rhs.y); - node.push_back(rhs.z); - node.push_back(rhs.w); - - return node; - } - - static bool decode(const Node& node, glm::vec4& rhs) { - if (!node.IsSequence() || node.size() != 4) { - return false; - } - - rhs.x = node[0].as(); - rhs.y = node[1].as(); - rhs.z = node[2].as(); - rhs.w = node[3].as(); - return true; - } - }; - - template<> - struct convert { - - static Node encode(const atlas::mesh_source& rhs) { - Node node; - // Encode glm::vec3 members - node["Model"] = rhs.model_path; - node["Color"] = rhs.color; - node["Diffuse"] = rhs.diffuse; - node["Specular"] = rhs.specular; - return node; - } - - static bool decode(const Node& node, atlas::mesh_source& rhs) { - if (!node.IsMap()) { - return false; - } - - rhs.model_path = node["Model"].as(); - rhs.color = node["Angular Velocity"].as(); - rhs.diffuse = node["Force"].as(); - rhs.specular = node["Impulse"].as(); - return true; - } - }; - - template<> - struct convert { - - static Node encode(const atlas::point_light& rhs) { - Node node; - // Encode glm::vec3 members - node["Color"] = rhs.color; - node["Attenuation"] = rhs.attenuation; - node["Ambient"] = rhs.ambient; - node["Diffuse"] = rhs.diffuse; - node["Specular"] = rhs.specular; - return node; - } - - static bool decode(const Node& node, atlas::point_light& rhs) { - if (!node.IsMap()) { - return false; - } - - rhs.color = node["Color"].as(); - rhs.attenuation = node["Attenuation"].as(); - rhs.ambient = node["Ambient"].as(); - rhs.diffuse = node["Diffuse"].as(); - rhs.specular = node["Specular"].as(); - return true; - } - }; - - /** - * @brief Custom specialized classes from yaml-cpp to specialize to take in - * a atlas::body_type specifically - * - * Specialization is used for converting atlas::body_type to yaml-cpp syntax - * when saving atlas::body_type data to disk - */ - template<> - struct convert { - static Node encode(const atlas::body_type& rhs) { - Node node; - node.push_back(static_cast(rhs)); - return node; - } - - static bool decode(const Node& node, atlas::body_type& rhs) { - if (!node.IsScalar()) { - return false; - } - rhs = static_cast(node.as()); - return true; - } - }; - - /** - * @brief Custom specialized classes from yaml-cpp to specialize to take in - * a atlas::body_layer specifically - * - * Specialization is used for converting atlas::body_layer to yaml-cpp - * syntax when saving atlas::body_layer data to disk - */ - template<> - struct convert { - static Node encode(const atlas::body_layer& rhs) { - Node node; - node.push_back(static_cast(rhs)); - return node; - } - - static bool decode(const Node& node, atlas::body_layer& rhs) { - if (!node.IsScalar()) { - return false; - } - rhs = static_cast(node.as()); - return true; - } - }; - - /** - * @brief Custom specialized classes from yaml-cpp to specialize to take in - * a atlas::physics_body specifically - * - * Specialization is used for converting atlas::physics_body to yaml-cpp - * syntax when saving atlas::physics_body data to disk - */ - template<> - struct convert { - - static Node encode(const atlas::physics_body& rhs) { - Node node; - // Encode glm::vec3 members - node["Linear Velocity"] = rhs.linear_velocity; - node["Angular Velocity"] = rhs.angular_velocity; - node["Force"] = rhs.force; - node["Impulse"] = rhs.impulse; - node["Torque"] = rhs.torque; - node["Mass Factor"] = rhs.mass_factor; - node["Center Mass Position"] = rhs.center_mass_position; - // node["Gravity Enabled"] = rhs.use_gravity; - node["Gravity Factor"] = rhs.gravity_factor; - // node["Body Type"] = rhs.body_type; - node["Friction"] = rhs.friction; - node["Restitution"] = rhs.restitution; - node["Body Movement Type"] = rhs.body_movement_type; - node["Body Layer Type"] = rhs.body_layer_type; - - return node; - } - - static bool decode(const Node& node, atlas::physics_body& rhs) { - if (!node.IsMap()) { - return false; - } - - rhs.linear_velocity = node["Linear Velocity"].as(); - rhs.angular_velocity = node["Angular Velocity"].as(); - rhs.force = node["Force"].as(); - rhs.impulse = node["Impulse"].as(); - rhs.torque = node["Torque"].as(); - rhs.mass_factor = node["Mass Factor"].as(); - rhs.center_mass_position = - node["Center Mass Position"].as(); - rhs.gravity_factor = node["Gravity Factor"].as(); - rhs.friction = node["Friction"].as(); - rhs.restitution = node["Restitution"].as(); - rhs.body_movement_type = node["Body Movement Type"].as(); - rhs.body_layer_type = node["Body Layer Type"].as(); - return true; - } - }; - - /** - * @brief Custom specialized classes from yaml-cpp to specialize to take in - * a atlas::box_collider specifically - * - * Specialization is used for converting atlas::box_collider to yaml-cpp - * syntax when saving atlas::box_collider data to disk - */ - template<> - struct convert { - - static Node encode(const atlas::box_collider& rhs) { - Node node; - // Encode glm::vec3 members - node["Half Extent"] = rhs.half_extent; - - return node; - } - - static bool decode(const Node& node, atlas::box_collider& rhs) { - if (!node.IsMap()) { - return false; - } - - rhs.half_extent = node["half Extent"].as(); - return true; - } - }; - - /** - * @brief Custom specialized classes from yaml-cpp to specialize to take in - * a atlas::sphere_collider specifically - * - * Specialization is used for converting atlas::sphere_collider to yaml-cpp - * syntax when saving atlas::sphere_collider data to disk - */ - template<> - struct convert { - - static Node encode(const atlas::sphere_collider& rhs) { - Node node; - // Encode glm::vec3 members - node["Radius"] = rhs.radius; - - return node; - } - - static bool decode(const Node& node, atlas::sphere_collider& rhs) { - if (!node.IsMap()) { - return false; - } - - rhs.radius = node["Radius"].as(); - return true; - } - }; - - /** - * @brief Custom specialized classes from yaml-cpp to specialize to take in - * a atlas::capsule_collider specifically - * - * Specialization is used for converting atlas::capsule_collider to yaml-cpp - * syntax when saving atlas::capsule_collider data to disk - */ - template<> - struct convert { - - static Node encode(const atlas::capsule_collider& rhs) { - Node node; - // Encode glm::vec3 members - node["Half Height"] = rhs.half_height; - node["Radius"] = rhs.radius; - - return node; - } - - static bool decode(const Node& node, atlas::capsule_collider& rhs) { - if (!node.IsMap()) { - return false; - } - - rhs.radius = node["Radius"].as(); - rhs.half_height = node["Half height"].as(); - return true; - } - }; -}; - -namespace atlas { - //! @brief from yaml-cpp, saving glm::highp_vec2 values to disk - YAML::Emitter& operator<<(YAML::Emitter& p_out, - const glm::highp_vec2& p_values); - - //! @brief from yaml-cpp, saving glm::highp_vec3 values to disk - YAML::Emitter& operator<<(YAML::Emitter& p_out, - const glm::highp_vec3& p_values); - - //! @brief from yaml-cpp, saving glm::highp_vec4 values to disk - YAML::Emitter& operator<<(YAML::Emitter& p_out, - const glm::highp_vec4& p_values); - - //! @brief from yaml-cpp, saving transform values to disk - YAML::Emitter& operator<<(YAML::Emitter& p_output, - const transform* p_transform); - - //! @brief from yaml-cpp, saving perspective_camera values to disk - YAML::Emitter& operator<<(YAML::Emitter& p_output, - const perspective_camera* p_camera); - - //! @brief from yaml-cpp, saving mesh_source values to disk - YAML::Emitter& operator<<(YAML::Emitter& p_output, - const mesh_source* p_material); - - //! @brief from yaml-cpp, saving mesh_source values to disk - YAML::Emitter& operator<<(YAML::Emitter& p_output, - const point_light* p_material); - - //! @brief from yaml-cpp, saving physics_body values to disk - YAML::Emitter& operator<<(YAML::Emitter& p_output, - const physics_body* p_body); - - //! @brief from yaml-cpp, saving box_collider values to disk - YAML::Emitter& operator<<(YAML::Emitter& p_output, - const box_collider* p_body); - - //! @brief from yaml-cpp, saving sphere_collider values to disk - YAML::Emitter& operator<<(YAML::Emitter& p_output, - const sphere_collider* p_body); - - //! @brief from yaml-cpp, saving capsule_collider values to disk - YAML::Emitter& operator<<(YAML::Emitter& p_output, - const capsule_collider* p_body); -}; \ No newline at end of file diff --git a/atlas/core/system/registry.hpp b/atlas/core/system/registry.hpp deleted file mode 100644 index 5333f255..00000000 --- a/atlas/core/system/registry.hpp +++ /dev/null @@ -1,74 +0,0 @@ -#pragma once -#include -#include - -namespace atlas { - /** - * @brief system registry acts as a utility for managing creation of game - * worlds initially - * - * Initially utilized to manage lifetimes of worlds and allow for by default - * setting to world #0, where we use few functions to get access to specific - * contexts - * - * - * TODO: This is going to be replaced with a level streaming manager that - * will help manage, maintain, and default creationg of a world and a scene. - * With additional responsibilities in how the world context gets created. - */ - class system_registry { - public: - /** - * @brief construct a new system registry - * - * @param p_name is for specifying a name to give this registry - */ - system_registry(const std::string& p_name); - - ~system_registry(); - - /** - * @note system_registry does the following: - * 1. Creates world scopes - * 2. Manages Lifetimes of world objects - * 3. Keeps tracks of the refcounting of references to these world - * objects - * 4. Provide globalized access to other worlds - */ - - /** - * @brief constructs a new world - * - * Initially this was used to create a world with a specified name - * associated with it - * - * This was used for getting world to be maintained implicitly by - * system_registry, though this will be changing. - */ - static ref create_world(const std::string& p_tag); - - //! @brief Searches and returns world if found - //! @brief Returns nullptr if world not found - - /** - * @brief searches in getting the world and looks up based on its - * specified name - * - * @return nullptr if not found, otherwise return - * shared_ptr - */ - static ref get_world(const std::string& p_tag); - - private: - ref search_world(const std::string& p_tag); - - // void append_world(const ref& p_world); - - ref append_world_and_get(const ref& p_world); - - private: - static system_registry* s_instance; - std::string m_tag = "Undefined"; - std::map> m_world_registered; - }; -}; \ No newline at end of file diff --git a/atlas/core/ui/widgets.hpp b/atlas/core/ui/widgets.hpp deleted file mode 100644 index 3043670c..00000000 --- a/atlas/core/ui/widgets.hpp +++ /dev/null @@ -1,237 +0,0 @@ -#pragma once -#include -#include -#include -#include -#include -#include - -namespace atlas::ui { - - /** - * @brief This is a free-standing function around - * ImGui::BeginPopupContextWindow - * - * It is primarily used to check if your mouse cursor is hovering over any - * items and to opening items based on if the mouse is specifically hovering - * over that particular item - * - * - * @param p_name is the string ID that is needed to be specified by imgui - * @param p_mb is the mouse button identifier that is an int to represent if - * the presses were (0=left, 1=right, 2=middle) - * @param p_over_items is a boolean to check if the mouse cursor has - * hoivered over that particular item specified by the string ID - * - * @return true if successful, otherwise return false - * - */ - bool begin_popup_context_window(const char* p_name, - ImGuiMouseButton p_mb, - bool p_over_items); - - /** - * @brief UI render glm::vec3 values to imgui - * - * @param p_name is the specified name ID to associate with - * @param p_value is the value parameter to modify through this widget - * @param p_reset_value is the reset value to set the glm::vec3 - */ - void draw_vec3(const std::string& p_name, - glm::vec3& p_value, - float p_reset_value = 0.f); - - /** - * @brief UI render glm::vec4 values to imgui - * - * @param p_name is the specified name ID to associate with - * @param p_value is the value parameter to modify through this widget - * @param p_reset_value is the reset value to set the glm::vec3 - */ - void draw_vec4(const std::string& p_name, - glm::vec4& p_value, - float p_reset_value = 0.f); - - /** - * @brief UI render glm::vec4 values to imgui - * - * @param p_name is the specified name ID to associate with - * @param p_value is the value parameter to modify through this widget - * @param p_reset_value is the reset value to set the glm::vec3 - */ - void draw_float(const std::string& p_tag, - float& p_value, - float p_reset_value = 0.f); - - /** - * @brief UI rendering input text - * - * - * @param p_dst is the destination string to be changed - * @param p_src is the original string that was previously given - */ - void draw_input_text(std::string& p_dst, std::string& p_src); - - /** - * @brief For UI rendering text to display and not input - * - * @param p_value is specified string for drawing text to imgui's UI - */ - void draw_text(const std::string& p_value); - - /** - * @brief Creates a panel that can be used to attach list of properties or - * other widgets too - * - * @tparam UComponent is the type of component or type to assoociate with - * this panel too - * @tparam UFunction is the callback that contains an arbitrary task related - * to the specified UComponent - * @param p_name is the name to give this panel - * @param p_entity is the entity that is being modified by this specific - * panel - * @param p_callback is a callback that is given an arbitrary task - * - * - * Example Usage: - * - * ```C++ - * draw_panel_component("transform", [](atlas::transform* - * p_transform){ - * // do some drawing with that transform - * }); - * ``` - */ - template - static void draw_panel_component(const std::string& p_name, - flecs::entity& p_entity, - const UFunction& p_callback) { - const ImGuiTreeNodeFlags tree_node_flags = - ImGuiTreeNodeFlags_DefaultOpen | ImGuiTreeNodeFlags_Framed | - ImGuiTreeNodeFlags_SpanAvailWidth | - ImGuiTreeNodeFlags_AllowItemOverlap | ImGuiTreeNodeFlags_FramePadding; - - ImVec2 content_region = ImGui::GetContentRegionAvail(); - ImGui::PushStyleVar(ImGuiStyleVar_FramePadding, ImVec2{ 4, 4 }); - - float line_height = - ImGui::GetFontSize() + ImGui::GetStyle().FramePadding.y * 2.0f; - ImGui::Separator(); - - bool opened = ImGui::TreeNodeEx((void*)typeid(UComponent).hash_code(), - tree_node_flags, - "%s", - p_name.c_str()); - ImGui::PopStyleVar(); - - ImGui::SameLine(content_region.x - line_height * 0.05f); - - if (ImGui::Button("+", ImVec2(line_height, line_height))) { - ImGui::OpenPopup("ComponentSettings"); - } - - bool remove_component = false; // @note for deferring when to - // delete component. - if (ImGui::BeginPopup("ComponentSettings")) { - if (ImGui::MenuItem("Remove Component")) { - remove_component = true; - } - - ImGui::EndPopup(); - } - - if (remove_component) { - p_entity.remove(); - } - - if (opened) { - p_callback(p_entity.get_mut()); - ImGui::TreePop(); - } - } - - /** - draw panel component - - ImGui Renders individual sections that is per-component section - @param T is the specified component - @param p_entity is the entity to do operations with - @param UFunction is callback to logic for setting up those specific data - properties - */ - template - static void draw_component(const std::string& p_tag, - flecs::entity& p_entity, - const UFunction& p_callable) { - const ImGuiTreeNodeFlags tree_node_flags = - ImGuiTreeNodeFlags_DefaultOpen | ImGuiTreeNodeFlags_Framed | - ImGuiTreeNodeFlags_SpanAvailWidth | - ImGuiTreeNodeFlags_AllowItemOverlap | ImGuiTreeNodeFlags_FramePadding; - - if (!p_entity.has()) { - return; - } - - T* component = p_entity.get_mut(); - - ImVec2 content_region = ImGui::GetContentRegionAvail(); - ImGui::PushStyleVar(ImGuiStyleVar_FramePadding, ImVec2{ 4, 4 }); - - float line_height = - ImGui::GetFontSize() + ImGui::GetStyle().FramePadding.y * 2.0f; - ImGui::Separator(); - - bool opened = ImGui::TreeNodeEx( - (void*)typeid(T).hash_code(), tree_node_flags, "%s", p_tag.c_str()); - ImGui::PopStyleVar(); - - ImGui::SameLine(content_region.x - line_height * 0.05f); - - if (ImGui::Button("+", ImVec2(line_height, line_height))) { - ImGui::OpenPopup("ComponentSettings"); - } - - bool remove_component = false; // @note for deferring when to - // delete component. - if (ImGui::BeginPopup("ComponentSettings")) { - if (ImGui::MenuItem("Remove Component")) { - remove_component = true; - } - - ImGui::EndPopup(); - } - - if (opened) { - p_callable(component); - ImGui::TreePop(); - } - - if (remove_component and !std::is_same_v) { - p_entity.remove(); - } - } - - /** - * @brief used for creating a main dockspace for the editor - * - * TODO: This should be removed because this will be added into a separate - * atlas/editor/ toolchain module - */ - void dockspace_window(GLFWwindow* p_window); - - /** - * @brief opens up a file dialog that uses imgui's button widget to make - * this happen - * - * This uses ImGui::Button to allow for when a click occurs it opens up the - * platform-specific file dialog to save or load in a particular file - * - * @param p_name is the specified name ID to pass into imgui - * @param p_filepath is the path of the file - * @param p_filter is the specific filter for file extensions to allow - * displaying in the fild dialog - */ - void button_open_file_dialog(const std::string& p_name, - std::string& p_filepath, - const std::string& p_filter = "obj;glftf;fbx"); -}; \ No newline at end of file diff --git a/atlas/core/utilities/hash.hpp b/atlas/core/utilities/hash.hpp deleted file mode 100644 index 9bc1fa5f..00000000 --- a/atlas/core/utilities/hash.hpp +++ /dev/null @@ -1,12 +0,0 @@ -#pragma once -#include -#include - -namespace atlas { - template - void hash_combine(size_t& seed, const T& v, const Rest&... rest) { - seed ^= std::hash()(v) + 0x9e3779b9 + (seed << 6) + (seed << 2); - (hash_combine(seed, rest), ...); - } - -}; \ No newline at end of file diff --git a/atlas/core/utilities/memory.hpp b/atlas/core/utilities/memory.hpp deleted file mode 100644 index e5df5eed..00000000 --- a/atlas/core/utilities/memory.hpp +++ /dev/null @@ -1,1665 +0,0 @@ -/* - Copied from - https://github.com/libhal/libhal/blob/main/include/libhal/pointers.hpp - - [atlas] modifications - 1.) File renamed to memory - 2.) In the atlas:: namespace. -*/ -#include -#include -#include -#include -#include -#include -#include -#include - -namespace atlas::memory { - // Forward declarations - template - class strong_ptr; - - template - class weak_ptr; - - namespace detail { - /** - * @brief Control block for reference counting - type erased. - * - * This structure manages the lifetime of reference-counted objects by - * tracking strong and weak references. It also stores the memory - * allocator and destroy function used to clean up the object when no - * more references exist. - */ - struct ref_info { - /** - * @brief Destroy function for ref counted object - * - * Always returns the total size of the object wrapped in a ref - * count object. Thus the size should normally be greater than - * sizeof(T). Expect sizeof(T) + sizeof(ref_info) and anything else - * the ref count object may contain. - * - * If a nullptr is passed to the destroy function, it returns the - * object size but does not destroy the object. - */ - using destroy_fn_t = size_t(void const*); - - /// Initialize to 1 since creation implies a reference - std::pmr::polymorphic_allocator<> allocator; - destroy_fn_t* destroy; - std::atomic strong_count = 1; - std::atomic weak_count = 0; - }; - - /** - * @brief Add strong reference to control block - * - * @param p_info Pointer to the control block - */ - inline void ptr_add_ref(ref_info* p_info) { - p_info->strong_count.fetch_add(1, std::memory_order_relaxed); - } - - /** - * @brief Release strong reference from control block - * - * If this was the last strong reference, the pointed-to object will be - * destroyed. If there are no remaining weak references, the memory - * will also be deallocated. - * - * @param p_info Pointer to the control block - */ - inline void ptr_release(ref_info* p_info) { - if (p_info->strong_count.fetch_sub(1, std::memory_order_acq_rel) == - 1) { - // No more strong references, destroy the object but keep - // control block if there are weak references - - // Call the destroy function which will: - // 1. Call the destructor of the object - // 2. Return the size of the rc for deallocation when needed - size_t const object_size = p_info->destroy(p_info); - - // If there are no weak references, deallocate memory - if (p_info->weak_count.load(std::memory_order_acquire) == 0) { - // Save allocator for deallocating - auto alloc = p_info->allocator; - - // Deallocate memory - alloc.deallocate_bytes(p_info, object_size); - } - } - } - - /** - * @brief Add weak reference to control block - * - * @param p_info Pointer to the control block - */ - inline void ptr_add_weak(ref_info* p_info) { - p_info->weak_count.fetch_add(1, std::memory_order_relaxed); - } - - /** - * @brief Release weak reference from control block - * - * If this was the last weak reference and there are no remaining - * strong references, the memory will be deallocated. - * - * @param p_info Pointer to the control block - */ - inline void ptr_release_weak(ref_info* p_info) { - if (p_info->weak_count.fetch_sub(1, std::memory_order_acq_rel) == - 0) { - // No more weak references, check if we can deallocate - if (p_info->strong_count.load(std::memory_order_acquire) == 0) { - // No strong references either, get the size from the - // destroy function - auto const object_size = p_info->destroy(nullptr); - - // Save allocator for deallocating - auto alloc = p_info->allocator; - - // Deallocate memory - alloc.deallocate_bytes(p_info, object_size); - } - } - } - - /** - * @brief A wrapper that contains both the ref_info and the actual - * object - * - * This structure keeps the control block and managed object together in - * memory. - * - * @tparam T The type of the managed object - */ - template - struct rc { - ref_info m_info; - T m_object; - - // Constructor that forwards arguments to the object - template - rc(std::pmr::polymorphic_allocator<> p_alloc, Args&&... args) - : m_info{ .allocator = p_alloc, .destroy = &destroy_function } - , m_object(std::forward(args)...) {} - - // Static function to destroy an instance and return its size - static size_t destroy_function(void const* p_object) { - if (p_object != nullptr) { - auto const* obj = static_cast const*>(p_object); - // Call destructor for the object only - obj->m_object.~T(); - } - // Return size for future deallocation - return sizeof(rc); - } - }; - // Check if a type is an array or std::array - template - struct is_array_like : std::false_type {}; - - // NOLINTBEGIN(modernize-avoid-c-arrays) - // Specialization for C-style arrays - template - struct is_array_like : std::true_type {}; - // NOLINTEND(modernize-avoid-c-arrays) - - // Specialization for std::array - template - struct is_array_like> : std::true_type {}; - - // Helper variable template - template - inline constexpr bool is_array_like_v = is_array_like::value; - - // Concept for array-like types - template - concept array_like = is_array_like_v; - - // Concept for non-array-like types - template - concept non_array_like = !array_like; - } // namespace detail - - /** - * @brief A non-nullable strong reference counted pointer - * - * strong_ptr is a smart pointer that maintains shared ownership of an - * object through a reference count. It is similar to std::shared_ptr but - * with these key differences: - * - * 1. Cannot be null - must always point to a valid object - * 2. Can only be created via make_strong_ptr, not from raw pointers - * 3. More memory efficient implementation - * - * Use strong_ptr when you need shared ownership semantics and can guarantee - * the pointer will never be null. For nullable references, use - * optional_ptr. - * - * Example usage: - * - * ```C++ - * // Create a strong_ptr to an object - * auto ptr = hal::make_strong_ptr(allocator, arg1, arg2); - * - * // Use the object using dereference (*) operator - * (*ptr).configure({ .clock_rate = 250_kHz }); - * - * // OR use the object using arrow (->) operator - * ptr->configure({ .clock_rate = 250_kHz }); - * - * // Share ownership with another driver or object - * auto my_imu = hal::make_strong_ptr(allocator, ptr, 0x13); - * ``` - * - * @tparam T The type of the managed object - */ - template - class strong_ptr { - public: - using element_type = T; - - /// Delete default constructor - strong_ptr must always be valid - strong_ptr() = delete; - - /// Delete nullptr constructor - strong_ptr must always be valid - strong_ptr(std::nullptr_t) = delete; - - /** - * @brief Copy constructor - * - * Creates a new strong reference to the same object. - * - * @param p_other The strong_ptr to copy from - */ - strong_ptr(strong_ptr const& p_other) noexcept - : m_ctrl(p_other.m_ctrl) - , m_ptr(p_other.m_ptr) { - ptr_add_ref(m_ctrl); - } - - /** - * @brief Converting copy constructor - * - * Creates a new strong reference to the same object, converting from - * a derived type U to base type T. - * - * @tparam U A type convertible to T - * @param p_other The strong_ptr to copy from - */ - template - strong_ptr(strong_ptr const& p_other) noexcept - requires(std::is_convertible_v) - : m_ctrl(p_other.m_ctrl) - , m_ptr(p_other.m_ptr) { - ptr_add_ref(m_ctrl); - } - - /** - * @brief Move constructor that intentionally behaves like a copy - * constructor for safety - * - * This move constructor deliberately performs a full copy operation - * rather than transferring ownership. This is a safety feature to - * prevent potential undefined behavior that could occur if code - * accidentally accessed a moved-from strong_ptr. - * - * After this operation, both the source and destination objects remain - * in valid states, and the reference count is incremented by 1. This - * ensures that even if code incorrectly continues to use the source - * object after a move, no undefined behavior will occur. - * - * @param p_other The strong_ptr to "move" from (actually copied for - * safety) - */ - strong_ptr(strong_ptr&& p_other) noexcept - : m_ctrl(p_other.m_ctrl) - , m_ptr(p_other.m_ptr) { - ptr_add_ref(m_ctrl); - } - - /** - * @brief Move assignment operator that behaves like a copy assignment - * for safety - * - * This move assignment operator deliberately performs a full copy - * operation rather than transferring ownership. This is a safety - * feature to prevent potential undefined behavior that could occur if - * code accidentally accessed a moved-from strong_ptr. - * - * After this operation, both the source and destination objects remain - * in valid states, and the reference count is incremented by 1. This - * ensures that even if code incorrectly continues to use the source - * object after a move, no undefined behavior will occur. - * - * @param p_other The strong_ptr to "move" from (actually copied for - * safety) - * @return Reference to *this - */ - strong_ptr& operator=(strong_ptr&& p_other) noexcept { - if (this != &p_other) { - release(); - m_ctrl = p_other.m_ctrl; - m_ptr = p_other.m_ptr; - ptr_add_ref(m_ctrl); - } - return *this; - } - - /** - * @brief Compile time error message for bad alias value - * - * `std::shared_ptr` provides an alias constructor that accepts any - * `void*` which is UB if that `void*` doesn't have the same lifetime as - * the object referenced by the `std::shared_ptr`. Users attempting to - * do this will get a list of constructors that failed to fit. This is - * not a good error message for users. Instead, we provide a - * static_assert message in plain english that explains why this - * overload fails at compile time. - * - * @tparam U - some type for the strong_ptr. - */ - template - strong_ptr(strong_ptr const&, void const*) noexcept { - // NOTE: The conditional used here is to prevent the compiler from - // jumping-the-gun and emitting the static assert error during - // template instantiation of the class. With this conditional, the - // error only appears when this constructor is used. - static_assert( - std::is_same_v && !std::is_same_v, - "Aliasing constructor only works with pointers-to-members " - "and does not work with arbitrary pointers like std::shared_ptr " - "allows."); - } - - /** - * @brief Safe aliasing constructor for object members - * - * This constructor creates a strong_ptr that points to a member of an - * object managed by another strong_ptr. The resulting strong_ptr shares - * ownership with the original strong_ptr, keeping the entire parent - * object alive. - * - * This version is only enabled for non-array members to prevent - * potential undefined behavior when accessing array elements directly. - * Use the array-specific versions instead. - * - * Example usage: - * ``` - * struct container { - * component part; - * }; - * - * // Create a strong_ptr to the container - * auto container_ptr = make_strong_ptr(allocator); - * - * // Create a strong_ptr to just the component - * auto component_ptr = strong_ptr(container_ptr, - * &container::part); - * ``` - * - * @tparam U Type of the parent object - * @tparam M Type of the member - * @param p_other The strong_ptr to the parent object - * @param p_member_ptr Pointer-to-member identifying which member to - * reference - */ - template - strong_ptr(strong_ptr const& p_other, - // clang-format off - M U::* p_member_ptr - // clang-format on - ) noexcept - - : m_ctrl(p_other.m_ctrl) - , m_ptr(&((*p_other).*p_member_ptr)) { - ptr_add_ref(m_ctrl); - } - - /** - * @brief Safe aliasing constructor for std::array members - * - * This constructor creates a strong_ptr that points to an element of an - * array member in an object managed by another strong_ptr. It performs - * bounds checking to ensure the index is valid. - * - * Example usage: - * ``` - * struct array_container { - * std::array elements; - * }; - * - * auto container_ptr = make_strong_ptr(allocator); - * - * // Get strong_ptr to the 2nd element - * auto element_ptr = strong_ptr( - * container_ptr, - * &array_container::elements, - * 2 // Index to access - * ); - * ``` - * - * @tparam U Type of the parent object - * @tparam E Type of the array element - * @tparam N Size of the array - * @param p_other The strong_ptr to the parent object - * @param p_array_ptr Pointer-to-member identifying the array member - * @param p_index Index of the element to reference - * @throws hal::out_of_range if index is out of bounds - */ - template - strong_ptr(strong_ptr const& p_other, - // clang-format off - std::array U::* p_array_ptr, - // clang-format on - std::size_t p_index) { - static_assert(std::is_convertible_v, - "Array element type must be convertible to T"); - throw_if_out_of_bounds(N, p_index); - m_ctrl = p_other.m_ctrl; - m_ptr = &((*p_other).*p_array_ptr)[p_index]; - ptr_add_ref(m_ctrl); - } - - // NOLINTBEGIN(modernize-avoid-c-arrays) - /** - * @brief Safe aliasing constructor for C-array members - * - * This constructor creates a strong_ptr that points to an element of a - * C-style array member in an object managed by another strong_ptr. It - * performs bounds checking to ensure the index is valid. - * - * Example usage: - * ``` - * struct c_array_container { - * element elements[5]; - * }; - * - * auto container_ptr = make_strong_ptr(allocator); - * - * // Get strong_ptr to the 2nd element - * auto element_ptr = strong_ptr( - * container_ptr, - * &c_array_container::elements, - * 2 // Index to access - * ); - * ``` - * - * @tparam U Type of the parent object - * @tparam E Type of the array element - * @tparam N Size of the array - * @param p_other The strong_ptr to the parent object - * @param p_array_ptr Pointer-to-member identifying the array member - * @param p_index Index of the element to reference - * @throws hal::out_of_range if index is out of bounds - */ - template - strong_ptr(strong_ptr const& p_other, - E (U::*p_array_ptr)[N], - std::size_t p_index) { - static_assert(std::is_convertible_v, - "Array element type must be convertible to T"); - throw_if_out_of_bounds(N, p_index); - m_ctrl = p_other.m_ctrl; - m_ptr = &((*p_other).*p_array_ptr)[p_index]; - ptr_add_ref(m_ctrl); - } - // NOLINTEND(modernize-avoid-c-arrays) - - /** - * @brief Destructor - * - * Decrements the reference count and destroys the managed object - * if this was the last strong reference. - */ - ~strong_ptr() { release(); } - - /** - * @brief Copy assignment operator - * - * Replaces the managed object with the one managed by p_other. - * - * @param p_other The strong_ptr to copy from - * @return Reference to *this - */ - strong_ptr& operator=(strong_ptr const& p_other) noexcept { - if (this != &p_other) { - release(); - m_ctrl = p_other.m_ctrl; - m_ptr = p_other.m_ptr; - ptr_add_ref(m_ctrl); - } - return *this; - } - - /** - * @brief Converting copy assignment operator - * - * Replaces the managed object with the one managed by p_other, - * converting from type U to type T. - * - * @tparam U A type convertible to T - * @param p_other The strong_ptr to copy from - * @return Reference to *this - */ - template - strong_ptr& operator=(strong_ptr const& p_other) noexcept - requires(std::is_convertible_v) - { - release(); - m_ctrl = p_other.m_ctrl; - m_ptr = p_other.m_ptr; - ptr_add_ref(m_ctrl); - return *this; - } - - /** - * @brief Swap the contents of this strong_ptr with another - * - * @param p_other The strong_ptr to swap with - */ - void swap(strong_ptr& p_other) noexcept { - std::swap(m_ctrl, p_other.m_ctrl); - std::swap(m_ptr, p_other.m_ptr); - } - - /** - * @brief Disable dereferencing for r-values (temporaries) - */ - T& operator*() && = delete; - - /** - * @brief Disable member access for r-values (temporaries) - */ - T* operator->() && = delete; - - /** - * @brief Dereference operator to access the managed object - * - * @return Reference to the managed object - */ - [[nodiscard]] T& operator*() const& noexcept { return *m_ptr; } - - /** - * @brief Member access operator to access the managed object - * - * @return Pointer to the managed object - */ - [[nodiscard]] T* operator->() const& noexcept { return m_ptr; } - - /** - * @brief Get the current reference count - * - * This is primarily for testing purposes. - * - * @return The number of strong references to the managed object - */ - [[nodiscard]] auto use_count() const noexcept { - return m_ctrl ? m_ctrl->strong_count.load(std::memory_order_relaxed) - : 0; - } - - private: - template - friend strong_ptr make_strong_ptr(std::pmr::polymorphic_allocator<>, - Args&&...); - - template - friend class strong_ptr; - - template - friend class weak_ptr; - - template - friend class optional_ptr; - - inline void throw_if_out_of_bounds(size_t p_size, size_t p_index) { - if (p_index >= p_size) { - throw std::out_of_range( - this, { .m_index = p_index, .m_capacity = p_size }); - } - } - - // Internal constructor with control block and pointer - used by make() - // and aliasing - strong_ptr(detail::ref_info* p_ctrl, T* p_ptr) noexcept - : m_ctrl(p_ctrl) - , m_ptr(p_ptr) {} - - void release() { - if (m_ctrl) { - ptr_release(m_ctrl); - } - } - - detail::ref_info* m_ctrl = nullptr; - T* m_ptr = nullptr; - }; - - /** - * @brief CRTP mixin to enable objects to create strong_ptr instances to - * themselves - * - * Similar to `std::enable_shared_from_this`, this class allows an object to - * safely obtain a strong_ptr to itself. The object must inherit from this - * class and be managed by a strong_ptr created via make_strong_ptr. - * - * Example usage: - * ```cpp - * class my_driver : public enable_strong_from_this { - * public: - * void register_callback() { - * // Get a strong_ptr to ourselves - * auto self = strong_from_this(); - * some_async_system.register_callback([self](){ - * self->handle_callback(); - * }); - * } - * }; - * - * auto obj = make_strong_ptr(allocator); - * obj->register_callback(); // Safe to get strong_ptr to self - * ``` - * - * @tparam T The derived class type - */ - template - class enable_strong_from_this { - public: - /** - * @brief Get a strong_ptr to this object - * - * @return strong_ptr pointing to this object - * @throws hal::bad_weak_ptr if this object is not managed by a - * strong_ptr - */ - [[nodiscard]] strong_ptr strong_from_this() { - auto locked = m_weak_this.lock(); - if (!locked) { - throw std::bad_weak_ptr(&weak_from_this); - } - return locked.value(); - } - - /** - * @brief Get a strong_ptr to this object (const version) - * - * @return strong_ptr pointing to this object - * @throws hal::bad_weak_ptr if this object is not managed by a - * strong_ptr - */ - [[nodiscard]] strong_ptr strong_from_this() const { - auto locked = m_weak_this.lock(); - if (!locked) { - throw std::bad_weak_ptr(&weak_from_this); - } - // Cast the strong_ptr to strong_ptr - return strong_ptr(locked.value()); - } - - /** - * @brief Get a weak_ptr to this object - * - * @return weak_ptr pointing to this object - */ - [[nodiscard]] weak_ptr weak_from_this() noexcept { - return m_weak_this; - } - - /** - * @brief Get a weak_ptr to this object (const version) - * - * @return weak_ptr pointing to this object - */ - [[nodiscard]] weak_ptr weak_from_this() const noexcept { - return weak_ptr(m_weak_this); - } - - protected: - /** - * @brief Protected constructor to prevent direct instantiation - */ - enable_strong_from_this() = default; - - /** - * @brief Protected copy constructor - * - * Note: The weak_ptr is not copied - each object gets its own weak - * reference - */ - enable_strong_from_this(enable_strong_from_this const&) noexcept { - // Intentionally don't copy m_weak_this - } - - /** - * @brief Protected assignment operator - * - * Note: The weak_ptr is not assigned - each object keeps its own weak - * reference - */ - enable_strong_from_this& operator=( - enable_strong_from_this const&) noexcept { - // Intentionally don't assign m_weak_this - return *this; - } - - /** - * @brief Protected destructor - */ - ~enable_strong_from_this() = default; - - private: - template - friend strong_ptr make_strong_ptr(std::pmr::polymorphic_allocator<>, - Args&&...); - - /** - * @brief Initialize the weak reference (called by make_strong_ptr) - * - * @param p_self The strong_ptr that manages this object - */ - void init_weak_this(strong_ptr const& p_self) noexcept { - m_weak_this = p_self; - } - - mutable weak_ptr m_weak_this; - }; - - template - class optional_ptr; - - /** - * @brief A weak reference to a strong_ptr - * - * weak_ptr provides a non-owning reference to an object managed by - * strong_ptr. It can be used to break reference cycles or to create an - * optional_ptr. - * - * A weak_ptr doesn't increase the strong reference count, so it doesn't - * prevent the object from being destroyed when the last strong_ptr goes - * away. - * - * Example usage: - * ``` - * // Create a strong_ptr to an object - * auto ptr = hal::make_strong_ptr(allocator, args...); - * - * // Create a weak reference - * weak_ptr weak = ptr; - * - * // Later, try to get a strong reference - * if (auto locked = weak.lock()) { - * // Use the object via locked - * locked->doSomething(); - * } else { - * // Object has been destroyed - * } - * ``` - * - * @tparam T The type of the referenced object - */ - template - class weak_ptr { - public: - template - friend class strong_ptr; - - template - friend class weak_ptr; - - using element_type = T; - - /** - * @brief Default constructor creates empty weak_ptr - */ - weak_ptr() noexcept = default; - - /** - * @brief Create weak_ptr from strong_ptr - * - * @param p_strong The strong_ptr to create a weak reference to - */ - weak_ptr(strong_ptr const& p_strong) noexcept - : m_ctrl(p_strong.m_ctrl) - , m_ptr(p_strong.m_ptr) { - if (m_ctrl) { - ptr_add_weak(m_ctrl); - } - } - - /** - * @brief Copy constructor - * - * @param p_other The weak_ptr to copy from - */ - weak_ptr(weak_ptr const& p_other) noexcept - : m_ctrl(p_other.m_ctrl) - , m_ptr(p_other.m_ptr) { - if (m_ctrl) { - ptr_add_weak(m_ctrl); - } - } - - /** - * @brief Move constructor - * - * @param p_other The weak_ptr to move from - */ - weak_ptr(weak_ptr&& p_other) noexcept - : m_ctrl(p_other.m_ctrl) - , m_ptr(p_other.m_ptr) { - p_other.m_ctrl = nullptr; - p_other.m_ptr = nullptr; - } - - /** - * @brief Converting copy constructor - * - * Creates a weak_ptr of T from a weak_ptr of U where U is convertible - * to T. - * - * @tparam U A type convertible to T - * @param p_other The weak_ptr to copy from - */ - template - weak_ptr(weak_ptr const& p_other) noexcept - requires(std::is_convertible_v) - : m_ctrl(p_other.m_ctrl) - , m_ptr(static_cast(p_other.m_ptr)) { - if (m_ctrl) { - ptr_add_weak(m_ctrl); - } - } - - /** - * @brief Converting move constructor - * - * Moves a weak_ptr of U to a weak_ptr T where U is convertible to T. - * - * @tparam U A type convertible to T - * @param p_other The weak_ptr to move from - */ - template - weak_ptr(weak_ptr&& p_other) noexcept - requires(std::is_convertible_v) - : m_ctrl(p_other.m_ctrl) - , m_ptr(static_cast(p_other.m_ptr)) { - p_other.m_ctrl = nullptr; - p_other.m_ptr = nullptr; - } - - /** - * @brief Converting constructor from strong_ptr - * - * Creates a weak_ptr from a strong_ptr where U is convertible to T. - * - * @tparam U A type convertible to T - * @param p_other The strong_ptr to create a weak reference to - */ - template - weak_ptr(strong_ptr const& p_other) noexcept - requires(std::is_convertible_v) - : m_ctrl(p_other.m_ctrl) - , m_ptr(static_cast(p_other.m_ptr)) { - if (m_ctrl) { - ptr_add_weak(m_ctrl); - } - } - - /** - * @brief Destructor - * - * Decrements the weak reference count and potentially deallocates - * memory if this was the last reference. - */ - ~weak_ptr() { - if (m_ctrl) { - ptr_release_weak(m_ctrl); - } - } - - /** - * @brief Copy assignment operator - * - * @param p_other The weak_ptr to copy from - * @return Reference to *this - */ - weak_ptr& operator=(weak_ptr const& p_other) noexcept { - weak_ptr(p_other).swap(*this); - return *this; - } - - /** - * @brief Move assignment operator - * - * @param p_other The weak_ptr to move from - * @return Reference to *this - */ - weak_ptr& operator=(weak_ptr&& p_other) noexcept { - weak_ptr(std::move(p_other)).swap(*this); - return *this; - } - - /** - * @brief Assignment from strong_ptr - * - * @param p_strong The strong_ptr to create a weak reference to - * @return Reference to *this - */ - weak_ptr& operator=(strong_ptr const& p_strong) noexcept { - weak_ptr(p_strong).swap(*this); - return *this; - } - - /** - * @brief Swap the contents of this weak_ptr with another - * - * @param p_other The weak_ptr to swap with - */ - void swap(weak_ptr& p_other) noexcept { - std::swap(m_ctrl, p_other.m_ctrl); - std::swap(m_ptr, p_other.m_ptr); - } - - /** - * @brief Check if the referenced object has been destroyed - * - * @return true if the object has been destroyed, false otherwise - */ - [[nodiscard]] bool expired() const noexcept { - return !m_ctrl || - m_ctrl->strong_count.load(std::memory_order_relaxed) == 0; - } - - /** - * @brief Attempt to obtain a strong_ptr to the referenced object - * - * If the object still exists, returns an optional_ptr containing - * a strong_ptr to it. Otherwise, returns an empty optional_ptr. - * - * @return An optional_ptr that is either empty or contains a strong_ptr - */ - [[nodiscard]] optional_ptr lock() const noexcept; - - /** - * @brief Get the current strong reference count - * - * This is primarily for testing purposes. - * - * @return The number of strong references to the managed object - */ - [[nodiscard]] auto use_count() const noexcept { - return m_ctrl ? m_ctrl->strong_count.load(std::memory_order_relaxed) - : 0; - } - - private: - detail::ref_info* m_ctrl = nullptr; - T* m_ptr = nullptr; - }; - - /** - * @brief Optional, nullable, smart pointer that works with - * `hal::strong_ptr`. - * - * optional_ptr provides a way to represent a strong_ptr that may or may not - * be present. Unlike strong_ptr, which is always valid, optional_ptr can be - * in a "disengaged" state where it doesn't reference any object. - * - * Use optional_ptr when you need a nullable reference to a - * reference-counted object, such as: - * - Representing the absence of a value - * - Return values from functions that may fail - * - Results of locking a weak_ptr - * - * Example usage: - * ``` - * // Create an empty optional_ptr - * optional_ptr opt1; - * - * // Create an optional_ptr from a strong_ptr - * auto ptr = make_strong_ptr(allocator, args...); - * optional_ptr opt2 = ptr; - * - * // Check if the optional_ptr is engaged - * if (opt2) { - * // Use the contained object - * opt2->doSomething(); - * } - * - * // Reset to disengage - * opt2.reset(); - * ``` - * - * @tparam T - The type pointed to by strong_ptr - */ - template - class optional_ptr { - public: - /** - * @brief Default constructor creates a disengaged optional - */ - constexpr optional_ptr() noexcept {} - - /** - * @brief Constructor for nullptr (creates a disengaged optional) - */ - constexpr optional_ptr(std::nullptr_t) noexcept {} - - /** - * @brief Move constructor is deleted - */ - constexpr optional_ptr(optional_ptr&& p_other) noexcept = delete; - - /** - * @brief Construct from a strong_ptr lvalue - * - * @param value The strong_ptr to wrap - */ - constexpr optional_ptr(strong_ptr const& value) noexcept - : m_value(value) {} - - /** - * @brief Copy constructor - * - * @param p_other The optional_ptr to copy from - */ - constexpr optional_ptr(optional_ptr const& p_other) { *this = p_other; } - - /** - * @brief Converting constructor from a strong_ptr - * - * @tparam U A type convertible to T - * @param p_value The strong_ptr to wrap - */ - template - constexpr optional_ptr(strong_ptr const& p_value) - requires(std::is_convertible_v) - { - *this = p_value; - } - - /** - * @brief Move assignment operator is deleted - */ - constexpr optional_ptr& operator=(optional_ptr&& other) noexcept = - delete; - - /** - * @brief Copy assignment operator - * - * @param other The optional_ptr to copy from - * @return Reference to *this - */ - constexpr optional_ptr& operator=(optional_ptr const& other) { - if (this != &other) { - if (is_engaged() && other.is_engaged()) { - m_value = other.m_value; - } - else if (is_engaged() && not other.is_engaged()) { - reset(); - } - else if (not is_engaged() && other.is_engaged()) { - new (&m_value) strong_ptr(other.m_value); - } - } - return *this; - } - - /** - * @brief Assignment from a strong_ptr - * - * @param value The strong_ptr to wrap - * @return Reference to *this - */ - constexpr optional_ptr& operator=(strong_ptr const& value) noexcept { - if (is_engaged()) { - m_value = value; - } - else { - new (&m_value) strong_ptr(value); - } - return *this; - } - - /** - * @brief Converting assignment from a strong_ptr - * - * @tparam U A type convertible to T - * @param p_value The strong_ptr to wrap - * @return Reference to *this - */ - template - constexpr optional_ptr& operator=(strong_ptr const& p_value) noexcept - requires(std::is_convertible_v) - { - if (is_engaged()) { - m_value = p_value; - } - else { - new (&m_value) strong_ptr(p_value); - } - return *this; - } - - /** - * @brief Assignment from nullptr (resets to disengaged state) - * - * @return Reference to *this - */ - constexpr optional_ptr& operator=(std::nullptr_t) noexcept { - reset(); - return *this; - } - - /** - * @brief Destructor - * - * Properly destroys the contained strong_ptr if engaged. - */ - ~optional_ptr() { - if (is_engaged()) { - m_value.~strong_ptr(); - } - } - - /** - * @brief Check if the optional_ptr is engaged - * - * @return true if the optional_ptr contains a value, false otherwise - */ - [[nodiscard]] constexpr bool has_value() const noexcept { - return is_engaged(); - } - - /** - * @brief Check if the optional_ptr is engaged - * - * @return true if the optional_ptr contains a value, false otherwise - */ - constexpr explicit operator bool() const noexcept { - return is_engaged(); - } - - /** - * @brief Access the contained value, throw if not engaged - * - * @return A copy of the contained strong_ptr - * @throws hal::bad_optional_ptr_access if *this is disengaged - */ - [[nodiscard]] constexpr strong_ptr& value() { - if (!is_engaged()) { - throw std::bad_optional_access(); - } - return m_value; - } - - /** - * @brief Access the contained value, throw if not engaged (const - * version) - * - * @return A copy of the contained strong_ptr - * @throws hal::bad_optional_ptr_access if *this is disengaged - */ - [[nodiscard]] constexpr strong_ptr const& value() const { - if (!is_engaged()) { - throw std::bad_optional_access(); - } - return m_value; - } - - /** - * @brief Implicitly convert to a strong_ptr - * - * This allows optional_ptr to be used anywhere a strong_ptr is expected - * when the optional_ptr is engaged. - * - * @return A copy of the contained strong_ptr - * @throws hal::bad_optional_ptr_access if *this is disengaged - */ - [[nodiscard]] constexpr operator strong_ptr() { return value(); } - - /** - * @brief Implicitly convert to a strong_ptr (const version) - * - * @return A copy of the contained strong_ptr - * @throws hal::bad_optional_ptr_access if *this is disengaged - */ - [[nodiscard]] constexpr operator strong_ptr() const { - return value(); - } - - /** - * @brief Implicitly convert to a strong_ptr for polymorphic types - * - * This allows optional_ptr to be converted to strong_ptr - * when Derived is convertible to Base. - * - * @tparam U The target type (must be convertible from T) - * @return A copy of the contained strong_ptr, converted to the target - * type - * @throws hal::bad_optional_ptr_access if *this is disengaged - */ - template - [[nodiscard]] constexpr operator strong_ptr() - requires(std::is_convertible_v && !std::is_same_v) - { - if (!is_engaged()) { - throw std::bad_optional_access(); - } - // strong_ptr handles the polymorphic conversion - return strong_ptr(m_value); - } - - /** - * @brief Implicitly convert to a strong_ptr for polymorphic types - * (const version) - * - * @tparam U The target type (must be convertible from T) - * @return A copy of the contained strong_ptr, converted to the target - * type - * @throws hal::bad_optional_ptr_access if *this is disengaged - */ - template - [[nodiscard]] constexpr operator strong_ptr() const - requires(std::is_convertible_v && !std::is_same_v) - { - if (!is_engaged()) { - // hal::safe_throw(hal::bad_optional_ptr_access(this)); - throw std::bad_optional_access(); - } - // strong_ptr handles the polymorphic conversion - return strong_ptr(m_value); - } - - /** - * @brief Arrow operator for accessing members of the contained object - * - * @return Pointer to the object managed by the contained strong_ptr - */ - [[nodiscard]] constexpr auto* operator->() { - auto& ref = *(this->value()); - return &ref; - } - - /** - * @brief Arrow operator for accessing members of the contained object - * (const version) - * - * @return Pointer to the object managed by the contained strong_ptr - */ - [[nodiscard]] constexpr auto* operator->() const { - auto& ref = *(this->value()); - return &ref; - } - - /** - * @brief Dereference operator for accessing the contained object - * - * @return Reference to the object managed by the contained strong_ptr - */ - [[nodiscard]] constexpr auto& operator*() { - auto& ref = *(this->value()); - return ref; - } - - /** - * @brief Dereference operator for accessing the contained object (const - * version) - * - * @return Reference to the object managed by the contained strong_ptr - */ - [[nodiscard]] constexpr auto& operator*() const { - auto& ref = *(this->value()); - return ref; - } - - /** - * @brief Reset the optional to a disengaged state - */ - constexpr void reset() noexcept { - if (is_engaged()) { - m_value.~strong_ptr(); - m_raw_ptrs[0] = nullptr; - m_raw_ptrs[1] = nullptr; - } - } - - /** - * @brief Emplace a new value - * - * Reset the optional and construct a new strong_ptr in-place. - * - * @tparam Args Types of arguments to forward to the constructor - * @param args Arguments to forward to the constructor - * @return Reference to the newly constructed strong_ptr - */ - template - constexpr strong_ptr& emplace(Args&&... args) { - reset(); - new (&m_value) strong_ptr(std::forward(args)...); - return m_value; - } - - /** - * @brief Swap the contents of this optional_ptr with another - * - * @param other The optional_ptr to swap with - */ - constexpr void swap(optional_ptr& other) noexcept { - if (is_engaged() && other.is_engaged()) { - std::swap(m_value, other.m_value); - } - else if (is_engaged() && !other.is_engaged()) { - new (&other.m_value) strong_ptr(std::move(m_value)); - reset(); - } - else if (!is_engaged() && other.is_engaged()) { - new (&m_value) strong_ptr(std::move(other.m_value)); - other.reset(); - } - } - - private: - /** - * @brief Use the strong_ptr's memory directly through a union - * - * This allows us to detect whether the optional_ptr is engaged - * by checking if the internal pointers are non-null. - */ - union { - std::array m_raw_ptrs = { nullptr, nullptr }; - strong_ptr m_value; - }; - - // Ensure the strong_ptr layout matches our expectations - static_assert(sizeof(m_value) == sizeof(m_raw_ptrs), - "strong_ptr must be exactly the size of two pointers"); - - /** - * @brief Helper to check if the optional is engaged - * - * @return true if the optional_ptr contains a value, false otherwise - */ - [[nodiscard]] constexpr bool is_engaged() const noexcept { - return m_raw_ptrs[0] != nullptr || m_raw_ptrs[1] != nullptr; - } - }; - - /** - * @brief Implement weak_ptr::lock() now that optional_ptr is defined - * - * This function attempts to obtain a strong_ptr from a weak_ptr. - * If the referenced object still exists, it returns an optional_ptr - * containing a strong_ptr to it. Otherwise, it returns an empty - * optional_ptr. - * - * @tparam T The type of the referenced object - * @return An optional_ptr that is either empty or contains a strong_ptr - */ - template - [[nodiscard]] inline optional_ptr weak_ptr::lock() const noexcept { - if (expired()) { - return nullptr; - } - - // Try to increment the strong count - auto current_count = - m_ctrl->strong_count.load(std::memory_order_relaxed); - while (current_count > 0) { - // TODO(kammce): Consider if this is dangerous - if (m_ctrl->strong_count.compare_exchange_weak( - current_count, - current_count + 1, - std::memory_order_acq_rel, - std::memory_order_relaxed)) { - // Successfully incremented - auto obj = strong_ptr(m_ctrl, m_ptr); - return obj; - } - } - - // Strong count is now 0 - return nullptr; - } - - /** - * @brief Non-member swap for strong_ptr - * - * @tparam T The type of the managed object - * @param p_lhs First strong_ptr to swap - * @param p_rhs Second strong_ptr to swap - */ - template - void swap(strong_ptr& p_lhs, strong_ptr& p_rhs) noexcept { - p_lhs.swap(p_rhs); - } - - /** - * @brief Non-member swap for weak_ptr - * - * @tparam T The type of the referenced object - * @param p_lhs First weak_ptr to swap - * @param p_rhs Second weak_ptr to swap - */ - template - void swap(weak_ptr& p_lhs, weak_ptr& p_rhs) noexcept { - p_lhs.swap(p_rhs); - } - - /** - * @brief Equality operator for strong_ptr - * - * Compares if two strong_ptr instances point to the same object. - * - * @tparam T The type of the first strong_ptr - * @tparam U The type of the second strong_ptr - * @param p_lhs First strong_ptr to compare - * @param p_rhs Second strong_ptr to compare - * @return true if both point to the same object, false otherwise - */ - template - bool operator==(strong_ptr const& p_lhs, - strong_ptr const& p_rhs) noexcept { - return p_lhs.operator->() == p_rhs.operator->(); - } - - /** - * @brief Inequality operator for strong_ptr - * - * Compares if two strong_ptr instances point to different objects. - * - * @tparam T The type of the first strong_ptr - * @tparam U The type of the second strong_ptr - * @param p_lhs First strong_ptr to compare - * @param p_rhs Second strong_ptr to compare - * @return true if they point to different objects, false otherwise - */ - template - bool operator!=(strong_ptr const& p_lhs, - strong_ptr const& p_rhs) noexcept { - return !(p_lhs == p_rhs); - } - /** - * @brief Equality operator for optional_ptr - * - * Compares if two optional_ptr instances are equal - they are equal if: - * 1. Both are disengaged (both empty) - * 2. Both are engaged and point to the same object - * - * @tparam T The type of the first optional_ptr - * @tparam U The type of the second optional_ptr - * @param p_lhs First optional_ptr to compare - * @param p_rhs Second optional_ptr to compare - * @return true if both are equal according to the rules above - */ - template - [[nodiscard]] bool operator==(optional_ptr const& p_lhs, - optional_ptr const& p_rhs) noexcept { - // If both are disengaged, they're equal - if (!p_lhs.has_value() && !p_rhs.has_value()) { - return true; - } - - // If one is engaged and the other isn't, they're not equal - if (p_lhs.has_value() != p_rhs.has_value()) { - return false; - } - - // Both are engaged, compare the underlying pointers - return p_lhs.value().operator->() == p_rhs.value().operator->(); - } - - /** - * @brief Inequality operator for optional_ptr - * - * Returns the opposite of the equality operator. - * - * @tparam T The type of the first optional_ptr - * @tparam U The type of the second optional_ptr - * @param p_lhs First optional_ptr to compare - * @param p_rhs Second optional_ptr to compare - * @return true if they are not equal - */ - template - [[nodiscard]] bool operator!=(optional_ptr const& p_lhs, - optional_ptr const& p_rhs) noexcept { - return !(p_lhs == p_rhs); - } - - /** - * @brief Equality operator between optional_ptr and nullptr - * - * An optional_ptr equals nullptr if it's disengaged. - * - * @tparam T The type of the optional_ptr - * @param p_lhs The optional_ptr to compare - * @return true if the optional_ptr is disengaged - */ - template - [[nodiscard]] bool operator==(optional_ptr const& p_lhs, - std::nullptr_t) noexcept { - return !p_lhs.has_value(); - } - - /** - * @brief Equality operator between nullptr and optional_ptr - * - * nullptr equals an optional_ptr if it's disengaged. - * - * @tparam T The type of the optional_ptr - * @param p_rhs The optional_ptr to compare - * @return true if the optional_ptr is disengaged - */ - template - [[nodiscard]] bool operator==(std::nullptr_t, - optional_ptr const& p_rhs) noexcept { - return !p_rhs.has_value(); - } - - /** - * @brief Inequality operator between optional_ptr and nullptr - * - * An optional_ptr does not equal nullptr if it's engaged. - * - * @tparam T The type of the optional_ptr - * @param p_lhs The optional_ptr to compare - * @return true if the optional_ptr is engaged - */ - template - [[nodiscard]] bool operator!=(optional_ptr const& p_lhs, - std::nullptr_t) noexcept { - return p_lhs.has_value(); - } - - /** - * @brief Inequality operator between nullptr and optional_ptr - * - * nullptr does not equal an optional_ptr if it's engaged. - * - * @tparam T The type of the optional_ptr - * @param p_rhs The optional_ptr to compare - * @return true if the optional_ptr is engaged - */ - template - [[nodiscard]] bool operator!=(std::nullptr_t, - optional_ptr const& p_rhs) noexcept { - return p_rhs.has_value(); - } - - /** - * @brief A construction token that can only be created by make_strong_ptr - * - * Make the first parameter of your class's constructor(s) in order to limit - * that constructor to only be used via `make_strong_ptr`. - */ - class strong_ptr_only_token { - private: - strong_ptr_only_token() = default; - - template - friend strong_ptr make_strong_ptr(std::pmr::polymorphic_allocator<>, - Args&&...); - }; - - /** - * @brief Factory function to create a strong_ptr with automatic - * construction detection - * - * This is the primary way to create a new strong_ptr. It automatically - * detects whether the target type requires token-based construction (for - * classes that should only be managed by strong_ptr) or supports normal - * construction. - * - * The function performs the following operations: - * 1. Allocates memory for both the object and its control block together - * 2. Detects at compile time if the type expects a strong_ptr_only_token - * 3. Constructs the object with appropriate parameters - * 4. Initializes enable_strong_from_this support if the type inherits from - * it - * 5. Returns a strong_ptr managing the newly created object - * - * **Token-based construction**: If a class constructor takes - * `strong_ptr_only_token` as its first parameter, this function - * automatically provides that token, ensuring the class can only be - * constructed via make_strong_ptr. - * - * **Normal construction**: For regular classes, construction proceeds - * normally with the provided arguments. - * - * **enable_strong_from_this support**: If the constructed type inherits - * from `enable_strong_from_this`, the weak reference is automatically - * initialized to enable `strong_from_this()` and `weak_from_this()` - * functionality. - * - * Example usage: - * - * ```cpp - * // Token-protected class (can only be created via make_strong_ptr) - * class protected_driver { - * public: - * protected_driver(strong_ptr_only_token, driver_config config); - * }; - * auto driver = make_strong_ptr(allocator, config{}); - * - * // Regular class - * class regular_class { - * public: - * regular_class(int value); - * }; - * auto obj = make_strong_ptr(allocator, 42); - * - * // Class with enable_strong_from_this support - * class self_aware : public enable_strong_from_this { - * public: - * self_aware(std::string name); - * void register_callback() { - * auto self = strong_from_this(); // This works automatically - * } - * }; - * auto obj = make_strong_ptr(allocator, "example"); - * ``` - * - * @tparam T The type of object to create - * @tparam Args Types of arguments to forward to the constructor - * @param p_alloc Allocator to use for memory allocation - * @param p_args Arguments to forward to the constructor - * @return A strong_ptr managing the newly created object - * @throws Any exception thrown by the object's constructor - * @throws std::bad_alloc if memory allocation fails - */ - template - [[nodiscard]] inline strong_ptr make_strong_ptr( - std::pmr::polymorphic_allocator<> p_alloc, - Args&&... p_args) { - using rc_t = detail::rc; - - rc_t* obj = nullptr; - - if constexpr (std:: - is_constructible_v) { - // Type expects token as first parameter - obj = p_alloc.new_object( - p_alloc, strong_ptr_only_token{}, std::forward(p_args)...); - } - else { - // Normal type, construct without token - obj = - p_alloc.new_object(p_alloc, std::forward(p_args)...); - } - - strong_ptr result(&obj->m_info, &obj->m_object); - - // Initialize enable_strong_from_this if the type inherits from it - if constexpr (std::is_base_of_v, T>) { - result->init_weak_this(result); - } - - return result; - } -} // namespace atlas::memory diff --git a/atlas/core/utilities/state.hpp b/atlas/core/utilities/state.hpp deleted file mode 100644 index 6183f6db..00000000 --- a/atlas/core/utilities/state.hpp +++ /dev/null @@ -1,224 +0,0 @@ -#pragma once -#include -#include - -namespace atlas { - - namespace detail { - /** - * @brief detail namespace is used for any internals that should not be - * accessed by the user - * - * @note When switching to C++'s modules, hopefully this removes the - * needs for having to represent namespaces in this way. - * - * Any invoke_* function is an internal detail that handles where those - * behaviorial state callbacks get handled into their respective state - * queue's - * - * Where the state queue will call those arbitrary callbacks at their - * respective point in each of the frame. - * - * As thesse are intended for invoking those queue's directly. - * - */ - void invoke_on_update(); - void invoke_defer_update(); - void invoke_physics_update(); - void invoke_ui_update(); - void invoke_start(); - - // TODO: Look into a different way of doing this - void poll_update(void* p_address, - const std::function& p_callback); - - void poll_defer_update(void* p_address, - const std::function& p_callback); - - void poll_physics_update(void* p_address, - const std::function& p_callback); - - void poll_ui_update(void* p_address, - const std::function& p_callback); - - void poll_start(void* p_address, - const std::function& p_callback); - - // TEMP: This is a temporary solution, should look into doing this - // differently - void remove_update(void* p_address); - - void remove_defer_update(void* p_address); - - void remove_physics_update(void* p_address); - - void remove_ui_update(void* p_address); - - void remove_start(void* p_address); - - }; - - /** - * @brief preloading any behavior that may be required of the users game - * objects, such as pre-loading assets or any metadata after construction of - * the objects. During engine's preloading stage. - * - * This is very useful for spawning or not initiating any pre-load logic - * that does not happen during the construction of your object itself - * - * Ideally I would like to expand this to allow for level transitioning of - * pointing to start registration for transitioning various preloading logic - * - * @tparam UObject is the specific object to point to the specified callback - * @tparam UCallback is the arbitrary type of the callback that contains the - * game logic itself - * @param p_instance is a pointer that points where the callback is coming - * from - * @param p_callable is the callback of arbitrary logic that then gets - * executed and is used alongside p_instance - * - * Example Usage: - * - * ```C++ - * atlas::register_start(this, &level_scene::preload); - * ``` - */ - template - void register_start(UObject* p_instance, const UCallback& p_callable) { - static_assert(std::is_member_pointer_v, - "Cannot register a function that is not a member " - "function of a class object"); - detail::poll_start(p_instance, [p_instance, p_callable]() { - (p_instance->*p_callable)(); - }); - } - - /** - * @brief Used for executing user-defined game logic during every framerate. - * - * This API allows you to register your game logic to be executed during - * every frame call. - * - * This is useful for any kind of game logic that is related to game inputs. - * - * @tparam UObject is the specific object to point to the specified callback - * @tparam UCallback is the arbitrary type of the callback that contains the - * game logic itself - * @param p_instance is a pointer that points where the callback is coming - * from - * @param p_callable is the callback of arbitrary logic that then gets - * executed and is used alongside p_instance - * - * Example Usage: - * - * ```C++ - * atlas::register_update(this, &level_scene::update_logic); - * ``` - */ - template - void register_update(UObject* p_instance, const UCallback& p_callable) { - static_assert(std::is_member_pointer_v, - "Cannot register a function that is not a member " - "function of a class object"); - detail::poll_update(p_instance, [p_instance, p_callable]() { - (p_instance->*p_callable)(); - }); - } - - /** - * @brief Primarily used for executing physics game logic during the physics - * fixed framerate - * - * This API rather allows for explicit control over where to execute your - * callback to the physics fixed framerate - * @tparam UObject is the specific object to point to the specified callback - * @tparam UCallback is the arbitrary type of the callback that contains the - * game logic itself - * @param p_instance is a pointer that points where the callback is coming - * from - * @param p_callable is the callback of arbitrary logic that then gets - * executed and is used alongside p_instance - * - * Example Usage: - * - * ```C++ - * atlas::register_physics(this, &level_scene::on_physics); - * ``` - */ - template - void register_physics(UObject* p_instance, const UCallback& p_callable) { - static_assert(std::is_member_pointer_v, - "Cannot register a function that is not a member " - "function of a class object"); - detail::poll_physics_update(p_instance, [p_instance, p_callable]() { - (p_instance->*p_callable)(); - }); - } - - /** - * @brief Intended to be used to specify game logic to be executed at the - * last possible moment in your game - * - * Intended to be used for game object logic that needs to be resolved at - * the last-moment in the frame. - * - * @tparam UObject is the specific object to point to the specified callback - * @tparam UCallback is the arbitrary type of the callback that contains the - * game logic itself - * @param p_instance is a pointer that points where the callback is coming - * from - * @param p_callable is the callback of arbitrary logic that then gets - * executed and is used alongside p_instance - * - * Example Usage: - * - * ```C++ - * atlas::register_deferred(this, &level_scene::late_update); - * ``` - * - */ - template - void register_deferred(UObject* p_instance, const UCallback& p_callable) { - static_assert(std::is_member_pointer_v, - "Cannot register a function that is not a member " - "function of a class object"); - detail::poll_defer_update(p_instance, [p_instance, p_callable]() { - (p_instance->*p_callable)(); - }); - } - - /** - * @brief This is just for registering UI logic for handling editorial UI - * logic such as widgets modification to entity transform components - * - * Intended for containing logic widgets may be used in. - * - * TODO: This might be redundant and may actually consider either removing - * this or simplify by just using register_deferred instead. - * - * @tparam UObject is the specific object to point to the specified callback - * @tparam UCallback is the arbitrary type of the callback that contains the - * game logic itself - * @param p_instance is a pointer that points where the callback is coming - * from - * @param p_callable is the callback of arbitrary logic that then gets - * executed and is used alongside p_instance - * - * Example Usage: - * - * ```C++ - * atlas::register_ui(this, &level_scene::late_update); - * ``` - * - */ - template - void register_ui(UObject* p_instance, const UCallback& p_callable) { - static_assert(std::is_member_pointer_v, - "Cannot register a function that is not a member " - "function of a class object"); - detail::poll_ui_update(p_instance, [p_instance, p_callable]() { - (p_instance->*p_callable)(); - }); - } - -}; \ No newline at end of file diff --git a/atlas/core/utilities/types.hpp b/atlas/core/utilities/types.hpp deleted file mode 100644 index a2fb6192..00000000 --- a/atlas/core/utilities/types.hpp +++ /dev/null @@ -1,15 +0,0 @@ -#pragma once -#include -#include - -namespace atlas { - /** - * @brief settings for specification for atlas::window - */ - struct window_settings { - uint32_t width = -1; - uint32_t height = -1; - std::string name = ""; - uint32_t frames_in_flight = 2; - }; -}; \ No newline at end of file diff --git a/atlas/core/window.hpp b/atlas/core/window.hpp deleted file mode 100644 index 0bc188b0..00000000 --- a/atlas/core/window.hpp +++ /dev/null @@ -1,119 +0,0 @@ -#pragma once -#include -#include -#include -#include -#include -#include - -namespace atlas { - - /** - * @brief Represent an entire window that lives throughout the entire - * duration of the application - * - * There should only be one window that is living throughout the - * applications lifetime - */ - class window { - public: - virtual ~window() = default; - - /** - * @brief Returns the width dimension of the window - */ - [[nodiscard]] uint32_t width() const; - - /** - * @brief Returns the height dimension of the window - */ - [[nodiscard]] uint32_t height() const; - - /** - * @brief Checks if window is available to close - */ - [[nodiscard]] bool available() const; - - /** - * @brief Returns the aspect ratio of the current window - */ - [[nodiscard]] float aspect_ratio() const; - - /** - * @brief gives you the next presentable image to use and the index to - * retrieving that image - * - * @return uint32_t - */ - [[nodiscard]] uint32_t acquired_next_frame() { - return read_acquired_next_frame(); - } - - /** - * @brief Returns the window's currently selected swapchain - */ - [[nodiscard]] vk::vk_swapchain current_swapchain() const { - return window_swapchain(); - } - - /** - * @brief retrieves the current command buffer using the current frame - * index to ensure we are processing commands to the right command - * buffer in our current frame - * - * @return command buffer to actively record commands to - */ - ::vk::command_buffer active_command(uint32_t p_frame_index) { - return current_active_command(p_frame_index); - } - - /** - * @brief operator overload for treating atlas::window as a GLFWwindow - * handle - */ - operator GLFWwindow*() const { return native_window(); } - - /** - * @brief operator overload for treating atlas::window as a GLFWwindow - * handle - */ - operator GLFWwindow*() { return native_window(); } - - /** - * @brief Closing the window operation - */ - void close(); - - /** - * @brief does the presentation operation that is operated internally - * with the vulkan swapchain - * - * @param p_current_frame_idx is current frame index to currently - * process an image in the current frame - */ - void present(const uint32_t& p_current_frame_idx); - - private: - [[nodiscard]] virtual window_settings settings() const = 0; - [[nodiscard]] virtual GLFWwindow* native_window() const = 0; - [[nodiscard]] virtual uint32_t read_acquired_next_frame() = 0; - [[nodiscard]] virtual vk::vk_swapchain window_swapchain() const = 0; - - [[nodiscard]] virtual ::vk::command_buffer current_active_command( - uint32_t p_frame_idx) = 0; - - virtual void presentation_process(const uint32_t& p_current_frame) = 0; - }; - - /** - * @brief constructs an atlas::window - * - * There should only ever be one window constructed throughout the entire - * application - * - * @param p_settings is the window settings to construct the window with - * - * @return shared_ptr - */ - ref create_window(const window_settings& p_settings); -}; diff --git a/atlas/drivers/graphics_context.hpp b/atlas/drivers/graphics_context.hpp deleted file mode 100644 index cb652d54..00000000 --- a/atlas/drivers/graphics_context.hpp +++ /dev/null @@ -1,28 +0,0 @@ -#pragma once -#include - -namespace atlas { - /** - * @brief graphics API-agnostic that is centralized to the graphics API - * themselves - */ - class graphics_context { - public: - virtual ~graphics_context() = default; - - /** - * @brief explicit cleanup of the graphics API context - */ - void destroy() { return destroy_context(); } - - private: - virtual void destroy_context() = 0; - }; - - /** - * @brief construct a new graphics context and initializes that API - * @return shared_ptr - */ - ref initialize_context(const std::string& p_tag); - -}; \ No newline at end of file diff --git a/atlas/drivers/jolt-cpp/jolt-imports.hpp b/atlas/drivers/jolt-cpp/jolt-imports.hpp deleted file mode 100644 index 0b8e097f..00000000 --- a/atlas/drivers/jolt-cpp/jolt-imports.hpp +++ /dev/null @@ -1,35 +0,0 @@ -#pragma once - -#include - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include - -#include -#include -#include -#include -#include -#include - -#include - -// jolt's math includes -#include -#include -#include \ No newline at end of file diff --git a/atlas/drivers/jolt-cpp/jolt_broad_phase.hpp b/atlas/drivers/jolt-cpp/jolt_broad_phase.hpp deleted file mode 100644 index 4d1e245e..00000000 --- a/atlas/drivers/jolt-cpp/jolt_broad_phase.hpp +++ /dev/null @@ -1,161 +0,0 @@ -#pragma once - -#include - -namespace atlas::physics { - - /** - * @brief This contains a few important comparisons having to do with - * setting up the oct-trees correctly as well as the filtering and collision - * interaction. - * - * @warning Most of these contain implicit conversions which might lead to - * unexpected behavior. This should probably be fixed or atleast checked - * eventually. - */ - - // This should eventually have a pipeline for the user to create masks. - enum class ObjectLayer : std::uint8_t { - NonMoving = 0, - Moving = 1, - NumLayers - }; - - enum class BroadPhaseLayers : std::uint8_t { - NonMoving = 0, - Moving = 1, - NumLayers - }; - - /** - * @brief This class is made to control the broadphase layer. Filters can be - * added to it to create a better and more organized broadphase. Ass well as - * giving some control to the user on how the broadphase should be - * organized. This requires dynamic masking however, which is not currently - * running. - * - */ - class broad_phase_layer_interface final - : public JPH::BroadPhaseLayerInterface { - public: - broad_phase_layer_interface() = default; - - /** - * @brief Get the Number of layers that exsist in the current context. - * Static for now. - * - * @return uint32_t - */ - [[nodiscard]] uint32_t GetNumBroadPhaseLayers() const override { - return (uint32_t)(BroadPhaseLayers::NumLayers); - } - - /** - * @brief Gives the caller access to the broadphase object. Allowing for - * some manipulation on how those interactions may go. Including but not - * limited to changing the filtering of the broadphase or reorganizing - * the oct-tree. - * - * @param p_in_layer The layer that the player wants. - * @return JPH::BroadPhaseLayer Object to organize and manipulate the - * oct-tree for that layer. - */ - [[nodiscard]] JPH::BroadPhaseLayer GetBroadPhaseLayer( - JPH::ObjectLayer p_in_layer) const override { - JPH_ASSERT(p_in_layer < (JPH::ObjectLayer)ObjectLayer::NumLayers); - return m_object_to_broadphase[p_in_layer]; - } - -#if defined(JPH_EXTERNAL_PROFILE) || defined(JPH_PROFILE_ENABLED) - /** - * @brief Only exsists for testing contexts or debug mode. Is made to - * return the names of the layers. Will be very helpful when the layers - * become dynamically created. - * - * @param p_in_layer The layer that the player wants as a name. - * @return const char* Name of the layer. - */ - [[nodiscard]] const char* GetBroadPhaseLayerName( - JPH::BroadPhaseLayer p_in_layer) const override { - switch (p_in_layer.GetValue()) { - case (JPH::BroadPhaseLayer::Type)(BroadPhaseLayers::NonMoving): - return "NonMoving"; - case (JPH::BroadPhaseLayer::Type)(BroadPhaseLayers::Moving): - return "Moving"; - default: - JPH_ASSERT(false); - return "Unknown"; - } - } -#endif - - private: - // The list of organizational layers - std::vector m_object_to_broadphase{ - JPH::BroadPhaseLayer((uint8_t)(BroadPhaseLayers::NonMoving)), - JPH::BroadPhaseLayer((uint8_t)(BroadPhaseLayers::Moving)) - - }; - }; - - /** - * @brief This is used to tell Jolt what can or cannot collide. As of right - * now the list is static therfore the layers do not need a dynamic set up. - * This will change when the object layers become user definable. - * - * @remark To give an example, there might exist something like this in the - * config of the editor: - * - * Dynamic Kenmatic Static - * Dynamic ✅ ✅ ✅ - * Kenmatic ✅ ✅ - * Static ✅ - * - * Where the interactions can partially be defined and controlled by the - * developer of the game. - */ - class object_vs_broadphase_layer final - : public JPH::ObjectVsBroadPhaseLayerFilter { - public: - [[nodiscard]] bool ShouldCollide( - JPH::ObjectLayer p_in_layer1, - JPH::BroadPhaseLayer p_in_layer2) const override { - switch (p_in_layer1) { - case (int)(ObjectLayer::NonMoving): - return p_in_layer2 == - JPH::BroadPhaseLayer((JPH::BroadPhaseLayer::Type)( - BroadPhaseLayers::Moving)); - case (int)ObjectLayer::Moving: - return true; - default: - JPH_ASSERT(false); - return false; - } - } - }; - - /** - * @brief This goes into more detailed ways of filtering, where the object - * collisions may be defined be what the other object is. In this case a - * static setup allows static object to trigger collision only when it is - * touched by a dynamic target. - * - */ - class object_layer_pair_filter final : public JPH::ObjectLayerPairFilter { - public: - [[nodiscard]] bool ShouldCollide( - JPH::ObjectLayer p_in_object1, - JPH::ObjectLayer p_in_object2) const override { - switch (p_in_object1) { - case (int)(ObjectLayer::NonMoving): - return p_in_object2 == (int)(ObjectLayer::Moving); - case (int)(ObjectLayer::Moving): - return true; - default: - JPH_ASSERT(false); - return false; - } - } - }; - -} diff --git a/atlas/drivers/jolt-cpp/jolt_components.hpp b/atlas/drivers/jolt-cpp/jolt_components.hpp deleted file mode 100644 index 51070d50..00000000 --- a/atlas/drivers/jolt-cpp/jolt_components.hpp +++ /dev/null @@ -1,82 +0,0 @@ -#pragma once - -#include -#include -#include -#include -#include -#include - -namespace atlas::physics { - enum thread_type : uint8_t { - default_system = 0, - job_system = 1, - }; - - /** - * @brief Used to keep global data for player access and use. - * Tells how physics bodies should act within a given scene by - * default. - */ - struct jolt_config { - // Global gravity vector for all in scene - glm::vec3 gravity = glm::vec3(0.0f, -9.80665f, 0.0f); - - //! @brief In seconds - float time_before_sleep = 5.0f; - - // What 1 unit refers to in meters - float world_unit_scale = 1.0f; - - // Helps stop the lauching of objects during numerical/flaoting point - // errors when collision happen bertween to objects. - float contact_bias_factor = 0.2f; - float restitution_threshold = 1.0f; - - bool enable_constraints = true; - bool enable_collision_callbacks = true; - }; - - /** - * @brief Jolt-specific context configurations - * These are going to be internally integrated to jolt_context - * - * As these parameters currently are going to be specific to Jolt. - * - * These parameters are also only specific to the construction-level, not - * initiation level of the API's - * - * @remark Min and max world bounds are values that are artbitrary (in other - * words limit the simulation space) as JoltPhysics has a limit on distance - * for its limitation in simulation space - */ - struct jolt_settings { - - uint32_t allocation_amount = 10 * 1024 * 1024; - - //! @brief Specifying which threading system to use for Jolt. - thread_type thread_type = thread_type::default_system; - - uint32_t physics_threads = - std::max(1u, std::thread::hardware_concurrency() - 2); - - uint32_t max_jobs_power = 10; - uint32_t max_barriers = physics_threads * 16; - bool enable_multithread = true; - - // Max memory size per scene - uint32_t max_bodies = 16384; - uint32_t max_body_pairs = 32768; - uint32_t max_contact_constraints = 8192; - }; - - // This might be able to be generalized eventually but we will have to - // create our own manifold before that happens. - struct contact_event { - uint64_t entity_a = 0; - uint64_t entity_b = 0; - JPH::ContactManifold manifold; - JPH::ContactSettings settings; - }; - -}; \ No newline at end of file diff --git a/atlas/drivers/jolt-cpp/jolt_contact_listener.hpp b/atlas/drivers/jolt-cpp/jolt_contact_listener.hpp deleted file mode 100644 index 2c9b5362..00000000 --- a/atlas/drivers/jolt-cpp/jolt_contact_listener.hpp +++ /dev/null @@ -1,84 +0,0 @@ -#pragma once - -#include -#include -#include -#include -#include - -namespace atlas::physics { - /** - * @brief implementation of Jolt's contact listener for collisions - * - * contact_listener gets set to Jolt's Physics System to allow for - * collisions to happen - */ - class contact_listener : public JPH::ContactListener { - public: - contact_listener(event::event_bus& p_bus); - - private: - /** - * @brief This allows us to make sure that the contacts are valid and - * not something that went wrong. It plays the role of both sanity check - * and saftey gaurd since if collisions were to be wrong you would not - * want that to crash the whole game. - * - * @param in_body1 is ID of the object1 who collided - * @param in_body2 is ID of object2 who object1 collided with - * @param in_base_offset for telling how far apart the center of the - * objects are - * @param in_collision_result The details about the collision - * @return JPH::ValidateResult - */ - JPH::ValidateResult OnContactValidate( - const JPH::Body& in_body1, - const JPH::Body& in_body2, - JPH::RVec3Arg in_base_offset, - const JPH::CollideShapeResult& in_collision_result) override; - - /** - * @brief This gets triggered each time a collision comes into contact. - * It is only called once and then removed. - * - * @param body1 Body that called - * @param body2 Target body - * @param manifold This class has a lot of stuff including heights, - * directions, offset etc... - * @param settings This has some of the body settings these objects - * have. - */ - void OnContactAdded(const JPH::Body& body1, - const JPH::Body& body2, - const JPH::ContactManifold& manifold, - JPH::ContactSettings& settings) override; - - /** - * @brief This gets called multiple times. It is not in use yet. - * - * @param in_body1 Body that called - * @param in_body2 Target body - * @param in_manifold This class has a lot of stuff including heights, - * directions, offset etc... - * @param io_settings This specifically descibes the settings that - * contacts should have. - * FIXME: Still needs to be implemented - */ - void OnContactPersisted(const JPH::Body& in_body1, - const JPH::Body& in_body2, - const JPH::ContactManifold& in_manifold, - JPH::ContactSettings& io_settings) override; - /** - * @brief This is used to clean to shapes and call exiting functions for - * contact. - * - * @param in_sub_shape_pair The pair of shapes that no longer touch. - * FIXME: Still needs to be implemented - */ - void OnContactRemoved( - const JPH::SubShapeIDPair& in_sub_shape_pair) override; - - private: - event::event_bus* m_bus; - }; -}; \ No newline at end of file diff --git a/atlas/drivers/jolt-cpp/jolt_context.hpp b/atlas/drivers/jolt-cpp/jolt_context.hpp deleted file mode 100644 index 02972348..00000000 --- a/atlas/drivers/jolt-cpp/jolt_context.hpp +++ /dev/null @@ -1,136 +0,0 @@ -#pragma once -#include -#include -#include -#include -#include -#include -#include - -namespace atlas::physics { - /** - * @brief jolt_context is the backend implementation of physics context - * - * This is the jolt specific implementation of the physics context - * - * Represents the external abstraction that is defined through the the - * engine-specific parameters. - */ - class jolt_context : public physics_context { - public: - /** - * @brief construct a new physics context with jolt implemented as its - * backend - * - * @param p_settings are the configuration parameters for initiating - * JoltPhysics - * @param p_bus is the event::bus that allows for publishing physics - * events to the subscribers of those said events - */ - jolt_context(const jolt_settings& p_settings, event::event_bus& p_bus); - ~jolt_context() override = default; - - private: - /** - * @brief Performs any specific cleanup needed by Jolt - */ - void destroy_bodies() override; - - void prepare_and_finalize() override; - - void update_simulation(float p_delta_time) override; - - protected: - void emplace_box_collider(uint32_t p_entity_id, - const transform* p_transform, - const physics_body* p_body, - const box_collider* p_collider) override; - - void emplace_sphere_collider( - uint32_t p_entity_id, - const transform* p_transform, - const physics_body* p_body, - const sphere_collider* p_collider) override; - - void emplace_capsule_collider( - uint32_t p_entity_id, - const transform* p_transform, - const physics_body* p_body, - const capsule_collider* p_collider) override; - - // void set_position_rotation(flecs::entity p_entity, const - // physics_body* p_body, const box_collider* p_collider, const - // transform* p_transform) override; - transform context_read_transform(uint32_t p_id) override; - - physics_body context_read_physics_body(uint32_t p_id) override; - - void linear_velocity(uint64_t p_id, - const glm::vec3& p_linear_velocity) override; - - void angular_velocity(uint64_t p_id, - const glm::vec3& p_angular_velocity) override; - - void force(uint64_t p_id, const glm::vec3& p_cumulative_force) override; - - void add_force_and_torque(uint64_t p_id, - const glm::vec3& p_force, - const glm::vec3& p_torque) override; - - void add_impulse(uint64_t p_id, const glm::vec3& p_impulse) override; - - private: - //! @note Must be defined before physics can be initialized otherwise - //! jolt cannot be created properly. - jolt_settings m_settings; - - /** - * @brief Creates a static allocation of all data - * - */ - ref m_temp_allocator; - - /** - * @brief Sets up a thread system, either jolts or custom based on - * thread settings in m_settings - * - */ - scope m_thread_system; - - /** - * @brief Creates filtering for the quad tree in terms of movement - * - */ - ref m_broad_phase_layer_interface; - - /** - * @brief Creates a filter for the quad tree in terms of objects types - * - */ - ref m_object_vs_broadphase_filter; - - /** - * @brief Creates a filter for pairs of collisions - * - */ - ref m_object_layer_pair_filter; - - /** - * @brief Creates a way to recognize collisions - * - */ - // ref m_contact_listener; - contact_listener m_contact_listener; - - /** - * @brief Gives access to the physics system. Is given to jolt_api as - * well. This is to allow us to give seperation of concerns. However, - * may change now do to Jolt conflict and unhandled dangling pointers - * within jolt_api. - * - */ - ref m_physics_system; - - std::map m_cached_body_ids; - }; -}; \ No newline at end of file diff --git a/atlas/drivers/jolt-cpp/types.hpp b/atlas/drivers/jolt-cpp/types.hpp deleted file mode 100644 index f1dabc7b..00000000 --- a/atlas/drivers/jolt-cpp/types.hpp +++ /dev/null @@ -1,47 +0,0 @@ -#pragma once -#include -#include -#include -#include -#include - -namespace atlas { - template<> - struct vector3 { - vector3() = default; - - vector3(const JPH::Vec3& p_other) { - m_value = { p_other.GetX(), p_other.GetY(), p_other.GetZ() }; - } - - operator glm::vec3() { return m_value; } - - glm::vec3 operator=(const JPH::Vec3& p_other) { - return { p_other.GetX(), p_other.GetY(), p_other.GetZ() }; - } - - bool operator==(const glm::vec3& p_other) { - return (m_value.x == p_other.x and m_value.y == p_other.y and - m_value.z == p_other.z); - } - - private: - glm::vec3 m_value; - }; - - namespace jolt { - JPH::RVec3 to_rvec3(const glm::vec3& p_value); - - JPH::Vec3 to_vec3(const glm::vec3& p_value); - - JPH::Quat to_quat(const glm::vec4& q); - - JPH::Quat to_quat(glm::quat& p_value); - }; - - glm::vec3 to_vec3(const JPH::Vec3& p_value); - - glm::quat to_quat(const JPH::Quat& p_value); - - glm::vec4 to_vec4(const JPH::Quat& p_value); -}; \ No newline at end of file diff --git a/atlas/drivers/renderer_context.hpp b/atlas/drivers/renderer_context.hpp deleted file mode 100644 index 56e75374..00000000 --- a/atlas/drivers/renderer_context.hpp +++ /dev/null @@ -1,92 +0,0 @@ -#pragma once -#include -#include -#include -#include - -namespace atlas { - /** - * @brief is an interface that defines a graphics APi-agnostic renderer - * - * This context allows for communication from the the internal engine logic - * to API-agnostic implementation of the renderers. - * - * This class is at the renderer-level of configurations. That relies on - * atlas::graphics_context for setting up the agnostic-graphics API's - * directly - */ - class render_context { - public: - virtual ~render_context() = default; - - /** - * @brief responsibility is to preload any data that is necessary to be - * loaded before being rendered - */ - void preload(const VkRenderPass& p_renderpass) { - return preload_assets(p_renderpass); - } - - /** - * @brief indicator of when the start of the frame is - * - * Semantically is used to indicate this is when we start recording - * operations to the GPU - * - * @param p_current is the current command buffer for recording - * @param p_settings is the current window settings that are currently - * applied - * @param p_renderpass is the main renderpass for doing the rendering - * operations - * @param p_framebuffer is the framebuffer handle required and passed to - * the renderpass - * @param p_proj_view is the (proj * view) camera matrices that is used - * by the game objects being rendered and passed as a shader uniform - */ - void begin_frame(const ::vk::command_buffer& p_current, - const window_settings& p_settings, - const VkRenderPass& p_renderpass, - const VkFramebuffer& p_framebuffer, - const glm::mat4& p_proj_view) { - return start_frame( - p_current, p_settings, p_renderpass, p_framebuffer, p_proj_view); - } - - /** - * @brief Intended to use to indicate when to end recording to the GPU - * in the current frame - */ - void end_frame() { return post_frame(); } - - /** - * @brief sets the background color and request that change to the - * graphics API - */ - void set_background_color(const std::array& p_color) { - return background_color(p_color); - } - - void current_scene_context(ref p_scene) { - return current_scene(std::move(p_scene)); - } - - private: - virtual void preload_assets(const VkRenderPass& p_renderpass) = 0; - - virtual void start_frame(const ::vk::command_buffer& p_current, - const window_settings& p_settings, - const VkRenderPass& p_renderpass, - const VkFramebuffer& p_framebuffer, - const glm::mat4& p_proj_view) = 0; - virtual void post_frame() = 0; - - virtual void background_color(const std::array& p_color) = 0; - - virtual void current_scene(ref) = 0; - }; - - ref initialize_renderer( - const window_settings& p_window_extent, - uint32_t p_image_size, - const std::string& p_tag); -}; diff --git a/atlas/drivers/vulkan-cpp/hash.hpp b/atlas/drivers/vulkan-cpp/hash.hpp deleted file mode 100644 index 678810d7..00000000 --- a/atlas/drivers/vulkan-cpp/hash.hpp +++ /dev/null @@ -1,38 +0,0 @@ -#pragma once -#include -#define GLM_ENABLE_EXPERIMENTAL -#include -#include - -namespace atlas { - template - void hash_combine(size_t& seed, const T& v, const Rest&... rest) { - seed ^= std::hash()(v) + 0x9e3779b9 + (seed << 6) + (seed << 2); - (hash_combine(seed, rest), ...); - } - -}; - -namespace std { - - // template<> - // struct hash { - // size_t operator()(const atlas::vk::vertex_input& vertex) const { - // size_t seed = 0; - // atlas::hash_combine( - // seed, vertex.position, vertex.color, vertex.normals, - // vertex.uv); - // return seed; - // } - // }; - template<> - struct hash<::vk::vertex_input> { - size_t operator()(const ::vk::vertex_input& vertex) const { - size_t seed = 0; - atlas::hash_combine( - seed, vertex.position, vertex.color, vertex.normals, vertex.uv); - return seed; - } - }; - -} \ No newline at end of file diff --git a/atlas/drivers/vulkan-cpp/mesh.hpp b/atlas/drivers/vulkan-cpp/mesh.hpp deleted file mode 100644 index b67b3ca9..00000000 --- a/atlas/drivers/vulkan-cpp/mesh.hpp +++ /dev/null @@ -1,79 +0,0 @@ -#pragma once -#define GLM_ENABLE_EXPERIMENTAL -#include -#include -#include -#include -#include -#include -#include -#include - -namespace atlas::vk { - - /** - * @brief mesh class specifically defined with vulkan implementations for - * specific primitives - * TODO: Whenever we load in a texture that will be laucnhed asyncronously - * - * @brief mesh class will contain metadata needed by vulkan specifications - * Ways to communicate through vulkan by only supplying information needed - * to update this mesh - * - * @brief Represents a renderable object -- supporting various material - * types, etc - * TODO - For now we have a map, this should - * be expanded to a proper material system for blending various materials - */ - class mesh { - public: - mesh() = default; - mesh(std::span<::vk::vertex_input> p_vertices, - std::span p_indices); - mesh(const std::filesystem::path& p_filename, bool p_flip = false); - - //! @brief Reload mesh vertices and indices when requested - void reload_mesh(const std::filesystem::path& p_path); - - void draw(const VkCommandBuffer& p_command_buffer); - - void destroy(); - - //! @brief Loading single texture with specified std::filesystem::path - void add_diffuse(const std::filesystem::path& p_path); - - void add_specular(const std::filesystem::path& p_path); - - [[nodiscard]] ::vk::sample_image diffuse() const { - return m_diffuse.image(); - } - [[nodiscard]] ::vk::sample_image specular() const { - return m_specular.image(); - } - - //! @return true if mesh geometry model loaded succesfully - [[nodiscard]] bool loaded() const { return m_model_loaded; } - - [[nodiscard]] bool diffuse_loaded() const { return m_diffuse.loaded(); } - [[nodiscard]] bool specular_loaded() const { - return m_specular.loaded(); - } - - void set_flip(bool p_flip) { m_flip = p_flip; } - - private: - void load_obj(const std::filesystem::path& p_filename); - - private: - vk_physical_driver m_physical; - VkDevice m_device = nullptr; - ::vk::texture m_diffuse; - ::vk::texture m_specular; - ::vk::vertex_buffer m_vbo{}; - ::vk::index_buffer m_ibo{}; - ::vk::uniform_buffer m_geoemtry_ubo; - ::vk::uniform_buffer m_material_ubo; - bool m_model_loaded = false; - bool m_flip = false; - }; -}; diff --git a/atlas/drivers/vulkan-cpp/shader_resource_group.hpp b/atlas/drivers/vulkan-cpp/shader_resource_group.hpp deleted file mode 100644 index 23cd101a..00000000 --- a/atlas/drivers/vulkan-cpp/shader_resource_group.hpp +++ /dev/null @@ -1,128 +0,0 @@ -#pragma once -#include -#include -#include -// #include - -namespace atlas::vk { - /** - * @brief resource group for loading shader sources that give you back - * VkShaderModule handles - * - * Responsibility is to load stages of shader sources whether that be - * through precompiler .spv files or through shaderc runtime shader - * compilation - * - * Responsibility is loading and streaming the amount of bytes from the - * compiled shader sources into the vulkan shader module handles - * - * resource groups up the creation and management of vulkan shader modules. - */ - class shader_resource_group { - public: - shader_resource_group() = default; - /** - * @brief constructs a new shader_resource_group - * - * @param p_device is the logical device required to creating the vulkan - * shader module - * @param p_info has the properties such as specified shader sources to - * load/compile - */ - shader_resource_group(const VkDevice& p_device, - const ::vk::shader_resource_info& p_info); - ~shader_resource_group() = default; - - /** - * @return true if resources are valid, otherwise return false - */ - [[nodiscard]] bool valid() const { return m_resource_valid; } - - /** - * @brief sets the vertex attributes with the shader modules that gets - * used by ::vk::pipeline (graphics pipeline) - * - * @param p_attributes is the high-level specifications for setting up - * vertex attributes that correspond with these shaders - */ - void vertex_attributes( - std::span p_attributes); - - /** - * @brief this gives you back the shader module handles along with each - * of their stages they have been compiled with - * - * Returns the vector to retain the shader modules that are needed by - * the graphics pipeline. - * - * It is required by vulkan specs the graphics pipeline to contain valid - * shader modules of the compiled shaders - * - * @return vector<::vk::shader_handle> - */ - [[nodiscard]] std::vector<::vk::shader_handle> handles() const { - return map_to_vector(); - } - - /** - * @return span - */ - [[nodiscard]] std::span - vertex_attributes() const { - return m_vertex_attributes; - } - - /** - * @return span - */ - [[nodiscard]] std::span - vertex_bind_attributes() const { - return m_vertex_binding_attributes; - } - - /** - * @brief explicit cleanup to the VkShaderModule handles created with - * this particular resource group - */ - void destroy(); - - /** - * @brief ideally used for requesting for reload - * - * Planning to use this for invalidation when for runtime shader - * hot-reloading - * - * @note this is not used at the moment as shader runtime hot reloading - * is currently not supported. - */ - [[nodiscard]] bool reload_requested() const { - return m_reload_requested; - } - - private: - /** - * converts unordered_map to - * vector - */ - [[nodiscard]] std::vector<::vk::shader_handle> map_to_vector() const; - - void create_module(std::span p_blob, - const ::vk::shader_source& p_source); - - void create_module(std::span p_blob, - const ::vk::shader_source& p_source); - - void reload_shader(const ::vk::shader_source& p_source); - - private: - VkDevice m_device = nullptr; - std::vector m_vertex_attributes; - std::vector - m_vertex_binding_attributes; - bool m_resource_valid = false; - // shader module handles - std::unordered_map m_modules; - // ref m_watcher; - bool m_reload_requested = false; - }; -}; \ No newline at end of file diff --git a/atlas/drivers/vulkan-cpp/shader_source_reader.hpp b/atlas/drivers/vulkan-cpp/shader_source_reader.hpp deleted file mode 100644 index cfc48efd..00000000 --- a/atlas/drivers/vulkan-cpp/shader_source_reader.hpp +++ /dev/null @@ -1,3 +0,0 @@ -#pragma once - -namespace atlas::vk {}; \ No newline at end of file diff --git a/atlas/drivers/vulkan-cpp/uniforms.hpp b/atlas/drivers/vulkan-cpp/uniforms.hpp deleted file mode 100644 index a9172551..00000000 --- a/atlas/drivers/vulkan-cpp/uniforms.hpp +++ /dev/null @@ -1,52 +0,0 @@ -#pragma once -#include - -namespace atlas::vk { - struct vertex_input { - glm::vec3 position; - glm::vec3 color; - glm::vec3 normals; - glm::vec2 uv; - - bool operator==(const vertex_input& other) const { - return position == other.position and color == other.color and - uv == other.uv and normals == other.normals; - } - }; - - //! @brief Going to remove this - //! @brief This is being used by descriptor sets and vk_renderer - //! TODO: Modify vk_descriptor_set and vk_renderer and add uniforms.hpp - //! inside renderer/ (dir) for used across vk_renderer and the renderer - struct camera_ubo { - glm::mat4 projection{ 1.f }; - glm::mat4 view{ 1.f }; - }; - - //! @brief Just for testing purposes for sending this struct over to the - //! shader - struct global_ubo { - glm::mat4 mvp = { 1.f }; - }; - - /** - * @brief material is going to define properties about how a scene object - * itself gets rendered - * - */ - struct geometry_uniform { - glm::mat4 model{ 1.f }; - glm::vec4 color{ 1.f }; - // std::vector texture_paths; - }; - - /** - * @brief Represents a vulkan specific mateiral to pass in two textures and - * offset for handling shininess - */ - struct material_uniform { - float shininess = 1.f; - ::vk::texture diffuse; - ::vk::texture specular; - }; -}; \ No newline at end of file diff --git a/atlas/drivers/vulkan-cpp/utilities.hpp b/atlas/drivers/vulkan-cpp/utilities.hpp deleted file mode 100644 index 2f537b39..00000000 --- a/atlas/drivers/vulkan-cpp/utilities.hpp +++ /dev/null @@ -1,19 +0,0 @@ -#pragma once -#include -#include -#include - -namespace atlas::vk { - - /** - * @param p_result checks if the result of a vulkan handler was created - * correctly - * @param p_name used for debugging of which handler failed - * @param p_source is the location of the call-site that invoked vk_check - */ - void vk_check( - const VkResult& p_result, - const std::string& p_name, - const std::source_location& p_source = std::source_location::current()); - -}; \ No newline at end of file diff --git a/atlas/drivers/vulkan-cpp/vk_context.hpp b/atlas/drivers/vulkan-cpp/vk_context.hpp deleted file mode 100644 index e93d7d0c..00000000 --- a/atlas/drivers/vulkan-cpp/vk_context.hpp +++ /dev/null @@ -1,77 +0,0 @@ -#pragma once -#include -#include -#include -#include - -namespace atlas::vk { - /** - * @brief vulkan-specific implementation that is the backend of the graphics - * contextd - */ - class vk_context : public graphics_context { - public: - vk_context(const std::string& p_tag); - - /** - * @brief used for providing a way to submit all vulkan metaobjects - * before the destruction of the vulkan logical device - * - * Per vulkan specification, it is required to have all object handles - * created with the logical device to be destroyed before the logical - * device itself gets destroyed during post cleanup - * - * This function was a means to ensure that the destruction of those - * vulkan child objects are handled in that order correctly - */ - static void submit_resource_free(std::function&& p_resource); - - /** - * @brief returns function pointer to allow for setting debug object - * name - * - * - * This allows for utilizing vkSetDebugUtilsObjectNameEXT during debug - * builds - * - * This allows for setting up object names that is useful to the - * programmer when a validation layer error message occurs unexpectedly - * - */ - static PFN_vkSetDebugUtilsObjectNameEXT get_debug_object_name() { - return s_instance->m_vk_set_debug_utils_object_name_ext; - } - - /** - * @brief Gives you direct access to the vulkan instance - */ - static VkInstance handler(); - - /** - * @brief direct access to the vulkan physical device - */ - static vk_physical_driver physical_driver() { - return s_instance->m_physical; - } - - /** - * @brief direct access to the vulkan logical device - */ - static vk_driver driver_context() { return s_instance->m_driver; } - - private: - void resource_free(std::function&& p_resource); - - private: - void destroy_context() override; - - private: - static vk_context* s_instance; - VkInstance m_instance_handler = nullptr; - vk_physical_driver m_physical{}; - vk_driver m_driver{}; - std::deque> m_resources_free{}; - - PFN_vkSetDebugUtilsObjectNameEXT m_vk_set_debug_utils_object_name_ext; - }; -}; \ No newline at end of file diff --git a/atlas/drivers/vulkan-cpp/vk_driver.hpp b/atlas/drivers/vulkan-cpp/vk_driver.hpp deleted file mode 100644 index 9ec69bb7..00000000 --- a/atlas/drivers/vulkan-cpp/vk_driver.hpp +++ /dev/null @@ -1,83 +0,0 @@ -#pragma once -#include -#include - -namespace atlas::vk { - - /** - * @brief logical device implementation wrapper around the VkDevice - * - * This class was a wrapper around VKDevice, that provided you with other - * API's to do with that particular logical device. - * - * Logical devices are representation of virtual software ways to interact - * with the GPU through Vulkan specifications - * - * TODO: Out-of-date. Using vulkan-cpp ::vk::device class to provide API's - * that allow you to do more queries on specific attributes the logical - * device gives you. - */ - class vk_driver { - struct device_queue_family { - VkQueue graphics_queue; - VkQueue transfer_queue; - VkQueue compute_queue; - }; - - public: - vk_driver() = default; - - /** - * @brief construct a new logical device - * @param p_physical is the physical device required for the creation of - * the logical device - */ - vk_driver(const vk_physical_driver& p_physical); - ~vk_driver() = default; - - /** - * @brief returns the specified graphics queue from this logical device - */ - [[nodiscard]] VkQueue graphics_queue() const { - return m_device_queues.graphics_queue; - } - - /** - * @return -1 if there are no flags available/compatible/valid - */ - uint32_t select_memory_type(uint32_t p_type_filter, - VkMemoryPropertyFlags p_property_flag); - - void destroy(); - - /** - * @brief gives you the depth format from the logical device - * - * @return VkFormat - */ - [[nodiscard]] VkFormat depth_format() const; - - /** - * @brief allows to treat vk_driver as a VkDevice handle - * - * For vulkan API's that accept only taking in VKDevice, this simplifies - * the need to not have a getter API - */ - operator VkDevice() const { return m_driver; } - - /** - * @brief allows to treat vk_driver as a VkDevice handle - * - * For vulkan API's that accept only taking in VKDevice, this simplifies - * the need to not have a getter API - */ - operator VkDevice() { return m_driver; } - - private: - vk_physical_driver m_physical{}; - VkDevice m_driver = nullptr; - device_queue_family m_device_queues{}; - VkFormat m_depth_format_selected; - }; - -}; \ No newline at end of file diff --git a/atlas/drivers/vulkan-cpp/vk_imgui.hpp b/atlas/drivers/vulkan-cpp/vk_imgui.hpp deleted file mode 100644 index d1baa163..00000000 --- a/atlas/drivers/vulkan-cpp/vk_imgui.hpp +++ /dev/null @@ -1,89 +0,0 @@ -#pragma once -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -namespace atlas::vk { - struct hud_data { - float playerHealth = 100.0f; - int playerScore = 0; - float fps = 0.0f; - std::string currentWeapon = "Assault Rifle"; - // Add more data as needed - }; - - class imgui_context { - public: - imgui_context() = default; - imgui_context(const ref& p_window_ctx); - - void create(GLFWwindow* p_window_handler, - const uint32_t& p_image_size, - const VkRenderPass& p_current_renderpass); - - void begin(const VkCommandBuffer& p_current, - const uint32_t& p_current_frame_idx); - - void end(); - - // HUD Example, using this to test if imgui initialization works - // note: experiemental, for testing imgui with new vulkan implementation - // Proper API I want to have this be in atlas::ui::hud namespace - // API Usage: ui::hud::health_bar(float) - // If users have custom components they want to register to the UI, then - // do: - /* - template - void custom_hud_component(UComponent* p_component,, UType p_type) { - // then prob do something lik this: use template to associate - struct component and the data, with type specified - imgui::progress_bar((p_component)->*p_data); - } - - User-side would be the following: - struct custom_component_heatlh { - uint32_t health_data = 10; - }; - some_entity->set({}); - const custom_component_health* player_hp = - some_entity.get(); - - // Through this specifications the UI will now apply this to the hud - // Questions that needs to be talked here are the following points: - 1.) How will users specify UI component uses? - * Position of HUD - * Handling alignment of the HUD - 2.) Ease of usability with minimal specifications on user-side for - getting HUD's to work 3.) Making a class be optional, meaning have - this be through imgui's API's as a function 4.) Asking if its needed - to be represented as a class atlas::ui::hud::health_bar(player_hp, - &custom_component_health::health_data) - */ - void draw_hud(const hud_data& p_test, - const window_settings& p_settings); - - [[nodiscard]] ::vk::command_buffer imgui_active_command() const { - return m_viewport_command_buffers[m_current_frame_index]; - } - void destroy(); - - private: - VkInstance m_instance = nullptr; - VkPhysicalDevice m_physical = nullptr; - vk_driver m_driver{}; - uint32_t m_current_frame_index = 0; - VkSwapchainKHR m_current_swapchain_handler = nullptr; - VkDescriptorPool m_desc_pool = nullptr; - VkCommandBuffer m_current = nullptr; - std::vector<::vk::command_buffer> m_viewport_command_buffers; - }; -}; \ No newline at end of file diff --git a/atlas/drivers/vulkan-cpp/vk_physical_driver.hpp b/atlas/drivers/vulkan-cpp/vk_physical_driver.hpp deleted file mode 100644 index 1548d99a..00000000 --- a/atlas/drivers/vulkan-cpp/vk_physical_driver.hpp +++ /dev/null @@ -1,97 +0,0 @@ -#pragma once -#include -#include - -namespace atlas::vk { - - struct surface_properties { - VkSurfaceCapabilitiesKHR surface_capabilities; - VkSurfaceFormatKHR surface_format; - }; - - /** - * @brief vulkan-specific implementation wrapper around VkPhysicalDevice - * - * Wrapper that constructs a single physical device that provides API's that - * can be used to query specific information for your specific physical - * device - * - * A physical device represents your current hardware GPU and allows for the - * ability to enumerate information to check for compatibility on the - * current GPU - */ - class vk_physical_driver { - struct queue_family_indices { - uint32_t graphics = -1; - uint32_t compute = -1; - uint32_t transfer = -1; - }; - - public: - vk_physical_driver() = default; - - /** - * @brief constructs a new vulkan physical device - * - * @param p_instance requires a VkInstance to create a VkPhysicalDevice - * handle - */ - vk_physical_driver(const VkInstance& p_instance); - - ~vk_physical_driver(); - - /** - * @brief gives you the queue families that are supported - * - * @return queue_family_indices are the indices of the specific queue's - * that are compatible on current hardware specifications - */ - [[nodiscard]] queue_family_indices read_queue_family_indices() const { - return m_queue_indices; - } - - [[nodiscard]] VkPhysicalDeviceMemoryProperties memory_properties() - const; - - /** - * @return uint32_t is the index to the presentation index of the - * specific presentation queue - */ - [[nodiscard]] uint32_t read_presentation_index( - const VkSurfaceKHR& p_surface); - - /** - * @brief querying surface properties based on the currently specified - * VkSurfaceKHR handle created - */ - [[nodiscard]] surface_properties get_surface_properties( - const VkSurfaceKHR& p_surface); - - /** - * @brief Allows for treating vk_physical_device as a VkPhysicalDevice - * handle - * - * Simplifies using this same class for creating other vulkan - * metaobjects - */ - operator VkPhysicalDevice() { return m_physical_driver; } - - /** - * @brief Allows for treating vk_physical_device as a VkPhysicalDevice - * handle - * - * Simplifies using this same class for creating other vulkan - * metaobjects - */ - operator VkPhysicalDevice() const { return m_physical_driver; } - - private: - queue_family_indices select_queue_family_indices(); - - private: - VkPhysicalDevice m_physical_driver = nullptr; - queue_family_indices m_queue_indices{}; - std::vector m_queue_family_properties{}; - surface_properties m_surface_properties{}; - }; -}; \ No newline at end of file diff --git a/atlas/drivers/vulkan-cpp/vk_renderer.hpp b/atlas/drivers/vulkan-cpp/vk_renderer.hpp deleted file mode 100644 index cb59f8a9..00000000 --- a/atlas/drivers/vulkan-cpp/vk_renderer.hpp +++ /dev/null @@ -1,96 +0,0 @@ -#pragma once -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -namespace atlas::vk { - /** - * @brief Something to consider for mesh loading. - * - * How will meshes get loaded? - * - * There are a few ways for considering for the base approach, which are: - * TODO: These are things to think about how this may happen because I want - * to make this lightweight in the sense the data isnt continuously being - * modified. Taking a looking at minimizing the loading state of vulkan - * implementation-specific meshes - * * While also making the way how mesh components are being added the - * same as before - * - Something to avoid is the entities containing the geometry data itself - * but being able to reference to their respective geometry data that are - * getting submitted to the GPU - * - * * Batching ID's into hash table that contains the actual geometry data - * * Using ID to search up the mesh loaded and cached into the map, then - * reuse that geometry whenever the uniforms are changed - * * This way we aren't reloading in the same mesh multiple times, treating - * the hash table as a slot of the mesh contained within that scene - * * Potentially std::map> m_geometries - * * Idea is the std::string is the geometries within this scene, the - * data format is: > - */ - class vk_renderer : public render_context { - public: - vk_renderer(const window_settings& p_settings, - uint32_t p_image_size, - const std::string& p_tag); - - ~vk_renderer() override = default; - - private: - void preload_assets(const VkRenderPass& p_renderpass) override; - - void start_frame(const ::vk::command_buffer& p_current, - const window_settings& p_settings, - const VkRenderPass& p_renderpass, - const VkFramebuffer& p_framebuffer, - const glm::mat4& p_proj_view) override; - void background_color(const std::array& p_color) override; - - void post_frame() override; - - void current_scene(ref) override; - - private: - VkDevice m_device = nullptr; - vk_physical_driver m_physical; - glm::mat4 m_proj_view; - VkRenderPass m_final_renderpass = nullptr; - window_settings m_window_extent; - ::vk::command_buffer m_current_command_buffer{}; - VkClearColorValue m_color; - - uint32_t m_image_count = 0; - shader_resource_group m_shader_group; - ::vk::pipeline m_main_pipeline; - ::vk::descriptor_resource m_global_descriptors; - std::vector m_sets_layouts; - - std::map m_cached_meshes; - ::vk::uniform_buffer m_global_uniforms; - ::vk::uniform_buffer m_point_light_uniforms; - - // game object-specific meshes - std::map m_mesh_geometry_set; - // TODO: Make this into a material system, eventually - std::map m_mesh_material_set; - std::map> - m_mesh_descriptors; - uint32_t m_current_frame = 0; - glm::mat4 m_model = { 1.f }; - - ::vk::texture m_white_texture; - - ref m_current_scene; - }; -}; diff --git a/atlas/drivers/vulkan-cpp/vk_swapchain.hpp b/atlas/drivers/vulkan-cpp/vk_swapchain.hpp deleted file mode 100644 index 50f9ef0e..00000000 --- a/atlas/drivers/vulkan-cpp/vk_swapchain.hpp +++ /dev/null @@ -1,102 +0,0 @@ -#pragma once -#include -#include -#include -#include -#include -#include -#include -#include -#include - -namespace atlas::vk { - /** - * @name vk_swapchain - * @brief High-level abstraction of a vulkan swapchain - * @brief ref will return the vk_swapchain directly - * @brief ref returning vk_swapchain will need to be changed - */ - class vk_swapchain { - public: - vk_swapchain() = default; - - /** - * @brief Constructs a new vulkan swapchain with a window settings to - * apply to this swapchain - * @param p_surface passing in the surface handler for swapchain uses - */ - vk_swapchain(const VkSurfaceKHR& p_surface, - const window_settings& p_settings); - - //! @return uint32_t the next available image to present acquired - uint32_t read_acquired_image(); - - //! @return current active command buffer being processed - [[nodiscard]] ::vk::command_buffer active_command( - uint32_t p_frame_index) { - return m_swapchain_command_buffers[p_frame_index]; - } - - [[nodiscard]] VkFramebuffer active_framebuffer(uint32_t p_frame) const { - return m_swapchain_framebuffers[p_frame]; - } - - [[nodiscard]] VkRenderPass swapchain_renderpass() const { - return m_final_renderpass; - } - - [[nodiscard]] window_settings settings() const { - return m_window_settings; - } - - [[nodiscard]] uint32_t image_size() const { return m_image_size; } - - [[nodiscard]] surface_properties data() const { - return m_surface_properties; - } - - void destroy(); - - void submit(std::span p_command); - - [[nodiscard]] ::vk::sample_image active_image(uint32_t p_index) const { - return m_swapchain_images[p_index]; - } - - operator VkSwapchainKHR() const { return m_swapchain_handler; } - - operator VkSwapchainKHR() { return m_swapchain_handler; } - - void present(const uint32_t& p_current_frame); - - private: - void invalidate(); - void create(); - - uint32_t select_images_size(const VkSurfaceCapabilitiesKHR&); - - private: - vk_physical_driver m_physical{}; - vk_driver m_driver{}; - VkSurfaceKHR m_current_surface_handler = nullptr; - VkSwapchainKHR m_swapchain_handler = nullptr; - VkExtent2D m_swapchain_extent{}; - window_settings m_window_settings{}; - - uint32_t m_image_size = 0; - - VkSurfaceKHR m_current_surface = nullptr; - surface_properties m_surface_properties{}; - std::vector<::vk::command_buffer> m_swapchain_command_buffers{}; - std::vector<::vk::framebuffer> m_swapchain_framebuffers; - - //! @brief setting up images - std::vector<::vk::sample_image> m_swapchain_images; - std::vector<::vk::sample_image> m_swapchain_depth_images; - - ::vk::renderpass m_final_renderpass; - - ::vk::device_present_queue m_present_to_queue; - }; - -}; diff --git a/atlas/drivers/vulkan-cpp/vk_window.hpp b/atlas/drivers/vulkan-cpp/vk_window.hpp deleted file mode 100644 index 2138bdb3..00000000 --- a/atlas/drivers/vulkan-cpp/vk_window.hpp +++ /dev/null @@ -1,42 +0,0 @@ -#pragma once -#include -#include -#include - -namespace atlas::vk { - class vk_window : public window { - public: - vk_window(const window_settings& p_settings); - ~vk_window() override; - - private: - void center_window(); - - private: - [[nodiscard]] window_settings settings() const override; - - [[nodiscard]] vk_swapchain window_swapchain() const override { - return m_swapchain; - } - - [[nodiscard]] uint32_t read_acquired_next_frame() override; - - [[nodiscard]] GLFWwindow* native_window() const override; - - void presentation_process(const uint32_t& p_current_frame) override; - - [[nodiscard]] ::vk::command_buffer current_active_command( - uint32_t p_frame_idx) override { - return m_swapchain.active_command(p_frame_idx); - } - - private: - VkInstance m_instance_handler = nullptr; - GLFWwindow* m_window_handler = nullptr; - VkSurfaceKHR m_window_surface = nullptr; - window_settings m_settings{}; - - vk_swapchain m_swapchain{}; - static vk_window* s_instance; - }; -}; diff --git a/atlas/drivers/vulkan-cpp/vulkan-imports.hpp b/atlas/drivers/vulkan-cpp/vulkan-imports.hpp deleted file mode 100644 index 91d4652a..00000000 --- a/atlas/drivers/vulkan-cpp/vulkan-imports.hpp +++ /dev/null @@ -1,13 +0,0 @@ -#pragma once - -#define GLFW_INCLUDE_VULKAN -#if _WIN32 -#define VK_USE_PLATFORM_WIN32_KHR -#include -#define GLFW_EXPOSE_NATIVE_WIN32 -#include -#include -#else -#include -#include -#endif \ No newline at end of file diff --git a/atlas/physics/components.hpp b/atlas/physics/components.hpp deleted file mode 100644 index e1301629..00000000 --- a/atlas/physics/components.hpp +++ /dev/null @@ -1,72 +0,0 @@ -#pragma once -#include - -namespace atlas { - /** - * @brief static is represented as fixed - */ - enum body_type : uint8_t { - fixed = 0, - kinematic = 1, - dynamic = 2, - bodynum, - }; - - /** - * @param non_moving is used for static objects that saves for not using the - * collider component - * @param moving is used for dynamic, kinematic, and character objects that - * will be used - */ - enum body_layer : uint8_t { - non_moving = 0, - moving = 1, - layer_num, - }; - - enum activation : uint8_t { activate, deactivate }; - - /** - * @brief physics body data-driven representative - * - * TODO: Add parameters for force, impulse, and torque - */ - struct physics_body { - glm::vec3 linear_velocity = glm::vec3(0.0); - glm::vec3 angular_velocity = glm::vec3(0.0f); - - glm::vec3 force = glm::vec3(0.0f); - glm::vec3 impulse = glm::vec3(0.0f); - glm::vec3 torque = glm::vec3(0.0f); - - float mass_factor = 1.0f; - glm::vec3 center_mass_position = glm::vec3(0.0f); - float linear_damping = 0.0f; - float angular_damping = 0.0f; - - float gravity_factor = 1.0f; - float friction = 0.8f; - float restitution = 0.2f; - - //! @brief body_type::fixed means this physics body is static - uint8_t body_movement_type = body_type::fixed; - - //! @brief body_layer (object layers) refer to the rules of the - //! collision system specified in JoltPhysics - uint8_t body_layer_type = body_layer::moving; - }; - - struct box_collider { - glm::vec3 half_extent = glm::vec3(0.5f); - }; - - struct capsule_collider { - float radius = 0.5f; - float half_height = 0.5f; - }; - - struct sphere_collider { - float radius = 0.5f; - }; - -}; \ No newline at end of file diff --git a/atlas/physics/math_types.hpp b/atlas/physics/math_types.hpp deleted file mode 100644 index 2098a0f9..00000000 --- a/atlas/physics/math_types.hpp +++ /dev/null @@ -1,191 +0,0 @@ -#pragma once - -#include -#include - -/** - * @brief Types are still be filled out. When this is completed to_jph() can be - * removed. - * - */ - -namespace atlas::physics { - - template - struct vector3; - - template<> - struct vector3 { - vector3() = default; - - vector3(const JPH::Vec3& v) { - m_value = { v.GetX(), v.GetY(), v.GetZ() }; - } - - operator glm::vec3() const { return m_value; } - - glm::vec3 operator=(const JPH::Vec3& v) { - m_value = { v.GetX(), v.GetY(), v.GetZ() }; - return m_value; - } - - bool operator==(const glm::vec3& other) const { - return m_value == other; - } - - private: - glm::vec3 m_value; - }; - - template<> - struct vector3 { - vector3() = default; - - vector3(const JPH::Float3& v) { m_value = { v.x, v.y, v.z }; } - - operator glm::vec3() const { return m_value; } - - glm::vec3 operator=(const JPH::Float3& v) { - m_value = { v.x, v.y, v.z }; - return m_value; - } - - bool operator==(const glm::vec3& other) const { - return m_value == other; - } - - private: - glm::vec3 m_value; - }; - - template<> - struct vector3 { - vector3() = default; - - vector3(const JPH::DVec3& v) { - m_value = { v.GetX(), v.GetY(), v.GetZ() }; - } - - operator glm::dvec3() const { return m_value; } - - glm::dvec3 operator=(const JPH::DVec3& v) { - m_value = { v.GetX(), v.GetY(), v.GetZ() }; - return m_value; - } - - bool operator==(const glm::dvec3& other) const { - return m_value == other; - } - - private: - glm::dvec3 m_value; - }; - - template<> - struct vector3 { - vector3() = default; - - vector3(const JPH::Double3& v) { m_value = { v.x, v.y, v.z }; } - - operator glm::dvec3() const { return m_value; } - - glm::dvec3 operator=(const JPH::Double3& v) { - m_value = { v.x, v.y, v.z }; - return m_value; - } - - bool operator==(const glm::dvec3& other) const { - return m_value == other; - } - - private: - glm::dvec3 m_value; - }; - - // === VECTOR4 ADAPTER === - template - struct vector4; - - template<> - struct vector4 { - vector4() = default; - - vector4(const JPH::Vec4& v) { - m_value = { v.GetX(), v.GetY(), v.GetZ(), v.GetW() }; - } - - operator glm::vec4() const { return m_value; } - - glm::vec4 operator=(const JPH::Vec4& v) { - m_value = { v.GetX(), v.GetY(), v.GetZ(), v.GetW() }; - return m_value; - } - - bool operator==(const glm::vec4& other) const { - return m_value == other; - } - - private: - glm::vec4 m_value; - }; - - template<> - struct vector4 { - vector4() = default; - - vector4(const JPH::Float4& v) { m_value = { v.x, v.y, v.z, v.w }; } - - operator glm::vec4() const { return m_value; } - - glm::vec4 operator=(const JPH::Float4& v) { - m_value = { v.x, v.y, v.z, v.w }; - return m_value; - } - - bool operator==(const glm::vec4& other) const { - return m_value == other; - } - - private: - glm::vec4 m_value; - }; - - // === QUATERNION ADAPTER === - template - struct quaternion; - - // === MATRIX4 ADAPTER === - template - struct matrix4; - - template<> - struct matrix4 { - matrix4() = default; - - matrix4(const JPH::Mat44& m) { - for (int i = 0; i < 4; ++i) { - const auto col = m.GetColumn4(i); - m_value[i] = - glm::vec4(col.GetX(), col.GetY(), col.GetZ(), col.GetW()); - } - } - - operator glm::mat4() const { return m_value; } - - glm::mat4 operator=(const JPH::Mat44& m) { - for (int i = 0; i < 4; ++i) { - const auto col = m.GetColumn4(i); - m_value[i] = - glm::vec4(col.GetX(), col.GetY(), col.GetZ(), col.GetW()); - } - return m_value; - } - - bool operator==(const glm::mat4& other) const { - return m_value == other; - } - - private: - glm::mat4 m_value; - }; -}; diff --git a/atlas/physics/physics_context.hpp b/atlas/physics/physics_context.hpp deleted file mode 100644 index a1ffb6f6..00000000 --- a/atlas/physics/physics_context.hpp +++ /dev/null @@ -1,188 +0,0 @@ -#pragma once -#include -#include -#include -#include -#include -#include -#include -#include - -namespace atlas::physics { - /** - * @brief The context is the way to interact with specific backend context - * implementation such as JoltPhysics as our specific implementation-backend - * - * Provides API's to interact with the implemented physics context to run - * its simulation - * - */ - class physics_context { - public: - virtual ~physics_context() = default; - - //! @brief Performs cleanup when simulation stops - void destroy() { return destroy_bodies(); } - - //! @brief updates our simulation using delta time and works with a - //! fixed timestep - void update(float p_delta_time) { - return update_simulation(p_delta_time); - } - - /** - * @brief As soon all physics bodies/colliders are created - * - * prepare() will be called to finalize all creation and apply them to - * the physics system for simulation - */ - void prepare() { return prepare_and_finalize(); } - - /** - * @param p_entity_id is the entity ID to associate with adding the - * sphere collider - * @param p_transform provide the location of the entity when creating - * this entity - * @param p_physics_body provide the actual physics body representation - * @param p_collider provides the actual sphere collider - */ - void add_box_collider(uint32_t p_entity_id, - const transform* p_transform, - const physics_body* p_body, - const box_collider* p_collider) { - return emplace_box_collider( - p_entity_id, p_transform, p_body, p_collider); - } - - /** - * @param p_entity_id is the entity ID to associate with adding the - * sphere collider - * @param p_transform provide the location of the entity when creating - * this entity - * @param p_physics_body provide the actual physics body representation - * @param p_collider provides the actual sphere collider - */ - void add_sphere_collider(uint32_t p_entity_id, - const transform* p_transform, - const physics_body* p_body, - const sphere_collider* p_collider) { - return emplace_sphere_collider( - p_entity_id, p_transform, p_body, p_collider); - } - - /** - * @param p_entity_id is the entity ID to associate with adding the - * sphere collider - * @param p_transform provide the location of the entity when creating - * this entity - * @param p_physics_body provide the actual physics body representation - * @param p_collider provides the actual capsule collider - */ - void add_capsule_collider(uint32_t p_entity_id, - const transform* p_transform, - const physics_body* p_body, - const capsule_collider* p_collider) { - return emplace_capsule_collider( - p_entity_id, p_transform, p_body, p_collider); - } - - /** - * @param p_id is the entity ID that is required to specifiy which - * entity this transform in physics simulation to return to - * @return transform back to the entity after its modification - */ - transform read_transform(uint32_t p_id) { - return context_read_transform(p_id); - } - - /** - * @param p_id is the entity ID that is required to specifiy which - * entity this transform in physics simulation to return to - * @return physics body back to the entity after its modification - */ - physics_body read_physics_body(uint32_t p_id) { - return context_read_physics_body(p_id); - } - - void set_linear_velocity(uint64_t p_id, - const glm::vec3& p_linear_velocity) { - return linear_velocity(p_id, p_linear_velocity); - } - - void set_angular_velocity(uint64_t p_id, - const glm::vec3& p_angular_velocity) { - return angular_velocity(p_id, p_angular_velocity); - } - - void set_force(uint64_t p_id, const glm::vec3& p_force) { - return force(p_id, p_force); - } - - void set_force_and_torque(uint64_t p_id, - const glm::vec3& p_force, - const glm::vec3& p_torque) { - add_force_and_torque(p_id, p_force, p_torque); - } - - void set_impulse(uint64_t p_id, const glm::vec3& p_impulse) { - add_impulse(p_id, p_impulse); - } - - private: - virtual void destroy_bodies() = 0; - - /** - * @brief Any emplace_* specific function are specific collider - * implementation-specific to the backend (context) API's they are - * implemented with - * - * Since colliders have specific parameters that define them. It would - * simplify what parameter-access they have when adding these specific - * colliders to the physics system - */ - virtual void emplace_box_collider(uint32_t p_entity_id, - const transform* p_transform, - const physics_body* p_body, - const box_collider* p_collider) = 0; - - virtual void emplace_sphere_collider( - uint32_t p_entity_id, - const transform* p_transform, - const physics_body* p_body, - const sphere_collider* p_collider) = 0; - - virtual void emplace_capsule_collider( - uint32_t p_entity_id, - const transform* p_transform, - const physics_body* p_body, - const capsule_collider* p_collider) = 0; - - virtual transform context_read_transform(uint32_t p_id) = 0; - - virtual physics_body context_read_physics_body(uint32_t p_id) = 0; - - virtual void prepare_and_finalize() = 0; - - virtual void update_simulation(float p_delta_time) = 0; - - virtual void linear_velocity(uint64_t p_id, const glm::vec3&) = 0; - - virtual void angular_velocity(uint64_t p_id, const glm::vec3&) = 0; - - virtual void force(uint64_t p_id, - const glm::vec3& p_cumulative_force) = 0; - - virtual void add_force_and_torque(uint64_t p_id, - const glm::vec3& p_force, - const glm::vec3& p_torque) = 0; - - virtual void add_impulse(uint64_t p_id, const glm::vec3& p_impulse) = 0; - }; - - //! @brief initializes the physics backend. SHOULD have an API associated - //! with but for now, we assume we only have JoltPhysics as our only physics - //! backend - ref initialize_physics_context( - const jolt_settings& p_settings, - event::event_bus& p_bus); -}; \ No newline at end of file diff --git a/atlas/physics/physics_engine.hpp b/atlas/physics/physics_engine.hpp deleted file mode 100644 index 9a67da5e..00000000 --- a/atlas/physics/physics_engine.hpp +++ /dev/null @@ -1,56 +0,0 @@ -#pragma once -#include -#include -#include -#include - -namespace atlas::physics { - - /** - * @brief The manager class for all physics engines. Manages the physics - * contexts and the collision engines. - * - */ - class physics_engine { - public: - // Required by maps but should not be used in anyother circumstance. - physics_engine() = default; - physics_engine(const jolt_settings& p_settings, - flecs::world& p_registry, - event::event_bus& p_bus); - - /** - * @brief The runtime is specifically the way to start the physics, - * utilizing defined data from level_scene and eventually any scene to - * create a physics scene and manage physics step. - * - */ - void start(); - - /** - * @brief Runs a single frame of the simulation. Should at minimum be - * called 60 fps. If below, it must be called twice. - * - */ - void update(float p_delta_time); - - /** - * @brief Deletes all physics bodies and shapes. Preps itself for - * runtime to be called again. - * - */ - void stop(); - - private: - flecs::world* m_registry; - ref m_physics_context; - flecs::query m_physics_bodies; - flecs::query - m_query_box_collider; - flecs::query - m_query_sphere_collider; - flecs::query - m_query_capsule_collider; - event::event_bus* m_bus; - }; -}; \ No newline at end of file diff --git a/atlas/renderer/renderer.hpp b/atlas/renderer/renderer.hpp deleted file mode 100644 index aef247d5..00000000 --- a/atlas/renderer/renderer.hpp +++ /dev/null @@ -1,48 +0,0 @@ -#pragma once -#include -#include -#include -#include - -namespace atlas { - /** - * @name Renderer - * @brief Submits high-level tasks that may get executed based on - * specifications for workloads - * @brief Provides API's for direct immediate execution to the backend - * context - * @brief Direct API's for performing certain rendering optimizations - * implementations - */ - class renderer { - public: - renderer() = default; - renderer(const window_settings& p_window_extent, - uint32_t p_image_size, - const std::string& p_tag = "Renderer"); - - void preload(const VkRenderPass& p_renderpass); - - void current_scene(ref); - - /** - * @brief Indicates to the renderer is at the start of the next frame to - * prepare workloads before next frame is processeed - */ - void begin(const ::vk::command_buffer& p_current, - const window_settings& p_settings, - const VkRenderPass& p_renderpass, - const VkFramebuffer& p_framebuffer, - const glm::mat4& p_proj_view); - - /** - * @brief Indications when the renderer has reached the end of the frame - */ - void end(); - - void set_background_color(const std::array& p_color); - - private: - ref m_render_context = nullptr; - }; -}; diff --git a/atlas/renderer/uniforms.hpp b/atlas/renderer/uniforms.hpp deleted file mode 100644 index 087d54ec..00000000 --- a/atlas/renderer/uniforms.hpp +++ /dev/null @@ -1,25 +0,0 @@ -#pragma once -#include -#include - -namespace atlas { - - struct point_light_ubo { - glm::vec4 position; // this is provided by the transform - glm::vec4 color = { 1.f, 1.f, 1.f, 1.f }; - float attenuation = 1.f; - float constant = 1.f; - float linear = 1.f; - float quadratic = 1.f; - - glm::vec4 ambient = glm::vec4(1.f); - glm::vec4 diffuse = glm::vec4(1.f); - glm::vec4 specular = glm::vec4(1.f); - }; - - struct light_scene_ubo { - alignas(16) uint32_t num_lights; - // alignas(16) std::array light_sources; - alignas(16) point_light_ubo light_sources[10]; - }; -}; \ No newline at end of file diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt deleted file mode 100644 index 96322730..00000000 --- a/src/CMakeLists.txt +++ /dev/null @@ -1,75 +0,0 @@ -set(INCLUDE_DIR ../atlas) -set(SRC_DIR atlas) - -set(VULKAN_INCLUDE_DIR ${INCLUDE_DIR}/drivers/vulkan-cpp) -set(VULKAN_SRC_DIR ${SRC_DIR}/drivers/vulkan-cpp) - -set( - all_src - ${SRC_DIR}/core/application.cpp - ${SRC_DIR}/core/event/event.cpp - - # ${SRC_DIR}/core/image/stb_image.cpp - - ${SRC_DIR}/core/engine_logger.cpp - ${SRC_DIR}/core/window.cpp - ${SRC_DIR}/core/utilities/state.cpp - - ${SRC_DIR}/core/platforms/main.cpp - ${SRC_DIR}/core/platforms/win32.cpp - - # System-related stuff - ${SRC_DIR}/core/scene/scene.cpp - ${SRC_DIR}/core/scene/game_object.cpp - ${SRC_DIR}/core/system/registry.cpp - - # math sources - ${SRC_DIR}/core/math/utilities.cpp - - # Filesystem stuff - ${SRC_DIR}/core/filesystem/file_dialog.cpp - - # serializer stuff - ${SRC_DIR}/core/serialize/serializer.cpp - ${SRC_DIR}/core/serialize/types.cpp - - # physics stuff - ${SRC_DIR}/physics/physics_engine.cpp - ${SRC_DIR}/physics/physics_context.cpp - - # jolt - ${SRC_DIR}/drivers/jolt-cpp/types.cpp - ${SRC_DIR}/drivers/jolt-cpp/jolt_context.cpp - ${SRC_DIR}/drivers/jolt-cpp/jolt_contact_listener.cpp - - # Scene stuff - ${SRC_DIR}/core/scene/world.cpp - - # Renderer-stuff - ${SRC_DIR}/renderer/renderer.cpp - ${SRC_DIR}/drivers/render_context.cpp - ${SRC_DIR}/drivers/graphics_context.cpp - - ${SRC_DIR}/core/ui/widgets.cpp - - # editor-level stuff - ${SRC_DIR}/core/editor/dockspace.cpp - ${SRC_DIR}/core/editor/menu_item.cpp - - - # imgui stuff - ${VULKAN_SRC_DIR}/vk_imgui.cpp - - ## Vulkan Driver stuff - ${VULKAN_SRC_DIR}/vk_window.cpp - ${VULKAN_SRC_DIR}/utilities.cpp - ${VULKAN_SRC_DIR}/vk_context.cpp - ${VULKAN_SRC_DIR}/vk_physical_driver.cpp - ${VULKAN_SRC_DIR}/vk_driver.cpp - ${VULKAN_SRC_DIR}/vk_swapchain.cpp - ${VULKAN_SRC_DIR}/mesh.cpp - ${VULKAN_SRC_DIR}/shader_resource_group.cpp - ${VULKAN_SRC_DIR}/vk_renderer.cpp -) - -add_library(${PROJECT_NAME} ${all_headers} ${all_src}) diff --git a/src/atlas/core/application.cpp b/src/atlas/core/application.cpp deleted file mode 100644 index c1304963..00000000 --- a/src/atlas/core/application.cpp +++ /dev/null @@ -1,256 +0,0 @@ -#include -#include -#include -#include -#include - -namespace atlas { - application* application::s_instance = nullptr; - - // For now we set this globally readable to other graphics-api agnostic - // API's Not able to be modified, rather only read. - static api g_graphics_backend_api = api::vulkan; - - application::application(const application_settings& p_settings) { - console_log_manager::set_current_logger(p_settings.name); - set_current_api(api::vulkan); - window_settings settings = { - .width = p_settings.width, - .height = p_settings.height, - .name = p_settings.name, - }; - m_window = create_window(settings); - - m_renderer = create_ref( - settings, m_window->current_swapchain().image_size(), "Renderer"); - m_renderer->set_background_color({ - p_settings.background_color.x, - p_settings.background_color.y, - p_settings.background_color.z, - p_settings.background_color.w, - }); - - // vulkan-specific imgui context that allows us to control our backend - // through vulkan - m_ui_context = vk::imgui_context(m_window); - - vk::vk_context::submit_resource_free( - [this]() { m_ui_context.destroy(); }); - s_instance = this; - } - - uint32_t application::current_frame() { - return s_instance->m_current_frame_index; - } - - application::~application() { - destroy(); - } - - void application::set_current_api(api api) { - g_graphics_backend_api = api; - } - - // NOTE: only good for immediate usage, - // this will not work for long-term storage due to the likelyhood - // of the handle being invalidated - VkSwapchainKHR application::get_current_swapchain() { - return m_window->current_swapchain(); - } - - api application::current_api() { - return g_graphics_backend_api; - } - - void application::destroy() { - s_instance->get_window().close(); - } - - float application::delta_time() { - return s_instance->m_delta_time; - } - - float application::physics_step() { - return 0.f; - } - - void application::execute() { - auto start_time = std::chrono::high_resolution_clock::now(); - - detail::invoke_start(); - - m_renderer->preload( - m_window->current_swapchain().swapchain_renderpass()); - - ref current_world = system_registry::get_world("Editor World"); - ref current_scene = current_world->get_scene("LevelScene"); - - flecs::world current_world_scope = *current_scene; - - /* - - flecs::system is how your able to schedule changes for given - portions of data in this case the projection/view matrices are only - being changed when flecs::world::progress(g_delta_time) is being - invoked within the mainloop - current_world_scope.system() - - - When users do object->add>(), this automatically gets invoked by the - .system<...> that gets invoked by the mainloop. - */ - current_world_scope - .system, - transform, - perspective_camera>() - .each([&](flecs::pair p_pair, - transform& p_transform, - perspective_camera& p_camera) { - float aspect_ratio = m_window->aspect_ratio(); - if (!p_camera.is_active) { - return; - } - - p_pair->projection = glm::mat4(1.f); - - p_pair->projection = - glm::perspective(glm::radians(p_camera.field_of_view), - aspect_ratio, - p_camera.plane.x, - p_camera.plane.y); - p_pair->projection[1][1] *= -1; - p_pair->view = glm::mat4(1.f); - - // This is converting a glm::highp_vec4 to a glm::quat - glm::quat quaternion = to_quat(p_transform.quaternion); - - p_pair->view = - glm::translate(p_pair->view, p_transform.position) * - glm::mat4_cast(quaternion); - - p_pair->view = glm::inverse(p_pair->view); - }); - - /* - - Currently how this works is we query with anything that has a - flecs::pair - - This tells the ecs flecs what to do query for in regards to - specific objects that are a camera - - in the tag:: namespace, this is to imply components that are empty - and just represent tags, to specify their uses. - */ - auto query_camera_objects = - current_scene - ->query_builder, - perspective_camera>() - .build(); - - while (m_window->available()) { - auto current_time = std::chrono::high_resolution_clock::now(); - m_delta_time = - std::chrono::duration( - current_time - start_time) - .count(); - start_time = current_time; - event::update_events(); - - // Progresses the flecs::world by one tick (or replaced with using - // the delta time) - // This also invokes the following system call before the - // mainloop - current_world_scope.progress(m_delta_time); - - m_current_frame_index = m_window->acquired_next_frame(); - - // Current commands that are going to be iterated through - // Prevents things like stalling so the CPU doesnt have to wait for - // the GPU to fully complete before starting on the next frame - // Command buffer uses this to track the frames to process its - // commands currently_active_frame = (m_current_frame_index + 1) % - // m_window->current_swapchain().settings().frames_in_flight; - // TODO: Going to need to figure out where to put this - // Added this here because to ensure the handlers being used by the - // renderer is in sync when swapchain is resized - ::vk::command_buffer currently_active = - m_window->active_command(m_current_frame_index); - - detail::invoke_physics_update(); - - detail::invoke_on_update(); - - detail::invoke_defer_update(); - - // We want this to be called after late update - // This queries all camera objects within the camera system - // Update -- going to be removing camera system in replacement of - // just simply using flecs::system to keep it simple for the time - query_camera_objects.each( - [&](flecs::entity, - flecs::pair p_pair, - perspective_camera& p_camera) { - if (!p_camera.is_active) { - return; - } - - m_proj_view = p_pair->projection * p_pair->view; - }); - - // TODO: Introduce scene renderer that will make use of the - // begin/end semantics for setting up tasks during pre-frame - // operations - // renderer begin to indicate when a start of the frame to start - // processing specific tasks that either need to be computed or - // pre-defined before the renderer does something with it. - // TODO: Add scene_manager to coordinate what to process - // before frame preparation - auto current_framebuffer = - m_window->current_swapchain().active_framebuffer( - m_current_frame_index); - m_renderer->begin( - currently_active, - m_window->current_swapchain().settings(), - m_window->current_swapchain().swapchain_renderpass(), - current_framebuffer, - m_proj_view); - - // TODO: vk:imgui_context will have its own renderpass, command - // buffers, and framebuffers specifically for UI-widgets + viewport - m_ui_context.begin(currently_active, m_current_frame_index); - - detail::invoke_ui_update(); - - m_ui_context.end(); - - m_renderer->end(); - - /* - TODO -- have m_window present this to the screen, eventually - m_renderer should just fetch the images in the order to offload - to the swapchain for rendering. - - Where each image has gone through different phases of the - renderpass onto the final image - */ - - std::array commands = { - currently_active, - }; - m_window->current_swapchain().submit(commands); - // Presents to the swapchain to display to screen - // m_renderer->present(m_current_frame_index); - m_window->present(m_current_frame_index); - } - } - - void application::post_destroy() { - m_window->close(); - } - - float application::aspect_ratio() { - return s_instance->m_window->aspect_ratio(); - } - - uint32_t application::image_size() { - return s_instance->m_window->current_swapchain().image_size(); - } -}; diff --git a/src/atlas/core/editor/dockspace.cpp b/src/atlas/core/editor/dockspace.cpp deleted file mode 100644 index 08aaa3a9..00000000 --- a/src/atlas/core/editor/dockspace.cpp +++ /dev/null @@ -1,42 +0,0 @@ -#include -#include - -namespace atlas::ui { - - void dockspace::begin() { - - ImGuiDockNodeFlags dockspace_flags = ImGuiDockNodeFlags_None; - ImGuiWindowFlags window_flags = - ImGuiWindowFlags_MenuBar | ImGuiWindowFlags_NoDocking; - - if (m_fullscreen_enabled) { - ImGuiViewport* viewport = ImGui::GetMainViewport(); - ImGui::SetNextWindowPos(viewport->Pos); - ImGui::SetNextWindowSize(viewport->Size); - ImGui::SetNextWindowViewport(viewport->ID); - window_flags |= ImGuiWindowFlags_NoTitleBar | - ImGuiWindowFlags_NoCollapse | - ImGuiWindowFlags_NoResize | ImGuiWindowFlags_NoMove; - window_flags |= ImGuiWindowFlags_NoBringToFrontOnFocus | - ImGuiWindowFlags_NoNavFocus; - } - - if (dockspace_flags & ImGuiDockNodeFlags_PassthruCentralNode) { - window_flags |= ImGuiWindowFlags_NoBackground; - } - ImGui::PushStyleVar(ImGuiStyleVar_WindowPadding, ImVec2(0.0f, 0.0f)); - ImGui::Begin("Dockspace Demo", &m_is_dockspace_open, window_flags); - ImGui::PopStyleVar(); - - // Dockspace - ImGuiIO& io = ImGui::GetIO(); - if (io.ConfigFlags & ImGuiConfigFlags_DockingEnable) { - ImGuiID dockspace_id = ImGui::GetID("MyDockspace"); - ImGui::DockSpace(dockspace_id, ImVec2(0.f, 0.f), dockspace_flags); - } - } - - void dockspace::end() { - ImGui::End(); - } -}; \ No newline at end of file diff --git a/src/atlas/core/editor/menu_item.cpp b/src/atlas/core/editor/menu_item.cpp deleted file mode 100644 index f1c65cfe..00000000 --- a/src/atlas/core/editor/menu_item.cpp +++ /dev/null @@ -1,23 +0,0 @@ -#include -#include - -namespace atlas::ui { - - void menu_item::begin() { - if (!ImGui::BeginMenuBar()) { - throw menu_bar_exception("ImGui::BeginMenuBar failed!"); - } - } - - void menu_item::end() { - ImGui::EndMenuBar(); - } - - void menu_item::add_child(const std::string& p_name, - const std::function& p_callback) { - if (ImGui::MenuItem(p_name.c_str())) { - p_callback(); - } - ImGui::Separator(); - } -}; \ No newline at end of file diff --git a/src/atlas/core/engine_logger.cpp b/src/atlas/core/engine_logger.cpp deleted file mode 100644 index 07a2c8e8..00000000 --- a/src/atlas/core/engine_logger.cpp +++ /dev/null @@ -1,59 +0,0 @@ -#include -#include -#include - -namespace atlas { - - std::string g_current_pattern_for_logs = "Undefined Pattern Specified"; - std::unordered_map> - console_log_manager::s_loggers; - - void console_log_manager::initialize_logger_manager( - const std::string& pattern) { - g_current_pattern_for_logs = pattern; - - //! @note Setting up logs for different log stdout's - //! @note Logs for p_tag is logs specific to the game. - s_loggers.insert({ "engine3d", spdlog::stdout_color_mt("engine3d") }); - s_loggers.insert({ "physics", spdlog::stdout_color_mt("physics") }); - s_loggers.insert({ "vulkan", spdlog::stdout_color_mt("vulkan") }); - s_loggers.insert( - { "assert", spdlog::stdout_color_mt("core assertion") }); - - s_loggers["engine3d"]->set_pattern(pattern); - s_loggers["engine3d"]->set_level(spdlog::level::trace); - - s_loggers["physics"]->set_level(spdlog::level::trace); - s_loggers["physics"]->set_pattern(pattern); - - s_loggers["vulkan"]->set_level(spdlog::level::trace); - s_loggers["vulkan"]->set_pattern(pattern); - - s_loggers["assert"]->set_level(spdlog::level::trace); - s_loggers["assert"]->set_pattern(pattern); - } - - void console_log_manager::create_new_logger( - [[maybe_unused]] const std::string& p_tag) { -#ifndef ENABLE_TESTS_ONLY - s_loggers[p_tag] = spdlog::stdout_color_mt(p_tag); - s_loggers[p_tag]->set_level(spdlog::level::trace); - s_loggers[p_tag]->set_pattern(g_current_pattern_for_logs); -#endif - } - - void console_log_manager::set_current_logger( - [[maybe_unused]] const std::string& p_tag) { -#ifndef ENABLE_TESTS_ONLY - //! @note Setting up logs for different log stdout's - //! @note Logs for p_tag is logs specific to the game - s_loggers[p_tag] = spdlog::stdout_color_mt(p_tag); - s_loggers[p_tag]->set_level(spdlog::level::trace); - s_loggers[p_tag]->set_pattern(g_current_pattern_for_logs); -#endif - } - - ref console_log_manager::get(const std::string& p_tag) { - return s_loggers[p_tag]; - } -}; \ No newline at end of file diff --git a/src/atlas/core/event/event.cpp b/src/atlas/core/event/event.cpp deleted file mode 100644 index 58a51f34..00000000 --- a/src/atlas/core/event/event.cpp +++ /dev/null @@ -1,163 +0,0 @@ -#include -#include -#include - -namespace atlas::event { - static std::map s_controllers; - - using button_id = int; - using controller_id = int; - - bool is_key_pressed(int p_key) { - GLFWwindow* window = application::get_window(); - - auto state = glfwGetKey(window, static_cast(p_key)); - return (state == GLFW_PRESS); - } - - bool is_key_released(int p_key) { - GLFWwindow* window = application::get_window(); - - auto state = glfwGetKey(window, static_cast(p_key)); - return (state == GLFW_RELEASE); - } - - bool is_mouse_pressed(int p_mouse_code) { - GLFWwindow* window = application::get_window(); - - auto state = - glfwGetMouseButton(window, static_cast(p_mouse_code)); - return (state == GLFW_PRESS); - } - - bool is_mouse_released(int p_mouse_code) { - GLFWwindow* window = application::get_window(); - - auto state = - glfwGetMouseButton(window, static_cast(p_mouse_code)); - return (state == GLFW_RELEASE); - } - - glm::vec2 cursor_position() { - GLFWwindow* window = application::get_window(); - - double x_pos, y_pos; - glfwGetCursorPos(window, &x_pos, &y_pos); - - return { x_pos, y_pos }; - } - - // joystic-specific functions - - bool is_joystic_present(int p_controller_id) { - return s_controllers.contains(p_controller_id); - } - - const char* is_joystick_guid(int p_controller_id) { - return glfwGetJoystickGUID(p_controller_id); - } - - float get_joystic_axis(int p_controller_id, int p_button) { - int count; - const float axes = - glfwGetJoystickAxes(p_controller_id, &count)[p_button]; - - if (count < p_button) { - return 0.0f; - } - else { - return axes; - } - } - - // bool is_button_released(button_id p_button, controller_id p_controller) { - // auto selected_controller = s_controllers[p_controller]; - // return (selected_controller.Buttons[p_button].ButtonState == - // input_state::Pressed); - // } - - // bool is_button_pressed(int p_button_id, int p_controller_id) { - // auto controller = s_controllers[p_controller_id]; - // return (controller.Buttons[p_button_id].ButtonState == GLFW_RELEASE); - // } - - bool is_joystick_button_pressed(int p_button) { - return p_button == GLFW_PRESS; - } - - bool is_joystick_button_released(int p_button) { - return p_button == GLFW_RELEASE; - } - - // specific for listening events - void update_events() { - glfwPollEvents(); - - // updating joysticks here - // .... - //! @note Must be called per input updated events. In the case either - //! game console disconnects or reconnects - //! @note This will continously check. - //! @note By default GLFW check's up to a total of 16 joystick ID's that - //! are available - //! @note We iterate all 16 joysticks, only using the joystic ID's that - //! are connected - //! @note Then checking for any events from the connected joystick has - //! occurred - // 1 is the first joystick. - // 16 is the last joystick - for (int joystick_id = 0; joystick_id < 16; joystick_id++) { - if (glfwJoystickPresent(joystick_id) == GLFW_TRUE) { - auto& joystick = s_controllers[joystick_id]; - joystick.ID = joystick_id; - joystick.JoystickName = glfwGetJoystickName(joystick_id); - - //! @note We always check how many buttons the joysticks that - //! are connected contain. - int amount_of_buttons = -1; - const unsigned char* buttons = - glfwGetJoystickButtons(joystick_id, &amount_of_buttons); - - // ConsoleLogWarn("Button Size = {}", amount_of_buttons); - - for (int i = 0; i < amount_of_buttons; i++) { - // ConsoleLogFatal("Button {} is ===> {}", i, buttons[i]); - // if(buttons[i] == GLFW_PRESS && !joystick.ButtonsDown[i]){ - if (is_joystick_button_pressed(buttons[i]) && - !joystick.ButtonsDown[i]) { - joystick.Buttons[i].ButtonState = input_state::Pressed; - } - // else if(buttons[i] == GLFW_RELEASE and - // joystick.ButtonsDown[i]){ - else if (is_joystick_button_released(buttons[i]) and - joystick.ButtonsDown[i]) { - joystick.Buttons[i].ButtonState = input_state::Released; - } - - // joystick.ButtonsDown[i] = (buttons[i] == GLFW_PRESS); - joystick.ButtonsDown[i] = - is_joystick_button_pressed(buttons[i]); - } - - int amount_of_axes = -1; - const float* axes = - glfwGetJoystickAxes(joystick_id, &amount_of_axes); - joystick.AxesOfController[joystick_id] = axes; - // ConsoleLogFatal("Axes at for-loop i = {} and Axes value = - // {:.3f}", 0, axes[0]); ConsoleLogFatal("Axes at for-loop i = - // {} and Axes value = {:.3f}", 1, axes[1]); for(int i = 0; i < - // amount_of_axes; i++){ - // ConsoleLogFatal("Axes at for-loop i = {} and Axes value = - // {:.3f}", i, axes[i]); - // } - } - else { - if (is_joystic_present(joystick_id)) { - s_controllers.erase(joystick_id); - } - } - } - } - - void wait_for_events() {} -}; \ No newline at end of file diff --git a/src/atlas/core/filesystem/file_dialog.cpp b/src/atlas/core/filesystem/file_dialog.cpp deleted file mode 100644 index a89d349f..00000000 --- a/src/atlas/core/filesystem/file_dialog.cpp +++ /dev/null @@ -1,37 +0,0 @@ -#include -#include -#include - -namespace atlas::filesystem { - std::string load_from_file_dialog( - const std::string& p_filter, - const std::filesystem::path& p_default_path) { - char* output_path = nullptr; - - nfdresult_t result = NFD_OpenDialog( - p_filter.c_str(), p_default_path.string().c_str(), &output_path); - - // if (result == NFD_OKAY) { - // return std::string(output_path); - // } - - // console_log_fatal("Error Loading File!"); - // return ""; - return (result == NFD_OKAY) ? std::string(output_path) : ""; - } - - std::string save_to_file(const std::string& p_filter, - const std::filesystem::path& p_default) { - char* output_path = nullptr; - nfdresult_t result = NFD_SaveDialog( - p_filter.c_str(), p_default.string().c_str(), &output_path); - - // if(result == NFD_ERROR){ - // return std::string(); - // } - - // return std::string(output_path); - - return (result == NFD_OKAY) ? std::string(output_path) : std::string(); - } -}; \ No newline at end of file diff --git a/src/atlas/core/image/stb_image.cpp b/src/atlas/core/image/stb_image.cpp deleted file mode 100644 index 37ea05db..00000000 --- a/src/atlas/core/image/stb_image.cpp +++ /dev/null @@ -1,4 +0,0 @@ -#ifndef STB_IMAGE_IMPLEMENTATION -#define STB_IMAGE_IMPLEMENTATION -#include -#endif \ No newline at end of file diff --git a/src/atlas/core/math/utilities.cpp b/src/atlas/core/math/utilities.cpp deleted file mode 100644 index 8947db55..00000000 --- a/src/atlas/core/math/utilities.cpp +++ /dev/null @@ -1,76 +0,0 @@ -#include -#include -#include - -namespace atlas { - - glm::quat to_quat(const glm::vec4& p_values) { - return glm::quat({ - p_values.w, - p_values.x, - p_values.y, - p_values.z, - }); - } - - glm::highp_vec4 from_quat(const glm::vec3& p_values) { - // converts glm::vec3 rotation to a quaternion returning the - // quaternion-converted values to glm::highp_vec4 - auto quaternion = glm::quat(p_values); - return glm::vec4( - { quaternion.x, quaternion.y, quaternion.z, quaternion.w }); - } - - glm::quat to_quat(const glm::vec3& p_values) { - return glm::quat(p_values); - } - - glm::quat to_quathp(const glm::highp_vec4& p_values) { - return glm::quat({ - p_values.w, - p_values.x, - p_values.y, - p_values.z, - }); - } - - namespace math { - - glm::vec3 zeroes() { - return glm::vec3(0.f); - } - - glm::vec3 ones() { - return glm::vec3(1.f); - } - - glm::quat identity() { - return glm::quat_identity(); - } - - glm::vec3 forward() { - return glm::vec3(0.f, 0.f, 1.f); - } - - glm::vec3 right() { - return glm::vec3(1.f, 0.f, 0.f); - } - - glm::vec3 left() { - return glm::vec3(-1.f, 0.f, 0.f); - } - - glm::vec3 backward() { - return glm::vec3(0.f, 0.f, -1.f); - } - - glm::vec3 up() { - return glm::vec3(0.f, 1.f, 0.f); - } - - glm::vec3 down() { - return glm::vec3(0.f, -1.f, 0.f); - } - }; - -}; \ No newline at end of file diff --git a/src/atlas/core/platforms/main.cpp b/src/atlas/core/platforms/main.cpp deleted file mode 100644 index 94840934..00000000 --- a/src/atlas/core/platforms/main.cpp +++ /dev/null @@ -1,16 +0,0 @@ -#include -#include -extern int win_main(); - -int -main() { - //! @note pre-init phase - atlas::console_log_manager::initialize_logger_manager(); - //! @note Ensures that glfw gets initiated during the pre-init phases - if (!glfwInit()) { - console_log_warn("GLFW: Failed to initialize"); - return -1; - } - - return win_main(); -} \ No newline at end of file diff --git a/src/atlas/core/platforms/win32.cpp b/src/atlas/core/platforms/win32.cpp deleted file mode 100644 index ef789510..00000000 --- a/src/atlas/core/platforms/win32.cpp +++ /dev/null @@ -1,20 +0,0 @@ -#include -#include -#include -#include -extern atlas::ref atlas::initialize_application(); - -int -win_main() { - // atlas::system_registry::initialize(); - atlas::ref graphic_context = - atlas::initialize_context("vulkan_context"); - - atlas::ref system = - atlas::create_ref("system"); - atlas::ref app = atlas::initialize_application(); - app->execute(); - graphic_context->destroy(); - app->post_destroy(); - return 0; -} diff --git a/src/atlas/core/scene/game_object.cpp b/src/atlas/core/scene/game_object.cpp deleted file mode 100644 index 397f2072..00000000 --- a/src/atlas/core/scene/game_object.cpp +++ /dev/null @@ -1,25 +0,0 @@ -#include -#include -#include -#include - -namespace atlas { - game_object::game_object(flecs::world_t* p_registry, flecs::entity_t p_id) - : flecs::entity(p_registry, p_id) { - add(); - } - - game_object::game_object(const flecs::entity& p_base) - : flecs::entity(p_base) { - add(); - } - - game_object::game_object(flecs::entity& p_base) - : flecs::entity(p_base) { - add(); - } - - void game_object::child_of(const std::optional& p_parent) { - add(flecs::ChildOf, p_parent.value()); - } -}; \ No newline at end of file diff --git a/src/atlas/core/scene/scene.cpp b/src/atlas/core/scene/scene.cpp deleted file mode 100644 index 6cb57848..00000000 --- a/src/atlas/core/scene/scene.cpp +++ /dev/null @@ -1,20 +0,0 @@ -#include - -namespace atlas { - scene::scene(const std::string& p_name, event::event_bus& p_bus) - : m_name(p_name) - , m_bus(&p_bus) {} - - game_object scene::entity(std::string_view p_name) { - return game_object(m_registry.entity(p_name.data())); - } - - game_object scene::entity(uint64_t p_id) { - return game_object(m_registry.entity(p_id)); - } - - uint32_t scene::children_count(const game_object& p_parent) { - return query_builder().with(flecs::ChildOf, p_parent).build().count(); - } - -}; \ No newline at end of file diff --git a/src/atlas/core/scene/world.cpp b/src/atlas/core/scene/world.cpp deleted file mode 100644 index 62d43aff..00000000 --- a/src/atlas/core/scene/world.cpp +++ /dev/null @@ -1,18 +0,0 @@ -#include -#include -#include - -namespace atlas { - - world::world(const std::string& p_name) - : m_name(p_name) {} - - /** - * @brief Currently how to pass in the scene context to the world - * TODO: Have a way of allowing creation and management of those - * created-scenes be done through world - */ - void world::add_scene(const ref& p_scene_context) { - m_scene_container.emplace(p_scene_context->name(), p_scene_context); - } -}; \ No newline at end of file diff --git a/src/atlas/core/serialize/serializer.cpp b/src/atlas/core/serialize/serializer.cpp deleted file mode 100644 index 83f4d3a5..00000000 --- a/src/atlas/core/serialize/serializer.cpp +++ /dev/null @@ -1,213 +0,0 @@ -#include -#include -#include -#include -#include -#include -#include - -namespace atlas { - - // used to serialize entities - // TODO -- expand on this to stream_reader and stream_writer - static void serialize_entity(YAML::Emitter& output, - const flecs::entity& p_entity) { - output << YAML::BeginMap; - - output << YAML::Key << "Entity" << YAML::Value << p_entity.name(); - - if (p_entity.has()) { - output << p_entity.get(); - } - - if (p_entity.has()) { - output << p_entity.get(); - } - - if (p_entity.has()) { - output << p_entity.get(); - } - - if (p_entity.has()) { - output << p_entity.get(); - } - - if (p_entity.has()) { - output << p_entity.get(); - } - - if (p_entity.has()) { - output << p_entity.get(); - } - - if (p_entity.has()) { - output << p_entity.get(); - } - - if (p_entity.has()) { - output << p_entity.get(); - } - - // serialize entity childrens -- TODO - // output << YAML::Key << "Children" << YAML::Value << YAML::BeginSeq; - // p_entity.children([&](flecs::entity p_child_entity){ - // serialize_entity(output, p_child_entity); - // }); - - output << YAML::EndMap; - } - - static void deserialize_entity(YAML::iterator::value_type p_entity_value, - flecs::entity& p_deserialize_to_object) { - if (p_entity_value["Transform"]) { - auto transform_data = p_entity_value["Transform"]; - p_deserialize_to_object.set({ - .position = transform_data["Position"].as(), - .quaternion = transform_data["Quaternion"].as(), - .rotation = transform_data["Rotation"].as(), - .scale = transform_data["Scale"].as(), - }); - } - - // Deserialize atlas::perspective_camera component - if (p_entity_value["PerspectiveCamera"]) { - auto perspective_camera_data = p_entity_value["PerspectiveCamera"]; - p_deserialize_to_object.set({ - .plane = perspective_camera_data["Plane"].as(), - .is_active = perspective_camera_data["Active"].as(), - .field_of_view = - perspective_camera_data["Field of View"].as(), - }); - } - - // Deserialize atlas::material component - if (p_entity_value["Mesh Source"]) { - auto perspective_camera_data = p_entity_value["Mesh Source"]; - p_deserialize_to_object.set({ - .model_path = - perspective_camera_data["Model Path"].as(), - .diffuse = perspective_camera_data["Diffuse"].as(), - .specular = perspective_camera_data["Specular"].as(), - }); - } - - if (p_entity_value["Point Light"]) { - auto point_light = p_entity_value["Point Light"]; - p_deserialize_to_object.set({ - .color = point_light["Color"].as(), - .attenuation = point_light["Attenuation"].as(), - .constant = 1.f, - .linear = 1.f, - .quadratic = 1.f, - .ambient = point_light["Ambient"].as(), - .diffuse = point_light["Diffuse"].as(), - .specular = point_light["Specular"].as(), - }); - } - - // deserialize physics body - if (p_entity_value["Physics Body"]) { - auto body = p_entity_value["Physics Body"]; - p_deserialize_to_object.set( - { .linear_velocity = body["Linear Velocity"].as(), - .angular_velocity = body["Angular Velocity"].as(), - .force = body["Force"].as(), - .impulse = body["Impulse"].as(), - .torque = body["Torque"].as(), - .center_mass_position = - body["Center Mass Position"].as(), - .friction = body["Friction"].as(), - .restitution = body["Restitution"].as(), - .body_movement_type = - static_cast(body["Body Movement Type"].as()), - .body_layer_type = - static_cast(body["Body Layer Type"].as()) }); - } - - if (p_entity_value["Box Collider"]) { - auto collider = p_entity_value["Box Collider"]; - p_deserialize_to_object.set({ - .half_extent = collider["Half Extent"].as(), - }); - } - - if (p_entity_value["Sphere Collider"]) { - auto collider = p_entity_value["Sphere Collider"]; - p_deserialize_to_object.set({ - .radius = collider["Radius"].as(), - }); - } - - if (p_entity_value["Capsule Collider"]) { - auto collider = p_entity_value["Capsule Collider"]; - p_deserialize_to_object.set({ - .radius = collider["Half Height"].as(), - .half_height = collider["Half Height"].as(), - }); - } - } - - serializer::serializer(const ref& p_scene_ctx) - : m_current_scene_ctx(p_scene_ctx) {} - - void serializer::save(const std::filesystem::path& p_filepath) { - YAML::Emitter output; - output << YAML::BeginMap; - output << YAML::Key << "Scene" << YAML::Value - << m_current_scene_ctx->name(); - output << YAML::Key << "Entities" << YAML::Value << YAML::BeginSeq; - - //! @note Queries in flecs the ecs framework are how we can query all - //! entities that the engine (user creates through our API) - // ref world_object = - // system_registry::get_world("Editor World"); - // ref current_scene = - // world_object->get_scene("LevelScene"); - - // flecs::query<> q = - // current_scene->query_builder().with().build(); - - // query all entities with a serialized tag specified - // while specifying to not query entities that also have the tag::editor - // specified - flecs::query<> q = m_current_scene_ctx->query_builder() - .with() - .without() - .build(); - - q.each([&output](flecs::entity p_entity_id) { - serialize_entity(output, p_entity_id); - }); - - std::ofstream output_file(p_filepath.string()); - output_file << output.c_str(); - } - - bool serializer::load(const std::filesystem::path& p_filepath, - const flecs::world& p_registry) { - std::ifstream ins(p_filepath.string()); - std::stringstream ss; - ss << ins.rdbuf(); - - YAML::Node data = YAML::Load(ss.str()); - - if (!data["Scene"]) { - return false; - } - - YAML::Node entity_objects = data["Entities"]; - - if (entity_objects) { - for (YAML::iterator::value_type entity : entity_objects) { - std::string name = entity["Entity"].as(); - flecs::entity deserialize_to_object = - p_registry.entity(name.c_str()); - - // Deserialize atlas::transform component - deserialize_entity(entity, deserialize_to_object); - } - } - - return true; - } -}; \ No newline at end of file diff --git a/src/atlas/core/serialize/types.cpp b/src/atlas/core/serialize/types.cpp deleted file mode 100644 index ffd47c12..00000000 --- a/src/atlas/core/serialize/types.cpp +++ /dev/null @@ -1,157 +0,0 @@ -#include - -namespace atlas { - - YAML::Emitter& operator<<(YAML::Emitter& p_out, - const glm::highp_vec2& p_values) { - p_out << YAML::Flow; - p_out << YAML::BeginSeq << p_values.x << p_values.y << YAML::EndSeq; - return p_out; - } - - YAML::Emitter& operator<<(YAML::Emitter& p_out, - const glm::highp_vec3& p_values) { - p_out << YAML::Flow; - p_out << YAML::BeginSeq << p_values.x << p_values.y << p_values.z - << YAML::EndSeq; - return p_out; - } - - YAML::Emitter& operator<<(YAML::Emitter& p_out, - const glm::highp_vec4& p_values) { - p_out << YAML::Flow; - p_out << YAML::BeginSeq << p_values.x << p_values.y << p_values.z - << p_values.w << YAML::EndSeq; - return p_out; - } - - // Serializing atlas::transform component to yaml format - YAML::Emitter& operator<<(YAML::Emitter& p_output, - const transform* p_transform) { - p_output << YAML::Key << "Transform"; - - p_output << YAML::BeginMap; - p_output << YAML::Key << "Position" << YAML::Value - << p_transform->position; - p_output << YAML::Key << "Scale" << YAML::Value << p_transform->scale; - p_output << YAML::Key << "Rotation" << YAML::Value - << p_transform->rotation; - p_output << YAML::Key << "Quaternion" << YAML::Value - << p_transform->quaternion; - p_output << YAML::EndMap; - return p_output; - } - - // Serialize perspective camera component into yaml format - YAML::Emitter& operator<<(YAML::Emitter& p_output, - const perspective_camera* p_camera) { - p_output << YAML::Key << "PerspectiveCamera"; - - p_output << YAML::BeginMap; - p_output << YAML::Key << "Plane" << YAML::Value << p_camera->plane; - p_output << YAML::Key << "Active" << YAML::Value << p_camera->is_active; - p_output << YAML::Key << "Field of View" << YAML::Value - << p_camera->field_of_view; - p_output << YAML::EndMap; - return p_output; - } - - YAML::Emitter& operator<<(YAML::Emitter& p_output, - const mesh_source* p_material) { - p_output << YAML::Key << "Mesh Source"; - - p_output << YAML::BeginMap; - p_output << YAML::Key << "Model Path" << YAML::Value - << p_material->model_path; - p_output << YAML::Key << "Diffuse" << YAML::Value - << p_material->diffuse; - p_output << YAML::Key << "Specular" << YAML::Value - << p_material->specular; - p_output << YAML::EndMap; - return p_output; - } - - YAML::Emitter& operator<<(YAML::Emitter& p_output, - const point_light* p_material) { - p_output << YAML::Key << "Point Light"; - - p_output << YAML::BeginMap; - p_output << YAML::Key << "Color" << YAML::Value << p_material->color; - p_output << YAML::Key << "Attenuation" << YAML::Value - << p_material->attenuation; - p_output << YAML::Key << "Ambient" << YAML::Value - << p_material->ambient; - p_output << YAML::Key << "Diffuse" << YAML::Value - << p_material->diffuse; - p_output << YAML::Key << "Specular" << YAML::Value - << p_material->specular; - p_output << YAML::EndMap; - return p_output; - } - - YAML::Emitter& operator<<(YAML::Emitter& p_output, - const physics_body* p_body) { - p_output << YAML::Key << "Physics Body"; - - p_output << YAML::BeginMap; - p_output << YAML::Key << "Linear Velocity" << YAML::Value - << p_body->linear_velocity; - p_output << YAML::Key << "Angular Velocity" << YAML::Value - << p_body->angular_velocity; - p_output << YAML::Key << "Force" << YAML::Value << p_body->force; - p_output << YAML::Key << "Impulse" << YAML::Value << p_body->impulse; - p_output << YAML::Key << "Torque" << YAML::Value << p_body->torque; - p_output << YAML::Key << "Mass Factor" << YAML::Value - << p_body->mass_factor; - p_output << YAML::Key << "Center Mass Position" << YAML::Value - << p_body->center_mass_position; - p_output << YAML::Key << "Friction" << YAML::Value << p_body->friction; - p_output << YAML::Key << "Restitution" << YAML::Value - << p_body->restitution; - p_output << YAML::Key << "Body Movement Type" << YAML::Value - << static_cast(p_body->body_movement_type); - p_output << YAML::Key << "Body Layer Type" << YAML::Value - << static_cast(p_body->body_layer_type); - p_output << YAML::EndMap; - return p_output; - } - - YAML::Emitter& operator<<(YAML::Emitter& p_output, - const box_collider* p_body) { - // Tag this specific serialization values to the box collider - p_output << YAML::Key << "Box Collider"; - - p_output << YAML::BeginMap; - p_output << YAML::Key << "Half Extent" << YAML::Value - << p_body->half_extent; - p_output << YAML::EndMap; - - return p_output; - } - - YAML::Emitter& operator<<(YAML::Emitter& p_output, - const sphere_collider* p_body) { - // - p_output << YAML::Key << "Sphere Collider"; - - p_output << YAML::BeginMap; - p_output << YAML::Key << "Radius" << YAML::Value << p_body->radius; - - p_output << YAML::EndMap; - - return p_output; - } - - YAML::Emitter& operator<<(YAML::Emitter& p_output, - const capsule_collider* p_body) { - // - p_output << YAML::Key << "Capsule Collider"; - p_output << YAML::BeginMap; - p_output << YAML::Key << "Radius" << YAML::Value << p_body->radius; - p_output << YAML::Key << "Half Height" << YAML::Value - << p_body->half_height; - p_output << YAML::EndMap; - - return p_output; - } -}; \ No newline at end of file diff --git a/src/atlas/core/system/registry.cpp b/src/atlas/core/system/registry.cpp deleted file mode 100644 index c0ccf02a..00000000 --- a/src/atlas/core/system/registry.cpp +++ /dev/null @@ -1,32 +0,0 @@ -#include -#include -#include - -namespace atlas { - system_registry* system_registry::s_instance = nullptr; - - system_registry::system_registry(const std::string& p_tag) - : m_tag(p_tag) { - s_instance = this; - } - - system_registry::~system_registry() = default; - - ref system_registry::create_world(const std::string& p_tag) { - return s_instance->append_world_and_get(create_ref(p_tag)); - } - - ref system_registry::get_world(const std::string& p_tag) { - return s_instance->search_world(p_tag); - } - - ref system_registry::search_world(const std::string& p_tag) { - return m_world_registered[p_tag]; - } - - ref system_registry::append_world_and_get( - const ref& p_world) { - m_world_registered.emplace(p_world->name(), p_world); - return m_world_registered[p_world->name()]; - } -}; \ No newline at end of file diff --git a/src/atlas/core/timer.cpp b/src/atlas/core/timer.cpp deleted file mode 100644 index 3e420505..00000000 --- a/src/atlas/core/timer.cpp +++ /dev/null @@ -1,4 +0,0 @@ -/* -- Delete this file along with core/timer.hpp if not done so -- Only exists to prevent merge conflicts in CMakeLists.txt -*/ \ No newline at end of file diff --git a/src/atlas/core/ui/widgets.cpp b/src/atlas/core/ui/widgets.cpp deleted file mode 100644 index 9a134699..00000000 --- a/src/atlas/core/ui/widgets.cpp +++ /dev/null @@ -1,313 +0,0 @@ -#include -#include // Used to include "PushMultiItemsWidths" - -namespace atlas::ui { - using ::ImGui::InputText; - - bool begin_popup_context_window(const char* str_id, - ImGuiMouseButton mb, - bool over_items) { - return ImGui::BeginPopupContextWindow( - str_id, mb | (over_items ? 0 : ImGuiPopupFlags_NoOpenOverItems)); - } - - void draw_vec3(const std::string& p_tag, - glm::vec3& p_position, - float p_reset_value) { - // ImGuiIO& io = ImGui::GetIO(); - ImGui::PushID(p_tag.c_str()); - - float column_width = 125.0f; - - ImGui::Columns(2); - ImGui::SetColumnWidth(0, column_width); - ImGui::Text("%s", p_tag.c_str()); - ImGui::NextColumn(); - - ImGui::PushMultiItemsWidths(3, ImGui::CalcItemWidth()); - ImGui::PushStyleVar(ImGuiStyleVar_ItemSpacing, ImVec2{ 0, 0 }); - - float line_height = - ImGui::GetFontSize() + ImGui::GetStyle().FramePadding.y * 2.0f; - ImVec2 button_size = { line_height + 3.0f, line_height }; - - ImGui::PushStyleColor(ImGuiCol_Button, - ImVec4{ 0.8, 0.1f, 0.15f, 1.0f }); - ImGui::PushStyleColor(ImGuiCol_ButtonHovered, - ImVec4{ 0.3f, 0.8f, 0.3f, 1.0f }); - ImGui::PushStyleColor(ImGuiCol_ButtonActive, - ImVec4{ 0.2, 0.1f, 0.2f, 1.0f }); - - if (ImGui::Button("X", button_size)) { - p_position.x = p_reset_value; - // ImGui::End(); - } - - // ImGui::PopFont(); - ImGui::PopStyleColor(3); - - ImGui::SameLine(); - ImGui::DragFloat("##X", &p_position.x, 0.1f, 0.0f, 0.0f, "%.2f"); - ImGui::PopItemWidth(); - ImGui::SameLine(); - - // Setting up for the Y button - ImGui::PushStyleColor(ImGuiCol_Button, ImVec4{ 0.2, 0.7f, 0.2f, 1.0f }); - ImGui::PushStyleColor(ImGuiCol_ButtonHovered, - ImVec4{ 0.3f, 0.8f, 0.3f, 1.0f }); - ImGui::PushStyleColor(ImGuiCol_ButtonActive, - ImVec4{ 0.2, 0.1f, 0.2f, 1.0f }); - - if (ImGui::Button("Y", button_size)) { - p_position.y = p_reset_value; - // ImGui::End(); - } - - // ImGui::PopFont(); - ImGui::PopStyleColor(3); - ImGui::SameLine(); - ImGui::DragFloat("##Y", &p_position.y, 0.1f, 0.0f, 0.0f, "%.2f"); - ImGui::PopItemWidth(); - ImGui::SameLine(); - - // Setting up for the Z button - ImGui::PushStyleColor(ImGuiCol_Button, - ImVec4{ 0.1, 0.25f, 0.8f, 1.0f }); - ImGui::PushStyleColor(ImGuiCol_ButtonHovered, - ImVec4{ 0.2f, 0.35f, 0.9f, 1.0f }); - ImGui::PushStyleColor(ImGuiCol_ButtonActive, - ImVec4{ 0.8, 0.1f, 0.15f, 1.0f }); - if (ImGui::Button("Z", button_size)) { - p_position.z = p_reset_value; - // ImGui::End(); - } - - // ImGui::PopFont(); - ImGui::PopStyleColor(3); - ImGui::SameLine(); - ImGui::DragFloat("##Z", &p_position.z, 0.1f, 0.0f, 0.0f, "%.2f"); - ImGui::PopItemWidth(); - - ImGui::PopStyleVar(); - - ImGui::Columns(1); - - ImGui::PopID(); - } - - void draw_vec4(const std::string& p_tag, - glm::vec4& p_value, - float p_reset_value) { - // ImGuiIO& io = ImGui::GetIO(); - ImGui::PushID(p_tag.c_str()); - - float column_width = 100.0f; - - ImGui::Columns(2); - ImGui::SetColumnWidth(0, column_width); - ImGui::Text("%s", p_tag.c_str()); - ImGui::NextColumn(); - - ImGui::PushMultiItemsWidths(3, ImGui::CalcItemWidth()); - ImGui::PushStyleVar(ImGuiStyleVar_ItemSpacing, ImVec2{ 0, 0 }); - - float line_height = - ImGui::GetFontSize() + ImGui::GetStyle().FramePadding.y * 2.0f; - ImVec2 button_size = { line_height + 3.0f, line_height }; - - ImGui::PushStyleColor(ImGuiCol_Button, - ImVec4{ 0.8, 0.1f, 0.15f, 1.0f }); - ImGui::PushStyleColor(ImGuiCol_ButtonHovered, - ImVec4{ 0.3f, 0.8f, 0.3f, 1.0f }); - ImGui::PushStyleColor(ImGuiCol_ButtonActive, - ImVec4{ 0.2, 0.1f, 0.2f, 1.0f }); - - if (ImGui::Button("X", button_size)) { - p_value.x = p_reset_value; - // ImGui::End(); - } - - // ImGui::PopFont(); - ImGui::PopStyleColor(3); - - ImGui::SameLine(); - ImGui::DragFloat("##X", &p_value.x, 0.1f, 0.0f, 0.0f, "%.2f"); - ImGui::PopItemWidth(); - ImGui::SameLine(); - - // Setting up for the Y button - ImGui::PushStyleColor(ImGuiCol_Button, ImVec4{ 0.2, 0.7f, 0.2f, 1.0f }); - ImGui::PushStyleColor(ImGuiCol_ButtonHovered, - ImVec4{ 0.3f, 0.8f, 0.3f, 1.0f }); - ImGui::PushStyleColor(ImGuiCol_ButtonActive, - ImVec4{ 0.2, 0.1f, 0.2f, 1.0f }); - - if (ImGui::Button("Y", button_size)) { - p_value.y = p_reset_value; - // ImGui::End(); - } - - // ImGui::PopFont(); - ImGui::PopStyleColor(3); - ImGui::SameLine(); - ImGui::DragFloat("##Y", &p_value.y, 0.1f, 0.0f, 0.0f, "%.2f"); - ImGui::PopItemWidth(); - ImGui::SameLine(); - - // Setting up for the Z button - ImGui::PushStyleColor(ImGuiCol_Button, - ImVec4{ 0.1, 0.25f, 0.8f, 1.0f }); - ImGui::PushStyleColor(ImGuiCol_ButtonHovered, - ImVec4{ 0.2f, 0.35f, 0.9f, 1.0f }); - ImGui::PushStyleColor(ImGuiCol_ButtonActive, - ImVec4{ 0.8, 0.1f, 0.15f, 1.0f }); - if (ImGui::Button("Z", button_size)) { - p_value.z = p_reset_value; - // ImGui::End(); - } - - // ImGui::PopFont(); - ImGui::PopStyleColor(3); - ImGui::SameLine(); - ImGui::DragFloat("##Z", &p_value.z, 0.1f, 0.0f, 0.0f, "%.2f"); - ImGui::PopItemWidth(); - - ImGui::PopStyleVar(); - - ImGui::Columns(1); - - ImGui::PopID(); - } - - void draw_float(const std::string& p_tag, - float& p_value, - float reset_value) { - ImGui::PushID(p_tag.c_str()); - - float column_width = 100.0f; - - ImGui::Columns(2); - - ImGui::SetColumnWidth(0, column_width); - ImGui::Text("%s", p_tag.c_str()); - ImGui::NextColumn(); - - ImGui::PushItemWidth(ImGui::CalcItemWidth()); - // ImGui::PushMultiItemsWidths(3, ImGui::CalcItemWidth()); - ImGui::PushStyleVar(ImGuiStyleVar_ItemSpacing, ImVec2{ 0, 0 }); - ImGui::PushStyleColor(ImGuiCol_Button, - ImVec4{ 0.8, 0.1f, 0.15f, 1.0f }); - ImGui::PushStyleColor(ImGuiCol_ButtonHovered, - ImVec4{ 0.3f, 0.8f, 0.3f, 1.0f }); - ImGui::PushStyleColor(ImGuiCol_ButtonActive, - ImVec4{ 0.2, 0.1f, 0.2f, 1.0f }); - - if (ImGui::Button(p_tag.c_str())) { - p_value = reset_value; - // ImGui::End(); - } - - // ImGui::PopFont(); - ImGui::PopStyleColor(3); - - ImGui::SameLine(); - ImGui::DragFloat("##X", &p_value, 0.1f, 0.0f, 0.0f, "%.2f"); - ImGui::PopItemWidth(); - ImGui::SameLine(); - - ImGui::PopStyleVar(); - - ImGui::Columns(1); - - ImGui::PopID(); - } - - void draw_input_text(std::string& p_dst, std::string& p_src) { - std::string input_buffer = p_src; - - ImGuiInputTextFlags flags = ImGuiInputTextFlags_EnterReturnsTrue; - input_buffer.resize(255); // resize to allocate for 255 in the char - // array since this should be long enough - - if (ImGui::InputText("##Name", - (char*)input_buffer.c_str(), - input_buffer.size() + 1, - flags)) { - p_dst = input_buffer; - } - - if (p_dst.empty()) { - p_dst = p_src; - return; - } - - if (p_dst == p_src) { - p_dst = p_src; - return; - } - } - - void draw_text(const std::string& p_value) { - ImGui::Text("%s", p_value.data()); - } - - void dockspace_window(GLFWwindow* p_window) { - - bool dockspace_open = true; - static bool opt_fullscreen_persistant = true; - bool opt_fullscreen = opt_fullscreen_persistant; - static ImGuiDockNodeFlags dockspace_flags = ImGuiDockNodeFlags_None; - - ImGuiWindowFlags window_flags = - ImGuiWindowFlags_MenuBar | ImGuiWindowFlags_NoDocking; - - if (opt_fullscreen) { - ImGuiViewport* viewport = ImGui::GetMainViewport(); - ImGui::SetNextWindowPos(viewport->Pos); - ImGui::SetNextWindowSize(viewport->Size); - ImGui::SetNextWindowViewport(viewport->ID); - window_flags |= ImGuiWindowFlags_NoTitleBar | - ImGuiWindowFlags_NoCollapse | - ImGuiWindowFlags_NoResize | ImGuiWindowFlags_NoMove; - window_flags |= ImGuiWindowFlags_NoBringToFrontOnFocus | - ImGuiWindowFlags_NoNavFocus; - } - - if (dockspace_flags & ImGuiDockNodeFlags_PassthruCentralNode) { - window_flags |= ImGuiWindowFlags_NoBackground; - } - - ImGui::PushStyleVar(ImGuiStyleVar_WindowPadding, ImVec2(0.0f, 0.0f)); - ImGui::Begin("Dockspace Demo", &dockspace_open, window_flags); - ImGui::PopStyleVar(); - - if (opt_fullscreen) { - ImGui::PopStyleVar(2); - } - - // Dockspace - ImGuiIO& io = ImGui::GetIO(); - if (io.ConfigFlags & ImGuiConfigFlags_DockingEnable) { - ImGuiID dockspace_id = ImGui::GetID("MyDockspace"); - ImGui::DockSpace(dockspace_id, ImVec2(0.f, 0.f), dockspace_flags); - } - - if (ImGui::BeginMenuBar()) { - if (ImGui::MenuItem("Exit")) { - glfwSetWindowShouldClose(p_window, true); - } - - ImGui::EndMenuBar(); - } - - ImGui::End(); - } - - void button_open_file_dialog(const std::string& p_tag, - std::string& p_filename, - const std::string& p_filter) { - if (ImGui::Button(p_tag.c_str())) { - p_filename = filesystem::load_from_file_dialog(p_filter); - } - } -}; \ No newline at end of file diff --git a/src/atlas/core/utilities/state.cpp b/src/atlas/core/utilities/state.cpp deleted file mode 100644 index 24f45316..00000000 --- a/src/atlas/core/utilities/state.cpp +++ /dev/null @@ -1,98 +0,0 @@ -#include -#include - -namespace atlas { - namespace detail { - // inline std::deque> s_update{}; - // inline std::deque> s_defer_update{}; - // inline std::deque> s_ui_update{}; - // inline std::deque> s_physica_update{}; - // inline std::deque> s_start{}; - - // TODO: This should be done in a better way - // Potential replace this approach with using std::hive from C++26 - inline std::unordered_map> s_update{}; - inline std::unordered_map> - s_defer_update{}; - inline std::unordered_map> s_ui_update{}; - inline std::unordered_map> - s_physica_update{}; - inline std::unordered_map> s_start{}; - - void poll_update(void* p_address, - const std::function& p_callable) { - // s_update.emplace_back(p_callback); - s_update.emplace(p_address, p_callable); - } - - void poll_defer_update(void* p_address, - const std::function& p_callback) { - s_defer_update.emplace(p_address, p_callback); - } - - void poll_physics_update(void* p_address, - const std::function& p_callback) { - s_physica_update.emplace(p_address, p_callback); - } - - void poll_ui_update(void* p_address, - const std::function& p_callback) { - s_ui_update.emplace(p_address, p_callback); - } - - void poll_start(void* p_address, - const std::function& p_callback) { - s_start.emplace(p_address, p_callback); - } - - void remove_update(void* p_address) { - s_update.erase(p_address); - } - - void remove_defer_update(void* p_address) { - s_defer_update.erase(p_address); - } - - void remove_physics_update(void* p_address) { - s_physica_update.erase(p_address); - } - - void remove_ui_update(void* p_address) { - s_ui_update.erase(p_address); - } - - void remove_start(void* p_address) { - s_start.erase(p_address); - } - - void invoke_on_update() { - for (auto& [address, on_update] : s_update) { - on_update(); - } - } - - void invoke_defer_update() { - for (auto& [address, on_update] : s_defer_update) { - on_update(); - } - } - - void invoke_physics_update() { - for (auto& [address, on_update] : s_physica_update) { - on_update(); - } - } - - void invoke_ui_update() { - for (auto& [address, on_update] : s_ui_update) { - on_update(); - } - } - - void invoke_start() { - for (auto& [address, on_update] : s_start) { - on_update(); - } - } - }; -}; \ No newline at end of file diff --git a/src/atlas/core/window.cpp b/src/atlas/core/window.cpp deleted file mode 100644 index b202cc86..00000000 --- a/src/atlas/core/window.cpp +++ /dev/null @@ -1,44 +0,0 @@ -#include -#include -#include -#include -#include - -namespace atlas { - ref create_window(const window_settings& p_settings) { - switch (application::current_api()) { - case api::vulkan: - return create_ref(p_settings); - default: - console_log_error( - "API that was input was not specifiying valid backend!"); - return nullptr; - } - - return nullptr; - } - - uint32_t window::width() const { - return settings().width; - } - - uint32_t window::height() const { - return settings().height; - } - - bool window::available() const { - return !glfwWindowShouldClose(native_window()); - } - - void window::close() { - glfwSetWindowShouldClose(native_window(), true); - } - - void window::present(const uint32_t& p_current_frame_idx) { - return presentation_process(p_current_frame_idx); - } - - float window::aspect_ratio() const { - return (float)width() / (float)height(); - } -}; \ No newline at end of file diff --git a/src/atlas/drivers/graphics_context.cpp b/src/atlas/drivers/graphics_context.cpp deleted file mode 100644 index 7d236703..00000000 --- a/src/atlas/drivers/graphics_context.cpp +++ /dev/null @@ -1,14 +0,0 @@ -#include -#include -#include - -namespace atlas { - ref initialize_context(const std::string& p_tag) { - switch (application::current_api()) { - case api::vulkan: - return create_ref(p_tag); - default: - return nullptr; - } - } -}; \ No newline at end of file diff --git a/src/atlas/drivers/jolt-cpp/jolt_contact_listener.cpp b/src/atlas/drivers/jolt-cpp/jolt_contact_listener.cpp deleted file mode 100644 index a6c7aff0..00000000 --- a/src/atlas/drivers/jolt-cpp/jolt_contact_listener.cpp +++ /dev/null @@ -1,51 +0,0 @@ -#include -#include -#include -#include -#include - -namespace atlas::physics { - - contact_listener::contact_listener(event::event_bus& p_bus) - : m_bus(&p_bus) {} - - JPH::ValidateResult contact_listener::OnContactValidate( - const JPH::Body&, - const JPH::Body&, - JPH::RVec3Arg, - const JPH::CollideShapeResult&) { - return JPH::ValidateResult::AcceptAllContactsForThisBodyPair; - } - - void contact_listener::OnContactAdded(const JPH::Body& p_body1, - const JPH::Body& p_body2, - const JPH::ContactManifold&, - JPH::ContactSettings&) { - event::collision_enter begin_event = { - .entity1 = static_cast(p_body1.GetUserData()), - .entity2 = static_cast(p_body2.GetUserData()) - }; - - // Publishes to all subscribers that this collision_enter event has - // occurred - m_bus->publish(begin_event); - } - - void contact_listener::OnContactPersisted(const JPH::Body& p_body1, - const JPH::Body& p_body2, - const JPH::ContactManifold&, - JPH::ContactSettings&) { - event::collision_persisted persisted_event = { - .entity1 = static_cast(p_body1.GetUserData()), - .entity2 = static_cast(p_body2.GetUserData()) - }; - - m_bus->publish(persisted_event); - } - - void contact_listener::OnContactRemoved(const JPH::SubShapeIDPair&) { - console_log_info("Collisions Removed!"); - // For Event system to handle when collision ends - } - -} \ No newline at end of file diff --git a/src/atlas/drivers/jolt-cpp/jolt_context.cpp b/src/atlas/drivers/jolt-cpp/jolt_context.cpp deleted file mode 100644 index 5b732e1e..00000000 --- a/src/atlas/drivers/jolt-cpp/jolt_context.cpp +++ /dev/null @@ -1,376 +0,0 @@ -#include -#include -#include -#include -#include - -namespace atlas::physics { - static void trace_impl(const char* p_in_fmt, ...) { - va_list list; - va_start(list, p_in_fmt); - char buffer[1024]; - vsnprintf(buffer, sizeof(buffer), p_in_fmt, list); - va_end(list); - console_log_error("{}", buffer); - } - - [[maybe_unused]] static bool assert_failed_impl(const char* p_in_expression, - const char* p_in_message, - const char* p_in_file, - unsigned int p_in_line) { - - console_log_error("{}:{}: ({}) {}", - p_in_file, - p_in_line, - p_in_expression, - (p_in_message != nullptr ? p_in_message : "")); - - return true; - }; - - jolt_context::jolt_context(const jolt_settings& p_settings, - event::event_bus& p_bus) - : m_contact_listener(p_bus) { - JPH::RegisterDefaultAllocator(); - - JPH::Trace = trace_impl; - JPH_IF_ENABLE_ASSERTS(JPH::AssertFailed = assert_failed_impl;) - - JPH::Factory::sInstance = new JPH::Factory(); - JPH::RegisterTypes(); - - m_temp_allocator = - create_ref(p_settings.allocation_amount); - - // This just sets up the JoltPhysics system and any listeners - m_physics_system = create_ref(); - m_broad_phase_layer_interface = - create_ref(); - m_object_vs_broadphase_filter = - create_ref(); - m_object_layer_pair_filter = create_ref(); - - if (p_settings.thread_type == thread_type::default_system) { - - m_thread_system = create_scope( - // Max jobs must be a power of 2, otherwise jph crashes. - // Bianary tree must be fully balanced - std::pow(2, p_settings.max_jobs_power), - p_settings.max_barriers, - p_settings.physics_threads); - } - else { - console_log_error("Unsupported custom job system"); - assert(false); - } - - m_physics_system->Init(p_settings.max_bodies, - 0, - p_settings.max_body_pairs, - p_settings.max_contact_constraints, - *m_broad_phase_layer_interface, - *m_object_vs_broadphase_filter, - *m_object_layer_pair_filter); - - // Default contact listener impl and can change during runtime - m_physics_system->SetContactListener(&m_contact_listener); - } - - void jolt_context::emplace_box_collider(uint32_t p_entity_id, - const transform* p_transform, - const physics_body* p_body, - const box_collider* p_collider) { - using namespace JPH; - auto& body_interface = m_physics_system->GetBodyInterface(); - - // Creating our box shape and specifying half_extent that is a glm::vec3 - // conversion to JPH::Vec3 half_extents must be 0.5f or else it can get - // an invalid convex radius - BoxShapeSettings shape_settings(jolt::to_vec3(p_collider->half_extent)); - auto result = shape_settings.Create(); - - if (result.HasError()) { - console_log_error("Box shape creation error: {}", - result.GetError()); - return; - } - EMotionType motion_type = EMotionType::Static; - switch (p_body->body_movement_type) { - case body_type::fixed: - motion_type = EMotionType::Static; - break; - case body_type::dynamic: - motion_type = EMotionType::Dynamic; - break; - case body_type::kinematic: - motion_type = EMotionType::Kinematic; - break; - } - - auto& box = result.Get(); - BodyCreationSettings body_settings( - box, - jolt::to_vec3(p_transform->position), - jolt::to_quat(p_transform->quaternion), - motion_type, - p_body->body_layer_type); - - // NOTE TO SELF ------ This is setting some pointer to the entity ID - // WE CAN USE THIS TO TELL THE EVENT SYSTEM WHICH FLECS ENTITY COLLIDED - // WITH EACH OTHER!!!!!!!! Because each contact listener allows you to - // take a pointer from the physics bodies that are just blocks of - // data!!! - body_settings.mUserData = static_cast(p_entity_id); - body_settings.mFriction = p_body->friction; - body_settings.mRestitution = p_body->restitution; - body_settings.mLinearVelocity = jolt::to_vec3(p_body->linear_velocity); - body_settings.mAngularVelocity = - jolt::to_vec3(p_body->angular_velocity); - - Body* body = body_interface.CreateBody(body_settings); - m_cached_body_ids.emplace(p_entity_id, body->GetID()); - } - - void jolt_context::emplace_sphere_collider( - uint32_t p_entity_id, - const transform* p_transform, - const physics_body* p_body, - const sphere_collider* p_collider) { - using namespace JPH; - auto& body_interface = m_physics_system->GetBodyInterface(); - // ensure that the half_extent of the box shape always matches the - // object and reference that information through the transform - SphereShapeSettings shape_settings(p_collider->radius); - auto result = shape_settings.Create(); - - if (result.HasError()) { - console_log_error("Sphere shape creation error: {}", - result.GetError()); - return; - } - EMotionType motion_type = EMotionType::Static; - switch (p_body->body_movement_type) { - case body_type::fixed: { - motion_type = EMotionType::Static; - } break; - case body_type::dynamic: { - motion_type = EMotionType::Dynamic; - } break; - case body_type::kinematic: { - motion_type = EMotionType::Kinematic; - } break; - } - - auto& box = result.Get(); - BodyCreationSettings body_settings( - box, - jolt::to_vec3(p_transform->position), - jolt::to_quat(p_transform->quaternion), - motion_type, - p_body->body_layer_type); - - // Assigning the entity ID as the user data - // Fetched when collision happens - body_settings.mUserData = static_cast(p_entity_id); - body_settings.mFriction = p_body->friction; - body_settings.mRestitution = p_body->restitution; - body_settings.mLinearVelocity = jolt::to_vec3(p_body->linear_velocity); - body_settings.mAngularVelocity = - jolt::to_vec3(p_body->angular_velocity); - Body* body = body_interface.CreateBody(body_settings); - - // body_interface.AddForce(body->GetID(), - // jolt::to_vec3(p_body->cumulative_force)); - m_cached_body_ids.emplace(p_entity_id, body->GetID()); - } - - void jolt_context::emplace_capsule_collider( - uint32_t p_entity_id, - const transform* p_transform, - const physics_body* p_body, - const capsule_collider* p_collider) { - using namespace JPH; - auto& body_interface = m_physics_system->GetBodyInterface(); - // ensure that the half_extent of the box shape always matches the - // object and reference that information through the transform - CapsuleShapeSettings shape_settings(p_collider->half_height, - p_collider->radius); - auto result = shape_settings.Create(); - - if (result.HasError()) { - console_log_error("Capsule shape creation error: {}", - result.GetError()); - return; - } - EMotionType motion_type = EMotionType::Static; - switch (p_body->body_movement_type) { - case body_type::fixed: { - motion_type = EMotionType::Static; - } break; - case body_type::dynamic: { - motion_type = EMotionType::Dynamic; - } break; - case body_type::kinematic: { - motion_type = EMotionType::Kinematic; - } break; - } - - auto& box = result.Get(); - BodyCreationSettings body_settings( - box, - jolt::to_vec3(p_transform->position), - jolt::to_quat(p_transform->quaternion), - motion_type, - p_body->body_layer_type); - body_settings.mFriction = p_body->friction; - body_settings.mRestitution = p_body->restitution; - body_settings.mLinearVelocity = jolt::to_vec3(p_body->linear_velocity); - body_settings.mAngularVelocity = - jolt::to_vec3(p_body->angular_velocity); - body_settings.mUserData = static_cast(p_entity_id); - - Body* body = body_interface.CreateBody(body_settings); - m_cached_body_ids.emplace(p_entity_id, body->GetID()); - } - - transform jolt_context::context_read_transform(uint32_t p_id) { - using namespace JPH; - transform new_transform{}; - auto& body_interface = m_physics_system->GetBodyInterface(); - - BodyID body_id = m_cached_body_ids[p_id]; - JPH::Vec3 pos = body_interface.GetPosition(body_id); - JPH::Quat rot = body_interface.GetRotation(body_id); - JPH::Vec3 rot_euler = rot.GetEulerAngles(); - - new_transform.position = to_vec3(pos); - new_transform.quaternion = to_vec4(rot); - new_transform.rotation = to_vec3(rot_euler); - - return new_transform; - } - - physics_body jolt_context::context_read_physics_body(uint32_t p_id) { - using namespace JPH; - auto& body_interface = m_physics_system->GetBodyInterface(); - - // TODO: Will need to change this because if this entity doesn't exist - // then it will be set to zeroes, gotta be careful about this - if (!m_cached_body_ids.contains(p_id)) { - return {}; - } - - auto body_id = m_cached_body_ids.at(p_id); - - physics_body body = { - .linear_velocity = - to_vec3(body_interface.GetLinearVelocity(body_id)), - .angular_velocity = - to_vec3(body_interface.GetAngularVelocity(body_id)), - .center_mass_position = - to_vec3(body_interface.GetCenterOfMassPosition(body_id)), - .gravity_factor = body_interface.GetGravityFactor(body_id), - .friction = body_interface.GetFriction(body_id), - .restitution = body_interface.GetRestitution(body_id), - }; - - return body; - } - - void jolt_context::destroy_bodies() { - auto& body_interface = m_physics_system->GetBodyInterface(); - - // Retrieve all body ID's to ensure that we do proper deactivation and - // post cleanup for the physics simulation - JPH::BodyIDVector all_body_ids; - m_physics_system->GetBodies(all_body_ids); - - if (!all_body_ids.empty()) { - - body_interface.DeactivateBodies( - all_body_ids.data(), static_cast(all_body_ids.size())); - - body_interface.RemoveBodies(all_body_ids.data(), - static_cast(all_body_ids.size())); - - body_interface.DestroyBodies(all_body_ids.data(), - static_cast(all_body_ids.size())); - - m_cached_body_ids.clear(); - } - } - - void jolt_context::linear_velocity(uint64_t p_id, - const glm::vec3& p_linear_velocity) { - using namespace JPH; - auto& body_interface = m_physics_system->GetBodyInterface(); - - body_interface.SetLinearVelocity(m_cached_body_ids.at(p_id), - jolt::to_vec3(p_linear_velocity)); - } - - void jolt_context::angular_velocity(uint64_t p_id, - const glm::vec3& p_angular_velocity) { - using namespace JPH; - auto& body_interface = m_physics_system->GetBodyInterface(); - BodyID body_id(p_id); - - body_interface.SetAngularVelocity(m_cached_body_ids.at(p_id), - jolt::to_vec3(p_angular_velocity)); - } - - void jolt_context::force(uint64_t p_id, const glm::vec3& p_force) { - using namespace JPH; - auto& body_interface = m_physics_system->GetBodyInterface(); - BodyID body_id(p_id); - - body_interface.AddForce(m_cached_body_ids.at(p_id), - jolt::to_vec3(p_force)); - } - - void jolt_context::add_force_and_torque(uint64_t p_id, - const glm::vec3& p_force, - const glm::vec3& p_torque) { - using namespace JPH; - auto& body_interface = m_physics_system->GetBodyInterface(); - - body_interface.AddForceAndTorque(m_cached_body_ids.at(p_id), - jolt::to_vec3(p_force), - jolt::to_vec3(p_torque)); - } - - void jolt_context::add_impulse(uint64_t p_id, const glm::vec3& p_impulse) { - using namespace JPH; - auto& body_interface = m_physics_system->GetBodyInterface(); - - body_interface.AddImpulse(m_cached_body_ids.at(p_id), - jolt::to_vec3(p_impulse)); - } - - void jolt_context::prepare_and_finalize() { - using namespace JPH; - - //! @brief We actually do not need to pass in the body ID's into - //! std::vector. Though we may need ways to store JPH::BodyID for - //! modifying specific bodies - JPH::BodyIDVector all_body_ids; - m_physics_system->GetBodies(all_body_ids); - - auto& body_interface = m_physics_system->GetBodyInterface(); - auto state = body_interface.AddBodiesPrepare( - all_body_ids.data(), static_cast(all_body_ids.size())); - body_interface.AddBodiesFinalize(all_body_ids.data(), - static_cast(all_body_ids.size()), - state, - JPH::EActivation::Activate); - } - - void jolt_context::update_simulation(float p_delta_time) { - float fixed_time_step = 1.0f / 60.0f; - int time_step = 1 + (int)(60 * fixed_time_step); - m_physics_system->Update(p_delta_time, - time_step, - m_temp_allocator.get(), - m_thread_system.get()); - } -} diff --git a/src/atlas/drivers/jolt-cpp/types.cpp b/src/atlas/drivers/jolt-cpp/types.cpp deleted file mode 100644 index 861e769b..00000000 --- a/src/atlas/drivers/jolt-cpp/types.cpp +++ /dev/null @@ -1,36 +0,0 @@ -#include -#include - -namespace atlas { - namespace jolt { - JPH::RVec3 to_rvec3(const glm::vec3& p_value) { - return { p_value.x, p_value.y, p_value.z }; - } - - JPH::Vec3 to_vec3(const glm::vec3& p_value) { - return { p_value.x, p_value.y, p_value.z }; - } - - JPH::Quat to_quat(const glm::vec4& q) { - return { q.x, q.y, q.z, q.w }; - } - - JPH::Quat to_quat(glm::quat& p_value) { - return JPH::Quat(p_value.w, p_value.x, p_value.y, p_value.z); - } - } - - glm::quat to_quat(const JPH::Quat& p_value) { - return glm::quat( - p_value.GetW(), p_value.GetX(), p_value.GetY(), p_value.GetZ()); - } - - glm::vec3 to_vec3(const JPH::Vec3& p_value) { - return vector3(p_value); - } - - glm::vec4 to_vec4(const JPH::Quat& p_value) { - return glm::vec4( - p_value.GetX(), p_value.GetY(), p_value.GetZ(), p_value.GetW()); - } -}; \ No newline at end of file diff --git a/src/atlas/drivers/render_context.cpp b/src/atlas/drivers/render_context.cpp deleted file mode 100644 index 7eff5ed6..00000000 --- a/src/atlas/drivers/render_context.cpp +++ /dev/null @@ -1,19 +0,0 @@ -#include -#include -#include - -namespace atlas { - - ref initialize_renderer( - const window_settings& p_window_extent, - uint32_t p_image_size, - const std::string& p_tag) { - switch (application::current_api()) { - case api::vulkan: - return create_ref( - p_window_extent, p_image_size, p_tag); - default: - return nullptr; - } - } -}; diff --git a/src/atlas/drivers/vulkan-cpp/mesh.cpp b/src/atlas/drivers/vulkan-cpp/mesh.cpp deleted file mode 100644 index 60d661aa..00000000 --- a/src/atlas/drivers/vulkan-cpp/mesh.cpp +++ /dev/null @@ -1,192 +0,0 @@ -#include -#include -#include -#define STB_IMAGE_IMPLEMENTATION -#define STB_IMAGE_WRITE_IMPLEMENTATION -#include -#include -#include - -namespace atlas::vk { - mesh::mesh(std::span<::vk::vertex_input> p_vertices, - std::span p_indices) { - m_physical = vk_context::physical_driver(); - m_device = vk_context::driver_context(); - ::vk::vertex_params vbo_settings = { .phsyical_memory_properties = - m_physical.memory_properties(), - .vertices = p_vertices }; - ::vk::index_params ibo_settings = { .phsyical_memory_properties = - m_physical.memory_properties(), - .indices = p_indices }; - m_vbo = ::vk::vertex_buffer(m_device, vbo_settings); - m_ibo = ::vk::index_buffer(m_device, ibo_settings); - } - - mesh::mesh(const std::filesystem::path& p_filename, bool p_flip) - : m_flip(p_flip) { - m_physical = vk_context::physical_driver(); - m_device = vk_context::driver_context(); - reload_mesh(p_filename); - } - - void mesh::reload_mesh(const std::filesystem::path& p_filename) { - console_log_info("Loading .obj file!!!"); - load_obj(p_filename); - } - - void mesh::load_obj(const std::filesystem::path& p_filename) { - tinyobj::attrib_t attrib; - std::vector shapes; - std::vector materials; - std::string warn, err; - - //! @note If we return the constructor then we can check if the mesh - //! loaded successfully - //! @note We also receive hints if the loading is successful! - //! @note Return default constructor automatically returns false means - //! that mesh will return the boolean as false because it wasnt - //! successful - if (!tinyobj::LoadObj(&attrib, - &shapes, - &materials, - &warn, - &err, - p_filename.string().c_str())) { - console_log_warn("Could not load model from path {}", - p_filename.string()); - m_model_loaded = false; - return; - } - - std::vector<::vk::vertex_input> vertices; - std::vector indices; - std::unordered_map<::vk::vertex_input, uint32_t> unique_vertices{}; - - // for (const auto& shape : shapes) { - for (size_t i = 0; i < shapes.size(); i++) { - auto shape = shapes[i]; - // for (const auto& index : shape.mesh.indices) { - for (size_t j = 0; j < shape.mesh.indices.size(); j++) { - auto index = shape.mesh.indices[j]; - ::vk::vertex_input vertex{}; - - if (!unique_vertices.contains(vertex)) { - unique_vertices[vertex] = - static_cast(vertices.size()); - vertices.push_back(vertex); - } - - if (index.vertex_index >= 0) { - vertex.position = { - attrib.vertices[3 * index.vertex_index + 0], - attrib.vertices[3 * index.vertex_index + 1], - attrib.vertices[3 * index.vertex_index + 2] - }; - - vertex.color = { - attrib.colors[3 * index.vertex_index + 0], - attrib.colors[3 * index.vertex_index + 1], - attrib.colors[3 * index.vertex_index + 2] - }; - } - - if (!attrib.normals.empty()) { - vertex.normals = { - attrib.normals[3 * index.normal_index + 0], - attrib.normals[3 * index.normal_index + 1], - attrib.normals[3 * index.normal_index + 2] - }; - } - if (!attrib.texcoords.empty()) { - glm::vec2 flipped_uv = { - attrib.texcoords - [static_cast(index.texcoord_index) * 2], - 1.0f - attrib.texcoords[static_cast( - index.texcoord_index) * - 2 + - 1], - }; - - glm::vec2 original_uv = { - attrib.texcoords - [static_cast(index.texcoord_index) * 2], - attrib.texcoords - [static_cast(index.texcoord_index) * 2 + - 1], - }; - - vertex.uv = m_flip ? flipped_uv : original_uv; - } - else { - vertex.uv = glm::vec2(0.f, 0.f); - } - - if (!unique_vertices.contains(vertex)) { - unique_vertices[vertex] = - static_cast(vertices.size()); - vertices.push_back(vertex); - } - - indices.push_back(unique_vertices[vertex]); - } - } - - ::vk::vertex_params vbo_settings = { .phsyical_memory_properties = - m_physical.memory_properties(), - .vertices = vertices }; - ::vk::index_params ibo_settings = { .phsyical_memory_properties = - m_physical.memory_properties(), - .indices = indices }; - m_vbo = ::vk::vertex_buffer(m_device, vbo_settings); - m_ibo = ::vk::index_buffer(m_device, ibo_settings); - m_model_loaded = true; - } - - void mesh::add_diffuse(const std::filesystem::path& p_path) { - ::vk::texture_info config_texture = { - .phsyical_memory_properties = m_physical.memory_properties(), - .filepath = p_path, - }; - m_diffuse = ::vk::texture(m_device, config_texture); - - if (!m_diffuse.loaded()) { - console_log_info("Diffuse Texture {} is NOT loaded!!!", - p_path.string()); - return; - } - } - - void mesh::add_specular(const std::filesystem::path& p_path) { - ::vk::texture_info config_texture = { .phsyical_memory_properties = - m_physical.memory_properties(), - .filepath = p_path }; - m_specular = ::vk::texture(m_device, config_texture); - - if (!m_specular.loaded()) { - console_log_error("Specular Texture {} is NOT loaded!!!", - p_path.string()); - return; - } - } - - void mesh::draw(const VkCommandBuffer& p_current) { - m_vbo.bind(p_current); - if (m_ibo.size() > 0) { - m_ibo.bind(p_current); - vkCmdDrawIndexed(p_current, m_ibo.size(), 1, 0, 0, 0); - } - else { - vkCmdDraw(p_current, m_vbo.size(), 1, 0, 0); - } - } - - void mesh::destroy() { - m_vbo.destroy(); - m_ibo.destroy(); - - m_diffuse.destroy(); - m_specular.destroy(); - m_geoemtry_ubo.destroy(); - m_material_ubo.destroy(); - } -}; \ No newline at end of file diff --git a/src/atlas/drivers/vulkan-cpp/shader_resource_group.cpp b/src/atlas/drivers/vulkan-cpp/shader_resource_group.cpp deleted file mode 100644 index aaa4fef8..00000000 --- a/src/atlas/drivers/vulkan-cpp/shader_resource_group.cpp +++ /dev/null @@ -1,346 +0,0 @@ -#include -#include -#include -#include -#include -#include -#include - -namespace atlas::vk { - - // Reading the raw .spv binaries - static std::vector read_raw_spirv(const std::string& p_file) { - std::vector out_buffer; - std::ifstream ins(p_file, std::ios::ate | std::ios::binary); - - if (!ins) { - throw std::runtime_error("Cannot load in .spv files!!"); - } - - uint32_t file_size = (uint32_t)ins.tellg(); - out_buffer.resize(file_size); - ins.seekg(0); - ins.read(out_buffer.data(), file_size); - return out_buffer; - } - - //! @brief Ensure file reads are valid before reading raw .spv binaries - static std::vector compile_binary_shader_source( - const ::vk::shader_source& p_shader_source) { - - if (!std::filesystem::is_regular_file(p_shader_source.filename)) { - throw std::runtime_error("Cannot load .spv file"); - } - - return read_raw_spirv(p_shader_source.filename); - } - - static std::string read_shader_source_code(const std::string& p_filename) { - std::ifstream ins(p_filename, std::ios::ate | std::ios::binary); - - if (!ins.is_open()) { - console_log_warn("Could not open filename = {}", p_filename); - return { 'a' }; - } - - size_t file_size = (size_t)ins.tellg(); - std::string output; - output.resize(file_size); - ins.seekg(0); - ins.read(output.data(), static_cast(file_size)); - - return output; - } - - /** - * compiles source code from the shader directly without needing manual - * recompilation - * - * shaderc requires these parameters to compile - * text_source_code: the std::string version of the entire source code to - * compile type: shader stage this shader corresponds to filename: input - * filename text entry_point: the entry point to this shader options: - * compiler-specific options to enable when compiling the shader sources - */ - static std::vector compile_source_from_file( - const ::vk::shader_source& p_shader_source) { - shaderc::CompileOptions options; - options.SetTargetEnvironment(shaderc_target_env_vulkan, - shaderc_env_version_vulkan_1_3); - options.SetWarningsAsErrors(); - - shaderc_shader_kind type; - - switch (p_shader_source.stage) { - case ::vk::shader_stage::vertex: - type = shaderc_glsl_vertex_shader; - break; - case ::vk::shader_stage::fragment: - type = shaderc_glsl_fragment_shader; - break; - default: - throw std::runtime_error("shader_stage unspecified!~!!"); - } - - shaderc::Compiler compiler; - std::string text_source_code = - read_shader_source_code(p_shader_source.filename); - - // Prints out the text of the shader source code - // console_log_warn("Source Text Code!!!"); - // console_log_info("{}", text_source_code); - shaderc::CompilationResult result = - compiler.CompileGlslToSpv(text_source_code, - type, - p_shader_source.filename.c_str(), - "main", - options); - - std::vector blob; - - if (result.GetCompilationStatus() != - shaderc_compilation_status_success) { - throw std::runtime_error( - std::format("Shader Compilation Error! Failed with reason {}\n{}", - p_shader_source.filename, - result.GetErrorMessage()) - .c_str()); - } - - for (auto blob_chunk : result) { - blob.push_back(blob_chunk); - } - - return blob; - } - - shader_resource_group::shader_resource_group( - const VkDevice& p_device, - const ::vk::shader_resource_info& p_info) - : m_device(p_device) { - - // We go through all of the specified shader source and their specific - // stage Compile them through shader compiler or if provided a .spv, - // then we compile and read in the stream of bytes directly - for (size_t i = 0; i < p_info.sources.size(); i++) { - const ::vk::shader_source shader_src = p_info.sources[i]; - std::filesystem::path filepath = - std::filesystem::path(shader_src.filename); - - if (filepath.extension().string() == ".spv") { - std::vector blob = - compile_binary_shader_source(shader_src); - - if (blob.empty()) { - m_resource_valid = false; - throw std::runtime_error("Cannot load in vector " - "blob of compiled down data!!!"); - } - - create_module(blob, shader_src); - } - else { - std::string text_source_code = - read_shader_source_code(filepath.string()); - std::vector blob = - compile_source_from_file(shader_src); - create_module(blob, shader_src); - } - } - - // This is a testing example for getting shaders hot-reloading - // m_watcher = create_ref("./experimental-shaders", - // [this](const wtr::event& e){ - // console_log_info("File {} Reload!!!", - // e.path_name.filename().string()); if (e.effect_type == - // wtr::event::effect_type::modify and e.path_type == - // wtr::event::path_type::file) { - // console_log_info("File has been modified!!"); - // // std::string fmt = std::format("experimental-shaders/{}", - // e.path_name.filename().string()); - // console_log_info("({}).contains = {}", - // e.path_name.filename().string(), - // m_modules.contains(e.path_name.filename().string())); - // if(m_modules.contains(e.path_name.filename().string())) { - // console_log_info("Reload has been requested!!!"); - // m_reload_requested = true; - // // reload - // ::vk::shader_source reload_src = { - // .filename = e.path_name.filename().string(), - // .stage = - // m_modules.at(e.path_name.filename().string()).stage - // }; - // reload_shader(reload_src); - - // } - // } - // else { - // console_log_info("File {} Could Not Be Reloaded!!!", - // e.path_name.filename().string()); - // } - // }); - - m_resource_valid = true; - } - - void shader_resource_group::reload_shader( - const ::vk::shader_source& p_source) { - console_log_info("p_source.filename = {}", p_source.filename); - if (m_modules[p_source.filename].module != nullptr) { - vkDestroyShaderModule( - m_device, m_modules[p_source.filename].module, nullptr); - } - - auto& handle = m_modules[p_source.filename]; - - std::filesystem::path filepath(p_source.filename); - std::string text_source_code = - read_shader_source_code(filepath.string()); - std::vector blob = compile_source_from_file(p_source); - std::span view_blob(blob.data(), blob.size()); - // create_module(blob, p_source); - VkShaderModuleCreateInfo shader_module_ci = { - .sType = VK_STRUCTURE_TYPE_SHADER_MODULE_CREATE_INFO, - .pNext = nullptr, - .codeSize = view_blob.size_bytes(), - .pCode = view_blob.data() - }; - - ::vk::vk_check(vkCreateShaderModule( - m_device, &shader_module_ci, nullptr, &handle.module), - "vkCreateShaderModule"); - } - - void shader_resource_group::create_module( - std::span p_blob, - const ::vk::shader_source& p_source) { - VkShaderModuleCreateInfo shader_module_ci = { - .sType = VK_STRUCTURE_TYPE_SHADER_MODULE_CREATE_INFO, - .pNext = nullptr, - .codeSize = p_blob.size(), - .pCode = reinterpret_cast(p_blob.data()) - }; - - std::filesystem::path filepath(p_source.filename); - std::string filename = filepath.filename().string(); - - // Setting m_shader_module_handlers[i]'s stage and the VkShaderModule - // handle altogether construct this beforehand and then we are going set - // that shader module - m_modules.emplace(filename, ::vk::shader_handle{}); - ::vk::vk_check( - vkCreateShaderModule( - m_device, &shader_module_ci, nullptr, &m_modules[filename].module), - "vkCreateShaderModule"); - m_modules[filename].stage = p_source.stage; - } - - void shader_resource_group::create_module( - std::span p_blob, - const ::vk::shader_source& p_source) { - VkShaderModuleCreateInfo shader_module_ci = { - .sType = VK_STRUCTURE_TYPE_SHADER_MODULE_CREATE_INFO, - .pNext = nullptr, - .codeSize = p_blob.size_bytes(), - .pCode = p_blob.data() - }; - - // console_log_info("map key = {}", p_source.filename); - std::filesystem::path filepath(p_source.filename); - - std::string filename = filepath.filename().string(); - - console_log_info("Key = {}", filename); - - // Setting m_shader_module_handlers[i]'s stage and the VkShaderModule - // handle altogether construct this beforehand and then we are going set - // that shader module - m_modules.emplace(filename, ::vk::shader_handle{}); - ::vk::vk_check( - vkCreateShaderModule( - m_device, &shader_module_ci, nullptr, &m_modules[filename].module), - "vkCreateShaderModule"); - m_modules[filename].stage = p_source.stage; - } - - std::vector<::vk::shader_handle> shader_resource_group::map_to_vector() - const { - // Using C++'s std::views to extract all of the values in - // unordered_map to a vector - // that gets passed to graphics pipeline - return (m_modules | std::views::values | - std::ranges::to()); - } - - void shader_resource_group::vertex_attributes( - std::span p_attributes) { - /* - -- These comments are a reminder to myself -- - - this function simplifies the need to separately define vertex - attributes and the vertex binding attributes as shown below: - - - vertex attributes specify the types of data within the vertex - - - vertex binding attribute specifies the rate of reading that data - layout specified by the vertex attributes - - - Interpret the following vertex attributes below with this shader - code with `layout(location = n)` specified where by default these are - set to binding zero by the shader - - layout(location = 0) in vec3 inPosition; - layout(location = 1) in vec3 inColor; - layout(location = 2) in vec3 inNormals; - layout(location = 3) in vec2 inTexCoords; - - m_shader_group.set_vertex_attributes(VkVertexInputAttributeDescription{ - { .location = 0, .binding = 0, .format = - VK_FORMAT_R32G32B32_SFLOAT, .offset = offsetof(vk::vertex, position), - }, { .location = 1, .binding = 0, .format = - VK_FORMAT_R32G32B32_SFLOAT, .offset = offsetof(vk::vertex, color), }, - { .location = 2, .binding = 0, .format = - VK_FORMAT_R32G32B32_SFLOAT, .offset = offsetof(vk::vertex, normals), - }, { .location = 3, .binding = 0, .format = VK_FORMAT_R32G32_SFLOAT, - .offset = offsetof(vk::vertex, uv), }, - }); - - m_shader_group.set_vertex_bind_attributes(VkVertexInputBindingDescription{ - {.binding = 0, .stride = sizeof(vk::vertex), .inputRate = - VK_VERTEX_INPUT_RATE_VERTEX,}, - }); - - Which gets handled in specifying the following below - */ - - m_vertex_binding_attributes.resize(p_attributes.size()); - - for (size_t i = 0; i < m_vertex_binding_attributes.size(); i++) { - // setting up vertex binding - const ::vk::vertex_attribute attribute = p_attributes[i]; - m_vertex_attributes.resize(attribute.entries.size()); - m_vertex_binding_attributes[i] = { .binding = attribute.binding, - .stride = attribute.stride, - .inputRate = to_input_rate( - attribute.input_rate) }; - - // then setting up the vertex attributes for the vertex data layouts - for (size_t j = 0; j < attribute.entries.size(); j++) { - const ::vk::vertex_attribute_entry entry = attribute.entries[j]; - m_vertex_attributes[j] = { .location = entry.location, - .binding = attribute.binding, - .format = static_cast( - entry.format), - .offset = entry.stride }; - } - } - } - - void shader_resource_group::destroy() { - - for (auto& [filename, shader_handle] : m_modules) { - if (shader_handle.module != nullptr) { - vkDestroyShaderModule(m_device, shader_handle.module, nullptr); - } - } - } -}; \ No newline at end of file diff --git a/src/atlas/drivers/vulkan-cpp/utilities.cpp b/src/atlas/drivers/vulkan-cpp/utilities.cpp deleted file mode 100644 index 8ed7c863..00000000 --- a/src/atlas/drivers/vulkan-cpp/utilities.cpp +++ /dev/null @@ -1,25 +0,0 @@ -#include -#include -#include -#include -#include - -namespace atlas::vk { - - void vk_check(const VkResult& p_result, - const std::string& p_name, - const std::source_location& p_source) { - if (p_result != VK_SUCCESS) { - console_log_error_tagged( - "vulkan", - "File {} on line {} failed VkResult check", - std::filesystem::relative(p_source.file_name()).string(), - p_source.line()); - console_log_error_tagged("vulkan", - "Current Function Location = {}", - p_source.function_name()); - console_log_error_tagged( - "vulkan", "{} VkResult returned: {}", p_name, (int)p_result); - } - } -}; \ No newline at end of file diff --git a/src/atlas/drivers/vulkan-cpp/vk_context.cpp b/src/atlas/drivers/vulkan-cpp/vk_context.cpp deleted file mode 100644 index 06e6e952..00000000 --- a/src/atlas/drivers/vulkan-cpp/vk_context.cpp +++ /dev/null @@ -1,170 +0,0 @@ -#include -#include -#include -#include - -namespace atlas::vk { - std::vector initialize_instance_extensions() { - std::vector extension_names; - - extension_names.emplace_back(VK_KHR_SURFACE_EXTENSION_NAME); - extension_names.emplace_back(VK_EXT_DEBUG_UTILS_EXTENSION_NAME); - - // An additional surface extension needs to be loaded. This extension is - // platform-specific so needs to be selected based on the platform the - // example is going to be deployed to. Preprocessor directives are used - // here to select the correct platform. -#ifdef VK_USE_PLATFORM_WIN32_KHR - extension_names.emplace_back(VK_KHR_WIN32_SURFACE_EXTENSION_NAME); -#endif -#ifdef VK_USE_PLATFORM_XLIB_KHR - extensionNames.emplace_back(VK_KHR_XLIB_SURFACE_EXTENSION_NAME); -#endif -#ifdef VK_USE_PLATFORM_XCB_KHR - extensionNames.emplace_back(VK_KHR_XCB_SURFACE_EXTENSION_NAME); -#endif -#ifdef VK_USE_PLATFORM_ANDROID_KHR - extensionNames.emplace_back(VK_KHR_ANDROID_SURFACE_EXTENSION_NAME); -#endif -#ifdef VK_USE_PLATFORM_WAYLAND_KHR - extensionNames.emplace_back(VK_KHR_WAYLAND_SURFACE_EXTENSION_NAME); -#endif -#ifdef VK_USE_PLATFORM_MACOS_MVK - extensionNames.emplace_back(VK_MVK_MACOS_SURFACE_EXTENSION_NAME); -#endif -#ifdef USE_PLATFORM_NULLWS - extensionNames.emplace_back(VK_KHR_DISPLAY_EXTENSION_NAME); -#endif - - return extension_names; - } - -#ifdef _DEBUG - const std::vector validation_layers = { - "VK_LAYER_KHRONOS_validation", - "VK_LAYER_KHRONOS_synchronization2" - }; - - static VKAPI_ATTR VkBool32 VKAPI_CALL debug_callback( - [[maybe_unused]] VkDebugUtilsMessageSeverityFlagBitsEXT - p_message_severity, - [[maybe_unused]] VkDebugUtilsMessageTypeFlagsEXT p_message_type, - const VkDebugUtilsMessengerCallbackDataEXT* p_callback_data, - [[maybe_unused]] void* p_user_data) { - console_log_trace("validation layer:\t\t{}", p_callback_data->pMessage); - return false; - } -#endif - - vk_context* vk_context::s_instance = nullptr; - - vk_context::vk_context(const std::string& p_tag) { - console_log_manager::create_new_logger(p_tag); - - VkApplicationInfo app_info = { - .sType = VK_STRUCTURE_TYPE_APPLICATION_INFO, - .pNext = nullptr, - .applicationVersion = 1, - .pEngineName = "TheAtlasEngine", - .engineVersion = 1, - .apiVersion = VK_API_VERSION_1_3, - }; - - VkInstanceCreateInfo create_info = { - .sType = VK_STRUCTURE_TYPE_INSTANCE_CREATE_INFO, - .pNext = nullptr, - .flags = 0, - .pApplicationInfo = &app_info - }; - - //! @note Setting up the required extensions for vulkan - std::vector extensions = initialize_instance_extensions(); -#if _DEBUG - extensions.push_back("VK_EXT_debug_utils"); -#endif - create_info.enabledExtensionCount = - static_cast(extensions.size()); - create_info.ppEnabledExtensionNames = extensions.data(); -#ifdef _DEBUG - // by default we enable validation layers used for debugging! - create_info.enabledLayerCount = - static_cast(validation_layers.size()); - create_info.ppEnabledLayerNames = validation_layers.data(); - - // printing out available validation layers - uint32_t layer_count; - std::vector available_validation_layers; - vkEnumerateInstanceLayerProperties(&layer_count, nullptr); - - available_validation_layers.resize(layer_count); - vkEnumerateInstanceLayerProperties(&layer_count, - available_validation_layers.data()); - - console_log_trace("================================================"); - console_log_trace("\tValidation Layers Available"); - console_log_trace("================================================"); - for (VkLayerProperties properties : available_validation_layers) { - console_log_trace("Validation Layer:\t\t{}", properties.layerName); - console_log_trace("Description\t\t{}", properties.description); - console_log_trace("Version\t\t\t{}", (int)properties.specVersion); - } - - console_log_trace("\n"); - console_log_trace("================================================\n"); - - VkDebugUtilsMessengerCreateInfoEXT debug_create_info = { - .sType = VK_STRUCTURE_TYPE_DEBUG_UTILS_MESSENGER_CREATE_INFO_EXT, - .messageSeverity = VK_DEBUG_UTILS_MESSAGE_SEVERITY_VERBOSE_BIT_EXT | - VK_DEBUG_UTILS_MESSAGE_SEVERITY_WARNING_BIT_EXT | - VK_DEBUG_UTILS_MESSAGE_SEVERITY_ERROR_BIT_EXT, - .messageType = VK_DEBUG_UTILS_MESSAGE_TYPE_GENERAL_BIT_EXT | - VK_DEBUG_UTILS_MESSAGE_TYPE_VALIDATION_BIT_EXT | - VK_DEBUG_UTILS_MESSAGE_TYPE_PERFORMANCE_BIT_EXT, - .pfnUserCallback = debug_callback, - }; - - create_info.pNext = - (VkDebugUtilsMessengerCreateInfoEXT*)&debug_create_info; -#else - create_info.enabledLayerCount = 0; - create_info.ppEnabledLayerNames = nullptr; - create_info.pNext = nullptr; -#endif - vk_check(vkCreateInstance(&create_info, nullptr, &m_instance_handler), - "vkCreateInstance"); - -#if _DEBUG - // This needs to be created after the VkInstance is or else it wont be - // applied the debug information during validation layer error message - // execution - m_vk_set_debug_utils_object_name_ext = - reinterpret_cast( - vkGetInstanceProcAddr(m_instance_handler, - "vkSetDebugUtilsObjectNameEXT")); -#endif - s_instance = this; - - m_physical = vk_physical_driver(m_instance_handler); - m_driver = vk_driver(m_physical); - } - - VkInstance vk_context::handler() { - return s_instance->m_instance_handler; - } - - void vk_context::resource_free(std::function&& p_resource) { - m_resources_free.push_back(p_resource); - } - - void vk_context::submit_resource_free(std::function&& p_resource) { - s_instance->m_resources_free.push_back(p_resource); - } - - void vk_context::destroy_context() { - for (auto& callback : m_resources_free) { - callback(); - } - - m_driver.destroy(); - } -}; diff --git a/src/atlas/drivers/vulkan-cpp/vk_driver.cpp b/src/atlas/drivers/vulkan-cpp/vk_driver.cpp deleted file mode 100644 index 5207712f..00000000 --- a/src/atlas/drivers/vulkan-cpp/vk_driver.cpp +++ /dev/null @@ -1,123 +0,0 @@ -#include -#include -#include -#include -#include - -namespace atlas::vk { - static VkFormat search_supported_depth_format( - const VkPhysicalDevice& p_physical, - std::span p_formats, - VkImageTiling p_tiling, - VkFormatFeatureFlags p_feature_flag) { - VkFormat format = VK_FORMAT_UNDEFINED; - - for (size_t i = 0; i < p_formats.size(); i++) { - VkFormat current_format = p_formats[i]; - VkFormatProperties format_properties; - vkGetPhysicalDeviceFormatProperties( - p_physical, current_format, &format_properties); - - if (p_tiling == VK_IMAGE_TILING_LINEAR) { - if (format_properties.linearTilingFeatures & p_feature_flag) { - format = current_format; - } - } - else if (p_tiling == VK_IMAGE_TILING_OPTIMAL and - format_properties.optimalTilingFeatures & p_feature_flag) { - format = current_format; - } - } - - return format; - } - - static VkFormat search_depth_format(const VkPhysicalDevice& p_physical) { - std::vector candidate_formats = { - VK_FORMAT_D32_SFLOAT, - VK_FORMAT_D32_SFLOAT_S8_UINT, - VK_FORMAT_D24_UNORM_S8_UINT - }; - - VkFormat format = search_supported_depth_format( - p_physical, - candidate_formats, - VK_IMAGE_TILING_OPTIMAL, - VK_FORMAT_FEATURE_DEPTH_STENCIL_ATTACHMENT_BIT); - return format; - } - - vk_driver::vk_driver(const vk_physical_driver& p_physical) - : m_physical(p_physical) { - m_depth_format_selected = search_depth_format(m_physical); - - float queue_priority[1] = { 0.0f }; - - std::vector device_extension = { - VK_KHR_SWAPCHAIN_EXTENSION_NAME - }; - - uint32_t graphics_index = - m_physical.read_queue_family_indices().graphics; - - VkDeviceQueueCreateInfo queue_create_info = { - .sType = VK_STRUCTURE_TYPE_DEVICE_QUEUE_CREATE_INFO, - .pNext = nullptr, - .flags = 0, - .queueFamilyIndex = graphics_index, - .queueCount = 1, - .pQueuePriorities = queue_priority, - }; - - VkDeviceCreateInfo create_info = { - .sType = VK_STRUCTURE_TYPE_DEVICE_CREATE_INFO, - .pNext = nullptr, - .flags = 0, - .queueCreateInfoCount = 1, - .pQueueCreateInfos = &queue_create_info, - .enabledLayerCount = 0, - .ppEnabledLayerNames = nullptr, - .enabledExtensionCount = - static_cast(device_extension.size()), - .ppEnabledExtensionNames = device_extension.data(), - }; - - VkPhysicalDeviceFeatures features; - vkGetPhysicalDeviceFeatures(m_physical, &features); - features.robustBufferAccess = false; - create_info.pEnabledFeatures = &features; - - vk_check(vkCreateDevice(m_physical, &create_info, nullptr, &m_driver), - "vkCreateDevice"); - - vkGetDeviceQueue( - m_driver, graphics_index, 0, &m_device_queues.graphics_queue); - } - - //! @note Returns -1 if there are no flags available/compatible/valid - uint32_t vk_driver::select_memory_type( - uint32_t p_type_filter, - VkMemoryPropertyFlags p_property_flag) { - VkPhysicalDeviceMemoryProperties mem_props; - vkGetPhysicalDeviceMemoryProperties(m_physical, &mem_props); - - for (uint32_t i = 0; i < mem_props.memoryTypeCount; i++) { - if ((p_type_filter & (1 << i)) and - (mem_props.memoryTypes[i].propertyFlags & p_property_flag) == - p_property_flag) { - return i; - } - } - - return -1; - } - - VkFormat vk_driver::depth_format() const { - return m_depth_format_selected; - } - - void vk_driver::destroy() { - vkDeviceWaitIdle(m_driver); - vkDestroyDevice(m_driver, nullptr); - } -}; \ No newline at end of file diff --git a/src/atlas/drivers/vulkan-cpp/vk_imgui.cpp b/src/atlas/drivers/vulkan-cpp/vk_imgui.cpp deleted file mode 100644 index 18deb51a..00000000 --- a/src/atlas/drivers/vulkan-cpp/vk_imgui.cpp +++ /dev/null @@ -1,294 +0,0 @@ -#include -#include -#include -#include -#include -#include -#include - -namespace atlas::vk { - - static void im_gui_layout_color_modification() { - auto& colors = ImGui::GetStyle().Colors; // @note Colors is ImVec4 - - colors[ImGuiCol_WindowBg] = ImVec4{ 0.1f, 0.105f, 0.11f, 1.0f }; - - // Headers - colors[ImGuiCol_Header] = ImVec4{ 0.2f, 0.205f, 0.21f, 1.0f }; - colors[ImGuiCol_HeaderHovered] = ImVec4{ 0.3f, 0.305f, 0.31f, 1.0f }; - colors[ImGuiCol_HeaderActive] = ImVec4{ 0.15f, 0.1505f, 0.151f, 1.0f }; - - // Buttons - colors[ImGuiCol_Button] = ImVec4{ 0.2f, 0.205f, 0.21f, 1.0f }; - colors[ImGuiCol_ButtonHovered] = ImVec4{ 0.3f, 0.305f, 0.31f, 1.0f }; - colors[ImGuiCol_ButtonActive] = ImVec4{ 0.15f, 0.1505f, 0.151f, 1.0f }; - - // Frame BG - colors[ImGuiCol_FrameBg] = ImVec4{ 0.2f, 0.205f, 0.21f, 1.0f }; - colors[ImGuiCol_FrameBgHovered] = ImVec4{ 0.3f, 0.305f, 0.31f, 1.0f }; - colors[ImGuiCol_FrameBgActive] = ImVec4{ 0.15f, 0.1505f, 0.151f, 1.0f }; - - // Tabs - colors[ImGuiCol_Tab] = ImVec4{ 0.15f, 0.1505f, 0.151f, 1.0f }; - colors[ImGuiCol_TabHovered] = ImVec4{ 0.38f, 0.3805f, 0.381f, 1.0f }; - colors[ImGuiCol_TabActive] = ImVec4{ 0.28f, 0.2805f, 0.281f, 1.0f }; - colors[ImGuiCol_TabUnfocused] = ImVec4{ 0.15f, 0.1505f, 0.15f, 1.0f }; - colors[ImGuiCol_TabUnfocusedActive] = - ImVec4{ 0.2f, 0.205f, 0.21f, 1.0f }; - - // Titles - colors[ImGuiCol_TitleBg] = ImVec4{ 0.15f, 0.1505f, 0.151f, 1.0f }; - colors[ImGuiCol_TitleBgActive] = ImVec4{ 0.15f, 0.1505f, 0.15f, 1.0f }; - colors[ImGuiCol_TitleBgCollapsed] = - ImVec4{ 0.1f, 0.150f, 0.951f, 1.0f }; - } - - imgui_context::imgui_context(const ref& p_window_ctx) { - m_instance = vk_context::handler(); - m_physical = vk_context::physical_driver(); - m_driver = vk_context::driver_context(); - - m_current_swapchain_handler = p_window_ctx->current_swapchain(); - - // Setting up imgui - IMGUI_CHECKVERSION(); - ImGui::CreateContext(); - ImGuiIO& io = ImGui::GetIO(); - - io.ConfigFlags |= - ImGuiConfigFlags_NavEnableKeyboard; // Enable Keyboard Controls - // io.ConfigFlags |= ImGuiConfigFlags_NavEnableGamepad; // Enable - // Gamepad Controls - io.ConfigFlags |= ImGuiConfigFlags_DockingEnable; // Enable Docking - io.ConfigFlags |= - ImGuiConfigFlags_ViewportsEnable; // Enable Multi-Viewport / Platform - // Windows - - // io.ConfigViewportsNoAutoMerge = true; - // io.ConfigViewportsNoAutoMerge = true; - // io.ConfigViewportsNoTaskBarIcon = true; - - // Setup Dear ImGui style - // ImGui::StyleColorsDark(); - // ImGui::StyleColorsClassic(); - im_gui_layout_color_modification(); - - ImGuiStyle& style = ImGui::GetStyle(); - if (io.ConfigFlags & ImGuiConfigFlags_ViewportsEnable) { - style.WindowRounding = 0.0f; - style.Colors[ImGuiCol_WindowBg].w = 1.0f; - } - - m_viewport_command_buffers.resize( - p_window_ctx->current_swapchain().image_size()); - - for (size_t i = 0; i < m_viewport_command_buffers.size(); i++) { - ::vk::command_params settings = { - .levels = ::vk::command_levels::primary, - // .queue_index = enumerate_swapchain_settings.present_index, - .queue_index = 0, - .flags = ::vk::command_pool_flags::reset, - }; - m_viewport_command_buffers[i] = - ::vk::command_buffer(m_driver, settings); - } - - // ::vk::descriptor_res - // m_imgui_descriptor = ::vk::descriptor_resource(m_driver, {}); - // 1: create descriptor pool for IMGUI - // the size of the pool is very oversize, but it's copied from imgui - // demo itself. - std::array pool_sizes = { - VkDescriptorPoolSize{ VK_DESCRIPTOR_TYPE_SAMPLER, 100 }, - VkDescriptorPoolSize{ VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, - 100 }, - VkDescriptorPoolSize{ VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE, 100 }, - VkDescriptorPoolSize{ VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, 100 }, - VkDescriptorPoolSize{ VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER, - 100 }, - VkDescriptorPoolSize{ VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER, - 100 }, - VkDescriptorPoolSize{ VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, 100 }, - VkDescriptorPoolSize{ VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, 100 }, - VkDescriptorPoolSize{ VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC, - 100 }, - VkDescriptorPoolSize{ VK_DESCRIPTOR_TYPE_STORAGE_BUFFER_DYNAMIC, - 100 }, - VkDescriptorPoolSize{ VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT, 100 } - }; - - VkDescriptorPoolCreateInfo desc_pool_create_info = { - .sType = VK_STRUCTURE_TYPE_DESCRIPTOR_POOL_CREATE_INFO, - .pNext = nullptr, - .flags = VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT, - .maxSets = static_cast(1000 * pool_sizes.size()), - // .poolSizeCount = (uint32_t)std::size(pool_sizes), - .poolSizeCount = static_cast(pool_sizes.size()), - .pPoolSizes = pool_sizes.data() - }; - - // VkDescriptorPool imgui_pool; - vk::vk_check(vkCreateDescriptorPool( - m_driver, &desc_pool_create_info, nullptr, &m_desc_pool), - "vkCreateDescriptorPool"); - - create(*p_window_ctx, - p_window_ctx->current_swapchain().image_size(), - p_window_ctx->current_swapchain().swapchain_renderpass()); - } - - void imgui_context::create(GLFWwindow* p_window_handler, - const uint32_t& p_image_size, - const VkRenderPass& p_current_renderpass) { - ImGui_ImplGlfw_InitForVulkan(p_window_handler, true); - ImGui_ImplVulkan_InitInfo init_info = {}; - init_info.Instance = m_instance; - init_info.PhysicalDevice = m_physical; - init_info.Device = m_driver; - init_info.Queue = m_driver.graphics_queue(); - init_info.RenderPass = p_current_renderpass; - init_info.PipelineCache = nullptr; - init_info.DescriptorPool = m_desc_pool; - init_info.MinImageCount = 2; - init_info.ImageCount = p_image_size; - init_info.UseDynamicRendering = false; - init_info.MSAASamples = VK_SAMPLE_COUNT_1_BIT; - ImGui_ImplVulkan_Init(&init_info); - } - - void imgui_context::begin(const VkCommandBuffer& p_current, - const uint32_t& p_frame_index) { - ImGui_ImplVulkan_NewFrame(); - ImGui_ImplGlfw_NewFrame(); - ImGui::NewFrame(); - - m_current_frame_index = p_frame_index; - m_current = p_current; - } - - void imgui_context::end() { - ImGui::Render(); - - ImDrawData* draw_data = ImGui::GetDrawData(); - ImGui_ImplVulkan_RenderDrawData(draw_data, m_current); - - ImGuiIO& io = ImGui::GetIO(); - if (io.ConfigFlags & ImGuiConfigFlags_ViewportsEnable) { - ImGui::UpdatePlatformWindows(); - ImGui::RenderPlatformWindowsDefault(); - } - } - - void imgui_context::draw_hud(const hud_data& p_hud_data, - const window_settings& p_settings) { - ImGuiIO& io = ImGui::GetIO(); - - // --- Top-Left HUD (FPS and Weapon) --- - ImGui::SetNextWindowPos(ImVec2(10, 10), - ImGuiCond_Always); // Fixed position - ImGui::SetNextWindowBgAlpha(0.0f); // Transparent background - - ImGuiWindowFlags hud_flags = - ImGuiWindowFlags_NoDecoration | // No title bar, borders, etc. - ImGuiWindowFlags_NoMove | // Cannot be moved by user - ImGuiWindowFlags_NoResize | // Cannot be resized by user - ImGuiWindowFlags_NoSavedSettings | // Don't save position/size to .ini - ImGuiWindowFlags_NoInputs; // Does not block mouse/keyboard input - - if (ImGui::Begin("TopLeftHUD", nullptr, hud_flags)) { - ImGui::Text("FPS: %.1f", p_hud_data.fps); - ImGui::Text("Weapon: %s", p_hud_data.currentWeapon.c_str()); - // ImGui::Text("Health:"); - // Use a progress bar for health - // ImGui::ProgressBar(p_hud_data.playerHealth / 100.0f, ImVec2(-1, - // 0), "#Health"); // -1 width fills available space - ImGui::Text("Health: %.1f", p_hud_data.playerHealth); - ImGui::ProgressBar(p_hud_data.playerHealth / 100.0f, - ImVec2(-1, 0)); // No overlay text here - } - ImGui::End(); - - // --- Health Bar (Bottom-Left) --- - ImGui::SetNextWindowPos(ImVec2(10, (float)p_settings.width - 50), - ImGuiCond_Always); - ImGui::SetNextWindowSize(ImVec2(200, 40), - ImGuiCond_Always); // Fixed size - ImGui::SetNextWindowBgAlpha(0.0f); - - // if (ImGui::Begin("HealthBar", nullptr, hud_flags)) { - // ImGui::Text("Health:"); - // // Use a progress bar for health - // ImGui::ProgressBar(p_hud_data.playerHealth / 100.0f, ImVec2(-1, - // 0), "HP"); // -1 width fills available space - // } - // ImGui::End(); - - // --- Score (Top-Right) --- - // Position it relative to the right edge - ImGui::SetNextWindowPos(ImVec2((float)p_settings.width - 150, 10), - ImGuiCond_Always); - ImGui::SetNextWindowSize( - ImVec2(140, 0), - ImGuiCond_Always); // 0 height means auto-size vertically - ImGui::SetNextWindowBgAlpha(0.0f); - - if (ImGui::Begin("ScoreDisplay", nullptr, hud_flags)) { - ImGui::SetCursorPosX( - ImGui::GetWindowSize().x - - ImGui::CalcTextSize( - std::to_string(p_hud_data.playerScore).c_str()) - .x - - ImGui::GetStyle().WindowPadding.x); - ImGui::Text("Score: %d", p_hud_data.playerScore); - } - ImGui::End(); - - // --- Crosshair (Custom Drawing - Optional) --- - // If you want a more custom crosshair, you might use ImDrawList. - // This is more advanced and often handled by your game's rendering - // pipeline directly, but ImGui can draw simple shapes. To draw on the - // main viewport, you can get the foreground draw list of the main - // viewport. - ImDrawList* draw_list = - ImGui::GetBackgroundDrawList(); // Or ImGui::GetForegroundDrawList() - if (draw_list) { - ImVec2 center = - ImVec2(io.DisplaySize.x * 0.5f, io.DisplaySize.y * 0.5f); - float crosshair_size = 10.0f; - float gap = 2.0f; - ImU32 crosshair_color = IM_COL32(255, 255, 255, 255); // White - - // Horizontal lines - draw_list->AddLine( - ImVec2(center.x - crosshair_size - gap, center.y), - ImVec2(center.x - gap, center.y), - crosshair_color); - draw_list->AddLine( - ImVec2(center.x + gap, center.y), - ImVec2(center.x + crosshair_size + gap, center.y), - crosshair_color); - - // Vertical lines - draw_list->AddLine( - ImVec2(center.x, center.y - crosshair_size - gap), - ImVec2(center.x, center.y - gap), - crosshair_color); - draw_list->AddLine( - ImVec2(center.x, center.y + gap), - ImVec2(center.x, center.y + crosshair_size + gap), - crosshair_color); - } - } - - void imgui_context::destroy() { - ImGui_ImplVulkan_Shutdown(); - vkDestroyDescriptorPool(m_driver, m_desc_pool, nullptr); - - for (auto& command_buffer : m_viewport_command_buffers) { - command_buffer.destroy(); - } - - ImGui_ImplGlfw_Shutdown(); - ImGui::DestroyContext(); - } -}; \ No newline at end of file diff --git a/src/atlas/drivers/vulkan-cpp/vk_physical_driver.cpp b/src/atlas/drivers/vulkan-cpp/vk_physical_driver.cpp deleted file mode 100644 index 3dc6945d..00000000 --- a/src/atlas/drivers/vulkan-cpp/vk_physical_driver.cpp +++ /dev/null @@ -1,128 +0,0 @@ -#include -#include -#include - -namespace atlas::vk { - - vk_physical_driver::vk_physical_driver(const VkInstance& p_instance) { - - uint32_t device_count = 0; - vkEnumeratePhysicalDevices(p_instance, &device_count, nullptr); - - if (device_count == 0) { - console_log_fatal("Device Count is {} and no devices found!!!", - device_count); - return; - } - - std::vector physical_drivers(device_count); - vkEnumeratePhysicalDevices( - p_instance, &device_count, physical_drivers.data()); - - for (const auto& device : physical_drivers) { - VkPhysicalDeviceProperties device_properties; - VkPhysicalDeviceFeatures device_features; - vkGetPhysicalDeviceProperties(device, &device_properties); - vkGetPhysicalDeviceFeatures(device, &device_features); - if (device_properties.deviceType == - VK_PHYSICAL_DEVICE_TYPE_DISCRETE_GPU) { - m_physical_driver = device; - break; - } - } - - uint32_t queue_family_count = 0; - vkGetPhysicalDeviceQueueFamilyProperties( - m_physical_driver, &queue_family_count, nullptr); - m_queue_family_properties.resize(queue_family_count); - - vkGetPhysicalDeviceQueueFamilyProperties( - m_physical_driver, - &queue_family_count, - m_queue_family_properties.data()); - - m_queue_indices = select_queue_family_indices(); - } - - vk_physical_driver::~vk_physical_driver() = default; - - surface_properties vk_physical_driver::get_surface_properties( - const VkSurfaceKHR& p_surface) { - vk_check(vkGetPhysicalDeviceSurfaceCapabilitiesKHR( - m_physical_driver, - p_surface, - &m_surface_properties.surface_capabilities), - "vkGetPhysicalDeviceSurfaceCapabilitiesKHR"); - - uint32_t format_count = 0; - std::vector formats; - vk_check(vkGetPhysicalDeviceSurfaceFormatsKHR( - m_physical_driver, p_surface, &format_count, nullptr), - "vkGetPhysicalDeviceSurfaceFormatsKHR"); - - formats.resize(format_count); - - vk_check(vkGetPhysicalDeviceSurfaceFormatsKHR( - m_physical_driver, p_surface, &format_count, formats.data()), - "vkGetPhysicalDeviceSurfaceFormatsKHR"); - - for (const auto& format : formats) { - if (format.format == VK_FORMAT_B8G8R8A8_SRGB && - format.colorSpace == VK_COLOR_SPACE_SRGB_NONLINEAR_KHR) { - m_surface_properties.surface_format = format; - } - } - - m_surface_properties.surface_format = formats[0]; - - return m_surface_properties; - } - - vk_physical_driver::queue_family_indices - vk_physical_driver::select_queue_family_indices() { - VkPhysicalDeviceMemoryProperties physical_device_memory_properties; - vkGetPhysicalDeviceMemoryProperties(m_physical_driver, - &physical_device_memory_properties); - vk_physical_driver::queue_family_indices indices; - int i = 0; - - for (const auto& queue_family : m_queue_family_properties) { - if (queue_family.queueFlags & VK_QUEUE_GRAPHICS_BIT) { - indices.graphics = i; - break; - } - i++; - } - - return indices; - } - - uint32_t vk_physical_driver::read_presentation_index( - const VkSurfaceKHR& p_surface) { - uint32_t presentation_index = -1; - VkBool32 compatible = VK_FALSE; - uint32_t i = 0; - for (const auto& queue_family : m_queue_family_properties) { - if (queue_family.queueFlags & VK_QUEUE_GRAPHICS_BIT) { - vk_check(vkGetPhysicalDeviceSurfaceSupportKHR( - m_physical_driver, i, p_surface, &compatible), - "vkGetPhysicalDeviceSurfaceSupportKHR"); - - if (compatible) { - presentation_index = i; - } - } - i++; - } - - return presentation_index; - } - - VkPhysicalDeviceMemoryProperties vk_physical_driver::memory_properties() - const { - VkPhysicalDeviceMemoryProperties physical_memory_properties; - vkGetPhysicalDeviceMemoryProperties(m_physical_driver, - &physical_memory_properties); - return physical_memory_properties; - } -}; \ No newline at end of file diff --git a/src/atlas/drivers/vulkan-cpp/vk_renderer.cpp b/src/atlas/drivers/vulkan-cpp/vk_renderer.cpp deleted file mode 100644 index bc79f807..00000000 --- a/src/atlas/drivers/vulkan-cpp/vk_renderer.cpp +++ /dev/null @@ -1,561 +0,0 @@ -#include -#include -#include -#include -#include -#include - -namespace atlas::vk { - - vk_renderer::vk_renderer(const window_settings& p_settings, - uint32_t p_image_size, - const std::string& p_tag) { - console_log_manager::create_new_logger(p_tag); - m_device = vk_context::driver_context(); - m_physical = vk_context::physical_driver(); - m_window_extent = p_settings; - - m_image_count = p_image_size; -#ifdef USE_SHADERC - std::array<::vk::shader_source, 2> shader_sources = { - ::vk::shader_source{ - "experimental-shaders/test.vert", - ::vk::shader_stage::vertex, - }, - ::vk::shader_source{ - "experimental-shaders/test.frag", - ::vk::shader_stage::fragment, - } - }; -#else - std::array<::vk::shader_source, 2> shader_sources = { - ::vk::shader_source{ - "experimental-shaders/test.vert.spv", - ::vk::shader_stage::vertex, - }, - ::vk::shader_source{ - "experimental-shaders/test.frag.spv", - ::vk::shader_stage::fragment, - } - }; -#endif - - std::array<::vk::vertex_attribute_entry, 4> attribute_entries = { - ::vk::vertex_attribute_entry{ - .location = 0, - .format = ::vk::format::rgb32_sfloat, - .stride = offsetof(vk::vertex_input, position), - }, - ::vk::vertex_attribute_entry{ - .location = 1, - .format = ::vk::format::rgb32_sfloat, - .stride = offsetof(vk::vertex_input, color), - }, - ::vk::vertex_attribute_entry{ - .location = 2, - .format = ::vk::format::rgb32_sfloat, - .stride = offsetof(vertex_input, normals), - }, - ::vk::vertex_attribute_entry{ - .location = 3, - .format = ::vk::format::rg32_sfloat, - .stride = offsetof(vertex_input, uv), - } - }; - - std::array<::vk::vertex_attribute, 1> attribute = { - ::vk::vertex_attribute{ - // layout (set = 0, binding = 0) - .binding = 0, - .entries = attribute_entries, - .stride = sizeof(vk::vertex_input), - .input_rate = ::vk::input_rate::vertex, - }, - }; - - ::vk::shader_resource_info shader_info = { - .sources = shader_sources, - }; - - try { - m_shader_group = shader_resource_group(m_device, shader_info); - m_shader_group.vertex_attributes(attribute); - } - catch (std::runtime_error& e) { - console_log_error("Compilation Error!!"); - console_log_error("{}", e.what()); - } - // Setting global descriptor set 0 - std::vector<::vk::descriptor_entry> set0_entries = { - ::vk::descriptor_entry{ - // specifies "layout (set = 0, binding = 0) uniform GlobalUbo" - .type = ::vk::buffer::uniform, - .binding_point = { - .binding = 0, - .stage = ::vk::shader_stage::vertex, - }, - .descriptor_count = 1, - }, - ::vk::descriptor_entry{ - // specifies "layout (set = 0, binding = 1) uniform light_ubo" - .type = ::vk::buffer::uniform, - .binding_point = { - .binding = 1, - .stage = ::vk::shader_stage::fragment, - }, - .descriptor_count = 1, - }, - }; - - // uint32_t image_count = image_count; - ::vk::descriptor_layout set0_layout = { - .slot = 0, - .max_sets = m_image_count, - .entries = set0_entries, - }; - m_global_descriptors = ::vk::descriptor_resource(m_device, set0_layout); - - ::vk::uniform_params global_info = { - .phsyical_memory_properties = m_physical.memory_properties(), - .size_bytes = sizeof(global_ubo), - .debug_name = "\nm_global_uniforms\n", - .vkSetDebugUtilsObjectNameEXT = vk_context::get_debug_object_name() - }; - m_global_uniforms = ::vk::uniform_buffer(m_device, global_info); - - // setting up our light uniforms as the global uniforms rather then - // per-object basis - ::vk::uniform_params light_ubo_params = { - .phsyical_memory_properties = m_physical.memory_properties(), - .size_bytes = sizeof(light_scene_ubo), - }; - m_point_light_uniforms = - ::vk::uniform_buffer(m_device, light_ubo_params); - - std::array<::vk::write_buffer, 1> binding0_uniforms = { - ::vk::write_buffer{ - .buffer = m_global_uniforms, - .offset = 0, - .range = m_global_uniforms.size_bytes(), - }, - }; - - std::array<::vk::write_buffer, 1> binding1_uniforms = { - ::vk::write_buffer{ - .buffer = m_point_light_uniforms, - .offset = 0, - .range = m_point_light_uniforms.size_bytes(), - }, - }; - - std::array<::vk::write_buffer_descriptor, 2> set0_write_buffers = { - ::vk::write_buffer_descriptor{ - .dst_binding = 0, - .uniforms = binding0_uniforms, - }, - ::vk::write_buffer_descriptor{ - .dst_binding = 1, - .uniforms = binding1_uniforms, - } - }; - m_global_descriptors.update(set0_write_buffers); - - m_sets_layouts = { - m_global_descriptors.layout(), - }; - - ::vk::image_extent extent = { - .width = 1, - .height = 1, - }; - m_white_texture = - ::vk::texture(m_device, extent, m_physical.memory_properties()); - - vk_context::submit_resource_free([this]() { - m_white_texture.destroy(); - m_shader_group.destroy(); - m_global_descriptors.destroy(); - m_global_uniforms.destroy(); - m_point_light_uniforms.destroy(); - for (auto& [id, mesh] : m_cached_meshes) { - console_log_trace("Entity \"{}\" Destroyed in vk_renderer!!!", - id); - mesh.destroy(); - } - - for (auto& [id, uniform] : m_mesh_geometry_set) { - uniform.destroy(); - } - - for (auto& [id, material_uniform] : m_mesh_material_set) { - material_uniform.destroy(); - } - - for (auto& [key, descriptor_map] : m_mesh_descriptors) { - for (auto& [descriptor_type, descriptor] : descriptor_map) { - descriptor.destroy(); - } - } - m_main_pipeline.destroy(); - }); - } - - void vk_renderer::current_scene(ref p_scene) { - m_current_scene = p_scene; - } - - void vk_renderer::background_color(const std::array& p_color) { - m_color = { - { p_color.at(0), p_color.at(1), p_color.at(2), p_color.at(3) } - }; - } - - void vk_renderer::preload_assets(const VkRenderPass& p_renderpass) { - m_final_renderpass = p_renderpass; - // set 1 -- material uniforms - // ref current_world = system_registry::get_world("Editor - // World"); ref current_scene = - // current_world->get_scene("LevelScene"); - - flecs::query<> caching = - m_current_scene->query_builder().build(); - - caching.each([this](flecs::entity p_entity) { - const mesh_source* target = p_entity.get(); - mesh new_mesh(std::filesystem::path(target->model_path), - target->flip); - - // we do a check if the geometry uniform associated with this game - // object is valid - if (!m_mesh_geometry_set.contains(p_entity.id())) { - ::vk::uniform_params geo_info = { - .phsyical_memory_properties = - m_physical.memory_properties(), - .size_bytes = sizeof(material_uniform), - }; - m_mesh_geometry_set[p_entity.id()] = - ::vk::uniform_buffer(m_device, geo_info); - } - - // check if material is already associated with this particular game - // object - if (!m_mesh_material_set.contains(p_entity.id())) { - ::vk::uniform_params mat_info = { - .phsyical_memory_properties = - m_physical.memory_properties(), - .size_bytes = sizeof(material_metadata), - }; - m_mesh_material_set[p_entity.id()] = - ::vk::uniform_buffer(m_device, mat_info); - } - - new_mesh.add_diffuse(std::filesystem::path(target->diffuse)); - new_mesh.add_specular(std::filesystem::path(target->specular)); - - if (new_mesh.loaded()) { - m_cached_meshes.emplace(p_entity.id(), new_mesh); - - std::vector<::vk::descriptor_entry> set1_entries = { - ::vk::descriptor_entry{ - // specifies "layout (set = 1, binding = 0) uniform geometry_uniform" - .type = ::vk::buffer::uniform, - .binding_point = { - .binding = 0, - .stage = ::vk::shader_stage::vertex, - }, - .descriptor_count = 1, - }, - ::vk::descriptor_entry{ - // specifies "layout (set = 1, binding = 1) uniform sampler2D diffuse_texture" - .type = ::vk::buffer::combined_image_sampler, - .binding_point = { - .binding = 1, - .stage = ::vk::shader_stage::fragment, - }, - .descriptor_count = 1, - }, - ::vk::descriptor_entry{ - // specifies "layout (set = 1, binding = 2) uniform sampler2D specular_texture" - .type = ::vk::buffer::combined_image_sampler, - .binding_point = { - .binding = 2, - .stage = ::vk::shader_stage::fragment, - }, - .descriptor_count = 1, - }, - ::vk::descriptor_entry{ - // specifies "layout (set = 1, binding = 3) uniform sampler2D material_ubo" - .type = ::vk::buffer::uniform, - .binding_point = { - .binding = 3, - .stage = ::vk::shader_stage::fragment, - }, - .descriptor_count = 1, - }, - }; - - ::vk::descriptor_layout set1_layout = { - .slot = 1, - .max_sets = m_image_count, - .entries = set1_entries, - }; - - m_mesh_descriptors[p_entity.id()].emplace( - "materials", - ::vk::descriptor_resource(m_device, set1_layout)); - - // specify to the vk::write_descriptor_buffer - std::array<::vk::write_buffer, 1> binding0_buffers = { - ::vk::write_buffer{ - .buffer = m_mesh_geometry_set[p_entity.id()], - .offset = 0, - .range = m_mesh_geometry_set[p_entity.id()].size_bytes(), - } - }; - - std::array<::vk::write_buffer, 1> binding3_buffers = { - ::vk::write_buffer{ - .buffer = m_mesh_material_set[p_entity.id()], - .offset = 0, - .range = m_mesh_material_set[p_entity.id()].size_bytes(), - } - }; - - std::vector<::vk::write_buffer_descriptor> material_uniforms = { - // layout(set= 1, binding = 0) geometry_ubo - ::vk::write_buffer_descriptor{ - .dst_binding = 0, - .uniforms = binding0_buffers, - }, - // layout(set= 1, binding = 3) material_ubo - ::vk::write_buffer_descriptor{ - .dst_binding = 3, - .uniforms = binding3_buffers, - }, - }; - - // layout(set = 1, binding = 1) - // If the texture loaded successfully then we use that texture, - // otherwise utilize the default white texture - ::vk::sample_image diffuse = - m_cached_meshes[p_entity.id()].diffuse_loaded() - ? m_cached_meshes[p_entity.id()].diffuse() - : m_white_texture.image(); - - // layout(set = 1, binding = 2) - ::vk::sample_image specular = - m_cached_meshes[p_entity.id()].specular_loaded() - ? m_cached_meshes[p_entity.id()].specular() - : m_white_texture.image(); - - // writes to texture at layout(set = 1, binding = 1) - std::array<::vk::write_image, 1> - binding1_images = { ::vk::write_image{ - .sampler = diffuse.sampler(), - .view = diffuse.image_view(), - // .image_layout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL, - .layout = ::vk::image_layout::shader_read_only_optimal, - } }; - - // writes to texture at layout(set = 1, binding = 2) - std::array<::vk::write_image, 1> - binding2_images = { ::vk::write_image{ - .sampler = specular.sampler(), - .view = specular.image_view(), - // .image_layout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL, - .layout = ::vk::image_layout::shader_read_only_optimal, - } }; - - // vulkan image descriptors are for writing textures - std::vector<::vk::write_image_descriptor> material_textures = { - // layout(set = 1, binding = 1) uniform sampler2D - ::vk::write_image_descriptor{ - .dst_binding = 1, - .sample_images = binding1_images, - }, - // layout(set = 1, binding = 2) uniform sampler2D - ::vk::write_image_descriptor{ - .dst_binding = 2, - .sample_images = binding2_images, - }, - }; - - m_mesh_descriptors[p_entity.id()]["materials"].update( - material_uniforms, material_textures); - - m_sets_layouts.push_back( - m_mesh_descriptors[p_entity.id()]["materials"].layout()); - } - }); - - std::vector<::vk::shader_handle> modules = m_shader_group.handles(); - - ::vk::pipeline_settings pipeline_configuration = { - .renderpass = m_final_renderpass, - .shader_modules = modules, - .vertex_attributes = m_shader_group.vertex_attributes(), - .vertex_bind_attributes = m_shader_group.vertex_bind_attributes(), - .descriptor_layouts = m_sets_layouts - }; - m_main_pipeline = ::vk::pipeline(m_device, pipeline_configuration); - } - - void vk_renderer::start_frame(const ::vk::command_buffer& p_current, - const window_settings& p_settings, - const VkRenderPass& p_renderpass, - const VkFramebuffer& p_framebuffer, - const glm::mat4& p_proj_view) { - m_proj_view = p_proj_view; - m_current_frame = application::current_frame(); - m_final_renderpass = p_renderpass; - - std::array clear_values = {}; - - clear_values[0].color = m_color; - clear_values[1].depthStencil = { 1.f, 0 }; - m_window_extent = p_settings; - - VkRenderPassBeginInfo renderpass_begin_info = { - .sType = VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO, - .pNext = nullptr, - .renderPass = p_renderpass, - .renderArea = { - .offset = { - .x = 0, - .y = 0 - }, - .extent = { - .width = p_settings.width, - .height = p_settings.height - }, - }, - .clearValueCount = static_cast(clear_values.size()), - .pClearValues = clear_values.data() - }; - - m_current_command_buffer = p_current; - m_current_command_buffer.begin( - ::vk::command_usage::simulatneous_use_bit); - - VkViewport viewport = { - .x = 0.0f, - .y = 0.0f, - .width = static_cast(m_window_extent.width), - .height = static_cast(m_window_extent.height), - .minDepth = 0.0f, - .maxDepth = 1.0f, - }; - - vkCmdSetViewport(m_current_command_buffer, 0, 1, &viewport); - - VkRect2D scissor = { - .offset = { 0, 0 }, - .extent = { m_window_extent.width, m_window_extent.height }, - }; - - vkCmdSetScissor(m_current_command_buffer, 0, 1, &scissor); - - renderpass_begin_info.framebuffer = p_framebuffer; - - vkCmdBeginRenderPass(m_current_command_buffer, - &renderpass_begin_info, - VK_SUBPASS_CONTENTS_INLINE); - } - - // This just returns the arbitrary amount of bytes of the object - // TODO: Move this into core/utilities.hpp - template - std::span to_bytes(T p_data) { - return std::span(reinterpret_cast(&p_data), - sizeof(p_data)); - } - - void vk_renderer::post_frame() { - - // For now, using this. Will need to remove this before vulkan - // integration merging into dev This is for testing and to hopefully - // have a global_ubo for globalized uniforms - global_ubo global_frame_ubo = { .mvp = m_proj_view }; - - // TODO: Make to_bytes be part of utilities. This can be useful in - // sending the amount of bytes in batches for batch-rendering - // std::span bytes_data = to_bytes(global_frame_ubo); - // m_global_uniforms.update(bytes_data.data()); - m_global_uniforms.update(&global_frame_ubo); - - ref current_world = system_registry::get_world("Editor World"); - ref current_scene = current_world->get_scene("LevelScene"); - - // query all entities that have a point light - flecs::query query_point_lights = - current_scene->query_builder().build(); - - light_scene_ubo test_light = {}; - uint32_t index = 0; - query_point_lights.each( - [&index, &test_light](flecs::entity p_entity, point_light& p_light) { - const transform* t = p_entity.get(); - p_light.position = t->position; - - test_light.light_sources[index] = { - .position = glm::vec4(p_light.position, 1.f), - .color = p_light.color, - .attenuation = p_light.attenuation, - .constant = p_light.constant, - .linear = p_light.linear, - .quadratic = p_light.quadratic, - .ambient = p_light.ambient, - .diffuse = p_light.diffuse, - .specular = p_light.specular, - }; - index += 1; - }); - test_light.num_lights = index; - - m_point_light_uniforms.update(&test_light); - - // query all objects with a specified 3d mesh source - flecs::query<> query_targets = - current_scene->query_builder().build(); - - m_main_pipeline.bind(m_current_command_buffer); - - // Bind global camera data here - m_global_descriptors.bind(m_current_command_buffer, - m_main_pipeline.layout()); - query_targets.each([this](flecs::entity p_entity) { - const transform* transform_component = p_entity.get(); - const mesh_source* material_component = p_entity.get(); - m_model = glm::mat4(1.f); - m_model = glm::translate(m_model, transform_component->position); - m_model = glm::scale(m_model, transform_component->scale); - glm::mat4 rotation_mat4 = - glm::mat4(glm::quat(transform_component->rotation)); - - m_model *= rotation_mat4; - - // Mesh used for viking_room - replaced with std::map equivalent - geometry_uniform mesh_ubo = { .model = m_model, - .color = material_component->color }; - - if (m_cached_meshes[p_entity.id()].loaded()) { - m_mesh_geometry_set[p_entity.id()].update(&mesh_ubo); - - material_metadata data = {}; - - if (p_entity.has()) { - data = *p_entity.get(); - } - m_mesh_material_set[p_entity.id()].update(&data); - - m_mesh_descriptors[p_entity.id()]["materials"].bind( - m_current_command_buffer, m_main_pipeline.layout()); - - m_cached_meshes[p_entity.id()].draw(m_current_command_buffer); - } - }); - - vkCmdEndRenderPass(m_current_command_buffer); - m_current_command_buffer.end(); - } -}; diff --git a/src/atlas/drivers/vulkan-cpp/vk_swapchain.cpp b/src/atlas/drivers/vulkan-cpp/vk_swapchain.cpp deleted file mode 100644 index f5b953a0..00000000 --- a/src/atlas/drivers/vulkan-cpp/vk_swapchain.cpp +++ /dev/null @@ -1,261 +0,0 @@ -#include -#include -#include -#include -#include -#include - -namespace atlas::vk { - - vk_swapchain::vk_swapchain(const VkSurfaceKHR& p_surface, - const window_settings& p_settings) - : m_current_surface_handler(p_surface) - , m_window_settings(p_settings) - , m_current_surface(p_surface) { - m_physical = vk_context::physical_driver(); - m_driver = vk_context::driver_context(); - - create(); - } - - void vk_swapchain::create() { - - // surface properties are always updated from the physical device - // so they are valid should the swapchain be recreated - m_surface_properties = - m_physical.get_surface_properties(m_current_surface); - m_window_settings.width = - m_surface_properties.surface_capabilities.currentExtent.width; - m_window_settings.height = - m_surface_properties.surface_capabilities.currentExtent.height; - - //! @note Setting up presentation stuff - // request what our minimum image count is - uint32_t request_min_image_count = - select_images_size(m_surface_properties.surface_capabilities); - - m_swapchain_extent = - m_surface_properties.surface_capabilities.currentExtent; - - // setting our presentation properties - uint32_t present_index = - m_physical.read_presentation_index(m_current_surface_handler); - - VkSwapchainCreateInfoKHR swapchain_ci = { - .sType = VK_STRUCTURE_TYPE_SWAPCHAIN_CREATE_INFO_KHR, - .surface = m_current_surface_handler, - .minImageCount = request_min_image_count, - .imageFormat = m_surface_properties.surface_format.format, - .imageColorSpace = m_surface_properties.surface_format.colorSpace, - // use physical device surface formats to getting the right formats - // in vulkan - .imageExtent = m_swapchain_extent, - .imageArrayLayers = 1, - .imageUsage = (VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | - VK_IMAGE_USAGE_TRANSFER_DST_BIT), - .queueFamilyIndexCount = 1, - .pQueueFamilyIndices = &present_index, - .preTransform = - m_surface_properties.surface_capabilities.currentTransform, - .compositeAlpha = VK_COMPOSITE_ALPHA_OPAQUE_BIT_KHR, - .presentMode = VK_PRESENT_MODE_IMMEDIATE_KHR, - .clipped = true - }; - - vk_check(vkCreateSwapchainKHR( - m_driver, &swapchain_ci, nullptr, &m_swapchain_handler), - "vkCreateSwapchainKHR"); - - //!@brief querying images available - uint32_t image_count = 0; - vkGetSwapchainImagesKHR(m_driver, - m_swapchain_handler, - &image_count, - nullptr); // used to get the amount of images - std::vector images(image_count); - vkGetSwapchainImagesKHR(m_driver, - m_swapchain_handler, - &image_count, - images.data()); // used to store in the images - - // Creating Images - m_swapchain_images.resize(image_count); - m_image_size = image_count; - m_swapchain_depth_images.resize(image_count); - - VkFormat depth_format = m_driver.depth_format(); - - for (uint32_t i = 0; i < m_swapchain_images.size(); i++) { - ::vk::image_params color_image_config = { - .extent = { m_swapchain_extent.width, - m_swapchain_extent.height, }, - .format = m_surface_properties.surface_format.format, - .aspect = ::vk::image_aspect_flags::color_bit, - .usage = VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT, - .mip_levels = 1, - .layer_count = 1, - .phsyical_memory_properties = m_physical.memory_properties(), - - }; - - m_swapchain_images[i] = - ::vk::sample_image(m_driver, images[i], color_image_config); - - ::vk::image_params depth_image_config = { - .extent = { m_swapchain_extent.width, - m_swapchain_extent.height, }, - .format = depth_format, - .aspect = ::vk::image_aspect_flags::depth_bit, - .usage = VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT, - .mip_levels = 1, - .layer_count = 1, - .phsyical_memory_properties = m_physical.memory_properties(), - }; - - m_swapchain_depth_images[i] = - ::vk::sample_image(m_driver, depth_image_config); - } - - // command buffers - - m_swapchain_command_buffers.resize(image_count); - - for (size_t i = 0; i < m_swapchain_command_buffers.size(); i++) { - ::vk::command_params settings = { - .levels = ::vk::command_levels::primary, - // .queue_index = enumerate_swapchain_settings.present_index, - .queue_index = 0, - .flags = ::vk::command_pool_flags::reset, - }; - - m_swapchain_command_buffers[i] = - ::vk::command_buffer(m_driver, settings); - } - - std::array<::vk::attachment, 2> renderpass_attachments = { - ::vk::attachment{ - .format = m_surface_properties.surface_format.format, - .layout = ::vk::image_layout::color_optimal, - .samples = ::vk::sample_bit::count_1, - .load = ::vk::attachment_load::clear, - .store = ::vk::attachment_store::store, - .stencil_load = ::vk::attachment_load::clear, - .stencil_store = ::vk::attachment_store::dont_care, - .initial_layout = ::vk::image_layout::undefined, - .final_layout = ::vk::image_layout::present_src_khr, - }, - ::vk::attachment{ - .format = depth_format, - .layout = ::vk::image_layout::depth_stencil_optimal, - .samples = ::vk::sample_bit::count_1, - .load = ::vk::attachment_load::clear, - .store = ::vk::attachment_store::dont_care, - .stencil_load = ::vk::attachment_load::dont_care, - .stencil_store = ::vk::attachment_store::dont_care, - .initial_layout = ::vk::image_layout::undefined, - .final_layout = ::vk::image_layout::depth_stencil_optimal, - }, - }; - m_final_renderpass = ::vk::renderpass(m_driver, renderpass_attachments); - - // creating framebuffers - m_swapchain_framebuffers.resize(m_swapchain_images.size()); - - for (uint32_t i = 0; i < m_swapchain_images.size(); i++) { - - std::array - image_attachments = { m_swapchain_images[i].image_view(), - m_swapchain_depth_images[i].image_view() }; - - ::vk::framebuffer_params framebuffer_info = { - .renderpass = m_final_renderpass, - .views = image_attachments, - .extent = m_swapchain_extent - }; - m_swapchain_framebuffers[i] = - ::vk::framebuffer(m_driver, framebuffer_info); - } - - ::vk::queue_params present_queue_params{ - .family = 0, - .index = 0, - }; - m_present_to_queue = ::vk::device_present_queue( - m_driver, m_swapchain_handler, present_queue_params); - } - - void vk_swapchain::invalidate() { - destroy(); - create(); - } - - uint32_t vk_swapchain::select_images_size( - const VkSurfaceCapabilitiesKHR& p_surface_capabilities) { - uint32_t requested_images = p_surface_capabilities.minImageCount + 1; - - uint32_t final_image_count = 0; - - if ((p_surface_capabilities.maxImageCount > 0) and - (requested_images > p_surface_capabilities.maxImageCount)) { - final_image_count = p_surface_capabilities.maxImageCount; - } - else { - final_image_count = requested_images; - } - - return final_image_count; - } - - uint32_t vk_swapchain::read_acquired_image() { - m_present_to_queue.wait_idle(); - - // uint32_t frame_idx = m_present_to_queue.acquired_frame(); - uint32_t frame_idx = m_present_to_queue.acquire_next_image(); - if (m_present_to_queue.out_of_date()) { - invalidate(); - m_present_to_queue.out_of_date(false); - frame_idx = m_present_to_queue.acquire_next_image(); - } - - return frame_idx; - } - - void vk_swapchain::present(const uint32_t& p_current_frame) { - m_present_to_queue.present_frame(p_current_frame); - if (m_present_to_queue.out_of_date()) { - invalidate(); - m_present_to_queue.out_of_date(false); - } - } - - void vk_swapchain::submit(std::span p_commands) { - // m_present_to_queue.submit_immediate_async(p_command); - m_present_to_queue.submit_async(p_commands); - } - - void vk_swapchain::destroy() { - vkDeviceWaitIdle(m_driver); - - for (size_t i = 0; i < m_swapchain_framebuffers.size(); i++) { - m_swapchain_framebuffers[i].destroy(); - } - - m_final_renderpass.destroy(); - - m_present_to_queue.destroy(); - - for (size_t i = 0; i < m_swapchain_command_buffers.size(); i++) { - m_swapchain_command_buffers[i].destroy(); - } - - for (uint32_t i = 0; i < m_swapchain_depth_images.size(); i++) { - m_swapchain_depth_images[i].destroy(); - } - - for (uint32_t i = 0; i < m_swapchain_images.size(); i++) { - m_swapchain_images[i].destroy(); - } - - vkDestroySwapchainKHR(m_driver, m_swapchain_handler, nullptr); - } -}; diff --git a/src/atlas/drivers/vulkan-cpp/vk_window.cpp b/src/atlas/drivers/vulkan-cpp/vk_window.cpp deleted file mode 100644 index 92fc063e..00000000 --- a/src/atlas/drivers/vulkan-cpp/vk_window.cpp +++ /dev/null @@ -1,78 +0,0 @@ -#include -#include -#include -#include -#include - -namespace atlas::vk { - vk_window* vk_window::s_instance = nullptr; - vk_window::vk_window(const window_settings& p_settings) - : m_settings(p_settings) { - - if (!glfwVulkanSupported()) { - console_log_warn("GLFW: Vulkan is not supported!"); - return; - } - - glfwWindowHint(GLFW_CLIENT_API, GLFW_NO_API); - glfwWindowHint(GLFW_RESIZABLE, GLFW_TRUE); - - m_instance_handler = vk_context::handler(); - - m_window_handler = glfwCreateWindow((int)p_settings.width, - (int)p_settings.height, - p_settings.name.c_str(), - nullptr, - nullptr); - - glfwMakeContextCurrent(m_window_handler); - - vk_check( - glfwCreateWindowSurface( - m_instance_handler, m_window_handler, nullptr, &m_window_surface), - "glfwCreateWindowSurface"); - - center_window(); - - m_swapchain = vk_swapchain(m_window_surface, m_settings); - - vk_context::submit_resource_free([this]() { - console_log_fatal("vk_window submit freed resources!!!"); - m_swapchain.destroy(); - }); - - glfwSetWindowUserPointer(m_window_handler, this); - - s_instance = this; - } - - vk_window::~vk_window() { - vkDestroySurfaceKHR(m_instance_handler, m_window_surface, nullptr); - vkDestroyInstance(m_instance_handler, nullptr); - glfwDestroyWindow(m_window_handler); - } - - void vk_window::center_window() { - GLFWmonitor* monitor = glfwGetPrimaryMonitor(); - const GLFWvidmode* mode = glfwGetVideoMode(monitor); - uint32_t width = (mode->width / 2) - (m_settings.width / 2); - uint32_t height = (mode->height / 2) - (m_settings.height / 2); - glfwSetWindowPos(m_window_handler, (int)width, (int)height); - } - - void vk_window::presentation_process(const uint32_t& p_current_frame) { - m_swapchain.present(p_current_frame); - } - - window_settings vk_window::settings() const { - return m_swapchain.settings(); - } - - uint32_t vk_window::read_acquired_next_frame() { - return m_swapchain.read_acquired_image(); - } - - GLFWwindow* vk_window::native_window() const { - return m_window_handler; - } -}; diff --git a/src/atlas/physics/physics_context.cpp b/src/atlas/physics/physics_context.cpp deleted file mode 100644 index 78f80e8a..00000000 --- a/src/atlas/physics/physics_context.cpp +++ /dev/null @@ -1,15 +0,0 @@ -#include -#include -#include -#include -#include - -namespace atlas::physics { - - ref initialize_physics_context( - const jolt_settings& p_settings, - event::event_bus& p_bus) { - return create_ref(p_settings, p_bus); - } - -} \ No newline at end of file diff --git a/src/atlas/physics/physics_engine.cpp b/src/atlas/physics/physics_engine.cpp deleted file mode 100644 index c2d6dad6..00000000 --- a/src/atlas/physics/physics_engine.cpp +++ /dev/null @@ -1,154 +0,0 @@ -#include -#include -#include -#include -#include -#include - -namespace atlas::physics { - - physics_engine::physics_engine(const jolt_settings& p_settings, - flecs::world& p_registry, - event::event_bus& p_bus) - : m_registry(&p_registry) - , m_bus(&p_bus) { - m_physics_context = initialize_physics_context(p_settings, *m_bus); - // This may change, but for now we want to ensure that we only want to - // create a single physics body with a specific collider Rather then - // having multiple colliders be associated to a single physics body - // itself. - m_query_box_collider = - m_registry->query_builder() - .without() - .build(); - m_query_sphere_collider = - m_registry->query_builder() - .without() - .build(); - m_query_capsule_collider = - m_registry->query_builder() - .without() - .build(); - - m_physics_bodies = m_registry->query_builder().build(); - }; - - void physics_engine::start() { - // At the start of every simulation we create physics bodies to run - // simulation on those physics bodies with the specific colliders - // associated with them - m_query_box_collider.each([this](flecs::entity p_entity, - transform& p_transform, - physics_body& p_body, - box_collider& p_collider) { - m_physics_context->add_box_collider( - p_entity.id(), &p_transform, &p_body, &p_collider); - }); - - m_query_sphere_collider.each([this](flecs::entity p_entity, - transform& p_transform, - physics_body& p_body, - sphere_collider& p_collider) { - m_physics_context->add_sphere_collider( - p_entity.id(), &p_transform, &p_body, &p_collider); - }); - - m_query_capsule_collider.each([this](flecs::entity p_entity, - transform& p_transform, - physics_body& p_body, - capsule_collider& p_collider) { - m_physics_context->add_capsule_collider( - p_entity.id(), &p_transform, &p_body, &p_collider); - }); - m_physics_context->prepare(); - } - - void physics_engine::update(float p_delta_time) { - using namespace JPH; - - m_physics_bodies.each( - [this](flecs::entity p_entity, physics_body& p_body) { - m_physics_context->set_force_and_torque( - p_entity.id(), p_body.force, p_body.torque); - m_physics_context->set_linear_velocity(p_entity.id(), - p_body.linear_velocity); - m_physics_context->set_angular_velocity(p_entity.id(), - p_body.angular_velocity); - m_physics_context->set_impulse(p_entity.id(), p_body.impulse); - }); - // This will ensure all physics bodies with which colliders they are - // associated with are update with the simulation, and their parameters - // are modified - m_physics_context->update(p_delta_time); - - m_query_box_collider.each([&](flecs::entity p_entity, - transform& p_transform, - physics_body& p_body, - box_collider&) { - // updating transform - transform t = m_physics_context->read_transform(p_entity.id()); - p_transform.position = t.position; - p_transform.rotation = t.rotation; - p_transform.quaternion = t.quaternion; - - // physics bodies parameters - auto body = m_physics_context->read_physics_body(p_entity.id()); - p_body.linear_damping = body.linear_damping; - p_body.linear_velocity = body.linear_velocity; - p_body.angular_velocity = body.angular_velocity; - p_body.gravity_factor = body.gravity_factor; - p_body.center_mass_position = body.center_mass_position; - p_body.friction = body.friction; - p_body.restitution = body.restitution; - p_body.angular_velocity = body.angular_velocity; - p_body.linear_velocity = body.linear_velocity; - }); - - // updating sphere collider - m_query_sphere_collider.each([this](flecs::entity p_entity, - transform& p_transform, - physics_body& p_body, - sphere_collider&) { - // updating transform - transform t = m_physics_context->read_transform(p_entity.id()); - p_transform.position = t.position; - p_transform.rotation = t.rotation; - p_transform.quaternion = t.quaternion; - - // updating physics body - auto body = m_physics_context->read_physics_body(p_entity.id()); - p_body.linear_damping = body.linear_damping; - p_body.linear_velocity = body.linear_velocity; - p_body.angular_velocity = body.angular_velocity; - p_body.gravity_factor = body.gravity_factor; - p_body.center_mass_position = body.center_mass_position; - p_body.friction = body.friction; - p_body.restitution = body.restitution; - }); - - // updating capsule collider - m_query_capsule_collider.each([this](flecs::entity p_entity, - transform& p_transform, - physics_body& p_body, - capsule_collider&) { - transform t = m_physics_context->read_transform(p_entity.id()); - p_transform.position = t.position; - p_transform.rotation = t.rotation; - p_transform.quaternion = t.quaternion; - - auto body = m_physics_context->read_physics_body(p_entity.id()); - p_body.linear_damping = body.linear_damping; - p_body.linear_velocity = body.linear_velocity; - p_body.angular_velocity = body.angular_velocity; - p_body.gravity_factor = body.gravity_factor; - p_body.center_mass_position = body.center_mass_position; - p_body.friction = body.friction; - p_body.restitution = body.restitution; - }); - } - - void physics_engine::stop() { - m_physics_context->destroy(); - } - -} \ No newline at end of file diff --git a/src/atlas/renderer/renderer.cpp b/src/atlas/renderer/renderer.cpp deleted file mode 100644 index 95b81109..00000000 --- a/src/atlas/renderer/renderer.cpp +++ /dev/null @@ -1,37 +0,0 @@ -#include -#include - -namespace atlas { - - renderer::renderer(const window_settings& p_window_extent, - uint32_t p_image_size, - const std::string& p_tag) { - m_render_context = - initialize_renderer(p_window_extent, p_image_size, p_tag); - } - - void renderer::preload(const VkRenderPass& p_renderpass) { - m_render_context->preload(p_renderpass); - } - - void renderer::begin(const ::vk::command_buffer& p_current, - const window_settings& p_settings, - const VkRenderPass& p_renderpass, - const VkFramebuffer& p_framebuffer, - const glm::mat4& p_proj_view) { - return m_render_context->begin_frame( - p_current, p_settings, p_renderpass, p_framebuffer, p_proj_view); - } - - void renderer::end() { - return m_render_context->end_frame(); - } - - void renderer::set_background_color(const std::array& p_color) { - m_render_context->set_background_color(p_color); - } - - void renderer::current_scene(ref p_scene) { - m_render_context->current_scene_context(std::move(p_scene)); - } -}; From f2ebaf3d76edd211989e569dbd2a9031496557d7 Mon Sep 17 00:00:00 2001 From: SpinnerX Date: Tue, 13 Jan 2026 13:05:58 -0800 Subject: [PATCH 28/68] Removed old editor code that uses headers --- editor/CMakeLists.txt | 16 - editor/application.cpp | 43 --- editor/conanfile.py | 33 -- editor/editor_world.cpp | 20 -- editor/editor_world.hpp | 17 - editor/level_scene.cpp | 728 ---------------------------------------- editor/level_scene.hpp | 63 ---- 7 files changed, 920 deletions(-) delete mode 100644 editor/CMakeLists.txt delete mode 100644 editor/application.cpp delete mode 100644 editor/conanfile.py delete mode 100644 editor/editor_world.cpp delete mode 100644 editor/editor_world.hpp delete mode 100644 editor/level_scene.cpp delete mode 100644 editor/level_scene.hpp diff --git a/editor/CMakeLists.txt b/editor/CMakeLists.txt deleted file mode 100644 index ccd36417..00000000 --- a/editor/CMakeLists.txt +++ /dev/null @@ -1,16 +0,0 @@ -cmake_minimum_required(VERSION 3.27) -project(editor CXX) - -build_application( - SOURCES - application.cpp - - editor_world.hpp - editor_world.cpp - - level_scene.hpp - level_scene.cpp - - LINK_PACKAGES - atlas -) \ No newline at end of file diff --git a/editor/application.cpp b/editor/application.cpp deleted file mode 100644 index 1c23ddac..00000000 --- a/editor/application.cpp +++ /dev/null @@ -1,43 +0,0 @@ -#include -#include "editor_world.hpp" -#include -#include - -/** - * This represents our editor's application - * - * TODO: Add a preload API to preload the application. For providing user - * preferences, project settings, or other configuration settings that are - * projects-related - */ -class editor_application : public atlas::application { -public: - editor_application(const atlas::application_settings& p_settings) - : application(p_settings) { - std::pmr::monotonic_buffer_resource resource{ 4096 }; - m_allocator.construct(&resource); - - // TODO -- this is going to be changed with the use of the level - // streamer API - m_world = atlas::create_strong_ref( - m_allocator, "Editor World", renderer_instance()); - } - -private: - std::pmr::polymorphic_allocator m_allocator; - atlas::optional_ref m_world; -}; - -namespace atlas { - ref initialize_application() { - application_settings settings = { - .name = "Editor", - .width = 1200, - .height = 800, - .background_color = { 0.f, 0.f, 0.f, 0.f }, - }; - - return create_ref(settings); - } - -} // end of namespace atlas \ No newline at end of file diff --git a/editor/conanfile.py b/editor/conanfile.py deleted file mode 100644 index e7480010..00000000 --- a/editor/conanfile.py +++ /dev/null @@ -1,33 +0,0 @@ -from conan import ConanFile -from conan.tools.cmake import CMake, cmake_layout - -class GameDemo(ConanFile): - name = "game-demo" - version = "1.0" - settings = "os", "compiler", "build_type", "arch" - generators = "CMakeDeps", "CMakeToolchain" - export_source = "CMakeLists.txt", "application.cpp" - - # Putting all of your build-related dependencies here - def build_requirements(self): - self.tool_requires("make/4.4.1") - self.tool_requires("cmake/3.27.1") - self.tool_requires("engine3d-cmake-utils/4.0") - - # Putting all of your packages here - # To build engine3d/1.0 locally do the following: - # conan create . --name=engine3d --version=0.1.0 --user=local --channel=12345 - def requirements(self): - self.requires("atlas/0.1") - - def build(self): - cmake = CMake(self) - cmake.configure() - cmake.build() - - def package(self): - cmake = CMake(self) - cmake.install() - - def layout(self): - cmake_layout(self) \ No newline at end of file diff --git a/editor/editor_world.cpp b/editor/editor_world.cpp deleted file mode 100644 index f25e936c..00000000 --- a/editor/editor_world.cpp +++ /dev/null @@ -1,20 +0,0 @@ -#include "editor_world.hpp" -#include -#include -#include "level_scene.hpp" - -editor_world::editor_world( - const std::string& p_tag, - /*NOLINT*/ atlas::ref p_renderer_instance) - : m_renderer(/*NOLINT*/ p_renderer_instance) { - m_main_world = atlas::system_registry::create_world(p_tag); - - m_bus.create_listener(); - m_bus.create_listener(); - m_bus.create_listener(); - - atlas::ref first_scene = - atlas::create_ref("LevelScene", m_bus); - m_renderer->current_scene(first_scene); - m_main_world->add_scene(first_scene); -} \ No newline at end of file diff --git a/editor/editor_world.hpp b/editor/editor_world.hpp deleted file mode 100644 index 50a06310..00000000 --- a/editor/editor_world.hpp +++ /dev/null @@ -1,17 +0,0 @@ -#pragma once -#include -#include -#include -#include - -class editor_world { -public: - editor_world(const std::string& p_tag, - atlas::ref p_renderer_instance); - -private: - atlas::ref m_main_world; - - atlas::event::event_bus m_bus; - atlas::ref m_renderer; -}; \ No newline at end of file diff --git a/editor/level_scene.cpp b/editor/level_scene.cpp deleted file mode 100644 index edd96f46..00000000 --- a/editor/level_scene.cpp +++ /dev/null @@ -1,728 +0,0 @@ -#include "level_scene.hpp" -#include -#include -#include -#include -#include -#include - -level_scene::level_scene(const std::string& p_name, - atlas::event::event_bus& p_bus) - : atlas::scene(p_name, p_bus) { - auto editor_camera = entity("Editor Camera"); - editor_camera - .add>(); - editor_camera.set({ - .position = { 3.50f, 4.90f, 36.40f }, - .scale{ 1.f }, - }); - editor_camera.set({ - .plane = { 0.1f, 5000.f }, - .is_active = true, - .field_of_view = 45.f, - }); - - atlas::game_object bob_object = entity("Bob"); - - bob_object.add(); - - atlas::game_object viking_room = entity("Viking Room"); - viking_room.add(); - viking_room.set({ - .position = { -2.70f, 2.70, -8.30f }, - .rotation = { 2.30f, 95.90f, 91.80f }, - .scale{ 1.f }, - }); - - viking_room.set({ - .radius = 1.0f, - }); - - viking_room.set({ - .friction = 15.f, - .restitution = 0.3f, - .body_movement_type = atlas::dynamic, - }); - - atlas::game_object cube = entity("Aircraft"); - - cube.set({ - .position = { 0.f, 2.10f, -7.30f }, - .scale = { 0.9f, 0.9f, 0.9f }, - }); - - cube.set({ - .color = { 1.f, 1.f, 1.f, 1.f }, - // .model_path = "assets/models/E 45 Aircraft_obj.obj", - .model_path = "assets/backpack/backpack.obj", - .diffuse = "assets/backpack/diffuse.jpg", - .specular = "assets/backpack/specular.jpg" - // .diffuse = "assets/models/E-45-steel detail_2_col.jpg", - }); - - atlas::game_object robot_model = entity("Cube"); - robot_model.add(); - // robot_model.add(); - robot_model.set({ - .position = { -2.70, 3.50f, 4.10f }, - .scale = { 1.f, 1.f, 1.f }, - }); - - robot_model.set( - { .color = { 1.f, 1.f, 1.f, 1.f }, - .model_path = "assets/models/cube.obj", - .diffuse = "assets/models/container_diffuse.png", - .specular = "assets/models/container_specular.png" }); - - robot_model.set({ - .half_extent = { 1.f, 1.f, 1.f }, - }); - robot_model.set({ - // .restitution = 1.f, - .body_movement_type = atlas::dynamic, - }); - - atlas::game_object platform = entity("Platform"); - - platform.set({ - .scale = { 15.f, 0.30f, 10.0f }, - }); - platform.set({ - .model_path = "assets/models/cube.obj", - .diffuse = "assets/models/wood.png", - }); - platform.set({ - .body_movement_type = atlas::fixed, - }); - platform.set({ - .half_extent = { 15.f, 0.30f, 10.0f }, - }); - - atlas::game_object point_light = entity("Point Light 1"); - point_light.set({ - .position = { 0.f, 2.10f, -7.30f }, - .scale = { 0.9f, 0.9f, 0.9f }, - }); - - point_light.set({ - .model_path = "assets/models/cube.obj", - .diffuse = "assets/models/wood.png", - }); - point_light.add(); - - // benchmark - - // auto start = std::chrono::high_resolution_clock::now(); - // TEMP Code - // [[maybe_unused]] atlas::game_object point_light_test = entity("Point - // Light 1"); auto end = std::chrono::high_resolution_clock::now(); auto - // duration = (end - start); - - // auto seconds = - // std::chrono::duration_cast(duration).count(); auto - // nanoseconds = - // std::chrono::duration_cast(duration).count(); - // auto microseconds = - // std::chrono::duration_cast(duration).count(); - - // console_log_fatal("Seconds = {:.1f}", static_cast(seconds)); - // console_log_fatal("Nanoseconds = {:.1f}", - // static_cast(nanoseconds)); console_log_fatal("Microseconds = - // {:.1f}", static_cast(microseconds)); - - // for(size_t i = 0; i < 26; i++) { - // auto obj = entity(std::format("Object #{}", i)); - // obj->set({ - // .restitution = 1.25f, - // .body_movement_type = atlas::dynamic, - // }); - - // obj->set( - // { - // .radius = 1.0f, - // }); - - // glm::vec3 pos = {float(0*1.4),float(0 * 1.4),float(0 * -3) }; - - // obj->set({ - // .position = pos, - // .rotation = {.3f, 0.0f, 0.0f}, - // }); - - // obj->set({ - // .model_path = "assets/models/Ball OBJ.obj", - // .diffuse = "assets/models/clear.png", - // }); - // } - - atlas::game_object gerald = entity("Gerald"); - gerald.add(); - - // TODO: Move this outside of level_scene - m_deserializer_test = atlas::serializer(); - - subscribe(this, - &level_scene::collision_enter); - - atlas::register_start(this, &level_scene::start); - atlas::register_physics(this, &level_scene::physics_update); - atlas::register_update(this, &level_scene::on_update); - atlas::register_ui(this, &level_scene::on_ui_update); -} - -void -level_scene::collision_enter(atlas::event::collision_enter& p_event) { - console_log_warn("collision_enter event!!!"); - atlas::game_object e1 = entity(p_event.entity1); - atlas::game_object e2 = entity(p_event.entity2); - - console_log_warn("Entity1 = {}", e1.name().c_str()); - console_log_warn("Entity2 = {}", e2.name().c_str()); -} - -void -level_scene::collision_persisted(atlas::event::collision_persisted& p_event) { - console_log_warn("collision_persisted(p_event) invoked!!"); - atlas::game_object e1 = entity(p_event.entity1); - atlas::game_object e2 = entity(p_event.entity2); - - console_log_warn("Entity1 = {}", e1.name().c_str()); - console_log_warn("Entity2 = {}", e2.name().c_str()); -} - -void -level_scene::runtime_start() { - // runs the physics simulation - m_physics_runtime = true; - - m_physics_engine.start(); -} - -void -level_scene::runtime_stop() { - m_physics_runtime = false; - - m_physics_engine.stop(); - - reset_objects(); -} - -void -level_scene::reset_objects() { - - if (!m_deserializer_test.load("LevelScene", *this)) { - console_log_error("Could not load yaml file LevelScene!!!"); - } -} - -void -ui_component_list(flecs::entity& p_selected_entity) { - std::string entity_name = p_selected_entity.name().c_str(); - std::string new_entity_name = ""; - atlas::ui::draw_input_text(new_entity_name, entity_name); - - p_selected_entity.set_name(new_entity_name.c_str()); - - ImGui::SameLine(); - ImGui::PushItemWidth(-1); - if (ImGui::Button("Add Component")) { - ImGui::OpenPopup("Add Component"); - } - - if (ImGui::BeginPopup("Add Component")) { - if (!p_selected_entity.has()) { - if (ImGui::MenuItem("Perspective Camera")) { - p_selected_entity.add< - flecs::pair>(); - p_selected_entity.add(); - ImGui::CloseCurrentPopup(); - } - } - - if (!p_selected_entity.has()) { - if (ImGui::MenuItem("Mesh Source")) { - p_selected_entity.add(); - ImGui::CloseCurrentPopup(); - } - } - - if (!p_selected_entity.has()) { - if (ImGui::MenuItem("Point Light")) { - p_selected_entity.add(); - ImGui::CloseCurrentPopup(); - } - } - - if (!p_selected_entity.has()) { - if (ImGui::MenuItem("Serialize")) { - p_selected_entity.add(); - ImGui::CloseCurrentPopup(); - } - } - - if (!p_selected_entity.has()) { - if (ImGui::MenuItem("Physics Body")) { - p_selected_entity.add(); - ImGui::CloseCurrentPopup(); - } - } - - if (!p_selected_entity.has()) { - if (ImGui::MenuItem("Box Collider")) { - p_selected_entity.add(); - ImGui::CloseCurrentPopup(); - } - } - - if (!p_selected_entity.has()) { - if (ImGui::MenuItem("Sphere Collider")) { - p_selected_entity.add(); - ImGui::CloseCurrentPopup(); - } - } - - if (!p_selected_entity.has()) { - if (ImGui::MenuItem("Capsule Collider")) { - p_selected_entity.add(); - ImGui::CloseCurrentPopup(); - } - } - ImGui::EndPopup(); - } - - ImGui::PopItemWidth(); -} - -void -level_scene::on_ui_update() { - - // setting up the dockspace UI widgets at the window toolbar - m_editor_dockspace.begin(); - - try { - m_editor_menu.begin(); - } - catch (const atlas::ui::menu_bar_exception& e) { - } - - if (ImGui::BeginMenu("File")) { - if (ImGui::MenuItem("Save")) { - // m_deserializer_test.save("LevelScene"); - } - - ImGui::Separator(); - - if (ImGui::MenuItem("Exit")) { - glfwSetWindowShouldClose(atlas::application::get_window(), true); - } - - ImGui::EndMenu(); - } - - m_editor_menu.end(); - - if (ImGui::Begin("Viewport")) { - glm::vec2 viewport_panel_size = - glm::vec2{ atlas::application::get_window().width(), - atlas::application::get_window().height() }; - - ImGui::End(); - } - - defer_begin(); - auto query_builder = this->query_builder().build(); - - if (ImGui::Begin("Scene Heirarchy")) { - // @note right click on blank space - // @param string_id - // @param popup_flags - will be the mouse flag (0=right, 1=left) - if (atlas::ui::begin_popup_context_window(nullptr, 1, false)) { - if (ImGui::MenuItem("Create Empty Entity")) { - m_current_entity = entity("Empty Entity"); - } - ImGui::EndPopup(); - } - - query_builder.each([&](flecs::entity p_entity, atlas::transform&) { - // We set the imgui flags for our scene heirarchy panel - // TODO -- Make the scene heirarchy panel a separate class that is - // used for specify the layout and other UI elements here - ImGuiTreeNodeFlags flags = - ((m_selected_entity == p_entity) ? ImGuiTreeNodeFlags_Selected - : 0) | - ImGuiTreeNodeFlags_OpenOnArrow; - flags |= ImGuiTreeNodeFlags_SpanAvailWidth; - flags |= ImGuiWindowFlags_Popup; - flags |= ImGuiTreeNodeFlags_AllowItemOverlap; - - bool opened = ImGui::TreeNodeEx(p_entity.name().c_str(), flags); - - if (ImGui::IsItemClicked()) { - m_selected_entity = p_entity; - } - - bool delete_entity = false; - if (ImGui::BeginPopupContextItem()) { - if (ImGui::MenuItem("Delete Entity")) { - delete_entity = true; - } - ImGui::EndPopup(); - } - - if (delete_entity) { - m_selected_entity.destruct(); - } - - ImGui::SameLine(); - ImGui::TextDisabled("(%llu)", p_entity.id()); - - if (opened) { - flags = ImGuiTreeNodeFlags_OpenOnArrow | - ImGuiTreeNodeFlags_SpanAvailWidth; - auto query_children_builder = - this->query_builder().with(flecs::ChildOf, p_entity).build(); - int32_t child_count = query_children_builder.count(); - - // // Only show children in scene heirarchy panel if there are - // children entities - if (child_count > 0) { - m_selected_entity.children([&](flecs::entity p_child) { - opened = - ImGui::TreeNodeEx(p_child.name().c_str(), flags); - if (opened) { - if (ImGui::IsItemClicked()) { - m_selected_entity = p_child; - } - ImGui::TreePop(); - } - }); - } - - ImGui::TreePop(); - } - }); - - defer_end(); - ImGui::End(); - } - - if (ImGui::Begin("Properties")) { - if (m_selected_entity.is_alive()) { - ui_component_list(m_selected_entity); - - atlas::ui::draw_component( - "transform", - m_selected_entity, - [](atlas::transform* p_transform) { - atlas::ui::draw_vec3("Position", p_transform->position); - atlas::ui::draw_vec3("Scale", p_transform->scale); - atlas::ui::draw_vec3("Rotation", p_transform->rotation); - }); - - atlas::ui::draw_component( - "camera", - m_selected_entity, - [this](atlas::perspective_camera* p_camera) { - atlas::ui::draw_float("field of view", - p_camera->field_of_view); - ImGui::Checkbox("is_active", &p_camera->is_active); - ImGui::DragFloat("Speed", &m_movement_speed); - }); - - atlas::ui::draw_component( - "atlas::mesh_source", - m_selected_entity, - [](atlas::mesh_source* p_source) { - std::string mesh_src = p_source->model_path; - atlas::ui::draw_input_text(p_source->model_path, mesh_src); - atlas::ui::draw_vec4("Color", p_source->color); - }); - - atlas::ui::draw_component( - "material", - m_selected_entity, - [](atlas::material_metadata* p_source) { - float speed = 0.01f; - ImGui::DragFloat4( - "Ambient", glm::value_ptr(p_source->ambient), speed); - ImGui::DragFloat4( - "Diffuse", glm::value_ptr(p_source->diffuse), speed); - ImGui::DragFloat4( - "Specular", glm::value_ptr(p_source->specular), speed); - atlas::ui::draw_float("Shininess", p_source->shininess); - }); - - /* - atlas::ui::draw_component("Directional - Light", m_selected_entity, [](atlas::directional_light* - p_dir_light){ ImGui::DragFloat4("Direction", - glm::value_ptr(p_dir_light->direction)); ImGui::DragFloat4("View - Pos", glm::value_ptr(p_dir_light->view_position)); - ImGui::DragFloat4("Color", glm::value_ptr(p_dir_light->color)); - ImGui::DragFloat4("Ambient", - glm::value_ptr(p_dir_light->ambient)); ImGui::DragFloat4("Diffuse", - glm::value_ptr(p_dir_light->diffuse)); ImGui::DragFloat4("Specular", - glm::value_ptr(p_dir_light->specular)); - }); - */ - - atlas::ui::draw_component( - "Point Light", - m_selected_entity, - [](atlas::point_light* p_dir_light) { - ImGui::DragFloat4( - "Color", glm::value_ptr(p_dir_light->color), 0.01); - ImGui::DragFloat( - "Attenuation", &p_dir_light->attenuation, 0.001); - ImGui::DragFloat4( - "Ambient", glm::value_ptr(p_dir_light->ambient), 0.01); - ImGui::DragFloat4( - "Diffuse", glm::value_ptr(p_dir_light->diffuse), 0.01); - ImGui::DragFloat4( - "Specular", glm::value_ptr(p_dir_light->specular), 0.01); - ImGui::DragFloat("Constant", &p_dir_light->constant, 0.01); - ImGui::DragFloat("Linear", &p_dir_light->linear, 0.01); - ImGui::DragFloat("Quadratic", &p_dir_light->quadratic, 0.01); - }); - - atlas::ui::draw_component( - "Physics Body", - m_selected_entity, - [](atlas::physics_body* p_body) { - std::array items = { - "Static", - "Kinematic", - "Dynamic", - }; - std::string combo_preview = items[p_body->body_movement_type]; - - // Begin the combo box - if (ImGui::BeginCombo("Body Type", combo_preview.data())) { - for (int n = 0; n < 3; n++) { - // Check if the current item is selected - const bool is_selected = - (p_body->body_movement_type == n); - if (ImGui::Selectable(items[n].data(), is_selected)) { - // Update the current type when a new item is - // selected - p_body->body_movement_type = - static_cast(n); - } - - // Set the initial focus when the combo box is first - // opened - if (is_selected) { - ImGui::SetItemDefaultFocus(); - } - } - ImGui::EndCombo(); - } - - // physics body parameters - atlas::ui::draw_vec3("Linear Velocity", - p_body->linear_velocity); - atlas::ui::draw_vec3("Angular Velocity", - p_body->angular_velocity); - atlas::ui::draw_vec3("Force", p_body->force); - atlas::ui::draw_vec3("Impulse", p_body->impulse); - atlas::ui::draw_vec3("Torque", p_body->torque); - atlas::ui::draw_vec3("Center Mass", - p_body->center_mass_position); - }); - - atlas::ui::draw_component( - "Box Collider", - m_selected_entity, - [](atlas::box_collider* p_collider) { - atlas::ui::draw_vec3("Half Extent", p_collider->half_extent); - }); - - atlas::ui::draw_component( - "Box Collider", - m_selected_entity, - [](atlas::sphere_collider* p_collider) { - atlas::ui::draw_float("Radius", p_collider->radius); - }); - - atlas::ui::draw_component( - "Box Collider", - m_selected_entity, - [](atlas::capsule_collider* p_collider) { - atlas::ui::draw_float("Half Height", p_collider->half_height); - atlas::ui::draw_float("Radius", p_collider->radius); - }); - - atlas::ui::draw_component( - "Serialize", - m_selected_entity, - [](atlas::tag::serialize* p_serialize) { - ImGui::Checkbox("Enable", &p_serialize->enable); - }); - } - - ImGui::End(); - - // Note --- just added this temporarily for testing - // auto time = atlas::application::delta_time(); - - // if((int)(time * 10.0f) % 8 > 4) { - // m_blink = !m_blink; - // } - - // auto width = atlas::application::get_window().width(); - // auto height = atlas::application::get_window().height(); - - // ImGui::SetNextWindowPos(ImVec2(static_cast(width) * 0.5f, - // static_cast(height) * 0.5f), ImGuiCond_Always, ImVec2(0.5f, - // 0.5f)); ImGui::SetNextWindowSize(ImVec2(200, 20), ImGuiCond_Always); - // ImGuiWindowFlags flags = ImGuiWindowFlags_NoDecoration | - // ImGuiWindowFlags_NoBackground | ImGuiWindowFlags_NoInputs; - // ImGui::SetNextWindowBgAlpha(0.f); - - // if(ImGui::Begin("Testing", nullptr, flags)) { - // ImGui::ProgressBar(10.f); - - // auto pos = ImGui::GetWindowPos(); - // pos.x += (float)width * 0.5f - 300.0f; - // pos.y += 50.0f; - // if(m_blink){ - // ImGui::GetForegroundDrawList()->AddText(m_font, 120.0f, - // pos, 0xffffffff, "Click to Play!"); - // } - - // ImGui::End(); - // } - } - - m_editor_dockspace.end(); -} - -void -level_scene::start() { - m_deserializer_test = atlas::serializer(); - - if (!m_deserializer_test.load("LevelScene", *this)) { - console_log_error("Could not load yaml file LevelScene!!!"); - } - - atlas::game_object viking_room = entity("Viking Room"); - atlas::mesh_source* src = viking_room.get_mut(); - src->flip = true; - - // Initiating physics system - atlas::physics::jolt_settings settings = {}; - flecs::world registry = *this; - m_physics_engine = - atlas::physics::physics_engine(settings, registry, *event_handle()); - - // Note -- just added for temporary - // ImGuiIO io = ImGui::GetIO(); - // m_font = io.Fonts->AddFontFromFileTTF("assets/OpenSans-Regular.ttf", - // 120.0f); -} - -void -level_scene::on_update() { - - auto query_cameras = - query_builder().build(); - - query_cameras.each([this](atlas::perspective_camera& p_camera, - atlas::transform& p_transform) { - if (!p_camera.is_active) { - return; - } - - float dt = atlas::application::delta_time(); - float default_speed = 10.f; // current default movement speed that does - // not applied modified speed - float rotation_speed = 1.f; - float velocity = default_speed * dt; - if (atlas::event::is_mouse_pressed(mouse_button_middle)) { - velocity = m_movement_speed * dt; - } - float rotation_velocity = rotation_speed * dt; - - glm::quat to_quaternion = atlas::to_quat(p_transform.quaternion); - - glm::vec3 up = glm::rotate(to_quaternion, atlas::math::up()); - glm::vec3 forward = glm::rotate(to_quaternion, atlas::math::backward()); - glm::vec3 right = glm::rotate(to_quaternion, atlas::math::right()); - - if (atlas::event::is_key_pressed(key_left_shift)) { - p_transform.position += up * velocity; - } - - if (atlas::event::is_key_pressed(key_space)) { - p_transform.position -= up * velocity; - } - - if (atlas::event::is_key_pressed(key_w)) { - p_transform.position += forward * velocity; - } - if (atlas::event::is_key_pressed(key_s)) { - p_transform.position -= forward * velocity; - } - - if (atlas::event::is_key_pressed(key_d)) { - p_transform.position += right * velocity; - } - if (atlas::event::is_key_pressed(key_a)) { - p_transform.position -= right * velocity; - } - - if (atlas::event::is_key_pressed(key_q)) { - p_transform.rotation.y += rotation_velocity; - } - if (atlas::event::is_key_pressed(key_e)) { - p_transform.rotation.y -= rotation_velocity; - } - - p_transform.set_rotation(p_transform.rotation); - }); -} - -void -level_scene::physics_update() { - float dt = atlas::application::delta_time(); - if (atlas::event::is_key_pressed(key_r) and !m_physics_runtime) { - runtime_start(); - } - - auto viking_room = entity("Viking Room"); - - atlas::physics_body* sphere_body = - viking_room.get_mut(); - // U = +up - // J = -up - // H = +left - // L = -Left - if (atlas::event::is_key_pressed(key_space)) { - glm::vec3 linear_velocity = { 0.f, 10.0f, 0.f }; - sphere_body->linear_velocity = linear_velocity; - sphere_body->impulse = linear_velocity; - } - - if (atlas::event::is_key_pressed(key_j)) { - glm::vec3 angular_vel = { -10.f, 0.f, 0.f }; - sphere_body->angular_velocity = angular_vel; - } - - if (atlas::event::is_key_pressed(key_h)) { - glm::vec3 angular_vel = { 10.f, 0.f, 0.f }; - sphere_body->angular_velocity = angular_vel; - } - - if (atlas::event::is_key_pressed(key_l)) { - glm::vec3 angular_vel = { -0.1f, 0.f, 0.f }; - sphere_body->angular_velocity = angular_vel; - } - - if (m_physics_runtime) { - m_physics_engine.update(dt); - } - - if (atlas::event::is_key_pressed(key_l) and m_physics_runtime) { - runtime_stop(); - } -} diff --git a/editor/level_scene.hpp b/editor/level_scene.hpp deleted file mode 100644 index 5891afec..00000000 --- a/editor/level_scene.hpp +++ /dev/null @@ -1,63 +0,0 @@ -#pragma once -#include -#include -#include -#include -#include -#include -#include -#include -#include - -/** - * @brief Implementation of a custom scene - * - * Represent a scene with an associated game objects that correspond to this - * game object. - * - */ - -class level_scene final : public atlas::scene { -public: - level_scene(const std::string& p_tag, atlas::event::event_bus& p_bus); - - ~level_scene() override = default; - - void start(); - - void on_update(); - - void on_ui_update(); - - void physics_update(); - - void runtime_start(); - - void runtime_stop(); - - void reset_objects(); - -private: - void collision_enter(atlas::event::collision_enter& p_event); - - void collision_persisted(atlas::event::collision_persisted& p_event); - -private: - atlas::serializer m_deserializer_test; - flecs::entity m_selected_entity; - - atlas::game_object_optional m_current_entity; - float m_movement_speed = 10.f; - - // Setting physics system - // TODO -- when refactoring this would be at atlas::world level - atlas::physics::physics_engine m_physics_engine; - - bool m_physics_runtime = false; - - atlas::ui::dockspace m_editor_dockspace; - atlas::ui::menu_item m_editor_menu; - - // Note -- Added this temporarily - // ImFont* m_font; -}; From 617ebe5d2391c55c222605d066648bbc09b7eb70 Mon Sep 17 00:00:00 2001 From: SpinnerX Date: Tue, 13 Jan 2026 13:15:19 -0800 Subject: [PATCH 29/68] Renamed atlas-modules to atlas to finalize changes migrating to modules --- CMakeLists.txt | 122 +++++++++--------- {atlas-modules => atlas}/atlas.cppm | 0 {atlas-modules => atlas}/core/api.cppm | 0 .../core/application.cppm | 0 {atlas-modules => atlas}/core/common.cppm | 0 {atlas-modules => atlas}/core/core.cppm | 0 .../core/editor/dockspace.cppm | 0 .../core/editor/menu_item.cppm | 0 .../core/entry_point/main.cpp | 0 {atlas-modules => atlas}/core/event/bus.cppm | 0 .../core/event/event.cppm | 0 .../core/event/joystick_codes.cppm | 0 {atlas-modules => atlas}/core/event/keys.cppm | 0 .../core/event/listener.cppm | 0 .../core/event/mouse_codes.cppm | 0 .../core/event/types.cppm | 0 .../core/filesystem/file_dialog.cppm | 0 {atlas-modules => atlas}/core/logger.cppm | 0 {atlas-modules => atlas}/core/math/math.cppm | 0 {atlas-modules => atlas}/core/math/types.cppm | 0 .../core/scene/components.cppm | 0 .../core/scene/game_object.cppm | 0 .../core/scene/scene.cppm | 0 .../core/scene/system_registry.cppm | 0 .../core/scene/world.cppm | 0 .../core/serialize/serializer.cppm | 0 .../core/serialize/types.cppm | 0 {atlas-modules => atlas}/core/ui/widgets.cppm | 0 .../core/utilities/poll_state.cppm | 0 .../core/utilities/state.cppm | 0 .../core/utilities/types.cppm | 0 {atlas-modules => atlas}/core/window.cppm | 0 {atlas-modules => atlas}/drivers/drivers.cppm | 0 .../drivers/graphics_context.cppm | 0 .../drivers/jolt_cpp/broad_phase.cppm | 0 .../drivers/jolt_cpp/contact_listener.cppm | 18 +-- .../drivers/jolt_cpp/context.cppm | 0 .../drivers/jolt_cpp/math.cppm | 0 .../drivers/physics_context.cppm | 0 .../drivers/renderer_system.cppm | 0 .../drivers/vulkan/device.cppm | 0 .../drivers/vulkan/hash.cppm | 0 .../drivers/vulkan/imgui_context.cppm | 0 .../drivers/vulkan/instance_context.cppm | 2 +- .../drivers/vulkan/mesh.cppm | 2 +- .../drivers/vulkan/physical_device.cppm | 0 .../drivers/vulkan/render_system.cppm | 100 +++++++------- .../drivers/vulkan/shader_resource_group.cppm | 6 +- .../drivers/vulkan/swapchain.cppm | 0 .../drivers/vulkan/uniforms.cppm | 0 .../drivers/vulkan/utilities.cppm | 0 .../drivers/vulkan/vulkan.cppm | 0 .../drivers/vulkan/window_context.cppm | 0 .../physics/physics_engine.cppm | 0 {atlas-modules => atlas}/physics/types.cppm | 0 .../renderer/renderer.cppm | 0 56 files changed, 128 insertions(+), 122 deletions(-) rename {atlas-modules => atlas}/atlas.cppm (100%) rename {atlas-modules => atlas}/core/api.cppm (100%) rename {atlas-modules => atlas}/core/application.cppm (100%) rename {atlas-modules => atlas}/core/common.cppm (100%) rename {atlas-modules => atlas}/core/core.cppm (100%) rename {atlas-modules => atlas}/core/editor/dockspace.cppm (100%) rename {atlas-modules => atlas}/core/editor/menu_item.cppm (100%) rename {atlas-modules => atlas}/core/entry_point/main.cpp (100%) rename {atlas-modules => atlas}/core/event/bus.cppm (100%) rename {atlas-modules => atlas}/core/event/event.cppm (100%) rename {atlas-modules => atlas}/core/event/joystick_codes.cppm (100%) rename {atlas-modules => atlas}/core/event/keys.cppm (100%) rename {atlas-modules => atlas}/core/event/listener.cppm (100%) rename {atlas-modules => atlas}/core/event/mouse_codes.cppm (100%) rename {atlas-modules => atlas}/core/event/types.cppm (100%) rename {atlas-modules => atlas}/core/filesystem/file_dialog.cppm (100%) rename {atlas-modules => atlas}/core/logger.cppm (100%) rename {atlas-modules => atlas}/core/math/math.cppm (100%) rename {atlas-modules => atlas}/core/math/types.cppm (100%) rename {atlas-modules => atlas}/core/scene/components.cppm (100%) rename {atlas-modules => atlas}/core/scene/game_object.cppm (100%) rename {atlas-modules => atlas}/core/scene/scene.cppm (100%) rename {atlas-modules => atlas}/core/scene/system_registry.cppm (100%) rename {atlas-modules => atlas}/core/scene/world.cppm (100%) rename {atlas-modules => atlas}/core/serialize/serializer.cppm (100%) rename {atlas-modules => atlas}/core/serialize/types.cppm (100%) rename {atlas-modules => atlas}/core/ui/widgets.cppm (100%) rename {atlas-modules => atlas}/core/utilities/poll_state.cppm (100%) rename {atlas-modules => atlas}/core/utilities/state.cppm (100%) rename {atlas-modules => atlas}/core/utilities/types.cppm (100%) rename {atlas-modules => atlas}/core/window.cppm (100%) rename {atlas-modules => atlas}/drivers/drivers.cppm (100%) rename {atlas-modules => atlas}/drivers/graphics_context.cppm (100%) rename {atlas-modules => atlas}/drivers/jolt_cpp/broad_phase.cppm (100%) rename {atlas-modules => atlas}/drivers/jolt_cpp/contact_listener.cppm (89%) rename {atlas-modules => atlas}/drivers/jolt_cpp/context.cppm (100%) rename {atlas-modules => atlas}/drivers/jolt_cpp/math.cppm (100%) rename {atlas-modules => atlas}/drivers/physics_context.cppm (100%) rename {atlas-modules => atlas}/drivers/renderer_system.cppm (100%) rename {atlas-modules => atlas}/drivers/vulkan/device.cppm (100%) rename {atlas-modules => atlas}/drivers/vulkan/hash.cppm (100%) rename {atlas-modules => atlas}/drivers/vulkan/imgui_context.cppm (100%) rename {atlas-modules => atlas}/drivers/vulkan/instance_context.cppm (99%) rename {atlas-modules => atlas}/drivers/vulkan/mesh.cppm (99%) rename {atlas-modules => atlas}/drivers/vulkan/physical_device.cppm (100%) rename {atlas-modules => atlas}/drivers/vulkan/render_system.cppm (89%) rename {atlas-modules => atlas}/drivers/vulkan/shader_resource_group.cppm (99%) rename {atlas-modules => atlas}/drivers/vulkan/swapchain.cppm (100%) rename {atlas-modules => atlas}/drivers/vulkan/uniforms.cppm (100%) rename {atlas-modules => atlas}/drivers/vulkan/utilities.cppm (100%) rename {atlas-modules => atlas}/drivers/vulkan/vulkan.cppm (100%) rename {atlas-modules => atlas}/drivers/vulkan/window_context.cppm (100%) rename {atlas-modules => atlas}/physics/physics_engine.cppm (100%) rename {atlas-modules => atlas}/physics/types.cppm (100%) rename {atlas-modules => atlas}/renderer/renderer.cppm (100%) diff --git a/CMakeLists.txt b/CMakeLists.txt index 54aafb23..71593f69 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -61,7 +61,7 @@ endif() # ) add_library(${PROJECT_NAME} STATIC) -add_subdirectory(editor_modules) +add_subdirectory(editor) set_packages( ENABLE_TESTS OFF @@ -111,94 +111,94 @@ target_sources(${PROJECT_NAME} PUBLIC FILE_SET CXX_MODULES TYPE CXX_MODULES FILES - atlas-modules/atlas.cppm - atlas-modules/core/api.cppm - atlas-modules/core/common.cppm - atlas-modules/core/utilities/types.cppm - atlas-modules/core/core.cppm - atlas-modules/core/logger.cppm - atlas-modules/core/application.cppm - atlas-modules/core/window.cppm + atlas/atlas.cppm + atlas/core/api.cppm + atlas/core/common.cppm + atlas/core/utilities/types.cppm + atlas/core/core.cppm + atlas/core/logger.cppm + atlas/core/application.cppm + atlas/core/window.cppm # math - atlas-modules/core/math/types.cppm - atlas-modules/core/math/math.cppm - - atlas-modules/core/scene/components.cppm - atlas-modules/core/scene/game_object.cppm - atlas-modules/core/scene/scene.cppm - atlas-modules/core/scene/world.cppm - atlas-modules/core/scene/system_registry.cppm - - atlas-modules/core/utilities/state.cppm - atlas-modules/core/utilities/poll_state.cppm - - atlas-modules/core/event/event.cppm - atlas-modules/core/event/bus.cppm - atlas-modules/core/event/listener.cppm - atlas-modules/core/event/keys.cppm - atlas-modules/core/event/mouse_codes.cppm - atlas-modules/core/event/joystick_codes.cppm - atlas-modules/core/event/types.cppm + atlas/core/math/types.cppm + atlas/core/math/math.cppm + + atlas/core/scene/components.cppm + atlas/core/scene/game_object.cppm + atlas/core/scene/scene.cppm + atlas/core/scene/world.cppm + atlas/core/scene/system_registry.cppm + + atlas/core/utilities/state.cppm + atlas/core/utilities/poll_state.cppm + + atlas/core/event/event.cppm + atlas/core/event/bus.cppm + atlas/core/event/listener.cppm + atlas/core/event/keys.cppm + atlas/core/event/mouse_codes.cppm + atlas/core/event/joystick_codes.cppm + atlas/core/event/types.cppm # editor - atlas-modules/core/editor/dockspace.cppm - atlas-modules/core/editor/menu_item.cppm - atlas-modules/core/ui/widgets.cppm - atlas-modules/core/filesystem/file_dialog.cppm + atlas/core/editor/dockspace.cppm + atlas/core/editor/menu_item.cppm + atlas/core/ui/widgets.cppm + atlas/core/filesystem/file_dialog.cppm # serialize - atlas-modules/core/serialize/types.cppm - atlas-modules/core/serialize/serializer.cppm + atlas/core/serialize/types.cppm + atlas/core/serialize/serializer.cppm - atlas-modules/renderer/renderer.cppm + atlas/renderer/renderer.cppm - atlas-modules/drivers/drivers.cppm - atlas-modules/drivers/graphics_context.cppm + atlas/drivers/drivers.cppm + atlas/drivers/graphics_context.cppm - atlas-modules/drivers/renderer_system.cppm - atlas-modules/drivers/vulkan/hash.cppm - atlas-modules/drivers/vulkan/mesh.cppm - atlas-modules/drivers/vulkan/shader_resource_group.cppm - atlas-modules/drivers/vulkan/render_system.cppm - atlas-modules/drivers/vulkan/uniforms.cppm + atlas/drivers/renderer_system.cppm + atlas/drivers/vulkan/hash.cppm + atlas/drivers/vulkan/mesh.cppm + atlas/drivers/vulkan/shader_resource_group.cppm + atlas/drivers/vulkan/render_system.cppm + atlas/drivers/vulkan/uniforms.cppm - atlas-modules/drivers/vulkan/imgui_context.cppm + atlas/drivers/vulkan/imgui_context.cppm # physics - atlas-modules/drivers/physics_context.cppm - atlas-modules/physics/types.cppm - atlas-modules/physics/physics_engine.cppm + atlas/drivers/physics_context.cppm + atlas/physics/types.cppm + atlas/physics/physics_engine.cppm # jolt_cpp - atlas-modules/drivers/jolt_cpp/math.cppm - atlas-modules/drivers/jolt_cpp/broad_phase.cppm - atlas-modules/drivers/jolt_cpp/contact_listener.cppm - atlas-modules/drivers/jolt_cpp/context.cppm + atlas/drivers/jolt_cpp/math.cppm + atlas/drivers/jolt_cpp/broad_phase.cppm + atlas/drivers/jolt_cpp/contact_listener.cppm + atlas/drivers/jolt_cpp/context.cppm - atlas-modules/drivers/vulkan/vulkan.cppm - atlas-modules/drivers/vulkan/utilities.cppm - atlas-modules/drivers/vulkan/instance_context.cppm - atlas-modules/drivers/vulkan/window_context.cppm - atlas-modules/drivers/vulkan/physical_device.cppm - atlas-modules/drivers/vulkan/device.cppm - atlas-modules/drivers/vulkan/swapchain.cppm + atlas/drivers/vulkan/vulkan.cppm + atlas/drivers/vulkan/utilities.cppm + atlas/drivers/vulkan/instance_context.cppm + atlas/drivers/vulkan/window_context.cppm + atlas/drivers/vulkan/physical_device.cppm + atlas/drivers/vulkan/device.cppm + atlas/drivers/vulkan/swapchain.cppm # entry point - # atlas-modules/core/entry_point/main.cppm + # atlas/core/entry_point/main.cppm ) target_sources(${PROJECT_NAME} PUBLIC FILE_SET CXX_MODULES TYPE CXX_MODULES - PRIVATE atlas-modules/core/entry_point/main.cpp + PRIVATE atlas/core/entry_point/main.cpp ) # target_sources(${PROJECT_NAME} PUBLIC # FILE_SET CXX_MODULES # TYPE CXX_MODULES -# PRIVATE atlas-modules/core/main.cpp +# PRIVATE atlas/core/main.cpp # ) target_compile_features(${PROJECT_NAME} PUBLIC cxx_std_23) diff --git a/atlas-modules/atlas.cppm b/atlas/atlas.cppm similarity index 100% rename from atlas-modules/atlas.cppm rename to atlas/atlas.cppm diff --git a/atlas-modules/core/api.cppm b/atlas/core/api.cppm similarity index 100% rename from atlas-modules/core/api.cppm rename to atlas/core/api.cppm diff --git a/atlas-modules/core/application.cppm b/atlas/core/application.cppm similarity index 100% rename from atlas-modules/core/application.cppm rename to atlas/core/application.cppm diff --git a/atlas-modules/core/common.cppm b/atlas/core/common.cppm similarity index 100% rename from atlas-modules/core/common.cppm rename to atlas/core/common.cppm diff --git a/atlas-modules/core/core.cppm b/atlas/core/core.cppm similarity index 100% rename from atlas-modules/core/core.cppm rename to atlas/core/core.cppm diff --git a/atlas-modules/core/editor/dockspace.cppm b/atlas/core/editor/dockspace.cppm similarity index 100% rename from atlas-modules/core/editor/dockspace.cppm rename to atlas/core/editor/dockspace.cppm diff --git a/atlas-modules/core/editor/menu_item.cppm b/atlas/core/editor/menu_item.cppm similarity index 100% rename from atlas-modules/core/editor/menu_item.cppm rename to atlas/core/editor/menu_item.cppm diff --git a/atlas-modules/core/entry_point/main.cpp b/atlas/core/entry_point/main.cpp similarity index 100% rename from atlas-modules/core/entry_point/main.cpp rename to atlas/core/entry_point/main.cpp diff --git a/atlas-modules/core/event/bus.cppm b/atlas/core/event/bus.cppm similarity index 100% rename from atlas-modules/core/event/bus.cppm rename to atlas/core/event/bus.cppm diff --git a/atlas-modules/core/event/event.cppm b/atlas/core/event/event.cppm similarity index 100% rename from atlas-modules/core/event/event.cppm rename to atlas/core/event/event.cppm diff --git a/atlas-modules/core/event/joystick_codes.cppm b/atlas/core/event/joystick_codes.cppm similarity index 100% rename from atlas-modules/core/event/joystick_codes.cppm rename to atlas/core/event/joystick_codes.cppm diff --git a/atlas-modules/core/event/keys.cppm b/atlas/core/event/keys.cppm similarity index 100% rename from atlas-modules/core/event/keys.cppm rename to atlas/core/event/keys.cppm diff --git a/atlas-modules/core/event/listener.cppm b/atlas/core/event/listener.cppm similarity index 100% rename from atlas-modules/core/event/listener.cppm rename to atlas/core/event/listener.cppm diff --git a/atlas-modules/core/event/mouse_codes.cppm b/atlas/core/event/mouse_codes.cppm similarity index 100% rename from atlas-modules/core/event/mouse_codes.cppm rename to atlas/core/event/mouse_codes.cppm diff --git a/atlas-modules/core/event/types.cppm b/atlas/core/event/types.cppm similarity index 100% rename from atlas-modules/core/event/types.cppm rename to atlas/core/event/types.cppm diff --git a/atlas-modules/core/filesystem/file_dialog.cppm b/atlas/core/filesystem/file_dialog.cppm similarity index 100% rename from atlas-modules/core/filesystem/file_dialog.cppm rename to atlas/core/filesystem/file_dialog.cppm diff --git a/atlas-modules/core/logger.cppm b/atlas/core/logger.cppm similarity index 100% rename from atlas-modules/core/logger.cppm rename to atlas/core/logger.cppm diff --git a/atlas-modules/core/math/math.cppm b/atlas/core/math/math.cppm similarity index 100% rename from atlas-modules/core/math/math.cppm rename to atlas/core/math/math.cppm diff --git a/atlas-modules/core/math/types.cppm b/atlas/core/math/types.cppm similarity index 100% rename from atlas-modules/core/math/types.cppm rename to atlas/core/math/types.cppm diff --git a/atlas-modules/core/scene/components.cppm b/atlas/core/scene/components.cppm similarity index 100% rename from atlas-modules/core/scene/components.cppm rename to atlas/core/scene/components.cppm diff --git a/atlas-modules/core/scene/game_object.cppm b/atlas/core/scene/game_object.cppm similarity index 100% rename from atlas-modules/core/scene/game_object.cppm rename to atlas/core/scene/game_object.cppm diff --git a/atlas-modules/core/scene/scene.cppm b/atlas/core/scene/scene.cppm similarity index 100% rename from atlas-modules/core/scene/scene.cppm rename to atlas/core/scene/scene.cppm diff --git a/atlas-modules/core/scene/system_registry.cppm b/atlas/core/scene/system_registry.cppm similarity index 100% rename from atlas-modules/core/scene/system_registry.cppm rename to atlas/core/scene/system_registry.cppm diff --git a/atlas-modules/core/scene/world.cppm b/atlas/core/scene/world.cppm similarity index 100% rename from atlas-modules/core/scene/world.cppm rename to atlas/core/scene/world.cppm diff --git a/atlas-modules/core/serialize/serializer.cppm b/atlas/core/serialize/serializer.cppm similarity index 100% rename from atlas-modules/core/serialize/serializer.cppm rename to atlas/core/serialize/serializer.cppm diff --git a/atlas-modules/core/serialize/types.cppm b/atlas/core/serialize/types.cppm similarity index 100% rename from atlas-modules/core/serialize/types.cppm rename to atlas/core/serialize/types.cppm diff --git a/atlas-modules/core/ui/widgets.cppm b/atlas/core/ui/widgets.cppm similarity index 100% rename from atlas-modules/core/ui/widgets.cppm rename to atlas/core/ui/widgets.cppm diff --git a/atlas-modules/core/utilities/poll_state.cppm b/atlas/core/utilities/poll_state.cppm similarity index 100% rename from atlas-modules/core/utilities/poll_state.cppm rename to atlas/core/utilities/poll_state.cppm diff --git a/atlas-modules/core/utilities/state.cppm b/atlas/core/utilities/state.cppm similarity index 100% rename from atlas-modules/core/utilities/state.cppm rename to atlas/core/utilities/state.cppm diff --git a/atlas-modules/core/utilities/types.cppm b/atlas/core/utilities/types.cppm similarity index 100% rename from atlas-modules/core/utilities/types.cppm rename to atlas/core/utilities/types.cppm diff --git a/atlas-modules/core/window.cppm b/atlas/core/window.cppm similarity index 100% rename from atlas-modules/core/window.cppm rename to atlas/core/window.cppm diff --git a/atlas-modules/drivers/drivers.cppm b/atlas/drivers/drivers.cppm similarity index 100% rename from atlas-modules/drivers/drivers.cppm rename to atlas/drivers/drivers.cppm diff --git a/atlas-modules/drivers/graphics_context.cppm b/atlas/drivers/graphics_context.cppm similarity index 100% rename from atlas-modules/drivers/graphics_context.cppm rename to atlas/drivers/graphics_context.cppm diff --git a/atlas-modules/drivers/jolt_cpp/broad_phase.cppm b/atlas/drivers/jolt_cpp/broad_phase.cppm similarity index 100% rename from atlas-modules/drivers/jolt_cpp/broad_phase.cppm rename to atlas/drivers/jolt_cpp/broad_phase.cppm diff --git a/atlas-modules/drivers/jolt_cpp/contact_listener.cppm b/atlas/drivers/jolt_cpp/contact_listener.cppm similarity index 89% rename from atlas-modules/drivers/jolt_cpp/contact_listener.cppm rename to atlas/drivers/jolt_cpp/contact_listener.cppm index 6a7dd005..7ce49ead 100644 --- a/atlas-modules/drivers/jolt_cpp/contact_listener.cppm +++ b/atlas/drivers/jolt_cpp/contact_listener.cppm @@ -63,10 +63,10 @@ export namespace atlas::physics { * @return JPH::ValidateResult */ JPH::ValidateResult OnContactValidate( - const JPH::Body& in_body1, - const JPH::Body& in_body2, - JPH::RVec3Arg in_base_offset, - const JPH::CollideShapeResult& in_collision_result) override { + const JPH::Body&, + const JPH::Body&, + JPH::RVec3Arg, + const JPH::CollideShapeResult&) override { return JPH::ValidateResult::AcceptAllContactsForThisBodyPair; } @@ -83,8 +83,8 @@ export namespace atlas::physics { */ void OnContactAdded(const JPH::Body& p_body1, const JPH::Body& p_body2, - const JPH::ContactManifold& manifold, - JPH::ContactSettings& settings) override { + const JPH::ContactManifold&, + JPH::ContactSettings&) override { event::collision_enter begin_event = { .entity1 = static_cast(p_body1.GetUserData()), .entity2 = static_cast(p_body2.GetUserData()) @@ -108,8 +108,8 @@ export namespace atlas::physics { */ void OnContactPersisted(const JPH::Body& p_body1, const JPH::Body& p_body2, - const JPH::ContactManifold& in_manifold, - JPH::ContactSettings& io_settings) override { + const JPH::ContactManifold&, + JPH::ContactSettings&) override { event::collision_persisted persisted_event = { .entity1 = static_cast(p_body1.GetUserData()), .entity2 = static_cast(p_body2.GetUserData()) @@ -125,7 +125,7 @@ export namespace atlas::physics { * @param in_sub_shape_pair The pair of shapes that no longer touch. * FIXME: Still needs to be implemented */ - void OnContactRemoved(const JPH::SubShapeIDPair& p_sub_shape_pair) override { + void OnContactRemoved(const JPH::SubShapeIDPair&) override { console_log_info("Collisions Removed!"); // For Event system to handle when collision ends } diff --git a/atlas-modules/drivers/jolt_cpp/context.cppm b/atlas/drivers/jolt_cpp/context.cppm similarity index 100% rename from atlas-modules/drivers/jolt_cpp/context.cppm rename to atlas/drivers/jolt_cpp/context.cppm diff --git a/atlas-modules/drivers/jolt_cpp/math.cppm b/atlas/drivers/jolt_cpp/math.cppm similarity index 100% rename from atlas-modules/drivers/jolt_cpp/math.cppm rename to atlas/drivers/jolt_cpp/math.cppm diff --git a/atlas-modules/drivers/physics_context.cppm b/atlas/drivers/physics_context.cppm similarity index 100% rename from atlas-modules/drivers/physics_context.cppm rename to atlas/drivers/physics_context.cppm diff --git a/atlas-modules/drivers/renderer_system.cppm b/atlas/drivers/renderer_system.cppm similarity index 100% rename from atlas-modules/drivers/renderer_system.cppm rename to atlas/drivers/renderer_system.cppm diff --git a/atlas-modules/drivers/vulkan/device.cppm b/atlas/drivers/vulkan/device.cppm similarity index 100% rename from atlas-modules/drivers/vulkan/device.cppm rename to atlas/drivers/vulkan/device.cppm diff --git a/atlas-modules/drivers/vulkan/hash.cppm b/atlas/drivers/vulkan/hash.cppm similarity index 100% rename from atlas-modules/drivers/vulkan/hash.cppm rename to atlas/drivers/vulkan/hash.cppm diff --git a/atlas-modules/drivers/vulkan/imgui_context.cppm b/atlas/drivers/vulkan/imgui_context.cppm similarity index 100% rename from atlas-modules/drivers/vulkan/imgui_context.cppm rename to atlas/drivers/vulkan/imgui_context.cppm diff --git a/atlas-modules/drivers/vulkan/instance_context.cppm b/atlas/drivers/vulkan/instance_context.cppm similarity index 99% rename from atlas-modules/drivers/vulkan/instance_context.cppm rename to atlas/drivers/vulkan/instance_context.cppm index ea2ffef6..44610546 100644 --- a/atlas-modules/drivers/vulkan/instance_context.cppm +++ b/atlas/drivers/vulkan/instance_context.cppm @@ -81,7 +81,7 @@ namespace atlas::vulkan { export class instance_context : public graphics_context { public: - instance_context(const std::string& p_name) { + instance_context(const std::string&) { VkApplicationInfo app_info = { .sType = VK_STRUCTURE_TYPE_APPLICATION_INFO, .pNext = nullptr, diff --git a/atlas-modules/drivers/vulkan/mesh.cppm b/atlas/drivers/vulkan/mesh.cppm similarity index 99% rename from atlas-modules/drivers/vulkan/mesh.cppm rename to atlas/drivers/vulkan/mesh.cppm index e473e8ba..94d797b4 100644 --- a/atlas-modules/drivers/vulkan/mesh.cppm +++ b/atlas/drivers/vulkan/mesh.cppm @@ -51,7 +51,7 @@ export namespace atlas::vulkan { m_ibo = vk::index_buffer(m_device, ibo_settings); } - mesh(const std::filesystem::path& p_filename, bool p_flip = false) { + mesh(const std::filesystem::path& p_filename, bool p_flip = false) : m_flip(p_flip) { m_physical = instance_context::physical_driver(); m_device = instance_context::logical_device(); reload_mesh(p_filename); diff --git a/atlas-modules/drivers/vulkan/physical_device.cppm b/atlas/drivers/vulkan/physical_device.cppm similarity index 100% rename from atlas-modules/drivers/vulkan/physical_device.cppm rename to atlas/drivers/vulkan/physical_device.cppm diff --git a/atlas-modules/drivers/vulkan/render_system.cppm b/atlas/drivers/vulkan/render_system.cppm similarity index 89% rename from atlas-modules/drivers/vulkan/render_system.cppm rename to atlas/drivers/vulkan/render_system.cppm index 3f7bfbbd..8c3d7e89 100644 --- a/atlas-modules/drivers/vulkan/render_system.cppm +++ b/atlas/drivers/vulkan/render_system.cppm @@ -60,7 +60,7 @@ export namespace atlas::vulkan { */ class render_system : public renderer_system { public: - render_system(const window_params& p_params, uint32_t p_image_size, const std::string& p_tag) { + render_system(const window_params& p_params, uint32_t p_image_size, const std::string&) { m_device = instance_context::logical_device(); console_log_info("m_device = {}", (m_device != nullptr)); @@ -95,34 +95,34 @@ export namespace atlas::vulkan { #endif std::array<::vk::vertex_attribute_entry, 4> attribute_entries = { ::vk::vertex_attribute_entry{ - .location = 0, - .format = ::vk::format::rgb32_sfloat, - .stride = offsetof(vk::vertex_input, position), + .location = 0, + .format = ::vk::format::rgb32_sfloat, + .stride = offsetof(vk::vertex_input, position), }, ::vk::vertex_attribute_entry{ - .location = 1, - .format = ::vk::format::rgb32_sfloat, - .stride = offsetof(vk::vertex_input, color), + .location = 1, + .format = ::vk::format::rgb32_sfloat, + .stride = offsetof(vk::vertex_input, color), }, ::vk::vertex_attribute_entry{ - .location = 2, - .format = ::vk::format::rgb32_sfloat, - .stride = offsetof(vk::vertex_input, normals), + .location = 2, + .format = ::vk::format::rgb32_sfloat, + .stride = offsetof(vk::vertex_input, normals), }, ::vk::vertex_attribute_entry{ - .location = 3, - .format = ::vk::format::rg32_sfloat, - .stride = offsetof(vk::vertex_input, uv), + .location = 3, + .format = ::vk::format::rg32_sfloat, + .stride = offsetof(vk::vertex_input, uv), } }; std::array<::vk::vertex_attribute, 1> attribute = { ::vk::vertex_attribute{ - // layout (set = 0, binding = 0) - .binding = 0, - .entries = attribute_entries, - .stride = sizeof(vk::vertex_input), - .input_rate = ::vk::input_rate::vertex, + // layout (set = 0, binding = 0) + .binding = 0, + .entries = attribute_entries, + .stride = sizeof(vk::vertex_input), + .input_rate = ::vk::input_rate::vertex, }, }; @@ -203,12 +203,12 @@ export namespace atlas::vulkan { std::array<::vk::write_buffer_descriptor, 2> set0_write_buffers = { ::vk::write_buffer_descriptor{ - .dst_binding = 0, - .uniforms = binding0_uniforms, + .dst_binding = 0, + .uniforms = binding0_uniforms, }, ::vk::write_buffer_descriptor{ - .dst_binding = 1, - .uniforms = binding1_uniforms, + .dst_binding = 1, + .uniforms = binding1_uniforms, } }; m_global_descriptors.update(set0_write_buffers); @@ -365,30 +365,30 @@ export namespace atlas::vulkan { // specify to the vk::write_descriptor_buffer std::array<::vk::write_buffer, 1> binding0_buffers = { ::vk::write_buffer{ - .buffer = m_mesh_geometry_set[p_entity.id()], - .offset = 0, - .range = m_mesh_geometry_set[p_entity.id()].size_bytes(), + .buffer = m_mesh_geometry_set[p_entity.id()], + .offset = 0, + .range = m_mesh_geometry_set[p_entity.id()].size_bytes(), } }; std::array<::vk::write_buffer, 1> binding3_buffers = { ::vk::write_buffer{ - .buffer = m_mesh_material_set[p_entity.id()], - .offset = 0, - .range = m_mesh_material_set[p_entity.id()].size_bytes(), + .buffer = m_mesh_material_set[p_entity.id()], + .offset = 0, + .range = m_mesh_material_set[p_entity.id()].size_bytes(), } }; std::vector<::vk::write_buffer_descriptor> material_uniforms = { // layout(set= 1, binding = 0) geometry_ubo ::vk::write_buffer_descriptor{ - .dst_binding = 0, - .uniforms = binding0_buffers, + .dst_binding = 0, + .uniforms = binding0_buffers, }, // layout(set= 1, binding = 3) material_ubo ::vk::write_buffer_descriptor{ - .dst_binding = 3, - .uniforms = binding3_buffers, + .dst_binding = 3, + .uniforms = binding3_buffers, }, }; @@ -408,33 +408,37 @@ export namespace atlas::vulkan { // writes to texture at layout(set = 1, binding = 1) std::array<::vk::write_image, 1> - binding1_images = { ::vk::write_image{ - .sampler = diffuse.sampler(), - .view = diffuse.image_view(), - // .image_layout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL, - .layout = ::vk::image_layout::shader_read_only_optimal, - } }; + binding1_images = { + ::vk::write_image{ + .sampler = diffuse.sampler(), + .view = diffuse.image_view(), + // .image_layout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL, + .layout = ::vk::image_layout::shader_read_only_optimal, + }, + }; // writes to texture at layout(set = 1, binding = 2) std::array<::vk::write_image, 1> - binding2_images = { ::vk::write_image{ - .sampler = specular.sampler(), - .view = specular.image_view(), - // .image_layout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL, - .layout = ::vk::image_layout::shader_read_only_optimal, - } }; + binding2_images = { + ::vk::write_image{ + .sampler = specular.sampler(), + .view = specular.image_view(), + // .image_layout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL, + .layout = ::vk::image_layout::shader_read_only_optimal, + }, + }; // vulkan image descriptors are for writing textures std::vector<::vk::write_image_descriptor> material_textures = { // layout(set = 1, binding = 1) uniform sampler2D ::vk::write_image_descriptor{ - .dst_binding = 1, - .sample_images = binding1_images, + .dst_binding = 1, + .sample_images = binding1_images, }, // layout(set = 1, binding = 2) uniform sampler2D ::vk::write_image_descriptor{ - .dst_binding = 2, - .sample_images = binding2_images, + .dst_binding = 2, + .sample_images = binding2_images, }, }; diff --git a/atlas-modules/drivers/vulkan/shader_resource_group.cppm b/atlas/drivers/vulkan/shader_resource_group.cppm similarity index 99% rename from atlas-modules/drivers/vulkan/shader_resource_group.cppm rename to atlas/drivers/vulkan/shader_resource_group.cppm index 631cf54a..16d77762 100644 --- a/atlas-modules/drivers/vulkan/shader_resource_group.cppm +++ b/atlas/drivers/vulkan/shader_resource_group.cppm @@ -39,6 +39,7 @@ namespace atlas::vulkan { return read_raw_spirv(p_shader_source.filename); } +#if ENABLE_SHADERC static std::string read_shader_source_code(const std::string& p_filename) { std::ifstream ins(p_filename, std::ios::ate | std::ios::binary); @@ -55,6 +56,7 @@ namespace atlas::vulkan { return output; } +#endif /** * compiles source code from the shader directly without needing manual @@ -66,7 +68,7 @@ namespace atlas::vulkan { * filename text entry_point: the entry point to this shader options: * compiler-specific options to enable when compiling the shader sources */ -#ifdef ENABLE_SHADERC +#if ENABLE_SHADERC static std::vector compile_source_from_file( const ::vk::shader_source& p_shader_source) { shaderc::CompileOptions options; @@ -167,7 +169,7 @@ namespace atlas::vulkan { } #endif -#if ENABLE_SHADERC +#ifdef ENABLE_SHADERC if (filepath.extension().string() != ".spv") { std::string text_source_code = read_shader_source_code(filepath.string()); diff --git a/atlas-modules/drivers/vulkan/swapchain.cppm b/atlas/drivers/vulkan/swapchain.cppm similarity index 100% rename from atlas-modules/drivers/vulkan/swapchain.cppm rename to atlas/drivers/vulkan/swapchain.cppm diff --git a/atlas-modules/drivers/vulkan/uniforms.cppm b/atlas/drivers/vulkan/uniforms.cppm similarity index 100% rename from atlas-modules/drivers/vulkan/uniforms.cppm rename to atlas/drivers/vulkan/uniforms.cppm diff --git a/atlas-modules/drivers/vulkan/utilities.cppm b/atlas/drivers/vulkan/utilities.cppm similarity index 100% rename from atlas-modules/drivers/vulkan/utilities.cppm rename to atlas/drivers/vulkan/utilities.cppm diff --git a/atlas-modules/drivers/vulkan/vulkan.cppm b/atlas/drivers/vulkan/vulkan.cppm similarity index 100% rename from atlas-modules/drivers/vulkan/vulkan.cppm rename to atlas/drivers/vulkan/vulkan.cppm diff --git a/atlas-modules/drivers/vulkan/window_context.cppm b/atlas/drivers/vulkan/window_context.cppm similarity index 100% rename from atlas-modules/drivers/vulkan/window_context.cppm rename to atlas/drivers/vulkan/window_context.cppm diff --git a/atlas-modules/physics/physics_engine.cppm b/atlas/physics/physics_engine.cppm similarity index 100% rename from atlas-modules/physics/physics_engine.cppm rename to atlas/physics/physics_engine.cppm diff --git a/atlas-modules/physics/types.cppm b/atlas/physics/types.cppm similarity index 100% rename from atlas-modules/physics/types.cppm rename to atlas/physics/types.cppm diff --git a/atlas-modules/renderer/renderer.cppm b/atlas/renderer/renderer.cppm similarity index 100% rename from atlas-modules/renderer/renderer.cppm rename to atlas/renderer/renderer.cppm From 6491b142c8043a20da72ca0962934e574b54b655 Mon Sep 17 00:00:00 2001 From: SpinnerX Date: Tue, 13 Jan 2026 13:15:56 -0800 Subject: [PATCH 30/68] Renamed from editor_modules to editor to finalize changes migrating editor code to modules --- {editor_modules => editor}/CMakeLists.txt | 0 {editor_modules => editor}/application.cpp | 0 {editor_modules => editor}/editor_world.cppm | 0 {editor_modules => editor}/level_scene.cppm | 0 4 files changed, 0 insertions(+), 0 deletions(-) rename {editor_modules => editor}/CMakeLists.txt (100%) rename {editor_modules => editor}/application.cpp (100%) rename {editor_modules => editor}/editor_world.cppm (100%) rename {editor_modules => editor}/level_scene.cppm (100%) diff --git a/editor_modules/CMakeLists.txt b/editor/CMakeLists.txt similarity index 100% rename from editor_modules/CMakeLists.txt rename to editor/CMakeLists.txt diff --git a/editor_modules/application.cpp b/editor/application.cpp similarity index 100% rename from editor_modules/application.cpp rename to editor/application.cpp diff --git a/editor_modules/editor_world.cppm b/editor/editor_world.cppm similarity index 100% rename from editor_modules/editor_world.cppm rename to editor/editor_world.cppm diff --git a/editor_modules/level_scene.cppm b/editor/level_scene.cppm similarity index 100% rename from editor_modules/level_scene.cppm rename to editor/level_scene.cppm From 104eb7699b4687d1683e581be1d9bf52548c2e2e Mon Sep 17 00:00:00 2001 From: SpinnerX Date: Tue, 13 Jan 2026 14:26:24 -0800 Subject: [PATCH 31/68] Cleaned up debugging comments --- atlas/core/entry_point/main.cpp | 9 +-------- atlas/drivers/vulkan/device.cppm | 2 -- atlas/drivers/vulkan/instance_context.cppm | 1 - atlas/drivers/vulkan/physical_device.cppm | 2 -- 4 files changed, 1 insertion(+), 13 deletions(-) diff --git a/atlas/core/entry_point/main.cpp b/atlas/core/entry_point/main.cpp index 0f84ba70..cfbf1726 100644 --- a/atlas/core/entry_point/main.cpp +++ b/atlas/core/entry_point/main.cpp @@ -59,14 +59,7 @@ int main() { return -1; } - // atlas::application_settings settings = { - // .name = "Editor", - // .width = 1900, - // .height = 600, - // .background_color = {1.f, 1.f, 1.f, 1.f}, - // }; - // atlas::ref app = atlas::create_ref(settings); - + // TODO: Level streamer is going to be replacing system_registry atlas::ref system = atlas::create_ref("system"); atlas::ref context = atlas::initialize_context("vulkan", atlas::graphics_api::vulkan); diff --git a/atlas/drivers/vulkan/device.cppm b/atlas/drivers/vulkan/device.cppm index c6d0269b..f204c8f3 100644 --- a/atlas/drivers/vulkan/device.cppm +++ b/atlas/drivers/vulkan/device.cppm @@ -139,8 +139,6 @@ namespace atlas::vulkan { vkGetDeviceQueue( m_driver, graphics_index, 0, &m_device_queues.graphics_queue); - - console_log_warn("vulkan::device constructed successfully!!!"); } // Use .destroy to explicitly invoke when to do proper vulkan cleanup diff --git a/atlas/drivers/vulkan/instance_context.cppm b/atlas/drivers/vulkan/instance_context.cppm index 44610546..4eac1cad 100644 --- a/atlas/drivers/vulkan/instance_context.cppm +++ b/atlas/drivers/vulkan/instance_context.cppm @@ -163,7 +163,6 @@ namespace atlas::vulkan { vkGetInstanceProcAddr(m_instance_handler, "vkSetDebugUtilsObjectNameEXT")); #endif - console_log_info("vulkan::instance_context finished being initialized!!!"); m_physical = physical_device(m_instance_handler); m_device = device(m_physical); diff --git a/atlas/drivers/vulkan/physical_device.cppm b/atlas/drivers/vulkan/physical_device.cppm index 6176dcd9..03956e7d 100644 --- a/atlas/drivers/vulkan/physical_device.cppm +++ b/atlas/drivers/vulkan/physical_device.cppm @@ -90,8 +90,6 @@ export namespace atlas::vulkan { m_queue_family_properties.data()); m_queue_indices = select_queue_family_indices(); - - console_log_warn("vulkan::physical_device constructed successful!!!"); } ~physical_device() = default; From 7f57500a44c8c7da7f68363e1813bc12ecfc79a7 Mon Sep 17 00:00:00 2001 From: SpinnerX Date: Tue, 13 Jan 2026 14:58:53 -0800 Subject: [PATCH 32/68] Marked instance_context destructer with overridfe keyword instead of virtual --- atlas/drivers/vulkan/instance_context.cppm | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/atlas/drivers/vulkan/instance_context.cppm b/atlas/drivers/vulkan/instance_context.cppm index 4eac1cad..4e4abb86 100644 --- a/atlas/drivers/vulkan/instance_context.cppm +++ b/atlas/drivers/vulkan/instance_context.cppm @@ -170,7 +170,7 @@ namespace atlas::vulkan { s_instance = this; } - virtual ~instance_context() { + ~instance_context() override { vkDestroyInstance(m_instance_handler, nullptr); } From 466231da7e510e787919601ab6188585718f639b Mon Sep 17 00:00:00 2001 From: SpinnerX Date: Tue, 13 Jan 2026 18:20:11 -0800 Subject: [PATCH 33/68] Added shorthand to importing utilities to using atlas.core.utilities rather then by individual module units --- CMakeLists.txt | 5 +++++ atlas/core/application.cppm | 12 ++++-------- atlas/core/entry_point/main.cpp | 2 -- atlas/core/utilities/utilities.cppm | 7 +++++++ atlas/core/window.cppm | 7 ++++--- atlas/drivers/drivers.cppm | 7 +------ atlas/drivers/jolt_cpp/context.cppm | 5 +++-- atlas/drivers/renderer_system.cppm | 7 ++++--- atlas/drivers/vulkan/device.cppm | 2 -- atlas/drivers/vulkan/render_system.cppm | 8 ++++---- atlas/drivers/vulkan/swapchain.cppm | 6 +++--- atlas/drivers/vulkan/utilities.cppm | 2 +- atlas/drivers/vulkan/window_context.cppm | 10 ++++++---- editor/application.cpp | 1 - editor/editor_world.cppm | 5 +++-- editor/level_scene.cppm | 3 ++- 16 files changed, 47 insertions(+), 42 deletions(-) create mode 100644 atlas/core/utilities/utilities.cppm diff --git a/CMakeLists.txt b/CMakeLists.txt index 71593f69..e408a4a1 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -111,10 +111,13 @@ target_sources(${PROJECT_NAME} PUBLIC FILE_SET CXX_MODULES TYPE CXX_MODULES FILES + + # core atlas/atlas.cppm atlas/core/api.cppm atlas/core/common.cppm atlas/core/utilities/types.cppm + atlas/core/utilities/utilities.cppm atlas/core/core.cppm atlas/core/logger.cppm atlas/core/application.cppm @@ -124,6 +127,7 @@ target_sources(${PROJECT_NAME} PUBLIC atlas/core/math/types.cppm atlas/core/math/math.cppm + # scenes atlas/core/scene/components.cppm atlas/core/scene/game_object.cppm atlas/core/scene/scene.cppm @@ -133,6 +137,7 @@ target_sources(${PROJECT_NAME} PUBLIC atlas/core/utilities/state.cppm atlas/core/utilities/poll_state.cppm + # event atlas/core/event/event.cppm atlas/core/event/bus.cppm atlas/core/event/listener.cppm diff --git a/atlas/core/application.cppm b/atlas/core/application.cppm index 11636cfc..5bb9e944 100644 --- a/atlas/core/application.cppm +++ b/atlas/core/application.cppm @@ -15,15 +15,11 @@ module; export module atlas.application; -import atlas.graphics_api; -import atlas.logger; -import atlas.core.utilities.types; -import atlas.common; +import atlas.core.utilities; +import atlas.core.utilities.poll_state; import atlas.window; import atlas.drivers; import atlas.core.event; -import atlas.core.utilities.poll_state; -import atlas.logger; import atlas.drivers.renderer_system; import atlas.renderer; import atlas.drivers.vulkan.instance_context; @@ -205,10 +201,10 @@ export namespace atlas { // renderer is in sync when swapchain is resized ::vk::command_buffer currently_active = m_window->active_command(m_current_frame_index); - invoke_on_update(); - invoke_physics_update(); + invoke_on_update(); + invoke_defer_update(); // We want this to be called after late update // This queries all camera objects within the camera system diff --git a/atlas/core/entry_point/main.cpp b/atlas/core/entry_point/main.cpp index cfbf1726..cedb919f 100644 --- a/atlas/core/entry_point/main.cpp +++ b/atlas/core/entry_point/main.cpp @@ -5,8 +5,6 @@ import atlas.common; import atlas.logger; import atlas.graphics_api; -import atlas.core.utilities.state; - // expose visibility to ref import atlas.drivers.graphics_context; diff --git a/atlas/core/utilities/utilities.cppm b/atlas/core/utilities/utilities.cppm new file mode 100644 index 00000000..0261aff2 --- /dev/null +++ b/atlas/core/utilities/utilities.cppm @@ -0,0 +1,7 @@ +export module atlas.core.utilities; + +export import atlas.logger; +export import atlas.common; +export import atlas.graphics_api; +export import atlas.core.utilities.types; +export import atlas.core.utilities.state; diff --git a/atlas/core/window.cppm b/atlas/core/window.cppm index 2e007be2..a04421c0 100644 --- a/atlas/core/window.cppm +++ b/atlas/core/window.cppm @@ -6,9 +6,10 @@ module; export module atlas.window; -import atlas.common; -import atlas.graphics_api; -import atlas.core.utilities.types; +// import atlas.common; +// import atlas.graphics_api; +// import atlas.core.utilities.types; +import atlas.core.utilities; import atlas.drivers.vulkan.swapchain; import vk; diff --git a/atlas/drivers/drivers.cppm b/atlas/drivers/drivers.cppm index 0e79a89f..b074c6cf 100644 --- a/atlas/drivers/drivers.cppm +++ b/atlas/drivers/drivers.cppm @@ -5,12 +5,7 @@ module; export module atlas.drivers; -import atlas.common; -import atlas.core.utilities.types; -// import atlas.vulkan.window_context; -// import atlas.drivers.vulkan; -import atlas.graphics_api; -import atlas.logger; +import atlas.core.utilities; import atlas.window; import atlas.drivers.graphics_context; import atlas.drivers.vulkan.window_context; diff --git a/atlas/drivers/jolt_cpp/context.cppm b/atlas/drivers/jolt_cpp/context.cppm index 5ef59c6b..33e07f72 100644 --- a/atlas/drivers/jolt_cpp/context.cppm +++ b/atlas/drivers/jolt_cpp/context.cppm @@ -37,8 +37,9 @@ module; export module atlas.drivers.jolt_cpp.context; -import atlas.logger; -import atlas.common; +// import atlas.logger; +// import atlas.common; +import atlas.core.utilities; import atlas.core.scene.components; import atlas.drivers.jolt_cpp.broad_phase; diff --git a/atlas/drivers/renderer_system.cppm b/atlas/drivers/renderer_system.cppm index 548c7ef0..69e54727 100644 --- a/atlas/drivers/renderer_system.cppm +++ b/atlas/drivers/renderer_system.cppm @@ -6,10 +6,11 @@ module; export module atlas.drivers.renderer_system; -import vk; -import atlas.core.utilities.types; -import atlas.common; +// import atlas.core.utilities.types; +// import atlas.common; +import atlas.core.utilities; import atlas.core.scene; +import vk; export namespace atlas { /** diff --git a/atlas/drivers/vulkan/device.cppm b/atlas/drivers/vulkan/device.cppm index f204c8f3..c05f3202 100644 --- a/atlas/drivers/vulkan/device.cppm +++ b/atlas/drivers/vulkan/device.cppm @@ -19,8 +19,6 @@ module; export module atlas.drivers.vulkan.device; -import atlas.logger; - import atlas.drivers.vulkan.utilities; import atlas.drivers.vulkan.physical_device; diff --git a/atlas/drivers/vulkan/render_system.cppm b/atlas/drivers/vulkan/render_system.cppm index 8c3d7e89..d7cd72bb 100644 --- a/atlas/drivers/vulkan/render_system.cppm +++ b/atlas/drivers/vulkan/render_system.cppm @@ -14,11 +14,11 @@ module; export module atlas.drivers.vulkan.render_system; import atlas.drivers.renderer_system; -import atlas.logger; -import atlas.common; +// import atlas.logger; +// import atlas.common; +// import atlas.core.utilities.types; +import atlas.core.utilities; import vk; -import atlas.core.utilities.types; -import atlas.common; import atlas.core.scene; import atlas.drivers.vulkan.instance_context; import atlas.drivers.vulkan.physical_device; diff --git a/atlas/drivers/vulkan/swapchain.cppm b/atlas/drivers/vulkan/swapchain.cppm index bdf08ae9..21733e36 100644 --- a/atlas/drivers/vulkan/swapchain.cppm +++ b/atlas/drivers/vulkan/swapchain.cppm @@ -8,9 +8,9 @@ export module atlas.drivers.vulkan.swapchain; import vk; -import atlas.logger; - -import atlas.core.utilities.types; +// import atlas.logger; +// import atlas.core.utilities.types; +import atlas.core.utilities; import atlas.drivers.vulkan.instance_context; import atlas.drivers.vulkan.physical_device; import atlas.drivers.vulkan.device; diff --git a/atlas/drivers/vulkan/utilities.cppm b/atlas/drivers/vulkan/utilities.cppm index 4536cc07..3611e637 100644 --- a/atlas/drivers/vulkan/utilities.cppm +++ b/atlas/drivers/vulkan/utilities.cppm @@ -4,8 +4,8 @@ module; #include export module atlas.drivers.vulkan.utilities; - import atlas.logger; + export namespace atlas { namespace vulkan { diff --git a/atlas/drivers/vulkan/window_context.cppm b/atlas/drivers/vulkan/window_context.cppm index 544fe778..7f5033e5 100644 --- a/atlas/drivers/vulkan/window_context.cppm +++ b/atlas/drivers/vulkan/window_context.cppm @@ -16,14 +16,16 @@ module; export module atlas.drivers.vulkan.window_context; +// import atlas.logger; +// import atlas.core.utilities.types; +import atlas.core.utilities; +import vk; + import atlas.window; -import atlas.logger; import atlas.drivers.vulkan.instance_context; import atlas.drivers.vulkan.utilities; -import atlas.core.utilities.types; - import atlas.drivers.vulkan.swapchain; -import vk; + export namespace atlas { namespace vulkan { diff --git a/editor/application.cpp b/editor/application.cpp index ba72fb14..45036d21 100644 --- a/editor/application.cpp +++ b/editor/application.cpp @@ -1,6 +1,5 @@ import atlas.application; import atlas.common; -import atlas.logger; import editor_world; import atlas.core.scene.system_registry; diff --git a/editor/editor_world.cppm b/editor/editor_world.cppm index 545237a5..ff458685 100644 --- a/editor/editor_world.cppm +++ b/editor/editor_world.cppm @@ -4,8 +4,9 @@ module; export module editor_world; -import atlas.common; -import atlas.logger; +// import atlas.common; +// import atlas.logger; +import atlas.core.utilities; import atlas.core.scene.world; import atlas.core.event.bus; import atlas.core.scene.system_registry; diff --git a/editor/level_scene.cppm b/editor/level_scene.cppm index 1d623d4b..191d9519 100644 --- a/editor/level_scene.cppm +++ b/editor/level_scene.cppm @@ -16,6 +16,8 @@ module; export module level_scene; +// import atlas.logger; +import atlas.core.utilities; import atlas.application; import atlas.core.event.types; import atlas.core.scene; @@ -32,7 +34,6 @@ import atlas.application; import atlas.core.ui.widgets; import atlas.core.editor.menu_item; import atlas.core.serialize; -import atlas.logger; import atlas.physics.engine; static void ui_component_list(flecs::entity& p_selected_entity) { From 0413f4a921735e2e8697cf186ad48213b37afdc2 Mon Sep 17 00:00:00 2001 From: SpinnerX Date: Tue, 13 Jan 2026 18:53:08 -0800 Subject: [PATCH 34/68] Added module unit atlas.core.event as a module partition to the events sources --- atlas/core/application.cppm | 1 - atlas/core/event/bus.cppm | 4 ++-- atlas/core/event/event.cppm | 6 ++++++ atlas/core/event/joystick_codes.cppm | 2 +- atlas/core/event/keys.cppm | 2 +- atlas/core/event/listener.cppm | 2 +- atlas/core/event/mouse_codes.cppm | 2 +- atlas/core/event/types.cppm | 2 +- atlas/core/scene/scene.cppm | 2 +- atlas/drivers/jolt_cpp/contact_listener.cppm | 4 ++-- atlas/drivers/jolt_cpp/context.cppm | 2 +- atlas/drivers/physics_context.cppm | 2 +- atlas/physics/physics_engine.cppm | 2 +- editor/editor_world.cppm | 5 +++-- editor/level_scene.cppm | 10 +++++----- 15 files changed, 27 insertions(+), 21 deletions(-) diff --git a/atlas/core/application.cppm b/atlas/core/application.cppm index 5bb9e944..11d38fa9 100644 --- a/atlas/core/application.cppm +++ b/atlas/core/application.cppm @@ -1,7 +1,6 @@ module; #include -// #include #include #define GLM_ENABLE_EXPERIMENTAL #include diff --git a/atlas/core/event/bus.cppm b/atlas/core/event/bus.cppm index f5aa4311..9bed5ecd 100644 --- a/atlas/core/event/bus.cppm +++ b/atlas/core/event/bus.cppm @@ -6,9 +6,9 @@ module; #include #include -export module atlas.core.event.bus; +export module atlas.core.event:bus; -import atlas.core.event.listener; +import :listener; export namespace atlas::event { /** diff --git a/atlas/core/event/event.cppm b/atlas/core/event/event.cppm index b29de79b..60201d8f 100644 --- a/atlas/core/event/event.cppm +++ b/atlas/core/event/event.cppm @@ -8,6 +8,12 @@ module; export module atlas.core.event; +export import :keys; +export import :mouse_codes; +export import :types; +export import :listener; +export import :bus; + namespace atlas { /** diff --git a/atlas/core/event/joystick_codes.cppm b/atlas/core/event/joystick_codes.cppm index ba7239c8..074820da 100644 --- a/atlas/core/event/joystick_codes.cppm +++ b/atlas/core/event/joystick_codes.cppm @@ -2,7 +2,7 @@ module; #include -export module atlas.core.event.joystick_codes; +export module atlas.core.event:joystick_codes; namespace atlas::event { enum JoystickCodes : int { diff --git a/atlas/core/event/keys.cppm b/atlas/core/event/keys.cppm index 60167c88..6db80291 100644 --- a/atlas/core/event/keys.cppm +++ b/atlas/core/event/keys.cppm @@ -2,7 +2,7 @@ module; #include -export module atlas.core.event.keys; +export module atlas.core.event:keys; export namespace atlas::event { diff --git a/atlas/core/event/listener.cppm b/atlas/core/event/listener.cppm index 0c845d4b..f6560408 100644 --- a/atlas/core/event/listener.cppm +++ b/atlas/core/event/listener.cppm @@ -3,7 +3,7 @@ module; #include #include -export module atlas.core.event.listener; +export module atlas.core.event:listener; export namespace atlas::event { /** diff --git a/atlas/core/event/mouse_codes.cppm b/atlas/core/event/mouse_codes.cppm index c357a868..e1addddc 100644 --- a/atlas/core/event/mouse_codes.cppm +++ b/atlas/core/event/mouse_codes.cppm @@ -2,7 +2,7 @@ module; #include -export module atlas.core.event.mouse_codes; +export module atlas.core.event:mouse_codes; namespace atlas::event { enum Mouse : uint32_t { diff --git a/atlas/core/event/types.cppm b/atlas/core/event/types.cppm index 2cfb2406..b86b9503 100644 --- a/atlas/core/event/types.cppm +++ b/atlas/core/event/types.cppm @@ -2,7 +2,7 @@ module; #include -export module atlas.core.event.types; +export module atlas.core.event:types; export namespace atlas::event { diff --git a/atlas/core/scene/scene.cppm b/atlas/core/scene/scene.cppm index a2957ed1..2228be0f 100644 --- a/atlas/core/scene/scene.cppm +++ b/atlas/core/scene/scene.cppm @@ -6,7 +6,7 @@ module; export module atlas.core.scene; import atlas.common; -import atlas.core.event.bus; +import atlas.core.event; import atlas.core.scene.game_object; diff --git a/atlas/drivers/jolt_cpp/contact_listener.cppm b/atlas/drivers/jolt_cpp/contact_listener.cppm index 7ce49ead..9acaa324 100644 --- a/atlas/drivers/jolt_cpp/contact_listener.cppm +++ b/atlas/drivers/jolt_cpp/contact_listener.cppm @@ -34,8 +34,8 @@ module; export module atlas.drivers.jolt_cpp.contact_listener; import atlas.logger; -import atlas.core.event.bus; -import atlas.core.event.types; +// import atlas.core.event.types; +import atlas.core.event; export namespace atlas::physics { /** diff --git a/atlas/drivers/jolt_cpp/context.cppm b/atlas/drivers/jolt_cpp/context.cppm index 33e07f72..aaf658b4 100644 --- a/atlas/drivers/jolt_cpp/context.cppm +++ b/atlas/drivers/jolt_cpp/context.cppm @@ -40,6 +40,7 @@ export module atlas.drivers.jolt_cpp.context; // import atlas.logger; // import atlas.common; import atlas.core.utilities; +import atlas.core.event; import atlas.core.scene.components; import atlas.drivers.jolt_cpp.broad_phase; @@ -47,7 +48,6 @@ import atlas.drivers.jolt_cpp.contact_listener; import atlas.drivers.jolt_cpp.types; import atlas.drivers.physics_context; -import atlas.core.event.bus; import atlas.drivers.jolt_cpp.types; namespace atlas::physics { diff --git a/atlas/drivers/physics_context.cppm b/atlas/drivers/physics_context.cppm index 44bec3ec..a15f0fe7 100644 --- a/atlas/drivers/physics_context.cppm +++ b/atlas/drivers/physics_context.cppm @@ -40,7 +40,7 @@ export module atlas.drivers.physics_context; import atlas.common; import atlas.core.scene.components; -import atlas.core.event.bus; +import atlas.core.event; diff --git a/atlas/physics/physics_engine.cppm b/atlas/physics/physics_engine.cppm index f4e81745..e95d2035 100644 --- a/atlas/physics/physics_engine.cppm +++ b/atlas/physics/physics_engine.cppm @@ -7,7 +7,7 @@ export module atlas.physics.engine; import atlas.common; import atlas.core.scene.components; -import atlas.core.event.bus; +import atlas.core.event; import atlas.drivers.physics_context; import atlas.drivers.physics_context; import atlas.drivers.jolt_cpp.context; diff --git a/editor/editor_world.cppm b/editor/editor_world.cppm index ff458685..9e8929ab 100644 --- a/editor/editor_world.cppm +++ b/editor/editor_world.cppm @@ -8,9 +8,10 @@ export module editor_world; // import atlas.logger; import atlas.core.utilities; import atlas.core.scene.world; -import atlas.core.event.bus; +// import atlas.core.event.bus; +// import atlas.core.event.types; +import atlas.core.event; import atlas.core.scene.system_registry; -import atlas.core.event.types; import atlas.drivers.renderer_system; import level_scene; diff --git a/editor/level_scene.cppm b/editor/level_scene.cppm index 191d9519..510c9efd 100644 --- a/editor/level_scene.cppm +++ b/editor/level_scene.cppm @@ -19,16 +19,16 @@ export module level_scene; // import atlas.logger; import atlas.core.utilities; import atlas.application; -import atlas.core.event.types; import atlas.core.scene; import atlas.core.scene.game_object; -import atlas.core.event.bus; +// import atlas.core.event.bus; +// import atlas.core.event.keys; +// import atlas.core.event.mouse_codes; +// import atlas.core.event.types; +import atlas.core.event; import atlas.core.scene.components; import atlas.core.utilities.state; import atlas.core.math; -import atlas.core.event; -import atlas.core.event.keys; -import atlas.core.event.mouse_codes; import atlas.core.editor.dockspace; import atlas.application; import atlas.core.ui.widgets; From 78b86621a417b27ead0194a1179dbb743f1d403e Mon Sep 17 00:00:00 2001 From: SpinnerX Date: Wed, 14 Jan 2026 14:01:09 -0800 Subject: [PATCH 35/68] Prepared build system for making TheAtlasEngine consumable --- CMakeLists.txt | 2 +- conanfile.py | 33 +++++++++++++-------------------- 2 files changed, 14 insertions(+), 21 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index e408a4a1..70d3a113 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -61,7 +61,7 @@ endif() # ) add_library(${PROJECT_NAME} STATIC) -add_subdirectory(editor) +# add_subdirectory(editor) set_packages( ENABLE_TESTS OFF diff --git a/conanfile.py b/conanfile.py index 36fcc636..80783df1 100644 --- a/conanfile.py +++ b/conanfile.py @@ -2,11 +2,12 @@ from conan.tools.cmake import CMakeToolchain, CMake, cmake_layout, CMakeDeps from conan.tools.files import copy import os +from pathlib import Path import shutil class AtlasRecipe(ConanFile): name = "atlas" - version = "0.4" + version = "0.5" package_type = "library" license = "Apache-2.0" homepage = "https://github.com/engine3d-dev/TheAtlasEngine" @@ -18,8 +19,8 @@ class AtlasRecipe(ConanFile): # Specifying our build_type is only Debug and Release options = {"shared": [True, False], "fPIC": [True, False], "enable_tests_only": [True, False], "enable_shaderc": [True, False]} - default_options = {"shared": False, "fPIC": True, "enable_tests_only": True, "enable_shaderc": True} - + default_options = {"shared": False, "fPIC": True, "enable_tests_only": True, "enable_shaderc": False} + exports_sources = "atlas/*", "tests/*", "CMakeLists.txt", "LICENSE" def build_requirements(self): self.tool_requires("cmake/4.1.1") @@ -45,13 +46,6 @@ def requirements(self): self.requires("nfd/2.0") self.requires("watcher/0.12.0") self.requires("boost-ext-ut/2.3.1") - - def export_sources(self): - copy(self,"CMakeLists.txt", self.recipe_folder, self.export_sources_folder) - copy(self,"src/CMakeLists.txt", self.recipe_folder, self.export_sources_folder) - copy(self,"*.hpp", self.recipe_folder, self.export_sources_folder) - copy(self,"*.cpp", self.recipe_folder, self.export_sources_folder) - copy(self, "shader_ubo_tutorial", self.recipe_folder, self.export_sources_folder) def config_options(self): if self.settings.os == "Windows": @@ -74,6 +68,7 @@ def generate(self): tc = CMakeToolchain(self) # TODO: Remove this once fixing shaderc issue in the CI is resolved # These are options that can be enabled/disabled with the `-o` parameter when compiling with `conan` command + tc.generator = "Ninja" tc.variables["USE_SHADERC"] = self.options.enable_shaderc tc.variables["ENABLE_TESTS_ONLY"] = self.options.enable_tests_only tc.generate() @@ -103,17 +98,15 @@ def build(self): def package(self): - copy(self, "LICENSE", src=self.source_folder, dst=os.path.join(self.package_folder, "licenses")) - copy(self, pattern="*.hpp", src=os.path.join(self.source_folder, "atlas"), dst=os.path.join(self.package_folder, "atlas")) - copy(self, pattern="*.a", src=self.build_folder, dst=os.path.join(self.package_folder, "lib"), keep_path=False) - copy(self, pattern="*.so", src=self.build_folder, dst=os.path.join(self.package_folder, "lib"), keep_path=False) - copy(self, pattern="*.lib", src=self.build_folder, dst=os.path.join(self.package_folder, "lib"), keep_path=False) - copy(self, pattern="*.dll", src=self.build_folder, dst=os.path.join(self.package_folder, "bin"), keep_path=False) - copy(self, pattern="*.dylib", src=self.build_folder, dst=os.path.join(self.package_folder, "lib"), keep_path=False) cmake = CMake(self) cmake.install() + copy(self, "LICENSE", + dst=Path(self.package_folder) / "licenses", + src=self.source_folder) + def package_info(self): - self.cpp_info.set_property("cmake_target_name", "atlas::atlas") - self.cpp_info.libs = ["atlas"] - self.cpp_info.includedirs = ['./', './atlas'] # Ordered list of include paths + # DISABLE Conan's config file generation + self.cpp_info.set_property("cmake_find_mode", "none") + # Tell CMake to include this directory in its search path + self.cpp_info.builddirs.append("lib/cmake") From d5d1e023b39a4efc3d852b2c60658e45419e3ba8 Mon Sep 17 00:00:00 2001 From: SpinnerX Date: Wed, 14 Jan 2026 14:01:58 -0800 Subject: [PATCH 36/68] Using the utilities import instead for importing utilities --- atlas/core/scene/scene.cppm | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/atlas/core/scene/scene.cppm b/atlas/core/scene/scene.cppm index 2228be0f..2620e0c4 100644 --- a/atlas/core/scene/scene.cppm +++ b/atlas/core/scene/scene.cppm @@ -5,7 +5,7 @@ module; export module atlas.core.scene; -import atlas.common; +import atlas.core.utilities; import atlas.core.event; import atlas.core.scene.game_object; From b782d6ef80cd2128d1e7fec8de957c149551141d Mon Sep 17 00:00:00 2001 From: SpinnerX Date: Wed, 14 Jan 2026 14:02:31 -0800 Subject: [PATCH 37/68] Added missing include to mesh.cppm --- atlas/drivers/drivers.cppm | 1 - atlas/drivers/vulkan/mesh.cppm | 1 + 2 files changed, 1 insertion(+), 1 deletion(-) diff --git a/atlas/drivers/drivers.cppm b/atlas/drivers/drivers.cppm index b074c6cf..774ea01e 100644 --- a/atlas/drivers/drivers.cppm +++ b/atlas/drivers/drivers.cppm @@ -1,7 +1,6 @@ module; #include -#include export module atlas.drivers; diff --git a/atlas/drivers/vulkan/mesh.cppm b/atlas/drivers/vulkan/mesh.cppm index 94d797b4..23e63b0e 100644 --- a/atlas/drivers/vulkan/mesh.cppm +++ b/atlas/drivers/vulkan/mesh.cppm @@ -8,6 +8,7 @@ module; #include #include #include +#include export module atlas.drivers.vulkan.mesh; import vk; From 17f053cfb946a7378cbc9218a6396844dcb973dc Mon Sep 17 00:00:00 2001 From: SpinnerX Date: Thu, 15 Jan 2026 01:03:43 -0800 Subject: [PATCH 38/68] Removed importing atlas.window from imgui_context as a dependency import; replaced with importing swapchain instead --- atlas/core/application.cppm | 2 +- atlas/drivers/vulkan/imgui_context.cppm | 14 +-- atlas/drivers/window_context.cppm | 128 ++++++++++++++++++++++++ 3 files changed, 136 insertions(+), 8 deletions(-) create mode 100644 atlas/drivers/window_context.cppm diff --git a/atlas/core/application.cppm b/atlas/core/application.cppm index 11d38fa9..2f9f674e 100644 --- a/atlas/core/application.cppm +++ b/atlas/core/application.cppm @@ -79,7 +79,7 @@ export namespace atlas { p_params.background_color.w, }); - m_ui_context = vulkan::imgui_context(m_window); + m_ui_context = vulkan::imgui_context(m_window->current_swapchain(), *m_window); vulkan::instance_context::submit_resource_free([this](){ m_ui_context.destroy(); diff --git a/atlas/drivers/vulkan/imgui_context.cppm b/atlas/drivers/vulkan/imgui_context.cppm index 732d23e7..3307c48a 100644 --- a/atlas/drivers/vulkan/imgui_context.cppm +++ b/atlas/drivers/vulkan/imgui_context.cppm @@ -12,11 +12,11 @@ export module atlas.drivers.vulkan.imgui_context; import atlas.common; import vk; -import atlas.window; import atlas.drivers.vulkan.instance_context; import atlas.drivers.vulkan.physical_device; import atlas.drivers.vulkan.device; +import atlas.drivers.vulkan.swapchain; namespace atlas::vulkan { static void im_gui_layout_color_modification() { @@ -58,12 +58,12 @@ namespace atlas::vulkan { public: imgui_context() = default; - imgui_context(const ref& p_window_ctx) { + imgui_context(const swapchain& p_swapchain_ctx, GLFWwindow* p_window_ctx) { m_instance = instance_context::handle(); m_physical = instance_context::physical_driver(); m_driver = instance_context::logical_device(); - m_current_swapchain_handler = p_window_ctx->current_swapchain(); + m_current_swapchain_handler = p_swapchain_ctx; // Setting up imgui IMGUI_CHECKVERSION(); @@ -95,7 +95,7 @@ namespace atlas::vulkan { } m_viewport_command_buffers.resize( - p_window_ctx->current_swapchain().image_size()); + p_swapchain_ctx.image_size()); for (size_t i = 0; i < m_viewport_command_buffers.size(); i++) { ::vk::command_params settings = { @@ -147,9 +147,9 @@ namespace atlas::vulkan { m_driver, &desc_pool_create_info, nullptr, &m_desc_pool), "vkCreateDescriptorPool"); - create(*p_window_ctx, - p_window_ctx->current_swapchain().image_size(), - p_window_ctx->current_swapchain().swapchain_renderpass()); + create(p_window_ctx, + p_swapchain_ctx.image_size(), + p_swapchain_ctx.swapchain_renderpass()); } void create(GLFWwindow* p_window_handler, const uint32_t& p_image_size, const VkRenderPass& p_current_renderpass) { diff --git a/atlas/drivers/window_context.cppm b/atlas/drivers/window_context.cppm new file mode 100644 index 00000000..27910e32 --- /dev/null +++ b/atlas/drivers/window_context.cppm @@ -0,0 +1,128 @@ +module; + +#include +#include +#include + +export module atlas.drivers.window_context; + +// import atlas.common; +// import atlas.graphics_api; +// import atlas.core.utilities.types; +import atlas.core.utilities; +import atlas.drivers.vulkan.window_context; +import atlas.drivers.vulkan.swapchain; +import vk; + +export namespace atlas { + + class window { + public: + virtual ~window() = default; + + [[nodiscard]] window_params data() const { + return get_params(); + } + + /** + * @brief Checks if window is available to close + */ + [[nodiscard]] bool available() const { + return !glfwWindowShouldClose(native_window()); + } + + /** + * @brief Returns the aspect ratio of the current window + */ + [[nodiscard]] float aspect_ratio() const { + return static_cast(get_params().width) / static_cast(get_params().height); + } + + /** + * @brief gives you the next presentable image to use and the index to + * retrieving that image + * + * @return uint32_t + */ + [[nodiscard]] uint32_t acquired_next_frame() { + return read_acquired_next_frame(); + } + + /** + * @brief Returns the window's currently selected swapchain + */ + [[nodiscard]] vulkan::swapchain current_swapchain() const { + return window_swapchain(); + } + + /** + * @brief retrieves the current command buffer using the current frame + * index to ensure we are processing commands to the right command + * buffer in our current frame + * + * @return command buffer to actively record commands to + */ + vk::command_buffer active_command(uint32_t p_frame_index) { + return current_active_command(p_frame_index); + } + + /** + * @brief operator overload for treating atlas::window as a GLFWwindow + * handle + */ + operator GLFWwindow*() const { return native_window(); } + + /** + * @brief operator overload for treating atlas::window as a GLFWwindow + * handle + */ + operator GLFWwindow*() { return native_window(); } + + /** + * @brief Closing the window operation + */ + void close() { + glfwSetWindowShouldClose(native_window(), true); + } + + /** + * @brief does the presentation operation that is operated internally + * with the vulkan swapchain + * + * @param p_current_frame_idx is current frame index to currently + * process an image in the current frame + */ + void present(const uint32_t& p_current_frame_idx) { + return present_frame(p_current_frame_idx); + } + + protected: + [[nodiscard]] virtual window_params get_params() const = 0; + [[nodiscard]] virtual GLFWwindow* native_window() const = 0; + [[nodiscard]] virtual uint32_t read_acquired_next_frame() = 0; + [[nodiscard]] virtual vulkan::swapchain window_swapchain() const = 0; + + [[nodiscard]] virtual vk::command_buffer current_active_command(uint32_t p_frame_idx) = 0; + + virtual void present_frame(const uint32_t& p_current_frame) = 0; + }; + + /** + * @brief constructs an atlas::window + * + * There should only ever be one window constructed throughout the entire + * application + * + * @param p_settings is the window settings to construct the window with + * + * @return shared_ptr + */ + ref initialize_window(const window_params& p_params, graphics_api p_api) { + switch(p_api) { + case graphics_api::vulkan: + return create_ref(p_params); + default: + return nullptr; + } + } +}; \ No newline at end of file From 39bc640ecb2a8f4d2f199b71fb810335106053c9 Mon Sep 17 00:00:00 2001 From: SpinnerX Date: Thu, 15 Jan 2026 02:32:58 -0800 Subject: [PATCH 39/68] WIP in adding in the import for atlas.renderer.loader --- CMakeLists.txt | 8 ++++++-- atlas/atlas.cppm | 2 +- atlas/core/application.cppm | 1 + atlas/core/entry_point/main.cpp | 3 ++- atlas/drivers/drivers.cppm | 19 +++++++++---------- atlas/renderer/loader.cppm | 28 ++++++++++++++++++++++++++++ 6 files changed, 47 insertions(+), 14 deletions(-) create mode 100644 atlas/renderer/loader.cppm diff --git a/CMakeLists.txt b/CMakeLists.txt index 70d3a113..6cdaf53c 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -61,7 +61,7 @@ endif() # ) add_library(${PROJECT_NAME} STATIC) -# add_subdirectory(editor) +add_subdirectory(editor) set_packages( ENABLE_TESTS OFF @@ -156,12 +156,16 @@ target_sources(${PROJECT_NAME} PUBLIC atlas/core/serialize/types.cppm atlas/core/serialize/serializer.cppm + # renderer + atlas/renderer/loader.cppm atlas/renderer/renderer.cppm atlas/drivers/drivers.cppm atlas/drivers/graphics_context.cppm atlas/drivers/renderer_system.cppm + + atlas/drivers/vulkan/hash.cppm atlas/drivers/vulkan/mesh.cppm atlas/drivers/vulkan/shader_resource_group.cppm @@ -181,7 +185,7 @@ target_sources(${PROJECT_NAME} PUBLIC atlas/drivers/jolt_cpp/contact_listener.cppm atlas/drivers/jolt_cpp/context.cppm - + # drivers atlas/drivers/vulkan/vulkan.cppm atlas/drivers/vulkan/utilities.cppm atlas/drivers/vulkan/instance_context.cppm diff --git a/atlas/atlas.cppm b/atlas/atlas.cppm index a35f512f..2bc3f22b 100644 --- a/atlas/atlas.cppm +++ b/atlas/atlas.cppm @@ -6,7 +6,7 @@ export module atlas; export import atlas.graphics_api; export import atlas.logger; -export import atlas.drivers; +// export import atlas.drivers; // atlas.subsystem_type_name - this is for anything that is globally needed throughout TheAtlasEngine,like loggers, utilities, etc. // import :internal_stuff - is used for implementation-specific details such as (implementing API-agnostic implementation specific to subsystems) diff --git a/atlas/core/application.cppm b/atlas/core/application.cppm index 2f9f674e..2c4467c3 100644 --- a/atlas/core/application.cppm +++ b/atlas/core/application.cppm @@ -18,6 +18,7 @@ import atlas.core.utilities; import atlas.core.utilities.poll_state; import atlas.window; import atlas.drivers; +import atlas.renderer.loader; import atlas.core.event; import atlas.drivers.renderer_system; import atlas.renderer; diff --git a/atlas/core/entry_point/main.cpp b/atlas/core/entry_point/main.cpp index cedb919f..dbfa10bc 100644 --- a/atlas/core/entry_point/main.cpp +++ b/atlas/core/entry_point/main.cpp @@ -9,7 +9,8 @@ import atlas.graphics_api; import atlas.drivers.graphics_context; // this includes initialize_context -import atlas.drivers; +// import atlas.drivers; +import atlas.renderer.loader; import atlas.core.scene.system_registry; // Defined in the user-application side diff --git a/atlas/drivers/drivers.cppm b/atlas/drivers/drivers.cppm index 774ea01e..e078cc66 100644 --- a/atlas/drivers/drivers.cppm +++ b/atlas/drivers/drivers.cppm @@ -6,9 +6,8 @@ export module atlas.drivers; import atlas.core.utilities; import atlas.window; -import atlas.drivers.graphics_context; +// import atlas.drivers.graphics_context; import atlas.drivers.vulkan.window_context; -import atlas.drivers.vulkan.instance_context; /** * @brief This drivers.cppm will contain API-agnostic implementation that may be widely implemented differently. @@ -40,12 +39,12 @@ export namespace atlas { * @brief construct a new graphics context and initializes that API * @return shared_ptr */ - ref initialize_context(const std::string& p_name, graphics_api p_api) { - switch(p_api) { - case graphics_api::vulkan: - return create_ref(p_name); - default: - return nullptr; - } - } + // ref initialize_context(const std::string& p_name, graphics_api p_api) { + // switch(p_api) { + // case graphics_api::vulkan: + // return create_ref(p_name); + // default: + // return nullptr; + // } + // } }; \ No newline at end of file diff --git a/atlas/renderer/loader.cppm b/atlas/renderer/loader.cppm new file mode 100644 index 00000000..616cc6bf --- /dev/null +++ b/atlas/renderer/loader.cppm @@ -0,0 +1,28 @@ +module; + +#include +#include + +export module atlas.renderer.loader; + +import atlas.core.utilities; + +import atlas.drivers.graphics_context; + +import atlas.drivers.vulkan.instance_context; + + +export namespace atlas { + /** + * @brief construct a new graphics context and initializes that API + * @return shared_ptr + */ + ref initialize_context(const std::string& p_name, graphics_api p_api) { + switch(p_api) { + case graphics_api::vulkan: + return create_ref(p_name); + default: + return nullptr; + } + } +}; \ No newline at end of file From 1a6acc10a4991fcaf0175b45f8690a3166cc3e76 Mon Sep 17 00:00:00 2001 From: SpinnerX Date: Thu, 15 Jan 2026 13:34:11 -0800 Subject: [PATCH 40/68] WIP in cleaning up the imports --- atlas/atlas.cppm | 16 ---- atlas/core/application.cppm | 1 + atlas/drivers/drivers.cppm | 13 --- atlas/drivers/vulkan/vulkan.cppm | 5 -- atlas/drivers/window_context.cppm | 128 ------------------------------ 5 files changed, 1 insertion(+), 162 deletions(-) delete mode 100644 atlas/atlas.cppm delete mode 100644 atlas/drivers/vulkan/vulkan.cppm delete mode 100644 atlas/drivers/window_context.cppm diff --git a/atlas/atlas.cppm b/atlas/atlas.cppm deleted file mode 100644 index 2bc3f22b..00000000 --- a/atlas/atlas.cppm +++ /dev/null @@ -1,16 +0,0 @@ -export module atlas; - -// export import core; -// export import atlas.application; - -export import atlas.graphics_api; -export import atlas.logger; - -// export import atlas.drivers; - -// atlas.subsystem_type_name - this is for anything that is globally needed throughout TheAtlasEngine,like loggers, utilities, etc. -// import :internal_stuff - is used for implementation-specific details such as (implementing API-agnostic implementation specific to subsystems) -// Example: Like API-agnostic renderer and API-agnostic physics system. - -export namespace atlas { -}; \ No newline at end of file diff --git a/atlas/core/application.cppm b/atlas/core/application.cppm index 2c4467c3..5749371a 100644 --- a/atlas/core/application.cppm +++ b/atlas/core/application.cppm @@ -27,6 +27,7 @@ import atlas.core.scene; import atlas.core.scene.world; import atlas.core.scene.system_registry; import atlas.core.scene.components; + import atlas.core.math; import atlas.drivers.vulkan.imgui_context; import vk; diff --git a/atlas/drivers/drivers.cppm b/atlas/drivers/drivers.cppm index e078cc66..9e1fa881 100644 --- a/atlas/drivers/drivers.cppm +++ b/atlas/drivers/drivers.cppm @@ -34,17 +34,4 @@ export namespace atlas { return nullptr; } } - - /** - * @brief construct a new graphics context and initializes that API - * @return shared_ptr - */ - // ref initialize_context(const std::string& p_name, graphics_api p_api) { - // switch(p_api) { - // case graphics_api::vulkan: - // return create_ref(p_name); - // default: - // return nullptr; - // } - // } }; \ No newline at end of file diff --git a/atlas/drivers/vulkan/vulkan.cppm b/atlas/drivers/vulkan/vulkan.cppm deleted file mode 100644 index 01c253ea..00000000 --- a/atlas/drivers/vulkan/vulkan.cppm +++ /dev/null @@ -1,5 +0,0 @@ -export module atlas.drivers.vulkan; - -// export import :instance_context; -// export import :utilities; -export import atlas.drivers.vulkan.utilities; \ No newline at end of file diff --git a/atlas/drivers/window_context.cppm b/atlas/drivers/window_context.cppm deleted file mode 100644 index 27910e32..00000000 --- a/atlas/drivers/window_context.cppm +++ /dev/null @@ -1,128 +0,0 @@ -module; - -#include -#include -#include - -export module atlas.drivers.window_context; - -// import atlas.common; -// import atlas.graphics_api; -// import atlas.core.utilities.types; -import atlas.core.utilities; -import atlas.drivers.vulkan.window_context; -import atlas.drivers.vulkan.swapchain; -import vk; - -export namespace atlas { - - class window { - public: - virtual ~window() = default; - - [[nodiscard]] window_params data() const { - return get_params(); - } - - /** - * @brief Checks if window is available to close - */ - [[nodiscard]] bool available() const { - return !glfwWindowShouldClose(native_window()); - } - - /** - * @brief Returns the aspect ratio of the current window - */ - [[nodiscard]] float aspect_ratio() const { - return static_cast(get_params().width) / static_cast(get_params().height); - } - - /** - * @brief gives you the next presentable image to use and the index to - * retrieving that image - * - * @return uint32_t - */ - [[nodiscard]] uint32_t acquired_next_frame() { - return read_acquired_next_frame(); - } - - /** - * @brief Returns the window's currently selected swapchain - */ - [[nodiscard]] vulkan::swapchain current_swapchain() const { - return window_swapchain(); - } - - /** - * @brief retrieves the current command buffer using the current frame - * index to ensure we are processing commands to the right command - * buffer in our current frame - * - * @return command buffer to actively record commands to - */ - vk::command_buffer active_command(uint32_t p_frame_index) { - return current_active_command(p_frame_index); - } - - /** - * @brief operator overload for treating atlas::window as a GLFWwindow - * handle - */ - operator GLFWwindow*() const { return native_window(); } - - /** - * @brief operator overload for treating atlas::window as a GLFWwindow - * handle - */ - operator GLFWwindow*() { return native_window(); } - - /** - * @brief Closing the window operation - */ - void close() { - glfwSetWindowShouldClose(native_window(), true); - } - - /** - * @brief does the presentation operation that is operated internally - * with the vulkan swapchain - * - * @param p_current_frame_idx is current frame index to currently - * process an image in the current frame - */ - void present(const uint32_t& p_current_frame_idx) { - return present_frame(p_current_frame_idx); - } - - protected: - [[nodiscard]] virtual window_params get_params() const = 0; - [[nodiscard]] virtual GLFWwindow* native_window() const = 0; - [[nodiscard]] virtual uint32_t read_acquired_next_frame() = 0; - [[nodiscard]] virtual vulkan::swapchain window_swapchain() const = 0; - - [[nodiscard]] virtual vk::command_buffer current_active_command(uint32_t p_frame_idx) = 0; - - virtual void present_frame(const uint32_t& p_current_frame) = 0; - }; - - /** - * @brief constructs an atlas::window - * - * There should only ever be one window constructed throughout the entire - * application - * - * @param p_settings is the window settings to construct the window with - * - * @return shared_ptr - */ - ref initialize_window(const window_params& p_params, graphics_api p_api) { - switch(p_api) { - case graphics_api::vulkan: - return create_ref(p_params); - default: - return nullptr; - } - } -}; \ No newline at end of file From 07e52453548c525c4a8d10cdf4012c58319c75ed Mon Sep 17 00:00:00 2001 From: SpinnerX Date: Thu, 15 Jan 2026 13:34:24 -0800 Subject: [PATCH 41/68] WIP updating the project cmake --- CMakeLists.txt | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 6cdaf53c..ad5680f8 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -113,7 +113,7 @@ target_sources(${PROJECT_NAME} PUBLIC FILES # core - atlas/atlas.cppm + # atlas/atlas.cppm atlas/core/api.cppm atlas/core/common.cppm atlas/core/utilities/types.cppm @@ -186,7 +186,8 @@ target_sources(${PROJECT_NAME} PUBLIC atlas/drivers/jolt_cpp/context.cppm # drivers - atlas/drivers/vulkan/vulkan.cppm + # atlas/drivers/window_context.cppm + # atlas/drivers/vulkan/vulkan.cppm atlas/drivers/vulkan/utilities.cppm atlas/drivers/vulkan/instance_context.cppm atlas/drivers/vulkan/window_context.cppm From 3118097fca3180ad0b3948c3d8150bd1eb7dce55 Mon Sep 17 00:00:00 2001 From: SpinnerX Date: Thu, 15 Jan 2026 14:02:58 -0800 Subject: [PATCH 42/68] WIP in passing around the graphics context to application --- atlas/core/application.cppm | 19 ++++++++++++++----- atlas/core/entry_point/main.cpp | 4 ++-- atlas/drivers/drivers.cppm | 6 +++--- atlas/drivers/graphics_context.cppm | 12 ++++++++++++ atlas/drivers/vulkan/imgui_context.cppm | 5 +++-- atlas/drivers/vulkan/instance_context.cppm | 12 ++++++++---- atlas/drivers/vulkan/render_system.cppm | 11 ++++------- atlas/drivers/vulkan/window_context.cppm | 10 ++++++---- atlas/renderer/renderer.cppm | 5 +++-- editor/application.cpp | 8 +++++--- 10 files changed, 60 insertions(+), 32 deletions(-) diff --git a/atlas/core/application.cppm b/atlas/core/application.cppm index 5749371a..a67a8256 100644 --- a/atlas/core/application.cppm +++ b/atlas/core/application.cppm @@ -31,9 +31,13 @@ import atlas.core.scene.components; import atlas.core.math; import atlas.drivers.vulkan.imgui_context; import vk; +import atlas.drivers.graphics_context; export namespace atlas { + struct resource { + ref graphics_context; + }; /** * @brief application properties settings for the window @@ -62,7 +66,7 @@ export namespace atlas { * @param p_settings is the specific application settings to configure * how the application may be setup */ - application(const application_settings& p_params) { + application(ref p_context, const application_settings& p_params) { console_log_info("application(const application_settings&) initialized!!!"); window_params params = { @@ -70,10 +74,10 @@ export namespace atlas { .height = p_params.height, .name = p_params.name, }; - m_window = initialize_window(params, graphics_api::vulkan); + m_window = initialize_window(p_context, params, graphics_api::vulkan); event::set_window_size(static_cast(*m_window)); - m_renderer = initialize_renderer(graphics_api::vulkan, params, m_window->current_swapchain().image_size(), "Renderer"); + m_renderer = initialize_renderer(p_context, graphics_api::vulkan, params, m_window->current_swapchain().image_size(), "Renderer"); m_renderer->set_background_color({ p_params.background_color.x, p_params.background_color.y, @@ -81,11 +85,16 @@ export namespace atlas { p_params.background_color.w, }); - m_ui_context = vulkan::imgui_context(m_window->current_swapchain(), *m_window); + m_ui_context = vulkan::imgui_context(p_context->handle(), m_window->current_swapchain(), *m_window); + + // vulkan::instance_context::submit_resource_free([this](){ + // m_ui_context.destroy(); + // }); - vulkan::instance_context::submit_resource_free([this](){ + p_context->submit_resource_free([this](){ m_ui_context.destroy(); }); + s_instance = this; } diff --git a/atlas/core/entry_point/main.cpp b/atlas/core/entry_point/main.cpp index dbfa10bc..9c19e887 100644 --- a/atlas/core/entry_point/main.cpp +++ b/atlas/core/entry_point/main.cpp @@ -14,7 +14,7 @@ import atlas.renderer.loader; import atlas.core.scene.system_registry; // Defined in the user-application side -[[nodiscard]] atlas::ref initialize_application(); +[[nodiscard]] atlas::ref initialize_application(atlas::ref p_context); // /* @@ -62,7 +62,7 @@ int main() { atlas::ref system = atlas::create_ref("system"); atlas::ref context = atlas::initialize_context("vulkan", atlas::graphics_api::vulkan); - atlas::ref app = initialize_application(); + atlas::ref app = initialize_application(context); app->execute(); diff --git a/atlas/drivers/drivers.cppm b/atlas/drivers/drivers.cppm index 9e1fa881..8a849984 100644 --- a/atlas/drivers/drivers.cppm +++ b/atlas/drivers/drivers.cppm @@ -6,7 +6,7 @@ export module atlas.drivers; import atlas.core.utilities; import atlas.window; -// import atlas.drivers.graphics_context; +import atlas.drivers.graphics_context; import atlas.drivers.vulkan.window_context; /** @@ -26,10 +26,10 @@ export namespace atlas { * * @return shared_ptr */ - ref initialize_window(const window_params& p_params, graphics_api p_api) { + ref initialize_window(ref p_context, const window_params& p_params, graphics_api p_api) { switch(p_api) { case graphics_api::vulkan: - return create_ref(p_params); + return create_ref(p_context, p_params); default: return nullptr; } diff --git a/atlas/drivers/graphics_context.cppm b/atlas/drivers/graphics_context.cppm index 1e76029f..8a966947 100644 --- a/atlas/drivers/graphics_context.cppm +++ b/atlas/drivers/graphics_context.cppm @@ -1,6 +1,7 @@ module; #include +#include export module atlas.drivers.graphics_context; @@ -13,12 +14,23 @@ export namespace atlas { public: virtual ~graphics_context() = default; + void submit_resource_free(const std::function& p_resource) { + return context_submit_resource_free(p_resource); + } + + [[nodiscard]] VkInstance handle() const { + return context_handle(); + } + void destroy() { return destroy_context(); } protected: virtual void destroy_context() = 0; + virtual void context_submit_resource_free(const std::function& p_resource) = 0; + + [[nodiscard]] virtual VkInstance context_handle() const = 0; }; }; \ No newline at end of file diff --git a/atlas/drivers/vulkan/imgui_context.cppm b/atlas/drivers/vulkan/imgui_context.cppm index 3307c48a..9fc56aff 100644 --- a/atlas/drivers/vulkan/imgui_context.cppm +++ b/atlas/drivers/vulkan/imgui_context.cppm @@ -58,8 +58,9 @@ namespace atlas::vulkan { public: imgui_context() = default; - imgui_context(const swapchain& p_swapchain_ctx, GLFWwindow* p_window_ctx) { - m_instance = instance_context::handle(); + imgui_context(const VkInstance& p_instance, const swapchain& p_swapchain_ctx, GLFWwindow* p_window_ctx) { + // m_instance = instance_context::handle(); + m_instance = p_instance; m_physical = instance_context::physical_driver(); m_driver = instance_context::logical_device(); diff --git a/atlas/drivers/vulkan/instance_context.cppm b/atlas/drivers/vulkan/instance_context.cppm index 4e4abb86..80b828fd 100644 --- a/atlas/drivers/vulkan/instance_context.cppm +++ b/atlas/drivers/vulkan/instance_context.cppm @@ -174,10 +174,6 @@ namespace atlas::vulkan { vkDestroyInstance(m_instance_handler, nullptr); } - static VkInstance handle() { - return s_instance->m_instance_handler; - } - /** * @brief returns function pointer to allow for setting debug object * name @@ -219,6 +215,14 @@ namespace atlas::vulkan { } protected: + [[nodiscard]] VkInstance context_handle() const override { + return m_instance_handler; + } + + void context_submit_resource_free(const std::function& p_resource) override { + m_resources_free.push_back(p_resource); + } + void destroy_context() override { console_log_info("destroy_context!"); for (auto& callback : m_resources_free) { diff --git a/atlas/drivers/vulkan/render_system.cppm b/atlas/drivers/vulkan/render_system.cppm index d7cd72bb..decac6b9 100644 --- a/atlas/drivers/vulkan/render_system.cppm +++ b/atlas/drivers/vulkan/render_system.cppm @@ -14,12 +14,10 @@ module; export module atlas.drivers.vulkan.render_system; import atlas.drivers.renderer_system; -// import atlas.logger; -// import atlas.common; -// import atlas.core.utilities.types; import atlas.core.utilities; import vk; import atlas.core.scene; +import atlas.drivers.graphics_context; import atlas.drivers.vulkan.instance_context; import atlas.drivers.vulkan.physical_device; import atlas.drivers.vulkan.device; @@ -60,11 +58,10 @@ export namespace atlas::vulkan { */ class render_system : public renderer_system { public: - render_system(const window_params& p_params, uint32_t p_image_size, const std::string&) { + render_system(ref p_context, const window_params& p_params, uint32_t p_image_size, const std::string&) { + m_physical = instance_context::physical_driver(); m_device = instance_context::logical_device(); - console_log_info("m_device = {}", (m_device != nullptr)); - m_physical = instance_context::physical_driver(); m_window_extent = p_params; m_image_count = p_image_size; @@ -224,7 +221,7 @@ export namespace atlas::vulkan { m_white_texture = ::vk::texture(m_device, extent, m_physical.memory_properties()); - instance_context::submit_resource_free([this]() { + p_context->submit_resource_free([this]() { console_log_info("vulkan::render_system destructin invoked!!"); m_white_texture.destroy(); m_shader_group.destroy(); diff --git a/atlas/drivers/vulkan/window_context.cppm b/atlas/drivers/vulkan/window_context.cppm index 7f5033e5..18aee443 100644 --- a/atlas/drivers/vulkan/window_context.cppm +++ b/atlas/drivers/vulkan/window_context.cppm @@ -22,7 +22,8 @@ import atlas.core.utilities; import vk; import atlas.window; -import atlas.drivers.vulkan.instance_context; +import atlas.drivers.graphics_context; +// import atlas.drivers.vulkan.instance_context; import atlas.drivers.vulkan.utilities; import atlas.drivers.vulkan.swapchain; @@ -34,7 +35,7 @@ export namespace atlas { */ class window_context : public window { public: - window_context(const window_params& p_params) : m_params(p_params) { + window_context(ref p_context, const window_params& p_params) : m_params(p_params) { console_log_info("window_context constructed!!!"); @@ -47,7 +48,8 @@ export namespace atlas { glfwWindowHint(GLFW_CLIENT_API, GLFW_NO_API); glfwWindowHint(GLFW_RESIZABLE, GLFW_TRUE); - m_instance = instance_context::handle(); + // m_instance = instance_context::handle(); + m_instance = p_context->handle(); m_window_handle = glfwCreateWindow(static_cast(m_params.width), static_cast(m_params.height), m_params.name.c_str(), nullptr, nullptr); @@ -64,7 +66,7 @@ export namespace atlas { m_window_swapchain = swapchain(m_window_surface, m_params); - instance_context::submit_resource_free([this](){ + p_context->submit_resource_free([this](){ console_log_info("vulkan::window_context submit_resource_free invokation!"); m_window_swapchain.destroy(); }); diff --git a/atlas/renderer/renderer.cppm b/atlas/renderer/renderer.cppm index 529a27a5..9fd6fd12 100644 --- a/atlas/renderer/renderer.cppm +++ b/atlas/renderer/renderer.cppm @@ -10,13 +10,14 @@ import atlas.drivers.renderer_system; import atlas.drivers.vulkan.render_system; import atlas.common; import atlas.graphics_api; +import atlas.drivers.graphics_context; import atlas.core.utilities.types; export namespace atlas { - ref initialize_renderer(graphics_api p_api, const window_params& p_window_extent, uint32_t p_image_size, const std::string& p_name) { + ref initialize_renderer(ref p_context, graphics_api p_api, const window_params& p_window_extent, uint32_t p_image_size, const std::string& p_name) { switch(p_api) { case graphics_api::vulkan: - return create_ref(p_window_extent, p_image_size, p_name); + return create_ref(p_context, p_window_extent, p_image_size, p_name); default: return nullptr; } diff --git a/editor/application.cpp b/editor/application.cpp index 45036d21..c48d5c04 100644 --- a/editor/application.cpp +++ b/editor/application.cpp @@ -4,9 +4,11 @@ import atlas.common; import editor_world; import atlas.core.scene.system_registry; +import atlas.drivers.graphics_context; + class test_application : public atlas::application { public: - test_application(const atlas::application_settings& p_settings) : atlas::application(p_settings) { + test_application(atlas::ref p_context, const atlas::application_settings& p_settings) : atlas::application(p_context, p_settings) { // atlas::register_update(this, &test_application::on_update);std::pmr::monotonic_buffer_resource resource{ 4096 }; // m_allocator.construct(&resource); @@ -22,12 +24,12 @@ class test_application : public atlas::application { }; -atlas::ref initialize_application() { +atlas::ref initialize_application(atlas::ref p_contetxt) { atlas::application_settings settings = { .name = "Editor", .width = 1200, .height = 800, .background_color = { 0.f, 0.f, 0.f, 0.f }, }; - return create_ref(settings); + return create_ref(p_contetxt, settings); } \ No newline at end of file From 452057a010f62ef503970fc365af5d2f0a843e96 Mon Sep 17 00:00:00 2001 From: SpinnerX Date: Thu, 15 Jan 2026 14:15:07 -0800 Subject: [PATCH 43/68] Application class cleanup by removing API's that utilize static --- atlas/core/application.cppm | 50 ++++++------------------------------- editor/level_scene.cppm | 7 +++--- 2 files changed, 11 insertions(+), 46 deletions(-) diff --git a/atlas/core/application.cppm b/atlas/core/application.cppm index a67a8256..21b5fdf5 100644 --- a/atlas/core/application.cppm +++ b/atlas/core/application.cppm @@ -79,10 +79,10 @@ export namespace atlas { m_renderer = initialize_renderer(p_context, graphics_api::vulkan, params, m_window->current_swapchain().image_size(), "Renderer"); m_renderer->set_background_color({ - p_params.background_color.x, - p_params.background_color.y, - p_params.background_color.z, - p_params.background_color.w, + p_params.background_color.x, + p_params.background_color.y, + p_params.background_color.z, + p_params.background_color.w, }); m_ui_context = vulkan::imgui_context(p_context->handle(), m_window->current_swapchain(), *m_window); @@ -99,7 +99,7 @@ export namespace atlas { } ~application() { - destroy(); + m_window->close(); } /** @@ -315,41 +315,6 @@ export namespace atlas { return m_window->current_swapchain(); } - /** - * @brief destroys the application completely - * - * TODO: Not make this static because you should not allow for this to - * be a direct calls users can have access to - */ - static void destroy() { - s_instance->m_window->close(); - } - - /** - * @brief gives you the current aspect ratio based on the dimensions of - * the window - * - * @return a float which is just a static_cast(width / height); - */ - static float aspect_ratio() { - return s_instance->m_window->aspect_ratio(); - } - - /** - * @brief Intended to get the image size so when you use current_frame() - * to get thje frame index, that you are not making an attempt at - * accessing anything outside of the frame. - * - * @return uint32_t - */ - static uint32_t image_size() { - return s_instance->m_window->current_swapchain().image_size(); - } - - static window_params params() { - return s_instance->m_window->current_swapchain().settings(); - } - protected: [[nodiscard]] ref renderer_instance() const { return m_renderer; @@ -366,7 +331,6 @@ export namespace atlas { vulkan::imgui_context m_ui_context; static application* s_instance; }; -}; - -atlas::application* atlas::application::s_instance = nullptr; \ No newline at end of file + application* application::s_instance = nullptr; +}; \ No newline at end of file diff --git a/editor/level_scene.cppm b/editor/level_scene.cppm index 510c9efd..18e40240 100644 --- a/editor/level_scene.cppm +++ b/editor/level_scene.cppm @@ -379,9 +379,10 @@ public: m_editor_menu.end(); if (ImGui::Begin("Viewport")) { - glm::vec2 viewport_panel_size = - glm::vec2{ atlas::application::params().width, - atlas::application::params().height }; + // TODO: Consider doing this a different way, but not with static. + // glm::vec2 viewport_panel_size = + // glm::vec2{ atlas::application::params().width, + // atlas::application::params().height }; ImGui::End(); } From ada78c6ed76a0a23d3f82d1e3bc356b5c596e221 Mon Sep 17 00:00:00 2001 From: SpinnerX Date: Thu, 15 Jan 2026 14:22:02 -0800 Subject: [PATCH 44/68] Updated on_update registration callback to take a single parameter that represents the delta time for each frame of application's iteration --- atlas/core/application.cppm | 2 +- atlas/core/utilities/poll_state.cppm | 8 ++++---- atlas/core/utilities/state.cppm | 4 ++-- editor/level_scene.cppm | 4 ++-- 4 files changed, 9 insertions(+), 9 deletions(-) diff --git a/atlas/core/application.cppm b/atlas/core/application.cppm index 21b5fdf5..34910d56 100644 --- a/atlas/core/application.cppm +++ b/atlas/core/application.cppm @@ -213,7 +213,7 @@ export namespace atlas { invoke_physics_update(); - invoke_on_update(); + invoke_on_update(m_delta_time); invoke_defer_update(); // We want this to be called after late update diff --git a/atlas/core/utilities/poll_state.cppm b/atlas/core/utilities/poll_state.cppm index 3f85cb0c..62152d26 100644 --- a/atlas/core/utilities/poll_state.cppm +++ b/atlas/core/utilities/poll_state.cppm @@ -7,7 +7,7 @@ export module atlas.core.utilities.poll_state; export namespace atlas { - inline std::unordered_map> s_update{}; + inline std::unordered_map> s_update{}; inline std::unordered_map> s_defer_update{}; inline std::unordered_map> s_ui_update{}; @@ -16,7 +16,7 @@ export namespace atlas { inline std::unordered_map> s_start{}; // TODO: Look into a different way of doing this - void poll_update(void* p_address,const std::function& p_callback) { + void poll_update(void* p_address,const std::function& p_callback) { s_update.emplace(p_address, p_callback); } @@ -75,9 +75,9 @@ export namespace atlas { * As thesse are intended for invoking those queue's directly. * */ - void invoke_on_update() { + void invoke_on_update(float p_delta_time) { for (auto& [address, on_update] : s_update) { - on_update(); + on_update(p_delta_time); } } diff --git a/atlas/core/utilities/state.cppm b/atlas/core/utilities/state.cppm index 6633b8f1..214e976c 100644 --- a/atlas/core/utilities/state.cppm +++ b/atlas/core/utilities/state.cppm @@ -70,8 +70,8 @@ export namespace atlas { static_assert(std::is_member_pointer_v, "Cannot register a function that is not a member " "function of a class object"); - poll_update(p_instance, [p_instance, p_callable]() { - (p_instance->*p_callable)(); + poll_update(p_instance, [p_instance, p_callable](float p_delta_time) { + (p_instance->*p_callable)(p_delta_time); }); } diff --git a/editor/level_scene.cppm b/editor/level_scene.cppm index 18e40240..e687c808 100644 --- a/editor/level_scene.cppm +++ b/editor/level_scene.cppm @@ -286,9 +286,9 @@ public: m_physics_engine = atlas::physics::engine(registry, *event_handle()); } - void on_update() { + void on_update(float p_delta_time) { auto query_cameras = query_builder().build(); - float dt = atlas::application::delta_time(); + float dt = p_delta_time; query_cameras.each([this, dt](atlas::perspective_camera& p_camera, atlas::transform& p_transform) { From 18d17361734449907a4b233e76ec15a86b40768c Mon Sep 17 00:00:00 2001 From: SpinnerX Date: Thu, 15 Jan 2026 15:53:35 -0800 Subject: [PATCH 45/68] Applied frames in flight to get the current frame index --- atlas/core/application.cppm | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/atlas/core/application.cppm b/atlas/core/application.cppm index 34910d56..a55feaa8 100644 --- a/atlas/core/application.cppm +++ b/atlas/core/application.cppm @@ -199,17 +199,20 @@ export namespace atlas { current_world_scope.progress(m_delta_time); m_current_frame_index = m_window->acquired_next_frame(); + console_log_info("current_frame_raw_index = {}", m_current_frame_index); // Current commands that are going to be iterated through // Prevents things like stalling so the CPU doesnt have to wait for // the GPU to fully complete before starting on the next frame - // Command buffer uses this to track the frames to process its - // commands currently_active_frame = (m_current_frame_index + 1) % - // m_window->current_swapchain().settings().frames_in_flight; + // Command buffer uses this to track the frames to process its commands. + // current_frame = (acquired_next_frame + 1) % frames_in_flight; + auto current_frame = (m_current_frame_index + 1) % 2; + console_log_info("current_frame = {}", current_frame); + // TODO: Going to need to figure out where to put this // Added this here because to ensure the handlers being used by the // renderer is in sync when swapchain is resized - ::vk::command_buffer currently_active = m_window->active_command(m_current_frame_index); + ::vk::command_buffer currently_active = m_window->active_command(current_frame); invoke_physics_update(); From a24a856a1899e0bd33308fa7e88b46dad9fcd2ef Mon Sep 17 00:00:00 2001 From: SpinnerX Date: Thu, 15 Jan 2026 21:13:48 -0800 Subject: [PATCH 46/68] More code cleanup to the vulkan::render_system and replaced std::array with glm::vec4 instead for setting background color --- atlas/core/application.cppm | 7 +- atlas/drivers/renderer_system.cppm | 4 +- atlas/drivers/vulkan/render_system.cppm | 186 ++++++++++++------------ 3 files changed, 96 insertions(+), 101 deletions(-) diff --git a/atlas/core/application.cppm b/atlas/core/application.cppm index a55feaa8..1e131ce1 100644 --- a/atlas/core/application.cppm +++ b/atlas/core/application.cppm @@ -78,12 +78,7 @@ export namespace atlas { event::set_window_size(static_cast(*m_window)); m_renderer = initialize_renderer(p_context, graphics_api::vulkan, params, m_window->current_swapchain().image_size(), "Renderer"); - m_renderer->set_background_color({ - p_params.background_color.x, - p_params.background_color.y, - p_params.background_color.z, - p_params.background_color.w, - }); + m_renderer->set_background_color(p_params.background_color); m_ui_context = vulkan::imgui_context(p_context->handle(), m_window->current_swapchain(), *m_window); diff --git a/atlas/drivers/renderer_system.cppm b/atlas/drivers/renderer_system.cppm index 69e54727..852c2831 100644 --- a/atlas/drivers/renderer_system.cppm +++ b/atlas/drivers/renderer_system.cppm @@ -71,7 +71,7 @@ export namespace atlas { * @brief sets the background color and request that change to the * graphics API */ - void set_background_color(const std::array& p_color) { + void set_background_color(const glm::vec4& p_color) { return background_color(p_color); } @@ -90,7 +90,7 @@ export namespace atlas { uint32_t p_current_frame) = 0; virtual void post_frame() = 0; - virtual void background_color(const std::array& p_color) = 0; + virtual void background_color(const glm::vec4& p_color) = 0; virtual void current_scene(ref) = 0; }; diff --git a/atlas/drivers/vulkan/render_system.cppm b/atlas/drivers/vulkan/render_system.cppm index decac6b9..9f3c1e3e 100644 --- a/atlas/drivers/vulkan/render_system.cppm +++ b/atlas/drivers/vulkan/render_system.cppm @@ -67,63 +67,63 @@ export namespace atlas::vulkan { #ifdef USE_SHADERC console_log_info("shaderc enabled!!"); - std::array<::vk::shader_source, 2> shader_sources = { - ::vk::shader_source{ + std::array shader_sources = { + vk::shader_source{ "experimental-shaders/test.vert", - ::vk::shader_stage::vertex, + vk::shader_stage::vertex, }, - ::vk::shader_source{ + vk::shader_source{ "experimental-shaders/test.frag", - ::vk::shader_stage::fragment, + vk::shader_stage::fragment, } }; #else console_log_info("shaderc disabled!!"); - std::array<::vk::shader_source, 2> shader_sources = { - ::vk::shader_source{ + std::array shader_sources = { + vk::shader_source{ "experimental-shaders/test.vert.spv", - ::vk::shader_stage::vertex, + vk::shader_stage::vertex, }, - ::vk::shader_source{ + vk::shader_source{ "experimental-shaders/test.frag.spv", - ::vk::shader_stage::fragment, + vk::shader_stage::fragment, } }; #endif - std::array<::vk::vertex_attribute_entry, 4> attribute_entries = { - ::vk::vertex_attribute_entry{ + std::array attribute_entries = { + vk::vertex_attribute_entry{ .location = 0, - .format = ::vk::format::rgb32_sfloat, + .format = vk::format::rgb32_sfloat, .stride = offsetof(vk::vertex_input, position), }, - ::vk::vertex_attribute_entry{ + vk::vertex_attribute_entry{ .location = 1, - .format = ::vk::format::rgb32_sfloat, + .format = vk::format::rgb32_sfloat, .stride = offsetof(vk::vertex_input, color), }, - ::vk::vertex_attribute_entry{ + vk::vertex_attribute_entry{ .location = 2, - .format = ::vk::format::rgb32_sfloat, + .format = vk::format::rgb32_sfloat, .stride = offsetof(vk::vertex_input, normals), }, - ::vk::vertex_attribute_entry{ + vk::vertex_attribute_entry{ .location = 3, - .format = ::vk::format::rg32_sfloat, + .format = vk::format::rg32_sfloat, .stride = offsetof(vk::vertex_input, uv), } }; - std::array<::vk::vertex_attribute, 1> attribute = { - ::vk::vertex_attribute{ + std::array attribute = { + vk::vertex_attribute{ // layout (set = 0, binding = 0) .binding = 0, .entries = attribute_entries, .stride = sizeof(vk::vertex_input), - .input_rate = ::vk::input_rate::vertex, + .input_rate = vk::input_rate::vertex, }, }; - ::vk::shader_resource_info shader_info = { + vk::shader_resource_info shader_info = { .sources = shader_sources, }; @@ -136,74 +136,74 @@ export namespace atlas::vulkan { console_log_error("{}", e.what()); } // Setting global descriptor set 0 - std::vector<::vk::descriptor_entry> set0_entries = { - ::vk::descriptor_entry{ + std::vector set0_entries = { + vk::descriptor_entry{ // specifies "layout (set = 0, binding = 0) uniform GlobalUbo" - .type = ::vk::buffer::uniform, + .type = vk::buffer::uniform, .binding_point = { .binding = 0, - .stage = ::vk::shader_stage::vertex, + .stage = vk::shader_stage::vertex, }, .descriptor_count = 1, }, - ::vk::descriptor_entry{ + vk::descriptor_entry{ // specifies "layout (set = 0, binding = 1) uniform light_ubo" - .type = ::vk::buffer::uniform, + .type = vk::buffer::uniform, .binding_point = { .binding = 1, - .stage = ::vk::shader_stage::fragment, + .stage = vk::shader_stage::fragment, }, .descriptor_count = 1, }, }; // uint32_t image_count = image_count; - ::vk::descriptor_layout set0_layout = { + vk::descriptor_layout set0_layout = { .slot = 0, .max_sets = m_image_count, .entries = set0_entries, }; - m_global_descriptors = ::vk::descriptor_resource(m_device, set0_layout); + m_global_descriptors = vk::descriptor_resource(m_device, set0_layout); - ::vk::uniform_params global_info = { + vk::uniform_params global_info = { .phsyical_memory_properties = m_physical.memory_properties(), .size_bytes = sizeof(global_ubo), .debug_name = "\nm_global_uniforms\n", .vkSetDebugUtilsObjectNameEXT = instance_context::get_debug_object_name() }; - m_global_uniforms = ::vk::uniform_buffer(m_device, global_info); + m_global_uniforms = vk::uniform_buffer(m_device, global_info); // setting up our light uniforms as the global uniforms rather then // per-object basis - ::vk::uniform_params light_ubo_params = { + vk::uniform_params light_ubo_params = { .phsyical_memory_properties = m_physical.memory_properties(), .size_bytes = sizeof(light_scene_ubo), }; m_point_light_uniforms = - ::vk::uniform_buffer(m_device, light_ubo_params); + vk::uniform_buffer(m_device, light_ubo_params); - std::array<::vk::write_buffer, 1> binding0_uniforms = { - ::vk::write_buffer{ + std::array binding0_uniforms = { + vk::write_buffer{ .buffer = m_global_uniforms, .offset = 0, .range = m_global_uniforms.size_bytes(), }, }; - std::array<::vk::write_buffer, 1> binding1_uniforms = { - ::vk::write_buffer{ + std::array binding1_uniforms = { + vk::write_buffer{ .buffer = m_point_light_uniforms, .offset = 0, .range = m_point_light_uniforms.size_bytes(), }, }; - std::array<::vk::write_buffer_descriptor, 2> set0_write_buffers = { - ::vk::write_buffer_descriptor{ + std::array set0_write_buffers = { + vk::write_buffer_descriptor{ .dst_binding = 0, .uniforms = binding0_uniforms, }, - ::vk::write_buffer_descriptor{ + vk::write_buffer_descriptor{ .dst_binding = 1, .uniforms = binding1_uniforms, } @@ -214,12 +214,12 @@ export namespace atlas::vulkan { m_global_descriptors.layout(), }; - ::vk::image_extent extent = { + vk::image_extent extent = { .width = 1, .height = 1, }; m_white_texture = - ::vk::texture(m_device, extent, m_physical.memory_properties()); + vk::texture(m_device, extent, m_physical.memory_properties()); p_context->submit_resource_free([this]() { console_log_info("vulkan::render_system destructin invoked!!"); @@ -283,25 +283,25 @@ export namespace atlas::vulkan { // we do a check if the geometry uniform associated with this game // object is valid if (!m_mesh_geometry_set.contains(p_entity.id())) { - ::vk::uniform_params geo_info = { + vk::uniform_params geo_info = { .phsyical_memory_properties = m_physical.memory_properties(), .size_bytes = sizeof(material_uniform), }; m_mesh_geometry_set[p_entity.id()] = - ::vk::uniform_buffer(m_device, geo_info); + vk::uniform_buffer(m_device, geo_info); } // check if material is already associated with this particular game // object if (!m_mesh_material_set.contains(p_entity.id())) { - ::vk::uniform_params mat_info = { + vk::uniform_params mat_info = { .phsyical_memory_properties = m_physical.memory_properties(), .size_bytes = sizeof(material_metadata), }; m_mesh_material_set[p_entity.id()] = - ::vk::uniform_buffer(m_device, mat_info); + vk::uniform_buffer(m_device, mat_info); } new_mesh.add_diffuse(std::filesystem::path(target->diffuse)); @@ -310,46 +310,46 @@ export namespace atlas::vulkan { if (new_mesh.loaded()) { m_cached_meshes.emplace(p_entity.id(), new_mesh); - std::vector<::vk::descriptor_entry> set1_entries = { - ::vk::descriptor_entry{ + std::vector set1_entries = { + vk::descriptor_entry{ // specifies "layout (set = 1, binding = 0) uniform geometry_uniform" - .type = ::vk::buffer::uniform, + .type = vk::buffer::uniform, .binding_point = { .binding = 0, - .stage = ::vk::shader_stage::vertex, + .stage = vk::shader_stage::vertex, }, .descriptor_count = 1, }, - ::vk::descriptor_entry{ + vk::descriptor_entry{ // specifies "layout (set = 1, binding = 1) uniform sampler2D diffuse_texture" - .type = ::vk::buffer::combined_image_sampler, + .type = vk::buffer::combined_image_sampler, .binding_point = { .binding = 1, - .stage = ::vk::shader_stage::fragment, + .stage = vk::shader_stage::fragment, }, .descriptor_count = 1, }, - ::vk::descriptor_entry{ + vk::descriptor_entry{ // specifies "layout (set = 1, binding = 2) uniform sampler2D specular_texture" - .type = ::vk::buffer::combined_image_sampler, + .type = vk::buffer::combined_image_sampler, .binding_point = { .binding = 2, - .stage = ::vk::shader_stage::fragment, + .stage = vk::shader_stage::fragment, }, .descriptor_count = 1, }, - ::vk::descriptor_entry{ + vk::descriptor_entry{ // specifies "layout (set = 1, binding = 3) uniform sampler2D material_ubo" - .type = ::vk::buffer::uniform, + .type = vk::buffer::uniform, .binding_point = { .binding = 3, - .stage = ::vk::shader_stage::fragment, + .stage = vk::shader_stage::fragment, }, .descriptor_count = 1, }, }; - ::vk::descriptor_layout set1_layout = { + vk::descriptor_layout set1_layout = { .slot = 1, .max_sets = m_image_count, .entries = set1_entries, @@ -357,33 +357,33 @@ export namespace atlas::vulkan { m_mesh_descriptors[p_entity.id()].emplace( "materials", - ::vk::descriptor_resource(m_device, set1_layout)); + vk::descriptor_resource(m_device, set1_layout)); // specify to the vk::write_descriptor_buffer - std::array<::vk::write_buffer, 1> binding0_buffers = { - ::vk::write_buffer{ + std::array binding0_buffers = { + vk::write_buffer{ .buffer = m_mesh_geometry_set[p_entity.id()], .offset = 0, .range = m_mesh_geometry_set[p_entity.id()].size_bytes(), } }; - std::array<::vk::write_buffer, 1> binding3_buffers = { - ::vk::write_buffer{ + std::array binding3_buffers = { + vk::write_buffer{ .buffer = m_mesh_material_set[p_entity.id()], .offset = 0, .range = m_mesh_material_set[p_entity.id()].size_bytes(), } }; - std::vector<::vk::write_buffer_descriptor> material_uniforms = { + std::vector material_uniforms = { // layout(set= 1, binding = 0) geometry_ubo - ::vk::write_buffer_descriptor{ + vk::write_buffer_descriptor{ .dst_binding = 0, .uniforms = binding0_buffers, }, // layout(set= 1, binding = 3) material_ubo - ::vk::write_buffer_descriptor{ + vk::write_buffer_descriptor{ .dst_binding = 3, .uniforms = binding3_buffers, }, @@ -392,48 +392,48 @@ export namespace atlas::vulkan { // layout(set = 1, binding = 1) // If the texture loaded successfully then we use that texture, // otherwise utilize the default white texture - ::vk::sample_image diffuse = + vk::sample_image diffuse = m_cached_meshes[p_entity.id()].diffuse_loaded() ? m_cached_meshes[p_entity.id()].diffuse() : m_white_texture.image(); // layout(set = 1, binding = 2) - ::vk::sample_image specular = + vk::sample_image specular = m_cached_meshes[p_entity.id()].specular_loaded() ? m_cached_meshes[p_entity.id()].specular() : m_white_texture.image(); // writes to texture at layout(set = 1, binding = 1) - std::array<::vk::write_image, 1> + std::array binding1_images = { - ::vk::write_image{ + vk::write_image{ .sampler = diffuse.sampler(), .view = diffuse.image_view(), // .image_layout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL, - .layout = ::vk::image_layout::shader_read_only_optimal, + .layout = vk::image_layout::shader_read_only_optimal, }, }; // writes to texture at layout(set = 1, binding = 2) - std::array<::vk::write_image, 1> + std::array binding2_images = { - ::vk::write_image{ + vk::write_image{ .sampler = specular.sampler(), .view = specular.image_view(), // .image_layout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL, - .layout = ::vk::image_layout::shader_read_only_optimal, + .layout = vk::image_layout::shader_read_only_optimal, }, }; // vulkan image descriptors are for writing textures - std::vector<::vk::write_image_descriptor> material_textures = { + std::vector material_textures = { // layout(set = 1, binding = 1) uniform sampler2D - ::vk::write_image_descriptor{ + vk::write_image_descriptor{ .dst_binding = 1, .sample_images = binding1_images, }, // layout(set = 1, binding = 2) uniform sampler2D - ::vk::write_image_descriptor{ + vk::write_image_descriptor{ .dst_binding = 2, .sample_images = binding2_images, }, @@ -447,21 +447,21 @@ export namespace atlas::vulkan { } }); - std::vector<::vk::shader_handle> modules = m_shader_group.handles(); + std::vector modules = m_shader_group.handles(); - ::vk::pipeline_settings pipeline_configuration = { + vk::pipeline_settings pipeline_configuration = { .renderpass = m_final_renderpass, .shader_modules = modules, .vertex_attributes = m_shader_group.vertex_attributes(), .vertex_bind_attributes = m_shader_group.vertex_bind_attributes(), .descriptor_layouts = m_sets_layouts }; - m_main_pipeline = ::vk::pipeline(m_device, pipeline_configuration); + m_main_pipeline = vk::pipeline(m_device, pipeline_configuration); console_log_warn("graphics pipeline = {}", m_main_pipeline.alive()); } - void start_frame(const ::vk::command_buffer& p_current, const window_params& p_settings, const VkRenderPass& p_renderpass, const VkFramebuffer& p_framebuffer, const glm::mat4& p_proj_view, uint32_t p_current_frame) override { + void start_frame(const vk::command_buffer& p_current, const window_params& p_settings, const VkRenderPass& p_renderpass, const VkFramebuffer& p_framebuffer, const glm::mat4& p_proj_view, uint32_t p_current_frame) override { m_proj_view = p_proj_view; // m_current_frame = application::current_frame(); m_current_frame = p_current_frame; @@ -493,7 +493,7 @@ export namespace atlas::vulkan { m_current_command_buffer = p_current; m_current_command_buffer.begin( - ::vk::command_usage::simulatneous_use_bit); + vk::command_usage::simulatneous_use_bit); VkViewport viewport = { .x = 0.0f, @@ -520,10 +520,10 @@ export namespace atlas::vulkan { VK_SUBPASS_CONTENTS_INLINE); } - void background_color(const std::array& p_color) override { + void background_color(const glm::vec4& p_color) override { m_color = { - { p_color.at(0), p_color.at(1), p_color.at(2), p_color.at(3) } - }; + { p_color.x, p_color.y, p_color.z, p_color.w }, + }; } void post_frame() override { @@ -639,10 +639,10 @@ export namespace atlas::vulkan { vk::uniform_buffer m_point_light_uniforms; // game object-specific meshes - std::map m_mesh_geometry_set; + std::map m_mesh_geometry_set; // TODO: Make this into a material system, eventually - std::map m_mesh_material_set; - std::map> + std::map m_mesh_material_set; + std::map> m_mesh_descriptors; uint32_t m_current_frame = 0; glm::mat4 m_model = { 1.f }; From 5517a2de377cc0479de7f8ccbf2cc8207aa83632 Mon Sep 17 00:00:00 2001 From: SpinnerX Date: Fri, 16 Jan 2026 00:08:36 -0800 Subject: [PATCH 47/68] Updated project cmake --- CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index ad5680f8..5cef49f4 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -157,7 +157,7 @@ target_sources(${PROJECT_NAME} PUBLIC atlas/core/serialize/serializer.cppm # renderer - atlas/renderer/loader.cppm + atlas/renderer/context_loader.cppm atlas/renderer/renderer.cppm atlas/drivers/drivers.cppm From 854d0cee27b8fe1ebce16549b70c0be53fcbe1ba Mon Sep 17 00:00:00 2001 From: SpinnerX Date: Fri, 16 Jan 2026 17:41:37 -0800 Subject: [PATCH 48/68] Cleanup to graphics context and cleaned up the physics system configuration parameters --- atlas/core/application.cppm | 6 +- atlas/core/entry_point/main.cpp | 2 +- atlas/drivers/jolt_cpp/context.cppm | 66 +++++++++-- atlas/drivers/physics_context.cppm | 106 +----------------- atlas/physics/physics_engine.cppm | 10 +- .../{loader.cppm => context_loader.cppm} | 2 +- 6 files changed, 65 insertions(+), 127 deletions(-) rename atlas/renderer/{loader.cppm => context_loader.cppm} (93%) diff --git a/atlas/core/application.cppm b/atlas/core/application.cppm index 1e131ce1..6423188a 100644 --- a/atlas/core/application.cppm +++ b/atlas/core/application.cppm @@ -18,7 +18,7 @@ import atlas.core.utilities; import atlas.core.utilities.poll_state; import atlas.window; import atlas.drivers; -import atlas.renderer.loader; +import atlas.renderer.context_loader; import atlas.core.event; import atlas.drivers.renderer_system; import atlas.renderer; @@ -35,10 +35,6 @@ import atlas.drivers.graphics_context; export namespace atlas { - struct resource { - ref graphics_context; - }; - /** * @brief application properties settings for the window */ diff --git a/atlas/core/entry_point/main.cpp b/atlas/core/entry_point/main.cpp index 9c19e887..e9ae5163 100644 --- a/atlas/core/entry_point/main.cpp +++ b/atlas/core/entry_point/main.cpp @@ -10,7 +10,7 @@ import atlas.drivers.graphics_context; // this includes initialize_context // import atlas.drivers; -import atlas.renderer.loader; +import atlas.renderer.context_loader; import atlas.core.scene.system_registry; // Defined in the user-application side diff --git a/atlas/drivers/jolt_cpp/context.cppm b/atlas/drivers/jolt_cpp/context.cppm index aaf658b4..d96b8d54 100644 --- a/atlas/drivers/jolt_cpp/context.cppm +++ b/atlas/drivers/jolt_cpp/context.cppm @@ -52,6 +52,53 @@ import atlas.drivers.jolt_cpp.types; namespace atlas::physics { + enum thread_type : uint8_t { + default_system = 0, + job_system = 1, + }; + + // This might be able to be generalized eventually but we will have to + // create our own manifold before that happens. + struct contact_event { + uint64_t entity_a = 0; + uint64_t entity_b = 0; + JPH::ContactManifold manifold; + JPH::ContactSettings settings; + }; + + /** + * @brief Jolt-specific context configurations + * These are going to be internally integrated to jolt_context + * + * As these parameters currently are going to be specific to Jolt. + * + * These parameters are also only specific to the construction-level, not + * initiation level of the API's + * + * @remark Min and max world bounds are values that are artbitrary (in other + * words limit the simulation space) as JoltPhysics has a limit on distance + * for its limitation in simulation space + */ + struct jolt_settings { + + uint32_t allocation_amount = 10 * 1024 * 1024; + + //! @brief Specifying which threading system to use for Jolt. + thread_type thread_type = thread_type::default_system; + + uint32_t physics_threads = + std::max(1u, std::thread::hardware_concurrency() - 2); + + uint32_t max_jobs_power = 10; + uint32_t max_barriers = physics_threads * 16; + bool enable_multithread = true; + + // Max memory size per scene + uint32_t max_bodies = 16384; + uint32_t max_body_pairs = 32768; + uint32_t max_contact_constraints = 8192; + }; + static void trace_impl(const char* p_in_fmt, ...) { va_list list; va_start(list, p_in_fmt); @@ -94,7 +141,8 @@ namespace atlas::physics { * @param p_bus is the event::bus that allows for publishing physics * events to the subscribers of those said events */ - jolt_context(const jolt_settings& p_settings, event::bus& p_bus) : m_contact_listener(p_bus) { + jolt_context(event::bus& p_bus) : m_contact_listener(p_bus) { + jolt_settings settings = {}; JPH::RegisterDefaultAllocator(); JPH::Trace = trace_impl; @@ -104,7 +152,7 @@ namespace atlas::physics { JPH::RegisterTypes(); m_temp_allocator = - create_ref(p_settings.allocation_amount); + create_ref(settings.allocation_amount); // This just sets up the JoltPhysics system and any listeners m_physics_system = create_ref(); @@ -114,24 +162,24 @@ namespace atlas::physics { create_ref(); m_object_layer_pair_filter = create_ref(); - if (p_settings.thread_type == thread_type::default_system) { + if (settings.thread_type == thread_type::default_system) { m_thread_system = create_scope( // Max jobs must be a power of 2, otherwise jph crashes. // Bianary tree must be fully balanced - std::pow(2, p_settings.max_jobs_power), - p_settings.max_barriers, - p_settings.physics_threads); + std::pow(2, settings.max_jobs_power), + settings.max_barriers, + settings.physics_threads); } else { console_log_error("Unsupported custom job system"); assert(false); } - m_physics_system->Init(p_settings.max_bodies, + m_physics_system->Init(settings.max_bodies, 0, - p_settings.max_body_pairs, - p_settings.max_contact_constraints, + settings.max_body_pairs, + settings.max_contact_constraints, *m_broad_phase_layer_interface, *m_object_vs_broadphase_filter, *m_object_layer_pair_filter); diff --git a/atlas/drivers/physics_context.cppm b/atlas/drivers/physics_context.cppm index a15f0fe7..1bbcb0c3 100644 --- a/atlas/drivers/physics_context.cppm +++ b/atlas/drivers/physics_context.cppm @@ -1,40 +1,7 @@ module; +#include #include -#include - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include - -#include -#include -#include -#include -#include -#include - -#include - -// jolt's math includes -#include -#include -#include -#include export module atlas.drivers.physics_context; @@ -45,77 +12,6 @@ import atlas.core.event; namespace atlas::physics { - export enum thread_type : uint8_t { - default_system = 0, - job_system = 1, - }; - - /** - * @brief Used to keep global data for player access and use. - * Tells how physics bodies should act within a given scene by - * default. - */ - struct jolt_config { - // Global gravity vector for all in scene - glm::vec3 gravity = glm::vec3(0.0f, -9.80665f, 0.0f); - - //! @brief In seconds - float time_before_sleep = 5.0f; - - // What 1 unit refers to in meters - float world_unit_scale = 1.0f; - - // Helps stop the lauching of objects during numerical/flaoting point - // errors when collision happen bertween to objects. - float contact_bias_factor = 0.2f; - float restitution_threshold = 1.0f; - - bool enable_constraints = true; - bool enable_collision_callbacks = true; - }; - - /** - * @brief Jolt-specific context configurations - * These are going to be internally integrated to jolt_context - * - * As these parameters currently are going to be specific to Jolt. - * - * These parameters are also only specific to the construction-level, not - * initiation level of the API's - * - * @remark Min and max world bounds are values that are artbitrary (in other - * words limit the simulation space) as JoltPhysics has a limit on distance - * for its limitation in simulation space - */ - export struct jolt_settings { - - uint32_t allocation_amount = 10 * 1024 * 1024; - - //! @brief Specifying which threading system to use for Jolt. - thread_type thread_type = thread_type::default_system; - - uint32_t physics_threads = - std::max(1u, std::thread::hardware_concurrency() - 2); - - uint32_t max_jobs_power = 10; - uint32_t max_barriers = physics_threads * 16; - bool enable_multithread = true; - - // Max memory size per scene - uint32_t max_bodies = 16384; - uint32_t max_body_pairs = 32768; - uint32_t max_contact_constraints = 8192; - }; - - // This might be able to be generalized eventually but we will have to - // create our own manifold before that happens. - struct contact_event { - uint64_t entity_a = 0; - uint64_t entity_b = 0; - JPH::ContactManifold manifold; - JPH::ContactSettings settings; - }; - /** * @brief The context is the way to interact with specific backend context diff --git a/atlas/physics/physics_engine.cppm b/atlas/physics/physics_engine.cppm index e95d2035..338cbbbf 100644 --- a/atlas/physics/physics_engine.cppm +++ b/atlas/physics/physics_engine.cppm @@ -9,7 +9,6 @@ import atlas.common; import atlas.core.scene.components; import atlas.core.event; import atlas.drivers.physics_context; -import atlas.drivers.physics_context; import atlas.drivers.jolt_cpp.context; namespace atlas::physics { @@ -17,8 +16,8 @@ namespace atlas::physics { //! @brief initializes the physics backend. SHOULD have an API associated //! with but for now, we assume we only have JoltPhysics as our only physics //! backend - ref initialize_physics_context(const jolt_settings& p_settings, event::bus& p_bus) { - return create_ref(p_settings, p_bus); + ref initialize_physics_context(event::bus& p_bus) { + return create_ref(p_bus); } /** @@ -31,9 +30,8 @@ namespace atlas::physics { // Required by maps but should not be used in anyother circumstance. engine() = default; engine(flecs::world& p_registry, - event::bus& p_bus, - const jolt_settings& p_settings={}) : m_registry(&p_registry), m_bus(&p_bus) { - m_physics_context = initialize_physics_context(p_settings, *m_bus); + event::bus& p_bus) : m_registry(&p_registry), m_bus(&p_bus) { + m_physics_context = initialize_physics_context(*m_bus); // This may change, but for now we want to ensure that we only want to // create a single physics body with a specific collider Rather then diff --git a/atlas/renderer/loader.cppm b/atlas/renderer/context_loader.cppm similarity index 93% rename from atlas/renderer/loader.cppm rename to atlas/renderer/context_loader.cppm index 616cc6bf..769f0a0d 100644 --- a/atlas/renderer/loader.cppm +++ b/atlas/renderer/context_loader.cppm @@ -3,7 +3,7 @@ module; #include #include -export module atlas.renderer.loader; +export module atlas.renderer.context_loader; import atlas.core.utilities; From f0bf3f55e58d8def3dfe10f47aab75b0a7ce12fd Mon Sep 17 00:00:00 2001 From: SpinnerX Date: Sun, 18 Jan 2026 16:59:13 -0800 Subject: [PATCH 49/68] Added logging messages for finding clang-format, clang-tidy, and the cmake.exe binaries --- CMakeLists.txt | 19 +++++++++++++++++++ conanfile.py | 11 +++++++++++ editor/level_scene.cppm | 30 ++++++------------------------ 3 files changed, 36 insertions(+), 24 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 5cef49f4..2f2703d7 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -30,6 +30,25 @@ else() message(STATUS "ENABLE_TESTS_ONLY macro not enabled") endif() +# The variable CLANG_FORMAT_PATH is now defined automatically by conan_toolchain.cmake +if(EXISTS "${CLANG_FORMAT_PATH}") + message(STATUS "${CLANG_FORMAT_PATH} found!") +else() + message(WARNING "${CLANG_FORMAT_PATH} not found!") +endif() + +if(EXISTS "${CLANG_TIDY_PATH}") + message(STATUS "${CLANG_TIDY_PATH} found!") +else() + message(WARNING "${CLANG_TIDY_PATH} not found!") +endif() + +if(EXISTS "${CMAKE_PATH}") + message(STATUS "${CMAKE_PATH} found!") +else() + message(WARNING "${CMAKE_PATH} not found!") +endif() + # build_core_library( # DIRECTORIES src editor diff --git a/conanfile.py b/conanfile.py index 80783df1..0011d69c 100644 --- a/conanfile.py +++ b/conanfile.py @@ -4,6 +4,7 @@ import os from pathlib import Path import shutil +from conan.tools.files import save class AtlasRecipe(ConanFile): name = "atlas" @@ -63,6 +64,13 @@ def layout(self): cmake_layout(self) def generate(self): + # llvm = self.dependencies["llvm-toolchain/20"] + llvm_path = self.dependencies.build["llvm-toolchain"].package_folder + cmake_path = self.dependencies.build["cmake"].package_folder + cmake_binary_location = f"{cmake_path.replace("\\", "/")}/bin/cmake.exe" + clang_format_path = f"{llvm_path}/bin/clang-format.exe" + clang_tidy_path = f"{llvm_path}/bin/clang-tidy.exe" + deps = CMakeDeps(self) deps.generate() tc = CMakeToolchain(self) @@ -71,6 +79,9 @@ def generate(self): tc.generator = "Ninja" tc.variables["USE_SHADERC"] = self.options.enable_shaderc tc.variables["ENABLE_TESTS_ONLY"] = self.options.enable_tests_only + tc.variables["CLANG_FORMAT_PATH"] = clang_format_path.replace("\\", "/") + tc.variables["CLANG_TIDY_PATH"] = clang_tidy_path.replace("\\", "/") + tc.variables["CMAKE_PATH"] = cmake_binary_location tc.generate() def build(self): diff --git a/editor/level_scene.cppm b/editor/level_scene.cppm index e687c808..69dd2384 100644 --- a/editor/level_scene.cppm +++ b/editor/level_scene.cppm @@ -13,6 +13,7 @@ module; #include #include #include +#include export module level_scene; @@ -213,46 +214,26 @@ public: }); point_light.add(); - // benchmark - - // auto start = std::chrono::high_resolution_clock::now(); - // TEMP Code - // [[maybe_unused]] atlas::game_object point_light_test = entity("Point - // Light 1"); auto end = std::chrono::high_resolution_clock::now(); auto - // duration = (end - start); - - // auto seconds = - // std::chrono::duration_cast(duration).count(); auto - // nanoseconds = - // std::chrono::duration_cast(duration).count(); - // auto microseconds = - // std::chrono::duration_cast(duration).count(); - - // console_log_fatal("Seconds = {:.1f}", static_cast(seconds)); - // console_log_fatal("Nanoseconds = {:.1f}", - // static_cast(nanoseconds)); console_log_fatal("Microseconds = - // {:.1f}", static_cast(microseconds)); - // for(size_t i = 0; i < 26; i++) { // auto obj = entity(std::format("Object #{}", i)); - // obj->set({ + // obj.set({ // .restitution = 1.25f, // .body_movement_type = atlas::dynamic, // }); - // obj->set( + // obj.set( // { // .radius = 1.0f, // }); // glm::vec3 pos = {float(0*1.4),float(0 * 1.4),float(0 * -3) }; - // obj->set({ + // obj.set({ // .position = pos, // .rotation = {.3f, 0.0f, 0.0f}, // }); - // obj->set({ + // obj.set({ // .model_path = "assets/models/Ball OBJ.obj", // .diffuse = "assets/models/clear.png", // }); @@ -656,6 +637,7 @@ public: } void physics_update() { + // TODO: Replace delta_time with physics fixed-timestep instead float dt = atlas::application::delta_time(); if (atlas::event::is_key_pressed(key_r) and !m_physics_runtime) { runtime_start(); From 61d007b9902eed119e5481eaf9b16db1a78c6a1b Mon Sep 17 00:00:00 2001 From: SpinnerX Date: Sun, 18 Jan 2026 17:00:04 -0800 Subject: [PATCH 50/68] Removed logging messagess from application.cppm --- atlas/core/application.cppm | 2 -- 1 file changed, 2 deletions(-) diff --git a/atlas/core/application.cppm b/atlas/core/application.cppm index 6423188a..b4d8db49 100644 --- a/atlas/core/application.cppm +++ b/atlas/core/application.cppm @@ -190,7 +190,6 @@ export namespace atlas { current_world_scope.progress(m_delta_time); m_current_frame_index = m_window->acquired_next_frame(); - console_log_info("current_frame_raw_index = {}", m_current_frame_index); // Current commands that are going to be iterated through // Prevents things like stalling so the CPU doesnt have to wait for @@ -198,7 +197,6 @@ export namespace atlas { // Command buffer uses this to track the frames to process its commands. // current_frame = (acquired_next_frame + 1) % frames_in_flight; auto current_frame = (m_current_frame_index + 1) % 2; - console_log_info("current_frame = {}", current_frame); // TODO: Going to need to figure out where to put this // Added this here because to ensure the handlers being used by the From e8b6c760e07a8ac7264751726dc60f8d5a02a9e3 Mon Sep 17 00:00:00 2001 From: SpinnerX Date: Mon, 19 Jan 2026 15:20:01 -0800 Subject: [PATCH 51/68] Renamed to builtin.shaders --- atlas/drivers/vulkan/render_system.cppm | 319 ++++++++++-------- builtin.shaders/compile.bat | 4 + .../test.frag | 0 .../test.vert | 0 4 files changed, 174 insertions(+), 149 deletions(-) create mode 100644 builtin.shaders/compile.bat rename {experimental-shaders => builtin.shaders}/test.frag (100%) rename {experimental-shaders => builtin.shaders}/test.vert (100%) diff --git a/atlas/drivers/vulkan/render_system.cppm b/atlas/drivers/vulkan/render_system.cppm index 9f3c1e3e..678c7192 100644 --- a/atlas/drivers/vulkan/render_system.cppm +++ b/atlas/drivers/vulkan/render_system.cppm @@ -58,7 +58,10 @@ export namespace atlas::vulkan { */ class render_system : public renderer_system { public: - render_system(ref p_context, const window_params& p_params, uint32_t p_image_size, const std::string&) { + render_system(ref p_context, + const window_params& p_params, + uint32_t p_image_size, + const std::string&) { m_physical = instance_context::physical_driver(); m_device = instance_context::logical_device(); @@ -66,60 +69,60 @@ export namespace atlas::vulkan { m_image_count = p_image_size; #ifdef USE_SHADERC - console_log_info("shaderc enabled!!"); - std::array shader_sources = { - vk::shader_source{ - "experimental-shaders/test.vert", - vk::shader_stage::vertex, - }, - vk::shader_source{ - "experimental-shaders/test.frag", - vk::shader_stage::fragment, - } - }; + console_log_info("shaderc enabled!!"); + std::array shader_sources = { + vk::shader_source{ + "builtin.shaders/test.vert", + vk::shader_stage::vertex, + }, + vk::shader_source { + "builtin.shaders/test.frag", + vk::shader_stage::fragment, + } + }; #else - console_log_info("shaderc disabled!!"); - std::array shader_sources = { - vk::shader_source{ - "experimental-shaders/test.vert.spv", - vk::shader_stage::vertex, - }, - vk::shader_source{ - "experimental-shaders/test.frag.spv", - vk::shader_stage::fragment, - } - }; + console_log_info("shaderc disabled!!"); + std::array shader_sources = { + vk::shader_source{ + "builtin.shaders/test.vert.spv", + vk::shader_stage::vertex, + }, + vk::shader_source{ + "builtin.shaders/test.frag.spv", + vk::shader_stage::fragment, + } + }; #endif std::array attribute_entries = { vk::vertex_attribute_entry{ - .location = 0, - .format = vk::format::rgb32_sfloat, - .stride = offsetof(vk::vertex_input, position), + .location = 0, + .format = vk::format::rgb32_sfloat, + .stride = offsetof(vk::vertex_input, position), }, vk::vertex_attribute_entry{ - .location = 1, - .format = vk::format::rgb32_sfloat, - .stride = offsetof(vk::vertex_input, color), + .location = 1, + .format = vk::format::rgb32_sfloat, + .stride = offsetof(vk::vertex_input, color), }, vk::vertex_attribute_entry{ - .location = 2, - .format = vk::format::rgb32_sfloat, - .stride = offsetof(vk::vertex_input, normals), + .location = 2, + .format = vk::format::rgb32_sfloat, + .stride = offsetof(vk::vertex_input, normals), }, vk::vertex_attribute_entry{ - .location = 3, - .format = vk::format::rg32_sfloat, - .stride = offsetof(vk::vertex_input, uv), + .location = 3, + .format = vk::format::rg32_sfloat, + .stride = offsetof(vk::vertex_input, uv), } }; std::array attribute = { vk::vertex_attribute{ - // layout (set = 0, binding = 0) - .binding = 0, - .entries = attribute_entries, - .stride = sizeof(vk::vertex_input), - .input_rate = vk::input_rate::vertex, + // layout (set = 0, binding = 0) + .binding = 0, + .entries = attribute_entries, + .stride = sizeof(vk::vertex_input), + .input_rate = vk::input_rate::vertex, }, }; @@ -163,13 +166,15 @@ export namespace atlas::vulkan { .max_sets = m_image_count, .entries = set0_entries, }; - m_global_descriptors = vk::descriptor_resource(m_device, set0_layout); + m_global_descriptors = + vk::descriptor_resource(m_device, set0_layout); vk::uniform_params global_info = { .phsyical_memory_properties = m_physical.memory_properties(), .size_bytes = sizeof(global_ubo), .debug_name = "\nm_global_uniforms\n", - .vkSetDebugUtilsObjectNameEXT = instance_context::get_debug_object_name() + .vkSetDebugUtilsObjectNameEXT = + instance_context::get_debug_object_name() }; m_global_uniforms = vk::uniform_buffer(m_device, global_info); @@ -180,32 +185,32 @@ export namespace atlas::vulkan { .size_bytes = sizeof(light_scene_ubo), }; m_point_light_uniforms = - vk::uniform_buffer(m_device, light_ubo_params); + vk::uniform_buffer(m_device, light_ubo_params); std::array binding0_uniforms = { vk::write_buffer{ - .buffer = m_global_uniforms, - .offset = 0, - .range = m_global_uniforms.size_bytes(), + .buffer = m_global_uniforms, + .offset = 0, + .range = m_global_uniforms.size_bytes(), }, }; std::array binding1_uniforms = { vk::write_buffer{ - .buffer = m_point_light_uniforms, - .offset = 0, - .range = m_point_light_uniforms.size_bytes(), + .buffer = m_point_light_uniforms, + .offset = 0, + .range = m_point_light_uniforms.size_bytes(), }, }; std::array set0_write_buffers = { vk::write_buffer_descriptor{ - .dst_binding = 0, - .uniforms = binding0_uniforms, + .dst_binding = 0, + .uniforms = binding0_uniforms, }, vk::write_buffer_descriptor{ - .dst_binding = 1, - .uniforms = binding1_uniforms, + .dst_binding = 1, + .uniforms = binding1_uniforms, } }; m_global_descriptors.update(set0_write_buffers); @@ -219,7 +224,7 @@ export namespace atlas::vulkan { .height = 1, }; m_white_texture = - vk::texture(m_device, extent, m_physical.memory_properties()); + vk::texture(m_device, extent, m_physical.memory_properties()); p_context->submit_resource_free([this]() { console_log_info("vulkan::render_system destructin invoked!!"); @@ -229,8 +234,8 @@ export namespace atlas::vulkan { m_global_uniforms.destroy(); m_point_light_uniforms.destroy(); for (auto& [id, mesh] : m_cached_meshes) { - console_log_trace("Entity \"{}\" Destroyed in vk_renderer!!!", - id); + console_log_trace( + "Entity \"{}\" Destroyed in vk_renderer!!!", id); mesh.destroy(); } @@ -250,8 +255,8 @@ export namespace atlas::vulkan { m_main_pipeline.destroy(); }); - - console_log_info("Vulkan-specific implementation constructed successfully!!!"); + console_log_info( + "Vulkan-specific implementation constructed successfully!!!"); } ~render_system() override = default; @@ -263,8 +268,8 @@ export namespace atlas::vulkan { // ref current_world = system_registry::get_world("Editor // World"); ref current_scene = // current_world->get_scene("LevelScene"); - - if(m_current_scene == nullptr) { + + if (m_current_scene == nullptr) { console_log_error("m_current_scene == nullptr!"); return; } @@ -273,35 +278,35 @@ export namespace atlas::vulkan { } flecs::query<> caching = - m_current_scene->query_builder().build(); + m_current_scene->query_builder().build(); caching.each([this](flecs::entity p_entity) { const mesh_source* target = p_entity.get(); mesh new_mesh(std::filesystem::path(target->model_path), - target->flip); + target->flip); - // we do a check if the geometry uniform associated with this game - // object is valid + // we do a check if the geometry uniform associated with this + // game object is valid if (!m_mesh_geometry_set.contains(p_entity.id())) { vk::uniform_params geo_info = { .phsyical_memory_properties = - m_physical.memory_properties(), + m_physical.memory_properties(), .size_bytes = sizeof(material_uniform), }; m_mesh_geometry_set[p_entity.id()] = - vk::uniform_buffer(m_device, geo_info); + vk::uniform_buffer(m_device, geo_info); } - // check if material is already associated with this particular game - // object + // check if material is already associated with this particular + // game object if (!m_mesh_material_set.contains(p_entity.id())) { vk::uniform_params mat_info = { .phsyical_memory_properties = - m_physical.memory_properties(), + m_physical.memory_properties(), .size_bytes = sizeof(material_metadata), }; m_mesh_material_set[p_entity.id()] = - vk::uniform_buffer(m_device, mat_info); + vk::uniform_buffer(m_device, mat_info); } new_mesh.add_diffuse(std::filesystem::path(target->diffuse)); @@ -356,94 +361,98 @@ export namespace atlas::vulkan { }; m_mesh_descriptors[p_entity.id()].emplace( - "materials", - vk::descriptor_resource(m_device, set1_layout)); + "materials", + vk::descriptor_resource(m_device, set1_layout)); // specify to the vk::write_descriptor_buffer std::array binding0_buffers = { vk::write_buffer{ - .buffer = m_mesh_geometry_set[p_entity.id()], - .offset = 0, - .range = m_mesh_geometry_set[p_entity.id()].size_bytes(), + .buffer = m_mesh_geometry_set[p_entity.id()], + .offset = 0, + .range = + m_mesh_geometry_set[p_entity.id()].size_bytes(), } }; std::array binding3_buffers = { vk::write_buffer{ - .buffer = m_mesh_material_set[p_entity.id()], - .offset = 0, - .range = m_mesh_material_set[p_entity.id()].size_bytes(), + .buffer = m_mesh_material_set[p_entity.id()], + .offset = 0, + .range = + m_mesh_material_set[p_entity.id()].size_bytes(), } }; - std::vector material_uniforms = { - // layout(set= 1, binding = 0) geometry_ubo - vk::write_buffer_descriptor{ + std::vector + material_uniforms = { + // layout(set= 1, binding = 0) geometry_ubo + vk::write_buffer_descriptor{ .dst_binding = 0, .uniforms = binding0_buffers, - }, - // layout(set= 1, binding = 3) material_ubo - vk::write_buffer_descriptor{ + }, + // layout(set= 1, binding = 3) material_ubo + vk::write_buffer_descriptor{ .dst_binding = 3, .uniforms = binding3_buffers, - }, - }; + }, + }; // layout(set = 1, binding = 1) - // If the texture loaded successfully then we use that texture, - // otherwise utilize the default white texture + // If the texture loaded successfully then we use that + // texture, otherwise utilize the default white texture vk::sample_image diffuse = - m_cached_meshes[p_entity.id()].diffuse_loaded() + m_cached_meshes[p_entity.id()].diffuse_loaded() ? m_cached_meshes[p_entity.id()].diffuse() : m_white_texture.image(); // layout(set = 1, binding = 2) vk::sample_image specular = - m_cached_meshes[p_entity.id()].specular_loaded() + m_cached_meshes[p_entity.id()].specular_loaded() ? m_cached_meshes[p_entity.id()].specular() : m_white_texture.image(); // writes to texture at layout(set = 1, binding = 1) - std::array - binding1_images = { + std::array binding1_images = { vk::write_image{ - .sampler = diffuse.sampler(), - .view = diffuse.image_view(), - // .image_layout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL, - .layout = vk::image_layout::shader_read_only_optimal, + .sampler = diffuse.sampler(), + .view = diffuse.image_view(), + // .image_layout = + // VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL, + .layout = vk::image_layout::shader_read_only_optimal, }, }; // writes to texture at layout(set = 1, binding = 2) - std::array - binding2_images = { - vk::write_image{ - .sampler = specular.sampler(), - .view = specular.image_view(), - // .image_layout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL, - .layout = vk::image_layout::shader_read_only_optimal, + std::array binding2_images = { + vk::write_image{ + .sampler = specular.sampler(), + .view = specular.image_view(), + // .image_layout = + // VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL, + .layout = vk::image_layout::shader_read_only_optimal, }, }; // vulkan image descriptors are for writing textures - std::vector material_textures = { - // layout(set = 1, binding = 1) uniform sampler2D - vk::write_image_descriptor{ + std::vector + material_textures = { + // layout(set = 1, binding = 1) uniform sampler2D + vk::write_image_descriptor{ .dst_binding = 1, .sample_images = binding1_images, - }, - // layout(set = 1, binding = 2) uniform sampler2D - vk::write_image_descriptor{ + }, + // layout(set = 1, binding = 2) uniform sampler2D + vk::write_image_descriptor{ .dst_binding = 2, .sample_images = binding2_images, - }, - }; + }, + }; m_mesh_descriptors[p_entity.id()]["materials"].update( - material_uniforms, material_textures); + material_uniforms, material_textures); m_sets_layouts.push_back( - m_mesh_descriptors[p_entity.id()]["materials"].layout()); + m_mesh_descriptors[p_entity.id()]["materials"].layout()); } }); @@ -453,7 +462,8 @@ export namespace atlas::vulkan { .renderpass = m_final_renderpass, .shader_modules = modules, .vertex_attributes = m_shader_group.vertex_attributes(), - .vertex_bind_attributes = m_shader_group.vertex_bind_attributes(), + .vertex_bind_attributes = + m_shader_group.vertex_bind_attributes(), .descriptor_layouts = m_sets_layouts }; m_main_pipeline = vk::pipeline(m_device, pipeline_configuration); @@ -461,7 +471,12 @@ export namespace atlas::vulkan { console_log_warn("graphics pipeline = {}", m_main_pipeline.alive()); } - void start_frame(const vk::command_buffer& p_current, const window_params& p_settings, const VkRenderPass& p_renderpass, const VkFramebuffer& p_framebuffer, const glm::mat4& p_proj_view, uint32_t p_current_frame) override { + void start_frame(const vk::command_buffer& p_current, + const window_params& p_settings, + const VkRenderPass& p_renderpass, + const VkFramebuffer& p_framebuffer, + const glm::mat4& p_proj_view, + uint32_t p_current_frame) override { m_proj_view = p_proj_view; // m_current_frame = application::current_frame(); m_current_frame = p_current_frame; @@ -493,7 +508,7 @@ export namespace atlas::vulkan { m_current_command_buffer = p_current; m_current_command_buffer.begin( - vk::command_usage::simulatneous_use_bit); + vk::command_usage::simulatneous_use_bit); VkViewport viewport = { .x = 0.0f, @@ -516,14 +531,14 @@ export namespace atlas::vulkan { renderpass_begin_info.framebuffer = p_framebuffer; vkCmdBeginRenderPass(m_current_command_buffer, - &renderpass_begin_info, - VK_SUBPASS_CONTENTS_INLINE); + &renderpass_begin_info, + VK_SUBPASS_CONTENTS_INLINE); } void background_color(const glm::vec4& p_color) override { m_color = { { p_color.x, p_color.y, p_color.z, p_color.w }, - }; + }; } void post_frame() override { @@ -538,61 +553,66 @@ export namespace atlas::vulkan { // m_global_uniforms.update(bytes_data.data()); m_global_uniforms.update(&global_frame_ubo); - // ref current_world = system_registry::get_world("Editor World"); - // ref current_scene = current_world->get_scene("LevelScene"); - + // ref current_world = system_registry::get_world("Editor + // World"); ref current_scene = + // current_world->get_scene("LevelScene"); // query all entities that have a point light flecs::query query_point_lights = - m_current_scene->query_builder().build(); + m_current_scene->query_builder().build(); light_scene_ubo test_light = {}; uint32_t index = 0; query_point_lights.each( - [&index, &test_light](flecs::entity p_entity, point_light& p_light) { - const transform* t = p_entity.get(); - p_light.position = t->position; - - test_light.light_sources[index] = { - .position = glm::vec4(p_light.position, 1.f), - .color = p_light.color, - .attenuation = p_light.attenuation, - .constant = p_light.constant, - .linear = p_light.linear, - .quadratic = p_light.quadratic, - .ambient = p_light.ambient, - .diffuse = p_light.diffuse, - .specular = p_light.specular, - }; - index += 1; - }); + [&index, &test_light](flecs::entity p_entity, + point_light& p_light) { + const transform* t = p_entity.get(); + p_light.position = t->position; + + test_light.light_sources[index] = { + .position = glm::vec4(p_light.position, 1.f), + .color = p_light.color, + .attenuation = p_light.attenuation, + .constant = p_light.constant, + .linear = p_light.linear, + .quadratic = p_light.quadratic, + .ambient = p_light.ambient, + .diffuse = p_light.diffuse, + .specular = p_light.specular, + }; + index += 1; + }); test_light.num_lights = index; m_point_light_uniforms.update(&test_light); // query all objects with a specified 3d mesh source flecs::query<> query_targets = - m_current_scene->query_builder().build(); + m_current_scene->query_builder().build(); m_main_pipeline.bind(m_current_command_buffer); // Bind global camera data here m_global_descriptors.bind(m_current_command_buffer, - m_main_pipeline.layout()); + m_main_pipeline.layout()); query_targets.each([this](flecs::entity p_entity) { - const transform* transform_component = p_entity.get(); - const mesh_source* material_component = p_entity.get(); + const transform* transform_component = + p_entity.get(); + const mesh_source* material_component = + p_entity.get(); m_model = glm::mat4(1.f); - m_model = glm::translate(m_model, transform_component->position); + m_model = + glm::translate(m_model, transform_component->position); m_model = glm::scale(m_model, transform_component->scale); glm::mat4 rotation_mat4 = - glm::mat4(glm::quat(transform_component->rotation)); + glm::mat4(glm::quat(transform_component->rotation)); m_model *= rotation_mat4; // Mesh used for viking_room - replaced with std::map equivalent geometry_uniform mesh_ubo = { .model = m_model, - .color = material_component->color }; + .color = + material_component->color }; if (m_cached_meshes[p_entity.id()].loaded()) { m_mesh_geometry_set[p_entity.id()].update(&mesh_ubo); @@ -605,9 +625,10 @@ export namespace atlas::vulkan { m_mesh_material_set[p_entity.id()].update(&data); m_mesh_descriptors[p_entity.id()]["materials"].bind( - m_current_command_buffer, m_main_pipeline.layout()); + m_current_command_buffer, m_main_pipeline.layout()); - m_cached_meshes[p_entity.id()].draw(m_current_command_buffer); + m_cached_meshes[p_entity.id()].draw( + m_current_command_buffer); } }); diff --git a/builtin.shaders/compile.bat b/builtin.shaders/compile.bat new file mode 100644 index 00000000..d6fd90fe --- /dev/null +++ b/builtin.shaders/compile.bat @@ -0,0 +1,4 @@ +glslc.exe builtin.shaders/test.vert -o builtin.shaders/test.vert.spv +glslc.exe builtin.shaders/test.frag -o builtin.shaders/test.frag.spv + +echo Finished Compiling GLSL Shaders \ No newline at end of file diff --git a/experimental-shaders/test.frag b/builtin.shaders/test.frag similarity index 100% rename from experimental-shaders/test.frag rename to builtin.shaders/test.frag diff --git a/experimental-shaders/test.vert b/builtin.shaders/test.vert similarity index 100% rename from experimental-shaders/test.vert rename to builtin.shaders/test.vert From abbd2b6bb1e03cdb05fb5acbb05d7f3d1b30f369 Mon Sep 17 00:00:00 2001 From: SpinnerX Date: Mon, 19 Jan 2026 15:21:43 -0800 Subject: [PATCH 52/68] Added *.spv files -- TODO: should remove this and do it differently --- builtin.shaders/test.frag.spv | Bin 0 -> 7356 bytes builtin.shaders/test.vert.spv | Bin 0 -> 2928 bytes 2 files changed, 0 insertions(+), 0 deletions(-) create mode 100644 builtin.shaders/test.frag.spv create mode 100644 builtin.shaders/test.vert.spv diff --git a/builtin.shaders/test.frag.spv b/builtin.shaders/test.frag.spv new file mode 100644 index 0000000000000000000000000000000000000000..d334191367bdcbea5bc8ac6b4c8da038e2922b9a GIT binary patch literal 7356 zcmZve2bi2y6^8$0cNT%r1cC^}4M71R5u_V|jYt-CB|(~sI1ID1Fu1!Dri8?nAfni? z;q%xfwkX)JVaH(CU~i~sR1gpw78DTlegC;9Tu1J+-*e9SPPzAmUOz4OAbHc5Ce8BhRQf&b|PvRDQ0TTSsgX70c-&` zgL}bTf_Em*I3`3JVwR%V3_o0KSBy_o$5*TvpE$8vU$v^*>8_n_RHvJ>jp}5x-Kck) zs~g5WB#Ud#)~9=uc|e7Td>xgdLPk-nYBguOR6FndE;|}2IcWG!v)gQyYaU6lET^cq zrdw@f#JbK}x7(QQ)ynYT?LxgZ+v(P3yQswX=W`9Ny+)CUt-xK_t4+2kQO{yW&}%d2 zHXD?PeET!moSN!&8e8+-M`u-|-kY{+!AyG;yCCbe>3TKW-~pX(yI1cn&Zxz!rw%VM zb?D-)f59OSUAlVeu&pR-4|5ybgB^3OVa~iLW?Su<+H~LE345wtJ8xyHgTKPr7RBmj z<08)swd8h1mNi&lr{qS8eUOAyyRCE}B|ls&D*34?M45XavfY@P=IqOou3-tBJ?O`b z6o;YA)Vhs!vo>Aro!gSPhw_fRuX3Jk-d8!#Ht(zFCGXjG&Tr0gjGYd;dprUe^P$2F z7fX?o%}#m##*AU-cg2{~<wHsuPl<&r#p4M1%LaWuD?9V$~ zG#`j3u2QVQ&evSwMXk%YtwrJVz0v%}RINANt@hVZ=QZ{Bv;payC!{;?dN;zg8y&*? z`B!1j_Ga>H=F-ZwT#d}`8oL-NB6->T~vE^dKaRcqH~klMEn*tZYZ zcl?iCDZk&XUN^2txgNjg@fN}{&i)P~*YiAyD0Ro8zSzpyCpo_v5oeCvXvPgC&L5p| z*6sUS2;{@w7u|Z=zAOE?o%?I}769im-Zx`>Zs+kE@EPxLo!%3N>vRO?d~&fLhsZD^C;MZ zc=xGo{RRBL;U49J*B1z0IZDR1Db5^gZI@!5OaJ!CFTaqA^N{N1=?m;m>~7ejU=BDa z*}J1VtTi7Q^K09qSflZ-aev@gfaUv$_=q#_aCrNme`&J4`*Jbwk?669qms}1;a`@x zu$N=ozpy9Jy=U6yd0!Y~;XeaIeos2_%%r>Te1yFhD>(~?ajySaDM-%sYx_1Go7DohauhgRoAw96Z5+>bi`-9^E}!_sd9YIJfq%kovsa&ZE5r$c62@)sB7KiOw`-{yj-| z-^OeEuJs#lkM09SvHp1dSEBjOt#>3h&9!*{9OnEBrh+uqH|GB+QCoXsW_vzY4cPvU zM!auzQ)Zj*Z)o_n{rwEv_**ht|E&Y|?F055$v&3#davIEywloM>a>-Vl2IX^`=XDu*C+qm%m3|+tH=eaxI z&w+frxnCqs-Z2MwHrBflso&h~kiP_SVgDL^3%G=R>;DZfMt)v;`@coE=7~VRb#Fq- zTgUzU4r~JYZb^2`aU1r{$#*MKJAA)K-vZ3@o2MPVKcG90KEHq3$E5GfAJKOK&Sgz= zjfuYf3ElNv53IKh^3Om%`u3N^$vfPmee>Pzi~K8y8h4^w$2;=3Qq6=ZLp*Kf0VFxc{Kb*^A&bLr+!{1)-m1pIc z2aY0cTjUN&-yXSRrtg&LJEPl&ha%&*dRKJU5cWQq?YS+=Y-=Bw+4`3Z*h>fOvCKCA z^Z~m$V6RDb+`T=p-CO=3&s&JoeB<@ocY7iq zXT1PjF6>93+t+yKqv*!S$2(t$?%clfQD9wrD<5_CL-(x0ek8gvS8&e0jYk1v63#61Pw+WMmQQ_-zG0ixE)=<;E&K(}`E^%V5ztG<;W z=6xEv`NqV&r=mNzzRS{DPD8gB`t02pQqFbFN1h2>*BQWdY=e9{kdNPvXCzME;hN?G zj~=@{Zsd=yKK%ZYpuk7yqB1hi<;{`r~)#e00~U z-@W=RlZ(AR2i?710AjDx=<>1G8FV?}$oJ}b&w@oDeh*vd=Ez4sR-xzpxDY$(g&P)*$6vr)PT^7)!R_+?N6GQ0(pHi8C(lmt5q(0(~sm=D!ly^T>Zy z;*5*)kc<4w(Z`Z){;Pp&jQrOm&bU~=ocYGT7P#K9Ux)7eejoI|9vCAZF;}2FN5s4V O-8lLCdF9&vZ}VTrjRfuh literal 0 HcmV?d00001 diff --git a/builtin.shaders/test.vert.spv b/builtin.shaders/test.vert.spv new file mode 100644 index 0000000000000000000000000000000000000000..e7b11cca922bcedd55c83a3e73bbf5df23e575d1 GIT binary patch literal 2928 zcmZ9N*>W326oxytMhV#g zH*Q`><@knTn55G%Ps5jK77xWb@DtkiqjVhQ+3RrjTMFKk1e`Tahf%EE zFzPW#<22Kb{VDBp`)M{1D?BLb&bY117o^ohB^eUk6#YV=G-ZzS7{ z{p6va=KVzBn2ZTPHjCrAEKon`Ig9*nYkyjHvNaox)WtF$aMmPCe-B^y=%vosey5!> zlP`0#o%Qz>u=t>up^^B_d3_tjO!=flxR3clrx(52Ow(*w)+H!r&L;;b{+K~@t%BGy zljD9KWxgNVJ#EEBzp2HJ;Ny)`ITJ7atmg;6Dq$g6zo$o_Ln^eM~zTbW!~A>Wq9zJoPdR{gdMH3x22K=`q+j@u#&f zi^%6{#h1UH<$cT#y7(lXv)YM=c=7*^c5K1%56_I4KXfmMocrrO@qVBax@J!;$ORmK zS1Z2mj~T-s@qSh4=}U`v;lCCkza;*KcJ2gQ(usMq8X|+Z=azP2Ku+B7{7!%^>6_Uh zXLP^SP7T1&g=cQSkl)vi9rwU*RJ`Q?->NX|(ch}^)NEUHL`01{+R4HE|D-ei!Lf&D z?!dTjS39;Qhvz>H4E+u5%pv-Af3M=L=TF6>kH2Tyxtn}$>4kA-zF7G9R|xM8U(6%_ zRp`RgPyRQIr=QmHIA_jJ3y(*`* z3L`e|x*`H&?W%I*`Jo6LV&R9_&E_MWu>m)mk97uzSch#s5rz$Z%;r;_!6BB}bd>{d z?=umx;2T|PK_9{C2|AyPz^q4K=*-)smgI6>gbp~h0sB(KUCcXj{4x*VR^vN5^PcMS z@V$6&?xJ>gMfAq{c28$?!12SIdLZHrLI^)A?@=#|mh-Edwwk009<=WPH zTSQ-)+IK`?EW>`#84N#${a9i2!shXj&e)@moO$F9eBIHh?rU4wB`Q1!qMmL!~ds9Z;Sp1Er{uU literal 0 HcmV?d00001 From cde8f5ce9e1e2d5f31ce081beb22886db5c45493 Mon Sep 17 00:00:00 2001 From: SpinnerX Date: Mon, 19 Jan 2026 15:24:40 -0800 Subject: [PATCH 53/68] Updated windows.yml --- .github/workflows/windows.yml | 48 ++++++++++++++++------------------- 1 file changed, 22 insertions(+), 26 deletions(-) diff --git a/.github/workflows/windows.yml b/.github/workflows/windows.yml index 46be8767..3f7701c4 100644 --- a/.github/workflows/windows.yml +++ b/.github/workflows/windows.yml @@ -1,4 +1,4 @@ -name: Windows Build Tests +name: Windows Platform Build on: [pull_request, workflow_dispatch] @@ -8,44 +8,40 @@ jobs: runs-on: windows-latest steps: - uses: actions/checkout@v4 - - # - name: Setting up C++ on Windows - # shell: pwsh - # run: winget install Microsoft.VisualStudio.2022.BuildTools --override "--add Microsoft.VisualStudio.Workload.VCTools --includeRecommended -p --installWhileDownloading" - name: Installing Choco shell: pwsh run: Set-ExecutionPolicy Bypass -Scope Process -Force; [System.Net.ServicePointManager]::SecurityProtocol = [System.Net.ServicePointManager]::SecurityProtocol -bor 3072; iex ((New-Object System.Net.WebClient).DownloadString('https://community.chocolatey.org/install.ps1')) - - name: Install tooling with Choco + - name: Installing Git shell: pwsh - run: | - choco install cmake.install --version=3.31.6 - cmake --version - choco install llvm --version=20.1.4 - clang++ --version - choco install git make mingw - - # - name: Installing python - # run: choco install python --version=3.12.2 + run: choco install git + + - name: Install Vulkan SDK + uses: humbletim/setup-vulkan-sdk@v1.2.1 + with: + vulkan-query-version: 1.4.304.1 + vulkan-components: Vulkan-Headers, Vulkan-Loader + vulkan-use-cache: true - name: Pip installing conan shell: pwsh run: pip install conan - - # - name: Installing vulkan - # shell: pwsh - # run: winget install --id=KhronosGroup.VulkanSDK -e - - name: Setting up conan profiles + - name: Setting up Conan configuration shell: pwsh - run: conan config install -sf profiles/x86_64/Windows/ -tf profiles https://github.com/engine3d-dev/conan-config.git + run: | + conan config install https://github.com/engine3d-dev/conan-config.git + conan atlas setup - - name: Setting up packages + - name: Creating Release build for TheAtlasEngine shell: pwsh - run: conan remote add engine3d-conan https://libhal.jfrog.io/artifactory/api/conan/engine3d-conan + run: conan atlas create . -s build_type=Release - - name: Running Test Cases + - name: Creating Debug build for TheAtlasEngine shell: pwsh - run: conan build . -b missing - + run: conan atlas create . -s build_type=Debug + + - name: Creating MinSizeRel build for TheAtlasEngine + shell: pwsh + run: conan atlas create . -s build_type=MinSizeRel \ No newline at end of file From 74fbd7f5939e23560368fa79ce7e1b909cfa3325 Mon Sep 17 00:00:00 2001 From: SpinnerX Date: Mon, 19 Jan 2026 15:25:33 -0800 Subject: [PATCH 54/68] Updated project cmake to enable specific flags on Windows --- CMakeLists.txt | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/CMakeLists.txt b/CMakeLists.txt index 2f2703d7..cd321a37 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -120,11 +120,19 @@ set_packages( nfd::nfd ) +if(UNIX AND NOT APPLE) target_compile_options( ${PROJECT_NAME} PUBLIC -g -Wall -Wextra -Wno-missing-field-initializers -Wshadow -msse4.1 -mavx ) +else() +target_compile_options( + ${PROJECT_NAME} + PUBLIC + -g -Wall -Wextra -Wno-missing-field-initializers -Wshadow +) +endif() target_sources(${PROJECT_NAME} PUBLIC FILE_SET CXX_MODULES From 58f99bb2c353046d6eb7fbbb5d041d3f4d0d7dbe Mon Sep 17 00:00:00 2001 From: SpinnerX Date: Mon, 19 Jan 2026 16:08:15 -0800 Subject: [PATCH 55/68] Updated the correct code path for specifying compiler flags --- CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index cd321a37..c9ded56e 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -120,7 +120,7 @@ set_packages( nfd::nfd ) -if(UNIX AND NOT APPLE) +if(WIN32 OR UNIX) target_compile_options( ${PROJECT_NAME} PUBLIC From 668045d1ec8e30cc6245e2fd21ecd0ff2dcd4a22 Mon Sep 17 00:00:00 2001 From: SpinnerX Date: Mon, 19 Jan 2026 16:09:32 -0800 Subject: [PATCH 56/68] Updated workflows for linux and mac --- .github/workflows/linux.yml | 40 +++++++++++++++++++++---------------- .github/workflows/mac.yml | 36 ++++++++++++++++++++++----------- 2 files changed, 47 insertions(+), 29 deletions(-) diff --git a/.github/workflows/linux.yml b/.github/workflows/linux.yml index 5f229265..11d337b6 100644 --- a/.github/workflows/linux.yml +++ b/.github/workflows/linux.yml @@ -1,4 +1,4 @@ -name: Linux Build Tests +name: Linux Platform Build on: [pull_request] @@ -9,11 +9,8 @@ jobs: steps: - uses: actions/checkout@v4 - - name: Install LLVM - run: wget https://apt.llvm.org/llvm.sh && chmod +x llvm.sh && sudo ./llvm.sh - - name: Install LLVM's C++ Standard Library - run: sudo apt install libc++-17-dev libc++abi-17-dev + run: sudo apt-get install libc++-20-dev libc++abi-20-dev - name: Installing pipx run: sudo apt install pipx @@ -21,24 +18,33 @@ jobs: - name: Installing Prerequisites for Linux run: | sudo apt-get update - sudo apt install lsb-release wget software-properties-common gnupg libgtk2.0-dev libgl1-mesa-dev -y - # sudo apt install libx11-dev libx11-xcb-dev libfontenc-dev libice-dev libsm-dev libxau-dev libxaw7-dev libxt-dev libxtst-dev libxrender-dev libxrandr-dev libxi-dev -y - sudo apt-get install -y libx11-dev libx11-xcb-dev libfontenc-dev libice-dev libsm-dev libxau-dev libxaw7-dev libxt-dev libxtst-dev libxrender-dev libxrandr-dev libxi-dev sudo apt install software-properties-common -y sudo add-apt-repository ppa:deadsnakes/ppa + - name: Install Vulkan SDK + uses: humbletim/setup-vulkan-sdk@v1.2.1 + with: + vulkan-query-version: 1.4.304.1 + vulkan-components: Vulkan-Headers, Vulkan-Loader + vulkan-use-cache: true + - name: Installing Conan - run: pipx install "conan>=2.10.1" + run: pipx install "conan>=2.18.1" - name: Setting up Conan Profiles run: conan config install -sf profiles/x86_64/linux/ -tf profiles https://github.com/engine3d-dev/conan-config.git - - name: Installing project dependencies - run: conan remote add engine3d-conan https://libhal.jfrog.io/artifactory/api/conan/engine3d-conan - - - name: Cloning Atlas repository - run: git clone https://github.com/engine3d-dev/TheAtlasEngine - - - name: Building Atlas - run: conan build . -b missing -c tools.system.package_manager:sudo=True -c tools.system.package_manager:mode=install + - name: Setting up Conan + run: | + conan config install https://github.com/engine3d-dev/conan-config.git + conan atlas setup + + - name: Creating Release build for vulkan-cpp + run: conan atlas create . -s build_type=Release + + - name: Creating Debug build for vulkan-cpp + run: conan atlas create . -s build_type=Debug + + - name: Creating MinSizeRel build for vulkan-cpp + run: conan atlas create . -s build_type=MinSizeRel diff --git a/.github/workflows/mac.yml b/.github/workflows/mac.yml index c8d17e03..4f185375 100644 --- a/.github/workflows/mac.yml +++ b/.github/workflows/mac.yml @@ -1,4 +1,4 @@ -name: Macos Build Tests +name: Macos Platform Build on: [pull_request] @@ -14,10 +14,20 @@ jobs: - name: Install LLVM run: | - brew install python pipx llvm@17 + brew install python pipx + + - name: Install Vulkan SDK + uses: humbletim/setup-vulkan-sdk@v1.2.1 + with: + vulkan-query-version: 1.4.304.1 + vulkan-components: Vulkan-Headers, Vulkan-Loader + vulkan-use-cache: true + - name: Installing conan - run: pipx install "conan>=2.10.2" + run: | + pipx install "conan>=2.18.2" + pipx upgrade conan - name: Installing clang-tidy run: sudo ln -s $(brew --prefix llvm)/bin/clang-tidy /usr/local/bin/ @@ -25,14 +35,16 @@ jobs: - name: Install Rosetta run: /usr/sbin/softwareupdate --install-rosetta --agree-to-license - - name: Setting up Conan profile - run: conan config install -sf profiles/armv8/mac/ -tf profiles https://github.com/engine3d-dev/conan-config.git - - - name: Installing Atlas repositories - run: conan remote add engine3d-conan https://libhal.jfrog.io/artifactory/api/conan/engine3d-conan + - name: Setting up Conan configuration + run: | + conan config install https://github.com/engine3d-dev/conan-config.git + conan atlas setup - - name: Cloning Atlas repository - run: git clone https://github.com/engine3d-dev/TheAtlasEngine + - name: Creating Release build for vulkan-cpp + run: conan atlas create . -s build_type=Release + + - name: Creating Debug build for vulkan-cpp + run: conan atlas create . -s build_type=Debug - - name: Building the project - run: conan build . -b missing + - name: Creating MinSizeRel build for vulkan-cpp + run: conan atlas create . -s build_type=MinSizeRel \ No newline at end of file From df31b9892efb0a8cc93db876a2bdfabd19dffc87 Mon Sep 17 00:00:00 2001 From: SpinnerX Date: Mon, 19 Jan 2026 16:26:28 -0800 Subject: [PATCH 57/68] Updated nfd/2.0 to 3.0 in conanfile.py --- conanfile.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/conanfile.py b/conanfile.py index 0011d69c..32cfb1c3 100644 --- a/conanfile.py +++ b/conanfile.py @@ -44,7 +44,7 @@ def requirements(self): self.requires("tinyobjloader/2.0.0-rc10") self.requires("stb/cci.20230920") - self.requires("nfd/2.0") + self.requires("nfd/3.0") self.requires("watcher/0.12.0") self.requires("boost-ext-ut/2.3.1") From 1b1452fc72a53c5a4f0b3e17e1de400a0cc06b17 Mon Sep 17 00:00:00 2001 From: SpinnerX Date: Mon, 19 Jan 2026 19:22:02 -0800 Subject: [PATCH 58/68] Finalized changes to conanfile.py --- conanfile.py | 1 - 1 file changed, 1 deletion(-) diff --git a/conanfile.py b/conanfile.py index 32cfb1c3..362f2eae 100644 --- a/conanfile.py +++ b/conanfile.py @@ -64,7 +64,6 @@ def layout(self): cmake_layout(self) def generate(self): - # llvm = self.dependencies["llvm-toolchain/20"] llvm_path = self.dependencies.build["llvm-toolchain"].package_folder cmake_path = self.dependencies.build["cmake"].package_folder cmake_binary_location = f"{cmake_path.replace("\\", "/")}/bin/cmake.exe" From dafcbe2e2b8589545ba4edd37e1859e5c38cb13c Mon Sep 17 00:00:00 2001 From: SpinnerX Date: Mon, 19 Jan 2026 19:24:53 -0800 Subject: [PATCH 59/68] Commented out adding editor in the cmake file --- CMakeLists.txt | 32 +------------------------------- 1 file changed, 1 insertion(+), 31 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index c9ded56e..3128ed32 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -49,38 +49,8 @@ else() message(WARNING "${CMAKE_PATH} not found!") endif() -# build_core_library( -# DIRECTORIES src editor - -# ENABLE_TESTS ${ENABLE_TESTS_ONLY} - -# UNIT_TEST_SOURCES - -# tests/main.test.cpp -# tests/basic_add.test.cpp -# tests/entity_component_system.test.cpp -# tests/math.test.cpp -# tests/scene.test.cpp -# tests/jolt_type_conversion.test.cpp -# tests/jolt_engine.test.cpp - -# PACKAGES -# tinyobjloader -# ${SHADERC_PACKAGE} -# watcher -# vulkan-cpp` -# nfd - -# LINK_PACKAGES -# tinyobjloader::tinyobjloader -# ${SHADERC_LINK_PACKAGE} -# watcher::watcher -# vulkan-cpp -# nfd::nfd -# ) - add_library(${PROJECT_NAME} STATIC) -add_subdirectory(editor) +# add_subdirectory(editor) set_packages( ENABLE_TESTS OFF From eae34ea8359834300e3c0987820ce322186987b3 Mon Sep 17 00:00:00 2001 From: SpinnerX Date: Mon, 19 Jan 2026 22:03:54 -0800 Subject: [PATCH 60/68] Updated project cmake to make sure they are enabled on other platforms besides apple --- CMakeLists.txt | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 3128ed32..4ab34110 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -90,17 +90,17 @@ set_packages( nfd::nfd ) -if(WIN32 OR UNIX) +if(APPLE) target_compile_options( ${PROJECT_NAME} PUBLIC - -g -Wall -Wextra -Wno-missing-field-initializers -Wshadow -msse4.1 -mavx + -g -Wall -Wextra -Wno-missing-field-initializers -Wshadow ) else() target_compile_options( ${PROJECT_NAME} PUBLIC - -g -Wall -Wextra -Wno-missing-field-initializers -Wshadow + -g -Wall -Wextra -Wno-missing-field-initializers -Wshadow -msse4.1 -mavx ) endif() From 1ad52a6056102bc6821b428044654198c6e37ec2 Mon Sep 17 00:00:00 2001 From: SpinnerX Date: Mon, 19 Jan 2026 22:04:46 -0800 Subject: [PATCH 61/68] Changed to TheAtlasEngine --- .github/workflows/linux.yml | 6 +++--- .github/workflows/mac.yml | 6 +++--- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/.github/workflows/linux.yml b/.github/workflows/linux.yml index 11d337b6..f139a319 100644 --- a/.github/workflows/linux.yml +++ b/.github/workflows/linux.yml @@ -39,12 +39,12 @@ jobs: conan config install https://github.com/engine3d-dev/conan-config.git conan atlas setup - - name: Creating Release build for vulkan-cpp + - name: Creating Release build for TheAtlasEngine run: conan atlas create . -s build_type=Release - - name: Creating Debug build for vulkan-cpp + - name: Creating Debug build for TheAtlasEngine run: conan atlas create . -s build_type=Debug - - name: Creating MinSizeRel build for vulkan-cpp + - name: Creating MinSizeRel build for TheAtlasEngine run: conan atlas create . -s build_type=MinSizeRel diff --git a/.github/workflows/mac.yml b/.github/workflows/mac.yml index 4f185375..2c52c1f0 100644 --- a/.github/workflows/mac.yml +++ b/.github/workflows/mac.yml @@ -40,11 +40,11 @@ jobs: conan config install https://github.com/engine3d-dev/conan-config.git conan atlas setup - - name: Creating Release build for vulkan-cpp + - name: Creating Release build for TheAtlasEngine run: conan atlas create . -s build_type=Release - - name: Creating Debug build for vulkan-cpp + - name: Creating Debug build for TheAtlasEngine run: conan atlas create . -s build_type=Debug - - name: Creating MinSizeRel build for vulkan-cpp + - name: Creating MinSizeRel build for TheAtlasEngine run: conan atlas create . -s build_type=MinSizeRel \ No newline at end of file From 36c6751a7d06f8cfee27ba2d12f601773fc43678 Mon Sep 17 00:00:00 2001 From: SpinnerX Date: Mon, 19 Jan 2026 22:43:48 -0800 Subject: [PATCH 62/68] Minor bug fixes --- atlas/core/ui/widgets.cppm | 1 + atlas/drivers/vulkan/shader_resource_group.cppm | 14 ++++++++++++-- atlas/physics/physics_engine.cppm | 2 +- 3 files changed, 14 insertions(+), 3 deletions(-) diff --git a/atlas/core/ui/widgets.cppm b/atlas/core/ui/widgets.cppm index 9cf44872..a89f4992 100644 --- a/atlas/core/ui/widgets.cppm +++ b/atlas/core/ui/widgets.cppm @@ -6,6 +6,7 @@ module; #include #include #include +#include export module atlas.core.ui.widgets; diff --git a/atlas/drivers/vulkan/shader_resource_group.cppm b/atlas/drivers/vulkan/shader_resource_group.cppm index 16d77762..ff5c23d5 100644 --- a/atlas/drivers/vulkan/shader_resource_group.cppm +++ b/atlas/drivers/vulkan/shader_resource_group.cppm @@ -324,8 +324,18 @@ namespace atlas::vulkan { // Using C++'s std::views to extract all of the values in // unordered_map to a vector // that gets passed to graphics pipeline - return (m_modules | std::views::values | - std::ranges::to()); + // TEMP: Removing this. Will add this back in later. + // return (m_modules | std::views::values | + // std::ranges::to()); + std::vector<::vk::shader_handle> result; + + result.reserve(m_modules.size()); + + for (auto const& [name, handle] : m_modules) { + result.push_back(handle); + } + + return result; } void create_module(std::span p_blob, const ::vk::shader_source& p_source) { diff --git a/atlas/physics/physics_engine.cppm b/atlas/physics/physics_engine.cppm index 338cbbbf..64385d8c 100644 --- a/atlas/physics/physics_engine.cppm +++ b/atlas/physics/physics_engine.cppm @@ -1,7 +1,7 @@ module; #include -#include +#include export module atlas.physics.engine; From 8634addc97fddfb688661460f093fffa8e4b54cb Mon Sep 17 00:00:00 2001 From: SpinnerX Date: Tue, 20 Jan 2026 01:18:25 -0800 Subject: [PATCH 63/68] Removed redundant tests and conform tests to using imports --- tests/entity_component_system.test.cpp | 12 +++++-- tests/jolt_engine.test.cpp | 35 --------------------- tests/jolt_type_conversion.test.cpp | 43 -------------------------- tests/math.test.cpp | 4 +-- tests/scene.test.cpp | 9 +++--- 5 files changed, 16 insertions(+), 87 deletions(-) delete mode 100644 tests/jolt_engine.test.cpp delete mode 100644 tests/jolt_type_conversion.test.cpp diff --git a/tests/entity_component_system.test.cpp b/tests/entity_component_system.test.cpp index 4e5b6ec5..49883113 100644 --- a/tests/entity_component_system.test.cpp +++ b/tests/entity_component_system.test.cpp @@ -1,10 +1,16 @@ #include -#include +// #include #include #include #include -#include +// #include +import atlas.core.scene; +import atlas.core.scene.game_object; +import atlas.core.math.types; +import atlas.core.event; + +#include namespace atlas { @@ -82,7 +88,7 @@ namespace atlas { //! @note Each scene will define flecs::world typically //! @note flecs::world is how flecs (ECS) stores entities and components - atlas::event::event_bus test_event_bus; + atlas::event::bus test_event_bus; atlas::scene test_scene = atlas::scene("Mock Scene", test_event_bus); "create_entity::add"_test = [&test_scene] { diff --git a/tests/jolt_engine.test.cpp b/tests/jolt_engine.test.cpp deleted file mode 100644 index c20aa02d..00000000 --- a/tests/jolt_engine.test.cpp +++ /dev/null @@ -1,35 +0,0 @@ -#include -#include -#include -#include -#include - -#include -#include -#include - -#include - -namespace atlas { - - /** - * @brief The physics is fully reliant on the ecs working. As it utilizes - * queries as well as scene to navigate location of entities. - * - */ - boost::ut::suite<"physics_engine_integration"> engine_test = [] { - using namespace boost::ut; - - // Setup to do testing and assume we have a specified current scene that - // gets provided to you during that runtime - atlas::event::event_bus bus; - atlas::scene test_environment_scene = atlas::scene("Mock 1", bus); - - // Do some testing if these two collides or something like that - // atlas::game_object obj1 = test_environment_scene.entity("Entity - // 1"); atlas::game_object obj2 = - // test_environment_scene.entity("Entity 2"); - - "on_collision_enter"_test = [] {}; - }; -}; \ No newline at end of file diff --git a/tests/jolt_type_conversion.test.cpp b/tests/jolt_type_conversion.test.cpp deleted file mode 100644 index 76f52f79..00000000 --- a/tests/jolt_type_conversion.test.cpp +++ /dev/null @@ -1,43 +0,0 @@ -#include -#include -#include -#include -#include -#include -#include - -#include -#include - -namespace atlas { - - bool approx_equal(float a, float b, float epsilon = 1e-6f) { - return std::fabs(a - b) < epsilon; - } - - boost::ut::suite<"jolt_helper"> jolt_helper_tests = [] { - using namespace boost::ut; - - "to_jph::vec3 conversion"_test = [] { - glm::vec3 glm_vec{ 1.0f, 2.0f, 3.0f }; - JPH::Vec3 jph_vec = jolt::to_vec3(glm_vec); - - expect(approx_equal(jph_vec.GetX(), 1.0f)); - expect(approx_equal(jph_vec.GetY(), 2.0f)); - expect(approx_equal(jph_vec.GetZ(), 3.0f)); - }; - - "to_jph::quat conversion"_test = [] { - glm::quat glm_quat{ 0.707f, 0.0f, 0.707f, 0.0f }; - glm::vec4 quat_vec = - glm::vec4(glm_quat.x, glm_quat.y, glm_quat.z, glm_quat.w); - - JPH::Quat jph_quat = jolt::to_quat(quat_vec); - - expect(approx_equal(jph_quat.GetX(), 0.0f)); - expect(approx_equal(jph_quat.GetY(), 0.707f)); - expect(approx_equal(jph_quat.GetZ(), 0.0f)); - expect(approx_equal(jph_quat.GetW(), 0.707f)); - }; - }; -}; \ No newline at end of file diff --git a/tests/math.test.cpp b/tests/math.test.cpp index 74a13be4..bb5f109b 100644 --- a/tests/math.test.cpp +++ b/tests/math.test.cpp @@ -1,8 +1,8 @@ -#include - +#include #include #include #include +import atlas.core.math.types; namespace atlas { /** diff --git a/tests/scene.test.cpp b/tests/scene.test.cpp index 32e567ec..c5eb1ea0 100644 --- a/tests/scene.test.cpp +++ b/tests/scene.test.cpp @@ -1,11 +1,12 @@ #include -#include -#include -#include +import atlas.core.scene; +import atlas.core.scene.game_object; +import atlas.core.scene.components; +import atlas.core.event; boost::ut::suite<"::scene"> scene_test = []() { using namespace boost::ut; - atlas::event::event_bus test_event_bus; + atlas::event::bus test_event_bus; atlas::scene test_scene = atlas::scene("Mock Scene 1", test_event_bus); "create_object"_test = [&test_scene]() { From d460c04c12c969107af7a45614dae31d396cf9c1 Mon Sep 17 00:00:00 2001 From: SpinnerX Date: Tue, 20 Jan 2026 01:18:47 -0800 Subject: [PATCH 64/68] Updated CMake to include tests --- CMakeLists.txt | 16 +++++++++++++++- 1 file changed, 15 insertions(+), 1 deletion(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 4ab34110..72452fcf 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -52,8 +52,22 @@ endif() add_library(${PROJECT_NAME} STATIC) # add_subdirectory(editor) +if(${ENABLE_TESTS_ONLY}) +message(STATUS "ENABLING_TESTS_ON = TRUE") +build_unit_test( + TEST_SOURCES + tests/main.test.cpp + tests/basic_add.test.cpp + tests/entity_component_system.test.cpp + tests/math.test.cpp + tests/scene.test.cpp + + LINK_PACKAGES + atlas +) +endif() + set_packages( - ENABLE_TESTS OFF PACKAGES glfw3 From f199ecc0584f795725ea7a7029ea8203dfea4ea7 Mon Sep 17 00:00:00 2001 From: SpinnerX Date: Tue, 20 Jan 2026 01:25:50 -0800 Subject: [PATCH 65/68] Conform code to clang-format --- atlas/core/entry_point/main.cpp | 55 ++++++--------------------------- editor/application.cpp | 17 +++++----- 2 files changed, 20 insertions(+), 52 deletions(-) diff --git a/atlas/core/entry_point/main.cpp b/atlas/core/entry_point/main.cpp index e9ae5163..f2d952b6 100644 --- a/atlas/core/entry_point/main.cpp +++ b/atlas/core/entry_point/main.cpp @@ -4,68 +4,33 @@ import atlas.application; import atlas.common; import atlas.logger; import atlas.graphics_api; - -// expose visibility to ref import atlas.drivers.graphics_context; - -// this includes initialize_context -// import atlas.drivers; import atlas.renderer.context_loader; import atlas.core.scene.system_registry; // Defined in the user-application side -[[nodiscard]] atlas::ref initialize_application(atlas::ref p_context); - +[[nodiscard]] atlas::ref initialize_application( + atlas::ref p_context); -// /* -// atlas/* -// core/* -// import atlas.core; -// drivers/ -// vulkan -// import atlas.vulkan -// jolt_cpp -// import atlas.jolt_cpp -// .... -// physics -// import atlas.physics -// renderer -// import atlas.renderer -// */ - -// /* -// core: module that is partitioned associated with -// logger -// import logger; -// drivers: -// vulkan: module that is partitioned associated with -// import vulkan; -// internal: export module vulkan:* -// jolt_cpp: module that is partitioned associated with -// import jolt_cpp -// internal: export module jolt_cpp:* -// atlas: global module unit -// export import core; -// export import vulkan; -// export import jolt_cpp -// */ - -int main() { +int +main() { atlas::console_log_manager manager = atlas::console_log_manager(); - if(!glfwInit()) { + if (!glfwInit()) { console_log_fatal("GLFW: Initialization failed!!"); return -1; } // TODO: Level streamer is going to be replacing system_registry - atlas::ref system = atlas::create_ref("system"); - atlas::ref context = atlas::initialize_context("vulkan", atlas::graphics_api::vulkan); + atlas::ref system = + atlas::create_ref("system"); + atlas::ref context = + atlas::initialize_context("vulkan", atlas::graphics_api::vulkan); atlas::ref app = initialize_application(context); app->execute(); - + app->post_destroy(); context->destroy(); diff --git a/editor/application.cpp b/editor/application.cpp index c48d5c04..ede95a60 100644 --- a/editor/application.cpp +++ b/editor/application.cpp @@ -8,23 +8,26 @@ import atlas.drivers.graphics_context; class test_application : public atlas::application { public: - test_application(atlas::ref p_context, const atlas::application_settings& p_settings) : atlas::application(p_context, p_settings) { - // atlas::register_update(this, &test_application::on_update);std::pmr::monotonic_buffer_resource resource{ 4096 }; - // m_allocator.construct(&resource); + test_application(atlas::ref p_context, + const atlas::application_settings& p_settings) + : atlas::application(p_context, p_settings) { + // atlas::register_update(this, + // &test_application::on_update);std::pmr::monotonic_buffer_resource + // resource{ 4096 }; m_allocator.construct(&resource); // TODO -- this is going to be changed with the use of the level // streamer API - m_world = atlas::create_ref("Editor World", renderer_instance()); + m_world = + atlas::create_ref("Editor World", renderer_instance()); } - private: // std::pmr::polymorphic_allocator m_allocator; atlas::ref m_world; - }; -atlas::ref initialize_application(atlas::ref p_contetxt) { +atlas::ref +initialize_application(atlas::ref p_contetxt) { atlas::application_settings settings = { .name = "Editor", .width = 1200, From 6e282e2916b49a8826ee5339c070cded46998ed9 Mon Sep 17 00:00:00 2001 From: SpinnerX Date: Tue, 20 Jan 2026 17:35:16 -0800 Subject: [PATCH 66/68] Minimal change to project cmake adding object.test.cpp --- CMakeLists.txt | 24 ++++++++++++------------ 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 72452fcf..727e459a 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -53,18 +53,18 @@ add_library(${PROJECT_NAME} STATIC) # add_subdirectory(editor) if(${ENABLE_TESTS_ONLY}) -message(STATUS "ENABLING_TESTS_ON = TRUE") -build_unit_test( - TEST_SOURCES - tests/main.test.cpp - tests/basic_add.test.cpp - tests/entity_component_system.test.cpp - tests/math.test.cpp - tests/scene.test.cpp - - LINK_PACKAGES - atlas -) + build_unit_test( + TEST_SOURCES + tests/main.test.cpp + tests/basic_add.test.cpp + tests/entity_component_system.test.cpp + tests/math.test.cpp + tests/scene.test.cpp + tests/object.test.cpp + + LINK_PACKAGES + atlas + ) endif() set_packages( From 3299b8eacafecbd67462237b5178885ee844a774 Mon Sep 17 00:00:00 2001 From: SpinnerX Date: Thu, 22 Jan 2026 03:32:56 -0800 Subject: [PATCH 67/68] Cleaned up project cmake and updated cmake utils to 5.0 --- CMakeLists.txt | 12 +----------- conanfile.py | 2 +- tests/object.test.cpp | 5 ----- 3 files changed, 2 insertions(+), 17 deletions(-) delete mode 100644 tests/object.test.cpp diff --git a/CMakeLists.txt b/CMakeLists.txt index 727e459a..80f3a972 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -5,7 +5,7 @@ set(CMAKE_EXPORT_COMPILE_COMMANDS ON) set(CMAKE_COLOR_DIAGNOSTICS ON) project(atlas LANGUAGES CXX) -set(ENGINE_INCLUDE_DIR ${CMAKE_CURRENT_LIST_DIR}/atlas) + # TODO: Remove this once shaderc in the github CI is fixed option(USE_SHADERC "[${PROJECT_NAME}] Enabling shaderc" OFF) @@ -60,7 +60,6 @@ if(${ENABLE_TESTS_ONLY}) tests/entity_component_system.test.cpp tests/math.test.cpp tests/scene.test.cpp - tests/object.test.cpp LINK_PACKAGES atlas @@ -205,9 +204,6 @@ target_sources(${PROJECT_NAME} PUBLIC atlas/drivers/vulkan/physical_device.cppm atlas/drivers/vulkan/device.cppm atlas/drivers/vulkan/swapchain.cppm - - # entry point - # atlas/core/entry_point/main.cppm ) target_sources(${PROJECT_NAME} PUBLIC @@ -216,12 +212,6 @@ target_sources(${PROJECT_NAME} PUBLIC PRIVATE atlas/core/entry_point/main.cpp ) -# target_sources(${PROJECT_NAME} PUBLIC -# FILE_SET CXX_MODULES -# TYPE CXX_MODULES -# PRIVATE atlas/core/main.cpp -# ) - target_compile_features(${PROJECT_NAME} PUBLIC cxx_std_23) # install(TARGETS ${PROJECT_NAME}) diff --git a/conanfile.py b/conanfile.py index 362f2eae..6cf03b46 100644 --- a/conanfile.py +++ b/conanfile.py @@ -26,7 +26,7 @@ class AtlasRecipe(ConanFile): def build_requirements(self): self.tool_requires("cmake/4.1.1") self.tool_requires("ninja/1.13.1") - self.tool_requires("engine3d-cmake-utils/4.0") + self.tool_requires("engine3d-cmake-utils/5.0") def requirements(self): self.requires("joltphysics/5.2.0") diff --git a/tests/object.test.cpp b/tests/object.test.cpp deleted file mode 100644 index a93b0fa3..00000000 --- a/tests/object.test.cpp +++ /dev/null @@ -1,5 +0,0 @@ -#include - -boost::ut::suite<"::object_test"> object_test = []() { - using namespace boost::ut; -}; \ No newline at end of file From 97bf06898adb0ff6afb1993d68695d5a045817a6 Mon Sep 17 00:00:00 2001 From: SpinnerX Date: Thu, 22 Jan 2026 22:52:17 -0800 Subject: [PATCH 68/68] Updated the README --- README.md | 25 ++++++++++--------------- 1 file changed, 10 insertions(+), 15 deletions(-) diff --git a/README.md b/README.md index 93d5da00..e67be14d 100644 --- a/README.md +++ b/README.md @@ -5,40 +5,35 @@ [![GitHub forks](https://img.shields.io/github/forks/engine3d-dev/TheAtlasEngine.svg)](https://github.com/engine3d-dev/TheAtlasEngine/network) [![GitHub issues](https://img.shields.io/github/issues/engine3d-dev/TheAtlasEngine.svg)](https://github.com/engine3d-dev/TheAtlasEngine/issues) -Open-source custom C++ 3D game engine which uses Vulkan for building games. +An open-source 3D game engine using C++ and Vulkan with native C++20 module support. # Setup Development Environment -TheAtlasEngine uses Conan the C++ package manager to manage our dependencies. - -Before you build the project, make sure to check the [getting start](https://engine3d-dev.github.io/0.1/getting_started/) page. +New here? We use the C++ package manager, Conan. Follow the [Getting Started Guide](https://engine3d-dev.github.io/0.1/getting_started/) to setup your environment. ## How to Build the Editor -Since there is not a way to set for building the editor. In the CMakeLists.txt file. +Since there isn't a way to officially to building the editor. In the CMakeLists.txt file. -Just add `editor` into your CMakeLists.txt file as shown in this example to build the editor. +Just uncomment the `editor` into your CMakeLists.txt file as shown in this example to build the editor. ```Cmake -build_core_library( - DIRECTORIES src editor - # ... -) +add_subdirectory(editor) ``` ## Building the Project > [!TIP] -> `-b missing` is to install any missing dependencies necessary to build TheAtlasEngine successfully. -> `-s build_type=Debug` is to compile as a debug build when developing on the project. +> `-s build_type=Debug` is recommended to compile the project as a Debug build for development. +> For development to disable the testing environment. ``` -conan build . -b missing -s build_type=Debug +conan atlas build . -s build_type=Debug -o enable_tests_only=False ``` ## Executable Location -After building TheAtlasEngine and the dependencies have been built successful. These are three locations where the editor executable is located at. +After building TheAtlasEngine has been successful. Your executable will be executed via the following path layout. * Debug build will follow with, `./build/Debug/` * Release build will follow with, `./build/Release/` @@ -67,7 +62,7 @@ This was the first game that we made with TheAtlasEngine when the project first ## Wallace and Grommit Rocket Game ### Description -Part of the SFSU Game Dev Club's Game Jam of Spring 2025. We developed a flappy-bird-like game mechanic rocket game. This is inspired by a few youtubers who also made a similar game. One of the YouTuber's named TheCherno. +Developed during the SFSU Game Dev Club Spring 2025 Game Jam, this project serves as a technical demonstration of TheAtlasEngine core capabilities. Inspired by similar projects from creators like TheCherno -- to test the game engine's capabilities. * [itch.io link](https://niccoll-dyson.itch.io/wallace-and-grommit-spaceship-game) to out game jam submission * GitHub [repository link](https://github.com/SpinnerX/3d-rocket-game)