[sm130labels -> sm130futures] Mission completed.
This commit is contained in:
@@ -9,6 +9,9 @@ change to JSON, but it is unsure if this will be done.
|
||||
Implement .ssc at your own risk.
|
||||
________________________________________________________________________________
|
||||
|
||||
[v0.57] - Wolfman2000
|
||||
* Implement #LABELS tag for easier Editor work/Rock Band section mimicry.
|
||||
|
||||
[v0.56] - Wolfman2000
|
||||
* Implement #WARPS tag to replace negative bpm/stop gimmicks.
|
||||
|
||||
|
||||
@@ -9,6 +9,16 @@ Not all changes are documented, for various reasons.
|
||||
supported but exist anyways.)
|
||||
_____________________________________________________________________________
|
||||
|
||||
================================================================================
|
||||
sm-ssc $SM5VERSION | 2011????
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
20110405
|
||||
--------
|
||||
* [NotesLoaderSSC, NotesWriterSSC] Add the #LABELS tag. This is meant for step
|
||||
editors to label different parts of their stepcharts. Use Control + , or . to
|
||||
jump to different labels made. [Wolfman2000]
|
||||
|
||||
================================================================================
|
||||
sm-ssc $NEXTVERSION | 2011????
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
@@ -1391,6 +1391,7 @@
|
||||
<Function name='GetBeatFromElapsedTime'/>
|
||||
<Function name='GetDelays'/>
|
||||
<Function name='GetElapsedTimeFromBeat'/>
|
||||
<Function name='GetLabels'/>
|
||||
<Function name='GetStops'/>
|
||||
<Function name='HasBPMChanges'/>
|
||||
<Function name='HasNegativeBPMs'/>
|
||||
|
||||
@@ -3241,6 +3241,9 @@
|
||||
<Function name='GetDelays' sm-ssc='true' return='{string}' arguments=''>
|
||||
Returns a table of the Delays and the times they happen as strings with the format "<code>beat=stop seconds</code>".
|
||||
</Function>
|
||||
<Function name='GetLabels' sm-ssc='true' return='{string}' arguments=''>
|
||||
Returns a table of the Labels and the times they happen as strings with the format "<code>beat=label name</code>."
|
||||
</Function>
|
||||
<Function name='HasBPMChanges' sm-ssc='true' return='bool' arguments=''>
|
||||
Returns <code>true</code> if the TimingData contains BPM changes.
|
||||
</Function>
|
||||
|
||||
@@ -843,6 +843,7 @@ Edit time signature (top)=Edit time signature (beats per measure)
|
||||
Edit time signature (bottom)=Edit time signature (single beat note value)
|
||||
Edit tickcount=Edit tickcount
|
||||
Edit combo=Edit combo
|
||||
Edit label=Edit label
|
||||
Edit warp=Edit warp
|
||||
Editor options=Options
|
||||
EditorShowBGChangesPlay=Show Backgrounds
|
||||
@@ -1210,6 +1211,7 @@ Enter a new Time Signature numerator value.=Enter the number of beats per measur
|
||||
Enter a new Time Signature denominator value.=Enter the note value that represents one beat.
|
||||
Enter a new Tickcount value.=Enter a new Tickcount value.
|
||||
Enter a new Combo value.=Enter a new Combo value.
|
||||
Enter a new Label value.=Enter a name for this section of the chart.
|
||||
Enter a new Warp value.=Enter the beat you will warp to when you reach this point.
|
||||
Enter a new artist transliteration.=Enter a new artist transliteration.
|
||||
Enter a new artist.=Enter a new artist.
|
||||
|
||||
@@ -981,6 +981,7 @@ WarpColor=color("1,0,0.5,1")
|
||||
TimeSignatureColor=color("1,0.55,0,1")
|
||||
TickcountColor=color("0,1,0,1")
|
||||
ComboColor=color("0.55,1,0,1")
|
||||
LabelColor=color("1,0,0,1")
|
||||
#
|
||||
BPMIsLeftSide=true
|
||||
StopIsLeftSide=true
|
||||
@@ -989,6 +990,7 @@ WarpIsLeftSide=false
|
||||
TimeSignatureIsLeftSide=true
|
||||
TickcountIsLeftSide=false
|
||||
ComboIsLeftSide=false
|
||||
LabelIsLeftSide=false
|
||||
#
|
||||
BPMOffsetX=60
|
||||
StopOffsetX=50
|
||||
@@ -997,6 +999,7 @@ WarpOffsetX=60
|
||||
TimeSignatureOffsetX=30
|
||||
TickcountOffsetX=10
|
||||
ComboOffsetX=30
|
||||
LabelOffsetX=80
|
||||
|
||||
[PlayerStageStats]
|
||||
# Original CVS Grading
|
||||
|
||||
@@ -426,6 +426,7 @@ static ThemeMetric<RageColor> WARP_COLOR ( "NoteField", "WarpColor" );
|
||||
static ThemeMetric<RageColor> TIME_SIGNATURE_COLOR ( "NoteField", "TimeSignatureColor" );
|
||||
static ThemeMetric<RageColor> TICKCOUNT_COLOR ( "NoteField", "TickcountColor" );
|
||||
static ThemeMetric<RageColor> COMBO_COLOR ( "NoteField", "ComboColor" );
|
||||
static ThemeMetric<RageColor> LABEL_COLOR ( "NoteField", "LabelColor" );
|
||||
static ThemeMetric<bool> BPM_IS_LEFT_SIDE ( "NoteField", "BPMIsLeftSide" );
|
||||
static ThemeMetric<bool> STOP_IS_LEFT_SIDE ( "NoteField", "StopIsLeftSide" );
|
||||
static ThemeMetric<bool> DELAY_IS_LEFT_SIDE ( "NoteField", "DelayIsLeftSide" );
|
||||
@@ -433,6 +434,7 @@ static ThemeMetric<bool> WARP_IS_LEFT_SIDE ( "NoteField", "WarpIsLeftSide" );
|
||||
static ThemeMetric<bool> TIME_SIGNATURE_IS_LEFT_SIDE ( "NoteField", "TimeSignatureIsLeftSide" );
|
||||
static ThemeMetric<bool> TICKCOUNT_IS_LEFT_SIDE ( "NoteField", "TickcountIsLeftSide" );
|
||||
static ThemeMetric<bool> COMBO_IS_LEFT_SIDE ( "NoteField", "ComboIsLeftSide" );
|
||||
static ThemeMetric<bool> LABEL_IS_LEFT_SIDE ( "NoteField", "LabelIsLeftSide" );
|
||||
static ThemeMetric<float> BPM_OFFSETX ( "NoteField", "BPMOffsetX" );
|
||||
static ThemeMetric<float> STOP_OFFSETX ( "NoteField", "StopOffsetX" );
|
||||
static ThemeMetric<float> DELAY_OFFSETX ( "NoteField", "DelayOffsetX" );
|
||||
@@ -440,6 +442,7 @@ static ThemeMetric<float> WARP_OFFSETX ( "NoteField", "WarpOffsetX" );
|
||||
static ThemeMetric<float> TIME_SIGNATURE_OFFSETX ( "NoteField", "TimeSignatureOffsetX" );
|
||||
static ThemeMetric<float> TICKCOUNT_OFFSETX ( "NoteField", "TickcountOffsetX" );
|
||||
static ThemeMetric<float> COMBO_OFFSETX ( "NoteField", "ComboOffsetX" );
|
||||
static ThemeMetric<float> LABEL_OFFSETX ( "NoteField", "LabelOffsetX" );
|
||||
|
||||
void NoteField::DrawBPMText( const float fBeat, const float fBPM )
|
||||
{
|
||||
@@ -552,6 +555,23 @@ void NoteField::DrawComboText( const float fBeat, int iCombo )
|
||||
m_textMeasureNumber.Draw();
|
||||
}
|
||||
|
||||
void NoteField::DrawLabelText( const float fBeat, RString sLabel )
|
||||
{
|
||||
const float fYOffset = ArrowEffects::GetYOffset( m_pPlayerState, 0, fBeat );
|
||||
const float fYPos = ArrowEffects::GetYPos( m_pPlayerState, 0, fYOffset, m_fYReverseOffsetPixels );
|
||||
const float fZoom = ArrowEffects::GetZoom( m_pPlayerState );
|
||||
const float xBase = GetWidth()/2.f;
|
||||
const float xOffset = LABEL_OFFSETX * fZoom;
|
||||
|
||||
m_textMeasureNumber.SetZoom( fZoom );
|
||||
m_textMeasureNumber.SetHorizAlign( LABEL_IS_LEFT_SIDE ? align_right : align_left );
|
||||
m_textMeasureNumber.SetDiffuse( LABEL_COLOR );
|
||||
m_textMeasureNumber.SetGlow( RageColor(1,1,1,RageFastCos(RageTimer::GetTimeSinceStartFast()*2)/2+0.5f) );
|
||||
m_textMeasureNumber.SetText( sLabel.c_str() );
|
||||
m_textMeasureNumber.SetXY( (LABEL_IS_LEFT_SIDE ? -xBase - xOffset : xBase + xOffset), fYPos );
|
||||
m_textMeasureNumber.Draw();
|
||||
}
|
||||
|
||||
void NoteField::DrawAttackText( const float fBeat, const Attack &attack )
|
||||
{
|
||||
const float fYOffset = ArrowEffects::GetYOffset( m_pPlayerState, 0, fBeat );
|
||||
@@ -842,6 +862,19 @@ void NoteField::DrawPrimitives()
|
||||
DrawComboText( fBeat, tComboSegments[i].m_iCombo );
|
||||
}
|
||||
}
|
||||
|
||||
// Label text
|
||||
const vector<LabelSegment> &lLabelSegments = GAMESTATE->m_pCurSong->m_Timing.m_LabelSegments;
|
||||
for( unsigned i=0; i<lLabelSegments.size(); i++ )
|
||||
{
|
||||
if( lLabelSegments[i].m_iStartRow >= iFirstRowToDraw &&
|
||||
lLabelSegments[i].m_iStartRow <= iLastRowToDraw)
|
||||
{
|
||||
float fBeat = NoteRowToBeat(lLabelSegments[i].m_iStartRow);
|
||||
if( IS_ON_SCREEN(fBeat) )
|
||||
DrawLabelText( fBeat, lLabelSegments[i].m_sLabel );
|
||||
}
|
||||
}
|
||||
|
||||
// Course mods text
|
||||
const Course *pCourse = GAMESTATE->m_pCurCourse;
|
||||
|
||||
@@ -61,6 +61,7 @@ protected:
|
||||
void DrawTimeSignatureText( const float fBeat, int iNumerator, int iDenominator );
|
||||
void DrawTickcountText( const float fBeat, int iTicks );
|
||||
void DrawComboText( const float fBeat, int iCombo );
|
||||
void DrawLabelText( const float fBeat, RString sLabel );
|
||||
void DrawAttackText( const float fBeat, const Attack &attack );
|
||||
void DrawBGChangeText( const float fBeat, const RString sNewBGName );
|
||||
float GetWidth() const;
|
||||
|
||||
+38
-161
@@ -514,6 +514,35 @@ bool SSCLoader::LoadFromSSCFile( const RString &sPath, Song &out, bool bFromCach
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
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() );
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
else if( sValueName=="TIMESIGNATURES" )
|
||||
{
|
||||
@@ -763,180 +792,28 @@ bool SSCLoader::LoadFromSSCFile( const RString &sPath, Song &out, bool bFromCach
|
||||
{
|
||||
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 );
|
||||
pNewNotes->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 );
|
||||
pNewNotes->m_Timing.AddStopSegment( new_seg );
|
||||
}
|
||||
else
|
||||
LOG->UserLog( "Song file", "(UNKNOWN)", "has an invalid stop at beat %f, length %f.", fFreezeBeat, fFreezeSeconds );
|
||||
}
|
||||
}
|
||||
*/
|
||||
// copy from above when it's time.
|
||||
}
|
||||
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)
|
||||
pNewNotes->m_Timing.AddStopSegment( new_seg );
|
||||
else
|
||||
LOG->UserLog( "Song file", "(UNKNOWN)", "has an invalid delay at beat %f, length %f.", fFreezeBeat, fFreezeSeconds );
|
||||
}
|
||||
*/
|
||||
// copy from above when it's time.
|
||||
}
|
||||
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;
|
||||
}
|
||||
|
||||
pNewNotes->m_Timing.AddTimeSignatureSegment( seg );
|
||||
}
|
||||
*/
|
||||
// copy from above when it's time.
|
||||
}
|
||||
|
||||
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 );
|
||||
pNewNotes->m_Timing.AddTickcountSegment( new_seg );
|
||||
}
|
||||
else
|
||||
{
|
||||
LOG->UserLog( "Song file", "(UNKNOWN)", "has an invalid tickcount at beat %f, ticks %d.", fTickcountBeat, iTicks );
|
||||
}
|
||||
}
|
||||
*/
|
||||
// copy from above when it's time.
|
||||
}
|
||||
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 );
|
||||
pNewNotes->m_Timing.AddComboSegment( new_seg );
|
||||
}
|
||||
*/
|
||||
// copy from above when it's time.
|
||||
}
|
||||
else if( sValueName=="WARPS" || sValueName=="LABELS" )
|
||||
{
|
||||
// copy from above when it's time.
|
||||
}
|
||||
else if( sValueName=="ATTACKS" )
|
||||
{
|
||||
|
||||
+15
-82
@@ -194,6 +194,17 @@ static void WriteGlobalTags( RageFile &f, const Song &out )
|
||||
}
|
||||
f.PutLine( ";" );
|
||||
|
||||
f.Write( "#LABELS:" );
|
||||
for( unsigned i=0; i<out.m_Timing.m_LabelSegments.size(); i++ )
|
||||
{
|
||||
const LabelSegment &ls = out.m_Timing.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 )
|
||||
f.Write( "," );
|
||||
}
|
||||
f.PutLine( ";" );
|
||||
|
||||
FOREACH_BackgroundLayer( b )
|
||||
{
|
||||
if( b==0 )
|
||||
@@ -295,97 +306,19 @@ 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, uncomment below block for Split Timing. -Wolfman2000
|
||||
/*
|
||||
* 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:;" );
|
||||
|
||||
/*
|
||||
vector<RString> asBPMValues;
|
||||
for( unsigned i=0; i<in.m_Timing.m_BPMSegments.size(); i++ )
|
||||
{
|
||||
const BPMSegment &bs = in.m_Timing.m_BPMSegments[i];
|
||||
asBPMValues.push_back( ssprintf("%.6f=%.6f", NoteRowToBeat(bs.m_iStartRow), bs.GetBPM() ) );
|
||||
}
|
||||
lines.push_back( ssprintf( "#BPMS:%s;", join("\n,", asBPMValues).c_str() ) );
|
||||
|
||||
vector<RString> asStopValues;
|
||||
for( unsigned i=0; i<in.m_Timing.m_StopSegments.size(); i++ )
|
||||
{
|
||||
const StopSegment &fs = in.m_Timing.m_StopSegments[i];
|
||||
|
||||
if(!fs.m_bDelay)
|
||||
{
|
||||
asStopValues.push_back( ssprintf( "%.6f=%.6f", NoteRowToBeat(fs.m_iStartRow), fs.m_fStopSeconds ) );
|
||||
}
|
||||
}
|
||||
lines.push_back( ssprintf( "#STOPS:%s;", join("\n,", asStopValues).c_str() ) );
|
||||
|
||||
vector<RString> asDelayValues;
|
||||
for( unsigned i=0; i<in.m_Timing.m_StopSegments.size(); i++ )
|
||||
{
|
||||
const StopSegment &fs = in.m_Timing.m_StopSegments[i];
|
||||
|
||||
if( fs.m_bDelay )
|
||||
{
|
||||
asDelayValues.push_back( ssprintf( "%.6f=%.6f", NoteRowToBeat(fs.m_iStartRow), fs.m_fStopSeconds ) );
|
||||
}
|
||||
}
|
||||
lines.push_back( ssprintf( "#DELAYS:%s;", join("\n,", asDelayValues).c_str() ) );
|
||||
|
||||
vector<RString> asWarpValues;
|
||||
for( unsigned i=0; i<in.m_Timing.m_WarpSegments.size(); i++ )
|
||||
{
|
||||
const WarpSegment &ws = in.m_Timing.m_WarpSegments[i];
|
||||
|
||||
if( ws.m_bDelay )
|
||||
{
|
||||
asWarpValues.push_back( ssprintf( "%.6f=%.6f", NoteRowToBeat(fs.m_iStartRow), fs.m_fWarpBeats ) );
|
||||
}
|
||||
}
|
||||
lines.push_back( ssprintf( "#WARPS:%s;", join("\n,", asWarpValues).c_str() ) );
|
||||
|
||||
ASSERT( !in.m_Timing.m_vTimeSignatureSegments.empty() );
|
||||
vector<RString> asTimeSigValues;
|
||||
FOREACH_CONST( TimeSignatureSegment, in.m_Timing.m_vTimeSignatureSegments, iter )
|
||||
{
|
||||
asTimeSigValues.push_back( ssprintf( "%.6f=%d=%d", NoteRowToBeat(iter->m_iStartRow), iter->m_iNumerator, iter->m_iDenominator ) );
|
||||
vector<TimeSignatureSegment>::const_iterator iter2 = iter;
|
||||
iter2++;
|
||||
}
|
||||
lines.push_back( ssprintf( "#TIMESIGNATURES:%s;", join("\n,", asTimeSigValues).c_str() ) );
|
||||
|
||||
ASSERT( !in.m_Timing.m_TickcountSegments.empty() );
|
||||
vector<RString> asTickValues;
|
||||
for( unsigned i=0; i<in.m_Timing.m_TickcountSegments.size(); i++ )
|
||||
{
|
||||
const TickcountSegment &ts = in.m_Timing.m_TickcountSegments[i];
|
||||
|
||||
asTickValues.push_back( ssprintf( "%.6f=%d", NoteRowToBeat(ts.m_iStartRow), ts.m_iTicks ) );
|
||||
}
|
||||
lines.push_back( ssprintf( "#TICKCOUNTS:%s;", join("\n,", asTickValues).c_str() ) );
|
||||
|
||||
ASSERT( !in.m_Timing.m_ComboSegments.empty() );
|
||||
vector<RString> asComboValues;
|
||||
for( unsigned i=0; i<in.m_Timing.m_ComboSegments.size(); i++ )
|
||||
{
|
||||
const ComboSegment &cs = in.m_Timing.m_ComboSegments[i];
|
||||
|
||||
asComboValues.push_back( ssprintf( "%.6f=%d", NoteRowToBeat(cs.m_iStartRow), cs.m_iComboFactor ) );
|
||||
}
|
||||
|
||||
lines.push_back( "#ATTACKS:;" );
|
||||
|
||||
lines.push_back( ssprintf( "#COMBOS:%s;", join("\n,", asComboValues).c_str() ) );
|
||||
|
||||
lines.push_back( ssprintf( "#OFFSET:%.6f;", in.m_Timing.m_fBeat0OffsetInSeconds ) );
|
||||
*/
|
||||
|
||||
RString sNoteData;
|
||||
in.GetSMNoteData( sNoteData );
|
||||
|
||||
|
||||
@@ -80,6 +80,7 @@ AutoScreenMessage( SM_BackFromTimeSignatureNumeratorChange );
|
||||
AutoScreenMessage( SM_BackFromTimeSignatureDenominatorChange );
|
||||
AutoScreenMessage( SM_BackFromTickcountChange );
|
||||
AutoScreenMessage( SM_BackFromComboChange );
|
||||
AutoScreenMessage( SM_BackFromLabelChange );
|
||||
AutoScreenMessage( SM_BackFromWarpChange );
|
||||
AutoScreenMessage( SM_DoSaveAndExit );
|
||||
AutoScreenMessage( SM_DoExit );
|
||||
@@ -255,6 +256,14 @@ void ScreenEdit::InitEditMappings()
|
||||
m_EditMappingsDeviceInput.button[EDIT_BUTTON_SCROLL_SELECT][0] = DeviceInput(DEVICE_KEYBOARD, KEY_LSHIFT);
|
||||
m_EditMappingsDeviceInput.button[EDIT_BUTTON_SCROLL_SELECT][1] = DeviceInput(DEVICE_KEYBOARD, KEY_RSHIFT);
|
||||
|
||||
m_EditMappingsDeviceInput.button[EDIT_BUTTON_LABEL_NEXT][0] = DeviceInput(DEVICE_KEYBOARD, KEY_PERIOD);
|
||||
m_EditMappingsDeviceInput.hold[EDIT_BUTTON_LABEL_NEXT][0] = DeviceInput(DEVICE_KEYBOARD, KEY_LCTRL);
|
||||
m_EditMappingsDeviceInput.hold[EDIT_BUTTON_LABEL_NEXT][1] = DeviceInput(DEVICE_KEYBOARD, KEY_RCTRL);
|
||||
|
||||
m_EditMappingsDeviceInput.button[EDIT_BUTTON_LABEL_PREV][0] = DeviceInput(DEVICE_KEYBOARD, KEY_COMMA);
|
||||
m_EditMappingsDeviceInput.hold[EDIT_BUTTON_LABEL_PREV][0] = DeviceInput(DEVICE_KEYBOARD, KEY_LCTRL);
|
||||
m_EditMappingsDeviceInput.hold[EDIT_BUTTON_LABEL_PREV][1] = DeviceInput(DEVICE_KEYBOARD, KEY_RCTRL);
|
||||
|
||||
m_EditMappingsDeviceInput.button[EDIT_BUTTON_SNAP_NEXT][0] = DeviceInput(DEVICE_KEYBOARD, KEY_LEFT);
|
||||
m_EditMappingsDeviceInput.button[EDIT_BUTTON_SNAP_PREV][0] = DeviceInput(DEVICE_KEYBOARD, KEY_RIGHT);
|
||||
|
||||
@@ -551,6 +560,7 @@ static MenuDef g_TimingDataInformation(
|
||||
MenuRowDef( ScreenEdit::time_signature_denominator, "Edit time signature (bottom)", true, EditMode_Full, true, true, 0, NULL ),
|
||||
MenuRowDef( ScreenEdit::tickcount, "Edit tickcount", true, EditMode_Full, true, true, 0, NULL ),
|
||||
MenuRowDef( ScreenEdit::combo, "Edit combo", true, EditMode_Full, true, true, 0, NULL ),
|
||||
MenuRowDef( ScreenEdit::label, "Edit label", true, EditMode_Full, true, true, 0, NULL ),
|
||||
MenuRowDef( ScreenEdit::warp, "Edit warp", true, EditMode_Full, true, true, 0, NULL )
|
||||
);
|
||||
|
||||
@@ -1425,6 +1435,18 @@ void ScreenEdit::InputEdit( const InputEventPlus &input, EditButton EditB )
|
||||
ScrollTo( NoteRowToBeat(iRow) );
|
||||
}
|
||||
break;
|
||||
case EDIT_BUTTON_LABEL_NEXT:
|
||||
{
|
||||
ScrollTo( GAMESTATE->m_pCurSong->m_Timing.
|
||||
GetNextLabelSegmentBeatAtBeat( GAMESTATE->m_fSongBeat ) );
|
||||
}
|
||||
break;
|
||||
case EDIT_BUTTON_LABEL_PREV:
|
||||
{
|
||||
ScrollTo( GAMESTATE->m_pCurSong->m_Timing.
|
||||
GetPreviousLabelSegmentBeatAtBeat( GAMESTATE->m_fSongBeat ) );
|
||||
}
|
||||
break;
|
||||
case EDIT_BUTTON_SNAP_NEXT:
|
||||
if( m_SnapDisplay.PrevSnapMode() )
|
||||
OnSnapModeChange();
|
||||
@@ -2644,6 +2666,17 @@ void ScreenEdit::HandleScreenMessage( const ScreenMessage SM )
|
||||
}
|
||||
SetDirty( true );
|
||||
}
|
||||
else if ( SM == SM_BackFromLabelChange )
|
||||
{
|
||||
RString sLabel = ScreenTextEntry::s_sLastAnswer;
|
||||
if ( !m_pSong->m_Timing.DoesLabelExist(sLabel) )
|
||||
{
|
||||
sLabel.Replace("=", "_");
|
||||
sLabel.Replace(",", "_");
|
||||
m_pSong->m_Timing.SetLabelAtBeat( GAMESTATE->m_fSongBeat, sLabel );
|
||||
SetDirty( true );
|
||||
}
|
||||
}
|
||||
else if ( SM == SM_BackFromWarpChange )
|
||||
{
|
||||
float fWarp = StringToFloat( ScreenTextEntry::s_sLastAnswer );
|
||||
@@ -3187,6 +3220,7 @@ void ScreenEdit::HandleMainMenuChoice( MainMenuChoice c, const vector<int> &iAns
|
||||
g_TimingDataInformation.rows[time_signature_denominator].SetOneUnthemedChoice( ssprintf("%d", pTime.GetTimeSignatureDenominatorAtBeat( fBeat ) ) );
|
||||
g_TimingDataInformation.rows[tickcount].SetOneUnthemedChoice( ssprintf("%d", pTime.GetTickcountAtBeat( fBeat ) ) );
|
||||
g_TimingDataInformation.rows[combo].SetOneUnthemedChoice( ssprintf("%d", pTime.GetComboAtBeat( fBeat ) ) );
|
||||
g_TimingDataInformation.rows[label].SetOneUnthemedChoice( pTime.GetLabelAtBeat( fBeat ).c_str() );
|
||||
g_TimingDataInformation.rows[warp].SetOneUnthemedChoice( ssprintf("%.5f", pTime.GetWarpAtBeat( fBeat ) ) );
|
||||
|
||||
EditMiniMenu( &g_TimingDataInformation, SM_BackFromTimingDataInformation );
|
||||
@@ -3618,6 +3652,7 @@ static LocalizedString ENTER_TIME_SIGNATURE_NUMERATOR_VALUE ( "ScreenEdit", "Ent
|
||||
static LocalizedString ENTER_TIME_SIGNATURE_DENOMINATOR_VALUE ( "ScreenEdit", "Enter a new Time Signature denominator value." );
|
||||
static LocalizedString ENTER_TICKCOUNT_VALUE ( "ScreenEdit", "Enter a new Tickcount value." );
|
||||
static LocalizedString ENTER_COMBO_VALUE ( "ScreenEdit", "Enter a new Combo value." );
|
||||
static LocalizedString ENTER_LABEL_VALUE ( "ScreenEdit", "Enter a new Label value." );
|
||||
static LocalizedString ENTER_WARP_VALUE ( "ScreenEdit", "Enter a new Warp value." );
|
||||
void ScreenEdit::HandleTimingDataInformationChoice( TimingDataInformationChoice c, const vector<int> &iAnswers )
|
||||
{
|
||||
@@ -3680,6 +3715,14 @@ void ScreenEdit::HandleTimingDataInformationChoice( TimingDataInformationChoice
|
||||
4
|
||||
);
|
||||
break;
|
||||
case label:
|
||||
ScreenTextEntry::TextEntry(
|
||||
SM_BackFromLabelChange,
|
||||
ENTER_LABEL_VALUE,
|
||||
ssprintf( "%s", m_pSong->m_Timing.GetLabelAtBeat( GAMESTATE->m_fSongBeat ).c_str() ),
|
||||
64
|
||||
);
|
||||
break;
|
||||
case warp:
|
||||
ScreenTextEntry::TextEntry(
|
||||
SM_BackFromWarpChange,
|
||||
|
||||
@@ -70,6 +70,9 @@ enum EditButton
|
||||
EDIT_BUTTON_SCROLL_NEXT,
|
||||
EDIT_BUTTON_SCROLL_PREV,
|
||||
|
||||
EDIT_BUTTON_LABEL_NEXT,
|
||||
EDIT_BUTTON_LABEL_PREV,
|
||||
|
||||
// These are modifiers to EDIT_BUTTON_SCROLL_*.
|
||||
EDIT_BUTTON_SCROLL_SELECT,
|
||||
|
||||
@@ -456,6 +459,7 @@ public:
|
||||
time_signature_denominator,
|
||||
tickcount,
|
||||
combo,
|
||||
label,
|
||||
warp,
|
||||
NUM_TIMING_DATA_INFORMATION_CHOICES
|
||||
};
|
||||
|
||||
+10
-8
@@ -41,7 +41,7 @@
|
||||
* @brief The internal version of the cache for StepMania.
|
||||
*
|
||||
* Increment this value to invalidate the current cache. */
|
||||
const int FILE_CACHE_VERSION = 167;
|
||||
const int FILE_CACHE_VERSION = 168;
|
||||
|
||||
/** @brief How long does a song sample last by default? */
|
||||
const float DEFAULT_MUSIC_SAMPLE_LENGTH = 12.f;
|
||||
@@ -781,10 +781,7 @@ void Song::TidyUpData()
|
||||
// If no time signature specified, assume 4/4 time for the whole song.
|
||||
if( m_Timing.m_vTimeSignatureSegments.empty() )
|
||||
{
|
||||
TimeSignatureSegment seg;
|
||||
seg.m_iStartRow = 0;
|
||||
seg.m_iNumerator = 4;
|
||||
seg.m_iDenominator = 4;
|
||||
TimeSignatureSegment seg(0, 4, 4);
|
||||
m_Timing.m_vTimeSignatureSegments.push_back( seg );
|
||||
}
|
||||
|
||||
@@ -795,9 +792,7 @@ void Song::TidyUpData()
|
||||
*/
|
||||
if( m_Timing.m_TickcountSegments.empty() )
|
||||
{
|
||||
TickcountSegment seg;
|
||||
seg.m_iStartRow = 0;
|
||||
seg.m_iTicks = 2;
|
||||
TickcountSegment seg(0, 2);
|
||||
m_Timing.m_TickcountSegments.push_back( seg );
|
||||
}
|
||||
|
||||
@@ -809,6 +804,13 @@ void Song::TidyUpData()
|
||||
seg.m_iCombo = 1;
|
||||
m_Timing.m_ComboSegments.push_back( seg );
|
||||
}
|
||||
|
||||
// Have a default label segment just in case.
|
||||
if( m_Timing.m_LabelSegments.empty() )
|
||||
{
|
||||
LabelSegment seg(0, "Song Start");
|
||||
m_Timing.m_LabelSegments.push_back( seg );
|
||||
}
|
||||
}
|
||||
|
||||
void Song::TranslateTitles()
|
||||
|
||||
+1
-1
@@ -17,7 +17,7 @@ struct lua_State;
|
||||
struct BackgroundChange;
|
||||
|
||||
/** @brief The version of the .ssc file format. */
|
||||
const static float STEPFILE_VERSION_NUMBER = 0.56f;
|
||||
const static float STEPFILE_VERSION_NUMBER = 0.57f;
|
||||
|
||||
/** @brief How many edits for this song can each profile have? */
|
||||
const int MAX_EDITS_PER_SONG_PER_PROFILE = 5;
|
||||
|
||||
+128
-6
@@ -57,6 +57,11 @@ void TimingData::AddComboSegment( const ComboSegment &seg )
|
||||
m_ComboSegments.insert( upper_bound(m_ComboSegments.begin(), m_ComboSegments.end(), seg), seg );
|
||||
}
|
||||
|
||||
void TimingData::AddLabelSegment( const LabelSegment &seg )
|
||||
{
|
||||
m_LabelSegments.insert( upper_bound(m_LabelSegments.begin(), m_LabelSegments.end(), seg), seg );
|
||||
}
|
||||
|
||||
/* Change an existing BPM segment, merge identical segments together or insert a new one. */
|
||||
void TimingData::SetBPMAtRow( int iNoteRow, float fBPM )
|
||||
{
|
||||
@@ -219,6 +224,27 @@ void TimingData::SetComboAtRow( int iRow, int iCombo )
|
||||
}
|
||||
}
|
||||
|
||||
void TimingData::SetLabelAtRow( int iRow, const RString sLabel )
|
||||
{
|
||||
unsigned i;
|
||||
for( i=0; i<m_LabelSegments.size(); i++ )
|
||||
if( m_LabelSegments[i].m_iStartRow >= iRow )
|
||||
break;
|
||||
|
||||
if( i == m_LabelSegments.size() || m_LabelSegments[i].m_iStartRow != iRow )
|
||||
{
|
||||
if( i == 0 || m_LabelSegments[i-1].m_sLabel != sLabel )
|
||||
AddLabelSegment( LabelSegment(iRow, sLabel ) );
|
||||
}
|
||||
else
|
||||
{
|
||||
if( i > 0 && ( m_LabelSegments[i-1].m_sLabel == sLabel || sLabel == "" ) )
|
||||
m_LabelSegments.erase( m_LabelSegments.begin()+i, m_LabelSegments.begin()+i+1 );
|
||||
else
|
||||
m_LabelSegments[i].m_sLabel = sLabel;
|
||||
}
|
||||
}
|
||||
|
||||
float TimingData::GetStopAtRow( int iNoteRow, bool bDelay ) const
|
||||
{
|
||||
for( unsigned i=0; i<m_StopSegments.size(); i++ )
|
||||
@@ -247,6 +273,11 @@ int TimingData::GetComboAtRow( int iNoteRow ) const
|
||||
return m_ComboSegments[GetComboSegmentIndexAtRow( iNoteRow )].m_iCombo;
|
||||
}
|
||||
|
||||
RString TimingData::GetLabelAtRow( int iRow ) const
|
||||
{
|
||||
return m_LabelSegments[GetLabelSegmentIndexAtRow( iRow )].m_sLabel;
|
||||
}
|
||||
|
||||
float TimingData::GetWarpAtRow( int iWarpRow ) const
|
||||
{
|
||||
for( unsigned i=0; i<m_WarpSegments.size(); i++ )
|
||||
@@ -384,6 +415,18 @@ int TimingData::GetComboSegmentIndexAtRow( int iRow ) const
|
||||
return static_cast<int>(i);
|
||||
}
|
||||
|
||||
int TimingData::GetLabelSegmentIndexAtRow( int iRow ) const
|
||||
{
|
||||
unsigned i;
|
||||
for( i=0; i<m_LabelSegments.size()-1; i++ )
|
||||
{
|
||||
const LabelSegment& s = m_LabelSegments[i+1];
|
||||
if( s.m_iStartRow > iRow )
|
||||
break;
|
||||
}
|
||||
return static_cast<int>(i);
|
||||
}
|
||||
|
||||
BPMSegment& TimingData::GetBPMSegmentAtRow( int iNoteRow )
|
||||
{
|
||||
static BPMSegment empty;
|
||||
@@ -422,6 +465,15 @@ ComboSegment& TimingData::GetComboSegmentAtRow( int iRow )
|
||||
return m_ComboSegments[i];
|
||||
}
|
||||
|
||||
LabelSegment& TimingData::GetLabelSegmentAtRow( int iRow )
|
||||
{
|
||||
unsigned i;
|
||||
for( i=0; i<m_LabelSegments.size()-1; i++ )
|
||||
if( m_LabelSegments[i+1].m_iStartRow > iRow )
|
||||
break;
|
||||
return m_LabelSegments[i];
|
||||
}
|
||||
|
||||
StopSegment& TimingData::GetStopSegmentAtRow( int iNoteRow, bool bDelay )
|
||||
{
|
||||
static StopSegment empty;
|
||||
@@ -444,11 +496,11 @@ WarpSegment& TimingData::GetWarpSegmentAtRow( int iRow )
|
||||
|
||||
int TimingData::GetTickcountSegmentIndexAtRow( int iRow ) const
|
||||
{
|
||||
int i;
|
||||
for (i=0; i < (int)(m_TickcountSegments.size()) - 1; i++ )
|
||||
unsigned i;
|
||||
for (i=0; i < m_TickcountSegments.size() - 1; i++ )
|
||||
if( m_TickcountSegments[i+1].m_iStartRow > iRow )
|
||||
break;
|
||||
return i;
|
||||
return static_cast<int>(i);
|
||||
}
|
||||
|
||||
TickcountSegment& TimingData::GetTickcountSegmentAtRow( int iRow )
|
||||
@@ -466,6 +518,43 @@ int TimingData::GetTickcountAtRow( int iRow ) const
|
||||
return m_TickcountSegments[GetTickcountSegmentIndexAtRow( iRow )].m_iTicks;
|
||||
}
|
||||
|
||||
float TimingData::GetPreviousLabelSegmentBeatAtRow( int iRow ) const
|
||||
{
|
||||
float backup = -1;
|
||||
for (unsigned i = 0; i < m_LabelSegments.size(); i++ )
|
||||
{
|
||||
if( m_LabelSegments[i].m_iStartRow >= iRow )
|
||||
{
|
||||
break;
|
||||
}
|
||||
backup = NoteRowToBeat(m_LabelSegments[i].m_iStartRow);
|
||||
}
|
||||
return (backup > -1) ? backup : NoteRowToBeat(iRow);
|
||||
}
|
||||
|
||||
float TimingData::GetNextLabelSegmentBeatAtRow( int iRow ) const
|
||||
{
|
||||
for (unsigned i = 0; i < m_LabelSegments.size(); i++ )
|
||||
{
|
||||
if( m_LabelSegments[i].m_iStartRow <= iRow )
|
||||
{
|
||||
continue;
|
||||
}
|
||||
return NoteRowToBeat(m_LabelSegments[i].m_iStartRow);
|
||||
}
|
||||
return NoteRowToBeat(iRow);
|
||||
}
|
||||
|
||||
bool TimingData::DoesLabelExist( RString sLabel ) const
|
||||
{
|
||||
FOREACH_CONST( LabelSegment, m_LabelSegments, seg )
|
||||
{
|
||||
if( seg->m_sLabel == sLabel )
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
void TimingData::GetBeatAndBPSFromElapsedTime( float fElapsedTime, float &fBeatOut, float &fBPSOut, bool &bFreezeOut, bool &bDelayOut, int &iWarpBeginOut, float &fWarpLengthOut ) const
|
||||
{
|
||||
fElapsedTime += PREFSMAN->m_fGlobalOffsetSeconds;
|
||||
@@ -582,9 +671,6 @@ void TimingData::GetBeatAndBPSFromElapsedTimeNoOffset( float fElapsedTime, float
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
float TimingData::GetElapsedTimeFromBeat( float fBeat ) const
|
||||
{
|
||||
return TimingData::GetElapsedTimeFromBeatNoOffset( fBeat ) - PREFSMAN->m_fGlobalOffsetSeconds;
|
||||
@@ -798,6 +884,13 @@ void TimingData::InsertRows( int iStartRow, int iRowsToAdd )
|
||||
continue;
|
||||
comb.m_iStartRow += iRowsToAdd;
|
||||
}
|
||||
for( unsigned i = 0; i < m_LabelSegments.size(); i++ )
|
||||
{
|
||||
LabelSegment &labl = m_LabelSegments[i];
|
||||
if( labl.m_iStartRow < iStartRow )
|
||||
continue;
|
||||
labl.m_iStartRow += iRowsToAdd;
|
||||
}
|
||||
|
||||
if( iStartRow == 0 )
|
||||
{
|
||||
@@ -939,6 +1032,22 @@ void TimingData::DeleteRows( int iStartRow, int iRowsToDelete )
|
||||
// After deleted region:
|
||||
comb.m_iStartRow -= iRowsToDelete;
|
||||
}
|
||||
|
||||
for( unsigned i = 0; i < m_LabelSegments.size(); i++ )
|
||||
{
|
||||
LabelSegment &labl = m_LabelSegments[i];
|
||||
|
||||
if( labl.m_iStartRow < iStartRow )
|
||||
continue;
|
||||
|
||||
if( labl.m_iStartRow < iStartRow+iRowsToDelete )
|
||||
{
|
||||
m_LabelSegments.erase( m_LabelSegments.begin()+i, m_LabelSegments.begin()+i+1 );
|
||||
--i;
|
||||
continue;
|
||||
}
|
||||
labl.m_iStartRow -= iRowsToDelete;
|
||||
}
|
||||
|
||||
this->SetBPMAtRow( iStartRow, fNewBPM );
|
||||
}
|
||||
@@ -1044,6 +1153,18 @@ public:
|
||||
LuaHelpers::CreateTableFromArray(vBPMs, L);
|
||||
return 1;
|
||||
}
|
||||
static int GetLabels( T* p, lua_State *L )
|
||||
{
|
||||
vector<RString> vLabels;
|
||||
FOREACH_CONST( LabelSegment, p->m_LabelSegments, seg )
|
||||
{
|
||||
const float fStartRow = NoteRowToBeat(seg->m_iStartRow);
|
||||
const RString sLabel = seg->m_sLabel;
|
||||
vLabels.push_back( ssprintf("%f=%s", fStartRow, sLabel.c_str()) );
|
||||
}
|
||||
LuaHelpers::CreateTableFromArray(vLabels, L);
|
||||
return 1;
|
||||
}
|
||||
static int GetBPMsAndTimes( T* p, lua_State *L )
|
||||
{
|
||||
vector<RString> vBPMs;
|
||||
@@ -1082,6 +1203,7 @@ public:
|
||||
ADD_METHOD( GetStops );
|
||||
ADD_METHOD( GetDelays );
|
||||
ADD_METHOD( GetBPMs );
|
||||
ADD_METHOD( GetLabels );
|
||||
ADD_METHOD( GetBPMsAndTimes );
|
||||
ADD_METHOD( GetActualBPM );
|
||||
ADD_METHOD( HasNegativeBPMs );
|
||||
|
||||
@@ -564,6 +564,90 @@ struct ComboSegment
|
||||
bool operator>=( const ComboSegment &other ) const { return !operator<(other); }
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief Identifies when a chart is entering a different section.
|
||||
*
|
||||
* This is meant for helping to identify different sections of a chart
|
||||
* versus relying on measures and beats alone.
|
||||
*/
|
||||
struct LabelSegment
|
||||
{
|
||||
/**
|
||||
* @brief Creates a simple Label Segment with default values.
|
||||
*
|
||||
* It is best to override the values as soon as possible.
|
||||
*/
|
||||
LabelSegment() : m_iStartRow(-1), m_sLabel("") { }
|
||||
/**
|
||||
* @brief Creates a Label Segment with the specified starting row and label.
|
||||
* @param s the starting row of this segment.
|
||||
* @param l the label for this section.
|
||||
*/
|
||||
LabelSegment( int s, RString l ): m_iStartRow(max(0, s)),
|
||||
m_sLabel(l) {}
|
||||
/**
|
||||
* @brief Creates a Label Segment with the specified starting beat and label.
|
||||
* @param s the starting beat of this segment.
|
||||
* @param l the label for this section.
|
||||
*/
|
||||
LabelSegment( float s, RString l ):
|
||||
m_iStartRow(max(0, BeatToNoteRow(s))), m_sLabel(l) {}
|
||||
/**
|
||||
* @brief The row in which the ComboSegment activates.
|
||||
*/
|
||||
int m_iStartRow;
|
||||
/**
|
||||
* @brief The label/section name for this point.
|
||||
*/
|
||||
RString m_sLabel;
|
||||
|
||||
/**
|
||||
* @brief Compares two LabelSegments to see if they are equal to each other.
|
||||
* @param other the other LabelSegment to compare to.
|
||||
* @return the equality of the two segments.
|
||||
*/
|
||||
bool operator==( const LabelSegment &other ) const
|
||||
{
|
||||
COMPARE( m_iStartRow );
|
||||
COMPARE( m_sLabel );
|
||||
return true;
|
||||
}
|
||||
/**
|
||||
* @brief Compares two LabelSegments to see if they are not equal to each other.
|
||||
* @param other the other LabelSegment to compare to.
|
||||
* @return the inequality of the two segments.
|
||||
*/
|
||||
bool operator!=( const LabelSegment &other ) const { return !operator==(other); }
|
||||
/**
|
||||
* @brief Compares two LabelSegments to see if one is less than the other.
|
||||
* @param other the other LabelSegment to compare to.
|
||||
* @return the truth/falsehood of if the first is less than the second.
|
||||
*/
|
||||
bool operator<( const LabelSegment &other ) const { return m_iStartRow < other.m_iStartRow; }
|
||||
/**
|
||||
* @brief Compares two LabelSegments to see if one is less than or equal to the other.
|
||||
* @param other the other LabelSegment to compare to.
|
||||
* @return the truth/falsehood of if the first is less or equal to than the second.
|
||||
*/
|
||||
bool operator<=( const LabelSegment &other ) const
|
||||
{
|
||||
return ( operator<(other) || operator==(other) );
|
||||
}
|
||||
/**
|
||||
* @brief Compares two LabelSegments to see if one is greater than the other.
|
||||
* @param other the other LabelSegment to compare to.
|
||||
* @return the truth/falsehood of if the first is greater than the second.
|
||||
*/
|
||||
bool operator>( const LabelSegment &other ) const { return !operator<=(other); }
|
||||
/**
|
||||
* @brief Compares two LabelSegments to see if one is greater than or equal to the other.
|
||||
* @param other the other LabelSegment to compare to.
|
||||
* @return the truth/falsehood of if the first is greater than or equal to the second.
|
||||
*/
|
||||
bool operator>=( const LabelSegment &other ) const { return !operator<(other); }
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @brief Holds data for translating beats<->seconds.
|
||||
*/
|
||||
@@ -1064,6 +1148,92 @@ public:
|
||||
*/
|
||||
void AddComboSegment( const ComboSegment &seg );
|
||||
|
||||
/**
|
||||
* @brief Retrieve the Label at the given row.
|
||||
* @param iNoteRow the row in question.
|
||||
* @return the Label.
|
||||
*/
|
||||
RString GetLabelAtRow( int iNoteRow ) const;
|
||||
/**
|
||||
* @brief Retrieve the Label at the given beat.
|
||||
* @param fBeat the beat in question.
|
||||
* @return the Label.
|
||||
*/
|
||||
RString GetLabelAtBeat( float fBeat ) const { return GetLabelAtRow( BeatToNoteRow(fBeat) ); }
|
||||
/**
|
||||
* @brief Set the row to have the new Label.
|
||||
* @param iNoteRow the row to have the new Label.
|
||||
* @param sLabel the Label.
|
||||
*/
|
||||
void SetLabelAtRow( int iNoteRow, const RString sLabel );
|
||||
/**
|
||||
* @brief Set the beat to have the new Label.
|
||||
* @param fBeat the beat to have the new Label.
|
||||
* @param sLabel the Label.
|
||||
*/
|
||||
void SetLabelAtBeat( float fBeat, const RString sLabel ) { SetLabelAtRow( BeatToNoteRow( fBeat ), sLabel ); }
|
||||
/**
|
||||
* @brief Retrieve the LabelSegment at the specified row.
|
||||
* @param iNoteRow the row that has a LabelSegment.
|
||||
* @return the LabelSegment in question.
|
||||
*/
|
||||
LabelSegment& GetLabelSegmentAtRow( int iNoteRow );
|
||||
/**
|
||||
* @brief Retrieve the LabelSegment at the specified beat.
|
||||
* @param fBeat the beat that has a LabelSegment.
|
||||
* @return the LabelSegment in question.
|
||||
*/
|
||||
LabelSegment& GetLabelSegmentAtBeat( float fBeat ) { return GetLabelSegmentAtRow( BeatToNoteRow(fBeat) ); }
|
||||
/**
|
||||
* @brief Retrieve the index of the LabelSegments at the specified row.
|
||||
* @param iNoteRow the row that has a LabelSegment.
|
||||
* @return the LabelSegment's index in question.
|
||||
*/
|
||||
int GetLabelSegmentIndexAtRow( int iNoteRow ) const;
|
||||
/**
|
||||
* @brief Retrieve the index of the LabelSegments at the specified beat.
|
||||
* @param fBeat the beat that has a LabelSegment.
|
||||
* @return the LabelSegment's index in question.
|
||||
*/
|
||||
int GetLabelSegmentIndexAtBeat( float fBeat ) const { return GetLabelSegmentIndexAtRow( BeatToNoteRow(fBeat) ); }
|
||||
/**
|
||||
* @brief Add the LabelSegment to the TimingData.
|
||||
* @param seg the new LabelSegment.
|
||||
*/
|
||||
void AddLabelSegment( const LabelSegment &seg );
|
||||
|
||||
/**
|
||||
* @brief Retrieve the previous beat that contains a LabelSegment.
|
||||
* @param iRow the present row.
|
||||
* @return the previous beat with a LabelSegment, or fBeat if there is none prior.
|
||||
*/
|
||||
float GetPreviousLabelSegmentBeatAtRow( int iRow ) const;
|
||||
/**
|
||||
* @brief Retrieve the previous beat that contains a LabelSegment.
|
||||
* @param fBeat the present beat.
|
||||
* @return the previous beat with a LabelSegment, or fBeat if there is none prior.
|
||||
*/
|
||||
float GetPreviousLabelSegmentBeatAtBeat( float fBeat ) const { return GetPreviousLabelSegmentBeatAtRow( BeatToNoteRow(fBeat) ); }
|
||||
|
||||
/**
|
||||
* @brief Determine if the requisite label already exists.
|
||||
* @param sLabel the label to check.
|
||||
* @return true if it exists, false otherwise. */
|
||||
bool DoesLabelExist( RString sLabel ) const;
|
||||
|
||||
/**
|
||||
* @brief Retrieve the next beat that contains a LabelSegment.
|
||||
* @param iRow the present row.
|
||||
* @return the next beat with a LabelSegment, or fBeat if there is none ahead.
|
||||
*/
|
||||
float GetNextLabelSegmentBeatAtRow( int iRow ) const;
|
||||
/**
|
||||
* @brief Retrieve the previous beat that contains a LabelSegment.
|
||||
* @param fBeat the present beat.
|
||||
* @return the next beat with a LabelSegment, or fBeat if there is none ahead.
|
||||
*/
|
||||
float GetNextLabelSegmentBeatAtBeat( float fBeat ) const { return GetNextLabelSegmentBeatAtRow( BeatToNoteRow(fBeat) ); }
|
||||
|
||||
void MultiplyBPMInBeatRange( int iStartIndex, int iEndIndex, float fFactor );
|
||||
|
||||
void NoteRowToMeasureAndBeat( int iNoteRow, int &iMeasureIndexOut, int &iBeatIndexOut, int &iRowsRemainder ) const;
|
||||
@@ -1131,6 +1301,8 @@ public:
|
||||
COMPARE( m_ComboSegments.size() );
|
||||
for( unsigned i=0; i<m_ComboSegments.size(); i++ )
|
||||
COMPARE( m_ComboSegments[i] );
|
||||
for( unsigned i=0; i<m_LabelSegments.size(); i++ )
|
||||
COMPARE( m_LabelSegments[i] );
|
||||
COMPARE( m_fBeat0OffsetInSeconds );
|
||||
return true;
|
||||
}
|
||||
@@ -1178,6 +1350,10 @@ public:
|
||||
* @brief The collection of ComboSegments.
|
||||
*/
|
||||
vector<ComboSegment> m_ComboSegments;
|
||||
/**
|
||||
* @brief The collection of LabelSegments.
|
||||
*/
|
||||
vector<LabelSegment> m_LabelSegments;
|
||||
/**
|
||||
* @brief The initial offset of a song.
|
||||
*/
|
||||
|
||||
Reference in New Issue
Block a user