Vegastrike 0.5.1 rc1  1.0
Original sources for Vegastrike Evolved
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
sprite.cpp
Go to the documentation of this file.
1 /*
2  * Vega Strike
3  * Copyright (C) 2001-2002 Daniel Horn
4  *
5  * http://vegastrike.sourceforge.net/
6  *
7  * This program is free software; you can redistribute it and/or
8  * modify it under the terms of the GNU General Public License
9  * as published by the Free Software Foundation; either version 2
10  * of the License, or (at your option) any later version.
11  *
12  * This program 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 this program; if not, write to the Free Software
19  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
20  */
21 #include <stdlib.h>
22 #include <iostream>
23 #include "vsfilesystem.h"
24 #include "cmd/unit_generic.h"
25 #include "aux_texture.h"
26 #include "ani_texture.h"
27 #include "sprite.h"
28 #include "matrix.h"
29 #include "gfxlib.h"
30 #include "vegastrike.h"
31 #include "vs_globals.h"
32 #include "../gldrv/gl_globals.h"
33 #include <assert.h>
34 #include <math.h>
35 #include "gnuhash.h"
36 
37 #ifdef _WIN32
38 #include <direct.h>
39 #endif
40 
41 #ifndef M_PI_2
42 # define M_PI_2 (1.57079632679489661923)
43 #endif
44 
45 #include "audio/Types.h"
46 #include "audio/Source.h"
47 
48 using namespace VSFileSystem;
49 
50 typedef vsUMap< std::string, VSSprite* >VSSpriteCache;
52 
53 static std::pair< bool, VSSprite* >cacheLookup( const char *file )
54 {
55  std::string hashName = VSFileSystem::GetHashName( std::string( file ) );
56  VSSpriteCache::iterator it = sprite_cache.find( hashName );
57  if ( it != sprite_cache.end() )
58  return std::pair< bool, VSSprite* > ( true, it->second );
59  else
60  return std::pair< bool, VSSprite* > ( false, (VSSprite*)NULL );
61 }
62 
63 static void cacheInsert( const char *file, VSSprite *spr )
64 {
65  std::string hashName = VSFileSystem::GetHashName( std::string( file ) );
66  sprite_cache.insert( std::pair< std::string, VSSprite* > ( hashName, spr ) );
67 }
68 
69 VSSprite::VSSprite( Texture *_surface, float _xcenter, float _ycenter, float _width, float _height, float _s, float _t, bool _isAnimation ) :
70  xcenter( _xcenter )
71  , ycenter( _ycenter )
72  , widtho2( _width/2 )
73  , heighto2( _height/2 )
74  , maxs( _s )
75  , maxt( _t )
76  , rotation( 0 )
77  , isAnimation(_isAnimation)
78 {
79  surface = _surface;
80 }
81 
82 VSSprite::VSSprite( const VSSprite &source )
83 {
84  *this = source;
85  if (surface != NULL)
86  surface = surface->Clone();
87 }
88 
89 VSSprite::VSSprite( const char *file, enum FILTER texturefilter, GFXBOOL force )
90 {
91  VSCONSTRUCT2( 'S' )
92  xcenter = ycenter = 0;
93  widtho2 = heighto2 = 0;
94  rotation = 0;
95  surface = NULL;
96  maxs = maxt = 0;
97  isAnimation = false;
98 
99  //Check cache
100  {
101  std::pair< bool, VSSprite* >lkup = cacheLookup( file );
102  if (lkup.first) {
103  if (lkup.second) {
104  *this = *lkup.second;
105  if (surface != NULL)
106  surface = surface->Clone();
107  } else {
108  return;
109  }
110  }
111  }
112 
113  VSFile f;
114  VSError err = Unspecified;
115  if (file[0] != '\0')
116  err = f.OpenReadOnly( file, VSSpriteFile );
117  if (err <= Ok) {
118  char texture[127] = {0};
119  char texturea[127] = {0};
120  f.Fscanf( "%126s %126s", texture, texturea );
121  f.Fscanf( "%f %f", &widtho2, &heighto2 );
122  f.Fscanf( "%f %f", &xcenter, &ycenter );
123  texture[sizeof (texture)-sizeof (*texture)-1] = 0;
124  texturea[sizeof (texturea)-sizeof (*texturea)-1] = 0;
125 
126  widtho2 /= 2;
127  heighto2 /= -2;
128  surface = NULL;
129  if (g_game.use_sprites || force == GFXTRUE) {
130  int len = strlen( texture );
131  if (len > 4 && texture[len-1] == 'i' && texture[len-2] == 'n' && texture[len-3] == 'a' && texture[len-4] == '.') {
132  surface = new AnimatedTexture( f, 0, texturefilter, GFXFALSE );
133  isAnimation = true;
134  } else if (texturea[0] == '0') {
135  surface = new Texture( texture, 0, texturefilter, TEXTURE2D, TEXTURE_2D, GFXTRUE, 65536, GFXFALSE );
136  isAnimation = false;
137  } else {
138  surface = new Texture( texture,
139  texturea,
140  0,
141  texturefilter,
142  TEXTURE2D,
143  TEXTURE_2D,
144  1,
145  0,
146  GFXTRUE,
147  65536,
148  GFXFALSE );
149  isAnimation = false;
150  }
151  if ( !surface->LoadSuccess() ) {
152  delete surface;
153  surface = NULL;
154  VSSprite *newspr = new VSSprite();
155  *newspr = *this;
156  newspr->surface = NULL;
157  cacheInsert( file, newspr );
158  } else {
159  //Update cache
160  VSSprite *newspr = new VSSprite();
161  *newspr = *this;
162  newspr->surface = this->surface->Clone();
163  cacheInsert( file, newspr );
164  }
165  }
166  //Finally close file
167  f.Close();
168  } else {
169  cacheInsert( file, 0 ); //Mark bad file
170  widtho2 = heighto2 = 0;
171  xcenter = ycenter = 0;
172  }
173 }
174 
176 {
177  if ( !f->Valid() ) {
178  widtho2 = heighto2 = 0;
179  xcenter = ycenter = 0;
180  std::cerr<<"VSSprite::ReadTexture error : VSFile not valid"<<std::endl;
181  return;
182  }
183  surface = new Texture( f );
184 }
185 
187 {
189  if (surface != NULL)
190  delete surface;
191 }
192 
193 void VSSprite::SetST( const float s, const float t )
194 {
195  maxs = s;
196  maxt = t;
197 }
198 
199 void VSSprite::GetST( float &s, float &t )
200 {
201  s = maxs;
202  t = maxt;
203 }
204 
206 {
207  if (surface)
208  surface->setTime( newtime );
209 }
210 
211 void VSSprite::DrawHere( Vector &ll, Vector &lr, Vector &ur, Vector &ul )
212 {
213  if (rotation) {
214  const float cw = widtho2*cos( rotation );
215  const float sw = widtho2*sin( rotation );
216  const float ch = heighto2*cos( M_PI_2+rotation );
217  const float sh = heighto2*sin( M_PI_2+rotation );
218  const float wnew = cw+ch;
219  const float hnew = sw+sh;
220  ll = Vector( xcenter-wnew, ycenter+hnew, 0.00f );
221  lr = Vector( xcenter+wnew, ycenter+hnew, 0.00f );
222  ur = Vector( xcenter+wnew, ycenter-hnew, 0.00f );
223  ul = Vector( xcenter-wnew, ycenter-hnew, 0.00f );
224  } else {
225  ll = Vector( xcenter-widtho2, ycenter+heighto2, 0.00f );
226  lr = Vector( xcenter+widtho2, ycenter+heighto2, 0.00f );
227  ur = Vector( xcenter+widtho2, ycenter-heighto2, 0.00f );
228  ul = Vector( xcenter-widtho2, ycenter-heighto2, 0.00f );
229  }
230 }
231 
233 {
234  if (surface) {
235  //don't do anything if no surface
236  size_t lyr;
237  size_t numlayers = surface->numLayers();
238  bool multitex = (numlayers > 1);
239  int numpasses = surface->numPasses();
240  GFXDisable( CULLFACE );
241  Vector ll, lr, ur, ul;
242  DrawHere( ll, lr, ur, ul );
243  BLENDFUNC src, dst;
244  GFXGetBlendMode( src, dst );
245  for (lyr = 0; (lyr < gl_options.Multitexture) || (lyr < numlayers); lyr++) {
246  GFXToggleTexture( (lyr < numlayers), lyr, surface->texture_target );
247  if (lyr < numlayers) GFXTextureCoordGenMode( lyr, NO_GEN, NULL, NULL );
248  }
249  for (int pass = 0; pass < numpasses; pass++) {
250  if ( surface->SetupPass( pass, 0, src, dst ) ) {
251  surface->MakeActive( 0, pass );
252 
253  // Keep below MakeActive, AnimatedTexture only sets
254  // the final effective coordinates there.
255  float ms = surface->mintcoord.i, Ms = surface->maxtcoord.i;
256  float mt = surface->mintcoord.j, Mt = surface->maxtcoord.j;
257  ms = (Ms-ms)*maxs+ms;
258  mt = (Mt-mt)*maxt+mt;
259 
261  GFXBegin( GFXQUAD );
262  if (!multitex)
263  GFXTexCoord2f( ms, Mt );
264  else
265  GFXTexCoord4f( ms, Mt, ms, Mt );
266  GFXVertexf( ll );
267  if (!multitex)
268  GFXTexCoord2f( Ms, Mt );
269  else
270  GFXTexCoord4f( Ms, Mt, Ms, Mt );
271  GFXVertexf( lr );
272  if (!multitex)
273  GFXTexCoord2f( Ms, mt );
274  else
275  GFXTexCoord4f( Ms, mt, Ms, mt );
276  GFXVertexf( ur );
277  if (!multitex)
278  GFXTexCoord2f( ms, mt );
279  else
280  GFXTexCoord4f( ms, mt, ms, mt );
281  GFXVertexf( ul );
282  GFXEnd();
283  }
284  }
285  surface->SetupPass( -1, 0, src, dst );
286  for (lyr = 0; lyr < numlayers; lyr++)
287  GFXToggleTexture( false, lyr, surface->texture_target );
288  GFXEnable( CULLFACE );
289  }
290 }
291 
292 void VSSprite::SetPosition( const float &x1, const float &y1 )
293 {
294  xcenter = x1;
295  ycenter = y1;
296 }
297 
298 void VSSprite::GetPosition( float &x1, float &y1 )
299 {
300  x1 = xcenter;
301  y1 = ycenter;
302 }
303 
304 void VSSprite::SetSize( float x1, float y1 )
305 {
306  widtho2 = x1/2;
307  heighto2 = y1/2;
308 }
309 
310 void VSSprite::GetSize( float &x1, float &y1 )
311 {
312  x1 = widtho2*2;
313  y1 = heighto2*2;
314 }
315 
316 void VSSprite::SetRotation( const float &rot )
317 {
318  rotation = rot;
319 }
320 
321 void VSSprite::GetRotation( float &rot )
322 {
323  rot = rotation;
324 }
325 
326 void VSSprite::SetTimeSource( SharedPtr<Audio::Source> source )
327 {
328  if (isAnimation)
329  ( (AnimatedTexture*) surface )->SetTimeSource( source );
330 }
331 
332 SharedPtr<Audio::Source> VSSprite::GetTimeSource() const
333 {
334  if (isAnimation)
335  return ( (AnimatedTexture*) surface )->GetTimeSource();
336  else
337  return SharedPtr<Audio::Source>();
338 }
339 
341 {
342  if (isAnimation)
343  ( (AnimatedTexture*) surface )->ClearTimeSource();
344 }
345 
346 bool VSSprite::Done() const
347 {
348  if (isAnimation)
349  return ( (AnimatedTexture*) surface )->Done();
350  else
351  return false;
352 }
353 
355 {
356  if (isAnimation)
357  ( (AnimatedTexture*) surface )->Reset();
358 }
359 
361 {
362  return surface != NULL && surface->LoadSuccess();
363 }
364