1//************************************ bs::framework - Copyright 2018 Marko Pintera **************************************//
2//*********** Licensed under the MIT license. See LICENSE.md for full terms. This notice is not to be removed. ***********//
3#include "Resources/BsResourceManifest.h"
4#include "Private/RTTI/BsResourceManifestRTTI.h"
5#include "Serialization/BsFileSerializer.h"
6#include "Error/BsException.h"
7
8namespace bs
9{
10 ResourceManifest::ResourceManifest(const ConstructPrivately& dummy)
11 {
12
13 }
14
15 ResourceManifest::ResourceManifest(const String& name)
16 :mName(name)
17 {
18
19 }
20
21 SPtr<ResourceManifest> ResourceManifest::create(const String& name)
22 {
23 return bs_shared_ptr_new<ResourceManifest>(name);
24 }
25
26 SPtr<ResourceManifest> ResourceManifest::createEmpty()
27 {
28 return bs_shared_ptr_new<ResourceManifest>(ConstructPrivately());
29 }
30
31 void ResourceManifest::registerResource(const UUID& uuid, const Path& filePath)
32 {
33 auto iterFind = mUUIDToFilePath.find(uuid);
34
35 if(iterFind != mUUIDToFilePath.end())
36 {
37 if (iterFind->second != filePath)
38 {
39 mFilePathToUUID.erase(iterFind->second);
40
41 mUUIDToFilePath[uuid] = filePath;
42 mFilePathToUUID[filePath] = uuid;
43 }
44 }
45 else
46 {
47 auto iterFind2 = mFilePathToUUID.find(filePath);
48 if (iterFind2 != mFilePathToUUID.end())
49 mUUIDToFilePath.erase(iterFind2->second);
50
51 mUUIDToFilePath[uuid] = filePath;
52 mFilePathToUUID[filePath] = uuid;
53 }
54 }
55
56 void ResourceManifest::unregisterResource(const UUID& uuid)
57 {
58 auto iterFind = mUUIDToFilePath.find(uuid);
59
60 if(iterFind != mUUIDToFilePath.end())
61 {
62 mFilePathToUUID.erase(iterFind->second);
63 mUUIDToFilePath.erase(uuid);
64 }
65 }
66
67 bool ResourceManifest::uuidToFilePath(const UUID& uuid, Path& filePath) const
68 {
69 auto iterFind = mUUIDToFilePath.find(uuid);
70
71 if(iterFind != mUUIDToFilePath.end())
72 {
73 filePath = iterFind->second;
74 return true;
75 }
76 else
77 {
78 filePath = Path::BLANK;
79 return false;
80 }
81 }
82
83 bool ResourceManifest::filePathToUUID(const Path& filePath, UUID& outUUID) const
84 {
85 auto iterFind = mFilePathToUUID.find(filePath);
86
87 if(iterFind != mFilePathToUUID.end())
88 {
89 outUUID = iterFind->second;
90 return true;
91 }
92 else
93 {
94 outUUID = UUID::EMPTY;
95 return false;
96 }
97 }
98
99 bool ResourceManifest::uuidExists(const UUID& uuid) const
100 {
101 auto iterFind = mUUIDToFilePath.find(uuid);
102
103 return iterFind != mUUIDToFilePath.end();
104 }
105
106 bool ResourceManifest::filePathExists(const Path& filePath) const
107 {
108 auto iterFind = mFilePathToUUID.find(filePath);
109
110 return iterFind != mFilePathToUUID.end();
111 }
112
113 void ResourceManifest::save(const SPtr<ResourceManifest>& manifest, const Path& path, const Path& relativePath)
114 {
115 if(relativePath.isEmpty())
116 {
117 FileEncoder fs(path);
118 fs.encode(manifest.get());
119 }
120 else
121 {
122 SPtr<ResourceManifest> copy = create(manifest->mName);
123
124 for (auto& elem : manifest->mFilePathToUUID)
125 {
126 if (!relativePath.includes(elem.first))
127 {
128 BS_EXCEPT(InvalidStateException, "Path in resource manifest cannot be made relative to: \"" +
129 relativePath.toString() + "\". Path: \"" + elem.first.toString() + "\"");
130 }
131
132 Path elementRelativePath = elem.first.getRelative(relativePath);
133
134 copy->mFilePathToUUID[elementRelativePath] = elem.second;
135 }
136
137 for (auto& elem : manifest->mUUIDToFilePath)
138 {
139 if (!relativePath.includes(elem.second))
140 {
141 BS_EXCEPT(InvalidStateException, "Path in resource manifest cannot be made relative to: \"" +
142 relativePath.toString() + "\". Path: \"" + elem.second.toString() + "\"");
143 }
144
145 Path elementRelativePath = elem.second.getRelative(relativePath);
146
147 copy->mUUIDToFilePath[elem.first] = elementRelativePath;
148 }
149
150 FileEncoder fs(path);
151 fs.encode(copy.get());
152 }
153 }
154
155 SPtr<ResourceManifest> ResourceManifest::load(const Path& path, const Path& relativePath)
156 {
157 FileDecoder fs(path);
158 SPtr<ResourceManifest> manifest = std::static_pointer_cast<ResourceManifest>(fs.decode());
159
160 if(relativePath.isEmpty())
161 return manifest;
162
163 SPtr<ResourceManifest> copy = create(manifest->mName);
164
165 for(auto& elem : manifest->mFilePathToUUID)
166 {
167 Path absPath = elem.first.getAbsolute(relativePath);
168 copy->mFilePathToUUID[absPath] = elem.second;
169 }
170
171 for(auto& elem : manifest->mUUIDToFilePath)
172 {
173 Path absPath = elem.second.getAbsolute(relativePath);
174 copy->mUUIDToFilePath[elem.first] = absPath;
175 }
176
177 return copy;
178 }
179
180 RTTITypeBase* ResourceManifest::getRTTIStatic()
181 {
182 return ResourceManifestRTTI::instance();
183 }
184
185 RTTITypeBase* ResourceManifest::getRTTI() const
186 {
187 return ResourceManifest::getRTTIStatic();
188 }
189}