From 2c7db70f4b60d78703286be3f1c9e8c27e634e81 Mon Sep 17 00:00:00 2001 From: Glenn Maynard Date: Sat, 8 Feb 2003 23:47:47 +0000 Subject: [PATCH] instead of toggling head/tail as wavy/not, have a wavy part (top cap and bottom cap) and a solid part (head/tail). allow overriding note skin metric values per-button (rather larger patch than I intended to commit at once; sorry) --- stepmania/src/NoteDisplay.cpp | 709 +++++++++++++++++------------- stepmania/src/NoteDisplay.h | 21 +- stepmania/src/NoteSkinManager.cpp | 39 +- stepmania/src/NoteSkinManager.h | 12 +- 4 files changed, 444 insertions(+), 337 deletions(-) diff --git a/stepmania/src/NoteDisplay.cpp b/stepmania/src/NoteDisplay.cpp index 8df16d3f3c..5472425823 100644 --- a/stepmania/src/NoteDisplay.cpp +++ b/stepmania/src/NoteDisplay.cpp @@ -26,79 +26,106 @@ #include "NoteTypes.h" -#define DRAW_HOLD_HEAD_FOR_TAPS_ON_SAME_ROW NOTESKIN->GetMetricB("NoteDisplay","DrawHoldHeadForTapsOnSameRow") -#define TAP_NOTE_ANIMATION_LENGTH_IN_BEATS NOTESKIN->GetMetricF("NoteDisplay","TapNoteAnimationLengthInBeats") -#define HOLD_HEAD_ANIMATION_LENGTH_IN_BEATS NOTESKIN->GetMetricF("NoteDisplay","HoldHeadAnimationLengthInBeats") -#define HOLD_BODY_ANIMATION_LENGTH_IN_BEATS NOTESKIN->GetMetricF("NoteDisplay","HoldBodyAnimationLengthInBeats") -#define HOLD_TAIL_ANIMATION_LENGTH_IN_BEATS NOTESKIN->GetMetricF("NoteDisplay","HoldTailAnimationLengthInBeats") -#define TAP_NOTE_ANIMATION_IS_VIVID NOTESKIN->GetMetricB("NoteDisplay","TapNoteAnimationIsVivid") -#define HOLD_HEAD_ANIMATION_IS_VIVID NOTESKIN->GetMetricB("NoteDisplay","HoldHeadAnimationIsVivid") -#define HOLD_BODY_ANIMATION_IS_VIVID NOTESKIN->GetMetricB("NoteDisplay","HoldBodyAnimationIsVivid") -#define HOLD_TAIL_ANIMATION_IS_VIVID NOTESKIN->GetMetricB("NoteDisplay","HoldTailAnimationIsVivid") -#define TAP_NOTE_ANIMATION_IS_NOTE_COLOR NOTESKIN->GetMetricB("NoteDisplay","TapNoteAnimationIsNoteColor") -#define HOLD_HEAD_ANIMATION_IS_NOTE_COLOR NOTESKIN->GetMetricB("NoteDisplay","HoldHeadAnimationIsNoteColor") -#define HOLD_BODY_ANIMATION_IS_NOTE_COLOR NOTESKIN->GetMetricB("NoteDisplay","HoldBodyAnimationIsNoteColor") -#define HOLD_TAIL_ANIMATION_IS_NOTE_COLOR NOTESKIN->GetMetricB("NoteDisplay","HoldTailAnimationIsNoteColor") -#define START_DRAWING_HOLD_BODY_OFFSET_FROM_HEAD NOTESKIN->GetMetricI("NoteDisplay","StartDrawingHoldBodyOffsetFromHead") -#define STOP_DRAWING_HOLD_BODY_OFFSET_FROM_TAIL NOTESKIN->GetMetricI("NoteDisplay","StopDrawingHoldBodyOffsetFromTail") -#define HOLD_HEAD_IS_WAVY NOTESKIN->GetMetricB("NoteDisplay","HoldHeadIsWavy") -#define HOLD_TAIL_IS_WAVY NOTESKIN->GetMetricB("NoteDisplay","HoldTailIsWavy") -#define HOLD_NG_GRAY_PERCENT NOTESKIN->GetMetricF("NoteDisplay","HoldNGGrayPercent") +#define DRAW_HOLD_HEAD_FOR_TAPS_ON_SAME_ROW NOTESKIN->GetMetricB(name,"DrawHoldHeadForTapsOnSameRow") +#define TAP_NOTE_ANIMATION_LENGTH_IN_BEATS NOTESKIN->GetMetricF(name,"TapNoteAnimationLengthInBeats") +#define HOLD_HEAD_ANIMATION_LENGTH_IN_BEATS NOTESKIN->GetMetricF(name,"HoldHeadAnimationLengthInBeats") +#define HOLD_TOPCAP_ANIMATION_LENGTH_IN_BEATS NOTESKIN->GetMetricF(name,"HoldTopCapAnimationLengthInBeats") +#define HOLD_BODY_ANIMATION_LENGTH_IN_BEATS NOTESKIN->GetMetricF(name,"HoldBodyAnimationLengthInBeats") +#define HOLD_BOTTOMCAP_ANIMATION_LENGTH_IN_BEATS NOTESKIN->GetMetricF(name,"HoldBottomCapAnimationLengthInBeats") +#define HOLD_TAIL_ANIMATION_LENGTH_IN_BEATS NOTESKIN->GetMetricF(name,"HoldTailAnimationLengthInBeats") +#define TAP_NOTE_ANIMATION_IS_VIVID NOTESKIN->GetMetricB(name,"TapNoteAnimationIsVivid") +#define HOLD_HEAD_ANIMATION_IS_VIVID NOTESKIN->GetMetricB(name,"HoldHeadAnimationIsVivid") +#define HOLD_TOPCAP_ANIMATION_IS_VIVID NOTESKIN->GetMetricB(name,"HoldTopCapAnimationIsVivid") +#define HOLD_BODY_ANIMATION_IS_VIVID NOTESKIN->GetMetricB(name,"HoldBodyAnimationIsVivid") +#define HOLD_BOTTOMCAP_ANIMATION_IS_VIVID NOTESKIN->GetMetricB(name,"HoldBottomCapAnimationIsVivid") +#define HOLD_TAIL_ANIMATION_IS_VIVID NOTESKIN->GetMetricB(name,"HoldTailAnimationIsVivid") +#define TAP_NOTE_ANIMATION_IS_NOTE_COLOR NOTESKIN->GetMetricB(name,"TapNoteAnimationIsNoteColor") +#define HOLD_HEAD_ANIMATION_IS_NOTE_COLOR NOTESKIN->GetMetricB(name,"HoldHeadAnimationIsNoteColor") +#define HOLD_TOPCAP_ANIMATION_IS_NOTE_COLOR NOTESKIN->GetMetricB(name,"HoldHeadAnimationIsNoteColor") +#define HOLD_BODY_ANIMATION_IS_NOTE_COLOR NOTESKIN->GetMetricB(name,"HoldBodyAnimationIsNoteColor") +#define HOLD_BOTTOMCAP_ANIMATION_IS_NOTE_COLOR NOTESKIN->GetMetricB(name,"HoldHeadAnimationIsNoteColor") +#define HOLD_TAIL_ANIMATION_IS_NOTE_COLOR NOTESKIN->GetMetricB(name,"HoldTailAnimationIsNoteColor") +#define START_DRAWING_HOLD_BODY_OFFSET_FROM_HEAD NOTESKIN->GetMetricI(name,"StartDrawingHoldBodyOffsetFromHead") +#define STOP_DRAWING_HOLD_BODY_OFFSET_FROM_TAIL NOTESKIN->GetMetricI(name,"StopDrawingHoldBodyOffsetFromTail") +#define HOLD_NG_GRAY_PERCENT NOTESKIN->GetMetricF(name,"HoldNGGrayPercent") // cache -bool g_bDrawHoldHeadForTapsOnSameRow; -float g_fTapNoteAnimationLengthInBeats; -float g_fHoldHeadAnimationLengthInBeats; -float g_fHoldBodyAnimationLengthInBeats; -float g_fHoldTailAnimationLengthInBeats; -bool g_bTapNoteAnimationIsVivid; -bool g_bHoldHeadAnimationIsVivid; -bool g_bHoldBodyAnimationIsVivid; -bool g_bHoldTailAnimationIsVivid; -bool g_bTapNoteAnimationIsNoteColor; -bool g_bHoldHeadAnimationIsNoteColor; -bool g_bHoldBodyAnimationIsNoteColor; -bool g_bHoldTailAnimationIsNoteColor; -int g_iStartDrawingHoldBodyOffsetFromHead; -int g_iStopDrawingHoldBodyOffsetFromTail; -bool g_bHoldHeadIsWavy; -bool g_bHoldTailIsWavy; -float g_fHoldNGGrayPercent; +struct NoteMetricCache_t { + bool m_bDrawHoldHeadForTapsOnSameRow; + float m_fTapNoteAnimationLengthInBeats; + float m_fHoldHeadAnimationLengthInBeats; + float m_fHoldTopCapAnimationLengthInBeats; + float m_fHoldBodyAnimationLengthInBeats; + float m_fHoldBottomCapAnimationLengthInBeats; + float m_fHoldTailAnimationLengthInBeats; + bool m_bTapNoteAnimationIsVivid; + bool m_bHoldHeadAnimationIsVivid; + bool m_bHoldTopCapAnimationIsVivid; + bool m_bHoldBodyAnimationIsVivid; + bool m_bHoldBottomCapAnimationIsVivid; + bool m_bHoldTailAnimationIsVivid; + bool m_bTapNoteAnimationIsNoteColor; + bool m_bHoldHeadAnimationIsNoteColor; + bool m_bHoldTopCapAnimationIsNoteColor; + bool m_bHoldBodyAnimationIsNoteColor; + bool m_bHoldBottomCapAnimationIsNoteColor; + bool m_bHoldTailAnimationIsNoteColor; + int m_iStartDrawingHoldBodyOffsetFromHead; + int m_iStopDrawingHoldBodyOffsetFromTail; + float m_fHoldNGGrayPercent; + + void Load(const CString &name); +} *NoteMetricCache; + +void NoteMetricCache_t::Load(const CString &name) +{ + m_bDrawHoldHeadForTapsOnSameRow = DRAW_HOLD_HEAD_FOR_TAPS_ON_SAME_ROW; + m_fTapNoteAnimationLengthInBeats = TAP_NOTE_ANIMATION_LENGTH_IN_BEATS; + m_fHoldHeadAnimationLengthInBeats = HOLD_HEAD_ANIMATION_LENGTH_IN_BEATS; + m_fHoldTopCapAnimationLengthInBeats = HOLD_TOPCAP_ANIMATION_LENGTH_IN_BEATS; + m_fHoldBodyAnimationLengthInBeats = HOLD_BODY_ANIMATION_LENGTH_IN_BEATS; + m_fHoldBottomCapAnimationLengthInBeats = HOLD_BOTTOMCAP_ANIMATION_LENGTH_IN_BEATS; + m_fHoldTailAnimationLengthInBeats = HOLD_TAIL_ANIMATION_LENGTH_IN_BEATS; + m_bTapNoteAnimationIsVivid = TAP_NOTE_ANIMATION_IS_VIVID; + m_bHoldHeadAnimationIsVivid = HOLD_HEAD_ANIMATION_IS_VIVID; + m_bHoldTopCapAnimationIsVivid = HOLD_TOPCAP_ANIMATION_IS_VIVID; + m_bHoldBodyAnimationIsVivid = HOLD_BODY_ANIMATION_IS_VIVID; + m_bHoldBottomCapAnimationIsVivid = HOLD_BOTTOMCAP_ANIMATION_IS_VIVID; + m_bHoldTailAnimationIsVivid = HOLD_TAIL_ANIMATION_IS_VIVID; + m_bTapNoteAnimationIsNoteColor = TAP_NOTE_ANIMATION_IS_NOTE_COLOR; + m_bHoldHeadAnimationIsNoteColor = HOLD_HEAD_ANIMATION_IS_NOTE_COLOR; + m_bHoldTopCapAnimationIsNoteColor = HOLD_TOPCAP_ANIMATION_IS_NOTE_COLOR; + m_bHoldBodyAnimationIsNoteColor = HOLD_BODY_ANIMATION_IS_NOTE_COLOR; + m_bHoldBottomCapAnimationIsNoteColor = HOLD_BOTTOMCAP_ANIMATION_IS_NOTE_COLOR; + m_bHoldTailAnimationIsNoteColor = HOLD_TAIL_ANIMATION_IS_NOTE_COLOR; + m_iStartDrawingHoldBodyOffsetFromHead = START_DRAWING_HOLD_BODY_OFFSET_FROM_HEAD; + m_iStopDrawingHoldBodyOffsetFromTail = STOP_DRAWING_HOLD_BODY_OFFSET_FROM_TAIL; + m_fHoldNGGrayPercent = HOLD_NG_GRAY_PERCENT; +} NoteDisplay::NoteDisplay() { - g_bDrawHoldHeadForTapsOnSameRow = DRAW_HOLD_HEAD_FOR_TAPS_ON_SAME_ROW; - g_fTapNoteAnimationLengthInBeats = TAP_NOTE_ANIMATION_LENGTH_IN_BEATS; - g_fHoldHeadAnimationLengthInBeats = HOLD_HEAD_ANIMATION_LENGTH_IN_BEATS; - g_fHoldBodyAnimationLengthInBeats = HOLD_BODY_ANIMATION_LENGTH_IN_BEATS; - g_fHoldTailAnimationLengthInBeats = HOLD_TAIL_ANIMATION_LENGTH_IN_BEATS; - g_bTapNoteAnimationIsVivid = TAP_NOTE_ANIMATION_IS_VIVID; - g_bHoldHeadAnimationIsVivid = HOLD_HEAD_ANIMATION_IS_VIVID; - g_bHoldBodyAnimationIsVivid = HOLD_BODY_ANIMATION_IS_VIVID; - g_bHoldTailAnimationIsVivid = HOLD_TAIL_ANIMATION_IS_VIVID; - g_bTapNoteAnimationIsNoteColor = TAP_NOTE_ANIMATION_IS_NOTE_COLOR; - g_bHoldHeadAnimationIsNoteColor = HOLD_HEAD_ANIMATION_IS_NOTE_COLOR; - g_bHoldBodyAnimationIsNoteColor = HOLD_BODY_ANIMATION_IS_NOTE_COLOR; - g_bHoldTailAnimationIsNoteColor = HOLD_TAIL_ANIMATION_IS_NOTE_COLOR; - g_iStartDrawingHoldBodyOffsetFromHead = START_DRAWING_HOLD_BODY_OFFSET_FROM_HEAD; - g_iStopDrawingHoldBodyOffsetFromTail = STOP_DRAWING_HOLD_BODY_OFFSET_FROM_TAIL; - g_bHoldHeadIsWavy = HOLD_HEAD_IS_WAVY; - g_bHoldTailIsWavy = HOLD_TAIL_IS_WAVY; - g_fHoldNGGrayPercent = HOLD_NG_GRAY_PERCENT; + cache = new NoteMetricCache_t; } +NoteDisplay::~NoteDisplay() +{ + delete cache; +} void NoteDisplay::Load( int iColNum, PlayerNumber pn ) { m_PlayerNumber = pn; + cache->Load(NoteSkinManager::ColToButtonName(iColNum)); + // Look up note names once and store them here. CString sNoteType[ NOTE_COLOR_IMAGES ]; for( int i=0; im_bTapNoteAnimationIsNoteColor ) { for( int i=0; iGetPathTo(iColNum, "tap note "+sNoteType[i]) ); @@ -108,7 +135,7 @@ void NoteDisplay::Load( int iColNum, PlayerNumber pn ) m_sprTapNote[0].Load( NOTESKIN->GetPathTo(iColNum, "tap note") ); } - if( g_bHoldHeadAnimationIsNoteColor ) + if( cache->m_bHoldHeadAnimationIsNoteColor ) { for( int i=0; iGetPathTo(iColNum, "hold head inactive") ); } - if( g_bHoldBodyAnimationIsNoteColor ) + if( cache->m_bHoldTopCapAnimationIsNoteColor ) + { + for( int i=0; iGetPathTo(iColNum, "hold topcap active "+sNoteType[i]) ); + m_sprHoldTopCapInactive[i].Load( NOTESKIN->GetPathTo(iColNum, "hold topcap inactive "+sNoteType[i]) ); + } + } + else + { + m_sprHoldTopCapActive[0].Load( NOTESKIN->GetPathTo(iColNum, "hold topcap active") ); + m_sprHoldTopCapInactive[0].Load( NOTESKIN->GetPathTo(iColNum, "hold topcap inactive") ); + } + + if( cache->m_bHoldBodyAnimationIsNoteColor ) { for( int i=0; iGetPathTo(iColNum, "hold body inactive") ); } - if( g_bHoldTailAnimationIsNoteColor ) + if( cache->m_bHoldBottomCapAnimationIsNoteColor ) + { + for( int i=0; iGetPathTo(iColNum, "hold bottomcap active "+sNoteType[i]) ); + m_sprHoldBottomCapInactive[i].Load( NOTESKIN->GetPathTo(iColNum, "hold bottomcap inactive "+sNoteType[i]) ); + } + } + else + { + m_sprHoldBottomCapActive[0].Load( NOTESKIN->GetPathTo(iColNum, "hold bottomcap active") ); + m_sprHoldBottomCapInactive[0].Load( NOTESKIN->GetPathTo(iColNum, "hold bottomcap inactive") ); + } + + if( cache->m_bHoldTailAnimationIsNoteColor ) { for( int i=0; im_fSongBeat; float fPrecentIntoAnimation = fmodf(fSongBeat,fAnimationLengthInBeats) / fAnimationLengthInBeats; float fNoteBeatFraction = fmodf( fNoteBeat, 1.0f ); @@ -166,88 +222,128 @@ int NoteDisplay::GetFrameNo( float fNoteBeat, int iNumFrames, float fAnimationLe iFrameNo %= iNumFrames; ASSERT( iFrameNo>=0 && iFrameNom_bTapNoteAnimationIsNoteColor ) + nt = BeatToNoteType( fNoteBeat ); + if( nt == NOTE_TYPE_INVALID ) + nt = NOTE_TYPE_32ND; + Sprite *pSpriteOut = &m_sprTapNote[nt]; - iFrameNoOut = GetFrameNo( + SetActiveFrame( fNoteBeat, - pSpriteOut->GetNumStates(), - g_fTapNoteAnimationLengthInBeats, - g_bTapNoteAnimationIsVivid, - g_bTapNoteAnimationIsNoteColor ); + *pSpriteOut, + cache->m_fTapNoteAnimationLengthInBeats, + cache->m_bTapNoteAnimationIsVivid, + cache->m_bTapNoteAnimationIsNoteColor ); + + return pSpriteOut; } -void NoteDisplay::GetHoldHeadSpriteAndFrameNo( float fNoteBeat, bool bActive, Sprite*& pSpriteOut, int& iFrameNoOut ) +Sprite * NoteDisplay::GetHoldTopCapSprite( float fNoteBeat, bool bActive ) { - if( g_bHoldHeadAnimationIsNoteColor ) - { - NoteType nt = BeatToNoteType( fNoteBeat ); - if( nt == NOTE_TYPE_INVALID ) - nt = NOTE_TYPE_32ND; - pSpriteOut = bActive ? &m_sprHoldHeadActive[nt] : &m_sprHoldHeadInactive[nt]; - } - else - pSpriteOut = bActive ? &m_sprHoldHeadActive[0] : &m_sprHoldHeadInactive[0]; + NoteType nt = NoteType(0); + if( cache->m_bHoldTopCapAnimationIsNoteColor ) + nt = BeatToNoteType( fNoteBeat ); + if( nt == NOTE_TYPE_INVALID ) + nt = NOTE_TYPE_32ND; + + Sprite *pSpriteOut = bActive ? &m_sprHoldTopCapActive[nt] : &m_sprHoldTopCapInactive[nt]; - iFrameNoOut = GetFrameNo( + SetActiveFrame( fNoteBeat, - pSpriteOut->GetNumStates(), - g_fHoldHeadAnimationLengthInBeats, - g_bHoldHeadAnimationIsVivid, - g_bHoldHeadAnimationIsNoteColor ); + *pSpriteOut, + cache->m_fHoldTopCapAnimationLengthInBeats, + cache->m_bHoldTopCapAnimationIsVivid, + cache->m_bHoldTopCapAnimationIsNoteColor ); + + return pSpriteOut; } -void NoteDisplay::GetHoldBodySpriteAndFrameNo( float fNoteBeat, bool bActive, Sprite*& pSpriteOut, int& iFrameNoOut ) +Sprite * NoteDisplay::GetHoldBottomCapSprite( float fNoteBeat, bool bActive ) { - if( g_bHoldBodyAnimationIsNoteColor ) - { - NoteType nt = BeatToNoteType( fNoteBeat ); - if( nt == NOTE_TYPE_INVALID ) - nt = NOTE_TYPE_32ND; - pSpriteOut = bActive ? &m_sprHoldBodyActive[nt] : &m_sprHoldBodyInactive[nt]; - } - else - pSpriteOut = bActive ? &m_sprHoldBodyActive[0] : &m_sprHoldBodyInactive[0]; + NoteType nt = NoteType(0); + if( cache->m_bHoldBottomCapAnimationIsNoteColor ) + nt = BeatToNoteType( fNoteBeat ); + if( nt == NOTE_TYPE_INVALID ) + nt = NOTE_TYPE_32ND; + + Sprite *pSpriteOut = bActive ? &m_sprHoldBottomCapActive[nt] : &m_sprHoldBottomCapInactive[nt]; - iFrameNoOut = GetFrameNo( + SetActiveFrame( fNoteBeat, - pSpriteOut->GetNumStates(), - g_fHoldBodyAnimationLengthInBeats, - g_bHoldBodyAnimationIsVivid, - g_bHoldBodyAnimationIsNoteColor ); + *pSpriteOut, + cache->m_fHoldBottomCapAnimationLengthInBeats, + cache->m_bHoldBottomCapAnimationIsVivid, + cache->m_bHoldBottomCapAnimationIsNoteColor ); + + return pSpriteOut; } -void NoteDisplay::GetHoldTailSpriteAndFrameNo( float fNoteBeat, bool bActive, Sprite*& pSpriteOut, int& iFrameNoOut ) + +Sprite * NoteDisplay::GetHoldHeadSprite( float fNoteBeat, bool bActive ) { + NoteType nt = NoteType(0); + if( cache->m_bHoldHeadAnimationIsNoteColor ) + nt = BeatToNoteType( fNoteBeat ); + if( nt == NOTE_TYPE_INVALID ) + nt = NOTE_TYPE_32ND; - if( g_bHoldTailAnimationIsNoteColor ) - { - NoteType nt = BeatToNoteType( fNoteBeat ); - if( nt == NOTE_TYPE_INVALID ) - nt = NOTE_TYPE_32ND; - pSpriteOut = bActive ? &m_sprHoldTailActive[nt] : &m_sprHoldTailInactive[nt]; - } - else - pSpriteOut = bActive ? &m_sprHoldTailActive[0] : &m_sprHoldTailInactive[0]; + Sprite *pSpriteOut = bActive ? &m_sprHoldHeadActive[nt] : &m_sprHoldHeadInactive[nt]; - iFrameNoOut = GetFrameNo( + SetActiveFrame( fNoteBeat, - pSpriteOut->GetNumStates(), - g_fHoldTailAnimationLengthInBeats, - g_bHoldTailAnimationIsVivid, - g_bHoldTailAnimationIsNoteColor ); + *pSpriteOut, + cache->m_fHoldHeadAnimationLengthInBeats, + cache->m_bHoldHeadAnimationIsVivid, + cache->m_bHoldHeadAnimationIsNoteColor ); + + return pSpriteOut; +} + +Sprite *NoteDisplay::GetHoldBodySprite( float fNoteBeat, bool bActive ) +{ + NoteType nt = NoteType(0); + if( cache->m_bHoldBodyAnimationIsNoteColor ) + nt = BeatToNoteType( fNoteBeat ); + if( nt == NOTE_TYPE_INVALID ) + nt = NOTE_TYPE_32ND; + + Sprite *pSpriteOut = bActive ? &m_sprHoldBodyActive[nt] : &m_sprHoldBodyInactive[nt]; + + SetActiveFrame( + fNoteBeat, + *pSpriteOut, + cache->m_fHoldBodyAnimationLengthInBeats, + cache->m_bHoldBodyAnimationIsVivid, + cache->m_bHoldBodyAnimationIsNoteColor ); + + return pSpriteOut; +} + +Sprite * NoteDisplay::GetHoldTailSprite( float fNoteBeat, bool bActive ) +{ + NoteType nt = NoteType(0); + if( cache->m_bHoldTailAnimationIsNoteColor ) + nt = BeatToNoteType( fNoteBeat ); + if( nt == NOTE_TYPE_INVALID ) + nt = NOTE_TYPE_32ND; + + Sprite *pSpriteOut = bActive ? &m_sprHoldTailActive[nt] : &m_sprHoldTailInactive[nt]; + + SetActiveFrame( + fNoteBeat, + *pSpriteOut, + cache->m_fHoldTailAnimationLengthInBeats, + cache->m_bHoldTailAnimationIsVivid, + cache->m_bHoldTailAnimationIsNoteColor ); + + return pSpriteOut; } @@ -268,120 +364,92 @@ void NoteDisplay::DrawHold( const HoldNote& hn, const bool bActive, const float const int fYStep = 16; // 16 logical pixels per segment - const float fColorScale = 1*fLife + (1-fLife)*g_fHoldNGGrayPercent; + const float fColorScale = 1*fLife + (1-fLife)*cache->m_fHoldNGGrayPercent; // // draw from tail to head (so head appears on top) // + /* The body and caps should have no overlap, so their order doesn't matter. + * Draw the head last, so it appears on top. */ static RageVertex queue[4096]; // - // Draw the tail + // Draw the bottom cap (always wavy) // { - Sprite* pSprTail; - int iFrameNo; - GetHoldTailSpriteAndFrameNo( hn.m_fStartBeat, bActive, pSprTail, iFrameNo ); + Sprite* pBottomCap = GetHoldBottomCapSprite( hn.m_fStartBeat, bActive ); - if( g_bHoldTailIsWavy ) + // draw manually in small segments + RageVertex *v = &queue[0]; + RageTexture* pTexture = pBottomCap->GetTexture(); + const RectF *pRect = pBottomCap->GetCurrentTextureCoordRect(); + DISPLAY->SetTexture( pTexture ); + DISPLAY->SetBlendModeNormal(); + if( bDrawGlowOnly ) + DISPLAY->SetTextureModeGlow(); + else + DISPLAY->SetTextureModeModulate(); + DISPLAY->DisableTextureWrapping(); + + const float fFrameWidth = pBottomCap->GetUnzoomedWidth(); + const float fFrameHeight = pBottomCap->GetUnzoomedHeight(); + const float fYCapTop = fYTail+cache->m_iStopDrawingHoldBodyOffsetFromTail; + const float fYCapBottom = fYTail+cache->m_iStopDrawingHoldBodyOffsetFromTail+fFrameHeight; + + // don't draw any part of the tail that is before the middle of the head + float fY=max( fYCapTop, fYHead ); + for( ; fYGetTexture(); - const RectF* pRect = pTexture->GetTextureCoordRect( iFrameNo ); - DISPLAY->SetTexture( pTexture ); - DISPLAY->SetBlendModeNormal(); - if( bDrawGlowOnly ) - DISPLAY->SetTextureModeGlow(); - else - DISPLAY->SetTextureModeModulate(); - DISPLAY->DisableTextureWrapping(); + const float fYTop = fY; + const float fStepHeight = min( fYStep, fFrameHeight ); + const float fYBottom = min( fY+fStepHeight, fYCapBottom ); + const float fXTop = ArrowGetXPos( m_PlayerNumber, iCol, fYTop ); + const float fXBottom = ArrowGetXPos( m_PlayerNumber, iCol, fYBottom ); + const float fXTopLeft = fXTop - fFrameWidth/2; + const float fXTopRight = fXTop + fFrameWidth/2; + const float fXBottomLeft = fXBottom - fFrameWidth/2; + const float fXBottomRight = fXBottom + fFrameWidth/2; + const float fTopDistFromTailTop = fYTop - fYCapTop; + const float fBottomDistFromTailTop = fYBottom - fYCapTop; + const float fTexCoordTop = SCALE( fTopDistFromTailTop, 0, fFrameHeight, pRect->top, pRect->bottom ); + const float fTexCoordBottom = SCALE( fBottomDistFromTailTop, 0, fFrameHeight, pRect->top, pRect->bottom ); + const float fTexCoordLeft = pRect->left; + const float fTexCoordRight = pRect->right; + const float fAlphaTop = ArrowGetAlpha( m_PlayerNumber, fYTop, fPercentFadeToFail ); + const float fAlphaBottom = ArrowGetAlpha( m_PlayerNumber, fYBottom, fPercentFadeToFail ); + const float fGlowTop = ArrowGetGlow( m_PlayerNumber, fYTop, fPercentFadeToFail ); + const float fGlowBottom = ArrowGetGlow( m_PlayerNumber, fYBottom, fPercentFadeToFail ); + const RageColor colorDiffuseTop = RageColor(fColorScale,fColorScale,fColorScale,fAlphaTop); + const RageColor colorDiffuseBottom = RageColor(fColorScale,fColorScale,fColorScale,fAlphaBottom); + const RageColor colorGlowTop = RageColor(1,1,1,fGlowTop); + const RageColor colorGlowBottom = RageColor(1,1,1,fGlowBottom); + if( bDrawGlowOnly && colorGlowTop.a==0 && colorGlowBottom.a==0 ) + continue; + if( !bDrawGlowOnly && colorDiffuseTop.a==0 && colorDiffuseBottom.a==0 ) + continue; - const float fFrameWidth = pSprTail->GetUnzoomedWidth(); - const float fFrameHeight = pSprTail->GetUnzoomedHeight(); - const float fYTailTop = fYTail-fFrameHeight/2; - const float fYTailBottom = fYTail+fFrameHeight/2; - - float fY=max( fYTailTop, fYHead ); // don't draw any part of the tail that is before the middle of the head - for( ; fYtop, pRect->bottom ); - const float fTexCoordBottom = SCALE( fBottomDistFromTailTop, 0, fFrameHeight, pRect->top, pRect->bottom ); - const float fTexCoordLeft = pRect->left; - const float fTexCoordRight = pRect->right; - const float fAlphaTop = ArrowGetAlpha( m_PlayerNumber, fYTop, fPercentFadeToFail ); - const float fAlphaBottom = ArrowGetAlpha( m_PlayerNumber, fYBottom, fPercentFadeToFail ); - const float fGlowTop = ArrowGetGlow( m_PlayerNumber, fYTop, fPercentFadeToFail ); - const float fGlowBottom = ArrowGetGlow( m_PlayerNumber, fYBottom, fPercentFadeToFail ); - const RageColor colorDiffuseTop = RageColor(fColorScale,fColorScale,fColorScale,fAlphaTop); - const RageColor colorDiffuseBottom = RageColor(fColorScale,fColorScale,fColorScale,fAlphaBottom); - const RageColor colorGlowTop = RageColor(1,1,1,fGlowTop); - const RageColor colorGlowBottom = RageColor(1,1,1,fGlowBottom); - - if( bDrawGlowOnly && colorGlowTop.a==0 && colorGlowBottom.a==0 ) - continue; - if( !bDrawGlowOnly && colorDiffuseTop.a==0 && colorDiffuseBottom.a==0 ) - continue; - - v[0].p = RageVector3(fXTopLeft, fYTop, 0); v[0].c = bDrawGlowOnly ? colorGlowTop : colorDiffuseTop; v[0].t = RageVector2(fTexCoordLeft, fTexCoordTop), - v[1].p = RageVector3(fXTopRight, fYTop, 0); v[1].c = bDrawGlowOnly ? colorGlowTop : colorDiffuseTop; v[1].t = RageVector2(fTexCoordRight, fTexCoordTop); - v[2].p = RageVector3(fXBottomRight,fYBottom,0); v[2].c = bDrawGlowOnly ? colorGlowBottom : colorDiffuseBottom; v[2].t = RageVector2(fTexCoordRight, fTexCoordBottom); - v[3].p = RageVector3(fXBottomLeft, fYBottom,0); v[3].c = bDrawGlowOnly ? colorGlowBottom : colorDiffuseBottom; v[3].t = RageVector2(fTexCoordLeft, fTexCoordBottom); - v+=4; - } - DISPLAY->DrawQuads( queue, v-queue ); - } - else // !g_bHoldTailIsWavy - { - // draw with normal Sprite - const float fY = fYTail; - const float fX = ArrowGetXPos( m_PlayerNumber, iCol, fY ); - const float fAlpha = ArrowGetAlpha( m_PlayerNumber, fY, fPercentFadeToFail ); - const float fGlow = ArrowGetGlow( m_PlayerNumber, fY, fPercentFadeToFail ); - const RageColor colorDiffuse= RageColor(fColorScale,fColorScale,fColorScale,fAlpha); - const RageColor colorGlow = RageColor(1,1,1,fGlow); - - pSprTail->SetXY( fX, fY ); - pSprTail->SetState( iFrameNo ); - if( bDrawGlowOnly ) - { - pSprTail->SetDiffuse( RageColor(1,1,1,0) ); - pSprTail->SetGlow( colorGlow ); - } - else - { - pSprTail->SetDiffuse( colorDiffuse ); - pSprTail->SetGlow( RageColor(0,0,0,0) ); - } - pSprTail->Draw(); + v[0].p = RageVector3(fXTopLeft, fYTop, 0); v[0].c = bDrawGlowOnly ? colorGlowTop : colorDiffuseTop; v[0].t = RageVector2(fTexCoordLeft, fTexCoordTop), + v[1].p = RageVector3(fXTopRight, fYTop, 0); v[1].c = bDrawGlowOnly ? colorGlowTop : colorDiffuseTop; v[1].t = RageVector2(fTexCoordRight, fTexCoordTop); + v[2].p = RageVector3(fXBottomRight,fYBottom,0); v[2].c = bDrawGlowOnly ? colorGlowBottom : colorDiffuseBottom; v[2].t = RageVector2(fTexCoordRight, fTexCoordBottom); + v[3].p = RageVector3(fXBottomLeft, fYBottom,0); v[3].c = bDrawGlowOnly ? colorGlowBottom : colorDiffuseBottom; v[3].t = RageVector2(fTexCoordLeft, fTexCoordBottom); + v+=4; } + DISPLAY->DrawQuads( queue, v-queue ); } // // Draw the body (always wavy) // { - Sprite* pSprBody; - int iFrameNo; - GetHoldBodySpriteAndFrameNo( hn.m_fStartBeat, bActive, pSprBody, iFrameNo ); + Sprite* pSprBody = GetHoldBodySprite( hn.m_fStartBeat, bActive ); // draw manually in small segments RageVertex *v = &queue[0]; RageTexture* pTexture = pSprBody->GetTexture(); - const RectF* pRect = pTexture->GetTextureCoordRect( iFrameNo ); + const RectF *pRect = pSprBody->GetCurrentTextureCoordRect(); DISPLAY->SetTexture( pTexture ); DISPLAY->SetBlendModeNormal(); if( bDrawGlowOnly ) @@ -393,8 +461,8 @@ void NoteDisplay::DrawHold( const HoldNote& hn, const bool bActive, const float const float fFrameWidth = pSprBody->GetUnzoomedWidth(); const float fFrameHeight = pSprBody->GetUnzoomedHeight(); - const float fYBodyTop = fYHead + g_iStartDrawingHoldBodyOffsetFromHead; - const float fYBodyBottom = fYTail + g_iStopDrawingHoldBodyOffsetFromTail; + const float fYBodyTop = fYHead + cache->m_iStartDrawingHoldBodyOffsetFromHead; + const float fYBodyBottom = fYTail + cache->m_iStopDrawingHoldBodyOffsetFromTail; // top to bottom for( float fY=fYBodyTop; fY<=fYBodyBottom; fY+=fYStep ) @@ -450,100 +518,125 @@ void NoteDisplay::DrawHold( const HoldNote& hn, const bool bActive, const float DISPLAY->DrawQuads( queue, v-queue ); } + // + // Draw the top cap (always wavy) + // + { + Sprite* pSprTopCap = GetHoldTopCapSprite( hn.m_fStartBeat, bActive ); + + // draw manually in small segments + RageVertex *v = &queue[0]; + RageTexture* pTexture = pSprTopCap->GetTexture(); + const RectF *pRect = pSprTopCap->GetCurrentTextureCoordRect(); + DISPLAY->SetTexture( pTexture ); + DISPLAY->SetBlendModeNormal(); + if( bDrawGlowOnly ) + DISPLAY->SetTextureModeGlow(); + else + DISPLAY->SetTextureModeModulate(); + DISPLAY->DisableTextureWrapping(); + + const float fFrameWidth = pSprTopCap->GetUnzoomedWidth(); + const float fFrameHeight = pSprTopCap->GetUnzoomedHeight(); + const float fYCapTop = fYHead+cache->m_iStartDrawingHoldBodyOffsetFromHead-fFrameHeight; + const float fYCapBottom = fYHead+cache->m_iStartDrawingHoldBodyOffsetFromHead; + + for( float fY=fYCapTop; fYtop, pRect->bottom ); + const float fTexCoordBottom = SCALE( fBottomDistFromHeadTop, 0, fFrameHeight, pRect->top, pRect->bottom ); + ASSERT( fTexCoordTop>=-0.0001 && fTexCoordBottom<=1.0001 ); /* allow for rounding error */ + const float fTexCoordLeft = pRect->left; + const float fTexCoordRight = pRect->right; + const float fAlphaTop = ArrowGetAlpha( m_PlayerNumber, fYTop, fPercentFadeToFail ); + const float fAlphaBottom = ArrowGetAlpha( m_PlayerNumber, fYBottom, fPercentFadeToFail ); + const float fGlowTop = ArrowGetGlow( m_PlayerNumber, fYTop, fPercentFadeToFail ); + const float fGlowBottom = ArrowGetGlow( m_PlayerNumber, fYBottom, fPercentFadeToFail ); + const RageColor colorDiffuseTop = RageColor(fColorScale,fColorScale,fColorScale,fAlphaTop); + const RageColor colorDiffuseBottom = RageColor(fColorScale,fColorScale,fColorScale,fAlphaBottom); + const RageColor colorGlowTop = RageColor(1,1,1,fGlowTop); + const RageColor colorGlowBottom = RageColor(1,1,1,fGlowBottom); + + if( bDrawGlowOnly && colorGlowTop.a==0 && colorGlowBottom.a==0 ) + continue; + if( !bDrawGlowOnly && colorDiffuseTop.a==0 && colorDiffuseBottom.a==0 ) + continue; + + v[0].p = RageVector3(fXTopLeft, fYTop, 0); v[0].c = bDrawGlowOnly ? colorGlowTop : colorDiffuseTop; v[0].t = RageVector2(fTexCoordLeft, fTexCoordTop), + v[1].p = RageVector3(fXTopRight, fYTop, 0); v[1].c = bDrawGlowOnly ? colorGlowTop : colorDiffuseTop; v[1].t = RageVector2(fTexCoordRight, fTexCoordTop); + v[2].p = RageVector3(fXBottomRight,fYBottom,0); v[2].c = bDrawGlowOnly ? colorGlowBottom : colorDiffuseBottom; v[2].t = RageVector2(fTexCoordRight, fTexCoordBottom); + v[3].p = RageVector3(fXBottomLeft, fYBottom,0); v[3].c = bDrawGlowOnly ? colorGlowBottom : colorDiffuseBottom; v[3].t = RageVector2(fTexCoordLeft, fTexCoordBottom); + v+=4; + } + DISPLAY->DrawQuads( queue, v-queue ); + } + + // + // Draw the tail + // + { + Sprite* pSprTail = GetHoldTailSprite( hn.m_fStartBeat, bActive ); + + const float fY = fYTail; + const float fX = ArrowGetXPos( m_PlayerNumber, iCol, fY ); + const float fAlpha = ArrowGetAlpha( m_PlayerNumber, fY, fPercentFadeToFail ); + const float fGlow = ArrowGetGlow( m_PlayerNumber, fY, fPercentFadeToFail ); + const RageColor colorDiffuse= RageColor(fColorScale,fColorScale,fColorScale,fAlpha); + const RageColor colorGlow = RageColor(1,1,1,fGlow); + + pSprTail->SetXY( fX, fY ); + if( bDrawGlowOnly ) + { + pSprTail->SetDiffuse( RageColor(1,1,1,0) ); + pSprTail->SetGlow( colorGlow ); + } + else + { + pSprTail->SetDiffuse( colorDiffuse ); + pSprTail->SetGlow( RageColor(0,0,0,0) ); + } + pSprTail->Draw(); + } // // Draw the head // { - Sprite* pSprHead; - int iFrameNo; - GetHoldHeadSpriteAndFrameNo( hn.m_fStartBeat, bActive, pSprHead, iFrameNo ); + Sprite* pSprHead = GetHoldHeadSprite( hn.m_fStartBeat, bActive ); - if( g_bHoldHeadIsWavy ) + // draw with normal Sprite + const float fY = fYHead; + const float fX = ArrowGetXPos( m_PlayerNumber, iCol, fY ); + const float fAlpha = ArrowGetAlpha( m_PlayerNumber, fY, fPercentFadeToFail ); + const float fGlow = ArrowGetGlow( m_PlayerNumber, fY, fPercentFadeToFail ); + const RageColor colorDiffuse= RageColor(fColorScale,fColorScale,fColorScale,fAlpha); + const RageColor colorGlow = RageColor(1,1,1,fGlow); + + pSprHead->SetXY( fX, fY ); + if( bDrawGlowOnly ) { - // draw manually in small segments - RageVertex *v = &queue[0]; - RageTexture* pTexture = pSprHead->GetTexture(); - const RectF* pRect = pTexture->GetTextureCoordRect( iFrameNo ); - DISPLAY->SetTexture( pTexture ); - DISPLAY->SetBlendModeNormal(); - if( bDrawGlowOnly ) - DISPLAY->SetTextureModeGlow(); - else - DISPLAY->SetTextureModeModulate(); - DISPLAY->EnableTextureWrapping(); - - const float fFrameWidth = pSprHead->GetUnzoomedWidth(); - const float fFrameHeight = pSprHead->GetUnzoomedHeight(); - const float fYHeadTop = fYHead-fFrameHeight/2; - const float fYHeadBottom = fYHead+fFrameHeight/2; - - for( float fY=fYHeadTop; fYtop, pRect->bottom ); - const float fTexCoordBottom = SCALE( fBottomDistFromHeadTop, 0, fFrameHeight, pRect->top, pRect->bottom ); - ASSERT( fTexCoordTop>=0 && fTexCoordBottom<=1 ); - const float fTexCoordLeft = pRect->left; - const float fTexCoordRight = pRect->right; - const float fAlphaTop = ArrowGetAlpha( m_PlayerNumber, fYTop, fPercentFadeToFail ); - const float fAlphaBottom = ArrowGetAlpha( m_PlayerNumber, fYBottom, fPercentFadeToFail ); - const float fGlowTop = ArrowGetGlow( m_PlayerNumber, fYTop, fPercentFadeToFail ); - const float fGlowBottom = ArrowGetGlow( m_PlayerNumber, fYBottom, fPercentFadeToFail ); - const RageColor colorDiffuseTop = RageColor(fColorScale,fColorScale,fColorScale,fAlphaTop); - const RageColor colorDiffuseBottom = RageColor(fColorScale,fColorScale,fColorScale,fAlphaBottom); - const RageColor colorGlowTop = RageColor(1,1,1,fGlowTop); - const RageColor colorGlowBottom = RageColor(1,1,1,fGlowBottom); - - if( bDrawGlowOnly && colorGlowTop.a==0 && colorGlowBottom.a==0 ) - continue; - if( !bDrawGlowOnly && colorDiffuseTop.a==0 && colorDiffuseBottom.a==0 ) - continue; - - v[0].p = RageVector3(fXTopLeft, fYTop, 0); v[0].c = bDrawGlowOnly ? colorGlowTop : colorDiffuseTop; v[0].t = RageVector2(fTexCoordLeft, fTexCoordTop), - v[1].p = RageVector3(fXTopRight, fYTop, 0); v[1].c = bDrawGlowOnly ? colorGlowTop : colorDiffuseTop; v[1].t = RageVector2(fTexCoordRight, fTexCoordTop); - v[2].p = RageVector3(fXBottomRight,fYBottom,0); v[2].c = bDrawGlowOnly ? colorGlowBottom : colorDiffuseBottom; v[2].t = RageVector2(fTexCoordRight, fTexCoordBottom); - v[3].p = RageVector3(fXBottomLeft, fYBottom,0); v[3].c = bDrawGlowOnly ? colorGlowBottom : colorDiffuseBottom; v[3].t = RageVector2(fTexCoordLeft, fTexCoordBottom); - v+=4; - } - DISPLAY->DrawQuads( queue, v-queue ); + pSprHead->SetDiffuse( RageColor(1,1,1,0) ); + pSprHead->SetGlow( colorGlow ); } - else // !g_bHoldHeadIsWavy + else { - // draw with normal Sprite - const float fY = fYHead; - const float fX = ArrowGetXPos( m_PlayerNumber, iCol, fY ); - const float fAlpha = ArrowGetAlpha( m_PlayerNumber, fY, fPercentFadeToFail ); - const float fGlow = ArrowGetGlow( m_PlayerNumber, fY, fPercentFadeToFail ); - const RageColor colorDiffuse= RageColor(fColorScale,fColorScale,fColorScale,fAlpha); - const RageColor colorGlow = RageColor(1,1,1,fGlow); - - pSprHead->SetXY( fX, fY ); - pSprHead->SetState( iFrameNo ); - if( bDrawGlowOnly ) - { - pSprHead->SetDiffuse( RageColor(1,1,1,0) ); - pSprHead->SetGlow( colorGlow ); - } - else - { - pSprHead->SetDiffuse( colorDiffuse ); - pSprHead->SetGlow( RageColor(0,0,0,0) ); - } - pSprHead->Draw(); + pSprHead->SetDiffuse( colorDiffuse ); + pSprHead->SetGlow( RageColor(0,0,0,0) ); } + pSprHead->Draw(); } - // now, draw the glow pass if( !bDrawGlowOnly ) DrawHold( hn, bActive, fLife, fPercentFadeToFail, true ); @@ -573,34 +666,24 @@ void NoteDisplay::DrawTap( const int iCol, const float fBeat, const bool bOnSame } */ - if( bOnSameRowAsHoldStart && g_bDrawHoldHeadForTapsOnSameRow ) + Sprite* pSprite; + if( bOnSameRowAsHoldStart && cache->m_bDrawHoldHeadForTapsOnSameRow ) { // draw hold head - Sprite* pSprHead; - int iFrameNo; - GetHoldHeadSpriteAndFrameNo( fBeat, false, pSprHead, iFrameNo ); - - pSprHead->SetXY( fXPos, fYPos ); - pSprHead->SetDiffuse( diffuse ); - pSprHead->SetGlow( glow ); - pSprHead->StopUsingCustomCoords(); - pSprHead->SetState( iFrameNo ); - pSprHead->Draw(); + pSprite = GetHoldHeadSprite( fBeat, false ); + pSprite->StopUsingCustomCoords(); } else { // draw tap - Sprite* pSprTap; - int iFrameNo; - GetTapNoteSpriteAndFrameNo( fBeat, pSprTap, iFrameNo ); - - pSprTap->SetXY( fXPos, fYPos ); - pSprTap->SetRotation( fRotation ); - pSprTap->SetGlow( glow ); - pSprTap->SetDiffuse( diffuse ); - pSprTap->SetState( iFrameNo ); - pSprTap->Draw(); + pSprite = GetTapNoteSprite( fBeat ); + pSprite->SetRotation( fRotation ); } + + pSprite->SetXY( fXPos, fYPos ); + pSprite->SetDiffuse( diffuse ); + pSprite->SetGlow( glow ); + pSprite->Draw(); } diff --git a/stepmania/src/NoteDisplay.h b/stepmania/src/NoteDisplay.h index b8a186f514..5d8a60a85f 100644 --- a/stepmania/src/NoteDisplay.h +++ b/stepmania/src/NoteDisplay.h @@ -17,10 +17,13 @@ #include "NoteTypes.h" +struct NoteMetricCache_t; + class NoteDisplay { public: NoteDisplay(); + ~NoteDisplay(); void Load( int iColNum, PlayerNumber pn ); @@ -28,21 +31,29 @@ public: void DrawHold( const HoldNote& hn, const bool bActive, const float fLife, const float fPercentFadeToFail, bool bDrawGlowOnly = false ); protected: - int GetFrameNo( float fNoteBeat, int iNumFrames, float fAnimationLengthInBeats, bool bVivid, bool bNoteColor ); - void GetTapNoteSpriteAndFrameNo( float fNoteBeat, Sprite*& pSpriteOut, int& iFrameNoOut ); - void GetHoldHeadSpriteAndFrameNo( float fNoteBeat, bool bActive, Sprite*& pSpriteOut, int& iFrameNoOut ); - void GetHoldBodySpriteAndFrameNo( float fNoteBeat, bool bActive, Sprite*& pSpriteOut, int& iFrameNoOut ); - void GetHoldTailSpriteAndFrameNo( float fNoteBeat, bool bActive, Sprite*& pSpriteOut, int& iFrameNoOut ); + void SetActiveFrame( float fNoteBeat, Sprite &Spr, float fAnimationLengthInBeats, bool bVivid, bool bNoteColor ); + Sprite *GetTapNoteSprite( float fNoteBeat ); + Sprite *GetHoldHeadSprite( float fNoteBeat, bool bActive ); + Sprite *GetHoldTopCapSprite( float fNoteBeat, bool bActive ); + Sprite *GetHoldBodySprite( float fNoteBeat, bool bActive ); + Sprite *GetHoldBottomCapSprite( float fNoteBeat, bool bActive ); + Sprite *GetHoldTailSprite( float fNoteBeat, bool bActive ); PlayerNumber m_PlayerNumber; // to look up PlayerOptions + struct NoteMetricCache_t *cache; + #define NOTE_COLOR_IMAGES 6 Sprite m_sprTapNote[NOTE_COLOR_IMAGES]; Sprite m_sprHoldHeadActive[NOTE_COLOR_IMAGES]; Sprite m_sprHoldHeadInactive[NOTE_COLOR_IMAGES]; + Sprite m_sprHoldTopCapActive[NOTE_COLOR_IMAGES]; + Sprite m_sprHoldTopCapInactive[NOTE_COLOR_IMAGES]; Sprite m_sprHoldBodyActive[NOTE_COLOR_IMAGES]; Sprite m_sprHoldBodyInactive[NOTE_COLOR_IMAGES]; + Sprite m_sprHoldBottomCapActive[NOTE_COLOR_IMAGES]; + Sprite m_sprHoldBottomCapInactive[NOTE_COLOR_IMAGES]; Sprite m_sprHoldTailActive[NOTE_COLOR_IMAGES]; Sprite m_sprHoldTailInactive[NOTE_COLOR_IMAGES]; }; diff --git a/stepmania/src/NoteSkinManager.cpp b/stepmania/src/NoteSkinManager.cpp index 2939b61700..a2e1ad80df 100644 --- a/stepmania/src/NoteSkinManager.cpp +++ b/stepmania/src/NoteSkinManager.cpp @@ -75,7 +75,11 @@ void NoteSkinManager::SwitchNoteSkin( CString sNewNoteSkin ) CStringArray as; GetNoteSkinNames( as ); ASSERT( !as.empty() ); + + /* Prefer "default" if it exists. */ sNewNoteSkin = as[0]; + for(unsigned i = 0; i < as.size(); ++i) + if(!as[i].CompareNoCase("default")) sNewNoteSkin = "default"; } m_sCurNoteSkinName = sNewNoteSkin; @@ -94,54 +98,61 @@ CString NoteSkinManager::GetNoteSkinDir( CString sSkinName ) return NOTESKINS_DIR + ssprintf("%s/%s/", pGameDef->m_szName, sSkinName.GetString()); } -CString NoteSkinManager::GetMetric( CString sClassName, CString sValue ) // looks in GAMESTATE for the current Style +CString NoteSkinManager::GetMetric( CString sButtonName, CString sValue ) // looks in GAMESTATE for the current Style { CString sReturn; - if( !m_pIniMetrics->GetValue( sClassName, sValue, sReturn ) ) - RageException::Throw( "Could not read metric '%s - %s'", sClassName.GetString(), sValue.GetString() ); + if( m_pIniMetrics->GetValue( sButtonName, sValue, sReturn ) ) + return sReturn; + if( !m_pIniMetrics->GetValue( "NoteDisplay", sValue, sReturn ) ) + RageException::Throw( "Could not read metric '%s - %s' or 'NoteDisplay - %s'", + sButtonName.GetString(), sValue.GetString(), sValue.GetString() ); return sReturn; } -int NoteSkinManager::GetMetricI( CString sClassName, CString sValueName ) +int NoteSkinManager::GetMetricI( CString sButtonName, CString sValueName ) { - return atoi( GetMetric(sClassName,sValueName) ); + return atoi( GetMetric(sButtonName,sValueName) ); } -float NoteSkinManager::GetMetricF( CString sClassName, CString sValueName ) +float NoteSkinManager::GetMetricF( CString sButtonName, CString sValueName ) { - return (float)atof( GetMetric(sClassName,sValueName) ); + return (float)atof( GetMetric(sButtonName,sValueName) ); } -bool NoteSkinManager::GetMetricB( CString sClassName, CString sValueName ) +bool NoteSkinManager::GetMetricB( CString sButtonName, CString sValueName ) { - return atoi( GetMetric(sClassName,sValueName) ) != 0; + return atoi( GetMetric(sButtonName,sValueName) ) != 0; } -RageColor NoteSkinManager::GetMetricC( CString sClassName, CString sValueName ) +RageColor NoteSkinManager::GetMetricC( CString sButtonName, CString sValueName ) { float r=1,b=1,g=1,a=1; // initialize in case sscanf fails - CString sValue = GetMetric(sClassName,sValueName); + CString sValue = GetMetric(sButtonName,sValueName); char szValue[40]; strncpy( szValue, sValue, 39 ); int result = sscanf( szValue, "%f,%f,%f,%f", &r, &g, &b, &a ); if( result != 4 ) { - LOG->Warn( "The color value '%s' for theme metric '%s : %s' is invalid.", szValue, sClassName.GetString(), sValueName.GetString() ); + LOG->Warn( "The color value '%s' for theme metric '%s : %s' is invalid.", szValue, sButtonName.GetString(), sValueName.GetString() ); ASSERT(0); } return RageColor(r,g,b,a); } -CString NoteSkinManager::GetPathTo( int col, CString sFileName ) // looks in GAMESTATE for the current Style +CString NoteSkinManager::ColToButtonName(int col) { const StyleDef* pStyleDef = GAMESTATE->GetCurrentStyleDef(); const GameDef* pGameDef = GAMESTATE->GetCurrentGameDef(); StyleInput SI( PLAYER_1, col ); GameInput GI = pStyleDef->StyleInputToGameInput( SI ); - CString sButtonName = pGameDef->m_szButtonNames[GI.button]; + return pGameDef->m_szButtonNames[GI.button]; +} +CString NoteSkinManager::GetPathTo( int col, CString sFileName ) // looks in GAMESTATE for the current Style +{ + CString sButtonName = ColToButtonName(col); CString sCurNoteSkinName = m_sCurNoteSkinName; if( GAMESTATE->m_bEditing ) diff --git a/stepmania/src/NoteSkinManager.h b/stepmania/src/NoteSkinManager.h index 3f27254082..4cb4f8b8b6 100644 --- a/stepmania/src/NoteSkinManager.h +++ b/stepmania/src/NoteSkinManager.h @@ -31,11 +31,13 @@ public: CString GetPathTo( int col, CString sFileName ); - CString GetMetric( CString sClassName, CString sValueName ); - int GetMetricI( CString sClassName, CString sValueName ); - float GetMetricF( CString sClassName, CString sValueName ); - bool GetMetricB( CString sClassName, CString sValueName ); - RageColor GetMetricC( CString sClassName, CString sValueName ); + CString GetMetric( CString sButtonName, CString sValueName ); + int GetMetricI( CString sButtonName, CString sValueName ); + float GetMetricF( CString sButtonName, CString sValueName ); + bool GetMetricB( CString sButtonName, CString sValueName ); + RageColor GetMetricC( CString sButtonName, CString sValueName ); + + static CString NoteSkinManager::ColToButtonName(int col); protected: CString GetPathTo( CString sSkinName, CString sButtonName, CString sFileName );