3
0

EditorCommon.cpp 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396
  1. /*
  2. * Copyright (c) Contributors to the Open 3D Engine Project.
  3. * For complete copyright and license terms please see the LICENSE at the root of this distribution.
  4. *
  5. * SPDX-License-Identifier: Apache-2.0 OR MIT
  6. *
  7. */
  8. #include <ImageProcessing_Traits_Platform.h>
  9. #include <Editor/EditorCommon.h>
  10. #include <Processing/ImageToProcess.h>
  11. #include <ImageLoader/ImageLoaders.h>
  12. #include <BuilderSettings/TextureSettings.h>
  13. #include <BuilderSettings/PresetSettings.h>
  14. #include <Atom/ImageProcessing/PixelFormats.h>
  15. #include <Converters/Cubemap.h>
  16. #include <Processing/ImageConvert.h>
  17. #include <AzCore/std/string/conversions.h>
  18. #include <AzFramework/StringFunc/StringFunc.h>
  19. namespace ImageProcessingAtomEditor
  20. {
  21. using namespace ImageProcessingAtom;
  22. bool EditorHelper::s_IsPixelFormatStringInited = false;
  23. const char* EditorHelper::s_PixelFormatString[ImageProcessingAtom::EPixelFormat::ePixelFormat_Count];
  24. void EditorHelper::InitPixelFormatString()
  25. {
  26. if (!s_IsPixelFormatStringInited)
  27. {
  28. s_IsPixelFormatStringInited = true;
  29. }
  30. CPixelFormats& pixelFormats = CPixelFormats::GetInstance();
  31. for (int format = 0; format < EPixelFormat::ePixelFormat_Count; format ++)
  32. {
  33. const PixelFormatInfo* info = pixelFormats.GetPixelFormatInfo((EPixelFormat)format);
  34. s_PixelFormatString[(EPixelFormat)format] = "";
  35. if (info)
  36. {
  37. s_PixelFormatString[(EPixelFormat)format] = info->szName;
  38. }
  39. else
  40. {
  41. AZ_Error("Texture Editor", false, "Cannot find name of EPixelFormat %i", format);
  42. }
  43. }
  44. }
  45. const AZStd::string EditorHelper::GetFileSizeString(size_t fileSizeInBytes)
  46. {
  47. AZStd::string fileSizeStr;
  48. static double kb = 1024.0f;
  49. static double mb = kb * 1024.0;
  50. static double gb = mb * 1024.0;
  51. static AZStd::fixed_string<2> byteStr = "B";
  52. static AZStd::fixed_string<3> kbStr = "KB";
  53. static AZStd::fixed_string<3> mbStr = "MB";
  54. static AZStd::fixed_string<3> gbStr = "GB";
  55. #if AZ_TRAIT_IMAGEPROCESSING_USE_BASE10_BYTE_PREFIX
  56. kb = 1000.0;
  57. mb = kb * 1000.0;
  58. gb = mb * 1000.0;
  59. kbStr = "kB";
  60. mbStr = "mB";
  61. gbStr = "gB";
  62. #endif // AZ_TRAIT_IMAGEPROCESSING_USE_BASE10_BYTE_PREFIX
  63. if (fileSizeInBytes < kb)
  64. {
  65. fileSizeStr = AZStd::string::format("%zu %s", fileSizeInBytes, byteStr.c_str());
  66. }
  67. else if (fileSizeInBytes < mb)
  68. {
  69. double size = fileSizeInBytes / kb;
  70. fileSizeStr = AZStd::string::format("%.2f %s", size, kbStr.c_str());
  71. }
  72. else if (fileSizeInBytes < gb)
  73. {
  74. double size = fileSizeInBytes / mb;
  75. fileSizeStr = AZStd::string::format("%.2f %s", size, mbStr.c_str());
  76. }
  77. else
  78. {
  79. double size = fileSizeInBytes / gb;
  80. fileSizeStr = AZStd::string::format("%.2f %s", size, gbStr.c_str());
  81. }
  82. return fileSizeStr;
  83. }
  84. const AZStd::string EditorHelper::ToReadablePlatformString(const AZStd::string& platformRawStr)
  85. {
  86. AZStd::string readableString;
  87. AZStd::string platformStrLowerCase = platformRawStr;
  88. AZStd::to_lower(platformStrLowerCase.begin(), platformStrLowerCase.end());
  89. if (platformStrLowerCase == "pc")
  90. {
  91. readableString = "PC";
  92. }
  93. else if (platformStrLowerCase == "linux")
  94. {
  95. readableString = "Linux";
  96. }
  97. else if (platformStrLowerCase == "android")
  98. {
  99. readableString = "Android";
  100. }
  101. else if (platformStrLowerCase == "mac")
  102. {
  103. readableString = "macOS";
  104. }
  105. else if (platformStrLowerCase == "provo")
  106. {
  107. readableString = "Provo";
  108. }
  109. else if (platformStrLowerCase == "ios")
  110. {
  111. readableString = "iOS";
  112. }
  113. else if (platformStrLowerCase == "salem")
  114. {
  115. readableString = "Salem";
  116. }
  117. else if (platformStrLowerCase == "jasper")
  118. {
  119. readableString = "Jasper";
  120. }
  121. else
  122. {
  123. return platformRawStr;
  124. }
  125. return readableString;
  126. }
  127. EditorTextureSetting::EditorTextureSetting(const AZ::Uuid& sourceTextureId)
  128. {
  129. const AzToolsFramework::AssetBrowser::SourceAssetBrowserEntry* fullDetails = AzToolsFramework::AssetBrowser::SourceAssetBrowserEntry::GetSourceByUuid(sourceTextureId);
  130. if (fullDetails)
  131. {
  132. InitFromPath(fullDetails->GetFullPath());
  133. }
  134. }
  135. EditorTextureSetting::EditorTextureSetting(const AZStd::string& texturePath)
  136. {
  137. InitFromPath(texturePath);
  138. }
  139. void EditorTextureSetting::InitFromPath(const AZStd::string& texturePath)
  140. {
  141. m_fullPath = texturePath;
  142. AzFramework::StringFunc::Path::GetFullFileName(texturePath.c_str(), m_textureName);
  143. m_img = IImageObjectPtr(LoadImageFromFile(m_fullPath));
  144. if (m_img == nullptr)
  145. {
  146. AZ_Warning("Texture Editor", false, "%s is not a valid texture image.", texturePath.c_str());
  147. return;
  148. }
  149. bool generatedDefaults = false;
  150. m_settingsMap = TextureSettings::GetMultiplatformTextureSetting(m_fullPath, generatedDefaults);
  151. // Get the preset id from one platform. The preset id for each platform should always be same
  152. AZ_Assert(m_settingsMap.size() > 0, "There is no platform information");
  153. PresetName presetName = m_settingsMap.begin()->second.m_preset;
  154. const PresetSettings* preset = BuilderSettingManager::Instance()->GetPreset(presetName);
  155. if (!preset)
  156. {
  157. AZ_Warning("Texture Editor", false, "Cannot find preset %s! Will assign a suggested one for the texture.", presetName.GetCStr());
  158. presetName = BuilderSettingManager::Instance()->GetSuggestedPreset(m_fullPath);
  159. for (auto& settingIter : m_settingsMap)
  160. {
  161. settingIter.second.ApplyPreset(presetName);
  162. }
  163. }
  164. }
  165. void EditorTextureSetting::SetIsOverrided()
  166. {
  167. for (auto& it : m_settingsMap)
  168. {
  169. m_overrideFromPreset = false;
  170. TextureSettings& textureSetting = it.second;
  171. const PresetSettings* presetSetting = BuilderSettingManager::Instance()->GetPreset(textureSetting.m_preset);
  172. if (presetSetting != nullptr)
  173. {
  174. if ((textureSetting.m_sizeReduceLevel != presetSetting->m_sizeReduceLevel) ||
  175. (textureSetting.m_suppressEngineReduce != presetSetting->m_suppressEngineReduce) ||
  176. (presetSetting->m_mipmapSetting != nullptr && textureSetting.m_mipGenType != presetSetting->m_mipmapSetting->m_type))
  177. {
  178. m_overrideFromPreset = true;
  179. }
  180. }
  181. else
  182. {
  183. AZ_Error("Texture Editor", false, "Texture Preset %s is not found!", textureSetting.m_preset.GetCStr());
  184. }
  185. }
  186. }
  187. void EditorTextureSetting::SetToPreset(const PresetName& presetName)
  188. {
  189. m_overrideFromPreset = false;
  190. for (auto& settingIter : m_settingsMap)
  191. {
  192. settingIter.second.ApplyPreset(presetName);
  193. }
  194. }
  195. //Get the texture setting on certain platform
  196. TextureSettings& EditorTextureSetting::GetMultiplatformTextureSetting(const AZStd::string& platform)
  197. {
  198. AZ_Assert(m_settingsMap.size() > 0, "Texture Editor", "There is no texture settings for texture %s", m_fullPath.c_str());
  199. PlatformName platformName = platform;
  200. if (platform.empty())
  201. {
  202. platformName = BuilderSettingManager::s_defaultPlatform;
  203. }
  204. if (m_settingsMap.find(platformName) != m_settingsMap.end())
  205. {
  206. return m_settingsMap[platformName];
  207. }
  208. else
  209. {
  210. AZ_Error("Texture Editor", false, "Cannot find texture setting on platform %s", platformName.c_str());
  211. }
  212. return m_settingsMap.begin()->second;
  213. }
  214. bool EditorTextureSetting::GetFinalInfoForTextureOnPlatform(const AZStd::string& platform, AZ::u32 wantedReduce, ResolutionInfo& outResolutionInfo)
  215. {
  216. if (m_settingsMap.find(platform) == m_settingsMap.end())
  217. {
  218. return false;
  219. }
  220. // Copy current texture setting and set to desired reduce
  221. TextureSettings textureSetting = m_settingsMap[platform];
  222. wantedReduce = AZStd::min<int>(AZStd::max<int>(s_MinReduceLevel, wantedReduce), s_MaxReduceLevel);
  223. textureSetting.m_sizeReduceLevel = wantedReduce;
  224. const PresetSettings* presetSetting = BuilderSettingManager::Instance()->GetPreset(textureSetting.m_preset, platform);
  225. if (presetSetting)
  226. {
  227. EPixelFormat pixelFormat = presetSetting->m_pixelFormat;
  228. CPixelFormats& pixelFormats = CPixelFormats::GetInstance();
  229. AZ::u32 inputWidth = m_img->GetWidth(0);
  230. AZ::u32 inputHeight = m_img->GetHeight(0);
  231. // Update input width and height if it's a cubemap
  232. if (presetSetting->m_cubemapSetting != nullptr)
  233. {
  234. if (IsValidLatLongMap(m_img))
  235. {
  236. inputWidth = inputWidth/4;
  237. }
  238. else
  239. {
  240. CubemapLayout *srcCubemap = CubemapLayout::CreateCubemapLayout(m_img);
  241. if (srcCubemap == nullptr)
  242. {
  243. return false;
  244. }
  245. inputWidth = srcCubemap->GetFaceSize();
  246. delete srcCubemap;
  247. }
  248. inputHeight = inputWidth;
  249. outResolutionInfo.arrayCount = 6;
  250. }
  251. GetOutputExtent(inputWidth, inputHeight, outResolutionInfo.width, outResolutionInfo.height, outResolutionInfo.reduce, &textureSetting, presetSetting);
  252. AZ::u32 mipMapCount = pixelFormats.ComputeMaxMipCount(pixelFormat, outResolutionInfo.width, outResolutionInfo.height);
  253. outResolutionInfo.mipCount = presetSetting->m_mipmapSetting != nullptr && textureSetting.m_enableMipmap ? mipMapCount : 1;
  254. return true;
  255. }
  256. else
  257. {
  258. return false;
  259. }
  260. }
  261. bool EditorTextureSetting::RefreshMipSetting(bool enableMip)
  262. {
  263. bool enabled = true;
  264. for (auto& it : m_settingsMap)
  265. {
  266. const PresetSettings* preset = BuilderSettingManager::Instance()->GetPreset(it.second.m_preset);
  267. if (enableMip)
  268. {
  269. if (preset && preset->m_mipmapSetting)
  270. {
  271. it.second.m_enableMipmap = true;
  272. it.second.m_mipGenType = preset->m_mipmapSetting->m_type;
  273. }
  274. else
  275. {
  276. it.second.m_enableMipmap = false;
  277. enabled = false;
  278. AZ_Error("Texture Editor", false, "Preset %s does not support mipmap!", preset->m_name.GetCStr());
  279. }
  280. }
  281. else
  282. {
  283. it.second.m_enableMipmap = false;
  284. enabled = false;
  285. }
  286. }
  287. return enabled;
  288. }
  289. void EditorTextureSetting::PropagateCommonSettings()
  290. {
  291. if (m_settingsMap.size() <= 1)
  292. {
  293. //Only one setting available, no need to propagate
  294. return;
  295. }
  296. TextureSettings& texSetting = GetMultiplatformTextureSetting();
  297. for (auto& it = ++ m_settingsMap.begin(); it != m_settingsMap.end(); ++it)
  298. {
  299. const PlatformName defaultPlatform = BuilderSettingManager::s_defaultPlatform;
  300. if (it->first != defaultPlatform)
  301. {
  302. it->second.m_enableMipmap = texSetting.m_enableMipmap;
  303. it->second.m_maintainAlphaCoverage = texSetting.m_maintainAlphaCoverage;
  304. it->second.m_mipGenEval = texSetting.m_mipGenEval;
  305. it->second.m_mipGenType = texSetting.m_mipGenType;
  306. for (size_t i = 0; i < TextureSettings::s_MaxMipMaps; i++)
  307. {
  308. it->second.m_mipAlphaAdjust[i] = texSetting.m_mipAlphaAdjust[i];
  309. }
  310. }
  311. }
  312. }
  313. AZStd::list<ResolutionInfo> EditorTextureSetting::GetResolutionInfo(AZStd::string platform, AZ::u32& minReduce, AZ::u32& maxReduce)
  314. {
  315. AZStd::list<ResolutionInfo> resolutionInfos;
  316. // Set the min/max reduce to the global value range first
  317. minReduce = s_MaxReduceLevel;
  318. maxReduce = s_MinReduceLevel;
  319. for (AZ::u32 i = s_MinReduceLevel; i <= s_MaxReduceLevel; i++)
  320. {
  321. ResolutionInfo resolutionInfo;
  322. GetFinalInfoForTextureOnPlatform(platform, i, resolutionInfo);
  323. // If actual reduce is lower than desired reduce, it reaches the limit and we can stop try lower resolution
  324. if (i > resolutionInfo.reduce)
  325. {
  326. break;
  327. }
  328. // Finds out the final min/max reduce based on range in different platforms
  329. minReduce = AZStd::min<AZ::u32>(resolutionInfo.reduce, minReduce);
  330. maxReduce = AZStd::max<AZ::u32>(resolutionInfo.reduce, maxReduce);
  331. resolutionInfos.push_back(resolutionInfo);
  332. }
  333. return resolutionInfos;
  334. }
  335. AZStd::list<ResolutionInfo> EditorTextureSetting::GetResolutionInfoForMipmap(AZStd::string platform)
  336. {
  337. AZStd::list<ResolutionInfo> resolutionInfos;
  338. unsigned int baseReduce = m_settingsMap[platform].m_sizeReduceLevel;
  339. ResolutionInfo baseInfo;
  340. GetFinalInfoForTextureOnPlatform(platform, baseReduce, baseInfo);
  341. resolutionInfos.push_back(baseInfo);
  342. for (AZ::u32 i = 1; i < baseInfo.mipCount; i++)
  343. {
  344. ResolutionInfo resolutionInfo = baseInfo;
  345. resolutionInfo.width = AZStd::max<AZ::u32>(baseInfo.width >> i, 1);
  346. resolutionInfo.height = AZStd::max<AZ::u32>(baseInfo.height >> i, 1);
  347. resolutionInfo.reduce = baseInfo.reduce + i;
  348. resolutionInfo.mipCount = 1;
  349. resolutionInfos.push_back(resolutionInfo);
  350. }
  351. return resolutionInfos;
  352. }
  353. } //namespace ImageProcessingAtomEditor