From 703ab3d7527a059c75094938d6b6f833b66e636f Mon Sep 17 00:00:00 2001 From: ansstuff Date: Fri, 16 Dec 2011 19:05:58 +0000 Subject: [PATCH] * changed ".tas" extension to ".fm3" * Tasedit: Markers notes (strings) * Tasedit: editing Marker notes, 2 text fields * Tasedit: View->Follow Marker Note context * Tasedit: View->Display Branch Tooltips * Tasedit: new accelerators: Ctrl-PgUp/Ctrl-PgDn/Shift-PgUp/Shift-PgDn * Tasedit: Config->Allow keyboard controls in Listview --- changelog.txt | 41 +- src/driver.h | 2 +- src/drivers/sdl/gui.cpp | 2 +- src/drivers/sdl/input.cpp | 4 +- src/drivers/sdl/sdl.cpp | 4 +- src/drivers/win/config.cpp | 10 +- src/drivers/win/main.cpp | 2 +- src/drivers/win/replay.cpp | 8 +- src/drivers/win/res.rc | 29 +- src/drivers/win/resource.h | 20 +- src/drivers/win/tasedit.cpp | 380 ++++++++++++++---- src/drivers/win/tasedit.h | 11 +- src/drivers/win/taseditlib/bookmarks.cpp | 24 +- src/drivers/win/taseditlib/inputhistory.cpp | 166 ++++---- src/drivers/win/taseditlib/inputhistory.h | 2 + src/drivers/win/taseditlib/inputsnapshot.cpp | 77 +--- src/drivers/win/taseditlib/inputsnapshot.h | 8 +- src/drivers/win/taseditlib/markers.cpp | 281 ++++++++++--- src/drivers/win/taseditlib/markers.h | 31 +- src/drivers/win/taseditlib/playback.cpp | 96 ++++- src/drivers/win/taseditlib/playback.h | 7 + src/drivers/win/taseditlib/recorder.cpp | 11 + src/drivers/win/taseditlib/recorder.h | 3 +- .../win/taseditlib/screenshot_display.cpp | 134 ++++-- .../win/taseditlib/screenshot_display.h | 13 +- src/drivers/win/taseditlib/tasedit_list.cpp | 51 ++- src/drivers/win/taseditlib/tasedit_list.h | 4 +- src/drivers/win/taseditlib/tasedit_sel.cpp | 104 ++++- src/drivers/win/taseditlib/tasedit_sel.h | 13 +- src/drivers/win/taseditlib/taseditproj.cpp | 45 ++- src/drivers/win/taseditlib/taseditproj.h | 6 +- src/drivers/win/window.cpp | 17 +- src/input.cpp | 1 + 33 files changed, 1199 insertions(+), 408 deletions(-) diff --git a/changelog.txt b/changelog.txt index 50e508eb..c0ce33b4 100644 --- a/changelog.txt +++ b/changelog.txt @@ -1,4 +1,29 @@ +16-dec-2011 - AnS - Tasedit: new accelerators: Ctrl-PgUp/Ctrl-PgDn/Shift-PgUp/Shift-PgDn; Config->Allow keyboard controls in Listview +16-dec-2011 - AnS - Tasedit: View->Display Branch Tooltips +16-dec-2011 - AnS - Tasedit: Markers notes; View->Follow Marker Note context +16-dec-2011 - AnS - changed ".tas" extension to ".fm3" +10-dec-2011 - AnS - loading TAS Editor projects by drag-n-drop +10-dec-2011 - AnS - Tasedit: File->Save Compact dialog +09-dec-2011 - AnS - Replaying TAS Editor project files in FCEUX (win32 and SDL) +07-dec-2011 - AnS - disabled changing PPU/PAL/input_type when Taseditor is engaged +07-dec-2011 - AnS - Tasedit: File->Recent projects +07-dec-2011 - AnS - enhanced Reload hotkey (Ctrl-F1), now it loads last ROM or last TAS Editor project +05-dec-2011 - AnS - Tasedit: Import input, Export to FM2 +04-dec-2011 - AnS - Tasedit: branches autofind best parent, "Set Marker"/"Remove marker" in context menu, checking clipboard at selection.init() and retrieving info +29-nov-2011 - AnS - Tasedit: MsgBox about not working with movies starting from savestate +26-nov-2011 - aquanull - win32: fixed graphic-tearing WITH vertical sync enabled in windowed mode. It used to wait for V-Blank too early so that the V-Blank would end too soon before the blitting could be finished. +26-nov-2011 - AnS - Fixed crash when using machine with no sound card +26-nov-2011 - zeromus - Fixed wrong default palette entry +25-nov-2011 - zeromus - add nestopia palette files +25-nov-2011 - AnS - Tasedit: selection << and >>, Turbo Seek checkbox, PasteInsert, Config->Superimpose affects copy/paste, Editing info texts +23-nov-2011 - zeromus - fix [3441099] printf bug in SwapSaveState() +21-nov-2011 - AnS - Tasedit: multitrack recording, "Superimpose" checkbox, Config->Use 1P keys for all single recordings, Config->Combine consecutive Recordings +19-nov-2011 - AnS - Tasedit: selection strobe, soft reset and power switch messages, messages when saving/loading Branches +17-nov-2011 - AnS - Tasedit: selection history, undo/redo, Reselect Clipboard, saving/loading selection history to .tas +17-nov-2011 - AnS - Tasedit: input hotchanges +14-nov-2011 - zeromus - straighten out bandai m159/m016 handling and add valid null-EEPROM emulation to get those games booting. +12-nov-2011 - adelikat - win32 - cheat search - slight GUI tweak 12-nov-2011 - AnS - Tasedit: project autosaving 10-nov-2011 - AnS - Tasedit: Branches show saved screenshot on mouseover (alpha-fade popup window) 7-nov-2011 - AnS - Tasedit: Drawing Branches Tree (using GDI), animations, transitions, mouseover @@ -6,7 +31,7 @@ 1-nov-2011 - zeromus - debugger - fix mysterious out of bounds condition while editing breakpoints 31-oct-2011 - zeromus - add winapi lua library 31-oct-2011 - zeromus - fix newppu bug; chr ram was not getting initialized to anything -28-oct-2011 - AnS - Switching Tasedit Bg input on/off when Tasedit gets/loses focus (allows FCEUX control without "Bg input") +28-oct-2011 - AnS - Switching Tasedit Bg input on/off when Tasedit gets/loses focus 27-oct-2011 - AnS - "Toggle Rerecord Display" hotkey (M), "Play Movie From Beginning" hotkey also works in Tasedit 27-oct-2011 - AnS - Tasedit: Bookmarks/Branches 23-oct-2011 - prg318 - sdl: fix a bug where alt key would get "stuck" when alt tabbing to window @@ -35,7 +60,7 @@ 28-sept-2011 - CaH4e3 - resetexstate crash fix 27-sept-2011 - AnS - Fixed old bug with "Play Movie From Beginning" 26-sept-2011 - AnS - added support for "Enable HUD recording" option to SDL version -25-sept-2011 - AnS - Tasedit: progressbar; holding "<" and ">" buttons; Ctrl-Delete bugfix +25-sept-2011 - AnS - Tasedit: progressbar; holding "<" and ">" buttons 25-sept-2011 - zeromus - newppu-fix bug in scroll reg logic causing mis-scrolls in p'radikus conflict 24-sept-2011 - CaH4e3 - latest mapper changes; code/data logger now can log data access from the RAM code; the new button to save unused data to the code/data logger 24-sept-2011 - AnS - Tasedit: changed control scheme to single click instead of double click @@ -45,17 +70,19 @@ 23-sept-2011 - AnS - Config->Movie options->Always suggest Read-Only replay (for Replay dialog) 22-sept-2011 - AnS - deleted "Lag Counter Reset" hotkey; added "Open TAS Edit" hotkey 22-sept-2011 - AnS - fixed long "savestate" messages containing path -22-sept-2011 - AnS - Tasedit: auto clear "Disable speed throttling" and "Run in background", auto set "Set high-priority thread" when entering TASEdit; FCEUX runs in bg when TASEdit has focus; Config->"Mute Turbo" check (same as in Config->Sound) +22-sept-2011 - AnS - Tasedit: auto clear "Disable speed throttling" and "Run in background", auto set "Set high-priority thread" when entering TASEdit; FCEUX runs in bg when TASEdit has focus; Config->"Mute Turbo" check 19-sept-2011 - AnS - Tasedit: accelerator table; Config->"Set greenzone capacity"; pauseframe is shown by flashing color 18-sept-2011 - zeromus - datalatch mapper-fix bug where wramless games would be able to do something mysterious to unmapped host emulator memory -17-sept-2011 - AnS - Tasedit: forced read-only behaviour when seeking or holding turbo; "Auto-restore last position" checkbox in playback controls; also fixed item drawing method, no more flicker and slowdowns +17-sept-2011 - AnS - Tasedit: forced read-only behaviour when seeking or holding turbo +17-sept-2011 - AnS - Tasedit: "Auto-restore last position" checkbox in playback controls +17-sept-2011 - AnS - Tasedit: fixed item drawing method, no more flicker and slowdowns 12-sept-2011 - prg318 - sdl: rename InputType to CurInputType due to variable of same name in src/movie.h -12-sept-2011 - AnS - Tasedit: rewrote project save/load functions; various bugfixes; Added string "Tweak Count" to Replay loading dialog -6-sept-2011 - AnS - Tasedit: red lines for lag frames; different method of accounting tweakCount +12-sept-2011 - AnS - Tasedit: rewrote project save/load functions, various bugfixes +6-sept-2011 - AnS - Tasedit: red lines for lag frames 6-sept-2011 - AnS - fixed bug when trying to open Replay dialog without having ROM loaded 3-sept-2011 - AnS - Tasedit: tweaks and bugfixes 3-sept-2011 - CaH4e3 - fixed bus conflict emulation, no kage no densetsu bug anymore -31-Aug-2011 - AnS - Tasedit: Added 4 pads support; also now current frame is shown by blue line; minor cleanups. +31-Aug-2011 - AnS - Tasedit: Added 4 pads support; also now current frame is shown by blue line; minor cleanups 30-Aug-2011 - mart0258 - Ram Search updates list when emulator is paused (on Power, or when resetting search) 25-Aug-2011 - zeromus - win32: fix context menus to use rightclicks in context menus correctly 19-Aug-2011 - CaH4e3 - PAL/NTSC noise fixed diff --git a/src/driver.h b/src/driver.h index ffa5bd6a..8fb6e27d 100644 --- a/src/driver.h +++ b/src/driver.h @@ -211,7 +211,7 @@ void FCEUI_CheatSearchSetCurrentAsOriginal(void); #define FCEUIOD_MOVIES 6 //.fm2 files #define FCEUIOD_MEMW 7 //memory watch fiels #define FCEUIOD_BBOT 8 //basicbot, obsolete -#define FCEUIOD_MACRO 9 //macro files - tasedit, currently not implemented +#define FCEUIOD_MACRO 9 //macro files - old tasedit v0.1 paradigm, not implemented, probably obsolete #define FCEUIOD_INPUT 10 //input presets #define FCEUIOD_LUA 11 //lua scripts #define FCEUIOD_AVI 12 //default file for avi output diff --git a/src/drivers/sdl/gui.cpp b/src/drivers/sdl/gui.cpp index 1e1b71cd..c6644e8a 100644 --- a/src/drivers/sdl/gui.cpp +++ b/src/drivers/sdl/gui.cpp @@ -1296,7 +1296,7 @@ void loadMovie () filterMovies = gtk_file_filter_new(); gtk_file_filter_add_pattern(filterMovies, "*.fm2"); gtk_file_filter_add_pattern(filterMovies, "*.FM2f"); - gtk_file_filter_add_pattern(filterMovies, "*.tas"); + gtk_file_filter_add_pattern(filterMovies, "*.fm3"); gtk_file_filter_set_name(filterMovies, "FM2 Movies, TAS Editor Projects"); filterFm2 = gtk_file_filter_new(); diff --git a/src/drivers/sdl/input.cpp b/src/drivers/sdl/input.cpp index 501cd888..bb94e590 100644 --- a/src/drivers/sdl/input.cpp +++ b/src/drivers/sdl/input.cpp @@ -512,14 +512,14 @@ KeyboardCommands() fname = GetFilename("Open FM2 movie for playback...", false, "FM2 movies|*.fm2"); if(fname != "") { - if(fname.find(".fm2") != std::string::npos || fname.find(".tas") != std::string::npos) + if(fname.find(".fm2") != std::string::npos || fname.find(".fm3") != std::string::npos) { FCEUI_printf("Playing back movie located at %s\n", fname.c_str()); FCEUI_LoadMovie(fname.c_str(), false, false); } else { - FCEUI_printf("Only .fm2 and .tas movies are supported.\n"); + FCEUI_printf("Only .fm2 and .fm3 movies are supported.\n"); } } } else { diff --git a/src/drivers/sdl/sdl.cpp b/src/drivers/sdl/sdl.cpp index dcdd9710..cb780064 100644 --- a/src/drivers/sdl/sdl.cpp +++ b/src/drivers/sdl/sdl.cpp @@ -104,7 +104,7 @@ Option Value Description\n\ --soundbufsize x Set sound buffer size to x ms.\n\ --volume {0-256} Set volume to x.\n\ --soundrecord f Record sound to file f.\n\ ---playmov f Play back a recorded FCM/FM2/TAS movie from filename f.\n\ +--playmov f Play back a recorded FCM/FM2/FM3 movie from filename f.\n\ --pauseframe x Pause movie playback at frame x.\n\ --fcmconvert f Convert fcm movie file f to fm2.\n\ --ripsubs f Convert movie's subtitles to srt\n\ @@ -798,7 +798,7 @@ int main(int argc, char *argv[]) g_config->setOption("SDL.Movie", ""); if (s != "") { - if(s.find(".fm2") != std::string::npos || s.find(".tas") != std::string::npos) + if(s.find(".fm2") != std::string::npos || s.find(".fm3") != std::string::npos) { static int pauseframe; g_config->getOption("SDL.PauseFrame", &pauseframe); diff --git a/src/drivers/win/config.cpp b/src/drivers/win/config.cpp index e31106b4..6d4451aa 100644 --- a/src/drivers/win/config.cpp +++ b/src/drivers/win/config.cpp @@ -74,10 +74,12 @@ extern bool TASEdit_turbo_seek; extern bool TASEdit_show_lag_frames; extern bool TASEdit_show_markers; extern bool TASEdit_show_branch_screenshots; +extern bool TASEdit_show_branch_tooltips; extern bool TASEdit_bind_markers; extern bool TASEdit_use_1p_rec; extern bool TASEdit_combine_consecutive_rec; extern bool TASEdit_superimpose_affects_paste; +extern bool TASEdit_keyboard_for_listview; extern bool TASEdit_branch_full_movie; extern bool TASEdit_branch_only_when_rec; extern bool TASEdit_view_branches_tree; @@ -89,14 +91,15 @@ extern int TASEdit_greenzone_capacity; extern int TasEdit_undo_levels; extern int TASEdit_autosave_period; extern bool TASEdit_jump_to_undo; +extern bool TASEdit_follow_note_context; extern int TASEdit_last_export_type; extern bool TASEdit_savecompact_binary; extern bool TASEdit_savecompact_markers; extern bool TASEdit_savecompact_bookmarks; extern bool TASEdit_savecompact_greenzone; extern bool TASEdit_savecompact_history; -extern bool TASEdit_savecompact_selection; extern bool TASEdit_savecompact_list; +extern bool TASEdit_savecompact_selection; extern char* recent_projects[]; //window positions and sizes: @@ -331,10 +334,12 @@ static CFGSTRUCT fceuconfig[] = { AC(TASEdit_show_lag_frames), AC(TASEdit_show_markers), AC(TASEdit_show_branch_screenshots), + AC(TASEdit_show_branch_tooltips), AC(TASEdit_bind_markers), AC(TASEdit_use_1p_rec), AC(TASEdit_combine_consecutive_rec), AC(TASEdit_superimpose_affects_paste), + AC(TASEdit_keyboard_for_listview), AC(TASEdit_branch_full_movie), AC(TASEdit_branch_only_when_rec), AC(TASEdit_view_branches_tree), @@ -346,14 +351,15 @@ static CFGSTRUCT fceuconfig[] = { AC(TasEdit_undo_levels), AC(TASEdit_autosave_period), AC(TASEdit_jump_to_undo), + AC(TASEdit_follow_note_context), AC(TASEdit_last_export_type), AC(TASEdit_savecompact_binary), AC(TASEdit_savecompact_markers), AC(TASEdit_savecompact_bookmarks), AC(TASEdit_savecompact_greenzone), AC(TASEdit_savecompact_history), - AC(TASEdit_savecompact_selection), AC(TASEdit_savecompact_list), + AC(TASEdit_savecompact_selection), AC(lagCounterDisplay), AC(oldInputDisplay), AC(movieSubtitles), diff --git a/src/drivers/win/main.cpp b/src/drivers/win/main.cpp index 1cf8304a..b8151466 100644 --- a/src/drivers/win/main.cpp +++ b/src/drivers/win/main.cpp @@ -403,7 +403,7 @@ void DoFCEUExit() return; #ifdef WIN32 - //If user was asked to save changes in Taseditor and chose cancel, don't close FCEUX + //If user was asked to save changes in TAS Editor and chose cancel, don't close FCEUX extern bool ExitTasEdit(); if (FCEUMOV_Mode(MOVIEMODE_TASEDIT) && !ExitTasEdit()) return; #endif diff --git a/src/drivers/win/replay.cpp b/src/drivers/win/replay.cpp index 660318ff..a4fcd209 100644 --- a/src/drivers/win/replay.cpp +++ b/src/drivers/win/replay.cpp @@ -7,7 +7,7 @@ #include "archive.h" #include "utils/xstring.h" -static const char* fm2ext[] = { "fm2", "tas", 0}; +static const char* fm2ext[] = { "fm2", "fm3", 0}; int MetaPosX,MetaPosY; @@ -552,12 +552,12 @@ BOOL CALLBACK ReplayDialogProc(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lP //TODO - a big copy/pasted block below. factor out extension extractor or use another one - // filter out everything that's not an extension we like (*.fm2 and *.tas) + // filter out everything that's not an extension we like (*.fm2 and *.fm3) // (because FindFirstFile is too dumb to do that) { std::string ext = getExtension(wfd.cFileName); if(ext != "fm2") - if(ext != "tas") + if(ext != "fm3") if(ext != "zip") if(ext != "rar") if(ext != "7z") @@ -665,7 +665,7 @@ BOOL CALLBACK ReplayDialogProc(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lP memset(&ofn, 0, sizeof(ofn)); ofn.lStructSize = sizeof(ofn); ofn.hwndOwner = hwndDlg; - ofn.lpstrFilter = "FCEUX Movie Files (*.fm2), TAS Editor Projects (*.tas)\0*.fm2;*.tas\0FCEUX Movie Files (*.fm2)\0*.fm2\0Archive Files (*.zip,*.rar,*.7z)\0*.zip;*.rar;*.7z\0All Files (*.*)\0*.*\0\0"; + ofn.lpstrFilter = "FCEUX Movie Files (*.fm2), TAS Editor Projects (*.fm3)\0*.fm2;*.fm3\0FCEUX Movie Files (*.fm2)\0*.fm2\0Archive Files (*.zip,*.rar,*.7z)\0*.zip;*.rar;*.7z\0All Files (*.*)\0*.*\0\0"; ofn.lpstrFile = szFile; ofn.nMaxFile = sizeof(szFile); ofn.lpstrInitialDir = pn; diff --git a/src/drivers/win/res.rc b/src/drivers/win/res.rc index 7534ee79..7ef506f1 100644 --- a/src/drivers/win/res.rc +++ b/src/drivers/win/res.rc @@ -248,9 +248,9 @@ BEGIN MENUITEM SEPARATOR MENUITEM "C&lear\tDel", ID_EDIT_CLEAR MENUITEM "&Delete\tCtrl+Del", ID_TASEDIT_DELETE - MENUITEM "&Insert\tCtrl+Ins", ID_EDIT_INSERTFRAMES + MENUITEM "Cl&one\tCtrl+Ins", ID_EDIT_CLONEFRAMES + MENUITEM "&Insert\tShift+Ins", ID_EDIT_INSERTFRAMES MENUITEM "Insert # of Frames\tIns", ID_EDIT_INSERT - MENUITEM "Cl&one\tShift+Ins", ID_EDIT_CLONEFRAMES MENUITEM SEPARATOR MENUITEM "Truncate\tCtrl+T", ID_EDIT_TRUNCATE END @@ -259,9 +259,11 @@ BEGIN MENUITEM "Show &Lag Frames", ID_VIEW_SHOW_LAG_FRAMES MENUITEM "Highlight &Markers", ID_VIEW_SHOW_MARKERS MENUITEM "Display Branch &Screenshots", ID_VIEW_SHOWBRANCHSCREENSHOTS + MENUITEM "Display Branch &Tooltips", ID_VIEW_SHOWBRANCHTOOLTIPS MENUITEM "Enable Hot &Changes", ID_VIEW_ENABLEHOTCHANGES MENUITEM SEPARATOR MENUITEM "&Follow undo context", ID_VIEW_JUMPWHENMAKINGUNDO + MENUITEM "Follow Marker &Note context", ID_VIEW_FOLLOWMARKERNOTECONTEXT END POPUP "&Config" BEGIN @@ -278,6 +280,7 @@ BEGIN MENUITEM "&Combine consecutive Recordings", ID_CONFIG_COMBINECONSECUTIVERECORDINGS MENUITEM "&Use 1P keys for all single Recordings", ID_CONFIG_USE1PFORRECORDING MENUITEM "&Superimpose affects copy/paste", ID_CONFIG_SUPERIMPOSE_AFFECTS_PASTE + MENUITEM "Allow &keyboard controls in Listview", ID_CONFIG_KEYBOARDCONTROLSINLISTVIEW MENUITEM SEPARATOR MENUITEM "Mute &Turbo", ID_CONFIG_MUTETURBO END @@ -1386,8 +1389,8 @@ BEGIN CONTROL " Follow cursor",CHECK_FOLLOW_CURSOR,"Button",BS_AUTOCHECKBOX,316,26,56,12 CONTROL " Auto-restore last position",CHECK_AUTORESTORE_PLAYBACK, "Button",BS_AUTOCHECKBOX,316,49,105,12 - GROUPBOX " Recording ",IDC_STATIC,310,64,123,48,BS_CENTER,WS_EX_RIGHT - GROUPBOX " Editing ",IDC_STATIC,310,113,123,35,BS_CENTER,WS_EX_RIGHT + GROUPBOX " Recorder ",IDC_STATIC,310,64,123,48,BS_CENTER,WS_EX_RIGHT + GROUPBOX " Splicer ",IDC_STATIC,310,113,123,35,BS_CENTER,WS_EX_RIGHT GROUPBOX " Bookmarks ",IDC_BOOKMARKS_BOX,310,150,123,103,BS_CENTER,WS_EX_RIGHT CONTROL "",IDC_BOOKMARKSLIST,"SysListView32",LVS_REPORT | LVS_SINGLESEL | LVS_ALIGNLEFT | LVS_OWNERDATA | LVS_NOSCROLL | LVS_NOCOLUMNHEADER | LVS_NOSORTHEADER | NOT WS_VISIBLE | WS_BORDER,315,160,113,89 CONTROL "",IDC_HISTORYLIST,"SysListView32",LVS_REPORT | LVS_SINGLESEL | LVS_SHOWSELALWAYS | LVS_NOLABELWRAP | LVS_ALIGNLEFT | LVS_OWNERDATA | LVS_NOCOLUMNHEADER | LVS_NOSORTHEADER | WS_BORDER,315,265,113,102 @@ -1399,14 +1402,14 @@ BEGIN CONTROL " 4P",IDC_RADIO6,"Button",BS_AUTORADIOBUTTON | WS_DISABLED,402,87,23,10 CONTROL " Superimpose",IDC_SUPERIMPOSE,"Button",BS_AUTO3STATE,316,100,56,10 GROUPBOX " History ",IDC_STATIC,310,255,123,116,BS_CENTER,WS_EX_RIGHT - EDITTEXT IDC_EDIT1,54,377,251,13,ES_READONLY | NOT WS_TABSTOP + EDITTEXT IDC_SELECTION_MARKER_EDIT,65,377,240,13,ES_READONLY | NOT WS_TABSTOP PUSHBUTTON "<<",TASEDIT_PREV_MARKER,315,376,23,14,NOT WS_TABSTOP PUSHBUTTON "Find",TASEDIT_FIND_BEST_MARKER,338,376,34,14,WS_DISABLED | NOT WS_TABSTOP PUSHBUTTON "Next",TASEDIT_FIND_NEXT_MARKER,372,376,34,14,WS_DISABLED | NOT WS_TABSTOP PUSHBUTTON ">>",TASEDIT_NEXT_MARKER,405,376,23,14,NOT WS_TABSTOP - RTEXT "Marker 99999",IDC_STATIC,6,379,45,10,0,WS_EX_RIGHT - RTEXT "Marker 0",IDC_STATIC,6,3,45,10,0,WS_EX_RIGHT - EDITTEXT IDC_EDIT2,54,1,251,13,ES_READONLY | NOT WS_TABSTOP + RTEXT "Marker 0",IDC_PLAYBACK_MARKER,3,3,60,10,0,WS_EX_RIGHT + RTEXT "Marker 99999",IDC_SELECTION_MARKER,3,379,60,10,0,WS_EX_RIGHT + EDITTEXT IDC_PLAYBACK_MARKER_EDIT,65,1,240,13,ES_READONLY | NOT WS_TABSTOP CONTROL "",IDC_BRANCHES_BITMAP,"Static",SS_OWNERDRAW | SS_NOTIFY | SS_REALSIZEIMAGE | NOT WS_VISIBLE,315,160,113,89 CONTROL " Turbo seek",CHECK_TURBO_SEEK,"Button",BS_AUTOCHECKBOX,379,26,50,12 CONTROL "",IDC_TEXT_SELECTION_BUTTON,"Button",BS_OWNERDRAW,315,121,113,12 @@ -1438,8 +1441,8 @@ BEGIN CONTROL " Bookmarks",IDC_CHECK_BOOKMARKS,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,35,36,67,10 CONTROL " Greenzone",IDC_CHECK_GREENZONE,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,35,51,67,10 CONTROL " History",IDC_CHECK_HISTORY,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,35,66,67,10 - CONTROL " Selection",IDC_CHECK_SELECTION,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,35,81,67,10 CONTROL " List data",IDC_CHECK_LIST,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,35,96,67,10 + CONTROL " Selection",IDC_CHECK_SELECTION,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,35,81,67,10 END ASSEMBLER DIALOGEX 0, 0, 202, 135 @@ -1975,6 +1978,10 @@ BEGIN BOTTOMMARGIN, 183 END + IDD_LUA, DIALOG + BEGIN + END + "VIDEOCONFIG", DIALOG BEGIN LEFTMARGIN, 10 @@ -2084,6 +2091,10 @@ BEGIN VK_INSERT, ACCEL_INS, VIRTKEY, NOINVERT VK_INSERT, ACCEL_SHIFT_INS, VIRTKEY, SHIFT, NOINVERT "V", ACCEL_SHIFT_V, VIRTKEY, SHIFT, NOINVERT + VK_PRIOR, ACCEL_CTRL_PGUP, VIRTKEY, CONTROL, NOINVERT + VK_NEXT, ACCEL_CTRL_PGDN, VIRTKEY, CONTROL, NOINVERT + VK_PRIOR, ACCEL_SHIFT_PGUP, VIRTKEY, SHIFT, NOINVERT + VK_NEXT, ACCEL_SHIFT_PGDN, VIRTKEY, SHIFT, NOINVERT END IDR_RWACCELERATOR ACCELERATORS diff --git a/src/drivers/win/resource.h b/src/drivers/win/resource.h index fc38ba26..b753d556 100644 --- a/src/drivers/win/resource.h +++ b/src/drivers/win/resource.h @@ -182,6 +182,7 @@ #define IDB_BRANCH_SPRITESHEET 184 #define IDD_TASEDIT_EXPORT 185 #define IDD_TASEDIT_SAVECOMPACT 186 +#define IDD_TASEDIT_BRANCH_NOTE 188 #define MENU_RESET 200 #define BUTTON_ROMS 200 #define TXT_PAD1 200 @@ -420,6 +421,7 @@ #define IDC_BUTTON8 1146 #define TASEDIT_FIND_BEST_MARKER 1146 #define IDC_EDIT1 1147 +#define IDC_SELECTION_MARKER_EDIT 1147 #define IDC_BUTTON9 1148 #define TASEDIT_FIND_NEXT_MARKER 1148 #define IDC_HISTORYLIST 1149 @@ -429,6 +431,7 @@ #define IDC_BRANCHES_BUTTON2 1153 #define IDC_TEXT_SELECTION_BUTTON 1153 #define IDC_EDIT2 1154 +#define IDC_PLAYBACK_MARKER_EDIT 1154 #define CHECK_SOUND_MUTETURBO 1179 #define IDC_EDIT_AUTHOR 1180 #define MEMW_STATIC 1181 @@ -552,7 +555,10 @@ #define IDC_TEXT_CLIPBOARD 1268 #define IDC_RADIO_1PLAYER 1269 #define IDC_RADIO_2PLAYERS 1270 +#define IDC_PLAYBACK_MARKER 1270 #define IDC_RADIO_FOURSCORE 1271 +#define IDC_SELECTION_MARKER 1271 +#define IDC_NOTE_TOOLTIP_EDIT 1272 #define MENU_NETWORK 40040 #define MENU_PALETTE 40041 #define MENU_SOUND 40042 @@ -934,6 +940,14 @@ #define ID_SELECTED_SETMARKER 40498 #define ID_SELECTED_CLEARMARKER 40499 #define ID_SELECTED_REMOVEMARKER40500 40500 +#define ID_CONFIG_KEYBOARDCONTROLSINLISTVIEW 40501 +#define ACCEL_CTRL_PGUP 40502 +#define ACCEL_CTRL_PGDN 40503 +#define ACCEL_SHIFT_PGUP 40504 +#define ACCEL_SHIFT_PGDN 40505 +#define ID_ACCELERATOR40506 40506 +#define ID_VIEW_FOLLOWMARKERNOTECONTEXT 40507 +#define ID_VIEW_SHOWBRANCHTOOLTIPS 40508 #define IDC_DEBUGGER_ICONTRAY 55535 #define MW_ValueLabel2 65423 #define MW_ValueLabel1 65426 @@ -942,9 +956,9 @@ // #ifdef APSTUDIO_INVOKED #ifndef APSTUDIO_READONLY_SYMBOLS -#define _APS_NEXT_RESOURCE_VALUE 187 -#define _APS_NEXT_COMMAND_VALUE 40501 -#define _APS_NEXT_CONTROL_VALUE 1270 +#define _APS_NEXT_RESOURCE_VALUE 189 +#define _APS_NEXT_COMMAND_VALUE 40509 +#define _APS_NEXT_CONTROL_VALUE 1273 #define _APS_NEXT_SYMED_VALUE 101 #endif #endif diff --git a/src/drivers/win/tasedit.cpp b/src/drivers/win/tasedit.cpp index 44ceb517..6d47cdc7 100644 --- a/src/drivers/win/tasedit.cpp +++ b/src/drivers/win/tasedit.cpp @@ -8,6 +8,7 @@ #include "help.h" #include "main.h" #include "tasedit.h" +#include "version.h" using namespace std; @@ -17,13 +18,15 @@ HMENU hmenu, hrmenu; bool TASEdit_focus = false; bool Tasedit_rewind_now = false; +int marker_note_edit = MARKER_NOTE_EDIT_NONE; + // all Taseditor functional modules TASEDIT_PROJECT project; INPUT_HISTORY history; PLAYBACK playback; RECORDER recorder; GREENZONE greenzone; -MARKERS markers; +MARKERS current_markers; BOOKMARKS bookmarks; SCREENSHOT_DISPLAY screenshot_display; TASEDIT_LIST tasedit_list; @@ -44,10 +47,12 @@ bool TASEdit_turbo_seek = true; bool TASEdit_show_lag_frames = true; bool TASEdit_show_markers = true; bool TASEdit_show_branch_screenshots = true; +bool TASEdit_show_branch_tooltips = true; bool TASEdit_bind_markers = true; bool TASEdit_use_1p_rec = true; bool TASEdit_combine_consecutive_rec = true; bool TASEdit_superimpose_affects_paste = true; +bool TASEdit_keyboard_for_listview = true; int TASEdit_superimpose = BST_UNCHECKED; bool TASEdit_branch_full_movie = true; bool TASEdit_branch_only_when_rec = false; @@ -60,14 +65,15 @@ int TASEdit_autosave_period = AUTOSAVE_PERIOD_DEFAULT; extern bool muteTurbo; bool TASEdit_enable_hot_changes = true; bool TASEdit_jump_to_undo = true; +bool TASEdit_follow_note_context = true; int TASEdit_last_export_type = EXPORT_TYPE_1P; bool TASEdit_savecompact_binary = true; bool TASEdit_savecompact_markers = true; bool TASEdit_savecompact_bookmarks = true; bool TASEdit_savecompact_greenzone = false; bool TASEdit_savecompact_history = false; -bool TASEdit_savecompact_selection = false; bool TASEdit_savecompact_list = true; +bool TASEdit_savecompact_selection = false; // Recent Menu HMENU recent_projects_menu; @@ -87,7 +93,7 @@ void UpdateTasEdit() if(!hwndTasEdit) return; tasedit_list.update(); - markers.update(); + current_markers.update(); greenzone.update(); playback.update(); recorder.update(); @@ -146,7 +152,7 @@ void RightClickMenu(LPNMITEMACTIVATE info) bool set_found = false, unset_found = false; for(SelectionFrames::iterator it(current_selection_begin); it != current_selection_end; it++) { - if(markers.GetMarker(*it)) + if(current_markers.GetMarker(*it)) set_found = true; else unset_found = true; @@ -214,11 +220,12 @@ void SingleClick(LPNMITEMACTIVATE info) if (info->uKeyFlags & LVKF_ALT) { // reverse MARKER_FLAG_BIT in pointed frame - markers.ToggleMarker(row_index); - if (markers.GetMarker(row_index)) - history.RegisterChanges(MODTYPE_MARKER_SET, row_index); + current_markers.ToggleMarker(row_index); + selection.must_find_current_marker = playback.must_find_current_marker = true; + if (current_markers.GetMarker(row_index)) + history.RegisterMarkersChange(MODTYPE_MARKER_SET, row_index); else - history.RegisterChanges(MODTYPE_MARKER_UNSET, row_index); + history.RegisterMarkersChange(MODTYPE_MARKER_UNSET, row_index); project.SetProjectChanged(); tasedit_list.RedrawRow(row_index); } @@ -266,11 +273,15 @@ void CloneFrames() // end of current region currMovieData.cloneRegion(*it, frames); if (TASEdit_bind_markers) - markers.insertEmpty(*it, frames); + current_markers.insertEmpty(*it, frames); frames = 1; } else frames++; } - markers.update(); + if (TASEdit_bind_markers) + { + current_markers.update(); + selection.must_find_current_marker = playback.must_find_current_marker = true; + } greenzone.InvalidateAndCheck(history.RegisterChanges(MODTYPE_CLONE, *current_selection->begin())); } @@ -296,11 +307,15 @@ void InsertFrames() // end of current region currMovieData.insertEmpty(*it,frames); if (TASEdit_bind_markers) - markers.insertEmpty(*it,frames); + current_markers.insertEmpty(*it,frames); frames = 1; } else frames++; } - markers.update(); + if (TASEdit_bind_markers) + { + current_markers.update(); + selection.must_find_current_marker = playback.must_find_current_marker = true; + } greenzone.InvalidateAndCheck(history.RegisterChanges(MODTYPE_INSERT, *current_selection->begin())); } @@ -325,7 +340,10 @@ void InsertNumFrames() } currMovieData.insertEmpty(index, frames); if (TASEdit_bind_markers) - markers.insertEmpty(index, frames); + { + current_markers.insertEmpty(index, frames); + selection.must_find_current_marker = playback.must_find_current_marker = true; + } // select inserted rows tasedit_list.update(); selection.SetRegionSelection(index, index + frames - 1); @@ -347,8 +365,10 @@ void DeleteFrames() { currMovieData.records.erase(currMovieData.records.begin() + *it); if (TASEdit_bind_markers) - markers.EraseMarker(*it); + current_markers.EraseMarker(*it); } + if (TASEdit_bind_markers) + selection.must_find_current_marker = playback.must_find_current_marker = true; // check if user deleted all frames if (!currMovieData.getNumRecords()) playback.StartFromZero(); @@ -396,7 +416,10 @@ void Truncate() { currMovieData.truncateAt(frame+1); if (TASEdit_bind_markers) - markers.truncateAt(frame+1); + { + current_markers.SetMarkersSize(frame+1); + selection.must_find_current_marker = playback.must_find_current_marker = true; + } tasedit_list.update(); int result = history.RegisterChanges(MODTYPE_TRUNCATE, frame+1); if (result >= 0) @@ -427,7 +450,7 @@ void FrameColumnSet() bool unset_found = false, changes_made = false; for(SelectionFrames::iterator it(current_selection_begin); it != current_selection_end; it++) { - if(!markers.GetMarker(*it)) + if(!current_markers.GetMarker(*it)) { unset_found = true; break; @@ -435,36 +458,38 @@ void FrameColumnSet() } if (unset_found) { - // set all for(SelectionFrames::iterator it(current_selection_begin); it != current_selection_end; it++) { - if(!markers.GetMarker(*it)) + if(!current_markers.GetMarker(*it)) { changes_made = true; - markers.SetMarker(*it); + current_markers.SetMarker(*it); tasedit_list.RedrawRow(*it); } } if (changes_made) - history.RegisterChanges(MODTYPE_MARKER_SET, *current_selection_begin, *current_selection->rbegin()); + history.RegisterMarkersChange(MODTYPE_MARKER_SET, *current_selection_begin, *current_selection->rbegin()); } else { // unset all for(SelectionFrames::iterator it(current_selection_begin); it != current_selection_end; it++) { - if(markers.GetMarker(*it)) + if(current_markers.GetMarker(*it)) { changes_made = true; - markers.ClearMarker(*it); + current_markers.ClearMarker(*it); tasedit_list.RedrawRow(*it); } } if (changes_made) - history.RegisterChanges(MODTYPE_MARKER_UNSET, *current_selection_begin, *current_selection->rbegin()); + history.RegisterMarkersChange(MODTYPE_MARKER_UNSET, *current_selection_begin, *current_selection->rbegin()); } if (changes_made) + { project.SetProjectChanged(); + selection.must_find_current_marker = playback.must_find_current_marker = true; + } } void InputColumnSet(int column) { @@ -606,7 +631,7 @@ bool Paste() if (currMovieData.getNumRecords() < pos+range) { currMovieData.insertEmpty(currMovieData.getNumRecords(),pos+range-currMovieData.getNumRecords()); - markers.update(); + current_markers.update(); } pGlobal = strchr(pGlobal, '\n'); @@ -702,7 +727,7 @@ bool PasteInsert() if (pGlobal[0]=='T' && pGlobal[1]=='A' && pGlobal[2]=='S') { // make sure markers have the same size as movie - markers.update(); + current_markers.update(); // init inserted_set (for input history hot changes) selection.GetInsertedSet().clear(); @@ -725,7 +750,7 @@ bool PasteInsert() if (currMovieData.getNumRecords() < pos) { currMovieData.insertEmpty(currMovieData.getNumRecords(), pos - currMovieData.getNumRecords()); - markers.update(); + current_markers.update(); } while (*frame && *frame != '\n' && *frame != '|') ++frame; @@ -737,7 +762,7 @@ bool PasteInsert() // insert new frame currMovieData.insertEmpty(pos, 1); - if (TASEdit_bind_markers) markers.insertEmpty(pos, 1); + if (TASEdit_bind_markers) current_markers.insertEmpty(pos, 1); selection.GetInsertedSet().insert(pos); // read this frame input @@ -765,7 +790,9 @@ bool PasteInsert() pGlobal = strchr(pGlobal, '\n'); } - markers.update(); + current_markers.update(); + if (TASEdit_bind_markers) + selection.must_find_current_marker = playback.must_find_current_marker = true; greenzone.InvalidateAndCheck(history.RegisterChanges(MODTYPE_PASTEINSERT, *current_selection_begin)); result = true; } @@ -785,7 +812,7 @@ void OpenProject() ofn.hwndOwner = hwndTasEdit; ofn.hInstance = fceu_hInstance; ofn.lpstrTitle = "Open TAS Editor Project"; - const char filter[] = "TAS Editor Projects (*.tas)\0*.tas\0\0"; + const char filter[] = "TAS Editor Projects (*.fm3)\0*.fm3\0All Files (*.*)\0*.*\0\0"; ofn.lpstrFilter = filter; char nameo[2048]; @@ -799,14 +826,13 @@ void OpenProject() if(GetOpenFileName(&ofn)) // If it is a valid filename { - // If they haven't put ".tas", stick it on ourselves - if (!strstr(nameo, ".tas")) - strcat(nameo, ".tas"); LoadProject(nameo); } } bool LoadProject(char* fullname) { + marker_note_edit = MARKER_NOTE_EDIT_NONE; + SetFocus(tasedit_list.hwndList); // remember to update fourscore status bool last_fourscore = currMovieData.fourscore; // try to load project @@ -851,7 +877,7 @@ void LoadRecentProject(int slot) // Saves current project bool SaveProjectAs() { - const char filter[] = "TAS Editor Projects (*.tas)\0*.tas\0All Files (*.*)\0*.*\0\0"; + const char filter[] = "TAS Editor Projects (*.fm3)\0*.fm3\0All Files (*.*)\0*.*\0\0"; OPENFILENAME ofn; memset(&ofn, 0, sizeof(ofn)); ofn.lStructSize = sizeof(ofn); @@ -869,7 +895,7 @@ bool SaveProjectAs() strncpy(nameo, project.GetProjectName().c_str(), 2047); ofn.lpstrFile = nameo; - ofn.lpstrDefExt = "tas"; + ofn.lpstrDefExt = "fm3"; ofn.nMaxFile = 2048; ofn.Flags = OFN_EXPLORER|OFN_HIDEREADONLY|OFN_OVERWRITEPROMPT; string initdir = FCEU_GetPath(FCEUMKF_MOVIE); //Initial directory @@ -901,8 +927,8 @@ void SaveCompact_GetCheckboxes(HWND hwndDlg) TASEdit_savecompact_bookmarks = (SendDlgItemMessage(hwndDlg, IDC_CHECK_BOOKMARKS, BM_GETCHECK, 0, 0) == BST_CHECKED); TASEdit_savecompact_greenzone = (SendDlgItemMessage(hwndDlg, IDC_CHECK_GREENZONE, BM_GETCHECK, 0, 0) == BST_CHECKED); TASEdit_savecompact_history = (SendDlgItemMessage(hwndDlg, IDC_CHECK_HISTORY, BM_GETCHECK, 0, 0) == BST_CHECKED); - TASEdit_savecompact_selection = (SendDlgItemMessage(hwndDlg, IDC_CHECK_SELECTION, BM_GETCHECK, 0, 0) == BST_CHECKED); TASEdit_savecompact_list = (SendDlgItemMessage(hwndDlg, IDC_CHECK_LIST, BM_GETCHECK, 0, 0) == BST_CHECKED); + TASEdit_savecompact_selection = (SendDlgItemMessage(hwndDlg, IDC_CHECK_SELECTION, BM_GETCHECK, 0, 0) == BST_CHECKED); } BOOL CALLBACK SaveCompactProc(HWND hwndDlg, UINT message, WPARAM wParam, LPARAM lParam) { @@ -916,8 +942,8 @@ BOOL CALLBACK SaveCompactProc(HWND hwndDlg, UINT message, WPARAM wParam, LPARAM CheckDlgButton(hwndDlg, IDC_CHECK_BOOKMARKS, TASEdit_savecompact_bookmarks?MF_CHECKED : MF_UNCHECKED); CheckDlgButton(hwndDlg, IDC_CHECK_GREENZONE, TASEdit_savecompact_greenzone?MF_CHECKED : MF_UNCHECKED); CheckDlgButton(hwndDlg, IDC_CHECK_HISTORY, TASEdit_savecompact_history?MF_CHECKED : MF_UNCHECKED); - CheckDlgButton(hwndDlg, IDC_CHECK_SELECTION, TASEdit_savecompact_selection?MF_CHECKED : MF_UNCHECKED); CheckDlgButton(hwndDlg, IDC_CHECK_LIST, TASEdit_savecompact_list?MF_CHECKED : MF_UNCHECKED); + CheckDlgButton(hwndDlg, IDC_CHECK_SELECTION, TASEdit_savecompact_selection?MF_CHECKED : MF_UNCHECKED); return TRUE; } case WM_COMMAND: @@ -949,7 +975,7 @@ void SaveCompact() { if (DialogBox(fceu_hInstance, MAKEINTRESOURCE(IDD_TASEDIT_SAVECOMPACT), hwndTasEdit, SaveCompactProc) > 0) { - const char filter[] = "TAS Editor Projects (*.tas)\0*.tas\0All Files (*.*)\0*.*\0\0"; + const char filter[] = "TAS Editor Projects (*.fm3)\0*.fm3\0All Files (*.*)\0*.*\0\0"; OPENFILENAME ofn; memset(&ofn, 0, sizeof(ofn)); ofn.lStructSize = sizeof(ofn); @@ -965,11 +991,12 @@ void SaveCompact() else // suggest current name strcpy(nameo, project.GetProjectName().c_str()); - // add "-compact" - strcat(nameo, "-compact"); + // add "-compact" if there's no such suffix + if (!strstr(nameo, "-compact")) + strcat(nameo, "-compact"); ofn.lpstrFile = nameo; - ofn.lpstrDefExt = "tas"; + ofn.lpstrDefExt = "fm3"; ofn.nMaxFile = 2048; ofn.Flags = OFN_EXPLORER|OFN_HIDEREADONLY|OFN_OVERWRITEPROMPT; string initdir = FCEU_GetPath(FCEUMKF_MOVIE); //Initial directory @@ -977,7 +1004,7 @@ void SaveCompact() if(GetSaveFileName(&ofn)) //If it is a valid filename { - project.save_compact(nameo, TASEdit_savecompact_binary, TASEdit_savecompact_markers, TASEdit_savecompact_bookmarks, TASEdit_savecompact_greenzone, TASEdit_savecompact_history, TASEdit_savecompact_selection, TASEdit_savecompact_list); + project.save_compact(nameo, TASEdit_savecompact_binary, TASEdit_savecompact_markers, TASEdit_savecompact_bookmarks, TASEdit_savecompact_greenzone, TASEdit_savecompact_history, TASEdit_savecompact_list, TASEdit_savecompact_selection); } } } @@ -1002,7 +1029,7 @@ bool AskSaveProject() extern bool LoadFM2(MovieData& movieData, EMUFILE* fp, int size, bool stopAfterHeader); void Import() { - const char filter[] = "FCEUX Movie Files (*.fm2), TAS Editor Projects (*.tas)\0*.fm2;*.tas\0All Files (*.*)\0*.*\0\0"; + const char filter[] = "FCEUX Movie Files (*.fm2), TAS Editor Projects (*.fm3)\0*.fm2;*.fm3\0All Files (*.*)\0*.*\0\0"; OPENFILENAME ofn; memset(&ofn, 0, sizeof(ofn)); ofn.lStructSize = sizeof(ofn); @@ -1220,6 +1247,7 @@ BOOL CALLBACK WndprocTasEdit(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lPar break; case NM_RCLICK: bookmarks.RightClick((LPNMITEMACTIVATE)lParam); + break; } break; case IDC_HISTORYLIST: @@ -1255,9 +1283,14 @@ BOOL CALLBACK WndprocTasEdit(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lPar break; case WM_ACTIVATE: if(LOWORD(wParam)) - GotFocus(); - else - LostFocus(); + { + TASEdit_focus = true; + SetTaseditInput(); + } else + { + TASEdit_focus = false; + ClearTaseditInput(); + } break; case WM_COMMAND: { @@ -1268,9 +1301,73 @@ BOOL CALLBACK WndprocTasEdit(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lPar LoadRecentProject(loword_wparam - MENU_FIRST_RECENT_PROJECT); break; } - // then check all other commands + // finally check all other commands switch(loword_wparam) { + case IDC_PLAYBACK_MARKER_EDIT: + { + switch (HIWORD(wParam)) + { + case EN_SETFOCUS: + { + marker_note_edit = MARKER_NOTE_EDIT_UPPER; + // enable editing + SendMessage(playback.hwndPlaybackMarkerEdit, EM_SETREADONLY, false, 0); + // disable FCEUX keyboard + ClearTaseditInput(); + if (TASEdit_follow_note_context) + tasedit_list.FollowPlayback(); + break; + } + case EN_KILLFOCUS: + { + if (marker_note_edit == MARKER_NOTE_EDIT_UPPER) + { + UpdateMarkerNote(); + marker_note_edit = MARKER_NOTE_EDIT_NONE; + } + // disable editing (make it grayed) + SendMessage(playback.hwndPlaybackMarkerEdit, EM_SETREADONLY, true, 0); + // enable FCEUX keyboard + if (TASEdit_focus) + SetTaseditInput(); + break; + } + } + break; + } + case IDC_SELECTION_MARKER_EDIT: + { + switch (HIWORD(wParam)) + { + case EN_SETFOCUS: + { + marker_note_edit = MARKER_NOTE_EDIT_LOWER; + // enable editing + SendMessage(selection.hwndSelectionMarkerEdit, EM_SETREADONLY, false, 0); + // disable FCEUX keyboard + ClearTaseditInput(); + if (TASEdit_follow_note_context) + tasedit_list.FollowSelection(); + break; + } + case EN_KILLFOCUS: + { + if (marker_note_edit == MARKER_NOTE_EDIT_LOWER) + { + UpdateMarkerNote(); + marker_note_edit = MARKER_NOTE_EDIT_NONE; + } + // disable editing (make it grayed) + SendMessage(selection.hwndSelectionMarkerEdit, EM_SETREADONLY, true, 0); + // enable FCEUX keyboard + if (TASEdit_focus) + SetTaseditInput(); + break; + } + } + break; + } case ID_FILE_OPENPROJECT: OpenProject(); break; @@ -1294,24 +1391,51 @@ BOOL CALLBACK WndprocTasEdit(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lPar ExitTasEdit(); break; case ID_EDIT_SELECTALL: - selection.SelectAll(); + if (marker_note_edit == MARKER_NOTE_EDIT_UPPER) + SendMessage(playback.hwndPlaybackMarkerEdit, EM_SETSEL, 0, -1); + else if (marker_note_edit == MARKER_NOTE_EDIT_LOWER) + SendMessage(selection.hwndSelectionMarkerEdit, EM_SETSEL, 0, -1); + else + selection.SelectAll(); break; case ACCEL_CTRL_X: case ID_TASEDIT_CUT: - Cut(); + if (marker_note_edit == MARKER_NOTE_EDIT_UPPER) + SendMessage(playback.hwndPlaybackMarkerEdit, WM_CUT, 0, 0); + else if (marker_note_edit == MARKER_NOTE_EDIT_LOWER) + SendMessage(selection.hwndSelectionMarkerEdit, WM_CUT, 0, 0); + else + Cut(); break; case ACCEL_CTRL_C: case ID_TASEDIT_COPY: - Copy(); + if (marker_note_edit == MARKER_NOTE_EDIT_UPPER) + SendMessage(playback.hwndPlaybackMarkerEdit, WM_COPY, 0, 0); + else if (marker_note_edit == MARKER_NOTE_EDIT_LOWER) + SendMessage(selection.hwndSelectionMarkerEdit, WM_COPY, 0, 0); + else + Copy(); break; case ACCEL_CTRL_V: case ID_TASEDIT_PASTE: - Paste(); + if (marker_note_edit == MARKER_NOTE_EDIT_UPPER) + SendMessage(playback.hwndPlaybackMarkerEdit, WM_PASTE, 0, 0); + else if (marker_note_edit == MARKER_NOTE_EDIT_LOWER) + SendMessage(selection.hwndSelectionMarkerEdit, WM_PASTE, 0, 0); + else + Paste(); break; case ACCEL_SHIFT_V: - case ID_EDIT_PASTEINSERT: PasteInsert(); break; + case ID_EDIT_PASTEINSERT: + if (marker_note_edit == MARKER_NOTE_EDIT_UPPER) + SendMessage(playback.hwndPlaybackMarkerEdit, WM_PASTE, 0, 0); + else if (marker_note_edit == MARKER_NOTE_EDIT_LOWER) + SendMessage(selection.hwndSelectionMarkerEdit, WM_PASTE, 0, 0); + else + PasteInsert(); + break; case ACCEL_CTRL_DELETE: case ID_TASEDIT_DELETE: case ID_CONTEXT_SELECTED_DELETEFRAMES: @@ -1333,7 +1457,7 @@ BOOL CALLBACK WndprocTasEdit(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lPar case ID_CONTEXT_SELECTED_INSERTFRAMES2: InsertNumFrames(); break; - case ACCEL_CTRL_INSERT: + case ACCEL_SHIFT_INS: case ID_EDIT_INSERTFRAMES: case ID_CONTEXT_SELECTED_INSERTFRAMES: InsertFrames(); @@ -1341,7 +1465,22 @@ BOOL CALLBACK WndprocTasEdit(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lPar case ACCEL_DEL: case ID_EDIT_CLEAR: case ID_CONTEXT_SELECTED_CLEARFRAMES: - ClearFrames(); + if (marker_note_edit == MARKER_NOTE_EDIT_UPPER) + { + DWORD sel_start, sel_end; + SendMessage(playback.hwndPlaybackMarkerEdit, EM_GETSEL, (WPARAM)&sel_start, (LPARAM)&sel_end); + if (sel_start == sel_end) + SendMessage(playback.hwndPlaybackMarkerEdit, EM_SETSEL, sel_start, sel_start + 1); + SendMessage(playback.hwndPlaybackMarkerEdit, WM_CLEAR, 0, 0); + } else if (marker_note_edit == MARKER_NOTE_EDIT_LOWER) + { + DWORD sel_start, sel_end; + SendMessage(selection.hwndSelectionMarkerEdit, EM_GETSEL, (WPARAM)&sel_start, (LPARAM)&sel_end); + if (sel_start == sel_end) + SendMessage(selection.hwndSelectionMarkerEdit, EM_SETSEL, sel_start, sel_start + 1); + SendMessage(selection.hwndSelectionMarkerEdit, WM_CLEAR, 0, 0); + } else + ClearFrames(); break; case TASEDIT_PLAYSTOP: playback.ToggleEmulationPause(); @@ -1383,6 +1522,11 @@ BOOL CALLBACK WndprocTasEdit(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lPar TASEdit_show_branch_screenshots ^= 1; CheckMenuItem(hmenu, ID_VIEW_SHOWBRANCHSCREENSHOTS, TASEdit_show_branch_screenshots?MF_CHECKED : MF_UNCHECKED); break; + case ID_VIEW_SHOWBRANCHTOOLTIPS: + //switch "Show Branch Screenshots" flag + TASEdit_show_branch_tooltips ^= 1; + CheckMenuItem(hmenu, ID_VIEW_SHOWBRANCHTOOLTIPS, TASEdit_show_branch_tooltips?MF_CHECKED : MF_UNCHECKED); + break; case ID_VIEW_ENABLEHOTCHANGES: TASEdit_enable_hot_changes ^= 1; CheckMenuItem(hmenu, ID_VIEW_ENABLEHOTCHANGES, TASEdit_enable_hot_changes?MF_CHECKED : MF_UNCHECKED); @@ -1392,6 +1536,10 @@ BOOL CALLBACK WndprocTasEdit(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lPar TASEdit_jump_to_undo ^= 1; CheckMenuItem(hmenu, ID_VIEW_JUMPWHENMAKINGUNDO, TASEdit_jump_to_undo?MF_CHECKED : MF_UNCHECKED); break; + case ID_VIEW_FOLLOWMARKERNOTECONTEXT: + TASEdit_follow_note_context ^= 1; + CheckMenuItem(hmenu, ID_VIEW_FOLLOWMARKERNOTECONTEXT, TASEdit_follow_note_context?MF_CHECKED : MF_UNCHECKED); + break; case ACCEL_CTRL_P: case CHECK_AUTORESTORE_PLAYBACK: //switch "Auto-restore last playback position" flag @@ -1484,6 +1632,10 @@ BOOL CALLBACK WndprocTasEdit(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lPar TASEdit_superimpose_affects_paste ^= 1; CheckMenuItem(hmenu, ID_CONFIG_SUPERIMPOSE_AFFECTS_PASTE, TASEdit_superimpose_affects_paste?MF_CHECKED : MF_UNCHECKED); break; + case ID_CONFIG_KEYBOARDCONTROLSINLISTVIEW: + TASEdit_keyboard_for_listview ^= 1; + CheckMenuItem(hmenu, ID_CONFIG_KEYBOARDCONTROLSINLISTVIEW, TASEdit_keyboard_for_listview?MF_CHECKED : MF_UNCHECKED); + break; case ID_CONFIG_MUTETURBO: muteTurbo ^= 1; CheckMenuItem(hmenu, ID_CONFIG_MUTETURBO, muteTurbo?MF_CHECKED : MF_UNCHECKED); @@ -1536,11 +1688,18 @@ BOOL CALLBACK WndprocTasEdit(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lPar CheckDlgButton(hwndTasEdit, IDC_SUPERIMPOSE, TASEdit_superimpose); break; case ACCEL_CTRL_A: + if (marker_note_edit == MARKER_NOTE_EDIT_UPPER) + SendMessage(playback.hwndPlaybackMarkerEdit, EM_SETSEL, 0, -1); + else if (marker_note_edit == MARKER_NOTE_EDIT_LOWER) + SendMessage(selection.hwndSelectionMarkerEdit, EM_SETSEL, 0, -1); + else + selection.SelectMidMarkers(); + break; case ID_EDIT_SELECTMIDMARKERS: case ID_SELECTED_SELECTMIDMARKERS: selection.SelectMidMarkers(); break; - case ACCEL_SHIFT_INS: + case ACCEL_CTRL_INSERT: case ID_EDIT_CLONEFRAMES: case ID_SELECTED_CLONE: CloneFrames(); @@ -1548,12 +1707,21 @@ BOOL CALLBACK WndprocTasEdit(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lPar case ACCEL_CTRL_Z: case ID_EDIT_UNDO: { - int result = history.undo(); - if (result >= 0) + if (marker_note_edit == MARKER_NOTE_EDIT_UPPER) { - tasedit_list.update(); - tasedit_list.FollowUndo(); - greenzone.InvalidateAndCheck(result); + SendMessage(playback.hwndPlaybackMarkerEdit, WM_UNDO, 0, 0); + } else if (marker_note_edit == MARKER_NOTE_EDIT_LOWER) + { + SendMessage(selection.hwndSelectionMarkerEdit, WM_UNDO, 0, 0); + } else + { + int result = history.undo(); + if (result >= 0) + { + tasedit_list.update(); + tasedit_list.FollowUndo(); + greenzone.InvalidateAndCheck(result); + } } break; } @@ -1605,16 +1773,17 @@ BOOL CALLBACK WndprocTasEdit(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lPar bool changes_made = false; for(SelectionFrames::iterator it(current_selection_begin); it != current_selection_end; it++) { - if(!markers.GetMarker(*it)) + if(!current_markers.GetMarker(*it)) { changes_made = true; - markers.SetMarker(*it); + current_markers.SetMarker(*it); tasedit_list.RedrawRow(*it); } } if (changes_made) { - history.RegisterChanges(MODTYPE_MARKER_SET, *current_selection_begin, *current_selection->rbegin()); + selection.must_find_current_marker = playback.must_find_current_marker = true; + history.RegisterMarkersChange(MODTYPE_MARKER_SET, *current_selection_begin, *current_selection->rbegin()); project.SetProjectChanged(); } } @@ -1630,22 +1799,38 @@ BOOL CALLBACK WndprocTasEdit(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lPar bool changes_made = false; for(SelectionFrames::iterator it(current_selection_begin); it != current_selection_end; it++) { - if(markers.GetMarker(*it)) + if(current_markers.GetMarker(*it)) { changes_made = true; - markers.ClearMarker(*it); + current_markers.ClearMarker(*it); tasedit_list.RedrawRow(*it); } } if (changes_made) { - history.RegisterChanges(MODTYPE_MARKER_UNSET, *current_selection_begin, *current_selection->rbegin()); + selection.must_find_current_marker = playback.must_find_current_marker = true; + history.RegisterMarkersChange(MODTYPE_MARKER_UNSET, *current_selection_begin, *current_selection->rbegin()); project.SetProjectChanged(); } } break; } - + case ACCEL_SHIFT_PGUP: + if (!playback.jump_was_used_this_frame) + playback.RewindFull(); + break; + case ACCEL_SHIFT_PGDN: + if (!playback.jump_was_used_this_frame) + playback.ForwardFull(); + break; + case ACCEL_CTRL_PGUP: + selection.JumpPrevMarker(); + break; + case ACCEL_CTRL_PGDN: + selection.JumpNextMarker(); + break; + + } break; } @@ -1669,11 +1854,11 @@ bool EnterTasEdit() hwndTasEdit = CreateDialog(fceu_hInstance,"TASEDIT", hAppWnd, WndprocTasEdit); if(hwndTasEdit) { + SetTaseditInput(); // save "eoptions" saved_eoptions = eoptions; // set "Run in background" eoptions |= EO_BGRUN; - GotFocus(); // "Set high-priority thread" eoptions |= EO_HIGHPRIO; DoPriority(); @@ -1694,7 +1879,9 @@ bool EnterTasEdit() CheckMenuItem(hmenu, ID_VIEW_SHOW_LAG_FRAMES, TASEdit_show_lag_frames?MF_CHECKED : MF_UNCHECKED); CheckMenuItem(hmenu, ID_VIEW_SHOW_MARKERS, TASEdit_show_markers?MF_CHECKED : MF_UNCHECKED); CheckMenuItem(hmenu, ID_VIEW_SHOWBRANCHSCREENSHOTS, TASEdit_show_branch_screenshots?MF_CHECKED : MF_UNCHECKED); + CheckMenuItem(hmenu, ID_VIEW_SHOWBRANCHTOOLTIPS, TASEdit_show_branch_tooltips?MF_CHECKED : MF_UNCHECKED); CheckMenuItem(hmenu, ID_VIEW_JUMPWHENMAKINGUNDO, TASEdit_jump_to_undo?MF_CHECKED : MF_UNCHECKED); + CheckMenuItem(hmenu, ID_VIEW_FOLLOWMARKERNOTECONTEXT, TASEdit_follow_note_context?MF_CHECKED : MF_UNCHECKED); CheckMenuItem(hmenu, ID_VIEW_ENABLEHOTCHANGES, TASEdit_enable_hot_changes?MF_CHECKED : MF_UNCHECKED); CheckMenuItem(hmenu, ID_CONFIG_BRANCHESRESTOREFULLMOVIE, TASEdit_branch_full_movie?MF_CHECKED : MF_UNCHECKED); CheckMenuItem(hmenu, ID_CONFIG_BRANCHESWORKONLYWHENRECORDING, TASEdit_branch_only_when_rec?MF_CHECKED : MF_UNCHECKED); @@ -1703,6 +1890,7 @@ bool EnterTasEdit() CheckMenuItem(hmenu, ID_CONFIG_USE1PFORRECORDING, TASEdit_use_1p_rec?MF_CHECKED : MF_UNCHECKED); CheckMenuItem(hmenu, ID_CONFIG_COMBINECONSECUTIVERECORDINGS, TASEdit_combine_consecutive_rec?MF_CHECKED : MF_UNCHECKED); CheckMenuItem(hmenu, ID_CONFIG_SUPERIMPOSE_AFFECTS_PASTE, TASEdit_superimpose_affects_paste?MF_CHECKED : MF_UNCHECKED); + CheckMenuItem(hmenu, ID_CONFIG_KEYBOARDCONTROLSINLISTVIEW, TASEdit_keyboard_for_listview?MF_CHECKED : MF_UNCHECKED); CheckMenuItem(hmenu, ID_CONFIG_MUTETURBO, muteTurbo?MF_CHECKED : MF_UNCHECKED); CheckDlgButton(hwndTasEdit,CHECK_AUTORESTORE_PLAYBACK,TASEdit_restore_position?BST_CHECKED:BST_UNCHECKED); CheckDlgButton(hwndTasEdit, IDC_SUPERIMPOSE, TASEdit_superimpose); @@ -1727,6 +1915,7 @@ bool EnterTasEdit() currMovieData.savestate.clear(); } FCEUI_StopMovie(); + currMovieData.emuVersion = FCEU_VERSION_NUMERIC; greenzone.TryDumpIncremental(lagFlag != 0); } // switch to taseditor mode @@ -1738,12 +1927,14 @@ bool EnterTasEdit() // init variables recorder.init(); tasedit_list.init(); - markers.init(); + current_markers.init(); project.init(); bookmarks.init(); screenshot_display.init(); history.init(); selection.init(); + + marker_note_edit = MARKER_NOTE_EDIT_NONE; SetFocus(history.hwndHistoryList); // set focus only once, to show selection cursor SetFocus(tasedit_list.hwndList); FCEU_DispMessage("TAS Editor engaged", 0); @@ -1759,18 +1950,16 @@ bool ExitTasEdit() DestroyWindow(hwndTasEdit); hwndTasEdit = 0; TASEdit_focus = false; + ClearTaseditInput(); // restore "eoptions" eoptions = saved_eoptions; // restore autosaves EnableAutosave = saved_EnableAutosave; DoPriority(); UpdateCheckedMenuItems(); - // clear "Background TAS Editor input" - KeyboardClearBackgroundAccessBit(KEYBACKACCESS_TASEDIT); - JoystickClearBackgroundAccessBit(JOYBACKACCESS_TASEDIT); // release memory tasedit_list.free(); - markers.free(); + current_markers.free(); greenzone.free(); bookmarks.free(); screenshot_display.free(); @@ -1784,20 +1973,59 @@ bool ExitTasEdit() return true; } -void GotFocus() +void SetTaseditInput() { - TASEdit_focus = true; // set "Background TAS Editor input" KeyboardSetBackgroundAccessBit(KEYBACKACCESS_TASEDIT); JoystickSetBackgroundAccessBit(JOYBACKACCESS_TASEDIT); } -void LostFocus() +void ClearTaseditInput() { - TASEdit_focus = false; // clear "Background TAS Editor input" KeyboardClearBackgroundAccessBit(KEYBACKACCESS_TASEDIT); JoystickClearBackgroundAccessBit(JOYBACKACCESS_TASEDIT); } + +void UpdateMarkerNote() +{ + if (!marker_note_edit) return; + char old_text[MAX_NOTE_LEN], new_text[MAX_NOTE_LEN]; + if (marker_note_edit == MARKER_NOTE_EDIT_UPPER) + { + int len = SendMessage(playback.hwndPlaybackMarkerEdit, WM_GETTEXT, MAX_NOTE_LEN, (LPARAM)new_text); + new_text[len] = 0; + // check changes + strcpy(old_text, current_markers.GetNote(playback.shown_marker).c_str()); + if (strcmp(old_text, new_text)) + { + current_markers.SetNote(playback.shown_marker, new_text); + if (playback.shown_marker) + history.RegisterMarkersChange(MODTYPE_MARKER_RENAME, current_markers.GetMarkerFrame(playback.shown_marker)); + else + // zeroth marker - just assume it's set on frame 0 + history.RegisterMarkersChange(MODTYPE_MARKER_RENAME, 0); + // notify selection to change text in lower marker (in case both are showing same marker) + selection.must_find_current_marker = true; + } + } else if (marker_note_edit == MARKER_NOTE_EDIT_LOWER) + { + int len = SendMessage(selection.hwndSelectionMarkerEdit, WM_GETTEXT, MAX_NOTE_LEN, (LPARAM)new_text); + new_text[len] = 0; + // check changes + strcpy(old_text, current_markers.GetNote(selection.shown_marker).c_str()); + if (strcmp(old_text, new_text)) + { + current_markers.SetNote(selection.shown_marker, new_text); + if (selection.shown_marker) + history.RegisterMarkersChange(MODTYPE_MARKER_RENAME, current_markers.GetMarkerFrame(selection.shown_marker)); + else + // zeroth marker - just assume it's set on frame 0 + history.RegisterMarkersChange(MODTYPE_MARKER_RENAME, 0); + // notify playback to change text in upper marker (in case both are showing same marker) + playback.must_find_current_marker = true; + } + } +} // -------------------------------------------------------------------------------------------- void UpdateRecentProjectsMenu() { diff --git a/src/drivers/win/tasedit.h b/src/drivers/win/tasedit.h index cfa5fd95..1b7b77db 100644 --- a/src/drivers/win/tasedit.h +++ b/src/drivers/win/tasedit.h @@ -14,6 +14,10 @@ #define EXPORT_TYPE_2P 1 #define EXPORT_TYPE_FOURSCORE 2 +#define MARKER_NOTE_EDIT_NONE 0 +#define MARKER_NOTE_EDIT_UPPER 1 +#define MARKER_NOTE_EDIT_LOWER 2 + enum ECONTEXTMENU { CONTEXTMENU_STRAY = 0, @@ -49,8 +53,11 @@ bool Copy(SelectionFrames* current_selection = 0); void Cut(); bool Paste(); bool PasteInsert(); -void GotFocus(); -void LostFocus(); + +void SetTaseditInput(); +void ClearTaseditInput(); + +void UpdateMarkerNote(); void UpdateRecentProjectsMenu(); void UpdateRecentProjectsArray(const char* addString); diff --git a/src/drivers/win/taseditlib/bookmarks.cpp b/src/drivers/win/taseditlib/bookmarks.cpp index 89b1bf3c..0ae1b2c6 100644 --- a/src/drivers/win/taseditlib/bookmarks.cpp +++ b/src/drivers/win/taseditlib/bookmarks.cpp @@ -14,10 +14,12 @@ WNDPROC hwndBookmarksList_oldWndProc, hwndBranchesBitmap_oldWndProc; extern SCREENSHOT_DISPLAY screenshot_display; extern PLAYBACK playback; +extern TASEDIT_SELECTION selection; extern GREENZONE greenzone; extern TASEDIT_PROJECT project; extern INPUT_HISTORY history; extern TASEDIT_LIST tasedit_list; +extern MARKERS current_markers; extern bool TASEdit_show_lag_frames; extern bool TASEdit_bind_markers; @@ -25,6 +27,8 @@ extern bool TASEdit_branch_full_movie; extern bool TASEdit_branch_only_when_rec; extern bool TASEdit_view_branches_tree; +extern void UpdateMarkerNote(); + // resources char bookmarks_save_id[BOOKMARKS_ID_LEN] = "BOOKMARKS"; char bookmarks_skipsave_id[BOOKMARKS_ID_LEN] = "BOOKMARKX"; @@ -32,11 +36,12 @@ char bookmarksCaption[3][23] = { " Bookmarks ", " Bookmarks / Branches ", " Bran // color tables for flashing when saving/loading bookmarks COLORREF bookmark_flash_colors[3][FLASH_PHASE_MAX+1] = { // set - 0x122330, 0x1b3541, 0x254753, 0x2e5964, 0x376b75, 0x417e87, 0x4a8f97, 0x53a1a8, 0x5db3b9, 0x66c5cb, 0x70d7dc, 0x79e9ed, + //0x122330, 0x1b3541, 0x254753, 0x2e5964, 0x376b75, 0x417e87, 0x4a8f97, 0x53a1a8, 0x5db3b9, 0x66c5cb, 0x70d7dc, 0x79e9ed, + 0x0d1241, 0x111853, 0x161e64, 0x1a2575, 0x1f2b87, 0x233197, 0x2837a8, 0x2c3db9, 0x3144cb, 0x354adc, 0x3a50ed, 0x3f57ff, // jump - 0x382309, 0x3c350e, 0x404814, 0x455a19, 0x486c1e, 0x4d7f23, 0x519128, 0x55a32d, 0x5ab532, 0x5ec837, 0x62da3c, 0x66ec41, + 0x14350f, 0x1c480f, 0x235a0f, 0x2a6c0f, 0x317f10, 0x38910f, 0x3fa30f, 0x46b50f, 0x4dc80f, 0x54da0f, 0x5bec0f, 0x63ff10, // unleash - 0x320d23, 0x341435, 0x361b48, 0x38215a, 0x39286c, 0x3b2f7f, 0x3c3691, 0x3e3ca3, 0x4043b5, 0x414ac8, 0x4351da, 0x4457ec }; + 0x43171d, 0x541d21, 0x652325, 0x762929, 0x872f2c, 0x983530, 0xa93b34, 0xba4137, 0xcb463b, 0xdc4c3f, 0xed5243, 0xff5947 }; // corners cursor animation int corners_cursor_shift[BRANCHES_ANIMATION_FRAMES] = {0, 1, 2, 3, 4, 5, 5, 4, 3, 2, 1, 0 }; @@ -268,6 +273,10 @@ void BOOKMARKS::update() void BOOKMARKS::set(int slot) { if (slot < 0 || slot >= TOTAL_BOOKMARKS) return; + + // First save edited note (in case it's being currently edited) + UpdateMarkerNote(); + int previous_frame = bookmarks_array[slot].snapshot.jump_frame; // save time of this slot before rewriting it char saved_time[TIME_DESC_LENGTH]; @@ -419,6 +428,7 @@ void BOOKMARKS::unleash(int slot) } if (slot < 0 || slot >= TOTAL_BOOKMARKS) return; if (!bookmarks_array[slot].not_empty) return; + int jump_frame = bookmarks_array[slot].snapshot.jump_frame; bool markers_changed = false; @@ -428,7 +438,7 @@ void BOOKMARKS::unleash(int slot) // update Markers if (TASEdit_bind_markers) { - if (bookmarks_array[slot].snapshot.checkMarkersDiff()) + if (bookmarks_array[slot].snapshot.my_markers.checkMarkersDiff(current_markers)) { bookmarks_array[slot].snapshot.copyToMarkers(); project.SetProjectChanged(); @@ -442,11 +452,13 @@ void BOOKMARKS::unleash(int slot) // restore entire movie bookmarks_array[slot].snapshot.toMovie(currMovieData, first_change); tasedit_list.update(); + selection.must_find_current_marker = playback.must_find_current_marker = true; history.RegisterBranching(MODTYPE_BRANCH_0 + slot, first_change, slot); greenzone.Invalidate(first_change); bookmarks_array[slot].unleashed(); } else if (markers_changed) { + selection.must_find_current_marker = playback.must_find_current_marker = true; history.RegisterBranching(MODTYPE_BRANCH_MARKERS_0 + slot, first_change, slot); tasedit_list.RedrawList(); bookmarks_array[slot].unleashed(); @@ -460,7 +472,7 @@ void BOOKMARKS::unleash(int slot) // update Markers if (TASEdit_bind_markers) { - if (bookmarks_array[slot].snapshot.checkMarkersDiff(jump_frame)) + if (bookmarks_array[slot].snapshot.my_markers.checkMarkersDiff(current_markers, jump_frame)) { bookmarks_array[slot].snapshot.copyToMarkers(jump_frame-1); project.SetProjectChanged(); @@ -475,11 +487,13 @@ void BOOKMARKS::unleash(int slot) if (currMovieData.getNumRecords() <= jump_frame) currMovieData.records.resize(jump_frame+1); // but if old movie is shorter, include last frame as blank frame bookmarks_array[slot].snapshot.toMovie(currMovieData, first_change, jump_frame-1); tasedit_list.update(); + selection.must_find_current_marker = playback.must_find_current_marker = true; history.RegisterBranching(MODTYPE_BRANCH_0 + slot, first_change, slot); greenzone.Invalidate(first_change); bookmarks_array[slot].unleashed(); } else if (markers_changed) { + selection.must_find_current_marker = playback.must_find_current_marker = true; history.RegisterBranching(MODTYPE_BRANCH_MARKERS_0 + slot, first_change, slot); tasedit_list.RedrawList(); bookmarks_array[slot].unleashed(); diff --git a/src/drivers/win/taseditlib/inputhistory.cpp b/src/drivers/win/taseditlib/inputhistory.cpp index eee19f8a..6564fe8e 100644 --- a/src/drivers/win/taseditlib/inputhistory.cpp +++ b/src/drivers/win/taseditlib/inputhistory.cpp @@ -12,16 +12,17 @@ extern int TasEdit_undo_levels; LRESULT APIENTRY HistoryListWndProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam); WNDPROC hwndHistoryList_oldWndProc; -extern MARKERS markers; +extern MARKERS current_markers; extern BOOKMARKS bookmarks; extern PLAYBACK playback; +extern TASEDIT_SELECTION selection; extern GREENZONE greenzone; extern TASEDIT_PROJECT project; extern TASEDIT_LIST tasedit_list; char history_save_id[HISTORY_ID_LEN] = "HISTORY"; char history_skipsave_id[HISTORY_ID_LEN] = "HISTORX"; -char modCaptions[36][20] = {" Init", +char modCaptions[37][20] = {" Init", " Change", " Set", " Unset", @@ -56,7 +57,8 @@ char modCaptions[36][20] = {" Init", " Marker Branch8 to ", " Marker Branch9 to ", " Marker Set", - " Marker Unset"}; + " Marker Unset", + " Marker Rename"}; char joypadCaptions[4][5] = {"(1P)", "(2P)", "(3P)", "(4P)"}; INPUT_HISTORY::INPUT_HISTORY() @@ -149,7 +151,7 @@ int INPUT_HISTORY::jump(int new_pos) bool markers_changed = false; if (TASEdit_bind_markers) { - if (input_snapshots[real_pos].checkMarkersDiff()) + if (input_snapshots[real_pos].my_markers.checkMarkersDiff(current_markers)) { input_snapshots[real_pos].copyToMarkers(); project.SetProjectChanged(); @@ -166,7 +168,8 @@ int INPUT_HISTORY::jump(int new_pos) // list will be redrawn by greenzone invalidation } else if (markers_changed) { - markers.update(); + current_markers.update(); + selection.must_find_current_marker = playback.must_find_current_marker = true; bookmarks.ChangesMadeSinceBranch(); tasedit_list.RedrawList(); } else if (TASEdit_enable_hot_changes) @@ -204,7 +207,7 @@ void INPUT_HISTORY::AddInputSnapshotToHistory(INPUT_SNAPSHOT &inp) // overwrite old snapshot real_pos = (history_start_pos + history_cursor_pos) % history_size; // compare with the snapshot we're going to overwrite, if it's different then truncate history after this item - if (input_snapshots[real_pos].checkDiff(inp) || input_snapshots[real_pos].checkMarkersDiff(inp)) + if (input_snapshots[real_pos].checkDiff(inp) || input_snapshots[real_pos].my_markers.checkMarkersDiff(inp.my_markers)) { history_total_items = history_cursor_pos+1; UpdateHistoryList(); @@ -237,13 +240,38 @@ int INPUT_HISTORY::RegisterChanges(int mod_type, int start, int end) INPUT_SNAPSHOT inp; inp.init(currMovieData, TASEdit_enable_hot_changes); inp.mod_type = mod_type; - if (mod_type == MODTYPE_MARKER_SET || mod_type == MODTYPE_MARKER_UNSET) + // check if there are input differences from latest snapshot + int real_pos = (history_start_pos + history_cursor_pos) % history_size; + int first_changes = inp.findFirstChange(input_snapshots[real_pos], start, end); + if (first_changes >= 0) { - // special case: changed markers, but input didn't change + // differences found // fill description: strcat(inp.description, modCaptions[mod_type]); - inp.jump_frame = start; - // add the frame to description + switch (mod_type) + { + case MODTYPE_CHANGE: + case MODTYPE_SET: + case MODTYPE_UNSET: + case MODTYPE_TRUNCATE: + case MODTYPE_CLEAR: + case MODTYPE_CUT: + { + inp.jump_frame = first_changes; + break; + } + case MODTYPE_INSERT: + case MODTYPE_DELETE: + case MODTYPE_PASTE: + case MODTYPE_PASTEINSERT: + case MODTYPE_CLONE: + { + // for these changes user prefers to see frame of attempted change (selection beginning), not frame of actual differences + inp.jump_frame = start; + break; + } + } + // add upper and lower frame to description char framenum[11]; _itoa(start, framenum, 10); strcat(inp.description, " "); @@ -254,92 +282,66 @@ int INPUT_HISTORY::RegisterChanges(int mod_type, int start, int end) strcat(inp.description, "-"); strcat(inp.description, framenum); } + // set hotchanges if (TASEdit_enable_hot_changes) - inp.copyHotChanges(&GetCurrentSnapshot()); - AddInputSnapshotToHistory(inp); - bookmarks.ChangesMadeSinceBranch(); - return -1; - } else - { - // other types of modification: - // check if there are input differences from latest snapshot - int real_pos = (history_start_pos + history_cursor_pos) % history_size; - int first_changes = inp.findFirstChange(input_snapshots[real_pos], start, end); - if (first_changes >= 0) { - // differences found - // fill description: - strcat(inp.description, modCaptions[mod_type]); + // inherit previous hotchanges and set new changes switch (mod_type) { + case MODTYPE_DELETE: + inp.inheritHotChanges_DeleteSelection(&input_snapshots[real_pos]); + break; + case MODTYPE_INSERT: + case MODTYPE_CLONE: + inp.inheritHotChanges_InsertSelection(&input_snapshots[real_pos]); + break; + case MODTYPE_PASTEINSERT: + inp.inheritHotChanges_PasteInsert(&input_snapshots[real_pos]); + break; case MODTYPE_CHANGE: case MODTYPE_SET: case MODTYPE_UNSET: - case MODTYPE_TRUNCATE: case MODTYPE_CLEAR: case MODTYPE_CUT: - { - inp.jump_frame = first_changes; - break; - } - case MODTYPE_INSERT: - case MODTYPE_DELETE: case MODTYPE_PASTE: - case MODTYPE_PASTEINSERT: - case MODTYPE_CLONE: - { - // for these changes user prefers to see frame of attempted change (selection beginning), not frame of actual differences - inp.jump_frame = start; + inp.inheritHotChanges(&input_snapshots[real_pos]); + inp.fillHotChanges(input_snapshots[real_pos], first_changes, end); + break; + case MODTYPE_TRUNCATE: + inp.copyHotChanges(&input_snapshots[real_pos]); + // do not add new hotchanges and do not fade old hotchanges, because there was nothing added break; - } } - // add upper and lower frame to description - char framenum[11]; - _itoa(start, framenum, 10); - strcat(inp.description, " "); - strcat(inp.description, framenum); - if (end > start) - { - _itoa(end, framenum, 10); - strcat(inp.description, "-"); - strcat(inp.description, framenum); - } - // set hotchanges - if (TASEdit_enable_hot_changes) - { - // inherit previous hotchanges and set new changes - switch (mod_type) - { - case MODTYPE_DELETE: - inp.inheritHotChanges_DeleteSelection(&input_snapshots[real_pos]); - break; - case MODTYPE_INSERT: - case MODTYPE_CLONE: - inp.inheritHotChanges_InsertSelection(&input_snapshots[real_pos]); - break; - case MODTYPE_PASTEINSERT: - inp.inheritHotChanges_PasteInsert(&input_snapshots[real_pos]); - break; - case MODTYPE_CHANGE: - case MODTYPE_SET: - case MODTYPE_UNSET: - case MODTYPE_CLEAR: - case MODTYPE_CUT: - case MODTYPE_PASTE: - inp.inheritHotChanges(&input_snapshots[real_pos]); - inp.fillHotChanges(input_snapshots[real_pos], first_changes, end); - break; - case MODTYPE_TRUNCATE: - inp.copyHotChanges(&input_snapshots[real_pos]); - // do not add new hotchanges and do not fade old hotchanges, because there was nothing added - break; - } - } - AddInputSnapshotToHistory(inp); - bookmarks.ChangesMadeSinceBranch(); } - return first_changes; + AddInputSnapshotToHistory(inp); + bookmarks.ChangesMadeSinceBranch(); } + return first_changes; +} +void INPUT_HISTORY::RegisterMarkersChange(int mod_type, int start, int end) +{ + // create new input shanshot + INPUT_SNAPSHOT inp; + inp.init(currMovieData, TASEdit_enable_hot_changes); + inp.mod_type = mod_type; + // fill description: + strcat(inp.description, modCaptions[mod_type]); + inp.jump_frame = start; + // add the frame to description + char framenum[11]; + _itoa(start, framenum, 10); + strcat(inp.description, " "); + strcat(inp.description, framenum); + if (end > start) + { + _itoa(end, framenum, 10); + strcat(inp.description, "-"); + strcat(inp.description, framenum); + } + if (TASEdit_enable_hot_changes) + inp.copyHotChanges(&GetCurrentSnapshot()); + AddInputSnapshotToHistory(inp); + bookmarks.ChangesMadeSinceBranch(); } void INPUT_HISTORY::RegisterBranching(int mod_type, int first_change, int slot) { diff --git a/src/drivers/win/taseditlib/inputhistory.h b/src/drivers/win/taseditlib/inputhistory.h index 9860a74f..c8c956b7 100644 --- a/src/drivers/win/taseditlib/inputhistory.h +++ b/src/drivers/win/taseditlib/inputhistory.h @@ -38,6 +38,7 @@ #define MODTYPE_BRANCH_MARKERS_9 33 #define MODTYPE_MARKER_SET 34 #define MODTYPE_MARKER_UNSET 35 +#define MODTYPE_MARKER_RENAME 36 #define HISTORY_NORMAL_COLOR 0x000000 #define HISTORY_INCOHERENT_COLOR 0x999999 @@ -63,6 +64,7 @@ public: void AddInputSnapshotToHistory(INPUT_SNAPSHOT &inp); int RegisterChanges(int mod_type, int start = 0, int end =-1); + void RegisterMarkersChange(int mod_type, int start = 0, int end =-1); void RegisterBranching(int mod_type, int first_change, int slot); void RegisterRecording(int frame_of_change); void RegisterImport(MovieData& md, char* filename); diff --git a/src/drivers/win/taseditlib/inputsnapshot.cpp b/src/drivers/win/taseditlib/inputsnapshot.cpp index 449a6096..f4adc663 100644 --- a/src/drivers/win/taseditlib/inputsnapshot.cpp +++ b/src/drivers/win/taseditlib/inputsnapshot.cpp @@ -7,7 +7,7 @@ const int bytes_per_frame[NUM_SUPPORTED_INPUT_TYPES] = {2, 4}; // so 16bits for extern void FCEU_printf(char *format, ...); -extern MARKERS markers; +extern MARKERS current_markers; extern TASEDIT_SELECTION selection; INPUT_SNAPSHOT::INPUT_SNAPSHOT() @@ -56,10 +56,10 @@ void INPUT_SNAPSHOT::init(MovieData& md, bool hotchanges, int force_input_type) } } - // make a copy of markers.markers_array - markers.MakeCopy(markers_array); - if ((int)markers_array.size() < size) - markers_array.resize(size); + // make a copy of current_markers + my_markers.MakeCopy(current_markers); + if ((int)my_markers.GetMarkersSize() < size) + my_markers.SetMarkersSize(size); coherent = true; already_compressed = false; @@ -72,7 +72,7 @@ void INPUT_SNAPSHOT::init(MovieData& md, bool hotchanges, int force_input_type) void INPUT_SNAPSHOT::copyToMarkers(int end) { - markers.RestoreFromCopy(markers_array, end); + current_markers.RestoreFromCopy(my_markers, end); } void INPUT_SNAPSHOT::toMovie(MovieData& md, int start, int end) @@ -132,13 +132,7 @@ void INPUT_SNAPSHOT::compress_data() compress(&hot_changes_compressed[0], &comprlen, &hot_changes[0], len); hot_changes_compressed.resize(comprlen); } - // compress markers - len = markers_array.size(); - comprlen = (len>>9)+12 + len; - markers_array_compressed.resize(comprlen); - compress(&markers_array_compressed[0], &comprlen, &markers_array[0], len); - markers_array_compressed.resize(comprlen); - // don't compress anymore + // don't recompress anymore already_compressed = true; } @@ -173,8 +167,7 @@ void INPUT_SNAPSHOT::save(EMUFILE *os) os->fwrite(&hot_changes_compressed[0], hot_changes_compressed.size()); } // save markers data - write32le(markers_array_compressed.size(), os); - os->fwrite(&markers_array_compressed[0], markers_array_compressed.size()); + my_markers.save(os, true); } // returns true if couldn't load bool INPUT_SNAPSHOT::load(EMUFILE *is) @@ -234,16 +227,8 @@ bool INPUT_SNAPSHOT::load(EMUFILE *is) e = uncompress(&hot_changes[0], &destlen, &hot_changes_compressed[0], comprlen); if (e != Z_OK && e != Z_BUF_ERROR) return true; } - // read and uncompress markers data - destlen = size; - markers_array.resize(destlen); - // read size - if (!read32le(&comprlen, is)) return true; - if (comprlen <= 0) return true; - markers_array_compressed.resize(comprlen); - if (is->fread(&markers_array_compressed[0], comprlen) != comprlen) return true; - e = uncompress(&markers_array[0], &destlen, &markers_array_compressed[0], comprlen); - if (e != Z_OK && e != Z_BUF_ERROR) return true; + // load markers data + if (my_markers.load(is)) return true; return false; } bool INPUT_SNAPSHOT::skipLoad(EMUFILE *is) @@ -251,11 +236,15 @@ bool INPUT_SNAPSHOT::skipLoad(EMUFILE *is) int tmp; uint8 tmp1; // read vars - if (!read32le(&tmp, is)) return true; - if (!read8le(&tmp1, is)) return true; - if (!read8le(&tmp1, is)) return true; - if (!read32le(&tmp, is)) return true; - if (!read8le(&tmp1, is)) return true; + if (is->fseek(sizeof(int) + // size + sizeof(uint8) + // input_type + sizeof(uint8) + // coherent + sizeof(int) + // jump_frame + sizeof(int) + // rec_end_frame + sizeof(int) + // rec_joypad_diff_bits + sizeof(int) + // mod_type + sizeof(uint8) // has_hot_changes + , SEEK_CUR)) return true; // read description if (!read8le(&tmp1, is)) return true; if (tmp1 >= SNAPSHOT_DESC_MAX_LENGTH) return true; @@ -273,8 +262,7 @@ bool INPUT_SNAPSHOT::skipLoad(EMUFILE *is) if (is->fseek(tmp, SEEK_CUR) != 0) return true; } // read markers data - if (!read32le(&tmp, is)) return true; - if (is->fseek(tmp, SEEK_CUR) != 0) return true; + if (my_markers.skipLoad(is)) return true; return false; } @@ -315,31 +303,6 @@ void INPUT_SNAPSHOT::fillJoypadsDiff(INPUT_SNAPSHOT& inp, int frame) } } -// return true if any difference in markers_array is found, comparing two snapshots -bool INPUT_SNAPSHOT::checkMarkersDiff(INPUT_SNAPSHOT& inp) -{ - if (size != inp.size) return true; - for (int i = size-1; i >= 0; i--) - if ((markers_array[i] - inp.markers_array[i]) & MARKER_FLAG_BIT) return true; - return false; -} -// return true if any difference in markers_array is found, comparing to markers.markers_array -bool INPUT_SNAPSHOT::checkMarkersDiff() -{ - if (markers_array.size() != markers.GetMarkersSize()) return true; - for (int i = markers_array.size()-1; i >= 0; i--) - if ((bool)(markers_array[i] & MARKER_FLAG_BIT) != markers.GetMarker(i)) return true; - return false; -} -// return true only when difference is found before end frame (not including end frame) -bool INPUT_SNAPSHOT::checkMarkersDiff(int end) -{ - if (markers_array.size() != markers.GetMarkersSize() && ((int)markers_array.size()-1 < end || (int)markers.GetMarkersSize()-1 < end)) return true; - for (int i = end-1; i >= 0; i--) - if ((bool)(markers_array[i] & MARKER_FLAG_BIT) != markers.GetMarker(i)) return true; - return false; -} - // return number of first frame of difference between two snapshots int INPUT_SNAPSHOT::findFirstChange(INPUT_SNAPSHOT& inp, int start, int end) { diff --git a/src/drivers/win/taseditlib/inputsnapshot.h b/src/drivers/win/taseditlib/inputsnapshot.h index df6768c2..8fa011f4 100644 --- a/src/drivers/win/taseditlib/inputsnapshot.h +++ b/src/drivers/win/taseditlib/inputsnapshot.h @@ -14,7 +14,6 @@ public: void init(MovieData& md, bool hotchanges, int force_input_type = -1); void toMovie(MovieData& md, int start = 0, int end = -1); - void toMarkers(); void copyToMarkers(int end = -1); void save(EMUFILE *os); @@ -24,10 +23,6 @@ public: bool checkDiff(INPUT_SNAPSHOT& inp); void fillJoypadsDiff(INPUT_SNAPSHOT& inp, int frame); - bool checkMarkersDiff(INPUT_SNAPSHOT& inp); - bool checkMarkersDiff(); - bool checkMarkersDiff(int end); - int findFirstChange(INPUT_SNAPSHOT& inp, int start = 0, int end = -1); int findFirstChange(MovieData& md, int start = 0, int end = -1); @@ -52,7 +47,7 @@ public: std::vector joysticks; // Format: joy0-for-frame0, joy1-for-frame0, joy2-for-frame0, joy3-for-frame0, joy0-for-frame1, joy1-for-frame1, ... std::vector commands; // Format: commands-for-frame0, commands-for-frame1, ... std::vector hot_changes; // Format: buttons01joy0-for-frame0, buttons23joy0-for-frame0, buttons45joy0-for-frame0, buttons67joy0-for-frame0, buttons01joy1-for-frame0, ... - std::vector markers_array; // just a copy of markers.markers_array + MARKERS my_markers; bool coherent; // indicates whether this state was made right after previous state int jump_frame; // for jumping when making undo @@ -69,7 +64,6 @@ private: std::vector joysticks_compressed; std::vector commands_compressed; std::vector hot_changes_compressed; - std::vector markers_array_compressed; }; diff --git a/src/drivers/win/taseditlib/markers.cpp b/src/drivers/win/taseditlib/markers.cpp index 3b7f345b..18b4f9fa 100644 --- a/src/drivers/win/taseditlib/markers.cpp +++ b/src/drivers/win/taseditlib/markers.cpp @@ -14,16 +14,18 @@ void MARKERS::init() { reset(); } -void MARKERS::reset() -{ - free(); - update(); -} void MARKERS::free() { markers_array.resize(0); + notes.resize(0); +} +void MARKERS::reset() +{ + free(); + notes.resize(1); + notes[0] = "Power on"; + update(); } - void MARKERS::update() { if ((int)markers_array.size() < currMovieData.getNumRecords()) @@ -40,12 +42,22 @@ void MARKERS::save(EMUFILE *os, bool really_save) int size = markers_array.size(); write32le(size, os); // compress and write array - int len = markers_array.size(); + int len = markers_array.size() * sizeof(int); uLongf comprlen = (len>>9)+12 + len; std::vector cbuf(comprlen); - compress(&cbuf[0], &comprlen, &markers_array[0], len); + compress(&cbuf[0], &comprlen, (uint8*)&markers_array[0], len); write32le(comprlen, os); os->fwrite(&cbuf[0], comprlen); + // write notes + size = notes.size(); + write32le(size, os); + for (int i = 0; i < size; ++i) + { + len = notes[i].length() + 1; + if (len > MAX_NOTE_LEN) len = MAX_NOTE_LEN; + write32le(len, os); + os->fwrite(notes[i].c_str(), len); + } } else { // write "MARKERX" string @@ -67,87 +79,221 @@ bool MARKERS::load(EMUFILE *is) } if (strcmp(markers_save_id, save_id)) goto error; // string is not valid int size; - if (read32le((uint32 *)&size, is) && size >= currMovieData.getNumRecords()) + if (read32le(&size, is)) { markers_array.resize(size); // read and uncompress array - int comprlen; - uLongf destlen = size; + int comprlen, len; + uLongf destlen = size * sizeof(int); if (!read32le(&comprlen, is)) goto error; if (comprlen <= 0) goto error; std::vector cbuf(comprlen); if (is->fread(&cbuf[0], comprlen) != comprlen) goto error; - int e = uncompress(&markers_array[0], &destlen, &cbuf[0], comprlen); + int e = uncompress((uint8*)&markers_array[0], &destlen, &cbuf[0], comprlen); if (e != Z_OK && e != Z_BUF_ERROR) goto error; - return false; + // read notes + if (read32le(&size, is) && size >= 0) + { + notes.resize(size); + char temp_str[MAX_NOTE_LEN]; + for (int i = 0; i < size; ++i) + { + if (!read32le(&len, is) || len < 0) goto error; + if ((int)is->fread(temp_str, len) < len) goto error; + notes[i] = temp_str; + } + // all ok + return false; + } } error: FCEU_printf("Error loading markers\n"); reset(); return true; } -// ---------------------------------------------------------- -void MARKERS::MakeCopy(std::vector &destination_array) +bool MARKERS::skipLoad(EMUFILE *is) { - // copy array - destination_array = markers_array; - // copy notes - + // read "MARKERS" string + char save_id[MARKERS_ID_LEN]; + if ((int)is->fread(save_id, MARKERS_ID_LEN) < MARKERS_ID_LEN) goto error; + if (!strcmp(markers_skipsave_id, save_id)) + { + // string says to skip loading Markers + reset(); + return false; + } + if (strcmp(markers_save_id, save_id)) goto error; // string is not valid + int size; + if (!(is->fseek(sizeof(int), SEEK_CUR))) + { + // read array + int comprlen, len; + if (!read32le(&comprlen, is)) goto error; + if (is->fseek(comprlen, SEEK_CUR) != 0) goto error; + // read notes + if (read32le(&size, is) && size >= 0) + { + for (int i = 0; i < size; ++i) + { + if (!read32le(&len, is) || len < 0) goto error; + if (is->fseek(len, SEEK_CUR) != 0) goto error; + } + // all ok + return false; + } + } +error: + FCEU_printf("Error skiploading markers\n"); + return true; } -void MARKERS::RestoreFromCopy(std::vector &source_array, int until_frame) +// ---------------------------------------------------------- +void MARKERS::MakeCopy(MARKERS& source) +{ + // provide references + source.CopyMarkersHere(markers_array, notes); +} +void MARKERS::CopyMarkersHere(std::vector& array_for_markers, std::vector& for_notes) +{ + // copy data to provided arrays + array_for_markers = markers_array; + for_notes = notes; +} +void MARKERS::RestoreFromCopy(MARKERS& source, int until_frame) { if (until_frame >= 0) { - // restore array up to and including the frame - if ((int)markers_array.size() <= until_frame) markers_array.resize(until_frame+1); - for (int i = until_frame; i >= 0; i--) - markers_array[i] = source_array[i]; - // restore some notes - + // restore markers up to and including the frame + if ((int)markers_array.size()-1 <= until_frame) + { + // only copy head of source + source.CopyMarkersHere(markers_array, notes); + markers_array.resize(until_frame+1); + // find last marker + int last_marker = GetMarkerUp(until_frame); + // delete all notes foolowing the note of the last marker + notes.resize(last_marker+1); + } else + { + // combine head of source and tail of destination (old markers) + // 1 - head + std::vector temp_markers_array; + std::vector temp_notes; + source.CopyMarkersHere(temp_markers_array, temp_notes); + temp_markers_array.resize(until_frame+1); + // find last marker in temp_markers_array + int last_marker, frame; + for (frame = until_frame; frame >= 0; frame--) + if (temp_markers_array[frame]) break; + if (frame >= 0) + last_marker = temp_markers_array[frame]; + else + last_marker = 0; + // delete all temp_notes foolowing the note of the last marker + temp_notes.resize(last_marker+1); + // 2 - tail + // delete all markers (and their notes) up to and including until_frame + //for (int i = until_frame; i >= 0; i--) // actually no need for that + // ClearMarker(i); + // 3 - combine head and tail (if there are actually markers left in the tail) + int size = markers_array.size(); + temp_markers_array.resize(size); + for (int i = until_frame+1; i < size; ++i) + { + if (markers_array[i]) + { + last_marker++; + temp_markers_array[i] = last_marker; + temp_notes.push_back(notes[markers_array[i]]); + } + } + // 4 - save result + markers_array = temp_markers_array; + notes = temp_notes; + } } else { - // restore array - markers_array = source_array; - // restore notes - + // frame not specified, consider this as "copy all" + MakeCopy(source); } } - +// ---------------------------------------------------------- int MARKERS::GetMarkersSize() { return markers_array.size(); } +void MARKERS::SetMarkersSize(int new_size) +{ + // if we are truncating, clear markers that are gonna be erased (so that obsolete notes will be erased too) + for (int i = markers_array.size() - 1; i >= new_size; i--) + if (markers_array[i]) + ClearMarker(i); + markers_array.resize(new_size); +} -bool MARKERS::GetMarker(int frame) +int MARKERS::GetMarker(int frame) { if (frame >= 0 && frame < (int)markers_array.size()) - return markers_array[frame] & MARKER_FLAG_BIT; - return false; + return markers_array[frame]; + else + return 0; } +// finds and returns # of Marker starting from start_frame and searching up +int MARKERS::GetMarkerUp(int start_frame) +{ + for (; start_frame >= 0; start_frame--) + if (markers_array[start_frame]) return markers_array[start_frame]; + return 0; +} +// finds frame where the Marker is set +int MARKERS::GetMarkerFrame(int marker_id) +{ + for (int i = markers_array.size() - 1; i >= 0; i--) + if (markers_array[i] == marker_id) return i; + // didn't find + return -1; +} + void MARKERS::SetMarker(int frame) { - markers_array[frame] |= MARKER_FLAG_BIT; + int marker_num = GetMarkerUp(frame) + 1; + markers_array[frame] = marker_num; + notes.insert(notes.begin() + marker_num, 1, ""); + // increase following markers' ids + int size = markers_array.size(); + for (frame++; frame < size; ++frame) + if (markers_array[frame]) + markers_array[frame]++; } void MARKERS::ClearMarker(int frame) { - markers_array[frame] &= ~MARKER_FLAG_BIT; -} -void MARKERS::EraseMarker(int frame) -{ - // check if there's a marker, delete note if needed - markers_array.erase(markers_array.begin() + frame); + // erase corresponding note + notes.erase(notes.begin() + markers_array[frame]); + // erase marker + markers_array[frame] = 0; + // decrease following markers' ids + int size = markers_array.size(); + for (frame++; frame < size; ++frame) + if (markers_array[frame]) + markers_array[frame]--; } void MARKERS::ToggleMarker(int frame) { if (frame >= 0 && frame < (int)markers_array.size()) { - if (markers_array[frame] & MARKER_FLAG_BIT) - markers_array[frame] &= ~MARKER_FLAG_BIT; + if (markers_array[frame]) + ClearMarker(frame); else - markers_array[frame] |= MARKER_FLAG_BIT; + SetMarker(frame); } } +void MARKERS::EraseMarker(int frame) +{ + // if there's a marker, first clear it + if (markers_array[frame]) + ClearMarker(frame); + markers_array.erase(markers_array.begin() + frame); +} void MARKERS::insertEmpty(int at, int frames) { if(at == -1) @@ -159,10 +305,51 @@ void MARKERS::insertEmpty(int at, int frames) } } -void MARKERS::truncateAt(int frame) +int MARKERS::GetNotesSize() { - markers_array.resize(frame); + return notes.size(); +} +std::string MARKERS::GetNote(int index) +{ + if (index >= 0 && index < (int)notes.size()) + return notes[index]; + else return notes[0]; +} +void MARKERS::SetNote(int index, char* new_text) +{ + if (index >= 0 && index < (int)notes.size()) + notes[index] = new_text; } - +// ---------------------------------------------------------- +// return true if any difference in markers_array is found, comparing to markers.markers_array +bool MARKERS::checkMarkersDiff(MARKERS& their_markers) +{ + if (GetMarkersSize() != their_markers.GetMarkersSize()) return true; + if (GetNotesSize() != their_markers.GetNotesSize()) return true; + for (int i = markers_array.size()-1; i >= 0; i--) + { + if (markers_array[i] != their_markers.GetMarker(i)) + return true; + else if (markers_array[i] && notes[markers_array[i]].compare(their_markers.GetNote(markers_array[i]))) + return true; + } + // also check if there's difference between 0th notes + if (notes[0].compare(their_markers.GetNote(0))) + return true; + return false; +} +// return true only when difference is found before end frame (not including end frame) +bool MARKERS::checkMarkersDiff(MARKERS& their_markers, int end) +{ + if (GetMarkersSize() != their_markers.GetMarkersSize() && (GetMarkersSize()-1 < end || their_markers.GetMarkersSize()-1 < end)) return true; + for (int i = end-1; i >= 0; i--) + { + if (markers_array[i] != their_markers.GetMarker(i)) + return true; + else if (markers_array[i] && notes[markers_array[i]].compare(their_markers.GetNote(markers_array[i]))) + return true; + } + return false; +} diff --git a/src/drivers/win/taseditlib/markers.h b/src/drivers/win/taseditlib/markers.h index 40a8a3dc..438374f9 100644 --- a/src/drivers/win/taseditlib/markers.h +++ b/src/drivers/win/taseditlib/markers.h @@ -1,36 +1,47 @@ //Specification file for Markers class - -#define MARKER_FLAG_BIT 1 - #define MARKERS_ID_LEN 8 +#define MAX_NOTE_LEN 100 class MARKERS { public: MARKERS(); void init(); - void reset(); void free(); + void reset(); void update(); void save(EMUFILE *os, bool really_save = true); bool load(EMUFILE *is); + bool skipLoad(EMUFILE *is); - void MakeCopy(std::vector &destination_array); - void RestoreFromCopy(std::vector &source_array, int until_frame = -1); + void MakeCopy(MARKERS& source); + void CopyMarkersHere(std::vector& array_for_markers, std::vector& for_notes); + void RestoreFromCopy(MARKERS& source, int until_frame = -1); - bool GetMarker(int frame); int GetMarkersSize(); + void SetMarkersSize(int new_size); + + int GetMarker(int frame); + int GetMarkerUp(int start_frame); + int GetMarkerFrame(int marker_id); void SetMarker(int frame); void ClearMarker(int frame); - void EraseMarker(int frame); void ToggleMarker(int frame); + void EraseMarker(int frame); void insertEmpty(int at, int frames); - void truncateAt(int frame); + + int GetNotesSize(); + std::string GetNote(int index); + void SetNote(int index, char* new_text); + + bool checkMarkersDiff(MARKERS& their_markers); + bool checkMarkersDiff(MARKERS& their_markers, int end); private: - std::vector markers_array; + std::vector markers_array; // Format: 0th = marker num (id) for frame 0, 1st = marker num for frame 1, ... + std::vector notes; // Format: 0th - note for intro (Marker 0), 1st - note for Marker1, 2nd - note for Marker2, ... }; diff --git a/src/drivers/win/taseditlib/playback.cpp b/src/drivers/win/taseditlib/playback.cpp index 785723d0..cc6fcfa0 100644 --- a/src/drivers/win/taseditlib/playback.cpp +++ b/src/drivers/win/taseditlib/playback.cpp @@ -1,5 +1,6 @@ //Implementation file of Playback class #include "taseditproj.h" +#include "..\tasedit.h" // only for MARKER_NOTE_EDIT_UPPER #ifdef _S9XLUA_H extern void ForceExecuteLuaFrameFunctions(); @@ -9,12 +10,21 @@ extern HWND hwndTasEdit; extern bool Tasedit_rewind_now; extern bool turbo; extern bool TASEdit_turbo_seek; +extern int marker_note_edit; -extern MARKERS markers; +extern MARKERS current_markers; extern GREENZONE greenzone; extern TASEDIT_LIST tasedit_list; extern BOOKMARKS bookmarks; +extern void UpdateMarkerNote(); + +LRESULT APIENTRY UpperMarkerEditWndProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam); +WNDPROC playbackMarkerEdit_oldWndproc; + +// resources +char upperMarkerText[] = "Marker "; + PLAYBACK::PLAYBACK() { } @@ -27,12 +37,21 @@ void PLAYBACK::init() hwndForward = GetDlgItem(hwndTasEdit, TASEDIT_FORWARD); hwndRewindFull = GetDlgItem(hwndTasEdit, TASEDIT_REWIND_FULL); hwndForwardFull = GetDlgItem(hwndTasEdit, TASEDIT_FORWARD_FULL); + hwndPlaybackMarker = GetDlgItem(hwndTasEdit, IDC_PLAYBACK_MARKER); + SendMessage(hwndPlaybackMarker, WM_SETFONT, (WPARAM)tasedit_list.hMarkersFont, 0); + hwndPlaybackMarkerEdit = GetDlgItem(hwndTasEdit, IDC_PLAYBACK_MARKER_EDIT); + SendMessage(hwndPlaybackMarkerEdit, EM_SETLIMITTEXT, MAX_NOTE_LEN - 1, 0); + SendMessage(hwndPlaybackMarkerEdit, WM_SETFONT, (WPARAM)tasedit_list.hMarkersEditFont, 0); + // subclass the edit control + playbackMarkerEdit_oldWndproc = (WNDPROC)SetWindowLong(hwndPlaybackMarkerEdit, GWL_WNDPROC, (LONG)UpperMarkerEditWndProc); reset(); } void PLAYBACK::reset() { - lastCursor = currFrameCounter; + must_find_current_marker = true; + shown_marker = 0; + lastCursor = -1; pause_frame = old_pauseframe = 0; old_show_pauseframe = show_pauseframe = false; old_rewind_button_state = rewind_button_state = false; @@ -44,6 +63,7 @@ void PLAYBACK::reset() } void PLAYBACK::update() { + jump_was_used_this_frame = false; // pause when seeking hit pause_frame if(!FCEUI_EmulationPaused()) if(pause_frame && pause_frame <= currFrameCounter + 1) @@ -100,8 +120,26 @@ void PLAYBACK::update() tasedit_list.RedrawRow(currFrameCounter); bookmarks.RedrawChangedBookmarks(currFrameCounter); // enforce redrawing now - UpdateWindow(tasedit_list.hwndList); lastCursor = currFrameCounter; + UpdateWindow(tasedit_list.hwndList); + // lazy update of "Playback's Marker text" + int current_marker = current_markers.GetMarkerUp(currFrameCounter); + if (shown_marker != current_marker) + { + UpdateMarkerNote(); + shown_marker = current_marker; + RedrawMarker(); + must_find_current_marker = false; + } + } + + // [non-lazy] update "Playback's Marker text" if needed + if (must_find_current_marker) + { + UpdateMarkerNote(); + shown_marker = current_markers.GetMarkerUp(currFrameCounter); + RedrawMarker(); + must_find_current_marker = false; } // update < and > buttons @@ -230,11 +268,12 @@ void PLAYBACK::RewindFull() // jump to previous marker int index = currFrameCounter - 1; for (; index >= 0; index--) - if (markers.GetMarker(index)) break; + if (current_markers.GetMarker(index)) break; if (index >= 0) jump(index); else jump(0); + jump_was_used_this_frame = true; } void PLAYBACK::ForwardFull() { @@ -242,13 +281,28 @@ void PLAYBACK::ForwardFull() int last_frame = currMovieData.getNumRecords()-1; int index = currFrameCounter + 1; for (; index <= last_frame; ++index) - if (markers.GetMarker(index)) break; + if (current_markers.GetMarker(index)) break; if (index <= last_frame) jump(index); else jump(last_frame); } +void PLAYBACK::RedrawMarker() +{ + // redraw marker num + char new_text[MAX_NOTE_LEN] = {0}; + if (shown_marker <= 99999) // if there's too many digits in the number then don't show the word "Marker" before the number + strcpy(new_text, upperMarkerText); + char num[11]; + _itoa(shown_marker, num, 10); + strcat(new_text, num); + SetWindowText(hwndPlaybackMarker, new_text); + // change marker note + strcpy(new_text, current_markers.GetNote(shown_marker).c_str()); + SetWindowText(hwndPlaybackMarkerEdit, new_text); +} + void PLAYBACK::StartFromZero() { poweron(true); @@ -321,6 +375,38 @@ void PLAYBACK::SetProgressbar(int a, int b) { SendMessage(hwndProgressbar, PBM_SETPOS, PROGRESSBAR_WIDTH * a / b, 0); } +// ------------------------------------------------------------------------- +LRESULT APIENTRY UpperMarkerEditWndProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam) +{ + if (marker_note_edit == MARKER_NOTE_EDIT_UPPER) + { + extern PLAYBACK playback; + extern TASEDIT_SELECTION selection; + switch(msg) + { + case WM_CHAR: + case WM_KEYDOWN: + switch(wParam) + { + case VK_ESCAPE: + // revert text to original note text + SetWindowText(playback.hwndPlaybackMarkerEdit, current_markers.GetNote(playback.shown_marker).c_str()); + SetFocus(tasedit_list.hwndList); + return 0; + case VK_RETURN: + // exit and save text changes + SetFocus(tasedit_list.hwndList); + return 0; + case VK_TAB: + // switch to lower edit control (also exit and save text changes) + SetFocus(selection.hwndSelectionMarkerEdit); + return 0; + } + break; + } + } + return CallWindowProc(playbackMarkerEdit_oldWndproc, hWnd, msg, wParam, lParam); +} diff --git a/src/drivers/win/taseditlib/playback.h b/src/drivers/win/taseditlib/playback.h index f2ab786b..c7bf173d 100644 --- a/src/drivers/win/taseditlib/playback.h +++ b/src/drivers/win/taseditlib/playback.h @@ -32,6 +32,7 @@ public: void RewindFull(); void ForwardFull(); + void RedrawMarker(); void StartFromZero(); @@ -39,8 +40,14 @@ public: void SetProgressbar(int a, int b); int pause_frame; + bool must_find_current_marker; + int shown_marker; HWND hwndProgressbar, hwndRewind, hwndForward, hwndRewindFull, hwndForwardFull; + HWND hwndPlaybackMarker, hwndPlaybackMarkerEdit; + + // temps + bool jump_was_used_this_frame; private: bool JumpToFrame(int index); diff --git a/src/drivers/win/taseditlib/recorder.cpp b/src/drivers/win/taseditlib/recorder.cpp index b3ea4c05..fcb38489 100644 --- a/src/drivers/win/taseditlib/recorder.cpp +++ b/src/drivers/win/taseditlib/recorder.cpp @@ -43,6 +43,17 @@ void RECORDER::reset() multitrack_recording_joypad = MULTITRACK_RECORDING_ALL; UncheckRecordingRadioButtons(); RecheckRecordingRadioButtons(); + if (currMovieData.fourscore) + { + // enable radiobuttons for 3P/4P multitracking + EnableWindow(hwndRB_Rec3P, true); + EnableWindow(hwndRB_Rec4P, true); + } else + { + // disable radiobuttons for 3P/4P multitracking + EnableWindow(hwndRB_Rec3P, false); + EnableWindow(hwndRB_Rec4P, false); + } } void RECORDER::update() { diff --git a/src/drivers/win/taseditlib/recorder.h b/src/drivers/win/taseditlib/recorder.h index 88ba4531..4f81418b 100644 --- a/src/drivers/win/taseditlib/recorder.h +++ b/src/drivers/win/taseditlib/recorder.h @@ -20,12 +20,13 @@ public: void InputChanged(); int multitrack_recording_joypad; - HWND hwndRB_RecOff, hwndRB_RecAll, hwndRB_Rec1P, hwndRB_Rec2P, hwndRB_Rec3P, hwndRB_Rec4P; private: int old_multitrack_recording_joypad; bool old_movie_readonly; + HWND hwndRB_RecOff, hwndRB_RecAll, hwndRB_Rec1P, hwndRB_Rec2P, hwndRB_Rec3P, hwndRB_Rec4P; + // temps std::vector old_joy; std::vector new_joy; diff --git a/src/drivers/win/taseditlib/screenshot_display.cpp b/src/drivers/win/taseditlib/screenshot_display.cpp index 2fdae366..40c7b1f8 100644 --- a/src/drivers/win/taseditlib/screenshot_display.cpp +++ b/src/drivers/win/taseditlib/screenshot_display.cpp @@ -6,14 +6,18 @@ extern HWND hwndTasEdit; extern int TasEdit_wndx, TasEdit_wndy; extern bool TASEdit_show_branch_screenshots; +extern bool TASEdit_show_branch_tooltips; +extern MARKERS current_markers; extern BOOKMARKS bookmarks; extern TASEDIT_LIST tasedit_list; LRESULT CALLBACK ScrBmpWndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam); +LRESULT APIENTRY MarkerNoteTooltipWndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam); // resources char szClassName[] = "ScrBmp"; +char szClassName2[] = "MarketNoteTooltip"; SCREENSHOT_DISPLAY::SCREENSHOT_DISPLAY() { @@ -27,21 +31,38 @@ SCREENSHOT_DISPLAY::SCREENSHOT_DISPLAY() scr_bmi->bmiHeader.biCompression = BI_RGB; scr_bmi->bmiHeader.biSizeImage = 0; + // register MarketNoteTooltip window class + wincl1.hInstance = fceu_hInstance; + wincl1.lpszClassName = szClassName; + wincl1.lpfnWndProc = ScrBmpWndProc; + wincl1.style = CS_DBLCLKS; + wincl1.cbSize = sizeof(WNDCLASSEX); + wincl1.hIcon = 0; + wincl1.hIconSm = 0; + wincl1.hCursor = 0; + wincl1.lpszMenuName = 0; + wincl1.cbClsExtra = 0; + wincl1.cbWndExtra = 0; + wincl1.hbrBackground = 0; + if(!RegisterClassEx(&wincl1)) + FCEU_printf("Error registering SCREENSHOT_DISPLAY window class\n"); + // register ScrBmp window class - wincl.hInstance = fceu_hInstance; - wincl.lpszClassName = szClassName; - wincl.lpfnWndProc = ScrBmpWndProc; - wincl.style = CS_DBLCLKS; - wincl.cbSize = sizeof(WNDCLASSEX); - wincl.hIcon = 0; - wincl.hIconSm = 0; - wincl.hCursor = 0; - wincl.lpszMenuName = 0; - wincl.cbClsExtra = 0; - wincl.cbWndExtra = 0; - wincl.hbrBackground = 0; - if(!RegisterClassEx(&wincl)) - FCEU_printf("Error registering SCR_DISPLAY window class\n"); + wincl2.hInstance = fceu_hInstance; + wincl2.lpszClassName = szClassName2; + wincl2.lpfnWndProc = MarkerNoteTooltipWndProc; + wincl2.style = CS_DBLCLKS; + wincl2.cbSize = sizeof(WNDCLASSEX); + wincl2.hIcon = 0; + wincl2.hIconSm = 0; + wincl2.hCursor = 0; + wincl2.lpszMenuName = 0; + wincl2.cbClsExtra = 0; + wincl2.cbWndExtra = 0; + wincl2.hbrBackground = 0; + if(!RegisterClassEx(&wincl2)) + FCEU_printf("Error registering MARKER_NOTE_TOOLTIP window class\n"); + // create blendfunction blend.BlendOp = AC_SRC_OVER; blend.BlendFlags = 0; @@ -67,7 +88,11 @@ void SCREENSHOT_DISPLAY::init() GetWindowRect(hwndTasEdit, &parent_rect); GetWindowRect(GetDlgItem(hwndTasEdit, IDC_BOOKMARKS_BOX), &temp_rect); scr_bmp_x = temp_rect.left - SCREENSHOT_WIDTH - SCR_BMP_DX - parent_rect.left; - scr_bmp_y = ((temp_rect.bottom + temp_rect.top - SCREENSHOT_HEIGHT) / 2) - parent_rect.top; + //scr_bmp_y = ((temp_rect.bottom + temp_rect.top - (SCREENSHOT_HEIGHT + SCR_BMP_TOOLTIP_GAP + MARKER_NOTE_TOOLTIP_HEIGHT)) / 2) - parent_rect.top; + scr_bmp_y = (temp_rect.bottom - SCREENSHOT_HEIGHT) - parent_rect.top; + tooltip_x = scr_bmp_x + SCREENSHOT_WIDTH - MARKER_NOTE_TOOLTIP_WIDTH; + //tooltip_y = scr_bmp_y + SCREENSHOT_HEIGHT + SCR_BMP_TOOLTIP_GAP; + tooltip_y = scr_bmp_y + SCREENSHOT_HEIGHT + SCR_BMP_TOOLTIP_GAP; } void SCREENSHOT_DISPLAY::free() { @@ -87,6 +112,11 @@ void SCREENSHOT_DISPLAY::reset() DestroyWindow(hwndScrBmp); hwndScrBmp = 0; } + if (hwndMarkerNoteTooltip) + { + DestroyWindow(hwndMarkerNoteTooltip); + hwndMarkerNoteTooltip = 0; + } } void SCREENSHOT_DISPLAY::update() @@ -95,20 +125,29 @@ void SCREENSHOT_DISPLAY::update() if (clock() > next_update_time) { next_update_time = clock() + DISPLAY_UPDATE_TICK; - if (bookmarks.item_under_mouse >= 0 && bookmarks.item_under_mouse < TOTAL_BOOKMARKS && TASEdit_show_branch_screenshots) + if (bookmarks.item_under_mouse >= 0 && bookmarks.item_under_mouse < TOTAL_BOOKMARKS) { - if (!hwndScrBmp) + if (TASEdit_show_branch_screenshots && !hwndScrBmp) { // create window hwndScrBmp = CreateWindowEx(WS_EX_LAYERED | WS_EX_TRANSPARENT, szClassName, szClassName, WS_POPUP, TasEdit_wndx + scr_bmp_x, TasEdit_wndy + scr_bmp_y, SCREENSHOT_WIDTH, SCREENSHOT_HEIGHT, hwndTasEdit, NULL, fceu_hInstance, NULL); RedrawScreenshotBitmap(); ShowWindow(hwndScrBmp, SW_SHOWNA); } - // change screenshot_bitmap pic if needed - if (bookmarks.item_under_mouse != screenshot_currently_shown) + if (TASEdit_show_branch_tooltips && !hwndMarkerNoteTooltip) { - if (bookmarks.bookmarks_array[bookmarks.item_under_mouse].not_empty) + hwndMarkerNoteTooltip = CreateWindowEx(WS_EX_LAYERED | WS_EX_TRANSPARENT, szClassName2, szClassName2, WS_POPUP, TasEdit_wndx + tooltip_x, TasEdit_wndy + tooltip_y, MARKER_NOTE_TOOLTIP_WIDTH, MARKER_NOTE_TOOLTIP_HEIGHT, hwndTasEdit, NULL, fceu_hInstance, NULL); + ChangeTooltipText(); + ShowWindow(hwndMarkerNoteTooltip, SW_SHOWNA); + } + // change screenshot_bitmap pic and tooltip text if needed + if (screenshot_currently_shown != bookmarks.item_under_mouse) + { + if (TASEdit_show_branch_screenshots) ChangeScreenshotBitmap(); + if (TASEdit_show_branch_tooltips) + ChangeTooltipText(); + screenshot_currently_shown = bookmarks.item_under_mouse; } if (scr_bmp_phase < SCR_BMP_PHASE_MAX) { @@ -116,8 +155,16 @@ void SCREENSHOT_DISPLAY::update() // update alpha int phase_alpha = scr_bmp_phase; if (phase_alpha > SCR_BMP_PHASE_ALPHA_MAX) phase_alpha = SCR_BMP_PHASE_ALPHA_MAX; - SetLayeredWindowAttributes(hwndScrBmp, 0, (255 * phase_alpha) / SCR_BMP_PHASE_ALPHA_MAX, LWA_ALPHA); - UpdateLayeredWindow(hwndScrBmp, 0, 0, 0, 0, 0, 0, &blend, ULW_ALPHA); + if (hwndScrBmp) + { + SetLayeredWindowAttributes(hwndScrBmp, 0, (255 * phase_alpha) / SCR_BMP_PHASE_ALPHA_MAX, LWA_ALPHA); + UpdateLayeredWindow(hwndScrBmp, 0, 0, 0, 0, 0, 0, &blend, ULW_ALPHA); + } + if (hwndMarkerNoteTooltip) + { + SetLayeredWindowAttributes(hwndMarkerNoteTooltip, 0, (255 * phase_alpha) / SCR_BMP_PHASE_ALPHA_MAX, LWA_ALPHA); + UpdateLayeredWindow(hwndMarkerNoteTooltip, 0, 0, 0, 0, 0, 0, &blend, ULW_ALPHA); + } } } else { @@ -126,14 +173,19 @@ void SCREENSHOT_DISPLAY::update() scr_bmp_phase--; if (scr_bmp_phase > 0) { + // update alpha + int phase_alpha = scr_bmp_phase; + if (phase_alpha > SCR_BMP_PHASE_ALPHA_MAX) phase_alpha = SCR_BMP_PHASE_ALPHA_MAX; if (hwndScrBmp) { - // update alpha - int phase_alpha = scr_bmp_phase; - if (phase_alpha > SCR_BMP_PHASE_ALPHA_MAX) phase_alpha = SCR_BMP_PHASE_ALPHA_MAX; SetLayeredWindowAttributes(hwndScrBmp, 0, (255 * phase_alpha) / SCR_BMP_PHASE_ALPHA_MAX, LWA_ALPHA); UpdateLayeredWindow(hwndScrBmp, 0, 0, 0, 0, 0, 0, &blend, ULW_ALPHA); } + if (hwndMarkerNoteTooltip) + { + SetLayeredWindowAttributes(hwndMarkerNoteTooltip, 0, (255 * phase_alpha) / SCR_BMP_PHASE_ALPHA_MAX, LWA_ALPHA); + UpdateLayeredWindow(hwndMarkerNoteTooltip, 0, 0, 0, 0, 0, 0, &blend, ULW_ALPHA); + } } else { // destroy screenshot bitmap window @@ -143,6 +195,11 @@ void SCREENSHOT_DISPLAY::update() DestroyWindow(hwndScrBmp); hwndScrBmp = 0; } + if (hwndMarkerNoteTooltip) + { + DestroyWindow(hwndMarkerNoteTooltip); + hwndMarkerNoteTooltip = 0; + } } } } @@ -160,7 +217,6 @@ void SCREENSHOT_DISPLAY::ChangeScreenshotBitmap() // at least fill bitmap with zeros memset(&scr_ptr[0], 0, SCREENSHOT_SIZE); } - screenshot_currently_shown = bookmarks.item_under_mouse; RedrawScreenshotBitmap(); } void SCREENSHOT_DISPLAY::RedrawScreenshotBitmap() @@ -169,11 +225,22 @@ void SCREENSHOT_DISPLAY::RedrawScreenshotBitmap() if (temp_bmp && temp_bmp != scr_bmp) DeleteObject(temp_bmp); } +void SCREENSHOT_DISPLAY::ChangeTooltipText() +{ + // retrieve info from the pointed bookmark's markers + int frame = bookmarks.bookmarks_array[bookmarks.item_under_mouse].snapshot.jump_frame; + int marker_id = bookmarks.bookmarks_array[bookmarks.item_under_mouse].snapshot.my_markers.GetMarkerUp(frame); + char new_text[MAX_NOTE_LEN]; + strcpy(new_text, bookmarks.bookmarks_array[bookmarks.item_under_mouse].snapshot.my_markers.GetNote(marker_id).c_str()); + SetWindowText(marker_note_tooltip, new_text); +} void SCREENSHOT_DISPLAY::ParentWindowMoved() { if (hwndScrBmp) SetWindowPos(hwndScrBmp, 0, TasEdit_wndx + scr_bmp_x, TasEdit_wndy + scr_bmp_y, 0, 0, SWP_NOSIZE|SWP_NOZORDER|SWP_NOACTIVATE); + if (hwndMarkerNoteTooltip) + SetWindowPos(hwndMarkerNoteTooltip, 0, TasEdit_wndx + tooltip_x, TasEdit_wndy + tooltip_y, 0, 0, SWP_NOSIZE|SWP_NOZORDER|SWP_NOACTIVATE); } // ---------------------------------------------------------------------------------------- LRESULT APIENTRY ScrBmpWndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam) @@ -191,5 +258,20 @@ LRESULT APIENTRY ScrBmpWndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lP return DefWindowProc(hwnd, message, wParam, lParam); } } +LRESULT APIENTRY MarkerNoteTooltipWndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam) +{ + extern SCREENSHOT_DISPLAY screenshot_display; + switch(message) + { + case WM_CREATE: + { + // create static text field + screenshot_display.marker_note_tooltip = CreateWindow(WC_STATIC, NULL, WS_CHILD | WS_VISIBLE | SS_CENTER | SS_SUNKEN, 1, 1, MARKER_NOTE_TOOLTIP_WIDTH - 2, MARKER_NOTE_TOOLTIP_HEIGHT - 2, hwnd, NULL, NULL, NULL); + return 0; + } + default: + return DefWindowProc(hwnd, message, wParam, lParam); + } +} diff --git a/src/drivers/win/taseditlib/screenshot_display.h b/src/drivers/win/taseditlib/screenshot_display.h index 619f3983..70248a30 100644 --- a/src/drivers/win/taseditlib/screenshot_display.h +++ b/src/drivers/win/taseditlib/screenshot_display.h @@ -4,6 +4,11 @@ #define SCR_BMP_PHASE_ALPHA_MAX 8 #define SCR_BMP_DX 7 +#define SCR_BMP_TOOLTIP_GAP 2 + +#define MARKER_NOTE_TOOLTIP_WIDTH 360 +#define MARKER_NOTE_TOOLTIP_HEIGHT 20 + #define DISPLAY_UPDATE_TICK 40 // update at 25FPS class SCREENSHOT_DISPLAY @@ -17,19 +22,23 @@ public: void ChangeScreenshotBitmap(); void RedrawScreenshotBitmap(); + void ChangeTooltipText(); void ParentWindowMoved(); int screenshot_currently_shown; - HWND hwndScrBmp, scr_bmp_pic; + HWND hwndScrBmp, scr_bmp_pic, hwndMarkerNoteTooltip, marker_note_tooltip; private: int scr_bmp_x; int scr_bmp_y; int scr_bmp_phase; int next_update_time; + + int tooltip_x; + int tooltip_y; - WNDCLASSEX wincl; + WNDCLASSEX wincl1, wincl2; BLENDFUNCTION blend; LPBITMAPINFO scr_bmi; HBITMAP scr_bmp; diff --git a/src/drivers/win/taseditlib/tasedit_list.cpp b/src/drivers/win/taseditlib/tasedit_list.cpp index a8c9d3d4..453578f8 100644 --- a/src/drivers/win/taseditlib/tasedit_list.cpp +++ b/src/drivers/win/taseditlib/tasedit_list.cpp @@ -12,7 +12,7 @@ extern PLAYBACK playback; extern RECORDER recorder; extern GREENZONE greenzone; extern INPUT_HISTORY history; -extern MARKERS markers; +extern MARKERS current_markers; extern TASEDIT_SELECTION selection; extern bool TASEdit_enable_hot_changes; @@ -20,6 +20,7 @@ extern bool TASEdit_show_markers; extern bool TASEdit_show_lag_frames; extern bool TASEdit_follow_playback; extern bool TASEdit_jump_to_undo; +extern bool TASEdit_keyboard_for_listview; LRESULT APIENTRY HeaderWndProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam); LRESULT APIENTRY ListWndProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam); @@ -48,6 +49,19 @@ TASEDIT_LIST::TASEDIT_LIST() ANSI_CHARSET, OUT_DEVICE_PRECIS, CLIP_MASK, /*charset, precision, clipping*/ DEFAULT_QUALITY, DEFAULT_PITCH, /*quality, and pitch*/ "Courier New"); /*font name*/ + // create fonts for Marker notes fields + hMarkersFont = CreateFont(16, 7, /*Height,Width*/ + 0, 0, /*escapement,orientation*/ + FW_NORMAL, FALSE, FALSE, FALSE, /*weight, italic, underline, strikeout*/ + ANSI_CHARSET, OUT_DEVICE_PRECIS, CLIP_MASK, /*charset, precision, clipping*/ + DEFAULT_QUALITY, DEFAULT_PITCH, /*quality, and pitch*/ + "Arial"); /*font name*/ + hMarkersEditFont = CreateFont(16, 7, /*Height,Width*/ + 0, 0, /*escapement,orientation*/ + FW_NORMAL, FALSE, FALSE, FALSE, /*weight, italic, underline, strikeout*/ + ANSI_CHARSET, OUT_DEVICE_PRECIS, CLIP_MASK, /*charset, precision, clipping*/ + DEFAULT_QUALITY, DEFAULT_PITCH, /*quality, and pitch*/ + "Arial"); /*font name*/ } @@ -56,7 +70,7 @@ void TASEDIT_LIST::init() free(); hwndList = GetDlgItem(hwndTasEdit, IDC_LIST1); // prepare the main listview - ListView_SetExtendedListViewStyleEx(hwndList, LVS_EX_FULLROWSELECT|LVS_EX_GRIDLINES, LVS_EX_FULLROWSELECT|LVS_EX_GRIDLINES); + ListView_SetExtendedListViewStyleEx(hwndList, LVS_EX_FULLROWSELECT|LVS_EX_GRIDLINES|LVS_EX_INFOTIP, LVS_EX_FULLROWSELECT|LVS_EX_GRIDLINES|LVS_EX_INFOTIP); // subclass the header hwndHeader = ListView_GetHeader(hwndList); hwndHeader_oldWndproc = (WNDPROC)SetWindowLong(hwndHeader, GWL_WNDPROC, (LONG)HeaderWndProc); @@ -155,8 +169,6 @@ void TASEDIT_LIST::init() // add pads 3 and 4 and frame_number2 if (currMovieData.fourscore) AddFourscore(); - listItems = ListView_GetCountPerPage(hwndList); - update(); reset(); } @@ -248,9 +260,6 @@ void TASEDIT_LIST::AddFourscore() lvc.cx = 75; lvc.pszText = "Frame#"; ListView_InsertColumn(hwndList, colidx++, &lvc); - // enable radiobuttons for 3P/4P multitracking - EnableWindow(recorder.hwndRB_Rec3P, true); - EnableWindow(recorder.hwndRB_Rec4P, true); // change eoptions FCEUI_SetInputFourscore(true); } @@ -261,9 +270,6 @@ void TASEDIT_LIST::RemoveFourscore() { ListView_DeleteColumn (hwndList, i); } - // disable radiobuttons for 3P/4P multitracking - EnableWindow(recorder.hwndRB_Rec3P, false); - EnableWindow(recorder.hwndRB_Rec4P, false); // change eoptions FCEUI_SetInputFourscore(false); } @@ -283,7 +289,7 @@ bool TASEDIT_LIST::CheckItemVisible(int frame) { int top = ListView_GetTopIndex(hwndList); // in fourscore there's horizontal scrollbar which takes one row for itself - if (frame >= top && frame < top + listItems - (currMovieData.fourscore)?1:0) + if (frame >= top && frame < top + ListView_GetCountPerPage(hwndList)) return true; return false; } @@ -300,8 +306,7 @@ void TASEDIT_LIST::FollowUndo() if (!CheckItemVisible(jump_frame)) { // center list at jump_frame - int list_items = listItems; - if (currMovieData.fourscore) list_items--; + int list_items = ListView_GetCountPerPage(hwndList); int lower_border = (list_items - 1) / 2; int upper_border = (list_items - 1) - lower_border; int index = jump_frame + lower_border; @@ -320,8 +325,7 @@ void TASEDIT_LIST::FollowSelection() SelectionFrames* current_selection = selection.MakeStrobe(); if (current_selection->size() == 0) return; - int list_items = listItems; - if (currMovieData.fourscore) list_items--; + int list_items = ListView_GetCountPerPage(hwndList); int selection_start = *current_selection->begin(); int selection_end = *current_selection->rbegin(); int selection_items = 1 + selection_end - selection_start; @@ -361,8 +365,7 @@ void TASEDIT_LIST::FollowPauseframe() if (jump_frame >= 0) { // center list at jump_frame - int list_items = listItems; - if (currMovieData.fourscore) list_items--; + int list_items = ListView_GetCountPerPage(hwndList); int lower_border = (list_items - 1) / 2; int upper_border = (list_items - 1) - lower_border; int index = jump_frame + lower_border; @@ -456,7 +459,7 @@ LONG TASEDIT_LIST::CustomDraw(NMLVCUSTOMDRAW* msg) if(cell_x == COLUMN_FRAMENUM || cell_x == COLUMN_FRAMENUM2) { // font - if(markers.GetMarker(cell_y)) + if(current_markers.GetMarker(cell_y)) SelectObject(msg->nmcd.hdc, hMainListSelectFont); else SelectObject(msg->nmcd.hdc, hMainListFont); @@ -465,7 +468,7 @@ LONG TASEDIT_LIST::CustomDraw(NMLVCUSTOMDRAW* msg) if (cell_y == history.GetUndoHint()) { // undo hint here - if (TASEdit_show_markers && markers.GetMarker(cell_y)) + if (TASEdit_show_markers && current_markers.GetMarker(cell_y)) { msg->clrTextBk = MARKED_UNDOHINT_FRAMENUM_COLOR; } else @@ -475,14 +478,14 @@ LONG TASEDIT_LIST::CustomDraw(NMLVCUSTOMDRAW* msg) } else if (cell_y == currFrameCounter || cell_y == (playback.GetPauseFrame() - 1)) { // current frame - if (TASEdit_show_markers && markers.GetMarker(cell_y)) + if (TASEdit_show_markers && current_markers.GetMarker(cell_y)) { msg->clrTextBk = CUR_MARKED_FRAMENUM_COLOR; } else { msg->clrTextBk = CUR_FRAMENUM_COLOR; } - } else if (TASEdit_show_markers && markers.GetMarker(cell_y)) + } else if (TASEdit_show_markers && current_markers.GetMarker(cell_y)) { // marked frame msg->clrTextBk = MARKED_FRAMENUM_COLOR; @@ -625,6 +628,12 @@ LRESULT APIENTRY ListWndProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam) } break; } + case WM_KEYDOWN: + { + if (!TASEdit_keyboard_for_listview) + return 0; + break; + } case WM_SYSKEYDOWN: { if (wParam == VK_F10) diff --git a/src/drivers/win/taseditlib/tasedit_list.h b/src/drivers/win/taseditlib/tasedit_list.h index ac10d0d4..2118446d 100644 --- a/src/drivers/win/taseditlib/tasedit_list.h +++ b/src/drivers/win/taseditlib/tasedit_list.h @@ -117,10 +117,8 @@ public: // GDI stuff HIMAGELIST himglist; - HFONT hMainListFont, hMainListSelectFont; + HFONT hMainListFont, hMainListSelectFont, hMarkersFont, hMarkersEditFont; private: - int listItems; // number of items per list page - }; diff --git a/src/drivers/win/taseditlib/tasedit_sel.cpp b/src/drivers/win/taseditlib/tasedit_sel.cpp index 62824a02..a62c76d8 100644 --- a/src/drivers/win/taseditlib/tasedit_sel.cpp +++ b/src/drivers/win/taseditlib/tasedit_sel.cpp @@ -1,16 +1,22 @@ //Implementation file of TASEDIT_SELECTION class - #include "taseditproj.h" +#include "..\tasedit.h" // only for MARKER_NOTE_EDIT_UPPER char selection_save_id[SELECTION_ID_LEN] = "SELECTION"; char selection_skipsave_id[SELECTION_ID_LEN] = "SELECTIOX"; extern HWND hwndTasEdit; extern int TasEdit_undo_levels; +extern int marker_note_edit; -extern MARKERS markers; +extern MARKERS current_markers; extern TASEDIT_LIST tasedit_list; +extern void UpdateMarkerNote(); + +LRESULT APIENTRY LowerMarkerEditWndProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam); +WNDPROC selectionMarkerEdit_oldWndproc; + // resources char selectionText[] = "Selection: "; char selectionEmptyText[] = "Selection: no"; @@ -20,6 +26,7 @@ char numTextColumn[] = "1 column"; char numTextColumns[] = " columns"; char clipboardText[] = "Clipboard: "; char clipboardEmptyText[] = "Clipboard: empty"; +char lowerMarkerText[] = "Marker "; TASEDIT_SELECTION::TASEDIT_SELECTION() { @@ -33,7 +40,14 @@ void TASEDIT_SELECTION::init() hwndFindNextMarker = GetDlgItem(hwndTasEdit, TASEDIT_FIND_NEXT_MARKER); hwndTextSelection = GetDlgItem(hwndTasEdit, IDC_TEXT_SELECTION); hwndTextClipboard = GetDlgItem(hwndTasEdit, IDC_TEXT_CLIPBOARD); - + hwndSelectionMarker = GetDlgItem(hwndTasEdit, IDC_SELECTION_MARKER); + SendMessage(hwndSelectionMarker, WM_SETFONT, (WPARAM)tasedit_list.hMarkersFont, 0); + hwndSelectionMarkerEdit = GetDlgItem(hwndTasEdit, IDC_SELECTION_MARKER_EDIT); + SendMessage(hwndSelectionMarkerEdit, EM_SETLIMITTEXT, MAX_NOTE_LEN - 1, 0); + SendMessage(hwndSelectionMarkerEdit, WM_SETFONT, (WPARAM)tasedit_list.hMarkersEditFont, 0); + // subclass the edit control + selectionMarkerEdit_oldWndproc = (WNDPROC)SetWindowLong(hwndSelectionMarkerEdit, GWL_WNDPROC, (LONG)LowerMarkerEditWndProc); + reset(); if (clipboard_selection.empty()) @@ -51,6 +65,9 @@ void TASEDIT_SELECTION::reset() { free(); // init vars + must_find_current_marker = true; + shown_marker = 0; + last_selection_beginning = -1; history_size = TasEdit_undo_levels + 1; selections_history.resize(history_size); history_start_pos = 0; @@ -81,6 +98,7 @@ void TASEDIT_SELECTION::update() if (!CurrentSelection().size()) break; } } + // update << and >> buttons old_prev_marker_button_state = prev_marker_button_state; prev_marker_button_state = ((Button_GetState(hwndPrevMarker) & BST_PUSHED) != 0); @@ -108,6 +126,7 @@ void TASEDIT_SELECTION::update() JumpNextMarker(); } } + // redraw selection info text of needed if (must_redraw_text) { @@ -144,6 +163,22 @@ void TASEDIT_SELECTION::update() must_redraw_text = false; } + // track changes of selection beginning + if (last_selection_beginning != GetCurrentSelectionBeginning()) + { + last_selection_beginning = GetCurrentSelectionBeginning(); + must_find_current_marker = true; + } + + // update "Selection's Marker text" if needed + if (must_find_current_marker) + { + UpdateMarkerNote(); + shown_marker = current_markers.GetMarkerUp(last_selection_beginning); + RedrawMarker(); + must_find_current_marker = false; + } + } void TASEDIT_SELECTION::RedrawTextClipboard() @@ -179,6 +214,20 @@ void TASEDIT_SELECTION::RedrawTextClipboard() } else SetWindowText(hwndTextClipboard, clipboardEmptyText); } +void TASEDIT_SELECTION::RedrawMarker() +{ + // redraw marker num + char new_text[MAX_NOTE_LEN] = {0}; + if (shown_marker <= 99999) // if there's too many digits in the number then don't show the word "Marker" before the number + strcpy(new_text, lowerMarkerText); + char num[11]; + _itoa(shown_marker, num, 10); + strcat(new_text, num); + SetWindowText(hwndSelectionMarker, new_text); + // change marker note + strcpy(new_text, current_markers.GetNote(shown_marker).c_str()); + SetWindowText(hwndSelectionMarkerEdit, new_text); +} void TASEDIT_SELECTION::JumpPrevMarker() { @@ -186,7 +235,7 @@ void TASEDIT_SELECTION::JumpPrevMarker() int index = GetCurrentSelectionBeginning(); if (index < 0) index = currFrameCounter; // if nothing is selected, consider playback cursor as current selection for (index--; index >= 0; index--) - if (markers.GetMarker(index)) break; + if (current_markers.GetMarker(index)) break; if (index >= 0) JumpToFrame(index); else @@ -200,7 +249,7 @@ void TASEDIT_SELECTION::JumpNextMarker() int last_frame = currMovieData.getNumRecords()-1; for (++index; index <= last_frame; ++index) - if (markers.GetMarker(index)) break; + if (current_markers.GetMarker(index)) break; if (index <= last_frame) JumpToFrame(index); else @@ -321,10 +370,9 @@ bool TASEDIT_SELECTION::loadSelection(SelectionFrames& selection, EMUFILE *is) } bool TASEDIT_SELECTION::skiploadSelection(EMUFILE *is) { - int temp_int, temp_size; + int temp_size; if (!read32le(&temp_size, is)) return true; - for(; temp_size > 0; temp_size--) - if (!read32le(&temp_int, is)) return true; + if (is->fseek(temp_size * sizeof(int), SEEK_CUR)) return true; return false; } // ---------------------------------------------------------- @@ -528,10 +576,10 @@ void TASEDIT_SELECTION::SelectMidMarkers() // find markers // searching up starting from center-0 for (upper_marker = center; upper_marker >= 0; upper_marker--) - if (markers.GetMarker(upper_marker)) break; + if (current_markers.GetMarker(upper_marker)) break; // searching down starting from center+1 for (lower_marker = center+1; lower_marker < movie_size; ++lower_marker) - if (markers.GetMarker(lower_marker)) break; + if (current_markers.GetMarker(lower_marker)) break; // clear selection without clearing focused, because otherwise there's strange bug when quickly pressing Ctrl+A right after clicking on already selected row ListView_SetItemState(tasedit_list.hwndList, -1, 0, LVIS_SELECTED); @@ -622,4 +670,40 @@ SelectionFrames& TASEDIT_SELECTION::CurrentSelection() { return selections_history[(history_start_pos + history_cursor_pos) % history_size]; } +// ------------------------------------------------------------------------- +LRESULT APIENTRY LowerMarkerEditWndProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam) +{ + if (marker_note_edit == MARKER_NOTE_EDIT_LOWER) + { + extern PLAYBACK playback; + extern TASEDIT_SELECTION selection; + switch(msg) + { + case WM_CHAR: + case WM_KEYDOWN: + switch(wParam) + { + case VK_ESCAPE: + // revert text to original note text + SetWindowText(selection.hwndSelectionMarkerEdit, current_markers.GetNote(selection.shown_marker).c_str()); + SetFocus(tasedit_list.hwndList); + return 0; + case VK_RETURN: + // exit and save text changes + SetFocus(tasedit_list.hwndList); + return 0; + case VK_TAB: + // switch to upper edit control (also exit and save text changes) + SetFocus(playback.hwndPlaybackMarkerEdit); + return 0; + } + break; + } + } + return CallWindowProc(selectionMarkerEdit_oldWndproc, hWnd, msg, wParam, lParam); +} + + + + diff --git a/src/drivers/win/taseditlib/tasedit_sel.h b/src/drivers/win/taseditlib/tasedit_sel.h index c11f6167..37347b81 100644 --- a/src/drivers/win/taseditlib/tasedit_sel.h +++ b/src/drivers/win/taseditlib/tasedit_sel.h @@ -13,6 +13,7 @@ public: void update(); void RedrawTextClipboard(); + void RedrawMarker(); void save(EMUFILE *os, bool really_save = true); bool load(EMUFILE *is); @@ -55,6 +56,13 @@ public: SelectionFrames& GetInsertedSet(); + bool must_find_current_marker; + int shown_marker; + + HWND hwndPrevMarker, hwndNextMarker, hwndFindBestMarker, hwndFindNextMarker; + HWND hwndTextSelection, hwndTextClipboard; + HWND hwndSelectionMarker, hwndSelectionMarkerEdit; + private: SelectionFrames& CurrentSelection(); void CheckClipboard(); @@ -62,6 +70,8 @@ private: bool track_selection_changes; bool must_redraw_text; + int last_selection_beginning; + bool old_prev_marker_button_state, prev_marker_button_state; bool old_next_marker_button_state, next_marker_button_state; int button_hold_time; @@ -78,7 +88,4 @@ private: SelectionFrames temp_selection; - HWND hwndPrevMarker, hwndNextMarker, hwndFindBestMarker, hwndFindNextMarker; - HWND hwndTextSelection, hwndTextClipboard; - }; diff --git a/src/drivers/win/taseditlib/taseditproj.cpp b/src/drivers/win/taseditlib/taseditproj.cpp index 7ebf05c2..1ff6a02e 100644 --- a/src/drivers/win/taseditlib/taseditproj.cpp +++ b/src/drivers/win/taseditlib/taseditproj.cpp @@ -1,8 +1,17 @@ //Implementation file of TASEdit Project class #include "taseditproj.h" #include "utils/xstring.h" +#include "version.h" -extern MARKERS markers; +#define MARKERS_SAVED 1 +#define BOOKMARKS_SAVED 2 +#define GREENZONE_SAVED 4 +#define HISTORY_SAVED 8 +#define LIST_SAVED 16 +#define SELECTION_SAVED 32 +#define ALL_SAVED MARKERS_SAVED|BOOKMARKS_SAVED|GREENZONE_SAVED|HISTORY_SAVED|LIST_SAVED|SELECTION_SAVED + +extern MARKERS current_markers; extern BOOKMARKS bookmarks; extern SCREENSHOT_DISPLAY screenshot_display; extern GREENZONE greenzone; @@ -58,12 +67,16 @@ bool TASEDIT_PROJECT::save() currMovieData.loadFrameCount = currMovieData.records.size(); currMovieData.dump(ofs, true); - markers.save(ofs); + + // save all modules + unsigned int saved_stuff = ALL_SAVED; + write32le(saved_stuff, ofs); + current_markers.save(ofs); bookmarks.save(ofs); greenzone.save(ofs); history.save(ofs); - selection.save(ofs); tasedit_list.save(ofs); + selection.save(ofs); delete ofs; @@ -71,18 +84,28 @@ bool TASEDIT_PROJECT::save() this->reset(); return true; } -bool TASEDIT_PROJECT::save_compact(char* filename, bool save_binary, bool save_markers, bool save_bookmarks, bool save_greenzone, bool save_history, bool save_selection, bool save_list) +bool TASEDIT_PROJECT::save_compact(char* filename, bool save_binary, bool save_markers, bool save_bookmarks, bool save_greenzone, bool save_history, bool save_list, bool save_selection) { EMUFILE_FILE* ofs = FCEUD_UTF8_fstream(filename,"wb"); currMovieData.loadFrameCount = currMovieData.records.size(); currMovieData.dump(ofs, save_binary); - markers.save(ofs, save_markers); + + // save specified modules + unsigned int saved_stuff = 0; + if (save_markers) saved_stuff |= MARKERS_SAVED; + if (save_bookmarks) saved_stuff |= BOOKMARKS_SAVED; + if (save_greenzone) saved_stuff |= GREENZONE_SAVED; + if (save_history) saved_stuff |= HISTORY_SAVED; + if (save_list) saved_stuff |= LIST_SAVED; + if (save_selection) saved_stuff |= SELECTION_SAVED; + write32le(saved_stuff, ofs); + current_markers.save(ofs, save_markers); bookmarks.save(ofs, save_bookmarks); greenzone.save(ofs, save_greenzone); history.save(ofs, save_history); - selection.save(ofs, save_selection); tasedit_list.save(ofs, save_list); + selection.save(ofs, save_selection); delete ofs; @@ -106,18 +129,24 @@ bool TASEDIT_PROJECT::load(char* fullname) if (LoadFM2(tempMovieData, &ifs, ifs.size(), false)) { currMovieData = tempMovieData; + currMovieData.emuVersion = FCEU_VERSION_NUMERIC; LoadSubtitles(currMovieData); } else { FCEU_PrintError("Error loading movie data from %s!", fullname); return false; } - markers.load(&ifs); + + // load modules + unsigned int saved_stuff; + read32le(&saved_stuff, &ifs); + current_markers.load(&ifs); bookmarks.load(&ifs); greenzone.load(&ifs); history.load(&ifs); - selection.load(&ifs); tasedit_list.load(&ifs); + selection.load(&ifs); + playback.reset(); recorder.reset(); diff --git a/src/drivers/win/taseditlib/taseditproj.h b/src/drivers/win/taseditlib/taseditproj.h index ebe3343b..23a2d752 100644 --- a/src/drivers/win/taseditlib/taseditproj.h +++ b/src/drivers/win/taseditlib/taseditproj.h @@ -5,12 +5,12 @@ typedef std::set SelectionFrames; #include #include "movie.h" #include "../common.h" +#include "markers.h" #include "inputsnapshot.h" #include "inputhistory.h" #include "playback.h" #include "recorder.h" #include "greenzone.h" -#include "markers.h" #include "bookmarks.h" #include "tasedit_list.h" #include "tasedit_sel.h" @@ -27,7 +27,7 @@ public: void update(); bool save(); - bool save_compact(char* filename, bool save_binary, bool save_markers, bool save_bookmarks, bool save_greenzone, bool save_history, bool save_selection, bool save_list); + bool save_compact(char* filename, bool save_binary, bool save_markers, bool save_bookmarks, bool save_greenzone, bool save_history, bool save_list, bool save_selection); bool load(char* fullname); void RenameProject(char* new_fullname); @@ -49,6 +49,6 @@ private: std::string projectFile; // full path std::string projectName; // file name only - std::string fm2FileName; // same as projectName but with .fm2 extension instead of .tas + std::string fm2FileName; // same as projectName but with .fm2 extension instead of .fm3 }; diff --git a/src/drivers/win/window.cpp b/src/drivers/win/window.cpp index 58da9844..7ced344c 100644 --- a/src/drivers/win/window.cpp +++ b/src/drivers/win/window.cpp @@ -126,7 +126,6 @@ bool AVIdisableMovieMessages = false; char *md5_asciistr(uint8 digest[16]); static int winwidth, winheight; static volatile int nofocus = 0; -extern bool TASEdit_focus; static int tog = 0; //Toggle for Hide Menu static bool loggingSound = false; static LONG WindowXC=1<<30,WindowYC; @@ -1490,19 +1489,21 @@ LRESULT FAR PASCAL AppWndProc(HWND hWnd,UINT msg,WPARAM wParam,LPARAM lParam) } } //------------------------------------------------------- - //Check if TAS Editor file + //Check if TAS Editor project file //------------------------------------------------------- - else if (!(fileDropped.find(".tas") == string::npos) && (fileDropped.find(".tas") == fileDropped.length()-4)) //ROM is already loaded and .tas in filename + else if (!(fileDropped.find(".fm3") == string::npos) && (fileDropped.find(".fm3") == fileDropped.length()-4)) //ROM is already loaded and .fm3 in filename { if (!GameInfo) //If no game is loaded, load the Open Game dialog LoadNewGamey(hWnd, 0); - if (GameInfo && !(fileDropped.find(".tas") == string::npos)) + if (GameInfo && !(fileDropped.find(".fm3") == string::npos)) { - //.tas is at the end of the filename so that must be the extension + //.fm3 is at the end of the filename so that must be the extension extern bool EnterTasEdit(); extern bool LoadProject(char* fullname); + extern bool AskSaveProject(); if (EnterTasEdit()) //We are convinced it is a TAS Editor project file, attempt to load in TAS Editor - LoadProject(ftmp); + if (AskSaveProject()) // in case there's unsaved project + LoadProject(ftmp); } } //------------------------------------------------------- @@ -2276,7 +2277,7 @@ adelikat: Outsourced this to a remappable hotkey EnableMenuItem(fceumenu,MENU_POWER,MF_BYCOMMAND | (FCEU_IsValidUI(FCEUI_POWER)?MF_ENABLED:MF_GRAYED)); EnableMenuItem(fceumenu,MENU_TASEDIT,MF_BYCOMMAND | (FCEU_IsValidUI(FCEUI_TASEDIT)?MF_ENABLED:MF_GRAYED)); EnableMenuItem(fceumenu,MENU_CLOSE_FILE,MF_BYCOMMAND | (FCEU_IsValidUI(FCEUI_CLOSEGAME) && GameInfo ?MF_ENABLED:MF_GRAYED)); - EnableMenuItem(fceumenu,MENU_RECENT_FILES,MF_BYCOMMAND | ((FCEU_IsValidUI(FCEUI_OPENGAME) && HasRecentFiles()) ?MF_ENABLED:MF_GRAYED)); //adelikat - added && recent_files, otherwise this line prevents recent from ever being gray when tasedit is not engaged + EnableMenuItem(fceumenu,MENU_RECENT_FILES,MF_BYCOMMAND | ((FCEU_IsValidUI(FCEUI_OPENGAME) && HasRecentFiles()) ?MF_ENABLED:MF_GRAYED)); //adelikat - added && recent_files, otherwise this line prevents recent from ever being gray when TAS Editor is not engaged EnableMenuItem(fceumenu,MENU_OPEN_FILE,MF_BYCOMMAND | (FCEU_IsValidUI(FCEUI_OPENGAME)?MF_ENABLED:MF_GRAYED)); EnableMenuItem(fceumenu,MENU_RECORD_MOVIE,MF_BYCOMMAND | (FCEU_IsValidUI(FCEUI_RECORDMOVIE)?MF_ENABLED:MF_GRAYED)); EnableMenuItem(fceumenu,MENU_REPLAY_MOVIE,MF_BYCOMMAND | (FCEU_IsValidUI(FCEUI_PLAYMOVIE)?MF_ENABLED:MF_GRAYED)); @@ -2860,7 +2861,7 @@ void UpdateMenuHotkeys() combined = "&Memory Watch...\t" + combo; ChangeMenuItemText(MENU_MEMORY_WATCH, combined); - //Open TAS Edit + //Open TAS Editor combo = GetKeyComboName(FCEUD_CommandMapping[EMUCMD_MISC_OPENTASEDIT]); combined = "&TAS Editor...\t" + combo; ChangeMenuItemText(MENU_TASEDIT, combined); diff --git a/src/input.cpp b/src/input.cpp index 994d81dd..d3e8912a 100644 --- a/src/input.cpp +++ b/src/input.cpp @@ -52,6 +52,7 @@ #include "drivers/win/window.h" #include "drivers/win/ntview.h" +#include "./drivers/win/taseditlib/markers.h" #include "./drivers/win/taseditlib/inputsnapshot.h" #include "./drivers/win/taseditlib/bookmarks.h" extern bool Tasedit_rewind_now;