]> git.xonotic.org Git - xonotic/netradiant.git/blob - plugins/imagehl/sprite.cpp
reformat code! now the code is only ugly on the *inside*
[xonotic/netradiant.git] / plugins / imagehl / sprite.cpp
1 /*
2    Copyright (C) 1999-2006 Id Software, Inc. and contributors.
3    For a list of contributors, see the accompanying CONTRIBUTORS file.
4
5    This file is part of GtkRadiant.
6
7    GtkRadiant is free software; you can redistribute it and/or modify
8    it under the terms of the GNU General Public License as published by
9    the Free Software Foundation; either version 2 of the License, or
10    (at your option) any later version.
11
12    GtkRadiant is distributed in the hope that it will be useful,
13    but WITHOUT ANY WARRANTY; without even the implied warranty of
14    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15    GNU General Public License for more details.
16
17    You should have received a copy of the GNU General Public License
18    along with GtkRadiant; if not, write to the Free Software
19    Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
20  */
21
22 // by Hydra - hydra@hydras-world.com
23
24 #include "sprite.h"
25
26 #include <stdlib.h>
27 #include <string.h>
28 #include <stdio.h>
29
30 typedef unsigned char byte;
31
32 #include "ifilesystem.h"
33
34 #include "imagelib.h"
35
36 /*
37    ============================================================================
38
39    IDSP IMAGE (.spr files)
40
41    Some code copied straight from the Q1 source, also used the HalfLife SDK as
42    a reference.
43
44    ============================================================================
45  */
46
47 typedef enum { ST_SYNC = 0, ST_RAND } synctype_t;
48 typedef enum { SPR_SINGLE = 0, SPR_GROUP } spriteframetype_t;
49
50 typedef struct dspriteheader_s {
51     int ident;
52     int version;
53 } dspriteheader_t;
54
55 // Quake1
56 typedef struct {
57     int type;
58     float boundingradius;
59     int width;
60     int height;
61     int numframes;
62     float beamlength;
63     synctype_t synctype;
64 } dspritev1_t;
65
66 // Halflife
67 typedef struct {
68     int type;
69     int texFormat;
70     float boundingradius;
71     int width;
72     int height;
73     int numframes;
74     float beamlength;
75     synctype_t synctype;
76 } dspritev2_t;
77
78 typedef struct {
79     int origin[2];
80     int width;
81     int height;
82 } dspriteframe_t;
83
84 typedef struct {
85     short type;
86 } dspriteframetype_t;
87
88 /*
89    typedef struct {
90    byte rgb[256][3];
91    } dpalette_t;
92  */
93
94 const int IDSPRITEHEADER = (('P' << 24) + ('S' << 16) + ('D' << 8) + 'I');
95 // little-endian "IDSP"
96
97 /*
98    =============
99    LoadIDSP
100    =============
101  */
102
103 Image *LoadIDSPBuff(byte *buffer)
104 {
105     byte *buf_p;
106     int columns, rows;
107     byte *pixbuf;
108
109     int row, column;
110     byte *palette;
111     unsigned char red, green, blue, alphabyte;
112
113     dspriteheader_t *header;
114     dspritev1_t *pinv1;
115     dspritev2_t *pinv2;
116     dspriteframetype_t *pframetype;
117     int version;
118     int numframes;
119     dspriteframe_t *spriteframe;
120
121     header = (dspriteheader_t *) buffer;
122
123     if (header->ident != IDSPRITEHEADER) {
124         globalErrorStream() << "WARNING: IDSP file has wrong header\n";
125         return 0;
126     }
127
128     version = header->version;
129     if (version != 1 && version != 2) {
130         globalErrorStream() << "WARNING: IDSP file has wrong version number "
131                 "(" << version << " should be 1 or 2)\n";
132         return 0;
133     }
134
135     // initialise variables depending on the sprite version.
136     switch (version) {
137         case 1:
138             pinv1 = (dspritev1_t *) (header + 1);
139             numframes = pinv1->numframes;
140             columns = pinv1->width;
141             rows = pinv1->height;
142             pframetype = (dspriteframetype_t *) (pinv1 + 1);
143             break;
144         case 2:
145             pinv2 = (dspritev2_t *) (header + 1);
146             numframes = pinv2->numframes;
147             columns = pinv2->width;
148             rows = pinv2->height;
149             pframetype = (dspriteframetype_t *) (pinv2 + 1);
150             break;
151         default:
152             globalErrorStream() << "WARNING: IDSP file has unsupported version\n";
153             return 0;
154     }
155     if (numframes > 1) {
156         globalErrorStream() << "WARNING: IDSP file has multiple frames, only the first frame will be used.\n";
157     }
158
159     // palette = buffer+mipdatasize+2;
160     // buf_p = buffer+lpMip->offsets[0];
161
162     RGBAImage *image = new RGBAImage(columns, rows);
163
164 #ifdef DEBUG
165     frametype = spriteframetype_t( pframetype->type );
166     if ( frametype == SPR_SINGLE ) {
167         globalOutputStream() << "Single Frame\n";
168     }
169     else if ( frametype == SPR_GROUP ) {
170         globalOutputStream() << "Group of Frames\n";
171     }
172     else
173     {
174         globalOutputStream() << "Bleh!\n"; // <-- we always get this, wtf!
175     }
176 #endif
177
178     palette = (byte *) (pframetype + 1);
179     spriteframe = (dspriteframe_t *) (palette + (256 * 3) + 4); // what are those 4 extra bytes ? what's missing ?
180     buf_p = (byte *) (spriteframe + 1);
181
182     for (row = 0; row < rows; row++) {
183         pixbuf = image->getRGBAPixels() + row * columns * 4;
184
185         for (column = 0; column < columns; column++) {
186             int palIndex;
187
188             palIndex = *buf_p++;
189
190             red = *(palette + (palIndex * 3));
191             green = *(palette + (palIndex * 3) + 1);
192             blue = *(palette + (palIndex * 3) + 2);
193
194             // HalfLife engine makes pixels that are BLUE transparent. (RGB = 0x0000FF)
195             // So show them that way in the editor.
196             if (blue == 0xff && red == 0x00 && green == 0x00) {
197                 alphabyte = 0xff; //FIXME: backwards? (so sprite models to render correctly)
198                 blue = 0x00; // don't set the resulting pixel to blue
199             } else {
200                 alphabyte = 0x00; //FIXME: backwards? (so sprite models to render correctly)
201             }
202
203             *pixbuf++ = red;
204             *pixbuf++ = green;
205             *pixbuf++ = blue;
206
207             *pixbuf++ = alphabyte;
208         }
209     }
210
211     return image;
212 }
213
214 Image *LoadIDSP(ArchiveFile &file)
215 {
216     ScopedArchiveBuffer buffer(file);
217     return LoadIDSPBuff(buffer.buffer);
218 }