From f55e8a54e6b3787cc36aef4bb9891c344b698c51 Mon Sep 17 00:00:00 2001 From: Chris Danford Date: Fri, 2 Sep 2005 21:42:34 +0000 Subject: [PATCH] Don't evaluate the ActorScroller transform function every time though Draw. Cache TweenState values at a provided interval, then interpolate between the TweenStates. TODO: Precalculate these TweenStates in Init? --- stepmania/Themes/default/metrics.ini | 2 + stepmania/src/ActorScroller.cpp | 43 ++++++++++++++++++-- stepmania/src/ActorScroller.h | 19 +++++++++ stepmania/src/RageUtil.h | 11 +++++ stepmania/src/ScreenCredits.cpp | 3 ++ stepmania/src/ScreenNameEntryTraditional.cpp | 1 + stepmania/src/ScreenSelectMaster.cpp | 2 + stepmania/src/ScreenSelectMaster.h | 1 + 8 files changed, 79 insertions(+), 3 deletions(-) diff --git a/stepmania/Themes/default/metrics.ini b/stepmania/Themes/default/metrics.ini index 829553f79e..b7befcd244 100644 --- a/stepmania/Themes/default/metrics.ini +++ b/stepmania/Themes/default/metrics.ini @@ -2917,6 +2917,7 @@ PostSwitchPageSeconds=0 ScrollerSecondsPerItem=0 ScrollerNumItemsToDraw=20 ScrollerTransform=function(self,offset,itemIndex,numItems) end +ScrollerSubdivisions=1 OverrideLockInputSeconds=0 LockInputSeconds=0 OverrideSleepAfterTweenOffSeconds=0 @@ -3155,6 +3156,7 @@ PostSwitchPageSeconds=0 ScrollerSecondsPerItem=0 ScrollerNumItemsToDraw=20 ScrollerTransform=function(self,offset,itemIndex,numItems) end +ScrollerSubdivisions=1 StyleIcon=1 OverrideSleepAfterTweenOffSeconds=0 SleepAfterTweenOffSeconds=0 diff --git a/stepmania/src/ActorScroller.cpp b/stepmania/src/ActorScroller.cpp index 5bf16a4527..332e5a1181 100644 --- a/stepmania/src/ActorScroller.cpp +++ b/stepmania/src/ActorScroller.cpp @@ -39,6 +39,8 @@ ActorScroller::ActorScroller() m_quadMask.SetBlendMode( BLEND_NO_EFFECT ); // don't change color values m_quadMask.SetUseZBuffer( true ); // we want to write to the Zbuffer m_quadMask.SetHidden( true ); + + m_iSubdivisions = 1; } void ActorScroller::Load2( @@ -62,6 +64,7 @@ void ActorScroller::Load2( m_exprTransformFunction.SetFromExpression( ssprintf("function(self,offset,itemIndex,numItems) return self:y(%f*offset) end",fItemHeight) ); + m_iSubdivisions = 1; m_bLoop = bLoop; m_fSecondsPerItem = fSecondsPerItem; @@ -90,6 +93,7 @@ void ActorScroller::Load3( float fNumItemsToDraw, bool bFastCatchup, const CString &sTransformFunction, + int iSubdivisions, bool bUseMask, bool bLoop ) @@ -98,6 +102,7 @@ void ActorScroller::Load3( m_fNumItemsToDraw = fNumItemsToDraw; m_bFastCatchup = bFastCatchup; m_exprTransformFunction.SetFromExpression( sTransformFunction ); + m_iSubdivisions = iSubdivisions; m_fQuantizePixels = 0; m_bUseMask = bUseMask; m_bLoop = bLoop; @@ -131,12 +136,14 @@ void ActorScroller::LoadFromNode( const CString &sDir, const XNode *pNode ) float fItemPaddingStart = 0; float fItemPaddingEnd = 0; CString sTransformFunction; + int iSubdivisions = 0; GET_VALUE( "SecondsPerItem", fSecondsPerItem ); GET_VALUE( "NumItemsToDraw", fNumItemsToDraw ); GET_VALUE( "ItemPaddingStart", fItemPaddingStart ); GET_VALUE( "ItemPaddingEnd", fItemPaddingEnd ); GET_VALUE( "TransformFunction", sTransformFunction ); + pNode->GetAttrValue( "Subdivisions", m_iSubdivisions ); #undef GET_VALUE Load3( @@ -144,6 +151,7 @@ void ActorScroller::LoadFromNode( const CString &sDir, const XNode *pNode ) fNumItemsToDraw, false, sTransformFunction, + iSubdivisions, false, false ); SetCurrentAndDestinationItem( -fItemPaddingStart ); @@ -201,18 +209,47 @@ void ActorScroller::UpdateInternal( float fDeltaTime ) m_fCurrentItem = fmodf( m_fCurrentItem, m_fNumItemsToDraw+1 ); } - -void ActorScroller::PositionItem( Actor *pActor, float fPositionOffsetFromCenter, int iItemIndex, int iNumItems ) +const Actor::TweenState &ActorScroller::GetPosition( float fPositionOffsetFromCenter, int iItemIndex, int iNumItems ) { + PositionOffsetAndItemIndex key = { fPositionOffsetFromCenter, iItemIndex }; + + map::iterator iter = m_mapPositionToTweenStateCache.find( key ); + if( iter != m_mapPositionToTweenStateCache.end() ) + return iter->second; + + Actor a; + Lua *L = LUA->Get(); m_exprTransformFunction.PushSelf( L ); ASSERT( !lua_isnil(L, -1) ); - pActor->PushSelf( L ); + a.PushSelf( L ); LuaHelpers::Push( fPositionOffsetFromCenter, L ); LuaHelpers::Push( iItemIndex, L ); LuaHelpers::Push( iNumItems, L ); lua_call( L, 4, 0 ); // 4 args, 0 results LUA->Release(L); + + return m_mapPositionToTweenStateCache[key] = a.DestTweenState(); +} + +void ActorScroller::PositionItem( Actor *pActor, float fPositionOffsetFromCenter, int iItemIndex, int iNumItems ) +{ + float fInterval = 1.0f / m_iSubdivisions; + float fFloor = QuantizeDown( fPositionOffsetFromCenter, fInterval ); + float fCeil = QuantizeUp( fPositionOffsetFromCenter, fInterval ); + + if( fFloor == fCeil ) + { + pActor->DestTweenState() = GetPosition( fCeil, iItemIndex, iNumItems ); + } + else + { + const Actor::TweenState &tsFloor = GetPosition( fFloor, iItemIndex, iNumItems ); + const Actor::TweenState &tsCeil = GetPosition( fCeil, iItemIndex, iNumItems ); + + float fPercentTowardCeil = SCALE( fPositionOffsetFromCenter, fFloor, fCeil, 0.0f, 1.0f ); + Actor::TweenState::MakeWeightedAverage( pActor->DestTweenState(), tsFloor, tsCeil, fPercentTowardCeil ); + } } void ActorScroller::DrawPrimitives() diff --git a/stepmania/src/ActorScroller.h b/stepmania/src/ActorScroller.h index 8cd60712c7..f51dd4fd8b 100644 --- a/stepmania/src/ActorScroller.h +++ b/stepmania/src/ActorScroller.h @@ -25,6 +25,7 @@ public: float fNumItemsToDraw, bool bFastCatchup, const CString &sTransformFunction, + int iSubdivisions, bool bUseMask, bool bLoop ); @@ -48,6 +49,7 @@ public: void PushSelf( lua_State *L ); protected: + const Actor::TweenState &GetPosition( float fPositionOffsetFromCenter, int iItemIndex, int iNumItems ); void PositionItem( Actor *pActor, float fPositionOffsetFromCenter, int iItemIndex, int iNumItems ); bool m_bLoaded; @@ -67,6 +69,23 @@ protected: Quad m_quadMask; LuaExpression m_exprTransformFunction; // params: self,offset,itemIndex,numItems + int m_iSubdivisions; // 1 == one evaluation per position + struct PositionOffsetAndItemIndex + { + float fPositionOffsetFromCenter; + int iItemIndex; + + bool operator<( const PositionOffsetAndItemIndex &other ) const + { + if( fPositionOffsetFromCenter < other.fPositionOffsetFromCenter ) + return true; + else if( fPositionOffsetFromCenter > other.fPositionOffsetFromCenter ) + return false; + else + return iItemIndex < other.iItemIndex; + } + }; + map m_mapPositionToTweenStateCache; }; class ActorScrollerAutoDeleteChildren : public ActorScroller diff --git a/stepmania/src/RageUtil.h b/stepmania/src/RageUtil.h index cf9c8f4878..b13b7c506d 100644 --- a/stepmania/src/RageUtil.h +++ b/stepmania/src/RageUtil.h @@ -207,6 +207,17 @@ inline float QuantizeUp( float i, float iInterval ) return ceilf( i/iInterval ) * iInterval; } +/* Return i rounded down to the nearest multiple of iInterval. */ +inline int QuantizeDown( int i, int iInterval ) +{ + return int( (i-iInterval+1)/iInterval ) * iInterval; +} + +inline float QuantizeDown( float i, float iInterval ) +{ + return floorf( i/iInterval ) * iInterval; +} + // Move val toward other_val by to_move. void fapproach( float& val, float other_val, float to_move ); diff --git a/stepmania/src/ScreenCredits.cpp b/stepmania/src/ScreenCredits.cpp index ce5dbfeb70..7a3528d715 100644 --- a/stepmania/src/ScreenCredits.cpp +++ b/stepmania/src/ScreenCredits.cpp @@ -185,6 +185,7 @@ void ScreenCredits::Init() 4, false, sBackgroundsTransformFunction, + 1, false, false ); SET_XY( m_ScrollerBackgrounds ); @@ -196,6 +197,7 @@ void ScreenCredits::Init() 4, false, sBackgroundsTransformFunction, + 1, false, false ); SET_XY( m_ScrollerFrames ); @@ -247,6 +249,7 @@ void ScreenCredits::Init() 40, false, sTextsTransformFunction, + 1, false, false ); SET_XY( m_ScrollerTexts ); diff --git a/stepmania/src/ScreenNameEntryTraditional.cpp b/stepmania/src/ScreenNameEntryTraditional.cpp index 2a3cecbce5..686a858e4e 100644 --- a/stepmania/src/ScreenNameEntryTraditional.cpp +++ b/stepmania/src/ScreenNameEntryTraditional.cpp @@ -120,6 +120,7 @@ void HighScoreWheel::Load( const HighScoreList& hsl, int iIndexToFocus ) 10.5, false, sTransformFunction, + 1, false, false ); Scroll(); diff --git a/stepmania/src/ScreenSelectMaster.cpp b/stepmania/src/ScreenSelectMaster.cpp index 38cb9f34ce..f60ab8ce3b 100644 --- a/stepmania/src/ScreenSelectMaster.cpp +++ b/stepmania/src/ScreenSelectMaster.cpp @@ -45,6 +45,7 @@ ScreenSelectMaster::ScreenSelectMaster( CString sClassName ) : ScreenSelect( sCl SCROLLER_SECONDS_PER_ITEM(m_sName,"ScrollerSecondsPerItem"), SCROLLER_NUM_ITEMS_TO_DRAW(m_sName,"ScrollerNumItemsToDraw"), SCROLLER_TRANSFORM(m_sName,"ScrollerTransform"), + SCROLLER_SUBDIVISIONS(m_sName,"ScrollerSubdivisions"), DEFAULT_CHOICE(m_sName,"DefaultChoice") { } @@ -110,6 +111,7 @@ void ScreenSelectMaster::Init() SCROLLER_NUM_ITEMS_TO_DRAW, SCROLLER_FAST_CATCHUP, SCROLLER_TRANSFORM, + SCROLLER_SUBDIVISIONS, false, LOOP_SCROLLER ); m_Scroller[*p].SetName( "Scroller"+PLAYER_APPEND_NO_SPACE(*p) ); diff --git a/stepmania/src/ScreenSelectMaster.h b/stepmania/src/ScreenSelectMaster.h index 72b5f2106b..3c58cec5dd 100644 --- a/stepmania/src/ScreenSelectMaster.h +++ b/stepmania/src/ScreenSelectMaster.h @@ -55,6 +55,7 @@ protected: ThemeMetric SCROLLER_SECONDS_PER_ITEM; ThemeMetric SCROLLER_NUM_ITEMS_TO_DRAW; ThemeMetric SCROLLER_TRANSFORM; + ThemeMetric SCROLLER_SUBDIVISIONS; ThemeMetric DEFAULT_CHOICE; int m_Next[NUM_MENU_DIRS][MAX_CHOICES];