Write timing tags for SSC files.

WARN: This does not work with ScreenEdit, yet!
This commit is contained in:
Thai Pangsakulyanont
2011-05-10 16:00:47 +07:00
parent 285f227851
commit b634639e8e
4 changed files with 168 additions and 170 deletions
+109 -129
View File
@@ -41,6 +41,111 @@ static RString BackgroundChangeToString( const BackgroundChange &bgc )
return s;
}
/**
* @brief Turn a vector of lines into a single line joined by newline characters.
* @param lines the list of lines to join.
* @return the joined lines. */
static RString JoinLineList( vector<RString> &lines )
{
for( unsigned i = 0; i < lines.size(); ++i )
TrimRight( lines[i] );
// Skip leading blanks.
unsigned j = 0;
while( j < lines.size() && lines.size() == 0 )
++j;
return join( "\r\n", lines.begin()+j, lines.end() );
}
// A utility class to write timing tags more easily!
struct TimingTagWriter {
vector<RString> *m_pvsLines;
RString m_sNext;
TimingTagWriter( vector<RString> *pvsLines ): m_pvsLines (pvsLines) { }
void Write( const int row, const char *value )
{
m_pvsLines->push_back( m_sNext + ssprintf( "%.6f=%s", NoteRowToBeat(row), value ) );
m_sNext = ",";
}
void Write( const int row, const float value ) { Write( row, ssprintf( "%.6f", value ) ); }
void Write( const int row, const int value ) { Write( row, ssprintf( "%d", value ) ); }
void Write( const int row, const int a, const int b ) { Write( row, ssprintf( "%d=%d", a, b ) ); }
void Init( const RString sTag ) { m_sNext = "#" + sTag + ":"; }
void Finish( ) { m_pvsLines->push_back( ( m_sNext != "," ? m_sNext : "" ) + ";" ); }
};
static void GetTimingTags( vector<RString> &lines, TimingData timing )
{
TimingTagWriter w ( &lines );
timing.TidyUpData();
w.Init( "BPMS" );
FOREACH_CONST( BPMSegment, timing.m_BPMSegments, bs )
w.Write( bs->m_iStartRow, bs->GetBPM() );
w.Finish();
w.Init( "STOPS" );
FOREACH_CONST( StopSegment, timing.m_StopSegments, ss )
if( !ss->m_bDelay )
w.Write( ss->m_iStartRow, ss->m_fStopSeconds );
w.Finish();
w.Init( "DELAYS" );
FOREACH_CONST( StopSegment, timing.m_StopSegments, ss )
if( ss->m_bDelay )
w.Write( ss->m_iStartRow, ss->m_fStopSeconds );
w.Finish();
w.Init( "WARPS" );
FOREACH_CONST( WarpSegment, timing.m_WarpSegments, ws )
w.Write( ws->m_iStartRow, ws->m_fEndBeat );
w.Finish();
ASSERT( !timing.m_vTimeSignatureSegments.empty() );
w.Init( "TIMESIGNATURES" );
FOREACH_CONST( TimeSignatureSegment, timing.m_vTimeSignatureSegments, iter )
w.Write( iter->m_iStartRow, iter->m_iNumerator, iter->m_iDenominator );
w.Finish();
ASSERT( !timing.m_TickcountSegments.empty() );
w.Init( "TICKCOUNTS" );
FOREACH_CONST( TickcountSegment, timing.m_TickcountSegments, ts )
w.Write( ts->m_iStartRow, ts->m_iTicks );
w.Finish();
ASSERT( !timing.m_ComboSegments.empty() );
w.Init( "COMBOS" );
FOREACH_CONST( ComboSegment, timing.m_ComboSegments, cs )
w.Write( cs->m_iStartRow, cs->m_iCombo );
w.Finish();
w.Init( "LABELS" );
FOREACH_CONST( LabelSegment, timing.m_LabelSegments, ls )
w.Write( ls->m_iStartRow, ls->m_sLabel.c_str() );
w.Finish();
}
static void WriteTimingTags( RageFile &f, const TimingData &timing )
{
vector<RString> lines;
GetTimingTags( lines, timing );
f.PutLine( JoinLineList( lines ) );
}
/**
* @brief Write out the common tags for .SM files.
* @param f the file in question.
@@ -106,105 +211,7 @@ static void WriteGlobalTags( RageFile &f, const Song &out )
break;
}
f.Write( "#BPMS:" );
for( unsigned i=0; i<out.m_SongTiming.m_BPMSegments.size(); 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_SongTiming.m_BPMSegments.size()-1 )
f.Write( "," );
}
f.PutLine( ";" );
f.Write( "#STOPS:" );
for( unsigned i=0; i<out.m_SongTiming.m_StopSegments.size(); 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_SongTiming.m_StopSegments.size()-1 )
f.Write( "," );
}
}
f.PutLine( ";" );
f.Write( "#DELAYS:" );
for( unsigned i=0; i<out.m_SongTiming.m_StopSegments.size(); 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_SongTiming.m_StopSegments.size()-1 )
f.Write( "," );
}
}
f.PutLine( ";" );
f.Write( "#WARPS:" );
for( unsigned i=0; i<out.m_SongTiming.m_WarpSegments.size(); 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_SongTiming.m_WarpSegments.size()-1 )
f.Write( "," );
}
f.PutLine( ";" );
ASSERT( !out.m_SongTiming.m_vTimeSignatureSegments.empty() );
f.Write( "#TIMESIGNATURES:" );
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_SongTiming.m_vTimeSignatureSegments.end() )
f.Write( "," );
}
f.PutLine( ";" );
ASSERT( !out.m_SongTiming.m_TickcountSegments.empty() );
f.Write( "#TICKCOUNTS:" );
for( unsigned i=0; i<out.m_SongTiming.m_TickcountSegments.size(); 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_SongTiming.m_TickcountSegments.size()-1 )
f.Write( "," );
}
f.PutLine( ";" );
ASSERT( !out.m_SongTiming.m_ComboSegments.empty() );
f.Write( "#COMBOS:" );
for( unsigned i=0; i<out.m_SongTiming.m_ComboSegments.size(); 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_SongTiming.m_ComboSegments.size()-1 )
f.Write( "," );
}
f.PutLine( ";" );
f.Write( "#LABELS:" );
for( unsigned i=0; i<out.m_SongTiming.m_LabelSegments.size(); 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_SongTiming.m_LabelSegments.size()-1 )
f.Write( "," );
}
f.PutLine( ";" );
WriteTimingTags( f, out.m_SongTiming );
FOREACH_BackgroundLayer( b )
{
@@ -258,23 +265,6 @@ static void WriteGlobalTags( RageFile &f, const Song &out )
f.PutLine( ";" );
}
/**
* @brief Turn a vector of lines into a single line joined by newline characters.
* @param lines the list of lines to join.
* @return the joined lines. */
static RString JoinLineList( vector<RString> &lines )
{
for( unsigned i = 0; i < lines.size(); ++i )
TrimRight( lines[i] );
// Skip leading blanks.
unsigned j = 0;
while( j < lines.size() && lines.size() == 0 )
++j;
return join( "\r\n", lines.begin()+j, lines.end() );
}
/**
* @brief Retrieve the individual batches of NoteData.
* @param song the Song in question.
@@ -307,19 +297,8 @@ static RString GetSSCNoteData( const Song &song, const Steps &in, bool bSavingCa
lines.push_back( ssprintf( "#CREDIT:%s;", SmEscape(in.GetCredit()).c_str() ) );
/*
* TODO: Remove this block, transplant above code
* below for Split Timing. -Wolfman2000 */
lines.push_back( "#BPMS:;" );
lines.push_back( "#STOPS:;" );
lines.push_back( "#DELAYS:;" );
lines.push_back( "#WARPS:;" );
lines.push_back( "#LABELS:;" );
lines.push_back( "#TIMESIGNATURES:;" );
lines.push_back( "#TICKCOUNTS:;" );
lines.push_back( "#ATTACKS:;" );
lines.push_back( "#COMBOS:;" );
GetTimingTags( lines, in.m_Timing );
RString sNoteData;
in.GetSMNoteData( sNoteData );
@@ -350,6 +329,7 @@ bool NotesWriterSSC::Write( RString sPath, const Song &out, const vector<Steps*>
}
WriteGlobalTags( f, out );
if( bSavingCache )
{
f.PutLine( ssprintf( "// cache tags:" ) );