2016-03-27 11:49:47 +02:00
|
|
|
/*
|
|
|
|
===========================================================================
|
2023-11-06 18:08:21 +01:00
|
|
|
Copyright (C) 2023 the OpenMoHAA team
|
2016-03-27 11:49:47 +02:00
|
|
|
|
|
|
|
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 {
|
2023-11-06 18:08:21 +01:00
|
|
|
const char *m_Value;
|
2016-03-27 11:49:47 +02:00
|
|
|
|
2023-11-06 18:08:21 +01:00
|
|
|
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); }
|
2016-03-27 11:49:47 +02:00
|
|
|
};
|
|
|
|
|
2023-11-06 18:08:21 +01:00
|
|
|
con_map<pchar, dtikianim_t *> *tikianimcache;
|
|
|
|
con_map<pchar, dtiki_t *> *tikicache;
|
|
|
|
static skeletor_c *skel_entity_cache[1024];
|
2016-03-27 11:49:47 +02:00
|
|
|
|
|
|
|
template<>
|
2023-11-06 18:08:21 +01:00
|
|
|
int HashCode<pchar>(const pchar& key)
|
2016-03-27 11:49:47 +02:00
|
|
|
{
|
2023-11-06 18:08:21 +01:00
|
|
|
return HashCode<const char *>(key.m_Value);
|
2016-03-27 11:49:47 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
===============
|
|
|
|
TIKI_FindTikiAnim
|
|
|
|
===============
|
|
|
|
*/
|
2023-11-06 18:08:21 +01:00
|
|
|
dtikianim_t *TIKI_FindTikiAnim(const char *path)
|
2016-03-27 11:49:47 +02:00
|
|
|
{
|
2023-11-06 18:08:21 +01:00
|
|
|
char filename[1024];
|
2016-03-27 11:49:47 +02:00
|
|
|
|
2023-11-06 18:08:21 +01:00
|
|
|
if (tikianimcache) {
|
|
|
|
dtikianim_t **t;
|
2016-03-27 11:49:47 +02:00
|
|
|
|
2023-11-06 18:08:21 +01:00
|
|
|
t = tikianimcache->find(filename);
|
|
|
|
if (t) {
|
|
|
|
return *t;
|
|
|
|
}
|
|
|
|
}
|
2016-03-27 11:49:47 +02:00
|
|
|
|
2023-11-06 18:08:21 +01:00
|
|
|
return NULL;
|
2016-03-27 11:49:47 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
===============
|
|
|
|
TIKI_FindTiki
|
|
|
|
===============
|
|
|
|
*/
|
2023-11-06 18:08:21 +01:00
|
|
|
dtiki_t *TIKI_FindTiki(const char *path)
|
2016-03-27 11:49:47 +02:00
|
|
|
{
|
2023-11-06 18:08:21 +01:00
|
|
|
char filename[1024];
|
2016-03-27 11:49:47 +02:00
|
|
|
|
2023-11-06 18:08:21 +01:00
|
|
|
if (tikicache) {
|
|
|
|
dtiki_t **t;
|
2016-03-27 11:49:47 +02:00
|
|
|
|
2023-11-06 18:08:21 +01:00
|
|
|
t = tikicache->find(filename);
|
|
|
|
if (t) {
|
|
|
|
return *t;
|
|
|
|
}
|
|
|
|
}
|
2016-03-27 11:49:47 +02:00
|
|
|
|
2023-11-06 18:08:21 +01:00
|
|
|
return NULL;
|
2016-03-27 11:49:47 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
===============
|
|
|
|
TIKI_RegisterTikiAnimFlags
|
|
|
|
===============
|
|
|
|
*/
|
2023-11-06 18:08:21 +01:00
|
|
|
dtikianim_t *TIKI_RegisterTikiAnimFlags(const char *path, qboolean use)
|
2016-03-27 11:49:47 +02:00
|
|
|
{
|
2023-11-06 18:08:21 +01:00
|
|
|
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;
|
2016-03-27 11:49:47 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
===============
|
|
|
|
TIKI_RegisterTikiAnim
|
|
|
|
===============
|
|
|
|
*/
|
2023-11-06 18:08:21 +01:00
|
|
|
dtikianim_t *TIKI_RegisterTikiAnim(const char *path)
|
2016-03-27 11:49:47 +02:00
|
|
|
{
|
2023-11-06 18:08:21 +01:00
|
|
|
return TIKI_RegisterTikiAnimFlags(path, qfalse);
|
2016-03-27 11:49:47 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
===============
|
|
|
|
TIKI_RegisterTikiFlags
|
|
|
|
===============
|
|
|
|
*/
|
2023-11-06 18:08:21 +01:00
|
|
|
dtiki_t *TIKI_RegisterTikiFlags(const char *path, qboolean use)
|
2016-03-27 11:49:47 +02:00
|
|
|
{
|
2023-11-06 18:08:21 +01:00
|
|
|
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;
|
2016-03-27 11:49:47 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
===============
|
|
|
|
TIKI_RegisterTiki
|
|
|
|
===============
|
|
|
|
*/
|
2023-11-06 18:08:21 +01:00
|
|
|
dtiki_t *TIKI_RegisterTiki(const char *path)
|
2016-03-27 11:49:47 +02:00
|
|
|
{
|
2023-11-06 18:08:21 +01:00
|
|
|
return TIKI_RegisterTikiFlags(path, qfalse);
|
2016-03-27 11:49:47 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
===============
|
|
|
|
TIKI_FreeAll
|
|
|
|
===============
|
|
|
|
*/
|
|
|
|
void TIKI_FreeAll()
|
|
|
|
{
|
2023-11-06 18:08:21 +01:00
|
|
|
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();
|
|
|
|
/*
|
2016-03-27 11:49:47 +02:00
|
|
|
if( tiki->a->m_aliases )
|
|
|
|
{
|
|
|
|
TIKI_Free( tiki->a->m_aliases );
|
|
|
|
tiki->a->m_aliases = NULL;
|
|
|
|
tiki->a->num_anims = 0;
|
|
|
|
}
|
2016-08-13 18:32:13 +02:00
|
|
|
*/
|
2016-03-27 11:49:47 +02:00
|
|
|
|
2023-11-06 18:08:21 +01:00
|
|
|
TIKI_Free(tiki);
|
|
|
|
}
|
2016-03-27 11:49:47 +02:00
|
|
|
|
2023-11-06 18:08:21 +01:00
|
|
|
tikicache->clear();
|
|
|
|
}
|
2016-03-27 11:49:47 +02:00
|
|
|
|
2023-11-06 18:08:21 +01:00
|
|
|
if (tikianimcache) {
|
|
|
|
con_map_enum<pchar, dtikianim_t *> en = *tikianimcache;
|
2016-03-27 11:49:47 +02:00
|
|
|
|
2023-11-06 18:08:21 +01:00
|
|
|
for (entryanim = en.NextValue(); entryanim != NULL; entryanim = en.NextValue()) {
|
|
|
|
tikianim = *entryanim;
|
2016-03-27 11:49:47 +02:00
|
|
|
|
2023-11-06 18:08:21 +01:00
|
|
|
TIKI_RemoveTiki(tikianim);
|
2016-08-13 18:32:13 +02:00
|
|
|
|
2023-11-06 18:08:21 +01:00
|
|
|
if (tikianim->m_aliases) {
|
|
|
|
TIKI_Free(tikianim->m_aliases);
|
|
|
|
tikianim->m_aliases = NULL;
|
|
|
|
tikianim->num_anims = 0;
|
|
|
|
}
|
2016-08-13 18:32:13 +02:00
|
|
|
|
2023-11-06 18:08:21 +01:00
|
|
|
TIKI_Free(tikianim);
|
|
|
|
}
|
2016-03-27 11:49:47 +02:00
|
|
|
|
2023-11-06 18:08:21 +01:00
|
|
|
tikianimcache->clear();
|
|
|
|
}
|
2016-03-27 11:49:47 +02:00
|
|
|
|
2023-11-06 18:08:21 +01:00
|
|
|
tiki_loading = true;
|
|
|
|
if (skelcache) {
|
|
|
|
for (i = 0; i < cache_maxskel; i++) {
|
|
|
|
if (skelcache->skel) {
|
|
|
|
TIKI_FreeSkel(i);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2016-03-27 11:49:47 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
===============
|
|
|
|
TIKI_GetSkeletor
|
|
|
|
===============
|
|
|
|
*/
|
|
|
|
static qboolean tiki_started;
|
|
|
|
|
2023-11-06 18:08:21 +01:00
|
|
|
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;
|
2016-03-27 11:49:47 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
===============
|
|
|
|
TIKI_DeleteSkeletor
|
|
|
|
===============
|
|
|
|
*/
|
2023-11-06 18:08:21 +01:00
|
|
|
static void TIKI_DeleteSkeletor(int entnum)
|
2016-03-27 11:49:47 +02:00
|
|
|
{
|
2023-11-06 18:08:21 +01:00
|
|
|
skeletor_c *skel;
|
|
|
|
|
|
|
|
if (entnum == ENTITYNUM_NONE) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
skel = skel_entity_cache[entnum];
|
|
|
|
if (skel) {
|
|
|
|
delete skel;
|
|
|
|
skel_entity_cache[entnum] = 0;
|
|
|
|
}
|
2016-03-27 11:49:47 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
===============
|
|
|
|
TIKI_Begin
|
|
|
|
===============
|
|
|
|
*/
|
2023-11-06 18:08:21 +01:00
|
|
|
void TIKI_Begin(void)
|
2016-03-27 11:49:47 +02:00
|
|
|
{
|
2023-11-06 18:08:21 +01:00
|
|
|
int i;
|
2016-03-27 11:49:47 +02:00
|
|
|
|
2023-11-06 18:08:21 +01:00
|
|
|
for (i = 0; i < TIKI_MAX_SKELCACHE; i++) {
|
|
|
|
skel_entity_cache[i] = 0;
|
|
|
|
}
|
2016-03-27 11:49:47 +02:00
|
|
|
|
2023-11-06 18:08:21 +01:00
|
|
|
tiki_started = true;
|
2016-03-27 11:49:47 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
===============
|
|
|
|
TIKI_End
|
|
|
|
===============
|
|
|
|
*/
|
2023-11-06 18:08:21 +01:00
|
|
|
void TIKI_End(void)
|
2016-03-27 11:49:47 +02:00
|
|
|
{
|
2023-11-06 18:08:21 +01:00
|
|
|
int i;
|
2016-03-27 11:49:47 +02:00
|
|
|
|
2023-11-06 18:08:21 +01:00
|
|
|
for (i = 0; i < TIKI_MAX_SKELCACHE; i++) {
|
|
|
|
TIKI_DeleteSkeletor(i);
|
|
|
|
}
|
2016-03-27 11:49:47 +02:00
|
|
|
|
2023-11-06 18:08:21 +01:00
|
|
|
tiki_started = false;
|
2016-03-27 11:49:47 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
===============
|
|
|
|
TIKI_FinishLoad
|
|
|
|
===============
|
|
|
|
*/
|
2023-11-06 18:08:21 +01:00
|
|
|
void TIKI_FinishLoad(void)
|
2016-03-27 11:49:47 +02:00
|
|
|
{
|
2023-11-06 18:08:21 +01:00
|
|
|
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);
|
|
|
|
}
|
|
|
|
}
|
2016-03-27 11:49:47 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
===============
|
|
|
|
TIKI_FreeImages
|
|
|
|
===============
|
|
|
|
*/
|
2023-11-06 18:08:21 +01:00
|
|
|
void TIKI_FreeImages(void)
|
2016-03-27 11:49:47 +02:00
|
|
|
{
|
2023-11-06 18:08:21 +01:00
|
|
|
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;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2016-03-27 11:49:47 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
===============
|
|
|
|
TIKI_TikiAnimList_f
|
|
|
|
===============
|
|
|
|
*/
|
2023-11-06 18:08:21 +01:00
|
|
|
void TIKI_TikiAnimList_f(void)
|
2016-03-27 11:49:47 +02:00
|
|
|
{
|
2023-11-06 18:08:21 +01:00
|
|
|
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);
|
|
|
|
}
|
|
|
|
}
|
2016-03-27 11:49:47 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
===============
|
|
|
|
TIKI_TikiList_f
|
|
|
|
===============
|
|
|
|
*/
|
2023-11-06 18:08:21 +01:00
|
|
|
void TIKI_TikiList_f(void)
|
2016-03-27 11:49:47 +02:00
|
|
|
{
|
2023-11-06 18:08:21 +01:00
|
|
|
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);
|
|
|
|
}
|
|
|
|
}
|
2016-03-27 11:49:47 +02:00
|
|
|
}
|