bug fixes

This commit is contained in:
Chris Danford
2002-08-18 23:20:18 +00:00
parent 8b55061827
commit 5c21d4b1ca
15 changed files with 243 additions and 258 deletions
+14 -7
View File
@@ -114,15 +114,16 @@ keyboad, dance pad, or other game controller.
The following is a list of special keys. The following is a list of special keys.
Any time: Anywhere:
* F4 = toggle fullscreen * F4 = toggle fullscreen
* F5 = toggle detail * F5 = toggle detail
* Tab = increase game speed 4x (useful for moving through menus quickly) * Hold Tab = increase game speed 4x (useful for moving through menus quickly)
* LShift = decrease game speed to 1/4x * Hold LShift = decrease game speed to 1/4x
In menus: In menus:
* Arrow keys navigate menus * Arrow keys navigate menus
* Enter = Start, Escape = Back * Enter = Start
* Escape = Back
In gameplay: In gameplay:
* F8 = toggle AutoPlay * F8 = toggle AutoPlay
@@ -1141,8 +1142,10 @@ CHANGE: KSF title discovery will use song foler name if KSF file contains
BUG FIX: Stepping before start of a note at beat 0 no longer results in a BAD. BUG FIX: Stepping before start of a note at beat 0 no longer results in a BAD.
BUG FIX: Editor now works with dance-couple note patterns BUG FIX: Editor now works with dance-couple note patterns
BUG FIX: Lead-in/lead-out time added to Play and Record in editor. BUG FIX: Lead-in/lead-out time added to Play and Record in editor.
CHANGE: Song specific Background Animations removed in favor of a more powerful CHANGE: Song specific Background Animations removed. It will be replaced with
system. a more powerful system soon.
CHANGE: BGAnimations are now chose randomly from all animations rather than
from a specific group ("trance", "techno", etc).
NEW FEATURE: "Show Danger" toggle in game options to enable/disable NEW FEATURE: "Show Danger" toggle in game options to enable/disable
flashing danger message. flashing danger message.
CHANGE: "Event Mode" option renamed to "Unlimited Arcade Stages". CHANGE: "Event Mode" option renamed to "Unlimited Arcade Stages".
@@ -1153,9 +1156,13 @@ NEW FEATURE: Graphic Option "MovieDecodeMS". Controls how many milliseconds
CHANGE: "SongFolders" renamed to "AdditionalSongFolders". CHANGE: "SongFolders" renamed to "AdditionalSongFolders".
BUG FIX: AdditionalSongFolers no longer creates duplicate entries on program BUG FIX: AdditionalSongFolers no longer creates duplicate entries on program
load. load.
CHANGE: RandomMovies do not start playing until the first beat CHANGE: RandomMovies now start playing on the note and stop playing on the
last note.
CHANGE: Background Movies now start playing at beat 0, and the movie should
synchronize with the notes (BMR's Colors, etc).
OPTIMIZATION: New deferred rendering architecture uses more CPU in order to OPTIMIZATION: New deferred rendering architecture uses more CPU in order to
create more efficient operations for the graphics card. create more efficient operations for the graphics card.
BUG FIX: Select Group no longer crashes with > 15 groups.
------------------------CVS after 3.00 beta 5---------------- ------------------------CVS after 3.00 beta 5----------------
OPTIMIZATION: Much faster song loading. OPTIMIZATION: Much faster song loading.
+4 -4
View File
@@ -134,7 +134,7 @@ void Background::LoadFromSong( Song* pSong, bool bDisableVisualizations )
case MODE_MOVIE_BG: case MODE_MOVIE_BG:
{ {
pTempBGA = new BackgroundAnimation; pTempBGA = new BackgroundAnimation;
pTempBGA->LoadFromMovie( pSong->GetMovieBackgroundPath() ); pTempBGA->LoadFromMovieBG( pSong->GetMovieBackgroundPath() );
m_BackgroundAnimations.Add( pTempBGA ); m_BackgroundAnimations.Add( pTempBGA );
} }
break; break;
@@ -178,7 +178,7 @@ void Background::LoadFromSong( Song* pSong, bool bDisableVisualizations )
{ {
int index = rand() % arrayPossibleMovies.GetSize(); int index = rand() % arrayPossibleMovies.GetSize();
pTempBGA = new BackgroundAnimation; pTempBGA = new BackgroundAnimation;
pTempBGA->LoadFromMovie( arrayPossibleMovies[index] ); pTempBGA->LoadFromRandomMovie( arrayPossibleMovies[index] );
m_BackgroundAnimations.Add( pTempBGA ); m_BackgroundAnimations.Add( pTempBGA );
arrayPossibleMovies.RemoveAt( index ); arrayPossibleMovies.RemoveAt( index );
} }
@@ -221,13 +221,13 @@ void Background::LoadFromSong( Song* pSong, bool bDisableVisualizations )
const BPMSegment& bpmseg = pSong->m_BPMSegments[i]; const BPMSegment& bpmseg = pSong->m_BPMSegments[i];
if( bpmseg.m_fStartBeat < fFirstBeat || bpmseg.m_fStartBeat > fLastBeat ) if( bpmseg.m_fStartBeat < fFirstBeat || bpmseg.m_fStartBeat > fLastBeat )
continue; // skip continue; // skip]
int index; int index;
if( m_BackgroundAnimations.GetSize()==1 ) if( m_BackgroundAnimations.GetSize()==1 )
index = 0; index = 0;
else else
int index = 1 + int(bpmseg.m_fBPM)%(m_BackgroundAnimations.GetSize()-1); index = 1 + int(bpmseg.m_fBPM)%(m_BackgroundAnimations.GetSize()-1);
m_aAnimSegs.Add( AnimSeg(bpmseg.m_fStartBeat,index) ); m_aAnimSegs.Add( AnimSeg(bpmseg.m_fStartBeat,index) );
} }
+93 -76
View File
@@ -51,7 +51,7 @@ CTextureRenderer::CTextureRenderer( LPUNKNOWN pUnk, HRESULT *phr )
{ {
// Store and ARageef the texture for our use. // Store and ARageef the texture for our use.
m_pTexture = NULL; m_pTexture = NULL;
m_bLocked[0] = m_bLocked[1] = FALSE; m_bBackBufferLocked = FALSE;
*phr = S_OK; *phr = S_OK;
} }
@@ -157,23 +157,23 @@ HRESULT CTextureRenderer::DoRenderSample( IMediaSample * pSample )
pSample->GetPointer( &pBmpBuffer ); pSample->GetPointer( &pBmpBuffer );
// Find which texture we should render to. // Find which texture we should render to. We want to copy to the "back buffer"
LPDIRECT3DTEXTURE8 pD3DTexture; LPDIRECT3DTEXTURE8 pD3DTextureCopyTo;
switch( m_pTexture->m_iIndexFrontBuffer )
switch( m_pTexture->m_iIndexActiveTexture )
{ {
case 0: pD3DTexture = m_pTexture->m_pd3dTexture[1]; break; // 0 is active, so render to 1 case 0: pD3DTextureCopyTo = m_pTexture->m_pd3dTexture[1]; break; // 0 is front, so copy to 1
case 1: pD3DTexture = m_pTexture->m_pd3dTexture[0]; break; // 1 is active, so render to 0 case 1: pD3DTextureCopyTo = m_pTexture->m_pd3dTexture[0]; break; // 1 is front, so copy to 0
} }
// Lock the Texture // Lock the Texture
D3DLOCKED_RECT d3dlr; D3DLOCKED_RECT d3dlr;
if (FAILED(pD3DTexture->LockRect(0, &d3dlr, 0, 0))) { while( FAILED( pD3DTextureCopyTo->LockRect(0, &d3dlr, 0, 0) ) )
DXTRACE_ERR_NOMSGBOX(TEXT("Failed to lock the texture!"), E_FAIL); {
return E_FAIL; LOG->Warn( "Failed to lock the texture for rendering movie!" );
// keep trying until we get the lock
} }
m_bLocked[m_pTexture->m_iIndexActiveTexture] = TRUE; m_bBackBufferLocked = TRUE;
// Get the texture buffer & pitch // Get the texture buffer & pitch
pTxtBuffer = static_cast<byte *>(d3dlr.pBits); pTxtBuffer = static_cast<byte *>(d3dlr.pBits);
@@ -183,56 +183,65 @@ HRESULT CTextureRenderer::DoRenderSample( IMediaSample * pSample )
// Copy the bits // Copy the bits
// OPTIMIZATION OPPORTUNITY: Use a video and texture // OPTIMIZATION OPPORTUNITY: Use a video and texture
// format that allows a simpler copy than this one. // format that allows a simpler copy than this one.
if (m_TextureFormat == D3DFMT_A8R8G8B8) { switch( m_TextureFormat )
for(int y = 0; y < m_lVidHeight; y++ ) { {
BYTE *pBmpBufferOld = pBmpBuffer; case D3DFMT_A8R8G8B8:
BYTE *pTxtBufferOld = pTxtBuffer; {
for (int x = 0; x < m_lVidWidth; x++) { for(int y = 0; y < m_lVidHeight; y++ ) {
pTxtBuffer[0] = pBmpBuffer[0]; BYTE *pBmpBufferOld = pBmpBuffer;
pTxtBuffer[1] = pBmpBuffer[1]; BYTE *pTxtBufferOld = pTxtBuffer;
pTxtBuffer[2] = pBmpBuffer[2]; for (int x = 0; x < m_lVidWidth; x++) {
pTxtBuffer[3] = 0xff; pTxtBuffer[0] = pBmpBuffer[0];
pTxtBuffer += 4; pTxtBuffer[1] = pBmpBuffer[1];
pBmpBuffer += 3; pTxtBuffer[2] = pBmpBuffer[2];
} pTxtBuffer[3] = 0xff;
pBmpBuffer = pBmpBufferOld + m_lVidPitch; pTxtBuffer += 4;
pTxtBuffer = pTxtBufferOld + lTxtPitch; pBmpBuffer += 3;
} }
} pBmpBuffer = pBmpBufferOld + m_lVidPitch;
pTxtBuffer = pTxtBufferOld + lTxtPitch;
if (m_TextureFormat == D3DFMT_A1R5G5B5) { }
for(int y = 0; y < m_lVidHeight; y++ ) { }
BYTE *pBmpBufferOld = pBmpBuffer; break;
BYTE *pTxtBufferOld = pTxtBuffer; case D3DFMT_A1R5G5B5:
for (int x = 0; x < m_lVidWidth; x++) { {
*(WORD *)pTxtBuffer = for(int y = 0; y < m_lVidHeight; y++ ) {
0x8000 + BYTE *pBmpBufferOld = pBmpBuffer;
((pBmpBuffer[2] & 0xF8) << 7) + BYTE *pTxtBufferOld = pTxtBuffer;
((pBmpBuffer[1] & 0xF8) << 2) + for (int x = 0; x < m_lVidWidth; x++) {
(pBmpBuffer[0] >> 3); *(WORD *)pTxtBuffer =
pTxtBuffer += 2; 0x8000 +
pBmpBuffer += 3; ((pBmpBuffer[2] & 0xF8) << 7) +
} ((pBmpBuffer[1] & 0xF8) << 2) +
pBmpBuffer = pBmpBufferOld + m_lVidPitch; (pBmpBuffer[0] >> 3);
pTxtBuffer = pTxtBufferOld + lTxtPitch; pTxtBuffer += 2;
} pBmpBuffer += 3;
} }
pBmpBuffer = pBmpBufferOld + m_lVidPitch;
pTxtBuffer = pTxtBufferOld + lTxtPitch;
}
}
break;
default:
ASSERT(0);
}
// Unlock the Texture // Unlock the Texture
if (FAILED(pD3DTexture->UnlockRect(0))) { if( FAILED( pD3DTextureCopyTo->UnlockRect(0) ) )
DXTRACE_ERR_NOMSGBOX(TEXT("Failed to unlock the texture!"), E_FAIL); {
LOG->Warn( "Failed to unlock the texture!" );
return E_FAIL; return E_FAIL;
} }
m_bLocked[m_pTexture->m_iIndexActiveTexture] = FALSE; m_bBackBufferLocked = FALSE;
// flip active texture // flip active texture
switch( m_pTexture->m_iIndexActiveTexture ) switch( m_pTexture->m_iIndexFrontBuffer )
{ {
case 0: m_pTexture->m_iIndexActiveTexture = 1; break; case 0: m_pTexture->m_iIndexFrontBuffer = 1; break;
case 1: m_pTexture->m_iIndexActiveTexture = 0; break; case 1: m_pTexture->m_iIndexFrontBuffer = 0; break;
} }
@@ -257,7 +266,7 @@ RageMovieTexture::RageMovieTexture(
LOG->Trace( "RageBitmapTexture::RageBitmapTexture()" ); LOG->Trace( "RageBitmapTexture::RageBitmapTexture()" );
m_pd3dTexture[0] = m_pd3dTexture[1] = NULL; m_pd3dTexture[0] = m_pd3dTexture[1] = NULL;
m_iIndexActiveTexture = 0; m_iIndexFrontBuffer = 0;
Create(); Create();
@@ -269,6 +278,8 @@ RageMovieTexture::RageMovieTexture(
m_TextureCoordRects[i].top = m_TextureCoordRects[i].bottom; m_TextureCoordRects[i].top = m_TextureCoordRects[i].bottom;
m_TextureCoordRects[i].bottom = fTemp; m_TextureCoordRects[i].bottom = fTemp;
} }
m_bLoop = true;
} }
RageMovieTexture::~RageMovieTexture() RageMovieTexture::~RageMovieTexture()
@@ -296,23 +307,11 @@ void RageMovieTexture::Reload(
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
LPDIRECT3DTEXTURE8 RageMovieTexture::GetD3DTexture() LPDIRECT3DTEXTURE8 RageMovieTexture::GetD3DTexture()
{ {
// Wait until the TextureRenderer is not copying to our texture. CheckMovieStatus(); // restart the movie if we reach the end
// If we try to draw using the texture while it is locked, the primitive
// will appear without a texture.
// Most of the time, the TextureRenderer is not busy copying (copying
// a frame of video is very quick). If it is busy, it's usually becase
// the video fell behind and is trying to copy several frames in a row
// to catch up. So, if the TextureRenderer is busy, give it a 1ms slice of
// time for it to catch up and copy all the frames it fell behind on.
// while( m_pCTR->IsLocked() ) {
// ::Sleep(1);
// LOG->Trace( "Sleeping waiting for unlock..." );
// }
// restart the movie if we reach the end // Return the front buffer because it's guaranteed that CTextureRenderer
CheckMovieStatus(); // doesn't have it locked.
return m_pd3dTexture[m_iIndexFrontBuffer];
return m_pd3dTexture[m_iIndexActiveTexture];
} }
@@ -436,13 +435,13 @@ HRESULT RageMovieTexture::CreateD3DTexture()
if( FAILED( hr = D3DXCreateTexture(m_pd3dDevice, if( FAILED( hr = D3DXCreateTexture(m_pd3dDevice,
m_iSourceWidth, m_iSourceHeight, m_iSourceWidth, m_iSourceHeight,
1, 0, 1, 0,
D3DFMT_A8R8G8B8, D3DPOOL_MANAGED, &m_pd3dTexture[0] ) ) ) D3DFMT_A1R5G5B5, D3DPOOL_MANAGED, &m_pd3dTexture[0] ) ) )
throw RageException( hr, "Could not create the D3DX texture!" ); throw RageException( hr, "Could not create the D3DX texture!" );
if( FAILED( hr = D3DXCreateTexture(m_pd3dDevice, if( FAILED( hr = D3DXCreateTexture(m_pd3dDevice,
m_iSourceWidth, m_iSourceHeight, m_iSourceWidth, m_iSourceHeight,
1, 0, 1, 0,
D3DFMT_A8R8G8B8, D3DPOOL_MANAGED, &m_pd3dTexture[1] ) ) ) D3DFMT_A1R5G5B5, D3DPOOL_MANAGED, &m_pd3dTexture[1] ) ) )
throw RageException( hr, "Could not create the D3DX texture!" ); throw RageException( hr, "Could not create the D3DX texture!" );
// D3DXCreateTexture can silently change the parameters on us // D3DXCreateTexture can silently change the parameters on us
@@ -484,7 +483,7 @@ void RageMovieTexture::CheckMovieStatus()
// Check for completion events // Check for completion events
m_pME->GetEvent( &lEventCode, &lParam1, &lParam2, 0 ); m_pME->GetEvent( &lEventCode, &lParam1, &lParam2, 0 );
if( EC_COMPLETE == lEventCode ) if( EC_COMPLETE == lEventCode && m_bLoop )
m_pMP->put_CurrentPosition(0); m_pMP->put_CurrentPosition(0);
} }
@@ -504,11 +503,6 @@ void RageMovieTexture::Play()
PlayMovie(); PlayMovie();
} }
void RageMovieTexture::SetPosition( float fSeconds )
{
m_pMP->put_CurrentPosition(0);
}
void RageMovieTexture::Pause() void RageMovieTexture::Pause()
{ {
HRESULT hr; HRESULT hr;
@@ -516,3 +510,26 @@ void RageMovieTexture::Pause()
throw RageException( hr, "Could not pause the DirectShow graph." ); throw RageException( hr, "Could not pause the DirectShow graph." );
} }
void RageMovieTexture::Stop()
{
HRESULT hr;
if( FAILED( hr = m_pMC->Stop() ) )
throw RageException( hr, "Could not stop the DirectShow graph." );
}
void RageMovieTexture::TurnLoopOn()
{
m_bLoop = true;
}
void RageMovieTexture::TurnLoopOff()
{
m_bLoop = false;
}
void RageMovieTexture::SetPosition( float fSeconds )
{
m_pMP->put_CurrentPosition(0);
}
+7 -6
View File
@@ -51,7 +51,6 @@ public:
LONG GetVidWidth() {return m_lVidWidth;}; LONG GetVidWidth() {return m_lVidWidth;};
LONG GetVidHeight(){return m_lVidHeight;}; LONG GetVidHeight(){return m_lVidHeight;};
HRESULT SetRenderTarget( RageMovieTexture* pTexture ); HRESULT SetRenderTarget( RageMovieTexture* pTexture );
BOOL IsLocked(int iIndex) { return m_bLocked[iIndex]; };
protected: protected:
LONG m_lVidWidth; // Video width LONG m_lVidWidth; // Video width
@@ -60,8 +59,7 @@ protected:
RageMovieTexture* m_pTexture; // the video surface we will copy new frames to RageMovieTexture* m_pTexture; // the video surface we will copy new frames to
D3DFORMAT m_TextureFormat; // Texture format D3DFORMAT m_TextureFormat; // Texture format
BOOL m_bLocked[2]; // Is the texture currently locked while we BOOL m_bBackBufferLocked;
// copy the movie frame to it?
}; };
@@ -94,12 +92,15 @@ public:
LPDIRECT3DTEXTURE8 GetD3DTexture(); LPDIRECT3DTEXTURE8 GetD3DTexture();
virtual void Play(); virtual void Play();
virtual void SetPosition( float fSeconds );
virtual void Pause(); virtual void Pause();
virtual void Stop();
virtual void SetPosition( float fSeconds );
virtual bool IsAMovie() { return true; }; virtual bool IsAMovie() { return true; };
virtual void TurnLoopOn();
virtual void TurnLoopOff();
LPDIRECT3DTEXTURE8 m_pd3dTexture[2]; // double buffered LPDIRECT3DTEXTURE8 m_pd3dTexture[2]; // double buffered
int m_iIndexActiveTexture; // either 0 or 1 int m_iIndexFrontBuffer; // index of the buffer that should be rendered from - either 0 or 1
protected: protected:
virtual VOID Create(); virtual VOID Create();
@@ -118,5 +119,5 @@ protected:
CComPtr<IMediaPosition> m_pMP; // Media Postion CComPtr<IMediaPosition> m_pMP; // Media Postion
CComPtr<IMediaEvent> m_pME; // Media Event CComPtr<IMediaEvent> m_pME; // Media Event
CTextureRenderer *m_pCTR; // DShow Texture renderer CTextureRenderer *m_pCTR; // DShow Texture renderer
bool m_bLoop;
}; };
+8
View File
@@ -111,3 +111,11 @@ void RageTexture::GetFrameDimensionsFromFileName( CString sPath, int* piFramesWi
} }
} }
void RageTexture::TurnLoopOn()
{
}
void RageTexture::TurnLoopOff()
{
}
+4 -1
View File
@@ -61,9 +61,12 @@ public:
virtual LPDIRECT3DTEXTURE8 GetD3DTexture() = 0; virtual LPDIRECT3DTEXTURE8 GetD3DTexture() = 0;
virtual void Play() {}; virtual void Play() {};
virtual void SetPosition( float fSeconds ) {}; virtual void Stop() {};
virtual void Pause() {}; virtual void Pause() {};
virtual void SetPosition( float fSeconds ) {};
virtual bool IsAMovie() { return false; }; virtual bool IsAMovie() { return false; };
virtual void TurnLoopOn();
virtual void TurnLoopOff();
int GetSourceWidth() {return m_iSourceWidth;}; int GetSourceWidth() {return m_iSourceWidth;};
int GetSourceHeight() {return m_iSourceHeight;}; int GetSourceHeight() {return m_iSourceHeight;};
+1 -1
View File
@@ -93,7 +93,7 @@ void ScreenAppearanceOptions::ImportOptions()
CStringArray arrayThemeNames; CStringArray arrayThemeNames;
THEME->GetThemeNamesForCurGame( arrayThemeNames ); THEME->GetThemeNamesForCurGame( arrayThemeNames );
m_OptionLineData[AO_THEME].iNumOptions = arrayThemeNames.GetSize() + 1; m_OptionLineData[AO_THEME].iNumOptions = arrayThemeNames.GetSize();
for( i=0; i<arrayThemeNames.GetSize(); i++ ) for( i=0; i<arrayThemeNames.GetSize(); i++ )
strcpy( m_OptionLineData[AO_THEME].szOptionsText[i], arrayThemeNames[i] ); strcpy( m_OptionLineData[AO_THEME].szOptionsText[i], arrayThemeNames[i] );
+12 -6
View File
@@ -228,7 +228,7 @@ ScreenEdit::ScreenEdit()
m_textInfo.LoadFromFont( THEME->GetPathTo("Fonts","normal") ); m_textInfo.LoadFromFont( THEME->GetPathTo("Fonts","normal") );
m_textInfo.SetXY( INFO_X, INFO_Y ); m_textInfo.SetXY( INFO_X, INFO_Y );
m_textInfo.SetHorizAlign( Actor::align_right ); m_textInfo.SetHorizAlign( Actor::align_right );
m_textInfo.SetVertAlign( Actor::align_top ); m_textInfo.SetVertAlign( Actor::align_bottom );
m_textInfo.SetZoom( 0.5f ); m_textInfo.SetZoom( 0.5f );
m_textInfo.SetShadowLength( 2 ); m_textInfo.SetShadowLength( 2 );
//m_textInfo.SetText(); // set this below every frame //m_textInfo.SetText(); // set this below every frame
@@ -302,10 +302,10 @@ void ScreenEdit::Update( float fDeltaTime )
{ {
if( m_EditMode == MODE_RECORDING ) if( m_EditMode == MODE_RECORDING )
{ {
TransitionToEditFromRecord(); TransitionFromRecordToEdit();
GAMESTATE->m_fSongBeat = m_NoteFieldEdit.m_fEndMarker; GAMESTATE->m_fSongBeat = m_NoteFieldEdit.m_fEndMarker;
m_rectRecordBack.BeginTweening( 0.5f ); m_rectRecordBack.BeginTweening( 0.5f );
m_rectRecordBack.SetDiffuseColor( D3DXCOLOR(0,0,0,0) ); m_rectRecordBack.SetTweenDiffuseColor( D3DXCOLOR(0,0,0,0) );
} }
else if( m_EditMode == MODE_PLAYING ) else if( m_EditMode == MODE_PLAYING )
{ {
@@ -313,7 +313,7 @@ void ScreenEdit::Update( float fDeltaTime )
m_EditMode = MODE_EDITING; m_EditMode = MODE_EDITING;
GAMESTATE->m_fSongBeat = m_NoteFieldEdit.m_fEndMarker; GAMESTATE->m_fSongBeat = m_NoteFieldEdit.m_fEndMarker;
m_rectRecordBack.BeginTweening( 0.5f ); m_rectRecordBack.BeginTweening( 0.5f );
m_rectRecordBack.SetDiffuseColor( D3DXCOLOR(0,0,0,0) ); m_rectRecordBack.SetTweenDiffuseColor( D3DXCOLOR(0,0,0,0) );
} }
} }
} }
@@ -965,7 +965,11 @@ void ScreenEdit::InputRecord( const DeviceInput& DeviceI, const InputEventType t
switch( DeviceI.button ) switch( DeviceI.button )
{ {
case DIK_ESCAPE: case DIK_ESCAPE:
TransitionToEditFromRecord(); TransitionFromRecordToEdit();
m_rectRecordBack.BeginTweening( 0.5f );
m_rectRecordBack.SetTweenDiffuseColor( D3DXCOLOR(0,0,0,0) );
break; break;
} }
} }
@@ -1054,6 +1058,8 @@ void ScreenEdit::InputPlay( const DeviceInput& DeviceI, const InputEventType typ
case DIK_ESCAPE: case DIK_ESCAPE:
m_EditMode = MODE_EDITING; m_EditMode = MODE_EDITING;
m_soundMusic.Stop(); m_soundMusic.Stop();
m_rectRecordBack.BeginTweening( 0.5f );
m_rectRecordBack.SetTweenDiffuseColor( D3DXCOLOR(0,0,0,0) );
GAMESTATE->m_fSongBeat = froundf( GAMESTATE->m_fSongBeat, NoteTypeToBeat(m_SnapDisplay.GetSnapMode()) ); GAMESTATE->m_fSongBeat = froundf( GAMESTATE->m_fSongBeat, NoteTypeToBeat(m_SnapDisplay.GetSnapMode()) );
break; break;
@@ -1070,7 +1076,7 @@ void ScreenEdit::InputPlay( const DeviceInput& DeviceI, const InputEventType typ
} }
void ScreenEdit::TransitionToEditFromRecord() void ScreenEdit::TransitionFromRecordToEdit()
{ {
m_EditMode = MODE_EDITING; m_EditMode = MODE_EDITING;
m_soundMusic.Stop(); m_soundMusic.Stop();
+1 -1
View File
@@ -38,7 +38,7 @@ public:
void InputRecord( const DeviceInput& DeviceI, const InputEventType type, const GameInput &GameI, const MenuInput &MenuI, const StyleInput &StyleI ); void InputRecord( const DeviceInput& DeviceI, const InputEventType type, const GameInput &GameI, const MenuInput &MenuI, const StyleInput &StyleI );
void InputPlay( const DeviceInput& DeviceI, const InputEventType type, const GameInput &GameI, const MenuInput &MenuI, const StyleInput &StyleI ); void InputPlay( const DeviceInput& DeviceI, const InputEventType type, const GameInput &GameI, const MenuInput &MenuI, const StyleInput &StyleI );
virtual void HandleScreenMessage( const ScreenMessage SM ); virtual void HandleScreenMessage( const ScreenMessage SM );
void TransitionToEditFromRecord(); void TransitionFromRecordToEdit();
protected: protected:
+1 -1
View File
@@ -781,7 +781,7 @@ void ScreenGameplay::Update( float fDeltaTime )
if( fSongBeat > GAMESTATE->m_pCurSong->m_fLastBeat+4 ) if( fSongBeat > GAMESTATE->m_pCurSong->m_fLastBeat+4 )
{ {
GAMESTATE->m_fSongBeat = 0; GAMESTATE->m_fSongBeat = 0;
m_soundMusic.Stop(); m_soundMusic.Pause();
this->SendScreenMessage( SM_NotesEnded, 0 ); this->SendScreenMessage( SM_NotesEnded, 0 );
} }
+1 -1
View File
@@ -45,7 +45,7 @@ OptionLineData g_GraphicOptionsLines[NUM_GRAPHIC_OPTIONS_LINES] = {
{ "Show Stats", 2, {"OFF","ON"} }, { "Show Stats", 2, {"OFF","ON"} },
{ "BG Mode", 4, {"OFF","ANIMATIONS","VISUALIZATIONS","RANDOM MOVIES"} }, { "BG Mode", 4, {"OFF","ANIMATIONS","VISUALIZATIONS","RANDOM MOVIES"} },
{ "BG Brightness", 5, {"20%","40%","60%","80%","100%"} }, { "BG Brightness", 5, {"20%","40%","60%","80%","100%"} },
{ "Movie Decode", 5, {"1ms","2ms","3ms","4ms","5ms"} }, { "Movie Decode", 4, {"1ms","2ms","3ms","4ms"} },
}; };
ScreenGraphicOptions::ScreenGraphicOptions() : ScreenGraphicOptions::ScreenGraphicOptions() :
+87 -152
View File
@@ -68,125 +68,72 @@ ScreenSelectGroup::ScreenSelectGroup()
// style (such as solo) are omitted. Bear with me! // style (such as solo) are omitted. Bear with me!
// -- dro kulix // -- dro kulix
// m_arrayGroupNames will contain all relevant group names // Chris:
CMap<int, int, CArray<Song*, Song*>*, CArray<Song*, Song*>*> // This is excellent! I'm going to move the filtering of songs
mapGroupToSongArray; // Will contain all relevant songs // that can't be played by current style to be the first action.
// This will simply the code a bit, and fix a weird case that
// causes a crash when there are duplicate song names.
{ // Let's get local! CArray<Song*, Song*> aAllSongs;
// (There are some variables we want deallocated before continuing.) aAllSongs.Copy( SONGMAN->m_pSongs );
// Retrieve list of ALL song groups and ALL songs // Filter out Songs that can't be played by the current Style
NotesType nt = GAMESTATE->GetCurrentStyleDef()->m_NotesType;
SONGMAN->GetGroupNames( m_arrayGroupNames ); for( i=aAllSongs.GetSize()-1; i>=0; i-- ) // foreach Song, back to front
{
Song* pSong = aAllSongs[i];
CArray<Song*, Song*> arrayAllSongs; bool bSongCanBePlayedByCurrentStyle = false;
arrayAllSongs.Copy( SONGMAN->m_pSongs ); for( int j=0; j<pSong->m_apNotes.GetSize(); j++ ) // foreach Notes
// Retrieve the identities (Song*) of all songs under these groups
for( i=0; i<min(m_arrayGroupNames.GetSize(), MAX_GROUPS); i++ )
{ {
CArray<Song*, Song*> *p_arrayGroupSongs = new CArray<Song*, Song*>; Notes* pNotes = pSong->m_apNotes[j];
// WARNING! We are creating new objects that must be destroyed.
const CString &sCurGroupName = m_arrayGroupNames[i];
SONGMAN->GetSongsInGroup( sCurGroupName, *p_arrayGroupSongs ); if( pNotes->m_NotesType == nt )
mapGroupToSongArray.SetAt(GetHashForString(sCurGroupName), p_arrayGroupSongs);
}
{
// Add "ALL MUSIC" group
CArray<Song*, Song*> *p_arrayGroupSongs = new CArray<Song*, Song*>;
// WARNING! (Same as last.)
m_arrayGroupNames.InsertAt(0, "ALL MUSIC");
p_arrayGroupSongs->Copy( arrayAllSongs );
mapGroupToSongArray.SetAt(GetHashForString("ALL MUSIC"), p_arrayGroupSongs);
}
// Now, create a map of all songs to their support for the current style.
// (Song *) -> (Support current style?)
CMap<Song*, Song*, bool, bool> mapStyleSupport;
mapStyleSupport.InitHashTable(arrayAllSongs.GetSize());
// The following loop is functionally identical to one used in MusicWheel
NotesType curNotesType = GAMESTATE->GetCurrentStyleDef()->m_NotesType;
for( i=0; i<arrayAllSongs.GetSize(); i++ )
{
CArray<Notes*, Notes*> arraySteps;
arrayAllSongs.GetAt(i)->GetNotesThatMatch( curNotesType, arraySteps );
if( arraySteps.GetSize() > 0 )
mapStyleSupport.SetAt(arrayAllSongs.GetAt(i), true);
else
mapStyleSupport.SetAt(arrayAllSongs.GetAt(i), false);
}
// Here's the fun part!
// Recurse each group of songs, removing the ones unsupported by this style.
// If a group ends up empty, remove it from the list.
{
int gi = 0;
// Group iteration
while (gi < m_arrayGroupNames.GetSize())
{ {
bSongCanBePlayedByCurrentStyle = true;
int si = 0; break;
int curKey = GetHashForString(m_arrayGroupNames.GetAt(gi));
CArray <Song*, Song*>* p_arrayGroupSongs = 0;
mapGroupToSongArray.Lookup(curKey, p_arrayGroupSongs);
// Song iteration
while (si < p_arrayGroupSongs->GetSize())
{
Song* curSong = p_arrayGroupSongs->GetAt(si);
bool bSongSupported = false;
mapStyleSupport.Lookup(curSong, bSongSupported);
if (bSongSupported)
{
// Increment only if no remove
si++;
}
else
{
// Remove
p_arrayGroupSongs->RemoveAt(si);
}
}
// Do we remove group?
// Never remove "ALL MUSIC".
if ( (gi > 0) && (p_arrayGroupSongs->GetSize() <= 0) )
{
// Yes, remove group, since it is empty and is not "ALL MUSIC".
// Deallocate empty song array
delete p_arrayGroupSongs;
// Remove from groups array and map
mapGroupToSongArray.RemoveKey(curKey);
m_arrayGroupNames.RemoveAt(gi);
}
else
{
// Keep this group; move on.
gi++;
}
} }
} // End recurse }
} // Ends local song-paring block. if( !bSongCanBePlayedByCurrentStyle )
aAllSongs.RemoveAt( i );
}
// Get group names by thowing them into a hash
CMapStringToString mapGroupToNothing;
for( i=0; i<aAllSongs.GetSize(); i++ ) // foreach Song
mapGroupToNothing[ aAllSongs[i]->m_sGroupName ] = "";
// Read group names back out into an m_asGroupNames
m_asGroupNames.Add( "ALL MUSIC" );
for( POSITION pos = mapGroupToNothing.GetStartPosition(); pos != NULL; )
{
CString sGroupName, sValue;
mapGroupToNothing.GetNextAssoc( pos, sGroupName, sValue );
m_asGroupNames.Add( sGroupName );
if( m_asGroupNames.GetSize() == MAX_GROUPS-1 )
break; // stop adding
}
SortCStringArray( m_asGroupNames, true );
// Add songs to groups (this isn't very efficient, but oh well...
CArray<Song*,Song*> aSongsInGroup[MAX_GROUPS];
aSongsInGroup[0].Copy( aAllSongs ); // add to ALL MUSIC
for( i=0; i<aAllSongs.GetSize(); i++ ) // foreach Song
{
Song* pSong = aAllSongs[i];
// find the corresponding group
for( int j=1; j<m_asGroupNames.GetSize(); j++ )
{
if( pSong->m_sGroupName == m_asGroupNames[j] )
{
aSongsInGroup[j].Add( pSong );
break;
}
}
}
// Retrieve list of song groups
//SONGMAN->GetGroupNames( m_arrayGroupNames );
//m_arrayGroupNames.InsertAt( 0, "ALL MUSIC" );
@@ -236,10 +183,9 @@ ScreenSelectGroup::ScreenSelectGroup()
} }
// This part is still compatible with the new pare routine. for( i=0; i<min(m_asGroupNames.GetSize(), MAX_GROUPS); i++ )
for( i=0; i<min(m_arrayGroupNames.GetSize(), MAX_GROUPS); i++ )
{ {
CString sGroupName = m_arrayGroupNames[i]; CString sGroupName = m_asGroupNames[i];
m_sprButton[i].Load( THEME->GetPathTo("Graphics","select group button") ); m_sprButton[i].Load( THEME->GetPathTo("Graphics","select group button") );
m_sprButton[i].SetXY( BUTTON_X, BUTTON_START_Y + i*BUTTON_SPACING_Y ); m_sprButton[i].SetXY( BUTTON_X, BUTTON_START_Y + i*BUTTON_SPACING_Y );
@@ -262,29 +208,35 @@ ScreenSelectGroup::ScreenSelectGroup()
// //
// Generate what text will show in the contents for each group // Generate what text will show in the contents for each group
// //
// This block is modified for the new paring routine for( i=0; i<min(m_asGroupNames.GetSize(), MAX_GROUPS); i++ )
for( i=0; i<min(m_arrayGroupNames.GetSize(), MAX_GROUPS); i++ )
{ {
CArray<Song*, Song*>* p_arraySongs; CArray<Song*,Song*>& aSongs = aSongsInGroup[i];
const CString &sCurGroupName = m_arrayGroupNames[i]; m_iNumSongsInGroup[i] = aSongs.GetSize();
SortSongPointerArrayByTitle( aSongs );
mapGroupToSongArray.Lookup( GetHashForString(sCurGroupName), p_arraySongs); for( int c=0; c<TITLES_COLUMNS; c++ ) // foreach col
m_iNumSongsInGroup[i] = p_arraySongs->GetSize();
SortSongPointerArrayByTitle( *p_arraySongs );
for( int c=0; c<TITLES_COLUMNS; c++ )
{ {
CString sText; CString sText;
for( int j=c*TITLES_ROWS; j<(c+1)*TITLES_ROWS; j++ ) for( int r=0; r<TITLES_ROWS; r++ ) // foreach row
{ {
if( j < p_arraySongs->GetSize() ) int iIndex = c*TITLES_ROWS + r;
if( iIndex < aSongs.GetSize() )
{ {
if( j == TITLES_COLUMNS * TITLES_ROWS - 1 ) if( c == TITLES_COLUMNS-1 && r == TITLES_ROWS-1 )
sText += ssprintf( "%d more.....", p_arraySongs->GetSize() - TITLES_COLUMNS * TITLES_ROWS - 1 ); {
sText += ssprintf( "%d more.....", aSongs.GetSize() - TITLES_COLUMNS * TITLES_ROWS - 1 );
}
else else
sText += (*p_arraySongs)[j]->GetFullTitle() + "\n"; {
CString sTitle = aSongs[iIndex]->GetFullTitle();
// TODO: Move this crop threshold into a theme metric or make automatic based on column width
if( sTitle.GetLength() > 40 )
{
sTitle = sTitle.Left( 37 );
sTitle += "...";
}
sText += sTitle + "\n";
}
} }
} }
m_sContentsText[i][c] = sText; m_sContentsText[i][c] = sText;
@@ -306,23 +258,6 @@ ScreenSelectGroup::ScreenSelectGroup()
m_Menu.TweenOnScreenFromMenu( SM_None ); m_Menu.TweenOnScreenFromMenu( SM_None );
TweenOnScreen(); TweenOnScreen();
AfterChange(); AfterChange();
// Deallocate remaining song arrays in map
{
int csKey;
CArray<Song*, Song*>* pSongArray;
POSITION Pos;
Pos = mapGroupToSongArray.GetStartPosition();
while (Pos)
{
mapGroupToSongArray.GetNextAssoc(Pos, csKey, pSongArray);
delete pSongArray;
}
}
} }
@@ -397,7 +332,7 @@ void ScreenSelectGroup::AfterChange()
for( int c=0; c<TITLES_COLUMNS; c++ ) for( int c=0; c<TITLES_COLUMNS; c++ )
m_textTitles[c].SetText( m_sContentsText[m_iSelection][c] ); m_textTitles[c].SetText( m_sContentsText[m_iSelection][c] );
CString sSelectedGroupName = m_arrayGroupNames[m_iSelection]; CString sSelectedGroupName = m_asGroupNames[m_iSelection];
CString sGroupBannerPath; CString sGroupBannerPath;
if( 0 == stricmp(sSelectedGroupName, "ALL MUSIC") ) if( 0 == stricmp(sSelectedGroupName, "ALL MUSIC") )
@@ -431,9 +366,9 @@ void ScreenSelectGroup::MenuUp( const PlayerNumber p )
BeforeChange(); BeforeChange();
m_iSelection = m_iSelection-1 % m_arrayGroupNames.GetSize(); m_iSelection = m_iSelection-1 % m_asGroupNames.GetSize();
if( m_iSelection < 0 ) if( m_iSelection < 0 )
m_iSelection += min( m_arrayGroupNames.GetSize(), MAX_GROUPS ); m_iSelection += min( m_asGroupNames.GetSize(), MAX_GROUPS );
AfterChange(); AfterChange();
@@ -448,7 +383,7 @@ void ScreenSelectGroup::MenuDown( const PlayerNumber p )
BeforeChange(); BeforeChange();
m_iSelection = (m_iSelection+1) % min( m_arrayGroupNames.GetSize(), MAX_GROUPS ); m_iSelection = (m_iSelection+1) % min( m_asGroupNames.GetSize(), MAX_GROUPS );
AfterChange(); AfterChange();
@@ -461,7 +396,7 @@ void ScreenSelectGroup::MenuStart( const PlayerNumber p )
m_bChosen = true; m_bChosen = true;
GAMESTATE->m_pCurSong = NULL; GAMESTATE->m_pCurSong = NULL;
GAMESTATE->m_sPreferredGroup = m_arrayGroupNames[m_iSelection]; GAMESTATE->m_sPreferredGroup = m_asGroupNames[m_iSelection];
if( 0 == stricmp(GAMESTATE->m_sPreferredGroup, "All Music") ) if( 0 == stricmp(GAMESTATE->m_sPreferredGroup, "All Music") )
SOUND->PlayOnceStreamedFromDir( ANNOUNCER->GetPathTo(ANNOUNCER_SELECT_GROUP_COMMENT_ALL_MUSIC) ); SOUND->PlayOnceStreamedFromDir( ANNOUNCER->GetPathTo(ANNOUNCER_SELECT_GROUP_COMMENT_ALL_MUSIC) );
@@ -505,7 +440,7 @@ void ScreenSelectGroup::TweenOffScreen()
} }
for( i=0; i<min(m_arrayGroupNames.GetSize(), MAX_GROUPS); i++ ) for( i=0; i<min(m_asGroupNames.GetSize(), MAX_GROUPS); i++ )
{ {
if( i == m_iSelection ) if( i == m_iSelection )
m_sprButton[i].BeginTweeningQueued( 1.0f, TWEEN_BOUNCE_BEGIN ); m_sprButton[i].BeginTweeningQueued( 1.0f, TWEEN_BOUNCE_BEGIN );
@@ -553,7 +488,7 @@ void ScreenSelectGroup::TweenOnScreen()
} }
for( i=0; i<min(m_arrayGroupNames.GetSize(), MAX_GROUPS); i++ ) for( i=0; i<min(m_asGroupNames.GetSize(), MAX_GROUPS); i++ )
{ {
m_sprButton[i].SetX( BUTTON_X+400 ); m_sprButton[i].SetX( BUTTON_X+400 );
m_sprButton[i].BeginTweeningQueued( 0.1f*i, TWEEN_BOUNCE_END ); m_sprButton[i].BeginTweeningQueued( 0.1f*i, TWEEN_BOUNCE_END );
+1 -1
View File
@@ -64,7 +64,7 @@ private:
RandomSample m_soundSelect; RandomSample m_soundSelect;
RandomSample m_soundFlyOff; RandomSample m_soundFlyOff;
CStringArray m_arrayGroupNames; CStringArray m_asGroupNames;
int m_iSelection; int m_iSelection;
bool m_bChosen; bool m_bChosen;
}; };
+5
View File
@@ -136,6 +136,11 @@ void Song::AddAnimationSegment( AnimationSegment seg )
SortAnimationSegmentsArray( m_AnimationSegments ); SortAnimationSegmentsArray( m_AnimationSegments );
} }
float Song::GetMusicStartBeat()
{
float fBPS = m_BPMSegments[0].m_fBPM / 60.0f;
return -m_fBeat0OffsetInSeconds*fBPS;
};
void Song::GetBeatAndBPSFromElapsedTime( float fElapsedTime, float &fBeatOut, float &fBPSOut, bool &bFreezeOut ) void Song::GetBeatAndBPSFromElapsedTime( float fElapsedTime, float &fBeatOut, float &fBPSOut, bool &bFreezeOut )
{ {
+3
View File
@@ -87,6 +87,9 @@ public:
float m_fLastBeat; float m_fLastBeat;
float m_fMusicSampleStartSeconds; float m_fMusicSampleStartSeconds;
float m_fMusicSampleLengthSeconds; float m_fMusicSampleLengthSeconds;
float GetMusicStartBeat();
CString m_sBannerFile; CString m_sBannerFile;
CString m_sBackgroundFile; CString m_sBackgroundFile;
CString m_sCDTitleFile; CString m_sCDTitleFile;