diff --git a/modules/CMakeLists.txt b/modules/CMakeLists.txt index 7665565..8ec8561 100644 --- a/modules/CMakeLists.txt +++ b/modules/CMakeLists.txt @@ -1,26 +1,37 @@ -# engine -add_subdirectory(./std) -add_subdirectory(./bitwise) -add_subdirectory(./env) -add_subdirectory(./memory) -add_subdirectory(./time) -add_subdirectory(./logger) -add_subdirectory(./debug) -add_subdirectory(./math) -# -add_subdirectory(./asset_baker) -add_subdirectory(./assets) -# -add_subdirectory(./camera) -add_subdirectory(./input) -# add_subdirectory(./ui) -# -add_subdirectory(./surface) -add_subdirectory(./renderer) -add_subdirectory(./ecs) -# -add_subdirectory(./app) +# engine add_subdirectory(./std) -# apps -add_subdirectory(./mirror) add_subdirectory(test) + +add_subdirectory(./logger) + +add_subdirectory(./bitwise) + +add_subdirectory(./env) + +add_subdirectory(./memory) + +add_subdirectory(./time) + +add_subdirectory(./debug) + +add_subdirectory(./math) + +add_subdirectory(./assets) + +add_subdirectory(./asset_baker) + +add_subdirectory(./camera) + +add_subdirectory(./app) +add_subdirectory(./ecs) + +add_subdirectory(./surface) + +add_subdirectory(./input) + +# add_subdirectory(./ui) + +# add_subdirectory(./renderer) + +# +# add_subdirectory(./mirror) diff --git a/modules/app/CMakeLists.txt b/modules/app/CMakeLists.txt index f7636bb..50919ba 100644 --- a/modules/app/CMakeLists.txt +++ b/modules/app/CMakeLists.txt @@ -1,4 +1,12 @@ -add_library_module(app application.cpp) +add_library_module( + NAME + app + INTERFACES + application.cppm + system.cppm + SOURCES + entrypoint.cpp) + target_link_libraries( app PUBLIC memory diff --git a/modules/app/application.cppm b/modules/app/application.cppm new file mode 100644 index 0000000..09784a9 --- /dev/null +++ b/modules/app/application.cppm @@ -0,0 +1,98 @@ +export module app; +import app.system; +import memory.reference; +import memory.scope; +import std; + +namespace lt::app { + +/** The main application class. + * Think of this like an aggregate of systems, you register systems through this interface. + * Then they'll tick every "application frame". + */ +export class Application +{ +public: + Application(const Application &) = delete; + + Application(Application &&) = delete; + + auto operator=(const Application &) -> Application & = delete; + + auto operator=(Application &&) -> Application & = delete; + + virtual ~Application() = default; + + void game_loop(); + + void register_system(memory::Ref system); + + void unregister_system(memory::Ref system); + +protected: + Application() = default; + +private: + std::vector> m_systems; + + std::vector> m_systems_to_be_unregistered; + + std::vector> m_systems_to_be_registered; +}; + +export extern memory::Scope create_application(); + +} // namespace lt::app + +module :private; +namespace lt::app { + +void Application::game_loop() +{ + while (true) + { + for (auto &system : m_systems) + { + const auto &last_tick = system->get_last_tick_result(); + const auto now = std::chrono::steady_clock::now(); + + system->tick( + TickInfo { + .delta_time = now - last_tick.end_time, + .budget = std::chrono::milliseconds { 10 }, + .start_time = now, + } + ); + } + + for (auto &system : m_systems_to_be_registered) + { + m_systems.emplace_back(system)->on_register(); + } + + for (auto &system : m_systems_to_be_unregistered) + { + m_systems.erase( + std::remove(m_systems.begin(), m_systems.end(), system), + m_systems.end() + ); + } + + if (m_systems.empty()) + { + return; + } + } +} + +void Application::register_system(memory::Ref system) +{ + m_systems.emplace_back(std::move(system)); +} + +void Application::unregister_system(memory::Ref system) +{ + m_systems_to_be_unregistered.emplace_back(std::move(system)); +} + +} // namespace lt::app diff --git a/modules/app/entrypoint.cpp b/modules/app/entrypoint.cpp new file mode 100644 index 0000000..7ef54bb --- /dev/null +++ b/modules/app/entrypoint.cpp @@ -0,0 +1,31 @@ +import memory.scope; +import logger; +import app; +import std; + +/** The ultimate entrypoint. */ +auto main(int argc, char *argv[]) -> std::int32_t +{ + try + { + std::ignore = argc; + std::ignore = argv; + + auto application = lt::memory::Scope {}; + application = lt::app::create_application(); + if (!application) + { + throw std::runtime_error { "Failed to create application\n" }; + } + + application->game_loop(); + return 0; + } + catch (const std::exception &exp) + { + lt::log::critical("Terminating due to uncaught exception:"); + lt::log::critical("\texception.what(): {}", exp.what()); + + return 1; + } +} diff --git a/modules/app/private/application.cpp b/modules/app/private/application.cpp deleted file mode 100644 index 32d8fdb..0000000 --- a/modules/app/private/application.cpp +++ /dev/null @@ -1,55 +0,0 @@ -#include -#include -#include - -namespace lt::app { - -void Application::game_loop() -{ - while (true) - { - for (auto &system : m_systems) - { - const auto &last_tick = system->get_last_tick_result(); - const auto now = std::chrono::steady_clock::now(); - - system->tick( - TickInfo { - .delta_time = now - last_tick.end_time, - .budget = std::chrono::milliseconds { 10 }, - .start_time = now, - } - ); - } - - for (auto &system : m_systems_to_be_registered) - { - m_systems.emplace_back(system)->on_register(); - } - - for (auto &system : m_systems_to_be_unregistered) - { - m_systems.erase( - std::remove(m_systems.begin(), m_systems.end(), system), - m_systems.end() - ); - } - - if (m_systems.empty()) - { - return; - } - } -} - -void Application::register_system(memory::Ref system) -{ - m_systems.emplace_back(std::move(system)); -} - -void Application::unregister_system(memory::Ref system) -{ - m_systems_to_be_unregistered.emplace_back(std::move(system)); -} - -} // namespace lt::app diff --git a/modules/app/public/application.hpp b/modules/app/public/application.hpp deleted file mode 100644 index c67297b..0000000 --- a/modules/app/public/application.hpp +++ /dev/null @@ -1,47 +0,0 @@ -#pragma once - -#include -#include - -namespace lt::app { - -class ISystem; - -extern memory::Scope create_application(); - -/** The main application class. - * Think of this like an aggregate of systems, you register systems through this interface. - * Then they'll tick every "application frame". - */ -class Application -{ -public: - Application(const Application &) = delete; - - Application(Application &&) = delete; - - auto operator=(const Application &) -> Application & = delete; - - auto operator=(Application &&) -> Application & = delete; - - virtual ~Application() = default; - - void game_loop(); - - void register_system(memory::Ref system); - - void unregister_system(memory::Ref system); - -protected: - Application() = default; - -private: - std::vector> m_systems; - - std::vector> m_systems_to_be_unregistered; - - std::vector> m_systems_to_be_registered; -}; - - -} // namespace lt::app diff --git a/modules/app/public/entrypoint.hpp b/modules/app/public/entrypoint.hpp deleted file mode 100644 index 805e426..0000000 --- a/modules/app/public/entrypoint.hpp +++ /dev/null @@ -1,28 +0,0 @@ -#pragma once - -#include -#include -#include - -auto main(int argc, char *argv[]) -> int32_t -try -{ - std::ignore = argc; - std::ignore = argv; - - auto application = lt::memory::Scope {}; - application = lt::app::create_application(); - if (!application) - { - throw std::runtime_error { "Failed to create application\n" }; - } - - application->game_loop(); - return EXIT_SUCCESS; -} -catch (const std::exception &exp) -{ - lt::log::critical("Terminating due to uncaught exception:"); - lt::log::critical("\texception.what(): {}", exp.what()); - return EXIT_FAILURE; -} diff --git a/modules/app/public/system.hpp b/modules/app/system.cppm similarity index 90% rename from modules/app/public/system.hpp rename to modules/app/system.cppm index 0d0736f..885f156 100644 --- a/modules/app/public/system.hpp +++ b/modules/app/system.cppm @@ -1,14 +1,13 @@ -#pragma once - -#include -#include +export module app.system; +import logger; +import std; namespace lt::app { /** Information required to tick a system. * @note May be used across an entire application-frame (consisting of multiple systems ticking) */ -struct TickInfo +export struct TickInfo { using Timepoint_T = std::chrono::time_point; @@ -31,7 +30,7 @@ struct TickInfo }; /** Information about how a system's tick performed */ -struct TickResult +export struct TickResult { using Timepoint_T = std::chrono::time_point; @@ -47,10 +46,9 @@ struct TickResult Timepoint_T end_time; }; - -struct SystemDiagnosis +export struct SystemDiagnosis { - enum class Severity : uint8_t + enum class Severity : std::uint8_t { verbose, info, @@ -66,7 +64,7 @@ struct SystemDiagnosis Severity severity; }; -class SystemStats +export class SystemStats { public: void push_diagnosis(SystemDiagnosis &&diagnosis) @@ -85,7 +83,7 @@ private: std::vector m_diagnosis; }; -class ISystem +export class ISystem { public: ISystem() = default; diff --git a/modules/asset_baker/CMakeLists.txt b/modules/asset_baker/CMakeLists.txt index d67142d..126f652 100644 --- a/modules/asset_baker/CMakeLists.txt +++ b/modules/asset_baker/CMakeLists.txt @@ -1,6 +1,5 @@ -add_library_module(libasset_baker bakers.cpp) -target_link_libraries(libasset_baker PUBLIC assets logger lt_debug tbb) -add_test_module(libasset_baker bakers.test.cpp) +add_library_module(NAME libasset_baker INTERFACES bakers.cppm) +target_link_libraries(libasset_baker PUBLIC assets logger lt_debug) -add_executable_module(asset_baker entrypoint/baker.cpp) +add_executable(asset_baker entrypoint.cpp) target_link_libraries(asset_baker PRIVATE libasset_baker) diff --git a/modules/asset_baker/bakers.cppm b/modules/asset_baker/bakers.cppm new file mode 100644 index 0000000..59823e8 --- /dev/null +++ b/modules/asset_baker/bakers.cppm @@ -0,0 +1,68 @@ +export module bakers; + +import debug.assertions; +import assets.metadata; +import assets.shader; +import logger; +import std; + +export void bake_shader( + const std::filesystem::path &in_path, + const std::filesystem::path &out_path, + lt::assets::ShaderAsset::Type type +) +{ + using lt::assets::ShaderAsset; + using enum lt::assets::ShaderAsset::Type; + + auto glsl_path = in_path.string(); + auto spv_path = std::format("{}.spv", glsl_path); + lt::log::trace( + "Compiling {} shader {} -> {}", + type == vertex ? "vertex" : "fragment", + glsl_path, + spv_path + ); + + // Don't bother linking to shaderc, just invoke the command with a system call. + // NOLINTNEXTLINE(concurrency-mt-unsafe) + std::system( + std::format( + "glslc --target-env=vulkan1.4 -std=450core -fshader-stage={} {} -o {}", + type == vertex ? "vert" : "frag", + glsl_path, + spv_path + ) + .c_str() + ); + + auto stream = std::ifstream(spv_path, std::ios::binary); + lt::debug::ensure( + stream.is_open(), + "Failed to open compiled {} shader at: {}", + type == vertex ? "vert" : "frag", + spv_path + ); + + stream.seekg(0, std::ios::end); + const auto size = stream.tellg(); + + auto bytes = std::vector(size); + stream.seekg(0, std::ios::beg); + stream.read((char *)bytes.data(), size); // NOLINT + lt::log::debug("BYTES: {}", bytes.size()); + stream.close(); + std::filesystem::remove(spv_path); + + ShaderAsset::pack( + out_path, + lt::assets::AssetMetadata { + .version = lt::assets::current_version, + .type = ShaderAsset::asset_type_identifier, + }, + ShaderAsset::Metadata { + .type = type, + }, + std::move(bytes) + ); +} diff --git a/modules/asset_baker/private/entrypoint/baker.cpp b/modules/asset_baker/entrypoint.cpp similarity index 81% rename from modules/asset_baker/private/entrypoint/baker.cpp rename to modules/asset_baker/entrypoint.cpp index 2c0b69a..7d40afc 100644 --- a/modules/asset_baker/private/entrypoint/baker.cpp +++ b/modules/asset_baker/entrypoint.cpp @@ -1,8 +1,10 @@ -#include -#include -#include +import assets.shader; +import logger; +import bakers; +import std; -auto main(int argc, char *argv[]) -> int32_t + +auto main(int argc, char *argv[]) -> std::int32_t try { if (argc != 2) @@ -31,12 +33,12 @@ try } } - return EXIT_SUCCESS; + return 0; } catch (const std::exception &exp) { lt::log::critical("Terminating due to uncaught exception:"); lt::log::critical("\texception.what: {}:", exp.what()); - return EXIT_FAILURE; + return 1; } diff --git a/modules/asset_baker/private/bakers.test.cpp b/modules/asset_baker/private/bakers.test.cpp deleted file mode 100644 index f31ea44..0000000 --- a/modules/asset_baker/private/bakers.test.cpp +++ /dev/null @@ -1,2 +0,0 @@ -#include -#include diff --git a/modules/asset_baker/public/bakers.hpp b/modules/asset_baker/public/bakers.hpp index 7555aee..b8e40ab 100644 --- a/modules/asset_baker/public/bakers.hpp +++ b/modules/asset_baker/public/bakers.hpp @@ -1,7 +1,5 @@ #pragma once -#include -#include inline void bake_shader( const std::filesystem::path &in_path, @@ -34,7 +32,7 @@ inline void bake_shader( ); auto stream = std::ifstream(spv_path, std::ios::binary); - lt::ensure( + lt::debug::ensure( stream.is_open(), "Failed to open compiled {} shader at: {}", type == vertex ? "vert" : "frag", diff --git a/modules/assets/CMakeLists.txt b/modules/assets/CMakeLists.txt index dfd002f..5e5ac08 100644 --- a/modules/assets/CMakeLists.txt +++ b/modules/assets/CMakeLists.txt @@ -1,5 +1,3 @@ -add_library_module(assets shader.cpp) - +add_library_module(NAME assets INTERFACES shader.cppm metadata.cppm) target_link_libraries(assets PUBLIC logger lt_debug) - add_test_module(assets shader.test.cpp) diff --git a/modules/assets/public/metadata.hpp b/modules/assets/metadata.cppm similarity index 56% rename from modules/assets/public/metadata.hpp rename to modules/assets/metadata.cppm index 4dd7e6a..1c9eece 100644 --- a/modules/assets/public/metadata.hpp +++ b/modules/assets/metadata.cppm @@ -1,18 +1,19 @@ -#pragma once +export module assets.metadata; +import std; -namespace lt::assets { +export namespace lt::assets { using Type_T = std::array; -using Tag_T = uint8_t; +using Tag_T = std::uint8_t; -using Version = uint8_t; +using Version = std::uint8_t; using Blob = std::vector; constexpr auto current_version = Version { 1u }; -enum class CompressionType : uint8_t +enum class CompressionType : std::uint8_t { none, lz4, @@ -30,13 +31,13 @@ struct BlobMetadata { Tag_T tag; - size_t offset; + std::size_t offset; CompressionType compression_type; - size_t compressed_size; + std::size_t compressed_size; - size_t uncompressed_size; + std::size_t uncompressed_size; }; } // namespace lt::assets diff --git a/modules/assets/public/compressors/lz4.hpp b/modules/assets/public/compressors/lz4.hpp deleted file mode 100644 index 40a1e26..0000000 --- a/modules/assets/public/compressors/lz4.hpp +++ /dev/null @@ -1,3 +0,0 @@ -#pragma once - -// TO BE DOOO diff --git a/modules/assets/public/shader.hpp b/modules/assets/public/shader.hpp deleted file mode 100644 index c8f6061..0000000 --- a/modules/assets/public/shader.hpp +++ /dev/null @@ -1,74 +0,0 @@ -#pragma once - -#include - -namespace lt::assets { - -class ShaderAsset -{ -public: - static constexpr auto asset_type_identifier = Type_T { "SHADER_________" }; - - enum class BlobTag : Tag_T - { - code, - }; - - enum class Type : uint8_t - { - vertex, - fragment, - geometry, - compute, - }; - - struct Metadata - { - Type type; - }; - - static void pack( - const std::filesystem::path &destination, - AssetMetadata asset_metadata, - Metadata metadata, - Blob code_blob - ); - - ShaderAsset(const std::filesystem::path &path); - - void unpack_to(BlobTag tag, std::span destination) const; - - [[nodiscard]] auto unpack(BlobTag tag) const -> Blob; - - [[nodiscard]] auto get_asset_metadata() const -> const AssetMetadata & - { - return m_asset_metadata; - } - - [[nodiscard]] auto get_metadata() const -> const Metadata & - { - return m_metadata; - } - - [[nodiscard]] auto get_blob_metadata(BlobTag tag) const -> const BlobMetadata & - { - ensure( - tag == BlobTag::code, - "Invalid blob tag for shader asset: {}", - std::to_underlying(tag) - ); - - return m_code_blob_metadata; - } - -private: - AssetMetadata m_asset_metadata {}; - - Metadata m_metadata {}; - - BlobMetadata m_code_blob_metadata {}; - - mutable std::ifstream m_stream; -}; - -} // namespace lt::assets diff --git a/modules/assets/private/shader.cpp b/modules/assets/shader.cppm similarity index 67% rename from modules/assets/private/shader.cpp rename to modules/assets/shader.cppm index 0a568ef..48c4a0b 100644 --- a/modules/assets/private/shader.cpp +++ b/modules/assets/shader.cppm @@ -1,4 +1,80 @@ -#include +export module assets.shader; +import assets.metadata; +import debug.assertions; + +import std; + +export namespace lt::assets { + +class ShaderAsset +{ +public: + static constexpr auto asset_type_identifier = Type_T { "SHADER_________" }; + + enum class BlobTag : Tag_T + { + code, + }; + + enum class Type : std::uint8_t + { + vertex, + fragment, + geometry, + compute, + }; + + struct Metadata + { + Type type; + }; + + static void pack( + const std::filesystem::path &destination, + AssetMetadata asset_metadata, + Metadata metadata, + Blob code_blob + ); + + ShaderAsset(const std::filesystem::path &path); + + void unpack_to(BlobTag tag, std::span destination) const; + + [[nodiscard]] auto unpack(BlobTag tag) const -> Blob; + + [[nodiscard]] auto get_asset_metadata() const -> const AssetMetadata & + { + return m_asset_metadata; + } + + [[nodiscard]] auto get_metadata() const -> const Metadata & + { + return m_metadata; + } + + [[nodiscard]] auto get_blob_metadata(BlobTag tag) const -> const BlobMetadata & + { + debug::ensure( + tag == BlobTag::code, + "Invalid blob tag for shader asset: {}", + std::to_underlying(tag) + ); + + return m_code_blob_metadata; + } + +private: + AssetMetadata m_asset_metadata {}; + + Metadata m_metadata {}; + + BlobMetadata m_code_blob_metadata {}; + + mutable std::ifstream m_stream; +}; + +} // namespace lt::assets + namespace lt::assets { @@ -14,14 +90,14 @@ constexpr auto total_metadata_size = // ShaderAsset::ShaderAsset(const std::filesystem::path &path): m_stream(path) { - ensure(m_stream.is_open(), "Failed to open shader asset at: {}", path.string()); + debug::ensure(m_stream.is_open(), "Failed to open shader asset at: {}", path.string()); const auto read = [this](auto &field) { m_stream.read(std::bit_cast(&field), sizeof(field)); }; m_stream.seekg(0, std::ifstream::end); - const auto file_size = static_cast(m_stream.tellg()); - ensure( + const auto file_size = static_cast(m_stream.tellg()); + debug::ensure( file_size > total_metadata_size, "Failed to open shader asset at: {}, file smaller than metadata: {} < {}", path.string(), @@ -39,7 +115,7 @@ ShaderAsset::ShaderAsset(const std::filesystem::path &path): m_stream(path) read(m_code_blob_metadata.compressed_size); read(m_code_blob_metadata.uncompressed_size); - ensure( + debug::ensure( m_asset_metadata.type == asset_type_identifier, "Failed to open shader asset at: {}, incorrect asset type: {} != {}", path.string(), @@ -47,7 +123,7 @@ ShaderAsset::ShaderAsset(const std::filesystem::path &path): m_stream(path) asset_type_identifier ); - ensure( + debug::ensure( m_asset_metadata.version == current_version, "Failed to open shader asset at: {}, version mismatch: {} != {}", path.string(), @@ -55,21 +131,21 @@ ShaderAsset::ShaderAsset(const std::filesystem::path &path): m_stream(path) current_version ); - ensure( + debug::ensure( std::to_underlying(m_metadata.type) <= std::to_underlying(Type::compute), "Failed to open shader asset at: {}, invalid shader type: {}", path.string(), std::to_underlying(m_metadata.type) ); - ensure( + debug::ensure( m_code_blob_metadata.tag == std::to_underlying(BlobTag::code), "Failed to open shader asset at: {}, invalid blob tag: {}", path.string(), m_code_blob_metadata.tag ); - ensure( + debug::ensure( m_code_blob_metadata.offset + m_code_blob_metadata.compressed_size <= file_size, "Failed to open shader asset at: {}, file smaller than blob: {} > {} + {}", path.string(), @@ -99,7 +175,7 @@ ShaderAsset::ShaderAsset(const std::filesystem::path &path): m_stream(path) .uncompressed_size = code_blob.size(), }; - ensure(stream.is_open(), "Failed to pack shader asset to {}", destination.string()); + debug::ensure(stream.is_open(), "Failed to pack shader asset to {}", destination.string()); const auto write = [&stream](auto &field) { stream.write(std::bit_cast(&field), sizeof(field)); }; @@ -116,14 +192,18 @@ ShaderAsset::ShaderAsset(const std::filesystem::path &path): m_stream(path) void ShaderAsset::unpack_to(BlobTag tag, std::span destination) const { - ensure(tag == BlobTag::code, "Invalid blob tag for shader asset: {}", std::to_underlying(tag)); + debug::ensure( + tag == BlobTag::code, + "Invalid blob tag for shader asset: {}", + std::to_underlying(tag) + ); - ensure( + debug::ensure( destination.size() >= m_code_blob_metadata.uncompressed_size, "Failed to unpack shader blob {} to destination ({}) of size {} since it's smaller " "than the blobl's uncompressed size: {}", std::to_underlying(tag), - std::bit_cast(destination.data()), + std::bit_cast(destination.data()), destination.size(), m_code_blob_metadata.uncompressed_size ); @@ -137,7 +217,11 @@ void ShaderAsset::unpack_to(BlobTag tag, std::span destination) const [[nodiscard]] auto ShaderAsset::unpack(BlobTag tag) const -> Blob { - ensure(tag == BlobTag::code, "Invalid blob tag for shader asset: {}", std::to_underlying(tag)); + debug::ensure( + tag == BlobTag::code, + "Invalid blob tag for shader asset: {}", + std::to_underlying(tag) + ); auto blob = Blob(m_code_blob_metadata.uncompressed_size); unpack_to(tag, blob); diff --git a/modules/assets/private/shader.test.cpp b/modules/assets/shader.test.cpp similarity index 92% rename from modules/assets/private/shader.test.cpp rename to modules/assets/shader.test.cpp index 32ce6cb..074572b 100644 --- a/modules/assets/private/shader.test.cpp +++ b/modules/assets/shader.test.cpp @@ -1,6 +1,8 @@ -#include -#include -#include +import assets.metadata; +import assets.shader; +import test.test; +import test.expects; +import std; using ::lt::assets::AssetMetadata; using ::lt::assets::BlobMetadata; @@ -10,6 +12,7 @@ using ::lt::test::expect_eq; using ::lt::test::expect_throw; using ::lt::test::expect_true; using ::lt::test::Suite; +using ::lt::test::operator""_suite; const auto test_data_path = std::filesystem::path { "./data/test_assets" }; const auto tmp_path = std::filesystem::path { "/tmp/lt_assets_tests/" }; @@ -70,7 +73,7 @@ Suite packing = "shader_pack"_suite = [] { expect_true(stream.is_open()); stream.seekg(0, std::ios::end); - const auto file_size = static_cast(stream.tellg()); + const auto file_size = static_cast(stream.tellg()); expect_eq(file_size, expected_size); stream.close(); diff --git a/modules/bitwise/CMakeLists.txt b/modules/bitwise/CMakeLists.txt index 7e9981a..0a9b300 100644 --- a/modules/bitwise/CMakeLists.txt +++ b/modules/bitwise/CMakeLists.txt @@ -1 +1 @@ -add_library_module(bitwise) +add_library_module(NAME bitwise INTERFACES operations.cppm) diff --git a/modules/bitwise/public/operations.hpp b/modules/bitwise/operations.cppm similarity index 50% rename from modules/bitwise/public/operations.hpp rename to modules/bitwise/operations.cppm index c2c4289..965b2b5 100644 --- a/modules/bitwise/public/operations.hpp +++ b/modules/bitwise/operations.cppm @@ -1,11 +1,10 @@ -#pragma once - -#include +export module bitwise; +import std; namespace lt::bitwise { /* bit-wise */ -constexpr auto bit(uint32_t x) -> uint32_t +constexpr auto bit(std::uint32_t x) -> std::uint32_t { return 1u << x; } diff --git a/modules/camera/CMakeLists.txt b/modules/camera/CMakeLists.txt index e45b507..7ee19f6 100644 --- a/modules/camera/CMakeLists.txt +++ b/modules/camera/CMakeLists.txt @@ -1,3 +1,3 @@ -add_library_module(camera) +add_library_module(NAME camera INTERFACES components.cppm) -target_link_libraries(camera INTERFACE math) +target_link_libraries(camera PUBLIC math) diff --git a/modules/camera/public/components.hpp b/modules/camera/components.cppm similarity index 73% rename from modules/camera/public/components.hpp rename to modules/camera/components.cppm index cae4b0e..883813b 100644 --- a/modules/camera/public/components.hpp +++ b/modules/camera/components.cppm @@ -1,10 +1,9 @@ -#pragma once - -#include +export module camera.components; +import math.vec4; namespace lt::camera::components { -struct PerspectiveCamera +export struct PerspectiveCamera { float vertical_fov {}; diff --git a/modules/debug/CMakeLists.txt b/modules/debug/CMakeLists.txt index 69a5396..fe7f651 100644 --- a/modules/debug/CMakeLists.txt +++ b/modules/debug/CMakeLists.txt @@ -1,4 +1,2 @@ -add_library_module(lt_debug instrumentor.cpp) +add_library_module(NAME lt_debug INTERFACES instrumentor.cppm assertions.cppm) target_link_libraries(lt_debug PUBLIC logger) -target_precompile_headers(lt_debug PUBLIC - ${CMAKE_CURRENT_SOURCE_DIR}/private/pch.hpp) diff --git a/modules/debug/assertions.cppm b/modules/debug/assertions.cppm new file mode 100644 index 0000000..1666d10 --- /dev/null +++ b/modules/debug/assertions.cppm @@ -0,0 +1,47 @@ +export module debug.assertions; + +import std; + +namespace lt::debug { + +/////////////////////////////////////// +// ----------* INTERFACE *--------- // +///////////////////////////////////// +export template +struct ensure +{ + ensure( + const Expression_T &expression, + std::format_string fmt, + Args_T &&...args, + const std::source_location &location = std::source_location::current() + ); +}; + +export template +ensure(Expression_T, std::format_string, Args_T &&...) + -> ensure; + +/////////////////////////////////////// +// * IMPLEMENTATION -- TEMPLATES * // +///////////////////////////////////// +template +ensure::ensure( + const Expression_T &expression, + std::format_string fmt, + Args_T &&...args, + const std::source_location &location +) +{ + if (!static_cast(expression)) + { + throw std::runtime_error { std::format( + "exception: {}\nlocation: {}:{}", + std::format(fmt, std::forward(args)...), + location.file_name(), + location.line() + ) }; + } +} + +} // namespace lt::debug diff --git a/modules/debug/private/instrumentor.cpp b/modules/debug/instrumentor.cppm similarity index 51% rename from modules/debug/private/instrumentor.cpp rename to modules/debug/instrumentor.cppm index 966a829..0f946df 100644 --- a/modules/debug/private/instrumentor.cpp +++ b/modules/debug/instrumentor.cppm @@ -1,7 +1,83 @@ -#include -#include +export module debug.instrumentor; -namespace lt { +import std; +import logger; + +namespace lt::debug { + +struct ScopeProfileResult +{ + std::string name; + long long start, duration; + std::uint32_t threadID; +}; + +class Instrumentor +{ +public: + static auto instance() -> Instrumentor & + { + static auto instance = Instrumentor {}; + return instance; + } + + static void begin_session(const std::string &outputPath) + { + instance().begin_session_impl(outputPath); + } + static void end_session() + { + instance().end_session_impl(); + } + + static void submit_scope_profile(const ScopeProfileResult &profileResult) + { + instance().submit_scope_profile_impl(profileResult); + } + +private: + std::ofstream m_output_file_stream; + + unsigned int m_current_session_count { 0u }; + + Instrumentor() = default; + + void begin_session_impl(const std::string &outputPath); + + void end_session_impl(); + + void submit_scope_profile_impl(const ScopeProfileResult &profileResult); +}; + +class InstrumentorTimer +{ +public: + InstrumentorTimer(const std::string &scopeName); + + ~InstrumentorTimer(); + +private: + ScopeProfileResult m_result; + + std::chrono::time_point m_start; +}; + +} // namespace lt::debug + +/* scope */ +#define lt_profile_scope(name) lt_profile_scope_no_redifinition(name, __LINE__) +#define lt_profile_scope_no_redifinition(name, line) lt_profile_scope_no_redifinition2(name, line) +#define lt_profile_scope_no_redifinition2(name, line) InstrumentorTimer timer##line(name) + +/* function */ +#define LT_PROFILE_FUNCTION lt_profile_scope(__FUNCSIG__) + +/* session */ +#define lt_profile_begin_session(outputPath) ::lt::Instrumentor::begin_session(outputPath) +#define lt_profile_end_session() ::lt::Instrumentor::end_session() + +module :private; +using namespace lt::debug; void Instrumentor::begin_session_impl(const std::string &outputPath) { @@ -67,5 +143,3 @@ InstrumentorTimer::~InstrumentorTimer() Instrumentor::submit_scope_profile(m_result); } - -} // namespace lt diff --git a/modules/debug/private/pch.hpp b/modules/debug/private/pch.hpp deleted file mode 100644 index 68fff38..0000000 --- a/modules/debug/private/pch.hpp +++ /dev/null @@ -1,3 +0,0 @@ -#pragma once - -#include diff --git a/modules/debug/public/assertions.hpp b/modules/debug/public/assertions.hpp deleted file mode 100644 index 514a8c5..0000000 --- a/modules/debug/public/assertions.hpp +++ /dev/null @@ -1,34 +0,0 @@ -#pragma once - -#include -#include - -namespace lt { - -template -struct ensure -{ - ensure( - const Expression_T &expression, - std::format_string fmt, - Args_T &&...args, - const std::source_location &location = std::source_location::current() - ) - { - if (!static_cast(expression)) - { - throw std::runtime_error { std::format( - "exception: {}\nlocation: {}:{}", - std::format(fmt, std::forward(args)...), - location.file_name(), - location.line() - ) }; - } - } -}; - -template -ensure(Expression_T, std::format_string, Args_T &&...) - -> ensure; - -} // namespace lt diff --git a/modules/debug/public/instrumentor.hpp b/modules/debug/public/instrumentor.hpp deleted file mode 100644 index 9820a9d..0000000 --- a/modules/debug/public/instrumentor.hpp +++ /dev/null @@ -1,77 +0,0 @@ -#pragma once - -#include -#include - -namespace lt { - -struct ScopeProfileResult -{ - std::string name; - long long start, duration; - uint32_t threadID; -}; - -class Instrumentor -{ -public: - static auto instance() -> Instrumentor & - { - static auto instance = Instrumentor {}; - return instance; - } - - static void begin_session(const std::string &outputPath) - { - instance().begin_session_impl(outputPath); - } - static void end_session() - { - instance().end_session_impl(); - } - - static void submit_scope_profile(const ScopeProfileResult &profileResult) - { - instance().submit_scope_profile_impl(profileResult); - } - -private: - std::ofstream m_output_file_stream; - - unsigned int m_current_session_count { 0u }; - - Instrumentor() = default; - - void begin_session_impl(const std::string &outputPath); - - void end_session_impl(); - - void submit_scope_profile_impl(const ScopeProfileResult &profileResult); -}; - -class InstrumentorTimer -{ -public: - InstrumentorTimer(const std::string &scopeName); - - ~InstrumentorTimer(); - -private: - ScopeProfileResult m_result; - - std::chrono::time_point m_start; -}; - -} // namespace lt - -/* scope */ -#define lt_profile_scope(name) lt_profile_scope_no_redifinition(name, __LINE__) -#define lt_profile_scope_no_redifinition(name, line) lt_profile_scope_no_redifinition2(name, line) -#define lt_profile_scope_no_redifinition2(name, line) InstrumentorTimer timer##line(name) - -/* function */ -#define LT_PROFILE_FUNCTION lt_profile_scope(__FUNCSIG__) - -/* session */ -#define lt_profile_begin_session(outputPath) ::lt::Instrumentor::begin_session(outputPath) -#define lt_profile_end_session() ::lt::Instrumentor::end_session() diff --git a/modules/ecs/CMakeLists.txt b/modules/ecs/CMakeLists.txt index 312dd4b..c0d5944 100644 --- a/modules/ecs/CMakeLists.txt +++ b/modules/ecs/CMakeLists.txt @@ -1,4 +1,5 @@ -add_library_module(ecs sparse_set.cpp) +add_library_module(NAME ecs INTERFACES sparse_set.cppm registry.cppm + entity.cppm) target_link_libraries(ecs PUBLIC logger lt_debug memory) add_test_module(ecs sparse_set.test.cpp registry.test.cpp) diff --git a/modules/ecs/public/entity.hpp b/modules/ecs/entity.cppm similarity index 79% rename from modules/ecs/public/entity.hpp rename to modules/ecs/entity.cppm index 9fdfda5..7d85808 100644 --- a/modules/ecs/public/entity.hpp +++ b/modules/ecs/entity.cppm @@ -1,19 +1,20 @@ -#pragma once - -#include -#include +export module ecs.entity; +import debug.assertions; +import memory.reference; +import ecs.registry; +import std; namespace lt::ecs { /** High-level entity convenience wrapper */ -class Entity +export class Entity { public: Entity(memory::Ref registry, EntityId identifier) : m_registry(std::move(registry)) , m_identifier(identifier) { - ensure(m_registry, "Failed to create Entity ({}): null registry", m_identifier); + debug::ensure(m_registry, "Failed to create Entity ({}): null registry", m_identifier); } template diff --git a/modules/ecs/public/registry.hpp b/modules/ecs/registry.cppm similarity index 90% rename from modules/ecs/public/registry.hpp rename to modules/ecs/registry.cppm index 7d7ca4b..1784352 100644 --- a/modules/ecs/public/registry.hpp +++ b/modules/ecs/registry.cppm @@ -1,13 +1,14 @@ -#pragma once - -#include -#include +export module ecs.registry; +import debug.assertions; +import ecs.sparse_set; +import memory.scope; +import std; namespace lt::ecs { -using EntityId = uint32_t; +export using EntityId = std::uint32_t; -constexpr auto null_entity = std::numeric_limits::max(); +export constexpr auto null_entity = std::numeric_limits::max(); /** A registry of components, the heart of an ECS architecture. * @@ -22,7 +23,7 @@ constexpr auto null_entity = std::numeric_limits::max(); * @ref https://github.com/skypjack/entt * @ref https://github.com/SanderMertens/flecs */ -class Registry +export class Registry { public: using UnderlyingSparseSet_T = TypeErasedSparseSet; @@ -189,25 +190,25 @@ public: } }; - [[nodiscard]] auto get_entity_count() const -> size_t + [[nodiscard]] auto get_entity_count() const -> std::size_t { - return static_cast(m_entity_count); + return static_cast(m_entity_count); } private: - using TypeId = size_t; + using TypeId = std::size_t; static consteval auto hash_cstr(const char *str) -> TypeId { - constexpr auto fnv_offset_basis = size_t { 14695981039346656037ull }; - constexpr auto fnv_prime = size_t { 1099511628211ull }; + constexpr auto fnv_offset_basis = std::size_t { 14695981039346656037ull }; + constexpr auto fnv_prime = std::size_t { 1099511628211ull }; auto hash = fnv_offset_basis; for (const auto &ch : std::string_view { str }) { hash *= fnv_prime; - hash ^= static_cast(ch); + hash ^= static_cast(ch); } return hash; @@ -241,7 +242,7 @@ private: auto *base_set = m_sparsed_sets[type_id].get(); auto *derived_set = dynamic_cast *>(base_set); - ensure(derived_set, "Failed to downcast to derived set"); + debug::ensure(derived_set, "Failed to downcast to derived set"); return *derived_set; } diff --git a/modules/ecs/private/registry.test.cpp b/modules/ecs/registry.test.cpp similarity index 96% rename from modules/ecs/private/registry.test.cpp rename to modules/ecs/registry.test.cpp index e9c380a..631fed9 100644 --- a/modules/ecs/private/registry.test.cpp +++ b/modules/ecs/registry.test.cpp @@ -1,19 +1,17 @@ -#include -#include -#include -#include +import ecs.registry; +import test.test; +import test.expects; +import std; -using lt::test::Case; -using lt::test::expect_unreachable; -using lt::test::Suite; - -using lt::test::expect_eq; - -using lt::test::expect_false; -using lt::test::expect_true; - -using lt::ecs::EntityId; -using lt::ecs::Registry; +using ::lt::ecs::EntityId; +using ::lt::ecs::Registry; +using ::lt::test::Case; +using ::lt::test::expect_eq; +using ::lt::test::expect_false; +using ::lt::test::expect_true; +using ::lt::test::expect_unreachable; +using ::lt::test::Suite; +using ::lt::test::operator""_suite; struct Component { diff --git a/modules/ecs/public/sparse_set.hpp b/modules/ecs/sparse_set.cppm similarity index 85% rename from modules/ecs/public/sparse_set.hpp rename to modules/ecs/sparse_set.cppm index 05a5265..340a760 100644 --- a/modules/ecs/public/sparse_set.hpp +++ b/modules/ecs/sparse_set.cppm @@ -1,12 +1,13 @@ -#pragma once +export module ecs.sparse_set; +import debug.assertions; +import std; namespace lt::ecs { /** - * * @ref https://programmingpraxis.com/2012/03/09/sparse-sets/ */ -template +export template class TypeErasedSparseSet { public: @@ -25,19 +26,19 @@ public: virtual void remove(Identifier_T identifier) = 0; }; -template +export template class SparseSet: public TypeErasedSparseSet { public: using Dense_T = std::pair; - static constexpr auto max_capacity = size_t { 1'000'000 }; + static constexpr auto max_capacity = std::size_t { 1'000'000 }; static constexpr auto null_identifier = std::numeric_limits().max(); - explicit SparseSet(size_t initial_capacity = 1) + explicit SparseSet(std::size_t initial_capacity = 1) { - ensure( + debug::ensure( initial_capacity <= max_capacity, "Failed to create SparseSet: capacity too large ({} > {})", initial_capacity, @@ -52,7 +53,10 @@ public: { if (m_sparse.size() < identifier + 1) { - auto new_capacity = std::max(static_cast(identifier + 1), m_sparse.size() * 2); + auto new_capacity = std::max( + static_cast(identifier + 1), + m_sparse.size() * 2 + ); new_capacity = std::min(new_capacity, max_capacity); // log::debug("Increasing sparse vector size:", m_dead_count); @@ -145,12 +149,12 @@ public: return std::forward(self).m_dense[std::forward(self).m_sparse[identifier]]; } - [[nodiscard]] auto get_size() const noexcept -> size_t + [[nodiscard]] auto get_size() const noexcept -> std::size_t { return m_alive_count; } - [[nodiscard]] auto get_capacity() const noexcept -> size_t + [[nodiscard]] auto get_capacity() const noexcept -> std::size_t { return m_sparse.capacity(); } @@ -165,9 +169,9 @@ private: std::vector m_sparse; - size_t m_alive_count {}; + std::size_t m_alive_count {}; - size_t m_dead_count {}; + std::size_t m_dead_count {}; }; } // namespace lt::ecs diff --git a/modules/ecs/private/sparse_set.test.cpp b/modules/ecs/sparse_set.test.cpp similarity index 91% rename from modules/ecs/private/sparse_set.test.cpp rename to modules/ecs/sparse_set.test.cpp index 6016d99..baf9fec 100644 --- a/modules/ecs/private/sparse_set.test.cpp +++ b/modules/ecs/sparse_set.test.cpp @@ -1,16 +1,16 @@ -#include -#include -#include -#include +import ecs.sparse_set; +import test.test; +import test.expects; +import std; -using lt::test::Case; -using lt::test::Suite; - -using lt::test::expect_eq; -using lt::test::expect_false; -using lt::test::expect_ne; -using lt::test::expect_throw; -using lt::test::expect_true; +using ::lt::test::Case; +using ::lt::test::expect_eq; +using ::lt::test::expect_false; +using ::lt::test::expect_ne; +using ::lt::test::expect_throw; +using ::lt::test::expect_true; +using ::lt::test::Suite; +using ::lt::test::operator""_suite; using Set = lt::ecs::SparseSet; constexpr auto capacity = 100; diff --git a/modules/env/CMakeLists.txt b/modules/env/CMakeLists.txt index a29a773..4dfdd37 100644 --- a/modules/env/CMakeLists.txt +++ b/modules/env/CMakeLists.txt @@ -1 +1 @@ -add_library_module(env) +add_library_module(NAME env INTERFACES constants.cppm) diff --git a/modules/env/public/constants.hpp b/modules/env/constants.cppm similarity index 92% rename from modules/env/public/constants.hpp rename to modules/env/constants.cppm index 22dc134..8c1b40f 100644 --- a/modules/env/public/constants.hpp +++ b/modules/env/constants.cppm @@ -1,8 +1,10 @@ -#pragma once +export module env; + +import std; namespace lt { -enum class Platform : uint8_t +enum class Platform : std::uint8_t { /** The GNU/Linux platform. * Tested on the following distros: arch-x86_64 @@ -24,7 +26,7 @@ enum class Platform : uint8_t }; /** The compiler that was used for compiling the project. */ -enum class Compiler : uint8_t +enum class Compiler : std::uint8_t { clang, gcc, diff --git a/modules/input/CMakeLists.txt b/modules/input/CMakeLists.txt index 700fc41..34947be 100644 --- a/modules/input/CMakeLists.txt +++ b/modules/input/CMakeLists.txt @@ -1,4 +1,4 @@ -add_library_module(input system.cpp) +add_library_module(NAME input INTERFACES system.cpp) target_link_libraries(input PUBLIC surface math logger tbb) add_test_module(input system.test.cpp) diff --git a/modules/input/public/key_codes.hpp b/modules/input/codes.cppm similarity index 91% rename from modules/input/public/key_codes.hpp rename to modules/input/codes.cppm index 0b91a56..6b3993f 100644 --- a/modules/input/public/key_codes.hpp +++ b/modules/input/codes.cppm @@ -2,7 +2,6 @@ #include -namespace lt::Key { enum : uint16_t { @@ -177,4 +176,21 @@ enum : uint16_t }; -} + +enum : uint8_t +{ + Button1 = 0, + Button2 = 1, + Button3 = 2, + Button4 = 3, + Button5 = 4, + Button6 = 5, + Button7 = 6, + Button8 = 7, + + LButton = Button1, + RButton = Button2, + MButton = Button3, +}; + +} // namespace lt::Key diff --git a/modules/input/public/components.hpp b/modules/input/components.cppm similarity index 95% rename from modules/input/public/components.hpp rename to modules/input/components.cppm index fb4d94b..e79a62e 100644 --- a/modules/input/public/components.hpp +++ b/modules/input/components.cppm @@ -1,4 +1,4 @@ -#pragma once +export module input.components; #include diff --git a/modules/input/public/events.hpp b/modules/input/events.cppm similarity index 100% rename from modules/input/public/events.hpp rename to modules/input/events.cppm diff --git a/modules/asset_baker/private/bakers.cpp b/modules/input/mouse_codes.cppm similarity index 100% rename from modules/asset_baker/private/bakers.cpp rename to modules/input/mouse_codes.cppm diff --git a/modules/input/public/mouse_codes.hpp b/modules/input/public/mouse_codes.hpp deleted file mode 100644 index a4e0a26..0000000 --- a/modules/input/public/mouse_codes.hpp +++ /dev/null @@ -1,23 +0,0 @@ -#pragma once - -#include - -namespace lt::Mouse { - -enum : uint8_t -{ - Button1 = 0, - Button2 = 1, - Button3 = 2, - Button4 = 3, - Button5 = 4, - Button6 = 5, - Button7 = 6, - Button8 = 7, - - LButton = Button1, - RButton = Button2, - MButton = Button3, -}; - -} diff --git a/modules/input/public/system.hpp b/modules/input/public/system.hpp deleted file mode 100644 index 61b77d7..0000000 --- a/modules/input/public/system.hpp +++ /dev/null @@ -1,55 +0,0 @@ -#pragma once - -#include -#include -#include -#include -#include -#include - -namespace lt::input { - -class System: public app::ISystem -{ -public: - System(memory::Ref registry); - - void tick(app::TickInfo tick) override; - - void on_register() override; - - void on_unregister() override; - - [[nodiscard]] auto get_last_tick_result() const -> const app::TickResult & override - { - return m_last_tick_result; - } - -private: - void handle_event(const surface::SurfaceComponent::Event &event); - - void on_surface_lost_focus(); - - void on_key_press(const lt::surface::KeyPressedEvent &event); - - void on_key_release(const lt::surface::KeyReleasedEvent &event); - - void on_pointer_move(const lt::surface::MouseMovedEvent &event); - - void on_button_press(const lt::surface::ButtonPressedEvent &event); - - void on_button_release(const lt::surface::ButtonReleasedEvent &event); - - memory::Ref m_registry; - - std::array m_keys {}; - - std::array m_buttons {}; - - math::vec2 m_pointer_position; - - app::TickResult m_last_tick_result {}; -}; - - -} // namespace lt::input diff --git a/modules/input/private/system.cpp b/modules/input/system.cppm similarity index 73% rename from modules/input/private/system.cpp rename to modules/input/system.cppm index b514762..719699c 100644 --- a/modules/input/private/system.cpp +++ b/modules/input/system.cppm @@ -1,3 +1,62 @@ +#pragma once + +#include +#include +#include +#include +#include +#include + +namespace lt::input { + +class System: public app::ISystem +{ +public: + System(memory::Ref registry); + + void tick(app::TickInfo tick) override; + + void on_register() override; + + void on_unregister() override; + + [[nodiscard]] auto get_last_tick_result() const -> const app::TickResult & override + { + return m_last_tick_result; + } + +private: + void handle_event(const surface::SurfaceComponent::Event &event); + + void on_surface_lost_focus(); + + void on_key_press(const lt::surface::KeyPressedEvent &event); + + void on_key_release(const lt::surface::KeyReleasedEvent &event); + + void on_pointer_move(const lt::surface::MouseMovedEvent &event); + + void on_button_press(const lt::surface::ButtonPressedEvent &event); + + void on_button_release(const lt::surface::ButtonReleasedEvent &event); + + memory::Ref m_registry; + + std::array m_keys {}; + + std::array m_buttons {}; + + math::vec2 m_pointer_position; + + app::TickResult m_last_tick_result {}; +}; + + +} // namespace lt::input + + +module :private; + #include -#include -#include -#include -#include - -//============================================================ -// Algorithms and Iterators -//============================================================ -#include -#include -#include -#include - -//============================================================ -// Strings and Localization -//============================================================ -#include -#include -#include -#include -#include - -//============================================================ -// Memory Management and Smart Pointers -//============================================================ -#include -#include -#include -#include - -//============================================================ -// Utility and Miscellaneous -//============================================================ -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -//============================================================ -// Concurrency and Multithreading -//============================================================ -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -//============================================================ -// Random Numbers and Numeric Limits -//============================================================ -#include -#include -#include -#include -#include - -//============================================================ -// Regular Expressions -//============================================================ -#include - -//============================================================ -// Error Handling and Diagnostics -//============================================================ -#include -#include -#include -#include -#include -#include - -//============================================================ -// C++20/23 Additions -//============================================================ -#include // C++20 bit operations -#include // C++20 three-way comparison -#include // C++23 std::expected (if supported) -#include // C++20 formatting -#include // C++23 print functions -#include // C++20 ranges library -#include // C++20 span (repeated intentionally for clarity) -// #include // C++23 stack tracing utilities // Not supported yet -#include // C++20 synchronized output streams -// NOLINTEND diff --git a/modules/surface/CMakeLists.txt b/modules/surface/CMakeLists.txt index af5c54d..b349396 100644 --- a/modules/surface/CMakeLists.txt +++ b/modules/surface/CMakeLists.txt @@ -1,9 +1,29 @@ if(NOT WIN32) - add_library_module(surface linux/system.cpp) + add_library_module( + NAME + surface + INTERFACES + system.cppm + requests.cppm + events.cppm + components.cppm + SOURCES + platform_linux.cpp) target_link_libraries(surface PRIVATE X11) else(WIN32) - add_library_module(surface windows/system.cpp) + add_library_module( + NAME + surface + INTERFACES + system.cppm + requests.cppm + system.cppm + requests.cppm + events.cppm + components.cppm + SOURCES + platform_windows.cpp) endif() @@ -13,4 +33,5 @@ target_link_libraries( PRIVATE logger lt_debug time) add_test_module(surface system.test.cpp) -add_fuzz_module(surface system.fuzz.cpp) + +# add_fuzz_module(surface system.fuzz.cpp) diff --git a/modules/surface/public/components.hpp b/modules/surface/components.cppm similarity index 87% rename from modules/surface/public/components.hpp rename to modules/surface/components.cppm index 3c231bc..0bffa16 100644 --- a/modules/surface/public/components.hpp +++ b/modules/surface/components.cppm @@ -1,40 +1,33 @@ -#pragma once - -#include -#include -#include -#include -#include -#include - +module; #ifdef LIGHT_PLATFORM_LINUX typedef struct _XDisplay Display; #endif +export module surface.system:components; +import std; +import math.vec2; +import surface.events; +import surface.requests; + namespace lt::surface { /** Represents a platform's surface (eg. a Window). * * @note This is a "system component" */ -class SurfaceComponent +export class SurfaceComponent { public: friend class System; using Event = std::variant< - // surface events ClosedEvent, MovedEvent, ResizedEvent, LostFocusEvent, GainFocusEvent, - - // keyboard events KeyPressedEvent, KeyReleasedEvent, - - // mouse events MouseMovedEvent, ButtonPressedEvent, ButtonReleasedEvent>; @@ -49,7 +42,7 @@ public: struct NativeData { Display *display; - uint32_t window; + std::uint32_t window; unsigned long wm_delete_message; }; #endif diff --git a/modules/surface/events.cppm b/modules/surface/events.cppm new file mode 100644 index 0000000..e4cf60a --- /dev/null +++ b/modules/surface/events.cppm @@ -0,0 +1,260 @@ +export module surface.events; +import math.vec2; +import std; + +export namespace lt::surface { + +class KeyPressedEvent +{ +public: + KeyPressedEvent(std::uint32_t key): m_key(key) + { + } + + [[nodiscard]] auto get_key() const -> std::uint32_t + { + return m_key; + } + + [[nodiscard]] auto to_string() const -> std::string + { + return std::format("KeyPressed: {}", m_key); + } + +private: + std::uint32_t m_key; +}; + +class KeyRepeatEvent +{ +public: + KeyRepeatEvent(std::int32_t key): m_key(key) + { + } + + [[nodiscard]] auto get_key() const -> std::uint32_t + { + return m_key; + } + + [[nodiscard]] auto to_string() const -> std::string + { + return std::format("KeyRepeated: {}", m_key); + } + +private: + std::uint32_t m_key; +}; + +class KeyReleasedEvent +{ +public: + KeyReleasedEvent(std::uint32_t key): m_key(key) + { + } + + [[nodiscard]] auto get_key() const -> std::uint32_t + { + return m_key; + } + + [[nodiscard]] auto to_string() const -> std::string + { + return std::format("KeyReleased: {}", m_key); + } + +private: + std::uint32_t m_key; +}; + +class KeySetCharEvent +{ +public: + KeySetCharEvent(std::uint32_t character): m_character(character) + { + } + + [[nodiscard]] auto get_character() const -> std::uint32_t + { + return m_character; + } + + [[nodiscard]] auto to_string() const -> std::string + { + return std::format("KeyCharSet: {}", m_character); + } + +private: + std::uint32_t m_character; +}; + +class MouseMovedEvent +{ +public: + MouseMovedEvent(float x, float y): m_position(x, y) + { + } + + [[nodiscard]] auto get_position() const -> const math::vec2 & + { + return m_position; + } + + [[nodiscard]] auto get_x() const -> float + { + return m_position.x; + } + + [[nodiscard]] auto get_y() const -> float + { + return m_position.y; + } + + [[nodiscard]] auto to_string() const -> std::string + { + return std::format("MouseMoved: {}, {}", m_position.x, m_position.y); + } + +private: + math::vec2 m_position; +}; + +class WheelScrolledEvent +{ +public: + WheelScrolledEvent(float offset): m_offset(offset) + { + } + + [[nodiscard]] auto get_offset() const -> float + { + return m_offset; + } + + [[nodiscard]] auto to_string() const -> std::string + { + std::stringstream ss; + ss << "WheelScrolled: " << m_offset; + return ss.str(); + } + +private: + float m_offset; +}; + +class ButtonPressedEvent +{ +public: + ButtonPressedEvent(std::int32_t button): m_button(button) + { + } + + [[nodiscard]] auto get_button() const -> std::int32_t + { + return m_button; + } + + [[nodiscard]] auto to_string() const -> std::string + { + return std::format("ButtonPressed: {}", m_button); + } + +private: + std::int32_t m_button; +}; + +class ButtonReleasedEvent +{ +public: + ButtonReleasedEvent(std::int32_t button): m_button(button) + { + } + + [[nodiscard]] auto get_button() const -> std::int32_t + { + return m_button; + } + + [[nodiscard]] auto to_string() const -> std::string + { + return std::format("ButtonReleased: {}", m_button); + } + +private: + std::int32_t m_button; +}; + +class ClosedEvent +{ +public: + [[nodiscard]] auto to_string() const -> std::string_view + { + return "SurfaceClosedEvent"; + } +}; + +class MovedEvent +{ +public: + MovedEvent(std::int32_t x, std::int32_t y): m_position(x, y) + { + } + + [[nodiscard]] auto get_position() const -> const math::ivec2 & + { + return m_position; + } + + [[nodiscard]] auto to_string() const -> std::string + { + auto stream = std::stringstream {}; + stream << "WindwoMoved: " << m_position.x << ", " << m_position.y; + return stream.str(); + } + +private: + math::ivec2 m_position; +}; + +class ResizedEvent +{ +public: + ResizedEvent(std::uint32_t width, std::uint32_t height): m_size(width, height) + { + } + + [[nodiscard]] auto get_size() const -> const math::uvec2 & + { + return m_size; + } + + [[nodiscard]] auto to_string() const -> std::string + { + auto stream = std::stringstream {}; + stream << "SurfaceResized: " << m_size.x << ", " << m_size.y; + return stream.str(); + } + +private: + math::uvec2 m_size; +}; + +class LostFocusEvent +{ +public: + [[nodiscard]] auto to_string() const -> std::string_view + { + return "SurfaceLostFocus"; + } +}; + +class GainFocusEvent +{ +public: + [[nodiscard]] auto to_string() const -> std::string_view + { + return "SurfaceGainFocus"; + } +}; + +} // namespace lt::surface diff --git a/modules/surface/private/linux/system.cpp b/modules/surface/platform_linux.cpp similarity index 91% rename from modules/surface/private/linux/system.cpp rename to modules/surface/platform_linux.cpp index 5a9dde3..946908a 100644 --- a/modules/surface/private/linux/system.cpp +++ b/modules/surface/platform_linux.cpp @@ -1,17 +1,18 @@ -#include -#include -#include -#include -#include -#include