assetmgr.cpp 74 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579
  1. /*
  2. ** Command & Conquer Renegade(tm)
  3. ** Copyright 2025 Electronic Arts Inc.
  4. **
  5. ** This program is free software: you can redistribute it and/or modify
  6. ** it under the terms of the GNU General Public License as published by
  7. ** the Free Software Foundation, either version 3 of the License, or
  8. ** (at your option) any later version.
  9. **
  10. ** This program is distributed in the hope that it will be useful,
  11. ** but WITHOUT ANY WARRANTY; without even the implied warranty of
  12. ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  13. ** GNU General Public License for more details.
  14. **
  15. ** You should have received a copy of the GNU General Public License
  16. ** along with this program. If not, see <http://www.gnu.org/licenses/>.
  17. */
  18. /* $Header: /Commando/Code/ww3d2/assetmgr.cpp 43 11/01/01 1:11a Jani_p $ */
  19. /***********************************************************************************************
  20. *** Confidential - Westwood Studios ***
  21. ***********************************************************************************************
  22. * *
  23. * Project Name : Commando *
  24. * *
  25. * $Archive:: /Commando/Code/ww3d2/assetmgr.cpp $*
  26. * *
  27. * Author:: Greg_h *
  28. * *
  29. * $Modtime:: 10/31/01 8:00p $*
  30. * *
  31. * $Revision:: 43 $*
  32. * *
  33. *---------------------------------------------------------------------------------------------*
  34. * Functions: *
  35. * WW3DAssetManager::WW3DAssetManager -- Constructor *
  36. * WW3DAssetManager::~WW3DAssetManager -- Destructor *
  37. * WW3DAssetManager::Free -- free all memory (un-needed?) *
  38. * WW3DAssetManager::Free_Assets -- Release all loaded assets *
  39. * WW3DAssetManager::Load_3D_Assets -- Load 3D assets from a .W3D file *
  40. * WW3DAssetManager::Load_Prototype -- loads a prototype from a W3D chunk *
  41. * WW3DAssetManager::Create_Render_Obj -- Create a render object for the user *
  42. * WW3DAssetManager::Render_Obj_Exists -- Check whether a render object with the given name *
  43. * WW3DAssetManager::Create_Render_Obj_Iterator -- Create an iterator which can enumerate al *
  44. * WW3DAssetManager::Release_Render_Obj_Iterator -- release a render object iterator *
  45. * WW3DAssetManager::Create_HAnim_Iterator -- Creates an HAnim Iterator *
  46. * WW3DAssetManager::Create_HTree_Iterator -- creates an htree iterator *
  47. * WW3DAssetManager::Create_Material_Iterator -- Create a material iterator *
  48. * WW3DAssetManager::Create_Font3DData_Iterator -- Create a Font3DData iterator *
  49. * WW3DAssetManager::Get_HAnim -- Returns a pointer to a names HAnim *
  50. * WW3DAssetManager::Get_HTree -- Returns a pointer to the named HTree *
  51. * WW3DAssetManager::Get_Material -- Gets a pointer to a loaded material or creates it *
  52. * WW3DAssetManager::Get_Material -- Gets a pointer to a loaded material or creates the mate *
  53. * WW3DAssetManager::Get_Material -- Gets a pointer to a loaded material or creates it *
  54. * WW3DAssetManager::Get_Font3DInstance -- Creates a pointer to a Font3DInstance *
  55. * WW3DAssetManager::Get_Font3DData -- Gets a pointer to a loaded Font3DData or creates it *
  56. * WW3DAssetManager::Release_Material -- Release a material *
  57. * WW3DAssetManager::Release_Font3DData -- Release a Font3DData *
  58. * WW3DAssetManager::Add_Material -- Add a material to the list *
  59. * WW3DAssetManager::Add_Font3DData -- Add a Font3DData to the list *
  60. * WW3DAssetManager::Get_Texture -- get a TextureClass for the specified targa *
  61. * WW3DAssetManager::Release_All_Textures -- release all textures in the system *
  62. * WW3DAssetManager::Register_Prototype_Loader -- add a new loader to the system *
  63. * WW3DAssetManager::Find_Prototype_Loader -- find the loader that handles this chunk type *
  64. * WW3DAssetManager::Add_Prototype -- adds the prototype to the hash table *
  65. * WW3DAssetManager::Find_Prototype -- searches the hash table for the prototype *
  66. * WW3DAssetManager::Open_Texture_File_Cache -- Turn on the texture cache system. *
  67. * WW3DAssetManager::Close_Texture_File_Cache -- Turn off the texture cache system. *
  68. * CachedTextureFileClass::getMipmapData -- get data for texture - check to see if in cache. *
  69. * CachedTextureFileClass::getMipmapLevelPartial -- not yet implemented *
  70. * CachedTextureFileClass::setupDefaultValues -- loads texture in to get default data. *
  71. * WW3DAssetManager::Get_Streaming_Texture -- Gets a streaming texture. *
  72. * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
  73. #include "assetmgr.h"
  74. #include <assert.h>
  75. #include "bittype.h"
  76. #include "chunkio.h"
  77. #include "realcrc.h"
  78. #include "wwdebug.h"
  79. #include "htreemgr.h"
  80. #include "hanimmgr.h"
  81. #include "texture.h"
  82. #include "font3d.h"
  83. #include "render2dsentence.h" // for FontCharsClass
  84. #include "proto.h"
  85. #include "hanim.h"
  86. #include "hcanim.h"
  87. #include "htree.h"
  88. #include "collect.h"
  89. #include "ww3d.h"
  90. #include "ffactory.h"
  91. #include "boxrobj.h"
  92. #include "nullrobj.h"
  93. #include "distlod.h"
  94. #include "hlod.h"
  95. #include "agg_def.h"
  96. #include "texfcach.h"
  97. #include "wwstring.h"
  98. #include "wwmemlog.h"
  99. #include "dazzle.h"
  100. #include "dx8wrapper.h"
  101. #include "metalmap.h"
  102. #include <ini.h>
  103. #include <windows.h>
  104. #include <stdio.h>
  105. #include <D3dx8core.h>
  106. #include "texture.h"
  107. #include "wwprofile.h"
  108. #include "assetstatus.h"
  109. /*
  110. ** Static member variable which keeps track of the single instanced asset manager
  111. */
  112. WW3DAssetManager * WW3DAssetManager::TheInstance = NULL;
  113. /*
  114. ** Static instance of the Null prototype. This render object is special cased
  115. ** to always be available...
  116. */
  117. static NullPrototypeClass _NullPrototype;
  118. /*
  119. ** Iterator for the Render Objects in the asset manager
  120. */
  121. class RObjIterator : public RenderObjIterator
  122. {
  123. public:
  124. virtual bool Is_Done(void);
  125. virtual const char * Current_Item_Name(void);
  126. virtual int Current_Item_Class_ID(void);
  127. protected:
  128. friend class WW3DAssetManager;
  129. };
  130. /*
  131. ** Iterators for the other types of 3D assets:
  132. ** HAnims, HTrees, Textures, Fonts
  133. */
  134. class HAnimIterator : public AssetIterator
  135. {
  136. public:
  137. HAnimIterator(void) : Iterator( WW3DAssetManager::Get_Instance()->HAnimManager ) { };
  138. virtual void First(void) { Iterator.First(); }
  139. virtual void Next(void) { Iterator.Next(); }
  140. virtual bool Is_Done(void) { return Iterator.Is_Done(); }
  141. virtual const char * Current_Item_Name(void) { return Iterator.Get_Current_Anim()->Get_Name(); }
  142. protected:
  143. HAnimManagerIterator Iterator;
  144. friend class WW3DAssetManager;
  145. };
  146. class HTreeIterator : public AssetIterator
  147. {
  148. public:
  149. virtual bool Is_Done(void);
  150. virtual const char * Current_Item_Name(void);
  151. protected:
  152. friend class WW3DAssetManager;
  153. };
  154. class Font3DDataIterator : public AssetIterator
  155. {
  156. public:
  157. virtual void First(void) { Node = WW3DAssetManager::Get_Instance()->Font3DDatas.Head(); }
  158. virtual void Next(void) { Node = Node->Next(); }
  159. virtual bool Is_Done(void) { return Node==NULL; }
  160. virtual const char * Current_Item_Name(void) { return Node->Data()->Name; }
  161. protected:
  162. Font3DDataIterator(void) { Node = WW3DAssetManager::Get_Instance()->Font3DDatas.Head(); }
  163. SLNode<Font3DDataClass> * Node;
  164. friend class WW3DAssetManager;
  165. };
  166. /***********************************************************************************************
  167. * WW3DAssetManager::WW3DAssetManager -- Constructor *
  168. * *
  169. * INPUT: *
  170. * *
  171. * OUTPUT: *
  172. * *
  173. * WARNINGS: *
  174. * *
  175. * HISTORY: *
  176. * 12/21/97 GTH : Created. *
  177. * 05/10/1999 SKB : Add TextureCache *
  178. *=============================================================================================*/
  179. WW3DAssetManager::WW3DAssetManager(void) :
  180. PrototypeLoaders (PROTOLOADERS_VECTOR_SIZE),
  181. Prototypes (PROTOTYPES_VECTOR_SIZE),
  182. #ifdef WW3D_DX8
  183. TextureCache (NULL),
  184. #endif //WW3D_DX8
  185. WW3D_Load_On_Demand (false),
  186. Activate_Fog_On_Load (false),
  187. MetalManager(0)
  188. {
  189. assert(TheInstance == NULL);
  190. TheInstance = this;
  191. // set the growth rates
  192. PrototypeLoaders.Set_Growth_Step(PROTOLOADERS_GROWTH_RATE);
  193. Prototypes.Set_Growth_Step(PROTOTYPES_GROWTH_RATE);
  194. // install the default loaders
  195. Register_Prototype_Loader(&_MeshLoader);
  196. Register_Prototype_Loader(&_HModelLoader);
  197. Register_Prototype_Loader(&_CollectionLoader);
  198. Register_Prototype_Loader(&_BoxLoader);
  199. Register_Prototype_Loader(&_HLodLoader);
  200. Register_Prototype_Loader(&_DistLODLoader);
  201. Register_Prototype_Loader(&_AggregateLoader);
  202. Register_Prototype_Loader(&_NullLoader);
  203. Register_Prototype_Loader(&_DazzleLoader);
  204. // allocate the hash table and clear it.
  205. PrototypeHashTable = new PrototypeClass * [PROTOTYPE_HASH_TABLE_SIZE];
  206. memset(PrototypeHashTable,0,sizeof(PrototypeClass *) * PROTOTYPE_HASH_TABLE_SIZE);
  207. }
  208. /***********************************************************************************************
  209. * WW3DAssetManager::~WW3DAssetManager -- Destructor *
  210. * *
  211. * INPUT: *
  212. * *
  213. * OUTPUT: *
  214. * *
  215. * WARNINGS: *
  216. * *
  217. * HISTORY: *
  218. * 12/21/97 GTH : Created. *
  219. *=============================================================================================*/
  220. WW3DAssetManager::~WW3DAssetManager(void)
  221. {
  222. if (MetalManager) delete MetalManager;
  223. Free();
  224. TheInstance = NULL;
  225. // If we need to, free the hash table
  226. if (PrototypeHashTable != NULL) {
  227. delete [] PrototypeHashTable;
  228. PrototypeHashTable = NULL;
  229. }
  230. #ifdef WW3D_DX8
  231. Close_Texture_File_Cache();
  232. #endif //WW3D_DX8
  233. }
  234. static void Create_Number_String(StringClass& number, unsigned value)
  235. {
  236. unsigned miljoonat=value/(1024*1028);
  237. unsigned tuhannet=(value/1024)%1024;
  238. unsigned ykkoset=value%1024;
  239. if (miljoonat) {
  240. number.Format("%d %3.3d %3.3d",miljoonat,tuhannet,ykkoset);
  241. }
  242. else if (tuhannet) {
  243. number.Format("%d %3.3d",tuhannet,ykkoset);
  244. }
  245. else {
  246. number.Format("%d",ykkoset);
  247. }
  248. }
  249. void WW3DAssetManager::Load_Procedural_Textures()
  250. {
  251. int i,count;
  252. if (!MetalManager)
  253. {
  254. INIClass ini;
  255. ini.Load("metals.ini");
  256. MetalManager=new MetalMapManagerClass(ini);
  257. }
  258. count=MetalManager->Metal_Map_Count();
  259. for (i=0; i<count; i++)
  260. {
  261. TextureClass *tex=MetalManager->Get_Metal_Map(i);
  262. TextureHash.Insert(tex->Get_Texture_Name(),tex);
  263. }
  264. }
  265. static void Log_Textures(bool inited,unsigned& total_count, unsigned& total_mem)
  266. {
  267. HashTemplateIterator<StringClass,TextureClass*> ite(WW3DAssetManager::Get_Instance()->Texture_Hash());
  268. for (ite.First();!ite.Is_Done();ite.Next()) {
  269. TextureClass * tex=ite.Peek_Value();
  270. if (tex->Is_Initialized()!=inited) continue;
  271. D3DSURFACE_DESC desc;
  272. IDirect3DTexture8* d3d_texture=tex->Peek_DX8_Texture();
  273. if (!d3d_texture) continue;
  274. DX8_ErrorCode(d3d_texture->GetLevelDesc(0,&desc));
  275. StringClass tex_format="Unknown";
  276. switch (desc.Format) {
  277. case D3DFMT_A8R8G8B8: tex_format="D3DFMT_A8R8G8B8"; break;
  278. case D3DFMT_R8G8B8: tex_format="D3DFMT_R8G8B8"; break;
  279. case D3DFMT_A4R4G4B4: tex_format="D3DFMT_A4R4G4B4"; break;
  280. case D3DFMT_A1R5G5B5: tex_format="D3DFMT_A1R5G5B5"; break;
  281. case D3DFMT_R5G6B5: tex_format="D3DFMT_R5G6B5"; break;
  282. case D3DFMT_L8: tex_format="D3DFMT_L8"; break;
  283. case D3DFMT_A8: tex_format="D3DFMT_A8"; break;
  284. case D3DFMT_P8: tex_format="D3DFMT_P8"; break;
  285. case D3DFMT_X8R8G8B8: tex_format="D3DFMT_X8R8G8B8"; break;
  286. case D3DFMT_X1R5G5B5: tex_format="D3DFMT_X1R5G5B5"; break;
  287. case D3DFMT_R3G3B2: tex_format="D3DFMT_R3G3B2"; break;
  288. case D3DFMT_A8R3G3B2: tex_format="D3DFMT_A8R3G3B2"; break;
  289. case D3DFMT_X4R4G4B4: tex_format="D3DFMT_X4R4G4B4"; break;
  290. case D3DFMT_A8P8: tex_format="D3DFMT_A8P8"; break;
  291. case D3DFMT_A8L8: tex_format="D3DFMT_A8L8"; break;
  292. case D3DFMT_A4L4: tex_format="D3DFMT_A4L4"; break;
  293. case D3DFMT_V8U8: tex_format="D3DFMT_V8U8"; break;
  294. case D3DFMT_L6V5U5: tex_format="D3DFMT_L6V5U5"; break;
  295. case D3DFMT_X8L8V8U8: tex_format="D3DFMT_X8L8V8U8"; break;
  296. case D3DFMT_Q8W8V8U8: tex_format="D3DFMT_Q8W8V8U8"; break;
  297. case D3DFMT_V16U16: tex_format="D3DFMT_V16U16"; break;
  298. case D3DFMT_W11V11U10: tex_format="D3DFMT_W11V11U10"; break;
  299. case D3DFMT_UYVY: tex_format="D3DFMT_UYVY"; break;
  300. case D3DFMT_YUY2: tex_format="D3DFMT_YUY2"; break;
  301. case D3DFMT_DXT1: tex_format="D3DFMT_DXT1"; break;
  302. case D3DFMT_DXT2: tex_format="D3DFMT_DXT2"; break;
  303. case D3DFMT_DXT3: tex_format="D3DFMT_DXT3"; break;
  304. case D3DFMT_DXT4: tex_format="D3DFMT_DXT4"; break;
  305. case D3DFMT_DXT5: tex_format="D3DFMT_DXT5"; break;
  306. case D3DFMT_D16_LOCKABLE: tex_format="D3DFMT_D16_LOCKABLE"; break;
  307. case D3DFMT_D32: tex_format="D3DFMT_D32"; break;
  308. case D3DFMT_D15S1: tex_format="D3DFMT_D15S1"; break;
  309. case D3DFMT_D24S8: tex_format="D3DFMT_D24S8"; break;
  310. case D3DFMT_D16: tex_format="D3DFMT_D16"; break;
  311. case D3DFMT_D24X8: tex_format="D3DFMT_D24X8"; break;
  312. case D3DFMT_D24X4S4: tex_format="D3DFMT_D24X4S4"; break;
  313. default: break;
  314. }
  315. unsigned texmem=tex->Get_Texture_Memory_Usage();
  316. total_mem+=texmem;
  317. total_count++;
  318. StringClass number;
  319. Create_Number_String(number,texmem);
  320. WWDEBUG_SAY(("%32s %4d * %4d (%15s), init %d, size: %14s bytes, refs: %d\n",
  321. tex->Get_Texture_Name(),
  322. desc.Width,
  323. desc.Height,
  324. tex_format,
  325. tex->Is_Initialized(),
  326. number,
  327. tex->Num_Refs()));
  328. }
  329. }
  330. void WW3DAssetManager::Log_Texture_Statistics()
  331. {
  332. unsigned total_initialized_tex_mem=0;
  333. unsigned total_uninitialized_tex_mem=0;
  334. unsigned total_initialized_count=0;
  335. unsigned total_uninitialized_count=0;
  336. StringClass number;
  337. WWDEBUG_SAY(("\nInitialized textures ------------------------------------------\n\n"));
  338. Log_Textures(true,total_initialized_count,total_initialized_tex_mem);
  339. Create_Number_String(number,total_initialized_tex_mem);
  340. WWDEBUG_SAY(("\n%d initialized textures, totalling %14s bytes\n\n",
  341. total_initialized_count,
  342. number));
  343. WWDEBUG_SAY(("\nUn-initialized textures ---------------------------------------\n\n"));
  344. Log_Textures(false,total_uninitialized_count,total_uninitialized_tex_mem);
  345. Create_Number_String(number,total_uninitialized_tex_mem);
  346. WWDEBUG_SAY(("\n%d un-initialized textures, totalling, totalling %14s bytes\n\n",
  347. total_uninitialized_count,
  348. number));
  349. /*
  350. RenderObjIterator * rite=WW3DAssetManager::Get_Instance()->Create_Render_Obj_Iterator();
  351. if (rite) {
  352. for (rite->First(); !rite->Is_Done(); rite->Next()) {
  353. // RenderObjClass * robj=Create_Render_Obj(rite->Current_Item_Name());
  354. // if (robj) {
  355. //
  356. // robj->Release_Ref();
  357. // }
  358. if (rite->Current_Item_Class_ID()==RenderObjClass::CLASSID_HMODEL) {
  359. WWDEBUG_SAY(("robj: %s\n",rite->Current_Item_Name()));
  360. }
  361. }
  362. WW3DAssetManager::Get_Instance()->Release_Render_Obj_Iterator(rite);
  363. }
  364. */
  365. }
  366. /***********************************************************************************************
  367. * WW3DAssetManager::Free -- free all memory (un-needed?) *
  368. * *
  369. * INPUT: *
  370. * *
  371. * OUTPUT: *
  372. * *
  373. * WARNINGS: *
  374. * *
  375. * HISTORY: *
  376. * 12/21/97 GTH : Created. *
  377. *=============================================================================================*/
  378. void WW3DAssetManager::Free(void)
  379. {
  380. Free_Assets();
  381. }
  382. /***********************************************************************************************
  383. * WW3DAssetManager::Free_Assets -- Release all loaded assets *
  384. * *
  385. * INPUT: *
  386. * *
  387. * OUTPUT: *
  388. * *
  389. * WARNINGS: *
  390. * *
  391. * HISTORY: *
  392. * 12/21/97 GTH : Created. *
  393. * 05/10/1999 SKB : Close down texture cache file. *
  394. *=============================================================================================*/
  395. void WW3DAssetManager::Free_Assets(void)
  396. {
  397. WWPROFILE( "WW3DAssetManager::Free_Assets" );
  398. // delete all of the prototypes
  399. int count = Prototypes.Count();
  400. while (count-- > 0) {
  401. PrototypeClass * proto = Prototypes[count];
  402. Prototypes.Delete(count);
  403. if (proto != NULL) {
  404. delete proto;
  405. }
  406. }
  407. // clear the prototype hash table
  408. memset(PrototypeHashTable,0,sizeof(PrototypeClass *) * PROTOTYPE_HASH_TABLE_SIZE);
  409. // delete all of the anims and trees
  410. HAnimManager.Free_All_Anims();
  411. HTreeManager.Free_All_Trees();
  412. // release all my references to the materials
  413. Release_All_Textures();
  414. Release_All_Font3DDatas();
  415. Release_All_FontChars();
  416. // Close down cache if it is open.
  417. // NONONONOO.... Don't close it as we might want to free the assets and still be able to load textures.
  418. // Close_Texture_File_Cache();
  419. }
  420. /***********************************************************************************************
  421. * WW3DAssetManager::Free_Unused_Assets -- Release all assets that are referenced only by *
  422. * the asset manager. *
  423. * INPUT: *
  424. * *
  425. * OUTPUT: *
  426. * *
  427. * WARNINGS: *
  428. * *
  429. * HISTORY: *
  430. * 02/18/99 EHC : Created. *
  431. *=============================================================================================*/
  432. void WW3DAssetManager::Release_Unused_Assets(void)
  433. {
  434. // release all references to objects that have only one reference on them
  435. // and remove them from our lists.
  436. Release_Unused_Textures();
  437. Release_Unused_Font3DDatas();
  438. }
  439. /***********************************************************************************************
  440. * WW3DAssetManager::Load_3D_Assets -- Load 3D assets from a file *
  441. * *
  442. * INPUT: *
  443. * *
  444. * OUTPUT: *
  445. * *
  446. * WARNINGS: *
  447. * *
  448. * HISTORY: *
  449. * 10/22/98 BMG : Created. *
  450. *=============================================================================================*/
  451. bool WW3DAssetManager::Load_3D_Assets( const char * filename )
  452. {
  453. bool result = false;
  454. FileClass * file = _TheFileFactory->Get_File( filename );
  455. if ( file ) {
  456. if ( file->Is_Available() ) {
  457. result = WW3DAssetManager::Load_3D_Assets( *file );
  458. }
  459. _TheFileFactory->Return_File( file );
  460. }
  461. return result;
  462. }
  463. /***********************************************************************************************
  464. * WW3DAssetManager::Load_3D_Assets -- Load 3D assets from a .W3D file *
  465. * *
  466. * INPUT: *
  467. * *
  468. * OUTPUT: *
  469. * *
  470. * WARNINGS: *
  471. * *
  472. * HISTORY: *
  473. * 12/21/97 GTH : Created. *
  474. *=============================================================================================*/
  475. bool WW3DAssetManager::Load_3D_Assets(FileClass & w3dfile)
  476. {
  477. WWPROFILE( "WW3DAssetManager::Load_3D_Assets" );
  478. if (!w3dfile.Open()) {
  479. return false;
  480. }
  481. ChunkLoadClass cload(&w3dfile);
  482. while (cload.Open_Chunk()) {
  483. switch (cload.Cur_Chunk_ID()) {
  484. case W3D_CHUNK_HIERARCHY:
  485. HTreeManager.Load_Tree(cload);
  486. break;
  487. case W3D_CHUNK_ANIMATION:
  488. case W3D_CHUNK_COMPRESSED_ANIMATION:
  489. case W3D_CHUNK_MORPH_ANIMATION:
  490. HAnimManager.Load_Anim(cload);
  491. break;
  492. default:
  493. Load_Prototype(cload);
  494. break;
  495. }
  496. cload.Close_Chunk();
  497. }
  498. w3dfile.Close();
  499. return true;
  500. }
  501. /***********************************************************************************************
  502. * WW3DAssetManager::Load_Prototype -- loads a prototype from a W3D chunk *
  503. * *
  504. * INPUT: *
  505. * *
  506. * OUTPUT: *
  507. * *
  508. * WARNINGS: *
  509. * *
  510. * HISTORY: *
  511. * 7/29/98 GTH : Created. *
  512. * 2/19/99 EHC : Now has the Add_Prototype call responsible for adding the prototype to *
  513. * the Prototypes list object. *
  514. *=============================================================================================*/
  515. bool WW3DAssetManager::Load_Prototype(ChunkLoadClass & cload)
  516. {
  517. WWPROFILE( "WW3DAssetManager::Load_Prototype" );
  518. WWMEMLOG(MEM_GEOMETRY);
  519. /*
  520. ** Get the chunk id
  521. */
  522. int chunk_id = cload.Cur_Chunk_ID();
  523. /*
  524. ** Find a loader that handles that type of chunk
  525. */
  526. PrototypeLoaderClass * loader = Find_Prototype_Loader(chunk_id);
  527. PrototypeClass * newproto = NULL;
  528. if (loader != NULL) {
  529. /*
  530. ** Ask it to create a prototype from the contents of the
  531. ** chunk.
  532. */
  533. newproto = loader->Load_W3D(cload);
  534. } else {
  535. /*
  536. ** Warn user about an unknown chunk type
  537. */
  538. WWDEBUG_SAY(("Unknown chunk type encountered! Chunk Id = %d\r\n",chunk_id));
  539. return false;
  540. }
  541. /*
  542. ** Now, see if the prototype that we loaded has a duplicate
  543. ** name with any of our currently loaded prototypes (can't have that!)
  544. */
  545. if (newproto != NULL) {
  546. if (!Render_Obj_Exists(newproto->Get_Name())) {
  547. /*
  548. ** Add the new, unique prototype to our list
  549. */
  550. Add_Prototype(newproto);
  551. } else {
  552. /*
  553. ** Warn the user about a name collision with this prototype
  554. ** and dump it
  555. */
  556. WWDEBUG_SAY(("Render Object Name Collision: %s\r\n",newproto->Get_Name()));
  557. delete newproto;
  558. newproto = NULL;
  559. return false;
  560. }
  561. } else {
  562. /*
  563. ** Warn user that a prototype was not generated from this
  564. ** chunk type
  565. */
  566. WWDEBUG_SAY(("Could not generate prototype! Chunk = %d\r\n",chunk_id));
  567. return false;
  568. }
  569. return true;
  570. }
  571. /***********************************************************************************************
  572. * WW3DAssetManager::Create_Render_Obj -- Create a render object for the user *
  573. * *
  574. * This function will create any type of render object. I.e. if you pass in the name *
  575. * of an HModel, it will create an hmodel for you. *
  576. * *
  577. * INPUT: *
  578. * *
  579. * OUTPUT: *
  580. * *
  581. * WARNINGS: *
  582. * *
  583. * HISTORY: *
  584. * 12/21/97 GTH : Created. *
  585. *=============================================================================================*/
  586. RenderObjClass * WW3DAssetManager::Create_Render_Obj(const char * name)
  587. {
  588. WWPROFILE( "WW3DAssetManager::Create_Render_Obj" );
  589. WWMEMLOG(MEM_GEOMETRY);
  590. // Try to find a prototype
  591. PrototypeClass * proto = Find_Prototype(name);
  592. if (WW3D_Load_On_Demand && proto == NULL) { // If we didn't find one, try to load on demand
  593. AssetStatusClass::Peek_Instance()->Report_Load_On_Demand_RObj(name);
  594. char filename [MAX_PATH];
  595. char *mesh_name = ::strchr (name, '.');
  596. if (mesh_name != NULL) {
  597. ::lstrcpyn (filename, name, ((int)mesh_name) - ((int)name) + 1);
  598. ::lstrcat (filename, ".w3d");
  599. } else {
  600. sprintf( filename, "%s.w3d", name);
  601. }
  602. // If we can't find it, try the parent directory
  603. if ( Load_3D_Assets( filename ) == false ) {
  604. StringClass new_filename(StringClass("..\\"),true);
  605. new_filename+=filename;
  606. Load_3D_Assets( new_filename );
  607. }
  608. proto = Find_Prototype(name); // try again
  609. }
  610. if (proto == NULL) {
  611. AssetStatusClass::Peek_Instance()->Report_Missing_RObj(name);
  612. return NULL; // Failed to find a prototype
  613. }
  614. return proto->Create();
  615. }
  616. /***********************************************************************************************
  617. * WW3DAssetManager::Render_Obj_Exists -- Check whether a render object with the given name ex *
  618. * *
  619. * INPUT: *
  620. * *
  621. * OUTPUT: *
  622. * *
  623. * WARNINGS: *
  624. * *
  625. * HISTORY: *
  626. * 12/21/97 GTH : Created. *
  627. *=============================================================================================*/
  628. bool WW3DAssetManager::Render_Obj_Exists(const char * name)
  629. {
  630. if (Find_Prototype(name) == NULL) return false;
  631. else return true;
  632. }
  633. /***********************************************************************************************
  634. * WW3DAssetManager::Create_Render_Obj_Iterator -- Create an iterator which can enumerate all *
  635. * *
  636. * The iterator returned can enumerate all of the loaded render objects for you. *
  637. * The user is responsible for releasing the iterator! *
  638. * *
  639. * INPUT: *
  640. * *
  641. * OUTPUT: *
  642. * *
  643. * WARNINGS: *
  644. * User must release the iterator back to the asset manager or there will be a memory leak *
  645. * *
  646. * HISTORY: *
  647. * 12/21/97 GTH : Created. *
  648. *=============================================================================================*/
  649. RenderObjIterator * WW3DAssetManager::Create_Render_Obj_Iterator(void)
  650. {
  651. return new RObjIterator();
  652. }
  653. /***********************************************************************************************
  654. * WW3DAssetManager::Release_Render_Obj_Iterator -- release a render object iterator *
  655. * *
  656. * INPUT: *
  657. * *
  658. * OUTPUT: *
  659. * *
  660. * WARNINGS: *
  661. * *
  662. * HISTORY: *
  663. * 9/28/98 GTH : Created. *
  664. *=============================================================================================*/
  665. void WW3DAssetManager::Release_Render_Obj_Iterator(RenderObjIterator * it)
  666. {
  667. WWASSERT(it != NULL);
  668. delete it;
  669. }
  670. /***********************************************************************************************
  671. * WW3DAssetManager::Create_HAnim_Iterator -- Creates an HAnim Iterator *
  672. * *
  673. * Creates an iterator which can enumerate each of the named hierarchical animations *
  674. * which are currently loaded. *
  675. * *
  676. * INPUT: *
  677. * *
  678. * OUTPUT: *
  679. * *
  680. * WARNINGS: *
  681. * User must delete the iterator! *
  682. * *
  683. * HISTORY: *
  684. * 12/21/97 GTH : Created. *
  685. *=============================================================================================*/
  686. AssetIterator * WW3DAssetManager::Create_HAnim_Iterator(void)
  687. {
  688. return new HAnimIterator();
  689. }
  690. /***********************************************************************************************
  691. * WW3DAssetManager::Create_HTree_Iterator -- creates an htree iterator *
  692. * *
  693. * INPUT: *
  694. * *
  695. * OUTPUT: *
  696. * *
  697. * WARNINGS: *
  698. * *
  699. * HISTORY: *
  700. * 3/11/98 GTH : Created. *
  701. *=============================================================================================*/
  702. AssetIterator * WW3DAssetManager::Create_HTree_Iterator(void)
  703. {
  704. return new HTreeIterator();
  705. }
  706. /***********************************************************************************************
  707. * WW3DAssetManager::Create_Font3DData_Iterator -- Create a Font3DData iterator *
  708. * *
  709. * Creates an iterator which can enumerate each of the Font3DDatas currently loaded *
  710. * *
  711. * INPUT: *
  712. * *
  713. * OUTPUT: *
  714. * *
  715. * WARNINGS: *
  716. * User must delete the iterator! *
  717. * *
  718. * HISTORY: *
  719. * 1/6/98 GTH : Created. *
  720. *=============================================================================================*/
  721. AssetIterator * WW3DAssetManager::Create_Font3DData_Iterator(void)
  722. {
  723. return new Font3DDataIterator();
  724. }
  725. /***********************************************************************************************
  726. * WW3DAssetManager::Get_HAnim -- Returns a pointer to a names HAnim *
  727. * *
  728. * INPUT: *
  729. * *
  730. * OUTPUT: *
  731. * *
  732. * WARNINGS: *
  733. * The implementation has changed since its inception, the asset manager no longer owns the *
  734. * hanim's so they need to be released by the caller. *
  735. * *
  736. * HISTORY: *
  737. * 12/21/97 GTH : Created. *
  738. *=============================================================================================*/
  739. HAnimClass * WW3DAssetManager::Get_HAnim(const char * name)
  740. {
  741. WWPROFILE( "WW3DAssetManager::Get_HAnim" );
  742. // Try to find the hanim
  743. HAnimClass * anim = HAnimManager.Get_Anim(name);
  744. if (WW3D_Load_On_Demand && anim == NULL) { // If we didn't find it, try to load on demand
  745. if ( !HAnimManager.Is_Missing( name ) ) { // if this is NOT a known missing anim
  746. AssetStatusClass::Peek_Instance()->Report_Load_On_Demand_HAnim(name);
  747. char filename[ MAX_PATH ];
  748. char *animname = strchr( name, '.');
  749. if (animname != NULL) {
  750. sprintf( filename, "%s.w3d", animname+1);
  751. } else {
  752. WWDEBUG_SAY(( "Animation %s has no . in the name\n", name ));
  753. WWASSERT( 0 );
  754. return NULL;
  755. }
  756. // If we can't find it, try the parent directory
  757. if ( Load_3D_Assets( filename ) == false ) {
  758. StringClass new_filename = StringClass("..\\") + filename;
  759. Load_3D_Assets( new_filename );
  760. }
  761. anim = HAnimManager.Get_Anim(name); // Try agai
  762. if (anim == NULL) {
  763. HAnimManager.Register_Missing( name ); // This is now a KNOWN missing anim
  764. AssetStatusClass::Peek_Instance()->Report_Missing_HAnim(name);
  765. }
  766. }
  767. }
  768. return anim;
  769. }
  770. /***********************************************************************************************
  771. * WW3DAssetManager::Get_HTree -- Returns a pointer to the named HTree *
  772. * *
  773. * INPUT: *
  774. * *
  775. * OUTPUT: *
  776. * *
  777. * WARNINGS: *
  778. * DO NOT DELETE the HTree you get from this function, it is "owned" by the asset manager. *
  779. * *
  780. * HISTORY: *
  781. * 12/21/97 GTH : Created. *
  782. *=============================================================================================*/
  783. HTreeClass * WW3DAssetManager::Get_HTree(const char * name)
  784. {
  785. WWPROFILE( "WW3DAssetManager::Get_HTree" );
  786. // Try to find the htree
  787. HTreeClass * htree = HTreeManager.Get_Tree(name);
  788. if (WW3D_Load_On_Demand && htree == NULL) { // If we didn't find it, try to load on demand
  789. AssetStatusClass::Peek_Instance()->Report_Load_On_Demand_HTree(name);
  790. char filename[ MAX_PATH ];
  791. sprintf( filename, "%s.w3d", name);
  792. // If we can't find it, try the parent directory
  793. if ( Load_3D_Assets( filename ) == false ) {
  794. StringClass new_filename("..\\",true);
  795. new_filename+=filename;
  796. Load_3D_Assets( new_filename );
  797. }
  798. htree = HTreeManager.Get_Tree(name); // Try again
  799. if (htree == NULL) {
  800. AssetStatusClass::Peek_Instance()->Report_Missing_HTree(name);
  801. }
  802. }
  803. return htree;
  804. }
  805. /***********************************************************************************************
  806. * WW3DAssetManager::Get_Texture -- get a TextureClass from the specified file *
  807. * *
  808. * INPUT: *
  809. * *
  810. * OUTPUT: *
  811. * *
  812. * WARNINGS: *
  813. * *
  814. * HISTORY: *
  815. * 1/31/2001 NH : Created. *
  816. *=============================================================================================*/
  817. TextureClass * WW3DAssetManager::Get_Texture(
  818. const char * filename,
  819. TextureClass::MipCountType mip_level_count,
  820. WW3DFormat texture_format,
  821. bool allow_compression)
  822. {
  823. WWPROFILE( "WW3DAssetManager::Get_Texture 1" );
  824. /*
  825. ** We cannot currently mip-map bumpmaps
  826. */
  827. if (texture_format==WW3D_FORMAT_U8V8) {
  828. mip_level_count=TextureClass::MIP_LEVELS_1;
  829. }
  830. /*
  831. ** Bail if the user isn't really asking for anything
  832. */
  833. if ((filename == NULL) || (strlen(filename) == 0)) {
  834. return NULL;
  835. }
  836. StringClass lower_case_name(filename,true);
  837. _strlwr(lower_case_name.Peek_Buffer());
  838. /*
  839. ** See if the texture has already been loaded.
  840. */
  841. TextureClass* tex = TextureHash.Get(lower_case_name);
  842. if (tex && (tex->Is_Initialized() == true) && (texture_format!=WW3D_FORMAT_UNKNOWN)) {
  843. WWASSERT_PRINT(tex->Get_Texture_Format()==texture_format,("Texture %s has already been loaded with different format",filename));
  844. }
  845. /*
  846. ** Didn't have it so we have to create a new texture
  847. */
  848. if (!tex) {
  849. tex = NEW_REF(TextureClass,(lower_case_name, NULL, mip_level_count, texture_format, allow_compression));
  850. TextureHash.Insert(tex->Get_Texture_Name(),tex);
  851. }
  852. tex->Add_Ref();
  853. return tex;
  854. }
  855. /***********************************************************************************************
  856. * WW3DAssetManager::Release_All_Textures -- release all textures in the system *
  857. * *
  858. * INPUT: *
  859. * *
  860. * OUTPUT: *
  861. * *
  862. * WARNINGS: *
  863. * *
  864. * HISTORY: *
  865. * 3/10/98 GTH : Created. *
  866. *=============================================================================================*/
  867. void WW3DAssetManager::Release_All_Textures(void)
  868. {
  869. /*
  870. ** for each texture in the list, get it and release ref it
  871. */
  872. HashTemplateIterator<StringClass,TextureClass*> ite(TextureHash);
  873. for (ite.First();!ite.Is_Done();ite.Next()) {
  874. TextureClass * tex=ite.Peek_Value();
  875. // WWASSERT(tex->Num_Refs()==1); // If asset manager is releasing the texture,
  876. // nobody should be referencing to it anymore!
  877. tex->Release_Ref();
  878. }
  879. TextureHash.Remove_All();
  880. }
  881. /***********************************************************************************************
  882. * WW3DAssetManager::Release_Unused_Textures -- release all textures with refcount == 1 *
  883. * *
  884. * INPUT: *
  885. * *
  886. * OUTPUT: *
  887. * *
  888. * WARNINGS: *
  889. * *
  890. * HISTORY: *
  891. * 2/18/99 EHC : Created. *
  892. *=============================================================================================*/
  893. void WW3DAssetManager::Release_Unused_Textures(void)
  894. {
  895. /*
  896. ** for each texture in the list, get it, check it's refcount, and and release ref it if the
  897. ** refcount is one.
  898. */
  899. unsigned count=0;
  900. TextureClass* temp_textures[256];
  901. HashTemplateIterator<StringClass,TextureClass*> ite(TextureHash);
  902. for (ite.First();!ite.Is_Done();ite.Next()) {
  903. TextureClass* tex=ite.Peek_Value();
  904. if (tex->Num_Refs() == 1) {
  905. temp_textures[count++]=tex;
  906. if (count==256) {
  907. for (unsigned i=0;i<256;++i) {
  908. TextureHash.Remove(temp_textures[i]->Get_Texture_Name());
  909. temp_textures[i]->Release_Ref();
  910. }
  911. count=0;
  912. ite.First(); // iterator doesn't support modifying the hash table while iterating, so start from the
  913. // beginning.
  914. }
  915. }
  916. }
  917. for (unsigned i=0;i<count;++i) {
  918. TextureHash.Remove(temp_textures[i]->Get_Texture_Name());
  919. temp_textures[i]->Release_Ref();
  920. }
  921. }
  922. /***********************************************************************************************
  923. * WW3DAssetManager::Release_Texture -- release a specific texture from the asset manager *
  924. * *
  925. * INPUT: *
  926. * *
  927. * OUTPUT: *
  928. * *
  929. * WARNINGS: *
  930. * *
  931. * HISTORY: *
  932. * 2/18/99 EHC : Created. *
  933. *=============================================================================================*/
  934. void WW3DAssetManager::Release_Texture(TextureClass *tex)
  935. {
  936. /*
  937. ** Try to find the texture in the list, if found release it and remove it from the list.
  938. */
  939. TextureHash.Remove(tex->Get_Texture_Name());
  940. tex->Release_Ref();
  941. }
  942. void WW3DAssetManager::Log_All_Textures(void)
  943. {
  944. Log_Texture_Statistics();
  945. HashTemplateIterator<StringClass,TextureClass*> ite(TextureHash);
  946. // Log lightmaps -----------------------------------
  947. WWDEBUG_SAY((
  948. "Lightmap textures: %d\n\n"
  949. "size name\n"
  950. "--------------------------------------\n"
  951. ,
  952. TextureClass::_Get_Total_Lightmap_Texture_Count()));
  953. for (ite.First();!ite.Is_Done();ite.Next()) {
  954. TextureClass* t=ite.Peek_Value();
  955. if (!t->Is_Lightmap()) continue;
  956. StringClass tmp(true);
  957. unsigned bytes=t->Get_Texture_Memory_Usage();
  958. if (!t->Is_Initialized()) {
  959. tmp+="*";
  960. }
  961. else {
  962. tmp+=" ";
  963. }
  964. WWDEBUG_SAY(("%4.4dkb %s%s\n",bytes/1024,tmp,t->Get_Texture_Name()));
  965. }
  966. // Log procedural textures -------------------------------
  967. WWDEBUG_SAY((
  968. "Procedural textures: %d\n\n"
  969. "size name\n"
  970. "--------------------------------------\n"
  971. ,
  972. TextureClass::_Get_Total_Procedural_Texture_Count()));
  973. for (ite.First();!ite.Is_Done();ite.Next()) {
  974. TextureClass* t=ite.Peek_Value();
  975. if (!t->Is_Procedural()) continue;
  976. StringClass tmp(true);
  977. unsigned bytes=t->Get_Texture_Memory_Usage();
  978. if (!t->Is_Initialized()) {
  979. tmp+="*";
  980. }
  981. else {
  982. tmp+=" ";
  983. }
  984. WWDEBUG_SAY(("%4.4dkb %s%s\n",bytes/1024,tmp,t->Get_Texture_Name()));
  985. }
  986. // Log "ordinary" textures -------------------------------
  987. WWDEBUG_SAY((
  988. "Ordinary textures: %d\n\n"
  989. "size name\n"
  990. "--------------------------------------\n"
  991. ,
  992. TextureClass::_Get_Total_Texture_Count()-TextureClass::_Get_Total_Lightmap_Texture_Count()-TextureClass::_Get_Total_Procedural_Texture_Count()));
  993. for (ite.First();!ite.Is_Done();ite.Next()) {
  994. TextureClass* t=ite.Peek_Value();
  995. if (t->Is_Procedural()) continue;
  996. if (t->Is_Lightmap()) continue;
  997. StringClass tmp(true);
  998. unsigned bytes=t->Get_Texture_Memory_Usage();
  999. if (!t->Is_Initialized()) {
  1000. tmp+="*";
  1001. }
  1002. else {
  1003. tmp+=" ";
  1004. }
  1005. WWDEBUG_SAY(("%4.4dkb %s%s\n",bytes/1024,tmp,t->Get_Texture_Name()));
  1006. }
  1007. }
  1008. /***********************************************************************************************
  1009. * WW3DAssetManager::Get_Font3DInstance -- Creates a pointer to a Font3DInstance *
  1010. * *
  1011. * INPUT: *
  1012. * *
  1013. * OUTPUT: *
  1014. * *
  1015. * WARNINGS: *
  1016. * *
  1017. * HISTORY: *
  1018. * 1/6/98 GTH : Created. *
  1019. *=============================================================================================*/
  1020. Font3DInstanceClass * WW3DAssetManager::Get_Font3DInstance( const char *name )
  1021. {
  1022. WWPROFILE( "WW3DAssetManager::Get_Font3DInstance" );
  1023. return NEW_REF( Font3DInstanceClass, ( name ));
  1024. }
  1025. /***********************************************************************************************
  1026. * WW3DAssetManager::Get_Font3DData -- Gets a pointer to a loaded Font3DData or creates it *
  1027. * *
  1028. * INPUT: *
  1029. * *
  1030. * OUTPUT: *
  1031. * *
  1032. * WARNINGS: *
  1033. * *
  1034. * HISTORY: *
  1035. * 1/6/98 GTH : Created. *
  1036. *=============================================================================================*/
  1037. Font3DDataClass * WW3DAssetManager::Get_Font3DData( const char *name )
  1038. {
  1039. WWPROFILE( "WW3DAssetManager::Get_Font3DData" );
  1040. // loop through and see if the Font3D we are looking for has already been
  1041. // allocated and thus we can just return it.
  1042. for ( SLNode<Font3DDataClass> *node = Font3DDatas.Head(); node; node = node->Next()) {
  1043. if (!stricmp(name, node->Data()->Name)) {
  1044. node->Data()->Add_Ref();
  1045. return node->Data();
  1046. }
  1047. }
  1048. // if one hasn't been found and a font name has been specified then create it
  1049. Font3DDataClass * font = NEW_REF( Font3DDataClass, ( name ));
  1050. // add it to the asset manager
  1051. Add_Font3DData( font);
  1052. // return it
  1053. return font;
  1054. }
  1055. /***********************************************************************************************
  1056. * WW3DAssetManager::Add_Font3DData -- Add a Font3DData to the list *
  1057. * *
  1058. * INPUT: *
  1059. * *
  1060. * OUTPUT: *
  1061. * *
  1062. * WARNINGS: *
  1063. * *
  1064. * HISTORY: *
  1065. * 1/6/98 GTH : Created. *
  1066. *=============================================================================================*/
  1067. void WW3DAssetManager::Add_Font3DData(Font3DDataClass * font)
  1068. {
  1069. font->Add_Ref();
  1070. Font3DDatas.Add_Head(font);
  1071. }
  1072. void WW3DAssetManager::Remove_Font3DData(Font3DDataClass * font)
  1073. {
  1074. font->Release_Ref();
  1075. Font3DDatas.Remove(font);
  1076. }
  1077. /***********************************************************************************************
  1078. * WW3DAssetManager::Release_All_Font3DDatas -- Release all Font3DDatas from the asset manager *
  1079. * *
  1080. * INPUT: *
  1081. * *
  1082. * OUTPUT: *
  1083. * *
  1084. * WARNINGS: *
  1085. * *
  1086. * HISTORY: *
  1087. * 1/6/98 GTH : Created. *
  1088. *=============================================================================================*/
  1089. void WW3DAssetManager::Release_All_Font3DDatas( void )
  1090. {
  1091. // for each mat in the list, get it and release ref it
  1092. Font3DDataClass *head;
  1093. while ((head = Font3DDatas.Remove_Head()) != NULL ) {
  1094. head->Release_Ref();
  1095. }
  1096. }
  1097. /***********************************************************************************************
  1098. * WW3DAssetManager::Release_Unused_Font3DDatas -- Release all Font3DDatas with refcount == 1 *
  1099. * *
  1100. * INPUT: *
  1101. * *
  1102. * OUTPUT: *
  1103. * *
  1104. * WARNINGS: *
  1105. * *
  1106. * HISTORY: *
  1107. * 1/6/98 GTH : Created. *
  1108. *=============================================================================================*/
  1109. void WW3DAssetManager::Release_Unused_Font3DDatas( void )
  1110. {
  1111. /*
  1112. ** for each font data in the list, get it, check it's refcount, and and release ref it if the
  1113. ** refcount is one.
  1114. */
  1115. SLNode<Font3DDataClass> *node, * next;
  1116. for ( node = Font3DDatas.Head(); node; node = next) {
  1117. next = node->Next();
  1118. Font3DDataClass *font = node->Data();
  1119. if (font->Num_Refs() == 1) {
  1120. Font3DDatas.Remove(font);
  1121. font->Release_Ref();
  1122. }
  1123. }
  1124. }
  1125. /***********************************************************************************************
  1126. * WW3DAssetManager::Get_FontChars -- Gets a pointer to a loaded FontChars or creates it *
  1127. * *
  1128. * INPUT: *
  1129. * *
  1130. * OUTPUT: *
  1131. * *
  1132. * WARNINGS: *
  1133. * *
  1134. * HISTORY: *
  1135. * 6/1/01 BMG : Created. *
  1136. *=============================================================================================*/
  1137. FontCharsClass * WW3DAssetManager::Get_FontChars( const char * name, int point_size, bool is_bold )
  1138. {
  1139. WWPROFILE( "WW3DAssetManager::Get_FontChars" );
  1140. // loop through and see if we already have the font chars and we can just return it.
  1141. for ( int i = 0; i < FontCharsList.Count(); i++ ) {
  1142. if ( FontCharsList[i]->Is_Font( name, point_size, is_bold ) ) {
  1143. FontCharsList[i]->Add_Ref();
  1144. return FontCharsList[i];
  1145. }
  1146. }
  1147. // If one hasn't been found, create it
  1148. FontCharsClass * font = NEW_REF( FontCharsClass, () );
  1149. font->Initialize_GDI_Font( name, point_size, is_bold );
  1150. font->Add_Ref();
  1151. FontCharsList.Add( font ); // add it to the list
  1152. return font; // return it
  1153. }
  1154. /***********************************************************************************************
  1155. * WW3DAssetManager::Release_All_FontChars -- Release all FontChars from the asset manager *
  1156. * *
  1157. * INPUT: *
  1158. * *
  1159. * OUTPUT: *
  1160. * *
  1161. * WARNINGS: *
  1162. * *
  1163. * HISTORY: *
  1164. * 6/1/01 BMG : Created. *
  1165. *=============================================================================================*/
  1166. void WW3DAssetManager::Release_All_FontChars( void )
  1167. {
  1168. // for each fontchars in the list, get it and release ref it
  1169. while ( FontCharsList.Count() ) {
  1170. FontCharsList[0]->Release_Ref();
  1171. FontCharsList.Delete( 0 );
  1172. }
  1173. }
  1174. /***********************************************************************************************
  1175. * WW3DAssetManager::Register_Prototype_Loader -- add a new loader to the system *
  1176. * *
  1177. * The library will automatically install loaders for the "built-in" render object *
  1178. * types. This function exists so that the user can design App-specific render objects, *
  1179. * define a chunk format for them, and have the asset manager load them in like everything *
  1180. * else. *
  1181. * *
  1182. * INPUT: *
  1183. * loader - pointer to a global or static instance of your loader type. *
  1184. * *
  1185. * OUTPUT: *
  1186. * *
  1187. * WARNINGS: *
  1188. * *
  1189. * HISTORY: *
  1190. * 7/28/98 GTH : Created. *
  1191. *=============================================================================================*/
  1192. void WW3DAssetManager::Register_Prototype_Loader(PrototypeLoaderClass * loader)
  1193. {
  1194. WWASSERT(loader != NULL);
  1195. PrototypeLoaders.Add(loader);
  1196. }
  1197. /***********************************************************************************************
  1198. * WW3DAssetManager::Find_Prototype_Loader -- find the loader that handles this chunk type *
  1199. * *
  1200. * INPUT: *
  1201. * chunk_id - chunk type that the loader needs to handle *
  1202. * *
  1203. * OUTPUT: *
  1204. * pointer to the appropriate loader or NULL if one wasn't found *
  1205. * *
  1206. * WARNINGS: *
  1207. * *
  1208. * HISTORY: *
  1209. * 7/28/98 GTH : Created. *
  1210. *=============================================================================================*/
  1211. PrototypeLoaderClass * WW3DAssetManager::Find_Prototype_Loader(int chunk_id)
  1212. {
  1213. for (int i=0; i<PrototypeLoaders.Count(); i++) {
  1214. PrototypeLoaderClass * loader = PrototypeLoaders[i];
  1215. if (loader && loader->Chunk_Type() == chunk_id) {
  1216. return loader;
  1217. }
  1218. }
  1219. return NULL;
  1220. }
  1221. /***********************************************************************************************
  1222. * WW3DAssetManager::Add_Prototype -- adds the prototype to the hash table *
  1223. * *
  1224. * INPUT: *
  1225. * *
  1226. * OUTPUT: *
  1227. * *
  1228. * WARNINGS: *
  1229. * *
  1230. * HISTORY: *
  1231. * 7/29/98 GTH : Created. *
  1232. * 12/8/98 GTH : Renamed to simply Add_Prototype *
  1233. * 2/19/99 EHC : Now adds the prototype to the prototype list *
  1234. *=============================================================================================*/
  1235. void WW3DAssetManager::Add_Prototype(PrototypeClass * newproto)
  1236. {
  1237. WWASSERT(newproto != NULL);
  1238. int hash = CRC_Stringi(newproto->Get_Name()) & PROTOTYPE_HASH_MASK;
  1239. newproto->NextHash = PrototypeHashTable[hash];
  1240. PrototypeHashTable[hash] = newproto;
  1241. Prototypes.Add(newproto);
  1242. }
  1243. /***********************************************************************************************
  1244. * WW3DAssetManager::Remove_Prototype -- Removes all references to the protype. *
  1245. * *
  1246. * INPUT: *
  1247. * *
  1248. * OUTPUT: *
  1249. * *
  1250. * WARNINGS: *
  1251. * *
  1252. * HISTORY: *
  1253. * 02/4/99 PDS : Created. *
  1254. *=============================================================================================*/
  1255. void WW3DAssetManager::Remove_Prototype(PrototypeClass *proto)
  1256. {
  1257. WWASSERT(proto != NULL);
  1258. if (proto != NULL) {
  1259. //
  1260. // Find the prototype in the hash table.
  1261. //
  1262. const char *pname = proto->Get_Name ();
  1263. bool bfound = false;
  1264. PrototypeClass *prev = NULL;
  1265. int hash = CRC_Stringi(pname) & PROTOTYPE_HASH_MASK;
  1266. for (PrototypeClass *test = PrototypeHashTable[hash];
  1267. (test != NULL) && (bfound == false);
  1268. test = test->NextHash) {
  1269. // Is this the prototype?
  1270. if (::stricmp (test->Get_Name(), pname) == 0) {
  1271. // Remove this prototype from the linked list for this hash index.
  1272. if (prev == NULL) {
  1273. PrototypeHashTable[hash] = test->NextHash;
  1274. } else {
  1275. prev->NextHash = test->NextHash;
  1276. }
  1277. // Success!
  1278. bfound = true;
  1279. }
  1280. // Remember who our previous entry is
  1281. prev = test;
  1282. }
  1283. // Now remove this from our vector-array of prototypes
  1284. Prototypes.Delete (proto);
  1285. }
  1286. return;
  1287. }
  1288. /***********************************************************************************************
  1289. * WW3DAssetManager::Remove_Prototype -- Removes all references to the protype. *
  1290. * *
  1291. * INPUT: *
  1292. * *
  1293. * OUTPUT: *
  1294. * *
  1295. * WARNINGS: *
  1296. * *
  1297. * HISTORY: *
  1298. * 02/4/99 PDS : Created. *
  1299. *=============================================================================================*/
  1300. void WW3DAssetManager::Remove_Prototype(const char *name)
  1301. {
  1302. WWASSERT(name != NULL);
  1303. if (name != NULL) {
  1304. // Lookup the prototype by name
  1305. PrototypeClass *proto = Find_Prototype (name);
  1306. if (proto != NULL) {
  1307. // Remove the prototype from our lists, and free its memory
  1308. Remove_Prototype (proto);
  1309. delete proto;
  1310. }
  1311. }
  1312. return;
  1313. }
  1314. /***********************************************************************************************
  1315. * WW3DAssetManager::Find_Prototype -- searches the hash table for the prototype *
  1316. * *
  1317. * INPUT: *
  1318. * *
  1319. * OUTPUT: *
  1320. * *
  1321. * WARNINGS: *
  1322. * *
  1323. * HISTORY: *
  1324. * 7/29/98 GTH : Created. *
  1325. * 12/8/98 GTH : Renamed to simply Find_Prototype *
  1326. *=============================================================================================*/
  1327. PrototypeClass * WW3DAssetManager::Find_Prototype(const char * name)
  1328. {
  1329. // Special case Null render object. So we always have it...
  1330. if (stricmp(name,"NULL") == 0) {
  1331. return &(_NullPrototype);
  1332. }
  1333. // Find the prototype
  1334. int hash = CRC_Stringi(name) & PROTOTYPE_HASH_MASK;
  1335. PrototypeClass * test = PrototypeHashTable[hash];
  1336. while (test != NULL) {
  1337. if (stricmp(test->Get_Name(),name) == 0) {
  1338. return test;
  1339. }
  1340. test = test->NextHash;
  1341. }
  1342. return NULL;
  1343. }
  1344. /*
  1345. ** Iterator Implementations.
  1346. ** =====================================================================
  1347. ** If the user derives a custom asset manager, you will have
  1348. ** to implement iterators which can walk through your datastructures.
  1349. */
  1350. bool RObjIterator::Is_Done(void)
  1351. {
  1352. return !(Index < WW3DAssetManager::Get_Instance()->Prototypes.Count());
  1353. }
  1354. const char * RObjIterator::Current_Item_Name(void)
  1355. {
  1356. if (Index < WW3DAssetManager::Get_Instance()->Prototypes.Count()) {
  1357. return WW3DAssetManager::Get_Instance()->Prototypes[Index]->Get_Name();
  1358. } else {
  1359. return NULL;
  1360. }
  1361. }
  1362. int RObjIterator::Current_Item_Class_ID(void)
  1363. {
  1364. if (Index < WW3DAssetManager::Get_Instance()->Prototypes.Count()) {
  1365. return WW3DAssetManager::Get_Instance()->Prototypes[Index]->Get_Class_ID();
  1366. } else {
  1367. return -1;
  1368. }
  1369. }
  1370. bool HTreeIterator::Is_Done(void)
  1371. {
  1372. return !(Index < WW3DAssetManager::Get_Instance()->HTreeManager.Num_Trees());
  1373. }
  1374. const char * HTreeIterator::Current_Item_Name(void)
  1375. {
  1376. return WW3DAssetManager::Get_Instance()->HTreeManager.Get_Tree(Index)->Get_Name();
  1377. }