Fix custom player skins for the sw renderers.

This commit is contained in:
Bill Currie 2012-01-23 23:38:32 +09:00
parent 1f3eaaf2e0
commit 19dc579a5a
3 changed files with 126 additions and 33 deletions

View file

@ -42,6 +42,13 @@
#define RSSHOT_WIDTH 320
#define RSSHOT_HEIGHT 200
// if more than 32 clients are to be supported, then this will need to be
// updated
#define MAX_TRANSLATIONS 32
#define PLAYER_WIDTH 296
#define PLAYER_HEIGHT 194
typedef struct skin_s {
const char *name;
qboolean valid; // the skin was found
@ -52,6 +59,7 @@ typedef struct skin_s {
} skin_t;
skin_t *Skin_SetColormap (skin_t *skin, int cmap);
skin_t *Skin_SetSkin (skin_t *skin, int cmap, const char *skinname);
void Skin_SetupSkin (skin_t *skin, int cmap);
void Skin_SetTranslation (int cmap, int top, int bottom);
void Skin_ProcessTranslation (int cmap, const byte *translation);

View file

@ -42,17 +42,25 @@ static __attribute__ ((used)) const char rcsid[] = "$Id$";
#include <stdlib.h>
#include "QF/hash.h"
#include "QF/image.h"
#include "QF/model.h"
#include "QF/pcx.h"
#include "QF/quakefs.h"
#include "QF/skin.h"
#include "QF/sys.h"
#include "QF/va.h"
#include "QF/GLSL/funcs.h"
// if more than 32 clients are to be supported, then this will need to be
// updated
#define MAX_TRANSLATIONS 32
typedef struct skinbank_s {
char *name;
tex_t *texels;
int users;
} skinbank_t;
static byte translations[MAX_TRANSLATIONS][VID_GRADES * 256];
static hashtab_t *skin_cache;
static skin_t *
new_skin (void)
@ -113,8 +121,110 @@ Skin_SetColormap (skin_t *skin, int cmap)
return skin;
}
skin_t *
Skin_SetSkin (skin_t *skin, int cmap, const char *skinname)
{
char *name = 0;
skinbank_t *sb = 0;
tex_t *tex = 0;
if (skinname) {
name = QFS_CompressPath (skinname);
QFS_StripExtension (name, name);
if (strchr (name, '.') || strchr (name, '/')) {
Sys_Printf ("Bad skin name: '%s'\n", skinname);
free (name);
name = 0;
}
}
do {
QFile *file;
byte *ipix, *opix;
int i;
tex_t *out;
if (!name)
break;
sb = Hash_Find (skin_cache, name);
if (sb) {
sb->users++;
tex = sb->texels;
break;
}
if (Hash_NumElements (skin_cache) >= MAX_CACHED_SKINS) {
Sys_Printf ("Too many skins\n");
free (name);
name = 0;
break;
}
QFS_FOpenFile (va ("skins/%s.pcx", name), &file);
if (!file) {
Sys_Printf ("Couldn't load skin %s\n", name);
free (name);
name = 0;
break;
}
tex = LoadPCX (file, 0, vid.palette);
Qclose (file);
if (!tex || tex->width > 320 || tex->height > 200) {
Sys_Printf ("Bad skin %s\n", name);
free (name);
name = 0;
tex = 0;
break;
}
out = malloc (field_offset (tex_t, data[PLAYER_WIDTH*PLAYER_HEIGHT]));
out->width = PLAYER_WIDTH;
out->height = PLAYER_HEIGHT;
out->format = tex_palette;
out->palette = vid.palette;
memset (out->data, 0, PLAYER_WIDTH * PLAYER_HEIGHT);
opix = out->data;
ipix = tex->data;
for (i = 0; i < out->height; i++) {
memcpy (opix, ipix, min (tex->width, out->width));
ipix += tex->width;
opix += out->width;
}
tex = out;
sb = malloc (sizeof (skinbank_t));
sb->texels = tex;
sb->name = name;
sb->users = 1;
Hash_Add (skin_cache, sb);
} while (0);
if (!skin)
skin = new_skin ();
skin->texels = tex;
skin->name = name;
Skin_SetupSkin (skin, cmap);
return skin;
}
static const char *
skin_getkey (void *sb, void *unused)
{
return ((skinbank_t *) sb)->name;
}
static void
skin_free (void *_sb, void *unused)
{
skinbank_t *sb = (skinbank_t *) _sb;
free (sb->name);
free (sb->texels);
free (sb);
}
void
Skin_Init (void)
{
skin_cache = Hash_NewTable (127, skin_getkey, skin_free, 0);
Skin_InitTranslations ();
}

View file

@ -208,7 +208,6 @@ CL_LinkPacketEntities (void)
entity_state_t *s1;
model_t *model;
packet_entities_t *pack;
//player_info_t *info;
pack = &cl.frames[cls.netchan.incoming_sequence &
UPDATE_MASK].packet_entities;
@ -244,26 +243,12 @@ CL_LinkPacketEntities (void)
// set colormap
if (s1->colormap && (s1->colormap <= MAX_CLIENTS)
&& cl.players[s1->colormap - 1].name[0]
&& !strcmp (ent->model->name, "progs/player.mdl")) {
&& cl.players[s1->colormap - 1].name[0]) {
ent->skin = Skin_SetColormap (ent->skin, s1->colormap);
//info = &cl.players[s1->colormap - 1];
} else {
ent->skin = Skin_SetColormap (ent->skin, 0);
//info = NULL;
}
#if 0 //XXX
if (info && info->skinname && !info->skin)
Skin_Find (info);
if (info && info->skin) {
ent->skin = Skin_NewTempSkin ();
if (ent->skin) {
CL_NewTranslation (s1->colormap - 1, ent->skin);
}
} else {
ent->skin = NULL;
}
#endif
// LordHavoc: cleaned up Endy's coding style, and fixed Endy's bugs
// Ender: Extend (Colormod) [QSG - Begin]
// N.B: All messy code below is the sole fault of LordHavoc and
@ -494,24 +479,14 @@ CL_LinkPlayers (void)
if (state->pls.modelindex == cl_playerindex) { //XXX
// use custom skin
#if 0
if (!info->skin)
Skin_Find (info);
if (info && info->skin) {
ent->skin = Skin_NewTempSkin ();
if (ent->skin) {
CL_NewTranslation (j, ent->skin);
}
} else {
ent->skin = NULL;
}
#endif
Skin_SetSkin (ent->skin, j + 1, info->skinname->value);
ent->min_light = min (cl.fbskins, cl_fb_players->value);
if (ent->min_light >= 1.0)
ent->fullbright = 1;
} else {
ent->skin = NULL;
Skin_SetSkin (ent->skin, j + 1, 0);
}
// stuff entity in map