From 4e52b9831bdcddf55ce28196a9a12acf8a603b26 Mon Sep 17 00:00:00 2001 From: Matt Jones Date: Mon, 16 May 2022 20:31:31 +0100 Subject: [PATCH 1/3] Narrative ECS skeleton. --- include/NovelRT/Ecs/Configurator.h | 6 +++ include/NovelRT/Ecs/Ecs.h | 1 + .../Ecs/Narrative/CharacterInformation.h | 39 +++++++++++++++++++ .../DefaultNarrativeComponentTypes.h | 39 +++++++++++++++++++ include/NovelRT/Ecs/Narrative/Ecs.Narrative.h | 26 +++++++++++++ .../Ecs/Narrative/NarrativePlayerState.h | 23 +++++++++++ .../Ecs/Narrative/NarrativePlayerSystem.h | 32 +++++++++++++++ .../Desktop/DesktopResourceLoader.h | 1 + .../ResourceManagement/ResourceLoader.h | 7 ++++ src/NovelRT/CMakeLists.txt | 1 + .../Ecs/Narrative/NarrativePlayerSystem.cpp | 16 ++++++++ .../Desktop/DesktopResourceLoader.cpp | 12 ++++++ 12 files changed, 203 insertions(+) create mode 100644 include/NovelRT/Ecs/Narrative/CharacterInformation.h create mode 100644 include/NovelRT/Ecs/Narrative/DefaultNarrativeComponentTypes.h create mode 100644 include/NovelRT/Ecs/Narrative/Ecs.Narrative.h create mode 100644 include/NovelRT/Ecs/Narrative/NarrativePlayerState.h create mode 100644 include/NovelRT/Ecs/Narrative/NarrativePlayerSystem.h create mode 100644 src/NovelRT/Ecs/Narrative/NarrativePlayerSystem.cpp diff --git a/include/NovelRT/Ecs/Configurator.h b/include/NovelRT/Ecs/Configurator.h index fe33e72a9..aa209de16 100644 --- a/include/NovelRT/Ecs/Configurator.h +++ b/include/NovelRT/Ecs/Configurator.h @@ -51,8 +51,14 @@ namespace NovelRT::Ecs Input::InputEventComponent{0, NovelRT::Input::KeyState::Idle, 0, 0}, "NovelRT::Ecs::Input::InputEventComponent"); + // You can register additional components here. - Matt + target.GetComponentCache().RegisterComponentType( + Narrative::NarrativePlayerStateComponent{Narrative::NarrativePlayerState::RequestDestroy,0, 0}, "NovelRT::Ecs::Narrative::NarrativePlayerStateComponent"); + target.RegisterSystem( std::make_shared(_windowingPluginProvider, _inputPluginProvider)); + + target.RegisterSystem(std::make_shared()); } public: diff --git a/include/NovelRT/Ecs/Ecs.h b/include/NovelRT/Ecs/Ecs.h index c9b92a5f2..bf72191c6 100644 --- a/include/NovelRT/Ecs/Ecs.h +++ b/include/NovelRT/Ecs/Ecs.h @@ -82,6 +82,7 @@ namespace NovelRT::Ecs #include "Graphics/Ecs.Graphics.h" #include "Audio/Ecs.Audio.h" #include "Input/Ecs.Input.h" +#include "Narrative/Ecs.Narrative.h" #include "Configurator.h" #include "LinkedEntityListView.h" #include "EntityGraphView.h" diff --git a/include/NovelRT/Ecs/Narrative/CharacterInformation.h b/include/NovelRT/Ecs/Narrative/CharacterInformation.h new file mode 100644 index 000000000..d6e1395de --- /dev/null +++ b/include/NovelRT/Ecs/Narrative/CharacterInformation.h @@ -0,0 +1,39 @@ +#include + +// Copyright © Matt Jones and Contributors. Licensed under the MIT Licence (MIT). See LICENCE.md in the repository root +// for more information. + +#ifndef NOVELRT_CHARACTERINFORMATION_H +#define NOVELRT_CHARACTERINFORMATION_H + +#ifndef NOVELRT_ECS_H +#error NovelRT does not support including types explicitly by default. Please include Ecs.h instead for the Ecs namespace subset. +#endif + +namespace NovelRT::Ecs::Narrative +{ + // This type currently does not have a CPP file due to its simplicity. Feel free to add one if you end up writing logic that shouldn't be inlined. + class CharacterInformation + { + private: + Atom _characterId; + std::string _name; + + public: + CharacterInformation(Atom characterId, std::string name) noexcept : _characterId(characterId), _name(std::move(name)) + { + } + + [[nodiscard]] inline Atom GetCharacterId() const noexcept + { + return _characterId; + } + + [[nodiscard]] const std::string& GetName() const noexcept + { + return _name; + } + }; +} + +#endif // NOVELRT_CHARACTERINFORMATION_H diff --git a/include/NovelRT/Ecs/Narrative/DefaultNarrativeComponentTypes.h b/include/NovelRT/Ecs/Narrative/DefaultNarrativeComponentTypes.h new file mode 100644 index 000000000..4d5652b0a --- /dev/null +++ b/include/NovelRT/Ecs/Narrative/DefaultNarrativeComponentTypes.h @@ -0,0 +1,39 @@ +// Copyright © Matt Jones and Contributors. Licensed under the MIT Licence (MIT). See LICENCE.md in the repository root +// for more information. + +#ifndef NOVELRT_ECS_NARRATIVE_DEFAULTNARRATIVECOMPONENTTYPES_H +#define NOVELRT_ECS_NARRATIVE_DEFAULTNARRATIVECOMPONENTTYPES_H + +#ifndef NOVELRT_ECS_H +#error NovelRT does not support including types explicitly by default. Please include Ecs.h instead for the Ecs namespace subset. +#endif + +namespace NovelRT::Ecs::Narrative +{ + // I couldn't think of any other component types we might need, so for now this is all we got. - Matt + struct NarrativePlayerStateComponent + { + NarrativePlayerState currentState = NarrativePlayerState::Idle; + Atom sectionId = 0; + Atom characterId = 0; + + inline NarrativePlayerStateComponent& operator+=(const NarrativePlayerStateComponent& other) + { + currentState = other.currentState; + sectionId = other.sectionId; + characterId = other.characterId; + } + + inline bool operator==(const NarrativePlayerStateComponent& other) const noexcept + { + return currentState == other.currentState && sectionId == other.sectionId && characterId == other.characterId; + } + + inline bool operator!=(const NarrativePlayerStateComponent& other) const noexcept + { + return !(*this == other); + } + }; +} + +#endif // NOVELRT_ECS_NARRATIVE_DEFAULTNARRATIVECOMPONENTTYPES_H diff --git a/include/NovelRT/Ecs/Narrative/Ecs.Narrative.h b/include/NovelRT/Ecs/Narrative/Ecs.Narrative.h new file mode 100644 index 000000000..1427648e3 --- /dev/null +++ b/include/NovelRT/Ecs/Narrative/Ecs.Narrative.h @@ -0,0 +1,26 @@ +// Copyright © Matt Jones and Contributors. Licensed under the MIT Licence (MIT). See LICENCE.md in the repository root +// for more information. + +#ifndef NOVELRT_ECS_NARRATIVE_H +#define NOVELRT_ECS_NARRATIVE_H + +#ifndef NOVELRT_ECS_H +#error NovelRT does not support including types explicitly by default. Please include Ecs.h instead for the Ecs namespace subset. +#endif + +namespace NovelRT::Ecs::Narrative +{ + enum class NarrativePlayerState : uint32_t; + struct NarrativePlayerStateComponent; + class NarrativePlayerSystem; + class CharacterInformation; +} + +// clang-format off +#include "NarrativePlayerState.h" +#include "DefaultNarrativeComponentTypes.h" +#include "NarrativePlayerSystem.h" +#include "CharacterInformation.h" +// clang-format on + +#endif // NOVELRT_ECS_NARRATIVE_H diff --git a/include/NovelRT/Ecs/Narrative/NarrativePlayerState.h b/include/NovelRT/Ecs/Narrative/NarrativePlayerState.h new file mode 100644 index 000000000..fb84a1b47 --- /dev/null +++ b/include/NovelRT/Ecs/Narrative/NarrativePlayerState.h @@ -0,0 +1,23 @@ +// Copyright © Matt Jones and Contributors. Licensed under the MIT Licence (MIT). See LICENCE.md in the repository root +// for more information. + +#ifndef NOVELRT_NARRATIVEPLAYERSTATE_H +#define NOVELRT_NARRATIVEPLAYERSTATE_H + +#ifndef NOVELRT_ECS_H +#error NovelRT does not support including types explicitly by default. Please include Ecs.h instead for the Ecs namespace subset. +#endif + +namespace NovelRT::Ecs::Narrative +{ + enum class NarrativePlayerState : uint32_t + { + Idle = 0, + RequestPlay = 1, + Playing = 2, + RequestStop = 3, + RequestDestroy = 4 + }; +} + +#endif // NOVELRT_NARRATIVEPLAYERSTATE_H diff --git a/include/NovelRT/Ecs/Narrative/NarrativePlayerSystem.h b/include/NovelRT/Ecs/Narrative/NarrativePlayerSystem.h new file mode 100644 index 000000000..780e0cd26 --- /dev/null +++ b/include/NovelRT/Ecs/Narrative/NarrativePlayerSystem.h @@ -0,0 +1,32 @@ +// Copyright © Matt Jones and Contributors. Licensed under the MIT Licence (MIT). See LICENCE.md in the repository root +// for more information. + +#ifndef NOVELRT_NARRATIVEPLAYERSYSTEM_H +#define NOVELRT_NARRATIVEPLAYERSYSTEM_H + +#ifndef NOVELRT_ECS_H +#error NovelRT does not support including types explicitly by default. Please include Ecs.h instead for the Ecs namespace subset. +#endif + +namespace NovelRT::Ecs::Narrative +{ + // This type should be as immutable as possible. Any methods that mutate the system that aren't Update() either need to be made thread-safe or specified it should be called from some well-defined location. - Matt + class NarrativePlayerSystem final : public IEcsSystem + { + private: + // Nothing here yet lol. - Matt + + public: + void Update(Timing::Timestamp delta, Catalogue catalogue) final; // update loop for the ECS. - Matt + + // These four should be inlined, if possible. - Matt + [[nodiscard]] const std::string& GetSectionName(Atom sectionId) const; + [[nodiscard]] Atom GetSectionName(const std::string& name) const; + [[nodiscard]] const CharacterInformation& GetCharacterInformation(Atom characterId) const; + [[nodiscard]] const CharacterInformation& GetCharacterInformation(const std::string& characterName) const; + + void RegisterInformationToCharacter(const std::string& name); // We will probably update/expand this as we figure out what information would be good for a CharacterInformation object. - Matt + }; +} + +#endif // NOVELRT_NARRATIVEPLAYERSYSTEM_H diff --git a/include/NovelRT/ResourceManagement/Desktop/DesktopResourceLoader.h b/include/NovelRT/ResourceManagement/Desktop/DesktopResourceLoader.h index 24c09c3b7..7a69d1321 100644 --- a/include/NovelRT/ResourceManagement/Desktop/DesktopResourceLoader.h +++ b/include/NovelRT/ResourceManagement/Desktop/DesktopResourceLoader.h @@ -18,6 +18,7 @@ namespace NovelRT::ResourceManagement::Desktop protected: [[nodiscard]] TextureMetadata LoadTexture(std::filesystem::path filePath) final; [[nodiscard]] std::vector LoadShaderSourceInternal(std::filesystem::path filePath) final; + [[nodiscard]] std::unique_ptr GetStreamToAsset(std::filesystem::path filePath) final; public: ~DesktopResourceLoader() final = default; diff --git a/include/NovelRT/ResourceManagement/ResourceLoader.h b/include/NovelRT/ResourceManagement/ResourceLoader.h index 583d2e439..efb954340 100644 --- a/include/NovelRT/ResourceManagement/ResourceLoader.h +++ b/include/NovelRT/ResourceManagement/ResourceLoader.h @@ -43,6 +43,13 @@ namespace NovelRT::ResourceManagement return LoadShaderSourceInternal(_resourcesRootDirectory / "Shaders" / fileName); } + [[nodiscard]] virtual std::unique_ptr GetStreamToAsset(std::filesystem::path filePath) = 0; + + [[nodiscard]] inline std::unique_ptr GetStreamToAssetRelativePath(const std::filesystem::path& relativeFilePath) + { + return GetStreamToAsset(ResourcesRootDirectory() / relativeFilePath); + } + virtual ~ResourceLoader() = default; }; } diff --git a/src/NovelRT/CMakeLists.txt b/src/NovelRT/CMakeLists.txt index abc6db8c8..381b700f7 100644 --- a/src/NovelRT/CMakeLists.txt +++ b/src/NovelRT/CMakeLists.txt @@ -35,6 +35,7 @@ set(SOURCES Ecs/Graphics/DefaultRenderingSystem.cpp Ecs/Audio/AudioSystem.cpp Ecs/Input/InputSystem.cpp + Ecs/Narrative/NarrativePlayerSystem.cpp EngineConfig.cpp diff --git a/src/NovelRT/Ecs/Narrative/NarrativePlayerSystem.cpp b/src/NovelRT/Ecs/Narrative/NarrativePlayerSystem.cpp new file mode 100644 index 000000000..095906b59 --- /dev/null +++ b/src/NovelRT/Ecs/Narrative/NarrativePlayerSystem.cpp @@ -0,0 +1,16 @@ +// Copyright © Matt Jones and Contributors. Licensed under the MIT Licence (MIT). See LICENCE.md in the repository root +// for more information. + +#include +#include "NovelRT/Ecs/Narrative/NarrativePlayerSystem.h" + +namespace NovelRT::Ecs::Narrative +{ + void NarrativePlayerSystem::Update(Timing::Timestamp delta, Catalogue catalogue) + { + } + + void NarrativePlayerSystem::RegisterInformationToCharacter(const std::string& name) + { + } +} \ No newline at end of file diff --git a/src/NovelRT/ResourceManagement/Desktop/DesktopResourceLoader.cpp b/src/NovelRT/ResourceManagement/Desktop/DesktopResourceLoader.cpp index 263525bd9..c0b6e77d2 100644 --- a/src/NovelRT/ResourceManagement/Desktop/DesktopResourceLoader.cpp +++ b/src/NovelRT/ResourceManagement/Desktop/DesktopResourceLoader.cpp @@ -161,4 +161,16 @@ namespace NovelRT::ResourceManagement::Desktop return buffer; } + + std::unique_ptr DesktopResourceLoader::GetStreamToAsset(std::filesystem::path filePath) + { + auto file = std::make_unique(filePath.string()); + + if (!file->is_open()) + { + throw NovelRT::Exceptions::FileNotFoundException(filePath.string()); + } + + return file; + } } From 6f7b9dfcd8a9c27e60268b7b2db6d0b69a914d31 Mon Sep 17 00:00:00 2001 From: Matt Jones Date: Mon, 16 May 2022 20:43:17 +0100 Subject: [PATCH 2/3] Finish ECS skeleton. --- .../DefaultNarrativeComponentTypes.h | 2 +- .../Ecs/Narrative/NarrativePlayerSystem.cpp | 25 +++++++++++++++++++ 2 files changed, 26 insertions(+), 1 deletion(-) diff --git a/include/NovelRT/Ecs/Narrative/DefaultNarrativeComponentTypes.h b/include/NovelRT/Ecs/Narrative/DefaultNarrativeComponentTypes.h index 4d5652b0a..321f26617 100644 --- a/include/NovelRT/Ecs/Narrative/DefaultNarrativeComponentTypes.h +++ b/include/NovelRT/Ecs/Narrative/DefaultNarrativeComponentTypes.h @@ -23,7 +23,7 @@ namespace NovelRT::Ecs::Narrative sectionId = other.sectionId; characterId = other.characterId; } - + inline bool operator==(const NarrativePlayerStateComponent& other) const noexcept { return currentState == other.currentState && sectionId == other.sectionId && characterId == other.characterId; diff --git a/src/NovelRT/Ecs/Narrative/NarrativePlayerSystem.cpp b/src/NovelRT/Ecs/Narrative/NarrativePlayerSystem.cpp index 095906b59..94fb6765f 100644 --- a/src/NovelRT/Ecs/Narrative/NarrativePlayerSystem.cpp +++ b/src/NovelRT/Ecs/Narrative/NarrativePlayerSystem.cpp @@ -8,6 +8,31 @@ namespace NovelRT::Ecs::Narrative { void NarrativePlayerSystem::Update(Timing::Timestamp delta, Catalogue catalogue) { + auto playerStateBuffer = catalogue.GetComponentView(); + + for (auto [entity, playerStateComponent] : playerStateBuffer) + { + switch (playerStateComponent.currentState) + { + // Do nothing. - Matt + case NarrativePlayerState::Idle: + break; + // Set state to playing and execute the section accordingly. You should update the instruction call here to represent correct state. - Matt + case NarrativePlayerState::RequestPlay: + playerStateBuffer.PushComponentUpdateInstruction(entity, NarrativePlayerStateComponent{NarrativePlayerState::Playing, playerStateComponent.sectionId, playerStateComponent.characterId}); + break; + // Ensure that the player state component gets an update on accurate information e.g. which character is talking and which section is running. - Matt + case NarrativePlayerState::Playing: + break; + // Set state to Idle and stop executing. - Matt + case NarrativePlayerState::RequestStop: + break; + // Destroy the narrative player state component and then do whatever you see fit internally based on that. - Matt + case NarrativePlayerState::RequestDestroy: + playerStateBuffer.RemoveComponent(entity); + break; + } + } } void NarrativePlayerSystem::RegisterInformationToCharacter(const std::string& name) From 429d4529665415cbb85593ecea7e0c4fbf96eb61 Mon Sep 17 00:00:00 2001 From: Matt Jones Date: Mon, 16 May 2022 20:49:23 +0100 Subject: [PATCH 3/3] Fix return value. --- include/NovelRT/Ecs/Narrative/DefaultNarrativeComponentTypes.h | 1 + 1 file changed, 1 insertion(+) diff --git a/include/NovelRT/Ecs/Narrative/DefaultNarrativeComponentTypes.h b/include/NovelRT/Ecs/Narrative/DefaultNarrativeComponentTypes.h index 321f26617..737044162 100644 --- a/include/NovelRT/Ecs/Narrative/DefaultNarrativeComponentTypes.h +++ b/include/NovelRT/Ecs/Narrative/DefaultNarrativeComponentTypes.h @@ -22,6 +22,7 @@ namespace NovelRT::Ecs::Narrative currentState = other.currentState; sectionId = other.sectionId; characterId = other.characterId; + return *this; } inline bool operator==(const NarrativePlayerStateComponent& other) const noexcept