Compare commits
5 Commits
e306a66956
...
1846d42401
| Author | SHA1 | Date |
|---|---|---|
|
|
1846d42401 | |
|
|
5c6ea6c485 | |
|
|
92179df553 | |
|
|
172d3ea720 | |
|
|
2ccc5c364c |
|
|
@ -0,0 +1,39 @@
|
|||
#include <Nazara/Audio.hpp>
|
||||
#include <Nazara/Core.hpp>
|
||||
#include <Nazara/Platform.hpp>
|
||||
|
||||
int main(int argc, char* argv[])
|
||||
{
|
||||
std::filesystem::path resourceDir = "assets";
|
||||
if (!std::filesystem::is_directory(resourceDir) && std::filesystem::is_directory("../.." / resourceDir))
|
||||
resourceDir = "../.." / resourceDir;
|
||||
|
||||
Nz::Application<Nz::Audio> app(argc, argv);
|
||||
|
||||
auto& windowing = app.AddComponent<Nz::WindowingAppComponent>();
|
||||
auto& fs = app.AddComponent<Nz::FilesystemAppComponent>();
|
||||
fs.Mount("game:/", resourceDir);
|
||||
|
||||
auto& catalog = app.AddComponent<Nz::AssetCatalogAppComponent>();
|
||||
catalog.AddFolder("game:/");
|
||||
|
||||
// Load an asset from its path
|
||||
Nz::Asset<Nz::Music> music = Nz::Asset<Nz::Music>::LoadFromFile("game:/examples/Audio/file_example_MP3_700KB.nzasset");
|
||||
|
||||
// or by its name
|
||||
music = catalog.Load<Nz::Music>("file_example_MP3_700KB");
|
||||
music->Play();
|
||||
|
||||
Nz::Asset<Nz::Sound> sound = catalog.Load<Nz::Sound>("examples/Audio/siren");
|
||||
sound->Play();
|
||||
|
||||
app.AddUpdaterFunc([&]
|
||||
{
|
||||
if (!music->IsPlaying())
|
||||
app.Quit();
|
||||
|
||||
std::this_thread::sleep_for(std::chrono::milliseconds(100));
|
||||
});
|
||||
|
||||
return app.Run();
|
||||
}
|
||||
|
|
@ -0,0 +1,3 @@
|
|||
target("Assets")
|
||||
add_deps("NazaraGraphics", "NazaraAudio")
|
||||
add_files("main.cpp")
|
||||
|
|
@ -39,6 +39,9 @@
|
|||
#include <Nazara/Core/ApplicationBase.hpp>
|
||||
#include <Nazara/Core/ApplicationComponent.hpp>
|
||||
#include <Nazara/Core/ApplicationUpdater.hpp>
|
||||
#include <Nazara/Core/Asset.hpp>
|
||||
#include <Nazara/Core/AssetDescriptor.hpp>
|
||||
#include <Nazara/Core/AssetCatalogAppComponent.hpp>
|
||||
#include <Nazara/Core/Buffer.hpp>
|
||||
#include <Nazara/Core/BufferMapper.hpp>
|
||||
#include <Nazara/Core/ByteArray.hpp>
|
||||
|
|
|
|||
|
|
@ -97,7 +97,7 @@ namespace Nz
|
|||
constexpr UInt64 typeHash = FNV1a64(TypeName<T>());
|
||||
|
||||
auto it = m_components.find(typeHash);
|
||||
if (it != m_components.end())
|
||||
if (it == m_components.end())
|
||||
return nullptr;
|
||||
|
||||
return static_cast<T*>(it->second.get());
|
||||
|
|
@ -109,7 +109,7 @@ namespace Nz
|
|||
constexpr UInt64 typeHash = FNV1a64(TypeName<T>());
|
||||
|
||||
auto it = m_components.find(typeHash);
|
||||
if (it != m_components.end())
|
||||
if (it == m_components.end())
|
||||
return nullptr;
|
||||
|
||||
return static_cast<const T*>(it->second.get());
|
||||
|
|
|
|||
|
|
@ -16,6 +16,8 @@ namespace Nz
|
|||
TResource* operator->() { return m_resource.get(); }
|
||||
const TResource* operator->() const { return m_resource.get(); }
|
||||
|
||||
static Asset LoadFromFile(const std::filesystem::path& path);
|
||||
|
||||
protected:
|
||||
AssetDescriptor<TResource> m_descriptor;
|
||||
std::shared_ptr<TResource> m_resource;
|
||||
|
|
@ -23,3 +25,5 @@ namespace Nz
|
|||
friend class AssetCatalog;
|
||||
};
|
||||
}
|
||||
|
||||
#include <Nazara/Core/Asset.inl>
|
||||
|
|
|
|||
|
|
@ -0,0 +1,60 @@
|
|||
#include <Nazara/Core/ApplicationBase.hpp>
|
||||
#include <Nazara/Core/FilesystemAppComponent.hpp>
|
||||
#include <Nazara/Core/JsonSerialization.hpp>
|
||||
|
||||
namespace Nz
|
||||
{
|
||||
template <typename TResource>
|
||||
concept IsStreamingResource = requires(TResource)
|
||||
{
|
||||
{ TResource::OpenFromFile({}) } -> std::same_as<std::shared_ptr<TResource>>;
|
||||
};
|
||||
|
||||
template <typename TResource>
|
||||
Asset<TResource> Asset<TResource>::LoadFromFile(const std::filesystem::path& path)
|
||||
{
|
||||
Asset<TResource> asset;
|
||||
|
||||
FilesystemAppComponent* fs = ApplicationBase::Instance()->TryGetComponent<FilesystemAppComponent>();
|
||||
if (fs) // first try using a FileSystem component to load the asset
|
||||
{
|
||||
auto json = fs->Load<JsonSerializationContext>(std::string_view(path.string()));
|
||||
if (json)
|
||||
{
|
||||
if (!Unserialize(*json, "", &asset.m_descriptor))
|
||||
return {};
|
||||
|
||||
std::string filepath = asset.m_descriptor.path.string();
|
||||
if constexpr (IsStreamingResource<TResource>)
|
||||
{
|
||||
asset.m_resource = fs->Open<TResource>(std::string_view(filepath), asset.m_descriptor.parameters);
|
||||
}
|
||||
else
|
||||
{
|
||||
asset.m_resource = fs->Load<TResource>(std::string_view(filepath), asset.m_descriptor.parameters);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!asset) // if it fails, use the default loader
|
||||
{
|
||||
JsonSerializationContext json;
|
||||
if (!json.Load(path))
|
||||
return {};
|
||||
|
||||
if (!Unserialize(json, "", &asset.m_descriptor))
|
||||
return {};
|
||||
|
||||
if constexpr (IsStreamingResource<TResource>)
|
||||
{
|
||||
asset.m_resource = TResource::OpenFromFile(asset.m_descriptor.path, asset.m_descriptor.parameters);
|
||||
}
|
||||
else
|
||||
{
|
||||
asset.m_resource = TResource::LoadFromFile(asset.m_descriptor.path, asset.m_descriptor.parameters);
|
||||
}
|
||||
}
|
||||
|
||||
return asset;
|
||||
}
|
||||
}
|
||||
|
|
@ -1,16 +0,0 @@
|
|||
#pragma once
|
||||
|
||||
#include <Nazara/Core/Asset.hpp>
|
||||
#include <Nazara/Core/Export.hpp>
|
||||
|
||||
namespace Nz
|
||||
{
|
||||
class NAZARA_CORE_API AssetCatalog
|
||||
{
|
||||
public:
|
||||
template <typename TResource>
|
||||
static Asset<TResource> LoadFromFile(const std::filesystem::path& path);
|
||||
};
|
||||
}
|
||||
|
||||
#include <Nazara/Core/AssetCatalog.inl>
|
||||
|
|
@ -1,59 +0,0 @@
|
|||
#include <Nazara/Core/ApplicationBase.hpp>
|
||||
#include <Nazara/Core/FilesystemAppComponent.hpp>
|
||||
#include <Nazara/Core/JsonSerialization.hpp>
|
||||
|
||||
namespace Nz
|
||||
{
|
||||
template <typename TResource>
|
||||
concept IsStreamingResource = requires(TResource)
|
||||
{
|
||||
{ TResource::OpenFromFile({}) } -> std::same_as<std::shared_ptr<TResource>>;
|
||||
};
|
||||
|
||||
template <typename TResource>
|
||||
Asset<TResource> AssetCatalog::LoadFromFile(const std::filesystem::path& path)
|
||||
{
|
||||
Asset<TResource> asset;
|
||||
|
||||
FilesystemAppComponent* fs = ApplicationBase::Instance()->TryGetComponent<FilesystemAppComponent>();
|
||||
if (fs) // first try using a FileSystem component to load the asset
|
||||
{
|
||||
auto json = fs->Load<JsonSerializationContext>(std::string_view(path.string()));
|
||||
|
||||
if (!Unserialize(*json, "", &asset.m_descriptor))
|
||||
return {};
|
||||
|
||||
|
||||
std::string filepath = asset.m_descriptor.path.string();
|
||||
if constexpr (IsStreamingResource<TResource>)
|
||||
{
|
||||
asset.m_resource = fs->Open<TResource>(std::string_view(filepath), asset.m_descriptor.parameters);
|
||||
}
|
||||
else
|
||||
{
|
||||
asset.m_resource = fs->Load<TResource>(std::string_view(filepath), asset.m_descriptor.parameters);
|
||||
}
|
||||
}
|
||||
|
||||
if (!asset) // if it fails, use the default loader
|
||||
{
|
||||
JsonSerializationContext json;
|
||||
if (!json.Load(path))
|
||||
return {};
|
||||
|
||||
if (!Unserialize(json, "", &asset.m_descriptor))
|
||||
return {};
|
||||
|
||||
if constexpr (IsStreamingResource<TResource>)
|
||||
{
|
||||
asset.m_resource = TResource::OpenFromFile(asset.m_descriptor.path, asset.m_descriptor.parameters);
|
||||
}
|
||||
else
|
||||
{
|
||||
asset.m_resource = TResource::LoadFromFile(asset.m_descriptor.path, asset.m_descriptor.parameters);
|
||||
}
|
||||
}
|
||||
|
||||
return asset;
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,45 @@
|
|||
#pragma once
|
||||
|
||||
#include <Nazara/Core/Asset.hpp>
|
||||
#include <Nazara/Core/ApplicationComponent.hpp>
|
||||
#include <Nazara/Core/Export.hpp>
|
||||
|
||||
#include <set>
|
||||
|
||||
namespace Nz
|
||||
{
|
||||
struct AssetHeaderLite
|
||||
{
|
||||
std::string name;
|
||||
std::filesystem::path path;
|
||||
|
||||
friend auto operator<=>(const AssetHeaderLite& A, const AssetHeaderLite& B)
|
||||
{
|
||||
return A.name <=> B.name;
|
||||
}
|
||||
};
|
||||
|
||||
NAZARA_CORE_API bool Serialize(struct SerializationContext& context, const AssetHeaderLite& header, TypeTag<AssetHeaderLite>);
|
||||
NAZARA_CORE_API bool Unserialize(struct SerializationContext& context, AssetHeaderLite* header, TypeTag<AssetHeaderLite>);
|
||||
|
||||
|
||||
class NAZARA_CORE_API AssetCatalogAppComponent
|
||||
: public ApplicationComponent
|
||||
{
|
||||
public:
|
||||
inline AssetCatalogAppComponent(ApplicationBase& app);
|
||||
AssetCatalogAppComponent(const AssetCatalogAppComponent&) = delete;
|
||||
AssetCatalogAppComponent(AssetCatalogAppComponent&&) = delete;
|
||||
~AssetCatalogAppComponent() = default;
|
||||
|
||||
void AddFolder(std::string_view folder);
|
||||
|
||||
template<typename TResource>
|
||||
inline Asset<TResource> Load(std::string_view name) const;
|
||||
|
||||
protected:
|
||||
std::set<AssetHeaderLite> m_assets;
|
||||
};
|
||||
}
|
||||
|
||||
#include <Nazara/Core/AssetCatalogAppComponent.inl>
|
||||
|
|
@ -0,0 +1,19 @@
|
|||
|
||||
namespace Nz
|
||||
{
|
||||
inline AssetCatalogAppComponent::AssetCatalogAppComponent(ApplicationBase& app)
|
||||
: ApplicationComponent(app)
|
||||
{
|
||||
}
|
||||
|
||||
template<typename TResource>
|
||||
Asset<TResource> AssetCatalogAppComponent::Load(std::string_view name) const
|
||||
{
|
||||
AssetHeaderLite header{ std::string(name), "" };
|
||||
auto it = m_assets.find(header);
|
||||
if (it == m_assets.end())
|
||||
return {};
|
||||
|
||||
return Asset<TResource>::LoadFromFile(it->path);
|
||||
}
|
||||
}
|
||||
|
|
@ -41,7 +41,7 @@ namespace Nz
|
|||
|
||||
inline bool Exists(std::string_view path);
|
||||
|
||||
template<typename F> void Foreach(F&& callback, bool includeDots = false);
|
||||
template<typename F> bool Foreach(F&& callback, bool recursive = false, bool includeDots = false);
|
||||
|
||||
template<typename F> bool GetDirectoryEntry(std::string_view path, F&& callback);
|
||||
template<typename F> bool GetEntry(std::string_view path, F&& callback);
|
||||
|
|
|
|||
|
|
@ -36,7 +36,7 @@ namespace Nz
|
|||
}
|
||||
|
||||
template<typename F>
|
||||
void VirtualDirectory::Foreach(F&& callback, bool includeDots)
|
||||
bool VirtualDirectory::Foreach(F&& callback, bool recursive, bool includeDots)
|
||||
{
|
||||
if (includeDots)
|
||||
{
|
||||
|
|
@ -46,16 +46,26 @@ namespace Nz
|
|||
{
|
||||
Entry parentEntry = DirectoryEntry{ { parent } };
|
||||
if (!CallbackReturn(callback, std::string_view(".."), parentEntry))
|
||||
return;
|
||||
return false;
|
||||
}
|
||||
else if (!CallbackReturn(callback, std::string_view(".."), ourselves))
|
||||
return;
|
||||
return false;
|
||||
}
|
||||
|
||||
for (auto&& entry : m_content)
|
||||
{
|
||||
if (!CallbackReturn(callback, std::string_view(entry.name), std::as_const(entry.entry)))
|
||||
return;
|
||||
return false;
|
||||
|
||||
if (recursive)
|
||||
{
|
||||
if (std::holds_alternative<DirectoryEntry>(entry.entry))
|
||||
{
|
||||
DirectoryEntry& child = std::get<DirectoryEntry>(entry.entry);
|
||||
if (!child.directory->Foreach(callback, recursive, includeDots))
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (m_resolver)
|
||||
|
|
@ -70,9 +80,22 @@ namespace Nz
|
|||
if (it != m_content.end() && it->name == filename)
|
||||
return true; //< this was already returned
|
||||
|
||||
return CallbackReturn(callback, filename, std::move(entry));
|
||||
if (!CallbackReturn(callback, filename, entry))
|
||||
return false;
|
||||
|
||||
if (recursive)
|
||||
{
|
||||
if (std::holds_alternative<DirectoryEntry>(entry))
|
||||
{
|
||||
DirectoryEntry& child = std::get<DirectoryEntry>(entry);
|
||||
if (!child.directory->Foreach(callback, recursive, includeDots))
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
});
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
template<typename F>
|
||||
|
|
|
|||
|
|
@ -0,0 +1,52 @@
|
|||
|
||||
#include <Nazara/Core/AssetCatalogAppComponent.hpp>
|
||||
#include <Nazara/Core/Serialization.hpp>
|
||||
|
||||
namespace Nz
|
||||
{
|
||||
bool Serialize(SerializationContext& context, const AssetHeaderLite& header, TypeTag<AssetHeaderLite>)
|
||||
{
|
||||
Serialize(context, "name", header.name);
|
||||
Serialize(context, "path", header.path);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool Unserialize(SerializationContext& context, AssetHeaderLite* header, TypeTag<AssetHeaderLite>)
|
||||
{
|
||||
Unserialize(context, "name", &header->name);
|
||||
Unserialize(context, "path", &header->path);
|
||||
return true;
|
||||
}
|
||||
|
||||
void AddFile(std::set<AssetHeaderLite>& container, Nz::Stream& stream)
|
||||
{
|
||||
AssetHeaderLite header;
|
||||
auto json = JsonSerializationContext::LoadFromStream(stream);
|
||||
if (!json)
|
||||
return;
|
||||
|
||||
if (!Unserialize(*json, "", &header))
|
||||
return;
|
||||
|
||||
header.path = stream.GetPath();
|
||||
container.insert(header);
|
||||
}
|
||||
|
||||
void AssetCatalogAppComponent::AddFolder(std::string_view folder)
|
||||
{
|
||||
auto& fs = GetApp().GetComponent<FilesystemAppComponent>();
|
||||
auto directory = fs.GetDirectory(folder);
|
||||
if (!directory)
|
||||
return;
|
||||
|
||||
directory->Foreach([&](std::string_view, const VirtualDirectory::Entry& entry) {
|
||||
if (std::holds_alternative<VirtualDirectory::FileEntry>(entry))
|
||||
{
|
||||
auto& file = std::get<VirtualDirectory::FileEntry>(entry);
|
||||
|
||||
if (file.stream->GetPath().extension() == ".nzasset")
|
||||
AddFile(m_assets, *file.stream.get());
|
||||
}
|
||||
}, true);
|
||||
}
|
||||
}
|
||||
|
|
@ -32,7 +32,7 @@ TEST_CASE("VirtualDirectory", "[Core][VirtualDirectory]")
|
|||
}
|
||||
if (name != "." && name != "..")
|
||||
FAIL("Got file " << name);
|
||||
}, true);
|
||||
}, false, true);
|
||||
|
||||
CHECK(dot);
|
||||
CHECK(dotDot);
|
||||
|
|
|
|||
Loading…
Reference in New Issue