Taseditor: some refactoring

This commit is contained in:
ansstuff 2012-05-13 17:14:10 +00:00
parent 53a005d38b
commit 5123d08a40
21 changed files with 241 additions and 246 deletions

View File

@ -71,7 +71,7 @@ void BOOKMARK::set()
if (taseditor_config.enable_hot_changes) if (taseditor_config.enable_hot_changes)
snapshot.copyHotChanges(&history.GetCurrentSnapshot()); snapshot.copyHotChanges(&history.GetCurrentSnapshot());
// copy savestate // copy savestate
savestate = greenzone.savestates[currFrameCounter]; savestate = greenzone.GetSavestate(currFrameCounter);
// save screenshot // save screenshot
uLongf comprlen = (SCREENSHOT_SIZE>>9)+12 + SCREENSHOT_SIZE; uLongf comprlen = (SCREENSHOT_SIZE>>9)+12 + SCREENSHOT_SIZE;
saved_screenshot.resize(comprlen); saved_screenshot.resize(comprlen);

View File

@ -289,7 +289,7 @@ void BOOKMARKS::deploy(int slot)
int jump_frame = bookmarks_array[slot].snapshot.jump_frame; int jump_frame = bookmarks_array[slot].snapshot.jump_frame;
bool markers_changed = false; bool markers_changed = false;
// update Markers // revert Markers to the Bookmarked state
if (taseditor_config.bind_markers) if (taseditor_config.bind_markers)
{ {
if (bookmarks_array[slot].snapshot.MarkersDifferFromCurrent()) if (bookmarks_array[slot].snapshot.MarkersDifferFromCurrent())
@ -326,24 +326,12 @@ void BOOKMARKS::deploy(int slot)
bookmarks_array[slot].deployed(); bookmarks_array[slot].deployed();
} else } else
{ {
// didn't restore anything // didn't change anything in current movie
bookmarks_array[slot].jumped(); bookmarks_array[slot].jumped();
} }
// jump to the target (bookmarked frame)
// if greenzone reduced so much that we can't jump immediately - substitute target frame greenzone with our savestate greenzone.WriteSavestate(jump_frame, bookmarks_array[slot].savestate);
if (greenzone.greenZoneCount <= jump_frame) playback.jump(jump_frame);
{
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);
greenzone.greenZoneCount = jump_frame+1;
}
if (greenzone.savestates[jump_frame].empty())
// restore savestate for immediate jump
greenzone.savestates[jump_frame] = bookmarks_array[slot].savestate;
// switch current branch to this branch // switch current branch to this branch
int old_current_branch = branches.GetCurrentBranch(); int old_current_branch = branches.GetCurrentBranch();
branches.HandleBookmarkDeploy(slot); branches.HandleBookmarkDeploy(slot);
@ -351,12 +339,9 @@ void BOOKMARKS::deploy(int slot)
{ {
piano_roll.RedrawRow(bookmarks_array[old_current_branch].snapshot.jump_frame); piano_roll.RedrawRow(bookmarks_array[old_current_branch].snapshot.jump_frame);
RedrawChangedBookmarks(bookmarks_array[old_current_branch].snapshot.jump_frame); RedrawChangedBookmarks(bookmarks_array[old_current_branch].snapshot.jump_frame);
piano_roll.RedrawRow(bookmarks_array[slot].snapshot.jump_frame); piano_roll.RedrawRow(jump_frame);
RedrawChangedBookmarks(bookmarks_array[slot].snapshot.jump_frame); RedrawChangedBookmarks(jump_frame);
} }
// jump to the target (bookmarked frame)
playback.jump(jump_frame);
FCEU_DispMessage("Branch %d loaded.", 0, slot); FCEU_DispMessage("Branch %d loaded.", 0, slot);
} }
@ -480,14 +465,6 @@ int BOOKMARKS::FindItemUnderMouse()
} }
return item; return item;
} }
// this getter contains formula to decide whether it's safe to show Bookmarks Data now
bool BOOKMARKS::IsSafeToShowBookmarksData()
{
if (edit_mode == EDIT_MODE_BRANCHES && branches.transition_phase)
return false; // can't show data when Branches Tree is transforming
return true;
}
// ---------------------------------------------------------------------------------------- // ----------------------------------------------------------------------------------------
void BOOKMARKS::GetDispInfo(NMLVDISPINFO* nmlvDispInfo) void BOOKMARKS::GetDispInfo(NMLVDISPINFO* nmlvDispInfo)
{ {
@ -548,18 +525,18 @@ LONG BOOKMARKS::CustomDraw(NMLVCUSTOMDRAW* msg)
{ {
// current frame // current frame
msg->clrTextBk = CUR_FRAMENUM_COLOR; msg->clrTextBk = CUR_FRAMENUM_COLOR;
} else if (frame < greenzone.greenZoneCount) } else if (frame < greenzone.GetSize())
{ {
if (!greenzone.savestates[frame].empty()) if (!greenzone.SavestateIsEmpty(frame))
{ {
if (greenzone.GetLagHistoryAtFrame(frame)) if (greenzone.GetLagHistoryAtFrame(frame))
msg->clrTextBk = LAG_FRAMENUM_COLOR; msg->clrTextBk = LAG_FRAMENUM_COLOR;
else else
msg->clrTextBk = GREENZONE_FRAMENUM_COLOR; msg->clrTextBk = GREENZONE_FRAMENUM_COLOR;
} else if ((!greenzone.savestates[frame & EVERY16TH].empty() && (int)greenzone.savestates.size() > (frame | 0xF) + 1 && !greenzone.savestates[(frame | 0xF) + 1].empty()) } else if ((!greenzone.SavestateIsEmpty(frame & EVERY16TH) && !greenzone.SavestateIsEmpty((frame & EVERY16TH) + 16))
|| (!greenzone.savestates[frame & EVERY8TH].empty() && (int)greenzone.savestates.size() > (frame | 0x7) + 1 && !greenzone.savestates[(frame | 0x7) + 1].empty()) || (!greenzone.SavestateIsEmpty(frame & EVERY8TH) && !greenzone.SavestateIsEmpty((frame & EVERY8TH) + 8))
|| (!greenzone.savestates[frame & EVERY4TH].empty() && (int)greenzone.savestates.size() > (frame | 0x3) + 1 && !greenzone.savestates[(frame | 0x3) + 1].empty()) || (!greenzone.SavestateIsEmpty(frame & EVERY4TH) && !greenzone.SavestateIsEmpty((frame & EVERY4TH) + 4))
|| (!greenzone.savestates[frame & EVERY2ND].empty() && !greenzone.savestates[(frame | 0x1) + 1].empty())) || (!greenzone.SavestateIsEmpty(frame & EVERY2ND) && !greenzone.SavestateIsEmpty((frame & EVERY2ND) + 2)))
{ {
if (greenzone.GetLagHistoryAtFrame(frame)) if (greenzone.GetLagHistoryAtFrame(frame))
msg->clrTextBk = PALE_LAG_FRAMENUM_COLOR; msg->clrTextBk = PALE_LAG_FRAMENUM_COLOR;
@ -579,18 +556,18 @@ LONG BOOKMARKS::CustomDraw(NMLVCUSTOMDRAW* msg)
{ {
// current frame // current frame
msg->clrTextBk = CUR_INPUT_COLOR1; msg->clrTextBk = CUR_INPUT_COLOR1;
} else if (frame < greenzone.greenZoneCount) } else if (frame < greenzone.GetSize())
{ {
if (!greenzone.savestates[frame].empty()) if (!greenzone.SavestateIsEmpty(frame))
{ {
if (greenzone.GetLagHistoryAtFrame(frame)) if (greenzone.GetLagHistoryAtFrame(frame))
msg->clrTextBk = LAG_INPUT_COLOR1; msg->clrTextBk = LAG_INPUT_COLOR1;
else else
msg->clrTextBk = GREENZONE_INPUT_COLOR1; msg->clrTextBk = GREENZONE_INPUT_COLOR1;
} else if ((!greenzone.savestates[frame & EVERY16TH].empty() && (int)greenzone.savestates.size() > (frame | 0xF) + 1 && !greenzone.savestates[(frame | 0xF) + 1].empty()) } else if ((!greenzone.SavestateIsEmpty(frame & EVERY16TH) && !greenzone.SavestateIsEmpty((frame & EVERY16TH) + 16))
|| (!greenzone.savestates[frame & EVERY8TH].empty() && (int)greenzone.savestates.size() > (frame | 0x7) + 1 && !greenzone.savestates[(frame | 0x7) + 1].empty()) || (!greenzone.SavestateIsEmpty(frame & EVERY8TH) && !greenzone.SavestateIsEmpty((frame & EVERY8TH) + 8))
|| (!greenzone.savestates[frame & EVERY4TH].empty() && (int)greenzone.savestates.size() > (frame | 0x3) + 1 && !greenzone.savestates[(frame | 0x3) + 1].empty()) || (!greenzone.SavestateIsEmpty(frame & EVERY4TH) && !greenzone.SavestateIsEmpty((frame & EVERY4TH) + 4))
|| (!greenzone.savestates[frame & EVERY2ND].empty() && !greenzone.savestates[(frame | 0x1) + 1].empty())) || (!greenzone.SavestateIsEmpty(frame & EVERY2ND) && !greenzone.SavestateIsEmpty((frame & EVERY2ND) + 2)))
{ {
if (greenzone.GetLagHistoryAtFrame(frame)) if (greenzone.GetLagHistoryAtFrame(frame))
msg->clrTextBk = PALE_LAG_INPUT_COLOR1; msg->clrTextBk = PALE_LAG_INPUT_COLOR1;

View File

@ -499,7 +499,7 @@ void BRANCHES::RedrawBranchesTree()
LineTo(hBitmapDC, branch_x, branch_y); LineTo(hBitmapDC, branch_x, branch_y);
} }
} }
if (bookmarks.IsSafeToShowBookmarksData()) if (IsSafeToShowBranchesData())
{ {
// lines for item under mouse // lines for item under mouse
if (bookmarks.item_under_mouse == TOTAL_BOOKMARKS || (bookmarks.item_under_mouse >= 0 && bookmarks.item_under_mouse < TOTAL_BOOKMARKS && bookmarks.bookmarks_array[bookmarks.item_under_mouse].not_empty)) if (bookmarks.item_under_mouse == TOTAL_BOOKMARKS || (bookmarks.item_under_mouse >= 0 && bookmarks.item_under_mouse < TOTAL_BOOKMARKS && bookmarks.bookmarks_array[bookmarks.item_under_mouse].not_empty))
@ -530,7 +530,7 @@ void BRANCHES::RedrawBranchesTree()
} }
if (changes_since_current_branch) if (changes_since_current_branch)
{ {
if (bookmarks.IsSafeToShowBookmarksData() && bookmarks.item_under_mouse == TOTAL_BOOKMARKS) if (IsSafeToShowBranchesData() && bookmarks.item_under_mouse == TOTAL_BOOKMARKS)
SelectObject(hBitmapDC, select_pen); SelectObject(hBitmapDC, select_pen);
else else
SelectObject(hBitmapDC, timeline_pen); SelectObject(hBitmapDC, timeline_pen);
@ -595,7 +595,7 @@ void BRANCHES::RedrawBranchesTree()
BitBlt(hBitmapDC, branch_x, branch_y, DIGIT_BITMAP_WIDTH, DIGIT_BITMAP_HEIGHT, hSpritesheetDC, i * DIGIT_BITMAP_WIDTH, 0, SRCCOPY); BitBlt(hBitmapDC, branch_x, branch_y, DIGIT_BITMAP_WIDTH, DIGIT_BITMAP_HEIGHT, hSpritesheetDC, i * DIGIT_BITMAP_WIDTH, 0, SRCCOPY);
} }
} }
if (bookmarks.IsSafeToShowBookmarksData()) if (IsSafeToShowBranchesData())
{ {
SetBkMode(hBitmapDC, TRANSPARENT); SetBkMode(hBitmapDC, TRANSPARENT);
// jump_frame of item under cursor (except cloud - it doesn't have particular frame) // jump_frame of item under cursor (except cloud - it doesn't have particular frame)
@ -689,6 +689,11 @@ void BRANCHES::PaintBranchesBitmap(HDC hdc)
BitBlt(hdc, 0, 0, BRANCHES_BITMAP_WIDTH, BRANCHES_BITMAP_HEIGHT, hBufferDC, 0, 0, SRCCOPY); BitBlt(hdc, 0, 0, BRANCHES_BITMAP_WIDTH, BRANCHES_BITMAP_HEIGHT, hBufferDC, 0, 0, SRCCOPY);
} }
// ---------------------------------------------------------------------------------------- // ----------------------------------------------------------------------------------------
// getters
int BRANCHES::GetParentOf(int child)
{
return parents[child];
}
int BRANCHES::GetCurrentBranch() int BRANCHES::GetCurrentBranch()
{ {
return current_branch; return current_branch;
@ -697,6 +702,13 @@ bool BRANCHES::GetChangesSinceCurrentBranch()
{ {
return changes_since_current_branch; return changes_since_current_branch;
} }
// this getter contains formula to decide whether it's safe to show Branches Data now
bool BRANCHES::IsSafeToShowBranchesData()
{
if (bookmarks.edit_mode == EDIT_MODE_BRANCHES && transition_phase)
return false; // can't show data when Branches Tree is transforming
return true;
}
void BRANCHES::HandleBookmarkSet(int slot) void BRANCHES::HandleBookmarkSet(int slot)
{ {

View File

@ -101,9 +101,12 @@ public:
void save(EMUFILE *os); void save(EMUFILE *os);
bool load(EMUFILE *is); bool load(EMUFILE *is);
int GetParentOf(int child);
int GetCurrentBranch(); int GetCurrentBranch();
bool GetChangesSinceCurrentBranch(); bool GetChangesSinceCurrentBranch();
bool IsSafeToShowBranchesData();
void RedrawBranchesTree(); void RedrawBranchesTree();
void PaintBranchesBitmap(HDC hdc); void PaintBranchesBitmap(HDC hdc);
@ -118,25 +121,21 @@ public:
int FindItemUnderMouse(int mouse_x, int mouse_y); int FindItemUnderMouse(int mouse_x, int mouse_y);
// not saved vars
bool must_redraw_branches_tree;
bool must_recalculate_branches_tree;
int branch_rightclicked;
private:
void SetCurrentPosTime();
void RecalculateParents(); void RecalculateParents();
void RecalculateBranchesTree(); void RecalculateBranchesTree();
void RecursiveAddHeight(int branch_num, int amount); void RecursiveAddHeight(int branch_num, int amount);
void RecursiveSetYPos(int parent, int parentY); void RecursiveSetYPos(int parent, int parentY);
// saved vars // saved vars
std::vector<int> parents; std::vector<int> parents;
// not saved vars
bool must_redraw_branches_tree;
bool must_recalculate_branches_tree;
int branch_rightclicked;
int transition_phase;
private:
void SetCurrentPosTime();
// also saved vars
int current_branch; int current_branch;
bool changes_since_current_branch; bool changes_since_current_branch;
char cloud_time[TIME_DESC_LENGTH]; char cloud_time[TIME_DESC_LENGTH];
@ -145,6 +144,7 @@ private:
std::vector<int8> cached_timelines; // stores id of the last branch on the timeline of every Branch. Sometimes it's the id of the Branch itself, but sometimes it's an id of its child/frandchild that shares the same input std::vector<int8> cached_timelines; // stores id of the last branch on the timeline of every Branch. Sometimes it's the id of the Branch itself, but sometimes it's an id of its child/frandchild that shares the same input
// not saved vars // not saved vars
int transition_phase;
int animation_frame; int animation_frame;
int next_animation_time; int next_animation_time;
int playback_x, playback_y; int playback_x, playback_y;

View File

@ -22,7 +22,6 @@ public:
std::vector<std::string> autofire_patterns_names; std::vector<std::string> autofire_patterns_names;
std::vector<std::vector<uint8>> autofire_patterns; std::vector<std::vector<uint8>> autofire_patterns;
private: private:
bool ReadString(EMUFILE *is, std::string& dest); bool ReadString(EMUFILE *is, std::string& dest);

View File

@ -53,8 +53,6 @@ void GREENZONE::free()
savestates.resize(0); savestates.resize(0);
greenZoneCount = 0; greenZoneCount = 0;
lag_history.resize(0); lag_history.resize(0);
// reset monitorings
} }
void GREENZONE::reset() void GREENZONE::reset()
{ {
@ -69,7 +67,7 @@ void GREENZONE::update()
// run cleaning from time to time // run cleaning from time to time
if (clock() > next_cleaning_time) if (clock() > next_cleaning_time)
GreenzoneCleaning(); RunGreenzoneCleaning();
} }
void GREENZONE::CollectCurrentState() void GREENZONE::CollectCurrentState()
@ -117,7 +115,7 @@ void GREENZONE::storeTasSavestate(int frame)
ms.trim(); ms.trim();
} }
void GREENZONE::GreenzoneCleaning() void GREENZONE::RunGreenzoneCleaning()
{ {
int i = currFrameCounter - taseditor_config.greenzone_capacity; int i = currFrameCounter - taseditor_config.greenzone_capacity;
bool changed = false; bool changed = false;
@ -194,6 +192,21 @@ void GREENZONE::ClearSavestate(int index)
std::vector<uint8> tmp; std::vector<uint8> tmp;
savestates[index].swap(tmp); savestates[index].swap(tmp);
} }
// this function is used by Bookmark Unleash procedure
void GREENZONE::WriteSavestate(int frame, std::vector<uint8>& savestate)
{
if ((int)savestates.size() <= frame)
savestates.resize(frame + 1);
if (greenZoneCount <= frame)
{
// clear old savestates: from current end of greenzone to new end of greenzone
for (int i = greenZoneCount; i <= frame; ++i)
ClearSavestate(i);
greenZoneCount = frame + 1;
}
if (savestates[frame].empty())
savestates[frame] = savestate;
}
void GREENZONE::save(EMUFILE *os, bool really_save) void GREENZONE::save(EMUFILE *os, bool really_save)
{ {
@ -215,7 +228,7 @@ void GREENZONE::save(EMUFILE *os, bool really_save)
// write savestates // write savestates
int frame, size; int frame, size;
int last_tick = 0; int last_tick = 0;
GreenzoneCleaning(); RunGreenzoneCleaning();
for (frame = 0; frame < greenZoneCount; ++frame) for (frame = 0; frame < greenZoneCount; ++frame)
{ {
// update TASEditor progressbar from time to time // update TASEditor progressbar from time to time
@ -226,7 +239,6 @@ void GREENZONE::save(EMUFILE *os, bool really_save)
} }
if (savestates[frame].empty()) continue; if (savestates[frame].empty()) continue;
write32le(frame, os); write32le(frame, os);
// write monitorings
// write savestate // write savestate
size = savestates[frame].size(); size = savestates[frame].size();
write32le(size, os); write32le(size, os);
@ -335,7 +347,6 @@ bool GREENZONE::load(EMUFILE *is, bool really_load)
playback.SetProgressbar(frame, greenZoneCount); playback.SetProgressbar(frame, greenZoneCount);
last_tick = frame / PROGRESSBAR_UPDATE_RATE; last_tick = frame / PROGRESSBAR_UPDATE_RATE;
} }
// read monitorings
// read savestate // read savestate
if (!read32le(&size, is)) break; if (!read32le(&size, is)) break;
if (size < 0) break; if (size < 0) break;
@ -388,7 +399,7 @@ error:
playback.StartFromZero(); // reset playback to frame 0 playback.StartFromZero(); // reset playback to frame 0
return true; return true;
} }
// -------------------------------------------------------------------------------------------------
// invalidate and restore playback // invalidate and restore playback
void GREENZONE::InvalidateAndCheck(int after) void GREENZONE::InvalidateAndCheck(int after)
{ {
@ -444,7 +455,7 @@ void GREENZONE::Invalidate(int after)
piano_roll.RedrawList(); piano_roll.RedrawList();
bookmarks.RedrawBookmarksList(); bookmarks.RedrawBookmarksList();
} }
// -------------------------------------------------------------------------------------------------
int GREENZONE::FindBeginningOfGreenZone(int starting_index) int GREENZONE::FindBeginningOfGreenZone(int starting_index)
{ {
for (int i = starting_index; i < greenZoneCount; ++i) for (int i = starting_index; i < greenZoneCount; ++i)
@ -453,8 +464,11 @@ int GREENZONE::FindBeginningOfGreenZone(int starting_index)
} }
return starting_index; return starting_index;
} }
// getters
// getter int GREENZONE::GetSize()
{
return greenZoneCount;
}
bool GREENZONE::GetLagHistoryAtFrame(int frame) bool GREENZONE::GetLagHistoryAtFrame(int frame)
{ {
if (frame < greenZoneCount && frame < (int)lag_history.size()) if (frame < greenZoneCount && frame < (int)lag_history.size())
@ -462,7 +476,15 @@ bool GREENZONE::GetLagHistoryAtFrame(int frame)
else else
return false; return false;
} }
std::vector<uint8>& GREENZONE::GetSavestate(int frame)
{
return savestates[frame];
}
bool GREENZONE::SavestateIsEmpty(int frame)
{
if (frame < greenZoneCount && frame < (int)savestates.size())
return savestates[frame].empty();
else
return true;
}

View File

@ -23,27 +23,30 @@ public:
void save(EMUFILE *os, bool really_save = true); void save(EMUFILE *os, bool really_save = true);
bool load(EMUFILE *is, bool really_load = true); bool load(EMUFILE *is, bool really_load = true);
void CollectCurrentState();
bool loadTasSavestate(int frame); bool loadTasSavestate(int frame);
void storeTasSavestate(int frame);
void GreenzoneCleaning(); void RunGreenzoneCleaning();
void ClearSavestate(int index); void ClearSavestate(int index);
void WriteSavestate(int frame, std::vector<uint8>& savestate);
void InvalidateAndCheck(int after); void InvalidateAndCheck(int after);
void Invalidate(int after); void Invalidate(int after);
int FindBeginningOfGreenZone(int starting_index = 0); int FindBeginningOfGreenZone(int starting_index = 0);
int GetSize();
bool GetLagHistoryAtFrame(int frame); bool GetLagHistoryAtFrame(int frame);
std::vector<uint8>& GetSavestate(int frame);
bool SavestateIsEmpty(int frame);
private:
void CollectCurrentState();
void storeTasSavestate(int frame);
// saved data // saved data
int greenZoneCount; int greenZoneCount;
std::vector<std::vector<uint8>> savestates; std::vector<std::vector<uint8>> savestates;
private:
// saved data
std::vector<uint8> lag_history; std::vector<uint8> lag_history;
// not saved data // not saved data

View File

@ -119,7 +119,7 @@ void HISTORY::init()
hwndHistoryList_oldWndProc = (WNDPROC)SetWindowLong(hwndHistoryList, GWL_WNDPROC, (LONG)HistoryListWndProc); hwndHistoryList_oldWndProc = (WNDPROC)SetWindowLong(hwndHistoryList, GWL_WNDPROC, (LONG)HistoryListWndProc);
LVCOLUMN lvc; LVCOLUMN lvc;
lvc.mask = LVCF_WIDTH | LVCF_FMT; lvc.mask = LVCF_WIDTH | LVCF_FMT;
lvc.cx = 500; lvc.cx = HISTORY_LIST_WIDTH;
lvc.fmt = LVCFMT_LEFT; lvc.fmt = LVCFMT_LEFT;
ListView_InsertColumn(hwndHistoryList, 0, &lvc); ListView_InsertColumn(hwndHistoryList, 0, &lvc);
// shedule first autocompression // shedule first autocompression
@ -147,7 +147,8 @@ void HISTORY::reset()
// create initial snapshot // create initial snapshot
SNAPSHOT snap; SNAPSHOT snap;
snap.init(currMovieData, taseditor_config.enable_hot_changes); snap.init(currMovieData, taseditor_config.enable_hot_changes);
strcat(snap.description, modCaptions[MODTYPE_INIT]); snap.mod_type = MODTYPE_INIT;
strcat(snap.description, modCaptions[snap.mod_type]);
snap.jump_frame = -1; snap.jump_frame = -1;
snap.start_frame = 0; snap.start_frame = 0;
snap.end_frame = snap.size - 1; snap.end_frame = snap.size - 1;
@ -157,9 +158,9 @@ void HISTORY::reset()
} }
void HISTORY::update() void HISTORY::update()
{ {
// update undo_hint // Update undo_hint
if (old_undo_hint_pos != undo_hint_pos && old_undo_hint_pos >= 0) if (old_undo_hint_pos != undo_hint_pos && old_undo_hint_pos >= 0)
piano_roll.RedrawRow(old_undo_hint_pos); // not changing Bookmarks List piano_roll.RedrawRow(old_undo_hint_pos);
old_undo_hint_pos = undo_hint_pos; old_undo_hint_pos = undo_hint_pos;
old_show_undo_hint = show_undo_hint; old_show_undo_hint = show_undo_hint;
show_undo_hint = false; show_undo_hint = false;
@ -168,17 +169,17 @@ void HISTORY::update()
if ((int)clock() < undo_hint_time) if ((int)clock() < undo_hint_time)
show_undo_hint = true; show_undo_hint = true;
else else
undo_hint_pos = -1; // finished hinting undo_hint_pos = -1; // finished hinting
} }
if (old_show_undo_hint != show_undo_hint) if (old_show_undo_hint != show_undo_hint)
piano_roll.RedrawRow(undo_hint_pos); // not changing Bookmarks List piano_roll.RedrawRow(undo_hint_pos);
// when cpu is idle, compress items from time to time // When cpu is idle, compress items from time to time
if (clock() > next_autocompress_time) if (clock() > next_autocompress_time)
{ {
if (FCEUI_EmulationPaused()) if (FCEUI_EmulationPaused())
{ {
// search for first occurence of an item with snapshot that is not compressed yet // search for first occurence of an item containing non-compressed snapshot
int real_pos; int real_pos;
for (int i = history_total_items - 1; i >= 0; i--) for (int i = history_total_items - 1; i >= 0; i--)
{ {
@ -240,10 +241,13 @@ void HISTORY::HistorySizeChanged()
RedrawHistoryList(); RedrawHistoryList();
} }
// returns frame of first input change (for greenzone invalidation) // returns frame of first input change (for Greenzone invalidation)
int HISTORY::jump(int new_pos) int HISTORY::JumpInTime(int new_pos)
{ {
if (new_pos < 0) new_pos = 0; else if (new_pos >= history_total_items) new_pos = history_total_items-1; if (new_pos < 0)
new_pos = 0;
else if (new_pos >= history_total_items)
new_pos = history_total_items-1;
// if nothing is done, do not invalidate greenzone // if nothing is done, do not invalidate greenzone
if (new_pos == history_cursor_pos) return -1; if (new_pos == history_cursor_pos) return -1;
@ -396,14 +400,14 @@ int HISTORY::jump(int new_pos)
void HISTORY::undo() void HISTORY::undo()
{ {
int result = jump(history_cursor_pos - 1); int result = JumpInTime(history_cursor_pos - 1);
if (result >= 0) if (result >= 0)
greenzone.InvalidateAndCheck(result); greenzone.InvalidateAndCheck(result);
return; return;
} }
void HISTORY::redo() void HISTORY::redo()
{ {
int result = jump(history_cursor_pos + 1); int result = JumpInTime(history_cursor_pos + 1);
if (result >= 0) if (result >= 0)
greenzone.InvalidateAndCheck(result); greenzone.InvalidateAndCheck(result);
return; return;
@ -1062,10 +1066,10 @@ LONG HISTORY::CustomDraw(NMLVCUSTOMDRAW* msg)
void HISTORY::Click(int row_index) void HISTORY::Click(int row_index)
{ {
// jump to pointed snapshot // jump in time to pointed item
if (row_index >= 0) if (row_index >= 0)
{ {
int result = jump(row_index); int result = JumpInTime(row_index);
if (result >= 0) if (result >= 0)
greenzone.InvalidateAndCheck(result); greenzone.InvalidateAndCheck(result);
} }

View File

@ -1,10 +1,12 @@
// Specification file for History class // Specification file for History class
#define UNDO_HINT_TIME 200 #define UNDO_HINT_TIME 200 // in milliseconds
#define SAVING_HISTORY_PROGRESSBAR_UPDATE_RATE 10 #define SAVING_HISTORY_PROGRESSBAR_UPDATE_RATE 10
#define TIME_BETWEEN_AUTOCOMPRESSIONS 500 // in milliseconds #define TIME_BETWEEN_AUTOCOMPRESSIONS 500 // in milliseconds
#define HISTORY_LIST_WIDTH 500
enum MOD_TYPES enum MOD_TYPES
{ {
MODTYPE_INIT, MODTYPE_INIT,
@ -98,8 +100,6 @@ public:
void save(EMUFILE *os, bool really_save = true); void save(EMUFILE *os, bool really_save = true);
bool load(EMUFILE *is, bool really_load = true); bool load(EMUFILE *is, bool really_load = true);
int jump(int new_pos);
void undo(); void undo();
void redo(); void redo();
@ -132,6 +132,8 @@ public:
HWND hwndHistoryList; HWND hwndHistoryList;
private: private:
int JumpInTime(int new_pos);
void AddItemToHistory(SNAPSHOT &snap, int cur_branch = 0); void AddItemToHistory(SNAPSHOT &snap, int cur_branch = 0);
void AddItemToHistory(SNAPSHOT &snap, int cur_branch, BOOKMARK &bookm); void AddItemToHistory(SNAPSHOT &snap, int cur_branch, BOOKMARK &bookm);

View File

@ -1163,18 +1163,18 @@ LONG PIANO_ROLL::CustomDraw(NMLVCUSTOMDRAW* msg)
msg->clrTextBk = (taseditor_config.bind_markers) ? BINDMARKED_FRAMENUM_COLOR : MARKED_FRAMENUM_COLOR; msg->clrTextBk = (taseditor_config.bind_markers) ? BINDMARKED_FRAMENUM_COLOR : MARKED_FRAMENUM_COLOR;
} else } else
{ {
if(cell_y < greenzone.greenZoneCount) if(cell_y < greenzone.GetSize())
{ {
if (!greenzone.savestates[cell_y].empty()) if (!greenzone.SavestateIsEmpty(cell_y))
{ {
if (greenzone.GetLagHistoryAtFrame(cell_y)) if (greenzone.GetLagHistoryAtFrame(cell_y))
msg->clrTextBk = LAG_FRAMENUM_COLOR; msg->clrTextBk = LAG_FRAMENUM_COLOR;
else else
msg->clrTextBk = GREENZONE_FRAMENUM_COLOR; msg->clrTextBk = GREENZONE_FRAMENUM_COLOR;
} else if ((!greenzone.savestates[cell_y & EVERY16TH].empty() && (int)greenzone.savestates.size() > (cell_y | 0xF) + 1 && !greenzone.savestates[(cell_y | 0xF) + 1].empty()) } else if ((!greenzone.SavestateIsEmpty(cell_y & EVERY16TH) && !greenzone.SavestateIsEmpty((cell_y & EVERY16TH) + 16))
|| (!greenzone.savestates[cell_y & EVERY8TH].empty() && (int)greenzone.savestates.size() > (cell_y | 0x7) + 1 && !greenzone.savestates[(cell_y | 0x7) + 1].empty()) || (!greenzone.SavestateIsEmpty(cell_y & EVERY8TH) && !greenzone.SavestateIsEmpty((cell_y & EVERY8TH) + 8))
|| (!greenzone.savestates[cell_y & EVERY4TH].empty() && (int)greenzone.savestates.size() > (cell_y | 0x3) + 1 && !greenzone.savestates[(cell_y | 0x3) + 1].empty()) || (!greenzone.SavestateIsEmpty(cell_y & EVERY4TH) && !greenzone.SavestateIsEmpty((cell_y & EVERY4TH) + 4))
|| (!greenzone.savestates[cell_y & EVERY2ND].empty() && !greenzone.savestates[(cell_y | 0x1) + 1].empty())) || (!greenzone.SavestateIsEmpty(cell_y & EVERY2ND) && !greenzone.SavestateIsEmpty((cell_y & EVERY2ND) + 2)))
{ {
if (greenzone.GetLagHistoryAtFrame(cell_y)) if (greenzone.GetLagHistoryAtFrame(cell_y))
msg->clrTextBk = PALE_LAG_FRAMENUM_COLOR; msg->clrTextBk = PALE_LAG_FRAMENUM_COLOR;
@ -1203,18 +1203,18 @@ LONG PIANO_ROLL::CustomDraw(NMLVCUSTOMDRAW* msg)
{ {
// current frame // current frame
msg->clrTextBk = CUR_INPUT_COLOR1; msg->clrTextBk = CUR_INPUT_COLOR1;
} else if(cell_y < greenzone.greenZoneCount) } else if(cell_y < greenzone.GetSize())
{ {
if (!greenzone.savestates[cell_y].empty()) if (!greenzone.SavestateIsEmpty(cell_y))
{ {
if (greenzone.GetLagHistoryAtFrame(cell_y)) if (greenzone.GetLagHistoryAtFrame(cell_y))
msg->clrTextBk = LAG_INPUT_COLOR1; msg->clrTextBk = LAG_INPUT_COLOR1;
else else
msg->clrTextBk = GREENZONE_INPUT_COLOR1; msg->clrTextBk = GREENZONE_INPUT_COLOR1;
} else if ((!greenzone.savestates[cell_y & EVERY16TH].empty() && (int)greenzone.savestates.size() > (cell_y | 0xF) + 1 && !greenzone.savestates[(cell_y | 0xF) + 1].empty()) } else if ((!greenzone.SavestateIsEmpty(cell_y & EVERY16TH) && !greenzone.SavestateIsEmpty((cell_y & EVERY16TH) + 16))
|| (!greenzone.savestates[cell_y & EVERY8TH].empty() && (int)greenzone.savestates.size() > (cell_y | 0x7) + 1 && !greenzone.savestates[(cell_y | 0x7) + 1].empty()) || (!greenzone.SavestateIsEmpty(cell_y & EVERY8TH) && !greenzone.SavestateIsEmpty((cell_y & EVERY8TH) + 8))
|| (!greenzone.savestates[cell_y & EVERY4TH].empty() && (int)greenzone.savestates.size() > (cell_y | 0x3) + 1 && !greenzone.savestates[(cell_y | 0x3) + 1].empty()) || (!greenzone.SavestateIsEmpty(cell_y & EVERY4TH) && !greenzone.SavestateIsEmpty((cell_y & EVERY4TH) + 4))
|| (!greenzone.savestates[cell_y & EVERY2ND].empty() && !greenzone.savestates[(cell_y | 0x1) + 1].empty())) || (!greenzone.SavestateIsEmpty(cell_y & EVERY2ND) && !greenzone.SavestateIsEmpty((cell_y & EVERY2ND) + 2)))
{ {
if (greenzone.GetLagHistoryAtFrame(cell_y)) if (greenzone.GetLagHistoryAtFrame(cell_y))
msg->clrTextBk = PALE_LAG_INPUT_COLOR1; msg->clrTextBk = PALE_LAG_INPUT_COLOR1;
@ -1242,18 +1242,18 @@ LONG PIANO_ROLL::CustomDraw(NMLVCUSTOMDRAW* msg)
{ {
// current frame // current frame
msg->clrTextBk = CUR_INPUT_COLOR2; msg->clrTextBk = CUR_INPUT_COLOR2;
} else if(cell_y < greenzone.greenZoneCount) } else if(cell_y < greenzone.GetSize())
{ {
if (!greenzone.savestates[cell_y].empty()) if (!greenzone.SavestateIsEmpty(cell_y))
{ {
if (greenzone.GetLagHistoryAtFrame(cell_y)) if (greenzone.GetLagHistoryAtFrame(cell_y))
msg->clrTextBk = LAG_INPUT_COLOR2; msg->clrTextBk = LAG_INPUT_COLOR2;
else else
msg->clrTextBk = GREENZONE_INPUT_COLOR2; msg->clrTextBk = GREENZONE_INPUT_COLOR2;
} else if ((!greenzone.savestates[cell_y & EVERY16TH].empty() && (int)greenzone.savestates.size() > (cell_y | 0xF) + 1 && !greenzone.savestates[(cell_y | 0xF) + 1].empty()) } else if ((!greenzone.SavestateIsEmpty(cell_y & EVERY16TH) && !greenzone.SavestateIsEmpty((cell_y & EVERY16TH) + 16))
|| (!greenzone.savestates[cell_y & EVERY8TH].empty() && (int)greenzone.savestates.size() > (cell_y | 0x7) + 1 && !greenzone.savestates[(cell_y | 0x7) + 1].empty()) || (!greenzone.SavestateIsEmpty(cell_y & EVERY8TH) && !greenzone.SavestateIsEmpty((cell_y & EVERY8TH) + 8))
|| (!greenzone.savestates[cell_y & EVERY4TH].empty() && (int)greenzone.savestates.size() > (cell_y | 0x3) + 1 && !greenzone.savestates[(cell_y | 0x3) + 1].empty()) || (!greenzone.SavestateIsEmpty(cell_y & EVERY4TH) && !greenzone.SavestateIsEmpty((cell_y & EVERY4TH) + 4))
|| (!greenzone.savestates[cell_y & EVERY2ND].empty() && !greenzone.savestates[(cell_y | 0x1) + 1].empty())) || (!greenzone.SavestateIsEmpty(cell_y & EVERY2ND) && !greenzone.SavestateIsEmpty((cell_y & EVERY2ND) + 2)))
{ {
if (greenzone.GetLagHistoryAtFrame(cell_y)) if (greenzone.GetLagHistoryAtFrame(cell_y))
msg->clrTextBk = PALE_LAG_INPUT_COLOR2; msg->clrTextBk = PALE_LAG_INPUT_COLOR2;

View File

@ -141,10 +141,11 @@ void PLAYBACK::update()
if (currFrameCounter + 1 >= lost_position_frame) if (currFrameCounter + 1 >= lost_position_frame)
lost_position_frame = 0; lost_position_frame = 0;
// pause when seeking hit pause_frame // pause when seeking hits pause_frame
if(pause_frame && currFrameCounter + 1 >= pause_frame) if(pause_frame && currFrameCounter + 1 >= pause_frame)
SeekingStop(); SeekingStop();
else if (!lost_position_frame && currFrameCounter >= currMovieData.getNumRecords()-1 && autopause_at_the_end && taseditor_config.autopause_at_finish) else if (!lost_position_frame && currFrameCounter >= currMovieData.getNumRecords()-1 && autopause_at_the_end && taseditor_config.autopause_at_finish)
// pause at the end of the movie
PauseEmulation(); PauseEmulation();
// update flashing pauseframe // update flashing pauseframe
@ -159,15 +160,15 @@ void PLAYBACK::update()
if (pause_frame) if (pause_frame)
{ {
if (emu_paused) if (emu_paused)
show_pauseframe = (int)(clock() / PAUSEFRAME_BLINKING_PERIOD_PAUSED) & 1; show_pauseframe = (int)(clock() / PAUSEFRAME_BLINKING_PERIOD_WHEN_PAUSED) & 1;
else else
show_pauseframe = (int)(clock() / PAUSEFRAME_BLINKING_PERIOD_SEEKING) & 1; show_pauseframe = (int)(clock() / PAUSEFRAME_BLINKING_PERIOD_WHEN_SEEKING) & 1;
} else show_pauseframe = false; } else show_pauseframe = false;
if (old_show_pauseframe != show_pauseframe) if (old_show_pauseframe != show_pauseframe)
{ {
// update pauseframe gfx // update pauseframe gfx
piano_roll.RedrawRow(pause_frame-1); piano_roll.RedrawRow(pause_frame - 1);
bookmarks.RedrawChangedBookmarks(pause_frame-1); bookmarks.RedrawChangedBookmarks(pause_frame - 1);
} }
// update seeking progressbar // update seeking progressbar
@ -198,7 +199,7 @@ void PLAYBACK::update()
} }
// update the playback cursor // update the playback cursor
if(currFrameCounter != lastCursor) if (currFrameCounter != lastCursor)
{ {
// update gfx of the old and new rows // update gfx of the old and new rows
piano_roll.RedrawRow(lastCursor); piano_roll.RedrawRow(lastCursor);
@ -245,8 +246,10 @@ void PLAYBACK::updateProgressbar()
} else } else
{ {
if (emu_paused) if (emu_paused)
// full progressbar
SetProgressbar(1, 1); SetProgressbar(1, 1);
else else
// cleared progressbar
SetProgressbar(0, 1); SetProgressbar(0, 1);
} }
} }
@ -271,21 +274,14 @@ void PLAYBACK::UnpauseEmulation()
void PLAYBACK::RestorePosition() void PLAYBACK::RestorePosition()
{ {
if (lost_position_frame && lost_position_frame > currFrameCounter + 1) if (lost_position_frame && lost_position_frame > currFrameCounter + 1)
{ SeekingStart(lost_position_frame);
// start seeking from here to lost_position_frame
pause_frame = lost_position_frame;
pause_frame_must_be_fixed = true;
seeking_start_frame = currFrameCounter;
if (taseditor_config.turbo_seek)
turbo = true;
UnpauseEmulation();
}
} }
void PLAYBACK::MiddleButtonClick() void PLAYBACK::MiddleButtonClick()
{ {
if (emu_paused) if (emu_paused)
{ {
// if right mouse button is released, either just unpause or start seeking // Unpause or start seeking
// works only when right mouse button is released
if (GetAsyncKeyState(GetSystemMetrics(SM_SWAPBUTTON) ? VK_LBUTTON : VK_RBUTTON) >= 0) if (GetAsyncKeyState(GetSystemMetrics(SM_SWAPBUTTON) ? VK_LBUTTON : VK_RBUTTON) >= 0)
{ {
if (GetAsyncKeyState(VK_SHIFT) < 0) if (GetAsyncKeyState(VK_SHIFT) < 0)
@ -296,29 +292,17 @@ void PLAYBACK::MiddleButtonClick()
for (; target_frame <= last_frame; ++target_frame) for (; target_frame <= last_frame; ++target_frame)
if (markers_manager.GetMarker(target_frame)) break; if (markers_manager.GetMarker(target_frame)) break;
if (target_frame <= last_frame) if (target_frame <= last_frame)
{ SeekingStart(target_frame + 1);
// start seeking to the Marker
seeking_start_frame = currFrameCounter;
pause_frame = target_frame + 1;
pause_frame_must_be_fixed = true;
if (taseditor_config.turbo_seek)
turbo = true;
}
} else if (GetAsyncKeyState(VK_CONTROL) < 0) } else if (GetAsyncKeyState(VK_CONTROL) < 0)
{ {
// if Ctrl is held, seek to Selection cursor // if Ctrl is held, seek to Selection cursor
int selection_beginning = selection.GetCurrentSelectionBeginning(); int selection_beginning = selection.GetCurrentSelectionBeginning();
if (selection_beginning > currFrameCounter) if (selection_beginning > currFrameCounter)
{ SeekingStart(selection_beginning + 1);
// start seeking to selection_beginning } else
seeking_start_frame = currFrameCounter; {
pause_frame = selection_beginning + 1; UnpauseEmulation();
pause_frame_must_be_fixed = true;
if (taseditor_config.turbo_seek)
turbo = true;
}
} }
UnpauseEmulation();
} }
} else } else
{ {
@ -332,13 +316,12 @@ void PLAYBACK::SeekingStart(int finish_frame)
{ {
seeking_start_frame = currFrameCounter; seeking_start_frame = currFrameCounter;
pause_frame = finish_frame; pause_frame = finish_frame;
pause_frame_must_be_fixed = true;
} }
pause_frame_must_be_fixed = true;
if (taseditor_config.turbo_seek) if (taseditor_config.turbo_seek)
turbo = true; turbo = true;
UnpauseEmulation(); UnpauseEmulation();
} }
void PLAYBACK::SeekingStop() void PLAYBACK::SeekingStop()
{ {
pause_frame = 0; pause_frame = 0;
@ -352,7 +335,7 @@ void PLAYBACK::RewindFrame()
{ {
if (pause_frame && !emu_paused) return; if (pause_frame && !emu_paused) return;
if (currFrameCounter > 0) if (currFrameCounter > 0)
jump(currFrameCounter-1); jump(currFrameCounter - 1);
else else
// cursor is at frame 0 - can't rewind, but still must make cursor visible if needed // cursor is at frame 0 - can't rewind, but still must make cursor visible if needed
piano_roll.FollowPlaybackIfNeeded(); piano_roll.FollowPlaybackIfNeeded();
@ -361,7 +344,7 @@ void PLAYBACK::RewindFrame()
void PLAYBACK::ForwardFrame() void PLAYBACK::ForwardFrame()
{ {
if (pause_frame && !emu_paused) return; if (pause_frame && !emu_paused) return;
jump(currFrameCounter+1); jump(currFrameCounter + 1);
if (!pause_frame) PauseEmulation(); if (!pause_frame) PauseEmulation();
turbo = false; turbo = false;
} }
@ -434,49 +417,50 @@ void PLAYBACK::StartFromZero()
poweron(true); poweron(true);
FCEUMOV_ClearCommands(); // clear POWER SWITCH command caused by poweron() FCEUMOV_ClearCommands(); // clear POWER SWITCH command caused by poweron()
currFrameCounter = 0; currFrameCounter = 0;
// if there's no frames in current movie, create initial frame record
if(currMovieData.getNumRecords() == 0) if(currMovieData.getNumRecords() == 0)
currMovieData.insertEmpty(-1, 1); currMovieData.insertEmpty(-1, 1);
} }
void PLAYBACK::jump(int frame) // external interface for sending Playback cursor
void PLAYBACK::jump(int frame, bool execute_lua, bool follow_cursor)
{ {
if (frame < 0) return;
if (JumpToFrame(frame)) if (JumpToFrame(frame))
{ {
ForceExecuteLuaFrameFunctions(); if (execute_lua)
piano_roll.FollowPlaybackIfNeeded(); ForceExecuteLuaFrameFunctions();
if (follow_cursor)
piano_roll.FollowPlaybackIfNeeded();
} }
} }
// returns true if a jump to the frame is made, false if started seeking outside greenzone or if nothing's done // returns true if a jump to the frame is made, false if started seeking outside greenzone or if nothing's done
bool PLAYBACK::JumpToFrame(int index) bool PLAYBACK::JumpToFrame(int index)
{ {
if (index < 0) return false; if (index >= greenzone.GetSize())
if (index >= greenzone.greenZoneCount)
{ {
// handle jump outside greenzone // make jump outside greenzone
if (currFrameCounter == greenzone.greenZoneCount - 1 || JumpToFrame(greenzone.greenZoneCount - 1)) if (currFrameCounter == greenzone.GetSize() - 1 || JumpToFrame(greenzone.GetSize() - 1))
// seek from the end of greenzone // seek there from the end of greenzone
SeekingStart(index+1); SeekingStart(index+1);
return false; return false;
} }
// handle jumps inside greenzone // make jump inside greenzone
if (greenzone.loadTasSavestate(index)) if (greenzone.loadTasSavestate(index))
{ {
turbo = false; // successfully restored emulator state at this frame
// if playback was seeking, pause emulation right here // if playback was seeking, pause emulation right here
if (pause_frame) SeekingStop(); if (pause_frame)
SeekingStop();
return true; return true;
} }
// search for an earlier frame with savestate // search for an earlier frame with savestate
int i = (index > 0)? index-1 : 0; int i = (index > 0) ? index-1 : 0;
for (; i > 0; i--) for (; i > 0; i--)
{
if (greenzone.loadTasSavestate(i)) break; if (greenzone.loadTasSavestate(i)) break;
} if (i > 0)
if (!i) StartFromZero(); // couldn't find a savestate
StartFromZero();
else
currFrameCounter = i;
// continue from the frame // continue from the frame
if (index != currFrameCounter) if (index != currFrameCounter)
SeekingStart(index + 1); SeekingStart(index + 1);
@ -561,8 +545,6 @@ LRESULT APIENTRY UpperMarkerEditWndProc(HWND hWnd, UINT msg, WPARAM wParam, LPAR
case WM_MBUTTONDOWN: case WM_MBUTTONDOWN:
case WM_MBUTTONDBLCLK: case WM_MBUTTONDBLCLK:
{ {
if (GetFocus() != hWnd)
SetFocus(hWnd);
playback.MiddleButtonClick(); playback.MiddleButtonClick();
return 0; return 0;
} }
@ -570,8 +552,3 @@ LRESULT APIENTRY UpperMarkerEditWndProc(HWND hWnd, UINT msg, WPARAM wParam, LPAR
return CallWindowProc(playbackMarkerEdit_oldWndproc, hWnd, msg, wParam, lParam); return CallWindowProc(playbackMarkerEdit_oldWndproc, hWnd, msg, wParam, lParam);
} }

View File

@ -2,8 +2,8 @@
#define PROGRESSBAR_WIDTH 200 #define PROGRESSBAR_WIDTH 200
#define PAUSEFRAME_BLINKING_PERIOD_SEEKING 100 #define PAUSEFRAME_BLINKING_PERIOD_WHEN_SEEKING 100
#define PAUSEFRAME_BLINKING_PERIOD_PAUSED 250 #define PAUSEFRAME_BLINKING_PERIOD_WHEN_PAUSED 250
#define HOLD_REPEAT_DELAY 250 // in milliseconds #define HOLD_REPEAT_DELAY 250 // in milliseconds
@ -16,15 +16,17 @@ public:
void reset(); void reset();
void update(); void update();
void jump(int frame); void jump(int frame, bool execute_lua = true, bool follow_cursor = true);
void updateProgressbar(); void updateProgressbar();
void SeekingStart(int finish_frame); void SeekingStart(int finish_frame);
void SeekingStop(); void SeekingStop();
void ToggleEmulationPause(); void ToggleEmulationPause();
void PauseEmulation(); void PauseEmulation();
void UnpauseEmulation(); void UnpauseEmulation();
void RestorePosition(); void RestorePosition();
void MiddleButtonClick(); void MiddleButtonClick();
@ -41,8 +43,6 @@ public:
void SetProgressbar(int a, int b); void SetProgressbar(int a, int b);
void CancelSeeking(); void CancelSeeking();
bool JumpToFrame(int index);
int lastCursor; // but for currentCursor we use external variable currFrameCounter int lastCursor; // but for currentCursor we use external variable currFrameCounter
int lost_position_frame; int lost_position_frame;
bool lost_position_must_be_fixed; // for when Greenzone invalidates several times, but the end of current segment must remain the same bool lost_position_must_be_fixed; // for when Greenzone invalidates several times, but the end of current segment must remain the same
@ -55,6 +55,8 @@ public:
HWND hwndPlaybackMarker, hwndPlaybackMarkerEdit; HWND hwndPlaybackMarker, hwndPlaybackMarkerEdit;
private: private:
bool JumpToFrame(int index);
bool autopause_at_the_end; bool autopause_at_the_end;
bool old_emu_paused, emu_paused; bool old_emu_paused, emu_paused;
int old_pauseframe; int old_pauseframe;

View File

@ -22,6 +22,7 @@ Popup display - Manager of popup windows
extern TASEDITOR_CONFIG taseditor_config; extern TASEDITOR_CONFIG taseditor_config;
extern TASEDITOR_WINDOW taseditor_window; extern TASEDITOR_WINDOW taseditor_window;
extern BOOKMARKS bookmarks; extern BOOKMARKS bookmarks;
extern BRANCHES branches;
extern PIANO_ROLL piano_roll; extern PIANO_ROLL piano_roll;
extern MARKERS_MANAGER markers_manager; extern MARKERS_MANAGER markers_manager;
extern PLAYBACK playback; extern PLAYBACK playback;
@ -99,7 +100,7 @@ void POPUP_DISPLAY::init()
} }
HDC win_hdc = GetWindowDC(piano_roll.hwndList); HDC win_hdc = GetWindowDC(piano_roll.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 // calculate coordinates of popup windows (relative to TAS Editor window)
ParentWindowMoved(); ParentWindowMoved();
} }
void POPUP_DISPLAY::free() void POPUP_DISPLAY::free()
@ -129,11 +130,11 @@ void POPUP_DISPLAY::reset()
void POPUP_DISPLAY::update() void POPUP_DISPLAY::update()
{ {
// once per 40 milliseconds update screenshot_bitmap alpha // once per 40 milliseconds update popup windows alpha
if (clock() > next_update_time) if (clock() > next_update_time)
{ {
next_update_time = clock() + DISPLAY_UPDATE_TICK; next_update_time = clock() + DISPLAY_UPDATE_TICK;
if (bookmarks.IsSafeToShowBookmarksData() && bookmarks.item_under_mouse >= 0 && bookmarks.item_under_mouse < TOTAL_BOOKMARKS && bookmarks.bookmarks_array[bookmarks.item_under_mouse].not_empty) if (branches.IsSafeToShowBranchesData() && bookmarks.item_under_mouse >= 0 && bookmarks.item_under_mouse < TOTAL_BOOKMARKS && bookmarks.bookmarks_array[bookmarks.item_under_mouse].not_empty)
{ {
if (taseditor_config.show_branch_screenshots && !hwndScrBmp) if (taseditor_config.show_branch_screenshots && !hwndScrBmp)
{ {
@ -186,7 +187,10 @@ void POPUP_DISPLAY::update()
{ {
// update alpha // update alpha
int phase_alpha = scr_bmp_phase; int phase_alpha = scr_bmp_phase;
if (phase_alpha > SCR_BMP_PHASE_ALPHA_MAX) phase_alpha = SCR_BMP_PHASE_ALPHA_MAX; if (phase_alpha > SCR_BMP_PHASE_ALPHA_MAX)
phase_alpha = SCR_BMP_PHASE_ALPHA_MAX;
else if (phase_alpha < 0)
phase_alpha = 0;
if (hwndScrBmp) if (hwndScrBmp)
{ {
SetLayeredWindowAttributes(hwndScrBmp, 0, (255 * phase_alpha) / SCR_BMP_PHASE_ALPHA_MAX, LWA_ALPHA); SetLayeredWindowAttributes(hwndScrBmp, 0, (255 * phase_alpha) / SCR_BMP_PHASE_ALPHA_MAX, LWA_ALPHA);
@ -199,7 +203,7 @@ void POPUP_DISPLAY::update()
} }
} else } else
{ {
// destroy screenshot bitmap window // destroy popup windows
scr_bmp_phase = 0; scr_bmp_phase = 0;
if (hwndScrBmp) if (hwndScrBmp)
{ {
@ -211,6 +215,8 @@ void POPUP_DISPLAY::update()
DestroyWindow(hwndMarkerNoteDescr); DestroyWindow(hwndMarkerNoteDescr);
hwndMarkerNoteDescr = 0; hwndMarkerNoteDescr = 0;
} }
// immediately redraw the window below those
UpdateWindow(taseditor_window.hwndTasEditor);
} }
} }
} }

View File

@ -90,19 +90,7 @@ void SELECTION::reset_vars()
} }
void SELECTION::update() void SELECTION::update()
{ {
// keep selection within movie limits UpdateSelectionSize();
if (CurrentSelection().size())
{
int delete_index;
int movie_size = currMovieData.getNumRecords();
while(1)
{
delete_index = *CurrentSelection().rbegin();
if (delete_index < movie_size) break;
CurrentSelection().erase(delete_index);
if (!CurrentSelection().size()) break;
}
}
// update << and >> buttons // update << and >> buttons
old_prev_marker_button_state = prev_marker_button_state; old_prev_marker_button_state = prev_marker_button_state;
@ -150,6 +138,23 @@ void SELECTION::update()
} }
void SELECTION::UpdateSelectionSize()
{
// keep selection within Piano Roll limits
if (CurrentSelection().size())
{
int delete_index;
int movie_size = currMovieData.getNumRecords();
while (true)
{
delete_index = *CurrentSelection().rbegin();
if (delete_index < movie_size) break;
CurrentSelection().erase(delete_index);
if (!CurrentSelection().size()) break;
}
}
}
void SELECTION::HistorySizeChanged() void SELECTION::HistorySizeChanged()
{ {
int new_history_size = taseditor_config.undo_levels + 1; int new_history_size = taseditor_config.undo_levels + 1;
@ -198,7 +203,7 @@ void SELECTION::RedrawMarker()
void SELECTION::JumpPrevMarker(int speed) void SELECTION::JumpPrevMarker(int speed)
{ {
// if nothing is selected, consider playback cursor as current selection // if nothing is selected, consider Playback cursor as current selection
int index = GetCurrentSelectionBeginning(); int index = GetCurrentSelectionBeginning();
if (index < 0) index = currFrameCounter; if (index < 0) index = currFrameCounter;
// jump trough "speed" amount of previous markers // jump trough "speed" amount of previous markers
@ -215,7 +220,7 @@ void SELECTION::JumpPrevMarker(int speed)
} }
void SELECTION::JumpNextMarker(int speed) void SELECTION::JumpNextMarker(int speed)
{ {
// if nothing is selected, consider playback cursor as current selection // if nothing is selected, consider Playback cursor as current selection
int index = GetCurrentSelectionBeginning(); int index = GetCurrentSelectionBeginning();
if (index < 0) index = currFrameCounter; if (index < 0) index = currFrameCounter;
int last_frame = currMovieData.getNumRecords() - 1; // the end of Piano Roll int last_frame = currMovieData.getNumRecords() - 1; // the end of Piano Roll
@ -356,7 +361,7 @@ bool SELECTION::skiploadSelection(EMUFILE *is)
return false; return false;
} }
// ---------------------------------------------------------- // ----------------------------------------------------------
//used to track selection // used to track selection
void SELECTION::ItemRangeChanged(NMLVODSTATECHANGE* info) void SELECTION::ItemRangeChanged(NMLVODSTATECHANGE* info)
{ {
bool ON = !(info->uOldState & LVIS_SELECTED) && (info->uNewState & LVIS_SELECTED); bool ON = !(info->uOldState & LVIS_SELECTED) && (info->uNewState & LVIS_SELECTED);
@ -390,9 +395,7 @@ void SELECTION::ItemChanged(NMLISTVIEW* info)
{ {
// select all // select all
for(int i = currMovieData.getNumRecords() - 1; i >= 0; i--) for(int i = currMovieData.getNumRecords() - 1; i >= 0; i--)
{
CurrentSelection().insert(i); CurrentSelection().insert(i);
}
} }
} else } else
{ {
@ -427,7 +430,7 @@ void SELECTION::AddNewSelectionToHistory()
selections_history[(history_start_pos + history_cursor_pos) % history_size] = selectionFrames; selections_history[(history_start_pos + history_cursor_pos) % history_size] = selectionFrames;
} }
void SELECTION::jump(int new_pos) void SELECTION::JumpInTime(int new_pos)
{ {
if (new_pos < 0) new_pos = 0; else if (new_pos >= history_total_items) new_pos = history_total_items-1; if (new_pos < 0) new_pos = 0; else if (new_pos >= history_total_items) new_pos = history_total_items-1;
if (new_pos == history_cursor_pos) return; if (new_pos == history_cursor_pos) return;
@ -437,15 +440,15 @@ void SELECTION::jump(int new_pos)
// update Piano Roll items // update Piano Roll items
EnforceSelectionToList(); EnforceSelectionToList();
// also keep selection within Piano Roll // also keep selection within Piano Roll
update(); UpdateSelectionSize();
} }
void SELECTION::undo() void SELECTION::undo()
{ {
jump(history_cursor_pos - 1); JumpInTime(history_cursor_pos - 1);
} }
void SELECTION::redo() void SELECTION::redo()
{ {
jump(history_cursor_pos + 1); JumpInTime(history_cursor_pos + 1);
} }
// ---------------------------------------------------------- // ----------------------------------------------------------
bool SELECTION::GetRowSelection(int index) bool SELECTION::GetRowSelection(int index)
@ -469,7 +472,6 @@ void SELECTION::ClearRegionSelection(int start, int end)
void SELECTION::SelectAll() void SELECTION::SelectAll()
{ {
// select all, but remove "focused" from all
ListView_SetItemState(piano_roll.hwndList, -1, LVIS_SELECTED, LVIS_SELECTED); ListView_SetItemState(piano_roll.hwndList, -1, LVIS_SELECTED, LVIS_SELECTED);
} }
void SELECTION::SetRowSelection(int index) void SELECTION::SetRowSelection(int index)
@ -508,7 +510,7 @@ void SELECTION::SelectBetweenMarkers()
int upper_marker, lower_marker; int upper_marker, lower_marker;
int movie_size = currMovieData.getNumRecords(); int movie_size = currMovieData.getNumRecords();
// if selection size=0 then playback cursor is selected and serves as center // if nothing is selected then Playback cursor serves as Selection cursor
if (CurrentSelection().size()) if (CurrentSelection().size())
{ {
upper_border = center = *CurrentSelection().begin(); upper_border = center = *CurrentSelection().begin();
@ -584,7 +586,7 @@ void SELECTION::ReselectClipboard()
CurrentSelection() = clipboard_selection; CurrentSelection() = clipboard_selection;
EnforceSelectionToList(); EnforceSelectionToList();
// also keep selection within Piano Roll // also keep selection within Piano Roll
update(); UpdateSelectionSize();
} }
void SELECTION::Transpose(int shift) void SELECTION::Transpose(int shift)
@ -730,8 +732,6 @@ LRESULT APIENTRY LowerMarkerEditWndProc(HWND hWnd, UINT msg, WPARAM wParam, LPAR
case WM_MBUTTONDOWN: case WM_MBUTTONDOWN:
case WM_MBUTTONDBLCLK: case WM_MBUTTONDBLCLK:
{ {
if (GetFocus() != hWnd)
SetFocus(hWnd);
playback.MiddleButtonClick(); playback.MiddleButtonClick();
return 0; return 0;
} }

View File

@ -15,6 +15,8 @@ public:
void reset_vars(); void reset_vars();
void update(); void update();
void UpdateSelectionSize();
void HistorySizeChanged(); void HistorySizeChanged();
void RedrawMarker(); void RedrawMarker();
@ -49,8 +51,6 @@ public:
void Transpose(int shift); void Transpose(int shift);
void EnforceSelectionToList();
void JumpPrevMarker(int speed = 1); void JumpPrevMarker(int speed = 1);
void JumpNextMarker(int speed = 1); void JumpNextMarker(int speed = 1);
void JumpToFrame(int frame); void JumpToFrame(int frame);
@ -70,7 +70,9 @@ public:
HWND hwndSelectionMarker, hwndSelectionMarkerEdit; HWND hwndSelectionMarker, hwndSelectionMarkerEdit;
private: private:
void jump(int new_pos); void JumpInTime(int new_pos);
void EnforceSelectionToList();
SelectionFrames& CurrentSelection(); SelectionFrames& CurrentSelection();

View File

@ -281,11 +281,8 @@ void SPLICER::DeleteFrames()
greenzone.InvalidateAndCheck(result); greenzone.InvalidateAndCheck(result);
} else } else
{ {
// check special case: user deleted a bunch of empty frames the end of the movie // check for special case: user deleted a bunch of empty frames the end of the movie
if (greenzone.greenZoneCount >= currMovieData.getNumRecords()) greenzone.InvalidateAndCheck(currMovieData.getNumRecords() - 1);
greenzone.InvalidateAndCheck(currMovieData.getNumRecords()-1);
else
piano_roll.RedrawList();
if (markers_changed) if (markers_changed)
history.RegisterMarkersChange(MODTYPE_MARKER_SHIFT, start_index); history.RegisterMarkersChange(MODTYPE_MARKER_SHIFT, start_index);
} }
@ -338,11 +335,8 @@ void SPLICER::Truncate()
greenzone.InvalidateAndCheck(result); greenzone.InvalidateAndCheck(result);
} else } else
{ {
// check special case: user truncated empty frames of the movie // check for special case: user truncated empty frames of the movie
if (greenzone.greenZoneCount >= currMovieData.getNumRecords()) greenzone.InvalidateAndCheck(currMovieData.getNumRecords() - 1);
greenzone.InvalidateAndCheck(currMovieData.getNumRecords()-1);
else
piano_roll.RedrawList();
if (markers_changed) if (markers_changed)
history.RegisterMarkersChange(MODTYPE_MARKER_REMOVE, frame+1, last_frame_was); history.RegisterMarkersChange(MODTYPE_MARKER_REMOVE, frame+1, last_frame_was);
} }

View File

@ -40,12 +40,11 @@ void TASEDITOR_LUA::init()
{ {
pending_changes.resize(0); pending_changes.resize(0);
hwndRunFunction = GetDlgItem(taseditor_window.hwndTasEditor, TASEDITOR_RUN_MANUAL); hwndRunFunction = GetDlgItem(taseditor_window.hwndTasEditor, TASEDITOR_RUN_MANUAL);
TaseditorUpdateManualFunctionStatus();
reset(); reset();
} }
void TASEDITOR_LUA::reset() void TASEDITOR_LUA::reset()
{ {
TaseditorUpdateManualFunctionStatus();
} }
void TASEDITOR_LUA::update() void TASEDITOR_LUA::update()
{ {
@ -237,7 +236,7 @@ int TASEDITOR_LUA::getplaybacktarget()
void TASEDITOR_LUA::setplayback(int frame) void TASEDITOR_LUA::setplayback(int frame)
{ {
if (FCEUMOV_Mode(MOVIEMODE_TASEDITOR)) if (FCEUMOV_Mode(MOVIEMODE_TASEDITOR))
playback.JumpToFrame(frame); // do not trigger lua functions after jump playback.jump(frame, false, true);
} }
// taseditor.stopseeking() // taseditor.stopseeking()
@ -434,12 +433,10 @@ int TASEDITOR_LUA::applyinputchanges(const char* name)
// check actual changes // check actual changes
int result = history.RegisterLuaChanges(name, start_index, InsertionDeletion_was_made); int result = history.RegisterLuaChanges(name, start_index, InsertionDeletion_was_made);
if (result >= 0) if (result >= 0)
{
greenzone.InvalidateAndCheck(result); greenzone.InvalidateAndCheck(result);
} else if (greenzone.greenZoneCount >= currMovieData.getNumRecords()) else
{ // check for special case: user deleted empty frames of the movie
greenzone.InvalidateAndCheck(currMovieData.getNumRecords()-1); greenzone.InvalidateAndCheck(currMovieData.getNumRecords() - 1);
} else piano_roll.RedrawList();
pending_changes.resize(0); pending_changes.resize(0);
return result; return result;

View File

@ -12,9 +12,9 @@ struct PENDING_CHANGES
enum enum
{ {
LUA_CHANGE_TYPE_INPUTCHANGE = 0, LUA_CHANGE_TYPE_INPUTCHANGE,
LUA_CHANGE_TYPE_INSERTFRAMES = 1, LUA_CHANGE_TYPE_INSERTFRAMES,
LUA_CHANGE_TYPE_DELETEFRAMES = 2, LUA_CHANGE_TYPE_DELETEFRAMES,
}; };
enum enum

View File

@ -125,7 +125,7 @@ bool TASEDITOR_PROJECT::save(const char* different_name, bool save_binary, bool
{ {
// change cursor to hourglass // change cursor to hourglass
SetCursor(LoadCursor(0, IDC_WAIT)); SetCursor(LoadCursor(0, IDC_WAIT));
// save fm2 data to the project file
currMovieData.loadFrameCount = currMovieData.records.size(); currMovieData.loadFrameCount = currMovieData.records.size();
currMovieData.emuVersion = FCEU_VERSION_NUMERIC; currMovieData.emuVersion = FCEU_VERSION_NUMERIC;
currMovieData.dump(ofs, save_binary); currMovieData.dump(ofs, save_binary);
@ -172,7 +172,7 @@ bool TASEDITOR_PROJECT::load(char* fullname)
// change cursor to hourglass // change cursor to hourglass
SetCursor(LoadCursor(0, IDC_WAIT)); SetCursor(LoadCursor(0, IDC_WAIT));
// load fm2 data from the project file
MovieData tempMovieData = MovieData(); MovieData tempMovieData = MovieData();
extern bool LoadFM2(MovieData& movieData, EMUFILE* fp, int size, bool stopAfterHeader); extern bool LoadFM2(MovieData& movieData, EMUFILE* fp, int size, bool stopAfterHeader);
if (LoadFM2(tempMovieData, &ifs, ifs.size(), false)) if (LoadFM2(tempMovieData, &ifs, ifs.size(), false))
@ -322,3 +322,4 @@ void TASEDITOR_PROJECT::SheduleNextAutosave()
if (taseditor_config.autosave_period) if (taseditor_config.autosave_period)
next_save_shedule = clock() + taseditor_config.autosave_period * AUTOSAVE_PERIOD_SCALE; next_save_shedule = clock() + taseditor_config.autosave_period * AUTOSAVE_PERIOD_SCALE;
} }

View File

@ -53,8 +53,6 @@ public:
void SheduleNextAutosave(); void SheduleNextAutosave();
// public vars
private: private:
bool changed; bool changed;
int next_save_shedule; int next_save_shedule;

View File

@ -350,7 +350,7 @@ void TASEDITOR_WINDOW::update()
{ {
if (timeline_branch == branch_under_mouse) if (timeline_branch == branch_under_mouse)
break; break;
timeline_branch = branches.parents[timeline_branch]; timeline_branch = branches.GetParentOf(timeline_branch);
} }
if (timeline_branch == ITEM_UNDER_MOUSE_CLOUD) if (timeline_branch == ITEM_UNDER_MOUSE_CLOUD)
// branch_under_mouse wasn't found in current timeline // branch_under_mouse wasn't found in current timeline
@ -358,7 +358,6 @@ void TASEDITOR_WINDOW::update()
} }
} }
} }
break; break;
} }
case DRAG_MODE_PLAYBACK: case DRAG_MODE_PLAYBACK:
@ -1064,7 +1063,7 @@ BOOL CALLBACK WndprocTasEditor(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lPara
if (new_capacity < taseditor_config.greenzone_capacity) if (new_capacity < taseditor_config.greenzone_capacity)
{ {
taseditor_config.greenzone_capacity = new_capacity; taseditor_config.greenzone_capacity = new_capacity;
greenzone.GreenzoneCleaning(); greenzone.RunGreenzoneCleaning();
} else taseditor_config.greenzone_capacity = new_capacity; } else taseditor_config.greenzone_capacity = new_capacity;
} }
break; break;