From bddef22cb87bf74f4ebbc8110a8b3e5be746a0c7 Mon Sep 17 00:00:00 2001 From: Dimo Markov Date: Wed, 13 Mar 2024 13:11:59 +0200 Subject: [PATCH] Seperated External.hpp and inl --- include/Entity/Module.hpp | 10 + include/Entity/Thing.hpp | 12 + include/Langulus/Asset.hpp | 71 ++ include/Langulus/Asset.inl | 92 ++ include/Langulus/Graphics.hpp | 101 +++ include/Langulus/IO.hpp | 135 +++ include/Langulus/IO.inl | 140 +++ include/Langulus/Image.hpp | 108 +++ include/Langulus/Image.inl | 164 ++++ include/Langulus/Material.hpp | 85 ++ include/Langulus/Material.inl | 72 ++ include/Langulus/Mesh.hpp | 110 +++ include/Langulus/Mesh.inl | 428 +++++++++ include/Langulus/Physical.hpp | 74 ++ include/Langulus/Platform.hpp | 69 ++ .../External.hpp => Langulus/Platform.inl} | 12 +- include/Langulus/UI.hpp | 76 ++ source/Common.hpp | 38 +- source/External.hpp | 634 ------------- source/External.inl | 837 ------------------ source/Hierarchy-Gather.inl | 8 +- source/Hierarchy-Seek.inl | 24 +- source/Hierarchy.hpp | 86 +- source/Module.hpp | 44 +- source/Runtime.cpp | 66 +- source/Runtime.hpp | 15 +- source/Thing-Gather.inl | 4 +- source/Thing-Seek.inl | 31 +- source/Thing-Verbs.cpp | 6 +- source/Thing.cpp | 12 +- source/Thing.hpp | 44 +- source/Thing.inl | 39 +- source/Unit-Gather.inl | 13 +- source/Unit-Seek.inl | 2 +- source/Unit.cpp | 8 +- source/Unit.hpp | 13 +- test/Main.cpp | 24 +- test/Main.hpp | 7 +- test/TestUnit.cpp | 4 +- 39 files changed, 1974 insertions(+), 1744 deletions(-) create mode 100644 include/Entity/Module.hpp create mode 100644 include/Langulus/Asset.hpp create mode 100644 include/Langulus/Asset.inl create mode 100644 include/Langulus/Graphics.hpp create mode 100644 include/Langulus/IO.hpp create mode 100644 include/Langulus/IO.inl create mode 100644 include/Langulus/Image.hpp create mode 100644 include/Langulus/Image.inl create mode 100644 include/Langulus/Material.hpp create mode 100644 include/Langulus/Material.inl create mode 100644 include/Langulus/Mesh.hpp create mode 100644 include/Langulus/Mesh.inl create mode 100644 include/Langulus/Physical.hpp create mode 100644 include/Langulus/Platform.hpp rename include/{Entity/External.hpp => Langulus/Platform.inl} (72%) create mode 100644 include/Langulus/UI.hpp delete mode 100644 source/External.hpp delete mode 100644 source/External.inl diff --git a/include/Entity/Module.hpp b/include/Entity/Module.hpp new file mode 100644 index 0000000..f5fd93b --- /dev/null +++ b/include/Entity/Module.hpp @@ -0,0 +1,10 @@ +/// +/// Langulus::Entity +/// Copyright (c) 2013 Dimo Markov +/// Part of the Langulus framework, see https://langulus.com +/// +/// Distributed under GNU General Public License v3+ +/// See LICENSE file, or https://www.gnu.org/licenses +/// +#pragma once +#include "../../source/Module.hpp" \ No newline at end of file diff --git a/include/Entity/Thing.hpp b/include/Entity/Thing.hpp index 6306460..c1abf92 100644 --- a/include/Entity/Thing.hpp +++ b/include/Entity/Thing.hpp @@ -12,3 +12,15 @@ #include "../../source/Thing-Gather.inl" #include "../../source/Thing-Seek.inl" #include "../../source/Pin.inl" +#include "../../source/Runtime.hpp" + + +namespace Langulus +{ + + using Thing = Entity::Thing; + using Runtime = Entity::Runtime; + template + using Pin = Entity::Pin; + +} // namespace Langulus diff --git a/include/Langulus/Asset.hpp b/include/Langulus/Asset.hpp new file mode 100644 index 0000000..607a620 --- /dev/null +++ b/include/Langulus/Asset.hpp @@ -0,0 +1,71 @@ +/// +/// Langulus::Entity +/// Copyright (c) 2013 Dimo Markov +/// Part of the Langulus framework, see https://langulus.com +/// +/// Distributed under GNU General Public License v3+ +/// See LICENSE file, or https://www.gnu.org/licenses +/// +#pragma once +#include "../Entity/Thing.hpp" +#include + + +namespace Langulus::A +{ + + /// + /// Abstract asset module + /// + struct AssetModule : Module { + LANGULUS_BASES(Module); + using Module::Module; + }; + + /// + /// Abstract asset unit + /// + struct Asset : Unit, ProducedFrom { + LANGULUS(PRODUCER) AssetModule; + LANGULUS_BASES(Unit); + + Asset(DMeta, AssetModule*, const Neat&); + + using Data = Any; + using DataList = TAny; + using DataListMap = TUnorderedMap; + + protected: + NOD() const DataListMap& GetDataListMap() const noexcept; + + // Map of lists of generated data + DataListMap mDataListMap; + + public: + virtual bool Generate(TMeta, Offset = 0) = 0; + + template class S, CT::Block B> + requires CT::Semantic> + void Commit(S&&); + + template + NOD() const Data* GetData(Offset = 0) const noexcept; + NOD() const Data* GetData(TMeta, Offset = 0) const noexcept; + + template + NOD() const DataList* GetDataList() const noexcept; + NOD() const DataList* GetDataList(TMeta) const noexcept; + }; + +} // namespace Langulus::A + +namespace Langulus::CT +{ + + /// A concept for any kind of asset + template + concept Asset = DerivedFrom; + +} // namespace Langulus::CT + +#include "Asset.inl" diff --git a/include/Langulus/Asset.inl b/include/Langulus/Asset.inl new file mode 100644 index 0000000..409f4a2 --- /dev/null +++ b/include/Langulus/Asset.inl @@ -0,0 +1,92 @@ +/// +/// Langulus::Entity +/// Copyright (c) 2013 Dimo Markov +/// Part of the Langulus framework, see https://langulus.com +/// +/// Distributed under GNU General Public License v3+ +/// See LICENSE file, or https://www.gnu.org/licenses +/// +#pragma once +#include "Asset.hpp" + + +namespace Langulus::A +{ + + /// Asset constructor + /// @param type - concrete type of the asset + /// @param producer - the asset library and producer + /// @param desc - messy descriptor for the content + LANGULUS(INLINED) + Asset::Asset(RTTI::DMeta type, AssetModule* producer, const Neat& desc) + : Unit {type} + , ProducedFrom {producer, desc} {} + + /// Get the entire content data map + /// @attention this doesn't generate any data + /// @return a reference to the contents + LANGULUS(INLINED) + const Asset::DataListMap& Asset::GetDataListMap() const noexcept { + return mDataListMap; + } + + /// Get a single data entry from the contents + /// @tparam T - the trait to search for + /// @param index - the Nth data associated to the trait + /// @return a pointer to the data entry, or nullptr if none exists + template LANGULUS(INLINED) + const Asset::Data* Asset::GetData(Offset index) const noexcept { + return GetData(MetaTraitOf(), index); + } + + /// Get a single data entry from the contents + /// @param trait - the trait to search for + /// @param index - the Nth data associated to the trait + /// @return a pointer to the data entry, or nullptr if none exists + LANGULUS(INLINED) + const Asset::Data* Asset::GetData(TMeta trait, Offset index) const noexcept { + if (not const_cast(this)->Generate(trait, index)) + return nullptr; + + const auto datalist = GetDataList(trait); + return datalist and datalist->GetCount() > index + ? &(*datalist)[index] + : nullptr; + } + + /// Get a data list from the contents + /// @tparam T - the trait to search for + /// @return a pointer to the data list, or nullptr if none exists + template + LANGULUS(INLINED) + const Asset::DataList* Asset::GetDataList() const noexcept { + return GetDataList(MetaTraitOf()); + } + + /// Get a data list from the contents + /// @param trait - the trait to search for + /// @return a pointer to the data list, or nullptr if none exists + LANGULUS(INLINED) + const Asset::DataList* Asset::GetDataList(TMeta trait) const noexcept { + if (not const_cast(this)->Generate(trait)) + return nullptr; + + const auto found = mDataListMap.FindIt(trait); + return found ? found.mValue : nullptr; + } + + /// Commit data to an asset + /// @attention data is always commited, even if such trait already exists + /// @tparam T - data trait, the intent we're commiting with + /// @param content - the data and semantic to commit + template class S, CT::Block B> + requires CT::Semantic> LANGULUS(INLINED) + void Asset::Commit(S&& content) { + const auto found = mDataListMap.FindIt(MetaTraitOf()); + if (found) + *found.mValue << Any {content.Forward()}; + else + mDataListMap.Insert(MetaTraitOf(), content.Forward()); + } + +} // namespace Langulus::A diff --git a/include/Langulus/Graphics.hpp b/include/Langulus/Graphics.hpp new file mode 100644 index 0000000..0123aa3 --- /dev/null +++ b/include/Langulus/Graphics.hpp @@ -0,0 +1,101 @@ +/// +/// Langulus::Entity +/// Copyright (c) 2013 Dimo Markov +/// Part of the Langulus framework, see https://langulus.com +/// +/// Distributed under GNU General Public License v3+ +/// See LICENSE file, or https://www.gnu.org/licenses +/// +#pragma once +#include "Module.hpp" +#include "Unit.hpp" +#include "Runtime.hpp" +#include +#include +#include +#include +#include +#include + +LANGULUS_DEFINE_TRAIT(FOV, + "Horizontal field of view angle, usually a real number"); +LANGULUS_DEFINE_TRAIT(AspectRatio, + "Aspect ratio trait (width / height), usually a real number"); +LANGULUS_DEFINE_TRAIT(Viewport, + "Viewport and depth clipping, usually a Range4"); + + +namespace Langulus::A +{ + + /// + /// Abstract graphics module + /// + struct GraphicsModule : Module { + LANGULUS_BASES(Module); + using Module::Module; + }; + + /// + /// Abstract graphics units + /// + struct Graphics : Unit { + LANGULUS_BASES(Unit); + using Unit::Unit; + }; + + /// + /// Abstract graphics renderer + /// + struct Renderer : Graphics { + LANGULUS(PRODUCER) GraphicsModule; + LANGULUS_BASES(Graphics); + using Graphics::Graphics; + }; + + /// + /// Abstract graphics layer + /// + struct Layer : Graphics { + LANGULUS(PRODUCER) Renderer; + LANGULUS_BASES(Graphics); + using Graphics::Graphics; + }; + + /// + /// Abstract graphics camera + /// + struct Camera : Graphics { + LANGULUS(PRODUCER) Layer; + LANGULUS_BASES(Graphics); + using Graphics::Graphics; + }; + + /// + /// Abstract graphics renderable + /// + struct Renderable : Graphics { + LANGULUS(PRODUCER) Layer; + LANGULUS_BASES(Graphics); + using Graphics::Graphics; + }; + + /// + /// Abstract graphics light + /// + struct Light : Graphics { + LANGULUS(PRODUCER) Layer; + LANGULUS_BASES(Graphics); + using Graphics::Graphics; + }; + +} // namespace Langulus::A + +namespace Langulus::CT +{ + + /// A concept for any kind of a graphics unit + template + concept Graphics = DerivedFrom; + +} // namespace Langulus::CT diff --git a/include/Langulus/IO.hpp b/include/Langulus/IO.hpp new file mode 100644 index 0000000..337dc3a --- /dev/null +++ b/include/Langulus/IO.hpp @@ -0,0 +1,135 @@ +/// +/// Langulus::Entity +/// Copyright (c) 2013 Dimo Markov +/// Part of the Langulus framework, see https://langulus.com +/// +/// Distributed under GNU General Public License v3+ +/// See LICENSE file, or https://www.gnu.org/licenses +/// +#pragma once +#include "../Entity/Thing.hpp" + + +namespace Langulus::A +{ + + struct File; + struct Folder; + + + /// + /// Abstract file system module + /// + struct FileSystem : Module { + protected: + // Working directory path + // This is the only full path that is exposed to the system, + // unless LANGULUS(PARANOID) is enabled + Path mWorkingPath; + // Main data directory, for both reading and writing + // Relative to mWorkingPath + Path mMainDataPath; + + public: + LANGULUS_BASES(Module); + using Module::Module; + + NOD() virtual Ref GetFile (const Path&) = 0; + NOD() virtual Ref GetFolder(const Path&) = 0; + + NOD() const Path& GetWorkingPath() const noexcept; + NOD() const Path& GetDataPath() const noexcept; + }; + + /// + /// Abstract file interface + /// + struct File : Unit { + protected: + Path mFilePath; + bool mExists {}; + DMeta mFormat {}; + Size mByteCount {}; + bool mIsReadOnly {}; + + public: + LANGULUS(PRODUCER) FileSystem; + LANGULUS_BASES(Unit); + using Unit::Unit; + + NOD() bool Exists() const noexcept; + NOD() bool IsReadOnly() const noexcept; + NOD() const Path& GetFilePath() const noexcept; + NOD() DMeta GetFormat() const noexcept; + NOD() Size GetBytesize() const noexcept; + + NOD() virtual Any ReadAs(DMeta) const = 0; + + NOD() virtual Ref RelativeFile (const Path&) const = 0; + NOD() virtual Ref RelativeFolder(const Path&) const = 0; + + template + NOD() T ReadAs() const; + + /// Abstract file reader stream + struct Reader { + protected: + File* mFile; + Offset mProgress {}; + + public: + Reader() = delete; + Reader(File* f) + : mFile {f} {} + + File* GetFile() const noexcept { return mFile; } + + virtual Offset Read(Any&) = 0; + }; + + /// Abstract file writer stream + struct Writer { + protected: + File* mFile; + Offset mProgress {}; + bool mAppend = false; + + public: + Writer() = delete; + Writer(File* f, bool append) + : mFile {f}, mAppend {append} {} + + File* GetFile() const noexcept { return mFile; } + + virtual Offset Write(const Any&) = 0; + }; + + NOD() virtual Ref NewReader() const = 0; + NOD() virtual Ref NewWriter(bool append) const = 0; + }; + + /// + /// Abstract folder interface + /// + struct Folder : Unit { + protected: + Path mFolderPath; + bool mExists = false; + bool mIsReadOnly = false; + + public: + LANGULUS(PRODUCER) FileSystem; + LANGULUS_BASES(Unit); + using Unit::Unit; + + NOD() bool Exists() const noexcept; + NOD() bool IsReadOnly() const noexcept; + NOD() const Path& GetFolderPath() const noexcept; + + NOD() virtual Ref RelativeFile (const Path&) const = 0; + NOD() virtual Ref RelativeFolder(const Path&) const = 0; + }; + +} // namespace Langulus::A + +#include "IO.inl" \ No newline at end of file diff --git a/include/Langulus/IO.inl b/include/Langulus/IO.inl new file mode 100644 index 0000000..cc6b435 --- /dev/null +++ b/include/Langulus/IO.inl @@ -0,0 +1,140 @@ +/// +/// Langulus::Entity +/// Copyright (c) 2013 Dimo Markov +/// Part of the Langulus framework, see https://langulus.com +/// +/// Distributed under GNU General Public License v3+ +/// See LICENSE file, or https://www.gnu.org/licenses +/// +#pragma once +#include "IO.hpp" + + +namespace Langulus::A +{ + + /// Get the current working path (where the main exe was executed) + /// @return the path + LANGULUS(INLINED) + const Path& FileSystem::GetWorkingPath() const noexcept { + return mWorkingPath; + } + + /// Get the current data path, like GetWorkingPath() / "data" + /// @return the path + LANGULUS(INLINED) + const Path& FileSystem::GetDataPath() const noexcept { + return mMainDataPath; + } + + /// Check if file physically exists + /// @return true if file exists + LANGULUS(INLINED) + bool File::Exists() const noexcept { + return mExists; + } + + /// Check if file is read-only + /// @return true if file exists and is read-only + LANGULUS(INLINED) + bool File::IsReadOnly() const noexcept { + return mIsReadOnly; + } + + /// Check file format, that is deduced from file extension, and compared + /// against all reflected file extensions + /// @return the file format + LANGULUS(INLINED) + DMeta File::GetFormat() const noexcept { + return mFormat; + } + + /// Get the size of the file in bytes (if file exists) + /// @return the size of the file in bytes, or 0 if it doesn't exist + LANGULUS(INLINED) + Size File::GetBytesize() const noexcept { + return mByteCount; + } + + /// Get the full path of the file + /// @return a reference to the path + LANGULUS(INLINED) + const Path& File::GetFilePath() const noexcept { + return mFilePath; + } + + /// Read a file and attempt to deserialize it as provided type T + /// Throws if deserialization isn't possible + /// @tparam T - the type to deserialize as, if possible + /// @return the deserialized instance of T + template LANGULUS(INLINED) + T File::ReadAs() const { + return ReadAs(MetaDataOf()).template As(); + } + + /// Check if folder physically exists + /// @return true if folder exists + LANGULUS(INLINED) + bool Folder::Exists() const noexcept { + return mExists; + } + + /// Check if file is read-only + /// @return true if file exists and is read-only + LANGULUS(INLINED) + bool Folder::IsReadOnly() const noexcept { + return mIsReadOnly; + } + + /// Get the full path of the folder + /// @return a reference to the path + LANGULUS(INLINED) + const Path& Folder::GetFolderPath() const noexcept { + return mFolderPath; + } + +} // namespace Langulus::A + + +namespace Langulus::Entity +{ + + /// Get a file interface, relying on external modules to find it + /// @param path - the path for the file + /// @return the file interface, or nullptr if file doesn't exist + Ref Runtime::GetFile(const Path& path) { + auto& fileSystems = GetModules(); + LANGULUS_ASSERT(fileSystems, Module, + "Can't retrieve file `", path, "` - no file system module available"); + return fileSystems.template As()->GetFile(path); + } + + /// Get a folder interface, relying on external modules to find it + /// @param path - the path for the folder + /// @return the folder interface, or nullptr if folder doesn't exist + Ref Runtime::GetFolder(const Path& path) { + auto& fileSystems = GetModules(); + LANGULUS_ASSERT(fileSystems, Module, + "Can't retrieve folder `", path, "` - no file system module available"); + return fileSystems.template As()->GetFolder(path); + } + + /// Get the current working path (where the main exe was executed) + /// @return the path + const Path& Runtime::GetWorkingPath() const { + auto& fileSystems = GetModules(); + LANGULUS_ASSERT(fileSystems, Module, + "Can't retrieve working path", " - no file system module available"); + return fileSystems.template As()->GetWorkingPath(); + } + + /// Get the current data path, like GetWorkingPath() / "data" + /// @return the path + const Path& Runtime::GetDataPath() const { + auto& fileSystems = GetModules(); + LANGULUS_ASSERT(fileSystems, Module, + "Can't retrieve data path", " - no file system module available"); + return fileSystems.template As()->GetDataPath(); + } + +} // namespace Langulus::Entity diff --git a/include/Langulus/Image.hpp b/include/Langulus/Image.hpp new file mode 100644 index 0000000..56bab9f --- /dev/null +++ b/include/Langulus/Image.hpp @@ -0,0 +1,108 @@ +/// +/// Langulus::Entity +/// Copyright (c) 2013 Dimo Markov +/// Part of the Langulus framework, see https://langulus.com +/// +/// Distributed under GNU General Public License v3+ +/// See LICENSE file, or https://www.gnu.org/licenses +/// +#pragma once +#include "Asset.hpp> + +LANGULUS_DEFINE_TRAIT(Image, "Image unit"); +LANGULUS_EXCEPTION(Image); + + +namespace Langulus +{ + + using namespace Langulus::Flow; + using namespace Langulus::Anyness; + using namespace Langulus::Entity; + using namespace Langulus::Math; + + + /// + /// Universal pixel buffer view + /// + struct ImageView { + uint32_t mWidth {1}; + uint32_t mHeight {1}; + uint32_t mDepth {1}; + uint32_t mFrames {1}; + DMeta mFormat {}; + // Reverse RGBA to BGRA + // This is not a scalable solution and would eventually fail + bool mReverseFormat {}; + + bool operator == (const ImageView&) const noexcept; + + NOD() constexpr uint32_t GetPixelCount() const noexcept; + NOD() constexpr uint32_t GetDimensionCount() const noexcept; + NOD() Size GetPixelBytesize() const noexcept; + NOD() Size GetBytesize() const noexcept; + NOD() uint32_t GetChannelCount() const noexcept; + NOD() Hash GetHash() const noexcept; + }; + +} // namespace Langulus + +namespace Langulus::A +{ + + /// + /// Abstract texture content + /// + struct Image : Asset { + LANGULUS_BASES(Asset); + using Asset::Asset; + + protected: + ImageView mView; + + public: + NOD() virtual Ref GetLOD(const LOD&) const = 0; + NOD() virtual void* GetGPUHandle() const noexcept = 0; + + NOD() DMeta GetFormat() const noexcept; + NOD() ImageView const& GetView() const noexcept; + NOD() ImageView& GetView() noexcept; + + template + auto ForEachPixel(F&&) const; + + template class S, CT::Block B> + requires CT::Semantic> + void Upload(S&&); + + /// + /// Iteration + /// + template + struct Iterator; + + NOD() constexpr Iterator begin() noexcept; + NOD() constexpr Iterator begin() const noexcept; + NOD() constexpr Iterator last() noexcept; + NOD() constexpr Iterator last() const noexcept; + constexpr A::IteratorEnd end() const noexcept { return {}; } + }; + + /// + /// Abstract font content + /// + struct Font : Image { + LANGULUS_BASES(Image); + using Image::Image; + }; + +} // namespace Langulus::A + +namespace Langulus::CT +{ + + /// A concept for any kind of image content unit + template + concept Image = DerivedFrom; + +} // namespace Langulus::CT diff --git a/include/Langulus/Image.inl b/include/Langulus/Image.inl new file mode 100644 index 0000000..3bb159b --- /dev/null +++ b/include/Langulus/Image.inl @@ -0,0 +1,164 @@ +/// +/// Langulus::Entity +/// Copyright (c) 2013 Dimo Markov +/// Part of the Langulus framework, see https://langulus.com +/// +/// Distributed under GNU General Public License v3+ +/// See LICENSE file, or https://www.gnu.org/licenses +/// +#pragma once +#include "Image.hpp" + + +namespace Langulus +{ + + /// Compare texture views + /// @param rhs - the texture view to compare against + /// @return true if both views are the same + LANGULUS(INLINED) + bool ImageView::operator == (const ImageView& rhs) const noexcept { + return mWidth == rhs.mWidth + and mHeight == rhs.mHeight + and mDepth == rhs.mDepth + and mFrames == rhs.mFrames + and mFormat == rhs.mFormat; + } + + /// Get the number of pixels in the texture + /// @return the number of pixels + LANGULUS(INLINED) + constexpr uint32_t ImageView::GetPixelCount() const noexcept { + return mWidth * mHeight * mDepth * mFrames; + } + + /// Get number of dimensions used for the image + /// @return return up to 4 dimensions + LANGULUS(INLINED) + constexpr uint32_t ImageView::GetDimensionCount() const noexcept { + return (mWidth > 1) + (mHeight > 1) + (mDepth > 1) + (mFrames > 1); + } + + /// Get the size in bytes for a single pixel + /// @return the size in bytes + LANGULUS(INLINED) + Size ImageView::GetPixelBytesize() const noexcept { + return mFormat ? mFormat->mSize : Size {0}; + } + + /// Get the bytesize of the entire image across all dimensions + /// @return the bytesize of the entire image + LANGULUS(INLINED) + Size ImageView::GetBytesize() const noexcept { + return GetPixelCount() * GetPixelBytesize(); + } + + /// Get the number of channels inside the color format + /// @return the number of channels + LANGULUS(INLINED) + uint32_t ImageView::GetChannelCount() const noexcept { + return static_cast(mFormat->GetMemberCount()); + } + + /// Get the hash of a normalized descriptor (cached) + /// @return the hash + LANGULUS(INLINED) + Hash ImageView::GetHash() const noexcept { + return HashOf( + mWidth, mHeight, mDepth, mFrames, + mFormat, mReverseFormat + ); + } + +} // namespace Langulus + +namespace Langulus::A +{ + + /// Get the pixel format of the texture + /// @return the pixel format type + LANGULUS(INLINED) + DMeta Image::GetFormat() const noexcept { + return mView.mFormat; + } + + /// Get the texture view (const) + /// @return the texture view + LANGULUS(INLINED) + const ImageView& Image::GetView() const noexcept { + return mView; + } + + /// Get the texture view + /// @return the texture view + LANGULUS(INLINED) + ImageView& Image::GetView() noexcept { + return mView; + } + + /// Execute a function for each pixel, represented by a desired type + /// @tparam F - the function signature (deducible) + /// @param call - the function to execute for each pixel + /// @return the number of pixels that were iterated + template + auto Image::ForEachPixel(F&& call) const { + auto pixels = GetData(); + + LANGULUS_ASSUME(DevAssumes, pixels and *pixels, + "No color data", " in ", Self()); + LANGULUS_ASSUME(DevAssumes, pixels->IsDense(), + "Image data is not dense", " for ", Self()); + LANGULUS_ASSUME(DevAssumes, + pixels->CastsTo() or pixels->CastsTo(), + "Image doesn't contain pixel data", + " - contains ", pixels->GetType(), " instead"); + + using A = Deref>; + using R = ReturnOf; + + static_assert(CT::Constant, "Color iterator must be constant"); + static_assert(CT::Dense, "Color iterator must be dense"); + + LANGULUS_ASSUME(DevAssumes, mView.mFormat->IsSimilar(), + "Iterator type is not compatible with contained color data"); + + // Iterate using the desired color type + UNUSED() Count counter = 0; + auto data = pixels->CastsTo() + ? pixels->Get().GetRawAs() + : pixels->GetRawAs(); + const auto dataEnd = data + mView.GetPixelCount(); + + while (data != dataEnd) { + if constexpr (CT::Bool) { + if (not call(*data)) + return counter; + ++counter; + } + else call(*data); + + ++data; + } + + if constexpr (CT::Bool) + return counter; + + //TODO map other kinds of pixel iterators? + } + + /// Upload raw data to the image by a semantic + /// @attention deletes any data previously commited + /// @param data - the block of data + template class S, CT::Block B> + requires CT::Semantic> LANGULUS(INLINED) + void Image::Upload(S&& data) { + // Check if provided data matches the view requirements + LANGULUS_ASSERT(mView.GetBytesize() == data->GetBytesize(), Image, + "Data is of the wrong size"); + + // Reset data and commit the new one + mDataListMap.Reset(); + Commit(data.Forward()); + } + +} // namespace Langulus::A diff --git a/include/Langulus/Material.hpp b/include/Langulus/Material.hpp new file mode 100644 index 0000000..2d2b3d9 --- /dev/null +++ b/include/Langulus/Material.hpp @@ -0,0 +1,85 @@ +/// +/// Langulus::Entity +/// Copyright (c) 2013 Dimo Markov +/// Part of the Langulus framework, see https://langulus.com +/// +/// Distributed under GNU General Public License v3+ +/// See LICENSE file, or https://www.gnu.org/licenses +/// +#pragma once +#include "Asset.hpp" + +LANGULUS_DEFINE_TRAIT(Material, "Material unit"); +LANGULUS_DEFINE_TRAIT(Shader, "Shader unit"); + + +namespace Langulus +{ + + /// + /// Shader stages + /// + namespace ShaderStage + { + enum Enum : uint32_t { + Vertex = 0, // Vertex shader stage + Geometry, // Geometry shader stage + TessCtrl, // Tesselation control stage + TessEval, // Tesselation evaluation stage + Pixel, // Pixel shader stage + Compute, // Compute shader stage + + Counter // Shader stage counter (keep at end) + }; + + /// Shader names + constexpr Token Names[Enum::Counter] = { + "vertex", + "geometry", + "tesselation control", + "tesselation evaluation", + "fragment", + "compute" + }; + } + + + /// + /// Shader layout tokens + /// + namespace ShaderToken + { + constexpr Token Version = "//#VERSION\n"; + constexpr Token Defines = "//#DEFINES\n"; + constexpr Token Input = "//#INPUT\n"; + constexpr Token Output = "//#OUTPUT\n"; + constexpr Token Dependencies = "//#DEPENDENCY\n"; + constexpr Token Colorize = "//#COLORIZE\n"; + constexpr Token Transform = "//#TRANSFORM\n"; + constexpr Token Position = "//#POSITION\n"; + constexpr Token Uniform = "//#UNIFORM\n"; + constexpr Token Texturize = "//#TEXTURIZE\n"; + constexpr Token Functions = "//#FUNCTIONS\n"; + } + + namespace A + { + + /// + /// Abstract material content + /// + struct Material : Asset { + LANGULUS_BASES(Asset); + using Asset::Asset; + + NOD() virtual Ref GetLOD(const LOD&) const = 0; + + NOD() const TraitList& GetInputs(Rate) const; + NOD() const TraitList& GetInputs(Offset) const; + + NOD() const TraitList& GetOutputs(Rate) const; + NOD() const TraitList& GetOutputs(Offset) const; + }; + + } // namespace Langulus::A +} // namespace Langulus \ No newline at end of file diff --git a/include/Langulus/Material.inl b/include/Langulus/Material.inl new file mode 100644 index 0000000..777f675 --- /dev/null +++ b/include/Langulus/Material.inl @@ -0,0 +1,72 @@ +/// +/// Langulus::Entity +/// Copyright (c) 2013 Dimo Markov +/// Part of the Langulus framework, see https://langulus.com +/// +/// Distributed under GNU General Public License v3+ +/// See LICENSE file, or https://www.gnu.org/licenses +/// +#pragma once +#include "Material.hpp" + + +namespace Langulus::A +{ + + /// Get input traits for a given rate (const) + /// @param rate - the rate + /// @return the input trait list + LANGULUS(INLINED) + const TraitList& Material::GetInputs(Rate rate) const { + return GetInputs(rate.GetInputIndex()); + } + + /// Get input traits for a given input offset (const) + /// @attention offset must be in the range [0; Rate::InputCount) + /// @param rate - the input offset + /// @return the input trait list + LANGULUS(INLINED) + const TraitList& Material::GetInputs(Offset rate) const { + LANGULUS_ASSUME(DevAssumes, + Asset::mDataListMap.ContainsKey(MetaOf()), + "Material doesn't contain inputs"); + LANGULUS_ASSUME(DevAssumes, + Asset::GetDataList()->GetCount() == Rate::InputCount, + "Material doesn't contain the correct number of rates"); + LANGULUS_ASSUME(DevAssumes, + rate < Rate::InputCount, + "Input offset out of range"); + + return *reinterpret_cast( + Asset::GetData(rate)); + } + + /// Get output traits for a given rate (const) + /// @param rate - the rate + /// @return the output trait list + LANGULUS(INLINED) + const TraitList& Material::GetOutputs(Rate rate) const { + return GetOutputs(rate.GetInputIndex()); + } + + /// Get output traits for a given input offset (const) + /// @attention offset must be in the range [0; Rate::InputCount) + /// @param rate - the input offset + /// @return the output trait list + LANGULUS(INLINED) + const TraitList& Material::GetOutputs(Offset rate) const { + LANGULUS_ASSUME(DevAssumes, + Asset::mDataListMap.ContainsKey(MetaOf()), + "Material doesn't contain inputs"); + LANGULUS_ASSUME(DevAssumes, + Asset::GetDataList()->GetCount() == Rate::InputCount, + "Material doesn't contain the correct number of rates"); + LANGULUS_ASSUME(DevAssumes, + rate < Rate::InputCount, + "Input offset out of range"); + + return *reinterpret_cast( + Asset::GetData(rate)); + } + +} // namespace Langulus::A diff --git a/include/Langulus/Mesh.hpp b/include/Langulus/Mesh.hpp new file mode 100644 index 0000000..8c1b143 --- /dev/null +++ b/include/Langulus/Mesh.hpp @@ -0,0 +1,110 @@ +/// +/// Langulus::Entity +/// Copyright (c) 2013 Dimo Markov +/// Part of the Langulus framework, see https://langulus.com +/// +/// Distributed under GNU General Public License v3+ +/// See LICENSE file, or https://www.gnu.org/licenses +/// +#pragma once +#include "Asset.hpp> + +LANGULUS_DEFINE_TRAIT(Mesh, "Mesh unit"); +LANGULUS_EXCEPTION(Mesh); + + +namespace Langulus +{ + + using namespace Langulus::Flow; + using namespace Langulus::Anyness; + using namespace Langulus::Entity; + using namespace Langulus::Math; + + + /// + /// Vertex/index buffer view + /// + struct MeshView { + // Number of primitives + uint32_t mPrimitiveCount {}; + // Starting primitive + uint32_t mPrimitiveStart {}; + // Number of indices + uint32_t mIndexCount {}; + // Starting index + uint32_t mIndexStart {}; + // Data topology + DMeta mTopology {}; + // Double-sidedness + bool mBilateral {}; + // Texture mapping mode + MapMode mTextureMapping {}; + + bool operator == (const MeshView&) const noexcept; + + NOD() MeshView Decay() const; + NOD() Hash GetHash() const noexcept; + }; + +} // namespace Langulus + +namespace Langulus::A +{ + + /// + /// Abstract geometry content + /// + struct Mesh : Asset { + LANGULUS_BASES(Asset); + using Asset::Asset; + + protected: + MeshView mView; + + public: + template + NOD() bool CheckTopology() const; + NOD() DMeta GetTopology() const noexcept; + + NOD() MapMode GetTextureMapper() const noexcept; + + NOD() const MeshView& GetView() const noexcept; + NOD() MeshView& GetView() noexcept; + + NOD() virtual Ref GetLOD(const LOD&) const = 0; + + NOD() Vec2u InnerGetIndices(const Data*, const Vec2u&) const; + NOD() Vec3u InnerGetIndices(const Data*, const Vec3u&) const; + + // + NOD() bool MadeOfPoints() const noexcept; + NOD() Count GetPointCount() const; + template + NOD() Any GetPointTrait(Offset) const; + + // + NOD() bool MadeOfLines() const noexcept; + NOD() Count GetLineCount() const; + NOD() Vec2u GetLineIndices(Offset) const; + template + NOD() Any GetLineTrait(Offset) const; + + // + NOD() bool MadeOfTriangles() const noexcept; + NOD() Count GetTriangleCount() const; + NOD() Vec3u GetTriangleIndices(Offset) const; + template + NOD() Any GetTriangleTrait(Offset) const; + }; + +} // namespace Langulus::A + +namespace Langulus::CT +{ + + /// A concept for any kind of geometric content unit + template + concept Mesh = DerivedFrom; + +} // namespace Langulus::CT diff --git a/include/Langulus/Mesh.inl b/include/Langulus/Mesh.inl new file mode 100644 index 0000000..fe4b603 --- /dev/null +++ b/include/Langulus/Mesh.inl @@ -0,0 +1,428 @@ +/// +/// Langulus::Entity +/// Copyright (c) 2013 Dimo Markov +/// Part of the Langulus framework, see https://langulus.com +/// +/// Distributed under GNU General Public License v3+ +/// See LICENSE file, or https://www.gnu.org/licenses +/// +#pragma once +#include "Mesh.hpp" + + +namespace Langulus +{ + + /// + /// Vertex/index buffer view + /// + + /// Compare geometry views + /// @param rhs - the geometry view to compare against + /// @return true if both views are the same + LANGULUS(INLINED) + bool MeshView::operator == (const MeshView& rhs) const noexcept { + return mPrimitiveCount == rhs.mPrimitiveCount + and mPrimitiveStart == rhs.mPrimitiveStart + and mIndexCount == rhs.mIndexCount + and mIndexStart == rhs.mIndexStart + and (mTopology == rhs.mTopology + or (mTopology and mTopology->IsExact(rhs.mTopology))) + and mBilateral == rhs.mBilateral; + } + + /// Decay the geometry view to a list of points + /// @return the decayed view + LANGULUS(INLINED) + MeshView MeshView::Decay() const { + LANGULUS_ASSERT(mPrimitiveCount and mTopology, Convert, "Bad vertex view"); + if (mTopology->template Is()) + return *this; + + MeshView result {*this}; + result.mTopology = MetaOf(); + + // mPrimitiveCount corresponds to the number of points in these + // cases: + if ( mTopology->template Is() + or mTopology->template Is() + or mTopology->template Is() + or mTopology->template Is()) + return result; + + if (mTopology->template Is()) { + // Decay triangles to points + result.mPrimitiveCount *= 3; + } + if (mTopology->template Is()) { + // Decay lines to points + result.mPrimitiveCount *= 2; + } + else LANGULUS_THROW(Convert, "Bad primitive type"); + + return result; + } + + /// Get the hash of a normalized descriptor (cached) + /// @return the hash + LANGULUS(INLINED) + Hash MeshView::GetHash() const noexcept { + return HashOf( + mPrimitiveCount, mPrimitiveStart, mIndexCount, mIndexStart, + mTopology, mBilateral, mTextureMapping + ); + } + +} // namespace Langulus + +namespace Langulus::A +{ + + /// Get the topology of the geometry + /// @return the topology type + LANGULUS(INLINED) + DMeta Mesh::GetTopology() const noexcept { + return mView.mTopology; + } + + /// Check if topology matches one of the specified types + /// @tparam T1, TN - types to check + /// @return true if T matches one of the topology types + template LANGULUS(INLINED) + bool Mesh::CheckTopology() const { + return mView.mTopology == MetaDataOf() + or ((mView.mTopology == MetaDataOf()) or ...); + } + + /// Helper that indirects in case there is an index buffer + /// @param indices - index buffer + /// @param where - line indices + /// @return the (eventually indirected) line indices + inline Math::Vec2u Mesh::InnerGetIndices(const Data* indices, const Math::Vec2u& where) const { + if (not indices or not *indices) + return where; + + if (indices->IsExact()) { + auto idx = indices->As(); + return {idx[where[0]], idx[where[1]]}; + } + + if (indices->IsExact()) { + auto idx = indices->As(); + return {idx[where[0]], idx[where[1]]}; + } + + if (indices->IsExact()) { + auto idx = indices->As(); + return {idx[where[0]], idx[where[1]]}; + } + + if (indices->IsExact()) { + auto idx = indices->As(); + return { + static_cast(idx[where[0]]), + static_cast(idx[where[1]]) + }; + } + + LANGULUS_THROW(Access, "Trying to get index from incompatible index buffer"); + } + + /// Helper that indirects in case there is an index buffer + /// @param indices - index buffer + /// @param where - triangle indices + /// @return the (eventually indirected) triangle indices + inline Math::Vec3u Mesh::InnerGetIndices(const Data* indices, const Math::Vec3u& where) const { + if (not indices or not *indices) + return where; + + if (indices->IsExact()) { + auto idx = indices->As(); + return {idx[where[0]], idx[where[1]], idx[where[2]]}; + } + + if (indices->IsExact()) { + auto idx = indices->As(); + return {idx[where[0]], idx[where[1]], idx[where[2]]}; + } + + if (indices->IsExact()) { + auto idx = indices->As(); + return {idx[where[0]], idx[where[1]], idx[where[2]]}; + } + + if (indices->IsExact()) { + auto idx = indices->As(); + return { + static_cast(idx[where[0]]), + static_cast(idx[where[1]]), + static_cast(idx[where[2]]) + }; + } + + LANGULUS_THROW(Access, "Trying to get index from incompatible index buffer"); + } + + /// Is topology a point list? + /// @return true if geometry is made of points + LANGULUS(INLINED) + bool Mesh::MadeOfPoints() const noexcept { + return CheckTopology(); + } + + /// Get the number of points inside the geometry + /// @return the number of points + LANGULUS(INLINED) + Count Mesh::GetPointCount() const { + TODO(); + return {}; + } + + template + Anyness::Any Mesh::GetPointTrait(Offset) const { + TODO(); + return {}; + } + + /// Is topology line list/strip/loop? + /// @return true if geometry is made of lines + LANGULUS(INLINED) + bool Mesh::MadeOfLines() const noexcept { + return CheckTopology(); + } + + /// Get the number of lines inside the geometry + /// @return the number of points + inline Count Mesh::GetLineCount() const { + if (MadeOfPoints()) + return 0; + + if (CheckTopology()) { + if (mView.mIndexCount > 1) + return mView.mIndexCount / 2; + else { + auto decayed = mView.Decay(); + if (decayed.mPrimitiveCount > 1) + return decayed.mPrimitiveCount / 2; + } + return 0; + } + else if (CheckTopology()) { + if (mView.mIndexCount > 1) + return mView.mIndexCount - 1; + else if (mView.mPrimitiveCount > 1) + return mView.mPrimitiveCount - 1; + return 0; + } + else if (CheckTopology()) { + if (mView.mIndexCount > 1) + return mView.mIndexCount; + else if (mView.mPrimitiveCount > 1) + return mView.mPrimitiveCount; + return 0; + } + else if (CheckTopology()) { + if (mView.mIndexCount > 2) + return mView.mIndexCount / 3; + else { + auto decayed = mView.Decay(); + if (decayed.mPrimitiveCount > 2) + return decayed.mPrimitiveCount; + } + return 0; + } + else if (CheckTopology()) { + if (mView.mIndexCount > 2) + return 1 + (mView.mIndexCount - 2) * 2; + else if (mView.mPrimitiveCount > 2) + return 1 + (mView.mPrimitiveCount - 2) * 2; + return 0; + } + + LANGULUS_THROW(Access, "Trying to count lines for unknown topology"); + } + + /// Get the point indices of a given line + /// @param index - line index + /// @return the point indices as a 32bit unsigned 2D vector + inline Vec2u Mesh::GetLineIndices(Offset index) const { + const auto indices = GetData(); + + if (CheckTopology()) + return InnerGetIndices(indices, Vec2u(index * 2, index * 2 + 1)); + else if (CheckTopology()) + return InnerGetIndices(indices, Vec2u(index > 0 ? index - 1 : 0, index > 0 ? index : 1)); + else if (CheckTopology()) { + if (index == GetLineCount() - 1) + return InnerGetIndices(indices, Vec2u(index, 0)); + else + return InnerGetIndices(indices, Vec2u(index > 0 ? index - 1 : 0, index > 0 ? index : 1)); + } + else if (CheckTopology()) { + switch (index % 3) { + case 0: case 1: + return InnerGetIndices(indices, Vec2u(index, index + 1)); + case 2: + return InnerGetIndices(indices, Vec2u(index, index - 2)); + } + } + else if (CheckTopology()) { + switch (index % 3) { + case 0: + return InnerGetIndices(indices, Vec2u(index == 0 ? 0 : index - 2, index == 0 ? 1 : index - 1)); + case 1: + return InnerGetIndices(indices, Vec2u(index - 1, index)); + case 2: + return InnerGetIndices(indices, Vec2u(index, index - 2)); + } + } + else if (CheckTopology()) { + switch (index % 3) { + case 0: + return InnerGetIndices(indices, Vec2u(0, index == 0 ? 1 : index - 1)); + case 1: + return InnerGetIndices(indices, Vec2u(index - 1, index)); + case 2: + return InnerGetIndices(indices, Vec2u(index, 0)); + } + } + + LANGULUS_THROW(Access, "Trying to count lines for unknown topology"); + } + + /// Get a specific property of a specific line + /// @tparam T - the trait to retrieve + /// @param lineIndex - the line index + /// @return data for the specific line + template + Any Mesh::GetLineTrait(Offset lineIndex) const { + const auto indices = GetLineIndices(lineIndex); + const auto soughtt = GetData(0); + if (not soughtt or not *soughtt) + return {}; + + Any soughtDecayed; + if (soughtt->template CastsTo()) + soughtDecayed = soughtt->template ReinterpretAs(); + else if (soughtt->template CastsTo()) + soughtDecayed = soughtt->template ReinterpretAs(); + else + soughtDecayed = *soughtt; + + Any result; + result.InsertBlock(IndexBack, soughtDecayed.GetElement(indices[0])); + result.InsertBlock(IndexBack, soughtDecayed.GetElement(indices[1])); + return result; + } + + /// Is geometry made up of triangles list/strip/fan? + /// @return true if geometry is made of triangles + LANGULUS(INLINED) + bool Mesh::MadeOfTriangles() const noexcept { + return CheckTopology(); + } + + /// Get the number of triangles inside the geometry + /// @return the number of points + inline Count Mesh::GetTriangleCount() const { + if (MadeOfPoints() or MadeOfLines()) + return 0; + + if (CheckTopology()) { + if (mView.mIndexCount > 2) + return mView.mIndexCount / 3; + + auto decayed = mView.Decay(); + LANGULUS_ASSERT(decayed.mPrimitiveCount % 3, Access, "Bad topology"); + return decayed.mPrimitiveCount / 3; + } + else if (CheckTopology()) { + if (mView.mIndexCount > 2) + return mView.mIndexCount - 2; + + LANGULUS_ASSERT(mView.mPrimitiveCount < 3, Access, "Bad topology"); + return mView.mPrimitiveCount - 2; + } + + LANGULUS_THROW(Access, "Trying to count triangles for unknown topology"); + } + + /// Get the indices of a given triangle + /// @param index - triangle index + /// @return the indices as a 32bit unsigned 3D vector + inline Vec3u Mesh::GetTriangleIndices(Offset index) const { + const auto indices = GetData(0); + + if (CheckTopology()) { + return InnerGetIndices(indices, Vec3u( + index * 3, + index * 3 + 1, + index * 3 + 2) + ); + } + else if (CheckTopology()) { + return InnerGetIndices(indices, Vec3u( + index == 0 ? 0 : index - 1, + index == 0 ? 1 : index, + index == 0 ? 2 : index + 1) + ); + } + else if (CheckTopology()) { + return InnerGetIndices(indices, Vec3u( + 0, + index == 0 ? 1 : index, + index == 0 ? 2 : index + 1) + ); + } + + LANGULUS_THROW(Access, "Trying to count triangles for unknown topology"); + } + + /// Get a specific property of a specific triangle + /// @tparam T - the trait to retrieve + /// @param triangleIndex - the triangle index + /// @return data for the specific triangle + template + Any Mesh::GetTriangleTrait(Offset triangleIndex) const { + const auto indices = GetTriangleIndices(triangleIndex); + const auto soughtt = GetData(0); + if (not soughtt or not *soughtt) + return {}; + + Any soughtDecayed; + if (soughtt->template CastsTo()) + soughtDecayed = soughtt->template ReinterpretAs(); + else if (soughtt->template CastsTo()) + soughtDecayed = soughtt->template ReinterpretAs(); + else + soughtDecayed = *soughtt; + + Any result; + result.InsertBlock(IndexBack, soughtDecayed.GetElement(indices[0])); + result.InsertBlock(IndexBack, soughtDecayed.GetElement(indices[1])); + result.InsertBlock(IndexBack, soughtDecayed.GetElement(indices[2])); + return result; + } + + /// Get texture mapping mode + /// @return the texturing mode + LANGULUS(INLINED) + Math::MapMode Mesh::GetTextureMapper() const noexcept { + return mView.mTextureMapping; + } + + /// Get the geometry view (const) + /// @return the geometry view + LANGULUS(INLINED) + const MeshView& Mesh::GetView() const noexcept { + return mView; + } + + /// Get the geometry view + /// @return the geometry view + LANGULUS(INLINED) + MeshView& Mesh::GetView() noexcept { + return mView; + } + +} // namespace Langulus::A diff --git a/include/Langulus/Physical.hpp b/include/Langulus/Physical.hpp new file mode 100644 index 0000000..7da8e69 --- /dev/null +++ b/include/Langulus/Physical.hpp @@ -0,0 +1,74 @@ +/// +/// Langulus::Entity +/// Copyright (c) 2013 Dimo Markov +/// Part of the Langulus framework, see https://langulus.com +/// +/// Distributed under GNU General Public License v3+ +/// See LICENSE file, or https://www.gnu.org/licenses +/// +#pragma once +#include "Module.hpp" +#include "Unit.hpp" +#include "Runtime.hpp" +#include +#include +#include +#include +#include +#include + + +namespace Langulus::A +{ + + /// + /// Abstract physical module + /// + struct PhysicalModule : Module { + LANGULUS_BASES(Module); + using Module::Module; + }; + + /// + /// Abstract physical unit + /// + struct Physical : Unit { + LANGULUS_BASES(Unit); + using Unit::Unit; + }; + + /// + /// Abstract physical world unit + /// + struct World : Physical { + LANGULUS(PRODUCER) PhysicalModule; + LANGULUS_BASES(Physical); + using Physical::Physical; + }; + + /// + /// Abstract physical instance unit + /// + struct Instance : Physical { + LANGULUS(PRODUCER) World; + LANGULUS_BASES(Physical); + using Physical::Physical; + + NOD() virtual bool Cull(const LOD&) const noexcept = 0; + NOD() virtual Level GetLevel() const noexcept = 0; + NOD() virtual Mat4 GetModelTransform(const LOD&) const noexcept = 0; + NOD() virtual Mat4 GetModelTransform(const Level& = {}) const noexcept = 0; + NOD() virtual Mat4 GetViewTransform(const LOD&) const noexcept = 0; + NOD() virtual Mat4 GetViewTransform(const Level& = {}) const noexcept = 0; + }; + +} // namespace Langulus::A + +namespace Langulus::CT +{ + + /// A concept for any kind of a physical unit + template + concept Physical = DerivedFrom; + +} // namespace Langulus::CT diff --git a/include/Langulus/Platform.hpp b/include/Langulus/Platform.hpp new file mode 100644 index 0000000..58e7fa3 --- /dev/null +++ b/include/Langulus/Platform.hpp @@ -0,0 +1,69 @@ +/// +/// Langulus::Entity +/// Copyright (c) 2013 Dimo Markov +/// Part of the Langulus framework, see https://langulus.com +/// +/// Distributed under GNU General Public License v3+ +/// See LICENSE file, or https://www.gnu.org/licenses +/// +#pragma once +#include "../Entity/Thing.hpp" +#include + +LANGULUS_DEFINE_TRAIT(Cursor, + "Enables or disables cursor for window"); +LANGULUS_DEFINE_TRAIT(Monitor, + "Monitor to which window is bound, making it fullscreen"); +LANGULUS_DEFINE_TRAIT(MousePosition, + "Mouse position, relative to a window"); +LANGULUS_DEFINE_TRAIT(MouseScroll, + "Mouse scroll for window"); +LANGULUS_DEFINE_TRAIT(NativeWindowHandle, + "Native window handle"); + + +namespace Langulus::A +{ + + /// + /// Abstract platform module + /// + struct PlatformModule : Module { + LANGULUS_BASES(Module); + using Module::Module; + }; + + /// + /// Abstract platform unit + /// + struct Platform : Unit { + LANGULUS_BASES(Unit); + using Unit::Unit; + }; + + /// + /// Abstract platform window + /// + struct Window : Platform { + LANGULUS(PRODUCER) PlatformModule; + LANGULUS_BASES(Platform); + using Platform::Platform; + using Scale2 = Math::Scale2; + + NOD() virtual void* GetNativeHandle() const noexcept = 0; + NOD() virtual Scale2 GetSize() const noexcept = 0; + NOD() virtual bool IsMinimized() const noexcept = 0; + }; + + /// + /// Abstract platform cursor + /// + struct Cursor : Platform { + LANGULUS(PRODUCER) PlatformModule; + LANGULUS_BASES(Platform); + using Platform::Platform; + }; + +} // namespace Langulus::A + +#include "Platform.inl" \ No newline at end of file diff --git a/include/Entity/External.hpp b/include/Langulus/Platform.inl similarity index 72% rename from include/Entity/External.hpp rename to include/Langulus/Platform.inl index be3e733..d2a88a9 100644 --- a/include/Entity/External.hpp +++ b/include/Langulus/Platform.inl @@ -7,12 +7,10 @@ /// See LICENSE file, or https://www.gnu.org/licenses /// #pragma once -#include "Thing.hpp" -#include "Unit.hpp" +#include "Platform.hpp" -#include "../../source/Hierarchy.hpp" -#include "../../source/Hierarchy-Seek.inl" -#include "../../source/Hierarchy-Gather.inl" -#include "../../source/External.hpp" -#include "../../source/External.inl" \ No newline at end of file +namespace Langulus::A +{ + +} // namespace Langulus::A diff --git a/include/Langulus/UI.hpp b/include/Langulus/UI.hpp new file mode 100644 index 0000000..2973d12 --- /dev/null +++ b/include/Langulus/UI.hpp @@ -0,0 +1,76 @@ +/// +/// Langulus::Entity +/// Copyright (c) 2013 Dimo Markov +/// Part of the Langulus framework, see https://langulus.com +/// +/// Distributed under GNU General Public License v3+ +/// See LICENSE file, or https://www.gnu.org/licenses +/// +#pragma once +#include "Module.hpp" +#include "Unit.hpp" +#include "Runtime.hpp" +#include +#include +#include +#include +#include +#include + + +namespace Langulus::A::UI +{ + + /// + /// Abstract UI module + /// + struct Module : A::Module { + LANGULUS_BASES(Entity::Module); + using A::Module::Module; + }; + + /// + /// Abstract UI unit + /// + struct Unit : A::Unit { + LANGULUS(PRODUCER) UI::Module; + LANGULUS_BASES(Entity::Unit); + using A::Unit::Unit; + }; + + /// + /// Abstract UI system + /// + struct System : UI::Unit { + LANGULUS_BASES(UI::Unit); + using UI::Unit::Unit; + }; + + /// + /// Abstract UI button + /// + struct Button : UI::Unit { + LANGULUS(PRODUCER) UI::System; + LANGULUS_BASES(UI::Unit); + using UI::Unit::Unit; + }; + + /// + /// Abstract UI text field + /// + struct Text : UI::Unit { + LANGULUS(PRODUCER) UI::System; + LANGULUS_BASES(UI::Unit); + using UI::Unit::Unit; + }; + + /// + /// Abstract UI input field + /// + struct Input : UI::Unit { + LANGULUS(PRODUCER) UI::System; + LANGULUS_BASES(UI::Unit); + using UI::Unit::Unit; + }; + +} // namespace Langulus::A::UI \ No newline at end of file diff --git a/source/Common.hpp b/source/Common.hpp index 1375555..10ad5f5 100644 --- a/source/Common.hpp +++ b/source/Common.hpp @@ -7,6 +7,12 @@ /// See LICENSE file, or https://www.gnu.org/licenses /// #pragma once +#include +#include +#include +#include +#include +#include #include #include @@ -17,24 +23,19 @@ #endif -namespace Langulus::Entity +namespace Langulus { - using namespace ::Langulus::Anyness; + using namespace Anyness; + using namespace Flow; - using Flow::Verb; - using Flow::Seek; - using Flow::Resolvable; - using Flow::Temporal; - using Flow::Code; +} // namespace Langulus::Entity - // - // Some predeclarations: +namespace Langulus::Entity +{ - struct Unit; class Thing; class Runtime; - class Module; struct Hierarchy; } // namespace Langulus::Entity @@ -42,6 +43,9 @@ namespace Langulus::Entity namespace Langulus::A { + struct Unit; + class Module; + struct PlatformModule; struct Platform; struct Window; @@ -70,6 +74,18 @@ namespace Langulus::A struct Material; struct Image; + namespace UI + { + + struct Module; + struct Unit; + struct System; + struct Button; + struct Text; + struct Input; + + } // namespace Langulus::A::UI + } // namespace Langulus::A /// Make the rest of the code aware, that Langulus::Entity has been included diff --git a/source/External.hpp b/source/External.hpp deleted file mode 100644 index 5748132..0000000 --- a/source/External.hpp +++ /dev/null @@ -1,634 +0,0 @@ -/// -/// Langulus::Entity -/// Copyright (c) 2013 Dimo Markov -/// Part of the Langulus framework, see https://langulus.com -/// -/// Distributed under GNU General Public License v3+ -/// See LICENSE file, or https://www.gnu.org/licenses -/// -#pragma once -#include "Module.hpp" -#include "Unit.hpp" -#include "Runtime.hpp" -#include -#include -#include -#include -#include -#include - -LANGULUS_DEFINE_TRAIT(Cursor, - "Enables or disables cursor for window"); -LANGULUS_DEFINE_TRAIT(Monitor, - "Monitor to which window is bound, making it fullscreen"); -LANGULUS_DEFINE_TRAIT(MousePosition, - "Mouse position, relative to a window"); -LANGULUS_DEFINE_TRAIT(MouseScroll, - "Mouse scroll for window"); -LANGULUS_DEFINE_TRAIT(NativeWindowHandle, - "Native window handle"); -LANGULUS_DEFINE_TRAIT(Shader, - "Shader unit"); -LANGULUS_DEFINE_TRAIT(Material, - "Material unit"); -LANGULUS_DEFINE_TRAIT(Image, - "Image unit"); -LANGULUS_DEFINE_TRAIT(Mesh, - "Mesh unit"); -LANGULUS_DEFINE_TRAIT(FOV, - "Horizontal field of view angle, usually a real number"); -LANGULUS_DEFINE_TRAIT(AspectRatio, - "Aspect ratio trait (width / height), usually a real number"); -LANGULUS_DEFINE_TRAIT(Viewport, - "Viewport and depth clipping, usually a Range4"); - -LANGULUS_EXCEPTION(Image); -LANGULUS_EXCEPTION(Mesh); - - -namespace Langulus -{ - using namespace Langulus::Flow; - using namespace Langulus::Anyness; - using namespace Langulus::Entity; - using namespace Langulus::Math; - - /// - /// Vertex/index buffer view - /// - struct MeshView { - // Number of primitives - uint32_t mPrimitiveCount {}; - // Starting primitive - uint32_t mPrimitiveStart {}; - // Number of indices - uint32_t mIndexCount {}; - // Starting index - uint32_t mIndexStart {}; - // Data topology - DMeta mTopology {}; - // Double-sidedness - bool mBilateral {}; - // Texture mapping mode - MapMode mTextureMapping {}; - - bool operator == (const MeshView&) const noexcept; - - NOD() MeshView Decay() const; - NOD() Hash GetHash() const noexcept; - }; - - - /// - /// Universal pixel buffer view - /// - struct ImageView { - uint32_t mWidth {1}; - uint32_t mHeight {1}; - uint32_t mDepth {1}; - uint32_t mFrames {1}; - DMeta mFormat {}; - // Reverse RGBA to BGRA - // This is not a scalable solution and would eventually fail - bool mReverseFormat {}; - - bool operator == (const ImageView&) const noexcept; - - NOD() constexpr uint32_t GetPixelCount() const noexcept; - NOD() constexpr uint32_t GetDimensionCount() const noexcept; - NOD() Size GetPixelBytesize() const noexcept; - NOD() Size GetBytesize() const noexcept; - NOD() uint32_t GetChannelCount() const noexcept; - NOD() Hash GetHash() const noexcept; - }; - - - /// - /// Shader stages - /// - namespace ShaderStage - { - enum Enum : uint32_t { - Vertex = 0, // Vertex shader stage - Geometry, // Geometry shader stage - TessCtrl, // Tesselation control stage - TessEval, // Tesselation evaluation stage - Pixel, // Pixel shader stage - Compute, // Compute shader stage - - Counter // Shader stage counter (keep at end) - }; - - /// Shader names - constexpr Token Names[Enum::Counter] = { - "vertex", - "geometry", - "tesselation control", - "tesselation evaluation", - "fragment", - "compute" - }; - } - - - /// - /// Shader layout tokens - /// - namespace ShaderToken - { - constexpr Token Version = "//#VERSION\n"; - constexpr Token Defines = "//#DEFINES\n"; - constexpr Token Input = "//#INPUT\n"; - constexpr Token Output = "//#OUTPUT\n"; - constexpr Token Dependencies = "//#DEPENDENCY\n"; - constexpr Token Colorize = "//#COLORIZE\n"; - constexpr Token Transform = "//#TRANSFORM\n"; - constexpr Token Position = "//#POSITION\n"; - constexpr Token Uniform = "//#UNIFORM\n"; - constexpr Token Texturize = "//#TEXTURIZE\n"; - constexpr Token Functions = "//#FUNCTIONS\n"; - } - -} // namespace Langulus - -namespace Langulus::A -{ - - /// - /// Abstract platform module - /// - struct PlatformModule : Module { - LANGULUS_BASES(Module); - using Module::Module; - }; - - /// - /// Abstract platform unit - /// - struct Platform : Unit { - LANGULUS_BASES(Unit); - using Unit::Unit; - }; - - /// - /// Abstract platform window - /// - struct Window : Platform { - LANGULUS(PRODUCER) PlatformModule; - LANGULUS_BASES(Platform); - using Platform::Platform; - - NOD() virtual void* GetNativeHandle() const noexcept = 0; - NOD() virtual Scale2 GetSize() const noexcept = 0; - NOD() virtual bool IsMinimized() const noexcept = 0; - }; - - /// - /// Abstract platform cursor - /// - struct Cursor : Platform { - LANGULUS(PRODUCER) PlatformModule; - LANGULUS_BASES(Platform); - using Platform::Platform; - }; - - /// - /// Abstract physical module - /// - struct PhysicalModule : Module { - LANGULUS_BASES(Module); - using Module::Module; - }; - - /// - /// Abstract physical unit - /// - struct Physical : Unit { - LANGULUS_BASES(Unit); - using Unit::Unit; - }; - - /// - /// Abstract physical world unit - /// - struct World : Physical { - LANGULUS(PRODUCER) PhysicalModule; - LANGULUS_BASES(Physical); - using Physical::Physical; - }; - - /// - /// Abstract physical instance unit - /// - struct Instance : Physical { - LANGULUS(PRODUCER) World; - LANGULUS_BASES(Physical); - using Physical::Physical; - - NOD() virtual bool Cull(const LOD&) const noexcept = 0; - NOD() virtual Level GetLevel() const noexcept = 0; - NOD() virtual Mat4 GetModelTransform(const LOD&) const noexcept = 0; - NOD() virtual Mat4 GetModelTransform(const Level& = {}) const noexcept = 0; - NOD() virtual Mat4 GetViewTransform(const LOD&) const noexcept = 0; - NOD() virtual Mat4 GetViewTransform(const Level& = {}) const noexcept = 0; - }; - - namespace UI - { - - /// - /// Abstract UI module - /// - struct Module : Entity::Module { - LANGULUS_BASES(Entity::Module); - using Entity::Module::Module; - }; - - /// - /// Abstract UI unit - /// - struct Unit : Entity::Unit { - LANGULUS(PRODUCER) UI::Module; - LANGULUS_BASES(Entity::Unit); - using Entity::Unit::Unit; - }; - - /// - /// Abstract UI system - /// - struct System : UI::Unit { - LANGULUS_BASES(UI::Unit); - using UI::Unit::Unit; - }; - - /// - /// Abstract UI button - /// - struct Button : UI::Unit { - LANGULUS(PRODUCER) UI::System; - LANGULUS_BASES(UI::Unit); - using UI::Unit::Unit; - }; - - /// - /// Abstract UI text field - /// - struct Text : UI::Unit { - LANGULUS(PRODUCER) UI::System; - LANGULUS_BASES(UI::Unit); - using UI::Unit::Unit; - }; - - /// - /// Abstract UI input field - /// - struct Input : UI::Unit { - LANGULUS(PRODUCER) UI::System; - LANGULUS_BASES(UI::Unit); - using UI::Unit::Unit; - }; - - } // namespace Langulus::A::UI - - struct File; - struct Folder; - - /// - /// Abstract file system module - /// - struct FileSystem : Module { - protected: - // Working directory path - // This is the only full path that is exposed to the system, - // unless LANGULUS(PARANOID) is enabled - Path mWorkingPath; - // Main data directory, for both reading and writing - // Relative to mWorkingPath - Path mMainDataPath; - - public: - LANGULUS_BASES(Module); - using Module::Module; - - NOD() virtual Ref GetFile (const Path&) = 0; - NOD() virtual Ref GetFolder(const Path&) = 0; - - NOD() const Path& GetWorkingPath() const noexcept; - NOD() const Path& GetDataPath() const noexcept; - }; - - /// - /// Abstract file interface - /// - struct File : Unit { - protected: - Path mFilePath; - bool mExists {}; - DMeta mFormat {}; - Size mByteCount {}; - bool mIsReadOnly {}; - - public: - LANGULUS(PRODUCER) FileSystem; - LANGULUS_BASES(Unit); - using Unit::Unit; - - NOD() bool Exists() const noexcept; - NOD() bool IsReadOnly() const noexcept; - NOD() const Path& GetFilePath() const noexcept; - NOD() DMeta GetFormat() const noexcept; - NOD() Size GetBytesize() const noexcept; - - NOD() virtual Any ReadAs(DMeta) const = 0; - - NOD() virtual Ref RelativeFile (const Path&) const = 0; - NOD() virtual Ref RelativeFolder(const Path&) const = 0; - - template - NOD() T ReadAs() const; - - /// Abstract file reader stream - struct Reader { - protected: - File* mFile; - Offset mProgress {}; - - public: - Reader() = delete; - Reader(File* f) - : mFile {f} {} - - File* GetFile() const noexcept { return mFile; } - - virtual Offset Read(Any&) = 0; - }; - - /// Abstract file writer stream - struct Writer { - protected: - File* mFile; - Offset mProgress {}; - bool mAppend = false; - - public: - Writer() = delete; - Writer(File* f, bool append) - : mFile {f}, mAppend {append} {} - - File* GetFile() const noexcept { return mFile; } - - virtual Offset Write(const Any&) = 0; - }; - - NOD() virtual Ref NewReader() const = 0; - NOD() virtual Ref NewWriter(bool append) const = 0; - }; - - /// - /// Abstract folder interface - /// - struct Folder : Unit { - protected: - Path mFolderPath; - bool mExists = false; - bool mIsReadOnly = false; - - public: - LANGULUS(PRODUCER) FileSystem; - LANGULUS_BASES(Unit); - using Unit::Unit; - - NOD() bool Exists() const noexcept; - NOD() bool IsReadOnly() const noexcept; - NOD() const Path& GetFolderPath() const noexcept; - - NOD() virtual Ref RelativeFile (const Path&) const = 0; - NOD() virtual Ref RelativeFolder(const Path&) const = 0; - }; - - /// - /// Abstract graphics module - /// - struct GraphicsModule : Module { - LANGULUS_BASES(Module); - using Module::Module; - }; - - /// - /// Abstract graphics units - /// - struct Graphics : Unit { - LANGULUS_BASES(Unit); - using Unit::Unit; - }; - - /// - /// Abstract graphics renderer - /// - struct Renderer : Graphics { - LANGULUS(PRODUCER) GraphicsModule; - LANGULUS_BASES(Graphics); - using Graphics::Graphics; - }; - - /// - /// Abstract graphics layer - /// - struct Layer : Graphics { - LANGULUS(PRODUCER) Renderer; - LANGULUS_BASES(Graphics); - using Graphics::Graphics; - }; - - /// - /// Abstract graphics camera - /// - struct Camera : Graphics { - LANGULUS(PRODUCER) Layer; - LANGULUS_BASES(Graphics); - using Graphics::Graphics; - }; - - /// - /// Abstract graphics renderable - /// - struct Renderable : Graphics { - LANGULUS(PRODUCER) Layer; - LANGULUS_BASES(Graphics); - using Graphics::Graphics; - }; - - /// - /// Abstract graphics light - /// - struct Light : Graphics { - LANGULUS(PRODUCER) Layer; - LANGULUS_BASES(Graphics); - using Graphics::Graphics; - }; - - /// - /// Abstract asset module - /// - struct AssetModule : Module { - LANGULUS_BASES(Entity::Module); - using Module::Module; - }; - - /// - /// Abstract asset unit - /// - struct Asset : Unit, ProducedFrom { - LANGULUS(PRODUCER) AssetModule; - LANGULUS_BASES(Unit); - - Asset(DMeta, AssetModule*, const Neat&); - - using Data = Any; - using DataList = TAny; - using DataListMap = TUnorderedMap; - - protected: - NOD() const DataListMap& GetDataListMap() const noexcept; - - // Map of lists of generated data - DataListMap mDataListMap; - - public: - virtual bool Generate(TMeta, Offset = 0) = 0; - - template class S, CT::Block B> - requires CT::Semantic> - void Commit(S&&); - - template - NOD() const Data* GetData(Offset = 0) const noexcept; - NOD() const Data* GetData(TMeta, Offset = 0) const noexcept; - - template - NOD() const DataList* GetDataList() const noexcept; - NOD() const DataList* GetDataList(TMeta) const noexcept; - }; - - /// - /// Abstract geometry content - /// - struct Mesh : Asset { - LANGULUS_BASES(Asset); - using Asset::Asset; - - protected: - MeshView mView; - - public: - template - NOD() bool CheckTopology() const; - NOD() DMeta GetTopology() const noexcept; - - NOD() MapMode GetTextureMapper() const noexcept; - - NOD() const MeshView& GetView() const noexcept; - NOD() MeshView& GetView() noexcept; - - NOD() virtual Ref GetLOD(const LOD&) const = 0; - - NOD() Vec2u InnerGetIndices(const Data*, const Vec2u&) const; - NOD() Vec3u InnerGetIndices(const Data*, const Vec3u&) const; - - // - NOD() bool MadeOfPoints() const noexcept; - NOD() Count GetPointCount() const; - template - NOD() Any GetPointTrait(Offset) const; - - // - NOD() bool MadeOfLines() const noexcept; - NOD() Count GetLineCount() const; - NOD() Vec2u GetLineIndices(Offset) const; - template - NOD() Any GetLineTrait(Offset) const; - - // - NOD() bool MadeOfTriangles() const noexcept; - NOD() Count GetTriangleCount() const; - NOD() Vec3u GetTriangleIndices(Offset) const; - template - NOD() Any GetTriangleTrait(Offset) const; - }; - - /// - /// Abstract material content - /// - struct Material : Asset { - LANGULUS_BASES(Asset); - using Asset::Asset; - - NOD() virtual Ref GetLOD(const LOD&) const = 0; - - NOD() const TraitList& GetInputs(Rate) const; - NOD() const TraitList& GetInputs(Offset) const; - - NOD() const TraitList& GetOutputs(Rate) const; - NOD() const TraitList& GetOutputs(Offset) const; - }; - - /// - /// Abstract texture content - /// - struct Image : Asset { - LANGULUS_BASES(Asset); - using Asset::Asset; - - protected: - ImageView mView; - - public: - NOD() virtual Ref GetLOD(const LOD&) const = 0; - NOD() virtual void* GetGPUHandle() const noexcept = 0; - - NOD() DMeta GetFormat() const noexcept; - NOD() const ImageView& GetView() const noexcept; - NOD() ImageView& GetView() noexcept; - - template - auto ForEachPixel(F&&) const; - - template class S, CT::Block B> - requires CT::Semantic> - void Upload(S&&); - }; - - /// - /// Abstract font content - /// - struct Font : Image { - LANGULUS_BASES(Image); - using Image::Image; - }; - -} // namespace Langulus::A - -namespace Langulus::CT -{ - - /// A concept for any kind of a graphics unit - template - concept Graphics = DerivedFrom; - - /// A concept for any kind of a physical unit - template - concept Physical = DerivedFrom; - - /// A concept for any kind of content unit - template - concept Asset = DerivedFrom; - - /// A concept for any kind of image content unit - template - concept Image = DerivedFrom; - - /// A concept for any kind of geometric content unit - template - concept Mesh = DerivedFrom; - -} // namespace Langulus::CT diff --git a/source/External.inl b/source/External.inl deleted file mode 100644 index 4b1bccb..0000000 --- a/source/External.inl +++ /dev/null @@ -1,837 +0,0 @@ -/// -/// Langulus::Entity -/// Copyright (c) 2013 Dimo Markov -/// Part of the Langulus framework, see https://langulus.com -/// -/// Distributed under GNU General Public License v3+ -/// See LICENSE file, or https://www.gnu.org/licenses -/// -#pragma once -#include "External.hpp" -#include -#include -#include -#include - - -namespace Langulus -{ - - /// - /// Vertex/index buffer view - /// - - /// Compare geometry views - /// @param rhs - the geometry view to compare against - /// @return true if both views are the same - LANGULUS(INLINED) - bool MeshView::operator == (const MeshView& rhs) const noexcept { - return mPrimitiveCount == rhs.mPrimitiveCount - and mPrimitiveStart == rhs.mPrimitiveStart - and mIndexCount == rhs.mIndexCount - and mIndexStart == rhs.mIndexStart - and (mTopology == rhs.mTopology - or (mTopology and mTopology->IsExact(rhs.mTopology))) - and mBilateral == rhs.mBilateral; - } - - /// Decay the geometry view to a list of points - /// @return the decayed view - LANGULUS(INLINED) - MeshView MeshView::Decay() const { - LANGULUS_ASSERT(mPrimitiveCount and mTopology, Convert, "Bad vertex view"); - if (mTopology->template Is()) - return *this; - - MeshView result {*this}; - result.mTopology = MetaOf(); - - // mPrimitiveCount corresponds to the number of points in these - // cases: - if ( mTopology->template Is() - or mTopology->template Is() - or mTopology->template Is() - or mTopology->template Is()) - return result; - - if (mTopology->template Is()) { - // Decay triangles to points - result.mPrimitiveCount *= 3; - } - if (mTopology->template Is()) { - // Decay lines to points - result.mPrimitiveCount *= 2; - } - else LANGULUS_THROW(Convert, "Bad primitive type"); - - return result; - } - - /// Get the hash of a normalized descriptor (cached) - /// @return the hash - LANGULUS(INLINED) - Hash MeshView::GetHash() const noexcept { - return HashOf( - mPrimitiveCount, mPrimitiveStart, mIndexCount, mIndexStart, - mTopology, mBilateral, mTextureMapping - ); - } - - - /// - /// Universal pixel buffer view - /// - - /// Compare texture views - /// @param rhs - the texture view to compare against - /// @return true if both views are the same - LANGULUS(INLINED) - bool ImageView::operator == (const ImageView& rhs) const noexcept { - return mWidth == rhs.mWidth - and mHeight == rhs.mHeight - and mDepth == rhs.mDepth - and mFrames == rhs.mFrames - and mFormat == rhs.mFormat; - } - - /// Get the number of pixels in the texture - /// @return the number of pixels - LANGULUS(INLINED) - constexpr uint32_t ImageView::GetPixelCount() const noexcept { - return mWidth * mHeight * mDepth * mFrames; - } - - /// Get number of dimensions used for the image - /// @return return up to 4 dimensions - LANGULUS(INLINED) - constexpr uint32_t ImageView::GetDimensionCount() const noexcept { - return (mWidth > 1) + (mHeight > 1) + (mDepth > 1) + (mFrames > 1); - } - - /// Get the size in bytes for a single pixel - /// @return the size in bytes - LANGULUS(INLINED) - Size ImageView::GetPixelBytesize() const noexcept { - return mFormat ? mFormat->mSize : Size {0}; - } - - /// Get the bytesize of the entire image across all dimensions - /// @return the bytesize of the entire image - LANGULUS(INLINED) - Size ImageView::GetBytesize() const noexcept { - return GetPixelCount() * GetPixelBytesize(); - } - - /// Get the number of channels inside the color format - /// @return the number of channels - LANGULUS(INLINED) - uint32_t ImageView::GetChannelCount() const noexcept { - return static_cast(mFormat->GetMemberCount()); - } - - /// Get the hash of a normalized descriptor (cached) - /// @return the hash - LANGULUS(INLINED) - Hash ImageView::GetHash() const noexcept { - return HashOf( - mWidth, mHeight, mDepth, mFrames, - mFormat, mReverseFormat - ); - } - -} // namespace Langulus - -namespace Langulus::A -{ - - /// - /// Abstract file system interface - /// - - /// Get the current working path (where the main exe was executed) - /// @return the path - LANGULUS(INLINED) - const Path& FileSystem::GetWorkingPath() const noexcept { - return mWorkingPath; - } - - /// Get the current data path, like GetWorkingPath() / "data" - /// @return the path - LANGULUS(INLINED) - const Path& FileSystem::GetDataPath() const noexcept { - return mMainDataPath; - } - - - /// - /// Abstract file interface - /// - - /// Check if file physically exists - /// @return true if file exists - LANGULUS(INLINED) - bool File::Exists() const noexcept { - return mExists; - } - - /// Check if file is read-only - /// @return true if file exists and is read-only - LANGULUS(INLINED) - bool File::IsReadOnly() const noexcept { - return mIsReadOnly; - } - - /// Check file format, that is deduced from file extension, and compared - /// against all reflected file extensions - /// @return the file format - LANGULUS(INLINED) - DMeta File::GetFormat() const noexcept { - return mFormat; - } - - /// Get the size of the file in bytes (if file exists) - /// @return the size of the file in bytes, or 0 if it doesn't exist - LANGULUS(INLINED) - Size File::GetBytesize() const noexcept { - return mByteCount; - } - - /// Get the full path of the file - /// @return a reference to the path - LANGULUS(INLINED) - const Path& File::GetFilePath() const noexcept { - return mFilePath; - } - - /// Read a file and attempt to deserialize it as provided type T - /// Throws if deserialization isn't possible - /// @tparam T - the type to deserialize as, if possible - /// @return the deserialized instance of T - template LANGULUS(INLINED) - T File::ReadAs() const { - return ReadAs(MetaDataOf()).template As(); - } - - - /// - /// Abstract folder interface - /// - - /// Check if folder physically exists - /// @return true if folder exists - LANGULUS(INLINED) - bool Folder::Exists() const noexcept { - return mExists; - } - - /// Check if file is read-only - /// @return true if file exists and is read-only - LANGULUS(INLINED) - bool Folder::IsReadOnly() const noexcept { - return mIsReadOnly; - } - - /// Get the full path of the folder - /// @return a reference to the path - LANGULUS(INLINED) - const Path& Folder::GetFolderPath() const noexcept { - return mFolderPath; - } - - - /// - /// Abstract content unit - /// - - /// Asset constructor - /// @param type - concrete type of the asset - /// @param producer - the asset library and producer - /// @param desc - messy descriptor for the content - LANGULUS(INLINED) - Asset::Asset(RTTI::DMeta type, AssetModule* producer, const Neat& desc) - : Unit {type} - , ProducedFrom {producer, desc} {} - - /// Get the entire content data map - /// @attention this doesn't generate any data - /// @return a reference to the contents - LANGULUS(INLINED) - const Asset::DataListMap& Asset::GetDataListMap() const noexcept { - return mDataListMap; - } - - /// Get a single data entry from the contents - /// @tparam T - the trait to search for - /// @param index - the Nth data associated to the trait - /// @return a pointer to the data entry, or nullptr if none exists - template LANGULUS(INLINED) - const Asset::Data* Asset::GetData(Offset index) const noexcept { - return GetData(MetaTraitOf(), index); - } - - /// Get a single data entry from the contents - /// @param trait - the trait to search for - /// @param index - the Nth data associated to the trait - /// @return a pointer to the data entry, or nullptr if none exists - LANGULUS(INLINED) - const Asset::Data* Asset::GetData(TMeta trait, Offset index) const noexcept { - if (not const_cast(this)->Generate(trait, index)) - return nullptr; - - const auto datalist = GetDataList(trait); - return datalist and datalist->GetCount() > index - ? &(*datalist)[index] - : nullptr; - } - - /// Get a data list from the contents - /// @tparam T - the trait to search for - /// @return a pointer to the data list, or nullptr if none exists - template - LANGULUS(INLINED) - const Asset::DataList* Asset::GetDataList() const noexcept { - return GetDataList(MetaTraitOf()); - } - - /// Get a data list from the contents - /// @param trait - the trait to search for - /// @return a pointer to the data list, or nullptr if none exists - LANGULUS(INLINED) - const Asset::DataList* Asset::GetDataList(TMeta trait) const noexcept { - if (not const_cast(this)->Generate(trait)) - return nullptr; - - const auto found = mDataListMap.FindIt(trait); - return found ? found.mValue : nullptr; - } - - /// Commit data to an asset - /// @attention data is always commited, even if such trait already exists - /// @tparam T - data trait, the intent we're commiting with - /// @param content - the data and semantic to commit - template class S, CT::Block B> - requires CT::Semantic> LANGULUS(INLINED) - void Asset::Commit(S&& content) { - const auto found = mDataListMap.FindIt(MetaTraitOf()); - if (found) - *found.mValue << Any {content.Forward()}; - else - mDataListMap.Insert(MetaTraitOf(), content.Forward()); - } - - - /// - /// Abstract geometry content - /// - - /// Get the topology of the geometry - /// @return the topology type - LANGULUS(INLINED) - DMeta Mesh::GetTopology() const noexcept { - return mView.mTopology; - } - - /// Check if topology matches one of the specified types - /// @tparam T1, TN - types to check - /// @return true if T matches one of the topology types - template LANGULUS(INLINED) - bool Mesh::CheckTopology() const { - return mView.mTopology == MetaDataOf() - or ((mView.mTopology == MetaDataOf()) or ...); - } - - /// Helper that indirects in case there is an index buffer - /// @param indices - index buffer - /// @param where - line indices - /// @return the (eventually indirected) line indices - inline Math::Vec2u Mesh::InnerGetIndices(const Data* indices, const Math::Vec2u& where) const { - if (not indices or not *indices) - return where; - - if (indices->IsExact()) { - auto idx = indices->As(); - return {idx[where[0]], idx[where[1]]}; - } - - if (indices->IsExact()) { - auto idx = indices->As(); - return {idx[where[0]], idx[where[1]]}; - } - - if (indices->IsExact()) { - auto idx = indices->As(); - return {idx[where[0]], idx[where[1]]}; - } - - if (indices->IsExact()) { - auto idx = indices->As(); - return { - static_cast(idx[where[0]]), - static_cast(idx[where[1]]) - }; - } - - LANGULUS_THROW(Access, "Trying to get index from incompatible index buffer"); - } - - /// Helper that indirects in case there is an index buffer - /// @param indices - index buffer - /// @param where - triangle indices - /// @return the (eventually indirected) triangle indices - inline Math::Vec3u Mesh::InnerGetIndices(const Data* indices, const Math::Vec3u& where) const { - if (not indices or not *indices) - return where; - - if (indices->IsExact()) { - auto idx = indices->As(); - return {idx[where[0]], idx[where[1]], idx[where[2]]}; - } - - if (indices->IsExact()) { - auto idx = indices->As(); - return {idx[where[0]], idx[where[1]], idx[where[2]]}; - } - - if (indices->IsExact()) { - auto idx = indices->As(); - return {idx[where[0]], idx[where[1]], idx[where[2]]}; - } - - if (indices->IsExact()) { - auto idx = indices->As(); - return { - static_cast(idx[where[0]]), - static_cast(idx[where[1]]), - static_cast(idx[where[2]]) - }; - } - - LANGULUS_THROW(Access, "Trying to get index from incompatible index buffer"); - } - - /// Is topology a point list? - /// @return true if geometry is made of points - LANGULUS(INLINED) - bool Mesh::MadeOfPoints() const noexcept { - return CheckTopology(); - } - - /// Get the number of points inside the geometry - /// @return the number of points - LANGULUS(INLINED) - Count Mesh::GetPointCount() const { - TODO(); - return {}; - } - - template - Anyness::Any Mesh::GetPointTrait(Offset) const { - TODO(); - return {}; - } - - /// Is topology line list/strip/loop? - /// @return true if geometry is made of lines - LANGULUS(INLINED) - bool Mesh::MadeOfLines() const noexcept { - return CheckTopology(); - } - - /// Get the number of lines inside the geometry - /// @return the number of points - inline Count Mesh::GetLineCount() const { - if (MadeOfPoints()) - return 0; - - if (CheckTopology()) { - if (mView.mIndexCount > 1) - return mView.mIndexCount / 2; - else { - auto decayed = mView.Decay(); - if (decayed.mPrimitiveCount > 1) - return decayed.mPrimitiveCount / 2; - } - return 0; - } - else if (CheckTopology()) { - if (mView.mIndexCount > 1) - return mView.mIndexCount - 1; - else if (mView.mPrimitiveCount > 1) - return mView.mPrimitiveCount - 1; - return 0; - } - else if (CheckTopology()) { - if (mView.mIndexCount > 1) - return mView.mIndexCount; - else if (mView.mPrimitiveCount > 1) - return mView.mPrimitiveCount; - return 0; - } - else if (CheckTopology()) { - if (mView.mIndexCount > 2) - return mView.mIndexCount / 3; - else { - auto decayed = mView.Decay(); - if (decayed.mPrimitiveCount > 2) - return decayed.mPrimitiveCount; - } - return 0; - } - else if (CheckTopology()) { - if (mView.mIndexCount > 2) - return 1 + (mView.mIndexCount - 2) * 2; - else if (mView.mPrimitiveCount > 2) - return 1 + (mView.mPrimitiveCount - 2) * 2; - return 0; - } - - LANGULUS_THROW(Access, "Trying to count lines for unknown topology"); - } - - /// Get the point indices of a given line - /// @param index - line index - /// @return the point indices as a 32bit unsigned 2D vector - inline Vec2u Mesh::GetLineIndices(Offset index) const { - const auto indices = GetData(); - - if (CheckTopology()) { - return InnerGetIndices(indices, Vec2u(index * 2, index * 2 + 1)); - } - else if (CheckTopology()) { - return InnerGetIndices(indices, Vec2u(index > 0 ? index - 1 : 0, index > 0 ? index : 1)); - } - else if (CheckTopology()) { - if (index == GetLineCount() - 1) - return InnerGetIndices(indices, Vec2u(index, 0)); - else - return InnerGetIndices(indices, Vec2u(index > 0 ? index - 1 : 0, index > 0 ? index : 1)); - } - else if (CheckTopology()) { - switch (index % 3) { - case 0: case 1: - return InnerGetIndices(indices, Vec2u(index, index + 1)); - case 2: - return InnerGetIndices(indices, Vec2u(index, index - 2)); - } - } - else if (CheckTopology()) { - switch (index % 3) { - case 0: - return InnerGetIndices(indices, Vec2u(index == 0 ? 0 : index - 2, index == 0 ? 1 : index - 1)); - case 1: - return InnerGetIndices(indices, Vec2u(index - 1, index)); - case 2: - return InnerGetIndices(indices, Vec2u(index, index - 2)); - } - } - else if (CheckTopology()) { - switch (index % 3) { - case 0: - return InnerGetIndices(indices, Vec2u(0, index == 0 ? 1 : index - 1)); - case 1: - return InnerGetIndices(indices, Vec2u(index - 1, index)); - case 2: - return InnerGetIndices(indices, Vec2u(index, 0)); - } - } - - LANGULUS_THROW(Access, "Trying to count lines for unknown topology"); - } - - /// Get a specific property of a specific line - /// @tparam T - the trait to retrieve - /// @param lineIndex - the line index - /// @return data for the specific line - template - Any Mesh::GetLineTrait(Offset lineIndex) const { - const auto indices = GetLineIndices(lineIndex); - const auto soughtt = GetData(0); - if (not soughtt or not *soughtt) - return {}; - - Any soughtDecayed; - if (soughtt->template CastsTo()) - soughtDecayed = soughtt->template ReinterpretAs(); - else if (soughtt->template CastsTo()) - soughtDecayed = soughtt->template ReinterpretAs(); - else - soughtDecayed = *soughtt; - - Any result; - result.InsertBlock(IndexBack, soughtDecayed.GetElement(indices[0])); - result.InsertBlock(IndexBack, soughtDecayed.GetElement(indices[1])); - return result; - } - - /// Is geometry made up of triangles list/strip/fan? - /// @return true if geometry is made of triangles - LANGULUS(INLINED) - bool Mesh::MadeOfTriangles() const noexcept { - return CheckTopology(); - } - - /// Get the number of triangles inside the geometry - /// @return the number of points - inline Count Mesh::GetTriangleCount() const { - if (MadeOfPoints() or MadeOfLines()) - return 0; - - if (CheckTopology()) { - if (mView.mIndexCount > 2) - return mView.mIndexCount / 3; - - auto decayed = mView.Decay(); - LANGULUS_ASSERT(decayed.mPrimitiveCount % 3, Access, "Bad topology"); - return decayed.mPrimitiveCount / 3; - } - else if (CheckTopology()) { - if (mView.mIndexCount > 2) - return mView.mIndexCount - 2; - - LANGULUS_ASSERT(mView.mPrimitiveCount < 3, Access, "Bad topology"); - return mView.mPrimitiveCount - 2; - } - - LANGULUS_THROW(Access, "Trying to count triangles for unknown topology"); - } - - /// Get the indices of a given triangle - /// @param index - triangle index - /// @return the indices as a 32bit unsigned 3D vector - inline Vec3u Mesh::GetTriangleIndices(Offset index) const { - const auto indices = GetData(0); - - if (CheckTopology()) { - return InnerGetIndices(indices, Vec3u( - index * 3, - index * 3 + 1, - index * 3 + 2) - ); - } - else if (CheckTopology()) { - return InnerGetIndices(indices, Vec3u( - index == 0 ? 0 : index - 1, - index == 0 ? 1 : index, - index == 0 ? 2 : index + 1) - ); - } - else if (CheckTopology()) { - return InnerGetIndices(indices, Vec3u( - 0, - index == 0 ? 1 : index, - index == 0 ? 2 : index + 1) - ); - } - - LANGULUS_THROW(Access, "Trying to count triangles for unknown topology"); - } - - /// Get a specific property of a specific triangle - /// @tparam T - the trait to retrieve - /// @param triangleIndex - the triangle index - /// @return data for the specific triangle - template - Any Mesh::GetTriangleTrait(Offset triangleIndex) const { - const auto indices = GetTriangleIndices(triangleIndex); - const auto soughtt = GetData(0); - if (not soughtt or not *soughtt) - return {}; - - Any soughtDecayed; - if (soughtt->template CastsTo()) - soughtDecayed = soughtt->template ReinterpretAs(); - else if (soughtt->template CastsTo()) - soughtDecayed = soughtt->template ReinterpretAs(); - else - soughtDecayed = *soughtt; - - Any result; - result.InsertBlock(IndexBack, soughtDecayed.GetElement(indices[0])); - result.InsertBlock(IndexBack, soughtDecayed.GetElement(indices[1])); - result.InsertBlock(IndexBack, soughtDecayed.GetElement(indices[2])); - return result; - } - - /// Get texture mapping mode - /// @return the texturing mode - LANGULUS(INLINED) - Math::MapMode Mesh::GetTextureMapper() const noexcept { - return mView.mTextureMapping; - } - - /// Get the geometry view (const) - /// @return the geometry view - LANGULUS(INLINED) - const MeshView& Mesh::GetView() const noexcept { - return mView; - } - - /// Get the geometry view - /// @return the geometry view - LANGULUS(INLINED) - MeshView& Mesh::GetView() noexcept { - return mView; - } - - - /// - /// Abstract material content - /// - - /// Get input traits for a given rate (const) - /// @param rate - the rate - /// @return the input trait list - LANGULUS(INLINED) - const TraitList& Material::GetInputs(Rate rate) const { - return GetInputs(rate.GetInputIndex()); - } - - /// Get input traits for a given input offset (const) - /// @attention offset must be in the range [0; Rate::InputCount) - /// @param rate - the input offset - /// @return the input trait list - LANGULUS(INLINED) - const TraitList& Material::GetInputs(Offset rate) const { - LANGULUS_ASSUME(DevAssumes, - Asset::mDataListMap.ContainsKey(MetaOf()), - "Material doesn't contain inputs" - ); - LANGULUS_ASSUME(DevAssumes, - Asset::GetDataList()->GetCount() == Rate::InputCount, - "Material doesn't contain the correct number of rates" - ); - LANGULUS_ASSUME(DevAssumes, - rate < Rate::InputCount, - "Input offset out of range" - ); - - return *reinterpret_cast( - Asset::GetData(rate) - ); - } - - /// Get output traits for a given rate (const) - /// @param rate - the rate - /// @return the output trait list - LANGULUS(INLINED) - const TraitList& Material::GetOutputs(Rate rate) const { - return GetOutputs(rate.GetInputIndex()); - } - - /// Get output traits for a given input offset (const) - /// @attention offset must be in the range [0; Rate::InputCount) - /// @param rate - the input offset - /// @return the output trait list - LANGULUS(INLINED) - const TraitList& Material::GetOutputs(Offset rate) const { - LANGULUS_ASSUME(DevAssumes, - Asset::mDataListMap.ContainsKey(MetaOf()), - "Material doesn't contain inputs" - ); - LANGULUS_ASSUME(DevAssumes, - Asset::GetDataList()->GetCount() == Rate::InputCount, - "Material doesn't contain the correct number of rates" - ); - LANGULUS_ASSUME(DevAssumes, - rate < Rate::InputCount, - "Input offset out of range" - ); - - return *reinterpret_cast( - Asset::GetData(rate) - ); - } - - - /// - /// Abstract texture content - /// - - /// Get the pixel format of the texture - /// @return the pixel format type - LANGULUS(INLINED) - DMeta Image::GetFormat() const noexcept { - return mView.mFormat; - } - - /// Get the texture view (const) - /// @return the texture view - LANGULUS(INLINED) - const ImageView& Image::GetView() const noexcept { - return mView; - } - - /// Get the texture view - /// @return the texture view - LANGULUS(INLINED) - ImageView& Image::GetView() noexcept { - return mView; - } - - /// Execute a function for each pixel, represented by a desired type - /// @tparam F - the function signature (deducible) - /// @param call - the function to execute for each pixel - /// @return the number of pixels that were iterated - template - auto Image::ForEachPixel(F&& call) const { - auto pixels = GetData(); - - LANGULUS_ASSUME(DevAssumes, pixels and *pixels, - "No color data", " in ", Self()); - LANGULUS_ASSUME(DevAssumes, pixels->IsDense(), - "Image data is not dense", " for ", Self()); - LANGULUS_ASSUME(DevAssumes, - pixels->CastsTo() or pixels->CastsTo(), - "Image doesn't contain pixel data", - " - contains ", pixels->GetType(), " instead" - ); - - using A = Deref>; - using R = ReturnOf; - - static_assert(CT::Constant, "Color iterator must be constant"); - static_assert(CT::Dense, "Color iterator must be dense"); - - LANGULUS_ASSUME(DevAssumes, mView.mFormat->IsSimilar(), - "Iterator type is not compatible with contained color data"); - - // Iterate using the desired color type - UNUSED() Count counter = 0; - auto data = pixels->CastsTo() - ? pixels->Get().GetRawAs() - : pixels->GetRawAs(); - const auto dataEnd = data + mView.GetPixelCount(); - - while (data != dataEnd) { - if constexpr (CT::Bool) { - if (not call(*data)) - return counter; - ++counter; - } - else call(*data); - - ++data; - } - - if constexpr (CT::Bool) - return counter; - - //TODO map other kinds of pixel iterators? - } - - /// Upload raw data to the image by a semantic - /// @attention deletes any data previously commited - /// @param data - the block of data - template class S, CT::Block B> - requires CT::Semantic> LANGULUS(INLINED) - void Image::Upload(S&& data) { - // Check if provided data matches the view requirements - LANGULUS_ASSERT(mView.GetBytesize() == data->GetBytesize(), Image, - "Data is of the wrong size"); - - // Reset data and commit the new one - mDataListMap.Reset(); - Commit(data.Forward()); - } - -} // namespace Langulus::A diff --git a/source/Hierarchy-Gather.inl b/source/Hierarchy-Gather.inl index 01e0c48..0e75617 100644 --- a/source/Hierarchy-Gather.inl +++ b/source/Hierarchy-Gather.inl @@ -21,7 +21,7 @@ namespace Langulus::Entity /// @param meta - the units to seek for /// @return the gathered units that match the type TEMPLATE() template LANGULUS(INLINED) - TAny TME()::GatherUnits(DMeta meta) const { + TAny TME()::GatherUnits(DMeta meta) const { return const_cast(static_cast(this)) ->template GatherUnits(meta); } @@ -62,13 +62,13 @@ namespace Langulus::Entity #if LANGULUS_FEATURE(MANAGED_REFLECTION) TEMPLATE() template LANGULUS(INLINED) - TAny TME()::GatherUnits(const Token& token) { + TAny TME()::GatherUnits(const Token& token) { return static_cast(this) ->template GatherUnits(RTTI::GetMetaData(token)); } TEMPLATE() template LANGULUS(INLINED) - TAny TME()::GatherUnits(const Token& token) const { + TAny TME()::GatherUnits(const Token& token) const { return static_cast(this) ->template GatherUnits(RTTI::GetMetaData(token)); } @@ -100,7 +100,7 @@ namespace Langulus::Entity /// @return the gathered units that match the type template LANGULUS(INLINED) - TAny Hierarchy::GatherUnits(DMeta meta) { + TAny Hierarchy::GatherUnits(DMeta meta) { TAny result; for (auto owner : *this) result += owner->template GatherUnits(meta); diff --git a/source/Hierarchy-Seek.inl b/source/Hierarchy-Seek.inl index 1d9c361..c941a73 100644 --- a/source/Hierarchy-Seek.inl +++ b/source/Hierarchy-Seek.inl @@ -22,7 +22,7 @@ namespace Langulus::Entity /// @param offset - the match to return /// @return a pointer to the found unit, or nullptr if not found TEMPLATE() template LANGULUS(INLINED) - const Unit* TME()::SeekUnit(DMeta type, Index offset) const { + const A::Unit* TME()::SeekUnit(DMeta type, Index offset) const { return const_cast(static_cast(this)) ->template SeekUnit(type, offset); } @@ -47,7 +47,7 @@ namespace Langulus::Entity /// @param offset - the match to return /// @return a pointer to the found unit, or nullptr if not found TEMPLATE() template LANGULUS(INLINED) - const Unit* TME()::SeekUnitAux(const Neat& aux, DMeta type, Index offset) const { + const A::Unit* TME()::SeekUnitAux(const Neat& aux, DMeta type, Index offset) const { return const_cast(static_cast(this)) ->template SeekUnitAux(aux, type, offset); } @@ -71,7 +71,7 @@ namespace Langulus::Entity /// @param offset - the match to return /// @return a pointer to the found unit, or nullptr if not found TEMPLATE() template LANGULUS(INLINED) - const Unit* TME()::SeekUnitExt(DMeta type, const Neat& ext, Index offset) const { + const A::Unit* TME()::SeekUnitExt(DMeta type, const Neat& ext, Index offset) const { return const_cast(static_cast(this)) ->template SeekUnitExt(type, ext, offset); } @@ -97,7 +97,7 @@ namespace Langulus::Entity /// @param offset - the match to return /// @return a pointer to the found unit, or nullptr if not found TEMPLATE() template LANGULUS(INLINED) - const Unit* TME()::SeekUnitAuxExt(DMeta type, const Neat& aux, const Neat& ext, Index offset) const { + const A::Unit* TME()::SeekUnitAuxExt(DMeta type, const Neat& aux, const Neat& ext, Index offset) const { return const_cast(static_cast(this)) ->template SeekUnitAuxExt(type, aux, ext, offset); } @@ -199,25 +199,25 @@ namespace Langulus::Entity /// Available only when managed reflection is enabled /// TEMPLATE() template LANGULUS(INLINED) - Unit* TME()::SeekUnit(const Token& dataToken, Index offset) { + A::Unit* TME()::SeekUnit(const Token& dataToken, Index offset) { return static_cast(this) ->template SeekUnit(RTTI::GetMetaData(dataToken), offset); } TEMPLATE() template LANGULUS(INLINED) - const Unit* TME()::SeekUnit(const Token& dataToken, Index offset) const { + const A::Unit* TME()::SeekUnit(const Token& dataToken, Index offset) const { return static_cast(this) ->template SeekUnit(RTTI::GetMetaData(dataToken), offset); } TEMPLATE() template LANGULUS(INLINED) - Unit* TME()::SeekUnitAux(const Neat& aux, const Token& dataToken, Index offset) { + A::Unit* TME()::SeekUnitAux(const Neat& aux, const Token& dataToken, Index offset) { return static_cast(this) ->template SeekUnitAux(aux, RTTI::GetMetaData(dataToken), offset); } TEMPLATE() template LANGULUS(INLINED) - const Unit* TME()::SeekUnitAux(const Neat& aux, const Token& dataToken, Index offset) const { + const A::Unit* TME()::SeekUnitAux(const Neat& aux, const Token& dataToken, Index offset) const { return static_cast(this) ->template SeekUnitAux(aux, RTTI::GetMetaData(dataToken), offset); } @@ -268,7 +268,7 @@ namespace Langulus::Entity /// @param offset - which of the matches to return /// @return the found unit, or nullptr if no such unit was found template LANGULUS(INLINED) - Unit* Hierarchy::SeekUnit(DMeta meta, Index offset) { + A::Unit* Hierarchy::SeekUnit(DMeta meta, Index offset) { for (auto owner : *this) { Unit* result = owner->template SeekUnit(meta, offset); if (result) @@ -286,7 +286,7 @@ namespace Langulus::Entity /// @param offset - the index of the unit to return /// @return the unit if found, or nullptr otherwise template LANGULUS(INLINED) - Unit* Hierarchy::SeekUnitAux(const Neat& aux, DMeta meta, Index offset) { + A::Unit* Hierarchy::SeekUnitAux(const Neat& aux, DMeta meta, Index offset) { const Unit* result {}; // Scan descriptor even if hierarchy is empty @@ -347,7 +347,7 @@ namespace Langulus::Entity /// @param offset - the index of the unit to return /// @return the unit if found, or nullptr otherwise template LANGULUS(INLINED) - Unit* Hierarchy::SeekUnitExt(DMeta type, const Neat& ext, Index offset) { + A::Unit* Hierarchy::SeekUnitExt(DMeta type, const Neat& ext, Index offset) { for (auto owner : *this) { Unit* result = owner->template SeekUnitExt(type, ext, offset); if (result) @@ -366,7 +366,7 @@ namespace Langulus::Entity /// @param offset - the index of the unit to return /// @return a pointer to the found unit, or nullptr if not found template LANGULUS(INLINED) - Unit* Hierarchy::SeekUnitAuxExt(DMeta type, const Neat& aux, const Neat& ext, Index offset) { + A::Unit* Hierarchy::SeekUnitAuxExt(DMeta type, const Neat& aux, const Neat& ext, Index offset) { // Scan descriptor even if hierarchy is empty Unit* result {}; aux.ForEachDeep([&](const Unit* u) { diff --git a/source/Hierarchy.hpp b/source/Hierarchy.hpp index be5a4b0..a032b40 100644 --- a/source/Hierarchy.hpp +++ b/source/Hierarchy.hpp @@ -8,37 +8,11 @@ /// #pragma once #include "Module.hpp" -#include -#include -#include -namespace Langulus::Anyness -{ - - /// Execute a verb for all elements inside a type-erased constant block - /// @param verb - the verb to execute - /*template - Flow::Verb& TAny::Run(Flow::Verb& verb) const { - Flow::DispatchDeep(*this, verb); - return verb; - } - - /// Execute a verb for all elements inside a type-erased block - /// @param verb - the verb to execute - template - Flow::Verb& TAny::Run(Flow::Verb& verb) { - Flow::DispatchDeep(*this, verb); - return verb; - }*/ - -} // namespace Langulus::Anyness namespace Langulus::Entity { - using TraitList = TAny; - - /// /// Seek interface for Hierarchy/Thing/Unit /// @@ -92,31 +66,31 @@ namespace Langulus::Entity /// above functions, which should be defined in THIS /// template - NOD() const Unit* SeekUnit(DMeta, Index = 0) const; - template + NOD() const A::Unit* SeekUnit(DMeta, Index = 0) const; + template NOD() Decay* SeekUnit(Index = 0); - template + template NOD() const Decay* SeekUnit(Index = 0) const; template - NOD() const Unit* SeekUnitAux(const Neat&, DMeta, Index = 0) const; - template + NOD() const A::Unit* SeekUnitAux(const Neat&, DMeta, Index = 0) const; + template NOD() Decay* SeekUnitAux(const Neat&, Index = 0); - template + template NOD() const Decay* SeekUnitAux(const Neat&, Index = 0) const; template - NOD() const Unit* SeekUnitExt(DMeta, const Neat&, Index = 0) const; - template + NOD() const A::Unit* SeekUnitExt(DMeta, const Neat&, Index = 0) const; + template NOD() Decay* SeekUnitExt(const Neat&, Index = 0); - template + template NOD() const Decay* SeekUnitExt(const Neat&, Index = 0) const; template - NOD() const Unit* SeekUnitAuxExt(DMeta, const Neat&, const Neat&, Index = 0) const; - template + NOD() const A::Unit* SeekUnitAuxExt(DMeta, const Neat&, const Neat&, Index = 0) const; + template NOD() Decay* SeekUnitAuxExt(const Neat&, const Neat&, Index = 0); - template + template NOD() const Decay* SeekUnitAuxExt(const Neat&, const Neat&, Index = 0) const; template @@ -146,17 +120,17 @@ namespace Langulus::Entity template - NOD() TAny GatherUnits(DMeta) const; - template + NOD() TAny GatherUnits(DMeta) const; + template NOD() TAny GatherUnits(); - template + template NOD() TAny GatherUnits() const; template - NOD() TAny GatherUnitsExt(DMeta, const Neat&) const; - template + NOD() TAny GatherUnitsExt(DMeta, const Neat&) const; + template NOD() TAny GatherUnitsExt(const Neat&); - template + template NOD() TAny GatherUnitsExt(const Neat&) const; @@ -174,14 +148,14 @@ namespace Langulus::Entity /// Available only when managed reflection is enabled /// template - NOD() Unit* SeekUnit(const Token&, Index = 0); + NOD() A::Unit* SeekUnit(const Token&, Index = 0); template - NOD() const Unit* SeekUnit(const Token&, Index = 0) const; + NOD() const A::Unit* SeekUnit(const Token&, Index = 0) const; template - NOD() Unit* SeekUnitAux(const Neat&, const Token&, Index = 0); + NOD() A::Unit* SeekUnitAux(const Neat&, const Token&, Index = 0); template - NOD() const Unit* SeekUnitAux(const Neat&, const Token&, Index = 0) const; + NOD() const A::Unit* SeekUnitAux(const Neat&, const Token&, Index = 0) const; template NOD() Trait SeekTrait(const Token&, Index = 0); @@ -200,9 +174,9 @@ namespace Langulus::Entity template - NOD() TAny GatherUnits(const Token&); + NOD() TAny GatherUnits(const Token&); template - NOD() TAny GatherUnits(const Token&) const; + NOD() TAny GatherUnits(const Token&) const; template NOD() TraitList GatherTraits(const Token&); @@ -236,13 +210,13 @@ namespace Langulus::Entity using SeekInterface::SeekValueAux; template - NOD() Unit* SeekUnit(DMeta, Index = 0); + NOD() A::Unit* SeekUnit(DMeta, Index = 0); template - NOD() Unit* SeekUnitAux(const Neat&, DMeta, Index = 0); + NOD() A::Unit* SeekUnitAux(const Neat&, DMeta, Index = 0); template - NOD() Unit* SeekUnitExt(DMeta, const Neat&, Index = 0); + NOD() A::Unit* SeekUnitExt(DMeta, const Neat&, Index = 0); template - NOD() Unit* SeekUnitAuxExt(DMeta, const Neat&, const Neat&, Index = 0); + NOD() A::Unit* SeekUnitAuxExt(DMeta, const Neat&, const Neat&, Index = 0); template NOD() Trait SeekTrait(TMeta, Index = 0); @@ -262,9 +236,9 @@ namespace Langulus::Entity using SeekInterface::GatherTraits; template - NOD() TAny GatherUnitsExt(DMeta, const Neat&); + NOD() TAny GatherUnitsExt(DMeta, const Neat&); template - NOD() TAny GatherUnits(DMeta); + NOD() TAny GatherUnits(DMeta); template NOD() TraitList GatherTraits(TMeta); diff --git a/source/Module.hpp b/source/Module.hpp index ee08a05..34f943e 100644 --- a/source/Module.hpp +++ b/source/Module.hpp @@ -8,18 +8,16 @@ /// #pragma once #include "Common.hpp" -#include -#include LANGULUS_EXCEPTION(Module); namespace Langulus { - namespace Entity - { - using MetaList = TUnorderedSet; - } + + using MetaList = Anyness::TUnorderedSet; + using TraitList = TAny; + using ModuleList = TAny; /// Helper function, that reflects and registers a list of any reflection /// primitives, like data, verbs, and traits. @@ -37,30 +35,30 @@ namespace Langulus /// be unloaded when shared library is unloaded. Unload /// will be forbidden, if they're still in use. template - void RegisterTypeList(Entity::MetaList& list) { + void RegisterTypeList(MetaList& list) { // Merge to avoid duplications (list << ... << MetaOf()); } } // namespace Langulus -namespace Langulus::Entity +namespace Langulus::A { /// /// External module interface /// class Module : public Resolvable { - LANGULUS(PRODUCER) Runtime; + LANGULUS(PRODUCER) Entity::Runtime; LANGULUS(UNINSERTABLE) false; LANGULUS_BASES(Resolvable); private: // Runtime that owns the module instance - Runtime* mRuntime; + Entity::Runtime* mRuntime; public: - Module(DMeta classid, Runtime* runtime) IF_UNSAFE(noexcept) + Module(DMeta classid, Entity::Runtime* runtime) IF_UNSAFE(noexcept) : Resolvable {classid} , mRuntime {runtime} {} @@ -75,7 +73,7 @@ namespace Langulus::Entity struct Info { // Define the order in which module updates, relative to others - Real mPriority; + Langulus::Real mPriority; // Name of the module const char* mName; // Information about the module @@ -87,23 +85,23 @@ namespace Langulus::Entity }; using EntryFunction = void(*)(DMeta&, MetaList&); - using CreateFunction = Module*(*)(Runtime*, const Neat&); + using CreateFunction = Module*(*)(Entity::Runtime*, const Neat&); using InfoFunction = const Info*(*)(); - NOD() Runtime* GetRuntime() const noexcept { return mRuntime; } + NOD() Entity::Runtime* GetRuntime() const noexcept { return mRuntime; } public: - virtual bool Update(Time) { return true; } + virtual bool Update(Langulus::Time) { return true; } }; -} // namespace Langulus::Entity +} // namespace Langulus::A namespace Langulus::CT { /// Any type that inherits Module is considered a module template - concept Module = DerivedFrom; + concept Module = DerivedFrom; } // namespace Langulus::CT @@ -132,18 +130,18 @@ namespace Langulus::CT \ extern "C" { \ LANGULUS_EXPORT() \ - void LANGULUS_MODULE_ENTRY() (::Langulus::DMeta& meta, ::Langulus::Entity::MetaList& list) { \ + void LANGULUS_MODULE_ENTRY() (::Langulus::DMeta& meta, ::Langulus::MetaList& list) { \ using DM = ::Langulus::Decay; \ meta = ::Langulus::MetaDataOf(); \ ::Langulus::RegisterTypeList, __VA_ARGS__>(list); \ } \ \ LANGULUS_EXPORT() \ - ::Langulus::Entity::Module* LANGULUS_MODULE_CREATE() ( \ + ::Langulus::A::Module* LANGULUS_MODULE_CREATE() ( \ ::Langulus::Entity::Runtime* rt, const ::Langulus::Anyness::Neat& desc) { \ - static_assert(::Langulus::CT::DerivedFrom, \ + static_assert(::Langulus::CT::DerivedFrom, \ "Langulus module class interface " \ - #m " doesn't inherit ::Langulus::Entity::Module"); \ + #m " doesn't inherit ::Langulus::A::Module"); \ static_assert(not ::Langulus::CT::Abstract, \ "Langulus module class interface " \ #m " is abstract, have you forgotten to define its interface?"); \ @@ -151,8 +149,8 @@ namespace Langulus::CT } \ \ LANGULUS_EXPORT() \ - const ::Langulus::Entity::Module::Info* LANGULUS_MODULE_INFO() () { \ - static const ::Langulus::Entity::Module::Info i { \ + const ::Langulus::A::Module::Info* LANGULUS_MODULE_INFO() () { \ + static const ::Langulus::A::Module::Info i { \ prio, name, info, depo, ::Langulus::MetaDataOf() \ }; \ return &i; \ diff --git a/source/Runtime.cpp b/source/Runtime.cpp index 5818d03..029ef89 100644 --- a/source/Runtime.cpp +++ b/source/Runtime.cpp @@ -8,8 +8,15 @@ /// #include "Thing.hpp" #include "Runtime.hpp" -#include "External.inl" -#include +#include "../include/Langulus/Asset.hpp" +#include "../include/Langulus/Graphics.hpp" +#include "../include/Langulus/Image.hpp" +#include "../include/Langulus/IO.hpp" +#include "../include/Langulus/Material.hpp" +#include "../include/Langulus/Mesh.hpp" +#include "../include/Langulus/Physical.hpp" +#include "../include/Langulus/Platform.hpp" +#include "../include/Langulus/UI.hpp" #if LANGULUS_OS(WINDOWS) #include @@ -98,6 +105,7 @@ namespace Langulus::Entity Logger::Error(this, ": Can't unload last module(s): "); for (auto library : mLibraries) Logger::Append(library.mKey, " "); + Logger::Error(this, ": This likely involves a memory leak, " "that withholds managed data, reflected by the given modules"); @@ -111,7 +119,7 @@ namespace Langulus::Entity /// @param name - module name /// @param descriptor - module initialization descriptor /// @return the new module instance - Module* Runtime::InstantiateModule(const Token& name, const Neat& descriptor) { + A::Module* Runtime::InstantiateModule(const Token& name, const Neat& descriptor) { // Load the library if not loaded yet const auto library = LoadSharedLibrary(name); @@ -133,7 +141,7 @@ namespace Langulus::Entity /// @param map - [in/out] the map to fill /// @param module - the module instance to push /// @param type - the type to unregister the module as - void RegisterAllBases(TUnorderedMap& map, Module* module, DMeta type) { + void RegisterAllBases(TUnorderedMap& map, A::Module* module, DMeta type) { VERBOSE("Registering `", type, '`'); auto found = map.FindIt(type); if (found) @@ -160,7 +168,7 @@ namespace Langulus::Entity /// @param map - [in/out] the map to unregister from /// @param module - the module instance to push /// @param type - the type to register the module as - void UnregisterAllBases(TUnorderedMap& map, Module* module, DMeta type) { + void UnregisterAllBases(TUnorderedMap& map, A::Module* module, DMeta type) { for (auto& base : type->mBases) { if (base.mType->IsExact()) break; @@ -181,13 +189,13 @@ namespace Langulus::Entity /// @param library - the library handle /// @param descriptor - module initialization descriptor /// @return the new module instance - Module* Runtime::InstantiateModule(const SharedLibrary& library, const Neat& descriptor) { + A::Module* Runtime::InstantiateModule(const SharedLibrary& library, const Neat& descriptor) { if (not library.IsValid()) return nullptr; // Use the creation point of the library to instantiate module const auto info = library.mInfo(); - Module* module {}; + A::Module* module {}; try { module = library.mCreator(this, descriptor); } catch (...) { @@ -292,11 +300,11 @@ namespace Langulus::Entity // Get entry, creator, info and exit points from the library #if LANGULUS_OS(WINDOWS) - library.mEntry = reinterpret_cast( + library.mEntry = reinterpret_cast( GetProcAddress(dll, LANGULUS_MODULE_ENTRY_TOKEN())); - library.mCreator = reinterpret_cast( + library.mCreator = reinterpret_cast( GetProcAddress(dll, LANGULUS_MODULE_CREATE_TOKEN())); - library.mInfo = reinterpret_cast( + library.mInfo = reinterpret_cast( GetProcAddress(dll, LANGULUS_MODULE_INFO_TOKEN())); #elif LANGULUS_OS(LINUX) library.mEntry = reinterpret_cast( @@ -517,44 +525,6 @@ namespace Langulus::Entity } #endif - /// Get a file interface, relying on external modules to find it - /// @param path - the path for the file - /// @return the file interface, or nullptr if file doesn't exist - Ref Runtime::GetFile(const Path& path) { - auto& fileSystems = GetModules(); - LANGULUS_ASSERT(fileSystems, Module, - "Can't retrieve file `", path, "` - no file system module available"); - return fileSystems.template As()->GetFile(path); - } - - /// Get a folder interface, relying on external modules to find it - /// @param path - the path for the folder - /// @return the folder interface, or nullptr if folder doesn't exist - Ref Runtime::GetFolder(const Path& path) { - auto& fileSystems = GetModules(); - LANGULUS_ASSERT(fileSystems, Module, - "Can't retrieve folder `", path, "` - no file system module available"); - return fileSystems.template As()->GetFolder(path); - } - - /// Get the current working path (where the main exe was executed) - /// @return the path - const Path& Runtime::GetWorkingPath() const { - auto& fileSystems = GetModules(); - LANGULUS_ASSERT(fileSystems, Module, - "Can't retrieve working path", " - no file system module available"); - return fileSystems.template As()->GetWorkingPath(); - } - - /// Get the current data path, like GetWorkingPath() / "data" - /// @return the path - const Path& Runtime::GetDataPath() const { - auto& fileSystems = GetModules(); - LANGULUS_ASSERT(fileSystems, Module, - "Can't retrieve data path", " - no file system module available"); - return fileSystems.template As()->GetDataPath(); - } - /// Update the runtime, by updating all module instantiations by order of /// their priority /// @param dt - delta time between update calls diff --git a/source/Runtime.hpp b/source/Runtime.hpp index 728afe4..1acbed2 100644 --- a/source/Runtime.hpp +++ b/source/Runtime.hpp @@ -8,16 +8,11 @@ /// #pragma once #include "Module.hpp" -#include -#include namespace Langulus::Entity { - using ModuleList = TAny; - - /// /// Runtime /// @@ -40,11 +35,11 @@ namespace Langulus::Entity // Library handle, returned by dlopen or LoadLibrary uintptr_t mHandle {}; // Exported entry function, that registers library types - Module::EntryFunction mEntry {}; + A::Module::EntryFunction mEntry {}; // Exported module instantiation function, produces modules - Module::CreateFunction mCreator {}; + A::Module::CreateFunction mCreator {}; // Information function, returning module description - Module::InfoFunction mInfo {}; + A::Module::InfoFunction mInfo {}; // Type of the module instance DMeta mModuleType {}; // The RTTI::Boundary of the library @@ -110,10 +105,10 @@ namespace Langulus::Entity NOD() auto GetOwner() const noexcept { return mOwner; } NOD() LANGULUS_API(ENTITY) - Module* InstantiateModule(const Token&, const Neat& = {}); + A::Module* InstantiateModule(const Token&, const Neat& = {}); NOD() LANGULUS_API(ENTITY) - Module* InstantiateModule(const SharedLibrary&, const Neat& = {}); + A::Module* InstantiateModule(const SharedLibrary&, const Neat& = {}); NOD() LANGULUS_API(ENTITY) SharedLibrary GetDependency(DMeta) const noexcept; diff --git a/source/Thing-Gather.inl b/source/Thing-Gather.inl index aa3e1b9..d225756 100644 --- a/source/Thing-Gather.inl +++ b/source/Thing-Gather.inl @@ -29,8 +29,8 @@ namespace Langulus::Entity /// @param meta - the units to seek for /// @return the gathered units that match the type template - TAny Thing::GatherUnits(DMeta meta) { - TAny result; + TAny Thing::GatherUnits(DMeta meta) { + TAny result; if constexpr (SEEK & Seek::Here) { // Seek here if requested const auto found = mUnitsAmbiguous.Find(meta); diff --git a/source/Thing-Seek.inl b/source/Thing-Seek.inl index b958e56..4d10183 100644 --- a/source/Thing-Seek.inl +++ b/source/Thing-Seek.inl @@ -30,8 +30,8 @@ namespace Langulus::Entity /// @param offset - which of the matches to return /// @return the found unit, or nullptr if no such unit was found template - Unit* Thing::SeekUnit(DMeta meta, Index offset) { - Unit* result = nullptr; + A::Unit* Thing::SeekUnit(DMeta meta, Index offset) { + A::Unit* result = nullptr; if constexpr (SEEK & Seek::Here) { // Seek here if requested result = GetUnitMeta(meta, offset); @@ -69,10 +69,9 @@ namespace Langulus::Entity /// @param meta - the type of the unit to seek for /// @param offset - the index of the unit to return /// @return the unit if found, or nullptr otherwise - template - LANGULUS(INLINED) - Unit* Thing::SeekUnitAux(const Neat& aux, DMeta meta, Index offset) { - Unit* result {}; + template LANGULUS(INLINED) + A::Unit* Thing::SeekUnitAux(const Neat& aux, DMeta meta, Index offset) { + A::Unit* result {}; aux.ForEachDeep([&](const Unit* unit) { if (unit->CastsTo(meta)) { if (offset == 0) { @@ -100,10 +99,9 @@ namespace Langulus::Entity /// @param ext - the type and properties of the unit to seek for /// @param offset - the index of the unit to return /// @return the unit if found, or nullptr otherwise - template - LANGULUS(INLINED) - Unit* Thing::SeekUnitExt(DMeta type, const Neat& ext, Index offset) { - Unit* result = nullptr; + template LANGULUS(INLINED) + A::Unit* Thing::SeekUnitExt(DMeta type, const Neat& ext, Index offset) { + A::Unit* result = nullptr; if constexpr (SEEK & Seek::Here) { // Seek here if requested result = GetUnitExt(type, ext, offset); @@ -141,11 +139,10 @@ namespace Langulus::Entity /// @param ext - the unit type and properties to seek for /// @param offset - the Nth match to return /// @return a pointer to the found unit, or nullptr if not found - template - LANGULUS(INLINED) - Unit* Thing::SeekUnitAuxExt(DMeta type, const Neat& aux, const Neat& ext, Index offset) { + template LANGULUS(INLINED) + A::Unit* Thing::SeekUnitAuxExt(DMeta type, const Neat& aux, const Neat& ext, Index offset) { // Scan descriptor even if hierarchy is empty - Unit* result {}; + A::Unit* result {}; aux.ForEachDeep([&](const Unit* unit) { if (unit->CastsTo(type)) { //TODO check construct arguments @@ -212,8 +209,7 @@ namespace Langulus::Entity /// @param meta - the trait type to search for /// @param offset - the number of the matching trait to use /// @return the trait, which is not empty, if trait was found - template - LANGULUS(INLINED) + template LANGULUS(INLINED) Trait Thing::SeekTraitAux(const Neat& aux, TMeta meta, Index offset) { // Scan descriptor Trait result; @@ -297,8 +293,7 @@ namespace Langulus::Entity /// @param output - [out] the found value will be written here /// @param offset - the number of the matching trait to use /// @return true if value has been found and rewritten - template - LANGULUS(INLINED) + template LANGULUS(INLINED) bool Thing::SeekValueAux(TMeta meta, const Neat& aux, CT::Data auto& output, Index offset) const { using D = Deref; diff --git a/source/Thing-Verbs.cpp b/source/Thing-Verbs.cpp index 3726435..6c86625 100644 --- a/source/Thing-Verbs.cpp +++ b/source/Thing-Verbs.cpp @@ -91,7 +91,7 @@ namespace Langulus::Entity void Thing::Select(Verb& verb) { // Probe every part of the argument and check if it matches TAny selectedTraits; - TAny selectedUnits; + TAny selectedUnits; TAny selectedEntities; bool mismatch = false; @@ -131,14 +131,14 @@ namespace Langulus::Entity return Loop::Continue; } } - else if (construct.CastsTo()) { + else if (construct.CastsTo()) { // Find a unit containing construct arguments if (not selectUnit(construct.GetType())) return Loop::Break; // selectedComponents has been populated with results // Filter them additionally by construct arguments - TAny filteredSelectedComponents; + TAny filteredSelectedComponents; for (auto& unit : selectedUnits) { bool localMismatch = false; auto unitBlock = unit->GetBlock(); diff --git a/source/Thing.cpp b/source/Thing.cpp index 1583420..3a3555c 100644 --- a/source/Thing.cpp +++ b/source/Thing.cpp @@ -323,7 +323,7 @@ namespace Langulus::Entity /// @param id - the type of the unit /// @param index - the unit index to seek /// @return the unit if found, or nullptr if not - Unit* Thing::GetUnitMeta(DMeta id, Index index) { + A::Unit* Thing::GetUnitMeta(DMeta id, Index index) { if (id) { // Search a typed trait const auto found = mUnitsAmbiguous.FindIt(id); @@ -334,7 +334,7 @@ namespace Langulus::Entity return mUnitsList[index].Get(); } - const Unit* Thing::GetUnitMeta(DMeta type, Index offset) const { + const A::Unit* Thing::GetUnitMeta(DMeta type, Index offset) const { return const_cast(this)->GetUnitMeta(type, offset); } @@ -345,7 +345,7 @@ namespace Langulus::Entity /// @param what - the desired properties of the unit /// @param index - the unit index to seek /// @return the unit if found, or nullptr if not - Unit* Thing::GetUnitExt(DMeta meta, const Neat& what, Index index) { + A::Unit* Thing::GetUnitExt(DMeta meta, const Neat& what, Index index) { if (meta) { // Search a typed unit const auto found = mUnitsAmbiguous.FindIt(meta); @@ -382,7 +382,7 @@ namespace Langulus::Entity return nullptr; } - const Unit* Thing::GetUnitExt(DMeta meta, const Neat& what, Index index) const { + const A::Unit* Thing::GetUnitExt(DMeta meta, const Neat& what, Index index) const { return const_cast(this)->GetUnitExt(meta, what, index); } @@ -391,7 +391,7 @@ namespace Langulus::Entity /// @param token - the type name of the unit /// @param offset - the unit index /// @return the unit if found, or nullptr if not - Unit* Thing::GetUnitMeta(const Token& token, Index offset) { + A::Unit* Thing::GetUnitMeta(const Token& token, Index offset) { return GetUnitMeta(RTTI::DisambiguateMeta(token), offset); } #endif @@ -538,7 +538,7 @@ namespace Langulus::Entity /// @param module - name of the module /// @param descriptor - instructions for module setup /// @return the instantiated module interface - Module* Thing::LoadMod(const Token& module, const Neat& descriptor) { + A::Module* Thing::LoadMod(const Token& module, const Neat& descriptor) { const auto runtime = GetRuntime(); LANGULUS_ASSUME(UserAssumes, runtime, "No runtime available for loading a module"); diff --git a/source/Thing.hpp b/source/Thing.hpp index 368ca24..51205fa 100644 --- a/source/Thing.hpp +++ b/source/Thing.hpp @@ -27,8 +27,8 @@ LANGULUS_DEFINE_TRAIT(Unit, namespace Langulus::Entity { - using UnitList = TAny>; - using UnitMap = TUnorderedMap>>; + using UnitList = TAny>; + using UnitMap = TUnorderedMap>>; using TraitMap = TUnorderedMap; /// A text specialization, dedicated for natural language text @@ -148,7 +148,7 @@ namespace Langulus::Entity Count RemoveChild(Thing*); LANGULUS_API(ENTITY) - Module* LoadMod(const Token&, const Neat& = {}); + A::Module* LoadMod(const Token&, const Neat& = {}); NOD() LANGULUS_API(ENTITY) const Hierarchy& GetChildren() const noexcept; @@ -173,9 +173,9 @@ namespace Langulus::Entity /// Unit management /// template - Count AddUnit(Unit*); + Count AddUnit(A::Unit*); template - Count RemoveUnit(Unit*); + Count RemoveUnit(A::Unit*); template Any CreateUnit(A&&...); @@ -185,7 +185,7 @@ namespace Langulus::Entity Any CreateUnitToken(const Token&, A&&...); #endif - template + template Count RemoveUnits(); /*LANGULUS_API(ENTITY) @@ -201,34 +201,34 @@ namespace Langulus::Entity const UnitList& GetUnits() const noexcept; NOD() LANGULUS_API(ENTITY) - Unit* GetUnitMeta(DMeta, Index = 0); + A::Unit* GetUnitMeta(DMeta, Index = 0); NOD() LANGULUS_API(ENTITY) - const Unit* GetUnitMeta(DMeta, Index = 0) const; + const A::Unit* GetUnitMeta(DMeta, Index = 0) const; NOD() LANGULUS_API(ENTITY) - Unit* GetUnitExt(DMeta, const Neat&, Index = 0); + A::Unit* GetUnitExt(DMeta, const Neat&, Index = 0); NOD() LANGULUS_API(ENTITY) - const Unit* GetUnitExt(DMeta, const Neat&, Index = 0) const; + const A::Unit* GetUnitExt(DMeta, const Neat&, Index = 0) const; - template + template NOD() Decay* GetUnit(Index = 0); - template + template NOD() const Decay* GetUnit(Index = 0) const; #if LANGULUS_FEATURE(MANAGED_REFLECTION) NOD() LANGULUS_API(ENTITY) - const Unit* GetUnitMeta(const Token&, Index = 0) const; + A::Unit const* GetUnitMeta(const Token&, Index = 0) const; NOD() LANGULUS_API(ENTITY) - Unit* GetUnitMeta(const Token&, Index = 0); + A::Unit* GetUnitMeta(const Token&, Index = 0); template NOD() Decay* GetUnitAs(const Token&, Index = 0); #endif private: - LANGULUS_API(ENTITY) void AddUnitBases(Unit*, DMeta); - LANGULUS_API(ENTITY) void RemoveUnitBases(Unit*, DMeta); + LANGULUS_API(ENTITY) void AddUnitBases(A::Unit*, DMeta); + LANGULUS_API(ENTITY) void RemoveUnitBases(A::Unit*, DMeta); public: /// @@ -293,13 +293,13 @@ namespace Langulus::Entity using SeekInterface::SeekValueAux; template - NOD() Unit* SeekUnit(DMeta, Index = 0); + NOD() A::Unit* SeekUnit(DMeta, Index = 0); template - NOD() Unit* SeekUnitAux(const Neat&, DMeta, Index = 0); + NOD() A::Unit* SeekUnitAux(const Neat&, DMeta, Index = 0); template - NOD() Unit* SeekUnitExt(DMeta, const Neat&, Index = 0); + NOD() A::Unit* SeekUnitExt(DMeta, const Neat&, Index = 0); template - NOD() Unit* SeekUnitAuxExt(DMeta, const Neat&, const Neat&, Index = 0); + NOD() A::Unit* SeekUnitAuxExt(DMeta, const Neat&, const Neat&, Index = 0); template NOD() Trait SeekTrait(TMeta, Index = 0); @@ -319,9 +319,9 @@ namespace Langulus::Entity using SeekInterface::GatherTraits; template - NOD() TAny GatherUnits(DMeta); + NOD() TAny GatherUnits(DMeta); template - NOD() TAny GatherUnitsExt(DMeta, const Neat&); + NOD() TAny GatherUnitsExt(DMeta, const Neat&); template NOD() TraitList GatherTraits(TMeta); diff --git a/source/Thing.inl b/source/Thing.inl index 66588df..7df295d 100644 --- a/source/Thing.inl +++ b/source/Thing.inl @@ -75,7 +75,7 @@ namespace Langulus::Entity // Instantiate a temporal flow verb << CreateFlow(); } - else if (stuff->template CastsTo()) { + else if (stuff->template CastsTo()) { // Instantiate a module from the runtime auto runtime = GetRuntime(); auto dependency = runtime->GetDependency(stuff); @@ -107,7 +107,7 @@ namespace Langulus::Entity // Instantiate a temporal flow verb << CreateFlow(); } - else if (stuff.template CastsTo()) { + else if (stuff.template CastsTo()) { // Instantiate a module from the runtime auto runtime = GetRuntime(); auto dependency = runtime->GetDependency(stuff.GetType()); @@ -234,7 +234,7 @@ namespace Langulus::Entity /// Register unit by all its bases in mUnitsAmbiguous /// @param unit - the unit instance to register /// @param type - the type to register the unit as - inline void Thing::AddUnitBases(Unit* unit, DMeta type) { + inline void Thing::AddUnitBases(A::Unit* unit, DMeta type) { const auto found = mUnitsAmbiguous.FindIt(type); if (found) *found.mValue << unit; @@ -242,7 +242,7 @@ namespace Langulus::Entity mUnitsAmbiguous.Insert(type, unit); for (auto& base : type->mBases) { - if (base.mType->IsExact()) + if (base.mType->IsExact()) break; AddUnitBases(unit, base.mType); @@ -252,7 +252,7 @@ namespace Langulus::Entity /// Unregister unit by all its bases in mUnitsAmbiguous /// @param unit - the unit instance to unregister /// @param type - the type to unregister the unit as - inline void Thing::RemoveUnitBases(Unit* unit, DMeta type) { + inline void Thing::RemoveUnitBases(A::Unit* unit, DMeta type) { const auto found = mUnitsAmbiguous.FindIt(type); if (found) { auto& set = *found.mValue; @@ -261,7 +261,7 @@ namespace Langulus::Entity } for (auto& base : type->mBases) { - if (base.mType->IsExact()) + if (base.mType->IsExact()) break; RemoveUnitBases(unit, base.mType); @@ -277,7 +277,7 @@ namespace Langulus::Entity /// @param unit - the unit to add /// @return 1 if unit has been added template - Count Thing::AddUnit(Unit* unit) { + Count Thing::AddUnit(A::Unit* unit) { // Check if the unit instance is already registered here const auto meta = unit->GetType(); const auto found = mUnitsAmbiguous.FindIt(meta); @@ -318,7 +318,7 @@ namespace Langulus::Entity /// @param unit - unit to remove from the entity /// @return 1 if unit has been removed template - Count Thing::RemoveUnit(Unit* unit) { + Count Thing::RemoveUnit(A::Unit* unit) { const auto meta = unit->GetType(); const auto foundType = mUnitsAmbiguous.FindIt(meta); if (not foundType) @@ -351,7 +351,7 @@ namespace Langulus::Entity /// @return the number of removed units template Count Thing::RemoveUnits() { - if constexpr (CT::Same) { + if constexpr (CT::Same) { // Remove all units const auto removed = mUnitsList.GetCount(); if constexpr (TWOSIDED) { @@ -432,7 +432,7 @@ namespace Langulus::Entity /// @return the unit if found, or nullptr if not template LANGULUS(INLINED) Decay* Thing::GetUnit(Index offset) { - if constexpr (not CT::Same) { + if constexpr (not CT::Same) { return static_cast*>( GetUnitMeta(MetaOf>(), offset) ); @@ -450,7 +450,7 @@ namespace Langulus::Entity /// @return the unit if found, or nullptr if not template LANGULUS(INLINED) const Decay* Thing::GetUnit(Index offset) const { - if constexpr (not CT::Same) { + if constexpr (not CT::Same) { return static_cast*>( GetUnitMeta(MetaOf>(), offset) ); @@ -469,7 +469,7 @@ namespace Langulus::Entity /// @param offset - optional offset (Nth match) /// @return the unit if found, or nullptr if not LANGULUS(INLINED) - const Unit* Thing::GetUnitMeta(const Token& token, Index offset) const { + const A::Unit* Thing::GetUnitMeta(const Token& token, Index offset) const { return const_cast(this)->GetUnitMeta(token, offset); } @@ -541,7 +541,7 @@ namespace Langulus::Entity if (producer) { // Data has a specific producer, we can narrow the required // contexts for creation a lot - if (producer->template CastsTo()) { + if (producer->template CastsTo()) { // Data is producible from a unit auto producers = GatherUnits(producer); LANGULUS_ASSERT(producers, Construct, @@ -562,7 +562,7 @@ namespace Langulus::Entity ": ", descriptor ); } - else if (producer->template CastsTo()) { + else if (producer->template CastsTo()) { // Data is producible from a module auto producers = GetRuntime()->GetModules(producer); LANGULUS_ASSERT(producers, Construct, @@ -592,7 +592,7 @@ namespace Langulus::Entity // Data doesn't have a specific producer, but it is abstract // so we know that only a module/unit can concretize it // Gather all units in the desired part of the hierarchy - auto producers = GatherUnits(); + auto producers = GatherUnits(); if (producers) { // Potential unit producers found, attempt creation there producers.MakeOr(); @@ -631,13 +631,18 @@ namespace Langulus::Entity return {}; } +} // namespace Langulus::Entity + +namespace Langulus::A +{ + /// Execute verb in all owners, seeking valid context in the specified /// seek direction /// @tparam SEEK - direction to seek valid execution context in /// @param verb - the verb to execute /// @return the verb output template - V& Unit::RunIn(V& verb) { + V& A::Unit::RunIn(V& verb) { if (not mOwners) { Logger::Warning(Self(), "No owners available for executing: ", verb); return verb; @@ -653,7 +658,7 @@ namespace Langulus::Entity return verb; } -} // namespace Langulus::Entity +} // namespace Langulus::A #undef ENTITY_VERBOSE_ENABLED #undef ENTITY_VERBOSE_SELF diff --git a/source/Unit-Gather.inl b/source/Unit-Gather.inl index d7bbda5..05ae078 100644 --- a/source/Unit-Gather.inl +++ b/source/Unit-Gather.inl @@ -10,15 +10,14 @@ #include "Unit.hpp" -namespace Langulus::Entity +namespace Langulus::A { /// Collects all units of the given type inside the hierarchy /// @tparam SEEK - where in the hierarchy are we seeking in? /// @param meta - the units to seek for /// @return the gathered units that match the type - template - LANGULUS(INLINED) + template LANGULUS(INLINED) TAny Unit::GatherUnits(DMeta meta) { return mOwners.template GatherUnits(meta); } @@ -27,9 +26,8 @@ namespace Langulus::Entity /// @tparam SEEK - where in the hierarchy are we seeking in? /// @param trait - the trait to seek for /// @return the gathered traits that match the type - template - LANGULUS(INLINED) - TAny Unit::GatherTraits(TMeta trait) { + template LANGULUS(INLINED) + TraitList Unit::GatherTraits(TMeta trait) { return mOwners.template GatherTraits(trait); } @@ -37,8 +35,7 @@ namespace Langulus::Entity /// @tparam D - type to convert to /// @tparam SEEK - where in the hierarchy are we seeking in? /// @return the gathered values - template - LANGULUS(INLINED) + template LANGULUS(INLINED) TAny Unit::GatherValues() const { return mOwners.template GatherValues(); } diff --git a/source/Unit-Seek.inl b/source/Unit-Seek.inl index a49b02a..193bf7b 100644 --- a/source/Unit-Seek.inl +++ b/source/Unit-Seek.inl @@ -10,7 +10,7 @@ #include "Unit.hpp" -namespace Langulus::Entity +namespace Langulus::A { /// Find a specific unit, searching into the hierarchy diff --git a/source/Unit.cpp b/source/Unit.cpp index 22d9267..92b41fb 100644 --- a/source/Unit.cpp +++ b/source/Unit.cpp @@ -8,7 +8,7 @@ /// #include "Thing.inl" -using namespace Langulus::Entity; +using namespace Langulus::A; /// Manual construction @@ -29,7 +29,7 @@ Unit::Unit(Unit&& other) noexcept /// Default unit selection simply relays to the owner /// @param verb - the selection verb -void Unit::Select(Verb& verb) { +void Unit::Select(Flow::Verb& verb) { for (auto owner : mOwners) owner->Select(verb); } @@ -54,7 +54,7 @@ bool Unit::CompareDescriptor(const Neat& descriptor) const { // First we compare traits only, all of them must be present bool mismatch {}; Offset memberOffset {}; - descriptor.ForEach([&](const Trait& trait) { + descriptor.ForEach([&](const Anyness::Trait& trait) { if (not GetMember(trait.GetTrait(), memberOffset) .Compare(static_cast(trait))) { mismatch = true; @@ -68,7 +68,7 @@ bool Unit::CompareDescriptor(const Neat& descriptor) const { // Then we run another check, based on data types, again, all // of them must be present, either in trait, or in other form memberOffset = {}; - descriptor.ForEachTail([&](const Block& anythingElse) { + descriptor.ForEachTail([&](const Anyness::Block& anythingElse) { if (not GetMember(TMeta {}, memberOffset).Compare(anythingElse)) { mismatch = true; return Loop::Break; diff --git a/source/Unit.hpp b/source/Unit.hpp index 933ddc2..16aeeaf 100644 --- a/source/Unit.hpp +++ b/source/Unit.hpp @@ -10,9 +10,14 @@ #include "Hierarchy.hpp" -namespace Langulus::Entity +namespace Langulus::A { + using Entity::Thing; + using Entity::Hierarchy; + using Entity::Runtime; + + /// /// An abstract unit /// @@ -21,7 +26,7 @@ namespace Langulus::Entity /// inside external, dynamically loaded modules. There are units for /// graphics, input, AI, content, and whatever extensions you make. /// - struct LANGULUS_API(ENTITY) Unit : Resolvable, SeekInterface { + struct LANGULUS_API(ENTITY) Unit : Resolvable, Entity::SeekInterface { LANGULUS(UNINSERTABLE) false; LANGULUS_BASES(Resolvable); @@ -50,7 +55,7 @@ namespace Langulus::Entity Unit& operator = (Unit&&) noexcept; - void Select(Verb&); + void Select(Flow::Verb&); public: virtual void Refresh(); @@ -127,6 +132,6 @@ namespace Langulus::CT /// Any type that inherits Unit is considered a unit template - concept Unit = DerivedFrom; + concept Unit = DerivedFrom; } // namespace Langulus::CT diff --git a/test/Main.cpp b/test/Main.cpp index 8818255..5e1cf48 100644 --- a/test/Main.cpp +++ b/test/Main.cpp @@ -14,18 +14,18 @@ LANGULUS_RTTI_BOUNDARY(RTTI::MainBoundary); int main(int argc, char* argv[]) { - static_assert(CT::Complete, "Oops1"); - static_assert(CT::Complete, "Oops2"); - static_assert(CT::Complete, "Oops3"); - static_assert(CT::Complete, "Oops4"); - static_assert(CT::Complete, "Oops5"); + static_assert(CT::Complete, "Oops1"); + static_assert(CT::Complete, "Oops2"); + static_assert(CT::Complete, "Oops3"); + static_assert(CT::Complete, "Oops4"); + static_assert(CT::Complete, "Oops5"); - // For reflection of all verbs - (void)MetaOf>(); - (void)MetaOf(); - (void)MetaOf(); - (void)MetaOf(); + // For reflection of all verbs + (void)MetaOf>(); + (void)MetaOf(); + (void)MetaOf(); + (void)MetaOf(); - Catch::Session session; - return session.run(argc, argv); + Catch::Session session; + return session.run(argc, argv); } diff --git a/test/Main.hpp b/test/Main.hpp index be62b03..68f65ee 100644 --- a/test/Main.hpp +++ b/test/Main.hpp @@ -7,15 +7,16 @@ /// See LICENSE file, or https://www.gnu.org/licenses /// #pragma once -#include +#include using namespace Langulus; +using namespace Entity; #define CATCH_CONFIG_ENABLE_BENCHMARKING /// A unit implementation for testing -class TestUnit1 final : public Unit { +class TestUnit1 final : public A::Unit { public: LANGULUS(ABSTRACT) false; LANGULUS_BASES(Unit); @@ -37,7 +38,7 @@ class TestUnit1 final : public Unit { }; /// A unit implementation for testing -class TestUnit2 final : public Unit { +class TestUnit2 final : public A::Unit { public: LANGULUS(ABSTRACT) false; LANGULUS_BASES(Unit); diff --git a/test/TestUnit.cpp b/test/TestUnit.cpp index a75e727..4b0b5e4 100644 --- a/test/TestUnit.cpp +++ b/test/TestUnit.cpp @@ -19,8 +19,8 @@ SCENARIO("Testing Unit", "[unit]") { WHEN("Dynamically casting to/from unit pointers") { TestUnit1 t1; TestUnit2 t2; - Unit* t1p = &t1; - Unit* t2p = &t2; + A::Unit* t1p = &t1; + A::Unit* t2p = &t2; REQUIRE(reinterpret_cast(t1p) == reinterpret_cast(&t1)); REQUIRE(reinterpret_cast(t2p) == reinterpret_cast(&t2));