From 2656123464656510681d5081d53e62f3227de5ad Mon Sep 17 00:00:00 2001 From: Kyzentun Date: Fri, 24 Apr 2015 15:55:54 -0600 Subject: [PATCH] RageTextureManager now keeps a map of textures by pointer for quicker lookup when deleting. RageTextureManager now keeps a map of textures that need updating, which is none of them because I couldn't find a class that inherits from RageTexture that doesn't have an empty Update function. ArrowEffects now requires setting the current PlayerOptions before calling any functions. This might make moving to per-column mods easier, and reduces the direct usage of PlayerState. Tipsy calculations for each column are done in ArrowEffects::Update instead of GetYPos and GetYOffset. DrawHold changed to only call DrawHoldBody once. DrawHoldBody now does the normal and glow passes together instead of needing to be called twice. DrawHoldPart changed to take most of its args in a struct. Giant copy paste mess that NoteField was using to draw timing segment text replaced with a couple functions and a macro. Selection glow for notefield is only calculated if a section is selected. Added RageVector3 functions to CubicSplineN for NoteDisplay to use. Actor effect period is cached now. Sprites and Models cache their animation length now. ReceptorArrowRow no longer calls ArrowEffects::Update in gameplay. --- src/Actor.cpp | 189 +++++++--------- src/Actor.h | 7 +- src/ArrowEffects.cpp | 235 ++++++++++++-------- src/ArrowEffects.h | 33 +-- src/CubicSpline.cpp | 14 ++ src/CubicSpline.h | 3 + src/Model.cpp | 16 +- src/Model.h | 5 +- src/NoteDisplay.cpp | 401 +++++++++++++++++---------------- src/NoteDisplay.h | 59 +++-- src/NoteField.cpp | 438 ++++++++----------------------------- src/NoteField.h | 21 +- src/Player.cpp | 4 +- src/RageTextureManager.cpp | 53 ++++- src/RageTextureManager.h | 2 + src/RageTimer.h | 6 +- src/ReceptorArrowRow.cpp | 9 +- src/ScreenGameplay.cpp | 3 - src/Sprite.cpp | 17 +- src/Sprite.h | 7 +- 20 files changed, 699 insertions(+), 823 deletions(-) diff --git a/src/Actor.cpp b/src/Actor.cpp index 10c51a967f..590436d168 100644 --- a/src/Actor.cpp +++ b/src/Actor.cpp @@ -17,6 +17,7 @@ #include static Preference g_bShowMasks("ShowMasks", false); +static const float default_effect_period= 1.0f; /** * @brief Set up a hidden Actor that won't be drawn. @@ -107,10 +108,7 @@ void Actor::InitState() #endif m_fSecsIntoEffect = 0; m_fEffectDelta = 0; - m_fEffectRampUp = 0.5f; - m_fEffectHoldAtHalf = 0; - m_fEffectRampDown = 0.5f; - m_fEffectHoldAtZero = 0; + SetEffectPeriod(default_effect_period); m_fEffectOffset = 0; m_EffectClock = CLOCK_TIMER; m_vEffectMagnitude = RageVector3(0,0,10); @@ -229,6 +227,7 @@ Actor::Actor( const Actor &cpy ): CPY( m_fEffectHoldAtHalf ); CPY( m_fEffectRampDown ); CPY( m_fEffectHoldAtZero ); + CPY(m_effect_period); CPY( m_fEffectOffset ); CPY( m_EffectClock ); @@ -801,7 +800,9 @@ void Actor::Update( float fDeltaTime ) { m_fHibernateSecondsLeft -= fDeltaTime; if( m_fHibernateSecondsLeft > 0 ) + { return; + } // Grab the leftover time. fDeltaTime = -m_fHibernateSecondsLeft; @@ -815,69 +816,65 @@ void Actor::Update( float fDeltaTime ) this->UpdateInternal( fDeltaTime ); } -void Actor::UpdateInternal( float fDeltaTime ) +static void generic_global_timer_update(float new_time, float& effect_delta_time, float& time_into_effect) +{ + effect_delta_time= new_time - time_into_effect; + time_into_effect= new_time; +} + +void Actor::UpdateInternal(float delta_time) { if( m_bFirstUpdate ) m_bFirstUpdate = false; - switch( m_EffectClock ) + switch(m_EffectClock) { - case CLOCK_TIMER: - m_fSecsIntoEffect += fDeltaTime; - m_fEffectDelta = fDeltaTime; - - /* Wrap the counter, so it doesn't increase indefinitely (causing loss - * of precision if a screen is left to sit for a day). */ - if( m_fSecsIntoEffect >= GetEffectPeriod() ) - m_fSecsIntoEffect -= GetEffectPeriod(); - break; - - case CLOCK_TIMER_GLOBAL: - { - float fTime = RageTimer::GetTimeSinceStartFast(); - m_fEffectDelta = fTime - m_fSecsIntoEffect; - m_fSecsIntoEffect = fTime; - break; - } - - case CLOCK_BGM_BEAT: - m_fEffectDelta = g_fCurrentBGMBeat - m_fSecsIntoEffect; - m_fSecsIntoEffect = g_fCurrentBGMBeat; - break; - - case CLOCK_BGM_BEAT_PLAYER1: - m_fEffectDelta = g_vfCurrentBGMBeatPlayer[PLAYER_1] - m_fSecsIntoEffect; - m_fSecsIntoEffect = g_vfCurrentBGMBeatPlayerNoOffset[PLAYER_1]; - break; - - case CLOCK_BGM_BEAT_PLAYER2: - m_fEffectDelta = g_vfCurrentBGMBeatPlayer[PLAYER_2] - m_fSecsIntoEffect; - m_fSecsIntoEffect = g_vfCurrentBGMBeatPlayerNoOffset[PLAYER_2]; - break; - - case CLOCK_BGM_TIME: - m_fEffectDelta = g_fCurrentBGMTime - m_fSecsIntoEffect; - m_fSecsIntoEffect = g_fCurrentBGMTime; - break; - - case CLOCK_BGM_BEAT_NO_OFFSET: - m_fEffectDelta = g_fCurrentBGMBeatNoOffset - m_fSecsIntoEffect; - m_fSecsIntoEffect = g_fCurrentBGMBeatNoOffset; - break; - - case CLOCK_BGM_TIME_NO_OFFSET: - m_fEffectDelta = g_fCurrentBGMTimeNoOffset - m_fSecsIntoEffect; - m_fSecsIntoEffect = g_fCurrentBGMTimeNoOffset; - break; - - default: - if( m_EffectClock >= CLOCK_LIGHT_1 && m_EffectClock <= CLOCK_LIGHT_LAST ) - { - int i = m_EffectClock - CLOCK_LIGHT_1; - m_fEffectDelta = g_fCabinetLights[i] - m_fSecsIntoEffect; - m_fSecsIntoEffect = g_fCabinetLights[i]; - } - break; + case CLOCK_TIMER: + m_fSecsIntoEffect+= delta_time; + m_fEffectDelta= delta_time; + // Wrap the counter, so it doesn't increase indefinitely (causing loss + // of precision if a screen is left to sit for a day). + if(m_fSecsIntoEffect > GetEffectPeriod()) + { + m_fSecsIntoEffect-= GetEffectPeriod(); + } + break; + case CLOCK_TIMER_GLOBAL: + generic_global_timer_update(RageTimer::GetUsecsSinceStart(), + m_fEffectDelta, m_fSecsIntoEffect); + break; + case CLOCK_BGM_BEAT: + generic_global_timer_update(g_fCurrentBGMBeat, + m_fEffectDelta, m_fSecsIntoEffect); + break; + case CLOCK_BGM_BEAT_PLAYER1: + generic_global_timer_update(g_vfCurrentBGMBeatPlayer[PLAYER_1], + m_fEffectDelta, m_fSecsIntoEffect); + break; + case CLOCK_BGM_BEAT_PLAYER2: + generic_global_timer_update(g_vfCurrentBGMBeatPlayer[PLAYER_2], + m_fEffectDelta, m_fSecsIntoEffect); + break; + case CLOCK_BGM_TIME: + generic_global_timer_update(g_fCurrentBGMTime, + m_fEffectDelta, m_fSecsIntoEffect); + break; + case CLOCK_BGM_BEAT_NO_OFFSET: + generic_global_timer_update(g_fCurrentBGMBeatNoOffset, + m_fEffectDelta, m_fSecsIntoEffect); + break; + case CLOCK_BGM_TIME_NO_OFFSET: + generic_global_timer_update(g_fCurrentBGMTimeNoOffset, + m_fEffectDelta, m_fSecsIntoEffect); + break; + default: + if(m_EffectClock >= CLOCK_LIGHT_1 && m_EffectClock <= CLOCK_LIGHT_LAST) + { + generic_global_timer_update( + g_fCabinetLights[m_EffectClock - CLOCK_LIGHT_1], + m_fEffectDelta, m_fSecsIntoEffect); + } + break; } // update effect @@ -893,7 +890,7 @@ void Actor::UpdateInternal( float fDeltaTime ) default: break; } - this->UpdateTweening( fDeltaTime ); + this->UpdateTweening(delta_time); } RString Actor::GetLineage() const @@ -1073,11 +1070,8 @@ void Actor::SetEffectPeriod( float fTime ) m_fEffectHoldAtHalf = 0; m_fEffectRampDown = fTime/2; m_fEffectHoldAtZero = 0; -} - -float Actor::GetEffectPeriod() const -{ - return m_fEffectRampUp + m_fEffectHoldAtHalf + m_fEffectRampDown + m_fEffectHoldAtZero; + m_effect_period= m_fEffectRampUp + m_fEffectHoldAtHalf + m_fEffectRampDown + + m_fEffectHoldAtZero; } void Actor::SetEffectTiming( float fRampUp, float fAtHalf, float fRampDown, float fAtZero ) @@ -1091,19 +1085,26 @@ void Actor::SetEffectTiming( float fRampUp, float fAtHalf, float fRampDown, floa m_fEffectHoldAtHalf = fAtHalf; m_fEffectRampDown = fRampDown; m_fEffectHoldAtZero = fAtZero; + m_effect_period= m_fEffectRampUp + m_fEffectHoldAtHalf + m_fEffectRampDown + + m_fEffectHoldAtZero; } // effect "macros" +void Actor::ResetEffectTimeIfDifferent(Effect new_effect) +{ + if(m_Effect != new_effect) + { + m_Effect= new_effect; + m_fSecsIntoEffect = 0; + } +} + void Actor::SetEffectDiffuseBlink( float fEffectPeriodSeconds, RageColor c1, RageColor c2 ) { ASSERT( fEffectPeriodSeconds > 0 ); // todo: account for SSC_FUTURES -aj - if( m_Effect != diffuse_blink ) - { - m_Effect = diffuse_blink; - m_fSecsIntoEffect = 0; - } + ResetEffectTimeIfDifferent(diffuse_blink); SetEffectPeriod( fEffectPeriodSeconds ); m_effectColor1 = c1; m_effectColor2 = c2; @@ -1113,11 +1114,7 @@ void Actor::SetEffectDiffuseShift( float fEffectPeriodSeconds, RageColor c1, Rag { ASSERT( fEffectPeriodSeconds > 0 ); // todo: account for SSC_FUTURES -aj - if( m_Effect != diffuse_shift ) - { - m_Effect = diffuse_shift; - m_fSecsIntoEffect = 0; - } + ResetEffectTimeIfDifferent(diffuse_shift); SetEffectPeriod( fEffectPeriodSeconds ); m_effectColor1 = c1; m_effectColor2 = c2; @@ -1127,11 +1124,7 @@ void Actor::SetEffectDiffuseRamp( float fEffectPeriodSeconds, RageColor c1, Rage { ASSERT( fEffectPeriodSeconds > 0 ); // todo: account for SSC_FUTURES -aj - if( m_Effect != diffuse_ramp ) - { - m_Effect = diffuse_ramp; - m_fSecsIntoEffect = 0; - } + ResetEffectTimeIfDifferent(diffuse_ramp); SetEffectPeriod( fEffectPeriodSeconds ); m_effectColor1 = c1; m_effectColor2 = c2; @@ -1141,11 +1134,7 @@ void Actor::SetEffectGlowBlink( float fEffectPeriodSeconds, RageColor c1, RageCo { ASSERT( fEffectPeriodSeconds > 0 ); // todo: account for SSC_FUTURES -aj - if( m_Effect != glow_blink ) - { - m_Effect = glow_blink; - m_fSecsIntoEffect = 0; - } + ResetEffectTimeIfDifferent(glow_blink); SetEffectPeriod( fEffectPeriodSeconds ); m_effectColor1 = c1; m_effectColor2 = c2; @@ -1155,11 +1144,7 @@ void Actor::SetEffectGlowShift( float fEffectPeriodSeconds, RageColor c1, RageCo { ASSERT( fEffectPeriodSeconds > 0 ); // todo: account for SSC_FUTURES -aj - if( m_Effect != glow_shift ) - { - m_Effect = glow_shift; - m_fSecsIntoEffect = 0; - } + ResetEffectTimeIfDifferent(glow_shift); SetEffectPeriod( fEffectPeriodSeconds ); m_effectColor1 = c1; m_effectColor2 = c2; @@ -1169,11 +1154,7 @@ void Actor::SetEffectGlowRamp( float fEffectPeriodSeconds, RageColor c1, RageCol { ASSERT( fEffectPeriodSeconds > 0 ); // todo: account for SSC_FUTURES -aj - if( m_Effect != glow_ramp ) - { - m_Effect = glow_ramp; - m_fSecsIntoEffect = 0; - } + ResetEffectTimeIfDifferent(glow_ramp); SetEffectPeriod( fEffectPeriodSeconds ); m_effectColor1 = c1; m_effectColor2 = c2; @@ -1183,11 +1164,7 @@ void Actor::SetEffectRainbow( float fEffectPeriodSeconds ) { ASSERT( fEffectPeriodSeconds > 0 ); // todo: account for SSC_FUTURES -aj - if( m_Effect != rainbow ) - { - m_Effect = rainbow; - m_fSecsIntoEffect = 0; - } + ResetEffectTimeIfDifferent(rainbow); SetEffectPeriod( fEffectPeriodSeconds ); } @@ -1195,11 +1172,7 @@ void Actor::SetEffectWag( float fPeriod, RageVector3 vect ) { ASSERT( fPeriod > 0 ); // todo: account for SSC_FUTURES -aj - if( m_Effect != wag ) - { - m_Effect = wag; - m_fSecsIntoEffect = 0; - } + ResetEffectTimeIfDifferent(wag); SetEffectPeriod( fPeriod ); m_vEffectMagnitude = vect; } diff --git a/src/Actor.h b/src/Actor.h index ccce22d864..2b0a540712 100644 --- a/src/Actor.h +++ b/src/Actor.h @@ -527,7 +527,7 @@ public: void SetEffectColor1( RageColor c ) { m_effectColor1 = c; } void SetEffectColor2( RageColor c ) { m_effectColor2 = c; } void SetEffectPeriod( float fTime ); - float GetEffectPeriod() const; + float GetEffectPeriod() const { return m_effect_period; } void SetEffectTiming( float fRampUp, float fAtHalf, float fRampDown, float fAtZero ); void SetEffectOffset( float fTime ) { m_fEffectOffset = fTime; } void SetEffectClock( EffectClock c ) { m_EffectClock = c; } @@ -536,6 +536,7 @@ public: void SetEffectMagnitude( RageVector3 vec ) { m_vEffectMagnitude = vec; } RageVector3 GetEffectMagnitude() const { return m_vEffectMagnitude; } + void ResetEffectTimeIfDifferent(Effect new_effect); void SetEffectDiffuseBlink( float fEffectPeriodSeconds, RageColor c1, RageColor c2 ); void SetEffectDiffuseShift( float fEffectPeriodSeconds, RageColor c1, RageColor c2 ); void SetEffectDiffuseRamp( float fEffectPeriodSeconds, RageColor c1, RageColor c2 ); @@ -690,6 +691,10 @@ protected: float m_fEffectRampDown; float m_fEffectHoldAtZero; float m_fEffectOffset; + // Anything changing ramp_up, hold_at_half, ramp_down, or hold_at_zero must + // also update the period so the period is only calculated when changed. + // -Kyz + float m_effect_period; EffectClock m_EffectClock; /* This can be used in lieu of the fDeltaTime parameter to Update() to diff --git a/src/ArrowEffects.cpp b/src/ArrowEffects.cpp index ae0ee06754..88b814c9a0 100644 --- a/src/ArrowEffects.cpp +++ b/src/ArrowEffects.cpp @@ -60,11 +60,13 @@ static ThemeMetric TINY_PERCENT_BASE( "ArrowEffects", "TinyPercentBase" ) static ThemeMetric TINY_PERCENT_GATE( "ArrowEffects", "TinyPercentGate" ); static ThemeMetric DIZZY_HOLD_HEADS( "ArrowEffects", "DizzyHoldHeads" ); -float ArrowGetPercentVisible( const PlayerState* pPlayerState, float fYPosWithoutReverse ); +static const PlayerOptions* curr_options= NULL; -static float GetNoteFieldHeight( const PlayerState* pPlayerState ) +float ArrowGetPercentVisible(float fYPosWithoutReverse); + +static float GetNoteFieldHeight() { - return SCREEN_HEIGHT + fabsf(pPlayerState->m_PlayerOptions.GetCurrent().m_fPerspectiveTilt)*200; + return SCREEN_HEIGHT + fabsf(curr_options->m_fPerspectiveTilt)*200; } namespace @@ -74,6 +76,8 @@ namespace float m_fMinTornadoX[MAX_COLS_PER_PLAYER]; float m_fMaxTornadoX[MAX_COLS_PER_PLAYER]; float m_fInvertDistance[MAX_COLS_PER_PLAYER]; + float m_tipsy_result[MAX_COLS_PER_PLAYER]; + float m_tipsy_offset_result[MAX_COLS_PER_PLAYER]; float m_fBeatFactor; float m_fExpandSeconds; }; @@ -92,6 +96,7 @@ void ArrowEffects::Update() const SongPosition &position = GAMESTATE->m_bIsUsingStepTiming ? GAMESTATE->m_pPlayerState[pn]->m_Position : GAMESTATE->m_Position; const float field_zoom= GAMESTATE->m_pPlayerState[pn]->m_NotefieldZoom; + const float* effects= GAMESTATE->m_pPlayerState[pn]->m_PlayerOptions.GetCurrent().m_fEffects; PerPlayerData &data = g_EffectData[pn]; @@ -176,6 +181,34 @@ void ArrowEffects::Update() data.m_fInvertDistance[iColNum] = fNewPixelOffset - fOldPixelOffset; } + // Update Tipsy + if(effects[PlayerOptions::EFFECT_TIPSY] != 0) + { + const float time= RageTimer::GetTimeSinceStartFast(); + const float time_times_timer= time * TIPSY_TIMER_FREQUENCY; + const float arrow_times_mag= ARROW_SIZE * TIPSY_ARROW_MAGNITUDE; + const float time_times_offset_timer= time * + TIPSY_OFFSET_TIMER_FREQUENCY; + const float arrow_times_offset_mag= ARROW_SIZE * + TIPSY_OFFSET_ARROW_MAGNITUDE; + for(int col= 0; col < MAX_COLS_PER_PLAYER; ++col) + { + data.m_tipsy_result[col]= RageFastCos( + time_times_timer + (col * TIPSY_COLUMN_FREQUENCY)) * + arrow_times_mag; + data.m_tipsy_offset_result[col]= RageFastCos( + time_times_offset_timer + (col * TIPSY_OFFSET_COLUMN_FREQUENCY)) * + arrow_times_offset_mag; + } + } + else + { + for(int col= 0; col < MAX_COLS_PER_PLAYER; ++col) + { + data.m_tipsy_result[col]= 0; + } + } + // Update Beat do { float fAccelTime = 0.2f, fTotalTime = 0.5f; @@ -212,6 +245,11 @@ void ArrowEffects::Update() fLastTime = fTime; } +void ArrowEffects::SetCurrentOptions(const PlayerOptions* options) +{ + curr_options= options; +} + static float GetDisplayedBeat( const PlayerState* pPlayerState, float beat ) { // do a binary search here @@ -254,7 +292,7 @@ float ArrowEffects::GetYOffset( const PlayerState* pPlayerState, int iCol, float /* Usually, fTimeSpacing is 0 or 1, in which case we use entirely beat spacing or * entirely time spacing (respectively). Occasionally, we tween between them. */ - if( pPlayerState->m_PlayerOptions.GetCurrent().m_fTimeSpacing != 1.0f ) + if( curr_options->m_fTimeSpacing != 1.0f ) { if( GAMESTATE->m_bInStepEditor ) { // Use constant spacing in step editor @@ -265,18 +303,18 @@ float ArrowEffects::GetYOffset( const PlayerState* pPlayerState, int iCol, float position.m_fSongBeatVisible, position.m_fMusicSecondsVisible ); } - fYOffset *= 1 - pPlayerState->m_PlayerOptions.GetCurrent().m_fTimeSpacing; + fYOffset *= 1 - curr_options->m_fTimeSpacing; } - if( pPlayerState->m_PlayerOptions.GetCurrent().m_fTimeSpacing != 0.0f ) + if( curr_options->m_fTimeSpacing != 0.0f ) { float fSongSeconds = GAMESTATE->m_Position.m_fMusicSecondsVisible; float fNoteSeconds = pCurSteps->GetTimingData()->GetElapsedTimeFromBeat(fNoteBeat); float fSecondsUntilStep = fNoteSeconds - fSongSeconds; - float fBPM = pPlayerState->m_PlayerOptions.GetCurrent().m_fScrollBPM; + float fBPM = curr_options->m_fScrollBPM; float fBPS = fBPM/60.f / GAMESTATE->m_SongOptions.GetCurrent().m_fMusicRate; float fYOffsetTimeSpacing = fSecondsUntilStep * fBPS; - fYOffset += fYOffsetTimeSpacing * pPlayerState->m_PlayerOptions.GetCurrent().m_fTimeSpacing; + fYOffset += fYOffsetTimeSpacing * curr_options->m_fTimeSpacing; } // TODO: If we allow noteskins to have metricable row spacing @@ -284,25 +322,27 @@ float ArrowEffects::GetYOffset( const PlayerState* pPlayerState, int iCol, float fYOffset *= ARROW_SPACING; // Factor in scroll speed - float fScrollSpeed = pPlayerState->m_PlayerOptions.GetCurrent().m_fScrollSpeed; - if(pPlayerState->m_PlayerOptions.GetCurrent().m_fMaxScrollBPM != 0) + float fScrollSpeed = curr_options->m_fScrollSpeed; + if(curr_options->m_fMaxScrollBPM != 0) { - fScrollSpeed= pPlayerState->m_PlayerOptions.GetCurrent().m_fMaxScrollBPM / + fScrollSpeed= curr_options->m_fMaxScrollBPM / (pPlayerState->m_fReadBPM * GAMESTATE->m_SongOptions.GetCurrent().m_fMusicRate); } // don't mess with the arrows after they've crossed 0 if( fYOffset < 0 ) + { return fYOffset * fScrollSpeed; + } - const float* fAccels = pPlayerState->m_PlayerOptions.GetCurrent().m_fAccels; - //const float* fEffects = pPlayerState->m_PlayerOptions.GetCurrent().m_fEffects; + const float* fAccels = curr_options->m_fAccels; + //const float* fEffects = curr_options->m_fEffects; float fYAdjust = 0; // fill this in depending on PlayerOptions if( fAccels[PlayerOptions::ACCEL_BOOST] != 0 ) { - float fEffectHeight = GetNoteFieldHeight(pPlayerState); + float fEffectHeight = GetNoteFieldHeight(); float fNewYOffset = fYOffset * 1.5f / ((fYOffset+fEffectHeight/1.2f)/fEffectHeight); float fAccelYAdjust = fAccels[PlayerOptions::ACCEL_BOOST] * (fNewYOffset - fYOffset); // TRICKY: Clamp this value, or else BOOST+BOOMERANG will draw a ton of arrows on the screen. @@ -311,7 +351,7 @@ float ArrowEffects::GetYOffset( const PlayerState* pPlayerState, int iCol, float } if( fAccels[PlayerOptions::ACCEL_BRAKE] != 0 ) { - float fEffectHeight = GetNoteFieldHeight(pPlayerState); + float fEffectHeight = GetNoteFieldHeight(); float fScale = SCALE( fYOffset, 0.f, fEffectHeight, 0, 1.f ); float fNewYOffset = fYOffset * fScale; float fBrakeYAdjust = fAccels[PlayerOptions::ACCEL_BRAKE] * (fNewYOffset - fYOffset); @@ -334,7 +374,7 @@ float ArrowEffects::GetYOffset( const PlayerState* pPlayerState, int iCol, float fYOffset = (-1*fYOffset*fYOffset/SCREEN_HEIGHT) + 1.5f*fYOffset; } - if( pPlayerState->m_PlayerOptions.GetCurrent().m_fRandomSpeed > 0 && !bAbsolute ) + if( curr_options->m_fRandomSpeed > 0 && !bAbsolute ) { // Generate a deterministically "random" speed for each arrow. unsigned seed = GAMESTATE->m_iStageSeed + ( BeatToNoteRow( fNoteBeat ) << 8 ) + (iCol * 100); @@ -348,7 +388,7 @@ float ArrowEffects::GetYOffset( const PlayerState* pPlayerState, int iCol, float fScrollSpeed *= SCALE( fRandom, 0.0f, 1.0f, - 1.0f, pPlayerState->m_PlayerOptions.GetCurrent().m_fRandomSpeed + 1.0f ); + 1.0f, curr_options->m_fRandomSpeed + 1.0f ); } if( fAccels[PlayerOptions::ACCEL_EXPAND] != 0 ) @@ -370,43 +410,43 @@ float ArrowEffects::GetYOffset( const PlayerState* pPlayerState, int iCol, float return fYOffset; } -static void ArrowGetReverseShiftAndScale( const PlayerState* pPlayerState, int iCol, float fYReverseOffsetPixels, float &fShiftOut, float &fScaleOut ) +static void ArrowGetReverseShiftAndScale(int iCol, float fYReverseOffsetPixels, float &fShiftOut, float &fScaleOut) { // XXX: Hack: we need to scale the reverse shift by the zoom. - float fMiniPercent = pPlayerState->m_PlayerOptions.GetCurrent().m_fEffects[PlayerOptions::EFFECT_MINI]; + float fMiniPercent = curr_options->m_fEffects[PlayerOptions::EFFECT_MINI]; float fZoom = 1 - fMiniPercent*0.5f; // don't divide by 0 if( fabsf(fZoom) < 0.01 ) fZoom = 0.01f; - float fPercentReverse = pPlayerState->m_PlayerOptions.GetCurrent().GetReversePercentForColumn(iCol); + float fPercentReverse = curr_options->GetReversePercentForColumn(iCol); fShiftOut = SCALE( fPercentReverse, 0.f, 1.f, -fYReverseOffsetPixels/fZoom/2, fYReverseOffsetPixels/fZoom/2 ); - float fPercentCentered = pPlayerState->m_PlayerOptions.GetCurrent().m_fScrolls[PlayerOptions::SCROLL_CENTERED]; + float fPercentCentered = curr_options->m_fScrolls[PlayerOptions::SCROLL_CENTERED]; fShiftOut = SCALE( fPercentCentered, 0.f, 1.f, fShiftOut, 0.0f ); fScaleOut = SCALE( fPercentReverse, 0.f, 1.f, 1.f, -1.f ); } -float ArrowEffects::GetYPos( const PlayerState* pPlayerState, int iCol, float fYOffset, float fYReverseOffsetPixels, bool WithReverse ) +float ArrowEffects::GetYPos(int iCol, float fYOffset, float fYReverseOffsetPixels, bool WithReverse) { float f = fYOffset; if( WithReverse ) { float fShift, fScale; - ArrowGetReverseShiftAndScale( pPlayerState, iCol, fYReverseOffsetPixels, fShift, fScale ); + ArrowGetReverseShiftAndScale(iCol, fYReverseOffsetPixels, fShift, fScale); f *= fScale; f += fShift; } - const float* fEffects = pPlayerState->m_PlayerOptions.GetCurrent().m_fEffects; - - if( fEffects[PlayerOptions::EFFECT_TIPSY] != 0 ) - f += fEffects[PlayerOptions::EFFECT_TIPSY] - * ( RageFastCos( RageTimer::GetTimeSinceStartFast()*TIPSY_TIMER_FREQUENCY - + iCol*TIPSY_COLUMN_FREQUENCY) * ARROW_SIZE*TIPSY_ARROW_MAGNITUDE ); + const float* fEffects = curr_options->m_fEffects; + // Doing the math with a precalculated result of 0 should be faster than + // checking whether tipsy is on. -Kyz + // TODO: Don't index by PlayerNumber. + PerPlayerData& data= g_EffectData[curr_options->m_pn]; + f+= fEffects[PlayerOptions::EFFECT_TIPSY] * data.m_tipsy_result[iCol]; // In beware's DDR Extreme-focused fork of StepMania 3.9, this value is // floored, making arrows show on integer Y coordinates. Supposedly it makes @@ -415,18 +455,19 @@ float ArrowEffects::GetYPos( const PlayerState* pPlayerState, int iCol, float fY return QUANTIZE_ARROW_Y ? floor(f) : f; } -float ArrowEffects::GetYOffsetFromYPos( const PlayerState* pPlayerState, int iCol, float YPos, float fYReverseOffsetPixels ) +float ArrowEffects::GetYOffsetFromYPos(int iCol, float YPos, float fYReverseOffsetPixels) { float f = YPos; - const float* fEffects = pPlayerState->m_PlayerOptions.GetCurrent().m_fEffects; - if( fEffects[PlayerOptions::EFFECT_TIPSY] != 0 ) - f -= fEffects[PlayerOptions::EFFECT_TIPSY] - * ( RageFastCos( RageTimer::GetTimeSinceStartFast()*TIPSY_OFFSET_TIMER_FREQUENCY - + iCol*TIPSY_OFFSET_COLUMN_FREQUENCY) * ARROW_SIZE*TIPSY_OFFSET_ARROW_MAGNITUDE ); + const float* fEffects = curr_options->m_fEffects; + // Doing the math with a precalculated result of 0 should be faster than + // checking whether tipsy is on. -Kyz + // TODO: Don't index by PlayerNumber. + PerPlayerData& data= g_EffectData[curr_options->m_pn]; + f+= fEffects[PlayerOptions::EFFECT_TIPSY] * data.m_tipsy_offset_result[iCol]; float fShift, fScale; - ArrowGetReverseShiftAndScale( pPlayerState, iCol, fYReverseOffsetPixels, fShift, fScale ); + ArrowGetReverseShiftAndScale(iCol, fYReverseOffsetPixels, fShift, fScale); f -= fShift; if( fScale ) @@ -440,7 +481,7 @@ float ArrowEffects::GetXPos( const PlayerState* pPlayerState, int iColNum, float float fPixelOffsetFromCenter = 0; // fill this in below const Style* pStyle = GAMESTATE->GetCurrentStyle(pPlayerState->m_PlayerNumber); - const float* fEffects = pPlayerState->m_PlayerOptions.GetCurrent().m_fEffects; + const float* fEffects = curr_options->m_fEffects; // TODO: Don't index by PlayerNumber. const Style::ColumnInfo* pCols = pStyle->m_ColumnInfo[pPlayerState->m_PlayerNumber]; @@ -528,9 +569,9 @@ float ArrowEffects::GetXPos( const PlayerState* pPlayerState, int iColNum, float return fPixelOffsetFromCenter; } -float ArrowEffects::GetRotationX( const PlayerState *pPlayerState, float fYOffset ) +float ArrowEffects::GetRotationX(float fYOffset) { - const float* fEffects = pPlayerState->m_PlayerOptions.GetCurrent().m_fEffects; + const float* fEffects = curr_options->m_fEffects; float fRotation = 0; if( fEffects[PlayerOptions::EFFECT_ROLL] != 0 ) { @@ -539,9 +580,9 @@ float ArrowEffects::GetRotationX( const PlayerState *pPlayerState, float fYOffse return fRotation; } -float ArrowEffects::GetRotationY( const PlayerState *pPlayerState, float fYOffset ) +float ArrowEffects::GetRotationY(float fYOffset) { - const float* fEffects = pPlayerState->m_PlayerOptions.GetCurrent().m_fEffects; + const float* fEffects = curr_options->m_fEffects; float fRotation = 0; if( fEffects[PlayerOptions::EFFECT_TWIRL] != 0 ) { @@ -552,7 +593,7 @@ float ArrowEffects::GetRotationY( const PlayerState *pPlayerState, float fYOffse float ArrowEffects::GetRotationZ( const PlayerState* pPlayerState, float fNoteBeat, bool bIsHoldHead ) { - const float* fEffects = pPlayerState->m_PlayerOptions.GetCurrent().m_fEffects; + const float* fEffects = curr_options->m_fEffects; float fRotation = 0; if( fEffects[PlayerOptions::EFFECT_CONFUSION] != 0 ) fRotation += ReceptorGetRotationZ( pPlayerState ); @@ -572,7 +613,7 @@ float ArrowEffects::GetRotationZ( const PlayerState* pPlayerState, float fNoteBe float ArrowEffects::ReceptorGetRotationZ( const PlayerState* pPlayerState ) { - const float* fEffects = pPlayerState->m_PlayerOptions.GetCurrent().m_fEffects; + const float* fEffects = curr_options->m_fEffects; float fRotation = 0; if( fEffects[PlayerOptions::EFFECT_CONFUSION] != 0 ) @@ -589,18 +630,18 @@ float ArrowEffects::ReceptorGetRotationZ( const PlayerState* pPlayerState ) #define CENTER_LINE_Y 160 // from fYOffset == 0 #define FADE_DIST_Y 40 -static float GetCenterLine( const PlayerState* pPlayerState ) +static float GetCenterLine() { /* Another mini hack: if EFFECT_MINI is on, then our center line is at * eg. 320, not 160. */ - const float fMiniPercent = pPlayerState->m_PlayerOptions.GetCurrent().m_fEffects[PlayerOptions::EFFECT_MINI]; + const float fMiniPercent = curr_options->m_fEffects[PlayerOptions::EFFECT_MINI]; const float fZoom = 1 - fMiniPercent*0.5f; return CENTER_LINE_Y / fZoom; } -static float GetHiddenSudden( const PlayerState* pPlayerState ) +static float GetHiddenSudden() { - const float* fAppearances = pPlayerState->m_PlayerOptions.GetCurrent().m_fAppearances; + const float* fAppearances = curr_options->m_fAppearances; return fAppearances[PlayerOptions::APPEARANCE_HIDDEN] * fAppearances[PlayerOptions::APPEARANCE_SUDDEN]; } @@ -617,55 +658,55 @@ static float GetHiddenSudden( const PlayerState* pPlayerState ) // ...invisible... // // TRICKY: We fudge hidden and sudden to be farther apart if they're both on. -static float GetHiddenEndLine( const PlayerState* pPlayerState ) +static float GetHiddenEndLine() { - return GetCenterLine( pPlayerState ) + - FADE_DIST_Y * SCALE( GetHiddenSudden(pPlayerState), 0.f, 1.f, -1.0f, -1.25f ) + - GetCenterLine( pPlayerState ) * pPlayerState->m_PlayerOptions.GetCurrent().m_fAppearances[PlayerOptions::APPEARANCE_HIDDEN_OFFSET]; + return GetCenterLine() + + FADE_DIST_Y * SCALE( GetHiddenSudden(), 0.f, 1.f, -1.0f, -1.25f ) + + GetCenterLine() * curr_options->m_fAppearances[PlayerOptions::APPEARANCE_HIDDEN_OFFSET]; } -static float GetHiddenStartLine( const PlayerState* pPlayerState ) +static float GetHiddenStartLine() { - return GetCenterLine( pPlayerState ) + - FADE_DIST_Y * SCALE( GetHiddenSudden(pPlayerState), 0.f, 1.f, +0.0f, -0.25f ) + - GetCenterLine( pPlayerState ) * pPlayerState->m_PlayerOptions.GetCurrent().m_fAppearances[PlayerOptions::APPEARANCE_HIDDEN_OFFSET]; + return GetCenterLine() + + FADE_DIST_Y * SCALE( GetHiddenSudden(), 0.f, 1.f, +0.0f, -0.25f ) + + GetCenterLine() * curr_options->m_fAppearances[PlayerOptions::APPEARANCE_HIDDEN_OFFSET]; } -static float GetSuddenEndLine( const PlayerState* pPlayerState ) +static float GetSuddenEndLine() { - return GetCenterLine( pPlayerState ) + - FADE_DIST_Y * SCALE( GetHiddenSudden(pPlayerState), 0.f, 1.f, -0.0f, +0.25f ) + - GetCenterLine( pPlayerState ) * pPlayerState->m_PlayerOptions.GetCurrent().m_fAppearances[PlayerOptions::APPEARANCE_SUDDEN_OFFSET]; + return GetCenterLine() + + FADE_DIST_Y * SCALE( GetHiddenSudden(), 0.f, 1.f, -0.0f, +0.25f ) + + GetCenterLine() * curr_options->m_fAppearances[PlayerOptions::APPEARANCE_SUDDEN_OFFSET]; } -static float GetSuddenStartLine( const PlayerState* pPlayerState ) +static float GetSuddenStartLine() { - return GetCenterLine( pPlayerState ) + - FADE_DIST_Y * SCALE( GetHiddenSudden(pPlayerState), 0.f, 1.f, +1.0f, +1.25f ) + - GetCenterLine( pPlayerState ) * pPlayerState->m_PlayerOptions.GetCurrent().m_fAppearances[PlayerOptions::APPEARANCE_SUDDEN_OFFSET]; + return GetCenterLine() + + FADE_DIST_Y * SCALE( GetHiddenSudden(), 0.f, 1.f, +1.0f, +1.25f ) + + GetCenterLine() * curr_options->m_fAppearances[PlayerOptions::APPEARANCE_SUDDEN_OFFSET]; } // used by ArrowGetAlpha and ArrowGetGlow below -float ArrowGetPercentVisible( const PlayerState* pPlayerState, float fYPosWithoutReverse ) +float ArrowGetPercentVisible(float fYPosWithoutReverse) { - const float fDistFromCenterLine = fYPosWithoutReverse - GetCenterLine( pPlayerState ); + const float fDistFromCenterLine = fYPosWithoutReverse - GetCenterLine(); if( fYPosWithoutReverse < 0 && HIDDEN_SUDDEN_PAST_RECEPTOR) // past Gray Arrows return 1; // totally visible - const float* fAppearances = pPlayerState->m_PlayerOptions.GetCurrent().m_fAppearances; + const float* fAppearances = curr_options->m_fAppearances; float fVisibleAdjust = 0; if( fAppearances[PlayerOptions::APPEARANCE_HIDDEN] != 0 ) { - float fHiddenVisibleAdjust = SCALE( fYPosWithoutReverse, GetHiddenStartLine(pPlayerState), GetHiddenEndLine(pPlayerState), 0, -1 ); + float fHiddenVisibleAdjust = SCALE( fYPosWithoutReverse, GetHiddenStartLine(), GetHiddenEndLine(), 0, -1 ); CLAMP( fHiddenVisibleAdjust, -1, 0 ); fVisibleAdjust += fAppearances[PlayerOptions::APPEARANCE_HIDDEN] * fHiddenVisibleAdjust; } if( fAppearances[PlayerOptions::APPEARANCE_SUDDEN] != 0 ) { - float fSuddenVisibleAdjust = SCALE( fYPosWithoutReverse, GetSuddenStartLine(pPlayerState), GetSuddenEndLine(pPlayerState), -1, 0 ); + float fSuddenVisibleAdjust = SCALE( fYPosWithoutReverse, GetSuddenStartLine(), GetSuddenEndLine(), -1, 0 ); CLAMP( fSuddenVisibleAdjust, -1, 0 ); fVisibleAdjust += fAppearances[PlayerOptions::APPEARANCE_SUDDEN] * fSuddenVisibleAdjust; } @@ -688,12 +729,12 @@ float ArrowGetPercentVisible( const PlayerState* pPlayerState, float fYPosWithou return clamp( 1+fVisibleAdjust, 0, 1 ); } -float ArrowEffects::GetAlpha( const PlayerState* pPlayerState, int iCol, float fYOffset, float fPercentFadeToFail, float fYReverseOffsetPixels, float fDrawDistanceBeforeTargetsPixels, float fFadeInPercentOfDrawFar ) +float ArrowEffects::GetAlpha(int iCol, float fYOffset, float fPercentFadeToFail, float fYReverseOffsetPixels, float fDrawDistanceBeforeTargetsPixels, float fFadeInPercentOfDrawFar) { // Get the YPos without reverse (that is, factor in EFFECT_TIPSY). - float fYPosWithoutReverse = ArrowEffects::GetYPos( pPlayerState, iCol, fYOffset, fYReverseOffsetPixels, false ); + float fYPosWithoutReverse = ArrowEffects::GetYPos(iCol, fYOffset, fYReverseOffsetPixels, false ); - float fPercentVisible = ArrowGetPercentVisible( pPlayerState, fYPosWithoutReverse ); + float fPercentVisible = ArrowGetPercentVisible(fYPosWithoutReverse); if( fPercentFadeToFail != -1 ) fPercentVisible = 1 - fPercentFadeToFail; @@ -705,17 +746,15 @@ float ArrowEffects::GetAlpha( const PlayerState* pPlayerState, int iCol, float f float f = SCALE( fYPosWithoutReverse, fFullAlphaY, fDrawDistanceBeforeTargetsPixels, 1.0f, 0.0f ); return f; } - - return (fPercentVisible>0.5f) ? 1.0f : 0.0f; } -float ArrowEffects::GetGlow( const PlayerState* pPlayerState, int iCol, float fYOffset, float fPercentFadeToFail, float fYReverseOffsetPixels, float fDrawDistanceBeforeTargetsPixels, float fFadeInPercentOfDrawFar ) +float ArrowEffects::GetGlow(int iCol, float fYOffset, float fPercentFadeToFail, float fYReverseOffsetPixels, float fDrawDistanceBeforeTargetsPixels, float fFadeInPercentOfDrawFar) { // Get the YPos without reverse (that is, factor in EFFECT_TIPSY). - float fYPosWithoutReverse = ArrowEffects::GetYPos( pPlayerState, iCol, fYOffset, fYReverseOffsetPixels, false ); + float fYPosWithoutReverse = ArrowEffects::GetYPos(iCol, fYOffset, fYReverseOffsetPixels, false ); - float fPercentVisible = ArrowGetPercentVisible( pPlayerState, fYPosWithoutReverse ); + float fPercentVisible = ArrowGetPercentVisible(fYPosWithoutReverse ); if( fPercentFadeToFail != -1 ) fPercentVisible = 1 - fPercentFadeToFail; @@ -738,10 +777,10 @@ float ArrowEffects::GetBrightness( const PlayerState* pPlayerState, float fNoteB } -float ArrowEffects::GetZPos( const PlayerState* pPlayerState, int iCol, float fYOffset ) +float ArrowEffects::GetZPos(int iCol, float fYOffset) { float fZPos=0; - const float* fEffects = pPlayerState->m_PlayerOptions.GetCurrent().m_fEffects; + const float* fEffects = curr_options->m_fEffects; if( fEffects[PlayerOptions::EFFECT_BUMPY] != 0 ) fZPos += fEffects[PlayerOptions::EFFECT_BUMPY] * 40*RageFastSin( fYOffset/16.0f ); @@ -749,15 +788,16 @@ float ArrowEffects::GetZPos( const PlayerState* pPlayerState, int iCol, float fY return fZPos; } -bool ArrowEffects::NeedZBuffer( const PlayerState* pPlayerState ) +bool ArrowEffects::NeedZBuffer() { - const float* fEffects = pPlayerState->m_PlayerOptions.GetCurrent().m_fEffects; + const float* fEffects = curr_options->m_fEffects; // We also need to use the Z buffer if twirl is in play, because of // hold modulation. -vyhd (OpenITG r623) if( fEffects[PlayerOptions::EFFECT_BUMPY] != 0 || fEffects[PlayerOptions::EFFECT_TWIRL] != 0 ) + { return true; - + } return false; } @@ -770,7 +810,7 @@ float ArrowEffects::GetZoom( const PlayerState* pPlayerState ) // PlayerState. -Kyz fZoom*= pPlayerState->m_NotefieldZoom; - float fTinyPercent = pPlayerState->m_PlayerOptions.GetCurrent().m_fEffects[PlayerOptions::EFFECT_TINY]; + float fTinyPercent = curr_options->m_fEffects[PlayerOptions::EFFECT_TINY]; if( fTinyPercent != 0 ) { fTinyPercent = powf( 0.5f, fTinyPercent ); @@ -840,6 +880,7 @@ namespace int GetYOffset( lua_State *L ) { PlayerState *ps = Luna::check( L, 1 ); + ArrowEffects::SetCurrentOptions(&ps->m_PlayerOptions.GetCurrent()); float fPeakYOffset; bool bIsPastPeak; @@ -854,7 +895,8 @@ namespace { PlayerState *ps = Luna::check( L, 1 ); float fYReverseOffsetPixels = YReverseOffset( L, 4 ); - lua_pushnumber( L, ArrowEffects::GetYPos( ps, IArg(2)-1, FArg(3), fYReverseOffsetPixels ) ); + ArrowEffects::SetCurrentOptions(&ps->m_PlayerOptions.GetCurrent()); + lua_pushnumber(L, ArrowEffects::GetYPos(IArg(2)-1, FArg(3), fYReverseOffsetPixels)); return 1; } @@ -862,8 +904,9 @@ namespace int GetYOffsetFromYPos( lua_State *L ) { PlayerState *ps = Luna::check( L, 1 ); + ArrowEffects::SetCurrentOptions(&ps->m_PlayerOptions.GetCurrent()); float fYReverseOffsetPixels = YReverseOffset( L, 4 ); - lua_pushnumber( L, ArrowEffects::GetYOffsetFromYPos( ps, IArg(2)-1, FArg(3), fYReverseOffsetPixels ) ); + lua_pushnumber(L, ArrowEffects::GetYOffsetFromYPos(IArg(2)-1, FArg(3), fYReverseOffsetPixels)); return 1; } @@ -871,6 +914,7 @@ namespace int GetXPos( lua_State *L ) { PlayerState *ps = Luna::check( L, 1 ); + ArrowEffects::SetCurrentOptions(&ps->m_PlayerOptions.GetCurrent()); lua_pushnumber( L, ArrowEffects::GetXPos( ps, IArg(2)-1, FArg(3) ) ); return 1; } @@ -879,7 +923,8 @@ namespace int GetZPos( lua_State *L ) { PlayerState *ps = Luna::check( L, 1 ); - lua_pushnumber( L, ArrowEffects::GetZPos( ps, IArg(2)-1, FArg(3) ) ); + ArrowEffects::SetCurrentOptions(&ps->m_PlayerOptions.GetCurrent()); + lua_pushnumber(L, ArrowEffects::GetZPos(IArg(2)-1, FArg(3))); return 1; } @@ -887,7 +932,8 @@ namespace int GetRotationX( lua_State *L ) { PlayerState *ps = Luna::check( L, 1 ); - lua_pushnumber( L, ArrowEffects::GetRotationX( ps, FArg(2) ) ); + ArrowEffects::SetCurrentOptions(&ps->m_PlayerOptions.GetCurrent()); + lua_pushnumber(L, ArrowEffects::GetRotationX(FArg(2))); return 1; } @@ -895,7 +941,8 @@ namespace int GetRotationY( lua_State *L ) { PlayerState *ps = Luna::check( L, 1 ); - lua_pushnumber( L, ArrowEffects::GetRotationY( ps, FArg(2) ) ); + ArrowEffects::SetCurrentOptions(&ps->m_PlayerOptions.GetCurrent()); + lua_pushnumber(L, ArrowEffects::GetRotationY(FArg(2))); return 1; } @@ -903,6 +950,7 @@ namespace int GetRotationZ( lua_State *L ) { PlayerState *ps = Luna::check( L, 1 ); + ArrowEffects::SetCurrentOptions(&ps->m_PlayerOptions.GetCurrent()); // Make bIsHoldHead optional. bool bIsHoldHead = false; if( lua_gettop(L) >= 3 && !lua_isnil(L, 3) ) @@ -917,6 +965,7 @@ namespace int ReceptorGetRotationZ( lua_State *L ) { PlayerState *ps = Luna::check( L, 1 ); + ArrowEffects::SetCurrentOptions(&ps->m_PlayerOptions.GetCurrent()); lua_pushnumber( L, ArrowEffects::ReceptorGetRotationZ( ps ) ); return 1; } @@ -925,6 +974,7 @@ namespace int GetAlpha( lua_State *L ) { PlayerState *ps = Luna::check( L, 1 ); + ArrowEffects::SetCurrentOptions(&ps->m_PlayerOptions.GetCurrent()); // Provide reasonable default values. float fPercentFadeToFail = -1; float fYReverseOffsetPixels = YReverseOffset( L, 5 ); @@ -942,7 +992,7 @@ namespace { fFadeInPercentOfDrawFar = FArg(7); } - lua_pushnumber( L, ArrowEffects::GetAlpha( ps, IArg(2)-1, FArg(3), fPercentFadeToFail, fYReverseOffsetPixels, fDrawDistanceBeforeTargetsPixels, fFadeInPercentOfDrawFar ) ); + lua_pushnumber(L, ArrowEffects::GetAlpha(IArg(2)-1, FArg(3), fPercentFadeToFail, fYReverseOffsetPixels, fDrawDistanceBeforeTargetsPixels, fFadeInPercentOfDrawFar)); return 1; } @@ -951,6 +1001,7 @@ namespace int GetGlow( lua_State *L ) { PlayerState *ps = Luna::check( L, 1 ); + ArrowEffects::SetCurrentOptions(&ps->m_PlayerOptions.GetCurrent()); // Provide reasonable default values. float fPercentFadeToFail = -1; // float fYReverseOffsetPixels = YReverseOffset( L, 5 ); @@ -968,7 +1019,7 @@ namespace { fFadeInPercentOfDrawFar = FArg(7); } - lua_pushnumber( L, ArrowEffects::GetGlow( ps, IArg(2)-1, FArg(3), fPercentFadeToFail, fYReverseOffsetPixels, fDrawDistanceBeforeTargetsPixels, fFadeInPercentOfDrawFar ) ); + lua_pushnumber( L, ArrowEffects::GetGlow(IArg(2)-1, FArg(3), fPercentFadeToFail, fYReverseOffsetPixels, fDrawDistanceBeforeTargetsPixels, fFadeInPercentOfDrawFar ) ); return 1; } @@ -976,6 +1027,7 @@ namespace int GetBrightness( lua_State *L ) { PlayerState *ps = Luna::check( L, 1 ); + ArrowEffects::SetCurrentOptions(&ps->m_PlayerOptions.GetCurrent()); lua_pushnumber( L, ArrowEffects::GetBrightness( ps, FArg(2) ) ); return 1; } @@ -984,7 +1036,8 @@ namespace int NeedZBuffer( lua_State *L ) { PlayerState *ps = Luna::check( L, 1 ); - lua_pushboolean( L, ArrowEffects::NeedZBuffer( ps ) ); + ArrowEffects::SetCurrentOptions(&ps->m_PlayerOptions.GetCurrent()); + lua_pushboolean(L, ArrowEffects::NeedZBuffer()); return 1; } @@ -992,6 +1045,7 @@ namespace int GetZoom( lua_State *L ) { PlayerState *ps = Luna::check( L, 1 ); + ArrowEffects::SetCurrentOptions(&ps->m_PlayerOptions.GetCurrent()); lua_pushnumber( L, ArrowEffects::GetZoom( ps ) ); return 1; } @@ -1000,6 +1054,7 @@ namespace int GetFrameWidthScale( lua_State *L ) { PlayerState *ps = Luna::check( L, 1 ); + ArrowEffects::SetCurrentOptions(&ps->m_PlayerOptions.GetCurrent()); // Make fOverlappedTime optional. float fOverlappedTime = 0; diff --git a/src/ArrowEffects.h b/src/ArrowEffects.h index 8629c8bd33..811f2d11fe 100644 --- a/src/ArrowEffects.h +++ b/src/ArrowEffects.h @@ -1,12 +1,20 @@ #ifndef ARROWEFFECTS_H #define ARROWEFFECTS_H +#include "RageTypes.h" + class PlayerState; +class PlayerOptions; /** @brief Functions that return properties of arrows based on Style and PlayerOptions. */ class ArrowEffects { public: static void Update(); + // SetCurrentOptions and the hidden static variable it set exists so that + // ArrowEffects doesn't have to reach through the PlayerState to check + // every option. Also, it will make it easier to implement per-column + // mods later. -Kyz + static void SetCurrentOptions(const PlayerOptions* options); // fYOffset is a vertical position in pixels relative to the center // (positive if has not yet been stepped on, negative if has already passed). @@ -19,12 +27,11 @@ public: return GetYOffset( pPlayerState, iCol, fNoteBeat, fThrowAway, bThrowAway, bAbsolute ); } - static void GetXYZPos(const PlayerState* player_state, int col, float y_offset, float y_reverse_offset, vector& ret, bool with_reverse= true) + static void GetXYZPos(const PlayerState* player_state, int col, float y_offset, float y_reverse_offset, RageVector3& ret, bool with_reverse= true) { - ASSERT(ret.size() == 3); - ret[0]= GetXPos(player_state, col, y_offset); - ret[1]= GetYPos(player_state, col, y_offset, y_reverse_offset, with_reverse); - ret[2]= GetZPos(player_state, col, y_offset); + ret.x= GetXPos(player_state, col, y_offset); + ret.y= GetYPos(col, y_offset, y_reverse_offset, with_reverse); + ret.z= GetZPos(col, y_offset); } /** @@ -37,10 +44,10 @@ public: * @param fYReverseOffsetPixels the amount offset due to reverse. * @param WithReverse a flag to see if the Reverse mod is on. * @return the actual display position. */ - static float GetYPos( const PlayerState* pPlayerState, int iCol, float fYOffset, float fYReverseOffsetPixels, bool WithReverse = true ); + static float GetYPos(int iCol, float fYOffset, float fYReverseOffsetPixels, bool WithReverse = true ); // Inverse of ArrowGetYPos (YPos -> fYOffset). - static float GetYOffsetFromYPos( const PlayerState* pPlayerState, int iCol, float YPos, float fYReverseOffsetPixels ); + static float GetYOffsetFromYPos(int iCol, float YPos, float fYReverseOffsetPixels); // fRotation is Z rotation of an arrow. This will depend on the column of // the arrow and possibly the Arrow effect and the fYOffset (in the case of @@ -50,8 +57,8 @@ public: // Due to the handling logic for holds on Twirl, we need to use an offset instead. // It's more intuitive for Roll to be based off offset, so use an offset there too. - static float GetRotationX( const PlayerState* pPlayerState, float fYOffset ); - static float GetRotationY( const PlayerState* pPlayerState, float fYOffset ); + static float GetRotationX(float fYOffset); + static float GetRotationY(float fYOffset); // fXPos is a horizontal position in pixels relative to the center of the field. // This depends on the column of the arrow and possibly the Arrow effect and @@ -66,18 +73,18 @@ public: * @param iCol the specific arrow column. * @param fYPos the Y position of the arrow. * @return the Z position. */ - static float GetZPos( const PlayerState* pPlayerState, int iCol, float fYPos ); + static float GetZPos(int iCol, float fYPos); // Enable this if any ZPos effects are enabled. - static bool NeedZBuffer( const PlayerState* pPlayerState ); + static bool NeedZBuffer(); // fAlpha is the transparency of the arrow. It depends on fYPos and the // AppearanceType. - static float GetAlpha( const PlayerState* pPlayerState, int iCol, float fYPos, float fPercentFadeToFail, float fYReverseOffsetPixels, float fDrawDistanceBeforeTargetsPixels, float fFadeInPercentOfDrawFar ); + static float GetAlpha(int iCol, float fYPos, float fPercentFadeToFail, float fYReverseOffsetPixels, float fDrawDistanceBeforeTargetsPixels, float fFadeInPercentOfDrawFar); // fAlpha is the transparency of the arrow. It depends on fYPos and the // AppearanceType. - static float GetGlow( const PlayerState* pPlayerState, int iCol, float fYPos, float fPercentFadeToFail, float fYReverseOffsetPixels, float fDrawDistanceBeforeTargetsPixels, float fFadeInPercentOfDrawFar ); + static float GetGlow(int iCol, float fYPos, float fPercentFadeToFail, float fYReverseOffsetPixels, float fDrawDistanceBeforeTargetsPixels, float fFadeInPercentOfDrawFar ); /** * @brief Retrieve the current brightness. diff --git a/src/CubicSpline.cpp b/src/CubicSpline.cpp index 142f305aa0..443d995f10 100644 --- a/src/CubicSpline.cpp +++ b/src/CubicSpline.cpp @@ -666,6 +666,20 @@ CSN_EVAL_SOMETHING(evaluate_third_derivative); #undef CSN_EVAL_SOMETHING +#define CSN_EVAL_RV_SOMETHING(something) \ +void CubicSplineN::something(float t, RageVector3& v) const \ +{ \ + ASSERT(m_splines.size() == 3); \ + v.x= m_splines[0].something(t, m_loop); \ + v.y= m_splines[1].something(t, m_loop); \ + v.z= m_splines[2].something(t, m_loop); \ +} + +CSN_EVAL_RV_SOMETHING(evaluate); +CSN_EVAL_RV_SOMETHING(evaluate_derivative); + +#undef CSN_EVAL_RV_SOMETHING + void CubicSplineN::set_point(size_t i, const vector& v) { ASSERT_M(v.size() == m_splines.size(), "CubicSplineN::set_point requires the passed point to be the same dimension as the spline."); diff --git a/src/CubicSpline.h b/src/CubicSpline.h index aae6e702e9..dbbf694e4c 100644 --- a/src/CubicSpline.h +++ b/src/CubicSpline.h @@ -3,6 +3,7 @@ #include using std::vector; +#include "RageTypes.h" struct lua_State; struct CubicSpline @@ -49,6 +50,8 @@ struct CubicSplineN void evaluate_derivative(float t, vector& v) const; void evaluate_second_derivative(float t, vector& v) const; void evaluate_third_derivative(float t, vector& v) const; + void evaluate(float t, RageVector3& v) const; + void evaluate_derivative(float t, RageVector3& v) const; void set_point(size_t i, const vector& v); void set_coefficients(size_t i, const vector& b, const vector& c, const vector& d); diff --git a/src/Model.cpp b/src/Model.cpp index 968d16229e..4f79646d24 100644 --- a/src/Model.cpp +++ b/src/Model.cpp @@ -49,6 +49,7 @@ void Model::Clear() m_Materials.clear(); m_mapNameToAnimation.clear(); m_pCurAnimation = NULL; + RecalcAnimationLengthSeconds(); if( m_pTempGeometry ) DISPLAY->DeleteCompiledGeometry( m_pTempGeometry ); @@ -62,6 +63,7 @@ void Model::Load( const RString &sFile ) sExt.MakeLower(); if( sExt=="txt" ) LoadMilkshapeAscii( sFile ); + RecalcAnimationLengthSeconds(); } #define THROW RageException::Throw( "Parse error in \"%s\" at line %d: \"%s\".", sPath.c_str(), iLineNum, sLine.c_str() ) @@ -102,6 +104,7 @@ void Model::LoadPieces( const RString &sMeshesPath, const RString &sMaterialsPat m_pTempGeometry = DISPLAY->CreateCompiledGeometry(); m_pTempGeometry->Set( m_vTempMeshes, this->MaterialsNeedNormals() ); } + RecalcAnimationLengthSeconds(); } void Model::LoadFromNode( const XNode* pNode ) @@ -117,6 +120,7 @@ void Model::LoadFromNode( const XNode* pNode ) } Actor::LoadFromNode( pNode ); + RecalcAnimationLengthSeconds(); } @@ -741,12 +745,14 @@ void Model::SetState( int iNewState ) } } -float Model::GetAnimationLengthSeconds() const +void Model::RecalcAnimationLengthSeconds() { - float fSeconds = 0; - FOREACH_CONST( msMaterial, m_Materials, m ) - fSeconds = max( fSeconds, m->diffuse.GetAnimationLengthSeconds() ); - return fSeconds; + m_animation_length_seconds= 0; + FOREACH_CONST(msMaterial, m_Materials, m) + { + m_animation_length_seconds= max(m_animation_length_seconds, + m->diffuse.GetAnimationLengthSeconds()); + } } void Model::SetSecondsIntoAnimation( float fSeconds ) diff --git a/src/Model.h b/src/Model.h index afb70cc738..af54269f45 100644 --- a/src/Model.h +++ b/src/Model.h @@ -43,7 +43,9 @@ public: virtual int GetNumStates() const; virtual void SetState( int iNewState ); - virtual float GetAnimationLengthSeconds() const; + virtual float GetAnimationLengthSeconds() const + { return m_animation_length_seconds; } + virtual void RecalcAnimationLengthSeconds(); virtual void SetSecondsIntoAnimation( float fSeconds ); RString GetDefaultAnimation() const { return m_sDefaultAnimation; }; @@ -57,6 +59,7 @@ public: private: RageModelGeometry *m_pGeometry; + float m_animation_length_seconds; vector m_Materials; map m_mapNameToAnimation; const msAnimation* m_pCurAnimation; diff --git a/src/NoteDisplay.cpp b/src/NoteDisplay.cpp index d4fa02ae95..1122bf25d9 100644 --- a/src/NoteDisplay.cpp +++ b/src/NoteDisplay.cpp @@ -303,19 +303,19 @@ float NCSplineHandler::BeatToTValue(float song_beat, float note_beat) const return relative_beat / m_beats_per_t; } -void NCSplineHandler::EvalForBeat(float song_beat, float note_beat, vector& ret) const +void NCSplineHandler::EvalForBeat(float song_beat, float note_beat, RageVector3& ret) const { float t_value= BeatToTValue(song_beat, note_beat); m_spline.evaluate(t_value, ret); } -void NCSplineHandler::EvalDerivForBeat(float song_beat, float note_beat, vector& ret) const +void NCSplineHandler::EvalDerivForBeat(float song_beat, float note_beat, RageVector3& ret) const { float t_value= BeatToTValue(song_beat, note_beat); m_spline.evaluate_derivative(t_value, ret); } -void NCSplineHandler::EvalForReceptor(float song_beat, vector& ret) const +void NCSplineHandler::EvalForReceptor(float song_beat, RageVector3& ret) const { float t_value= m_receptor_t; if(!m_subtract_song_beat_from_curr) @@ -344,22 +344,17 @@ void NCSplineHandler::MakeWeightedAverage(NCSplineHandler& out, between); } -void NoteColumnRenderArgs::spae_pos_for_beat(const PlayerState* state, +void NoteColumnRenderArgs::spae_pos_for_beat(const PlayerState* player_state, float beat, float y_offset, float y_reverse_offset, - vector& sp_pos, vector& ae_pos) const + RageVector3& sp_pos, RageVector3& ae_pos) const { switch(pos_handler->m_spline_mode) { case NCSM_Disabled: - ArrowEffects::GetXYZPos(state, column, y_offset, y_reverse_offset, ae_pos); - sp_pos.resize(3); - // Sure, resize is supposed to call the default constructor, and for - // numbers the default constructor is supposed to set it to zero, but - // I got bit for relying on that once. -Kyz - sp_pos[0]= sp_pos[1]= sp_pos[2]= 0.0f; + ArrowEffects::GetXYZPos(player_state, column, y_offset, y_reverse_offset, ae_pos); break; case NCSM_Offset: - ArrowEffects::GetXYZPos(state, column, y_offset, y_reverse_offset, ae_pos); + ArrowEffects::GetXYZPos(player_state, column, y_offset, y_reverse_offset, ae_pos); pos_handler->EvalForBeat(song_beat, beat, sp_pos); break; case NCSM_Position: @@ -368,17 +363,15 @@ void NoteColumnRenderArgs::spae_pos_for_beat(const PlayerState* state, } } void NoteColumnRenderArgs::spae_zoom_for_beat(const PlayerState* state, float beat, - vector& sp_zoom, vector& ae_zoom) const + RageVector3& sp_zoom, RageVector3& ae_zoom) const { switch(zoom_handler->m_spline_mode) { case NCSM_Disabled: - ae_zoom[0]= ae_zoom[1]= ae_zoom[2]= ArrowEffects::GetZoom(state); - sp_zoom.resize(3); - sp_zoom[0]= sp_zoom[1]= sp_zoom[2]= 0.0f; + ae_zoom.x= ae_zoom.y= ae_zoom.z= ArrowEffects::GetZoom(state); break; case NCSM_Offset: - ae_zoom[0]= ae_zoom[1]= ae_zoom[2]= ArrowEffects::GetZoom(state); + ae_zoom.x= ae_zoom.y= ae_zoom.z= ArrowEffects::GetZoom(state); zoom_handler->EvalForBeat(song_beat, beat, sp_zoom); break; case NCSM_Position: @@ -387,19 +380,19 @@ void NoteColumnRenderArgs::spae_zoom_for_beat(const PlayerState* state, float be } } void NoteColumnRenderArgs::SetPRZForActor(Actor* actor, - const vector& sp_pos, const vector& ae_pos, - const vector& sp_rot, const vector& ae_rot, - const vector& sp_zoom, const vector& ae_zoom) const + const RageVector3& sp_pos, const RageVector3& ae_pos, + const RageVector3& sp_rot, const RageVector3& ae_rot, + const RageVector3& sp_zoom, const RageVector3& ae_zoom) const { - actor->SetX(sp_pos[0] + ae_pos[0]); - actor->SetY(sp_pos[1] + ae_pos[1]); - actor->SetZ(sp_pos[2] + ae_pos[2]); - actor->SetRotationX(sp_rot[0] * PI_180R + ae_rot[0]); - actor->SetRotationY(sp_rot[1] * PI_180R + ae_rot[1]); - actor->SetRotationZ(sp_rot[2] * PI_180R + ae_rot[2]); - actor->SetZoomX(sp_zoom[0] + ae_zoom[0]); - actor->SetZoomY(sp_zoom[1] + ae_zoom[1]); - actor->SetZoomZ(sp_zoom[2] + ae_zoom[2]); + actor->SetX(sp_pos.x + ae_pos.x); + actor->SetY(sp_pos.y + ae_pos.y); + actor->SetZ(sp_pos.z + ae_pos.z); + actor->SetRotationX(sp_rot.x * PI_180R + ae_rot.x); + actor->SetRotationY(sp_rot.y * PI_180R + ae_rot.y); + actor->SetRotationZ(sp_rot.z * PI_180R + ae_rot.z); + actor->SetZoomX(sp_zoom.x + ae_zoom.x); + actor->SetZoomY(sp_zoom.y + ae_zoom.y); + actor->SetZoomZ(sp_zoom.z + ae_zoom.z); } @@ -704,9 +697,9 @@ Sprite *NoteDisplay::GetHoldSprite( NoteColorSprite ncs[NUM_HoldType][NUM_Active static float ArrowGetAlphaOrGlow( bool bGlow, const PlayerState* pPlayerState, int iCol, float fYOffset, float fPercentFadeToFail, float fYReverseOffsetPixels, float fDrawDistanceBeforeTargetsPixels, float fFadeInPercentOfDrawFar ) { if( bGlow ) - return ArrowEffects::GetGlow( pPlayerState, iCol, fYOffset, fPercentFadeToFail, fYReverseOffsetPixels, fDrawDistanceBeforeTargetsPixels, fFadeInPercentOfDrawFar ); + return ArrowEffects::GetGlow(iCol, fYOffset, fPercentFadeToFail, fYReverseOffsetPixels, fDrawDistanceBeforeTargetsPixels, fFadeInPercentOfDrawFar); else - return ArrowEffects::GetAlpha( pPlayerState, iCol, fYOffset, fPercentFadeToFail, fYReverseOffsetPixels, fDrawDistanceBeforeTargetsPixels, fFadeInPercentOfDrawFar ); + return ArrowEffects::GetAlpha(iCol, fYOffset, fPercentFadeToFail, fYReverseOffsetPixels, fDrawDistanceBeforeTargetsPixels, fFadeInPercentOfDrawFar); } struct StripBuffer @@ -738,53 +731,49 @@ struct StripBuffer void NoteDisplay::DrawHoldPart(vector &vpSpr, const NoteFieldRenderArgs& field_args, - const NoteColumnRenderArgs& column_args, int fYStep, - float fPercentFadeToFail, float fColorScale, bool bGlow, - float fOverlappedTime, float fYTop, float fYBottom, float fYStartPos, - float fYEndPos, bool bWrapping, bool bAnchorToTop, - bool bFlipTextureVertically, float top_beat, float bottom_beat) + const NoteColumnRenderArgs& column_args, + const draw_hold_part_args& part_args, bool glow) { - ASSERT( !vpSpr.empty() ); + ASSERT(!vpSpr.empty()); float ae_zoom= ArrowEffects::GetZoom(m_pPlayerState); Sprite *pSprite = vpSpr.front(); // draw manually in small segments RectF rect = *pSprite->GetCurrentTextureCoordRect(); - if( bFlipTextureVertically ) - swap( rect.top, rect.bottom ); + if(part_args.flip_texture_vertically) + swap(rect.top, rect.bottom); const float fFrameWidth = pSprite->GetUnzoomedWidth(); const float fFrameHeight = pSprite->GetUnzoomedHeight() * ae_zoom; /* 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 - * fYTop or fYBottom; they need to be left alone to calculate texture coordinates. */ - fYStartPos = max( fYTop, fYStartPos ); - fYEndPos = min( fYBottom, fYEndPos ); - - if( bGlow ) - fColorScale = 1; + * part_args.y_top or part_args.y_bottom; they need to be left alone to calculate texture coordinates. */ + const float y_start_pos = max(part_args.y_top, part_args.y_start_pos); + const float y_end_pos = min(part_args.y_bottom, part_args.y_end_pos); + const float color_scale= glow ? 1 : part_args.color_scale; // top to bottom bool bAllAreTransparent = true; bool bLast = false; float fAddToTexCoord = 0; - if( !bAnchorToTop ) + if(!part_args.anchor_to_top) { - float fTexCoordBottom = SCALE( fYBottom - fYTop, 0, fFrameHeight, rect.top, rect.bottom ); - float fWantTexCoordBottom = ceilf( fTexCoordBottom - 0.0001f ); - fAddToTexCoord = fWantTexCoordBottom - fTexCoordBottom; + float tex_coord_bottom= SCALE(part_args.y_bottom - part_args.y_top, + 0, fFrameHeight, rect.top, rect.bottom); + float want_tex_coord_bottom = ceilf(tex_coord_bottom - 0.0001f); + fAddToTexCoord = want_tex_coord_bottom - tex_coord_bottom; } - if( bWrapping ) + if(part_args.wrapping) { /* For very large hold notes, shift the texture coordinates to be near 0, so we * don't send very large values to the renderer. */ - const float fDistFromTop = fYStartPos - fYTop; - float fTexCoordTop = SCALE( fDistFromTop, 0, fFrameHeight, rect.top, rect.bottom ); + const float fDistFromTop = y_start_pos - part_args.y_top; + float fTexCoordTop = SCALE(fDistFromTop, 0, fFrameHeight, rect.top, rect.bottom); fTexCoordTop += fAddToTexCoord; - fAddToTexCoord -= floorf( fTexCoordTop ); + fAddToTexCoord -= floorf(fTexCoordTop); } DISPLAY->ClearAllTextures(); @@ -798,20 +787,20 @@ void NoteDisplay::DrawHoldPart(vector &vpSpr, static const RageVector3 pos_y_vec(0.0f, 1.0f, 0.0f); StripBuffer queue; - for( float fY = fYStartPos; !bLast; fY += fYStep ) + for(float fY = y_start_pos; !bLast; fY += part_args.y_step) { - if( fY >= fYEndPos ) + if(fY >= y_end_pos) { - fY = fYEndPos; + fY = y_end_pos; bLast = true; } - const float fYOffset = ArrowEffects::GetYOffsetFromYPos( m_pPlayerState, column_args.column, fY, m_fYReverseOffsetPixels ); + const float fYOffset= ArrowEffects::GetYOffsetFromYPos(column_args.column, fY, m_fYReverseOffsetPixels); - float cur_beat= top_beat; - if(top_beat != bottom_beat) + float cur_beat= part_args.top_beat; + if(part_args.top_beat != part_args.bottom_beat) { - cur_beat= SCALE(fY, fYTop, fYBottom, top_beat, bottom_beat); + cur_beat= SCALE(fY, part_args.y_top, part_args.y_bottom, part_args.top_beat, part_args.bottom_beat); } // Fun times ahead with vector math. If the notes are being moved by the @@ -834,12 +823,12 @@ void NoteDisplay::DrawHoldPart(vector &vpSpr, // TODO: Figure out whether it's worth the time investment to figure out // a way to skip the complex vector handling if the spline is disabled. - vector sp_pos; - vector sp_pos_forward; - vector sp_rot; - vector sp_zoom; - vector ae_pos(3, 0.0f); - vector ae_rot(3, 0.0f); + RageVector3 sp_pos; + RageVector3 sp_pos_forward; + RageVector3 sp_rot; + RageVector3 sp_zoom; + RageVector3 ae_pos; + RageVector3 ae_rot; // (step 1 of vector handling, part 1) // ArrowEffects only contributes to the Y component of the vector to @@ -848,32 +837,30 @@ void NoteDisplay::DrawHoldPart(vector &vpSpr, RageVector3 render_forward(0.0f, 1.0f, 0.0f); column_args.spae_pos_for_beat(m_pPlayerState, cur_beat, fYOffset, m_fYReverseOffsetPixels, sp_pos, ae_pos); - // fX and fZ are sp_pos[0] + ae_pos[0] and sp_pos[2] + ae_pos[2]. -Kyz + // fX and fZ are sp_pos.x + ae_pos.x and sp_pos.z + ae_pos.z. -Kyz // fY is the actual y position that should be used, not whatever spae // fetched from ArrowEffects. -Kyz switch(column_args.pos_handler->m_spline_mode) { case NCSM_Disabled: - ae_pos[1]= fY; - sp_pos_forward.resize(3); - sp_pos_forward[0]= sp_pos_forward[1]= sp_pos_forward[2]= 0.0f; + ae_pos.y= fY; break; case NCSM_Offset: - ae_pos[1]= fY; + ae_pos.y= fY; column_args.pos_handler->EvalDerivForBeat(column_args.song_beat, cur_beat, sp_pos_forward); - VectorFloatNormalize(sp_pos_forward); + RageVec3Normalize(&sp_pos_forward, &sp_pos_forward); break; case NCSM_Position: - ae_pos[1]= 0.0f; + ae_pos.y= 0.0f; render_forward.y= 0.0f; column_args.pos_handler->EvalDerivForBeat(column_args.song_beat, cur_beat, sp_pos_forward); - VectorFloatNormalize(sp_pos_forward); + RageVec3Normalize(&sp_pos_forward, &sp_pos_forward); break; } - render_forward.x+= sp_pos_forward[0]; - render_forward.y+= sp_pos_forward[1]; - render_forward.z+= sp_pos_forward[2]; + render_forward.x+= sp_pos_forward.x; + render_forward.y+= sp_pos_forward.y; + render_forward.z+= sp_pos_forward.z; // Normalize the vector so it'll be easy to test when determining whether // to use pos_z_vec or pos_y_vec for the cross product in step 2. RageVec3Normalize(&render_forward, &render_forward); @@ -888,15 +875,15 @@ void NoteDisplay::DrawHoldPart(vector &vpSpr, break; case NCSM_Offset: column_args.zoom_handler->EvalForBeat(column_args.song_beat, cur_beat, sp_zoom); - render_width= fFrameWidth * (ae_zoom + sp_zoom[0]); + render_width= fFrameWidth * (ae_zoom + sp_zoom.x); break; case NCSM_Position: column_args.zoom_handler->EvalForBeat(column_args.song_beat, cur_beat, sp_zoom); - render_width= fFrameWidth * sp_zoom[0]; + render_width= fFrameWidth * sp_zoom.x; break; } - const float fFrameWidthScale = ArrowEffects::GetFrameWidthScale( m_pPlayerState, fYOffset, fOverlappedTime ); + const float fFrameWidthScale = ArrowEffects::GetFrameWidthScale(m_pPlayerState, fYOffset, part_args.overlapped_time); const float fScaledFrameWidth = render_width * fFrameWidthScale; // Can't use the same code as for taps because hold bodies can only rotate @@ -905,12 +892,10 @@ void NoteDisplay::DrawHoldPart(vector &vpSpr, { case NCSM_Disabled: // XXX: Actor rotations use degrees, Math uses radians. Convert here. - ae_rot[1]= ArrowEffects::GetRotationY(m_pPlayerState, fYOffset) * PI_180; - sp_rot.resize(3); - sp_rot[0]= sp_rot[1]= sp_rot[2]= 0.0f; + ae_rot.y= ArrowEffects::GetRotationY(fYOffset) * PI_180; break; case NCSM_Offset: - ae_rot[1]= ArrowEffects::GetRotationY(m_pPlayerState, fYOffset) * PI_180; + ae_rot.y= ArrowEffects::GetRotationY(fYOffset) * PI_180; column_args.rot_handler->EvalForBeat(column_args.song_beat, cur_beat, sp_rot); break; case NCSM_Position: @@ -918,18 +903,18 @@ void NoteDisplay::DrawHoldPart(vector &vpSpr, break; } - RageVector3 center_vert(sp_pos[0] + ae_pos[0], - sp_pos[1] + ae_pos[1], sp_pos[2] + ae_pos[2]); + RageVector3 center_vert(sp_pos.x + ae_pos.x, + sp_pos.y + ae_pos.y, sp_pos.z + ae_pos.z); // Special case for hold caps, which have the same top and bottom beat. - if(top_beat == bottom_beat && fY != fYStartPos) + if(part_args.top_beat == part_args.bottom_beat && fY != y_start_pos) { center_vert.x+= render_forward.x; center_vert.y+= render_forward.y; center_vert.z+= render_forward.z; } - const float render_roty= (sp_rot[1] + ae_rot[1]); + const float render_roty= (sp_rot.y + ae_rot.y); // (step 2 of vector handling) RageVector3 render_left; @@ -952,21 +937,18 @@ void NoteDisplay::DrawHoldPart(vector &vpSpr, const RageVector3 right_vert(center_vert.x - render_left.x, center_vert.y - render_left.y, center_vert.z - render_left.z); - const float fDistFromTop = fY - fYTop; - float fTexCoordTop = SCALE( fDistFromTop, 0, fFrameHeight, rect.top, rect.bottom ); + const float fDistFromTop = fY - part_args.y_top; + float fTexCoordTop = SCALE(fDistFromTop, 0, fFrameHeight, rect.top, rect.bottom); fTexCoordTop += fAddToTexCoord; - const float fAlpha = ArrowGetAlphaOrGlow( bGlow, m_pPlayerState, column_args.column, fYOffset, fPercentFadeToFail, m_fYReverseOffsetPixels, field_args.draw_pixels_before_targets, field_args.fade_before_targets ); + const float fAlpha = ArrowGetAlphaOrGlow(glow, m_pPlayerState, column_args.column, fYOffset, part_args.percent_fade_to_fail, m_fYReverseOffsetPixels, field_args.draw_pixels_before_targets, field_args.fade_before_targets); const RageColor color= RageColor( - column_args.diffuse.r * fColorScale, - column_args.diffuse.g * fColorScale, - column_args.diffuse.b * fColorScale, + column_args.diffuse.r * color_scale, + column_args.diffuse.g * color_scale, + column_args.diffuse.b * color_scale, column_args.diffuse.a * fAlpha); - // Holds don't get a glow pass because rendering them is already - // painfully slow. -Kyz - - if( fAlpha > 0 ) + if(fAlpha > 0) bAllAreTransparent = false; queue.v[0].p = left_vert; queue.v[0].c = color; queue.v[0].t = RageVector2(fTexCoordLeft, fTexCoordTop); @@ -974,124 +956,146 @@ void NoteDisplay::DrawHoldPart(vector &vpSpr, queue.v[2].p = right_vert; queue.v[2].c = color; queue.v[2].t = RageVector2(fTexCoordRight, fTexCoordTop); queue.v+=3; - if( queue.Free() < 3 || bLast ) + if(queue.Free() < 3 || bLast) { /* The queue is full. Render it, clear the buffer, and move back a step to * start off the strip again. */ - if( !bAllAreTransparent ) + if(!bAllAreTransparent) { - FOREACH( Sprite*, vpSpr, spr ) + FOREACH(Sprite*, vpSpr, spr) { RageTexture* pTexture = (*spr)->GetTexture(); - DISPLAY->SetTexture( TextureUnit_1, pTexture->GetTexHandle() ); - DISPLAY->SetBlendMode( spr == vpSpr.begin() ? BLEND_NORMAL : BLEND_ADD ); - DISPLAY->SetCullMode( CULL_NONE ); - DISPLAY->SetTextureWrapping( TextureUnit_1, bWrapping ); + DISPLAY->SetTexture(TextureUnit_1, pTexture->GetTexHandle()); + DISPLAY->SetBlendMode(spr == vpSpr.begin() ? BLEND_NORMAL : BLEND_ADD); + DISPLAY->SetCullMode(CULL_NONE); + DISPLAY->SetTextureWrapping(TextureUnit_1, part_args.wrapping); queue.Draw(); } } queue.Init(); bAllAreTransparent = true; - fY -= fYStep; + fY -= part_args.y_step; } } } +void NoteDisplay::DrawHoldBodyInternal(vector& sprite_top, + vector& sprite_body, vector& sprite_bottom, + const NoteFieldRenderArgs& field_args, + const NoteColumnRenderArgs& column_args, + draw_hold_part_args& part_args, + const float head_minus_top, const float tail_plus_bottom, + const float y_head, const float y_tail, const float top_beat, + const float bottom_beat, bool glow) +{ + // Draw the top cap + part_args.y_top= head_minus_top; + part_args.y_bottom= y_head; + part_args.top_beat= top_beat; + part_args.bottom_beat= top_beat; + part_args.wrapping= false; + DrawHoldPart(sprite_top, field_args, column_args, part_args, glow); + // Draw the body + part_args.y_top= y_head; + part_args.y_bottom= y_tail; + part_args.bottom_beat= bottom_beat; + part_args.wrapping= true; + DrawHoldPart(sprite_body, field_args, column_args, part_args, glow); + // Draw the bottom cap + part_args.y_top= y_tail; + part_args.y_bottom= tail_plus_bottom; + part_args.top_beat= bottom_beat; + part_args.y_start_pos= max(part_args.y_start_pos, y_head); + DrawHoldPart(sprite_bottom, field_args, column_args, part_args, glow); +} + void NoteDisplay::DrawHoldBody(const TapNote& tn, const NoteFieldRenderArgs& field_args, - const NoteColumnRenderArgs& column_args, float fBeat, - bool bIsBeingHeld, float fYHead, float fYTail, bool bIsAddition, - float fPercentFadeToFail, float fColorScale, bool bGlow, - float top_beat, float bottom_beat) + const NoteColumnRenderArgs& column_args, float beat, + bool being_held, float y_head, float y_tail, float percent_fade_to_fail, + float color_scale, float top_beat, float bottom_beat) { + draw_hold_part_args part_args; + part_args.percent_fade_to_fail= percent_fade_to_fail; + part_args.color_scale= color_scale; + part_args.overlapped_time= tn.HoldResult.fOverlappedTime; vector vpSprTop; - Sprite *pSpriteTop = GetHoldSprite( m_HoldTopCap, NotePart_HoldTopCap, fBeat, tn.subType == TapNoteSubType_Roll, bIsBeingHeld && !cache->m_bHoldActiveIsAddLayer ); + Sprite *pSpriteTop = GetHoldSprite( m_HoldTopCap, NotePart_HoldTopCap, beat, tn.subType == TapNoteSubType_Roll, being_held && !cache->m_bHoldActiveIsAddLayer ); vpSprTop.push_back( pSpriteTop ); vector vpSprBody; - Sprite *pSpriteBody = GetHoldSprite( m_HoldBody, NotePart_HoldBody, fBeat, tn.subType == TapNoteSubType_Roll, bIsBeingHeld && !cache->m_bHoldActiveIsAddLayer ); + Sprite *pSpriteBody = GetHoldSprite( m_HoldBody, NotePart_HoldBody, beat, tn.subType == TapNoteSubType_Roll, being_held && !cache->m_bHoldActiveIsAddLayer ); vpSprBody.push_back( pSpriteBody ); vector vpSprBottom; - Sprite *pSpriteBottom = GetHoldSprite( m_HoldBottomCap, NotePart_HoldBottomCap, fBeat, tn.subType == TapNoteSubType_Roll, bIsBeingHeld && !cache->m_bHoldActiveIsAddLayer ); + Sprite *pSpriteBottom = GetHoldSprite( m_HoldBottomCap, NotePart_HoldBottomCap, beat, tn.subType == TapNoteSubType_Roll, being_held && !cache->m_bHoldActiveIsAddLayer ); vpSprBottom.push_back( pSpriteBottom ); - if( bIsBeingHeld && cache->m_bHoldActiveIsAddLayer ) + if(being_held && cache->m_bHoldActiveIsAddLayer) { - Sprite *pSprTop = GetHoldSprite( m_HoldTopCap, NotePart_HoldTopCap, fBeat, tn.subType == TapNoteSubType_Roll, true ); + Sprite *pSprTop = GetHoldSprite( m_HoldTopCap, NotePart_HoldTopCap, beat, tn.subType == TapNoteSubType_Roll, true ); vpSprTop.push_back( pSprTop ); - Sprite *pSprBody = GetHoldSprite( m_HoldBody, NotePart_HoldBody, fBeat, tn.subType == TapNoteSubType_Roll, true ); + Sprite *pSprBody = GetHoldSprite( m_HoldBody, NotePart_HoldBody, beat, tn.subType == TapNoteSubType_Roll, true ); vpSprBody.push_back( pSprBody ); - Sprite *pSprBottom = GetHoldSprite( m_HoldBottomCap, NotePart_HoldBottomCap, fBeat, tn.subType == TapNoteSubType_Roll, true ); + Sprite *pSprBottom = GetHoldSprite( m_HoldBottomCap, NotePart_HoldBottomCap, beat, tn.subType == TapNoteSubType_Roll, true ); vpSprBottom.push_back( pSprBottom ); } - const bool bReverse = m_pPlayerState->m_PlayerOptions.GetCurrent().GetReversePercentForColumn(column_args.column) > 0.5f; - bool bFlipHoldBody = bReverse && cache->m_bFlipHoldBodyWhenReverse; - if( bFlipHoldBody ) + const bool reverse = m_pPlayerState->m_PlayerOptions.GetCurrent().GetReversePercentForColumn(column_args.column) > 0.5f; + part_args.flip_texture_vertically = reverse && cache->m_bFlipHoldBodyWhenReverse; + if(part_args.flip_texture_vertically) { swap( vpSprTop, vpSprBottom ); swap( pSpriteTop, pSpriteBottom ); } - if( bGlow ) - DISPLAY->SetTextureMode( TextureUnit_1, TextureMode_Glow ); - else - DISPLAY->SetTextureMode( TextureUnit_1, TextureMode_Modulate ); - - const bool bWavyPartsNeedZBuffer = ArrowEffects::NeedZBuffer( m_pPlayerState ); + const bool bWavyPartsNeedZBuffer = ArrowEffects::NeedZBuffer(); DISPLAY->SetZTestMode( bWavyPartsNeedZBuffer?ZTEST_WRITE_ON_PASS:ZTEST_OFF ); DISPLAY->SetZWrite( bWavyPartsNeedZBuffer ); // Hack: Z effects need a finer grain step. - const int fYStep = bWavyPartsNeedZBuffer? 4: 16; // use small steps only if wavy + part_args.y_step = bWavyPartsNeedZBuffer? 4: 16; // use small steps only if wavy - if( bFlipHoldBody ) + if(part_args.flip_texture_vertically) { - fYHead -= cache->m_iStopDrawingHoldBodyOffsetFromTail; - fYTail -= cache->m_iStartDrawingHoldBodyOffsetFromHead; + y_head -= cache->m_iStopDrawingHoldBodyOffsetFromTail; + y_tail -= cache->m_iStartDrawingHoldBodyOffsetFromHead; } else { - fYHead += cache->m_iStartDrawingHoldBodyOffsetFromHead; - fYTail += cache->m_iStopDrawingHoldBodyOffsetFromTail; + y_head += cache->m_iStartDrawingHoldBodyOffsetFromHead; + y_tail += cache->m_iStopDrawingHoldBodyOffsetFromTail; } - const float fFrameHeightTop = pSpriteTop->GetUnzoomedHeight(); - const float fFrameHeightBottom = pSpriteBottom->GetUnzoomedHeight(); + const float frame_height_top= pSpriteTop->GetUnzoomedHeight(); + const float frame_height_bottom= pSpriteBottom->GetUnzoomedHeight(); - float fYStartPos = ArrowEffects::GetYPos( m_pPlayerState, column_args.column, - field_args.draw_pixels_after_targets, m_fYReverseOffsetPixels ); - float fYEndPos = ArrowEffects::GetYPos( m_pPlayerState, column_args.column, - field_args.draw_pixels_before_targets, m_fYReverseOffsetPixels ); - if( bReverse ) - swap( fYStartPos, fYEndPos ); + part_args.y_start_pos= ArrowEffects::GetYPos(column_args.column, + field_args.draw_pixels_after_targets, m_fYReverseOffsetPixels); + part_args.y_end_pos= ArrowEffects::GetYPos(column_args.column, + field_args.draw_pixels_before_targets, m_fYReverseOffsetPixels); + if(reverse) + { + swap(part_args.y_start_pos, part_args.y_end_pos); + } + // So that part_args.y_start_pos can be changed when drawing the bottom. + const float original_y_start_pos= part_args.y_start_pos; + const float head_minus_top= y_head - frame_height_top; + const float tail_plus_bottom= y_tail + frame_height_bottom; - bool bTopAnchor = bReverse && cache->m_bTopHoldAnchorWhenReverse; + part_args.anchor_to_top= reverse && cache->m_bTopHoldAnchorWhenReverse; - // Draw the top cap - DrawHoldPart(vpSprTop, field_args, column_args, fYStep, fPercentFadeToFail, - fColorScale, bGlow, - tn.HoldResult.fOverlappedTime, - fYHead-fFrameHeightTop, fYHead, - fYStartPos, fYEndPos, - false, bTopAnchor, bFlipHoldBody, top_beat, top_beat); - - // Draw the body - DrawHoldPart(vpSprBody, field_args, column_args, fYStep, fPercentFadeToFail, - fColorScale, bGlow, - tn.HoldResult.fOverlappedTime, - fYHead, fYTail, - fYStartPos, fYEndPos, - true, bTopAnchor, bFlipHoldBody, top_beat, bottom_beat); - - // Draw the bottom cap - DrawHoldPart(vpSprBottom, field_args, column_args, fYStep, fPercentFadeToFail, - fColorScale, bGlow, - tn.HoldResult.fOverlappedTime, - fYTail, fYTail+fFrameHeightBottom, - max(fYStartPos, fYHead), fYEndPos, - false, bTopAnchor, bFlipHoldBody, bottom_beat, bottom_beat); + DISPLAY->SetTextureMode(TextureUnit_1, TextureMode_Modulate); + DrawHoldBodyInternal(vpSprTop, vpSprBody, vpSprBottom, field_args, + column_args, part_args, head_minus_top, + tail_plus_bottom, y_head, y_tail, top_beat, bottom_beat, + false); + part_args.y_start_pos= original_y_start_pos; + DISPLAY->SetTextureMode(TextureUnit_1, TextureMode_Glow); + DrawHoldBodyInternal(vpSprTop, vpSprBody, vpSprBottom, field_args, + column_args, part_args, head_minus_top, + tail_plus_bottom, y_head, y_tail, top_beat, bottom_beat, + true); } void NoteDisplay::DrawHold(const TapNote& tn, @@ -1136,8 +1140,8 @@ void NoteDisplay::DrawHold(const TapNote& tn, if( bReverse ) swap( fStartYOffset, fEndYOffset ); - const float fYHead = ArrowEffects::GetYPos( m_pPlayerState, column_args.column, fStartYOffset, m_fYReverseOffsetPixels ); - const float fYTail = ArrowEffects::GetYPos( m_pPlayerState, column_args.column, fEndYOffset, m_fYReverseOffsetPixels ); + const float fYHead= ArrowEffects::GetYPos(column_args.column, fStartYOffset, m_fYReverseOffsetPixels); + const float fYTail= ArrowEffects::GetYPos(column_args.column, fEndYOffset, m_fYReverseOffsetPixels); const float fColorScale = SCALE( tn.HoldResult.fLife, 0.0f, 1.0f, cache->m_fHoldLetGoGrayPercent, 1.0f ); @@ -1162,8 +1166,7 @@ void NoteDisplay::DrawHold(const TapNote& tn, } */ - DrawHoldBody(tn, field_args, column_args, fBeat, bIsBeingHeld, fYHead, fYTail, bIsAddition, fPercentFadeToFail, fColorScale, false, top_beat, bottom_beat); - DrawHoldBody(tn, field_args, column_args, fBeat, bIsBeingHeld, fYHead, fYTail, bIsAddition, fPercentFadeToFail, fColorScale, true, top_beat, bottom_beat); + DrawHoldBody(tn, field_args, column_args, fBeat, bIsBeingHeld, fYHead, fYTail, fPercentFadeToFail, fColorScale, top_beat, bottom_beat); /* These set the texture mode themselves. */ // this part was modified in pumpmania, where it flips the draw order @@ -1188,12 +1191,14 @@ void NoteDisplay::DrawActor(const TapNote& tn, Actor* pActor, NotePart part, if (tn.type == TapNoteType_AutoKeysound && !GAMESTATE->m_bInStepEditor) return; if(fYOffset < field_args.draw_pixels_after_targets || fYOffset > field_args.draw_pixels_before_targets) + { return; + } float spline_beat= fBeat; if(is_being_held) { spline_beat= column_args.song_beat; } - const float fAlpha = ArrowEffects::GetAlpha( m_pPlayerState, column_args.column, fYOffset, fPercentFadeToFail, m_fYReverseOffsetPixels, field_args.draw_pixels_before_targets, field_args.fade_before_targets ); - const float fGlow = ArrowEffects::GetGlow( m_pPlayerState, column_args.column, fYOffset, fPercentFadeToFail, m_fYReverseOffsetPixels, field_args.draw_pixels_before_targets, field_args.fade_before_targets ); + const float fAlpha= ArrowEffects::GetAlpha(column_args.column, fYOffset, fPercentFadeToFail, m_fYReverseOffsetPixels, field_args.draw_pixels_before_targets, field_args.fade_before_targets); + const float fGlow= ArrowEffects::GetGlow(column_args.column, fYOffset, fPercentFadeToFail, m_fYReverseOffsetPixels, field_args.draw_pixels_before_targets, field_args.fade_before_targets); const RageColor diffuse = RageColor( column_args.diffuse.r * fColorScale, column_args.diffuse.g * fColorScale, @@ -1213,12 +1218,12 @@ void NoteDisplay::DrawActor(const TapNote& tn, Actor* pActor, NotePart part, // same logical structure as in UpdateReceptorGhostStuff, I just haven't // figured out a good way to combine them. -Kyz - vector sp_pos; - vector sp_rot; - vector sp_zoom; - vector ae_pos(3, 0.0f); - vector ae_rot(3, 0.0f); - vector ae_zoom(3, 0.0f); + RageVector3 sp_pos; + RageVector3 sp_rot; + RageVector3 sp_zoom; + RageVector3 ae_pos; + RageVector3 ae_rot; + RageVector3 ae_zoom; column_args.spae_pos_for_beat(m_pPlayerState, spline_beat, fYOffset, m_fYReverseOffsetPixels, sp_pos, ae_pos); @@ -1227,20 +1232,18 @@ void NoteDisplay::DrawActor(const TapNote& tn, Actor* pActor, NotePart part, case NCSM_Disabled: if(!bIsHoldCap) { - ae_rot[0]= ArrowEffects::GetRotationX(m_pPlayerState, fYOffset); + ae_rot.x= ArrowEffects::GetRotationX(fYOffset); } - ae_rot[1]= ArrowEffects::GetRotationY(m_pPlayerState, fYOffset); - ae_rot[2]= ArrowEffects::GetRotationZ(m_pPlayerState, fBeat, bIsHoldHead); - sp_rot.resize(3); - sp_rot[0]= sp_rot[1]= sp_rot[2]= 0.0f; + ae_rot.y= ArrowEffects::GetRotationY(fYOffset); + ae_rot.z= ArrowEffects::GetRotationZ(m_pPlayerState, fBeat, bIsHoldHead); break; case NCSM_Offset: if(!bIsHoldCap) { - ae_rot[0]= ArrowEffects::GetRotationX(m_pPlayerState, fYOffset); + ae_rot.x= ArrowEffects::GetRotationX(fYOffset); } - ae_rot[1]= ArrowEffects::GetRotationY(m_pPlayerState, fYOffset); - ae_rot[2]= ArrowEffects::GetRotationZ(m_pPlayerState, fBeat, bIsHoldHead); + ae_rot.y= ArrowEffects::GetRotationY(fYOffset); + ae_rot.z= ArrowEffects::GetRotationZ(m_pPlayerState, fBeat, bIsHoldHead); column_args.rot_handler->EvalForBeat(column_args.song_beat, spline_beat, sp_rot); break; case NCSM_Position: @@ -1375,21 +1378,16 @@ void NoteColumnRenderer::UpdateReceptorGhostStuff(Actor* receptor) const // sp_* will be zeroes in NCSM_Disabled, and ae_* will be zeroes in // NCSM_Position, so the setting step won't have to check the mode. -Kyz // sp_* are sized by the spline evaluate function. - vector sp_pos; - vector sp_rot; - vector sp_zoom; - vector ae_pos(3, 0.0f); - vector ae_rot(3, 0.0f); - vector ae_zoom(3, 0.0f); + RageVector3 sp_pos; + RageVector3 sp_rot; + RageVector3 sp_zoom; + RageVector3 ae_pos; + RageVector3 ae_rot; + RageVector3 ae_zoom; switch(NCR_current.m_pos_handler.m_spline_mode) { case NCSM_Disabled: ArrowEffects::GetXYZPos(player_state, m_column, 0, m_field_render_args->reverse_offset_pixels, ae_pos); - sp_pos.resize(3); - // Sure, resize is supposed to call the default constructor, and for - // numbers the default constructor is supposed to set it to zero, but - // I got bit for relying on that once. -Kyz - sp_pos[0]= sp_pos[1]= sp_pos[2]= 0.0f; break; case NCSM_Offset: ArrowEffects::GetXYZPos(player_state, m_column, 0, m_field_render_args->reverse_offset_pixels, ae_pos); @@ -1402,12 +1400,10 @@ void NoteColumnRenderer::UpdateReceptorGhostStuff(Actor* receptor) const switch(NCR_current.m_rot_handler.m_spline_mode) { case NCSM_Disabled: - ae_rot[2]= ArrowEffects::ReceptorGetRotationZ(player_state); - sp_rot.resize(3); - sp_rot[0]= sp_rot[1]= sp_rot[2]= 0.0f; + ae_rot.z= ArrowEffects::ReceptorGetRotationZ(player_state); break; case NCSM_Offset: - ae_rot[2]= ArrowEffects::ReceptorGetRotationZ(player_state); + ae_rot.z= ArrowEffects::ReceptorGetRotationZ(player_state); NCR_current.m_rot_handler.EvalForReceptor(song_beat, sp_rot); break; case NCSM_Position: @@ -1417,12 +1413,10 @@ void NoteColumnRenderer::UpdateReceptorGhostStuff(Actor* receptor) const switch(NCR_current.m_zoom_handler.m_spline_mode) { case NCSM_Disabled: - ae_zoom[0]= ae_zoom[1]= ae_zoom[2]= ArrowEffects::GetZoom(player_state); - sp_zoom.resize(3); - sp_zoom[0]= sp_zoom[1]= sp_zoom[2]= 0.0f; + ae_zoom.x= ae_zoom.y= ae_zoom.z= ArrowEffects::GetZoom(player_state); break; case NCSM_Offset: - ae_zoom[0]= ae_zoom[1]= ae_zoom[2]= ArrowEffects::GetZoom(player_state); + ae_zoom.x= ae_zoom.y= ae_zoom.z= ArrowEffects::GetZoom(player_state); NCR_current.m_zoom_handler.EvalForReceptor(song_beat, sp_zoom); break; case NCSM_Position: @@ -1436,6 +1430,7 @@ void NoteColumnRenderer::UpdateReceptorGhostStuff(Actor* receptor) const void NoteColumnRenderer::DrawPrimitives() { + ArrowEffects::SetCurrentOptions(&m_field_render_args->player_state->m_PlayerOptions.GetCurrent()); m_column_render_args.song_beat= m_field_render_args->player_state->GetDisplayedPosition().m_fSongBeatVisible; m_column_render_args.pos_handler= &NCR_current.m_pos_handler; m_column_render_args.rot_handler= &NCR_current.m_rot_handler; diff --git a/src/NoteDisplay.h b/src/NoteDisplay.h index 1a7d008c7f..2727dfbfd1 100644 --- a/src/NoteDisplay.h +++ b/src/NoteDisplay.h @@ -136,9 +136,9 @@ struct NCSplineHandler m_subtract_song_beat_from_curr= true; } float BeatToTValue(float song_beat, float note_beat) const; - void EvalForBeat(float song_beat, float note_beat, vector& ret) const; - void EvalDerivForBeat(float song_beat, float note_beat, vector& ret) const; - void EvalForReceptor(float song_beat, vector& ret) const; + void EvalForBeat(float song_beat, float note_beat, RageVector3& ret) const; + void EvalDerivForBeat(float song_beat, float note_beat, RageVector3& ret) const; + void EvalForReceptor(float song_beat, RageVector3& ret) const; static void MakeWeightedAverage(NCSplineHandler& out, const NCSplineHandler& from, const NCSplineHandler& to, float between); @@ -153,15 +153,15 @@ struct NCSplineHandler struct NoteColumnRenderArgs { - void spae_pos_for_beat(const PlayerState* state, + void spae_pos_for_beat(const PlayerState* player_state, float beat, float y_offset, float y_reverse_offset, - vector& sp_pos, vector& ae_pos) const; + RageVector3& sp_pos, RageVector3& ae_pos) const; void spae_zoom_for_beat(const PlayerState* state, float beat, - vector& sp_zoom, vector& ae_zoom) const; + RageVector3& sp_zoom, RageVector3& ae_zoom) const; void SetPRZForActor(Actor* actor, - const vector& sp_pos, const vector& ae_pos, - const vector& sp_rot, const vector& ae_rot, - const vector& sp_zoom, const vector& ae_zoom) const; + const RageVector3& sp_pos, const RageVector3& ae_pos, + const RageVector3& sp_rot, const RageVector3& ae_rot, + const RageVector3& sp_zoom, const RageVector3& ae_zoom) const; const NCSplineHandler* pos_handler; const NCSplineHandler* rot_handler; const NCSplineHandler* zoom_handler; @@ -221,23 +221,44 @@ private: Actor *GetHoldActor( NoteColorActor nca[NUM_HoldType][NUM_ActiveType], NotePart part, float fNoteBeat, bool bIsRoll, bool bIsBeingHeld ); Sprite *GetHoldSprite( NoteColorSprite ncs[NUM_HoldType][NUM_ActiveType], NotePart part, float fNoteBeat, bool bIsRoll, bool bIsBeingHeld ); + struct draw_hold_part_args + { + int y_step; + float percent_fade_to_fail; + float color_scale; + float overlapped_time; + float y_top; + float y_bottom; + float y_start_pos; + float y_end_pos; + float top_beat; + float bottom_beat; + bool wrapping; + bool anchor_to_top; + bool flip_texture_vertically; + }; + void DrawActor(const TapNote& tn, Actor* pActor, NotePart part, const NoteFieldRenderArgs& field_args, const NoteColumnRenderArgs& column_args, float fYOffset, float fBeat, bool bIsAddition, float fPercentFadeToFail, float fColorScale, bool is_being_held); - void DrawHoldBody(const TapNote& tn, const NoteFieldRenderArgs& field_args, - const NoteColumnRenderArgs& column_args, float fBeat, bool bIsBeingHeld, - float fYHead, float fYTail, - bool bIsAddition, float fPercentFadeToFail, float fColorScale, - bool bGlow, float top_beat, float bottom_beat); void DrawHoldPart(vector &vpSpr, const NoteFieldRenderArgs& field_args, - const NoteColumnRenderArgs& column_args, int fYStep, - float fPercentFadeToFail, float fColorScale, bool bGlow, - float fOverlappedTime, float fYTop, float fYBottom, float fYStartPos, - float fYEndPos, bool bWrapping, bool bAnchorToTop, - bool bFlipTextureVertically, float top_beat, float bottom_beat); + const NoteColumnRenderArgs& column_args, + const draw_hold_part_args& part_args, bool glow); + void DrawHoldBodyInternal(vector& sprite_top, + vector& sprite_body, vector& sprite_bottom, + const NoteFieldRenderArgs& field_args, + const NoteColumnRenderArgs& column_args, + draw_hold_part_args& part_args, + const float head_minus_top, const float tail_plus_bottom, + const float y_head, const float y_tail, const float top_beat, + const float bottom_beat, bool glow); + void DrawHoldBody(const TapNote& tn, const NoteFieldRenderArgs& field_args, + const NoteColumnRenderArgs& column_args, float beat, bool being_held, + float y_head, float y_tail, float percent_fade_to_fail, + float color_scale, float top_beat, float bottom_beat); const PlayerState *m_pPlayerState; // to look up PlayerOptions NoteMetricCache_t *cache; diff --git a/src/NoteField.cpp b/src/NoteField.cpp index 82fb8bbdbe..7e28ca1b74 100644 --- a/src/NoteField.cpp +++ b/src/NoteField.cpp @@ -299,6 +299,7 @@ void NoteField::Update( float fDeltaTime ) } ActorFrame::Update( fDeltaTime ); + ArrowEffects::SetCurrentOptions(&m_pPlayerState->m_PlayerOptions.GetCurrent()); for(size_t c= 0; c < m_ColumnRenderers.size(); ++c) { @@ -310,8 +311,8 @@ void NoteField::Update( float fDeltaTime ) bool bTweeningOn = m_sprBoard->GetCurrentDiffuseAlpha() >= 0.98 && m_sprBoard->GetCurrentDiffuseAlpha() < 1.00; // HACK if( !bTweeningOn && m_fCurrentBeatLastUpdate != -1 ) { - const float fYOffsetLast = ArrowEffects::GetYOffset( m_pPlayerState, 0, m_fCurrentBeatLastUpdate ); - const float fYPosLast = ArrowEffects::GetYPos( m_pPlayerState, 0, fYOffsetLast, m_fYReverseOffsetPixels ); + const float fYOffsetLast = ArrowEffects::GetYOffset(m_pPlayerState, 0, m_fCurrentBeatLastUpdate); + const float fYPosLast= ArrowEffects::GetYPos(0, fYOffsetLast, m_fYReverseOffsetPixels); const float fPixelDifference = fYPosLast - m_fYPosCurrentBeatLastUpdate; //LOG->Trace( "speed = %f, %f, %f, %f, %f, %f", fSpeed, fYOffsetAtCurrent, fYOffsetAtNext, fSecondsAtCurrent, fSecondsAtNext, fPixelDifference, fSecondsDifference ); @@ -321,7 +322,7 @@ void NoteField::Update( float fDeltaTime ) } m_fCurrentBeatLastUpdate = fCurrentBeat; const float fYOffsetCurrent = ArrowEffects::GetYOffset( m_pPlayerState, 0, m_fCurrentBeatLastUpdate ); - m_fYPosCurrentBeatLastUpdate = ArrowEffects::GetYPos( m_pPlayerState, 0, fYOffsetCurrent, m_fYReverseOffsetPixels ); + m_fYPosCurrentBeatLastUpdate= ArrowEffects::GetYPos(0, fYOffsetCurrent, m_fYReverseOffsetPixels); m_rectMarkerBar.Update( fDeltaTime ); @@ -362,7 +363,7 @@ void NoteField::DrawBeatBar( const float fBeat, BeatBarType type, int iMeasureIn bool bIsMeasure = type == measure; const float fYOffset = ArrowEffects::GetYOffset( m_pPlayerState, 0, fBeat ); - const float fYPos = ArrowEffects::GetYPos( m_pPlayerState, 0, fYOffset, m_fYReverseOffsetPixels ); + const float fYPos= ArrowEffects::GetYPos(0, fYOffset, m_fYReverseOffsetPixels); float fAlpha; int iState; @@ -434,7 +435,7 @@ void NoteField::DrawBoard( int iDrawDistanceAfterTargetsPixels, int iDrawDistanc { // Draw the board centered on fYPosAt0 so that the board doesn't slide as // the draw distance changes with modifiers. - const float fYPosAt0 = ArrowEffects::GetYPos( m_pPlayerState, 0, 0, m_fYReverseOffsetPixels ); + const float fYPosAt0= ArrowEffects::GetYPos(0, 0, m_fYReverseOffsetPixels); RectF rect = *pSprite->GetCurrentTextureCoordRect(); const float fBoardGraphicHeightPixels = pSprite->GetUnzoomedHeight(); @@ -461,7 +462,7 @@ void NoteField::DrawMarkerBar( int iBeat ) { float fBeat = NoteRowToBeat( iBeat ); const float fYOffset = ArrowEffects::GetYOffset( m_pPlayerState, 0, fBeat ); - const float fYPos = ArrowEffects::GetYPos( m_pPlayerState, 0, fYOffset, m_fYReverseOffsetPixels ); + const float fYPos = ArrowEffects::GetYPos(0, fYOffset, m_fYReverseOffsetPixels); m_rectMarkerBar.StretchTo( RectF(-GetWidth()/2, fYPos-ARROW_SIZE/2, GetWidth()/2, fYPos+ARROW_SIZE/2) ); m_rectMarkerBar.Draw(); @@ -473,9 +474,9 @@ void NoteField::DrawAreaHighlight( int iStartBeat, int iEndBeat ) float fStartBeat = NoteRowToBeat( iStartBeat ); float fEndBeat = NoteRowToBeat( iEndBeat ); float fDrawDistanceAfterTargetsPixels = ArrowEffects::GetYOffset( m_pPlayerState, 0, fStartBeat ); - float fYStartPos = ArrowEffects::GetYPos( m_pPlayerState, 0, fDrawDistanceAfterTargetsPixels, m_fYReverseOffsetPixels ); + float fYStartPos = ArrowEffects::GetYPos(0, fDrawDistanceAfterTargetsPixels, m_fYReverseOffsetPixels); float fDrawDistanceBeforeTargetsPixels = ArrowEffects::GetYOffset( m_pPlayerState, 0, fEndBeat ); - float fYEndPos = ArrowEffects::GetYPos( m_pPlayerState, 0, fDrawDistanceBeforeTargetsPixels, m_fYReverseOffsetPixels ); + float fYEndPos= ArrowEffects::GetYPos(0, fDrawDistanceBeforeTargetsPixels, m_fYReverseOffsetPixels); // The caller should have clamped these to reasonable values ASSERT( fYStartPos > -1000 ); @@ -492,7 +493,7 @@ static ThemeMetric BPM_COLOR ( "NoteField", "BPMColor" ); static ThemeMetric STOP_COLOR ( "NoteField", "StopColor" ); static ThemeMetric DELAY_COLOR ( "NoteField", "DelayColor" ); static ThemeMetric WARP_COLOR ( "NoteField", "WarpColor" ); -static ThemeMetric TIME_SIGNATURE_COLOR ( "NoteField", "TimeSignatureColor" ); +static ThemeMetric TIME_SIG_COLOR ( "NoteField", "TimeSignatureColor" ); static ThemeMetric TICKCOUNT_COLOR ( "NoteField", "TickcountColor" ); static ThemeMetric COMBO_COLOR ( "NoteField", "ComboColor" ); static ThemeMetric LABEL_COLOR ( "NoteField", "LabelColor" ); @@ -503,7 +504,7 @@ static ThemeMetric BPM_IS_LEFT_SIDE ( "NoteField", "BPMIsLeftSide" ); static ThemeMetric STOP_IS_LEFT_SIDE ( "NoteField", "StopIsLeftSide" ); static ThemeMetric DELAY_IS_LEFT_SIDE ( "NoteField", "DelayIsLeftSide" ); static ThemeMetric WARP_IS_LEFT_SIDE ( "NoteField", "WarpIsLeftSide" ); -static ThemeMetric TIME_SIGNATURE_IS_LEFT_SIDE ( "NoteField", "TimeSignatureIsLeftSide" ); +static ThemeMetric TIME_SIG_IS_LEFT_SIDE ( "NoteField", "TimeSignatureIsLeftSide" ); static ThemeMetric TICKCOUNT_IS_LEFT_SIDE ( "NoteField", "TickcountIsLeftSide" ); static ThemeMetric COMBO_IS_LEFT_SIDE ( "NoteField", "ComboIsLeftSide" ); static ThemeMetric LABEL_IS_LEFT_SIDE ( "NoteField", "LabelIsLeftSide" ); @@ -514,7 +515,7 @@ static ThemeMetric BPM_OFFSETX ( "NoteField", "BPMOffsetX" ); static ThemeMetric STOP_OFFSETX ( "NoteField", "StopOffsetX" ); static ThemeMetric DELAY_OFFSETX ( "NoteField", "DelayOffsetX" ); static ThemeMetric WARP_OFFSETX ( "NoteField", "WarpOffsetX" ); -static ThemeMetric TIME_SIGNATURE_OFFSETX ( "NoteField", "TimeSignatureOffsetX" ); +static ThemeMetric TIME_SIG_OFFSETX ( "NoteField", "TimeSignatureOffsetX" ); static ThemeMetric TICKCOUNT_OFFSETX ( "NoteField", "TickcountOffsetX" ); static ThemeMetric COMBO_OFFSETX ( "NoteField", "ComboOffsetX" ); static ThemeMetric LABEL_OFFSETX ( "NoteField", "LabelOffsetX" ); @@ -522,220 +523,48 @@ static ThemeMetric SPEED_OFFSETX ( "NoteField", "SpeedOffsetX" ); static ThemeMetric SCROLL_OFFSETX ( "NoteField", "ScrollOffsetX" ); static ThemeMetric FAKE_OFFSETX ( "NoteField", "FakeOffsetX" ); -void NoteField::DrawBPMText( const float fBeat, const float fBPM ) +void NoteField::set_text_measure_number_for_draw( + const float beat, const float side_sign, float x_offset, + const float horiz_align, const RageColor& color, const RageColor& glow) { - const float fYOffset = ArrowEffects::GetYOffset( m_pPlayerState, 0, fBeat ); - const float fYPos = ArrowEffects::GetYPos( m_pPlayerState, 0, fYOffset, m_fYReverseOffsetPixels ); - const float fZoom = ArrowEffects::GetZoom( m_pPlayerState ); - const float xBase = GetWidth()/2.f; - const float xOffset = BPM_OFFSETX * fZoom; + const float y_offset= ArrowEffects::GetYOffset(m_pPlayerState, 0, beat); + const float y_pos= ArrowEffects::GetYPos(0, y_offset, m_fYReverseOffsetPixels); + const float zoom= ArrowEffects::GetZoom(m_pPlayerState); + const float x_base= GetWidth() * .5f; + x_offset*= zoom; - m_textMeasureNumber.SetZoom( fZoom ); - m_textMeasureNumber.SetHorizAlign( BPM_IS_LEFT_SIDE ? align_right : align_left ); - m_textMeasureNumber.SetDiffuse( BPM_COLOR ); - m_textMeasureNumber.SetGlow( RageColor(1,1,1,RageFastCos(RageTimer::GetTimeSinceStartFast()*2)/2+0.5f) ); - m_textMeasureNumber.SetText( FloatToString(fBPM) ); - m_textMeasureNumber.SetXY( (BPM_IS_LEFT_SIDE ? -xBase - xOffset : xBase + xOffset), fYPos ); + m_textMeasureNumber.SetZoom(zoom); + m_textMeasureNumber.SetHorizAlign(horiz_align); + m_textMeasureNumber.SetDiffuse(color); + m_textMeasureNumber.SetGlow(glow); + m_textMeasureNumber.SetXY((x_offset + x_base) * side_sign, y_pos); +} + +void NoteField::draw_timing_segment_text(const RString& text, + const float beat, const float side_sign, float x_offset, + const float horiz_align, const RageColor& color, const RageColor& glow) +{ + set_text_measure_number_for_draw(beat, side_sign, x_offset, horiz_align, + color, glow); + m_textMeasureNumber.SetText(text); m_textMeasureNumber.Draw(); } -void NoteField::DrawFreezeText( const float fBeat, const float fSecs ) +void NoteField::DrawAttackText(const float beat, const Attack &attack, + const RageColor& glow) { - const float fYOffset = ArrowEffects::GetYOffset( m_pPlayerState, 0, fBeat ); - const float fYPos = ArrowEffects::GetYPos( m_pPlayerState, 0, fYOffset, m_fYReverseOffsetPixels ); - const float fZoom = ArrowEffects::GetZoom( m_pPlayerState ); - const float xBase = GetWidth()/2.f; - const float xOffset = STOP_OFFSETX * fZoom; - - m_textMeasureNumber.SetZoom( fZoom ); - m_textMeasureNumber.SetHorizAlign( STOP_IS_LEFT_SIDE ? align_right : align_left ); - m_textMeasureNumber.SetDiffuse( STOP_COLOR ); - m_textMeasureNumber.SetXY( (STOP_IS_LEFT_SIDE ? -xBase - xOffset : xBase + xOffset), fYPos ); - m_textMeasureNumber.SetGlow( RageColor(1,1,1,RageFastCos(RageTimer::GetTimeSinceStartFast()*2)/2+0.5f) ); - m_textMeasureNumber.SetText( FloatToString(fSecs) ); - m_textMeasureNumber.Draw(); -} - -void NoteField::DrawDelayText( const float fBeat, const float fSecs ) -{ - const float fYOffset = ArrowEffects::GetYOffset( m_pPlayerState, 0, fBeat ); - const float fYPos = ArrowEffects::GetYPos( m_pPlayerState, 0, fYOffset, m_fYReverseOffsetPixels ); - const float fZoom = ArrowEffects::GetZoom( m_pPlayerState ); - const float xBase = GetWidth()/2.f; - const float xOffset = DELAY_OFFSETX * fZoom; - - m_textMeasureNumber.SetZoom( fZoom ); - m_textMeasureNumber.SetHorizAlign( DELAY_IS_LEFT_SIDE ? align_right : align_left ); - m_textMeasureNumber.SetDiffuse( DELAY_COLOR ); - m_textMeasureNumber.SetXY( (DELAY_IS_LEFT_SIDE ? -xBase - xOffset : xBase + xOffset), fYPos ); - m_textMeasureNumber.SetGlow( RageColor(1,1,1,RageFastCos(RageTimer::GetTimeSinceStartFast()*2)/2+0.5f) ); - m_textMeasureNumber.SetText( FloatToString(fSecs) ); - m_textMeasureNumber.Draw(); -} - -void NoteField::DrawWarpText( const float fBeat, const float fNewBeat ) -{ - const float fYOffset = ArrowEffects::GetYOffset( m_pPlayerState, 0, fBeat ); - const float fYPos = ArrowEffects::GetYPos( m_pPlayerState, 0, fYOffset, m_fYReverseOffsetPixels ); - const float fZoom = ArrowEffects::GetZoom( m_pPlayerState ); - const float xBase = GetWidth()/2.f; - const float xOffset = WARP_OFFSETX * fZoom; - - m_textMeasureNumber.SetZoom( fZoom ); - m_textMeasureNumber.SetHorizAlign( WARP_IS_LEFT_SIDE ? align_right : align_left ); - m_textMeasureNumber.SetDiffuse( WARP_COLOR ); - m_textMeasureNumber.SetGlow( RageColor(1,1,1,RageFastCos(RageTimer::GetTimeSinceStartFast()*2)/2+0.5f) ); - m_textMeasureNumber.SetText( FloatToString(fNewBeat) ); - m_textMeasureNumber.SetXY( (WARP_IS_LEFT_SIDE ? -xBase - xOffset : xBase + xOffset), fYPos ); - m_textMeasureNumber.Draw(); -} - -void NoteField::DrawTimeSignatureText( const float fBeat, int iNumerator, int iDenominator ) -{ - const float fYOffset = ArrowEffects::GetYOffset( m_pPlayerState, 0, fBeat ); - const float fYPos = ArrowEffects::GetYPos( m_pPlayerState, 0, fYOffset, m_fYReverseOffsetPixels ); - const float fZoom = ArrowEffects::GetZoom( m_pPlayerState ); - const float xBase = GetWidth()/2.f; - const float xOffset = TIME_SIGNATURE_OFFSETX * fZoom; - - m_textMeasureNumber.SetZoom( fZoom ); - m_textMeasureNumber.SetHorizAlign( TIME_SIGNATURE_IS_LEFT_SIDE ? align_right : align_left ); - m_textMeasureNumber.SetDiffuse( TIME_SIGNATURE_COLOR ); - m_textMeasureNumber.SetGlow( RageColor(1,1,1,RageFastCos(RageTimer::GetTimeSinceStartFast()*2)/2+0.5f) ); - m_textMeasureNumber.SetText( ssprintf("%d\n--\n%d", iNumerator, iDenominator) ); - m_textMeasureNumber.SetXY( (TIME_SIGNATURE_IS_LEFT_SIDE ? -xBase - xOffset : xBase + xOffset), fYPos ); - m_textMeasureNumber.Draw(); -} - -void NoteField::DrawTickcountText( const float fBeat, int iTicks ) -{ - const float fYOffset = ArrowEffects::GetYOffset( m_pPlayerState, 0, fBeat ); - const float fYPos = ArrowEffects::GetYPos( m_pPlayerState, 0, fYOffset, m_fYReverseOffsetPixels ); - const float fZoom = ArrowEffects::GetZoom( m_pPlayerState ); - const float xBase = GetWidth()/2.f; - const float xOffset = TICKCOUNT_OFFSETX * fZoom; - - m_textMeasureNumber.SetZoom( fZoom ); - m_textMeasureNumber.SetHorizAlign( TICKCOUNT_IS_LEFT_SIDE ? align_right : align_left ); - m_textMeasureNumber.SetDiffuse( TICKCOUNT_COLOR ); - m_textMeasureNumber.SetGlow( RageColor(1,1,1,RageFastCos(RageTimer::GetTimeSinceStartFast()*2)/2+0.5f) ); - m_textMeasureNumber.SetText( ssprintf("%d", iTicks) ); - m_textMeasureNumber.SetXY( (TICKCOUNT_IS_LEFT_SIDE ? -xBase - xOffset : xBase + xOffset), fYPos ); - m_textMeasureNumber.Draw(); -} - -void NoteField::DrawComboText( const float fBeat, int iCombo, int iMiss ) -{ - const float fYOffset = ArrowEffects::GetYOffset( m_pPlayerState, 0, fBeat ); - const float fYPos = ArrowEffects::GetYPos( m_pPlayerState, 0, fYOffset, m_fYReverseOffsetPixels ); - const float fZoom = ArrowEffects::GetZoom( m_pPlayerState ); - const float xBase = GetWidth()/2.f; - const float xOffset = COMBO_OFFSETX * fZoom; - - m_textMeasureNumber.SetZoom( fZoom ); - m_textMeasureNumber.SetHorizAlign( COMBO_IS_LEFT_SIDE ? align_right : align_left ); - m_textMeasureNumber.SetDiffuse( COMBO_COLOR ); - m_textMeasureNumber.SetGlow( RageColor(1,1,1,RageFastCos(RageTimer::GetTimeSinceStartFast()*2)/2+0.5f) ); - m_textMeasureNumber.SetText( ssprintf("%d/%d", iCombo, iMiss) ); - m_textMeasureNumber.SetXY( (COMBO_IS_LEFT_SIDE ? -xBase - xOffset : xBase + xOffset), fYPos ); - m_textMeasureNumber.Draw(); -} - -void NoteField::DrawLabelText( const float fBeat, RString sLabel ) -{ - const float fYOffset = ArrowEffects::GetYOffset( m_pPlayerState, 0, fBeat ); - const float fYPos = ArrowEffects::GetYPos( m_pPlayerState, 0, fYOffset, m_fYReverseOffsetPixels ); - const float fZoom = ArrowEffects::GetZoom( m_pPlayerState ); - const float xBase = GetWidth()/2.f; - const float xOffset = LABEL_OFFSETX * fZoom; - - m_textMeasureNumber.SetZoom( fZoom ); - m_textMeasureNumber.SetHorizAlign( LABEL_IS_LEFT_SIDE ? align_right : align_left ); - m_textMeasureNumber.SetDiffuse( LABEL_COLOR ); - m_textMeasureNumber.SetGlow( RageColor(1,1,1,RageFastCos(RageTimer::GetTimeSinceStartFast()*2)/2+0.5f) ); - m_textMeasureNumber.SetText( sLabel.c_str() ); - m_textMeasureNumber.SetXY( (LABEL_IS_LEFT_SIDE ? -xBase - xOffset : xBase + xOffset), fYPos ); - m_textMeasureNumber.Draw(); -} - -void NoteField::DrawSpeedText( const float fBeat, float fPercent, float fWait, int iMode ) -{ - const float fYOffset = ArrowEffects::GetYOffset( m_pPlayerState, 0, fBeat ); - const float fYPos = ArrowEffects::GetYPos( m_pPlayerState, 0, fYOffset, m_fYReverseOffsetPixels ); - const float fZoom = ArrowEffects::GetZoom( m_pPlayerState ); - const float xBase = GetWidth()/2.f; - const float xOffset = SPEED_OFFSETX * fZoom; - - m_textMeasureNumber.SetZoom( fZoom ); - m_textMeasureNumber.SetHorizAlign( SPEED_IS_LEFT_SIDE ? align_right : align_left ); - m_textMeasureNumber.SetDiffuse( SPEED_COLOR ); - m_textMeasureNumber.SetGlow( RageColor(1,1,1,RageFastCos(RageTimer::GetTimeSinceStartFast()*2)/2+0.5f) ); - m_textMeasureNumber.SetText( ssprintf("%s\n%s\n%s", FloatToString(fPercent).c_str(), (iMode == 1 ? "S" : "B"), FloatToString(fWait).c_str()) ); - m_textMeasureNumber.SetXY( (SPEED_IS_LEFT_SIDE ? -xBase - xOffset : xBase + xOffset), fYPos ); - m_textMeasureNumber.Draw(); -} - -void NoteField::DrawScrollText( const float fBeat, float fPercent ) -{ - const float fYOffset = ArrowEffects::GetYOffset( m_pPlayerState, 0, fBeat ); - const float fYPos = ArrowEffects::GetYPos( m_pPlayerState, 0, fYOffset, m_fYReverseOffsetPixels ); - const float fZoom = ArrowEffects::GetZoom( m_pPlayerState ); - const float xBase = GetWidth()/2.f; - const float xOffset = SCROLL_OFFSETX * fZoom; - - m_textMeasureNumber.SetZoom( fZoom ); - m_textMeasureNumber.SetHorizAlign( SCROLL_IS_LEFT_SIDE ? align_right : align_left ); - m_textMeasureNumber.SetDiffuse( SCROLL_COLOR ); - m_textMeasureNumber.SetGlow( RageColor(1,1,1,RageFastCos(RageTimer::GetTimeSinceStartFast()*2)/2+0.5f) ); - m_textMeasureNumber.SetText( FloatToString(fPercent) ); - m_textMeasureNumber.SetXY( (SCROLL_IS_LEFT_SIDE ? -xBase - xOffset : xBase + xOffset), fYPos ); - m_textMeasureNumber.Draw(); -} - -void NoteField::DrawFakeText( const float fBeat, const float fNewBeat ) -{ - const float fYOffset = ArrowEffects::GetYOffset( m_pPlayerState, 0, fBeat ); - const float fYPos = ArrowEffects::GetYPos( m_pPlayerState, 0, fYOffset, m_fYReverseOffsetPixels ); - const float fZoom = ArrowEffects::GetZoom( m_pPlayerState ); - const float xBase = GetWidth()/2.f; - const float xOffset = FAKE_OFFSETX * fZoom; - - m_textMeasureNumber.SetZoom( fZoom ); - m_textMeasureNumber.SetHorizAlign( FAKE_IS_LEFT_SIDE ? align_right : align_left ); - m_textMeasureNumber.SetDiffuse( FAKE_COLOR ); - m_textMeasureNumber.SetGlow( RageColor(1,1,1,RageFastCos(RageTimer::GetTimeSinceStartFast()*2)/2+0.5f) ); - m_textMeasureNumber.SetText( FloatToString(fNewBeat) ); - m_textMeasureNumber.SetXY( (FAKE_IS_LEFT_SIDE ? -xBase - xOffset : xBase + xOffset), fYPos ); - m_textMeasureNumber.Draw(); -} - -void NoteField::DrawAttackText( const float fBeat, const Attack &attack ) -{ - const float fYOffset = ArrowEffects::GetYOffset( m_pPlayerState, 0, fBeat ); - const float fYPos = ArrowEffects::GetYPos( m_pPlayerState, 0, fYOffset, m_fYReverseOffsetPixels ); - const float fZoom = ArrowEffects::GetZoom( m_pPlayerState ); - - m_textMeasureNumber.SetZoom( fZoom ); - m_textMeasureNumber.SetHorizAlign( align_left ); - m_textMeasureNumber.SetDiffuse( RageColor(0,0.8f,0.8f,1) ); - m_textMeasureNumber.SetGlow( RageColor(1,1,1,RageFastCos(RageTimer::GetTimeSinceStartFast()*2)/2+0.5f) ); + set_text_measure_number_for_draw(beat, 1, 10, align_left, + RageColor(0,0.8f,0.8f,1), glow); m_textMeasureNumber.SetText( attack.GetTextDescription() ); - m_textMeasureNumber.SetXY( +GetWidth()/2.f + 10*fZoom, fYPos ); m_textMeasureNumber.Draw(); } -void NoteField::DrawBGChangeText( const float fBeat, const RString sNewBGName ) +void NoteField::DrawBGChangeText(const float beat, const RString new_bg_name, + const RageColor& glow) { - const float fYOffset = ArrowEffects::GetYOffset( m_pPlayerState, 0, fBeat ); - const float fYPos = ArrowEffects::GetYPos( m_pPlayerState, 0, fYOffset, m_fYReverseOffsetPixels ); - const float fZoom = ArrowEffects::GetZoom( m_pPlayerState ); - - m_textMeasureNumber.SetZoom( fZoom ); - m_textMeasureNumber.SetHorizAlign( align_left ); - m_textMeasureNumber.SetDiffuse( RageColor(0,1,0,1) ); - m_textMeasureNumber.SetGlow( RageColor(1,1,1,RageFastCos(RageTimer::GetTimeSinceStartFast()*2)/2+0.5f) ); - m_textMeasureNumber.SetText( sNewBGName ); - m_textMeasureNumber.SetXY( +GetWidth()/2.f, fYPos ); + set_text_measure_number_for_draw(beat, 1, 0, align_left, RageColor(0,1,0,1), + glow); + m_textMeasureNumber.SetText(new_bg_name); m_textMeasureNumber.Draw(); } @@ -993,139 +822,42 @@ void NoteField::DrawPrimitives() ASSERT(GAMESTATE->m_pCurSong != NULL); const TimingData &timing = *pTiming; + const RageColor text_glow= RageColor(1,1,1,RageFastCos(RageTimer::GetTimeSinceStartFast()*2)/2+0.5f); - // Scroll text - for (i = 0; i < segs[SEGMENT_SCROLL]->size(); i++) - { - ScrollSegment *seg = ToScroll( segs[SEGMENT_SCROLL]->at(i) ); - if( seg->GetRow() >= m_FieldRenderArgs.first_row && seg->GetRow() <= m_FieldRenderArgs.last_row ) - { - float fBeat = seg->GetBeat(); - if( IS_ON_SCREEN(fBeat) ) - DrawScrollText( fBeat, seg->GetRatio() ); - } + float horiz_align= align_right; + float side_sign= 1; +#define draw_all_segments(str_exp, name, caps_name) \ + horiz_align= caps_name##_IS_LEFT_SIDE ? align_right : align_left; \ + side_sign= caps_name##_IS_LEFT_SIDE ? -1 : 1; \ + for(unsigned int i= 0; i < segs[SEGMENT_##caps_name]->size(); ++i) \ + { \ + const name##Segment* seg= To##name((*segs[SEGMENT_##caps_name])[i]); \ + if(seg->GetRow() >= m_FieldRenderArgs.first_row && \ + seg->GetRow() <= m_FieldRenderArgs.last_row && \ + IS_ON_SCREEN(seg->GetBeat())) \ + { \ + draw_timing_segment_text(str_exp, beat, side_sign, \ + caps_name##_OFFSETX, horiz_align, caps_name##_COLOR, text_glow); \ + } \ } - // BPM text - for (i = 0; i < segs[SEGMENT_BPM]->size(); i++) - { - const BPMSegment *seg = ToBPM( segs[SEGMENT_BPM]->at(i) ); - if( seg->GetRow() >= m_FieldRenderArgs.first_row && seg->GetRow() <= m_FieldRenderArgs.last_row ) - { - float fBeat = seg->GetBeat(); - if( IS_ON_SCREEN(fBeat) ) - DrawBPMText( fBeat, seg->GetBPM() ); - } - } - - // Freeze text - for (i = 0; i < segs[SEGMENT_STOP]->size(); i++) - { - const StopSegment *seg = ToStop( segs[SEGMENT_STOP]->at(i) ); - if( seg->GetRow() >= m_FieldRenderArgs.first_row && seg->GetRow() <= m_FieldRenderArgs.last_row ) - { - float fBeat = seg->GetBeat(); - if( IS_ON_SCREEN(fBeat) ) - DrawFreezeText( fBeat, seg->GetPause() ); - } - } - - // Delay text - for (i = 0; i < segs[SEGMENT_DELAY]->size(); i++) - { - const DelaySegment *seg = ToDelay( segs[SEGMENT_DELAY]->at(i) ); - if( seg->GetRow() >= m_FieldRenderArgs.first_row && seg->GetRow() <= m_FieldRenderArgs.last_row ) - { - float fBeat = seg->GetBeat(); - if( IS_ON_SCREEN(fBeat) ) - DrawDelayText( fBeat, seg->GetPause() ); - } - } - - // Warp text - for (i = 0; i < segs[SEGMENT_WARP]->size(); i++) - { - const WarpSegment *seg = ToWarp( segs[SEGMENT_WARP]->at(i) ); - if( seg->GetRow() >= m_FieldRenderArgs.first_row && seg->GetRow() <= m_FieldRenderArgs.last_row ) - { - float fBeat = seg->GetBeat(); - if( IS_ON_SCREEN(fBeat) ) - DrawWarpText( fBeat, seg->GetLength() ); - } - } - - // Time Signature text - for (i = 0; i < segs[SEGMENT_TIME_SIG]->size(); i++) - { - const TimeSignatureSegment *seg = ToTimeSignature( segs[SEGMENT_TIME_SIG]->at(i) ); - if( seg->GetRow() >= m_FieldRenderArgs.first_row && seg->GetRow() <= m_FieldRenderArgs.last_row ) - { - float fBeat = seg->GetBeat(); - if( IS_ON_SCREEN(fBeat) ) - DrawTimeSignatureText( fBeat, seg->GetNum(), seg->GetDen() ); - } - } - - // Tickcount text - for (i = 0; i < segs[SEGMENT_TICKCOUNT]->size(); i++) - { - const TickcountSegment *seg = ToTickcount( segs[SEGMENT_TICKCOUNT]->at(i) ); - if( seg->GetRow() >= m_FieldRenderArgs.first_row && seg->GetRow() <= m_FieldRenderArgs.last_row ) - { - float fBeat = seg->GetBeat(); - if( IS_ON_SCREEN(fBeat) ) - DrawTickcountText( fBeat, seg->GetTicks() ); - } - } - - // Combo text - for (i = 0; i < segs[SEGMENT_COMBO]->size(); i++) - { - const ComboSegment *seg = ToCombo( segs[SEGMENT_COMBO]->at(i) ); - if( seg->GetRow() >= m_FieldRenderArgs.first_row && seg->GetRow() <= m_FieldRenderArgs.last_row ) - { - float fBeat = seg->GetBeat(); - if( IS_ON_SCREEN(fBeat) ) - DrawComboText( fBeat, seg->GetCombo(), seg->GetMissCombo() ); - } - } - - // Label text - for (i = 0; i < segs[SEGMENT_LABEL]->size(); i++) - { - const LabelSegment *seg = ToLabel( segs[SEGMENT_LABEL]->at(i) ); - if( seg->GetRow() >= m_FieldRenderArgs.first_row && seg->GetRow() <= m_FieldRenderArgs.last_row ) - { - float fBeat = seg->GetBeat(); - if( IS_ON_SCREEN(fBeat) ) - DrawLabelText( fBeat, seg->GetLabel() ); - } - } - - // Speed text - for (i = 0; i < segs[SEGMENT_SPEED]->size(); i++) - { - const SpeedSegment *seg = ToSpeed( segs[SEGMENT_SPEED]->at(i) ); - if( seg->GetRow() >= m_FieldRenderArgs.first_row && seg->GetRow() <= m_FieldRenderArgs.last_row ) - { - float fBeat = seg->GetBeat(); - if( IS_ON_SCREEN(fBeat) ) - DrawSpeedText(fBeat, seg->GetRatio(), - seg->GetDelay(), seg->GetUnit() ); - } - } - - // Fake text - for (i = 0; i < segs[SEGMENT_FAKE]->size(); i++) - { - const FakeSegment *seg = ToFake( segs[SEGMENT_FAKE]->at(i) ); - if( seg->GetRow() >= m_FieldRenderArgs.first_row && seg->GetRow() <= m_FieldRenderArgs.last_row ) - { - float fBeat = seg->GetBeat(); - if( IS_ON_SCREEN(fBeat) ) - DrawFakeText( fBeat, seg->GetLength() ); - } - } + draw_all_segments(FloatToString(seg->GetRatio()), Scroll, SCROLL); + draw_all_segments(FloatToString(seg->GetBPM()), BPM, BPM); + draw_all_segments(FloatToString(seg->GetPause()), Stop, STOP); + draw_all_segments(FloatToString(seg->GetPause()), Delay, DELAY); + draw_all_segments(FloatToString(seg->GetLength()), Warp, WARP); + draw_all_segments(ssprintf("%d\n--\n%d", seg->GetNum(), seg->GetDen()), + TimeSignature, TIME_SIG); + draw_all_segments(ssprintf("%d", seg->GetTicks()), Tickcount, TICKCOUNT); + draw_all_segments( + ssprintf("%d/%d", seg->GetCombo(), seg->GetMissCombo()), Combo, COMBO); + draw_all_segments(seg->GetLabel(), Label, LABEL); + draw_all_segments(ssprintf("%s\n%s\n%s", + FloatToString(seg->GetRatio()).c_str(), + (seg->GetUnit() == 1 ? "S" : "B"), + FloatToString(seg->GetDelay()).c_str()), Speed, SPEED); + draw_all_segments(FloatToString(seg->GetLength()), Fake, FAKE); +#undef draw_all_segments // Course mods text const Course *pCourse = GAMESTATE->m_pCurCourse; @@ -1140,10 +872,10 @@ void NoteField::DrawPrimitives() float fBeat = timing.GetBeatFromElapsedTime( fSecond ); if( BeatToNoteRow(fBeat) >= m_FieldRenderArgs.first_row && - BeatToNoteRow(fBeat) <= m_FieldRenderArgs.last_row) + BeatToNoteRow(fBeat) <= m_FieldRenderArgs.last_row && + IS_ON_SCREEN(fBeat)) { - if( IS_ON_SCREEN(fBeat) ) - DrawAttackText( fBeat, *a ); + DrawAttackText(fBeat, *a, text_glow); } } } @@ -1162,7 +894,7 @@ void NoteField::DrawPrimitives() BeatToNoteRow(fBeat) <= m_FieldRenderArgs.last_row && IS_ON_SCREEN(fBeat)) { - this->DrawAttackText(fBeat, *a); + this->DrawAttackText(fBeat, *a, text_glow); } } } @@ -1226,7 +958,7 @@ void NoteField::DrawPrimitives() s = ssprintf("%d: ",*bl) + s; vsBGChanges.push_back( s ); } - DrawBGChangeText( fLowestBeat, join("\n",vsBGChanges) ); + DrawBGChangeText(fLowestBeat, join("\n",vsBGChanges), text_glow); } FOREACH_CONST( BackgroundLayer, viLowestIndex, bl ) iter[*bl]++; @@ -1270,8 +1002,12 @@ void NoteField::DrawPrimitives() ssprintf("NumTracks %d != ColsPerPlayer %d",m_pNoteData->GetNumTracks(), GAMESTATE->GetCurrentStyle(m_pPlayerState->m_PlayerNumber)->m_iColsPerPlayer)); - m_FieldRenderArgs.selection_glow= SCALE( - RageFastCos(RageTimer::GetTimeSinceStartFast()*2), -1, 1, 0.1f, 0.3f); + if(*m_FieldRenderArgs.selection_begin_marker != -1 && + *m_FieldRenderArgs.selection_end_marker != -1) + { + m_FieldRenderArgs.selection_glow= SCALE( + RageFastCos(RageTimer::GetTimeSinceStartFast()*2), -1, 1, 0.1f, 0.3f); + } m_FieldRenderArgs.fade_before_targets= FADE_BEFORE_TARGETS_PERCENT; for( int j=0; jGetNumTracks(); j++ ) // for each arrow column diff --git a/src/NoteField.h b/src/NoteField.h index 67d47ce911..f49670131a 100644 --- a/src/NoteField.h +++ b/src/NoteField.h @@ -75,19 +75,14 @@ protected: void DrawBeatBar( const float fBeat, BeatBarType type, int iMeasureIndex ); void DrawMarkerBar( int fBeat ); void DrawAreaHighlight( int iStartBeat, int iEndBeat ); - void DrawBPMText( const float fBeat, const float fBPM ); - void DrawFreezeText( const float fBeat, const float fLength ); - void DrawDelayText( const float fBeat, const float fLength ); - void DrawWarpText( const float fBeat, const float fNewBeat ); - void DrawTimeSignatureText( const float fBeat, int iNumerator, int iDenominator ); - void DrawTickcountText( const float fBeat, int iTicks ); - void DrawComboText( const float fBeat, int iCombo, int iMiss ); - void DrawLabelText( const float fBeat, RString sLabel ); - void DrawSpeedText( const float fBeat, float fPercent, float fWait, int iMode ); - void DrawScrollText( const float fBeat, float fPercent ); - void DrawFakeText( const float fBeat, const float fNewBeat ); - void DrawAttackText( const float fBeat, const Attack &attack ); - void DrawBGChangeText( const float fBeat, const RString sNewBGName ); + void set_text_measure_number_for_draw( + const float beat, const float side_sign, float x_offset, + const float horiz_align, const RageColor& color, const RageColor& glow); + void draw_timing_segment_text(const RString& text, + const float beat, const float side_sign, float x_offset, + const float horiz_align, const RageColor& color, const RageColor& glow); + void DrawAttackText(const float beat, const Attack &attack, const RageColor& glow); + void DrawBGChangeText(const float beat, const RString new_bg_name, const RageColor& glow); float GetWidth() const; const NoteData *m_pNoteData; diff --git a/src/Player.cpp b/src/Player.cpp index ebf7fa9b50..ab31fae6c5 100644 --- a/src/Player.cpp +++ b/src/Player.cpp @@ -819,6 +819,8 @@ void Player::Update( float fDeltaTime ) const float fSongBeat = m_pPlayerState->m_Position.m_fSongBeat; const int iSongRow = BeatToNoteRow( fSongBeat ); + ArrowEffects::SetCurrentOptions(&m_pPlayerState->m_PlayerOptions.GetCurrent()); + // Optimization: Don't spend time processing the things below that won't show // if the Player doesn't show anything on the screen. if( HasVisibleParts() ) @@ -869,7 +871,7 @@ void Player::Update( float fDeltaTime ) //float fGrayYPos = SCALE( fPercentReverse, 0.f, 1.f, GRAY_ARROWS_Y_STANDARD, GRAY_ARROWS_Y_REVERSE ); float fX = ArrowEffects::GetXPos( m_pPlayerState, c, 0 ); - const float fZ = ArrowEffects::GetZPos( m_pPlayerState, c, 0 ); + const float fZ = ArrowEffects::GetZPos(c, 0); fX *= ( 1 - fMiniPercent * 0.5f ); m_vpHoldJudgment[c]->SetX( fX ); diff --git a/src/RageTextureManager.cpp b/src/RageTextureManager.cpp index f11fff0e5d..7c13995945 100644 --- a/src/RageTextureManager.cpp +++ b/src/RageTextureManager.cpp @@ -35,6 +35,8 @@ RageTextureManager* TEXTUREMAN = NULL; // global and accessible from anywhere namespace { map m_mapPathToTexture; + map m_textures_to_update; + map m_texture_ids_by_pointer; }; RageTextureManager::RageTextureManager(): @@ -50,11 +52,13 @@ RageTextureManager::~RageTextureManager() LOG->Trace( "TEXTUREMAN LEAK: '%s', RefCount = %d.", i->first.filename.c_str(), pTexture->m_iRefCount ); SAFE_DELETE( pTexture ); } + m_textures_to_update.clear(); + m_texture_ids_by_pointer.clear(); } void RageTextureManager::Update( float fDeltaTime ) { - FOREACHM( RageTextureID, RageTexture*, m_mapPathToTexture, i ) + FOREACHM(RageTextureID, RageTexture*, m_textures_to_update, i) { RageTexture* pTexture = i->second; pTexture->Update( fDeltaTime ); @@ -93,6 +97,12 @@ void RageTextureManager::RegisterTexture( RageTextureID ID, RageTexture *pTextur } m_mapPathToTexture[ID] = pTexture; + m_texture_ids_by_pointer[pTexture]= ID; +} + +void RageTextureManager::RegisterTextureForUpdating(RageTextureID id, RageTexture* tex) +{ + m_textures_to_update[id]= tex; } static const RString g_sDefaultTextureName = "__blank__"; @@ -164,6 +174,7 @@ RageTexture* RageTextureManager::LoadTextureInternal( RageTextureID ID ) } m_mapPathToTexture[ID] = pTexture; + m_texture_ids_by_pointer[pTexture]= ID; return pTexture; } @@ -224,13 +235,43 @@ void RageTextureManager::DeleteTexture( RageTexture *t ) ASSERT( t->m_iRefCount == 0 ); LOG->Trace( "RageTextureManager: deleting '%s'.", t->GetID().filename.c_str() ); - FOREACHM( RageTextureID, RageTexture*, m_mapPathToTexture, i ) + map::iterator id_entry= + m_texture_ids_by_pointer.find(t); + if(id_entry != m_texture_ids_by_pointer.end()) { - if( i->second == t ) + map::iterator tex_entry= + m_mapPathToTexture.find(id_entry->second); + if(tex_entry != m_mapPathToTexture.end()) { - m_mapPathToTexture.erase( i ); // remove map entry - SAFE_DELETE( t ); // free the texture - return; + m_mapPathToTexture.erase(tex_entry); + SAFE_DELETE(t); + } + map::iterator tex_update_entry= + m_textures_to_update.find(id_entry->second); + if(tex_update_entry != m_textures_to_update.end()) + { + m_textures_to_update.erase(tex_update_entry); + } + m_texture_ids_by_pointer.erase(id_entry); + return; + } + else + { + FAIL_M("Tried to delete a texture that wasn't in the ids by pointer list."); + FOREACHM( RageTextureID, RageTexture*, m_mapPathToTexture, i ) + { + if( i->second == t ) + { + m_mapPathToTexture.erase( i ); // remove map entry + SAFE_DELETE( t ); // free the texture + map::iterator tex_update_entry= + m_textures_to_update.find(i->first); + if(tex_update_entry != m_textures_to_update.end()) + { + m_textures_to_update.erase(tex_update_entry); + } + return; + } } } diff --git a/src/RageTextureManager.h b/src/RageTextureManager.h index 8ce1ae8e1c..50cdd9ddfd 100644 --- a/src/RageTextureManager.h +++ b/src/RageTextureManager.h @@ -60,6 +60,8 @@ public: void UnloadTexture( RageTexture *t ); void ReloadAll(); + void RegisterTextureForUpdating(RageTextureID id, RageTexture* tex); + bool SetPrefs( RageTextureManagerPrefs prefs ); RageTextureManagerPrefs GetPrefs() { return m_Prefs; }; diff --git a/src/RageTimer.h b/src/RageTimer.h index 3354145caa..795f2fe825 100644 --- a/src/RageTimer.h +++ b/src/RageTimer.h @@ -57,13 +57,17 @@ extern const RageTimer RageZeroTimer; #define START_TIME_CALL_COUNT(name) START_TIME(name); ++name##_call_count; #define END_TIME(name) uint64_t name##_end_time= RageTimer::GetUsecsSinceStart(); LOG->Time(#name " time: %zu to %zu = %zu", name##_start_time, name##_end_time, name##_end_time - name##_start_time); #define END_TIME_ADD_TO(name) uint64_t name##_end_time= RageTimer::GetUsecsSinceStart(); name##_total += name##_end_time - name##_start_time; +#define END_TIME_CALL_COUNT(name) END_TIME_ADD_TO(name); ++name##_end_count; #define DECL_TOTAL_TIME(name) extern uint64_t name##_total; #define DEF_TOTAL_TIME(name) uint64_t name##_total= 0; #define PRINT_TOTAL_TIME(name) LOG->Time(#name " total time: %zu", name##_total); #define DECL_TOT_CALL_PAIR(name) extern uint64_t name##_total; extern uint64_t name##_call_count; #define DEF_TOT_CALL_PAIR(name) uint64_t name##_total= 0; uint64_t name##_call_count= 0; -#define PRINT_TOT_CALL_PAIR(name) LOG->Time(#name " calls: %zu, time: %zu", name##_call_count, name##_total); +#define PRINT_TOT_CALL_PAIR(name) LOG->Time(#name " calls: %zu, time: %zu, per: %f", name##_call_count, name##_total, static_cast(name##_total) / name##_call_count); +#define DECL_TOT_CALL_END(name) DECL_TOT_CALL_PAIR(name); extern uint64_t name##_end_count; +#define DEF_TOT_CALL_END(name) DEF_TOT_CALL_PAIR(name); uint64_t name##_end_count= 0; +#define PRINT_TOT_CALL_END(name) LOG->Time(#name " calls: %zu, time: %zu, early end: %zu, per: %f", name##_call_count, name##_total, name##_end_count, static_cast(name##_total) / (name##_call_count - name##_end_count)); #endif diff --git a/src/ReceptorArrowRow.cpp b/src/ReceptorArrowRow.cpp index c339601a7b..dc2ad5bc3f 100644 --- a/src/ReceptorArrowRow.cpp +++ b/src/ReceptorArrowRow.cpp @@ -50,7 +50,14 @@ ReceptorArrowRow::~ReceptorArrowRow() void ReceptorArrowRow::Update( float fDeltaTime ) { ActorFrame::Update( fDeltaTime ); - ArrowEffects::Update(); + // If we're on gameplay, then the notefield will take care of updating + // ArrowEffects. But if we're on ScreenNameEntry, there is no notefield, + // Checking whether m_renderers is null is a proxy for checking whether + // there is a notefield. -Kyz + if(m_renderers == NULL) + { + ArrowEffects::Update(); + } for( unsigned c=0; cuseSMserver ) @@ -2010,7 +2008,6 @@ void ScreenGameplay::Update( float fDeltaTime ) if( m_bShowScoreboard && NSMAN->ChangedScoreboard(cn) && GAMESTATE->GetFirstDisabledPlayer() != PLAYER_INVALID ) m_Scoreboard[cn].SetText( NSMAN->m_Scoreboard[cn] ); } - // ArrowEffects::Update call moved because having it happen once per // NoteField (which means twice in two player) seemed wasteful. -Kyz ArrowEffects::Update(); diff --git a/src/Sprite.cpp b/src/Sprite.cpp index da98194523..5ba279be33 100644 --- a/src/Sprite.cpp +++ b/src/Sprite.cpp @@ -8,6 +8,7 @@ #include "RageLog.h" #include "RageDisplay.h" #include "RageTexture.h" +#include "RageTimer.h" #include "RageUtil.h" #include "ActorUtil.h" #include "Foreach.h" @@ -23,6 +24,7 @@ Sprite::Sprite() m_pTexture = NULL; m_iCurState = 0; m_fSecsIntoState = 0.0f; + m_animation_length_seconds= 0.0f; m_bUsingCustomTexCoords = false; m_bUsingCustomPosCoords = false; m_bSkipNextUpdate = true; @@ -58,6 +60,7 @@ Sprite::Sprite( const Sprite &cpy ): { #define CPY(a) a = cpy.a CPY( m_States ); + CPY(m_animation_length_seconds); CPY( m_iCurState ); CPY( m_fSecsIntoState ); CPY( m_bUsingCustomTexCoords ); @@ -93,6 +96,7 @@ void Sprite::SetAllStateDelays(float fDelay) { m_States[i].fDelay = fDelay; } + RecalcAnimationLengthSeconds(); } RageTextureID Sprite::SongBGTexture( RageTextureID ID ) @@ -248,6 +252,7 @@ void Sprite::LoadFromNode( const XNode* pNode ) } Actor::LoadFromNode( pNode ); + RecalcAnimationLengthSeconds(); } void Sprite::UnloadTexture() @@ -351,6 +356,7 @@ void Sprite::LoadStatesFromTexture() newState.rect = *m_pTexture->GetTextureCoordRect( i ); m_States.push_back( newState ); } + RecalcAnimationLengthSeconds(); } void Sprite::UpdateAnimationState() @@ -774,12 +780,13 @@ void Sprite::SetState( int iNewState ) m_fSecsIntoState = 0.0f; } -float Sprite::GetAnimationLengthSeconds() const +void Sprite::RecalcAnimationLengthSeconds() { - float fTotal = 0; - FOREACH_CONST( State, m_States, s ) - fTotal += s->fDelay; - return fTotal; + float m_animation_length_seconds = 0; + FOREACH_CONST(State, m_States, s) + { + m_animation_length_seconds += s->fDelay; + } } void Sprite::SetSecondsIntoAnimation( float fSeconds ) diff --git a/src/Sprite.h b/src/Sprite.h index 30da184a7c..e9b2fa371d 100644 --- a/src/Sprite.h +++ b/src/Sprite.h @@ -54,10 +54,12 @@ public: virtual int GetNumStates() const; virtual void SetState( int iNewState ); int GetState() { return m_iCurState; } - virtual float GetAnimationLengthSeconds() const; + virtual float GetAnimationLengthSeconds() const + { return m_animation_length_seconds; } + virtual void RecalcAnimationLengthSeconds(); virtual void SetSecondsIntoAnimation( float fSeconds ); void SetStateProperties(const vector& new_states) - { m_States= new_states; SetState(0); } + { m_States= new_states; RecalcAnimationLengthSeconds(); SetState(0); } RString GetTexturePath() const; @@ -106,6 +108,7 @@ private: int m_iCurState; /** @brief The number of seconds that have elapsed since we switched to this frame. */ float m_fSecsIntoState; + float m_animation_length_seconds; EffectMode m_EffectMode; bool m_bUsingCustomTexCoords;