ImageAsset.h 19 KB

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