* Tasedit: Keeping track of branching activities

* Tasedit: "Branches mode" of Bookmarks window
* Tasedit: Drawing Branches Tree (using GDI), animations, transitions, mouseover
This commit is contained in:
ansstuff 2011-11-07 16:02:25 +00:00
parent 8fafc755df
commit 80662af1d3
38 changed files with 1150 additions and 111 deletions

View File

@ -74,6 +74,7 @@ extern bool TASEdit_show_markers;
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_restore_position;
extern bool TASEdit_show_dot;
extern int TASEdit_greenzone_capacity;
@ -302,6 +303,7 @@ static CFGSTRUCT fceuconfig[] = {
AC(TASEdit_bind_markers),
AC(TASEdit_branch_full_movie),
AC(TASEdit_branch_only_when_rec),
AC(TASEdit_view_branches_tree),
AC(TASEdit_restore_position),
AC(TASEdit_show_dot),
AC(TASEdit_greenzone_capacity),

View File

@ -1352,38 +1352,48 @@ BEGIN
EDITTEXT IDC_LABEL_NEWPPUUSED,76,166,155,12,ES_READONLY | NOT WS_BORDER | NOT WS_TABSTOP
END
TASEDIT DIALOGEX 0, 0, 438, 380
TASEDIT DIALOGEX 0, 0, 438, 396
STYLE DS_SETFONT | DS_MODALFRAME | DS_FIXEDSYS | WS_MINIMIZEBOX | WS_POPUP | WS_VISIBLE | WS_CAPTION | WS_SYSMENU
CAPTION "TAS Editor"
MENU TASEDITMENU
FONT 8, "MS Shell Dlg", 400, 0, 0x1
BEGIN
CONTROL "",IDC_LIST1,"SysListView32",LVS_REPORT | LVS_SHOWSELALWAYS | LVS_ALIGNLEFT | LVS_OWNERDATA | LVS_NOSORTHEADER | WS_BORDER,6,5,299,370
GROUPBOX " Playback ",IDC_STATIC,310,5,123,62,BS_CENTER,WS_EX_RIGHT
PUSHBUTTON "<<",TASEDIT_REWIND_FULL,314,14,23,14,NOT WS_TABSTOP
PUSHBUTTON "<",TASEDIT_REWIND,337,14,23,14,NOT WS_TABSTOP
PUSHBUTTON "||",TASEDIT_PLAYSTOP,360,14,23,14,NOT WS_TABSTOP
PUSHBUTTON ">",TASEDIT_FORWARD,383,14,23,14,NOT WS_TABSTOP
PUSHBUTTON ">>",TASEDIT_FORWARD_FULL,406,14,23,14,NOT WS_TABSTOP
CONTROL "",IDC_PROGRESS_BUTTON,"Button",BS_OWNERDRAW | WS_TABSTOP,314,42,116,10
CONTROL "",IDC_PROGRESS1,"msctls_progress32",PBS_SMOOTH | WS_BORDER,314,44,115,6
CONTROL " Follow cursor",CHECK_FOLLOW_CURSOR,"Button",BS_AUTOCHECKBOX,316,30,105,12
CONTROL "",IDC_LIST1,"SysListView32",LVS_REPORT | LVS_SHOWSELALWAYS | LVS_ALIGNLEFT | LVS_OWNERDATA | LVS_NOSORTHEADER | WS_BORDER,6,15,299,362
GROUPBOX " Playback ",IDC_STATIC,310,1,123,62,BS_CENTER,WS_EX_RIGHT
PUSHBUTTON "<<",TASEDIT_REWIND_FULL,314,10,23,14,NOT WS_TABSTOP
PUSHBUTTON "<",TASEDIT_REWIND,337,10,23,14,NOT WS_TABSTOP
PUSHBUTTON "||",TASEDIT_PLAYSTOP,360,10,23,14,NOT WS_TABSTOP
PUSHBUTTON ">",TASEDIT_FORWARD,383,10,23,14,NOT WS_TABSTOP
PUSHBUTTON ">>",TASEDIT_FORWARD_FULL,406,10,23,14,NOT WS_TABSTOP
CONTROL "",IDC_PROGRESS_BUTTON,"Button",BS_OWNERDRAW,314,38,116,10
CONTROL "",IDC_BRANCHES_BUTTON,"Button",BS_OWNERDRAW,320,151,104,11
CONTROL "",IDC_PROGRESS1,"msctls_progress32",PBS_SMOOTH | WS_BORDER,314,40,115,6
CONTROL " Follow cursor",CHECK_FOLLOW_CURSOR,"Button",BS_AUTOCHECKBOX,316,26,105,12
CONTROL " Auto-restore last position",CHECK_AUTORESTORE_PLAYBACK,
"Button",BS_AUTOCHECKBOX,316,53,105,12
GROUPBOX " Recording ",IDC_STATIC,310,68,123,48,BS_CENTER,WS_EX_RIGHT
GROUPBOX " Editing ",IDC_STATIC,310,118,123,38,BS_CENTER,WS_EX_RIGHT
GROUPBOX " Bookmarks ",IDC_BOOKMARKS_BOX,310,158,123,103,BS_CENTER,WS_EX_RIGHT
CONTROL "",IDC_BOOKMARKSLIST,"SysListView32",LVS_REPORT | LVS_SINGLESEL | LVS_ALIGNLEFT | LVS_OWNERDATA | LVS_NOSCROLL | LVS_NOCOLUMNHEADER | LVS_NOSORTHEADER | WS_BORDER,315,168,113,89
CONTROL "",IDC_HISTORYLIST,"SysListView32",LVS_REPORT | LVS_SINGLESEL | LVS_SHOWSELALWAYS | LVS_NOLABELWRAP | LVS_ALIGNLEFT | LVS_OWNERDATA | LVS_NOCOLUMNHEADER | LVS_NOSORTHEADER | WS_BORDER,315,273,113,99
CONTROL " OFF",IDC_RADIO1,"Button",BS_AUTORADIOBUTTON,316,78,27,10
CONTROL " ON",IDC_RADIO2,"Button",BS_AUTORADIOBUTTON,316,91,27,10
CONTROL " 1P",IDC_RADIO3,"Button",BS_AUTORADIOBUTTON,373,78,25,10
CONTROL " 2P",IDC_RADIO4,"Button",BS_AUTORADIOBUTTON,402,78,23,10
CONTROL " 3P",IDC_RADIO5,"Button",BS_AUTORADIOBUTTON | WS_DISABLED,373,91,25,10
CONTROL " 4P",IDC_RADIO6,"Button",BS_AUTORADIOBUTTON | WS_DISABLED,402,91,23,10
CONTROL " Superimpose",IDC_SUPERIMPOSE,"Button",BS_AUTOCHECKBOX,316,104,56,10
CONTROL " Omit blank",IDC_OMITBLANK,"Button",BS_AUTOCHECKBOX,377,104,51,10
GROUPBOX " History ",IDC_STATIC,310,263,123,113,BS_CENTER,WS_EX_RIGHT
"Button",BS_AUTOCHECKBOX,316,49,105,12
GROUPBOX " Recording ",IDC_STATIC,310,64,123,48,BS_CENTER,WS_EX_RIGHT
GROUPBOX " Editing ",IDC_STATIC,310,113,123,37,BS_CENTER,WS_EX_RIGHT
GROUPBOX " Bookmarks ",IDC_BOOKMARKS_BOX,310,152,123,103,BS_CENTER,WS_EX_RIGHT
CONTROL "",IDC_BOOKMARKSLIST,"SysListView32",LVS_REPORT | LVS_SINGLESEL | LVS_ALIGNLEFT | LVS_OWNERDATA | LVS_NOSCROLL | LVS_NOCOLUMNHEADER | LVS_NOSORTHEADER | NOT WS_VISIBLE | WS_BORDER,315,162,113,89
CONTROL "",IDC_HISTORYLIST,"SysListView32",LVS_REPORT | LVS_SINGLESEL | LVS_SHOWSELALWAYS | LVS_NOLABELWRAP | LVS_ALIGNLEFT | LVS_OWNERDATA | LVS_NOCOLUMNHEADER | LVS_NOSORTHEADER | WS_BORDER,315,267,113,100
CONTROL " OFF",IDC_RADIO1,"Button",BS_AUTORADIOBUTTON,316,74,27,10
CONTROL " ON",IDC_RADIO2,"Button",BS_AUTORADIOBUTTON,316,87,27,10
CONTROL " 1P",IDC_RADIO3,"Button",BS_AUTORADIOBUTTON,373,74,25,10
CONTROL " 2P",IDC_RADIO4,"Button",BS_AUTORADIOBUTTON,402,74,23,10
CONTROL " 3P",IDC_RADIO5,"Button",BS_AUTORADIOBUTTON | WS_DISABLED,373,87,25,10
CONTROL " 4P",IDC_RADIO6,"Button",BS_AUTORADIOBUTTON | WS_DISABLED,402,87,23,10
CONTROL " Superimpose",IDC_SUPERIMPOSE,"Button",BS_AUTOCHECKBOX,316,100,56,10
CONTROL " Omit blank",IDC_OMITBLANK,"Button",BS_AUTOCHECKBOX,377,100,51,10
GROUPBOX " History ",IDC_STATIC,310,257,123,114,BS_CENTER,WS_EX_RIGHT
EDITTEXT IDC_EDIT1,54,377,251,13,ES_READONLY | NOT WS_TABSTOP
PUSHBUTTON "<<",TASEDIT_REWIND_FULL2,315,376,23,14,NOT WS_TABSTOP
PUSHBUTTON "Find",TASEDIT_REWIND_FULL3,338,376,34,14,WS_DISABLED | NOT WS_TABSTOP
PUSHBUTTON "Next",TASEDIT_REWIND_FULL4,372,376,34,14,WS_DISABLED | NOT WS_TABSTOP
PUSHBUTTON ">>",TASEDIT_REWIND_FULL5,405,376,23,14,NOT WS_TABSTOP
RTEXT "Marker 99999",IDC_STATIC,6,379,45,10,0,WS_EX_RIGHT
RTEXT "Marker 0",IDC_STATIC,6,3,45,10,0,WS_EX_RIGHT
EDITTEXT IDC_EDIT2,54,1,251,13,ES_READONLY | NOT WS_TABSTOP
CONTROL "",IDC_BRANCHES_BITMAP,"Static",SS_OWNERDRAW | SS_NOTIFY | SS_REALSIZEIMAGE | NOT WS_VISIBLE,315,162,113,89
END
ASSEMBLER DIALOGEX 0, 0, 202, 135
@ -1890,10 +1900,6 @@ BEGIN
"TASEDIT", DIALOG
BEGIN
LEFTMARGIN, 7
RIGHTMARGIN, 436
TOPMARGIN, 5
BOTTOMMARGIN, 374
END
"ASSEMBLER", DIALOG
@ -2064,7 +2070,6 @@ END
// Bitmap
//
IDB_TE_ARROW BITMAP "res/te_arrow.bmp"
IDB_BITMAP0 BITMAP "res\\te_0.bmp"
IDB_BITMAP1 BITMAP "res\\te_1.bmp"
IDB_BITMAP2 BITMAP "res\\te_2.bmp"
@ -2075,6 +2080,18 @@ IDB_BITMAP6 BITMAP "res\\te_6.bmp"
IDB_BITMAP7 BITMAP "res\\te_7.bmp"
IDB_BITMAP8 BITMAP "res\\te_8.bmp"
IDB_BITMAP9 BITMAP "res\\te_9.bmp"
IDB_BITMAP10 BITMAP "res\\te_10.bmp"
IDB_BITMAP11 BITMAP "res\\te_11.bmp"
IDB_BITMAP12 BITMAP "res\\te_12.bmp"
IDB_BITMAP13 BITMAP "res\\te_13.bmp"
IDB_BITMAP14 BITMAP "res\\te_14.bmp"
IDB_BITMAP15 BITMAP "res\\te_15.bmp"
IDB_BITMAP16 BITMAP "res\\te_16.bmp"
IDB_BITMAP17 BITMAP "res\\te_17.bmp"
IDB_BITMAP18 BITMAP "res\\te_18.bmp"
IDB_BITMAP19 BITMAP "res\\te_19.bmp"
IDB_TE_ARROW BITMAP "res/te_arrow.bmp"
IDB_BRANCH_SPRITESHEET BITMAP "res\\branch_spritesheet.bmp"
#endif // Àíãëèéñêèé (ÑØÀ) resources
/////////////////////////////////////////////////////////////////////////////

Binary file not shown.

After

Width:  |  Height:  |  Size: 23 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.2 KiB

After

Width:  |  Height:  |  Size: 418 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.2 KiB

After

Width:  |  Height:  |  Size: 418 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 418 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 418 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 418 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 418 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 418 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 418 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 418 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 418 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 418 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 418 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.2 KiB

After

Width:  |  Height:  |  Size: 418 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.2 KiB

After

Width:  |  Height:  |  Size: 418 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.2 KiB

After

Width:  |  Height:  |  Size: 418 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.2 KiB

After

Width:  |  Height:  |  Size: 418 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.2 KiB

After

Width:  |  Height:  |  Size: 418 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.2 KiB

After

Width:  |  Height:  |  Size: 418 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.2 KiB

After

Width:  |  Height:  |  Size: 418 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.2 KiB

After

Width:  |  Height:  |  Size: 418 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.2 KiB

After

Width:  |  Height:  |  Size: 418 B

View File

@ -169,6 +169,17 @@
#define IDB_BITMAP7 170
#define IDB_BITMAP8 171
#define IDB_BITMAP9 172
#define IDB_BITMAP10 173
#define IDB_BITMAP11 174
#define IDB_BITMAP12 175
#define IDB_BITMAP13 176
#define IDB_BITMAP14 177
#define IDB_BITMAP15 178
#define IDB_BITMAP16 179
#define IDB_BITMAP17 180
#define IDB_BITMAP18 181
#define IDB_BITMAP19 182
#define IDB_BRANCH_SPRITESHEET 184
#define MENU_RESET 200
#define BUTTON_ROMS 200
#define TXT_PAD1 200
@ -403,11 +414,17 @@
#define MEMW_EDIT02FORMULA 1144
#define IDC_BUTTON7 1145
#define MEMW_EDIT03FORMULA 1145
#define TASEDIT_REWIND_FULL2 1145
#define IDC_BUTTON8 1146
#define TASEDIT_REWIND_FULL3 1146
#define IDC_EDIT1 1147
#define IDC_BUTTON9 1148
#define TASEDIT_REWIND_FULL4 1148
#define IDC_HISTORYLIST 1149
#define IDC_BOOKMARKSLIST 1150
#define TASEDIT_REWIND_FULL5 1151
#define IDC_BRANCHES_BUTTON 1152
#define IDC_EDIT2 1154
#define CHECK_SOUND_MUTETURBO 1179
#define IDC_EDIT_AUTHOR 1180
#define MEMW_STATIC 1181
@ -511,6 +528,7 @@
#define IDC_PROGRESS1 1262
#define CHECK_FOLLOW_CURSOR 1263
#define IDC_BOOKMARKS_BOX 1264
#define IDC_BRANCHES_BITMAP 1265
#define MENU_NETWORK 40040
#define MENU_PALETTE 40041
#define MENU_SOUND 40042
@ -880,9 +898,9 @@
//
#ifdef APSTUDIO_INVOKED
#ifndef APSTUDIO_READONLY_SYMBOLS
#define _APS_NEXT_RESOURCE_VALUE 173
#define _APS_NEXT_RESOURCE_VALUE 185
#define _APS_NEXT_COMMAND_VALUE 40475
#define _APS_NEXT_CONTROL_VALUE 1265
#define _APS_NEXT_CONTROL_VALUE 1266
#define _APS_NEXT_SYMED_VALUE 101
#endif
#endif

View File

@ -39,6 +39,7 @@ bool TASEdit_show_markers = true;
bool TASEdit_bind_markers = true;
bool TASEdit_branch_full_movie = true;
bool TASEdit_branch_only_when_rec = false;
bool TASEdit_view_branches_tree = false;
bool TASEdit_restore_position = false;
int TASEdit_greenzone_capacity = GREENZONE_CAPACITY_DEFAULT;
extern bool muteTurbo;
@ -67,6 +68,8 @@ HWND hwndBookmarksList, hwndBookmarks;
WNDPROC hwndBookmarksList_oldWndProc;
HWND hwndProgressbar, hwndRewind, hwndForward, hwndRewindFull, hwndForwardFull;
HWND hwndRB_RecOff, hwndRB_RecAll, hwndRB_Rec1P, hwndRB_Rec2P, hwndRB_Rec3P, hwndRB_Rec4P;
HWND hwndBranchesBitmap;
WNDPROC hwndBranchesBitmap_oldWndProc;
HFONT hMainListFont;
@ -101,8 +104,6 @@ void GetDispInfo(NMLVDISPINFO* nmlvDispInfo)
{
if (item.iItem == currFrameCounter)
item.iImage = ARROW_IMAGE_ID;
else
item.iImage = -1;
}
}
break;
@ -274,7 +275,7 @@ void UpdateTasEdit()
{
if(!hwndTasEdit) return;
UpdateList();
UpdateList(); // also markers are updated there
greenzone.update();
playback.update();
@ -349,11 +350,19 @@ void RedrawTasedit()
InvalidateRect(hwndTasEdit, 0, FALSE);
}
void RedrawList()
{
InvalidateRect(hwndList, 0, FALSE);
}
void RedrawListAndBookmarks()
{
InvalidateRect(hwndList, 0, FALSE);
bookmarks.RedrawBookmarksList();
}
void RedrawRow(int index)
{
ListView_RedrawItems(hwndList, index, index);
}
void RedrawRowAndBookmark(int index)
{
ListView_RedrawItems(hwndList, index, index);
bookmarks.RedrawChangedBookmarks(index);
@ -592,6 +601,8 @@ void Truncate()
if (currMovieData.getNumRecords() > frame+1)
{
currMovieData.truncateAt(frame+1);
if (TASEdit_bind_markers)
markers.truncateAt(frame+1);
UpdateList();
int result = history.RegisterChanges(MODTYPE_TRUNCATE, frame+1);
if (result >= 0)
@ -981,7 +992,7 @@ LRESULT APIENTRY BookmarksListWndProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM
return CallWindowProc(hwndBookmarksList_oldWndProc, hWnd, msg, wParam, lParam);
}
LRESULT APIENTRY HistoryListWndProc(HWND hWnd,UINT msg,WPARAM wParam,LPARAM lParam)
LRESULT APIENTRY HistoryListWndProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam)
{
switch(msg)
{
@ -1000,6 +1011,46 @@ LRESULT APIENTRY HistoryListWndProc(HWND hWnd,UINT msg,WPARAM wParam,LPARAM lPar
return CallWindowProc(hwndHistoryList_oldWndProc, hWnd, msg, wParam, lParam);
}
LRESULT APIENTRY BranchesBitmapWndProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam)
{
switch(msg)
{
case WM_MOUSEMOVE:
{
if (!bookmarks.mouse_over_bitmap)
{
bookmarks.mouse_over_bitmap = true;
bookmarks.tme.hwndTrack = hWnd;
TrackMouseEvent(&bookmarks.tme);
}
bookmarks.MouseMove(GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam));
break;
}
case WM_MOUSELEAVE:
{
bookmarks.mouse_over_bitmap = false;
bookmarks.MouseMove(-1, -1);
break;
}
case WM_SYSKEYDOWN:
{
if (wParam == VK_F10)
return 0;
break;
}
case WM_PAINT:
{
PAINTSTRUCT ps;
HDC hdc = BeginPaint(hWnd, &ps);
bookmarks.PaintBranchesBitmap(hdc);
EndPaint(hWnd, &ps);
return 0;
}
}
return CallWindowProc(hwndBranchesBitmap_oldWndProc, hWnd, msg, wParam, lParam);
}
void AddFourscore()
{
// add list columns
@ -1138,7 +1189,6 @@ void OpenProject()
FollowPlayback();
RedrawTasedit();
RedrawWindowCaption();
bookmarks.RedrawBookmarksCaption();
}
}
@ -1315,6 +1365,7 @@ BOOL CALLBACK WndprocTasEdit(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lPar
hwndRB_Rec2P = GetDlgItem(hwndDlg, IDC_RADIO4);
hwndRB_Rec3P = GetDlgItem(hwndDlg, IDC_RADIO5);
hwndRB_Rec4P = GetDlgItem(hwndDlg, IDC_RADIO6);
hwndBranchesBitmap = GetDlgItem(hwndDlg, IDC_BRANCHES_BITMAP);
break;
case WM_MOVE:
@ -1420,8 +1471,8 @@ BOOL CALLBACK WndprocTasEdit(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lPar
ExitTasEdit();
break;
case WM_ACTIVATEAPP:
if((BOOL)wParam)
case WM_ACTIVATE:
if(LOWORD(wParam))
GotFocus();
else
LostFocus();
@ -1540,7 +1591,7 @@ BOOL CALLBACK WndprocTasEdit(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lPar
//switch "Highlight lag frames" flag
TASEdit_show_lag_frames ^= 1;
CheckMenuItem(hmenu, ID_VIEW_SHOW_LAG_FRAMES, TASEdit_show_lag_frames?MF_CHECKED : MF_UNCHECKED);
RedrawList();
RedrawListAndBookmarks();
break;
case ID_VIEW_SHOW_MARKERS:
//switch "Show Markers" flag
@ -1625,6 +1676,11 @@ BOOL CALLBACK WndprocTasEdit(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lPar
// click on progressbar - stop seeking
if (playback.pauseframe) playback.SeekingStop();
break;
case IDC_BRANCHES_BUTTON:
// click on "Bookmarks/Branches" - switch "View Tree of branches"
TASEdit_view_branches_tree ^= 1;
bookmarks.RedrawBookmarksCaption();
break;
case IDC_RADIO1:
// switch to readonly, no need to recheck radiobuttons
if (!movie_readonly) FCEUI_MovieToggleReadOnly();
@ -1838,6 +1894,7 @@ void EnterTasEdit()
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
@ -1877,37 +1934,67 @@ void EnterTasEdit()
// setup images for the listview
HIMAGELIST himglist = ImageList_Create(9, 13, ILC_COLOR8 | ILC_MASK, 1, 1);
HBITMAP bmp = LoadBitmap(fceu_hInstance, MAKEINTRESOURCE(IDB_BITMAP0));
ImageList_AddMasked(himglist, bmp, 0xFF00FF);
ImageList_AddMasked(himglist, bmp, 0xFFFFFF);
DeleteObject(bmp);
bmp = LoadBitmap(fceu_hInstance, MAKEINTRESOURCE(IDB_BITMAP1));
ImageList_AddMasked(himglist, bmp, 0xFF00FF);
ImageList_AddMasked(himglist, bmp, 0xFFFFFF);
DeleteObject(bmp);
bmp = LoadBitmap(fceu_hInstance, MAKEINTRESOURCE(IDB_BITMAP2));
ImageList_AddMasked(himglist, bmp, 0xFF00FF);
ImageList_AddMasked(himglist, bmp, 0xFFFFFF);
DeleteObject(bmp);
bmp = LoadBitmap(fceu_hInstance, MAKEINTRESOURCE(IDB_BITMAP3));
ImageList_AddMasked(himglist, bmp, 0xFF00FF);
ImageList_AddMasked(himglist, bmp, 0xFFFFFF);
DeleteObject(bmp);
bmp = LoadBitmap(fceu_hInstance, MAKEINTRESOURCE(IDB_BITMAP4));
ImageList_AddMasked(himglist, bmp, 0xFF00FF);
ImageList_AddMasked(himglist, bmp, 0xFFFFFF);
DeleteObject(bmp);
bmp = LoadBitmap(fceu_hInstance, MAKEINTRESOURCE(IDB_BITMAP5));
ImageList_AddMasked(himglist, bmp, 0xFF00FF);
ImageList_AddMasked(himglist, bmp, 0xFFFFFF);
DeleteObject(bmp);
bmp = LoadBitmap(fceu_hInstance, MAKEINTRESOURCE(IDB_BITMAP6));
ImageList_AddMasked(himglist, bmp, 0xFF00FF);
ImageList_AddMasked(himglist, bmp, 0xFFFFFF);
DeleteObject(bmp);
bmp = LoadBitmap(fceu_hInstance, MAKEINTRESOURCE(IDB_BITMAP7));
ImageList_AddMasked(himglist, bmp, 0xFF00FF);
ImageList_AddMasked(himglist, bmp, 0xFFFFFF);
DeleteObject(bmp);
bmp = LoadBitmap(fceu_hInstance, MAKEINTRESOURCE(IDB_BITMAP8));
ImageList_AddMasked(himglist, bmp, 0xFF00FF);
ImageList_AddMasked(himglist, bmp, 0xFFFFFF);
DeleteObject(bmp);
bmp = LoadBitmap(fceu_hInstance, MAKEINTRESOURCE(IDB_BITMAP9));
ImageList_AddMasked(himglist, bmp, 0xFF00FF);
ImageList_AddMasked(himglist, bmp, 0xFFFFFF);
DeleteObject(bmp);
bmp = LoadBitmap(fceu_hInstance, MAKEINTRESOURCE(IDB_BITMAP10));
ImageList_AddMasked(himglist, bmp, 0xFFFFFF);
DeleteObject(bmp);
bmp = LoadBitmap(fceu_hInstance, MAKEINTRESOURCE(IDB_BITMAP11));
ImageList_AddMasked(himglist, bmp, 0xFFFFFF);
DeleteObject(bmp);
bmp = LoadBitmap(fceu_hInstance, MAKEINTRESOURCE(IDB_BITMAP12));
ImageList_AddMasked(himglist, bmp, 0xFFFFFF);
DeleteObject(bmp);
bmp = LoadBitmap(fceu_hInstance, MAKEINTRESOURCE(IDB_BITMAP13));
ImageList_AddMasked(himglist, bmp, 0xFFFFFF);
DeleteObject(bmp);
bmp = LoadBitmap(fceu_hInstance, MAKEINTRESOURCE(IDB_BITMAP14));
ImageList_AddMasked(himglist, bmp, 0xFFFFFF);
DeleteObject(bmp);
bmp = LoadBitmap(fceu_hInstance, MAKEINTRESOURCE(IDB_BITMAP15));
ImageList_AddMasked(himglist, bmp, 0xFFFFFF);
DeleteObject(bmp);
bmp = LoadBitmap(fceu_hInstance, MAKEINTRESOURCE(IDB_BITMAP16));
ImageList_AddMasked(himglist, bmp, 0xFFFFFF);
DeleteObject(bmp);
bmp = LoadBitmap(fceu_hInstance, MAKEINTRESOURCE(IDB_BITMAP17));
ImageList_AddMasked(himglist, bmp, 0xFFFFFF);
DeleteObject(bmp);
bmp = LoadBitmap(fceu_hInstance, MAKEINTRESOURCE(IDB_BITMAP18));
ImageList_AddMasked(himglist, bmp, 0xFFFFFF);
DeleteObject(bmp);
bmp = LoadBitmap(fceu_hInstance, MAKEINTRESOURCE(IDB_BITMAP19));
ImageList_AddMasked(himglist, bmp, 0xFFFFFF);
DeleteObject(bmp);
bmp = LoadBitmap(fceu_hInstance, MAKEINTRESOURCE(IDB_TE_ARROW));
ImageList_AddMasked(himglist, bmp, 0xFF00FF);
ImageList_AddMasked(himglist, bmp, 0xFFFFFF);
DeleteObject(bmp);
ListView_SetImageList(hwndList, himglist, LVSIL_SMALL);
// setup columns
@ -1967,6 +2054,9 @@ 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();
@ -1995,6 +2085,7 @@ bool ExitTasEdit()
// clear "Background TASEdit input"
KeyboardClearBackgroundAccessBit(KEYBACKACCESS_TASEDIT);
JoystickClearBackgroundAccessBit(JOYBACKACCESS_TASEDIT);
// release memory
markers.free();
greenzone.clearGreenzone();

View File

@ -58,7 +58,7 @@
#define COLUMN_JOYPAD4_R 33
#define COLUMN_FRAMENUM2 34
#define DIGITS_IN_FRAMENUM 7
#define ARROW_IMAGE_ID 10
#define ARROW_IMAGE_ID 20
// listview colors
#define NORMAL_FRAMENUM_COLOR 0xFFFFFF
#define NORMAL_INPUT_COLOR1 0xEDEDED
@ -116,7 +116,9 @@ void RemoveFourscore();
void RedrawWindowCaption();
void RedrawTasedit();
void RedrawList();
void RedrawListAndBookmarks();
void RedrawRow(int index);
void RedrawRowAndBookmark(int index);
void ToggleJoypadBit(int column_index, int row_index, UINT KeyFlags);
void SwitchToReadOnly();
void UncheckRecordingRadioButtons();

View File

@ -18,6 +18,7 @@ void BOOKMARK::init()
not_empty = false;
flash_type = flash_phase = 0;
snapshot.jump_frame = -1;
parent_branch = -1; // -1 = root
}
void BOOKMARK::set()
@ -25,7 +26,7 @@ void BOOKMARK::set()
snapshot.init(currMovieData, false);
snapshot.jump_frame = currFrameCounter;
savestate = greenzone.savestates[currFrameCounter];
//screenshots
// save screenshot
not_empty = true;
flash_phase = FLASH_PHASE_MAX;
@ -38,7 +39,7 @@ void BOOKMARK::jump()
flash_type = FLASH_TYPE_JUMP;
}
void BOOKMARK::unleash()
void BOOKMARK::unleashed()
{
flash_phase = FLASH_PHASE_MAX;
flash_type = FLASH_TYPE_UNLEASH;
@ -49,12 +50,15 @@ void BOOKMARK::save(EMUFILE *os)
if (not_empty)
{
write8le(1, os);
// write parent_branch
write8le((uint8)parent_branch, os);
// write snapshot
snapshot.save(os);
// write savestate
int size = savestate.size();
write32le(size, os);
os->fwrite(&savestate[0], size);
//write screenshots (current, saved)
// write saved_screenshot
} else write8le((uint8)0, os);
}
@ -66,13 +70,17 @@ bool BOOKMARK::load(EMUFILE *is)
not_empty = tmp != 0;
if (not_empty)
{
// read parent_branch
if (!read8le(&tmp, is)) return true;
parent_branch = *(int8*)(&tmp); // don't kill me for that
// read snapshot
if (snapshot.load(is)) return true;
// read savestate
int size;
if (!read32le((uint32 *)&size, is)) return true;
savestate.resize(size);
if ((int)is->fread(&savestate[0], size) < size) return true;
//read screenshots (current, saved)
// read saved_screenshot
}
// all ok

View File

@ -13,7 +13,7 @@ public:
void set();
void jump();
void unleash();
void unleashed();
void save(EMUFILE *os);
bool load(EMUFILE *is);
@ -23,8 +23,8 @@ public:
int flash_type;
INPUT_SNAPSHOT snapshot;
std::vector<uint8> savestate;
std::vector<uint8> current_screenshot;
std::vector<uint8> saved_screenshot;
int parent_branch;
private:

View File

@ -7,8 +7,10 @@
#include "zlib.h"
#include "utils/xstring.h"
#pragma comment(lib, "msimg32.lib")
char bookmarks_save_id[BOOKMARKS_ID_LEN] = "BOOKMARKS";
char bookmarksCaption[2][23] = { " Bookmarks ", " Bookmarks / Branches " };
char bookmarksCaption[3][23] = { " Bookmarks ", " Bookmarks / Branches ", " Branches " };
// color tables for flashing when saving/loading bookmarks
COLORREF bookmark_flash_colors[3][FLASH_PHASE_MAX+1] = {
@ -18,6 +20,8 @@ COLORREF bookmark_flash_colors[3][FLASH_PHASE_MAX+1] = {
0x382309, 0x3c350e, 0x404814, 0x455a19, 0x486c1e, 0x4d7f23, 0x519128, 0x55a32d, 0x5ab532, 0x5ec837, 0x62da3c, 0x66ec41,
// unleash
0x320d23, 0x341435, 0x361b48, 0x38215a, 0x39286c, 0x3b2f7f, 0x3c3691, 0x3e3ca3, 0x4043b5, 0x414ac8, 0x4351da, 0x4457ec };
// corners cursor animation
int corners_cursor_shift[BRANCHES_ANIMATION_FRAMES] = {0, 1, 2, 3, 4, 5, 5, 4, 3, 2, 1, 0 };
extern PLAYBACK playback;
extern GREENZONE greenzone;
@ -27,26 +31,16 @@ extern MARKERS markers;
extern HWND hwndBookmarks;
extern HWND hwndBookmarksList;
extern HWND hwndBranchesBitmap;
extern bool TASEdit_show_lag_frames;
extern bool TASEdit_bind_markers;
extern bool TASEdit_branch_full_movie;
extern bool TASEdit_branch_only_when_rec;
extern bool TASEdit_view_branches_tree;
BOOKMARKS::BOOKMARKS()
{
}
void BOOKMARKS::init()
{
free();
bookmarks_array.resize(TOTAL_BOOKMARKS);
for (int i = 0; i < TOTAL_BOOKMARKS; ++i)
{
bookmarks_array[i].init();
}
ListView_SetItemCountEx(hwndBookmarksList, TOTAL_BOOKMARKS, LVSICF_NOSCROLL | LVSICF_NOINVALIDATEALL);
// create font
hBookmarksFont = CreateFont(13, 8, /*Height,Width*/
0, 0, /*escapement,orientation*/
@ -54,14 +48,120 @@ void BOOKMARKS::init()
ANSI_CHARSET, OUT_DEVICE_PRECIS, CLIP_MASK, /*charset, precision, clipping*/
DEFAULT_QUALITY, DEFAULT_PITCH, /*quality, and pitch*/
"Courier"); /*font name*/
// fill TrackMouseEvent struct
tme.cbSize = sizeof(tme);
tme.dwFlags = TME_LEAVE;
tme.hwndTrack = hwndBranchesBitmap;
}
void BOOKMARKS::init()
{
free();
// init arrays
BranchX.resize(TOTAL_BOOKMARKS+1);
BranchY.resize(TOTAL_BOOKMARKS+1);
BranchPrevX.resize(TOTAL_BOOKMARKS+1);
BranchPrevY.resize(TOTAL_BOOKMARKS+1);
BranchCurrX.resize(TOTAL_BOOKMARKS+1);
BranchCurrY.resize(TOTAL_BOOKMARKS+1);
for (int i = TOTAL_BOOKMARKS; i >= 0; i--)
{
BranchX[i] = BranchPrevX[i] = BranchCurrX[i] = EMPTY_BRANCHES_X;
BranchY[i] = BranchPrevY[i] = BranchCurrY[i] = EMPTY_BRANCHES_Y_BASE + EMPTY_BRANCHES_Y_FACTOR * ((i + TOTAL_BOOKMARKS - 1) % TOTAL_BOOKMARKS);
}
CursorX = CursorPrevX = CloudX = CloudPrevX = BRANCHES_CLOUD_X;
CursorY = CursorPrevY = BRANCHES_CLOUD_Y;
reset();
current_branch = -1; // -1 = root
changes_since_current_branch = false;
fireball_size = 0;
// set cloud_time and current_pos_time
SetCurrentPosTime();
strcpy(cloud_time, current_pos_time);
// init bookmarks
bookmarks_array.resize(TOTAL_BOOKMARKS);
for (int i = 0; i < TOTAL_BOOKMARKS; ++i)
bookmarks_array[i].init();
ListView_SetItemCountEx(hwndBookmarksList, TOTAL_BOOKMARKS, LVSICF_NOSCROLL | LVSICF_NOINVALIDATEALL);
// init GDI stuff
HDC win_hdc = GetWindowDC(hwndBookmarksList);
hBitmapDC = CreateCompatibleDC(win_hdc);
branches_hbitmap = CreateCompatibleBitmap(win_hdc, BRANCHES_BITMAP_WIDTH, BRANCHES_BITMAP_WIDTH);
hOldBitmap = (HBITMAP)SelectObject(hBitmapDC, branches_hbitmap);
hBufferDC = CreateCompatibleDC(win_hdc);
buffer_hbitmap = CreateCompatibleBitmap(win_hdc, BRANCHES_BITMAP_WIDTH, BRANCHES_BITMAP_WIDTH);
hOldBitmap1 = (HBITMAP)SelectObject(hBufferDC, buffer_hbitmap);
normal_brush = CreateSolidBrush(0x000000);
// prepare branches spritesheet
branchesSpritesheet = LoadBitmap(fceu_hInstance, MAKEINTRESOURCE(IDB_BRANCH_SPRITESHEET));
hSpritesheetDC = CreateCompatibleDC(win_hdc);
hOldBitmap2 = (HBITMAP)SelectObject(hSpritesheetDC, branchesSpritesheet);
// create pens
normal_pen = CreatePen(PS_SOLID, 1, 0x0);
select_pen = CreatePen(PS_SOLID, 2, 0xFF9080);
RedrawBookmarksCaption();
update();
}
void BOOKMARKS::reset()
{
transition_phase = animation_frame = 0;
mouse_x = mouse_y = -1;
item_under_mouse = ITEM_UNDER_MOUSE_NONE;
mouse_over_bitmap = false;
must_recalculate_branches_tree = must_redraw_branches_tree = true;
check_flash_shedule = clock() + BOOKMARKS_FLASH_TICK;
RedrawBookmarksList();
next_animation_time = clock() + BRANCHES_ANIMATION_TICK;
}
void BOOKMARKS::free()
{
bookmarks_array.resize(0);
BranchX.resize(0);
BranchY.resize(0);
BranchPrevX.resize(0);
BranchPrevY.resize(0);
BranchCurrX.resize(0);
BranchCurrY.resize(0);
// free GDI stuff
if (hOldBitmap && hBitmapDC)
{
SelectObject(hBitmapDC, hOldBitmap);
DeleteDC(hBitmapDC);
hBitmapDC = NULL;
}
if (branches_hbitmap)
{
DeleteObject(branches_hbitmap);
branches_hbitmap = NULL;
}
if (hOldBitmap1 && hBufferDC)
{
SelectObject(hBufferDC, hOldBitmap1);
DeleteDC(hBufferDC);
hBufferDC = NULL;
}
if (buffer_hbitmap)
{
DeleteObject(buffer_hbitmap);
buffer_hbitmap = NULL;
}
if (hOldBitmap2 && hSpritesheetDC)
{
SelectObject(hSpritesheetDC, hOldBitmap2);
DeleteDC(hSpritesheetDC);
hSpritesheetDC = NULL;
}
if (branchesSpritesheet)
{
DeleteObject(branchesSpritesheet);
branchesSpritesheet = NULL;
}
}
void BOOKMARKS::update()
@ -76,21 +176,98 @@ void BOOKMARKS::update()
{
bookmarks_array[i].flash_phase--;
RedrawBookmarksRow((i + TOTAL_BOOKMARKS - 1) % TOTAL_BOOKMARKS);
must_redraw_branches_tree = true;
}
}
}
if (must_recalculate_branches_tree)
RecalculateBranchesTree();
if (edit_mode == EDIT_MODE_BRANCHES)
{
if (clock() > next_animation_time)
{
// animate
next_animation_time = clock() + BRANCHES_ANIMATION_TICK;
animation_frame = (animation_frame + 1) % BRANCHES_ANIMATION_FRAMES;
// grow or shring fireball
if (changes_since_current_branch)
{
fireball_size++;
if (fireball_size > BRANCHES_FIREBALL_MAX_SIZE) fireball_size = BRANCHES_FIREBALL_MAX_SIZE;
} else
{
fireball_size--;
if (fireball_size < 0) fireball_size = 0;
}
// also update transition from old to new tree
if (transition_phase)
{
transition_phase--;
must_redraw_branches_tree = true;
} else if (!must_redraw_branches_tree)
{
InvalidateRect(hwndBranchesBitmap, 0, FALSE);
}
}
// render
if (must_redraw_branches_tree)
RedrawBranchesTree();
}
}
void BOOKMARKS::set(int slot)
{
if (slot < 0 || slot >= TOTAL_BOOKMARKS) return;
int previous_frame = bookmarks_array[slot].snapshot.jump_frame;
// save time of this slot before rewriting it
char saved_time[TIME_DESC_LENGTH];
if (bookmarks_array[slot].not_empty)
strncpy(saved_time, bookmarks_array[slot].snapshot.description, TIME_DESC_LENGTH-1);
else
saved_time[0] = 0;
bookmarks_array[slot].set();
if (previous_frame >= 0 && previous_frame != currFrameCounter)
RedrawRow(previous_frame);
RedrawRow(currFrameCounter);
RedrawBookmarksRow((slot + TOTAL_BOOKMARKS - 1) % TOTAL_BOOKMARKS);
// inherit current branch
if (slot != current_branch)
{
int parent = bookmarks_array[slot].parent_branch;
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
int i = 0;
for (; i < TOTAL_BOOKMARKS; ++i)
{
if (bookmarks_array[i].not_empty && bookmarks_array[i].parent_branch == -1 && i != slot)
break;
}
if (i >= TOTAL_BOOKMARKS)
// didn't find another child of cloud
strcpy(cloud_time, saved_time);
}
// before disconnecting from old parent, connect all childs to the 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;
}
bookmarks_array[slot].parent_branch = current_branch;
}
// switch current branch to this branch
if (slot != current_branch && current_branch >= 0)
RedrawRowAndBookmark(bookmarks_array[current_branch].snapshot.jump_frame);
if (slot != current_branch || changes_since_current_branch)
must_recalculate_branches_tree = true;
current_branch = slot;
changes_since_current_branch = false;
project.changed = true;
if (previous_frame >= 0 && previous_frame != currFrameCounter)
RedrawRowAndBookmark(previous_frame);
RedrawRowAndBookmark(currFrameCounter);
}
void BOOKMARKS::jump(int slot)
@ -143,12 +320,12 @@ void BOOKMARKS::unleash(int slot)
UpdateList();
history.RegisterBranch(MODTYPE_BRANCH_0 + slot, first_change, bookmarks_array[slot].snapshot.description);
greenzone.Invalidate(first_change);
bookmarks_array[slot].unleash();
bookmarks_array[slot].unleashed();
} else if (markers_changed)
{
history.RegisterBranch(MODTYPE_BRANCH_MARKERS_0 + slot, first_change, bookmarks_array[slot].snapshot.description);
RedrawList();
bookmarks_array[slot].unleash();
bookmarks_array[slot].unleashed();
} else
{
// didn't restore anything
@ -177,12 +354,12 @@ void BOOKMARKS::unleash(int slot)
UpdateList();
history.RegisterBranch(MODTYPE_BRANCH_0 + slot, first_change, bookmarks_array[slot].snapshot.description);
greenzone.Invalidate(first_change);
bookmarks_array[slot].unleash();
bookmarks_array[slot].unleashed();
} else if (markers_changed)
{
history.RegisterBranch(MODTYPE_BRANCH_MARKERS_0 + slot, first_change, bookmarks_array[slot].snapshot.description);
RedrawList();
bookmarks_array[slot].unleash();
bookmarks_array[slot].unleashed();
} else
{
// didn't restore anything
@ -193,23 +370,48 @@ void BOOKMARKS::unleash(int slot)
// if greenzone reduced so much that we can't jump immediately - substitute target frame greenzone with our savestate
if (greenzone.greenZoneCount <= jump_frame || greenzone.savestates[jump_frame].empty())
{
if ((int)greenzone.savestates.size() <= jump_frame)
greenzone.savestates.resize(jump_frame+1);
// clear old savestates: from current end of greenzone to new end of greenzone
for (int i = greenzone.greenZoneCount; i < jump_frame; ++i)
greenzone.ClearSavestate(i);
if (greenzone.greenZoneCount <= jump_frame)
{
for (int i = greenzone.greenZoneCount; i < jump_frame; ++i)
greenzone.ClearSavestate(i);
greenzone.greenZoneCount = jump_frame+1;
}
// restore savestate for immediate jump
greenzone.savestates[jump_frame] = bookmarks_array[slot].savestate;
// and move greenzone end to this new position
if (greenzone.greenZoneCount <= jump_frame) greenzone.greenZoneCount = jump_frame+1;
}
greenzone.update();
// jump to the target (bookmarked frame)
playback.jump(jump_frame);
// switch current branch to this branch
if (slot != current_branch && current_branch >= 0)
{
RedrawRowAndBookmark(bookmarks_array[current_branch].snapshot.jump_frame);
RedrawRowAndBookmark(bookmarks_array[slot].snapshot.jump_frame);
}
current_branch = slot;
changes_since_current_branch = false;
must_recalculate_branches_tree = true;
}
void BOOKMARKS::save(EMUFILE *os)
{
// write "BOOKMARKS" string
os->fwrite(bookmarks_save_id, BOOKMARKS_ID_LEN);
// write cloud time
os->fwrite(cloud_time, TIME_DESC_LENGTH);
// write current branch and flag of changes since it
write8le((uint8)current_branch, os);
if (changes_since_current_branch)
write8le((uint8)1, os);
else
write8le((uint8)0, os);
// write current_position time
os->fwrite(current_pos_time, TIME_DESC_LENGTH);
// write all 10 bookmarks
for (int i = 0; i < TOTAL_BOOKMARKS; ++i)
{
@ -223,27 +425,53 @@ bool BOOKMARKS::load(EMUFILE *is)
char save_id[BOOKMARKS_ID_LEN];
if ((int)is->fread(save_id, BOOKMARKS_ID_LEN) < BOOKMARKS_ID_LEN) return true;
if (strcmp(bookmarks_save_id, save_id)) return true; // string is not valid
// read cloud time
if ((int)is->fread(cloud_time, TIME_DESC_LENGTH) < TIME_DESC_LENGTH) return true;
// read current branch and flag of changes since it
uint8 tmp;
if (!read8le(&tmp, is)) return true;
current_branch = tmp;
if (!read8le(&tmp, is)) return true;
changes_since_current_branch = (tmp != 0);
// read current_position time
if ((int)is->fread(current_pos_time, TIME_DESC_LENGTH) < TIME_DESC_LENGTH) return true;
// read all 10 bookmarks
for (int i = 0; i < TOTAL_BOOKMARKS; ++i)
{
if (bookmarks_array[i].load(is)) return true;
}
// all ok
check_flash_shedule = clock() + BOOKMARKS_FLASH_TICK;
reset();
RedrawBookmarksCaption();
return false;
}
// ----------------------------------------------------------
void BOOKMARKS::RedrawBookmarksCaption()
{
if (TASEdit_branch_only_when_rec)
SetWindowText(hwndBookmarks, bookmarksCaption[(movie_readonly)?0:1]);
else
SetWindowText(hwndBookmarks, bookmarksCaption[1]);
RedrawBookmarksList();
if (TASEdit_branch_only_when_rec && movie_readonly)
{
edit_mode = EDIT_MODE_BOOKMARKS;
ShowWindow(hwndBranchesBitmap, SW_HIDE);
ShowWindow(hwndBookmarksList, SW_SHOW);
RedrawBookmarksList();
} else if (TASEdit_view_branches_tree)
{
edit_mode = EDIT_MODE_BRANCHES;
ShowWindow(hwndBookmarksList, SW_HIDE);
ShowWindow(hwndBranchesBitmap, SW_SHOW);
} else
{
edit_mode = EDIT_MODE_BOTH;
ShowWindow(hwndBranchesBitmap, SW_HIDE);
ShowWindow(hwndBookmarksList, SW_SHOW);
RedrawBookmarksList();
}
SetWindowText(hwndBookmarks, bookmarksCaption[edit_mode]);
}
void BOOKMARKS::RedrawBookmarksList()
{
InvalidateRect(hwndBookmarksList, 0, FALSE);
if (edit_mode != EDIT_MODE_BRANCHES)
InvalidateRect(hwndBookmarksList, 0, FALSE);
}
void BOOKMARKS::RedrawChangedBookmarks(int frame)
{
@ -258,6 +486,215 @@ void BOOKMARKS::RedrawBookmarksRow(int index)
ListView_RedrawItems(hwndBookmarksList, index, index);
}
void BOOKMARKS::RedrawBranchesTree()
{
// first calculate current positions of branch items
for (int i = 0; i <= TOTAL_BOOKMARKS; ++i)
{
BranchCurrX[i] = (BranchX[i] * (BRANCHES_TRANSITION_MAX - transition_phase) + BranchPrevX[i] * transition_phase) / BRANCHES_TRANSITION_MAX;
BranchCurrY[i] = (BranchY[i] * (BRANCHES_TRANSITION_MAX - transition_phase) + BranchPrevY[i] * transition_phase) / BRANCHES_TRANSITION_MAX;
}
int cloud_x = (CloudX * (BRANCHES_TRANSITION_MAX - transition_phase) + CloudPrevX * transition_phase) / BRANCHES_TRANSITION_MAX;
// find item under mouse
item_under_mouse = ITEM_UNDER_MOUSE_NONE;
for (int i = 0; i < TOTAL_BOOKMARKS; ++i)
if (item_under_mouse == ITEM_UNDER_MOUSE_NONE && mouse_x >= BranchCurrX[i] - DIGIT_RECT_HALFWIDTH && mouse_x < BranchCurrX[i] - DIGIT_RECT_HALFWIDTH + DIGIT_RECT_WIDTH && mouse_y >= BranchCurrY[i] - DIGIT_RECT_HALFHEIGHT && mouse_y < BranchCurrY[i] - DIGIT_RECT_HALFHEIGHT + DIGIT_RECT_HEIGHT)
item_under_mouse = i;
if (item_under_mouse == ITEM_UNDER_MOUSE_NONE && mouse_x >= cloud_x - BRANCHES_CLOUD_HALFWIDTH && mouse_x < cloud_x - BRANCHES_CLOUD_HALFWIDTH + BRANCHES_CLOUD_WIDTH && mouse_y >= BRANCHES_CLOUD_Y - BRANCHES_CLOUD_HALFHEIGHT && mouse_y < BRANCHES_CLOUD_Y - BRANCHES_CLOUD_HALFHEIGHT + BRANCHES_CLOUD_HEIGHT)
item_under_mouse = ITEM_UNDER_MOUSE_CLOUD;
if (item_under_mouse == ITEM_UNDER_MOUSE_NONE && changes_since_current_branch && mouse_x >= BranchCurrX[TOTAL_BOOKMARKS] - DIGIT_RECT_HALFWIDTH && mouse_x < BranchCurrX[TOTAL_BOOKMARKS] - DIGIT_RECT_HALFWIDTH + DIGIT_RECT_WIDTH && mouse_y >= BranchCurrY[TOTAL_BOOKMARKS] - DIGIT_RECT_HALFHEIGHT && mouse_y < BranchCurrY[TOTAL_BOOKMARKS] - DIGIT_RECT_HALFHEIGHT + DIGIT_RECT_HEIGHT)
item_under_mouse = TOTAL_BOOKMARKS;
// draw background gradient
TRIVERTEX vertex[2] ;
vertex[0].x = 0;
vertex[0].y = 0;
vertex[0].Red = 0xC700;
vertex[0].Green = 0xE700;
vertex[0].Blue = 0xF300;
vertex[0].Alpha = 0x0000;
vertex[1].x = BRANCHES_BITMAP_WIDTH;
vertex[1].y = BRANCHES_BITMAP_HEIGHT;
vertex[1].Red = 0xEB00;
vertex[1].Green = 0xFA00;
vertex[1].Blue = 0xF800;
vertex[1].Alpha = 0x0000;
GRADIENT_RECT gRect;
gRect.UpperLeft = 0;
gRect.LowerRight = 1;
GradientFill(hBitmapDC, vertex, 2, &gRect, 1, GRADIENT_FILL_RECT_H);
// lines
int branch_x, branch_y, parent_x, parent_y, child_id;
SelectObject(hBitmapDC, normal_pen);
for (int t = Children.size() - 1; t >= 0; t--)
{
if (t > 0)
{
parent_x = BranchCurrX[t-1];
parent_y = BranchCurrY[t-1];
} else
{
parent_x = cloud_x;
parent_y = BRANCHES_CLOUD_Y;
}
for (int i = Children[t].size() - 1; i >= 0; i--)
{
child_id = Children[t][i];
if (child_id < TOTAL_BOOKMARKS)
{
MoveToEx(hBitmapDC, parent_x, parent_y, 0);
LineTo(hBitmapDC, BranchCurrX[child_id], BranchCurrY[child_id]);
}
}
}
// lines for item under mouse
SelectObject(hBitmapDC, select_pen);
int branch = item_under_mouse;
if (item_under_mouse == TOTAL_BOOKMARKS)
branch = current_branch;
while (branch >= 0)
{
branch_x = BranchCurrX[branch];
branch_y = BranchCurrY[branch];
MoveToEx(hBitmapDC, branch_x, branch_y, 0);
branch = bookmarks_array[branch].parent_branch;
if (branch >= 0)
{
branch_x = BranchCurrX[branch];
branch_y = BranchCurrY[branch];
} else
{
branch_x = cloud_x;
branch_y = BRANCHES_CLOUD_Y;
}
LineTo(hBitmapDC, branch_x, branch_y);
}
if (changes_since_current_branch)
{
if (item_under_mouse != TOTAL_BOOKMARKS)
SelectObject(hBitmapDC, normal_pen);
if (current_branch >= 0)
{
parent_x = BranchCurrX[current_branch];
parent_y = BranchCurrY[current_branch];
} else
{
parent_x = cloud_x;
parent_y = BRANCHES_CLOUD_Y;
}
MoveToEx(hBitmapDC, parent_x, parent_y, 0);
branch_x = BranchCurrX[TOTAL_BOOKMARKS];
branch_y = BranchCurrY[TOTAL_BOOKMARKS];
LineTo(hBitmapDC, branch_x, branch_y);
}
// cloud
TransparentBlt(hBitmapDC, cloud_x - BRANCHES_CLOUD_HALFWIDTH, BRANCHES_CLOUD_Y - BRANCHES_CLOUD_HALFHEIGHT, BRANCHES_CLOUD_WIDTH, BRANCHES_CLOUD_HEIGHT, hSpritesheetDC, BRANCHES_CLOUD_SPRITESHEET_X, BRANCHES_CLOUD_SPRITESHEET_Y, BRANCHES_CLOUD_WIDTH, BRANCHES_CLOUD_HEIGHT, 0x00FF00);
// branches rectangles
for (int i = 0; i < TOTAL_BOOKMARKS; ++i)
{
temp_rect.left = BranchCurrX[i] - DIGIT_RECT_HALFWIDTH;
temp_rect.top = BranchCurrY[i] - DIGIT_RECT_HALFHEIGHT;
temp_rect.right = temp_rect.left + DIGIT_RECT_WIDTH;
temp_rect.bottom = temp_rect.top + DIGIT_RECT_HEIGHT;
if (bookmarks_array[i].flash_phase)
{
// draw colored rect
HBRUSH color_brush = CreateSolidBrush(bookmark_flash_colors[bookmarks_array[i].flash_type][bookmarks_array[i].flash_phase]);
FillRect(hBitmapDC, &temp_rect, color_brush);
DeleteObject(color_brush);
} else
{
// draw black rect
FillRect(hBitmapDC, &temp_rect, normal_brush);
}
}
// digits
for (int i = 0; i < TOTAL_BOOKMARKS; ++i)
{
branch_x = BranchCurrX[i] - DIGIT_BITMAP_HALFWIDTH;
branch_y = BranchCurrY[i] - DIGIT_BITMAP_HALFHEIGHT;
if(i == current_branch)
{
if (i == item_under_mouse)
BitBlt(hBitmapDC, branch_x, branch_y, DIGIT_BITMAP_WIDTH, DIGIT_BITMAP_HEIGHT, hSpritesheetDC, i * DIGIT_BITMAP_WIDTH + BLUE_DIGITS_SPRITESHEET_DX, MOUSEOVER_DIGITS_SPRITESHEET_DY, SRCCOPY);
else
BitBlt(hBitmapDC, branch_x, branch_y, DIGIT_BITMAP_WIDTH, DIGIT_BITMAP_HEIGHT, hSpritesheetDC, i * DIGIT_BITMAP_WIDTH + BLUE_DIGITS_SPRITESHEET_DX, 0, SRCCOPY);
} else
{
if (i == item_under_mouse)
BitBlt(hBitmapDC, branch_x, branch_y, DIGIT_BITMAP_WIDTH, DIGIT_BITMAP_HEIGHT, hSpritesheetDC, i * DIGIT_BITMAP_WIDTH, MOUSEOVER_DIGITS_SPRITESHEET_DY, SRCCOPY);
else
BitBlt(hBitmapDC, branch_x, branch_y, DIGIT_BITMAP_WIDTH, DIGIT_BITMAP_HEIGHT, hSpritesheetDC, i * DIGIT_BITMAP_WIDTH, 0, SRCCOPY);
}
}
// 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);
else if (item_under_mouse < TOTAL_BOOKMARKS)
TextOut(hBitmapDC, 0, 0, (LPCSTR)bookmarks_array[item_under_mouse].snapshot.description, 8);
else
TextOut(hBitmapDC, 0, 0, (LPCSTR)current_pos_time, 8);
}
// finished
must_redraw_branches_tree = false;
InvalidateRect(hwndBranchesBitmap, 0, FALSE);
}
// this is called by wndproc on WM_PAINT
void BOOKMARKS::PaintBranchesBitmap(HDC hdc)
{
int branch_x, branch_y;
// "bg"
BitBlt(hBufferDC, 0, 0, BRANCHES_BITMAP_WIDTH, BRANCHES_BITMAP_HEIGHT, hBitmapDC, 0, 0, SRCCOPY);
// "sprites"
// fireball
if (fireball_size)
{
branch_x = BranchCurrX[TOTAL_BOOKMARKS] - BRANCHES_FIREBALL_HALFWIDTH;
branch_y = BranchCurrY[TOTAL_BOOKMARKS] - BRANCHES_FIREBALL_HALFHEIGHT;
if (fireball_size >= BRANCHES_FIREBALL_MAX_SIZE)
{
TransparentBlt(hBufferDC, branch_x, branch_y, BRANCHES_FIREBALL_WIDTH, BRANCHES_FIREBALL_HEIGHT, hSpritesheetDC, animation_frame * BRANCHES_FIREBALL_WIDTH + BRANCHES_FIREBALL_SPRITESHEET_X, BRANCHES_FIREBALL_SPRITESHEET_Y, BRANCHES_FIREBALL_WIDTH, BRANCHES_FIREBALL_HEIGHT, 0x00FF00);
} else
{
TransparentBlt(hBufferDC, branch_x, branch_y, BRANCHES_FIREBALL_WIDTH, BRANCHES_FIREBALL_HEIGHT, hSpritesheetDC, BRANCHES_FIREBALL_SPRITESHEET_END_X - fireball_size * BRANCHES_FIREBALL_WIDTH, BRANCHES_FIREBALL_SPRITESHEET_Y, BRANCHES_FIREBALL_WIDTH, BRANCHES_FIREBALL_HEIGHT, 0x00FF00);
}
}
// corners cursor
branch_x = (CursorX * (BRANCHES_TRANSITION_MAX - transition_phase) + CursorPrevX * transition_phase) / BRANCHES_TRANSITION_MAX;
branch_y = (CursorY * (BRANCHES_TRANSITION_MAX - transition_phase) + CursorPrevY * transition_phase) / BRANCHES_TRANSITION_MAX;
int current_corners_cursor_shift = BRANCHES_CORNER_BASE_SHIFT + corners_cursor_shift[animation_frame];
int corner_x, corner_y;
// upper left
corner_x = branch_x - current_corners_cursor_shift - BRANCHES_CORNER_HALFWIDTH;
corner_y = branch_y - current_corners_cursor_shift - BRANCHES_CORNER_HALFHEIGHT;
TransparentBlt(hBufferDC, corner_x, corner_y, BRANCHES_CORNER_WIDTH, BRANCHES_CORNER_HEIGHT, hSpritesheetDC, BRANCHES_CORNER1_SPRITESHEET_X, BRANCHES_CORNER1_SPRITESHEET_Y, BRANCHES_CORNER_WIDTH, BRANCHES_CORNER_HEIGHT, 0x00FF00);
// upper right
corner_x = branch_x + current_corners_cursor_shift - BRANCHES_CORNER_HALFWIDTH;
corner_y = branch_y - current_corners_cursor_shift - BRANCHES_CORNER_HALFHEIGHT;
TransparentBlt(hBufferDC, corner_x, corner_y, BRANCHES_CORNER_WIDTH, BRANCHES_CORNER_HEIGHT, hSpritesheetDC, BRANCHES_CORNER2_SPRITESHEET_X, BRANCHES_CORNER2_SPRITESHEET_Y, BRANCHES_CORNER_WIDTH, BRANCHES_CORNER_HEIGHT, 0x00FF00);
// lower left
corner_x = branch_x - current_corners_cursor_shift - BRANCHES_CORNER_HALFWIDTH;
corner_y = branch_y + current_corners_cursor_shift - BRANCHES_CORNER_HALFHEIGHT;
TransparentBlt(hBufferDC, corner_x, corner_y, BRANCHES_CORNER_WIDTH, BRANCHES_CORNER_HEIGHT, hSpritesheetDC, BRANCHES_CORNER3_SPRITESHEET_X, BRANCHES_CORNER3_SPRITESHEET_Y, BRANCHES_CORNER_WIDTH, BRANCHES_CORNER_HEIGHT, 0x00FF00);
// lower right
corner_x = branch_x + current_corners_cursor_shift - BRANCHES_CORNER_HALFWIDTH;
corner_y = branch_y + current_corners_cursor_shift - BRANCHES_CORNER_HALFHEIGHT;
TransparentBlt(hBufferDC, corner_x, corner_y, BRANCHES_CORNER_WIDTH, BRANCHES_CORNER_HEIGHT, hSpritesheetDC, BRANCHES_CORNER4_SPRITESHEET_X, BRANCHES_CORNER4_SPRITESHEET_Y, BRANCHES_CORNER_WIDTH, BRANCHES_CORNER_HEIGHT, 0x00FF00);
// finish - paste buffer bitmap to screen
BitBlt(hdc, 0, 0, BRANCHES_BITMAP_WIDTH, BRANCHES_BITMAP_HEIGHT, hBufferDC, 0, 0, SRCCOPY);
}
void BOOKMARKS::MouseMove(int new_x, int new_y)
{
mouse_x = new_x;
mouse_y = new_y;
must_redraw_branches_tree = true;
}
// ----------------------------------------------------------------------------------------
void BOOKMARKS::GetDispInfo(NMLVDISPINFO* nmlvDispInfo)
{
LVITEM& item = nmlvDispInfo->item;
@ -267,7 +704,10 @@ void BOOKMARKS::GetDispInfo(NMLVDISPINFO* nmlvDispInfo)
{
case BOOKMARKS_COLUMN_ICON:
{
item.iImage = (item.iItem + 1) % TOTAL_BOOKMARKS;
if ((item.iItem + 1) % TOTAL_BOOKMARKS == current_branch)
item.iImage = ((item.iItem + 1) % TOTAL_BOOKMARKS) + TOTAL_BOOKMARKS;
else
item.iImage = (item.iItem + 1) % TOTAL_BOOKMARKS;
break;
}
case BOOKMARKS_COLUMN_FRAME:
@ -396,11 +836,280 @@ void BOOKMARKS::RightClick(LPNMITEMACTIVATE info)
int BOOKMARKS::FindBookmarkAtFrame(int frame)
{
if (current_branch >= 0 && bookmarks_array[current_branch].snapshot.jump_frame == frame) return current_branch + TOTAL_BOOKMARKS; // blue digit
for (int i = 0; i < TOTAL_BOOKMARKS; ++i)
{
if (bookmarks_array[i].snapshot.jump_frame == frame) return i;
if (bookmarks_array[i].snapshot.jump_frame == frame) return i; // green digit
}
return -1;
}
void BOOKMARKS::ChangesMadeSinceBranch()
{
bool prev_changes_since_current_branch = changes_since_current_branch;
changes_since_current_branch = true;
SetCurrentPosTime();
// recalculate branch tree if previous_changes = false
if (!prev_changes_since_current_branch)
must_recalculate_branches_tree = true;
else if (edit_mode == EDIT_MODE_BRANCHES && item_under_mouse == TOTAL_BOOKMARKS)
// redraw displayed time if it's currently shown
must_redraw_branches_tree = true;
}
void BOOKMARKS::SetCurrentPosTime()
{
time_t raw_time;
time(&raw_time);
struct tm * timeinfo = localtime(&raw_time);
strftime(current_pos_time, TIME_DESC_LENGTH, "%H:%M:%S", timeinfo);
}
void BOOKMARKS::RecalculateBranchesTree()
{
// save previous values
for (int i = TOTAL_BOOKMARKS; i >= 0; i--)
{
BranchPrevX[i] = (BranchX[i] * (BRANCHES_TRANSITION_MAX - transition_phase) + BranchPrevX[i] * transition_phase) / BRANCHES_TRANSITION_MAX;
BranchPrevY[i] = (BranchY[i] * (BRANCHES_TRANSITION_MAX - transition_phase) + BranchPrevY[i] * transition_phase) / BRANCHES_TRANSITION_MAX;
}
CloudPrevX = (CloudX * (BRANCHES_TRANSITION_MAX - transition_phase) + CloudPrevX * transition_phase) / BRANCHES_TRANSITION_MAX;
CursorPrevX = (CursorX * (BRANCHES_TRANSITION_MAX - transition_phase) + CursorPrevX * transition_phase) / BRANCHES_TRANSITION_MAX;
CursorPrevY = (CursorY * (BRANCHES_TRANSITION_MAX - transition_phase) + CursorPrevY * transition_phase) / BRANCHES_TRANSITION_MAX;
transition_phase = BRANCHES_TRANSITION_MAX;
// 0. Prepare arrays
GridX.resize(0);
GridY.resize(0);
Children.resize(0);
GridHeight.resize(0);
GridX.resize(TOTAL_BOOKMARKS+1);
GridY.resize(TOTAL_BOOKMARKS+1);
Children.resize(TOTAL_BOOKMARKS+2); // 0th subvector is for cloud's children
GridHeight.resize(TOTAL_BOOKMARKS+1);
for (int i = TOTAL_BOOKMARKS; i >= 0; i--)
GridHeight[i] = 1;
// 1. Define GridX of branches (distribute to levels) and GridHeight of branches
int current_grid_x = 0;
std::vector<std::vector<int>> BranchesLevels;
std::vector<uint8> UndistributedBranches;
UndistributedBranches.resize(TOTAL_BOOKMARKS);
for (int i = UndistributedBranches.size()-1; i >= 0; i--)
UndistributedBranches[i] = i;
// remove all empty branches
for (int i = UndistributedBranches.size()-1; i >= 0; i--)
{
if (!bookmarks_array[UndistributedBranches[i]].not_empty)
UndistributedBranches.erase(UndistributedBranches.begin() + i);
}
// highest level: cloud (id = -1)
BranchesLevels.resize(current_grid_x+1);
BranchesLevels[current_grid_x].resize(1);
BranchesLevels[current_grid_x][0] = -1;
// go lower until all branches are arranged to levels
int current_parent;
while(UndistributedBranches.size())
{
current_grid_x++;
BranchesLevels.resize(current_grid_x+1);
BranchesLevels[current_grid_x].resize(0);
for (int t = BranchesLevels[current_grid_x-1].size()-1; t >= 0; t--)
{
current_parent = BranchesLevels[current_grid_x-1][t];
for (int i = UndistributedBranches.size()-1; i >= 0; i--)
{
if (bookmarks_array[UndistributedBranches[i]].parent_branch == current_parent)
{
// assign this branch to current level
GridX[UndistributedBranches[i]] = current_grid_x;
BranchesLevels[current_grid_x].push_back(UndistributedBranches[i]);
// also add it to parent's Children array
Children[current_parent+1].push_back(UndistributedBranches[i]);
UndistributedBranches.erase(UndistributedBranches.begin() + i);
}
}
if (current_parent >= 0)
{
GridHeight[current_parent] = Children[current_parent+1].size();
if (Children[current_parent+1].size() > 1)
RecursiveAddHeight(bookmarks_array[current_parent].parent_branch, GridHeight[current_parent] - 1);
else
GridHeight[current_parent] = 1; // its own height
}
}
}
if (changes_since_current_branch)
{
// also define "current_pos" GridX
if (current_branch >= 0)
{
if (Children[current_branch+1].size() < MAX_NUM_CHILDREN)
{
// "current_pos" becomes a child of current_branch
GridX[TOTAL_BOOKMARKS] = GridX[current_branch] + 1;
if ((int)BranchesLevels.size() <= GridX[TOTAL_BOOKMARKS])
BranchesLevels.resize(GridX[TOTAL_BOOKMARKS] + 1);
BranchesLevels[GridX[TOTAL_BOOKMARKS]].push_back(TOTAL_BOOKMARKS); // ID of "current_pos" = number of bookmarks
Children[current_branch+1].push_back(TOTAL_BOOKMARKS);
if (Children[current_branch+1].size() > 1)
RecursiveAddHeight(current_branch, 1);
} else
{
// special case 0: if there's too many items on one level (more than canvas can show)
// "current_pos" becomes special branch above current_branch
GridX[TOTAL_BOOKMARKS] = GridX[current_branch];
GridY[TOTAL_BOOKMARKS] = GridY[current_branch] - 7;
}
} else
{
// special case 1: one and (presumably) only child of "cloud"
GridX[TOTAL_BOOKMARKS] = 1;
GridY[TOTAL_BOOKMARKS] = 0;
if ((int)BranchesLevels.size() <= GridX[TOTAL_BOOKMARKS])
BranchesLevels.resize(GridX[TOTAL_BOOKMARKS] + 1);
BranchesLevels[GridX[TOTAL_BOOKMARKS]].push_back(TOTAL_BOOKMARKS);
}
}
// define grid_width
int grid_width, cloud_prefix = 0;
if (BranchesLevels.size()-1 > 0)
{
grid_width = BRANCHES_CANVAS_WIDTH / (BranchesLevels.size()-1);
if (grid_width < BRANCHES_GRID_MIN_WIDTH)
grid_width = BRANCHES_GRID_MIN_WIDTH;
else if (grid_width > BRANCHES_GRID_MAX_WIDTH)
grid_width = BRANCHES_GRID_MAX_WIDTH;
} else grid_width = BRANCHES_GRID_MAX_WIDTH;
if (grid_width < MIN_CLOUD_LINE_LENGTH)
cloud_prefix = MIN_CLOUD_LINE_LENGTH - grid_width;
// 2. Define GridY of branches
RecursiveSetYPos(-1, 0);
// define grid_halfheight
int grid_halfheight;
int totalHeight = 0;
for (int i = Children[0].size()-1; i >= 0; i--)
totalHeight += GridHeight[Children[0][i]];
if (totalHeight)
{
grid_halfheight = BRANCHES_CANVAS_HEIGHT / (2 * totalHeight);
if (grid_halfheight < BRANCHES_GRID_MIN_HALFHEIGHT)
grid_halfheight = BRANCHES_GRID_MIN_HALFHEIGHT;
else if (grid_halfheight > BRANCHES_GRID_MAX_HALFHEIGHT)
grid_halfheight = BRANCHES_GRID_MAX_HALFHEIGHT;
} else grid_halfheight = BRANCHES_GRID_MAX_HALFHEIGHT;
// special case 2: if chain of branches is too long, last item (normally it's fireball) goes up
if (changes_since_current_branch)
{
if (GridX[TOTAL_BOOKMARKS] > MAX_CHAIN_LEN)
{
GridX[TOTAL_BOOKMARKS] = MAX_CHAIN_LEN;
GridY[TOTAL_BOOKMARKS] -= 2;
}
}
// special case 3: if some branch crosses upper or lower border
int parent;
for (int t = TOTAL_BOOKMARKS; t >= 0; t--)
{
if (GridY[t] > MAX_GRID_Y_POS)
{
if (t < TOTAL_BOOKMARKS)
parent = bookmarks_array[t].parent_branch;
else
parent = current_branch;
int pos = MAX_GRID_Y_POS;
for (int i = 0; i < (int)Children[parent+1].size(); ++i)
{
GridY[Children[parent+1][i]] = pos;
pos -= 2;
}
} else if (GridY[t] < -MAX_GRID_Y_POS)
{
if (t < TOTAL_BOOKMARKS)
parent = bookmarks_array[t].parent_branch;
else
parent = current_branch;
int pos = -MAX_GRID_Y_POS;
for (int i = Children[parent+1].size()-1; i >= 0; i--)
{
GridY[Children[parent+1][i]] = pos;
pos += 2;
}
}
}
// 3. Set pixel positions of branches
int max_x = 0;
for (int i = TOTAL_BOOKMARKS-1; i >= 0; i--)
{
if (bookmarks_array[i].not_empty)
{
BranchX[i] = cloud_prefix + GridX[i] * grid_width;
BranchY[i] = BRANCHES_CLOUD_Y + GridY[i] * grid_halfheight;
} else
{
BranchX[i] = EMPTY_BRANCHES_X;
BranchY[i] = EMPTY_BRANCHES_Y_BASE + EMPTY_BRANCHES_Y_FACTOR * ((i + TOTAL_BOOKMARKS - 1) % TOTAL_BOOKMARKS);
}
if (max_x < BranchX[i]) max_x = BranchX[i];
}
if (changes_since_current_branch)
{
// also set pixel position of "current_pos"
BranchX[TOTAL_BOOKMARKS] = cloud_prefix + GridX[TOTAL_BOOKMARKS] * grid_width;
BranchY[TOTAL_BOOKMARKS] = BRANCHES_CLOUD_Y + GridY[TOTAL_BOOKMARKS] * grid_halfheight;
} else if (current_branch >= 0)
{
BranchX[TOTAL_BOOKMARKS] = cloud_prefix + GridX[current_branch] * grid_width;
BranchY[TOTAL_BOOKMARKS] = BRANCHES_CLOUD_Y + GridY[current_branch] * grid_halfheight;
} else
{
BranchX[TOTAL_BOOKMARKS] = 0;
BranchY[TOTAL_BOOKMARKS] = BRANCHES_CLOUD_Y;
}
if (max_x < BranchX[TOTAL_BOOKMARKS]) max_x = BranchX[TOTAL_BOOKMARKS];
// align whole tree horizontally
CloudX = (BRANCHES_BITMAP_WIDTH + 1 - max_x) / 2;
if (CloudX < 0) CloudX = 0;
for (int i = TOTAL_BOOKMARKS-1; i >= 0; i--)
if (bookmarks_array[i].not_empty)
BranchX[i] += CloudX;
BranchX[TOTAL_BOOKMARKS] += CloudX;
// target cursor
CursorX = BranchX[TOTAL_BOOKMARKS];
CursorY = BranchY[TOTAL_BOOKMARKS];
// finished recalculating
must_recalculate_branches_tree = false;
must_redraw_branches_tree = true;
}
void BOOKMARKS::RecursiveAddHeight(int branch_num, int amount)
{
if (branch_num >= 0)
{
GridHeight[branch_num] += amount;
if (bookmarks_array[branch_num].parent_branch >= 0)
RecursiveAddHeight(bookmarks_array[branch_num].parent_branch, amount);
}
}
void BOOKMARKS::RecursiveSetYPos(int parent, int parentY)
{
if (Children[parent+1].size())
{
// find total height of children
int totalHeight = 0;
for (int i = Children[parent+1].size()-1; i >= 0; i--)
totalHeight += GridHeight[Children[parent+1][i]];
// set Y of children and subchildren
for (int i = Children[parent+1].size()-1; i >= 0; i--)
{
int child_id = Children[parent+1][i];
GridY[child_id] = parentY + GridHeight[child_id] - totalHeight;
RecursiveSetYPos(child_id, GridY[child_id]);
parentY += 2 * GridHeight[child_id];
}
}
}

View File

@ -4,20 +4,89 @@
#define TOTAL_BOOKMARKS 10
#define BOOKMARKS_FLASH_TICK 50 // in milliseconds
#define EDIT_MODE_BOOKMARKS 0
#define EDIT_MODE_BOTH 1
#define EDIT_MODE_BRANCHES 2
#define ITEM_UNDER_MOUSE_NONE -2
#define ITEM_UNDER_MOUSE_CLOUD -1
#define BOOKMARKS_FLASH_TICK 100 // in milliseconds
#define BRANCHES_ANIMATION_TICK 50 // animate at 20FPS
#define BRANCHES_TRANSITION_MAX 8
// branches bitmap
#define BRANCHES_BITMAP_WIDTH 170
#define BRANCHES_BITMAP_HEIGHT 145
#define BRANCHES_ANIMATION_FRAMES 12
// constants for drawing branches tree
#define BRANCHES_CANVAS_WIDTH 146
#define BRANCHES_CANVAS_HEIGHT 130
#define BRANCHES_CLOUD_X 14
#define BRANCHES_CLOUD_Y 72
#define BRANCHES_GRID_MIN_WIDTH 14
#define BRANCHES_GRID_MAX_WIDTH 30
#define MIN_CLOUD_LINE_LENGTH 19
#define BRANCHES_GRID_MIN_HALFHEIGHT 8
#define BRANCHES_GRID_MAX_HALFHEIGHT 12
#define EMPTY_BRANCHES_X -6
#define EMPTY_BRANCHES_Y_BASE 8
#define EMPTY_BRANCHES_Y_FACTOR 14
#define MAX_NUM_CHILDREN 9
#define MAX_CHAIN_LEN 10
#define MAX_GRID_Y_POS 8
// spritesheet
#define DIGIT_BITMAP_WIDTH 9
#define DIGIT_BITMAP_HALFWIDTH DIGIT_BITMAP_WIDTH/2
#define DIGIT_BITMAP_HEIGHT 13
#define DIGIT_BITMAP_HALFHEIGHT DIGIT_BITMAP_HEIGHT/2
#define BLUE_DIGITS_SPRITESHEET_DX DIGIT_BITMAP_WIDTH*TOTAL_BOOKMARKS
#define MOUSEOVER_DIGITS_SPRITESHEET_DY DIGIT_BITMAP_HEIGHT
#define DIGIT_RECT_WIDTH 11
#define DIGIT_RECT_HALFWIDTH DIGIT_RECT_WIDTH/2
#define DIGIT_RECT_HEIGHT 15
#define DIGIT_RECT_HALFHEIGHT DIGIT_RECT_HEIGHT/2
#define BRANCHES_CLOUD_WIDTH 26
#define BRANCHES_CLOUD_HALFWIDTH BRANCHES_CLOUD_WIDTH/2
#define BRANCHES_CLOUD_HEIGHT 15
#define BRANCHES_CLOUD_HALFHEIGHT BRANCHES_CLOUD_HEIGHT/2
#define BRANCHES_CLOUD_SPRITESHEET_X 180
#define BRANCHES_CLOUD_SPRITESHEET_Y 0
#define BRANCHES_FIREBALL_WIDTH 10
#define BRANCHES_FIREBALL_HALFWIDTH BRANCHES_FIREBALL_WIDTH/2
#define BRANCHES_FIREBALL_HEIGHT 10
#define BRANCHES_FIREBALL_HALFHEIGHT BRANCHES_FIREBALL_HEIGHT/2
#define BRANCHES_FIREBALL_SPRITESHEET_X 0
#define BRANCHES_FIREBALL_SPRITESHEET_Y 26
#define BRANCHES_FIREBALL_MAX_SIZE 5
#define BRANCHES_FIREBALL_SPRITESHEET_END_X 160
#define BRANCHES_CORNER_WIDTH 7
#define BRANCHES_CORNER_HALFWIDTH BRANCHES_CORNER_WIDTH/2
#define BRANCHES_CORNER_HEIGHT 7
#define BRANCHES_CORNER_HALFHEIGHT BRANCHES_CORNER_HEIGHT/2
#define BRANCHES_CORNER1_SPRITESHEET_X 206
#define BRANCHES_CORNER1_SPRITESHEET_Y 0
#define BRANCHES_CORNER2_SPRITESHEET_X 213
#define BRANCHES_CORNER2_SPRITESHEET_Y 0
#define BRANCHES_CORNER3_SPRITESHEET_X 206
#define BRANCHES_CORNER3_SPRITESHEET_Y 7
#define BRANCHES_CORNER4_SPRITESHEET_X 213
#define BRANCHES_CORNER4_SPRITESHEET_Y 7
#define BRANCHES_CORNER_BASE_SHIFT 6
// listview columns
#define BOOKMARKS_COLUMN_ICON 0
#define BOOKMARKS_COLUMN_FRAME 1
#define BOOKMARKS_COLUMN_TIME 2
#define BOOKMARKS_ID_LEN 10
#define TIME_DESC_LENGTH 9 // "HH:MM:SS"
class BOOKMARKS
{
public:
BOOKMARKS();
void init();
void reset();
void free();
void update();
@ -40,10 +109,66 @@ public:
void RedrawChangedBookmarks(int frame);
void RedrawBookmarksRow(int index);
void RedrawBranchesTree();
void PaintBranchesBitmap(HDC hdc);
void MouseMove(int new_x, int new_y);
void ChangesMadeSinceBranch();
void RecalculateBranchesTree();
void RecursiveAddHeight(int branch_num, int amount);
void RecursiveSetYPos(int parent, int parentY);
std::vector<BOOKMARK> bookmarks_array;
// not saved vars
bool mouse_over_bitmap;
TRACKMOUSEEVENT tme;
private:
HFONT hBookmarksFont;
void SetCurrentPosTime();
// also saved vars
int current_branch;
bool changes_since_current_branch;
char cloud_time[TIME_DESC_LENGTH];
char current_pos_time[TIME_DESC_LENGTH];
// not saved vars
int check_flash_shedule;
int edit_mode;
int animation_frame; // 0-13
int next_animation_time;
bool must_redraw_branches_tree;
bool must_recalculate_branches_tree;
std::vector<int> BranchX; // in pixels
std::vector<int> BranchY;
std::vector<int> BranchPrevX;
std::vector<int> BranchPrevY;
std::vector<int> BranchCurrX;
std::vector<int> BranchCurrY;
int CloudX, CloudPrevX;
int CursorX, CursorPrevX, CursorY, CursorPrevY;
int transition_phase;
int fireball_size;
int mouse_x, mouse_y;
int item_under_mouse;
// GDI stuff
HFONT hBookmarksFont;
HBRUSH normal_brush;
RECT temp_rect;
HPEN normal_pen, select_pen;
HBITMAP branches_hbitmap, hOldBitmap, buffer_hbitmap, hOldBitmap1, branchesSpritesheet, hOldBitmap2;
HDC hBitmapDC, hBufferDC, hSpritesheetDC;
// temps
std::vector<int> GridX; // in grid units
std::vector<int> GridY;
std::vector<int> GridHeight;
std::vector<std::vector<uint8>> Children;
};

View File

@ -35,9 +35,13 @@ void GREENZONE::reset()
}
void GREENZONE::update()
{
if ((int)savestates.size() < greenZoneCount)
savestates.resize(greenZoneCount);
if ((int)lag_history.size() < greenZoneCount)
lag_history.resize(greenZoneCount);
if (clock() > next_cleaning_time)
GreenzoneCleaning();
}
void GREENZONE::TryDumpIncremental(bool lagFlag)
@ -151,7 +155,7 @@ void GREENZONE::GreenzoneCleaning()
}
}
finish:
if (changed) RedrawList();
if (changed) RedrawListAndBookmarks();
// shedule next cleaning
next_cleaning_time = clock() + TIME_BETWEEN_CLEANINGS;
}
@ -334,7 +338,7 @@ void GREENZONE::InvalidateAndCheck(int after)
}
}
// redraw list even if greenzone didn't change
RedrawList();
RedrawListAndBookmarks();
}
// This version doesn't restore playback, may be used only by Branching functions!
void GREENZONE::Invalidate(int after)
@ -349,7 +353,7 @@ void GREENZONE::Invalidate(int after)
}
}
// redraw list even if greenzone didn't change
RedrawList();
RedrawListAndBookmarks();
}
int GREENZONE::FindBeginningOfGreenZone(int starting_index)

View File

@ -10,10 +10,11 @@ extern void FCEU_printf(char *format, ...);
extern HWND hwndHistoryList;
extern bool TASEdit_bind_markers;
extern MARKERS markers;
extern BOOKMARKS bookmarks;
extern PLAYBACK playback;
extern GREENZONE greenzone;
extern TASEDIT_PROJECT project;
extern MARKERS markers;
char history_save_id[HISTORY_ID_LEN] = "HISTORY";
char modCaptions[36][20] = {" Init",
@ -89,7 +90,8 @@ void INPUT_HISTORY::free()
void INPUT_HISTORY::update()
{
// update undo_hint
if (old_undo_hint_pos != undo_hint_pos && old_undo_hint_pos >= 0) RedrawRow(old_undo_hint_pos);
if (old_undo_hint_pos != undo_hint_pos && old_undo_hint_pos >= 0)
RedrawRow(old_undo_hint_pos); // not changing bookmarks list
old_undo_hint_pos = undo_hint_pos;
old_show_undo_hint = show_undo_hint;
show_undo_hint = false;
@ -100,7 +102,8 @@ void INPUT_HISTORY::update()
else
undo_hint_pos = -1; // finished hinting
}
if (old_show_undo_hint != show_undo_hint) RedrawRow(undo_hint_pos);
if (old_show_undo_hint != show_undo_hint)
RedrawRow(undo_hint_pos); // not changing bookmarks list
@ -145,9 +148,11 @@ 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();
} else if (markers_changed)
{
markers.update();
bookmarks.ChangesMadeSinceBranch();
RedrawList();
}
@ -231,6 +236,7 @@ int INPUT_HISTORY::RegisterChanges(int mod_type, int start, int end)
strcat(inp.description, framenum);
}
AddInputSnapshotToHistory(inp);
bookmarks.ChangesMadeSinceBranch();
return -1;
} else
{
@ -294,6 +300,7 @@ int INPUT_HISTORY::RegisterChanges(int mod_type, int start, int end)
strcat(inp.description, framenum);
}
AddInputSnapshotToHistory(inp);
bookmarks.ChangesMadeSinceBranch();
}
return first_changes;
}

View File

@ -47,14 +47,14 @@ void MARKERS::save(EMUFILE *os)
// returns true if couldn't load
bool MARKERS::load(EMUFILE *is)
{
markers_array.resize(currMovieData.getNumRecords());
// read "MARKERS" string
char save_id[MARKERS_ID_LEN];
if ((int)is->fread(save_id, MARKERS_ID_LEN) < MARKERS_ID_LEN) goto error;
if (strcmp(markers_save_id, save_id)) goto error; // string is not valid
int size;
if (read32le((uint32 *)&size, is) && size == currMovieData.getNumRecords())
if (read32le((uint32 *)&size, is) && size >= currMovieData.getNumRecords())
{
markers_array.resize(size);
// read and uncompress array
int comprlen;
uLongf destlen = size;
@ -89,3 +89,10 @@ void MARKERS::insertEmpty(int at, int frames)
}
}
void MARKERS::truncateAt(int frame)
{
markers_array.resize(frame);
}

View File

@ -17,6 +17,7 @@ public:
void ToggleMarker(int frame);
void insertEmpty(int at, int frames);
void truncateAt(int frame);
std::vector<uint8> markers_array;

View File

@ -46,7 +46,7 @@ void PLAYBACK::update()
SeekingStop();
// update flashing pauseframe
if (old_pauseframe != pauseframe && old_pauseframe) RedrawRow(old_pauseframe-1);
if (old_pauseframe != pauseframe && old_pauseframe) RedrawRowAndBookmark(old_pauseframe-1);
old_pauseframe = pauseframe;
old_show_pauseframe = show_pauseframe;
if (pauseframe)
@ -56,7 +56,7 @@ void PLAYBACK::update()
else
show_pauseframe = (int)(clock() / PAUSEFRAME_BLINKING_PERIOD_SEEKING) & 1;
} else show_pauseframe = false;
if (old_show_pauseframe != show_pauseframe) RedrawRow(pauseframe-1);
if (old_show_pauseframe != show_pauseframe) RedrawRowAndBookmark(pauseframe-1);
// update seeking progressbar
old_emu_paused = emu_paused;
@ -81,8 +81,8 @@ void PLAYBACK::update()
{
FollowPlayback();
//update the old and new rows
RedrawRow(lastCursor);
RedrawRow(currFrameCounter);
RedrawRowAndBookmark(lastCursor);
RedrawRowAndBookmark(currFrameCounter);
UpdateWindow(hwndList);
lastCursor = currFrameCounter;
}

View File

@ -843,10 +843,22 @@
</ItemGroup>
<ItemGroup>
<None Include="..\src\drivers\win\res\bitmap1.bmp" />
<None Include="..\src\drivers\win\res\branch_spritesheet.bmp" />
<None Include="..\src\drivers\win\res\branch_spritesheet.png" />
<None Include="..\src\drivers\win\res\ICON_1.ico" />
<None Include="..\src\drivers\win\res\ICON_2.ico" />
<None Include="..\src\drivers\win\res\te_0.bmp" />
<None Include="..\src\drivers\win\res\te_1.bmp" />
<None Include="..\src\drivers\win\res\te_10.bmp" />
<None Include="..\src\drivers\win\res\te_11.bmp" />
<None Include="..\src\drivers\win\res\te_12.bmp" />
<None Include="..\src\drivers\win\res\te_13.bmp" />
<None Include="..\src\drivers\win\res\te_14.bmp" />
<None Include="..\src\drivers\win\res\te_15.bmp" />
<None Include="..\src\drivers\win\res\te_16.bmp" />
<None Include="..\src\drivers\win\res\te_17.bmp" />
<None Include="..\src\drivers\win\res\te_18.bmp" />
<None Include="..\src\drivers\win\res\te_19.bmp" />
<None Include="..\src\drivers\win\res\te_2.bmp" />
<None Include="..\src\drivers\win\res\te_3.bmp" />
<None Include="..\src\drivers\win\res\te_4.bmp" />
@ -872,8 +884,20 @@
</CustomBuild>
<None Include="..\src\pputile.inc" />
<None Include="ClassDiagram1.cd" />
<None Include="res\branch_spritesheet.bmp" />
<None Include="res\branch_spritesheet.png" />
<None Include="res\te_0.bmp" />
<None Include="res\te_1.bmp" />
<None Include="res\te_10.bmp" />
<None Include="res\te_11.bmp" />
<None Include="res\te_12.bmp" />
<None Include="res\te_13.bmp" />
<None Include="res\te_14.bmp" />
<None Include="res\te_15.bmp" />
<None Include="res\te_16.bmp" />
<None Include="res\te_17.bmp" />
<None Include="res\te_18.bmp" />
<None Include="res\te_19.bmp" />
<None Include="res\te_2.bmp" />
<None Include="res\te_3.bmp" />
<None Include="res\te_4.bmp" />

View File

@ -1414,6 +1414,30 @@
<None Include="..\src\drivers\win\res\te_7.bmp" />
<None Include="..\src\drivers\win\res\te_8.bmp" />
<None Include="..\src\drivers\win\res\te_9.bmp" />
<None Include="res\te_10.bmp" />
<None Include="res\te_11.bmp" />
<None Include="res\te_12.bmp" />
<None Include="res\te_13.bmp" />
<None Include="res\te_14.bmp" />
<None Include="res\te_15.bmp" />
<None Include="res\te_16.bmp" />
<None Include="res\te_17.bmp" />
<None Include="res\te_18.bmp" />
<None Include="res\te_19.bmp" />
<None Include="..\src\drivers\win\res\te_10.bmp" />
<None Include="..\src\drivers\win\res\te_11.bmp" />
<None Include="..\src\drivers\win\res\te_12.bmp" />
<None Include="..\src\drivers\win\res\te_13.bmp" />
<None Include="..\src\drivers\win\res\te_14.bmp" />
<None Include="..\src\drivers\win\res\te_15.bmp" />
<None Include="..\src\drivers\win\res\te_16.bmp" />
<None Include="..\src\drivers\win\res\te_17.bmp" />
<None Include="..\src\drivers\win\res\te_18.bmp" />
<None Include="..\src\drivers\win\res\te_19.bmp" />
<None Include="res\branch_spritesheet.png" />
<None Include="..\src\drivers\win\res\branch_spritesheet.png" />
<None Include="res\branch_spritesheet.bmp" />
<None Include="..\src\drivers\win\res\branch_spritesheet.bmp" />
</ItemGroup>
<ItemGroup>
<CustomBuild Include="..\src\auxlib.lua" />