assetmgr.cpp 82 KB

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