Speed Segments Satisfied.

This commit is contained in:
Jason Felds
2011-05-31 15:27:27 -04:00
parent 30dc1d4e92
commit f9eb6fb387
9 changed files with 206 additions and 179 deletions
+4 -3
View File
@@ -984,11 +984,12 @@ void NoteField::DrawPrimitives()
{
FOREACH_CONST( SpeedSegment, timing.m_SpeedSegments, seg )
{
if( seg->m_iStartRow >= iFirstRowToDraw && seg->m_iStartRow <= iLastRowToDraw )
if( seg->GetRow() >= iFirstRowToDraw && seg->GetRow() <= iLastRowToDraw )
{
float fBeat = NoteRowToBeat(seg->m_iStartRow);
float fBeat = seg->GetBeat();
if( IS_ON_SCREEN(fBeat) )
DrawSpeedText( fBeat, seg->m_fPercent, seg->m_fWait, seg->m_usMode );
DrawSpeedText(fBeat, seg->GetRatio(),
seg->GetLength(), seg->GetUnit() );
}
}
}
+4 -3
View File
@@ -340,7 +340,8 @@ void SMALoader::ProcessSpeeds( TimingData &out, const int iRowsPerBeat, const RS
unsigned short tmp = ( (vs2[2].find("s") || vs2[2].find("S") )
? 1 : 0);
SpeedSegment seg( fBeat, StringToFloat( vs2[1] ), StringToFloat( vs2[2] ), tmp);
SpeedSegment seg(fBeat, StringToFloat( vs2[1] ), StringToFloat(vs2[2]));
seg.SetUnit(tmp);
if( fBeat < 0 )
{
@@ -348,9 +349,9 @@ void SMALoader::ProcessSpeeds( TimingData &out, const int iRowsPerBeat, const RS
continue;
}
if( seg.m_fWait < 0 )
if( seg.GetLength() < 0 )
{
LOG->UserLog( "Song file", "(UNKNOWN)", "has an speed change with beat %f, fWait %f.", fBeat, seg.m_fWait );
LOG->UserLog( "Song file", "(UNKNOWN)", "has an speed change with beat %f, length %f.", fBeat, seg.GetLength() );
continue;
}
+4 -3
View File
@@ -158,7 +158,8 @@ void SSCLoader::ProcessSpeeds( TimingData &out, const RString sParam )
const float fBeat = StringToFloat( vs2[0] );
SpeedSegment seg( fBeat, StringToFloat( vs2[1] ), StringToFloat( vs2[2] ), static_cast<unsigned short>(StringToInt(vs2[3])));
SpeedSegment seg( fBeat, StringToFloat( vs2[1] ), StringToFloat( vs2[2] ));
seg.SetUnit(StringToInt(vs2[3]));
if( fBeat < 0 )
{
@@ -166,9 +167,9 @@ void SSCLoader::ProcessSpeeds( TimingData &out, const RString sParam )
continue;
}
if( seg.m_fWait < 0 )
if( seg.GetLength() < 0 )
{
LOG->UserLog( "Song file", "(UNKNOWN)", "has an speed change with beat %f, fWait %f.", fBeat, seg.m_fWait );
LOG->UserLog( "Song file", "(UNKNOWN)", "has an speed change with beat %f, length %f.", fBeat, seg.GetLength() );
continue;
}
+1 -1
View File
@@ -134,7 +134,7 @@ static void GetTimingTags( vector<RString> &lines, TimingData timing, bool bIsSo
// Song Timing should only have the initial value.
w.Init( "SPEEDS" );
FOREACH_CONST( SpeedSegment, timing.m_SpeedSegments, ss )
w.Write( ss->m_iStartRow, ss->m_fPercent, ss->m_fWait, ss->m_usMode );
w.Write( ss->GetRow(), ss->GetRatio(), ss->GetLength(), ss->GetUnit() );
w.Finish();
w.Init( "SCROLLS" );
+3 -3
View File
@@ -3224,7 +3224,7 @@ void ScreenEdit::DisplayTimingMenu()
{
float fBeat = GetBeat();
TimingData &pTime = GetAppropriateTiming();
bool bHasSpeedOnThisRow = pTime.GetSpeedSegmentAtBeat( fBeat ).m_iStartRow == BeatToNoteRow( fBeat );
bool bHasSpeedOnThisRow = pTime.GetSpeedSegmentAtBeat( fBeat ).GetBeat() == fBeat;
g_TimingDataInformation.rows[beat_0_offset].SetOneUnthemedChoice( ssprintf("%.5f", pTime.m_fBeat0OffsetInSeconds) );
g_TimingDataInformation.rows[bpm].SetOneUnthemedChoice( ssprintf("%.5f", pTime.GetBPMAtBeat( fBeat ) ) );
@@ -4015,7 +4015,7 @@ void ScreenEdit::HandleTimingDataInformationChoice( TimingDataInformationChoice
ScreenTextEntry::TextEntry(
SM_BackFromSpeedPercentChange,
ENTER_SPEED_PERCENT_VALUE,
ssprintf( "%.5f", GetAppropriateTiming().GetSpeedSegmentAtBeat( GetBeat() ).m_fPercent ),
ssprintf( "%.5f", GetAppropriateTiming().GetSpeedSegmentAtBeat( GetBeat() ).GetRatio() ),
10
);
break;
@@ -4031,7 +4031,7 @@ void ScreenEdit::HandleTimingDataInformationChoice( TimingDataInformationChoice
ScreenTextEntry::TextEntry(
SM_BackFromSpeedWaitChange,
ENTER_SPEED_WAIT_VALUE,
ssprintf( "%.5f", GetAppropriateTiming().GetSpeedSegmentAtBeat( GetBeat() ).m_fWait ),
ssprintf( "%.5f", GetAppropriateTiming().GetSpeedSegmentAtBeat( GetBeat() ).GetLength() ),
10
);
break;
+37 -36
View File
@@ -269,27 +269,27 @@ void TimingData::SetSpeedAtRow( int iRow, float fPercent, float fWait, unsigned
unsigned i;
for( i = 0; i < m_SpeedSegments.size(); i++ )
{
if( m_SpeedSegments[i].m_iStartRow >= iRow)
if( m_SpeedSegments[i].GetRow() >= iRow)
break;
}
if ( i == m_SpeedSegments.size() || m_SpeedSegments[i].m_iStartRow != iRow )
if ( i == m_SpeedSegments.size() || m_SpeedSegments[i].GetRow() != iRow )
{
// the core mod itself matters the most for comparisons.
if( i == 0 || m_SpeedSegments[i-1].m_fPercent != fPercent )
if( i == 0 || m_SpeedSegments[i-1].GetRatio() != fPercent )
AddSpeedSegment( SpeedSegment(iRow, fPercent, fWait, usMode) );
}
else
{
// The others aren't compared: only the mod itself matters.
if( i > 0 && m_SpeedSegments[i-1].m_fPercent == fPercent )
if( i > 0 && m_SpeedSegments[i-1].GetRatio() == fPercent )
m_SpeedSegments.erase( m_SpeedSegments.begin()+i,
m_SpeedSegments.begin()+i+1 );
else
{
m_SpeedSegments[i].m_fPercent = fPercent;
m_SpeedSegments[i].m_fWait = fWait;
m_SpeedSegments[i].m_usMode = usMode;
m_SpeedSegments[i].SetRatio(fPercent);
m_SpeedSegments[i].SetLength(fWait);
m_SpeedSegments[i].SetUnit(usMode);
}
}
}
@@ -351,23 +351,23 @@ void TimingData::SetSpeedPercentAtRow( int iRow, float fPercent )
{
SetSpeedAtRow( iRow,
fPercent,
GetSpeedSegmentAtBeat( NoteRowToBeat( iRow ) ).m_fWait,
GetSpeedSegmentAtBeat( NoteRowToBeat( iRow ) ).m_usMode);
GetSpeedSegmentAtBeat( NoteRowToBeat( iRow ) ).GetLength(),
GetSpeedSegmentAtBeat( NoteRowToBeat( iRow ) ).GetUnit());
}
void TimingData::SetSpeedWaitAtRow( int iRow, float fWait )
{
SetSpeedAtRow( iRow,
GetSpeedSegmentAtBeat( NoteRowToBeat( iRow ) ).m_fPercent,
GetSpeedSegmentAtBeat( NoteRowToBeat( iRow ) ).GetRatio(),
fWait,
GetSpeedSegmentAtBeat( NoteRowToBeat( iRow ) ).m_usMode);
GetSpeedSegmentAtBeat( NoteRowToBeat( iRow ) ).GetUnit());
}
void TimingData::SetSpeedModeAtRow( int iRow, unsigned short usMode )
{
SetSpeedAtRow( iRow,
GetSpeedSegmentAtBeat( NoteRowToBeat( iRow ) ).m_fPercent,
GetSpeedSegmentAtBeat( NoteRowToBeat( iRow ) ).m_fWait,
GetSpeedSegmentAtBeat( NoteRowToBeat( iRow ) ).GetRatio(),
GetSpeedSegmentAtBeat( NoteRowToBeat( iRow ) ).GetLength(),
usMode );
}
@@ -419,17 +419,17 @@ float TimingData::GetWarpAtRow( int iWarpRow ) const
float TimingData::GetSpeedPercentAtRow( int iRow )
{
return GetSpeedSegmentAtRow( iRow ).m_fPercent;
return GetSpeedSegmentAtRow( iRow ).GetRatio();
}
float TimingData::GetSpeedWaitAtRow( int iRow )
{
return GetSpeedSegmentAtRow( iRow ).m_fWait;
return GetSpeedSegmentAtRow( iRow ).GetLength();
}
unsigned short TimingData::GetSpeedModeAtRow( int iRow )
{
return GetSpeedSegmentAtRow( iRow ).m_usMode;
return GetSpeedSegmentAtRow( iRow ).GetUnit();
}
float TimingData::GetScrollAtRow( int iRow )
@@ -619,7 +619,7 @@ int TimingData::GetSpeedSegmentIndexAtRow( int iRow ) const
{
unsigned i;
for (i=0; i < m_SpeedSegments.size() - 1; i++ )
if( m_SpeedSegments[i+1].m_iStartRow > iRow )
if( m_SpeedSegments[i+1].GetRow() > iRow )
break;
return static_cast<int>(i);
}
@@ -656,7 +656,7 @@ SpeedSegment& TimingData::GetSpeedSegmentAtRow( int iRow )
{
unsigned i;
for( i=0; i<m_SpeedSegments.size()-1; i++ )
if( m_SpeedSegments[i+1].m_iStartRow > iRow )
if( m_SpeedSegments[i+1].GetRow() > iRow )
break;
return m_SpeedSegments[i];
}
@@ -1113,13 +1113,13 @@ void TimingData::ScaleRegion( float fScale, int iStartIndex, int iEndIndex, bool
for ( unsigned i = 0; i < m_SpeedSegments.size(); i++ )
{
SpeedSegment &s = m_SpeedSegments[i];
const int iSegStart = s.m_iStartRow;
const int iSegStart = s.GetRow();
if( iSegStart < iStartIndex )
continue;
else if( iSegStart > iEndIndex )
s.m_iStartRow += lrintf( (iEndIndex - iStartIndex) * (fScale - 1) );
s.SetRow(s.GetRow() + lrintf( (iEndIndex - iStartIndex) * (fScale - 1) ));
else
s.m_iStartRow = lrintf( (iSegStart - iStartIndex) * fScale ) + iStartIndex;
s.SetRow(lrintf( (iSegStart - iStartIndex) * fScale ) + iStartIndex);
}
for( unsigned i = 0; i < m_FakeSegments.size(); i++ )
@@ -1242,9 +1242,9 @@ void TimingData::InsertRows( int iStartRow, int iRowsToAdd )
for( unsigned i = 0; i < m_SpeedSegments.size(); i++ )
{
SpeedSegment &sped = m_SpeedSegments[i];
if( sped.m_iStartRow < iStartRow )
if( sped.GetRow() < iStartRow )
continue;
sped.m_iStartRow += iRowsToAdd;
sped.SetRow(sped.GetRow() + iRowsToAdd);
}
for( unsigned i = 0; i < m_FakeSegments.size(); i++ )
@@ -1420,17 +1420,17 @@ void TimingData::DeleteRows( int iStartRow, int iRowsToDelete )
for( unsigned i = 0; i < m_SpeedSegments.size(); i++ )
{
SpeedSegment &sped = m_SpeedSegments[i];
if( sped.m_iStartRow < iStartRow )
int keyRow = sped.GetRow();
if( keyRow < iStartRow )
continue;
if( sped.m_iStartRow < iStartRow+iRowsToDelete )
if( keyRow < iStartRow+iRowsToDelete )
{
m_SpeedSegments.erase( m_SpeedSegments.begin()+i, m_SpeedSegments.begin()+i+1 );
--i;
continue;
}
sped.m_iStartRow -= iRowsToDelete;
sped.SetRow(keyRow - iRowsToDelete);
}
for( unsigned i = 0; i < m_FakeSegments.size(); i++ )
@@ -1477,38 +1477,39 @@ float TimingData::GetDisplayedSpeedPercent( float fSongBeat, float fMusicSeconds
const int index = GetSpeedSegmentIndexAtBeat( fSongBeat );
const SpeedSegment &seg = m_SpeedSegments[index];
float fStartBeat = NoteRowToBeat(seg.m_iStartRow);
float fStartBeat = seg.GetBeat();
float fStartTime = GetElapsedTimeFromBeat( fStartBeat ) - GetDelayAtBeat( fStartBeat );
float fEndTime;
float fCurTime = fMusicSeconds;
if( seg.m_usMode == 1 ) // seconds
if( seg.GetUnit() == 1 ) // seconds
{
fEndTime = fStartTime + seg.m_fWait;
fEndTime = fStartTime + seg.GetLength();
}
else
{
fEndTime = GetElapsedTimeFromBeat( fStartBeat + seg.m_fWait ) - GetDelayAtBeat( fStartBeat + seg.m_fWait );
fEndTime = GetElapsedTimeFromBeat( fStartBeat + seg.GetLength() )
- GetDelayAtBeat( fStartBeat + seg.GetLength() );
}
if( ( index == 0 && m_SpeedSegments[0].m_fWait > 0.0 ) && fCurTime < fStartTime )
if( ( index == 0 && m_SpeedSegments[0].GetLength() > 0.0 ) && fCurTime < fStartTime )
{
return 1.0;
}
else if( fEndTime >= fCurTime && ( index > 0 || m_SpeedSegments[0].m_fWait > 0.0 ) )
else if( fEndTime >= fCurTime && ( index > 0 || m_SpeedSegments[0].GetLength() > 0.0 ) )
{
const float fPriorSpeed = ( index == 0 ? 1 : m_SpeedSegments[index - 1].m_fPercent );
const float fPriorSpeed = ( index == 0 ? 1 : m_SpeedSegments[index - 1].GetRatio() );
float fTimeUsed = fCurTime - fStartTime;
float fDuration = fEndTime - fStartTime;
float fRatioUsed = fDuration == 0.0 ? 1 : fTimeUsed / fDuration;
float fDistance = fPriorSpeed - seg.m_fPercent;
float fDistance = fPriorSpeed - seg.GetRatio();
float fRatioNeed = fRatioUsed * -fDistance;
return (fPriorSpeed + fRatioNeed);
}
else
{
return seg.m_fPercent;
return seg.GetRatio();
}
}
-130
View File
@@ -119,136 +119,6 @@ struct StopSegment
bool operator>=( const StopSegment &other ) const { return !operator<(other); }
};
/**
* @brief Identifies when the arrow scroll changes.
*
* SpeedSegments take a Player's scrolling BPM (Step's BPM * speed mod),
* and then multiplies it with the percentage value. No matter the player's
* speed mod, the ratio will be the same. Unlike forced attacks, these
* cannot be turned off at a set time: reset it by setting the precentage
* back to 1.
*
* These were inspired by the Pump It Up series. */
struct SpeedSegment
{
/** @brief Sets up the SpeedSegment with default values. */
SpeedSegment(): m_iStartRow(0),
m_fPercent(1), m_fWait(0), m_usMode(0) {}
/**
* @brief Sets up the SpeedSegment with specified values.
* @param i The row this activates.
* @param p The percentage to use. */
SpeedSegment(int i, float p): m_iStartRow(i),
m_fPercent(p), m_fWait(0), m_usMode(0) {}
/**
* @brief Sets up the SpeedSegment with specified values.
* @param r The beat this activates.
* @param p The percentage to use. */
SpeedSegment(float r, float p): m_iStartRow(BeatToNoteRow(r)),
m_fPercent(p), m_fWait(0), m_usMode(0) {}
/**
* @brief Sets up the SpeedSegment with specified values.
* @param i The row this activates.
* @param p The percentage to use.
* @param w The number of beats to wait. */
SpeedSegment(int i, float p, float w): m_iStartRow(i),
m_fPercent(p), m_fWait(w), m_usMode(0) {}
/**
* @brief Sets up the SpeedSegment with specified values.
* @param r The beat this activates.
* @param p The percentage to use.
* @param w The number of beats to wait. */
SpeedSegment(float r, float p, float w): m_iStartRow(BeatToNoteRow(r)),
m_fPercent(p), m_fWait(w), m_usMode(0) {}
/**
* @brief Sets up the SpeedSegment with specified values.
* @param i The row this activates.
* @param p The percentage to use.
* @param w The number of beats/seconds to wait.
* @param k The mode used for the wait variable. */
SpeedSegment(int i, float p, float w, unsigned short k): m_iStartRow(i),
m_fPercent(p), m_fWait(w), m_usMode(k) {}
/**
* @brief Sets up the SpeedSegment with specified values.
* @param r The beat this activates.
* @param p The percentage to use.
* @param w The number of beats/seconds to wait.
* @param k The mode used for the wait variable.*/
SpeedSegment(float r, float p, float w, unsigned short k): m_iStartRow(BeatToNoteRow(r)),
m_fPercent(p), m_fWait(w), m_usMode(k) {}
/** @brief The row in which the ComboSegment activates. */
int m_iStartRow;
/** @brief The percentage to use when multiplying the Player's BPM. */
float m_fPercent;
/**
* @brief The number of beats or seconds to wait for the change to take place.
*
* A value of 0 means this is immediate. */
float m_fWait;
/**
* @brief The mode that this segment uses for the math.
*
* 0: beats
* 1: seconds
* other
*/
unsigned short m_usMode;
/**
* @brief Compares two SpeedSegments to see if they are equal to each other.
* @param other the other SpeedSegment to compare to.
* @return the equality of the two segments.
*/
bool operator==( const SpeedSegment &other ) const
{
COMPARE( m_iStartRow );
COMPARE( m_fPercent );
COMPARE( m_usMode );
COMPARE( m_fWait );
return true;
}
/**
* @brief Compares two SpeedSegments to see if they are not equal to each other.
* @param other the other SpeedSegment to compare to.
* @return the inequality of the two segments.
*/
bool operator!=( const SpeedSegment &other ) const { return !operator==(other); }
/**
* @brief Compares two SpeedSegments to see if one is less than the other.
* @param other the other SpeedSegment to compare to.
* @return the truth/falsehood of if the first is less than the second.
*/
bool operator<( const SpeedSegment &other ) const { return m_iStartRow < other.m_iStartRow; }
/**
* @brief Compares two SpeedSegments to see if one is less than or equal to the other.
* @param other the other SpeedSegment to compare to.
* @return the truth/falsehood of if the first is less or equal to than the second.
*/
bool operator<=( const SpeedSegment &other ) const
{
return ( operator<(other) || operator==(other) );
}
/**
* @brief Compares two SpeedSegments to see if one is greater than the other.
* @param other the other SpeedSegment to compare to.
* @return the truth/falsehood of if the first is greater than the second.
*/
bool operator>( const SpeedSegment &other ) const { return !operator<=(other); }
/**
* @brief Compares two SpeedSegments to see if one is greater than or equal to the other.
* @param other the other SpeedSegment to compare to.
* @return the truth/falsehood of if the first is greater than or equal to the second.
*/
bool operator>=( const SpeedSegment &other ) const { return !operator<(other); }
};
/**
* @brief Identifies when the chart scroll changes.
*
+43
View File
@@ -195,7 +195,50 @@ bool TimeSignatureSegment::operator<( const TimeSignatureSegment &other ) const
return false;
}
float SpeedSegment::GetRatio() const
{
return this->ratio;
}
void SpeedSegment::SetRatio(const float i)
{
this->ratio = i;
}
float SpeedSegment::GetLength() const
{
return this->length;
}
void SpeedSegment::SetLength(const float i)
{
this->length = i;
}
unsigned short SpeedSegment::GetUnit() const
{
return this->unit;
}
void SpeedSegment::SetUnit(const unsigned short i)
{
this->unit = i;
}
void SpeedSegment::SetUnit(const int i)
{
this->unit = static_cast<unsigned short>(i);
}
bool SpeedSegment::operator<( const SpeedSegment &other ) const
{
LTCOMPARE(GetRow());
LTCOMPARE(GetRatio());
LTCOMPARE(GetLength());
LTCOMPARE(GetUnit());
return false;
}
/**
+110
View File
@@ -525,6 +525,116 @@ private:
int denominator;
};
/**
* @brief Identifies when the arrow scroll changes.
*
* SpeedSegments take a Player's scrolling BPM (Step's BPM * speed mod),
* and then multiplies it with the percentage value. No matter the player's
* speed mod, the ratio will be the same. Unlike forced attacks, these
* cannot be turned off at a set time: reset it by setting the precentage
* back to 1.
*
* These were inspired by the Pump It Up series. */
struct SpeedSegment : public TimingSegment<SpeedSegment>
{
/** @brief Sets up the SpeedSegment with default values. */
SpeedSegment():
TimingSegment<SpeedSegment>(0),
ratio(1), length(0), unit(0) {}
/**
* @brief Sets up the SpeedSegment with specified values.
* @param r The row / beat this activates.
* @param p The percentage to use. */
template <typename StartType>
SpeedSegment( StartType r, float p):
TimingSegment<SpeedSegment>(max((StartType)0, r)),
ratio(p), length(0), unit(0) {}
/**
* @brief Sets up the SpeedSegment with specified values.
* @param r The row / beat this activates.
* @param p The percentage to use.
* @param w The number of beats to wait. */
template <typename StartType>
SpeedSegment(StartType r, float p, float w):
TimingSegment<SpeedSegment>(max((StartType)0, r)),
ratio(p), length(w), unit(0) {}
/**
* @brief Sets up the SpeedSegment with specified values.
* @param r The row / beat this activates.
* @param p The percentage to use.
* @param w The number of beats/seconds to wait.
* @param k The mode used for the wait variable. */
template <typename StartType>
SpeedSegment(StartType r, float p, float w, unsigned short k):
TimingSegment<SpeedSegment>(max((StartType)0, r)),
ratio(p), length(w), unit(k) {}
/**
* @brief Get the ratio in this SpeedSegment.
* @return the ratio. */
float GetRatio() const;
/**
* @brief Set the ratio in this SpeedSegment.
* @param i the ratio. */
void SetRatio(const float i);
/**
* @brief Get the length in this SpeedSegment.
* @return the length. */
float GetLength() const;
/**
* @brief Set the length in this SpeedSegment.
* @param i the length. */
void SetLength(const float i);
/**
* @brief Get the unit in this SpeedSegment.
* @return the unit. */
unsigned short GetUnit() const;
/**
* @brief Set the unit in this SpeedSegment.
* @param i the unit. */
void SetUnit(const unsigned short i);
/**
* @brief Set the unit in this SpeedSegment.
*
* This one is offered for quicker compatibility.
* @param i the unit. */
void SetUnit(const int i);
/**
* @brief Compares two SpeedSegments to see if one is less than the other.
* @param other the other SpeedSegment to compare to.
* @return the truth/falsehood of if the first is less than the second.
*/
bool operator<( const SpeedSegment &other ) const;
private:
/** @brief The percentage (ratio) to use when multiplying the Player's BPM. */
float ratio;
/**
* @brief The number of beats or seconds to wait for the change to take place.
*
* A value of 0 means this is immediate. */
float length;
/**
* @brief The mode that this segment uses for the math.
*
* 0: beats
* 1: seconds
* other
*/
unsigned short unit;
};
#endif
/**