diff --git a/projs/shadow/shadow-engine/assets/src/fs/file.h b/projs/shadow/shadow-engine/assets/inc/shadow/assets/fs/file.h similarity index 80% rename from projs/shadow/shadow-engine/assets/src/fs/file.h rename to projs/shadow/shadow-engine/assets/inc/shadow/assets/fs/file.h index 0bc97aeb..5a8947a6 100644 --- a/projs/shadow/shadow-engine/assets/src/fs/file.h +++ b/projs/shadow/shadow-engine/assets/inc/shadow/assets/fs/file.h @@ -1,8 +1,7 @@ #pragma once -#include -#include -#include #include +#include "iostream.h" +#include "path.h" template struct Delegate; @@ -13,7 +12,7 @@ namespace ShadowEngine { FileInput(); ~FileInput() = default; - [[nodiscard]] bool open(std::string& path); + [[nodiscard]] bool open(const std::string& path); void close(); using InputStream::read; @@ -34,7 +33,7 @@ namespace ShadowEngine { FileOutput(); ~FileOutput() = default; - [[nodiscard]] bool open(std::string& path); + [[nodiscard]] bool open(const std::string& path); void close(); void flush(); bool errored() const { return error; } @@ -71,31 +70,31 @@ namespace ShadowEngine { }; // Create a Filesystem that interacts with files on disk. - static std::unique_ptr createDiskFS(std::string& basePath); + static std::unique_ptr createDiskFS(const std::string& basePath); // Create a Virtual Filesystem based on the given path. - static std::unique_ptr createVFS(std::string& basePath); + static std::unique_ptr createVFS(const std::string& basePath); virtual ~FileSystem() = default; // Open a file for reading. - virtual bool open(std::string& path, FileInput& input) = 0; + virtual bool open(const std::string& path, FileInput& input) = 0; // Open a file for writing. - virtual bool open(std::string& path, FileOutput& output) = 0; + virtual bool open(const std::string& path, FileOutput& output) = 0; // Check whether a file exists at the given path. - virtual bool fileExists(std::string& path) = 0; + virtual bool fileExists(const std::string& path) = 0; // Get the time a file at the given path was last modified. - virtual size_t getLastModified(std::string& path) = 0; + virtual size_t getLastModified(const std::string& path) = 0; // Copy a file from one path to another. - virtual bool copyFile(std::string& from, std::string& to) = 0; + virtual bool copyFile(const std::string& from, const std::string& to) = 0; // Move a file from one path to another. - virtual bool moveFile(std::string& from, std::string& to) = 0; + virtual bool moveFile(const std::string& from, const std::string& to) = 0; // Disassociate any files at the given path (not an immediate delete) - virtual bool deleteFile(std::string& path) = 0; + virtual bool deleteFile(const std::string& path) = 0; // Get the path that this FileSystem originates at. The default is "/" for VFS, and whatever the Executable Path is for Disk FS. virtual std::string const& getBasePath() const = 0; // Set a new base path for the FileSystem. Any operations involving file paths will be relative to this new path. - virtual void setBasePath(std::string& path) = 0; + virtual void setBasePath(const std::string& path) = 0; // Process all the callbacks for async file operations. virtual void processCallbacks() = 0; diff --git a/projs/shadow/shadow-engine/assets/src/fs/hash.h b/projs/shadow/shadow-engine/assets/inc/shadow/assets/fs/hash.h similarity index 96% rename from projs/shadow/shadow-engine/assets/src/fs/hash.h rename to projs/shadow/shadow-engine/assets/inc/shadow/assets/fs/hash.h index f5b9f04f..e1abd33c 100644 --- a/projs/shadow/shadow-engine/assets/src/fs/hash.h +++ b/projs/shadow/shadow-engine/assets/inc/shadow/assets/fs/hash.h @@ -15,7 +15,7 @@ namespace ShadowEngine { HeapHash() = default; // Hash a string; for paths and such. - explicit HeapHash(std::string& str); + explicit HeapHash(const std::string& str); // Hash arbitrary data. HeapHash(const void* data, uint32_t length); @@ -39,7 +39,7 @@ namespace ShadowEngine { HeapHash32() = default; // Hash a string; for paths and such. - explicit HeapHash32(std::string& str); + explicit HeapHash32(const std::string& str); // Hash arbitrary data. HeapHash32(const void* data, uint32_t length); @@ -59,7 +59,7 @@ namespace ShadowEngine { struct StableHash { static StableHash fromLong(size_t data); StableHash() = default; - explicit StableHash(std::string& str); + explicit StableHash(const std::string& str); StableHash(const void* data, uint32_t length); bool operator!= (const StableHash& other) const { return hash != other.hash; } @@ -80,7 +80,7 @@ namespace ShadowEngine { struct StableHash32 { static StableHash32 fromInt(uint32_t data); StableHash32() = default; - StableHash32(std::string& str); + StableHash32(const std::string& str); StableHash32(const void* data, uint32_t length); bool operator!= (StableHash32& other) const { return hash != other.hash; } diff --git a/projs/shadow/shadow-engine/assets/src/fs/iostream.h b/projs/shadow/shadow-engine/assets/inc/shadow/assets/fs/iostream.h similarity index 100% rename from projs/shadow/shadow-engine/assets/src/fs/iostream.h rename to projs/shadow/shadow-engine/assets/inc/shadow/assets/fs/iostream.h diff --git a/projs/shadow/shadow-engine/assets/src/fs/path.h b/projs/shadow/shadow-engine/assets/inc/shadow/assets/fs/path.h similarity index 74% rename from projs/shadow/shadow-engine/assets/src/fs/path.h rename to projs/shadow/shadow-engine/assets/inc/shadow/assets/fs/path.h index 5c943a21..47f9cd6b 100644 --- a/projs/shadow/shadow-engine/assets/src/fs/path.h +++ b/projs/shadow/shadow-engine/assets/inc/shadow/assets/fs/path.h @@ -1,7 +1,7 @@ #pragma once #include -#include +#include "hash.h" namespace ShadowEngine { /** @@ -9,7 +9,7 @@ namespace ShadowEngine { * Not to be used as a replacement for the Path class. */ struct PathInfo { - explicit PathInfo(std::string& str); + explicit PathInfo(const std::string& str); char extension[10]; char baseName[256]; @@ -28,21 +28,21 @@ namespace ShadowEngine { // Make sure the path is valid. // Always from the root. // One slash separating. - static std::string normalise(std::string& path); + static std::string normalise(const std::string& path); // Get the prelude of the given path. - static std::string getPrelude(std::string& path); + static std::string getPrelude(const std::string& path); // Get the domain of the given path. - static std::string getDomain(std::string& path); + static std::string getDomain(const std::string& path); // Get the directory of the given path. - static std::string getDirectory(std::string& path); + static std::string getDirectory(const std::string& path); // Get the name of the file of the given path. - static std::string getFilename(std::string& path); + static std::string getFilename(const std::string& path); // Get the file extension of the given path. - static std::string getExtension(std::string& path); + static std::string getExtension(const std::string& path); // Check if the path has the given extension. - static bool hasExtension(std::string& path, std::string& ext); + static bool hasExtension(const std::string& path, const std::string& ext); // Replace the extension of the given path. - static std::string replaceExtension(std::string& path, std::string& newExt); + static std::string replaceExtension(const std::string& path, const std::string& newExt); Path(); explicit Path(const std::string& str); diff --git a/projs/shadow/shadow-engine/assets/src/fs/xxhash.h b/projs/shadow/shadow-engine/assets/inc/shadow/assets/fs/xxhash.h similarity index 100% rename from projs/shadow/shadow-engine/assets/src/fs/xxhash.h rename to projs/shadow/shadow-engine/assets/inc/shadow/assets/fs/xxhash.h diff --git a/projs/shadow/shadow-engine/assets/src/management/delegate.h b/projs/shadow/shadow-engine/assets/inc/shadow/assets/management/delegate.h similarity index 100% rename from projs/shadow/shadow-engine/assets/src/management/delegate.h rename to projs/shadow/shadow-engine/assets/inc/shadow/assets/management/delegate.h diff --git a/projs/shadow/shadow-engine/assets/src/management/delegate_list.h b/projs/shadow/shadow-engine/assets/inc/shadow/assets/management/delegate_list.h similarity index 100% rename from projs/shadow/shadow-engine/assets/src/management/delegate_list.h rename to projs/shadow/shadow-engine/assets/inc/shadow/assets/management/delegate_list.h diff --git a/projs/shadow/shadow-engine/assets/src/management/synchronization.h b/projs/shadow/shadow-engine/assets/inc/shadow/assets/management/synchronization.h similarity index 100% rename from projs/shadow/shadow-engine/assets/src/management/synchronization.h rename to projs/shadow/shadow-engine/assets/inc/shadow/assets/management/synchronization.h diff --git a/projs/shadow/shadow-engine/assets/inc/shadow/assets/resource/Resource.h b/projs/shadow/shadow-engine/assets/inc/shadow/assets/resource/Resource.h new file mode 100644 index 00000000..5ac64114 --- /dev/null +++ b/projs/shadow/shadow-engine/assets/inc/shadow/assets/resource/Resource.h @@ -0,0 +1,139 @@ +#pragma once + +#include "shadow/assets/fs/hash.h" +#include "shadow/assets/fs/path.h" +#include "shadow/assets/fs/file.h" +#include + +namespace ShadowEngine { + + /** + * A runtime-only struct that determines the type of a resource - whether it be a texture, mesh, animation, or other data. + * Provides some specializations for living in a map. + */ + struct ResourceType { + ResourceType() = default; + explicit ResourceType(const std::string& name); + bool operator!=(const ResourceType& o) const { return o.hash != hash; } + bool operator==(const ResourceType& o) const { return o.hash == hash; } + bool operator< (const ResourceType& o) const { return o.hash.getHash() < hash.getHash(); } + bool isValid() const { return hash.getHash() != 0; } + + HeapHash hash; + }; + + // A Resource Type that is guaranteed to be invalid. + static std::string empty; + const ResourceType INVALID_RESOURCE(empty); + + // A specialization of HashFunc for ResourceTypes, since they already have a HeapHash within. + template<> struct HashFunc { + static uint32_t get(const ResourceType& key) { return HashFunc::get(key.hash); } + }; + +#pragma pack(1) + struct ResourceHeader { + static const uint32_t MAGIC; + uint32_t magic = MAGIC; // VXI Package header + uint32_t version = 0; + uint32_t flags = 0; + uint32_t padding = 0; + uint32_t decompressedSize = 0; + }; +#pragma pack() + + /** + * A basic Resource type. + * Represents a single file loaded from disk. + * May have dependencies on other Resources, and other Resources may depend on this. + * Resources are reference-counted, and are removed when they go out of usage. + */ + + struct Resource { + friend struct ResourceTypeManager; + friend struct ResourceManager; + + enum class State : uint32_t { + EMPTY = 0, + READY, + FAILED + }; + + using Observer = DelegateList; + + virtual ~Resource(); + virtual ResourceType getType() const = 0; + State getState() const { return state; } + + bool isEmpty() const { return state == State::EMPTY; } + bool isReady() const { return state == State::READY; } + bool isFailure() const { return state == State::FAILED; } + + uint32_t getReferenceCount() const { return references; } + + Observer const& getCallback() const { return callback; } + size_t getSize() const { return size; } + + const Path& getPath() const { return path; } + + struct ResourceTypeManager& getManager() { return manager; } + + uint32_t decreaseReferences(); + uint32_t increaseReferences() { return references++; } + + bool toInitialize() const { return desiredState == State::READY; } + bool isHooked() const { return hooked; } + + template void onLoaded(C* instance) { + callback.bind(instance); + if (isReady()) (instance->*Function)(State::READY, State::READY, *this); + } + + protected: + Resource(Path path, ResourceTypeManager& manager); + + virtual void onReadying() {} + virtual void unload() = 0; + virtual bool load(size_t size, const uint8_t* mem) = 0; + + void onCreated(State newState); + void performUnload(); + void addDependency(Resource& dependent); + void removeDependency(Resource& dependent); + void checkState(); + void refresh(); + + State desiredState; + uint16_t emptyDependencies; + ResourceTypeManager& manager; + + private: + + void doLoad(); + void fileLoaded(size_t fileSize, const uint8_t* mem, bool success); + void stateChanged(State old, State newState, Resource&); + + Resource(const Resource&) = delete; + void operator=(const Resource&) = delete; + + Observer callback; + size_t size; + Path path; + uint32_t references; + uint16_t failedDependencies; + FileSystem::AsyncHandle handle; + State state; + bool hooked = false; + }; + + struct PrefabResource : Resource { + PrefabResource(const Path& path, ResourceTypeManager& resource_manager); + ResourceType getType() const override; + void unload() override; + bool load(size_t size, const uint8_t* data) override; + + OutputMemoryStream data; + StableHash hash; + static const ResourceType TYPE; + }; +} \ No newline at end of file diff --git a/projs/shadow/shadow-engine/shadow-assets/src/resource/ResourceManager.h b/projs/shadow/shadow-engine/assets/inc/shadow/assets/resource/ResourceManager.h similarity index 98% rename from projs/shadow/shadow-engine/shadow-assets/src/resource/ResourceManager.h rename to projs/shadow/shadow-engine/assets/inc/shadow/assets/resource/ResourceManager.h index 98fc6b1e..6acb5c1c 100644 --- a/projs/shadow/shadow-engine/shadow-assets/src/resource/ResourceManager.h +++ b/projs/shadow/shadow-engine/assets/inc/shadow/assets/resource/ResourceManager.h @@ -1,7 +1,5 @@ #pragma once #include -#include -#include namespace ShadowEngine { diff --git a/projs/shadow/shadow-engine/assets/src/SFFElement.h b/projs/shadow/shadow-engine/assets/inc/shadow/assets/sff/SFFElement.h similarity index 93% rename from projs/shadow/shadow-engine/assets/src/SFFElement.h rename to projs/shadow/shadow-engine/assets/inc/shadow/assets/sff/SFFElement.h index b3bbe88c..bf8946dc 100644 --- a/projs/shadow/shadow-engine/assets/src/SFFElement.h +++ b/projs/shadow/shadow-engine/assets/inc/shadow/assets/sff/SFFElement.h @@ -1,36 +1,36 @@ -#pragma once - -#include -#include -#include - - - namespace Shadow::SFF { - - class SFFElement - { - public: - SFFElement* parent; - - std::string name; - - bool isBlock; - - std::string value; - typedef std::map ChildrenMap; - - ChildrenMap children; - - std::string GetStringProperty(std::string name); - - SFFElement* GetFirstChild(); - - SFFElement* GetChildByIndex(int index); - - SFFElement* GetChildByName(std::string name); - - ~SFFElement(); - - }; - +#pragma once + +#include +#include +#include + + + namespace Shadow::SFF { + + class SFFElement + { + public: + SFFElement* parent; + + std::string name; + + bool isBlock; + + std::string value; + typedef std::map ChildrenMap; + + ChildrenMap children; + + std::string GetStringProperty(std::string name); + + SFFElement* GetFirstChild(); + + SFFElement* GetChildByIndex(int index); + + SFFElement* GetChildByName(std::string name); + + ~SFFElement(); + + }; + } \ No newline at end of file diff --git a/projs/shadow/shadow-engine/assets/src/SFFParser.h b/projs/shadow/shadow-engine/assets/inc/shadow/assets/sff/SFFParser.h similarity index 93% rename from projs/shadow/shadow-engine/assets/src/SFFParser.h rename to projs/shadow/shadow-engine/assets/inc/shadow/assets/sff/SFFParser.h index 542e3dec..d6aa8a3a 100644 --- a/projs/shadow/shadow-engine/assets/src/SFFParser.h +++ b/projs/shadow/shadow-engine/assets/inc/shadow/assets/sff/SFFParser.h @@ -1,22 +1,22 @@ -#pragma once - -#include -#include - -#include "SFFElement.h" -#include "SFFVersion.h" - -namespace Shadow::SFF { - - class SFFParser - { - public: - - static SFFElement* ReadFromStream(std::istream& stream); - - static SFFVersion ReadVersionFromHeader(std::istream& stream); - - static SFFElement* ReadFromFile(std::string path); - }; - -} +#pragma once + +#include +#include + +#include "SFFElement.h" +#include "SFFVersion.h" + +namespace Shadow::SFF { + + class SFFParser + { + public: + + static SFFElement* ReadFromStream(std::istream& stream); + + static SFFVersion ReadVersionFromHeader(std::istream& stream); + + static SFFElement* ReadFromFile(std::string path); + }; + +} diff --git a/projs/shadow/shadow-engine/assets/src/SFFVersion.h b/projs/shadow/shadow-engine/assets/inc/shadow/assets/sff/SFFVersion.h similarity index 92% rename from projs/shadow/shadow-engine/assets/src/SFFVersion.h rename to projs/shadow/shadow-engine/assets/inc/shadow/assets/sff/SFFVersion.h index 2afff832..136b0bf6 100644 --- a/projs/shadow/shadow-engine/assets/src/SFFVersion.h +++ b/projs/shadow/shadow-engine/assets/inc/shadow/assets/sff/SFFVersion.h @@ -1,28 +1,28 @@ -#pragma once - -namespace Shadow::SFF { - - struct SFFVersion { - public: - int mayor; - int minor; - int patch; - - bool invalid; - - SFFVersion(int ma, int mi, int pa) - { - this->mayor = ma; - this->minor = mi; - this->patch = pa; - - if (ma >= 0 && mi >= 0 && pa >= 0) { - this->invalid = false; - } - else - { - invalid = true; - } - } - }; +#pragma once + +namespace Shadow::SFF { + + struct SFFVersion { + public: + int mayor; + int minor; + int patch; + + bool invalid; + + SFFVersion(int ma, int mi, int pa) + { + this->mayor = ma; + this->minor = mi; + this->patch = pa; + + if (ma >= 0 && mi >= 0 && pa >= 0) { + this->invalid = false; + } + else + { + invalid = true; + } + } + }; } \ No newline at end of file diff --git a/projs/shadow/shadow-engine/assets/src/SFFWriter.h b/projs/shadow/shadow-engine/assets/inc/shadow/assets/sff/SFFWriter.h similarity index 92% rename from projs/shadow/shadow-engine/assets/src/SFFWriter.h rename to projs/shadow/shadow-engine/assets/inc/shadow/assets/sff/SFFWriter.h index 31b254f4..2ee034ac 100644 --- a/projs/shadow/shadow-engine/assets/src/SFFWriter.h +++ b/projs/shadow/shadow-engine/assets/inc/shadow/assets/sff/SFFWriter.h @@ -1,26 +1,26 @@ -#pragma once - -#include -#include -#include - -#include "SFFElement.h" -#include "SFFVersion.h" - -namespace Shadow::SFF { - - class SFFWriter - { - public: - - static void WriteFile(SFFElement& root, std::string path); - - static void WriteElement(std::ostream& w, SFFElement& e, int &depth); - - - - }; - -} - - +#pragma once + +#include +#include +#include + +#include "SFFElement.h" +#include "SFFVersion.h" + +namespace Shadow::SFF { + + class SFFWriter + { + public: + + static void WriteFile(SFFElement& root, std::string path); + + static void WriteElement(std::ostream& w, SFFElement& e, int &depth); + + + + }; + +} + + diff --git a/projs/shadow/shadow-engine/assets/src/str/string.h b/projs/shadow/shadow-engine/assets/inc/shadow/assets/str/string.h similarity index 100% rename from projs/shadow/shadow-engine/assets/src/str/string.h rename to projs/shadow/shadow-engine/assets/inc/shadow/assets/str/string.h diff --git a/projs/shadow/shadow-engine/assets/src/fs/file.cpp b/projs/shadow/shadow-engine/assets/src/fs/file.cpp index 6b944c0b..ccda9a3b 100644 --- a/projs/shadow/shadow-engine/assets/src/fs/file.cpp +++ b/projs/shadow/shadow-engine/assets/src/fs/file.cpp @@ -1,17 +1,20 @@ -#include +#include #include -#include "management/synchronization.h" #include #include -#include #include +#include "shadow/assets/fs/iostream.h" +#include "shadow/assets/fs/path.h" +#include "shadow/assets/fs/hash.h" +#include +#include namespace ShadowEngine { - // Because fuck Linux? Need platform-specific source files! + // Because fuck Linux? Need platform-specific source files! #ifdef _WIN32 -#define WIN32_LEAN_AND_MEAN + #define WIN32_LEAN_AND_MEAN #include FileInput::FileInput() { @@ -23,243 +26,299 @@ namespace ShadowEngine { handle = (void*) INVALID_HANDLE_VALUE; } - bool FileOutput::open(std::string& path) { + bool FileOutput::open(const std::string& path) { + handle = (HANDLE) CreateFile(path.c_str(), GENERIC_READ, FILE_SHARE_READ, nullptr, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, nullptr); + return INVALID_HANDLE_VALUE != handle; + } + bool FileInput::open(const std::string& path) { + handle = (HANDLE) CreateFile(path.c_str(), GENERIC_READ, FILE_SHARE_READ, nullptr, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, nullptr); + return INVALID_HANDLE_VALUE != handle; } -#endif + void FileInput::close() { + if (INVALID_HANDLE_VALUE != (HANDLE) handle) { + CloseHandle((HANDLE) handle); + handle = (void*) INVALID_HANDLE_VALUE; + } + } - /** - * An async operation to be performed. - * For reading files from disk into memory. - */ + void FileOutput::close() { + if (INVALID_HANDLE_VALUE != (HANDLE) handle) { + CloseHandle((HANDLE) handle); + handle = (void*) INVALID_HANDLE_VALUE; + } + } + + size_t FileInput::size() const { + assert(INVALID_HANDLE_VALUE != handle); + return GetFileSize((HANDLE) handle, 0); + } - struct AsyncRead { - enum class Flags : uint32_t { - FAILED = 0, // The read failed due to some error. - CANCELLED // The read was cancelled due to the resource not being needed any more. - }; + size_t FileInput::pos() { + assert(INVALID_HANDLE_VALUE != handle); + return SetFilePointer((HANDLE) handle, 0, nullptr, FILE_CURRENT); + } + + bool FileInput::seek(size_t pos) { + assert(INVALID_HANDLE_VALUE != handle); + LARGE_INTEGER distance; + distance.QuadPart = pos; + return SetFilePointer((HANDLE) handle, distance.u.LowPart, &distance.u.HighPart, FILE_BEGIN) != INVALID_SET_FILE_POINTER; + } + + bool FileInput::read(void* data, size_t size) { + assert(INVALID_HANDLE_VALUE != handle); + DWORD read = 0; + BOOL success = ReadFile((HANDLE) handle, data, (DWORD) size, (LPDWORD) &read, nullptr); + return success && size == read; + } + + void FileOutput::flush() { + assert(handle != nullptr); + FlushFileBuffers((HANDLE) handle); + } + + bool FileOutput::write(const void* data, size_t size) { + assert(handle != INVALID_HANDLE_VALUE); + size_t written = 0; + WriteFile((HANDLE) handle, data, (DWORD) size, (LPDWORD) &written, nullptr); + error = error | size != written; + return !error; + } - AsyncRead() : data() {} +#endif - bool isFailed() const { return flags == Flags::FAILED; } - bool isCancelled() const { return flags == Flags::CANCELLED; } + /** + * An async operation to be performed. + * For reading files from disk into memory. + */ - FileSystem::ContentCallback callback; - OutputMemoryStream data; - std::string path; - uint32_t id = 0; - Flags flags; + struct AsyncRead { + enum class Flags : uint32_t { + FAILED = 0, // The read failed due to some error. + CANCELLED // The read was cancelled due to the resource not being needed any more. }; - // The FileSystem that operates on raw on-disk files. - struct DiskFS; + AsyncRead() : data() {} - struct DiskFS : FileSystem { + bool isFailed() const { return flags == Flags::FAILED; } + bool isCancelled() const { return flags == Flags::CANCELLED; } - explicit DiskFS(std::string& path) : sem(0, 0xffff) { - setBasePath(path); - } + FileSystem::ContentCallback callback; + OutputMemoryStream data; + std::string path; + uint32_t id = 0; + Flags flags; + }; - bool hasWork() override { - return workCounter != 0; - } + // The FileSystem that operates on raw on-disk files. + struct DiskFS; - std::string const& getBasePath() const override { return basePath; } - void setBasePath(std::string& path) final { - basePath = Path::normalise(path); - if (!basePath.ends_with('/') && !basePath.ends_with('\\')) - basePath.append("/"); - } + struct DiskFS : FileSystem { - bool saveSync(const Path& path, const uint8_t* data, const size_t size) override { - FileOutput file; - std::string fullPath(basePath.append(path.c_str())); + explicit DiskFS(const std::string& path) : sem(0, 0xffff) { + setBasePath(path); + } - if (!file.open(fullPath)) return false; - bool res = file.write(data, size); - file.close(); + bool hasWork() override { + return workCounter != 0; + } - return res; - } + std::string const& getBasePath() const override { return basePath; } + void setBasePath(const std::string& path) final { + basePath = Path::normalise(path); + if (!basePath.ends_with('/') && !basePath.ends_with('\\')) + basePath.append("/"); + } - bool readSync(const Path& path, struct OutputMemoryStream& content) override { - FileInput file; - std::string fullPath(basePath.append(path.c_str())); + bool saveSync(const Path& path, const uint8_t* data, const size_t size) override { + FileOutput file; + std::string fullPath(basePath.append(path.c_str())); - if (!file.open(fullPath)) return false; + if (!file.open(fullPath)) return false; + bool res = file.write(data, size); + file.close(); - content.resize(file.size()); - if (!file.read(content.dataMut(), content.size())) { - file.close(); - return false; - } + return res; + } + + bool readSync(const Path& path, struct OutputMemoryStream& content) override { + FileInput file; + std::string fullPath(basePath.append(path.c_str())); + + if (!file.open(fullPath)) return false; + content.resize(file.size()); + if (!file.read(content.dataMut(), content.size())) { file.close(); - return true; + return false; } - AsyncHandle readAsync(const Path& file, const ContentCallback& callback) override { - if (!file.isEmpty()) return AsyncHandle::invalid(); + file.close(); + return true; + } - MutexGuard lock(mutex); - workCounter++; + AsyncHandle readAsync(const Path& file, const ContentCallback& callback) override { + if (!file.isEmpty()) return AsyncHandle::invalid(); - AsyncRead& read = queue.emplace_back(); - if (++lastID == 0) lastID++; + ShadowEngine::MutexGuard lock(mutex); + workCounter++; - read.id = lastID; - read.path = file.c_str(); - read.callback = callback; - sem.raise(); + AsyncRead& read = queue.emplace_back(); + if (++lastID == 0) lastID++; - return AsyncHandle(read.id); - } + read.id = lastID; + read.path = file.c_str(); + read.callback = callback; + sem.raise(); - void cancelAsync(AsyncHandle& handle) override { - MutexGuard lock(mutex); + return AsyncHandle(read.id); + } - for (AsyncRead& read : queue) { - if (read.id == handle.value) { - read.flags = AsyncRead::Flags::CANCELLED; - workCounter--; - return; - } - } + void cancelAsync(AsyncHandle& handle) override { + MutexGuard lock(mutex); - for (AsyncRead& read : finished) { - if (read.id == handle.value) { - read.flags = AsyncRead::Flags::CANCELLED; - return; - } + for (AsyncRead& read : queue) { + if (read.id == handle.value) { + read.flags = AsyncRead::Flags::CANCELLED; + workCounter--; + return; } } - bool open(std::string& path, FileInput& file) override { - return file.open(basePath.append(path)); - } - - bool open(std::string& path, FileOutput& file) override { - return file.open(basePath.append(path)); + for (AsyncRead& read : finished) { + if (read.id == handle.value) { + read.flags = AsyncRead::Flags::CANCELLED; + return; + } } + } - bool deleteFile(std::string& path) override { - return std::remove((basePath.append(path).c_str())); - } + bool open(const std::string& path, FileInput& file) override { + return file.open(basePath.append(path)); + } - bool moveFile(std::string& from, std::string& to) override { - try { - std::rename(basePath.append(from).c_str(), basePath.append(to).c_str()); - } catch (std::filesystem::filesystem_error& e) { - return false; - } - return true; - } + bool open(const std::string& path, FileOutput& file) override { + return file.open(basePath.append(path)); + } - bool copyFile(std::string& from, std::string& to) override { - try { - std::filesystem::copy(basePath.append(from).c_str(), basePath.append(to).c_str()); - } catch (std::filesystem::filesystem_error& e) { - return false; - } + bool deleteFile(const std::string& path) override { + return std::remove((basePath.append(path).c_str())); + } - return true; + bool moveFile(const std::string& from, const std::string& to) override { + try { + std::rename(basePath.append(from).c_str(), basePath.append(to).c_str()); + } catch (std::filesystem::filesystem_error& e) { + return false; } + return true; + } - bool fileExists(std::string& path) override { - return std::filesystem::exists(path); + bool copyFile(const std::string& from, const std::string& to) override { + try { + std::filesystem::copy(basePath.append(from).c_str(), basePath.append(to).c_str()); + } catch (std::filesystem::filesystem_error& e) { + return false; } - size_t getLastModified(std::string& path) override { - return std::filesystem::last_write_time(path).time_since_epoch().count(); - } + return true; + } - // TODO: File iterators + bool fileExists(const std::string& path) override { + return std::filesystem::exists(path); + } - void processCallbacks() override { - // TODO: Timeout this function! - for (;;) { - mutex.enter(); - if (finished.empty() || workCounter == 0) { - mutex.exit(); - break; - } + size_t getLastModified(const std::string& path) override { + return std::filesystem::last_write_time(path).time_since_epoch().count(); + } - AsyncRead item = finished[0]; - finished.erase(finished.begin()); - --workCounter; + // TODO: File iterators + void processCallbacks() override { + // TODO: Timeout this function! + for (;;) { + mutex.enter(); + if (finished.empty() || workCounter == 0) { mutex.exit(); + break; + } - if (!item.isCancelled()) - item.callback.invoke(item.data.size(), (const uint8_t*) item.data.data(), !item.isFailed()); + AsyncRead item = finished[0]; + finished.erase(finished.begin()); + --workCounter; - } - } + mutex.exit(); - // TODO: Task Management - std::string basePath; - std::vector queue; - uint64_t workCounter; - std::vector finished; - Mutex mutex; - Semaphore sem; + if (!item.isCancelled()) + item.callback.invoke(item.data.size(), (const uint8_t*) item.data.data(), !item.isFailed()); + } + } - uint32_t lastID; + // TODO: Run Management + std::string basePath; + std::vector queue; + uint64_t workCounter; + std::vector finished; + Mutex mutex; + Semaphore sem; - }; + uint32_t lastID; - struct VFS : DiskFS { - VFS(std::string& root_pack_path) : DiskFS((std::string &) "vfs:/") { - if (!pack.open(root_pack_path)) { - spdlog::error("Unable to open " + root_pack_path + ", please check paths"); - return; - } + }; - const auto count = pack.read(); - for (size_t i = 0; i < count; i++) { - const auto hash = pack.read(); - PackFile& file = packFiles[hash]; - file.offset = pack.read(); - file.size = pack.read(); - } + struct VFS : DiskFS { + VFS(const std::string& root_pack_path) : DiskFS((std::string &) "vfs:/") { + if (!pack.open(root_pack_path)) { + spdlog::error("Unable to open " + root_pack_path + ", please check paths"); + return; } - ~VFS() { pack.close(); } + const auto count = pack.read(); + for (size_t i = 0; i < count; i++) { + const auto hash = pack.read(); + PackFile& file = packFiles[hash]; + file.offset = pack.read(); + file.size = pack.read(); + } + } - bool readSync(const Path& path, OutputMemoryStream& content) override { - std::string basename = Path::getFilename(const_cast(path.get())); - PathHash hash = path.getHash(); + ~VFS() { pack.close(); } - auto i = packFiles.find(hash); - if (i == packFiles.end()) return false; + bool readSync(const Path& path, OutputMemoryStream& content) override { + std::string basename = Path::getFilename(const_cast(path.get())); + PathHash hash = path.getHash(); - content.resize(i->second.size); - MutexGuard lock(mutex); + auto i = packFiles.find(hash); + if (i == packFiles.end()) return false; - const size_t headerSize = sizeof(uint32_t) + packFiles.size() * (3 * sizeof(size_t)); - if (pack.seek(i->second.offset + headerSize) || !pack.read(content.dataMut(), content.size())) { - spdlog::error("Could not read file " + path.get() + " from the pack file."); - return false; - } + content.resize(i->second.size); + MutexGuard lock(mutex); - return true; + const size_t headerSize = sizeof(uint32_t) + packFiles.size() * (3 * sizeof(size_t)); + if (pack.seek(i->second.offset + headerSize) || !pack.read(content.dataMut(), content.size())) { + spdlog::error("Could not read file " + path.get() + " from the pack file."); + return false; } - struct PackFile { - size_t offset; - size_t size; - }; + return true; + } - std::map packFiles; - FileInput pack; + struct PackFile { + size_t offset; + size_t size; }; - std::unique_ptr FileSystem::createDiskFS(std::string &basePath) { - return std::make_unique(basePath); - } + std::map packFiles; + FileInput pack; + }; - std::unique_ptr FileSystem::createVFS(std::string& basePath) { - return std::make_unique(basePath); - } + std::unique_ptr FileSystem::createDiskFS(const std::string& basePath) { + return std::make_unique(basePath); + } + + std::unique_ptr FileSystem::createVFS(const std::string& basePath) { + return std::make_unique(basePath); + } } \ No newline at end of file diff --git a/projs/shadow/shadow-engine/assets/src/fs/hash.cpp b/projs/shadow/shadow-engine/assets/src/fs/hash.cpp index 67970e91..2f01069c 100644 --- a/projs/shadow/shadow-engine/assets/src/fs/hash.cpp +++ b/projs/shadow/shadow-engine/assets/src/fs/hash.cpp @@ -1,148 +1,148 @@ -#include -#include "xxhash.h" +#include +#include namespace ShadowEngine { - StableHash::StableHash(const void *data, uint32_t length) { - hash = XXHash64::hash(data, length, 0); - } - - StableHash::StableHash(std::string &str) { - hash = XXHash64::hash(str.data(), str.size(), 0); - } - - HeapHash::HeapHash(const void *data, uint32_t length) { - hash = XXHash64::hash(data, length, 0); - } - - HeapHash::HeapHash(std::string &str) { - hash = XXHash64::hash(str.data(), str.size(), 0); - } - - HeapHash HeapHash::fromLong(size_t hash) { - HeapHash heap; - heap.hash = hash; - return heap; - } - - HeapHash32 HeapHash32::fromInt(uint32_t hash) { - HeapHash32 heap; - heap.hash = hash; - return heap; - } - - StableHash StableHash::fromLong(size_t hash) { - StableHash stable; - stable.hash = hash; - return stable; - } - - StableHash32 StableHash32::fromInt(uint32_t hash) { - StableHash32 stable; - stable.hash = hash; - return stable; - } - - static uint32_t CRC[256] = { - 0x00000000, 0x77073096, 0xee0e612c, 0x990951ba, 0x076dc419, 0x706af48f, - 0xe963a535, 0x9e6495a3, 0x0edb8832, 0x79dcb8a4, 0xe0d5e91e, 0x97d2d988, - 0x09b64c2b, 0x7eb17cbd, 0xe7b82d07, 0x90bf1d91, 0x1db71064, 0x6ab020f2, - 0xf3b97148, 0x84be41de, 0x1adad47d, 0x6ddde4eb, 0xf4d4b551, 0x83d385c7, - 0x136c9856, 0x646ba8c0, 0xfd62f97a, 0x8a65c9ec, 0x14015c4f, 0x63066cd9, - 0xfa0f3d63, 0x8d080df5, 0x3b6e20c8, 0x4c69105e, 0xd56041e4, 0xa2677172, - 0x3c03e4d1, 0x4b04d447, 0xd20d85fd, 0xa50ab56b, 0x35b5a8fa, 0x42b2986c, - 0xdbbbc9d6, 0xacbcf940, 0x32d86ce3, 0x45df5c75, 0xdcd60dcf, 0xabd13d59, - 0x26d930ac, 0x51de003a, 0xc8d75180, 0xbfd06116, 0x21b4f4b5, 0x56b3c423, - 0xcfba9599, 0xb8bda50f, 0x2802b89e, 0x5f058808, 0xc60cd9b2, 0xb10be924, - 0x2f6f7c87, 0x58684c11, 0xc1611dab, 0xb6662d3d, 0x76dc4190, 0x01db7106, - 0x98d220bc, 0xefd5102a, 0x71b18589, 0x06b6b51f, 0x9fbfe4a5, 0xe8b8d433, - 0x7807c9a2, 0x0f00f934, 0x9609a88e, 0xe10e9818, 0x7f6a0dbb, 0x086d3d2d, - 0x91646c97, 0xe6635c01, 0x6b6b51f4, 0x1c6c6162, 0x856530d8, 0xf262004e, - 0x6c0695ed, 0x1b01a57b, 0x8208f4c1, 0xf50fc457, 0x65b0d9c6, 0x12b7e950, - 0x8bbeb8ea, 0xfcb9887c, 0x62dd1ddf, 0x15da2d49, 0x8cd37cf3, 0xfbd44c65, - 0x4db26158, 0x3ab551ce, 0xa3bc0074, 0xd4bb30e2, 0x4adfa541, 0x3dd895d7, - 0xa4d1c46d, 0xd3d6f4fb, 0x4369e96a, 0x346ed9fc, 0xad678846, 0xda60b8d0, - 0x44042d73, 0x33031de5, 0xaa0a4c5f, 0xdd0d7cc9, 0x5005713c, 0x270241aa, - 0xbe0b1010, 0xc90c2086, 0x5768b525, 0x206f85b3, 0xb966d409, 0xce61e49f, - 0x5edef90e, 0x29d9c998, 0xb0d09822, 0xc7d7a8b4, 0x59b33d17, 0x2eb40d81, - 0xb7bd5c3b, 0xc0ba6cad, 0xedb88320, 0x9abfb3b6, 0x03b6e20c, 0x74b1d29a, - 0xead54739, 0x9dd277af, 0x04db2615, 0x73dc1683, 0xe3630b12, 0x94643b84, - 0x0d6d6a3e, 0x7a6a5aa8, 0xe40ecf0b, 0x9309ff9d, 0x0a00ae27, 0x7d079eb1, - 0xf00f9344, 0x8708a3d2, 0x1e01f268, 0x6906c2fe, 0xf762575d, 0x806567cb, - 0x196c3671, 0x6e6b06e7, 0xfed41b76, 0x89d32be0, 0x10da7a5a, 0x67dd4acc, - 0xf9b9df6f, 0x8ebeeff9, 0x17b7be43, 0x60b08ed5, 0xd6d6a3e8, 0xa1d1937e, - 0x38d8c2c4, 0x4fdff252, 0xd1bb67f1, 0xa6bc5767, 0x3fb506dd, 0x48b2364b, - 0xd80d2bda, 0xaf0a1b4c, 0x36034af6, 0x41047a60, 0xdf60efc3, 0xa867df55, - 0x316e8eef, 0x4669be79, 0xcb61b38c, 0xbc66831a, 0x256fd2a0, 0x5268e236, - 0xcc0c7795, 0xbb0b4703, 0x220216b9, 0x5505262f, 0xc5ba3bbe, 0xb2bd0b28, - 0x2bb45a92, 0x5cb36a04, 0xc2d7ffa7, 0xb5d0cf31, 0x2cd99e8b, 0x5bdeae1d, - 0x9b64c2b0, 0xec63f226, 0x756aa39c, 0x026d930a, 0x9c0906a9, 0xeb0e363f, - 0x72076785, 0x05005713, 0x95bf4a82, 0xe2b87a14, 0x7bb12bae, 0x0cb61b38, - 0x92d28e9b, 0xe5d5be0d, 0x7cdcefb7, 0x0bdbdf21, 0x86d3d2d4, 0xf1d4e242, - 0x68ddb3f8, 0x1fda836e, 0x81be16cd, 0xf6b9265b, 0x6fb077e1, 0x18b74777, - 0x88085ae6, 0xff0f6a70, 0x66063bca, 0x11010b5c, 0x8f659eff, 0xf862ae69, - 0x616bffd3, 0x166ccf45, 0xa00ae278, 0xd70dd2ee, 0x4e048354, 0x3903b3c2, - 0xa7672661, 0xd06016f7, 0x4969474d, 0x3e6e77db, 0xaed16a4a, 0xd9d65adc, - 0x40df0b66, 0x37d83bf0, 0xa9bcae53, 0xdebb9ec5, 0x47b2cf7f, 0x30b5ffe9, - 0xbdbdf21c, 0xcabac28a, 0x53b39330, 0x24b4a3a6, 0xbad03605, 0xcdd70693, - 0x54de5729, 0x23d967bf, 0xb3667a2e, 0xc4614ab8, 0x5d681b02, 0x2a6f2b94, - 0xb40bbe37, 0xc30c8ea1, 0x5a05df1b, 0x2d02ef8d}; - - static uint32_t CRC32(const void* data, uint32_t length) { - const auto* c = static_cast(data); - uint32_t crcTemp = 0xFFFFFFFF; - uint32_t len = length; - while (len) { - crcTemp = (crcTemp >> 8) ^ CRC[(crcTemp & 0xFF) ^ *c]; - --len; ++c; - } - - return ~crcTemp; - } - - StableHash32::StableHash32(const void *data, uint32_t length) { - hash = CRC32(data, length); - } - - StableHash32::StableHash32(std::string &str) { - hash = CRC32(str.data(), str.size()); - } - - static XXHash64 DeferredHashState(0); - - DeferredHash::DeferredHash() { - DeferredHashState = XXHash64(0); - } - - void DeferredHash::insert(const void *data, uint32_t length) { - DeferredHashState.add(data, length); - } - - StableHash32 DeferredHash::submit32() { - const auto result = DeferredHashState.hash(); - return StableHash32::fromInt(uint32_t(result ^ (result >> 32))); - } - - StableHash DeferredHash::submit() { - const auto result = DeferredHashState.hash(); - return StableHash::fromLong(result); - } - - DeferredHeapHash::DeferredHeapHash() { - DeferredHashState = XXHash64(0); - } - - void DeferredHeapHash::insert(const void *data, uint32_t length) { - DeferredHashState.add(data, length); - } - - HeapHash32 DeferredHeapHash::submit32() { - const auto result = DeferredHashState.hash(); - return HeapHash32::fromInt(uint32_t(result ^ (result >> 32))); - } - - HeapHash DeferredHeapHash::submit() { - const auto result = DeferredHashState.hash(); - return HeapHash::fromLong(result); - } + StableHash::StableHash(const void *data, uint32_t length) { + hash = XXHash64::hash(data, length, 0); + } + + StableHash::StableHash(const std::string &str) { + hash = XXHash64::hash(str.data(), str.size(), 0); + } + + HeapHash::HeapHash(const void *data, uint32_t length) { + hash = XXHash64::hash(data, length, 0); + } + + HeapHash::HeapHash(const std::string& str) { + hash = XXHash64::hash(str.data(), str.size(), 0); + } + + HeapHash HeapHash::fromLong(size_t hash) { + HeapHash heap; + heap.hash = hash; + return heap; + } + + HeapHash32 HeapHash32::fromInt(uint32_t hash) { + HeapHash32 heap; + heap.hash = hash; + return heap; + } + + StableHash StableHash::fromLong(size_t hash) { + StableHash stable; + stable.hash = hash; + return stable; + } + + StableHash32 StableHash32::fromInt(uint32_t hash) { + StableHash32 stable; + stable.hash = hash; + return stable; + } + + static uint32_t CRC[256] = { + 0x00000000, 0x77073096, 0xee0e612c, 0x990951ba, 0x076dc419, 0x706af48f, + 0xe963a535, 0x9e6495a3, 0x0edb8832, 0x79dcb8a4, 0xe0d5e91e, 0x97d2d988, + 0x09b64c2b, 0x7eb17cbd, 0xe7b82d07, 0x90bf1d91, 0x1db71064, 0x6ab020f2, + 0xf3b97148, 0x84be41de, 0x1adad47d, 0x6ddde4eb, 0xf4d4b551, 0x83d385c7, + 0x136c9856, 0x646ba8c0, 0xfd62f97a, 0x8a65c9ec, 0x14015c4f, 0x63066cd9, + 0xfa0f3d63, 0x8d080df5, 0x3b6e20c8, 0x4c69105e, 0xd56041e4, 0xa2677172, + 0x3c03e4d1, 0x4b04d447, 0xd20d85fd, 0xa50ab56b, 0x35b5a8fa, 0x42b2986c, + 0xdbbbc9d6, 0xacbcf940, 0x32d86ce3, 0x45df5c75, 0xdcd60dcf, 0xabd13d59, + 0x26d930ac, 0x51de003a, 0xc8d75180, 0xbfd06116, 0x21b4f4b5, 0x56b3c423, + 0xcfba9599, 0xb8bda50f, 0x2802b89e, 0x5f058808, 0xc60cd9b2, 0xb10be924, + 0x2f6f7c87, 0x58684c11, 0xc1611dab, 0xb6662d3d, 0x76dc4190, 0x01db7106, + 0x98d220bc, 0xefd5102a, 0x71b18589, 0x06b6b51f, 0x9fbfe4a5, 0xe8b8d433, + 0x7807c9a2, 0x0f00f934, 0x9609a88e, 0xe10e9818, 0x7f6a0dbb, 0x086d3d2d, + 0x91646c97, 0xe6635c01, 0x6b6b51f4, 0x1c6c6162, 0x856530d8, 0xf262004e, + 0x6c0695ed, 0x1b01a57b, 0x8208f4c1, 0xf50fc457, 0x65b0d9c6, 0x12b7e950, + 0x8bbeb8ea, 0xfcb9887c, 0x62dd1ddf, 0x15da2d49, 0x8cd37cf3, 0xfbd44c65, + 0x4db26158, 0x3ab551ce, 0xa3bc0074, 0xd4bb30e2, 0x4adfa541, 0x3dd895d7, + 0xa4d1c46d, 0xd3d6f4fb, 0x4369e96a, 0x346ed9fc, 0xad678846, 0xda60b8d0, + 0x44042d73, 0x33031de5, 0xaa0a4c5f, 0xdd0d7cc9, 0x5005713c, 0x270241aa, + 0xbe0b1010, 0xc90c2086, 0x5768b525, 0x206f85b3, 0xb966d409, 0xce61e49f, + 0x5edef90e, 0x29d9c998, 0xb0d09822, 0xc7d7a8b4, 0x59b33d17, 0x2eb40d81, + 0xb7bd5c3b, 0xc0ba6cad, 0xedb88320, 0x9abfb3b6, 0x03b6e20c, 0x74b1d29a, + 0xead54739, 0x9dd277af, 0x04db2615, 0x73dc1683, 0xe3630b12, 0x94643b84, + 0x0d6d6a3e, 0x7a6a5aa8, 0xe40ecf0b, 0x9309ff9d, 0x0a00ae27, 0x7d079eb1, + 0xf00f9344, 0x8708a3d2, 0x1e01f268, 0x6906c2fe, 0xf762575d, 0x806567cb, + 0x196c3671, 0x6e6b06e7, 0xfed41b76, 0x89d32be0, 0x10da7a5a, 0x67dd4acc, + 0xf9b9df6f, 0x8ebeeff9, 0x17b7be43, 0x60b08ed5, 0xd6d6a3e8, 0xa1d1937e, + 0x38d8c2c4, 0x4fdff252, 0xd1bb67f1, 0xa6bc5767, 0x3fb506dd, 0x48b2364b, + 0xd80d2bda, 0xaf0a1b4c, 0x36034af6, 0x41047a60, 0xdf60efc3, 0xa867df55, + 0x316e8eef, 0x4669be79, 0xcb61b38c, 0xbc66831a, 0x256fd2a0, 0x5268e236, + 0xcc0c7795, 0xbb0b4703, 0x220216b9, 0x5505262f, 0xc5ba3bbe, 0xb2bd0b28, + 0x2bb45a92, 0x5cb36a04, 0xc2d7ffa7, 0xb5d0cf31, 0x2cd99e8b, 0x5bdeae1d, + 0x9b64c2b0, 0xec63f226, 0x756aa39c, 0x026d930a, 0x9c0906a9, 0xeb0e363f, + 0x72076785, 0x05005713, 0x95bf4a82, 0xe2b87a14, 0x7bb12bae, 0x0cb61b38, + 0x92d28e9b, 0xe5d5be0d, 0x7cdcefb7, 0x0bdbdf21, 0x86d3d2d4, 0xf1d4e242, + 0x68ddb3f8, 0x1fda836e, 0x81be16cd, 0xf6b9265b, 0x6fb077e1, 0x18b74777, + 0x88085ae6, 0xff0f6a70, 0x66063bca, 0x11010b5c, 0x8f659eff, 0xf862ae69, + 0x616bffd3, 0x166ccf45, 0xa00ae278, 0xd70dd2ee, 0x4e048354, 0x3903b3c2, + 0xa7672661, 0xd06016f7, 0x4969474d, 0x3e6e77db, 0xaed16a4a, 0xd9d65adc, + 0x40df0b66, 0x37d83bf0, 0xa9bcae53, 0xdebb9ec5, 0x47b2cf7f, 0x30b5ffe9, + 0xbdbdf21c, 0xcabac28a, 0x53b39330, 0x24b4a3a6, 0xbad03605, 0xcdd70693, + 0x54de5729, 0x23d967bf, 0xb3667a2e, 0xc4614ab8, 0x5d681b02, 0x2a6f2b94, + 0xb40bbe37, 0xc30c8ea1, 0x5a05df1b, 0x2d02ef8d}; + + static uint32_t CRC32(const void* data, uint32_t length) { + const auto* c = static_cast(data); + uint32_t crcTemp = 0xFFFFFFFF; + uint32_t len = length; + while (len) { + crcTemp = (crcTemp >> 8) ^ CRC[(crcTemp & 0xFF) ^ *c]; + --len; ++c; + } + + return ~crcTemp; + } + + StableHash32::StableHash32(const void *data, uint32_t length) { + hash = CRC32(data, length); + } + + StableHash32::StableHash32(const std::string &str) { + hash = CRC32(str.data(), str.size()); + } + + static XXHash64 DeferredHashState(0); + + DeferredHash::DeferredHash() { + DeferredHashState = XXHash64(0); + } + + void DeferredHash::insert(const void *data, uint32_t length) { + DeferredHashState.add(data, length); + } + + StableHash32 DeferredHash::submit32() { + const auto result = DeferredHashState.hash(); + return StableHash32::fromInt(uint32_t(result ^ (result >> 32))); + } + + StableHash DeferredHash::submit() { + const auto result = DeferredHashState.hash(); + return StableHash::fromLong(result); + } + + DeferredHeapHash::DeferredHeapHash() { + DeferredHashState = XXHash64(0); + } + + void DeferredHeapHash::insert(const void *data, uint32_t length) { + DeferredHashState.add(data, length); + } + + HeapHash32 DeferredHeapHash::submit32() { + const auto result = DeferredHashState.hash(); + return HeapHash32::fromInt(uint32_t(result ^ (result >> 32))); + } + + HeapHash DeferredHeapHash::submit() { + const auto result = DeferredHashState.hash(); + return HeapHash::fromLong(result); + } } \ No newline at end of file diff --git a/projs/shadow/shadow-engine/assets/src/fs/iostream.cpp b/projs/shadow/shadow-engine/assets/src/fs/iostream.cpp index a8c1e93a..f02f7bb6 100644 --- a/projs/shadow/shadow-engine/assets/src/fs/iostream.cpp +++ b/projs/shadow/shadow-engine/assets/src/fs/iostream.cpp @@ -1,5 +1,6 @@ -#include + #include +#include "shadow/assets/fs/iostream.h" namespace ShadowEngine { diff --git a/projs/shadow/shadow-engine/assets/src/fs/path.cpp b/projs/shadow/shadow-engine/assets/src/fs/path.cpp index 8766231d..d63ca3d9 100644 --- a/projs/shadow/shadow-engine/assets/src/fs/path.cpp +++ b/projs/shadow/shadow-engine/assets/src/fs/path.cpp @@ -1,6 +1,9 @@ -#include -#include -#include + +#include +#include +#include +#include +#include namespace ShadowEngine { @@ -37,7 +40,7 @@ namespace ShadowEngine { return path != rhs.path; } - std::string Path::normalise(std::string &str) { + std::string Path::normalise(const std::string &str) { bool prevSlash = false; std::string temp; @@ -72,35 +75,35 @@ namespace ShadowEngine { return temp; } - std::string Path::getPrelude(std::string &path) { + std::string Path::getPrelude(const std::string &path) { return path.substr(0, path.find_first_of(":")); } - std::string Path::getDomain(std::string &path) { + std::string Path::getDomain(const std::string &path) { return path.substr(path.find_first_of(":"), path.find_first_of("/")); } - std::string Path::getDirectory(std::string &path) { + std::string Path::getDirectory(const std::string &path) { return path.substr(path.find_first_of(":"), path.find_last_of("/")); } - std::string Path::getFilename(std::string &path) { + std::string Path::getFilename(const std::string &path) { return path.substr(path.find_last_of("/"), path.find_last_of(".")); } - std::string Path::getExtension(std::string &path) { + std::string Path::getExtension(const std::string &path) { return path.substr(path.find_last_of("."), path.length()); } - std::string Path::replaceExtension(std::string &path, std::string &newExt) { + std::string Path::replaceExtension(const std::string &path, const std::string &newExt) { return path.substr(0, path.length() - newExt.length()).append(newExt); } - bool Path::hasExtension(std::string &path, std::string &ext) { + bool Path::hasExtension(const std::string &path, const std::string &ext) { return path.find_last_of(ext) == path.length() - ext.length(); } - PathInfo::PathInfo(std::string &str) { + PathInfo::PathInfo(const std::string &str) { std::string normalised = Path::normalise(str); std::string preludeS = Path::getPrelude(normalised); diff --git a/projs/shadow/shadow-engine/assets/src/management/synchronization.cpp b/projs/shadow/shadow-engine/assets/src/management/synchronization.cpp index 985109e3..910db104 100644 --- a/projs/shadow/shadow-engine/assets/src/management/synchronization.cpp +++ b/projs/shadow/shadow-engine/assets/src/management/synchronization.cpp @@ -1,4 +1,3 @@ -#include // This doesn't work on Linux. Sucks to be you? dpeter won't let me do system-specific source files. #ifdef _WIN32 @@ -6,7 +5,7 @@ #include #define WIN32_LEAN_AND_MEAN #include - +#include "shadow/assets/management/synchronization.h" namespace ShadowEngine { struct NewPlaceholder {}; } inline void* operator new(size_t, ShadowEngine::NewPlaceholder, void* where) { return where; } diff --git a/projs/shadow/shadow-engine/assets/src/resource/Resource.cpp b/projs/shadow/shadow-engine/assets/src/resource/Resource.cpp new file mode 100644 index 00000000..4319b22a --- /dev/null +++ b/projs/shadow/shadow-engine/assets/src/resource/Resource.cpp @@ -0,0 +1,198 @@ +#include "shadow/assets/resource/Resource.h" +#include "shadow/assets/fs/file.h" +#include "shadow/assets/management/delegate.h" +#include +#include + +#include + +namespace ShadowEngine { + const uint32_t ResourceHeader::MAGIC = 'VXIP'; + + ResourceType::ResourceType(const std::string& name) { + hash = HeapHash(name); + } + + Resource::Resource(ShadowEngine::Path path, ShadowEngine::ResourceTypeManager &manager) + : references(0), + emptyDependencies(0), + failedDependencies(0), + state(State::EMPTY), + desiredState(State::EMPTY), + path(std::move(path)), + size(), + callback(), + manager(manager), + handle(FileSystem::AsyncHandle::invalid()) { + } + + Resource::~Resource() = default; + + void Resource::refresh() { + if (state == State::EMPTY) return; + + const State old = state; + state = State::EMPTY; + callback.invoke(old, state, *this); + checkState(); + } + + void Resource::checkState() { + State old = state; + if (failedDependencies > 0 && state != State::FAILED) { + state = State::FAILED; + } else if (failedDependencies == 0) { + if (emptyDependencies > 0 && state != State::EMPTY) + state = State::EMPTY; + + if (emptyDependencies == 0 && state != State::READY && desiredState != State::EMPTY) { + onReadying(); + + if (emptyDependencies != 0 || state == State::READY || desiredState == State::EMPTY) + return; + + if (failedDependencies != 0) { + checkState(); + return; + } + + state = State::READY; + } + } + callback.invoke(old, state, *this); + } + + void Resource::fileLoaded(size_t fileSize, const uint8_t *mem, bool success) { + handle = FileSystem::AsyncHandle::invalid(); + if (desiredState != State::READY) return; + + if (!success) { + ResourceManager& owner = getManager().getOwner(); + if (!hooked && owner.isHooked()) { + if (owner.onLoad(*this) == ResourceManager::LoadHook::Action::DEFERRED) { + hooked = true; + desiredState = State::READY; + increaseReferences(); + return; + } + } + + --emptyDependencies; + ++failedDependencies; + checkState(); + handle = FileSystem::AsyncHandle::invalid(); + return; + } + + const auto* header = (const ResourceHeader*) mem; + + if (size < sizeof(*header)) { + spdlog::error("Invalid resource: ", path.get(), ": size mismatch. Expected ", fileSize, ", got " , sizeof(*header)); + failedDependencies++; + } else if (header->magic != ResourceHeader::MAGIC) { + spdlog::error("Invalid resource: " , path.get(), ": magic number mismatch. Expected " , ResourceHeader::MAGIC, ", got ", header->magic); + failedDependencies++; + } else if (header->version > 0) { + spdlog::error("Invalid resource: ", path.get(), ": verison mismatch. Expected 0, got ", header->version); + failedDependencies++; + } else { + // TODO: Compression? + if (!load(size - sizeof(*header), mem + sizeof(*header))) + failedDependencies++; + size = header->decompressedSize; + } + + emptyDependencies--; + checkState(); + handle = FileSystem::AsyncHandle::invalid(); + } + + void Resource::performUnload() { + if (handle.valid()) { + FileSystem& fs = manager.getOwner().getFileSystem(); + fs.cancelAsync(handle); + handle = FileSystem::AsyncHandle::invalid(); + } + + hooked = false; + desiredState = State::EMPTY; + unload(); + + size = 0; + emptyDependencies = 1; + failedDependencies = 0; + checkState(); + } + + void Resource::onCreated(ShadowEngine::Resource::State newState) { + state = newState; + desiredState = State::READY; + failedDependencies = state == State::FAILED ? 1 : 0; + emptyDependencies = 0; + } + + void Resource::doLoad() { + if (desiredState == State::READY) return; + desiredState = State::READY; + + if (handle.valid()) return; + + FileSystem& fs = manager.getOwner().getFileSystem(); + FileSystem::ContentCallback cb = makeDelegate<&Resource::fileLoaded>(this); + + const PathHash hash = path.getHash(); + Path resourcePath("./resources/" + std::to_string(hash.getHash()) + ".res"); + handle = fs.readAsync(resourcePath, cb); + } + + void Resource::addDependency(ShadowEngine::Resource &dependent) { + dependent.callback.bind<&Resource::stateChanged>(this); + if (dependent.isEmpty()) emptyDependencies++; + if (dependent.isFailure()) failedDependencies++; + + checkState(); + } + + void Resource::removeDependency(ShadowEngine::Resource &dependent) { + dependent.callback.unbind<&Resource::stateChanged>(this); + if (dependent.isEmpty()) --emptyDependencies; + if (dependent.isFailure()) --failedDependencies; + + checkState(); + } + + uint32_t Resource::decreaseReferences() { + --references; + if (references == 0 && manager.unloadEnabled) + performUnload(); + + return references; + } + + void Resource::stateChanged(ShadowEngine::Resource::State old, ShadowEngine::Resource::State newState, + ShadowEngine::Resource &) { + if (old == State::EMPTY) --emptyDependencies; + if (old == State::FAILED) --failedDependencies; + + if (newState == State::EMPTY) ++emptyDependencies; + if (newState == State::FAILED) ++failedDependencies; + + checkState(); + } + + const ResourceType PrefabResource::TYPE("prefab"); + + PrefabResource::PrefabResource(const ShadowEngine::Path &path, + ShadowEngine::ResourceTypeManager &resource_manager) : Resource(path, resource_manager) {} + + ResourceType PrefabResource::getType() const { return TYPE; } + + void PrefabResource::unload() { data.clear(); } + + bool PrefabResource::load(size_t size, const uint8_t *mem) { + data.resize(size); + memcpy(data.dataMut(), mem, size); + hash = StableHash(mem, size); + return true; + } +} \ No newline at end of file diff --git a/projs/shadow/shadow-engine/shadow-assets/src/resource/ResourceManager.cpp b/projs/shadow/shadow-engine/assets/src/resource/ResourceManager.cpp similarity index 97% rename from projs/shadow/shadow-engine/shadow-assets/src/resource/ResourceManager.cpp rename to projs/shadow/shadow-engine/assets/src/resource/ResourceManager.cpp index 163183d5..d52e16b9 100644 --- a/projs/shadow/shadow-engine/shadow-assets/src/resource/ResourceManager.cpp +++ b/projs/shadow/shadow-engine/assets/src/resource/ResourceManager.cpp @@ -1,6 +1,8 @@ -#include "ResourceManager.h" -#include "Resource.h" + #include "spdlog/spdlog.h" +#include "shadow/assets/resource/Resource.h" +#include "shadow/assets/resource/ResourceManager.h" +#include "shadow/assets/fs/path.h" namespace ShadowEngine { diff --git a/projs/shadow/shadow-engine/assets/src/str/string.cpp b/projs/shadow/shadow-engine/assets/src/str/string.cpp index 6cb12eea..96fcc596 100644 --- a/projs/shadow/shadow-engine/assets/src/str/string.cpp +++ b/projs/shadow/shadow-engine/assets/src/str/string.cpp @@ -1,4 +1,6 @@ -#include +#include + + namespace ShadowEngine::Str { std::string toLower(const std::string& str) { diff --git a/projs/shadow/shadow-engine/core/inc/shadow/core/Module.h b/projs/shadow/shadow-engine/core/inc/shadow/core/Module.h index 3f081a44..9a1bcdff 100644 --- a/projs/shadow/shadow-engine/core/inc/shadow/core/Module.h +++ b/projs/shadow/shadow-engine/core/inc/shadow/core/Module.h @@ -4,7 +4,6 @@ #include #include "shadow/SHObject.h" -#include "shadow/renderer/vulkan/vlkx/vulkan/abstraction/Commands.h" namespace SH { @@ -43,20 +42,5 @@ namespace SH { }; }; -/** - * A class especially for modules that are renderers. - * Allows the engine to access state from the renderer independent of implementation. - */ - class RendererModule : public Module { - public: - // Begin the render pass using the given commands. - // Will call out through the regular modules to gather geometry to render. - virtual void BeginRenderPass(const std::unique_ptr &commands) = 0; - - virtual void EnableEditor() = 0; - - virtual VkExtent2D GetRenderExtent() = 0; - }; - } diff --git a/projs/shadow/shadow-engine/core/inc/shadow/core/ShadowApplication.h b/projs/shadow/shadow-engine/core/inc/shadow/core/ShadowApplication.h index 2a18382f..f04bcbf9 100644 --- a/projs/shadow/shadow-engine/core/inc/shadow/core/ShadowApplication.h +++ b/projs/shadow/shadow-engine/core/inc/shadow/core/ShadowApplication.h @@ -6,6 +6,7 @@ #include "imgui_impl_sdl2.h" #include "imgui_impl_vulkan.h" #include "shadow/event-bus/event_bus.h" +#include "shadow/assets/fs/file.h" #include @@ -16,12 +17,15 @@ namespace SH { /// class API ShadowApplication : SH::SHObject { SHObject_Base(ShadowApplication) - /// + public: + static std::unique_ptr diskFS; + /// /// This is the singleton instance /// static ShadowApplication *instance; + private: - /// + /// /// The module manager instance /// ModuleManager moduleManager; diff --git a/projs/shadow/shadow-engine/core/inc/shadow/core/ShadowWindow.h b/projs/shadow/shadow-engine/core/inc/shadow/core/ShadowWindow.h index 67e3e36c..ea26db2a 100644 --- a/projs/shadow/shadow-engine/core/inc/shadow/core/ShadowWindow.h +++ b/projs/shadow/shadow-engine/core/inc/shadow/core/ShadowWindow.h @@ -6,7 +6,6 @@ namespace SH { class ShadowWindow { public: - int Height; int Width; @@ -14,9 +13,6 @@ namespace SH { SDL_Surface *sdlSurface = NULL; - - //ShadowEngine::Ref context; - ShadowWindow(int W, int H); ~ShadowWindow(); diff --git a/projs/shadow/shadow-engine/core/inc/shadow/event-bus/events.h b/projs/shadow/shadow-engine/core/inc/shadow/event-bus/events.h index d7eb08e4..01e75b3a 100644 --- a/projs/shadow/shadow-engine/core/inc/shadow/event-bus/events.h +++ b/projs/shadow/shadow-engine/core/inc/shadow/event-bus/events.h @@ -18,14 +18,6 @@ namespace SH::Events { SDL_Event event; }; - class OverlayRender : public Event { - SHObject_Base(OverlayRender) - }; - - class PreRender : public Event { - SHObject_Base(PreRender) - }; - class Recreate : public Event { SHObject_Base(Recreate) }; diff --git a/projs/shadow/shadow-engine/core/src/core/ShadowApplication.cpp b/projs/shadow/shadow-engine/core/src/core/ShadowApplication.cpp index 6f2b50f6..84e1a272 100644 --- a/projs/shadow/shadow-engine/core/src/core/ShadowApplication.cpp +++ b/projs/shadow/shadow-engine/core/src/core/ShadowApplication.cpp @@ -5,10 +5,9 @@ #include "runtime/Runtime.h" #include "shadow/core/ShadowApplication.h" #include "shadow/core/Time.h" -#include "shadow/renderer/vulkan/vlkx/vulkan/abstraction/Commands.h" -#include "shadow/renderer/vulkan/vlkx/vulkan/VulkanModule.h" #include "shadow/platform/console-setup.h" +#include "shadow/assets/fs/file.h" #define CATCH(x) \ try { x } catch (std::exception& e) { spdlog::error(e.what()); exit(0); } @@ -21,9 +20,7 @@ namespace SH { ShadowApplication *ShadowApplication::instance = nullptr; - std::unique_ptr renderCommands; - - std::weak_ptr renderer; + std::unique_ptr ShadowApplication::diskFS = ShadowEngine::FileSystem::createDiskFS("./"); ShadowApplication::ShadowApplication(int argc, char *argv[]) { instance = this; @@ -64,9 +61,7 @@ namespace SH { moduleManager.Init(); - renderer = moduleManager.GetById("module:/renderer/vulkan"); - renderCommands = std::make_unique(2); } void ShadowApplication::Start() { @@ -79,16 +74,7 @@ namespace SH { if (event.type == SDL_QUIT) running = false; } - - eventBus.fire(SH::Events::PreRender()); - - if (!renderer.expired()) { - auto r = renderer.lock(); - r->BeginRenderPass(renderCommands); - } - - renderCommands->nextFrame(); - Time::UpdateTime(); + Timer::UpdateTime(); } //moduleManager.Destroy(); diff --git a/projs/shadow/shadow-engine/core/src/event_bus/event_bus.cpp b/projs/shadow/shadow-engine/core/src/event_bus/event_bus.cpp index 44783998..943201ae 100644 --- a/projs/shadow/shadow-engine/core/src/event_bus/event_bus.cpp +++ b/projs/shadow/shadow-engine/core/src/event_bus/event_bus.cpp @@ -9,14 +9,6 @@ namespace SH::Events { Event_Impl(SDLEvent) - SHObject_Base_Impl(OverlayRender) - - Event_Impl(OverlayRender) - - SHObject_Base_Impl(PreRender) - - Event_Impl(PreRender) - SHObject_Base_Impl(Recreate) Event_Impl(Recreate) diff --git a/projs/shadow/shadow-engine/shadow-assets/src/resource/Resource.cpp b/projs/shadow/shadow-engine/shadow-assets/src/resource/Resource.cpp deleted file mode 100644 index 46a2323c..00000000 --- a/projs/shadow/shadow-engine/shadow-assets/src/resource/Resource.cpp +++ /dev/null @@ -1,194 +0,0 @@ -#include -#include -#include - -namespace ShadowEngine { - - ResourceType::ResourceType(std::string& name) { - hash = HeapHash(name); - } - - Resource::Resource(const ShadowEngine::Path& path, ShadowEngine::ResourceTypeManager &manager) - : references(0), - emptyDependencies(0), - failedDependencies(0), - state(State::EMPTY), - desiredState(State::EMPTY), - path(path), - size(), - callback(), - manager(manager), - handle(FileSystem::AsyncHandle::invalid()) { - } - - Resource::~Resource() = default; - - void Resource::refresh() { - if (state == State::EMPTY) return; - - const State old = state; - state = State::EMPTY; - callback.invoke(old, state, *this); - checkState(); - } - - void Resource::checkState() { - State old = state; - if (failedDependencies > 0 && state != State::FAILED) { - state = State::FAILED; - } else if (failedDependencies == 0) { - if (emptyDependencies > 0 && state != State::EMPTY) - state = State::EMPTY; - - if (emptyDependencies == 0 && state != State::READY && desiredState != State::EMPTY) { - onReadying(); - - if (emptyDependencies != 0 || state == State::READY || desiredState == State::EMPTY) - return; - - if (failedDependencies != 0) { - checkState(); - return; - } - - state = State::READY; - } - } - callback.invoke(old, state, *this); - } - - void Resource::fileLoaded(size_t fileSize, const uint8_t *mem, bool success) { - handle = FileSystem::AsyncHandle::invalid(); - if (desiredState != State::READY) return; - - if (!success) { - ResourceManager& owner = getManager().getOwner(); - if (!hooked && owner.isHooked()) { - if (owner.onLoad(*this) == ResourceManager::LoadHook::Action::DEFERRED) { - hooked = true; - desiredState = State::READY; - increaseReferences(); - return; - } - } - - --emptyDependencies; - ++failedDependencies; - checkState(); - handle = FileSystem::AsyncHandle::invalid(); - return; - } - - const ResourceHeader* header = (const ResourceHeader*) mem; - - if (size < sizeof(*header)) { - spdlog::error("Invalid resource: ", path.get(), ": size mismatch. Expected ", fileSize, ", got " , sizeof(*header)); - failedDependencies++; - } else if (header->magic != ResourceHeader::MAGIC) { - spdlog::error("Invalid resource: " , path.get(), ": magic number mismatch. Expected " , ResourceHeader::MAGIC, ", got ", header->magic); - failedDependencies++; - } else if (header->version > 0) { - spdlog::error("Invalid resource: ", path.get(), ": verison mismatch. Expected 0, got ", header->version); - failedDependencies++; - } else { - // TODO: Compression? - if (!load(size - sizeof(*header), mem + sizeof(*header))) - failedDependencies++; - size = header->decompressedSize; - } - - emptyDependencies--; - checkState(); - handle = FileSystem::AsyncHandle::invalid(); - } - - void Resource::performUnload() { - if (handle.valid()) { - FileSystem& fs = manager.getOwner().getFileSystem(); - fs.cancelAsync(handle); - handle = FileSystem::AsyncHandle::invalid(); - } - - hooked = false; - desiredState = State::EMPTY; - unload(); - - size = 0; - emptyDependencies = 1; - failedDependencies = 0; - checkState(); - } - - void Resource::onCreated(ShadowEngine::Resource::State newState) { - state = newState; - desiredState = State::READY; - failedDependencies = state == State::FAILED ? 1 : 0; - emptyDependencies = 0; - } - - void Resource::doLoad() { - if (desiredState == State::READY) return; - desiredState = State::READY; - - if (handle.valid()) return; - - FileSystem& fs = manager.getOwner().getFileSystem(); - FileSystem::ContentCallback cb = makeDelegate<&Resource::fileLoaded>(this); - - const PathHash hash = path.getHash(); - Path resourcePath("./resources/" + std::to_string(hash.getHash()) + ".res"); - handle = fs.readAsync(resourcePath, cb); - } - - void Resource::addDependency(ShadowEngine::Resource &dependent) { - dependent.callback.bind<&Resource::stateChanged>(this); - if (dependent.isEmpty()) emptyDependencies++; - if (dependent.isFailure()) failedDependencies++; - - checkState(); - } - - void Resource::removeDependency(ShadowEngine::Resource &dependent) { - dependent.callback.unbind<&Resource::stateChanged>(this); - if (dependent.isEmpty()) --emptyDependencies; - if (dependent.isFailure()) --failedDependencies; - - checkState(); - } - - uint32_t Resource::decreaseReferences() { - --references; - if (references == 0 && manager.unloadEnabled) - performUnload(); - - return references; - } - - void Resource::stateChanged(ShadowEngine::Resource::State old, ShadowEngine::Resource::State newState, - ShadowEngine::Resource &) { - if (old == State::EMPTY) --emptyDependencies; - if (old == State::FAILED) --failedDependencies; - - if (newState == State::EMPTY) ++emptyDependencies; - if (newState == State::FAILED) ++failedDependencies; - - checkState(); - } - - static std::string type("prefab"); - const ResourceType PrefabResource::TYPE(type); - - PrefabResource::PrefabResource(const ShadowEngine::Path &path, - ShadowEngine::ResourceTypeManager &resource_manager) : Resource(path, resource_manager) {} - - ResourceType PrefabResource::getType() const { return TYPE; } - - void PrefabResource::unload() { data.clear(); } - - bool PrefabResource::load(size_t size, const uint8_t *mem) { - data.resize(size); - memcpy(data.dataMut(), mem, size); - hash = StableHash(mem, size); - return true; - } -} \ No newline at end of file diff --git a/projs/shadow/shadow-engine/shadow-assets/src/resource/Resource.h b/projs/shadow/shadow-engine/shadow-assets/src/resource/Resource.h deleted file mode 100644 index a26af607..00000000 --- a/projs/shadow/shadow-engine/shadow-assets/src/resource/Resource.h +++ /dev/null @@ -1,140 +0,0 @@ -#pragma once - -#include "fs/hash.h" -#include "fs/path.h" -#include "fs/file.h" -#include - -namespace ShadowEngine { - - /** - * A runtime-only struct that determines the type of a resource - whether it be a texture, mesh, animation, or other data. - * Provides some specializations for living in a map. - */ - struct ResourceType { - ResourceType() = default; - explicit ResourceType(std::string& name); - bool operator!=(const ResourceType& o) const { return o.hash != hash; } - bool operator==(const ResourceType& o) const { return o.hash == hash; } - bool operator< (const ResourceType& o) const { return o.hash.getHash() < hash.getHash(); } - bool isValid() const { return hash.getHash() != 0; } - - HeapHash hash; - }; - - // A Resource Type that is guaranteed to be invalid. - static std::string empty; - const ResourceType INVALID_RESOURCE(empty); - - // A specialization of HashFunc for ResourceTypes, since they already have a HeapHash within. - template<> struct HashFunc { - static uint32_t get(const ResourceType& key) { return HashFunc::get(key.hash); } - }; - -#pragma pack(1) - struct ResourceHeader { - static const uint32_t MAGIC = 'VXIP'; - uint32_t magic = MAGIC; // VXI Package header - uint32_t version = 0; - uint32_t flags = 0; - uint32_t padding = 0; - uint32_t decompressedSize = 0; - }; -#pragma pack() - - /** - * A basic Resource type. - * Represents a single file loaded from disk. - * May have dependencies on other Resources, and other Resources may depend on this. - * Resources are reference-counted, and are removed when they go out of usage. - */ - - struct Resource { - - friend struct ResourceTypeManager; - friend struct ResourceManager; - - enum class State : uint32_t { - EMPTY = 0, - READY, - FAILED - }; - - using Observer = DelegateList; - - virtual ~Resource(); - virtual ResourceType getType() const = 0; - State getState() const { return state; } - - bool isEmpty() const { return state == State::EMPTY; } - bool isReady() const { return state == State::READY; } - bool isFailure() const { return state == State::FAILED; } - - uint32_t getReferenceCount() const { return references; } - - Observer const& getCallback() const { return callback; } - size_t getSize() const { return size; } - - const Path& getPath() const { return path; } - - struct ResourceTypeManager& getManager() { return manager; } - - uint32_t decreaseReferences(); - uint32_t increaseReferences() { return references++; } - - bool toInitialize() const { return desiredState == State::READY; } - bool isHooked() const { return hooked; } - - template void onLoaded(C* instance) { - callback.bind(instance); - if (isReady()) (instance->*Function)(State::READY, State::READY, *this); - } - - protected: - Resource(const Path& path, ResourceTypeManager& manager); - - virtual void onReadying() {} - virtual void unload() = 0; - virtual bool load(size_t size, const uint8_t* mem) = 0; - - void onCreated(State newState); - void performUnload(); - void addDependency(Resource& dependent); - void removeDependency(Resource& dependent); - void checkState(); - void refresh(); - - State desiredState; - uint16_t emptyDependencies; - ResourceTypeManager& manager; - - private: - - void doLoad(); - void fileLoaded(size_t fileSize, const uint8_t* mem, bool success); - void stateChanged(State old, State newState, Resource&); - - Resource(const Resource&) = delete; - void operator=(const Resource&) = delete; - - Observer callback; - size_t size; - Path path; - uint32_t references; - uint16_t failedDependencies; - FileSystem::AsyncHandle handle; - State state; - bool hooked = false; - }; - - struct PrefabResource : Resource { - PrefabResource(const Path& path, ResourceTypeManager& resource_manager); - ResourceType getType() const override; - void unload() override; - bool load(size_t size, const uint8_t* data) override; - - OutputMemoryStream data; - StableHash hash; - static const ResourceType TYPE; - }; -} \ No newline at end of file diff --git a/projs/shadow/shadow-engine/utility/inc/shadow/util/string-helpers.h b/projs/shadow/shadow-engine/utility/inc/shadow/util/string-helpers.h index 68f05e19..671793c0 100644 --- a/projs/shadow/shadow-engine/utility/inc/shadow/util/string-helpers.h +++ b/projs/shadow/shadow-engine/utility/inc/shadow/util/string-helpers.h @@ -16,5 +16,19 @@ namespace SH { std::vector API explode(const std::string &s, const char &c); std::string API substr_range(std::string const &str, size_t start, size_t end); + + void StringConvert(const std::string& from, std::wstring& to); + + void StringConvert(const std::wstring& from, std::string& to); + +// Parameter - to - must be pre-allocated! +// dest_size_in_characters : number of characters in the pre-allocated string memory +// returns result string length + int StringConvert(const char* from, wchar_t* to, int dest_size_in_characters = -1); + +// Parameter - to - must be pre-allocated! +// dest_size_in_characters : number of characters in the pre-allocated string memory +// returns result string length + int StringConvert(const wchar_t* from, char* to, int dest_size_in_characters = -1); } } \ No newline at end of file diff --git a/projs/shadow/shadow-engine/utility/src/string-helpers.cpp b/projs/shadow/shadow-engine/utility/src/string-helpers.cpp index f768df66..324f7412 100644 --- a/projs/shadow/shadow-engine/utility/src/string-helpers.cpp +++ b/projs/shadow/shadow-engine/utility/src/string-helpers.cpp @@ -1,8 +1,11 @@ +#include #include "shadow/util/string-helpers.h" namespace SH::Util::Str { + #define CP_UTF8 65001 + std::vector explode(const std::string &s, const char &c) { std::string buff; std::vector v; @@ -30,4 +33,75 @@ namespace SH::Util::Str { std::string substr_range(std::string const &str, size_t start, size_t end) { return str.substr(start, end - start); } + + + void StringConvert(const std::string& from, std::wstring& to) { +#ifdef _WIN32 + int num = MultiByteToWideChar(CP_UTF8, 0, from.c_str(), -1, NULL, 0); + if (num > 0) { + to.resize(size_t(num) - 1); + MultiByteToWideChar(CP_UTF8, 0, from.c_str(), -1, &to[0], num); + } +#else + std::wstring_convert> cv; + to = cv.from_bytes(from); +#endif // _WIN32 + } + + void StringConvert(const std::wstring& from, std::string& to) { +#ifdef _WIN32 + int num = WideCharToMultiByte(CP_UTF8, 0, from.c_str(), -1, NULL, 0, NULL, NULL); + if (num > 0) { + to.resize(size_t(num) - 1); + WideCharToMultiByte(CP_UTF8, 0, from.c_str(), -1, &to[0], num, NULL, NULL); + } +#else + std::wstring_convert> cv; + to = cv.to_bytes(from); +#endif // _WIN32 + } + + int StringConvert(const char* from, wchar_t* to, int dest_size_in_characters) { +#ifdef _WIN32 + int num = MultiByteToWideChar(CP_UTF8, 0, from, -1, NULL, 0); + if (num > 0) { + if (dest_size_in_characters >= 0) { + num = std::min(num, dest_size_in_characters); + } + MultiByteToWideChar(CP_UTF8, 0, from, -1, &to[0], num); + } + return num; +#else + std::wstring_convert> cv; + auto result = cv.from_bytes(from).c_str(); + int num = (int)cv.converted(); + if (dest_size_in_characters >= 0) { + num = std::min(num, dest_size_in_characters); + } + std::memcpy(to, result, num * sizeof(wchar_t)); + return num; +#endif // _WIN32 + } + + int StringConvert(const wchar_t* from, char* to, int dest_size_in_characters) { +#ifdef _WIN32 + int num = WideCharToMultiByte(CP_UTF8, 0, from, -1, NULL, 0, NULL, NULL); + if (num > 0) { + if (dest_size_in_characters >= 0) { + num = std::min(num, dest_size_in_characters); + } + WideCharToMultiByte(CP_UTF8, 0, from, -1, &to[0], num, NULL, NULL); + } + return num; +#else + std::wstring_convert> cv; + auto result = cv.to_bytes(from).c_str(); + int num = (size_t)cv.converted(); + if (dest_size_in_characters >= 0) { + num = std::min(num, dest_size_in_characters); + } + std::memcpy(to, result, num * sizeof(char)); + return num; +#endif // _WIN32 + } } \ No newline at end of file