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