diff --git a/stepmania/src/NoteData.cpp b/stepmania/src/NoteData.cpp index 36c646330d..ef51066004 100644 --- a/stepmania/src/NoteData.cpp +++ b/stepmania/src/NoteData.cpp @@ -224,7 +224,7 @@ int NoteData::GetFirstTrackWithTapOrHoldHead( int index ) const void NoteData::AddHoldNote( HoldNote add ) { - ASSERT( add.fStartBeat>=0 && add.fEndBeat>=0 ); + ASSERT( add.iStartRow>=0 && add.iEndRow>=0 ); int i; @@ -235,17 +235,10 @@ void NoteData::AddHoldNote( HoldNote add ) { HoldNote &other = GetHoldNote(i); if( add.iTrack == other.iTrack && // the tracks correspond - // they overlap - ( - ( other.fStartBeat <= add.fStartBeat && other.fEndBeat >= add.fEndBeat ) || // other consumes add - ( other.fStartBeat >= add.fStartBeat && other.fEndBeat <= add.fEndBeat ) || // other inside add - ( add.fStartBeat <= other.fStartBeat && other.fStartBeat <= add.fEndBeat ) || // other overlaps add - ( add.fStartBeat <= other.fEndBeat && other.fEndBeat <= add.fEndBeat ) // other overlaps add - ) - ) + add.RangeOverlaps(other) ) // they overlap { - add.fStartBeat = min(add.fStartBeat, other.fStartBeat); - add.fEndBeat = max(add.fEndBeat, other.fEndBeat); + add.iStartRow = min(add.iStartRow, other.iStartRow); + add.iEndRow = max(add.iEndRow, other.iEndRow); // delete this HoldNote RemoveHoldNote( i ); @@ -253,8 +246,8 @@ void NoteData::AddHoldNote( HoldNote add ) } } - int iAddStartIndex = BeatToNoteRow(add.fStartBeat); - int iAddEndIndex = BeatToNoteRow(add.fEndBeat); + int iAddStartIndex = add.iStartRow; + int iAddEndIndex = add.iEndRow; // delete TapNotes under this HoldNote for( i=iAddStartIndex+1; i<=iAddEndIndex; i++ ) @@ -272,7 +265,7 @@ void NoteData::RemoveHoldNote( int iHoldIndex ) HoldNote& hn = GetHoldNote(iHoldIndex); - int iHoldStartIndex = BeatToNoteRow(hn.fStartBeat); + const int iHoldStartIndex = hn.iStartRow; // delete a tap note at the start of this hold SetTapNote(hn.iTrack, iHoldStartIndex, TAP_EMPTY); @@ -344,45 +337,40 @@ const Attack& NoteData::GetAttackAt( int track, int row ) int NoteData::GetFirstRow() const { - return BeatToNoteRow( GetFirstBeat() ); -} - -float NoteData::GetFirstBeat() const -{ - float fEarliestBeatFoundSoFar = -1; + int iEarliestRowFoundSoFar = -1; int i; - for( i=0; i <= int(m_TapNotes[0].size()); i++ ) + for( i=0; i < int(m_TapNotes[0].size()); i++ ) { if( !IsRowEmpty(i) ) { - fEarliestBeatFoundSoFar = NoteRowToBeat(i); + iEarliestRowFoundSoFar = i; break; } } for( i=0; i fOldestBeatFoundSoFar ) - fOldestBeatFoundSoFar = GetHoldNote(i).fEndBeat; + if( GetHoldNote(i).iEndRow > iOldestRowFoundSoFar ) + iOldestRowFoundSoFar = GetHoldNote(i).iEndRow; } - return fOldestBeatFoundSoFar; + return iOldestRowFoundSoFar; +} + +float NoteData::GetLastBeat() const +{ + return NoteRowToBeat( GetLastRow() ); } int NoteData::GetNumTapNotes( float fStartBeat, float fEndBeat ) const @@ -487,13 +480,13 @@ int NoteData::GetNumRowsWithTapOrHoldHead( float fStartBeat, float fEndBeat ) co int NoteData::GetNumHands( float fStartBeat, float fEndBeat ) const { - /* We want to count both three taps at the same time, a tap while two - * hold notes are being held, etc. */ - NoteData temp; - temp.To4s( *this ); - + /* Count the number of times you have to use your hands. This includes + * three taps at the same time, a tap while two hold notes are being held, + * etc. Only count rows that have at least one tap note (hold heads count). + * Otherwise, every row of hold notes counts, so three simultaneous hold + * notes will count as hundreds of "hands". */ if( fEndBeat == -1 ) - fEndBeat = temp.GetMaxBeat(); + fEndBeat = GetMaxBeat(); int iStartIndex = BeatToNoteRow( fStartBeat ); int iEndIndex = BeatToNoteRow( fEndBeat ); @@ -502,20 +495,46 @@ int NoteData::GetNumHands( float fStartBeat, float fEndBeat ) const iStartIndex = max( iStartIndex, 0 ); iEndIndex = min( iEndIndex, GetMaxRow()-1 ); +// vector HoldsAtRow; +// HoldsAtRow.insert( HoldsAtRow.begin(), iEndIndex-iStartIndex+1, 0 ); + int i; +// for( i=0; i= 3 ) iNum++; } - +LOG->Trace("xxxxxx %i", iNum); return iNum; } @@ -550,13 +569,16 @@ int NoteData::GetNumN( int MinTaps, float fStartBeat, float fEndBeat ) const int NoteData::GetNumHoldNotes( float fStartBeat, float fEndBeat ) const { - int iNumHolds = 0; + if( fEndBeat == -1 ) + fEndBeat = GetMaxBeat(); + int iStartIndex = BeatToNoteRow( fStartBeat ); + int iEndIndex = BeatToNoteRow( fEndBeat ); - if(fEndBeat == -1) fEndBeat = GetMaxBeat(); + int iNumHolds = 0; for( int i=0; i& viTracksOut ) { - float fBeat = NoteRowToBeat(row); for( unsigned i=0; i= hn.fStartBeat && fBeat <= hn.fEndBeat ) + if( hn.RowIsInRange(row) ) viTracksOut.push_back( hn.iTrack ); } } diff --git a/stepmania/src/NoteDataUtil.cpp b/stepmania/src/NoteDataUtil.cpp index 962143e528..4c01f06ce0 100644 --- a/stepmania/src/NoteDataUtil.cpp +++ b/stepmania/src/NoteDataUtil.cpp @@ -353,22 +353,21 @@ float NoteDataUtil::GetChaosRadarValue( const NoteData &in, float fSongSeconds ) void NoteDataUtil::RemoveHoldNotes(NoteData &in, float fStartBeat, float fEndBeat) { + int iStartIndex = BeatToNoteRow( fStartBeat ); + int iEndIndex = BeatToNoteRow( fEndBeat ); + // turn all the HoldNotes into TapNotes for( int i=in.GetNumHoldNotes()-1; i>=0; i-- ) // iterate backwards so we can delete { - const HoldNote hn = in.GetHoldNote(i); - - bool bHoldInRange = - (hn.fStartBeat <= fStartBeat && hn.fEndBeat >= fEndBeat) || - (hn.fStartBeat >= fStartBeat && hn.fStartBeat <= fEndBeat) || - (hn.fEndBeat >= fStartBeat && hn.fEndBeat <= fEndBeat); - - if( !bHoldInRange ) + const HoldNote &hn = in.GetHoldNote(i); + if( !hn.RangeInside( iStartIndex, iEndIndex ) ) continue; // skip + const int iStartRow = hn.iStartRow; + in.RemoveHoldNote( i ); - in.SetTapNote(hn.iTrack, BeatToNoteRow(hn.fStartBeat), TAP_TAP); + in.SetTapNote(hn.iTrack, iStartRow, TAP_TAP); } } @@ -599,7 +598,7 @@ void NoteDataUtil::Little(NoteData &in, float fStartBeat, float fEndBeat) in.SetTapNote(c, i, TAP_EMPTY); for( i=in.GetNumHoldNotes()-1; i>=0; i-- ) - if( fmodf(in.GetHoldNote(i).fStartBeat,1) != 0 ) // doesn't start on a beat + if( fmodf(in.GetHoldNote(i).GetStartBeat(),1) != 0 ) // doesn't start on a beat in.RemoveHoldNote( i ); } @@ -775,7 +774,7 @@ void NoteDataUtil::AddMines( NoteData &in, float fStartBeat, float fEndBeat ) for( int i=0; i last_row ) continue; @@ -887,7 +886,7 @@ void NoteDataUtil::ConvertTapsToHolds( NoteData &in, int iSimultaneousHolds, flo // to a hold that lasts for at least one beat. if( r2==r+1 ) fEndBeat = fStartBeat+1; - in.AddHoldNote( HoldNote(t,fStartBeat,fEndBeat) ); + in.AddHoldNote( HoldNote(t,BeatToNoteRow(fStartBeat),BeatToNoteRow(fEndBeat)) ); } dont_add_hold: ; diff --git a/stepmania/src/NoteDataWithScoring.cpp b/stepmania/src/NoteDataWithScoring.cpp index 621c107858..7244280e4f 100644 --- a/stepmania/src/NoteDataWithScoring.cpp +++ b/stepmania/src/NoteDataWithScoring.cpp @@ -92,12 +92,15 @@ int NoteDataWithScoring::GetNumHoldNotesWithScore( HoldNoteScore hns, const floa int iNumSuccessfulHolds = 0; if(fEndBeat == -1) - fEndBeat = GetMaxBeat()+1; + fEndBeat = GetMaxBeat(); + + int iStartIndex = BeatToNoteRow( fStartBeat ); + int iEndIndex = BeatToNoteRow( fEndBeat ); for( int i=0; im_CurrentPlayerOptions[m_PlayerNumber].GetReversePercentForColumn(iCol) > 0.5; - const float fStartYOffset = ArrowGetYOffset( m_PlayerNumber, iCol, hn.fStartBeat ); + const float fStartYOffset = ArrowGetYOffset( m_PlayerNumber, iCol, hn.GetStartBeat() ); const float fStartYPos = ArrowGetYPos( m_PlayerNumber, iCol, fStartYOffset, fReverseOffsetPixels ); - const float fEndYOffset = ArrowGetYOffset( m_PlayerNumber, iCol, hn.fEndBeat ); + const float fEndYOffset = ArrowGetYOffset( m_PlayerNumber, iCol, hn.GetEndBeat() ); const float fEndYPos = ArrowGetYPos( m_PlayerNumber, iCol, fEndYOffset, fReverseOffsetPixels ); const float fYHead = bReverse ? fEndYPos : fStartYPos; // the center of the head diff --git a/stepmania/src/NoteField.cpp b/stepmania/src/NoteField.cpp index 46a73be5da..250153aa13 100644 --- a/stepmania/src/NoteField.cpp +++ b/stepmania/src/NoteField.cpp @@ -529,18 +529,22 @@ void NoteField::DrawPrimitives() continue; // If no part of this HoldNote is on the screen, skip it - if( !( fFirstBeatToDraw <= hn.fEndBeat && hn.fEndBeat <= fLastBeatToDraw || - fFirstBeatToDraw <= hn.fStartBeat && hn.fStartBeat <= fLastBeatToDraw || - hn.fStartBeat < fFirstBeatToDraw && hn.fEndBeat > fLastBeatToDraw ) ) + if( !( iFirstIndexToDraw <= hn.iEndRow && hn.iEndRow <= iLastIndexToDraw || + iFirstIndexToDraw <= hn.iStartRow && hn.iStartRow <= iLastIndexToDraw || + hn.iStartRow < iFirstIndexToDraw && hn.iEndRow > iLastIndexToDraw ) ) { continue; // skip } - SearchForBeat( CurDisplay, NextDisplay, hn.fStartBeat ); + SearchForBeat( CurDisplay, NextDisplay, NoteRowToBeat(hn.iStartRow) ); bool bIsInSelectionRange = false; if( m_fBeginMarker!=-1 && m_fEndMarker!=-1 ) - bIsInSelectionRange = m_fBeginMarker<=hn.fStartBeat && hn.fStartBeat<=m_fEndMarker && m_fBeginMarker<=hn.fEndBeat && hn.fEndBeat<=m_fEndMarker; + bIsInSelectionRange = + m_fBeginMarker <= hn.GetStartBeat() && + hn.GetStartBeat() <= m_fEndMarker && + m_fBeginMarker <= hn.GetEndBeat() && + hn.GetEndBeat() <= m_fEndMarker; NoteDisplayCols *nd = CurDisplay->second; diff --git a/stepmania/src/NoteTypes.h b/stepmania/src/NoteTypes.h index 8d4387210f..32b35708f1 100644 --- a/stepmania/src/NoteTypes.h +++ b/stepmania/src/NoteTypes.h @@ -132,17 +132,6 @@ NoteType BeatToNoteType( float fBeat ); bool IsNoteOfType( int iNoteIndex, NoteType t ); CString NoteTypeToString( NoteType nt ); - - -struct HoldNote -{ - HoldNote( int t, float s, float e ) { iTrack=t; fStartBeat=s; fEndBeat=e; } - int iTrack; - float fStartBeat; - float fEndBeat; -}; - - inline int BeatToNoteRow( float fBeatNum ) { return int( fBeatNum * ROWS_PER_BEAT + 0.5f); }; // round inline int BeatToNoteRowNotRounded( float fBeatNum ) { return (int)( fBeatNum * ROWS_PER_BEAT ); }; inline float NoteRowToBeat( float fNoteIndex ) { return fNoteIndex / (float)ROWS_PER_BEAT; }; @@ -150,5 +139,30 @@ inline float NoteRowToBeat( int iNoteIndex ) { return NoteRowToBeat( (float)iN +struct HoldNote +{ + HoldNote( int t, int s, int e ) { iTrack=t; iStartRow=s; iEndRow=e; } + bool RowIsInRange( int row ) const { return iStartRow <= row && row <= iEndRow; } + bool RangeOverlaps( int start, int end ) const + { + return + ( iStartRow >= start && end >= iEndRow ) || // other consumes us + ( iStartRow <= start && end <= iEndRow ) || // other inside us + ( iStartRow <= start && start <= iEndRow ) || // other overlaps us + ( iStartRow <= end && end <= iEndRow ); // other overlaps us + } + bool RangeOverlaps( const HoldNote &hn ) const { return RangeOverlaps(hn.iStartRow, hn.iEndRow); } + bool RangeInside( int start, int end ) const { return iStartRow <= start && end <= iEndRow; } + + float GetStartBeat() const { return NoteRowToBeat( iStartRow ); } + float GetEndBeat() const { return NoteRowToBeat( iEndRow ); } + int iTrack; + int iStartRow; + int iEndRow; +}; + + + + #endif diff --git a/stepmania/src/NotesLoaderKSF.cpp b/stepmania/src/NotesLoaderKSF.cpp index 12771cba41..d5354cdc4e 100644 --- a/stepmania/src/NotesLoaderKSF.cpp +++ b/stepmania/src/NotesLoaderKSF.cpp @@ -184,8 +184,8 @@ bool KSFLoader::LoadFromKSFFile( const CString &sPath, Steps &out, const Song &s { HoldNote hn ( t, /* button */ - iHoldStartRow[t]/(float)iTickCount, /* start */ - (r-1)/(float)iTickCount /* end */ + BeatToNoteRow(iHoldStartRow[t]/(float)iTickCount), /* start */ + BeatToNoteRow((r-1)/(float)iTickCount) /* end */ ); notedata.AddHoldNote( hn ); iHoldStartRow[t] = -1; diff --git a/stepmania/src/Player.cpp b/stepmania/src/Player.cpp index 985cece809..d9668f4092 100644 --- a/stepmania/src/Player.cpp +++ b/stepmania/src/Player.cpp @@ -238,6 +238,7 @@ void PlayerMinus::Update( float fDeltaTime ) const float fSongBeat = GAMESTATE->m_fSongBeat; + const int iSongRow = BeatToNoteRow( fSongBeat ); m_pNoteField->Update( fDeltaTime ); @@ -282,7 +283,7 @@ void PlayerMinus::Update( float fDeltaTime ) const HoldNote &hn = GetHoldNote(i); HoldNoteScore hns = GetHoldNoteScore(i); float fLife = GetHoldNoteLife(i); - int iHoldStartIndex = BeatToNoteRow(hn.fStartBeat); + int iHoldStartIndex = hn.iStartRow; m_pNoteField->m_bIsHoldingHoldNote[i] = false; // set host flag so NoteField can do intelligent drawing @@ -297,7 +298,7 @@ void PlayerMinus::Update( float fDeltaTime ) const bool bSteppedOnTapNote = tns != TNS_NONE && tns != TNS_MISS; // did they step on the start of this hold? // If the song beat is in the range of this hold: - if( hn.fStartBeat <= fSongBeat && fSongBeat <= hn.fEndBeat ) + if( hn.iStartRow <= iSongRow && iSongRow <= hn.iEndRow ) { bool bIsHoldingButton = INPUTMAPPER->IsButtonDown( GameI ); @@ -316,7 +317,7 @@ void PlayerMinus::Update( float fDeltaTime ) // its HoldNote::fEndBeat. Otherwise, when HoldNotes are converted to the // 4s representation, it disappears, which causes problems for the way we // store HoldNote life (by index of the hold). - m_pNoteField->GetHoldNote(i).fStartBeat = min( fSongBeat, m_pNoteField->GetHoldNote(i).fEndBeat -NoteRowToBeat(1) ); + m_pNoteField->GetHoldNote(i).iStartRow = min( iSongRow, m_pNoteField->GetHoldNote(i).iEndRow-1 ); } if( bSteppedOnTapNote && bIsHoldingButton ) @@ -347,7 +348,7 @@ void PlayerMinus::Update( float fDeltaTime ) hns = HNS_NG; // check for OK - if( fSongBeat >= hn.fEndBeat && bSteppedOnTapNote && fLife > 0 ) // if this HoldNote is in the past + if( iSongRow >= hn.iEndRow && bSteppedOnTapNote && fLife > 0 ) // if this HoldNote is in the past { fLife = 1; hns = HNS_OK; diff --git a/stepmania/src/ScreenEdit.cpp b/stepmania/src/ScreenEdit.cpp index fdf6b21785..be7ca716ca 100644 --- a/stepmania/src/ScreenEdit.cpp +++ b/stepmania/src/ScreenEdit.cpp @@ -416,7 +416,7 @@ void ScreenEdit::Update( float fDeltaTime ) fEndBeat = froundf( fEndBeat, NoteTypeToBeat(m_SnapDisplay.GetNoteType()) ); // create a new hold note - HoldNote newHN( t, fStartBeat, fEndBeat ); + HoldNote newHN( t, BeatToNoteRow(fStartBeat), BeatToNoteRow(fEndBeat) ); m_NoteFieldRecord.AddHoldNote( newHN ); } } @@ -656,7 +656,7 @@ void ScreenEdit::InputEdit( const DeviceInput& DeviceI, const InputEventType typ { const HoldNote &hn = m_NoteFieldEdit.GetHoldNote(i); if( iCol == hn.iTrack && // the notes correspond - fSongBeat >= hn.fStartBeat && fSongBeat <= hn.fEndBeat ) // the cursor lies within this HoldNote + hn.RowIsInRange(iSongIndex) ) // the cursor lies within this HoldNote { m_NoteFieldEdit.RemoveHoldNote( i ); return; @@ -764,10 +764,10 @@ void ScreenEdit::InputEdit( const DeviceInput& DeviceI, const InputEventType typ continue; // create a new hold note - HoldNote newHN( iCol, min(fStartBeat, fEndBeat), max(fStartBeat, fEndBeat) ); + HoldNote newHN( iCol, BeatToNoteRow(min(fStartBeat, fEndBeat)), BeatToNoteRow(max(fStartBeat, fEndBeat)) ); - newHN.fStartBeat = max(newHN.fStartBeat, 0); - newHN.fEndBeat = max(newHN.fEndBeat, 0); + newHN.iStartRow = max(newHN.iStartRow, 0); + newHN.iEndRow = max(newHN.iEndRow, 0); m_NoteFieldEdit.AddHoldNote( newHN ); }