Mission accomplished: #COMBOS tag in sm-ssc.

This tag will not show up on saved SM files.
Let's not mess with that format any more than needed.
This commit is contained in:
Jason Felds
2011-03-05 02:03:59 -05:00
16 changed files with 320 additions and 20 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.55] - Wolfman2000
* Add #COMBOS tag to the Song and Steps (does nothing here).
[v0.54] - Wolfman2000
* Add #ATTACKS tag to the Notedata sections. Right now it does nothing.
+4
View File
@@ -13,6 +13,10 @@ _____________________________________________________________________________
sm-ssc v1.2.3 | 201103??
--------------------------------------------------------------------------------
20110305
--------
* Added #COMBOS tag to the .ssc format. [Wolfman2000]
20110302
--------
* [ScreenGameplaySyncMachine] Allow themers to use either .ssc or .sm files. [AJ]
+2
View File
@@ -842,6 +842,7 @@ Edit time signature=Edit time signature (not working yet)
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
Editor options=Options
EditorShowBGChangesPlay=Show Backgrounds
Effect=Effect
@@ -1207,6 +1208,7 @@ Enter a new Delay value.=Enter a new Delay value.
Enter a new Time Signature numerator value.=Enter the number of beats per measure.
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 artist transliteration.=Enter a new artist transliteration.
Enter a new artist.=Enter a new artist.
Enter a new genre.=Enter a new genre.
+3
View File
@@ -956,18 +956,21 @@ StopColor=color("0.8,0.8,0,1")
DelayColor=color("0,0.8,0.8,1")
TimeSignatureColor=color("1,0.55,0,1")
TickcountColor=color("0,1,0,1")
ComboColor=color("0.55,1,0,1")
#
BPMIsLeftSide=true
StopIsLeftSide=true
DelayIsLeftSide=true
TimeSignatureIsLeftSide=true
TickcountIsLeftSide=false
ComboIsLeftSide=false
#
BPMOffsetX=60
StopOffsetX=10
DelayOffsetX=10
TimeSignatureOffsetX=30
TickcountOffsetX=10
ComboOffsetX=30
[PlayerStageStats]
# Original CVS Grading
+33
View File
@@ -424,16 +424,19 @@ static ThemeMetric<RageColor> STOP_COLOR ( "NoteField", "StopColor" );
static ThemeMetric<RageColor> DELAY_COLOR ( "NoteField", "DelayColor" );
static ThemeMetric<RageColor> TIME_SIGNATURE_COLOR ( "NoteField", "TimeSignatureColor" );
static ThemeMetric<RageColor> TICKCOUNT_COLOR ( "NoteField", "TickcountColor" );
static ThemeMetric<RageColor> COMBO_COLOR ( "NoteField", "ComboColor" );
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" );
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<float> BPM_OFFSETX ( "NoteField", "BPMOffsetX" );
static ThemeMetric<float> STOP_OFFSETX ( "NoteField", "StopOffsetX" );
static ThemeMetric<float> DELAY_OFFSETX ( "NoteField", "DelayOffsetX" );
static ThemeMetric<float> TIME_SIGNATURE_OFFSETX ( "NoteField", "TimeSignatureOffsetX" );
static ThemeMetric<float> TICKCOUNT_OFFSETX ( "NoteField", "TickcountOffsetX" );
static ThemeMetric<float> COMBO_OFFSETX ( "NoteField", "ComboOffsetX" );
void NoteField::DrawBPMText( const float fBeat, const float fBPM )
{
@@ -512,6 +515,23 @@ void NoteField::DrawTickcountText( const float fBeat, int iTicks )
m_textMeasureNumber.Draw();
}
void NoteField::DrawComboText( const float fBeat, int iCombo )
{
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 = COMBO_OFFSETX * fZoom;
m_textMeasureNumber.SetZoom( fZoom );
m_textMeasureNumber.SetHorizAlign( COMBO_IS_LEFT_SIDE ? align_right : align_left );
m_textMeasureNumber.SetDiffuse( COMBO_COLOR );
m_textMeasureNumber.SetGlow( RageColor(1,1,1,RageFastCos(RageTimer::GetTimeSinceStartFast()*2)/2+0.5f) );
m_textMeasureNumber.SetText( ssprintf("%d", iCombo) );
m_textMeasureNumber.SetXY( (COMBO_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 );
@@ -776,6 +796,19 @@ void NoteField::DrawPrimitives()
DrawTickcountText( fBeat, tTickcountSegments[i].m_iTicks );
}
}
// Combo text
const vector<ComboSegment> &tComboSegments = GAMESTATE->m_pCurSong->m_Timing.m_ComboSegments;
for( unsigned i=0; i<tComboSegments.size(); i++ )
{
if( tComboSegments[i].m_iStartRow >= iFirstRowToDraw &&
tComboSegments[i].m_iStartRow <= iLastRowToDraw)
{
float fBeat = NoteRowToBeat(tComboSegments[i].m_iStartRow);
if( IS_ON_SCREEN(fBeat) )
DrawComboText( fBeat, tComboSegments[i].m_iCombo );
}
}
// todo: add warp text -aj
+1
View File
@@ -59,6 +59,7 @@ protected:
void DrawFreezeText( const float fBeat, const float fBPM, const float bDelay );
void DrawTimeSignatureText( const float fBeat, int iNumerator, int iDenominator );
void DrawTickcountText( const float fBeat, int iTicks );
void DrawComboText( const float fBeat, int iCombo );
void DrawAttackText( const float fBeat, const Attack &attack );
void DrawBGChangeText( const float fBeat, const RString sNewBGName );
float GetWidth() const;
+1 -2
View File
@@ -565,7 +565,7 @@ bool SSCLoader::LoadFromSSCFile( const RString &sPath, Song &out, bool bFromCach
}
else if( sValueName=="COMBOS" )
{/*
{
vector<RString> arrayComboExpressions;
split( sParams[1], ",", arrayComboExpressions );
@@ -584,7 +584,6 @@ bool SSCLoader::LoadFromSSCFile( const RString &sPath, Song &out, bool bFromCach
ComboSegment new_seg( BeatToNoteRow( fComboBeat ), iCombos );
out.m_Timing.AddComboSegment( new_seg );
}
*/
}
/* The following are cache tags. Never fill their values
+4 -4
View File
@@ -181,19 +181,19 @@ static void WriteGlobalTags( RageFile &f, const Song &out )
}
f.PutLine( ";" );
/*
ASSERT( !out.m_Timing.m_ComboSegments.empty() );
f.Write( "#COMBOS:" );
for( unsigned i=0; i<out.m_Timing.m_ComboSegments.size(); i++ )
{
const ComboSegment &cs = out.m_Timing.m_ComboSegments[i];
f.PutLine( ssprintf( "%.6f=%d", NoteRowToBeat(cs.m_iStartRow), cs.m_iComboFactor ) );
f.PutLine( ssprintf( "%.6f=%d", NoteRowToBeat(cs.m_iStartRow), cs.m_iCombo ) );
if( i != out.m_Timing.m_ComboSegments.size()-1 )
f.Write( "," );
}
f.PutLine( ";" );
*/
FOREACH_BackgroundLayer( b )
{
if( b==0 )
@@ -302,7 +302,7 @@ static RString GetSSCNoteData( const Song &song, const Steps &in, bool bSavingCa
lines.push_back( "#TIMESIGNATURES:;" );
lines.push_back( "#TICKCOUNTS:;" );
lines.push_back( "#ATTACKS:;" );
// lines.push_back( "#COMBOS:;" );
lines.push_back( "#COMBOS:;" );
/*
vector<RString> asBPMValues;
+13 -8
View File
@@ -18,6 +18,7 @@
#include "Game.h"
#include "Style.h"
#include "Song.h"
#include "TimingData.h"
#include "NoteDataWithScoring.h"
@@ -577,7 +578,7 @@ void ScoreKeeperNormal::HandleHoldCheckpointScore( const NoteData &nd, int iRow,
}
HandleTapNoteScoreInternal( iNumHoldsMissedThisRow == 0? TNS_CheckpointHit:TNS_CheckpointMiss, TNS_CheckpointHit );
HandleComboInternal( iNumHoldsHeldThisRow, 0, iNumHoldsMissedThisRow );
HandleComboInternal( iNumHoldsHeldThisRow, 0, iNumHoldsMissedThisRow, iRow );
}
void ScoreKeeperNormal::HandleTapNoteScoreInternal( TapNoteScore tns, TapNoteScore maximum )
@@ -593,7 +594,7 @@ void ScoreKeeperNormal::HandleTapNoteScoreInternal( TapNoteScore tns, TapNoteSco
m_pPlayerStageStats->m_iCurPossibleDancePoints += TapNoteScoreToDancePoints( maximum );
}
void ScoreKeeperNormal::HandleComboInternal( int iNumHitContinueCombo, int iNumHitMaintainCombo, int iNumBreakCombo )
void ScoreKeeperNormal::HandleComboInternal( int iNumHitContinueCombo, int iNumHitMaintainCombo, int iNumBreakCombo, int iRow )
{
// Regular combo
if( m_ComboIsPerRow )
@@ -610,7 +611,9 @@ void ScoreKeeperNormal::HandleComboInternal( int iNumHitContinueCombo, int iNumH
if( iNumBreakCombo == 0 )
{
m_pPlayerStageStats->m_iCurCombo += iNumHitContinueCombo;
TimingData td = GAMESTATE->m_pCurSong->m_Timing;
int multiplier = ( iRow == -1 ? 1 : td.GetComboSegmentAtRow( iRow ).m_iCombo );
m_pPlayerStageStats->m_iCurCombo += iNumHitContinueCombo * multiplier;
}
else
{
@@ -619,7 +622,7 @@ void ScoreKeeperNormal::HandleComboInternal( int iNumHitContinueCombo, int iNumH
}
}
void ScoreKeeperNormal::HandleRowComboInternal( TapNoteScore tns, int iNumTapsInRow )
void ScoreKeeperNormal::HandleRowComboInternal( TapNoteScore tns, int iNumTapsInRow, int iRow )
{
if( m_ComboIsPerRow )
{
@@ -628,7 +631,9 @@ void ScoreKeeperNormal::HandleRowComboInternal( TapNoteScore tns, int iNumTapsIn
if ( tns >= m_MinScoreToContinueCombo )
{
m_pPlayerStageStats->m_iCurMissCombo = 0;
m_pPlayerStageStats->m_iCurCombo += iNumTapsInRow;
TimingData td = GAMESTATE->m_pCurSong->m_Timing;
int multiplier = ( iRow == -1 ? 1 : td.GetComboSegmentAtRow( iRow ).m_iCombo );
m_pPlayerStageStats->m_iCurCombo += iNumTapsInRow * multiplier;
}
else if ( tns < m_MinScoreToMaintainCombo )
{
@@ -673,14 +678,14 @@ void ScoreKeeperNormal::HandleTapRowScore( const NoteData &nd, int iRow )
TapNoteScore scoreOfLastTap = NoteDataWithScoring::LastTapNoteWithResult( nd, iRow ).result.tns;
HandleTapNoteScoreInternal( scoreOfLastTap, TNS_W1 );
if ( GAMESTATE->GetCurrentGame()->m_bCountNotesSeparately )
{
HandleComboInternal( iNumHitContinueCombo, iNumHitMaintainCombo, iNumBreakCombo );
HandleComboInternal( iNumHitContinueCombo, iNumHitMaintainCombo, iNumBreakCombo, iRow );
}
else
{
HandleRowComboInternal( scoreOfLastTap, iNumTapsInRow ); //This should work?
HandleRowComboInternal( scoreOfLastTap, iNumTapsInRow, iRow ); //This should work?
}
if( m_pPlayerState->m_PlayerNumber != PLAYER_INVALID )
+2 -2
View File
@@ -114,8 +114,8 @@ public:
private:
void HandleTapNoteScoreInternal( TapNoteScore tns, TapNoteScore maximum );
void HandleComboInternal( int iNumHitContinueCombo, int iNumHitMaintainCombo, int iNumBreakCombo );
void HandleRowComboInternal( TapNoteScore tns, int iNumTapsInRow );
void HandleComboInternal( int iNumHitContinueCombo, int iNumHitMaintainCombo, int iNumBreakCombo, int iRow = -1 );
void HandleRowComboInternal( TapNoteScore tns, int iNumTapsInRow, int iRow = -1 );
void GetRowCounts( const NoteData &nd, int iRow, int &iNumHitContinueCombo, int &iNumHitMaintainCombo, int &iNumBreakCombo );
};
+22 -1
View File
@@ -78,6 +78,7 @@ AutoScreenMessage( SM_BackFromDelayChange );
AutoScreenMessage( SM_BackFromTimeSignatureNumeratorChange );
AutoScreenMessage( SM_BackFromTimeSignatureDenominatorChange );
AutoScreenMessage( SM_BackFromTickcountChange );
AutoScreenMessage( SM_BackFromComboChange );
AutoScreenMessage( SM_DoSaveAndExit );
AutoScreenMessage( SM_DoExit );
AutoScreenMessage( SM_SaveSuccessful );
@@ -578,7 +579,8 @@ static MenuDef g_TimingDataInformation(
MenuRowDef( ScreenEdit::delay, "Edit delay", true, EditMode_Full, true, true, 0, NULL ),
MenuRowDef( ScreenEdit::time_signature_numerator, "Edit time signature (top)", true, EditMode_Full, true, true, 0, NULL ),
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::tickcount, "Edit tickcount", true, EditMode_Full, true, true, 0, NULL ),
MenuRowDef( ScreenEdit::combo, "Edit combo", true, EditMode_Full, true, true, 0, NULL )
);
enum { song_bganimation, song_movie, song_bitmap, global_bganimation, global_movie, global_movie_song_group, global_movie_song_group_and_genre, dynamic_random, baked_random, none };
@@ -2651,6 +2653,15 @@ void ScreenEdit::HandleScreenMessage( const ScreenMessage SM )
}
SetDirty( true );
}
else if ( SM == SM_BackFromComboChange )
{
int iCombo = atoi( ScreenTextEntry::s_sLastAnswer );
if ( iCombo >= 0 )
{
m_pSong->m_Timing.SetComboAtBeat( GAMESTATE->m_fSongBeat, iCombo );
}
SetDirty( true );
}
else if( SM == SM_BackFromBGChange )
{
HandleBGChangeChoice( (BGChangeChoice)ScreenMiniMenu::s_iLastRowCode, ScreenMiniMenu::s_viLastAnswers );
@@ -3169,6 +3180,7 @@ void ScreenEdit::HandleMainMenuChoice( MainMenuChoice c, const vector<int> &iAns
g_TimingDataInformation.rows[time_signature_numerator].SetOneUnthemedChoice( ssprintf("%d", pTime.GetTimeSignatureNumeratorAtBeat( fBeat ) ) );
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 ) ) );
EditMiniMenu( &g_TimingDataInformation, SM_BackFromTimingDataInformation );
}
@@ -3620,6 +3632,7 @@ static LocalizedString ENTER_DELAY_VALUE ( "ScreenEdit", "Enter a new Delay va
static LocalizedString ENTER_TIME_SIGNATURE_NUMERATOR_VALUE ( "ScreenEdit", "Enter a new Time Signature numerator value." );
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." );
void ScreenEdit::HandleTimingDataInformationChoice( TimingDataInformationChoice c, const vector<int> &iAnswers )
{
switch( c )
@@ -3676,6 +3689,14 @@ void ScreenEdit::HandleTimingDataInformationChoice( TimingDataInformationChoice
2
);
break;
case combo:
ScreenTextEntry::TextEntry(
SM_BackFromComboChange,
ENTER_COMBO_VALUE,
ssprintf( "%d", m_pSong->m_Timing.GetComboAtBeat( GAMESTATE->m_fSongBeat ) ),
4
);
break;
}
}
+1
View File
@@ -448,6 +448,7 @@ public:
time_signature_numerator,
time_signature_denominator,
tickcount,
combo,
NUM_TIMING_DATA_INFORMATION_CHOICES
};
+10 -1
View File
@@ -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 = 165;
const int FILE_CACHE_VERSION = 166;
/** @brief How long does a song sample last by default? */
const float DEFAULT_MUSIC_SAMPLE_LENGTH = 12.f;
@@ -782,6 +782,15 @@ void Song::TidyUpData()
seg.m_iTicks = 2;
m_Timing.m_TickcountSegments.push_back( seg );
}
// Have a default combo segment of one just in case.
if( m_Timing.m_ComboSegments.empty() )
{
ComboSegment seg;
seg.m_iStartRow = 0;
seg.m_iCombo = 1;
m_Timing.m_ComboSegments.push_back( seg );
}
}
void Song::TranslateTitles()
+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.54f;
const static float STEPFILE_VERSION_NUMBER = 0.55f;
/** @brief How many edits for this song can each profile have? */
const int MAX_EDITS_PER_SONG_PER_PROFILE = 5;
+83
View File
@@ -52,6 +52,11 @@ void TimingData::AddTickcountSegment( const TickcountSegment &seg )
m_TickcountSegments.insert( upper_bound(m_TickcountSegments.begin(), m_TickcountSegments.end(), seg), seg );
}
void TimingData::AddComboSegment( const ComboSegment &seg )
{
m_ComboSegments.insert( upper_bound(m_ComboSegments.begin(), m_ComboSegments.end(), seg), seg );
}
/* Change an existing BPM segment, merge identical segments together or insert a new one. */
void TimingData::SetBPMAtRow( int iNoteRow, float fBPM )
{
@@ -176,6 +181,27 @@ void TimingData::SetTickcountAtRow( int iRow, int iTicks )
}
}
void TimingData::SetComboAtRow( int iRow, int iCombo )
{
unsigned i;
for( i=0; i<m_ComboSegments.size(); i++ )
if( m_ComboSegments[i].m_iStartRow >= iRow )
break;
if( i == m_ComboSegments.size() || m_ComboSegments[i].m_iStartRow != iRow )
{
if( i == 0 || m_ComboSegments[i-1].m_iCombo != iCombo )
AddComboSegment( ComboSegment(iRow, iCombo ) );
}
else
{
if( i > 0 && m_ComboSegments[i-1].m_iCombo == iCombo )
m_ComboSegments.erase( m_ComboSegments.begin()+i, m_ComboSegments.begin()+i+1 );
else
m_ComboSegments[i].m_iCombo = iCombo;
}
}
float TimingData::GetStopAtRow( int iNoteRow, bool bDelay ) const
{
for( unsigned i=0; i<m_StopSegments.size(); i++ )
@@ -199,6 +225,11 @@ float TimingData::GetDelayAtRow( int iRow ) const
return GetStopAtRow( iRow, true );
}
int TimingData::GetComboAtRow( int iNoteRow ) const
{
return m_ComboSegments[GetComboSegmentIndexAtRow( iNoteRow )].m_iCombo;
}
int TimingData::GetWarpToRow( int iWarpBeginRow ) const
{
for( unsigned i=0; i<m_WarpSegments.size(); i++ )
@@ -309,6 +340,18 @@ int TimingData::GetTimeSignatureDenominatorAtRow( int iRow )
return GetTimeSignatureSegmentAtRow( iRow ).m_iDenominator;
}
int TimingData::GetComboSegmentIndexAtRow( int iRow ) const
{
unsigned i;
for( i=0; i<m_ComboSegments.size()-1; i++ )
{
const ComboSegment& s = m_ComboSegments[i+1];
if( s.m_iStartRow > iRow )
break;
}
return (int)i;
}
BPMSegment& TimingData::GetBPMSegmentAtRow( int iNoteRow )
{
static BPMSegment empty;
@@ -319,6 +362,15 @@ BPMSegment& TimingData::GetBPMSegmentAtRow( int iNoteRow )
return m_BPMSegments[i];
}
ComboSegment& TimingData::GetComboSegmentAtRow( int iRow )
{
unsigned i;
for( i=0; i<m_ComboSegments.size()-1; i++ )
if( m_ComboSegments[i+1].m_iStartRow > iRow )
break;
return m_ComboSegments[i];
}
StopSegment& TimingData::GetStopSegmentAtRow( int iNoteRow, bool bDelay )
{
static StopSegment empty;
@@ -487,16 +539,19 @@ void TimingData::GetBeatAndBPSFromElapsedTimeNoOffset( float fElapsedTime, float
vector<WarpSegment> vWS = m_WarpSegments;
vector<TimeSignatureSegment> vTSS = m_vTimeSignatureSegments;
vector<TickcountSegment> vTS = m_TickcountSegments;
vector<ComboSegment> vCS = m_ComboSegments;
sort( vBPMS.begin(), vBPMS.end() );
sort( vSS.begin(), vSS.end() );
sort( vWS.begin(), vWS.end() );
sort( vTSS.begin(), vTSS.end() );
sort( vTS.begin(), vTS.end() );
sort( vCS.begin(), vCS.end() );
ASSERT_M( vBPMS == m_BPMSegments, "The BPM segments were not sorted!" );
ASSERT_M( vSS == m_StopSegments, "The Stop segments were not sorted!" );
ASSERT_M( vWS == m_WarpSegments, "The Warp segments were not sorted!" );
ASSERT_M( vTSS == m_vTimeSignatureSegments, "The Time Signature segments were not sorted!" );
ASSERT_M( vTS == m_TickcountSegments, "The Tickcount segments were not sorted!" );
ASSERT_M( vCS == m_ComboSegments, "The Combo segments were not sorted!" );
FAIL_M( ssprintf("Failed to find the appropriate segment for elapsed time %f.", fTime) );
}
@@ -619,6 +674,14 @@ void TimingData::InsertRows( int iStartRow, int iRowsToAdd )
continue;
tick.m_iStartRow += iRowsToAdd;
}
for( unsigned i = 0; i < m_ComboSegments.size(); i++ )
{
ComboSegment &comb = m_ComboSegments[i];
if( comb.m_iStartRow < iStartRow )
continue;
comb.m_iStartRow += iRowsToAdd;
}
if( iStartRow == 0 )
{
@@ -720,6 +783,26 @@ void TimingData::DeleteRows( int iStartRow, int iRowsToDelete )
// After deleted region:
tick.m_iStartRow -= iRowsToDelete;
}
for( unsigned i = 0; i < m_ComboSegments.size(); i++ )
{
ComboSegment &comb = m_ComboSegments[i];
// Before deleted region:
if( comb.m_iStartRow < iStartRow )
continue;
// Inside deleted region:
if( comb.m_iStartRow < iStartRow+iRowsToDelete )
{
m_ComboSegments.erase( m_ComboSegments.begin()+i, m_ComboSegments.begin()+i+1 );
--i;
continue;
}
// After deleted region:
comb.m_iStartRow -= iRowsToDelete;
}
this->SetBPMAtRow( iStartRow, fNewBPM );
}
+137 -1
View File
@@ -478,6 +478,82 @@ struct TickcountSegment
*/
bool operator>=( const TickcountSegment &other ) const { return !operator<(other); }
};
/**
* @brief Identifies when a chart is to have a different combo multiplier value.
*
* Admitedly, this would primarily be used for mission mode style charts. However,
* it can have its place during normal gameplay.
*/
struct ComboSegment
{
/**
* @brief Creates a simple Combo Segment with default values.
*
* It is best to override the values as soon as possible.
*/
ComboSegment() : m_iStartRow(-1), m_iCombo(1) { }
/**
* @brief Creates a Combo Segment with the specified starting row and combo factor.
* @param s the starting row of this segment.
* @param t the amount the combo increases on a succesful hit.
*/
ComboSegment( int s, int t ){ m_iStartRow = max( 0, s ); m_iCombo = max( 1, t ); }
/**
* @brief The row in which the ComboSegment activates.
*/
int m_iStartRow;
/**
* @brief The amount the combo increases at this point.
*/
int m_iCombo;
/**
* @brief Compares two ComboSegments to see if they are equal to each other.
* @param other the other ComboSegment to compare to.
* @return the equality of the two segments.
*/
bool operator==( const ComboSegment &other ) const
{
COMPARE( m_iStartRow );
COMPARE( m_iCombo );
return true;
}
/**
* @brief Compares two ComboSegments to see if they are not equal to each other.
* @param other the other ComboSegment to compare to.
* @return the inequality of the two segments.
*/
bool operator!=( const ComboSegment &other ) const { return !operator==(other); }
/**
* @brief Compares two ComboSegments to see if one is less than the other.
* @param other the other ComboSegment to compare to.
* @return the truth/falsehood of if the first is less than the second.
*/
bool operator<( const ComboSegment &other ) const { return m_iStartRow < other.m_iStartRow; }
/**
* @brief Compares two ComboSegments to see if one is less than or equal to the other.
* @param other the other ComboSegment to compare to.
* @return the truth/falsehood of if the first is less or equal to than the second.
*/
bool operator<=( const ComboSegment &other ) const
{
return ( operator<(other) || operator==(other) );
}
/**
* @brief Compares two ComboSegments to see if one is greater than the other.
* @param other the other ComboSegment to compare to.
* @return the truth/falsehood of if the first is greater than the second.
*/
bool operator>( const ComboSegment &other ) const { return !operator<=(other); }
/**
* @brief Compares two ComboSegments to see if one is greater than or equal to the other.
* @param other the other ComboSegment to compare to.
* @return the truth/falsehood of if the first is greater than or equal to the second.
*/
bool operator>=( const ComboSegment &other ) const { return !operator<(other); }
};
/**
* @brief Holds data for translating beats<->seconds.
*/
@@ -872,6 +948,60 @@ public:
*/
void AddTickcountSegment( const TickcountSegment &seg );
/**
* @brief Retrieve the Combo at the given row.
* @param iNoteRow the row in question.
* @return the Combo.
*/
int GetComboAtRow( int iNoteRow ) const;
/**
* @brief Retrieve the Combo at the given beat.
* @param fBeat the beat in question.
* @return the Combo.
*/
int GetComboAtBeat( float fBeat ) const { return GetComboAtRow( BeatToNoteRow(fBeat) ); }
/**
* @brief Set the row to have the new Combo.
* @param iNoteRow the row to have the new Combo.
* @param iTicks the Combo.
*/
void SetComboAtRow( int iNoteRow, int iCombo );
/**
* @brief Set the beat to have the new Combo.
* @param fBeat the beat to have the new Combo.
* @param iTicks the Combo.
*/
void SetComboAtBeat( float fBeat, int iCombo ) { SetComboAtRow( BeatToNoteRow( fBeat ), iCombo ); }
/**
* @brief Retrieve the ComboSegment at the specified row.
* @param iNoteRow the row that has a ComboSegment.
* @return the ComboSegment in question.
*/
ComboSegment& GetComboSegmentAtRow( int iNoteRow );
/**
* @brief Retrieve the ComboSegment at the specified beat.
* @param fBeat the beat that has a ComboSegment.
* @return the ComboSegment in question.
*/
ComboSegment& GetComboSegmentAtBeat( float fBeat ) { return GetComboSegmentAtRow( BeatToNoteRow(fBeat) ); }
/**
* @brief Retrieve the index of the ComboSegments at the specified row.
* @param iNoteRow the row that has a ComboSegment.
* @return the ComboSegment's index in question.
*/
int GetComboSegmentIndexAtRow( int iNoteRow ) const;
/**
* @brief Retrieve the index of the ComboSegments at the specified beat.
* @param fBeat the beat that has a ComboSegment.
* @return the ComboSegment's index in question.
*/
int GetComboSegmentIndexAtBeat( float fBeat ) const { return GetComboSegmentIndexAtRow( BeatToNoteRow(fBeat) ); }
/**
* @brief Add the ComboSegment to the TimingData.
* @param seg the new ComboSegment.
*/
void AddComboSegment( const ComboSegment &seg );
void MultiplyBPMInBeatRange( int iStartIndex, int iEndIndex, float fFactor );
void NoteRowToMeasureAndBeat( int iNoteRow, int &iMeasureIndexOut, int &iBeatIndexOut, int &iRowsRemainder ) const;
@@ -936,6 +1066,9 @@ public:
COMPARE( m_TickcountSegments.size() );
for( unsigned i=0; i<m_TickcountSegments.size(); i++ )
COMPARE( m_TickcountSegments[i] );
COMPARE( m_ComboSegments.size() );
for( unsigned i=0; i<m_ComboSegments.size(); i++ )
COMPARE( m_ComboSegments[i] );
COMPARE( m_fBeat0OffsetInSeconds );
return true;
}
@@ -979,6 +1112,10 @@ public:
* @brief The collection of TickcountSegments.
*/
vector<TickcountSegment> m_TickcountSegments;
/**
* @brief The collection of ComboSegments.
*/
vector<ComboSegment> m_ComboSegments;
/**
* @brief The initial offset of a song.
*/
@@ -999,7 +1136,6 @@ public:
/**
* @file
* @author Chris Danford, Glenn Maynard (c) 2001-2004
*
* @section LICENSE
* All rights reserved.
*