diff --git a/stepmania/README-FIRST.html b/stepmania/README-FIRST.html
index 75559535f1..dc91ff3e16 100644
--- a/stepmania/README-FIRST.html
+++ b/stepmania/README-FIRST.html
@@ -6,7 +6,7 @@
-StepMania 3.0 final
+StepMania X.X
©2001-2003, StepMania team, All rights reserved.
http://www.stepmania.com
@@ -35,11 +35,14 @@ and Help
Creating an Announcer
Creating a Note Skin
Creating a Theme
+Actor Commands
+ScreenSelect
How StepMania Loads Textures
Building StepMania from CVS Source
Thanks
See the file NEWS for version history.
+See the file COPYING.txt for license information.
@@ -923,6 +926,125 @@ Graphics folder "Themes\MySuperTheme\Graphics".
+Actor Commands (top)
+
+
+
+
+In the old paradigm, you would define the position of an Actor with two
+different metrics - one for the X position, and one for the Y. For example:
+ObjectX=100
+ObjectY=220
+
+This system is being replaced by more powerful "commands strings". A command
+string can set positions, colors, effects, and also script animations over time.
+Positioning an Actor with command string would look like this:
+ObjectOnCommand=x,100;y,220
+
+A command string contains one or more commands separated by semicolons. This
+command string contains two commands: "x,100" and "y,220". A command is made up
+of a command name and a list of parameters. The command name and any parameters
+are separated by commas. In the example above, both the commands "x" and "y"
+both take exactly one parameter. Other commands like "diffuse" take 4 parameters
+(R, G, B, and A). For example, the command "diffuse,1,0,1,1" would turn an
+Actor's color to opaque purple.
+
+Typically, the metrics file will have two commands per Actor - the "OnCommand"
+(which is where you command an Actor to tween onto the screen), and the "OffCommand"
+(for tweening the Actor off the screen).
+
+Below is a list of actor commands and their equivalent C++ equivalents. I'll
+have an explanation of animations and more examples in the full documentation.
+
+
+sleep BeginTweening( fParam(0), TWEEN_LINEAR );
+linear BeginTweening( fParam(0), TWEEN_LINEAR );
+accelerate BeginTweening( fParam(0), TWEEN_ACCELERATE );
+decelerate BeginTweening( fParam(0), TWEEN_DECELERATE );
+bouncebegin BeginTweening( fParam(0), TWEEN_BOUNCE_BEGIN );
+bounceend BeginTweening( fParam(0), TWEEN_BOUNCE_END );
+spring BeginTweening( fParam(0), TWEEN_SPRING );
+stoptweening { StopTweening(); BeginTweening( 0.0001f, TWEEN_LINEAR ); }
+x SetX( fParam(0) );
+y SetY( fParam(0) );
+xoffset SetX( GetX()+fParam(0) );
+yoffset SetY( GetY()+fParam(0) );
+zoom SetZoom( fParam(0) );
+zoomx SetZoomY( fParam(0) );
+zoomy SetZoomY( fParam(0) );
+diffuse SetDiffuse( RageColor(fParam(0),fParam(1),fParam(2),fParam(3)) );
+glow SetGlow( RageColor(fParam(0),fParam(1),fParam(2),fParam(3)) );
+rotationx SetRotationX( fParam(0) );
+rotationy SetRotationY( fParam(0) );
+rotationz SetRotationZ( fParam(0) );
+shadowlength SetShadowLength( fParam(0) );
+horizalign SetHorizAlign( sParam(0) );
+vertalign SetVertAlign( sParam(0) );
+diffuseblink SetEffectDiffuseBlink();
+diffuseshift SetEffectDiffuseShift();
+glowblink SetEffectGlowBlink();
+glowshift SetEffectGlowShift();
+wag SetEffectWag();
+bounce SetEffectBounce();
+bob SetEffectBob();
+spin SetEffectSpin();
+vibrate SetEffectVibrate();
+stopeffect SetEffectNone();
+effectcolor1 SetEffectColor1( RageColor(fParam(0),fParam(1),fParam(2),fParam(3))
+);
+effectcolor2 SetEffectColor2( RageColor(fParam(0),fParam(1),fParam(2),fParam(3))
+);
+effectperiod SetEffectPeriod( fParam(0) );
+effectmagnitude SetEffectMagnitude( RageVector3(fParam(0),fParam(1),fParam(2))
+);
+additiveblend EnableAdditiveBlend( iParam(0)!=0 );
+
+
+
+
+ScreenSelect (top)
+
+
+
+
+ScreenSelect is a type of screen that presents the user with a list of choices.
+The choices shown on these screens can be Styles, Difficulties, PlayModes, or
+any combination thereof. Each ScreenSelect screen has two metrics that define
+what choices are shown (examples below). Currently, there are only two different
+screens that support the ScreenSelect framework.
+- ScreenSelectMaxType1
+- ScreenSelectMaxType2
+- (more will be converted over in the next couple days)
+
+
+// Example 1: Show all Styles for the current game type the DDR MAX Select Style
+template
+
+[ScreenSelectMaxType1]
+ChoicesType=0 // 0=styles, 1=difficulties, 2=modes, 3=games
+Choices=
+
+
+// Example 2: Show specific Difficulty and PlayMode choices using a DDR MAX
+Select Difficulty template
+
+[ScreenSelectMaxType2]
+ChoicesType=1 // 0=styles, 1=difficulties, 2=modes, 3=games
+Choices=Beginner,Easy,Medium,Hard,Nonstop,Oni,Endless
+
+
+// Example 3: Show specific Style-PlayMode-Difficulty combinations using a DDR
+MAX Select Style template
+
+ChoicesType=2 // 0=styles, 1=difficulties, 2=modes, 3=games
+Choices=versus-arcade-medium,couple-arcade-medium,double-arcade-medium,single-arcade-medium,single-battle-medium,double-battle-medium,couple-battle-medium,versus-battle-medium
+
+
+
+
+
+
+
How StepMania Loads Textures (top)
diff --git a/stepmania/src/PrefsManager.cpp b/stepmania/src/PrefsManager.cpp
index d6957837c1..f77c2ddb18 100644
--- a/stepmania/src/PrefsManager.cpp
+++ b/stepmania/src/PrefsManager.cpp
@@ -71,8 +71,8 @@ PrefsManager::PrefsManager()
m_bShowSelectGroup = true;
m_bShowTranslations = true;
m_bArcadeOptionsNavigation = false;
- m_bSoloSingle = false; // OFF!!!!
- m_iUnloadTextureDelaySeconds = 0; // disabled 60*30; // 30 mins
+ m_bSoloSingle = false;
+ m_bDelayedTextureDelete = true;
m_MusicWheelUsesSections = ALWAYS;
m_iMusicWheelSwitchSpeed = 10;
m_bChangeBannersWhenFast = false;
@@ -163,7 +163,7 @@ void PrefsManager::ReadGlobalPrefsFromDisk( bool bSwitchToLastPlayedGame )
ini.GetValueB( "Options", "ShowTranslations", m_bShowTranslations );
ini.GetValueB( "Options", "ArcadeOptionsNavigation", m_bArcadeOptionsNavigation );
ini.GetValue ( "Options", "DWIPath", m_DWIPath );
- ini.GetValueI( "Options", "UnloadTextureDelaySeconds", m_iUnloadTextureDelaySeconds );
+ ini.GetValueB( "Options", "DelayedTextureDelete", m_bDelayedTextureDelete );
ini.GetValueI( "Options", "MusicWheelUsesSections", (int&)m_MusicWheelUsesSections );
ini.GetValueI( "Options", "MusicWheelSwitchSpeed", m_iMusicWheelSwitchSpeed );
ini.GetValueB( "Options", "ChangeBannersWhenFast", m_bChangeBannersWhenFast );
@@ -245,7 +245,7 @@ void PrefsManager::SaveGlobalPrefsToDisk()
ini.SetValueB( "Options", "ShowTranslations", m_bShowTranslations );
ini.SetValueB( "Options", "ArcadeOptionsNavigation", m_bArcadeOptionsNavigation );
ini.SetValue ( "Options", "DWIPath", m_DWIPath );
- ini.SetValueI( "Options", "UnloadTextureDelaySeconds", m_iUnloadTextureDelaySeconds );
+ ini.SetValueB( "Options", "DelayedTextureDelete", m_bDelayedTextureDelete );
ini.SetValueI( "Options", "MusicWheelUsesSections", m_MusicWheelUsesSections );
ini.SetValueI( "Options", "MusicWheelSwitchSpeed", m_iMusicWheelSwitchSpeed );
ini.SetValueB( "Options", "ChangeBannersWhenFast", m_bChangeBannersWhenFast );
diff --git a/stepmania/src/PrefsManager.h b/stepmania/src/PrefsManager.h
index 1a849567ec..0a5e35d075 100644
--- a/stepmania/src/PrefsManager.h
+++ b/stepmania/src/PrefsManager.h
@@ -33,7 +33,7 @@ public:
bool m_bUseBGIfNoBanner;
bool m_bHiddenSongs;
bool m_bVsync;
- int m_iUnloadTextureDelaySeconds;
+ bool m_bDelayedTextureDelete;
bool m_bIgnoreJoyAxes;
bool m_bOnlyDedicatedMenuButtons;
diff --git a/stepmania/src/RageTexture.h b/stepmania/src/RageTexture.h
index 3bf8d8d7b2..09e9d9fb81 100644
--- a/stepmania/src/RageTexture.h
+++ b/stepmania/src/RageTexture.h
@@ -86,7 +86,7 @@ public:
const CString &GetFilePath() const { return GetID().filename; }
int m_iRefCount;
- int m_iTimeOfLastUnload;
+ bool m_bCacheThis;
/* The ID that we were asked to load: */
const RageTextureID &GetID() const { return m_ID; }
diff --git a/stepmania/src/RageTextureManager.cpp b/stepmania/src/RageTextureManager.cpp
index 136564d77f..1ba925086e 100644
--- a/stepmania/src/RageTextureManager.cpp
+++ b/stepmania/src/RageTextureManager.cpp
@@ -27,9 +27,8 @@ RageTextureManager* TEXTUREMAN = NULL;
//-----------------------------------------------------------------------------
// constructor/destructor
//-----------------------------------------------------------------------------
-RageTextureManager::RageTextureManager( int iTextureColorDepth, int iSecondsBeforeUnload, int iMaxTextureResolution )
+RageTextureManager::RageTextureManager()
{
- SetPrefs( iTextureColorDepth, iSecondsBeforeUnload, iMaxTextureResolution );
}
RageTextureManager::~RageTextureManager()
@@ -103,21 +102,49 @@ RageTexture* RageTextureManager::LoadTexture( RageTextureID ID )
return pTexture;
}
-
-void RageTextureManager::GCTextures()
+void RageTextureManager::CacheTexture( RageTextureID ID )
{
- /* If m_iSecondsBeforeUnload is 0, then we'll unload textures immediately when
- * they're no longer needed, to use as little extra memory as possible, so don't
- * bother checking for expired textures here. */
- if(!m_iSecondsBeforeUnload) return;
+ RageTexture* pTexture = LoadTexture( ID );
+ pTexture->m_bCacheThis |= true;
+ UnloadTexture( pTexture );
+}
- static int timeLastGarbageCollect = time(NULL);
- if( timeLastGarbageCollect+m_iSecondsBeforeUnload/2 > time(NULL) )
- return;
+void RageTextureManager::UnloadTexture( RageTexture *t )
+{
+ t->m_iRefCount--;
+ ASSERT( t->m_iRefCount >= 0 );
+ /* Always unload movies, so we don't waste time decoding.
+ *
+ * Actually, multiple refs to a movie won't work; they should play independently,
+ * but they'll actually share settings. Not worth fixing, since we don't currently
+ * using movies for anything except BGAs (though we could).
+ */
+ if( t->m_iRefCount==0 )
+ {
+ bool bDeleteThis = false;
+ if( t->IsAMovie() )
+ bDeleteThis = true;
+ if( !m_bDelayedDelete || !t->m_bCacheThis )
+ bDeleteThis = true;
+
+ if( bDeleteThis )
+ DeleteTexture( t );
+ }
+}
+
+void RageTextureManager::DeleteTexture( RageTexture *t )
+{
+ ASSERT( t->m_iRefCount==0 );
+ LOG->Trace( "RageTextureManager: deleting '%s'.", t->GetID().filename.GetString() );
+ m_mapPathToTexture.erase( t->GetID() ); // remove map entry
+ SAFE_DELETE( t ); // free the texture
+}
+
+void RageTextureManager::GarbageCollect( GCType type )
+{
// Search for old textures with refcount==0 to unload
- LOG->Trace("Performing texture garbage collection");
- timeLastGarbageCollect = time(NULL);
+ LOG->Trace("Performing texture garbage collection.");
for( std::map::iterator i = m_mapPathToTexture.begin();
i != m_mapPathToTexture.end(); )
@@ -126,16 +153,25 @@ void RageTextureManager::GCTextures()
i++;
CString sPath = j->first.filename;
- RageTexture* pTexture = j->second;
- if( pTexture->m_iRefCount==0 &&
- pTexture->m_iTimeOfLastUnload+m_iSecondsBeforeUnload < time(NULL) )
+ RageTexture* t = j->second;
+
+ if( t->m_iRefCount==0 )
{
- SAFE_DELETE( pTexture ); // free the texture
- m_mapPathToTexture.erase(j); // and remove the key in the map
+ bool bDeleteThis = false;
+ if( type==cached_textures && !m_bDelayedDelete )
+ bDeleteThis = true;
+ if( type==delayed_delete )
+ bDeleteThis = true;
+
+ if( bDeleteThis )
+ DeleteTexture( t );
}
}
}
+/*
+
+ Redundant. -Chris
void RageTextureManager::UnloadTexture( RageTextureID ID )
{
@@ -155,31 +191,8 @@ void RageTextureManager::UnloadTexture( RageTextureID ID )
UnloadTexture(p->second);
//LOG->Trace( "RageTextureManager: '%s' will not be deleted. It still has %d references.", sTexturePath.GetString(), pTexture->m_iRefCount );
}
+*/
-void RageTextureManager::UnloadTexture( RageTexture *t )
-{
- t->m_iRefCount--;
- t->m_iTimeOfLastUnload = time(NULL);
- ASSERT( t->m_iRefCount >= 0 );
-
- /* Always unload movies, so we don't waste time decoding.
- *
- * Actually, multiple refs to a movie won't work; they should play independently,
- * but they'll actually share settings. Not worth fixing, since we don't currently
- * using movies for anything except BGAs (though we could).
- *
- * Also, if texture caching is off, just remove it now instead of doing
- * garbage collection. */
- if( t->m_iRefCount == 0 &&
- (t->IsAMovie() || !m_iSecondsBeforeUnload ))
- {
- // LOG->Trace( "RageTextureManager: '%s' will be deleted. It has %d references.", sTexturePath.GetString(), pTexture->m_iRefCount );
- m_mapPathToTexture.erase(t->GetID()); // and remove the key in the map
- SAFE_DELETE( t ); // free the texture
- }
-
- GCTextures();
-}
void RageTextureManager::ReloadAll()
{
@@ -228,15 +241,15 @@ void RageTextureManager::InvalidateTextures()
}
}
-bool RageTextureManager::SetPrefs( int iTextureColorDepth, int iSecondsBeforeUnload, int iMaxTextureResolution )
+bool RageTextureManager::SetPrefs( int iTextureColorDepth, bool bDelayedDelete, int iMaxTextureResolution )
{
bool need_reload = false;
- if(m_iSecondsBeforeUnload != iSecondsBeforeUnload ||
+ if( m_bDelayedDelete != bDelayedDelete ||
m_iTextureColorDepth != iTextureColorDepth ||
m_iMaxTextureResolution != iMaxTextureResolution )
need_reload = true;
- m_iSecondsBeforeUnload = iSecondsBeforeUnload;
+ m_bDelayedDelete = bDelayedDelete;
m_iTextureColorDepth = iTextureColorDepth;
m_iMaxTextureResolution = iMaxTextureResolution;
diff --git a/stepmania/src/RageTextureManager.h b/stepmania/src/RageTextureManager.h
index 4f5a6050fc..28a924246e 100644
--- a/stepmania/src/RageTextureManager.h
+++ b/stepmania/src/RageTextureManager.h
@@ -21,27 +21,35 @@
class RageTextureManager
{
public:
- RageTextureManager( int iTextureColorDepth, int iSecsBeforeUnload, int iMaxTextureResolution );
+ RageTextureManager();
void Update( float fDeltaTime );
~RageTextureManager();
RageTexture* LoadTexture( RageTextureID ID );
- void UnloadTexture( RageTextureID ID );
+ void CacheTexture( RageTextureID ID );
void UnloadTexture( RageTexture *t );
void ReloadAll();
- bool SetPrefs( int iTextureColorDepth, int iSecsBeforeUnload, int iMaxTextureResolution );
+ bool SetPrefs( int iTextureColorDepth, bool bDelayedDelete, int iMaxTextureResolution );
int GetTextureColorDepth() { return m_iTextureColorDepth; };
+ bool GetDelayedDelete() { return m_bDelayedDelete; };
int GetMaxTextureResolution() { return m_iMaxTextureResolution; };
- int GetSecsBeforeUnload() { return m_iSecondsBeforeUnload; };
+ // call this between Screens
+ void DeleteCachedTextures() { GarbageCollect(cached_textures); }
+
+ // call this on switch theme
+ void DoDelayedDelete() { GarbageCollect(delayed_delete); }
+
void InvalidateTextures();
protected:
- void GCTextures();
+ void DeleteTexture( RageTexture *t );
+ enum GCType { cached_textures, delayed_delete };
+ void GarbageCollect( GCType type );
int m_iTextureColorDepth;
- int m_iSecondsBeforeUnload;
+ bool m_bDelayedDelete;
int m_iMaxTextureResolution;
std::map m_mapPathToTexture;
diff --git a/stepmania/src/ScreenAppearanceOptions.cpp b/stepmania/src/ScreenAppearanceOptions.cpp
index 19f9357160..3334641276 100644
--- a/stepmania/src/ScreenAppearanceOptions.cpp
+++ b/stepmania/src/ScreenAppearanceOptions.cpp
@@ -157,6 +157,7 @@ void ScreenAppearanceOptions::ExportOptions()
int iSelectedTheme = m_iSelectedOption[0][AO_THEME];
CString sNewTheme = m_OptionRow[AO_THEME].choices[iSelectedTheme];
THEME->SwitchTheme( sNewTheme );
+ TEXTUREMAN->DoDelayedDelete(); // delete all textures that don't have references
int iSelectedSkin = m_iSelectedOption[0][AO_SKIN];
CString sNewSkin = m_OptionRow[AO_SKIN].choices[iSelectedSkin];
diff --git a/stepmania/src/ScreenGraphicOptions.cpp b/stepmania/src/ScreenGraphicOptions.cpp
index 67da6be4fa..209f0d9e0b 100644
--- a/stepmania/src/ScreenGraphicOptions.cpp
+++ b/stepmania/src/ScreenGraphicOptions.cpp
@@ -109,7 +109,7 @@ void ScreenGraphicOptions::ImportOptions()
case 32: m_iSelectedOption[0][GO_TEXTURE_COLOR_DEPTH] = 1; break;
}
- m_iSelectedOption[0][GO_KEEP_TEXTURES_IN_MEM] = PREFSMAN->m_iUnloadTextureDelaySeconds>0 ? 1:0;
+ m_iSelectedOption[0][GO_KEEP_TEXTURES_IN_MEM] = PREFSMAN->m_bDelayedTextureDelete ? 1:0;
switch(PREFSMAN->m_iRefreshRate)
{
@@ -153,7 +153,7 @@ void ScreenGraphicOptions::ExportOptions()
default: ASSERT(0); PREFSMAN->m_iTextureColorDepth = 16; break;
}
- PREFSMAN->m_iUnloadTextureDelaySeconds = (m_iSelectedOption[0][GO_KEEP_TEXTURES_IN_MEM] == 1) ? 1200 : 0; // 20 mins
+ PREFSMAN->m_bDelayedTextureDelete = (m_iSelectedOption[0][GO_KEEP_TEXTURES_IN_MEM] == 1);
if(m_iSelectedOption[0][GO_REFRESH_RATE] == 0)
PREFSMAN->m_iRefreshRate = REFRESH_DEFAULT;
diff --git a/stepmania/src/ScreenManager.cpp b/stepmania/src/ScreenManager.cpp
index 1656902502..d941beb76c 100644
--- a/stepmania/src/ScreenManager.cpp
+++ b/stepmania/src/ScreenManager.cpp
@@ -24,9 +24,9 @@
#include "RageDisplay.h"
#include "Screen.h"
#include "SongManager.h"
-
#include "BitmapText.h"
#include "Quad.h"
+#include "RageTextureManager.h"
ScreenManager* SCREENMAN = NULL; // global and accessable from anywhere in our program
@@ -370,6 +370,8 @@ void ScreenManager::Input( const DeviceInput& DeviceI, const InputEventType type
Screen* ScreenManager::MakeNewScreen( CString sClassName )
{
+ TEXTUREMAN->DeleteCachedTextures();
+
Screen *ret = Screen::Create( sClassName );
/* Loading probably took a little while. Let's reset stats. This prevents us
diff --git a/stepmania/src/ScreenTitleMenu.cpp b/stepmania/src/ScreenTitleMenu.cpp
index 5b30a2b4ba..25c956ff4b 100644
--- a/stepmania/src/ScreenTitleMenu.cpp
+++ b/stepmania/src/ScreenTitleMenu.cpp
@@ -27,6 +27,7 @@
#include "SDL_utils.h"
#include "RageSoundManager.h"
#include "CodeDetector.h"
+#include "RageTextureManager.h"
#define LOGO_ON_COMMAND THEME->GetMetric("ScreenTitleMenu","LogoOnCommand")
@@ -240,6 +241,7 @@ void ScreenTitleMenu::Input( const DeviceInput& DeviceI, const InputEventType ty
THEME->NextTheme();
SCREENMAN->SystemMessage( "Theme: "+THEME->GetCurThemeName() );
SCREENMAN->SetNewScreen( "ScreenTitleMenu" );
+ TEXTUREMAN->DoDelayedDelete();
}
if( CodeDetector::EnteredCode(GameI.controller,CodeDetector::CODE_NEXT_ANNOUNCER) )
{
diff --git a/stepmania/src/StepMania.cpp b/stepmania/src/StepMania.cpp
index 7f94401f76..a52b5056b1 100644
--- a/stepmania/src/StepMania.cpp
+++ b/stepmania/src/StepMania.cpp
@@ -98,7 +98,7 @@ void ApplyGraphicOptions()
bNeedReload |= TEXTUREMAN->SetPrefs(
PREFSMAN->m_iTextureColorDepth,
- PREFSMAN->m_iUnloadTextureDelaySeconds,
+ PREFSMAN->m_bDelayedTextureDelete,
PREFSMAN->m_iMaxTextureResolution );
if( bNeedReload )
@@ -133,6 +133,7 @@ void ResetGame()
THEME->SwitchTheme( sGameName );
else
THEME->SwitchTheme( "default" );
+ TEXTUREMAN->DoDelayedDelete();
}
PREFSMAN->SaveGamePrefsToDisk();
@@ -297,7 +298,11 @@ int main(int argc, char* argv[])
PREFSMAN->m_iDisplayColorDepth,
PREFSMAN->m_iRefreshRate,
PREFSMAN->m_bVsync );
- TEXTUREMAN = new RageTextureManager( PREFSMAN->m_iTextureColorDepth, PREFSMAN->m_iUnloadTextureDelaySeconds, PREFSMAN->m_iMaxTextureResolution );
+ TEXTUREMAN = new RageTextureManager();
+ TEXTUREMAN->SetPrefs(
+ PREFSMAN->m_iTextureColorDepth,
+ PREFSMAN->m_bDelayedTextureDelete,
+ PREFSMAN->m_iMaxTextureResolution );
/* Now that we've started DISPLAY, we can set up event masks. */
SDL_EventState(SDL_QUIT, SDL_ENABLE);