2002-04-16 17:31:00 +00:00
# include "stdafx.h"
/*
-----------------------------------------------------------------------------
Class: NoteField
Desc: See header.
2002-05-19 01:59:48 +00:00
Copyright (c) 2001-2002 by the person(s) listed below. All rights reserved.
2002-04-16 17:31:00 +00:00
Chris Danford
-----------------------------------------------------------------------------
*/
# include "NoteField.h"
# include "RageUtil.h"
2002-05-01 19:14:55 +00:00
# include "GameConstantsAndTypes.h"
2002-07-23 01:41:40 +00:00
# include "PrefsManager.h"
2002-04-16 17:31:00 +00:00
# include "ArrowEffects.h"
# include "PrefsManager.h"
# include "GameManager.h"
2002-07-23 01:41:40 +00:00
# include "GameState.h"
2002-04-16 17:31:00 +00:00
2002-06-14 22:25:22 +00:00
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 ;
2002-04-16 17:31:00 +00:00
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 ;
2002-06-27 17:49:10 +00:00
2002-07-02 00:27:58 +00:00
m_fOverrideAdd = - 1 ;
2002-04-16 17:31:00 +00:00
}
2002-05-27 08:23:27 +00:00
void NoteField : : Load ( NoteData * pNoteData , PlayerNumber p , StyleDef * pStyleDef , PlayerOptions po , float fNumBeatsToDrawBehind , float fNumBeatsToDrawAhead , NoteFieldMode mode )
2002-04-16 17:31:00 +00:00
{
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 < m_iNumTracks ; c + + )
{
2002-05-19 01:59:48 +00:00
CArray < D3DXCOLOR , D3DXCOLOR > arrayTweenColors ;
2002-07-23 01:41:40 +00:00
GAMEMAN - > GetTweenColors ( c , arrayTweenColors ) ;
2002-05-19 01:59:48 +00:00
2002-07-23 01:41:40 +00:00
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 ) ) ;
2002-04-16 17:31:00 +00:00
}
2002-07-11 19:02:26 +00:00
for ( int i = 0 ; i < MAX_HOLD_NOTES ; i + + )
2002-04-28 20:42:32 +00:00
m_HoldNoteLife [ i ] = 1 ; // start with full life
2002-07-23 01:41:40 +00:00
ASSERT ( m_iNumTracks = = GAMESTATE - > GetCurrentStyleDef ( ) - > m_iColsPerPlayer ) ;
2002-04-16 17:31:00 +00:00
}
void NoteField : : Update ( float fDeltaTime , float fSongBeat )
{
m_fSongBeat = fSongBeat ;
m_rectMarkerBar . Update ( fDeltaTime ) ;
}
2002-04-28 20:42:32 +00:00
void NoteField : : CreateTapNoteInstance ( ColorNoteInstance & cni , const int iCol , const float fIndex , const D3DXCOLOR color )
2002-04-16 17:31:00 +00:00
{
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 ) ;
2002-07-02 00:27:58 +00:00
const float fAlpha = ArrowGetAlpha ( m_PlayerOptions , fYPos ) ;
2002-04-16 17:31:00 +00:00
2002-04-28 20:42:32 +00:00
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 ;
2002-07-02 00:27:58 +00:00
float fAddAlpha = m_ColorNote [ iCol ] . GetAddAlphaFromDiffuseAlpha ( fAlpha ) ;
if ( m_fOverrideAdd ! = - 1 )
fAddAlpha = m_fOverrideAdd ;
2002-04-28 20:42:32 +00:00
int iGrayPartFrameNo = m_ColorNote [ iCol ] . GetGrayPartFrameNoFromIndexAndBeat ( roundf ( fIndex ) , m_fSongBeat ) ;
2002-04-16 17:31:00 +00:00
2002-04-28 20:42:32 +00:00
ColorNoteInstance instance = { fXPos , fYPos , fRotation , fAlpha , colorLeading , colorTrailing , fAddAlpha , iGrayPartFrameNo } ;
cni = instance ;
2002-04-16 17:31:00 +00:00
}
2002-04-28 20:42:32 +00:00
void NoteField : : CreateHoldNoteInstance ( ColorNoteInstance & cni , const bool bActive , const float fIndex , const HoldNote & hn , const float fHoldNoteLife )
2002-04-16 17:31:00 +00:00
{
2002-04-28 20:42:32 +00:00
const int iCol = hn . m_iTrack ;
2002-04-16 17:31:00 +00:00
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 ) ;
2002-07-02 00:27:58 +00:00
const float fAlpha = ArrowGetAlpha ( m_PlayerOptions , fYPos ) ;
2002-04-16 17:31:00 +00:00
2002-04-28 20:42:32 +00:00
int iGrayPartFrameNo ;
if ( bActive & & m_Mode = = MODE_DANCING )
iGrayPartFrameNo = m_ColorNote [ iCol ] . GetGrayPartFrameNoFull ( ) ;
else
iGrayPartFrameNo = m_ColorNote [ iCol ] . GetGrayPartFrameNoClear ( ) ;
2002-04-16 17:31:00 +00:00
2002-04-28 20:42:32 +00:00
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 ;
2002-07-02 00:27:58 +00:00
float fAddAlpha = m_ColorNote [ iCol ] . GetAddAlphaFromDiffuseAlpha ( fAlpha ) ;
if ( m_fOverrideAdd ! = - 1 )
fAddAlpha = m_fOverrideAdd ;
2002-04-16 17:31:00 +00:00
2002-04-28 20:42:32 +00:00
ColorNoteInstance instance = { fXPos , fYPos , fRotation , fAlpha , colorLeading , colorTrailing , fAddAlpha , iGrayPartFrameNo } ;
cni = instance ;
2002-04-16 17:31:00 +00:00
}
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 ( ) ;
2002-06-29 11:59:09 +00:00
m_textMeasureNumber . SetDiffuseColor ( D3DXCOLOR ( 1 , 1 , 1 , 1 ) ) ;
m_textMeasureNumber . SetAddColor ( D3DXCOLOR ( 1 , 1 , 1 , 0 ) ) ;
2002-04-16 17:31:00 +00:00
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 ( ) ;
}
2002-06-29 11:59:09 +00:00
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 ) ) ;
2002-07-02 00:27:58 +00:00
m_textMeasureNumber . SetXY ( - m_rectMeasureBar . GetZoomedWidth ( ) / 2 - 60 , fYPos ) ;
2002-06-29 11:59:09 +00:00
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 ) ;
2002-07-02 00:27:58 +00:00
m_textMeasureNumber . SetDiffuseColor ( D3DXCOLOR ( 0.8f , 0.8f , 0 , 1 ) ) ;
2002-06-29 11:59:09 +00:00
m_textMeasureNumber . SetAddColor ( D3DXCOLOR ( 1 , 1 , 1 , cosf ( TIMER - > GetTimeSinceStart ( ) * 2 ) / 2 + 0.5f ) ) ;
m_textMeasureNumber . SetText ( ssprintf ( " %.2f " , fSecs ) ) ;
2002-07-02 00:27:58 +00:00
m_textMeasureNumber . SetXY ( - m_rectMeasureBar . GetZoomedWidth ( ) / 2 - 10 , fYPos ) ;
2002-06-29 11:59:09 +00:00
m_textMeasureNumber . Draw ( ) ;
}
2002-05-19 01:59:48 +00:00
void NoteField : : DrawPrimitives ( )
2002-04-16 17:31:00 +00:00
{
2002-05-19 01:59:48 +00:00
//LOG->WriteLine( "NoteField::DrawPrimitives()" );
2002-04-16 17:31:00 +00:00
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
2002-05-19 01:59:48 +00:00
int iIndexFirstArrowToDraw = BeatToNoteRow ( m_fSongBeat - m_fNumBeatsToDrawBehind ) ; // 2 beats earlier
2002-04-16 17:31:00 +00:00
if ( iIndexFirstArrowToDraw < 0 ) iIndexFirstArrowToDraw = 0 ;
2002-05-19 01:59:48 +00:00
int iIndexLastArrowToDraw = BeatToNoteRow ( m_fSongBeat + m_fNumBeatsToDrawAhead ) ; // 7 beats later
2002-04-16 17:31:00 +00:00
2002-05-01 19:14:55 +00:00
//LOG->WriteLine( "Drawing elements %d through %d", iIndexFirstArrowToDraw, iIndexLastArrowToDraw );
2002-04-16 17:31:00 +00:00
if ( m_Mode = = MODE_EDITING )
{
2002-06-29 11:59:09 +00:00
//
// Draw measure bars
//
2002-04-16 17:31:00 +00:00
for ( int i = iIndexFirstArrowToDraw ; i < = iIndexLastArrowToDraw ; i + + )
{
if ( i % ELEMENTS_PER_MEASURE = = 0 )
2002-06-29 11:59:09 +00:00
DrawMeasureBar ( i , i / ELEMENTS_PER_MEASURE + 1 ) ;
2002-04-16 17:31:00 +00:00
}
2002-06-29 11:59:09 +00:00
//
// BPM text
//
2002-07-23 01:41:40 +00:00
CArray < BPMSegment , BPMSegment & > & aBPMSegments = GAMESTATE - > m_pCurSong - > m_BPMSegments ;
2002-06-29 11:59:09 +00:00
for ( i = 0 ; i < aBPMSegments . GetSize ( ) ; i + + )
{
DrawBPMText ( BeatToNoteRow ( aBPMSegments [ i ] . m_fStartBeat ) , aBPMSegments [ i ] . m_fBPM ) ;
}
//
// Freeze text
//
2002-07-23 01:41:40 +00:00
CArray < StopSegment , StopSegment & > & aStopSegments = GAMESTATE - > m_pCurSong - > m_StopSegments ;
2002-07-11 19:02:26 +00:00
for ( i = 0 ; i < aStopSegments . GetSize ( ) ; i + + )
2002-06-29 11:59:09 +00:00
{
2002-07-11 19:02:26 +00:00
DrawFreezeText ( BeatToNoteRow ( aStopSegments [ i ] . m_fStartBeat ) , aStopSegments [ i ] . m_fStopSeconds ) ;
2002-06-29 11:59:09 +00:00
}
//
// Draw marker bars
//
2002-04-16 17:31:00 +00:00
if ( m_fBeginMarker ! = - 1 )
{
2002-05-19 01:59:48 +00:00
DrawMarkerBar ( BeatToNoteRow ( m_fBeginMarker ) ) ;
2002-04-16 17:31:00 +00:00
}
if ( m_fEndMarker ! = - 1 )
{
2002-05-19 01:59:48 +00:00
DrawMarkerBar ( BeatToNoteRow ( m_fEndMarker ) ) ;
2002-04-16 17:31:00 +00:00
}
2002-06-29 11:59:09 +00:00
2002-04-16 17:31:00 +00:00
}
2002-06-29 11:59:09 +00:00
2002-04-16 17:31:00 +00:00
//
2002-04-28 20:42:32 +00:00
// Optimization is very important here because there are so many arrows to draw. We're going
// to draw the arrows in order of column. This will let us fill up a vertex buffer of arrows
// so we can draw them in one swoop without texture or state changes.
2002-04-16 17:31:00 +00:00
//
2002-04-28 20:42:32 +00:00
for ( int c = 0 ; c < m_iNumTracks ; c + + ) // for each arrow column
{
const int MAX_COLOR_NOTE_INSTANCES = 300 ;
ColorNoteInstance instances [ MAX_COLOR_NOTE_INSTANCES ] ;
2002-06-14 22:25:22 +00:00
int iCount = 0 ; // number of valid elements in the instances array
2002-04-28 20:42:32 +00:00
2002-04-16 17:31:00 +00:00
2002-06-14 22:25:22 +00:00
/////////////////////////////////
// Draw all HoldNotes in this column (so that they appear under the tap notes)
/////////////////////////////////
for ( int i = 0 ; i < m_iNumHoldNotes ; i + + )
2002-04-16 17:31:00 +00:00
{
2002-04-28 20:42:32 +00:00
HoldNote & hn = m_HoldNotes [ i ] ;
2002-07-11 19:02:26 +00:00
const float fLife = m_HoldNoteLife [ i ] ;
2002-04-16 17:31:00 +00:00
2002-04-28 20:42:32 +00:00
if ( hn . m_iTrack ! = c ) // this HoldNote doesn't belong to this column
continue ;
2002-04-16 17:31:00 +00:00
2002-04-28 20:42:32 +00:00
// If no part of this HoldNote is on the screen, skip it
if ( ! ( iIndexFirstArrowToDraw < = hn . m_iEndIndex & & hn . m_iEndIndex < = iIndexLastArrowToDraw | |
iIndexFirstArrowToDraw < = hn . m_iStartIndex & & hn . m_iStartIndex < = iIndexLastArrowToDraw | |
hn . m_iStartIndex < iIndexFirstArrowToDraw & & hn . m_iEndIndex > iIndexLastArrowToDraw ) )
{
2002-06-14 22:25:22 +00:00
continue ; // skip
2002-04-28 20:42:32 +00:00
}
2002-04-16 17:31:00 +00:00
2002-06-14 22:25:22 +00:00
// If this note was in the past and has life > 0, then it was completed and don't draw it!
2002-07-11 19:02:26 +00:00
if ( hn . m_iEndIndex < BeatToNoteRow ( m_fSongBeat ) & & fLife > 0 )
2002-06-14 22:25:22 +00:00
continue ; // skip
2002-04-28 20:42:32 +00:00
const int iCol = hn . m_iTrack ;
const float fHoldNoteLife = m_HoldNoteLife [ i ] ;
2002-06-24 22:04:31 +00:00
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
2002-04-16 17:31:00 +00:00
2002-06-14 22:25:22 +00:00
// 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
2002-04-28 20:42:32 +00:00
{
// check if this arrow is off the the screen
if ( j < iIndexFirstArrowToDraw | | iIndexLastArrowToDraw < j )
continue ; // skip this arrow
2002-04-16 17:31:00 +00:00
2002-07-11 19:02:26 +00:00
if ( fLife > 0 & & NoteRowToBeat ( j ) < m_fSongBeat )
continue ;
2002-06-14 22:25:22 +00:00
CreateHoldNoteInstance ( instances [ iCount + + ] , bActive , ( float ) j , hn , fHoldNoteLife ) ;
2002-04-28 20:42:32 +00:00
}
2002-04-16 17:31:00 +00:00
}
2002-04-28 20:42:32 +00:00
const bool bDrawAddPass = m_PlayerOptions . m_AppearanceType ! = PlayerOptions : : APPEARANCE_VISIBLE ;
if ( iCount > 0 )
m_ColorNote [ c ] . DrawList ( iCount , instances , bDrawAddPass ) ;
2002-06-14 22:25:22 +00:00
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 < m_iNumHoldNotes ; j + + )
{
if ( m_HoldNotes [ j ] . m_iStartIndex = = i )
{
bHoldNoteOnThisBeat = true ;
break ;
}
}
if ( bHoldNoteOnThisBeat )
CreateTapNoteInstance ( instances [ iCount + + ] , c , ( float ) i , D3DXCOLOR ( 0 , 1 , 0 , 1 ) ) ;
else
CreateTapNoteInstance ( instances [ iCount + + ] , c , ( float ) i ) ;
}
if ( iCount > 0 )
m_ColorNote [ c ] . DrawList ( iCount , instances , bDrawAddPass ) ;
2002-04-16 17:31:00 +00:00
}
2002-04-28 20:42:32 +00:00
2002-04-16 17:31:00 +00:00
}
void NoteField : : RemoveTapNoteRow ( int iIndex )
{
for ( int c = 0 ; c < m_iNumTracks ; c + + )
m_TapNotes [ c ] [ iIndex ] = ' 0 ' ;
}
void NoteField : : SetHoldNoteLife ( int iIndex , float fLife )
{
m_HoldNoteLife [ iIndex ] = fLife ;
2002-06-24 22:04:31 +00:00
}