[splittiming]

- load split timing from BMS files
- fix a crash because autogen'd steps don't inherit the timing from parent
- be more verbose in UpdateSongPosition
This commit is contained in:
Thai Pangsakulyanont
2011-05-12 16:44:24 +07:00
parent a478308345
commit eda727ddf9
7 changed files with 243 additions and 186 deletions
+1 -1
View File
@@ -99,7 +99,7 @@ void AutoKeysounds::LoadAutoplaySoundsInto( RageSoundReader_Chain *pChain )
if( tn[pn].iKeysoundIndex >= 0 ) if( tn[pn].iKeysoundIndex >= 0 )
{ {
RString sKeysoundFilePath = sSongDir + pSong->m_vsKeysoundFile[tn[pn].iKeysoundIndex]; RString sKeysoundFilePath = sSongDir + pSong->m_vsKeysoundFile[tn[pn].iKeysoundIndex];
float fSeconds = pSong->m_SongTiming.GetElapsedTimeFromBeatNoOffset( NoteRowToBeat(iRow) ) + SOUNDMAN->GetPlayLatency(); float fSeconds = GAMESTATE->m_pCurSteps[pn]->m_Timing.GetElapsedTimeFromBeatNoOffset( NoteRowToBeat(iRow) ) + SOUNDMAN->GetPlayLatency();
float fPan = 0; float fPan = 0;
if( !bSoundIsGlobal ) if( !bSoundIsGlobal )
+5 -4
View File
@@ -940,14 +940,15 @@ void GameState::ResetStageStatistics()
m_iStageSeed = rand(); m_iStageSeed = rand();
} }
void GameState::UpdateSongPosition( float fPositionSeconds, const TimingData &timing, const RageTimer &timestamp ) void GameState::UpdateSongPosition( float fPositionSeconds, const TimingData &timing, const RageTimer &timestamp, bool bUpdatePlayers )
{ {
m_Position.UpdateSongPosition( fPositionSeconds, timing, timestamp ); m_Position.UpdateSongPosition( fPositionSeconds, timing, timestamp );
FOREACH_EnabledPlayer( pn ) if( bUpdatePlayers )
if( m_pCurSteps[pn] ) FOREACH_EnabledPlayer( pn )
m_pPlayerState[pn]->m_Position.UpdateSongPosition( fPositionSeconds, m_pCurSteps[pn]->m_Timing, timestamp ); if( m_pCurSteps[pn] )
m_pPlayerState[pn]->m_Position.UpdateSongPosition( fPositionSeconds, m_pCurSteps[pn]->m_Timing, timestamp );
Actor::SetBGMTime( GAMESTATE->m_Position.m_fMusicSecondsVisible, GAMESTATE->m_Position.m_fSongBeatVisible, fPositionSeconds, GAMESTATE->m_Position.m_fSongBeatNoOffset ); Actor::SetBGMTime( GAMESTATE->m_Position.m_fMusicSecondsVisible, GAMESTATE->m_Position.m_fSongBeatVisible, fPositionSeconds, GAMESTATE->m_Position.m_fSongBeatNoOffset );
// LOG->Trace( "m_fMusicSeconds = %f, m_fSongBeat = %f, m_fCurBPS = %f, m_bFreeze = %f", m_fMusicSeconds, m_fSongBeat, m_fCurBPS, m_bFreeze ); // LOG->Trace( "m_fMusicSeconds = %f, m_fSongBeat = %f, m_fCurBPS = %f, m_bFreeze = %f", m_fMusicSeconds, m_fSongBeat, m_fCurBPS, m_bFreeze );
+1 -1
View File
@@ -205,7 +205,7 @@ public:
static const float MUSIC_SECONDS_INVALID; static const float MUSIC_SECONDS_INVALID;
void ResetMusicStatistics(); // Call this when it's time to play a new song. Clears the values above. void ResetMusicStatistics(); // Call this when it's time to play a new song. Clears the values above.
void UpdateSongPosition( float fPositionSeconds, const TimingData &timing, const RageTimer &timestamp = RageZeroTimer ); void UpdateSongPosition( float fPositionSeconds, const TimingData &timing, const RageTimer &timestamp = RageZeroTimer, bool bUpdatePlayers = false );
float GetSongPercent( float beat ) const; float GetSongPercent( float beat ) const;
bool AllAreInDangerOrWorse() const; bool AllAreInDangerOrWorse() const;
+231 -177
View File
@@ -435,9 +435,121 @@ static void ReadTimeSigs( const NameToData_t &mapNameToData, MeasureToTimeSig_t
static const int BEATS_PER_MEASURE = 4; static const int BEATS_PER_MEASURE = 4;
static const int ROWS_PER_MEASURE = ROWS_PER_BEAT * BEATS_PER_MEASURE; static const int ROWS_PER_MEASURE = ROWS_PER_BEAT * BEATS_PER_MEASURE;
static bool LoadFromBMSFile( const RString &sPath, const NameToData_t &mapNameToData, Steps &out, static bool SearchForKeysound( const RString &sPath, RString nDataOriginal, map<RString, int> &mapFilenameToKeysoundIndex, Song &out, int &outKeysoundIndex )
const MeasureToTimeSig_t &sigAdjustments, const map<RString,int> &idToKeySoundIndex )
{ {
// Search for memoized file names:
{
RString nDataToSearchFor = nDataOriginal;
nDataToSearchFor.MakeLower();
map<RString, int>::iterator it = mapFilenameToKeysoundIndex.find(nDataToSearchFor);
if (it != mapFilenameToKeysoundIndex.end()) {
outKeysoundIndex = it->second;
return true;
}
}
// FIXME: garbled song names seem to crash the app.
// this might not be the best place to put this code.
if( !utf8_is_valid(nDataOriginal) )
return false;
/* Due to bugs in some programs, many BMS files have a "WAV" extension
* on files in the BMS for files that actually have some other extension.
* Do a search. Don't do a wildcard search; if sData is "song.wav",
* we might also have "song.png", which we shouldn't match. */
RString nData = nDataOriginal;
if( !IsAFile(out.GetSongDir()+nData) )
{
const char *exts[] = { "oga", "ogg", "wav", "mp3", NULL }; // XXX: stop duplicating these everywhere
for( unsigned i = 0; exts[i] != NULL; ++i )
{
RString fn = SetExtension( nData, exts[i] );
if( IsAFile(out.GetSongDir()+fn) )
{
nData = fn;
break;
}
}
}
if( !IsAFile(out.GetSongDir()+nData) )
{
LOG->UserLog( "Song file", out.GetSongDir(), "references key \"%s\" that can't be found", nData.c_str() );
return false;
}
// Let's again search for memoized file names (we got the normalized one!):
{
RString nDataToSearchFor = nData;
nDataToSearchFor.MakeLower();
map<RString, int>::iterator it = mapFilenameToKeysoundIndex.find(nDataToSearchFor);
if (it != mapFilenameToKeysoundIndex.end()) {
outKeysoundIndex = it->second;
{
RString nDataToAdd = nDataOriginal;
nDataToAdd.MakeLower();
mapFilenameToKeysoundIndex[nDataToAdd] = outKeysoundIndex;
}
return true;
}
}
// Now this is a new sample.
out.m_vsKeysoundFile.push_back( nData );
outKeysoundIndex = out.m_vsKeysoundFile.size() - 1;
{
RString nDataToAdd = nDataOriginal;
nDataToAdd.MakeLower();
mapFilenameToKeysoundIndex[nDataToAdd] = outKeysoundIndex;
}
{
RString nDataToAdd = nData;
nDataToAdd.MakeLower();
mapFilenameToKeysoundIndex[nDataToAdd] = outKeysoundIndex;
}
return true;
}
static bool SearchForKeysound( const RString &sPath, RString sNoteId, const NameToData_t &mapNameToData, map<RString, int> &mapIdToKeysoundIndex, map<RString, int> &mapFilenameToKeysoundIndex, Song &out, int &outKeysoundIndex )
{
sNoteId.MakeLower();
{
map<RString, int>::iterator it = mapIdToKeysoundIndex.find(sNoteId);
if (it != mapIdToKeysoundIndex.end())
{
outKeysoundIndex = it->second;
return outKeysoundIndex >= 0;
}
}
RString sTagToLookFor = ssprintf( "#wav%s", sNoteId.c_str() );
RString nDataOriginal;
if( !GetTagFromMap( mapNameToData, sTagToLookFor, nDataOriginal ) )
{
LOG->UserLog( "Song file", sPath.c_str(), "has tag \"%s\" which cannot be found.", sTagToLookFor.c_str() );
return false;
}
bool retval = SearchForKeysound(sPath, nDataOriginal, mapFilenameToKeysoundIndex, out, outKeysoundIndex);
mapIdToKeysoundIndex[sNoteId] = outKeysoundIndex;
return retval;
}
static bool LoadFromBMSFile( const RString &sPath, const NameToData_t &mapNameToData, Steps &out, Song &outSong, map<RString, int> &mapFilenameToKeysoundIndex )
{
map<RString, int> mapIdToKeysoundIndex;
MeasureToTimeSig_t sigAdjustments;
LOG->Trace( "Steps::LoadFromBMSFile( '%s' )", sPath.c_str() ); LOG->Trace( "Steps::LoadFromBMSFile( '%s' )", sPath.c_str() );
out.m_StepsType = StepsType_Invalid; out.m_StepsType = StepsType_Invalid;
@@ -453,11 +565,121 @@ static bool LoadFromBMSFile( const RString &sPath, const NameToData_t &mapNameTo
NoteData ndNotes; NoteData ndNotes;
ndNotes.SetNumTracks( NUM_BMS_TRACKS ); ndNotes.SetNumTracks( NUM_BMS_TRACKS );
// Read BPM
if( GetTagFromMap(mapNameToData, "#bpm", sData) )
{
const float fBPM = StringToFloat( sData );
if( fBPM > 0.0f )
{
BPMSegment newSeg( 0, fBPM );
out.m_Timing.AddBPMSegment( newSeg );
LOG->Trace( "Inserting new BPM change at beat %f, BPM %f", NoteRowToBeat(0), fBPM );
}
else
{
LOG->UserLog( "Song file", sPath.c_str(), "has an invalid BPM change at beat %f, BPM %f.",
NoteRowToBeat(0), fBPM );
}
}
/* Read time signatures. Note that these can differ across files in the same /* Read time signatures. Note that these can differ across files in the same
* song. */ * song. */
MeasureToTimeSig_t mapMeasureToTimeSig; MeasureToTimeSig_t mapMeasureToTimeSig;
ReadTimeSigs( mapNameToData, mapMeasureToTimeSig ); ReadTimeSigs( mapNameToData, mapMeasureToTimeSig );
for( NameToData_t::const_iterator it = mapNameToData.lower_bound("#00000"); it != mapNameToData.end(); ++it )
{
const RString &sName = it->first;
if( sName.size() != 6 || sName[0] != '#' || !IsAnInt( sName.substr(1,5) ) )
continue;
// this is step or offset data. Looks like "#00705"
int iMeasureNo = atoi( sName.substr(1, 3).c_str() );
int iBMSTrackNo = atoi( sName.substr(4, 2).c_str() );
int iStepIndex = GetMeasureStartRow( mapMeasureToTimeSig, iMeasureNo, sigAdjustments );
float fBeatsPerMeasure = GetBeatsPerMeasure( mapMeasureToTimeSig, iMeasureNo, sigAdjustments );
int iRowsPerMeasure = BeatToNoteRow( fBeatsPerMeasure );
RString nData = it->second;
int totalPairs = nData.size() / 2;
for( int i = 0; i < totalPairs; ++i )
{
RString sPair = nData.substr( i*2, 2 );
int iRow = iStepIndex + (i * iRowsPerMeasure) / totalPairs;
float fBeat = NoteRowToBeat( iRow );
int iVal = 0;
sscanf( sPair, "%x", &iVal );
if (sPair == "00")
{
continue;
}
switch( iBMSTrackNo )
{
case BMS_TRACK_BPM:
if( iVal > 0 )
{
out.m_Timing.SetBPMAtBeat( fBeat, (float) iVal );
LOG->Trace( "Inserting new BPM change at beat %f, BPM %i", fBeat, iVal );
}
else
{
LOG->UserLog( "Song file", sPath.c_str(), "has an invalid BPM change at beat %f, BPM %d.",
fBeat, iVal );
}
break;
case BMS_TRACK_BPM_REF:
{
RString sTagToLookFor = ssprintf( "#bpm%s", sPair.c_str() );
RString sBPM;
if( GetTagFromMap( mapNameToData, sTagToLookFor, sBPM ) )
{
float fBPM = StringToFloat( sBPM );
out.m_Timing.SetBPMAtBeat( fBeat, fBPM );
}
else
{
LOG->UserLog( "Song file", sPath.c_str(), "has tag \"%s\" which cannot be found.", sTagToLookFor.c_str() );
}
break;
}
case BMS_TRACK_STOP:
{
if( iVal == 0 )
{
break;
}
RString sTagToLookFor = ssprintf( "#stop%02x", iVal );
RString sBeats;
if( GetTagFromMap( mapNameToData, sTagToLookFor, sBeats ) )
{
// find the BPM at the time of this freeze
float fBPS = out.m_Timing.GetBPMAtBeat(fBeat) / 60.0f;
float fBeats = StringToFloat( sBeats ) / 48.0f;
float fFreezeSecs = fBeats / fBPS;
StopSegment newSeg( BeatToNoteRow(fBeat), fFreezeSecs );
out.m_Timing.AddStopSegment( newSeg );
LOG->Trace( "Inserting new Freeze at beat %f, secs %f", fBeat, newSeg.m_fStopSeconds );
}
else
{
LOG->UserLog( "Song file", sPath.c_str(), "has tag \"%s\" which cannot be found.", sTagToLookFor.c_str() );
}
break;
}
}
}
}
// Now that we're done reading BPMs, factor out weird time signatures.
SetTimeSigAdjustments( mapMeasureToTimeSig, outSong, sigAdjustments );
int iHoldStarts[NUM_BMS_TRACKS]; int iHoldStarts[NUM_BMS_TRACKS];
TapNote iHoldHeads[NUM_BMS_TRACKS]; TapNote iHoldHeads[NUM_BMS_TRACKS];
@@ -487,10 +709,9 @@ static bool LoadFromBMSFile( const RString &sPath, const NameToData_t &mapNameTo
RString sNoteId = sNoteData.substr( i, 2 ); RString sNoteId = sNoteData.substr( i, 2 );
if( sNoteId != "00" ) if( sNoteId != "00" )
{ {
vTapNotes.push_back( TAP_ORIGINAL_TAP ); TapNote tn = TAP_ORIGINAL_TAP;
map<RString,int>::const_iterator rInt = idToKeySoundIndex.find( sNoteId ); SearchForKeysound( sPath, sNoteId, mapNameToData, mapIdToKeysoundIndex, mapFilenameToKeysoundIndex, outSong, tn.iKeysoundIndex );
if( rInt != idToKeySoundIndex.end() ) vTapNotes.push_back( tn );
vTapNotes.back().iKeysoundIndex = rInt->second;
} }
else else
{ {
@@ -781,7 +1002,7 @@ static bool LoadFromBMSFile( const RString &sPath, const NameToData_t &mapNameTo
return true; return true;
} }
static void ReadGlobalTags( const NameToData_t &mapNameToData, Song &out, MeasureToTimeSig_t &sigAdjustmentsOut, map<RString,int> &idToKeySoundIndexOut ) static void ReadGlobalTags( const NameToData_t &mapNameToData, Song &out )
{ {
RString sData; RString sData;
if( GetTagFromMap(mapNameToData, "#title", sData) ) if( GetTagFromMap(mapNameToData, "#title", sData) )
@@ -792,172 +1013,6 @@ static void ReadGlobalTags( const NameToData_t &mapNameToData, Song &out, Measur
GetTagFromMap( mapNameToData, "#backbmp", out.m_sBackgroundFile ); GetTagFromMap( mapNameToData, "#backbmp", out.m_sBackgroundFile );
GetTagFromMap( mapNameToData, "#wav", out.m_sMusicFile ); GetTagFromMap( mapNameToData, "#wav", out.m_sMusicFile );
if( GetTagFromMap(mapNameToData, "#bpm", sData) )
{
const float fBPM = StringToFloat( sData );
if( PREFSMAN->m_bQuirksMode )
{
BPMSegment newSeg( 0, fBPM );
out.m_SongTiming.AddBPMSegment( newSeg );
if( fBPM > 0.0f )
LOG->Trace( "Inserting new positive BPM change at beat %f, BPM %f", NoteRowToBeat(0), fBPM );
else
LOG->Trace( "Inserting new negative BPM change at beat %f, BPM %f", NoteRowToBeat(0), fBPM );
}
else
{
if( fBPM > 0.0f )
{
BPMSegment newSeg( 0, fBPM );
out.m_SongTiming.AddBPMSegment( newSeg );
LOG->Trace( "Inserting new BPM change at beat %f, BPM %f", NoteRowToBeat(0), fBPM );
}
else
{
LOG->UserLog( "Song file", out.GetSongDir(), "has an invalid BPM change at beat %f, BPM %f.",
NoteRowToBeat(0), fBPM );
}
}
}
NameToData_t::const_iterator it;
for( it = mapNameToData.lower_bound("#wav"); it != mapNameToData.end(); ++it )
{
const RString &sName = it->first;
if( sName.size() != 6 || sName.Left(4) != "#wav" )
continue;
// this is keysound file name. Looks like "#WAV1A"
RString nData = it->second;
RString sWavID = sName.Right(2);
// FIXME: garbled song names seem to crash the app.
// this might not be the best place to put this code.
if( !utf8_is_valid(nData) )
continue;
/* Due to bugs in some programs, many BMS files have a "WAV" extension
* on files in the BMS for files that actually have some other extension.
* Do a search. Don't do a wildcard search; if sData is "song.wav",
* we might also have "song.png", which we shouldn't match. */
if( !IsAFile(out.GetSongDir()+nData) )
{
const char *exts[] = { "oga", "ogg", "wav", "mp3", NULL }; // XXX: stop duplicating these everywhere
for( unsigned i = 0; exts[i] != NULL; ++i )
{
RString fn = SetExtension( nData, exts[i] );
if( IsAFile(out.GetSongDir()+fn) )
{
nData = fn;
break;
}
}
}
if( !IsAFile(out.GetSongDir()+nData) )
LOG->UserLog( "Song file", out.GetSongDir(), "references key \"%s\" that can't be found", nData.c_str() );
sWavID.MakeUpper(); // HACK: undo the MakeLower()
out.m_vsKeysoundFile.push_back( nData );
idToKeySoundIndexOut[ sWavID ] = out.m_vsKeysoundFile.size()-1;
LOG->Trace( "Inserting keysound index %u '%s'", unsigned(out.m_vsKeysoundFile.size()-1), sWavID.c_str() );
}
// Time signature tags affect all other global timing tags, so read them first.
MeasureToTimeSig_t mapMeasureToTimeSig;
ReadTimeSigs( mapNameToData, mapMeasureToTimeSig );
for( it = mapNameToData.lower_bound("#00000"); it != mapNameToData.end(); ++it )
{
const RString &sName = it->first;
if( sName.size() != 6 || sName[0] != '#' || !IsAnInt( sName.substr(1,5) ) )
continue;
// this is step or offset data. Looks like "#00705"
int iMeasureNo = atoi( sName.substr(1, 3).c_str() );
int iBMSTrackNo = atoi( sName.substr(4, 2).c_str() );
int iStepIndex = GetMeasureStartRow( mapMeasureToTimeSig, iMeasureNo, sigAdjustmentsOut );
float fBeatsPerMeasure = GetBeatsPerMeasure( mapMeasureToTimeSig, iMeasureNo, sigAdjustmentsOut );
int iRowsPerMeasure = BeatToNoteRow( fBeatsPerMeasure );
RString nData = it->second;
int totalPairs = nData.size() / 2;
for( int i = 0; i < totalPairs; ++i )
{
RString sPair = nData.substr( i*2, 2 );
int iRow = iStepIndex + (i * iRowsPerMeasure) / totalPairs;
float fBeat = NoteRowToBeat( iRow );
int iVal = 0;
sscanf( sPair, "%x", &iVal );
if (sPair == "00")
{
continue;
}
switch( iBMSTrackNo )
{
case BMS_TRACK_BPM:
if( iVal > 0 )
{
out.m_SongTiming.SetBPMAtBeat( fBeat, (float) iVal );
LOG->Trace( "Inserting new BPM change at beat %f, BPM %i", fBeat, iVal );
}
else
{
LOG->UserLog( "Song file", out.GetSongDir(), "has an invalid BPM change at beat %f, BPM %d.",
fBeat, iVal );
}
break;
case BMS_TRACK_BPM_REF:
{
RString sTagToLookFor = ssprintf( "#bpm%s", sPair.c_str() );
RString sBPM;
if( GetTagFromMap( mapNameToData, sTagToLookFor, sBPM ) )
{
float fBPM = StringToFloat( sBPM );
out.m_SongTiming.SetBPMAtBeat( fBeat, fBPM );
}
else
{
LOG->UserLog( "Song file", out.GetSongDir(), "has tag \"%s\" which cannot be found.", sTagToLookFor.c_str() );
}
break;
}
case BMS_TRACK_STOP:
{
if( iVal == 0 )
{
break;
}
RString sTagToLookFor = ssprintf( "#stop%02x", iVal );
RString sBeats;
if( GetTagFromMap( mapNameToData, sTagToLookFor, sBeats ) )
{
// find the BPM at the time of this freeze
float fBPS = out.m_SongTiming.GetBPMAtBeat(fBeat) / 60.0f;
float fBeats = StringToFloat( sBeats ) / 48.0f;
float fFreezeSecs = fBeats / fBPS;
StopSegment newSeg( BeatToNoteRow(fBeat), fFreezeSecs );
out.m_SongTiming.AddStopSegment( newSeg );
LOG->Trace( "Inserting new Freeze at beat %f, secs %f", fBeat, newSeg.m_fStopSeconds );
}
else
{
LOG->UserLog( "Song file", out.GetSongDir(), "has tag \"%s\" which cannot be found.", sTagToLookFor.c_str() );
}
break;
}
}
}
}
// Now that we're done reading BPMs, factor out weird time signatures.
SetTimeSigAdjustments( mapMeasureToTimeSig, out, sigAdjustmentsOut );
} }
static void SlideDuplicateDifficulties( Song &p ) static void SlideDuplicateDifficulties( Song &p )
@@ -1100,9 +1155,7 @@ bool BMSLoader::LoadFromDir( const RString &sDir, Song &out )
if( apSteps[i]->GetDifficulty() == Difficulty_Medium ) if( apSteps[i]->GetDifficulty() == Difficulty_Medium )
iMainDataIndex = i; iMainDataIndex = i;
MeasureToTimeSig_t sigAdjustments; ReadGlobalTags( aBMSData[iMainDataIndex], out );
map<RString,int> idToKeysoundIndex;
ReadGlobalTags( aBMSData[iMainDataIndex], out, sigAdjustments, idToKeysoundIndex );
// The brackets before the difficulty are in common substring, so remove them if it's found. // The brackets before the difficulty are in common substring, so remove them if it's found.
if( commonSubstring.size() > 2 && commonSubstring[commonSubstring.size() - 2] == ' ' ) if( commonSubstring.size() > 2 && commonSubstring[commonSubstring.size() - 2] == ' ' )
@@ -1124,10 +1177,11 @@ bool BMSLoader::LoadFromDir( const RString &sDir, Song &out )
// Now that we've parsed the keysound data, load the Steps from the rest // Now that we've parsed the keysound data, load the Steps from the rest
// of the .bms files. // of the .bms files.
map<RString, int> mapFilenameToKeysoundIndex;
for( unsigned i=0; i<arrayBMSFileNames.size(); i++ ) for( unsigned i=0; i<arrayBMSFileNames.size(); i++ )
{ {
Steps* pNewNotes = apSteps[i]; Steps* pNewNotes = apSteps[i];
const bool ok = LoadFromBMSFile( out.GetSongDir() + arrayBMSFileNames[i], aBMSData[i], *pNewNotes, sigAdjustments, idToKeysoundIndex ); const bool ok = LoadFromBMSFile( out.GetSongDir() + arrayBMSFileNames[i], aBMSData[i], *pNewNotes, out, mapFilenameToKeysoundIndex );
if( ok ) if( ok )
out.AddSteps( pNewNotes ); out.AddSteps( pNewNotes );
else else
+2 -2
View File
@@ -915,7 +915,7 @@ void ScreenEdit::Update( float fDeltaTime )
{ {
RageTimer tm; RageTimer tm;
const float fSeconds = m_pSoundMusic->GetPositionSeconds( NULL, &tm ); const float fSeconds = m_pSoundMusic->GetPositionSeconds( NULL, &tm );
GAMESTATE->UpdateSongPosition( fSeconds, GAMESTATE->m_pCurSong->m_SongTiming, tm ); GAMESTATE->UpdateSongPosition( fSeconds, GAMESTATE->m_pCurSong->m_SongTiming, tm, true );
} }
if( m_EditState == STATE_RECORDING ) if( m_EditState == STATE_RECORDING )
@@ -2388,7 +2388,7 @@ void ScreenEdit::TransitionEditState( EditState em )
/* Give a 1 second lead-in. If we're loading Player, this must be done first. */ /* Give a 1 second lead-in. If we're loading Player, this must be done first. */
float fSeconds = m_pSteps->m_Timing.GetElapsedTimeFromBeat( NoteRowToBeat(m_iStartPlayingAt) ) - 1; float fSeconds = m_pSteps->m_Timing.GetElapsedTimeFromBeat( NoteRowToBeat(m_iStartPlayingAt) ) - 1;
GAMESTATE->UpdateSongPosition( fSeconds, m_pSteps->m_Timing ); GAMESTATE->UpdateSongPosition( fSeconds, m_pSteps->m_Timing, RageZeroTimer, true );
GAMESTATE->m_bGameplayLeadIn.Set( false ); GAMESTATE->m_bGameplayLeadIn.Set( false );
+1 -1
View File
@@ -1423,7 +1423,7 @@ void ScreenGameplay::UpdateSongPosition( float fDeltaTime )
RageTimer tm; RageTimer tm;
const float fSeconds = m_pSoundMusic->GetPositionSeconds( NULL, &tm ); const float fSeconds = m_pSoundMusic->GetPositionSeconds( NULL, &tm );
const float fAdjust = SOUND->GetFrameTimingAdjustment( fDeltaTime ); const float fAdjust = SOUND->GetFrameTimingAdjustment( fDeltaTime );
GAMESTATE->UpdateSongPosition( fSeconds+fAdjust, GAMESTATE->m_pCurSong->m_SongTiming, tm+fAdjust ); GAMESTATE->UpdateSongPosition( fSeconds+fAdjust, GAMESTATE->m_pCurSong->m_SongTiming, tm+fAdjust, true );
} }
void ScreenGameplay::BeginScreen() void ScreenGameplay::BeginScreen()
+2
View File
@@ -339,6 +339,7 @@ void Steps::AutogenFrom( const Steps *parent_, StepsType ntTo )
{ {
parent = parent_; parent = parent_;
m_StepsType = ntTo; m_StepsType = ntTo;
m_Timing = parent->m_Timing;
} }
void Steps::CopyFrom( Steps* pSource, StepsType ntTo, float fMusicLengthSeconds ) // pSource does not have to be of the same StepsType void Steps::CopyFrom( Steps* pSource, StepsType ntTo, float fMusicLengthSeconds ) // pSource does not have to be of the same StepsType
@@ -348,6 +349,7 @@ void Steps::CopyFrom( Steps* pSource, StepsType ntTo, float fMusicLengthSeconds
pSource->GetNoteData( noteData ); pSource->GetNoteData( noteData );
noteData.SetNumTracks( GAMEMAN->GetStepsTypeInfo(ntTo).iNumTracks ); noteData.SetNumTracks( GAMEMAN->GetStepsTypeInfo(ntTo).iNumTracks );
parent = NULL; parent = NULL;
m_Timing = pSource->m_Timing;
this->SetNoteData( noteData ); this->SetNoteData( noteData );
this->SetDescription( pSource->GetDescription() ); this->SetDescription( pSource->GetDescription() );
this->SetDifficulty( pSource->GetDifficulty() ); this->SetDifficulty( pSource->GetDifficulty() );