2003-02-16 04:01:45 +00:00
|
|
|
#include "global.h"
|
2002-08-13 23:26:46 +00:00
|
|
|
#include "NoteDisplay.h"
|
|
|
|
|
#include "GameState.h"
|
2003-02-06 07:32:57 +00:00
|
|
|
#include "NoteSkinManager.h"
|
2002-08-13 23:26:46 +00:00
|
|
|
#include "ArrowEffects.h"
|
|
|
|
|
#include "RageLog.h"
|
2002-11-11 04:53:31 +00:00
|
|
|
#include "RageDisplay.h"
|
2003-02-05 03:53:57 +00:00
|
|
|
#include "NoteTypes.h"
|
2003-04-17 21:45:37 +00:00
|
|
|
#include "NoteFieldPositioning.h"
|
2003-09-21 20:57:07 +00:00
|
|
|
#include "ActorUtil.h"
|
2004-09-06 02:49:36 +00:00
|
|
|
#include "Game.h"
|
2004-12-20 06:25:59 +00:00
|
|
|
#include "PlayerState.h"
|
2005-07-06 04:20:27 +00:00
|
|
|
#include "LuaBinding.h"
|
2003-02-05 03:53:57 +00:00
|
|
|
|
2005-10-04 19:45:45 +00:00
|
|
|
const CString& NoteNotePartToString( NotePart i );
|
|
|
|
|
#define FOREACH_NotePart( i ) FOREACH_ENUM( NotePart, NUM_NotePart, i )
|
2005-04-24 05:44:42 +00:00
|
|
|
|
2005-10-04 19:45:45 +00:00
|
|
|
static const CString NotePartNames[] = {
|
2005-04-24 05:44:42 +00:00
|
|
|
"TapNote",
|
|
|
|
|
"TapAddition",
|
|
|
|
|
"TapMine",
|
|
|
|
|
"HoldHead",
|
|
|
|
|
"HoldTopCap",
|
|
|
|
|
"HoldBody",
|
|
|
|
|
"HoldBottomCap",
|
|
|
|
|
"HoldTail",
|
|
|
|
|
};
|
2005-10-04 19:45:45 +00:00
|
|
|
XToString( NotePart, NUM_NotePart );
|
2004-04-16 05:21:25 +00:00
|
|
|
|
2005-10-04 19:45:45 +00:00
|
|
|
static const RageVector2 g_emptyVector = RageVector2( 0, 0 );
|
2004-04-16 05:21:25 +00:00
|
|
|
|
2003-01-13 08:31:34 +00:00
|
|
|
// cache
|
2004-04-16 04:17:26 +00:00
|
|
|
struct NoteMetricCache_t
|
|
|
|
|
{
|
2003-02-08 23:47:47 +00:00
|
|
|
bool m_bDrawHoldHeadForTapsOnSameRow;
|
2005-10-04 19:45:45 +00:00
|
|
|
float m_fAnimationLengthInBeats[NUM_NotePart];
|
|
|
|
|
bool m_bAnimationIsVivid[NUM_NotePart];
|
|
|
|
|
RageVector2 m_fNoteColorTextureCoordSpacing[NUM_NotePart];
|
2004-04-16 05:21:25 +00:00
|
|
|
|
2003-07-17 07:37:56 +00:00
|
|
|
bool m_bHoldHeadIsAboveWavyParts;
|
|
|
|
|
bool m_bHoldTailIsAboveWavyParts;
|
2003-02-08 23:47:47 +00:00
|
|
|
int m_iStartDrawingHoldBodyOffsetFromHead;
|
|
|
|
|
int m_iStopDrawingHoldBodyOffsetFromTail;
|
|
|
|
|
float m_fHoldNGGrayPercent;
|
2003-12-31 08:15:34 +00:00
|
|
|
bool m_bTapNoteUseLighting;
|
|
|
|
|
bool m_bTapAdditionUseLighting;
|
|
|
|
|
bool m_bTapMineUseLighting;
|
|
|
|
|
bool m_bHoldHeadUseLighting;
|
|
|
|
|
bool m_bHoldTailUseLighting;
|
2003-10-14 04:41:24 +00:00
|
|
|
bool m_bFlipHeadAndTailWhenReverse;
|
2003-02-08 23:47:47 +00:00
|
|
|
|
2005-04-18 01:19:56 +00:00
|
|
|
void Load( const CString &sButton );
|
2003-02-08 23:47:47 +00:00
|
|
|
} *NoteMetricCache;
|
|
|
|
|
|
2005-04-18 01:19:56 +00:00
|
|
|
void NoteMetricCache_t::Load( const CString &sButton )
|
2003-02-08 23:47:47 +00:00
|
|
|
{
|
2005-04-24 05:44:42 +00:00
|
|
|
m_bDrawHoldHeadForTapsOnSameRow = NOTESKIN->GetMetricB(sButton,"DrawHoldHeadForTapsOnSameRow");
|
2005-10-04 19:45:45 +00:00
|
|
|
FOREACH_NotePart( p )
|
|
|
|
|
{
|
|
|
|
|
const CString s = NotePartToString(p);
|
|
|
|
|
m_fAnimationLengthInBeats[p] = NOTESKIN->GetMetricF(sButton,s+"AnimationLengthInBeats");
|
|
|
|
|
m_bAnimationIsVivid[p] = NOTESKIN->GetMetricB(sButton,s+"AnimationIsVivid");
|
|
|
|
|
m_fNoteColorTextureCoordSpacing[p].x = NOTESKIN->GetMetricF(sButton,s+"NoteColorTextureCoordSpacingX");
|
|
|
|
|
m_fNoteColorTextureCoordSpacing[p].y = NOTESKIN->GetMetricF(sButton,s+"NoteColorTextureCoordSpacingY");
|
|
|
|
|
}
|
2005-04-24 05:44:42 +00:00
|
|
|
m_bHoldHeadIsAboveWavyParts = NOTESKIN->GetMetricB(sButton,"HoldHeadIsAboveWavyParts");
|
|
|
|
|
m_bHoldTailIsAboveWavyParts = NOTESKIN->GetMetricB(sButton,"HoldTailIsAboveWavyParts");
|
|
|
|
|
m_iStartDrawingHoldBodyOffsetFromHead = NOTESKIN->GetMetricI(sButton,"StartDrawingHoldBodyOffsetFromHead");
|
|
|
|
|
m_iStopDrawingHoldBodyOffsetFromTail = NOTESKIN->GetMetricI(sButton,"StopDrawingHoldBodyOffsetFromTail");
|
|
|
|
|
m_fHoldNGGrayPercent = NOTESKIN->GetMetricF(sButton,"HoldNGGrayPercent");
|
|
|
|
|
m_bTapNoteUseLighting = NOTESKIN->GetMetricB(sButton,"TapNoteUseLighting");
|
|
|
|
|
m_bTapAdditionUseLighting = NOTESKIN->GetMetricB(sButton,"TapAdditionUseLighting");
|
|
|
|
|
m_bTapMineUseLighting = NOTESKIN->GetMetricB(sButton,"TapMineUseLighting");
|
|
|
|
|
m_bHoldHeadUseLighting = NOTESKIN->GetMetricB(sButton,"HoldHeadUseLighting");
|
|
|
|
|
m_bHoldTailUseLighting = NOTESKIN->GetMetricB(sButton,"HoldTailUseLighting");
|
|
|
|
|
m_bFlipHeadAndTailWhenReverse = NOTESKIN->GetMetricB(sButton,"FlipHeadAndTailWhenReverse");
|
2003-09-12 02:44:14 +00:00
|
|
|
}
|
|
|
|
|
|
2004-08-21 00:34:24 +00:00
|
|
|
|
2005-04-18 01:19:56 +00:00
|
|
|
struct NoteSkinAndPath
|
|
|
|
|
{
|
|
|
|
|
NoteSkinAndPath( const CString sNoteSkin_, const CString sPath_ ) { sNoteSkin = sNoteSkin_; sPath = sPath_; }
|
|
|
|
|
CString sNoteSkin;
|
|
|
|
|
CString sPath;
|
|
|
|
|
bool operator<( const NoteSkinAndPath &other ) const
|
|
|
|
|
{
|
2005-04-23 11:06:28 +00:00
|
|
|
int cmp = strcmp(sNoteSkin, other.sNoteSkin);
|
|
|
|
|
if( cmp < 0 )
|
|
|
|
|
return true;
|
|
|
|
|
else if( cmp == 0 )
|
|
|
|
|
return sPath < other.sPath;
|
|
|
|
|
else
|
|
|
|
|
return false;
|
2005-04-18 01:19:56 +00:00
|
|
|
}
|
|
|
|
|
};
|
|
|
|
|
|
2004-08-21 00:34:24 +00:00
|
|
|
struct NoteResource
|
|
|
|
|
{
|
2005-04-18 01:19:56 +00:00
|
|
|
NoteResource( const NoteSkinAndPath &nsap ): m_nsap(nsap)
|
2004-08-21 00:34:24 +00:00
|
|
|
{
|
|
|
|
|
m_iRefCount = 0;
|
|
|
|
|
m_pActor = NULL;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
~NoteResource()
|
|
|
|
|
{
|
|
|
|
|
delete m_pActor;
|
|
|
|
|
}
|
|
|
|
|
|
2005-04-18 01:19:56 +00:00
|
|
|
const NoteSkinAndPath m_nsap; /* should be refcounted along with g_NoteResource[] */
|
2004-08-21 00:34:24 +00:00
|
|
|
int m_iRefCount;
|
|
|
|
|
Actor *m_pActor;
|
|
|
|
|
};
|
|
|
|
|
|
2005-04-18 01:19:56 +00:00
|
|
|
static map<NoteSkinAndPath, NoteResource *> g_NoteResource;
|
2004-08-21 00:34:24 +00:00
|
|
|
|
2005-10-04 19:45:45 +00:00
|
|
|
static NoteResource *MakeNoteResource( const CString &sButton, const CString &sElement, bool bSpriteOnly )
|
2004-08-21 00:34:24 +00:00
|
|
|
{
|
2005-10-04 19:45:45 +00:00
|
|
|
CString sElementAndType = sElement;
|
2005-07-05 08:45:51 +00:00
|
|
|
NoteSkinAndPath nsap( NOTESKIN->GetCurrentNoteSkin(), NOTESKIN->GetPath(sButton, sElementAndType) );
|
|
|
|
|
|
2005-04-18 01:19:56 +00:00
|
|
|
map<NoteSkinAndPath, NoteResource *>::iterator it = g_NoteResource.find( nsap );
|
2004-08-21 00:34:24 +00:00
|
|
|
if( it == g_NoteResource.end() )
|
|
|
|
|
{
|
2005-04-18 01:19:56 +00:00
|
|
|
NoteResource *pRes = new NoteResource( nsap );
|
2005-07-06 04:20:27 +00:00
|
|
|
|
|
|
|
|
pRes->m_pActor = ActorUtil::MakeActor( nsap.sPath );
|
|
|
|
|
ASSERT( pRes->m_pActor );
|
|
|
|
|
|
|
|
|
|
/* Make sure pActor is a Sprite (or something derived from Sprite). */
|
2004-08-21 00:34:24 +00:00
|
|
|
if( bSpriteOnly )
|
|
|
|
|
{
|
2005-07-06 04:20:27 +00:00
|
|
|
Lua *L = LUA->Get();
|
|
|
|
|
pRes->m_pActor->PushSelf( L );
|
|
|
|
|
Luna<Sprite>::check( L, lua_gettop(L) );
|
|
|
|
|
lua_pop( L, 1 );
|
|
|
|
|
LUA->Release( L );
|
2005-01-17 04:08:08 +00:00
|
|
|
}
|
2004-08-21 00:34:24 +00:00
|
|
|
|
2005-04-18 01:19:56 +00:00
|
|
|
g_NoteResource[nsap] = pRes;
|
|
|
|
|
it = g_NoteResource.find( nsap );
|
2004-08-21 00:34:24 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
NoteResource *pRet = it->second;
|
|
|
|
|
++pRet->m_iRefCount;
|
|
|
|
|
return pRet;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static NoteResource *FindNoteResource( const Actor *pActor )
|
|
|
|
|
{
|
2005-04-18 01:19:56 +00:00
|
|
|
map<NoteSkinAndPath, NoteResource *>::iterator it;
|
2004-08-21 00:34:24 +00:00
|
|
|
for( it = g_NoteResource.begin(); it != g_NoteResource.end(); ++it )
|
|
|
|
|
{
|
|
|
|
|
NoteResource *pRes = it->second;
|
|
|
|
|
if( pRes->m_pActor == pActor )
|
|
|
|
|
return pRes;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return NULL;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void DeleteNoteResource( const Actor *pActor )
|
|
|
|
|
{
|
|
|
|
|
if( pActor == NULL )
|
|
|
|
|
return;
|
|
|
|
|
|
|
|
|
|
NoteResource *pRes = FindNoteResource( pActor );
|
|
|
|
|
ASSERT( pRes != NULL );
|
|
|
|
|
|
|
|
|
|
ASSERT_M( pRes->m_iRefCount > 0, ssprintf("%i", pRes->m_iRefCount) );
|
|
|
|
|
--pRes->m_iRefCount;
|
|
|
|
|
if( pRes->m_iRefCount )
|
|
|
|
|
return;
|
|
|
|
|
|
2005-04-18 01:19:56 +00:00
|
|
|
g_NoteResource.erase( pRes->m_nsap );
|
2004-08-21 00:34:24 +00:00
|
|
|
delete pRes;
|
|
|
|
|
}
|
|
|
|
|
|
2005-10-04 19:45:45 +00:00
|
|
|
Actor *MakeRefcountedActor( const CString &sButton, const CString &sElement )
|
2004-08-21 00:34:24 +00:00
|
|
|
{
|
2005-10-04 19:45:45 +00:00
|
|
|
NoteResource *pRes = MakeNoteResource( sButton, sElement, false );
|
2004-08-21 00:34:24 +00:00
|
|
|
return pRes->m_pActor;
|
|
|
|
|
}
|
|
|
|
|
|
2005-10-04 19:45:45 +00:00
|
|
|
Sprite *MakeRefcountedSprite( const CString &sButton, const CString &sElement )
|
2004-08-21 00:34:24 +00:00
|
|
|
{
|
2005-10-04 19:45:45 +00:00
|
|
|
NoteResource *pRes = MakeNoteResource( sButton, sElement, true );
|
2004-08-21 00:34:24 +00:00
|
|
|
return (Sprite *) pRes->m_pActor; /* XXX ick */
|
|
|
|
|
}
|
|
|
|
|
|
2005-04-17 00:39:09 +00:00
|
|
|
NoteColorActor::NoteColorActor()
|
2003-09-12 02:44:14 +00:00
|
|
|
{
|
2005-10-05 05:00:50 +00:00
|
|
|
m_p = NULL;
|
2003-09-12 02:44:14 +00:00
|
|
|
}
|
|
|
|
|
|
2005-04-17 00:39:09 +00:00
|
|
|
NoteColorActor::~NoteColorActor()
|
2003-09-12 02:44:14 +00:00
|
|
|
{
|
2005-10-05 05:00:50 +00:00
|
|
|
if( m_p )
|
|
|
|
|
DeleteNoteResource( m_p );
|
2005-04-17 00:39:09 +00:00
|
|
|
}
|
|
|
|
|
|
2005-10-04 19:45:45 +00:00
|
|
|
void NoteColorActor::Load( const CString &sButton, const CString &sElement )
|
2005-04-17 00:39:09 +00:00
|
|
|
{
|
2005-10-05 05:00:50 +00:00
|
|
|
m_p = MakeRefcountedActor( sButton, sElement );
|
2005-04-17 00:39:09 +00:00
|
|
|
}
|
2003-09-12 02:44:14 +00:00
|
|
|
|
2003-02-08 23:47:47 +00:00
|
|
|
|
2005-04-17 00:39:09 +00:00
|
|
|
NoteColorSprite::NoteColorSprite()
|
|
|
|
|
{
|
2005-10-05 05:00:50 +00:00
|
|
|
m_p = NULL;
|
2005-04-17 00:39:09 +00:00
|
|
|
}
|
2002-08-13 23:26:46 +00:00
|
|
|
|
2005-04-17 00:39:09 +00:00
|
|
|
NoteColorSprite::~NoteColorSprite()
|
|
|
|
|
{
|
2005-10-05 05:00:50 +00:00
|
|
|
if( m_p )
|
|
|
|
|
DeleteNoteResource( m_p );
|
2005-04-17 00:39:09 +00:00
|
|
|
}
|
2002-08-13 23:26:46 +00:00
|
|
|
|
2005-10-04 19:45:45 +00:00
|
|
|
void NoteColorSprite::Load( const CString &sButton, const CString &sElement )
|
2005-04-17 00:39:09 +00:00
|
|
|
{
|
2005-10-05 05:00:50 +00:00
|
|
|
m_p = MakeRefcountedSprite( sButton, sElement );
|
2005-04-17 00:39:09 +00:00
|
|
|
}
|
2003-08-10 10:12:50 +00:00
|
|
|
|
2003-02-06 07:32:57 +00:00
|
|
|
|
2005-05-05 19:55:04 +00:00
|
|
|
static const CString HoldTypeNames[] = {
|
2005-04-18 01:19:56 +00:00
|
|
|
"hold",
|
|
|
|
|
"roll",
|
|
|
|
|
};
|
|
|
|
|
XToString( HoldType, NUM_HOLD_TYPES );
|
|
|
|
|
|
2005-05-05 19:55:04 +00:00
|
|
|
static const CString ActiveTypeNames[] = {
|
2005-04-18 01:19:56 +00:00
|
|
|
"active",
|
|
|
|
|
"inactive",
|
|
|
|
|
};
|
|
|
|
|
XToString( ActiveType, NUM_ACTIVE_TYPES );
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
2005-04-17 00:39:09 +00:00
|
|
|
NoteDisplay::NoteDisplay()
|
|
|
|
|
{
|
|
|
|
|
cache = new NoteMetricCache_t;
|
|
|
|
|
}
|
2003-02-08 23:47:47 +00:00
|
|
|
|
2005-04-17 00:39:09 +00:00
|
|
|
NoteDisplay::~NoteDisplay()
|
|
|
|
|
{
|
|
|
|
|
delete cache;
|
|
|
|
|
}
|
2003-02-05 03:53:57 +00:00
|
|
|
|
2005-04-18 01:19:56 +00:00
|
|
|
void NoteDisplay::Load( int iColNum, const PlayerState* pPlayerState, float fYReverseOffsetPixels )
|
2005-04-17 00:39:09 +00:00
|
|
|
{
|
|
|
|
|
m_pPlayerState = pPlayerState;
|
|
|
|
|
m_fYReverseOffsetPixels = fYReverseOffsetPixels;
|
2003-02-08 23:47:47 +00:00
|
|
|
|
2005-04-18 01:19:56 +00:00
|
|
|
const CString &sButton = GAMESTATE->GetCurrentGame()->ColToButtonName( iColNum );
|
|
|
|
|
|
|
|
|
|
cache->Load( sButton );
|
|
|
|
|
|
2005-10-04 19:45:45 +00:00
|
|
|
m_TapNote.Load( sButton, "tap note" );
|
|
|
|
|
m_TapAddition.Load( sButton, "tap addition" );
|
|
|
|
|
m_TapMine.Load( sButton, "tap mine" );
|
2005-04-18 01:19:56 +00:00
|
|
|
|
|
|
|
|
FOREACH_HoldType( ht )
|
|
|
|
|
{
|
|
|
|
|
FOREACH_ActiveType( at )
|
|
|
|
|
{
|
2005-10-04 19:45:45 +00:00
|
|
|
m_HoldHead[ht][at].Load( sButton, HoldTypeToString(ht)+" head "+ActiveTypeToString(at) );
|
|
|
|
|
m_HoldTopCap[ht][at].Load( sButton, HoldTypeToString(ht)+" topcap "+ActiveTypeToString(at) );
|
|
|
|
|
m_HoldBody[ht][at].Load( sButton, HoldTypeToString(ht)+" body "+ActiveTypeToString(at) );
|
|
|
|
|
m_HoldBottomCap[ht][at].Load( sButton, HoldTypeToString(ht)+" bottomcap "+ActiveTypeToString(at) );
|
|
|
|
|
m_HoldTail[ht][at].Load( sButton, HoldTypeToString(ht)+" tail "+ActiveTypeToString(at) );
|
2005-04-18 01:19:56 +00:00
|
|
|
}
|
|
|
|
|
}
|
2003-02-06 07:32:57 +00:00
|
|
|
}
|
|
|
|
|
|
2005-01-22 05:00:33 +00:00
|
|
|
bool NoteDisplay::DrawHoldHeadForTapsOnSameRow() const
|
|
|
|
|
{
|
|
|
|
|
return cache->m_bDrawHoldHeadForTapsOnSameRow;
|
|
|
|
|
}
|
|
|
|
|
|
2004-03-01 05:58:19 +00:00
|
|
|
void NoteDisplay::Update( float fDeltaTime )
|
|
|
|
|
{
|
2004-08-21 00:34:24 +00:00
|
|
|
/* This function is static: it's called once per game loop, not once per
|
|
|
|
|
* NoteDisplay. Update each cached item exactly once. */
|
2005-04-18 01:19:56 +00:00
|
|
|
map<NoteSkinAndPath, NoteResource *>::iterator it;
|
2004-08-21 00:34:24 +00:00
|
|
|
for( it = g_NoteResource.begin(); it != g_NoteResource.end(); ++it )
|
|
|
|
|
{
|
|
|
|
|
NoteResource *pRes = it->second;
|
|
|
|
|
pRes->m_pActor->Update( fDeltaTime );
|
|
|
|
|
}
|
2004-03-01 05:58:19 +00:00
|
|
|
}
|
2003-02-06 07:32:57 +00:00
|
|
|
|
2005-10-04 19:45:45 +00:00
|
|
|
void NoteDisplay::SetActiveFrame( float fNoteBeat, Actor &actorToSet, float fAnimationLengthInBeats, bool bVivid )
|
2003-02-06 07:32:57 +00:00
|
|
|
{
|
2005-03-12 06:09:43 +00:00
|
|
|
/* -inf ... inf */
|
2003-02-06 07:32:57 +00:00
|
|
|
float fSongBeat = GAMESTATE->m_fSongBeat;
|
2005-03-12 06:09:43 +00:00
|
|
|
/* -len ... +len */
|
|
|
|
|
float fPercentIntoAnimation = fmodf( fSongBeat, fAnimationLengthInBeats );
|
|
|
|
|
/* -1 ... 1 */
|
|
|
|
|
fPercentIntoAnimation /= fAnimationLengthInBeats;
|
2003-02-06 07:32:57 +00:00
|
|
|
|
|
|
|
|
if( bVivid )
|
2004-03-01 01:37:22 +00:00
|
|
|
{
|
2004-02-21 05:20:39 +00:00
|
|
|
// changed to deal with the minor complaint that the color cycling is
|
|
|
|
|
// one tick off in general
|
2005-03-12 05:02:22 +00:00
|
|
|
const float fNoteBeatFraction = fmodf( fNoteBeat, 1.0f );
|
2004-03-01 01:37:22 +00:00
|
|
|
const float fFraction = fNoteBeatFraction - 0.25f/fAnimationLengthInBeats;
|
|
|
|
|
const float fInterval = 1.f / fAnimationLengthInBeats;
|
2004-10-24 17:44:51 +00:00
|
|
|
fPercentIntoAnimation += Quantize(fFraction,fInterval);
|
2003-02-06 07:32:57 +00:00
|
|
|
|
2005-03-12 06:09:43 +00:00
|
|
|
// just in case somehow we're majorly negative with the subtraction
|
|
|
|
|
wrap( fPercentIntoAnimation, 1.f );
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
/* 0 ... 1, wrapped */
|
|
|
|
|
if( fPercentIntoAnimation < 0 )
|
|
|
|
|
fPercentIntoAnimation += 1.0f;
|
|
|
|
|
}
|
2002-08-13 23:26:46 +00:00
|
|
|
|
2004-08-09 00:46:42 +00:00
|
|
|
float fLengthSeconds = actorToSet.GetAnimationLengthSeconds();
|
|
|
|
|
actorToSet.SetSecondsIntoAnimation( fPercentIntoAnimation*fLengthSeconds );
|
2003-01-13 08:31:34 +00:00
|
|
|
}
|
2002-08-13 23:26:46 +00:00
|
|
|
|
2003-05-09 04:42:04 +00:00
|
|
|
Actor * NoteDisplay::GetTapNoteActor( float fNoteBeat )
|
2003-02-05 03:53:57 +00:00
|
|
|
{
|
2005-10-05 05:00:50 +00:00
|
|
|
Actor *pActorOut = m_TapNote.Get();
|
2003-02-08 23:47:47 +00:00
|
|
|
|
|
|
|
|
SetActiveFrame(
|
|
|
|
|
fNoteBeat,
|
2003-05-09 04:42:04 +00:00
|
|
|
*pActorOut,
|
2005-10-04 19:45:45 +00:00
|
|
|
cache->m_fAnimationLengthInBeats[NotePart_Tap],
|
|
|
|
|
cache->m_bAnimationIsVivid[NotePart_Tap] );
|
2003-02-08 23:47:47 +00:00
|
|
|
|
2003-05-09 04:42:04 +00:00
|
|
|
return pActorOut;
|
2003-02-08 23:47:47 +00:00
|
|
|
}
|
2003-02-06 07:32:57 +00:00
|
|
|
|
2003-08-10 06:00:30 +00:00
|
|
|
Actor * NoteDisplay::GetTapAdditionActor( float fNoteBeat )
|
|
|
|
|
{
|
2005-10-05 05:00:50 +00:00
|
|
|
Actor *pActorOut = m_TapAddition.Get();
|
2003-12-29 03:51:15 +00:00
|
|
|
|
2003-08-10 06:00:30 +00:00
|
|
|
SetActiveFrame(
|
|
|
|
|
fNoteBeat,
|
2003-12-29 03:51:15 +00:00
|
|
|
*pActorOut,
|
2005-10-04 19:45:45 +00:00
|
|
|
cache->m_fAnimationLengthInBeats[NotePart_Addition],
|
|
|
|
|
cache->m_bAnimationIsVivid[NotePart_Addition] );
|
2003-08-10 06:00:30 +00:00
|
|
|
|
2003-12-29 03:51:15 +00:00
|
|
|
return pActorOut;
|
2003-08-10 06:00:30 +00:00
|
|
|
}
|
|
|
|
|
|
2003-08-10 10:12:50 +00:00
|
|
|
Actor * NoteDisplay::GetTapMineActor( float fNoteBeat )
|
|
|
|
|
{
|
2005-10-05 05:00:50 +00:00
|
|
|
Actor *pActorOut = m_TapMine.Get();
|
2004-08-21 01:35:50 +00:00
|
|
|
|
2003-08-10 10:12:50 +00:00
|
|
|
SetActiveFrame(
|
|
|
|
|
fNoteBeat,
|
2004-08-21 01:35:50 +00:00
|
|
|
*pActorOut,
|
2005-10-04 19:45:45 +00:00
|
|
|
cache->m_fAnimationLengthInBeats[NotePart_Mine],
|
|
|
|
|
cache->m_bAnimationIsVivid[NotePart_Mine] );
|
2003-08-10 10:12:50 +00:00
|
|
|
|
2004-08-21 01:35:50 +00:00
|
|
|
return pActorOut;
|
2003-08-10 10:12:50 +00:00
|
|
|
}
|
|
|
|
|
|
2005-04-18 01:19:56 +00:00
|
|
|
Sprite * NoteDisplay::GetHoldTopCapSprite( float fNoteBeat, bool bIsRoll, bool bIsBeingHeld )
|
2003-02-08 23:47:47 +00:00
|
|
|
{
|
2005-10-05 05:00:50 +00:00
|
|
|
Sprite *pSpriteOut = m_HoldTopCap[bIsRoll ? roll:hold][bIsBeingHeld ? active:inactive].Get();
|
2003-02-08 23:47:47 +00:00
|
|
|
|
|
|
|
|
SetActiveFrame(
|
2003-02-05 03:53:57 +00:00
|
|
|
fNoteBeat,
|
2003-02-08 23:47:47 +00:00
|
|
|
*pSpriteOut,
|
2005-10-04 19:45:45 +00:00
|
|
|
cache->m_fAnimationLengthInBeats[NotePart_HoldTopCap],
|
|
|
|
|
cache->m_bAnimationIsVivid[NotePart_HoldTopCap] );
|
2003-02-08 23:47:47 +00:00
|
|
|
|
|
|
|
|
return pSpriteOut;
|
2003-02-05 03:53:57 +00:00
|
|
|
}
|
|
|
|
|
|
2005-04-18 01:19:56 +00:00
|
|
|
Sprite * NoteDisplay::GetHoldBottomCapSprite( float fNoteBeat, bool bIsRoll, bool bIsBeingHeld )
|
2003-02-05 03:53:57 +00:00
|
|
|
{
|
2005-10-05 05:00:50 +00:00
|
|
|
Sprite *pSpriteOut = m_HoldBottomCap[bIsRoll ? roll:hold][bIsBeingHeld ? active:inactive].Get();
|
2003-02-08 23:47:47 +00:00
|
|
|
|
|
|
|
|
SetActiveFrame(
|
|
|
|
|
fNoteBeat,
|
|
|
|
|
*pSpriteOut,
|
2005-10-04 19:45:45 +00:00
|
|
|
cache->m_fAnimationLengthInBeats[NotePart_HoldBottomCap],
|
|
|
|
|
cache->m_bAnimationIsVivid[NotePart_HoldBottomCap] );
|
2003-02-08 23:47:47 +00:00
|
|
|
|
|
|
|
|
return pSpriteOut;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
2005-04-18 01:19:56 +00:00
|
|
|
Actor* NoteDisplay::GetHoldHeadActor( float fNoteBeat, bool bIsRoll, bool bIsBeingHeld )
|
2003-02-08 23:47:47 +00:00
|
|
|
{
|
2005-10-05 05:00:50 +00:00
|
|
|
Actor *pActorOut = m_HoldHead[bIsRoll ? roll:hold][bIsBeingHeld ? active:inactive].Get();
|
2003-02-06 07:32:57 +00:00
|
|
|
|
2003-02-08 23:47:47 +00:00
|
|
|
SetActiveFrame(
|
2003-02-05 03:53:57 +00:00
|
|
|
fNoteBeat,
|
2003-05-09 04:42:04 +00:00
|
|
|
*pActorOut,
|
2005-10-04 19:45:45 +00:00
|
|
|
cache->m_fAnimationLengthInBeats[NotePart_HoldHead],
|
|
|
|
|
cache->m_bAnimationIsVivid[NotePart_HoldHead] );
|
2003-02-08 23:47:47 +00:00
|
|
|
|
2003-05-09 04:42:04 +00:00
|
|
|
return pActorOut;
|
2003-02-05 03:53:57 +00:00
|
|
|
}
|
|
|
|
|
|
2005-04-18 01:19:56 +00:00
|
|
|
Sprite *NoteDisplay::GetHoldBodySprite( float fNoteBeat, bool bIsRoll, bool bIsBeingHeld )
|
2003-02-05 03:53:57 +00:00
|
|
|
{
|
2005-10-05 05:00:50 +00:00
|
|
|
Sprite *pSpriteOut = m_HoldBody[bIsRoll ? roll:hold][bIsBeingHeld ? active:inactive].Get();
|
2003-02-06 07:32:57 +00:00
|
|
|
|
2003-02-08 23:47:47 +00:00
|
|
|
SetActiveFrame(
|
2003-02-05 03:53:57 +00:00
|
|
|
fNoteBeat,
|
2003-02-08 23:47:47 +00:00
|
|
|
*pSpriteOut,
|
2005-10-04 19:45:45 +00:00
|
|
|
cache->m_fAnimationLengthInBeats[NotePart_HoldBody],
|
|
|
|
|
cache->m_bAnimationIsVivid[NotePart_HoldBody] );
|
2003-02-08 23:47:47 +00:00
|
|
|
|
|
|
|
|
return pSpriteOut;
|
2003-02-05 03:53:57 +00:00
|
|
|
}
|
|
|
|
|
|
2005-04-18 01:19:56 +00:00
|
|
|
Actor* NoteDisplay::GetHoldTailActor( float fNoteBeat, bool bIsRoll, bool bIsBeingHeld )
|
2003-02-05 03:53:57 +00:00
|
|
|
{
|
2005-10-05 05:00:50 +00:00
|
|
|
Actor *pActorOut = m_HoldTail[bIsRoll ? roll:hold][bIsBeingHeld ? active:inactive].Get();
|
2003-02-06 07:32:57 +00:00
|
|
|
|
2003-02-08 23:47:47 +00:00
|
|
|
SetActiveFrame(
|
2003-02-05 03:53:57 +00:00
|
|
|
fNoteBeat,
|
2003-07-09 05:57:48 +00:00
|
|
|
*pActorOut,
|
2005-10-04 19:45:45 +00:00
|
|
|
cache->m_fAnimationLengthInBeats[NotePart_HoldTail],
|
|
|
|
|
cache->m_bAnimationIsVivid[NotePart_HoldTail] );
|
2003-02-08 23:47:47 +00:00
|
|
|
|
2003-07-09 05:57:48 +00:00
|
|
|
return pActorOut;
|
2003-02-05 03:53:57 +00:00
|
|
|
}
|
|
|
|
|
|
2004-12-20 06:25:59 +00:00
|
|
|
static float ArrowGetAlphaOrGlow( bool bGlow, const PlayerState* pPlayerState, int iCol, float fYOffset, float fPercentFadeToFail, float fYReverseOffsetPixels )
|
2004-04-16 03:05:16 +00:00
|
|
|
{
|
|
|
|
|
if( bGlow )
|
2004-12-20 06:25:59 +00:00
|
|
|
return ArrowEffects::GetGlow( pPlayerState, iCol, fYOffset, fPercentFadeToFail, fYReverseOffsetPixels );
|
2004-04-16 03:05:16 +00:00
|
|
|
else
|
2004-12-20 06:25:59 +00:00
|
|
|
return ArrowEffects::GetAlpha( pPlayerState, iCol, fYOffset, fPercentFadeToFail, fYReverseOffsetPixels );
|
2004-04-16 03:05:16 +00:00
|
|
|
}
|
2003-02-05 03:53:57 +00:00
|
|
|
|
2004-10-27 21:58:31 +00:00
|
|
|
struct StripBuffer
|
|
|
|
|
{
|
|
|
|
|
enum { size = 512 };
|
2005-01-10 13:09:19 +00:00
|
|
|
RageSpriteVertex *buf;
|
2004-10-27 21:58:31 +00:00
|
|
|
RageSpriteVertex *v;
|
2005-01-10 13:09:19 +00:00
|
|
|
StripBuffer()
|
|
|
|
|
{
|
|
|
|
|
buf = (RageSpriteVertex *) malloc( size * sizeof(RageSpriteVertex) );
|
|
|
|
|
Init();
|
|
|
|
|
}
|
|
|
|
|
~StripBuffer()
|
|
|
|
|
{
|
|
|
|
|
free( buf );
|
|
|
|
|
}
|
|
|
|
|
|
2004-10-27 21:58:31 +00:00
|
|
|
void Init()
|
|
|
|
|
{
|
|
|
|
|
v = buf;
|
|
|
|
|
}
|
|
|
|
|
void Draw()
|
|
|
|
|
{
|
|
|
|
|
DISPLAY->DrawQuadStrip( buf, v-buf );
|
|
|
|
|
}
|
|
|
|
|
int Used() const { return v - buf; }
|
|
|
|
|
int Free() const { return size - Used(); }
|
|
|
|
|
};
|
|
|
|
|
|
2005-04-18 01:19:56 +00:00
|
|
|
void NoteDisplay::DrawHoldTopCap( const TapNote& tn, int iCol, int iRow, bool bIsBeingHeld, float fYHead, float fYTail, int fYStep, float fPercentFadeToFail, float fColorScale, bool bGlow, float fYStartOffset, float fYEndOffset )
|
2002-08-13 23:26:46 +00:00
|
|
|
{
|
2003-02-05 03:53:57 +00:00
|
|
|
//
|
2003-07-17 06:10:25 +00:00
|
|
|
// Draw the top cap (always wavy)
|
2003-02-05 03:53:57 +00:00
|
|
|
//
|
2004-10-27 21:58:31 +00:00
|
|
|
StripBuffer queue;
|
|
|
|
|
|
2005-04-20 01:53:41 +00:00
|
|
|
Sprite* pSprTopCap = GetHoldTopCapSprite( NoteRowToBeat(iRow), tn.subType == TapNote::hold_head_roll, bIsBeingHeld );
|
2003-07-17 06:10:25 +00:00
|
|
|
|
2004-12-20 06:25:59 +00:00
|
|
|
pSprTopCap->SetZoom( ArrowEffects::GetZoom( m_pPlayerState ) );
|
2004-06-08 22:27:37 +00:00
|
|
|
|
2003-07-17 06:10:25 +00:00
|
|
|
// draw manually in small segments
|
|
|
|
|
RageTexture* pTexture = pSprTopCap->GetTexture();
|
|
|
|
|
const RectF *pRect = pSprTopCap->GetCurrentTextureCoordRect();
|
2004-02-04 09:55:18 +00:00
|
|
|
DISPLAY->ClearAllTextures();
|
|
|
|
|
DISPLAY->SetTexture( 0, pTexture );
|
2003-07-17 06:10:25 +00:00
|
|
|
DISPLAY->SetBlendMode( BLEND_NORMAL );
|
2004-02-04 11:05:33 +00:00
|
|
|
DISPLAY->SetCullMode( CULL_NONE );
|
2003-07-17 06:10:25 +00:00
|
|
|
DISPLAY->SetTextureWrapping(false);
|
|
|
|
|
|
2004-06-08 19:04:26 +00:00
|
|
|
const float fFrameWidth = pSprTopCap->GetZoomedWidth();
|
|
|
|
|
const float fFrameHeight = pSprTopCap->GetZoomedHeight();
|
2003-07-17 06:10:25 +00:00
|
|
|
const float fYCapTop = fYHead+cache->m_iStartDrawingHoldBodyOffsetFromHead-fFrameHeight;
|
|
|
|
|
const float fYCapBottom = fYHead+cache->m_iStartDrawingHoldBodyOffsetFromHead;
|
|
|
|
|
|
2005-03-02 10:35:02 +00:00
|
|
|
bool bReverse = m_pPlayerState->m_CurrentPlayerOptions.GetReversePercentForColumn(iCol) > 0.5f;
|
|
|
|
|
|
2004-04-16 03:05:16 +00:00
|
|
|
if( bGlow )
|
|
|
|
|
fColorScale = 1;
|
|
|
|
|
|
2005-02-07 21:13:04 +00:00
|
|
|
float fDrawYCapTop;
|
|
|
|
|
float fDrawYCapBottom;
|
|
|
|
|
{
|
|
|
|
|
float fYStartPos = ArrowEffects::GetYPos( m_pPlayerState, iCol, fYStartOffset, m_fYReverseOffsetPixels );
|
|
|
|
|
float fYEndPos = ArrowEffects::GetYPos( m_pPlayerState, iCol, fYEndOffset, m_fYReverseOffsetPixels );
|
2005-03-02 10:35:02 +00:00
|
|
|
fDrawYCapTop = max( fYCapTop, bReverse ? fYEndPos : fYStartPos );
|
|
|
|
|
fDrawYCapBottom = min( fYCapBottom, bReverse ? fYStartPos : fYEndPos );
|
2005-02-07 21:13:04 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// don't draw any part of the head that is after the middle of the tail
|
|
|
|
|
fDrawYCapBottom = min( fYTail, fDrawYCapBottom );
|
|
|
|
|
|
2004-04-16 03:05:16 +00:00
|
|
|
bool bAllAreTransparent = true;
|
2004-04-13 07:47:10 +00:00
|
|
|
bool bLast = false;
|
2005-02-07 21:13:04 +00:00
|
|
|
|
|
|
|
|
float fY = fDrawYCapTop;
|
2004-05-04 05:49:35 +00:00
|
|
|
for( ; !bLast; fY+=fYStep )
|
2002-08-13 23:26:46 +00:00
|
|
|
{
|
2005-02-07 21:13:04 +00:00
|
|
|
if( fY >= fDrawYCapBottom )
|
2004-04-13 07:47:10 +00:00
|
|
|
{
|
2005-02-07 21:13:04 +00:00
|
|
|
fY = fDrawYCapBottom;
|
2004-04-13 07:47:10 +00:00
|
|
|
bLast = true;
|
|
|
|
|
}
|
|
|
|
|
|
2004-12-20 06:25:59 +00:00
|
|
|
const float fYOffset = ArrowEffects::GetYOffsetFromYPos( m_pPlayerState, iCol, fY, m_fYReverseOffsetPixels );
|
|
|
|
|
const float fZ = ArrowEffects::GetZPos( m_pPlayerState, iCol, fYOffset );
|
|
|
|
|
const float fX = ArrowEffects::GetXPos( m_pPlayerState, iCol, fYOffset );
|
2004-04-13 07:47:10 +00:00
|
|
|
const float fXLeft = fX - fFrameWidth/2;
|
|
|
|
|
const float fXRight = fX + fFrameWidth/2;
|
|
|
|
|
const float fTopDistFromHeadTop = fY - fYCapTop;
|
2003-07-17 06:10:25 +00:00
|
|
|
const float fTexCoordTop = SCALE( fTopDistFromHeadTop, 0, fFrameHeight, pRect->top, pRect->bottom );
|
|
|
|
|
const float fTexCoordLeft = pRect->left;
|
|
|
|
|
const float fTexCoordRight = pRect->right;
|
2004-12-20 06:25:59 +00:00
|
|
|
const float fAlpha = ArrowGetAlphaOrGlow( bGlow, m_pPlayerState, iCol, fYOffset, fPercentFadeToFail, m_fYReverseOffsetPixels );
|
2004-04-16 03:05:16 +00:00
|
|
|
const RageColor color = RageColor(fColorScale,fColorScale,fColorScale,fAlpha);
|
|
|
|
|
|
|
|
|
|
if( fAlpha > 0 )
|
|
|
|
|
bAllAreTransparent = false;
|
2004-04-13 07:47:10 +00:00
|
|
|
|
2004-10-27 21:58:31 +00:00
|
|
|
queue.v[0].p = RageVector3(fXLeft, fY, fZ); queue.v[0].c = color; queue.v[0].t = RageVector2(fTexCoordLeft, fTexCoordTop);
|
|
|
|
|
queue.v[1].p = RageVector3(fXRight, fY, fZ); queue.v[1].c = color; queue.v[1].t = RageVector2(fTexCoordRight, fTexCoordTop);
|
|
|
|
|
queue.v+=2;
|
|
|
|
|
if( queue.Free() < 2 )
|
|
|
|
|
{
|
|
|
|
|
/* The queue is full. Render it, clear the buffer, and move back a step to
|
|
|
|
|
* start off the quad strip again. */
|
|
|
|
|
if( !bAllAreTransparent )
|
|
|
|
|
queue.Draw();
|
|
|
|
|
queue.Init();
|
|
|
|
|
bAllAreTransparent = true;
|
|
|
|
|
fY -= fYStep;
|
|
|
|
|
}
|
2002-08-13 23:26:46 +00:00
|
|
|
}
|
2004-04-16 03:05:16 +00:00
|
|
|
if( !bAllAreTransparent )
|
2004-10-27 21:58:31 +00:00
|
|
|
queue.Draw();
|
2003-07-17 06:10:25 +00:00
|
|
|
}
|
2002-08-13 23:26:46 +00:00
|
|
|
|
2004-10-27 21:58:31 +00:00
|
|
|
|
2005-04-18 01:19:56 +00:00
|
|
|
void NoteDisplay::DrawHoldBody( const TapNote& tn, int iCol, int iRow, bool bIsBeingHeld, float fYHead, float fYTail, int fYStep, float fPercentFadeToFail, float fColorScale, bool bGlow,
|
2005-02-07 21:00:21 +00:00
|
|
|
float fYStartOffset, float fYEndOffset )
|
2003-07-17 06:10:25 +00:00
|
|
|
{
|
2002-08-13 23:26:46 +00:00
|
|
|
//
|
2003-02-05 03:53:57 +00:00
|
|
|
// Draw the body (always wavy)
|
2002-08-13 23:26:46 +00:00
|
|
|
//
|
2004-10-27 21:58:31 +00:00
|
|
|
StripBuffer queue;
|
2003-07-17 06:10:25 +00:00
|
|
|
|
2005-04-20 01:53:41 +00:00
|
|
|
Sprite* pSprBody = GetHoldBodySprite( NoteRowToBeat(iRow), tn.subType == TapNote::hold_head_roll, bIsBeingHeld );
|
2003-07-17 06:10:25 +00:00
|
|
|
|
2004-12-20 06:25:59 +00:00
|
|
|
pSprBody->SetZoom( ArrowEffects::GetZoom( m_pPlayerState ) );
|
2004-06-08 22:27:37 +00:00
|
|
|
|
2003-07-17 06:10:25 +00:00
|
|
|
// draw manually in small segments
|
|
|
|
|
RageTexture* pTexture = pSprBody->GetTexture();
|
|
|
|
|
const RectF *pRect = pSprBody->GetCurrentTextureCoordRect();
|
2004-02-04 09:55:18 +00:00
|
|
|
DISPLAY->ClearAllTextures();
|
|
|
|
|
DISPLAY->SetTexture( 0, pTexture );
|
2003-07-17 06:10:25 +00:00
|
|
|
DISPLAY->SetBlendMode( BLEND_NORMAL );
|
2004-02-04 11:05:33 +00:00
|
|
|
DISPLAY->SetCullMode( CULL_NONE );
|
2003-07-17 06:10:25 +00:00
|
|
|
DISPLAY->SetTextureWrapping( true );
|
|
|
|
|
|
|
|
|
|
|
2004-06-08 19:04:26 +00:00
|
|
|
const float fFrameWidth = pSprBody->GetZoomedWidth();
|
|
|
|
|
const float fFrameHeight = pSprBody->GetZoomedHeight();
|
2003-07-17 06:10:25 +00:00
|
|
|
const float fYBodyTop = fYHead + cache->m_iStartDrawingHoldBodyOffsetFromHead;
|
|
|
|
|
const float fYBodyBottom = fYTail + cache->m_iStopDrawingHoldBodyOffsetFromTail;
|
2004-06-07 20:54:21 +00:00
|
|
|
|
2005-02-01 20:57:16 +00:00
|
|
|
const bool bReverse = m_pPlayerState->m_CurrentPlayerOptions.GetReversePercentForColumn(iCol) > 0.5f;
|
2003-12-31 23:47:01 +00:00
|
|
|
bool bAnchorToBottom = bReverse && cache->m_bFlipHeadAndTailWhenReverse;
|
|
|
|
|
|
2004-04-16 03:05:16 +00:00
|
|
|
if( bGlow )
|
|
|
|
|
fColorScale = 1;
|
|
|
|
|
|
2005-02-07 21:00:21 +00:00
|
|
|
/* Only draw the section that's within the range specified. If a hold note is
|
|
|
|
|
* very long, don't process or draw the part outside of the range. Don't change
|
|
|
|
|
* fYBodyTop or fYBodyBottom; they need to be left alone to calculate texture
|
|
|
|
|
* coordinates. */
|
|
|
|
|
float fDrawYBodyTop;
|
|
|
|
|
float fDrawYBodyBottom;
|
|
|
|
|
{
|
|
|
|
|
float fYStartPos = ArrowEffects::GetYPos( m_pPlayerState, iCol, fYStartOffset, m_fYReverseOffsetPixels );
|
|
|
|
|
float fYEndPos = ArrowEffects::GetYPos( m_pPlayerState, iCol, fYEndOffset, m_fYReverseOffsetPixels );
|
2005-03-02 10:35:02 +00:00
|
|
|
|
|
|
|
|
fDrawYBodyTop = max( fYBodyTop, bReverse ? fYEndPos : fYStartPos );
|
|
|
|
|
fDrawYBodyBottom = min( fYBodyBottom, bReverse ? fYStartPos : fYEndPos );
|
2005-02-07 21:00:21 +00:00
|
|
|
}
|
|
|
|
|
|
2003-07-17 06:10:25 +00:00
|
|
|
// top to bottom
|
2004-04-16 03:05:16 +00:00
|
|
|
bool bAllAreTransparent = true;
|
2004-04-13 07:47:10 +00:00
|
|
|
bool bLast = false;
|
2005-03-30 08:36:55 +00:00
|
|
|
float fVertTexCoordOffset = 0;
|
2005-02-07 21:00:21 +00:00
|
|
|
for( float fY = fDrawYBodyTop; !bLast; fY += fYStep )
|
2002-08-13 23:26:46 +00:00
|
|
|
{
|
2005-02-07 21:00:21 +00:00
|
|
|
if( fY >= fDrawYBodyBottom )
|
2003-12-31 23:47:01 +00:00
|
|
|
{
|
2005-02-07 21:00:21 +00:00
|
|
|
fY = fDrawYBodyBottom;
|
2004-04-13 07:47:10 +00:00
|
|
|
bLast = true;
|
2003-07-17 06:10:25 +00:00
|
|
|
}
|
2004-04-13 07:47:10 +00:00
|
|
|
|
2004-12-20 06:25:59 +00:00
|
|
|
const float fYOffset = ArrowEffects::GetYOffsetFromYPos( m_pPlayerState, iCol, fY, m_fYReverseOffsetPixels );
|
|
|
|
|
const float fZ = ArrowEffects::GetZPos( m_pPlayerState, iCol, fYOffset );
|
|
|
|
|
const float fX = ArrowEffects::GetXPos( m_pPlayerState, iCol, fYOffset );
|
2004-04-13 07:47:10 +00:00
|
|
|
const float fXLeft = fX - fFrameWidth/2;
|
|
|
|
|
const float fXRight = fX + fFrameWidth/2;
|
|
|
|
|
const float fDistFromBodyBottom = fYBodyBottom - fY;
|
|
|
|
|
const float fDistFromBodyTop = fY - fYBodyTop;
|
2005-03-30 08:36:55 +00:00
|
|
|
float fTexCoordTop = SCALE( bAnchorToBottom ? fDistFromBodyTop : fDistFromBodyBottom, 0, fFrameHeight, pRect->bottom, pRect->top );
|
|
|
|
|
/* For very large hold notes, shift the texture coordinates to be near 0, so we
|
|
|
|
|
* don't send very large values to the renderer. */
|
|
|
|
|
if( fY == fDrawYBodyTop ) // first
|
|
|
|
|
fVertTexCoordOffset = floorf( fTexCoordTop );
|
|
|
|
|
fTexCoordTop -= fVertTexCoordOffset;
|
2004-04-13 07:47:10 +00:00
|
|
|
const float fTexCoordLeft = pRect->left;
|
|
|
|
|
const float fTexCoordRight = pRect->right;
|
2004-12-20 06:25:59 +00:00
|
|
|
const float fAlpha = ArrowGetAlphaOrGlow( bGlow, m_pPlayerState, iCol, fYOffset, fPercentFadeToFail, m_fYReverseOffsetPixels );
|
2004-04-16 03:05:16 +00:00
|
|
|
const RageColor color = RageColor(fColorScale,fColorScale,fColorScale,fAlpha);
|
|
|
|
|
|
|
|
|
|
if( fAlpha > 0 )
|
|
|
|
|
bAllAreTransparent = false;
|
2004-04-13 07:47:10 +00:00
|
|
|
|
2004-10-27 21:58:31 +00:00
|
|
|
queue.v[0].p = RageVector3(fXLeft, fY, fZ); queue.v[0].c = color; queue.v[0].t = RageVector2(fTexCoordLeft, fTexCoordTop);
|
|
|
|
|
queue.v[1].p = RageVector3(fXRight, fY, fZ); queue.v[1].c = color; queue.v[1].t = RageVector2(fTexCoordRight, fTexCoordTop);
|
|
|
|
|
queue.v+=2;
|
|
|
|
|
if( queue.Free() < 2 )
|
|
|
|
|
{
|
|
|
|
|
/* The queue is full. Render it, clear the buffer, and move back a step to
|
|
|
|
|
* start off the quad strip again. */
|
|
|
|
|
if( !bAllAreTransparent )
|
|
|
|
|
queue.Draw();
|
|
|
|
|
queue.Init();
|
|
|
|
|
bAllAreTransparent = true;
|
|
|
|
|
fY -= fYStep;
|
|
|
|
|
}
|
2004-04-13 07:47:10 +00:00
|
|
|
}
|
|
|
|
|
|
2004-04-16 03:05:16 +00:00
|
|
|
if( !bAllAreTransparent )
|
2004-10-27 21:58:31 +00:00
|
|
|
queue.Draw();
|
2003-07-17 06:10:25 +00:00
|
|
|
}
|
2003-02-05 03:53:57 +00:00
|
|
|
|
2005-04-18 01:19:56 +00:00
|
|
|
void NoteDisplay::DrawHoldBottomCap( const TapNote& tn, int iCol, int iRow, bool bIsBeingHeld, float fYHead, float fYTail, int fYStep, float fPercentFadeToFail, float fColorScale, bool bGlow, float fYStartOffset, float fYEndOffset )
|
2003-07-17 06:10:25 +00:00
|
|
|
{
|
2003-02-08 23:47:47 +00:00
|
|
|
//
|
2003-07-17 06:10:25 +00:00
|
|
|
// Draw the bottom cap (always wavy)
|
2003-02-08 23:47:47 +00:00
|
|
|
//
|
2004-10-27 21:58:31 +00:00
|
|
|
StripBuffer queue;
|
2003-07-17 06:10:25 +00:00
|
|
|
|
2005-04-20 01:53:41 +00:00
|
|
|
Sprite* pBottomCap = GetHoldBottomCapSprite( NoteRowToBeat(iRow), tn.subType == TapNote::hold_head_roll, bIsBeingHeld );
|
2003-07-17 06:10:25 +00:00
|
|
|
|
2004-12-20 06:25:59 +00:00
|
|
|
pBottomCap->SetZoom( ArrowEffects::GetZoom( m_pPlayerState ) );
|
2004-06-08 22:27:37 +00:00
|
|
|
|
2003-07-17 06:10:25 +00:00
|
|
|
// draw manually in small segments
|
|
|
|
|
RageTexture* pTexture = pBottomCap->GetTexture();
|
|
|
|
|
const RectF *pRect = pBottomCap->GetCurrentTextureCoordRect();
|
2004-02-04 09:55:18 +00:00
|
|
|
DISPLAY->ClearAllTextures();
|
|
|
|
|
DISPLAY->SetTexture( 0, pTexture );
|
2003-07-17 06:10:25 +00:00
|
|
|
DISPLAY->SetBlendMode( BLEND_NORMAL );
|
2004-02-04 11:05:33 +00:00
|
|
|
DISPLAY->SetCullMode( CULL_NONE );
|
2003-07-17 06:10:25 +00:00
|
|
|
DISPLAY->SetTextureWrapping(false);
|
|
|
|
|
|
2004-06-08 19:04:26 +00:00
|
|
|
const float fFrameWidth = pBottomCap->GetZoomedWidth();
|
|
|
|
|
const float fFrameHeight = pBottomCap->GetZoomedHeight();
|
2003-07-17 06:10:25 +00:00
|
|
|
const float fYCapTop = fYTail+cache->m_iStopDrawingHoldBodyOffsetFromTail;
|
|
|
|
|
const float fYCapBottom = fYTail+cache->m_iStopDrawingHoldBodyOffsetFromTail+fFrameHeight;
|
|
|
|
|
|
2005-03-02 10:35:02 +00:00
|
|
|
bool bReverse = m_pPlayerState->m_CurrentPlayerOptions.GetReversePercentForColumn(iCol) > 0.5f;
|
|
|
|
|
|
2004-04-16 03:05:16 +00:00
|
|
|
if( bGlow )
|
|
|
|
|
fColorScale = 1;
|
|
|
|
|
|
2005-02-07 21:13:04 +00:00
|
|
|
float fDrawYCapTop;
|
|
|
|
|
float fDrawYCapBottom;
|
|
|
|
|
{
|
|
|
|
|
float fYStartPos = ArrowEffects::GetYPos( m_pPlayerState, iCol, fYStartOffset, m_fYReverseOffsetPixels );
|
|
|
|
|
float fYEndPos = ArrowEffects::GetYPos( m_pPlayerState, iCol, fYEndOffset, m_fYReverseOffsetPixels );
|
2005-03-02 10:35:02 +00:00
|
|
|
fDrawYCapTop = max( fYCapTop, bReverse ? fYEndPos : fYStartPos );
|
|
|
|
|
fDrawYCapBottom = min( fYCapBottom, bReverse ? fYStartPos : fYEndPos );
|
2005-02-07 21:13:04 +00:00
|
|
|
}
|
|
|
|
|
|
2004-04-16 03:05:16 +00:00
|
|
|
bool bAllAreTransparent = true;
|
2004-04-13 07:47:10 +00:00
|
|
|
bool bLast = false;
|
2004-05-04 05:49:35 +00:00
|
|
|
// don't draw any part of the tail that is before the middle of the head
|
2005-02-07 21:13:04 +00:00
|
|
|
float fY=max( fDrawYCapTop, fYHead );
|
2004-04-13 07:47:10 +00:00
|
|
|
for( ; !bLast; fY += fYStep )
|
2003-02-08 23:47:47 +00:00
|
|
|
{
|
2005-02-07 21:13:04 +00:00
|
|
|
if( fY >= fDrawYCapBottom )
|
2004-04-13 07:47:10 +00:00
|
|
|
{
|
2005-02-07 21:13:04 +00:00
|
|
|
fY = fDrawYCapBottom;
|
2004-04-13 07:47:10 +00:00
|
|
|
bLast = true;
|
|
|
|
|
}
|
|
|
|
|
|
2004-12-20 06:25:59 +00:00
|
|
|
const float fYOffset = ArrowEffects::GetYOffsetFromYPos( m_pPlayerState, iCol, fY, m_fYReverseOffsetPixels );
|
|
|
|
|
const float fZ = ArrowEffects::GetZPos( m_pPlayerState, iCol, fYOffset );
|
|
|
|
|
const float fX = ArrowEffects::GetXPos( m_pPlayerState, iCol, fYOffset );
|
2004-04-13 07:47:10 +00:00
|
|
|
const float fXLeft = fX - fFrameWidth/2;
|
|
|
|
|
const float fXRight = fX + fFrameWidth/2;
|
|
|
|
|
const float fTopDistFromTail = fY - fYCapTop;
|
|
|
|
|
const float fTexCoordTop = SCALE( fTopDistFromTail, 0, fFrameHeight, pRect->top, pRect->bottom );
|
2003-07-17 06:10:25 +00:00
|
|
|
const float fTexCoordLeft = pRect->left;
|
|
|
|
|
const float fTexCoordRight = pRect->right;
|
2004-12-20 06:25:59 +00:00
|
|
|
const float fAlpha = ArrowGetAlphaOrGlow( bGlow, m_pPlayerState, iCol, fYOffset, fPercentFadeToFail, m_fYReverseOffsetPixels );
|
2004-04-16 03:05:16 +00:00
|
|
|
const RageColor color = RageColor(fColorScale,fColorScale,fColorScale,fAlpha);
|
|
|
|
|
|
|
|
|
|
if( fAlpha > 0 )
|
|
|
|
|
bAllAreTransparent = false;
|
2004-04-13 07:47:10 +00:00
|
|
|
|
2004-10-27 21:58:31 +00:00
|
|
|
queue.v[0].p = RageVector3(fXLeft, fY, fZ); queue.v[0].c = color; queue.v[0].t = RageVector2(fTexCoordLeft, fTexCoordTop);
|
|
|
|
|
queue.v[1].p = RageVector3(fXRight, fY, fZ); queue.v[1].c = color; queue.v[1].t = RageVector2(fTexCoordRight, fTexCoordTop);
|
|
|
|
|
queue.v+=2;
|
|
|
|
|
if( queue.Free() < 2 )
|
|
|
|
|
{
|
|
|
|
|
/* The queue is full. Render it, clear the buffer, and move back a step to
|
|
|
|
|
* start off the quad strip again. */
|
|
|
|
|
if( !bAllAreTransparent )
|
|
|
|
|
queue.Draw();
|
|
|
|
|
queue.Init();
|
|
|
|
|
bAllAreTransparent = true;
|
|
|
|
|
fY -= fYStep;
|
|
|
|
|
}
|
2003-02-08 23:47:47 +00:00
|
|
|
}
|
2004-04-16 03:05:16 +00:00
|
|
|
if( !bAllAreTransparent )
|
2004-10-27 21:58:31 +00:00
|
|
|
queue.Draw();
|
2003-07-17 06:10:25 +00:00
|
|
|
}
|
2003-02-05 03:53:57 +00:00
|
|
|
|
2005-04-18 01:19:56 +00:00
|
|
|
void NoteDisplay::DrawHoldTail( const TapNote& tn, int iCol, int iRow, bool bIsBeingHeld, float fYTail, float fPercentFadeToFail, float fColorScale, bool bGlow, float fYStartOffset, float fYEndOffset )
|
2003-07-17 06:10:25 +00:00
|
|
|
{
|
2003-02-05 03:53:57 +00:00
|
|
|
//
|
2003-02-08 23:47:47 +00:00
|
|
|
// Draw the tail
|
2003-02-05 03:53:57 +00:00
|
|
|
//
|
2005-04-20 01:53:41 +00:00
|
|
|
Actor* pSprTail = GetHoldTailActor( NoteRowToBeat(iRow), tn.subType == TapNote::hold_head_roll, bIsBeingHeld );
|
2003-07-17 06:10:25 +00:00
|
|
|
|
2004-12-20 06:25:59 +00:00
|
|
|
pSprTail->SetZoom( ArrowEffects::GetZoom( m_pPlayerState ) );
|
2004-06-17 21:42:00 +00:00
|
|
|
|
2003-07-17 06:10:25 +00:00
|
|
|
const float fY = fYTail;
|
2004-12-20 06:25:59 +00:00
|
|
|
const float fYOffset = ArrowEffects::GetYOffsetFromYPos( m_pPlayerState, iCol, fY, m_fYReverseOffsetPixels );
|
2005-03-30 08:36:55 +00:00
|
|
|
if( fYOffset < fYStartOffset || fYOffset > fYEndOffset )
|
|
|
|
|
return;
|
2004-12-20 06:25:59 +00:00
|
|
|
const float fX = ArrowEffects::GetXPos( m_pPlayerState, iCol, fYOffset );
|
|
|
|
|
const float fZ = ArrowEffects::GetZPos( m_pPlayerState, iCol, fYOffset );
|
|
|
|
|
const float fAlpha = ArrowEffects::GetAlpha( m_pPlayerState, iCol, fYOffset, fPercentFadeToFail, m_fYReverseOffsetPixels );
|
|
|
|
|
const float fGlow = ArrowEffects::GetGlow( m_pPlayerState, iCol, fYOffset, fPercentFadeToFail, m_fYReverseOffsetPixels );
|
2003-07-17 06:10:25 +00:00
|
|
|
const RageColor colorDiffuse= RageColor(fColorScale,fColorScale,fColorScale,fAlpha);
|
|
|
|
|
const RageColor colorGlow = RageColor(1,1,1,fGlow);
|
|
|
|
|
|
|
|
|
|
pSprTail->SetXY( fX, fY );
|
|
|
|
|
pSprTail->SetZ( fZ );
|
|
|
|
|
|
2005-10-04 19:45:45 +00:00
|
|
|
if( cache->m_fNoteColorTextureCoordSpacing[NotePart_HoldTail] != g_emptyVector )
|
|
|
|
|
{
|
|
|
|
|
DISPLAY->TexturePushMatrix();
|
|
|
|
|
NoteType nt = GetNoteType( iRow );
|
2005-10-04 20:32:11 +00:00
|
|
|
DISPLAY->TextureTranslate( cache->m_fNoteColorTextureCoordSpacing[NotePart_HoldTail]*(float)nt );
|
2005-10-04 19:45:45 +00:00
|
|
|
}
|
|
|
|
|
|
2003-07-17 06:10:25 +00:00
|
|
|
if( bGlow )
|
2002-09-17 23:02:37 +00:00
|
|
|
{
|
2003-07-17 06:10:25 +00:00
|
|
|
pSprTail->SetDiffuse( RageColor(1,1,1,0) );
|
|
|
|
|
pSprTail->SetGlow( colorGlow );
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
pSprTail->SetDiffuse( colorDiffuse );
|
|
|
|
|
pSprTail->SetGlow( RageColor(0,0,0,0) );
|
2002-08-13 23:26:46 +00:00
|
|
|
}
|
2003-07-17 06:11:32 +00:00
|
|
|
|
2003-12-31 08:15:34 +00:00
|
|
|
if( cache->m_bHoldTailUseLighting )
|
2003-07-17 06:11:32 +00:00
|
|
|
{
|
|
|
|
|
DISPLAY->SetLighting( true );
|
|
|
|
|
DISPLAY->SetLightDirectional(
|
|
|
|
|
0,
|
2003-12-31 03:42:59 +00:00
|
|
|
RageColor(1,1,1,1),
|
2003-07-17 06:11:32 +00:00
|
|
|
RageColor(1,1,1,1),
|
|
|
|
|
RageColor(1,1,1,1),
|
|
|
|
|
RageVector3(1, 0, +1) );
|
|
|
|
|
}
|
|
|
|
|
|
2003-07-17 06:10:25 +00:00
|
|
|
pSprTail->Draw();
|
2003-07-17 06:11:32 +00:00
|
|
|
|
2003-12-31 08:15:34 +00:00
|
|
|
if( cache->m_bHoldTailUseLighting )
|
2003-07-17 06:11:32 +00:00
|
|
|
{
|
|
|
|
|
DISPLAY->SetLightOff( 0 );
|
|
|
|
|
DISPLAY->SetLighting( false );
|
|
|
|
|
}
|
2005-10-04 19:45:45 +00:00
|
|
|
|
|
|
|
|
if( cache->m_fNoteColorTextureCoordSpacing[NotePart_HoldTail] != g_emptyVector )
|
|
|
|
|
{
|
|
|
|
|
DISPLAY->TexturePopMatrix();
|
|
|
|
|
}
|
2003-07-17 06:10:25 +00:00
|
|
|
}
|
2002-08-29 01:38:21 +00:00
|
|
|
|
2005-04-18 01:19:56 +00:00
|
|
|
void NoteDisplay::DrawHoldHead( const TapNote& tn, int iCol, int iRow, bool bIsBeingHeld, float fYHead, float fPercentFadeToFail, float fColorScale, bool bGlow, float fYStartOffset, float fYEndOffset )
|
2003-07-17 06:10:25 +00:00
|
|
|
{
|
2003-02-08 23:47:47 +00:00
|
|
|
//
|
|
|
|
|
// Draw the head
|
|
|
|
|
//
|
2005-04-20 01:53:41 +00:00
|
|
|
Actor* pActor = GetHoldHeadActor( NoteRowToBeat(iRow), tn.subType == TapNote::hold_head_roll, bIsBeingHeld );
|
2003-02-08 23:47:47 +00:00
|
|
|
|
2004-12-20 06:25:59 +00:00
|
|
|
pActor->SetZoom( ArrowEffects::GetZoom( m_pPlayerState ) );
|
2004-06-17 21:42:00 +00:00
|
|
|
|
2003-07-17 06:10:25 +00:00
|
|
|
// draw with normal Sprite
|
|
|
|
|
const float fY = fYHead;
|
2004-12-20 06:25:59 +00:00
|
|
|
const float fYOffset = ArrowEffects::GetYOffsetFromYPos( m_pPlayerState, iCol, fY, m_fYReverseOffsetPixels );
|
2005-03-30 08:36:55 +00:00
|
|
|
if( fYOffset < fYStartOffset || fYOffset > fYEndOffset )
|
|
|
|
|
return;
|
2004-12-20 06:25:59 +00:00
|
|
|
const float fX = ArrowEffects::GetXPos( m_pPlayerState, iCol, fYOffset );
|
|
|
|
|
const float fZ = ArrowEffects::GetZPos( m_pPlayerState, iCol, fYOffset );
|
|
|
|
|
const float fAlpha = ArrowEffects::GetAlpha( m_pPlayerState, iCol, fYOffset, fPercentFadeToFail, m_fYReverseOffsetPixels );
|
|
|
|
|
const float fGlow = ArrowEffects::GetGlow( m_pPlayerState, iCol, fYOffset, fPercentFadeToFail, m_fYReverseOffsetPixels );
|
2003-07-17 06:10:25 +00:00
|
|
|
const RageColor colorDiffuse= RageColor(fColorScale,fColorScale,fColorScale,fAlpha);
|
|
|
|
|
const RageColor colorGlow = RageColor(1,1,1,fGlow);
|
2003-02-08 23:47:47 +00:00
|
|
|
|
2004-03-20 19:15:15 +00:00
|
|
|
pActor->SetRotationZ( 0 );
|
2003-07-17 06:10:25 +00:00
|
|
|
pActor->SetXY( fX, fY );
|
|
|
|
|
pActor->SetZ( fZ );
|
2003-07-09 00:49:05 +00:00
|
|
|
|
2005-10-04 19:45:45 +00:00
|
|
|
if( cache->m_fNoteColorTextureCoordSpacing[NotePart_HoldHead] != g_emptyVector )
|
|
|
|
|
{
|
|
|
|
|
DISPLAY->TexturePushMatrix();
|
|
|
|
|
NoteType nt = GetNoteType( iRow );
|
2005-10-04 20:32:11 +00:00
|
|
|
DISPLAY->TextureTranslate( cache->m_fNoteColorTextureCoordSpacing[NotePart_HoldHead]*(float)nt );
|
2005-10-04 19:45:45 +00:00
|
|
|
}
|
|
|
|
|
|
2003-07-17 06:10:25 +00:00
|
|
|
if( bGlow )
|
|
|
|
|
{
|
|
|
|
|
pActor->SetDiffuse( RageColor(1,1,1,0) );
|
|
|
|
|
pActor->SetGlow( colorGlow );
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
pActor->SetDiffuse( colorDiffuse );
|
|
|
|
|
pActor->SetGlow( RageColor(0,0,0,0) );
|
|
|
|
|
}
|
2003-07-10 03:38:45 +00:00
|
|
|
|
2003-12-31 08:15:34 +00:00
|
|
|
if( cache->m_bHoldHeadUseLighting )
|
2003-07-17 06:10:25 +00:00
|
|
|
{
|
|
|
|
|
DISPLAY->SetLighting( true );
|
|
|
|
|
DISPLAY->SetLightDirectional(
|
|
|
|
|
0,
|
2003-12-31 03:42:59 +00:00
|
|
|
RageColor(1,1,1,1),
|
2003-07-17 06:10:25 +00:00
|
|
|
RageColor(1,1,1,1),
|
|
|
|
|
RageColor(1,1,1,1),
|
|
|
|
|
RageVector3(1, 0, +1) );
|
|
|
|
|
}
|
2003-07-10 03:38:45 +00:00
|
|
|
|
2003-07-17 06:10:25 +00:00
|
|
|
pActor->Draw();
|
2003-07-10 03:38:45 +00:00
|
|
|
|
2003-12-31 08:15:34 +00:00
|
|
|
if( cache->m_bHoldHeadUseLighting )
|
2003-07-17 06:10:25 +00:00
|
|
|
{
|
|
|
|
|
DISPLAY->SetLightOff( 0 );
|
|
|
|
|
DISPLAY->SetLighting( false );
|
2003-02-08 23:47:47 +00:00
|
|
|
}
|
2005-10-04 19:45:45 +00:00
|
|
|
|
|
|
|
|
if( cache->m_fNoteColorTextureCoordSpacing[NotePart_HoldHead] != g_emptyVector )
|
|
|
|
|
{
|
|
|
|
|
DISPLAY->TexturePopMatrix();
|
|
|
|
|
}
|
2003-07-17 06:10:25 +00:00
|
|
|
}
|
|
|
|
|
|
2005-04-07 01:41:16 +00:00
|
|
|
void NoteDisplay::DrawHold( const TapNote &tn, int iCol, int iRow, bool bIsBeingHeld, bool bIsActive, const HoldNoteResult &Result, float fPercentFadeToFail, bool bDrawGlowOnly, float fReverseOffsetPixels, float fYStartOffset, float fYEndOffset )
|
2003-07-17 06:10:25 +00:00
|
|
|
{
|
2005-04-07 06:41:02 +00:00
|
|
|
int iEndRow = iRow + tn.iDuration;
|
2005-01-25 05:45:51 +00:00
|
|
|
|
2003-07-17 06:10:25 +00:00
|
|
|
// bDrawGlowOnly is a little hacky. We need to draw the diffuse part and the glow part one pass at a time to minimize state changes
|
|
|
|
|
|
2005-02-01 20:57:16 +00:00
|
|
|
bool bReverse = m_pPlayerState->m_CurrentPlayerOptions.GetReversePercentForColumn(iCol) > 0.5f;
|
2005-04-07 01:41:16 +00:00
|
|
|
float fStartBeat = NoteRowToBeat( max(tn.HoldResult.iLastHeldRow, iRow) );
|
2005-04-07 06:41:02 +00:00
|
|
|
float fThrowAway = 0;
|
2004-01-01 02:14:01 +00:00
|
|
|
|
2005-04-07 06:41:02 +00:00
|
|
|
// HACK: If active, don't set YOffset to 0 so that it doesn't jiggle around the receptor.
|
|
|
|
|
bool bStartIsPastPeak = true;
|
|
|
|
|
float fStartYOffset = 0;
|
|
|
|
|
if( bIsActive )
|
|
|
|
|
; // use the default values filled in above
|
|
|
|
|
else
|
|
|
|
|
fStartYOffset = ArrowEffects::GetYOffset( m_pPlayerState, iCol, fStartBeat, fThrowAway, bStartIsPastPeak );
|
|
|
|
|
|
2004-12-20 06:25:59 +00:00
|
|
|
float fStartYPos = ArrowEffects::GetYPos( m_pPlayerState, iCol, fStartYOffset, fReverseOffsetPixels );
|
2005-04-07 06:41:02 +00:00
|
|
|
float fEndPeakYOffset = 0;
|
|
|
|
|
bool bEndIsPastPeak = false;
|
|
|
|
|
float fEndYOffset = ArrowEffects::GetYOffset( m_pPlayerState, iCol, NoteRowToBeat(iEndRow), fEndPeakYOffset, bEndIsPastPeak );
|
|
|
|
|
|
|
|
|
|
// In boomerang, the arrows reverse direction at Y offset value fPeakAtYOffset.
|
|
|
|
|
// If fPeakAtYOffset lies inside of the hold we're drawing, then the we
|
|
|
|
|
// want to draw the tail at that max Y offset, or else the hold will appear
|
|
|
|
|
// to magically grow as the tail approaches the max Y offset.
|
|
|
|
|
if( bStartIsPastPeak && !bEndIsPastPeak )
|
|
|
|
|
fEndYOffset = fEndPeakYOffset; // use the calculated PeakYOffset so that long holds don't appear to grow
|
|
|
|
|
|
2004-12-20 06:25:59 +00:00
|
|
|
float fEndYPos = ArrowEffects::GetYPos( m_pPlayerState, iCol, fEndYOffset, fReverseOffsetPixels );
|
2003-07-17 06:10:25 +00:00
|
|
|
|
|
|
|
|
const float fYHead = bReverse ? fEndYPos : fStartYPos; // the center of the head
|
|
|
|
|
const float fYTail = bReverse ? fStartYPos : fEndYPos; // the center the tail
|
|
|
|
|
|
|
|
|
|
// const bool bWavy = GAMESTATE->m_PlayerOptions[m_PlayerNumber].m_fEffects[PlayerOptions::EFFECT_DRUNK] > 0;
|
2004-12-20 06:25:59 +00:00
|
|
|
const bool WavyPartsNeedZBuffer = ArrowEffects::NeedZBuffer( m_pPlayerState );
|
2003-07-17 06:10:25 +00:00
|
|
|
/* Hack: Z effects need a finer grain step. */
|
|
|
|
|
const int fYStep = WavyPartsNeedZBuffer? 4: 16; //bWavy ? 16 : 128; // use small steps only if wavy
|
|
|
|
|
|
2005-01-25 05:45:51 +00:00
|
|
|
const float fColorScale = tn.HoldResult.fLife + (1-tn.HoldResult.fLife)*cache->m_fHoldNGGrayPercent;
|
2003-07-17 06:10:25 +00:00
|
|
|
|
2003-10-19 07:47:16 +00:00
|
|
|
bool bFlipHeadAndTail = bReverse && cache->m_bFlipHeadAndTailWhenReverse;
|
|
|
|
|
|
2003-07-17 06:10:25 +00:00
|
|
|
/* The body and caps should have no overlap, so their order doesn't matter.
|
|
|
|
|
* Draw the head last, so it appears on top. */
|
2003-07-17 07:37:56 +00:00
|
|
|
if( !cache->m_bHoldHeadIsAboveWavyParts )
|
2005-04-07 01:41:16 +00:00
|
|
|
DrawHoldHead( tn, iCol, iRow, bIsBeingHeld, bFlipHeadAndTail ? fYTail : fYHead, fPercentFadeToFail, fColorScale, bDrawGlowOnly, fYStartOffset, fYEndOffset );
|
2003-07-17 07:37:56 +00:00
|
|
|
if( !cache->m_bHoldTailIsAboveWavyParts )
|
2005-04-07 01:41:16 +00:00
|
|
|
DrawHoldTail( tn, iCol, iRow, bIsBeingHeld, bFlipHeadAndTail ? fYHead : fYTail, fPercentFadeToFail, fColorScale, bDrawGlowOnly, fYStartOffset, fYEndOffset );
|
2003-07-17 07:37:56 +00:00
|
|
|
|
2003-07-17 06:10:25 +00:00
|
|
|
if( bDrawGlowOnly )
|
|
|
|
|
DISPLAY->SetTextureModeGlow();
|
|
|
|
|
else
|
|
|
|
|
DISPLAY->SetTextureModeModulate();
|
2004-05-15 18:35:03 +00:00
|
|
|
DISPLAY->SetZTestMode( WavyPartsNeedZBuffer?ZTEST_WRITE_ON_PASS:ZTEST_OFF );
|
|
|
|
|
DISPLAY->SetZWrite( WavyPartsNeedZBuffer );
|
2004-01-01 00:03:14 +00:00
|
|
|
|
|
|
|
|
if( !bFlipHeadAndTail )
|
2005-04-07 01:41:16 +00:00
|
|
|
DrawHoldBottomCap( tn, iCol, iRow, bIsBeingHeld, fYHead, fYTail, fYStep, fPercentFadeToFail, fColorScale, bDrawGlowOnly, fYStartOffset, fYEndOffset );
|
|
|
|
|
DrawHoldBody( tn, iCol, iRow, bIsBeingHeld, fYHead, fYTail, fYStep, fPercentFadeToFail, fColorScale, bDrawGlowOnly, fYStartOffset, fYEndOffset );
|
2004-01-01 00:03:14 +00:00
|
|
|
if( bFlipHeadAndTail )
|
2005-04-07 01:41:16 +00:00
|
|
|
DrawHoldTopCap( tn, iCol, iRow, bIsBeingHeld, fYHead, fYTail, fYStep, fPercentFadeToFail, fColorScale, bDrawGlowOnly, fYStartOffset, fYEndOffset );
|
2003-07-17 06:10:25 +00:00
|
|
|
|
|
|
|
|
/* These set the texture mode themselves. */
|
2003-07-17 07:37:56 +00:00
|
|
|
if( cache->m_bHoldTailIsAboveWavyParts )
|
2005-04-07 01:41:16 +00:00
|
|
|
DrawHoldTail( tn, iCol, iRow, bIsBeingHeld, bFlipHeadAndTail ? fYHead : fYTail, fPercentFadeToFail, fColorScale, bDrawGlowOnly, fYStartOffset, fYEndOffset );
|
2003-07-17 07:37:56 +00:00
|
|
|
if( cache->m_bHoldHeadIsAboveWavyParts )
|
2005-04-07 01:41:16 +00:00
|
|
|
DrawHoldHead( tn, iCol, iRow, bIsBeingHeld, bFlipHeadAndTail ? fYTail : fYHead, fPercentFadeToFail, fColorScale, bDrawGlowOnly, fYStartOffset, fYEndOffset );
|
2002-09-17 23:02:37 +00:00
|
|
|
|
2002-09-02 21:59:58 +00:00
|
|
|
// now, draw the glow pass
|
2002-08-29 01:38:21 +00:00
|
|
|
if( !bDrawGlowOnly )
|
2005-04-07 01:41:16 +00:00
|
|
|
DrawHold( tn, iCol, iRow, bIsBeingHeld, bIsActive, Result, fPercentFadeToFail, true, fReverseOffsetPixels, fYStartOffset, fYEndOffset );
|
2002-08-13 23:26:46 +00:00
|
|
|
}
|
|
|
|
|
|
2005-10-04 19:45:45 +00:00
|
|
|
void NoteDisplay::DrawActor( Actor* pActor, int iCol, float fBeat, float fPercentFadeToFail, float fLife, float fReverseOffsetPixels, bool bUseLighting, NotePart part )
|
2002-08-13 23:26:46 +00:00
|
|
|
{
|
2004-12-20 06:25:59 +00:00
|
|
|
const float fYOffset = ArrowEffects::GetYOffset( m_pPlayerState, iCol, fBeat );
|
|
|
|
|
const float fYPos = ArrowEffects::GetYPos( m_pPlayerState, iCol, fYOffset, fReverseOffsetPixels );
|
|
|
|
|
const float fRotation = ArrowEffects::GetRotation( m_pPlayerState, fBeat );
|
|
|
|
|
const float fXPos = ArrowEffects::GetXPos( m_pPlayerState, iCol, fYOffset );
|
|
|
|
|
const float fZPos = ArrowEffects::GetZPos( m_pPlayerState, iCol, fYOffset );
|
|
|
|
|
const float fAlpha = ArrowEffects::GetAlpha( m_pPlayerState, iCol, fYOffset, fPercentFadeToFail, m_fYReverseOffsetPixels );
|
|
|
|
|
const float fGlow = ArrowEffects::GetGlow( m_pPlayerState, iCol, fYOffset, fPercentFadeToFail, m_fYReverseOffsetPixels );
|
|
|
|
|
const float fColorScale = ArrowEffects::GetBrightness( m_pPlayerState, fBeat ) * SCALE(fLife,0,1,0.2f,1);
|
|
|
|
|
const float fZoom = ArrowEffects::GetZoom( m_pPlayerState );
|
2003-01-14 05:35:12 +00:00
|
|
|
RageColor diffuse = RageColor(fColorScale,fColorScale,fColorScale,fAlpha);
|
|
|
|
|
RageColor glow = RageColor(1,1,1,fGlow);
|
|
|
|
|
|
2003-08-10 06:00:30 +00:00
|
|
|
pActor->SetRotationZ( fRotation );
|
2003-05-09 04:42:04 +00:00
|
|
|
pActor->SetXY( fXPos, fYPos );
|
2003-07-09 00:49:05 +00:00
|
|
|
pActor->SetZ( fZPos );
|
2003-05-09 04:42:04 +00:00
|
|
|
pActor->SetDiffuse( diffuse );
|
|
|
|
|
pActor->SetGlow( glow );
|
2004-06-08 22:27:37 +00:00
|
|
|
pActor->SetZoom( fZoom );
|
2003-05-11 07:23:47 +00:00
|
|
|
|
2005-10-04 19:45:45 +00:00
|
|
|
if( cache->m_fNoteColorTextureCoordSpacing[part] != g_emptyVector )
|
|
|
|
|
{
|
|
|
|
|
DISPLAY->TexturePushMatrix();
|
|
|
|
|
NoteType nt = BeatToNoteType( fBeat );
|
2005-10-04 20:32:11 +00:00
|
|
|
DISPLAY->TextureTranslate( cache->m_fNoteColorTextureCoordSpacing[part]*(float)nt );
|
2005-10-04 19:45:45 +00:00
|
|
|
}
|
|
|
|
|
|
2003-12-31 08:15:34 +00:00
|
|
|
if( bUseLighting )
|
2003-05-13 13:35:32 +00:00
|
|
|
{
|
2003-05-15 06:09:19 +00:00
|
|
|
DISPLAY->SetLighting( true );
|
2003-05-13 13:35:32 +00:00
|
|
|
DISPLAY->SetLightDirectional(
|
|
|
|
|
0,
|
2003-12-31 03:42:59 +00:00
|
|
|
RageColor(1,1,1,1),
|
2003-05-13 13:35:32 +00:00
|
|
|
RageColor(1,1,1,1),
|
|
|
|
|
RageColor(1,1,1,1),
|
|
|
|
|
RageVector3(1, 0, +1) );
|
|
|
|
|
}
|
2003-05-11 07:23:47 +00:00
|
|
|
|
2003-05-09 04:42:04 +00:00
|
|
|
pActor->Draw();
|
2003-05-11 07:23:47 +00:00
|
|
|
|
2003-12-31 08:15:34 +00:00
|
|
|
if( bUseLighting )
|
2003-05-13 13:35:32 +00:00
|
|
|
{
|
|
|
|
|
DISPLAY->SetLightOff( 0 );
|
2003-05-15 06:09:19 +00:00
|
|
|
DISPLAY->SetLighting( false );
|
2003-05-13 13:35:32 +00:00
|
|
|
}
|
2005-10-04 19:45:45 +00:00
|
|
|
|
|
|
|
|
if( cache->m_fNoteColorTextureCoordSpacing[part] != g_emptyVector )
|
|
|
|
|
{
|
|
|
|
|
DISPLAY->TexturePopMatrix();
|
|
|
|
|
}
|
2003-01-14 05:35:12 +00:00
|
|
|
}
|
|
|
|
|
|
2003-11-15 08:51:47 +00:00
|
|
|
void NoteDisplay::DrawTap( int iCol, float fBeat, bool bOnSameRowAsHoldStart, bool bIsAddition, bool bIsMine, float fPercentFadeToFail, float fLife, float fReverseOffsetPixels )
|
|
|
|
|
{
|
|
|
|
|
Actor* pActor = NULL;
|
2003-12-31 08:15:34 +00:00
|
|
|
bool bUseLighting = false;
|
2003-11-15 08:51:47 +00:00
|
|
|
if( bIsMine )
|
2003-12-31 08:15:34 +00:00
|
|
|
{
|
2003-11-15 08:51:47 +00:00
|
|
|
pActor = GetTapMineActor( fBeat );
|
2003-12-31 08:15:34 +00:00
|
|
|
bUseLighting = cache->m_bTapMineUseLighting;
|
|
|
|
|
}
|
2003-11-15 08:51:47 +00:00
|
|
|
else if( bIsAddition )
|
2003-12-31 08:15:34 +00:00
|
|
|
{
|
2003-11-15 08:51:47 +00:00
|
|
|
pActor = GetTapAdditionActor( fBeat );
|
2003-12-31 08:15:34 +00:00
|
|
|
bUseLighting = cache->m_bTapAdditionUseLighting;
|
|
|
|
|
}
|
2003-11-15 08:51:47 +00:00
|
|
|
else if( bOnSameRowAsHoldStart && cache->m_bDrawHoldHeadForTapsOnSameRow )
|
2003-12-31 08:15:34 +00:00
|
|
|
{
|
2005-04-18 01:19:56 +00:00
|
|
|
pActor = GetHoldHeadActor( fBeat, false, false );
|
2003-12-31 08:15:34 +00:00
|
|
|
bUseLighting = cache->m_bHoldHeadUseLighting;
|
|
|
|
|
}
|
2003-11-15 08:51:47 +00:00
|
|
|
else
|
2003-12-31 08:15:34 +00:00
|
|
|
{
|
2003-11-15 08:51:47 +00:00
|
|
|
pActor = GetTapNoteActor( fBeat );
|
2003-12-31 08:15:34 +00:00
|
|
|
bUseLighting = cache->m_bTapNoteUseLighting;
|
|
|
|
|
}
|
2003-11-15 08:51:47 +00:00
|
|
|
|
2005-10-04 19:45:45 +00:00
|
|
|
DrawActor( pActor, iCol, fBeat, fPercentFadeToFail, fLife, fReverseOffsetPixels, bUseLighting, NotePart_Tap );
|
2003-11-15 08:51:47 +00:00
|
|
|
}
|
2004-06-08 00:08:04 +00:00
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* (c) 2001-2004 Brian Bugh, Ben Nordstrom, Chris Danford
|
|
|
|
|
* All rights reserved.
|
|
|
|
|
*
|
|
|
|
|
* Permission is hereby granted, free of charge, to any person obtaining a
|
|
|
|
|
* copy of this software and associated documentation files (the
|
|
|
|
|
* "Software"), to deal in the Software without restriction, including
|
|
|
|
|
* without limitation the rights to use, copy, modify, merge, publish,
|
|
|
|
|
* distribute, and/or sell copies of the Software, and to permit persons to
|
|
|
|
|
* whom the Software is furnished to do so, provided that the above
|
|
|
|
|
* copyright notice(s) and this permission notice appear in all copies of
|
|
|
|
|
* the Software and that both the above copyright notice(s) and this
|
|
|
|
|
* permission notice appear in supporting documentation.
|
|
|
|
|
*
|
|
|
|
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
|
|
|
|
|
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
|
|
|
|
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF
|
|
|
|
|
* THIRD PARTY RIGHTS. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR HOLDERS
|
|
|
|
|
* INCLUDED IN THIS NOTICE BE LIABLE FOR ANY CLAIM, OR ANY SPECIAL INDIRECT
|
|
|
|
|
* OR CONSEQUENTIAL DAMAGES, OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS
|
|
|
|
|
* OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
|
|
|
|
|
* OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
|
|
|
|
|
* PERFORMANCE OF THIS SOFTWARE.
|
|
|
|
|
*/
|