2005-07-29 02:23:02 +00:00
# include "global.h"
# include "ScreenOptionsEditCourse.h"
# include "ScreenManager.h"
# include "RageLog.h"
# include "GameState.h"
# include "SongManager.h"
# include "CommonMetrics.h"
# include "GameManager.h"
# include "song.h"
2005-07-30 04:50:17 +00:00
# include "ScreenMiniMenu.h"
2005-07-30 23:40:26 +00:00
# include "ScreenPrompt.h"
2005-08-03 03:28:13 +00:00
# include "CourseUtil.h"
2005-12-22 03:10:04 +00:00
# include "LocalizedString.h"
2005-07-29 02:23:02 +00:00
enum EditCourseRow
{
2005-08-01 05:12:06 +00:00
EditCourseRow_Type ,
EditCourseRow_Meter ,
2005-07-29 02:23:02 +00:00
NUM_EditCourseRow
} ;
2005-07-30 04:50:17 +00:00
AutoScreenMessage ( SM_BackFromContextMenu )
2005-07-29 02:23:02 +00:00
enum CourseEntryAction
{
CourseEntryAction_Edit ,
CourseEntryAction_InsertEntry ,
CourseEntryAction_Delete ,
NUM_CourseEntryAction
} ;
2006-01-04 22:30:51 +00:00
static const char * CourseEntryActionNames [ ] = {
2005-07-29 02:23:02 +00:00
" Edit " ,
" Insert Entry " ,
" Delete " ,
} ;
XToString ( CourseEntryAction , NUM_CourseEntryAction ) ;
# define FOREACH_CourseEntryAction( i ) FOREACH_ENUM( CourseEntryAction, NUM_CourseEntryAction, i )
2005-07-30 04:50:17 +00:00
static MenuDef g_TempMenu (
" ScreenMiniMenuContext "
) ;
2005-07-29 02:23:02 +00:00
2006-01-15 19:49:02 +00:00
REGISTER_SCREEN_CLASS_NEW ( ScreenOptionsEditCourse ) ;
2005-07-29 02:23:02 +00:00
void ScreenOptionsEditCourse : : Init ( )
{
ScreenOptions : : Init ( ) ;
2005-08-15 02:32:36 +00:00
}
2005-07-29 02:23:02 +00:00
2005-08-15 02:32:36 +00:00
void ScreenOptionsEditCourse : : BeginScreen ( )
{
2005-07-29 02:23:02 +00:00
// save a backup that we'll use if we revert.
ASSERT ( GAMESTATE - > m_pCurCourse ) ;
Course * pCourse = GAMESTATE - > m_pCurCourse ;
m_Original = * pCourse ;
2005-08-15 16:02:14 +00:00
SONGMAN - > GetSongs ( m_vpDisplayedSongs ) ;
2005-07-29 02:23:02 +00:00
vector < OptionRowDefinition > vDefs ;
vector < OptionRowHandler * > vHands ;
OptionRowDefinition def ;
def . m_layoutType = LAYOUT_SHOW_ONE_IN_ROW ;
2005-08-01 05:12:06 +00:00
def . m_bExportOnChange = true ;
2005-07-29 02:23:02 +00:00
2005-08-01 05:12:06 +00:00
def . m_sName = " Type " ;
2005-07-29 02:23:02 +00:00
def . m_vsChoices . clear ( ) ;
2005-08-01 05:12:06 +00:00
FOREACH_CourseType ( i )
2006-01-07 04:11:29 +00:00
def . m_vsChoices . push_back ( CourseTypeToLocalizedString ( i ) ) ;
2005-07-29 02:23:02 +00:00
vDefs . push_back ( def ) ;
vHands . push_back ( NULL ) ;
def . m_sName = " Meter " ;
def . m_vsChoices . clear ( ) ;
2005-08-01 05:12:06 +00:00
def . m_vsChoices . push_back ( " Auto " ) ;
2005-07-29 02:23:02 +00:00
for ( int i = MIN_METER ; i < = MAX_METER ; i + + )
def . m_vsChoices . push_back ( ssprintf ( " %d " , i ) ) ;
vDefs . push_back ( def ) ;
vHands . push_back ( NULL ) ;
FOREACH_CONST ( CourseEntry , pCourse - > m_vEntries , ce )
{
int iEntryIndex = ce - pCourse - > m_vEntries . begin ( ) ;
def . m_sName = ssprintf ( " Entry %d " , iEntryIndex + 1 ) ;
def . m_vsChoices . clear ( ) ;
2005-08-15 16:02:14 +00:00
FOREACH_CONST ( Song * , m_vpDisplayedSongs , s )
def . m_vsChoices . push_back ( ( * s ) - > GetTranslitFullTitle ( ) ) ;
2005-07-29 02:23:02 +00:00
vDefs . push_back ( def ) ;
vHands . push_back ( NULL ) ;
}
2005-07-30 04:50:17 +00:00
def . m_sName = " " ;
2005-07-29 02:23:02 +00:00
def . m_vsChoices . clear ( ) ;
2005-07-30 04:50:17 +00:00
def . m_vsChoices . push_back ( " Insert Entry " ) ;
2005-07-29 02:23:02 +00:00
vDefs . push_back ( def ) ;
vHands . push_back ( NULL ) ;
ScreenOptions : : InitMenu ( vDefs , vHands ) ;
ScreenOptions : : BeginScreen ( ) ;
2005-07-30 23:40:26 +00:00
if ( GAMESTATE - > m_iEditCourseEntryIndex > - 1 )
this - > MoveRowAbsolute ( PLAYER_1 , NUM_EditCourseRow + GAMESTATE - > m_iEditCourseEntryIndex , false ) ;
2005-07-30 04:50:17 +00:00
AfterChangeRow ( GAMESTATE - > m_MasterPlayerNumber ) ;
2005-07-29 02:23:02 +00:00
}
2005-12-21 09:56:16 +00:00
static LocalizedString MAXIMUM_COURSE_ENTRIES ( " ScreenOptionsEditCourse " , " The maximum number of entries per course is %d. This course already has %d entries. " ) ;
static bool AreEntriesFull ( )
{
Course * pCourse = GAMESTATE - > m_pCurCourse ;
if ( pCourse - > m_vEntries . size ( ) > = size_t ( MAX_ENTRIES_PER_COURSE ) )
{
CString sError = ssprintf ( MAXIMUM_COURSE_ENTRIES . GetValue ( ) , MAX_ENTRIES_PER_COURSE , pCourse - > m_vEntries . size ( ) ) ;
ScreenPrompt : : Prompt ( SM_None , sError ) ;
return true ;
}
return false ;
}
static LocalizedString CANNOT_DELETE_LAST_ENTRY ( " ScreenOptionsEditCourse " , " You cannot delete the last entry in a course. " ) ;
2005-07-29 02:23:02 +00:00
void ScreenOptionsEditCourse : : HandleScreenMessage ( const ScreenMessage SM )
{
2005-07-30 23:40:26 +00:00
Course * pCourse = GAMESTATE - > m_pCurCourse ;
2005-07-29 02:23:02 +00:00
if ( SM = = SM_GoToNextScreen )
{
int iCurRow = m_iCurrentRow [ GAMESTATE - > m_MasterPlayerNumber ] ;
2005-08-01 05:12:06 +00:00
if ( iCurRow = = ( int ) m_pRows . size ( ) - 1 )
2005-07-29 02:23:02 +00:00
{
this - > HandleScreenMessage ( SM_GoToPrevScreen ) ;
return ; // don't call base
}
}
2005-07-30 23:40:26 +00:00
else if ( SM = = SM_GoToPrevScreen )
{
GAMESTATE - > m_iEditCourseEntryIndex . Set ( - 1 ) ;
}
2005-07-30 04:50:17 +00:00
else if ( SM = = SM_BackFromContextMenu )
2005-07-29 02:23:02 +00:00
{
2005-07-30 04:50:17 +00:00
if ( ! ScreenMiniMenu : : s_bCancelled )
{
switch ( ScreenMiniMenu : : s_iLastRowCode )
{
case CourseEntryAction_Edit :
ScreenOptions : : BeginFadingOut ( ) ;
break ;
case CourseEntryAction_InsertEntry :
{
2005-12-21 09:56:16 +00:00
if ( AreEntriesFull ( ) )
2005-07-30 23:40:26 +00:00
return ;
2005-08-03 03:28:13 +00:00
CourseEntry ce ;
CourseUtil : : MakeDefaultEditCourseEntry ( ce ) ;
pCourse - > m_vEntries . insert ( pCourse - > m_vEntries . begin ( ) + GetCourseEntryIndexWithFocus ( ) , ce ) ;
2005-07-30 04:50:17 +00:00
SCREENMAN - > SetNewScreen ( this - > m_sName ) ; // reload
}
break ;
case CourseEntryAction_Delete :
{
2005-08-01 05:12:06 +00:00
if ( pCourse - > m_vEntries . size ( ) = = 1 )
{
2005-12-21 09:56:16 +00:00
ScreenPrompt : : Prompt ( SM_None , CANNOT_DELETE_LAST_ENTRY ) ;
2005-08-01 05:12:06 +00:00
return ;
}
2005-07-30 04:50:17 +00:00
pCourse - > m_vEntries . erase ( pCourse - > m_vEntries . begin ( ) + GetCourseEntryIndexWithFocus ( ) ) ;
2005-07-30 23:40:26 +00:00
GAMESTATE - > m_iEditCourseEntryIndex . Set ( GAMESTATE - > m_iEditCourseEntryIndex ) ;
2005-07-30 04:50:17 +00:00
SCREENMAN - > SetNewScreen ( this - > m_sName ) ; // reload
}
break ;
}
}
2005-07-29 02:23:02 +00:00
}
ScreenOptions : : HandleScreenMessage ( SM ) ;
}
2005-07-30 04:50:17 +00:00
void ScreenOptionsEditCourse : : AfterChangeRow ( PlayerNumber pn )
2005-07-29 02:23:02 +00:00
{
2005-07-30 04:50:17 +00:00
ScreenOptions : : AfterChangeRow ( pn ) ;
int iCourseEntry = GetCourseEntryIndexWithFocus ( ) ;
GAMESTATE - > m_iEditCourseEntryIndex . Set ( iCourseEntry ) ;
2005-07-29 02:23:02 +00:00
}
2005-08-01 05:12:06 +00:00
void ScreenOptionsEditCourse : : AfterChangeValueInRow ( int iRow , PlayerNumber pn )
{
ScreenOptions : : AfterChangeValueInRow ( iRow , pn ) ;
Course * pCourse = GAMESTATE - > m_pCurCourse ;
// Regemerate Trails so that the new values propagate
GAMESTATE - > m_pCurTrail [ PLAYER_1 ] . Set ( NULL ) ;
Trail * pTrail = pCourse - > GetTrailForceRegenCache ( GAMESTATE - > m_stEdit , GAMESTATE - > m_PreferredCourseDifficulty [ PLAYER_1 ] ) ;
// cause overlay elements to refresh by changing the course
GAMESTATE - > m_pCurCourse . Set ( pCourse ) ;
GAMESTATE - > m_pCurTrail [ PLAYER_1 ] . Set ( pTrail ) ;
}
2005-07-29 02:23:02 +00:00
void ScreenOptionsEditCourse : : ImportOptions ( int iRow , const vector < PlayerNumber > & vpns )
{
2005-08-01 05:12:06 +00:00
OptionRow & row = * m_pRows [ iRow ] ;
Course * pCourse = GAMESTATE - > m_pCurCourse ;
2005-07-29 02:23:02 +00:00
switch ( iRow )
{
2005-08-01 05:12:06 +00:00
case EditCourseRow_Type :
row . SetOneSharedSelection ( pCourse - > GetCourseType ( ) ) ;
2005-07-29 02:23:02 +00:00
break ;
2005-08-01 05:12:06 +00:00
case EditCourseRow_Meter :
{
int iMeter = pCourse - > m_iCustomMeter [ DIFFICULTY_MEDIUM ] ;
if ( iMeter = = - 1 )
row . SetOneSharedSelection ( 0 ) ;
else
row . SetOneSharedSelection ( iMeter + 1 - MIN_METER ) ;
}
2005-07-29 02:23:02 +00:00
break ;
}
}
void ScreenOptionsEditCourse : : ExportOptions ( int iRow , const vector < PlayerNumber > & vpns )
{
2005-08-01 05:12:06 +00:00
OptionRow & row = * m_pRows [ iRow ] ;
Course * pCourse = GAMESTATE - > m_pCurCourse ;
2005-07-29 02:23:02 +00:00
2005-08-01 05:12:06 +00:00
switch ( iRow )
{
case EditCourseRow_Type :
{
CourseType ct = ( CourseType ) row . GetOneSharedSelection ( ) ;
pCourse - > SetCourseType ( ct ) ;
}
break ;
case EditCourseRow_Meter :
{
int iSel = row . GetOneSharedSelection ( ) ;
if ( iSel = = 0 ) // "auto"
pCourse - > m_iCustomMeter [ DIFFICULTY_MEDIUM ] = - 1 ;
else
pCourse - > m_iCustomMeter [ DIFFICULTY_MEDIUM ] = iSel - 1 + MIN_METER ;
}
break ;
}
2005-07-29 02:23:02 +00:00
}
2005-09-23 00:44:52 +00:00
void ScreenOptionsEditCourse : : ProcessMenuStart ( const InputEventPlus & input )
2005-07-29 02:23:02 +00:00
{
2005-07-30 04:50:17 +00:00
int iCurRow = m_iCurrentRow [ PLAYER_1 ] ;
2005-07-30 23:40:26 +00:00
Course * pCourse = GAMESTATE - > m_pCurCourse ;
2005-07-29 02:23:02 +00:00
2005-07-30 04:50:17 +00:00
if ( iCurRow < NUM_EditCourseRow )
{
// ignore
}
2005-08-01 05:12:06 +00:00
else if ( iCurRow = = ( int ) m_pRows . size ( ) - 2 ) // "create entry"
2005-07-30 04:50:17 +00:00
{
2005-12-21 09:56:16 +00:00
if ( AreEntriesFull ( ) )
2005-07-30 23:40:26 +00:00
return ;
2005-08-03 03:28:13 +00:00
CourseEntry ce ;
CourseUtil : : MakeDefaultEditCourseEntry ( ce ) ;
pCourse - > m_vEntries . push_back ( ce ) ;
2005-07-30 23:40:26 +00:00
GAMESTATE - > m_iEditCourseEntryIndex . Set ( pCourse - > m_vEntries . size ( ) - 1 ) ;
SCREENMAN - > SetNewScreen ( this - > m_sName ) ; // reload
2005-07-30 04:50:17 +00:00
}
2005-08-01 05:12:06 +00:00
else if ( iCurRow = = ( int ) m_pRows . size ( ) - 1 ) // "done"
2005-07-29 02:23:02 +00:00
{
2005-07-30 04:50:17 +00:00
this - > BeginFadingOut ( ) ;
}
else // a course entry
{
g_TempMenu . rows . clear ( ) ;
FOREACH_CourseEntryAction ( i )
2005-07-29 02:23:02 +00:00
{
2005-12-06 23:44:01 +00:00
MenuRowDef mrd ( i , CourseEntryActionToString ( i ) , true , EditMode_Home , true , 0 , " " ) ;
2005-07-30 04:50:17 +00:00
g_TempMenu . rows . push_back ( mrd ) ;
2005-07-29 02:23:02 +00:00
}
2005-07-30 04:50:17 +00:00
int iWidth , iX , iY ;
this - > GetWidthXY ( PLAYER_1 , iCurRow , 0 , iWidth , iX , iY ) ;
2005-08-01 05:12:06 +00:00
ScreenMiniMenu : : MiniMenu ( & g_TempMenu , SM_BackFromContextMenu , SM_BackFromContextMenu , ( float ) iX , ( float ) iY ) ;
2005-07-29 02:23:02 +00:00
}
}
int ScreenOptionsEditCourse : : GetCourseEntryIndexWithFocus ( ) const
{
int iCurRow = m_iCurrentRow [ GAMESTATE - > m_MasterPlayerNumber ] ;
if ( iCurRow < NUM_EditCourseRow ) // not a CourseEntry
return - 1 ;
2005-08-01 05:12:06 +00:00
else if ( iCurRow = = ( int ) m_pRows . size ( ) - 1 ) // "done"
2005-07-29 02:23:02 +00:00
return - 1 ;
else
return iCurRow - NUM_EditCourseRow ;
}
/*
* (c) 2002-2004 Chris Danford
* 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.
*/