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.
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.
+4 -4
View File
@@ -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) );
}
+93 -76
View File
@@ -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);
}
+7 -6
View File
@@ -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;
};
+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 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;};
+1 -1
View File
@@ -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] );
+12 -6
View File
@@ -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();
+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 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:
+1 -1
View File
@@ -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 );
}
+1 -1
View File
@@ -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() :
+88 -153
View File
@@ -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 );
+1 -1
View File
@@ -64,7 +64,7 @@ private:
RandomSample m_soundSelect;
RandomSample m_soundFlyOff;
CStringArray m_arrayGroupNames;
CStringArray m_asGroupNames;
int m_iSelection;
bool m_bChosen;
};
+5
View File
@@ -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 )
{
+3
View File
@@ -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;