openmohaa/code/tiki/tiki_cache.cpp

505 lines
8.5 KiB
C++

/*
===========================================================================
Copyright (C) 2015 the OpenMoHAA team
This file is part of OpenMoHAA source code.
OpenMoHAA source code 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 2 of the License,
or (at your option) any later version.
OpenMoHAA source code 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 OpenMoHAA source code; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
===========================================================================
*/
// tiki_cache.cpp : TIKI's fast implementation
#include "q_shared.h"
#include "qcommon.h"
#include "../skeletor/skeletor.h"
#include <mem_blockalloc.h>
#include <con_set.h>
#include "tiki_files.h"
#include "tiki_skel.h"
struct pchar {
const char *m_Value;
pchar() { m_Value = NULL; }
pchar( const char *value ) { m_Value = value; }
friend bool operator==( const pchar& l, const pchar& r ) { return !strcmp( l.m_Value, r.m_Value ); }
};
con_map< pchar, dtikianim_t * > *tikianimcache;
con_map< pchar, dtiki_t * > *tikicache;
static skeletor_c *skel_entity_cache[ 1024 ];
template<>
int HashCode< pchar >( const pchar& key )
{
return HashCode< const char * >( key.m_Value );
}
/*
===============
TIKI_FindTikiAnim
===============
*/
dtikianim_t *TIKI_FindTikiAnim( const char *path )
{
char filename[ 1024 ];
if( tikianimcache )
{
dtikianim_t **t;
t = tikianimcache->find( filename );
if( t ) {
return *t;
}
}
return NULL;
}
/*
===============
TIKI_FindTiki
===============
*/
dtiki_t *TIKI_FindTiki( const char *path )
{
char filename[ 1024 ];
if( tikicache )
{
dtiki_t **t;
t = tikicache->find( filename );
if( t ) {
return *t;
}
}
return NULL;
}
/*
===============
TIKI_RegisterTikiAnimFlags
===============
*/
dtikianim_t *TIKI_RegisterTikiAnimFlags( const char *path, qboolean use )
{
dtikianim_t *tiki;
char filename[ 1024 ];
strcpy( filename, path );
FS_CanonicalFilename( filename );
if( tikianimcache )
{
dtikianim_t **t;
t = tikianimcache->find( filename );
if( t ) {
return *t;
}
}
else
{
tikianimcache = new con_map < pchar, dtikianim_t * > ;
}
tiki = TIKI_LoadTikiAnim( filename );
if( tiki )
{
if( use )
{
Com_Printf( "^~^~^ Add the following line to the *_precache.scr map script:\n" );
Com_Printf( "cache %s\n", filename );
}
( *tikianimcache )[ tiki->name ] = tiki;
}
return tiki;
}
/*
===============
TIKI_RegisterTikiAnim
===============
*/
dtikianim_t *TIKI_RegisterTikiAnim( const char *path )
{
return TIKI_RegisterTikiAnimFlags( path, qfalse );
}
/*
===============
TIKI_RegisterTikiFlags
===============
*/
dtiki_t *TIKI_RegisterTikiFlags( const char *path, qboolean use )
{
dtiki_t *tiki = NULL;
dtikianim_t* tikianim = NULL;
con_map< str, str > keyValues;
const char *next_path;
str key;
str value;
const char *name;
char filename[ 1024 ];
char full_filename[ 1024 ];
full_filename[ 0 ] = 0;
name = path;
for(next_path = strstr(name, "|"); next_path; next_path = strstr(name, "|"))
{
key = name;
key[next_path - name] = 0;
name = next_path + 1;
next_path = strstr(name, "|" );
if( !next_path ) {
break;
}
value = name;
value[next_path - name] = 0;
name = next_path + 1;
// add it to the entry
keyValues[key] = value;
strcat(full_filename, key.c_str());
strcat(full_filename, "|");
strcat(full_filename, value.c_str());
strcat(full_filename, "|");
}
strcpy(filename, name);
FS_CanonicalFilename(filename);
strcat(full_filename, filename);
if (!tikicache)
{
tikicache = new con_map<pchar, dtiki_t*>;
}
else
{
dtiki_t **t;
t = tikicache->find(full_filename);
if (t) {
return *t;
}
}
tikianim = TIKI_RegisterTikiAnimFlags(filename, use);
if (tikianim)
{
tiki = TIKI_LoadTikiModel(tikianim, full_filename, &keyValues);
if (tiki)
{
// cache the tiki
(*tikicache)[tiki->name] = tiki;
}
}
return tiki;
}
/*
===============
TIKI_RegisterTiki
===============
*/
dtiki_t *TIKI_RegisterTiki( const char *path )
{
return TIKI_RegisterTikiFlags( path, qfalse );
}
/*
===============
TIKI_FreeAll
===============
*/
void TIKI_FreeAll()
{
dtiki_t **entry;
dtikianim_t **entryanim;
dtiki_t *tiki;
dtikianim_t *tikianim;
int i;
if( tikicache )
{
con_map_enum< pchar, dtiki_t * > en = *tikicache;
for( entry = en.NextValue(); entry != NULL; entry = en.NextValue() )
{
skeletor_c *skeletor;
tiki = *entry;
skeletor = ( skeletor_c * )tiki->skeletor;
if( skeletor ) {
delete skeletor;
}
tiki->m_boneList.CleanUpChannels();
/*
if( tiki->a->m_aliases )
{
TIKI_Free( tiki->a->m_aliases );
tiki->a->m_aliases = NULL;
tiki->a->num_anims = 0;
}
*/
TIKI_Free( tiki );
}
tikicache->clear();
}
if( tikianimcache )
{
con_map_enum< pchar, dtikianim_t * > en = *tikianimcache;
for( entryanim = en.NextValue(); entryanim != NULL; entryanim = en.NextValue() )
{
tikianim = *entryanim;
TIKI_RemoveTiki( tikianim );
if( tikianim->m_aliases )
{
TIKI_Free( tikianim->m_aliases );
tikianim->m_aliases = NULL;
tikianim->num_anims = 0;
}
TIKI_Free( tikianim );
}
tikianimcache->clear();
}
tiki_loading = true;
if( skelcache )
{
for( i = 0; i < cache_maxskel; i++ )
{
if (skelcache->skel)
{
TIKI_FreeSkel(i);
}
}
}
}
/*
===============
TIKI_GetSkeletor
===============
*/
static qboolean tiki_started;
void *TIKI_GetSkeletor( dtiki_t *tiki, int entnum )
{
skeletor_c *skel;
if( entnum == ENTITYNUM_NONE )
{
if( !tiki->skeletor ) tiki->skeletor = new skeletor_c( tiki );
skel = ( skeletor_c * )tiki->skeletor;
}
else
{
skel = skel_entity_cache[ entnum ];
if( skel )
{
if( skel->m_Tiki == tiki ) {
return skel_entity_cache[ entnum ];
}
delete skel;
}
skel = new skeletor_c( tiki );
skel_entity_cache[ entnum ] = skel;
}
return skel;
}
/*
===============
TIKI_DeleteSkeletor
===============
*/
static void TIKI_DeleteSkeletor( int entnum )
{
skeletor_c *skel;
if( entnum == ENTITYNUM_NONE )
{
return;
}
skel = skel_entity_cache[ entnum ];
if( skel )
{
delete skel;
skel_entity_cache[ entnum ] = 0;
}
}
/*
===============
TIKI_Begin
===============
*/
void TIKI_Begin( void )
{
int i;
for( i = 0; i < TIKI_MAX_SKELCACHE; i++ )
skel_entity_cache[ i ] = 0;
tiki_started = true;
}
/*
===============
TIKI_End
===============
*/
void TIKI_End( void )
{
int i;
for( i = 0; i < TIKI_MAX_SKELCACHE; i++ )
TIKI_DeleteSkeletor( i );
tiki_started = false;
}
/*
===============
TIKI_FinishLoad
===============
*/
void TIKI_FinishLoad( void )
{
con_map_enum< pchar, dtikianim_t * > en;
dtikianim_t **entry;
if( !tiki_loading )
{
return;
}
tiki_loading = false;
SkeletorCacheCleanCache();
if( !low_anim_memory || !low_anim_memory->integer )
{
return;
}
if( tikianimcache )
{
en = *tikianimcache;
for( entry = en.NextValue(); entry != NULL; entry = en.NextValue() )
{
TIKI_LoadAnim( *entry );
}
}
}
/*
===============
TIKI_FreeImages
===============
*/
void TIKI_FreeImages( void )
{
dtikisurface_t *dsurf;
dtiki_t *tiki;
int j, k;
dtiki_t **entry;
con_map_enum< pchar, dtiki_t * > en;
if( !tikicache )
{
return;
}
en = *tikicache;
for( entry = en.NextValue(); entry != NULL; entry = en.NextValue() )
{
tiki = *entry;
for( k = 0; k < tiki->num_surfaces; k++ )
{
dsurf = &tiki->surfaces[ k ];
for( j = 0; j < dsurf->numskins; j++ )
{
dsurf->hShader[ j ] = 0;
}
}
}
}
/*
===============
TIKI_TikiAnimList_f
===============
*/
void TIKI_TikiAnimList_f( void )
{
con_map_enum< pchar, dtikianim_t * > en;
dtikianim_t **entry;
Com_Printf( "\ntikianimlist:\n" );
if( tikicache )
{
en = *tikianimcache;
for( entry = en.NextValue(); entry != NULL; entry = en.NextValue() )
{
Com_Printf( "%s\n", ( *entry )->name );
}
}
}
/*
===============
TIKI_TikiList_f
===============
*/
void TIKI_TikiList_f( void )
{
con_map_enum< pchar, dtiki_t * > en;
dtiki_t **entry;
Com_Printf( "\ntikilist:\n" );
if( tikicache )
{
en = *tikicache;
for( entry = en.NextValue(); entry != NULL; entry = en.NextValue() )
{
Com_Printf( "%s\n", ( *entry )->name );
}
}
}