#include "stdafx.h" /* ----------------------------------------------------------------------------- Class: NoteField Desc: See header. Copyright (c) 2001-2002 by the person(s) listed below. All rights reserved. Chris Danford ----------------------------------------------------------------------------- */ #include "NoteField.h" #include "RageUtil.h" #include "GameConstantsAndTypes.h" #include "PrefsManager.h" #include "ArrowEffects.h" #include "PrefsManager.h" #include "GameManager.h" #include "GameState.h" const float HOLD_NOTE_BITS_PER_BEAT = 6; const float HOLD_NOTE_BITS_PER_ROW = HOLD_NOTE_BITS_PER_BEAT / ELEMENTS_PER_BEAT; const float ROWS_BETWEEN_HOLD_BITS = 1 / HOLD_NOTE_BITS_PER_ROW; NoteField::NoteField() { m_rectMeasureBar.TurnShadowOff(); m_textMeasureNumber.Load( THEME->GetPathTo(FONT_NORMAL) ); m_textMeasureNumber.SetZoom( 1.0f ); m_rectMarkerBar.TurnShadowOff(); m_rectMarkerBar.SetEffectGlowing(); m_Mode = MODE_DANCING; m_fBeginMarker = m_fEndMarker = -1; m_fOverrideAdd = -1; } void NoteField::Load( NoteData* pNoteData, PlayerNumber p, StyleDef* pStyleDef, PlayerOptions po, float fNumBeatsToDrawBehind, float fNumBeatsToDrawAhead, NoteFieldMode mode ) { m_PlayerOptions = po; m_fNumBeatsToDrawBehind = fNumBeatsToDrawBehind; m_fNumBeatsToDrawAhead = fNumBeatsToDrawAhead; m_Mode = mode; this->CopyAll( pNoteData ); // init arrow rotations and X positions for( int c=0; c arrayTweenColors; GAMEMAN->GetTweenColors( c, arrayTweenColors ); m_ColorNote[c].m_sprColorPart.Load( GAMEMAN->GetPathTo(c, GRAPHIC_NOTE_COLOR_PART) ); m_ColorNote[c].m_sprGrayPart.Load( GAMEMAN->GetPathTo(c, GRAPHIC_NOTE_GRAY_PART) ); } for( int i=0; iGetCurrentStyleDef()->m_iColsPerPlayer ); } void NoteField::Update( float fDeltaTime, float fSongBeat ) { m_fSongBeat = fSongBeat; m_rectMarkerBar.Update( fDeltaTime ); } void NoteField::CreateTapNoteInstance( ColorNoteInstance &cni, const int iCol, const float fIndex, const D3DXCOLOR color ) { const float fYOffset = ArrowGetYOffset( m_PlayerOptions, fIndex, m_fSongBeat ); const float fYPos = ArrowGetYPos( m_PlayerOptions, fYOffset ); const float fRotation = ArrowGetRotation( m_PlayerOptions, iCol, fYOffset ); const float fXPos = ArrowGetXPos( m_PlayerOptions, iCol, fYOffset, m_fSongBeat ); const float fAlpha = ArrowGetAlpha( m_PlayerOptions, fYPos ); D3DXCOLOR colorLeading, colorTrailing; // of the color part. Alpha here be overwritten with fAlpha! if( color.a == -1 ) // indicated "NULL" m_ColorNote[iCol].GetEdgeColorsFromIndexAndBeat( roundf(fIndex), m_fSongBeat, m_PlayerOptions.m_ColorType, colorLeading, colorTrailing ); else colorLeading = colorTrailing = color; float fAddAlpha = m_ColorNote[iCol].GetAddAlphaFromDiffuseAlpha( fAlpha ); if( m_fOverrideAdd != -1 ) fAddAlpha = m_fOverrideAdd; int iGrayPartFrameNo = m_ColorNote[iCol].GetGrayPartFrameNoFromIndexAndBeat( roundf(fIndex), m_fSongBeat ); ColorNoteInstance instance = { fXPos, fYPos, fRotation, fAlpha, colorLeading, colorTrailing, fAddAlpha, iGrayPartFrameNo }; cni = instance; } void NoteField::CreateHoldNoteInstance( ColorNoteInstance &cni, const bool bActive, const float fIndex, const HoldNote &hn, const float fHoldNoteLife ) { const int iCol = hn.m_iTrack; const float fYOffset = ArrowGetYOffset( m_PlayerOptions, fIndex, m_fSongBeat ); const float fYPos = ArrowGetYPos( m_PlayerOptions, fYOffset ); const float fRotation = ArrowGetRotation( m_PlayerOptions, iCol, fYOffset ); const float fXPos = ArrowGetXPos( m_PlayerOptions, iCol, fYOffset, m_fSongBeat ); const float fAlpha = ArrowGetAlpha( m_PlayerOptions, fYPos ); int iGrayPartFrameNo; if( bActive && m_Mode == MODE_DANCING ) iGrayPartFrameNo = m_ColorNote[iCol].GetGrayPartFrameNoFull(); else iGrayPartFrameNo = m_ColorNote[iCol].GetGrayPartFrameNoClear(); const float fPercentIntoHold = (fIndex-hn.m_iStartIndex)/(hn.m_iEndIndex-hn.m_iStartIndex); D3DXCOLOR colorLeading( fPercentIntoHold, 1, 0, 1 ); // color shifts from green to yellow colorLeading *= fHoldNoteLife; colorLeading.a = 1; D3DXCOLOR colorTrailing = colorLeading; float fAddAlpha = m_ColorNote[iCol].GetAddAlphaFromDiffuseAlpha( fAlpha ); if( m_fOverrideAdd != -1 ) fAddAlpha = m_fOverrideAdd; ColorNoteInstance instance = { fXPos, fYPos, fRotation, fAlpha, colorLeading, colorTrailing, fAddAlpha, iGrayPartFrameNo }; cni = instance; } void NoteField::DrawMeasureBar( const int iIndex, const int iMeasureNo ) { const float fYOffset = ArrowGetYOffset( m_PlayerOptions, (float)iIndex, m_fSongBeat ); const float fYPos = ArrowGetYPos( m_PlayerOptions, fYOffset ); m_rectMeasureBar.SetXY( 0, fYPos ); m_rectMeasureBar.SetWidth( (float)(m_iNumTracks+1) * ARROW_SIZE ); m_rectMeasureBar.SetHeight( 20 ); m_rectMeasureBar.SetDiffuseColor( D3DXCOLOR(0,0,0,0.5f) ); m_rectMeasureBar.Draw(); m_textMeasureNumber.SetDiffuseColor( D3DXCOLOR(1,1,1,1) ); m_textMeasureNumber.SetAddColor( D3DXCOLOR(1,1,1,0) ); m_textMeasureNumber.SetText( ssprintf("%d", iMeasureNo) ); m_textMeasureNumber.SetXY( -m_rectMeasureBar.GetZoomedWidth()/2 + 10, fYPos ); m_textMeasureNumber.Draw(); } void NoteField::DrawMarkerBar( const int iIndex ) { const float fYOffset = ArrowGetYOffset( m_PlayerOptions, (float)iIndex, m_fSongBeat ); const float fYPos = ArrowGetYPos( m_PlayerOptions, fYOffset ); m_rectMarkerBar.SetXY( 0, fYPos ); m_rectMarkerBar.SetWidth( (float)(m_iNumTracks+1) * ARROW_SIZE ); m_rectMarkerBar.SetHeight( 20 ); m_rectMarkerBar.SetDiffuseColor( D3DXCOLOR(0,0,0,0.5f) ); m_rectMarkerBar.Draw(); } void NoteField::DrawBPMText( const int iIndex, const float fBPM ) { const float fYOffset = ArrowGetYOffset( m_PlayerOptions, (float)iIndex, m_fSongBeat ); const float fYPos = ArrowGetYPos( m_PlayerOptions, fYOffset ); m_textMeasureNumber.SetDiffuseColor( D3DXCOLOR(1,0,0,1) ); m_textMeasureNumber.SetAddColor( D3DXCOLOR(1,1,1,cosf(TIMER->GetTimeSinceStart()*2)/2+0.5f) ); m_textMeasureNumber.SetText( ssprintf("%.2f", fBPM) ); m_textMeasureNumber.SetXY( -m_rectMeasureBar.GetZoomedWidth()/2 - 60, fYPos ); m_textMeasureNumber.Draw(); } void NoteField::DrawFreezeText( const int iIndex, const float fSecs ) { const float fYOffset = ArrowGetYOffset( m_PlayerOptions, (float)iIndex, m_fSongBeat ); const float fYPos = ArrowGetYPos( m_PlayerOptions, fYOffset ); m_textMeasureNumber.SetDiffuseColor( D3DXCOLOR(0.8f,0.8f,0,1) ); m_textMeasureNumber.SetAddColor( D3DXCOLOR(1,1,1,cosf(TIMER->GetTimeSinceStart()*2)/2+0.5f) ); m_textMeasureNumber.SetText( ssprintf("%.2f", fSecs) ); m_textMeasureNumber.SetXY( -m_rectMeasureBar.GetZoomedWidth()/2 - 10, fYPos ); m_textMeasureNumber.Draw(); } void NoteField::DrawPrimitives() { //LOG->WriteLine( "NoteField::DrawPrimitives()" ); if( m_fSongBeat < 0 ) m_fSongBeat = 0; int iBaseFrameNo = (int)(m_fSongBeat*2.5) % NUM_FRAMES_IN_COLOR_ARROW_SPRITE; // 2.5 is a "fudge number" :-) This should be based on BPM int iIndexFirstArrowToDraw = BeatToNoteRow( m_fSongBeat - m_fNumBeatsToDrawBehind ); // 2 beats earlier if( iIndexFirstArrowToDraw < 0 ) iIndexFirstArrowToDraw = 0; int iIndexLastArrowToDraw = BeatToNoteRow( m_fSongBeat + m_fNumBeatsToDrawAhead ); // 7 beats later //LOG->WriteLine( "Drawing elements %d through %d", iIndexFirstArrowToDraw, iIndexLastArrowToDraw ); if( m_Mode == MODE_EDITING ) { // // Draw measure bars // for( int i=iIndexFirstArrowToDraw; i<=iIndexLastArrowToDraw; i++ ) { if( i % ELEMENTS_PER_MEASURE == 0 ) DrawMeasureBar( i, i / ELEMENTS_PER_MEASURE + 1 ); } // // BPM text // CArray &aBPMSegments = GAMESTATE->m_pCurSong->m_BPMSegments; for( i=0; i &aStopSegments = GAMESTATE->m_pCurSong->m_StopSegments; for( i=0; i iIndexLastArrowToDraw ) ) { continue; // skip } // If this note was in the past and has life > 0, then it was completed and don't draw it! if( hn.m_iEndIndex < BeatToNoteRow(m_fSongBeat) && fLife > 0 ) continue; // skip const int iCol = hn.m_iTrack; const float fHoldNoteLife = m_HoldNoteLife[i]; const bool bActive = NoteRowToBeat(hn.m_iStartIndex-1) <= m_fSongBeat && m_fSongBeat <= NoteRowToBeat(hn.m_iEndIndex); // hack: added -1 because hn.m_iStartIndex changes as note is held // parts of the hold const float fStartDrawingAtBeat = froundf( (float)hn.m_iStartIndex, ROWS_BETWEEN_HOLD_BITS ); for( float j=fStartDrawingAtBeat; j<=hn.m_iEndIndex; j+=ROWS_BETWEEN_HOLD_BITS/m_PlayerOptions.m_fArrowScrollSpeed ) // for each bit of the hold { // check if this arrow is off the the screen if( j < iIndexFirstArrowToDraw || iIndexLastArrowToDraw < j) continue; // skip this arrow if( fLife > 0 && NoteRowToBeat(j) < m_fSongBeat ) continue; CreateHoldNoteInstance( instances[iCount++], bActive, (float)j, hn, fHoldNoteLife ); } } const bool bDrawAddPass = m_PlayerOptions.m_AppearanceType != PlayerOptions::APPEARANCE_VISIBLE; if( iCount > 0 ) m_ColorNote[c].DrawList( iCount, instances, bDrawAddPass ); iCount = 0; // reset count /////////////////////////////////// // Draw all TapNotes in this column /////////////////////////////////// for( i=iIndexFirstArrowToDraw; i<=iIndexLastArrowToDraw; i++ ) // for each row { if( m_TapNotes[c][i] == '0' ) continue; // no note here // See if there is a hold step that begins on this beat. bool bHoldNoteOnThisBeat = false; for( int j=0; j 0 ) m_ColorNote[c].DrawList( iCount, instances, bDrawAddPass ); } } void NoteField::RemoveTapNoteRow( int iIndex ) { for( int c=0; c