Files
itgmania212121/stepmania/src/NoteField.cpp
T

286 lines
9.2 KiB
C++
Raw Normal View History

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-07-27 19:29:51 +00:00
#include "RageException.h"
#include "RageTimer.h"
#include "RageLog.h"
#include <math.h>
#include "ThemeManager.h"
2002-07-27 19:29:51 +00:00
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 / ROWS_PER_BEAT;
2002-06-14 22:25:22 +00:00
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.LoadFromFont( THEME->GetPathTo("Fonts","normal") );
2002-04-16 17:31:00 +00:00
m_textMeasureNumber.SetZoom( 1.0f );
m_rectMarkerBar.TurnShadowOff();
m_rectMarkerBar.SetEffectGlowing();
m_fBeginMarker = m_fEndMarker = -1;
2002-06-27 17:49:10 +00:00
2002-08-01 21:55:40 +00:00
m_fPercentFadeToFail = -1;
2002-04-16 17:31:00 +00:00
}
2002-07-28 20:28:37 +00:00
void NoteField::Load( NoteData* pNoteData, PlayerNumber pn, int iPixelsToDrawBehind, int iPixelsToDrawAhead )
2002-04-16 17:31:00 +00:00
{
2002-07-28 20:28:37 +00:00
m_PlayerNumber = pn;
2002-07-27 19:29:51 +00:00
m_iPixelsToDrawBehind = iPixelsToDrawBehind;
m_iPixelsToDrawAhead = iPixelsToDrawAhead;
2002-07-28 20:28:37 +00:00
2002-08-01 21:55:40 +00:00
m_fPercentFadeToFail = -1;
2002-11-03 21:38:22 +00:00
NoteDataWithScoring::Init(pNoteData->GetNumTapNotes(), pNoteData->GetNumHoldNotes());
2002-08-01 03:15:27 +00:00
2002-11-03 21:45:26 +00:00
m_bIsHoldingHoldNote.clear();
m_bIsHoldingHoldNote.insert(m_bIsHoldingHoldNote.end(), pNoteData->GetNumTapNotes(), false);
2002-08-01 03:15:27 +00:00
2002-04-16 17:31:00 +00:00
this->CopyAll( pNoteData );
// init note displays
2002-04-16 17:31:00 +00:00
for( int c=0; c<m_iNumTracks; c++ )
m_NoteDisplay[c].Load( c, pn );
2002-04-16 17:31:00 +00:00
2002-07-23 01:41:40 +00:00
ASSERT( m_iNumTracks == GAMESTATE->GetCurrentStyleDef()->m_iColsPerPlayer );
2002-04-16 17:31:00 +00:00
}
2002-07-28 20:28:37 +00:00
void NoteField::Update( float fDeltaTime )
2002-04-16 17:31:00 +00:00
{
m_rectMarkerBar.Update( fDeltaTime );
2002-08-01 21:55:40 +00:00
if( m_fPercentFadeToFail >= 0 )
2002-09-05 20:42:49 +00:00
m_fPercentFadeToFail = min( m_fPercentFadeToFail + fDeltaTime/1.5f, 1 ); // take 1.5 seconds to totally fade
2002-04-16 17:31:00 +00:00
}
void NoteField::DrawMeasureBar( int iMeasureIndex )
2002-04-16 17:31:00 +00:00
{
const int iMeasureNoDisplay = iMeasureIndex+1;
const float fBeat = float(iMeasureIndex * BEATS_PER_MEASURE);
const float fYOffset = ArrowGetYOffset( m_PlayerNumber, fBeat );
2002-07-28 20:28:37 +00:00
const float fYPos = ArrowGetYPos( m_PlayerNumber, fYOffset );
2002-04-16 17:31:00 +00:00
m_rectMeasureBar.SetXY( 0, fYPos );
m_rectMeasureBar.SetZoomX( (float)(m_iNumTracks+1) * ARROW_SIZE );
m_rectMeasureBar.SetZoomY( 20 );
m_rectMeasureBar.SetDiffuse( RageColor(0,0,0,0.5f) );
2002-04-16 17:31:00 +00:00
m_rectMeasureBar.Draw();
m_textMeasureNumber.SetDiffuse( RageColor(1,1,1,1) );
m_textMeasureNumber.SetGlow( RageColor(1,1,1,0) );
m_textMeasureNumber.SetText( ssprintf("%d", iMeasureNoDisplay) );
2002-04-16 17:31:00 +00:00
m_textMeasureNumber.SetXY( -m_rectMeasureBar.GetZoomedWidth()/2 + 10, fYPos );
m_textMeasureNumber.Draw();
}
void NoteField::DrawMarkerBar( const float fBeat )
2002-04-16 17:31:00 +00:00
{
const float fYOffset = ArrowGetYOffset( m_PlayerNumber, fBeat );
2002-07-28 20:28:37 +00:00
const float fYPos = ArrowGetYPos( m_PlayerNumber, fYOffset );
2002-04-16 17:31:00 +00:00
m_rectMarkerBar.SetXY( 0, fYPos );
m_rectMarkerBar.SetZoomX( (float)(m_iNumTracks+1) * ARROW_SIZE );
m_rectMarkerBar.SetZoomY( 20 );
m_rectMarkerBar.SetDiffuse( RageColor(0,0,0,0.5f) );
2002-04-16 17:31:00 +00:00
m_rectMarkerBar.Draw();
}
void NoteField::DrawBPMText( const float fBeat, const float fBPM )
2002-06-29 11:59:09 +00:00
{
const float fYOffset = ArrowGetYOffset( m_PlayerNumber, fBeat );
2002-07-28 20:28:37 +00:00
const float fYPos = ArrowGetYPos( m_PlayerNumber, fYOffset );
2002-06-29 11:59:09 +00:00
m_textMeasureNumber.SetDiffuse( RageColor(1,0,0,1) );
m_textMeasureNumber.SetGlow( RageColor(1,1,1,cosf(TIMER->GetTimeSinceStart()*2)/2+0.5f) );
2002-06-29 11:59:09 +00:00
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 float fBeat, const float fSecs )
2002-06-29 11:59:09 +00:00
{
const float fYOffset = ArrowGetYOffset( m_PlayerNumber, fBeat );
2002-07-28 20:28:37 +00:00
const float fYPos = ArrowGetYPos( m_PlayerNumber, fYOffset );
2002-06-29 11:59:09 +00:00
m_textMeasureNumber.SetDiffuse( RageColor(0.8f,0.8f,0,1) );
m_textMeasureNumber.SetGlow( RageColor(1,1,1,cosf(TIMER->GetTimeSinceStart()*2)/2+0.5f) );
2002-06-29 11:59:09 +00:00
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();
}
void NoteField::DrawBGChangeText( const float fBeat, const CString sNewBGName )
{
const float fYOffset = ArrowGetYOffset( m_PlayerNumber, fBeat );
const float fYPos = ArrowGetYPos( m_PlayerNumber, fYOffset );
m_textMeasureNumber.SetDiffuse( RageColor(0,1,0,1) );
m_textMeasureNumber.SetGlow( RageColor(1,1,1,cosf(TIMER->GetTimeSinceStart()*2)/2+0.5f) );
m_textMeasureNumber.SetText( sNewBGName );
m_textMeasureNumber.SetXY( +m_rectMeasureBar.GetZoomedWidth()/2 + 10, fYPos );
m_textMeasureNumber.Draw();
}
2002-05-19 01:59:48 +00:00
void NoteField::DrawPrimitives()
2002-04-16 17:31:00 +00:00
{
//LOG->Trace( "NoteField::DrawPrimitives()" );
2002-04-16 17:31:00 +00:00
const float fSongBeat = GAMESTATE->m_fSongBeat;
2002-04-16 17:31:00 +00:00
2002-07-28 20:28:37 +00:00
const float fBeatsToDrawBehind = m_iPixelsToDrawBehind * (1/(float)ARROW_SIZE) * (1/GAMESTATE->m_PlayerOptions[m_PlayerNumber].m_fArrowScrollSpeed);
const float fBeatsToDrawAhead = m_iPixelsToDrawAhead * (1/(float)ARROW_SIZE) * (1/GAMESTATE->m_PlayerOptions[m_PlayerNumber].m_fArrowScrollSpeed);
const float fFirstBeatToDraw = max( 0, fSongBeat - fBeatsToDrawBehind );
/* We actually want to draw up to the last row, which is after MAX_BEATS-1 but
* before MAX_BEATS. Rely on GetTapNote to cap it for us correctly. */
const float fLastBeatToDraw = min( MAX_BEATS, fSongBeat + fBeatsToDrawAhead );
const int iFirstIndexToDraw = BeatToNoteRow(fFirstBeatToDraw);
const int iLastIndexToDraw = BeatToNoteRow(fLastBeatToDraw);
2002-04-16 17:31:00 +00:00
2002-09-11 04:49:07 +00:00
// LOG->Trace( "Drawing elements %d through %d", iFirstIndexToDraw, iLastIndexToDraw );
2002-04-16 17:31:00 +00:00
2002-07-28 20:28:37 +00:00
if( GAMESTATE->m_bEditing )
2002-04-16 17:31:00 +00:00
{
unsigned i;
2002-06-29 11:59:09 +00:00
//
// Draw measure bars
//
2002-10-31 03:25:35 +00:00
unsigned iFirstMeasureToDraw = int(fFirstBeatToDraw)/BEATS_PER_MEASURE;
unsigned iLastMeasureToDraw = (int(fLastBeatToDraw)/BEATS_PER_MEASURE)+1;
2002-08-19 20:02:30 +00:00
for( i=iFirstMeasureToDraw; i<=iLastMeasureToDraw; i++ )
2002-08-17 06:44:04 +00:00
DrawMeasureBar( i );
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;
for( i=0; i<aBPMSegments.size(); i++ )
DrawBPMText( aBPMSegments[i].m_fStartBeat, aBPMSegments[i].m_fBPM );
2002-06-29 11:59:09 +00:00
//
// Freeze text
//
2002-07-23 01:41:40 +00:00
CArray<StopSegment,StopSegment&> &aStopSegments = GAMESTATE->m_pCurSong->m_StopSegments;
for( i=0; i<aStopSegments.size(); i++ )
DrawFreezeText( aStopSegments[i].m_fStartBeat, aStopSegments[i].m_fStopSeconds );
2002-06-29 11:59:09 +00:00
//
// BGChange text
//
CArray<BackgroundChange,BackgroundChange&> &aBackgroundChanges = GAMESTATE->m_pCurSong->m_BackgroundChanges;
for( i=0; i<aBackgroundChanges.size(); i++ )
DrawBGChangeText( aBackgroundChanges[i].m_fStartBeat, aBackgroundChanges[i].m_sBGName );
2002-06-29 11:59:09 +00:00
//
// Draw marker bars
//
2002-04-16 17:31:00 +00:00
if( m_fBeginMarker != -1 )
DrawMarkerBar( m_fBeginMarker );
2002-04-16 17:31:00 +00:00
if( m_fEndMarker != -1 )
DrawMarkerBar( m_fEndMarker );
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
//
// Optimization is very important here because there are so many arrows to draw.
// Draw the arrows in order of column. This minimize texture switches and let us
// draw in big batches.
//
2002-04-28 20:42:32 +00:00
for( int c=0; c<m_iNumTracks; c++ ) // for each arrow column
{
2002-06-14 22:25:22 +00:00
/////////////////////////////////
// Draw all HoldNotes in this column (so that they appear under the tap notes)
/////////////////////////////////
2002-11-16 09:12:55 +00:00
int i;
for( i=0; i < GetNumHoldNotes(); i++ )
2002-04-16 17:31:00 +00:00
{
2002-11-02 22:46:15 +00:00
const HoldNote &hn = GetHoldNote(i);
2002-08-01 03:15:27 +00:00
HoldNoteScore &hns = m_HoldNoteScores[i];
const float fLife = m_fHoldNoteLife[i];
const bool bIsHoldingNote = m_bIsHoldingHoldNote[i]; // hack: added -1 because hn.m_iStartIndex changes as note is held
2002-08-01 03:15:27 +00:00
if( hns == HNS_OK ) // if this HoldNote was completed
continue; // don't draw anything
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( !( fFirstBeatToDraw <= hn.m_fEndBeat && hn.m_fEndBeat <= fLastBeatToDraw ||
fFirstBeatToDraw <= hn.m_fStartBeat && hn.m_fStartBeat <= fLastBeatToDraw ||
hn.m_fStartBeat < fFirstBeatToDraw && hn.m_fEndBeat > fLastBeatToDraw ) )
2002-04-28 20:42:32 +00:00
{
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
m_NoteDisplay[c].DrawHold( hn, bIsHoldingNote, fLife, m_fPercentFadeToFail );
2002-04-16 17:31:00 +00:00
}
2002-06-14 22:25:22 +00:00
///////////////////////////////////
// Draw all TapNotes in this column
///////////////////////////////////
for( i=iFirstIndexToDraw; i<=iLastIndexToDraw; i++ ) // for each row
2002-06-14 22:25:22 +00:00
{
2002-11-02 21:44:52 +00:00
if( GetTapNote(c, i) == TAP_EMPTY ) // no note here
continue; // skip
2002-06-14 22:25:22 +00:00
2002-11-02 21:44:52 +00:00
if( GetTapNote(c, i) == TAP_HOLD_HEAD ) // this is a HoldNote begin marker. Grade it, but don't draw
continue; // skip
// See if there is a hold step that begins on this index.
bool bHoldNoteBeginsOnThisBeat = false;
for( int c2=0; c2<m_iNumTracks; c2++ )
2002-06-14 22:25:22 +00:00
{
2002-11-02 21:44:52 +00:00
if( GetTapNote(c2, i) == TAP_HOLD_HEAD )
2002-06-14 22:25:22 +00:00
{
bHoldNoteBeginsOnThisBeat = true;
2002-06-14 22:25:22 +00:00
break;
}
}
m_NoteDisplay[c].DrawTap( c, NoteRowToBeat(i), bHoldNoteBeginsOnThisBeat, m_fPercentFadeToFail );
}
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++ )
2002-10-25 04:59:12 +00:00
SetTapNote(c, iIndex, TAP_EMPTY);
2002-04-16 17:31:00 +00:00
}
2002-08-01 21:55:40 +00:00
void NoteField::FadeToFail()
{
m_fPercentFadeToFail = max( 0.0f, m_fPercentFadeToFail ); // this will slowly increase every Update()
// don't fade all over again if this is called twice
2002-11-16 09:12:55 +00:00
}