#include "global.h" #include "ScreenOptionsMasterPrefs.h" #include "PrefsManager.h" #include "ThemeManager.h" #include "AnnouncerManager.h" #include "NoteSkinManager.h" #include "PlayerOptions.h" #include "SongOptions.h" #include "RageDisplay.h" #include "RageUtil.h" #include "GameManager.h" #include "GameState.h" #include "StepMania.h" #include "Game.h" #include "Foreach.h" #include "GameConstantsAndTypes.h" #include "DisplayResolutions.h" #include "LocalizedString.h" #include "SpecialFiles.h" #include "RageLog.h" using namespace StringConversion; static void GetPrefsDefaultModifiers( PlayerOptions &po, SongOptions &so ) { po.FromString( PREFSMAN->m_sDefaultModifiers ); so.FromString( PREFSMAN->m_sDefaultModifiers ); } static void SetPrefsDefaultModifiers( const PlayerOptions &po, const SongOptions &so ) { vector as; #define remove_empty_back() if(as.back() == "") { as.pop_back(); } as.push_back(po.GetString()); remove_empty_back(); as.push_back(so.GetString()); remove_empty_back(); #undef remove_empty_back PREFSMAN->m_sDefaultModifiers.Set( join(", ",as) ); } /* Ugly: the input values may be a different type than the mapping. For example, * the mapping may be an enum, and value an int. This is because we don't * have FromString/ToString for every enum type. Assume that the distance between * T and U can be represented as a float. */ template int FindClosestEntry( T value, const U *mapping, unsigned cnt ) { int iBestIndex = 0; float best_dist = 0; bool have_best = false; for( unsigned i = 0; i < cnt; ++i ) { const U val = mapping[i]; float dist = value < val? (float)(val-value):(float)(value-val); if( have_best && best_dist < dist ) continue; have_best = true; best_dist = dist; iBestIndex = i; } if( have_best ) return iBestIndex; else return 0; } template static void MoveMap( int &sel, T &opt, bool ToSel, const T *mapping, unsigned cnt ) { if( ToSel ) { sel = FindClosestEntry( opt, mapping, cnt ); } else { // sel -> opt opt = mapping[sel]; } } template static void MoveMap( int &sel, IPreference &opt, bool ToSel, const T *mapping, unsigned cnt ) { if( ToSel ) { RString sOpt = opt.ToString(); // This should really be T, but we can't FromString an enum. float val; FromString( sOpt, val ); sel = FindClosestEntry( val, mapping, cnt ); } else { // sel -> opt RString sOpt = ToString( mapping[sel] ); opt.FromString( sOpt ); } } template static void MoveMap( int &sel, const ConfOption *pConfOption, bool ToSel, const T *mapping, unsigned cnt ) { ASSERT( pConfOption != NULL ); IPreference *pPref = IPreference::GetPreferenceByName( pConfOption->m_sPrefName ); ASSERT_M( pPref != NULL, pConfOption->m_sPrefName ); MoveMap( sel, *pPref, ToSel, mapping, cnt ); } template static void MovePref( int &iSel, bool bToSel, const ConfOption *pConfOption ) { IPreference *pPref = IPreference::GetPreferenceByName( pConfOption->m_sPrefName ); ASSERT_M( pPref != NULL, pConfOption->m_sPrefName ); if( bToSel ) { // TODO: why not get the int directly from pPref? // Why are we writing it to a string and then back? T t; FromString( pPref->ToString(), t ); iSel = static_cast( t ); } else { pPref->FromString( ToString( static_cast( iSel ) ) ); } } template <> void MovePref( int &iSel, bool bToSel, const ConfOption *pConfOption ) { IPreference *pPref = IPreference::GetPreferenceByName( pConfOption->m_sPrefName ); ASSERT_M( pPref != NULL, pConfOption->m_sPrefName ); if( bToSel ) { // TODO: why not get the int directly from pPref? // Why are we writing it to a string and then back? bool b; FromString( pPref->ToString(), b ); iSel = b ? 1 : 0; } else { // If we don't make a specific instantiation of MovePref, there is // a compile warning here because of static_cast( iSel ) where // iSel is an int. What is the best way to remove that compile warning? pPref->FromString( ToString( iSel ? true : false ) ); } } static void MoveNop( int &iSel, bool bToSel, const ConfOption *pConfOption ) { if( bToSel ) iSel = 0; } // TODO: Write GenerateValueList() function that can use ints and floats. -aj static void GameChoices( vector &out ) { vector aGames; GAMEMAN->GetEnabledGames( aGames ); FOREACH( const Game*, aGames, g ) { RString sGameName = (*g)->m_szName; out.push_back( sGameName ); } } static void GameSel( int &sel, bool ToSel, const ConfOption *pConfOption ) { vector choices; pConfOption->MakeOptionsList( choices ); if( ToSel ) { const RString sCurGameName = PREFSMAN->GetCurrentGame(); sel = 0; for(unsigned i = 0; i < choices.size(); ++i) if( !stricmp(choices[i], sCurGameName) ) sel = i; } else { vector aGames; GAMEMAN->GetEnabledGames( aGames ); PREFSMAN->SetCurrentGame(aGames[sel]->m_szName); } } static void LanguageChoices( vector &out ) { vector vs; THEME->GetLanguages( vs ); SortRStringArray( vs, true ); FOREACH_CONST( RString, vs, s ) { const LanguageInfo *pLI = GetLanguageInfo( *s ); if( pLI ) out.push_back( THEME->GetString("NativeLanguageNames", pLI->szEnglishName) ); else out.push_back( *s ); } } static void Language( int &sel, bool ToSel, const ConfOption *pConfOption ) { vector vs; THEME->GetLanguages( vs ); SortRStringArray( vs, true ); if( ToSel ) { sel = -1; for( unsigned i=0; sel == -1 && i < vs.size(); ++i ) if( !stricmp(vs[i], THEME->GetCurLanguage()) ) sel = i; // If the current language doesn't exist, we'll show BASE_LANGUAGE, so select that. for( unsigned i=0; sel == -1 && i < vs.size(); ++i ) if( !stricmp(vs[i], SpecialFiles::BASE_LANGUAGE) ) sel = i; if( sel == -1 ) { LOG->Warn( "Couldn't find language \"%s\" or fallback \"%s\"; using \"%s\"", THEME->GetCurLanguage().c_str(), SpecialFiles::BASE_LANGUAGE.c_str(), vs[0].c_str() ); sel = 0; } } else { const RString &sNewLanguage = vs[sel]; PREFSMAN->m_sLanguage.Set( sNewLanguage ); if( THEME->GetCurLanguage() != sNewLanguage ) THEME->SwitchThemeAndLanguage( THEME->GetCurThemeName(), PREFSMAN->m_sLanguage, PREFSMAN->m_bPseudoLocalize ); } } static void ThemeChoices( vector &out ) { THEME->GetSelectableThemeNames( out ); FOREACH( RString, out, s ) *s = THEME->GetThemeDisplayName( *s ); } static void DisplayResolutionChoices( vector &out ) { DisplayResolutions d; DISPLAY->GetDisplayResolutions( d ); FOREACHS_CONST( DisplayResolution, d, iter ) { RString s = ssprintf("%dx%d", iter->iWidth, iter->iHeight); out.push_back( s ); } } static void RequestedTheme( int &sel, bool ToSel, const ConfOption *pConfOption ) { vector choices; pConfOption->MakeOptionsList( choices ); vector vsThemeNames; THEME->GetSelectableThemeNames( vsThemeNames ); if( ToSel ) { sel = 0; for( unsigned i=1; im_sTheme.Get()) ) sel = i; } else { const RString sNewTheme = vsThemeNames[sel]; PREFSMAN->m_sTheme.Set( sNewTheme ); // OPT_APPLY_THEME will load the theme } } static LocalizedString OFF ("ScreenOptionsMasterPrefs","Off"); static void AnnouncerChoices( vector &out ) { ANNOUNCER->GetAnnouncerNames( out ); out.insert( out.begin(), OFF ); } static void Announcer( int &sel, bool ToSel, const ConfOption *pConfOption ) { vector choices; pConfOption->MakeOptionsList( choices ); if( ToSel ) { sel = 0; for( unsigned i=1; iGetCurAnnouncerName()) ) sel = i; } else { const RString sNewAnnouncer = sel? choices[sel]:RString(""); ANNOUNCER->SwitchAnnouncer( sNewAnnouncer ); PREFSMAN->m_sAnnouncer.Set( sNewAnnouncer ); } } static void DefaultNoteSkinChoices( vector &out ) { NOTESKIN->GetNoteSkinNames( out ); } static void DefaultNoteSkin( int &sel, bool ToSel, const ConfOption *pConfOption ) { vector choices; pConfOption->MakeOptionsList( choices ); if( ToSel ) { PlayerOptions po; po.FromString( PREFSMAN->m_sDefaultModifiers ); sel = 0; for( unsigned i=0; i < choices.size(); i++ ) if( !stricmp(choices[i], po.m_sNoteSkin) ) sel = i; } else { PlayerOptions po; SongOptions so; GetPrefsDefaultModifiers( po, so ); po.m_sNoteSkin = choices[sel]; SetPrefsDefaultModifiers( po, so ); } } static void DefaultFailChoices(vector& out) { out.push_back("Immediate"); out.push_back("ImmediateContinue"); out.push_back("EndOfSong"); out.push_back("Off"); } static void DefaultFailType(int& sel, bool to_sel, const ConfOption* conf_option) { if(to_sel) { PlayerOptions po; po.FromString(PREFSMAN->m_sDefaultModifiers); sel= po.m_FailType; } else { PlayerOptions po; SongOptions so; GetPrefsDefaultModifiers(po, so); po.m_FailType= static_cast(sel); SetPrefsDefaultModifiers(po, so); } } // Background options static void BGBrightness( int &sel, bool ToSel, const ConfOption *pConfOption ) { // TODO: I hate the way the list of numbers is duplicated here and where the // option is created. Try to find a way to only use the same list once. // Do that for all of these float and int lists. const float mapping[] = { 0.0f,0.1f,0.2f,0.3f,0.4f,0.5f,0.6f,0.7f,0.8f,0.9f,1.0f }; MoveMap( sel, pConfOption, ToSel, mapping, ARRAYLEN(mapping) ); } static void BGBrightnessNoZero( int &sel, bool ToSel, const ConfOption *pConfOption ) { const float mapping[] = { 0.1f,0.2f,0.3f,0.4f,0.5f,0.6f,0.7f,0.8f,0.9f,1.0f }; MoveMap( sel, pConfOption, ToSel, mapping, ARRAYLEN(mapping) ); } static void BGBrightnessOrStatic( int &sel, bool ToSel, const ConfOption *pConfOption ) { const float mapping[] = { 0.5f,0.25f,0.5f,0.75f }; MoveMap( sel, pConfOption, ToSel, mapping, ARRAYLEN(mapping) ); IPreference *pSongBackgroundsPref = IPreference::GetPreferenceByName( "SongBackgrounds" ); if( ToSel && pSongBackgroundsPref->ToString() == "0" ) sel = 0; if( !ToSel ) pSongBackgroundsPref->FromString( sel? "1":"0" ); } static void NumBackgrounds( int &sel, bool ToSel, const ConfOption *pConfOption ) { const int mapping[] = { 5,10,15,20 }; MoveMap( sel, pConfOption, ToSel, mapping, ARRAYLEN(mapping) ); } // Input options static void MusicWheelSwitchSpeed( int &sel, bool ToSel, const ConfOption *pConfOption ) { const int mapping[] = { 5, 10, 15, 25 }; MoveMap( sel, pConfOption, ToSel, mapping, ARRAYLEN(mapping) ); } static void InputDebounceTime(int& sel, bool to_sel, ConfOption const* conf_option) { float const mapping[]= {0.0f, 0.01f, 0.02f, 0.03f, 0.04f, 0.05f, 0.06f, 0.07f, 0.08f, 0.09f, 0.1f}; MoveMap(sel, conf_option, to_sel, mapping, ARRAYLEN(mapping)); } // Machine options static void CoinModeNoHome( int &sel, bool ToSel, const ConfOption *pConfOption ) { // 0 = Pay, 1 = Free // But MovePref thinks 0 = Home, 1 = Pay, 2 = Free if( ToSel ) { MovePref( sel, ToSel, pConfOption ); // If the mode was Pay, the index is 0; otherwise, set the index // to 1 to avoid out-of-range crashing. if (sel == 1) sel = 0; else sel = 1; } else { int tmp = sel + 1; MovePref( tmp, ToSel, pConfOption ); } } static void CoinsPerCredit( int &sel, bool ToSel, const ConfOption *pConfOption ) { if( ToSel ) { MovePref( sel, ToSel, pConfOption ); sel--; } else { int tmp = sel + 1; MovePref( tmp, ToSel, pConfOption ); } } static void JointPremium( int &sel, bool ToSel, const ConfOption *pConfOption ) { const Premium mapping[] = { Premium_DoubleFor1Credit, Premium_2PlayersFor1Credit }; MoveMap( sel, pConfOption, ToSel, mapping, ARRAYLEN(mapping) ); } static void SongsPerPlay( int &sel, bool ToSel, const ConfOption *pConfOption ) { const int mapping[] = { 1,2,3,4,5 }; MoveMap( sel, pConfOption, ToSel, mapping, ARRAYLEN(mapping) ); } static void SongsPerPlayOrEventMode( int &sel, bool ToSel, const ConfOption *pConfOption ) { const int mapping[] = { 1,2,3,4,5,6 }; MoveMap( sel, pConfOption, ToSel, mapping, ARRAYLEN(mapping) ); if( ToSel && PREFSMAN->m_bEventMode ) sel = 5; if( !ToSel ) PREFSMAN->m_bEventMode.Set( sel == 5 ); } // Machine options /** @brief Timing Window scale */ static void TimingWindowScale( int &sel, bool ToSel, const ConfOption *pConfOption ) { // StepMania 5 values (implemented 2008/03/12) //const float mapping[] = { 2.0f,1.66f,1.33f,1.00f,0.75f,0.50f,0.25f }; // StepMania 3.9 and 4.0 values: const float mapping[] = { 1.50f,1.33f,1.16f,1.00f,0.84f,0.66f,0.50f,0.33f,0.20f }; MoveMap( sel, pConfOption, ToSel, mapping, ARRAYLEN(mapping) ); } /** @brief Life Difficulty scale */ static void LifeDifficulty( int &sel, bool ToSel, const ConfOption *pConfOption ) { // original StepMania 5 values (implemented 2008/03/12) //const float mapping[] = { 2.0f,1.50f,1.00f,0.66f,0.33f }; // 3.9 modified so that L6 is L4 (in SM5 some time after) //const float mapping[] = { 1.20f,1.00f,0.80f,0.60f,0.40f,0.33f,0.25f }; // StepMania 3.9 and 4.0 values: const float mapping[] = { 1.60f,1.40f,1.20f,1.00f,0.80f,0.60f,0.40f }; MoveMap( sel, pConfOption, ToSel, mapping, ARRAYLEN(mapping) ); } static void MaxHighScoresPerListForMachine(int& sel, bool to_sel, ConfOption const* conf_option) { int const mapping[]= {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20}; MoveMap(sel, conf_option, to_sel, mapping, ARRAYLEN(mapping)); } static void MaxHighScoresPerListForPlayer(int& sel, bool to_sel, ConfOption const* conf_option) { int const mapping[]= {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20}; MoveMap(sel, conf_option, to_sel, mapping, ARRAYLEN(mapping)); } #include "LuaManager.h" static int GetTimingDifficulty() { int iTimingDifficulty = 0; TimingWindowScale( iTimingDifficulty, true, ConfOption::Find("TimingWindowScale") ); iTimingDifficulty++; // TimingDifficulty returns an index return iTimingDifficulty; } LuaFunction( GetTimingDifficulty, GetTimingDifficulty() ); static int GetLifeDifficulty() { int iLifeDifficulty = 0; LifeDifficulty( iLifeDifficulty, true, ConfOption::Find("LifeDifficulty") ); iLifeDifficulty++; // LifeDifficulty returns an index return iLifeDifficulty; } LuaFunction( GetLifeDifficulty, GetLifeDifficulty() ); // Graphic options struct res_t { int w, h; res_t(): w(0), h(0) { } res_t( int w_, int h_ ): w(w_), h(h_) { } res_t& operator-=( res_t const &rhs) { w -= rhs.w; h -= rhs.h; return *this; } // Ugly: allow convert to a float for FindClosestEntry. operator float() const { return w * 5000.0f + h; } }; inline bool operator<(res_t const &lhs, res_t const &rhs) { if( lhs.w != rhs.w ) { return lhs.w < rhs.w; } return lhs.h < rhs.h; } inline bool operator>(res_t const &lhs, res_t const &rhs) { return operator<(rhs, lhs); } inline bool operator<=(res_t const &lhs, res_t const &rhs) { return !operator<(rhs, lhs); } inline bool operator>=(res_t const &lhs, res_t const &rhs) { return !operator<(lhs, rhs); } inline res_t operator-(res_t lhs, res_t const &rhs) { lhs -= rhs; return lhs; } static void DisplayResolutionM( int &sel, bool ToSel, const ConfOption *pConfOption ) { vector v; DisplayResolutions d; DISPLAY->GetDisplayResolutions( d ); FOREACHS_CONST( DisplayResolution, d, iter ) { v.push_back( res_t(iter->iWidth, iter->iHeight) ); } res_t sel_res( PREFSMAN->m_iDisplayWidth, PREFSMAN->m_iDisplayHeight ); MoveMap( sel, sel_res, ToSel, &v[0], v.size() ); if( !ToSel ) { PREFSMAN->m_iDisplayWidth.Set( sel_res.w ); PREFSMAN->m_iDisplayHeight.Set( sel_res.h ); } } static void DisplayColorDepth( int &sel, bool ToSel, const ConfOption *pConfOption ) { const int mapping[] = { 16,32 }; MoveMap( sel, pConfOption, ToSel, mapping, ARRAYLEN(mapping) ); } static void MaxTextureResolution( int &sel, bool ToSel, const ConfOption *pConfOption ) { const int mapping[] = { 256,512,1024,2048 }; MoveMap( sel, pConfOption, ToSel, mapping, ARRAYLEN(mapping) ); } static void TextureColorDepth( int &sel, bool ToSel, const ConfOption *pConfOption ) { const int mapping[] = { 16,32 }; MoveMap( sel, pConfOption, ToSel, mapping, ARRAYLEN(mapping) ); } static void MovieColorDepth( int &sel, bool ToSel, const ConfOption *pConfOption ) { const int mapping[] = { 16,32 }; MoveMap( sel, pConfOption, ToSel, mapping, ARRAYLEN(mapping) ); } static void RefreshRate( int &sel, bool ToSel, const ConfOption *pConfOption ) { const int mapping[] = { (int) REFRESH_DEFAULT,60,70,72,75,80,85,90,100,120,150 }; MoveMap( sel, pConfOption, ToSel, mapping, ARRAYLEN(mapping) ); } static void DisplayAspectRatio( int &sel, bool ToSel, const ConfOption *pConfOption ) { const float mapping[] = { 3/4.f, 1, 4/3.0f, 5/4.0f, 16/10.0f, 16/9.f, 8/3.f }; MoveMap( sel, pConfOption, ToSel, mapping, ARRAYLEN(mapping) ); } /* Simpler DisplayAspectRatio setting, which only offers "on" and "off". * "On" can be 16:9 or 16:10. */ static void WideScreen16_10( int &sel, bool ToSel, const ConfOption *pConfOption ) { const float mapping[] = { 4/3.0f, 16/10.0f }; MoveMap( sel, pConfOption, ToSel, mapping, ARRAYLEN(mapping) ); } static void WideScreen16_9( int &sel, bool ToSel, const ConfOption *pConfOption ) { const float mapping[] = { 4/3.0f, 16/9.0f }; MoveMap( sel, pConfOption, ToSel, mapping, ARRAYLEN(mapping) ); } // BackgroundCache code isn't live yet -aj /* static void BackgroundCache( int &sel, bool ToSel, const ConfOption *pConfOption ) { const BackgroundCache mapping[] = { BackgroundCacheMode_Off, BackgroundCacheMode_LowResPreload, BackgroundCacheMode_LowResLoadOnDemand, BackgroundCacheMode_Full }; MoveMap( sel, pConfOption, ToSel, mapping, ARRAYLEN(mapping) ); } */ // Sound options static void SoundVolume( int &sel, bool ToSel, const ConfOption *pConfOption ) { const float mapping[] = { 0.0f,0.1f,0.2f,0.3f,0.4f,0.5f,0.6f,0.7f,0.8f,0.9f,1.0f }; MoveMap( sel, pConfOption, ToSel, mapping, ARRAYLEN(mapping) ); } static void SoundVolumeAttract( int &sel, bool ToSel, const ConfOption *pConfOption ) { const float mapping[] = { 0.0f,0.1f,0.2f,0.3f,0.4f,0.5f,0.6f,0.7f,0.8f,0.9f,1.0f }; MoveMap( sel, pConfOption, ToSel, mapping, ARRAYLEN(mapping) ); } static void VisualDelaySeconds( int &sel, bool ToSel, const ConfOption *pConfOption ) { const float mapping[] = { -0.125f,-0.1f,-0.075f,-0.05f,-0.025f,0.0f,0.025f,0.05f,0.075f,0.1f,0.125f }; MoveMap( sel, pConfOption, ToSel, mapping, ARRAYLEN(mapping) ); } static void GlobalOffsetSeconds( int &sel, bool ToSel, const ConfOption *pConfOption ) { float mapping[41]; for( int i = 0; i < 41; ++i ) mapping[i] = SCALE( i, 0.0f, 40.0f, -0.1f, +0.1f ); MoveMap( sel, pConfOption, ToSel, mapping, ARRAYLEN(mapping) ); } static void EditRecordModeLeadIn(int &sel, bool to_sel, const ConfOption* conf_option) { float mapping[32]; for(int i= 0; i < 32; ++i) { mapping[i]= static_cast(i); } MoveMap(sel, conf_option, to_sel, mapping, ARRAYLEN(mapping)); } static vector g_ConfOptions; static void InitializeConfOptions() { if( !g_ConfOptions.empty() ) return; // There are a couple ways of getting the current preference column or turning // a new choice in the interface into a new preference. The easiest is when // the interface choices are an exact mapping to the values the preference // can be. In that case, the easiest thing to do is use MovePref. // The next easiest case is when there is a hardcoded mapping that is not 1-1, // such as CoinModeNoHome. In that case, you need to remap the result of // MovePref to the correct mapping. Harder yet is when there is a // float or a dynamic set of options, such as Language or Theme. // Those require individual attention. #define ADD(x) g_ConfOptions.push_back( x ) // Select game ADD( ConfOption( "Game", GameSel, GameChoices ) ); g_ConfOptions.back().m_iEffects = OPT_CHANGE_GAME; // Appearance options ADD( ConfOption( "Language", Language, LanguageChoices ) ); ADD( ConfOption( "Theme", RequestedTheme, ThemeChoices ) ); g_ConfOptions.back().m_iEffects = OPT_APPLY_THEME; ADD( ConfOption( "Announcer", Announcer, AnnouncerChoices ) ); ADD( ConfOption( "DefaultNoteSkin", DefaultNoteSkin, DefaultNoteSkinChoices ) ); ADD( ConfOption( "ShowInstructions", MovePref, "Skip","Show") ); ADD( ConfOption( "ShowCaution", MovePref, "Skip","Show") ); ADD( ConfOption( "DancePointsForOni", MovePref, "Percent","Dance Points") ); ADD( ConfOption( "ShowSelectGroup", MovePref, "All Music","Choose") ); ADD( ConfOption( "MusicWheelUsesSections", MovePref, "Never","Always","Title Only") ); ADD( ConfOption( "CourseSortOrder", MovePref, "Num Songs","Average Feet","Total Feet","Ranking") ); ADD( ConfOption( "MoveRandomToEnd", MovePref, "No","Yes") ); ADD( ConfOption( "ShowNativeLanguage", MovePref, "Romanization","Native Language") ); ADD( ConfOption( "ShowLyrics", MovePref, "Hide","Show") ); // Misc options ADD( ConfOption( "AutogenSteps", MovePref, "Off","On" ) ); ADD( ConfOption( "OnlyPreferredDifficulties", MovePref, "Off","On" ) ); g_ConfOptions.back().m_iEffects = OPT_APPLY_SONG; ADD( ConfOption( "AutogenGroupCourses", MovePref, "Off","On" ) ); ADD( ConfOption( "FastLoad", MovePref, "Off","On" ) ); ADD( ConfOption( "FastLoadAdditionalSongs", MovePref, "Off","On" ) ); { ConfOption c("EditRecordModeLeadIn", EditRecordModeLeadIn); for(int i= 0; i < 32; ++i) { c.AddOption(ssprintf("%+i s", i)); } ADD(c); } // Background options ADD( ConfOption( "RandomBackgroundMode", MovePref, "Off","Animations","Random Movies" ) ); ADD( ConfOption( "BGBrightness", BGBrightness, "|0%","|10%","|20%","|30%","|40%","|50%","|60%","|70%","|80%","|90%","|100%" ) ); ADD( ConfOption( "BGBrightnessNoZero", BGBrightnessNoZero, "|10%","|20%","|30%","|40%","|50%","|60%","|70%","|80%","|90%","|100%" ) ); g_ConfOptions.back().m_sPrefName = "BGBrightness"; ADD( ConfOption( "BGBrightnessOrStatic", BGBrightnessOrStatic, "Disabled","25% Bright","50% Bright","75% Bright" ) ); g_ConfOptions.back().m_sPrefName = "BGBrightness"; ADD( ConfOption( "StretchBackgrounds", MovePref, "Off","On" ) ); // Deprecated, unused by default/_fallback. -Kyz ADD( ConfOption( "BackgroundFitMode", MovePref, "CoverDistort", "CoverPreserve", "FitInside", "FitInsideAvoidLetter", "FitInsideAvoidPillar") ); ADD( ConfOption( "ShowDanger", MovePref, "Hide","Show" ) ); ADD( ConfOption( "ShowDancingCharacters", MovePref, "Default to Off","Default to Random","Select" ) ); ADD( ConfOption( "ShowBeginnerHelper", MovePref, "Off","On" ) ); ADD( ConfOption( "NumBackgrounds", NumBackgrounds, "|5","|10","|15","|20" ) ); // Input options ADD( ConfOption( "AutoMapOnJoyChange", MovePref, "Off","On (recommended)" ) ); ADD( ConfOption( "OnlyDedicatedMenuButtons", MovePref, "Use Gameplay Buttons","Only Dedicated Buttons" ) ); ADD( ConfOption( "AutoPlay", MovePref, "Off","On","CPU-Controlled" ) ); ADD( ConfOption( "DelayedBack", MovePref, "Instant","Hold" ) ); ADD( ConfOption( "ArcadeOptionsNavigation", MovePref, "StepMania Style","Arcade Style" ) ); ADD( ConfOption( "ThreeKeyNavigation", MovePref, "Five Key Menu", "Three Key Menu" ) ); ADD( ConfOption( "MusicWheelSwitchSpeed", MusicWheelSwitchSpeed, "Slow","Normal","Fast","Really Fast" ) ); ADD( ConfOption( "InputDebounceTime", InputDebounceTime, "0ms", "10ms", "20ms", "30ms", "40ms", "50ms", "60ms", "70ms", "80ms", "90ms", "100ms") ); // Gameplay options ADD( ConfOption( "Center1Player", MovePref, "Off","On" ) ); ADD( ConfOption( "HiddenSongs", MovePref, "Off","On" ) ); ADD( ConfOption( "EasterEggs", MovePref, "Off","On" ) ); // W1 is Fantastic Timing ADD( ConfOption( "AllowW1", MovePref, "Never","Courses Only","Always" ) ); ADD( ConfOption( "AllowExtraStage", MovePref, "Off","On" ) ); ADD( ConfOption( "AllowMultipleHighScoreWithSameName", MovePref, "Off", "On" ) ); ADD( ConfOption( "ComboContinuesBetweenSongs", MovePref, "Off", "On") ); ADD( ConfOption( "Disqualification", MovePref, "Off","On" ) ); ADD( ConfOption( "FailOffForFirstStageEasy", MovePref, "Off","On" ) ); ADD( ConfOption( "FailOffInBeginner", MovePref, "Off","On" ) ); ADD( ConfOption( "LockCourseDifficulties", MovePref, "Off", "On" ) ); ADD( ConfOption( "PickExtraStage", MovePref, "Off","On" ) ); ADD( ConfOption( "UseUnlockSystem", MovePref, "Off","On" ) ); // Machine options ADD( ConfOption( "MenuTimer", MovePref, "Off","On" ) ); ADD( ConfOption( "CoinMode", MovePref, "Home","Pay","Free Play" ) ); ADD( ConfOption( "CoinModeNoHome", CoinModeNoHome, "Pay","Free Play" ) ); g_ConfOptions.back().m_sPrefName = "CoinMode"; ADD( ConfOption( "CoinsPerCredit", CoinsPerCredit, "|1","|2","|3","|4","|5","|6","|7","|8","|9","|10","|11","|12","|13","|14","|15","|16" ) ); ADD( ConfOption( "SongsPerPlay", SongsPerPlay, "|1","|2","|3","|4","|5" ) ); ADD( ConfOption( "SongsPerPlayOrEvent", SongsPerPlayOrEventMode,"|1","|2","|3","|4","|5","Event" ) ); g_ConfOptions.back().m_sPrefName = "SongsPerPlay"; ADD( ConfOption( "EventMode", MovePref, "Off","On (recommended)" ) ); ADD( ConfOption( "TimingWindowScale", TimingWindowScale, "|1","|2","|3","|4","|5","|6","|7","|8","Justice" ) ); ADD( ConfOption( "LifeDifficulty", LifeDifficulty, "|1","|2","|3","|4","|5","|6","|7" ) ); g_ConfOptions.back().m_sPrefName = "LifeDifficultyScale"; ADD( ConfOption( "ProgressiveLifebar", MovePref, "Off","|1","|2","|3","|4","|5","|6","|7","|8") ); ADD( ConfOption( "ProgressiveStageLifebar", MovePref, "Off","|1","|2","|3","|4","|5","|6","|7","|8","Insanity") ); ADD( ConfOption( "ProgressiveNonstopLifebar", MovePref, "Off","|1","|2","|3","|4","|5","|6","|7","|8","Insanity") ); ADD( ConfOption( "DefaultFailType", DefaultFailType, DefaultFailChoices ) ); ADD( ConfOption( "CoinsPerCredit", CoinsPerCredit, "|1","|2","|3","|4","|5","|6","|7","|8","|9","|10","|11","|12","|13","|14","|15","|16" ) ); ADD( ConfOption( "Premium", MovePref, "Off","Double for 1 Credit","2 Players for 1 Credit" ) ); ADD( ConfOption( "JointPremium", JointPremium, "Off","2 Players for 1 Credit" ) ); g_ConfOptions.back().m_sPrefName = "Premium"; ADD( ConfOption( "ShowSongOptions", MovePref, "Ask", "Hide","Show" ) ); ADD( ConfOption( "PercentageScoring", MovePref, "Off","On" ) ); ADD( ConfOption( "GetRankingName", MovePref, "Off", "On", "Ranking Songs" ) ); ADD( ConfOption( "MaxHighScoresPerListForMachine", MaxHighScoresPerListForMachine, "1", "2", "3", "4", "5", "6", "7", "8", "9", "10", "11", "12", "13", "14", "15", "16", "17", "18", "19", "20") ); ADD( ConfOption( "MaxHighScoresPerListForPlayer", MaxHighScoresPerListForPlayer, "1", "2", "3", "4", "5", "6", "7", "8", "9", "10", "11", "12", "13", "14", "15", "16", "17", "18", "19", "20") ); ADD( ConfOption( "MinTNSToHideNotes", MovePref, "TNS_None", "TNS_HitMine", "TNS_AvoidMine", "TNS_CheckpointMiss", "TNS_Miss", "TNS_W5", "TNS_W4", "TNS_W3", "TNS_W2", "TNS_W1", "TNS_CheckpointHit")); // Graphic options ADD( ConfOption( "Windowed", MovePref, "Full Screen", "Windowed" ) ); g_ConfOptions.back().m_iEffects = OPT_APPLY_GRAPHICS; ADD( ConfOption( "DisplayResolution", DisplayResolutionM, DisplayResolutionChoices ) ); g_ConfOptions.back().m_iEffects = OPT_APPLY_GRAPHICS | OPT_APPLY_ASPECT_RATIO; ADD( ConfOption( "DisplayAspectRatio", DisplayAspectRatio, "|3:4","|1:1","|4:3","|5:4","|16:10","|16:9","|8:3" ) ); g_ConfOptions.back().m_iEffects = OPT_APPLY_GRAPHICS | OPT_APPLY_ASPECT_RATIO; // need OPT_APPLY_GRAPHICS because if windowed the width may change to make square pixels ADD( ConfOption( "WideScreen16_10", WideScreen16_10, "Off", "On" ) ); g_ConfOptions.back().m_sPrefName = "DisplayAspectRatio"; g_ConfOptions.back().m_iEffects = OPT_APPLY_ASPECT_RATIO; ADD( ConfOption( "WideScreen16_9", WideScreen16_9, "Off", "On" ) ); g_ConfOptions.back().m_sPrefName = "DisplayAspectRatio"; g_ConfOptions.back().m_iEffects = OPT_APPLY_ASPECT_RATIO; ADD( ConfOption( "DisplayColorDepth", DisplayColorDepth, "16bit","32bit" ) ); g_ConfOptions.back().m_iEffects = OPT_APPLY_GRAPHICS; ADD( ConfOption( "HighResolutionTextures", MovePref, "Auto","Force Off","Force On" ) ); g_ConfOptions.back().m_iEffects = OPT_APPLY_GRAPHICS; ADD( ConfOption( "MaxTextureResolution", MaxTextureResolution, "|256","|512","|1024","|2048" ) ); g_ConfOptions.back().m_iEffects = OPT_APPLY_GRAPHICS; ADD( ConfOption( "TextureColorDepth", TextureColorDepth, "16bit","32bit" ) ); g_ConfOptions.back().m_iEffects = OPT_APPLY_GRAPHICS; ADD( ConfOption( "MovieColorDepth", MovieColorDepth, "16bit","32bit" ) ); ADD( ConfOption( "DelayedTextureDelete", MovePref, "Off","On" ) ); g_ConfOptions.back().m_iEffects = OPT_APPLY_GRAPHICS; ADD( ConfOption( "CelShadeModels", MovePref, "Off","On" ) ); ADD( ConfOption( "SmoothLines", MovePref, "Off","On" ) ); g_ConfOptions.back().m_iEffects = OPT_APPLY_GRAPHICS; ADD( ConfOption( "RefreshRate", RefreshRate, "Default","|60","|70","|72","|75","|80","|85","|90","|100","|120","|150" ) ); g_ConfOptions.back().m_iEffects = OPT_APPLY_GRAPHICS; ADD( ConfOption( "Vsync", MovePref, "No", "Yes" ) ); g_ConfOptions.back().m_iEffects = OPT_APPLY_GRAPHICS; ADD( ConfOption( "FastNoteRendering", MovePref, "Off", "On")); ADD( ConfOption( "ShowStats", MovePref, "Off","On" ) ); ADD( ConfOption( "ShowBanners", MovePref, "Off","On" ) ); // Sound options ADD( ConfOption( "AttractSoundFrequency", MovePref, "Never","Always","2 Times","3 Times","4 Times","5 Times" ) ); ADD( ConfOption( "SoundVolume", SoundVolume, "Silent","|10%","|20%","|30%","|40%","|50%","|60%","|70%","|80%","|90%","|100%" ) ); g_ConfOptions.back().m_iEffects = OPT_APPLY_SOUND; ADD( ConfOption( "SoundVolumeAttract", SoundVolumeAttract, "Silent","|10%","|20%","|30%","|40%","|50%","|60%","|70%","|80%","|90%","|100%" ) ); ADD( ConfOption( "VisualDelaySeconds", VisualDelaySeconds, "|-5","|-4","|-3","|-2","|-1","|0","|+1","|+2","|+3","|+4","|+5" ) ); { ConfOption c( "GlobalOffsetSeconds", GlobalOffsetSeconds ); for( int i = -100; i <= +100; i += 5 ) c.AddOption( ssprintf("%+i ms", i) ); ADD( c ); } ADD( ConfOption( "EnableAttackSounds", MovePref, "No","Yes" ) ); ADD( ConfOption( "EnableMineHitSound", MovePref, "No","Yes" ) ); // Editor options ADD( ConfOption( "EditorShowBGChangesPlay", MovePref, "Hide","Show") ); ADD( ConfOption( "Invalid", MoveNop, "|Invalid option") ); } // Get a mask of effects to apply if the given option changes. int ConfOption::GetEffects() const { return m_iEffects | OPT_SAVE_PREFERENCES; } ConfOption *ConfOption::Find( RString name ) { InitializeConfOptions(); for( unsigned i = 0; i < g_ConfOptions.size(); ++i ) { ConfOption *opt = &g_ConfOptions[i]; RString match(opt->name); if( match.CompareNoCase(name) ) continue; return opt; } return NULL; } void ConfOption::UpdateAvailableOptions() { if( MakeOptionsListCB != NULL ) { names.clear(); MakeOptionsListCB( names ); } } void ConfOption::MakeOptionsList( vector &out ) const { out = names; } /** * @file * @author Glenn Maynard (c) 2003-2004 * @section LICENSE * All rights reserved. * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the * "Software"), to deal in the Software without restriction, including * without limitation the rights to use, copy, modify, merge, publish, * distribute, and/or sell copies of the Software, and to permit persons to * whom the Software is furnished to do so, provided that the above * copyright notice(s) and this permission notice appear in all copies of * the Software and that both the above copyright notice(s) and this * permission notice appear in supporting documentation. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF * THIRD PARTY RIGHTS. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR HOLDERS * INCLUDED IN THIS NOTICE BE LIABLE FOR ANY CLAIM, OR ANY SPECIAL INDIRECT * OR CONSEQUENTIAL DAMAGES, OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS * OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR * OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR * PERFORMANCE OF THIS SOFTWARE. */