ImageAsset.h 19 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505
  1. #pragma once
  2. //-----------------------------------------------------------------------------
  3. // Copyright (c) 2013 GarageGames, LLC
  4. //
  5. // Permission is hereby granted, free of charge, to any person obtaining a copy
  6. // of this software and associated documentation files (the "Software"), to
  7. // deal in the Software without restriction, including without limitation the
  8. // rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
  9. // sell copies of the Software, and to permit persons to whom the Software is
  10. // furnished to do so, subject to the following conditions:
  11. //
  12. // The above copyright notice and this permission notice shall be included in
  13. // all copies or substantial portions of the Software.
  14. //
  15. // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  16. // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  17. // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
  18. // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  19. // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
  20. // FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
  21. // IN THE SOFTWARE.
  22. //-----------------------------------------------------------------------------
  23. #pragma once
  24. #ifndef _ASSET_BASE_H_
  25. #include "assets/assetBase.h"
  26. #endif
  27. #ifndef _ASSET_DEFINITION_H_
  28. #include "assets/assetDefinition.h"
  29. #endif
  30. #ifndef _STRINGUNIT_H_
  31. #include "string/stringUnit.h"
  32. #endif
  33. #ifndef _ASSET_FIELD_TYPES_H_
  34. #include "assets/assetFieldTypes.h"
  35. #endif
  36. #ifndef _ASSET_PTR_H_
  37. #include "assets/assetPtr.h"
  38. #endif
  39. #include "gfx/bitmap/gBitmap.h"
  40. #include "gfx/gfxTextureHandle.h"
  41. #include "sim/netConnection.h"
  42. #include <string>
  43. #include "assetMacroHelpers.h"
  44. //-----------------------------------------------------------------------------
  45. class ImageAsset : public AssetBase
  46. {
  47. typedef AssetBase Parent;
  48. public:
  49. /// The different types of image use cases
  50. enum ImageTypes
  51. {
  52. Albedo = 0,
  53. Normal = 1,
  54. ORMConfig = 2,
  55. GUI = 3,
  56. Roughness = 4,
  57. AO = 5,
  58. Metalness = 6,
  59. Glow = 7,
  60. Particle = 8,
  61. Decal = 9,
  62. Cubemap = 10,
  63. ImageTypeCount = 11
  64. };
  65. static StringTableEntry smNoImageAssetFallback;
  66. protected:
  67. StringTableEntry mImageFileName;
  68. StringTableEntry mImagePath;
  69. bool mIsValidImage;
  70. bool mUseMips;
  71. bool mIsHDRImage;
  72. ImageTypes mImageType;
  73. HashMap<GFXTextureProfile*, GFXTexHandle> mResourceMap;
  74. typedef Signal<void()> ImageAssetChanged;
  75. ImageAssetChanged mChangeSignal;
  76. typedef Signal<void(S32 index)> ImageAssetArrayChanged;
  77. ImageAssetArrayChanged mChangeArraySignal;
  78. public:
  79. ImageAsset();
  80. virtual ~ImageAsset();
  81. /// Set up some global script interface stuff.
  82. static void consoleInit();
  83. /// Engine.
  84. static void initPersistFields();
  85. virtual void copyTo(SimObject* object);
  86. /// Declare Console Object.
  87. DECLARE_CONOBJECT(ImageAsset);
  88. void _onResourceChanged(const Torque::Path& path);
  89. ImageAssetChanged& getChangedSignal() { return mChangeSignal; }
  90. ImageAssetArrayChanged& getChangedArraySignal() { return mChangeArraySignal; }
  91. void setImageFileName(StringTableEntry pScriptFile);
  92. inline StringTableEntry getImageFileName(void) const { return mImageFileName; };
  93. inline StringTableEntry getImagePath(void) const { return mImagePath; };
  94. bool isValid() { return mIsValidImage; }
  95. const GBitmap& getImage();
  96. GFXTexHandle getTexture(GFXTextureProfile* requestedProfile);
  97. StringTableEntry getImageInfo();
  98. static StringTableEntry getImageTypeNameFromType(ImageTypes type);
  99. static ImageTypes getImageTypeFromName(StringTableEntry name);
  100. void setImageType(ImageTypes type) { mImageType = type; }
  101. ImageTypes getImageType() { return mImageType; }
  102. static U32 getAssetByFilename(StringTableEntry fileName, AssetPtr<ImageAsset>* imageAsset);
  103. static StringTableEntry getAssetIdByFilename(StringTableEntry fileName);
  104. static U32 getAssetById(StringTableEntry assetId, AssetPtr<ImageAsset>* imageAsset);
  105. static U32 getAssetById(String assetId, AssetPtr<ImageAsset>* imageAsset) { return getAssetById(assetId.c_str(), imageAsset); };
  106. protected:
  107. virtual void initializeAsset(void);
  108. virtual void onAssetRefresh(void);
  109. static bool setImageFileName(void* obj, StringTableEntry index, StringTableEntry data) { static_cast<ImageAsset*>(obj)->setImageFileName(data); return false; }
  110. static StringTableEntry getImageFileName(void* obj, StringTableEntry data) { return static_cast<ImageAsset*>(obj)->getImageFileName(); }
  111. void loadImage();
  112. };
  113. DefineConsoleType(TypeImageAssetPtr, ImageAsset)
  114. DefineConsoleType(TypeImageAssetId, String)
  115. typedef ImageAsset::ImageTypes ImageAssetType;
  116. DefineEnumType(ImageAssetType);
  117. #pragma region Singular Asset Macros
  118. //Singular assets
  119. /// <Summary>
  120. /// Declares an image asset
  121. /// This establishes the assetId, asset and legacy filepath fields, along with supplemental getter and setter functions
  122. /// </Summary>
  123. #define DECLARE_IMAGEASSET(className, name, changeFunc, profile) public: \
  124. GFXTexHandle m##name = NULL;\
  125. StringTableEntry m##name##Name; \
  126. StringTableEntry m##name##AssetId;\
  127. AssetPtr<ImageAsset> m##name##Asset;\
  128. GFXTextureProfile* m##name##Profile = &profile;\
  129. public: \
  130. const StringTableEntry get##name##File() const { return m##name##Name; }\
  131. void set##name##File(const FileName &_in) { m##name##Name = StringTable->insert(_in.c_str());}\
  132. const AssetPtr<ImageAsset> & get##name##Asset() const { return m##name##Asset; }\
  133. void set##name##Asset(const AssetPtr<ImageAsset> &_in) { m##name##Asset = _in;}\
  134. \
  135. bool _set##name(StringTableEntry _in)\
  136. {\
  137. if(m##name##AssetId != _in || m##name##Name != _in)\
  138. {\
  139. if (m##name##Asset.notNull())\
  140. {\
  141. m##name##Asset->getChangedSignal().remove(this, &className::changeFunc);\
  142. }\
  143. if (_in == NULL || _in == StringTable->EmptyString())\
  144. {\
  145. m##name##Name = StringTable->EmptyString();\
  146. m##name##AssetId = StringTable->EmptyString();\
  147. m##name##Asset = NULL;\
  148. m##name.free();\
  149. m##name = NULL;\
  150. return true;\
  151. }\
  152. else if(_in[0] == '$' || _in[0] == '#')\
  153. {\
  154. m##name##Name = _in;\
  155. m##name##AssetId = StringTable->EmptyString();\
  156. m##name##Asset = NULL;\
  157. m##name.free();\
  158. m##name = NULL;\
  159. return true;\
  160. }\
  161. \
  162. if (AssetDatabase.isDeclaredAsset(_in))\
  163. {\
  164. m##name##AssetId = _in;\
  165. \
  166. U32 assetState = ImageAsset::getAssetById(m##name##AssetId, &m##name##Asset);\
  167. \
  168. if (ImageAsset::Ok == assetState)\
  169. {\
  170. m##name##Name = StringTable->EmptyString();\
  171. }\
  172. }\
  173. else\
  174. {\
  175. StringTableEntry assetId = ImageAsset::getAssetIdByFilename(_in);\
  176. if (assetId != StringTable->EmptyString())\
  177. {\
  178. m##name##AssetId = assetId;\
  179. if (ImageAsset::getAssetById(m##name##AssetId, &m##name##Asset) == ImageAsset::Ok)\
  180. {\
  181. m##name##Name = StringTable->EmptyString();\
  182. }\
  183. }\
  184. else\
  185. {\
  186. m##name##Name = _in;\
  187. m##name##AssetId = StringTable->EmptyString();\
  188. m##name##Asset = NULL;\
  189. }\
  190. }\
  191. }\
  192. if (get##name() != StringTable->EmptyString() && m##name##Name != StringTable->insert("texhandle"))\
  193. {\
  194. if (m##name##Asset.notNull())\
  195. {\
  196. m##name##Asset->getChangedSignal().notify(this, &className::changeFunc);\
  197. }\
  198. \
  199. m##name.set(get##name(), m##name##Profile, avar("%s() - mTextureObject (line %d)", __FUNCTION__, __LINE__));\
  200. }\
  201. else\
  202. {\
  203. m##name.free();\
  204. m##name = NULL;\
  205. }\
  206. \
  207. if(get##name() == StringTable->EmptyString())\
  208. return true;\
  209. \
  210. if (m##name##Asset.notNull() && m##name##Asset->getStatus() != ImageAsset::Ok)\
  211. {\
  212. Con::errorf("%s(%s)::_set%s() - image asset failure\"%s\" due to [%s]", macroText(className), getName(), macroText(name), _in, ImageAsset::getAssetErrstrn(m##name##Asset->getStatus()).c_str());\
  213. return false; \
  214. }\
  215. else if (!m##name)\
  216. {\
  217. Con::errorf("%s(%s)::_set%s() - Couldn't load image \"%s\"", macroText(className), getName(), macroText(name), _in);\
  218. return false;\
  219. }\
  220. return true;\
  221. }\
  222. \
  223. const StringTableEntry get##name() const\
  224. {\
  225. if (m##name##Asset && (m##name##Asset->getImageFileName() != StringTable->EmptyString()))\
  226. return Platform::makeRelativePathName(m##name##Asset->getImagePath(), Platform::getMainDotCsDir());\
  227. else if (m##name##AssetId != StringTable->EmptyString())\
  228. return m##name##AssetId;\
  229. else if (m##name##Name != StringTable->EmptyString())\
  230. return StringTable->insert(Platform::makeRelativePathName(m##name##Name, Platform::getMainDotCsDir()));\
  231. else\
  232. return StringTable->EmptyString();\
  233. }\
  234. GFXTexHandle get##name##Resource() \
  235. {\
  236. return m##name;\
  237. }\
  238. bool name##Valid() {return (get##name() != StringTable->EmptyString() && m##name##Asset->getStatus() == AssetBase::Ok); }
  239. #ifdef TORQUE_SHOW_LEGACY_FILE_FIELDS
  240. #define INITPERSISTFIELD_IMAGEASSET(name, consoleClass, docs) \
  241. addProtectedField(#name, TypeImageFilename, Offset(m##name##Name, consoleClass), _set##name##Data, &defaultProtectedGetFn, assetDoc(name, docs)); \
  242. addProtectedField(assetText(name, Asset), TypeImageAssetId, Offset(m##name##AssetId, consoleClass), _set##name##Data, &defaultProtectedGetFn, assetDoc(name, asset docs.));
  243. #else
  244. #define INITPERSISTFIELD_IMAGEASSET(name, consoleClass, docs) \
  245. addProtectedField(#name, TypeImageFilename, Offset(m##name##Name, consoleClass), _set##name##Data, &defaultProtectedGetFn, assetDoc(name, docs), AbstractClassRep::FIELD_HideInInspectors); \
  246. addProtectedField(assetText(name, Asset), TypeImageAssetId, Offset(m##name##AssetId, consoleClass), _set##name##Data, &defaultProtectedGetFn, assetDoc(name, asset docs.));
  247. #endif // SHOW_LEGACY_FILE_FIELDS
  248. #define LOAD_IMAGEASSET(name)\
  249. if (m##name##AssetId != StringTable->EmptyString())\
  250. {\
  251. S32 assetState = ImageAsset::getAssetById(m##name##AssetId, &m##name##Asset);\
  252. if (assetState == ImageAsset::Ok )\
  253. {\
  254. m##name##Name = StringTable->EmptyString();\
  255. }\
  256. else Con::warnf("Warning: %s::LOAD_IMAGEASSET(%s)-%s", mClassName, m##name##AssetId, ImageAsset::getAssetErrstrn(assetState).c_str());\
  257. }
  258. #pragma endregion
  259. #pragma region Arrayed Asset Macros
  260. //Arrayed Assets
  261. #define DECLARE_IMAGEASSET_ARRAY(className, name, max) public: \
  262. static const U32 sm##name##Count = max;\
  263. GFXTexHandle m##name[max];\
  264. StringTableEntry m##name##Name[max]; \
  265. StringTableEntry m##name##AssetId[max];\
  266. AssetPtr<ImageAsset> m##name##Asset[max];\
  267. GFXTextureProfile * m##name##Profile[max];\
  268. public: \
  269. const StringTableEntry get##name##File(const U32& index) const { return m##name##Name[index]; }\
  270. void set##name##File(const FileName &_in, const U32& index) { m##name##Name[index] = StringTable->insert(_in.c_str());}\
  271. const AssetPtr<ImageAsset> & get##name##Asset(const U32& index) const { return m##name##Asset[index]; }\
  272. void set##name##Asset(const AssetPtr<ImageAsset> &_in, const U32& index) { m##name##Asset[index] = _in;}\
  273. \
  274. bool _set##name(StringTableEntry _in, const U32& index)\
  275. {\
  276. if(m##name##AssetId[index] != _in || m##name##Name[index] != _in)\
  277. {\
  278. if(index >= sm##name##Count || index < 0)\
  279. return false;\
  280. if (_in == NULL || _in == StringTable->EmptyString())\
  281. {\
  282. m##name##Name[index] = StringTable->EmptyString();\
  283. m##name##AssetId[index] = StringTable->EmptyString();\
  284. m##name##Asset[index] = NULL;\
  285. m##name[index].free();\
  286. m##name[index] = NULL;\
  287. return true;\
  288. }\
  289. else if(_in[0] == '$' || _in[0] == '#')\
  290. {\
  291. m##name##Name[index] = _in;\
  292. m##name##AssetId[index] = StringTable->EmptyString();\
  293. m##name##Asset[index] = NULL;\
  294. m##name[index].free();\
  295. m##name[index] = NULL;\
  296. return true;\
  297. }\
  298. \
  299. if (AssetDatabase.isDeclaredAsset(_in))\
  300. {\
  301. m##name##AssetId[index] = _in;\
  302. \
  303. U32 assetState = ImageAsset::getAssetById(m##name##AssetId[index], &m##name##Asset[index]);\
  304. \
  305. if (ImageAsset::Ok == assetState)\
  306. {\
  307. m##name##Name[index] = StringTable->EmptyString();\
  308. }\
  309. }\
  310. else\
  311. {\
  312. StringTableEntry assetId = ImageAsset::getAssetIdByFilename(_in);\
  313. if (assetId != StringTable->EmptyString())\
  314. {\
  315. m##name##AssetId[index] = assetId;\
  316. if (ImageAsset::getAssetById(m##name##AssetId[index], &m##name##Asset[index]) == ImageAsset::Ok)\
  317. {\
  318. m##name##Name[index] = StringTable->EmptyString();\
  319. }\
  320. }\
  321. else\
  322. {\
  323. m##name##Name[index] = _in;\
  324. m##name##AssetId[index] = StringTable->EmptyString();\
  325. m##name##Asset[index] = NULL;\
  326. }\
  327. }\
  328. }\
  329. if (get##name(index) != StringTable->EmptyString() && m##name##Name[index] != StringTable->insert("texhandle"))\
  330. {\
  331. m##name[index].set(get##name(index), m##name##Profile[index], avar("%s() - mTextureObject (line %d)", __FUNCTION__, __LINE__));\
  332. }\
  333. else\
  334. {\
  335. m##name[index].free();\
  336. m##name[index] = NULL;\
  337. }\
  338. \
  339. if(get##name(index) == StringTable->EmptyString())\
  340. return true;\
  341. \
  342. if (m##name##Asset[index].notNull() && m##name##Asset[index]->getStatus() != ImageAsset::Ok)\
  343. {\
  344. Con::errorf("%s(%s)::_set%s(%i) - image asset failure\"%s\" due to [%s]", macroText(className), getName(), macroText(name), index, _in, ImageAsset::getAssetErrstrn(m##name##Asset[index]->getStatus()).c_str());\
  345. return false; \
  346. }\
  347. else if (!m##name[index])\
  348. {\
  349. Con::errorf("%s(%s)::_set%s(%i) - Couldn't load image \"%s\"", macroText(className), getName(), macroText(name), index, _in);\
  350. return false; \
  351. }\
  352. return true;\
  353. }\
  354. \
  355. const StringTableEntry get##name(const U32& index) const\
  356. {\
  357. if (m##name##Asset[index] && (m##name##Asset[index]->getImageFileName() != StringTable->EmptyString()))\
  358. return Platform::makeRelativePathName(m##name##Asset[index]->getImagePath(), Platform::getMainDotCsDir());\
  359. else if (m##name##AssetId[index] != StringTable->EmptyString())\
  360. return m##name##AssetId[index];\
  361. else if (m##name##Name[index] != StringTable->EmptyString())\
  362. {\
  363. if (String(m##name##Name[index]).startsWith("#") || String(m##name##Name[index]).startsWith("$"))\
  364. return StringTable->insert(m##name##Name[index]);\
  365. else\
  366. return StringTable->insert(Platform::makeRelativePathName(m##name##Name[index], Platform::getMainDotCsDir()));\
  367. }\
  368. else\
  369. return StringTable->EmptyString();\
  370. }\
  371. GFXTexHandle get##name##Resource(const U32& index) \
  372. {\
  373. if(index >= sm##name##Count || index < 0)\
  374. return nullptr;\
  375. return m##name[index];\
  376. }\
  377. bool name##Valid(const U32& id) {return (get##name(id) != StringTable->EmptyString() && m##name##Asset[id]->getStatus() == AssetBase::Ok); }
  378. #define DECLARE_IMAGEASSET_ARRAY_SETGET(className, name)\
  379. static bool _set##name##Data(void* obj, const char* index, const char* data)\
  380. {\
  381. if (!index) return false;\
  382. U32 idx = dAtoi(index);\
  383. if (idx >= sm##name##Count)\
  384. return false;\
  385. bool ret = false;\
  386. className* object = static_cast<className*>(obj);\
  387. ret = object->_set##name(StringTable->insert(data),idx);\
  388. return ret;\
  389. }
  390. #define DECLARE_IMAGEASSET_ARRAY_NET_SETGET(className, name, bitmask)\
  391. static bool _set##name##Data(void* obj, const char* index, const char* data)\
  392. {\
  393. if (!index) return false;\
  394. U32 idx = dAtoi(index);\
  395. if (idx >= sm##name##Count)\
  396. return false;\
  397. bool ret = false;\
  398. className* object = static_cast<className*>(obj);\
  399. ret = object->_set##name(StringTable->insert(data),idx);\
  400. if(ret)\
  401. object->setMaskBits(bitmask);\
  402. return ret;\
  403. }
  404. #define INIT_IMAGEASSET_ARRAY(name, profile, index) \
  405. {\
  406. m##name##Name[index] = StringTable->EmptyString(); \
  407. m##name##AssetId[index] = StringTable->EmptyString(); \
  408. m##name##Asset[index] = NULL;\
  409. m##name[index] = NULL;\
  410. m##name##Profile[index] = &profile;\
  411. }
  412. #define DEF_IMAGEASSET_ARRAY_BINDS(className,name)\
  413. DefineEngineMethod(className, get##name, const char*, (S32 index), , "get name")\
  414. {\
  415. return object->get##name(index); \
  416. }\
  417. DefineEngineMethod(className, get##name##Asset, const char*, (S32 index), , assetText(name, asset reference))\
  418. {\
  419. if(index >= className::sm##name##Count || index < 0)\
  420. return "";\
  421. return object->m##name##AssetId[index]; \
  422. }\
  423. DefineEngineMethod(className, set##name, bool, (const char* map, S32 index), , assetText(name,assignment. first tries asset then flat file.))\
  424. {\
  425. return object->_set##name(StringTable->insert(map), index);\
  426. }
  427. #ifdef TORQUE_SHOW_LEGACY_FILE_FIELDS
  428. #define INITPERSISTFIELD_IMAGEASSET_ARRAY(name, arraySize, consoleClass, docs) \
  429. addProtectedField(#name, TypeImageFilename, Offset(m##name##Name, consoleClass), _set##name##Data, &defaultProtectedGetFn, arraySize, assetDoc(name, docs)); \
  430. addProtectedField(assetText(name, Asset), TypeImageAssetId, Offset(m##name##AssetId, consoleClass), _set##name##Data, &defaultProtectedGetFn, arraySize, assetDoc(name, asset docs.));
  431. #else
  432. #define INITPERSISTFIELD_IMAGEASSET_ARRAY(name, arraySize, consoleClass, docs) \
  433. addProtectedField(#name, TypeImageFilename, Offset(m##name##Name, consoleClass), _set##name##Data, &defaultProtectedGetFn, arraySize, assetDoc(name, docs), AbstractClassRep::FIELD_HideInInspectors); \
  434. addProtectedField(assetText(name, Asset), TypeImageAssetId, Offset(m##name##AssetId, consoleClass), _set##name##Data, &defaultProtectedGetFn, arraySize, assetDoc(name, asset docs.));
  435. #endif
  436. #define LOAD_IMAGEASSET_ARRAY(name, index)\
  437. if (m##name##AssetId[index] != StringTable->EmptyString())\
  438. {\
  439. S32 assetState = ImageAsset::getAssetById(m##name##AssetId[index], &m##name##Asset[index]);\
  440. if (assetState == ImageAsset::Ok )\
  441. {\
  442. m##name##Name[index] = StringTable->EmptyString();\
  443. }\
  444. else Con::warnf("Warning: %s::LOAD_IMAGEASSET(%s)-%s", mClassName, m##name##AssetId[index], ImageAsset::getAssetErrstrn(assetState).c_str());\
  445. }
  446. #pragma endregion