diff --git a/stepmania/src/NoteData.cpp b/stepmania/src/NoteData.cpp index 8a52e322ae..04136ff9b0 100644 --- a/stepmania/src/NoteData.cpp +++ b/stepmania/src/NoteData.cpp @@ -174,6 +174,40 @@ void NoteData::RemoveHoldNote( int iHoldIndex ) m_HoldNotes.erase(m_HoldNotes.begin()+iHoldIndex, m_HoldNotes.begin()+iHoldIndex+1); } +void NoteData::AddAttackNote( AttackNote an ) +{ + m_AttackNotes.push_back(an); +} + +void NoteData::RemoveAttackNote( int index ) +{ + m_AttackNotes.erase( m_AttackNotes.begin()+index ); +} + +bool CompareAttackNotes( const AttackNote& an1, const AttackNote& an2 ) +{ + return an1.fBeat < an2.fBeat; +} + +void NoteData::ShuffleAttackNotesOnSameRow() +{ + // sort, then shuffle + sort( m_AttackNotes.begin(), m_AttackNotes.end(), CompareAttackNotes ); + + for( int i=0; i m_HoldNotes; + vector m_AttackNotes; + /* Pad m_TapNotes so it includes the row "rows". */ void PadTapNotes(int rows); @@ -51,8 +53,7 @@ public: } void MoveTapNoteTrack(int dest, int src); void SetTapNote(int track, int row, TapNote t); - void SetTapNoteAttack( int track, int row, CString sMods, float fDurationSeconds ); - + void ClearRange( int iNoteIndexBegin, int iNoteIndexEnd ); void ClearAll(); void CopyRange( const NoteData* pFrom, int iFromIndexBegin, int iFromIndexEnd, int iToIndexBegin = -1 ); @@ -139,6 +140,12 @@ public: HoldNote &GetHoldNote( int index ) { return m_HoldNotes[index]; } const HoldNote &GetHoldNote( int index ) const { return m_HoldNotes[index]; } + // used in edit/record + void AddAttackNote( AttackNote an ); // add note hold note merging overlapping HoldNotes and destroying TapNotes underneath + void RemoveAttackNote( int index ); + const AttackNote& GetAttackNote( int index ) { return m_AttackNotes[index]; } + void ShuffleAttackNotesOnSameRow(); + // statistics /* Return the highest beat/row that might contain notes. (Use GetLastBeat if you need @@ -157,6 +164,7 @@ public: /* optimization: for the default of start to end, use the second (faster) */ int GetNumHoldNotes( const float fStartBeat, const float fEndBeat = -1 ) const; int GetNumHoldNotes() const { return m_HoldNotes.size(); } + int GetNumAttackNotes() const { return m_AttackNotes.size(); } // Transformations void LoadTransformed( const NoteData* pOriginal, int iNewNumTracks, const int iOriginalTrackToTakeFrom[] ); // -1 for iOriginalTracksToTakeFrom means no track diff --git a/stepmania/src/NoteDataUtil.cpp b/stepmania/src/NoteDataUtil.cpp index 1277f82d41..31abe85f0a 100644 --- a/stepmania/src/NoteDataUtil.cpp +++ b/stepmania/src/NoteDataUtil.cpp @@ -169,17 +169,7 @@ void NoteDataUtil::GetSMNoteDataString( const NoteData &in_, CString &out ) case TAP_HOLD_HEAD: c = '2'; break; case TAP_HOLD_TAIL: c = '3'; break; case TAP_MINE: c = 'M'; break; - default: - if( tn >= TAP_ATTACK_BEGIN && tn <= TAP_ATTACK_END ) - { - c = tn - TAP_ATTACK_BEGIN + 'a'; // TODO: overflow check? - } - else - { - ASSERT(0); - c = '0'; - } - break; + default: ASSERT(0); c = '0'; break; } sRet.append(1, c); } diff --git a/stepmania/src/NoteDisplay.cpp b/stepmania/src/NoteDisplay.cpp index ed75fd979d..89462e5eea 100644 --- a/stepmania/src/NoteDisplay.cpp +++ b/stepmania/src/NoteDisplay.cpp @@ -824,7 +824,7 @@ void NoteDisplay::DrawHold( const HoldNote& hn, const bool bActive, const float DrawHold( hn, bActive, fLife, fPercentFadeToFail, true, fReverseOffsetPixels ); } -void NoteDisplay::DrawTap( int iCol, float fBeat, bool bOnSameRowAsHoldStart, bool bIsAddition, bool bIsMine, float fPercentFadeToFail, float fLife, float fReverseOffsetPixels ) +void NoteDisplay::DrawActor( Actor* pActor, int iCol, float fBeat, float fPercentFadeToFail, float fLife, float fReverseOffsetPixels ) { const float fYOffset = ArrowGetYOffset( m_PlayerNumber, iCol, fBeat ); const float fYPos = ArrowGetYPos( m_PlayerNumber, iCol, fYOffset, fReverseOffsetPixels ); @@ -837,16 +837,6 @@ void NoteDisplay::DrawTap( int iCol, float fBeat, bool bOnSameRowAsHoldStart, bo RageColor diffuse = RageColor(fColorScale,fColorScale,fColorScale,fAlpha); RageColor glow = RageColor(1,1,1,fGlow); - Actor* pActor = NULL; - if( bIsMine ) - pActor = GetTapMineActor( fBeat ); - else if( bIsAddition ) - pActor = GetTapAdditionActor( fBeat ); - else if( bOnSameRowAsHoldStart && cache->m_bDrawHoldHeadForTapsOnSameRow ) - pActor = GetHoldHeadActor( fBeat, false ); - else - pActor = GetTapNoteActor( fBeat ); - pActor->SetRotationZ( fRotation ); pActor->SetXY( fXPos, fYPos ); pActor->SetZ( fZPos ); @@ -873,6 +863,21 @@ void NoteDisplay::DrawTap( int iCol, float fBeat, bool bOnSameRowAsHoldStart, bo } } +void NoteDisplay::DrawTap( int iCol, float fBeat, bool bOnSameRowAsHoldStart, bool bIsAddition, bool bIsMine, float fPercentFadeToFail, float fLife, float fReverseOffsetPixels ) +{ + Actor* pActor = NULL; + if( bIsMine ) + pActor = GetTapMineActor( fBeat ); + else if( bIsAddition ) + pActor = GetTapAdditionActor( fBeat ); + else if( bOnSameRowAsHoldStart && cache->m_bDrawHoldHeadForTapsOnSameRow ) + pActor = GetHoldHeadActor( fBeat, false ); + else + pActor = GetTapNoteActor( fBeat ); + + DrawActor( pActor, iCol, fBeat, fPercentFadeToFail, fLife, fReverseOffsetPixels ); +} + // if( ct == PlayerOptions::COLOR_NOTE ) // { diff --git a/stepmania/src/NoteDisplay.h b/stepmania/src/NoteDisplay.h index 26069655b8..1063bd4e9d 100644 --- a/stepmania/src/NoteDisplay.h +++ b/stepmania/src/NoteDisplay.h @@ -29,6 +29,7 @@ public: void Load( int iColNum, PlayerNumber pn, CString NoteSkin, float fYReverseOffsetPixels ); + void DrawActor( Actor* pActor, int iCol, float fBeat, float fPercentFadeToFail, float fLife, float fReverseOffsetPixels ); void DrawTap( int iCol, float fBeat, bool bOnSameRowAsHoldStart, bool bIsAddition, bool bIsMine, float fPercentFadeToFail, float fLife, float fReverseOffsetPixels ); void DrawHold( const HoldNote& hn, bool bActive, float fLife, float fPercentFadeToFail, bool bDrawGlowOnly, float fReverseOffsetPixels ); diff --git a/stepmania/src/NoteField.cpp b/stepmania/src/NoteField.cpp index adb20aeead..0fe38260b0 100644 --- a/stepmania/src/NoteField.cpp +++ b/stepmania/src/NoteField.cpp @@ -465,9 +465,9 @@ void NoteField::DrawPrimitives() { g_NoteFieldMode[m_PlayerNumber].BeginDrawTrack(c); - ///////////////////////////////// + // // Draw all HoldNotes in this column (so that they appear under the tap notes) - ///////////////////////////////// + // int i; NDMap::iterator CurDisplay = m_BeatToNoteDisplays.begin(); @@ -507,9 +507,9 @@ void NoteField::DrawPrimitives() } - /////////////////////////////////// + // // Draw all TapNotes in this column - /////////////////////////////////// + // CurDisplay = m_BeatToNoteDisplays.begin(); NextDisplay = CurDisplay; ++NextDisplay; @@ -543,25 +543,41 @@ void NoteField::DrawPrimitives() bool bIsAddition = (tn == TAP_ADDITION); bool bIsMine = (tn == TAP_MINE); - bool bIsAttack = (tn==TAP_ATTACK); - if( bIsAttack ) - { - const AttackNote* pA = GetAttackNoteAt( c, i ); - Sprite sprite; - sprite.Load( THEME->GetPathToG("NoteField attack "+pA->sModifiers) ); - SearchForBeat( CurDisplay, NextDisplay, NoteRowToBeat(i) ); - NoteDisplayCols *nd = CurDisplay->second; - nd->display[c].DrawActor( &sprite, c, NoteRowToBeat(i), bIsInSelectionRange ? fSelectedRangeGlow : m_fPercentFadeToFail, 1, m_fYReverseOffsetPixels ); - } - else - { - SearchForBeat( CurDisplay, NextDisplay, NoteRowToBeat(i) ); - NoteDisplayCols *nd = CurDisplay->second; - nd->display[c].DrawTap( c, NoteRowToBeat(i), bHoldNoteBeginsOnThisBeat, bIsAddition, bIsMine, bIsInSelectionRange ? fSelectedRangeGlow : m_fPercentFadeToFail, 1, m_fYReverseOffsetPixels ); - } + SearchForBeat( CurDisplay, NextDisplay, NoteRowToBeat(i) ); + NoteDisplayCols *nd = CurDisplay->second; + nd->display[c].DrawTap( c, NoteRowToBeat(i), bHoldNoteBeginsOnThisBeat, bIsAddition, bIsMine, bIsInSelectionRange ? fSelectedRangeGlow : m_fPercentFadeToFail, 1, m_fYReverseOffsetPixels ); } + + // + // Draw all AttackNotes in this column + // + for( i=0; i < GetNumAttackNotes(); i++ ) + { + const AttackNote& an = GetAttackNote( i ); + + // If this AttackNote isn't on the screen, skip it + if( an.iTrack != c || + an.fBeat < fFirstBeatToDraw || + an.fBeat > fLastBeatToDraw ) + continue; // skip + + bool bIsInSelectionRange = false; + if( m_fBeginMarker!=-1 && m_fEndMarker!=-1 ) + { + bIsInSelectionRange = m_fBeginMarker<=an.fBeat && an.fBeat<=m_fEndMarker; + } + + + Sprite sprite; + sprite.Load( THEME->GetPathToG("NoteField attack "+an.sModifiers) ); + SearchForBeat( CurDisplay, NextDisplay, an.fBeat ); + NoteDisplayCols *nd = CurDisplay->second; + nd->display[c].DrawActor( &sprite, an.iTrack, an.fBeat, bIsInSelectionRange ? fSelectedRangeGlow : m_fPercentFadeToFail, 1, m_fYReverseOffsetPixels ); + } + + g_NoteFieldMode[m_PlayerNumber].EndDrawTrack(c); } diff --git a/stepmania/src/NoteTypes.h b/stepmania/src/NoteTypes.h index 1c1727150e..760a6394a2 100644 --- a/stepmania/src/NoteTypes.h +++ b/stepmania/src/NoteTypes.h @@ -40,7 +40,8 @@ static const TapNote TAP_MINE = '6'; // MD 11/12/03 - for future modifiers // TAP_ADD_HOLD is to TAP_HOLD what TAP_ADDITION is to TAP_TAP. // There is no equivalent for TAP_MINE. -static const TapNote TAP_ADD_HOLD = '7'; +static const TapNote TAP_ADD_HOLD = '7'; // is this supposed to be TAP_ADD_HOLD_HEAD? -Chris + // BM-specific // Removed taps, e.g. in Little - play keysounds here as if @@ -69,10 +70,6 @@ static const TapNote TAP_REMOVED_HOLD_TAIL = '\''; // MD 11/12/03 end -// attack note start. Use lowercase letters a-z. -// Don't use uppercase letters - 'M' it taken for mine. -static const TapNote TAP_ATTACK_BEGIN = 'a'; -static const TapNote TAP_ATTACK_END = 'z'; enum { @@ -135,6 +132,15 @@ struct HoldNote float fEndBeat; }; +struct AttackNote +{ + AttackNote( int t, float b, CString m, float d ) { iTrack=t; fBeat=b; sModifiers=m; fDurationSeconds=d; } + int iTrack; + float fBeat; + CString sModifiers; + float fDurationSeconds; +}; + 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 ); }; diff --git a/stepmania/src/NotesWriterDWI.cpp b/stepmania/src/NotesWriterDWI.cpp index 02014e1294..518b56476c 100644 --- a/stepmania/src/NotesWriterDWI.cpp +++ b/stepmania/src/NotesWriterDWI.cpp @@ -19,11 +19,6 @@ CString NotesWriterDWI::NotesToDWIString( const TapNote cNoteCols[6] ) case TAP_EMPTY: case TAP_MINE: continue; - default: - if( cNoteCols[col] >= TAP_ATTACK_BEGIN && cNoteCols[col] <= TAP_ATTACK_END ) - continue; - else - ASSERT(0); } if( cNoteCols[col] == TAP_HOLD_HEAD ) diff --git a/stepmania/src/ScreenEdit.cpp b/stepmania/src/ScreenEdit.cpp index d8a4dab3ee..5aae093ff5 100644 --- a/stepmania/src/ScreenEdit.cpp +++ b/stepmania/src/ScreenEdit.cpp @@ -663,41 +663,51 @@ void ScreenEdit::InputEdit( const DeviceInput& DeviceI, const InputEventType typ if( iCol >= m_NoteFieldEdit.GetNumTracks() ) // this button is not in the range of columns for this StyleDef break; + int i; + // check for to see if the user intended to remove a HoldNote - bool bRemovedAHoldNote = false; - for( int i=0; i= hn.fStartBeat && fSongBeat <= hn.fEndBeat ) // the cursor lies within this HoldNote { m_NoteFieldEdit.RemoveHoldNote( i ); - bRemovedAHoldNote = true; - break; // stop iterating over all HoldNotes + return; } } - if( !bRemovedAHoldNote ) + // check for to see if the user intended to remove an AttackNote + for( i=0; iIsBeingPressed(DeviceInput(DEVICE_KEYBOARD, SDLK_LSHIFT)) ) - m_NoteFieldEdit.SetTapNote(iCol, iSongIndex, TAP_MINE ); - else if( INPUTFILTER->IsBeingPressed(DeviceInput(DEVICE_KEYBOARD, SDLK_RSHIFT)) ) - { - g_iLastInsertAttackTrack = iCol; - SCREENMAN->MiniMenu( &g_InsertAttack, SM_BackFromInsertAttack ); - } - else - m_NoteFieldEdit.SetTapNote(iCol, iSongIndex, TAP_TAP ); + m_NoteFieldEdit.RemoveAttackNote( i ); + return; } } + + if( m_NoteFieldEdit.GetTapNote(iCol, iSongIndex) != TAP_EMPTY ) + { + m_NoteFieldEdit.SetTapNote( iCol, iSongIndex, TAP_EMPTY ); + return; + } + + // Hold LShift to lay mine, hold RShift to lay an attack + if( INPUTFILTER->IsBeingPressed(DeviceInput(DEVICE_KEYBOARD, SDLK_LSHIFT)) ) + { + m_NoteFieldEdit.SetTapNote(iCol, iSongIndex, TAP_MINE ); + } + else if( INPUTFILTER->IsBeingPressed(DeviceInput(DEVICE_KEYBOARD, SDLK_RSHIFT)) ) + { + g_iLastInsertAttackTrack = iCol; + SCREENMAN->MiniMenu( &g_InsertAttack, SM_BackFromInsertAttack ); + } + else + { + m_NoteFieldEdit.SetTapNote(iCol, iSongIndex, TAP_TAP ); + } } break; case SDLK_UP: @@ -1276,9 +1286,7 @@ void ScreenEdit::HandleScreenMessage( const ScreenMessage SM ) { PlayerOptions poChosen = GAMESTATE->m_PlayerOptions[PLAYER_1]; CString sMods = poChosen.GetString(); - int row = BeatToNoteRow( GAMESTATE->m_fSongBeat ); - m_NoteFieldEdit.SetTapNote( g_iLastInsertAttackTrack, row, TAP_TAP ); - m_NoteFieldEdit.SetTapNoteAttack( g_iLastInsertAttackTrack, row, sMods, g_fLastInsertAttackDurationSeconds ); + m_NoteFieldEdit.AddAttackNote( AttackNote(g_iLastInsertAttackTrack,GAMESTATE->m_fSongBeat,sMods,g_fLastInsertAttackDurationSeconds) ); GAMESTATE->RestoreSelectedOptions(); // restore the edit and playback options } break;