#include "stdafx.h" /* ----------------------------------------------------------------------------- Class: ScreenEdit Desc: See header. Copyright (c) 2001-2002 by the person(s) listed below. All rights reserved. Chris Danford ----------------------------------------------------------------------------- */ #include "ScreenEdit.h" #include "PrefsManager.h" #include "SongManager.h" #include "ScreenManager.h" #include "GameConstantsAndTypes.h" #include "PrefsManager.h" #include "GameManager.h" #include "GameConstantsAndTypes.h" #include "RageLog.h" #include "GameState.h" #include "InputMapper.h" #include "RageLog.h" #include #include "ThemeManager.h" #include "SDL_keysym.h" // for SDLKeys #include const float RECORD_HOLD_THRESHOLD = 0.3f; // // Defines specific to GameScreenTitleMenu // const float MAX_SECONDS_CAN_BE_OFF_BY = 0.20f; const float GRAY_ARROW_Y = ARROW_SIZE * 1.5; const float DEBUG_X = SCREEN_LEFT + 10; const float DEBUG_Y = CENTER_Y-100; const float HELP_X = SCREEN_LEFT + 10; const float HELP_Y = SCREEN_BOTTOM - 10; const float SHORTCUTS_X = CENTER_X - 150; const float SHORTCUTS_Y = CENTER_Y; const float INFO_X = SCREEN_RIGHT - 10 ; const float INFO_Y = SCREEN_BOTTOM - 10; const float MENU_WIDTH = 110; const float EDIT_X = CENTER_X; const float EDIT_GRAY_Y = GRAY_ARROW_Y; const float PLAYER_X = EDIT_X; const float PLAYER_Y = SCREEN_TOP; const float ACTION_MENU_ITEM_X = CENTER_X-200; const float ACTION_MENU_ITEM_START_Y = SCREEN_TOP + 24; const float ACTION_MENU_ITEM_SPACING_Y = 18; const float NAMING_MENU_ITEM_X = CENTER_X-200; const float NAMING_MENU_ITEM_START_Y = SCREEN_TOP + 24; const float NAMING_MENU_ITEM_SPACING_Y = 18; #define TICK_EARLY_SECONDS THEME->GetMetricF("ScreenGameplay","TickEarlySeconds") static float g_fTickEarlySecondsCache = 0; // reading directly out of theme metrics is slow const CString HELP_TEXT = "Esc: show command menu\n" // "Hold F1 to show more commands\n" "Hold keys for faster change:\n" "F7/F8: Decrease/increase BPM at cur beat\n" "F9/F10: Dec/inc freeze secs at cur beat\n" "F11/F12: Decrease/increase music offset\n" "[ and ]: Dec/inc sample music start\n" "{ and }: Dec/inc sample music length\n" "Up/Down: change beat\n" "Left/Right: change snap\n" "PgUp/PgDn: jump 1 measure\n" "Home/End: jump to first/last beat\n" "Number keys: add or remove tap note\n" "To create a hold note, hold a number key\n" " while changing the beat pressing Up/Down\n"; const CString SHORTCUT_TEXT = ""; /* "S: save changes\n" "W: save as SM and DWI (lossy)\n" "Enter/Space: set begin/end selection markers\n" "G/H/J/K/L: Quantize selection to nearest\n" " 4th / 8th / 12th / 16th / 12th or 16th\n" "P: Play selected area\n" "R: Record in selected area\n" "T: Toggle Play/Record rate\n" "X: Cut selected area\n" "C: Copy selected area\n" "V: Paste at current beat\n" "D: Toggle difficulty\n" "E: Edit description\n" "A: Edit main title\n" "U: Edit sub title\n" "B: Add/Edit background change\n" "Ins: Insert blank beat\n" "Del: Delete current beat and shift\n" "M: Play sample music\n"; */ const CString ACTION_MENU_ITEM_TEXT[NUM_ACTION_MENU_ITEMS] = { "Enter: Set begin marker (Enter)", "Space: Set end marker (Space)", "P: Play selection", "R: Record in selection", "T: Toggle Play/Record rate", "X: Cut selection", "C: Copy selection", "V: Paste clipboard at current beat", "D: Toggle difficulty", "E: Edit description", "N: Edit Title/Subtitle/Artist & Transliterations", "I: Toggle assist tick", "B: Add/Edit background change at current beat", "Ins: Insert blank beat and shift down", "Del: Delete blank beat and shift up", "G: Quantize selection to 4th notes", "H: Quantize selection to 8th notes", "J: Quantize selection to 12th notes", "K: Quantize selection to 16th notes", "L: Quantize selection to 12th or 16th notes", "M: Play sample music", "S: Save changes as SM and DWI", "Q: Quit" }; const int ACTION_MENU_ITEM_KEY[NUM_ACTION_MENU_ITEMS] = { SDLK_RETURN, SDLK_SPACE, SDLK_p, SDLK_r, SDLK_t, SDLK_x, SDLK_c, SDLK_v, SDLK_d, SDLK_e, SDLK_n, SDLK_i, SDLK_b, SDLK_INSERT, SDLK_DELETE, SDLK_g, SDLK_h, SDLK_j, SDLK_k, SDLK_l, SDLK_m, SDLK_s, SDLK_q, }; const CString NAMING_MENU_ITEM_TEXT[NUM_NAMING_MENU_ITEMS] = { " M: Edit main title", " S: Edit sub title", " A: Edit artist", "Shift-M: Edit main title transliteration", "Shift-S: Edit sub title transliteration", "Shift-A: Edit artist transliteration" }; // Pairs of keystroke + ifCapital const std::pair NAMING_MENU_ITEM_KEY[NUM_NAMING_MENU_ITEMS] = { std::make_pair(SDLK_m, false), std::make_pair(SDLK_s, false), std::make_pair(SDLK_a, false), std::make_pair(SDLK_m, true), std::make_pair(SDLK_s, true), std::make_pair(SDLK_a, true), }; ScreenEdit::ScreenEdit() { LOG->Trace( "ScreenEdit::ScreenEdit()" ); // set both players to joined so the credit message doesn't show for( int p=0; pm_bSideIsJoined[p] = true; SCREENMAN->RefreshCreditsMessages(); m_iRowLastCrossed = -1; m_pSong = GAMESTATE->m_pCurSong; m_pNotes = GAMESTATE->m_pCurNotes[PLAYER_1]; g_fTickEarlySecondsCache = TICK_EARLY_SECONDS; /* Make EditMenu responsible for creating new Notes */ //if( m_pNotes == NULL ) //{ // m_pNotes = new Notes; // m_pNotes->SetDifficulty(DIFFICULTY_MEDIUM); // m_pNotes->m_NotesType = GAMESTATE->GetCurrentStyleDef()->m_NotesType; // m_pNotes->SetDescription("Untitled"); // // In ScreenEditMenu, the screen preceding this one, // // GAMEMAN->m_CurStyle is set to the target game style // // of the current edit. Naturally, this is where we'll // // want to extract the NotesType for a (NEW) sequence. // m_pSong->m_apNotes.push_back( m_pNotes ); // GAMESTATE->m_pCurNotes[PLAYER_1] = m_pNotes; //} NoteData noteData; m_pNotes->GetNoteData( ¬eData ); m_EditMode = MODE_EDITING; GAMESTATE->m_bEditing = true; GAMESTATE->m_fSongBeat = 0; m_fTrailingBeat = GAMESTATE->m_fSongBeat; GAMESTATE->m_SongOptions.m_fMusicRate = 1; GAMESTATE->m_PlayerOptions[PLAYER_1].m_fScrollSpeed = 1; GAMESTATE->m_PlayerOptions[PLAYER_1].m_ColorType = PlayerOptions::COLOR_NOTE; m_BGAnimation.LoadFromAniDir( THEME->GetPathTo("BGAnimations","edit") ); shiftAnchor = -1; m_SnapDisplay.SetXY( EDIT_X, EDIT_GRAY_Y ); m_SnapDisplay.Load( PLAYER_1 ); m_SnapDisplay.SetZoom( 0.5f ); m_GrayArrowRowEdit.SetXY( EDIT_X, EDIT_GRAY_Y ); m_GrayArrowRowEdit.Load( PLAYER_1 ); m_GrayArrowRowEdit.SetZoom( 0.5f ); m_NoteFieldEdit.SetXY( EDIT_X, EDIT_GRAY_Y ); m_NoteFieldEdit.SetZoom( 0.5f ); m_NoteFieldEdit.Load( ¬eData, PLAYER_1, -200, 800 ); m_rectRecordBack.StretchTo( RectI(SCREEN_LEFT, SCREEN_TOP, SCREEN_RIGHT, SCREEN_BOTTOM) ); m_rectRecordBack.SetDiffuse( RageColor(0,0,0,0) ); m_GrayArrowRowRecord.SetXY( EDIT_X, EDIT_GRAY_Y ); m_GrayArrowRowRecord.Load( PLAYER_1 ); m_GrayArrowRowRecord.SetZoom( 1.0f ); m_NoteFieldRecord.SetXY( EDIT_X, EDIT_GRAY_Y ); m_NoteFieldRecord.SetZoom( 1.0f ); m_NoteFieldRecord.Load( ¬eData, PLAYER_1, -150, 350 ); m_Clipboard.SetNumTracks( m_NoteFieldEdit.GetNumTracks() ); m_Player.Load( PLAYER_1, ¬eData, NULL, NULL ); m_Player.SetXY( PLAYER_X, PLAYER_Y ); m_Fade.SetClosed(); m_textInfo.LoadFromFont( THEME->GetPathTo("Fonts","normal") ); m_textInfo.SetXY( INFO_X, INFO_Y ); m_textInfo.SetHorizAlign( Actor::align_right ); m_textInfo.SetVertAlign( Actor::align_bottom ); m_textInfo.SetZoom( 0.5f ); m_textInfo.SetShadowLength( 2 ); //m_textInfo.SetText(); // set this below every frame m_textHelp.LoadFromFont( THEME->GetPathTo("Fonts","normal") ); m_textHelp.SetXY( HELP_X, HELP_Y ); m_textHelp.SetHorizAlign( Actor::align_left ); m_textHelp.SetVertAlign( Actor::align_bottom ); m_textHelp.SetZoom( 0.5f ); m_textHelp.SetShadowLength( 2 ); m_textHelp.SetText( HELP_TEXT ); m_rectShortcutsBack.StretchTo( RectI(SCREEN_LEFT, SCREEN_TOP, SCREEN_RIGHT, SCREEN_BOTTOM) ); m_rectShortcutsBack.SetDiffuse( RageColor(0,0,0,0.8f) ); m_textShortcuts.LoadFromFont( THEME->GetPathTo("Fonts","normal") ); m_textShortcuts.SetXY( SHORTCUTS_X, SHORTCUTS_Y ); m_textShortcuts.SetHorizAlign( Actor::align_left ); m_textShortcuts.SetVertAlign( Actor::align_middle ); m_textShortcuts.SetZoom( 0.5f ); m_textShortcuts.SetShadowLength( 2 ); m_textShortcuts.SetText( SHORTCUT_TEXT ); m_soundChangeLine.Load( THEME->GetPathTo("Sounds","edit change line") ); m_soundChangeSnap.Load( THEME->GetPathTo("Sounds","edit change snap") ); m_soundMarker.Load( THEME->GetPathTo("Sounds","edit marker") ); m_soundInvalid.Load( THEME->GetPathTo("Sounds","menu invalid") ); m_soundMusic.Load(m_pSong->GetMusicPath()); m_soundMusic.SetAccurateSync(true); m_soundAssistTick.Load( THEME->GetPathTo("Sounds","gameplay assist tick") ); for( int i=0; iGetPathTo("Fonts","normal") ); m_textActionMenu[i].SetXY( ACTION_MENU_ITEM_X, ACTION_MENU_ITEM_START_Y + ACTION_MENU_ITEM_SPACING_Y*i ); m_textActionMenu[i].SetHorizAlign( Actor::align_left ); m_textActionMenu[i].SetZoom( 0.5f ); m_textActionMenu[i].SetShadowLength( 2 ); m_textActionMenu[i].SetText( ACTION_MENU_ITEM_TEXT[i] ); } for( int j=0; jGetPathTo("Fonts","normal") ); m_textNamingMenu[j].SetXY( NAMING_MENU_ITEM_X, NAMING_MENU_ITEM_START_Y + NAMING_MENU_ITEM_SPACING_Y*j ); m_textNamingMenu[j].SetHorizAlign( Actor::align_left ); m_textNamingMenu[j].SetZoom( 0.5f ); m_textNamingMenu[j].SetShadowLength( 2 ); m_textNamingMenu[j].SetText( NAMING_MENU_ITEM_TEXT[j] ); } m_iMenuSelection = 0; m_Fade.OpenWipingRight(); } ScreenEdit::~ScreenEdit() { LOG->Trace( "ScreenEdit::~ScreenEdit()" ); m_soundMusic.StopPlaying(); } // play assist ticks bool ScreenEdit::PlayTicks() const { // 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 if( GAMESTATE->m_SongOptions.m_AssistType != SongOptions::ASSIST_TICK ) return false; float fPositionSeconds = GAMESTATE->m_fMusicSeconds; // HACK: Play the sound a little bit early to account for the fact that the middle of the tick sounds occurs 0.015 seconds into playing. fPositionSeconds += (SOUNDMAN->GetPlayLatency()+g_fTickEarlySecondsCache) * m_soundMusic.GetPlaybackRate(); float fSongBeat=GAMESTATE->m_pCurSong->GetBeatFromElapsedTime( fPositionSeconds ); int iRowNow = BeatToNoteRowNotRounded( fSongBeat ); iRowNow = max( 0, iRowNow ); static int iRowLastCrossed = 0; bool bAnyoneHasANote = false; // set this to true if any player has a note at one of the indicies we crossed for( int r=iRowLastCrossed+1; r<=iRowNow; r++ ) // for each index we crossed since the last update bAnyoneHasANote |= m_Player.IsThereANoteAtRow( r ); iRowLastCrossed = iRowNow; return bAnyoneHasANote; } void ScreenEdit::Update( float fDeltaTime ) { float fPositionSeconds = m_soundMusic.GetPositionSeconds(); float fSongBeat, fBPS; bool bFreeze; m_pSong->GetBeatAndBPSFromElapsedTime( fPositionSeconds, fSongBeat, fBPS, bFreeze ); // update the global music statistics for other classes to access GAMESTATE->m_fMusicSeconds = fPositionSeconds; // GAMESTATE->m_fSongBeat = fSongBeat; GAMESTATE->m_fCurBPS = fBPS; GAMESTATE->m_bFreeze = bFreeze; if( m_EditMode == MODE_RECORDING ) { // add or extend holds for( int t=0; tGetCurrentStyleDef()->m_iColsPerPlayer; t++ ) // for each track { StyleInput StyleI( PLAYER_1, t ); float fSecsHeld = INPUTMAPPER->GetSecsHeld( StyleI ); if( fSecsHeld > RECORD_HOLD_THRESHOLD ) { // add or extend hold const float fHoldStartSeconds = m_soundMusic.GetPositionSeconds() - fSecsHeld; float fStartBeat = m_pSong->GetBeatFromElapsedTime( fHoldStartSeconds ); float fEndBeat = GAMESTATE->m_fSongBeat; // Round hold start and end to the nearest snap interval fStartBeat = froundf( fStartBeat, NoteTypeToBeat(m_SnapDisplay.GetNoteType()) ); fEndBeat = froundf( fEndBeat, NoteTypeToBeat(m_SnapDisplay.GetNoteType()) ); // create a new hold note HoldNote newHN = { t, fStartBeat, fEndBeat }; m_NoteFieldRecord.AddHoldNote( newHN ); } } } if( m_EditMode == MODE_RECORDING || m_EditMode == MODE_PLAYING ) { GAMESTATE->m_fSongBeat = fSongBeat; if( GAMESTATE->m_fSongBeat > m_NoteFieldEdit.m_fEndMarker + 4 ) // give a one measure lead out { if( m_EditMode == MODE_RECORDING ) { TransitionFromRecordToEdit(); } else if( m_EditMode == MODE_PLAYING ) { TransitionToEdit(); } GAMESTATE->m_fSongBeat = m_NoteFieldEdit.m_fEndMarker; } } m_BGAnimation.Update( fDeltaTime ); m_SnapDisplay.Update( fDeltaTime ); m_GrayArrowRowEdit.Update( fDeltaTime ); m_NoteFieldEdit.Update( fDeltaTime ); m_Fade.Update( fDeltaTime ); m_textHelp.Update( fDeltaTime ); m_textInfo.Update( fDeltaTime ); m_rectShortcutsBack.Update( fDeltaTime ); m_textShortcuts.Update( fDeltaTime ); m_rectRecordBack.Update( fDeltaTime ); if( m_EditMode == MODE_RECORDING ) { m_GrayArrowRowRecord.Update( fDeltaTime ); m_NoteFieldRecord.Update( fDeltaTime ); } if( m_EditMode == MODE_PLAYING ) { m_Player.Update( fDeltaTime ); } //LOG->Trace( "ScreenEdit::Update(%f)", fDeltaTime ); Screen::Update( fDeltaTime ); // Update trailing beat float fDelta = GAMESTATE->m_fSongBeat - m_fTrailingBeat; if( fabsf(fDelta) < 0.01 ) { m_fTrailingBeat = GAMESTATE->m_fSongBeat; // snap } else { float fSign = fDelta / fabsf(fDelta); float fMoveDelta = fSign*fDeltaTime*40; if( fabsf(fMoveDelta) > fabsf(fDelta) ) fMoveDelta = fDelta; m_fTrailingBeat += fMoveDelta; if( fabsf(fDelta) > 10 ) m_fTrailingBeat += fDelta * fDeltaTime*5; } if( m_EditMode == MODE_ACTION_MENU ) { for( int i=0; im_fSongBeat, m_NoteFieldEdit.m_fBeginMarker, m_NoteFieldEdit.m_fEndMarker, GAMESTATE->m_SongOptions.m_fMusicRate, DifficultyToString( m_pNotes->GetDifficulty() ).GetString(), GAMESTATE->m_pCurNotes[PLAYER_1] ? GAMESTATE->m_pCurNotes[PLAYER_1]->GetDescription().GetString() : "no description", m_pSong->m_sMainTitle.GetString(), m_pSong->m_sSubTitle.GetString(), iNumTapNotes, iNumHoldNotes, GAMESTATE->m_SongOptions.m_AssistType==SongOptions::ASSIST_TICK ? "ON" : "OFF", m_pSong->m_fBeat0OffsetInSeconds, m_pSong->m_fMusicSampleStartSeconds, m_pSong->m_fMusicSampleLengthSeconds ) ); } void ScreenEdit::DrawPrimitives() { m_BGAnimation.Draw(); m_SnapDisplay.Draw(); m_GrayArrowRowEdit.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_textHelp.Draw(); m_textInfo.Draw(); m_Fade.Draw(); /* if( INPUTFILTER->IsBeingPressed( DeviceInput(DEVICE_KEYBOARD,SDLK_F1) ) ) { m_rectShortcutsBack.Draw(); m_textShortcuts.Draw(); } */ m_rectRecordBack.Draw(); if( m_EditMode == MODE_RECORDING ) { m_GrayArrowRowRecord.Draw(); m_NoteFieldRecord.Draw(); } if( m_EditMode == MODE_PLAYING ) { m_Player.Draw(); } if( m_EditMode == MODE_RECORDING ) { /* for( int t=0; tGetCurrentStyleDef()->m_iColsPerPlayer; t++ ) { if( m_bLayingAHold[t] ) { bool bHoldingButton = false; for( int p=0; pIsButtonDown( StyleInput(PlayerInput(p), t) ); if( bHoldingButton } } */ } if( m_EditMode == MODE_ACTION_MENU ) { for( int i=0; iTrace( "ScreenEdit::Input()" ); switch( m_EditMode ) { case MODE_EDITING: InputEdit( DeviceI, type, GameI, MenuI, StyleI ); break; case MODE_ACTION_MENU: InputActionMenu( DeviceI, type, GameI, MenuI, StyleI ); break; case MODE_NAMING_MENU: InputNamingMenu( DeviceI, type, GameI, MenuI, StyleI ); break; case MODE_RECORDING: InputRecord( DeviceI, type, GameI, MenuI, StyleI ); break; case MODE_PLAYING: InputPlay( DeviceI, type, GameI, MenuI, StyleI ); break; default: ASSERT(0); } } // Begin helper functions for InputEdit void AddBGChange( CString sBGName ) { Song* pSong = GAMESTATE->m_pCurSong; unsigned i; for( i=0; im_BackgroundChanges.size(); i++ ) { if( pSong->m_BackgroundChanges[i].m_fStartBeat == GAMESTATE->m_fSongBeat ) break; } if( i != pSong->m_BackgroundChanges.size() ) // there is already a BGChange here pSong->m_BackgroundChanges.erase( pSong->m_BackgroundChanges.begin()+i, pSong->m_BackgroundChanges.begin()+i+1); // create a new BGChange if( sBGName != "" ) pSong->AddBackgroundChange( BackgroundChange(GAMESTATE->m_fSongBeat, sBGName) ); } void ChangeDescription( CString sNew ) { Notes* pNotes = GAMESTATE->m_pCurNotes[PLAYER_1]; pNotes->SetDescription(sNew); } 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; } 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 for InputEdit void ScreenEdit::InputEdit( const DeviceInput& DeviceI, const InputEventType type, const GameInput &GameI, const MenuInput &MenuI, const StyleInput &StyleI ) { if( DeviceI.device != DEVICE_KEYBOARD ) return; if(type == IET_RELEASE) { switch( DeviceI.button ) { case SDLK_LSHIFT: case SDLK_RSHIFT: shiftAnchor = -1; break; } return; } switch( DeviceI.button ) { case SDLK_1: case SDLK_2: case SDLK_3: case SDLK_4: case SDLK_5: case SDLK_6: case SDLK_7: case SDLK_8: case SDLK_9: case SDLK_0: { if( type != IET_FIRST_PRESS ) break; // We only care about first presses int iCol = DeviceI.button - SDLK_1; const float fSongBeat = GAMESTATE->m_fSongBeat; const int iSongIndex = BeatToNoteRow( fSongBeat ); if( iCol >= m_NoteFieldEdit.GetNumTracks() ) // this button is not in the range of columns for this StyleDef break; /* XXX: easier to do with 4s */ // check for to see if the user intended to remove a HoldNote bool bRemovedAHoldNote = false; for( int i=0; i= hn.m_fStartBeat && fSongBeat <= hn.m_fEndBeat ) // the cursor lies within this HoldNote { m_NoteFieldEdit.RemoveHoldNote( i ); bRemovedAHoldNote = true; break; // stop iterating over all HoldNotes } } if( !bRemovedAHoldNote ) { // We didn't remove a HoldNote, so the user wants to add or delete a TapNote if( m_NoteFieldEdit.GetTapNote(iCol, iSongIndex) == TAP_EMPTY ) m_NoteFieldEdit.SetTapNote(iCol, iSongIndex, TAP_TAP ); else m_NoteFieldEdit.SetTapNote(iCol, iSongIndex, TAP_EMPTY ); } } break; case SDLK_q: SCREENMAN->SetNewScreen( "ScreenEditMenu" ); break; case SDLK_s: { // copy edit into current Notes Notes* pNotes = GAMESTATE->m_pCurNotes[PLAYER_1]; ASSERT( pNotes ); pNotes->SetNoteData( &m_NoteFieldEdit ); GAMESTATE->m_pCurSong->Save(); SCREENMAN->SystemMessage( "Saved as SM and DWI." ); SOUNDMAN->PlayOnce( THEME->GetPathTo("Sounds","edit save") ); } break; case SDLK_UP: case SDLK_DOWN: case SDLK_PAGEUP: case SDLK_PAGEDOWN: { float fBeatsToMove=0.f; switch( DeviceI.button ) { case SDLK_UP: case SDLK_DOWN: fBeatsToMove = NoteTypeToBeat( m_SnapDisplay.GetNoteType() ); if( DeviceI.button == SDLK_UP ) fBeatsToMove *= -1; break; case SDLK_PAGEUP: case SDLK_PAGEDOWN: fBeatsToMove = BEATS_PER_MEASURE; if( DeviceI.button == SDLK_PAGEUP ) fBeatsToMove *= -1; } const float fStartBeat = GAMESTATE->m_fSongBeat; const float fEndBeat = GAMESTATE->m_fSongBeat + fBeatsToMove; // check to see if they're holding a button for( int col=0; colIsBeingPressed(di) ) continue; // create a new hold note HoldNote newHN; newHN.m_iTrack = col; newHN.m_fStartBeat = min(fStartBeat, fEndBeat); newHN.m_fEndBeat = max(fStartBeat, fEndBeat); newHN.m_fStartBeat = max(newHN.m_fStartBeat, 0); newHN.m_fEndBeat = max(newHN.m_fEndBeat, 0); m_NoteFieldEdit.AddHoldNote( newHN ); } if( INPUTFILTER->IsBeingPressed(DeviceInput(DEVICE_KEYBOARD, SDLK_LSHIFT)) || INPUTFILTER->IsBeingPressed(DeviceInput(DEVICE_KEYBOARD, SDLK_RSHIFT))) { /* 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 { 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); } } GAMESTATE->m_fSongBeat += fBeatsToMove; GAMESTATE->m_fSongBeat = clamp( GAMESTATE->m_fSongBeat, 0, MAX_BEATS-1 ); GAMESTATE->m_fSongBeat = froundf( GAMESTATE->m_fSongBeat, NoteTypeToBeat(m_SnapDisplay.GetNoteType()) ); m_soundChangeLine.Play(); } break; case SDLK_HOME: GAMESTATE->m_fSongBeat = 0; m_soundChangeLine.Play(); break; case SDLK_END: GAMESTATE->m_fSongBeat = m_NoteFieldEdit.GetLastBeat(); m_soundChangeLine.Play(); break; case SDLK_RIGHT: m_SnapDisplay.PrevSnapMode(); OnSnapModeChange(); break; case SDLK_LEFT: m_SnapDisplay.NextSnapMode(); OnSnapModeChange(); break; case SDLK_RETURN: case SDLK_KP_ENTER: if( m_NoteFieldEdit.m_fEndMarker != -1 && GAMESTATE->m_fSongBeat > m_NoteFieldEdit.m_fEndMarker ) { // invalid! The begin maker must be placed before the end marker m_soundInvalid.Play(); } else { m_NoteFieldEdit.m_fBeginMarker = GAMESTATE->m_fSongBeat; m_soundMarker.Play(); } break; case SDLK_SPACE: if( m_NoteFieldEdit.m_fBeginMarker != -1 && GAMESTATE->m_fSongBeat < m_NoteFieldEdit.m_fBeginMarker ) { // invalid! The end maker must be placed after the begin marker m_soundInvalid.Play(); } else { m_NoteFieldEdit.m_fEndMarker = GAMESTATE->m_fSongBeat; m_soundMarker.Play(); } break; case SDLK_g: case SDLK_h: case SDLK_j: case SDLK_k: case SDLK_l: { if( m_NoteFieldEdit.m_fBeginMarker == -1 || m_NoteFieldEdit.m_fEndMarker == -1 ) { m_soundInvalid.Play(); } else { NoteType noteType1; NoteType noteType2; switch( DeviceI.button ) { case SDLK_g: noteType1 = NOTE_TYPE_4TH; noteType2 = NOTE_TYPE_4TH; break; case SDLK_h: noteType1 = NOTE_TYPE_8TH; noteType2 = NOTE_TYPE_8TH; break; case SDLK_j: noteType1 = NOTE_TYPE_12TH; noteType2 = NOTE_TYPE_12TH; break; case SDLK_k: noteType1 = NOTE_TYPE_16TH; noteType2 = NOTE_TYPE_16TH; break; case SDLK_l: noteType1 = NOTE_TYPE_12TH; noteType2 = NOTE_TYPE_16TH; break; default: ASSERT( false ); return; } NoteDataUtil::SnapToNearestNoteType( m_NoteFieldEdit, noteType1, noteType2, m_NoteFieldEdit.m_fBeginMarker, m_NoteFieldEdit.m_fEndMarker ); } } break; case SDLK_ESCAPE: { m_EditMode = MODE_ACTION_MENU; m_iMenuSelection = 0; MenuItemGainFocus( &m_textActionMenu[m_iMenuSelection] ); m_rectRecordBack.StopTweening(); m_rectRecordBack.BeginTweening( 0.5f ); m_rectRecordBack.SetTweenDiffuse( RageColor(0,0,0,0.8f) ); } break; case SDLK_n: { m_EditMode = MODE_NAMING_MENU; m_iMenuSelection = 0; MenuItemGainFocus( &m_textNamingMenu[m_iMenuSelection] ); m_rectRecordBack.StopTweening(); m_rectRecordBack.BeginTweening( 0.5f ); m_rectRecordBack.SetTweenDiffuse( RageColor(0,0,0,0.8f) ); } break; case SDLK_r: case SDLK_p: { if( m_NoteFieldEdit.m_fBeginMarker == -1 ) m_NoteFieldEdit.m_fBeginMarker = GAMESTATE->m_fSongBeat; if( m_NoteFieldEdit.m_fEndMarker == -1 ) m_NoteFieldEdit.m_fEndMarker = m_pSong->m_fLastBeat; if(DeviceI.button == SDLK_r) { m_EditMode = MODE_RECORDING; // initialize m_NoteFieldRecord m_NoteFieldRecord.ClearAll(); m_NoteFieldRecord.SetNumTracks( m_NoteFieldEdit.GetNumTracks() ); m_NoteFieldRecord.m_fBeginMarker = m_NoteFieldEdit.m_fBeginMarker; m_NoteFieldRecord.m_fEndMarker = m_NoteFieldEdit.m_fEndMarker; } else { m_EditMode = MODE_PLAYING; m_Player.Load( PLAYER_1, (NoteData*)&m_NoteFieldEdit, NULL, NULL ); } m_rectRecordBack.StopTweening(); m_rectRecordBack.BeginTweening( 0.5f ); m_rectRecordBack.SetTweenDiffuse( RageColor(0,0,0,0.8f) ); GAMESTATE->m_fSongBeat = m_NoteFieldEdit.m_fBeginMarker - 4; // give a 1 measure lead-in float fStartSeconds = m_pSong->GetElapsedTimeFromBeat(GAMESTATE->m_fSongBeat) ; m_soundMusic.SetPositionSeconds( fStartSeconds ); m_soundMusic.SetPlaybackRate( GAMESTATE->m_SongOptions.m_fMusicRate ); m_soundMusic.StartPlaying(); } break; case SDLK_t: if( GAMESTATE->m_SongOptions.m_fMusicRate == 1.0f ) GAMESTATE->m_SongOptions.m_fMusicRate = 0.9f; else if( GAMESTATE->m_SongOptions.m_fMusicRate == 0.9f ) GAMESTATE->m_SongOptions.m_fMusicRate = 0.8f; else if( GAMESTATE->m_SongOptions.m_fMusicRate == 0.8f ) GAMESTATE->m_SongOptions.m_fMusicRate = 0.7f; else if( GAMESTATE->m_SongOptions.m_fMusicRate == 0.7f ) GAMESTATE->m_SongOptions.m_fMusicRate = 1.5f; else if( GAMESTATE->m_SongOptions.m_fMusicRate == 1.5f ) GAMESTATE->m_SongOptions.m_fMusicRate = 1.4f; else if( GAMESTATE->m_SongOptions.m_fMusicRate == 1.4f ) GAMESTATE->m_SongOptions.m_fMusicRate = 1.3f; else if( GAMESTATE->m_SongOptions.m_fMusicRate == 1.3f ) GAMESTATE->m_SongOptions.m_fMusicRate = 1.2f; else if( GAMESTATE->m_SongOptions.m_fMusicRate == 1.2f ) GAMESTATE->m_SongOptions.m_fMusicRate = 1.1f; else if( GAMESTATE->m_SongOptions.m_fMusicRate == 1.1f ) GAMESTATE->m_SongOptions.m_fMusicRate = 1.0f; break; case SDLK_INSERT: case SDLK_DELETE: { NoteData temp; temp.SetNumTracks( m_NoteFieldEdit.GetNumTracks() ); int iTakeFromRow=0; int iPasteAtRow; switch( DeviceI.button ) { case SDLK_INSERT: iTakeFromRow = BeatToNoteRow( GAMESTATE->m_fSongBeat ); iPasteAtRow = BeatToNoteRow( GAMESTATE->m_fSongBeat+1 ); break; case SDLK_DELETE: iTakeFromRow = BeatToNoteRow( GAMESTATE->m_fSongBeat+1 ); iPasteAtRow = BeatToNoteRow( GAMESTATE->m_fSongBeat ); break; } temp.CopyRange( &m_NoteFieldEdit, iTakeFromRow, m_NoteFieldEdit.GetLastRow() ); m_NoteFieldEdit.ClearRange( min(iTakeFromRow,iPasteAtRow), m_NoteFieldEdit.GetLastRow() ); m_NoteFieldEdit.CopyRange( &temp, 0, temp.GetLastRow(), iPasteAtRow ); } break; case SDLK_x: if( m_NoteFieldEdit.m_fBeginMarker == -1 || m_NoteFieldEdit.m_fEndMarker == -1 ) { m_soundInvalid.Play(); } else { int iFirstRow = BeatToNoteRow( m_NoteFieldEdit.m_fBeginMarker ); int iLastRow = BeatToNoteRow( m_NoteFieldEdit.m_fEndMarker ); m_Clipboard.ClearAll(); m_Clipboard.CopyRange( &m_NoteFieldEdit, iFirstRow, iLastRow ); if(DeviceI.button == SDLK_x) m_NoteFieldEdit.ClearRange( iFirstRow, iLastRow ); } break; case SDLK_v: { int iSrcFirstRow = 0; int iSrcLastRow = BeatToNoteRow( m_Clipboard.GetLastBeat() ); int iDestFirstRow = BeatToNoteRow( GAMESTATE->m_fSongBeat ); m_NoteFieldEdit.CopyRange( &m_Clipboard, iSrcFirstRow, iSrcLastRow, iDestFirstRow ); } break; case SDLK_d: { Difficulty dc = Difficulty( (m_pNotes->GetDifficulty()+1)%NUM_DIFFICULTIES ); m_pNotes->SetDifficulty(dc); } break; case SDLK_e: SCREENMAN->TextEntry( SM_None, "Edit notes description.\nPress Enter to confirm,\nEscape to cancel.", m_pNotes->GetDescription(), ChangeDescription, NULL ); break; case SDLK_b: { CString sOldBackground; unsigned i; for( i=0; im_BackgroundChanges.size(); i++ ) { if( m_pSong->m_BackgroundChanges[i].m_fStartBeat == GAMESTATE->m_fSongBeat ) break; } if( i != m_pSong->m_BackgroundChanges.size() ) // there is already a BGChange here sOldBackground = m_pSong->m_BackgroundChanges[i].m_sBGName; SCREENMAN->TextEntry( SM_None, "Type a background name.\nPress Enter to keep,\nEscape to cancel.\nEnter an empty string to remove\nthe Background Change.", sOldBackground, AddBGChange, NULL ); } break; case SDLK_i: if( GAMESTATE->m_SongOptions.m_AssistType==SongOptions::ASSIST_TICK ) GAMESTATE->m_SongOptions.m_AssistType = SongOptions::ASSIST_NONE; else GAMESTATE->m_SongOptions.m_AssistType = SongOptions::ASSIST_TICK; break; case SDLK_F7: case SDLK_F8: { float fBPM = m_pSong->GetBPMAtBeat( GAMESTATE->m_fSongBeat ); float fDeltaBPM; switch( DeviceI.button ) { case SDLK_F7: fDeltaBPM = - 0.020f; break; case SDLK_F8: fDeltaBPM = + 0.020f; break; default: ASSERT(0); return; } switch( type ) { case IET_SLOW_REPEAT: fDeltaBPM *= 10; break; case IET_FAST_REPEAT: fDeltaBPM *= 40; break; } float fNewBPM = fBPM + fDeltaBPM; unsigned i; for( i=0; im_BPMSegments.size(); i++ ) if( m_pSong->m_BPMSegments[i].m_fStartBeat == GAMESTATE->m_fSongBeat ) break; if( i == m_pSong->m_BPMSegments.size() ) // there is no BPMSegment at the current beat { // create a new BPMSegment m_pSong->AddBPMSegment( BPMSegment(GAMESTATE->m_fSongBeat, fNewBPM) ); } else // BPMSegment being modified is m_BPMSegments[i] { if( i > 0 && fabsf(m_pSong->m_BPMSegments[i-1].m_fBPM - fNewBPM) < 0.025f ) m_pSong->m_BPMSegments.erase( m_pSong->m_BPMSegments.begin()+i, m_pSong->m_BPMSegments.begin()+i+1); else m_pSong->m_BPMSegments[i].m_fBPM = fNewBPM; } } break; case SDLK_F9: case SDLK_F10: { float fStopDelta; switch( DeviceI.button ) { case SDLK_F9: fStopDelta = -0.02f; break; case SDLK_F10: fStopDelta = +0.02f; break; default: ASSERT(0); return; } switch( type ) { case IET_SLOW_REPEAT: fStopDelta *= 10; break; case IET_FAST_REPEAT: fStopDelta *= 40; break; } unsigned i; for( i=0; im_StopSegments.size(); i++ ) { if( m_pSong->m_StopSegments[i].m_fStartBeat == GAMESTATE->m_fSongBeat ) break; } if( i == m_pSong->m_StopSegments.size() ) // there is no BPMSegment at the current beat { // create a new StopSegment if( fStopDelta > 0 ) m_pSong->AddStopSegment( StopSegment(GAMESTATE->m_fSongBeat, fStopDelta) ); } else // StopSegment being modified is m_StopSegments[i] { m_pSong->m_StopSegments[i].m_fStopSeconds += fStopDelta; if( m_pSong->m_StopSegments[i].m_fStopSeconds <= 0 ) m_pSong->m_StopSegments.erase( m_pSong->m_StopSegments.begin()+i, m_pSong->m_StopSegments.begin()+i+1); } } break; case SDLK_F11: case SDLK_F12: { float fOffsetDelta; switch( DeviceI.button ) { case SDLK_F11: fOffsetDelta = -0.02f; break; case SDLK_F12: fOffsetDelta = +0.02f; break; default: ASSERT(0); return; } switch( type ) { case IET_SLOW_REPEAT: fOffsetDelta *= 10; break; case IET_FAST_REPEAT: fOffsetDelta *= 40; break; } m_pSong->m_fBeat0OffsetInSeconds += fOffsetDelta; } break; case SDLK_m: SOUNDMAN->PlayMusic(""); SOUNDMAN->PlayMusic( m_pSong->GetMusicPath(), false, m_pSong->m_fMusicSampleStartSeconds, m_pSong->m_fMusicSampleLengthSeconds ); break; case SDLK_LEFTBRACKET: case SDLK_RIGHTBRACKET: { float fDelta; switch( DeviceI.button ) { case SDLK_LEFTBRACKET: fDelta = -0.02f; break; case SDLK_RIGHTBRACKET: fDelta = +0.02f; break; default: ASSERT(0); return; } switch( type ) { case IET_SLOW_REPEAT: fDelta *= 10; break; case IET_FAST_REPEAT: fDelta *= 40; break; } if( INPUTFILTER->IsBeingPressed(DeviceInput(DEVICE_KEYBOARD, SDLK_LSHIFT)) || INPUTFILTER->IsBeingPressed(DeviceInput(DEVICE_KEYBOARD, SDLK_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); } } break; } } void ScreenEdit::InputRecord( const DeviceInput& DeviceI, const InputEventType type, const GameInput &GameI, const MenuInput &MenuI, const StyleInput &StyleI ) { if( DeviceI.device == DEVICE_KEYBOARD && DeviceI.button == SDLK_ESCAPE ) { TransitionFromRecordToEdit(); return; } if( StyleI.player != PLAYER_1 ) return; // ignore const int iCol = StyleI.col; switch( type ) { case IET_FIRST_PRESS: { // Add a tap float fBeat = GAMESTATE->m_fSongBeat; fBeat = froundf( fBeat, NoteTypeToBeat(m_SnapDisplay.GetNoteType()) ); const int iRow = BeatToNoteRow( fBeat ); if( iRow < 0 ) break; m_NoteFieldRecord.SetTapNote(iCol, iRow, TAP_TAP); m_GrayArrowRowRecord.Step( iCol ); } break; case IET_SLOW_REPEAT: case IET_FAST_REPEAT: case IET_RELEASE: // don't add or extend holds here break; } } void ScreenEdit::InputActionMenu( const DeviceInput& DeviceI, const InputEventType type, const GameInput &GameI, const MenuInput &MenuI, const StyleInput &StyleI ) { if( DeviceI.device != DEVICE_KEYBOARD ) return; if(type == IET_RELEASE) return; // don't care switch( DeviceI.button ) { case SDLK_UP: MenuItemLoseFocus( &m_textActionMenu[m_iMenuSelection] ); m_iMenuSelection = (m_iMenuSelection-1+NUM_ACTION_MENU_ITEMS) % NUM_ACTION_MENU_ITEMS; printf( "%d\n", m_iMenuSelection ); MenuItemGainFocus( &m_textActionMenu[m_iMenuSelection] ); break; case SDLK_DOWN: MenuItemLoseFocus( &m_textActionMenu[m_iMenuSelection] ); m_iMenuSelection = (m_iMenuSelection+1) % NUM_ACTION_MENU_ITEMS; printf( "%d\n", m_iMenuSelection ); MenuItemGainFocus( &m_textActionMenu[m_iMenuSelection] ); break; case SDLK_RETURN: case SDLK_ESCAPE: TransitionToEdit(); MenuItemLoseFocus( &m_textActionMenu[m_iMenuSelection] ); if( DeviceI.button == SDLK_RETURN ) { SOUNDMAN->PlayOnce( THEME->GetPathTo("Sounds","menu start") ); int iMenuKey = ACTION_MENU_ITEM_KEY[m_iMenuSelection]; InputEdit( DeviceInput(DEVICE_KEYBOARD,iMenuKey), IET_FIRST_PRESS, GameInput(), MenuInput(), StyleInput() ); } break; default: // On recognized keys, behave as on the top level for(int i=0; iPlayOnce( THEME->GetPathTo("Sounds","menu start") ); InputEdit( DeviceI, IET_FIRST_PRESS, GameInput(), MenuInput(), StyleInput() ); } } break; } } void ScreenEdit::InputNamingMenu( const DeviceInput& DeviceI, const InputEventType type, const GameInput &GameI, const MenuInput &MenuI, const StyleInput &StyleI, bool forceShiftPressed ) { if( DeviceI.device != DEVICE_KEYBOARD ) return; if(type == IET_RELEASE) return; // don't care bool translit = forceShiftPressed || INPUTFILTER->IsBeingPressed(DeviceInput(DEVICE_KEYBOARD, SDLK_LSHIFT)) || INPUTFILTER->IsBeingPressed(DeviceInput(DEVICE_KEYBOARD, SDLK_RSHIFT)); switch( DeviceI.button ) { case SDLK_m: case SDLK_s: case SDLK_a: case SDLK_ESCAPE: case SDLK_RETURN: TransitionToEdit(); MenuItemLoseFocus( &m_textNamingMenu[m_iMenuSelection] ); break; } switch( DeviceI.button ) { case SDLK_m: if(translit) { SCREENMAN->TextEntry( SM_None, "Edit song main title transliteration.\nPress Enter to confirm,\nEscape to cancel.", m_pSong->m_sMainTitleTranslit, ChangeMainTitleTranslit, NULL); } else { SCREENMAN->TextEntry( SM_None, "Edit song main title.\nPress Enter to confirm,\nEscape to cancel.", m_pSong->m_sMainTitle, ChangeMainTitle, NULL ); } break; case SDLK_s: if(translit) { SCREENMAN->TextEntry( SM_None, "Edit song sub title transliteration.\nPress Enter to confirm,\nEscape to cancel.", m_pSong->m_sSubTitleTranslit, ChangeSubTitleTranslit, NULL); } else { SCREENMAN->TextEntry( SM_None, "Edit song sub title.\nPress Enter to confirm,\nEscape to cancel.", m_pSong->m_sSubTitle, ChangeSubTitle, NULL ); } break; case SDLK_a: if(translit) { SCREENMAN->TextEntry( SM_None, "Edit song artist transliteration.\nPress Enter to confirm,\nEscape to cancel.", m_pSong->m_sArtistTranslit, ChangeArtistTranslit, NULL); } else { SCREENMAN->TextEntry( SM_None, "Edit song artist.\nPress Enter to confirm,\nEscape to cancel.", m_pSong->m_sArtist, ChangeArtist, NULL ); } break; case SDLK_UP: MenuItemLoseFocus( &m_textNamingMenu[m_iMenuSelection] ); m_iMenuSelection = (m_iMenuSelection-1+NUM_NAMING_MENU_ITEMS) % NUM_NAMING_MENU_ITEMS; printf( "%d\n", m_iMenuSelection ); MenuItemGainFocus( &m_textNamingMenu[m_iMenuSelection] ); break; case SDLK_DOWN: MenuItemLoseFocus( &m_textNamingMenu[m_iMenuSelection] ); m_iMenuSelection = (m_iMenuSelection+1) % NUM_NAMING_MENU_ITEMS; printf( "%d\n", m_iMenuSelection ); MenuItemGainFocus( &m_textNamingMenu[m_iMenuSelection] ); break; case SDLK_RETURN: SOUNDMAN->PlayOnce( THEME->GetPathTo("Sounds","menu start") ); const std::pair& pairMenuKey = NAMING_MENU_ITEM_KEY[m_iMenuSelection]; InputNamingMenu( DeviceInput(DEVICE_KEYBOARD,pairMenuKey.first), IET_FIRST_PRESS, GameInput(), MenuInput(), StyleInput(), pairMenuKey.second ); break; } } 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 ) { case SDLK_ESCAPE: TransitionToEdit(); break; case SDLK_F11: case SDLK_F12: { float fOffsetDelta; switch( DeviceI.button ) { case SDLK_F11: fOffsetDelta = -0.020f; break; case SDLK_F12: fOffsetDelta = +0.020f; break; default: ASSERT(0); return; } switch( type ) { case IET_SLOW_REPEAT: fOffsetDelta *= 10; break; case IET_FAST_REPEAT: fOffsetDelta *= 40; break; } m_pSong->m_fBeat0OffsetInSeconds += fOffsetDelta; } break; } } switch( StyleI.player ) { case PLAYER_1: m_Player.Step( StyleI.col ); return; } } /* Switch to editing. */ void ScreenEdit::TransitionToEdit() { m_EditMode = MODE_EDITING; m_soundMusic.StopPlaying(); m_rectRecordBack.StopTweening(); m_rectRecordBack.BeginTweening( 0.5f ); m_rectRecordBack.SetTweenDiffuse( RageColor(0,0,0,0) ); /* Make sure we're snapped. */ GAMESTATE->m_fSongBeat = froundf( 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 ); } void ScreenEdit::TransitionFromRecordToEdit() { TransitionToEdit(); int iNoteIndexBegin = BeatToNoteRow( m_NoteFieldEdit.m_fBeginMarker ); int iNoteIndexEnd = BeatToNoteRow( m_NoteFieldEdit.m_fEndMarker ); // delete old TapNotes in the range m_NoteFieldEdit.ClearRange( iNoteIndexBegin, iNoteIndexEnd ); m_NoteFieldEdit.CopyRange( &m_NoteFieldRecord, iNoteIndexBegin, iNoteIndexEnd, iNoteIndexBegin ); } void ScreenEdit::HandleScreenMessage( const ScreenMessage SM ) { switch( SM ) { case SM_GoToPrevScreen: SCREENMAN->SetNewScreen( "ScreenEditMenu" ); break; case SM_GoToNextScreen: SCREENMAN->SetNewScreen( "ScreenEditMenu" ); break; } } void ScreenEdit::OnSnapModeChange() { m_soundChangeSnap.Play(); NoteType nt = m_SnapDisplay.GetNoteType(); int iStepIndex = BeatToNoteRow( GAMESTATE->m_fSongBeat ); int iElementsPerNoteType = BeatToNoteRow( NoteTypeToBeat(nt) ); int iStepIndexHangover = iStepIndex % iElementsPerNoteType; GAMESTATE->m_fSongBeat -= NoteRowToBeat( iStepIndexHangover ); } void ScreenEdit::MenuItemGainFocus( BitmapText* menuitem ) { menuitem->SetEffectCamelion( 2.5, RageColor(1,1,1,1), RageColor(0,1,0,1) ); menuitem->SetZoom( 0.7f ); SOUNDMAN->PlayOnce( THEME->GetPathTo("Sounds","edit menu row") ); } void ScreenEdit::MenuItemLoseFocus( BitmapText* menuitem ) { menuitem->SetEffectNone(); menuitem->SetZoom( 0.5f ); }