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;