WarpZones:
[divverent/darkplaces.git] / cl_dyntexture.c
1 // Andreas Kirsch 07
2
3 #include "quakedef.h"
4 #include "cl_dyntexture.h"
5
6 typedef struct dyntexture_s {
7         // everything after DYNAMIC_TEXTURE_PATH_PREFIX
8         char name[ MAX_QPATH + 32 ];
9         // texture pointer (points to r_texture_white at first)
10         rtexture_t *texture;
11 } dyntexture_t;
12
13 static dyntexture_t dyntextures[ MAX_DYNAMIC_TEXTURE_COUNT ];
14 static unsigned dyntexturecount;
15
16 #define DEFAULT_DYNTEXTURE r_texture_grey128
17
18 static dyntexture_t * cl_finddyntexture( const char *name, qboolean warnonfailure ) {
19         unsigned i;
20         dyntexture_t *dyntexture = NULL;
21
22         // sanity checks - make sure its actually a dynamic texture path
23         if( !name || !*name || strncmp( name, CLDYNTEXTUREPREFIX, sizeof( CLDYNTEXTUREPREFIX ) - 1 ) != 0 ) {
24                 // TODO: print a warning or something
25                 if (warnonfailure)
26                         Con_Printf( "cl_finddyntexture: Bad dynamic texture name '%s'\n", name );
27                 return NULL;
28         }
29
30         for( i = 0 ; i < dyntexturecount ; i++ ) {
31                 dyntexture = &dyntextures[ i ];
32                 if( dyntexture->name && strcmp( dyntexture->name, name ) == 0 ) {
33                         return dyntexture;
34                 }
35         }
36
37         if( dyntexturecount == MAX_DYNAMIC_TEXTURE_COUNT ) {
38                 // TODO: warn or expand the array, etc.
39                 return NULL;
40         }
41         dyntexture = &dyntextures[ dyntexturecount++ ];
42         strlcpy( dyntexture->name, name, sizeof( dyntexture->name ) );
43         dyntexture->texture = DEFAULT_DYNTEXTURE;
44         return dyntexture;
45 }
46
47 rtexture_t * CL_GetDynTexture( const char *name ) {
48         dyntexture_t *dyntexture = cl_finddyntexture( name, false );
49         if( dyntexture ) {
50                 return dyntexture->texture;
51         } else {
52                 return NULL;
53         }
54 }
55
56 void CL_LinkDynTexture( const char *name, rtexture_t *texture ) {
57         dyntexture_t *dyntexture;
58         cachepic_t *cachepic;
59         skinframe_t *skinframe;
60
61         dyntexture = cl_finddyntexture( name, true );
62         if( !dyntexture ) {
63                 Con_Printf( "CL_LinkDynTexture: internal error in cl_finddyntexture!\n" );
64                 return;
65         }
66         // TODO: assert dyntexture != NULL!
67         if( dyntexture->texture != texture ) {
68                 dyntexture->texture = texture;
69
70                 cachepic = Draw_CachePic_Flags( name, CACHEPICFLAG_NOTPERSISTENT );
71                 // TODO: assert cachepic and skinframe should be valid pointers...
72                 // TODO: assert cachepic->tex = dyntexture->texture
73                 cachepic->tex = texture;
74                 // update cachepic's size, too
75                 cachepic->width = R_TextureWidth( texture );
76                 cachepic->height = R_TextureHeight( texture );
77
78                 // update skinframes
79                 skinframe = NULL;
80                 while( (skinframe = R_SkinFrame_FindNextByName( skinframe, name )) != NULL ) {
81                         skinframe->base = texture;
82                         // simply reset the compare* attributes of skinframe
83                         skinframe->comparecrc = 0;
84                         skinframe->comparewidth = skinframe->compareheight = 0;
85                         // this is kind of hacky
86                 }
87         }
88 }
89
90 void CL_UnlinkDynTexture( const char *name ) {
91         CL_LinkDynTexture( name, DEFAULT_DYNTEXTURE );
92 }
93