Files
itgmania212121/stepmania/src/ScreenEdit.cpp
T

2416 lines
81 KiB
C++
Raw Normal View History

2003-02-16 04:01:45 +00:00
#include "global.h"
2002-05-20 08:59:37 +00:00
#include "ScreenEdit.h"
#include "PrefsManager.h"
#include "SongManager.h"
#include "ScreenManager.h"
#include "GameConstantsAndTypes.h"
2002-07-23 01:41:40 +00:00
#include "PrefsManager.h"
2002-05-20 08:59:37 +00:00
#include "GameManager.h"
#include "GameConstantsAndTypes.h"
#include "RageLog.h"
2004-07-08 00:10:34 +00:00
#include "GameSoundManager.h"
2002-07-23 01:41:40 +00:00
#include "GameState.h"
2002-10-18 19:01:32 +00:00
#include "InputMapper.h"
#include "RageLog.h"
#include "ThemeManager.h"
2003-02-18 23:15:38 +00:00
#include "ScreenMiniMenu.h"
2003-02-19 06:27:20 +00:00
#include "NoteSkinManager.h"
2003-08-03 00:13:55 +00:00
#include "Steps.h"
#include <utility>
#include "NoteFieldPositioning.h"
2003-07-22 07:47:27 +00:00
#include "arch/arch.h"
2003-08-07 06:36:34 +00:00
#include "NoteDataUtil.h"
#include "SongUtil.h"
#include "StepsUtil.h"
#include "Foreach.h"
#include "ScreenDimensions.h"
#include "ThemeMetric.h"
#include "PlayerState.h"
2002-05-20 08:59:37 +00:00
2003-02-18 23:15:38 +00:00
const float RECORD_HOLD_SECONDS = 0.3f;
2002-10-18 19:01:32 +00:00
2002-05-20 08:59:37 +00:00
//
// Defines specific to GameScreenTitleMenu
//
2003-09-21 23:16:44 +00:00
#define DEBUG_X (SCREEN_LEFT + 10)
2004-11-05 06:35:10 +00:00
#define DEBUG_Y (SCREEN_CENTER_Y-100)
2002-08-17 06:44:04 +00:00
2004-11-05 06:35:10 +00:00
#define SHORTCUTS_X (SCREEN_CENTER_X - 150)
#define SHORTCUTS_Y (SCREEN_CENTER_Y)
2002-05-20 08:59:37 +00:00
2003-09-21 23:16:44 +00:00
#define HELP_X (SCREEN_LEFT)
2004-11-05 06:35:10 +00:00
#define HELP_Y (SCREEN_CENTER_Y)
2002-05-20 08:59:37 +00:00
2003-09-21 23:16:44 +00:00
#define HELP_TEXT_X (SCREEN_LEFT + 4)
#define HELP_TEXT_Y (40)
2003-02-18 23:15:38 +00:00
2003-09-21 23:16:44 +00:00
#define INFO_X (SCREEN_RIGHT)
2004-11-05 06:35:10 +00:00
#define INFO_Y (SCREEN_CENTER_Y)
2003-02-18 23:15:38 +00:00
2003-09-21 23:16:44 +00:00
#define INFO_TEXT_X (SCREEN_RIGHT - 114)
#define INFO_TEXT_Y (40)
2003-02-18 23:15:38 +00:00
2003-09-21 23:16:44 +00:00
#define MENU_WIDTH (110)
2004-11-05 06:35:10 +00:00
#define EDIT_X (SCREEN_CENTER_X)
2003-09-21 23:16:44 +00:00
#define EDIT_GRAY_Y_STANDARD (SCREEN_TOP+60)
#define EDIT_GRAY_Y_REVERSE (SCREEN_BOTTOM-60)
2002-05-20 08:59:37 +00:00
2004-11-05 06:35:10 +00:00
#define PLAYER_X (SCREEN_CENTER_X)
#define PLAYER_Y (SCREEN_CENTER_Y)
2003-09-21 23:16:44 +00:00
#define PLAYER_HEIGHT (360)
#define PLAYER_Y_STANDARD (PLAYER_Y-PLAYER_HEIGHT/2)
#define PLAYER_Y_REVERSE (PLAYER_Y+PLAYER_HEIGHT/2)
2003-10-02 03:05:52 +00:00
2002-05-20 08:59:37 +00:00
2004-11-05 06:35:10 +00:00
#define ACTION_MENU_ITEM_X (SCREEN_CENTER_X-200)
2003-09-21 23:16:44 +00:00
#define ACTION_MENU_ITEM_START_Y (SCREEN_TOP + 24)
#define ACTION_MENU_ITEM_SPACING_Y (18)
2002-07-02 00:27:58 +00:00
2004-11-05 06:35:10 +00:00
#define NAMING_MENU_ITEM_X (SCREEN_CENTER_X-200)
2003-09-21 23:16:44 +00:00
#define NAMING_MENU_ITEM_START_Y (SCREEN_TOP + 24)
#define NAMING_MENU_ITEM_SPACING_Y (18)
2002-08-17 06:44:04 +00:00
ThemeMetric<float> TICK_EARLY_SECONDS ("ScreenGameplay","TickEarlySeconds");
2003-02-18 23:15:38 +00:00
const ScreenMessage SM_BackFromMainMenu = (ScreenMessage)(SM_User+1);
const ScreenMessage SM_BackFromAreaMenu = (ScreenMessage)(SM_User+2);
const ScreenMessage SM_BackFromEditNotesStatistics = (ScreenMessage)(SM_User+3);
const ScreenMessage SM_BackFromEditOptions = (ScreenMessage)(SM_User+4);
const ScreenMessage SM_BackFromEditSongInfo = (ScreenMessage)(SM_User+5);
const ScreenMessage SM_BackFromBGChange = (ScreenMessage)(SM_User+6);
2003-11-12 08:13:02 +00:00
const ScreenMessage SM_BackFromPlayerOptions = (ScreenMessage)(SM_User+7);
const ScreenMessage SM_BackFromSongOptions = (ScreenMessage)(SM_User+8);
const ScreenMessage SM_BackFromInsertAttack = (ScreenMessage)(SM_User+9);
const ScreenMessage SM_BackFromInsertAttackModifiers= (ScreenMessage)(SM_User+10);
const ScreenMessage SM_BackFromPrefs = (ScreenMessage)(SM_User+11);
2004-01-26 20:56:58 +00:00
const ScreenMessage SM_BackFromCourseModeMenu = (ScreenMessage)(SM_User+12);
const ScreenMessage SM_DoReloadFromDisk = (ScreenMessage)(SM_User+13);
const ScreenMessage SM_DoUpdateTextInfo = (ScreenMessage)(SM_User+14);
2002-06-29 11:59:09 +00:00
2003-02-18 23:15:38 +00:00
const CString HELP_TEXT =
2004-10-28 07:56:13 +00:00
#if !defined(XBOX)
2003-02-18 23:15:38 +00:00
"Up/Down:\n change beat\n"
"Left/Right:\n change snap\n"
"Number keys:\n add/remove\n tap note\n"
"Create hold note:\n Hold a number\n while moving\n Up or Down\n"
2003-02-19 05:46:09 +00:00
"Space bar:\n Set area\n marker\n"
"Enter:\n Area Menu\n"
"Escape:\n Main Menu\n"
"F1:\n Show\n keyboard\n shortcuts\n";
2004-10-28 07:56:13 +00:00
#else
"Up/Down:\n change beat\n"
"Left/Right:\n change snap\n"
"A/B/X/Y:\n add/remove\n tap note\n"
"Create hold note:\n Hold a button\n while moving\n Up or Down\n"
"White:\n Set area\n marker\n"
"Start:\n Area Menu\n"
"Select:\n Main Menu\n"
"Black:\n Show\n shortcuts\n";
#endif
2003-02-18 23:15:38 +00:00
static const MenuRow g_KeyboardShortcutsItems[] =
{
2004-10-28 07:56:13 +00:00
#if !defined(XBOX)
2003-11-08 00:56:39 +00:00
{ "PgUp/PgDn: jump measure", false, 0, { NULL } },
{ "Home/End: jump to first/last beat", false, 0, { NULL } },
{ "Ctrl + Up/Down: Change zoom", false, 0, { NULL } },
{ "Shift + Up/Down: Drag area marker", false, 0, { NULL } },
{ "P: Play selection", false, 0, { NULL } },
{ "Ctrl + P: Play whole song", false, 0, { NULL } },
{ "Shift + P: Play current beat to end", false, 0, { NULL } },
{ "Ctrl + R: Record", false, 0, { NULL } },
{ "F4: Toggle assist tick", false, 0, { NULL } },
{ "F5/F6: Next/prev steps of same StepsType", false, 0, { NULL } },
{ "F7/F8: Decrease/increase BPM at cur beat", false, 0, { NULL } },
{ "F9/F10: Decrease/increase stop at cur beat", false, 0, { NULL } },
{ "F11/F12: Decrease/increase music offset", false, 0, { NULL } },
2003-03-05 02:38:17 +00:00
/* XXX: This would be better as a single submenu, to let people tweak
* and play the sample several times (without having to re-enter the
* menu each time), so it doesn't use a whole bunch of hotkeys. */
2003-11-08 00:56:39 +00:00
{ "[ and ]: Decrease/increase sample music start", false, 0, { NULL } },
{ "{ and }: Decrease/increase sample music length", false, 0, { NULL } },
{ "M: Play sample music", false, 0, { NULL } },
{ "B: Add/Edit Background Change", false, 0, { NULL } },
{ "Insert: Insert beat and shift down", false, 0, { NULL } },
{ "Ctrl + Insert: Shift BPM changes and stops down one beat",
false, 0, { NULL } },
2003-11-08 00:56:39 +00:00
{ "Delete: Delete beat and shift up", false, 0, { NULL } },
{ "Ctrl + Delete: Shift BPM changes and stops up one beat",
false, 0, { NULL } },
2003-11-08 00:56:39 +00:00
{ "Shift + number: Lay mine", false, 0, { NULL } },
2003-11-08 01:00:27 +00:00
{ "Alt + number: Add to/remove from right half", false, 0, { NULL } },
2004-10-28 07:56:13 +00:00
#else
{ "L + Up/Down: Change zoom", false, 0, { NULL } },
{ "R + Up/Down: Drag area marker", false, 0, { NULL } },
{ "L + Select: Play selection", false, 0, { NULL } },
{ "R + Start: Play whole song", false, 0, { NULL } },
{ "R + Select: Record", false, 0, { NULL } },
{ "L + Black: Toggle assist tick", false, 0, { NULL } },
{ "R + White: Insert beat and shift down", false, 0, { NULL } },
{ "R + Black: Delete beat and shift up", false, 0, { NULL } },
{ "R + button: Lay mine", false, 0, { NULL } },
{ "L + button: Add to/remove from right half", false, 0, { NULL } },
#endif
2003-11-08 01:00:27 +00:00
{ NULL, true, 0, { NULL } }
};
static Menu g_KeyboardShortcuts( "Keyboard Shortcuts", g_KeyboardShortcutsItems );
static const MenuRow g_MainMenuItems[] =
{
2003-11-08 00:56:39 +00:00
{ "Edit Steps Statistics", true, 0, { NULL } },
{ "Play Whole Song", true, 0, { NULL } },
{ "Play Current Beat To End", true, 0, { NULL } },
{ "Save", true, 0, { NULL } },
2004-01-24 20:36:09 +00:00
{ "Reload from disk", true, 0, { NULL } },
2003-11-08 00:56:39 +00:00
{ "Player Options", true, 0, { NULL } },
{ "Song Options", true, 0, { NULL } },
{ "Edit Song Info", true, 0, { NULL } },
{ "Add/Edit BG Change", true, 0, { NULL } },
{ "Play preview music", true, 0, { NULL } },
{ "Preferences", true, 0, { NULL } },
2003-11-08 01:00:27 +00:00
{ "Exit (discards changes since last save)",true, 0, { NULL } },
{ NULL, true, 0, { NULL } }
};
static Menu g_MainMenu( "Main Menu", g_MainMenuItems );
static const MenuRow g_AreaMenuItems[] =
{
2003-11-08 00:56:39 +00:00
{ "Cut", true, 0, { NULL } },
{ "Copy", true, 0, { NULL } },
{ "Paste at current beat", true, 0, { NULL } },
{ "Paste at begin marker", true, 0, { NULL } },
{ "Clear", true, 0, { NULL } },
2003-11-08 01:00:27 +00:00
{ "Quantize", true, 0, { "4TH","8TH","12TH","16TH","24TH","32ND","48TH","64TH" } },
{ "Turn", true, 0, { "Left","Right","Mirror","Shuffle","Super Shuffle" } },
2004-08-29 21:26:52 +00:00
{ "Transform", true, 0, { "NoHolds","NoMines","Little","Wide","Big","Quick","BMRize","Skippy","Mines","Echo","Stomp","Planted","Floored","Twister","NoJumps","NoHands","NoQuads" } },
2003-12-31 07:49:30 +00:00
{ "Alter", true, 0, { "Backwards","Swap Sides","Copy Left To Right","Copy Right To Left","Clear Left","Clear Right","Collapse To One","Collapse Left","Shift Left","Shift Right" } },
2003-11-08 01:00:27 +00:00
{ "Tempo", true, 0, { "Compress 2x","Compress 3->2","Compress 4->3","Expand 3->4","Expand 2->3","Expand 2x" } },
2003-11-08 00:56:39 +00:00
{ "Play selection", true, 0, { NULL } },
{ "Record in selection", true, 0, { NULL } },
{ "Insert beat and shift down", true, 0, { NULL } },
{ "Delete beat and shift up", true, 0, { NULL } },
{ "Shift pauses and BPM changes down",
true, 0, { NULL } },
{ "Shift pauses and BPM changes up",
true, 0, { NULL } },
2003-11-08 00:56:39 +00:00
{ "Convert beats to pause", true, 0, { NULL } },
2003-11-08 01:00:27 +00:00
{ "Convert pause to beats", true, 0, { NULL } },
{ NULL, true, 0, { NULL } }
};
static Menu g_AreaMenu( "Area Menu", g_AreaMenuItems );
static const MenuRow g_EditNotesStatisticsItems[] =
{
2004-02-25 23:43:50 +00:00
{ "Difficulty", true, 0, { "BEGINNER","EASY","MEDIUM","HARD","CHALLENGE","EDIT" } },
{ "Meter", true, 0, { "1","2","3","4","5","6","7","8","9","10","11","12","13","14","15" } },
{ "Description", true, 0, { NULL } },
{ "Predicted Meter", false, 0, { NULL } },
2003-11-08 00:56:39 +00:00
{ "Tap Steps", false, 0, { NULL } },
{ "Hold Steps", false, 0, { NULL } },
{ "Stream", false, 0, { NULL } },
{ "Voltage", false, 0, { NULL } },
{ "Air", false, 0, { NULL } },
{ "Freeze", false, 0, { NULL } },
2003-11-08 01:00:27 +00:00
{ "Chaos", false, 0, { NULL } },
{ NULL, true, 0, { NULL } }
};
static Menu g_EditNotesStatistics( "Statistics", g_EditNotesStatisticsItems );
static const MenuRow g_EditSongInfoItems[] =
{
2003-11-08 00:56:39 +00:00
{ "Main title", true, 0, { NULL } },
{ "Sub title", true, 0, { NULL } },
{ "Artist", true, 0, { NULL } },
{ "Credit", true, 0, { NULL } },
{ "Main title transliteration", true, 0, { NULL } },
{ "Sub title transliteration", true, 0, { NULL } },
2003-11-08 01:00:27 +00:00
{ "Artist transliteration", true, 0, { NULL } },
{ NULL, true, 0, { NULL } }
};
static Menu g_EditSongInfo( "Edit Song Info", g_EditSongInfoItems );
static const MenuRow g_BGChangeItems[] =
{
{ "Rate (applies to new adds)", true, 10, { "0%","10%","20%","30%","40%","50%","60%","70%","80%","90%","100%","120%","140%","160%","180%","200%" } },
2003-11-08 01:00:27 +00:00
{ "Fade Last (applies to new adds)", true, 0, { "NO","YES" } },
{ "Rewind Movie (applies to new adds)", true, 0, { "NO","YES" } },
{ "Loop (applies to new adds)", true, 1, { "NO","YES" } },
2003-11-08 00:56:39 +00:00
{ "Add Change to random", true, 0, { NULL } },
{ "Add Change to song BGAnimation", true, 0, { NULL } },
{ "Add Change to song Movie", true, 0, { NULL } },
{ "Add Change to song Still", true, 0, { NULL } },
{ "Add Change to global Random Movie", true, 0, { NULL } },
{ "Add Change to global BGAnimation", true, 0, { NULL } },
{ "Add Change to global Visualization", true, 0, { NULL } },
2003-11-08 01:00:27 +00:00
{ "Remove Change", true, 0, { NULL } },
{ NULL, true, 0, { NULL } }
};
static Menu g_BGChange( "Background Change", g_BGChangeItems );
2002-05-20 08:59:37 +00:00
static const MenuRow g_PrefsItems[] =
{
{ "Show BGChanges during Play/Record", true, 0, { "NO","YES" } },
{ NULL, true, 0, { NULL } }
};
static Menu g_Prefs( "Preferences", g_PrefsItems );
2003-11-12 08:13:02 +00:00
static const MenuRow g_InsertAttackItems[] =
{
{ "Duration seconds", true, 3, { "5","10","15","20","25","30","35","40","45" } },
2003-11-12 08:13:02 +00:00
{ "Set modifiers", true, 0, { "PRESS START" } },
{ NULL, true, 0, { NULL } }
};
static Menu g_InsertAttack( "Insert Attack", g_InsertAttackItems );
2004-01-26 20:56:58 +00:00
static const MenuRow g_CourseModeItems[] =
{
{ "Play mods from course", true, 0, { NULL } },
{ NULL, true, 0, { NULL } }
};
static Menu g_CourseMode( "Course Display", g_CourseModeItems );
2003-11-12 08:13:02 +00:00
// HACK: need to remember the track we're inserting on so
// that we can lay the attack note after coming back from
// menus.
int g_iLastInsertAttackTrack = -1;
2003-11-12 08:32:32 +00:00
float g_fLastInsertAttackDurationSeconds = -1;
2003-11-12 08:13:02 +00:00
2004-10-28 07:56:13 +00:00
#if defined(XBOX)
bool lIsHeld = false; // true if L (Ctrl) is being held
bool rIsHeld = false; // true if R (Shift) is being held
bool buttonHeld[4] = {false};
DeviceInput TranslateInput(const DeviceInput& DeviceI, const InputEventType type)
{
DeviceInput ret;
ret.device = DEVICE_KEYBOARD;
ret.button = 0;
int i = -1;
switch(DeviceI.button)
{
case JOY_HAT_LEFT:
ret.button = KEY_LEFT;
break;
case JOY_HAT_RIGHT:
ret.button = KEY_RIGHT;
break;
case JOY_HAT_UP:
ret.button = KEY_UP;
break;
case JOY_HAT_DOWN:
ret.button = KEY_DOWN;
break;
case JOY_AUX_1: // start
if(!lIsHeld)
ret.button = KEY_ENTER;
else
ret.button = KEY_CP;
break;
case JOY_AUX_2: // select
if(rIsHeld)
ret.button = KEY_Cr;
else if(lIsHeld)
ret.button = KEY_Cp;
else
ret.button = KEY_ESC;
break;
case JOY_1:
i = 1;
ret.button = KEY_C2;
break;
case JOY_2:
i = 3;
ret.button = KEY_C4;
break;
case JOY_3:
i = 0;
ret.button = KEY_C1;
break;
case JOY_4:
i = 2;
ret.button = KEY_C3;
break;
case JOY_5: // Black
if(lIsHeld)
ret.button = KEY_F4;
else if(rIsHeld)
ret.button = KEY_DEL;
else
ret.button = KEY_F1;
break;
case JOY_6: // White
if(rIsHeld)
ret.button = KEY_INSERT;
else
ret.button = KEY_SPACE;
break;
case JOY_7: // L
if(type == IET_FIRST_PRESS)
lIsHeld = true;
else if(type == IET_RELEASE)
lIsHeld = false;
break;
case JOY_8: // R
if(type == IET_FIRST_PRESS)
rIsHeld = true;
else if(type == IET_RELEASE)
rIsHeld = false;
ret.button = KEY_LSHIFT;
break;
}
if(i != -1)
{
if(type == IET_FIRST_PRESS)
buttonHeld[i] = true;
else if(type == IET_RELEASE)
buttonHeld[i] = false;
}
return ret;
}
#endif
2004-11-26 17:28:47 +00:00
REGISTER_SCREEN_CLASS( ScreenEdit );
2003-09-27 22:30:51 +00:00
ScreenEdit::ScreenEdit( CString sName ) : Screen( sName )
2002-05-20 08:59:37 +00:00
{
LOG->Trace( "ScreenEdit::ScreenEdit()" );
2002-05-20 08:59:37 +00:00
2003-12-18 08:53:38 +00:00
/* We do this ourself. */
SOUND->HandleSongTimer( false );
2002-08-17 06:44:04 +00:00
// set both players to joined so the credit message doesn't show
FOREACH_PlayerNumber( p )
2002-08-20 21:00:56 +00:00
GAMESTATE->m_bSideIsJoined[p] = true;
2002-08-17 06:44:04 +00:00
SCREENMAN->RefreshCreditsMessages();
2002-07-23 01:41:40 +00:00
m_pSong = GAMESTATE->m_pCurSong;
2004-05-24 06:12:17 +00:00
m_pSteps = GAMESTATE->m_pCurSteps[PLAYER_1];
2004-01-26 20:56:58 +00:00
m_pAttacksFromCourse = NULL;
2002-05-20 08:59:37 +00:00
2002-07-03 03:13:13 +00:00
NoteData noteData;
2004-10-23 17:43:49 +00:00
m_pSteps->GetNoteData( noteData );
2002-07-03 03:13:13 +00:00
2002-07-28 20:28:37 +00:00
m_EditMode = MODE_EDITING;
2004-02-01 02:05:09 +00:00
GAMESTATE->m_bPastHereWeGo = false;
2002-07-28 20:28:37 +00:00
GAMESTATE->m_bEditing = true;
2002-05-20 08:59:37 +00:00
GAMESTATE->m_fSongBeat = 0;
m_fTrailingBeat = GAMESTATE->m_fSongBeat;
2002-08-01 13:42:56 +00:00
GAMESTATE->m_pPlayerState[PLAYER_1]->m_PlayerOptions.m_fScrollSpeed = 1;
2003-02-19 06:27:20 +00:00
GAMESTATE->m_SongOptions.m_fMusicRate = 1;
2003-08-09 19:00:52 +00:00
/* Not all games have a noteskin named "note" ... */
if( NOTESKIN->DoesNoteSkinExist("note") )
GAMESTATE->m_pPlayerState[PLAYER_1]->m_PlayerOptions.m_sNoteSkin = "note"; // change noteskin before loading all of the edit Actors
GAMESTATE->ResetNoteSkins();
GAMESTATE->StoreSelectedOptions();
2002-05-20 08:59:37 +00:00
shiftAnchor = -1;
2003-09-21 23:16:44 +00:00
m_SnapDisplay.SetXY( EDIT_X, PLAYER_Y_STANDARD );
2002-08-17 06:44:04 +00:00
m_SnapDisplay.Load( PLAYER_1 );
m_SnapDisplay.SetZoom( 0.5f );
2002-05-20 08:59:37 +00:00
2003-09-21 23:16:44 +00:00
m_NoteFieldEdit.SetXY( EDIT_X, PLAYER_Y );
2002-05-20 08:59:37 +00:00
m_NoteFieldEdit.SetZoom( 0.5f );
m_NoteFieldEdit.Load( &noteData, GAMESTATE->m_pPlayerState[PLAYER_1], -240, 800, PLAYER_HEIGHT*2 );
2002-05-20 08:59:37 +00:00
2004-09-21 08:41:17 +00:00
m_rectRecordBack.StretchTo( RectF(SCREEN_LEFT, SCREEN_TOP, SCREEN_RIGHT, SCREEN_BOTTOM) );
m_rectRecordBack.SetDiffuse( RageColor(0,0,0,0) );
2002-05-20 08:59:37 +00:00
2003-10-02 04:10:56 +00:00
m_NoteFieldRecord.SetXY( EDIT_X, PLAYER_Y );
2002-05-20 08:59:37 +00:00
m_NoteFieldRecord.SetZoom( 1.0f );
m_NoteFieldRecord.Load( &noteData, GAMESTATE->m_pPlayerState[PLAYER_1], -150, 350, 350 );
2002-07-02 00:27:58 +00:00
2003-02-01 05:16:38 +00:00
m_Clipboard.SetNumTracks( m_NoteFieldEdit.GetNumTracks() );
2002-05-20 08:59:37 +00:00
2003-02-19 06:27:20 +00:00
GAMESTATE->m_pPlayerState[PLAYER_1]->m_PlayerOptions.Init(); // don't allow weird options in editor. It doesn't handle reverse well.
// Set NoteSkin to note if available.
// Change noteskin back to default before loading player.
if( NOTESKIN->DoesNoteSkinExist("note") )
GAMESTATE->m_pPlayerState[PLAYER_1]->m_PlayerOptions.m_sNoteSkin = "note";
GAMESTATE->ResetNoteSkins();
2003-02-19 06:27:20 +00:00
2004-01-24 20:36:09 +00:00
/* XXX: Do we actually have to send real note data here, and to m_NoteFieldRecord?
* (We load again on play/record.) */
m_Player.Load(
GAMESTATE->m_pPlayerState[PLAYER_1],
noteData,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL );
GAMESTATE->m_pPlayerState[PLAYER_1]->m_PlayerController = PC_HUMAN;
2004-12-01 04:02:00 +00:00
m_Player.SetXY( PLAYER_X, PLAYER_Y );
2002-05-20 08:59:37 +00:00
m_In.Load( THEME->GetPathToB("ScreenEdit in") );
m_In.StartTransitioning();
m_Out.Load( THEME->GetPathToB("ScreenEdit out") );
2002-05-20 08:59:37 +00:00
m_sprHelp.Load( THEME->GetPathToG("ScreenEdit help") );
2003-02-18 23:15:38 +00:00
m_sprHelp.SetHorizAlign( Actor::align_left );
m_sprHelp.SetXY( HELP_X, HELP_Y );
2002-05-20 08:59:37 +00:00
m_textHelp.LoadFromFont( THEME->GetPathToF("Common normal") );
2003-02-18 23:15:38 +00:00
m_textHelp.SetXY( HELP_TEXT_X, HELP_TEXT_Y );
2002-06-29 11:59:09 +00:00
m_textHelp.SetHorizAlign( Actor::align_left );
2003-02-18 23:15:38 +00:00
m_textHelp.SetVertAlign( Actor::align_top );
2002-06-29 11:59:09 +00:00
m_textHelp.SetZoom( 0.5f );
m_textHelp.SetText( HELP_TEXT );
m_textHelp.SetShadowLength( 0 );
2002-05-20 08:59:37 +00:00
m_sprInfo.Load( THEME->GetPathToG("ScreenEdit Info") );
2003-02-18 23:15:38 +00:00
m_sprInfo.SetHorizAlign( Actor::align_right );
m_sprInfo.SetXY( INFO_X, INFO_Y );
2002-08-17 06:44:04 +00:00
m_textInfo.LoadFromFont( THEME->GetPathToF("Common normal") );
2003-02-18 23:15:38 +00:00
m_textInfo.SetXY( INFO_TEXT_X, INFO_TEXT_Y );
m_textInfo.SetHorizAlign( Actor::align_left );
m_textInfo.SetVertAlign( Actor::align_top );
m_textInfo.SetZoom( 0.5f );
m_textInfo.SetShadowLength( 0 );
2003-02-18 23:15:38 +00:00
//m_textInfo.SetText(); // set this below every frame
2002-06-29 11:59:09 +00:00
m_soundChangeLine.Load( THEME->GetPathToS("ScreenEdit line") );
m_soundChangeSnap.Load( THEME->GetPathToS("ScreenEdit snap") );
m_soundMarker.Load( THEME->GetPathToS("ScreenEdit marker") );
2002-05-20 08:59:37 +00:00
2002-06-29 11:59:09 +00:00
m_soundMusic.Load(m_pSong->GetMusicPath());
2002-05-20 08:59:37 +00:00
m_soundAssistTick.Load( THEME->GetPathToS("ScreenEdit assist tick") );
this->HandleScreenMessage( SM_DoUpdateTextInfo );
2002-05-20 08:59:37 +00:00
}
ScreenEdit::~ScreenEdit()
{
LOG->Trace( "ScreenEdit::~ScreenEdit()" );
m_soundMusic.StopPlaying();
2002-05-20 08:59:37 +00:00
}
// play assist ticks
2004-01-12 09:36:01 +00:00
void ScreenEdit::PlayTicks()
{
2004-01-12 09:36:01 +00:00
if( !GAMESTATE->m_SongOptions.m_bAssistTick || m_EditMode != MODE_PLAYING )
return;
/* Sound cards have a latency between when a sample is Play()ed and when the sound
* will start coming out the speaker. Compensate for this by boosting fPositionSeconds
* ahead. This is just to make sure that we request the sound early enough for it to
* come out on time; the actual precise timing is handled by SetStartTime. */
float fPositionSeconds = GAMESTATE->m_fMusicSeconds;
2004-01-12 09:36:01 +00:00
fPositionSeconds += SOUND->GetPlayLatency() + (float)TICK_EARLY_SECONDS + 0.250f;
const float fSongBeat = GAMESTATE->m_pCurSong->GetBeatFromElapsedTime( fPositionSeconds );
2004-01-12 09:36:01 +00:00
const int iSongRow = max( 0, BeatToNoteRowNotRounded( fSongBeat ) );
2004-04-04 04:12:26 +00:00
static int iRowLastCrossed = -1;
if( iSongRow < iRowLastCrossed )
2004-06-06 05:28:58 +00:00
iRowLastCrossed = iSongRow;
2004-01-12 09:36:01 +00:00
int iTickRow = -1;
2004-12-03 23:50:20 +00:00
// for each index we crossed since the last update:
FOREACH_NONEMPTY_ROW_ALL_TRACKS_RANGE( m_Player.m_NoteData, r, iRowLastCrossed+1, iSongRow )
2004-10-23 17:43:49 +00:00
if( m_Player.m_NoteData.IsThereATapOrHoldHeadAtRow( r ) )
2004-01-12 09:36:01 +00:00
iTickRow = r;
2004-01-12 09:36:01 +00:00
iRowLastCrossed = iSongRow;
2004-01-12 09:36:01 +00:00
if( iTickRow != -1 )
{
const float fTickBeat = NoteRowToBeat( iTickRow );
const float fTickSecond = GAMESTATE->m_pCurSong->m_Timing.GetElapsedTimeFromBeat( fTickBeat );
float fSecondsUntil = fTickSecond - GAMESTATE->m_fMusicSeconds;
fSecondsUntil /= m_soundMusic.GetPlaybackRate(); /* 2x music rate means the time until the tick is halved */
RageSoundParams p;
2004-04-04 04:11:43 +00:00
p.StartTime = GAMESTATE->m_LastBeatUpdate + (fSecondsUntil - (float)TICK_EARLY_SECONDS);
m_soundAssistTick.Play( &p );
2004-01-12 09:36:01 +00:00
}
}
2002-05-20 08:59:37 +00:00
2003-03-05 02:38:17 +00:00
void ScreenEdit::PlayPreviewMusic()
{
2003-07-26 22:53:22 +00:00
SOUND->PlayMusic("");
2004-04-04 05:39:10 +00:00
SOUND->PlayMusic( m_pSong->GetMusicPath(), false,
2003-03-05 02:38:17 +00:00
m_pSong->m_fMusicSampleStartSeconds,
m_pSong->m_fMusicSampleLengthSeconds,
1.5f );
}
2002-05-20 08:59:37 +00:00
void ScreenEdit::Update( float fDeltaTime )
{
2004-01-18 06:57:59 +00:00
if( m_soundMusic.IsPlaying() )
{
RageTimer tm;
const float fSeconds = m_soundMusic.GetPositionSeconds( NULL, &tm );
GAMESTATE->UpdateSongPosition( fSeconds, GAMESTATE->m_pCurSong->m_Timing, tm );
}
2002-10-18 19:01:32 +00:00
if( m_EditMode == MODE_RECORDING )
{
// add or extend holds
2004-06-28 07:26:00 +00:00
for( int t=0; t<GAMESTATE->GetCurrentStyle()->m_iColsPerPlayer; t++ ) // for each track
2002-10-18 19:01:32 +00:00
{
StyleInput StyleI( PLAYER_1, t );
float fSecsHeld = INPUTMAPPER->GetSecsHeld( StyleI );
if( fSecsHeld > RECORD_HOLD_SECONDS && GAMESTATE->m_fSongBeat > 0 )
2002-10-18 19:01:32 +00:00
{
// add or extend hold
const float fHoldStartSeconds = m_soundMusic.GetPositionSeconds() - fSecsHeld;
float fStartBeat = max( 0, m_pSong->GetBeatFromElapsedTime( fHoldStartSeconds ) );
float fEndBeat = max( fStartBeat, GAMESTATE->m_fSongBeat );
2002-10-18 19:01:32 +00:00
// Round hold start and end to the nearest snap interval
2004-10-24 17:44:51 +00:00
fStartBeat = Quantize( fStartBeat, NoteTypeToBeat(m_SnapDisplay.GetNoteType()) );
fEndBeat = Quantize( fEndBeat, NoteTypeToBeat(m_SnapDisplay.GetNoteType()) );
2002-10-18 19:01:32 +00:00
// create a new hold note
2003-12-16 04:00:39 +00:00
HoldNote newHN( t, BeatToNoteRow(fStartBeat), BeatToNoteRow(fEndBeat) );
2002-10-18 19:01:32 +00:00
m_NoteFieldRecord.AddHoldNote( newHN );
}
}
}
2002-07-28 20:28:37 +00:00
if( m_EditMode == MODE_RECORDING || m_EditMode == MODE_PLAYING )
2002-05-20 08:59:37 +00:00
{
if( PREFSMAN->m_bEditorShowBGChangesPlay )
{
m_Background.Update( fDeltaTime );
m_Foreground.Update( fDeltaTime );
}
// check for end of playback/record
2002-05-20 08:59:37 +00:00
2002-08-17 06:44:04 +00:00
if( GAMESTATE->m_fSongBeat > m_NoteFieldEdit.m_fEndMarker + 4 ) // give a one measure lead out
2002-05-20 08:59:37 +00:00
{
2002-07-28 20:28:37 +00:00
if( m_EditMode == MODE_RECORDING )
2002-05-20 08:59:37 +00:00
{
2002-08-18 23:20:18 +00:00
TransitionFromRecordToEdit();
2002-05-20 08:59:37 +00:00
}
2002-07-28 20:28:37 +00:00
else if( m_EditMode == MODE_PLAYING )
2002-05-20 08:59:37 +00:00
{
2002-10-18 00:45:09 +00:00
TransitionToEdit();
2002-05-20 08:59:37 +00:00
}
2002-10-18 00:30:00 +00:00
GAMESTATE->m_fSongBeat = m_NoteFieldEdit.m_fEndMarker;
2002-05-20 08:59:37 +00:00
}
}
m_SnapDisplay.Update( fDeltaTime );
2002-07-28 20:28:37 +00:00
m_NoteFieldEdit.Update( fDeltaTime );
m_In.Update( fDeltaTime );
m_Out.Update( fDeltaTime );
2003-02-18 23:15:38 +00:00
m_sprHelp.Update( fDeltaTime );
2002-06-29 11:59:09 +00:00
m_textHelp.Update( fDeltaTime );
2003-02-18 23:15:38 +00:00
m_sprInfo.Update( fDeltaTime );
2002-05-20 08:59:37 +00:00
m_textInfo.Update( fDeltaTime );
2002-08-17 06:44:04 +00:00
m_rectRecordBack.Update( fDeltaTime );
2002-05-20 08:59:37 +00:00
2002-07-28 20:28:37 +00:00
if( m_EditMode == MODE_RECORDING )
m_NoteFieldRecord.Update( fDeltaTime );
2002-05-20 08:59:37 +00:00
2002-07-28 20:28:37 +00:00
if( m_EditMode == MODE_PLAYING )
2002-05-20 08:59:37 +00:00
{
2002-07-28 20:28:37 +00:00
m_Player.Update( fDeltaTime );
2002-05-20 08:59:37 +00:00
}
//LOG->Trace( "ScreenEdit::Update(%f)", fDeltaTime );
2002-05-20 08:59:37 +00:00
Screen::Update( fDeltaTime );
2002-06-29 11:59:09 +00:00
// Update trailing beat
float fDelta = GAMESTATE->m_fSongBeat - m_fTrailingBeat;
2002-05-20 08:59:37 +00:00
2002-06-29 11:59:09 +00:00
if( fabsf(fDelta) < 0.01 )
{
m_fTrailingBeat = GAMESTATE->m_fSongBeat; // snap
2002-06-29 11:59:09 +00:00
}
else
{
float fSign = fDelta / fabsf(fDelta);
float fMoveDelta = fSign*fDeltaTime*40 / GAMESTATE->m_pPlayerState[PLAYER_1]->m_CurrentPlayerOptions.m_fScrollSpeed;
2002-06-29 11:59:09 +00:00
if( fabsf(fMoveDelta) > fabsf(fDelta) )
fMoveDelta = fDelta;
m_fTrailingBeat += fMoveDelta;
2002-06-29 11:59:09 +00:00
if( fabsf(fDelta) > 10 )
{
/* We're far off; move faster. Be sure to not overshoot. */
fMoveDelta = fDelta * fDeltaTime*5;
float fNewDelta = GAMESTATE->m_fSongBeat - m_fTrailingBeat;
if( fabsf(fMoveDelta) > fabsf(fNewDelta) )
fMoveDelta = fNewDelta;
m_fTrailingBeat += fMoveDelta;
}
2002-05-20 08:59:37 +00:00
}
2002-07-28 20:28:37 +00:00
m_NoteFieldEdit.Update( fDeltaTime );
2002-05-20 08:59:37 +00:00
2004-01-12 09:36:01 +00:00
PlayTicks();
}
void ScreenEdit::UpdateTextInfo()
{
2004-05-24 04:26:54 +00:00
int iNumTapNotes = m_NoteFieldEdit.GetNumTapNotes();
int iNumHoldNotes = m_NoteFieldEdit.GetNumHoldNotes();
2002-05-20 08:59:37 +00:00
CString sNoteType;
2002-10-18 19:01:32 +00:00
switch( m_SnapDisplay.GetNoteType() )
2002-05-20 08:59:37 +00:00
{
2002-10-18 19:01:32 +00:00
case NOTE_TYPE_4TH: sNoteType = "4th notes"; break;
case NOTE_TYPE_8TH: sNoteType = "8th notes"; break;
case NOTE_TYPE_12TH: sNoteType = "12th notes"; break;
case NOTE_TYPE_16TH: sNoteType = "16th notes"; break;
case NOTE_TYPE_24TH: sNoteType = "24th notes"; break;
case NOTE_TYPE_32ND: sNoteType = "32nd notes"; break;
2003-11-03 08:44:49 +00:00
case NOTE_TYPE_48TH: sNoteType = "48th notes"; break;
case NOTE_TYPE_64TH: sNoteType = "64th notes"; break;
default: ASSERT(0);
2002-05-20 08:59:37 +00:00
}
CString sText;
2003-11-04 18:32:35 +00:00
// check Editor.ini for a few of these
// entries used: CurBeatPlaces, CurSecPlaces, OffsetPlaces,
// PreviewStartPlaces, PreviewLengthPlaces
2003-11-04 18:32:35 +00:00
/* No need for that (unneeded options is just a maintenance pain). If you want
* more precision here, add it. I doubt there's a need for precise preview output,
* though (it'd be nearly inaudible at the millisecond level, and it's approximate
* anyway). */
sText += ssprintf( "Current Beat:\n %.2f\n", GAMESTATE->m_fSongBeat );
sText += ssprintf( "Current Second:\n %.2f\n", m_pSong->GetElapsedTimeFromBeat(GAMESTATE->m_fSongBeat) );
2003-04-25 00:01:35 +00:00
sText += ssprintf( "Snap to:\n %s\n", sNoteType.c_str() );
sText += ssprintf( "Selection begin:\n %s\n", m_NoteFieldEdit.m_fBeginMarker==-1 ? "not set" : ssprintf("%.2f",m_NoteFieldEdit.m_fBeginMarker).c_str() );
sText += ssprintf( "Selection end:\n %s\n", m_NoteFieldEdit.m_fEndMarker==-1 ? "not set" : ssprintf("%.2f",m_NoteFieldEdit.m_fEndMarker).c_str() );
2004-05-24 03:41:39 +00:00
sText += ssprintf( "Difficulty:\n %s\n", DifficultyToString( m_pSteps->GetDifficulty() ).c_str() );
2004-05-24 06:12:17 +00:00
sText += ssprintf( "Description:\n %s\n", GAMESTATE->m_pCurSteps[PLAYER_1] ? GAMESTATE->m_pCurSteps[PLAYER_1]->GetDescription().c_str() : "no description" );
2003-04-25 00:01:35 +00:00
sText += ssprintf( "Main title:\n %s\n", m_pSong->m_sMainTitle.c_str() );
2003-10-03 03:32:08 +00:00
sText += ssprintf( "Sub title:\n %s\n", m_pSong->m_sSubTitle.c_str() );
2004-05-24 04:26:54 +00:00
sText += ssprintf( "Tap Steps:\n %d\n", iNumTapNotes );
2003-08-03 00:13:55 +00:00
sText += ssprintf( "Hold Steps:\n %d\n", iNumHoldNotes );
2003-12-18 04:48:26 +00:00
sText += ssprintf( "Beat 0 Offset:\n %.3f secs\n", m_pSong->m_Timing.m_fBeat0OffsetInSeconds );
sText += ssprintf( "Preview Start:\n %.2f secs\n", m_pSong->m_fMusicSampleStartSeconds );
sText += ssprintf( "Preview Length:\n %.2f secs\n",m_pSong->m_fMusicSampleLengthSeconds );
m_textInfo.SetText( sText );
2002-05-20 08:59:37 +00:00
}
void ScreenEdit::DrawPrimitives()
{
// m_rectRecordBack.Draw();
switch( m_EditMode )
2002-05-20 08:59:37 +00:00
{
case MODE_EDITING:
{
2003-08-24 17:03:33 +00:00
m_sprHelp.Draw();
m_textHelp.Draw();
m_sprInfo.Draw();
m_textInfo.Draw();
m_SnapDisplay.Draw();
// HACK: Make NoteFieldEdit draw using the trailing beat
float fSongBeat = GAMESTATE->m_fSongBeat; // save song beat
GAMESTATE->m_fSongBeat = m_fTrailingBeat; // put trailing beat in effect
m_NoteFieldEdit.Draw();
GAMESTATE->m_fSongBeat = fSongBeat; // restore real song beat
m_In.Draw();
m_Out.Draw();
}
break;
case MODE_RECORDING:
if( PREFSMAN->m_bEditorShowBGChangesPlay )
m_Background.Draw();
2002-05-20 08:59:37 +00:00
m_NoteFieldRecord.Draw();
if( PREFSMAN->m_bEditorShowBGChangesPlay )
m_Foreground.Draw();
break;
case MODE_PLAYING:
if( PREFSMAN->m_bEditorShowBGChangesPlay )
m_Background.Draw();
2002-05-20 08:59:37 +00:00
m_Player.Draw();
if( PREFSMAN->m_bEditorShowBGChangesPlay )
m_Foreground.Draw();
break;
default:
ASSERT(0);
2002-05-20 08:59:37 +00:00
}
Screen::DrawPrimitives();
}
void ScreenEdit::Input( const DeviceInput& DeviceI, const InputEventType type, const GameInput &GameI, const MenuInput &MenuI, const StyleInput &StyleI )
{
2003-02-25 00:33:42 +00:00
// LOG->Trace( "ScreenEdit::Input()" );
2002-05-20 08:59:37 +00:00
if( m_In.IsTransitioning() || m_Out.IsTransitioning() )
return;
2004-11-01 06:30:35 +00:00
const DeviceInput& di =
2004-10-28 07:56:13 +00:00
#if defined(XBOX)
2004-11-01 06:30:35 +00:00
TranslateInput(DeviceI, type);
2004-10-28 07:56:13 +00:00
#else
2004-11-01 06:30:35 +00:00
DeviceI;
2004-10-28 07:56:13 +00:00
#endif
2002-07-28 20:28:37 +00:00
switch( m_EditMode )
2002-05-20 08:59:37 +00:00
{
2004-10-28 07:56:13 +00:00
case MODE_EDITING: InputEdit( di, type, GameI, MenuI, StyleI ); break;
case MODE_RECORDING: InputRecord( di, type, GameI, MenuI, StyleI ); break;
case MODE_PLAYING: InputPlay( di, type, GameI, MenuI, StyleI ); break;
2002-08-17 06:44:04 +00:00
default: ASSERT(0);
2002-05-20 08:59:37 +00:00
}
2004-05-03 01:39:25 +00:00
/* Make sure the displayed time is up-to-date after possibly changing something,
* so it doesn't feel lagged. */
UpdateTextInfo();
2002-05-20 08:59:37 +00:00
}
2003-09-07 22:28:46 +00:00
2002-05-20 08:59:37 +00:00
void ScreenEdit::InputEdit( const DeviceInput& DeviceI, const InputEventType type, const GameInput &GameI, const MenuInput &MenuI, const StyleInput &StyleI )
{
2002-08-17 06:44:04 +00:00
if( DeviceI.device != DEVICE_KEYBOARD )
return;
2002-05-20 08:59:37 +00:00
2004-09-09 22:21:50 +00:00
if( type == IET_LEVEL_CHANGED )
return; // don't care
if(type == IET_RELEASE)
{
switch( DeviceI.button ) {
2004-09-09 17:48:25 +00:00
case KEY_LSHIFT:
case KEY_RSHIFT:
shiftAnchor = -1;
break;
}
return;
}
2002-08-17 06:44:04 +00:00
switch( DeviceI.button )
2002-05-20 08:59:37 +00:00
{
2004-09-09 17:48:25 +00:00
case KEY_C1:
case KEY_C2:
case KEY_C3:
case KEY_C4:
case KEY_C5:
case KEY_C6:
case KEY_C7:
case KEY_C8:
case KEY_C9:
case KEY_C0:
2002-05-20 08:59:37 +00:00
{
2002-08-17 06:44:04 +00:00
if( type != IET_FIRST_PRESS )
break; // We only care about first presses
2002-05-20 08:59:37 +00:00
2004-09-09 17:48:25 +00:00
/* Why was this changed back to just "DeviceI.button - KEY_1"? That causes
2003-10-10 22:22:10 +00:00
* crashes when 0 is pressed (0 - 1 = -1). -glenn */
2004-09-09 17:48:25 +00:00
// int iCol = DeviceI.button - KEY_1;
int iCol = DeviceI.button == KEY_C0? 9: DeviceI.button - KEY_C1;
2003-08-31 23:52:02 +00:00
// Alt + number = input to right half
2004-10-28 07:56:13 +00:00
#if !defined(XBOX)
2004-09-09 17:48:25 +00:00
if( INPUTFILTER->IsBeingPressed(DeviceInput(DEVICE_KEYBOARD, KEY_LALT)) ||
INPUTFILTER->IsBeingPressed(DeviceInput(DEVICE_KEYBOARD, KEY_RALT)))
2004-10-28 07:56:13 +00:00
#else
if(lIsHeld)
#endif
2003-08-31 23:52:02 +00:00
iCol += m_NoteFieldEdit.GetNumTracks()/2;
2003-04-26 06:06:24 +00:00
2002-08-17 06:44:04 +00:00
const float fSongBeat = GAMESTATE->m_fSongBeat;
const int iSongIndex = BeatToNoteRow( fSongBeat );
2002-05-20 08:59:37 +00:00
2004-06-28 07:26:00 +00:00
if( iCol >= m_NoteFieldEdit.GetNumTracks() ) // this button is not in the range of columns for this Style
2002-08-17 06:44:04 +00:00
break;
2002-05-20 08:59:37 +00:00
2002-08-17 06:44:04 +00:00
// check for to see if the user intended to remove a HoldNote
2004-09-21 07:53:39 +00:00
for( int i=0; i<m_NoteFieldEdit.GetNumHoldNotes(); i++ ) // for each HoldNote
2002-08-17 06:44:04 +00:00
{
2002-11-02 22:46:15 +00:00
const HoldNote &hn = m_NoteFieldEdit.GetHoldNote(i);
if( iCol == hn.iTrack && // the notes correspond
2003-12-16 04:00:39 +00:00
hn.RowIsInRange(iSongIndex) ) // the cursor lies within this HoldNote
2002-06-29 11:59:09 +00:00
{
2002-08-17 06:44:04 +00:00
m_NoteFieldEdit.RemoveHoldNote( i );
2003-11-15 08:51:47 +00:00
return;
2002-06-29 11:59:09 +00:00
}
2002-05-20 08:59:37 +00:00
}
2002-06-29 11:59:09 +00:00
if( m_NoteFieldEdit.GetTapNote(iCol, iSongIndex).type != TapNote::empty )
2003-11-15 08:51:47 +00:00
{
m_NoteFieldEdit.SetTapNote( iCol, iSongIndex, TAP_EMPTY );
return;
}
// Hold LShift to lay mine, hold RShift to lay an attack
2004-10-28 07:56:13 +00:00
#if !defined(XBOX)
2004-09-09 17:48:25 +00:00
if( INPUTFILTER->IsBeingPressed(DeviceInput(DEVICE_KEYBOARD, KEY_LSHIFT)) )
2004-10-28 07:56:13 +00:00
#else
if(rIsHeld)
#endif
2003-11-15 08:51:47 +00:00
{
m_NoteFieldEdit.SetTapNote(iCol, iSongIndex, TAP_ORIGINAL_MINE );
2003-11-15 08:51:47 +00:00
}
2004-09-09 17:48:25 +00:00
else if( INPUTFILTER->IsBeingPressed(DeviceInput(DEVICE_KEYBOARD, KEY_RSHIFT)) )
2003-11-15 08:51:47 +00:00
{
g_iLastInsertAttackTrack = iCol;
SCREENMAN->MiniMenu( &g_InsertAttack, SM_BackFromInsertAttack );
}
else
{
m_NoteFieldEdit.SetTapNote(iCol, iSongIndex, TAP_ORIGINAL_TAP );
2003-11-15 08:51:47 +00:00
}
2002-08-17 06:44:04 +00:00
}
break;
2004-09-09 17:48:25 +00:00
case KEY_UP:
case KEY_DOWN:
case KEY_PGUP:
case KEY_PGDN:
2002-08-17 06:44:04 +00:00
{
2004-10-28 07:56:13 +00:00
#if !defined(XBOX)
2004-09-09 17:48:25 +00:00
if( INPUTFILTER->IsBeingPressed(DeviceInput(DEVICE_KEYBOARD,KEY_LCTRL)) ||
INPUTFILTER->IsBeingPressed(DeviceInput(DEVICE_KEYBOARD,KEY_RCTRL)) )
2004-10-28 07:56:13 +00:00
#else
if(lIsHeld)
#endif
2003-02-18 23:15:38 +00:00
{
float& fScrollSpeed = GAMESTATE->m_pPlayerState[PLAYER_1]->m_PlayerOptions.m_fScrollSpeed;
2004-03-07 03:49:28 +00:00
float fNewScrollSpeed = fScrollSpeed;
2004-09-09 17:48:25 +00:00
if( DeviceI.button == KEY_UP )
2003-02-18 23:15:38 +00:00
{
if( fScrollSpeed == 4 )
2004-03-07 03:49:28 +00:00
fNewScrollSpeed = 2;
else if( fScrollSpeed == 2 )
2004-03-07 03:49:28 +00:00
fNewScrollSpeed = 1;
2003-02-18 23:15:38 +00:00
}
2004-09-09 17:48:25 +00:00
else if( DeviceI.button == KEY_DOWN )
2003-02-18 23:15:38 +00:00
{
if( fScrollSpeed == 2 )
2004-03-07 03:49:28 +00:00
fNewScrollSpeed = 4;
else if( fScrollSpeed == 1 )
2004-03-07 03:49:28 +00:00
fNewScrollSpeed = 2;
2003-02-18 23:15:38 +00:00
}
2004-03-07 03:49:28 +00:00
if( fNewScrollSpeed != fScrollSpeed )
{
fScrollSpeed = fNewScrollSpeed;
m_soundMarker.Play();
GAMESTATE->StoreSelectedOptions();
}
break;
2003-02-18 23:15:38 +00:00
}
2002-09-07 10:33:44 +00:00
float fBeatsToMove=0.f;
2002-08-17 06:44:04 +00:00
switch( DeviceI.button )
2002-05-20 08:59:37 +00:00
{
2004-09-09 17:48:25 +00:00
case KEY_UP:
case KEY_DOWN:
2002-10-18 19:01:32 +00:00
fBeatsToMove = NoteTypeToBeat( m_SnapDisplay.GetNoteType() );
2004-09-09 17:48:25 +00:00
if( DeviceI.button == KEY_UP )
2002-08-17 06:44:04 +00:00
fBeatsToMove *= -1;
break;
2004-09-09 17:48:25 +00:00
case KEY_PGUP:
case KEY_PGDN:
2002-08-17 06:44:04 +00:00
fBeatsToMove = BEATS_PER_MEASURE;
2004-09-09 17:48:25 +00:00
if( DeviceI.button == KEY_PGUP )
2002-08-17 06:44:04 +00:00
fBeatsToMove *= -1;
}
const float fStartBeat = GAMESTATE->m_fSongBeat;
const float fEndBeat = GAMESTATE->m_fSongBeat + fBeatsToMove;
2002-05-20 08:59:37 +00:00
2002-08-17 06:44:04 +00:00
// check to see if they're holding a button
2003-08-31 23:52:02 +00:00
for( int n=0; n<=9; n++ ) // for each number key
2002-08-17 06:44:04 +00:00
{
2003-08-31 23:52:02 +00:00
int iCol = n;
// Ctrl + number = input to right half
2004-10-28 07:56:13 +00:00
#if !defined(XBOX)
2004-09-09 17:48:25 +00:00
if( INPUTFILTER->IsBeingPressed(DeviceInput(DEVICE_KEYBOARD, KEY_LALT)) ||
INPUTFILTER->IsBeingPressed(DeviceInput(DEVICE_KEYBOARD, KEY_RALT)))
2004-10-28 07:56:13 +00:00
#else
if(lIsHeld)
#endif
2003-08-31 23:52:02 +00:00
iCol += m_NoteFieldEdit.GetNumTracks()/2;
if( iCol >= m_NoteFieldEdit.GetNumTracks() )
continue; // skip
2004-10-28 07:56:13 +00:00
#if !defined(XBOX)
2004-09-09 17:48:25 +00:00
const DeviceInput di(DEVICE_KEYBOARD, KEY_C1+n);
2003-08-31 23:52:02 +00:00
2002-09-08 06:11:59 +00:00
if( !INPUTFILTER->IsBeingPressed(di) )
2004-10-28 07:56:13 +00:00
#else
if(n > 3)
continue;
if(!buttonHeld[n])
#endif
continue;
// create a new hold note
2003-12-16 04:00:39 +00:00
HoldNote newHN( iCol, BeatToNoteRow(min(fStartBeat, fEndBeat)), BeatToNoteRow(max(fStartBeat, fEndBeat)) );
2003-12-16 04:00:39 +00:00
newHN.iStartRow = max(newHN.iStartRow, 0);
newHN.iEndRow = max(newHN.iEndRow, 0);
m_NoteFieldEdit.AddHoldNote( newHN );
}
2004-10-28 07:56:13 +00:00
#if !defined(XBOX)
2004-09-09 17:48:25 +00:00
if( INPUTFILTER->IsBeingPressed(DeviceInput(DEVICE_KEYBOARD, KEY_LSHIFT)) ||
INPUTFILTER->IsBeingPressed(DeviceInput(DEVICE_KEYBOARD, KEY_RSHIFT)))
2004-10-28 07:56:13 +00:00
#else
if(rIsHeld)
#endif
{
/* Shift is being held.
*
* If this is the first time we've moved since shift was depressed,
* the old position (before this move) becomes the start pos: */
if(shiftAnchor == -1)
shiftAnchor = fStartBeat;
if(fEndBeat == shiftAnchor)
{
/* We're back at the anchor, so we have nothing selected. */
m_NoteFieldEdit.m_fBeginMarker = m_NoteFieldEdit.m_fEndMarker = -1;
}
else
2002-05-20 08:59:37 +00:00
{
m_NoteFieldEdit.m_fBeginMarker = shiftAnchor;
m_NoteFieldEdit.m_fEndMarker = fEndBeat;
if(m_NoteFieldEdit.m_fBeginMarker > m_NoteFieldEdit.m_fEndMarker)
swap(m_NoteFieldEdit.m_fBeginMarker, m_NoteFieldEdit.m_fEndMarker);
2002-05-20 08:59:37 +00:00
}
}
2002-08-17 06:44:04 +00:00
GAMESTATE->m_fSongBeat += fBeatsToMove;
2003-03-06 22:50:44 +00:00
GAMESTATE->m_fSongBeat = max( GAMESTATE->m_fSongBeat, 0 );
2004-10-24 17:44:51 +00:00
GAMESTATE->m_fSongBeat = Quantize( GAMESTATE->m_fSongBeat, NoteTypeToBeat(m_SnapDisplay.GetNoteType()) );
2002-06-29 11:59:09 +00:00
m_soundChangeLine.Play();
2002-08-17 06:44:04 +00:00
}
break;
2004-09-09 17:48:25 +00:00
case KEY_HOME:
2002-08-17 06:44:04 +00:00
GAMESTATE->m_fSongBeat = 0;
m_soundChangeLine.Play();
break;
2004-09-09 17:48:25 +00:00
case KEY_END:
2002-08-17 06:44:04 +00:00
GAMESTATE->m_fSongBeat = m_NoteFieldEdit.GetLastBeat();
m_soundChangeLine.Play();
break;
2004-09-09 17:48:25 +00:00
case KEY_LEFT:
2004-08-13 02:41:19 +00:00
if( m_SnapDisplay.PrevSnapMode() )
OnSnapModeChange();
2002-08-17 06:44:04 +00:00
break;
2004-09-09 17:48:25 +00:00
case KEY_RIGHT:
2004-08-13 02:41:19 +00:00
if( m_SnapDisplay.NextSnapMode() )
OnSnapModeChange();
2002-08-17 06:44:04 +00:00
break;
2004-09-09 17:48:25 +00:00
case KEY_SPACE:
2003-02-18 23:15:38 +00:00
if( m_NoteFieldEdit.m_fBeginMarker==-1 && m_NoteFieldEdit.m_fEndMarker==-1 )
2002-08-17 06:44:04 +00:00
{
2003-02-18 23:15:38 +00:00
// lay begin marker
m_NoteFieldEdit.m_fBeginMarker = GAMESTATE->m_fSongBeat;
2002-08-17 06:44:04 +00:00
}
2003-02-18 23:15:38 +00:00
else if( m_NoteFieldEdit.m_fEndMarker==-1 ) // only begin marker is laid
2002-08-17 06:44:04 +00:00
{
2003-02-18 23:15:38 +00:00
if( GAMESTATE->m_fSongBeat == m_NoteFieldEdit.m_fBeginMarker )
2002-05-20 08:59:37 +00:00
{
2003-02-18 23:15:38 +00:00
m_NoteFieldEdit.m_fBeginMarker = -1;
2002-05-20 08:59:37 +00:00
}
else
{
2003-02-18 23:15:38 +00:00
m_NoteFieldEdit.m_fEndMarker = max( m_NoteFieldEdit.m_fBeginMarker, GAMESTATE->m_fSongBeat );
m_NoteFieldEdit.m_fBeginMarker = min( m_NoteFieldEdit.m_fBeginMarker, GAMESTATE->m_fSongBeat );
2002-05-20 08:59:37 +00:00
}
2002-08-17 06:44:04 +00:00
}
2003-02-18 23:15:38 +00:00
else // both markers are laid
2002-08-17 06:44:04 +00:00
{
m_NoteFieldEdit.m_fBeginMarker = GAMESTATE->m_fSongBeat;
m_NoteFieldEdit.m_fEndMarker = -1;
2002-08-17 06:44:04 +00:00
}
2003-02-18 23:15:38 +00:00
m_soundMarker.Play();
2002-08-17 06:44:04 +00:00
break;
2004-09-09 17:48:25 +00:00
case KEY_ENTER:
case KEY_KP_ENTER:
2002-08-17 06:44:04 +00:00
{
2003-02-18 23:15:38 +00:00
// update enabled/disabled in g_AreaMenu
bool bAreaSelected = m_NoteFieldEdit.m_fBeginMarker!=-1 && m_NoteFieldEdit.m_fEndMarker!=-1;
g_AreaMenu.rows[cut].enabled = bAreaSelected;
g_AreaMenu.rows[copy].enabled = bAreaSelected;
g_AreaMenu.rows[paste_at_current_beat].enabled = this->m_Clipboard.GetLastBeat() != 0;
g_AreaMenu.rows[paste_at_begin_marker].enabled = this->m_Clipboard.GetLastBeat() != 0 && m_NoteFieldEdit.m_fBeginMarker!=-1;
g_AreaMenu.rows[clear].enabled = bAreaSelected;
g_AreaMenu.rows[quantize].enabled = bAreaSelected;
g_AreaMenu.rows[turn].enabled = bAreaSelected;
g_AreaMenu.rows[transform].enabled = bAreaSelected;
g_AreaMenu.rows[alter].enabled = bAreaSelected;
2003-09-07 22:28:46 +00:00
g_AreaMenu.rows[tempo].enabled = bAreaSelected;
g_AreaMenu.rows[play].enabled = bAreaSelected;
g_AreaMenu.rows[record].enabled = bAreaSelected;
2003-11-03 10:44:19 +00:00
g_AreaMenu.rows[convert_beat_to_pause].enabled = bAreaSelected;
2003-02-18 23:15:38 +00:00
SCREENMAN->MiniMenu( &g_AreaMenu, SM_BackFromAreaMenu );
2002-08-17 06:44:04 +00:00
}
break;
2004-09-09 17:48:25 +00:00
case KEY_ESC:
2003-02-18 23:15:38 +00:00
SCREENMAN->MiniMenu( &g_MainMenu, SM_BackFromMainMenu );
2002-08-17 06:44:04 +00:00
break;
2002-06-29 11:59:09 +00:00
2004-09-09 17:48:25 +00:00
case KEY_F1:
2003-02-19 05:46:09 +00:00
SCREENMAN->MiniMenu( &g_KeyboardShortcuts, SM_None );
break;
2004-09-09 17:48:25 +00:00
case KEY_F4:
2003-04-23 01:23:14 +00:00
GAMESTATE->m_SongOptions.m_bAssistTick ^= 1;
break;
2004-09-09 17:48:25 +00:00
case KEY_F5:
case KEY_F6:
2003-08-24 05:12:08 +00:00
{
// save current steps
2004-05-24 06:12:17 +00:00
Steps* pSteps = GAMESTATE->m_pCurSteps[PLAYER_1];
2004-05-24 03:41:39 +00:00
ASSERT( pSteps );
2004-10-23 17:43:49 +00:00
pSteps->SetNoteData( m_NoteFieldEdit );
2003-08-24 05:12:08 +00:00
// Get all Steps of this StepsType
2004-05-24 03:41:39 +00:00
StepsType st = pSteps->m_StepsType;
2003-08-24 05:12:08 +00:00
vector<Steps*> vSteps;
GAMESTATE->m_pCurSong->GetSteps( vSteps, st );
2004-01-24 20:36:09 +00:00
// Sort them by difficulty.
StepsUtil::SortStepsByTypeAndDifficulty( vSteps );
2004-01-24 20:36:09 +00:00
2003-08-24 05:12:08 +00:00
// Find out what index the current Steps are
2004-05-24 03:41:39 +00:00
vector<Steps*>::iterator it = find( vSteps.begin(), vSteps.end(), pSteps );
2003-08-24 05:12:08 +00:00
ASSERT( it != vSteps.end() );
switch( DeviceI.button )
{
2004-09-09 17:48:25 +00:00
case KEY_F5:
2003-08-24 05:12:08 +00:00
if( it==vSteps.begin() )
{
SCREENMAN->PlayInvalidSound();
2003-08-24 05:12:08 +00:00
return;
}
it--;
break;
2004-09-09 17:48:25 +00:00
case KEY_F6:
2003-08-24 05:12:08 +00:00
it++;
if( it==vSteps.end() )
{
SCREENMAN->PlayInvalidSound();
2003-08-24 05:12:08 +00:00
return;
}
break;
default: ASSERT(0); return;
}
2004-05-24 03:41:39 +00:00
pSteps = *it;
2004-05-24 06:12:17 +00:00
GAMESTATE->m_pCurSteps[PLAYER_1] = m_pSteps = pSteps;
2004-10-23 17:43:49 +00:00
pSteps->GetNoteData( m_NoteFieldEdit );
2003-08-24 05:12:08 +00:00
SCREENMAN->SystemMessage( ssprintf(
"Switched to %s %s '%s'",
2004-07-12 02:19:24 +00:00
GAMEMAN->StepsTypeToString( pSteps->m_StepsType ).c_str(),
2004-05-24 03:41:39 +00:00
DifficultyToString( pSteps->GetDifficulty() ).c_str(),
pSteps->GetDescription().c_str() ) );
2003-08-24 05:12:08 +00:00
SOUND->PlayOnce( THEME->GetPathToS("ScreenEdit switch") );
}
break;
2004-09-09 17:48:25 +00:00
case KEY_F7:
case KEY_F8:
2002-08-17 06:44:04 +00:00
{
2003-11-03 08:44:49 +00:00
// MD 11/02/03 - start referring to Editor.ini entries
// entries here: BPMDelta, BPMDeltaFine
2002-08-17 06:44:04 +00:00
float fBPM = m_pSong->GetBPMAtBeat( GAMESTATE->m_fSongBeat );
float fDeltaBPM;
switch( DeviceI.button )
2002-05-20 08:59:37 +00:00
{
2004-09-09 17:48:25 +00:00
case KEY_F7: fDeltaBPM = - 0.020f; break;
case KEY_F8: fDeltaBPM = + 0.020f; break;
2002-09-07 10:31:35 +00:00
default: ASSERT(0); return;
2002-06-29 11:59:09 +00:00
}
2004-09-09 17:48:25 +00:00
if( INPUTFILTER->IsBeingPressed( DeviceInput(DEVICE_KEYBOARD, KEY_RALT)) ||
INPUTFILTER->IsBeingPressed( DeviceInput(DEVICE_KEYBOARD, KEY_LALT)) )
2003-06-17 06:24:13 +00:00
fDeltaBPM /= 2; /* .010 */
else switch( type )
2002-05-20 08:59:37 +00:00
{
2002-08-17 06:44:04 +00:00
case IET_SLOW_REPEAT: fDeltaBPM *= 10; break;
case IET_FAST_REPEAT: fDeltaBPM *= 40; break;
2002-05-20 08:59:37 +00:00
}
2003-09-07 22:28:46 +00:00
2002-08-17 06:44:04 +00:00
float fNewBPM = fBPM + fDeltaBPM;
2003-09-07 22:28:46 +00:00
m_pSong->SetBPMAtBeat( GAMESTATE->m_fSongBeat, fNewBPM );
2002-08-17 06:44:04 +00:00
}
break;
2004-09-09 17:48:25 +00:00
case KEY_F9:
case KEY_F10:
2002-08-17 06:44:04 +00:00
{
2003-11-03 08:44:49 +00:00
// MD 11/02/03 - start referring to Editor.ini entries
// entries here: StopDelta, StopDeltaFine
float fStopDelta;
2002-08-17 06:44:04 +00:00
switch( DeviceI.button )
2002-06-29 11:59:09 +00:00
{
2004-09-09 17:48:25 +00:00
case KEY_F9: fStopDelta = -0.02f; break;
case KEY_F10: fStopDelta = +0.02f; break;
2002-09-07 10:31:35 +00:00
default: ASSERT(0); return;
2002-06-29 11:59:09 +00:00
}
2003-11-03 08:44:49 +00:00
// MD 11/02/03 - requested: fine adjust for stops as well
2004-09-09 17:48:25 +00:00
if( INPUTFILTER->IsBeingPressed( DeviceInput(DEVICE_KEYBOARD, KEY_RALT)) ||
INPUTFILTER->IsBeingPressed( DeviceInput(DEVICE_KEYBOARD, KEY_LALT)) )
2003-11-03 08:44:49 +00:00
fStopDelta /= 4; /* .005 */
else switch( type )
2002-06-29 11:59:09 +00:00
{
case IET_SLOW_REPEAT: fStopDelta *= 10; break;
case IET_FAST_REPEAT: fStopDelta *= 40; break;
2002-05-20 08:59:37 +00:00
}
2002-06-29 11:59:09 +00:00
unsigned i;
2003-12-18 04:48:26 +00:00
for( i=0; i<m_pSong->m_Timing.m_StopSegments.size(); i++ )
2002-05-20 08:59:37 +00:00
{
2003-12-18 04:48:26 +00:00
if( m_pSong->m_Timing.m_StopSegments[i].m_fStartBeat == GAMESTATE->m_fSongBeat )
2002-08-17 06:44:04 +00:00
break;
2002-05-20 08:59:37 +00:00
}
2003-12-18 04:48:26 +00:00
if( i == m_pSong->m_Timing.m_StopSegments.size() ) // there is no BPMSegment at the current beat
2002-06-29 11:59:09 +00:00
{
2002-08-17 06:44:04 +00:00
// create a new StopSegment
if( fStopDelta > 0 )
m_pSong->AddStopSegment( StopSegment(GAMESTATE->m_fSongBeat, fStopDelta) );
2002-06-29 11:59:09 +00:00
}
2003-12-18 04:48:26 +00:00
else // StopSegment being modified is m_Timing.m_StopSegments[i]
2002-06-29 11:59:09 +00:00
{
2003-12-18 04:48:26 +00:00
m_pSong->m_Timing.m_StopSegments[i].m_fStopSeconds += fStopDelta;
if( m_pSong->m_Timing.m_StopSegments[i].m_fStopSeconds <= 0 )
m_pSong->m_Timing.m_StopSegments.erase( m_pSong->m_Timing.m_StopSegments.begin()+i,
m_pSong->m_Timing.m_StopSegments.begin()+i+1);
2002-06-29 11:59:09 +00:00
}
2002-08-17 06:44:04 +00:00
}
break;
2004-09-09 17:48:25 +00:00
case KEY_F11:
case KEY_F12:
2002-08-17 06:44:04 +00:00
{
2003-11-03 08:44:49 +00:00
// MD 11/02/03 - start referring to Editor.ini entries
// entries here: OffsetDelta, OffsetDeltaFine
2002-08-17 06:44:04 +00:00
float fOffsetDelta;
switch( DeviceI.button )
2002-07-02 00:27:58 +00:00
{
2004-09-09 17:48:25 +00:00
case KEY_F11: fOffsetDelta = -0.02f; break;
case KEY_F12: fOffsetDelta = +0.02f; break;
2002-09-07 10:31:35 +00:00
default: ASSERT(0); return;
2002-07-02 00:27:58 +00:00
}
2004-09-09 17:48:25 +00:00
if( INPUTFILTER->IsBeingPressed( DeviceInput(DEVICE_KEYBOARD, KEY_RALT)) ||
INPUTFILTER->IsBeingPressed( DeviceInput(DEVICE_KEYBOARD, KEY_LALT)) )
fOffsetDelta /= 20; /* 1ms */
else switch( type )
2002-07-02 00:27:58 +00:00
{
2002-08-17 06:44:04 +00:00
case IET_SLOW_REPEAT: fOffsetDelta *= 10; break;
case IET_FAST_REPEAT: fOffsetDelta *= 40; break;
}
2002-06-29 11:59:09 +00:00
2003-12-18 04:48:26 +00:00
m_pSong->m_Timing.m_fBeat0OffsetInSeconds += fOffsetDelta;
2002-08-17 06:44:04 +00:00
}
break;
2004-09-09 17:48:25 +00:00
case KEY_LBRACKET:
case KEY_RBRACKET:
2002-08-17 06:44:04 +00:00
{
2003-11-03 08:44:49 +00:00
// MD 11/02/03 - start referring to Editor.ini entries
// entries here: SampleLengthDelta, SampleLengthDeltaFine
// SampleStartDelta, SampleStartDeltaFine
2002-08-17 06:44:04 +00:00
float fDelta;
switch( DeviceI.button )
{
2004-09-09 17:48:25 +00:00
case KEY_LBRACKET: fDelta = -0.02f; break;
case KEY_RBRACKET: fDelta = +0.02f; break;
2002-09-07 10:31:35 +00:00
default: ASSERT(0); return;
2002-07-02 00:27:58 +00:00
}
2002-08-17 06:44:04 +00:00
switch( type )
{
case IET_SLOW_REPEAT: fDelta *= 10; break;
case IET_FAST_REPEAT: fDelta *= 40; break;
}
2004-09-09 17:48:25 +00:00
if( INPUTFILTER->IsBeingPressed(DeviceInput(DEVICE_KEYBOARD, KEY_LSHIFT)) ||
INPUTFILTER->IsBeingPressed(DeviceInput(DEVICE_KEYBOARD, KEY_RSHIFT)))
{
m_pSong->m_fMusicSampleLengthSeconds += fDelta;
m_pSong->m_fMusicSampleLengthSeconds = max(m_pSong->m_fMusicSampleLengthSeconds,0);
} else {
m_pSong->m_fMusicSampleStartSeconds += fDelta;
m_pSong->m_fMusicSampleStartSeconds = max(m_pSong->m_fMusicSampleStartSeconds,0);
}
2002-07-02 00:27:58 +00:00
}
2002-08-17 06:44:04 +00:00
break;
2004-09-09 17:48:25 +00:00
case KEY_Cm:
2003-03-05 02:38:17 +00:00
PlayPreviewMusic();
break;
2004-09-09 17:48:25 +00:00
case KEY_Cb:
HandleMainMenuChoice( edit_bg_change, NULL );
break;
2004-09-09 17:48:25 +00:00
case KEY_Cc:
2004-01-26 20:56:58 +00:00
{
g_CourseMode.rows[0].choices.clear();
g_CourseMode.rows[0].choices.push_back( "OFF" );
g_CourseMode.rows[0].defaultChoice = 0;
vector<Course*> courses;
SONGMAN->GetAllCourses( courses, false );
for( unsigned i = 0; i < courses.size(); ++i )
{
const Course *crs = courses[i];
bool bUsesThisSong = false;
for( unsigned e = 0; e < crs->m_entries.size(); ++e )
{
if( crs->m_entries[e].type != COURSE_ENTRY_FIXED )
continue;
if( crs->m_entries[e].pSong != m_pSong )
continue;
bUsesThisSong = true;
}
if( bUsesThisSong )
{
2004-07-11 10:02:38 +00:00
g_CourseMode.rows[0].choices.push_back( crs->GetFullDisplayTitle() );
2004-01-26 20:56:58 +00:00
if( crs == m_pAttacksFromCourse )
g_CourseMode.rows[0].defaultChoice = g_CourseMode.rows[0].choices.size()-1;
}
}
SCREENMAN->MiniMenu( &g_CourseMode, SM_BackFromCourseModeMenu );
break;
}
2004-09-09 17:48:25 +00:00
case KEY_Cp:
{
2004-10-28 07:56:13 +00:00
#if !defined(XBOX)
2004-09-09 17:48:25 +00:00
if( INPUTFILTER->IsBeingPressed(DeviceInput(DEVICE_KEYBOARD,KEY_LCTRL)) ||
INPUTFILTER->IsBeingPressed(DeviceInput(DEVICE_KEYBOARD,KEY_RCTRL)) )
HandleMainMenuChoice( play_whole_song, NULL );
2004-09-09 17:48:25 +00:00
else if( INPUTFILTER->IsBeingPressed(DeviceInput(DEVICE_KEYBOARD,KEY_LSHIFT)) ||
INPUTFILTER->IsBeingPressed(DeviceInput(DEVICE_KEYBOARD,KEY_RSHIFT)) )
HandleMainMenuChoice( play_current_beat_to_end, NULL );
else
if( m_NoteFieldEdit.m_fBeginMarker!=-1 && m_NoteFieldEdit.m_fEndMarker!=-1 )
HandleAreaMenuChoice( play, NULL );
2004-10-28 07:56:13 +00:00
#else
if(rIsHeld)
HandleMainMenuChoice( play_whole_song, NULL );
else
HandleAreaMenuChoice( play, NULL );
#endif
}
break;
2004-09-09 17:48:25 +00:00
case KEY_Cr:
2003-04-21 03:09:48 +00:00
{
2004-10-28 07:56:13 +00:00
#if !defined(XBOX)
2004-09-09 17:48:25 +00:00
if( INPUTFILTER->IsBeingPressed(DeviceInput(DEVICE_KEYBOARD,KEY_LCTRL)) ||
INPUTFILTER->IsBeingPressed(DeviceInput(DEVICE_KEYBOARD,KEY_RCTRL)) )
2004-10-28 07:56:13 +00:00
#endif
2003-04-21 03:09:48 +00:00
if( m_NoteFieldEdit.m_fBeginMarker!=-1 && m_NoteFieldEdit.m_fEndMarker!=-1 )
HandleAreaMenuChoice( record, NULL );
}
break;
2004-09-09 17:48:25 +00:00
case KEY_INSERT:
2004-10-28 07:56:13 +00:00
#if !defined(XBOX)
if( INPUTFILTER->IsBeingPressed(DeviceInput(DEVICE_KEYBOARD,KEY_LCTRL)) ||
2004-09-09 17:48:25 +00:00
INPUTFILTER->IsBeingPressed(DeviceInput(DEVICE_KEYBOARD,KEY_RCTRL)) )
HandleAreaMenuChoice( shift_pauses_forward, NULL );
else
2004-10-28 07:56:13 +00:00
#endif
HandleAreaMenuChoice( insert_and_shift, NULL );
2004-08-14 06:40:17 +00:00
SCREENMAN->PlayInvalidSound();
break;
2004-09-09 17:48:25 +00:00
case KEY_DEL:
2004-10-28 07:56:13 +00:00
#if !defined(XBOX)
2004-09-09 17:48:25 +00:00
if( INPUTFILTER->IsBeingPressed(DeviceInput(DEVICE_KEYBOARD,KEY_LCTRL)) ||
INPUTFILTER->IsBeingPressed(DeviceInput(DEVICE_KEYBOARD,KEY_RCTRL)) )
HandleAreaMenuChoice( shift_pauses_backward, NULL );
else
2004-10-28 07:56:13 +00:00
#endif
HandleAreaMenuChoice( delete_and_shift, NULL );
2004-08-14 06:40:17 +00:00
SCREENMAN->PlayInvalidSound();
break;
2002-05-20 08:59:37 +00:00
}
}
void ScreenEdit::InputRecord( const DeviceInput& DeviceI, const InputEventType type, const GameInput &GameI, const MenuInput &MenuI, const StyleInput &StyleI )
{
2004-09-09 17:48:25 +00:00
if( DeviceI.device == DEVICE_KEYBOARD && DeviceI.button == KEY_ESC )
2002-05-20 08:59:37 +00:00
{
2002-10-18 19:01:32 +00:00
TransitionFromRecordToEdit();
return;
}
2002-05-20 08:59:37 +00:00
2002-10-18 19:01:32 +00:00
if( StyleI.player != PLAYER_1 )
return; // ignore
2002-05-20 08:59:37 +00:00
2002-10-18 19:01:32 +00:00
const int iCol = StyleI.col;
2002-05-20 08:59:37 +00:00
2002-10-18 19:01:32 +00:00
switch( type )
{
case IET_FIRST_PRESS:
{
// Add a tap
2002-05-20 08:59:37 +00:00
2002-10-18 19:01:32 +00:00
float fBeat = GAMESTATE->m_fSongBeat;
2004-10-24 17:44:51 +00:00
fBeat = Quantize( fBeat, NoteTypeToBeat(m_SnapDisplay.GetNoteType()) );
2002-10-18 19:01:32 +00:00
const int iRow = BeatToNoteRow( fBeat );
if( iRow < 0 )
break;
m_NoteFieldRecord.SetTapNote(iCol, iRow, TAP_ORIGINAL_TAP);
2004-07-02 20:08:17 +00:00
m_NoteFieldRecord.Step( iCol, TNS_MARVELOUS );
2002-10-18 19:01:32 +00:00
}
break;
case IET_SLOW_REPEAT:
case IET_FAST_REPEAT:
case IET_RELEASE:
// don't add or extend holds here
break;
2002-05-20 08:59:37 +00:00
}
}
void ScreenEdit::InputPlay( const DeviceInput& DeviceI, const InputEventType type, const GameInput &GameI, const MenuInput &MenuI, const StyleInput &StyleI )
{
if( type != IET_FIRST_PRESS )
return;
if( DeviceI.device == DEVICE_KEYBOARD )
{
switch( DeviceI.button )
{
2004-09-09 17:48:25 +00:00
case KEY_ESC:
2002-10-18 00:45:09 +00:00
TransitionToEdit();
2002-05-20 08:59:37 +00:00
break;
2004-09-09 17:48:25 +00:00
case KEY_F4:
2003-04-23 01:23:14 +00:00
GAMESTATE->m_SongOptions.m_bAssistTick ^= 1;
break;
2004-09-09 17:48:25 +00:00
case KEY_F8:
{
PREFSMAN->m_bAutoPlay = !PREFSMAN->m_bAutoPlay;
FOREACH_HumanPlayer( p )
GAMESTATE->m_pPlayerState[p]->m_PlayerController = PREFSMAN->m_bAutoPlay?PC_AUTOPLAY:PC_HUMAN;
}
break;
2004-09-09 17:48:25 +00:00
case KEY_F11:
case KEY_F12:
2002-09-11 04:49:07 +00:00
{
float fOffsetDelta;
switch( DeviceI.button )
{
2004-09-09 17:48:25 +00:00
case KEY_F11: fOffsetDelta = -0.020f; break;
case KEY_F12: fOffsetDelta = +0.020f; break;
2002-09-11 04:49:07 +00:00
default: ASSERT(0); return;
}
2004-09-09 17:48:25 +00:00
if( INPUTFILTER->IsBeingPressed( DeviceInput(DEVICE_KEYBOARD, KEY_RALT)) ||
INPUTFILTER->IsBeingPressed( DeviceInput(DEVICE_KEYBOARD, KEY_LALT)) )
fOffsetDelta /= 20; /* 1ms */
else switch( type )
2002-09-11 04:49:07 +00:00
{
case IET_SLOW_REPEAT: fOffsetDelta *= 10; break;
case IET_FAST_REPEAT: fOffsetDelta *= 40; break;
}
2003-12-18 04:48:26 +00:00
m_pSong->m_Timing.m_fBeat0OffsetInSeconds += fOffsetDelta;
2002-09-11 04:49:07 +00:00
}
break;
2002-05-20 08:59:37 +00:00
}
}
switch( StyleI.player )
{
2003-07-13 00:34:30 +00:00
case PLAYER_1:
if( !PREFSMAN->m_bAutoPlay )
m_Player.Step( StyleI.col, DeviceI.ts );
break;
2002-05-20 08:59:37 +00:00
}
}
2002-10-18 00:45:09 +00:00
/* Switch to editing. */
void ScreenEdit::TransitionToEdit()
2002-05-20 08:59:37 +00:00
{
/* Important: people will stop playing, change the BG and start again; make sure we reload */
m_Background.Unload();
m_Foreground.Unload();
2002-07-28 20:28:37 +00:00
m_EditMode = MODE_EDITING;
2004-02-01 02:05:09 +00:00
GAMESTATE->m_bPastHereWeGo = false;
m_soundMusic.StopPlaying();
2004-01-12 09:36:01 +00:00
m_soundAssistTick.StopPlaying(); /* Stop any queued assist ticks. */
2002-10-18 00:45:09 +00:00
m_rectRecordBack.StopTweening();
m_rectRecordBack.BeginTweening( 0.5f );
2003-04-12 06:16:12 +00:00
m_rectRecordBack.SetDiffuse( RageColor(0,0,0,0) );
2002-10-18 00:53:22 +00:00
/* Make sure we're snapped. */
2004-10-24 17:44:51 +00:00
GAMESTATE->m_fSongBeat = Quantize( GAMESTATE->m_fSongBeat, NoteTypeToBeat(m_SnapDisplay.GetNoteType()) );
/* Playing and recording have lead-ins, which may start before beat 0;
* make sure we don't stay there if we escaped out early. */
GAMESTATE->m_fSongBeat = max( GAMESTATE->m_fSongBeat, 0 );
2004-01-26 20:56:58 +00:00
/* Stop displaying course attacks, if any. */
GAMESTATE->RemoveAllActiveAttacks();
GAMESTATE->RebuildPlayerOptionsFromActiveAttacks( PLAYER_1 );
GAMESTATE->m_pPlayerState[PLAYER_1]->m_CurrentPlayerOptions = GAMESTATE->m_pPlayerState[PLAYER_1]->m_PlayerOptions;
2002-10-18 00:45:09 +00:00
}
void ScreenEdit::TransitionFromRecordToEdit()
{
TransitionToEdit();
2002-05-20 08:59:37 +00:00
2004-10-24 00:17:15 +00:00
int rowBegin = BeatToNoteRow( m_NoteFieldEdit.m_fBeginMarker );
int rowEnd = BeatToNoteRow( m_NoteFieldEdit.m_fEndMarker );
2002-05-20 08:59:37 +00:00
2004-05-24 04:17:19 +00:00
// delete old TapNotes in the range
2004-10-24 00:17:15 +00:00
m_NoteFieldEdit.ClearRange( rowBegin, rowEnd );
2002-05-20 08:59:37 +00:00
2004-10-24 00:17:15 +00:00
m_NoteFieldEdit.CopyRange( m_NoteFieldRecord, rowBegin, rowEnd, rowBegin );
2002-05-20 08:59:37 +00:00
}
2004-01-24 20:36:09 +00:00
/* Helper for SM_DoReloadFromDisk */
static bool g_DoReload;
void ReloadFromDisk( void *p )
{
g_DoReload = true;
}
2002-05-20 08:59:37 +00:00
void ScreenEdit::HandleScreenMessage( const ScreenMessage SM )
{
switch( SM )
{
case SM_GoToNextScreen:
// Reload song from disk to discard changes.
2004-08-11 08:23:14 +00:00
SONGMAN->RevertFromDisk( GAMESTATE->m_pCurSong, true );
2004-08-12 04:49:15 +00:00
2004-05-24 03:41:39 +00:00
/* We might do something with m_pSteps (eg. UpdateTextInfo) before we end up
* in ScreenEditMenu, and m_pSteps might be invalid due to RevertFromDisk. */
2004-05-24 06:12:17 +00:00
m_pSteps = GAMESTATE->m_pCurSteps[PLAYER_1];
2004-08-12 04:49:15 +00:00
SCREENMAN->SetNewScreen( "ScreenEditMenu" );
2002-05-20 08:59:37 +00:00
break;
2003-02-18 23:15:38 +00:00
case SM_BackFromMainMenu:
HandleMainMenuChoice( (MainMenuChoice)ScreenMiniMenu::s_iLastLine, ScreenMiniMenu::s_iLastAnswers );
break;
case SM_BackFromAreaMenu:
HandleAreaMenuChoice( (AreaMenuChoice)ScreenMiniMenu::s_iLastLine, ScreenMiniMenu::s_iLastAnswers );
break;
case SM_BackFromEditNotesStatistics:
HandleEditNotesStatisticsChoice( (EditNotesStatisticsChoice)ScreenMiniMenu::s_iLastLine, ScreenMiniMenu::s_iLastAnswers );
break;
case SM_BackFromEditSongInfo:
HandleEditSongInfoChoice( (EditSongInfoChoice)ScreenMiniMenu::s_iLastLine, ScreenMiniMenu::s_iLastAnswers );
break;
case SM_BackFromBGChange:
HandleBGChangeChoice( (BGChangeChoice)ScreenMiniMenu::s_iLastLine, ScreenMiniMenu::s_iLastAnswers );
break;
case SM_BackFromPrefs:
PREFSMAN->m_bEditorShowBGChangesPlay = !!ScreenMiniMenu::s_iLastAnswers[pref_show_bgs_play];
PREFSMAN->SaveGlobalPrefsToDisk();
break;
2004-01-26 20:56:58 +00:00
case SM_BackFromCourseModeMenu:
{
const int num = ScreenMiniMenu::s_iLastAnswers[0];
m_pAttacksFromCourse = NULL;
if( num != 0 )
{
const CString name = g_CourseMode.rows[0].choices[num];
m_pAttacksFromCourse = SONGMAN->FindCourse( name );
ASSERT( m_pAttacksFromCourse );
}
break;
}
2003-11-12 08:13:02 +00:00
case SM_BackFromPlayerOptions:
case SM_BackFromSongOptions:
2003-02-19 05:46:09 +00:00
// coming back from PlayerOptions or SongOptions
2004-01-26 22:20:42 +00:00
GAMESTATE->StoreSelectedOptions();
// stop any music that screen may have been playing
SOUND->StopMusic();
2003-02-19 05:46:09 +00:00
break;
2003-11-12 08:13:02 +00:00
case SM_BackFromInsertAttack:
2003-11-12 08:32:32 +00:00
{
int iDurationChoice = ScreenMiniMenu::s_iLastAnswers[0];
g_fLastInsertAttackDurationSeconds = strtof( g_InsertAttackItems[0].choices[iDurationChoice], NULL );
2003-11-12 08:32:32 +00:00
GAMESTATE->StoreSelectedOptions(); // save so that we don't lose the options chosen for edit and playback
SCREENMAN->AddNewScreenToTop( "ScreenPlayerOptions", SM_BackFromInsertAttackModifiers );
}
2003-11-12 08:13:02 +00:00
break;
case SM_BackFromInsertAttackModifiers:
{
PlayerOptions poChosen = GAMESTATE->m_pPlayerState[PLAYER_1]->m_PlayerOptions;
2003-11-12 08:13:02 +00:00
CString sMods = poChosen.GetString();
2004-10-23 23:41:49 +00:00
const int row = BeatToNoteRow( GAMESTATE->m_fSongBeat );
2003-11-15 23:19:13 +00:00
2004-10-23 23:41:49 +00:00
m_NoteFieldEdit.SetTapAttackNote( g_iLastInsertAttackTrack, row, sMods, g_fLastInsertAttackDurationSeconds );
2003-11-12 08:13:02 +00:00
GAMESTATE->RestoreSelectedOptions(); // restore the edit and playback options
}
break;
2004-01-24 20:36:09 +00:00
case SM_DoReloadFromDisk:
{
if( !g_DoReload )
return;
2004-05-24 03:41:39 +00:00
const StepsType st = m_pSteps->m_StepsType;
2004-04-18 08:06:14 +00:00
StepsID id;
2004-05-24 03:41:39 +00:00
id.FromSteps( m_pSteps );
2004-01-24 20:36:09 +00:00
2004-05-24 06:12:17 +00:00
GAMESTATE->m_pCurSteps[PLAYER_1] = NULL; /* make RevertFromDisk not try to reset it */
2004-08-11 08:23:14 +00:00
SONGMAN->RevertFromDisk( GAMESTATE->m_pCurSong );
2004-01-24 20:36:09 +00:00
CString sMessage = "Reloaded from disk.";
2004-04-18 08:06:14 +00:00
Steps *pSteps = id.ToSteps( GAMESTATE->m_pCurSong, false );
2004-01-24 20:36:09 +00:00
// Don't allow an autogen match. This can't be what they chose to
// edit originally because autogen steps are hidden.
if( pSteps && pSteps->IsAutogen() )
pSteps = NULL;
2004-01-24 20:36:09 +00:00
/* If we couldn't find the steps we were on before, warn and use the first available. */
if( pSteps == NULL )
{
pSteps = GAMESTATE->m_pCurSong->GetStepsByDifficulty( st, DIFFICULTY_INVALID, false );
if( pSteps )
2004-04-18 08:06:14 +00:00
sMessage = ssprintf( "old steps not found; changed to %s.",
2004-01-24 20:36:09 +00:00
DifficultyToString(pSteps->GetDifficulty()).c_str() );
}
/* If we still couldn't find any steps, then all steps of the current StepsType
* were removed. Don't create them; only do that in EditMenu. */
if( pSteps == NULL )
{
SCREENMAN->SetNewScreen( "ScreenEditMenu" );
return;
}
2004-01-24 20:36:09 +00:00
SCREENMAN->SystemMessage( sMessage );
2004-05-24 06:12:17 +00:00
m_pSteps = GAMESTATE->m_pCurSteps[PLAYER_1] = pSteps;
2004-10-23 17:43:49 +00:00
m_pSteps->GetNoteData( m_NoteFieldEdit );
2004-01-24 20:36:09 +00:00
break;
}
case SM_DoUpdateTextInfo:
this->PostScreenMessage( SM_DoUpdateTextInfo, 0.5f );
UpdateTextInfo();
break;
2003-12-22 20:27:47 +00:00
case SM_GainFocus:
/* We do this ourself. */
SOUND->HandleSongTimer( false );
/* When another screen comes up, RageSounds takes over the sound timer. When we come
* back, put the timer back to where it was. */
GAMESTATE->m_fSongBeat = m_fTrailingBeat;
break;
case SM_LoseFocus:
/* Snap the trailing beat, in case we lose focus while tweening. */
m_fTrailingBeat = GAMESTATE->m_fSongBeat;
2003-12-22 20:27:47 +00:00
break;
2002-05-20 08:59:37 +00:00
}
}
void ScreenEdit::OnSnapModeChange()
{
2002-06-29 11:59:09 +00:00
m_soundChangeSnap.Play();
2002-05-20 08:59:37 +00:00
2002-10-18 19:01:32 +00:00
NoteType nt = m_SnapDisplay.GetNoteType();
int iStepIndex = BeatToNoteRow( GAMESTATE->m_fSongBeat );
2002-05-20 08:59:37 +00:00
int iElementsPerNoteType = BeatToNoteRow( NoteTypeToBeat(nt) );
int iStepIndexHangover = iStepIndex % iElementsPerNoteType;
GAMESTATE->m_fSongBeat -= NoteRowToBeat( iStepIndexHangover );
2002-05-20 08:59:37 +00:00
}
2002-08-17 06:44:04 +00:00
2003-02-19 05:46:09 +00:00
// Helper function for below
// Begin helper functions for InputEdit
void ChangeDescription( CString sNew )
{
2004-05-24 06:12:17 +00:00
Steps* pSteps = GAMESTATE->m_pCurSteps[PLAYER_1];
2004-05-24 03:41:39 +00:00
pSteps->SetDescription(sNew);
2003-02-19 05:46:09 +00:00
}
void ChangeMainTitle( CString sNew )
{
Song* pSong = GAMESTATE->m_pCurSong;
pSong->m_sMainTitle = sNew;
}
void ChangeSubTitle( CString sNew )
{
Song* pSong = GAMESTATE->m_pCurSong;
pSong->m_sSubTitle = sNew;
}
void ChangeArtist( CString sNew )
{
Song* pSong = GAMESTATE->m_pCurSong;
pSong->m_sArtist = sNew;
}
2003-06-23 02:24:13 +00:00
void ChangeCredit( CString sNew )
{
Song* pSong = GAMESTATE->m_pCurSong;
pSong->m_sCredit = sNew;
}
2003-02-19 05:46:09 +00:00
void ChangeMainTitleTranslit( CString sNew )
{
Song* pSong = GAMESTATE->m_pCurSong;
pSong->m_sMainTitleTranslit = sNew;
}
void ChangeSubTitleTranslit( CString sNew )
{
Song* pSong = GAMESTATE->m_pCurSong;
pSong->m_sSubTitleTranslit = sNew;
}
void ChangeArtistTranslit( CString sNew )
{
Song* pSong = GAMESTATE->m_pCurSong;
pSong->m_sArtistTranslit = sNew;
}
// End helper functions
2003-02-19 05:46:09 +00:00
2003-02-18 23:15:38 +00:00
void ScreenEdit::HandleMainMenuChoice( MainMenuChoice c, int* iAnswers )
{
switch( c )
{
case edit_notes_statistics:
{
2004-05-24 03:41:39 +00:00
/* XXX: If the difficulty is changed from EDIT, and pSteps->WasLoadedFromProfile()
2004-02-25 23:43:50 +00:00
* is true, we should warn that the steps will no longer be saved to the profile. */
2004-05-24 06:12:17 +00:00
Steps* pSteps = GAMESTATE->m_pCurSteps[PLAYER_1];
2003-02-18 23:15:38 +00:00
float fMusicSeconds = m_soundMusic.GetLengthSeconds();
2004-05-24 03:41:39 +00:00
g_EditNotesStatistics.rows[difficulty].defaultChoice = pSteps->GetDifficulty();
2004-07-19 20:30:52 +00:00
g_EditNotesStatistics.rows[meter].defaultChoice = clamp( pSteps->GetMeter()-1, 0, 14 );
2004-05-24 03:41:39 +00:00
g_EditNotesStatistics.rows[predict_meter].choices.resize(1);g_EditNotesStatistics.rows[predict_meter].choices[0] = ssprintf("%f",pSteps->PredictMeter());
g_EditNotesStatistics.rows[description].choices.resize(1); g_EditNotesStatistics.rows[description].choices[0] = pSteps->GetDescription();
2004-05-24 04:26:54 +00:00
g_EditNotesStatistics.rows[tap_notes].choices.resize(1); g_EditNotesStatistics.rows[tap_notes].choices[0] = ssprintf("%d", m_NoteFieldEdit.GetNumTapNotes());
g_EditNotesStatistics.rows[hold_notes].choices.resize(1); g_EditNotesStatistics.rows[hold_notes].choices[0] = ssprintf("%d", m_NoteFieldEdit.GetNumHoldNotes());
g_EditNotesStatistics.rows[stream].choices.resize(1); g_EditNotesStatistics.rows[stream].choices[0] = ssprintf("%f", NoteDataUtil::GetStreamRadarValue(m_NoteFieldEdit,fMusicSeconds));
g_EditNotesStatistics.rows[voltage].choices.resize(1); g_EditNotesStatistics.rows[voltage].choices[0] = ssprintf("%f", NoteDataUtil::GetVoltageRadarValue(m_NoteFieldEdit,fMusicSeconds));
g_EditNotesStatistics.rows[air].choices.resize(1); g_EditNotesStatistics.rows[air].choices[0] = ssprintf("%f", NoteDataUtil::GetAirRadarValue(m_NoteFieldEdit,fMusicSeconds));
g_EditNotesStatistics.rows[freeze].choices.resize(1); g_EditNotesStatistics.rows[freeze].choices[0] = ssprintf("%f", NoteDataUtil::GetFreezeRadarValue(m_NoteFieldEdit,fMusicSeconds));
g_EditNotesStatistics.rows[chaos].choices.resize(1); g_EditNotesStatistics.rows[chaos].choices[0] = ssprintf("%f", NoteDataUtil::GetChaosRadarValue(m_NoteFieldEdit,fMusicSeconds));
2003-02-18 23:15:38 +00:00
SCREENMAN->MiniMenu( &g_EditNotesStatistics, SM_BackFromEditNotesStatistics );
}
break;
case play_whole_song:
2003-02-19 05:46:09 +00:00
{
m_NoteFieldEdit.m_fBeginMarker = 0;
m_NoteFieldEdit.m_fEndMarker = m_NoteFieldEdit.GetLastBeat();
HandleAreaMenuChoice( play, NULL );
}
2003-02-18 23:15:38 +00:00
break;
case play_current_beat_to_end:
{
m_NoteFieldEdit.m_fBeginMarker = GAMESTATE->m_fSongBeat;
m_NoteFieldEdit.m_fEndMarker = m_NoteFieldEdit.GetLastBeat();
HandleAreaMenuChoice( play, NULL );
}
break;
2003-02-18 23:15:38 +00:00
case save:
{
2003-08-03 00:13:55 +00:00
// copy edit into current Steps
2004-05-24 06:12:17 +00:00
Steps* pSteps = GAMESTATE->m_pCurSteps[PLAYER_1];
2004-05-24 03:41:39 +00:00
ASSERT( pSteps );
2003-02-18 23:15:38 +00:00
2004-10-23 17:43:49 +00:00
pSteps->SetNoteData( m_NoteFieldEdit );
2003-02-18 23:15:38 +00:00
GAMESTATE->m_pCurSong->Save();
// we shouldn't say we're saving a DWI if we're on any game besides
// dance, it just looks tacky and people may be wondering where the
// DWI file is :-)
2004-05-24 03:41:39 +00:00
if ((int)pSteps->m_StepsType <= (int)STEPS_TYPE_DANCE_SOLO)
SCREENMAN->SystemMessage( "Saved as SM and DWI." );
else
SCREENMAN->SystemMessage( "Saved as SM." );
2003-07-26 22:53:22 +00:00
SOUND->PlayOnce( THEME->GetPathToS("ScreenEdit save") );
2003-02-18 23:15:38 +00:00
}
break;
2004-01-24 20:36:09 +00:00
case reload:
g_DoReload = false;
SCREENMAN->Prompt( SM_DoReloadFromDisk,
"Do you want to reload from disk?\n\nThis will destroy all changes.",
true, false, ReloadFromDisk, NULL, NULL );
break;
2003-02-18 23:15:38 +00:00
case player_options:
2003-11-12 08:13:02 +00:00
SCREENMAN->AddNewScreenToTop( "ScreenPlayerOptions", SM_BackFromPlayerOptions );
2003-02-18 23:15:38 +00:00
break;
case song_options:
2003-11-12 08:13:02 +00:00
SCREENMAN->AddNewScreenToTop( "ScreenSongOptions", SM_BackFromSongOptions );
2003-02-18 23:15:38 +00:00
break;
case edit_song_info:
2003-02-19 05:46:09 +00:00
{
Song* pSong = GAMESTATE->m_pCurSong;
g_EditSongInfo.rows[main_title].choices.resize(1); g_EditSongInfo.rows[main_title].choices[0] = pSong->m_sMainTitle;
g_EditSongInfo.rows[sub_title].choices.resize(1); g_EditSongInfo.rows[sub_title].choices[0] = pSong->m_sSubTitle;
g_EditSongInfo.rows[artist].choices.resize(1); g_EditSongInfo.rows[artist].choices[0] = pSong->m_sArtist;
2003-06-23 02:24:13 +00:00
g_EditSongInfo.rows[credit].choices.resize(1); g_EditSongInfo.rows[credit].choices[0] = pSong->m_sCredit;
g_EditSongInfo.rows[main_title_transliteration].choices.resize(1); g_EditSongInfo.rows[main_title_transliteration].choices[0] = pSong->m_sMainTitleTranslit;
g_EditSongInfo.rows[sub_title_transliteration].choices.resize(1); g_EditSongInfo.rows[sub_title_transliteration].choices[0] = pSong->m_sSubTitleTranslit;
g_EditSongInfo.rows[artist_transliteration].choices.resize(1); g_EditSongInfo.rows[artist_transliteration].choices[0] = pSong->m_sArtistTranslit;
2003-02-19 05:46:09 +00:00
SCREENMAN->MiniMenu( &g_EditSongInfo, SM_BackFromEditSongInfo );
}
2003-02-18 23:15:38 +00:00
break;
2003-08-26 07:43:29 +00:00
// case edit_bpm:
// break;
// case edit_stop:
// break;
2003-02-18 23:15:38 +00:00
case edit_bg_change:
2003-02-19 05:46:09 +00:00
{
//
// Fill in option names
//
// m_pSong->GetSongDir() has trailing slash
g_BGChange.rows[add_song_bganimation].choices.clear();
GetDirListing( m_pSong->GetSongDir()+"*", g_BGChange.rows[add_song_bganimation].choices, true );
g_BGChange.rows[add_song_movie].choices.clear();
GetDirListing( m_pSong->GetSongDir()+"*.avi", g_BGChange.rows[add_song_movie].choices, false );
GetDirListing( m_pSong->GetSongDir()+"*.mpg", g_BGChange.rows[add_song_movie].choices, false );
GetDirListing( m_pSong->GetSongDir()+"*.mpeg", g_BGChange.rows[add_song_movie].choices, false );
2003-04-13 23:22:27 +00:00
g_BGChange.rows[add_song_still].choices.clear();
GetDirListing( m_pSong->GetSongDir()+"*.png", g_BGChange.rows[add_song_still].choices, false );
GetDirListing( m_pSong->GetSongDir()+"*.jpg", g_BGChange.rows[add_song_still].choices, false );
GetDirListing( m_pSong->GetSongDir()+"*.gif", g_BGChange.rows[add_song_still].choices, false );
GetDirListing( m_pSong->GetSongDir()+"*.bmp", g_BGChange.rows[add_song_still].choices, false );
g_BGChange.rows[add_global_random_movie].choices.clear();
GetDirListing( RANDOMMOVIES_DIR+"*.avi", g_BGChange.rows[add_global_random_movie].choices, false );
GetDirListing( RANDOMMOVIES_DIR+"*.mpg", g_BGChange.rows[add_global_random_movie].choices, false );
GetDirListing( RANDOMMOVIES_DIR+"*.mpeg", g_BGChange.rows[add_global_random_movie].choices, false );
g_BGChange.rows[add_global_bganimation].choices.clear();
GetDirListing( BG_ANIMS_DIR+"*", g_BGChange.rows[add_global_bganimation].choices, true );
g_BGChange.rows[add_global_visualization].choices.clear();
GetDirListing( VISUALIZATIONS_DIR+"*.avi", g_BGChange.rows[add_global_visualization].choices, false );
GetDirListing( VISUALIZATIONS_DIR+"*.mpg", g_BGChange.rows[add_global_visualization].choices, false );
GetDirListing( VISUALIZATIONS_DIR+"*.mpeg", g_BGChange.rows[add_global_visualization].choices, false );
//
// Fill in line enabled/disabled
//
bool bAlreadyBGChangeHere = false;
BackgroundChange bgChange;
FOREACH( BackgroundChange, m_pSong->m_BackgroundChanges, bgc )
{
if( bgc->m_fStartBeat == GAMESTATE->m_fSongBeat )
{
bAlreadyBGChangeHere = true;
bgChange = *bgc;
}
}
g_BGChange.rows[add_random].enabled = true;
g_BGChange.rows[add_song_bganimation].enabled = g_BGChange.rows[add_song_bganimation].choices.size() > 0;
g_BGChange.rows[add_song_movie].enabled = g_BGChange.rows[add_song_movie].choices.size() > 0;
2003-04-13 23:22:27 +00:00
g_BGChange.rows[add_song_still].enabled = g_BGChange.rows[add_song_still].choices.size() > 0;
g_BGChange.rows[add_global_random_movie].enabled = g_BGChange.rows[add_global_random_movie].choices.size() > 0;
g_BGChange.rows[add_global_bganimation].enabled = g_BGChange.rows[add_global_bganimation].choices.size() > 0;
g_BGChange.rows[add_global_visualization].enabled = g_BGChange.rows[add_global_visualization].choices.size() > 0;
g_BGChange.rows[delete_change].enabled = bAlreadyBGChangeHere;
2003-02-19 05:46:09 +00:00
// set default choices
g_BGChange.rows[rate]. SetDefaultChoiceIfPresent( ssprintf("%2.0f%%",bgChange.m_fRate*100) );
g_BGChange.rows[fade_last].defaultChoice = bgChange.m_bFadeLast ? 1 : 0;
g_BGChange.rows[rewind_movie].defaultChoice = bgChange.m_bRewindMovie ? 1 : 0;
g_BGChange.rows[loop].defaultChoice = bgChange.m_bLoop ? 1 : 0;
g_BGChange.rows[add_song_bganimation]. SetDefaultChoiceIfPresent( bgChange.m_sBGName );
g_BGChange.rows[add_song_movie]. SetDefaultChoiceIfPresent( bgChange.m_sBGName );
g_BGChange.rows[add_song_still]. SetDefaultChoiceIfPresent( bgChange.m_sBGName );
g_BGChange.rows[add_global_random_movie]. SetDefaultChoiceIfPresent( bgChange.m_sBGName );
g_BGChange.rows[add_global_bganimation]. SetDefaultChoiceIfPresent( bgChange.m_sBGName );
g_BGChange.rows[add_global_visualization]. SetDefaultChoiceIfPresent( bgChange.m_sBGName );
SCREENMAN->MiniMenu( &g_BGChange, SM_BackFromBGChange );
2003-02-19 05:46:09 +00:00
}
2003-02-18 23:15:38 +00:00
break;
case preferences:
g_Prefs.rows[pref_show_bgs_play].defaultChoice = PREFSMAN->m_bEditorShowBGChangesPlay;
SCREENMAN->MiniMenu( &g_Prefs, SM_BackFromPrefs );
break;
2003-02-18 23:15:38 +00:00
case play_preview_music:
2003-03-05 02:38:17 +00:00
PlayPreviewMusic();
2003-02-18 23:15:38 +00:00
break;
case exit:
m_Out.StartTransitioning( SM_GoToNextScreen );
2003-02-18 23:15:38 +00:00
break;
default:
ASSERT(0);
};
}
void ScreenEdit::HandleAreaMenuChoice( AreaMenuChoice c, int* iAnswers )
{
switch( c )
{
case cut:
{
2003-02-22 00:48:38 +00:00
HandleAreaMenuChoice( copy, NULL );
HandleAreaMenuChoice( clear, NULL );
2003-02-18 23:15:38 +00:00
}
break;
case copy:
{
ASSERT( m_NoteFieldEdit.m_fBeginMarker!=-1 && m_NoteFieldEdit.m_fEndMarker!=-1 );
int iFirstRow = BeatToNoteRow( m_NoteFieldEdit.m_fBeginMarker );
int iLastRow = BeatToNoteRow( m_NoteFieldEdit.m_fEndMarker );
m_Clipboard.ClearAll();
2004-10-23 17:43:49 +00:00
m_Clipboard.CopyRange( m_NoteFieldEdit, iFirstRow, iLastRow );
2003-02-18 23:15:38 +00:00
}
break;
2003-02-22 00:48:38 +00:00
case paste_at_current_beat:
2003-02-18 23:15:38 +00:00
{
int iSrcFirstRow = 0;
int iSrcLastRow = BeatToNoteRow( m_Clipboard.GetLastBeat() );
int iDestFirstRow = BeatToNoteRow( GAMESTATE->m_fSongBeat );
2004-10-23 17:43:49 +00:00
m_NoteFieldEdit.CopyRange( m_Clipboard, iSrcFirstRow, iSrcLastRow, iDestFirstRow );
2003-02-18 23:15:38 +00:00
}
break;
2003-02-22 00:48:38 +00:00
case paste_at_begin_marker:
{
ASSERT( m_NoteFieldEdit.m_fBeginMarker!=-1 );
int iSrcFirstRow = 0;
int iSrcLastRow = BeatToNoteRow( m_Clipboard.GetLastBeat() );
int iDestFirstRow = BeatToNoteRow( m_NoteFieldEdit.m_fBeginMarker );
2004-10-23 17:43:49 +00:00
m_NoteFieldEdit.CopyRange( m_Clipboard, iSrcFirstRow, iSrcLastRow, iDestFirstRow );
2003-02-22 00:48:38 +00:00
}
break;
2003-02-18 23:15:38 +00:00
case clear:
{
ASSERT( m_NoteFieldEdit.m_fBeginMarker!=-1 && m_NoteFieldEdit.m_fEndMarker!=-1 );
int iFirstRow = BeatToNoteRow( m_NoteFieldEdit.m_fBeginMarker );
int iLastRow = BeatToNoteRow( m_NoteFieldEdit.m_fEndMarker );
m_NoteFieldEdit.ClearRange( iFirstRow, iLastRow );
}
break;
case quantize:
{
NoteType nt = (NoteType)iAnswers[c];
NoteDataUtil::SnapToNearestNoteType( m_NoteFieldEdit, nt, nt, m_NoteFieldEdit.m_fBeginMarker, m_NoteFieldEdit.m_fEndMarker );
}
break;
2003-03-13 09:20:21 +00:00
case turn:
2003-02-18 23:15:38 +00:00
{
const NoteData OldClipboard( m_Clipboard );
2003-02-22 00:48:38 +00:00
HandleAreaMenuChoice( cut, NULL );
2004-06-28 07:26:00 +00:00
StepsType st = GAMESTATE->GetCurrentStyle()->m_StepsType;
2003-03-13 09:20:21 +00:00
TurnType tt = (TurnType)iAnswers[c];
2003-02-18 23:15:38 +00:00
switch( tt )
{
2003-08-07 06:36:34 +00:00
case left: NoteDataUtil::Turn( m_Clipboard, st, NoteDataUtil::left ); break;
case right: NoteDataUtil::Turn( m_Clipboard, st, NoteDataUtil::right ); break;
case mirror: NoteDataUtil::Turn( m_Clipboard, st, NoteDataUtil::mirror ); break;
case shuffle: NoteDataUtil::Turn( m_Clipboard, st, NoteDataUtil::shuffle ); break;
case super_shuffle: NoteDataUtil::Turn( m_Clipboard, st, NoteDataUtil::super_shuffle ); break;
2003-02-18 23:15:38 +00:00
default: ASSERT(0);
}
2003-02-22 00:48:38 +00:00
HandleAreaMenuChoice( paste_at_begin_marker, NULL );
m_Clipboard = OldClipboard;
2003-02-18 23:15:38 +00:00
}
break;
2003-03-13 09:20:21 +00:00
case transform:
{
float fBeginBeat = m_NoteFieldEdit.m_fBeginMarker;
float fEndBeat = m_NoteFieldEdit.m_fEndMarker;
2003-03-13 09:20:21 +00:00
TransformType tt = (TransformType)iAnswers[c];
2004-06-28 07:26:00 +00:00
StepsType st = GAMESTATE->GetCurrentStyle()->m_StepsType;
2003-03-13 09:20:21 +00:00
switch( tt )
{
2003-11-07 08:45:21 +00:00
case noholds: NoteDataUtil::RemoveHoldNotes( m_NoteFieldEdit, fBeginBeat, fEndBeat ); break;
case nomines: NoteDataUtil::RemoveMines( m_NoteFieldEdit, fBeginBeat, fEndBeat ); break;
case little: NoteDataUtil::Little( m_NoteFieldEdit, fBeginBeat, fEndBeat ); break;
case wide: NoteDataUtil::Wide( m_NoteFieldEdit, fBeginBeat, fEndBeat ); break;
case big: NoteDataUtil::Big( m_NoteFieldEdit, fBeginBeat, fEndBeat ); break;
case quick: NoteDataUtil::Quick( m_NoteFieldEdit, fBeginBeat, fEndBeat ); break;
case bmrize: NoteDataUtil::BMRize( m_NoteFieldEdit, fBeginBeat, fEndBeat ); break;
case skippy: NoteDataUtil::Skippy( m_NoteFieldEdit, fBeginBeat, fEndBeat ); break;
2003-11-07 08:45:21 +00:00
case mines: NoteDataUtil::AddMines( m_NoteFieldEdit, fBeginBeat, fEndBeat ); break;
2003-11-07 05:17:41 +00:00
case echo: NoteDataUtil::Echo( m_NoteFieldEdit, fBeginBeat, fEndBeat ); break;
2004-01-02 21:02:06 +00:00
case stomp: NoteDataUtil::Stomp( m_NoteFieldEdit, st, fBeginBeat, fEndBeat ); break;
2004-08-29 21:26:52 +00:00
case planted: NoteDataUtil::Planted( m_NoteFieldEdit, fBeginBeat, fEndBeat ); break;
case floored: NoteDataUtil::Floored( m_NoteFieldEdit, fBeginBeat, fEndBeat ); break;
2003-11-07 08:45:21 +00:00
case twister: NoteDataUtil::Twister( m_NoteFieldEdit, fBeginBeat, fEndBeat ); break;
2004-01-11 06:34:30 +00:00
case nojumps: NoteDataUtil::RemoveJumps( m_NoteFieldEdit, fBeginBeat, fEndBeat ); break;
2004-01-02 11:25:21 +00:00
case nohands: NoteDataUtil::RemoveHands( m_NoteFieldEdit, fBeginBeat, fEndBeat ); break;
2004-01-12 03:47:55 +00:00
case noquads: NoteDataUtil::RemoveQuads( m_NoteFieldEdit, fBeginBeat, fEndBeat ); break;
2003-03-13 09:20:21 +00:00
default: ASSERT(0);
}
// bake in the additions
NoteDataUtil::ConvertAdditionsToRegular( m_NoteFieldEdit );
2003-03-13 09:20:21 +00:00
}
break;
case alter:
{
const NoteData OldClipboard( m_Clipboard );
HandleAreaMenuChoice( cut, NULL );
AlterType at = (AlterType)iAnswers[c];
switch( at )
{
case backwards: NoteDataUtil::Backwards( m_Clipboard ); break;
case swap_sides: NoteDataUtil::SwapSides( m_Clipboard ); break;
case copy_left_to_right: NoteDataUtil::CopyLeftToRight( m_Clipboard ); break;
case copy_right_to_left: NoteDataUtil::CopyRightToLeft( m_Clipboard ); break;
case clear_left: NoteDataUtil::ClearLeft( m_Clipboard ); break;
case clear_right: NoteDataUtil::ClearRight( m_Clipboard ); break;
case collapse_to_one: NoteDataUtil::CollapseToOne( m_Clipboard ); break;
2003-12-31 07:49:30 +00:00
case collapse_left: NoteDataUtil::CollapseLeft( m_Clipboard ); break;
case shift_left: NoteDataUtil::ShiftLeft( m_Clipboard ); break;
case shift_right: NoteDataUtil::ShiftRight( m_Clipboard ); break;
default: ASSERT(0);
}
HandleAreaMenuChoice( paste_at_begin_marker, NULL );
m_Clipboard = OldClipboard;
}
break;
2003-09-07 22:28:46 +00:00
case tempo:
{
// This affects all steps.
const NoteData OldClipboard( m_Clipboard );
2003-09-07 22:28:46 +00:00
HandleAreaMenuChoice( cut, NULL );
AlterType at = (AlterType)iAnswers[c];
float fScale = -1;
switch( at )
{
2003-11-03 08:44:49 +00:00
case compress_2x: fScale = 0.5f; break;
case compress_3_2: fScale = 2.0f/3; break;
case compress_4_3: fScale = 0.75f; break;
case expand_4_3: fScale = 4.0f/3; break;
case expand_3_2: fScale = 1.5f; break;
case expand_2x: fScale = 2; break;
2003-09-07 22:28:46 +00:00
default: ASSERT(0);
}
m_Clipboard.ConvertHoldNotesTo2sAnd3s();
2003-09-07 22:28:46 +00:00
switch( at )
{
case compress_2x: NoteDataUtil::Scale( m_Clipboard, fScale ); break;
2003-11-03 08:44:49 +00:00
case compress_3_2: NoteDataUtil::Scale( m_Clipboard, fScale ); break;
case compress_4_3: NoteDataUtil::Scale( m_Clipboard, fScale ); break;
case expand_4_3: NoteDataUtil::Scale( m_Clipboard, fScale ); break;
case expand_3_2: NoteDataUtil::Scale( m_Clipboard, fScale ); break;
2003-09-07 22:28:46 +00:00
case expand_2x: NoteDataUtil::Scale( m_Clipboard, fScale ); break;
default: ASSERT(0);
}
m_Clipboard.Convert2sAnd3sToHoldNotes();
2003-09-07 22:48:25 +00:00
// float fOldClipboardEndBeat = m_NoteFieldEdit.m_fEndMarker;
2003-09-07 22:28:46 +00:00
float fOldClipboardBeats = m_NoteFieldEdit.m_fEndMarker - m_NoteFieldEdit.m_fBeginMarker;
float fNewClipboardBeats = fOldClipboardBeats * fScale;
float fDeltaBeats = fNewClipboardBeats - fOldClipboardBeats;
float fNewClipboardEndBeat = m_NoteFieldEdit.m_fBeginMarker + fNewClipboardBeats;
NoteDataUtil::ShiftRows( m_NoteFieldEdit, m_NoteFieldEdit.m_fBeginMarker, fDeltaBeats );
m_pSong->m_Timing.ScaleRegion( fScale, m_NoteFieldEdit.m_fBeginMarker, m_NoteFieldEdit.m_fEndMarker );
HandleAreaMenuChoice( paste_at_begin_marker, NULL );
const vector<Steps*> sIter = m_pSong->GetAllSteps();
NoteData ndTemp;
CString sTempStyle, sTempDiff;
2004-02-26 06:47:13 +00:00
for( unsigned i = 0; i < sIter.size(); i++ )
{
if( sIter[i]->IsAutogen() )
continue;
2004-02-26 06:47:13 +00:00
2004-05-24 03:41:39 +00:00
/* XXX: Edits are distinguished by description. Compare vs m_pSteps. */
2004-05-24 06:12:17 +00:00
if( (sIter[i]->m_StepsType == GAMESTATE->m_pCurSteps[PLAYER_1]->m_StepsType) &&
(sIter[i]->GetDifficulty() == GAMESTATE->m_pCurSteps[PLAYER_1]->GetDifficulty()) )
continue;
2004-10-23 17:43:49 +00:00
sIter[i]->GetNoteData( ndTemp );
ndTemp.ConvertHoldNotesTo2sAnd3s();
NoteDataUtil::ScaleRegion( ndTemp, fScale, m_NoteFieldEdit.m_fBeginMarker, m_NoteFieldEdit.m_fEndMarker );
ndTemp.Convert2sAnd3sToHoldNotes();
2004-10-23 17:43:49 +00:00
sIter[i]->SetNoteData( ndTemp );
}
2003-09-07 22:28:46 +00:00
m_NoteFieldEdit.m_fEndMarker = fNewClipboardEndBeat;
float fOldBPM = m_pSong->GetBPMAtBeat( m_NoteFieldEdit.m_fBeginMarker );
float fNewBPM = fOldBPM * fScale;
m_pSong->SetBPMAtBeat( m_NoteFieldEdit.m_fBeginMarker, fNewBPM );
m_pSong->SetBPMAtBeat( fNewClipboardEndBeat, fOldBPM );
}
break;
2003-02-18 23:15:38 +00:00
case play:
{
ASSERT( m_NoteFieldEdit.m_fBeginMarker!=-1 && m_NoteFieldEdit.m_fEndMarker!=-1 );
2003-07-26 22:53:22 +00:00
SOUND->PlayMusic("");
2003-02-18 23:15:38 +00:00
m_EditMode = MODE_PLAYING;
2004-02-01 02:05:09 +00:00
GAMESTATE->m_bPastHereWeGo = true;
2003-02-18 23:15:38 +00:00
/* Reset the note skin, in case preferences have changed. */
GAMESTATE->ResetNoteSkins();
2003-06-25 05:35:14 +00:00
/* Give a 1 measure lead-in. Set this before loading Player, so it knows
* where we're starting. */
2004-01-26 20:56:58 +00:00
float fSeconds = m_pSong->m_Timing.GetElapsedTimeFromBeat( m_NoteFieldEdit.m_fBeginMarker - 4 );
GAMESTATE->UpdateSongPosition( fSeconds, m_pSong->m_Timing );
SetupCourseAttacks();
2003-06-25 05:35:14 +00:00
m_Player.Load( GAMESTATE->m_pPlayerState[PLAYER_1], m_NoteFieldEdit, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL );
GAMESTATE->m_pPlayerState[PLAYER_1]->m_PlayerController = PREFSMAN->m_bAutoPlay?PC_AUTOPLAY:PC_HUMAN;
2003-02-18 23:15:38 +00:00
m_rectRecordBack.StopTweening();
m_rectRecordBack.BeginTweening( 0.5f );
2003-04-12 06:16:12 +00:00
m_rectRecordBack.SetDiffuse( RageColor(0,0,0,0.8f) );
2003-06-25 05:35:14 +00:00
const float fStartSeconds = m_pSong->GetElapsedTimeFromBeat(GAMESTATE->m_fSongBeat) ;
2003-02-25 00:33:42 +00:00
LOG->Trace( "Starting playback at %f", fStartSeconds );
if( PREFSMAN->m_bEditorShowBGChangesPlay )
{
/* FirstBeat affects backgrounds, so commit changes to memory (not to disk)
* and recalc it. */
2004-05-24 06:12:17 +00:00
Steps* pSteps = GAMESTATE->m_pCurSteps[PLAYER_1];
2004-05-24 03:41:39 +00:00
ASSERT( pSteps );
2004-10-23 17:43:49 +00:00
pSteps->SetNoteData( m_NoteFieldEdit );
m_pSong->ReCalculateRadarValuesAndLastBeat();
m_Background.Unload();
m_Background.LoadFromSong( m_pSong );
m_Foreground.Unload();
m_Foreground.LoadFromSong( m_pSong );
}
RageSoundParams p;
p.SetPlaybackRate( GAMESTATE->m_SongOptions.m_fMusicRate );
p.m_StartSecond = fStartSeconds;
p.AccurateSync = true;
p.StopMode = RageSoundParams::M_CONTINUE;
m_soundMusic.Play( &p );
2003-02-18 23:15:38 +00:00
}
break;
case record:
{
ASSERT( m_NoteFieldEdit.m_fBeginMarker!=-1 && m_NoteFieldEdit.m_fEndMarker!=-1 );
2003-07-26 22:53:22 +00:00
SOUND->PlayMusic("");
2003-02-18 23:15:38 +00:00
m_EditMode = MODE_RECORDING;
2004-02-01 02:05:09 +00:00
GAMESTATE->m_bPastHereWeGo = true;
2003-02-18 23:15:38 +00:00
/* Reset the note skin, in case preferences have changed. */
GAMESTATE->ResetNoteSkins();
2003-02-18 23:15:38 +00:00
// initialize m_NoteFieldRecord
m_NoteFieldRecord.Load( &m_NoteFieldEdit, GAMESTATE->m_pPlayerState[PLAYER_1], -150, 350, 350 );
2003-02-18 23:15:38 +00:00
m_NoteFieldRecord.SetNumTracks( m_NoteFieldEdit.GetNumTracks() );
m_rectRecordBack.StopTweening();
m_rectRecordBack.BeginTweening( 0.5f );
2003-04-12 06:16:12 +00:00
m_rectRecordBack.SetDiffuse( RageColor(0,0,0,0.8f) );
2003-02-18 23:15:38 +00:00
GAMESTATE->m_fSongBeat = m_NoteFieldEdit.m_fBeginMarker - 4; // give a 1 measure lead-in
2003-02-25 00:33:42 +00:00
float fStartSeconds = m_pSong->GetElapsedTimeFromBeat(GAMESTATE->m_fSongBeat);
LOG->Trace( "Starting playback at %f", fStartSeconds );
RageSoundParams p;
p.SetPlaybackRate( GAMESTATE->m_SongOptions.m_fMusicRate );
p.m_StartSecond = fStartSeconds;
p.AccurateSync = true;
p.StopMode = RageSoundParams::M_CONTINUE;
m_soundMusic.Play( &p );
2003-02-18 23:15:38 +00:00
}
break;
case insert_and_shift:
2003-09-07 22:28:46 +00:00
NoteDataUtil::ShiftRows( m_NoteFieldEdit, GAMESTATE->m_fSongBeat, 1 );
2003-02-18 23:15:38 +00:00
break;
case delete_and_shift:
2003-09-07 22:28:46 +00:00
NoteDataUtil::ShiftRows( m_NoteFieldEdit, GAMESTATE->m_fSongBeat, -1 );
break;
case shift_pauses_forward:
m_pSong->m_Timing.ShiftRows( GAMESTATE->m_fSongBeat, 1 );
break;
case shift_pauses_backward:
m_pSong->m_Timing.ShiftRows( GAMESTATE->m_fSongBeat, -1 );
2003-02-18 23:15:38 +00:00
break;
2003-11-03 08:44:49 +00:00
// MD 11/02/03 - Converting selected region to a pause of the same length.
case convert_beat_to_pause:
{
ASSERT( m_NoteFieldEdit.m_fBeginMarker!=-1 && m_NoteFieldEdit.m_fEndMarker!=-1 );
2004-02-23 17:18:02 +00:00
// This was written horribly, using beats and not converting to time at all.
float fMarkerStart = m_pSong->m_Timing.GetElapsedTimeFromBeat(m_NoteFieldEdit.m_fBeginMarker);
float fMarkerEnd = m_pSong->m_Timing.GetElapsedTimeFromBeat(m_NoteFieldEdit.m_fEndMarker);
float fStopLength = fMarkerEnd - fMarkerStart;
2003-11-03 08:44:49 +00:00
// be sure not to clobber the row at the start - a row at the end
// can be dropped safely, though
NoteDataUtil::ShiftRows( m_NoteFieldEdit,
m_NoteFieldEdit.m_fBeginMarker + 0.003f,
2004-02-23 17:18:02 +00:00
(-m_NoteFieldEdit.m_fEndMarker+m_NoteFieldEdit.m_fBeginMarker)
2003-11-03 08:44:49 +00:00
);
m_pSong->m_Timing.ShiftRows( m_NoteFieldEdit.m_fBeginMarker + 0.003f,
(-m_NoteFieldEdit.m_fEndMarker+m_NoteFieldEdit.m_fBeginMarker)
);
2003-11-03 08:44:49 +00:00
unsigned i;
2003-12-18 04:48:26 +00:00
for( i=0; i<m_pSong->m_Timing.m_StopSegments.size(); i++ )
2003-11-03 08:44:49 +00:00
{
2004-02-23 17:18:02 +00:00
float fStart = m_pSong->m_Timing.GetElapsedTimeFromBeat(m_pSong->m_Timing.m_StopSegments[i].m_fStartBeat);
float fEnd = fStart + m_pSong->m_Timing.m_StopSegments[i].m_fStopSeconds;
if( fStart > fMarkerEnd || fEnd < fMarkerStart )
continue;
else {
if (fStart > fMarkerStart)
m_pSong->m_Timing.m_StopSegments[i].m_fStartBeat = m_NoteFieldEdit.m_fBeginMarker;
m_pSong->m_Timing.m_StopSegments[i].m_fStopSeconds = fStopLength;
2003-11-03 08:44:49 +00:00
break;
2004-02-23 17:18:02 +00:00
}
2003-11-03 08:44:49 +00:00
}
2003-12-18 04:48:26 +00:00
if( i == m_pSong->m_Timing.m_StopSegments.size() ) // there is no BPMSegment at the current beat
2004-02-23 17:18:02 +00:00
m_pSong->AddStopSegment( StopSegment(m_NoteFieldEdit.m_fBeginMarker, fStopLength) );
2003-11-03 08:44:49 +00:00
m_NoteFieldEdit.m_fEndMarker = -1;
break;
}
// MD 11/02/03 - Converting a pause at the current beat into beats.
// I know this will break holds that cross the pause. Anyone who
// wants to rewrite this to fix that behavior is welcome to - I'm
// not sure how exactly to do it without making this a lot longer
// than it is.
// NOTE: Fixed this so that holds aren't broken by it. Working in 2s and
// 3s makes this work better, too. :-) It sorta makes you wonder WHY we
// don't bring it into 2s and 3s when we bring up the editor.
2003-11-03 08:44:49 +00:00
case convert_pause_to_beat:
{
float fBPMatPause = m_pSong->GetBPMAtBeat( GAMESTATE->m_fSongBeat );
unsigned i;
2003-12-18 04:48:26 +00:00
for( i=0; i<m_pSong->m_Timing.m_StopSegments.size(); i++ )
2003-11-03 08:44:49 +00:00
{
2003-12-18 04:48:26 +00:00
if( m_pSong->m_Timing.m_StopSegments[i].m_fStartBeat == GAMESTATE->m_fSongBeat )
2003-11-03 08:44:49 +00:00
break;
}
2003-12-18 04:48:26 +00:00
if( i == m_pSong->m_Timing.m_StopSegments.size() ) // there is no BPMSegment at the current beat
2003-11-03 08:44:49 +00:00
break;
2003-12-18 04:48:26 +00:00
else // StopSegment being modified is m_Timing.m_StopSegments[i]
2003-11-03 08:44:49 +00:00
{
2003-12-18 04:48:26 +00:00
float fStopLength = m_pSong->m_Timing.m_StopSegments[i].m_fStopSeconds;
m_pSong->m_Timing.m_StopSegments.erase( m_pSong->m_Timing.m_StopSegments.begin()+i,
m_pSong->m_Timing.m_StopSegments.begin()+i+1);
2004-02-23 17:18:02 +00:00
fStopLength *= fBPMatPause;
fStopLength /= 60;
2003-11-03 08:44:49 +00:00
// don't move the step from where it is, just move everything later
m_NoteFieldEdit.ConvertHoldNotesTo2sAnd3s();
2003-11-03 08:44:49 +00:00
NoteDataUtil::ShiftRows( m_NoteFieldEdit, GAMESTATE->m_fSongBeat + 0.003f, fStopLength );
m_pSong->m_Timing.ShiftRows( GAMESTATE->m_fSongBeat + 0.003f, fStopLength );
m_NoteFieldEdit.Convert2sAnd3sToHoldNotes();
2003-11-03 08:44:49 +00:00
}
// Hello and welcome to I FEEL STUPID :-)
break;
2003-11-03 08:44:49 +00:00
}
2003-02-18 23:15:38 +00:00
default:
ASSERT(0);
};
}
void ScreenEdit::HandleEditNotesStatisticsChoice( EditNotesStatisticsChoice c, int* iAnswers )
2002-08-17 06:44:04 +00:00
{
2004-05-24 06:12:17 +00:00
Steps* pSteps = GAMESTATE->m_pCurSteps[PLAYER_1];
2003-02-19 05:46:09 +00:00
Difficulty dc = (Difficulty)iAnswers[difficulty];
2004-05-24 03:41:39 +00:00
pSteps->SetDifficulty( dc );
2003-02-19 05:46:09 +00:00
int iMeter = iAnswers[meter]+1;
2004-05-24 03:41:39 +00:00
pSteps->SetMeter( iMeter );
2003-02-18 23:15:38 +00:00
switch( c )
{
2003-02-19 05:46:09 +00:00
case description:
2004-05-24 03:41:39 +00:00
SCREENMAN->TextEntry( SM_None, "Edit notes description.\nPress Enter to confirm,\nEscape to cancel.", m_pSteps->GetDescription(), ChangeDescription, NULL );
2003-02-18 23:15:38 +00:00
break;
2003-02-19 05:46:09 +00:00
}
2002-08-17 06:44:04 +00:00
}
2003-02-18 23:15:38 +00:00
void ScreenEdit::HandleEditSongInfoChoice( EditSongInfoChoice c, int* iAnswers )
{
2003-02-19 05:46:09 +00:00
Song* pSong = GAMESTATE->m_pCurSong;
2003-02-18 23:15:38 +00:00
switch( c )
{
case main_title:
2003-02-19 05:46:09 +00:00
SCREENMAN->TextEntry( SM_None, "Edit main title.\nPress Enter to confirm,\nEscape to cancel.", pSong->m_sMainTitle, ChangeMainTitle, NULL );
2003-02-18 23:15:38 +00:00
break;
case sub_title:
2003-02-19 05:46:09 +00:00
SCREENMAN->TextEntry( SM_None, "Edit sub title.\nPress Enter to confirm,\nEscape to cancel.", pSong->m_sSubTitle, ChangeSubTitle, NULL );
2003-02-18 23:15:38 +00:00
break;
case artist:
2003-02-19 05:46:09 +00:00
SCREENMAN->TextEntry( SM_None, "Edit artist.\nPress Enter to confirm,\nEscape to cancel.", pSong->m_sArtist, ChangeArtist, NULL );
2003-02-18 23:15:38 +00:00
break;
2003-06-23 02:24:13 +00:00
case credit:
SCREENMAN->TextEntry( SM_None, "Edit credit.\nPress Enter to confirm,\nEscape to cancel.", pSong->m_sCredit, ChangeCredit, NULL );
break;
2003-02-18 23:15:38 +00:00
case main_title_transliteration:
2003-02-19 05:46:09 +00:00
SCREENMAN->TextEntry( SM_None, "Edit main title transliteration.\nPress Enter to confirm,\nEscape to cancel.", pSong->m_sMainTitleTranslit, ChangeMainTitleTranslit, NULL );
2003-02-18 23:15:38 +00:00
break;
case sub_title_transliteration:
2003-02-19 05:46:09 +00:00
SCREENMAN->TextEntry( SM_None, "Edit sub title transliteration.\nPress Enter to confirm,\nEscape to cancel.", pSong->m_sSubTitleTranslit, ChangeSubTitleTranslit, NULL );
2003-02-18 23:15:38 +00:00
break;
case artist_transliteration:
2003-02-19 05:46:09 +00:00
SCREENMAN->TextEntry( SM_None, "Edit artist transliteration.\nPress Enter to confirm,\nEscape to cancel.", pSong->m_sArtistTranslit, ChangeArtistTranslit, NULL );
2003-02-18 23:15:38 +00:00
break;
default:
ASSERT(0);
};
}
void ScreenEdit::HandleBGChangeChoice( BGChangeChoice c, int* iAnswers )
{
BackgroundChange newChange;
FOREACH( BackgroundChange, m_pSong->m_BackgroundChanges, iter )
{
if( iter->m_fStartBeat == GAMESTATE->m_fSongBeat )
{
newChange = *iter;
// delete the old change. We'll add a new one below.
m_pSong->m_BackgroundChanges.erase( iter );
break;
}
}
newChange.m_fStartBeat = GAMESTATE->m_fSongBeat;
switch( c )
{
case add_random:
newChange.m_sBGName = "-random-";
break;
case add_song_bganimation:
case add_song_movie:
2003-04-13 23:22:27 +00:00
case add_song_still:
case add_global_random_movie:
case add_global_bganimation:
case add_global_visualization:
newChange.m_sBGName = g_BGChange.rows[c].choices[iAnswers[c]];
break;
case delete_change:
newChange.m_sBGName = "";
break;
default:
break;
};
newChange.m_fRate = strtof( g_BGChange.rows[rate].choices[iAnswers[rate]], NULL )/100.f;
newChange.m_bFadeLast = !!iAnswers[fade_last];
newChange.m_bRewindMovie = !!iAnswers[rewind_movie];
newChange.m_bLoop = !!iAnswers[loop];
if( newChange.m_sBGName != "" )
m_pSong->AddBackgroundChange( newChange );
}
2004-01-26 20:56:58 +00:00
void ScreenEdit::SetupCourseAttacks()
{
/* This is the first beat that can be changed without it being visible. Until
* we draw for the first time, any beat can be changed. */
GAMESTATE->m_pPlayerState[PLAYER_1]->m_fLastDrawnBeat = -100;
2004-01-26 20:56:58 +00:00
// Put course options into effect.
GAMESTATE->m_pPlayerState[PLAYER_1]->m_ModsToApply.clear();
2004-01-26 20:56:58 +00:00
GAMESTATE->RemoveActiveAttacksForPlayer( PLAYER_1 );
if( m_pAttacksFromCourse )
{
m_pAttacksFromCourse->LoadFromCRSFile( m_pAttacksFromCourse->m_sPath );
AttackArray Attacks;
for( unsigned e = 0; e < m_pAttacksFromCourse->m_entries.size(); ++e )
{
if( m_pAttacksFromCourse->m_entries[e].type != COURSE_ENTRY_FIXED )
continue;
if( m_pAttacksFromCourse->m_entries[e].pSong != m_pSong )
continue;
Attacks = m_pAttacksFromCourse->m_entries[e].attacks;
break;
}
for( unsigned i=0; i<Attacks.size(); ++i )
GAMESTATE->LaunchAttack( PLAYER_1, Attacks[i] );
}
GAMESTATE->RebuildPlayerOptionsFromActiveAttacks( PLAYER_1 );
}
2004-06-08 05:22:33 +00:00
/*
* (c) 2001-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.
*/