#include "global.h" /* ----------------------------------------------------------------------------- Class: ScreenOptions Desc: See header. Copyright (c) 2001-2002 by the person(s) listed below. All rights reserved. Chris Danford ----------------------------------------------------------------------------- */ #include "ScreenOptions.h" #include "RageTextureManager.h" #include "RageUtil.h" #include "RageSoundManager.h" #include "ScreenManager.h" #include "PrefsManager.h" #include "GameConstantsAndTypes.h" #include "RageLog.h" #include "GameState.h" #include "ThemeManager.h" const float ITEM_X[NUM_PLAYERS] = { 260, 420 }; #define ICONS_X( p ) THEME->GetMetricF("ScreenOptions",ssprintf("IconsP%dX",p+1)) #define ARROWS_X THEME->GetMetricF("ScreenOptions","ArrowsX") #define LABELS_X THEME->GetMetricF("ScreenOptions","LabelsX") #define LABELS_ZOOM THEME->GetMetricF("ScreenOptions","LabelsZoom") #define LABELS_H_ALIGN THEME->GetMetricI("ScreenOptions","LabelsHAlign") #define ITEMS_ZOOM THEME->GetMetricF("ScreenOptions","ItemsZoom") #define ITEMS_START_X THEME->GetMetricF("ScreenOptions","ItemsStartX") #define ITEMS_GAP_X THEME->GetMetricF("ScreenOptions","ItemsGapX") #define ITEMS_START_Y THEME->GetMetricF("ScreenOptions","ItemsStartY") #define ITEMS_SPACING_Y THEME->GetMetricF("ScreenOptions","ItemsSpacingY") #define EXPLANATION_X THEME->GetMetricF("ScreenOptions","ExplanationX") #define EXPLANATION_Y THEME->GetMetricF("ScreenOptions","ExplanationY") #define EXPLANATION_ZOOM THEME->GetMetricF("ScreenOptions","ExplanationZoom") #define HELP_TEXT THEME->GetMetric("ScreenOptions","HelpText") #define TIMER_SECONDS THEME->GetMetricI("ScreenOptions","TimerSeconds") #define COLOR_SELECTED THEME->GetMetricC("ScreenOptions","ColorSelected") #define COLOR_NOT_SELECTED THEME->GetMetricC("ScreenOptions","ColorNotSelected") ScreenOptions::ScreenOptions( CString sClassName, bool bEnableTimer ) { LOG->Trace( "ScreenOptions::ScreenOptions()" ); m_sClassName = sClassName; m_SoundChangeCol.Load( THEME->GetPathTo("Sounds","ScreenOptions change") ); m_SoundNextRow.Load( THEME->GetPathTo("Sounds","ScreenOptions next") ); m_SoundPrevRow.Load( THEME->GetPathTo("Sounds","ScreenOptions prev") ); m_SoundStart.Load( THEME->GetPathTo("Sounds","Common start") ); m_Menu.Load( sClassName, bEnableTimer, false ); // no style icon this->AddChild( &m_Menu ); // add everything to m_framePage so we can animate everything at once this->AddChild( &m_framePage ); m_sprPage.Load( THEME->GetPathTo("Graphics",sClassName+" page") ); m_sprPage.SetXY( CENTER_X, CENTER_Y ); m_framePage.AddChild( &m_sprPage ); for( int p=0; pTrace( "ScreenOptions::Set()" ); m_InputMode = im; m_OptionRow = OptionRow; m_iNumOptionRows = iNumOptionLines; m_bUseIcons = bUseIcons; m_bLoadExplanations = bLoadExplanations; this->ImportOptions(); if( m_InputMode == INPUTMODE_BOTH ) { for( unsigned l=0; lIsPlayerEnabled(p) ) continue; // skip for( int l=0; lGetPathTo("Fonts","ScreenOptions explanation") ); m_textExplanation.SetXY( EXPLANATION_X, EXPLANATION_Y ); m_textExplanation.SetZoom( EXPLANATION_ZOOM ); m_textExplanation.SetShadowLength( 2 ); m_framePage.AddChild( &m_textExplanation ); InitOptionsText(); PositionUnderlines(); PositionIcons(); RefreshIcons(); PositionCursors(); UpdateEnabledDisabled(); OnChange(); } ScreenOptions::~ScreenOptions() { LOG->Trace( "ScreenOptions::~ScreenOptions()" ); } void ScreenOptions::GetWidthXY( PlayerNumber pn, int iRow, int &iWidthOut, int &iXOut, int &iYOut ) { bool bExitRow = iRow == m_iNumOptionRows; bool bLotsOfOptions = m_bRowIsLong[iRow]; int iOptionInRow = bExitRow ? 0 : bLotsOfOptions ? pn : m_iSelectedOption[pn][iRow]; BitmapText &text = m_textItems[iRow][iOptionInRow]; iWidthOut = int(roundf( text.GetWidestLineWidthInSourcePixels() * text.GetZoomX() )); iXOut = int(roundf( text.GetX() )); iYOut = int(roundf( text.GetY() )); } void ScreenOptions::InitOptionsText() { const float fLineGap = ITEMS_SPACING_Y - max(0, (m_iNumOptionRows-10)*2); // init m_textItems from optionLines int i; for( i=0; iGetPathTo("Fonts","ScreenOptions title") ); CString sText = optline.name; title.SetText( sText ); title.SetXY( LABELS_X, fY ); title.SetZoom( LABELS_ZOOM ); title.SetHorizAlign( (Actor::HorizAlign)LABELS_H_ALIGN ); title.SetVertAlign( Actor::align_middle ); title.EnableShadow( false ); Sprite &bullet = m_sprBullets[i]; bullet.Load( THEME->GetPathTo("Graphics","ScreenOptions bullet") ); bullet.SetXY( ARROWS_X, fY ); // init all text in this line and count the width of the line float fX = ITEMS_START_X; // indent 70 pixels for( unsigned j=0; jGetPathTo("Fonts","ScreenOptions item") ); option.SetText( optline.choices[j] ); option.SetZoom( ITEMS_ZOOM ); option.EnableShadow( false ); // set the XY position of each item in the line float fItemWidth = option.GetWidestLineWidthInSourcePixels() * option.GetZoomX(); fX += fItemWidth/2; option.SetXY( fX, fY ); fX += fItemWidth/2 + ITEMS_GAP_X; } m_bRowIsLong[i] = fX > SCREEN_RIGHT-40; // goes off edge of screen if( m_bRowIsLong[i] ) { // re-init with "long row" style for( unsigned j=0; jIsPlayerEnabled(p) ) { BitmapText &option = m_textItems[i][p]; int iChoiceInRow = m_iSelectedOption[p][i]; option.LoadFromFont( THEME->GetPathTo("Fonts","ScreenOptions item") ); option.SetText( m_OptionRow[i].choices[iChoiceInRow] ); option.SetZoom( ITEMS_ZOOM ); option.EnableShadow( false ); option.SetXY( ITEM_X[p], fY ); UpdateText( (PlayerNumber)p ); } } } } BitmapText &option = m_textItems[i][0]; option.LoadFromFont( THEME->GetPathTo("Fonts","ScreenOptions item") ); option.SetText( "EXIT" ); option.SetZoom( ITEMS_ZOOM ); option.SetShadowLength( 2 ); float fY = ITEMS_START_Y + fLineGap*i; option.SetXY( CENTER_X, fY ); } void ScreenOptions::DimOption(int line, int option, bool dim) { if(m_OptionDim[line][option] == dim) return; m_OptionDim[line][option] = dim; m_textItems[line][option].StopTweening(); m_textItems[line][option].BeginTweening(.250); if(m_OptionDim[line][option]) m_textItems[line][option].SetTweenDiffuse( RageColor(.5,.5,.5,1) ); else m_textItems[line][option].SetTweenDiffuse( RageColor(1,1,1,1) ); } bool ScreenOptions::RowCompletelyDimmed(int line) const { for(unsigned i = 0; i < m_OptionRow[line].choices.size(); ++i) if(!m_OptionDim[line][i]) return false; return true; } void ScreenOptions::PositionUnderlines() { // Set the position of the underscores showing the current choice for each option line. for( int p=0; pIsPlayerEnabled(p) && m_iCurrentRow[p] == i ) bThisRowIsSelected = true; m_sprBullets[i].SetDiffuse( bThisRowIsSelected ? colorSelected : colorNotSelected ); m_textTitles[i].SetDiffuse( bThisRowIsSelected ? colorSelected : colorNotSelected ); if( m_bRowIsLong[i] ) for( unsigned j=0; jIsPlayerEnabled(p) && m_iCurrentRow[p] != i ) bThisRowIsSelectedByBoth = false; m_textItems[i][0].SetDiffuse( bThisRowIsSelectedByBoth ? colorNotSelected : colorSelected ); if( bThisRowIsSelectedByBoth ) m_textItems[i][0].SetEffectDiffuseShift( 1.0f, colorSelected, colorNotSelected ); else m_textItems[i][0].SetEffectNone(); } void ScreenOptions::Update( float fDeltaTime ) { //LOG->Trace( "ScreenOptions::Update(%f)", fDeltaTime ); Screen::Update( fDeltaTime ); } void ScreenOptions::DrawPrimitives() { m_Menu.DrawBottomLayer(); Screen::DrawPrimitives(); m_Menu.DrawTopLayer(); } void ScreenOptions::Input( const DeviceInput& DeviceI, const InputEventType type, const GameInput &GameI, const MenuInput &MenuI, const StyleInput &StyleI ) { /* Allow input when transitioning in (m_In.IsTransitioning()), but ignore it * when we're transitioning out. */ if( m_Menu.m_Back.IsTransitioning() || m_Menu.m_Out.IsTransitioning() ) return; // default input handler Screen::Input( DeviceI, type, GameI, MenuI, StyleI ); } void ScreenOptions::HandleScreenMessage( const ScreenMessage SM ) { switch( SM ) { case SM_MenuTimer: this->PostScreenMessage( SM_BeginFadingOut, 0 ); break; case SM_GoToPrevScreen: // this->ExportOptions(); // Don't save options if we're going back! this->GoToPrevState(); break; case SM_GoToNextScreen: this->ExportOptions(); this->GoToNextState(); break; case SM_BeginFadingOut: if(m_Menu.IsTransitioning()) return; /* already transitioning */ m_Menu.StartTransitioning( SM_GoToNextScreen ); m_SoundStart.Play(); m_framePage.BeginTweening( 0.3f, Actor::TWEEN_ACCELERATE ); m_framePage.SetTweenX( SCREEN_RIGHT ); break; } } void ScreenOptions::OnChange() { PositionUnderlines(); RefreshIcons(); UpdateEnabledDisabled(); int iCurRow = m_iCurrentRow[PLAYER_1]; bool bIsExitRow = iCurRow == m_iNumOptionRows; if( !bIsExitRow && m_bLoadExplanations ) { CString sLineName = m_OptionRow[iCurRow].name; if( sLineName=="" ) sLineName = m_OptionRow[iCurRow].choices[0]; sLineName.Replace("\n",""); sLineName.Replace(" ",""); m_textExplanation.SetText( THEME->GetMetric(m_sClassName,sLineName) ); } else m_textExplanation.SetText( "" ); } void ScreenOptions::MenuBack( PlayerNumber pn ) { Screen::MenuBack( pn ); m_Menu.Back( SM_GoToPrevScreen ); } void ScreenOptions::StartGoToNextState() { this->PostScreenMessage( SM_BeginFadingOut, 0 ); } void ScreenOptions::MenuStart( PlayerNumber pn ) { if( m_Menu.IsTransitioning() ) return; if( PREFSMAN->m_bArcadeOptionsNavigation ) { bool bAllOnExit = true; for( int p=0; pIsPlayerEnabled(p) && m_iCurrentRow[p] != m_iNumOptionRows ) bAllOnExit = false; if( m_iCurrentRow[pn] != m_iNumOptionRows ) // not on exit MenuDown( pn ); // can't go down any more else if( bAllOnExit ) this->PostScreenMessage( SM_BeginFadingOut, 0 ); } else // !m_bArcadeOptionsNavigation { this->PostScreenMessage( SM_BeginFadingOut, 0 ); } } void ScreenOptions::MenuLeft( PlayerNumber pn ) { for( int p=0; p