bug fixes
This commit is contained in:
@@ -114,15 +114,16 @@ keyboad, dance pad, or other game controller.
|
||||
|
||||
The following is a list of special keys.
|
||||
|
||||
Any time:
|
||||
Anywhere:
|
||||
* F4 = toggle fullscreen
|
||||
* F5 = toggle detail
|
||||
* Tab = increase game speed 4x (useful for moving through menus quickly)
|
||||
* LShift = decrease game speed to 1/4x
|
||||
* Hold Tab = increase game speed 4x (useful for moving through menus quickly)
|
||||
* Hold LShift = decrease game speed to 1/4x
|
||||
|
||||
In menus:
|
||||
* Arrow keys navigate menus
|
||||
* Enter = Start, Escape = Back
|
||||
* Enter = Start
|
||||
* Escape = Back
|
||||
|
||||
In gameplay:
|
||||
* 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: Editor now works with dance-couple note patterns
|
||||
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
|
||||
system.
|
||||
CHANGE: Song specific Background Animations removed. It will be replaced with
|
||||
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
|
||||
flashing danger message.
|
||||
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".
|
||||
BUG FIX: AdditionalSongFolers no longer creates duplicate entries on program
|
||||
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
|
||||
create more efficient operations for the graphics card.
|
||||
BUG FIX: Select Group no longer crashes with > 15 groups.
|
||||
|
||||
------------------------CVS after 3.00 beta 5----------------
|
||||
OPTIMIZATION: Much faster song loading.
|
||||
|
||||
@@ -134,7 +134,7 @@ void Background::LoadFromSong( Song* pSong, bool bDisableVisualizations )
|
||||
case MODE_MOVIE_BG:
|
||||
{
|
||||
pTempBGA = new BackgroundAnimation;
|
||||
pTempBGA->LoadFromMovie( pSong->GetMovieBackgroundPath() );
|
||||
pTempBGA->LoadFromMovieBG( pSong->GetMovieBackgroundPath() );
|
||||
m_BackgroundAnimations.Add( pTempBGA );
|
||||
}
|
||||
break;
|
||||
@@ -178,7 +178,7 @@ void Background::LoadFromSong( Song* pSong, bool bDisableVisualizations )
|
||||
{
|
||||
int index = rand() % arrayPossibleMovies.GetSize();
|
||||
pTempBGA = new BackgroundAnimation;
|
||||
pTempBGA->LoadFromMovie( arrayPossibleMovies[index] );
|
||||
pTempBGA->LoadFromRandomMovie( arrayPossibleMovies[index] );
|
||||
m_BackgroundAnimations.Add( pTempBGA );
|
||||
arrayPossibleMovies.RemoveAt( index );
|
||||
}
|
||||
@@ -221,13 +221,13 @@ void Background::LoadFromSong( Song* pSong, bool bDisableVisualizations )
|
||||
const BPMSegment& bpmseg = pSong->m_BPMSegments[i];
|
||||
|
||||
if( bpmseg.m_fStartBeat < fFirstBeat || bpmseg.m_fStartBeat > fLastBeat )
|
||||
continue; // skip
|
||||
continue; // skip]
|
||||
|
||||
int index;
|
||||
if( m_BackgroundAnimations.GetSize()==1 )
|
||||
index = 0;
|
||||
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) );
|
||||
}
|
||||
|
||||
|
||||
@@ -51,7 +51,7 @@ CTextureRenderer::CTextureRenderer( LPUNKNOWN pUnk, HRESULT *phr )
|
||||
{
|
||||
// Store and ARageef the texture for our use.
|
||||
m_pTexture = NULL;
|
||||
m_bLocked[0] = m_bLocked[1] = FALSE;
|
||||
m_bBackBufferLocked = FALSE;
|
||||
*phr = S_OK;
|
||||
}
|
||||
|
||||
@@ -157,23 +157,23 @@ HRESULT CTextureRenderer::DoRenderSample( IMediaSample * pSample )
|
||||
pSample->GetPointer( &pBmpBuffer );
|
||||
|
||||
|
||||
// Find which texture we should render to.
|
||||
LPDIRECT3DTEXTURE8 pD3DTexture;
|
||||
|
||||
switch( m_pTexture->m_iIndexActiveTexture )
|
||||
// Find which texture we should render to. We want to copy to the "back buffer"
|
||||
LPDIRECT3DTEXTURE8 pD3DTextureCopyTo;
|
||||
switch( m_pTexture->m_iIndexFrontBuffer )
|
||||
{
|
||||
case 0: pD3DTexture = m_pTexture->m_pd3dTexture[1]; break; // 0 is active, so render to 1
|
||||
case 1: pD3DTexture = m_pTexture->m_pd3dTexture[0]; break; // 1 is active, so render to 0
|
||||
case 0: pD3DTextureCopyTo = m_pTexture->m_pd3dTexture[1]; break; // 0 is front, so copy to 1
|
||||
case 1: pD3DTextureCopyTo = m_pTexture->m_pd3dTexture[0]; break; // 1 is front, so copy to 0
|
||||
}
|
||||
|
||||
// Lock the Texture
|
||||
D3DLOCKED_RECT d3dlr;
|
||||
if (FAILED(pD3DTexture->LockRect(0, &d3dlr, 0, 0))) {
|
||||
DXTRACE_ERR_NOMSGBOX(TEXT("Failed to lock the texture!"), E_FAIL);
|
||||
return E_FAIL;
|
||||
while( FAILED( pD3DTextureCopyTo->LockRect(0, &d3dlr, 0, 0) ) )
|
||||
{
|
||||
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
|
||||
pTxtBuffer = static_cast<byte *>(d3dlr.pBits);
|
||||
@@ -183,56 +183,65 @@ HRESULT CTextureRenderer::DoRenderSample( IMediaSample * pSample )
|
||||
// Copy the bits
|
||||
// OPTIMIZATION OPPORTUNITY: Use a video and texture
|
||||
// format that allows a simpler copy than this one.
|
||||
if (m_TextureFormat == D3DFMT_A8R8G8B8) {
|
||||
for(int y = 0; y < m_lVidHeight; y++ ) {
|
||||
BYTE *pBmpBufferOld = pBmpBuffer;
|
||||
BYTE *pTxtBufferOld = pTxtBuffer;
|
||||
for (int x = 0; x < m_lVidWidth; x++) {
|
||||
pTxtBuffer[0] = pBmpBuffer[0];
|
||||
pTxtBuffer[1] = pBmpBuffer[1];
|
||||
pTxtBuffer[2] = pBmpBuffer[2];
|
||||
pTxtBuffer[3] = 0xff;
|
||||
pTxtBuffer += 4;
|
||||
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;
|
||||
BYTE *pTxtBufferOld = pTxtBuffer;
|
||||
for (int x = 0; x < m_lVidWidth; x++) {
|
||||
*(WORD *)pTxtBuffer =
|
||||
0x8000 +
|
||||
((pBmpBuffer[2] & 0xF8) << 7) +
|
||||
((pBmpBuffer[1] & 0xF8) << 2) +
|
||||
(pBmpBuffer[0] >> 3);
|
||||
pTxtBuffer += 2;
|
||||
pBmpBuffer += 3;
|
||||
}
|
||||
pBmpBuffer = pBmpBufferOld + m_lVidPitch;
|
||||
pTxtBuffer = pTxtBufferOld + lTxtPitch;
|
||||
}
|
||||
}
|
||||
switch( m_TextureFormat )
|
||||
{
|
||||
case D3DFMT_A8R8G8B8:
|
||||
{
|
||||
for(int y = 0; y < m_lVidHeight; y++ ) {
|
||||
BYTE *pBmpBufferOld = pBmpBuffer;
|
||||
BYTE *pTxtBufferOld = pTxtBuffer;
|
||||
for (int x = 0; x < m_lVidWidth; x++) {
|
||||
pTxtBuffer[0] = pBmpBuffer[0];
|
||||
pTxtBuffer[1] = pBmpBuffer[1];
|
||||
pTxtBuffer[2] = pBmpBuffer[2];
|
||||
pTxtBuffer[3] = 0xff;
|
||||
pTxtBuffer += 4;
|
||||
pBmpBuffer += 3;
|
||||
}
|
||||
pBmpBuffer = pBmpBufferOld + m_lVidPitch;
|
||||
pTxtBuffer = pTxtBufferOld + lTxtPitch;
|
||||
}
|
||||
}
|
||||
break;
|
||||
case D3DFMT_A1R5G5B5:
|
||||
{
|
||||
for(int y = 0; y < m_lVidHeight; y++ ) {
|
||||
BYTE *pBmpBufferOld = pBmpBuffer;
|
||||
BYTE *pTxtBufferOld = pTxtBuffer;
|
||||
for (int x = 0; x < m_lVidWidth; x++) {
|
||||
*(WORD *)pTxtBuffer =
|
||||
0x8000 +
|
||||
((pBmpBuffer[2] & 0xF8) << 7) +
|
||||
((pBmpBuffer[1] & 0xF8) << 2) +
|
||||
(pBmpBuffer[0] >> 3);
|
||||
pTxtBuffer += 2;
|
||||
pBmpBuffer += 3;
|
||||
}
|
||||
pBmpBuffer = pBmpBufferOld + m_lVidPitch;
|
||||
pTxtBuffer = pTxtBufferOld + lTxtPitch;
|
||||
}
|
||||
}
|
||||
break;
|
||||
default:
|
||||
ASSERT(0);
|
||||
}
|
||||
|
||||
|
||||
// Unlock the Texture
|
||||
if (FAILED(pD3DTexture->UnlockRect(0))) {
|
||||
DXTRACE_ERR_NOMSGBOX(TEXT("Failed to unlock the texture!"), E_FAIL);
|
||||
if( FAILED( pD3DTextureCopyTo->UnlockRect(0) ) )
|
||||
{
|
||||
LOG->Warn( "Failed to unlock the texture!" );
|
||||
return E_FAIL;
|
||||
}
|
||||
|
||||
m_bLocked[m_pTexture->m_iIndexActiveTexture] = FALSE;
|
||||
m_bBackBufferLocked = FALSE;
|
||||
|
||||
|
||||
// flip active texture
|
||||
switch( m_pTexture->m_iIndexActiveTexture )
|
||||
switch( m_pTexture->m_iIndexFrontBuffer )
|
||||
{
|
||||
case 0: m_pTexture->m_iIndexActiveTexture = 1; break;
|
||||
case 1: m_pTexture->m_iIndexActiveTexture = 0; break;
|
||||
case 0: m_pTexture->m_iIndexFrontBuffer = 1; break;
|
||||
case 1: m_pTexture->m_iIndexFrontBuffer = 0; break;
|
||||
}
|
||||
|
||||
|
||||
@@ -257,7 +266,7 @@ RageMovieTexture::RageMovieTexture(
|
||||
LOG->Trace( "RageBitmapTexture::RageBitmapTexture()" );
|
||||
|
||||
m_pd3dTexture[0] = m_pd3dTexture[1] = NULL;
|
||||
m_iIndexActiveTexture = 0;
|
||||
m_iIndexFrontBuffer = 0;
|
||||
|
||||
Create();
|
||||
|
||||
@@ -269,6 +278,8 @@ RageMovieTexture::RageMovieTexture(
|
||||
m_TextureCoordRects[i].top = m_TextureCoordRects[i].bottom;
|
||||
m_TextureCoordRects[i].bottom = fTemp;
|
||||
}
|
||||
|
||||
m_bLoop = true;
|
||||
}
|
||||
|
||||
RageMovieTexture::~RageMovieTexture()
|
||||
@@ -296,23 +307,11 @@ void RageMovieTexture::Reload(
|
||||
//-----------------------------------------------------------------------------
|
||||
LPDIRECT3DTEXTURE8 RageMovieTexture::GetD3DTexture()
|
||||
{
|
||||
// Wait until the TextureRenderer is not copying to our texture.
|
||||
// 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..." );
|
||||
// }
|
||||
CheckMovieStatus(); // restart the movie if we reach the end
|
||||
|
||||
// restart the movie if we reach the end
|
||||
CheckMovieStatus();
|
||||
|
||||
return m_pd3dTexture[m_iIndexActiveTexture];
|
||||
// Return the front buffer because it's guaranteed that CTextureRenderer
|
||||
// doesn't have it locked.
|
||||
return m_pd3dTexture[m_iIndexFrontBuffer];
|
||||
}
|
||||
|
||||
|
||||
@@ -436,13 +435,13 @@ HRESULT RageMovieTexture::CreateD3DTexture()
|
||||
if( FAILED( hr = D3DXCreateTexture(m_pd3dDevice,
|
||||
m_iSourceWidth, m_iSourceHeight,
|
||||
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!" );
|
||||
|
||||
if( FAILED( hr = D3DXCreateTexture(m_pd3dDevice,
|
||||
m_iSourceWidth, m_iSourceHeight,
|
||||
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!" );
|
||||
|
||||
// D3DXCreateTexture can silently change the parameters on us
|
||||
@@ -484,7 +483,7 @@ void RageMovieTexture::CheckMovieStatus()
|
||||
|
||||
// Check for completion events
|
||||
m_pME->GetEvent( &lEventCode, &lParam1, &lParam2, 0 );
|
||||
if( EC_COMPLETE == lEventCode )
|
||||
if( EC_COMPLETE == lEventCode && m_bLoop )
|
||||
m_pMP->put_CurrentPosition(0);
|
||||
}
|
||||
|
||||
@@ -504,11 +503,6 @@ void RageMovieTexture::Play()
|
||||
PlayMovie();
|
||||
}
|
||||
|
||||
void RageMovieTexture::SetPosition( float fSeconds )
|
||||
{
|
||||
m_pMP->put_CurrentPosition(0);
|
||||
}
|
||||
|
||||
void RageMovieTexture::Pause()
|
||||
{
|
||||
HRESULT hr;
|
||||
@@ -516,3 +510,26 @@ void RageMovieTexture::Pause()
|
||||
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);
|
||||
}
|
||||
|
||||
|
||||
@@ -51,7 +51,6 @@ public:
|
||||
LONG GetVidWidth() {return m_lVidWidth;};
|
||||
LONG GetVidHeight(){return m_lVidHeight;};
|
||||
HRESULT SetRenderTarget( RageMovieTexture* pTexture );
|
||||
BOOL IsLocked(int iIndex) { return m_bLocked[iIndex]; };
|
||||
|
||||
protected:
|
||||
LONG m_lVidWidth; // Video width
|
||||
@@ -60,8 +59,7 @@ protected:
|
||||
|
||||
RageMovieTexture* m_pTexture; // the video surface we will copy new frames to
|
||||
D3DFORMAT m_TextureFormat; // Texture format
|
||||
BOOL m_bLocked[2]; // Is the texture currently locked while we
|
||||
// copy the movie frame to it?
|
||||
BOOL m_bBackBufferLocked;
|
||||
};
|
||||
|
||||
|
||||
@@ -94,12 +92,15 @@ public:
|
||||
|
||||
LPDIRECT3DTEXTURE8 GetD3DTexture();
|
||||
virtual void Play();
|
||||
virtual void SetPosition( float fSeconds );
|
||||
virtual void Pause();
|
||||
virtual void Stop();
|
||||
virtual void SetPosition( float fSeconds );
|
||||
virtual bool IsAMovie() { return true; };
|
||||
virtual void TurnLoopOn();
|
||||
virtual void TurnLoopOff();
|
||||
|
||||
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:
|
||||
virtual VOID Create();
|
||||
@@ -118,5 +119,5 @@ protected:
|
||||
CComPtr<IMediaPosition> m_pMP; // Media Postion
|
||||
CComPtr<IMediaEvent> m_pME; // Media Event
|
||||
CTextureRenderer *m_pCTR; // DShow Texture renderer
|
||||
|
||||
bool m_bLoop;
|
||||
};
|
||||
|
||||
@@ -111,3 +111,11 @@ void RageTexture::GetFrameDimensionsFromFileName( CString sPath, int* piFramesWi
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void RageTexture::TurnLoopOn()
|
||||
{
|
||||
}
|
||||
|
||||
void RageTexture::TurnLoopOff()
|
||||
{
|
||||
}
|
||||
|
||||
@@ -61,9 +61,12 @@ public:
|
||||
|
||||
virtual LPDIRECT3DTEXTURE8 GetD3DTexture() = 0;
|
||||
virtual void Play() {};
|
||||
virtual void SetPosition( float fSeconds ) {};
|
||||
virtual void Stop() {};
|
||||
virtual void Pause() {};
|
||||
virtual void SetPosition( float fSeconds ) {};
|
||||
virtual bool IsAMovie() { return false; };
|
||||
virtual void TurnLoopOn();
|
||||
virtual void TurnLoopOff();
|
||||
|
||||
int GetSourceWidth() {return m_iSourceWidth;};
|
||||
int GetSourceHeight() {return m_iSourceHeight;};
|
||||
|
||||
@@ -93,7 +93,7 @@ void ScreenAppearanceOptions::ImportOptions()
|
||||
CStringArray 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++ )
|
||||
strcpy( m_OptionLineData[AO_THEME].szOptionsText[i], arrayThemeNames[i] );
|
||||
|
||||
@@ -228,7 +228,7 @@ ScreenEdit::ScreenEdit()
|
||||
m_textInfo.LoadFromFont( THEME->GetPathTo("Fonts","normal") );
|
||||
m_textInfo.SetXY( INFO_X, INFO_Y );
|
||||
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.SetShadowLength( 2 );
|
||||
//m_textInfo.SetText(); // set this below every frame
|
||||
@@ -302,10 +302,10 @@ void ScreenEdit::Update( float fDeltaTime )
|
||||
{
|
||||
if( m_EditMode == MODE_RECORDING )
|
||||
{
|
||||
TransitionToEditFromRecord();
|
||||
TransitionFromRecordToEdit();
|
||||
GAMESTATE->m_fSongBeat = m_NoteFieldEdit.m_fEndMarker;
|
||||
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 )
|
||||
{
|
||||
@@ -313,7 +313,7 @@ void ScreenEdit::Update( float fDeltaTime )
|
||||
m_EditMode = MODE_EDITING;
|
||||
GAMESTATE->m_fSongBeat = m_NoteFieldEdit.m_fEndMarker;
|
||||
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 )
|
||||
{
|
||||
case DIK_ESCAPE:
|
||||
TransitionToEditFromRecord();
|
||||
TransitionFromRecordToEdit();
|
||||
|
||||
m_rectRecordBack.BeginTweening( 0.5f );
|
||||
m_rectRecordBack.SetTweenDiffuseColor( D3DXCOLOR(0,0,0,0) );
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
@@ -1054,6 +1058,8 @@ void ScreenEdit::InputPlay( const DeviceInput& DeviceI, const InputEventType typ
|
||||
case DIK_ESCAPE:
|
||||
m_EditMode = MODE_EDITING;
|
||||
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()) );
|
||||
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_soundMusic.Stop();
|
||||
|
||||
@@ -38,7 +38,7 @@ public:
|
||||
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 );
|
||||
virtual void HandleScreenMessage( const ScreenMessage SM );
|
||||
void TransitionToEditFromRecord();
|
||||
void TransitionFromRecordToEdit();
|
||||
|
||||
|
||||
protected:
|
||||
|
||||
@@ -781,7 +781,7 @@ void ScreenGameplay::Update( float fDeltaTime )
|
||||
if( fSongBeat > GAMESTATE->m_pCurSong->m_fLastBeat+4 )
|
||||
{
|
||||
GAMESTATE->m_fSongBeat = 0;
|
||||
m_soundMusic.Stop();
|
||||
m_soundMusic.Pause();
|
||||
this->SendScreenMessage( SM_NotesEnded, 0 );
|
||||
}
|
||||
|
||||
|
||||
@@ -45,7 +45,7 @@ OptionLineData g_GraphicOptionsLines[NUM_GRAPHIC_OPTIONS_LINES] = {
|
||||
{ "Show Stats", 2, {"OFF","ON"} },
|
||||
{ "BG Mode", 4, {"OFF","ANIMATIONS","VISUALIZATIONS","RANDOM MOVIES"} },
|
||||
{ "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() :
|
||||
|
||||
@@ -67,129 +67,76 @@ ScreenSelectGroup::ScreenSelectGroup()
|
||||
// and groups that do not contain any steps for the current
|
||||
// style (such as solo) are omitted. Bear with me!
|
||||
// -- dro kulix
|
||||
|
||||
// Chris:
|
||||
// This is excellent! I'm going to move the filtering of 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.
|
||||
|
||||
// m_arrayGroupNames will contain all relevant group names
|
||||
CMap<int, int, CArray<Song*, Song*>*, CArray<Song*, Song*>*>
|
||||
mapGroupToSongArray; // Will contain all relevant songs
|
||||
CArray<Song*, Song*> aAllSongs;
|
||||
aAllSongs.Copy( SONGMAN->m_pSongs );
|
||||
|
||||
{ // Let's get local!
|
||||
// (There are some variables we want deallocated before continuing.)
|
||||
// Filter out Songs that can't be played by the current Style
|
||||
NotesType nt = GAMESTATE->GetCurrentStyleDef()->m_NotesType;
|
||||
|
||||
// Retrieve list of ALL song groups and ALL songs
|
||||
for( i=aAllSongs.GetSize()-1; i>=0; i-- ) // foreach Song, back to front
|
||||
{
|
||||
Song* pSong = aAllSongs[i];
|
||||
|
||||
SONGMAN->GetGroupNames( m_arrayGroupNames );
|
||||
|
||||
CArray<Song*, Song*> arrayAllSongs;
|
||||
arrayAllSongs.Copy( SONGMAN->m_pSongs );
|
||||
|
||||
// Retrieve the identities (Song*) of all songs under these groups
|
||||
|
||||
for( i=0; i<min(m_arrayGroupNames.GetSize(), MAX_GROUPS); i++ )
|
||||
bool bSongCanBePlayedByCurrentStyle = false;
|
||||
for( int j=0; j<pSong->m_apNotes.GetSize(); j++ ) // foreach Notes
|
||||
{
|
||||
CArray<Song*, Song*> *p_arrayGroupSongs = new CArray<Song*, Song*>;
|
||||
// WARNING! We are creating new objects that must be destroyed.
|
||||
const CString &sCurGroupName = m_arrayGroupNames[i];
|
||||
|
||||
SONGMAN->GetSongsInGroup( sCurGroupName, *p_arrayGroupSongs );
|
||||
mapGroupToSongArray.SetAt(GetHashForString(sCurGroupName), p_arrayGroupSongs);
|
||||
}
|
||||
Notes* pNotes = pSong->m_apNotes[j];
|
||||
|
||||
{
|
||||
// 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())
|
||||
if( pNotes->m_NotesType == nt )
|
||||
{
|
||||
|
||||
int si = 0;
|
||||
|
||||
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++;
|
||||
}
|
||||
|
||||
bSongCanBePlayedByCurrentStyle = true;
|
||||
break;
|
||||
}
|
||||
} // 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 ] = "";
|
||||
|
||||
// Retrieve list of song groups
|
||||
//SONGMAN->GetGroupNames( m_arrayGroupNames );
|
||||
//m_arrayGroupNames.InsertAt( 0, "ALL MUSIC" );
|
||||
// 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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
m_iSelection = 0;
|
||||
m_bChosen = false;
|
||||
|
||||
@@ -236,10 +183,9 @@ ScreenSelectGroup::ScreenSelectGroup()
|
||||
}
|
||||
|
||||
|
||||
// This part is still compatible with the new pare routine.
|
||||
for( i=0; i<min(m_arrayGroupNames.GetSize(), MAX_GROUPS); i++ )
|
||||
for( i=0; i<min(m_asGroupNames.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].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
|
||||
//
|
||||
// This block is modified for the new paring routine
|
||||
for( i=0; i<min(m_arrayGroupNames.GetSize(), MAX_GROUPS); i++ )
|
||||
for( i=0; i<min(m_asGroupNames.GetSize(), MAX_GROUPS); i++ )
|
||||
{
|
||||
CArray<Song*, Song*>* p_arraySongs;
|
||||
const CString &sCurGroupName = m_arrayGroupNames[i];
|
||||
|
||||
mapGroupToSongArray.Lookup( GetHashForString(sCurGroupName), p_arraySongs);
|
||||
CArray<Song*,Song*>& aSongs = aSongsInGroup[i];
|
||||
m_iNumSongsInGroup[i] = aSongs.GetSize();
|
||||
SortSongPointerArrayByTitle( aSongs );
|
||||
|
||||
m_iNumSongsInGroup[i] = p_arraySongs->GetSize();
|
||||
|
||||
SortSongPointerArrayByTitle( *p_arraySongs );
|
||||
|
||||
for( int c=0; c<TITLES_COLUMNS; c++ )
|
||||
for( int c=0; c<TITLES_COLUMNS; c++ ) // foreach col
|
||||
{
|
||||
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 )
|
||||
sText += ssprintf( "%d more.....", p_arraySongs->GetSize() - TITLES_COLUMNS * TITLES_ROWS - 1 );
|
||||
if( c == TITLES_COLUMNS-1 && r == TITLES_ROWS-1 )
|
||||
{
|
||||
sText += ssprintf( "%d more.....", aSongs.GetSize() - TITLES_COLUMNS * TITLES_ROWS - 1 );
|
||||
}
|
||||
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;
|
||||
@@ -306,23 +258,6 @@ ScreenSelectGroup::ScreenSelectGroup()
|
||||
m_Menu.TweenOnScreenFromMenu( SM_None );
|
||||
TweenOnScreen();
|
||||
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++ )
|
||||
m_textTitles[c].SetText( m_sContentsText[m_iSelection][c] );
|
||||
|
||||
CString sSelectedGroupName = m_arrayGroupNames[m_iSelection];
|
||||
CString sSelectedGroupName = m_asGroupNames[m_iSelection];
|
||||
|
||||
CString sGroupBannerPath;
|
||||
if( 0 == stricmp(sSelectedGroupName, "ALL MUSIC") )
|
||||
@@ -431,9 +366,9 @@ void ScreenSelectGroup::MenuUp( const PlayerNumber p )
|
||||
|
||||
BeforeChange();
|
||||
|
||||
m_iSelection = m_iSelection-1 % m_arrayGroupNames.GetSize();
|
||||
m_iSelection = m_iSelection-1 % m_asGroupNames.GetSize();
|
||||
if( m_iSelection < 0 )
|
||||
m_iSelection += min( m_arrayGroupNames.GetSize(), MAX_GROUPS );
|
||||
m_iSelection += min( m_asGroupNames.GetSize(), MAX_GROUPS );
|
||||
|
||||
AfterChange();
|
||||
|
||||
@@ -448,7 +383,7 @@ void ScreenSelectGroup::MenuDown( const PlayerNumber p )
|
||||
|
||||
BeforeChange();
|
||||
|
||||
m_iSelection = (m_iSelection+1) % min( m_arrayGroupNames.GetSize(), MAX_GROUPS );
|
||||
m_iSelection = (m_iSelection+1) % min( m_asGroupNames.GetSize(), MAX_GROUPS );
|
||||
|
||||
AfterChange();
|
||||
|
||||
@@ -461,7 +396,7 @@ void ScreenSelectGroup::MenuStart( const PlayerNumber p )
|
||||
m_bChosen = true;
|
||||
|
||||
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") )
|
||||
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 )
|
||||
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].BeginTweeningQueued( 0.1f*i, TWEEN_BOUNCE_END );
|
||||
|
||||
@@ -64,7 +64,7 @@ private:
|
||||
RandomSample m_soundSelect;
|
||||
RandomSample m_soundFlyOff;
|
||||
|
||||
CStringArray m_arrayGroupNames;
|
||||
CStringArray m_asGroupNames;
|
||||
int m_iSelection;
|
||||
bool m_bChosen;
|
||||
};
|
||||
|
||||
@@ -136,6 +136,11 @@ void Song::AddAnimationSegment( AnimationSegment seg )
|
||||
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 )
|
||||
{
|
||||
|
||||
@@ -87,6 +87,9 @@ public:
|
||||
float m_fLastBeat;
|
||||
float m_fMusicSampleStartSeconds;
|
||||
float m_fMusicSampleLengthSeconds;
|
||||
|
||||
float GetMusicStartBeat();
|
||||
|
||||
CString m_sBannerFile;
|
||||
CString m_sBackgroundFile;
|
||||
CString m_sCDTitleFile;
|
||||
|
||||
Reference in New Issue
Block a user