tasedit multi-edit (select rows and then click the column header)
This commit is contained in:
parent
bdf11aafa5
commit
2b142ddd71
|
@ -1269,9 +1269,10 @@ STYLE DS_SETFONT | DS_MODALFRAME | DS_FIXEDSYS | WS_POPUP | WS_VISIBLE | WS_CAPT
|
|||
CAPTION "TAS Editor"
|
||||
FONT 8, "MS Shell Dlg", 400, 0, 0x1
|
||||
BEGIN
|
||||
CONTROL "",IDC_LIST1,"SysListView32",LVS_REPORT | LVS_SINGLESEL | LVS_SHOWSELALWAYS | LVS_ALIGNLEFT | LVS_OWNERDATA | LVS_NOSORTHEADER | WS_BORDER | WS_TABSTOP,7,7,273,296
|
||||
PUSHBUTTON "Hacky add 1000 frames",IDC_HACKY2,318,73,124,38
|
||||
CONTROL "",IDC_LIST1,"SysListView32",LVS_REPORT | LVS_SHOWSELALWAYS | LVS_ALIGNLEFT | LVS_OWNERDATA | LVS_NOSORTHEADER | WS_BORDER | WS_TABSTOP,7,7,273,296
|
||||
PUSHBUTTON "Hacky export as fm2",IDC_HACKYEXPORT,315,122,124,38
|
||||
PUSHBUTTON "Hacky truncate after current frame",IDC_HACKY1,313,31,124,38
|
||||
PUSHBUTTON "Hacky add 1000 frames",IDC_HACKY2,327,82,124,38
|
||||
END
|
||||
|
||||
|
||||
|
|
|
@ -244,6 +244,7 @@
|
|||
#define IDC_LIST1 1130
|
||||
#define IDC_HACKY2 1131
|
||||
#define IDC_HACKY1 1132
|
||||
#define IDC_HACKYEXPORT 1133
|
||||
#define MENU_NETWORK 40040
|
||||
#define MENU_PALETTE 40041
|
||||
#define MENU_SOUND 40042
|
||||
|
|
|
@ -1,3 +1,5 @@
|
|||
#include <set>
|
||||
|
||||
#include "common.h"
|
||||
#include "tasedit.h"
|
||||
#include "../../fceu.h"
|
||||
|
@ -10,7 +12,11 @@
|
|||
|
||||
HWND hwndTasEdit = 0;
|
||||
static int lastCursor;
|
||||
static HWND hwndList;
|
||||
static HWND hwndList, hwndHeader;
|
||||
static WNDPROC hwndHeader_oldWndproc;
|
||||
|
||||
typedef std::set<int> TSelectionFrames;
|
||||
static TSelectionFrames selectionFrames;
|
||||
|
||||
//hacky.. we need to think about how to convey information from the driver to the movie code.
|
||||
//add a new fceud_ function?? blehhh maybe
|
||||
|
@ -96,12 +102,13 @@ void UpdateTasEdit()
|
|||
//scroll to the row
|
||||
ListView_EnsureVisible(hwndList,newCursor,FALSE);
|
||||
//select the row
|
||||
ListView_SetItemState(hwndList,lastCursor,0, LVIS_FOCUSED|LVIS_SELECTED);
|
||||
ListView_SetItemState(hwndList,newCursor,LVIS_FOCUSED|LVIS_SELECTED,LVIS_FOCUSED|LVIS_SELECTED);
|
||||
|
||||
//update the old and new rows
|
||||
ListView_Update(hwndList,lastCursor);
|
||||
ListView_Update(hwndList,newCursor);
|
||||
|
||||
|
||||
lastCursor = newCursor;
|
||||
}
|
||||
}
|
||||
|
@ -145,19 +152,86 @@ void DoubleClick(LPNMITEMACTIVATE info)
|
|||
}
|
||||
}
|
||||
|
||||
void InitDialog()
|
||||
|
||||
//the column set operation, for setting a button for a span of selected values
|
||||
static void ColumnSet(int column)
|
||||
{
|
||||
int button = column-2;
|
||||
|
||||
//inspect the selected frames. count the set and unset rows
|
||||
int set=0, unset=0;
|
||||
for(TSelectionFrames::iterator it(selectionFrames.begin()); it != selectionFrames.end(); it++)
|
||||
{
|
||||
if(currMovieData.records[*it].checkBit(0,button))
|
||||
set++;
|
||||
else unset++;
|
||||
}
|
||||
|
||||
//if it is half and half, then set them all
|
||||
//if they are all set, unset them all
|
||||
//if they are all unset, set them all
|
||||
bool setz = (set==0);
|
||||
bool unsetz = (unset==0);
|
||||
bool newValue;
|
||||
|
||||
//do nothing if we didnt even have any work to do
|
||||
if(setz && unsetz)
|
||||
return;
|
||||
//all unset.. set them
|
||||
else if(setz && !unsetz)
|
||||
newValue = true;
|
||||
//all set.. unset them
|
||||
else if(!setz && unsetz)
|
||||
newValue = false;
|
||||
//a mix. set them.
|
||||
else newValue = true;
|
||||
|
||||
//operate on the data and update the listview
|
||||
for(TSelectionFrames::iterator it(selectionFrames.begin()); it != selectionFrames.end(); it++)
|
||||
{
|
||||
currMovieData.records[*it].setBitValue(0,button,newValue);
|
||||
ListView_Update(hwndList,*it);
|
||||
}
|
||||
}
|
||||
|
||||
//The subclass wndproc for the listview header
|
||||
static LRESULT APIENTRY HeaderWndProc(HWND hWnd,UINT msg,WPARAM wParam,LPARAM lParam)
|
||||
{
|
||||
switch(msg)
|
||||
{
|
||||
case WM_LBUTTONDOWN:
|
||||
{
|
||||
//perform hit test
|
||||
HDHITTESTINFO info;
|
||||
info.pt.x = GET_X_LPARAM(lParam);
|
||||
info.pt.y = GET_Y_LPARAM(lParam);
|
||||
SendMessage(hWnd,HDM_HITTEST,0,(LPARAM)&info);
|
||||
if(info.iItem != -1)
|
||||
ColumnSet(info.iItem);
|
||||
}
|
||||
}
|
||||
return CallWindowProc(hwndHeader_oldWndproc,hWnd,msg,wParam,lParam);
|
||||
}
|
||||
|
||||
//All dialog initialization
|
||||
static void InitDialog()
|
||||
{
|
||||
//prepare the listview
|
||||
ListView_SetExtendedListViewStyleEx(hwndList,
|
||||
LVS_EX_FULLROWSELECT | LVS_EX_GRIDLINES ,
|
||||
LVS_EX_FULLROWSELECT | LVS_EX_GRIDLINES );
|
||||
|
||||
//subclass the header
|
||||
hwndHeader = ListView_GetHeader(hwndList);
|
||||
hwndHeader_oldWndproc = (WNDPROC)SetWindowLong(hwndHeader,GWL_WNDPROC,(LONG)HeaderWndProc);
|
||||
|
||||
|
||||
//setup all images for the listview
|
||||
HIMAGELIST himglist = ImageList_Create(12,12,ILC_COLOR32 | ILC_MASK,1,1);
|
||||
HBITMAP bmp = LoadBitmap(fceu_hInstance,MAKEINTRESOURCE(IDB_TE_ARROW));
|
||||
ImageList_AddMasked(himglist, bmp, RGB(255,0,255));
|
||||
DeleteObject(bmp);
|
||||
ListView_SetImageList(hwndList,himglist,LVSIL_SMALL);
|
||||
|
||||
//doesnt work well??
|
||||
//HIMAGELIST himglist = ImageList_LoadImage(fceu_hInstance,MAKEINTRESOURCE(IDB_TE_ARROW),12,1,RGB(255,0,255),IMAGE_BITMAP,LR_DEFAULTCOLOR);
|
||||
|
||||
|
@ -202,6 +276,70 @@ void KillTasEdit()
|
|||
moviePleaseLogSavestates = false;
|
||||
}
|
||||
|
||||
static void Export()
|
||||
{
|
||||
const char filter[]="FCEUX Movie File(*.fm2)\0*.fm2\0";
|
||||
char fname[2048] = {0};
|
||||
OPENFILENAME ofn;
|
||||
memset(&ofn,0,sizeof(ofn));
|
||||
ofn.lStructSize=sizeof(ofn);
|
||||
ofn.hInstance=fceu_hInstance;
|
||||
ofn.lpstrTitle="Export TAS as...";
|
||||
ofn.lpstrFilter=filter;
|
||||
ofn.lpstrFile=fname;
|
||||
ofn.nMaxFile=256;
|
||||
ofn.lpstrInitialDir=FCEU_GetPath(FCEUMKF_MOVIE);
|
||||
if(GetSaveFileName(&ofn))
|
||||
{
|
||||
}
|
||||
}
|
||||
|
||||
//likewise, handles a changed item range from the listview
|
||||
static void ItemRangeChanged(NMLVODSTATECHANGE* info)
|
||||
{
|
||||
bool ON = !(info->uOldState & LVIS_SELECTED) && (info->uNewState & LVIS_SELECTED);
|
||||
bool OFF = (info->uOldState & LVIS_SELECTED) && !(info->uNewState & LVIS_SELECTED);
|
||||
|
||||
if(ON)
|
||||
for(int i=info->iFrom;i<=info->iTo;i++)
|
||||
selectionFrames.insert(i);
|
||||
else
|
||||
for(int i=info->iFrom;i<=info->iTo;i++)
|
||||
selectionFrames.erase(i);
|
||||
}
|
||||
|
||||
//handles a changed item from the listview
|
||||
//used to track selection
|
||||
static void ItemChanged(NMLISTVIEW* info)
|
||||
{
|
||||
int item = info->iItem;
|
||||
|
||||
bool ON = !(info->uOldState & LVIS_SELECTED) && (info->uNewState & LVIS_SELECTED);
|
||||
bool OFF = (info->uOldState & LVIS_SELECTED) && !(info->uNewState & LVIS_SELECTED);
|
||||
|
||||
//if the item is -1, apply the change to all items
|
||||
if(item == -1)
|
||||
{
|
||||
if(OFF)
|
||||
{
|
||||
selectionFrames.clear();
|
||||
}
|
||||
else
|
||||
FCEUD_PrintError("Unexpected condition in TasEdit ItemChanged. Please report.");
|
||||
}
|
||||
else
|
||||
{
|
||||
if(ON) {
|
||||
printf("%d ON\n",item);
|
||||
selectionFrames.insert(item);
|
||||
}
|
||||
else if(OFF)
|
||||
{
|
||||
printf("%d OFF\n",item);
|
||||
selectionFrames.erase(item);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
BOOL CALLBACK WndprocTasEdit(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam)
|
||||
{
|
||||
|
@ -213,6 +351,7 @@ BOOL CALLBACK WndprocTasEdit(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lPar
|
|||
break;
|
||||
|
||||
case WM_NOTIFY:
|
||||
|
||||
switch(wParam)
|
||||
{
|
||||
case IDC_LIST1:
|
||||
|
@ -224,11 +363,15 @@ BOOL CALLBACK WndprocTasEdit(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lPar
|
|||
case LVN_GETDISPINFO:
|
||||
GetDispInfo((NMLVDISPINFO*)lParam);
|
||||
break;
|
||||
case NM_CLICK:
|
||||
break;
|
||||
case NM_DBLCLK:
|
||||
DoubleClick((LPNMITEMACTIVATE)lParam);
|
||||
break;
|
||||
case LVN_ITEMCHANGED:
|
||||
ItemChanged((LPNMLISTVIEW) lParam);
|
||||
break;
|
||||
case LVN_ODSTATECHANGED:
|
||||
ItemRangeChanged((LPNMLVODSTATECHANGE) lParam);
|
||||
break;
|
||||
|
||||
}
|
||||
break;
|
||||
|
@ -254,6 +397,11 @@ BOOL CALLBACK WndprocTasEdit(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lPar
|
|||
currMovieData.clearRecordRange(currMovieData.records.size()-1000,1000);
|
||||
UpdateTasEdit();
|
||||
break;
|
||||
|
||||
case IDC_HACKYEXPORT:
|
||||
//hackyexport: save an fm2
|
||||
Export();
|
||||
break;
|
||||
|
||||
case ACCEL_CTRL_W:
|
||||
KillTasEdit();
|
||||
|
|
28
src/movie.h
28
src/movie.h
|
@ -26,8 +26,28 @@ public:
|
|||
|
||||
void toggleBit(int joy, int bit)
|
||||
{
|
||||
int mask = (1<<bit);
|
||||
joysticks[joy] ^= mask;
|
||||
joysticks[joy] ^= mask(bit);
|
||||
}
|
||||
|
||||
void setBit(int joy, int bit)
|
||||
{
|
||||
joysticks[joy] |= mask(bit);
|
||||
}
|
||||
|
||||
void clearBit(int joy, int bit)
|
||||
{
|
||||
joysticks[joy] &= ~mask(bit);
|
||||
}
|
||||
|
||||
void setBitValue(int joy, int bit, bool val)
|
||||
{
|
||||
if(val) setBit(joy,bit);
|
||||
else clearBit(joy,bit);
|
||||
}
|
||||
|
||||
bool checkBit(int joy, int bit)
|
||||
{
|
||||
return (joysticks[joy] & mask(bit))!=0;
|
||||
}
|
||||
|
||||
void clear() {
|
||||
|
@ -40,6 +60,9 @@ public:
|
|||
void dump(FILE* fp, int index);
|
||||
|
||||
static const char mnemonics[8];
|
||||
|
||||
private:
|
||||
int mask(int bit) { return 1<<bit; }
|
||||
};
|
||||
|
||||
class MovieData
|
||||
|
@ -58,6 +81,7 @@ public:
|
|||
std::string romFilename;
|
||||
std::vector<uint8> savestate;
|
||||
std::vector<MovieRecord> records;
|
||||
//this is the RERECORD COUNT. please rename variable.
|
||||
int recordCount;
|
||||
FCEU_Guid guid;
|
||||
|
||||
|
|
Loading…
Reference in New Issue