2012-07-11 00:13:36 -05:00
# include "global.h"
# include "ScreenEditMenu.h"
# include "CommonMetrics.h"
# include "GameConstantsAndTypes.h"
# include "GameManager.h"
# include "GameSoundManager.h"
# include "GameState.h"
# include "LocalizedString.h"
# include "RageFile.h"
# include "RageFileManager.h"
# include "RageLog.h"
# include "RageUtil.h"
# include "ScreenManager.h"
# include "ScreenPrompt.h"
# include "ScreenTextEntry.h"
# include "Song.h"
# include "SongManager.h"
# include "SongUtil.h"
# include "Steps.h"
# include "ThemeManager.h"
static const RString TEMP_FILE_NAME = " --temp-- " ;
# define EXPLANATION_TEXT( row ) THEME->GetString(m_sName,"Explanation"+EditMenuRowToString(row))
# define EDIT_MENU_TYPE THEME->GetMetric(m_sName,"EditMenuType")
AutoScreenMessage ( SM_RefreshSelector ) ;
AutoScreenMessage ( SM_BackFromEditDescription ) ;
REGISTER_SCREEN_CLASS ( ScreenEditMenu ) ;
void ScreenEditMenu : : Init ( )
{
// HACK: Disable any style set by the editor.
2019-06-22 12:35:38 -07:00
GAMESTATE - > SetCurrentStyle ( nullptr , PLAYER_INVALID ) ;
2012-07-11 00:13:36 -05:00
// Enable all players.
FOREACH_PlayerNumber ( pn )
GAMESTATE - > JoinPlayer ( pn ) ;
2015-08-29 18:48:44 -06:00
// Edit mode DOES NOT WORK if the master player is not player 1. The same
// is true of various parts of this poorly designed screen. -Kyz
if ( GAMESTATE - > GetMasterPlayerNumber ( ) ! = PLAYER_1 )
{
LOG - > Warn ( " Master player number was not player 1, forcing it to player 1 so that edit mode will work. If playing in edit mode doesn't work, this might be related. " ) ;
GAMESTATE - > SetMasterPlayerNumber ( PLAYER_1 ) ;
}
2012-07-11 00:13:36 -05:00
ScreenWithMenuElements : : Init ( ) ;
m_Selector . SetName ( " EditMenu " ) ;
m_Selector . Load ( EDIT_MENU_TYPE ) ;
m_Selector . SetXY ( 0 , 0 ) ;
this - > AddChild ( & m_Selector ) ;
m_textExplanation . SetName ( " Explanation " ) ;
m_textExplanation . LoadFromFont ( THEME - > GetPathF ( m_sName , " explanation " ) ) ;
LOAD_ALL_COMMANDS_AND_SET_XY ( m_textExplanation ) ;
RefreshExplanationText ( ) ;
this - > AddChild ( & m_textExplanation ) ;
m_textNumStepsLoadedFromProfile . SetName ( " NumStepsLoadedFromProfile " ) ;
m_textNumStepsLoadedFromProfile . LoadFromFont ( THEME - > GetPathF ( m_sName , " NumStepsLoadedFromProfile " ) ) ;
LOAD_ALL_COMMANDS_AND_SET_XY_AND_ON_COMMAND ( m_textNumStepsLoadedFromProfile ) ;
RefreshNumStepsLoadedFromProfile ( ) ;
this - > AddChild ( & m_textNumStepsLoadedFromProfile ) ;
2014-12-24 02:27:46 -07:00
if ( ! m_Selector . SafeToUse ( ) )
{
m_NoSongsMessage . SetName ( " NoSongsMessage " ) ;
m_NoSongsMessage . LoadFromFont ( THEME - > GetPathF ( m_sName , " NoSongsMessage " ) ) ;
LOAD_ALL_COMMANDS_AND_SET_XY_AND_ON_COMMAND ( m_NoSongsMessage ) ;
AddChild ( & m_NoSongsMessage ) ;
m_Selector . SetVisible ( false ) ;
m_textExplanation . SetVisible ( false ) ;
m_textNumStepsLoadedFromProfile . SetVisible ( false ) ;
}
2012-07-11 00:13:36 -05:00
}
void ScreenEditMenu : : HandleScreenMessage ( const ScreenMessage SM )
{
if ( SM = = SM_RefreshSelector )
{
m_Selector . RefreshAll ( ) ;
RefreshNumStepsLoadedFromProfile ( ) ;
}
else if ( SM = = SM_Success & & m_Selector . GetSelectedAction ( ) = = EditMenuAction_Delete )
{
LOG - > Trace ( " Delete successful; deleting steps from memory " ) ;
Song * pSong = GAMESTATE - > m_pCurSong ;
Steps * pStepsToDelete = GAMESTATE - > m_pCurSteps [ PLAYER_1 ] ;
2015-02-26 14:51:54 -07:00
FOREACH_PlayerNumber ( pn )
{
2019-06-22 12:35:38 -07:00
GAMESTATE - > m_pCurSteps [ pn ] . Set ( nullptr ) ;
2015-02-26 14:51:54 -07:00
}
2012-07-11 00:13:36 -05:00
bool bSaveSong = ! pStepsToDelete - > WasLoadedFromProfile ( ) ;
pSong - > DeleteSteps ( pStepsToDelete ) ;
SONGMAN - > Invalidate ( pSong ) ;
/* Only save to the main .SM file if the steps we're deleting
* were loaded from it. */
if ( bSaveSong )
{
pSong - > Save ( ) ;
SCREENMAN - > ZeroNextUpdate ( ) ;
}
SCREENMAN - > SendMessageToTopScreen ( SM_RefreshSelector ) ;
}
else if ( SM = = SM_Failure & & m_Selector . GetSelectedAction ( ) = = EditMenuAction_Delete )
{
LOG - > Trace ( " Delete failed; not deleting steps " ) ;
}
else if ( SM = = SM_BackFromEditDescription )
{
if ( ! ScreenTextEntry : : s_bCancelledLast )
{
SOUND - > StopMusic ( ) ;
StartTransitioningScreen ( SM_GoToNextScreen ) ;
}
}
ScreenWithMenuElements : : HandleScreenMessage ( SM ) ;
}
2013-01-12 22:48:38 -05:00
bool ScreenEditMenu : : MenuUp ( const InputEventPlus & )
2012-07-11 00:13:36 -05:00
{
if ( m_Selector . CanGoUp ( ) )
{
m_Selector . Up ( ) ;
RefreshExplanationText ( ) ;
}
2013-01-12 22:48:38 -05:00
return true ;
2012-07-11 00:13:36 -05:00
}
2013-01-12 22:48:38 -05:00
bool ScreenEditMenu : : MenuDown ( const InputEventPlus & )
2012-07-11 00:13:36 -05:00
{
if ( m_Selector . CanGoDown ( ) )
{
m_Selector . Down ( ) ;
RefreshExplanationText ( ) ;
}
2013-01-12 22:48:38 -05:00
return true ;
2012-07-11 00:13:36 -05:00
}
2013-01-12 22:48:38 -05:00
bool ScreenEditMenu : : MenuLeft ( const InputEventPlus & )
2012-07-11 00:13:36 -05:00
{
if ( m_Selector . CanGoLeft ( ) )
{
m_Selector . Left ( ) ;
}
2013-01-12 22:48:38 -05:00
return true ;
2012-07-11 00:13:36 -05:00
}
2013-01-12 22:48:38 -05:00
bool ScreenEditMenu : : MenuRight ( const InputEventPlus & )
2012-07-11 00:13:36 -05:00
{
if ( m_Selector . CanGoRight ( ) )
{
m_Selector . Right ( ) ;
}
2013-01-12 22:48:38 -05:00
return true ;
2012-07-11 00:13:36 -05:00
}
static RString GetCopyDescription ( const Steps * pSourceSteps )
{
RString s = pSourceSteps - > GetDescription ( ) ;
return s ;
}
static void SetCurrentStepsDescription ( const RString & s )
{
GAMESTATE - > m_pCurSteps [ 0 ] - > SetDescription ( s ) ;
}
static void DeleteCurrentSteps ( )
{
GAMESTATE - > m_pCurSong - > DeleteSteps ( GAMESTATE - > m_pCurSteps [ 0 ] ) ;
2013-05-03 23:39:52 -04:00
GAMESTATE - > m_pCurSteps [ 0 ] . Set ( nullptr ) ;
2012-07-11 00:13:36 -05:00
}
static LocalizedString MISSING_MUSIC_FILE ( " ScreenEditMenu " , " This song is missing a music file and cannot be edited. " ) ;
static LocalizedString SONG_DIR_READ_ONLY ( " ScreenEditMenu " , " The song directory is read-only and cannot be edited. " ) ;
static LocalizedString DELETED_AUTOGEN_STEPS ( " ScreenEditMenu " , " These steps are produced by autogen. You do not need to delete them. " ) ;
static LocalizedString STEPS_WILL_BE_LOST ( " ScreenEditMenu " , " These steps will be lost permanently. " ) ;
static LocalizedString CONTINUE_WITH_DELETE ( " ScreenEditMenu " , " Continue with delete? " ) ;
static LocalizedString ENTER_EDIT_DESCRIPTION ( " ScreenEditMenu " , " Enter a description for this edit. " ) ;
2014-12-24 02:27:46 -07:00
static LocalizedString INVALID_SELECTION ( " ScreenEditMenu " , " One of the selected things is invalid. Pick something valid instead. " ) ;
2012-12-27 00:00:28 -05:00
2013-01-12 22:48:38 -05:00
bool ScreenEditMenu : : MenuStart ( const InputEventPlus & )
2012-07-11 00:13:36 -05:00
{
if ( IsTransitioning ( ) )
2013-01-12 22:48:38 -05:00
return false ;
2014-12-24 02:27:46 -07:00
if ( ! m_Selector . SafeToUse ( ) )
{
return false ;
}
2012-07-11 00:13:36 -05:00
if ( m_Selector . CanGoDown ( ) )
{
m_Selector . Down ( ) ;
RefreshExplanationText ( ) ;
2013-01-12 22:48:38 -05:00
return true ;
2012-07-11 00:13:36 -05:00
}
Song * pSong = m_Selector . GetSelectedSong ( ) ;
StepsType st = m_Selector . GetSelectedStepsType ( ) ;
Difficulty dc = m_Selector . GetSelectedDifficulty ( ) ;
Steps * pSteps = m_Selector . GetSelectedSteps ( ) ;
// StepsType soureNT = m_Selector.GetSelectedSourceStepsType();
// Difficulty sourceDiff = m_Selector.GetSelectedSourceDifficulty();
Steps * pSourceSteps = m_Selector . GetSelectedSourceSteps ( ) ;
EditMenuAction action = m_Selector . GetSelectedAction ( ) ;
2014-12-24 02:27:46 -07:00
if ( st = = StepsType_Invalid )
{
ScreenPrompt : : Prompt ( SM_None , INVALID_SELECTION ) ;
return true ;
}
2012-07-11 00:13:36 -05:00
GAMESTATE - > m_pCurSong . Set ( pSong ) ;
2019-06-22 12:35:38 -07:00
GAMESTATE - > m_pCurCourse . Set ( nullptr ) ;
2014-12-07 01:53:17 -07:00
GAMESTATE - > SetCurrentStyle ( GAMEMAN - > GetEditorStyleForStepsType ( st ) , PLAYER_INVALID ) ;
2012-07-11 00:13:36 -05:00
GAMESTATE - > m_pCurSteps [ PLAYER_1 ] . Set ( pSteps ) ;
// handle error cases
if ( ! pSong - > HasMusic ( ) )
{
ScreenPrompt : : Prompt ( SM_None , MISSING_MUSIC_FILE ) ;
2013-01-12 22:48:38 -05:00
return true ;
2012-07-11 00:13:36 -05:00
}
switch ( m_Selector . EDIT_MODE )
{
case EditMode_Full :
{
RString sDir = pSong - > GetSongDir ( ) ;
RString sTempFile = sDir + TEMP_FILE_NAME ;
RageFile file ;
if ( ! file . Open ( sTempFile , RageFile : : WRITE ) )
{
ScreenPrompt : : Prompt ( SM_None , SONG_DIR_READ_ONLY ) ;
2013-01-12 22:48:38 -05:00
return true ;
2012-07-11 00:13:36 -05:00
}
file . Close ( ) ;
FILEMAN - > Remove ( sTempFile ) ;
break ;
}
default :
break ;
}
switch ( action )
{
case EditMenuAction_Delete :
{
2013-05-03 23:01:54 -04:00
ASSERT ( pSteps ! = nullptr ) ;
2012-07-11 00:13:36 -05:00
if ( pSteps - > IsAutogen ( ) )
{
SCREENMAN - > PlayInvalidSound ( ) ;
SCREENMAN - > SystemMessage ( DELETED_AUTOGEN_STEPS . GetValue ( ) ) ;
2013-01-12 22:48:38 -05:00
return true ;
2012-07-11 00:13:36 -05:00
}
}
default : break ;
}
// Do work
switch ( action )
{
case EditMenuAction_Edit :
case EditMenuAction_Practice :
break ;
case EditMenuAction_Delete :
2013-05-03 23:01:54 -04:00
ASSERT ( pSteps ! = nullptr ) ;
2012-07-11 00:13:36 -05:00
ScreenPrompt : : Prompt ( SM_None , STEPS_WILL_BE_LOST . GetValue ( ) + " \n \n " + CONTINUE_WITH_DELETE . GetValue ( ) ,
PROMPT_YES_NO , ANSWER_NO ) ;
break ;
2015-02-27 10:36:17 -07:00
case EditMenuAction_LoadAutosave :
if ( pSong )
{
FOREACH_PlayerNumber ( pn )
{
2019-06-22 12:35:38 -07:00
GAMESTATE - > m_pCurSteps [ pn ] . Set ( nullptr ) ;
2015-02-27 10:36:17 -07:00
}
pSong - > LoadAutosaveFile ( ) ;
SONGMAN - > Invalidate ( pSong ) ;
SCREENMAN - > SendMessageToTopScreen ( SM_RefreshSelector ) ;
}
break ;
2012-07-11 00:13:36 -05:00
case EditMenuAction_Create :
ASSERT ( ! pSteps ) ;
{
pSteps = pSong - > CreateSteps ( ) ;
2012-12-27 16:59:35 -05:00
EditMode mode = m_Selector . EDIT_MODE ;
switch ( mode )
2012-07-11 00:13:36 -05:00
{
default :
2012-12-27 16:59:35 -05:00
FAIL_M ( ssprintf ( " Invalid EditMode: %i " , mode ) ) ;
2012-07-11 00:13:36 -05:00
case EditMode_Full :
break ;
case EditMode_Home :
pSteps - > SetLoadedFromProfile ( ProfileSlot_Machine ) ;
break ;
case EditMode_Practice :
2012-12-27 16:59:35 -05:00
FAIL_M ( " Cannot create steps in EditMode_Practice " ) ;
2012-07-11 00:13:36 -05:00
}
RString sEditName ;
if ( pSourceSteps )
{
pSteps - > CopyFrom ( pSourceSteps , st , pSong - > m_fMusicLengthSeconds ) ;
sEditName = GetCopyDescription ( pSourceSteps ) ;
}
else
{
pSteps - > CreateBlank ( st ) ;
pSteps - > SetMeter ( 1 ) ;
sEditName = " " ;
}
pSteps - > SetDifficulty ( dc ) ; // override difficulty with the user's choice
SongUtil : : MakeUniqueEditDescription ( pSong , st , sEditName ) ;
pSteps - > SetDescription ( sEditName ) ;
pSong - > AddSteps ( pSteps ) ;
SCREENMAN - > PlayStartSound ( ) ;
GAMESTATE - > m_pCurSong . Set ( pSong ) ;
GAMESTATE - > m_pCurSteps [ PLAYER_1 ] . Set ( pSteps ) ;
2013-05-03 23:39:52 -04:00
GAMESTATE - > m_pCurCourse . Set ( nullptr ) ;
2012-07-11 00:13:36 -05:00
}
break ;
default :
2012-12-27 16:59:35 -05:00
FAIL_M ( ssprintf ( " Invalid edit menu action: %i " , action ) ) ;
2012-07-11 00:13:36 -05:00
}
// Go to the next screen.
switch ( action )
{
case EditMenuAction_Edit :
case EditMenuAction_Create :
case EditMenuAction_Practice :
{
// Prepare for ScreenEdit
2013-05-03 23:01:54 -04:00
ASSERT ( pSteps ! = nullptr ) ;
2012-07-11 00:13:36 -05:00
bool bPromptToNameSteps = ( action = = EditMenuAction_Create & & dc = = Difficulty_Edit ) ;
if ( bPromptToNameSteps )
{
ScreenTextEntry : : TextEntry (
SM_BackFromEditDescription ,
ENTER_EDIT_DESCRIPTION ,
GAMESTATE - > m_pCurSteps [ 0 ] - > GetDescription ( ) ,
MAX_STEPS_DESCRIPTION_LENGTH ,
SongUtil : : ValidateCurrentStepsDescription ,
SetCurrentStepsDescription ,
DeleteCurrentSteps ) ;
}
else
{
SOUND - > StopMusic ( ) ;
SCREENMAN - > PlayStartSound ( ) ;
StartTransitioningScreen ( SM_GoToNextScreen ) ;
}
}
2013-01-12 22:48:38 -05:00
return true ;
2012-07-11 00:13:36 -05:00
case EditMenuAction_Delete :
2015-02-27 10:36:17 -07:00
case EditMenuAction_LoadAutosave :
2013-01-12 22:48:38 -05:00
return true ;
2012-07-11 00:13:36 -05:00
default :
2012-12-27 16:59:35 -05:00
FAIL_M ( ssprintf ( " Invalid edit menu action: %i " , action ) ) ;
2012-07-11 00:13:36 -05:00
}
}
2013-01-12 22:48:38 -05:00
bool ScreenEditMenu : : MenuBack ( const InputEventPlus & input )
2012-07-11 00:13:36 -05:00
{
Cancel ( SM_GoToPrevScreen ) ;
2013-01-12 22:48:38 -05:00
return true ;
2012-07-11 00:13:36 -05:00
}
void ScreenEditMenu : : RefreshExplanationText ( )
{
m_textExplanation . SetText ( EXPLANATION_TEXT ( m_Selector . GetSelectedRow ( ) ) ) ;
m_textExplanation . StopTweening ( ) ;
ON_COMMAND ( m_textExplanation ) ;
}
void ScreenEditMenu : : RefreshNumStepsLoadedFromProfile ( )
{
RString s = ssprintf ( " edits used: %d " , SONGMAN - > GetNumStepsLoadedFromProfile ( ) ) ;
m_textNumStepsLoadedFromProfile . SetText ( s ) ;
}
/*
* (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.
*/