* Tasedit: View->Show Branch Screenshots
* Tasedit: selection history, undo/redo (Ctrl-Q/Ctrl-W) * Tasedit: Reselect Clipboard (Ctrl-B) * Tasedit: saving/loading selection history to .tas * Tasedit: input hotchanges (16 gradations), storing/handling data inside input_snapshot class * Tasedit: View->Enable Hot Changes
This commit is contained in:
parent
170bcefdd2
commit
514c80e416
|
@ -71,13 +71,14 @@ extern int frameSkipAmt;
|
|||
extern bool TASEdit_follow_playback;
|
||||
extern bool TASEdit_show_lag_frames;
|
||||
extern bool TASEdit_show_markers;
|
||||
extern bool TASEdit_show_branch_screenshots;
|
||||
extern bool TASEdit_bind_markers;
|
||||
extern bool TASEdit_branch_full_movie;
|
||||
extern bool TASEdit_branch_only_when_rec;
|
||||
extern bool TASEdit_view_branches_tree;
|
||||
extern bool TASEdit_branch_scr_hud;
|
||||
extern bool TASEdit_restore_position;
|
||||
extern bool TASEdit_show_dot;
|
||||
extern bool TASEdit_enable_hot_changes;
|
||||
extern int TASEdit_greenzone_capacity;
|
||||
extern int TasEdit_undo_levels;
|
||||
extern int TASEdit_autosave_period;
|
||||
|
@ -302,13 +303,14 @@ static CFGSTRUCT fceuconfig[] = {
|
|||
AC(TASEdit_follow_playback),
|
||||
AC(TASEdit_show_lag_frames),
|
||||
AC(TASEdit_show_markers),
|
||||
AC(TASEdit_show_branch_screenshots),
|
||||
AC(TASEdit_bind_markers),
|
||||
AC(TASEdit_branch_full_movie),
|
||||
AC(TASEdit_branch_only_when_rec),
|
||||
AC(TASEdit_view_branches_tree),
|
||||
AC(TASEdit_branch_scr_hud),
|
||||
AC(TASEdit_restore_position),
|
||||
AC(TASEdit_show_dot),
|
||||
AC(TASEdit_enable_hot_changes),
|
||||
AC(TASEdit_greenzone_capacity),
|
||||
AC(TasEdit_undo_levels),
|
||||
AC(TASEdit_autosave_period),
|
||||
|
|
|
@ -221,9 +221,10 @@ TASEDITMENU MENU
|
|||
BEGIN
|
||||
POPUP "&File"
|
||||
BEGIN
|
||||
MENUITEM "&Open Project...", ID_FILE_OPENPROJECT
|
||||
MENUITEM "&Save Project\tCtrl+S", ID_FILE_SAVEPROJECT
|
||||
MENUITEM "S&ave Project As...", ID_FILE_SAVEPROJECTAS
|
||||
MENUITEM "&Open", ID_FILE_OPENPROJECT
|
||||
MENUITEM "&Save\tCtrl+S", ID_FILE_SAVEPROJECT
|
||||
MENUITEM "S&ave As", ID_FILE_SAVEPROJECTAS
|
||||
MENUITEM "Save &Compact", ID_FILE_SAVECOMPACT, INACTIVE
|
||||
MENUITEM "&Recent", ID_TASEDIT_FILE_RECENT
|
||||
MENUITEM SEPARATOR
|
||||
MENUITEM "&Import FM2", ID_FILE_IMPORTFM2, INACTIVE
|
||||
|
@ -233,29 +234,33 @@ BEGIN
|
|||
END
|
||||
POPUP "&Edit"
|
||||
BEGIN
|
||||
MENUITEM "&Undo\tCtrl+Z", ID_EDIT_UNDO
|
||||
MENUITEM "&Redo\tCtrl+Y", ID_EDIT_REDO
|
||||
MENUITEM "Selection Undo\tCtrl+Q", ID_EDIT_SELECTIONUNDO
|
||||
MENUITEM "Selection Redo\tCtrl+W", ID_EDIT_SELECTIONREDO
|
||||
MENUITEM SEPARATOR
|
||||
MENUITEM "Select &All", ID_EDIT_SELECTALL
|
||||
MENUITEM "Select mid &Markers\tCtrl+A", ID_EDIT_SELECTMIDMARKERS
|
||||
MENUITEM "Reselect Clipboard\tCtrl+B", ID_EDIT_RESELECTCLIPBOARD
|
||||
MENUITEM SEPARATOR
|
||||
MENUITEM "Cu&t\tCtrl+X", ID_TASEDIT_CUT
|
||||
MENUITEM "&Copy\tCtrl+C", ID_TASEDIT_COPY
|
||||
MENUITEM "&Paste\tCtrl+V", ID_TASEDIT_PASTE
|
||||
MENUITEM "Cu&t\tCtrl+X", ID_TASEDIT_CUT
|
||||
MENUITEM SEPARATOR
|
||||
MENUITEM "C&lear\tDelete", ID_EDIT_CLEAR
|
||||
MENUITEM "C&lear\tDel", ID_EDIT_CLEAR
|
||||
MENUITEM "&Delete\tCtrl+Del", ID_TASEDIT_DELETE
|
||||
MENUITEM "&Insert\tCtrl+Ins", ID_EDIT_INSERTFRAMES
|
||||
MENUITEM "Insert # of Frames\tInsert", ID_EDIT_INSERT
|
||||
MENUITEM "Insert # of Frames\tIns", ID_EDIT_INSERT
|
||||
MENUITEM "Cl&one\tShift+Ins", ID_EDIT_CLONEFRAMES
|
||||
MENUITEM SEPARATOR
|
||||
MENUITEM "Truncate movie\tCtrl+T", ID_EDIT_TRUNCATE
|
||||
MENUITEM SEPARATOR
|
||||
MENUITEM "&Undo\tCtrl-Z", ID_EDIT_UNDO
|
||||
MENUITEM "&Redo\tCtrl-Y", ID_EDIT_REDO
|
||||
MENUITEM "Truncate\tCtrl+T", ID_EDIT_TRUNCATE
|
||||
END
|
||||
POPUP "&View"
|
||||
BEGIN
|
||||
MENUITEM "Highlight &Lag Frames", ID_VIEW_SHOW_LAG_FRAMES
|
||||
MENUITEM "Show &Markers", ID_VIEW_SHOW_MARKERS
|
||||
MENUITEM "Show &dot in empty cells", ID_VIEW_SHOWDOTINEMPTYCELLS
|
||||
MENUITEM "Show Branch &Screenshots", ID_VIEW_SHOWBRANCHSCREENSHOTS
|
||||
MENUITEM "Enable Hot &Changes", ID_VIEW_ENABLEHOTCHANGES
|
||||
MENUITEM SEPARATOR
|
||||
MENUITEM "&Follow undo context", ID_VIEW_JUMPWHENMAKINGUNDO
|
||||
END
|
||||
|
@ -275,7 +280,8 @@ BEGIN
|
|||
END
|
||||
POPUP "&Help"
|
||||
BEGIN
|
||||
MENUITEM "&TASEdit Help...", ID_HELP_TASEDITHELP
|
||||
MENUITEM "&TASEdit Help", ID_HELP_TASEDITHELP
|
||||
MENUITEM "&About", ID_HELP_ABOUT
|
||||
END
|
||||
END
|
||||
|
||||
|
@ -1997,15 +2003,18 @@ BEGIN
|
|||
"F", ACCEL_CTRL_F, VIRTKEY, CONTROL, NOINVERT
|
||||
VK_INSERT, ACCEL_CTRL_INSERT, VIRTKEY, CONTROL, NOINVERT
|
||||
"P", ACCEL_CTRL_P, 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
|
||||
"Y", ACCEL_CTRL_Y, VIRTKEY, CONTROL, NOINVERT
|
||||
"Z", ACCEL_CTRL_Z, VIRTKEY, CONTROL, NOINVERT
|
||||
VK_DELETE, ACCEL_DEL, VIRTKEY, NOINVERT
|
||||
VK_INSERT, ACCEL_INS, VIRTKEY, NOINVERT
|
||||
VK_INSERT, ACCEL_SHIFT_INS, VIRTKEY, SHIFT, NOINVERT
|
||||
"B", ACCEL_CTRL_B, VIRTKEY, CONTROL, NOINVERT
|
||||
END
|
||||
|
||||
IDR_RWACCELERATOR ACCELERATORS
|
||||
|
|
|
@ -893,6 +893,14 @@
|
|||
#define ID_CONFIG_BRANCHESWORKONLYWHENRECORDING 40474
|
||||
#define ID_CONFIG_HUDINBRANCHSCREENSHOTS 40475
|
||||
#define ID_CONFIG_SETAUTOSAVEPERIOD 40476
|
||||
#define ACCEL_CTRL_Q 40478
|
||||
#define ID_EDIT_SELECTIONUNDO 40481
|
||||
#define ID_EDIT_SELECTIONREDO 40482
|
||||
#define ID_EDIT_RESELECTCLIPBOARD 40483
|
||||
#define ID_FILE_SAVECOMPACT 40484
|
||||
#define ID_HELP_ABOUT 40485
|
||||
#define ID_VIEW_ENABLEHOTCHANGES 40488
|
||||
#define ID_VIEW_SHOWBRANCHSCREENSHOTS 40489
|
||||
#define IDC_DEBUGGER_ICONTRAY 55535
|
||||
#define MW_ValueLabel2 65423
|
||||
#define MW_ValueLabel1 65426
|
||||
|
@ -902,7 +910,7 @@
|
|||
#ifdef APSTUDIO_INVOKED
|
||||
#ifndef APSTUDIO_READONLY_SYMBOLS
|
||||
#define _APS_NEXT_RESOURCE_VALUE 185
|
||||
#define _APS_NEXT_COMMAND_VALUE 40477
|
||||
#define _APS_NEXT_COMMAND_VALUE 40490
|
||||
#define _APS_NEXT_CONTROL_VALUE 1267
|
||||
#define _APS_NEXT_SYMED_VALUE 101
|
||||
#endif
|
||||
|
|
|
@ -2,7 +2,6 @@
|
|||
#include <fstream>
|
||||
#include <sstream>
|
||||
|
||||
#include "common.h"
|
||||
#include "taseditlib/taseditproj.h"
|
||||
#include "fceu.h"
|
||||
#include "debugger.h"
|
||||
|
@ -18,24 +17,26 @@
|
|||
|
||||
using namespace std;
|
||||
|
||||
//to change header font
|
||||
//http://forums.devx.com/archive/index.php/t-37234.html
|
||||
|
||||
int old_multitrack_recording_joypad, multitrack_recording_joypad;
|
||||
bool old_movie_readonly;
|
||||
bool TASEdit_focus = false;
|
||||
bool Tasedit_rewind_now = false;
|
||||
int listItems; // number of items per list page
|
||||
|
||||
// saved FCEU config
|
||||
int saved_eoptions;
|
||||
int saved_EnableAutosave;
|
||||
extern int EnableAutosave;
|
||||
|
||||
extern HWND hwndScrBmp;
|
||||
extern EMOVIEMODE movieMode; // maybe we need normal setter for movieMode, to encapsulate it
|
||||
|
||||
// vars saved in cfg file
|
||||
int TasEdit_wndx, TasEdit_wndy;
|
||||
bool TASEdit_follow_playback = true;
|
||||
bool TASEdit_show_lag_frames = true;
|
||||
bool TASEdit_show_markers = true;
|
||||
bool TASEdit_show_branch_screenshots = true;
|
||||
bool TASEdit_bind_markers = true;
|
||||
bool TASEdit_branch_full_movie = true;
|
||||
bool TASEdit_branch_only_when_rec = false;
|
||||
|
@ -46,9 +47,10 @@ int TASEdit_greenzone_capacity = GREENZONE_CAPACITY_DEFAULT;
|
|||
int TasEdit_undo_levels = UNDO_LEVELS_DEFAULT;
|
||||
int TASEdit_autosave_period = AUTOSAVE_PERIOD_DEFAULT;
|
||||
extern bool muteTurbo;
|
||||
bool TASEdit_show_dot = true;
|
||||
bool TASEdit_enable_hot_changes = true;
|
||||
bool TASEdit_jump_to_undo = true;
|
||||
|
||||
// resources
|
||||
string tasedithelp = "{16CDE0C4-02B0-4A60-A88D-076319909A4D}"; //Name of TASEdit Help page
|
||||
char buttonNames[NUM_JOYPAD_BUTTONS][2] = {"A", "B", "S", "T", "U", "D", "L", "R"};
|
||||
char windowCaptions[6][30] = { "TAS Editor",
|
||||
|
@ -57,8 +59,7 @@ char windowCaptions[6][30] = { "TAS Editor",
|
|||
"TAS Editor (Recording 2P)",
|
||||
"TAS Editor (Recording 3P)",
|
||||
"TAS Editor (Recording 4P)"};
|
||||
// hot changes color table
|
||||
COLORREF hot_changes_colors[16] = { 0x0, 0x41f2c, 0x62a3b, 0x7344a, 0x93f59, 0xb4968, 0xc5477, 0xe5e86, 0xf6995, 0x1174a4, 0x127eb3, 0x1489c2, 0x1693d1, 0x179ee0, 0x19a8ef, 0x1bb4ff };
|
||||
COLORREF hot_changes_colors[16] = { 0x0, 0x661212, 0x842B4E, 0x652C73, 0x48247D, 0x383596, 0x2947AE, 0x1E53C1, 0x135DD2, 0x116EDA, 0x107EE3, 0x0F8EEB, 0x209FF4, 0x3DB1FD, 0x51C2FF, 0x4DCDFF };
|
||||
|
||||
HWND hwndTasEdit = 0;
|
||||
HMENU hmenu, hrmenu;
|
||||
|
@ -73,14 +74,7 @@ HWND hwndRB_RecOff, hwndRB_RecAll, hwndRB_Rec1P, hwndRB_Rec2P, hwndRB_Rec3P, hwn
|
|||
HWND hwndBranchesBitmap;
|
||||
WNDPROC hwndBranchesBitmap_oldWndProc;
|
||||
|
||||
HFONT hMainListFont;
|
||||
|
||||
typedef std::set<int> TSelectionFrames;
|
||||
static TSelectionFrames selectionFrames;
|
||||
|
||||
//hacky.. we need to think about how to convey information from the driver to the movie code.
|
||||
//add a new fceud_ function?? blehhh maybe
|
||||
extern EMOVIEMODE movieMode;
|
||||
HFONT hMainListFont, hMainListSelectFont;
|
||||
|
||||
// all Taseditor functional modules
|
||||
TASEDIT_PROJECT project;
|
||||
|
@ -89,6 +83,7 @@ PLAYBACK playback;
|
|||
GREENZONE greenzone;
|
||||
MARKERS markers;
|
||||
BOOKMARKS bookmarks;
|
||||
TASEDIT_SELECTION selection;
|
||||
|
||||
void GetDispInfo(NMLVDISPINFO* nmlvDispInfo)
|
||||
{
|
||||
|
@ -113,7 +108,7 @@ void GetDispInfo(NMLVDISPINFO* nmlvDispInfo)
|
|||
case COLUMN_FRAMENUM:
|
||||
case COLUMN_FRAMENUM2:
|
||||
{
|
||||
U32ToDecStr(item.pszText,item.iItem,DIGITS_IN_FRAMENUM);
|
||||
U32ToDecStr(item.pszText, item.iItem, DIGITS_IN_FRAMENUM);
|
||||
break;
|
||||
}
|
||||
case COLUMN_JOYPAD1_A: case COLUMN_JOYPAD1_B: case COLUMN_JOYPAD1_S: case COLUMN_JOYPAD1_T:
|
||||
|
@ -130,13 +125,13 @@ void GetDispInfo(NMLVDISPINFO* nmlvDispInfo)
|
|||
uint8 data = currMovieData.records[item.iItem].joysticks[joy];
|
||||
if(data & (1<<bit))
|
||||
{
|
||||
item.pszText[0] = MovieRecord::mnemonics[bit];
|
||||
item.pszText[1] = 0;
|
||||
item.pszText[0] = buttonNames[bit][0];
|
||||
item.pszText[2] = 0;
|
||||
} else
|
||||
{
|
||||
if (TASEdit_show_dot)
|
||||
if (TASEdit_enable_hot_changes && history.GetCurrentSnapshot().GetHotChangeInfo(item.iItem, item.iSubItem - COLUMN_JOYPAD1_A))
|
||||
{
|
||||
item.pszText[0] = 46; // "."
|
||||
item.pszText[0] = 45; // "-"
|
||||
item.pszText[1] = 0;
|
||||
} else item.pszText[0] = 0;
|
||||
}
|
||||
|
@ -159,11 +154,17 @@ LONG CustomDraw(NMLVCUSTOMDRAW* msg)
|
|||
cell_x = msg->iSubItem;
|
||||
cell_y = msg->nmcd.dwItemSpec;
|
||||
|
||||
//msg->clrText = 0xFF0000;
|
||||
|
||||
|
||||
if(cell_x > COLUMN_ICONS)
|
||||
{
|
||||
SelectObject(msg->nmcd.hdc, hMainListFont);
|
||||
// text color
|
||||
if(TASEdit_enable_hot_changes && cell_x >= COLUMN_JOYPAD1_A && cell_x <= COLUMN_JOYPAD4_R)
|
||||
{
|
||||
msg->clrText = hot_changes_colors[history.GetCurrentSnapshot().GetHotChangeInfo(cell_y, cell_x - COLUMN_JOYPAD1_A)];
|
||||
} else msg->clrText = NORMAL_TEXT_COLOR;
|
||||
// bg color
|
||||
if(cell_x == COLUMN_FRAMENUM || cell_x == COLUMN_FRAMENUM2)
|
||||
{
|
||||
// frame number
|
||||
|
@ -277,13 +278,15 @@ void UpdateTasEdit()
|
|||
{
|
||||
if(!hwndTasEdit) return;
|
||||
|
||||
UpdateList(); // also markers are updated there
|
||||
|
||||
UpdateList();
|
||||
markers.update();
|
||||
greenzone.update();
|
||||
playback.update();
|
||||
bookmarks.update();
|
||||
selection.update();
|
||||
history.update();
|
||||
project.update();
|
||||
selection.update();
|
||||
|
||||
// update window caption
|
||||
if (old_movie_readonly != movie_readonly || old_multitrack_recording_joypad != multitrack_recording_joypad)
|
||||
|
@ -304,28 +307,11 @@ void UpdateTasEdit()
|
|||
|
||||
void UpdateList()
|
||||
{
|
||||
// first update number of items in markers array
|
||||
markers.update();
|
||||
//update the number of items in the list
|
||||
int currLVItemCount = ListView_GetItemCount(hwndList);
|
||||
int movie_size = currMovieData.getNumRecords();
|
||||
if(currLVItemCount != movie_size)
|
||||
{
|
||||
ListView_SetItemCountEx(hwndList,movie_size,LVSICF_NOSCROLL | LVSICF_NOINVALIDATEALL);
|
||||
// also reduce selection if needed
|
||||
if (selectionFrames.size())
|
||||
{
|
||||
int delete_index;
|
||||
while(1)
|
||||
{
|
||||
delete_index = *selectionFrames.rbegin();
|
||||
if (delete_index < movie_size) break;
|
||||
// reduce selection manually, because reduced list won't call ItemChanged for these rows
|
||||
selectionFrames.erase(delete_index);
|
||||
if (!selectionFrames.size()) break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void RedrawWindowCaption()
|
||||
|
@ -370,12 +356,6 @@ void RedrawRowAndBookmark(int index)
|
|||
bookmarks.RedrawChangedBookmarks(index);
|
||||
}
|
||||
|
||||
enum ECONTEXTMENU
|
||||
{
|
||||
CONTEXTMENU_STRAY = 0,
|
||||
CONTEXTMENU_SELECTED = 1,
|
||||
};
|
||||
|
||||
void ShowMenu(ECONTEXTMENU which, POINT& pt)
|
||||
{
|
||||
HMENU sub = GetSubMenu(hrmenu,(int)which);
|
||||
|
@ -408,14 +388,8 @@ void RightClick(LPNMITEMACTIVATE info)
|
|||
return;
|
||||
}
|
||||
|
||||
//make sure that the click is in our currently selected set.
|
||||
//if it is not, then we don't know what to do yet
|
||||
if(selectionFrames.find(index) == selectionFrames.end())
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
RightClickMenu(info);
|
||||
if (selection.CheckFrameSelected(index))
|
||||
RightClickMenu(info);
|
||||
}
|
||||
|
||||
void InputChangedRec()
|
||||
|
@ -430,11 +404,11 @@ void ToggleJoypadBit(int column_index, int row_index, UINT KeyFlags)
|
|||
if (KeyFlags & (LVKF_SHIFT|LVKF_CONTROL))
|
||||
{
|
||||
//update multiple rows
|
||||
for(TSelectionFrames::iterator it(selectionFrames.begin()); it != selectionFrames.end(); it++)
|
||||
for(SelectionFrames::iterator it(selection.CurrentSelection().begin()); it != selection.CurrentSelection().end(); it++)
|
||||
{
|
||||
currMovieData.records[*it].toggleBit(joy,bit);
|
||||
}
|
||||
greenzone.InvalidateAndCheck(history.RegisterChanges(MODTYPE_CHANGE, *selectionFrames.begin(), *selectionFrames.rbegin()));
|
||||
greenzone.InvalidateAndCheck(history.RegisterChanges(MODTYPE_CHANGE, *selection.CurrentSelection().begin(), *selection.CurrentSelection().rbegin()));
|
||||
} else
|
||||
{
|
||||
//update one row
|
||||
|
@ -456,7 +430,7 @@ void SingleClick(LPNMITEMACTIVATE info)
|
|||
if(column_index == COLUMN_ICONS)
|
||||
{
|
||||
// click on the "icons" column - jump to the frame
|
||||
ClearSelection();
|
||||
selection.ClearSelection();
|
||||
playback.jump(row_index);
|
||||
} else if(column_index == COLUMN_FRAMENUM || column_index == COLUMN_FRAMENUM2)
|
||||
{
|
||||
|
@ -491,7 +465,7 @@ void DoubleClick(LPNMITEMACTIVATE info)
|
|||
if(column_index == COLUMN_ICONS || column_index == COLUMN_FRAMENUM || column_index == COLUMN_FRAMENUM2)
|
||||
{
|
||||
// double click sends playback to the frame
|
||||
ClearSelection();
|
||||
selection.ClearSelection();
|
||||
playback.jump(row_index);
|
||||
} else if(column_index >= COLUMN_JOYPAD1_A && column_index <= COLUMN_JOYPAD4_R)
|
||||
{
|
||||
|
@ -501,18 +475,19 @@ void DoubleClick(LPNMITEMACTIVATE info)
|
|||
|
||||
void CloneFrames()
|
||||
{
|
||||
int frames = selectionFrames.size();
|
||||
int frames = selection.CurrentSelection().size();
|
||||
if (!frames) return;
|
||||
|
||||
currMovieData.records.reserve(currMovieData.getNumRecords() + frames);
|
||||
|
||||
//insert frames before each selection, but consecutive selection lines are accounted as single region
|
||||
frames = 1;
|
||||
TSelectionFrames::reverse_iterator next_it;
|
||||
for(TSelectionFrames::reverse_iterator it(selectionFrames.rbegin()); it != selectionFrames.rend(); it++)
|
||||
SelectionFrames::reverse_iterator next_it;
|
||||
for(SelectionFrames::reverse_iterator it(selection.CurrentSelection().rbegin()); it != selection.CurrentSelection().rend(); it++)
|
||||
{
|
||||
next_it = it;
|
||||
next_it++;
|
||||
if (next_it == selectionFrames.rend() || (int)*next_it < ((int)*it - 1))
|
||||
if (next_it == selection.CurrentSelection().rend() || (int)*next_it < ((int)*it - 1))
|
||||
{
|
||||
// end of current region
|
||||
currMovieData.cloneRegion(*it, frames);
|
||||
|
@ -522,24 +497,25 @@ void CloneFrames()
|
|||
} else frames++;
|
||||
}
|
||||
UpdateList();
|
||||
greenzone.InvalidateAndCheck(history.RegisterChanges(MODTYPE_CLONE, *selectionFrames.begin()));
|
||||
greenzone.InvalidateAndCheck(history.RegisterChanges(MODTYPE_CLONE, *selection.CurrentSelection().begin()));
|
||||
}
|
||||
|
||||
void InsertFrames()
|
||||
{
|
||||
int frames = selectionFrames.size();
|
||||
int frames = selection.CurrentSelection().size();
|
||||
if (!frames) return;
|
||||
|
||||
//to keep this from being even slower than it would otherwise be, go ahead and reserve records
|
||||
currMovieData.records.reserve(currMovieData.getNumRecords() + frames);
|
||||
|
||||
//insert frames before each selection, but consecutive selection lines are accounted as single region
|
||||
frames = 1;
|
||||
TSelectionFrames::reverse_iterator next_it;
|
||||
for(TSelectionFrames::reverse_iterator it(selectionFrames.rbegin()); it != selectionFrames.rend(); it++)
|
||||
SelectionFrames::reverse_iterator next_it;
|
||||
for(SelectionFrames::reverse_iterator it(selection.CurrentSelection().rbegin()); it != selection.CurrentSelection().rend(); it++)
|
||||
{
|
||||
next_it = it;
|
||||
next_it++;
|
||||
if (next_it == selectionFrames.rend() || (int)*next_it < ((int)*it - 1))
|
||||
if (next_it == selection.CurrentSelection().rend() || (int)*next_it < ((int)*it - 1))
|
||||
{
|
||||
// end of current region
|
||||
currMovieData.insertEmpty(*it,frames);
|
||||
|
@ -549,15 +525,45 @@ void InsertFrames()
|
|||
} else frames++;
|
||||
}
|
||||
UpdateList();
|
||||
greenzone.InvalidateAndCheck(history.RegisterChanges(MODTYPE_INSERT, *selectionFrames.begin()));
|
||||
greenzone.InvalidateAndCheck(history.RegisterChanges(MODTYPE_INSERT, *selection.CurrentSelection().begin()));
|
||||
}
|
||||
|
||||
void InsertNumFrames()
|
||||
{
|
||||
int frames = selection.CurrentSelection().size();
|
||||
if(CWin32InputBox::GetInteger("Insert number of Frames", "How many frames?", frames, hwndTasEdit) == IDOK)
|
||||
{
|
||||
if (frames > 0)
|
||||
{
|
||||
int index;
|
||||
if (selection.CurrentSelection().size())
|
||||
{
|
||||
// insert at selection
|
||||
index = *selection.CurrentSelection().begin();
|
||||
selection.ClearSelection();
|
||||
} else
|
||||
{
|
||||
// insert at playback cursor
|
||||
index = currFrameCounter;
|
||||
}
|
||||
currMovieData.insertEmpty(index, frames);
|
||||
if (TASEdit_bind_markers)
|
||||
markers.insertEmpty(index, frames);
|
||||
UpdateList();
|
||||
// select inserted rows
|
||||
selection.SetRegionSelection(index, index + frames - 1);
|
||||
greenzone.InvalidateAndCheck(history.RegisterChanges(MODTYPE_INSERT, index));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void DeleteFrames()
|
||||
{
|
||||
int start_index = *selectionFrames.begin();
|
||||
int end_index = *selectionFrames.rbegin();
|
||||
if (selection.CurrentSelection().size() == 0) return;
|
||||
int start_index = *selection.CurrentSelection().begin();
|
||||
int end_index = *selection.CurrentSelection().rbegin();
|
||||
//delete frames on each selection, going backwards
|
||||
for(TSelectionFrames::reverse_iterator it(selectionFrames.rbegin()); it != selectionFrames.rend(); it++)
|
||||
for(SelectionFrames::reverse_iterator it(selection.CurrentSelection().rbegin()); it != selection.CurrentSelection().rend(); it++)
|
||||
{
|
||||
currMovieData.records.erase(currMovieData.records.begin() + *it);
|
||||
if (TASEdit_bind_markers)
|
||||
|
@ -581,24 +587,25 @@ void DeleteFrames()
|
|||
|
||||
void ClearFrames(bool cut)
|
||||
{
|
||||
if (selection.CurrentSelection().size() == 0) return;
|
||||
//clear input on each selection
|
||||
for(TSelectionFrames::iterator it(selectionFrames.begin()); it != selectionFrames.end(); it++)
|
||||
for(SelectionFrames::iterator it(selection.CurrentSelection().begin()); it != selection.CurrentSelection().end(); it++)
|
||||
{
|
||||
currMovieData.records[*it].clear();
|
||||
}
|
||||
if (cut)
|
||||
greenzone.InvalidateAndCheck(history.RegisterChanges(MODTYPE_CUT, *selectionFrames.begin(), *selectionFrames.rbegin()));
|
||||
greenzone.InvalidateAndCheck(history.RegisterChanges(MODTYPE_CUT, *selection.CurrentSelection().begin(), *selection.CurrentSelection().rbegin()));
|
||||
else
|
||||
greenzone.InvalidateAndCheck(history.RegisterChanges(MODTYPE_CLEAR, *selectionFrames.begin(), *selectionFrames.rbegin()));
|
||||
greenzone.InvalidateAndCheck(history.RegisterChanges(MODTYPE_CLEAR, *selection.CurrentSelection().begin(), *selection.CurrentSelection().rbegin()));
|
||||
}
|
||||
|
||||
void Truncate()
|
||||
{
|
||||
int frame = currFrameCounter;
|
||||
if (selectionFrames.size())
|
||||
if (selection.CurrentSelection().size())
|
||||
{
|
||||
frame=*selectionFrames.begin();
|
||||
ClearSelection();
|
||||
frame = *selection.CurrentSelection().begin();
|
||||
selection.ClearSelection();
|
||||
}
|
||||
if (currMovieData.getNumRecords() > frame+1)
|
||||
{
|
||||
|
@ -625,7 +632,7 @@ void ColumnSet(int column)
|
|||
// Markers column
|
||||
//inspect the selected frames, if they are all set, then unset all, else set all
|
||||
bool unset_found = false;
|
||||
for(TSelectionFrames::iterator it(selectionFrames.begin()); it != selectionFrames.end(); it++)
|
||||
for(SelectionFrames::iterator it(selection.CurrentSelection().begin()); it != selection.CurrentSelection().end(); it++)
|
||||
{
|
||||
if(!(markers.markers_array[*it] & MARKER_FLAG_BIT))
|
||||
{
|
||||
|
@ -636,18 +643,18 @@ void ColumnSet(int column)
|
|||
if (unset_found)
|
||||
{
|
||||
// set all
|
||||
for(TSelectionFrames::iterator it(selectionFrames.begin()); it != selectionFrames.end(); it++)
|
||||
for(SelectionFrames::iterator it(selection.CurrentSelection().begin()); it != selection.CurrentSelection().end(); it++)
|
||||
markers.markers_array[*it] |= MARKER_FLAG_BIT;
|
||||
history.RegisterChanges(MODTYPE_MARKER_SET, *selectionFrames.begin(), *selectionFrames.rbegin());
|
||||
history.RegisterChanges(MODTYPE_MARKER_SET, *selection.CurrentSelection().begin(), *selection.CurrentSelection().rbegin());
|
||||
} else
|
||||
{
|
||||
// unset all
|
||||
for(TSelectionFrames::iterator it(selectionFrames.begin()); it != selectionFrames.end(); it++)
|
||||
for(SelectionFrames::iterator it(selection.CurrentSelection().begin()); it != selection.CurrentSelection().end(); it++)
|
||||
markers.markers_array[*it] &= ~MARKER_FLAG_BIT;
|
||||
history.RegisterChanges(MODTYPE_MARKER_UNSET, *selectionFrames.begin(), *selectionFrames.rbegin());
|
||||
history.RegisterChanges(MODTYPE_MARKER_UNSET, *selection.CurrentSelection().begin(), *selection.CurrentSelection().rbegin());
|
||||
}
|
||||
project.SetProjectChanged();
|
||||
ClearSelection();
|
||||
selection.ClearSelection();
|
||||
// no need to RedrawList();
|
||||
} else
|
||||
{
|
||||
|
@ -657,7 +664,7 @@ void ColumnSet(int column)
|
|||
int button = (column - COLUMN_JOYPAD1_A) % NUM_JOYPAD_BUTTONS;
|
||||
//inspect the selected frames, if they are all set, then unset all, else set all
|
||||
bool newValue = false;
|
||||
for(TSelectionFrames::iterator it(selectionFrames.begin()); it != selectionFrames.end(); it++)
|
||||
for(SelectionFrames::iterator it(selection.CurrentSelection().begin()); it != selection.CurrentSelection().end(); it++)
|
||||
{
|
||||
if(!(currMovieData.records[*it].checkBit(joy,button)))
|
||||
{
|
||||
|
@ -666,114 +673,30 @@ void ColumnSet(int column)
|
|||
}
|
||||
}
|
||||
// apply newValue
|
||||
for(TSelectionFrames::iterator it(selectionFrames.begin()); it != selectionFrames.end(); it++)
|
||||
for(SelectionFrames::iterator it(selection.CurrentSelection().begin()); it != selection.CurrentSelection().end(); it++)
|
||||
currMovieData.records[*it].setBitValue(joy,button,newValue);
|
||||
if (newValue)
|
||||
greenzone.InvalidateAndCheck(history.RegisterChanges(MODTYPE_SET, *selectionFrames.begin(), *selectionFrames.rbegin()));
|
||||
greenzone.InvalidateAndCheck(history.RegisterChanges(MODTYPE_SET, *selection.CurrentSelection().begin(), *selection.CurrentSelection().rbegin()));
|
||||
else
|
||||
greenzone.InvalidateAndCheck(history.RegisterChanges(MODTYPE_UNSET, *selectionFrames.begin(), *selectionFrames.rbegin()));
|
||||
greenzone.InvalidateAndCheck(history.RegisterChanges(MODTYPE_UNSET, *selection.CurrentSelection().begin(), *selection.CurrentSelection().rbegin()));
|
||||
}
|
||||
}
|
||||
|
||||
void ClearSelection()
|
||||
{
|
||||
ListView_SetItemState(hwndList, -1, 0, LVIS_FOCUSED|LVIS_SELECTED);
|
||||
}
|
||||
void ClearRowSelection(int index)
|
||||
{
|
||||
ListView_SetItemState(hwndList,index,0, LVIS_SELECTED);
|
||||
}
|
||||
|
||||
void SelectAll()
|
||||
{
|
||||
ListView_SetItemState(hwndList,-1,LVIS_SELECTED, LVIS_SELECTED);
|
||||
RedrawList();
|
||||
}
|
||||
void SelectMidMarkers()
|
||||
{
|
||||
int center, upper_border, lower_border;
|
||||
int upper_marker, lower_marker;
|
||||
int movie_size = currMovieData.getNumRecords();
|
||||
|
||||
// if selection size=0 then playback cursor is selected and serves as center
|
||||
if (selectionFrames.size())
|
||||
{
|
||||
upper_border = center = *selectionFrames.begin();
|
||||
lower_border = *selectionFrames.rbegin();
|
||||
} else lower_border = upper_border = center = currFrameCounter;
|
||||
|
||||
// find markers
|
||||
// searching up starting from center-0
|
||||
for (upper_marker = center; upper_marker >= 0; upper_marker--)
|
||||
if (markers.markers_array[upper_marker] & MARKER_FLAG_BIT) break;
|
||||
// searching down starting from center+1
|
||||
for (lower_marker = center+1; lower_marker < movie_size; ++lower_marker)
|
||||
if (markers.markers_array[lower_marker] & MARKER_FLAG_BIT) break;
|
||||
|
||||
if (upper_marker == -1 && lower_marker == movie_size)
|
||||
{
|
||||
SelectAll();
|
||||
return;
|
||||
}
|
||||
|
||||
//ClearSelection(); - need to clear without clearing focused, because otherwise there's strange bug when quickly pressing Ctrl+A right after clicking on already selected row
|
||||
ListView_SetItemState(hwndList, -1, 0, LVIS_SELECTED);
|
||||
// selecting circle:
|
||||
if (upper_border > upper_marker+1 || lower_border < lower_marker-1 || lower_border > lower_marker)
|
||||
{
|
||||
// default: select all between markers
|
||||
for (int i = upper_marker+1; i < lower_marker; ++i)
|
||||
{
|
||||
ListView_SetItemState(hwndList,i,LVIS_SELECTED,LVIS_SELECTED);
|
||||
}
|
||||
} else if (upper_border == upper_marker+1 && lower_border == lower_marker-1)
|
||||
{
|
||||
// already selected all between markers - now select both markers or at least select the marker that is not outside movie range
|
||||
if (upper_marker < 0) upper_marker = 0;
|
||||
if (lower_marker >= movie_size) lower_marker = movie_size - 1;
|
||||
for (int i = upper_marker; i <= lower_marker; ++i)
|
||||
{
|
||||
ListView_SetItemState(hwndList,i,LVIS_SELECTED,LVIS_SELECTED);
|
||||
}
|
||||
} else if (upper_border <= upper_marker && lower_border >= lower_marker)
|
||||
{
|
||||
// selected all between markers and both markers selected too - now deselect lower marker
|
||||
for (int i = upper_marker; i < lower_marker; ++i)
|
||||
{
|
||||
ListView_SetItemState(hwndList,i,LVIS_SELECTED,LVIS_SELECTED);
|
||||
}
|
||||
} else if (upper_border == upper_marker && lower_border == lower_marker-1)
|
||||
{
|
||||
// selected all between markers and upper marker selected too - now deselect upper marker and (if lower marker < movie_size) reselect lower marker
|
||||
if (lower_marker >= movie_size) lower_marker = movie_size - 1;
|
||||
for (int i = upper_marker+1; i <= lower_marker; ++i)
|
||||
{
|
||||
ListView_SetItemState(hwndList,i,LVIS_SELECTED,LVIS_SELECTED);
|
||||
}
|
||||
} else if (upper_border == upper_marker+1 && lower_border == lower_marker)
|
||||
{
|
||||
// selected all between markers and lower marker selected too - now deselect lower marker (return to "selected all between markers")
|
||||
for (int i = upper_marker + 1; i < lower_marker; ++i)
|
||||
{
|
||||
ListView_SetItemState(hwndList,i,LVIS_SELECTED,LVIS_SELECTED);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool Copy()
|
||||
{
|
||||
if (selectionFrames.size()==0) return false;
|
||||
if (selection.CurrentSelection().size() == 0) return false;
|
||||
|
||||
int cframe=*selectionFrames.begin()-1;
|
||||
int cframe = *selection.CurrentSelection().begin()-1;
|
||||
try
|
||||
{
|
||||
int range = *selectionFrames.rbegin() - *selectionFrames.begin()+1;
|
||||
int range = *selection.CurrentSelection().rbegin() - *selection.CurrentSelection().begin()+1;
|
||||
//std::string outbuf clipString("TAS");
|
||||
|
||||
std::stringstream clipString;
|
||||
clipString << "TAS " << range << std::endl;
|
||||
|
||||
for(TSelectionFrames::iterator it(selectionFrames.begin()); it != selectionFrames.end(); it++)
|
||||
for(SelectionFrames::iterator it(selection.CurrentSelection().begin()); it != selection.CurrentSelection().end(); it++)
|
||||
{
|
||||
if (*it>cframe+1)
|
||||
{
|
||||
|
@ -793,7 +716,7 @@ bool Copy()
|
|||
{
|
||||
if (currMovieData.records[*it].joysticks[joy] & (1<<bit))
|
||||
{
|
||||
clipString << MovieRecord::mnemonics[bit];
|
||||
clipString << buttonNames[bit];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -823,7 +746,8 @@ bool Copy()
|
|||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
// copied successfully
|
||||
selection.MemorizeClipboardSelection();
|
||||
return true;
|
||||
}
|
||||
void Cut()
|
||||
|
@ -836,10 +760,10 @@ void Cut()
|
|||
bool Paste()
|
||||
{
|
||||
bool result = false;
|
||||
if (selectionFrames.size()==0)
|
||||
if (selection.CurrentSelection().size()==0)
|
||||
return false;
|
||||
|
||||
int pos = *selectionFrames.begin();
|
||||
int pos = *selection.CurrentSelection().begin();
|
||||
|
||||
if (!OpenClipboard(hwndTasEdit))
|
||||
return false;
|
||||
|
@ -895,7 +819,7 @@ bool Paste()
|
|||
default:
|
||||
for (int bit=0; bit<NUM_JOYPAD_BUTTONS; ++bit)
|
||||
{
|
||||
if (*frame==MovieRecord::mnemonics[bit])
|
||||
if (*frame == buttonNames[bit][0])
|
||||
{
|
||||
currMovieData.records[pos].joysticks[joy]|=(1<<bit);
|
||||
break;
|
||||
|
@ -908,7 +832,7 @@ bool Paste()
|
|||
|
||||
pGlobal = strchr(pGlobal, '\n');
|
||||
}
|
||||
greenzone.InvalidateAndCheck(history.RegisterChanges(MODTYPE_PASTE, *selectionFrames.begin()));
|
||||
greenzone.InvalidateAndCheck(history.RegisterChanges(MODTYPE_PASTE, *selection.CurrentSelection().begin()));
|
||||
result = true;
|
||||
}
|
||||
|
||||
|
@ -929,7 +853,7 @@ LRESULT APIENTRY HeaderWndProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam
|
|||
case WM_LBUTTONDOWN:
|
||||
case WM_LBUTTONDBLCLK:
|
||||
{
|
||||
if (selectionFrames.size())
|
||||
if (selection.CurrentSelection().size())
|
||||
{
|
||||
//perform hit test
|
||||
HD_HITTESTINFO info;
|
||||
|
@ -1193,7 +1117,6 @@ void OpenProject()
|
|||
bool last_fourscore = currMovieData.fourscore;
|
||||
// Load project
|
||||
project.LoadProject(project.GetProjectFile());
|
||||
UpdateList();
|
||||
// update fourscore status
|
||||
if (last_fourscore && !currMovieData.fourscore)
|
||||
RemoveFourscore();
|
||||
|
@ -1208,9 +1131,6 @@ void OpenProject()
|
|||
// Saves current project
|
||||
bool SaveProjectAs()
|
||||
{
|
||||
//Save project as new user selected filename
|
||||
//flag project as not changed
|
||||
|
||||
const char TPfilter[]="TASEdit Project (*.tas)\0*.tas\0All Files (*.*)\0*.*\0\0"; //Filetype filter
|
||||
|
||||
OPENFILENAME ofn;
|
||||
|
@ -1304,51 +1224,6 @@ void Export()
|
|||
}
|
||||
}
|
||||
|
||||
//used to track selection
|
||||
void ItemRangeChanged(NMLVODSTATECHANGE* info)
|
||||
{
|
||||
bool ON = !(info->uOldState & LVIS_SELECTED) && (info->uNewState & LVIS_SELECTED);
|
||||
bool OFF = (info->uOldState & LVIS_SELECTED) && !(info->uNewState & LVIS_SELECTED);
|
||||
|
||||
if(ON)
|
||||
for(int i=info->iFrom;i<=info->iTo;i++)
|
||||
selectionFrames.insert(i);
|
||||
else
|
||||
for(int i=info->iFrom;i<=info->iTo;i++)
|
||||
selectionFrames.erase(i);
|
||||
}
|
||||
void ItemChanged(NMLISTVIEW* info)
|
||||
{
|
||||
int item = info->iItem;
|
||||
|
||||
bool ON = !(info->uOldState & LVIS_SELECTED) && (info->uNewState & LVIS_SELECTED);
|
||||
bool OFF = (info->uOldState & LVIS_SELECTED) && !(info->uNewState & LVIS_SELECTED);
|
||||
|
||||
//if the item is -1, apply the change to all items
|
||||
if(item == -1)
|
||||
{
|
||||
if(OFF)
|
||||
{
|
||||
// clear all
|
||||
selectionFrames.clear();
|
||||
} else if (ON)
|
||||
{
|
||||
// select all
|
||||
for(int i = currMovieData.getNumRecords() - 1; i >= 0; i--)
|
||||
{
|
||||
selectionFrames.insert(i);
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if(ON)
|
||||
selectionFrames.insert(item);
|
||||
else if(OFF)
|
||||
selectionFrames.erase(item);
|
||||
}
|
||||
}
|
||||
|
||||
BOOL CALLBACK WndprocTasEdit(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam)
|
||||
{
|
||||
switch(uMsg)
|
||||
|
@ -1391,7 +1266,6 @@ BOOL CALLBACK WndprocTasEdit(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lPar
|
|||
TasEdit_wndy = wrect.top;
|
||||
WindowBoundsCheckNoResize(TasEdit_wndx,TasEdit_wndy,wrect.right);
|
||||
// also move screenshot bitmap if it's open
|
||||
extern HWND hwndScrBmp;
|
||||
if (hwndScrBmp)
|
||||
SetWindowPos(hwndScrBmp, 0, TasEdit_wndx + bookmarks.scr_bmp_x, TasEdit_wndy + bookmarks.scr_bmp_y, 0, 0,SWP_NOSIZE|SWP_NOZORDER|SWP_NOACTIVATE);
|
||||
}
|
||||
|
@ -1421,10 +1295,10 @@ BOOL CALLBACK WndprocTasEdit(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lPar
|
|||
RightClick((LPNMITEMACTIVATE)lParam);
|
||||
break;
|
||||
case LVN_ITEMCHANGED:
|
||||
ItemChanged((LPNMLISTVIEW) lParam);
|
||||
selection.ItemChanged((LPNMLISTVIEW) lParam);
|
||||
break;
|
||||
case LVN_ODSTATECHANGED:
|
||||
ItemRangeChanged((LPNMLVODSTATECHANGE) lParam);
|
||||
selection.ItemRangeChanged((LPNMLVODSTATECHANGE) lParam);
|
||||
break;
|
||||
/*
|
||||
case LVN_ENDSCROLL:
|
||||
|
@ -1518,7 +1392,7 @@ BOOL CALLBACK WndprocTasEdit(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lPar
|
|||
ExitTasEdit();
|
||||
break;
|
||||
case ID_EDIT_SELECTALL:
|
||||
SelectAll();
|
||||
selection.SelectAll();
|
||||
break;
|
||||
case ACCEL_CTRL_X:
|
||||
case ID_TASEDIT_CUT:
|
||||
|
@ -1535,7 +1409,7 @@ BOOL CALLBACK WndprocTasEdit(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lPar
|
|||
case ACCEL_CTRL_DELETE:
|
||||
case ID_TASEDIT_DELETE:
|
||||
case ID_CONTEXT_SELECTED_DELETEFRAMES:
|
||||
if (selectionFrames.size()) DeleteFrames();
|
||||
DeleteFrames();
|
||||
break;
|
||||
case ACCEL_CTRL_T:
|
||||
case ID_EDIT_TRUNCATE:
|
||||
|
@ -1551,41 +1425,17 @@ BOOL CALLBACK WndprocTasEdit(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lPar
|
|||
case ID_EDIT_INSERT:
|
||||
case MENU_CONTEXT_STRAY_INSERTFRAMES:
|
||||
case ID_CONTEXT_SELECTED_INSERTFRAMES2:
|
||||
{
|
||||
int frames = selectionFrames.size();
|
||||
if(CWin32InputBox::GetInteger("Insert number of Frames", "How many frames?", frames, hwndDlg) == IDOK)
|
||||
{
|
||||
if (frames > 0)
|
||||
{
|
||||
if (selectionFrames.size())
|
||||
{
|
||||
// insert at selection
|
||||
int index = *selectionFrames.begin();
|
||||
currMovieData.insertEmpty(index, frames);
|
||||
if (TASEdit_bind_markers)
|
||||
markers.insertEmpty(index, frames);
|
||||
greenzone.InvalidateAndCheck(history.RegisterChanges(MODTYPE_INSERT, index));
|
||||
} else
|
||||
{
|
||||
// insert at playback cursor
|
||||
currMovieData.insertEmpty(currFrameCounter, frames);
|
||||
if (TASEdit_bind_markers)
|
||||
markers.insertEmpty(currFrameCounter, frames);
|
||||
greenzone.InvalidateAndCheck(history.RegisterChanges(MODTYPE_INSERT, currFrameCounter));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
InsertNumFrames();
|
||||
break;
|
||||
case ACCEL_CTRL_INSERT:
|
||||
case ID_EDIT_INSERTFRAMES:
|
||||
case ID_CONTEXT_SELECTED_INSERTFRAMES:
|
||||
if (selectionFrames.size()) InsertFrames();
|
||||
InsertFrames();
|
||||
break;
|
||||
case ACCEL_DEL:
|
||||
case ID_EDIT_CLEAR:
|
||||
case ID_CONTEXT_SELECTED_CLEARFRAMES:
|
||||
if (selectionFrames.size()) ClearFrames();
|
||||
ClearFrames();
|
||||
break;
|
||||
case TASEDIT_PLAYSTOP:
|
||||
playback.ToggleEmulationPause();
|
||||
|
@ -1598,7 +1448,7 @@ BOOL CALLBACK WndprocTasEdit(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lPar
|
|||
// if switched off then jump to selection
|
||||
if (TASEdit_follow_playback)
|
||||
FollowPlayback();
|
||||
else if (selectionFrames.size())
|
||||
else if (selection.CurrentSelection().size())
|
||||
FollowSelection();
|
||||
else if (playback.pauseframe)
|
||||
FollowPauseframe();
|
||||
|
@ -1613,12 +1463,17 @@ BOOL CALLBACK WndprocTasEdit(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lPar
|
|||
//switch "Show Markers" flag
|
||||
TASEdit_show_markers ^= 1;
|
||||
CheckMenuItem(hmenu, ID_VIEW_SHOW_MARKERS, TASEdit_show_markers?MF_CHECKED : MF_UNCHECKED);
|
||||
RedrawList();
|
||||
RedrawList(); // no need to redraw Bookmarks, as Markers are only shown in main list
|
||||
break;
|
||||
case ID_VIEW_SHOWDOTINEMPTYCELLS:
|
||||
TASEdit_show_dot ^= 1;
|
||||
CheckMenuItem(hmenu, ID_VIEW_SHOWDOTINEMPTYCELLS, TASEdit_show_dot?MF_CHECKED : MF_UNCHECKED);
|
||||
RedrawList();
|
||||
case ID_VIEW_SHOWBRANCHSCREENSHOTS:
|
||||
//switch "Show Branch Screenshots" flag
|
||||
TASEdit_show_branch_screenshots ^= 1;
|
||||
CheckMenuItem(hmenu, ID_VIEW_SHOWBRANCHSCREENSHOTS, TASEdit_show_branch_screenshots?MF_CHECKED : MF_UNCHECKED);
|
||||
break;
|
||||
case ID_VIEW_ENABLEHOTCHANGES:
|
||||
TASEdit_enable_hot_changes ^= 1;
|
||||
CheckMenuItem(hmenu, ID_VIEW_ENABLEHOTCHANGES, TASEdit_enable_hot_changes?MF_CHECKED : MF_UNCHECKED);
|
||||
RedrawList(); // redraw buttons text
|
||||
break;
|
||||
case ID_VIEW_JUMPWHENMAKINGUNDO:
|
||||
TASEdit_jump_to_undo ^= 1;
|
||||
|
@ -1660,6 +1515,7 @@ BOOL CALLBACK WndprocTasEdit(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lPar
|
|||
{
|
||||
TasEdit_undo_levels = new_size;
|
||||
history.init(TasEdit_undo_levels);
|
||||
selection.init(TasEdit_undo_levels);
|
||||
// hot changes were cleared, so update list
|
||||
RedrawList();
|
||||
}
|
||||
|
@ -1680,15 +1536,6 @@ BOOL CALLBACK WndprocTasEdit(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lPar
|
|||
}
|
||||
break;
|
||||
}
|
||||
case ID_CONFIG_MUTETURBO:
|
||||
muteTurbo ^= 1;
|
||||
CheckMenuItem(hmenu, ID_CONFIG_MUTETURBO, muteTurbo?MF_CHECKED : MF_UNCHECKED);
|
||||
break;
|
||||
case ID_CONFIG_BINDMARKERSTOINPUT:
|
||||
//switch "Bind Markers to Input" flag
|
||||
TASEdit_bind_markers ^= 1;
|
||||
CheckMenuItem(hmenu, ID_CONFIG_BINDMARKERSTOINPUT, TASEdit_bind_markers?MF_CHECKED : MF_UNCHECKED);
|
||||
break;
|
||||
case ID_CONFIG_BRANCHESRESTOREFULLMOVIE:
|
||||
//switch "Branches restore entire Movie" flag
|
||||
TASEdit_branch_full_movie ^= 1;
|
||||
|
@ -1705,6 +1552,15 @@ BOOL CALLBACK WndprocTasEdit(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lPar
|
|||
TASEdit_branch_scr_hud ^= 1;
|
||||
CheckMenuItem(hmenu, ID_CONFIG_HUDINBRANCHSCREENSHOTS, TASEdit_branch_scr_hud?MF_CHECKED : MF_UNCHECKED);
|
||||
break;
|
||||
case ID_CONFIG_BINDMARKERSTOINPUT:
|
||||
//switch "Bind Markers to Input" flag
|
||||
TASEdit_bind_markers ^= 1;
|
||||
CheckMenuItem(hmenu, ID_CONFIG_BINDMARKERSTOINPUT, TASEdit_bind_markers?MF_CHECKED : MF_UNCHECKED);
|
||||
break;
|
||||
case ID_CONFIG_MUTETURBO:
|
||||
muteTurbo ^= 1;
|
||||
CheckMenuItem(hmenu, ID_CONFIG_MUTETURBO, muteTurbo?MF_CHECKED : MF_UNCHECKED);
|
||||
break;
|
||||
case IDC_PROGRESS_BUTTON:
|
||||
// click on progressbar - stop seeking
|
||||
if (playback.pauseframe) playback.SeekingStop();
|
||||
|
@ -1746,12 +1602,12 @@ BOOL CALLBACK WndprocTasEdit(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lPar
|
|||
case ACCEL_CTRL_A:
|
||||
case ID_EDIT_SELECTMIDMARKERS:
|
||||
case ID_SELECTED_SELECTMIDMARKERS:
|
||||
SelectMidMarkers();
|
||||
selection.SelectMidMarkers();
|
||||
break;
|
||||
case ACCEL_SHIFT_INS:
|
||||
case ID_EDIT_CLONEFRAMES:
|
||||
case ID_SELECTED_CLONE:
|
||||
if (selectionFrames.size()) CloneFrames();
|
||||
CloneFrames();
|
||||
break;
|
||||
case ACCEL_CTRL_Z:
|
||||
case ID_EDIT_UNDO:
|
||||
|
@ -1777,6 +1633,27 @@ BOOL CALLBACK WndprocTasEdit(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lPar
|
|||
}
|
||||
break;
|
||||
}
|
||||
case ID_EDIT_SELECTIONUNDO:
|
||||
case ACCEL_CTRL_Q:
|
||||
{
|
||||
selection.undo();
|
||||
FollowSelection();
|
||||
break;
|
||||
}
|
||||
case ID_EDIT_SELECTIONREDO:
|
||||
case ACCEL_CTRL_W:
|
||||
{
|
||||
selection.redo();
|
||||
FollowSelection();
|
||||
break;
|
||||
}
|
||||
case ID_EDIT_RESELECTCLIPBOARD:
|
||||
case ACCEL_CTRL_B:
|
||||
{
|
||||
selection.ReselectClipboard();
|
||||
FollowSelection();
|
||||
break;
|
||||
}
|
||||
|
||||
}
|
||||
break;
|
||||
|
@ -1831,10 +1708,12 @@ void FollowUndo()
|
|||
}
|
||||
void FollowSelection()
|
||||
{
|
||||
if (selection.CurrentSelection().size() == 0) return;
|
||||
|
||||
int list_items = listItems;
|
||||
if (currMovieData.fourscore) list_items--;
|
||||
int selection_start = *selectionFrames.begin();
|
||||
int selection_end = *selectionFrames.rbegin();
|
||||
int selection_start = *selection.CurrentSelection().begin();
|
||||
int selection_end = *selection.CurrentSelection().rbegin();
|
||||
int selection_items = 1 + selection_end - selection_start;
|
||||
|
||||
if (selection_items <= list_items)
|
||||
|
@ -1917,22 +1796,23 @@ void EnterTasEdit()
|
|||
CheckDlgButton(hwndTasEdit, CHECK_FOLLOW_CURSOR, TASEdit_follow_playback?MF_CHECKED : MF_UNCHECKED);
|
||||
CheckMenuItem(hmenu, ID_VIEW_SHOW_LAG_FRAMES, TASEdit_show_lag_frames?MF_CHECKED : MF_UNCHECKED);
|
||||
CheckMenuItem(hmenu, ID_VIEW_SHOW_MARKERS, TASEdit_show_markers?MF_CHECKED : MF_UNCHECKED);
|
||||
CheckMenuItem(hmenu, ID_VIEW_SHOWBRANCHSCREENSHOTS, TASEdit_show_branch_screenshots?MF_CHECKED : MF_UNCHECKED);
|
||||
CheckMenuItem(hmenu, ID_VIEW_JUMPWHENMAKINGUNDO, TASEdit_jump_to_undo?MF_CHECKED : MF_UNCHECKED);
|
||||
CheckMenuItem(hmenu, ID_CONFIG_BINDMARKERSTOINPUT, TASEdit_bind_markers?MF_CHECKED : MF_UNCHECKED);
|
||||
CheckMenuItem(hmenu, ID_CONFIG_BRANCHESRESTOREFULLMOVIE, TASEdit_branch_full_movie?MF_CHECKED : MF_UNCHECKED);
|
||||
CheckMenuItem(hmenu, ID_CONFIG_BRANCHESWORKONLYWHENRECORDING, TASEdit_branch_only_when_rec?MF_CHECKED : MF_UNCHECKED);
|
||||
CheckMenuItem(hmenu, ID_CONFIG_HUDINBRANCHSCREENSHOTS, TASEdit_branch_scr_hud?MF_CHECKED : MF_UNCHECKED);
|
||||
CheckDlgButton(hwndTasEdit,CHECK_AUTORESTORE_PLAYBACK,TASEdit_restore_position?BST_CHECKED:BST_UNCHECKED);
|
||||
CheckMenuItem(hmenu, ID_CONFIG_BINDMARKERSTOINPUT, TASEdit_bind_markers?MF_CHECKED : MF_UNCHECKED);
|
||||
CheckMenuItem(hmenu, ID_VIEW_ENABLEHOTCHANGES, TASEdit_enable_hot_changes?MF_CHECKED : MF_UNCHECKED);
|
||||
CheckMenuItem(hmenu, ID_CONFIG_MUTETURBO, muteTurbo?MF_CHECKED : MF_UNCHECKED);
|
||||
CheckMenuItem(hmenu, ID_VIEW_SHOWDOTINEMPTYCELLS, TASEdit_show_dot?MF_CHECKED : MF_UNCHECKED);
|
||||
CheckDlgButton(hwndTasEdit,CHECK_AUTORESTORE_PLAYBACK,TASEdit_restore_position?BST_CHECKED:BST_UNCHECKED);
|
||||
|
||||
SetWindowPos(hwndTasEdit,HWND_TOP,0,0,0,0,SWP_NOSIZE|SWP_NOMOVE|SWP_NOOWNERZORDER);
|
||||
SetWindowPos(hwndTasEdit, HWND_TOP, 0, 0, 0, 0, SWP_NOSIZE|SWP_NOMOVE|SWP_NOOWNERZORDER);
|
||||
|
||||
// init modules
|
||||
greenzone.init();
|
||||
playback.init();
|
||||
// either start new movie or use current movie
|
||||
if (movieMode == MOVIEMODE_INACTIVE)
|
||||
if (FCEUMOV_Mode(MOVIEMODE_INACTIVE))
|
||||
{
|
||||
FCEUI_StopMovie();
|
||||
CreateCleanMovie();
|
||||
|
@ -1948,15 +1828,23 @@ void EnterTasEdit()
|
|||
movie_readonly = true;
|
||||
multitrack_recording_joypad = MULTITRACK_RECORDING_ALL;
|
||||
RecheckRecordingRadioButtons();
|
||||
|
||||
// switch to tasedit mode
|
||||
movieMode = MOVIEMODE_TASEDIT;
|
||||
|
||||
// create font for main listview
|
||||
hMainListFont = CreateFont(13, 8, /*Height,Width*/
|
||||
// create fonts for main listview
|
||||
hMainListFont = CreateFont(15, 10, /*Height,Width*/
|
||||
0, 0, /*escapement,orientation*/
|
||||
FW_REGULAR, FALSE, FALSE, FALSE, /*weight, italic, underline, strikeout*/
|
||||
FW_BOLD, FALSE, FALSE, FALSE, /*weight, italic, underline, strikeout*/
|
||||
ANSI_CHARSET, OUT_DEVICE_PRECIS, CLIP_MASK, /*charset, precision, clipping*/
|
||||
DEFAULT_QUALITY, DEFAULT_PITCH, /*quality, and pitch*/
|
||||
"Courier"); /*font name*/
|
||||
hMainListSelectFont = CreateFont(14, 7, /*Height,Width*/
|
||||
0, 0, /*escapement,orientation*/
|
||||
FW_BOLD, FALSE, FALSE, FALSE, /*weight, italic, underline, strikeout*/
|
||||
ANSI_CHARSET, OUT_DEVICE_PRECIS, CLIP_MASK, /*charset, precision, clipping*/
|
||||
DEFAULT_QUALITY, DEFAULT_PITCH, /*quality, and pitch*/
|
||||
"Arial"); /*font name*/
|
||||
|
||||
// prepare the main listview
|
||||
ListView_SetExtendedListViewStyleEx(hwndList, LVS_EX_FULLROWSELECT|LVS_EX_GRIDLINES, LVS_EX_FULLROWSELECT|LVS_EX_GRIDLINES);
|
||||
|
@ -2041,7 +1929,7 @@ void EnterTasEdit()
|
|||
// frame number column
|
||||
lvc.mask = LVCF_WIDTH | LVCF_TEXT | LVCF_FMT;
|
||||
lvc.fmt = LVCFMT_CENTER;
|
||||
lvc.cx = 74;
|
||||
lvc.cx = 75;
|
||||
lvc.pszText = "Frame#";
|
||||
ListView_InsertColumn(hwndList, colidx++, &lvc);
|
||||
// pads columns
|
||||
|
@ -2079,12 +1967,15 @@ void EnterTasEdit()
|
|||
// jump_frame column
|
||||
lvc.mask = LVCF_WIDTH | LVCF_TEXT | LVCF_FMT;
|
||||
lvc.fmt = LVCFMT_CENTER;
|
||||
lvc.cx = 72;
|
||||
lvc.cx = 74;
|
||||
ListView_InsertColumn(hwndBookmarksList, 1, &lvc);
|
||||
// time column
|
||||
lvc.cx = 82;
|
||||
lvc.cx = 80;
|
||||
ListView_InsertColumn(hwndBookmarksList, 2, &lvc);
|
||||
|
||||
// subclass BranchesBitmap
|
||||
hwndBranchesBitmap_oldWndProc = (WNDPROC)SetWindowLong(hwndBranchesBitmap, GWL_WNDPROC, (LONG)BranchesBitmapWndProc);
|
||||
|
||||
// prepare the history listview
|
||||
ListView_SetExtendedListViewStyleEx(hwndHistoryList, LVS_EX_FULLROWSELECT|LVS_EX_GRIDLINES, LVS_EX_FULLROWSELECT|LVS_EX_GRIDLINES);
|
||||
// subclass the listview
|
||||
|
@ -2094,14 +1985,12 @@ void EnterTasEdit()
|
|||
lvc.fmt = LVCFMT_LEFT;
|
||||
ListView_InsertColumn(hwndHistoryList, 0, &lvc);
|
||||
|
||||
// subclass BranchesBitmap
|
||||
hwndBranchesBitmap_oldWndProc = (WNDPROC)SetWindowLong(hwndBranchesBitmap, GWL_WNDPROC, (LONG)BranchesBitmapWndProc);
|
||||
|
||||
// init variables
|
||||
markers.init();
|
||||
project.init();
|
||||
bookmarks.init();
|
||||
history.init(TasEdit_undo_levels);
|
||||
selection.init(TasEdit_undo_levels);
|
||||
SetFocus(hwndHistoryList); // to show darkblue cursor
|
||||
SetFocus(hwndList);
|
||||
FCEU_DispMessage("Tasedit engaged",0);
|
||||
|
@ -2132,6 +2021,7 @@ bool ExitTasEdit()
|
|||
bookmarks.free();
|
||||
history.free();
|
||||
playback.SeekingStop();
|
||||
selection.free();
|
||||
|
||||
movieMode = MOVIEMODE_INACTIVE;
|
||||
FCEU_DispMessage("Tasedit disengaged",0);
|
||||
|
|
|
@ -65,6 +65,8 @@
|
|||
#define DIGITS_IN_FRAMENUM 7
|
||||
#define ARROW_IMAGE_ID 20
|
||||
// listview colors
|
||||
#define NORMAL_TEXT_COLOR 0x0
|
||||
|
||||
#define NORMAL_FRAMENUM_COLOR 0xFFFFFF
|
||||
#define NORMAL_INPUT_COLOR1 0xEDEDED
|
||||
#define NORMAL_INPUT_COLOR2 0xDEDEDE
|
||||
|
@ -94,7 +96,7 @@
|
|||
#define UNDOHINT_INPUT_COLOR2 0xE5B7CC
|
||||
|
||||
#define MARKED_FRAMENUM_COLOR 0xC0FCFF
|
||||
#define CUR_MARKED_FRAMENUM_COLOR 0xDEF7F4
|
||||
#define CUR_MARKED_FRAMENUM_COLOR 0xDEF7F3
|
||||
#define MARKED_UNDOHINT_FRAMENUM_COLOR 0xE1E7EC
|
||||
|
||||
// greenzone cleaning masks
|
||||
|
@ -103,6 +105,11 @@
|
|||
#define EVERY4TH 0xFFFFFFFC
|
||||
#define EVERY2ND 0xFFFFFFFE
|
||||
// -----------------------------
|
||||
enum ECONTEXTMENU
|
||||
{
|
||||
CONTEXTMENU_STRAY = 0,
|
||||
CONTEXTMENU_SELECTED = 1,
|
||||
};
|
||||
void EnterTasEdit();
|
||||
void InitDialog();
|
||||
bool ExitTasEdit();
|
||||
|
@ -114,8 +121,6 @@ void FollowPlayback();
|
|||
void FollowUndo();
|
||||
void FollowSelection();
|
||||
void FollowPauseframe();
|
||||
void ClearSelection();
|
||||
void ClearRowSelection(int index);
|
||||
void AddFourscore();
|
||||
void RemoveFourscore();
|
||||
void RedrawWindowCaption();
|
||||
|
@ -132,10 +137,9 @@ void OpenProject();
|
|||
bool SaveProject();
|
||||
bool SaveProjectAs();
|
||||
bool AskSaveProject();
|
||||
void SelectAll();
|
||||
void SelectMidMarkers();
|
||||
void CloneFrames();
|
||||
void InsertFrames();
|
||||
void InsertNumFrames();
|
||||
void DeleteFrames();
|
||||
void ClearFrames(bool cut = false);
|
||||
void Truncate();
|
||||
|
|
|
@ -7,8 +7,11 @@
|
|||
#include "zlib.h"
|
||||
|
||||
extern GREENZONE greenzone;
|
||||
extern INPUT_HISTORY history;
|
||||
|
||||
extern bool TASEdit_branch_scr_hud;
|
||||
extern bool TASEdit_enable_hot_changes;
|
||||
|
||||
extern uint8 *XBuf;
|
||||
extern uint8 *XBackBuf;
|
||||
|
||||
|
@ -27,8 +30,12 @@ void BOOKMARK::init()
|
|||
|
||||
void BOOKMARK::set()
|
||||
{
|
||||
snapshot.init(currMovieData, false);
|
||||
// copy input and hotchanges
|
||||
snapshot.init(currMovieData, TASEdit_enable_hot_changes);
|
||||
snapshot.jump_frame = currFrameCounter;
|
||||
if (TASEdit_enable_hot_changes)
|
||||
snapshot.copyHotChanges(&history.GetCurrentSnapshot());
|
||||
// copy savestate
|
||||
savestate = greenzone.savestates[currFrameCounter];
|
||||
// save screenshot
|
||||
uLongf comprlen = (SCREENSHOT_SIZE>>9)+12 + SCREENSHOT_SIZE;
|
||||
|
|
|
@ -46,13 +46,14 @@ extern bool TASEdit_bind_markers;
|
|||
extern bool TASEdit_branch_full_movie;
|
||||
extern bool TASEdit_branch_only_when_rec;
|
||||
extern bool TASEdit_view_branches_tree;
|
||||
extern bool TASEdit_show_branch_screenshots;
|
||||
|
||||
BOOKMARKS::BOOKMARKS()
|
||||
{
|
||||
// create font
|
||||
hBookmarksFont = CreateFont(13, 8, /*Height,Width*/
|
||||
hBookmarksFont = CreateFont(15, 10, /*Height,Width*/
|
||||
0, 0, /*escapement,orientation*/
|
||||
FW_REGULAR, FALSE, FALSE, FALSE, /*weight, italic, underline, strikeout*/
|
||||
FW_BOLD, FALSE, FALSE, FALSE, /*weight, italic, underline, strikeout*/
|
||||
ANSI_CHARSET, OUT_DEVICE_PRECIS, CLIP_MASK, /*charset, precision, clipping*/
|
||||
DEFAULT_QUALITY, DEFAULT_PITCH, /*quality, and pitch*/
|
||||
"Courier"); /*font name*/
|
||||
|
@ -292,11 +293,11 @@ void BOOKMARKS::update()
|
|||
if (must_check_item_under_mouse)
|
||||
CheckMousePos();
|
||||
// render branches_bitmap
|
||||
if (must_redraw_branches_tree)
|
||||
if (edit_mode == EDIT_MODE_BRANCHES && must_redraw_branches_tree)
|
||||
RedrawBranchesTree();
|
||||
|
||||
// change screenshot_bitmap alpha if needed
|
||||
if (item_under_mouse >= 0 && item_under_mouse < TOTAL_BOOKMARKS)
|
||||
if (item_under_mouse >= 0 && item_under_mouse < TOTAL_BOOKMARKS && TASEdit_show_branch_screenshots)
|
||||
{
|
||||
if (!hwndScrBmp)
|
||||
{
|
||||
|
@ -315,18 +316,24 @@ void BOOKMARKS::update()
|
|||
{
|
||||
scr_bmp_phase++;
|
||||
// update alpha
|
||||
SetLayeredWindowAttributes(hwndScrBmp, 0, (255 * scr_bmp_phase) / SCR_BMP_PHASE_MAX, LWA_ALPHA);
|
||||
int phase_alpha = scr_bmp_phase;
|
||||
if (phase_alpha > SCR_BMP_PHASE_ALPHA_MAX) phase_alpha = SCR_BMP_PHASE_ALPHA_MAX;
|
||||
SetLayeredWindowAttributes(hwndScrBmp, 0, (255 * phase_alpha) / SCR_BMP_PHASE_ALPHA_MAX, LWA_ALPHA);
|
||||
UpdateLayeredWindow(hwndScrBmp, 0, 0, 0, 0, 0, 0, &blend, ULW_ALPHA);
|
||||
}
|
||||
} else
|
||||
{
|
||||
// fade and finally hide screenshot
|
||||
if (scr_bmp_phase > 0)
|
||||
scr_bmp_phase--;
|
||||
if (scr_bmp_phase > 0)
|
||||
{
|
||||
scr_bmp_phase--;
|
||||
if (hwndScrBmp)
|
||||
{
|
||||
// update alpha
|
||||
SetLayeredWindowAttributes(hwndScrBmp, 0, (255 * scr_bmp_phase) / SCR_BMP_PHASE_MAX, LWA_ALPHA);
|
||||
int phase_alpha = scr_bmp_phase;
|
||||
if (phase_alpha > SCR_BMP_PHASE_ALPHA_MAX) phase_alpha = SCR_BMP_PHASE_ALPHA_MAX;
|
||||
SetLayeredWindowAttributes(hwndScrBmp, 0, (255 * phase_alpha) / SCR_BMP_PHASE_ALPHA_MAX, LWA_ALPHA);
|
||||
UpdateLayeredWindow(hwndScrBmp, 0, 0, 0, 0, 0, 0, &blend, ULW_ALPHA);
|
||||
}
|
||||
} else
|
||||
|
@ -426,11 +433,11 @@ void BOOKMARKS::unleash(int slot)
|
|||
if (!bookmarks_array[slot].not_empty) return;
|
||||
int jump_frame = bookmarks_array[slot].snapshot.jump_frame;
|
||||
|
||||
// revert movie to the input_snapshot state
|
||||
bool markers_changed = false;
|
||||
// revert current movie to the input_snapshot state
|
||||
if (TASEdit_branch_full_movie)
|
||||
{
|
||||
// update Markers
|
||||
bool markers_changed = false;
|
||||
if (TASEdit_bind_markers)
|
||||
{
|
||||
if (bookmarks_array[slot].snapshot.checkMarkersDiff())
|
||||
|
@ -448,12 +455,12 @@ void BOOKMARKS::unleash(int slot)
|
|||
currMovieData.records.resize(bookmarks_array[slot].snapshot.size);
|
||||
bookmarks_array[slot].snapshot.toMovie(currMovieData, first_change);
|
||||
UpdateList();
|
||||
history.RegisterBranch(MODTYPE_BRANCH_0 + slot, first_change, bookmarks_array[slot].snapshot.description);
|
||||
history.RegisterBranching(MODTYPE_BRANCH_0 + slot, first_change, slot);
|
||||
greenzone.Invalidate(first_change);
|
||||
bookmarks_array[slot].unleashed();
|
||||
} else if (markers_changed)
|
||||
{
|
||||
history.RegisterBranch(MODTYPE_BRANCH_MARKERS_0 + slot, first_change, bookmarks_array[slot].snapshot.description);
|
||||
history.RegisterBranching(MODTYPE_BRANCH_MARKERS_0 + slot, first_change, slot);
|
||||
RedrawList();
|
||||
bookmarks_array[slot].unleashed();
|
||||
} else
|
||||
|
@ -464,7 +471,6 @@ void BOOKMARKS::unleash(int slot)
|
|||
} else
|
||||
{
|
||||
// update Markers
|
||||
bool markers_changed = false;
|
||||
if (TASEdit_bind_markers)
|
||||
{
|
||||
if (bookmarks_array[slot].snapshot.checkMarkersDiff(jump_frame))
|
||||
|
@ -482,12 +488,12 @@ void BOOKMARKS::unleash(int slot)
|
|||
if (currMovieData.getNumRecords() <= jump_frame) currMovieData.records.resize(jump_frame+1); // but if old movie is shorter, include last frame as blank frame
|
||||
bookmarks_array[slot].snapshot.toMovie(currMovieData, first_change, jump_frame-1);
|
||||
UpdateList();
|
||||
history.RegisterBranch(MODTYPE_BRANCH_0 + slot, first_change, bookmarks_array[slot].snapshot.description);
|
||||
history.RegisterBranching(MODTYPE_BRANCH_0 + slot, first_change, slot);
|
||||
greenzone.Invalidate(first_change);
|
||||
bookmarks_array[slot].unleashed();
|
||||
} else if (markers_changed)
|
||||
{
|
||||
history.RegisterBranch(MODTYPE_BRANCH_MARKERS_0 + slot, first_change, bookmarks_array[slot].snapshot.description);
|
||||
history.RegisterBranching(MODTYPE_BRANCH_MARKERS_0 + slot, first_change, slot);
|
||||
RedrawList();
|
||||
bookmarks_array[slot].unleashed();
|
||||
} else
|
||||
|
@ -746,15 +752,25 @@ void BOOKMARKS::RedrawBranchesTree()
|
|||
BitBlt(hBitmapDC, branch_x, branch_y, DIGIT_BITMAP_WIDTH, DIGIT_BITMAP_HEIGHT, hSpritesheetDC, i * DIGIT_BITMAP_WIDTH, 0, SRCCOPY);
|
||||
}
|
||||
}
|
||||
// jump_frame of item under cursor (except cloud - it doesn't have particular frame)
|
||||
if (item_under_mouse > ITEM_UNDER_MOUSE_CLOUD)
|
||||
{
|
||||
char framenum_string[DIGITS_IN_FRAMENUM+1] = {0};
|
||||
if (item_under_mouse < TOTAL_BOOKMARKS)
|
||||
U32ToDecStr(framenum_string, bookmarks_array[item_under_mouse].snapshot.jump_frame, DIGITS_IN_FRAMENUM);
|
||||
else
|
||||
U32ToDecStr(framenum_string, currFrameCounter, DIGITS_IN_FRAMENUM);
|
||||
TextOut(hBitmapDC, BRANCHES_BITMAP_FRAMENUM_X, BRANCHES_BITMAP_FRAMENUM_Y, (LPCSTR)framenum_string, DIGITS_IN_FRAMENUM);
|
||||
}
|
||||
// time of item under cursor
|
||||
if (item_under_mouse > ITEM_UNDER_MOUSE_NONE)
|
||||
{
|
||||
if (item_under_mouse == ITEM_UNDER_MOUSE_CLOUD)
|
||||
TextOut(hBitmapDC, 0, 0, (LPCSTR)cloud_time, 8);
|
||||
TextOut(hBitmapDC, BRANCHES_BITMAP_TIME_X, BRANCHES_BITMAP_TIME_Y, (LPCSTR)cloud_time, TIME_DESC_LENGTH-1);
|
||||
else if (item_under_mouse < TOTAL_BOOKMARKS)
|
||||
TextOut(hBitmapDC, 0, 0, (LPCSTR)bookmarks_array[item_under_mouse].snapshot.description, 8);
|
||||
TextOut(hBitmapDC, BRANCHES_BITMAP_TIME_X, BRANCHES_BITMAP_TIME_Y, (LPCSTR)bookmarks_array[item_under_mouse].snapshot.description, TIME_DESC_LENGTH-1);
|
||||
else
|
||||
TextOut(hBitmapDC, 0, 0, (LPCSTR)current_pos_time, 8);
|
||||
TextOut(hBitmapDC, BRANCHES_BITMAP_TIME_X, BRANCHES_BITMAP_TIME_Y, (LPCSTR)current_pos_time, TIME_DESC_LENGTH-1);
|
||||
}
|
||||
// finished
|
||||
must_redraw_branches_tree = false;
|
||||
|
|
|
@ -19,6 +19,10 @@
|
|||
#define BRANCHES_BITMAP_WIDTH 170
|
||||
#define BRANCHES_BITMAP_HEIGHT 145
|
||||
#define BRANCHES_ANIMATION_FRAMES 12
|
||||
#define BRANCHES_BITMAP_FRAMENUM_X 0
|
||||
#define BRANCHES_BITMAP_FRAMENUM_Y 0
|
||||
#define BRANCHES_BITMAP_TIME_X 0
|
||||
#define BRANCHES_BITMAP_TIME_Y BRANCHES_BITMAP_HEIGHT - 17
|
||||
// constants for drawing branches tree
|
||||
#define BRANCHES_CANVAS_WIDTH 146
|
||||
#define BRANCHES_CANVAS_HEIGHT 130
|
||||
|
@ -82,8 +86,8 @@
|
|||
#define TIME_DESC_LENGTH 9 // "HH:MM:SS"
|
||||
|
||||
// screenshot bitmap
|
||||
#define SCR_BMP_PHASE_MAX 10
|
||||
|
||||
#define SCR_BMP_PHASE_MAX 11
|
||||
#define SCR_BMP_PHASE_ALPHA_MAX 8
|
||||
|
||||
class BOOKMARKS
|
||||
{
|
||||
|
|
|
@ -231,7 +231,7 @@ bool GREENZONE::load(EMUFILE *is)
|
|||
if ((int)is->fread(save_id, GREENZONE_ID_LEN) < GREENZONE_ID_LEN) goto error;
|
||||
if (strcmp(greenzone_save_id, save_id)) goto error; // string is not valid
|
||||
// read size
|
||||
if (read32le((uint32 *)&size, is) && size >= 0 && size <= currMovieData.getNumRecords())
|
||||
if (read32le(&size, is) && size >= 0 && size <= currMovieData.getNumRecords())
|
||||
{
|
||||
greenZoneCount = size;
|
||||
savestates.resize(greenZoneCount);
|
||||
|
@ -246,7 +246,7 @@ bool GREENZONE::load(EMUFILE *is)
|
|||
int e = uncompress(&lag_history[0], &destlen, &cbuf[0], comprlen);
|
||||
if (e != Z_OK && e != Z_BUF_ERROR) goto error;
|
||||
// read playback position
|
||||
if (read32le((uint32 *)&frame, is))
|
||||
if (read32le(&frame, is))
|
||||
{
|
||||
currFrameCounter = frame;
|
||||
int greenzone_tail_frame = currFrameCounter - TASEdit_greenzone_capacity;
|
||||
|
@ -257,7 +257,7 @@ bool GREENZONE::load(EMUFILE *is)
|
|||
// read savestates
|
||||
while(1)
|
||||
{
|
||||
if (!read32le((uint32 *)&frame, is)) break;
|
||||
if (!read32le(&frame, is)) break;
|
||||
if (frame < 0) break; // -1 = eof
|
||||
// update TASEditor progressbar from time to time
|
||||
if (frame / PROGRESSBAR_UPDATE_RATE > last_tick)
|
||||
|
@ -268,7 +268,7 @@ bool GREENZONE::load(EMUFILE *is)
|
|||
// read lua_colorings
|
||||
// read monitorings
|
||||
// read savestate
|
||||
if (!read32le((uint32 *)&size, is)) break;
|
||||
if (!read32le(&size, is)) break;
|
||||
if (size < 0) break;
|
||||
if (frame <= greenzone_tail_frame16
|
||||
|| (frame <= greenzone_tail_frame8 && (frame & 0xF))
|
||||
|
|
|
@ -1,14 +1,14 @@
|
|||
//Implementation file of Input History class (Undo feature)
|
||||
|
||||
#include "movie.h"
|
||||
#include "../common.h"
|
||||
#include "../tasedit.h"
|
||||
#include "taseditproj.h"
|
||||
#include "../tasedit.h" // just for mainlist functions, later this should be deleted
|
||||
|
||||
extern void FCEU_printf(char *format, ...);
|
||||
|
||||
extern HWND hwndHistoryList;
|
||||
extern bool TASEdit_bind_markers;
|
||||
extern bool TASEdit_enable_hot_changes;
|
||||
extern bool TASEdit_branch_full_movie;
|
||||
|
||||
extern MARKERS markers;
|
||||
extern BOOKMARKS bookmarks;
|
||||
|
@ -68,13 +68,13 @@ void INPUT_HISTORY::init(int new_size)
|
|||
undo_hint_pos = old_undo_hint_pos = undo_hint_time = -1;
|
||||
old_show_undo_hint = show_undo_hint = false;
|
||||
// clear snapshots history
|
||||
history_total_items = 0;
|
||||
free();
|
||||
input_snapshots.resize(history_size);
|
||||
history_start_pos = 0;
|
||||
history_cursor_pos = -1;
|
||||
// create initial snapshot
|
||||
INPUT_SNAPSHOT inp;
|
||||
inp.init(currMovieData, true);
|
||||
inp.init(currMovieData, TASEdit_enable_hot_changes);
|
||||
strcat(inp.description, modCaptions[0]);
|
||||
inp.jump_frame = -1;
|
||||
AddInputSnapshotToHistory(inp);
|
||||
|
@ -85,6 +85,7 @@ void INPUT_HISTORY::init(int new_size)
|
|||
void INPUT_HISTORY::free()
|
||||
{
|
||||
input_snapshots.resize(0);
|
||||
history_total_items = 0;
|
||||
}
|
||||
|
||||
void INPUT_HISTORY::update()
|
||||
|
@ -149,11 +150,16 @@ int INPUT_HISTORY::jump(int new_pos)
|
|||
currMovieData.records.resize(input_snapshots[real_pos].size);
|
||||
input_snapshots[real_pos].toMovie(currMovieData, first_change);
|
||||
bookmarks.ChangesMadeSinceBranch();
|
||||
// list will be redrawn by greenzone invalidation
|
||||
} else if (markers_changed)
|
||||
{
|
||||
markers.update();
|
||||
bookmarks.ChangesMadeSinceBranch();
|
||||
RedrawList();
|
||||
} else if (TASEdit_enable_hot_changes)
|
||||
{
|
||||
// when using Hot Changes, list should be always redrawn, because old changes become less hot
|
||||
RedrawList();
|
||||
}
|
||||
|
||||
return first_change;
|
||||
|
@ -173,7 +179,7 @@ void INPUT_HISTORY::AddInputSnapshotToHistory(INPUT_SNAPSHOT &inp)
|
|||
int real_pos;
|
||||
if (history_cursor_pos+1 >= history_size)
|
||||
{
|
||||
// reached the end of available history_size - move history_start_pos (thus deleting older snapshot)
|
||||
// reached the end of available history_size - move history_start_pos (thus deleting oldest snapshot)
|
||||
history_cursor_pos = history_size-1;
|
||||
history_start_pos = (history_start_pos + 1) % history_size;
|
||||
} else
|
||||
|
@ -211,13 +217,12 @@ void INPUT_HISTORY::AddInputSnapshotToHistory(INPUT_SNAPSHOT &inp)
|
|||
RedrawHistoryList();
|
||||
}
|
||||
|
||||
|
||||
// returns frame of first actual change
|
||||
int INPUT_HISTORY::RegisterChanges(int mod_type, int start, int end)
|
||||
{
|
||||
// create new input shanshot
|
||||
INPUT_SNAPSHOT inp;
|
||||
inp.init(currMovieData, true);
|
||||
inp.init(currMovieData, TASEdit_enable_hot_changes);
|
||||
if (mod_type == MODTYPE_MARKER_SET || mod_type == MODTYPE_MARKER_UNSET)
|
||||
{
|
||||
// special case: changed markers, but input didn't change
|
||||
|
@ -235,6 +240,8 @@ int INPUT_HISTORY::RegisterChanges(int mod_type, int start, int end)
|
|||
strcat(inp.description, "-");
|
||||
strcat(inp.description, framenum);
|
||||
}
|
||||
if (TASEdit_enable_hot_changes)
|
||||
inp.copyHotChanges(&GetCurrentSnapshot());
|
||||
AddInputSnapshotToHistory(inp);
|
||||
bookmarks.ChangesMadeSinceBranch();
|
||||
return -1;
|
||||
|
@ -247,10 +254,6 @@ int INPUT_HISTORY::RegisterChanges(int mod_type, int start, int end)
|
|||
if (first_changes >= 0)
|
||||
{
|
||||
// differences found
|
||||
// fade old hot_changes by 1
|
||||
|
||||
// highlight new hot changes
|
||||
|
||||
// fill description:
|
||||
strcat(inp.description, modCaptions[mod_type]);
|
||||
switch (mod_type)
|
||||
|
@ -278,14 +281,14 @@ int INPUT_HISTORY::RegisterChanges(int mod_type, int start, int end)
|
|||
}
|
||||
case MODTYPE_RECORD:
|
||||
{
|
||||
// add info which joypads were affected
|
||||
inp.jump_frame = start;
|
||||
// also add info which joypads were affected
|
||||
int num = (inp.input_type + 1) * 2; // hacky, only for distingushing between normal2p and fourscore
|
||||
for (int i = 0; i < num; ++i)
|
||||
{
|
||||
if (inp.checkJoypadDiff(input_snapshots[real_pos], first_changes, i))
|
||||
strcat(inp.description, joypadCaptions[i]);
|
||||
}
|
||||
inp.jump_frame = start;
|
||||
}
|
||||
}
|
||||
// add upper and lower frame to description
|
||||
|
@ -299,21 +302,75 @@ int INPUT_HISTORY::RegisterChanges(int mod_type, int start, int end)
|
|||
strcat(inp.description, "-");
|
||||
strcat(inp.description, framenum);
|
||||
}
|
||||
// set hotchanges
|
||||
if (TASEdit_enable_hot_changes)
|
||||
{
|
||||
// inherit previous hotchanges and set new changes
|
||||
switch (mod_type)
|
||||
{
|
||||
case MODTYPE_DELETE:
|
||||
inp.inheritHotChanges_DeleteSelection(&input_snapshots[real_pos]);
|
||||
break;
|
||||
case MODTYPE_INSERT:
|
||||
case MODTYPE_PASTEINSERT:
|
||||
case MODTYPE_CLONE:
|
||||
inp.inheritHotChanges_InsertSelection(&input_snapshots[real_pos]);
|
||||
break;
|
||||
case MODTYPE_CHANGE:
|
||||
case MODTYPE_SET:
|
||||
case MODTYPE_UNSET:
|
||||
case MODTYPE_CLEAR:
|
||||
case MODTYPE_CUT:
|
||||
case MODTYPE_PASTE:
|
||||
case MODTYPE_RECORD:
|
||||
inp.inheritHotChanges(&input_snapshots[real_pos]);
|
||||
inp.fillHotChanges(input_snapshots[real_pos], first_changes, end);
|
||||
break;
|
||||
case MODTYPE_TRUNCATE:
|
||||
inp.copyHotChanges(&input_snapshots[real_pos]);
|
||||
// do not add new hotchanges and do not fade old hotchanges, because there was nothing added
|
||||
break;
|
||||
case MODTYPE_IMPORT:
|
||||
// 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, end);
|
||||
break;
|
||||
}
|
||||
}
|
||||
AddInputSnapshotToHistory(inp);
|
||||
bookmarks.ChangesMadeSinceBranch();
|
||||
}
|
||||
return first_changes;
|
||||
}
|
||||
}
|
||||
void INPUT_HISTORY::RegisterBranch(int mod_type, int first_change, char* branch_creation_time)
|
||||
void INPUT_HISTORY::RegisterBranching(int mod_type, int first_change, int slot)
|
||||
{
|
||||
// create new input shanshot
|
||||
// create new input snapshot
|
||||
INPUT_SNAPSHOT inp;
|
||||
inp.init(currMovieData, true);
|
||||
// fill description:
|
||||
inp.init(currMovieData, TASEdit_enable_hot_changes);
|
||||
// fill description: modification type + time of the Branch
|
||||
strcat(inp.description, modCaptions[mod_type]);
|
||||
strcat(inp.description, branch_creation_time);
|
||||
strcat(inp.description, bookmarks.bookmarks_array[slot].snapshot.description);
|
||||
inp.jump_frame = first_change;
|
||||
if (TASEdit_enable_hot_changes)
|
||||
{
|
||||
if (mod_type < MODTYPE_BRANCH_MARKERS_0)
|
||||
{
|
||||
// input was changed
|
||||
// copy hotchanges of the Branch
|
||||
if (TASEdit_branch_full_movie)
|
||||
{
|
||||
inp.copyHotChanges(&bookmarks.bookmarks_array[slot].snapshot);
|
||||
} else
|
||||
{
|
||||
// input was branched partially, so copy hotchanges only up to and not including jump_frame of the Branch
|
||||
inp.copyHotChanges(&bookmarks.bookmarks_array[slot].snapshot, bookmarks.bookmarks_array[slot].snapshot.jump_frame);
|
||||
}
|
||||
} else
|
||||
{
|
||||
// input was not changed, only Markers were changed
|
||||
inp.copyHotChanges(&GetCurrentSnapshot());
|
||||
}
|
||||
}
|
||||
AddInputSnapshotToHistory(inp);
|
||||
}
|
||||
|
||||
|
@ -345,8 +402,8 @@ bool INPUT_HISTORY::load(EMUFILE *is)
|
|||
if ((int)is->fread(save_id, HISTORY_ID_LEN) < HISTORY_ID_LEN) goto error;
|
||||
if (strcmp(history_save_id, save_id)) goto error; // string is not valid
|
||||
// read vars
|
||||
if (!read32le((uint32 *)&history_cursor_pos, is)) goto error;
|
||||
if (!read32le((uint32 *)&history_total_items, is)) goto error;
|
||||
if (!read32le(&history_cursor_pos, is)) goto error;
|
||||
if (!read32le(&history_total_items, is)) goto error;
|
||||
if (history_cursor_pos > history_total_items) goto error;
|
||||
history_start_pos = 0;
|
||||
// read snapshots
|
||||
|
@ -373,7 +430,6 @@ bool INPUT_HISTORY::load(EMUFILE *is)
|
|||
// load snapshots
|
||||
for (i = 0; i < history_total_items; ++i)
|
||||
{
|
||||
// skip snapshots if current history_size is less then history_total_items
|
||||
if (input_snapshots[i].load(is)) goto error;
|
||||
playback.SetProgressbar(i, history_total_items);
|
||||
}
|
||||
|
|
|
@ -63,11 +63,7 @@ public:
|
|||
void AddInputSnapshotToHistory(INPUT_SNAPSHOT &inp);
|
||||
|
||||
int RegisterChanges(int mod_type, int start = 0, int end =-1);
|
||||
void RegisterBranch(int mod_type, int first_change, char* branch_creation_time);
|
||||
|
||||
int InputChanged(int start, int end);
|
||||
int InputInserted(int start);
|
||||
int InputDeleted(int start);
|
||||
void RegisterBranching(int mod_type, int first_change, int slot);
|
||||
|
||||
INPUT_SNAPSHOT& GetCurrentSnapshot();
|
||||
INPUT_SNAPSHOT& GetNextToCurrentSnapshot();
|
||||
|
|
|
@ -1,8 +1,6 @@
|
|||
//Implementation file of Input Snapshot class (Undo feature)
|
||||
|
||||
#include "movie.h"
|
||||
#include "inputsnapshot.h"
|
||||
#include "markers.h"
|
||||
#include "taseditproj.h"
|
||||
#include "zlib.h"
|
||||
|
||||
const int bytes_per_frame[NUM_SUPPORTED_INPUT_TYPES] = {2, 4}; // 16bits for normal joypads, 32bits for fourscore
|
||||
|
@ -10,10 +8,10 @@ const int bytes_per_frame[NUM_SUPPORTED_INPUT_TYPES] = {2, 4}; // 16bits for nor
|
|||
extern void FCEU_printf(char *format, ...);
|
||||
|
||||
extern MARKERS markers;
|
||||
extern TASEDIT_SELECTION selection;
|
||||
|
||||
INPUT_SNAPSHOT::INPUT_SNAPSHOT()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
void INPUT_SNAPSHOT::init(MovieData& md, bool hotchanges)
|
||||
|
@ -64,6 +62,7 @@ void INPUT_SNAPSHOT::init(MovieData& md, bool hotchanges)
|
|||
struct tm * timeinfo = localtime(&raw_time);
|
||||
strftime(description, 10, "%H:%M:%S", timeinfo);
|
||||
}
|
||||
|
||||
// copy all stored markers to Markers
|
||||
void INPUT_SNAPSHOT::toMarkers()
|
||||
{
|
||||
|
@ -72,7 +71,7 @@ void INPUT_SNAPSHOT::toMarkers()
|
|||
// copy some stored markers to Markers manually, from Frame 0 to end frame (including end frame)
|
||||
void INPUT_SNAPSHOT::copyToMarkers(int end)
|
||||
{
|
||||
if (markers.markers_array.size() <= end) markers.markers_array.resize(end+1);
|
||||
if ((int)markers.markers_array.size() <= end) markers.markers_array.resize(end+1);
|
||||
for (int i = end; i >= 0; i--)
|
||||
markers.markers_array[i] = markers_array[i];
|
||||
}
|
||||
|
@ -178,7 +177,6 @@ void INPUT_SNAPSHOT::save(EMUFILE *os)
|
|||
// returns true if couldn't load
|
||||
bool INPUT_SNAPSHOT::load(EMUFILE *is)
|
||||
{
|
||||
int len;
|
||||
uint8 tmp;
|
||||
// read vars
|
||||
if (!read32le(&size, is)) return true;
|
||||
|
@ -326,7 +324,7 @@ bool INPUT_SNAPSHOT::checkMarkersDiff()
|
|||
// return true only when difference is found before end frame (not including end frame)
|
||||
bool INPUT_SNAPSHOT::checkMarkersDiff(int end)
|
||||
{
|
||||
if (markers_array.size() != markers.markers_array.size() && (markers_array.size()-1 < end || markers.markers_array.size()-1 < end)) return true;
|
||||
if (markers_array.size() != markers.markers_array.size() && ((int)markers_array.size()-1 < end || (int)markers.markers_array.size()-1 < end)) return true;
|
||||
for (int i = end-1; i >= 0; i--)
|
||||
if ((markers_array[i] - markers.markers_array[i]) & MARKER_FLAG_BIT) return true;
|
||||
return false;
|
||||
|
@ -338,7 +336,6 @@ int INPUT_SNAPSHOT::findFirstChange(INPUT_SNAPSHOT& inp, int start, int end)
|
|||
// 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;
|
||||
|
||||
switch(input_type)
|
||||
{
|
||||
case FOURSCORE:
|
||||
|
@ -391,7 +388,7 @@ int INPUT_SNAPSHOT::findFirstChange(INPUT_SNAPSHOT& inp, int start, int end)
|
|||
}
|
||||
}
|
||||
// if current size is less then previous, return size-1 as the frame of difference
|
||||
if (size < inp.size) return size-1;
|
||||
if (size < inp_end) return size-1;
|
||||
// no changes were found
|
||||
return -1;
|
||||
}
|
||||
|
@ -432,7 +429,214 @@ int INPUT_SNAPSHOT::findFirstChange(MovieData& md, int start, int end)
|
|||
|
||||
return -1; // no changes were found
|
||||
}
|
||||
// --------------------------------------------------------
|
||||
void INPUT_SNAPSHOT::copyHotChanges(INPUT_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)
|
||||
{
|
||||
int min = hot_changes.size();
|
||||
if (min > (int)source_of_hotchanges->hot_changes.size())
|
||||
min = source_of_hotchanges->hot_changes.size();
|
||||
|
||||
// special case for Branches: if limit_frame if specified, then copy only hotchanges from 0 to limit_frame
|
||||
if (limit_frame_of_source >= 0)
|
||||
{
|
||||
if (min > limit_frame_of_source * bytes_per_frame[input_type] * HOTCHANGE_BYTES_PER_JOY)
|
||||
min = limit_frame_of_source * bytes_per_frame[input_type] * HOTCHANGE_BYTES_PER_JOY;
|
||||
}
|
||||
|
||||
memcpy(&hot_changes[0], &source_of_hotchanges->hot_changes[0], min);
|
||||
}
|
||||
}
|
||||
void INPUT_SNAPSHOT::inheritHotChanges(INPUT_SNAPSHOT* source_of_hotchanges)
|
||||
{
|
||||
// copy hot changes from source snapshot and fade them
|
||||
if (source_of_hotchanges && source_of_hotchanges->has_hot_changes)
|
||||
{
|
||||
int min = hot_changes.size();
|
||||
if (min > (int)source_of_hotchanges->hot_changes.size())
|
||||
min = source_of_hotchanges->hot_changes.size();
|
||||
|
||||
memcpy(&hot_changes[0], &source_of_hotchanges->hot_changes[0], min);
|
||||
FadeHotChanges();
|
||||
}
|
||||
}
|
||||
void INPUT_SNAPSHOT::inheritHotChanges_DeleteSelection(INPUT_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)
|
||||
{
|
||||
int bytes = bytes_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.CurrentSelection().begin());
|
||||
while (pos < this_size && source_pos < source_size)
|
||||
{
|
||||
if (it != selection.CurrentSelection().end() && frame == *it)
|
||||
{
|
||||
// this frame is selected
|
||||
it++;
|
||||
// omit the frame
|
||||
source_pos += bytes;
|
||||
} else
|
||||
{
|
||||
// copy hotchanges of this frame
|
||||
memcpy(&hot_changes[pos], &source_of_hotchanges->hot_changes[source_pos], bytes);
|
||||
pos += bytes;
|
||||
source_pos += bytes;
|
||||
}
|
||||
frame++;
|
||||
}
|
||||
FadeHotChanges();
|
||||
}
|
||||
}
|
||||
void INPUT_SNAPSHOT::inheritHotChanges_InsertSelection(INPUT_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)
|
||||
{
|
||||
int bytes = bytes_per_frame[input_type] * HOTCHANGE_BYTES_PER_JOY;
|
||||
int frame = 0, region_len = 0, pos = 0, source_pos = 0;
|
||||
int this_size = hot_changes.size(), source_size = source_of_hotchanges->hot_changes.size();
|
||||
SelectionFrames::iterator it(selection.CurrentSelection().begin());
|
||||
while (pos < this_size && source_pos < source_size)
|
||||
{
|
||||
if (it != selection.CurrentSelection().end() && frame == *it)
|
||||
{
|
||||
// this frame is selected
|
||||
it++;
|
||||
region_len++;
|
||||
// set filled line to the frame
|
||||
memset(&hot_changes[pos], 0xFF, bytes);
|
||||
pos += bytes;
|
||||
} else
|
||||
{
|
||||
// this frame is not selected
|
||||
frame -= region_len;
|
||||
region_len = 0;
|
||||
// copy hotchanges of this frame
|
||||
memcpy(&hot_changes[pos], &source_of_hotchanges->hot_changes[source_pos], bytes);
|
||||
pos += bytes;
|
||||
source_pos += bytes;
|
||||
}
|
||||
frame++;
|
||||
}
|
||||
FadeHotChanges();
|
||||
} else
|
||||
{
|
||||
// no old data, just fill selected lines
|
||||
int bytes = bytes_per_frame[input_type] * HOTCHANGE_BYTES_PER_JOY;
|
||||
int frame = 0, region_len = 0, pos = 0;
|
||||
int this_size = hot_changes.size();
|
||||
SelectionFrames::iterator it(selection.CurrentSelection().begin());
|
||||
while (pos < this_size)
|
||||
{
|
||||
if (it != selection.CurrentSelection().end() && frame == *it)
|
||||
{
|
||||
// this frame is selected
|
||||
it++;
|
||||
region_len++;
|
||||
// set filled line to the frame
|
||||
memset(&hot_changes[pos], 0xFF, bytes);
|
||||
pos += bytes;
|
||||
// exit loop when all selection frames are handled
|
||||
if (it == selection.CurrentSelection().end()) break;
|
||||
} else
|
||||
{
|
||||
// this frame is not selected
|
||||
frame -= region_len;
|
||||
region_len = 0;
|
||||
// leave zeros in this frame
|
||||
pos += bytes;
|
||||
}
|
||||
frame++;
|
||||
}
|
||||
}
|
||||
}
|
||||
void INPUT_SNAPSHOT::fillHotChanges(INPUT_SNAPSHOT& inp, int start, int end)
|
||||
{
|
||||
// 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;
|
||||
switch(input_type)
|
||||
{
|
||||
case FOURSCORE:
|
||||
{
|
||||
for (int frame = start, pos = start * bytes_per_frame[input_type]; frame <= end; ++frame)
|
||||
{
|
||||
// set changed if found different byte, or found emptiness in inp when there's non-zero value here
|
||||
if (frame < inp_end)
|
||||
{
|
||||
if (joysticks[pos] != inp.joysticks[pos])
|
||||
SetMaxHotChange_Bits(frame, 0, joysticks[pos] ^ inp.joysticks[pos]);
|
||||
pos++;
|
||||
if (joysticks[pos] != inp.joysticks[pos])
|
||||
SetMaxHotChange_Bits(frame, 1, joysticks[pos] ^ inp.joysticks[pos]);
|
||||
pos++;
|
||||
if (joysticks[pos] != inp.joysticks[pos])
|
||||
SetMaxHotChange_Bits(frame, 2, joysticks[pos] ^ inp.joysticks[pos]);
|
||||
pos++;
|
||||
if (joysticks[pos] != inp.joysticks[pos])
|
||||
SetMaxHotChange_Bits(frame, 3, joysticks[pos] ^ inp.joysticks[pos]);
|
||||
pos++;
|
||||
} else
|
||||
{
|
||||
if (joysticks[pos])
|
||||
SetMaxHotChange_Bits(frame, 0, joysticks[pos]);
|
||||
pos++;
|
||||
if (joysticks[pos])
|
||||
SetMaxHotChange_Bits(frame, 1, joysticks[pos]);
|
||||
pos++;
|
||||
if (joysticks[pos])
|
||||
SetMaxHotChange_Bits(frame, 2, joysticks[pos]);
|
||||
pos++;
|
||||
if (joysticks[pos])
|
||||
SetMaxHotChange_Bits(frame, 3, joysticks[pos]);
|
||||
pos++;
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
case NORMAL_2JOYPADS:
|
||||
{
|
||||
for (int frame = start, pos = start * bytes_per_frame[input_type]; frame <= end; ++frame)
|
||||
{
|
||||
// set changed if found different byte, or found emptiness in inp when there's non-zero value here
|
||||
if (frame < inp_end)
|
||||
{
|
||||
if (joysticks[pos] != inp.joysticks[pos])
|
||||
SetMaxHotChange_Bits(frame, 0, joysticks[pos] ^ inp.joysticks[pos]);
|
||||
pos++;
|
||||
if (joysticks[pos] != inp.joysticks[pos])
|
||||
SetMaxHotChange_Bits(frame, 1, joysticks[pos] ^ inp.joysticks[pos]);
|
||||
pos++;
|
||||
} else
|
||||
{
|
||||
if (joysticks[pos])
|
||||
SetMaxHotChange_Bits(frame, 0, joysticks[pos]);
|
||||
pos++;
|
||||
if (joysticks[pos])
|
||||
SetMaxHotChange_Bits(frame, 1, joysticks[pos]);
|
||||
pos++;
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void INPUT_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
|
||||
for (int i = 0; i < 8; ++i)
|
||||
{
|
||||
if (joy_bits & mask)
|
||||
SetMaxHotChange(frame, joypad * 8 + i);
|
||||
mask <<= 1;
|
||||
}
|
||||
}
|
||||
void INPUT_SNAPSHOT::SetMaxHotChange(int frame, int absolute_button)
|
||||
{
|
||||
if (frame < 0 || frame >= size || !has_hot_changes) return;
|
||||
|
@ -444,10 +648,10 @@ void INPUT_SNAPSHOT::SetMaxHotChange(int frame, int absolute_button)
|
|||
// 32 buttons = 16bytes
|
||||
if (absolute_button & 1)
|
||||
// odd buttons (B, T, D, R) - set upper 4 bits of the byte
|
||||
hot_changes[(frame << 4) | (absolute_button >> 1)] &= 0xF0;
|
||||
hot_changes[(frame << 4) | (absolute_button >> 1)] |= 0xF0;
|
||||
else
|
||||
// even buttons (A, S, U, L) - set lower 4 bits of the byte
|
||||
hot_changes[(frame << 4) | (absolute_button >> 1)] &= 0x0F;
|
||||
hot_changes[(frame << 4) | (absolute_button >> 1)] |= 0x0F;
|
||||
break;
|
||||
}
|
||||
case NORMAL_2JOYPADS:
|
||||
|
@ -455,18 +659,35 @@ void INPUT_SNAPSHOT::SetMaxHotChange(int frame, int absolute_button)
|
|||
// 16 buttons = 8bytes
|
||||
if (absolute_button & 1)
|
||||
// odd buttons (B, T, D, R) - set upper 4 bits of the byte
|
||||
hot_changes[(frame << 3) | (absolute_button >> 1)] &= 0xF0;
|
||||
hot_changes[(frame << 3) | (absolute_button >> 1)] |= 0xF0;
|
||||
else
|
||||
// even buttons (A, S, U, L) - set lower 4 bits of the byte
|
||||
hot_changes[(frame << 3) | (absolute_button >> 1)] &= 0x0F;
|
||||
hot_changes[(frame << 3) | (absolute_button >> 1)] |= 0x0F;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void INPUT_SNAPSHOT::FadeHotChanges()
|
||||
{
|
||||
uint8 hi_half, low_half;
|
||||
for (int i = hot_changes.size() - 1; i >= 0; i--)
|
||||
{
|
||||
if (hot_changes[i])
|
||||
{
|
||||
hi_half = hot_changes[i] >> 4;
|
||||
low_half = hot_changes[i] & 15;
|
||||
if (hi_half) hi_half--;
|
||||
if (low_half) low_half--;
|
||||
hot_changes[i] = (hi_half << 4) | low_half;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
int INPUT_SNAPSHOT::GetHotChangeInfo(int frame, int absolute_button)
|
||||
{
|
||||
if (frame < 0 || frame >= size || !has_hot_changes) return 0;
|
||||
if (absolute_button < 0 || absolute_button > 31) return 0;
|
||||
if (!has_hot_changes || frame < 0 || frame >= size || absolute_button < 0 || absolute_button > 31)
|
||||
return 0;
|
||||
|
||||
uint8 val;
|
||||
switch(input_type)
|
||||
|
@ -493,4 +714,3 @@ int INPUT_SNAPSHOT::GetHotChangeInfo(int frame, int absolute_button)
|
|||
return val & 15;
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -33,11 +33,21 @@ public:
|
|||
int findFirstChange(INPUT_SNAPSHOT& inp, int start = 0, int end = -1);
|
||||
int findFirstChange(MovieData& md, int start = 0, int end = -1);
|
||||
|
||||
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 fillHotChanges(INPUT_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);
|
||||
|
||||
void FadeHotChanges();
|
||||
|
||||
int GetHotChangeInfo(int frame, int absolute_button);
|
||||
|
||||
int size; // in frames
|
||||
int input_type; // 0=normal, 1=fourscore, in future may support other input types
|
||||
int input_type; // 0=normal, 1=fourscore; theoretically TASEdit can support other input types, although some stuff may be unintentionally hardcoded
|
||||
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, ...
|
||||
|
@ -46,6 +56,7 @@ public:
|
|||
bool coherent; // indicates whether this state was made right after previous state
|
||||
int jump_frame; // for jumping when making undo
|
||||
char description[SNAPSHOT_DESC_MAX_LENGTH];
|
||||
bool has_hot_changes;
|
||||
|
||||
private:
|
||||
void compress_data();
|
||||
|
@ -56,6 +67,5 @@ private:
|
|||
std::vector<uint8> hot_changes_compressed;
|
||||
std::vector<uint8> markers_array_compressed;
|
||||
|
||||
bool has_hot_changes;
|
||||
};
|
||||
|
||||
|
|
|
@ -0,0 +1,386 @@
|
|||
//Implementation file of TASEDIT_SELECTION class
|
||||
|
||||
#include "../common.h"
|
||||
#include "taseditproj.h"
|
||||
//#include "../tasedit.h"
|
||||
|
||||
char selection_save_id[SELECTION_ID_LEN] = "SELECTION";
|
||||
|
||||
extern MARKERS markers;
|
||||
|
||||
extern HWND hwndList;
|
||||
extern void RedrawList();
|
||||
|
||||
TASEDIT_SELECTION::TASEDIT_SELECTION()
|
||||
{
|
||||
}
|
||||
|
||||
void TASEDIT_SELECTION::init(int new_size)
|
||||
{
|
||||
// init vars
|
||||
if (new_size > 0)
|
||||
history_size = new_size + 1;
|
||||
// clear selections history
|
||||
free();
|
||||
selections_history.resize(history_size);
|
||||
history_start_pos = 0;
|
||||
history_cursor_pos = -1;
|
||||
// create initial selection
|
||||
AddNewSelectionToHistory();
|
||||
|
||||
track_selection_changes = true;
|
||||
}
|
||||
void TASEDIT_SELECTION::free()
|
||||
{
|
||||
// clear history
|
||||
selections_history.resize(0);
|
||||
history_total_items = 0;
|
||||
clipboard_selection.clear();
|
||||
}
|
||||
|
||||
void TASEDIT_SELECTION::update()
|
||||
{
|
||||
// keep selection within list limits
|
||||
if (CurrentSelection().size())
|
||||
{
|
||||
int delete_index;
|
||||
int movie_size = currMovieData.getNumRecords();
|
||||
while(1)
|
||||
{
|
||||
delete_index = *CurrentSelection().rbegin();
|
||||
if (delete_index < movie_size) break;
|
||||
CurrentSelection().erase(delete_index);
|
||||
if (!CurrentSelection().size()) break;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
bool TASEDIT_SELECTION::CheckFrameSelected(int frame)
|
||||
{
|
||||
if(CurrentSelection().find(frame) == CurrentSelection().end())
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
void TASEDIT_SELECTION::save(EMUFILE *os)
|
||||
{
|
||||
// write "SELECTION" string
|
||||
os->fwrite(selection_save_id, SELECTION_ID_LEN);
|
||||
// write vars
|
||||
write32le(history_cursor_pos, os);
|
||||
write32le(history_total_items, os);
|
||||
// write selections starting from history_start_pos
|
||||
for (int i = 0; i < history_total_items; ++i)
|
||||
{
|
||||
saveSelection(selections_history[(history_start_pos + i) % history_size], os);
|
||||
}
|
||||
// write clipboard_selection
|
||||
saveSelection(clipboard_selection, os);
|
||||
}
|
||||
// returns true if couldn't load
|
||||
bool TASEDIT_SELECTION::load(EMUFILE *is)
|
||||
{
|
||||
// read "SELECTION" string
|
||||
char save_id[SELECTION_ID_LEN];
|
||||
if ((int)is->fread(save_id, SELECTION_ID_LEN) < SELECTION_ID_LEN) goto error;
|
||||
if (strcmp(selection_save_id, save_id)) goto error; // string is not valid
|
||||
// read vars
|
||||
if (!read32le(&history_cursor_pos, is)) goto error;
|
||||
if (!read32le(&history_total_items, is)) goto error;
|
||||
if (history_cursor_pos > history_total_items) goto error;
|
||||
history_start_pos = 0;
|
||||
// read selections
|
||||
int i;
|
||||
int total = history_total_items;
|
||||
if (history_total_items > history_size)
|
||||
{
|
||||
// user can't afford that much undo levels, skip some selections
|
||||
int num_selections_to_skip = history_total_items - history_size;
|
||||
// first try to skip selections over history_cursor_pos (future selections), because "redo" is less important than "undo"
|
||||
int num_redo_selections = history_total_items-1 - history_cursor_pos;
|
||||
if (num_selections_to_skip >= num_redo_selections)
|
||||
{
|
||||
// skip all redo selections
|
||||
history_total_items = history_cursor_pos+1;
|
||||
num_selections_to_skip -= num_redo_selections;
|
||||
// and still need to skip some undo selections
|
||||
for (i = 0; i < num_selections_to_skip; ++i)
|
||||
if (skiploadSelection(is)) goto error;
|
||||
total -= num_selections_to_skip;
|
||||
history_cursor_pos -= num_selections_to_skip;
|
||||
}
|
||||
history_total_items -= num_selections_to_skip;
|
||||
}
|
||||
// load selections
|
||||
for (i = 0; i < history_total_items; ++i)
|
||||
{
|
||||
if (loadSelection(selections_history[i], is)) goto error;
|
||||
}
|
||||
// skip redo selections if needed
|
||||
for (; i < total; ++i)
|
||||
if (skiploadSelection(is)) goto error;
|
||||
|
||||
// read clipboard_selection
|
||||
if (loadSelection(clipboard_selection, is)) goto error;
|
||||
// all ok
|
||||
EnforceSelectionToList();
|
||||
return false;
|
||||
error:
|
||||
return true;
|
||||
}
|
||||
|
||||
void TASEDIT_SELECTION::saveSelection(SelectionFrames& selection, EMUFILE *os)
|
||||
{
|
||||
write32le(selection.size(), os);
|
||||
if (selection.size())
|
||||
{
|
||||
for(SelectionFrames::iterator it(selection.begin()); it != selection.end(); it++)
|
||||
write32le(*it, os);
|
||||
}
|
||||
}
|
||||
bool TASEDIT_SELECTION::loadSelection(SelectionFrames& selection, EMUFILE *is)
|
||||
{
|
||||
int temp_int, temp_size;
|
||||
selection.clear();
|
||||
if (!read32le(&temp_size, is)) return true;
|
||||
selection.clear();
|
||||
for(; temp_size > 0; temp_size--)
|
||||
{
|
||||
if (!read32le(&temp_int, is)) return true;
|
||||
selection.insert(temp_int);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
bool TASEDIT_SELECTION::skiploadSelection(EMUFILE *is)
|
||||
{
|
||||
int temp_int, temp_size;
|
||||
if (!read32le(&temp_size, is)) return true;
|
||||
for(; temp_size > 0; temp_size--)
|
||||
if (!read32le(&temp_int, is)) return true;
|
||||
return false;
|
||||
}
|
||||
// ----------------------------------------------------------
|
||||
//used to track selection
|
||||
void TASEDIT_SELECTION::ItemRangeChanged(NMLVODSTATECHANGE* info)
|
||||
{
|
||||
bool ON = !(info->uOldState & LVIS_SELECTED) && (info->uNewState & LVIS_SELECTED);
|
||||
bool OFF = (info->uOldState & LVIS_SELECTED) && !(info->uNewState & LVIS_SELECTED);
|
||||
|
||||
if(ON)
|
||||
for(int i = info->iFrom; i <= info->iTo; ++i)
|
||||
CurrentSelection().insert(i);
|
||||
else
|
||||
for(int i = info->iFrom; i <= info->iTo; ++i)
|
||||
CurrentSelection().erase(i);
|
||||
}
|
||||
void TASEDIT_SELECTION::ItemChanged(NMLISTVIEW* info)
|
||||
{
|
||||
int item = info->iItem;
|
||||
|
||||
bool ON = !(info->uOldState & LVIS_SELECTED) && (info->uNewState & LVIS_SELECTED);
|
||||
bool OFF = (info->uOldState & LVIS_SELECTED) && !(info->uNewState & LVIS_SELECTED);
|
||||
|
||||
//if the item is -1, apply the change to all items
|
||||
if(item == -1)
|
||||
{
|
||||
if(OFF)
|
||||
{
|
||||
// clear all (actually add new empty selection to history)
|
||||
if (CurrentSelection().size() && track_selection_changes)
|
||||
AddNewSelectionToHistory();
|
||||
} else if (ON)
|
||||
{
|
||||
// select all
|
||||
for(int i = currMovieData.getNumRecords() - 1; i >= 0; i--)
|
||||
{
|
||||
CurrentSelection().insert(i);
|
||||
}
|
||||
}
|
||||
} else
|
||||
{
|
||||
if(ON)
|
||||
CurrentSelection().insert(item);
|
||||
else if(OFF)
|
||||
CurrentSelection().erase(item);
|
||||
}
|
||||
}
|
||||
// ----------------------------------------------------------
|
||||
void TASEDIT_SELECTION::AddNewSelectionToHistory()
|
||||
{
|
||||
// create new empty selection
|
||||
SelectionFrames selectionFrames;
|
||||
// increase current position
|
||||
// history uses conveyor of selections (vector with fixed size) to avoid resizing
|
||||
if (history_cursor_pos+1 >= history_size)
|
||||
{
|
||||
// reached the end of available history_size - move history_start_pos (thus deleting oldest selection)
|
||||
history_cursor_pos = history_size-1;
|
||||
history_start_pos = (history_start_pos + 1) % history_size;
|
||||
} else
|
||||
{
|
||||
// didn't reach the end of history yet
|
||||
history_cursor_pos++;
|
||||
if (history_cursor_pos >= history_total_items)
|
||||
history_total_items = history_cursor_pos+1;
|
||||
}
|
||||
// add
|
||||
selections_history[(history_start_pos + history_cursor_pos) % history_size] = selectionFrames;
|
||||
}
|
||||
|
||||
SelectionFrames& TASEDIT_SELECTION::CurrentSelection()
|
||||
{
|
||||
return selections_history[(history_start_pos + history_cursor_pos) % history_size];
|
||||
}
|
||||
|
||||
void TASEDIT_SELECTION::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 (new_pos == history_cursor_pos) return;
|
||||
|
||||
// make jump
|
||||
history_cursor_pos = new_pos;
|
||||
// update list items
|
||||
EnforceSelectionToList();
|
||||
// also keep selection within list
|
||||
update();
|
||||
}
|
||||
void TASEDIT_SELECTION::undo()
|
||||
{
|
||||
jump(history_cursor_pos - 1);
|
||||
}
|
||||
void TASEDIT_SELECTION::redo()
|
||||
{
|
||||
jump(history_cursor_pos + 1);
|
||||
}
|
||||
|
||||
void TASEDIT_SELECTION::MemorizeClipboardSelection()
|
||||
{
|
||||
// copy current selection data to clipboard_selection
|
||||
clipboard_selection = CurrentSelection();
|
||||
}
|
||||
void TASEDIT_SELECTION::ReselectClipboard()
|
||||
{
|
||||
if (clipboard_selection.size() == 0) return;
|
||||
|
||||
ClearSelection();
|
||||
CurrentSelection() = clipboard_selection;
|
||||
EnforceSelectionToList();
|
||||
// also keep selection within list
|
||||
update();
|
||||
}
|
||||
// ----------------------------------------------------------
|
||||
void TASEDIT_SELECTION::ClearSelection()
|
||||
{
|
||||
ListView_SetItemState(hwndList, -1, 0, LVIS_FOCUSED|LVIS_SELECTED);
|
||||
}
|
||||
void TASEDIT_SELECTION::ClearRowSelection(int index)
|
||||
{
|
||||
ListView_SetItemState(hwndList, index, 0, LVIS_SELECTED);
|
||||
}
|
||||
|
||||
void TASEDIT_SELECTION::EnforceSelectionToList()
|
||||
{
|
||||
track_selection_changes = false;
|
||||
ClearSelection();
|
||||
for(SelectionFrames::reverse_iterator it(CurrentSelection().rbegin()); it != CurrentSelection().rend(); it++)
|
||||
{
|
||||
ListView_SetItemState(hwndList, *it, LVIS_SELECTED, LVIS_SELECTED);
|
||||
}
|
||||
track_selection_changes = true;
|
||||
}
|
||||
|
||||
void TASEDIT_SELECTION::SelectAll()
|
||||
{
|
||||
ListView_SetItemState(hwndList, -1, LVIS_SELECTED, LVIS_SELECTED);
|
||||
//RedrawList();
|
||||
}
|
||||
void TASEDIT_SELECTION::SetRowSelection(int index)
|
||||
{
|
||||
ListView_SetItemState(hwndList, index, LVIS_SELECTED, LVIS_SELECTED);
|
||||
}
|
||||
void TASEDIT_SELECTION::SetRegionSelection(int start, int end)
|
||||
{
|
||||
for (int i = start; i <= end; ++i)
|
||||
ListView_SetItemState(hwndList, i, LVIS_SELECTED, LVIS_SELECTED);
|
||||
}
|
||||
void TASEDIT_SELECTION::SelectMidMarkers()
|
||||
{
|
||||
int center, upper_border, lower_border;
|
||||
int upper_marker, lower_marker;
|
||||
int movie_size = currMovieData.getNumRecords();
|
||||
|
||||
// if selection size=0 then playback cursor is selected and serves as center
|
||||
if (CurrentSelection().size())
|
||||
{
|
||||
upper_border = center = *CurrentSelection().begin();
|
||||
lower_border = *CurrentSelection().rbegin();
|
||||
} else lower_border = upper_border = center = currFrameCounter;
|
||||
|
||||
// find markers
|
||||
// searching up starting from center-0
|
||||
for (upper_marker = center; upper_marker >= 0; upper_marker--)
|
||||
if (markers.markers_array[upper_marker] & MARKER_FLAG_BIT) break;
|
||||
// searching down starting from center+1
|
||||
for (lower_marker = center+1; lower_marker < movie_size; ++lower_marker)
|
||||
if (markers.markers_array[lower_marker] & MARKER_FLAG_BIT) 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(hwndList, -1, 0, LVIS_SELECTED);
|
||||
|
||||
// special case
|
||||
if (upper_marker == -1 && lower_marker == movie_size)
|
||||
{
|
||||
SelectAll();
|
||||
return;
|
||||
}
|
||||
|
||||
// selecting circle:
|
||||
if (upper_border > upper_marker+1 || lower_border < lower_marker-1 || lower_border > lower_marker)
|
||||
{
|
||||
// default: select all between markers
|
||||
for (int i = upper_marker+1; i < lower_marker; ++i)
|
||||
{
|
||||
ListView_SetItemState(hwndList, i, LVIS_SELECTED, LVIS_SELECTED);
|
||||
}
|
||||
} else if (upper_border == upper_marker+1 && lower_border == lower_marker-1)
|
||||
{
|
||||
// already selected all between markers - now select both markers or at least select the marker that is not outside movie range
|
||||
if (upper_marker < 0) upper_marker = 0;
|
||||
if (lower_marker >= movie_size) lower_marker = movie_size - 1;
|
||||
for (int i = upper_marker; i <= lower_marker; ++i)
|
||||
{
|
||||
ListView_SetItemState(hwndList, i, LVIS_SELECTED, LVIS_SELECTED);
|
||||
}
|
||||
} else if (upper_border <= upper_marker && lower_border >= lower_marker)
|
||||
{
|
||||
// selected all between markers and both markers selected too - now deselect lower marker
|
||||
for (int i = upper_marker; i < lower_marker; ++i)
|
||||
{
|
||||
ListView_SetItemState(hwndList, i, LVIS_SELECTED, LVIS_SELECTED);
|
||||
}
|
||||
} else if (upper_border == upper_marker && lower_border == lower_marker-1)
|
||||
{
|
||||
// selected all between markers and upper marker selected too - now deselect upper marker and (if lower marker < movie_size) reselect lower marker
|
||||
if (lower_marker >= movie_size) lower_marker = movie_size - 1;
|
||||
for (int i = upper_marker+1; i <= lower_marker; ++i)
|
||||
{
|
||||
ListView_SetItemState(hwndList, i, LVIS_SELECTED, LVIS_SELECTED);
|
||||
}
|
||||
} else if (upper_border == upper_marker+1 && lower_border == lower_marker)
|
||||
{
|
||||
// selected all between markers and lower marker selected too - now deselect lower marker (return to "selected all between markers")
|
||||
for (int i = upper_marker + 1; i < lower_marker; ++i)
|
||||
{
|
||||
ListView_SetItemState(hwndList, i, LVIS_SELECTED, LVIS_SELECTED);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
|
@ -0,0 +1,57 @@
|
|||
//Specification file for TASEDIT_SELECTION class
|
||||
|
||||
#define SELECTION_ID_LEN 10
|
||||
|
||||
class TASEDIT_SELECTION
|
||||
{
|
||||
public:
|
||||
TASEDIT_SELECTION();
|
||||
void init(int new_size = 0);
|
||||
void free();
|
||||
void update();
|
||||
|
||||
void save(EMUFILE *os);
|
||||
bool load(EMUFILE *is);
|
||||
void saveSelection(SelectionFrames& selection, EMUFILE *os);
|
||||
bool loadSelection(SelectionFrames& selection, EMUFILE *is);
|
||||
bool skiploadSelection(EMUFILE *is);
|
||||
|
||||
void ItemRangeChanged(NMLVODSTATECHANGE* info);
|
||||
void ItemChanged(NMLISTVIEW* info);
|
||||
|
||||
void AddNewSelectionToHistory();
|
||||
SelectionFrames& CurrentSelection();
|
||||
|
||||
void undo();
|
||||
void redo();
|
||||
void jump(int new_pos);
|
||||
|
||||
void MemorizeClipboardSelection();
|
||||
void ReselectClipboard();
|
||||
|
||||
void ClearSelection();
|
||||
void ClearRowSelection(int index);
|
||||
|
||||
void EnforceSelectionToList();
|
||||
|
||||
void SelectAll();
|
||||
void SetRowSelection(int index);
|
||||
void SetRegionSelection(int start, int end);
|
||||
void SelectMidMarkers();
|
||||
|
||||
|
||||
bool CheckFrameSelected(int frame);
|
||||
|
||||
private:
|
||||
bool track_selection_changes;
|
||||
|
||||
std::vector<SelectionFrames> selections_history;
|
||||
SelectionFrames clipboard_selection;
|
||||
|
||||
int history_cursor_pos;
|
||||
int history_start_pos;
|
||||
int history_total_items;
|
||||
int history_size;
|
||||
|
||||
|
||||
};
|
|
@ -9,6 +9,7 @@ extern BOOKMARKS bookmarks;
|
|||
extern GREENZONE greenzone;
|
||||
extern PLAYBACK playback;
|
||||
extern INPUT_HISTORY history;
|
||||
extern TASEDIT_SELECTION selection;
|
||||
|
||||
extern void FCEU_printf(char *format, ...);
|
||||
extern int TASEdit_autosave_period;
|
||||
|
@ -57,6 +58,7 @@ bool TASEDIT_PROJECT::saveProject()
|
|||
bookmarks.save(ofs);
|
||||
greenzone.save(ofs);
|
||||
history.save(ofs);
|
||||
selection.save(ofs);
|
||||
|
||||
delete ofs;
|
||||
|
||||
|
@ -79,6 +81,7 @@ bool TASEDIT_PROJECT::LoadProject(std::string PFN)
|
|||
bool error;
|
||||
LoadFM2(currMovieData, &ifs, ifs.size(), false);
|
||||
LoadSubtitles(currMovieData);
|
||||
UpdateList();
|
||||
// try to load markers
|
||||
error = markers.load(&ifs);
|
||||
if (error)
|
||||
|
@ -113,6 +116,15 @@ bool TASEDIT_PROJECT::LoadProject(std::string PFN)
|
|||
{
|
||||
FCEU_printf("Error loading history\n");
|
||||
history.init();
|
||||
} else
|
||||
{
|
||||
// try to load selection
|
||||
error = selection.load(&ifs);
|
||||
}
|
||||
if (error)
|
||||
{
|
||||
FCEU_printf("Error loading selection\n");
|
||||
selection.init();
|
||||
}
|
||||
|
||||
reset();
|
||||
|
|
|
@ -1,12 +1,17 @@
|
|||
//Specification file for the TASEdit Project class
|
||||
|
||||
#include <set>
|
||||
typedef std::set<int> SelectionFrames;
|
||||
|
||||
#include "movie.h"
|
||||
#include "../common.h"
|
||||
#include "inputsnapshot.h"
|
||||
#include "inputhistory.h"
|
||||
#include "playback.h"
|
||||
#include "greenzone.h"
|
||||
#include "markers.h"
|
||||
#include "bookmarks.h"
|
||||
#include "tasedit_sel.h"
|
||||
|
||||
class TASEDIT_PROJECT
|
||||
{
|
||||
|
|
|
@ -426,6 +426,7 @@
|
|||
<ClCompile Include="..\src\drivers\win\taseditlib\inputsnapshot.cpp" />
|
||||
<ClCompile Include="..\src\drivers\win\taseditlib\markers.cpp" />
|
||||
<ClCompile Include="..\src\drivers\win\taseditlib\playback.cpp" />
|
||||
<ClCompile Include="..\src\drivers\win\taseditlib\tasedit_sel.cpp" />
|
||||
<ClCompile Include="..\src\drivers\win\texthook.cpp" />
|
||||
<ClCompile Include="..\src\drivers\win\throttle.cpp" />
|
||||
<ClCompile Include="..\src\drivers\win\timing.cpp" />
|
||||
|
@ -738,6 +739,7 @@
|
|||
<ClInclude Include="..\src\drivers\win\state.h" />
|
||||
<ClInclude Include="..\src\drivers\win\tasedit.h" />
|
||||
<ClInclude Include="..\src\drivers\win\taseditlib\inputhistory.h" />
|
||||
<ClInclude Include="..\src\drivers\win\taseditlib\tasedit_sel.h" />
|
||||
<ClInclude Include="..\src\drivers\win\texthook.h" />
|
||||
<ClInclude Include="..\src\drivers\win\throttle.h" />
|
||||
<ClInclude Include="..\src\drivers\win\timing.h" />
|
||||
|
|
|
@ -928,6 +928,7 @@
|
|||
<ClCompile Include="..\src\drivers\win\taseditlib\playback.cpp">
|
||||
<Filter>drivers\win\taseditlib</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\src\drivers\win\taseditlib\tasedit_sel.cpp" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClInclude Include="..\src\cart.h">
|
||||
|
@ -1375,6 +1376,7 @@
|
|||
<ClInclude Include="..\src\drivers\win\taseditlib\inputhistory.h">
|
||||
<Filter>drivers\win\taseditlib</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\src\drivers\win\taseditlib\tasedit_sel.h" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ResourceCompile Include="..\src\drivers\win\res.rc">
|
||||
|
|
Loading…
Reference in New Issue