ImageAsset.h 21 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545
  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. #include "gfx/gfxDevice.h"
  45. #ifndef _MATTEXTURETARGET_H_
  46. #include "materials/matTextureTarget.h"
  47. #endif
  48. //-----------------------------------------------------------------------------
  49. class ImageAsset : public AssetBase
  50. {
  51. typedef AssetBase Parent;
  52. typedef AssetPtr<ImageAsset> ConcreteAssetPtr;
  53. public:
  54. /// The different types of image use cases
  55. enum ImageTypes
  56. {
  57. Albedo = 0,
  58. Normal = 1,
  59. ORMConfig = 2,
  60. GUI = 3,
  61. Roughness = 4,
  62. AO = 5,
  63. Metalness = 6,
  64. Glow = 7,
  65. Particle = 8,
  66. Decal = 9,
  67. Cubemap = 10,
  68. ImageTypeCount = 11
  69. };
  70. static StringTableEntry smNoImageAssetFallback;
  71. enum ImageAssetErrCode
  72. {
  73. TooManyMips = AssetErrCode::Extended,
  74. Extended
  75. };
  76. static const String mErrCodeStrings[U32(ImageAssetErrCode::Extended) - U32(Parent::Extended) + 1];
  77. static U32 getAssetErrCode(ConcreteAssetPtr checkAsset) { if (checkAsset) return checkAsset->mLoadedState; else return 0; }
  78. static String getAssetErrstrn(U32 errCode)
  79. {
  80. if (errCode < Parent::Extended) return Parent::getAssetErrstrn(errCode);
  81. if (errCode > ImageAssetErrCode::Extended) return "undefined error";
  82. return mErrCodeStrings[errCode - Parent::Extended];
  83. };
  84. protected:
  85. StringTableEntry mImageFileName;
  86. StringTableEntry mImagePath;
  87. NamedTexTargetRef mNamedTarget;
  88. bool mIsValidImage;
  89. bool mUseMips;
  90. bool mIsHDRImage;
  91. ImageTypes mImageType;
  92. HashMap<GFXTextureProfile*, GFXTexHandle> mResourceMap;
  93. typedef Signal<void()> ImageAssetChanged;
  94. ImageAssetChanged mChangeSignal;
  95. typedef Signal<void(S32 index)> ImageAssetArrayChanged;
  96. ImageAssetArrayChanged mChangeArraySignal;
  97. public:
  98. ImageAsset();
  99. virtual ~ImageAsset();
  100. /// Set up some global script interface stuff.
  101. static void consoleInit();
  102. /// Engine.
  103. static void initPersistFields();
  104. void copyTo(SimObject* object) override;
  105. /// Declare Console Object.
  106. DECLARE_CONOBJECT(ImageAsset);
  107. void _onResourceChanged(const Torque::Path& path);
  108. ImageAssetChanged& getChangedSignal() { return mChangeSignal; }
  109. ImageAssetArrayChanged& getChangedArraySignal() { return mChangeArraySignal; }
  110. void setImageFileName(StringTableEntry pScriptFile);
  111. inline StringTableEntry getImageFileName(void) const { return mImageFileName; };
  112. inline StringTableEntry getImagePath(void) const { return mImagePath; };
  113. bool isValid() { return mIsValidImage; }
  114. GFXTexHandle getTexture(GFXTextureProfile* requestedProfile);
  115. StringTableEntry getImageInfo();
  116. static StringTableEntry getImageTypeNameFromType(ImageTypes type);
  117. static ImageTypes getImageTypeFromName(StringTableEntry name);
  118. void setImageType(ImageTypes type) { mImageType = type; }
  119. ImageTypes getImageType() { return mImageType; }
  120. static U32 getAssetByFilename(StringTableEntry fileName, AssetPtr<ImageAsset>* imageAsset);
  121. static StringTableEntry getAssetIdByFilename(StringTableEntry fileName);
  122. static U32 getAssetById(StringTableEntry assetId, AssetPtr<ImageAsset>* imageAsset);
  123. static U32 getAssetById(String assetId, AssetPtr<ImageAsset>* imageAsset) { return getAssetById(assetId.c_str(), imageAsset); };
  124. U32 load() override;
  125. protected:
  126. void initializeAsset(void) override;
  127. void onAssetRefresh(void) override;
  128. static bool setImageFileName(void* obj, StringTableEntry index, StringTableEntry data) { static_cast<ImageAsset*>(obj)->setImageFileName(data); return false; }
  129. static StringTableEntry getImageFileName(void* obj, StringTableEntry data) { return static_cast<ImageAsset*>(obj)->getImageFileName(); }
  130. };
  131. DefineConsoleType(TypeImageAssetPtr, ImageAsset)
  132. DefineConsoleType(TypeImageAssetId, String)
  133. typedef ImageAsset::ImageTypes ImageAssetType;
  134. DefineEnumType(ImageAssetType);
  135. #pragma region Singular Asset Macros
  136. //Singular assets
  137. /// <Summary>
  138. /// Declares an image asset
  139. /// This establishes the assetId, asset and legacy filepath fields, along with supplemental getter and setter functions
  140. /// </Summary>
  141. #define DECLARE_IMAGEASSET(className, name, changeFunc, profile) public: \
  142. GFXTexHandle m##name = NULL;\
  143. StringTableEntry m##name##Name; \
  144. StringTableEntry m##name##AssetId;\
  145. AssetPtr<ImageAsset> m##name##Asset;\
  146. GFXTextureProfile* m##name##Profile = &profile;\
  147. public: \
  148. const StringTableEntry get##name##File() const { return m##name##Name; }\
  149. void set##name##File(const FileName &_in) { m##name##Name = StringTable->insert(_in.c_str());}\
  150. const AssetPtr<ImageAsset> & get##name##Asset() const { return m##name##Asset; }\
  151. void set##name##Asset(const AssetPtr<ImageAsset> &_in) { m##name##Asset = _in;}\
  152. \
  153. bool _set##name(StringTableEntry _in)\
  154. {\
  155. if(m##name##AssetId != _in || m##name##Name != _in)\
  156. {\
  157. if (m##name##Asset.notNull())\
  158. {\
  159. m##name##Asset->getChangedSignal().remove(this, &className::changeFunc);\
  160. }\
  161. if (_in == NULL || _in == StringTable->EmptyString())\
  162. {\
  163. m##name##Name = StringTable->EmptyString();\
  164. m##name##AssetId = StringTable->EmptyString();\
  165. m##name##Asset = NULL;\
  166. m##name.free();\
  167. m##name = NULL;\
  168. return true;\
  169. }\
  170. else if(_in[0] == '$' || _in[0] == '#')\
  171. {\
  172. m##name##Name = _in;\
  173. m##name##AssetId = StringTable->EmptyString();\
  174. m##name##Asset = NULL;\
  175. m##name.free();\
  176. m##name = NULL;\
  177. return true;\
  178. }\
  179. \
  180. if (AssetDatabase.isDeclaredAsset(_in))\
  181. {\
  182. m##name##AssetId = _in;\
  183. \
  184. U32 assetState = ImageAsset::getAssetById(m##name##AssetId, &m##name##Asset);\
  185. \
  186. if (ImageAsset::Ok == assetState)\
  187. {\
  188. m##name##Name = StringTable->EmptyString();\
  189. }\
  190. }\
  191. else\
  192. {\
  193. StringTableEntry assetId = ImageAsset::getAssetIdByFilename(_in);\
  194. if (assetId != StringTable->EmptyString())\
  195. {\
  196. m##name##AssetId = assetId;\
  197. if (ImageAsset::getAssetById(m##name##AssetId, &m##name##Asset) == ImageAsset::Ok)\
  198. {\
  199. m##name##Name = StringTable->EmptyString();\
  200. }\
  201. }\
  202. else\
  203. {\
  204. m##name##Name = _in;\
  205. m##name##AssetId = StringTable->EmptyString();\
  206. m##name##Asset = NULL;\
  207. }\
  208. }\
  209. }\
  210. if (get##name() != StringTable->EmptyString() && m##name##Name != StringTable->insert("texhandle"))\
  211. {\
  212. if (m##name##Asset.notNull())\
  213. {\
  214. m##name##Asset->getChangedSignal().notify(this, &className::changeFunc);\
  215. }\
  216. \
  217. if (get##name()[0] != '$' && get##name()[0] != '#') {\
  218. m##name.set(get##name(), m##name##Profile, avar("%s() - mTextureObject (line %d)", __FUNCTION__, __LINE__));\
  219. }\
  220. }\
  221. else\
  222. {\
  223. m##name.free();\
  224. m##name = NULL;\
  225. }\
  226. \
  227. if(get##name() == StringTable->EmptyString())\
  228. return true;\
  229. \
  230. if (m##name##Asset.notNull() && m##name##Asset->getStatus() != ImageAsset::Ok)\
  231. {\
  232. 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());\
  233. return false; \
  234. }\
  235. else if (!m##name)\
  236. {\
  237. if (GFX->getAdapterType() != NullDevice)\
  238. Con::errorf("%s(%s)::_set%s() - Couldn't load image \"%s\"", macroText(className), getName(), macroText(name), _in);\
  239. return false;\
  240. }\
  241. return true;\
  242. }\
  243. \
  244. const StringTableEntry get##name() const\
  245. {\
  246. if (m##name##Asset && (m##name##Asset->getImageFileName() != StringTable->EmptyString()))\
  247. if (m##name##Asset->getImageFileName()[0] == '#' || m##name##Asset->getImageFileName()[0] == '$')\
  248. return m##name##Asset->getImageFileName();\
  249. else\
  250. return Platform::makeRelativePathName(m##name##Asset->getImagePath(), Platform::getMainDotCsDir());\
  251. else if (m##name##AssetId != StringTable->EmptyString())\
  252. return m##name##AssetId;\
  253. else if (m##name##Name != StringTable->EmptyString())\
  254. return StringTable->insert(Platform::makeRelativePathName(m##name##Name, Platform::getMainDotCsDir()));\
  255. else\
  256. return StringTable->EmptyString();\
  257. }\
  258. GFXTexHandle get##name##Resource() \
  259. {\
  260. if (m##name##Asset && (m##name##Asset->getImageFileName() != StringTable->EmptyString()))\
  261. return m##name##Asset->getTexture(m##name##Profile);\
  262. return m##name;\
  263. }\
  264. bool name##Valid() {return (get##name() != StringTable->EmptyString() && m##name##Asset->getStatus() == AssetBase::Ok); }
  265. #ifdef TORQUE_SHOW_LEGACY_FILE_FIELDS
  266. #define INITPERSISTFIELD_IMAGEASSET(name, consoleClass, docs) \
  267. addProtectedField(#name, TypeImageFilename, Offset(m##name##Name, consoleClass), _set##name##Data, &defaultProtectedGetFn, assetDoc(name, docs)); \
  268. addProtectedField(assetText(name, Asset), TypeImageAssetId, Offset(m##name##AssetId, consoleClass), _set##name##Data, &defaultProtectedGetFn, assetDoc(name, asset docs.));
  269. #else
  270. #define INITPERSISTFIELD_IMAGEASSET(name, consoleClass, docs) \
  271. addProtectedField(#name, TypeImageFilename, Offset(m##name##Name, consoleClass), _set##name##Data, &defaultProtectedGetFn, assetDoc(name, docs), AbstractClassRep::FIELD_HideInInspectors); \
  272. addProtectedField(assetText(name, Asset), TypeImageAssetId, Offset(m##name##AssetId, consoleClass), _set##name##Data, &defaultProtectedGetFn, assetDoc(name, asset docs.));
  273. #endif // SHOW_LEGACY_FILE_FIELDS
  274. #define LOAD_IMAGEASSET(name)\
  275. if (m##name##AssetId != StringTable->EmptyString())\
  276. {\
  277. S32 assetState = ImageAsset::getAssetById(m##name##AssetId, &m##name##Asset);\
  278. if (assetState == ImageAsset::Ok )\
  279. {\
  280. m##name##Name = StringTable->EmptyString();\
  281. }\
  282. else Con::warnf("Warning: %s::LOAD_IMAGEASSET(%s)-%s", mClassName, m##name##AssetId, ImageAsset::getAssetErrstrn(assetState).c_str());\
  283. }
  284. #pragma endregion
  285. #pragma region Arrayed Asset Macros
  286. //Arrayed Assets
  287. #define DECLARE_IMAGEASSET_ARRAY(className, name, max, changeFunc) public: \
  288. static const U32 sm##name##Count = max;\
  289. GFXTexHandle m##name[max];\
  290. StringTableEntry m##name##Name[max]; \
  291. StringTableEntry m##name##AssetId[max];\
  292. AssetPtr<ImageAsset> m##name##Asset[max];\
  293. GFXTextureProfile * m##name##Profile[max];\
  294. public: \
  295. const StringTableEntry get##name##File(const U32& index) const { return m##name##Name[index]; }\
  296. void set##name##File(const FileName &_in, const U32& index) { m##name##Name[index] = StringTable->insert(_in.c_str());}\
  297. const AssetPtr<ImageAsset> & get##name##Asset(const U32& index) const { return m##name##Asset[index]; }\
  298. void set##name##Asset(const AssetPtr<ImageAsset> &_in, const U32& index) { m##name##Asset[index] = _in;}\
  299. \
  300. bool _set##name(StringTableEntry _in, const U32& index)\
  301. {\
  302. if(m##name##AssetId[index] != _in || m##name##Name[index] != _in)\
  303. {\
  304. if(index >= sm##name##Count || index < 0)\
  305. return false;\
  306. if (_in == NULL || _in == StringTable->EmptyString())\
  307. {\
  308. m##name##Name[index] = StringTable->EmptyString();\
  309. m##name##AssetId[index] = StringTable->EmptyString();\
  310. m##name##Asset[index] = NULL;\
  311. m##name[index].free();\
  312. m##name[index] = NULL;\
  313. return true;\
  314. }\
  315. else if(_in[0] == '$' || _in[0] == '#')\
  316. {\
  317. m##name##Name[index] = _in;\
  318. m##name##AssetId[index] = StringTable->EmptyString();\
  319. m##name##Asset[index] = NULL;\
  320. m##name[index].free();\
  321. m##name[index] = NULL;\
  322. return true;\
  323. }\
  324. \
  325. if (AssetDatabase.isDeclaredAsset(_in))\
  326. {\
  327. m##name##AssetId[index] = _in;\
  328. \
  329. U32 assetState = ImageAsset::getAssetById(m##name##AssetId[index], &m##name##Asset[index]);\
  330. \
  331. if (ImageAsset::Ok == assetState)\
  332. {\
  333. m##name##Name[index] = StringTable->EmptyString();\
  334. }\
  335. }\
  336. else\
  337. {\
  338. StringTableEntry assetId = ImageAsset::getAssetIdByFilename(_in);\
  339. if (assetId != StringTable->EmptyString())\
  340. {\
  341. m##name##AssetId[index] = assetId;\
  342. if (ImageAsset::getAssetById(m##name##AssetId[index], &m##name##Asset[index]) == ImageAsset::Ok)\
  343. {\
  344. m##name##Name[index] = StringTable->EmptyString();\
  345. }\
  346. }\
  347. else\
  348. {\
  349. m##name##Name[index] = _in;\
  350. m##name##AssetId[index] = StringTable->EmptyString();\
  351. m##name##Asset[index] = NULL;\
  352. }\
  353. }\
  354. }\
  355. if (get##name(index) != StringTable->EmptyString() && m##name##Name[index] != StringTable->insert("texhandle"))\
  356. {\
  357. m##name##Asset[index]->getChangedSignal().notify(this, &className::changeFunc);\
  358. if (get##name(index)[0] != '$' && get##name(index)[0] != '#')\
  359. m##name[index].set(get##name(index), m##name##Profile[index], avar("%s() - mTextureObject (line %d)", __FUNCTION__, __LINE__));\
  360. }\
  361. else\
  362. {\
  363. m##name[index].free();\
  364. m##name[index] = NULL;\
  365. }\
  366. \
  367. if(get##name(index) == StringTable->EmptyString())\
  368. return true;\
  369. \
  370. if (m##name##Asset[index].notNull() && m##name##Asset[index]->getStatus() != ImageAsset::Ok)\
  371. {\
  372. 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());\
  373. return false; \
  374. }\
  375. else if (!m##name[index])\
  376. {\
  377. if (GFX->getAdapterType() != NullDevice)\
  378. Con::errorf("%s(%s)::_set%s(%i) - Couldn't load image \"%s\"", macroText(className), getName(), macroText(name), index, _in);\
  379. return false; \
  380. }\
  381. return true;\
  382. }\
  383. \
  384. const StringTableEntry get##name(const U32& index) const\
  385. {\
  386. if (m##name##Asset[index] && (m##name##Asset[index]->getImageFileName() != StringTable->EmptyString()))\
  387. if (m##name##Asset[index]->getImageFileName()[0] == '#' || m##name##Asset[index]->getImageFileName()[0] == '$')\
  388. return m##name##Asset[index]->getImageFileName();\
  389. else\
  390. return Platform::makeRelativePathName(m##name##Asset[index]->getImagePath(), Platform::getMainDotCsDir());\
  391. else if (m##name##AssetId[index] != StringTable->EmptyString())\
  392. return m##name##AssetId[index];\
  393. else if (m##name##Name[index] != StringTable->EmptyString())\
  394. {\
  395. if (String(m##name##Name[index]).startsWith("#") || String(m##name##Name[index]).startsWith("$"))\
  396. return StringTable->insert(m##name##Name[index]);\
  397. else\
  398. return StringTable->insert(Platform::makeRelativePathName(m##name##Name[index], Platform::getMainDotCsDir()));\
  399. }\
  400. else\
  401. return StringTable->EmptyString();\
  402. }\
  403. GFXTexHandle get##name##Resource(const U32& index) \
  404. {\
  405. if(index >= sm##name##Count || index < 0)\
  406. return nullptr;\
  407. if (m##name##Asset[index] && (m##name##Asset[index]->getImageFileName() != StringTable->EmptyString()))\
  408. return m##name##Asset[index]->getTexture(m##name##Profile[index]);\
  409. return m##name[index];\
  410. }\
  411. bool name##Valid(const U32& id) {return (get##name(id) != StringTable->EmptyString() && m##name##Asset[id]->getStatus() == AssetBase::Ok); }
  412. #define DECLARE_IMAGEASSET_ARRAY_SETGET(className, name)\
  413. static bool _set##name##Data(void* obj, const char* index, const char* data)\
  414. {\
  415. if (!index) return false;\
  416. U32 idx = dAtoi(index);\
  417. if (idx >= sm##name##Count)\
  418. return false;\
  419. bool ret = false;\
  420. className* object = static_cast<className*>(obj);\
  421. ret = object->_set##name(StringTable->insert(data),idx);\
  422. return ret;\
  423. }
  424. #define DECLARE_IMAGEASSET_ARRAY_NET_SETGET(className, name, bitmask)\
  425. static bool _set##name##Data(void* obj, const char* index, const char* data)\
  426. {\
  427. if (!index) return false;\
  428. U32 idx = dAtoi(index);\
  429. if (idx >= sm##name##Count)\
  430. return false;\
  431. bool ret = false;\
  432. className* object = static_cast<className*>(obj);\
  433. ret = object->_set##name(StringTable->insert(data),idx);\
  434. if(ret)\
  435. object->setMaskBits(bitmask);\
  436. return ret;\
  437. }
  438. #define INIT_IMAGEASSET_ARRAY(name, profile, index) \
  439. {\
  440. m##name##Name[index] = StringTable->EmptyString(); \
  441. m##name##AssetId[index] = StringTable->EmptyString(); \
  442. m##name##Asset[index] = NULL;\
  443. m##name[index] = NULL;\
  444. m##name##Profile[index] = &profile;\
  445. }
  446. #define DEF_IMAGEASSET_ARRAY_BINDS(className,name)\
  447. DefineEngineMethod(className, get##name, const char*, (S32 index), , "get name")\
  448. {\
  449. return object->get##name(index); \
  450. }\
  451. DefineEngineMethod(className, get##name##Asset, const char*, (S32 index), , assetText(name, asset reference))\
  452. {\
  453. if(index >= className::sm##name##Count || index < 0)\
  454. return "";\
  455. return object->m##name##AssetId[index]; \
  456. }\
  457. DefineEngineMethod(className, set##name, bool, (const char* map, S32 index), , assetText(name,assignment. first tries asset then flat file.))\
  458. {\
  459. return object->_set##name(StringTable->insert(map), index);\
  460. }
  461. #ifdef TORQUE_SHOW_LEGACY_FILE_FIELDS
  462. #define INITPERSISTFIELD_IMAGEASSET_ARRAY(name, arraySize, consoleClass, docs) \
  463. addProtectedField(#name, TypeImageFilename, Offset(m##name##Name, consoleClass), _set##name##Data, &defaultProtectedGetFn, arraySize, assetDoc(name, docs)); \
  464. addProtectedField(assetText(name, Asset), TypeImageAssetId, Offset(m##name##AssetId, consoleClass), _set##name##Data, &defaultProtectedGetFn, arraySize, assetDoc(name, asset docs.));
  465. #else
  466. #define INITPERSISTFIELD_IMAGEASSET_ARRAY(name, arraySize, consoleClass, docs) \
  467. addProtectedField(#name, TypeImageFilename, Offset(m##name##Name, consoleClass), _set##name##Data, &defaultProtectedGetFn, arraySize, assetDoc(name, docs), AbstractClassRep::FIELD_HideInInspectors); \
  468. addProtectedField(assetText(name, Asset), TypeImageAssetId, Offset(m##name##AssetId, consoleClass), _set##name##Data, &defaultProtectedGetFn, arraySize, assetDoc(name, asset docs.));
  469. #endif
  470. #define LOAD_IMAGEASSET_ARRAY(name, index)\
  471. if (m##name##AssetId[index] != StringTable->EmptyString())\
  472. {\
  473. S32 assetState = ImageAsset::getAssetById(m##name##AssetId[index], &m##name##Asset[index]);\
  474. if (assetState == ImageAsset::Ok )\
  475. {\
  476. m##name##Name[index] = StringTable->EmptyString();\
  477. }\
  478. else Con::warnf("Warning: %s::LOAD_IMAGEASSET(%s)-%s", mClassName, m##name##AssetId[index], ImageAsset::getAssetErrstrn(assetState).c_str());\
  479. }
  480. #pragma endregion