diff --git a/stepmania/src/ActorFrame.cpp b/stepmania/src/ActorFrame.cpp index 04478ec1f6..5e49309095 100644 --- a/stepmania/src/ActorFrame.cpp +++ b/stepmania/src/ActorFrame.cpp @@ -99,31 +99,13 @@ float ActorFrame::GetTweenTimeLeft() const } +bool CompareActorsByZDesc(const Actor *p1, const Actor *p2) +{ + return p1->GetZ() > p2->GetZ(); +} + void ActorFrame::SortByZ() { - // Sort to have descending Z values so we draw back to front. - // STL sort()s typically use qsort, which won't preserve - // ordering of Actors with equal Z values. - // Sort it ourselves. -Chris - vector v; - for( unsigned i=0; iGetZ() > v[j]->GetZ() ) - { - v.insert( v.begin()+j, pToInsert ); - break; - } - - if( j == v.size() ) - v.push_back( pToInsert ); - } - - for( unsigned j=0; jGetZ() ); - - m_SubActors = v; + // Preserve ordering of Actors with equal Z values. + stable_sort( m_SubActors.begin(), m_SubActors.end(), CompareActorsByZDesc ); } diff --git a/stepmania/src/ScreenSelectMaster.cpp b/stepmania/src/ScreenSelectMaster.cpp new file mode 100644 index 0000000000..33c802a729 --- /dev/null +++ b/stepmania/src/ScreenSelectMaster.cpp @@ -0,0 +1,571 @@ +#include "global.h" +/* +----------------------------------------------------------------------------- + Class: ScreenSelectMaster + + Desc: See header. + + Copyright (c) 2001-2002 by the person(s) listed below. All rights reserved. + Chris Danford +----------------------------------------------------------------------------- +*/ + +#include "ScreenSelectMaster.h" +#include "ScreenManager.h" +#include "PrefsManager.h" +#include "GameManager.h" +#include "ThemeManager.h" +#include "GameState.h" +#include "AnnouncerManager.h" +#include "ModeChoice.h" +#include "ActorUtil.h" + +#define NUM_ICON_PARTS THEME->GetMetricI("ScreenSelectMaster","NumIconParts") +#define NUM_PREVIEW_PARTS THEME->GetMetricI("ScreenSelectMaster","NumPreviewParts") +#define NUM_CURSOR_PARTS THEME->GetMetricI("ScreenSelectMaster","NumCursorParts") +#define SHARED_PREVIEW_AND_CURSOR THEME->GetMetricB("ScreenSelectMaster","SharedPreviewAndCursor") +#define NUM_CHOICES_ON_PAGE_1 THEME->GetMetricI("ScreenSelectMaster","NumChoicesOnPage1") +#define CURSOR_OFFSET_X_FROM_ICON( p, part ) THEME->GetMetricF("ScreenSelectMaster",ssprintf("CursorPart%dP%dOffsetXFromIcon",part+1,p+1)) +#define CURSOR_OFFSET_Y_FROM_ICON( p, part ) THEME->GetMetricF("ScreenSelectMaster",ssprintf("CursorPart%dP%dOffsetYFromIcon",part+1,p+1)) +#define DISABLED_COLOR THEME->GetMetricC("ScreenSelectMaster","DisabledColor") +#define PRE_SWITCH_PAGE_SECONDS THEME->GetMetricF("ScreenSelectMaster","PreSwitchPageSeconds") +#define POST_SWITCH_PAGE_SECONDS THEME->GetMetricF("ScreenSelectMaster","PostSwitchPageSeconds") + +const ScreenMessage SM_PlayPostSwitchPage = (ScreenMessage)(SM_User+1); + +ScreenSelectMaster::ScreenSelectMaster() : ScreenSelect( "ScreenSelectMaster" ) +{ + int p, i; + + for( p=0; pGetPathToG(sFName) ); + this->AddChild( &m_sprCursor[i][0] ); + } + } + else + { + for( i=0; iIsPlayerEnabled(p) ) + continue; // skip + CString sFName = ssprintf("%s Cursor Part%d P%d", m_sName.c_str(),i+1,p+1); + m_sprCursor[i][p].SetName( ssprintf("CursorPart%dP%d",i+1,p+1) ); + m_sprCursor[i][p].Load( THEME->GetPathToG(sFName) ); + this->AddChild( &m_sprCursor[i][p] ); + } + } + } + + for( unsigned c=0; cGetPathToG(sFName) ); + this->AddChild( &m_sprIcon[i][c] ); + } + + if( SHARED_PREVIEW_AND_CURSOR ) + { + for( i=0; iGetPathToG(sFName) ); + this->AddChild( &m_sprPreview[i][c][0] ); + } + } + else + { + for( i=0; iIsPlayerEnabled(p) ) + continue; // skip + CString sFName = ssprintf("%s Preview Part%d Choice%d P%d", m_sName.c_str(),i+1,c+1,p+1); + m_sprPreview[i][c][p].SetName( ssprintf("PreviewPart%dP%d",i+1,p+1) ); + m_sprPreview[i][c][p].Load( THEME->GetPathToG(sFName) ); + this->AddChild( &m_sprPreview[i][c][p] ); + } + } + } + } + + for( int page=0; pageGetPathToG( ssprintf("ScreenSelectMaster more page%d",page+1) ) ); + this->AddChild( &m_sprMore[page] ); + + m_sprExplanation[page].SetName( ssprintf("ExplanationPage%d",page+1) ); + m_sprExplanation[page].Load( THEME->GetPathToG( ssprintf("ScreenSelectMaster explanation page%d",page+1) ) ); + this->AddChild( &m_sprExplanation[page] ); + } + + + for( p=0; pGetPathToS( "ScreenSelectMaster change") ); + m_soundSelect.Load( THEME->GetPathToS( "Common start") ); + m_soundDifficult.Load( ANNOUNCER->GetPathTo("select difficulty challenge") ); + + m_fLockInputSecs = TweenOnScreen(); +} + +void ScreenSelectMaster::Update( float fDelta ) +{ + ScreenSelect::Update( fDelta ); + m_fLockInputSecs = max( 0, m_fLockInputSecs-fDelta ); +} + +void ScreenSelectMaster::HandleScreenMessage( const ScreenMessage SM ) +{ + ScreenSelect::HandleScreenMessage( SM ); + + switch( SM ) + { + case SM_PlayPostSwitchPage: + { + float fSecs = 0; + + if( SHARED_PREVIEW_AND_CURSOR ) + { + for( int i=0; iIsPlayerEnabled(p) ) + { + m_sprCursor[i][p].SetXY( GetCursorX((PlayerNumber)p,i), GetCursorY((PlayerNumber)p,i) ); + fSecs = max( fSecs, COMMAND( m_sprCursor[i][p], "PostSwitchPage" ) ); + } + } + + if( SHARED_PREVIEW_AND_CURSOR ) + { + for( int i=0; iIsPlayerEnabled(p) ) + fSecs = max( fSecs, COMMAND( m_sprPreview[i][m_iChoice[p]][p], "PostSwitchPage" ) ); + } + + m_fLockInputSecs = POST_SWITCH_PAGE_SECONDS; + } + break; + case SM_BeginFadingOut: + float fSecs = TweenOffScreen(); + SCREENMAN->PostMessageToTopScreen( SM_AllDoneChoosing, fSecs ); // nofify parent that we're finished + m_Menu.m_MenuTimer.Stop(); + break; + } +} + +int ScreenSelectMaster::GetSelectionIndex( PlayerNumber pn ) +{ + return m_iChoice[pn]; +} + +void ScreenSelectMaster::UpdateSelectableChoices() +{ + /* XXX: If a player joins during the tween-in, this diffuse change + * will be undone by the tween. Hmm. */ + for( unsigned c=0; cIsPlayable(m_aModeChoices[c]) ) + for( int i=0; iIsHumanPlayer(p) ) + { + MenuRight( (PlayerNumber)p ); + MenuLeft( (PlayerNumber)p ); + } + } +} + +void ScreenSelectMaster::MenuLeft( PlayerNumber pn ) +{ + if( m_fLockInputSecs > 0 ) + return; + if( m_bChosen[pn] ) + return; + if( m_iChoice[pn] == 0 ) // can't go left any more + return; + + if( GetPage(m_iChoice[pn]) != GetPage(m_iChoice[pn]-1) ) + ChangePage( GetPage(m_iChoice[pn]-1) ); + else + ChangeSelection( pn, m_iChoice[pn]-1 ); +} + + +void ScreenSelectMaster::MenuRight( PlayerNumber pn ) +{ + if( m_fLockInputSecs > 0 ) + return; + if( m_bChosen[pn] ) + return; + if( m_iChoice[pn] == (int)m_aModeChoices.size()-1 ) // can't go right any more + return; + + if( GetPage(m_iChoice[pn]) != GetPage(m_iChoice[pn]+1) ) + ChangePage( GetPage(m_iChoice[pn]+1) ); + else + ChangeSelection( pn, m_iChoice[pn]+1 ); +} + +void ScreenSelectMaster::ChangePage( Page newPage ) +{ + // If anyone has already chosen, don't allow changing of pages + for( int p=0; pIsHumanPlayer(p) && m_bChosen[p] ) + return; + + float fSecs = 0; + + if( SHARED_PREVIEW_AND_CURSOR ) + { + for( int i=0; iIsHumanPlayer(p) ) + fSecs = max( fSecs, COMMAND( m_sprCursor[i][p], "PreSwitchPage" ) ); + } + + const CString sIconAndExplanationCommand = ssprintf( "SwitchToPage%d", newPage+1 ); + + for( unsigned c=0; cIsPlayerEnabled(p) ) + fSecs = max( fSecs, COMMAND( m_sprPreview[i][m_iChoice[p]][p], "PreSwitchPage" ) ); + } + + for( int page=0; pagePostScreenMessage( SM_PlayPostSwitchPage, PRE_SWITCH_PAGE_SECONDS ); +} + +void ScreenSelectMaster::ChangeSelection( PlayerNumber pn, int iNewChoice ) +{ + for( int p=0; pIsHumanPlayer(p) ) + continue; // skip + + if( p!=pn && GetCurrentPage()==PAGE_1 ) + continue; // skip + + const int iOldChoice = m_iChoice[p]; + + if( SHARED_PREVIEW_AND_CURSOR ) + { + for( int i=0; im_MasterPlayerNumber] ); +} + + +void ScreenSelectMaster::MenuStart( PlayerNumber pn ) +{ + if( m_fLockInputSecs > 0 ) + return; + if( m_bChosen[pn] == true ) + return; + m_bChosen[pn] = true; + + for( int page=0; pagePlayOnceFromDir( ANNOUNCER->GetPathTo(ssprintf("ScreenSelectMaster comment %s",mc.name)) ); + m_soundSelect.Play(); + } + + if( GetCurrentPage() == PAGE_2 ) + { + // choose this for all the other players too + for( p=0; pIsHumanPlayer(p) && !m_bChosen[p] ) + MenuStart( (PlayerNumber)p ); + } + + float fSecs = 0; + + for( int i=0; iIsHumanPlayer((PlayerNumber)p) ) + bAllDone &= m_bChosen[p]; + if( bAllDone ) + this->PostScreenMessage( SM_BeginFadingOut, fSecs );// tell our owner it's time to move on +} + +float ScreenSelectMaster::TweenOnScreen() +{ + float fSecs = 0; + + for( unsigned c=0; cIsPlayerEnabled(p) ) + for( int i=0; iIsPlayerEnabled(p) ) + for( int i=0; iIsPlayerEnabled(p) ) + { + m_sprCursor[i][p].SetXY( GetCursorX((PlayerNumber)p,i), GetCursorY((PlayerNumber)p,i) ); + fSecs = max( fSecs, ON_COMMAND( m_sprCursor[i][p] ) ); + } + } + + + fSecs = max( fSecs, SET_XY_AND_ON_COMMAND( m_sprExplanation[GetCurrentPage()] ) ); + fSecs = max( fSecs, SET_XY_AND_ON_COMMAND( m_sprMore[GetCurrentPage()] ) ); + + this->SortByZ(); + + return fSecs; +} + +float ScreenSelectMaster::TweenOffScreen() +{ + float fSecs = 0; + + if( SHARED_PREVIEW_AND_CURSOR ) + { + for( int i=0; iIsPlayerEnabled(p) ) + fSecs = max( fSecs, OFF_COMMAND( m_sprCursor[i][p] ) ); + } + + for( unsigned c=0; cIsPlayerEnabled(p) ) + fSecs = max( fSecs, OFF_COMMAND( m_sprPreview[i][c][p] ) ); + } + } + + fSecs = max( fSecs, OFF_COMMAND( m_sprExplanation[GetCurrentPage()] ) ); + fSecs = max( fSecs, OFF_COMMAND( m_sprMore[GetCurrentPage()] ) ); + + return fSecs; +} + + +float ScreenSelectMaster::GetCursorX( PlayerNumber pn, int iPartIndex ) +{ + return m_sprIcon[0][m_iChoice[pn]].GetX() + CURSOR_OFFSET_X_FROM_ICON(pn, iPartIndex); +} + +float ScreenSelectMaster::GetCursorY( PlayerNumber pn, int iPartIndex ) +{ + return m_sprIcon[0][m_iChoice[pn]].GetY() + CURSOR_OFFSET_Y_FROM_ICON(pn, iPartIndex); +} diff --git a/stepmania/src/ScreenSelectMaster.h b/stepmania/src/ScreenSelectMaster.h new file mode 100644 index 0000000000..b3b0182c75 --- /dev/null +++ b/stepmania/src/ScreenSelectMaster.h @@ -0,0 +1,72 @@ +#ifndef ScreenSelectMaster_H +#define ScreenSelectMaster_H +/* +----------------------------------------------------------------------------- + Class: ScreenSelectMaster + + Desc: Abstract class for a widget that selects a ModeChoice + + Copyright (c) 2001-2002 by the person(s) listed below. All rights reserved. + Chris Danford +----------------------------------------------------------------------------- +*/ + + +#include "ScreenSelect.h" +#include "Sprite.h" +#include "BitmapText.h" +#include "RageSound.h" +#include "RandomSample.h" + +class ScreenSelectMaster : public ScreenSelect +{ +public: + ScreenSelectMaster(); + + virtual void Update( float fDelta ); + + virtual void MenuLeft( PlayerNumber pn ); + virtual void MenuRight( PlayerNumber pn ); + virtual void MenuUp( PlayerNumber pn ) {}; + virtual void MenuDown( PlayerNumber pn ) {}; + virtual void MenuStart( PlayerNumber pn ); +// virtual void MenuBack( PlayerNumber pn ); + float TweenOffScreen(); // return time in seconds to execute the command + float TweenOnScreen(); // return time in seconds to execute the command + + virtual void HandleScreenMessage( const ScreenMessage SM ); + +protected: + enum Page { PAGE_1, PAGE_2, NUM_PAGES }; // on PAGE_2, cursors are locked together + Page GetPage( int iChoiceIndex ); + Page GetCurrentPage(); + + virtual int GetSelectionIndex( PlayerNumber pn ); + virtual void UpdateSelectableChoices(); + + void ChangePage( Page page ); + void ChangeSelection( PlayerNumber pn, int iNewChoice ); + + float GetCursorX( PlayerNumber pn, int iPartIndex ); + float GetCursorY( PlayerNumber pn, int iPartIndex ); + + Sprite m_sprExplanation[NUM_PAGES]; + Sprite m_sprMore[NUM_PAGES]; +#define MAX_ICON_PARTS 3 + Sprite m_sprIcon[MAX_ICON_PARTS][MAX_CHOICES]; +#define MAX_PREVIEW_PARTS 3 + Sprite m_sprPreview[MAX_PREVIEW_PARTS][MAX_CHOICES][NUM_PLAYERS]; +#define MAX_CURSOR_PARTS 3 + Sprite m_sprCursor[MAX_CURSOR_PARTS][NUM_PLAYERS]; + + RageSound m_soundChange; + RageSound m_soundSelect; + RandomSample m_soundDifficult; + + int m_iChoice[NUM_PLAYERS]; + bool m_bChosen[NUM_PLAYERS]; + + float m_fLockInputSecs; +}; + +#endif diff --git a/stepmania/src/StepMania.vcproj b/stepmania/src/StepMania.vcproj index 4d1b4af80f..af25a1435b 100644 --- a/stepmania/src/StepMania.vcproj +++ b/stepmania/src/StepMania.vcproj @@ -439,6 +439,12 @@ cl /Zl /nologo /c verstub.cpp /Fo"$(IntDir)"\ + + + +