/* ScreenEdit - Edit, record, playback, and synchronize notes. */ #ifndef SCREEN_EDIT_H #define SCREEN_EDIT_H #include "ScreenWithMenuElements.h" #include "Sprite.h" #include "BitmapText.h" #include "Player.h" #include "RageSound.h" #include "SnapDisplay.h" #include "Background.h" #include "Foreground.h" #include "Course.h" #include "NoteField.h" #include "song.h" #include "Steps.h" #include "ThemeMetric.h" #include "PlayerState.h" #include "ScreenMiniMenu.h" const int NUM_EDIT_BUTTON_COLUMNS = 10; struct MenuDef; enum EditState { STATE_EDITING, STATE_RECORDING, STATE_RECORDING_PAUSED, STATE_PLAYING, NUM_EDIT_STATES, STATE_INVALID }; enum EditButton { EDIT_BUTTON_COLUMN_0, EDIT_BUTTON_COLUMN_1, EDIT_BUTTON_COLUMN_2, EDIT_BUTTON_COLUMN_3, EDIT_BUTTON_COLUMN_4, EDIT_BUTTON_COLUMN_5, EDIT_BUTTON_COLUMN_6, EDIT_BUTTON_COLUMN_7, EDIT_BUTTON_COLUMN_8, EDIT_BUTTON_COLUMN_9, /* These are modifiers to EDIT_BUTTON_COLUMN_*. */ EDIT_BUTTON_RIGHT_SIDE, EDIT_BUTTON_LAY_MINE_OR_ROLL, EDIT_BUTTON_LAY_TAP_ATTACK, EDIT_BUTTON_REMOVE_NOTE, EDIT_BUTTON_SCROLL_UP_LINE, EDIT_BUTTON_SCROLL_UP_PAGE, EDIT_BUTTON_SCROLL_DOWN_LINE, EDIT_BUTTON_SCROLL_DOWN_PAGE, EDIT_BUTTON_SCROLL_NEXT_MEASURE, EDIT_BUTTON_SCROLL_PREV_MEASURE, EDIT_BUTTON_SCROLL_HOME, EDIT_BUTTON_SCROLL_END, EDIT_BUTTON_SCROLL_NEXT, EDIT_BUTTON_SCROLL_PREV, /* These are modifiers to EDIT_BUTTON_SCROLL_*. */ EDIT_BUTTON_SCROLL_SELECT, EDIT_BUTTON_LAY_SELECT, EDIT_BUTTON_SCROLL_SPEED_UP, EDIT_BUTTON_SCROLL_SPEED_DOWN, EDIT_BUTTON_SNAP_NEXT, EDIT_BUTTON_SNAP_PREV, EDIT_BUTTON_OPEN_EDIT_MENU, EDIT_BUTTON_OPEN_AREA_MENU, EDIT_BUTTON_OPEN_BGCHANGE_LAYER1_MENU, EDIT_BUTTON_OPEN_BGCHANGE_LAYER2_MENU, EDIT_BUTTON_OPEN_COURSE_MENU, EDIT_BUTTON_OPEN_COURSE_ATTACK_MENU, EDIT_BUTTON_OPEN_INPUT_HELP, EDIT_BUTTON_BAKE_RANDOM_FROM_SONG_GROUP, EDIT_BUTTON_BAKE_RANDOM_FROM_SONG_GROUP_AND_GENRE, EDIT_BUTTON_PLAY_FROM_START, EDIT_BUTTON_PLAY_FROM_CURSOR, EDIT_BUTTON_PLAY_SELECTION, EDIT_BUTTON_RECORD_FROM_CURSOR, EDIT_BUTTON_RECORD_SELECTION, EDIT_BUTTON_RETURN_TO_EDIT, EDIT_BUTTON_INSERT, EDIT_BUTTON_DELETE, EDIT_BUTTON_INSERT_SHIFT_PAUSES, EDIT_BUTTON_DELETE_SHIFT_PAUSES, EDIT_BUTTON_OPEN_NEXT_STEPS, EDIT_BUTTON_OPEN_PREV_STEPS, EDIT_BUTTON_TOGGLE_ASSIST_TICK, EDIT_BUTTON_TOGGLE_AUTOPLAY, EDIT_BUTTON_PLAY_SAMPLE_MUSIC, EDIT_BUTTON_BPM_UP, EDIT_BUTTON_BPM_DOWN, EDIT_BUTTON_STOP_UP, EDIT_BUTTON_STOP_DOWN, EDIT_BUTTON_OFFSET_UP, EDIT_BUTTON_OFFSET_DOWN, EDIT_BUTTON_SAMPLE_START_UP, EDIT_BUTTON_SAMPLE_START_DOWN, EDIT_BUTTON_SAMPLE_LENGTH_UP, EDIT_BUTTON_SAMPLE_LENGTH_DOWN, /* This modifies offset, BPM, and stop segment changes. */ EDIT_BUTTON_ADJUST_FINE, EDIT_BUTTON_UNDO, NUM_EDIT_BUTTONS, // leave this at the end EDIT_BUTTON_INVALID }; #define FOREACH_EditButton( e ) FOREACH_ENUM( EditButton, NUM_EDIT_BUTTONS, e ) #define NUM_EDIT_TO_DEVICE_SLOTS 2 /* * g_MapEditToDI is a simple mapping: edit functions map to DeviceInputs. * If g_MapEditToDIHold for a given edit function is valid, then at least one * input in g_MapEditToDIHold must be held when pressing any key in g_MapEditToDI * for the input to occur. */ struct MapEditToDI { DeviceInput button[NUM_EDIT_BUTTONS][NUM_EDIT_TO_DEVICE_SLOTS]; DeviceInput hold[NUM_EDIT_BUTTONS][NUM_EDIT_TO_DEVICE_SLOTS]; void Clear() { FOREACH_EditButton(e) for( int slot = 0; slot < NUM_EDIT_TO_DEVICE_SLOTS; ++slot ) { button[e][slot].MakeInvalid(); hold[e][slot].MakeInvalid(); } } }; class ScreenEdit : public ScreenWithMenuElements { public: ScreenEdit( CString sName ); virtual void Init(); virtual ~ScreenEdit(); virtual void Update( float fDeltaTime ); virtual void DrawPrimitives(); virtual void Input( const InputEventPlus &input ); void InputEdit( const InputEventPlus &input, EditButton EditB ); void InputRecord( const InputEventPlus &input, EditButton EditB ); void InputRecordPaused( const InputEventPlus &input, EditButton EditB ); void InputPlay( const InputEventPlus &input, EditButton EditB ); virtual void HandleScreenMessage( const ScreenMessage SM ); protected: virtual ScreenType GetScreenType() const { return m_EditState==STATE_PLAYING ? gameplay : system_menu; } void TransitionEditState( EditState em ); void ScrollTo( float fDestinationBeat ); void PlayTicks(); void PlayPreviewMusic(); // Call this before modifying m_NoteDataEdit. void SaveUndo(); // Revert m_NoteDataEdit using m_Undo. void Undo(); // Call this after modifying m_NoteDataEdit. It will Undo() if // MAX_NOTES_PER_MEASURE was exceeded. void CheckNumberOfNotesAndUndo(); void OnSnapModeChange(); void MenuItemGainFocus( BitmapText* menuitem ); void MenuItemLoseFocus( BitmapText* menuitem ); float GetMaximumBeatForNewNote() const; // don't allow Down key to go past this beat. float GetMaximumBeatForMoving() const; // don't allow Down key to go past this beat. EditState m_EditState; Song* m_pSong; Steps* m_pSteps; PlayerState m_PlayerStateEdit; NoteField m_NoteFieldEdit; NoteData m_NoteDataEdit; SnapDisplay m_SnapDisplay; BitmapText m_textInputTips; void UpdateTextInfo(); BitmapText m_textInfo; // status information that changes bool m_bTextInfoNeedsUpdate; BitmapText m_textPlayRecordHelp; // keep track of where we are and what we're doing float m_fTrailingBeat; // this approaches GAMESTATE->m_fSongBeat, which is the actual beat /* The location we were at when shift was pressed, or * -1 when shift isn't pressed: */ int m_iShiftAnchor; NoteData m_Clipboard; bool m_bHasUndo; NoteData m_Undo; RageSound m_soundAddNote; RageSound m_soundRemoveNote; RageSound m_soundChangeLine; RageSound m_soundChangeSnap; RageSound m_soundMarker; RageSound m_soundSwitch; RageSound m_soundSave; // used for reverting void CopyToLastSave(); void CopyFromLastSave(); void RevertFromDisk(); Song m_songLastSave; Steps m_stepsLastSave; // for MODE_RECORD NoteField m_NoteFieldRecord; NoteData m_NoteDataRecord; RageTimer m_RemoveNoteButtonLastChanged; bool m_bRemoveNoteButtonDown; // for MODE_PLAY void SetupCourseAttacks(); Player m_Player; Background m_Background; Foreground m_Foreground; bool m_bReturnToRecordMenuAfterPlay; // for MODE_RECORD and MODE_PLAY int m_iStartPlayingAt, m_iStopPlayingAt; float m_fBeatToReturnTo; RageSound m_soundMusic; RageSound m_soundAssistTick; ThemeMetricEnum EDIT_MODE; public: enum MainMenuChoice { edit_steps_information, play_whole_song, play_current_beat_to_end, save, revert_to_last_save, revert_from_disk, options, edit_song_info, edit_bpm, edit_stop, play_preview_music, exit, save_on_exit, NUM_MAIN_MENU_CHOICES, MAIN_MENU_CHOICE_INVALID }; void HandleMainMenuChoice( MainMenuChoice c, const vector &iAnswers ); void HandleMainMenuChoice( MainMenuChoice c ) { const vector v; HandleMainMenuChoice( c, v ); } MainMenuChoice m_CurrentAction; enum AreaMenuChoice { cut, copy, paste_at_current_beat, paste_at_begin_marker, clear, quantize, turn, transform, alter, tempo, play, record, insert_and_shift, delete_and_shift, shift_pauses_forward, shift_pauses_backward, convert_beat_to_pause, convert_pause_to_beat, undo, NUM_AREA_MENU_CHOICES }; void HandleAreaMenuChoice( AreaMenuChoice c, const vector &iAnswers, bool bAllowUndo = true ); void HandleAreaMenuChoice( AreaMenuChoice c, bool bAllowUndo = true ) { const vector v; HandleAreaMenuChoice( c, v, bAllowUndo ); } enum TurnType { left, right, mirror, shuffle, super_shuffle, NUM_TURN_TYPES }; enum TransformType { noholds, nomines, little, wide, big, quick, skippy, add_mines, echo, stomp, planted, floored, twister, nojumps, nohands, noquads, nostretch, NUM_TRANSFORM_TYPES }; enum AlterType { autogen_to_fill_width, backwards, swap_sides, copy_left_to_right, copy_right_to_left, clear_left, clear_right, collapse_to_one, collapse_left, shift_left, shift_right, NUM_ALTER_TYPES }; enum TempoType { compress_2x, compress_3_2, compress_4_3, expand_4_3, expand_3_2, expand_2x, NUM_TEMPO_TYPES }; enum StepsInformationChoice { difficulty, meter, description, predict_meter, tap_notes, jumps, hands, quads, holds, mines, stream, voltage, air, freeze, chaos, NUM_STEPS_INFORMATION_CHOICES }; void HandleStepsInformationChoice( StepsInformationChoice c, const vector &iAnswers ); enum SongInformationChoice { main_title, sub_title, artist, credit, main_title_transliteration, sub_title_transliteration, artist_transliteration, NUM_SONG_INFORMATION_CHOICES }; void HandleSongInformationChoice( SongInformationChoice c, const vector &iAnswers ); enum BGChangeChoice { layer, rate, transition, effect, color1, color2, file1_type, file1_song_bganimation, file1_song_movie, file1_song_still, file1_global_bganimation, file1_global_movie, file1_global_movie_song_group, file1_global_movie_song_group_and_genre, file2_type, file2_song_bganimation, file2_song_movie, file2_song_still, file2_global_bganimation, file2_global_movie, file2_global_movie_song_group, file2_global_movie_song_group_and_genre, delete_change, NUM_BGCHANGE_CHOICES }; void HandleBGChangeChoice( BGChangeChoice c, const vector &iAnswers ); enum CourseAttackChoice { duration, set_mods, remove, NUM_CourseAttackChoice }; void InitEditMappings(); bool DeviceToEdit( DeviceInput DeviceI, EditButton &button ) const; bool EditToDevice( EditButton button, int iSlotNum, DeviceInput &DeviceI ) const; bool EditPressed( EditButton button, const DeviceInput &DeviceI ); bool EditIsBeingPressed( EditButton button ) const; const MapEditToDI *GetCurrentMap() const; MapEditToDI m_EditMappings, m_PlayMappings, m_RecordMappings, m_RecordPausedMappings; void MakeFilteredMenuDef( const MenuDef* pDef, MenuDef &menu ); ScreenMiniMenu *LoadEditMiniMenu( const MenuDef* pDef ); void EditMiniMenu( ScreenMiniMenu *pScreen, ScreenMessage SM_SendOnOK = SM_None, ScreenMessage SM_SendOnCancel = SM_None, const MenuDef* pDef = NULL ); ScreenMiniMenu *m_pHelpMenu; ScreenMiniMenu *m_pMiniMenu; ScreenMiniMenu *m_pMainMenu; ScreenMiniMenu *m_pAreaMenu; ScreenMiniMenu *m_pStepsInformation; ScreenMiniMenu *m_pSongInformation; ScreenMiniMenu *m_pBackgroundChangeMenu; ScreenMiniMenu *m_pInsertTapAttackMenu; ScreenMiniMenu *m_pInsertCourseAttackMenu; ScreenMiniMenu *m_pCourseModeMenu; Screen *m_pScreenOptions; }; #endif /* * (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. */