openmohaa/code/tiki/tiki_cache.cpp

500 lines
11 KiB
C++
Raw Normal View History

2016-03-27 11:49:47 +02:00
/*
===========================================================================
Copyright (C) 2024 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;
2024-02-20 20:44:55 +01:00
static skeletor_c *skel_entity_cache[TIKI_MAX_ENTITY_CACHE];
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
Q_strncpyz(filename, path, sizeof(filename));
FS_CanonicalFilename(filename);
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];
2024-09-20 21:53:48 +02:00
Q_strncpyz(filename, path, sizeof(filename));
2023-11-06 18:08:21 +01:00
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_DPrintf("^~^~^ Add the following line to the *_precache.scr map script:\n");
Com_DPrintf("cache %s\n", filename);
2023-11-06 18:08:21 +01:00
}
(*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, "|");
}
2024-09-20 21:53:48 +02:00
Q_strncpyz(filename, name, sizeof(filename));
2023-11-06 18:08:21 +01:00
FS_CanonicalFilename(filename);
2024-09-20 21:53:48 +02:00
Q_strcat(full_filename, sizeof(full_filename), filename);
2023-11-06 18:08:21 +01:00
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();
// Fixed in OPM
// It's better to free aliases when actually clearing the anim cache
2023-11-06 18:08:21 +01:00
/*
if (tiki->a->m_aliases) {
TIKI_Free(tiki->a->m_aliases);
tiki->a->m_aliases = NULL;
tiki->a->num_anims = 0;
}
*/
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
// Fixed in OPM
// Each tikianim should free their aliases
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;
for (i = 0; i < cache_maxskel; i++) {
if (skelcache[i].skel) {
TIKI_FreeSkel(i);
}
2023-11-06 18:08:21 +01:00
}
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;
int i;
int index;
2023-11-06 18:08:21 +01:00
if (entnum == ENTITYNUM_NONE) {
if (!tiki->skeletor) {
tiki->skeletor = new skeletor_c(tiki);
}
skel = (skeletor_c *)tiki->skeletor;
} else {
2024-02-20 20:44:55 +01:00
// Added in 2.30
// Multiple caches per entity
for (i = 0; i < TIKI_MAX_ENTITY_CACHE_PER_ENT; i++) {
index = ((entnum % TIKI_MAX_ENTITIES) * TIKI_MAX_ENTITY_CACHE_PER_ENT) + i;
skel = skel_entity_cache[index];
if (!skel) {
break;
}
2023-11-06 18:08:21 +01:00
if (skel->m_Tiki == tiki) {
2024-02-20 20:44:55 +01:00
return skel;
2023-11-06 18:08:21 +01:00
}
2024-02-20 20:44:55 +01:00
}
if (i == TIKI_MAX_ENTITY_CACHE_PER_ENT) {
i = 0;
}
2023-11-06 18:08:21 +01:00
2024-02-20 20:44:55 +01:00
index = ((entnum % TIKI_MAX_ENTITIES) * TIKI_MAX_ENTITY_CACHE_PER_ENT) + i;
skel = skel_entity_cache[index];
2024-02-20 20:44:55 +01:00
if (skel) {
2023-11-06 18:08:21 +01:00
delete skel;
}
skel = new skeletor_c(tiki);
2024-02-20 20:44:55 +01:00
skel_entity_cache[index] = skel;
2023-11-06 18:08:21 +01:00
}
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;
int i;
2023-11-06 18:08:21 +01:00
if (entnum == ENTITYNUM_NONE) {
return;
}
2024-02-20 20:44:55 +01:00
for (i = 0; i < TIKI_MAX_ENTITY_CACHE_PER_ENT; i++) {
skel = skel_entity_cache[entnum * TIKI_MAX_ENTITY_CACHE_PER_ENT + i];
if (skel) {
delete skel;
}
2023-11-06 18:08:21 +01:00
}
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
2024-02-20 22:42:34 +01:00
for (i = 0; i < TIKI_MAX_ENTITY_CACHE; i++) {
2023-11-06 18:08:21 +01:00
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
2024-02-20 20:44:55 +01:00
for (i = 0; i < MAX_GENTITIES; i++) {
2023-11-06 18:08:21 +01:00
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
}