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
ani_texture.cpp
Go to the documentation of this file.
1 #include "cmd/unit_generic.h"
2 #include "ani_texture.h"
3 #include "audiolib.h"
4 
5 #include <vector>
6 #include <stdio.h>
7 #include <stdlib.h>
8 #include "lin_time.h"
9 #include "vegastrike.h"
10 #include "vsfilesystem.h"
11 #include "vs_globals.h"
12 #include "vs_random.h"
13 #include "../gldrv/gl_globals.h"
14 #include <set>
15 #include <math.h>
16 
17 using std::set;
18 static set< AnimatedTexture* >anis;
19 
20 static inline unsigned int intmin( unsigned int a, unsigned int b )
21 {
22  return a < b ? a : b;
23 }
24 
25 static inline unsigned int intmax( unsigned int a, unsigned int b )
26 {
27  return a < b ? b : a;
28 }
29 
30 static enum ADDRESSMODE parseAddressMode( const string &addrmodestr, ADDRESSMODE defaultAddressMode )
31 {
32  enum ADDRESSMODE addrmode = defaultAddressMode;
33  if (addrmodestr == "wrap")
34  addrmode = WRAP;
35 
36  else if (addrmodestr == "mirror")
37  addrmode = MIRROR;
38 
39  else if (addrmodestr == "clamp")
40  addrmode = CLAMP;
41 
42  else if (addrmodestr == "border")
43  addrmode = BORDER;
44  return addrmode;
45 }
46 
47 static void ActivateWhite( int stage )
48 {
49  static Texture *white = new Texture( "white.bmp", 0, MIPMAP, TEXTURE2D, TEXTURE_2D, 1 );
50  if ( white->LoadSuccess() )
51  white->MakeActive( stage );
52 }
53 
54 void AnimatedTexture::MakeActive( int stage, int pass )
55 {
56  // Set active frame and texture coordinates
57  if (timeperframe && !vidSource) {
58  unsigned int numframes = numFrames();
59  unsigned int active = ( (unsigned int) (curtime/timeperframe) );
60  if ( GetLoop() )
61  active %= numframes;
62 
63  else
64  active = intmin( active, numframes-1 );
65  unsigned int nextactive = ( GetLoopInterp() ? ( (active+1)%numframes ) : intmin( active+1, numframes-1 ) );
66  float fraction = (curtime/timeperframe)-(unsigned int) (curtime/timeperframe);
67  if (fraction < 0) fraction += 1.0f;
68  this->active = active;
69  this->nextactive = nextactive;
70  this->active_fraction = fraction;
71  if (!vidMode) {
72  if ( GetInterpolateTCoord() && (active != nextactive) ) {
73  if (Decal && Decal[active] && Decal[nextactive]) {
74  this->maxtcoord = (1-fraction)*Decal[active]->maxtcoord+fraction*Decal[nextactive]->maxtcoord;
75  this->mintcoord = (1-fraction)*Decal[active]->mintcoord+fraction*Decal[nextactive]->mintcoord;
76  }
77  } else if (Decal && Decal[active]) {
78  this->maxtcoord = Decal[active]->maxtcoord;
79  this->mintcoord = Decal[active]->mintcoord;
80  }
81  } else {
82  if ( GetInterpolateTCoord() && (active != nextactive) ) {
83  if ( frames_maxtc.size() < intmax( active, nextactive ) ) {
84  this->maxtcoord = (1-fraction)*frames_maxtc[active]+fraction*frames_maxtc[nextactive];
85  this->mintcoord = (1-fraction)*frames_mintc[active]+fraction*frames_mintc[nextactive];
86  }
87  } else if ( active < frames_maxtc.size() ) {
88  this->maxtcoord = frames_maxtc[active];
89  this->mintcoord = frames_mintc[active];
90  }
91  }
92  active = ( (unsigned int) (curtime/timeperframe) )%numframes;
93  }
94 
95  // Effectively activate texture units
96  switch (pass)
97  {
98  case 0:
99  if (!vidMode) {
100  if ( GetInterpolateFrames() && (active != nextactive) ) {
101  if ( gl_options.Multitexture && ( (stage+1) < static_cast<int>(gl_options.Multitexture) ) ) {
102  if (Decal && Decal[nextactive%numframes])
103  Decal[nextactive%numframes]->MakeActive( stage+1 );
104 
105  else
106  ActivateWhite( stage+1 );
108  if (Decal && Decal[active%numframes])
109  Decal[active%numframes]->MakeActive( stage );
110 
111  else
112  ActivateWhite( stage );
113  //GFXTextureEnv(stage,GFXMODULATETEXTURE);
114  } else {
115  if (Decal && Decal[active%numframes])
116  Decal[active%numframes]->MakeActive( stage );
117 
118  else
119  ActivateWhite( stage );
120  multipass_interp_basecolor = GFXColorf();
121  GFXColor color = multipass_interp_basecolor;
122  color.r *= (1.0-active_fraction);
123  color.g *= (1.0-active_fraction);
124  color.b *= (1.0-active_fraction);
125  GFXColorf( color );
126  //GFXTextureEnv(stage,GFXMODULATETEXTURE);
127  }
128  } else {
129  if (Decal && Decal[active%numframes])
130  Decal[active%numframes]->MakeActive( stage );
131 
132  else
133  ActivateWhite( stage );
134  }
135  } else if (!vidSource) {
136  //No frame interpolation anything supported
137  if (Decal && *Decal) {
138  if (active != activebound)
140  (*Decal)->MakeActive( stage );
141  }
142  } else {
143  try {
144  //vidSource leaves frame data in its framebuffer, and our image data is initialized
145  //to point to that framebuffer, so all we need to do is transfer it to the GL.
146  if ( vidSource->seek( curtime ) ) {
147  //Override compression options temporarily
148  //NOTE: This is ugly, but otherwise we would have to hack Texture way too much,
149  //or double the code. Let's use this then.
150  int ocompression = gl_options.compression;
152 
153  VSFileSystem::vs_dprintf( 1, "Transferring video frame\n" );
154  Transfer( 65535, GFXFALSE );
155 
156  gl_options.compression = ocompression;
157  }
158  }
159  catch (::VidFile::EndOfStreamException e) {
160  if (GetLoop() && curtime > 0) {
161  setTime( 0 );
162  MakeActive( stage, pass );
163  return;
164  } else {
165  done = true;
166  }
167  }
168  catch (::VidFile::Exception e) {
169  VSFileSystem::vs_dprintf( 1, "\nVidFile exception: %s\n", e.what() );
170  }
171  Texture::MakeActive( stage, pass );
172  }
173  break;
174  case 1:
175  if ( !vidMode && GetInterpolateFrames() && (active != nextactive)
176  && !( gl_options.Multitexture && ( (stage+1) < static_cast<int>(gl_options.Multitexture) ) ) ) {
177  if (Decal && Decal[nextactive%numframes])
178  Decal[nextactive%numframes]->MakeActive( stage );
179 
180  else
181  ActivateWhite( stage );
182  GFXColor color = multipass_interp_basecolor;
183  color.r *= active_fraction;
184  color.g *= active_fraction;
185  color.b *= active_fraction;
186  GFXColorf( color );
187  //GFXTextureEnv(stage,GFXMODULATETEXTURE);
188  } else {ActivateWhite( stage ); } break;
189  }
190 }
191 
192 bool AnimatedTexture::SetupPass( int pass, int stage, const enum BLENDFUNC src, const enum BLENDFUNC dst )
193 {
194  switch (pass)
195  {
196  case -1:
197  if ( !vidMode && GetInterpolateFrames() ) {
198  if ( !( gl_options.Multitexture && ( (stage+1) < static_cast<int>(gl_options.Multitexture) ) ) )
199  GFXColorf( multipass_interp_basecolor ); //Restore old color
200  else
201  //GFXTextureEnv(texstage,GFXMODULATETEXTURE); //Most expect this
202  GFXTextureEnv( stage+1, GFXADDTEXTURE ); //Most expect this
203  }
204  return true;
205 
206  default:
207  //Hey! Nothing to do! Yippie!
208  return true;
209  }
210 }
211 
213 {
214  for (set< AnimatedTexture* >::iterator iter = anis.begin(); iter != anis.end(); iter++)
215  (*iter)->physicsactive -= SIMULATION_ATOM;
216 }
217 
219 {
220  double elapsed = GetElapsedTime();
221  double realtime = realTime();
222  for (set< AnimatedTexture* >::iterator iter = anis.begin(); iter != anis.end(); iter++) {
223  AnimatedTexture *ani = *iter;
224  if (ani->options & optSoundTiming) {
225  // lazy init
226  if (ani->lastrealtime == 0)
227  ani->lastrealtime = realtime;
228 
229  // de-jitter, playtime reporting tends to have some jitter
230  double newcurtime = ani->GetTimeSource()->getPlayingTime();
231  double delta = realtime - ani->lastrealtime;
232  double drift = newcurtime - ani->lastcurtime - delta;
233  if (fabs(drift) > 1.0) {
234  ani->lastcurtime = newcurtime - delta;
235  ani->lastrealtime = realtime;
236  } else if (fabs(drift) > 0.2) {
237  double catchup = drift * ((delta > 0.5) ? 0.5 : delta);
238  ani->lastcurtime += catchup;
239  ani->lastrealtime = realtime;
240  }
241  ani->setTime(ani->lastcurtime + delta);
242  } else {
243  ani->setTime( ani->curTime()+elapsed );
244  }
245  }
246 }
247 
249 {
250  //return physicsactive<0;
251  //Explosions aren't working right, and this would fix them.
252  //I don't see the reason for using physics frames as reference, all AnimatedTextures
253  //I've seen are gaphic-only entities (bolts use their own time-keeping system, for instance)
254  //If I'm wrong, and the above line is crucial, well... feel free to fix it.
255  return vidSource ? done : curtime >= numframes*timeperframe;
256 }
257 
258 void AnimatedTexture::setTime( double tim )
259 {
260  curtime = tim;
261 }
262 
263 using namespace VSFileSystem;
264 
265 AnimatedTexture::AnimatedTexture( const char *file, int stage, enum FILTER imm, bool detailtex )
266 {
267  AniInit();
268  VSFile f;
269  VSError err = f.OpenReadOnly( file, AnimFile );
270  //bool setdir=false;
271  if (err <= Ok) {
272  float width, height;
273  f.Fscanf( "%f %f", &width, &height ); //it's actually an animation in global animation shares
274  //setdir=true;
275  }
276  if (err <= Ok) {
277  Load( f, stage, imm, detailtex );
278  f.Close();
279  } else {
280  loadSuccess = false;
281  /*
282  * if (setdir) {
283  * VSFileSystem::vs_resetdir();
284  * }
285  */
286  }
287 }
288 
289 void AnimatedTexture::AniInit()
290 {
292 
293  Decal = NULL;
294  activebound = -1;
295  physicsactive = 0;
296  loadSuccess = false;
297  vidMode = false;
298  detailTex = false;
299  ismipmapped = BILINEAR;
300  texstage = 0;
301  vidSource = 0;
302 
303  options = optLoop;
304 
305  defaultAddressMode = DEFAULT_ADDRESS_MODE;
306 
307  numframes = 1;
308  timeperframe = 1;
309  active = 0;
310  nextactive = 0;
311  active_fraction = 0;
312  curtime = lastcurtime = lastrealtime = 0;
313  constframerate = true;
314  done = false;
315 }
316 //AnimatedTexture::AnimatedTexture (FILE * fp, int stage, enum FILTER imm, bool detailtex){
317 //AniInit();
318 //if (fp)
319 //Load (fp,stage,imm,detailtex);
320 //}
321 
322 AnimatedTexture::AnimatedTexture( VSFileSystem::VSFile &fp, int stage, enum FILTER imm, bool detailtex )
323 {
324  AniInit();
325  Load( fp, stage, imm, detailtex );
326 }
327 
328 AnimatedTexture::AnimatedTexture( int stage, enum FILTER imm, bool detailtex ) :
329  Texture( stage, imm )
330 {
331  AniInit();
332 }
333 
335 {
336  return Decal ? Decal[active]->Original() : this;
337 }
338 
340 {
341  return Decal ? Decal[active]->Original() : this;
342 }
343 
345 {
346  AnimatedTexture *retval = new AnimatedTexture();
347  if (Decal) {
348  *retval = *this;
349  int nf = vidMode ? 1 : numframes;
350  retval->Decal = new Texture*[nf];
351  for (int i = 0; i < nf; i++)
352  retval->Decal[i] = Decal[i]->Clone();
353  } else if (vidSource) {
354  *retval = *this;
355  }
356  if (vidSource) {
357  retval->name = -1;
358  retval->bound = false;
360  f.OpenReadOnly( wrapper_file_path, wrapper_file_type );
361  retval->LoadVideoSource( f );
362  } else if (Decal) {
363  //LoadVideoSource adds to anis, otherwise we'll have to add ourselves
364  anis.insert( retval );
365  }
366  return retval;
367 }
368 
370 {
371  Destroy();
372  data = NULL;
373  active = 0;
374  palette = NULL;
375 }
376 
378 {
379  AniInit();
380 }
381 
383 {
384  anis.erase( this );
385  if (vidSource) {
386  delete vidSource;
387  vidSource = 0;
388  }
389  if (Decal) {
390  int i, nf;
391  nf = vidMode ? 1 : numframes;
392  for (i = 0; i < nf; i++)
393  delete Decal[i];
394  delete[] Decal;
395  Decal = NULL;
396  }
397 }
398 
400 {
401  curtime = 0;
402  active = 0;
403  activebound = -1;
404  img_sides = SIDE_SINGLE;
405  physicsactive = numframes*timeperframe;
406  done = false;
407 }
408 
409 static void alltrim( string &str )
410 {
411  string::size_type ltrim = str.find_first_not_of( " \t\r\n" );
412  string::size_type rtrim = str.find_last_not_of( " \t\r\n" );
413  if (rtrim != string::npos) str.resize( rtrim+1 );
414  str.erase( 0, ltrim );
415 }
416 
417 static void alltrim( char *_str )
418 {
419  string str = _str;
420  alltrim( str );
421  strcpy( _str, str.c_str() );
422 }
423 
424 void AnimatedTexture::Load( VSFileSystem::VSFile &f, int stage, enum FILTER ismipmapped, bool detailtex )
425 {
426  curtime = 0;
427  frames.clear();
428  frames_maxtc.clear();
429  frames_mintc.clear();
430  if (f.GetType() == VSFileSystem::VideoFile)
431  LoadVideoSource( f );
432  else
433  LoadAni( f, stage, ismipmapped, detailtex );
434 }
435 
437 {
438  wrapper_file_path = f.GetFilename();
439  wrapper_file_type = f.GetType();
440  f.Close();
441 
442  Reset();
443 
444  vidMode = true;
445 
446  try {
447  vidSource = new::VidFile();
448  vidSource->open( wrapper_file_path, gl_options.max_movie_dimension, gl_options.pot_video_textures );
449 
450  physicsactive = vidSource->getDuration();
451  timeperframe = 1.0/vidSource->getFrameRate();
452  numframes = (unsigned int) (physicsactive*timeperframe);
453 
454  loadSuccess = true;
455  }
456  catch (::VidFile::Exception e) {
457  loadSuccess = false;
458  }
459  if (loadSuccess) {
460  sizeX = vidSource->getWidth();
461  sizeY = vidSource->getHeight();
462  mode = _24BIT;
463  data = (unsigned char*) vidSource->getFrameBuffer();
464  if ((ismipmapped == BILINEAR || ismipmapped == NEAREST) && gl_options.rect_textures) {
467  }
468 
469  Bind( 65535, GFXFALSE );
470 
471  maxtcoord.x = sizeX-0.5f;
472  maxtcoord.y = sizeY-0.5f;
473  mintcoord.x = 0.5f;
474  mintcoord.y = 0.5f;
475 
477  maxtcoord.x /= sizeX;
478  maxtcoord.y /= sizeY;
479  mintcoord.x /= sizeX;
480  mintcoord.y /= sizeY;
481  }
482 
483  anis.insert( this );
484  }
485 }
486 
488  int stage,
489  enum FILTER ismipmapped,
490  bool detailtex )
491 {
492  AnimatedTexture *rv = new AnimatedTexture( stage, ismipmapped, detailtex );
494  VSError err = f.OpenReadOnly( fname, VSFileSystem::VideoFile );
495  if (err <= Ok)
496  rv->LoadVideoSource( f );
497  else
498  fprintf( stderr, "CreateVideoTexture could not find %s\n", fname.c_str() );
499 
500  // Videos usually don't want to be looped, so set non-looping as default
501  rv->SetLoop(false);
502 
503  return rv;
504 }
505 
506 void AnimatedTexture::LoadAni( VSFileSystem::VSFile &f, int stage, enum FILTER ismipmapped, bool detailtex )
507 {
508  char options[1024];
509  f.Fscanf( "%d %f", &numframes, &timeperframe );
510  f.ReadLine( options, sizeof (options)-sizeof (*options) );
511  options[sizeof (options)/sizeof (*options)-1] = 0;
512  alltrim( options );
513 
514  Reset();
515 
516  vidMode = XMLSupport::parse_option_ispresent( options, "video" );
517  SetInterpolateFrames( XMLSupport::parse_option_ispresent( options, "interpolateFrames" ) );
518  SetInterpolateTCoord( XMLSupport::parse_option_ispresent( options, "interpolateTCoord" ) );
519  if ( XMLSupport::parse_option_ispresent( options, "forceLoopInterp" ) )
520  SetLoopInterp( true );
521 
522  else if ( XMLSupport::parse_option_ispresent( options, "forceNoLoopInterp" ) )
523  SetLoopInterp( false );
524  if ( XMLSupport::parse_option_ispresent( options, "forceLoop" ) )
525  SetLoop( true );
526 
527  else if ( XMLSupport::parse_option_ispresent( options, "forceNoLoop" ) )
528  SetLoop( false );
529  if ( XMLSupport::parse_option_ispresent( options, "startRandom" ) ) {
530  int curf = vsrandom.genrand_int32()%numframes;
531  setTime( (0.00001+curf)*timeperframe );
532  }
533  string addrmodestr = XMLSupport::parse_option_value( options, "addressMode", "" );
534  defaultAddressMode = parseAddressMode( addrmodestr, DEFAULT_ADDRESS_MODE );
535 
536  string defms = XMLSupport::parse_option_value( options, "mins", "0" );
537  string defmt = XMLSupport::parse_option_value( options, "mint", "0" );
538  string defmr = XMLSupport::parse_option_value( options, "minr", "0" );
539  string defMs = XMLSupport::parse_option_value( options, "maxs", "1" );
540  string defMt = XMLSupport::parse_option_value( options, "maxt", "1" );
541  string defMr = XMLSupport::parse_option_value( options, "maxr", "1" );
542 
543  int midframe; //FIXME midframe not initialized by all paths below
544  midframe = 0; //FIXME this line temporarily added by chuck_starchaser
545  bool loadall;
546  if (!vidMode)
547  loadall = !( g_game.use_animations == 0 || (g_game.use_animations != 0 && g_game.use_textures == 0) );
548 
549  else
550  loadall = !( g_game.use_videos == 0 || (g_game.use_videos != 0 && g_game.use_textures == 0) );
551  if (!loadall) {
553  midframe = numframes/2;
554  numframes = 1;
555  } //Added by Klauss
556 
557  active = 0;
558  int nf = (vidMode ? 1 : numframes);
559  Decal = new Texture*[nf];
560  if (vidMode) Decal[0] = new Texture;
561  char temp[512] = "white.bmp";
562  char file[512] = "white.bmp";
563  char alp[512] = "white.bmp";
564  char opt[512] = "";
565  int i = 0, j = 0;
566  for (; i < static_cast<int>(numframes); i++)
567  if ( loadall || (i == midframe) ) { //FIXME midframe used without guaranteed initialization
568  //if() added by Klauss
569  int numgets = 0;
570  while ( numgets <= 0 && !f.Eof() ) {
571  if (f.ReadLine( temp, 511 ) == Ok) {
572  temp[511] = '\0';
573  file[0] = 'z';
574  file[1] = '\0';
575  alp[0] = 'z';
576  alp[1] = '\0'; //windows crashes on null
577  opt[0] = 'z';
578  opt[1] = '\0';
579 
580  numgets = sscanf( temp, "%s %s %[^\r\n]", file, alp, opt );
581  if ( (numgets < 2) || (strcmp( alp, "-" ) == 0) ) alp[0] = '\0';
582  alltrim( opt );
583  } else {break; }}
584  if (vidMode) {
585  frames.push_back( StringPool::Reference( string( temp ) ) );
586  frames_mintc.push_back( Vector(
589  XMLSupport::parse_float( XMLSupport::parse_option_value( opt, "minr", defmr ) ) ) );
590  frames_maxtc.push_back( Vector(
593  XMLSupport::parse_float( XMLSupport::parse_option_value( opt, "maxr", defMr ) ) ) );
594  } else {
596  "addressMode",
597  "" ), defaultAddressMode );
598  if (alp[0] != '\0') {
599  Decal[j++] =
600  new Texture( file,
601  alp,
602  stage,
603  ismipmapped,
604  TEXTURE2D,
605  TEXTURE_2D,
606  1,
607  0,
609  65536,
610  (detailtex ? GFXTRUE : GFXFALSE),
611  GFXFALSE,
612  addrmode );
613  } else {
614  Decal[j++] = new Texture( file,
615  stage,
616  ismipmapped,
617  TEXTURE2D,
618  TEXTURE_2D,
620  65536,
621  (detailtex ? GFXTRUE : GFXFALSE),
622  GFXFALSE,
623  addrmode );
624  }
625  if (Decal[j-1]) {
626  Decal[j-1]->mintcoord = Vector(
629  XMLSupport::parse_float( XMLSupport::parse_option_value( opt, "minr", defmr ) ) );
630  Decal[j-1]->maxtcoord = Vector(
633  XMLSupport::parse_float( XMLSupport::parse_option_value( opt, "maxr", defMr ) ) );
634  }
635  }
636  }
637  this->texstage = stage;
638  this->detailTex = detailtex;
639  this->ismipmapped = ismipmapped;
640  if (vidMode) {
641  wrapper_file_path = f.GetFilename();
642  wrapper_file_type = f.GetType();
643  }
644  original = NULL;
645  loadSuccess = true;
646 
647  anis.insert( this );
648 
649  //Needed - must do housekeeping, tcoord stuff and the like.
650  setTime( curtime );
651 }
652 
653 void AnimatedTexture::LoadFrame( int frame )
654 {
655  if ( !vidMode || (Decal == NULL) || (*Decal == NULL) ) return;
656  if ( (frame < 0) || (frame >= static_cast<int>(numframes)) ) return;
657  if ( (activebound >= 0) && (activebound < numframes) && (frames[frame] == frames[activebound]) ) return;
658  const char *temp = frames[frame].get().c_str();
659  char file[512] = "white.bmp";
660  char alp[512] = "white.bmp";
661  char opt[512] = "";
662  int numgets = 0;
663  numgets = sscanf( temp, "%s %s %[^\r\n]", file, alp, opt );
664  if ( (numgets < 2) || (strcmp( alp, "-" ) == 0) ) alp[0] = '\0';
665  string addrmodestr = XMLSupport::parse_option_value( opt, "addressMode", "" );
666  enum ADDRESSMODE addrmode = parseAddressMode( addrmodestr, defaultAddressMode );
667 
668  //Override compression options temporarily
669  //NOTE: This is ugly, but otherwise we would have to hack Texture way too much,
670  //or double the code. Let's use this then.
671  int ocompression = gl_options.compression;
673 
674  //Without this, VSFileSystem won't find the file -- ugly, but it's how it is.
675  VSFile f;
676  VSError err = f.OpenReadOnly( wrapper_file_path, wrapper_file_type );
677 
678  //Override mipmaping for video mode - too much overhead in generating the mipmamps.
679  enum FILTER ismip2 =
680  ( (ismipmapped == BILINEAR) || (ismipmapped == TRILINEAR) || (ismipmapped == MIPMAP) ) ? BILINEAR : NEAREST;
681  loadSuccess = true;
682  if (alp[0] != '\0') {
683  (*Decal)->Load( file,
684  alp,
685  texstage,
686  ismip2,
687  TEXTURE2D,
688  TEXTURE_2D,
689  1,
690  0,
692  65536,
693  (detailTex ? GFXTRUE : GFXFALSE),
694  GFXTRUE,
695  addrmode );
696  } else if (numgets == 1) {
697  (*Decal)->Load( file, texstage, ismip2, TEXTURE2D, TEXTURE_2D, (g_game.use_videos) ? GFXTRUE : GFXFALSE, 65536,
698  (detailTex ? GFXTRUE : GFXFALSE), GFXTRUE, addrmode );
699  } else {
700  loadSuccess = false;
701  }
702  if (err <= Ok) f.Close();
703  gl_options.compression = ocompression;
704 
705  original = NULL;
706  loadSuccess = loadSuccess && (*Decal)->LoadSuccess();
707  if (loadSuccess) activebound = frame;
708 }
709 
711 {
712  return loadSuccess != false;
713 }
714 
715 unsigned int AnimatedTexture::numLayers() const
716 {
718  && ( (texstage+1) < static_cast<int>(gl_options.Multitexture) ) )
719  return 2;
720 
721  else
722  return 1;
723 }
724 
725 unsigned int AnimatedTexture::numPasses() const
726 {
727  if ( GetInterpolateFrames() && (active != nextactive) ) {
728  if ( gl_options.Multitexture && ( (texstage+1) < static_cast<int>(gl_options.Multitexture) ) )
729  return 1;
730  else
731  return 2;
732  } else {
733  return 1;
734  }
735 }
736 
737 void AnimatedTexture::SetTimeSource( SharedPtr<Audio::Source> source )
738 {
739  timeSource = source;
740  if (source)
741  options |= optSoundTiming;
742 
743  else
744  options &= ~optSoundTiming;
745 }
746 
748 {
749  timeSource.reset();
750  options &= ~optSoundTiming;
751 }