Grindstone Game Engine v0.2.0
An open source game engine and toolkit.
Loading...
Searching...
No Matches
AssetReference.hpp
1#pragma once
2
3#include <string>
4#include <type_traits>
5
6#include <EngineCore/Assets/Asset.hpp>
7
8namespace Grindstone::AssetFunctions {
9 [[nodiscard]] void* Get(Grindstone::AssetType assetType, Grindstone::Uuid uuid);
10 [[nodiscard]] void* GetAndIncrement(Grindstone::AssetType assetType, Grindstone::Uuid uuid);
11 void Increment(Grindstone::AssetType assetType, Grindstone::Uuid uuid);
12 void Decrement(Grindstone::AssetType assetType, Grindstone::Uuid uuid);
13}
14
15namespace Grindstone {
16 struct GenericAssetReference {
17 GenericAssetReference() = default;
18 GenericAssetReference(Grindstone::Uuid uuid) : uuid(uuid) {}
19 GenericAssetReference(const GenericAssetReference& other) = default;
20 GenericAssetReference(GenericAssetReference&& other) = default;
21
22 GenericAssetReference& operator=(const GenericAssetReference& other) noexcept {
23 uuid = other.uuid;
24 return *this;
25 }
26
27 GenericAssetReference& operator=(GenericAssetReference&& other) noexcept {
28 uuid = other.uuid;
29 return *this;
30 }
31
32 operator bool() const noexcept {
33 return uuid.IsValid();
34 }
35
36 // TODO: It's not clear that IsValid just refers to a valid uuid, rather than an existing asset. We need separate functions for this.
37 bool IsValid() const noexcept {
38 return uuid.IsValid();
39 }
40
41 Uuid uuid;
42 };
43
44 template<typename T>
45 struct AssetReference : public GenericAssetReference {
46 static_assert(std::is_base_of_v<Grindstone::Asset, T>, "T not derived from Grindstone::Asset");
47
48 static AssetReference<T> CreateWithoutIncrement(Uuid uuid) {
49 return AssetReference(uuid);
50 }
51
52 static AssetReference<T> CreateAndIncrement(Uuid uuid) {
53 Grindstone::AssetFunctions::Increment(T::GetStaticType(), uuid);
54 return AssetReference(uuid);
55 }
56
57 AssetReference() : GenericAssetReference() {}
58
59 AssetReference(const AssetReference& other) : GenericAssetReference(other.uuid) {
60 Grindstone::AssetFunctions::Increment(T::GetStaticType(), uuid);
61 }
62
63 AssetReference(AssetReference&& other) noexcept : GenericAssetReference(other.uuid) {
64 other.uuid = Grindstone::Uuid();
65 }
66
67 AssetReference& operator=(const AssetReference& other) {
68 if (uuid != other.uuid) {
69 if (uuid.IsValid()) {
70 Grindstone::AssetFunctions::Decrement(T::GetStaticType(), uuid);
71 }
72
73 uuid = other.uuid;
74 if (uuid.IsValid()) {
75 Grindstone::AssetFunctions::Increment(T::GetStaticType(), uuid);
76 }
77 }
78
79 return *this;
80 }
81
82 AssetReference& operator=(AssetReference&& other) noexcept {
83 if (uuid != other.uuid) {
84 if (uuid.IsValid()) {
85 Grindstone::AssetFunctions::Decrement(T::GetStaticType(), uuid);
86 }
87
88 uuid = other.uuid;
89 other.uuid = Grindstone::Uuid();
90 }
91
92 return *this;
93 }
94
95 ~AssetReference() {
96 if (uuid.IsValid()) {
97 Grindstone::AssetFunctions::Decrement(T::GetStaticType(), uuid);
98 uuid = Uuid();
99 }
100 }
101
102 void Release() {
103 if (uuid.IsValid()) {
104 Grindstone::AssetFunctions::Decrement(T::GetStaticType(), uuid);
105 uuid = Uuid();
106 }
107 }
108
109 // Return a pointer to the actual asset whether or not there was an error.
110 [[nodiscard]] T* GetUnchecked() {
111 return reinterpret_cast<T*>(Grindstone::AssetFunctions::Get(T::GetStaticType(), uuid));
112 }
113
114 // Return a pointer to the actual asset whether or not there was an error.
115 [[nodiscard]] const T* GetUnchecked() const {
116 return reinterpret_cast<T*>(Grindstone::AssetFunctions::Get(T::GetStaticType(), uuid));
117 }
118
119 // Return a pointer to the actual asset, but only if the asset is ready to be used.
120 [[nodiscard]] T* Get() {
121 T* asset = reinterpret_cast<T*>(Grindstone::AssetFunctions::Get(T::GetStaticType(), uuid));
122 return asset && asset->assetLoadStatus == Grindstone::AssetLoadStatus::Ready
123 ? asset
124 : nullptr;
125 }
126
127 // Return a pointer to the actual asset, but only if the asset is ready to be used.
128 [[nodiscard]] const T* Get() const {
129 T* asset = reinterpret_cast<T*>(Grindstone::AssetFunctions::Get(T::GetStaticType(), uuid));
130 return asset && asset->assetLoadStatus == Grindstone::AssetLoadStatus::Ready
131 ? asset
132 : nullptr;
133 }
134
135 // Don't implement operators * or ->, as they imply getting data is a cheap operator.
136 // It's relatively cheap, but best practice is to cache the data when you use it
137 // within the function it's in, but not across multiple frames.
138
139 private:
140 AssetReference(Grindstone::Uuid uuid) : GenericAssetReference(uuid) {}
141 };
142}
Definition Uuid.hpp:7