assetmgr.cpp 81 KB

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