Warps are properly templated.

Seven more to go I believe.
This commit is contained in:
Jason Felds
2011-05-31 10:59:18 -04:00
parent 26ecddfc9d
commit 1fcf290571
7 changed files with 117 additions and 142 deletions
+3 -3
View File
@@ -921,11 +921,11 @@ void NoteField::DrawPrimitives()
// Warp text // Warp text
FOREACH_CONST( WarpSegment, timing.m_WarpSegments, seg ) FOREACH_CONST( WarpSegment, timing.m_WarpSegments, 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) ) if( IS_ON_SCREEN(fBeat) )
DrawWarpText( fBeat, seg->m_fLengthBeats ); DrawWarpText( fBeat, seg->GetLength() );
} }
} }
+2 -2
View File
@@ -113,9 +113,9 @@ static void WriteGlobalTags( RageFile &f, Song &out )
{ {
for( unsigned i=0; i < wSize; i++ ) for( unsigned i=0; i < wSize; i++ )
{ {
int iRow = out.m_SongTiming.m_WarpSegments[i].m_iStartRow; int iRow = out.m_SongTiming.m_WarpSegments[i].GetRow();
float fBPS = 60 / out.m_SongTiming.GetBPMAtRow(iRow); float fBPS = 60 / out.m_SongTiming.GetBPMAtRow(iRow);
float fSkip = fBPS * out.m_SongTiming.m_WarpSegments[i].m_fLengthBeats; float fSkip = fBPS * out.m_SongTiming.m_WarpSegments[i].GetLength();
StopSegment ss; StopSegment ss;
ss.m_iStartRow = iRow; ss.m_iStartRow = iRow;
ss.m_fStopSeconds = -fSkip; ss.m_fStopSeconds = -fSkip;
+1 -1
View File
@@ -110,7 +110,7 @@ static void GetTimingTags( vector<RString> &lines, TimingData timing, bool bIsSo
w.Init( "WARPS" ); w.Init( "WARPS" );
FOREACH_CONST( WarpSegment, timing.m_WarpSegments, ws ) FOREACH_CONST( WarpSegment, timing.m_WarpSegments, ws )
w.Write( ws->m_iStartRow, ws->m_fLengthBeats ); w.Write( ws->GetRow(), ws->GetLength() );
w.Finish(); w.Finish();
ASSERT( !timing.m_vTimeSignatureSegments.empty() ); ASSERT( !timing.m_vTimeSignatureSegments.empty() );
+27 -24
View File
@@ -179,7 +179,7 @@ void TimingData::SetWarpAtRow( int iRow, float fNew )
{ {
unsigned i; unsigned i;
for( i=0; i<m_WarpSegments.size(); i++ ) for( i=0; i<m_WarpSegments.size(); i++ )
if( m_WarpSegments[i].m_iStartRow == iRow ) if( m_WarpSegments[i].GetRow() == iRow )
break; break;
bool valid = iRow > 0 && fNew > 0; bool valid = iRow > 0 && fNew > 0;
if( i == m_WarpSegments.size() ) if( i == m_WarpSegments.size() )
@@ -193,7 +193,7 @@ void TimingData::SetWarpAtRow( int iRow, float fNew )
{ {
if( valid ) if( valid )
{ {
m_WarpSegments[i].m_fLengthBeats = fNew; m_WarpSegments[i].SetLength(fNew);
} }
else else
m_WarpSegments.erase( m_WarpSegments.begin()+i, m_WarpSegments.begin()+i+1 ); m_WarpSegments.erase( m_WarpSegments.begin()+i, m_WarpSegments.begin()+i+1 );
@@ -410,9 +410,9 @@ float TimingData::GetWarpAtRow( int iWarpRow ) const
{ {
for( unsigned i=0; i<m_WarpSegments.size(); i++ ) for( unsigned i=0; i<m_WarpSegments.size(); i++ )
{ {
if( m_WarpSegments[i].m_iStartRow == iWarpRow ) if( m_WarpSegments[i].GetRow() == iWarpRow )
{ {
return m_WarpSegments[i].m_fLengthBeats; return m_WarpSegments[i].GetLength();
} }
} }
return 0; return 0;
@@ -526,7 +526,7 @@ int TimingData::GetWarpSegmentIndexAtRow( int iNoteRow ) const
for( i=0; i<m_WarpSegments.size()-1; i++ ) for( i=0; i<m_WarpSegments.size()-1; i++ )
{ {
const WarpSegment& s = m_WarpSegments[i+1]; const WarpSegment& s = m_WarpSegments[i+1];
if( s.m_iStartRow > iNoteRow ) if( s.GetRow() > iNoteRow )
break; break;
} }
return static_cast<int>(i); return static_cast<int>(i);
@@ -551,7 +551,8 @@ bool TimingData::IsWarpAtRow( int iNoteRow ) const
int i = GetWarpSegmentIndexAtRow( iNoteRow ); int i = GetWarpSegmentIndexAtRow( iNoteRow );
const WarpSegment& s = m_WarpSegments[i]; const WarpSegment& s = m_WarpSegments[i];
if( s.m_iStartRow <= iNoteRow && iNoteRow < (s.m_iStartRow + BeatToNoteRow(s.m_fLengthBeats) ) ) float beatRow = NoteRowToBeat(iNoteRow);
if( s.GetBeat() <= beatRow && beatRow < (s.GetBeat() + s.GetLength() ) )
{ {
// Allow stops inside warps to allow things like stop, warp, stop, warp, stop, and so on. // Allow stops inside warps to allow things like stop, warp, stop, warp, stop, and so on.
if( m_StopSegments.empty() ) if( m_StopSegments.empty() )
@@ -844,9 +845,9 @@ void TimingData::GetBeatAndBPSFromElapsedTimeNoOffset( float fElapsedTime, float
iEventRow = itSS->m_iStartRow; iEventRow = itSS->m_iStartRow;
iEventType = FOUND_STOP; iEventType = FOUND_STOP;
} }
if( itWS != m_WarpSegments.end() && itWS->m_iStartRow < iEventRow ) if( itWS != m_WarpSegments.end() && itWS->GetRow() < iEventRow )
{ {
iEventRow = itWS->m_iStartRow; iEventRow = itWS->GetRow();
iEventType = FOUND_WARP; iEventType = FOUND_WARP;
} }
if( iEventType == NOT_FOUND ) if( iEventType == NOT_FOUND )
@@ -889,7 +890,7 @@ void TimingData::GetBeatAndBPSFromElapsedTimeNoOffset( float fElapsedTime, float
case FOUND_WARP: case FOUND_WARP:
{ {
bIsWarping = true; bIsWarping = true;
float fWarpSum = itWS->m_fLengthBeats + NoteRowToBeat( itWS->m_iStartRow ); float fWarpSum = itWS->GetLength() + itWS->GetBeat();
if( fWarpSum > fWarpDestination ) if( fWarpSum > fWarpDestination )
{ {
fWarpDestination = fWarpSum; fWarpDestination = fWarpSum;
@@ -956,9 +957,9 @@ float TimingData::GetElapsedTimeFromBeatNoOffset( float fBeat ) const
iEventRow = itSS->m_iStartRow; iEventRow = itSS->m_iStartRow;
iEventType = FOUND_STOP; iEventType = FOUND_STOP;
} }
if( itWS != m_WarpSegments.end() && itWS->m_iStartRow < iEventRow ) if( itWS != m_WarpSegments.end() && itWS->GetRow() < iEventRow )
{ {
iEventRow = itWS->m_iStartRow; iEventRow = itWS->GetRow();
iEventType = FOUND_WARP; iEventType = FOUND_WARP;
} }
float fTimeToNextEvent = bIsWarping ? 0 : NoteRowToBeat( iEventRow - iLastRow ) / fBPS; float fTimeToNextEvent = bIsWarping ? 0 : NoteRowToBeat( iEventRow - iLastRow ) / fBPS;
@@ -984,7 +985,7 @@ float TimingData::GetElapsedTimeFromBeatNoOffset( float fBeat ) const
case FOUND_WARP: case FOUND_WARP:
{ {
bIsWarping = true; bIsWarping = true;
float fWarpSum = itWS->m_fLengthBeats + NoteRowToBeat( itWS->m_iStartRow ); float fWarpSum = itWS->GetLength() + itWS->GetBeat();
if( fWarpSum > fWarpDestination ) if( fWarpSum > fWarpDestination )
{ {
fWarpDestination = fWarpSum; fWarpDestination = fWarpSum;
@@ -1052,21 +1053,23 @@ void TimingData::ScaleRegion( float fScale, int iStartIndex, int iEndIndex, bool
for( unsigned i = 0; i < m_WarpSegments.size(); i++ ) for( unsigned i = 0; i < m_WarpSegments.size(); i++ )
{ {
const int iSegStartRow = m_WarpSegments[i].m_iStartRow; WarpSegment &w = m_WarpSegments[i];
const int iSegEndRow = iSegStartRow + BeatToNoteRow( m_WarpSegments[i].m_fLengthBeats ); const int iSegStartRow = w.GetRow();
const int iSegEndRow = iSegStartRow + BeatToNoteRow( w.GetLength() );
if( iSegEndRow >= iStartIndex ) if( iSegEndRow >= iStartIndex )
{ {
if( iSegEndRow > iEndIndex ) if( iSegEndRow > iEndIndex )
m_WarpSegments[i].m_fLengthBeats += NoteRowToBeat(lrintf((iEndIndex - iStartIndex) * (fScale - 1))); w.SetLength(w.GetLength() +
NoteRowToBeat(lrintf((iEndIndex - iStartIndex) * (fScale - 1))));
else else
m_WarpSegments[i].m_fLengthBeats = NoteRowToBeat(lrintf((iSegEndRow - iStartIndex) * fScale)); w.SetLength(NoteRowToBeat(lrintf((iSegEndRow - iStartIndex) * fScale)));
} }
if( iSegStartRow < iStartIndex ) if( iSegStartRow < iStartIndex )
continue; continue;
else if( iSegStartRow > iEndIndex ) else if( iSegStartRow > iEndIndex )
m_WarpSegments[i].m_iStartRow += lrintf((iEndIndex - iStartIndex) * (fScale - 1)); w.SetRow(w.GetRow() + lrintf((iEndIndex - iStartIndex) * (fScale - 1)));
else else
m_WarpSegments[i].m_iStartRow = lrintf((iSegStartRow - iStartIndex) * fScale) + iStartIndex; w.SetRow(lrintf((iSegStartRow - iStartIndex) * fScale) + iStartIndex);
} }
for ( unsigned i = 0; i < m_TickcountSegments.size(); i++ ) for ( unsigned i = 0; i < m_TickcountSegments.size(); i++ )
@@ -1194,9 +1197,9 @@ void TimingData::InsertRows( int iStartRow, int iRowsToAdd )
for( unsigned i = 0; i < m_WarpSegments.size(); i++ ) for( unsigned i = 0; i < m_WarpSegments.size(); i++ )
{ {
WarpSegment &warp = m_WarpSegments[i]; WarpSegment &warp = m_WarpSegments[i];
if( warp.m_iStartRow < iStartRow ) if( warp.GetRow() < iStartRow )
continue; continue;
warp.m_iStartRow += iRowsToAdd; warp.SetRow(warp.GetRow() + iRowsToAdd);
} }
for( unsigned i = 0; i < m_vTimeSignatureSegments.size(); i++ ) for( unsigned i = 0; i < m_vTimeSignatureSegments.size(); i++ )
@@ -1314,18 +1317,18 @@ void TimingData::DeleteRows( int iStartRow, int iRowsToDelete )
for( unsigned i = 0; i < m_WarpSegments.size(); i++ ) for( unsigned i = 0; i < m_WarpSegments.size(); i++ )
{ {
WarpSegment &warp = m_WarpSegments[i]; WarpSegment &warp = m_WarpSegments[i];
int keyRow = warp.GetRow();
if( warp.m_iStartRow < iStartRow ) if( keyRow < iStartRow )
continue; continue;
if( warp.m_iStartRow < iStartRow+iRowsToDelete ) if( keyRow < iStartRow+iRowsToDelete )
{ {
m_WarpSegments.erase( m_WarpSegments.begin()+i, m_WarpSegments.begin()+i+1 ); m_WarpSegments.erase( m_WarpSegments.begin()+i, m_WarpSegments.begin()+i+1 );
--i; --i;
continue; continue;
} }
warp.m_iStartRow -= iRowsToDelete; warp.SetRow(keyRow - iRowsToDelete);
} }
for( unsigned i = 0; i < m_vTimeSignatureSegments.size(); i++ ) for( unsigned i = 0; i < m_vTimeSignatureSegments.size(); i++ )
-103
View File
@@ -309,109 +309,6 @@ struct TimeSignatureSegment
bool operator>= (const TimeSignatureSegment &other ) const { return !operator<(other); } bool operator>= (const TimeSignatureSegment &other ) const { return !operator<(other); }
}; };
/**
* @brief Identifies when a song needs to warp to a new beat.
*
* A warp segment is used to replicate the effects of Negative BPMs without
* abusing negative BPMs. Negative BPMs should be converted to warp segments.
* WarpAt=WarpToRelative is the format, where both are in beats.
* (Technically they're both rows though.) */
struct WarpSegment
{
/**
* @brief Create a simple Warp Segment with default values.
*
* It is best to override the values as soon as possible.
*/
WarpSegment() : m_iStartRow(-1), m_fLengthBeats(-1) { }
/**
* @brief Create a Warp Segment with the specified starting row and row to warp to.
* @param s the starting row of this segment.
* @param r the number of rows to jump ahead.
*/
WarpSegment( int s, int r ): m_iStartRow(s),
m_fLengthBeats(NoteRowToBeat(r)) {}
/**
* @brief Creates a Warp Segment with the specified starting row and beat to warp to.
* @param s the starting row of this segment.
* @param b the number of beats to jump ahead.
*/
WarpSegment( int s, float b ): m_iStartRow(max(0, s)),
m_fLengthBeats(max(0, b)) {}
/**
* @brief Create a Warp Segment with the specified starting beat and row to warp to.
* @param s the starting beat in this segment.
* @param r the number of rows to jump ahead.
*/
WarpSegment( float s, int r ):
m_iStartRow(max(0, BeatToNoteRow(s))),
m_fLengthBeats(max(0, NoteRowToBeat(r))) {}
/**
* @brief Creates a Warp Segment with the specified starting beat and beat to warp to.
* @param s the starting beat of this segment.
* @param b the number of beats to jump ahead.
*/
WarpSegment( float s, float b ):
m_iStartRow(BeatToNoteRow(s)),
m_fLengthBeats(b) {}
/**
* @brief The row in which the WarpSegment activates.
*/
int m_iStartRow;
/**
* @brief The number of beats to warp ahead by.
*/
float m_fLengthBeats;
/**
* @brief Compares two WarpSegments to see if they are equal to each other.
* @param other the other WarpSegment to compare to.
* @return the equality of the two segments.
*/
bool operator==( const WarpSegment &other ) const
{
COMPARE( m_iStartRow );
COMPARE( m_fLengthBeats );
return true;
}
/**
* @brief Compares two WarpSegments to see if they are not equal to each other.
* @param other the other WarpSegment to compare to.
* @return the inequality of the two segments.
*/
bool operator!=( const WarpSegment &other ) const { return !operator==(other); }
/**
* @brief Compares two WarpSegments to see if one is less than the other.
* @param other the other WarpSegment to compare to.
* @return the truth/falsehood of if the first is less than the second.
*/
bool operator<( const WarpSegment &other ) const
{
return m_iStartRow < other.m_iStartRow ||
( m_iStartRow == other.m_iStartRow && m_fLengthBeats < other.m_fLengthBeats );
}
/**
* @brief Compares two WarpSegments to see if one is less than or equal to the other.
* @param other the other WarpSegment to compare to.
* @return the truth/falsehood of if the first is less or equal to than the second.
*/
bool operator<=( const WarpSegment &other ) const
{
return ( operator<(other) || operator==(other) );
}
/**
* @brief Compares two WarpSegments to see if one is greater than the other.
* @param other the other WarpSegment to compare to.
* @return the truth/falsehood of if the first is greater than the second.
*/
bool operator>( const WarpSegment &other ) const { return !operator<=(other); }
/**
* @brief Compares two WarpSegments to see if one is greater than or equal to the other.
* @param other the other WarpSegment to compare to.
* @return the truth/falsehood of if the first is greater than or equal to the second.
*/
bool operator>=( const WarpSegment &other ) const { return !operator<(other); }
};
/** /**
* @brief Identifies when a chart is to have a different combo multiplier value. * @brief Identifies when a chart is to have a different combo multiplier value.
* *
+17
View File
@@ -53,6 +53,23 @@ bool FakeSegment::operator<( const FakeSegment &other ) const
return false; return false;
} }
float WarpSegment::GetLength() const
{
return this->lengthBeats;
}
void WarpSegment::SetLength(const float b)
{
this->lengthBeats = b;
}
bool WarpSegment::operator<( const WarpSegment &other ) const
{
LTCOMPARE(GetRow());
LTCOMPARE(GetLength());
return false;
}
int TickcountSegment::GetTicks() const int TickcountSegment::GetTicks() const
+67 -9
View File
@@ -3,12 +3,6 @@
#include "NoteTypes.h" // Converting rows to beats and vice~versa. #include "NoteTypes.h" // Converting rows to beats and vice~versa.
/**
* @brief Compare a TimingData segment's properties with one another.
*
* This will be removed once we start respecting public & private data.*/
#define COMPARE(x) if(x!=other.x) return false;
/** /**
* @brief The base timing segment for all of the changing glory. * @brief The base timing segment for all of the changing glory.
* *
@@ -91,7 +85,11 @@ struct TimingSegment: public BaseTimingSegment
* This is virtual to allow other segments to implement comparison * This is virtual to allow other segments to implement comparison
* as required by them. * as required by them.
*/ */
bool operator==( const DerivedSegment &other ) const { return !this->operator<(other) && !other.operator<(*static_cast<const DerivedSegment *>(this)); }; bool operator==( const DerivedSegment &other ) const
{
return !this->operator<(other) &&
!other.operator<(*static_cast<const DerivedSegment *>(this));
};
/** /**
* @brief Compares two DrivedSegments to see if they are not equal to each other. * @brief Compares two DrivedSegments to see if they are not equal to each other.
* @param other the other DrivedSegments to compare to. * @param other the other DrivedSegments to compare to.
@@ -109,7 +107,10 @@ struct TimingSegment: public BaseTimingSegment
* @param other the other DrivedSegments to compare to. * @param other the other DrivedSegments to compare to.
* @return the truth/falsehood of if the first is greater than the second. * @return the truth/falsehood of if the first is greater than the second.
*/ */
bool operator>( const DerivedSegment &other ) const { return other.operator<(*static_cast<const DerivedSegment *>(this)); }; bool operator>( const DerivedSegment &other ) const
{
return other.operator<(*static_cast<const DerivedSegment *>(this));
};
/** /**
* @brief Compares two DrivedSegments to see if one is greater than or equal to the other. * @brief Compares two DrivedSegments to see if one is greater than or equal to the other.
* @param other the other DrivedSegments to compare to. * @param other the other DrivedSegments to compare to.
@@ -148,7 +149,8 @@ struct FakeSegment : public TimingSegment<FakeSegment>
*/ */
template <typename StartType, typename LengthType> template <typename StartType, typename LengthType>
FakeSegment( StartType s, LengthType r ): FakeSegment( StartType s, LengthType r ):
TimingSegment<FakeSegment>(max((StartType)0, s)), lengthBeats(ToBeat(max((LengthType)0, r))) {}; TimingSegment<FakeSegment>(max((StartType)0, s)),
lengthBeats(ToBeat(max((LengthType)0, r))) {};
/** /**
* @brief Get the length in beats of the FakeSegment. * @brief Get the length in beats of the FakeSegment.
@@ -180,6 +182,62 @@ private:
float lengthBeats; float lengthBeats;
}; };
/**
* @brief Identifies when a song needs to warp to a new beat.
*
* A warp segment is used to replicate the effects of Negative BPMs without
* abusing negative BPMs. Negative BPMs should be converted to warp segments.
* WarpAt=WarpToRelative is the format, where both are in beats.
* (Technically they're both rows though.) */
struct WarpSegment : public TimingSegment<WarpSegment>
{
/**
* @brief Create a simple Warp Segment with default values.
*
* It is best to override the values as soon as possible.
*/
WarpSegment():
TimingSegment<WarpSegment>(), lengthBeats(-1) {};
/**
* @brief Create a Warp Segment with the specified values.
* @param s the starting row of this segment.
* @param r the number of rows this segment lasts.
*/
template <typename StartType, typename LengthType>
WarpSegment( StartType s, LengthType r ):
TimingSegment<WarpSegment>(max((StartType)0, s)),
lengthBeats(ToBeat(max((LengthType)0, r))) {};
/**
* @brief Get the length in beats of the WarpSegment.
* @return the length in beats. */
float GetLength() const;
/**
* @brief Set the length in beats of the WarpSegment.
* @param b the length in beats. */
void SetLength(const float b);
/**
* @brief Compares two WarpSegments to see if they are equal to each other.
* @param other the other WarpSegment to compare to.
* @return the equality of the two segments.
*/
bool operator==( const WarpSegment &other ) const;
/*
* @brief Compares two WarpSegments to see if one is less than the other.
* @param other the other WarpSegment to compare to.
* @return the truth/falsehood of if the first is less than the second.
*/
bool operator<( const WarpSegment &other ) const;
private:
/**
* @brief The number of beats the FakeSegment is alive for.
*/
float lengthBeats;
};
/** /**
* @brief Identifies when a chart is to have a different tickcount value * @brief Identifies when a chart is to have a different tickcount value
* for hold notes. * for hold notes.