* Taseditor: quicksave/quickload hotkeys save/load current branch
* Taseditor: Help->Show Tooltips * Added "Restore Playback (TAS Editor)" hotkey (Enter by default) * 9 new Lua functions in TAS Editor library
This commit is contained in:
parent
d509d8ecac
commit
a1e0de898b
|
@ -17,8 +17,8 @@ pads = {
|
|||
buttons = {
|
||||
A = {x=30,y=5,w=3,h=3},
|
||||
B = {x=24,y=5,w=3,h=3},
|
||||
start = {x=12,y=7,w=3,h=1},
|
||||
select = {x=18,y=7,w=3,h=1},
|
||||
start = {x=12,y=7,w=3,h=1},
|
||||
up = {x=4, y=1,w=2,h=2},
|
||||
down = {x=4, y=7,w=2,h=2},
|
||||
left = {x=1, y=4,w=2,h=2},
|
||||
|
|
|
@ -342,6 +342,8 @@ static CFGSTRUCT fceuconfig[] = {
|
|||
AC(taseditor_config.savecompact_selection),
|
||||
AC(taseditor_config.findnote_matchcase),
|
||||
AC(taseditor_config.findnote_search_up),
|
||||
AC(taseditor_config.silent_autosave),
|
||||
AC(taseditor_config.tooltips),
|
||||
ACS(taseditor_config_last_author),
|
||||
AC(lagCounterDisplay),
|
||||
AC(oldInputDisplay),
|
||||
|
|
|
@ -75,6 +75,7 @@ static struct
|
|||
{ EMUCMD_MISC_TOGGLEFULLSCREEN, SCAN_ENTER | CMD_KEY_ALT, },
|
||||
{ EMUCMD_TASEDITOR_REWIND, SCAN_ESCAPE, },
|
||||
{ EMUCMD_RERECORD_DISPLAY_TOGGLE, SCAN_M, },
|
||||
{ EMUCMD_TASEDITOR_RESTORE_PLAYBACK, SCAN_ENTER, },
|
||||
};
|
||||
|
||||
#define NUM_DEFAULT_MAPPINGS (sizeof(DefaultCommandMapping)/sizeof(DefaultCommandMapping[0]))
|
||||
|
|
|
@ -255,8 +255,7 @@ BEGIN
|
|||
MENUITEM "&Insert\tShift+Ins", ID_EDIT_INSERTFRAMES
|
||||
MENUITEM "Insert # of Frames\tIns", ID_EDIT_INSERT
|
||||
MENUITEM SEPARATOR
|
||||
MENUITEM "Truncate\tCtrl+T", ID_EDIT_TRUNCATE
|
||||
MENUITEM SEPARATOR
|
||||
MENUITEM "Truncate movie", ID_EDIT_TRUNCATE
|
||||
END
|
||||
POPUP "&View"
|
||||
BEGIN
|
||||
|
@ -296,7 +295,8 @@ BEGIN
|
|||
END
|
||||
POPUP "&Help"
|
||||
BEGIN
|
||||
MENUITEM "&TAS Editor Help", ID_HELP_TASEDITORHELP
|
||||
MENUITEM "TAS Editor &Help", ID_HELP_TASEDITORHELP
|
||||
MENUITEM "Enable &Tooltips", ID_HELP_TOOLTIPS
|
||||
MENUITEM SEPARATOR
|
||||
MENUITEM "&About", ID_HELP_ABOUT
|
||||
END
|
||||
|
@ -376,15 +376,16 @@ TASEDITORCONTEXTMENUS MENU
|
|||
BEGIN
|
||||
POPUP "Stray"
|
||||
BEGIN
|
||||
MENUITEM "Insert # of Frames", MENU_CONTEXT_STRAY_INSERTFRAMES
|
||||
MENUITEM "Unpause emulator", ID_STRAY_UNPAUSE
|
||||
MENUITEM SEPARATOR
|
||||
MENUITEM "Truncate movie", ID_CONTEXT_STRAY_TRUNCATE
|
||||
MENUITEM "Insert # of Frames", MENU_CONTEXT_STRAY_INSERTFRAMES
|
||||
MENUITEM "Truncate movie", ID_STRAY_TRUNCATE
|
||||
END
|
||||
POPUP "Selected"
|
||||
BEGIN
|
||||
MENUITEM "Set Marker", ID_SELECTED_SETMARKER
|
||||
MENUITEM "Remove Marker", ID_SELECTED_REMOVEMARKER
|
||||
MENUITEM "Select mid &Markers", ID_SELECTED_SELECTMIDMARKERS
|
||||
MENUITEM "Select between &Markers", ID_SELECTED_SELECTMIDMARKERS
|
||||
MENUITEM SEPARATOR
|
||||
MENUITEM "C&lear", ID_CONTEXT_SELECTED_CLEARFRAMES
|
||||
MENUITEM "&Delete", ID_CONTEXT_SELECTED_DELETEFRAMES
|
||||
|
@ -1649,6 +1650,7 @@ END
|
|||
|
||||
IDD_LUA DIALOGEX 0, 0, 270, 150
|
||||
STYLE DS_SETFONT | DS_FIXEDSYS | WS_MINIMIZEBOX | WS_POPUP | WS_CLIPCHILDREN | WS_CAPTION | WS_SYSMENU | WS_THICKFRAME
|
||||
EXSTYLE WS_EX_APPWINDOW
|
||||
CAPTION "Lua Script"
|
||||
MENU LUAWINDOW_MENU
|
||||
FONT 8, "MS Shell Dlg", 400, 0, 0x1
|
||||
|
@ -2189,7 +2191,6 @@ BEGIN
|
|||
VK_PRIOR, ACCEL_CTRL_PGUP, VIRTKEY, CONTROL, NOINVERT
|
||||
"Q", ACCEL_CTRL_Q, VIRTKEY, CONTROL, NOINVERT
|
||||
"S", ACCEL_CTRL_S, VIRTKEY, CONTROL, NOINVERT
|
||||
"T", ACCEL_CTRL_T, VIRTKEY, CONTROL, NOINVERT
|
||||
"V", ACCEL_CTRL_V, VIRTKEY, CONTROL, NOINVERT
|
||||
"W", ACCEL_CTRL_W, VIRTKEY, CONTROL, NOINVERT
|
||||
"X", ACCEL_CTRL_X, VIRTKEY, CONTROL, NOINVERT
|
||||
|
@ -2243,7 +2244,8 @@ IDB_BITMAP16 BITMAP "res\\te_16.bmp"
|
|||
IDB_BITMAP17 BITMAP "res\\te_17.bmp"
|
||||
IDB_BITMAP18 BITMAP "res\\te_18.bmp"
|
||||
IDB_BITMAP19 BITMAP "res\\te_19.bmp"
|
||||
IDB_TE_ARROW BITMAP "res/te_arrow.bmp"
|
||||
IDB_TE_ARROW BITMAP "res\\te_arrow.bmp"
|
||||
IDB_TE_GREEN_ARROW BITMAP "res\\te_green_arrow.bmp"
|
||||
IDB_BRANCH_SPRITESHEET BITMAP "res\\branch_spritesheet.bmp"
|
||||
#endif // Àíãëèéñêèé (ÑØÀ) resources
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
|
|
|
@ -234,6 +234,8 @@
|
|||
#define IDC_DEBUGGER_FLAG_D 204
|
||||
#define IDC_NETMOO_KEY 205
|
||||
#define IDC_DEBUGGER_FLAG_I 205
|
||||
#define IDB_BITMAP20 205
|
||||
#define IDB_TE_GREEN_ARROW 205
|
||||
#define IDC_NETMOO_PASS 206
|
||||
#define IDC_DEBUGGER_FLAG_Z 206
|
||||
#define IDC_DEBUGGER_FLAG_C 207
|
||||
|
@ -977,6 +979,11 @@
|
|||
#define ID_HELP_TASEDITORHELP 40523
|
||||
#define MENU_TASEDITOR 40524
|
||||
#define ID_FILE_NEW 40525
|
||||
#define ID_HELP_SHOWTOOLTIPS 40526
|
||||
#define ID_HELP_TOOLTIPS 40527
|
||||
#define ID_STRAY_UNPAUSEEMULATOR 40528
|
||||
#define ID_STRAY_UNPAUSE 40529
|
||||
#define ID_STRAY_TRUNCATE40530 40530
|
||||
#define IDC_DEBUGGER_ICONTRAY 55535
|
||||
#define MW_ValueLabel2 65423
|
||||
#define MW_ValueLabel1 65426
|
||||
|
@ -985,8 +992,8 @@
|
|||
//
|
||||
#ifdef APSTUDIO_INVOKED
|
||||
#ifndef APSTUDIO_READONLY_SYMBOLS
|
||||
#define _APS_NEXT_RESOURCE_VALUE 203
|
||||
#define _APS_NEXT_COMMAND_VALUE 40526
|
||||
#define _APS_NEXT_RESOURCE_VALUE 206
|
||||
#define _APS_NEXT_COMMAND_VALUE 40531
|
||||
#define _APS_NEXT_CONTROL_VALUE 1280
|
||||
#define _APS_NEXT_SYMED_VALUE 101
|
||||
#endif
|
||||
|
|
|
@ -6,29 +6,22 @@
|
|||
#include "main.h" // for GetRomName
|
||||
#include "taseditor.h"
|
||||
#include "version.h"
|
||||
#include <Shlwapi.h> // for StrStrI
|
||||
|
||||
#pragma comment(lib, "Shlwapi.lib")
|
||||
|
||||
using namespace std;
|
||||
|
||||
// TAS Editor data
|
||||
bool Taseditor_rewind_now = false;
|
||||
bool must_call_manual_lua_function = false;
|
||||
// note editing/search (probably should be moved to separate class/module)
|
||||
int marker_note_edit = MARKER_NOTE_EDIT_NONE;
|
||||
char findnote_string[MAX_NOTE_LEN] = {0};
|
||||
int search_similar_marker = 0;
|
||||
|
||||
// all Taseditor functional modules
|
||||
TASEDITOR_CONFIG taseditor_config;
|
||||
TASEDITOR_WINDOW taseditor_window;
|
||||
TASEDITOR_PROJECT project;
|
||||
INPUT_HISTORY history;
|
||||
HISTORY history;
|
||||
PLAYBACK playback;
|
||||
RECORDER recorder;
|
||||
GREENZONE greenzone;
|
||||
MARKERS current_markers;
|
||||
MARKERS_MANAGER markers_manager;
|
||||
BOOKMARKS bookmarks;
|
||||
POPUP_DISPLAY popup_display;
|
||||
TASEDITOR_LIST list;
|
||||
|
@ -61,7 +54,7 @@ void UpdateTasEditor()
|
|||
// update all modules that need to be updated every frame
|
||||
recorder.update();
|
||||
list.update();
|
||||
current_markers.update();
|
||||
markers_manager.update();
|
||||
greenzone.update();
|
||||
playback.update();
|
||||
bookmarks.update();
|
||||
|
@ -81,187 +74,6 @@ void UpdateTasEditor()
|
|||
}
|
||||
}
|
||||
|
||||
void SingleClick(LPNMITEMACTIVATE info)
|
||||
{
|
||||
int row_index = info->iItem;
|
||||
if(row_index == -1) return;
|
||||
int column_index = info->iSubItem;
|
||||
|
||||
if(column_index == COLUMN_ICONS)
|
||||
{
|
||||
// click on the "icons" column - jump to the frame
|
||||
selection.ClearSelection();
|
||||
playback.jump(row_index);
|
||||
} else if(column_index == COLUMN_FRAMENUM || column_index == COLUMN_FRAMENUM2)
|
||||
{
|
||||
// click on the "frame number" column - set marker if clicked with Alt
|
||||
if (info->uKeyFlags & LVKF_ALT)
|
||||
{
|
||||
// reverse MARKER_FLAG_BIT in pointed frame
|
||||
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.RegisterMarkersChange(MODTYPE_MARKER_UNSET, row_index);
|
||||
list.RedrawRow(row_index);
|
||||
}
|
||||
}
|
||||
else if(column_index >= COLUMN_JOYPAD1_A && column_index <= COLUMN_JOYPAD4_R)
|
||||
{
|
||||
ToggleJoypadBit(column_index, row_index, info->uKeyFlags);
|
||||
}
|
||||
}
|
||||
void DoubleClick(LPNMITEMACTIVATE info)
|
||||
{
|
||||
int row_index = info->iItem;
|
||||
if(row_index == -1) return;
|
||||
int column_index = info->iSubItem;
|
||||
|
||||
if(column_index == COLUMN_ICONS || column_index == COLUMN_FRAMENUM || column_index == COLUMN_FRAMENUM2)
|
||||
{
|
||||
// double click sends playback to the frame
|
||||
selection.ClearSelection();
|
||||
playback.jump(row_index);
|
||||
} else if(column_index >= COLUMN_JOYPAD1_A && column_index <= COLUMN_JOYPAD4_R)
|
||||
{
|
||||
ToggleJoypadBit(column_index, row_index, info->uKeyFlags);
|
||||
}
|
||||
}
|
||||
|
||||
void ToggleJoypadBit(int column_index, int row_index, UINT KeyFlags)
|
||||
{
|
||||
int joy = (column_index - COLUMN_JOYPAD1_A) / NUM_JOYPAD_BUTTONS;
|
||||
int bit = (column_index - COLUMN_JOYPAD1_A) % NUM_JOYPAD_BUTTONS;
|
||||
if (KeyFlags & (LVKF_SHIFT|LVKF_CONTROL))
|
||||
{
|
||||
// update multiple rows, using last row index as a flag to decide operation
|
||||
SelectionFrames* current_selection = selection.MakeStrobe();
|
||||
SelectionFrames::iterator current_selection_end(current_selection->end());
|
||||
if (currMovieData.records[row_index].checkBit(joy, bit))
|
||||
{
|
||||
// clear range
|
||||
for(SelectionFrames::iterator it(current_selection->begin()); it != current_selection_end; it++)
|
||||
{
|
||||
currMovieData.records[*it].clearBit(joy, bit);
|
||||
}
|
||||
greenzone.InvalidateAndCheck(history.RegisterChanges(MODTYPE_UNSET, *current_selection->begin(), *current_selection->rbegin()));
|
||||
} else
|
||||
{
|
||||
// set range
|
||||
for(SelectionFrames::iterator it(current_selection->begin()); it != current_selection_end; it++)
|
||||
{
|
||||
currMovieData.records[*it].setBit(joy, bit);
|
||||
}
|
||||
greenzone.InvalidateAndCheck(history.RegisterChanges(MODTYPE_SET, *current_selection->begin(), *current_selection->rbegin()));
|
||||
}
|
||||
} else
|
||||
{
|
||||
// update one row
|
||||
currMovieData.records[row_index].toggleBit(joy, bit);
|
||||
if (currMovieData.records[row_index].checkBit(joy, bit))
|
||||
greenzone.InvalidateAndCheck(history.RegisterChanges(MODTYPE_SET, row_index, row_index));
|
||||
else
|
||||
greenzone.InvalidateAndCheck(history.RegisterChanges(MODTYPE_UNSET, row_index, row_index));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void ColumnSet(int column)
|
||||
{
|
||||
if (column == COLUMN_FRAMENUM || column == COLUMN_FRAMENUM2)
|
||||
FrameColumnSet();
|
||||
else
|
||||
InputColumnSet(column);
|
||||
}
|
||||
void FrameColumnSet()
|
||||
{
|
||||
SelectionFrames* current_selection = selection.MakeStrobe();
|
||||
if (current_selection->size() == 0) return;
|
||||
SelectionFrames::iterator current_selection_begin(current_selection->begin());
|
||||
SelectionFrames::iterator current_selection_end(current_selection->end());
|
||||
|
||||
// inspect the selected frames, if they are all set, then unset all, else set all
|
||||
bool unset_found = false, changes_made = false;
|
||||
for(SelectionFrames::iterator it(current_selection_begin); it != current_selection_end; it++)
|
||||
{
|
||||
if(!current_markers.GetMarker(*it))
|
||||
{
|
||||
unset_found = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (unset_found)
|
||||
{
|
||||
// set all
|
||||
for(SelectionFrames::iterator it(current_selection_begin); it != current_selection_end; it++)
|
||||
{
|
||||
if(!current_markers.GetMarker(*it))
|
||||
{
|
||||
if (current_markers.SetMarker(*it))
|
||||
{
|
||||
changes_made = true;
|
||||
list.RedrawRow(*it);
|
||||
}
|
||||
}
|
||||
}
|
||||
if (changes_made)
|
||||
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(current_markers.GetMarker(*it))
|
||||
{
|
||||
current_markers.ClearMarker(*it);
|
||||
changes_made = true;
|
||||
list.RedrawRow(*it);
|
||||
}
|
||||
}
|
||||
if (changes_made)
|
||||
history.RegisterMarkersChange(MODTYPE_MARKER_UNSET, *current_selection_begin, *current_selection->rbegin());
|
||||
}
|
||||
if (changes_made)
|
||||
{
|
||||
selection.must_find_current_marker = playback.must_find_current_marker = true;
|
||||
list.SetHeaderColumnLight(COLUMN_FRAMENUM, HEADER_LIGHT_MAX);
|
||||
}
|
||||
}
|
||||
void InputColumnSet(int column)
|
||||
{
|
||||
int joy = (column - COLUMN_JOYPAD1_A) / NUM_JOYPAD_BUTTONS;
|
||||
if (joy < 0 || joy >= joysticks_per_frame[GetInputType(currMovieData)]) return;
|
||||
int button = (column - COLUMN_JOYPAD1_A) % NUM_JOYPAD_BUTTONS;
|
||||
|
||||
SelectionFrames* current_selection = selection.MakeStrobe();
|
||||
if (current_selection->size() == 0) return;
|
||||
SelectionFrames::iterator current_selection_begin(current_selection->begin());
|
||||
SelectionFrames::iterator current_selection_end(current_selection->end());
|
||||
|
||||
//inspect the selected frames, if they are all set, then unset all, else set all
|
||||
bool newValue = false;
|
||||
for(SelectionFrames::iterator it(current_selection_begin); it != current_selection_end; it++)
|
||||
{
|
||||
if(!(currMovieData.records[*it].checkBit(joy,button)))
|
||||
{
|
||||
newValue = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
// apply newValue
|
||||
for(SelectionFrames::iterator it(current_selection_begin); it != current_selection_end; it++)
|
||||
currMovieData.records[*it].setBitValue(joy,button,newValue);
|
||||
if (newValue)
|
||||
{
|
||||
greenzone.InvalidateAndCheck(history.RegisterChanges(MODTYPE_SET, *current_selection_begin, *current_selection->rbegin()));
|
||||
} else
|
||||
{
|
||||
greenzone.InvalidateAndCheck(history.RegisterChanges(MODTYPE_UNSET, *current_selection_begin, *current_selection->rbegin()));
|
||||
}
|
||||
list.SetHeaderColumnLight(column, HEADER_LIGHT_MAX);
|
||||
}
|
||||
|
||||
BOOL CALLBACK NewProjectProc(HWND hwndDlg, UINT message, WPARAM wParam, LPARAM lParam)
|
||||
{
|
||||
static struct NewProjectParameters* p = NULL;
|
||||
|
@ -360,10 +172,11 @@ void NewProject()
|
|||
// copy input from current snapshot (from history)
|
||||
history.GetCurrentSnapshot().toMovie(currMovieData);
|
||||
if (!params.copy_current_markers)
|
||||
current_markers.reset();
|
||||
markers_manager.reset();
|
||||
if(params.author_name != L"") currMovieData.comments.push_back(L"author " + params.author_name);
|
||||
|
||||
// reset Taseditor
|
||||
project.init(); // new project has blank name
|
||||
greenzone.reset();
|
||||
playback.reset();
|
||||
playback.StartFromZero();
|
||||
|
@ -374,11 +187,8 @@ void NewProject()
|
|||
splicer.reset();
|
||||
recorder.reset();
|
||||
popup_display.reset();
|
||||
project.reset();
|
||||
taseditor_window.RedrawTaseditor();
|
||||
taseditor_window.UpdateCaption();
|
||||
search_similar_marker = 0;
|
||||
marker_note_edit = MARKER_NOTE_EDIT_NONE;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -411,8 +221,6 @@ void OpenProject()
|
|||
}
|
||||
bool LoadProject(char* fullname)
|
||||
{
|
||||
marker_note_edit = MARKER_NOTE_EDIT_NONE;
|
||||
SetFocus(list.hwndList);
|
||||
// try to load project
|
||||
if (project.load(fullname))
|
||||
{
|
||||
|
@ -422,14 +230,12 @@ bool LoadProject(char* fullname)
|
|||
taseditor_window.UpdateRecentProjectsArray(fullname);
|
||||
taseditor_window.RedrawTaseditor();
|
||||
taseditor_window.UpdateCaption();
|
||||
search_similar_marker = 0;
|
||||
return true;
|
||||
} else
|
||||
{
|
||||
// failed to load
|
||||
taseditor_window.RedrawTaseditor();
|
||||
taseditor_window.UpdateCaption();
|
||||
search_similar_marker = 0;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
@ -731,15 +537,15 @@ void Export()
|
|||
char framenum[11];
|
||||
std::string subtitle;
|
||||
int marker_id;
|
||||
for (int i = 0; i < current_markers.GetMarkersSize(); ++i)
|
||||
for (int i = 0; i < markers_manager.GetMarkersSize(); ++i)
|
||||
{
|
||||
marker_id = current_markers.GetMarker(i);
|
||||
marker_id = markers_manager.GetMarker(i);
|
||||
if (marker_id)
|
||||
{
|
||||
_itoa(i, framenum, 10);
|
||||
strcat(framenum, " ");
|
||||
subtitle = framenum;
|
||||
subtitle.append(current_markers.GetNote(marker_id));
|
||||
subtitle.append(markers_manager.GetNote(marker_id));
|
||||
temp_md.subtitles.push_back(subtitle);
|
||||
}
|
||||
}
|
||||
|
@ -761,7 +567,7 @@ bool EnterTasEditor()
|
|||
taseditor_window.init();
|
||||
if(taseditor_window.hwndTasEditor)
|
||||
{
|
||||
SetTaseditInput();
|
||||
SetTaseditorInput();
|
||||
// save "eoptions"
|
||||
saved_eoptions = eoptions;
|
||||
// set "Run in background"
|
||||
|
@ -783,7 +589,7 @@ bool EnterTasEditor()
|
|||
playback.init();
|
||||
greenzone.init();
|
||||
recorder.init();
|
||||
current_markers.init();
|
||||
markers_manager.init();
|
||||
project.init();
|
||||
bookmarks.init();
|
||||
popup_display.init();
|
||||
|
@ -809,7 +615,6 @@ bool EnterTasEditor()
|
|||
FCEUI_StopMovie();
|
||||
movieMode = MOVIEMODE_TASEDITOR;
|
||||
currMovieData.emuVersion = FCEU_VERSION_NUMERIC;
|
||||
greenzone.TryDumpIncremental(lagFlag != 0);
|
||||
}
|
||||
// ensure that movie has correct set of ports/fourscore
|
||||
SetInputType(currMovieData, GetInputType(currMovieData));
|
||||
|
@ -822,12 +627,11 @@ bool EnterTasEditor()
|
|||
history.reset();
|
||||
// reset Taseditor variables
|
||||
must_call_manual_lua_function = false;
|
||||
marker_note_edit = MARKER_NOTE_EDIT_NONE;
|
||||
search_similar_marker = 0;
|
||||
|
||||
SetFocus(history.hwndHistoryList); // set focus only once, to show selection cursor
|
||||
SetFocus(list.hwndList);
|
||||
FCEU_DispMessage("TAS Editor engaged", 0);
|
||||
taseditor_window.RedrawTaseditor();
|
||||
return true;
|
||||
} else return false;
|
||||
} else return true;
|
||||
|
@ -841,7 +645,7 @@ bool ExitTasEditor()
|
|||
taseditor_window.exit();
|
||||
// release memory
|
||||
list.free();
|
||||
current_markers.free();
|
||||
markers_manager.free();
|
||||
greenzone.free();
|
||||
bookmarks.free();
|
||||
popup_display.free();
|
||||
|
@ -849,7 +653,7 @@ bool ExitTasEditor()
|
|||
playback.SeekingStop();
|
||||
selection.free();
|
||||
|
||||
ClearTaseditInput();
|
||||
ClearTaseditorInput();
|
||||
// restore "eoptions"
|
||||
eoptions = saved_eoptions;
|
||||
// restore autosaves
|
||||
|
@ -900,184 +704,16 @@ void SetInputType(MovieData& md, int new_input_type)
|
|||
}
|
||||
}
|
||||
|
||||
void SetTaseditInput()
|
||||
void SetTaseditorInput()
|
||||
{
|
||||
// set "Background TAS Editor input"
|
||||
KeyboardSetBackgroundAccessBit(KEYBACKACCESS_TASEDITOR);
|
||||
JoystickSetBackgroundAccessBit(JOYBACKACCESS_TASEDITOR);
|
||||
}
|
||||
void ClearTaseditInput()
|
||||
void ClearTaseditorInput()
|
||||
{
|
||||
// clear "Background TAS Editor input"
|
||||
KeyboardClearBackgroundAccessBit(KEYBACKACCESS_TASEDITOR);
|
||||
JoystickClearBackgroundAccessBit(JOYBACKACCESS_TASEDITOR);
|
||||
}
|
||||
|
||||
void UpdateMarkerNote()
|
||||
{
|
||||
if (!marker_note_edit) return;
|
||||
char 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
|
||||
if (strcmp(current_markers.GetNote(playback.shown_marker).c_str(), 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
|
||||
if (strcmp(current_markers.GetNote(selection.shown_marker).c_str(), 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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
BOOL CALLBACK FindNoteProc(HWND hwndDlg, UINT message, WPARAM wParam, LPARAM lParam)
|
||||
{
|
||||
switch (message)
|
||||
{
|
||||
case WM_INITDIALOG:
|
||||
{
|
||||
if (taseditor_config.findnote_wndx == -32000) taseditor_config.findnote_wndx = 0; //Just in case
|
||||
if (taseditor_config.findnote_wndy == -32000) taseditor_config.findnote_wndy = 0;
|
||||
SetWindowPos(hwndDlg, 0, taseditor_config.findnote_wndx, taseditor_config.findnote_wndy, 0, 0, SWP_NOSIZE | SWP_NOZORDER | SWP_NOOWNERZORDER);
|
||||
|
||||
CheckDlgButton(hwndDlg, IDC_MATCH_CASE, taseditor_config.findnote_matchcase?MF_CHECKED : MF_UNCHECKED);
|
||||
if (taseditor_config.findnote_search_up)
|
||||
Button_SetCheck(GetDlgItem(hwndDlg, IDC_RADIO_UP), BST_CHECKED);
|
||||
else
|
||||
Button_SetCheck(GetDlgItem(hwndDlg, IDC_RADIO_DOWN), BST_CHECKED);
|
||||
HWND hwndEdit = GetDlgItem(hwndDlg, IDC_NOTE_TO_FIND);
|
||||
SendMessage(hwndEdit, EM_SETLIMITTEXT, MAX_NOTE_LEN - 1, 0);
|
||||
SetWindowText(hwndEdit, findnote_string);
|
||||
if (GetDlgCtrlID((HWND)wParam) != IDC_NOTE_TO_FIND)
|
||||
{
|
||||
SetFocus(hwndEdit);
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
case WM_MOVE:
|
||||
{
|
||||
if (!IsIconic(hwndDlg))
|
||||
{
|
||||
RECT wrect;
|
||||
GetWindowRect(hwndDlg, &wrect);
|
||||
taseditor_config.findnote_wndx = wrect.left;
|
||||
taseditor_config.findnote_wndy = wrect.top;
|
||||
WindowBoundsCheckNoResize(taseditor_config.findnote_wndx, taseditor_config.findnote_wndy, wrect.right);
|
||||
}
|
||||
break;
|
||||
}
|
||||
case WM_COMMAND:
|
||||
{
|
||||
switch (LOWORD(wParam))
|
||||
{
|
||||
case IDC_NOTE_TO_FIND:
|
||||
{
|
||||
if(HIWORD(wParam) == EN_CHANGE)
|
||||
{
|
||||
if (GetWindowTextLength(GetDlgItem(hwndDlg, IDC_NOTE_TO_FIND)))
|
||||
EnableWindow(GetDlgItem(hwndDlg, IDOK), true);
|
||||
else
|
||||
EnableWindow(GetDlgItem(hwndDlg, IDOK), false);
|
||||
}
|
||||
break;
|
||||
}
|
||||
case IDC_RADIO_UP:
|
||||
taseditor_config.findnote_search_up = true;
|
||||
break;
|
||||
case IDC_RADIO_DOWN:
|
||||
taseditor_config.findnote_search_up = false;
|
||||
break;
|
||||
case IDC_MATCH_CASE:
|
||||
taseditor_config.findnote_matchcase ^= 1;
|
||||
CheckDlgButton(hwndDlg, IDC_MATCH_CASE, taseditor_config.findnote_matchcase?MF_CHECKED : MF_UNCHECKED);
|
||||
break;
|
||||
case IDOK:
|
||||
{
|
||||
int len = SendMessage(GetDlgItem(hwndDlg, IDC_NOTE_TO_FIND), WM_GETTEXT, MAX_NOTE_LEN, (LPARAM)findnote_string);
|
||||
findnote_string[len] = 0;
|
||||
// scan frames from current selection to the border
|
||||
int cur_marker = 0;
|
||||
bool result;
|
||||
int movie_size = currMovieData.getNumRecords();
|
||||
int current_frame = selection.GetCurrentSelectionBeginning();
|
||||
if (current_frame < 0 && taseditor_config.findnote_search_up)
|
||||
current_frame = movie_size;
|
||||
while (true)
|
||||
{
|
||||
// move forward
|
||||
if (taseditor_config.findnote_search_up)
|
||||
{
|
||||
current_frame--;
|
||||
if (current_frame < 0)
|
||||
{
|
||||
MessageBox(taseditor_window.hwndFindNote, "Nothing was found.", "Find Note", MB_OK);
|
||||
break;
|
||||
}
|
||||
} else
|
||||
{
|
||||
current_frame++;
|
||||
if (current_frame >= movie_size)
|
||||
{
|
||||
MessageBox(taseditor_window.hwndFindNote, "Nothing was found!", "Find Note", MB_OK);
|
||||
break;
|
||||
}
|
||||
}
|
||||
// scan marked frames
|
||||
cur_marker = current_markers.GetMarker(current_frame);
|
||||
if (cur_marker)
|
||||
{
|
||||
if (taseditor_config.findnote_matchcase)
|
||||
result = (strstr(current_markers.GetNote(cur_marker).c_str(), findnote_string) != 0);
|
||||
else
|
||||
result = (StrStrI(current_markers.GetNote(cur_marker).c_str(), findnote_string) != 0);
|
||||
if (result)
|
||||
{
|
||||
// found note containing searched string - jump there
|
||||
selection.JumpToFrame(current_frame);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
return TRUE;
|
||||
}
|
||||
case IDCANCEL:
|
||||
DestroyWindow(taseditor_window.hwndFindNote);
|
||||
taseditor_window.hwndFindNote = 0;
|
||||
return TRUE;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case WM_CLOSE:
|
||||
case WM_QUIT:
|
||||
{
|
||||
DestroyWindow(taseditor_window.hwndFindNote);
|
||||
taseditor_window.hwndFindNote = 0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
|
|
|
@ -1,9 +1,4 @@
|
|||
enum
|
||||
{
|
||||
MARKER_NOTE_EDIT_NONE,
|
||||
MARKER_NOTE_EDIT_UPPER,
|
||||
MARKER_NOTE_EDIT_LOWER
|
||||
};
|
||||
// main TAS Editor file
|
||||
|
||||
struct NewProjectParameters
|
||||
{
|
||||
|
@ -13,14 +8,6 @@ struct NewProjectParameters
|
|||
std::wstring author_name;
|
||||
};
|
||||
|
||||
void SingleClick(LPNMITEMACTIVATE info);
|
||||
void DoubleClick(LPNMITEMACTIVATE info);
|
||||
|
||||
void ToggleJoypadBit(int column_index, int row_index, UINT KeyFlags);
|
||||
void ColumnSet(int column);
|
||||
void InputColumnSet(int column);
|
||||
void FrameColumnSet();
|
||||
|
||||
bool EnterTasEditor();
|
||||
bool ExitTasEditor();
|
||||
void UpdateTasEditor();
|
||||
|
@ -39,8 +26,5 @@ void Export();
|
|||
int GetInputType(MovieData& md);
|
||||
void SetInputType(MovieData& md, int new_input_type);
|
||||
|
||||
void SetTaseditInput();
|
||||
void ClearTaseditInput();
|
||||
|
||||
void UpdateMarkerNote();
|
||||
|
||||
void SetTaseditorInput();
|
||||
void ClearTaseditorInput();
|
||||
|
|
|
@ -4,7 +4,7 @@
|
|||
|
||||
extern TASEDITOR_CONFIG taseditor_config;
|
||||
extern GREENZONE greenzone;
|
||||
extern INPUT_HISTORY history;
|
||||
extern HISTORY history;
|
||||
|
||||
extern uint8 *XBuf;
|
||||
extern uint8 *XBackBuf;
|
||||
|
@ -45,16 +45,16 @@ void BOOKMARK::set()
|
|||
flash_type = FLASH_TYPE_SET;
|
||||
}
|
||||
|
||||
void BOOKMARK::jump()
|
||||
void BOOKMARK::jumped()
|
||||
{
|
||||
flash_phase = FLASH_PHASE_MAX;
|
||||
flash_type = FLASH_TYPE_JUMP;
|
||||
}
|
||||
|
||||
void BOOKMARK::unleashed()
|
||||
void BOOKMARK::deployed()
|
||||
{
|
||||
flash_phase = FLASH_PHASE_MAX;
|
||||
flash_type = FLASH_TYPE_UNLEASH;
|
||||
flash_type = FLASH_TYPE_DEPLOY;
|
||||
}
|
||||
|
||||
void BOOKMARK::save(EMUFILE *os)
|
||||
|
|
|
@ -5,7 +5,7 @@ enum
|
|||
{
|
||||
FLASH_TYPE_SET = 0,
|
||||
FLASH_TYPE_JUMP = 1,
|
||||
FLASH_TYPE_UNLEASH = 2,
|
||||
FLASH_TYPE_DEPLOY = 2,
|
||||
};
|
||||
|
||||
#define SCREENSHOT_WIDTH 256
|
||||
|
@ -19,8 +19,8 @@ public:
|
|||
void init();
|
||||
|
||||
void set();
|
||||
void jump();
|
||||
void unleashed();
|
||||
void jumped();
|
||||
void deployed();
|
||||
|
||||
void save(EMUFILE *os);
|
||||
bool load(EMUFILE *is);
|
||||
|
@ -28,7 +28,7 @@ public:
|
|||
bool not_empty;
|
||||
int flash_phase;
|
||||
int flash_type;
|
||||
INPUT_SNAPSHOT snapshot;
|
||||
SNAPSHOT snapshot;
|
||||
std::vector<uint8> savestate;
|
||||
std::vector<uint8> saved_screenshot;
|
||||
int parent_branch;
|
||||
|
|
|
@ -16,11 +16,9 @@ extern PLAYBACK playback;
|
|||
extern TASEDITOR_SELECTION selection;
|
||||
extern GREENZONE greenzone;
|
||||
extern TASEDITOR_PROJECT project;
|
||||
extern INPUT_HISTORY history;
|
||||
extern HISTORY history;
|
||||
extern TASEDITOR_LIST list;
|
||||
extern MARKERS current_markers;
|
||||
|
||||
extern void UpdateMarkerNote();
|
||||
extern MARKERS_MANAGER markers_manager;
|
||||
|
||||
// resources
|
||||
char bookmarks_save_id[BOOKMARKS_ID_LEN] = "BOOKMARKS";
|
||||
|
@ -33,7 +31,7 @@ COLORREF bookmark_flash_colors[3][FLASH_PHASE_MAX+1] = {
|
|||
0x0d1241, 0x111853, 0x161e64, 0x1a2575, 0x1f2b87, 0x233197, 0x2837a8, 0x2c3db9, 0x3144cb, 0x354adc, 0x3a50ed, 0x3f57ff,
|
||||
// jump
|
||||
0x14350f, 0x1c480f, 0x235a0f, 0x2a6c0f, 0x317f10, 0x38910f, 0x3fa30f, 0x46b50f, 0x4dc80f, 0x54da0f, 0x5bec0f, 0x63ff10,
|
||||
// unleash
|
||||
// deploy
|
||||
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 };
|
||||
|
@ -173,6 +171,8 @@ void BOOKMARKS::free()
|
|||
}
|
||||
void BOOKMARKS::reset()
|
||||
{
|
||||
// delete all commands if there are any
|
||||
commands.resize(0);
|
||||
// init bookmarks
|
||||
bookmarks_array.resize(0);
|
||||
bookmarks_array.resize(TOTAL_BOOKMARKS);
|
||||
|
@ -208,6 +208,26 @@ void BOOKMARKS::reset_vars()
|
|||
|
||||
void BOOKMARKS::update()
|
||||
{
|
||||
// execute all commands if needed
|
||||
for (int i = 0; (i + 1) < (int)commands.size(); )
|
||||
{
|
||||
int command_id = commands[i++];
|
||||
int slot = commands[i++];
|
||||
switch (command_id)
|
||||
{
|
||||
case COMMAND_SET:
|
||||
set(slot);
|
||||
break;
|
||||
case COMMAND_JUMP:
|
||||
jump(slot);
|
||||
break;
|
||||
case COMMAND_DEPLOY:
|
||||
deploy(slot);
|
||||
break;
|
||||
}
|
||||
}
|
||||
commands.resize(0);
|
||||
|
||||
// once per 100 milliseconds fade bookmark flashes
|
||||
if (clock() > check_flash_shedule)
|
||||
{
|
||||
|
@ -264,12 +284,38 @@ void BOOKMARKS::update()
|
|||
}
|
||||
}
|
||||
|
||||
// stores commands in array for update() function
|
||||
void BOOKMARKS::command(int command_id, int slot)
|
||||
{
|
||||
switch (command_id)
|
||||
{
|
||||
case COMMAND_SET:
|
||||
{
|
||||
if (slot < 0 || slot >= TOTAL_BOOKMARKS)
|
||||
slot = DEFAULT_BOOKMARK;
|
||||
commands.push_back(command_id);
|
||||
commands.push_back(slot);
|
||||
break;
|
||||
}
|
||||
case COMMAND_JUMP:
|
||||
case COMMAND_DEPLOY:
|
||||
{
|
||||
if (slot >= 0 && slot < TOTAL_BOOKMARKS)
|
||||
{
|
||||
commands.push_back(command_id);
|
||||
commands.push_back(slot);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void BOOKMARKS::set(int slot)
|
||||
{
|
||||
if (slot < 0 || slot >= TOTAL_BOOKMARKS) return;
|
||||
|
||||
// First save edited note (in case it's being currently edited)
|
||||
UpdateMarkerNote();
|
||||
markers_manager.UpdateMarkerNote();
|
||||
|
||||
int previous_frame = bookmarks_array[slot].snapshot.jump_frame;
|
||||
// save time of this slot before rewriting it
|
||||
|
@ -405,13 +451,13 @@ void BOOKMARKS::jump(int slot)
|
|||
{
|
||||
int frame = bookmarks_array[slot].snapshot.jump_frame;
|
||||
playback.jump(frame);
|
||||
if (playback.GetPauseFrame())
|
||||
if (playback.pause_frame)
|
||||
list.FollowPauseframe();
|
||||
bookmarks_array[slot].jump();
|
||||
bookmarks_array[slot].jumped();
|
||||
}
|
||||
}
|
||||
|
||||
void BOOKMARKS::unleash(int slot)
|
||||
void BOOKMARKS::deploy(int slot)
|
||||
{
|
||||
if (taseditor_config.branch_only_when_rec && movie_readonly)
|
||||
{
|
||||
|
@ -424,13 +470,13 @@ void BOOKMARKS::unleash(int slot)
|
|||
int jump_frame = bookmarks_array[slot].snapshot.jump_frame;
|
||||
|
||||
bool markers_changed = false;
|
||||
// revert current movie to the input_snapshot state
|
||||
// revert current movie to the snapshot state
|
||||
if (taseditor_config.branch_full_movie)
|
||||
{
|
||||
// update Markers
|
||||
if (taseditor_config.bind_markers)
|
||||
{
|
||||
if (bookmarks_array[slot].snapshot.my_markers.checkMarkersDiff(current_markers))
|
||||
if (bookmarks_array[slot].snapshot.MarkersDifferFromCurrent())
|
||||
{
|
||||
bookmarks_array[slot].snapshot.copyToMarkers();
|
||||
project.SetProjectChanged();
|
||||
|
@ -447,26 +493,26 @@ void BOOKMARKS::unleash(int slot)
|
|||
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();
|
||||
bookmarks_array[slot].deployed();
|
||||
} 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);
|
||||
list.RedrawList();
|
||||
bookmarks_array[slot].unleashed();
|
||||
bookmarks_array[slot].deployed();
|
||||
} else
|
||||
{
|
||||
// didn't restore anything
|
||||
bookmarks_array[slot].jump();
|
||||
bookmarks_array[slot].jumped();
|
||||
}
|
||||
} else if (jump_frame > 0)
|
||||
{
|
||||
// update Markers
|
||||
if (taseditor_config.bind_markers)
|
||||
{
|
||||
if (bookmarks_array[slot].snapshot.my_markers.checkMarkersDiff(current_markers, jump_frame))
|
||||
if (bookmarks_array[slot].snapshot.MarkersDifferFromCurrent(jump_frame))
|
||||
{
|
||||
bookmarks_array[slot].snapshot.copyToMarkers(jump_frame-1);
|
||||
bookmarks_array[slot].snapshot.copyToMarkers(jump_frame);
|
||||
project.SetProjectChanged();
|
||||
markers_changed = true;
|
||||
}
|
||||
|
@ -482,17 +528,17 @@ void BOOKMARKS::unleash(int slot)
|
|||
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();
|
||||
bookmarks_array[slot].deployed();
|
||||
} 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);
|
||||
list.RedrawList();
|
||||
bookmarks_array[slot].unleashed();
|
||||
bookmarks_array[slot].deployed();
|
||||
} else
|
||||
{
|
||||
// didn't restore anything
|
||||
bookmarks_array[slot].jump();
|
||||
bookmarks_array[slot].jumped();
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -938,7 +984,7 @@ LONG BOOKMARKS::CustomDraw(NMLVCUSTOMDRAW* msg)
|
|||
// frame number
|
||||
SelectObject(msg->nmcd.hdc, list.hMainListFont);
|
||||
int frame = bookmarks_array[cell_y].snapshot.jump_frame;
|
||||
if (frame == currFrameCounter || frame == (playback.GetPauseFrame() - 1))
|
||||
if (frame == currFrameCounter || frame == (playback.GetFlashingPauseFrame() - 1))
|
||||
{
|
||||
// current frame
|
||||
msg->clrTextBk = CUR_FRAMENUM_COLOR;
|
||||
|
@ -969,7 +1015,7 @@ LONG BOOKMARKS::CustomDraw(NMLVCUSTOMDRAW* msg)
|
|||
// frame number
|
||||
SelectObject(msg->nmcd.hdc, list.hMainListFont);
|
||||
int frame = bookmarks_array[cell_y].snapshot.jump_frame;
|
||||
if (frame == currFrameCounter || frame == (playback.GetPauseFrame() - 1))
|
||||
if (frame == currFrameCounter || frame == (playback.GetFlashingPauseFrame() - 1))
|
||||
{
|
||||
// current frame
|
||||
msg->clrTextBk = CUR_INPUT_COLOR1;
|
||||
|
@ -1006,9 +1052,9 @@ void BOOKMARKS::LeftClick(LPNMITEMACTIVATE info)
|
|||
if (cell_y >= 0 && cell_x >= 0)
|
||||
{
|
||||
if (cell_x <= BOOKMARKS_COLUMN_FRAME || (taseditor_config.branch_only_when_rec && movie_readonly))
|
||||
jump((cell_y + 1) % TOTAL_BOOKMARKS);
|
||||
command(COMMAND_JUMP, (cell_y + 1) % TOTAL_BOOKMARKS);
|
||||
else if (cell_x == BOOKMARKS_COLUMN_TIME && (!taseditor_config.branch_only_when_rec || !movie_readonly))
|
||||
unleash((cell_y + 1) % TOTAL_BOOKMARKS);
|
||||
command(COMMAND_DEPLOY, (cell_y + 1) % TOTAL_BOOKMARKS);
|
||||
}
|
||||
// remove selection
|
||||
ListView_SetItemState(hwndBookmarksList, -1, 0, LVIS_FOCUSED|LVIS_SELECTED);
|
||||
|
@ -1017,7 +1063,7 @@ void BOOKMARKS::RightClick(LPNMITEMACTIVATE info)
|
|||
{
|
||||
int cell_y = info->iItem;
|
||||
if (cell_y >= 0)
|
||||
set((cell_y + 1) % TOTAL_BOOKMARKS);
|
||||
command(COMMAND_SET, (cell_y + 1) % TOTAL_BOOKMARKS);
|
||||
// remove selection
|
||||
ListView_SetItemState(hwndBookmarksList, -1, 0, LVIS_FOCUSED|LVIS_SELECTED);
|
||||
}
|
||||
|
|
|
@ -10,6 +10,14 @@ enum
|
|||
EDIT_MODE_BRANCHES = 2,
|
||||
};
|
||||
|
||||
enum COMMANDS
|
||||
{
|
||||
COMMAND_SET = 0,
|
||||
COMMAND_JUMP = 1,
|
||||
COMMAND_DEPLOY = 2,
|
||||
COMMAND_DELETE = 3, // not implemented, probably useless
|
||||
};
|
||||
|
||||
#define ITEM_UNDER_MOUSE_NONE -2
|
||||
#define ITEM_UNDER_MOUSE_CLOUD -1
|
||||
|
||||
|
@ -90,6 +98,8 @@ enum
|
|||
#define BOOKMARKS_ID_LEN 10
|
||||
#define TIME_DESC_LENGTH 9 // "HH:MM:SS"
|
||||
|
||||
#define DEFAULT_BOOKMARK 1
|
||||
|
||||
class BOOKMARKS
|
||||
{
|
||||
public:
|
||||
|
@ -103,9 +113,7 @@ public:
|
|||
void save(EMUFILE *os, bool really_save = true);
|
||||
bool load(EMUFILE *is);
|
||||
|
||||
void set(int slot);
|
||||
void jump(int slot);
|
||||
void unleash(int slot);
|
||||
void command(int command_id, int slot);
|
||||
|
||||
void GetDispInfo(NMLVDISPINFO* nmlvDispInfo);
|
||||
LONG CustomDraw(NMLVCUSTOMDRAW* msg);
|
||||
|
@ -132,6 +140,7 @@ public:
|
|||
void RecursiveAddHeight(int branch_num, int amount);
|
||||
void RecursiveSetYPos(int parent, int parentY);
|
||||
|
||||
// saved vars
|
||||
std::vector<BOOKMARK> bookmarks_array;
|
||||
|
||||
// not saved vars
|
||||
|
@ -143,6 +152,10 @@ public:
|
|||
TRACKMOUSEEVENT tme, list_tme;
|
||||
|
||||
private:
|
||||
void set(int slot);
|
||||
void jump(int slot);
|
||||
void deploy(int slot);
|
||||
|
||||
void SetCurrentPosTime();
|
||||
|
||||
// also saved vars
|
||||
|
@ -152,6 +165,7 @@ private:
|
|||
char current_pos_time[TIME_DESC_LENGTH];
|
||||
|
||||
// not saved vars
|
||||
std::vector<int> commands;
|
||||
int check_flash_shedule;
|
||||
int edit_mode;
|
||||
int animation_frame;
|
||||
|
|
|
@ -9,6 +9,8 @@ extern PLAYBACK playback;
|
|||
extern BOOKMARKS bookmarks;
|
||||
extern TASEDITOR_LIST list;
|
||||
|
||||
extern char lagFlag;
|
||||
|
||||
char greenzone_save_id[GREENZONE_ID_LEN] = "GREENZONE";
|
||||
char greenzone_skipsave_id[GREENZONE_ID_LEN] = "GREENZONX";
|
||||
|
||||
|
@ -31,7 +33,6 @@ void GREENZONE::free()
|
|||
savestates.resize(0);
|
||||
greenZoneCount = 0;
|
||||
lag_history.resize(0);
|
||||
// reset lua_colorings
|
||||
// reset monitorings
|
||||
|
||||
}
|
||||
|
@ -42,24 +43,21 @@ void GREENZONE::reset()
|
|||
}
|
||||
void GREENZONE::update()
|
||||
{
|
||||
if ((int)savestates.size() < greenZoneCount)
|
||||
savestates.resize(greenZoneCount);
|
||||
if ((int)lag_history.size() < greenZoneCount)
|
||||
lag_history.resize(greenZoneCount);
|
||||
// keep memorizing savestates, this function should be called at the end of every frame
|
||||
if (greenZoneCount <= currFrameCounter || (int)savestates.size() <= currFrameCounter || savestates[currFrameCounter].empty())
|
||||
CollectCurrentState();
|
||||
|
||||
// run cleaning from time to time
|
||||
if (clock() > next_cleaning_time)
|
||||
GreenzoneCleaning();
|
||||
}
|
||||
|
||||
void GREENZONE::TryDumpIncremental(bool lagFlag)
|
||||
void GREENZONE::CollectCurrentState()
|
||||
{
|
||||
// if movie length is less than currFrame, pad it with empty frames
|
||||
if(currMovieData.getNumRecords() <= currFrameCounter)
|
||||
currMovieData.insertEmpty(-1, 1 + currFrameCounter - currMovieData.getNumRecords());
|
||||
|
||||
// update greenzone upper limit
|
||||
// update greenzone upper limit if needed
|
||||
if (greenZoneCount <= currFrameCounter)
|
||||
greenZoneCount = currFrameCounter+1;
|
||||
|
||||
if ((int)savestates.size() < greenZoneCount)
|
||||
savestates.resize(greenZoneCount);
|
||||
if ((int)lag_history.size() < greenZoneCount)
|
||||
|
@ -67,7 +65,7 @@ void GREENZONE::TryDumpIncremental(bool lagFlag)
|
|||
|
||||
// if frame changed - log savestate
|
||||
storeTasSavestate(currFrameCounter);
|
||||
// also log frame_flags
|
||||
// also log lag frames
|
||||
if (currFrameCounter > 0)
|
||||
{
|
||||
// lagFlag indicates that lag was in previous frame
|
||||
|
@ -91,8 +89,8 @@ bool GREENZONE::loadTasSavestate(int frame)
|
|||
|
||||
void GREENZONE::storeTasSavestate(int frame)
|
||||
{
|
||||
if ((int)savestates.size()<=frame)
|
||||
savestates.resize(frame+1);
|
||||
if ((int)savestates.size() <= frame)
|
||||
savestates.resize(frame + 1);
|
||||
|
||||
EMUFILE_MEMORY ms(&savestates[frame]);
|
||||
FCEUSS_SaveMS(&ms, Z_DEFAULT_COMPRESSION);
|
||||
|
@ -103,11 +101,11 @@ void GREENZONE::GreenzoneCleaning()
|
|||
{
|
||||
int i = currFrameCounter - taseditor_config.greenzone_capacity;
|
||||
bool changed = false;
|
||||
if (i < 0) goto finish;
|
||||
if (i <= 0) goto finish; // zeroth frame should not be cleaned
|
||||
int limit;
|
||||
// 2x of 1/2
|
||||
limit = i - 2 * taseditor_config.greenzone_capacity;
|
||||
if (limit < -1) limit = -1;
|
||||
if (limit < 0) limit = 0;
|
||||
for (; i > limit; i--)
|
||||
{
|
||||
if ((i & 0x1) && !savestates[i].empty())
|
||||
|
@ -119,7 +117,7 @@ void GREENZONE::GreenzoneCleaning()
|
|||
if (i < 0) goto finish;
|
||||
// 4x of 1/4
|
||||
limit = i - 4 * taseditor_config.greenzone_capacity;
|
||||
if (limit < -1) limit = -1;
|
||||
if (limit < 0) limit = 0;
|
||||
for (; i > limit; i--)
|
||||
{
|
||||
if ((i & 0x3) && !savestates[i].empty())
|
||||
|
@ -131,7 +129,7 @@ void GREENZONE::GreenzoneCleaning()
|
|||
if (i < 0) goto finish;
|
||||
// 8x of 1/8
|
||||
limit = i - 8 * taseditor_config.greenzone_capacity;
|
||||
if (limit < -1) limit = -1;
|
||||
if (limit < 0) limit = 0;
|
||||
for (; i > limit; i--)
|
||||
{
|
||||
if ((i & 0x7) && !savestates[i].empty())
|
||||
|
@ -143,7 +141,7 @@ void GREENZONE::GreenzoneCleaning()
|
|||
if (i < 0) goto finish;
|
||||
// 16x of 1/16
|
||||
limit = i - 16 * taseditor_config.greenzone_capacity;
|
||||
if (limit < -1) limit = -1;
|
||||
if (limit < 0) limit = 0;
|
||||
for (; i > limit; i--)
|
||||
{
|
||||
if ((i & 0xF) && !savestates[i].empty())
|
||||
|
@ -153,7 +151,7 @@ void GREENZONE::GreenzoneCleaning()
|
|||
}
|
||||
}
|
||||
// clear all remaining
|
||||
for (; i >= 0; i--)
|
||||
for (; i > 0; i--)
|
||||
{
|
||||
if (!savestates[i].empty())
|
||||
{
|
||||
|
@ -208,7 +206,6 @@ void GREENZONE::save(EMUFILE *os, bool really_save)
|
|||
}
|
||||
if (savestates[frame].empty()) continue;
|
||||
write32le(frame, os);
|
||||
// write lua_colorings
|
||||
// write monitorings
|
||||
// write savestate
|
||||
size = savestates[frame].size();
|
||||
|
@ -312,7 +309,6 @@ bool GREENZONE::load(EMUFILE *is)
|
|||
playback.SetProgressbar(frame, greenZoneCount);
|
||||
last_tick = frame / PROGRESSBAR_UPDATE_RATE;
|
||||
}
|
||||
// read lua_colorings
|
||||
// read monitorings
|
||||
// read savestate
|
||||
if (!read32le(&size, is)) break;
|
||||
|
@ -380,6 +376,10 @@ void GREENZONE::InvalidateAndCheck(int after)
|
|||
// either set playback cursor to the end of greenzone or run seeking to restore playback position
|
||||
if (currFrameCounter >= greenZoneCount)
|
||||
{
|
||||
// remember the lost position
|
||||
if (playback.lost_position_frame-1 < currFrameCounter)
|
||||
playback.lost_position_frame = currFrameCounter + 1;
|
||||
// auto-restore position if needed
|
||||
if (taseditor_config.restore_position)
|
||||
playback.restorePosition();
|
||||
else
|
||||
|
|
|
@ -1,10 +1,8 @@
|
|||
//Specification file for Greenzone class
|
||||
|
||||
//#define LAG_FLAG_BIT 1
|
||||
#define TIME_BETWEEN_CLEANINGS 10000 // in milliseconds
|
||||
|
||||
#define GREENZONE_ID_LEN 10
|
||||
|
||||
#define TIME_BETWEEN_CLEANINGS 10000 // in milliseconds
|
||||
// greenzone cleaning masks
|
||||
#define EVERY16TH 0xFFFFFFF0
|
||||
#define EVERY8TH 0xFFFFFFF8
|
||||
|
@ -23,7 +21,7 @@ public:
|
|||
void save(EMUFILE *os, bool really_save = true);
|
||||
bool load(EMUFILE *is);
|
||||
|
||||
void TryDumpIncremental(bool lagFlag = true);
|
||||
void CollectCurrentState();
|
||||
|
||||
bool loadTasSavestate(int frame);
|
||||
void storeTasSavestate(int frame);
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
//Implementation file of Input History class (Undo feature)
|
||||
//Implementation file of History class (Undo feature)
|
||||
#include "taseditor_project.h"
|
||||
|
||||
LRESULT APIENTRY HistoryListWndProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam);
|
||||
|
@ -6,13 +6,14 @@ WNDPROC hwndHistoryList_oldWndProc;
|
|||
|
||||
extern TASEDITOR_CONFIG taseditor_config;
|
||||
extern TASEDITOR_WINDOW taseditor_window;
|
||||
extern MARKERS current_markers;
|
||||
extern MARKERS_MANAGER markers_manager;
|
||||
extern BOOKMARKS bookmarks;
|
||||
extern PLAYBACK playback;
|
||||
extern TASEDITOR_SELECTION selection;
|
||||
extern GREENZONE greenzone;
|
||||
extern TASEDITOR_PROJECT project;
|
||||
extern TASEDITOR_LIST list;
|
||||
extern TASEDITOR_LUA taseditor_lua;
|
||||
|
||||
extern int joysticks_per_frame[NUM_SUPPORTED_INPUT_TYPES];
|
||||
extern int GetInputType(MovieData& md);
|
||||
|
@ -60,13 +61,14 @@ char modCaptions[41][20] = {" Init",
|
|||
" LUA Marker Unset",
|
||||
" LUA Marker Rename",
|
||||
" LUA Change" };
|
||||
char LuaCaptionPrefix[6] = " LUA ";
|
||||
char joypadCaptions[4][5] = {"(1P)", "(2P)", "(3P)", "(4P)"};
|
||||
|
||||
INPUT_HISTORY::INPUT_HISTORY()
|
||||
HISTORY::HISTORY()
|
||||
{
|
||||
}
|
||||
|
||||
void INPUT_HISTORY::init()
|
||||
void HISTORY::init()
|
||||
{
|
||||
// prepare the history listview
|
||||
hwndHistoryList = GetDlgItem(taseditor_window.hwndTasEditor, IDC_HISTORYLIST);
|
||||
|
@ -79,31 +81,31 @@ void INPUT_HISTORY::init()
|
|||
lvc.fmt = LVCFMT_LEFT;
|
||||
ListView_InsertColumn(hwndHistoryList, 0, &lvc);
|
||||
}
|
||||
void INPUT_HISTORY::free()
|
||||
void HISTORY::free()
|
||||
{
|
||||
input_snapshots.resize(0);
|
||||
snapshots.resize(0);
|
||||
history_total_items = 0;
|
||||
}
|
||||
void INPUT_HISTORY::reset()
|
||||
void HISTORY::reset()
|
||||
{
|
||||
free();
|
||||
// init vars
|
||||
history_size = taseditor_config.undo_levels + 1;
|
||||
undo_hint_pos = old_undo_hint_pos = undo_hint_time = -1;
|
||||
old_show_undo_hint = show_undo_hint = false;
|
||||
input_snapshots.resize(history_size);
|
||||
snapshots.resize(history_size);
|
||||
history_start_pos = 0;
|
||||
history_cursor_pos = -1;
|
||||
// create initial snapshot
|
||||
INPUT_SNAPSHOT inp;
|
||||
SNAPSHOT inp;
|
||||
inp.init(currMovieData, taseditor_config.enable_hot_changes);
|
||||
strcat(inp.description, modCaptions[0]);
|
||||
inp.jump_frame = -1;
|
||||
AddInputSnapshotToHistory(inp);
|
||||
AddSnapshotToHistory(inp);
|
||||
UpdateHistoryList();
|
||||
RedrawHistoryList();
|
||||
}
|
||||
void INPUT_HISTORY::update()
|
||||
void HISTORY::update()
|
||||
{
|
||||
// update undo_hint
|
||||
if (old_undo_hint_pos != undo_hint_pos && old_undo_hint_pos >= 0)
|
||||
|
@ -120,13 +122,10 @@ void INPUT_HISTORY::update()
|
|||
}
|
||||
if (old_show_undo_hint != show_undo_hint)
|
||||
list.RedrawRow(undo_hint_pos); // not changing bookmarks list
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
// returns frame of first input change (for greenzone invalidation)
|
||||
int INPUT_HISTORY::jump(int new_pos)
|
||||
int HISTORY::jump(int new_pos)
|
||||
{
|
||||
if (new_pos < 0) new_pos = 0; else if (new_pos >= history_total_items) new_pos = history_total_items-1;
|
||||
// if nothing is done, do not invalidate greenzone
|
||||
|
@ -150,25 +149,25 @@ int INPUT_HISTORY::jump(int new_pos)
|
|||
bool markers_changed = false;
|
||||
if (taseditor_config.bind_markers)
|
||||
{
|
||||
if (input_snapshots[real_pos].my_markers.checkMarkersDiff(current_markers))
|
||||
if (snapshots[real_pos].MarkersDifferFromCurrent())
|
||||
{
|
||||
input_snapshots[real_pos].copyToMarkers();
|
||||
snapshots[real_pos].copyToMarkers();
|
||||
project.SetProjectChanged();
|
||||
markers_changed = true;
|
||||
}
|
||||
}
|
||||
|
||||
// update current movie
|
||||
int first_change = input_snapshots[real_pos].findFirstChange(currMovieData);
|
||||
int first_change = snapshots[real_pos].findFirstChange(currMovieData);
|
||||
if (first_change >= 0)
|
||||
{
|
||||
input_snapshots[real_pos].toMovie(currMovieData, first_change);
|
||||
snapshots[real_pos].toMovie(currMovieData, first_change);
|
||||
selection.must_find_current_marker = playback.must_find_current_marker = true;
|
||||
bookmarks.ChangesMadeSinceBranch();
|
||||
// list will be redrawn by greenzone invalidation
|
||||
} else if (markers_changed)
|
||||
{
|
||||
current_markers.update();
|
||||
markers_manager.update();
|
||||
selection.must_find_current_marker = playback.must_find_current_marker = true;
|
||||
bookmarks.ChangesMadeSinceBranch();
|
||||
list.RedrawList();
|
||||
|
@ -181,19 +180,18 @@ int INPUT_HISTORY::jump(int new_pos)
|
|||
|
||||
return first_change;
|
||||
}
|
||||
int INPUT_HISTORY::undo()
|
||||
int HISTORY::undo()
|
||||
{
|
||||
return jump(history_cursor_pos - 1);
|
||||
}
|
||||
int INPUT_HISTORY::redo()
|
||||
int HISTORY::redo()
|
||||
{
|
||||
return jump(history_cursor_pos + 1);
|
||||
}
|
||||
// ----------------------------
|
||||
void INPUT_HISTORY::AddInputSnapshotToHistory(INPUT_SNAPSHOT &inp)
|
||||
void HISTORY::AddSnapshotToHistory(SNAPSHOT &inp)
|
||||
{
|
||||
// history uses conveyor of snapshots (vector with fixed size) to aviod resizing which is awfully expensive with such large objects as INPUT_SNAPSHOT
|
||||
int real_pos;
|
||||
// history uses conveyor of snapshots (vector with fixed size) to aviod resizing which is awfully expensive with such large objects as SNAPSHOT
|
||||
if (history_cursor_pos+1 >= history_size)
|
||||
{
|
||||
// reached the end of available history_size - move history_start_pos (thus deleting oldest snapshot)
|
||||
|
@ -203,47 +201,25 @@ void INPUT_HISTORY::AddInputSnapshotToHistory(INPUT_SNAPSHOT &inp)
|
|||
{
|
||||
// didn't reach the end of history yet
|
||||
history_cursor_pos++;
|
||||
if (history_cursor_pos < history_total_items)
|
||||
{
|
||||
// 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].my_markers.checkMarkersDiff(inp.my_markers))
|
||||
{
|
||||
history_total_items = history_cursor_pos+1;
|
||||
UpdateHistoryList();
|
||||
} else
|
||||
{
|
||||
// it's not different - don't truncate history, but break the chain of coherent snapshots
|
||||
for (int i = history_cursor_pos+1; i < history_total_items; ++i)
|
||||
{
|
||||
real_pos = (history_start_pos + i) % history_size;
|
||||
input_snapshots[real_pos].coherent = false;
|
||||
}
|
||||
}
|
||||
} else
|
||||
{
|
||||
// add new snapshot
|
||||
history_total_items = history_cursor_pos+1;
|
||||
UpdateHistoryList();
|
||||
}
|
||||
history_total_items = history_cursor_pos+1;
|
||||
UpdateHistoryList();
|
||||
}
|
||||
// write snapshot
|
||||
real_pos = (history_start_pos + history_cursor_pos) % history_size;
|
||||
input_snapshots[real_pos] = inp;
|
||||
int real_pos = (history_start_pos + history_cursor_pos) % history_size;
|
||||
snapshots[real_pos] = inp;
|
||||
RedrawHistoryList();
|
||||
}
|
||||
|
||||
// returns frame of first actual change
|
||||
int INPUT_HISTORY::RegisterChanges(int mod_type, int start, int end)
|
||||
int HISTORY::RegisterChanges(int mod_type, int start, int end)
|
||||
{
|
||||
// create new input shanshot
|
||||
INPUT_SNAPSHOT inp;
|
||||
// create new shanshot
|
||||
SNAPSHOT inp;
|
||||
inp.init(currMovieData, taseditor_config.enable_hot_changes);
|
||||
inp.mod_type = mod_type;
|
||||
// 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);
|
||||
int first_changes = inp.findFirstChange(snapshots[real_pos], start, end);
|
||||
if (first_changes >= 0)
|
||||
{
|
||||
// differences found
|
||||
|
@ -264,7 +240,6 @@ int INPUT_HISTORY::RegisterChanges(int mod_type, int start, int end)
|
|||
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
|
||||
|
@ -290,14 +265,11 @@ int INPUT_HISTORY::RegisterChanges(int mod_type, int start, int end)
|
|||
switch (mod_type)
|
||||
{
|
||||
case MODTYPE_DELETE:
|
||||
inp.inheritHotChanges_DeleteSelection(&input_snapshots[real_pos]);
|
||||
inp.inheritHotChanges_DeleteSelection(&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]);
|
||||
inp.inheritHotChanges_InsertSelection(&snapshots[real_pos]);
|
||||
break;
|
||||
case MODTYPE_CHANGE:
|
||||
case MODTYPE_SET:
|
||||
|
@ -305,24 +277,53 @@ int INPUT_HISTORY::RegisterChanges(int mod_type, int start, int end)
|
|||
case MODTYPE_CLEAR:
|
||||
case MODTYPE_CUT:
|
||||
case MODTYPE_PASTE:
|
||||
inp.inheritHotChanges(&input_snapshots[real_pos]);
|
||||
inp.fillHotChanges(input_snapshots[real_pos], first_changes, end);
|
||||
inp.inheritHotChanges(&snapshots[real_pos]);
|
||||
inp.fillHotChanges(snapshots[real_pos], first_changes, end);
|
||||
break;
|
||||
case MODTYPE_TRUNCATE:
|
||||
inp.copyHotChanges(&input_snapshots[real_pos]);
|
||||
inp.copyHotChanges(&snapshots[real_pos]);
|
||||
// do not add new hotchanges and do not fade old hotchanges, because there was nothing added
|
||||
break;
|
||||
}
|
||||
}
|
||||
AddInputSnapshotToHistory(inp);
|
||||
AddSnapshotToHistory(inp);
|
||||
bookmarks.ChangesMadeSinceBranch();
|
||||
}
|
||||
return first_changes;
|
||||
}
|
||||
void INPUT_HISTORY::RegisterMarkersChange(int mod_type, int start, int end)
|
||||
int HISTORY::RegisterPasteInsert(int start, SelectionFrames& inserted_set)
|
||||
{
|
||||
// create new input shanshot
|
||||
INPUT_SNAPSHOT inp;
|
||||
// create new shanshot
|
||||
SNAPSHOT inp;
|
||||
inp.init(currMovieData, taseditor_config.enable_hot_changes);
|
||||
inp.mod_type = MODTYPE_PASTEINSERT;
|
||||
// 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(snapshots[real_pos], start);
|
||||
if (first_changes >= 0)
|
||||
{
|
||||
// differences found
|
||||
// fill description:
|
||||
strcat(inp.description, modCaptions[inp.mod_type]);
|
||||
// for PasteInsert user prefers to see frame of attempted change (selection beginning), not frame of actual differences
|
||||
inp.jump_frame = start;
|
||||
// add upper frame to description
|
||||
char framenum[11];
|
||||
_itoa(start, framenum, 10);
|
||||
strcat(inp.description, " ");
|
||||
strcat(inp.description, framenum);
|
||||
// set hotchanges
|
||||
if (taseditor_config.enable_hot_changes)
|
||||
inp.inheritHotChanges_PasteInsert(&snapshots[real_pos], inserted_set);
|
||||
AddSnapshotToHistory(inp);
|
||||
bookmarks.ChangesMadeSinceBranch();
|
||||
}
|
||||
return first_changes;
|
||||
}
|
||||
void HISTORY::RegisterMarkersChange(int mod_type, int start, int end)
|
||||
{
|
||||
// create new shanshot
|
||||
SNAPSHOT inp;
|
||||
inp.init(currMovieData, taseditor_config.enable_hot_changes);
|
||||
inp.mod_type = mod_type;
|
||||
// fill description:
|
||||
|
@ -341,14 +342,14 @@ void INPUT_HISTORY::RegisterMarkersChange(int mod_type, int start, int end)
|
|||
}
|
||||
if (taseditor_config.enable_hot_changes)
|
||||
inp.copyHotChanges(&GetCurrentSnapshot());
|
||||
AddInputSnapshotToHistory(inp);
|
||||
AddSnapshotToHistory(inp);
|
||||
bookmarks.ChangesMadeSinceBranch();
|
||||
project.SetProjectChanged();
|
||||
}
|
||||
void INPUT_HISTORY::RegisterBranching(int mod_type, int first_change, int slot)
|
||||
void HISTORY::RegisterBranching(int mod_type, int first_change, int slot)
|
||||
{
|
||||
// create new input snapshot
|
||||
INPUT_SNAPSHOT inp;
|
||||
// create new snapshot
|
||||
SNAPSHOT inp;
|
||||
inp.init(currMovieData, taseditor_config.enable_hot_changes);
|
||||
// fill description: modification type + time of the Branch
|
||||
inp.mod_type = mod_type;
|
||||
|
@ -375,25 +376,25 @@ void INPUT_HISTORY::RegisterBranching(int mod_type, int first_change, int slot)
|
|||
inp.copyHotChanges(&GetCurrentSnapshot());
|
||||
}
|
||||
}
|
||||
AddInputSnapshotToHistory(inp);
|
||||
AddSnapshotToHistory(inp);
|
||||
}
|
||||
void INPUT_HISTORY::RegisterRecording(int frame_of_change)
|
||||
void HISTORY::RegisterRecording(int frame_of_change)
|
||||
{
|
||||
int real_pos = (history_start_pos + history_cursor_pos) % history_size;
|
||||
INPUT_SNAPSHOT inp;
|
||||
SNAPSHOT inp;
|
||||
inp.init(currMovieData, taseditor_config.enable_hot_changes);
|
||||
inp.fillJoypadsDiff(input_snapshots[real_pos], frame_of_change);
|
||||
inp.fillJoypadsDiff(snapshots[real_pos], frame_of_change);
|
||||
inp.mod_type = MODTYPE_RECORD;
|
||||
strcat(inp.description, modCaptions[MODTYPE_RECORD]);
|
||||
char framenum[11];
|
||||
// check if current snapshot is also Recording and maybe it is consecutive recording
|
||||
if (taseditor_config.combine_consecutive_rec
|
||||
&& input_snapshots[real_pos].mod_type == MODTYPE_RECORD // a) also Recording
|
||||
&& input_snapshots[real_pos].rec_end_frame+1 == frame_of_change // b) consecutive
|
||||
&& input_snapshots[real_pos].rec_joypad_diff_bits == inp.rec_joypad_diff_bits) // c) recorded same set of joysticks
|
||||
&& snapshots[real_pos].mod_type == MODTYPE_RECORD // a) also Recording
|
||||
&& snapshots[real_pos].rec_end_frame+1 == frame_of_change // b) consecutive
|
||||
&& snapshots[real_pos].rec_joypad_diff_bits == inp.rec_joypad_diff_bits) // c) recorded same set of joysticks
|
||||
{
|
||||
// clone this snapshot and continue chain of recorded frames
|
||||
inp.jump_frame = input_snapshots[real_pos].jump_frame;
|
||||
inp.jump_frame = snapshots[real_pos].jump_frame;
|
||||
inp.rec_end_frame = frame_of_change;
|
||||
// add info which joypads were affected
|
||||
int num = joysticks_per_frame[inp.input_type];
|
||||
|
@ -414,11 +415,11 @@ void INPUT_HISTORY::RegisterRecording(int frame_of_change)
|
|||
// set hotchanges
|
||||
if (taseditor_config.enable_hot_changes)
|
||||
{
|
||||
inp.copyHotChanges(&input_snapshots[real_pos]);
|
||||
inp.fillHotChanges(input_snapshots[real_pos], frame_of_change, frame_of_change);
|
||||
inp.copyHotChanges(&snapshots[real_pos]);
|
||||
inp.fillHotChanges(snapshots[real_pos], frame_of_change, frame_of_change);
|
||||
}
|
||||
// replace current snapshot with this cloned snapshot and truncate history here
|
||||
input_snapshots[real_pos] = inp;
|
||||
snapshots[real_pos] = inp;
|
||||
history_total_items = history_cursor_pos+1;
|
||||
UpdateHistoryList();
|
||||
RedrawHistoryList();
|
||||
|
@ -442,21 +443,21 @@ void INPUT_HISTORY::RegisterRecording(int frame_of_change)
|
|||
// set hotchanges
|
||||
if (taseditor_config.enable_hot_changes)
|
||||
{
|
||||
inp.inheritHotChanges(&input_snapshots[real_pos]);
|
||||
inp.fillHotChanges(input_snapshots[real_pos], frame_of_change, frame_of_change);
|
||||
inp.inheritHotChanges(&snapshots[real_pos]);
|
||||
inp.fillHotChanges(snapshots[real_pos], frame_of_change, frame_of_change);
|
||||
}
|
||||
AddInputSnapshotToHistory(inp);
|
||||
AddSnapshotToHistory(inp);
|
||||
}
|
||||
bookmarks.ChangesMadeSinceBranch();
|
||||
}
|
||||
void INPUT_HISTORY::RegisterImport(MovieData& md, char* filename)
|
||||
void HISTORY::RegisterImport(MovieData& md, char* filename)
|
||||
{
|
||||
// create new input snapshot
|
||||
INPUT_SNAPSHOT inp;
|
||||
// create new snapshot
|
||||
SNAPSHOT inp;
|
||||
inp.init(md, taseditor_config.enable_hot_changes, GetInputType(currMovieData));
|
||||
// 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]);
|
||||
int first_changes = inp.findFirstChange(snapshots[real_pos]);
|
||||
if (first_changes >= 0)
|
||||
{
|
||||
// differences found
|
||||
|
@ -470,9 +471,9 @@ void INPUT_HISTORY::RegisterImport(MovieData& md, char* filename)
|
|||
if (taseditor_config.enable_hot_changes)
|
||||
{
|
||||
// do not inherit old hotchanges, because imported input (most likely) doesn't have direct connection with recent edits, so old hotchanges are irrelevant and should not be copied
|
||||
inp.fillHotChanges(input_snapshots[real_pos], first_changes);
|
||||
inp.fillHotChanges(snapshots[real_pos], first_changes);
|
||||
}
|
||||
AddInputSnapshotToHistory(inp);
|
||||
AddSnapshotToHistory(inp);
|
||||
inp.toMovie(currMovieData);
|
||||
list.update();
|
||||
bookmarks.ChangesMadeSinceBranch();
|
||||
|
@ -483,8 +484,72 @@ void INPUT_HISTORY::RegisterImport(MovieData& md, char* filename)
|
|||
MessageBox(taseditor_window.hwndTasEditor, "Imported movie has the same input.\nNo changes were made.", "TAS Editor", MB_OK);
|
||||
}
|
||||
}
|
||||
int HISTORY::RegisterLuaChanges(const char* name, int start, bool InsertionDeletion_was_made)
|
||||
{
|
||||
// create new shanshot
|
||||
SNAPSHOT inp;
|
||||
inp.init(currMovieData, taseditor_config.enable_hot_changes);
|
||||
inp.mod_type = MODTYPE_LUA_CHANGE;
|
||||
// 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(snapshots[real_pos], start);
|
||||
if (first_changes >= 0)
|
||||
{
|
||||
// differences found
|
||||
// fill description:
|
||||
if (name[0])
|
||||
{
|
||||
// custom name of operation
|
||||
strcat(inp.description, LuaCaptionPrefix);
|
||||
strncat(inp.description, name, LUACHANGES_NAME_MAX_LEN);
|
||||
} else
|
||||
{
|
||||
// default name
|
||||
strcat(inp.description, modCaptions[inp.mod_type]);
|
||||
}
|
||||
inp.jump_frame = first_changes;
|
||||
// add upper frame to description
|
||||
char framenum[11];
|
||||
_itoa(first_changes, framenum, 10);
|
||||
strcat(inp.description, " ");
|
||||
strcat(inp.description, framenum);
|
||||
// set hotchanges
|
||||
if (taseditor_config.enable_hot_changes)
|
||||
{
|
||||
if (InsertionDeletion_was_made)
|
||||
{
|
||||
// do it hard way: take old hot_changes and insert/delete rows to create a snapshot that is comparable to inp
|
||||
if (inp.input_type == snapshots[real_pos].input_type)
|
||||
{
|
||||
// create temp copy of current snapshot (we need it as a container for hot_changes)
|
||||
SNAPSHOT hotchanges_snapshot = snapshots[real_pos];
|
||||
if (hotchanges_snapshot.has_hot_changes)
|
||||
{
|
||||
hotchanges_snapshot.FadeHotChanges();
|
||||
} else
|
||||
{
|
||||
hotchanges_snapshot.has_hot_changes = true;
|
||||
hotchanges_snapshot.hot_changes.resize(joysticks_per_frame[inp.input_type] * hotchanges_snapshot.size * HOTCHANGE_BYTES_PER_JOY);
|
||||
}
|
||||
// insert/delete frames in hotchanges_snapshot, so that it will be the same size as inp
|
||||
taseditor_lua.InsertDelete_rows_to_Snaphot(hotchanges_snapshot);
|
||||
inp.copyHotChanges(&hotchanges_snapshot);
|
||||
inp.fillHotChanges(hotchanges_snapshot, first_changes);
|
||||
}
|
||||
} else
|
||||
{
|
||||
// easy way: inp.size is equal to currentsnapshot.size, so we can simply inherit hotchanges
|
||||
inp.inheritHotChanges(&snapshots[real_pos]);
|
||||
inp.fillHotChanges(snapshots[real_pos], first_changes);
|
||||
}
|
||||
}
|
||||
AddSnapshotToHistory(inp);
|
||||
bookmarks.ChangesMadeSinceBranch();
|
||||
}
|
||||
return first_changes;
|
||||
}
|
||||
|
||||
void INPUT_HISTORY::save(EMUFILE *os, bool really_save)
|
||||
void HISTORY::save(EMUFILE *os, bool really_save)
|
||||
{
|
||||
if (really_save)
|
||||
{
|
||||
|
@ -498,7 +563,7 @@ void INPUT_HISTORY::save(EMUFILE *os, bool really_save)
|
|||
for (int i = 0; i < history_total_items; ++i)
|
||||
{
|
||||
real_pos = (history_start_pos + i) % history_size;
|
||||
input_snapshots[real_pos].save(os);
|
||||
snapshots[real_pos].save(os);
|
||||
playback.SetProgressbar(i, history_total_items);
|
||||
}
|
||||
} else
|
||||
|
@ -508,12 +573,12 @@ void INPUT_HISTORY::save(EMUFILE *os, bool really_save)
|
|||
}
|
||||
}
|
||||
// returns true if couldn't load
|
||||
bool INPUT_HISTORY::load(EMUFILE *is)
|
||||
bool HISTORY::load(EMUFILE *is)
|
||||
{
|
||||
int i = -1;
|
||||
INPUT_SNAPSHOT inp;
|
||||
SNAPSHOT inp;
|
||||
// delete old snapshots
|
||||
input_snapshots.resize(history_size);
|
||||
snapshots.resize(history_size);
|
||||
// read "HISTORY" string
|
||||
char save_id[HISTORY_ID_LEN];
|
||||
if ((int)is->fread(save_id, HISTORY_ID_LEN) < HISTORY_ID_LEN) goto error;
|
||||
|
@ -554,7 +619,7 @@ bool INPUT_HISTORY::load(EMUFILE *is)
|
|||
// load snapshots
|
||||
for (i = 0; i < history_total_items; ++i)
|
||||
{
|
||||
if (input_snapshots[i].load(is)) goto error;
|
||||
if (snapshots[i].load(is)) goto error;
|
||||
playback.SetProgressbar(i, history_total_items);
|
||||
}
|
||||
// skip redo snapshots if needed
|
||||
|
@ -575,35 +640,30 @@ error:
|
|||
return true;
|
||||
}
|
||||
// ----------------------------
|
||||
void INPUT_HISTORY::GetDispInfo(NMLVDISPINFO* nmlvDispInfo)
|
||||
void HISTORY::GetDispInfo(NMLVDISPINFO* nmlvDispInfo)
|
||||
{
|
||||
LVITEM& item = nmlvDispInfo->item;
|
||||
if(item.mask & LVIF_TEXT)
|
||||
strcpy(item.pszText, GetItemDesc(item.iItem));
|
||||
}
|
||||
|
||||
LONG INPUT_HISTORY::CustomDraw(NMLVCUSTOMDRAW* msg)
|
||||
LONG HISTORY::CustomDraw(NMLVCUSTOMDRAW* msg)
|
||||
{
|
||||
switch(msg->nmcd.dwDrawStage)
|
||||
{
|
||||
case CDDS_PREPAINT:
|
||||
return CDRF_NOTIFYITEMDRAW;
|
||||
case CDDS_ITEMPREPAINT:
|
||||
{
|
||||
if (GetItemCoherence(msg->nmcd.dwItemSpec))
|
||||
msg->clrText = HISTORY_NORMAL_COLOR;
|
||||
else
|
||||
msg->clrText = HISTORY_INCOHERENT_COLOR;
|
||||
}
|
||||
msg->clrText = HISTORY_NORMAL_COLOR;
|
||||
default:
|
||||
return CDRF_DODEFAULT;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void INPUT_HISTORY::Click(LPNMITEMACTIVATE info)
|
||||
void HISTORY::Click(LPNMITEMACTIVATE info)
|
||||
{
|
||||
// jump to pointed input snapshot
|
||||
// jump to pointed snapshot
|
||||
int item = info->iItem;
|
||||
if (item >= 0)
|
||||
{
|
||||
|
@ -619,7 +679,7 @@ void INPUT_HISTORY::Click(LPNMITEMACTIVATE info)
|
|||
RedrawHistoryList();
|
||||
}
|
||||
|
||||
void INPUT_HISTORY::UpdateHistoryList()
|
||||
void HISTORY::UpdateHistoryList()
|
||||
{
|
||||
//update the number of items in the history list
|
||||
int currLVItemCount = ListView_GetItemCount(hwndHistoryList);
|
||||
|
@ -627,33 +687,29 @@ void INPUT_HISTORY::UpdateHistoryList()
|
|||
ListView_SetItemCountEx(hwndHistoryList, history_total_items, LVSICF_NOSCROLL | LVSICF_NOINVALIDATEALL);
|
||||
}
|
||||
|
||||
void INPUT_HISTORY::RedrawHistoryList()
|
||||
void HISTORY::RedrawHistoryList()
|
||||
{
|
||||
ListView_SetItemState(hwndHistoryList, history_cursor_pos, LVIS_FOCUSED|LVIS_SELECTED, LVIS_FOCUSED|LVIS_SELECTED);
|
||||
ListView_EnsureVisible(hwndHistoryList, history_cursor_pos, FALSE);
|
||||
InvalidateRect(hwndHistoryList, 0, FALSE);
|
||||
}
|
||||
// ----------------------------
|
||||
INPUT_SNAPSHOT& INPUT_HISTORY::GetCurrentSnapshot()
|
||||
SNAPSHOT& HISTORY::GetCurrentSnapshot()
|
||||
{
|
||||
return input_snapshots[(history_start_pos + history_cursor_pos) % history_size];
|
||||
return snapshots[(history_start_pos + history_cursor_pos) % history_size];
|
||||
}
|
||||
INPUT_SNAPSHOT& INPUT_HISTORY::GetNextToCurrentSnapshot()
|
||||
SNAPSHOT& HISTORY::GetNextToCurrentSnapshot()
|
||||
{
|
||||
if (history_cursor_pos < history_total_items)
|
||||
return input_snapshots[(history_start_pos + history_cursor_pos + 1) % history_size];
|
||||
return snapshots[(history_start_pos + history_cursor_pos + 1) % history_size];
|
||||
else
|
||||
return input_snapshots[(history_start_pos + history_cursor_pos) % history_size];
|
||||
return snapshots[(history_start_pos + history_cursor_pos) % history_size];
|
||||
}
|
||||
char* INPUT_HISTORY::GetItemDesc(int pos)
|
||||
char* HISTORY::GetItemDesc(int pos)
|
||||
{
|
||||
return input_snapshots[(history_start_pos + pos) % history_size].description;
|
||||
return snapshots[(history_start_pos + pos) % history_size].description;
|
||||
}
|
||||
bool INPUT_HISTORY::GetItemCoherence(int pos)
|
||||
{
|
||||
return input_snapshots[(history_start_pos + pos) % history_size].coherent;
|
||||
}
|
||||
int INPUT_HISTORY::GetUndoHint()
|
||||
int HISTORY::GetUndoHint()
|
||||
{
|
||||
if (show_undo_hint)
|
||||
return undo_hint_pos;
|
|
@ -46,14 +46,13 @@ enum
|
|||
MODTYPE_LUA_CHANGE = 40,
|
||||
};
|
||||
#define HISTORY_NORMAL_COLOR 0x000000
|
||||
#define HISTORY_INCOHERENT_COLOR 0x999999
|
||||
|
||||
#define HISTORY_ID_LEN 8
|
||||
|
||||
class INPUT_HISTORY
|
||||
class HISTORY
|
||||
{
|
||||
public:
|
||||
INPUT_HISTORY();
|
||||
HISTORY();
|
||||
void init();
|
||||
void free();
|
||||
void reset();
|
||||
|
@ -66,18 +65,17 @@ public:
|
|||
int redo();
|
||||
int jump(int new_pos);
|
||||
|
||||
void AddInputSnapshotToHistory(INPUT_SNAPSHOT &inp);
|
||||
|
||||
int RegisterChanges(int mod_type, int start = 0, int end =-1);
|
||||
int RegisterPasteInsert(int start, SelectionFrames& inserted_set);
|
||||
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);
|
||||
int RegisterLuaChanges(const char* name, int start, bool InsertionDeletion_was_made);
|
||||
|
||||
INPUT_SNAPSHOT& GetCurrentSnapshot();
|
||||
INPUT_SNAPSHOT& GetNextToCurrentSnapshot();
|
||||
SNAPSHOT& GetCurrentSnapshot();
|
||||
SNAPSHOT& GetNextToCurrentSnapshot();
|
||||
char* GetItemDesc(int pos);
|
||||
bool GetItemCoherence(int pos);
|
||||
int GetUndoHint();
|
||||
|
||||
void GetDispInfo(NMLVDISPINFO* nmlvDispInfo);
|
||||
|
@ -90,7 +88,9 @@ public:
|
|||
HWND hwndHistoryList;
|
||||
|
||||
private:
|
||||
std::vector<INPUT_SNAPSHOT> input_snapshots;
|
||||
void AddSnapshotToHistory(SNAPSHOT &inp);
|
||||
|
||||
std::vector<SNAPSHOT> snapshots;
|
||||
|
||||
int history_cursor_pos;
|
||||
int history_start_pos;
|
|
@ -1,90 +1,38 @@
|
|||
//Implementation file of Markers class
|
||||
#include "taseditor_project.h"
|
||||
#include "../common.h"
|
||||
#include "markers.h"
|
||||
#include "zlib.h"
|
||||
#include <Shlwapi.h> // for StrStrI
|
||||
|
||||
extern TASEDITOR_CONFIG taseditor_config;
|
||||
extern TASEDITOR_WINDOW taseditor_window;
|
||||
extern PLAYBACK playback;
|
||||
extern TASEDITOR_SELECTION selection;
|
||||
|
||||
// resources
|
||||
char markers_save_id[MARKERS_ID_LEN] = "MARKERS";
|
||||
char markers_skipsave_id[MARKERS_ID_LEN] = "MARKERX";
|
||||
char keywordDelimiters[] = " !\"#$%&'()*+,-./:;<=>?@[\\]^_`{|}~";
|
||||
|
||||
MARKERS::MARKERS()
|
||||
{
|
||||
}
|
||||
|
||||
void MARKERS::init()
|
||||
void MARKERS::save(EMUFILE *os)
|
||||
{
|
||||
reset();
|
||||
}
|
||||
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())
|
||||
markers_array.resize(currMovieData.getNumRecords());
|
||||
}
|
||||
|
||||
void MARKERS::save(EMUFILE *os, bool really_save)
|
||||
{
|
||||
if (really_save)
|
||||
// write size
|
||||
int size = markers_array.size();
|
||||
write32le(size, os);
|
||||
// compress and write array
|
||||
int len = markers_array.size() * sizeof(int);
|
||||
uLongf comprlen = (len>>9)+12 + len;
|
||||
std::vector<uint8> cbuf(comprlen);
|
||||
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)
|
||||
{
|
||||
// write "MARKERS" string
|
||||
os->fwrite(markers_save_id, MARKERS_ID_LEN);
|
||||
// write size
|
||||
int size = markers_array.size();
|
||||
write32le(size, os);
|
||||
// compress and write array
|
||||
int len = markers_array.size() * sizeof(int);
|
||||
uLongf comprlen = (len>>9)+12 + len;
|
||||
std::vector<uint8> cbuf(comprlen);
|
||||
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
|
||||
os->fwrite(markers_skipsave_id, MARKERS_ID_LEN);
|
||||
len = notes[i].length() + 1;
|
||||
if (len > MAX_NOTE_LEN) len = MAX_NOTE_LEN;
|
||||
write32le(len, os);
|
||||
os->fwrite(notes[i].c_str(), len);
|
||||
}
|
||||
}
|
||||
// returns true if couldn't load
|
||||
bool MARKERS::load(EMUFILE *is)
|
||||
{
|
||||
// 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
|
||||
FCEU_printf("No markers in the file\n");
|
||||
reset();
|
||||
return false;
|
||||
}
|
||||
if (strcmp(markers_save_id, save_id)) goto error; // string is not valid
|
||||
int size;
|
||||
if (read32le(&size, is))
|
||||
{
|
||||
|
@ -92,12 +40,12 @@ bool MARKERS::load(EMUFILE *is)
|
|||
// read and uncompress array
|
||||
int comprlen, len;
|
||||
uLongf destlen = size * sizeof(int);
|
||||
if (!read32le(&comprlen, is)) goto error;
|
||||
if (comprlen <= 0) goto error;
|
||||
if (!read32le(&comprlen, is)) return true;
|
||||
if (comprlen <= 0) return true;
|
||||
std::vector<uint8> cbuf(comprlen);
|
||||
if (is->fread(&cbuf[0], comprlen) != comprlen) goto error;
|
||||
if (is->fread(&cbuf[0], comprlen) != comprlen) return true;
|
||||
int e = uncompress((uint8*)&markers_array[0], &destlen, &cbuf[0], comprlen);
|
||||
if (e != Z_OK && e != Z_BUF_ERROR) goto error;
|
||||
if (e != Z_OK && e != Z_BUF_ERROR) return true;
|
||||
// read notes
|
||||
if (read32le(&size, is) && size >= 0)
|
||||
{
|
||||
|
@ -105,484 +53,36 @@ bool MARKERS::load(EMUFILE *is)
|
|||
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;
|
||||
if (!read32le(&len, is) || len < 0) return true;
|
||||
if ((int)is->fread(temp_str, len) < len) return true;
|
||||
notes[i] = temp_str;
|
||||
}
|
||||
// all ok
|
||||
return false;
|
||||
}
|
||||
}
|
||||
error:
|
||||
FCEU_printf("Error loading markers\n");
|
||||
reset();
|
||||
return true;
|
||||
}
|
||||
bool MARKERS::skipLoad(EMUFILE *is)
|
||||
{
|
||||
// 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;
|
||||
if (!read32le(&comprlen, is)) return true;
|
||||
if (is->fseek(comprlen, SEEK_CUR) != 0) return true;
|
||||
// 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;
|
||||
if (!read32le(&len, is) || len < 0) return true;
|
||||
if (is->fseek(len, SEEK_CUR) != 0) return true;
|
||||
}
|
||||
// all ok
|
||||
return false;
|
||||
}
|
||||
}
|
||||
error:
|
||||
FCEU_printf("Error skiploading markers\n");
|
||||
return true;
|
||||
}
|
||||
// ----------------------------------------------------------
|
||||
void MARKERS::MakeCopy(MARKERS& source)
|
||||
{
|
||||
// provide references
|
||||
source.CopyMarkersHere(markers_array, notes);
|
||||
}
|
||||
void MARKERS::CopyMarkersHere(std::vector<int>& array_for_markers, std::vector<std::string>& 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 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<int> temp_markers_array;
|
||||
std::vector<std::string> 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
|
||||
{
|
||||
// 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);
|
||||
}
|
||||
|
||||
int MARKERS::GetMarker(int frame)
|
||||
{
|
||||
if (frame >= 0 && frame < (int)markers_array.size())
|
||||
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)
|
||||
{
|
||||
if (start_frame >= (int)markers_array.size())
|
||||
start_frame = markers_array.size() - 1;
|
||||
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;
|
||||
}
|
||||
// returns number of new marker
|
||||
int MARKERS::SetMarker(int frame)
|
||||
{
|
||||
if (frame < 0)
|
||||
return 0;
|
||||
else if (frame >= (int)markers_array.size())
|
||||
markers_array.resize(frame + 1);
|
||||
else if (markers_array[frame])
|
||||
return markers_array[frame];
|
||||
|
||||
int marker_num = GetMarkerUp(frame) + 1;
|
||||
markers_array[frame] = marker_num;
|
||||
if (taseditor_config.empty_marker_notes)
|
||||
notes.insert(notes.begin() + marker_num, 1, "");
|
||||
else
|
||||
// copy previous marker note
|
||||
notes.insert(notes.begin() + marker_num, 1, notes[marker_num - 1]);
|
||||
// increase following markers' ids
|
||||
int size = markers_array.size();
|
||||
for (frame++; frame < size; ++frame)
|
||||
if (markers_array[frame])
|
||||
markers_array[frame]++;
|
||||
return marker_num;
|
||||
}
|
||||
void MARKERS::ClearMarker(int frame)
|
||||
{
|
||||
if (markers_array[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])
|
||||
ClearMarker(frame);
|
||||
else
|
||||
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)
|
||||
{
|
||||
markers_array.resize(markers_array.size() + frames);
|
||||
} else
|
||||
{
|
||||
markers_array.insert(markers_array.begin() + at, frames, 0);
|
||||
}
|
||||
}
|
||||
|
||||
int MARKERS::GetNotesSize()
|
||||
{
|
||||
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, const 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;
|
||||
}
|
||||
// ------------------------------------------------------------------------------------
|
||||
bool ordering(const std::pair<int, double>& d1, const std::pair<int, double>& d2)
|
||||
{
|
||||
return d1.second < d2.second;
|
||||
}
|
||||
void MARKERS::FindSimilar(int offset)
|
||||
{
|
||||
int i, t;
|
||||
int sourceMarker = playback.shown_marker;
|
||||
char sourceNote[MAX_NOTE_LEN];
|
||||
strcpy(sourceNote, GetNote(sourceMarker).c_str());
|
||||
|
||||
// check if playback_marker_text is empty
|
||||
if (!sourceNote[0])
|
||||
{
|
||||
MessageBox(taseditor_window.hwndTasEditor, "Marker Note under Playback cursor is empty!", "Find Similar Note", MB_OK);
|
||||
return;
|
||||
}
|
||||
// check if there's at least one note (not counting zeroth note)
|
||||
if (notes.size() <= 0)
|
||||
{
|
||||
MessageBox(taseditor_window.hwndTasEditor, "This project doesn't have any Markers!", "Find Similar Note", MB_OK);
|
||||
return;
|
||||
}
|
||||
|
||||
// 0 - divide source string into keywords
|
||||
int totalSourceKeywords = 0;
|
||||
char sourceKeywords[MAX_NUM_KEYWORDS][MAX_NOTE_LEN] = {0};
|
||||
int current_line_pos = 0;
|
||||
char sourceKeywordsLine[MAX_NUM_KEYWORDS] = {0};
|
||||
char* pch;
|
||||
// divide into tokens
|
||||
pch = strtok(sourceNote, keywordDelimiters);
|
||||
while (pch != NULL)
|
||||
{
|
||||
if (strlen(pch) >= KEYWORD_MIN_LEN)
|
||||
{
|
||||
// check if same keyword already appeared in the string
|
||||
for (t = totalSourceKeywords - 1; t >= 0; t--)
|
||||
if (!_stricmp(sourceKeywords[t], pch)) break;
|
||||
if (t < 0)
|
||||
{
|
||||
// save new keyword
|
||||
strcpy(sourceKeywords[totalSourceKeywords], pch);
|
||||
// also set its id into the line
|
||||
sourceKeywordsLine[current_line_pos++] = totalSourceKeywords + 1;
|
||||
totalSourceKeywords++;
|
||||
} else
|
||||
{
|
||||
// same keyword found
|
||||
sourceKeywordsLine[current_line_pos++] = t + 1;
|
||||
}
|
||||
}
|
||||
pch = strtok(NULL, keywordDelimiters);
|
||||
}
|
||||
// we found the line (sequence) of keywords
|
||||
sourceKeywordsLine[current_line_pos] = 0;
|
||||
|
||||
if (!totalSourceKeywords)
|
||||
{
|
||||
MessageBox(taseditor_window.hwndTasEditor, "Marker Note under Playback cursor doesn't have keywords!", "Find Similar Note", MB_OK);
|
||||
return;
|
||||
}
|
||||
|
||||
// 1 - find how frequently each keyword appears in notes
|
||||
std::vector<int> keywordFound(totalSourceKeywords);
|
||||
char checkedNote[MAX_NOTE_LEN];
|
||||
for (i = notes.size() - 1; i > 0; i--)
|
||||
{
|
||||
if (i != sourceMarker)
|
||||
{
|
||||
strcpy(checkedNote, notes[i].c_str());
|
||||
for (t = totalSourceKeywords - 1; t >= 0; t--)
|
||||
if (StrStrI(checkedNote, sourceKeywords[t]))
|
||||
keywordFound[t]++;
|
||||
}
|
||||
}
|
||||
// findmax
|
||||
int maxFound = 0;
|
||||
for (t = totalSourceKeywords - 1; t >= 0; t--)
|
||||
if (maxFound < keywordFound[t])
|
||||
maxFound = keywordFound[t];
|
||||
// and then calculate weight of each keyword: the more often it appears in markers, the less weight it has
|
||||
std::vector<double> keywordWeight(totalSourceKeywords);
|
||||
for (t = totalSourceKeywords - 1; t >= 0; t--)
|
||||
keywordWeight[t] = KEYWORD_WEIGHT_BASE + KEYWORD_WEIGHT_FACTOR * (keywordFound[t] / (double)maxFound);
|
||||
|
||||
// start accumulating priorities
|
||||
std::vector<std::pair<int, double>> notePriority(notes.size());
|
||||
|
||||
// 2 - find keywords in notes (including cases when keyword appears inside another word)
|
||||
for (i = notePriority.size() - 1; i > 0; i--)
|
||||
{
|
||||
notePriority[i].first = i;
|
||||
if (i != sourceMarker)
|
||||
{
|
||||
strcpy(checkedNote, notes[i].c_str());
|
||||
for (t = totalSourceKeywords - 1; t >= 0; t--)
|
||||
{
|
||||
if (StrStrI(checkedNote, sourceKeywords[t]))
|
||||
notePriority[i].second += KEYWORD_CASEINSENTITIVE_BONUS_PER_CHAR * keywordWeight[t] * strlen(sourceKeywords[t]);
|
||||
if (strstr(checkedNote, sourceKeywords[t]))
|
||||
notePriority[i].second += KEYWORD_CASESENTITIVE_BONUS_PER_CHAR * keywordWeight[t] * strlen(sourceKeywords[t]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 3 - search sequences of keywords from all other notes
|
||||
current_line_pos = 0;
|
||||
char checkedKeywordsLine[MAX_NUM_KEYWORDS] = {0};
|
||||
int keyword_id;
|
||||
for (i = notes.size() - 1; i > 0; i--)
|
||||
{
|
||||
if (i != sourceMarker)
|
||||
{
|
||||
strcpy(checkedNote, notes[i].c_str());
|
||||
// divide into tokens
|
||||
pch = strtok(checkedNote, keywordDelimiters);
|
||||
while (pch != NULL)
|
||||
{
|
||||
if (strlen(pch) >= KEYWORD_MIN_LEN)
|
||||
{
|
||||
// check if the keyword is one of sourceKeywords
|
||||
for (t = totalSourceKeywords - 1; t >= 0; t--)
|
||||
if (!_stricmp(sourceKeywords[t], pch)) break;
|
||||
if (t >= 0)
|
||||
{
|
||||
// the keyword is one of sourceKeywords - set its id into the line
|
||||
checkedKeywordsLine[current_line_pos++] = t + 1;
|
||||
} else
|
||||
{
|
||||
// found keyword that doesn't appear in sourceNote, give penalty
|
||||
notePriority[i].second -= KEYWORD_PENALTY_FOR_STRANGERS * strlen(pch);
|
||||
// since the keyword breaks our sequence of coincident keywords, check if that sequence is similar to sourceKeywordsLine
|
||||
if (current_line_pos >= KEYWORDS_LINE_MIN_SEQUENCE)
|
||||
{
|
||||
checkedKeywordsLine[current_line_pos] = 0;
|
||||
// search checkedKeywordsLine in sourceKeywordsLine
|
||||
if (strstr(sourceKeywordsLine, checkedKeywordsLine))
|
||||
{
|
||||
// found same sequence of keywords! add priority to this checkedNote
|
||||
for (t = current_line_pos - 1; t >= 0; t--)
|
||||
{
|
||||
// add bonus for every keyword in the sequence
|
||||
keyword_id = checkedKeywordsLine[t] - 1;
|
||||
notePriority[i].second += current_line_pos * KEYWORD_SEQUENCE_BONUS_PER_CHAR * keywordWeight[keyword_id] * strlen(sourceKeywords[keyword_id]);
|
||||
}
|
||||
}
|
||||
}
|
||||
// clear checkedKeywordsLine
|
||||
memset(checkedKeywordsLine, 0, MAX_NUM_KEYWORDS);
|
||||
current_line_pos = 0;
|
||||
}
|
||||
}
|
||||
pch = strtok(NULL, keywordDelimiters);
|
||||
}
|
||||
// finished dividing into tokens
|
||||
if (current_line_pos >= KEYWORDS_LINE_MIN_SEQUENCE)
|
||||
{
|
||||
checkedKeywordsLine[current_line_pos] = 0;
|
||||
// search checkedKeywordsLine in sourceKeywordsLine
|
||||
if (strstr(sourceKeywordsLine, checkedKeywordsLine))
|
||||
{
|
||||
// found same sequence of keywords! add priority to this checkedNote
|
||||
for (t = current_line_pos - 1; t >= 0; t--)
|
||||
{
|
||||
// add bonus for every keyword in the sequence
|
||||
keyword_id = checkedKeywordsLine[t] - 1;
|
||||
notePriority[i].second += current_line_pos * KEYWORD_SEQUENCE_BONUS_PER_CHAR * keywordWeight[keyword_id] * strlen(sourceKeywords[keyword_id]);
|
||||
}
|
||||
}
|
||||
}
|
||||
// clear checkedKeywordsLine
|
||||
memset(checkedKeywordsLine, 0, MAX_NUM_KEYWORDS);
|
||||
current_line_pos = 0;
|
||||
}
|
||||
}
|
||||
|
||||
// 4 - sort notePriority by second member of the pair
|
||||
std::sort(notePriority.begin(), notePriority.end(), ordering);
|
||||
|
||||
/*
|
||||
// debug trace
|
||||
FCEU_printf("\n\n\n\n\n\n\n\n\n\n");
|
||||
for (t = totalSourceKeywords - 1; t >= 0; t--)
|
||||
FCEU_printf("Keyword: %s, %d, %f\n", sourceKeywords[t], keywordFound[t], keywordWeight[t]);
|
||||
for (i = notePriority.size() - 1; i > 0; i--)
|
||||
{
|
||||
int marker_id = notePriority[i].first;
|
||||
FCEU_printf("Result: %s, %d, %f\n", notes[marker_id].c_str(), marker_id, notePriority[i].second);
|
||||
}
|
||||
*/
|
||||
|
||||
// Send selection to the marker found
|
||||
int index = notePriority.size()-1 - offset;
|
||||
if (index >= 0 && notePriority[index].second >= MIN_PRIORITY_TRESHOLD)
|
||||
{
|
||||
int marker_id = notePriority[index].first;
|
||||
int frame = GetMarkerFrame(marker_id);
|
||||
if (frame >= 0)
|
||||
selection.JumpToFrame(frame);
|
||||
} else
|
||||
{
|
||||
if (offset)
|
||||
MessageBox(taseditor_window.hwndTasEditor, "Could not find more Notes similar to Marker Note under Playback cursor!", "Find Similar Note", MB_OK);
|
||||
else
|
||||
MessageBox(taseditor_window.hwndTasEditor, "Could not find anything similar to Marker Note under Playback cursor!", "Find Similar Note", MB_OK);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -1,63 +1,18 @@
|
|||
//Specification file for Markers class
|
||||
#define MARKERS_ID_LEN 8
|
||||
#define MAX_NOTE_LEN 100
|
||||
|
||||
// constants for "Find Similar Note" algorithm (may need finetuning)
|
||||
#define KEYWORD_MIN_LEN 2
|
||||
#define MAX_NUM_KEYWORDS (MAX_NOTE_LEN / (KEYWORD_MIN_LEN+1)) + 1
|
||||
#define KEYWORD_WEIGHT_BASE 2.0
|
||||
#define KEYWORD_WEIGHT_FACTOR -1.0
|
||||
#define KEYWORD_CASEINSENTITIVE_BONUS_PER_CHAR 1.0 // these two should be small, because they also work when keyword is inside another keyword, giving irrelevant results
|
||||
#define KEYWORD_CASESENTITIVE_BONUS_PER_CHAR 1.0
|
||||
#define KEYWORD_SEQUENCE_BONUS_PER_CHAR 5.0
|
||||
#define KEYWORD_PENALTY_FOR_STRANGERS 0.2
|
||||
|
||||
#define KEYWORDS_LINE_MIN_SEQUENCE 1
|
||||
|
||||
#define MIN_PRIORITY_TRESHOLD 5.0
|
||||
|
||||
class MARKERS
|
||||
{
|
||||
public:
|
||||
MARKERS();
|
||||
void init();
|
||||
void free();
|
||||
void reset();
|
||||
void update();
|
||||
|
||||
void save(EMUFILE *os, bool really_save = true);
|
||||
void save(EMUFILE *os);
|
||||
bool load(EMUFILE *is);
|
||||
bool skipLoad(EMUFILE *is);
|
||||
|
||||
void MakeCopy(MARKERS& source);
|
||||
void CopyMarkersHere(std::vector<int>& array_for_markers, std::vector<std::string>& for_notes);
|
||||
void RestoreFromCopy(MARKERS& source, int until_frame = -1);
|
||||
|
||||
int GetMarkersSize();
|
||||
void SetMarkersSize(int new_size);
|
||||
|
||||
int GetMarker(int frame);
|
||||
int GetMarkerUp(int start_frame);
|
||||
int GetMarkerFrame(int marker_id);
|
||||
|
||||
int SetMarker(int frame);
|
||||
void ClearMarker(int frame);
|
||||
void ToggleMarker(int frame);
|
||||
|
||||
void EraseMarker(int frame);
|
||||
void insertEmpty(int at, int frames);
|
||||
|
||||
int GetNotesSize();
|
||||
std::string GetNote(int index);
|
||||
void SetNote(int index, const char* new_text);
|
||||
|
||||
bool checkMarkersDiff(MARKERS& their_markers);
|
||||
bool checkMarkersDiff(MARKERS& their_markers, int end);
|
||||
|
||||
void FindSimilar(int offset);
|
||||
|
||||
private:
|
||||
std::vector<int> markers_array; // Format: 0th = marker num (id) for frame 0, 1st = marker num for frame 1, ...
|
||||
std::vector<std::string> notes; // Format: 0th - note for intro (Marker 0), 1st - note for Marker1, 2nd - note for Marker2, ...
|
||||
|
||||
private:
|
||||
|
||||
};
|
||||
|
|
|
@ -0,0 +1,714 @@
|
|||
//Implementation file of Markers_manager class
|
||||
#include "taseditor_project.h"
|
||||
#include <Shlwapi.h> // for StrStrI
|
||||
|
||||
#pragma comment(lib, "Shlwapi.lib")
|
||||
|
||||
extern TASEDITOR_CONFIG taseditor_config;
|
||||
extern TASEDITOR_WINDOW taseditor_window;
|
||||
extern PLAYBACK playback;
|
||||
extern TASEDITOR_SELECTION selection;
|
||||
extern HISTORY history;
|
||||
|
||||
// resources
|
||||
char markers_save_id[MARKERS_ID_LEN] = "MARKERS";
|
||||
char markers_skipsave_id[MARKERS_ID_LEN] = "MARKERX";
|
||||
char keywordDelimiters[] = " !\"#$%&'()*+,-./:;<=>?@[\\]^_`{|}~";
|
||||
|
||||
MARKERS_MANAGER::MARKERS_MANAGER()
|
||||
{
|
||||
memset(findnote_string, 0, MAX_NOTE_LEN);
|
||||
}
|
||||
|
||||
void MARKERS_MANAGER::init()
|
||||
{
|
||||
reset();
|
||||
}
|
||||
void MARKERS_MANAGER::free()
|
||||
{
|
||||
markers.markers_array.resize(0);
|
||||
markers.notes.resize(0);
|
||||
}
|
||||
void MARKERS_MANAGER::reset()
|
||||
{
|
||||
free();
|
||||
marker_note_edit = MARKER_NOTE_EDIT_NONE;
|
||||
search_similar_marker = 0;
|
||||
markers.notes.resize(1);
|
||||
markers.notes[0] = "Power on";
|
||||
update();
|
||||
}
|
||||
void MARKERS_MANAGER::update()
|
||||
{
|
||||
if ((int)markers.markers_array.size() < currMovieData.getNumRecords())
|
||||
markers.markers_array.resize(currMovieData.getNumRecords());
|
||||
}
|
||||
|
||||
void MARKERS_MANAGER::save(EMUFILE *os, bool really_save)
|
||||
{
|
||||
if (really_save)
|
||||
{
|
||||
// write "MARKERS" string
|
||||
os->fwrite(markers_save_id, MARKERS_ID_LEN);
|
||||
markers.save(os);
|
||||
} else
|
||||
{
|
||||
// write "MARKERX" string, meaning that markers are not saved
|
||||
os->fwrite(markers_skipsave_id, MARKERS_ID_LEN);
|
||||
}
|
||||
}
|
||||
// returns true if couldn't load
|
||||
bool MARKERS_MANAGER::load(EMUFILE *is)
|
||||
{
|
||||
// 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
|
||||
FCEU_printf("No markers in the file\n");
|
||||
reset();
|
||||
return false;
|
||||
}
|
||||
if (strcmp(markers_save_id, save_id)) goto error; // string is not valid
|
||||
if (markers.load(is)) goto error;
|
||||
// all ok
|
||||
return false;
|
||||
error:
|
||||
FCEU_printf("Error loading markers\n");
|
||||
reset();
|
||||
return true;
|
||||
}
|
||||
// -----------------------------------------------------------------------------------------
|
||||
int MARKERS_MANAGER::GetMarkersSize()
|
||||
{
|
||||
return markers.markers_array.size();
|
||||
}
|
||||
void MARKERS_MANAGER::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.markers_array.size() - 1; i >= new_size; i--)
|
||||
if (markers.markers_array[i])
|
||||
ClearMarker(i);
|
||||
markers.markers_array.resize(new_size);
|
||||
}
|
||||
|
||||
int MARKERS_MANAGER::GetMarker(int frame)
|
||||
{
|
||||
if (frame >= 0 && frame < (int)markers.markers_array.size())
|
||||
return markers.markers_array[frame];
|
||||
else
|
||||
return 0;
|
||||
}
|
||||
// finds and returns # of Marker starting from start_frame and searching up
|
||||
int MARKERS_MANAGER::GetMarkerUp(int start_frame)
|
||||
{
|
||||
if (start_frame >= (int)markers.markers_array.size())
|
||||
start_frame = markers.markers_array.size() - 1;
|
||||
for (; start_frame >= 0; start_frame--)
|
||||
if (markers.markers_array[start_frame]) return markers.markers_array[start_frame];
|
||||
return 0;
|
||||
}
|
||||
// special version of the function
|
||||
int MARKERS_MANAGER::GetMarkerUp(MARKERS& target_markers, int start_frame)
|
||||
{
|
||||
if (start_frame >= (int)target_markers.markers_array.size())
|
||||
start_frame = target_markers.markers_array.size() - 1;
|
||||
for (; start_frame >= 0; start_frame--)
|
||||
if (target_markers.markers_array[start_frame]) return target_markers.markers_array[start_frame];
|
||||
return 0;
|
||||
}
|
||||
// finds frame where the Marker is set
|
||||
int MARKERS_MANAGER::GetMarkerFrame(int marker_id)
|
||||
{
|
||||
for (int i = markers.markers_array.size() - 1; i >= 0; i--)
|
||||
if (markers.markers_array[i] == marker_id) return i;
|
||||
// didn't find
|
||||
return -1;
|
||||
}
|
||||
// returns number of new marker
|
||||
int MARKERS_MANAGER::SetMarker(int frame)
|
||||
{
|
||||
if (frame < 0)
|
||||
return 0;
|
||||
else if (frame >= (int)markers.markers_array.size())
|
||||
markers.markers_array.resize(frame + 1);
|
||||
else if (markers.markers_array[frame])
|
||||
return markers.markers_array[frame];
|
||||
|
||||
int marker_num = GetMarkerUp(frame) + 1;
|
||||
markers.markers_array[frame] = marker_num;
|
||||
if (taseditor_config.empty_marker_notes)
|
||||
markers.notes.insert(markers.notes.begin() + marker_num, 1, "");
|
||||
else
|
||||
// copy previous marker note
|
||||
markers.notes.insert(markers.notes.begin() + marker_num, 1, markers.notes[marker_num - 1]);
|
||||
// increase following markers' ids
|
||||
int size = markers.markers_array.size();
|
||||
for (frame++; frame < size; ++frame)
|
||||
if (markers.markers_array[frame])
|
||||
markers.markers_array[frame]++;
|
||||
return marker_num;
|
||||
}
|
||||
void MARKERS_MANAGER::ClearMarker(int frame)
|
||||
{
|
||||
if (markers.markers_array[frame])
|
||||
{
|
||||
// erase corresponding note
|
||||
markers.notes.erase(markers.notes.begin() + markers.markers_array[frame]);
|
||||
// erase marker
|
||||
markers.markers_array[frame] = 0;
|
||||
// decrease following markers' ids
|
||||
int size = markers.markers_array.size();
|
||||
for (frame++; frame < size; ++frame)
|
||||
if (markers.markers_array[frame])
|
||||
markers.markers_array[frame]--;
|
||||
}
|
||||
}
|
||||
void MARKERS_MANAGER::ToggleMarker(int frame)
|
||||
{
|
||||
if (frame >= 0 && frame < (int)markers.markers_array.size())
|
||||
{
|
||||
if (markers.markers_array[frame])
|
||||
ClearMarker(frame);
|
||||
else
|
||||
SetMarker(frame);
|
||||
}
|
||||
}
|
||||
|
||||
void MARKERS_MANAGER::EraseMarker(int frame)
|
||||
{
|
||||
if (frame < (int)markers.markers_array.size())
|
||||
{
|
||||
// if there's a marker, first clear it
|
||||
if (markers.markers_array[frame])
|
||||
ClearMarker(frame);
|
||||
markers.markers_array.erase(markers.markers_array.begin() + frame);
|
||||
}
|
||||
}
|
||||
void MARKERS_MANAGER::insertEmpty(int at, int frames)
|
||||
{
|
||||
if(at == -1)
|
||||
{
|
||||
markers.markers_array.resize(markers.markers_array.size() + frames);
|
||||
} else
|
||||
{
|
||||
markers.markers_array.insert(markers.markers_array.begin() + at, frames, 0);
|
||||
}
|
||||
}
|
||||
|
||||
int MARKERS_MANAGER::GetNotesSize()
|
||||
{
|
||||
return markers.notes.size();
|
||||
}
|
||||
std::string MARKERS_MANAGER::GetNote(int index)
|
||||
{
|
||||
if (index >= 0 && index < (int)markers.notes.size())
|
||||
return markers.notes[index];
|
||||
else
|
||||
return markers.notes[0];
|
||||
}
|
||||
// special version of the function
|
||||
std::string MARKERS_MANAGER::GetNote(MARKERS& target_markers, int index)
|
||||
{
|
||||
if (index >= 0 && index < (int)target_markers.notes.size())
|
||||
return target_markers.notes[index];
|
||||
else
|
||||
return target_markers.notes[0];
|
||||
}
|
||||
void MARKERS_MANAGER::SetNote(int index, const char* new_text)
|
||||
{
|
||||
if (index >= 0 && index < (int)markers.notes.size())
|
||||
markers.notes[index] = new_text;
|
||||
}
|
||||
// ---------------------------------------------------------------------------------------
|
||||
void MARKERS_MANAGER::MakeCopyTo(MARKERS& destination)
|
||||
{
|
||||
destination.markers_array = markers.markers_array;
|
||||
destination.notes = markers.notes;
|
||||
}
|
||||
void MARKERS_MANAGER::RestoreFromCopy(MARKERS& source, int until_frame)
|
||||
{
|
||||
if (until_frame >= 0)
|
||||
{
|
||||
// restore markers up to and not including the frame
|
||||
if ((int)markers.markers_array.size() <= until_frame)
|
||||
{
|
||||
// only copy head of source
|
||||
markers.markers_array = source.markers_array;
|
||||
markers.markers_array.resize(until_frame);
|
||||
markers.notes = source.notes;
|
||||
// find last marker
|
||||
int last_marker = GetMarkerUp(until_frame-1);
|
||||
// delete all notes following the note of the last marker
|
||||
markers.notes.resize(last_marker+1);
|
||||
} else
|
||||
{
|
||||
// combine head of source and tail of destination (old markers)
|
||||
// 1 - head = part of source markers
|
||||
std::vector<int> temp_markers_array;
|
||||
std::vector<std::string> temp_notes;
|
||||
temp_markers_array = source.markers_array;
|
||||
temp_markers_array.resize(until_frame);
|
||||
temp_notes = source.notes;
|
||||
// find last marker in temp_markers_array
|
||||
int last_marker, frame;
|
||||
for (frame = until_frame-1; 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 = part of old (current) markers
|
||||
// delete all markers (and their notes) up to and not including until_frame
|
||||
//for (int i = until_frame-1; 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.markers_array.size();
|
||||
temp_markers_array.resize(size);
|
||||
for (int i = until_frame; i < size; ++i)
|
||||
{
|
||||
if (markers.markers_array[i])
|
||||
{
|
||||
last_marker++; // make new id for old marker
|
||||
temp_markers_array[i] = last_marker;
|
||||
temp_notes.push_back(markers.notes[markers.markers_array[i]]); // take note from old markers and add it to the end of the head
|
||||
}
|
||||
}
|
||||
// 4 - save result
|
||||
markers.markers_array = temp_markers_array;
|
||||
markers.notes = temp_notes;
|
||||
}
|
||||
} else
|
||||
{
|
||||
// end frame was not specified, consider this as "copy all"
|
||||
markers.markers_array = source.markers_array;
|
||||
markers.notes = source.notes;
|
||||
}
|
||||
}
|
||||
|
||||
// return true if any difference in markers_array is found, comparing to markers.markers_array
|
||||
bool MARKERS_MANAGER::checkMarkersDiff(MARKERS& their_markers)
|
||||
{
|
||||
if (GetMarkersSize() != their_markers.markers_array.size()) return true;
|
||||
if (GetNotesSize() != their_markers.notes.size()) return true;
|
||||
for (int i = markers.markers_array.size()-1; i >= 0; i--)
|
||||
{
|
||||
if (markers.markers_array[i] != their_markers.markers_array[i])
|
||||
return true;
|
||||
else if (markers.markers_array[i] && markers.notes[markers.markers_array[i]].compare(their_markers.notes[their_markers.markers_array[i]]))
|
||||
return true;
|
||||
}
|
||||
// also check if there's difference between 0th notes
|
||||
if (markers.notes[0].compare(their_markers.notes[0]))
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
// return true only when difference is found before end frame (not including end frame)
|
||||
bool MARKERS_MANAGER::checkMarkersDiff(MARKERS& their_markers, int end)
|
||||
{
|
||||
if (end < 0)
|
||||
return checkMarkersDiff(their_markers);
|
||||
|
||||
if (markers.markers_array.size() != their_markers.markers_array.size() && ((int)markers.markers_array.size()-1 < end || (int)their_markers.markers_array.size()-1 < end)) return true;
|
||||
for (int i = end-1; i >= 0; i--)
|
||||
{
|
||||
if (markers.markers_array[i] != their_markers.markers_array[i])
|
||||
return true;
|
||||
else if (markers.markers_array[i] && markers.notes[markers.markers_array[i]].compare(their_markers.notes[their_markers.markers_array[i]]))
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
// ------------------------------------------------------------------------------------
|
||||
// ordering function, used by std::sort
|
||||
bool ordering(const std::pair<int, double>& d1, const std::pair<int, double>& d2)
|
||||
{
|
||||
return d1.second < d2.second;
|
||||
}
|
||||
|
||||
void MARKERS_MANAGER::FindSimilar()
|
||||
{
|
||||
search_similar_marker = 0;
|
||||
FindNextSimilar();
|
||||
}
|
||||
void MARKERS_MANAGER::FindNextSimilar()
|
||||
{
|
||||
int i, t;
|
||||
int sourceMarker = playback.shown_marker;
|
||||
char sourceNote[MAX_NOTE_LEN];
|
||||
strcpy(sourceNote, GetNote(sourceMarker).c_str());
|
||||
|
||||
// check if playback_marker_text is empty
|
||||
if (!sourceNote[0])
|
||||
{
|
||||
MessageBox(taseditor_window.hwndTasEditor, "Marker Note under Playback cursor is empty!", "Find Similar Note", MB_OK);
|
||||
return;
|
||||
}
|
||||
// check if there's at least one note (not counting zeroth note)
|
||||
if (markers.notes.size() <= 0)
|
||||
{
|
||||
MessageBox(taseditor_window.hwndTasEditor, "This project doesn't have any Markers!", "Find Similar Note", MB_OK);
|
||||
return;
|
||||
}
|
||||
|
||||
// 0 - divide source string into keywords
|
||||
int totalSourceKeywords = 0;
|
||||
char sourceKeywords[MAX_NUM_KEYWORDS][MAX_NOTE_LEN] = {0};
|
||||
int current_line_pos = 0;
|
||||
char sourceKeywordsLine[MAX_NUM_KEYWORDS] = {0};
|
||||
char* pch;
|
||||
// divide into tokens
|
||||
pch = strtok(sourceNote, keywordDelimiters);
|
||||
while (pch != NULL)
|
||||
{
|
||||
if (strlen(pch) >= KEYWORD_MIN_LEN)
|
||||
{
|
||||
// check if same keyword already appeared in the string
|
||||
for (t = totalSourceKeywords - 1; t >= 0; t--)
|
||||
if (!_stricmp(sourceKeywords[t], pch)) break;
|
||||
if (t < 0)
|
||||
{
|
||||
// save new keyword
|
||||
strcpy(sourceKeywords[totalSourceKeywords], pch);
|
||||
// also set its id into the line
|
||||
sourceKeywordsLine[current_line_pos++] = totalSourceKeywords + 1;
|
||||
totalSourceKeywords++;
|
||||
} else
|
||||
{
|
||||
// same keyword found
|
||||
sourceKeywordsLine[current_line_pos++] = t + 1;
|
||||
}
|
||||
}
|
||||
pch = strtok(NULL, keywordDelimiters);
|
||||
}
|
||||
// we found the line (sequence) of keywords
|
||||
sourceKeywordsLine[current_line_pos] = 0;
|
||||
|
||||
if (!totalSourceKeywords)
|
||||
{
|
||||
MessageBox(taseditor_window.hwndTasEditor, "Marker Note under Playback cursor doesn't have keywords!", "Find Similar Note", MB_OK);
|
||||
return;
|
||||
}
|
||||
|
||||
// 1 - find how frequently each keyword appears in notes
|
||||
std::vector<int> keywordFound(totalSourceKeywords);
|
||||
char checkedNote[MAX_NOTE_LEN];
|
||||
for (i = markers.notes.size() - 1; i > 0; i--)
|
||||
{
|
||||
if (i != sourceMarker)
|
||||
{
|
||||
strcpy(checkedNote, markers.notes[i].c_str());
|
||||
for (t = totalSourceKeywords - 1; t >= 0; t--)
|
||||
if (StrStrI(checkedNote, sourceKeywords[t]))
|
||||
keywordFound[t]++;
|
||||
}
|
||||
}
|
||||
// findmax
|
||||
int maxFound = 0;
|
||||
for (t = totalSourceKeywords - 1; t >= 0; t--)
|
||||
if (maxFound < keywordFound[t])
|
||||
maxFound = keywordFound[t];
|
||||
// and then calculate weight of each keyword: the more often it appears in markers, the less weight it has
|
||||
std::vector<double> keywordWeight(totalSourceKeywords);
|
||||
for (t = totalSourceKeywords - 1; t >= 0; t--)
|
||||
keywordWeight[t] = KEYWORD_WEIGHT_BASE + KEYWORD_WEIGHT_FACTOR * (keywordFound[t] / (double)maxFound);
|
||||
|
||||
// start accumulating priorities
|
||||
std::vector<std::pair<int, double>> notePriority(markers.notes.size());
|
||||
|
||||
// 2 - find keywords in notes (including cases when keyword appears inside another word)
|
||||
for (i = notePriority.size() - 1; i > 0; i--)
|
||||
{
|
||||
notePriority[i].first = i;
|
||||
if (i != sourceMarker)
|
||||
{
|
||||
strcpy(checkedNote, markers.notes[i].c_str());
|
||||
for (t = totalSourceKeywords - 1; t >= 0; t--)
|
||||
{
|
||||
if (StrStrI(checkedNote, sourceKeywords[t]))
|
||||
notePriority[i].second += KEYWORD_CASEINSENTITIVE_BONUS_PER_CHAR * keywordWeight[t] * strlen(sourceKeywords[t]);
|
||||
if (strstr(checkedNote, sourceKeywords[t]))
|
||||
notePriority[i].second += KEYWORD_CASESENTITIVE_BONUS_PER_CHAR * keywordWeight[t] * strlen(sourceKeywords[t]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 3 - search sequences of keywords from all other notes
|
||||
current_line_pos = 0;
|
||||
char checkedKeywordsLine[MAX_NUM_KEYWORDS] = {0};
|
||||
int keyword_id;
|
||||
for (i = markers.notes.size() - 1; i > 0; i--)
|
||||
{
|
||||
if (i != sourceMarker)
|
||||
{
|
||||
strcpy(checkedNote, markers.notes[i].c_str());
|
||||
// divide into tokens
|
||||
pch = strtok(checkedNote, keywordDelimiters);
|
||||
while (pch != NULL)
|
||||
{
|
||||
if (strlen(pch) >= KEYWORD_MIN_LEN)
|
||||
{
|
||||
// check if the keyword is one of sourceKeywords
|
||||
for (t = totalSourceKeywords - 1; t >= 0; t--)
|
||||
if (!_stricmp(sourceKeywords[t], pch)) break;
|
||||
if (t >= 0)
|
||||
{
|
||||
// the keyword is one of sourceKeywords - set its id into the line
|
||||
checkedKeywordsLine[current_line_pos++] = t + 1;
|
||||
} else
|
||||
{
|
||||
// found keyword that doesn't appear in sourceNote, give penalty
|
||||
notePriority[i].second -= KEYWORD_PENALTY_FOR_STRANGERS * strlen(pch);
|
||||
// since the keyword breaks our sequence of coincident keywords, check if that sequence is similar to sourceKeywordsLine
|
||||
if (current_line_pos >= KEYWORDS_LINE_MIN_SEQUENCE)
|
||||
{
|
||||
checkedKeywordsLine[current_line_pos] = 0;
|
||||
// search checkedKeywordsLine in sourceKeywordsLine
|
||||
if (strstr(sourceKeywordsLine, checkedKeywordsLine))
|
||||
{
|
||||
// found same sequence of keywords! add priority to this checkedNote
|
||||
for (t = current_line_pos - 1; t >= 0; t--)
|
||||
{
|
||||
// add bonus for every keyword in the sequence
|
||||
keyword_id = checkedKeywordsLine[t] - 1;
|
||||
notePriority[i].second += current_line_pos * KEYWORD_SEQUENCE_BONUS_PER_CHAR * keywordWeight[keyword_id] * strlen(sourceKeywords[keyword_id]);
|
||||
}
|
||||
}
|
||||
}
|
||||
// clear checkedKeywordsLine
|
||||
memset(checkedKeywordsLine, 0, MAX_NUM_KEYWORDS);
|
||||
current_line_pos = 0;
|
||||
}
|
||||
}
|
||||
pch = strtok(NULL, keywordDelimiters);
|
||||
}
|
||||
// finished dividing into tokens
|
||||
if (current_line_pos >= KEYWORDS_LINE_MIN_SEQUENCE)
|
||||
{
|
||||
checkedKeywordsLine[current_line_pos] = 0;
|
||||
// search checkedKeywordsLine in sourceKeywordsLine
|
||||
if (strstr(sourceKeywordsLine, checkedKeywordsLine))
|
||||
{
|
||||
// found same sequence of keywords! add priority to this checkedNote
|
||||
for (t = current_line_pos - 1; t >= 0; t--)
|
||||
{
|
||||
// add bonus for every keyword in the sequence
|
||||
keyword_id = checkedKeywordsLine[t] - 1;
|
||||
notePriority[i].second += current_line_pos * KEYWORD_SEQUENCE_BONUS_PER_CHAR * keywordWeight[keyword_id] * strlen(sourceKeywords[keyword_id]);
|
||||
}
|
||||
}
|
||||
}
|
||||
// clear checkedKeywordsLine
|
||||
memset(checkedKeywordsLine, 0, MAX_NUM_KEYWORDS);
|
||||
current_line_pos = 0;
|
||||
}
|
||||
}
|
||||
|
||||
// 4 - sort notePriority by second member of the pair
|
||||
std::sort(notePriority.begin(), notePriority.end(), ordering);
|
||||
|
||||
/*
|
||||
// debug trace
|
||||
FCEU_printf("\n\n\n\n\n\n\n\n\n\n");
|
||||
for (t = totalSourceKeywords - 1; t >= 0; t--)
|
||||
FCEU_printf("Keyword: %s, %d, %f\n", sourceKeywords[t], keywordFound[t], keywordWeight[t]);
|
||||
for (i = notePriority.size() - 1; i > 0; i--)
|
||||
{
|
||||
int marker_id = notePriority[i].first;
|
||||
FCEU_printf("Result: %s, %d, %f\n", notes[marker_id].c_str(), marker_id, notePriority[i].second);
|
||||
}
|
||||
*/
|
||||
|
||||
// Send selection to the marker found
|
||||
int index = notePriority.size()-1 - search_similar_marker;
|
||||
if (index >= 0 && notePriority[index].second >= MIN_PRIORITY_TRESHOLD)
|
||||
{
|
||||
int marker_id = notePriority[index].first;
|
||||
int frame = GetMarkerFrame(marker_id);
|
||||
if (frame >= 0)
|
||||
selection.JumpToFrame(frame);
|
||||
} else
|
||||
{
|
||||
if (search_similar_marker)
|
||||
MessageBox(taseditor_window.hwndTasEditor, "Could not find more Notes similar to Marker Note under Playback cursor!", "Find Similar Note", MB_OK);
|
||||
else
|
||||
MessageBox(taseditor_window.hwndTasEditor, "Could not find anything similar to Marker Note under Playback cursor!", "Find Similar Note", MB_OK);
|
||||
}
|
||||
|
||||
// increase search_similar_marker so that next time we'll find another note
|
||||
search_similar_marker++;
|
||||
}
|
||||
// ------------------------------------------------------------------------------------
|
||||
void MARKERS_MANAGER::UpdateMarkerNote()
|
||||
{
|
||||
if (!marker_note_edit) return;
|
||||
char 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
|
||||
if (strcmp(GetNote(playback.shown_marker).c_str(), new_text))
|
||||
{
|
||||
SetNote(playback.shown_marker, new_text);
|
||||
if (playback.shown_marker)
|
||||
history.RegisterMarkersChange(MODTYPE_MARKER_RENAME, 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
|
||||
if (strcmp(GetNote(selection.shown_marker).c_str(), new_text))
|
||||
{
|
||||
SetNote(selection.shown_marker, new_text);
|
||||
if (selection.shown_marker)
|
||||
history.RegisterMarkersChange(MODTYPE_MARKER_RENAME, 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;
|
||||
}
|
||||
}
|
||||
}
|
||||
// ------------------------------------------------------------------------------------
|
||||
BOOL CALLBACK FindNoteProc(HWND hwndDlg, UINT message, WPARAM wParam, LPARAM lParam)
|
||||
{
|
||||
extern MARKERS_MANAGER markers_manager;
|
||||
switch (message)
|
||||
{
|
||||
case WM_INITDIALOG:
|
||||
{
|
||||
if (taseditor_config.findnote_wndx == -32000) taseditor_config.findnote_wndx = 0; //Just in case
|
||||
if (taseditor_config.findnote_wndy == -32000) taseditor_config.findnote_wndy = 0;
|
||||
SetWindowPos(hwndDlg, 0, taseditor_config.findnote_wndx, taseditor_config.findnote_wndy, 0, 0, SWP_NOSIZE | SWP_NOZORDER | SWP_NOOWNERZORDER);
|
||||
|
||||
CheckDlgButton(hwndDlg, IDC_MATCH_CASE, taseditor_config.findnote_matchcase?MF_CHECKED : MF_UNCHECKED);
|
||||
if (taseditor_config.findnote_search_up)
|
||||
Button_SetCheck(GetDlgItem(hwndDlg, IDC_RADIO_UP), BST_CHECKED);
|
||||
else
|
||||
Button_SetCheck(GetDlgItem(hwndDlg, IDC_RADIO_DOWN), BST_CHECKED);
|
||||
HWND hwndEdit = GetDlgItem(hwndDlg, IDC_NOTE_TO_FIND);
|
||||
SendMessage(hwndEdit, EM_SETLIMITTEXT, MAX_NOTE_LEN - 1, 0);
|
||||
SetWindowText(hwndEdit, markers_manager.findnote_string);
|
||||
if (GetDlgCtrlID((HWND)wParam) != IDC_NOTE_TO_FIND)
|
||||
{
|
||||
SetFocus(hwndEdit);
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
case WM_MOVE:
|
||||
{
|
||||
if (!IsIconic(hwndDlg))
|
||||
{
|
||||
RECT wrect;
|
||||
GetWindowRect(hwndDlg, &wrect);
|
||||
taseditor_config.findnote_wndx = wrect.left;
|
||||
taseditor_config.findnote_wndy = wrect.top;
|
||||
WindowBoundsCheckNoResize(taseditor_config.findnote_wndx, taseditor_config.findnote_wndy, wrect.right);
|
||||
}
|
||||
break;
|
||||
}
|
||||
case WM_COMMAND:
|
||||
{
|
||||
switch (LOWORD(wParam))
|
||||
{
|
||||
case IDC_NOTE_TO_FIND:
|
||||
{
|
||||
if(HIWORD(wParam) == EN_CHANGE)
|
||||
{
|
||||
if (GetWindowTextLength(GetDlgItem(hwndDlg, IDC_NOTE_TO_FIND)))
|
||||
EnableWindow(GetDlgItem(hwndDlg, IDOK), true);
|
||||
else
|
||||
EnableWindow(GetDlgItem(hwndDlg, IDOK), false);
|
||||
}
|
||||
break;
|
||||
}
|
||||
case IDC_RADIO_UP:
|
||||
taseditor_config.findnote_search_up = true;
|
||||
break;
|
||||
case IDC_RADIO_DOWN:
|
||||
taseditor_config.findnote_search_up = false;
|
||||
break;
|
||||
case IDC_MATCH_CASE:
|
||||
taseditor_config.findnote_matchcase ^= 1;
|
||||
CheckDlgButton(hwndDlg, IDC_MATCH_CASE, taseditor_config.findnote_matchcase?MF_CHECKED : MF_UNCHECKED);
|
||||
break;
|
||||
case IDOK:
|
||||
{
|
||||
int len = SendMessage(GetDlgItem(hwndDlg, IDC_NOTE_TO_FIND), WM_GETTEXT, MAX_NOTE_LEN, (LPARAM)markers_manager.findnote_string);
|
||||
markers_manager.findnote_string[len] = 0;
|
||||
// scan frames from current selection to the border
|
||||
int cur_marker = 0;
|
||||
bool result;
|
||||
int movie_size = currMovieData.getNumRecords();
|
||||
int current_frame = selection.GetCurrentSelectionBeginning();
|
||||
if (current_frame < 0 && taseditor_config.findnote_search_up)
|
||||
current_frame = movie_size;
|
||||
while (true)
|
||||
{
|
||||
// move forward
|
||||
if (taseditor_config.findnote_search_up)
|
||||
{
|
||||
current_frame--;
|
||||
if (current_frame < 0)
|
||||
{
|
||||
MessageBox(taseditor_window.hwndFindNote, "Nothing was found.", "Find Note", MB_OK);
|
||||
break;
|
||||
}
|
||||
} else
|
||||
{
|
||||
current_frame++;
|
||||
if (current_frame >= movie_size)
|
||||
{
|
||||
MessageBox(taseditor_window.hwndFindNote, "Nothing was found!", "Find Note", MB_OK);
|
||||
break;
|
||||
}
|
||||
}
|
||||
// scan marked frames
|
||||
cur_marker = markers_manager.GetMarker(current_frame);
|
||||
if (cur_marker)
|
||||
{
|
||||
if (taseditor_config.findnote_matchcase)
|
||||
result = (strstr(markers_manager.GetNote(cur_marker).c_str(), markers_manager.findnote_string) != 0);
|
||||
else
|
||||
result = (StrStrI(markers_manager.GetNote(cur_marker).c_str(), markers_manager.findnote_string) != 0);
|
||||
if (result)
|
||||
{
|
||||
// found note containing searched string - jump there
|
||||
selection.JumpToFrame(current_frame);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
return TRUE;
|
||||
}
|
||||
case IDCANCEL:
|
||||
DestroyWindow(taseditor_window.hwndFindNote);
|
||||
taseditor_window.hwndFindNote = 0;
|
||||
return TRUE;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case WM_CLOSE:
|
||||
case WM_QUIT:
|
||||
{
|
||||
DestroyWindow(taseditor_window.hwndFindNote);
|
||||
taseditor_window.hwndFindNote = 0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
|
|
@ -0,0 +1,76 @@
|
|||
//Specification file for Markers_manager class
|
||||
#include "markers.h"
|
||||
|
||||
#define MARKERS_ID_LEN 8
|
||||
// constants for "Find Similar Note" algorithm (may need finetuning)
|
||||
#define KEYWORD_MIN_LEN 2
|
||||
#define MAX_NUM_KEYWORDS (MAX_NOTE_LEN / (KEYWORD_MIN_LEN+1)) + 1
|
||||
#define KEYWORD_WEIGHT_BASE 2.0
|
||||
#define KEYWORD_WEIGHT_FACTOR -1.0
|
||||
#define KEYWORD_CASEINSENTITIVE_BONUS_PER_CHAR 1.0 // these two should be small, because they also work when keyword is inside another keyword, giving irrelevant results
|
||||
#define KEYWORD_CASESENTITIVE_BONUS_PER_CHAR 1.0
|
||||
#define KEYWORD_SEQUENCE_BONUS_PER_CHAR 5.0
|
||||
#define KEYWORD_PENALTY_FOR_STRANGERS 0.2
|
||||
#define KEYWORDS_LINE_MIN_SEQUENCE 1
|
||||
#define MIN_PRIORITY_TRESHOLD 5.0
|
||||
|
||||
enum
|
||||
{
|
||||
MARKER_NOTE_EDIT_NONE,
|
||||
MARKER_NOTE_EDIT_UPPER,
|
||||
MARKER_NOTE_EDIT_LOWER
|
||||
};
|
||||
|
||||
class MARKERS_MANAGER
|
||||
{
|
||||
public:
|
||||
MARKERS_MANAGER();
|
||||
void init();
|
||||
void free();
|
||||
void reset();
|
||||
void update();
|
||||
|
||||
void save(EMUFILE *os, bool really_save = true);
|
||||
bool load(EMUFILE *is);
|
||||
|
||||
int GetMarkersSize();
|
||||
void SetMarkersSize(int new_size);
|
||||
|
||||
int GetMarker(int frame);
|
||||
int GetMarkerUp(int start_frame);
|
||||
int GetMarkerUp(MARKERS& target_markers, int start_frame); // special version of the function
|
||||
int GetMarkerFrame(int marker_id);
|
||||
|
||||
int SetMarker(int frame);
|
||||
void ClearMarker(int frame);
|
||||
void ToggleMarker(int frame);
|
||||
|
||||
void EraseMarker(int frame);
|
||||
void insertEmpty(int at, int frames);
|
||||
|
||||
int GetNotesSize();
|
||||
std::string GetNote(int index);
|
||||
std::string GetNote(MARKERS& target_markers, int index); // special version of the function
|
||||
void SetNote(int index, const char* new_text);
|
||||
|
||||
void MakeCopyTo(MARKERS& destination);
|
||||
void RestoreFromCopy(MARKERS& source, int until_frame = -1);
|
||||
|
||||
bool checkMarkersDiff(MARKERS& their_markers);
|
||||
bool checkMarkersDiff(MARKERS& their_markers, int end);
|
||||
|
||||
void FindSimilar();
|
||||
void FindNextSimilar();
|
||||
|
||||
void UpdateMarkerNote();
|
||||
|
||||
// not saved vars
|
||||
int marker_note_edit;
|
||||
char findnote_string[MAX_NOTE_LEN];
|
||||
int search_similar_marker;
|
||||
|
||||
private:
|
||||
// saved vars
|
||||
MARKERS markers;
|
||||
|
||||
};
|
|
@ -1,6 +1,5 @@
|
|||
//Implementation file of Playback class
|
||||
#include "taseditor_project.h"
|
||||
#include "..\taseditor.h" // only for MARKER_NOTE_EDIT_UPPER
|
||||
|
||||
#ifdef _S9XLUA_H
|
||||
extern void ForceExecuteLuaFrameFunctions();
|
||||
|
@ -8,18 +7,14 @@ extern void ForceExecuteLuaFrameFunctions();
|
|||
|
||||
extern bool Taseditor_rewind_now;
|
||||
extern bool turbo;
|
||||
extern int marker_note_edit;
|
||||
extern int search_similar_marker;
|
||||
|
||||
extern TASEDITOR_CONFIG taseditor_config;
|
||||
extern TASEDITOR_WINDOW taseditor_window;
|
||||
extern MARKERS current_markers;
|
||||
extern MARKERS_MANAGER markers_manager;
|
||||
extern GREENZONE greenzone;
|
||||
extern TASEDITOR_LIST list;
|
||||
extern BOOKMARKS bookmarks;
|
||||
|
||||
extern void UpdateMarkerNote();
|
||||
|
||||
LRESULT APIENTRY UpperMarkerEditWndProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam);
|
||||
WNDPROC playbackMarkerEdit_oldWndproc;
|
||||
|
||||
|
@ -53,7 +48,7 @@ void PLAYBACK::reset()
|
|||
must_find_current_marker = true;
|
||||
shown_marker = 0;
|
||||
lastCursor = -1;
|
||||
pause_frame = old_pauseframe = 0;
|
||||
lost_position_frame = pause_frame = old_pauseframe = 0;
|
||||
old_show_pauseframe = show_pauseframe = false;
|
||||
old_rewind_button_state = rewind_button_state = false;
|
||||
old_forward_button_state = forward_button_state = false;
|
||||
|
@ -65,6 +60,11 @@ void PLAYBACK::reset()
|
|||
void PLAYBACK::update()
|
||||
{
|
||||
jump_was_used_this_frame = false;
|
||||
|
||||
// forget lost_position_frame when the position is restored
|
||||
if (currFrameCounter + 1 == lost_position_frame)
|
||||
lost_position_frame = 0;
|
||||
|
||||
// pause when seeking hit pause_frame
|
||||
if(!FCEUI_EmulationPaused())
|
||||
if(pause_frame && pause_frame <= currFrameCounter + 1)
|
||||
|
@ -124,10 +124,10 @@ void PLAYBACK::update()
|
|||
lastCursor = currFrameCounter;
|
||||
UpdateWindow(list.hwndList);
|
||||
// lazy update of "Playback's Marker text"
|
||||
int current_marker = current_markers.GetMarkerUp(currFrameCounter);
|
||||
int current_marker = markers_manager.GetMarkerUp(currFrameCounter);
|
||||
if (shown_marker != current_marker)
|
||||
{
|
||||
UpdateMarkerNote();
|
||||
markers_manager.UpdateMarkerNote();
|
||||
shown_marker = current_marker;
|
||||
RedrawMarker();
|
||||
must_find_current_marker = false;
|
||||
|
@ -137,8 +137,8 @@ void PLAYBACK::update()
|
|||
// [non-lazy] update "Playback's Marker text" if needed
|
||||
if (must_find_current_marker)
|
||||
{
|
||||
UpdateMarkerNote();
|
||||
shown_marker = current_markers.GetMarkerUp(currFrameCounter);
|
||||
markers_manager.UpdateMarkerNote();
|
||||
shown_marker = markers_manager.GetMarkerUp(currFrameCounter);
|
||||
RedrawMarker();
|
||||
must_find_current_marker = false;
|
||||
}
|
||||
|
@ -270,7 +270,7 @@ void PLAYBACK::RewindFull()
|
|||
// jump to previous marker
|
||||
int index = currFrameCounter - 1;
|
||||
for (; index >= 0; index--)
|
||||
if (current_markers.GetMarker(index)) break;
|
||||
if (markers_manager.GetMarker(index)) break;
|
||||
if (index >= 0)
|
||||
jump(index);
|
||||
else
|
||||
|
@ -283,7 +283,7 @@ void PLAYBACK::ForwardFull()
|
|||
int last_frame = currMovieData.getNumRecords()-1;
|
||||
int index = currFrameCounter + 1;
|
||||
for (; index <= last_frame; ++index)
|
||||
if (current_markers.GetMarker(index)) break;
|
||||
if (markers_manager.GetMarker(index)) break;
|
||||
if (index <= last_frame)
|
||||
jump(index);
|
||||
else
|
||||
|
@ -301,17 +301,18 @@ void PLAYBACK::RedrawMarker()
|
|||
strcat(new_text, num);
|
||||
SetWindowText(hwndPlaybackMarker, new_text);
|
||||
// change marker note
|
||||
strcpy(new_text, current_markers.GetNote(shown_marker).c_str());
|
||||
strcpy(new_text, markers_manager.GetNote(shown_marker).c_str());
|
||||
SetWindowText(hwndPlaybackMarkerEdit, new_text);
|
||||
// reset search_similar_marker
|
||||
search_similar_marker = 0;
|
||||
// reset search_similar_marker, because source marker changed
|
||||
markers_manager.search_similar_marker = 0;
|
||||
}
|
||||
|
||||
void PLAYBACK::StartFromZero()
|
||||
{
|
||||
poweron(true);
|
||||
currFrameCounter = 0;
|
||||
greenzone.TryDumpIncremental();
|
||||
if(currMovieData.getNumRecords() == 0)
|
||||
currMovieData.insertEmpty(-1, 1);
|
||||
}
|
||||
|
||||
void PLAYBACK::jump(int frame)
|
||||
|
@ -327,7 +328,7 @@ void PLAYBACK::restorePosition()
|
|||
if (pause_frame)
|
||||
jump(pause_frame-1);
|
||||
else
|
||||
jump(currFrameCounter);
|
||||
jump(lost_position_frame-1);
|
||||
}
|
||||
|
||||
bool PLAYBACK::JumpToFrame(int index)
|
||||
|
@ -367,7 +368,7 @@ bool PLAYBACK::JumpToFrame(int index)
|
|||
return true;
|
||||
}
|
||||
|
||||
int PLAYBACK::GetPauseFrame()
|
||||
int PLAYBACK::GetFlashingPauseFrame()
|
||||
{
|
||||
if (show_pauseframe)
|
||||
return pause_frame;
|
||||
|
@ -382,7 +383,7 @@ void PLAYBACK::SetProgressbar(int a, int b)
|
|||
// -------------------------------------------------------------------------
|
||||
LRESULT APIENTRY UpperMarkerEditWndProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam)
|
||||
{
|
||||
if (marker_note_edit == MARKER_NOTE_EDIT_UPPER)
|
||||
if (markers_manager.marker_note_edit == MARKER_NOTE_EDIT_UPPER)
|
||||
{
|
||||
extern PLAYBACK playback;
|
||||
extern TASEDITOR_SELECTION selection;
|
||||
|
@ -394,7 +395,7 @@ LRESULT APIENTRY UpperMarkerEditWndProc(HWND hWnd, UINT msg, WPARAM wParam, LPAR
|
|||
{
|
||||
case VK_ESCAPE:
|
||||
// revert text to original note text
|
||||
SetWindowText(playback.hwndPlaybackMarkerEdit, current_markers.GetNote(playback.shown_marker).c_str());
|
||||
SetWindowText(playback.hwndPlaybackMarkerEdit, markers_manager.GetNote(playback.shown_marker).c_str());
|
||||
SetFocus(list.hwndList);
|
||||
return 0;
|
||||
case VK_RETURN:
|
||||
|
|
|
@ -36,11 +36,12 @@ public:
|
|||
|
||||
void StartFromZero();
|
||||
|
||||
int GetPauseFrame();
|
||||
int GetFlashingPauseFrame();
|
||||
void SetProgressbar(int a, int b);
|
||||
|
||||
bool JumpToFrame(int index);
|
||||
|
||||
int lost_position_frame;
|
||||
int pause_frame;
|
||||
bool must_find_current_marker;
|
||||
int shown_marker;
|
||||
|
|
|
@ -4,9 +4,9 @@
|
|||
|
||||
extern TASEDITOR_CONFIG taseditor_config;
|
||||
extern TASEDITOR_WINDOW taseditor_window;
|
||||
extern MARKERS current_markers;
|
||||
extern BOOKMARKS bookmarks;
|
||||
extern TASEDITOR_LIST list;
|
||||
extern MARKERS_MANAGER markers_manager;
|
||||
|
||||
LRESULT CALLBACK ScrBmpWndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam);
|
||||
LRESULT APIENTRY MarkerNoteTooltipWndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam);
|
||||
|
@ -217,9 +217,9 @@ void POPUP_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);
|
||||
int marker_id = markers_manager.GetMarkerUp(bookmarks.bookmarks_array[bookmarks.item_under_mouse].snapshot.GetMarkers(), 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());
|
||||
strcpy(new_text, markers_manager.GetNote(bookmarks.bookmarks_array[bookmarks.item_under_mouse].snapshot.GetMarkers(), marker_id).c_str());
|
||||
SetWindowText(marker_note_tooltip, new_text);
|
||||
}
|
||||
|
||||
|
|
|
@ -1,17 +1,15 @@
|
|||
//Implementation file of RECORDER class
|
||||
#include "taseditor_project.h"
|
||||
#include "zlib.h"
|
||||
|
||||
extern int joysticks_per_frame[NUM_SUPPORTED_INPUT_TYPES];
|
||||
|
||||
extern uint32 GetGamepadPressedImmediate();
|
||||
extern void ColumnSet(int column);
|
||||
extern int GetInputType(MovieData& md);
|
||||
|
||||
extern TASEDITOR_CONFIG taseditor_config;
|
||||
extern TASEDITOR_WINDOW taseditor_window;
|
||||
extern BOOKMARKS bookmarks;
|
||||
extern INPUT_HISTORY history;
|
||||
extern HISTORY history;
|
||||
extern GREENZONE greenzone;
|
||||
extern TASEDITOR_LIST list;
|
||||
|
||||
|
@ -131,7 +129,7 @@ void RECORDER::update()
|
|||
{
|
||||
// if the button was pressed right now
|
||||
if ((current_joy[joy] & (1 << button)) && !(old_joy[joy] & (1 << button)))
|
||||
ColumnSet(COLUMN_JOYPAD1_A + joy * NUM_JOYPAD_BUTTONS + button);
|
||||
list.ColumnSet(COLUMN_JOYPAD1_A + joy * NUM_JOYPAD_BUTTONS + button);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,19 +1,19 @@
|
|||
//Implementation file of Input Snapshot class (Undo feature)
|
||||
//Implementation file of Snapshot class (Undo feature)
|
||||
#include "taseditor_project.h"
|
||||
#include "zlib.h"
|
||||
|
||||
int joysticks_per_frame[NUM_SUPPORTED_INPUT_TYPES] = {1, 2, 4};
|
||||
|
||||
extern MARKERS current_markers;
|
||||
extern MARKERS_MANAGER markers_manager;
|
||||
extern TASEDITOR_SELECTION selection;
|
||||
|
||||
extern int GetInputType(MovieData& md);
|
||||
|
||||
INPUT_SNAPSHOT::INPUT_SNAPSHOT()
|
||||
SNAPSHOT::SNAPSHOT()
|
||||
{
|
||||
}
|
||||
|
||||
void INPUT_SNAPSHOT::init(MovieData& md, bool hotchanges, int force_input_type)
|
||||
void SNAPSHOT::init(MovieData& md, bool hotchanges, int force_input_type)
|
||||
{
|
||||
has_hot_changes = hotchanges;
|
||||
if (force_input_type < 0)
|
||||
|
@ -64,12 +64,11 @@ void INPUT_SNAPSHOT::init(MovieData& md, bool hotchanges, int force_input_type)
|
|||
}
|
||||
}
|
||||
|
||||
// make a copy of current_markers
|
||||
my_markers.MakeCopy(current_markers);
|
||||
if ((int)my_markers.GetMarkersSize() < size)
|
||||
my_markers.SetMarkersSize(size);
|
||||
// make a copy of markers_manager.markers
|
||||
markers_manager.MakeCopyTo(my_markers);
|
||||
if ((int)my_markers.markers_array.size() < size)
|
||||
my_markers.markers_array.resize(size);
|
||||
|
||||
coherent = true;
|
||||
already_compressed = false;
|
||||
// save current time to description
|
||||
time_t raw_time;
|
||||
|
@ -78,12 +77,20 @@ void INPUT_SNAPSHOT::init(MovieData& md, bool hotchanges, int force_input_type)
|
|||
strftime(description, 10, "%H:%M:%S", timeinfo);
|
||||
}
|
||||
|
||||
void INPUT_SNAPSHOT::copyToMarkers(int end)
|
||||
bool SNAPSHOT::MarkersDifferFromCurrent(int end)
|
||||
{
|
||||
current_markers.RestoreFromCopy(my_markers, end);
|
||||
return markers_manager.checkMarkersDiff(my_markers, end);
|
||||
}
|
||||
void SNAPSHOT::copyToMarkers(int end)
|
||||
{
|
||||
markers_manager.RestoreFromCopy(my_markers, end);
|
||||
}
|
||||
MARKERS& SNAPSHOT::GetMarkers()
|
||||
{
|
||||
return my_markers;
|
||||
}
|
||||
|
||||
void INPUT_SNAPSHOT::toMovie(MovieData& md, int start, int end)
|
||||
void SNAPSHOT::toMovie(MovieData& md, int start, int end)
|
||||
{
|
||||
if (end < 0) end = size-1;
|
||||
// write input data to movie data
|
||||
|
@ -127,7 +134,7 @@ void INPUT_SNAPSHOT::toMovie(MovieData& md, int start, int end)
|
|||
}
|
||||
}
|
||||
|
||||
void INPUT_SNAPSHOT::compress_data()
|
||||
void SNAPSHOT::compress_data()
|
||||
{
|
||||
// compress joysticks
|
||||
int len = joysticks.size();
|
||||
|
@ -154,12 +161,11 @@ void INPUT_SNAPSHOT::compress_data()
|
|||
already_compressed = true;
|
||||
}
|
||||
|
||||
void INPUT_SNAPSHOT::save(EMUFILE *os)
|
||||
void SNAPSHOT::save(EMUFILE *os)
|
||||
{
|
||||
// write vars
|
||||
write32le(size, os);
|
||||
write8le(input_type, os);
|
||||
if (coherent) write8le(1, os); else write8le((uint8)0, os);
|
||||
write32le(jump_frame, os);
|
||||
write32le(rec_end_frame, os);
|
||||
write32le(rec_joypad_diff_bits, os);
|
||||
|
@ -185,18 +191,16 @@ void INPUT_SNAPSHOT::save(EMUFILE *os)
|
|||
os->fwrite(&hot_changes_compressed[0], hot_changes_compressed.size());
|
||||
}
|
||||
// save markers data
|
||||
my_markers.save(os, true);
|
||||
my_markers.save(os);
|
||||
}
|
||||
// returns true if couldn't load
|
||||
bool INPUT_SNAPSHOT::load(EMUFILE *is)
|
||||
bool SNAPSHOT::load(EMUFILE *is)
|
||||
{
|
||||
uint8 tmp;
|
||||
// read vars
|
||||
if (!read32le(&size, is)) return true;
|
||||
if (!read8le(&tmp, is)) return true;
|
||||
input_type = tmp;
|
||||
if (!read8le(&tmp, is)) return true;
|
||||
coherent = (tmp != 0);
|
||||
if (!read32le(&jump_frame, is)) return true;
|
||||
if (!read32le(&rec_end_frame, is)) return true;
|
||||
if (!read32le(&rec_joypad_diff_bits, is)) return true;
|
||||
|
@ -249,14 +253,13 @@ bool INPUT_SNAPSHOT::load(EMUFILE *is)
|
|||
if (my_markers.load(is)) return true;
|
||||
return false;
|
||||
}
|
||||
bool INPUT_SNAPSHOT::skipLoad(EMUFILE *is)
|
||||
bool SNAPSHOT::skipLoad(EMUFILE *is)
|
||||
{
|
||||
int tmp;
|
||||
uint8 tmp1;
|
||||
// read vars
|
||||
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
|
||||
|
@ -285,7 +288,7 @@ bool INPUT_SNAPSHOT::skipLoad(EMUFILE *is)
|
|||
}
|
||||
|
||||
// return true if any difference is found
|
||||
bool INPUT_SNAPSHOT::checkDiff(INPUT_SNAPSHOT& inp)
|
||||
bool SNAPSHOT::checkDiff(SNAPSHOT& inp)
|
||||
{
|
||||
if (size != inp.size) return true;
|
||||
if (findFirstChange(inp) >= 0)
|
||||
|
@ -295,7 +298,7 @@ bool INPUT_SNAPSHOT::checkDiff(INPUT_SNAPSHOT& inp)
|
|||
}
|
||||
|
||||
// fills map of bits judging on which joypads differ (this function is only used by "Record" modtype)
|
||||
void INPUT_SNAPSHOT::fillJoypadsDiff(INPUT_SNAPSHOT& inp, int frame)
|
||||
void SNAPSHOT::fillJoypadsDiff(SNAPSHOT& inp, int frame)
|
||||
{
|
||||
rec_joypad_diff_bits = 0;
|
||||
uint32 current_mask = 1;
|
||||
|
@ -323,8 +326,12 @@ void INPUT_SNAPSHOT::fillJoypadsDiff(INPUT_SNAPSHOT& inp, int frame)
|
|||
}
|
||||
|
||||
// return number of first frame of difference between two snapshots
|
||||
int INPUT_SNAPSHOT::findFirstChange(INPUT_SNAPSHOT& inp, int start, int end)
|
||||
int SNAPSHOT::findFirstChange(SNAPSHOT& inp, int start, int end)
|
||||
{
|
||||
// if these two snapshots have different input_type (abnormal situation) then refuse to search and return the beginning
|
||||
if (inp.input_type != input_type)
|
||||
return start;
|
||||
|
||||
// search for differences to the specified end (or to the end of this snapshot)
|
||||
if (end < 0 || end >= size) end = size-1;
|
||||
int inp_end = inp.size;
|
||||
|
@ -402,8 +409,8 @@ int INPUT_SNAPSHOT::findFirstChange(INPUT_SNAPSHOT& inp, int start, int end)
|
|||
// no changes were found
|
||||
return -1;
|
||||
}
|
||||
// return number of first frame of difference between this input_snapshot and MovieData
|
||||
int INPUT_SNAPSHOT::findFirstChange(MovieData& md, int start, int end)
|
||||
// return number of first frame of difference between this snapshot and MovieData
|
||||
int SNAPSHOT::findFirstChange(MovieData& md, int start, int end)
|
||||
{
|
||||
// search for differences to the specified end (or to the end of this snapshot / to the end of the movie)
|
||||
if (end < 0 || end >= size) end = size-1;
|
||||
|
@ -449,7 +456,7 @@ int INPUT_SNAPSHOT::findFirstChange(MovieData& md, int start, int end)
|
|||
return -1; // no changes were found
|
||||
}
|
||||
|
||||
int INPUT_SNAPSHOT::GetJoystickInfo(int frame, int joy)
|
||||
int SNAPSHOT::GetJoystickInfo(int frame, int joy)
|
||||
{
|
||||
if (frame < 0 || frame >= size) return 0;
|
||||
switch(input_type)
|
||||
|
@ -463,11 +470,63 @@ int INPUT_SNAPSHOT::GetJoystickInfo(int frame, int joy)
|
|||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
void SNAPSHOT::insertFrames(int at, int frames)
|
||||
{
|
||||
size += frames;
|
||||
if(at == -1)
|
||||
{
|
||||
// append frames to the end
|
||||
commands.resize(size);
|
||||
joysticks.resize(BYTES_PER_JOYSTICK * joysticks_per_frame[input_type] * size);
|
||||
if (has_hot_changes)
|
||||
{
|
||||
hot_changes.resize(joysticks_per_frame[input_type] * size * HOTCHANGE_BYTES_PER_JOY);
|
||||
// fill new hotchanges with max value
|
||||
int lower_limit = joysticks_per_frame[input_type] * (size - frames) * HOTCHANGE_BYTES_PER_JOY;
|
||||
for (int i = hot_changes.size() - 1; i >= lower_limit; i--)
|
||||
hot_changes[i] = 0xFF;
|
||||
}
|
||||
} else
|
||||
{
|
||||
// insert frames
|
||||
// insert 1 byte of commands
|
||||
commands.insert(commands.begin() + at, frames, 0);
|
||||
// insert X bytes of joystics
|
||||
int bytes = BYTES_PER_JOYSTICK * joysticks_per_frame[input_type];
|
||||
joysticks.insert(joysticks.begin() + (at * bytes), frames * bytes, 0);
|
||||
if (has_hot_changes)
|
||||
{
|
||||
// insert X bytes of hot_changes
|
||||
bytes = joysticks_per_frame[input_type] * HOTCHANGE_BYTES_PER_JOY;
|
||||
hot_changes.insert(hot_changes.begin() + (at * bytes), frames * bytes, 0xFF);
|
||||
}
|
||||
}
|
||||
// data was changed
|
||||
already_compressed = false;
|
||||
}
|
||||
void SNAPSHOT::eraseFrame(int frame)
|
||||
{
|
||||
// erase 1 byte of commands
|
||||
commands.erase(commands.begin() + frame);
|
||||
// erase X bytes of joystics
|
||||
int bytes = BYTES_PER_JOYSTICK * joysticks_per_frame[input_type];
|
||||
joysticks.erase(joysticks.begin() + (frame * bytes), joysticks.begin() + ((frame + 1) * bytes));
|
||||
if (has_hot_changes)
|
||||
{
|
||||
// erase X bytes of hot_changes
|
||||
bytes = joysticks_per_frame[input_type] * HOTCHANGE_BYTES_PER_JOY;
|
||||
hot_changes.erase(hot_changes.begin() + (frame * bytes), hot_changes.begin() + ((frame + 1) * bytes));
|
||||
}
|
||||
size--;
|
||||
// data was changed
|
||||
already_compressed = false;
|
||||
}
|
||||
// --------------------------------------------------------
|
||||
void INPUT_SNAPSHOT::copyHotChanges(INPUT_SNAPSHOT* source_of_hotchanges, int limit_frame_of_source)
|
||||
void SNAPSHOT::copyHotChanges(SNAPSHOT* source_of_hotchanges, int limit_frame_of_source)
|
||||
{
|
||||
// copy hot changes from source snapshot
|
||||
if (source_of_hotchanges && source_of_hotchanges->has_hot_changes)
|
||||
if (source_of_hotchanges && source_of_hotchanges->has_hot_changes && source_of_hotchanges->input_type == input_type)
|
||||
{
|
||||
int min = hot_changes.size();
|
||||
if (min > (int)source_of_hotchanges->hot_changes.size())
|
||||
|
@ -483,10 +542,10 @@ void INPUT_SNAPSHOT::copyHotChanges(INPUT_SNAPSHOT* source_of_hotchanges, int li
|
|||
memcpy(&hot_changes[0], &source_of_hotchanges->hot_changes[0], min);
|
||||
}
|
||||
}
|
||||
void INPUT_SNAPSHOT::inheritHotChanges(INPUT_SNAPSHOT* source_of_hotchanges)
|
||||
void SNAPSHOT::inheritHotChanges(SNAPSHOT* source_of_hotchanges)
|
||||
{
|
||||
// copy hot changes from source snapshot and fade them
|
||||
if (source_of_hotchanges && source_of_hotchanges->has_hot_changes)
|
||||
if (source_of_hotchanges && source_of_hotchanges->has_hot_changes && source_of_hotchanges->input_type == input_type)
|
||||
{
|
||||
int min = hot_changes.size();
|
||||
if (min > (int)source_of_hotchanges->hot_changes.size())
|
||||
|
@ -496,10 +555,10 @@ void INPUT_SNAPSHOT::inheritHotChanges(INPUT_SNAPSHOT* source_of_hotchanges)
|
|||
FadeHotChanges();
|
||||
}
|
||||
}
|
||||
void INPUT_SNAPSHOT::inheritHotChanges_DeleteSelection(INPUT_SNAPSHOT* source_of_hotchanges)
|
||||
void SNAPSHOT::inheritHotChanges_DeleteSelection(SNAPSHOT* source_of_hotchanges)
|
||||
{
|
||||
// copy hot changes from source snapshot, but omit deleted frames (which are represented by current selection)
|
||||
if (source_of_hotchanges && source_of_hotchanges->has_hot_changes)
|
||||
if (source_of_hotchanges && source_of_hotchanges->has_hot_changes && source_of_hotchanges->input_type == input_type)
|
||||
{
|
||||
int bytes = joysticks_per_frame[input_type] * HOTCHANGE_BYTES_PER_JOY;
|
||||
int frame = 0, pos = 0, source_pos = 0;
|
||||
|
@ -525,10 +584,10 @@ void INPUT_SNAPSHOT::inheritHotChanges_DeleteSelection(INPUT_SNAPSHOT* source_of
|
|||
FadeHotChanges();
|
||||
}
|
||||
}
|
||||
void INPUT_SNAPSHOT::inheritHotChanges_InsertSelection(INPUT_SNAPSHOT* source_of_hotchanges)
|
||||
void SNAPSHOT::inheritHotChanges_InsertSelection(SNAPSHOT* source_of_hotchanges)
|
||||
{
|
||||
// copy hot changes from source snapshot, but insert filled lines for inserted frames (which are represented by current selection)
|
||||
if (source_of_hotchanges && source_of_hotchanges->has_hot_changes)
|
||||
if (source_of_hotchanges && source_of_hotchanges->has_hot_changes && source_of_hotchanges->input_type == input_type)
|
||||
{
|
||||
int bytes = joysticks_per_frame[input_type] * HOTCHANGE_BYTES_PER_JOY;
|
||||
int frame = 0, region_len = 0, pos = 0, source_pos = 0;
|
||||
|
@ -588,16 +647,16 @@ void INPUT_SNAPSHOT::inheritHotChanges_InsertSelection(INPUT_SNAPSHOT* source_of
|
|||
}
|
||||
}
|
||||
}
|
||||
void INPUT_SNAPSHOT::inheritHotChanges_PasteInsert(INPUT_SNAPSHOT* source_of_hotchanges)
|
||||
void SNAPSHOT::inheritHotChanges_PasteInsert(SNAPSHOT* source_of_hotchanges, SelectionFrames& inserted_set)
|
||||
{
|
||||
// copy hot changes from source snapshot and insert filled lines for inserted frames (which are represented by inserted_set)
|
||||
if (source_of_hotchanges && source_of_hotchanges->has_hot_changes)
|
||||
if (source_of_hotchanges && source_of_hotchanges->has_hot_changes && source_of_hotchanges->input_type == input_type)
|
||||
{
|
||||
int bytes = joysticks_per_frame[input_type] * HOTCHANGE_BYTES_PER_JOY;
|
||||
int frame = 0, pos = 0, source_pos = 0;
|
||||
int this_size = hot_changes.size(), source_size = source_of_hotchanges->hot_changes.size();
|
||||
SelectionFrames::iterator it(selection.GetInsertedSet().begin());
|
||||
SelectionFrames::iterator inserted_set_end(selection.GetInsertedSet().end());
|
||||
SelectionFrames::iterator it(inserted_set.begin());
|
||||
SelectionFrames::iterator inserted_set_end(inserted_set.end());
|
||||
while (pos < this_size)
|
||||
{
|
||||
if (it != inserted_set_end && frame == *it)
|
||||
|
@ -622,8 +681,8 @@ void INPUT_SNAPSHOT::inheritHotChanges_PasteInsert(INPUT_SNAPSHOT* source_of_hot
|
|||
int bytes = joysticks_per_frame[input_type] * HOTCHANGE_BYTES_PER_JOY;
|
||||
int frame = 0, pos = 0;
|
||||
int this_size = hot_changes.size();
|
||||
SelectionFrames::iterator it(selection.GetInsertedSet().begin());
|
||||
SelectionFrames::iterator inserted_set_end(selection.GetInsertedSet().end());
|
||||
SelectionFrames::iterator it(inserted_set.begin());
|
||||
SelectionFrames::iterator inserted_set_end(inserted_set.end());
|
||||
while (pos < this_size)
|
||||
{
|
||||
if (it != inserted_set_end && frame == *it)
|
||||
|
@ -644,9 +703,13 @@ void INPUT_SNAPSHOT::inheritHotChanges_PasteInsert(INPUT_SNAPSHOT* source_of_hot
|
|||
}
|
||||
}
|
||||
}
|
||||
void INPUT_SNAPSHOT::fillHotChanges(INPUT_SNAPSHOT& inp, int start, int end)
|
||||
void SNAPSHOT::fillHotChanges(SNAPSHOT& inp, int start, int end)
|
||||
{
|
||||
// search for differences to the specified end (or to the end of this snapshot)
|
||||
// if these two snapshots have different input_type (abnormal situation) then refuse to compare
|
||||
if (inp.input_type != input_type)
|
||||
return;
|
||||
|
||||
// compare snapshots to the specified end (or to the end of this snapshot)
|
||||
if (end < 0 || end >= size) end = size-1;
|
||||
int inp_end = inp.size;
|
||||
switch(input_type)
|
||||
|
@ -735,7 +798,7 @@ void INPUT_SNAPSHOT::fillHotChanges(INPUT_SNAPSHOT& inp, int start, int end)
|
|||
}
|
||||
}
|
||||
|
||||
void INPUT_SNAPSHOT::SetMaxHotChange_Bits(int frame, int joypad, uint8 joy_bits)
|
||||
void SNAPSHOT::SetMaxHotChange_Bits(int frame, int joypad, uint8 joy_bits)
|
||||
{
|
||||
uint8 mask = 1;
|
||||
// check all 8 buttons and set max hot_changes for bits that are set
|
||||
|
@ -746,7 +809,7 @@ void INPUT_SNAPSHOT::SetMaxHotChange_Bits(int frame, int joypad, uint8 joy_bits)
|
|||
mask <<= 1;
|
||||
}
|
||||
}
|
||||
void INPUT_SNAPSHOT::SetMaxHotChange(int frame, int absolute_button)
|
||||
void SNAPSHOT::SetMaxHotChange(int frame, int absolute_button)
|
||||
{
|
||||
if (frame < 0 || frame >= size || !has_hot_changes) return;
|
||||
// set max value (15) to the button hotness
|
||||
|
@ -788,7 +851,7 @@ void INPUT_SNAPSHOT::SetMaxHotChange(int frame, int absolute_button)
|
|||
}
|
||||
}
|
||||
|
||||
void INPUT_SNAPSHOT::FadeHotChanges()
|
||||
void SNAPSHOT::FadeHotChanges()
|
||||
{
|
||||
uint8 hi_half, low_half;
|
||||
for (int i = hot_changes.size() - 1; i >= 0; i--)
|
||||
|
@ -804,7 +867,7 @@ void INPUT_SNAPSHOT::FadeHotChanges()
|
|||
}
|
||||
}
|
||||
|
||||
int INPUT_SNAPSHOT::GetHotChangeInfo(int frame, int absolute_button)
|
||||
int SNAPSHOT::GetHotChangeInfo(int frame, int absolute_button)
|
||||
{
|
||||
if (!has_hot_changes || frame < 0 || frame >= size || absolute_button < 0 || absolute_button >= NUM_JOYPAD_BUTTONS * joysticks_per_frame[input_type])
|
||||
return 0;
|
|
@ -13,33 +13,39 @@ enum Input_types
|
|||
|
||||
#define SNAPSHOT_DESC_MAX_LENGTH 100
|
||||
|
||||
class INPUT_SNAPSHOT
|
||||
class SNAPSHOT
|
||||
{
|
||||
public:
|
||||
INPUT_SNAPSHOT();
|
||||
SNAPSHOT();
|
||||
void init(MovieData& md, bool hotchanges, int force_input_type = -1);
|
||||
|
||||
void toMovie(MovieData& md, int start = 0, int end = -1);
|
||||
bool MarkersDifferFromCurrent(int end = -1);
|
||||
void copyToMarkers(int end = -1);
|
||||
MARKERS& GetMarkers();
|
||||
|
||||
void toMovie(MovieData& md, int start = 0, int end = -1);
|
||||
|
||||
void save(EMUFILE *os);
|
||||
bool load(EMUFILE *is);
|
||||
bool skipLoad(EMUFILE *is);
|
||||
|
||||
bool checkDiff(INPUT_SNAPSHOT& inp);
|
||||
void fillJoypadsDiff(INPUT_SNAPSHOT& inp, int frame);
|
||||
bool checkDiff(SNAPSHOT& inp);
|
||||
void fillJoypadsDiff(SNAPSHOT& inp, int frame);
|
||||
|
||||
int findFirstChange(INPUT_SNAPSHOT& inp, int start = 0, int end = -1);
|
||||
int findFirstChange(SNAPSHOT& inp, int start = 0, int end = -1);
|
||||
int findFirstChange(MovieData& md, int start = 0, int end = -1);
|
||||
|
||||
int GetJoystickInfo(int frame, int joy);
|
||||
|
||||
void copyHotChanges(INPUT_SNAPSHOT* source_of_hotchanges, int limit_frame_of_source = -1);
|
||||
void inheritHotChanges(INPUT_SNAPSHOT* source_of_hotchanges);
|
||||
void inheritHotChanges_DeleteSelection(INPUT_SNAPSHOT* source_of_hotchanges);
|
||||
void inheritHotChanges_InsertSelection(INPUT_SNAPSHOT* source_of_hotchanges);
|
||||
void inheritHotChanges_PasteInsert(INPUT_SNAPSHOT* source_of_hotchanges);
|
||||
void fillHotChanges(INPUT_SNAPSHOT& inp, int start = 0, int end = -1);
|
||||
void insertFrames(int at, int frames);
|
||||
void eraseFrame(int frame);
|
||||
|
||||
void copyHotChanges(SNAPSHOT* source_of_hotchanges, int limit_frame_of_source = -1);
|
||||
void inheritHotChanges(SNAPSHOT* source_of_hotchanges);
|
||||
void inheritHotChanges_DeleteSelection(SNAPSHOT* source_of_hotchanges);
|
||||
void inheritHotChanges_InsertSelection(SNAPSHOT* source_of_hotchanges);
|
||||
void inheritHotChanges_PasteInsert(SNAPSHOT* source_of_hotchanges, SelectionFrames& inserted_set);
|
||||
void fillHotChanges(SNAPSHOT& inp, int start = 0, int end = -1);
|
||||
|
||||
void SetMaxHotChange_Bits(int frame, int joypad, uint8 joy_bits);
|
||||
void SetMaxHotChange(int frame, int absolute_button);
|
||||
|
@ -48,14 +54,12 @@ public:
|
|||
|
||||
int GetHotChangeInfo(int frame, int absolute_button);
|
||||
|
||||
// saved data
|
||||
int size; // in frames
|
||||
int input_type; // theoretically TAS Editor can support any other input types
|
||||
std::vector<uint8> joysticks; // Format: joy0-for-frame0, joy1-for-frame0, joy2-for-frame0, joy3-for-frame0, joy0-for-frame1, joy1-for-frame1, ...
|
||||
std::vector<uint8> commands; // Format: commands-for-frame0, commands-for-frame1, ...
|
||||
std::vector<uint8> hot_changes; // Format: buttons01joy0-for-frame0, buttons23joy0-for-frame0, buttons45joy0-for-frame0, buttons67joy0-for-frame0, buttons01joy1-for-frame0, ...
|
||||
MARKERS my_markers;
|
||||
|
||||
bool coherent; // indicates whether this state was made right after previous state
|
||||
int jump_frame; // for jumping when making undo
|
||||
int rec_end_frame; // for consecutive Recordings
|
||||
uint32 rec_joypad_diff_bits; // for consecutive Recordings
|
||||
|
@ -66,10 +70,12 @@ public:
|
|||
private:
|
||||
void compress_data();
|
||||
|
||||
bool already_compressed; // to compress only once
|
||||
// also saved data
|
||||
MARKERS my_markers;
|
||||
std::vector<uint8> joysticks_compressed;
|
||||
std::vector<uint8> commands_compressed;
|
||||
std::vector<uint8> hot_changes_compressed;
|
||||
|
||||
bool already_compressed; // to compress only once
|
||||
};
|
||||
|
|
@ -5,8 +5,8 @@
|
|||
|
||||
extern TASEDITOR_WINDOW taseditor_window;
|
||||
extern TASEDITOR_CONFIG taseditor_config;
|
||||
extern INPUT_HISTORY history;
|
||||
extern MARKERS current_markers;
|
||||
extern HISTORY history;
|
||||
extern MARKERS_MANAGER markers_manager;
|
||||
extern PLAYBACK playback;
|
||||
extern GREENZONE greenzone;
|
||||
extern TASEDITOR_LIST list;
|
||||
|
@ -105,13 +105,13 @@ void SPLICER::CloneFrames()
|
|||
// end of current region
|
||||
currMovieData.cloneRegion(*it, frames);
|
||||
if (taseditor_config.bind_markers)
|
||||
current_markers.insertEmpty(*it, frames);
|
||||
markers_manager.insertEmpty(*it, frames);
|
||||
frames = 1;
|
||||
} else frames++;
|
||||
}
|
||||
if (taseditor_config.bind_markers)
|
||||
{
|
||||
current_markers.update();
|
||||
markers_manager.update();
|
||||
selection.must_find_current_marker = playback.must_find_current_marker = true;
|
||||
}
|
||||
greenzone.InvalidateAndCheck(history.RegisterChanges(MODTYPE_CLONE, *current_selection->begin()));
|
||||
|
@ -139,13 +139,13 @@ void SPLICER::InsertFrames()
|
|||
// end of current region
|
||||
currMovieData.insertEmpty(*it,frames);
|
||||
if (taseditor_config.bind_markers)
|
||||
current_markers.insertEmpty(*it,frames);
|
||||
markers_manager.insertEmpty(*it,frames);
|
||||
frames = 1;
|
||||
} else frames++;
|
||||
}
|
||||
if (taseditor_config.bind_markers)
|
||||
{
|
||||
current_markers.update();
|
||||
markers_manager.update();
|
||||
selection.must_find_current_marker = playback.must_find_current_marker = true;
|
||||
}
|
||||
greenzone.InvalidateAndCheck(history.RegisterChanges(MODTYPE_INSERT, *current_selection->begin()));
|
||||
|
@ -173,7 +173,7 @@ void SPLICER::InsertNumFrames()
|
|||
currMovieData.insertEmpty(index, frames);
|
||||
if (taseditor_config.bind_markers)
|
||||
{
|
||||
current_markers.insertEmpty(index, frames);
|
||||
markers_manager.insertEmpty(index, frames);
|
||||
selection.must_find_current_marker = playback.must_find_current_marker = true;
|
||||
}
|
||||
// select inserted rows
|
||||
|
@ -197,7 +197,7 @@ void SPLICER::DeleteFrames()
|
|||
{
|
||||
currMovieData.records.erase(currMovieData.records.begin() + *it);
|
||||
if (taseditor_config.bind_markers)
|
||||
current_markers.EraseMarker(*it);
|
||||
markers_manager.EraseMarker(*it);
|
||||
}
|
||||
if (taseditor_config.bind_markers)
|
||||
selection.must_find_current_marker = playback.must_find_current_marker = true;
|
||||
|
@ -249,7 +249,7 @@ void SPLICER::Truncate()
|
|||
currMovieData.truncateAt(frame+1);
|
||||
if (taseditor_config.bind_markers)
|
||||
{
|
||||
current_markers.SetMarkersSize(frame+1);
|
||||
markers_manager.SetMarkersSize(frame+1);
|
||||
selection.must_find_current_marker = playback.must_find_current_marker = true;
|
||||
}
|
||||
list.update();
|
||||
|
@ -308,26 +308,24 @@ bool SPLICER::Copy(SelectionFrames* current_selection)
|
|||
}
|
||||
}
|
||||
clipString << std::endl;
|
||||
|
||||
if (!OpenClipboard(taseditor_window.hwndTasEditor))
|
||||
return false;
|
||||
EmptyClipboard();
|
||||
|
||||
HGLOBAL hGlobal = GlobalAlloc(GMEM_MOVEABLE, clipString.str().size()+1);
|
||||
|
||||
if (hGlobal==INVALID_HANDLE_VALUE)
|
||||
{
|
||||
CloseClipboard();
|
||||
return false;
|
||||
}
|
||||
char *pGlobal = (char*)GlobalLock(hGlobal);
|
||||
strcpy(pGlobal, clipString.str().c_str());
|
||||
GlobalUnlock(hGlobal);
|
||||
SetClipboardData(CF_TEXT, hGlobal);
|
||||
|
||||
CloseClipboard();
|
||||
}
|
||||
// write data to clipboard
|
||||
if (!OpenClipboard(taseditor_window.hwndTasEditor))
|
||||
return false;
|
||||
EmptyClipboard();
|
||||
|
||||
HGLOBAL hGlobal = GlobalAlloc(GMEM_MOVEABLE, clipString.str().size()+1);
|
||||
if (hGlobal==INVALID_HANDLE_VALUE)
|
||||
{
|
||||
CloseClipboard();
|
||||
return false;
|
||||
}
|
||||
char *pGlobal = (char*)GlobalLock(hGlobal);
|
||||
strcpy(pGlobal, clipString.str().c_str());
|
||||
GlobalUnlock(hGlobal);
|
||||
SetClipboardData(CF_TEXT, hGlobal);
|
||||
|
||||
CloseClipboard();
|
||||
}
|
||||
catch (std::bad_alloc e)
|
||||
{
|
||||
|
@ -374,7 +372,7 @@ bool SPLICER::Paste()
|
|||
if (currMovieData.getNumRecords() < pos+range)
|
||||
{
|
||||
currMovieData.insertEmpty(currMovieData.getNumRecords(),pos+range-currMovieData.getNumRecords());
|
||||
current_markers.update();
|
||||
markers_manager.update();
|
||||
}
|
||||
|
||||
pGlobal = strchr(pGlobal, '\n');
|
||||
|
@ -490,15 +488,14 @@ bool SPLICER::PasteInsert()
|
|||
if (pGlobal[0]=='T' && pGlobal[1]=='A' && pGlobal[2]=='S')
|
||||
{
|
||||
// make sure markers have the same size as movie
|
||||
current_markers.update();
|
||||
// init inserted_set (for input history hot changes)
|
||||
selection.GetInsertedSet().clear();
|
||||
markers_manager.update();
|
||||
// create inserted_set (for input history hot changes)
|
||||
SelectionFrames inserted_set;
|
||||
|
||||
// Extract number of frames
|
||||
int range;
|
||||
sscanf (pGlobal+3, "%d", &range);
|
||||
|
||||
|
||||
pGlobal = strchr(pGlobal, '\n');
|
||||
char* frame;
|
||||
int joy=0;
|
||||
|
@ -514,7 +511,7 @@ bool SPLICER::PasteInsert()
|
|||
if (currMovieData.getNumRecords() < pos)
|
||||
{
|
||||
currMovieData.insertEmpty(currMovieData.getNumRecords(), pos - currMovieData.getNumRecords());
|
||||
current_markers.update();
|
||||
markers_manager.update();
|
||||
}
|
||||
while (*frame && *frame != '\n' && *frame != '|')
|
||||
++frame;
|
||||
|
@ -526,8 +523,8 @@ bool SPLICER::PasteInsert()
|
|||
|
||||
// insert new frame
|
||||
currMovieData.insertEmpty(pos, 1);
|
||||
if (taseditor_config.bind_markers) current_markers.insertEmpty(pos, 1);
|
||||
selection.GetInsertedSet().insert(pos);
|
||||
if (taseditor_config.bind_markers) markers_manager.insertEmpty(pos, 1);
|
||||
inserted_set.insert(pos);
|
||||
|
||||
// read this frame input
|
||||
int joy = 0;
|
||||
|
@ -555,10 +552,10 @@ bool SPLICER::PasteInsert()
|
|||
|
||||
pGlobal = strchr(pGlobal, '\n');
|
||||
}
|
||||
current_markers.update();
|
||||
markers_manager.update();
|
||||
if (taseditor_config.bind_markers)
|
||||
selection.must_find_current_marker = playback.must_find_current_marker = true;
|
||||
greenzone.InvalidateAndCheck(history.RegisterChanges(MODTYPE_PASTEINSERT, *current_selection_begin));
|
||||
greenzone.InvalidateAndCheck(history.RegisterPasteInsert(*current_selection_begin, inserted_set));
|
||||
// flash list header columns that were changed during paste
|
||||
for (int joy = 0; joy < num_joypads; ++joy)
|
||||
{
|
||||
|
|
|
@ -49,6 +49,7 @@ TASEDITOR_CONFIG::TASEDITOR_CONFIG()
|
|||
findnote_search_up = false;
|
||||
enable_auto_function = true;
|
||||
silent_autosave = true;
|
||||
tooltips = true;
|
||||
// empty name
|
||||
last_author[0] = 0;
|
||||
|
||||
|
|
|
@ -1,4 +1,6 @@
|
|||
//Specification file for TASEDITOR_CONFIG class
|
||||
// --------------------------------------------------------
|
||||
|
||||
#define GREENZONE_CAPACITY_MIN 1
|
||||
#define GREENZONE_CAPACITY_MAX 50000
|
||||
#define GREENZONE_CAPACITY_DEFAULT 10000
|
||||
|
@ -63,6 +65,7 @@ public:
|
|||
bool findnote_search_up;
|
||||
bool enable_auto_function;
|
||||
bool silent_autosave;
|
||||
bool tooltips;
|
||||
char last_author[AUTHOR_MAX_LEN];
|
||||
|
||||
private:
|
||||
|
|
|
@ -7,7 +7,6 @@
|
|||
|
||||
extern int joysticks_per_frame[NUM_SUPPORTED_INPUT_TYPES];
|
||||
extern char buttonNames[NUM_JOYPAD_BUTTONS][2];
|
||||
extern void ColumnSet(int column);
|
||||
|
||||
extern TASEDITOR_CONFIG taseditor_config;
|
||||
extern TASEDITOR_WINDOW taseditor_window;
|
||||
|
@ -15,8 +14,8 @@ extern BOOKMARKS bookmarks;
|
|||
extern PLAYBACK playback;
|
||||
extern RECORDER recorder;
|
||||
extern GREENZONE greenzone;
|
||||
extern INPUT_HISTORY history;
|
||||
extern MARKERS current_markers;
|
||||
extern HISTORY history;
|
||||
extern MARKERS_MANAGER markers_manager;
|
||||
extern TASEDITOR_SELECTION selection;
|
||||
|
||||
extern int GetInputType(MovieData& md);
|
||||
|
@ -26,13 +25,12 @@ LRESULT APIENTRY ListWndProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam);
|
|||
WNDPROC hwndList_oldWndProc = 0, hwndHeader_oldWndproc = 0;
|
||||
|
||||
// resources
|
||||
char list_save_id[LIST_ID_LEN] = "LIST";
|
||||
char list_skipsave_id[LIST_ID_LEN] = "LISX";
|
||||
COLORREF hot_changes_colors[16] = { 0x0, 0x5c4c44, 0x854604, 0xab2500, 0xc20006, 0xd6006f, 0xd40091, 0xba00a4, 0x9500ba, 0x7a00cc, 0x5800d4, 0x0045e2, 0x0063ea, 0x0079f4, 0x0092fa, 0x00aaff };
|
||||
//COLORREF hot_changes_colors[16] = { 0x0, 0x661212, 0x842B4E, 0x652C73, 0x48247D, 0x383596, 0x2947AE, 0x1E53C1, 0x135DD2, 0x116EDA, 0x107EE3, 0x0F8EEB, 0x209FF4, 0x3DB1FD, 0x51C2FF, 0x4DCDFF };
|
||||
COLORREF header_lights_colors[11] = { 0x0, 0x006311, 0x008500, 0x1dad00, 0x46d100, 0x6ee300, 0x97e800, 0xb8f000, 0xdaf700, 0xffff7e, 0xffffb7 };
|
||||
|
||||
char list_save_id[LIST_ID_LEN] = "LIST";
|
||||
char list_skipsave_id[LIST_ID_LEN] = "LISX";
|
||||
|
||||
TASEDITOR_LIST::TASEDITOR_LIST()
|
||||
{
|
||||
}
|
||||
|
@ -68,7 +66,7 @@ void TASEDITOR_LIST::init()
|
|||
"Arial"); /*font name*/
|
||||
bg_brush = CreateSolidBrush(GetSysColor(COLOR_BTNFACE));
|
||||
|
||||
header_colors.resize(MAX_NUM_COLUMNS);
|
||||
header_colors.resize(TOTAL_COLUMNS);
|
||||
|
||||
hwndList = GetDlgItem(taseditor_window.hwndTasEditor, IDC_LIST1);
|
||||
// prepare the main listview
|
||||
|
@ -145,6 +143,9 @@ void TASEDITOR_LIST::init()
|
|||
bmp = LoadBitmap(fceu_hInstance, MAKEINTRESOURCE(IDB_TE_ARROW));
|
||||
ImageList_AddMasked(himglist, bmp, 0xFFFFFF);
|
||||
DeleteObject(bmp);
|
||||
bmp = LoadBitmap(fceu_hInstance, MAKEINTRESOURCE(IDB_TE_GREEN_ARROW));
|
||||
ImageList_AddMasked(himglist, bmp, 0xFFFFFF);
|
||||
DeleteObject(bmp);
|
||||
ListView_SetImageList(hwndList, himglist, LVSIL_SMALL);
|
||||
// setup 0th column
|
||||
LVCOLUMN lvc;
|
||||
|
@ -193,8 +194,8 @@ void TASEDITOR_LIST::reset()
|
|||
// delete all columns except 0th
|
||||
while (ListView_DeleteColumn(hwndList, 1)) {}
|
||||
// setup columns
|
||||
LVCOLUMN lvc;
|
||||
num_columns = 1;
|
||||
LVCOLUMN lvc;
|
||||
// frame number column
|
||||
lvc.mask = LVCF_WIDTH | LVCF_TEXT | LVCF_FMT;
|
||||
lvc.fmt = LVCFMT_CENTER;
|
||||
|
@ -427,7 +428,7 @@ void TASEDITOR_LIST::FollowSelection()
|
|||
}
|
||||
void TASEDITOR_LIST::FollowPauseframe()
|
||||
{
|
||||
int jump_frame = playback.GetPauseFrame();
|
||||
int jump_frame = playback.pause_frame;
|
||||
if (jump_frame >= 0)
|
||||
{
|
||||
// center list at jump_frame
|
||||
|
@ -474,6 +475,8 @@ void TASEDITOR_LIST::GetDispInfo(NMLVDISPINFO* nmlvDispInfo)
|
|||
{
|
||||
if (item.iItem == currFrameCounter)
|
||||
item.iImage = ARROW_IMAGE_ID;
|
||||
else if (item.iItem == playback.lost_position_frame-1)
|
||||
item.iImage = GREEN_ARROW_IMAGE_ID;
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
@ -538,7 +541,7 @@ LONG TASEDITOR_LIST::CustomDraw(NMLVCUSTOMDRAW* msg)
|
|||
if(cell_x == COLUMN_FRAMENUM || cell_x == COLUMN_FRAMENUM2)
|
||||
{
|
||||
// font
|
||||
if(current_markers.GetMarker(cell_y))
|
||||
if(markers_manager.GetMarker(cell_y))
|
||||
SelectObject(msg->nmcd.hdc, hMainListSelectFont);
|
||||
else
|
||||
SelectObject(msg->nmcd.hdc, hMainListFont);
|
||||
|
@ -547,24 +550,24 @@ LONG TASEDITOR_LIST::CustomDraw(NMLVCUSTOMDRAW* msg)
|
|||
if (cell_y == history.GetUndoHint())
|
||||
{
|
||||
// undo hint here
|
||||
if (taseditor_config.show_markers && current_markers.GetMarker(cell_y))
|
||||
if (taseditor_config.show_markers && markers_manager.GetMarker(cell_y))
|
||||
{
|
||||
msg->clrTextBk = (taseditor_config.bind_markers) ? BINDMARKED_UNDOHINT_FRAMENUM_COLOR : MARKED_UNDOHINT_FRAMENUM_COLOR;
|
||||
} else
|
||||
{
|
||||
msg->clrTextBk = UNDOHINT_FRAMENUM_COLOR;
|
||||
}
|
||||
} else if (cell_y == currFrameCounter || cell_y == (playback.GetPauseFrame() - 1))
|
||||
} else if (cell_y == currFrameCounter || cell_y == (playback.GetFlashingPauseFrame() - 1))
|
||||
{
|
||||
// current frame
|
||||
if (taseditor_config.show_markers && current_markers.GetMarker(cell_y))
|
||||
if (taseditor_config.show_markers && markers_manager.GetMarker(cell_y))
|
||||
{
|
||||
msg->clrTextBk = (taseditor_config.bind_markers) ? CUR_BINDMARKED_FRAMENUM_COLOR : CUR_MARKED_FRAMENUM_COLOR;
|
||||
} else
|
||||
{
|
||||
msg->clrTextBk = CUR_FRAMENUM_COLOR;
|
||||
}
|
||||
} else if (taseditor_config.show_markers && current_markers.GetMarker(cell_y))
|
||||
} else if (taseditor_config.show_markers && markers_manager.GetMarker(cell_y))
|
||||
{
|
||||
// marked frame
|
||||
msg->clrTextBk = (taseditor_config.bind_markers) ? BINDMARKED_FRAMENUM_COLOR : MARKED_FRAMENUM_COLOR;
|
||||
|
@ -600,7 +603,7 @@ LONG TASEDITOR_LIST::CustomDraw(NMLVCUSTOMDRAW* msg)
|
|||
{
|
||||
// undo hint here
|
||||
msg->clrTextBk = UNDOHINT_INPUT_COLOR1;
|
||||
} else if (cell_y == currFrameCounter || cell_y == (playback.GetPauseFrame() - 1))
|
||||
} else if (cell_y == currFrameCounter || cell_y == (playback.GetFlashingPauseFrame() - 1))
|
||||
{
|
||||
// current frame
|
||||
msg->clrTextBk = CUR_INPUT_COLOR1;
|
||||
|
@ -633,7 +636,7 @@ LONG TASEDITOR_LIST::CustomDraw(NMLVCUSTOMDRAW* msg)
|
|||
{
|
||||
// undo hint here
|
||||
msg->clrTextBk = UNDOHINT_INPUT_COLOR2;
|
||||
} else if (cell_y == currFrameCounter || cell_y == (playback.GetPauseFrame() - 1))
|
||||
} else if (cell_y == currFrameCounter || cell_y == (playback.GetFlashingPauseFrame() - 1))
|
||||
{
|
||||
// current frame
|
||||
msg->clrTextBk = CUR_INPUT_COLOR2;
|
||||
|
@ -684,9 +687,191 @@ LONG TASEDITOR_LIST::HeaderCustomDraw(NMLVCUSTOMDRAW* msg)
|
|||
return CDRF_DODEFAULT;
|
||||
}
|
||||
}
|
||||
|
||||
void TASEDITOR_LIST::SingleClick(LPNMITEMACTIVATE info)
|
||||
{
|
||||
int row_index = info->iItem;
|
||||
if(row_index == -1) return;
|
||||
int column_index = info->iSubItem;
|
||||
|
||||
if(column_index == COLUMN_ICONS)
|
||||
{
|
||||
// click on the "icons" column - jump to the frame
|
||||
selection.ClearSelection();
|
||||
playback.jump(row_index);
|
||||
} else if(column_index == COLUMN_FRAMENUM || column_index == COLUMN_FRAMENUM2)
|
||||
{
|
||||
// click on the "frame number" column - set marker if clicked with Alt
|
||||
if (info->uKeyFlags & LVKF_ALT)
|
||||
{
|
||||
// reverse MARKER_FLAG_BIT in pointed frame
|
||||
markers_manager.ToggleMarker(row_index);
|
||||
selection.must_find_current_marker = playback.must_find_current_marker = true;
|
||||
if (markers_manager.GetMarker(row_index))
|
||||
history.RegisterMarkersChange(MODTYPE_MARKER_SET, row_index);
|
||||
else
|
||||
history.RegisterMarkersChange(MODTYPE_MARKER_UNSET, row_index);
|
||||
RedrawRow(row_index);
|
||||
}
|
||||
}
|
||||
else if(column_index >= COLUMN_JOYPAD1_A && column_index <= COLUMN_JOYPAD4_R)
|
||||
{
|
||||
ToggleJoypadBit(column_index, row_index, info->uKeyFlags);
|
||||
}
|
||||
}
|
||||
void TASEDITOR_LIST::DoubleClick(LPNMITEMACTIVATE info)
|
||||
{
|
||||
int row_index = info->iItem;
|
||||
if(row_index == -1) return;
|
||||
int column_index = info->iSubItem;
|
||||
|
||||
if(column_index == COLUMN_ICONS || column_index == COLUMN_FRAMENUM || column_index == COLUMN_FRAMENUM2)
|
||||
{
|
||||
// double click sends playback to the frame
|
||||
selection.ClearSelection();
|
||||
playback.jump(row_index);
|
||||
} else if(column_index >= COLUMN_JOYPAD1_A && column_index <= COLUMN_JOYPAD4_R)
|
||||
{
|
||||
ToggleJoypadBit(column_index, row_index, info->uKeyFlags);
|
||||
}
|
||||
}
|
||||
|
||||
void TASEDITOR_LIST::ToggleJoypadBit(int column_index, int row_index, UINT KeyFlags)
|
||||
{
|
||||
int joy = (column_index - COLUMN_JOYPAD1_A) / NUM_JOYPAD_BUTTONS;
|
||||
int bit = (column_index - COLUMN_JOYPAD1_A) % NUM_JOYPAD_BUTTONS;
|
||||
if (KeyFlags & (LVKF_SHIFT|LVKF_CONTROL))
|
||||
{
|
||||
// update multiple rows, using last row index as a flag to decide operation
|
||||
SelectionFrames* current_selection = selection.MakeStrobe();
|
||||
SelectionFrames::iterator current_selection_end(current_selection->end());
|
||||
if (currMovieData.records[row_index].checkBit(joy, bit))
|
||||
{
|
||||
// clear range
|
||||
for(SelectionFrames::iterator it(current_selection->begin()); it != current_selection_end; it++)
|
||||
{
|
||||
currMovieData.records[*it].clearBit(joy, bit);
|
||||
}
|
||||
greenzone.InvalidateAndCheck(history.RegisterChanges(MODTYPE_UNSET, *current_selection->begin(), *current_selection->rbegin()));
|
||||
} else
|
||||
{
|
||||
// set range
|
||||
for(SelectionFrames::iterator it(current_selection->begin()); it != current_selection_end; it++)
|
||||
{
|
||||
currMovieData.records[*it].setBit(joy, bit);
|
||||
}
|
||||
greenzone.InvalidateAndCheck(history.RegisterChanges(MODTYPE_SET, *current_selection->begin(), *current_selection->rbegin()));
|
||||
}
|
||||
} else
|
||||
{
|
||||
// update one row
|
||||
currMovieData.records[row_index].toggleBit(joy, bit);
|
||||
if (currMovieData.records[row_index].checkBit(joy, bit))
|
||||
greenzone.InvalidateAndCheck(history.RegisterChanges(MODTYPE_SET, row_index, row_index));
|
||||
else
|
||||
greenzone.InvalidateAndCheck(history.RegisterChanges(MODTYPE_UNSET, row_index, row_index));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void TASEDITOR_LIST::ColumnSet(int column)
|
||||
{
|
||||
if (column == COLUMN_FRAMENUM || column == COLUMN_FRAMENUM2)
|
||||
FrameColumnSet();
|
||||
else
|
||||
InputColumnSet(column);
|
||||
}
|
||||
void TASEDITOR_LIST::FrameColumnSet()
|
||||
{
|
||||
SelectionFrames* current_selection = selection.MakeStrobe();
|
||||
if (current_selection->size() == 0) return;
|
||||
SelectionFrames::iterator current_selection_begin(current_selection->begin());
|
||||
SelectionFrames::iterator current_selection_end(current_selection->end());
|
||||
|
||||
// inspect the selected frames, if they are all set, then unset all, else set all
|
||||
bool unset_found = false, changes_made = false;
|
||||
for(SelectionFrames::iterator it(current_selection_begin); it != current_selection_end; it++)
|
||||
{
|
||||
if(!markers_manager.GetMarker(*it))
|
||||
{
|
||||
unset_found = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (unset_found)
|
||||
{
|
||||
// set all
|
||||
for(SelectionFrames::iterator it(current_selection_begin); it != current_selection_end; it++)
|
||||
{
|
||||
if(!markers_manager.GetMarker(*it))
|
||||
{
|
||||
if (markers_manager.SetMarker(*it))
|
||||
{
|
||||
changes_made = true;
|
||||
RedrawRow(*it);
|
||||
}
|
||||
}
|
||||
}
|
||||
if (changes_made)
|
||||
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_manager.GetMarker(*it))
|
||||
{
|
||||
markers_manager.ClearMarker(*it);
|
||||
changes_made = true;
|
||||
RedrawRow(*it);
|
||||
}
|
||||
}
|
||||
if (changes_made)
|
||||
history.RegisterMarkersChange(MODTYPE_MARKER_UNSET, *current_selection_begin, *current_selection->rbegin());
|
||||
}
|
||||
if (changes_made)
|
||||
{
|
||||
selection.must_find_current_marker = playback.must_find_current_marker = true;
|
||||
SetHeaderColumnLight(COLUMN_FRAMENUM, HEADER_LIGHT_MAX);
|
||||
}
|
||||
}
|
||||
void TASEDITOR_LIST::InputColumnSet(int column)
|
||||
{
|
||||
int joy = (column - COLUMN_JOYPAD1_A) / NUM_JOYPAD_BUTTONS;
|
||||
if (joy < 0 || joy >= joysticks_per_frame[GetInputType(currMovieData)]) return;
|
||||
int button = (column - COLUMN_JOYPAD1_A) % NUM_JOYPAD_BUTTONS;
|
||||
|
||||
SelectionFrames* current_selection = selection.MakeStrobe();
|
||||
if (current_selection->size() == 0) return;
|
||||
SelectionFrames::iterator current_selection_begin(current_selection->begin());
|
||||
SelectionFrames::iterator current_selection_end(current_selection->end());
|
||||
|
||||
//inspect the selected frames, if they are all set, then unset all, else set all
|
||||
bool newValue = false;
|
||||
for(SelectionFrames::iterator it(current_selection_begin); it != current_selection_end; it++)
|
||||
{
|
||||
if(!(currMovieData.records[*it].checkBit(joy,button)))
|
||||
{
|
||||
newValue = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
// apply newValue
|
||||
for(SelectionFrames::iterator it(current_selection_begin); it != current_selection_end; it++)
|
||||
currMovieData.records[*it].setBitValue(joy,button,newValue);
|
||||
if (newValue)
|
||||
{
|
||||
greenzone.InvalidateAndCheck(history.RegisterChanges(MODTYPE_SET, *current_selection_begin, *current_selection->rbegin()));
|
||||
} else
|
||||
{
|
||||
greenzone.InvalidateAndCheck(history.RegisterChanges(MODTYPE_UNSET, *current_selection_begin, *current_selection->rbegin()));
|
||||
}
|
||||
SetHeaderColumnLight(column, HEADER_LIGHT_MAX);
|
||||
}
|
||||
// -------------------------------------------------------------------------
|
||||
LRESULT APIENTRY HeaderWndProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam)
|
||||
{
|
||||
extern TASEDITOR_LIST list;
|
||||
switch(msg)
|
||||
{
|
||||
case WM_SETCURSOR:
|
||||
|
@ -702,7 +887,7 @@ LRESULT APIENTRY HeaderWndProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam
|
|||
info.pt.y = GET_Y_LPARAM(lParam);
|
||||
SendMessage(hWnd,HDM_HITTEST,0,(LPARAM)&info);
|
||||
if(info.iItem >= COLUMN_FRAMENUM && info.iItem <= COLUMN_FRAMENUM2)
|
||||
ColumnSet(info.iItem);
|
||||
list.ColumnSet(info.iItem);
|
||||
}
|
||||
}
|
||||
return true;
|
||||
|
|
|
@ -51,7 +51,7 @@ enum
|
|||
COLUMN_JOYPAD4_R,
|
||||
COLUMN_FRAMENUM2,
|
||||
|
||||
MAX_NUM_COLUMNS
|
||||
TOTAL_COLUMNS
|
||||
};
|
||||
|
||||
// when there's too many button columns, there's need for 2nd Frame# column at the end
|
||||
|
@ -59,6 +59,7 @@ enum
|
|||
|
||||
#define DIGITS_IN_FRAMENUM 7
|
||||
#define ARROW_IMAGE_ID 20
|
||||
#define GREEN_ARROW_IMAGE_ID 21
|
||||
|
||||
#define COLUMN_ICONS_WIDTH 13
|
||||
#define COLUMN_FRAMENUM_WIDTH 75
|
||||
|
@ -135,6 +136,15 @@ public:
|
|||
LONG CustomDraw(NMLVCUSTOMDRAW* msg);
|
||||
LONG HeaderCustomDraw(NMLVCUSTOMDRAW* msg);
|
||||
|
||||
void SingleClick(LPNMITEMACTIVATE info);
|
||||
void DoubleClick(LPNMITEMACTIVATE info);
|
||||
|
||||
void ToggleJoypadBit(int column_index, int row_index, UINT KeyFlags);
|
||||
void ColumnSet(int column);
|
||||
void InputColumnSet(int column);
|
||||
void FrameColumnSet();
|
||||
|
||||
|
||||
HWND hwndList, hwndHeader;
|
||||
|
||||
// GDI stuff
|
||||
|
|
|
@ -1,12 +1,14 @@
|
|||
//Implementation file of TASEDITOR_LUA class
|
||||
#include "taseditor_project.h"
|
||||
|
||||
extern TASEDITOR_CONFIG taseditor_config;
|
||||
extern TASEDITOR_WINDOW taseditor_window;
|
||||
extern INPUT_HISTORY history;
|
||||
extern MARKERS current_markers;
|
||||
extern HISTORY history;
|
||||
extern MARKERS_MANAGER markers_manager;
|
||||
extern BOOKMARKS bookmarks;
|
||||
extern RECORDER recorder;
|
||||
extern PLAYBACK playback;
|
||||
extern GREENZONE greenzone;
|
||||
extern TASEDITOR_LIST list;
|
||||
extern TASEDITOR_SELECTION selection;
|
||||
|
||||
|
@ -18,6 +20,7 @@ TASEDITOR_LUA::TASEDITOR_LUA()
|
|||
|
||||
void TASEDITOR_LUA::init()
|
||||
{
|
||||
pending_changes.resize(0);
|
||||
hwndRunFunction = GetDlgItem(taseditor_window.hwndTasEditor, TASEDITOR_RUN_MANUAL);
|
||||
TaseditorUpdateManualFunctionStatus();
|
||||
reset();
|
||||
|
@ -39,6 +42,39 @@ void TASEDITOR_LUA::DisableRunFunction()
|
|||
{
|
||||
EnableWindow(hwndRunFunction, false);
|
||||
}
|
||||
|
||||
void TASEDITOR_LUA::InsertDelete_rows_to_Snaphot(SNAPSHOT& snapshot)
|
||||
{
|
||||
int size = pending_changes.size();
|
||||
if (size)
|
||||
{
|
||||
// apply changes to given snapshot (only insertion/deletion)
|
||||
for (int i = 0; i < size; ++i)
|
||||
{
|
||||
if (pending_changes[i].frame >= snapshot.size)
|
||||
// expand snapshot to fit the frame
|
||||
snapshot.insertFrames(-1, 1 + pending_changes[i].frame - snapshot.size);
|
||||
switch (pending_changes[i].type)
|
||||
{
|
||||
case LUA_CHANGE_TYPE_INSERTFRAMES:
|
||||
{
|
||||
snapshot.insertFrames(pending_changes[i].frame, pending_changes[i].data);
|
||||
break;
|
||||
}
|
||||
case LUA_CHANGE_TYPE_DELETEFRAMES:
|
||||
{
|
||||
for (int t = pending_changes[i].data; t > 0; t--)
|
||||
{
|
||||
if (pending_changes[i].frame < snapshot.size)
|
||||
snapshot.eraseFrame(pending_changes[i].frame);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// --------------------------------------------------------------------------------
|
||||
// Lua functions of taseditor library
|
||||
|
||||
|
@ -52,7 +88,7 @@ bool TASEDITOR_LUA::engaged()
|
|||
bool TASEDITOR_LUA::markedframe(int frame)
|
||||
{
|
||||
if (FCEUMOV_Mode(MOVIEMODE_TASEDITOR))
|
||||
return current_markers.GetMarker(frame) != 0;
|
||||
return markers_manager.GetMarker(frame) != 0;
|
||||
else
|
||||
return false;
|
||||
}
|
||||
|
@ -61,7 +97,7 @@ bool TASEDITOR_LUA::markedframe(int frame)
|
|||
int TASEDITOR_LUA::getmarker(int frame)
|
||||
{
|
||||
if (FCEUMOV_Mode(MOVIEMODE_TASEDITOR))
|
||||
return current_markers.GetMarkerUp(frame);
|
||||
return markers_manager.GetMarkerUp(frame);
|
||||
else
|
||||
return -1;
|
||||
}
|
||||
|
@ -71,10 +107,10 @@ int TASEDITOR_LUA::setmarker(int frame)
|
|||
{
|
||||
if (FCEUMOV_Mode(MOVIEMODE_TASEDITOR))
|
||||
{
|
||||
int marker_id = current_markers.GetMarker(frame);
|
||||
int marker_id = markers_manager.GetMarker(frame);
|
||||
if(!marker_id)
|
||||
{
|
||||
marker_id = current_markers.SetMarker(frame);
|
||||
marker_id = markers_manager.SetMarker(frame);
|
||||
if (marker_id)
|
||||
{
|
||||
// new marker was created - register changes in TAS Editor
|
||||
|
@ -93,9 +129,9 @@ void TASEDITOR_LUA::clearmarker(int frame)
|
|||
{
|
||||
if (FCEUMOV_Mode(MOVIEMODE_TASEDITOR))
|
||||
{
|
||||
if (current_markers.GetMarker(frame))
|
||||
if (markers_manager.GetMarker(frame))
|
||||
{
|
||||
current_markers.ClearMarker(frame);
|
||||
markers_manager.ClearMarker(frame);
|
||||
// marker was deleted - register changes in TAS Editor
|
||||
history.RegisterMarkersChange(MODTYPE_LUA_MARKER_UNSET, frame);
|
||||
selection.must_find_current_marker = playback.must_find_current_marker = true;
|
||||
|
@ -108,8 +144,9 @@ void TASEDITOR_LUA::clearmarker(int frame)
|
|||
const char* TASEDITOR_LUA::getnote(int index)
|
||||
{
|
||||
if (FCEUMOV_Mode(MOVIEMODE_TASEDITOR))
|
||||
return current_markers.GetNote(index).c_str();
|
||||
else
|
||||
{
|
||||
return strdup(markers_manager.GetNote(index).c_str());
|
||||
} else
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
@ -121,11 +158,11 @@ void TASEDITOR_LUA::setnote(int index, const char* newtext)
|
|||
// rename only if newtext is different from old text
|
||||
char text[MAX_NOTE_LEN];
|
||||
strncpy(text, newtext, MAX_NOTE_LEN - 1);
|
||||
if (strcmp(current_markers.GetNote(index).c_str(), text))
|
||||
if (strcmp(markers_manager.GetNote(index).c_str(), text))
|
||||
{
|
||||
// text differs from old note - rename
|
||||
current_markers.SetNote(index, text);
|
||||
history.RegisterMarkersChange(MODTYPE_LUA_MARKER_RENAME, current_markers.GetMarkerFrame(index));
|
||||
markers_manager.SetNote(index, text);
|
||||
history.RegisterMarkersChange(MODTYPE_LUA_MARKER_RENAME, markers_manager.GetMarkerFrame(index));
|
||||
selection.must_find_current_marker = playback.must_find_current_marker = true;
|
||||
}
|
||||
}
|
||||
|
@ -149,6 +186,15 @@ const char* TASEDITOR_LUA::getrecordermode()
|
|||
return NULL;
|
||||
}
|
||||
|
||||
// int taseditor.getlostplayback()
|
||||
int TASEDITOR_LUA::getlostplayback()
|
||||
{
|
||||
if (FCEUMOV_Mode(MOVIEMODE_TASEDITOR))
|
||||
return playback.lost_position_frame - 1;
|
||||
else
|
||||
return -1;
|
||||
}
|
||||
|
||||
// int taseditor.getplaybacktarget()
|
||||
int TASEDITOR_LUA::getplaybacktarget()
|
||||
{
|
||||
|
@ -158,7 +204,7 @@ int TASEDITOR_LUA::getplaybacktarget()
|
|||
return -1;
|
||||
}
|
||||
|
||||
// taseditor.setplayback()
|
||||
// taseditor.setplayback(int frame)
|
||||
void TASEDITOR_LUA::setplayback(int frame)
|
||||
{
|
||||
if (FCEUMOV_Mode(MOVIEMODE_TASEDITOR))
|
||||
|
@ -172,6 +218,220 @@ void TASEDITOR_LUA::stopseeking()
|
|||
playback.SeekingStop();
|
||||
}
|
||||
|
||||
// table taseditor.getselection()
|
||||
void TASEDITOR_LUA::getselection(std::vector<int>& placeholder)
|
||||
{
|
||||
if (FCEUMOV_Mode(MOVIEMODE_TASEDITOR))
|
||||
{
|
||||
SelectionFrames* current_selection = selection.MakeStrobe();
|
||||
int frames = current_selection->size();
|
||||
if (!frames) return;
|
||||
|
||||
placeholder.resize(frames);
|
||||
SelectionFrames::iterator current_selection_end(current_selection->end());
|
||||
int i = 0;
|
||||
for(SelectionFrames::iterator it(current_selection->begin()); it != current_selection_end; ++it)
|
||||
placeholder[i++] = *it;
|
||||
}
|
||||
}
|
||||
|
||||
// taseditor.setselection(table new_set)
|
||||
void TASEDITOR_LUA::setselection(std::vector<int>& new_set)
|
||||
{
|
||||
if (FCEUMOV_Mode(MOVIEMODE_TASEDITOR))
|
||||
{
|
||||
selection.ClearSelection();
|
||||
for (int i = new_set.size() - 1; i >= 0; i--)
|
||||
selection.SetRowSelection(new_set[i]);
|
||||
}
|
||||
}
|
||||
|
||||
// int taseditor.getinput(int frame, int joypad)
|
||||
int TASEDITOR_LUA::getinput(int frame, int joypad)
|
||||
{
|
||||
if (FCEUMOV_Mode(MOVIEMODE_TASEDITOR))
|
||||
{
|
||||
if (frame < 0) return -1;
|
||||
if (frame >= currMovieData.getNumRecords()) return 0;
|
||||
switch (joypad)
|
||||
{
|
||||
case LUA_JOYPAD_COMMANDS:
|
||||
return currMovieData.records[frame].commands;
|
||||
case LUA_JOYPAD_1P:
|
||||
return currMovieData.records[frame].joysticks[0];
|
||||
case LUA_JOYPAD_2P:
|
||||
return currMovieData.records[frame].joysticks[1];
|
||||
case LUA_JOYPAD_3P:
|
||||
return currMovieData.records[frame].joysticks[2];
|
||||
case LUA_JOYPAD_4P:
|
||||
return currMovieData.records[frame].joysticks[3];
|
||||
}
|
||||
return -1;
|
||||
} else
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
// taseditor.submitinputchange(int frame, int joypad, int input)
|
||||
void TASEDITOR_LUA::submitinputchange(int frame, int joypad, int input)
|
||||
{
|
||||
if (FCEUMOV_Mode(MOVIEMODE_TASEDITOR))
|
||||
{
|
||||
if (frame >= 0)
|
||||
{
|
||||
if (joypad == LUA_JOYPAD_COMMANDS || joypad == LUA_JOYPAD_1P || joypad == LUA_JOYPAD_2P || joypad == LUA_JOYPAD_3P || joypad == LUA_JOYPAD_4P)
|
||||
{
|
||||
PENDING_CHANGES new_change;
|
||||
new_change.type = LUA_CHANGE_TYPE_INPUTCHANGE;
|
||||
new_change.frame = frame;
|
||||
new_change.joypad = joypad;
|
||||
new_change.data = input;
|
||||
pending_changes.push_back(new_change);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void TASEDITOR_LUA::submitinsertframes(int frame, int number)
|
||||
{
|
||||
if (FCEUMOV_Mode(MOVIEMODE_TASEDITOR))
|
||||
{
|
||||
if (frame >= 0 && number > 0)
|
||||
{
|
||||
PENDING_CHANGES new_change;
|
||||
new_change.type = LUA_CHANGE_TYPE_INSERTFRAMES;
|
||||
new_change.frame = frame;
|
||||
new_change.joypad = 0; // doesn't matter in TAS Editor v1.0, whole frame will be inserted
|
||||
new_change.data = number;
|
||||
pending_changes.push_back(new_change);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void TASEDITOR_LUA::submitdeleteframes(int frame, int number)
|
||||
{
|
||||
if (FCEUMOV_Mode(MOVIEMODE_TASEDITOR))
|
||||
{
|
||||
if (frame >= 0 && number > 0)
|
||||
{
|
||||
PENDING_CHANGES new_change;
|
||||
new_change.type = LUA_CHANGE_TYPE_DELETEFRAMES;
|
||||
new_change.frame = frame;
|
||||
new_change.joypad = 0; // doesn't matter in TAS Editor v1.0, whole frame will be deleted
|
||||
new_change.data = number;
|
||||
pending_changes.push_back(new_change);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// int taseditor.applyinputchanges([string name])
|
||||
int TASEDITOR_LUA::applyinputchanges(const char* name)
|
||||
{
|
||||
if (FCEUMOV_Mode(MOVIEMODE_TASEDITOR))
|
||||
{
|
||||
int size = pending_changes.size();
|
||||
int start_index = currMovieData.getNumRecords() - 1;
|
||||
bool InsertionDeletion_was_made = false;
|
||||
if (size)
|
||||
{
|
||||
// apply changes to current movie data
|
||||
for (int i = 0; i < size; ++i)
|
||||
{
|
||||
if (pending_changes[i].frame < start_index)
|
||||
start_index = pending_changes[i].frame;
|
||||
if (pending_changes[i].frame >= (int)currMovieData.getNumRecords())
|
||||
{
|
||||
// expand movie to fit the frame
|
||||
currMovieData.insertEmpty(-1, 1 + pending_changes[i].frame - currMovieData.getNumRecords());
|
||||
markers_manager.update();
|
||||
InsertionDeletion_was_made = true;
|
||||
}
|
||||
switch (pending_changes[i].type)
|
||||
{
|
||||
case LUA_CHANGE_TYPE_INPUTCHANGE:
|
||||
{
|
||||
switch (pending_changes[i].joypad)
|
||||
{
|
||||
case LUA_JOYPAD_COMMANDS:
|
||||
currMovieData.records[pending_changes[i].frame].commands = pending_changes[i].data;
|
||||
break;
|
||||
case LUA_JOYPAD_1P:
|
||||
currMovieData.records[pending_changes[i].frame].joysticks[0] = pending_changes[i].data;
|
||||
break;
|
||||
case LUA_JOYPAD_2P:
|
||||
currMovieData.records[pending_changes[i].frame].joysticks[1] = pending_changes[i].data;
|
||||
break;
|
||||
case LUA_JOYPAD_3P:
|
||||
currMovieData.records[pending_changes[i].frame].joysticks[2] = pending_changes[i].data;
|
||||
break;
|
||||
case LUA_JOYPAD_4P:
|
||||
currMovieData.records[pending_changes[i].frame].joysticks[3] = pending_changes[i].data;
|
||||
break;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case LUA_CHANGE_TYPE_INSERTFRAMES:
|
||||
{
|
||||
InsertionDeletion_was_made = true;
|
||||
currMovieData.insertEmpty(pending_changes[i].frame, pending_changes[i].data);
|
||||
if (taseditor_config.bind_markers)
|
||||
markers_manager.insertEmpty(pending_changes[i].frame, pending_changes[i].data);
|
||||
break;
|
||||
}
|
||||
case LUA_CHANGE_TYPE_DELETEFRAMES:
|
||||
{
|
||||
InsertionDeletion_was_made = true;
|
||||
for (int t = pending_changes[i].data; t > 0; t--)
|
||||
{
|
||||
if (pending_changes[i].frame < (int)currMovieData.getNumRecords())
|
||||
currMovieData.records.erase(currMovieData.records.begin() + pending_changes[i].frame);
|
||||
if (taseditor_config.bind_markers)
|
||||
markers_manager.EraseMarker(pending_changes[i].frame);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (taseditor_config.bind_markers)
|
||||
selection.must_find_current_marker = playback.must_find_current_marker = true;
|
||||
// check if user deleted all frames
|
||||
if (!currMovieData.getNumRecords())
|
||||
playback.StartFromZero();
|
||||
// reduce list
|
||||
list.update();
|
||||
// check actual changes
|
||||
int result = history.RegisterLuaChanges(name, start_index, InsertionDeletion_was_made);
|
||||
if (result >= 0)
|
||||
{
|
||||
greenzone.InvalidateAndCheck(result);
|
||||
} else if (greenzone.greenZoneCount >= currMovieData.getNumRecords())
|
||||
{
|
||||
greenzone.InvalidateAndCheck(currMovieData.getNumRecords()-1);
|
||||
} else list.RedrawList();
|
||||
|
||||
pending_changes.resize(0);
|
||||
return result;
|
||||
} else
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
} else
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
// taseditor.clearinputchanges()
|
||||
void TASEDITOR_LUA::clearinputchanges()
|
||||
{
|
||||
if (FCEUMOV_Mode(MOVIEMODE_TASEDITOR))
|
||||
{
|
||||
pending_changes.resize(0);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
|
|
@ -1,4 +1,29 @@
|
|||
//Specification file for TASEDITOR_LUA class
|
||||
#define LUACHANGES_NAME_MAX_LEN 80 // the name should not be longer than 80 letters
|
||||
|
||||
struct PENDING_CHANGES
|
||||
{
|
||||
uint8 type;
|
||||
int frame;
|
||||
uint8 joypad;
|
||||
int data;
|
||||
};
|
||||
|
||||
enum
|
||||
{
|
||||
LUA_CHANGE_TYPE_INPUTCHANGE = 0,
|
||||
LUA_CHANGE_TYPE_INSERTFRAMES = 1,
|
||||
LUA_CHANGE_TYPE_DELETEFRAMES = 2,
|
||||
};
|
||||
|
||||
enum
|
||||
{
|
||||
LUA_JOYPAD_COMMANDS = 0,
|
||||
LUA_JOYPAD_1P = 1,
|
||||
LUA_JOYPAD_2P = 2,
|
||||
LUA_JOYPAD_3P = 3,
|
||||
LUA_JOYPAD_4P = 4,
|
||||
};
|
||||
|
||||
class TASEDITOR_LUA
|
||||
{
|
||||
|
@ -11,6 +36,8 @@ public:
|
|||
void EnableRunFunction();
|
||||
void DisableRunFunction();
|
||||
|
||||
void InsertDelete_rows_to_Snaphot(SNAPSHOT& snapshot);
|
||||
|
||||
// Taseditor Lua library
|
||||
bool engaged();
|
||||
bool markedframe(int frame);
|
||||
|
@ -21,12 +48,22 @@ public:
|
|||
void setnote(int index, const char* newtext);
|
||||
int getcurrentbranch();
|
||||
const char* getrecordermode();
|
||||
int getlostplayback();
|
||||
int getplaybacktarget();
|
||||
void setplayback(int frame);
|
||||
void stopseeking();
|
||||
|
||||
void getselection(std::vector<int>& placeholder);
|
||||
void setselection(std::vector<int>& new_set);
|
||||
int getinput(int frame, int joypad);
|
||||
void submitinputchange(int frame, int joypad, int input);
|
||||
void submitinsertframes(int frame, int number);
|
||||
void submitdeleteframes(int frame, int number);
|
||||
int applyinputchanges(const char* name);
|
||||
void clearinputchanges();
|
||||
|
||||
private:
|
||||
std::vector<PENDING_CHANGES> pending_changes;
|
||||
|
||||
HWND hwndRunFunction;
|
||||
|
||||
};
|
||||
|
|
|
@ -5,13 +5,13 @@
|
|||
|
||||
extern TASEDITOR_CONFIG taseditor_config;
|
||||
extern TASEDITOR_WINDOW taseditor_window;
|
||||
extern MARKERS current_markers;
|
||||
extern MARKERS_MANAGER markers_manager;
|
||||
extern BOOKMARKS bookmarks;
|
||||
extern POPUP_DISPLAY popup_display;
|
||||
extern GREENZONE greenzone;
|
||||
extern PLAYBACK playback;
|
||||
extern RECORDER recorder;
|
||||
extern INPUT_HISTORY history;
|
||||
extern HISTORY history;
|
||||
extern TASEDITOR_LIST list;
|
||||
extern TASEDITOR_SELECTION selection;
|
||||
extern SPLICER splicer;
|
||||
|
@ -28,14 +28,14 @@ TASEDITOR_PROJECT::TASEDITOR_PROJECT()
|
|||
|
||||
void TASEDITOR_PROJECT::init()
|
||||
{
|
||||
projectFile = "";
|
||||
projectName = "";
|
||||
fm2FileName = "";
|
||||
reset();
|
||||
}
|
||||
void TASEDITOR_PROJECT::reset()
|
||||
{
|
||||
changed = false;
|
||||
projectFile = "";
|
||||
projectName = "";
|
||||
fm2FileName = "";
|
||||
}
|
||||
void TASEDITOR_PROJECT::update()
|
||||
{
|
||||
|
@ -65,7 +65,7 @@ bool TASEDITOR_PROJECT::save()
|
|||
// save all modules
|
||||
unsigned int saved_stuff = ALL_SAVED;
|
||||
write32le(saved_stuff, ofs);
|
||||
current_markers.save(ofs);
|
||||
markers_manager.save(ofs);
|
||||
bookmarks.save(ofs);
|
||||
greenzone.save(ofs);
|
||||
history.save(ofs);
|
||||
|
@ -94,7 +94,7 @@ bool TASEDITOR_PROJECT::save_compact(char* filename, bool save_binary, bool save
|
|||
if (save_list) saved_stuff |= LIST_SAVED;
|
||||
if (save_selection) saved_stuff |= SELECTION_SAVED;
|
||||
write32le(saved_stuff, ofs);
|
||||
current_markers.save(ofs, save_markers);
|
||||
markers_manager.save(ofs, save_markers);
|
||||
bookmarks.save(ofs, save_bookmarks);
|
||||
greenzone.save(ofs, save_greenzone);
|
||||
history.save(ofs, save_history);
|
||||
|
@ -138,7 +138,7 @@ bool TASEDITOR_PROJECT::load(char* fullname)
|
|||
// load modules
|
||||
unsigned int saved_stuff;
|
||||
read32le(&saved_stuff, &ifs);
|
||||
current_markers.load(&ifs);
|
||||
markers_manager.load(&ifs);
|
||||
bookmarks.load(&ifs);
|
||||
greenzone.load(&ifs);
|
||||
history.load(&ifs);
|
||||
|
|
|
@ -1,22 +1,19 @@
|
|||
//Specification file for the TASEDITOR_PROJECT class
|
||||
#include <set>
|
||||
typedef std::set<int> SelectionFrames;
|
||||
|
||||
#include <time.h>
|
||||
#include "movie.h"
|
||||
#include "../common.h"
|
||||
#include "taseditor_config.h"
|
||||
#include "taseditor_window.h"
|
||||
#include "markers.h"
|
||||
#include "inputsnapshot.h"
|
||||
#include "inputhistory.h"
|
||||
#include "taseditor_sel.h"
|
||||
#include "markers_manager.h"
|
||||
#include "snapshot.h"
|
||||
#include "history.h"
|
||||
#include "playback.h"
|
||||
#include "recorder.h"
|
||||
#include "greenzone.h"
|
||||
#include "bookmarks.h"
|
||||
#include "taseditor_list.h"
|
||||
#include "taseditor_lua.h"
|
||||
#include "taseditor_sel.h"
|
||||
#include "splicer.h"
|
||||
#include "popup_display.h"
|
||||
|
||||
|
|
|
@ -1,16 +1,13 @@
|
|||
//Implementation file of TASEDITOR_SELECTION class
|
||||
#include "taseditor_project.h"
|
||||
#include "..\taseditor.h" // only for MARKER_NOTE_EDIT_LOWER
|
||||
|
||||
extern TASEDITOR_CONFIG taseditor_config;
|
||||
extern TASEDITOR_WINDOW taseditor_window;
|
||||
extern MARKERS current_markers;
|
||||
extern MARKERS_MANAGER markers_manager;
|
||||
extern TASEDITOR_LIST list;
|
||||
extern SPLICER splicer;
|
||||
|
||||
extern int marker_note_edit;
|
||||
extern int joysticks_per_frame[NUM_SUPPORTED_INPUT_TYPES];
|
||||
extern void UpdateMarkerNote();
|
||||
|
||||
LRESULT APIENTRY LowerMarkerEditWndProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam);
|
||||
WNDPROC selectionMarkerEdit_oldWndproc;
|
||||
|
@ -120,8 +117,8 @@ void TASEDITOR_SELECTION::update()
|
|||
// update "Selection's Marker text" if needed
|
||||
if (must_find_current_marker)
|
||||
{
|
||||
UpdateMarkerNote();
|
||||
shown_marker = current_markers.GetMarkerUp(last_selection_beginning);
|
||||
markers_manager.UpdateMarkerNote();
|
||||
shown_marker = markers_manager.GetMarkerUp(last_selection_beginning);
|
||||
RedrawMarker();
|
||||
must_find_current_marker = false;
|
||||
}
|
||||
|
@ -139,7 +136,7 @@ void TASEDITOR_SELECTION::RedrawMarker()
|
|||
strcat(new_text, num);
|
||||
SetWindowText(hwndSelectionMarker, new_text);
|
||||
// change marker note
|
||||
strcpy(new_text, current_markers.GetNote(shown_marker).c_str());
|
||||
strcpy(new_text, markers_manager.GetNote(shown_marker).c_str());
|
||||
SetWindowText(hwndSelectionMarkerEdit, new_text);
|
||||
}
|
||||
|
||||
|
@ -149,7 +146,7 @@ void TASEDITOR_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 (current_markers.GetMarker(index)) break;
|
||||
if (markers_manager.GetMarker(index)) break;
|
||||
if (index >= 0)
|
||||
JumpToFrame(index);
|
||||
else
|
||||
|
@ -163,7 +160,7 @@ void TASEDITOR_SELECTION::JumpNextMarker()
|
|||
|
||||
int last_frame = currMovieData.getNumRecords()-1;
|
||||
for (++index; index <= last_frame; ++index)
|
||||
if (current_markers.GetMarker(index)) break;
|
||||
if (markers_manager.GetMarker(index)) break;
|
||||
if (index <= last_frame)
|
||||
JumpToFrame(index);
|
||||
else
|
||||
|
@ -431,10 +428,10 @@ void TASEDITOR_SELECTION::SelectBetweenMarkers()
|
|||
// find markers
|
||||
// searching up starting from center-0
|
||||
for (upper_marker = center; upper_marker >= 0; upper_marker--)
|
||||
if (current_markers.GetMarker(upper_marker)) break;
|
||||
if (markers_manager.GetMarker(upper_marker)) break;
|
||||
// searching down starting from center+1
|
||||
for (lower_marker = center+1; lower_marker < movie_size; ++lower_marker)
|
||||
if (current_markers.GetMarker(lower_marker)) break;
|
||||
if (markers_manager.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(list.hwndList, -1, 0, LVIS_SELECTED);
|
||||
|
@ -528,11 +525,7 @@ SelectionFrames& TASEDITOR_SELECTION::GetStrobedSelection()
|
|||
return temp_selection;
|
||||
}
|
||||
|
||||
SelectionFrames& TASEDITOR_SELECTION::GetInsertedSet()
|
||||
{
|
||||
return inserted_set;
|
||||
}
|
||||
// this getter is only for inside-class use
|
||||
// this getter is private
|
||||
SelectionFrames& TASEDITOR_SELECTION::CurrentSelection()
|
||||
{
|
||||
return selections_history[(history_start_pos + history_cursor_pos) % history_size];
|
||||
|
@ -540,7 +533,7 @@ SelectionFrames& TASEDITOR_SELECTION::CurrentSelection()
|
|||
// -------------------------------------------------------------------------
|
||||
LRESULT APIENTRY LowerMarkerEditWndProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam)
|
||||
{
|
||||
if (marker_note_edit == MARKER_NOTE_EDIT_LOWER)
|
||||
if (markers_manager.marker_note_edit == MARKER_NOTE_EDIT_LOWER)
|
||||
{
|
||||
extern PLAYBACK playback;
|
||||
extern TASEDITOR_SELECTION selection;
|
||||
|
@ -552,7 +545,7 @@ LRESULT APIENTRY LowerMarkerEditWndProc(HWND hWnd, UINT msg, WPARAM wParam, LPAR
|
|||
{
|
||||
case VK_ESCAPE:
|
||||
// revert text to original note text
|
||||
SetWindowText(selection.hwndSelectionMarkerEdit, current_markers.GetNote(selection.shown_marker).c_str());
|
||||
SetWindowText(selection.hwndSelectionMarkerEdit, markers_manager.GetNote(selection.shown_marker).c_str());
|
||||
SetFocus(list.hwndList);
|
||||
return 0;
|
||||
case VK_RETURN:
|
||||
|
|
|
@ -1,4 +1,6 @@
|
|||
//Specification file for TASEDITOR_SELECTION class
|
||||
#include <set>
|
||||
typedef std::set<int> SelectionFrames;
|
||||
|
||||
#define SELECTION_ID_LEN 10
|
||||
|
||||
|
@ -27,7 +29,6 @@ public:
|
|||
|
||||
void undo();
|
||||
void redo();
|
||||
void jump(int new_pos);
|
||||
|
||||
void ClearSelection();
|
||||
void ClearRowSelection(int index);
|
||||
|
@ -51,8 +52,6 @@ public:
|
|||
SelectionFrames* MakeStrobe();
|
||||
SelectionFrames& GetStrobedSelection();
|
||||
|
||||
SelectionFrames& GetInsertedSet();
|
||||
|
||||
bool must_find_current_marker;
|
||||
int shown_marker;
|
||||
|
||||
|
@ -60,6 +59,8 @@ public:
|
|||
HWND hwndSelectionMarker, hwndSelectionMarkerEdit;
|
||||
|
||||
private:
|
||||
void jump(int new_pos);
|
||||
|
||||
SelectionFrames& CurrentSelection();
|
||||
|
||||
bool track_selection_changes;
|
||||
|
@ -71,8 +72,6 @@ private:
|
|||
|
||||
std::vector<SelectionFrames> selections_history;
|
||||
|
||||
SelectionFrames inserted_set;
|
||||
|
||||
int history_cursor_pos;
|
||||
int history_start_pos;
|
||||
int history_total_items;
|
||||
|
|
|
@ -4,6 +4,7 @@
|
|||
#include "../Win32InputBox.h"
|
||||
#include "../taseditor.h"
|
||||
#include <htmlhelp.h>
|
||||
#include "../../input.h" // for EMUCMD
|
||||
|
||||
extern TASEDITOR_CONFIG taseditor_config;
|
||||
extern PLAYBACK playback;
|
||||
|
@ -13,21 +14,22 @@ extern TASEDITOR_PROJECT project;
|
|||
extern TASEDITOR_LIST list;
|
||||
extern TASEDITOR_SELECTION selection;
|
||||
extern SPLICER splicer;
|
||||
extern MARKERS current_markers;
|
||||
extern MARKERS_MANAGER markers_manager;
|
||||
extern BOOKMARKS bookmarks;
|
||||
extern INPUT_HISTORY history;
|
||||
extern HISTORY history;
|
||||
extern POPUP_DISPLAY popup_display;
|
||||
|
||||
extern bool turbo;
|
||||
extern bool muteTurbo;
|
||||
extern int marker_note_edit;
|
||||
extern int search_similar_marker;
|
||||
extern bool must_call_manual_lua_function;
|
||||
|
||||
BOOL CALLBACK WndprocTasEditor(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam);
|
||||
extern char* GetKeyComboName(int c);
|
||||
|
||||
extern BOOL CALLBACK FindNoteProc(HWND hwndDlg, UINT message, WPARAM wParam, LPARAM lParam);
|
||||
extern BOOL CALLBACK AboutProc(HWND hwndDlg, UINT message, WPARAM wParam, LPARAM lParam);
|
||||
|
||||
BOOL CALLBACK WndprocTasEditor(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam);
|
||||
|
||||
// Recent Menu
|
||||
HMENU recent_projects_menu;
|
||||
char* recent_projects[] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
|
||||
|
@ -46,49 +48,54 @@ static struct
|
|||
int y;
|
||||
int width;
|
||||
int height;
|
||||
char tooltip_text_base[TOOLTIP_TEXT_MAX_LEN];
|
||||
char tooltip_text[TOOLTIP_TEXT_MAX_LEN];
|
||||
bool static_rect;
|
||||
int hotkey_emucmd;
|
||||
HWND tooltip_hwnd;
|
||||
} window_items[TASEDITOR_WINDOW_TOTAL_ITEMS] = {
|
||||
IDC_PROGRESS_BUTTON, -1, 0, 0, 0,
|
||||
IDC_BRANCHES_BUTTON, -1, 0, 0, 0,
|
||||
IDC_LIST1, 0, 0, -1, -1,
|
||||
IDC_PLAYBACK_BOX, -1, 0, 0, 0,
|
||||
IDC_RECORDER_BOX, -1, 0, 0, 0,
|
||||
IDC_SPLICER_BOX, -1, 0, 0, 0,
|
||||
IDC_LUA_BOX, -1, 0, 0, 0,
|
||||
IDC_BOOKMARKS_BOX, -1, 0, 0, 0,
|
||||
IDC_HISTORY_BOX, -1, 0, 0, -1,
|
||||
TASEDITOR_REWIND_FULL, -1, 0, 0, 0,
|
||||
TASEDITOR_REWIND, -1, 0, 0, 0,
|
||||
TASEDITOR_PLAYSTOP, -1, 0, 0, 0,
|
||||
TASEDITOR_FORWARD, -1, 0, 0, 0,
|
||||
TASEDITOR_FORWARD_FULL, -1, 0, 0, 0,
|
||||
IDC_PROGRESS1, -1, 0, 0, 0,
|
||||
CHECK_FOLLOW_CURSOR, -1, 0, 0, 0,
|
||||
CHECK_AUTORESTORE_PLAYBACK, -1, 0, 0, 0,
|
||||
IDC_BOOKMARKSLIST, -1, 0, 0, 0,
|
||||
IDC_HISTORYLIST, -1, 0, 0, -1,
|
||||
IDC_RADIO_ALL, -1, 0, 0, 0,
|
||||
IDC_RADIO_1P, -1, 0, 0, 0,
|
||||
IDC_RADIO_2P, -1, 0, 0, 0,
|
||||
IDC_RADIO_3P, -1, 0, 0, 0,
|
||||
IDC_RADIO_4P, -1, 0, 0, 0,
|
||||
IDC_SUPERIMPOSE, -1, 0, 0, 0,
|
||||
TASEDITOR_PREV_MARKER, -1, -1, 0, -1,
|
||||
TASEDITOR_FIND_BEST_SIMILAR_MARKER, -1, -1, 0, -1,
|
||||
TASEDITOR_FIND_NEXT_SIMILAR_MARKER, -1, -1, 0, -1,
|
||||
TASEDITOR_NEXT_MARKER, -1, -1, 0, -1,
|
||||
IDC_JUMP_PLAYBACK_BUTTON, 0, 0, 0, 0,
|
||||
IDC_PLAYBACK_MARKER_EDIT, 0, 0, -1, 0,
|
||||
IDC_PLAYBACK_MARKER, 0, 0, 0, 0,
|
||||
IDC_JUMP_SELECTION_BUTTON, 0, -1, 0, -1,
|
||||
IDC_SELECTION_MARKER_EDIT, 0, -1, -1, -1,
|
||||
IDC_SELECTION_MARKER, 0, -1, 0, -1,
|
||||
IDC_BRANCHES_BITMAP, -1, 0, 0, 0,
|
||||
CHECK_TURBO_SEEK, -1, 0, 0, 0,
|
||||
IDC_TEXT_SELECTION, -1, 0, 0, 0,
|
||||
IDC_TEXT_CLIPBOARD, -1, 0, 0, 0,
|
||||
IDC_RECORDING, -1, 0, 0, 0,
|
||||
TASEDITOR_RUN_MANUAL, -1, 0, 0, 0,
|
||||
IDC_RUN_AUTO, -1, 0, 0, 0,
|
||||
IDC_PROGRESS_BUTTON, -1, 0, 0, 0, "Click here whenever you want to abort seeking", "", false, 0, 0,
|
||||
IDC_BRANCHES_BUTTON, -1, 0, 0, 0, "Click here to switch between Bookmarks List and Branches Tree", "", false, 0, 0,
|
||||
IDC_LIST1, 0, 0, -1, -1, "", "", false, 0, 0,
|
||||
IDC_PLAYBACK_BOX, -1, 0, 0, 0, "", "", false, 0, 0,
|
||||
IDC_RECORDER_BOX, -1, 0, 0, 0, "", "", false, 0, 0,
|
||||
IDC_SPLICER_BOX, -1, 0, 0, 0, "", "", false, 0, 0,
|
||||
IDC_LUA_BOX, -1, 0, 0, 0, "", "", false, 0, 0,
|
||||
IDC_BOOKMARKS_BOX, -1, 0, 0, 0, "", "", false, 0, 0,
|
||||
IDC_HISTORY_BOX, -1, 0, 0, -1, "", "", false, 0, 0,
|
||||
TASEDITOR_REWIND_FULL, -1, 0, 0, 0, "Send Playback to previous Marker (hotkey: Shift+PageUp)", "", false, 0, 0,
|
||||
TASEDITOR_REWIND, -1, 0, 0, 0, "Rewind one frame", "", false, EMUCMD_TASEDITOR_REWIND, 0,
|
||||
TASEDITOR_PLAYSTOP, -1, 0, 0, 0, "Pause/Unpause Emulation", "", false, EMUCMD_PAUSE, 0,
|
||||
TASEDITOR_FORWARD, -1, 0, 0, 0, "Advance one frame", "", false, EMUCMD_FRAME_ADVANCE, 0,
|
||||
TASEDITOR_FORWARD_FULL, -1, 0, 0, 0, "Send Playback to next Marker (hotkey: Shift+PageDown)", "", false, 0, 0,
|
||||
IDC_PROGRESS1, -1, 0, 0, 0, "", "", false, 0, 0,
|
||||
CHECK_FOLLOW_CURSOR, -1, 0, 0, 0, "The List will follow Playback cursor movements", "", false, 0, 0,
|
||||
CHECK_AUTORESTORE_PLAYBACK, -1, 0, 0, 0, "If you change input above Playback, cursor will run where it was before change", "", false, 0, 0,
|
||||
IDC_BOOKMARKSLIST, -1, 0, 0, 0, "Right click = set Bookmark, Left click = jump to Bookmark or load Branch", "", false, 0, 0,
|
||||
IDC_HISTORYLIST, -1, 0, 0, -1, "Click to revert movie back to that time", "", false, 0, 0,
|
||||
IDC_RADIO_ALL, -1, 0, 0, 0, "", "", false, 0, 0,
|
||||
IDC_RADIO_1P, -1, 0, 0, 0, "", "", false, 0, 0,
|
||||
IDC_RADIO_2P, -1, 0, 0, 0, "", "", false, 0, 0,
|
||||
IDC_RADIO_3P, -1, 0, 0, 0, "", "", false, 0, 0,
|
||||
IDC_RADIO_4P, -1, 0, 0, 0, "", "", false, 0, 0,
|
||||
IDC_SUPERIMPOSE, -1, 0, 0, 0, "Allows to superimpose old input with new buttons, instead of overwriting", "", false, 0, 0,
|
||||
TASEDITOR_PREV_MARKER, -1, -1, 0, -1, "Send Selection to previous Marker (hotkey: Ctrl+PageUp)", "", false, 0, 0,
|
||||
TASEDITOR_FIND_BEST_SIMILAR_MARKER, -1, -1, 0, -1, "Auto-search for Marker Note", "", false, 0, 0,
|
||||
TASEDITOR_FIND_NEXT_SIMILAR_MARKER, -1, -1, 0, -1, "Continue Auto-search", "", false, 0, 0,
|
||||
TASEDITOR_NEXT_MARKER, -1, -1, 0, -1, "Send Selection to next Marker (hotkey: Ctrl+PageDown)", "", false, 0, 0,
|
||||
IDC_JUMP_PLAYBACK_BUTTON, 0, 0, 0, 0, "Click here to scroll the List to Playback cursor", "", false, 0, 0,
|
||||
IDC_PLAYBACK_MARKER_EDIT, 0, 0, -1, 0, "Click to edit text", "", false, 0, 0,
|
||||
IDC_PLAYBACK_MARKER, 0, 0, 0, 0, "", "", false, 0, 0,
|
||||
IDC_JUMP_SELECTION_BUTTON, 0, -1, 0, -1, "Click here to scroll the List to Selection", "", false, 0, 0,
|
||||
IDC_SELECTION_MARKER_EDIT, 0, -1, -1, -1, "Click to edit text", "", false, 0, 0,
|
||||
IDC_SELECTION_MARKER, 0, -1, 0, -1, "", "", false, 0, 0,
|
||||
IDC_BRANCHES_BITMAP, -1, 0, 0, 0, "This window visualizes the hierarchy of your Branches", "", false, 0, 0,
|
||||
CHECK_TURBO_SEEK, -1, 0, 0, 0, "Uncheck when you need to watch seeking in slow motion", "", false, 0, 0,
|
||||
IDC_TEXT_SELECTION, -1, 0, 0, 0, "Current size of Selection", "", true, 0, 0,
|
||||
IDC_TEXT_CLIPBOARD, -1, 0, 0, 0, "Current size of Input in the Clipboard", "", true, 0, 0,
|
||||
IDC_RECORDING, -1, 0, 0, 0, "Switch Input Recording on/off", "", false, EMUCMD_MOVIE_READONLY_TOGGLE, 0,
|
||||
TASEDITOR_RUN_MANUAL, -1, 0, 0, 0, "Press the button to execute Lua Manual Function", "", false, 0, 0,
|
||||
IDC_RUN_AUTO, -1, 0, 0, 0, "Enable Lua Auto Function (but first it must be registered by Lua script)", "", false, 0, 0,
|
||||
};
|
||||
|
||||
TASEDITOR_WINDOW::TASEDITOR_WINDOW()
|
||||
|
@ -108,17 +115,73 @@ void TASEDITOR_WINDOW::init()
|
|||
ready_for_resizing = false;
|
||||
hTaseditorIcon = (HICON)LoadImage(fceu_hInstance, MAKEINTRESOURCE(IDI_ICON3), IMAGE_ICON, 16, 16, LR_DEFAULTSIZE);
|
||||
hwndTasEditor = CreateDialog(fceu_hInstance, "TASEDITOR", hAppWnd, WndprocTasEditor);
|
||||
SendMessage(hwndTasEditor, WM_SETICON, ICON_SMALL, (LPARAM)hTaseditorIcon);
|
||||
CalculateItems();
|
||||
// restore position and size from config, also bring the window on top
|
||||
//RECT desiredRect = {0, 0, taseditor_config.wndwidth, taseditor_config.wndheight};
|
||||
//AdjustWindowRectEx(&desiredRect, GetWindowLong(hwndTasEditor, GWL_STYLE), true, GetWindowLong(hwndTasEditor, GWL_EXSTYLE));
|
||||
SetWindowPos(hwndTasEditor, HWND_TOP, taseditor_config.wndx, taseditor_config.wndy, taseditor_config.wndwidth, taseditor_config.wndheight, SWP_NOOWNERZORDER);
|
||||
|
||||
// menus and checked items
|
||||
hmenu = GetMenu(hwndTasEditor);
|
||||
hrmenu = LoadMenu(fceu_hInstance,"TASEDITORCONTEXTMENUS");
|
||||
|
||||
UpdateCheckedItems();
|
||||
|
||||
// tooltips
|
||||
int x = 0;
|
||||
for (int i = 0; i < TASEDITOR_WINDOW_TOTAL_ITEMS; ++i)
|
||||
{
|
||||
if (window_items[i].tooltip_text_base[0])
|
||||
{
|
||||
// Create the tooltip. g_hInst is the global instance handle
|
||||
window_items[i].tooltip_hwnd = CreateWindowEx(NULL, TOOLTIPS_CLASS, NULL,
|
||||
WS_POPUP | TTS_ALWAYSTIP | TTS_BALLOON,
|
||||
CW_USEDEFAULT, CW_USEDEFAULT,
|
||||
CW_USEDEFAULT, CW_USEDEFAULT,
|
||||
hwndTasEditor, NULL,
|
||||
fceu_hInstance, NULL);
|
||||
if (window_items[i].tooltip_hwnd)
|
||||
{
|
||||
// Associate the tooltip with the tool
|
||||
TOOLINFO toolInfo = {0};
|
||||
toolInfo.cbSize = sizeof(toolInfo);
|
||||
toolInfo.hwnd = hwndTasEditor;
|
||||
toolInfo.uId = (UINT_PTR)GetDlgItem(hwndTasEditor, window_items[i].id);
|
||||
if (window_items[i].static_rect)
|
||||
{
|
||||
// for static text we specify rectangle
|
||||
toolInfo.uFlags = TTF_SUBCLASS;
|
||||
RECT tool_rect;
|
||||
GetWindowRect(GetDlgItem(hwndTasEditor, window_items[i].id), &tool_rect);
|
||||
POINT pt;
|
||||
pt.x = tool_rect.left;
|
||||
pt.y = tool_rect.top;
|
||||
ScreenToClient(hwndTasEditor, &pt);
|
||||
toolInfo.rect.left = pt.x;
|
||||
toolInfo.rect.right = toolInfo.rect.left + (tool_rect.right - tool_rect.left);
|
||||
toolInfo.rect.top = pt.y;
|
||||
toolInfo.rect.bottom = toolInfo.rect.top + (tool_rect.bottom - tool_rect.top);
|
||||
} else
|
||||
{
|
||||
// for other controls we provide hwnd
|
||||
toolInfo.uFlags = TTF_IDISHWND | TTF_SUBCLASS;
|
||||
}
|
||||
// add hotkey mapping if needed
|
||||
if (window_items[i].hotkey_emucmd && FCEUD_CommandMapping[window_items[i].hotkey_emucmd])
|
||||
{
|
||||
window_items[i].tooltip_text[0] = 0;
|
||||
strcpy(window_items[i].tooltip_text, window_items[i].tooltip_text_base);
|
||||
strcat(window_items[i].tooltip_text, " (hotkey: ");
|
||||
strncat(window_items[i].tooltip_text, GetKeyComboName(FCEUD_CommandMapping[window_items[i].hotkey_emucmd]), TOOLTIP_TEXT_MAX_LEN - strlen(window_items[i].tooltip_text) - 1);
|
||||
strncat(window_items[i].tooltip_text, ")", TOOLTIP_TEXT_MAX_LEN - strlen(window_items[i].tooltip_text) - 1);
|
||||
toolInfo.lpszText = window_items[i].tooltip_text;
|
||||
} else
|
||||
{
|
||||
toolInfo.lpszText = window_items[i].tooltip_text_base;
|
||||
}
|
||||
SendMessage(window_items[i].tooltip_hwnd, TTM_ADDTOOL, 0, (LPARAM)&toolInfo);
|
||||
SendMessage(window_items[i].tooltip_hwnd, TTM_SETDELAYTIME, TTDT_AUTOPOP, TOOLTIPS_AUTOPOP_TIMEOUT);
|
||||
}
|
||||
}
|
||||
}
|
||||
UpdateTooltips();
|
||||
// recent projects submenu
|
||||
recent_projects_menu = CreateMenu();
|
||||
UpdateRecentProjectsMenu();
|
||||
|
||||
|
@ -126,6 +189,14 @@ void TASEDITOR_WINDOW::init()
|
|||
}
|
||||
void TASEDITOR_WINDOW::exit()
|
||||
{
|
||||
for (int i = 0; i < TASEDITOR_WINDOW_TOTAL_ITEMS; ++i)
|
||||
{
|
||||
if (window_items[i].tooltip_hwnd)
|
||||
{
|
||||
DestroyWindow(window_items[i].tooltip_hwnd);
|
||||
window_items[i].tooltip_hwnd = 0;
|
||||
}
|
||||
}
|
||||
if (hwndFindNote)
|
||||
{
|
||||
DestroyWindow(hwndFindNote);
|
||||
|
@ -238,12 +309,10 @@ void TASEDITOR_WINDOW::ResizeItems()
|
|||
else
|
||||
// normal height
|
||||
height = window_items[i].height;
|
||||
SetWindowPos(hCtrl, 0, x, y, width, height, SWP_NOZORDER | SWP_NOOWNERZORDER | SWP_NOREDRAW);
|
||||
SetWindowPos(hCtrl, 0, x, y, width, height, SWP_NOZORDER | SWP_NOOWNERZORDER);
|
||||
}
|
||||
RedrawTaseditor();
|
||||
//RedrawWindow(hwndTasEditor, NULL, NULL, RDW_INVALIDATE);
|
||||
}
|
||||
|
||||
void TASEDITOR_WINDOW::WindowMovedOrResized()
|
||||
{
|
||||
RECT wrect;
|
||||
|
@ -259,6 +328,25 @@ void TASEDITOR_WINDOW::WindowMovedOrResized()
|
|||
taseditor_config.wndheight = min_height;
|
||||
}
|
||||
|
||||
void TASEDITOR_WINDOW::UpdateTooltips()
|
||||
{
|
||||
if (taseditor_config.tooltips)
|
||||
{
|
||||
for (int i = 0; i < TASEDITOR_WINDOW_TOTAL_ITEMS; ++i)
|
||||
{
|
||||
if (window_items[i].tooltip_hwnd)
|
||||
SendMessage(window_items[i].tooltip_hwnd, TTM_ACTIVATE, true, 0);
|
||||
}
|
||||
} else
|
||||
{
|
||||
for (int i = 0; i < TASEDITOR_WINDOW_TOTAL_ITEMS; ++i)
|
||||
{
|
||||
if (window_items[i].tooltip_hwnd)
|
||||
SendMessage(window_items[i].tooltip_hwnd, TTM_ACTIVATE, false, 0);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void TASEDITOR_WINDOW::UpdateCaption()
|
||||
{
|
||||
char new_caption[300];
|
||||
|
@ -315,7 +403,7 @@ void TASEDITOR_WINDOW::RightClickMenu(LPNMITEMACTIVATE info)
|
|||
bool set_found = false, unset_found = false;
|
||||
for(SelectionFrames::iterator it(current_selection_begin); it != current_selection_end; it++)
|
||||
{
|
||||
if(current_markers.GetMarker(*it))
|
||||
if(markers_manager.GetMarker(*it))
|
||||
set_found = true;
|
||||
else
|
||||
unset_found = true;
|
||||
|
@ -359,6 +447,7 @@ void TASEDITOR_WINDOW::UpdateCheckedItems()
|
|||
CheckMenuItem(hmenu, ID_CONFIG_SUPERIMPOSE_AFFECTS_PASTE, taseditor_config.superimpose_affects_paste?MF_CHECKED : MF_UNCHECKED);
|
||||
CheckMenuItem(hmenu, ID_CONFIG_MUTETURBO, muteTurbo?MF_CHECKED : MF_UNCHECKED);
|
||||
CheckMenuItem(hmenu, ID_CONFIG_SILENTAUTOSAVE, taseditor_config.silent_autosave?MF_CHECKED : MF_UNCHECKED);
|
||||
CheckMenuItem(hmenu, ID_HELP_TOOLTIPS, taseditor_config.tooltips?MF_CHECKED : MF_UNCHECKED);
|
||||
|
||||
}
|
||||
|
||||
|
@ -493,7 +582,6 @@ BOOL CALLBACK WndprocTasEditor(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lP
|
|||
{
|
||||
if (taseditor_config.wndx == -32000) taseditor_config.wndx = 0; //Just in case
|
||||
if (taseditor_config.wndy == -32000) taseditor_config.wndy = 0;
|
||||
SendMessage(hwndDlg, WM_SETICON, ICON_SMALL, (LPARAM)taseditor_window.hTaseditorIcon);
|
||||
break;
|
||||
}
|
||||
case WM_WINDOWPOSCHANGED:
|
||||
|
@ -542,10 +630,10 @@ BOOL CALLBACK WndprocTasEditor(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lP
|
|||
list.GetDispInfo((NMLVDISPINFO*)lParam);
|
||||
break;
|
||||
case NM_CLICK:
|
||||
SingleClick((LPNMITEMACTIVATE)lParam);
|
||||
list.SingleClick((LPNMITEMACTIVATE)lParam);
|
||||
break;
|
||||
case NM_DBLCLK:
|
||||
DoubleClick((LPNMITEMACTIVATE)lParam);
|
||||
list.DoubleClick((LPNMITEMACTIVATE)lParam);
|
||||
break;
|
||||
case NM_RCLICK:
|
||||
taseditor_window.RightClick((LPNMITEMACTIVATE)lParam);
|
||||
|
@ -610,6 +698,9 @@ BOOL CALLBACK WndprocTasEditor(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lP
|
|||
break;
|
||||
}
|
||||
break;
|
||||
case ID_STRAY_UNPAUSE:
|
||||
playback.UnpauseEmulation();
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case WM_CLOSE:
|
||||
|
@ -620,11 +711,11 @@ BOOL CALLBACK WndprocTasEditor(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lP
|
|||
if(LOWORD(wParam))
|
||||
{
|
||||
taseditor_window.TASEditor_focus = true;
|
||||
SetTaseditInput();
|
||||
SetTaseditorInput();
|
||||
} else
|
||||
{
|
||||
taseditor_window.TASEditor_focus = false;
|
||||
ClearTaseditInput();
|
||||
ClearTaseditorInput();
|
||||
}
|
||||
break;
|
||||
case WM_CTLCOLORSTATIC:
|
||||
|
@ -659,27 +750,27 @@ BOOL CALLBACK WndprocTasEditor(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lP
|
|||
{
|
||||
case EN_SETFOCUS:
|
||||
{
|
||||
marker_note_edit = MARKER_NOTE_EDIT_UPPER;
|
||||
markers_manager.marker_note_edit = MARKER_NOTE_EDIT_UPPER;
|
||||
// enable editing
|
||||
SendMessage(playback.hwndPlaybackMarkerEdit, EM_SETREADONLY, false, 0);
|
||||
// disable FCEUX keyboard
|
||||
ClearTaseditInput();
|
||||
ClearTaseditorInput();
|
||||
if (taseditor_config.follow_note_context)
|
||||
list.FollowPlayback();
|
||||
break;
|
||||
}
|
||||
case EN_KILLFOCUS:
|
||||
{
|
||||
if (marker_note_edit == MARKER_NOTE_EDIT_UPPER)
|
||||
if (markers_manager.marker_note_edit == MARKER_NOTE_EDIT_UPPER)
|
||||
{
|
||||
UpdateMarkerNote();
|
||||
marker_note_edit = MARKER_NOTE_EDIT_NONE;
|
||||
markers_manager.UpdateMarkerNote();
|
||||
markers_manager.marker_note_edit = MARKER_NOTE_EDIT_NONE;
|
||||
}
|
||||
// disable editing (make it grayed)
|
||||
SendMessage(playback.hwndPlaybackMarkerEdit, EM_SETREADONLY, true, 0);
|
||||
// enable FCEUX keyboard
|
||||
if (taseditor_window.TASEditor_focus)
|
||||
SetTaseditInput();
|
||||
SetTaseditorInput();
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
@ -691,27 +782,27 @@ BOOL CALLBACK WndprocTasEditor(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lP
|
|||
{
|
||||
case EN_SETFOCUS:
|
||||
{
|
||||
marker_note_edit = MARKER_NOTE_EDIT_LOWER;
|
||||
markers_manager.marker_note_edit = MARKER_NOTE_EDIT_LOWER;
|
||||
// enable editing
|
||||
SendMessage(selection.hwndSelectionMarkerEdit, EM_SETREADONLY, false, 0);
|
||||
// disable FCEUX keyboard
|
||||
ClearTaseditInput();
|
||||
ClearTaseditorInput();
|
||||
if (taseditor_config.follow_note_context)
|
||||
list.FollowSelection();
|
||||
break;
|
||||
}
|
||||
case EN_KILLFOCUS:
|
||||
{
|
||||
if (marker_note_edit == MARKER_NOTE_EDIT_LOWER)
|
||||
if (markers_manager.marker_note_edit == MARKER_NOTE_EDIT_LOWER)
|
||||
{
|
||||
UpdateMarkerNote();
|
||||
marker_note_edit = MARKER_NOTE_EDIT_NONE;
|
||||
markers_manager.UpdateMarkerNote();
|
||||
markers_manager.marker_note_edit = MARKER_NOTE_EDIT_NONE;
|
||||
}
|
||||
// disable editing (make it grayed)
|
||||
SendMessage(selection.hwndSelectionMarkerEdit, EM_SETREADONLY, true, 0);
|
||||
// enable FCEUX keyboard
|
||||
if (taseditor_window.TASEditor_focus)
|
||||
SetTaseditInput();
|
||||
SetTaseditorInput();
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
@ -743,36 +834,36 @@ BOOL CALLBACK WndprocTasEditor(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lP
|
|||
ExitTasEditor();
|
||||
break;
|
||||
case ID_EDIT_SELECTALL:
|
||||
if (marker_note_edit == MARKER_NOTE_EDIT_UPPER)
|
||||
if (markers_manager.marker_note_edit == MARKER_NOTE_EDIT_UPPER)
|
||||
SendMessage(playback.hwndPlaybackMarkerEdit, EM_SETSEL, 0, -1);
|
||||
else if (marker_note_edit == MARKER_NOTE_EDIT_LOWER)
|
||||
else if (markers_manager.marker_note_edit == MARKER_NOTE_EDIT_LOWER)
|
||||
SendMessage(selection.hwndSelectionMarkerEdit, EM_SETSEL, 0, -1);
|
||||
else
|
||||
selection.SelectAll();
|
||||
break;
|
||||
case ACCEL_CTRL_X:
|
||||
case ID_EDIT_CUT:
|
||||
if (marker_note_edit == MARKER_NOTE_EDIT_UPPER)
|
||||
if (markers_manager.marker_note_edit == MARKER_NOTE_EDIT_UPPER)
|
||||
SendMessage(playback.hwndPlaybackMarkerEdit, WM_CUT, 0, 0);
|
||||
else if (marker_note_edit == MARKER_NOTE_EDIT_LOWER)
|
||||
else if (markers_manager.marker_note_edit == MARKER_NOTE_EDIT_LOWER)
|
||||
SendMessage(selection.hwndSelectionMarkerEdit, WM_CUT, 0, 0);
|
||||
else
|
||||
splicer.Cut();
|
||||
break;
|
||||
case ACCEL_CTRL_C:
|
||||
case ID_EDIT_COPY:
|
||||
if (marker_note_edit == MARKER_NOTE_EDIT_UPPER)
|
||||
if (markers_manager.marker_note_edit == MARKER_NOTE_EDIT_UPPER)
|
||||
SendMessage(playback.hwndPlaybackMarkerEdit, WM_COPY, 0, 0);
|
||||
else if (marker_note_edit == MARKER_NOTE_EDIT_LOWER)
|
||||
else if (markers_manager.marker_note_edit == MARKER_NOTE_EDIT_LOWER)
|
||||
SendMessage(selection.hwndSelectionMarkerEdit, WM_COPY, 0, 0);
|
||||
else
|
||||
splicer.Copy();
|
||||
break;
|
||||
case ACCEL_CTRL_V:
|
||||
case ID_EDIT_PASTE:
|
||||
if (marker_note_edit == MARKER_NOTE_EDIT_UPPER)
|
||||
if (markers_manager.marker_note_edit == MARKER_NOTE_EDIT_UPPER)
|
||||
SendMessage(playback.hwndPlaybackMarkerEdit, WM_PASTE, 0, 0);
|
||||
else if (marker_note_edit == MARKER_NOTE_EDIT_LOWER)
|
||||
else if (markers_manager.marker_note_edit == MARKER_NOTE_EDIT_LOWER)
|
||||
SendMessage(selection.hwndSelectionMarkerEdit, WM_PASTE, 0, 0);
|
||||
else
|
||||
splicer.Paste();
|
||||
|
@ -782,13 +873,13 @@ BOOL CALLBACK WndprocTasEditor(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lP
|
|||
// hack to allow entering Shift-V into edit control even though accelerator steals the input message
|
||||
char insert_v[] = "v";
|
||||
char insert_V[] = "V";
|
||||
if (marker_note_edit == MARKER_NOTE_EDIT_UPPER)
|
||||
if (markers_manager.marker_note_edit == MARKER_NOTE_EDIT_UPPER)
|
||||
{
|
||||
if (GetKeyState(VK_CAPITAL) & 1)
|
||||
SendMessage(playback.hwndPlaybackMarkerEdit, EM_REPLACESEL, true, (LPARAM)insert_v);
|
||||
else
|
||||
SendMessage(playback.hwndPlaybackMarkerEdit, EM_REPLACESEL, true, (LPARAM)insert_V);
|
||||
} else if (marker_note_edit == MARKER_NOTE_EDIT_LOWER)
|
||||
} else if (markers_manager.marker_note_edit == MARKER_NOTE_EDIT_LOWER)
|
||||
{
|
||||
if (GetKeyState(VK_CAPITAL) & 1)
|
||||
SendMessage(selection.hwndSelectionMarkerEdit, EM_REPLACESEL, true, (LPARAM)insert_v);
|
||||
|
@ -799,9 +890,9 @@ BOOL CALLBACK WndprocTasEditor(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lP
|
|||
break;
|
||||
}
|
||||
case ID_EDIT_PASTEINSERT:
|
||||
if (marker_note_edit == MARKER_NOTE_EDIT_UPPER)
|
||||
if (markers_manager.marker_note_edit == MARKER_NOTE_EDIT_UPPER)
|
||||
SendMessage(playback.hwndPlaybackMarkerEdit, WM_PASTE, 0, 0);
|
||||
else if (marker_note_edit == MARKER_NOTE_EDIT_LOWER)
|
||||
else if (markers_manager.marker_note_edit == MARKER_NOTE_EDIT_LOWER)
|
||||
SendMessage(selection.hwndSelectionMarkerEdit, WM_PASTE, 0, 0);
|
||||
else
|
||||
splicer.PasteInsert();
|
||||
|
@ -811,20 +902,11 @@ BOOL CALLBACK WndprocTasEditor(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lP
|
|||
case ID_CONTEXT_SELECTED_DELETEFRAMES:
|
||||
splicer.DeleteFrames();
|
||||
break;
|
||||
case ACCEL_CTRL_T:
|
||||
case ID_EDIT_TRUNCATE:
|
||||
case ID_CONTEXT_SELECTED_TRUNCATE:
|
||||
case ID_CONTEXT_STRAY_TRUNCATE:
|
||||
case ID_STRAY_TRUNCATE:
|
||||
splicer.Truncate();
|
||||
break;
|
||||
case ID_HELP_TASEDITHELP:
|
||||
{
|
||||
//OpenHelpWindow(tasedithelp);
|
||||
std::string helpFileName = BaseDirectory;
|
||||
helpFileName.append(taseditor_help_filename);
|
||||
HtmlHelp(GetDesktopWindow(), helpFileName.c_str(), HH_DISPLAY_TOPIC, (DWORD)NULL);
|
||||
break;
|
||||
}
|
||||
case ACCEL_INS:
|
||||
case ID_EDIT_INSERT:
|
||||
case MENU_CONTEXT_STRAY_INSERTFRAMES:
|
||||
|
@ -839,14 +921,14 @@ BOOL CALLBACK WndprocTasEditor(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lP
|
|||
case ACCEL_DEL:
|
||||
case ID_EDIT_CLEAR:
|
||||
case ID_CONTEXT_SELECTED_CLEARFRAMES:
|
||||
if (marker_note_edit == MARKER_NOTE_EDIT_UPPER)
|
||||
if (markers_manager.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)
|
||||
} else if (markers_manager.marker_note_edit == MARKER_NOTE_EDIT_LOWER)
|
||||
{
|
||||
DWORD sel_start, sel_end;
|
||||
SendMessage(selection.hwndSelectionMarkerEdit, EM_GETSEL, (WPARAM)&sel_start, (LPARAM)&sel_end);
|
||||
|
@ -864,7 +946,7 @@ BOOL CALLBACK WndprocTasEditor(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lP
|
|||
taseditor_config.follow_playback ^= 1;
|
||||
taseditor_window.UpdateCheckedItems();
|
||||
// if switched off then maybe jump to target frame
|
||||
if (!taseditor_config.follow_playback && playback.GetPauseFrame())
|
||||
if (!taseditor_config.follow_playback && playback.pause_frame)
|
||||
list.FollowPauseframe();
|
||||
break;
|
||||
case CHECK_TURBO_SEEK:
|
||||
|
@ -1022,7 +1104,7 @@ BOOL CALLBACK WndprocTasEditor(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lP
|
|||
break;
|
||||
case IDC_PROGRESS_BUTTON:
|
||||
// click on progressbar - stop seeking
|
||||
if (playback.GetPauseFrame()) playback.SeekingStop();
|
||||
if (playback.pause_frame) playback.SeekingStop();
|
||||
break;
|
||||
case IDC_BRANCHES_BUTTON:
|
||||
// click on "Bookmarks/Branches" - switch "View Tree of branches"
|
||||
|
@ -1059,9 +1141,9 @@ BOOL CALLBACK WndprocTasEditor(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lP
|
|||
taseditor_window.UpdateCheckedItems();
|
||||
break;
|
||||
case ACCEL_CTRL_A:
|
||||
if (marker_note_edit == MARKER_NOTE_EDIT_UPPER)
|
||||
if (markers_manager.marker_note_edit == MARKER_NOTE_EDIT_UPPER)
|
||||
SendMessage(playback.hwndPlaybackMarkerEdit, EM_SETSEL, 0, -1);
|
||||
else if (marker_note_edit == MARKER_NOTE_EDIT_LOWER)
|
||||
else if (markers_manager.marker_note_edit == MARKER_NOTE_EDIT_LOWER)
|
||||
SendMessage(selection.hwndSelectionMarkerEdit, EM_SETSEL, 0, -1);
|
||||
else
|
||||
selection.SelectBetweenMarkers();
|
||||
|
@ -1078,10 +1160,10 @@ BOOL CALLBACK WndprocTasEditor(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lP
|
|||
case ACCEL_CTRL_Z:
|
||||
case ID_EDIT_UNDO:
|
||||
{
|
||||
if (marker_note_edit == MARKER_NOTE_EDIT_UPPER)
|
||||
if (markers_manager.marker_note_edit == MARKER_NOTE_EDIT_UPPER)
|
||||
{
|
||||
SendMessage(playback.hwndPlaybackMarkerEdit, WM_UNDO, 0, 0);
|
||||
} else if (marker_note_edit == MARKER_NOTE_EDIT_LOWER)
|
||||
} else if (markers_manager.marker_note_edit == MARKER_NOTE_EDIT_LOWER)
|
||||
{
|
||||
SendMessage(selection.hwndSelectionMarkerEdit, WM_UNDO, 0, 0);
|
||||
} else
|
||||
|
@ -1149,9 +1231,9 @@ BOOL CALLBACK WndprocTasEditor(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lP
|
|||
bool changes_made = false;
|
||||
for(SelectionFrames::iterator it(current_selection_begin); it != current_selection_end; it++)
|
||||
{
|
||||
if(!current_markers.GetMarker(*it))
|
||||
if(!markers_manager.GetMarker(*it))
|
||||
{
|
||||
if (current_markers.SetMarker(*it))
|
||||
if (markers_manager.SetMarker(*it))
|
||||
{
|
||||
changes_made = true;
|
||||
list.RedrawRow(*it);
|
||||
|
@ -1176,9 +1258,9 @@ BOOL CALLBACK WndprocTasEditor(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lP
|
|||
bool changes_made = false;
|
||||
for(SelectionFrames::iterator it(current_selection_begin); it != current_selection_end; it++)
|
||||
{
|
||||
if(current_markers.GetMarker(*it))
|
||||
if(markers_manager.GetMarker(*it))
|
||||
{
|
||||
current_markers.ClearMarker(*it);
|
||||
markers_manager.ClearMarker(*it);
|
||||
changes_made = true;
|
||||
list.RedrawRow(*it);
|
||||
}
|
||||
|
@ -1215,16 +1297,10 @@ BOOL CALLBACK WndprocTasEditor(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lP
|
|||
break;
|
||||
}
|
||||
case TASEDITOR_FIND_BEST_SIMILAR_MARKER:
|
||||
search_similar_marker = 0;
|
||||
current_markers.FindSimilar(search_similar_marker);
|
||||
search_similar_marker++;
|
||||
markers_manager.FindSimilar();
|
||||
break;
|
||||
case TASEDITOR_FIND_NEXT_SIMILAR_MARKER:
|
||||
current_markers.FindSimilar(search_similar_marker);
|
||||
search_similar_marker++;
|
||||
break;
|
||||
case ID_HELP_ABOUT:
|
||||
DialogBox(fceu_hInstance, MAKEINTRESOURCE(IDD_TASEDITOR_ABOUT), taseditor_window.hwndTasEditor, AboutProc);
|
||||
markers_manager.FindNextSimilar();
|
||||
break;
|
||||
case TASEDITOR_RUN_MANUAL:
|
||||
// the function will be called in next window update
|
||||
|
@ -1234,6 +1310,21 @@ BOOL CALLBACK WndprocTasEditor(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lP
|
|||
taseditor_config.enable_auto_function ^= 1;
|
||||
taseditor_window.UpdateCheckedItems();
|
||||
break;
|
||||
case ID_HELP_TASEDITHELP:
|
||||
{
|
||||
std::string helpFileName = BaseDirectory;
|
||||
helpFileName.append(taseditor_help_filename);
|
||||
HtmlHelp(GetDesktopWindow(), helpFileName.c_str(), HH_DISPLAY_TOPIC, (DWORD)NULL);
|
||||
break;
|
||||
}
|
||||
case ID_HELP_TOOLTIPS:
|
||||
taseditor_config.tooltips ^= 1;
|
||||
taseditor_window.UpdateCheckedItems();
|
||||
taseditor_window.UpdateTooltips();
|
||||
break;
|
||||
case ID_HELP_ABOUT:
|
||||
DialogBox(fceu_hInstance, MAKEINTRESOURCE(IDD_TASEDITOR_ABOUT), taseditor_window.hwndTasEditor, AboutProc);
|
||||
break;
|
||||
|
||||
|
||||
}
|
||||
|
@ -1252,20 +1343,3 @@ BOOL CALLBACK WndprocTasEditor(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lP
|
|||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
|
|
@ -1,5 +1,7 @@
|
|||
//Specification file for TASEDITOR_WINDOW class
|
||||
#define TASEDITOR_WINDOW_TOTAL_ITEMS 42
|
||||
#define TOOLTIP_TEXT_MAX_LEN 80
|
||||
#define TOOLTIPS_AUTOPOP_TIMEOUT 30000
|
||||
|
||||
enum ECONTEXTMENU
|
||||
{
|
||||
|
@ -16,11 +18,11 @@ public:
|
|||
void reset();
|
||||
void update();
|
||||
|
||||
void CalculateItems();
|
||||
void ResizeItems();
|
||||
|
||||
void WindowMovedOrResized();
|
||||
|
||||
void UpdateTooltips();
|
||||
|
||||
void UpdateCaption();
|
||||
void RedrawTaseditor();
|
||||
|
||||
|
@ -36,13 +38,16 @@ public:
|
|||
void LoadRecentProject(int slot);
|
||||
|
||||
HWND hwndTasEditor, hwndFindNote;
|
||||
HMENU hmenu, hrmenu;
|
||||
HICON hTaseditorIcon;
|
||||
bool TASEditor_focus;
|
||||
bool ready_for_resizing;
|
||||
int min_width;
|
||||
int min_height;
|
||||
|
||||
private:
|
||||
void CalculateItems();
|
||||
|
||||
HWND hToolTipWnd;
|
||||
HMENU hmenu, hrmenu;
|
||||
HICON hTaseditorIcon;
|
||||
|
||||
};
|
||||
|
|
|
@ -718,11 +718,6 @@ void FCEUI_Emulate(uint8 **pXBuf, int32 **SoundBuf, int32 *SoundBufSize, int ski
|
|||
|
||||
if (movieSubtitles)
|
||||
ProcessSubtitles();
|
||||
|
||||
#ifdef WIN32
|
||||
if(FCEUMOV_Mode(MOVIEMODE_TASEDITOR))
|
||||
greenzone.TryDumpIncremental(lagFlag != 0);
|
||||
#endif
|
||||
}
|
||||
|
||||
void FCEUI_CloseGame(void)
|
||||
|
|
|
@ -54,11 +54,14 @@
|
|||
|
||||
#include "./drivers/win/taseditor/taseditor_window.h"
|
||||
#include "./drivers/win/taseditor/markers.h"
|
||||
#include "./drivers/win/taseditor/inputsnapshot.h"
|
||||
#include "./drivers/win/taseditor/taseditor_sel.h"
|
||||
#include "./drivers/win/taseditor/snapshot.h"
|
||||
#include "./drivers/win/taseditor/bookmarks.h"
|
||||
#include "./drivers/win/taseditor/playback.h"
|
||||
extern bool Taseditor_rewind_now;
|
||||
extern BOOKMARKS bookmarks;
|
||||
extern TASEDITOR_WINDOW taseditor_window;
|
||||
extern PLAYBACK playback;
|
||||
#endif // WIN32
|
||||
|
||||
//it is easier to declare these input drivers extern here than include a bunch of files
|
||||
|
@ -656,6 +659,7 @@ static void FCEUI_DoExit(void);
|
|||
static void ToggleFullscreen(void);
|
||||
static void TaseditorRewindOn(void);
|
||||
static void TaseditorRewindOff(void);
|
||||
static void TaseditorRestorePlayback(void);
|
||||
|
||||
struct EMUCMDTABLE FCEUI_CommandTable[]=
|
||||
{
|
||||
|
@ -686,7 +690,7 @@ struct EMUCMDTABLE FCEUI_CommandTable[]=
|
|||
{ EMUCMD_SAVE_SLOT_9, EMUCMDTYPE_STATE, CommandSelectSaveSlot, 0, 0, "Savestate Slot 9", EMUCMDFLAG_TASEDITOR },
|
||||
{ EMUCMD_SAVE_SLOT_NEXT, EMUCMDTYPE_STATE, CommandSelectSaveSlot, 0, 0, "Next Savestate Slot", 0 },
|
||||
{ EMUCMD_SAVE_SLOT_PREV, EMUCMDTYPE_STATE, CommandSelectSaveSlot, 0, 0, "Previous Savestate Slot", 0 },
|
||||
{ EMUCMD_SAVE_STATE, EMUCMDTYPE_STATE, CommandStateSave, 0, 0, "Save State", 0 },
|
||||
{ EMUCMD_SAVE_STATE, EMUCMDTYPE_STATE, CommandStateSave, 0, 0, "Save State", EMUCMDFLAG_TASEDITOR },
|
||||
{ EMUCMD_SAVE_STATE_AS, EMUCMDTYPE_STATE, FCEUD_SaveStateAs, 0, 0, "Save State As...", 0 },
|
||||
{ EMUCMD_SAVE_STATE_SLOT_0, EMUCMDTYPE_STATE, CommandStateSave, 0, 0, "Save State to Slot 0", EMUCMDFLAG_TASEDITOR },
|
||||
{ EMUCMD_SAVE_STATE_SLOT_1, EMUCMDTYPE_STATE, CommandStateSave, 0, 0, "Save State to Slot 1", EMUCMDFLAG_TASEDITOR },
|
||||
|
@ -698,7 +702,7 @@ struct EMUCMDTABLE FCEUI_CommandTable[]=
|
|||
{ EMUCMD_SAVE_STATE_SLOT_7, EMUCMDTYPE_STATE, CommandStateSave, 0, 0, "Save State to Slot 7", EMUCMDFLAG_TASEDITOR },
|
||||
{ EMUCMD_SAVE_STATE_SLOT_8, EMUCMDTYPE_STATE, CommandStateSave, 0, 0, "Save State to Slot 8", EMUCMDFLAG_TASEDITOR },
|
||||
{ EMUCMD_SAVE_STATE_SLOT_9, EMUCMDTYPE_STATE, CommandStateSave, 0, 0, "Save State to Slot 9", EMUCMDFLAG_TASEDITOR },
|
||||
{ EMUCMD_LOAD_STATE, EMUCMDTYPE_STATE, CommandStateLoad, 0, 0, "Load State", 0 },
|
||||
{ EMUCMD_LOAD_STATE, EMUCMDTYPE_STATE, CommandStateLoad, 0, 0, "Load State", EMUCMDFLAG_TASEDITOR },
|
||||
{ EMUCMD_LOAD_STATE_FROM, EMUCMDTYPE_STATE, FCEUD_LoadStateFrom, 0, 0, "Load State From...", 0 },
|
||||
{ EMUCMD_LOAD_STATE_SLOT_0, EMUCMDTYPE_STATE, CommandStateLoad, 0, 0, "Load State from Slot 0", EMUCMDFLAG_TASEDITOR },
|
||||
{ EMUCMD_LOAD_STATE_SLOT_1, EMUCMDTYPE_STATE, CommandStateLoad, 0, 0, "Load State from Slot 1", EMUCMDFLAG_TASEDITOR },
|
||||
|
@ -779,8 +783,9 @@ struct EMUCMDTABLE FCEUI_CommandTable[]=
|
|||
{ EMUCMD_TOOL_RAMSEARCHGTE, EMUCMDTYPE_TOOL, RamSearchOpGTE, 0, 0, "Ram Search - Greater Than or Equal", 0},
|
||||
{ EMUCMD_TOOL_RAMSEARCHEQ, EMUCMDTYPE_TOOL, RamSearchOpEQ, 0, 0, "Ram Search - Equal", 0},
|
||||
{ EMUCMD_TOOL_RAMSEARCHNE, EMUCMDTYPE_TOOL, RamSearchOpNE, 0, 0, "Ram Search - Not Equal", 0},
|
||||
{ EMUCMD_TASEDITOR_REWIND, EMUCMDTYPE_MISC, TaseditorRewindOn, TaseditorRewindOff, 0, "Rewind Frame (TAS Editor only)", EMUCMDFLAG_TASEDITOR },
|
||||
{ EMUCMD_TASEDITOR_REWIND, EMUCMDTYPE_MISC, TaseditorRewindOn, TaseditorRewindOff, 0, "Rewind Frame (TAS Editor)", EMUCMDFLAG_TASEDITOR },
|
||||
{ EMUCMD_RERECORD_DISPLAY_TOGGLE, EMUCMDTYPE_MISC, FCEUI_MovieToggleRerecordDisplay, 0, 0, "Toggle Rerecord Display", EMUCMDFLAG_TASEDITOR },
|
||||
{ EMUCMD_TASEDITOR_RESTORE_PLAYBACK, EMUCMDTYPE_MISC, TaseditorRestorePlayback, 0, 0, "Restore Playback (TAS Editor)", EMUCMDFLAG_TASEDITOR },
|
||||
};
|
||||
|
||||
#define NUM_EMU_CMDS (sizeof(FCEUI_CommandTable)/sizeof(FCEUI_CommandTable[0]))
|
||||
|
@ -840,7 +845,7 @@ static void CommandSelectSaveSlot(void)
|
|||
if (FCEUMOV_Mode(MOVIEMODE_TASEDITOR))
|
||||
{
|
||||
#ifdef WIN32
|
||||
bookmarks.jump(execcmd - EMUCMD_SAVE_SLOT_0);
|
||||
bookmarks.command(COMMAND_JUMP, execcmd - EMUCMD_SAVE_SLOT_0);
|
||||
#endif
|
||||
} else
|
||||
{
|
||||
|
@ -858,7 +863,10 @@ static void CommandStateSave(void)
|
|||
if (FCEUMOV_Mode(MOVIEMODE_TASEDITOR))
|
||||
{
|
||||
#ifdef WIN32
|
||||
bookmarks.set(execcmd - EMUCMD_SAVE_STATE_SLOT_0);
|
||||
if (execcmd == EMUCMD_SAVE_STATE)
|
||||
bookmarks.command(COMMAND_SET, bookmarks.GetCurrentBranch());
|
||||
else if(execcmd >= EMUCMD_SAVE_STATE_SLOT_0 && execcmd <= EMUCMD_SAVE_STATE_SLOT_9)
|
||||
bookmarks.command(COMMAND_SET, execcmd - EMUCMD_SAVE_STATE_SLOT_0);
|
||||
#endif
|
||||
} else
|
||||
{
|
||||
|
@ -879,7 +887,10 @@ static void CommandStateLoad(void)
|
|||
if (FCEUMOV_Mode(MOVIEMODE_TASEDITOR))
|
||||
{
|
||||
#ifdef WIN32
|
||||
bookmarks.unleash(execcmd - EMUCMD_LOAD_STATE_SLOT_0);
|
||||
if (execcmd == EMUCMD_LOAD_STATE)
|
||||
bookmarks.command(COMMAND_DEPLOY, bookmarks.GetCurrentBranch());
|
||||
else if(execcmd >= EMUCMD_LOAD_STATE_SLOT_0 && execcmd <= EMUCMD_LOAD_STATE_SLOT_9)
|
||||
bookmarks.command(COMMAND_DEPLOY, execcmd - EMUCMD_LOAD_STATE_SLOT_0);
|
||||
#endif
|
||||
} else
|
||||
{
|
||||
|
@ -1177,4 +1188,10 @@ static void TaseditorRewindOff(void)
|
|||
#endif
|
||||
}
|
||||
|
||||
static void TaseditorRestorePlayback(void)
|
||||
{
|
||||
#ifdef WIN32
|
||||
playback.restorePosition();
|
||||
#endif
|
||||
}
|
||||
|
||||
|
|
|
@ -232,9 +232,10 @@ enum EMUCMD
|
|||
EMUCMD_TOOL_RAMSEARCHNE,
|
||||
EMUCMD_TOOL_OPENNTVIEW,
|
||||
EMUCMD_TASEDITOR_REWIND,
|
||||
EMUCMD_RERECORD_DISPLAY_TOGGLE,
|
||||
//-----------------------------
|
||||
//keep adding these in order of newness or else the hotkey binding configs will get messed up...
|
||||
EMUCMD_RERECORD_DISPLAY_TOGGLE,
|
||||
EMUCMD_TASEDITOR_RESTORE_PLAYBACK,
|
||||
|
||||
EMUCMD_MAX
|
||||
};
|
||||
|
|
|
@ -40,6 +40,9 @@
|
|||
|
||||
#ifdef WIN32
|
||||
#include "drivers/win/common.h"
|
||||
#include "drivers/win/taseditor/taseditor_sel.h"
|
||||
#include "drivers/win/taseditor/markers.h"
|
||||
#include "drivers/win/taseditor/snapshot.h"
|
||||
#include "drivers/win/taseditor/taseditor_lua.h"
|
||||
extern TASEDITOR_LUA taseditor_lua;
|
||||
#endif
|
||||
|
@ -2709,7 +2712,7 @@ int movie_isplaying (lua_State *L) {
|
|||
//
|
||||
//returns the rerecord count of the current movie
|
||||
static int movie_rerecordcount (lua_State *L) {
|
||||
if (!FCEUMOV_IsRecording() && !FCEUMOV_IsPlaying())
|
||||
if (!FCEUMOV_IsRecording() && !FCEUMOV_IsPlaying() && !FCEUMOV_Mode(MOVIEMODE_TASEDITOR))
|
||||
luaL_error(L, "No movie loaded.");
|
||||
|
||||
lua_pushinteger(L, FCEUI_GetMovieRerecordCount());
|
||||
|
@ -2722,7 +2725,7 @@ static int movie_rerecordcount (lua_State *L) {
|
|||
//returns an int value representing the total length of the current movie loaded
|
||||
|
||||
static int movie_getlength (lua_State *L) {
|
||||
if (!FCEUMOV_IsRecording() && !FCEUMOV_IsPlaying())
|
||||
if (!FCEUMOV_IsRecording() && !FCEUMOV_IsPlaying() && !FCEUMOV_Mode(MOVIEMODE_TASEDITOR))
|
||||
luaL_error(L, "No movie loaded.");
|
||||
|
||||
lua_pushinteger(L, FCEUI_GetMovieLength());
|
||||
|
@ -2754,7 +2757,7 @@ static int movie_setreadonly (lua_State *L) {
|
|||
//returns the filename of the movie loaded
|
||||
static int movie_getname (lua_State *L) {
|
||||
|
||||
if (!FCEUMOV_IsRecording() && !FCEUMOV_IsPlaying())
|
||||
if (!FCEUMOV_IsRecording() && !FCEUMOV_IsPlaying() && !FCEUMOV_Mode(MOVIEMODE_TASEDITOR))
|
||||
luaL_error(L, "No movie loaded.");
|
||||
|
||||
std::string name = FCEUI_GetMovieName();
|
||||
|
@ -2767,7 +2770,7 @@ static int movie_getname (lua_State *L) {
|
|||
//returns the filename of movie loaded with no path
|
||||
static int movie_getfilename (lua_State *L) {
|
||||
|
||||
if (!FCEUMOV_IsRecording() && !FCEUMOV_IsPlaying())
|
||||
if (!FCEUMOV_IsRecording() && !FCEUMOV_IsPlaying() && !FCEUMOV_Mode(MOVIEMODE_TASEDITOR))
|
||||
luaL_error(L, "No movie loaded.");
|
||||
|
||||
std::string name = FCEUI_GetMovieName();
|
||||
|
@ -4418,6 +4421,17 @@ static int taseditor_getrecordermode(lua_State *L)
|
|||
return 1;
|
||||
}
|
||||
|
||||
// int taseditor.getlostplayback()
|
||||
static int taseditor_getlostplayback(lua_State *L)
|
||||
{
|
||||
#ifdef WIN32
|
||||
lua_pushinteger(L, taseditor_lua.getlostplayback());
|
||||
#else
|
||||
lua_pushinteger(L, -1);
|
||||
#endif
|
||||
return 1;
|
||||
}
|
||||
|
||||
// int taseditor.getplaybacktarget()
|
||||
static int taseditor_getplaybacktarget(lua_State *L)
|
||||
{
|
||||
|
@ -4447,8 +4461,124 @@ static int taseditor_stopseeking(lua_State *L)
|
|||
return 0;
|
||||
}
|
||||
|
||||
// table taseditor.getselection()
|
||||
static int taseditor_getselection(lua_State *L)
|
||||
{
|
||||
#ifdef WIN32
|
||||
// create temp vector and provide its reference to TAS Editor for filling the vector with data
|
||||
std::vector<int> cur_set;
|
||||
taseditor_lua.getselection(cur_set);
|
||||
int size = cur_set.size();
|
||||
if (size)
|
||||
{
|
||||
lua_createtable(L, size, 0);
|
||||
for (int i = 0; i < size; ++i)
|
||||
{
|
||||
lua_pushinteger(L, cur_set[i]);
|
||||
lua_rawseti(L, -2, i + 1);
|
||||
}
|
||||
} else
|
||||
{
|
||||
lua_pushnil(L);
|
||||
}
|
||||
#else
|
||||
lua_pushnil(L);
|
||||
#endif
|
||||
return 1;
|
||||
}
|
||||
|
||||
// taseditor.setselection(table new_set)
|
||||
static int taseditor_setselection(lua_State *L)
|
||||
{
|
||||
#ifdef WIN32
|
||||
std::vector<int> cur_set;
|
||||
// retrieve new_set data from table to vector
|
||||
if (!lua_isnil(L, 1))
|
||||
{
|
||||
luaL_checktype(L, 1, LUA_TTABLE);
|
||||
int max_index = luaL_getn(L, 1);
|
||||
int i = 1;
|
||||
while (i <= max_index)
|
||||
{
|
||||
lua_rawgeti(L, 1, i);
|
||||
cur_set.push_back(lua_tonumber(L, -1));
|
||||
lua_pop(L, 1);
|
||||
i++;
|
||||
}
|
||||
}
|
||||
// and provide its reference to TAS Editor for changing selection
|
||||
taseditor_lua.setselection(cur_set);
|
||||
#endif
|
||||
return 0;
|
||||
}
|
||||
|
||||
// int taseditor.getinput(int frame, int joypad)
|
||||
static int taseditor_getinput(lua_State *L)
|
||||
{
|
||||
#ifdef WIN32
|
||||
lua_pushinteger(L, taseditor_lua.getinput(luaL_checkinteger(L, 1), luaL_checkinteger(L, 2)));
|
||||
#else
|
||||
lua_pushinteger(L, -1);
|
||||
#endif
|
||||
return 1;
|
||||
}
|
||||
|
||||
// taseditor.submitinputchange(int frame, int joypad, int input)
|
||||
static int taseditor_submitinputchange(lua_State *L)
|
||||
{
|
||||
#ifdef WIN32
|
||||
taseditor_lua.submitinputchange(luaL_checkinteger(L, 1), luaL_checkinteger(L, 2), luaL_checkinteger(L, 3));
|
||||
#endif
|
||||
return 0;
|
||||
}
|
||||
|
||||
// taseditor.submitinsertframes(int frame, int joypad, int input)
|
||||
static int taseditor_submitinsertframes(lua_State *L)
|
||||
{
|
||||
#ifdef WIN32
|
||||
taseditor_lua.submitinsertframes(luaL_checkinteger(L, 1), luaL_checkinteger(L, 2));
|
||||
#endif
|
||||
return 0;
|
||||
}
|
||||
|
||||
// taseditor.submitdeleteframes(int frame, int joypad, int input)
|
||||
static int taseditor_submitdeleteframes(lua_State *L)
|
||||
{
|
||||
#ifdef WIN32
|
||||
taseditor_lua.submitdeleteframes(luaL_checkinteger(L, 1), luaL_checkinteger(L, 2));
|
||||
#endif
|
||||
return 0;
|
||||
}
|
||||
|
||||
// int taseditor.applyinputchanges([string name])
|
||||
static int taseditor_applyinputchanges(lua_State *L)
|
||||
{
|
||||
#ifdef WIN32
|
||||
if (lua_isnil(L, 1))
|
||||
{
|
||||
lua_pushinteger(L, taseditor_lua.applyinputchanges(""));
|
||||
} else
|
||||
{
|
||||
const char* name = lua_tostring(L, 1);
|
||||
if (name)
|
||||
lua_pushinteger(L, taseditor_lua.applyinputchanges(name));
|
||||
else
|
||||
lua_pushinteger(L, taseditor_lua.applyinputchanges(""));
|
||||
}
|
||||
#else
|
||||
lua_pushinteger(L, -1);
|
||||
#endif
|
||||
return 1;
|
||||
}
|
||||
|
||||
// taseditor.clearinputchanges()
|
||||
static int taseditor_clearinputchanges(lua_State *L)
|
||||
{
|
||||
#ifdef WIN32
|
||||
taseditor_lua.clearinputchanges();
|
||||
#endif
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
static int doPopup(lua_State *L, const char* deftype, const char* deficon) {
|
||||
|
@ -5221,9 +5351,18 @@ static const struct luaL_reg taseditorlib[] = {
|
|||
{"setnote", taseditor_setnote},
|
||||
{"getcurrentbranch", taseditor_getcurrentbranch},
|
||||
{"getrecordermode", taseditor_getrecordermode},
|
||||
{"getlostplayback", taseditor_getlostplayback},
|
||||
{"getplaybacktarget", taseditor_getplaybacktarget},
|
||||
{"setplayback", taseditor_setplayback},
|
||||
{"stopseeking", taseditor_stopseeking},
|
||||
{"getselection", taseditor_getselection},
|
||||
{"setselection", taseditor_setselection},
|
||||
{"getinput", taseditor_getinput},
|
||||
{"submitinputchange", taseditor_submitinputchange},
|
||||
{"submitinsertframes", taseditor_submitinsertframes},
|
||||
{"submitdeleteframes", taseditor_submitdeleteframes},
|
||||
{"applyinputchanges", taseditor_applyinputchanges},
|
||||
{"clearinputchanges", taseditor_clearinputchanges},
|
||||
{NULL,NULL}
|
||||
};
|
||||
|
||||
|
|
|
@ -979,9 +979,9 @@ void FCEUMOV_AddInputState()
|
|||
#ifdef _WIN32
|
||||
if(movieMode == MOVIEMODE_TASEDITOR)
|
||||
{
|
||||
// if movie length is less than currFrame, pad it with empty frames
|
||||
if((int)currMovieData.records.size() <= currFrameCounter)
|
||||
currMovieData.insertEmpty(-1, 1 + currFrameCounter - (int)currMovieData.records.size());
|
||||
// if movie length is less or equal to currFrame, pad it with empty frames
|
||||
if((int)currMovieData.records.size()-1 <= currFrameCounter)
|
||||
currMovieData.insertEmpty(-1, 2 + currFrameCounter - (int)currMovieData.records.size());
|
||||
|
||||
MovieRecord* mr = &currMovieData.records[currFrameCounter];
|
||||
if(movie_readonly || turbo || playback.pause_frame > currFrameCounter)
|
||||
|
@ -1001,6 +1001,9 @@ void FCEUMOV_AddInputState()
|
|||
joyports[0].log(mr);
|
||||
joyports[1].log(mr);
|
||||
recorder.InputChanged();
|
||||
// return data from movie to joyports in case Recorder changed it (for example, by applying Superimpose)
|
||||
joyports[0].load(mr);
|
||||
joyports[1].load(mr);
|
||||
}
|
||||
_currCommand = 0;
|
||||
} else
|
||||
|
|
|
@ -424,12 +424,13 @@
|
|||
<ClCompile Include="..\src\drivers\win\taseditor\bookmark.cpp" />
|
||||
<ClCompile Include="..\src\drivers\win\taseditor\bookmarks.cpp" />
|
||||
<ClCompile Include="..\src\drivers\win\taseditor\greenzone.cpp" />
|
||||
<ClCompile Include="..\src\drivers\win\taseditor\inputhistory.cpp" />
|
||||
<ClCompile Include="..\src\drivers\win\taseditor\inputsnapshot.cpp" />
|
||||
<ClCompile Include="..\src\drivers\win\taseditor\history.cpp" />
|
||||
<ClCompile Include="..\src\drivers\win\taseditor\markers.cpp" />
|
||||
<ClCompile Include="..\src\drivers\win\taseditor\markers_manager.cpp" />
|
||||
<ClCompile Include="..\src\drivers\win\taseditor\playback.cpp" />
|
||||
<ClCompile Include="..\src\drivers\win\taseditor\popup_display.cpp" />
|
||||
<ClCompile Include="..\src\drivers\win\taseditor\recorder.cpp" />
|
||||
<ClCompile Include="..\src\drivers\win\taseditor\snapshot.cpp" />
|
||||
<ClCompile Include="..\src\drivers\win\taseditor\splicer.cpp" />
|
||||
<ClCompile Include="..\src\drivers\win\taseditor\taseditor_config.cpp" />
|
||||
<ClCompile Include="..\src\drivers\win\taseditor\taseditor_list.cpp" />
|
||||
|
@ -750,12 +751,13 @@
|
|||
<ClInclude Include="..\src\drivers\win\taseditor\bookmark.h" />
|
||||
<ClInclude Include="..\src\drivers\win\taseditor\bookmarks.h" />
|
||||
<ClInclude Include="..\src\drivers\win\taseditor\greenzone.h" />
|
||||
<ClInclude Include="..\src\drivers\win\taseditor\inputhistory.h" />
|
||||
<ClInclude Include="..\src\drivers\win\taseditor\inputsnapshot.h" />
|
||||
<ClInclude Include="..\src\drivers\win\taseditor\history.h" />
|
||||
<ClInclude Include="..\src\drivers\win\taseditor\markers.h" />
|
||||
<ClInclude Include="..\src\drivers\win\taseditor\markers_manager.h" />
|
||||
<ClInclude Include="..\src\drivers\win\taseditor\playback.h" />
|
||||
<ClInclude Include="..\src\drivers\win\taseditor\popup_display.h" />
|
||||
<ClInclude Include="..\src\drivers\win\taseditor\recorder.h" />
|
||||
<ClInclude Include="..\src\drivers\win\taseditor\snapshot.h" />
|
||||
<ClInclude Include="..\src\drivers\win\taseditor\splicer.h" />
|
||||
<ClInclude Include="..\src\drivers\win\taseditor\taseditor_config.h" />
|
||||
<ClInclude Include="..\src\drivers\win\taseditor\taseditor_list.h" />
|
||||
|
@ -866,6 +868,8 @@
|
|||
<ResourceCompile Include="..\src\drivers\win\res.rc" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<None Include="..\..\..\tasedit\psd\bmp\te_green_arrow.bmp" />
|
||||
<None Include="..\src\drivers\win\res\bitmap20.bmp" />
|
||||
<None Include="..\src\drivers\win\res\branch_spritesheet.bmp" />
|
||||
<None Include="..\src\drivers\win\res\icon3.ico" />
|
||||
<None Include="..\src\drivers\win\res\icon4.ico" />
|
||||
|
@ -908,6 +912,7 @@
|
|||
</Command>
|
||||
<Outputs Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">$(OutDir)auxlib.lua;%(Outputs)</Outputs>
|
||||
</CustomBuild>
|
||||
<None Include="..\src\drivers\win\res\te_green_arrow.bmp" />
|
||||
<None Include="..\src\pputile.inc" />
|
||||
<None Include="ClassDiagram1.cd" />
|
||||
</ItemGroup>
|
||||
|
|
|
@ -940,12 +940,6 @@
|
|||
<ClCompile Include="..\src\drivers\win\taseditor\greenzone.cpp">
|
||||
<Filter>drivers\win\taseditor</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\src\drivers\win\taseditor\inputhistory.cpp">
|
||||
<Filter>drivers\win\taseditor</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\src\drivers\win\taseditor\inputsnapshot.cpp">
|
||||
<Filter>drivers\win\taseditor</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\src\drivers\win\taseditor\markers.cpp">
|
||||
<Filter>drivers\win\taseditor</Filter>
|
||||
</ClCompile>
|
||||
|
@ -955,6 +949,15 @@
|
|||
<ClCompile Include="..\src\drivers\win\taseditor\popup_display.cpp">
|
||||
<Filter>drivers\win\taseditor</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\src\drivers\win\taseditor\history.cpp">
|
||||
<Filter>drivers\win\taseditor</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\src\drivers\win\taseditor\snapshot.cpp">
|
||||
<Filter>drivers\win\taseditor</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\src\drivers\win\taseditor\markers_manager.cpp">
|
||||
<Filter>drivers\win\taseditor</Filter>
|
||||
</ClCompile>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClInclude Include="..\src\cart.h">
|
||||
|
@ -1432,18 +1435,21 @@
|
|||
<ClInclude Include="..\src\drivers\win\taseditor\greenzone.h">
|
||||
<Filter>drivers\win\taseditor</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\src\drivers\win\taseditor\inputhistory.h">
|
||||
<Filter>drivers\win\taseditor</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\src\drivers\win\taseditor\inputsnapshot.h">
|
||||
<Filter>drivers\win\taseditor</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\src\drivers\win\taseditor\markers.h">
|
||||
<Filter>drivers\win\taseditor</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\src\drivers\win\taseditor\playback.h">
|
||||
<Filter>drivers\win\taseditor</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\src\drivers\win\taseditor\history.h">
|
||||
<Filter>drivers\win\taseditor</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\src\drivers\win\taseditor\snapshot.h">
|
||||
<Filter>drivers\win\taseditor</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\src\drivers\win\taseditor\markers_manager.h">
|
||||
<Filter>drivers\win\taseditor</Filter>
|
||||
</ClInclude>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ResourceCompile Include="..\src\drivers\win\res.rc">
|
||||
|
@ -1529,6 +1535,9 @@
|
|||
<None Include="..\src\drivers\win\res\icon4.ico" />
|
||||
<None Include="..\src\drivers\win\res\taseditor-icon.ico" />
|
||||
<None Include="..\src\drivers\win\res\taseditor-icon32.ico" />
|
||||
<None Include="..\src\drivers\win\res\bitmap20.bmp" />
|
||||
<None Include="..\..\..\tasedit\psd\bmp\te_green_arrow.bmp" />
|
||||
<None Include="..\src\drivers\win\res\te_green_arrow.bmp" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<CustomBuild Include="..\src\auxlib.lua" />
|
||||
|
|
Loading…
Reference in New Issue