[default -> splittiming] forgot to push my merge. ouch

This commit is contained in:
Thai Pangsakulyanont
2011-05-10 12:57:54 +07:00
36 changed files with 640 additions and 868 deletions
+3
View File
@@ -9,6 +9,9 @@ change to JSON, but it is unsure if this will be done.
Implement .ssc at your own risk.
________________________________________________________________________________
[v0.7] - theDtTvB, Wolfman2000
* Split Timing officially implemented.
[v0.59] - Wolfman2000
* Typo fix: #RADARVALUES needed a semicolon at the end, not a colon.
+1
View File
@@ -11,6 +11,7 @@ function GetTotalItems(radars)
return radars:GetValue('RadarCategory_TapsAndHolds')
+ radars:GetValue('RadarCategory_Holds')
+ radars:GetValue('RadarCategory_Rolls');
+ radars:GetValue('RadarCategory_Lifts');
end;
-- Determine whether marvelous timing is to be considered.
+12 -12
View File
@@ -58,7 +58,7 @@ void AdjustSync::ResetOriginalSyncData()
s_pTimingDataOriginal = new TimingData;
if( GAMESTATE->m_pCurSong )
*s_pTimingDataOriginal = GAMESTATE->m_pCurSong->m_Timing;
*s_pTimingDataOriginal = GAMESTATE->m_pCurSong->m_SongTiming;
else
*s_pTimingDataOriginal = TimingData();
s_fGlobalOffsetSecondsOriginal = PREFSMAN->m_fGlobalOffsetSeconds;
@@ -87,7 +87,7 @@ void AdjustSync::SaveSyncChanges()
{
if( GAMESTATE->IsCourseMode() )
return;
if( GAMESTATE->m_pCurSong && *s_pTimingDataOriginal != GAMESTATE->m_pCurSong->m_Timing )
if( GAMESTATE->m_pCurSong && *s_pTimingDataOriginal != GAMESTATE->m_pCurSong->m_SongTiming )
{
if( GAMESTATE->IsEditing() )
{
@@ -110,7 +110,7 @@ void AdjustSync::RevertSyncChanges()
if( GAMESTATE->IsCourseMode() )
return;
PREFSMAN->m_fGlobalOffsetSeconds.Set( s_fGlobalOffsetSecondsOriginal );
GAMESTATE->m_pCurSong->m_Timing = *s_pTimingDataOriginal;
GAMESTATE->m_pCurSong->m_SongTiming = *s_pTimingDataOriginal;
ResetOriginalSyncData();
s_fStandardDeviation = 0.0f;
s_fAverageError = 0.0f;
@@ -186,7 +186,7 @@ void AdjustSync::AutosyncOffset()
switch( GAMESTATE->m_SongOptions.GetCurrent().m_AutosyncType )
{
case SongOptions::AUTOSYNC_SONG:
GAMESTATE->m_pCurSong->m_Timing.m_fBeat0OffsetInSeconds += mean;
GAMESTATE->m_pCurSong->m_SongTiming.m_fBeat0OffsetInSeconds += mean;
break;
case SongOptions::AUTOSYNC_MACHINE:
PREFSMAN->m_fGlobalOffsetSeconds.Set( PREFSMAN->m_fGlobalOffsetSeconds + mean );
@@ -232,15 +232,15 @@ void AdjustSync::AutosyncTempo()
if( !CalcLeastSquares( s_vAutosyncTempoData, fSlope, fIntercept, fFilteredError ) )
return;
GAMESTATE->m_pCurSong->m_Timing.m_fBeat0OffsetInSeconds += fIntercept;
GAMESTATE->m_pCurSong->m_SongTiming.m_fBeat0OffsetInSeconds += fIntercept;
const float fScaleBPM = 1.0f/(1.0f - fSlope);
FOREACH( BPMSegment, GAMESTATE->m_pCurSong->m_Timing.m_BPMSegments, i )
FOREACH( BPMSegment, GAMESTATE->m_pCurSong->m_SongTiming.m_BPMSegments, i )
i->SetBPM( i->GetBPM() * fScaleBPM );
// We assume that the stops were measured as a number of beats.
// Therefore, if we change the bpms, we need to make a similar
// change to the stops.
FOREACH( StopSegment, GAMESTATE->m_pCurSong->m_Timing.m_StopSegments, i )
FOREACH( StopSegment, GAMESTATE->m_pCurSong->m_SongTiming.m_StopSegments, i )
i->m_fStopSeconds *= 1.0f - fSlope;
SCREENMAN->SystemMessage( AUTOSYNC_CORRECTION_APPLIED.GetValue() );
@@ -296,7 +296,7 @@ void AdjustSync::GetSyncChangeTextSong( vector<RString> &vsAddTo )
{
float fOld = Quantize( AdjustSync::s_pTimingDataOriginal->m_fBeat0OffsetInSeconds, 0.001f );
float fNew = Quantize( GAMESTATE->m_pCurSong->m_Timing.m_fBeat0OffsetInSeconds, 0.001f );
float fNew = Quantize( GAMESTATE->m_pCurSong->m_SongTiming.m_fBeat0OffsetInSeconds, 0.001f );
float fDelta = fNew - fOld;
if( fabsf(fDelta) > 0.0001f )
@@ -309,10 +309,10 @@ void AdjustSync::GetSyncChangeTextSong( vector<RString> &vsAddTo )
}
}
for( unsigned i=0; i<GAMESTATE->m_pCurSong->m_Timing.m_BPMSegments.size(); i++ )
for( unsigned i=0; i<GAMESTATE->m_pCurSong->m_SongTiming.m_BPMSegments.size(); i++ )
{
float fOld = Quantize( AdjustSync::s_pTimingDataOriginal->m_BPMSegments[i].GetBPM(), 0.001f );
float fNew = Quantize( GAMESTATE->m_pCurSong->m_Timing.m_BPMSegments[i].GetBPM(), 0.001f );
float fNew = Quantize( GAMESTATE->m_pCurSong->m_SongTiming.m_BPMSegments[i].GetBPM(), 0.001f );
float fDelta = fNew - fOld;
if( fabsf(fDelta) > 0.0001f )
@@ -330,10 +330,10 @@ void AdjustSync::GetSyncChangeTextSong( vector<RString> &vsAddTo )
}
}
for( unsigned i=0; i<GAMESTATE->m_pCurSong->m_Timing.m_StopSegments.size(); i++ )
for( unsigned i=0; i<GAMESTATE->m_pCurSong->m_SongTiming.m_StopSegments.size(); i++ )
{
float fOld = Quantize( AdjustSync::s_pTimingDataOriginal->m_StopSegments[i].m_fStopSeconds, 0.001f );
float fNew = Quantize( GAMESTATE->m_pCurSong->m_Timing.m_StopSegments[i].m_fStopSeconds, 0.001f );
float fNew = Quantize( GAMESTATE->m_pCurSong->m_SongTiming.m_StopSegments[i].m_fStopSeconds, 0.001f );
float fDelta = fNew - fOld;
if( fabsf(fDelta) > 0.0001f )
+7 -5
View File
@@ -11,9 +11,10 @@ void Attack::GetAttackBeats( const Song *pSong, float &fStartBeat, float &fEndBe
{
ASSERT( pSong );
ASSERT_M( fStartSecond >= 0, ssprintf("StartSecond: %f",fStartSecond) );
fStartBeat = pSong->GetBeatFromElapsedTime( fStartSecond );
fEndBeat = pSong->GetBeatFromElapsedTime( fStartSecond+fSecsRemaining );
const TimingData &timing = pSong->m_SongTiming;
fStartBeat = timing.GetBeatFromElapsedTime( fStartSecond );
fEndBeat = timing.GetBeatFromElapsedTime( fStartSecond+fSecsRemaining );
}
/* Get the range for an attack that's being applied in realtime, eg. during battle
@@ -34,9 +35,10 @@ void Attack::GetRealtimeAttackBeats( const Song *pSong, const PlayerState* pPlay
fStartBeat = min( GAMESTATE->m_fSongBeat+8, pPlayerState->m_fLastDrawnBeat );
fStartBeat = truncf(fStartBeat)+1;
const float lStartSecond = pSong->GetElapsedTimeFromBeat( fStartBeat );
const TimingData &timing = pSong->m_SongTiming;
const float lStartSecond = timing.GetElapsedTimeFromBeat( fStartBeat );
const float fEndSecond = lStartSecond + fSecsRemaining;
fEndBeat = pSong->GetBeatFromElapsedTime( fEndSecond );
fEndBeat = timing.GetBeatFromElapsedTime( fEndSecond );
fEndBeat = truncf(fEndBeat)+1;
// loading the course should have caught this.
+1 -1
View File
@@ -99,7 +99,7 @@ void AutoKeysounds::LoadAutoplaySoundsInto( RageSoundReader_Chain *pChain )
if( tn[pn].iKeysoundIndex >= 0 )
{
RString sKeysoundFilePath = sSongDir + pSong->m_vsKeysoundFile[tn[pn].iKeysoundIndex];
float fSeconds = pSong->m_Timing.GetElapsedTimeFromBeatNoOffset( NoteRowToBeat(iRow) ) + SOUNDMAN->GetPlayLatency();
float fSeconds = pSong->m_SongTiming.GetElapsedTimeFromBeatNoOffset( NoteRowToBeat(iRow) ) + SOUNDMAN->GetPlayLatency();
float fPan = 0;
if( !bSoundIsGlobal )
+3 -3
View File
@@ -419,7 +419,7 @@ void BackgroundImpl::LoadFromRandom( float fFirstBeat, float fEndBeat, const Bac
int iStartRow = BeatToNoteRow(fFirstBeat);
int iEndRow = BeatToNoteRow(fEndBeat);
const TimingData &timing = m_pSong->m_Timing;
const TimingData &timing = m_pSong->m_SongTiming;
// change BG every time signature change or 4 measures
FOREACH_CONST( TimeSignatureSegment, timing.m_vTimeSignatureSegments, iter )
@@ -697,7 +697,7 @@ void BackgroundImpl::Layer::UpdateCurBGChange( const Song *pSong, float fLastMus
float fBeat, fBPS, fThrowAway;
bool bFreeze;
int iThrowAway;
pSong->m_Timing.GetBeatAndBPSFromElapsedTime( fCurrentTime, fBeat, fBPS, bFreeze, bFreeze, iThrowAway, fThrowAway );
pSong->m_SongTiming.GetBeatAndBPSFromElapsedTime( fCurrentTime, fBeat, fBPS, bFreeze, bFreeze, iThrowAway, fThrowAway );
// Calls to Update() should *not* be scaled by music rate; fCurrentTime is. Undo it.
const float fRate = GAMESTATE->m_SongOptions.GetCurrent().m_fMusicRate;
@@ -762,7 +762,7 @@ void BackgroundImpl::Layer::UpdateCurBGChange( const Song *pSong, float fLastMus
m_pCurrentBGA->PlayCommand( "GainFocus" );
/* How much time of this BGA have we skipped? (This happens with SetSeconds.) */
const float fStartSecond = pSong->m_Timing.GetElapsedTimeFromBeat( change.m_fStartBeat );
const float fStartSecond = pSong->m_SongTiming.GetElapsedTimeFromBeat( change.m_fStartBeat );
/* This is affected by the music rate. */
fDeltaTime = fCurrentTime - fStartSecond;
+3 -3
View File
@@ -41,9 +41,9 @@ void Foreground::LoadFromSong( const Song *pSong )
bga.m_fStartBeat = change.m_fStartBeat;
bga.m_bFinished = false;
const float fStartSecond = pSong->m_Timing.GetElapsedTimeFromBeat( bga.m_fStartBeat );
const float fStartSecond = pSong->m_SongTiming.GetElapsedTimeFromBeat( bga.m_fStartBeat );
const float fStopSecond = fStartSecond + bga.m_bga->GetTweenTimeLeft();
bga.m_fStopBeat = pSong->m_Timing.GetBeatFromElapsedTime( fStopSecond );
bga.m_fStopBeat = pSong->m_SongTiming.GetBeatFromElapsedTime( fStopSecond );
bga.m_bga->SetVisible( false );
@@ -82,7 +82,7 @@ void Foreground::Update( float fDeltaTime )
bga.m_bga->SetVisible( true );
bga.m_bga->PlayCommand( "On" );
const float fStartSecond = m_pSong->m_Timing.GetElapsedTimeFromBeat( bga.m_fStartBeat );
const float fStartSecond = m_pSong->m_SongTiming.GetElapsedTimeFromBeat( bga.m_fStartBeat );
lDeltaTime = GAMESTATE->m_fMusicSeconds - fStartSecond;
}
else
+2 -2
View File
@@ -146,7 +146,7 @@ static void StartMusic( MusicToPlay &ToPlay )
SSCLoader::LoadFromSSCFile(ToPlay.m_sTimingFile, song) )
{
ToPlay.HasTiming = true;
ToPlay.m_TimingData = song.m_Timing;
ToPlay.m_TimingData = song.m_SongTiming;
// get cabinet lights if any
Steps *pStepsCabinetLights = SongUtil::GetOneSteps( &song, StepsType_lights_cabinet );
if( pStepsCabinetLights )
@@ -156,7 +156,7 @@ static void StartMusic( MusicToPlay &ToPlay )
SMLoader::LoadFromSMFile(ToPlay.m_sTimingFile, song) )
{
ToPlay.HasTiming = true;
ToPlay.m_TimingData = song.m_Timing;
ToPlay.m_TimingData = song.m_SongTiming;
// get cabinet lights if any
Steps *pStepsCabinetLights = SongUtil::GetOneSteps( &song, StepsType_lights_cabinet );
if( pStepsCabinetLights )
+1 -1
View File
@@ -27,7 +27,7 @@ void GameplayAssist::PlayTicks( const NoteData &nd )
* come out on time; the actual precise timing is handled by SetStartTime. */
float fPositionSeconds = GAMESTATE->m_fMusicSeconds;
fPositionSeconds += SOUNDMAN->GetPlayLatency() + (float)CommonMetrics::TICK_EARLY_SECONDS + 0.250f;
const TimingData &timing = GAMESTATE->m_pCurSong->m_Timing;
const TimingData &timing = GAMESTATE->m_pCurSong->m_SongTiming;
const float fSongBeat = timing.GetBeatFromElapsedTimeNoOffset( fPositionSeconds );
const int iSongRow = max( 0, BeatToNoteRowNotRounded( fSongBeat ) );
+1 -1
View File
@@ -59,7 +59,7 @@ void LyricDisplay::Update( float fDeltaTime )
if( m_iCurLyricNumber+1 < GAMESTATE->m_pCurSong->m_LyricSegments.size() )
fEndTime = pSong->m_LyricSegments[m_iCurLyricNumber+1].m_fStartTime;
else
fEndTime = pSong->GetElapsedTimeFromBeat( pSong->m_fLastBeat );
fEndTime = pSong->m_SongTiming.GetElapsedTimeFromBeat( pSong->m_fLastBeat );
const float fDistance = fEndTime - pSong->m_LyricSegments[m_iCurLyricNumber].m_fStartTime;
const float fTweenBufferTime = IN_LENGTH.GetValue() + OUT_LENGTH.GetValue();
+2 -2
View File
@@ -73,8 +73,8 @@ void SongMeterDisplay::Update( float fDeltaTime )
{
if( GAMESTATE->m_pCurSong )
{
float fSongStartSeconds = GAMESTATE->m_pCurSong->m_Timing.GetElapsedTimeFromBeat( GAMESTATE->m_pCurSong->m_fFirstBeat );
float fSongEndSeconds = GAMESTATE->m_pCurSong->m_Timing.GetElapsedTimeFromBeat( GAMESTATE->m_pCurSong->m_fLastBeat );
float fSongStartSeconds = GAMESTATE->m_pCurSong->m_SongTiming.GetElapsedTimeFromBeat( GAMESTATE->m_pCurSong->m_fFirstBeat );
float fSongEndSeconds = GAMESTATE->m_pCurSong->m_SongTiming.GetElapsedTimeFromBeat( GAMESTATE->m_pCurSong->m_fLastBeat );
float fPercentPositionSong = SCALE( GAMESTATE->m_fMusicSeconds, fSongStartSeconds, fSongEndSeconds, 0.0f, 1.0f );
CLAMP( fPercentPositionSong, 0, 1 );
+2 -1
View File
@@ -466,7 +466,8 @@ int NoteData::GetNumTapNotes( int iStartIndex, int iEndIndex ) const
FOREACH_NONEMPTY_ROW_IN_TRACK_RANGE( *this, t, r, iStartIndex, iEndIndex )
{
const TapNote &tn = GetTapNote(t, r);
if( tn.type != TapNote::empty && tn.type != TapNote::mine && tn.type != TapNote::fake )
if( tn.type != TapNote::empty && tn.type != TapNote::mine
&& tn.type != TapNote::lift && tn.type != TapNote::fake )
iNumNotes++;
}
}
+2 -2
View File
@@ -2215,7 +2215,7 @@ void NoteDataUtil::AddTapAttacks( NoteData &nd, Song* pSong )
for( float sec=15; sec<pSong->m_fMusicLengthSeconds; sec+=30 )
{
float fBeat = pSong->GetBeatFromElapsedTime( sec );
float fBeat = pSong->m_SongTiming.GetBeatFromElapsedTime( sec );
int iBeat = (int)fBeat;
int iTrack = iBeat % nd.GetNumTracks(); // deterministically calculates track
TapNote tn(
@@ -2448,7 +2448,7 @@ void NoteDataUtil::SetHopoPossibleFlags( const Song *pSong, NoteData& ndInOut )
FOREACH_NONEMPTY_ROW_ALL_TRACKS( ndInOut, r )
{
float fBeat = NoteRowToBeat( r );
float fSeconds = pSong->GetElapsedTimeFromBeat( fBeat );
float fSeconds = pSong->m_SongTiming.GetElapsedTimeFromBeat( fBeat );
int iLastTapTrack = ndInOut.GetLastTrackWithTapOrHoldHead( r );
if( iLastTapTrack != -1 && fSeconds <= fLastRowMusicSeconds + g_fTimingWindowHopo )
+11 -9
View File
@@ -742,7 +742,7 @@ void NoteField::DrawPrimitives()
// Draw beat bars
if( GAMESTATE->IsEditing() || SHOW_BEAT_BARS )
{
const vector<TimeSignatureSegment> &vTimeSignatureSegments = GAMESTATE->m_pCurSong->m_Timing.m_vTimeSignatureSegments;
const vector<TimeSignatureSegment> &vTimeSignatureSegments = GAMESTATE->m_pCurSong->m_SongTiming.m_vTimeSignatureSegments;
int iMeasureIndex = 0;
FOREACH_CONST( TimeSignatureSegment, vTimeSignatureSegments, iter )
{
@@ -785,8 +785,10 @@ void NoteField::DrawPrimitives()
{
ASSERT(GAMESTATE->m_pCurSong);
const TimingData &timing = GAMESTATE->m_pCurSong->m_SongTiming;
// BPM text
FOREACH_CONST( BPMSegment, GAMESTATE->m_pCurSong->m_Timing.m_BPMSegments, seg )
FOREACH_CONST( BPMSegment, timing.m_BPMSegments, seg )
{
if( seg->m_iStartRow >= iFirstRowToDraw && seg->m_iStartRow <= iLastRowToDraw )
{
@@ -797,7 +799,7 @@ void NoteField::DrawPrimitives()
}
// Freeze text
FOREACH_CONST( StopSegment, GAMESTATE->m_pCurSong->m_Timing.m_StopSegments, seg )
FOREACH_CONST( StopSegment, timing.m_StopSegments, seg )
{
if( seg->m_iStartRow >= iFirstRowToDraw && seg->m_iStartRow <= iLastRowToDraw )
{
@@ -808,7 +810,7 @@ void NoteField::DrawPrimitives()
}
// Warp text
FOREACH_CONST( WarpSegment, GAMESTATE->m_pCurSong->m_Timing.m_WarpSegments, seg )
FOREACH_CONST( WarpSegment, timing.m_WarpSegments, seg )
{
if( seg->m_iStartRow >= iFirstRowToDraw && seg->m_iStartRow <= iLastRowToDraw )
{
@@ -819,7 +821,7 @@ void NoteField::DrawPrimitives()
}
// Time Signature text
FOREACH_CONST( TimeSignatureSegment, GAMESTATE->m_pCurSong->m_Timing.m_vTimeSignatureSegments, seg )
FOREACH_CONST( TimeSignatureSegment, timing.m_vTimeSignatureSegments, seg )
{
if( seg->m_iStartRow >= iFirstRowToDraw && seg->m_iStartRow <= iLastRowToDraw )
{
@@ -830,7 +832,7 @@ void NoteField::DrawPrimitives()
}
// Tickcount text
FOREACH_CONST( TickcountSegment, GAMESTATE->m_pCurSong->m_Timing.m_TickcountSegments, seg )
FOREACH_CONST( TickcountSegment, timing.m_TickcountSegments, seg )
{
if( seg->m_iStartRow >= iFirstRowToDraw && seg->m_iStartRow <= iLastRowToDraw )
{
@@ -841,7 +843,7 @@ void NoteField::DrawPrimitives()
}
// Combo text
FOREACH_CONST( ComboSegment, GAMESTATE->m_pCurSong->m_Timing.m_ComboSegments, seg )
FOREACH_CONST( ComboSegment, timing.m_ComboSegments, seg )
{
if( seg->m_iStartRow >= iFirstRowToDraw && seg->m_iStartRow <= iLastRowToDraw )
{
@@ -852,7 +854,7 @@ void NoteField::DrawPrimitives()
}
// Label text
FOREACH_CONST( LabelSegment, GAMESTATE->m_pCurSong->m_Timing.m_LabelSegments, seg )
FOREACH_CONST( LabelSegment, timing.m_LabelSegments, seg )
{
if( seg->m_iStartRow >= iFirstRowToDraw && seg->m_iStartRow <= iLastRowToDraw )
{
@@ -872,7 +874,7 @@ void NoteField::DrawPrimitives()
FOREACH_CONST( Attack, ce.attacks, a )
{
float fSecond = a->fStartSecond;
float fBeat = GAMESTATE->m_pCurSong->m_Timing.GetBeatFromElapsedTime( fSecond );
float fBeat = timing.GetBeatFromElapsedTime( fSecond );
if( BeatToNoteRow(fBeat) >= iFirstRowToDraw &&
BeatToNoteRow(fBeat) <= iLastRowToDraw)
+6 -6
View File
@@ -799,7 +799,7 @@ static void ReadGlobalTags( const NameToData_t &mapNameToData, Song &out, Measur
if( PREFSMAN->m_bQuirksMode )
{
BPMSegment newSeg( 0, fBPM );
out.AddBPMSegment( newSeg );
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
@@ -810,7 +810,7 @@ static void ReadGlobalTags( const NameToData_t &mapNameToData, Song &out, Measur
if( fBPM > 0.0f )
{
BPMSegment newSeg( 0, fBPM );
out.AddBPMSegment( newSeg );
out.m_SongTiming.AddBPMSegment( newSeg );
LOG->Trace( "Inserting new BPM change at beat %f, BPM %f", NoteRowToBeat(0), fBPM );
}
else
@@ -901,7 +901,7 @@ static void ReadGlobalTags( const NameToData_t &mapNameToData, Song &out, Measur
case BMS_TRACK_BPM:
if( iVal > 0 )
{
out.SetBPMAtBeat( fBeat, (float) iVal );
out.m_SongTiming.SetBPMAtBeat( fBeat, (float) iVal );
LOG->Trace( "Inserting new BPM change at beat %f, BPM %i", fBeat, iVal );
}
else
@@ -918,7 +918,7 @@ static void ReadGlobalTags( const NameToData_t &mapNameToData, Song &out, Measur
if( GetTagFromMap( mapNameToData, sTagToLookFor, sBPM ) )
{
float fBPM = StringToFloat( sBPM );
out.SetBPMAtBeat( fBeat, fBPM );
out.m_SongTiming.SetBPMAtBeat( fBeat, fBPM );
}
else
{
@@ -937,12 +937,12 @@ static void ReadGlobalTags( const NameToData_t &mapNameToData, Song &out, Measur
if( GetTagFromMap( mapNameToData, sTagToLookFor, sBeats ) )
{
// find the BPM at the time of this freeze
float fBPS = out.m_Timing.GetBPMAtBeat(fBeat) / 60.0f;
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.AddStopSegment( newSeg );
out.m_SongTiming.AddStopSegment( newSeg );
LOG->Trace( "Inserting new Freeze at beat %f, secs %f", fBeat, newSeg.m_fStopSeconds );
}
else
+12 -12
View File
@@ -358,7 +358,7 @@ static bool LoadGlobalData( const RString &sPath, Song &out, bool &bKIUCompliant
else if( sValueName=="BPM" )
{
BPM1 = StringToFloat(sParams[1]);
out.AddBPMSegment( BPMSegment(0, BPM1) );
out.m_SongTiming.AddBPMSegment( BPMSegment(0, BPM1) );
}
else if( sValueName=="BPM2" )
{
@@ -383,7 +383,7 @@ static bool LoadGlobalData( const RString &sPath, Song &out, bool &bKIUCompliant
else if( sValueName=="STARTTIME" )
{
SMGap1 = -StringToFloat( sParams[1] )/100;
out.m_Timing.m_fBeat0OffsetInSeconds = SMGap1;
out.m_SongTiming.m_fBeat0OffsetInSeconds = SMGap1;
}
// This is currently required for more accurate KIU BPM changes.
else if( sValueName=="STARTTIME2" )
@@ -409,7 +409,7 @@ static bool LoadGlobalData( const RString &sPath, Song &out, bool &bKIUCompliant
TickcountSegment tcs;
tcs.m_iStartRow = BeatToNoteRow(0.0f);
tcs.m_iTicks = iTickCount > ROWS_PER_BEAT ? ROWS_PER_BEAT : iTickCount;
out.m_Timing.AddTickcountSegment( tcs );
out.m_SongTiming.AddTickcountSegment( tcs );
}
else if ( sValueName=="STEP" )
{
@@ -469,7 +469,7 @@ static bool LoadGlobalData( const RString &sPath, Song &out, bool &bKIUCompliant
const float beat = (BPMPos2 + SMGap1) * BeatsPerSecond;
LOG->Trace( "BPM %f, BPS %f, BPMPos2 %f, beat %f",
BPM1, BeatsPerSecond, BPMPos2, beat );
out.AddBPMSegment( BPMSegment(BeatToNoteRow(beat), BPM2) );
out.m_SongTiming.AddBPMSegment( BPMSegment(BeatToNoteRow(beat), BPM2) );
}
if( BPM3 > 0 && BPMPos3 > 0 )
@@ -479,7 +479,7 @@ static bool LoadGlobalData( const RString &sPath, Song &out, bool &bKIUCompliant
const float beat = (BPMPos3 + SMGap2) * BeatsPerSecond;
LOG->Trace( "BPM %f, BPS %f, BPMPos3 %f, beat %f",
BPM2, BeatsPerSecond, BPMPos3, beat );
out.AddBPMSegment( BPMSegment(BeatToNoteRow(beat), BPM3) );
out.m_SongTiming.AddBPMSegment( BPMSegment(BeatToNoteRow(beat), BPM3) );
}
}
else
@@ -515,7 +515,7 @@ static bool LoadGlobalData( const RString &sPath, Song &out, bool &bKIUCompliant
TickcountSegment tcs;
tcs.m_iStartRow = BeatToNoteRow(fCurBeat);
tcs.m_iTicks = iTickCount > ROWS_PER_BEAT ? ROWS_PER_BEAT : iTickCount;
out.m_Timing.AddTickcountSegment( tcs );
out.m_SongTiming.AddTickcountSegment( tcs );
continue;
}
@@ -523,22 +523,22 @@ static bool LoadGlobalData( const RString &sPath, Song &out, bool &bKIUCompliant
{
float fCurBpm = (float)numTemp;
//out.m_Timing.AddBPMSegment( BPMSegment( BeatToNoteRow(fCurBeat), (float)numTemp ) );
out.m_Timing.SetBPMAtBeat( fCurBeat, fCurBpm );
out.m_SongTiming.SetBPMAtBeat( fCurBeat, fCurBpm );
continue;
}
else if (BeginsWith(NoteRowString, "|E"))
{
// Finally! the |E| tag is working as it should. I can die happy now -DaisuMaster
float fCurDelay = 60 / out.m_Timing.GetBPMAtBeat(fCurBeat) * (float)numTemp / iTickCount;
fCurDelay += out.m_Timing.GetStopAtRow(BeatToNoteRow(fCurBeat) );
out.m_Timing.SetStopAtBeat( fCurBeat, fCurDelay, true );
float fCurDelay = 60 / out.m_SongTiming.GetBPMAtBeat(fCurBeat) * (float)numTemp / iTickCount;
fCurDelay += out.m_SongTiming.GetStopAtRow(BeatToNoteRow(fCurBeat) );
out.m_SongTiming.SetStopAtBeat( fCurBeat, fCurDelay, true );
continue;
}
else if (BeginsWith(NoteRowString, "|D"))
{
float fCurDelay = out.m_Timing.GetStopAtRow(BeatToNoteRow(fCurBeat) );
float fCurDelay = out.m_SongTiming.GetStopAtRow(BeatToNoteRow(fCurBeat) );
fCurDelay += (float)numTemp / 1000;
out.m_Timing.SetStopAtBeat( fCurBeat, fCurDelay, true );
out.m_SongTiming.SetStopAtBeat( fCurBeat, fCurDelay, true );
continue;
}
}
+2 -2
View File
@@ -682,7 +682,7 @@ static bool LoadFromMidi( const RString &sPath, Song &songOut )
double fSecondsPerBeat = (iter->tickSeconds * GUITAR_MIDI_COUNTS_PER_BEAT);
bpmSeg.m_fBPS = float( 1. / fSecondsPerBeat );
songOut.m_Timing.AddBPMSegment( bpmSeg );
songOut.m_SongTiming.AddBPMSegment( bpmSeg );
}
FOREACH_CONST( MidiFileIn::TimeSignatureChange, midi.timeSignatureEvents_, iter )
@@ -692,7 +692,7 @@ static bool LoadFromMidi( const RString &sPath, Song &songOut )
seg.m_iNumerator = iter->numerator;
seg.m_iDenominator = iter->denominator;
songOut.m_Timing.AddTimeSignatureSegment( seg );
songOut.m_SongTiming.AddTimeSignatureSegment( seg );
}
+6 -6
View File
@@ -591,7 +591,7 @@ static void ReadGlobalTags( const NameToData_t &mapNameToData, Song &out, Measur
if( fBPM > 0.0f )
{
BPMSegment newSeg( 0, fBPM );
out.AddBPMSegment( newSeg );
out.m_SongTiming.AddBPMSegment( newSeg );
LOG->Trace( "Inserting new BPM change at beat %f, BPM %f", NoteRowToBeat(0), fBPM );
}
else
@@ -673,7 +673,7 @@ static void ReadGlobalTags( const NameToData_t &mapNameToData, Song &out, Measur
case PMS_TRACK_BPM:
if( iVal > 0 )
{
out.SetBPMAtBeat( fBeat, (float) iVal );
out.m_SongTiming.SetBPMAtBeat( fBeat, (float) iVal );
LOG->Trace( "Inserting new BPM change at beat %f, BPM %i", fBeat, iVal );
}
else
@@ -694,7 +694,7 @@ static void ReadGlobalTags( const NameToData_t &mapNameToData, Song &out, Measur
if( fBPM > 0.0f )
{
BPMSegment newSeg( BeatToNoteRow(fBeat), fBPM );
out.AddBPMSegment( newSeg );
out.m_SongTiming.AddBPMSegment( newSeg );
LOG->Trace( "Inserting new BPM change at beat %f, BPM %f", fBeat, newSeg.GetBPM() );
}
else
@@ -716,12 +716,12 @@ static void ReadGlobalTags( const NameToData_t &mapNameToData, Song &out, Measur
if( GetTagFromMap( mapNameToData, sTagToLookFor, sBeats ) )
{
// find the BPM at the time of this freeze
float fBPS = out.m_Timing.GetBPMAtBeat(fBeat) / 60.0f;
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.AddStopSegment( newSeg );
out.m_SongTiming.AddStopSegment( newSeg );
LOG->Trace( "Inserting new Freeze at beat %f, secs %f", fBeat, newSeg.m_fStopSeconds );
}
else
@@ -750,7 +750,7 @@ static void ReadGlobalTags( const NameToData_t &mapNameToData, Song &out, Measur
if( fBPM > 0.0f )
{
BPMSegment newSeg( iStepIndex, fBPM );
out.AddBPMSegment( newSeg );
out.m_SongTiming.AddBPMSegment( newSeg );
LOG->Trace( "Inserting new BPM change at beat %f, BPM %f", NoteRowToBeat(newSeg.m_iStartRow), newSeg.GetBPM() );
}
+243 -233
View File
@@ -103,6 +103,244 @@ bool SMLoader::LoadTimingFromFile( const RString &fn, TimingData &out )
return true;
}
void SMLoader::ProcessBPMs( TimingData &out, const RString sParam )
{
vector<RString> arrayBPMChangeExpressions;
split( sParam, ",", arrayBPMChangeExpressions );
// prepare storage variables for negative BPMs -> Warps.
float negBeat = -1;
float negBPM = 1;
float highspeedBeat = -1;
for( unsigned b=0; b<arrayBPMChangeExpressions.size(); b++ )
{
vector<RString> arrayBPMChangeValues;
split( arrayBPMChangeExpressions[b], "=", arrayBPMChangeValues );
// XXX: Hard to tell which file caused this.
if( arrayBPMChangeValues.size() != 2 )
{
LOG->UserLog( "Song file", "(UNKNOWN)", "has an invalid #BPMs value \"%s\" (must have exactly one '='), ignored.",
arrayBPMChangeExpressions[b].c_str() );
continue;
}
const float fBeat = StringToFloat( arrayBPMChangeValues[0] );
const float fNewBPM = StringToFloat( arrayBPMChangeValues[1] );
if( fNewBPM < 0.0f )
{
out.m_bHasNegativeBpms = true;
negBeat = fBeat;
negBPM = fNewBPM;
}
else if( fNewBPM > 0.0f )
{
// add in a warp.
if( negBPM < 0 )
{
float endBeat = fBeat + (fNewBPM / -negBPM) * (fBeat - negBeat);
WarpSegment new_seg(negBeat, endBeat);
out.AddWarpSegment( new_seg );
negBeat = -1;
negBPM = 1;
}
// too fast. make it a warp.
if( fNewBPM > FAST_BPM_WARP )
{
highspeedBeat = fBeat;
}
else
{
// add in a warp.
if( highspeedBeat > 0 )
{
WarpSegment new_seg(highspeedBeat, fBeat);
out.AddWarpSegment( new_seg );
highspeedBeat = -1;
}
{
BPMSegment new_seg;
new_seg.m_iStartRow = BeatToNoteRow(fBeat);
new_seg.SetBPM( fNewBPM );
out.AddBPMSegment( new_seg );
}
}
}
}
}
void SMLoader::ProcessStops( TimingData &out, const RString sParam )
{
vector<RString> arrayFreezeExpressions;
split( sParam, ",", arrayFreezeExpressions );
// Prepare variables for negative stop conversion.
float negBeat = -1;
float negPause = 0;
for( unsigned f=0; f<arrayFreezeExpressions.size(); f++ )
{
vector<RString> arrayFreezeValues;
split( arrayFreezeExpressions[f], "=", arrayFreezeValues );
if( arrayFreezeValues.size() != 2 )
{
// XXX: Hard to tell which file caused this.
LOG->UserLog( "Song file", "(UNKNOWN)", "has an invalid #STOPS value \"%s\" (must have exactly one '='), ignored.",
arrayFreezeExpressions[f].c_str() );
continue;
}
const float fFreezeBeat = StringToFloat( arrayFreezeValues[0] );
const float fFreezeSeconds = StringToFloat( arrayFreezeValues[1] );
// Process the prior stop.
if( negPause > 0 )
{
BPMSegment oldBPM = out.GetBPMSegmentAtRow(BeatToNoteRow(negBeat));
float fSecondsPerBeat = 60 / oldBPM.GetBPM();
float fSkipBeats = negPause / fSecondsPerBeat;
if( negBeat + fSkipBeats > fFreezeBeat )
fSkipBeats = fFreezeBeat - negBeat;
WarpSegment ws( negBeat, negBeat + fSkipBeats);
out.AddWarpSegment( ws );
negBeat = -1;
negPause = 0;
}
if( fFreezeSeconds < 0.0f )
{
negBeat = fFreezeBeat;
negPause = -fFreezeSeconds;
}
else if( fFreezeSeconds > 0.0f )
{
StopSegment ss( BeatToNoteRow(fFreezeBeat), fFreezeSeconds );
out.AddStopSegment( ss );
}
}
// Process the prior stop if there was one.
if( negPause > 0 )
{
BPMSegment oldBPM = out.GetBPMSegmentAtRow(BeatToNoteRow(negBeat));
float fSecondsPerBeat = 60 / oldBPM.GetBPM();
float fSkipBeats = negPause / fSecondsPerBeat;
WarpSegment ws( negBeat, negBeat + fSkipBeats);
out.AddWarpSegment( ws );
}
}
void SMLoader::ProcessDelays( TimingData &out, const RString sParam )
{
vector<RString> arrayDelayExpressions;
split( sParam, ",", arrayDelayExpressions );
for( unsigned f=0; f<arrayDelayExpressions.size(); f++ )
{
vector<RString> arrayDelayValues;
split( arrayDelayExpressions[f], "=", arrayDelayValues );
if( arrayDelayValues.size() != 2 )
{
// XXX: Hard to tell which file caused this.
LOG->UserLog( "Song file", "(UNKNOWN)", "has an invalid #DELAYS value \"%s\" (must have exactly one '='), ignored.",
arrayDelayExpressions[f].c_str() );
continue;
}
const float fFreezeBeat = StringToFloat( arrayDelayValues[0] );
const float fFreezeSeconds = StringToFloat( arrayDelayValues[1] );
StopSegment new_seg( BeatToNoteRow(fFreezeBeat), fFreezeSeconds, true );
// XXX: Remove Negatives Bug?
new_seg.m_iStartRow = BeatToNoteRow(fFreezeBeat);
new_seg.m_fStopSeconds = fFreezeSeconds;
// LOG->Trace( "Adding a delay segment: beat: %f, seconds = %f", new_seg.m_fStartBeat, new_seg.m_fStopSeconds );
if(fFreezeSeconds > 0.0f)
out.AddStopSegment( new_seg );
else
LOG->UserLog( "Song file", "(UNKNOWN)", "has an invalid delay at beat %f, length %f.", fFreezeBeat, fFreezeSeconds );
}
}
void SMLoader::ProcessTimeSignatures( TimingData &out, const RString sParam )
{
vector<RString> vs1;
split( sParam, ",", vs1 );
FOREACH_CONST( RString, vs1, s1 )
{
vector<RString> vs2;
split( *s1, "=", vs2 );
if( vs2.size() < 3 )
{
LOG->UserLog( "Song file", "(UNKNOWN)", "has an invalid time signature change with %i values.", (int)vs2.size() );
continue;
}
const float fBeat = StringToFloat( vs2[0] );
TimeSignatureSegment seg;
seg.m_iStartRow = BeatToNoteRow(fBeat);
seg.m_iNumerator = atoi( vs2[1] );
seg.m_iDenominator = atoi( vs2[2] );
if( fBeat < 0 )
{
LOG->UserLog( "Song file", "(UNKNOWN)", "has an invalid time signature change with beat %f.", fBeat );
continue;
}
if( seg.m_iNumerator < 1 )
{
LOG->UserLog( "Song file", "(UNKNOWN)", "has an invalid time signature change with beat %f, iNumerator %i.", fBeat, seg.m_iNumerator );
continue;
}
if( seg.m_iDenominator < 1 )
{
LOG->UserLog( "Song file", "(UNKNOWN)", "has an invalid time signature change with beat %f, iDenominator %i.", fBeat, seg.m_iDenominator );
continue;
}
out.AddTimeSignatureSegment( seg );
}
}
void SMLoader::ProcessTickcounts( TimingData &out, const RString sParam )
{
vector<RString> arrayTickcountExpressions;
split( sParam, ",", arrayTickcountExpressions );
for( unsigned f=0; f<arrayTickcountExpressions.size(); f++ )
{
vector<RString> arrayTickcountValues;
split( arrayTickcountExpressions[f], "=", arrayTickcountValues );
if( arrayTickcountValues.size() != 2 )
{
// XXX: Hard to tell which file caused this.
LOG->UserLog( "Song file", "(UNKNOWN)", "has an invalid #TICKCOUNTS value \"%s\" (must have exactly one '='), ignored.",
arrayTickcountExpressions[f].c_str() );
continue;
}
const float fTickcountBeat = StringToFloat( arrayTickcountValues[0] );
int iTicks = clamp(atoi( arrayTickcountValues[1] ), 0, ROWS_PER_BEAT);
TickcountSegment new_seg( BeatToNoteRow(fTickcountBeat), iTicks );
out.AddTickcountSegment( new_seg );
}
}
void SMLoader::LoadTimingFromSMFile( const MsdFile &msd, TimingData &out )
{
out.m_fBeat0OffsetInSeconds = 0;
@@ -123,255 +361,27 @@ void SMLoader::LoadTimingFromSMFile( const MsdFile &msd, TimingData &out )
}
else if( sValueName=="BPMS" )
{
vector<RString> arrayBPMChangeExpressions;
split( sParams[1], ",", arrayBPMChangeExpressions );
// prepare storage variables for negative BPMs -> Warps.
float negBeat = -1;
float negBPM = 1;
float highspeedBeat = -1;
for( unsigned b=0; b<arrayBPMChangeExpressions.size(); b++ )
{
vector<RString> arrayBPMChangeValues;
split( arrayBPMChangeExpressions[b], "=", arrayBPMChangeValues );
// XXX: Hard to tell which file caused this.
if( arrayBPMChangeValues.size() != 2 )
{
LOG->UserLog( "Song file", "(UNKNOWN)", "has an invalid #%s value \"%s\" (must have exactly one '='), ignored.",
sValueName.c_str(), arrayBPMChangeExpressions[b].c_str() );
continue;
}
const float fBeat = StringToFloat( arrayBPMChangeValues[0] );
const float fNewBPM = StringToFloat( arrayBPMChangeValues[1] );
if( fNewBPM < 0.0f )
{
out.m_bHasNegativeBpms = true;
negBeat = fBeat;
negBPM = fNewBPM;
}
else if( fNewBPM > 0.0f )
{
// add in a warp.
if( negBPM < 0 )
{
float endBeat = fBeat + (fNewBPM / -negBPM) * (fBeat - negBeat);
WarpSegment new_seg(negBeat, endBeat);
out.AddWarpSegment( new_seg );
negBeat = -1;
negBPM = 1;
}
// too fast. make it a warp.
if( fNewBPM > FAST_BPM_WARP )
{
highspeedBeat = fBeat;
}
else
{
// add in a warp.
if( highspeedBeat > 0 )
{
WarpSegment new_seg(highspeedBeat, fBeat);
out.AddWarpSegment( new_seg );
highspeedBeat = -1;
}
{
BPMSegment new_seg;
new_seg.m_iStartRow = BeatToNoteRow(fBeat);
new_seg.SetBPM( fNewBPM );
out.AddBPMSegment( new_seg );
}
}
}
}
ProcessBPMs(out, sParams[1]);
}
else if( sValueName=="STOPS" || sValueName=="FREEZES" )
{
vector<RString> arrayFreezeExpressions;
split( sParams[1], ",", arrayFreezeExpressions );
// Prepare variables for negative stop conversion.
float negBeat = -1;
float negPause = 0;
for( unsigned f=0; f<arrayFreezeExpressions.size(); f++ )
{
vector<RString> arrayFreezeValues;
split( arrayFreezeExpressions[f], "=", arrayFreezeValues );
if( arrayFreezeValues.size() != 2 )
{
// XXX: Hard to tell which file caused this.
LOG->UserLog( "Song file", "(UNKNOWN)", "has an invalid #%s value \"%s\" (must have exactly one '='), ignored.",
sValueName.c_str(), arrayFreezeExpressions[f].c_str() );
continue;
}
const float fFreezeBeat = StringToFloat( arrayFreezeValues[0] );
const float fFreezeSeconds = StringToFloat( arrayFreezeValues[1] );
// Process the prior stop.
if( negPause > 0 )
{
BPMSegment oldBPM = out.GetBPMSegmentAtRow(BeatToNoteRow(negBeat));
float fSecondsPerBeat = 60 / oldBPM.GetBPM();
float fSkipBeats = negPause / fSecondsPerBeat;
if( negBeat + fSkipBeats > fFreezeBeat )
fSkipBeats = fFreezeBeat - negBeat;
WarpSegment ws( negBeat, negBeat + fSkipBeats);
out.AddWarpSegment( ws );
negBeat = -1;
negPause = 0;
}
if( fFreezeSeconds < 0.0f )
{
negBeat = fFreezeBeat;
negPause = -fFreezeSeconds;
}
else if( fFreezeSeconds > 0.0f )
{
StopSegment ss( BeatToNoteRow(fFreezeBeat), fFreezeSeconds );
out.AddStopSegment( ss );
}
}
// Process the prior stop if there was one.
if( negPause > 0 )
{
BPMSegment oldBPM = out.GetBPMSegmentAtRow(BeatToNoteRow(negBeat));
float fSecondsPerBeat = 60 / oldBPM.GetBPM();
float fSkipBeats = negPause / fSecondsPerBeat;
WarpSegment ws( negBeat, negBeat + fSkipBeats);
out.AddWarpSegment( ws );
}
ProcessStops(out, sParams[1]);
}
else if( sValueName=="DELAYS" )
{
vector<RString> arrayDelayExpressions;
split( sParams[1], ",", arrayDelayExpressions );
for( unsigned f=0; f<arrayDelayExpressions.size(); f++ )
{
vector<RString> arrayDelayValues;
split( arrayDelayExpressions[f], "=", arrayDelayValues );
if( arrayDelayValues.size() != 2 )
{
// XXX: Hard to tell which file caused this.
LOG->UserLog( "Song file", "(UNKNOWN)", "has an invalid #%s value \"%s\" (must have exactly one '='), ignored.",
sValueName.c_str(), arrayDelayExpressions[f].c_str() );
continue;
}
const float fFreezeBeat = StringToFloat( arrayDelayValues[0] );
const float fFreezeSeconds = StringToFloat( arrayDelayValues[1] );
StopSegment new_seg( BeatToNoteRow(fFreezeBeat), fFreezeSeconds, true );
// XXX: Remove Negatives Bug?
new_seg.m_iStartRow = BeatToNoteRow(fFreezeBeat);
new_seg.m_fStopSeconds = fFreezeSeconds;
// LOG->Trace( "Adding a delay segment: beat: %f, seconds = %f", new_seg.m_fStartBeat, new_seg.m_fStopSeconds );
if(fFreezeSeconds > 0.0f)
out.AddStopSegment( new_seg );
else
LOG->UserLog( "Song file", "(UNKNOWN)", "has an invalid delay at beat %f, length %f.", fFreezeBeat, fFreezeSeconds );
}
ProcessDelays(out, sParams[1]);
}
else if( sValueName=="TIMESIGNATURES" )
{
vector<RString> vs1;
split( sParams[1], ",", vs1 );
FOREACH_CONST( RString, vs1, s1 )
{
vector<RString> vs2;
split( *s1, "=", vs2 );
if( vs2.size() < 3 )
{
LOG->UserLog( "Song file", "(UNKNOWN)", "has an invalid time signature change with %i values.", (int)vs2.size() );
continue;
}
const float fBeat = StringToFloat( vs2[0] );
TimeSignatureSegment seg;
seg.m_iStartRow = BeatToNoteRow(fBeat);
seg.m_iNumerator = atoi( vs2[1] );
seg.m_iDenominator = atoi( vs2[2] );
if( fBeat < 0 )
{
LOG->UserLog( "Song file", "(UNKNOWN)", "has an invalid time signature change with beat %f.", fBeat );
continue;
}
if( seg.m_iNumerator < 1 )
{
LOG->UserLog( "Song file", "(UNKNOWN)", "has an invalid time signature change with beat %f, iNumerator %i.", fBeat, seg.m_iNumerator );
continue;
}
if( seg.m_iDenominator < 1 )
{
LOG->UserLog( "Song file", "(UNKNOWN)", "has an invalid time signature change with beat %f, iDenominator %i.", fBeat, seg.m_iDenominator );
continue;
}
out.AddTimeSignatureSegment( seg );
}
ProcessTimeSignatures(out, sParams[1]);
}
else if( sValueName=="TICKCOUNTS" )
{
vector<RString> arrayTickcountExpressions;
split( sParams[1], ",", arrayTickcountExpressions );
for( unsigned f=0; f<arrayTickcountExpressions.size(); f++ )
{
vector<RString> arrayTickcountValues;
split( arrayTickcountExpressions[f], "=", arrayTickcountValues );
if( arrayTickcountValues.size() != 2 )
{
// XXX: Hard to tell which file caused this.
LOG->UserLog( "Song file", "(UNKNOWN)", "has an invalid #%s value \"%s\" (must have exactly one '='), ignored.",
sValueName.c_str(), arrayTickcountExpressions[f].c_str() );
continue;
}
const float fTickcountBeat = StringToFloat( arrayTickcountValues[0] );
int iTicks = atoi( arrayTickcountValues[1] );
// you're lazy, let SM do the work for you... -DaisuMaster
if( iTicks < 1) iTicks = 1;
if( iTicks > ROWS_PER_BEAT ) iTicks = ROWS_PER_BEAT;
TickcountSegment new_seg( BeatToNoteRow(fTickcountBeat), iTicks );
out.AddTickcountSegment( new_seg );
if(iTicks >= 1 && iTicks <= ROWS_PER_BEAT ) // Constants
{
// LOG->Trace( "Adding a tickcount segment: beat: %f, ticks = %d", fTickcountBeat, iTicks );
//out.AddTickcountSegment( new_seg );
}
else
{
//LOG->UserLog( "Song file", "(UNKNOWN)", "has an invalid tickcount at beat %f, ticks %d.", fTickcountBeat, iTicks );
//LOG->UserLog( "Song file", "(UNKNOWN)", "Clamping tickcount value to %d at beat %f.", iTicks, fTickcountBeat);
//etc
}
}
ProcessTickcounts(out, sParams[1]);
}
// Ensure all of the warps are handled right.
sort(out.m_WarpSegments.begin(), out.m_WarpSegments.end());
+7
View File
@@ -25,6 +25,13 @@ namespace SMLoader
bool LoadEditFromBuffer( const RString &sBuffer, const RString &sEditFilePath, ProfileSlot slot );
bool LoadEditFromMsd( const MsdFile &msd, const RString &sEditFilePath, ProfileSlot slot, bool bAddStepsToSong );
bool LoadFromBGChangesString( BackgroundChange &change, const RString &sBGChangeExpression );
void ProcessBPMs( TimingData &, const RString );
void ProcessStops( TimingData &, const RString );
void ProcessDelays( TimingData &, const RString );
void ProcessTimeSignatures( TimingData &, const RString );
void ProcessTickcounts( TimingData &, const RString );
}
#endif
+2 -2
View File
@@ -113,8 +113,8 @@ bool SMALoader::LoadFromSMAFile( const RString &sPath, Song &out )
return false;
}
out.m_Timing.m_sFile = sPath;
LoadTimingFromSMAFile( msd, out.m_Timing );
out.m_SongTiming.m_sFile = sPath;
LoadTimingFromSMAFile( msd, out.m_SongTiming );
for( unsigned i=0; i<msd.GetNumValues(); i++ )
{
+111 -393
View File
@@ -4,7 +4,7 @@
#include "GameManager.h"
#include "MsdFile.h" // No JSON here.
#include "NoteTypes.h"
#include "NotesLoaderSM.h" // For loading SM style edits.
#include "NotesLoaderSM.h" // For programming shortcuts.
#include "RageFileManager.h"
#include "RageLog.h"
#include "RageUtil.h"
@@ -21,79 +21,13 @@ const int MAX_EDIT_STEPS_SIZE_BYTES = 60*1024; // 60 KB
/**
* @brief Attempt to load any background changes in use by this song.
*
* This code is right now copied from NotesLoaderSM. There may be a time
* when we add to this code, or perhaps just refactor it properly.
* @param change a reference to the background change.
* @param sBGChangeExpression a reference to the list of changes to be made.
* @return its success or failure.
*/
bool LoadFromBGSSCChangesString( BackgroundChange &change, const RString &sBGChangeExpression )
{
vector<RString> aBGChangeValues;
split( sBGChangeExpression, "=", aBGChangeValues, false );
aBGChangeValues.resize( min((int)aBGChangeValues.size(),11) );
switch( aBGChangeValues.size() )
{
case 11:
change.m_def.m_sColor2 = aBGChangeValues[10];
change.m_def.m_sColor2.Replace( '^', ',' );
change.m_def.m_sColor2 = RageColor::NormalizeColorString( change.m_def.m_sColor2 );
// fall through
case 10:
change.m_def.m_sColor1 = aBGChangeValues[9];
change.m_def.m_sColor1.Replace( '^', ',' );
change.m_def.m_sColor1 = RageColor::NormalizeColorString( change.m_def.m_sColor1 );
// fall through
case 9:
change.m_sTransition = aBGChangeValues[8];
// fall through
case 8:
change.m_def.m_sFile2 = aBGChangeValues[7];
// fall through
case 7:
change.m_def.m_sEffect = aBGChangeValues[6];
// fall through
case 6:
// param 7 overrides this.
// Backward compatibility:
if( change.m_def.m_sEffect.empty() )
{
bool bLoop = atoi( aBGChangeValues[5] ) != 0;
if( !bLoop )
change.m_def.m_sEffect = SBE_StretchNoLoop;
}
// fall through
case 5:
// param 7 overrides this.
// Backward compatibility:
if( change.m_def.m_sEffect.empty() )
{
bool bRewindMovie = atoi( aBGChangeValues[4] ) != 0;
if( bRewindMovie )
change.m_def.m_sEffect = SBE_StretchRewind;
}
// fall through
case 4:
// param 9 overrides this.
// Backward compatibility:
if( change.m_sTransition.empty() )
change.m_sTransition = (atoi( aBGChangeValues[3] ) != 0) ? "CrossFade" : "";
// fall through
case 3:
change.m_fRate = StringToFloat( aBGChangeValues[2] );
// fall through
case 2:
change.m_def.m_sFile1 = aBGChangeValues[1];
// fall through
case 1:
change.m_fStartBeat = StringToFloat( aBGChangeValues[0] );
// fall through
}
return aBGChangeValues.size() >= 2;
return SMLoader::LoadFromBGChangesString( change, sBGChangeExpression );
}
bool SSCLoader::LoadFromDir( const RString &sPath, Song &out )
@@ -112,6 +46,86 @@ bool SSCLoader::LoadFromDir( const RString &sPath, Song &out )
return LoadFromSSCFile( sPath + aFileNames[0], out );
}
void SSCLoader::ProcessWarps( TimingData &out, const RString sParam )
{
vector<RString> arrayWarpExpressions;
split( sParam, ",", arrayWarpExpressions );
for( unsigned b=0; b<arrayWarpExpressions.size(); b++ )
{
vector<RString> arrayWarpValues;
split( arrayWarpExpressions[b], "=", arrayWarpValues );
// XXX: Hard to tell which file caused this.
if( arrayWarpValues.size() != 2 )
{
LOG->UserLog( "Song file", "(UNKNOWN)", "has an invalid #WARPS value \"%s\" (must have exactly one '='), ignored.",
arrayWarpExpressions[b].c_str() );
continue;
}
const float fBeat = StringToFloat( arrayWarpValues[0] );
const float fNewBeat = StringToFloat( arrayWarpValues[1] );
if(fNewBeat > fBeat)
out.AddWarpSegment( WarpSegment(fBeat, fNewBeat) );
else
{
LOG->UserLog( "Song file", "(UNKNOWN)", "has an invalid Warp at beat %f, BPM %f.", fBeat, fNewBeat );
}
}
}
void SSCLoader::ProcessLabels( TimingData &out, const RString sParam )
{
vector<RString> arrayLabelExpressions;
split( sParam, ",", arrayLabelExpressions );
for( unsigned b=0; b<arrayLabelExpressions.size(); b++ )
{
vector<RString> arrayLabelValues;
split( arrayLabelExpressions[b], "=", arrayLabelValues );
if( arrayLabelValues.size() != 2 )
{
LOG->UserLog( "Song file", "(UNKNOWN)", "has an invalid #LABELS value \"%s\" (must have exactly one '='), ignored.",
arrayLabelExpressions[b].c_str() );
continue;
}
const float fBeat = StringToFloat( arrayLabelValues[0] );
RString sLabel = arrayLabelValues[1];
TrimRight(sLabel);
if( fBeat >= 0.0f )
out.AddLabelSegment( LabelSegment(fBeat, sLabel) );
else
{
LOG->UserLog( "Song file", "(UNKNOWN)", "has an invalid Label at beat %f called %s.", fBeat, sLabel.c_str() );
}
}
}
void SSCLoader::ProcessCombos( TimingData &out, const RString sParam )
{
vector<RString> arrayComboExpressions;
split( sParam, ",", arrayComboExpressions );
for( unsigned f=0; f<arrayComboExpressions.size(); f++ )
{
vector<RString> arrayComboValues;
split( arrayComboExpressions[f], "=", arrayComboValues );
if( arrayComboValues.size() != 2 )
{
LOG->UserLog( "Song file", "(UNKNOWN)", "has an invalid #COMBOS value \"%s\" (must have exactly one '='), ignored.",
arrayComboExpressions[f].c_str() );
continue;
}
const float fComboBeat = StringToFloat( arrayComboValues[0] );
const int iCombos = atoi( arrayComboValues[1] );
ComboSegment new_seg( BeatToNoteRow( fComboBeat ), iCombos );
out.AddComboSegment( new_seg );
}
}
bool SSCLoader::LoadFromSSCFile( const RString &sPath, Song &out, bool bFromCache )
{
LOG->Trace( "Song::LoadFromSSCFile(%s)", sPath.c_str() );
@@ -123,7 +137,7 @@ bool SSCLoader::LoadFromSSCFile( const RString &sPath, Song &out, bool bFromCach
return false;
}
out.m_Timing.m_sFile = sPath; // songs still have their fallback timing.
out.m_SongTiming.m_sFile = sPath; // songs still have their fallback timing.
int state = GETTING_SONG_INFO;
const unsigned values = msd.GetNumValues();
@@ -384,270 +398,47 @@ bool SSCLoader::LoadFromSSCFile( const RString &sPath, Song &out, bool bFromCach
else if( sValueName=="OFFSET" )
{
out.m_Timing.m_fBeat0OffsetInSeconds = StringToFloat( sParams[1] );
out.m_SongTiming.m_fBeat0OffsetInSeconds = StringToFloat( sParams[1] );
}
/* Below are the song based timings that should only be used
* if the steps do not have their own timing. */
else if( sValueName=="STOPS" )
{
vector<RString> arrayFreezeExpressions;
split( sParams[1], ",", arrayFreezeExpressions );
for( unsigned f=0; f<arrayFreezeExpressions.size(); f++ )
{
vector<RString> arrayFreezeValues;
split( arrayFreezeExpressions[f], "=", arrayFreezeValues );
if( arrayFreezeValues.size() != 2 )
{
// XXX: Hard to tell which file caused this.
LOG->UserLog( "Song file", "(UNKNOWN)", "has an invalid #%s value \"%s\" (must have exactly one '='), ignored.",
sValueName.c_str(), arrayFreezeExpressions[f].c_str() );
continue;
}
const float fFreezeBeat = StringToFloat( arrayFreezeValues[0] );
const float fFreezeSeconds = StringToFloat( arrayFreezeValues[1] );
StopSegment new_seg( BeatToNoteRow(fFreezeBeat), fFreezeSeconds );
if(fFreezeSeconds > 0.0f)
{
// LOG->Trace( "Adding a freeze segment: beat: %f, seconds = %f", new_seg.m_fStartBeat, new_seg.m_fStopSeconds );
out.m_Timing.AddStopSegment( new_seg );
}
else
{
// negative stops (hi JS!) -aj
if( PREFSMAN->m_bQuirksMode )
{
// LOG->Trace( "Adding a negative freeze segment: beat: %f, seconds = %f", new_seg.m_fStartBeat, new_seg.m_fStopSeconds );
out.m_Timing.AddStopSegment( new_seg );
}
else
LOG->UserLog( "Song file", "(UNKNOWN)", "has an invalid stop at beat %f, length %f.", fFreezeBeat, fFreezeSeconds );
}
}
SMLoader::ProcessStops(out.m_SongTiming, sParams[1]);
}
else if( sValueName=="DELAYS" )
{
vector<RString> arrayDelayExpressions;
split( sParams[1], ",", arrayDelayExpressions );
for( unsigned f=0; f<arrayDelayExpressions.size(); f++ )
{
vector<RString> arrayDelayValues;
split( arrayDelayExpressions[f], "=", arrayDelayValues );
if( arrayDelayValues.size() != 2 )
{
// XXX: Hard to tell which file caused this.
LOG->UserLog( "Song file", "(UNKNOWN)", "has an invalid #%s value \"%s\" (must have exactly one '='), ignored.",
sValueName.c_str(), arrayDelayExpressions[f].c_str() );
continue;
}
const float fFreezeBeat = StringToFloat( arrayDelayValues[0] );
const float fFreezeSeconds = StringToFloat( arrayDelayValues[1] );
StopSegment new_seg( BeatToNoteRow(fFreezeBeat), fFreezeSeconds, true );
// LOG->Trace( "Adding a delay segment: beat: %f, seconds = %f", new_seg.m_fStartBeat, new_seg.m_fStopSeconds );
if(fFreezeSeconds > 0.0f)
out.m_Timing.AddStopSegment( new_seg );
else
LOG->UserLog( "Song file", "(UNKNOWN)", "has an invalid delay at beat %f, length %f.", fFreezeBeat, fFreezeSeconds );
}
SMLoader::ProcessDelays(out.m_SongTiming, sParams[1]);
}
else if( sValueName=="BPMS" )
{
vector<RString> arrayBPMChangeExpressions;
split( sParams[1], ",", arrayBPMChangeExpressions );
for( unsigned b=0; b<arrayBPMChangeExpressions.size(); b++ )
{
vector<RString> arrayBPMChangeValues;
split( arrayBPMChangeExpressions[b], "=", arrayBPMChangeValues );
// XXX: Hard to tell which file caused this.
if( arrayBPMChangeValues.size() != 2 )
{
LOG->UserLog( "Song file", "(UNKNOWN)", "has an invalid #%s value \"%s\" (must have exactly one '='), ignored.",
sValueName.c_str(), arrayBPMChangeExpressions[b].c_str() );
continue;
}
const float fBeat = StringToFloat( arrayBPMChangeValues[0] );
const float fNewBPM = StringToFloat( arrayBPMChangeValues[1] );
if(fNewBPM > 0.0f)
out.m_Timing.AddBPMSegment( BPMSegment(BeatToNoteRow(fBeat), fNewBPM) );
else
{
out.m_Timing.m_bHasNegativeBpms = true;
// only add Negative BPMs in quirks mode -aj
if( PREFSMAN->m_bQuirksMode )
out.m_Timing.AddBPMSegment( BPMSegment(BeatToNoteRow(fBeat), fNewBPM) );
else
LOG->UserLog( "Song file", "(UNKNOWN)", "has an invalid BPM change at beat %f, BPM %f.", fBeat, fNewBPM );
}
}
SMLoader::ProcessBPMs(out.m_SongTiming, sParams[1]);
}
else if( sValueName=="WARPS" )
{
vector<RString> arrayWarpExpressions;
split( sParams[1], ",", arrayWarpExpressions );
for( unsigned b=0; b<arrayWarpExpressions.size(); b++ )
{
vector<RString> arrayWarpValues;
split( arrayWarpExpressions[b], "=", arrayWarpValues );
// XXX: Hard to tell which file caused this.
if( arrayWarpValues.size() != 2 )
{
LOG->UserLog( "Song file", "(UNKNOWN)", "has an invalid #%s value \"%s\" (must have exactly one '='), ignored.",
sValueName.c_str(), arrayWarpExpressions[b].c_str() );
continue;
}
const float fBeat = StringToFloat( arrayWarpValues[0] );
const float fNewBeat = StringToFloat( arrayWarpValues[1] );
if(fNewBeat > fBeat)
out.m_Timing.AddWarpSegment( WarpSegment(fBeat, fNewBeat) );
else
{
LOG->UserLog( "Song file", "(UNKNOWN)", "has an invalid Warp at beat %f, BPM %f.", fBeat, fNewBeat );
}
}
ProcessWarps( out.m_SongTiming, sParams[1] );
}
else if( sValueName=="LABELS" )
{
vector<RString> arrayLabelExpressions;
split( sParams[1], ",", arrayLabelExpressions );
for( unsigned b=0; b<arrayLabelExpressions.size(); b++ )
{
vector<RString> arrayLabelValues;
split( arrayLabelExpressions[b], "=", arrayLabelValues );
if( arrayLabelValues.size() != 2 )
{
LOG->UserLog( "Song file", "(UNKNOWN)", "has an invalid #%s value \"%s\" (must have exactly one '='), ignored.",
sValueName.c_str(), arrayLabelExpressions[b].c_str() );
continue;
}
const float fBeat = StringToFloat( arrayLabelValues[0] );
RString sLabel = arrayLabelValues[1];
TrimRight(sLabel);
if( fBeat >= 0.0f )
out.m_Timing.AddLabelSegment( LabelSegment(fBeat, sLabel) );
else
{
LOG->UserLog( "Song file", "(UNKNOWN)", "has an invalid Label at beat %f called %s.", fBeat, sLabel.c_str() );
}
}
ProcessLabels( out.m_SongTiming, sParams[1] );
}
else if( sValueName=="TIMESIGNATURES" )
{
vector<RString> vs1;
split( sParams[1], ",", vs1 );
FOREACH_CONST( RString, vs1, s1 )
{
vector<RString> vs2;
split( *s1, "=", vs2 );
if( vs2.size() < 3 )
{
LOG->UserLog( "Song file", "(UNKNOWN)", "has an invalid time signature change with %i values.", (int)vs2.size() );
continue;
}
const float fBeat = StringToFloat( vs2[0] );
TimeSignatureSegment seg;
seg.m_iStartRow = BeatToNoteRow(fBeat);
seg.m_iNumerator = atoi( vs2[1] );
seg.m_iDenominator = atoi( vs2[2] );
if( fBeat < 0 )
{
LOG->UserLog( "Song file", "(UNKNOWN)", "has an invalid time signature change with beat %f.", fBeat );
continue;
}
if( seg.m_iNumerator < 1 )
{
LOG->UserLog( "Song file", "(UNKNOWN)", "has an invalid time signature change with beat %f, iNumerator %i.", fBeat, seg.m_iNumerator );
continue;
}
if( seg.m_iDenominator < 1 )
{
LOG->UserLog( "Song file", "(UNKNOWN)", "has an invalid time signature change with beat %f, iDenominator %i.", fBeat, seg.m_iDenominator );
continue;
}
out.m_Timing.AddTimeSignatureSegment( seg );
}
SMLoader::ProcessTimeSignatures(out.m_SongTiming, sParams[1]);
}
else if( sValueName=="TICKCOUNTS" )
{
vector<RString> arrayTickcountExpressions;
split( sParams[1], ",", arrayTickcountExpressions );
for( unsigned f=0; f<arrayTickcountExpressions.size(); f++ )
{
vector<RString> arrayTickcountValues;
split( arrayTickcountExpressions[f], "=", arrayTickcountValues );
if( arrayTickcountValues.size() != 2 )
{
// XXX: Hard to tell which file caused this.
LOG->UserLog( "Song file", "(UNKNOWN)", "has an invalid #%s value \"%s\" (must have exactly one '='), ignored.",
sValueName.c_str(), arrayTickcountExpressions[f].c_str() );
continue;
}
const float fTickcountBeat = StringToFloat( arrayTickcountValues[0] );
const int iTicks = atoi( arrayTickcountValues[1] );
TickcountSegment new_seg( BeatToNoteRow(fTickcountBeat), iTicks );
if(iTicks >= 1 && iTicks <= ROWS_PER_BEAT ) // Constants
{
// LOG->Trace( "Adding a tickcount segment: beat: %f, ticks = %d", fTickcountBeat, iTicks );
out.m_Timing.AddTickcountSegment( new_seg );
}
else
{
LOG->UserLog( "Song file", "(UNKNOWN)", "has an invalid tickcount at beat %f, ticks %d.", fTickcountBeat, iTicks );
}
}
SMLoader::ProcessTickcounts(out.m_SongTiming, sParams[1]);
}
else if( sValueName=="COMBOS" )
{
vector<RString> arrayComboExpressions;
split( sParams[1], ",", arrayComboExpressions );
for( unsigned f=0; f<arrayComboExpressions.size(); f++ )
{
vector<RString> arrayComboValues;
split( arrayComboExpressions[f], "=", arrayComboValues );
if( arrayComboValues.size() != 2 )
{
LOG->UserLog( "Song file", "(UNKNOWN)", "has an invalid #%s value \"%s\" (must have exactly one '='), ignored.",
sValueName.c_str(), arrayComboExpressions[f].c_str() );
continue;
}
const float fComboBeat = StringToFloat( arrayComboValues[0] );
const int iCombos = atoi( arrayComboValues[1] );
ComboSegment new_seg( BeatToNoteRow( fComboBeat ), iCombos );
out.m_Timing.AddComboSegment( new_seg );
}
ProcessCombos( out.m_SongTiming, sParams[1] );
}
/* The following are cache tags. Never fill their values
@@ -756,41 +547,14 @@ bool SSCLoader::LoadFromSSCFile( const RString &sPath, Song &out, bool bFromCach
out.AddSteps( pNewNotes );
}
else if( sValueName=="BPMS" )
else if( sValueName=="BPMS" ) // This must ALWAYS be here in Split Timing.
{
/*
state = GETTING_STEP_TIMING_INFO;
vector<RString> arrayBPMChangeExpressions;
split( sParams[1], ",", arrayBPMChangeExpressions );
for( unsigned b=0; b<arrayBPMChangeExpressions.size(); b++ )
{
vector<RString> arrayBPMChangeValues;
split( arrayBPMChangeExpressions[b], "=", arrayBPMChangeValues );
// XXX: Hard to tell which file caused this.
if( arrayBPMChangeValues.size() != 2 )
{
LOG->UserLog( "Song file", "(UNKNOWN)", "has an invalid #%s value \"%s\" (must have exactly one '='), ignored.",
sValueName.c_str(), arrayBPMChangeExpressions[b].c_str() );
continue;
}
const float fBeat = StringToFloat( arrayBPMChangeValues[0] );
const float fNewBPM = StringToFloat( arrayBPMChangeValues[1] );
if(fNewBPM > 0.0f)
pNewNotes->m_Timing.AddBPMSegment( BPMSegment(BeatToNoteRow(fBeat), fNewBPM) );
else
{
pNewNotes->m_Timing.m_bHasNegativeBpms = true;
// only add Negative BPMs in quirks mode -aj
if( PREFSMAN->m_bQuirksMode )
pNewNotes->m_Timing.AddBPMSegment( BPMSegment(BeatToNoteRow(fBeat), fNewBPM) );
else
LOG->UserLog( "Song file", "(UNKNOWN)", "has an invalid BPM change at beat %f, BPM %f.", fBeat, fNewBPM );
}
}
*/
/*
pNewNotes->m_Timing = TimingData(out.m_SongTiming.m_fBeat0OffsetInSeconds);
SMLoader::ProcessBPMs(pNewNotes->m_Timing, sParams[1]);
*/
}
break;
}
@@ -798,28 +562,31 @@ bool SSCLoader::LoadFromSSCFile( const RString &sPath, Song &out, bool bFromCach
{
if( sValueName=="STOPS" )
{
// copy from above when it's time.
// SMLoader::ProcessStops(pNewNotes->m_Timing, sParams[1]);
}
else if( sValueName=="DELAYS" )
{
// copy from above when it's time.
// SMLoader::ProcessDelays(pNewNotes->m_Timing, sParams[1]);
}
else if( sValueName=="TIMESIGNATURES" )
{
// copy from above when it's time.
// SMLoader::ProcessTimeSignatures(pNewNotes->m_Timing, sParams[1]);
}
else if( sValueName=="TICKCOUNTS" )
{
// copy from above when it's time.
// SMLoader::ProcessTickcounts(pNewNotes->m_Timing, sParams[1]);
}
else if( sValueName=="COMBOS" )
{
// copy from above when it's time.
// ProcessCombos(pNewNotes->m_Timing, sParams[1]);
}
else if( sValueName=="WARPS" || sValueName=="LABELS" )
else if( sValueName=="WARPS" )
{
// copy from above when it's time.
// ProcessWarps(pNewNotes->m_Timing, sParams[1]);
}
else if( sValueName=="LABELS" )
{
// ProcessLabels(pNewNotes->m_Timing, sParams[1]);
}
else if( sValueName=="ATTACKS" )
{
@@ -874,10 +641,9 @@ bool SSCLoader::LoadFromSSCFile( const RString &sPath, Song &out, bool bFromCach
*/
}
else if( sValueName=="NOTES" )
else if( sValueName=="NOTES" || sValueName=="NOTES2" )
{
state = GETTING_SONG_INFO;
// pNewNotes->m_Timing.m_fBeat0OffsetInSeconds = out.m_Timing.m_fBeat0OffsetInSeconds;
pNewNotes->SetSMNoteData( sParams[1] );
pNewNotes->TidyUpData();
out.AddSteps( pNewNotes );
@@ -1095,55 +861,7 @@ bool SSCLoader::LoadEditFromMsd( const MsdFile &msd, const RString &sEditFilePat
void SSCLoader::TidyUpData( Song &song, bool bFromCache )
{
/*
* Hack: if the song has any changes at all (so it won't use a random BGA)
* and doesn't end with "-nosongbg-", add a song background BGC. Remove
* "-nosongbg-" if it exists.
*
* This way, songs that were created earlier, when we added the song BG
* at the end by default, will still behave as expected; all new songs will
* have to add an explicit song BG tag if they want it. This is really a
* formatting hack only; nothing outside of SMLoader ever sees "-nosongbg-".
*/
vector<BackgroundChange> &bg = song.GetBackgroundChanges(BACKGROUND_LAYER_1);
if( !bg.empty() )
{
/* BGChanges have been sorted. On the odd chance that a BGChange exists
* with a very high beat, search the whole list. */
bool bHasNoSongBgTag = false;
for( unsigned i = 0; !bHasNoSongBgTag && i < bg.size(); ++i )
{
if( !bg[i].m_def.m_sFile1.CompareNoCase(NO_SONG_BG_FILE) )
{
bg.erase( bg.begin()+i );
bHasNoSongBgTag = true;
}
}
// If there's no -nosongbg- tag, add the song BG.
if( !bHasNoSongBgTag ) do
{
/* If we're loading cache, -nosongbg- should always be in there. We
* must not call IsAFile(song.GetBackgroundPath()) when loading cache. */
if( bFromCache )
break;
/* If BGChanges already exist after the last beat, don't add the
* background in the middle. */
if( !bg.empty() && bg.back().m_fStartBeat-0.0001f >= song.m_fLastBeat )
break;
// If the last BGA is already the song BGA, don't add a duplicate.
if( !bg.empty() && !bg.back().m_def.m_sFile1.CompareNoCase(song.m_sBackgroundFile) )
break;
if( !IsAFile( song.GetBackgroundPath() ) )
break;
bg.push_back( BackgroundChange(song.m_fLastBeat,song.m_sBackgroundFile) );
} while(0);
}
SMLoader::TidyUpData(song, bFromCache);
}
/*
+7
View File
@@ -25,6 +25,8 @@ enum SSCLoadingStates
const float VERSION_RADAR_FAKE = 0.53f;
/** @brief The version where WarpSegments started to be utilized. */
const float VERSION_WARP_SEGMENT = 0.56f;
/** @brief The version that formally introduced Split Timing. */
const float VERSION_SPLIT_TIMING = 0.7f;
/**
* @brief The SSCLoader handles all of the parsing needed for .ssc files.
@@ -75,6 +77,11 @@ namespace SSCLoader
* @param bFromCache a flag to determine if this song is loaded from a cache file.
*/
void TidyUpData( Song &song, bool bFromCache );
void ProcessWarps( TimingData &, const RString );
void ProcessLabels( TimingData &, const RString );
void ProcessCombos( TimingData &, const RString );
}
#endif
/**
+27 -27
View File
@@ -74,7 +74,7 @@ static void WriteGlobalTags( RageFile &f, const Song &out )
f.PutLine( "#INSTRUMENTTRACK:" + s + ";\n" );
}
}
f.PutLine( ssprintf( "#OFFSET:%.6f;", out.m_Timing.m_fBeat0OffsetInSeconds ) );
f.PutLine( ssprintf( "#OFFSET:%.6f;", out.m_SongTiming.m_fBeat0OffsetInSeconds ) );
f.PutLine( ssprintf( "#SAMPLESTART:%.6f;", out.m_fMusicSampleStartSeconds ) );
f.PutLine( ssprintf( "#SAMPLELENGTH:%.6f;", out.m_fMusicSampleLengthSeconds ) );
if( out.m_fSpecifiedLastBeat > 0 )
@@ -107,39 +107,39 @@ static void WriteGlobalTags( RageFile &f, const Song &out )
}
f.Write( "#BPMS:" );
for( unsigned i=0; i<out.m_Timing.m_BPMSegments.size(); i++ )
for( unsigned i=0; i<out.m_SongTiming.m_BPMSegments.size(); i++ )
{
const BPMSegment &bs = out.m_Timing.m_BPMSegments[i];
const BPMSegment &bs = out.m_SongTiming.m_BPMSegments[i];
f.PutLine( ssprintf( "%.6f=%.6f", NoteRowToBeat(bs.m_iStartRow), bs.GetBPM() ) );
if( i != out.m_Timing.m_BPMSegments.size()-1 )
if( i != out.m_SongTiming.m_BPMSegments.size()-1 )
f.Write( "," );
}
f.PutLine( ";" );
f.Write( "#STOPS:" );
for( unsigned i=0; i<out.m_Timing.m_StopSegments.size(); i++ )
for( unsigned i=0; i<out.m_SongTiming.m_StopSegments.size(); i++ )
{
const StopSegment &fs = out.m_Timing.m_StopSegments[i];
const StopSegment &fs = out.m_SongTiming.m_StopSegments[i];
if(!fs.m_bDelay)
{
f.PutLine( ssprintf( "%.6f=%.6f", NoteRowToBeat(fs.m_iStartRow), fs.m_fStopSeconds ) );
if( i != out.m_Timing.m_StopSegments.size()-1 )
if( i != out.m_SongTiming.m_StopSegments.size()-1 )
f.Write( "," );
}
}
f.PutLine( ";" );
f.Write( "#DELAYS:" );
for( unsigned i=0; i<out.m_Timing.m_StopSegments.size(); i++ )
for( unsigned i=0; i<out.m_SongTiming.m_StopSegments.size(); i++ )
{
const StopSegment &fs = out.m_Timing.m_StopSegments[i];
const StopSegment &fs = out.m_SongTiming.m_StopSegments[i];
if( fs.m_bDelay )
{
f.PutLine( ssprintf( "%.6f=%.6f", NoteRowToBeat(fs.m_iStartRow), fs.m_fStopSeconds ) );
if( i != out.m_Timing.m_StopSegments.size()-1 )
if( i != out.m_SongTiming.m_StopSegments.size()-1 )
f.Write( "," );
}
}
@@ -147,61 +147,61 @@ static void WriteGlobalTags( RageFile &f, const Song &out )
f.Write( "#WARPS:" );
for( unsigned i=0; i<out.m_Timing.m_WarpSegments.size(); i++ )
for( unsigned i=0; i<out.m_SongTiming.m_WarpSegments.size(); i++ )
{
const WarpSegment &ws = out.m_Timing.m_WarpSegments[i];
const WarpSegment &ws = out.m_SongTiming.m_WarpSegments[i];
f.PutLine( ssprintf( "%.6f=%.6f", NoteRowToBeat(ws.m_iStartRow), ws.m_fEndBeat ) );
if( i != out.m_Timing.m_WarpSegments.size()-1 )
if( i != out.m_SongTiming.m_WarpSegments.size()-1 )
f.Write( "," );
}
f.PutLine( ";" );
ASSERT( !out.m_Timing.m_vTimeSignatureSegments.empty() );
ASSERT( !out.m_SongTiming.m_vTimeSignatureSegments.empty() );
f.Write( "#TIMESIGNATURES:" );
FOREACH_CONST( TimeSignatureSegment, out.m_Timing.m_vTimeSignatureSegments, iter )
FOREACH_CONST( TimeSignatureSegment, out.m_SongTiming.m_vTimeSignatureSegments, iter )
{
f.PutLine( ssprintf( "%.6f=%d=%d", NoteRowToBeat(iter->m_iStartRow), iter->m_iNumerator, iter->m_iDenominator ) );
vector<TimeSignatureSegment>::const_iterator iter2 = iter;
iter2++;
if( iter2 != out.m_Timing.m_vTimeSignatureSegments.end() )
if( iter2 != out.m_SongTiming.m_vTimeSignatureSegments.end() )
f.Write( "," );
}
f.PutLine( ";" );
ASSERT( !out.m_Timing.m_TickcountSegments.empty() );
ASSERT( !out.m_SongTiming.m_TickcountSegments.empty() );
f.Write( "#TICKCOUNTS:" );
for( unsigned i=0; i<out.m_Timing.m_TickcountSegments.size(); i++ )
for( unsigned i=0; i<out.m_SongTiming.m_TickcountSegments.size(); i++ )
{
const TickcountSegment &ts = out.m_Timing.m_TickcountSegments[i];
const TickcountSegment &ts = out.m_SongTiming.m_TickcountSegments[i];
f.PutLine( ssprintf( "%.6f=%d", NoteRowToBeat(ts.m_iStartRow), ts.m_iTicks ) );
if( i != out.m_Timing.m_TickcountSegments.size()-1 )
if( i != out.m_SongTiming.m_TickcountSegments.size()-1 )
f.Write( "," );
}
f.PutLine( ";" );
ASSERT( !out.m_Timing.m_ComboSegments.empty() );
ASSERT( !out.m_SongTiming.m_ComboSegments.empty() );
f.Write( "#COMBOS:" );
for( unsigned i=0; i<out.m_Timing.m_ComboSegments.size(); i++ )
for( unsigned i=0; i<out.m_SongTiming.m_ComboSegments.size(); i++ )
{
const ComboSegment &cs = out.m_Timing.m_ComboSegments[i];
const ComboSegment &cs = out.m_SongTiming.m_ComboSegments[i];
f.PutLine( ssprintf( "%.6f=%d", NoteRowToBeat(cs.m_iStartRow), cs.m_iCombo ) );
if( i != out.m_Timing.m_ComboSegments.size()-1 )
if( i != out.m_SongTiming.m_ComboSegments.size()-1 )
f.Write( "," );
}
f.PutLine( ";" );
f.Write( "#LABELS:" );
for( unsigned i=0; i<out.m_Timing.m_LabelSegments.size(); i++ )
for( unsigned i=0; i<out.m_SongTiming.m_LabelSegments.size(); i++ )
{
const LabelSegment &ls = out.m_Timing.m_LabelSegments[i];
const LabelSegment &ls = out.m_SongTiming.m_LabelSegments[i];
f.PutLine( ssprintf( "%.6f=%s", NoteRowToBeat(ls.m_iStartRow), ls.m_sLabel.c_str() ) );
if( i != out.m_Timing.m_LabelSegments.size()-1 )
if( i != out.m_SongTiming.m_LabelSegments.size()-1 )
f.Write( "," );
}
f.PutLine( ";" );
+14 -14
View File
@@ -1528,7 +1528,7 @@ int Player::GetClosestNoteDirectional( int col, int iStartRow, int iEndRow, bool
// Is this the row we want?
do {
const TapNote &tn = begin->second;
if( GAMESTATE->m_pCurSong->m_Timing.IsWarpAtRow( begin->first ) )
if( GAMESTATE->m_pCurSong->m_SongTiming.IsWarpAtRow( begin->first ) )
break;
if( tn.type == TapNote::empty )
break;
@@ -1579,7 +1579,7 @@ int Player::GetClosestNonEmptyRowDirectional( int iStartRow, int iEndRow, bool b
++iter;
continue;
}
if( GAMESTATE->m_pCurSong->m_Timing.IsWarpAtRow( iter.Row() ) )
if( GAMESTATE->m_pCurSong->m_SongTiming.IsWarpAtRow( iter.Row() ) )
{
++iter;
continue;
@@ -1873,7 +1873,7 @@ void Player::StepStrumHopo( int col, int row, const RageTimer &tm, bool bHeld, b
break;
}
const float fSongBeat = GAMESTATE->m_pCurSong ? GAMESTATE->m_pCurSong->GetBeatFromElapsedTime( fPositionSeconds ) : GAMESTATE->m_fSongBeat;
const float fSongBeat = GAMESTATE->m_pCurSong ? GAMESTATE->m_pCurSong->m_SongTiming.GetBeatFromElapsedTime( fPositionSeconds ) : GAMESTATE->m_fSongBeat;
const int iSongRow = row == -1 ? BeatToNoteRow( fSongBeat ) : row;
if( col != -1 && !bRelease )
@@ -2011,8 +2011,8 @@ void Player::StepStrumHopo( int col, int row, const RageTimer &tm, bool bHeld, b
* "jack hammers." Hmm.
*/
const int iStepSearchRows = max(
BeatToNoteRow( GAMESTATE->m_pCurSong->m_Timing.GetBeatFromElapsedTime( GAMESTATE->m_fMusicSeconds + StepSearchDistance ) ) - iSongRow,
iSongRow - BeatToNoteRow( GAMESTATE->m_pCurSong->m_Timing.GetBeatFromElapsedTime( GAMESTATE->m_fMusicSeconds - StepSearchDistance ) )
BeatToNoteRow( GAMESTATE->m_pCurSong->m_SongTiming.GetBeatFromElapsedTime( GAMESTATE->m_fMusicSeconds + StepSearchDistance ) ) - iSongRow,
iSongRow - BeatToNoteRow( GAMESTATE->m_pCurSong->m_SongTiming.GetBeatFromElapsedTime( GAMESTATE->m_fMusicSeconds - StepSearchDistance ) )
) + ROWS_PER_BEAT;
int iRowOfOverlappingNoteOrRow = row;
if( row == -1 )
@@ -2039,7 +2039,7 @@ void Player::StepStrumHopo( int col, int row, const RageTimer &tm, bool bHeld, b
float fNoteOffset = 0.0f;
// we need this later if we are autosyncing
const float fStepBeat = NoteRowToBeat( iRowOfOverlappingNoteOrRow );
const float fStepSeconds = GAMESTATE->m_pCurSong->GetElapsedTimeFromBeat(fStepBeat);
const float fStepSeconds = GAMESTATE->m_pCurSong->m_SongTiming.GetElapsedTimeFromBeat(fStepBeat);
if( row == -1 )
{
@@ -2089,7 +2089,7 @@ void Player::StepStrumHopo( int col, int row, const RageTimer &tm, bool bHeld, b
// Stepped too close to mine?
if( !bRelease && ( REQUIRE_STEP_ON_MINES == !bHeld ) &&
fSecondsFromExact <= GetWindowSeconds(TW_Mine) &&
!GAMESTATE->m_pCurSong->m_Timing.IsWarpAtRow(iSongRow) )
!GAMESTATE->m_pCurSong->m_SongTiming.IsWarpAtRow(iSongRow) )
score = TNS_HitMine;
break;
@@ -2564,7 +2564,7 @@ void Player::UpdateTapNotesMissedOlderThan( float fMissIfOlderThanSeconds )
float fThrowAway;
int iWarpBeginRow;
float fWarpLength;
GAMESTATE->m_pCurSong->m_Timing.GetBeatAndBPSFromElapsedTime( fEarliestTime, fMissIfOlderThanThisBeat, fThrowAway, bFreeze, bDelay, iWarpBeginRow, fWarpLength );
GAMESTATE->m_pCurSong->m_SongTiming.GetBeatAndBPSFromElapsedTime( fEarliestTime, fMissIfOlderThanThisBeat, fThrowAway, bFreeze, bDelay, iWarpBeginRow, fWarpLength );
iMissIfOlderThanThisRow = BeatToNoteRow( fMissIfOlderThanThisBeat );
if( bFreeze || bDelay )
@@ -2587,7 +2587,7 @@ void Player::UpdateTapNotesMissedOlderThan( float fMissIfOlderThanSeconds )
continue;
// Ignore all notes that are skipped via WARPS.
if( GAMESTATE->m_pCurSong->m_Timing.IsWarpAtRow( iter.Row() ) )
if( GAMESTATE->m_pCurSong->m_SongTiming.IsWarpAtRow( iter.Row() ) )
continue;
if( tn.type == TapNote::mine )
@@ -2622,7 +2622,7 @@ void Player::UpdateJudgedRows()
int iRow = iter.Row();
// If row is within a warp section, ignore it. -aj
if( GAMESTATE->m_pCurSong->m_Timing.IsWarpAtRow(iRow) )
if( GAMESTATE->m_pCurSong->m_SongTiming.IsWarpAtRow(iRow) )
continue;
if( iLastSeenRow != iRow )
@@ -2843,13 +2843,13 @@ void Player::CrossedRows( int iLastRowCrossed, const RageTimer &now )
int iCheckpointFrequencyRows = ROWS_PER_BEAT/2;
if( CHECKPOINTS_USE_TICKCOUNTS )
{
int tickCurrent = GAMESTATE->m_pCurSong->m_Timing.GetTickcountAtRow( iLastRowCrossed );
int tickCurrent = GAMESTATE->m_pCurSong->m_SongTiming.GetTickcountAtRow( iLastRowCrossed );
// There are some charts that don't want tickcounts involved at all.
iCheckpointFrequencyRows = (tickCurrent > 0 ? ROWS_PER_BEAT / tickCurrent : 0);
}
else if( CHECKPOINTS_USE_TIME_SIGNATURES )
{
TimeSignatureSegment tSignature = GAMESTATE->m_pCurSong->m_Timing.GetTimeSignatureSegmentAtBeat( NoteRowToBeat( iLastRowCrossed ) );
TimeSignatureSegment tSignature = GAMESTATE->m_pCurSong->m_SongTiming.GetTimeSignatureSegmentAtBeat( NoteRowToBeat( iLastRowCrossed ) );
// Most songs are in 4/4 time. The frequency for checking tick counts should reflect that.
iCheckpointFrequencyRows = ROWS_PER_BEAT * tSignature.m_iDenominator / (tSignature.m_iNumerator * 4);
@@ -2957,7 +2957,7 @@ void Player::HandleTapRowScore( unsigned row )
#endif
// Warp hackery. -aj
if( GAMESTATE->m_pCurSong->m_Timing.IsWarpAtRow( row ) )
if( GAMESTATE->m_pCurSong->m_SongTiming.IsWarpAtRow( row ) )
return;
if( GAMESTATE->m_bDemonstrationOrJukebox )
@@ -3061,7 +3061,7 @@ void Player::HandleHoldCheckpoint( int iRow, int iNumHoldsHeldThisRow, int iNumH
#endif
// More warp hackery. -aj
if( GAMESTATE->m_pCurSong->m_Timing.IsWarpAtRow( iRow ) )
if( GAMESTATE->m_pCurSong->m_SongTiming.IsWarpAtRow( iRow ) )
return;
// don't accumulate combo if AutoPlay is on.
+2 -2
View File
@@ -443,7 +443,7 @@ void ScoreKeeperNormal::HandleComboInternal( int iNumHitContinueCombo, int iNumH
if( iNumBreakCombo == 0 )
{
TimingData td = GAMESTATE->m_pCurSong->m_Timing;
TimingData td = GAMESTATE->m_pCurSong->m_SongTiming;
int multiplier = ( iRow == -1 ? 1 : td.GetComboSegmentAtRow( iRow ).m_iCombo );
m_pPlayerStageStats->m_iCurCombo += iNumHitContinueCombo * multiplier;
}
@@ -463,7 +463,7 @@ void ScoreKeeperNormal::HandleRowComboInternal( TapNoteScore tns, int iNumTapsIn
if ( tns >= m_MinScoreToContinueCombo )
{
m_pPlayerStageStats->m_iCurMissCombo = 0;
TimingData td = GAMESTATE->m_pCurSong->m_Timing;
TimingData td = GAMESTATE->m_pCurSong->m_SongTiming;
int multiplier = ( iRow == -1 ? 1 : td.GetComboSegmentAtRow( iRow ).m_iCombo );
m_pPlayerStageStats->m_iCurCombo += iNumTapsInRow * multiplier;
}
+76 -76
View File
@@ -913,7 +913,7 @@ void ScreenEdit::Update( float fDeltaTime )
{
RageTimer tm;
const float fSeconds = m_pSoundMusic->GetPositionSeconds( NULL, &tm );
GAMESTATE->UpdateSongPosition( fSeconds, GAMESTATE->m_pCurSong->m_Timing, tm );
GAMESTATE->UpdateSongPosition( fSeconds, GAMESTATE->m_pCurSong->m_SongTiming, tm );
}
if( m_EditState == STATE_RECORDING )
@@ -931,7 +931,7 @@ void ScreenEdit::Update( float fDeltaTime )
continue;
float fStartedHoldingSeconds = m_pSoundMusic->GetPositionSeconds() - fSecsHeld;
float fStartBeat = max( fStartPlayingAtBeat, m_pSong->GetBeatFromElapsedTime(fStartedHoldingSeconds) );
float fStartBeat = max( fStartPlayingAtBeat, m_pSong->m_SongTiming.GetBeatFromElapsedTime(fStartedHoldingSeconds) );
float fEndBeat = max( fStartBeat, GAMESTATE->m_fSongBeat );
fEndBeat = min( fEndBeat, NoteRowToBeat(m_iStopPlayingAt) );
@@ -976,11 +976,11 @@ void ScreenEdit::Update( float fDeltaTime )
float fLastBeat = NoteRowToBeat(m_iStopPlayingAt);
if( bButtonIsBeingPressed && m_EditState == STATE_RECORDING )
{
float fSeconds = m_pSong->m_Timing.GetElapsedTimeFromBeat( fLastBeat );
fLastBeat = m_pSong->m_Timing.GetBeatFromElapsedTime( fSeconds + 0.5f );
float fSeconds = m_pSong->m_SongTiming.GetElapsedTimeFromBeat( fLastBeat );
fLastBeat = m_pSong->m_SongTiming.GetBeatFromElapsedTime( fSeconds + 0.5f );
}
float fStopAtSeconds = m_pSong->m_Timing.GetElapsedTimeFromBeat( NoteRowToBeat(m_iStopPlayingAt) ) + 1;
float fStopAtSeconds = m_pSong->m_SongTiming.GetElapsedTimeFromBeat( NoteRowToBeat(m_iStopPlayingAt) ) + 1;
if( GAMESTATE->m_fMusicSeconds > fStopAtSeconds )
{
// loop
@@ -1071,7 +1071,7 @@ void ScreenEdit::UpdateTextInfo()
RString sText;
sText += ssprintf( CURRENT_BEAT_FORMAT.GetValue(), CURRENT_BEAT.GetValue().c_str(), GAMESTATE->m_fSongBeat );
sText += ssprintf( CURRENT_SECOND_FORMAT.GetValue(), CURRENT_SECOND.GetValue().c_str(), m_pSong->GetElapsedTimeFromBeat(GAMESTATE->m_fSongBeat) );
sText += ssprintf( CURRENT_SECOND_FORMAT.GetValue(), CURRENT_SECOND.GetValue().c_str(), m_pSong->m_SongTiming.GetElapsedTimeFromBeat(GAMESTATE->m_fSongBeat) );
switch( EDIT_MODE.GetValue() )
{
DEFAULT_FAIL( EDIT_MODE.GetValue() );
@@ -1129,7 +1129,7 @@ void ScreenEdit::UpdateTextInfo()
case EditMode_Home:
break;
case EditMode_Full:
sText += ssprintf( BEAT_0_OFFSET_FORMAT.GetValue(), BEAT_0_OFFSET.GetValue().c_str(), m_pSong->m_Timing.m_fBeat0OffsetInSeconds );
sText += ssprintf( BEAT_0_OFFSET_FORMAT.GetValue(), BEAT_0_OFFSET.GetValue().c_str(), m_pSong->m_SongTiming.m_fBeat0OffsetInSeconds );
sText += ssprintf( PREVIEW_START_FORMAT.GetValue(), PREVIEW_START.GetValue().c_str(), m_pSong->m_fMusicSampleStartSeconds );
sText += ssprintf( PREVIEW_LENGTH_FORMAT.GetValue(), PREVIEW_LENGTH.GetValue().c_str(), m_pSong->m_fMusicSampleLengthSeconds );
break;
@@ -1243,7 +1243,7 @@ void ScreenEdit::InputEdit( const InputEventPlus &input, EditButton EditB )
m_iShiftAnchor = -1;
return;
}
int beatsPerMeasure = GAMESTATE->m_pCurSong->m_Timing.GetTimeSignatureSegmentAtBeat( GAMESTATE->m_fSongBeat ).m_iNumerator;
int beatsPerMeasure = GAMESTATE->m_pCurSong->m_SongTiming.GetTimeSignatureSegmentAtBeat( GAMESTATE->m_fSongBeat ).m_iNumerator;
switch( EditB )
{
@@ -1443,13 +1443,13 @@ void ScreenEdit::InputEdit( const InputEventPlus &input, EditButton EditB )
break;
case EDIT_BUTTON_LABEL_NEXT:
{
ScrollTo( GAMESTATE->m_pCurSong->m_Timing.
ScrollTo( GAMESTATE->m_pCurSong->m_SongTiming.
GetNextLabelSegmentBeatAtBeat( GAMESTATE->m_fSongBeat ) );
}
break;
case EDIT_BUTTON_LABEL_PREV:
{
ScrollTo( GAMESTATE->m_pCurSong->m_Timing.
ScrollTo( GAMESTATE->m_pCurSong->m_SongTiming.
GetPreviousLabelSegmentBeatAtBeat( GAMESTATE->m_fSongBeat ) );
}
break;
@@ -1579,7 +1579,7 @@ void ScreenEdit::InputEdit( const InputEventPlus &input, EditButton EditB )
case EDIT_BUTTON_BPM_UP:
case EDIT_BUTTON_BPM_DOWN:
{
float fBPM = m_pSong->GetBPMAtBeat( GAMESTATE->m_fSongBeat );
float fBPM = m_pSong->m_SongTiming.GetBPMAtBeat( GAMESTATE->m_fSongBeat );
float fDelta;
switch( EditB )
{
@@ -1600,7 +1600,7 @@ void ScreenEdit::InputEdit( const InputEventPlus &input, EditButton EditB )
}
float fNewBPM = fBPM + fDelta;
m_pSong->SetBPMAtBeat( GAMESTATE->m_fSongBeat, fNewBPM );
m_pSong->m_SongTiming.SetBPMAtBeat( GAMESTATE->m_fSongBeat, fNewBPM );
(fDelta>0 ? m_soundValueIncrease : m_soundValueDecrease).Play();
SetDirty( true );
}
@@ -1627,24 +1627,24 @@ void ScreenEdit::InputEdit( const InputEventPlus &input, EditButton EditB )
fDelta *= 40;
}
unsigned i;
for( i=0; i<m_pSong->m_Timing.m_StopSegments.size(); i++ )
for( i=0; i<m_pSong->m_SongTiming.m_StopSegments.size(); i++ )
{
if( m_pSong->m_Timing.m_StopSegments[i].m_iStartRow == BeatToNoteRow(GAMESTATE->m_fSongBeat) )
if( m_pSong->m_SongTiming.m_StopSegments[i].m_iStartRow == BeatToNoteRow(GAMESTATE->m_fSongBeat) )
break;
}
if( i == m_pSong->m_Timing.m_StopSegments.size() ) // there is no StopSegment at the current beat
if( i == m_pSong->m_SongTiming.m_StopSegments.size() ) // there is no StopSegment at the current beat
{
// create a new StopSegment
if( fDelta > 0 )
m_pSong->AddStopSegment( StopSegment(BeatToNoteRow(GAMESTATE->m_fSongBeat), fDelta) );
m_pSong->m_SongTiming.AddStopSegment( StopSegment(BeatToNoteRow(GAMESTATE->m_fSongBeat), fDelta) );
}
else // StopSegment being modified is m_Timing.m_StopSegments[i]
else // StopSegment being modified is m_SongTiming.m_StopSegments[i]
{
m_pSong->m_Timing.m_StopSegments[i].m_fStopSeconds += fDelta;
if( m_pSong->m_Timing.m_StopSegments[i].m_fStopSeconds <= 0 )
m_pSong->m_Timing.m_StopSegments.erase( m_pSong->m_Timing.m_StopSegments.begin()+i,
m_pSong->m_Timing.m_StopSegments.begin()+i+1);
m_pSong->m_SongTiming.m_StopSegments[i].m_fStopSeconds += fDelta;
if( m_pSong->m_SongTiming.m_StopSegments[i].m_fStopSeconds <= 0 )
m_pSong->m_SongTiming.m_StopSegments.erase( m_pSong->m_SongTiming.m_StopSegments.begin()+i,
m_pSong->m_SongTiming.m_StopSegments.begin()+i+1);
}
(fDelta>0 ? m_soundValueIncrease : m_soundValueDecrease).Play();
SetDirty( true );
@@ -1673,24 +1673,24 @@ void ScreenEdit::InputEdit( const InputEventPlus &input, EditButton EditB )
fDelta *= 40;
}
unsigned i;
for( i=0; i<m_pSong->m_Timing.m_StopSegments.size(); i++ )
for( i=0; i<m_pSong->m_SongTiming.m_StopSegments.size(); i++ )
{
if( m_pSong->m_Timing.m_StopSegments[i].m_iStartRow == BeatToNoteRow(GAMESTATE->m_fSongBeat) )
if( m_pSong->m_SongTiming.m_StopSegments[i].m_iStartRow == BeatToNoteRow(GAMESTATE->m_fSongBeat) )
break;
}
if( i == m_pSong->m_Timing.m_StopSegments.size() ) // there is no delay segment at the current beat
if( i == m_pSong->m_SongTiming.m_StopSegments.size() ) // there is no delay segment at the current beat
{
// create a new delay segment
if( fDelta > 0 )
m_pSong->AddStopSegment( StopSegment(BeatToNoteRow(GAMESTATE->m_fSongBeat), fDelta, true) );
}
else // delay segment being modified is m_Timing.m_StopSegments[i]
else // delay segment being modified is m_SongTiming.m_StopSegments[i]
{
m_pSong->m_Timing.m_StopSegments[i].m_fStopSeconds += fDelta;
if( m_pSong->m_Timing.m_StopSegments[i].m_fStopSeconds <= 0 )
m_pSong->m_Timing.m_StopSegments.erase( m_pSong->m_Timing.m_StopSegments.begin()+i,
m_pSong->m_Timing.m_StopSegments.begin()+i+1);
m_pSong->m_SongTiming.m_StopSegments[i].m_fStopSeconds += fDelta;
if( m_pSong->m_SongTiming.m_StopSegments[i].m_fStopSeconds <= 0 )
m_pSong->m_SongTiming.m_StopSegments.erase( m_pSong->m_SongTiming.m_StopSegments.begin()+i,
m_pSong->m_SongTiming.m_StopSegments.begin()+i+1);
}
(fDelta>0 ? m_soundValueIncrease : m_soundValueDecrease).Play();
SetDirty( true );
@@ -1718,7 +1718,7 @@ void ScreenEdit::InputEdit( const InputEventPlus &input, EditButton EditB )
else
fDelta *= 40;
}
m_pSong->m_Timing.m_fBeat0OffsetInSeconds += fDelta;
m_pSong->m_SongTiming.m_fBeat0OffsetInSeconds += fDelta;
(fDelta>0 ? m_soundValueIncrease : m_soundValueDecrease).Play();
SetDirty( true );
}
@@ -1900,7 +1900,7 @@ void ScreenEdit::InputEdit( const InputEventPlus &input, EditButton EditB )
if( pCourse == NULL )
break;
CourseEntry &ce = pCourse->m_vEntries[GAMESTATE->m_iEditCourseEntryIndex];
float fStartTime = m_pSong->GetElapsedTimeFromBeat( GAMESTATE->m_fSongBeat );
float fStartTime = m_pSong->m_SongTiming.GetElapsedTimeFromBeat( GAMESTATE->m_fSongBeat );
int iAttack = FindAttackAtTime( ce.attacks, fStartTime );
if( iAttack >= 0 )
@@ -1941,7 +1941,7 @@ void ScreenEdit::InputEdit( const InputEventPlus &input, EditButton EditB )
}
else
{
fStart = m_pSong->GetElapsedTimeFromBeat( NoteRowToBeat(m_NoteFieldEdit.m_iBeginMarker) );
fStart = m_pSong->m_SongTiming.GetElapsedTimeFromBeat( NoteRowToBeat(m_NoteFieldEdit.m_iBeginMarker) );
int iAttack = FindAttackAtTime( ce.attacks, fStart );
if( iAttack >= 0 )
@@ -1950,7 +1950,7 @@ void ScreenEdit::InputEdit( const InputEventPlus &input, EditButton EditB )
if( m_NoteFieldEdit.m_iEndMarker == -1 )
fEnd = m_pSong->m_fMusicLengthSeconds;
else
fEnd = m_pSong->GetElapsedTimeFromBeat( NoteRowToBeat(m_NoteFieldEdit.m_iEndMarker) );
fEnd = m_pSong->m_SongTiming.GetElapsedTimeFromBeat( NoteRowToBeat(m_NoteFieldEdit.m_iEndMarker) );
}
g_fLastInsertAttackPositionSeconds = fStart;
g_fLastInsertAttackDurationSeconds = fEnd - fStart;
@@ -2265,7 +2265,7 @@ void ScreenEdit::InputPlay( const InputEventPlus &input, EditButton EditB )
fOffsetDelta *= 40;
}
m_pSong->m_Timing.m_fBeat0OffsetInSeconds += fOffsetDelta;
m_pSong->m_SongTiming.m_fBeat0OffsetInSeconds += fOffsetDelta;
}
break;
}
@@ -2381,8 +2381,8 @@ void ScreenEdit::TransitionEditState( EditState em )
AdjustSync::ResetOriginalSyncData();
/* Give a 1 second lead-in. If we're loading Player, this must be done first. */
float fSeconds = m_pSong->m_Timing.GetElapsedTimeFromBeat( NoteRowToBeat(m_iStartPlayingAt) ) - 1;
GAMESTATE->UpdateSongPosition( fSeconds, m_pSong->m_Timing );
float fSeconds = m_pSong->m_SongTiming.GetElapsedTimeFromBeat( NoteRowToBeat(m_iStartPlayingAt) ) - 1;
GAMESTATE->UpdateSongPosition( fSeconds, m_pSong->m_SongTiming );
GAMESTATE->m_bGameplayLeadIn.Set( false );
@@ -2463,7 +2463,7 @@ void ScreenEdit::TransitionEditState( EditState em )
{
case STATE_PLAYING:
case STATE_RECORDING:
const float fStartSeconds = m_pSong->GetElapsedTimeFromBeat(GAMESTATE->m_fSongBeat);
const float fStartSeconds = m_pSong->m_SongTiming.GetElapsedTimeFromBeat(GAMESTATE->m_fSongBeat);
LOG->Trace( "Starting playback at %f", fStartSeconds );
RageSoundParams p;
@@ -2627,21 +2627,21 @@ void ScreenEdit::HandleScreenMessage( const ScreenMessage SM )
{
float fBPM = StringToFloat( ScreenTextEntry::s_sLastAnswer );
if( fBPM > 0 )
m_pSong->SetBPMAtBeat( GAMESTATE->m_fSongBeat, fBPM );
m_pSong->m_SongTiming.SetBPMAtBeat( GAMESTATE->m_fSongBeat, fBPM );
SetDirty( true );
}
else if( SM == SM_BackFromStopChange )
{
float fStop = StringToFloat( ScreenTextEntry::s_sLastAnswer );
if( fStop >= 0 )
m_pSong->m_Timing.SetStopAtBeat( GAMESTATE->m_fSongBeat, fStop );
m_pSong->m_SongTiming.SetStopAtBeat( GAMESTATE->m_fSongBeat, fStop );
SetDirty( true );
}
else if( SM == SM_BackFromDelayChange )
{
float fDelay = StringToFloat( ScreenTextEntry::s_sLastAnswer );
if( fDelay >= 0 )
m_pSong->m_Timing.SetStopAtBeat( GAMESTATE->m_fSongBeat, fDelay, true );
m_pSong->m_SongTiming.SetStopAtBeat( GAMESTATE->m_fSongBeat, fDelay, true );
SetDirty( true );
}
else if( SM == SM_BackFromTimeSignatureNumeratorChange )
@@ -2649,7 +2649,7 @@ void ScreenEdit::HandleScreenMessage( const ScreenMessage SM )
int iNum = atoi( ScreenTextEntry::s_sLastAnswer );
if( iNum > 0 )
{
m_pSong->m_Timing.SetTimeSignatureNumeratorAtBeat( GAMESTATE->m_fSongBeat, iNum );
m_pSong->m_SongTiming.SetTimeSignatureNumeratorAtBeat( GAMESTATE->m_fSongBeat, iNum );
}
SetDirty( true );
}
@@ -2658,7 +2658,7 @@ void ScreenEdit::HandleScreenMessage( const ScreenMessage SM )
int iDen = atoi( ScreenTextEntry::s_sLastAnswer );
if( iDen > 0)
{
m_pSong->m_Timing.SetTimeSignatureDenominatorAtBeat( GAMESTATE->m_fSongBeat, iDen );
m_pSong->m_SongTiming.SetTimeSignatureDenominatorAtBeat( GAMESTATE->m_fSongBeat, iDen );
}
SetDirty( true );
}
@@ -2667,7 +2667,7 @@ void ScreenEdit::HandleScreenMessage( const ScreenMessage SM )
int iTick = atoi( ScreenTextEntry::s_sLastAnswer );
if ( iTick >= 0 && iTick <= ROWS_PER_BEAT )
{
m_pSong->m_Timing.SetTickcountAtBeat( GAMESTATE->m_fSongBeat, iTick );
m_pSong->m_SongTiming.SetTickcountAtBeat( GAMESTATE->m_fSongBeat, iTick );
}
SetDirty( true );
}
@@ -2676,25 +2676,25 @@ void ScreenEdit::HandleScreenMessage( const ScreenMessage SM )
int iCombo = atoi( ScreenTextEntry::s_sLastAnswer );
if ( iCombo >= 0 )
{
m_pSong->m_Timing.SetComboAtBeat( GAMESTATE->m_fSongBeat, iCombo );
m_pSong->m_SongTiming.SetComboAtBeat( GAMESTATE->m_fSongBeat, iCombo );
}
SetDirty( true );
}
else if ( SM == SM_BackFromLabelChange )
{
RString sLabel = ScreenTextEntry::s_sLastAnswer;
if ( !m_pSong->m_Timing.DoesLabelExist(sLabel) )
if ( !m_pSong->m_SongTiming.DoesLabelExist(sLabel) )
{
sLabel.Replace("=", "_");
sLabel.Replace(",", "_");
m_pSong->m_Timing.SetLabelAtBeat( GAMESTATE->m_fSongBeat, sLabel );
m_pSong->m_SongTiming.SetLabelAtBeat( GAMESTATE->m_fSongBeat, sLabel );
SetDirty( true );
}
}
else if ( SM == SM_BackFromWarpChange )
{
float fWarp = StringToFloat( ScreenTextEntry::s_sLastAnswer );
m_pSong->m_Timing.SetWarpAtBeat( GAMESTATE->m_fSongBeat, fWarp );
m_pSong->m_SongTiming.SetWarpAtBeat( GAMESTATE->m_fSongBeat, fWarp );
SetDirty( true );
}
else if( SM == SM_BackFromBGChange )
@@ -2767,7 +2767,7 @@ void ScreenEdit::HandleScreenMessage( const ScreenMessage SM )
CourseEntry &ce = pCourse->m_vEntries[GAMESTATE->m_iEditCourseEntryIndex];
int iAttack;
g_fLastInsertAttackPositionSeconds = m_pSong->GetElapsedTimeFromBeat( GAMESTATE->m_fSongBeat );
g_fLastInsertAttackPositionSeconds = m_pSong->m_SongTiming.GetElapsedTimeFromBeat( GAMESTATE->m_fSongBeat );
g_fLastInsertAttackDurationSeconds = StringToFloat( g_InsertCourseAttack.rows[0].choices[iDurationChoice] );
iAttack = FindAttackAtTime( ce.attacks, g_fLastInsertAttackPositionSeconds );
@@ -3024,7 +3024,7 @@ static void ChangeArtistTranslit( const RString &sNew )
static void ChangeBeat0Offset( const RString &sNew )
{
GAMESTATE->m_pCurSong->m_Timing.m_fBeat0OffsetInSeconds = StringToFloat( sNew );
GAMESTATE->m_pCurSong->m_SongTiming.m_fBeat0OffsetInSeconds = StringToFloat( sNew );
}
static void ChangeLastBeatHint( const RString &sNew )
@@ -3135,7 +3135,7 @@ void ScreenEdit::HandleMainMenuChoice( MainMenuChoice c, const vector<int> &iAns
}
g_StepsInformation.rows[difficulty].iDefaultChoice = pSteps->GetDifficulty();
g_StepsInformation.rows[difficulty].bEnabled = (EDIT_MODE.GetValue() >= EditMode_Full);
g_StepsInformation.rows[meter].SetOneUnthemedChoice( ssprintf("%d", pSteps->GetMeter()-1) );
g_StepsInformation.rows[meter].SetOneUnthemedChoice( ssprintf("%d", pSteps->GetMeter()) );
g_StepsInformation.rows[meter].bEnabled = (EDIT_MODE.GetValue() >= EditMode_Home);
g_StepsInformation.rows[predict_meter].SetOneUnthemedChoice( ssprintf("%.2f",pSteps->PredictMeter()) );
g_StepsInformation.rows[description].bEnabled = (EDIT_MODE.GetValue() >= EditMode_Full);
@@ -3242,7 +3242,7 @@ void ScreenEdit::HandleMainMenuChoice( MainMenuChoice c, const vector<int> &iAns
g_SongInformation.rows[main_title_transliteration].SetOneUnthemedChoice( pSong->m_sMainTitleTranslit );
g_SongInformation.rows[sub_title_transliteration].SetOneUnthemedChoice( pSong->m_sSubTitleTranslit );
g_SongInformation.rows[artist_transliteration].SetOneUnthemedChoice( pSong->m_sArtistTranslit );
g_SongInformation.rows[beat_0_offset].SetOneUnthemedChoice( ssprintf("%.5f", pSong->m_Timing.m_fBeat0OffsetInSeconds) );
g_SongInformation.rows[beat_0_offset].SetOneUnthemedChoice( ssprintf("%.5f", pSong->m_SongTiming.m_fBeat0OffsetInSeconds) );
g_SongInformation.rows[last_beat_hint].SetOneUnthemedChoice( ssprintf("%.5f", pSong->m_fSpecifiedLastBeat) );
g_SongInformation.rows[preview_start].SetOneUnthemedChoice( ssprintf("%.5f", pSong->m_fMusicSampleStartSeconds) );
g_SongInformation.rows[preview_length].SetOneUnthemedChoice( ssprintf("%.5f", pSong->m_fMusicSampleLengthSeconds) );
@@ -3256,9 +3256,9 @@ void ScreenEdit::HandleMainMenuChoice( MainMenuChoice c, const vector<int> &iAns
case edit_timing_data:
{
const Song* pSong = GAMESTATE->m_pCurSong;
TimingData pTime = pSong->m_Timing;
TimingData pTime = pSong->m_SongTiming;
const float fBeat = GAMESTATE->m_fSongBeat;
g_TimingDataInformation.rows[bpm].SetOneUnthemedChoice( ssprintf("%.5f", pSong->GetBPMAtBeat( fBeat ) ) );
g_TimingDataInformation.rows[bpm].SetOneUnthemedChoice( ssprintf("%.5f", pTime.GetBPMAtBeat( fBeat ) ) );
g_TimingDataInformation.rows[stop].SetOneUnthemedChoice( ssprintf("%.5f", pTime.GetStopAtBeat( fBeat ) ) ) ;
g_TimingDataInformation.rows[delay].SetOneUnthemedChoice( ssprintf("%.5f", pTime.GetDelayAtBeat( fBeat ) ) );
g_TimingDataInformation.rows[time_signature_numerator].SetOneUnthemedChoice( ssprintf("%d", pTime.GetTimeSignatureNumeratorAtBeat( fBeat ) ) );
@@ -3501,7 +3501,7 @@ void ScreenEdit::HandleAreaMenuChoice( AreaMenuChoice c, const vector<int> &iAns
NoteDataUtil::ScaleRegion( m_NoteDataEdit, fScale, iStartIndex, iEndIndex );
// scale timing data
m_pSong->m_Timing.ScaleRegion( fScale, m_NoteFieldEdit.m_iBeginMarker, m_NoteFieldEdit.m_iEndMarker, true );
m_pSong->m_SongTiming.ScaleRegion( fScale, m_NoteFieldEdit.m_iBeginMarker, m_NoteFieldEdit.m_iEndMarker, true );
// scale all other steps.
const vector<Steps*> sIter = m_pSong->GetAllSteps();
@@ -3546,16 +3546,16 @@ void ScreenEdit::HandleAreaMenuChoice( AreaMenuChoice c, const vector<int> &iAns
NoteDataUtil::DeleteRows( m_NoteDataEdit, BeatToNoteRow(GAMESTATE->m_fSongBeat), BeatToNoteRow(1) );
break;
case shift_pauses_forward:
m_pSong->m_Timing.InsertRows( BeatToNoteRow(GAMESTATE->m_fSongBeat), BeatToNoteRow(1) );
m_pSong->m_SongTiming.InsertRows( BeatToNoteRow(GAMESTATE->m_fSongBeat), BeatToNoteRow(1) );
break;
case shift_pauses_backward:
m_pSong->m_Timing.DeleteRows( BeatToNoteRow(GAMESTATE->m_fSongBeat), BeatToNoteRow(1) );
m_pSong->m_SongTiming.DeleteRows( BeatToNoteRow(GAMESTATE->m_fSongBeat), BeatToNoteRow(1) );
break;
case convert_to_pause:
{
ASSERT( m_NoteFieldEdit.m_iBeginMarker!=-1 && m_NoteFieldEdit.m_iEndMarker!=-1 );
float fMarkerStart = m_pSong->m_Timing.GetElapsedTimeFromBeat( NoteRowToBeat(m_NoteFieldEdit.m_iBeginMarker) );
float fMarkerEnd = m_pSong->m_Timing.GetElapsedTimeFromBeat( NoteRowToBeat(m_NoteFieldEdit.m_iEndMarker) );
float fMarkerStart = m_pSong->m_SongTiming.GetElapsedTimeFromBeat( NoteRowToBeat(m_NoteFieldEdit.m_iBeginMarker) );
float fMarkerEnd = m_pSong->m_SongTiming.GetElapsedTimeFromBeat( NoteRowToBeat(m_NoteFieldEdit.m_iEndMarker) );
// The length of the stop segment we're going to create. This includes time spent in any
// stops in the selection, which will be deleted and subsumed into the new stop.
@@ -3567,9 +3567,9 @@ void ScreenEdit::HandleAreaMenuChoice( AreaMenuChoice c, const vector<int> &iAns
m_NoteFieldEdit.m_iBeginMarker + 1,
m_NoteFieldEdit.m_iEndMarker-m_NoteFieldEdit.m_iBeginMarker
);
m_pSong->m_Timing.DeleteRows( m_NoteFieldEdit.m_iBeginMarker,
m_pSong->m_SongTiming.DeleteRows( m_NoteFieldEdit.m_iBeginMarker,
m_NoteFieldEdit.m_iEndMarker-m_NoteFieldEdit.m_iBeginMarker );
m_pSong->m_Timing.SetStopAtRow( m_NoteFieldEdit.m_iBeginMarker, fStopLength );
m_pSong->m_SongTiming.SetStopAtRow( m_NoteFieldEdit.m_iBeginMarker, fStopLength );
m_NoteFieldEdit.m_iBeginMarker = -1;
m_NoteFieldEdit.m_iEndMarker = -1;
break;
@@ -3577,14 +3577,14 @@ void ScreenEdit::HandleAreaMenuChoice( AreaMenuChoice c, const vector<int> &iAns
case convert_pause_to_beat:
{
// TODO: Convert both Delays and Stops at once.
float fStopSeconds = m_pSong->m_Timing.GetStopAtRow( BeatToNoteRow(GAMESTATE->m_fSongBeat) );
m_pSong->m_Timing.SetStopAtBeat( GAMESTATE->m_fSongBeat, 0 );
float fStopSeconds = m_pSong->m_SongTiming.GetStopAtRow( BeatToNoteRow(GAMESTATE->m_fSongBeat) );
m_pSong->m_SongTiming.SetStopAtBeat( GAMESTATE->m_fSongBeat, 0 );
float fStopBeats = fStopSeconds * m_pSong->GetBPMAtBeat(GAMESTATE->m_fSongBeat) / 60;
float fStopBeats = fStopSeconds * m_pSong->m_SongTiming.GetBPMAtBeat(GAMESTATE->m_fSongBeat) / 60;
// don't move the step from where it is, just move everything later
NoteDataUtil::InsertRows( m_NoteDataEdit, BeatToNoteRow(GAMESTATE->m_fSongBeat) + 1, BeatToNoteRow(fStopBeats) );
m_pSong->m_Timing.InsertRows( BeatToNoteRow(GAMESTATE->m_fSongBeat) + 1, BeatToNoteRow(fStopBeats) );
m_pSong->m_SongTiming.InsertRows( BeatToNoteRow(GAMESTATE->m_fSongBeat) + 1, BeatToNoteRow(fStopBeats) );
}
break;
case undo:
@@ -3701,7 +3701,7 @@ void ScreenEdit::HandleSongInformationChoice( SongInformationChoice c, const vec
break;
case beat_0_offset:
ScreenTextEntry::TextEntry( SM_None, ENTER_BEAT_0_OFFSET,
ssprintf("%.5f", pSong->m_Timing.m_fBeat0OffsetInSeconds), 20,
ssprintf("%.5f", pSong->m_SongTiming.m_fBeat0OffsetInSeconds), 20,
ScreenTextEntry::FloatValidate, ChangeBeat0Offset, NULL );
break;
case last_beat_hint:
@@ -3750,7 +3750,7 @@ void ScreenEdit::HandleTimingDataInformationChoice( TimingDataInformationChoice
ScreenTextEntry::TextEntry(
SM_BackFromBPMChange,
ENTER_BPM_VALUE,
ssprintf( "%.4f", m_pSong->GetBPMAtBeat(GAMESTATE->m_fSongBeat) ),
ssprintf( "%.4f", m_pSong->m_SongTiming.GetBPMAtBeat(GAMESTATE->m_fSongBeat) ),
10
);
break;
@@ -3758,7 +3758,7 @@ void ScreenEdit::HandleTimingDataInformationChoice( TimingDataInformationChoice
ScreenTextEntry::TextEntry(
SM_BackFromStopChange,
ENTER_STOP_VALUE,
ssprintf( "%.4f", m_pSong->m_Timing.GetStopAtRow( BeatToNoteRow(GAMESTATE->m_fSongBeat) ) ),
ssprintf( "%.4f", m_pSong->m_SongTiming.GetStopAtRow( BeatToNoteRow(GAMESTATE->m_fSongBeat) ) ),
10
);
break;
@@ -3766,7 +3766,7 @@ void ScreenEdit::HandleTimingDataInformationChoice( TimingDataInformationChoice
ScreenTextEntry::TextEntry(
SM_BackFromDelayChange,
ENTER_DELAY_VALUE,
ssprintf( "%.4f", m_pSong->m_Timing.GetDelayAtRow( BeatToNoteRow(GAMESTATE->m_fSongBeat) ) ),
ssprintf( "%.4f", m_pSong->m_SongTiming.GetDelayAtRow( BeatToNoteRow(GAMESTATE->m_fSongBeat) ) ),
10
);
break;
@@ -3774,7 +3774,7 @@ void ScreenEdit::HandleTimingDataInformationChoice( TimingDataInformationChoice
ScreenTextEntry::TextEntry(
SM_BackFromTimeSignatureNumeratorChange,
ENTER_TIME_SIGNATURE_NUMERATOR_VALUE,
ssprintf( "%d", m_pSong->m_Timing.GetTimeSignatureSegmentAtBeat( GAMESTATE->m_fSongBeat ).m_iNumerator ),
ssprintf( "%d", m_pSong->m_SongTiming.GetTimeSignatureSegmentAtBeat( GAMESTATE->m_fSongBeat ).m_iNumerator ),
3
);
break;
@@ -3782,7 +3782,7 @@ void ScreenEdit::HandleTimingDataInformationChoice( TimingDataInformationChoice
ScreenTextEntry::TextEntry(
SM_BackFromTimeSignatureDenominatorChange,
ENTER_TIME_SIGNATURE_DENOMINATOR_VALUE,
ssprintf( "%d", m_pSong->m_Timing.GetTimeSignatureSegmentAtBeat( GAMESTATE->m_fSongBeat ).m_iDenominator ),
ssprintf( "%d", m_pSong->m_SongTiming.GetTimeSignatureSegmentAtBeat( GAMESTATE->m_fSongBeat ).m_iDenominator ),
3
);
break;
@@ -3790,7 +3790,7 @@ void ScreenEdit::HandleTimingDataInformationChoice( TimingDataInformationChoice
ScreenTextEntry::TextEntry(
SM_BackFromTickcountChange,
ENTER_TICKCOUNT_VALUE,
ssprintf( "%d", m_pSong->m_Timing.GetTickcountAtBeat( GAMESTATE->m_fSongBeat ) ),
ssprintf( "%d", m_pSong->m_SongTiming.GetTickcountAtBeat( GAMESTATE->m_fSongBeat ) ),
2
);
break;
@@ -3798,7 +3798,7 @@ void ScreenEdit::HandleTimingDataInformationChoice( TimingDataInformationChoice
ScreenTextEntry::TextEntry(
SM_BackFromComboChange,
ENTER_COMBO_VALUE,
ssprintf( "%d", m_pSong->m_Timing.GetComboAtBeat( GAMESTATE->m_fSongBeat ) ),
ssprintf( "%d", m_pSong->m_SongTiming.GetComboAtBeat( GAMESTATE->m_fSongBeat ) ),
4
);
break;
@@ -3806,7 +3806,7 @@ void ScreenEdit::HandleTimingDataInformationChoice( TimingDataInformationChoice
ScreenTextEntry::TextEntry(
SM_BackFromLabelChange,
ENTER_LABEL_VALUE,
ssprintf( "%s", m_pSong->m_Timing.GetLabelAtBeat( GAMESTATE->m_fSongBeat ).c_str() ),
ssprintf( "%s", m_pSong->m_SongTiming.GetLabelAtBeat( GAMESTATE->m_fSongBeat ).c_str() ),
64
);
break;
@@ -3814,7 +3814,7 @@ void ScreenEdit::HandleTimingDataInformationChoice( TimingDataInformationChoice
ScreenTextEntry::TextEntry(
SM_BackFromWarpChange,
ENTER_WARP_VALUE,
ssprintf( "%.4f", m_pSong->m_Timing.GetWarpAtRow( BeatToNoteRow(GAMESTATE->m_fSongBeat) ) ),
ssprintf( "%.4f", m_pSong->m_SongTiming.GetWarpAtRow( BeatToNoteRow(GAMESTATE->m_fSongBeat) ) ),
10
);
break;
@@ -4021,7 +4021,7 @@ void ScreenEdit::CheckNumberOfNotesAndUndo()
if( EDIT_MODE.GetValue() != EditMode_Home )
return;
TimeSignatureSegment curTime = GAMESTATE->m_pCurSong->m_Timing.GetTimeSignatureSegmentAtBeat( GAMESTATE->m_fSongBeat );
TimeSignatureSegment curTime = GAMESTATE->m_pCurSong->m_SongTiming.GetTimeSignatureSegmentAtBeat( GAMESTATE->m_fSongBeat );
int rowsPerMeasure = curTime.m_iDenominator * curTime.m_iNumerator;
for( int row=0; row<=m_NoteDataEdit.GetLastRow(); row+=rowsPerMeasure )
@@ -4073,7 +4073,7 @@ float ScreenEdit::GetMaximumBeatForNewNote() const
/* Round up to the next measure end. Some songs end on weird beats
* mid-measure, and it's odd to have movement capped to these weird
* beats. */
int beatsPerMeasure = GAMESTATE->m_pCurSong->m_Timing.GetTimeSignatureSegmentAtBeat( GAMESTATE->m_fSongBeat ).m_iNumerator;
int beatsPerMeasure = GAMESTATE->m_pCurSong->m_SongTiming.GetTimeSignatureSegmentAtBeat( GAMESTATE->m_fSongBeat ).m_iNumerator;
fEndBeat += beatsPerMeasure;
fEndBeat = ftruncf( fEndBeat, (float)beatsPerMeasure );
+31 -22
View File
@@ -128,8 +128,7 @@ enum EditButton
EDIT_BUTTON_SAMPLE_LENGTH_UP,
EDIT_BUTTON_SAMPLE_LENGTH_DOWN,
// This modifies offset, BPM, and stop segment changes.
EDIT_BUTTON_ADJUST_FINE,
EDIT_BUTTON_ADJUST_FINE, /**< This button modifies offset, BPM, and stop segment changes. */
EDIT_BUTTON_SAVE, /**< Save the present changes into the chart. */
@@ -166,7 +165,9 @@ struct MapEditToDI
}
};
// Like MapEditToDI, but maps GameButton instead of DeviceInput.
/**
* @brief This is similar to MapEditToDI,
* but maps GameButton instead of DeviceInput. */
struct MapEditButtonToMenuButton
{
GameButton button[NUM_EditButton][NUM_EDIT_TO_MENU_SLOTS];
@@ -214,11 +215,14 @@ protected:
// Call this before modifying m_NoteDataEdit.
void SaveUndo();
// Revert m_NoteDataEdit using m_Undo.
/** @brief Revert the last change made to m_NoteDataEdit. */
void Undo();
/** @brief Remove the previously stored NoteData to prevent undoing. */
void ClearUndo();
// Call this after modifying m_NoteDataEdit. It will Undo() if
// MAX_NOTES_PER_MEASURE was exceeded.
/**
* @brief This is to be called after modifying m_NoteDataEdit.
*
* It will Undo itself if MAX_NOTES_PER_MEASURE was exceeded. */
void CheckNumberOfNotesAndUndo();
void OnSnapModeChange();
@@ -252,7 +256,10 @@ protected:
// keep track of where we are and what we're doing
float m_fTrailingBeat; // this approaches GAMESTATE->m_fSongBeat, which is the actual beat
// The location we were at when shift was pressed, or -1 when shift isn't pressed:
/**
* @brief The location we were at when shift was pressed.
*
* If shift wasn't pressed, this will be -1. */
int m_iShiftAnchor;
/** @brief The NoteData that has been cut or copied. */
@@ -311,22 +318,23 @@ protected:
ThemeMetric<EditMode> EDIT_MODE;
public:
/** @brief What are the choices that one can make on the main menu? */
enum MainMenuChoice
{
play_selection,
set_selection_start,
set_selection_end,
edit_steps_information,
play_whole_song,
play_whole_song, /**< Play the entire chart from the beginning. */
play_selection_start_to_end,
play_current_beat_to_end,
save,
save, /**< Save the current chart to disk. */
revert_to_last_save,
revert_from_disk,
options,
edit_song_info,
edit_timing_data,
play_preview_music,
options, /**< Modify the PlayerOptions and SongOptions. */
edit_song_info, /**< Edit some general information about the song. */
edit_timing_data, /**< Edit the chart's timing data. */
play_preview_music, /**< Play the song's preview music. */
exit,
save_on_exit,
NUM_MAIN_MENU_CHOICES,
@@ -361,13 +369,14 @@ public:
};
void HandleAreaMenuChoice( AreaMenuChoice c, const vector<int> &iAnswers, bool bAllowUndo = true );
void HandleAreaMenuChoice( AreaMenuChoice c, bool bAllowUndo = true ) { const vector<int> v; HandleAreaMenuChoice( c, v, bAllowUndo ); }
/** @brief How should the selected notes be transformed? */
enum TurnType
{
left,
right,
mirror,
shuffle,
super_shuffle,
left, /**< Turn the notes as if you were facing to the left. */
right, /**< Turn the notes as if you were facing to the right. */
mirror, /**< Turn the notes as if you were facing away from the machine. */
shuffle, /**< Replace one column with another column. */
super_shuffle, /**< Replace each note individually. */
NUM_TURN_TYPES
};
enum TransformType
@@ -421,10 +430,10 @@ public:
{
difficulty,
meter,
description,
chartstyle,
step_credit,
predict_meter,
description, /**< What is the description of this chart? */
chartstyle, /**< How is this chart meant to be played? */
step_credit, /**< Who wrote this individual chart? */
predict_meter, /**< What does the game think this chart's rating should be? */
tap_notes,
jumps,
hands,
+4 -4
View File
@@ -1423,7 +1423,7 @@ void ScreenGameplay::UpdateSongPosition( float fDeltaTime )
RageTimer tm;
const float fSeconds = m_pSoundMusic->GetPositionSeconds( NULL, &tm );
const float fAdjust = SOUND->GetFrameTimingAdjustment( fDeltaTime );
GAMESTATE->UpdateSongPosition( fSeconds+fAdjust, GAMESTATE->m_pCurSong->m_Timing, tm+fAdjust );
GAMESTATE->UpdateSongPosition( fSeconds+fAdjust, GAMESTATE->m_pCurSong->m_SongTiming, tm+fAdjust );
}
void ScreenGameplay::BeginScreen()
@@ -1480,7 +1480,7 @@ bool ScreenGameplay::AllAreFailing()
void ScreenGameplay::GetMusicEndTiming( float &fSecondsToStartFadingOutMusic, float &fSecondsToStartTransitioningOut )
{
float fLastStepSeconds = GAMESTATE->m_pCurSong->GetElapsedTimeFromBeat( GAMESTATE->m_pCurSong->m_fLastBeat );
float fLastStepSeconds = GAMESTATE->m_pCurSong->m_SongTiming.GetElapsedTimeFromBeat( GAMESTATE->m_pCurSong->m_fLastBeat );
fLastStepSeconds += Player::GetMaxStepDistanceSeconds();
float fTransitionLength;
@@ -1995,7 +1995,7 @@ void ScreenGameplay::SendCrossedMessages()
static int iRowLastCrossed = 0;
float fPositionSeconds = GAMESTATE->m_fMusicSeconds;
float fSongBeat = GAMESTATE->m_pCurSong->GetBeatFromElapsedTime( fPositionSeconds );
float fSongBeat = GAMESTATE->m_pCurSong->m_SongTiming.GetBeatFromElapsedTime( fPositionSeconds );
int iRowNow = BeatToNoteRowNotRounded( fSongBeat );
iRowNow = max( 0, iRowNow );
@@ -2033,7 +2033,7 @@ void ScreenGameplay::SendCrossedMessages()
float fNoteWillCrossInSeconds = MESSAGE_SPACING_SECONDS * i;
float fPositionSeconds = GAMESTATE->m_fMusicSeconds + fNoteWillCrossInSeconds;
float fSongBeat = GAMESTATE->m_pCurSong->GetBeatFromElapsedTime( fPositionSeconds );
float fSongBeat = GAMESTATE->m_pCurSong->m_SongTiming.GetBeatFromElapsedTime( fPositionSeconds );
int iRowNow = BeatToNoteRowNotRounded( fSongBeat );
iRowNow = max( 0, iRowNow );
+1 -1
View File
@@ -244,7 +244,7 @@ void ScreenHowToPlay::Update( float fDelta )
{
if( GAMESTATE->m_pCurSong != NULL )
{
GAMESTATE->UpdateSongPosition( m_fFakeSecondsIntoSong, GAMESTATE->m_pCurSong->m_Timing );
GAMESTATE->UpdateSongPosition( m_fFakeSecondsIntoSong, GAMESTATE->m_pCurSong->m_SongTiming );
m_fFakeSecondsIntoSong += fDelta;
static int iLastNoteRowCounted = 0;
+1 -1
View File
@@ -1763,7 +1763,7 @@ void ScreenSelectMusic::AfterMusicChange()
case SampleMusicPreviewMode_LastSong: // fall through
// play the sample music
m_sSampleMusicToPlay = pSong->GetMusicPath();
m_pSampleMusicTimingData = &pSong->m_Timing;
m_pSampleMusicTimingData = &pSong->m_SongTiming;
m_fSampleStartSeconds = pSong->m_fMusicSampleStartSeconds;
m_fSampleLengthSeconds = pSong->m_fMusicSampleLengthSeconds;
break;
+2 -2
View File
@@ -221,7 +221,7 @@ bool ScreenSyncOverlay::OverlayInput( const InputEventPlus &input )
}
if( GAMESTATE->m_pCurSong != NULL )
{
BPMSegment& seg = GAMESTATE->m_pCurSong->GetBPMSegmentAtBeat( GAMESTATE->m_fSongBeat );
BPMSegment& seg = GAMESTATE->m_pCurSong->m_SongTiming.GetBPMSegmentAtBeat( GAMESTATE->m_fSongBeat );
seg.m_fBPS += fDelta;
}
}
@@ -253,7 +253,7 @@ bool ScreenSyncOverlay::OverlayInput( const InputEventPlus &input )
case ChangeSongOffset:
if( GAMESTATE->m_pCurSong != NULL )
GAMESTATE->m_pCurSong->m_Timing.m_fBeat0OffsetInSeconds += fDelta;
GAMESTATE->m_pCurSong->m_SongTiming.m_fBeat0OffsetInSeconds += fDelta;
break;
}
}
+21 -19
View File
@@ -167,7 +167,7 @@ void Song::GetDisplayBpms( DisplayBpms &AddTo ) const
else
{
float fMinBPM, fMaxBPM;
m_Timing.GetActualBPM( fMinBPM, fMaxBPM );
m_SongTiming.GetActualBPM( fMinBPM, fMaxBPM );
AddTo.Add( fMinBPM );
AddTo.Add( fMaxBPM );
}
@@ -488,29 +488,30 @@ void Song::TidyUpData()
m_sArtist = "Unknown artist";
TranslateTitles();
if( m_Timing.m_BPMSegments.empty() )
if( m_SongTiming.m_BPMSegments.empty() )
{
LOG->UserLog( "Song file", m_sSongDir + m_sSongFileName, "has no BPM segments, default provided." );
m_Timing.AddBPMSegment( BPMSegment(0, 60) );
m_SongTiming.AddBPMSegment( BPMSegment(0, 60) );
}
// Make sure the first BPM segment starts at beat 0.
if( m_Timing.m_BPMSegments[0].m_iStartRow != 0 )
m_Timing.m_BPMSegments[0].m_iStartRow = 0;
if( m_SongTiming.m_BPMSegments[0].m_iStartRow != 0 )
m_SongTiming.m_BPMSegments[0].m_iStartRow = 0;
if( m_fMusicSampleStartSeconds == -1 ||
m_fMusicSampleStartSeconds == 0 ||
m_fMusicSampleStartSeconds+m_fMusicSampleLengthSeconds > this->m_fMusicLengthSeconds )
{
m_fMusicSampleStartSeconds = this->GetElapsedTimeFromBeat( 100 );
const TimingData &timing = this->m_SongTiming;
m_fMusicSampleStartSeconds = timing.GetElapsedTimeFromBeat( 100 );
if( m_fMusicSampleStartSeconds+m_fMusicSampleLengthSeconds > this->m_fMusicLengthSeconds )
{
int iBeat = lrintf( m_fLastBeat/2 );
iBeat -= iBeat%4;
m_fMusicSampleStartSeconds = this->GetElapsedTimeFromBeat( (float)iBeat );
m_fMusicSampleStartSeconds = timing.GetElapsedTimeFromBeat( (float)iBeat );
}
}
@@ -791,10 +792,10 @@ void Song::TidyUpData()
}
// If no time signature specified, assume 4/4 time for the whole song.
if( m_Timing.m_vTimeSignatureSegments.empty() )
if( m_SongTiming.m_vTimeSignatureSegments.empty() )
{
TimeSignatureSegment seg(0, 4, 4);
m_Timing.m_vTimeSignatureSegments.push_back( seg );
m_SongTiming.m_vTimeSignatureSegments.push_back( seg );
}
/*
@@ -802,24 +803,24 @@ void Song::TidyUpData()
* per beat for the entire song. The default of 2 is chosen more
* for compatibility with the Pump Pro series than anything else.
*/
if( m_Timing.m_TickcountSegments.empty() )
if( m_SongTiming.m_TickcountSegments.empty() )
{
TickcountSegment seg(0, 2);
m_Timing.m_TickcountSegments.push_back( seg );
m_SongTiming.m_TickcountSegments.push_back( seg );
}
// Have a default combo segment of one just in case.
if( m_Timing.m_ComboSegments.empty() )
if( m_SongTiming.m_ComboSegments.empty() )
{
ComboSegment seg(0, 1);
m_Timing.m_ComboSegments.push_back( seg );
m_SongTiming.m_ComboSegments.push_back( seg );
}
// Have a default label segment just in case.
if( m_Timing.m_LabelSegments.empty() )
if( m_SongTiming.m_LabelSegments.empty() )
{
LabelSegment seg(0, "Song Start");
m_Timing.m_LabelSegments.push_back( seg );
m_SongTiming.m_LabelSegments.push_back( seg );
}
}
@@ -1465,7 +1466,7 @@ bool Song::IsEditAlreadyLoaded( Steps* pSteps ) const
bool Song::HasSignificantBpmChangesOrStops() const
{
if( m_Timing.HasStops() )
if( m_SongTiming.HasStops() )
return true;
// Don't consider BPM changes that only are only for maintaining sync as
@@ -1475,7 +1476,7 @@ bool Song::HasSignificantBpmChangesOrStops() const
if( m_fSpecifiedBPMMin != m_fSpecifiedBPMMax )
return true;
}
else if( m_Timing.HasBpmChanges() )
else if( m_SongTiming.HasBpmChanges() )
{
return true;
}
@@ -1485,7 +1486,8 @@ bool Song::HasSignificantBpmChangesOrStops() const
float Song::GetStepsSeconds() const
{
return GetElapsedTimeFromBeat( m_fLastBeat ) - GetElapsedTimeFromBeat( m_fFirstBeat );
const TimingData &timing = this->m_SongTiming;
return timing.GetElapsedTimeFromBeat( m_fLastBeat ) - timing.GetElapsedTimeFromBeat( m_fFirstBeat );
}
bool Song::IsLong() const
@@ -1568,7 +1570,7 @@ public:
}
static int GetTimingData( T* p, lua_State *L )
{
p->m_Timing.PushSelf(L);
p->m_SongTiming.PushSelf(L);
return 1;
}
// has functions
+1 -1
View File
@@ -17,7 +17,7 @@ struct lua_State;
struct BackgroundChange;
/** @brief The version of the .ssc file format. */
const static float STEPFILE_VERSION_NUMBER = 0.59f;
const static float STEPFILE_VERSION_NUMBER = 0.7f;
/** @brief How many edits for this song can each profile have? */
const int MAX_EDITS_PER_SONG_PER_PROFILE = 5;
+9 -3
View File
@@ -8,10 +8,16 @@
#include <float.h>
TimingData::TimingData()
TimingData::TimingData() :
m_fBeat0OffsetInSeconds(0),
m_bHasNegativeBpms(false)
{
m_fBeat0OffsetInSeconds = 0;
m_bHasNegativeBpms = false;
}
TimingData::TimingData(float fOffset) :
m_fBeat0OffsetInSeconds(fOffset),
m_bHasNegativeBpms(false)
{
}
void TimingData::GetActualBPM( float &fMinBPMOut, float &fMaxBPMOut ) const
+4
View File
@@ -658,6 +658,10 @@ public:
* @brief Sets up initial timing data.
*/
TimingData();
/**
* @brief Sets up initial timing data with a defined offset.
* @param fOffset the offset from the 0th beat. */
TimingData(float fOffset);
/**
* @brief Gets the actual BPM of the song.
* @param fMinBPMOut the minimium specified BPM.