#include "stdafx.h" /* ----------------------------------------------------------------------------- Class: NoteData Desc: See header. Copyright (c) 2001-2002 by the person(s) listed below. All rights reserved. Chris Danford ----------------------------------------------------------------------------- */ #include "NoteData.h" #include "RageUtil.h" #include "GameConstantsAndTypes.h" #include "PrefsManager.h" #include "ArrowEffects.h" #include "PrefsManager.h" #include "GameConstantsAndTypes.h" #include "RageException.h" NoteData::NoteData() { Init(); } void NoteData::Init() { memset( m_TapNotes, '0', MAX_NOTE_TRACKS*MAX_TAP_NOTE_ROWS*sizeof(m_TapNotes[0][0]) ); m_iNumTracks = 0; m_iNumHoldNotes = 0; } NoteData::~NoteData() { } void NoteData::LoadFromSMNoteDataString( CString sSMNoteData ) { int iNumTracks = m_iNumTracks; NoteData::Init(); m_iNumTracks = iNumTracks; // strip comments out of sSMNoteData while( sSMNoteData.Find("//") != -1 ) { int iIndexCommentStart = sSMNoteData.Find("//"); int iIndexCommentEnd = sSMNoteData.Find("\n", iIndexCommentStart); if( iIndexCommentEnd == -1 ) // comment doesn't have an end? sSMNoteData.Delete( iIndexCommentStart, 2 ); else sSMNoteData.Delete( iIndexCommentStart, iIndexCommentEnd-iIndexCommentStart ); } CStringArray asMeasures; split( sSMNoteData, ",", asMeasures, true ); // ignore empty is important for( int m=0; mConvert2sAnd3sToHoldNotes(); } CString NoteData::GetSMNoteDataString() { this->ConvertHoldNotesTo2sAnd3s(); float fLastBeat = GetLastBeat(); int iLastMeasure = int( fLastBeat/BEATS_PER_MEASURE ); CStringArray asMeasureStrings; for( int m=0; m<=iLastMeasure; m++ ) // foreach measure { int iMeasureStartIndex = m * ELEMENTS_PER_MEASURE; int iMeasureLastIndex = (m+1) * ELEMENTS_PER_MEASURE - 1; // probe to find the smallest note type NoteType nt; int iNoteIndexSpacing; for( nt=(NoteType)0; ntConvert2sAnd3sToHoldNotes(); return join( "\n,", asMeasureStrings ); } void NoteData::ClearRange( int iNoteIndexBegin, int iNoteIndexEnd ) { // delete old TapNotes in the range for( int i=iNoteIndexBegin; i<=iNoteIndexEnd; i++ ) { for( int c=0; c= iNoteIndexBegin && hn.m_iStartIndex <= iNoteIndexEnd) || (hn.m_iEndIndex >= iNoteIndexBegin && hn.m_iEndIndex <= iNoteIndexEnd) ) // overlap (kinda) { ; // do nothing } else // ! overlap { m_HoldNotes[iIndexWrite] = m_HoldNotes[iIndexRead]; iIndexWrite++; } } m_iNumHoldNotes = iIndexWrite; } void NoteData::CopyRange( NoteData* pFrom, int iFromIndexBegin, int iFromIndexEnd, int iToIndexBegin ) { ASSERT( pFrom->m_iNumTracks == m_iNumTracks ); if( iToIndexBegin == -1 ) iToIndexBegin = 0; pFrom->ConvertHoldNotesTo2sAnd3s(); int f, t; // copy recorded TapNotes f = iFromIndexBegin; t = iToIndexBegin; while( f<=iFromIndexEnd ) { for( int c=0; cm_TapNotes[c][f]; f++; t++; } pFrom->Convert2sAnd3sToHoldNotes(); this->Convert2sAnd3sToHoldNotes(); } void NoteData::AddHoldNote( HoldNote add ) { int i; // look for other hold notes that overlap and merge them for( i=0; i= add.m_iStartIndex ) // these HoldNotes overlap (this isn't entirely correct!) { add.m_iStartIndex = min(add.m_iStartIndex, other.m_iStartIndex); add.m_iEndIndex = max(add.m_iEndIndex, other.m_iEndIndex); // delete this HoldNote for( int j=i; j 0 && index < m_iNumHoldNotes ); // delete a tap note at the start of this hold HoldNote &hn = m_HoldNotes[index]; m_TapNotes[hn.m_iTrack][hn.m_iStartIndex] = '0'; // remove from list for( int j=index; j=iOldestIndexFoundSoFar; i-- ) // iterate back to front { if( !IsRowEmpty(i) ) { iOldestIndexFoundSoFar = i; break; } } for( i=0; i iOldestIndexFoundSoFar ) iOldestIndexFoundSoFar = m_HoldNotes[i].m_iEndIndex; } return iOldestIndexFoundSoFar; } float NoteData::GetLastBeat() { return NoteRowToBeat( GetLastRow() ); } int NoteData::GetNumTapNotes( const float fStartBeat, const float fEndBeat ) { int iNumNotes = 0; int iStartIndex = BeatToNoteRow( fStartBeat ); int iEndIndex = BeatToNoteRow( fEndBeat ); for( int i=iStartIndex; i= 2 ) iNumDoubles++; } return iNumDoubles; } int NoteData::GetNumHoldNotes( const float fStartBeat, const float fEndBeat ) { int iNumHolds = 0; int iStartIndex = BeatToNoteRow( fStartBeat ); int iEndIndex = BeatToNoteRow( fEndBeat ); for( int i=0; i=0; i-- ) // foreach HoldNote { if( c >= iFirstRightSideColumn ) { // delete this HoldNote by shifting everything down for( int j=i; j=0; i-- ) // foreach HoldNote { HoldNote &hn = m_HoldNotes[i]; if( hn.m_iTrack < iFirstRightSideColumn ) { // delete this HoldNote by shifting everything down RemoveHoldNote( i ); } else { m_HoldNotes[i].m_iTrack -= 4; } } } void NoteData::RemoveHoldNotes() { // turn all the HoldNotes into TapNotes for( int i=0; i= NOTE_12TH ) iNumChaosNotes++; } float fReturn = iNumChaosNotes / fSongSeconds * 0.5f; return min( fReturn, 1.0f ); } float NoteData::GetFreezeRadarValue( float fSongSeconds ) { // number of hold steps float fReturn = GetNumHoldNotes() / fSongSeconds; return min( fReturn, 1.0f ); } void NoteData::LoadTransformed( NoteData* pOriginal, int iNewNumTracks, int iNewToOriginalTrack[] ) { // init Init(); m_iNumTracks = iNewNumTracks; // copy tracks for( int t=0; tm_TapNotes[iOriginalTrack], MAX_TAP_NOTE_ROWS*sizeof(m_TapNotes[0][0]) ); for( i=0; im_iNumHoldNotes; i++ ) { HoldNote &hn = pOriginal->m_HoldNotes[i]; if( hn.m_iTrack == iOriginalTrack ) { hn.m_iTrack = t; this->AddHoldNote( hn ); } } } }