1#include "TextureStore/TextureStore.h"
3#include "Data/ApplicationState.h"
4#include "Utils/Utils.h"
11#define TEXTURE_STORE_ITEM_DND(text, var) \
12 if(item.var.size() > 3) \
14 ImGui::Selectable(text, &tmp); \
15 if(ImGui::BeginDragDropSource(ImGuiDragDropFlags_None)) \
17 ImGui::SetDragDropPayload("TerraForge3D_Texture", item.var.data(), sizeof(char) * item.var.size()); \
18 ImGui::Image((ImTextureID)item.texThumbnail->GetRendererID(), ImVec2(128, 128)); \
19 ImGui::Text("%s", item.name.c_str()); \
20 ImGui::EndDragDropSource(); \
25inline char *strcasestr(
const char *str,
const char *pattern)
36 if (toupper((
unsigned char)*str) == toupper((
unsigned char)*pattern))
45 if (toupper((
unsigned char)str[i]) != toupper((
unsigned char)pattern[i]))
61 bool loadFromFile =
true;
63 if(IsNetWorkConnected() && rand() % 2 == 0)
68 if(!FileExists(GetExecutableDir() + PATH_SEPARATOR
"Data" PATH_SEPARATOR
"cache" PATH_SEPARATOR
"texture_database.terr3d"))
75 Log(
"Loading texture database from file");
77 std::string tmpStr = ReadShaderSourceFile(GetExecutableDir() + PATH_SEPARATOR
"Data" PATH_SEPARATOR
"cache" PATH_SEPARATOR
"texture_database.terr3d", &tmp);
81 Log(
"Failed to load texture database from file");
92 Log(
"Failed to parse texture database from file");
99 Log(
"Fetching texture database from web database.");
100 std::string tmp = FetchURL(
"https://api.polyhaven.com",
"/assets?t=textures");
104 Log(
"Failed to fetch texture database from web database.");
108 SaveToFile(GetExecutableDir() + PATH_SEPARATOR
"Data" PATH_SEPARATOR
"cache" PATH_SEPARATOR
"texture_database.terr3d", tmp);
113void TextureStore::VerifyTextureThumbs()
115 MkDir(GetExecutableDir() + PATH_SEPARATOR
"Data" PATH_SEPARATOR
"cache" PATH_SEPARATOR
"texture_thumbnails" PATH_SEPARATOR);
117 for(
auto it = textureDatabaseJ.
begin() ; it != textureDatabaseJ.
end() ; it++)
119 if(!FileExists(GetExecutableDir() + PATH_SEPARATOR
"Data" PATH_SEPARATOR
"cache" PATH_SEPARATOR
"texture_thumbnails" PATH_SEPARATOR + it.key() +
".png"))
121 Log(
"Downloading thumbnail for texture: " + it.key());
122 DownloadFile(
"https://cdn.polyhaven.com",
"/asset_img/thumbs/" +
123 it.key() +
".png?width=100&height=100", GetExecutableDir()
124 + PATH_SEPARATOR
"Data" PATH_SEPARATOR
"cache"
125 PATH_SEPARATOR
"texture_thumbnails" PATH_SEPARATOR +
133 if(!FileExists(GetExecutableDir() + PATH_SEPARATOR
"Data" PATH_SEPARATOR
"configs" PATH_SEPARATOR
"texture_database_downloaded.terr3d"))
135 Log(
"No Textures downloaded yet");
140 std::string tmpStr = ReadShaderSourceFile(GetExecutableDir() +
141 PATH_SEPARATOR
"Data" PATH_SEPARATOR
"configs" PATH_SEPARATOR
142 "texture_database_downloaded.terr3d", &tmp);
146 Log(
"Failed to load downloaded texture database from file");
159 Log(
"Failed to parse downloaded texture database from file");
167void TextureStore::LoadTextureDatabase()
169 textureDatabaseJ = LoadTextureDatabaseJ();
170 downloadedTextureDatabaseJ = LoadDownloadedTextureDatabaseJ();
171 textureStoreItems.clear();
172 downloadedTextureStoreItems.clear();
174 for(
auto it = textureDatabaseJ.
begin() ; it != textureDatabaseJ.
end() ; it++)
177 item.name = it.key();
178 item.thumbnailPath = GetExecutableDir() + PATH_SEPARATOR
"Data"
179 PATH_SEPARATOR
"cache" PATH_SEPARATOR
"texture_thumbnails"
180 PATH_SEPARATOR + item.name +
".png";
181 item.download_count = it.value()[
"download_count"];
183 for(
auto it2 = it.value()[
"authors"].begin() ; it2 != it.value()[
"authors"].end() ; it2++)
185 item.authours.push_back(it2.key());
188 if(downloadedTextureDatabaseJ.
find(item.name) != downloadedTextureDatabaseJ.
end())
190 item.downloaded =
true;
191 item.abledo = downloadedTextureDatabaseJ[item.name][
"abledo"];
192 item.normal = downloadedTextureDatabaseJ[item.name][
"normal"];
193 item.roughness = downloadedTextureDatabaseJ[item.name][
"roughness"];
194 item.metallic = downloadedTextureDatabaseJ[item.name][
"metallic"];
195 item.ao = downloadedTextureDatabaseJ[item.name][
"ao"];
196 item.arm = downloadedTextureDatabaseJ[item.name][
"arm"];
197 item.baseDir = downloadedTextureDatabaseJ[item.name][
"baseDir"];
198 downloadedTextureStoreItems.push_back(textureStoreItems.size());
201 textureStoreItems.push_back(item);
205void TextureStore::LoadTextureThumbs()
207 Log(
"Loading texture thumbnails");
210 for(
auto &it : textureStoreItems)
214 if(!FileExists(GetExecutableDir() + PATH_SEPARATOR
"Data" PATH_SEPARATOR
"cache" PATH_SEPARATOR
"texture_thumbnails" PATH_SEPARATOR + it.name +
".png"))
216 Log(
"Thumbnail for texture: " + it.name +
" not found.");
217 it.texThumbnail =
new Texture2D(GetExecutableDir() + PATH_SEPARATOR
218 "Data" PATH_SEPARATOR
"textures" PATH_SEPARATOR
224 it.texThumbnail =
new Texture2D(it.thumbnailPath,
false);
229 std::cout << (
"Loaded " + std::to_string(i) +
" of " + std::to_string(textureStoreItems.size()) +
" texture thumbnails\r");
233 Log(
"Texture thumbnails loaded");
236void TextureStore::SaveDownloadsDatabase()
240 for(
int id : downloadedTextureStoreItems)
243 tmp[
"abledo"] = textureStoreItems[id].abledo;
244 tmp[
"normal"] = textureStoreItems[id].normal;
245 tmp[
"roughness"]= textureStoreItems[id].roughness;
246 tmp[
"metallic"] = textureStoreItems[id].metallic;
247 tmp[
"ao"] = textureStoreItems[id].ao;
248 tmp[
"arm"] = textureStoreItems[id].arm;
249 tmp[
"baseDir"] = textureStoreItems[id].baseDir;
250 tmp2[textureStoreItems[id].name] = tmp;
253 SaveToFile(GetExecutableDir() + PATH_SEPARATOR
"Data" PATH_SEPARATOR
254 "configs" PATH_SEPARATOR
"texture_database_downloaded.terr3d",
258void TextureStore::DeleteTexture(
int id)
261 DeleteFileT(textureStoreItems[
id].abledo);
262 DeleteFileT(textureStoreItems[
id].ao);
263 DeleteFileT(textureStoreItems[
id].normal);
264 DeleteFileT(textureStoreItems[
id].metallic);
265 DeleteFileT(textureStoreItems[
id].roughness);
266 DeleteFileT(textureStoreItems[
id].arm);
267 DeleteFileT(textureStoreItems[
id].baseDir + PATH_SEPARATOR
"displacement.png");
268 textureStoreItems[id].downloaded =
false;
269 downloadedTextureStoreItems.erase(std::find(downloadedTextureStoreItems.begin(), downloadedTextureStoreItems.end(),
id));
270 SaveDownloadsDatabase();
273void TextureStore::DownloadTexture(
int id,
int res)
275 std::string tmpStr = FetchURL(
"https://api.polyhaven.com",
"/files/" + textureStoreItems[
id].name);
285 Log(
"Failed to download texture : " + textureStoreItems[
id].name);
289 std::string baseDir = GetExecutableDir() + PATH_SEPARATOR
"Data"
290 PATH_SEPARATOR
"textures" PATH_SEPARATOR + textureStoreItems[id].name;
292 textureStoreItems[id].baseDir = baseDir;
293 tmpStr = tmpJ[
"Diffuse"][std::to_string(res) +
"k"][
"png"][
"url"];
294 DownloadFile(
"https://dl.polyhaven.org", tmpStr.substr(24), baseDir + PATH_SEPARATOR
"albedo.png");
295 textureStoreItems[id].abledo = baseDir + PATH_SEPARATOR
"albedo.png";
296 tmpStr = tmpJ[
"nor_gl"][std::to_string(res) +
"k"][
"png"][
"url"];
297 DownloadFile(
"https://dl.polyhaven.org", tmpStr.substr(24), baseDir + PATH_SEPARATOR
"normal.png");
298 textureStoreItems[id].normal = baseDir + PATH_SEPARATOR
"normal.png";
299 tmpStr = tmpJ[
"Rough"][std::to_string(res) +
"k"][
"png"][
"url"];
300 DownloadFile(
"https://dl.polyhaven.org", tmpStr.substr(24), baseDir + PATH_SEPARATOR
"roughness.png");
301 textureStoreItems[id].roughness = baseDir + PATH_SEPARATOR
"roughness.png";
302 tmpStr = tmpJ[
"AO"][std::to_string(res) +
"k"][
"png"][
"url"];
303 DownloadFile(
"https://dl.polyhaven.org", tmpStr.substr(24), baseDir + PATH_SEPARATOR
"ao.png");
304 textureStoreItems[id].ao = baseDir + PATH_SEPARATOR
"ao.png";
305 tmpStr = tmpJ[
"arm"][std::to_string(res) +
"k"][
"png"][
"url"];
306 DownloadFile(
"https://dl.polyhaven.org", tmpStr.substr(24), baseDir + PATH_SEPARATOR
"arm.png");
307 textureStoreItems[id].arm = baseDir + PATH_SEPARATOR
"arm.png";
308 tmpStr = tmpJ[
"Displacement"][std::to_string(res) +
"k"][
"png"][
"url"];
309 DownloadFile(
"https://dl.polyhaven.org", tmpStr.substr(24), baseDir + PATH_SEPARATOR
"displacement.png");
310 textureStoreItems[id].downloaded =
true;
311 downloadedTextureStoreItems.push_back(
id);
312 SaveDownloadsDatabase();
315void TextureStore::ShowAllTexturesSettings()
317 int searchLength = strlen(searchStr);
318 ImGui::Columns(4, NULL);
319 float width = ImGui::GetContentRegionAvail().x;
326 ImGui::PushStyleColor(ImGuiCol_ChildBg, ImVec4(0.3f, 0.3f, 0.3f, 0.7f));
328 for(
int i=0; i<textureStoreItems.size(); i++)
333 if(searchLength == 0 || strcasestr(item.name.c_str(), searchStr) != NULL)
335 tmp = item.downloaded;
340 ImGui::PushStyleColor(ImGuiCol_ChildBg, ImVec4(0.5f, 0.5f, 0.5f, 0.7f));
343 ImGui::PushID(item.name.data());
344 ImGui::BeginChild(
"##texture_thumb", ImVec2(width, 300),
true);
345 ImGui::Image((ImTextureID)item.texThumbnail->GetRendererID(), ImVec2(width, 150));
346 ImGui::Text(item.name.data());
350 if(ImGui::Button(
"Download 1K"))
352 DownloadTexture(i, 1);
356 if(ImGui::Button(
"Download 2K"))
358 DownloadTexture(i, 2);
362 if(ImGui::Button(
"Download 4K"))
364 DownloadTexture(i, 4);
371 static bool tmp =
false;
374 TEXTURE_STORE_ITEM_DND(
"Albedo", abledo)
375 TEXTURE_STORE_ITEM_DND(
"Normal", normal)
376 TEXTURE_STORE_ITEM_DND(
"Metallic", metallic)
377 TEXTURE_STORE_ITEM_DND(
"Roughness", roughness)
378 TEXTURE_STORE_ITEM_DND(
"AO", ao)
379 TEXTURE_STORE_ITEM_DND(
"ARM", arm)
382 if(ImGui::Button(
"Delete"))
399 ImGui::PopStyleColor();
406 ImGui::PopStyleColor();
410void TextureStore::ShowDownloadedTexturesSettings()
412 ImGui::Columns(4, NULL);
413 float width = ImGui::GetContentRegionAvail().x;
420 ImGui::PushStyleColor(ImGuiCol_ChildBg, ImVec4(0.5f, 0.5f, 0.5f, 0.7f));
422 for(
int i=0; i<downloadedTextureStoreItems.size(); i++)
426 ImGui::BeginChild(
"##texture_thumb", ImVec2(width, 300),
true);
427 ImGui::Image((ImTextureID)item.texThumbnail->GetRendererID(), ImVec2(width, 120));
428 ImGui::Text(item.name.c_str());
430 if(ImGui::Button(
"Delete##DTS"))
432 DeleteTexture(downloadedTextureStoreItems[i]);
446 ImGui::PopStyleColor();
450void TextureStore::ShowSettings(
bool *pOpen)
452 ImGui::Begin(
"Textute Store Settings", pOpen);
453 ImGui::InputTextWithHint(
"##TextureStorePolyHavenSearch",
"Search ...", searchStr, 4096);
456 if (ImGui::BeginTabBar(
"##textureStoreTabBar"))
458 if (ImGui::BeginTabItem(
"All Textures"))
460 ImGui::PushStyleVar(ImGuiStyleVar_ChildRounding, 12);
461 ImGui::PushStyleVar(ImGuiStyleVar_WindowPadding, ImVec2(6.0f, 6.0f));
462 ShowAllTexturesSettings();
463 ImGui::PopStyleVar();
464 ImGui::PopStyleVar();
468 if (ImGui::BeginTabItem(
"Downloaded Textures"))
470 ImGui::PushStyleVar(ImGuiStyleVar_ChildRounding, 12);
471 ImGui::PushStyleVar(ImGuiStyleVar_WindowPadding, ImVec2(6.0f, 6.0f));
472 ShowDownloadedTexturesSettings();
473 ImGui::PopStyleVar();
474 ImGui::PopStyleVar();
478 if (ImGui::BeginTabItem(
"About"))
480 ImGui::Text(
"This texture store provides collection of free PBR textures.\nThis is powered by Polyhaven.");
493 uid = GenerateId(32);
494 memset(searchStr, 0,
sizeof(searchStr) /
sizeof(searchStr[0]));
496 LoadTextureDatabase();
499 VerifyTextureThumbs();
505TextureStore::~TextureStore()
507 for(
auto &it : textureStoreItems)
509 delete it.texThumbnail;
static JSON_HEDLEY_WARN_UNUSED_RESULT basic_json parse(InputType &&i, const parser_callback_t cb=nullptr, const bool allow_exceptions=true, const bool ignore_comments=false)
deserialize from a compatible input
iterator begin() noexcept
returns an iterator to the first element
string_t dump(const int indent=-1, const char indent_char=' ', const bool ensure_ascii=false, const error_handler_t error_handler=error_handler_t::strict) const
serialization
iterator end() noexcept
returns an iterator to one past the last element
iterator find(KeyT &&key)
find an element in a JSON object
a class to store JSON values
exception indicating a parse error
basic_json<> json
default JSON class