Merge pull request #236 from kyzentun/RevalidateNoteDataATIs

Added revalidation scheme to NoteData's all_tracks_iterator
This commit is contained in:
kyzentun
2014-07-30 23:02:13 -06:00
3 changed files with 194 additions and 5 deletions
+129 -2
View File
@@ -1176,6 +1176,48 @@ void NoteData::LoadFromNode( const XNode* pNode )
FAIL_M("NoteData::LoadFromNode() not implemented");
}
void NoteData::AddATIToList(all_tracks_iterator* iter) const
{
m_atis.insert(iter);
}
void NoteData::AddATIToList(all_tracks_const_iterator* iter) const
{
m_const_atis.insert(iter);
}
void NoteData::RemoveATIFromList(all_tracks_iterator* iter) const
{
set<all_tracks_iterator*>::iterator pos= m_atis.find(iter);
if(pos != m_atis.end())
{
m_atis.erase(pos);
}
}
void NoteData::RemoveATIFromList(all_tracks_const_iterator* iter) const
{
set<all_tracks_const_iterator*>::iterator pos= m_const_atis.find(iter);
if(pos != m_const_atis.end())
{
m_const_atis.erase(pos);
}
}
void NoteData::RevalidateATIs(vector<int> const& added_or_removed_tracks, bool added)
{
for(set<all_tracks_iterator*>::iterator cur= m_atis.begin();
cur != m_atis.end(); ++cur)
{
(*cur)->Revalidate(this, added_or_removed_tracks, added);
}
for(set<all_tracks_const_iterator*>::iterator cur= m_const_atis.begin();
cur != m_const_atis.end(); ++cur)
{
(*cur)->Revalidate(this, added_or_removed_tracks, added);
}
}
template<typename ND, typename iter, typename TN>
void NoteData::_all_tracks_iterator<ND, iter, TN>::Find( bool bReverse )
{
@@ -1213,14 +1255,18 @@ void NoteData::_all_tracks_iterator<ND, iter, TN>::Find( bool bReverse )
}
template<typename ND, typename iter, typename TN>
NoteData::_all_tracks_iterator<ND, iter, TN>::_all_tracks_iterator( ND &nd, int iStartRow, int iEndRow, bool bReverse, bool bInclusive ) :
NoteData::_all_tracks_iterator<ND, iter, TN>::_all_tracks_iterator( ND &nd, int iStartRow, int iEndRow, bool bReverse, bool bInclusive ) :
m_pNoteData(&nd), m_iTrack(0), m_bReverse(bReverse)
{
ASSERT( m_pNoteData->GetNumTracks() > 0 );
m_StartRow= iStartRow;
m_EndRow= iEndRow;
for( int iTrack = 0; iTrack < m_pNoteData->GetNumTracks(); ++iTrack )
{
iter begin, end;
m_Inclusive= bInclusive;
if( bInclusive )
m_pNoteData->GetTapNoteRangeInclusive( iTrack, iStartRow, iEndRow, begin, end );
else
@@ -1228,6 +1274,7 @@ NoteData::_all_tracks_iterator<ND, iter, TN>::_all_tracks_iterator( ND &nd, int
m_vBeginIters.push_back( begin );
m_vEndIters.push_back( end );
m_PrevCurrentRows.push_back(0);
iter cur;
if( m_bReverse )
@@ -1242,6 +1289,7 @@ NoteData::_all_tracks_iterator<ND, iter, TN>::_all_tracks_iterator( ND &nd, int
}
m_vCurrentIters.push_back( cur );
}
m_pNoteData->AddATIToList(this);
Find( bReverse );
}
@@ -1254,14 +1302,28 @@ NoteData::_all_tracks_iterator<ND, iter, TN>::_all_tracks_iterator( const _all_t
COPY_OTHER( m_vCurrentIters ),
COPY_OTHER( m_vEndIters ),
COPY_OTHER( m_iTrack ),
COPY_OTHER( m_bReverse )
COPY_OTHER( m_bReverse ),
COPY_OTHER( m_PrevCurrentRows ),
COPY_OTHER( m_StartRow ),
COPY_OTHER( m_EndRow )
#undef COPY_OTHER
{
m_pNoteData->AddATIToList(this);
}
template<typename ND, typename iter, typename TN>
NoteData::_all_tracks_iterator<ND, iter, TN>::~_all_tracks_iterator()
{
if(m_pNoteData != NULL)
{
m_pNoteData->RemoveATIFromList(this);
}
}
template<typename ND, typename iter, typename TN>
NoteData::_all_tracks_iterator<ND, iter, TN> &NoteData::_all_tracks_iterator<ND, iter, TN>::operator++() // preincrement
{
m_PrevCurrentRows[m_iTrack]= Row();
if( m_bReverse )
{
if( m_vCurrentIters[m_iTrack] == m_vBeginIters[m_iTrack] )
@@ -1284,6 +1346,71 @@ NoteData::_all_tracks_iterator<ND, iter, TN> NoteData::_all_tracks_iterator<ND,
operator++();
return ret;
}
template<typename ND, typename iter, typename TN>
void NoteData::_all_tracks_iterator<ND, iter, TN>::Revalidate(
ND* notedata, vector<int> const& added_or_removed_tracks, bool added)
{
m_pNoteData= notedata;
ASSERT( m_pNoteData->GetNumTracks() > 0 );
if(!added_or_removed_tracks.empty())
{
if(added)
{
int avg_row= 0;
for(size_t p= 0; p < m_PrevCurrentRows.size(); ++p)
{
avg_row+= m_PrevCurrentRows[p];
}
avg_row/= m_PrevCurrentRows.size();
for(size_t a= 0; a < added_or_removed_tracks.size(); ++a)
{
int track_id= added_or_removed_tracks[a];
m_PrevCurrentRows.insert(m_PrevCurrentRows.begin()+track_id, avg_row);
}
m_vBeginIters.resize(m_pNoteData->GetNumTracks());
m_vCurrentIters.resize(m_pNoteData->GetNumTracks());
m_vEndIters.resize(m_pNoteData->GetNumTracks());
}
else
{
for(size_t a= 0; a < added_or_removed_tracks.size(); ++a)
{
int track_id= added_or_removed_tracks[a];
m_PrevCurrentRows.erase(m_PrevCurrentRows.begin()+track_id);
}
m_vBeginIters.resize(m_pNoteData->GetNumTracks());
m_vCurrentIters.resize(m_pNoteData->GetNumTracks());
m_vEndIters.resize(m_pNoteData->GetNumTracks());
}
}
for(int track= 0; track < m_pNoteData->GetNumTracks(); ++track)
{
iter begin, end;
if(m_Inclusive)
{
m_pNoteData->GetTapNoteRangeInclusive(track, m_StartRow, m_EndRow, begin, end);
}
else
{
m_pNoteData->GetTapNoteRange(track, m_StartRow, m_EndRow, begin, end);
}
m_vBeginIters[track]= begin;
m_vEndIters[track]= end;
iter cur;
if(m_bReverse)
{
cur= m_pNoteData->upper_bound(track, m_PrevCurrentRows[track]);
}
else
{
cur= m_pNoteData->lower_bound(track, m_PrevCurrentRows[track]);
}
m_vCurrentIters[track]= cur;
}
Find(m_bReverse);
}
/* XXX: This doesn't satisfy the requirements that ++iter; --iter; is a no-op so it cannot be bidirectional for now. */
#if 0
template<typename ND, typename iter, typename TN>
+33 -2
View File
@@ -47,7 +47,12 @@ public:
const_iterator lower_bound( int iTrack, int iRow ) const { return m_TapNotes[iTrack].lower_bound( iRow ); }
iterator upper_bound( int iTrack, int iRow ) { return m_TapNotes[iTrack].upper_bound( iRow ); }
const_iterator upper_bound( int iTrack, int iRow ) const { return m_TapNotes[iTrack].upper_bound( iRow ); }
void swap( NoteData &nd ) { m_TapNotes.swap( nd.m_TapNotes ); }
void swap( NoteData &nd )
{
m_TapNotes.swap(nd.m_TapNotes);
m_atis.swap(nd.m_atis);
m_const_atis.swap(nd.m_const_atis);
}
// This is ugly to make it templated but I don't want to have to write the same class twice.
@@ -65,10 +70,18 @@ public:
int m_iTrack;
bool m_bReverse;
// These exist so that the iterator can be revalidated if the NoteData is
// transformed during this iterator's lifetime.
vector<int> m_PrevCurrentRows;
bool m_Inclusive;
int m_StartRow;
int m_EndRow;
void Find( bool bReverse );
public:
_all_tracks_iterator( ND &nd, int iStartRow, int iEndRow, bool bReverse, bool bInclusive );
_all_tracks_iterator( const _all_tracks_iterator &other );
~_all_tracks_iterator();
_all_tracks_iterator &operator++(); // preincrement
_all_tracks_iterator operator++( int dummy ); // postincrement
//_all_tracks_iterator &operator--(); // predecrement
@@ -81,11 +94,15 @@ public:
inline TN *operator->() { DEBUG_ASSERT( !IsAtEnd() ); return &m_vCurrentIters[m_iTrack]->second; }
inline const TN &operator*() const { DEBUG_ASSERT( !IsAtEnd() ); return m_vCurrentIters[m_iTrack]->second; }
inline const TN *operator->() const { DEBUG_ASSERT( !IsAtEnd() ); return &m_vCurrentIters[m_iTrack]->second; }
// Use when transforming the NoteData.
void Revalidate(ND* notedata, vector<int> const& added_or_removed_tracks, bool added);
};
typedef _all_tracks_iterator<NoteData, NoteData::iterator, TapNote> all_tracks_iterator;
typedef _all_tracks_iterator<const NoteData, NoteData::const_iterator, const TapNote> all_tracks_const_iterator;
typedef all_tracks_iterator all_tracks_reverse_iterator;
typedef all_tracks_const_iterator all_tracks_const_reverse_iterator;
friend class _all_tracks_iterator<NoteData, NoteData::iterator, TapNote>;
friend class _all_tracks_iterator<const NoteData, NoteData::const_iterator, const TapNote>;
private:
// There's no point in inserting empty notes into the map.
// Any blank space in the map is defined to be empty.
@@ -129,7 +146,17 @@ private:
pair<int, int> GetNumRowsWithSimultaneousTapsTwoPlayer(int minTaps = 2,
int startRow = 0,
int endRow = MAX_NOTE_ROW) const;
// These exist so that they can be revalidated when something that transforms
// the NoteData occurs. -Kyz
mutable set<all_tracks_iterator*> m_atis;
mutable set<all_tracks_const_iterator*> m_const_atis;
void AddATIToList(all_tracks_iterator* iter) const;
void AddATIToList(all_tracks_const_iterator* iter) const;
void RemoveATIFromList(all_tracks_iterator* iter) const;
void RemoveATIFromList(all_tracks_const_iterator* iter) const;
public:
void Init();
@@ -196,6 +223,10 @@ public:
return all_tracks_const_iterator(*this, iStartRow, iEndRow, true, bInclusive );
}
// Call this after using any transform that changes the NoteData.
void RevalidateATIs(vector<int> const& added_or_removed_tracks, bool added);
void TransferATIs(NoteData& to);
/* Return an iterator range include iStartRow to iEndRow. Extend the range to include
* hold notes overlapping the boundary. */
void GetTapNoteRangeInclusive(int iTrack, int iStartRow, int iEndRow,
+32 -1
View File
@@ -261,6 +261,7 @@ static void LoadFromSMNoteDataStringWithPlayer( NoteData& out, const RString &sS
begin = next;
}
}
out.RevalidateATIs(vector<int>(), false);
}
void NoteDataUtil::LoadFromSMNoteDataString( NoteData &out, const RString &sSMNoteData_, bool bComposite )
@@ -311,6 +312,7 @@ void NoteDataUtil::LoadFromSMNoteDataString( NoteData &out, const RString &sSMNo
LoadFromSMNoteDataStringWithPlayer( nd, sSMNoteData, start, size, pn, iNumTracks );
}
CombineCompositeNoteData( out, vParts );
out.RevalidateATIs(vector<int>(), false);
}
void NoteDataUtil::InsertHoldTails( NoteData &inout )
@@ -487,6 +489,7 @@ void NoteDataUtil::CombineCompositeNoteData( NoteData &out, const vector<NoteDat
}
}
}
out.RevalidateATIs(vector<int>(), false);
}
@@ -557,6 +560,7 @@ void NoteDataUtil::LoadTransformedSlidingWindow( const NoteData &in, NoteData &o
out.SetTapNote( iNewTrack, r, tn );
}
}
out.RevalidateATIs(vector<int>(), false);
}
void PlaceAutoKeysound( NoteData &out, int row, TapNote akTap )
@@ -672,6 +676,7 @@ void NoteDataUtil::LoadOverlapped( const NoteData &in, NoteData &out, int iNewNu
PlaceAutoKeysound( out, row, tnFrom );
}
}
out.RevalidateATIs(vector<int>(), false);
}
int FindLongestOverlappingHoldNoteForAnyTrack( const NoteData &in, int iRow )
@@ -981,6 +986,7 @@ void NoteDataUtil::RemoveHoldNotes( NoteData &in, int iStartIndex, int iEndIndex
begin->second.type = TapNote::tap;
}
}
in.RevalidateATIs(vector<int>(), false);
}
void NoteDataUtil::ChangeRollsToHolds( NoteData &in, int iStartIndex, int iEndIndex )
@@ -997,6 +1003,7 @@ void NoteDataUtil::ChangeRollsToHolds( NoteData &in, int iStartIndex, int iEndIn
begin->second.subType = TapNote::hold_head_hold;
}
}
in.RevalidateATIs(vector<int>(), false);
}
void NoteDataUtil::ChangeHoldsToRolls( NoteData &in, int iStartIndex, int iEndIndex )
@@ -1013,6 +1020,7 @@ void NoteDataUtil::ChangeHoldsToRolls( NoteData &in, int iStartIndex, int iEndIn
begin->second.subType = TapNote::hold_head_roll;
}
}
in.RevalidateATIs(vector<int>(), false);
}
void NoteDataUtil::RemoveSimultaneousNotes( NoteData &in, int iMaxSimultaneous, int iStartIndex, int iEndIndex )
@@ -1051,6 +1059,7 @@ void NoteDataUtil::RemoveSimultaneousNotes( NoteData &in, int iMaxSimultaneous,
}
}
}
in.RevalidateATIs(vector<int>(), false);
}
void NoteDataUtil::RemoveJumps( NoteData &inout, int iStartIndex, int iEndIndex )
@@ -1074,6 +1083,7 @@ void NoteDataUtil::RemoveSpecificTapNotes( NoteData &inout, TapNote::Type tn, in
FOREACH_NONEMPTY_ROW_IN_TRACK_RANGE( inout, t, r, iStartIndex, iEndIndex )
if( inout.GetTapNote(t,r).type == tn )
inout.SetTapNote( t, r, TAP_EMPTY );
inout.RevalidateATIs(vector<int>(), false);
}
void NoteDataUtil::RemoveMines( NoteData &inout, int iStartIndex, int iEndIndex )
@@ -1110,6 +1120,7 @@ void NoteDataUtil::RemoveAllButOneTap( NoteData &inout, int row )
if( iter != inout.end(track) && iter->second.type == TapNote::tap )
inout.RemoveTapNote( track, iter );
}
inout.RevalidateATIs(vector<int>(), false);
}
void NoteDataUtil::RemoveAllButPlayer( NoteData &inout, PlayerNumber pn )
@@ -1126,6 +1137,7 @@ void NoteDataUtil::RemoveAllButPlayer( NoteData &inout, PlayerNumber pn )
++i;
}
}
inout.RevalidateATIs(vector<int>(), false);
}
// TODO: Perform appropriate matrix calculations for everything instead.
@@ -1536,6 +1548,7 @@ void NoteDataUtil::Turn( NoteData &inout, StepsType st, TrackMapping tt, int iSt
SuperShuffleTaps( tempNoteData, iStartIndex, iEndIndex );
inout.CopyAll( tempNoteData );
inout.RevalidateATIs(vector<int>(), false);
}
void NoteDataUtil::Backwards( NoteData &inout )
@@ -1560,6 +1573,7 @@ void NoteDataUtil::Backwards( NoteData &inout )
}
inout.swap( out );
inout.RevalidateATIs(vector<int>(), false);
}
void NoteDataUtil::SwapSides( NoteData &inout )
@@ -1575,6 +1589,7 @@ void NoteDataUtil::SwapSides( NoteData &inout )
NoteData orig( inout );
inout.LoadTransformed( orig, orig.GetNumTracks(), iOriginalTrackToTakeFrom );
inout.RevalidateATIs(vector<int>(), false);
}
void NoteDataUtil::Little( NoteData &inout, int iStartIndex, int iEndIndex )
@@ -1589,6 +1604,7 @@ void NoteDataUtil::Little( NoteData &inout, int iStartIndex, int iEndIndex )
inout.SetTapNote( t, i, TAP_EMPTY );
}
}
inout.RevalidateATIs(vector<int>(), false);
}
// Make all quarter notes into jumps.
@@ -1641,6 +1657,7 @@ void NoteDataUtil::Wide( NoteData &inout, int iStartIndex, int iEndIndex )
}
inout.SetTapNote(iTrackToAdd, i, TAP_ADDITION_TAP);
}
inout.RevalidateATIs(vector<int>(), false);
}
void NoteDataUtil::Big( NoteData &inout, int iStartIndex, int iEndIndex )
@@ -1747,6 +1764,7 @@ void NoteDataUtil::InsertIntelligentTaps(
inout.SetTapNote(iTrackOfNoteToAdd, iRowToAdd, TAP_ADDITION_TAP);
}
inout.RevalidateATIs(vector<int>(), false);
}
#if 0
class TrackIterator
@@ -1873,6 +1891,7 @@ void NoteDataUtil::AddMines( NoteData &inout, int iStartIndex, int iEndIndex )
iRowCount = 0;
}
}
inout.RevalidateATIs(vector<int>(), false);
}
void NoteDataUtil::Echo( NoteData &inout, int iStartIndex, int iEndIndex )
@@ -1927,6 +1946,7 @@ void NoteDataUtil::Echo( NoteData &inout, int iStartIndex, int iEndIndex )
inout.SetTapNote( iEchoTrack, iRowEcho, TAP_ADDITION_TAP );
}
inout.RevalidateATIs(vector<int>(), false);
}
void NoteDataUtil::Planted( NoteData &inout, int iStartIndex, int iEndIndex )
@@ -1999,7 +2019,7 @@ void NoteDataUtil::ConvertTapsToHolds( NoteData &inout, int iSimultaneousHolds,
}
}
}
inout.RevalidateATIs(vector<int>(), false);
}
void NoteDataUtil::Stomp( NoteData &inout, StepsType st, int iStartIndex, int iEndIndex )
@@ -2042,6 +2062,7 @@ void NoteDataUtil::Stomp( NoteData &inout, StepsType st, int iStartIndex, int iE
}
}
}
inout.RevalidateATIs(vector<int>(), false);
}
void NoteDataUtil::SnapToNearestNoteType( NoteData &inout, NoteType nt1, NoteType nt2, int iStartIndex, int iEndIndex )
@@ -2088,6 +2109,7 @@ void NoteDataUtil::SnapToNearestNoteType( NoteData &inout, NoteType nt1, NoteTyp
inout.SetTapNote( c, iNewIndex, tnNew );
}
}
inout.RevalidateATIs(vector<int>(), false);
}
@@ -2254,6 +2276,7 @@ void NoteDataUtil::RemoveStretch( NoteData &inout, StepsType st, int iStartIndex
if( !bPassedOneMask )
RemoveAllButOneTap( inout, r );
}
inout.RevalidateATIs(vector<int>(), false);
}
bool NoteDataUtil::RowPassesValidMask( NoteData &inout, int row, const bool bValidMask[] )
@@ -2277,6 +2300,7 @@ void NoteDataUtil::ConvertAdditionsToRegular( NoteData &inout )
tn.source = TapNote::original;
inout.SetTapNote( t, r, tn );
}
inout.RevalidateATIs(vector<int>(), false);
}
void NoteDataUtil::TransformNoteData( NoteData &nd, const AttackArray &aa, StepsType st, Song* pSong )
@@ -2373,6 +2397,7 @@ void NoteDataUtil::AddTapAttacks( NoteData &nd, Song* pSong )
-1 );
nd.SetTapNote( iTrack, BeatToNoteRow(fBeat), tn );
}
nd.RevalidateATIs(vector<int>(), false);
}
void NoteDataUtil::Scale( NoteData &nd, float fScale )
@@ -2395,6 +2420,7 @@ void NoteDataUtil::Scale( NoteData &nd, float fScale )
}
nd.swap( ndOut );
nd.RevalidateATIs(vector<int>(), false);
}
/* XXX: move this to an appropriate place, same place as NoteRowToBeat perhaps? */
@@ -2430,6 +2456,7 @@ void NoteDataUtil::ScaleRegion( NoteData &nd, float fScale, int iStartIndex, int
}
nd.swap( ndOut );
nd.RevalidateATIs(vector<int>(), false);
}
void NoteDataUtil::InsertRows( NoteData &nd, int iStartIndex, int iRowsToAdd )
@@ -2441,6 +2468,7 @@ void NoteDataUtil::InsertRows( NoteData &nd, int iStartIndex, int iRowsToAdd )
temp.CopyRange( nd, iStartIndex, MAX_NOTE_ROW );
nd.ClearRange( iStartIndex, MAX_NOTE_ROW );
nd.CopyRange( temp, 0, MAX_NOTE_ROW, iStartIndex + iRowsToAdd );
nd.RevalidateATIs(vector<int>(), false);
}
void NoteDataUtil::DeleteRows( NoteData &nd, int iStartIndex, int iRowsToDelete )
@@ -2452,6 +2480,7 @@ void NoteDataUtil::DeleteRows( NoteData &nd, int iStartIndex, int iRowsToDelete
temp.CopyRange( nd, iStartIndex + iRowsToDelete, MAX_NOTE_ROW );
nd.ClearRange( iStartIndex, MAX_NOTE_ROW );
nd.CopyRange( temp, 0, MAX_NOTE_ROW, iStartIndex );
nd.RevalidateATIs(vector<int>(), false);
}
void NoteDataUtil::RemoveAllTapsOfType( NoteData& ndInOut, TapNote::Type typeToRemove )
@@ -2470,6 +2499,7 @@ void NoteDataUtil::RemoveAllTapsOfType( NoteData& ndInOut, TapNote::Type typeToR
++iter;
}
}
ndInOut.RevalidateATIs(vector<int>(), false);
}
void NoteDataUtil::RemoveAllTapsExceptForType( NoteData& ndInOut, TapNote::Type typeToKeep )
@@ -2485,6 +2515,7 @@ void NoteDataUtil::RemoveAllTapsExceptForType( NoteData& ndInOut, TapNote::Type
++iter;
}
}
ndInOut.RevalidateATIs(vector<int>(), false);
}
int NoteDataUtil::GetMaxNonEmptyTrack( const NoteData& in )