1579 lines
74 KiB
C++
1579 lines
74 KiB
C++
/*
|
|
** Command & Conquer Renegade(tm)
|
|
** Copyright 2025 Electronic Arts Inc.
|
|
**
|
|
** This program is free software: you can redistribute it and/or modify
|
|
** it under the terms of the GNU General Public License as published by
|
|
** the Free Software Foundation, either version 3 of the License, or
|
|
** (at your option) any later version.
|
|
**
|
|
** This program is distributed in the hope that it will be useful,
|
|
** but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
** GNU General Public License for more details.
|
|
**
|
|
** You should have received a copy of the GNU General Public License
|
|
** along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
*/
|
|
|
|
/* $Header: /Commando/Code/ww3d2/assetmgr.cpp 43 11/01/01 1:11a Jani_p $ */
|
|
/***********************************************************************************************
|
|
*** Confidential - Westwood Studios ***
|
|
***********************************************************************************************
|
|
* *
|
|
* Project Name : Commando *
|
|
* *
|
|
* $Archive:: /Commando/Code/ww3d2/assetmgr.cpp $*
|
|
* *
|
|
* Author:: Greg_h *
|
|
* *
|
|
* $Modtime:: 10/31/01 8:00p $*
|
|
* *
|
|
* $Revision:: 43 $*
|
|
* *
|
|
*---------------------------------------------------------------------------------------------*
|
|
* Functions: *
|
|
* WW3DAssetManager::WW3DAssetManager -- Constructor *
|
|
* WW3DAssetManager::~WW3DAssetManager -- Destructor *
|
|
* WW3DAssetManager::Free -- free all memory (un-needed?) *
|
|
* WW3DAssetManager::Free_Assets -- Release all loaded assets *
|
|
* WW3DAssetManager::Load_3D_Assets -- Load 3D assets from a .W3D file *
|
|
* WW3DAssetManager::Load_Prototype -- loads a prototype from a W3D chunk *
|
|
* WW3DAssetManager::Create_Render_Obj -- Create a render object for the user *
|
|
* WW3DAssetManager::Render_Obj_Exists -- Check whether a render object with the given name *
|
|
* WW3DAssetManager::Create_Render_Obj_Iterator -- Create an iterator which can enumerate al *
|
|
* WW3DAssetManager::Release_Render_Obj_Iterator -- release a render object iterator *
|
|
* WW3DAssetManager::Create_HAnim_Iterator -- Creates an HAnim Iterator *
|
|
* WW3DAssetManager::Create_HTree_Iterator -- creates an htree iterator *
|
|
* WW3DAssetManager::Create_Material_Iterator -- Create a material iterator *
|
|
* WW3DAssetManager::Create_Font3DData_Iterator -- Create a Font3DData iterator *
|
|
* WW3DAssetManager::Get_HAnim -- Returns a pointer to a names HAnim *
|
|
* WW3DAssetManager::Get_HTree -- Returns a pointer to the named HTree *
|
|
* WW3DAssetManager::Get_Material -- Gets a pointer to a loaded material or creates it *
|
|
* WW3DAssetManager::Get_Material -- Gets a pointer to a loaded material or creates the mate *
|
|
* WW3DAssetManager::Get_Material -- Gets a pointer to a loaded material or creates it *
|
|
* WW3DAssetManager::Get_Font3DInstance -- Creates a pointer to a Font3DInstance *
|
|
* WW3DAssetManager::Get_Font3DData -- Gets a pointer to a loaded Font3DData or creates it *
|
|
* WW3DAssetManager::Release_Material -- Release a material *
|
|
* WW3DAssetManager::Release_Font3DData -- Release a Font3DData *
|
|
* WW3DAssetManager::Add_Material -- Add a material to the list *
|
|
* WW3DAssetManager::Add_Font3DData -- Add a Font3DData to the list *
|
|
* WW3DAssetManager::Get_Texture -- get a TextureClass for the specified targa *
|
|
* WW3DAssetManager::Release_All_Textures -- release all textures in the system *
|
|
* WW3DAssetManager::Register_Prototype_Loader -- add a new loader to the system *
|
|
* WW3DAssetManager::Find_Prototype_Loader -- find the loader that handles this chunk type *
|
|
* WW3DAssetManager::Add_Prototype -- adds the prototype to the hash table *
|
|
* WW3DAssetManager::Find_Prototype -- searches the hash table for the prototype *
|
|
* WW3DAssetManager::Open_Texture_File_Cache -- Turn on the texture cache system. *
|
|
* WW3DAssetManager::Close_Texture_File_Cache -- Turn off the texture cache system. *
|
|
* CachedTextureFileClass::getMipmapData -- get data for texture - check to see if in cache. *
|
|
* CachedTextureFileClass::getMipmapLevelPartial -- not yet implemented *
|
|
* CachedTextureFileClass::setupDefaultValues -- loads texture in to get default data. *
|
|
* WW3DAssetManager::Get_Streaming_Texture -- Gets a streaming texture. *
|
|
* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
|
|
|
|
#include "assetmgr.h"
|
|
#include <assert.h>
|
|
|
|
#include "bittype.h"
|
|
#include "chunkio.h"
|
|
#include "realcrc.h"
|
|
|
|
#include "wwdebug.h"
|
|
|
|
#include "htreemgr.h"
|
|
#include "hanimmgr.h"
|
|
#include "texture.h"
|
|
#include "font3d.h"
|
|
#include "render2dsentence.h" // for FontCharsClass
|
|
#include "proto.h"
|
|
#include "hanim.h"
|
|
#include "hcanim.h"
|
|
#include "htree.h"
|
|
#include "collect.h"
|
|
#include "ww3d.h"
|
|
#include "ffactory.h"
|
|
#include "boxrobj.h"
|
|
#include "nullrobj.h"
|
|
#include "distlod.h"
|
|
#include "hlod.h"
|
|
#include "agg_def.h"
|
|
#include "texfcach.h"
|
|
#include "wwstring.h"
|
|
#include "wwmemlog.h"
|
|
#include "dazzle.h"
|
|
#include "dx8wrapper.h"
|
|
#include "metalmap.h"
|
|
#include <ini.h>
|
|
#include <windows.h>
|
|
#include <stdio.h>
|
|
#include <D3dx8core.h>
|
|
#include "texture.h"
|
|
#include "wwprofile.h"
|
|
#include "assetstatus.h"
|
|
|
|
/*
|
|
** Static member variable which keeps track of the single instanced asset manager
|
|
*/
|
|
WW3DAssetManager * WW3DAssetManager::TheInstance = NULL;
|
|
|
|
/*
|
|
** Static instance of the Null prototype. This render object is special cased
|
|
** to always be available...
|
|
*/
|
|
static NullPrototypeClass _NullPrototype;
|
|
|
|
/*
|
|
** Iterator for the Render Objects in the asset manager
|
|
*/
|
|
class RObjIterator : public RenderObjIterator
|
|
{
|
|
public:
|
|
virtual bool Is_Done(void);
|
|
virtual const char * Current_Item_Name(void);
|
|
virtual int Current_Item_Class_ID(void);
|
|
protected:
|
|
friend class WW3DAssetManager;
|
|
};
|
|
|
|
|
|
/*
|
|
** Iterators for the other types of 3D assets:
|
|
** HAnims, HTrees, Textures, Fonts
|
|
*/
|
|
class HAnimIterator : public AssetIterator
|
|
{
|
|
public:
|
|
HAnimIterator(void) : Iterator( WW3DAssetManager::Get_Instance()->HAnimManager ) { };
|
|
|
|
virtual void First(void) { Iterator.First(); }
|
|
virtual void Next(void) { Iterator.Next(); }
|
|
virtual bool Is_Done(void) { return Iterator.Is_Done(); }
|
|
virtual const char * Current_Item_Name(void) { return Iterator.Get_Current_Anim()->Get_Name(); }
|
|
|
|
protected:
|
|
HAnimManagerIterator Iterator;
|
|
friend class WW3DAssetManager;
|
|
};
|
|
|
|
class HTreeIterator : public AssetIterator
|
|
{
|
|
public:
|
|
virtual bool Is_Done(void);
|
|
virtual const char * Current_Item_Name(void);
|
|
protected:
|
|
friend class WW3DAssetManager;
|
|
};
|
|
|
|
class Font3DDataIterator : public AssetIterator
|
|
{
|
|
public:
|
|
|
|
virtual void First(void) { Node = WW3DAssetManager::Get_Instance()->Font3DDatas.Head(); }
|
|
virtual void Next(void) { Node = Node->Next(); }
|
|
virtual bool Is_Done(void) { return Node==NULL; }
|
|
virtual const char * Current_Item_Name(void) { return Node->Data()->Name; }
|
|
|
|
protected:
|
|
|
|
Font3DDataIterator(void) { Node = WW3DAssetManager::Get_Instance()->Font3DDatas.Head(); }
|
|
SLNode<Font3DDataClass> * Node;
|
|
friend class WW3DAssetManager;
|
|
};
|
|
|
|
/***********************************************************************************************
|
|
* WW3DAssetManager::WW3DAssetManager -- Constructor *
|
|
* *
|
|
* INPUT: *
|
|
* *
|
|
* OUTPUT: *
|
|
* *
|
|
* WARNINGS: *
|
|
* *
|
|
* HISTORY: *
|
|
* 12/21/97 GTH : Created. *
|
|
* 05/10/1999 SKB : Add TextureCache *
|
|
*=============================================================================================*/
|
|
WW3DAssetManager::WW3DAssetManager(void) :
|
|
PrototypeLoaders (PROTOLOADERS_VECTOR_SIZE),
|
|
Prototypes (PROTOTYPES_VECTOR_SIZE),
|
|
|
|
#ifdef WW3D_DX8
|
|
TextureCache (NULL),
|
|
#endif //WW3D_DX8
|
|
|
|
WW3D_Load_On_Demand (false),
|
|
Activate_Fog_On_Load (false),
|
|
MetalManager(0)
|
|
{
|
|
assert(TheInstance == NULL);
|
|
TheInstance = this;
|
|
|
|
// set the growth rates
|
|
PrototypeLoaders.Set_Growth_Step(PROTOLOADERS_GROWTH_RATE);
|
|
Prototypes.Set_Growth_Step(PROTOTYPES_GROWTH_RATE);
|
|
|
|
// install the default loaders
|
|
Register_Prototype_Loader(&_MeshLoader);
|
|
Register_Prototype_Loader(&_HModelLoader);
|
|
Register_Prototype_Loader(&_CollectionLoader);
|
|
Register_Prototype_Loader(&_BoxLoader);
|
|
Register_Prototype_Loader(&_HLodLoader);
|
|
Register_Prototype_Loader(&_DistLODLoader);
|
|
Register_Prototype_Loader(&_AggregateLoader);
|
|
Register_Prototype_Loader(&_NullLoader);
|
|
Register_Prototype_Loader(&_DazzleLoader);
|
|
|
|
// allocate the hash table and clear it.
|
|
PrototypeHashTable = new PrototypeClass * [PROTOTYPE_HASH_TABLE_SIZE];
|
|
memset(PrototypeHashTable,0,sizeof(PrototypeClass *) * PROTOTYPE_HASH_TABLE_SIZE);
|
|
}
|
|
|
|
|
|
/***********************************************************************************************
|
|
* WW3DAssetManager::~WW3DAssetManager -- Destructor *
|
|
* *
|
|
* INPUT: *
|
|
* *
|
|
* OUTPUT: *
|
|
* *
|
|
* WARNINGS: *
|
|
* *
|
|
* HISTORY: *
|
|
* 12/21/97 GTH : Created. *
|
|
*=============================================================================================*/
|
|
WW3DAssetManager::~WW3DAssetManager(void)
|
|
{
|
|
if (MetalManager) delete MetalManager;
|
|
Free();
|
|
TheInstance = NULL;
|
|
|
|
// If we need to, free the hash table
|
|
if (PrototypeHashTable != NULL) {
|
|
delete [] PrototypeHashTable;
|
|
PrototypeHashTable = NULL;
|
|
}
|
|
#ifdef WW3D_DX8
|
|
Close_Texture_File_Cache();
|
|
#endif //WW3D_DX8
|
|
}
|
|
|
|
static void Create_Number_String(StringClass& number, unsigned value)
|
|
{
|
|
unsigned miljoonat=value/(1024*1028);
|
|
unsigned tuhannet=(value/1024)%1024;
|
|
unsigned ykkoset=value%1024;
|
|
if (miljoonat) {
|
|
number.Format("%d %3.3d %3.3d",miljoonat,tuhannet,ykkoset);
|
|
}
|
|
else if (tuhannet) {
|
|
number.Format("%d %3.3d",tuhannet,ykkoset);
|
|
}
|
|
else {
|
|
number.Format("%d",ykkoset);
|
|
}
|
|
}
|
|
|
|
void WW3DAssetManager::Load_Procedural_Textures()
|
|
{
|
|
int i,count;
|
|
if (!MetalManager)
|
|
{
|
|
INIClass ini;
|
|
ini.Load("metals.ini");
|
|
MetalManager=new MetalMapManagerClass(ini);
|
|
}
|
|
|
|
count=MetalManager->Metal_Map_Count();
|
|
for (i=0; i<count; i++)
|
|
{
|
|
TextureClass *tex=MetalManager->Get_Metal_Map(i);
|
|
TextureHash.Insert(tex->Get_Texture_Name(),tex);
|
|
}
|
|
}
|
|
|
|
static void Log_Textures(bool inited,unsigned& total_count, unsigned& total_mem)
|
|
{
|
|
HashTemplateIterator<StringClass,TextureClass*> ite(WW3DAssetManager::Get_Instance()->Texture_Hash());
|
|
for (ite.First();!ite.Is_Done();ite.Next()) {
|
|
TextureClass * tex=ite.Peek_Value();
|
|
if (tex->Is_Initialized()!=inited) continue;
|
|
|
|
D3DSURFACE_DESC desc;
|
|
IDirect3DTexture8* d3d_texture=tex->Peek_DX8_Texture();
|
|
if (!d3d_texture) continue;
|
|
DX8_ErrorCode(d3d_texture->GetLevelDesc(0,&desc));
|
|
|
|
StringClass tex_format="Unknown";
|
|
switch (desc.Format) {
|
|
case D3DFMT_A8R8G8B8: tex_format="D3DFMT_A8R8G8B8"; break;
|
|
case D3DFMT_R8G8B8: tex_format="D3DFMT_R8G8B8"; break;
|
|
case D3DFMT_A4R4G4B4: tex_format="D3DFMT_A4R4G4B4"; break;
|
|
case D3DFMT_A1R5G5B5: tex_format="D3DFMT_A1R5G5B5"; break;
|
|
case D3DFMT_R5G6B5: tex_format="D3DFMT_R5G6B5"; break;
|
|
case D3DFMT_L8: tex_format="D3DFMT_L8"; break;
|
|
case D3DFMT_A8: tex_format="D3DFMT_A8"; break;
|
|
case D3DFMT_P8: tex_format="D3DFMT_P8"; break;
|
|
case D3DFMT_X8R8G8B8: tex_format="D3DFMT_X8R8G8B8"; break;
|
|
case D3DFMT_X1R5G5B5: tex_format="D3DFMT_X1R5G5B5"; break;
|
|
case D3DFMT_R3G3B2: tex_format="D3DFMT_R3G3B2"; break;
|
|
case D3DFMT_A8R3G3B2: tex_format="D3DFMT_A8R3G3B2"; break;
|
|
case D3DFMT_X4R4G4B4: tex_format="D3DFMT_X4R4G4B4"; break;
|
|
case D3DFMT_A8P8: tex_format="D3DFMT_A8P8"; break;
|
|
case D3DFMT_A8L8: tex_format="D3DFMT_A8L8"; break;
|
|
case D3DFMT_A4L4: tex_format="D3DFMT_A4L4"; break;
|
|
case D3DFMT_V8U8: tex_format="D3DFMT_V8U8"; break;
|
|
case D3DFMT_L6V5U5: tex_format="D3DFMT_L6V5U5"; break;
|
|
case D3DFMT_X8L8V8U8: tex_format="D3DFMT_X8L8V8U8"; break;
|
|
case D3DFMT_Q8W8V8U8: tex_format="D3DFMT_Q8W8V8U8"; break;
|
|
case D3DFMT_V16U16: tex_format="D3DFMT_V16U16"; break;
|
|
case D3DFMT_W11V11U10: tex_format="D3DFMT_W11V11U10"; break;
|
|
case D3DFMT_UYVY: tex_format="D3DFMT_UYVY"; break;
|
|
case D3DFMT_YUY2: tex_format="D3DFMT_YUY2"; break;
|
|
case D3DFMT_DXT1: tex_format="D3DFMT_DXT1"; break;
|
|
case D3DFMT_DXT2: tex_format="D3DFMT_DXT2"; break;
|
|
case D3DFMT_DXT3: tex_format="D3DFMT_DXT3"; break;
|
|
case D3DFMT_DXT4: tex_format="D3DFMT_DXT4"; break;
|
|
case D3DFMT_DXT5: tex_format="D3DFMT_DXT5"; break;
|
|
case D3DFMT_D16_LOCKABLE: tex_format="D3DFMT_D16_LOCKABLE"; break;
|
|
case D3DFMT_D32: tex_format="D3DFMT_D32"; break;
|
|
case D3DFMT_D15S1: tex_format="D3DFMT_D15S1"; break;
|
|
case D3DFMT_D24S8: tex_format="D3DFMT_D24S8"; break;
|
|
case D3DFMT_D16: tex_format="D3DFMT_D16"; break;
|
|
case D3DFMT_D24X8: tex_format="D3DFMT_D24X8"; break;
|
|
case D3DFMT_D24X4S4: tex_format="D3DFMT_D24X4S4"; break;
|
|
default: break;
|
|
}
|
|
|
|
unsigned texmem=tex->Get_Texture_Memory_Usage();
|
|
total_mem+=texmem;
|
|
total_count++;
|
|
StringClass number;
|
|
Create_Number_String(number,texmem);
|
|
|
|
WWDEBUG_SAY(("%32s %4d * %4d (%15s), init %d, size: %14s bytes, refs: %d\n",
|
|
tex->Get_Texture_Name(),
|
|
desc.Width,
|
|
desc.Height,
|
|
tex_format,
|
|
tex->Is_Initialized(),
|
|
number,
|
|
tex->Num_Refs()));
|
|
|
|
}
|
|
}
|
|
|
|
void WW3DAssetManager::Log_Texture_Statistics()
|
|
{
|
|
unsigned total_initialized_tex_mem=0;
|
|
unsigned total_uninitialized_tex_mem=0;
|
|
unsigned total_initialized_count=0;
|
|
unsigned total_uninitialized_count=0;
|
|
StringClass number;
|
|
|
|
WWDEBUG_SAY(("\nInitialized textures ------------------------------------------\n\n"));
|
|
Log_Textures(true,total_initialized_count,total_initialized_tex_mem);
|
|
|
|
Create_Number_String(number,total_initialized_tex_mem);
|
|
WWDEBUG_SAY(("\n%d initialized textures, totalling %14s bytes\n\n",
|
|
total_initialized_count,
|
|
number));
|
|
|
|
WWDEBUG_SAY(("\nUn-initialized textures ---------------------------------------\n\n"));
|
|
Log_Textures(false,total_uninitialized_count,total_uninitialized_tex_mem);
|
|
|
|
Create_Number_String(number,total_uninitialized_tex_mem);
|
|
WWDEBUG_SAY(("\n%d un-initialized textures, totalling, totalling %14s bytes\n\n",
|
|
total_uninitialized_count,
|
|
number));
|
|
/*
|
|
RenderObjIterator * rite=WW3DAssetManager::Get_Instance()->Create_Render_Obj_Iterator();
|
|
if (rite) {
|
|
for (rite->First(); !rite->Is_Done(); rite->Next()) {
|
|
// RenderObjClass * robj=Create_Render_Obj(rite->Current_Item_Name());
|
|
// if (robj) {
|
|
//
|
|
// robj->Release_Ref();
|
|
// }
|
|
if (rite->Current_Item_Class_ID()==RenderObjClass::CLASSID_HMODEL) {
|
|
WWDEBUG_SAY(("robj: %s\n",rite->Current_Item_Name()));
|
|
}
|
|
}
|
|
|
|
WW3DAssetManager::Get_Instance()->Release_Render_Obj_Iterator(rite);
|
|
}
|
|
*/
|
|
}
|
|
|
|
/***********************************************************************************************
|
|
* WW3DAssetManager::Free -- free all memory (un-needed?) *
|
|
* *
|
|
* INPUT: *
|
|
* *
|
|
* OUTPUT: *
|
|
* *
|
|
* WARNINGS: *
|
|
* *
|
|
* HISTORY: *
|
|
* 12/21/97 GTH : Created. *
|
|
*=============================================================================================*/
|
|
void WW3DAssetManager::Free(void)
|
|
{
|
|
Free_Assets();
|
|
}
|
|
|
|
|
|
/***********************************************************************************************
|
|
* WW3DAssetManager::Free_Assets -- Release all loaded assets *
|
|
* *
|
|
* INPUT: *
|
|
* *
|
|
* OUTPUT: *
|
|
* *
|
|
* WARNINGS: *
|
|
* *
|
|
* HISTORY: *
|
|
* 12/21/97 GTH : Created. *
|
|
* 05/10/1999 SKB : Close down texture cache file. *
|
|
*=============================================================================================*/
|
|
void WW3DAssetManager::Free_Assets(void)
|
|
{
|
|
WWPROFILE( "WW3DAssetManager::Free_Assets" );
|
|
|
|
// delete all of the prototypes
|
|
int count = Prototypes.Count();
|
|
while (count-- > 0) {
|
|
|
|
PrototypeClass * proto = Prototypes[count];
|
|
Prototypes.Delete(count);
|
|
|
|
if (proto != NULL) {
|
|
delete proto;
|
|
}
|
|
}
|
|
|
|
// clear the prototype hash table
|
|
memset(PrototypeHashTable,0,sizeof(PrototypeClass *) * PROTOTYPE_HASH_TABLE_SIZE);
|
|
|
|
// delete all of the anims and trees
|
|
HAnimManager.Free_All_Anims();
|
|
HTreeManager.Free_All_Trees();
|
|
|
|
// release all my references to the materials
|
|
Release_All_Textures();
|
|
Release_All_Font3DDatas();
|
|
Release_All_FontChars();
|
|
|
|
// Close down cache if it is open.
|
|
// NONONONOO.... Don't close it as we might want to free the assets and still be able to load textures.
|
|
// Close_Texture_File_Cache();
|
|
}
|
|
|
|
|
|
/***********************************************************************************************
|
|
* WW3DAssetManager::Free_Unused_Assets -- Release all assets that are referenced only by *
|
|
* the asset manager. *
|
|
* INPUT: *
|
|
* *
|
|
* OUTPUT: *
|
|
* *
|
|
* WARNINGS: *
|
|
* *
|
|
* HISTORY: *
|
|
* 02/18/99 EHC : Created. *
|
|
*=============================================================================================*/
|
|
void WW3DAssetManager::Release_Unused_Assets(void)
|
|
{
|
|
// release all references to objects that have only one reference on them
|
|
// and remove them from our lists.
|
|
Release_Unused_Textures();
|
|
Release_Unused_Font3DDatas();
|
|
}
|
|
|
|
|
|
/***********************************************************************************************
|
|
* WW3DAssetManager::Load_3D_Assets -- Load 3D assets from a file *
|
|
* *
|
|
* INPUT: *
|
|
* *
|
|
* OUTPUT: *
|
|
* *
|
|
* WARNINGS: *
|
|
* *
|
|
* HISTORY: *
|
|
* 10/22/98 BMG : Created. *
|
|
*=============================================================================================*/
|
|
bool WW3DAssetManager::Load_3D_Assets( const char * filename )
|
|
{
|
|
bool result = false;
|
|
|
|
FileClass * file = _TheFileFactory->Get_File( filename );
|
|
if ( file ) {
|
|
if ( file->Is_Available() ) {
|
|
result = WW3DAssetManager::Load_3D_Assets( *file );
|
|
}
|
|
_TheFileFactory->Return_File( file );
|
|
}
|
|
|
|
return result;
|
|
}
|
|
|
|
|
|
/***********************************************************************************************
|
|
* WW3DAssetManager::Load_3D_Assets -- Load 3D assets from a .W3D file *
|
|
* *
|
|
* INPUT: *
|
|
* *
|
|
* OUTPUT: *
|
|
* *
|
|
* WARNINGS: *
|
|
* *
|
|
* HISTORY: *
|
|
* 12/21/97 GTH : Created. *
|
|
*=============================================================================================*/
|
|
bool WW3DAssetManager::Load_3D_Assets(FileClass & w3dfile)
|
|
{
|
|
WWPROFILE( "WW3DAssetManager::Load_3D_Assets" );
|
|
if (!w3dfile.Open()) {
|
|
return false;
|
|
}
|
|
|
|
ChunkLoadClass cload(&w3dfile);
|
|
|
|
while (cload.Open_Chunk()) {
|
|
|
|
switch (cload.Cur_Chunk_ID()) {
|
|
|
|
case W3D_CHUNK_HIERARCHY:
|
|
HTreeManager.Load_Tree(cload);
|
|
break;
|
|
|
|
case W3D_CHUNK_ANIMATION:
|
|
case W3D_CHUNK_COMPRESSED_ANIMATION:
|
|
case W3D_CHUNK_MORPH_ANIMATION:
|
|
HAnimManager.Load_Anim(cload);
|
|
break;
|
|
|
|
default:
|
|
Load_Prototype(cload);
|
|
break;
|
|
}
|
|
|
|
cload.Close_Chunk();
|
|
}
|
|
|
|
w3dfile.Close();
|
|
|
|
return true;
|
|
}
|
|
|
|
|
|
/***********************************************************************************************
|
|
* WW3DAssetManager::Load_Prototype -- loads a prototype from a W3D chunk *
|
|
* *
|
|
* INPUT: *
|
|
* *
|
|
* OUTPUT: *
|
|
* *
|
|
* WARNINGS: *
|
|
* *
|
|
* HISTORY: *
|
|
* 7/29/98 GTH : Created. *
|
|
* 2/19/99 EHC : Now has the Add_Prototype call responsible for adding the prototype to *
|
|
* the Prototypes list object. *
|
|
*=============================================================================================*/
|
|
bool WW3DAssetManager::Load_Prototype(ChunkLoadClass & cload)
|
|
{
|
|
WWPROFILE( "WW3DAssetManager::Load_Prototype" );
|
|
WWMEMLOG(MEM_GEOMETRY);
|
|
|
|
/*
|
|
** Get the chunk id
|
|
*/
|
|
int chunk_id = cload.Cur_Chunk_ID();
|
|
|
|
/*
|
|
** Find a loader that handles that type of chunk
|
|
*/
|
|
PrototypeLoaderClass * loader = Find_Prototype_Loader(chunk_id);
|
|
PrototypeClass * newproto = NULL;
|
|
|
|
if (loader != NULL) {
|
|
|
|
/*
|
|
** Ask it to create a prototype from the contents of the
|
|
** chunk.
|
|
*/
|
|
newproto = loader->Load_W3D(cload);
|
|
|
|
} else {
|
|
|
|
/*
|
|
** Warn user about an unknown chunk type
|
|
*/
|
|
WWDEBUG_SAY(("Unknown chunk type encountered! Chunk Id = %d\r\n",chunk_id));
|
|
return false;
|
|
}
|
|
|
|
/*
|
|
** Now, see if the prototype that we loaded has a duplicate
|
|
** name with any of our currently loaded prototypes (can't have that!)
|
|
*/
|
|
if (newproto != NULL) {
|
|
|
|
if (!Render_Obj_Exists(newproto->Get_Name())) {
|
|
|
|
/*
|
|
** Add the new, unique prototype to our list
|
|
*/
|
|
Add_Prototype(newproto);
|
|
|
|
} else {
|
|
|
|
/*
|
|
** Warn the user about a name collision with this prototype
|
|
** and dump it
|
|
*/
|
|
WWDEBUG_SAY(("Render Object Name Collision: %s\r\n",newproto->Get_Name()));
|
|
delete newproto;
|
|
newproto = NULL;
|
|
return false;
|
|
}
|
|
|
|
} else {
|
|
|
|
/*
|
|
** Warn user that a prototype was not generated from this
|
|
** chunk type
|
|
*/
|
|
WWDEBUG_SAY(("Could not generate prototype! Chunk = %d\r\n",chunk_id));
|
|
return false;
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
|
|
/***********************************************************************************************
|
|
* WW3DAssetManager::Create_Render_Obj -- Create a render object for the user *
|
|
* *
|
|
* This function will create any type of render object. I.e. if you pass in the name *
|
|
* of an HModel, it will create an hmodel for you. *
|
|
* *
|
|
* INPUT: *
|
|
* *
|
|
* OUTPUT: *
|
|
* *
|
|
* WARNINGS: *
|
|
* *
|
|
* HISTORY: *
|
|
* 12/21/97 GTH : Created. *
|
|
*=============================================================================================*/
|
|
RenderObjClass * WW3DAssetManager::Create_Render_Obj(const char * name)
|
|
{
|
|
WWPROFILE( "WW3DAssetManager::Create_Render_Obj" );
|
|
WWMEMLOG(MEM_GEOMETRY);
|
|
|
|
// Try to find a prototype
|
|
PrototypeClass * proto = Find_Prototype(name);
|
|
|
|
if (WW3D_Load_On_Demand && proto == NULL) { // If we didn't find one, try to load on demand
|
|
AssetStatusClass::Peek_Instance()->Report_Load_On_Demand_RObj(name);
|
|
|
|
char filename [MAX_PATH];
|
|
char *mesh_name = ::strchr (name, '.');
|
|
if (mesh_name != NULL) {
|
|
::lstrcpyn (filename, name, ((int)mesh_name) - ((int)name) + 1);
|
|
::lstrcat (filename, ".w3d");
|
|
} else {
|
|
sprintf( filename, "%s.w3d", name);
|
|
}
|
|
|
|
// If we can't find it, try the parent directory
|
|
if ( Load_3D_Assets( filename ) == false ) {
|
|
StringClass new_filename(StringClass("..\\"),true);
|
|
new_filename+=filename;
|
|
Load_3D_Assets( new_filename );
|
|
}
|
|
|
|
proto = Find_Prototype(name); // try again
|
|
}
|
|
|
|
if (proto == NULL) {
|
|
AssetStatusClass::Peek_Instance()->Report_Missing_RObj(name);
|
|
return NULL; // Failed to find a prototype
|
|
}
|
|
|
|
return proto->Create();
|
|
}
|
|
|
|
|
|
/***********************************************************************************************
|
|
* WW3DAssetManager::Render_Obj_Exists -- Check whether a render object with the given name ex *
|
|
* *
|
|
* INPUT: *
|
|
* *
|
|
* OUTPUT: *
|
|
* *
|
|
* WARNINGS: *
|
|
* *
|
|
* HISTORY: *
|
|
* 12/21/97 GTH : Created. *
|
|
*=============================================================================================*/
|
|
bool WW3DAssetManager::Render_Obj_Exists(const char * name)
|
|
{
|
|
if (Find_Prototype(name) == NULL) return false;
|
|
else return true;
|
|
}
|
|
|
|
|
|
/***********************************************************************************************
|
|
* WW3DAssetManager::Create_Render_Obj_Iterator -- Create an iterator which can enumerate all *
|
|
* *
|
|
* The iterator returned can enumerate all of the loaded render objects for you. *
|
|
* The user is responsible for releasing the iterator! *
|
|
* *
|
|
* INPUT: *
|
|
* *
|
|
* OUTPUT: *
|
|
* *
|
|
* WARNINGS: *
|
|
* User must release the iterator back to the asset manager or there will be a memory leak *
|
|
* *
|
|
* HISTORY: *
|
|
* 12/21/97 GTH : Created. *
|
|
*=============================================================================================*/
|
|
RenderObjIterator * WW3DAssetManager::Create_Render_Obj_Iterator(void)
|
|
{
|
|
return new RObjIterator();
|
|
}
|
|
|
|
|
|
/***********************************************************************************************
|
|
* WW3DAssetManager::Release_Render_Obj_Iterator -- release a render object iterator *
|
|
* *
|
|
* INPUT: *
|
|
* *
|
|
* OUTPUT: *
|
|
* *
|
|
* WARNINGS: *
|
|
* *
|
|
* HISTORY: *
|
|
* 9/28/98 GTH : Created. *
|
|
*=============================================================================================*/
|
|
void WW3DAssetManager::Release_Render_Obj_Iterator(RenderObjIterator * it)
|
|
{
|
|
WWASSERT(it != NULL);
|
|
delete it;
|
|
}
|
|
|
|
/***********************************************************************************************
|
|
* WW3DAssetManager::Create_HAnim_Iterator -- Creates an HAnim Iterator *
|
|
* *
|
|
* Creates an iterator which can enumerate each of the named hierarchical animations *
|
|
* which are currently loaded. *
|
|
* *
|
|
* INPUT: *
|
|
* *
|
|
* OUTPUT: *
|
|
* *
|
|
* WARNINGS: *
|
|
* User must delete the iterator! *
|
|
* *
|
|
* HISTORY: *
|
|
* 12/21/97 GTH : Created. *
|
|
*=============================================================================================*/
|
|
AssetIterator * WW3DAssetManager::Create_HAnim_Iterator(void)
|
|
{
|
|
return new HAnimIterator();
|
|
}
|
|
|
|
|
|
/***********************************************************************************************
|
|
* WW3DAssetManager::Create_HTree_Iterator -- creates an htree iterator *
|
|
* *
|
|
* INPUT: *
|
|
* *
|
|
* OUTPUT: *
|
|
* *
|
|
* WARNINGS: *
|
|
* *
|
|
* HISTORY: *
|
|
* 3/11/98 GTH : Created. *
|
|
*=============================================================================================*/
|
|
AssetIterator * WW3DAssetManager::Create_HTree_Iterator(void)
|
|
{
|
|
return new HTreeIterator();
|
|
}
|
|
|
|
|
|
/***********************************************************************************************
|
|
* WW3DAssetManager::Create_Font3DData_Iterator -- Create a Font3DData iterator *
|
|
* *
|
|
* Creates an iterator which can enumerate each of the Font3DDatas currently loaded *
|
|
* *
|
|
* INPUT: *
|
|
* *
|
|
* OUTPUT: *
|
|
* *
|
|
* WARNINGS: *
|
|
* User must delete the iterator! *
|
|
* *
|
|
* HISTORY: *
|
|
* 1/6/98 GTH : Created. *
|
|
*=============================================================================================*/
|
|
AssetIterator * WW3DAssetManager::Create_Font3DData_Iterator(void)
|
|
{
|
|
return new Font3DDataIterator();
|
|
}
|
|
|
|
/***********************************************************************************************
|
|
* WW3DAssetManager::Get_HAnim -- Returns a pointer to a names HAnim *
|
|
* *
|
|
* INPUT: *
|
|
* *
|
|
* OUTPUT: *
|
|
* *
|
|
* WARNINGS: *
|
|
* The implementation has changed since its inception, the asset manager no longer owns the *
|
|
* hanim's so they need to be released by the caller. *
|
|
* *
|
|
* HISTORY: *
|
|
* 12/21/97 GTH : Created. *
|
|
*=============================================================================================*/
|
|
HAnimClass * WW3DAssetManager::Get_HAnim(const char * name)
|
|
{
|
|
WWPROFILE( "WW3DAssetManager::Get_HAnim" );
|
|
|
|
// Try to find the hanim
|
|
HAnimClass * anim = HAnimManager.Get_Anim(name);
|
|
|
|
if (WW3D_Load_On_Demand && anim == NULL) { // If we didn't find it, try to load on demand
|
|
|
|
if ( !HAnimManager.Is_Missing( name ) ) { // if this is NOT a known missing anim
|
|
|
|
AssetStatusClass::Peek_Instance()->Report_Load_On_Demand_HAnim(name);
|
|
|
|
char filename[ MAX_PATH ];
|
|
char *animname = strchr( name, '.');
|
|
if (animname != NULL) {
|
|
sprintf( filename, "%s.w3d", animname+1);
|
|
} else {
|
|
WWDEBUG_SAY(( "Animation %s has no . in the name\n", name ));
|
|
WWASSERT( 0 );
|
|
return NULL;
|
|
}
|
|
|
|
// If we can't find it, try the parent directory
|
|
if ( Load_3D_Assets( filename ) == false ) {
|
|
StringClass new_filename = StringClass("..\\") + filename;
|
|
Load_3D_Assets( new_filename );
|
|
}
|
|
|
|
anim = HAnimManager.Get_Anim(name); // Try agai
|
|
if (anim == NULL) {
|
|
HAnimManager.Register_Missing( name ); // This is now a KNOWN missing anim
|
|
AssetStatusClass::Peek_Instance()->Report_Missing_HAnim(name);
|
|
}
|
|
}
|
|
}
|
|
|
|
return anim;
|
|
}
|
|
|
|
|
|
/***********************************************************************************************
|
|
* WW3DAssetManager::Get_HTree -- Returns a pointer to the named HTree *
|
|
* *
|
|
* INPUT: *
|
|
* *
|
|
* OUTPUT: *
|
|
* *
|
|
* WARNINGS: *
|
|
* DO NOT DELETE the HTree you get from this function, it is "owned" by the asset manager. *
|
|
* *
|
|
* HISTORY: *
|
|
* 12/21/97 GTH : Created. *
|
|
*=============================================================================================*/
|
|
HTreeClass * WW3DAssetManager::Get_HTree(const char * name)
|
|
{
|
|
WWPROFILE( "WW3DAssetManager::Get_HTree" );
|
|
|
|
// Try to find the htree
|
|
HTreeClass * htree = HTreeManager.Get_Tree(name);
|
|
|
|
if (WW3D_Load_On_Demand && htree == NULL) { // If we didn't find it, try to load on demand
|
|
|
|
AssetStatusClass::Peek_Instance()->Report_Load_On_Demand_HTree(name);
|
|
|
|
char filename[ MAX_PATH ];
|
|
sprintf( filename, "%s.w3d", name);
|
|
|
|
// If we can't find it, try the parent directory
|
|
if ( Load_3D_Assets( filename ) == false ) {
|
|
StringClass new_filename("..\\",true);
|
|
new_filename+=filename;
|
|
Load_3D_Assets( new_filename );
|
|
}
|
|
|
|
htree = HTreeManager.Get_Tree(name); // Try again
|
|
|
|
if (htree == NULL) {
|
|
AssetStatusClass::Peek_Instance()->Report_Missing_HTree(name);
|
|
}
|
|
}
|
|
|
|
return htree;
|
|
}
|
|
|
|
/***********************************************************************************************
|
|
* WW3DAssetManager::Get_Texture -- get a TextureClass from the specified file *
|
|
* *
|
|
* INPUT: *
|
|
* *
|
|
* OUTPUT: *
|
|
* *
|
|
* WARNINGS: *
|
|
* *
|
|
* HISTORY: *
|
|
* 1/31/2001 NH : Created. *
|
|
*=============================================================================================*/
|
|
TextureClass * WW3DAssetManager::Get_Texture(
|
|
const char * filename,
|
|
TextureClass::MipCountType mip_level_count,
|
|
WW3DFormat texture_format,
|
|
bool allow_compression)
|
|
{
|
|
WWPROFILE( "WW3DAssetManager::Get_Texture 1" );
|
|
|
|
/*
|
|
** We cannot currently mip-map bumpmaps
|
|
*/
|
|
if (texture_format==WW3D_FORMAT_U8V8) {
|
|
mip_level_count=TextureClass::MIP_LEVELS_1;
|
|
}
|
|
|
|
/*
|
|
** Bail if the user isn't really asking for anything
|
|
*/
|
|
if ((filename == NULL) || (strlen(filename) == 0)) {
|
|
return NULL;
|
|
}
|
|
|
|
StringClass lower_case_name(filename,true);
|
|
_strlwr(lower_case_name.Peek_Buffer());
|
|
|
|
/*
|
|
** See if the texture has already been loaded.
|
|
*/
|
|
TextureClass* tex = TextureHash.Get(lower_case_name);
|
|
if (tex && (tex->Is_Initialized() == true) && (texture_format!=WW3D_FORMAT_UNKNOWN)) {
|
|
WWASSERT_PRINT(tex->Get_Texture_Format()==texture_format,("Texture %s has already been loaded with different format",filename));
|
|
}
|
|
|
|
/*
|
|
** Didn't have it so we have to create a new texture
|
|
*/
|
|
if (!tex) {
|
|
tex = NEW_REF(TextureClass,(lower_case_name, NULL, mip_level_count, texture_format, allow_compression));
|
|
TextureHash.Insert(tex->Get_Texture_Name(),tex);
|
|
}
|
|
|
|
tex->Add_Ref();
|
|
return tex;
|
|
}
|
|
|
|
|
|
/***********************************************************************************************
|
|
* WW3DAssetManager::Release_All_Textures -- release all textures in the system *
|
|
* *
|
|
* INPUT: *
|
|
* *
|
|
* OUTPUT: *
|
|
* *
|
|
* WARNINGS: *
|
|
* *
|
|
* HISTORY: *
|
|
* 3/10/98 GTH : Created. *
|
|
*=============================================================================================*/
|
|
void WW3DAssetManager::Release_All_Textures(void)
|
|
{
|
|
/*
|
|
** for each texture in the list, get it and release ref it
|
|
*/
|
|
|
|
HashTemplateIterator<StringClass,TextureClass*> ite(TextureHash);
|
|
for (ite.First();!ite.Is_Done();ite.Next()) {
|
|
TextureClass * tex=ite.Peek_Value();
|
|
// WWASSERT(tex->Num_Refs()==1); // If asset manager is releasing the texture,
|
|
// nobody should be referencing to it anymore!
|
|
tex->Release_Ref();
|
|
}
|
|
TextureHash.Remove_All();
|
|
}
|
|
|
|
|
|
/***********************************************************************************************
|
|
* WW3DAssetManager::Release_Unused_Textures -- release all textures with refcount == 1 *
|
|
* *
|
|
* INPUT: *
|
|
* *
|
|
* OUTPUT: *
|
|
* *
|
|
* WARNINGS: *
|
|
* *
|
|
* HISTORY: *
|
|
* 2/18/99 EHC : Created. *
|
|
*=============================================================================================*/
|
|
void WW3DAssetManager::Release_Unused_Textures(void)
|
|
{
|
|
/*
|
|
** for each texture in the list, get it, check it's refcount, and and release ref it if the
|
|
** refcount is one.
|
|
*/
|
|
|
|
unsigned count=0;
|
|
TextureClass* temp_textures[256];
|
|
|
|
HashTemplateIterator<StringClass,TextureClass*> ite(TextureHash);
|
|
for (ite.First();!ite.Is_Done();ite.Next()) {
|
|
TextureClass* tex=ite.Peek_Value();
|
|
if (tex->Num_Refs() == 1) {
|
|
temp_textures[count++]=tex;
|
|
if (count==256) {
|
|
for (unsigned i=0;i<256;++i) {
|
|
TextureHash.Remove(temp_textures[i]->Get_Texture_Name());
|
|
temp_textures[i]->Release_Ref();
|
|
}
|
|
count=0;
|
|
ite.First(); // iterator doesn't support modifying the hash table while iterating, so start from the
|
|
// beginning.
|
|
}
|
|
}
|
|
}
|
|
for (unsigned i=0;i<count;++i) {
|
|
TextureHash.Remove(temp_textures[i]->Get_Texture_Name());
|
|
temp_textures[i]->Release_Ref();
|
|
}
|
|
}
|
|
|
|
/***********************************************************************************************
|
|
* WW3DAssetManager::Release_Texture -- release a specific texture from the asset manager *
|
|
* *
|
|
* INPUT: *
|
|
* *
|
|
* OUTPUT: *
|
|
* *
|
|
* WARNINGS: *
|
|
* *
|
|
* HISTORY: *
|
|
* 2/18/99 EHC : Created. *
|
|
*=============================================================================================*/
|
|
void WW3DAssetManager::Release_Texture(TextureClass *tex)
|
|
{
|
|
/*
|
|
** Try to find the texture in the list, if found release it and remove it from the list.
|
|
*/
|
|
|
|
TextureHash.Remove(tex->Get_Texture_Name());
|
|
tex->Release_Ref();
|
|
}
|
|
|
|
void WW3DAssetManager::Log_All_Textures(void)
|
|
{
|
|
Log_Texture_Statistics();
|
|
|
|
HashTemplateIterator<StringClass,TextureClass*> ite(TextureHash);
|
|
|
|
// Log lightmaps -----------------------------------
|
|
|
|
WWDEBUG_SAY((
|
|
"Lightmap textures: %d\n\n"
|
|
"size name\n"
|
|
"--------------------------------------\n"
|
|
,
|
|
TextureClass::_Get_Total_Lightmap_Texture_Count()));
|
|
|
|
for (ite.First();!ite.Is_Done();ite.Next()) {
|
|
TextureClass* t=ite.Peek_Value();
|
|
if (!t->Is_Lightmap()) continue;
|
|
|
|
StringClass tmp(true);
|
|
unsigned bytes=t->Get_Texture_Memory_Usage();
|
|
if (!t->Is_Initialized()) {
|
|
tmp+="*";
|
|
}
|
|
else {
|
|
tmp+=" ";
|
|
}
|
|
WWDEBUG_SAY(("%4.4dkb %s%s\n",bytes/1024,tmp,t->Get_Texture_Name()));
|
|
}
|
|
|
|
// Log procedural textures -------------------------------
|
|
|
|
WWDEBUG_SAY((
|
|
"Procedural textures: %d\n\n"
|
|
"size name\n"
|
|
"--------------------------------------\n"
|
|
,
|
|
TextureClass::_Get_Total_Procedural_Texture_Count()));
|
|
|
|
for (ite.First();!ite.Is_Done();ite.Next()) {
|
|
TextureClass* t=ite.Peek_Value();
|
|
if (!t->Is_Procedural()) continue;
|
|
|
|
StringClass tmp(true);
|
|
unsigned bytes=t->Get_Texture_Memory_Usage();
|
|
if (!t->Is_Initialized()) {
|
|
tmp+="*";
|
|
}
|
|
else {
|
|
tmp+=" ";
|
|
}
|
|
WWDEBUG_SAY(("%4.4dkb %s%s\n",bytes/1024,tmp,t->Get_Texture_Name()));
|
|
}
|
|
|
|
// Log "ordinary" textures -------------------------------
|
|
|
|
WWDEBUG_SAY((
|
|
"Ordinary textures: %d\n\n"
|
|
"size name\n"
|
|
"--------------------------------------\n"
|
|
,
|
|
TextureClass::_Get_Total_Texture_Count()-TextureClass::_Get_Total_Lightmap_Texture_Count()-TextureClass::_Get_Total_Procedural_Texture_Count()));
|
|
|
|
for (ite.First();!ite.Is_Done();ite.Next()) {
|
|
TextureClass* t=ite.Peek_Value();
|
|
if (t->Is_Procedural()) continue;
|
|
if (t->Is_Lightmap()) continue;
|
|
|
|
StringClass tmp(true);
|
|
unsigned bytes=t->Get_Texture_Memory_Usage();
|
|
if (!t->Is_Initialized()) {
|
|
tmp+="*";
|
|
}
|
|
else {
|
|
tmp+=" ";
|
|
}
|
|
WWDEBUG_SAY(("%4.4dkb %s%s\n",bytes/1024,tmp,t->Get_Texture_Name()));
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/***********************************************************************************************
|
|
* WW3DAssetManager::Get_Font3DInstance -- Creates a pointer to a Font3DInstance *
|
|
* *
|
|
* INPUT: *
|
|
* *
|
|
* OUTPUT: *
|
|
* *
|
|
* WARNINGS: *
|
|
* *
|
|
* HISTORY: *
|
|
* 1/6/98 GTH : Created. *
|
|
*=============================================================================================*/
|
|
Font3DInstanceClass * WW3DAssetManager::Get_Font3DInstance( const char *name )
|
|
{
|
|
WWPROFILE( "WW3DAssetManager::Get_Font3DInstance" );
|
|
return NEW_REF( Font3DInstanceClass, ( name ));
|
|
}
|
|
|
|
|
|
/***********************************************************************************************
|
|
* WW3DAssetManager::Get_Font3DData -- Gets a pointer to a loaded Font3DData or creates it *
|
|
* *
|
|
* INPUT: *
|
|
* *
|
|
* OUTPUT: *
|
|
* *
|
|
* WARNINGS: *
|
|
* *
|
|
* HISTORY: *
|
|
* 1/6/98 GTH : Created. *
|
|
*=============================================================================================*/
|
|
Font3DDataClass * WW3DAssetManager::Get_Font3DData( const char *name )
|
|
{
|
|
WWPROFILE( "WW3DAssetManager::Get_Font3DData" );
|
|
// loop through and see if the Font3D we are looking for has already been
|
|
// allocated and thus we can just return it.
|
|
for ( SLNode<Font3DDataClass> *node = Font3DDatas.Head(); node; node = node->Next()) {
|
|
if (!stricmp(name, node->Data()->Name)) {
|
|
node->Data()->Add_Ref();
|
|
return node->Data();
|
|
}
|
|
}
|
|
|
|
// if one hasn't been found and a font name has been specified then create it
|
|
Font3DDataClass * font = NEW_REF( Font3DDataClass, ( name ));
|
|
|
|
// add it to the asset manager
|
|
Add_Font3DData( font);
|
|
|
|
// return it
|
|
return font;
|
|
}
|
|
|
|
/***********************************************************************************************
|
|
* WW3DAssetManager::Add_Font3DData -- Add a Font3DData to the list *
|
|
* *
|
|
* INPUT: *
|
|
* *
|
|
* OUTPUT: *
|
|
* *
|
|
* WARNINGS: *
|
|
* *
|
|
* HISTORY: *
|
|
* 1/6/98 GTH : Created. *
|
|
*=============================================================================================*/
|
|
void WW3DAssetManager::Add_Font3DData(Font3DDataClass * font)
|
|
{
|
|
font->Add_Ref();
|
|
Font3DDatas.Add_Head(font);
|
|
}
|
|
|
|
void WW3DAssetManager::Remove_Font3DData(Font3DDataClass * font)
|
|
{
|
|
font->Release_Ref();
|
|
Font3DDatas.Remove(font);
|
|
}
|
|
|
|
/***********************************************************************************************
|
|
* WW3DAssetManager::Release_All_Font3DDatas -- Release all Font3DDatas from the asset manager *
|
|
* *
|
|
* INPUT: *
|
|
* *
|
|
* OUTPUT: *
|
|
* *
|
|
* WARNINGS: *
|
|
* *
|
|
* HISTORY: *
|
|
* 1/6/98 GTH : Created. *
|
|
*=============================================================================================*/
|
|
void WW3DAssetManager::Release_All_Font3DDatas( void )
|
|
{
|
|
// for each mat in the list, get it and release ref it
|
|
Font3DDataClass *head;
|
|
while ((head = Font3DDatas.Remove_Head()) != NULL ) {
|
|
head->Release_Ref();
|
|
}
|
|
}
|
|
|
|
/***********************************************************************************************
|
|
* WW3DAssetManager::Release_Unused_Font3DDatas -- Release all Font3DDatas with refcount == 1 *
|
|
* *
|
|
* INPUT: *
|
|
* *
|
|
* OUTPUT: *
|
|
* *
|
|
* WARNINGS: *
|
|
* *
|
|
* HISTORY: *
|
|
* 1/6/98 GTH : Created. *
|
|
*=============================================================================================*/
|
|
void WW3DAssetManager::Release_Unused_Font3DDatas( void )
|
|
{
|
|
/*
|
|
** for each font data in the list, get it, check it's refcount, and and release ref it if the
|
|
** refcount is one.
|
|
*/
|
|
SLNode<Font3DDataClass> *node, * next;
|
|
for ( node = Font3DDatas.Head(); node; node = next) {
|
|
next = node->Next();
|
|
Font3DDataClass *font = node->Data();
|
|
if (font->Num_Refs() == 1) {
|
|
Font3DDatas.Remove(font);
|
|
font->Release_Ref();
|
|
}
|
|
}
|
|
}
|
|
|
|
/***********************************************************************************************
|
|
* WW3DAssetManager::Get_FontChars -- Gets a pointer to a loaded FontChars or creates it *
|
|
* *
|
|
* INPUT: *
|
|
* *
|
|
* OUTPUT: *
|
|
* *
|
|
* WARNINGS: *
|
|
* *
|
|
* HISTORY: *
|
|
* 6/1/01 BMG : Created. *
|
|
*=============================================================================================*/
|
|
FontCharsClass * WW3DAssetManager::Get_FontChars( const char * name, int point_size, bool is_bold )
|
|
{
|
|
WWPROFILE( "WW3DAssetManager::Get_FontChars" );
|
|
|
|
// loop through and see if we already have the font chars and we can just return it.
|
|
for ( int i = 0; i < FontCharsList.Count(); i++ ) {
|
|
if ( FontCharsList[i]->Is_Font( name, point_size, is_bold ) ) {
|
|
FontCharsList[i]->Add_Ref();
|
|
return FontCharsList[i];
|
|
}
|
|
}
|
|
|
|
// If one hasn't been found, create it
|
|
FontCharsClass * font = NEW_REF( FontCharsClass, () );
|
|
font->Initialize_GDI_Font( name, point_size, is_bold );
|
|
font->Add_Ref();
|
|
FontCharsList.Add( font ); // add it to the list
|
|
return font; // return it
|
|
}
|
|
|
|
|
|
/***********************************************************************************************
|
|
* WW3DAssetManager::Release_All_FontChars -- Release all FontChars from the asset manager *
|
|
* *
|
|
* INPUT: *
|
|
* *
|
|
* OUTPUT: *
|
|
* *
|
|
* WARNINGS: *
|
|
* *
|
|
* HISTORY: *
|
|
* 6/1/01 BMG : Created. *
|
|
*=============================================================================================*/
|
|
void WW3DAssetManager::Release_All_FontChars( void )
|
|
{
|
|
// for each fontchars in the list, get it and release ref it
|
|
while ( FontCharsList.Count() ) {
|
|
FontCharsList[0]->Release_Ref();
|
|
FontCharsList.Delete( 0 );
|
|
}
|
|
}
|
|
|
|
/***********************************************************************************************
|
|
* WW3DAssetManager::Register_Prototype_Loader -- add a new loader to the system *
|
|
* *
|
|
* The library will automatically install loaders for the "built-in" render object *
|
|
* types. This function exists so that the user can design App-specific render objects, *
|
|
* define a chunk format for them, and have the asset manager load them in like everything *
|
|
* else. *
|
|
* *
|
|
* INPUT: *
|
|
* loader - pointer to a global or static instance of your loader type. *
|
|
* *
|
|
* OUTPUT: *
|
|
* *
|
|
* WARNINGS: *
|
|
* *
|
|
* HISTORY: *
|
|
* 7/28/98 GTH : Created. *
|
|
*=============================================================================================*/
|
|
void WW3DAssetManager::Register_Prototype_Loader(PrototypeLoaderClass * loader)
|
|
{
|
|
WWASSERT(loader != NULL);
|
|
PrototypeLoaders.Add(loader);
|
|
}
|
|
|
|
|
|
/***********************************************************************************************
|
|
* WW3DAssetManager::Find_Prototype_Loader -- find the loader that handles this chunk type *
|
|
* *
|
|
* INPUT: *
|
|
* chunk_id - chunk type that the loader needs to handle *
|
|
* *
|
|
* OUTPUT: *
|
|
* pointer to the appropriate loader or NULL if one wasn't found *
|
|
* *
|
|
* WARNINGS: *
|
|
* *
|
|
* HISTORY: *
|
|
* 7/28/98 GTH : Created. *
|
|
*=============================================================================================*/
|
|
PrototypeLoaderClass * WW3DAssetManager::Find_Prototype_Loader(int chunk_id)
|
|
{
|
|
for (int i=0; i<PrototypeLoaders.Count(); i++) {
|
|
PrototypeLoaderClass * loader = PrototypeLoaders[i];
|
|
if (loader && loader->Chunk_Type() == chunk_id) {
|
|
return loader;
|
|
}
|
|
}
|
|
return NULL;
|
|
}
|
|
|
|
|
|
/***********************************************************************************************
|
|
* WW3DAssetManager::Add_Prototype -- adds the prototype to the hash table *
|
|
* *
|
|
* INPUT: *
|
|
* *
|
|
* OUTPUT: *
|
|
* *
|
|
* WARNINGS: *
|
|
* *
|
|
* HISTORY: *
|
|
* 7/29/98 GTH : Created. *
|
|
* 12/8/98 GTH : Renamed to simply Add_Prototype *
|
|
* 2/19/99 EHC : Now adds the prototype to the prototype list *
|
|
*=============================================================================================*/
|
|
void WW3DAssetManager::Add_Prototype(PrototypeClass * newproto)
|
|
{
|
|
WWASSERT(newproto != NULL);
|
|
int hash = CRC_Stringi(newproto->Get_Name()) & PROTOTYPE_HASH_MASK;
|
|
newproto->NextHash = PrototypeHashTable[hash];
|
|
PrototypeHashTable[hash] = newproto;
|
|
Prototypes.Add(newproto);
|
|
}
|
|
|
|
|
|
/***********************************************************************************************
|
|
* WW3DAssetManager::Remove_Prototype -- Removes all references to the protype. *
|
|
* *
|
|
* INPUT: *
|
|
* *
|
|
* OUTPUT: *
|
|
* *
|
|
* WARNINGS: *
|
|
* *
|
|
* HISTORY: *
|
|
* 02/4/99 PDS : Created. *
|
|
*=============================================================================================*/
|
|
void WW3DAssetManager::Remove_Prototype(PrototypeClass *proto)
|
|
{
|
|
WWASSERT(proto != NULL);
|
|
if (proto != NULL) {
|
|
|
|
//
|
|
// Find the prototype in the hash table.
|
|
//
|
|
const char *pname = proto->Get_Name ();
|
|
bool bfound = false;
|
|
PrototypeClass *prev = NULL;
|
|
int hash = CRC_Stringi(pname) & PROTOTYPE_HASH_MASK;
|
|
for (PrototypeClass *test = PrototypeHashTable[hash];
|
|
(test != NULL) && (bfound == false);
|
|
test = test->NextHash) {
|
|
|
|
// Is this the prototype?
|
|
if (::stricmp (test->Get_Name(), pname) == 0) {
|
|
|
|
// Remove this prototype from the linked list for this hash index.
|
|
if (prev == NULL) {
|
|
PrototypeHashTable[hash] = test->NextHash;
|
|
} else {
|
|
prev->NextHash = test->NextHash;
|
|
}
|
|
|
|
// Success!
|
|
bfound = true;
|
|
}
|
|
|
|
// Remember who our previous entry is
|
|
prev = test;
|
|
}
|
|
|
|
// Now remove this from our vector-array of prototypes
|
|
Prototypes.Delete (proto);
|
|
}
|
|
|
|
return;
|
|
}
|
|
|
|
|
|
/***********************************************************************************************
|
|
* WW3DAssetManager::Remove_Prototype -- Removes all references to the protype. *
|
|
* *
|
|
* INPUT: *
|
|
* *
|
|
* OUTPUT: *
|
|
* *
|
|
* WARNINGS: *
|
|
* *
|
|
* HISTORY: *
|
|
* 02/4/99 PDS : Created. *
|
|
*=============================================================================================*/
|
|
void WW3DAssetManager::Remove_Prototype(const char *name)
|
|
{
|
|
WWASSERT(name != NULL);
|
|
if (name != NULL) {
|
|
|
|
// Lookup the prototype by name
|
|
PrototypeClass *proto = Find_Prototype (name);
|
|
if (proto != NULL) {
|
|
|
|
// Remove the prototype from our lists, and free its memory
|
|
Remove_Prototype (proto);
|
|
delete proto;
|
|
}
|
|
}
|
|
|
|
return;
|
|
}
|
|
|
|
|
|
/***********************************************************************************************
|
|
* WW3DAssetManager::Find_Prototype -- searches the hash table for the prototype *
|
|
* *
|
|
* INPUT: *
|
|
* *
|
|
* OUTPUT: *
|
|
* *
|
|
* WARNINGS: *
|
|
* *
|
|
* HISTORY: *
|
|
* 7/29/98 GTH : Created. *
|
|
* 12/8/98 GTH : Renamed to simply Find_Prototype *
|
|
*=============================================================================================*/
|
|
PrototypeClass * WW3DAssetManager::Find_Prototype(const char * name)
|
|
{
|
|
// Special case Null render object. So we always have it...
|
|
if (stricmp(name,"NULL") == 0) {
|
|
return &(_NullPrototype);
|
|
}
|
|
|
|
// Find the prototype
|
|
int hash = CRC_Stringi(name) & PROTOTYPE_HASH_MASK;
|
|
PrototypeClass * test = PrototypeHashTable[hash];
|
|
|
|
while (test != NULL) {
|
|
if (stricmp(test->Get_Name(),name) == 0) {
|
|
return test;
|
|
}
|
|
test = test->NextHash;
|
|
}
|
|
return NULL;
|
|
}
|
|
|
|
/*
|
|
** Iterator Implementations.
|
|
** =====================================================================
|
|
** If the user derives a custom asset manager, you will have
|
|
** to implement iterators which can walk through your datastructures.
|
|
*/
|
|
|
|
bool RObjIterator::Is_Done(void)
|
|
{
|
|
return !(Index < WW3DAssetManager::Get_Instance()->Prototypes.Count());
|
|
}
|
|
|
|
const char * RObjIterator::Current_Item_Name(void)
|
|
{
|
|
if (Index < WW3DAssetManager::Get_Instance()->Prototypes.Count()) {
|
|
return WW3DAssetManager::Get_Instance()->Prototypes[Index]->Get_Name();
|
|
} else {
|
|
return NULL;
|
|
}
|
|
}
|
|
|
|
int RObjIterator::Current_Item_Class_ID(void)
|
|
{
|
|
if (Index < WW3DAssetManager::Get_Instance()->Prototypes.Count()) {
|
|
return WW3DAssetManager::Get_Instance()->Prototypes[Index]->Get_Class_ID();
|
|
} else {
|
|
return -1;
|
|
}
|
|
}
|
|
|
|
bool HTreeIterator::Is_Done(void)
|
|
{
|
|
return !(Index < WW3DAssetManager::Get_Instance()->HTreeManager.Num_Trees());
|
|
}
|
|
|
|
const char * HTreeIterator::Current_Item_Name(void)
|
|
{
|
|
return WW3DAssetManager::Get_Instance()->HTreeManager.Get_Tree(Index)->Get_Name();
|
|
}
|
|
|
|
|