one path for parsing and theming player options - fixes "SuperShuffle" not themed

warn in ActiveAttackList if an invalid mod is encountered
don't hard code font name
This commit is contained in:
Chris Danford
2005-04-06 05:32:09 +00:00
parent 759be18af5
commit ea34de2bef
5 changed files with 148 additions and 147 deletions
+7 -20
View File
@@ -32,11 +32,9 @@ void ActiveAttackList::Update( float fDelta )
void ActiveAttackList::Refresh()
{
CString s;
const AttackArray& attacks = m_pPlayerState->m_ActiveAttacks;
// clear all lines, then add all active attacks
vector<CString> vsThemedMods;
for( unsigned i=0; i<attacks.size(); i++ )
{
const Attack& attack = attacks[i];
@@ -44,24 +42,13 @@ void ActiveAttackList::Refresh()
if( !attack.bOn )
continue; /* hasn't started yet */
CString sMods = attack.sModifier;
CStringArray asMods;
split( sMods, ",", asMods );
for( unsigned j=0; j<asMods.size(); j++ )
{
CString& sMod = asMods[j];
TrimLeft( sMod );
TrimRight( sMod );
sMod = PlayerOptions::ThemeMod( sMod );
if( s.empty() )
s = sMod;
else
s = sMod + "\n" + s;
}
PlayerOptions po;
po.FromString( attack.sModifier, true );
po.GetThemedMods( vsThemedMods );
}
CString s = join( "\n", vsThemedMods );
this->SetText( s ); // BitmapText will not rebuild vertices if these strings are the same.
}
+8 -1
View File
@@ -232,7 +232,14 @@ void SaveCatalogXml()
for( set<CString>::const_iterator iter = modifiers.begin(); iter != modifiers.end(); iter++ )
{
XNode* pNode2 = pNode->AppendChild( "Modifier", *iter );
pNode2->AppendAttr( "DisplayAs", PlayerOptions::ThemeMod(*iter) );
PlayerOptions po;
CString s = *iter;
po.FromString( s, false );
vector<CString> v;
po.GetThemedMods( v );
if( v.empty() )
continue;
pNode2->AppendAttr( "DisplayAs", join(" ",v) );
}
}
}
+112 -107
View File
@@ -2,7 +2,6 @@
#include "PlayerOptions.h"
#include "RageUtil.h"
#include "RageLog.h"
#include "GameState.h"
#include "NoteSkinManager.h"
#include "song.h"
@@ -12,11 +11,13 @@
#include "Foreach.h"
#include "Style.h"
#include "CommonMetrics.h"
#include "arch/Dialog/Dialog.h"
#define ONE( arr ) { for( unsigned Z = 0; Z < ARRAYSIZE(arr); ++Z ) arr[Z]=1.0f; }
void PlayerOptions::Init()
{
m_bSetScrollSpeed = false;
m_fTimeSpacing = 0; m_SpeedfTimeSpacing = 1.0f;
m_fScrollSpeed = 1.0f; m_SpeedfScrollSpeed = 1.0f;
m_fScrollBPM = 200; m_SpeedfScrollBPM = 1.0f;
@@ -61,23 +62,30 @@ void PlayerOptions::Approach( const PlayerOptions& other, float fDeltaSeconds )
APP( fRandomSpeed );
}
static CString AddPart( float level, CString name )
static void AddPart( vector<CString> &AddTo, float level, CString name )
{
if( level == 0 )
return "";
return;
const CString LevelStr = (level == 1)? CString(""): ssprintf( "%i%% ", (int) roundf(level*100) );
return LevelStr + name + ", ";
AddTo.push_back( LevelStr + name );
}
CString PlayerOptions::GetString() const
{
vector<CString> v;
GetMods( v );
return join( ", ", v );
}
void PlayerOptions::GetMods( vector<CString> &AddTo ) const
{
CString sReturn;
if( !m_fTimeSpacing )
{
if( m_fScrollSpeed != 1 )
if( m_bSetScrollSpeed || m_fScrollSpeed != 1 )
{
/* -> 1.00 */
CString s = ssprintf( "%2.2f", m_fScrollSpeed );
@@ -89,95 +97,91 @@ CString PlayerOptions::GetString() const
s.erase(s.GetLength()-2); // delete last 2 chars
}
}
sReturn += s + "x, ";
AddTo.push_back( s + "x" );
}
}
else
{
CString s = ssprintf( "C%.0f", m_fScrollBPM );
sReturn += s + ", ";
AddTo.push_back( s );
}
sReturn += AddPart( m_fAccels[ACCEL_BOOST], "Boost" );
sReturn += AddPart( m_fAccels[ACCEL_BRAKE], "Brake" );
sReturn += AddPart( m_fAccels[ACCEL_WAVE], "Wave" );
sReturn += AddPart( m_fAccels[ACCEL_EXPAND], "Expand" );
sReturn += AddPart( m_fAccels[ACCEL_BOOMERANG], "Boomerang" );
AddPart( AddTo, m_fAccels[ACCEL_BOOST], "Boost" );
AddPart( AddTo, m_fAccels[ACCEL_BRAKE], "Brake" );
AddPart( AddTo, m_fAccels[ACCEL_WAVE], "Wave" );
AddPart( AddTo, m_fAccels[ACCEL_EXPAND], "Expand" );
AddPart( AddTo, m_fAccels[ACCEL_BOOMERANG], "Boomerang" );
sReturn += AddPart( m_fEffects[EFFECT_DRUNK], "Drunk" );
sReturn += AddPart( m_fEffects[EFFECT_DIZZY], "Dizzy" );
sReturn += AddPart( m_fEffects[EFFECT_MINI], "Mini" );
sReturn += AddPart( m_fEffects[EFFECT_FLIP], "Flip" );
sReturn += AddPart( m_fEffects[EFFECT_TORNADO], "Tornado" );
sReturn += AddPart( m_fEffects[EFFECT_TIPSY], "Tipsy" );
sReturn += AddPart( m_fEffects[EFFECT_BUMPY], "Bumpy" );
sReturn += AddPart( m_fEffects[EFFECT_BEAT], "Beat" );
AddPart( AddTo, m_fEffects[EFFECT_DRUNK], "Drunk" );
AddPart( AddTo, m_fEffects[EFFECT_DIZZY], "Dizzy" );
AddPart( AddTo, m_fEffects[EFFECT_MINI], "Mini" );
AddPart( AddTo, m_fEffects[EFFECT_FLIP], "Flip" );
AddPart( AddTo, m_fEffects[EFFECT_TORNADO], "Tornado" );
AddPart( AddTo, m_fEffects[EFFECT_TIPSY], "Tipsy" );
AddPart( AddTo, m_fEffects[EFFECT_BUMPY], "Bumpy" );
AddPart( AddTo, m_fEffects[EFFECT_BEAT], "Beat" );
sReturn += AddPart( m_fAppearances[APPEARANCE_HIDDEN], "Hidden" );
sReturn += AddPart( m_fAppearances[APPEARANCE_SUDDEN], "Sudden" );
sReturn += AddPart( m_fAppearances[APPEARANCE_STEALTH], "Stealth" );
sReturn += AddPart( m_fAppearances[APPEARANCE_BLINK], "Blink" );
sReturn += AddPart( m_fAppearances[APPEARANCE_RANDOMVANISH], "RandomVanish" );
AddPart( AddTo, m_fAppearances[APPEARANCE_HIDDEN], "Hidden" );
AddPart( AddTo, m_fAppearances[APPEARANCE_SUDDEN], "Sudden" );
AddPart( AddTo, m_fAppearances[APPEARANCE_STEALTH], "Stealth" );
AddPart( AddTo, m_fAppearances[APPEARANCE_BLINK], "Blink" );
AddPart( AddTo, m_fAppearances[APPEARANCE_RANDOMVANISH],"RandomVanish" );
sReturn += AddPart( m_fScrolls[SCROLL_REVERSE], "Reverse" );
sReturn += AddPart( m_fScrolls[SCROLL_SPLIT], "Split" );
sReturn += AddPart( m_fScrolls[SCROLL_ALTERNATE], "Alternate" );
sReturn += AddPart( m_fScrolls[SCROLL_CROSS], "Cross" );
sReturn += AddPart( m_fScrolls[SCROLL_CENTERED], "Centered" );
AddPart( AddTo, m_fScrolls[SCROLL_REVERSE], "Reverse" );
AddPart( AddTo, m_fScrolls[SCROLL_SPLIT], "Split" );
AddPart( AddTo, m_fScrolls[SCROLL_ALTERNATE], "Alternate" );
AddPart( AddTo, m_fScrolls[SCROLL_CROSS], "Cross" );
AddPart( AddTo, m_fScrolls[SCROLL_CENTERED], "Centered" );
sReturn += AddPart( m_fDark, "Dark");
AddPart( AddTo, m_fDark, "Dark" );
sReturn += AddPart( m_fBlind, "Blind");
sReturn += AddPart( m_fCover, "Cover");
AddPart( AddTo, m_fBlind, "Blind" );
AddPart( AddTo, m_fCover, "Cover" );
sReturn += AddPart( m_fPassmark, "Passmark");
AddPart( AddTo, m_fPassmark, "Passmark" );
sReturn += AddPart( m_fRandomSpeed, "RandomSpeed" );
AddPart( AddTo, m_fRandomSpeed, "RandomSpeed" );
if( m_bTurns[TURN_MIRROR] ) sReturn += "Mirror, ";
if( m_bTurns[TURN_LEFT] ) sReturn += "Left, ";
if( m_bTurns[TURN_RIGHT] ) sReturn += "Right, ";
if( m_bTurns[TURN_SHUFFLE] ) sReturn += "Shuffle, ";
if( m_bTurns[TURN_SUPER_SHUFFLE] ) sReturn += "SuperShuffle, ";
if( m_bTurns[TURN_MIRROR] ) AddTo.push_back( "Mirror" );
if( m_bTurns[TURN_LEFT] ) AddTo.push_back( "Left" );
if( m_bTurns[TURN_RIGHT] ) AddTo.push_back( "Right" );
if( m_bTurns[TURN_SHUFFLE] ) AddTo.push_back( "Shuffle" );
if( m_bTurns[TURN_SUPER_SHUFFLE] ) AddTo.push_back( "SuperShuffle" );
if( m_bTransforms[TRANSFORM_NOHOLDS] ) sReturn += "NoHolds, ";
if( m_bTransforms[TRANSFORM_NOMINES] ) sReturn += "NoMines, ";
if( m_bTransforms[TRANSFORM_LITTLE] ) sReturn += "Little, ";
if( m_bTransforms[TRANSFORM_WIDE] ) sReturn += "Wide, ";
if( m_bTransforms[TRANSFORM_BIG] ) sReturn += "Big, ";
if( m_bTransforms[TRANSFORM_QUICK] ) sReturn += "Quick, ";
if( m_bTransforms[TRANSFORM_BMRIZE] ) sReturn += "BMRize, ";
if( m_bTransforms[TRANSFORM_SKIPPY] ) sReturn += "Skippy, ";
if( m_bTransforms[TRANSFORM_MINES] ) sReturn += "Mines, ";
if( m_bTransforms[TRANSFORM_ECHO] ) sReturn += "Echo, ";
if( m_bTransforms[TRANSFORM_STOMP] ) sReturn += "Stomp, ";
if( m_bTransforms[TRANSFORM_PLANTED] ) sReturn += "Planted, ";
if( m_bTransforms[TRANSFORM_FLOORED] ) sReturn += "Floored, ";
if( m_bTransforms[TRANSFORM_TWISTER] ) sReturn += "Twister, ";
if( m_bTransforms[TRANSFORM_NOJUMPS] ) sReturn += "NoJumps, ";
if( m_bTransforms[TRANSFORM_NOHANDS] ) sReturn += "NoHands, ";
if( m_bTransforms[TRANSFORM_NOQUADS] ) sReturn += "NoQuads, ";
if( m_bTransforms[TRANSFORM_NOHOLDS] ) AddTo.push_back( "NoHolds" );
if( m_bTransforms[TRANSFORM_NOMINES] ) AddTo.push_back( "NoMines" );
if( m_bTransforms[TRANSFORM_LITTLE] ) AddTo.push_back( "Little" );
if( m_bTransforms[TRANSFORM_WIDE] ) AddTo.push_back( "Wide" );
if( m_bTransforms[TRANSFORM_BIG] ) AddTo.push_back( "Big" );
if( m_bTransforms[TRANSFORM_QUICK] ) AddTo.push_back( "Quick" );
if( m_bTransforms[TRANSFORM_BMRIZE] ) AddTo.push_back( "BMRize" );
if( m_bTransforms[TRANSFORM_SKIPPY] ) AddTo.push_back( "Skippy" );
if( m_bTransforms[TRANSFORM_MINES] ) AddTo.push_back( "Mines" );
if( m_bTransforms[TRANSFORM_ECHO] ) AddTo.push_back( "Echo" );
if( m_bTransforms[TRANSFORM_STOMP] ) AddTo.push_back( "Stomp" );
if( m_bTransforms[TRANSFORM_PLANTED] ) AddTo.push_back( "Planted" );
if( m_bTransforms[TRANSFORM_FLOORED] ) AddTo.push_back( "Floored" );
if( m_bTransforms[TRANSFORM_TWISTER] ) AddTo.push_back( "Twister" );
if( m_bTransforms[TRANSFORM_NOJUMPS] ) AddTo.push_back( "NoJumps" );
if( m_bTransforms[TRANSFORM_NOHANDS] ) AddTo.push_back( "NoHands" );
if( m_bTransforms[TRANSFORM_NOQUADS] ) AddTo.push_back( "NoQuads" );
if( m_fSkew==1 && m_fPerspectiveTilt==-1 )
sReturn += "Incoming, ";
else if( m_fSkew==1 && m_fPerspectiveTilt==+1 )
sReturn += "Space, ";
else if( m_fSkew==0 && m_fPerspectiveTilt==-1 )
sReturn += "Hallway, ";
else if( m_fSkew==0 && m_fPerspectiveTilt==+1 )
sReturn += "Distant, ";
if( m_fSkew==1 && m_fPerspectiveTilt==-1 ) AddTo.push_back( "Incoming" );
else if( m_fSkew==1 && m_fPerspectiveTilt==+1 ) AddTo.push_back( "Space" );
else if( m_fSkew==0 && m_fPerspectiveTilt==-1 ) AddTo.push_back( "Hallway" );
else if( m_fSkew==0 && m_fPerspectiveTilt==+1 ) AddTo.push_back( "Distant" );
if( !m_sNoteSkin.empty() && m_sNoteSkin.CompareNoCase("default")!=0 )
sReturn += m_sNoteSkin + ", ";
if( sReturn.GetLength() > 2 )
sReturn.erase( sReturn.GetLength()-2 ); // delete the trailing ", "
return sReturn;
{
CString s = m_sNoteSkin;
Capitalize( s );
AddTo.push_back( s );
}
}
/* Options are added to the current settings; call Init() beforehand if
* you don't want this. */
void PlayerOptions::FromString( CString sOptions )
void PlayerOptions::FromString( CString sOptions, bool bWarnOnInvalid )
{
ASSERT( NOTESKIN );
// Init();
@@ -304,6 +308,15 @@ void PlayerOptions::FromString( CString sOptions )
else if( sBit == "subtractscore" ) m_ScoreDisplay = SCORING_SUBTRACT;
else if( sBit == "averagescore" ) m_ScoreDisplay = SCORING_AVERAGE;
else if( sBit == "random" ) ChooseRandomMofifiers();
else
{
if( bWarnOnInvalid )
{
CString sWarning = ssprintf( "The options string '%s' contains an invalid mod name '%s'", sOptions.c_str(), sBit.c_str() );
LOG->Warn( sWarning );
Dialog::OK( sWarning, "INVALID_PLAYER_OPTION_WANRING" );
}
}
}
}
@@ -569,45 +582,37 @@ bool PlayerOptions::IsEasierForCourseAndTrail( Course* pCourse, Trail* pTrail )
return false;
}
CString PlayerOptions::ThemeMod( CString sOneMod )
void PlayerOptions::GetThemedMods( vector<CString> &AddTo ) const
{
// Change all token to first letter capitalized, rest lowercase
CStringArray asTokens;
split( sOneMod, " ", asTokens );
FOREACH( CString, asTokens, s )
vector<CString> vMods;
GetMods( vMods );
FOREACH_CONST( CString, vMods, s )
{
s->MakeLower();
*s = Capitalize( *s );
const CString& sOneMod = *s;
ASSERT( !sOneMod.empty() );
CStringArray asTokens;
split( sOneMod, " ", asTokens );
if( asTokens.empty() )
continue;
// Strip the approach speed token, if any
if( asTokens[0][0] == '*' )
asTokens.erase( asTokens.begin() );
// capitalize NoteSkin names
asTokens.back() = Capitalize( asTokens.back() );
/* Theme the mod name (the last string). Allow this to not exist, since
* characters might use modifiers that don't exist in the theme. */
asTokens.back() = THEME_OPTION_ITEM( asTokens.back(), true );
CString sThemedMod = join( " ", asTokens );
AddTo.push_back( sThemedMod );
}
// Strip the approach speed token, if any
if( asTokens[0][0] == '*' )
asTokens.erase( asTokens.begin() );
// Strip "100%", if any
if( asTokens[0] == "100%" )
asTokens.erase( asTokens.begin() );
/* Theme the mod name (the last string). Allow this to not exist, since
* characters might use modifiers that don't exist in the theme. */
asTokens.back() = THEME_OPTION_ITEM( asTokens.back(), true );
return join( " ", asTokens );
}
CString PlayerOptions::GetThemedString() const
{
CString sMods = GetString();
CStringArray asMods;
split( sMods, ", ", asMods );
CStringArray asThemedMods;
for( unsigned j=0; j<asMods.size(); j++ )
{
CString& sMod = asMods[j];
asThemedMods.push_back( ThemeMod(sMod) );
}
return join( ", ", asThemedMods );
}
bool PlayerOptions::ContainsTransformOrTurn() const
+17 -16
View File
@@ -18,9 +18,9 @@ struct PlayerOptions
CString GetString() const;
CString GetSavedPrefsString() const; // only the basic options that players would want for every song
void ResetSavedPrefs();
static CString ThemeMod( CString sOneMod );
CString GetThemedString() const;
void FromString( CString sOptions );
void GetMods( vector<CString> &AddTo ) const;
void GetThemedMods( vector<CString> &AddTo ) const;
void FromString( CString sOptions, bool bWarnOnInvalid = false );
void ChooseRandomMofifiers();
bool ContainsTransformOrTurn() const;
@@ -103,20 +103,21 @@ struct PlayerOptions
/* All floats have a corresponding speed setting, which determines how fast
* PlayerOptions::Approach approaches. */
float m_fTimeSpacing, m_SpeedfTimeSpacing; // instead of Beat spacing
float m_fScrollSpeed, m_SpeedfScrollSpeed; // used if !m_bTimeSpacing
float m_fScrollBPM, m_SpeedfScrollBPM; // used if m_bTimeSpacing
float m_fAccels[NUM_ACCELS], m_SpeedfAccels[NUM_ACCELS];
float m_fEffects[NUM_EFFECTS],m_SpeedfEffects[NUM_EFFECTS];
float m_fAppearances[NUM_APPEARANCES],m_SpeedfAppearances[NUM_APPEARANCES];
float m_fScrolls[NUM_SCROLLS],m_SpeedfScrolls[NUM_SCROLLS];
float m_fDark, m_SpeedfDark;
float m_fBlind, m_SpeedfBlind;
float m_fCover, m_SpeedfCover; // hide the background per-player--can't think of a good name
float m_fPerspectiveTilt, m_SpeedfPerspectiveTilt; // -1 = near, 0 = overhead, +1 = space
float m_fSkew, m_SpeedfSkew; // 0 = vanish point is in center of player, 1 = vanish point is in center of screen
bool m_bSetScrollSpeed; // true if the scroll speed was set by FromString
float m_fTimeSpacing, m_SpeedfTimeSpacing; // instead of Beat spacing
float m_fScrollSpeed, m_SpeedfScrollSpeed; // used if !m_bTimeSpacing
float m_fScrollBPM, m_SpeedfScrollBPM; // used if m_bTimeSpacing
float m_fAccels[NUM_ACCELS], m_SpeedfAccels[NUM_ACCELS];
float m_fEffects[NUM_EFFECTS],m_SpeedfEffects[NUM_EFFECTS];
float m_fAppearances[NUM_APPEARANCES],m_SpeedfAppearances[NUM_APPEARANCES];
float m_fScrolls[NUM_SCROLLS],m_SpeedfScrolls[NUM_SCROLLS];
float m_fDark, m_SpeedfDark;
float m_fBlind, m_SpeedfBlind;
float m_fCover, m_SpeedfCover; // hide the background per-player--can't think of a good name
float m_fPerspectiveTilt, m_SpeedfPerspectiveTilt; // -1 = near, 0 = overhead, +1 = space
float m_fSkew, m_SpeedfSkew; // 0 = vanish point is in center of player, 1 = vanish point is in center of screen
float m_fRandomSpeed, m_SpeedfRandomSpeed;
float m_fRandomSpeed, m_SpeedfRandomSpeed;
/* If this is > 0, then the player must have life above this value at the end of
* the song to pass. This is independent of SongOptions::m_FailType. */
+4 -3
View File
@@ -410,11 +410,12 @@ void ScreenEvaluation::Init()
SET_XY_AND_ON_COMMAND( m_DifficultyMeter[p] );
this->AddChild( &m_DifficultyMeter[p] );
m_textPlayerOptions[p].LoadFromFont( THEME->GetPathF("Common","normal") );
CString sPO = GAMESTATE->m_pPlayerState[p]->m_PlayerOptions.GetThemedString();
sPO.Replace( ", ", PLAYER_OPTIONS_SEPARATOR );
m_textPlayerOptions[p].LoadFromFont( THEME->GetPathF(m_sName,"PlayerOptions") );
m_textPlayerOptions[p].SetName( ssprintf("PlayerOptionsP%d",p+1) );
SET_XY_AND_ON_COMMAND( m_textPlayerOptions[p] );
vector<CString> v;
GAMESTATE->m_pPlayerState[p]->m_PlayerOptions.GetThemedMods( v );
CString sPO = join( PLAYER_OPTIONS_SEPARATOR, v );
m_textPlayerOptions[p].SetText( sPO );
this->AddChild( &m_textPlayerOptions[p] );