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 if (uuid.IsValid()) {
61 Grindstone::AssetFunctions::Increment(T::GetStaticType(), uuid);
62 }
63 }
64
65 AssetReference(AssetReference&& other) noexcept : GenericAssetReference(other.uuid) {
66 other.uuid = Grindstone::Uuid();
67 }
68
69 AssetReference& operator=(const AssetReference& other) {
70 if (uuid != other.uuid) {
71 if (uuid.IsValid()) {
72 Grindstone::AssetFunctions::Decrement(T::GetStaticType(), uuid);
73 }
74
75 uuid = other.uuid;
76 if (uuid.IsValid()) {
77 Grindstone::AssetFunctions::Increment(T::GetStaticType(), uuid);
78 }
79 }
80
81 return *this;
82 }
83
84 AssetReference& operator=(AssetReference&& other) noexcept {
85 if (uuid != other.uuid) {
86 if (uuid.IsValid()) {
87 Grindstone::AssetFunctions::Decrement(T::GetStaticType(), uuid);
88 }
89
90 uuid = other.uuid;
91 other.uuid = Grindstone::Uuid();
92 }
93
94 return *this;
95 }
96
97 ~AssetReference() {
98 if (uuid.IsValid()) {
99 Grindstone::AssetFunctions::Decrement(T::GetStaticType(), uuid);
100 uuid = Uuid();
101 }
102 }
103
104 void Release() {
105 if (uuid.IsValid()) {
106 Grindstone::AssetFunctions::Decrement(T::GetStaticType(), uuid);
107 uuid = Uuid();
108 }
109 }
110
111 // Return a pointer to the actual asset whether or not there was an error.
112 [[nodiscard]] T* GetUnchecked() {
113 return reinterpret_cast<T*>(Grindstone::AssetFunctions::Get(T::GetStaticType(), uuid));
114 }
115
116 // Return a pointer to the actual asset whether or not there was an error.
117 [[nodiscard]] const T* GetUnchecked() const {
118 return reinterpret_cast<T*>(Grindstone::AssetFunctions::Get(T::GetStaticType(), uuid));
119 }
120
121 // Return a pointer to the actual asset, but only if the asset is ready to be used.
122 [[nodiscard]] T* Get() {
123 T* asset = reinterpret_cast<T*>(Grindstone::AssetFunctions::Get(T::GetStaticType(), uuid));
124 return asset && asset->assetLoadStatus == Grindstone::AssetLoadStatus::Ready
125 ? asset
126 : nullptr;
127 }
128
129 // Return a pointer to the actual asset, but only if the asset is ready to be used.
130 [[nodiscard]] const T* Get() const {
131 T* asset = reinterpret_cast<T*>(Grindstone::AssetFunctions::Get(T::GetStaticType(), uuid));
132 return asset && asset->assetLoadStatus == Grindstone::AssetLoadStatus::Ready
133 ? asset
134 : nullptr;
135 }
136
137 // Don't implement operators * or ->, as they imply getting data is a cheap operator.
138 // It's relatively cheap, but best practice is to cache the data when you use it
139 // within the function it's in, but not across multiple frames.
140
141 private:
142 AssetReference(Grindstone::Uuid uuid) : GenericAssetReference(uuid) {}
143 };
144}
Definition Uuid.hpp:7