aboutsummaryrefslogtreecommitdiff
path: root/core/src/Model/Assets.hpp
blob: bc5219d1e379a9f55c6525b42f034b5459d6ecf9 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
#pragma once

#include <tsl/array_map.h>
#include <filesystem>
#include <iosfwd>
#include <memory>
#include <string_view>

/// A structure representing a ready-to-be-loaded asset, locating on the disk.
struct SavedAsset
{
	std::filesystem::path Path;
	std::string Name;
	/// `Path`'s string form, encoded in UTF-8.
	std::string PathString = Path.string();
};

class Asset
{
public:
	Asset();
	virtual ~Asset() = default;
};

class AssetCategory
{
public:
	virtual ~AssetCategory() = default;

	virtual void DiscoverFiles(const std::function<void(SavedAsset)>& callback) const = 0;

	virtual Asset* CreateEmpty(const SavedAsset& diskForm) const = 0;
	std::unique_ptr<Asset> CreateEmptyUnique(const SavedAsset& diskForm) const;
	virtual Asset* Load(const SavedAsset& diskForm) const = 0;
	std::unique_ptr<Asset> LoadUnique(const SavedAsset& diskForm) const;

	/// This should call ImGui::BeginTable() along with other accessories such as setting up the header row.
	virtual void SetupDetailsTable(const char* tableId) const = 0;
	virtual void DrawBigIcon(const SavedAsset& asset) const = 0;
	virtual void DrawDetailsTableRow(const SavedAsset& asset) const = 0;

protected:
	/* Helper loader functions */

	static void DiscoverFilesByExtension(const std::function<void(SavedAsset)>& callback, const std::filesystem::path& containerDir, std::string_view extension);
	static void DiscoverFilesByHeader(const std::function<void(SavedAsset)>& callback, const std::filesystem::path& containerDir, const std::function<bool(std::istream&)>& validater);
};

class AssetList
{
private:
	const AssetCategory* mLoader;
	tsl::array_map<char, SavedAsset> mAssets;
	tsl::array_map<char, std::unique_ptr<Asset>> mCache;
	int mCacheSizeLimit = 0;

public:
	AssetList(const AssetCategory& loader);

	// TODO support file watches
	void Reload();

	const SavedAsset* FindByName(std::string_view name) const;
	const SavedAsset& Create(SavedAsset asset);
	std::unique_ptr<Asset> CreateAndLoad(SavedAsset asset);
	std::unique_ptr<Asset> LoadFromDisk(std::string_view name) const;
	bool Rename(std::string_view oldName, std::string_view newName);
	bool Remove(std::string_view name);

	int GetCacheSizeLimit() const;
	void SetCacheSizeLimit(int limit);

	struct DrawState
	{
		const SavedAsset* SelectedAsset = nullptr;
	};
	void DrawBigIcons(DrawState& state);
	void DrawDetails(DrawState& state);
};

template <class TAsset>
class TypedAssetList : public AssetList
{
public:
	using Asset = TAsset;
	using AssetType = typename TAsset::CategoryType;

public:
	// Import constructor
	using AssetList::AssetList;

	Asset* FindByName(std::string_view name) const
	{
		return static_cast<TAsset*>(AssetList::FindByName(name));
	}
	std::unique_ptr<Asset> Create(std::string_view name)
	{
		return std::unique_ptr<TAsset>(static_cast<TAsset*>(AssetList::Create(name).release()));
	}
	std::unique_ptr<Asset> LoadFromDisk(std::string_view name) const
	{
		return std::unique_ptr<TAsset>(static_cast<TAsset>(AssetList::LoadFromDisk(name)));
	}
};