Files
itgmania212121/stepmania/src/BGAnimationLayer.cpp
T

985 lines
28 KiB
C++
Raw Normal View History

2003-02-16 04:01:45 +00:00
#include "global.h"
2002-09-29 05:06:18 +00:00
/*
-----------------------------------------------------------------------------
Class: BGAnimation
Desc: Particles used initially for background effects
Copyright (c) 2001-2002 by the person(s) listed below. All rights reserved.
Ben Nordstrom
Chris Danford
-----------------------------------------------------------------------------
*/
#include "BGAnimationLayer.h"
#include "PrefsManager.h"
#include "GameState.h"
#include "IniFile.h"
#include "RageMath.h"
2003-02-14 06:49:01 +00:00
#include "SDL_utils.h"
#include <math.h>
2003-03-05 02:52:40 +00:00
#include "RageTimer.h"
#include "RageLog.h"
2003-03-10 05:07:00 +00:00
#include "song.h"
#include "ThemeManager.h"
2003-04-03 22:10:40 +00:00
#include "ActorCollision.h"
#include "Sprite.h"
#include "RageDisplay.h"
#include "ActorUtil.h"
#include "StepMania.h" // for HOOKS
#include "RageTextureManager.h"
2002-09-29 05:06:18 +00:00
2003-03-05 02:52:40 +00:00
const float PARTICLE_SPEED = 300;
2002-09-29 05:06:18 +00:00
const float SPIRAL_MAX_ZOOM = 2;
const float SPIRAL_MIN_ZOOM = 0.3f;
BGAnimationLayer::BGAnimationLayer()
{
2003-03-05 02:52:40 +00:00
Init();
}
BGAnimationLayer::~BGAnimationLayer()
{
Unload();
}
void BGAnimationLayer::Unload()
{
for( unsigned i=0; i<m_pActors.size(); i++ )
delete m_pActors[i];
m_pActors.clear();
}
2003-03-05 02:52:40 +00:00
void BGAnimationLayer::Init()
{
Unload();
m_fUpdateRate = 1;
m_fFOV = -1; // no change
m_bLighting = false;
2003-03-05 02:52:40 +00:00
// m_bCycleColor = false;
// m_bCycleAlpha = false;
// m_Effect = EFFECT_STRETCH_STILL;
for( int i=0; i<MAX_SPRITES; i++ )
m_vParticleVelocity[i] = RageVector3( 0, 0, 0 );
m_Type = TYPE_SPRITE;
m_fStretchTexCoordVelocityX = 0;
m_fStretchTexCoordVelocityY = 0;
m_fZoomMin = 1;
m_fZoomMax = 1;
m_fVelocityXMin = 10;
m_fVelocityXMax = 10;
m_fVelocityYMin = 0;
m_fVelocityYMax = 0;
m_fVelocityZMin = 0;
m_fVelocityZMax = 0;
m_fOverrideSpeed = 0;
m_iNumParticles = 10;
m_bParticlesBounce = false;
2003-03-09 09:25:32 +00:00
m_iNumTilesWide = -1;
m_iNumTilesHigh = -1;
2003-03-05 02:52:40 +00:00
m_fTilesStartX = 0;
m_fTilesStartY = 0;
2003-03-09 09:25:32 +00:00
m_fTilesSpacingX = -1;
m_fTilesSpacingY = -1;
2003-03-05 02:52:40 +00:00
m_fTileVelocityX = 0;
m_fTileVelocityY = 0;
/*
m_PosX = m_PosY = 0;
m_Zoom = 0;
m_Rot = 0;
m_ShowTime = 0;
m_HideTime = 0;
m_TweenStartTime = 0;
m_TweenX = m_TweenY = 0.0;
m_TweenSpeed = 0;
m_TweenState = 0;
m_TweenPassedX = m_TweenPassedY = 0;
2003-03-05 02:52:40 +00:00
*/
2002-09-29 05:06:18 +00:00
}
2003-01-09 04:47:23 +00:00
/* Static background layers are simple, uncomposited background images with nothing
* behind them. Since they have nothing behind them, they have no need for alpha,
* so turn that off. */
2002-09-29 05:06:18 +00:00
void BGAnimationLayer::LoadFromStaticGraphic( CString sPath )
{
2003-03-05 02:52:40 +00:00
Init();
2003-01-09 04:47:23 +00:00
RageTextureID ID(sPath);
ID.iAlphaBits = 0;
Sprite* pSprite = new Sprite;
pSprite->LoadBG( ID );
pSprite->StretchTo( RectI(SCREEN_LEFT,SCREEN_TOP,SCREEN_RIGHT,SCREEN_BOTTOM) );
m_pActors.push_back( pSprite );
2002-09-29 05:06:18 +00:00
}
void BGAnimationLayer::LoadFromMovie( CString sMoviePath )
2002-09-29 05:06:18 +00:00
{
2003-03-05 02:52:40 +00:00
Init();
Sprite* pSprite = new Sprite;
pSprite->LoadBG( sMoviePath );
pSprite->StretchTo( RectI(SCREEN_LEFT,SCREEN_TOP,SCREEN_RIGHT,SCREEN_BOTTOM) );
pSprite->GetTexture()->Play();
2003-02-14 06:49:01 +00:00
SDL_Delay( 50 ); // decode a frame so we don't see a black flash at the beginning
pSprite->GetTexture()->Pause();
m_pActors.push_back( pSprite );
2002-09-29 05:06:18 +00:00
}
void BGAnimationLayer::LoadFromVisualization( CString sMoviePath )
{
2003-03-05 02:52:40 +00:00
Init();
Sprite* pSprite = new Sprite;
m_pActors.push_back( pSprite );
pSprite->LoadBG( sMoviePath );
pSprite->StretchTo( RectI(SCREEN_LEFT,SCREEN_TOP,SCREEN_RIGHT,SCREEN_BOTTOM) );
pSprite->SetBlendMode( BLEND_ADD );
2002-09-29 05:06:18 +00:00
}
2003-03-05 02:52:40 +00:00
void BGAnimationLayer::LoadFromAniLayerFile( CString sPath )
2002-09-29 05:06:18 +00:00
{
Song* pSong = GAMESTATE->m_pCurSong;
CString sSongBGPath;
if( pSong && pSong->HasBackground() )
sSongBGPath = pSong->GetBackgroundPath();
else
sSongBGPath = THEME->GetPathToG("Common fallback background");
2003-03-05 02:52:40 +00:00
Init();
2003-02-14 22:46:45 +00:00
CString lcPath = sPath;
lcPath.MakeLower();
2002-09-29 05:06:18 +00:00
2003-02-14 22:46:45 +00:00
if( lcPath.Find("usesongbg") != -1 )
2002-09-29 05:06:18 +00:00
{
LoadFromStaticGraphic( sSongBGPath );
return; // this will ignore other effects in the file name
}
const CString EFFECT_STRING[NUM_EFFECTS] = {
"center",
"stretchstill",
"stretchscrollleft",
2002-09-29 05:06:18 +00:00
"stretchscrollright",
"stretchscrollup",
"stretchscrolldown",
"stretchwater",
"stretchbubble",
"stretchtwist",
"stretchspin",
"particlesspiralout",
"particlesspiralin",
"particlesfloatup",
"particlesfloatdown",
"particlesfloatleft",
"particlesfloatright",
"particlesbounce",
"tilestill",
"tilescrollleft",
"tilescrollright",
"tilescrollup",
"tilescrolldown",
"tileflipx",
"tileflipy",
"tilepulse",
};
2003-03-05 02:52:40 +00:00
Effect effect = EFFECT_CENTER;
2002-09-29 05:06:18 +00:00
for( int i=0; i<NUM_EFFECTS; i++ )
2003-02-14 22:46:45 +00:00
if( lcPath.Find(EFFECT_STRING[i]) != -1 )
2003-03-05 02:52:40 +00:00
effect = (Effect)i;
2002-09-29 05:06:18 +00:00
2003-03-05 02:52:40 +00:00
switch( effect )
2002-09-29 05:06:18 +00:00
{
case EFFECT_CENTER:
{
m_Type = TYPE_SPRITE;
Sprite* pSprite = new Sprite;
m_pActors.push_back( pSprite );
pSprite->Load( sPath );
pSprite->SetXY( CENTER_X, CENTER_Y );
}
2002-09-29 05:06:18 +00:00
break;
case EFFECT_STRETCH_STILL:
case EFFECT_STRETCH_SCROLL_LEFT:
case EFFECT_STRETCH_SCROLL_RIGHT:
case EFFECT_STRETCH_SCROLL_UP:
case EFFECT_STRETCH_SCROLL_DOWN:
case EFFECT_STRETCH_WATER:
case EFFECT_STRETCH_BUBBLE:
case EFFECT_STRETCH_TWIST:
{
2003-03-05 02:52:40 +00:00
m_Type = TYPE_STRETCH;
Sprite* pSprite = new Sprite;
m_pActors.push_back( pSprite );
RageTextureID ID(sPath);
ID.bStretch = true;
pSprite->LoadBG( ID );
pSprite->StretchTo( RectI(SCREEN_LEFT,SCREEN_TOP,SCREEN_RIGHT,SCREEN_BOTTOM) );
pSprite->SetCustomTextureRect( RectF(0,0,1,1) );
2003-03-05 02:52:40 +00:00
switch( effect )
{
2003-03-05 02:52:40 +00:00
case EFFECT_STRETCH_SCROLL_LEFT: m_fStretchTexCoordVelocityX = +0.5f; m_fStretchTexCoordVelocityY = 0; break;
case EFFECT_STRETCH_SCROLL_RIGHT: m_fStretchTexCoordVelocityX = -0.5f; m_fStretchTexCoordVelocityY = 0; break;
case EFFECT_STRETCH_SCROLL_UP: m_fStretchTexCoordVelocityX = 0; m_fStretchTexCoordVelocityY = +0.5f; break;
case EFFECT_STRETCH_SCROLL_DOWN: m_fStretchTexCoordVelocityX = 0; m_fStretchTexCoordVelocityY = -0.5f; break;
break;
}
2002-09-29 05:06:18 +00:00
}
break;
2003-03-05 02:52:40 +00:00
case EFFECT_STRETCH_SPIN:
{
2003-03-05 02:52:40 +00:00
m_Type = TYPE_STRETCH;
Sprite* pSprite = new Sprite;
m_pActors.push_back( pSprite );
pSprite->LoadBG( sPath );
pSprite->ScaleToCover( RectI(SCREEN_LEFT-200,SCREEN_TOP-200,SCREEN_RIGHT+200,SCREEN_BOTTOM+200) );
pSprite->SetEffectSpin( RageVector3(0,0,60) );
}
break;
2002-09-29 05:06:18 +00:00
case EFFECT_PARTICLES_SPIRAL_OUT:
case EFFECT_PARTICLES_SPIRAL_IN:
2003-03-05 02:52:40 +00:00
/* {
m_Type = TYPE_PARTICLES;
pSprite->Load( sPath );
int iSpriteArea = int( pSprite->GetUnzoomedWidth()*pSprite->GetUnzoomedHeight() );
2002-09-29 05:06:18 +00:00
int iMaxArea = SCREEN_WIDTH*SCREEN_HEIGHT;
2003-03-05 02:52:40 +00:00
m_iNumSprites = m_iNumParticles = iMaxArea / iSpriteArea;
m_iNumSprites = m_iNumParticles = min( m_iNumSprites, MAX_SPRITES );
for( unsigned i=0; i<m_iNumSprites; i++ )
2002-09-29 05:06:18 +00:00
{
m_pActors[i].Load( sPath );
m_pActors[i].SetZoom( randomf(0.2f,2) );
m_pActors[i].SetRotationZ( randomf(0,360) );
2002-09-29 05:06:18 +00:00
}
}
break;
2003-03-05 02:52:40 +00:00
*/ case EFFECT_PARTICLES_FLOAT_UP:
2002-09-29 05:06:18 +00:00
case EFFECT_PARTICLES_FLOAT_DOWN:
case EFFECT_PARTICLES_FLOAT_LEFT:
case EFFECT_PARTICLES_FLOAT_RIGHT:
case EFFECT_PARTICLES_BOUNCE:
{
2003-03-05 02:52:40 +00:00
m_Type = TYPE_PARTICLES;
Sprite s;
s.Load( sPath );
int iSpriteArea = int( s.GetUnzoomedWidth()*s.GetUnzoomedHeight() );
const int iMaxArea = SCREEN_WIDTH*SCREEN_HEIGHT;
m_iNumParticles = iMaxArea / iSpriteArea;
m_iNumParticles = min( m_iNumParticles, MAX_SPRITES );
for( int i=0; i<m_iNumParticles; i++ )
2002-09-29 05:06:18 +00:00
{
Sprite* pSprite = new Sprite;
m_pActors.push_back( pSprite );
pSprite->Load( sPath );
pSprite->SetZoom( 0.7f + 0.6f*i/(float)m_iNumParticles );
pSprite->SetX( randomf( GetGuardRailLeft(pSprite), GetGuardRailRight(pSprite) ) );
pSprite->SetY( randomf( GetGuardRailTop(pSprite), GetGuardRailBottom(pSprite) ) );
2002-09-29 05:06:18 +00:00
2003-03-05 02:52:40 +00:00
switch( effect )
2002-09-29 05:06:18 +00:00
{
2003-03-05 02:52:40 +00:00
case EFFECT_PARTICLES_FLOAT_UP:
case EFFECT_PARTICLES_SPIRAL_OUT:
m_vParticleVelocity[i] = RageVector3( 0, -PARTICLE_SPEED*pSprite->GetZoom(), 0 );
2003-03-05 02:52:40 +00:00
break;
case EFFECT_PARTICLES_FLOAT_DOWN:
case EFFECT_PARTICLES_SPIRAL_IN:
m_vParticleVelocity[i] = RageVector3( 0, PARTICLE_SPEED*pSprite->GetZoom(), 0 );
2003-03-05 02:52:40 +00:00
break;
case EFFECT_PARTICLES_FLOAT_LEFT:
m_vParticleVelocity[i] = RageVector3( -PARTICLE_SPEED*pSprite->GetZoom(), 0, 0 );
2003-03-05 02:52:40 +00:00
break;
case EFFECT_PARTICLES_FLOAT_RIGHT:
m_vParticleVelocity[i] = RageVector3( +PARTICLE_SPEED*pSprite->GetZoom(), 0, 0 );
2003-03-05 02:52:40 +00:00
break;
case EFFECT_PARTICLES_BOUNCE:
m_bParticlesBounce = true;
pSprite->SetZoom( 1 );
2003-03-05 02:52:40 +00:00
m_vParticleVelocity[i] = RageVector3( randomf(), randomf(), 0 );
RageVec3Normalize( &m_vParticleVelocity[i], &m_vParticleVelocity[i] );
break;
default:
ASSERT(0);
2002-09-29 05:06:18 +00:00
}
}
}
break;
case EFFECT_TILE_STILL:
case EFFECT_TILE_SCROLL_LEFT:
case EFFECT_TILE_SCROLL_RIGHT:
case EFFECT_TILE_SCROLL_UP:
case EFFECT_TILE_SCROLL_DOWN:
case EFFECT_TILE_FLIP_X:
case EFFECT_TILE_FLIP_Y:
case EFFECT_TILE_PULSE:
{
2003-03-05 02:52:40 +00:00
m_Type = TYPE_TILES;
RageTextureID ID(sPath);
ID.bStretch = true;
Sprite s;
s.Load( ID );
m_iNumTilesWide = 2+int(SCREEN_WIDTH /s.GetUnzoomedWidth());
2003-03-05 02:52:40 +00:00
m_iNumTilesWide = min( m_iNumTilesWide, MAX_TILES_WIDE );
m_iNumTilesHigh = 2+int(SCREEN_HEIGHT/s.GetUnzoomedHeight());
2003-03-05 02:52:40 +00:00
m_iNumTilesHigh = min( m_iNumTilesHigh, MAX_TILES_HIGH );
m_fTilesStartX = s.GetUnzoomedWidth() / 2;
m_fTilesStartY = s.GetUnzoomedHeight() / 2;
m_fTilesSpacingX = s.GetUnzoomedWidth();
m_fTilesSpacingY = s.GetUnzoomedHeight();
// m_fTilesSpacingX -= 1; // HACK: Fix textures with transparence have gaps
// m_fTilesSpacingY -= 1; // HACK: Fix textures with transparence have gaps
2003-03-05 02:52:40 +00:00
for( int x=0; x<m_iNumTilesWide; x++ )
2002-09-29 05:06:18 +00:00
{
2003-03-05 02:52:40 +00:00
for( int y=0; y<m_iNumTilesHigh; y++ )
2002-09-29 05:06:18 +00:00
{
Sprite* pSprite = new Sprite;
m_pActors.push_back( pSprite );
pSprite->Load( ID );
pSprite->SetTextureWrapping( true ); // gets rid of some "cracks"
2003-03-05 02:52:40 +00:00
switch( effect )
{
case EFFECT_TILE_STILL:
break;
case EFFECT_TILE_SCROLL_LEFT:
m_fTileVelocityX = -PARTICLE_SPEED;
break;
case EFFECT_TILE_SCROLL_RIGHT:
m_fTileVelocityX = +PARTICLE_SPEED;
break;
case EFFECT_TILE_SCROLL_UP:
m_fTileVelocityY = -PARTICLE_SPEED;
break;
case EFFECT_TILE_SCROLL_DOWN:
m_fTileVelocityY = +PARTICLE_SPEED;
break;
case EFFECT_TILE_FLIP_X:
pSprite->SetEffectSpin( RageVector3(2,0,0) );
2003-03-05 02:52:40 +00:00
break;
case EFFECT_TILE_FLIP_Y:
pSprite->SetEffectSpin( RageVector3(0,2,0) );
2003-03-05 02:52:40 +00:00
break;
case EFFECT_TILE_PULSE:
pSprite->SetEffectPulse( 1, 0.3f, 1.f );
2003-03-05 02:52:40 +00:00
break;
default:
ASSERT(0);
}
2002-09-29 05:06:18 +00:00
}
}
}
break;
default:
ASSERT(0);
}
2003-03-05 02:52:40 +00:00
sPath.MakeLower();
if( sPath.Find("cyclecolor") != -1 )
for( unsigned i=0; i<m_pActors.size(); i++ )
m_pActors[i]->SetEffectRainbow( 5 );
2003-03-05 02:52:40 +00:00
if( sPath.Find("cyclealpha") != -1 )
for( unsigned i=0; i<m_pActors.size(); i++ )
m_pActors[i]->SetEffectDiffuseShift( 2, RageColor(1,1,1,1), RageColor(1,1,1,0) );
2002-09-29 05:06:18 +00:00
if( sPath.Find("startonrandomframe") != -1 )
for( unsigned i=0; i<m_pActors.size(); i++ )
m_pActors[i]->SetState( rand()%m_pActors[i]->GetNumStates() );
2002-09-29 05:06:18 +00:00
if( sPath.Find("dontanimate") != -1 )
for( unsigned i=0; i<m_pActors.size(); i++ )
m_pActors[i]->StopAnimating();
2002-09-29 05:06:18 +00:00
if( sPath.Find("add") != -1 )
for( unsigned i=0; i<m_pActors.size(); i++ )
m_pActors[i]->SetBlendMode( BLEND_ADD );
2002-09-29 05:06:18 +00:00
2003-03-05 02:52:40 +00:00
/*
2002-09-29 05:06:18 +00:00
CString sDir, sFName, sExt;
splitrelpath( sPath, sDir, sFName, sExt );
CString sIniPath = sDir+"/"+sFName+".ini";
2002-09-29 05:06:18 +00:00
IniFile ini;
ini.SetPath( sIniPath );
if( ini.ReadFile() )
{
2003-01-12 00:57:53 +00:00
ini.GetValueF( "BGAnimationLayer", "SetXpos", m_PosX );
ini.GetValueF( "BGAnimationLayer", "SetYpos", m_PosY );
ini.GetValueF( "BGAnimationLayer", "SetZoom", m_Zoom );
ini.GetValueF( "BGAnimationLayer", "SetRot", m_Rot );
ini.GetValueF( "BGAnimationLayer", "TweenStartTime", m_TweenStartTime );
ini.GetValueF( "BGAnimationLayer", "TweenX", m_TweenX );
ini.GetValueF( "BGAnimationLayer", "TweenY", m_TweenY );
ini.GetValueF( "BGAnimationLayer", "TweenSpeed", m_TweenSpeed );
ini.GetValueF( "BGAnimationLayer", "ShowTime", m_ShowTime );
ini.GetValueF( "BGAnimationLayer", "HideTime", m_HideTime );
2002-09-29 05:06:18 +00:00
ini.GetValueF( "BGAnimationLayer", "TexCoordVelocityX", m_vTexCoordVelocity.x );
ini.GetValueF( "BGAnimationLayer", "TexCoordVelocityY", m_vTexCoordVelocity.y );
ini.GetValueF( "BGAnimationLayer", "RotationalVelocity", m_fRotationalVelocity );
ini.GetValueF( "BGAnimationLayer", "SetY", m_fStretchScrollH_Y );
2002-09-29 05:06:18 +00:00
}
2003-01-12 00:57:53 +00:00
if(m_ShowTime != 0) // they don't want to show until a certain point... hide it all
{
m_pActors[0].SetDiffuse(RageColor(0,0,0,0));
2003-01-12 00:57:53 +00:00
}
if(m_PosX != 0)
{
m_pActors[0].SetX(m_PosX);
2003-01-12 00:57:53 +00:00
}
if(m_PosY != 0)
{
m_pActors[0].SetY(m_PosY);
2003-01-12 00:57:53 +00:00
}
if(m_Zoom != 0)
{
m_pActors[0].SetZoom(m_Zoom);
2003-01-12 00:57:53 +00:00
}
if(m_Rot != 0)
{
m_pActors[0].SetRotationZ(m_Rot);
2003-01-12 00:57:53 +00:00
}
2003-03-05 02:52:40 +00:00
*/
2002-09-29 05:06:18 +00:00
}
void BGAnimationLayer::LoadFromIni( CString sAniDir, CString sLayer )
2003-03-05 02:52:40 +00:00
{
Init();
if( sAniDir.Right(1) != "/" )
sAniDir += "/";
ASSERT( IsADirectory(sAniDir) );
CString sPathToIni = sAniDir + "BGAnimation.ini";
IniFile ini(sPathToIni);
ini.ReadFile();
2003-04-21 03:08:02 +00:00
bool IsBanner = false;
2003-04-13 00:44:50 +00:00
CString sFile;
ini.GetValue( sLayer, "File", sFile );
CString sPath = sAniDir+sFile;
2003-03-05 02:52:40 +00:00
2003-04-13 00:44:50 +00:00
if( sFile.CompareNoCase("songbackground")==0 )
{
2003-03-17 03:24:12 +00:00
Song *pSong = GAMESTATE->m_pCurSong;
2003-04-13 00:44:50 +00:00
if( pSong && pSong->HasBackground() )
2003-03-17 03:24:12 +00:00
sPath = pSong->GetBackgroundPath();
else
sPath = THEME->GetPathToG("Common fallback background");
2003-04-13 00:44:50 +00:00
}
else if( sFile.CompareNoCase("songbanner")==0 )
{
Song *pSong = GAMESTATE->m_pCurSong;
if( pSong && pSong->HasBanner() )
sPath = pSong->GetBannerPath();
else
sPath = THEME->GetPathToG("Common fallback banner");
2003-04-21 03:08:02 +00:00
IsBanner = true;
2003-04-13 00:44:50 +00:00
}
else if( sFile == "" )
{
if( DISPLAY->IsWindowed() )
HOOKS->MessageBoxOK( ssprintf(
"In the ini file for BGAnimation '%s', '%s' is missing a the line 'File='.", sAniDir.c_str(), sLayer.c_str() ) );
2003-03-17 03:24:12 +00:00
}
2003-03-05 02:52:40 +00:00
/* XXX: Search the BGA dir first, then search the Graphics directory if this
* is a theme BGA, so common BG graphics can be overridden. */
{
vector<CString> asElementPaths;
GetDirListing( sPath + "*", asElementPaths, false, true );
if(asElementPaths.size() == 0)
{
if( DISPLAY->IsWindowed() )
HOOKS->MessageBoxOK( ssprintf("In the ini file for BGAnimation '%s', the specified File '%s' does not exist.", sAniDir.c_str(), sFile.c_str()) );
return;
}
if(asElementPaths.size() > 1)
{
if( DISPLAY->IsWindowed() )
HOOKS->MessageBoxOK( ssprintf(
"There is more than one file that matches "
"'%s/%s'. Please remove all but one of these matches.",
sAniDir.c_str(), sFile.c_str() ) );
}
sPath = asElementPaths[0];
}
2003-04-13 01:09:19 +00:00
2003-03-05 02:52:40 +00:00
ini.GetValueI( sLayer, "Type", (int&)m_Type );
2003-07-10 03:37:13 +00:00
ini.GetValue ( sLayer, "Command", m_sOnCommand );
ini.GetValue ( sLayer, "OffCommand", m_sOffCommand );
ini.GetValueF( sLayer, "FOV", m_fFOV );
2003-07-07 20:24:51 +00:00
ini.GetValueB( sLayer, "Lighting", m_bLighting );
2003-03-05 02:52:40 +00:00
ini.GetValueF( sLayer, "StretchTexCoordVelocityX", m_fStretchTexCoordVelocityX );
ini.GetValueF( sLayer, "StretchTexCoordVelocityY", m_fStretchTexCoordVelocityY );
ini.GetValueF( sLayer, "ZoomMin", m_fZoomMin );
ini.GetValueF( sLayer, "ZoomMax", m_fZoomMax );
ini.GetValueF( sLayer, "VelocityXMin", m_fVelocityXMin );
ini.GetValueF( sLayer, "VelocityXMax", m_fVelocityXMax );
ini.GetValueF( sLayer, "VelocityYMin", m_fVelocityYMin );
ini.GetValueF( sLayer, "VelocityYMax", m_fVelocityYMax );
ini.GetValueF( sLayer, "VelocityZMin", m_fVelocityZMin );
ini.GetValueF( sLayer, "VelocityZMax", m_fVelocityZMax );
ini.GetValueF( sLayer, "OverrideSpeed", m_fOverrideSpeed );
ini.GetValueI( sLayer, "NumParticles", m_iNumParticles );
ini.GetValueB( sLayer, "ParticlesBounce", m_bParticlesBounce );
2003-03-09 09:25:32 +00:00
// ini.GetValueI( sLayer, "NumTilesWide", m_iNumTilesWide ); // infer from spacing (or else the Update logic breaks)
// ini.GetValueI( sLayer, "NumTilesHigh", m_iNumTilesHigh ); // infer from spacing (or else the Update logic breaks)
2003-03-05 02:52:40 +00:00
ini.GetValueF( sLayer, "TilesStartX", m_fTilesStartX );
ini.GetValueF( sLayer, "TilesStartY", m_fTilesStartY );
ini.GetValueF( sLayer, "TilesSpacingX", m_fTilesSpacingX );
ini.GetValueF( sLayer, "TilesSpacingY", m_fTilesSpacingY );
ini.GetValueF( sLayer, "TileVelocityX", m_fTileVelocityX );
ini.GetValueF( sLayer, "TileVelocityY", m_fTileVelocityY );
if( IsBanner )
TEXTUREMAN->DisableOddDimensionWarning();
2003-03-05 02:52:40 +00:00
switch( m_Type )
2002-09-29 05:06:18 +00:00
{
2003-03-05 02:52:40 +00:00
case TYPE_SPRITE:
{
Actor* pActor = MakeActor( sPath );
m_pActors.push_back( pActor );
pActor->SetXY( CENTER_X, CENTER_Y );
}
2003-03-05 02:52:40 +00:00
break;
case TYPE_STRETCH:
2002-09-29 05:06:18 +00:00
{
Sprite* pSprite = new Sprite;
m_pActors.push_back( pSprite );
2003-03-05 02:52:40 +00:00
RageTextureID ID(sPath);
ID.bStretch = true;
pSprite->LoadBG( ID );
pSprite->StretchTo( RectI(SCREEN_LEFT,SCREEN_TOP,SCREEN_RIGHT,SCREEN_BOTTOM) );
pSprite->SetCustomTextureRect( RectF(0,0,1,1) );
2002-09-29 05:06:18 +00:00
}
2003-03-05 02:52:40 +00:00
break;
case TYPE_PARTICLES:
2002-09-29 05:06:18 +00:00
{
for( int i=0; i<m_iNumParticles; i++ )
2003-03-05 02:52:40 +00:00
{
Actor* pActor = MakeActor( sPath );
m_pActors.push_back( pActor );
pActor->SetXY( randomf(SCREEN_LEFT,SCREEN_RIGHT), randomf(SCREEN_TOP,SCREEN_BOTTOM) );
pActor->SetZoom( randomf(m_fZoomMin,m_fZoomMax) );
2003-03-05 02:52:40 +00:00
m_vParticleVelocity[i] = RageVector3(
randomf(m_fVelocityXMin,m_fVelocityXMax),
randomf(m_fVelocityYMin,m_fVelocityYMax),
randomf(m_fVelocityZMin,m_fVelocityZMax) );
if( m_fOverrideSpeed != 0 )
{
RageVec3Normalize( &m_vParticleVelocity[i], &m_vParticleVelocity[i] );
m_vParticleVelocity[i] *= m_fOverrideSpeed;
}
}
2002-09-29 05:06:18 +00:00
}
2003-03-05 02:52:40 +00:00
break;
case TYPE_TILES:
{
Sprite s;
RageTextureID ID(sPath);
ID.bStretch = true;
s.Load( ID );
2003-03-09 09:25:32 +00:00
if( m_fTilesSpacingX == -1 )
2003-03-25 19:32:17 +00:00
m_fTilesSpacingX = s.GetUnzoomedWidth();
2003-03-09 09:25:32 +00:00
if( m_fTilesSpacingY == -1 )
2003-03-25 19:32:17 +00:00
m_fTilesSpacingY = s.GetUnzoomedHeight();
2003-03-05 02:52:40 +00:00
m_iNumTilesWide = 2+(int)(SCREEN_WIDTH /m_fTilesSpacingX);
m_iNumTilesHigh = 2+(int)(SCREEN_HEIGHT/m_fTilesSpacingY);
unsigned NumSprites = m_iNumTilesWide * m_iNumTilesHigh;
for( unsigned i=0; i<NumSprites; i++ )
2003-03-05 02:52:40 +00:00
{
Sprite* pSprite = new Sprite;
m_pActors.push_back( pSprite );
pSprite->Load( ID );
pSprite->SetTextureWrapping( true ); // gets rid of some "cracks"
pSprite->SetZoom( randomf(m_fZoomMin,m_fZoomMax) );
2003-03-05 02:52:40 +00:00
}
}
break;
default:
ASSERT(0);
2002-09-29 05:06:18 +00:00
}
if( IsBanner )
TEXTUREMAN->EnableOddDimensionWarning();
2002-09-29 05:06:18 +00:00
2003-03-05 02:52:40 +00:00
bool bStartOnRandomFrame = false;
ini.GetValueB( sLayer, "StartOnRandomFrame", bStartOnRandomFrame );
if( bStartOnRandomFrame )
{
for( unsigned i=0; i<m_pActors.size(); i++ )
m_pActors[i]->SetState( rand()%m_pActors[i]->GetNumStates() );
2003-03-05 02:52:40 +00:00
}
2003-07-10 03:37:13 +00:00
if( m_sOnCommand != "" )
2003-03-05 02:52:40 +00:00
{
for( unsigned i=0; i<m_pActors.size(); i++ )
2003-07-10 03:37:13 +00:00
m_pActors[i]->Command( m_sOnCommand );
2003-03-05 02:52:40 +00:00
}
}
2003-03-17 01:34:12 +00:00
float BGAnimationLayer::GetMaxTweenTimeLeft() const
{
float ret = 0;
for( unsigned i=0; i<m_pActors.size(); i++ )
ret = max(ret, m_pActors[i]->GetTweenTimeLeft());
2003-03-17 01:34:12 +00:00
return ret;
}
2003-03-05 02:52:40 +00:00
void BGAnimationLayer::Update( float fDeltaTime )
{
fDeltaTime *= m_fUpdateRate;
2003-03-05 02:52:40 +00:00
const float fSongBeat = GAMESTATE->m_fSongBeat;
2002-09-29 05:06:18 +00:00
2003-03-06 01:02:17 +00:00
unsigned i;
for( i=0; i<m_pActors.size(); i++ )
m_pActors[i]->Update( fDeltaTime );
2002-09-29 05:06:18 +00:00
2003-03-05 02:52:40 +00:00
switch( m_Type )
2002-09-29 05:06:18 +00:00
{
2003-03-05 02:52:40 +00:00
case TYPE_SPRITE:
2002-09-29 05:06:18 +00:00
break;
2003-03-05 02:52:40 +00:00
case TYPE_STRETCH:
for( i=0; i<m_pActors.size(); i++ )
2002-09-29 05:06:18 +00:00
{
float fTexCoords[8];
// FIXME: Very dangerous. How could we handle this better?
Sprite* pSprite = (Sprite*)m_pActors[i];
pSprite->GetActiveTextureCoords( fTexCoords );
2002-09-29 05:06:18 +00:00
for( int j=0; j<8; j+=2 )
{
fTexCoords[j ] += fDeltaTime*m_fStretchTexCoordVelocityX;
fTexCoords[j+1] += fDeltaTime*m_fStretchTexCoordVelocityY;
}
pSprite->SetCustomTextureCoords( fTexCoords );
2003-03-05 02:52:40 +00:00
}
2002-09-29 05:06:18 +00:00
break;
2003-03-05 02:52:40 +00:00
/* case EFFECT_PARTICLES_SPIRAL_OUT:
2002-09-29 05:06:18 +00:00
for( i=0; i<m_iNumSprites; i++ )
{
m_pActors[i].SetZoom( m_pActors[i].GetZoom() + fDeltaTime );
if( m_pActors[i].GetZoom() > SPIRAL_MAX_ZOOM )
m_pActors[i].SetZoom( SPIRAL_MIN_ZOOM );
2002-09-29 05:06:18 +00:00
m_pActors[i].SetRotationZ( m_pActors[i].GetRotationZ() + fDeltaTime );
2002-09-29 05:06:18 +00:00
float fRadius = (m_pActors[i].GetZoom()-SPIRAL_MIN_ZOOM);
2002-09-29 05:06:18 +00:00
fRadius *= fRadius;
fRadius *= 200;
m_pActors[i].SetX( CENTER_X + cosf(m_pActors[i].GetRotationZ())*fRadius );
m_pActors[i].SetY( CENTER_Y + sinf(m_pActors[i].GetRotationZ())*fRadius );
2002-09-29 05:06:18 +00:00
}
break;
case EFFECT_PARTICLES_SPIRAL_IN:
for( i=0; i<m_iNumSprites; i++ )
{
m_pActors[i].SetZoom( m_pActors[i].GetZoom() - fDeltaTime );
if( m_pActors[i].GetZoom() < SPIRAL_MIN_ZOOM )
m_pActors[i].SetZoom( SPIRAL_MAX_ZOOM );
2002-09-29 05:06:18 +00:00
m_pActors[i].SetRotationZ( m_pActors[i].GetRotationZ() - fDeltaTime );
2002-09-29 05:06:18 +00:00
float fRadius = (m_pActors[i].GetZoom()-SPIRAL_MIN_ZOOM);
2002-09-29 05:06:18 +00:00
fRadius *= fRadius;
fRadius *= 200;
m_pActors[i].SetX( CENTER_X + cosf(m_pActors[i].GetRotationZ())*fRadius );
m_pActors[i].SetY( CENTER_Y + sinf(m_pActors[i].GetRotationZ())*fRadius );
2002-09-29 05:06:18 +00:00
}
break;
2003-03-05 02:52:40 +00:00
*/
case TYPE_PARTICLES:
for( i=0; i<m_pActors.size(); i++ )
2002-09-29 05:06:18 +00:00
{
m_pActors[i]->SetX( m_pActors[i]->GetX() + fDeltaTime*m_vParticleVelocity[i].x );
m_pActors[i]->SetY( m_pActors[i]->GetY() + fDeltaTime*m_vParticleVelocity[i].y );
m_pActors[i]->SetZ( m_pActors[i]->GetZ() + fDeltaTime*m_vParticleVelocity[i].z );
2003-03-05 02:52:40 +00:00
if( m_bParticlesBounce )
2003-01-13 08:31:34 +00:00
{
if( HitGuardRailLeft(m_pActors[i]) )
2003-03-05 02:52:40 +00:00
{
m_vParticleVelocity[i].x *= -1;
m_pActors[i]->SetX( GetGuardRailLeft(m_pActors[i]) );
2003-03-05 02:52:40 +00:00
}
if( HitGuardRailRight(m_pActors[i]) )
2003-03-05 02:52:40 +00:00
{
m_vParticleVelocity[i].x *= -1;
m_pActors[i]->SetX( GetGuardRailRight(m_pActors[i]) );
2003-03-05 02:52:40 +00:00
}
if( HitGuardRailTop(m_pActors[i]) )
2003-03-05 02:52:40 +00:00
{
m_vParticleVelocity[i].y *= -1;
m_pActors[i]->SetY( GetGuardRailTop(m_pActors[i]) );
2003-03-05 02:52:40 +00:00
}
if( HitGuardRailBottom(m_pActors[i]) )
2003-03-05 02:52:40 +00:00
{
m_vParticleVelocity[i].y *= -1;
m_pActors[i]->SetY( GetGuardRailBottom(m_pActors[i]) );
2003-03-05 02:52:40 +00:00
}
2003-01-13 08:31:34 +00:00
}
2003-03-05 02:52:40 +00:00
else // !m_bParticlesBounce
2003-01-13 08:31:34 +00:00
{
if( m_vParticleVelocity[i].x<0 && IsOffScreenLeft(m_pActors[i]) )
m_pActors[i]->SetX( GetOffScreenRight(m_pActors[i]) );
if( m_vParticleVelocity[i].x>0 && IsOffScreenRight(m_pActors[i]) )
m_pActors[i]->SetX( GetOffScreenLeft(m_pActors[i]) );
if( m_vParticleVelocity[i].y<0 && IsOffScreenTop(m_pActors[i]) )
m_pActors[i]->SetY( GetOffScreenBottom(m_pActors[i]) );
if( m_vParticleVelocity[i].y>0 && IsOffScreenBottom(m_pActors[i]) )
m_pActors[i]->SetY( GetOffScreenTop(m_pActors[i]) );
2003-01-13 08:31:34 +00:00
}
2002-09-29 05:06:18 +00:00
}
break;
2003-03-05 02:52:40 +00:00
case TYPE_TILES:
{
float fSecs = RageTimer::GetTimeSinceStart();
float fTotalWidth = m_iNumTilesWide * m_fTilesSpacingX;
float fTotalHeight = m_iNumTilesHigh * m_fTilesSpacingY;
ASSERT( int(m_pActors.size()) == m_iNumTilesWide * m_iNumTilesHigh );
2003-03-05 02:52:40 +00:00
for( int x=0; x<m_iNumTilesWide; x++ )
{
for( int y=0; y<m_iNumTilesHigh; y++ )
{
int i = y*m_iNumTilesWide + x;
float fX = m_fTilesStartX + m_fTilesSpacingX * x + fSecs * m_fTileVelocityX;
float fY = m_fTilesStartY + m_fTilesSpacingY * y + fSecs * m_fTileVelocityY;
fX += m_fTilesSpacingX/2;
fY += m_fTilesSpacingY/2;
fX = fmodf( fX, fTotalWidth );
fY = fmodf( fY, fTotalHeight );
if( fX < 0 ) fX += fTotalWidth;
if( fY < 0 ) fY += fTotalHeight;
fX -= m_fTilesSpacingX/2;
fY -= m_fTilesSpacingY/2;
m_pActors[i]->SetX( fX );
m_pActors[i]->SetY( fY );
2003-03-05 02:52:40 +00:00
}
}
/*
2002-09-29 05:06:18 +00:00
for( i=0; i<m_iNumSprites; i++ )
{
m_pActors[i].SetX( m_pActors[i].GetX() + fDeltaTime* );
m_pActors[i].SetY( m_pActors[i].GetY() + fDeltaTime*m_vParticleVelocity[i].y );
m_pActors[i].SetZ( m_pActors[i].GetZ() + fDeltaTime*m_vParticleVelocity[i].z );
if( IsOffScreenLeft(&m_pActors[i]) )
m_pActors[i].SetX( m_pActors[i].GetX()-GetOffScreenLeft(&m_pActors[i]) + GetOffScreenRight(&m_pActors[i]) );
if( IsOffScreenRight(&m_pActors[i]) )
m_pActors[i].SetX( m_pActors[i].GetX()-GetOffScreenRight(&m_pActors[i]) + GetOffScreenLeft(&m_pActors[i]) );
if( IsOffScreenTop(&m_pActors[i]) )
m_pActors[i].SetY( m_pActors[i].GetY()-GetOffScreenTop(&m_pActors[i]) + GetOffScreenBottom(&m_pActors[i]) );
if( IsOffScreenBottom(&m_pActors[i]) )
m_pActors[i].SetY( m_pActors[i].GetY()-GetOffScreenBottom(&m_pActors[i]) + GetOffScreenTop(&m_pActors[i]) );
2003-03-05 02:52:40 +00:00
*/
2002-09-29 05:06:18 +00:00
}
break;
case EFFECT_TILE_PULSE:
for( i=0; i<m_pActors.size(); i++ )
m_pActors[i]->SetZoom( sinf( fSongBeat*PI/2 ) );
2002-09-29 05:06:18 +00:00
break;
default:
ASSERT(0);
}
2003-01-12 00:57:53 +00:00
2003-03-05 02:52:40 +00:00
/*
2003-01-12 00:57:53 +00:00
if(m_TweenStartTime != 0 && !(m_TweenStartTime < 0))
{
m_TweenStartTime -= fDeltaTime;
if(m_TweenStartTime <= 0) // if we've gone past the magic point... show the beast....
{
// m_pActors[0].SetXY( m_TweenX, m_TweenY);
2003-01-12 00:57:53 +00:00
// WHAT WOULD BE NICE HERE:
// Set the Sprite Tweening To m_TweenX and m_TweenY
// Going as fast as m_TweenSpeed specifies.
// however, TWEEN falls over on its face at this point.
// Lovely.
// Instead: Manual tweening. Blah.
m_TweenState = 1;
if(m_PosX == m_TweenX)
{
m_TweenPassedX = 1;
}
if(m_PosY == m_TweenY)
{
m_TweenPassedY = 1;
}
2003-01-12 00:57:53 +00:00
}
}
if(m_TweenState) // A FAR from perfect Tweening Mechanism.
{
if(m_TweenPassedY != 1) // Check to see if we still need to Tween Along the Y Axis
{
if(m_pActors[0].GetY() < m_TweenY) // it needs to travel down
{
// Speed = Distance / Time....
// Take away from the current position... the distance it has to travel divided by the time they want it done in...
m_pActors[0].SetY(m_pActors[0].GetY() + ((m_TweenY - m_PosY)/(m_TweenSpeed*60)));
if(m_pActors[0].GetY() > m_TweenY) // passed the location we wanna go to?
{
m_pActors[0].SetY(m_TweenY); // set it to the exact location we want
m_TweenPassedY = 1; // say we passed it.
}
}
else // travelling up
{
m_pActors[0].SetY(m_pActors[0].GetY() - ((m_TweenY + m_PosY)/(m_TweenSpeed*60)));
if(m_pActors[0].GetY() < m_TweenY)
{
m_pActors[0].SetY(m_TweenY);
m_TweenPassedY = 1;
}
}
}
if(m_TweenPassedX != 1) // Check to see if we still need to Tween Along the X Axis
{
if(m_pActors[0].GetX() < m_TweenX) // it needs to travel right
{
m_pActors[0].SetX(m_pActors[0].GetX() + ((m_TweenX - m_PosX)/(m_TweenSpeed*60)));
if(m_pActors[0].GetX() > m_TweenX)
{
m_pActors[0].SetX(m_TweenX);
m_TweenPassedX = 1;
}
}
else // travelling left
{
m_pActors[0].SetX(m_pActors[0].GetX() - ((m_TweenX + m_PosX)/(m_TweenSpeed*60)));
if(m_pActors[0].GetX() < m_TweenX)
{
m_pActors[0].SetX(m_TweenX);
m_TweenPassedX = 1;
}
}
}
if(m_TweenPassedY == 1 && m_TweenPassedX == 1) // totally passed both X and Y? Stop tweening.
{
m_TweenState = 0;
}
}
2003-01-12 00:57:53 +00:00
if(m_ShowTime != 0 && !(m_ShowTime < 0))
{
m_ShowTime -= fDeltaTime;
if(m_ShowTime <= 0) // if we've gone past the magic point... show the beast....
{
m_pActors[0].SetDiffuse( RageColor(1,1,1,1) );
2003-01-12 00:57:53 +00:00
}
}
if(m_HideTime != 0 && !(m_HideTime < 0)) // make sure it's not 0 or less than 0...
{
m_HideTime -= fDeltaTime;
if(m_HideTime <= 0) // if we've gone past the magic point... hide the beast....
{
m_pActors[0].SetDiffuse( RageColor(0,0,0,0) );
2003-01-12 00:57:53 +00:00
}
}
2003-03-05 02:52:40 +00:00
*/
2002-09-29 05:06:18 +00:00
}
void BGAnimationLayer::Draw()
{
float fLastFOV = DISPLAY->GetMenuPerspectiveFOV();
if( m_fFOV != -1 )
DISPLAY->LoadMenuPerspective( m_fFOV );
2003-07-07 20:24:51 +00:00
if( m_bLighting )
{
DISPLAY->SetLighting( true );
DISPLAY->SetLightDirectional(
0,
RageColor(0.6f,0.6f,0.6f,1),
RageColor(0.9f,0.9f,0.9f,1),
2003-07-07 20:24:51 +00:00
RageColor(0,0,0,1),
RageVector3(0, 0, 1) );
}
for( unsigned i=0; i<m_pActors.size(); i++ )
m_pActors[i]->Draw();
2003-07-07 20:24:51 +00:00
if( m_fFOV != -1 )
DISPLAY->LoadMenuPerspective( fLastFOV );
2003-07-07 20:24:51 +00:00
if( m_bLighting )
{
DISPLAY->SetLightOff( 0 );
DISPLAY->SetLighting( false );
}
2003-03-05 02:52:40 +00:00
}
void BGAnimationLayer::SetDiffuse( RageColor c )
{
for(unsigned i=0; i<m_pActors.size(); i++)
m_pActors[i]->SetDiffuse(c);
2002-09-29 05:06:18 +00:00
}
void BGAnimationLayer::GainingFocus( float fRate, bool bRewindMovie, bool bLoop )
2002-09-29 05:06:18 +00:00
{
2003-04-14 04:56:57 +00:00
m_fUpdateRate = fRate;
// FIXME: Very dangerous. How could we handle this better?
Sprite* pSprite = (Sprite*)m_pActors[0];
pSprite->GetTexture()->SetPlaybackRate(fRate);
if( bRewindMovie )
pSprite->GetTexture()->SetPosition( 0 );
pSprite->GetTexture()->SetLooping(bLoop);
2002-09-29 05:06:18 +00:00
// if movie texture, pause and play movie so we don't waste CPU cycles decoding frames that won't be shown
pSprite->GetTexture()->Play();
2003-03-05 02:52:40 +00:00
for( unsigned i=0; i<m_pActors.size(); i++ )
2003-07-10 03:37:13 +00:00
m_pActors[i]->Command( m_sOnCommand );
2002-09-29 05:06:18 +00:00
}
void BGAnimationLayer::LosingFocus()
{
// FIXME: Very dangerous. How could we handle this better?
Sprite* pSprite = (Sprite*)m_pActors[0];
pSprite->GetTexture()->Pause();
2002-09-29 05:06:18 +00:00
}
2003-07-10 03:37:13 +00:00
void BGAnimationLayer::PlayOffCommand()
{
if( m_sOffCommand != "" )
{
for( unsigned i=0; i<m_pActors.size(); i++ )
m_pActors[i]->Command( m_sOffCommand );
}
}