* Tasedit: branches autofind best parent
* Tasedit: better hotchanges gradient * Tasedit: "Set Marker"/"Remove marker" in context menu * Tasedit: checking clipboard at selection.init() and retrieving info
This commit is contained in:
parent
1b728ca591
commit
06c4fff479
|
@ -275,8 +275,8 @@ BEGIN
|
||||||
MENUITEM SEPARATOR
|
MENUITEM SEPARATOR
|
||||||
MENUITEM "&Bind Markers to Input", ID_CONFIG_BINDMARKERSTOINPUT
|
MENUITEM "&Bind Markers to Input", ID_CONFIG_BINDMARKERSTOINPUT
|
||||||
MENUITEM SEPARATOR
|
MENUITEM SEPARATOR
|
||||||
MENUITEM "&Use 1P keys for all single Recordings", ID_CONFIG_USE1PFORRECORDING
|
|
||||||
MENUITEM "&Combine consecutive Recordings", ID_CONFIG_COMBINECONSECUTIVERECORDINGS
|
MENUITEM "&Combine consecutive Recordings", ID_CONFIG_COMBINECONSECUTIVERECORDINGS
|
||||||
|
MENUITEM "&Use 1P keys for all single Recordings", ID_CONFIG_USE1PFORRECORDING
|
||||||
MENUITEM "&Superimpose affects copy/paste", ID_CONFIG_SUPERIMPOSE_AFFECTS_PASTE
|
MENUITEM "&Superimpose affects copy/paste", ID_CONFIG_SUPERIMPOSE_AFFECTS_PASTE
|
||||||
MENUITEM SEPARATOR
|
MENUITEM SEPARATOR
|
||||||
MENUITEM "Mute &Turbo", ID_CONFIG_MUTETURBO
|
MENUITEM "Mute &Turbo", ID_CONFIG_MUTETURBO
|
||||||
|
@ -368,6 +368,8 @@ BEGIN
|
||||||
END
|
END
|
||||||
POPUP "Selected"
|
POPUP "Selected"
|
||||||
BEGIN
|
BEGIN
|
||||||
|
MENUITEM "Set Marker", ID_SELECTED_SETMARKER
|
||||||
|
MENUITEM "Remove Marker", ID_SELECTED_REMOVEMARKER
|
||||||
MENUITEM "Select mid &Markers", ID_SELECTED_SELECTMIDMARKERS
|
MENUITEM "Select mid &Markers", ID_SELECTED_SELECTMIDMARKERS
|
||||||
MENUITEM SEPARATOR
|
MENUITEM SEPARATOR
|
||||||
MENUITEM "C&lear", ID_CONTEXT_SELECTED_CLEARFRAMES
|
MENUITEM "C&lear", ID_CONTEXT_SELECTED_CLEARFRAMES
|
||||||
|
|
|
@ -913,6 +913,9 @@
|
||||||
#define ID_EDIT_PASTEINSERT 40495
|
#define ID_EDIT_PASTEINSERT 40495
|
||||||
#define ID_CONFIG_SUPERIMPOSEAFFECTSCOPY 40496
|
#define ID_CONFIG_SUPERIMPOSEAFFECTSCOPY 40496
|
||||||
#define ID_CONFIG_SUPERIMPOSE_AFFECTS_PASTE 40497
|
#define ID_CONFIG_SUPERIMPOSE_AFFECTS_PASTE 40497
|
||||||
|
#define ID_SELECTED_SETMARKER 40498
|
||||||
|
#define ID_SELECTED_CLEARMARKER 40499
|
||||||
|
#define ID_SELECTED_REMOVEMARKER40500 40500
|
||||||
#define IDC_DEBUGGER_ICONTRAY 55535
|
#define IDC_DEBUGGER_ICONTRAY 55535
|
||||||
#define MW_ValueLabel2 65423
|
#define MW_ValueLabel2 65423
|
||||||
#define MW_ValueLabel1 65426
|
#define MW_ValueLabel1 65426
|
||||||
|
@ -922,7 +925,7 @@
|
||||||
#ifdef APSTUDIO_INVOKED
|
#ifdef APSTUDIO_INVOKED
|
||||||
#ifndef APSTUDIO_READONLY_SYMBOLS
|
#ifndef APSTUDIO_READONLY_SYMBOLS
|
||||||
#define _APS_NEXT_RESOURCE_VALUE 185
|
#define _APS_NEXT_RESOURCE_VALUE 185
|
||||||
#define _APS_NEXT_COMMAND_VALUE 40498
|
#define _APS_NEXT_COMMAND_VALUE 40501
|
||||||
#define _APS_NEXT_CONTROL_VALUE 1269
|
#define _APS_NEXT_CONTROL_VALUE 1269
|
||||||
#define _APS_NEXT_SYMED_VALUE 101
|
#define _APS_NEXT_SYMED_VALUE 101
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -108,39 +108,53 @@ void RedrawTasedit()
|
||||||
InvalidateRect(hwndTasEdit, 0, FALSE);
|
InvalidateRect(hwndTasEdit, 0, FALSE);
|
||||||
}
|
}
|
||||||
|
|
||||||
void ShowMenu(ECONTEXTMENU which, POINT& pt)
|
|
||||||
{
|
|
||||||
HMENU sub = GetSubMenu(hrmenu,(int)which);
|
|
||||||
TrackPopupMenu(sub,0,pt.x,pt.y,TPM_RIGHTBUTTON,hwndTasEdit,0);
|
|
||||||
}
|
|
||||||
|
|
||||||
void StrayClickMenu(LPNMITEMACTIVATE info)
|
void StrayClickMenu(LPNMITEMACTIVATE info)
|
||||||
{
|
{
|
||||||
POINT pt = info->ptAction;
|
POINT pt = info->ptAction;
|
||||||
ClientToScreen(tasedit_list.hwndList, &pt);
|
ClientToScreen(tasedit_list.hwndList, &pt);
|
||||||
ShowMenu(CONTEXTMENU_STRAY, pt);
|
HMENU sub = GetSubMenu(hrmenu, CONTEXTMENU_STRAY);
|
||||||
|
TrackPopupMenu(sub, 0, pt.x, pt.y, 0, hwndTasEdit, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
void RightClickMenu(LPNMITEMACTIVATE info)
|
void RightClickMenu(LPNMITEMACTIVATE info)
|
||||||
{
|
{
|
||||||
POINT pt = info->ptAction;
|
POINT pt = info->ptAction;
|
||||||
ClientToScreen(tasedit_list.hwndList, &pt);
|
ClientToScreen(tasedit_list.hwndList, &pt);
|
||||||
ShowMenu(CONTEXTMENU_SELECTED, pt);
|
|
||||||
}
|
|
||||||
|
|
||||||
void RightClick(LPNMITEMACTIVATE info)
|
SelectionFrames* current_selection = selection.MakeStrobe();
|
||||||
{
|
if (current_selection->size() == 0)
|
||||||
int index = info->iItem;
|
|
||||||
int column = info->iSubItem;
|
|
||||||
|
|
||||||
//stray clicks give a context menu:
|
|
||||||
if(index == -1)
|
|
||||||
{
|
{
|
||||||
StrayClickMenu(info);
|
StrayClickMenu(info);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
HMENU sub = GetSubMenu(hrmenu, CONTEXTMENU_SELECTED);
|
||||||
|
// inspect current selection and disable inappropriate menu items
|
||||||
|
SelectionFrames::iterator current_selection_begin(current_selection->begin());
|
||||||
|
SelectionFrames::iterator current_selection_end(current_selection->end());
|
||||||
|
bool set_found = false, unset_found = false;
|
||||||
|
for(SelectionFrames::iterator it(current_selection_begin); it != current_selection_end; it++)
|
||||||
|
{
|
||||||
|
if(markers.GetMarker(*it))
|
||||||
|
set_found = true;
|
||||||
|
else
|
||||||
|
unset_found = true;
|
||||||
|
}
|
||||||
|
if (set_found)
|
||||||
|
EnableMenuItem(sub, ID_SELECTED_REMOVEMARKER, MF_BYCOMMAND | MF_ENABLED);
|
||||||
|
else
|
||||||
|
EnableMenuItem(sub, ID_SELECTED_REMOVEMARKER, MF_BYCOMMAND | MF_DISABLED | MF_GRAYED);
|
||||||
|
if (unset_found)
|
||||||
|
EnableMenuItem(sub, ID_SELECTED_SETMARKER, MF_BYCOMMAND | MF_ENABLED);
|
||||||
|
else
|
||||||
|
EnableMenuItem(sub, ID_SELECTED_SETMARKER, MF_BYCOMMAND | MF_DISABLED | MF_GRAYED);
|
||||||
|
|
||||||
if (selection.CheckFrameSelected(index))
|
TrackPopupMenu(sub, 0, pt.x, pt.y, 0, hwndTasEdit, 0);
|
||||||
|
}
|
||||||
|
void RightClick(LPNMITEMACTIVATE info)
|
||||||
|
{
|
||||||
|
int index = info->iItem;
|
||||||
|
if(index == -1)
|
||||||
|
StrayClickMenu(info);
|
||||||
|
else if (selection.CheckFrameSelected(index))
|
||||||
RightClickMenu(info);
|
RightClickMenu(info);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -382,74 +396,93 @@ void Truncate()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
//the column set operation, for setting a button/Marker for a span of selected values
|
|
||||||
void ColumnSet(int column)
|
void ColumnSet(int column)
|
||||||
|
{
|
||||||
|
if (column == COLUMN_FRAMENUM || column == COLUMN_FRAMENUM2)
|
||||||
|
FrameColumnSet();
|
||||||
|
else
|
||||||
|
InputColumnSet(column);
|
||||||
|
}
|
||||||
|
void FrameColumnSet()
|
||||||
{
|
{
|
||||||
SelectionFrames* current_selection = selection.MakeStrobe();
|
SelectionFrames* current_selection = selection.MakeStrobe();
|
||||||
if (current_selection->size() == 0) return;
|
if (current_selection->size() == 0) return;
|
||||||
|
|
||||||
SelectionFrames::iterator current_selection_begin(current_selection->begin());
|
SelectionFrames::iterator current_selection_begin(current_selection->begin());
|
||||||
SelectionFrames::iterator current_selection_end(current_selection->end());
|
SelectionFrames::iterator current_selection_end(current_selection->end());
|
||||||
if (column == COLUMN_FRAMENUM || column == COLUMN_FRAMENUM2)
|
|
||||||
|
// inspect the selected frames, if they are all set, then unset all, else set all
|
||||||
|
bool unset_found = false, changes_made = false;
|
||||||
|
for(SelectionFrames::iterator it(current_selection_begin); it != current_selection_end; it++)
|
||||||
{
|
{
|
||||||
// Markers column
|
if(!markers.GetMarker(*it))
|
||||||
// inspect the selected frames, if they are all set, then unset all, else set all
|
{
|
||||||
bool unset_found = false;
|
unset_found = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (unset_found)
|
||||||
|
{
|
||||||
|
|
||||||
|
// set all
|
||||||
for(SelectionFrames::iterator it(current_selection_begin); it != current_selection_end; it++)
|
for(SelectionFrames::iterator it(current_selection_begin); it != current_selection_end; it++)
|
||||||
{
|
{
|
||||||
if(!markers.GetMarker(*it))
|
if(!markers.GetMarker(*it))
|
||||||
{
|
{
|
||||||
unset_found = true;
|
changes_made = true;
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (unset_found)
|
|
||||||
{
|
|
||||||
// set all
|
|
||||||
for(SelectionFrames::iterator it(current_selection_begin); it != current_selection_end; it++)
|
|
||||||
{
|
|
||||||
markers.SetMarker(*it);
|
markers.SetMarker(*it);
|
||||||
tasedit_list.RedrawRow(*it);
|
tasedit_list.RedrawRow(*it);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
if (changes_made)
|
||||||
history.RegisterChanges(MODTYPE_MARKER_SET, *current_selection_begin, *current_selection->rbegin());
|
history.RegisterChanges(MODTYPE_MARKER_SET, *current_selection_begin, *current_selection->rbegin());
|
||||||
} else
|
} else
|
||||||
|
{
|
||||||
|
// unset all
|
||||||
|
for(SelectionFrames::iterator it(current_selection_begin); it != current_selection_end; it++)
|
||||||
{
|
{
|
||||||
// unset all
|
if(markers.GetMarker(*it))
|
||||||
for(SelectionFrames::iterator it(current_selection_begin); it != current_selection_end; it++)
|
|
||||||
{
|
{
|
||||||
|
changes_made = true;
|
||||||
markers.ClearMarker(*it);
|
markers.ClearMarker(*it);
|
||||||
tasedit_list.RedrawRow(*it);
|
tasedit_list.RedrawRow(*it);
|
||||||
}
|
}
|
||||||
history.RegisterChanges(MODTYPE_MARKER_UNSET, *current_selection_begin, *current_selection->rbegin());
|
|
||||||
}
|
}
|
||||||
|
if (changes_made)
|
||||||
|
history.RegisterChanges(MODTYPE_MARKER_UNSET, *current_selection_begin, *current_selection->rbegin());
|
||||||
|
}
|
||||||
|
if (changes_made)
|
||||||
project.SetProjectChanged();
|
project.SetProjectChanged();
|
||||||
// no need to RedrawList();
|
}
|
||||||
|
void InputColumnSet(int column)
|
||||||
|
{
|
||||||
|
int joy = (column - COLUMN_JOYPAD1_A) / NUM_JOYPAD_BUTTONS;
|
||||||
|
if (joy < 0 || joy >= NUM_JOYPADS) return;
|
||||||
|
int button = (column - COLUMN_JOYPAD1_A) % NUM_JOYPAD_BUTTONS;
|
||||||
|
|
||||||
|
SelectionFrames* current_selection = selection.MakeStrobe();
|
||||||
|
if (current_selection->size() == 0) return;
|
||||||
|
SelectionFrames::iterator current_selection_begin(current_selection->begin());
|
||||||
|
SelectionFrames::iterator current_selection_end(current_selection->end());
|
||||||
|
|
||||||
|
//inspect the selected frames, if they are all set, then unset all, else set all
|
||||||
|
bool newValue = false;
|
||||||
|
for(SelectionFrames::iterator it(current_selection_begin); it != current_selection_end; it++)
|
||||||
|
{
|
||||||
|
if(!(currMovieData.records[*it].checkBit(joy,button)))
|
||||||
|
{
|
||||||
|
newValue = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// apply newValue
|
||||||
|
for(SelectionFrames::iterator it(current_selection_begin); it != current_selection_end; it++)
|
||||||
|
currMovieData.records[*it].setBitValue(joy,button,newValue);
|
||||||
|
if (newValue)
|
||||||
|
{
|
||||||
|
greenzone.InvalidateAndCheck(history.RegisterChanges(MODTYPE_SET, *current_selection_begin, *current_selection->rbegin()));
|
||||||
} else
|
} else
|
||||||
{
|
{
|
||||||
// buttons column
|
greenzone.InvalidateAndCheck(history.RegisterChanges(MODTYPE_UNSET, *current_selection_begin, *current_selection->rbegin()));
|
||||||
int joy = (column - COLUMN_JOYPAD1_A) / NUM_JOYPAD_BUTTONS;
|
|
||||||
if (joy < 0 || joy >= NUM_JOYPADS) return;
|
|
||||||
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(SelectionFrames::iterator it(current_selection_begin); it != current_selection_end; it++)
|
|
||||||
{
|
|
||||||
if(!(currMovieData.records[*it].checkBit(joy,button)))
|
|
||||||
{
|
|
||||||
newValue = true;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// apply newValue
|
|
||||||
for(SelectionFrames::iterator it(current_selection_begin); it != current_selection_end; it++)
|
|
||||||
currMovieData.records[*it].setBitValue(joy,button,newValue);
|
|
||||||
if (newValue)
|
|
||||||
{
|
|
||||||
greenzone.InvalidateAndCheck(history.RegisterChanges(MODTYPE_SET, *current_selection_begin, *current_selection->rbegin()));
|
|
||||||
} else
|
|
||||||
{
|
|
||||||
greenzone.InvalidateAndCheck(history.RegisterChanges(MODTYPE_UNSET, *current_selection_begin, *current_selection->rbegin()));
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -551,7 +584,7 @@ bool Paste()
|
||||||
{
|
{
|
||||||
char *pGlobal = (char*)GlobalLock((HGLOBAL)hGlobal);
|
char *pGlobal = (char*)GlobalLock((HGLOBAL)hGlobal);
|
||||||
|
|
||||||
// TAS recording info starts with "TAS ".
|
// TAS recording info starts with "TAS "
|
||||||
if (pGlobal[0]=='T' && pGlobal[1]=='A' && pGlobal[2]=='S')
|
if (pGlobal[0]=='T' && pGlobal[1]=='A' && pGlobal[2]=='S')
|
||||||
{
|
{
|
||||||
// Extract number of frames
|
// Extract number of frames
|
||||||
|
@ -567,12 +600,11 @@ bool Paste()
|
||||||
int joy = 0;
|
int joy = 0;
|
||||||
uint8 new_buttons = 0;
|
uint8 new_buttons = 0;
|
||||||
char* frame;
|
char* frame;
|
||||||
|
|
||||||
--pos;
|
--pos;
|
||||||
while (pGlobal++ && *pGlobal!='\0')
|
while (pGlobal++ && *pGlobal!='\0')
|
||||||
{
|
{
|
||||||
|
// Detect skipped frames in paste
|
||||||
frame = pGlobal;
|
frame = pGlobal;
|
||||||
// Detect skipped frames in paste.
|
|
||||||
if (frame[0]=='+')
|
if (frame[0]=='+')
|
||||||
{
|
{
|
||||||
pos += atoi(frame+1);
|
pos += atoi(frame+1);
|
||||||
|
@ -653,7 +685,7 @@ bool PasteInsert()
|
||||||
{
|
{
|
||||||
char *pGlobal = (char*)GlobalLock((HGLOBAL)hGlobal);
|
char *pGlobal = (char*)GlobalLock((HGLOBAL)hGlobal);
|
||||||
|
|
||||||
// TAS recording info starts with "TAS ".
|
// TAS recording info starts with "TAS "
|
||||||
if (pGlobal[0]=='T' && pGlobal[1]=='A' && pGlobal[2]=='S')
|
if (pGlobal[0]=='T' && pGlobal[1]=='A' && pGlobal[2]=='S')
|
||||||
{
|
{
|
||||||
// make sure markers have the same size as movie
|
// make sure markers have the same size as movie
|
||||||
|
@ -667,14 +699,13 @@ bool PasteInsert()
|
||||||
|
|
||||||
|
|
||||||
pGlobal = strchr(pGlobal, '\n');
|
pGlobal = strchr(pGlobal, '\n');
|
||||||
|
char* frame;
|
||||||
int joy=0;
|
int joy=0;
|
||||||
--pos;
|
--pos;
|
||||||
|
|
||||||
while (pGlobal++ && *pGlobal!='\0')
|
while (pGlobal++ && *pGlobal!='\0')
|
||||||
{
|
{
|
||||||
char *frame = pGlobal;
|
// Detect skipped frames in paste
|
||||||
|
frame = pGlobal;
|
||||||
// Detect skipped frames in paste.
|
|
||||||
if (frame[0]=='+')
|
if (frame[0]=='+')
|
||||||
{
|
{
|
||||||
pos += atoi(frame+1);
|
pos += atoi(frame+1);
|
||||||
|
@ -1322,6 +1353,57 @@ BOOL CALLBACK WndprocTasEdit(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lPar
|
||||||
tasedit_list.FollowSelection();
|
tasedit_list.FollowSelection();
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
case ID_SELECTED_SETMARKER:
|
||||||
|
{
|
||||||
|
SelectionFrames* current_selection = selection.MakeStrobe();
|
||||||
|
if (current_selection->size())
|
||||||
|
{
|
||||||
|
SelectionFrames::iterator current_selection_begin(current_selection->begin());
|
||||||
|
SelectionFrames::iterator current_selection_end(current_selection->end());
|
||||||
|
bool changes_made = false;
|
||||||
|
for(SelectionFrames::iterator it(current_selection_begin); it != current_selection_end; it++)
|
||||||
|
{
|
||||||
|
if(!markers.GetMarker(*it))
|
||||||
|
{
|
||||||
|
changes_made = true;
|
||||||
|
markers.SetMarker(*it);
|
||||||
|
tasedit_list.RedrawRow(*it);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (changes_made)
|
||||||
|
{
|
||||||
|
history.RegisterChanges(MODTYPE_MARKER_SET, *current_selection_begin, *current_selection->rbegin());
|
||||||
|
project.SetProjectChanged();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case ID_SELECTED_REMOVEMARKER:
|
||||||
|
{
|
||||||
|
SelectionFrames* current_selection = selection.MakeStrobe();
|
||||||
|
if (current_selection->size())
|
||||||
|
{
|
||||||
|
SelectionFrames::iterator current_selection_begin(current_selection->begin());
|
||||||
|
SelectionFrames::iterator current_selection_end(current_selection->end());
|
||||||
|
bool changes_made = false;
|
||||||
|
for(SelectionFrames::iterator it(current_selection_begin); it != current_selection_end; it++)
|
||||||
|
{
|
||||||
|
if(markers.GetMarker(*it))
|
||||||
|
{
|
||||||
|
changes_made = true;
|
||||||
|
markers.ClearMarker(*it);
|
||||||
|
tasedit_list.RedrawRow(*it);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (changes_made)
|
||||||
|
{
|
||||||
|
history.RegisterChanges(MODTYPE_MARKER_UNSET, *current_selection_begin, *current_selection->rbegin());
|
||||||
|
project.SetProjectChanged();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
@ -1382,17 +1464,9 @@ void EnterTasEdit()
|
||||||
|
|
||||||
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
|
// init modules
|
||||||
FCEU_printf("1");
|
|
||||||
greenzone.init();
|
greenzone.init();
|
||||||
FCEU_printf("2");
|
|
||||||
playback.init();
|
playback.init();
|
||||||
// either start new movie or use current movie
|
// either start new movie or use current movie
|
||||||
if (currMovieData.savestate.size() != 0)
|
|
||||||
{
|
|
||||||
FCEUD_PrintError("This version of TAS Editor doesn't work with movies starting from savestate.");
|
|
||||||
// delete savestate, but preserve input
|
|
||||||
currMovieData.savestate.clear();
|
|
||||||
}
|
|
||||||
if (FCEUMOV_Mode(MOVIEMODE_INACTIVE))
|
if (FCEUMOV_Mode(MOVIEMODE_INACTIVE))
|
||||||
{
|
{
|
||||||
FCEUI_StopMovie();
|
FCEUI_StopMovie();
|
||||||
|
@ -1401,6 +1475,12 @@ void EnterTasEdit()
|
||||||
} else
|
} else
|
||||||
{
|
{
|
||||||
// use current movie to create a new project
|
// use current movie to create a new project
|
||||||
|
if (currMovieData.savestate.size() != 0)
|
||||||
|
{
|
||||||
|
FCEUD_PrintError("This version of TAS Editor doesn't work with movies starting from savestate.");
|
||||||
|
// delete savestate, but preserve input
|
||||||
|
currMovieData.savestate.clear();
|
||||||
|
}
|
||||||
FCEUI_StopMovie();
|
FCEUI_StopMovie();
|
||||||
greenzone.TryDumpIncremental(lagFlag != 0);
|
greenzone.TryDumpIncremental(lagFlag != 0);
|
||||||
}
|
}
|
||||||
|
|
|
@ -36,6 +36,8 @@ void DeleteFrames();
|
||||||
void ClearFrames(SelectionFrames* current_selection = 0);
|
void ClearFrames(SelectionFrames* current_selection = 0);
|
||||||
void Truncate();
|
void Truncate();
|
||||||
void ColumnSet(int column);
|
void ColumnSet(int column);
|
||||||
|
void InputColumnSet(int column);
|
||||||
|
void FrameColumnSet();
|
||||||
bool Copy(SelectionFrames* current_selection = 0);
|
bool Copy(SelectionFrames* current_selection = 0);
|
||||||
void Cut();
|
void Cut();
|
||||||
bool Paste();
|
bool Paste();
|
||||||
|
|
|
@ -272,17 +272,18 @@ void BOOKMARKS::set(int slot)
|
||||||
|
|
||||||
bookmarks_array[slot].set();
|
bookmarks_array[slot].set();
|
||||||
|
|
||||||
// if this screenshot is shown on screen - reinit and redraw it
|
// if this screenshot is currently shown - reinit and redraw it
|
||||||
if (screenshot_display.screenshot_currently_shown == slot)
|
if (screenshot_display.screenshot_currently_shown == slot)
|
||||||
screenshot_display.screenshot_currently_shown = ITEM_UNDER_MOUSE_NONE;
|
screenshot_display.screenshot_currently_shown = ITEM_UNDER_MOUSE_NONE;
|
||||||
|
|
||||||
|
int parent;
|
||||||
// inherit current branch
|
// inherit current branch
|
||||||
if (slot != current_branch)
|
if (slot != current_branch)
|
||||||
{
|
{
|
||||||
int parent = bookmarks_array[slot].parent_branch;
|
parent = bookmarks_array[slot].parent_branch;
|
||||||
if (parent == -1 && saved_time[0])
|
if (parent == -1 && saved_time[0])
|
||||||
{
|
{
|
||||||
// check if this is the only child of cloud parent, if so then set cloud time to the saved_time
|
// check if this was the only child of cloud parent, if so then set cloud time to the saved_time
|
||||||
int i = 0;
|
int i = 0;
|
||||||
for (; i < TOTAL_BOOKMARKS; ++i)
|
for (; i < TOTAL_BOOKMARKS; ++i)
|
||||||
{
|
{
|
||||||
|
@ -293,7 +294,7 @@ void BOOKMARKS::set(int slot)
|
||||||
// didn't find another child of cloud
|
// didn't find another child of cloud
|
||||||
strcpy(cloud_time, saved_time);
|
strcpy(cloud_time, saved_time);
|
||||||
}
|
}
|
||||||
// before disconnecting from old parent, connect all childs to the parent
|
// before disconnecting from old parent, connect all childs to the old parent
|
||||||
for (int i = 0; i < TOTAL_BOOKMARKS; ++i)
|
for (int i = 0; i < TOTAL_BOOKMARKS; ++i)
|
||||||
{
|
{
|
||||||
if (bookmarks_array[i].not_empty && bookmarks_array[i].parent_branch == slot)
|
if (bookmarks_array[i].not_empty && bookmarks_array[i].parent_branch == slot)
|
||||||
|
@ -302,6 +303,69 @@ void BOOKMARKS::set(int slot)
|
||||||
bookmarks_array[slot].parent_branch = current_branch;
|
bookmarks_array[slot].parent_branch = current_branch;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// if parent is invalid (first_change < parent.jump_frame) then find better parent
|
||||||
|
int factor;
|
||||||
|
// also if parent == cloud, then try to find better parent
|
||||||
|
parent = bookmarks_array[slot].parent_branch;
|
||||||
|
if (parent >= 0)
|
||||||
|
factor = bookmarks_array[slot].snapshot.findFirstChange(bookmarks_array[parent].snapshot);
|
||||||
|
if (parent < 0 || (factor >= 0 && factor < bookmarks_array[parent].snapshot.jump_frame))
|
||||||
|
{
|
||||||
|
// find highest frame of change
|
||||||
|
std::vector<int> DecisiveFactor(TOTAL_BOOKMARKS);
|
||||||
|
int best_branch = -1;
|
||||||
|
for (int i = TOTAL_BOOKMARKS-1; i >= 0; i--)
|
||||||
|
{
|
||||||
|
if (i != slot && i != parent && bookmarks_array[i].not_empty && bookmarks_array[slot].snapshot.size >= bookmarks_array[i].snapshot.jump_frame)
|
||||||
|
{
|
||||||
|
factor = bookmarks_array[slot].snapshot.findFirstChange(bookmarks_array[i].snapshot);
|
||||||
|
if (factor < 0)
|
||||||
|
{
|
||||||
|
// this branch is identical to this slot
|
||||||
|
DecisiveFactor[i] = 2 * bookmarks_array[i].snapshot.size;
|
||||||
|
} else if (factor >= bookmarks_array[i].snapshot.jump_frame)
|
||||||
|
{
|
||||||
|
// hey, this branch could be our new parent...
|
||||||
|
DecisiveFactor[i] = 2 * factor;
|
||||||
|
} else
|
||||||
|
DecisiveFactor[i] = 0;
|
||||||
|
} else
|
||||||
|
{
|
||||||
|
DecisiveFactor[i] = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// add +1 as a bonus to current parents and grandparents (a bit of nepotism!)
|
||||||
|
while (parent >= 0)
|
||||||
|
{
|
||||||
|
if (DecisiveFactor[parent])
|
||||||
|
DecisiveFactor[parent]++;
|
||||||
|
parent = bookmarks_array[parent].parent_branch;
|
||||||
|
}
|
||||||
|
// find max
|
||||||
|
factor = 0;
|
||||||
|
for (int i = TOTAL_BOOKMARKS-1; i >= 0; i--)
|
||||||
|
{
|
||||||
|
if (DecisiveFactor[i] && DecisiveFactor[i] > factor)
|
||||||
|
{
|
||||||
|
factor = DecisiveFactor[i];
|
||||||
|
best_branch = i;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
parent = bookmarks_array[slot].parent_branch;
|
||||||
|
if (parent != best_branch)
|
||||||
|
{
|
||||||
|
// before disconnecting from old parent, connect all childs to the old parent
|
||||||
|
for (int i = 0; i < TOTAL_BOOKMARKS; ++i)
|
||||||
|
{
|
||||||
|
if (bookmarks_array[i].not_empty && bookmarks_array[i].parent_branch == slot)
|
||||||
|
bookmarks_array[i].parent_branch = parent;
|
||||||
|
}
|
||||||
|
// found new parent
|
||||||
|
bookmarks_array[slot].parent_branch = best_branch;
|
||||||
|
must_recalculate_branches_tree = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// switch current branch to this branch
|
// switch current branch to this branch
|
||||||
if (slot != current_branch && current_branch >= 0)
|
if (slot != current_branch && current_branch >= 0)
|
||||||
{
|
{
|
||||||
|
@ -1041,7 +1105,7 @@ void BOOKMARKS::RecalculateBranchesTree()
|
||||||
// also define "current_pos" GridX
|
// also define "current_pos" GridX
|
||||||
if (current_branch >= 0)
|
if (current_branch >= 0)
|
||||||
{
|
{
|
||||||
if (Children[current_branch+1].size() < MAX_NUM_CHILDREN)
|
if (Children[current_branch+1].size() < MAX_NUM_CHILDREN_ON_CANVAS_HEIGHT)
|
||||||
{
|
{
|
||||||
// "current_pos" becomes a child of current_branch
|
// "current_pos" becomes a child of current_branch
|
||||||
GridX[TOTAL_BOOKMARKS] = GridX[current_branch] + 1;
|
GridX[TOTAL_BOOKMARKS] = GridX[current_branch] + 1;
|
||||||
|
@ -1053,8 +1117,8 @@ void BOOKMARKS::RecalculateBranchesTree()
|
||||||
RecursiveAddHeight(current_branch, 1);
|
RecursiveAddHeight(current_branch, 1);
|
||||||
} else
|
} else
|
||||||
{
|
{
|
||||||
// special case 0: if there's too many items on one level (more than canvas can show)
|
// special case 0: if there's too many children on one level (more than canvas can show)
|
||||||
// "current_pos" becomes special branch above current_branch
|
// then "current_pos" becomes special branch above current_branch
|
||||||
GridX[TOTAL_BOOKMARKS] = GridX[current_branch];
|
GridX[TOTAL_BOOKMARKS] = GridX[current_branch];
|
||||||
GridY[TOTAL_BOOKMARKS] = GridY[current_branch] - 7;
|
GridY[TOTAL_BOOKMARKS] = GridY[current_branch] - 7;
|
||||||
}
|
}
|
||||||
|
@ -1135,6 +1199,37 @@ void BOOKMARKS::RecalculateBranchesTree()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
// special case 4: if cloud has all 10 children, then one child will be out of canvas
|
||||||
|
if (Children[0].size() == TOTAL_BOOKMARKS)
|
||||||
|
{
|
||||||
|
// find this child and move it to be visible
|
||||||
|
for (int t = TOTAL_BOOKMARKS - 1; t >= 0; t--)
|
||||||
|
{
|
||||||
|
if (GridY[t] > MAX_GRID_Y_POS)
|
||||||
|
{
|
||||||
|
GridY[t] = MAX_GRID_Y_POS;
|
||||||
|
GridX[t] -= 2;
|
||||||
|
// also move fireball to position near this branch
|
||||||
|
if (changes_since_current_branch && current_branch == t)
|
||||||
|
{
|
||||||
|
GridY[TOTAL_BOOKMARKS] = GridY[t];
|
||||||
|
GridX[TOTAL_BOOKMARKS] = GridX[t] + 1;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
} else if (GridY[t] < -MAX_GRID_Y_POS)
|
||||||
|
{
|
||||||
|
GridY[t] = -MAX_GRID_Y_POS;
|
||||||
|
GridX[t] -= 2;
|
||||||
|
// also move fireball to position near this branch
|
||||||
|
if (changes_since_current_branch && current_branch == t)
|
||||||
|
{
|
||||||
|
GridY[TOTAL_BOOKMARKS] = GridY[t];
|
||||||
|
GridX[TOTAL_BOOKMARKS] = GridX[t] + 1;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// 3. Set pixel positions of branches
|
// 3. Set pixel positions of branches
|
||||||
int max_x = 0;
|
int max_x = 0;
|
||||||
|
|
|
@ -35,7 +35,7 @@
|
||||||
#define EMPTY_BRANCHES_X -6
|
#define EMPTY_BRANCHES_X -6
|
||||||
#define EMPTY_BRANCHES_Y_BASE 8
|
#define EMPTY_BRANCHES_Y_BASE 8
|
||||||
#define EMPTY_BRANCHES_Y_FACTOR 14
|
#define EMPTY_BRANCHES_Y_FACTOR 14
|
||||||
#define MAX_NUM_CHILDREN 9
|
#define MAX_NUM_CHILDREN_ON_CANVAS_HEIGHT 9
|
||||||
#define MAX_CHAIN_LEN 10
|
#define MAX_CHAIN_LEN 10
|
||||||
#define MAX_GRID_Y_POS 8
|
#define MAX_GRID_Y_POS 8
|
||||||
// spritesheet
|
// spritesheet
|
||||||
|
|
|
@ -62,12 +62,12 @@ void SCREENSHOT_DISPLAY::init()
|
||||||
}
|
}
|
||||||
HDC win_hdc = GetWindowDC(tasedit_list.hwndList);
|
HDC win_hdc = GetWindowDC(tasedit_list.hwndList);
|
||||||
scr_bmp = CreateDIBSection(win_hdc, scr_bmi, DIB_RGB_COLORS, (void**)&scr_ptr, 0, 0);
|
scr_bmp = CreateDIBSection(win_hdc, scr_bmi, DIB_RGB_COLORS, (void**)&scr_ptr, 0, 0);
|
||||||
// calculate coordinates (relative to the listview top-left corner)
|
// calculate coordinates (relative to IDC_BOOKMARKS_BOX top-left corner)
|
||||||
RECT temp_rect, parent_rect;
|
RECT temp_rect, parent_rect;
|
||||||
GetWindowRect(hwndTasEdit, &parent_rect);
|
GetWindowRect(hwndTasEdit, &parent_rect);
|
||||||
GetWindowRect(tasedit_list.hwndHeader, &temp_rect);
|
GetWindowRect(GetDlgItem(hwndTasEdit, IDC_BOOKMARKS_BOX), &temp_rect);
|
||||||
scr_bmp_x = temp_rect.left - parent_rect.left;
|
scr_bmp_x = temp_rect.left - SCREENSHOT_WIDTH - SCR_BMP_DX - parent_rect.left;
|
||||||
scr_bmp_y = temp_rect.bottom - parent_rect.top;
|
scr_bmp_y = ((temp_rect.bottom + temp_rect.top - SCREENSHOT_HEIGHT) / 2) - parent_rect.top;
|
||||||
}
|
}
|
||||||
void SCREENSHOT_DISPLAY::free()
|
void SCREENSHOT_DISPLAY::free()
|
||||||
{
|
{
|
||||||
|
|
|
@ -1,7 +1,8 @@
|
||||||
//Specification file for SCREENSHOT_DISPLAY class
|
//Specification file for SCREENSHOT_DISPLAY class
|
||||||
|
|
||||||
#define SCR_BMP_PHASE_MAX 13
|
#define SCR_BMP_PHASE_MAX 12
|
||||||
#define SCR_BMP_PHASE_ALPHA_MAX 10
|
#define SCR_BMP_PHASE_ALPHA_MAX 10
|
||||||
|
#define SCR_BMP_DX 7
|
||||||
|
|
||||||
#define DISPLAY_UPDATE_TICK 40 // update at 25FPS
|
#define DISPLAY_UPDATE_TICK 40 // update at 25FPS
|
||||||
|
|
||||||
|
|
|
@ -26,7 +26,9 @@ LRESULT APIENTRY ListWndProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam);
|
||||||
WNDPROC hwndList_oldWndProc, hwndHeader_oldWndproc;
|
WNDPROC hwndList_oldWndProc, hwndHeader_oldWndproc;
|
||||||
|
|
||||||
// resources
|
// resources
|
||||||
COLORREF hot_changes_colors[16] = { 0x0, 0x661212, 0x842B4E, 0x652C73, 0x48247D, 0x383596, 0x2947AE, 0x1E53C1, 0x135DD2, 0x116EDA, 0x107EE3, 0x0F8EEB, 0x209FF4, 0x3DB1FD, 0x51C2FF, 0x4DCDFF };
|
COLORREF hot_changes_colors[16] = { 0x0, 0x5c4c44, 0x854604, 0xab2500, 0xc20006, 0xd6006f, 0xd40091, 0xba00a4, 0x9500ba, 0x7a00cc, 0x5800d4, 0x0045e2, 0x0063ea, 0x0079f4, 0x0092fa, 0x00aaff };
|
||||||
|
//COLORREF hot_changes_colors[16] = { 0x0, 0x661212, 0x842B4E, 0x652C73, 0x48247D, 0x383596, 0x2947AE, 0x1E53C1, 0x135DD2, 0x116EDA, 0x107EE3, 0x0F8EEB, 0x209FF4, 0x3DB1FD, 0x51C2FF, 0x4DCDFF };
|
||||||
|
|
||||||
char list_save_id[LIST_ID_LEN] = "LIST";
|
char list_save_id[LIST_ID_LEN] = "LIST";
|
||||||
|
|
||||||
TASEDIT_LIST::TASEDIT_LIST()
|
TASEDIT_LIST::TASEDIT_LIST()
|
||||||
|
@ -52,7 +54,6 @@ void TASEDIT_LIST::init()
|
||||||
{
|
{
|
||||||
free();
|
free();
|
||||||
hwndList = GetDlgItem(hwndTasEdit, IDC_LIST1);
|
hwndList = GetDlgItem(hwndTasEdit, IDC_LIST1);
|
||||||
|
|
||||||
// prepare the main listview
|
// prepare the main listview
|
||||||
ListView_SetExtendedListViewStyleEx(hwndList, LVS_EX_FULLROWSELECT|LVS_EX_GRIDLINES, LVS_EX_FULLROWSELECT|LVS_EX_GRIDLINES);
|
ListView_SetExtendedListViewStyleEx(hwndList, LVS_EX_FULLROWSELECT|LVS_EX_GRIDLINES, LVS_EX_FULLROWSELECT|LVS_EX_GRIDLINES);
|
||||||
// subclass the header
|
// subclass the header
|
||||||
|
|
|
@ -43,6 +43,9 @@ void TASEDIT_SELECTION::init(int new_size)
|
||||||
AddNewSelectionToHistory();
|
AddNewSelectionToHistory();
|
||||||
track_selection_changes = true;
|
track_selection_changes = true;
|
||||||
reset();
|
reset();
|
||||||
|
|
||||||
|
if (clipboard_selection.empty())
|
||||||
|
CheckClipboard();
|
||||||
RedrawTextClipboard();
|
RedrawTextClipboard();
|
||||||
}
|
}
|
||||||
void TASEDIT_SELECTION::free()
|
void TASEDIT_SELECTION::free()
|
||||||
|
@ -51,7 +54,6 @@ void TASEDIT_SELECTION::free()
|
||||||
selections_history.resize(0);
|
selections_history.resize(0);
|
||||||
history_total_items = 0;
|
history_total_items = 0;
|
||||||
temp_selection.clear();
|
temp_selection.clear();
|
||||||
clipboard_selection.clear();
|
|
||||||
}
|
}
|
||||||
void TASEDIT_SELECTION::reset()
|
void TASEDIT_SELECTION::reset()
|
||||||
{
|
{
|
||||||
|
@ -414,6 +416,48 @@ void TASEDIT_SELECTION::ReselectClipboard()
|
||||||
// also keep selection within list
|
// also keep selection within list
|
||||||
update();
|
update();
|
||||||
}
|
}
|
||||||
|
// retrieves some information from clipboard to clipboard_selection
|
||||||
|
void TASEDIT_SELECTION::CheckClipboard()
|
||||||
|
{
|
||||||
|
if (OpenClipboard(hwndTasEdit))
|
||||||
|
{
|
||||||
|
// check if clipboard contains TAS Editor input data
|
||||||
|
HANDLE hGlobal = GetClipboardData(CF_TEXT);
|
||||||
|
if (hGlobal)
|
||||||
|
{
|
||||||
|
clipboard_selection.clear();
|
||||||
|
int current_pos = -1;
|
||||||
|
char *pGlobal = (char*)GlobalLock((HGLOBAL)hGlobal);
|
||||||
|
// TAS recording info starts with "TAS "
|
||||||
|
if (pGlobal[0]=='T' && pGlobal[1]=='A' && pGlobal[2]=='S')
|
||||||
|
{
|
||||||
|
// Extract number of frames
|
||||||
|
int range;
|
||||||
|
sscanf (pGlobal+3, "%d", &range);
|
||||||
|
pGlobal = strchr(pGlobal, '\n');
|
||||||
|
|
||||||
|
while (pGlobal++ && *pGlobal!='\0')
|
||||||
|
{
|
||||||
|
// Detect skipped frames in paste
|
||||||
|
char *frame = pGlobal;
|
||||||
|
if (frame[0]=='+')
|
||||||
|
{
|
||||||
|
current_pos += atoi(frame+1);
|
||||||
|
while (*frame && *frame != '\n' && *frame != '|')
|
||||||
|
++frame;
|
||||||
|
if (*frame=='|') ++frame;
|
||||||
|
} else
|
||||||
|
current_pos++;
|
||||||
|
clipboard_selection.insert(current_pos);
|
||||||
|
// skip input
|
||||||
|
pGlobal = strchr(pGlobal, '\n');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
GlobalUnlock(hGlobal);
|
||||||
|
}
|
||||||
|
CloseClipboard();
|
||||||
|
}
|
||||||
|
}
|
||||||
// ----------------------------------------------------------
|
// ----------------------------------------------------------
|
||||||
void TASEDIT_SELECTION::ClearSelection()
|
void TASEDIT_SELECTION::ClearSelection()
|
||||||
{
|
{
|
||||||
|
|
|
@ -56,6 +56,7 @@ public:
|
||||||
|
|
||||||
private:
|
private:
|
||||||
SelectionFrames& CurrentSelection();
|
SelectionFrames& CurrentSelection();
|
||||||
|
void CheckClipboard();
|
||||||
|
|
||||||
bool track_selection_changes;
|
bool track_selection_changes;
|
||||||
bool must_redraw_text;
|
bool must_redraw_text;
|
||||||
|
|
Loading…
Reference in New Issue