* Taseditor: changed the order of "Select between Markers"
* Taseditor: applying PAL and PPU flags when loading projects * Taseditor: much better way of calculating Branches Tree; hinting full timelines * Taseditor: miniarrow showing current Playback cursor position in Branches Tree * Taseditor: "Bookmark#" modtype, undo/redo works for Bookmarks * Taseditor: version data in fm3 * fixed HUD/messages dumping in AVI [[Split portion of a mixed commit.]]
This commit is contained in:
parent
91d5c1f076
commit
f79d4f9a3f
|
@ -434,28 +434,20 @@ bool FCEUI_AviIsRecording()
|
|||
{
|
||||
if(avi_file)
|
||||
return true;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
bool FCEUI_AviEnableHUDrecording()
|
||||
{
|
||||
if (enableHUDrecording)
|
||||
return true;
|
||||
|
||||
return false;
|
||||
return enableHUDrecording;
|
||||
}
|
||||
void FCEUI_SetAviEnableHUDrecording(bool enable)
|
||||
{
|
||||
enableHUDrecording = enable;
|
||||
}
|
||||
|
||||
bool FCEUI_AviDisableMovieMessages()
|
||||
{
|
||||
if (disableMovieMessages)
|
||||
return true;
|
||||
|
||||
return false;
|
||||
return disableMovieMessages;
|
||||
}
|
||||
void FCEUI_SetAviDisableMovieMessages(bool disable)
|
||||
{
|
||||
|
|
|
@ -62,8 +62,8 @@ extern uint8 gNoBGFillColor;
|
|||
extern bool rightClickEnabled;
|
||||
extern int CurrentState;
|
||||
extern bool pauseWhileActive; //adelikat: Cheats dialog
|
||||
extern bool AVIenableHUDrecording;
|
||||
extern bool AVIdisableMovieMessages;
|
||||
extern bool enableHUDrecording;
|
||||
extern bool disableMovieMessages;
|
||||
extern bool replaceP2StartWithMicrophone;
|
||||
extern bool SingleInstanceOnly;
|
||||
extern bool oldInputDisplay;
|
||||
|
@ -389,8 +389,8 @@ static CFGSTRUCT fceuconfig[] = {
|
|||
AC(backupSavestates),
|
||||
AC(compressSavestates),
|
||||
AC(pauseWhileActive),
|
||||
AC(AVIenableHUDrecording),
|
||||
AC(AVIdisableMovieMessages),
|
||||
AC(enableHUDrecording),
|
||||
AC(disableMovieMessages),
|
||||
AC(replaceP2StartWithMicrophone),
|
||||
AC(SingleInstanceOnly),
|
||||
|
||||
|
|
Binary file not shown.
Before Width: | Height: | Size: 23 KiB After Width: | Height: | Size: 23 KiB |
|
@ -49,6 +49,10 @@ EDITOR editor;
|
|||
|
||||
extern int joysticks_per_frame[NUM_SUPPORTED_INPUT_TYPES];
|
||||
extern bool turbo;
|
||||
extern int pal_emulation;
|
||||
extern int newppu;
|
||||
extern void PushCurrentVideoSettings();
|
||||
extern void RefreshThrottleFPS();
|
||||
// temporarily saved FCEUX config
|
||||
int saved_eoptions;
|
||||
int saved_EnableAutosave;
|
||||
|
@ -122,8 +126,8 @@ bool EnterTasEditor()
|
|||
// ensure that movie has correct set of ports/fourscore
|
||||
SetInputType(currMovieData, GetInputType(currMovieData));
|
||||
// force the input configuration stored in the movie to apply to FCEUX config
|
||||
FCEUD_SetInput(currMovieData.fourscore, currMovieData.microphone, (ESI)currMovieData.ports[0], (ESI)currMovieData.ports[1], (ESIFC)currMovieData.ports[2]);
|
||||
// reset some modules that need MovidData info
|
||||
ApplyMovieInputConfig();
|
||||
// reset some modules that need MovieData info
|
||||
piano_roll.reset();
|
||||
recorder.reset();
|
||||
// create initial snapshot in history
|
||||
|
@ -366,8 +370,8 @@ bool LoadProject(char* fullname)
|
|||
// try to load project
|
||||
if (project.load(fullname))
|
||||
{
|
||||
// update FCEUX input config
|
||||
FCEUD_SetInput(currMovieData.fourscore, currMovieData.microphone, (ESI)currMovieData.ports[0], (ESI)currMovieData.ports[1], (ESIFC)currMovieData.ports[2]);
|
||||
// loaded successfully
|
||||
ApplyMovieInputConfig();
|
||||
// add new file to Recent menu
|
||||
taseditor_window.UpdateRecentProjectsArray(fullname);
|
||||
taseditor_window.RedrawTaseditor();
|
||||
|
@ -749,6 +753,19 @@ void SetInputType(MovieData& md, int new_input_type)
|
|||
}
|
||||
}
|
||||
|
||||
void ApplyMovieInputConfig()
|
||||
{
|
||||
// update FCEUX input config
|
||||
FCEUD_SetInput(currMovieData.fourscore, currMovieData.microphone, (ESI)currMovieData.ports[0], (ESI)currMovieData.ports[1], (ESIFC)currMovieData.ports[2]);
|
||||
// update PAL flag
|
||||
pal_emulation = currMovieData.palFlag;
|
||||
FCEUI_SetVidSystem(pal_emulation);
|
||||
RefreshThrottleFPS();
|
||||
PushCurrentVideoSettings();
|
||||
// update PPU type
|
||||
newppu = currMovieData.PPUflag;
|
||||
}
|
||||
|
||||
// this getter contains formula to decide whether to record or replay movie
|
||||
bool TaseditorIsRecording()
|
||||
{
|
||||
|
|
|
@ -26,5 +26,7 @@ void Export();
|
|||
int GetInputType(MovieData& md);
|
||||
void SetInputType(MovieData& md, int new_input_type);
|
||||
|
||||
void ApplyMovieInputConfig();
|
||||
|
||||
bool TaseditorIsRecording();
|
||||
|
||||
|
|
|
@ -27,13 +27,40 @@ extern uint8 *XBackBuf;
|
|||
|
||||
BOOKMARK::BOOKMARK()
|
||||
{
|
||||
not_empty = false;
|
||||
}
|
||||
|
||||
void BOOKMARK::init()
|
||||
{
|
||||
free();
|
||||
}
|
||||
void BOOKMARK::free()
|
||||
{
|
||||
not_empty = false;
|
||||
flash_type = flash_phase = 0;
|
||||
snapshot.jump_frame = -1;
|
||||
SNAPSHOT tmp;
|
||||
snapshot = tmp;
|
||||
savestate.resize(0);
|
||||
saved_screenshot.resize(0);
|
||||
}
|
||||
|
||||
bool BOOKMARK::checkDiffFromCurrent()
|
||||
{
|
||||
// check if the Bookmark data differs from current project/MovieData/Markers/settings
|
||||
if (not_empty && snapshot.jump_frame == currFrameCounter)
|
||||
{
|
||||
if (snapshot.size == currMovieData.getNumRecords() && snapshot.findFirstChange(currMovieData) < 0)
|
||||
{
|
||||
if (!snapshot.MarkersDifferFromCurrent())
|
||||
{
|
||||
if (snapshot.has_hot_changes == taseditor_config.enable_hot_changes)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
void BOOKMARK::set()
|
||||
|
@ -94,7 +121,7 @@ bool BOOKMARK::load(EMUFILE *is)
|
|||
{
|
||||
uint8 tmp;
|
||||
if (!read8le(&tmp, is)) return true;
|
||||
not_empty = tmp != 0;
|
||||
not_empty = (tmp != 0);
|
||||
if (not_empty)
|
||||
{
|
||||
// read snapshot
|
||||
|
@ -108,11 +135,33 @@ bool BOOKMARK::load(EMUFILE *is)
|
|||
if (!read32le(&size, is)) return true;
|
||||
saved_screenshot.resize(size);
|
||||
if ((int)is->fread(&saved_screenshot[0], size) < size) return true;
|
||||
} else
|
||||
{
|
||||
free();
|
||||
}
|
||||
// all ok
|
||||
flash_type = flash_phase = 0;
|
||||
return false;
|
||||
}
|
||||
bool BOOKMARK::skipLoad(EMUFILE *is)
|
||||
{
|
||||
uint8 tmp;
|
||||
if (!read8le(&tmp, is)) return true;
|
||||
if (tmp != 0)
|
||||
{
|
||||
// read snapshot
|
||||
if (snapshot.skipLoad(is)) return true;
|
||||
// read savestate
|
||||
int size;
|
||||
if (!read32le(&size, is)) return true;
|
||||
if (is->fseek(size, SEEK_CUR)) return true;
|
||||
// read saved_screenshot
|
||||
if (!read32le(&size, is)) return true;
|
||||
if (is->fseek(size, SEEK_CUR)) return true;
|
||||
}
|
||||
// all ok
|
||||
return false;
|
||||
}
|
||||
// ----------------------------------------------------------
|
||||
|
||||
|
||||
|
|
|
@ -19,13 +19,16 @@ class BOOKMARK
|
|||
public:
|
||||
BOOKMARK();
|
||||
void init();
|
||||
void free();
|
||||
|
||||
bool checkDiffFromCurrent();
|
||||
void set();
|
||||
void jumped();
|
||||
void deployed();
|
||||
|
||||
void save(EMUFILE *os);
|
||||
bool load(EMUFILE *is);
|
||||
bool skipLoad(EMUFILE *is);
|
||||
|
||||
// saved vars
|
||||
bool not_empty;
|
||||
|
|
|
@ -169,7 +169,7 @@ void BOOKMARKS::update()
|
|||
if (bookmarks_array[i].flash_phase != FLASH_PHASE_BUTTONHELD)
|
||||
{
|
||||
bookmarks_array[i].flash_phase = FLASH_PHASE_BUTTONHELD;
|
||||
RedrawBookmarksRow((i + TOTAL_BOOKMARKS - 1) % TOTAL_BOOKMARKS);
|
||||
RedrawBookmark(i);
|
||||
branches.must_redraw_branches_tree = true; // because border of branch digit has changed
|
||||
}
|
||||
} else
|
||||
|
@ -177,7 +177,7 @@ void BOOKMARKS::update()
|
|||
if (bookmarks_array[i].flash_phase > 0)
|
||||
{
|
||||
bookmarks_array[i].flash_phase--;
|
||||
RedrawBookmarksRow((i + TOTAL_BOOKMARKS - 1) % TOTAL_BOOKMARKS);
|
||||
RedrawBookmark(i);
|
||||
branches.must_redraw_branches_tree = true; // because border of branch digit has changed
|
||||
}
|
||||
}
|
||||
|
@ -233,41 +233,36 @@ void BOOKMARKS::set(int slot)
|
|||
markers_manager.UpdateMarkerNote();
|
||||
|
||||
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)
|
||||
if (bookmarks_array[slot].checkDiffFromCurrent())
|
||||
{
|
||||
strncpy(saved_time, bookmarks_array[slot].snapshot.description, TIME_DESC_LENGTH - 1);
|
||||
saved_time[TIME_DESC_LENGTH - 1] = 0;
|
||||
} else
|
||||
{
|
||||
saved_time[0] = 0;
|
||||
}
|
||||
// write current MovieData to the slot
|
||||
bookmarks_array[slot].set();
|
||||
// find its new place in Branches Tree
|
||||
int old_current_branch = branches.GetCurrentBranch();
|
||||
branches.HandleBookmarkSet(slot, saved_time);
|
||||
if (slot != old_current_branch && old_current_branch != ITEM_UNDER_MOUSE_CLOUD)
|
||||
{
|
||||
// current_branch was switched to slot, redraw Bookmarks List to change the color of digits
|
||||
piano_roll.RedrawRow(bookmarks_array[old_current_branch].snapshot.jump_frame);
|
||||
RedrawChangedBookmarks(bookmarks_array[old_current_branch].snapshot.jump_frame);
|
||||
}
|
||||
// also redraw List rows
|
||||
if (previous_frame >= 0 && previous_frame != currFrameCounter)
|
||||
{
|
||||
piano_roll.RedrawRow(previous_frame);
|
||||
RedrawChangedBookmarks(previous_frame);
|
||||
}
|
||||
piano_roll.RedrawRow(currFrameCounter);
|
||||
RedrawChangedBookmarks(currFrameCounter);
|
||||
// if screenshot of the slot is currently shown - reinit and redraw the picture
|
||||
if (popup_display.screenshot_currently_shown == slot)
|
||||
popup_display.screenshot_currently_shown = ITEM_UNDER_MOUSE_NONE;
|
||||
BOOKMARK backup_copy(bookmarks_array[slot]);
|
||||
bookmarks_array[slot].set();
|
||||
// rebuild Branches Tree
|
||||
int old_current_branch = branches.GetCurrentBranch();
|
||||
branches.HandleBookmarkSet(slot);
|
||||
if (slot != old_current_branch && old_current_branch != ITEM_UNDER_MOUSE_CLOUD)
|
||||
{
|
||||
// current_branch was switched to slot, redraw Bookmarks List to change the color of digits
|
||||
piano_roll.RedrawRow(bookmarks_array[old_current_branch].snapshot.jump_frame);
|
||||
RedrawChangedBookmarks(bookmarks_array[old_current_branch].snapshot.jump_frame);
|
||||
}
|
||||
// also redraw List rows
|
||||
if (previous_frame >= 0 && previous_frame != currFrameCounter)
|
||||
{
|
||||
piano_roll.RedrawRow(previous_frame);
|
||||
RedrawChangedBookmarks(previous_frame);
|
||||
}
|
||||
piano_roll.RedrawRow(currFrameCounter);
|
||||
RedrawChangedBookmarks(currFrameCounter);
|
||||
// if screenshot of the slot is currently shown - reinit and redraw the picture
|
||||
if (popup_display.screenshot_currently_shown == slot)
|
||||
popup_display.screenshot_currently_shown = ITEM_UNDER_MOUSE_NONE;
|
||||
|
||||
project.SetProjectChanged();
|
||||
FCEU_DispMessage("Branch %d saved.", 0, slot);
|
||||
history.RegisterBookmarkSet(slot, backup_copy, old_current_branch);
|
||||
project.SetProjectChanged();
|
||||
must_check_item_under_mouse = true;
|
||||
FCEU_DispMessage("Branch %d saved.", 0, slot);
|
||||
}
|
||||
}
|
||||
|
||||
void BOOKMARKS::jump(int slot)
|
||||
|
@ -294,7 +289,7 @@ void BOOKMARKS::deploy(int slot)
|
|||
if (!bookmarks_array[slot].not_empty) return;
|
||||
|
||||
int jump_frame = bookmarks_array[slot].snapshot.jump_frame;
|
||||
|
||||
int old_current_branch = branches.GetCurrentBranch();
|
||||
bool markers_changed = false;
|
||||
// revert current movie to the snapshot state
|
||||
if (taseditor_config.branch_full_movie)
|
||||
|
@ -317,13 +312,13 @@ void BOOKMARKS::deploy(int slot)
|
|||
bookmarks_array[slot].snapshot.toMovie(currMovieData, first_change);
|
||||
piano_roll.UpdateItemCount();
|
||||
selection.must_find_current_marker = playback.must_find_current_marker = true;
|
||||
history.RegisterBranching(MODTYPE_BRANCH_0 + slot, first_change, slot);
|
||||
history.RegisterBranching(MODTYPE_BRANCH_0 + slot, first_change, slot, old_current_branch);
|
||||
greenzone.Invalidate(first_change);
|
||||
bookmarks_array[slot].deployed();
|
||||
} else if (markers_changed)
|
||||
{
|
||||
selection.must_find_current_marker = playback.must_find_current_marker = true;
|
||||
history.RegisterBranching(MODTYPE_BRANCH_MARKERS_0 + slot, first_change, slot);
|
||||
history.RegisterBranching(MODTYPE_BRANCH_MARKERS_0 + slot, first_change, slot, old_current_branch);
|
||||
piano_roll.RedrawList();
|
||||
bookmarks_array[slot].deployed();
|
||||
} else
|
||||
|
@ -352,13 +347,13 @@ void BOOKMARKS::deploy(int slot)
|
|||
bookmarks_array[slot].snapshot.toMovie(currMovieData, first_change, jump_frame-1);
|
||||
piano_roll.UpdateItemCount();
|
||||
selection.must_find_current_marker = playback.must_find_current_marker = true;
|
||||
history.RegisterBranching(MODTYPE_BRANCH_0 + slot, first_change, slot);
|
||||
history.RegisterBranching(MODTYPE_BRANCH_0 + slot, first_change, slot, old_current_branch);
|
||||
greenzone.Invalidate(first_change);
|
||||
bookmarks_array[slot].deployed();
|
||||
} else if (markers_changed)
|
||||
{
|
||||
selection.must_find_current_marker = playback.must_find_current_marker = true;
|
||||
history.RegisterBranching(MODTYPE_BRANCH_MARKERS_0 + slot, first_change, slot);
|
||||
history.RegisterBranching(MODTYPE_BRANCH_MARKERS_0 + slot, first_change, slot, old_current_branch);
|
||||
piano_roll.RedrawList();
|
||||
bookmarks_array[slot].deployed();
|
||||
} else
|
||||
|
@ -369,24 +364,20 @@ void BOOKMARKS::deploy(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 (greenzone.greenZoneCount <= 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
|
||||
if (greenzone.greenZoneCount <= jump_frame)
|
||||
{
|
||||
for (int i = greenzone.greenZoneCount; i < jump_frame; ++i)
|
||||
greenzone.ClearSavestate(i);
|
||||
greenzone.greenZoneCount = jump_frame+1;
|
||||
}
|
||||
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;
|
||||
}
|
||||
greenzone.update();
|
||||
|
||||
// switch current branch to this branch
|
||||
int old_current_branch = branches.GetCurrentBranch();
|
||||
branches.HandleBookmarkDeploy(slot);
|
||||
if (slot != old_current_branch && old_current_branch != ITEM_UNDER_MOUSE_CLOUD)
|
||||
{
|
||||
|
@ -419,8 +410,14 @@ void BOOKMARKS::save(EMUFILE *os, bool really_save)
|
|||
}
|
||||
}
|
||||
// returns true if couldn't load
|
||||
bool BOOKMARKS::load(EMUFILE *is)
|
||||
bool BOOKMARKS::load(EMUFILE *is, bool really_load)
|
||||
{
|
||||
if (!really_load)
|
||||
{
|
||||
reset();
|
||||
branches.reset();
|
||||
return false;
|
||||
}
|
||||
// read "BOOKMARKS" string
|
||||
char save_id[BOOKMARKS_ID_LEN];
|
||||
if ((int)is->fread(save_id, BOOKMARKS_ID_LEN) < BOOKMARKS_ID_LEN) goto error;
|
||||
|
@ -474,22 +471,26 @@ void BOOKMARKS::RedrawBookmarksCaption()
|
|||
must_check_item_under_mouse = true;
|
||||
SetWindowText(hwndBookmarks, bookmarksCaption[edit_mode]);
|
||||
}
|
||||
void BOOKMARKS::RedrawBookmarksList()
|
||||
void BOOKMARKS::RedrawBookmarksList(bool erase_bg)
|
||||
{
|
||||
if (edit_mode != EDIT_MODE_BRANCHES)
|
||||
InvalidateRect(hwndBookmarksList, 0, FALSE);
|
||||
InvalidateRect(hwndBookmarksList, 0, erase_bg);
|
||||
}
|
||||
void BOOKMARKS::RedrawChangedBookmarks(int frame)
|
||||
{
|
||||
for (int i = 0; i < TOTAL_BOOKMARKS; ++i)
|
||||
{
|
||||
if (bookmarks_array[i].snapshot.jump_frame == frame)
|
||||
RedrawBookmarksRow((i + TOTAL_BOOKMARKS - 1) % TOTAL_BOOKMARKS);
|
||||
RedrawBookmark(i);
|
||||
}
|
||||
}
|
||||
void BOOKMARKS::RedrawBookmarksRow(int index)
|
||||
void BOOKMARKS::RedrawBookmark(int bookmark_number)
|
||||
{
|
||||
ListView_RedrawItems(hwndBookmarksList, index, index);
|
||||
RedrawListRow((bookmark_number + TOTAL_BOOKMARKS - 1) % TOTAL_BOOKMARKS);
|
||||
}
|
||||
void BOOKMARKS::RedrawListRow(int row_index)
|
||||
{
|
||||
ListView_RedrawItems(hwndBookmarksList, row_index, row_index);
|
||||
}
|
||||
|
||||
void BOOKMARKS::MouseMove(int new_x, int new_y)
|
||||
|
@ -578,7 +579,7 @@ LONG BOOKMARKS::CustomDraw(NMLVCUSTOMDRAW* msg)
|
|||
{
|
||||
if (!greenzone.savestates[frame].empty())
|
||||
{
|
||||
if (taseditor_config.show_lag_frames && greenzone.lag_history[frame])
|
||||
if (taseditor_config.show_lag_frames && greenzone.GetLagHistoryAtFrame(frame))
|
||||
msg->clrTextBk = LAG_FRAMENUM_COLOR;
|
||||
else
|
||||
msg->clrTextBk = GREENZONE_FRAMENUM_COLOR;
|
||||
|
@ -587,7 +588,7 @@ LONG BOOKMARKS::CustomDraw(NMLVCUSTOMDRAW* msg)
|
|||
|| (!greenzone.savestates[frame & EVERY4TH].empty() && (int)greenzone.savestates.size() > (frame | 0x3) + 1 && !greenzone.savestates[(frame | 0x3) + 1].empty())
|
||||
|| (!greenzone.savestates[frame & EVERY2ND].empty() && !greenzone.savestates[(frame | 0x1) + 1].empty()))
|
||||
{
|
||||
if (taseditor_config.show_lag_frames && greenzone.lag_history[frame])
|
||||
if (taseditor_config.show_lag_frames && greenzone.GetLagHistoryAtFrame(frame))
|
||||
msg->clrTextBk = PALE_LAG_FRAMENUM_COLOR;
|
||||
else
|
||||
msg->clrTextBk = PALE_GREENZONE_FRAMENUM_COLOR;
|
||||
|
@ -609,7 +610,7 @@ LONG BOOKMARKS::CustomDraw(NMLVCUSTOMDRAW* msg)
|
|||
{
|
||||
if (!greenzone.savestates[frame].empty())
|
||||
{
|
||||
if (taseditor_config.show_lag_frames && greenzone.lag_history[frame])
|
||||
if (taseditor_config.show_lag_frames && greenzone.GetLagHistoryAtFrame(frame))
|
||||
msg->clrTextBk = LAG_INPUT_COLOR1;
|
||||
else
|
||||
msg->clrTextBk = GREENZONE_INPUT_COLOR1;
|
||||
|
@ -618,7 +619,7 @@ LONG BOOKMARKS::CustomDraw(NMLVCUSTOMDRAW* msg)
|
|||
|| (!greenzone.savestates[frame & EVERY4TH].empty() && (int)greenzone.savestates.size() > (frame | 0x3) + 1 && !greenzone.savestates[(frame | 0x3) + 1].empty())
|
||||
|| (!greenzone.savestates[frame & EVERY2ND].empty() && !greenzone.savestates[(frame | 0x1) + 1].empty()))
|
||||
{
|
||||
if (taseditor_config.show_lag_frames && greenzone.lag_history[frame])
|
||||
if (taseditor_config.show_lag_frames && greenzone.GetLagHistoryAtFrame(frame))
|
||||
msg->clrTextBk = PALE_LAG_INPUT_COLOR1;
|
||||
else
|
||||
msg->clrTextBk = PALE_GREENZONE_INPUT_COLOR1;
|
||||
|
@ -651,7 +652,8 @@ int BOOKMARKS::FindBookmarkAtFrame(int frame)
|
|||
return current_branch + TOTAL_BOOKMARKS; // blue digit has highest priority when drawing
|
||||
for (int i = 0; i < TOTAL_BOOKMARKS; ++i)
|
||||
{
|
||||
if (bookmarks_array[i].snapshot.jump_frame == frame) return i; // green digit
|
||||
if (bookmarks_array[i].not_empty && bookmarks_array[i].snapshot.jump_frame == frame)
|
||||
return i; // green digit
|
||||
}
|
||||
return -1; // no Bookmarks at the frame
|
||||
}
|
||||
|
|
|
@ -54,7 +54,7 @@ public:
|
|||
void update();
|
||||
|
||||
void save(EMUFILE *os, bool really_save = true);
|
||||
bool load(EMUFILE *is);
|
||||
bool load(EMUFILE *is, bool really_load = true);
|
||||
|
||||
void command(int command_id, int slot = -1);
|
||||
|
||||
|
@ -66,9 +66,10 @@ public:
|
|||
int FindBookmarkAtFrame(int frame);
|
||||
|
||||
void RedrawBookmarksCaption();
|
||||
void RedrawBookmarksList();
|
||||
void RedrawBookmarksList(bool erase_bg = false);
|
||||
void RedrawChangedBookmarks(int frame);
|
||||
void RedrawBookmarksRow(int index);
|
||||
void RedrawBookmark(int bookmark_number);
|
||||
void RedrawListRow(int row_index);
|
||||
|
||||
void MouseMove(int new_x, int new_y);
|
||||
void FindItemUnderMouse();
|
||||
|
|
|
@ -11,18 +11,19 @@ Branches - Manager of Branches
|
|||
[Singleton]
|
||||
|
||||
* stores info about Branches (relations of Bookmarks) and the id of current Branch
|
||||
* also stores the time of the last modification (see fireball) and the time of the root of Branches Tree (see cloudlet)
|
||||
* finds best place for every new Bookmark in the Branches Tree
|
||||
* also stores the time of the last modification (see fireball) and the time of project beginning (see cloudlet)
|
||||
* also caches data used in calculations (cached_first_difference, cached_timelines)
|
||||
* saves and loads the data from a project file. On error: sends warning to caller
|
||||
* implements the working of Branches Tree: creating, recalculating relations, animating, redrawing, mouseover
|
||||
* on demand: reacts on project changes and recalculates Branches Tree
|
||||
* regularly updates animations in Branches Tree
|
||||
* on demand: reacts on Bookmarks/current Movie changes and recalculates the Branches Tree
|
||||
* regularly updates animations in Branches Tree and calculates Playback cursor position on the Tree
|
||||
* stores resources: coordinates for building Branches Tree, animation timings
|
||||
------------------------------------------------------------------------------------ */
|
||||
|
||||
#include "taseditor_project.h"
|
||||
#include "utils/xstring.h"
|
||||
#include "zlib.h"
|
||||
#include <math.h>
|
||||
|
||||
#pragma comment(lib, "msimg32.lib")
|
||||
|
||||
|
@ -81,6 +82,7 @@ void BRANCHES::init()
|
|||
hOldBitmap2 = (HBITMAP)SelectObject(hSpritesheetDC, branchesSpritesheet);
|
||||
// create pens
|
||||
normal_pen = CreatePen(PS_SOLID, 1, 0x0);
|
||||
timeline_pen = CreatePen(PS_SOLID, 1, 0x0020E0);
|
||||
select_pen = CreatePen(PS_SOLID, 2, 0xFF9080);
|
||||
|
||||
reset();
|
||||
|
@ -91,6 +93,8 @@ void BRANCHES::init()
|
|||
void BRANCHES::free()
|
||||
{
|
||||
parents.resize(0);
|
||||
cached_first_difference.resize(0);
|
||||
cached_timelines.resize(0);
|
||||
BranchX.resize(0);
|
||||
BranchY.resize(0);
|
||||
BranchPrevX.resize(0);
|
||||
|
@ -131,6 +135,21 @@ void BRANCHES::free()
|
|||
DeleteObject(branchesSpritesheet);
|
||||
branchesSpritesheet = NULL;
|
||||
}
|
||||
if (normal_pen)
|
||||
{
|
||||
DeleteObject(normal_pen);
|
||||
normal_pen = 0;
|
||||
}
|
||||
if (timeline_pen)
|
||||
{
|
||||
DeleteObject(normal_pen);
|
||||
timeline_pen = 0;
|
||||
}
|
||||
if (select_pen)
|
||||
{
|
||||
DeleteObject(normal_pen);
|
||||
select_pen = 0;
|
||||
}
|
||||
}
|
||||
void BRANCHES::reset()
|
||||
{
|
||||
|
@ -138,14 +157,24 @@ void BRANCHES::reset()
|
|||
for (int i = TOTAL_BOOKMARKS-1; i >= 0; i--)
|
||||
parents[i] = ITEM_UNDER_MOUSE_CLOUD;
|
||||
|
||||
cached_timelines.resize(TOTAL_BOOKMARKS);
|
||||
cached_first_difference.resize(TOTAL_BOOKMARKS);
|
||||
for (int i = TOTAL_BOOKMARKS-1; i >= 0; i--)
|
||||
{
|
||||
cached_timelines[i] = ITEM_UNDER_MOUSE_CLOUD;
|
||||
cached_first_difference[i].resize(TOTAL_BOOKMARKS);
|
||||
for (int t = TOTAL_BOOKMARKS-1; t >= 0; t--)
|
||||
cached_first_difference[i][t] = FIRST_DIFFERENCE_UNKNOWN;
|
||||
}
|
||||
|
||||
// set positions of slots to default coordinates
|
||||
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;
|
||||
CloudX = CloudPrevX = BRANCHES_CLOUD_X;
|
||||
cursor_x = cursor_y = 0;
|
||||
|
||||
reset_vars();
|
||||
|
||||
|
@ -160,6 +189,7 @@ void BRANCHES::reset()
|
|||
void BRANCHES::reset_vars()
|
||||
{
|
||||
transition_phase = animation_frame = 0;
|
||||
playback_x = playback_y = -50;
|
||||
must_recalculate_branches_tree = must_redraw_branches_tree = true;
|
||||
next_animation_time = clock() + BRANCHES_ANIMATION_TICK;
|
||||
}
|
||||
|
@ -205,6 +235,92 @@ void BRANCHES::update()
|
|||
// just update sprites
|
||||
InvalidateRect(bookmarks.hwndBranchesBitmap, 0, FALSE);
|
||||
}
|
||||
// calculate playback position
|
||||
int branch, branch_x, branch_y, parent, parent_x, parent_y, upper_frame, lower_frame;
|
||||
double distance;
|
||||
if (current_branch != ITEM_UNDER_MOUSE_CLOUD)
|
||||
{
|
||||
if (changes_since_current_branch)
|
||||
parent = TOTAL_BOOKMARKS;
|
||||
else
|
||||
parent = FindFullTimelineForBranch(current_branch);
|
||||
do
|
||||
{
|
||||
branch = parent;
|
||||
if (branch == TOTAL_BOOKMARKS)
|
||||
parent = current_branch;
|
||||
else
|
||||
parent = parents[branch];
|
||||
if (parent == ITEM_UNDER_MOUSE_CLOUD)
|
||||
lower_frame = -1;
|
||||
else
|
||||
lower_frame = bookmarks.bookmarks_array[parent].snapshot.jump_frame;
|
||||
} while (parent != ITEM_UNDER_MOUSE_CLOUD && currFrameCounter < lower_frame);
|
||||
if (branch == TOTAL_BOOKMARKS)
|
||||
upper_frame = currMovieData.getNumRecords() - 1;
|
||||
else
|
||||
upper_frame = bookmarks.bookmarks_array[branch].snapshot.jump_frame;
|
||||
branch_x = BranchCurrX[branch];
|
||||
branch_y = BranchCurrY[branch];
|
||||
if (parent == ITEM_UNDER_MOUSE_CLOUD)
|
||||
{
|
||||
parent_x = cloud_x;
|
||||
parent_y = BRANCHES_CLOUD_Y;
|
||||
} else
|
||||
{
|
||||
parent_x = BranchCurrX[parent];
|
||||
parent_y = BranchCurrY[parent];
|
||||
}
|
||||
if (upper_frame != lower_frame)
|
||||
distance = (double)(currFrameCounter - lower_frame) / (double)(upper_frame - lower_frame);
|
||||
else
|
||||
distance = 0;
|
||||
if (distance > 1.0) distance = 1.0;
|
||||
playback_x = parent_x + distance * (branch_x - parent_x);
|
||||
playback_y = parent_y + distance * (branch_y - parent_y);
|
||||
} else
|
||||
{
|
||||
if (changes_since_current_branch)
|
||||
{
|
||||
// special case: there's only cloud + fireball
|
||||
upper_frame = currMovieData.getNumRecords() - 1;
|
||||
lower_frame = 0;
|
||||
parent_x = cloud_x;
|
||||
parent_y = BRANCHES_CLOUD_Y;
|
||||
branch_x = BranchCurrX[TOTAL_BOOKMARKS];
|
||||
branch_y = BranchCurrY[TOTAL_BOOKMARKS];
|
||||
if (upper_frame != lower_frame)
|
||||
distance = (double)(currFrameCounter - lower_frame) / (double)(upper_frame - lower_frame);
|
||||
else
|
||||
distance = 0;
|
||||
if (distance > 1.0) distance = 1.0;
|
||||
playback_x = parent_x + distance * (branch_x - parent_x);
|
||||
playback_y = parent_y + distance * (branch_y - parent_y);
|
||||
} else
|
||||
{
|
||||
// special case: there's only cloud
|
||||
playback_x = cloud_x;
|
||||
playback_y = BRANCHES_CLOUD_Y;
|
||||
}
|
||||
}
|
||||
// move cursor to playback position
|
||||
double dx = playback_x - cursor_x;
|
||||
double dy = playback_y - cursor_y;
|
||||
distance = sqrt(dx*dx + dy*dy);
|
||||
if (distance < CURSOR_MIN_DISTANCE || distance > CURSOR_MAX_DISTANCE)
|
||||
{
|
||||
// teleport
|
||||
cursor_x = playback_x;
|
||||
cursor_y = playback_y;
|
||||
} else
|
||||
{
|
||||
// advance
|
||||
double speed = sqrt(distance);
|
||||
if (speed < CURSOR_MIN_SPEED)
|
||||
speed = CURSOR_MIN_SPEED;
|
||||
cursor_x += dx * speed / distance;
|
||||
cursor_y += dy * speed / distance;
|
||||
}
|
||||
if (must_redraw_branches_tree)
|
||||
RedrawBranchesTree();
|
||||
}
|
||||
|
@ -226,6 +342,12 @@ void BRANCHES::save(EMUFILE *os)
|
|||
// write all 10 parents
|
||||
for (int i = 0; i < TOTAL_BOOKMARKS; ++i)
|
||||
write32le(parents[i], os);
|
||||
// write cached_timelines
|
||||
os->fwrite(&cached_timelines[0], TOTAL_BOOKMARKS);
|
||||
// write cached_first_difference
|
||||
for (int i = 0; i < TOTAL_BOOKMARKS; ++i)
|
||||
for (int t = 0; t < TOTAL_BOOKMARKS; ++t)
|
||||
write32le(cached_first_difference[i][t], os);
|
||||
}
|
||||
// returns true if couldn't load
|
||||
bool BRANCHES::load(EMUFILE *is)
|
||||
|
@ -242,6 +364,12 @@ bool BRANCHES::load(EMUFILE *is)
|
|||
// read all 10 parents
|
||||
for (int i = 0; i < TOTAL_BOOKMARKS; ++i)
|
||||
if (!read32le(&parents[i], is)) goto error;
|
||||
// read cached_timelines
|
||||
if ((int)is->fread(&cached_timelines[0], TOTAL_BOOKMARKS) < TOTAL_BOOKMARKS) goto error;
|
||||
// read cached_first_difference
|
||||
for (int i = 0; i < TOTAL_BOOKMARKS; ++i)
|
||||
for (int t = 0; t < TOTAL_BOOKMARKS; ++t)
|
||||
if (!read32le(&cached_first_difference[i][t], is)) goto error;
|
||||
// all ok
|
||||
reset_vars();
|
||||
return false;
|
||||
|
@ -272,7 +400,7 @@ void BRANCHES::RedrawBranchesTree()
|
|||
GradientFill(hBitmapDC, vertex, 2, &gRect, 1, GRADIENT_FILL_RECT_H);
|
||||
|
||||
// lines
|
||||
int branch_x, branch_y, parent_x, parent_y, child_id;
|
||||
int branch, branch_x, branch_y, parent_x, parent_y, child_id;
|
||||
SelectObject(hBitmapDC, normal_pen);
|
||||
for (int t = Children.size() - 1; t >= 0; t--)
|
||||
{
|
||||
|
@ -295,40 +423,72 @@ void BRANCHES::RedrawBranchesTree()
|
|||
}
|
||||
}
|
||||
}
|
||||
// lines for item under mouse
|
||||
SelectObject(hBitmapDC, select_pen);
|
||||
int branch = bookmarks.item_under_mouse;
|
||||
if (branch == TOTAL_BOOKMARKS)
|
||||
branch = current_branch;
|
||||
while (branch >= 0)
|
||||
// lines for current timeline
|
||||
if (current_branch != ITEM_UNDER_MOUSE_CLOUD)
|
||||
{
|
||||
branch_x = BranchCurrX[branch];
|
||||
branch_y = BranchCurrY[branch];
|
||||
MoveToEx(hBitmapDC, branch_x, branch_y, 0);
|
||||
branch = parents[branch];
|
||||
if (branch >= 0)
|
||||
SelectObject(hBitmapDC, timeline_pen);
|
||||
if (changes_since_current_branch)
|
||||
branch = current_branch;
|
||||
else
|
||||
branch = FindFullTimelineForBranch(current_branch);
|
||||
while (branch >= 0)
|
||||
{
|
||||
branch_x = BranchCurrX[branch];
|
||||
branch_x = BranchCurrX[branch];
|
||||
branch_y = BranchCurrY[branch];
|
||||
} else
|
||||
{
|
||||
branch_x = cloud_x;
|
||||
branch_y = BRANCHES_CLOUD_Y;
|
||||
MoveToEx(hBitmapDC, branch_x, branch_y, 0);
|
||||
branch = parents[branch];
|
||||
if (branch == ITEM_UNDER_MOUSE_CLOUD)
|
||||
{
|
||||
branch_x = cloud_x;
|
||||
branch_y = BRANCHES_CLOUD_Y;
|
||||
} else
|
||||
{
|
||||
branch_x = BranchCurrX[branch];
|
||||
branch_y = BranchCurrY[branch];
|
||||
}
|
||||
LineTo(hBitmapDC, branch_x, branch_y);
|
||||
}
|
||||
}
|
||||
// lines for item under mouse
|
||||
if (bookmarks.item_under_mouse >= 0 && bookmarks.item_under_mouse <= TOTAL_BOOKMARKS)
|
||||
{
|
||||
SelectObject(hBitmapDC, select_pen);
|
||||
if (bookmarks.item_under_mouse == TOTAL_BOOKMARKS)
|
||||
branch = current_branch;
|
||||
else
|
||||
branch = FindFullTimelineForBranch(bookmarks.item_under_mouse);
|
||||
while (branch >= 0)
|
||||
{
|
||||
branch_x = BranchCurrX[branch];
|
||||
branch_y = BranchCurrY[branch];
|
||||
MoveToEx(hBitmapDC, branch_x, branch_y, 0);
|
||||
branch = parents[branch];
|
||||
if (branch == ITEM_UNDER_MOUSE_CLOUD)
|
||||
{
|
||||
branch_x = cloud_x;
|
||||
branch_y = BRANCHES_CLOUD_Y;
|
||||
} else
|
||||
{
|
||||
branch_x = BranchCurrX[branch];
|
||||
branch_y = BranchCurrY[branch];
|
||||
}
|
||||
LineTo(hBitmapDC, branch_x, branch_y);
|
||||
}
|
||||
LineTo(hBitmapDC, branch_x, branch_y);
|
||||
}
|
||||
if (changes_since_current_branch)
|
||||
{
|
||||
if (bookmarks.item_under_mouse != TOTAL_BOOKMARKS)
|
||||
SelectObject(hBitmapDC, normal_pen);
|
||||
if (current_branch >= 0)
|
||||
{
|
||||
parent_x = BranchCurrX[current_branch];
|
||||
parent_y = BranchCurrY[current_branch];
|
||||
} else
|
||||
if (bookmarks.item_under_mouse == TOTAL_BOOKMARKS)
|
||||
SelectObject(hBitmapDC, select_pen);
|
||||
else
|
||||
SelectObject(hBitmapDC, timeline_pen);
|
||||
if (current_branch == ITEM_UNDER_MOUSE_CLOUD)
|
||||
{
|
||||
parent_x = cloud_x;
|
||||
parent_y = BRANCHES_CLOUD_Y;
|
||||
} else
|
||||
{
|
||||
parent_x = BranchCurrX[current_branch];
|
||||
parent_y = BranchCurrY[current_branch];
|
||||
}
|
||||
MoveToEx(hBitmapDC, parent_x, parent_y, 0);
|
||||
branch_x = BranchCurrX[TOTAL_BOOKMARKS];
|
||||
|
@ -440,26 +600,27 @@ void BRANCHES::PaintBranchesBitmap(HDC hdc)
|
|||
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);
|
||||
}
|
||||
}
|
||||
// blinking Playback cursor point
|
||||
if (animation_frame & 1)
|
||||
TransparentBlt(hBufferDC, playback_x - BRANCHES_MINIARROW_HALFWIDTH, playback_y - BRANCHES_MINIARROW_HALFHEIGHT, BRANCHES_MINIARROW_WIDTH, BRANCHES_MINIARROW_HEIGHT, hSpritesheetDC, BRANCHES_MINIARROW_SPRITESHEET_X, BRANCHES_MINIARROW_SPRITESHEET_Y, BRANCHES_MINIARROW_WIDTH, BRANCHES_MINIARROW_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;
|
||||
corner_x = cursor_x - current_corners_cursor_shift - BRANCHES_CORNER_HALFWIDTH;
|
||||
corner_y = cursor_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;
|
||||
corner_x = cursor_x + current_corners_cursor_shift - BRANCHES_CORNER_HALFWIDTH;
|
||||
corner_y = cursor_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;
|
||||
corner_x = cursor_x - current_corners_cursor_shift - BRANCHES_CORNER_HALFWIDTH;
|
||||
corner_y = cursor_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;
|
||||
corner_x = cursor_x + current_corners_cursor_shift - BRANCHES_CORNER_HALFWIDTH;
|
||||
corner_y = cursor_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);
|
||||
|
@ -469,104 +630,19 @@ int BRANCHES::GetCurrentBranch()
|
|||
{
|
||||
return current_branch;
|
||||
}
|
||||
|
||||
// this function finds best place for a new Bookmark in the Branches Tree
|
||||
void BRANCHES::HandleBookmarkSet(int slot, char* slot_time)
|
||||
bool BRANCHES::GetChangesSinceCurrentBranch()
|
||||
{
|
||||
if (slot != current_branch)
|
||||
{
|
||||
// inherit current branch, forget previous parent
|
||||
int parent = parents[slot];
|
||||
if (parent == ITEM_UNDER_MOUSE_CLOUD && slot_time[0])
|
||||
{
|
||||
// check if this was 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.bookmarks_array[i].not_empty && parents[i] == ITEM_UNDER_MOUSE_CLOUD && i != slot)
|
||||
break;
|
||||
}
|
||||
if (i >= TOTAL_BOOKMARKS)
|
||||
// didn't find another child of cloud, so after this slot disconnects, cloud will have 0 children
|
||||
// it will mean that old cloud disappears and new cloud is formed where the slot was
|
||||
strcpy(cloud_time, slot_time);
|
||||
}
|
||||
// before disconnecting from old parent, connect all childs to the old parent
|
||||
for (int i = 0; i < TOTAL_BOOKMARKS; ++i)
|
||||
{
|
||||
if (bookmarks.bookmarks_array[i].not_empty && parents[i] == slot)
|
||||
parents[i] = parent;
|
||||
}
|
||||
parents[slot] = current_branch;
|
||||
}
|
||||
return changes_since_current_branch;
|
||||
}
|
||||
|
||||
// if parent is invalid (first_change < parent.jump_frame) then find better parent
|
||||
int factor = 0;
|
||||
// also if parent == cloud, then try to find better parent
|
||||
int parent = parents[slot];
|
||||
if (parent != ITEM_UNDER_MOUSE_CLOUD)
|
||||
factor = bookmarks.bookmarks_array[slot].snapshot.findFirstChange(bookmarks.bookmarks_array[parent].snapshot);
|
||||
if (parent == ITEM_UNDER_MOUSE_CLOUD || (factor >= 0 && factor < bookmarks.bookmarks_array[parent].snapshot.jump_frame))
|
||||
{
|
||||
// find highest frame of change
|
||||
std::vector<int> DecisiveFactor(TOTAL_BOOKMARKS);
|
||||
int best_branch = ITEM_UNDER_MOUSE_CLOUD;
|
||||
for (int i = TOTAL_BOOKMARKS-1; i >= 0; i--)
|
||||
{
|
||||
if (i != slot && i != parent && bookmarks.bookmarks_array[i].not_empty && bookmarks.bookmarks_array[slot].snapshot.size >= bookmarks.bookmarks_array[i].snapshot.jump_frame)
|
||||
{
|
||||
factor = bookmarks.bookmarks_array[slot].snapshot.findFirstChange(bookmarks.bookmarks_array[i].snapshot);
|
||||
if (factor < 0)
|
||||
{
|
||||
// this branch is identical to this slot
|
||||
DecisiveFactor[i] = 2 * bookmarks.bookmarks_array[i].snapshot.size;
|
||||
} else if (factor >= bookmarks.bookmarks_array[i].snapshot.jump_frame)
|
||||
{
|
||||
// hey, this branch could be our new parent...
|
||||
DecisiveFactor[i] = 2 * factor;
|
||||
} else
|
||||
DecisiveFactor[i] = 0;
|
||||
} else
|
||||
{
|
||||
DecisiveFactor[i] = 0;
|
||||
}
|
||||
}
|
||||
// add +1 as a bonus to current parents and grandparents (a bit of nepotism here)
|
||||
while (parent >= 0)
|
||||
{
|
||||
if (DecisiveFactor[parent])
|
||||
DecisiveFactor[parent]++;
|
||||
parent = parents[parent];
|
||||
}
|
||||
// find max
|
||||
factor = 0;
|
||||
for (int i = TOTAL_BOOKMARKS-1; i >= 0; i--)
|
||||
{
|
||||
if (DecisiveFactor[i] && DecisiveFactor[i] > factor)
|
||||
{
|
||||
factor = DecisiveFactor[i];
|
||||
best_branch = i;
|
||||
}
|
||||
}
|
||||
parent = parents[slot];
|
||||
if (parent != best_branch)
|
||||
{
|
||||
// before disconnecting from old parent, connect all childs to the old parent
|
||||
for (int i = 0; i < TOTAL_BOOKMARKS; ++i)
|
||||
{
|
||||
if (bookmarks.bookmarks_array[i].not_empty && parents[i] == slot)
|
||||
parents[i] = parent;
|
||||
}
|
||||
// found new parent
|
||||
parents[slot] = best_branch;
|
||||
must_recalculate_branches_tree = true;
|
||||
}
|
||||
}
|
||||
// switch current branch to this branch
|
||||
if (slot != current_branch || changes_since_current_branch)
|
||||
must_recalculate_branches_tree = true;
|
||||
void BRANCHES::HandleBookmarkSet(int slot)
|
||||
{
|
||||
// new Branch is written into the slot
|
||||
InvalidateBranchSlot(slot);
|
||||
RecalculateParents();
|
||||
current_branch = slot;
|
||||
changes_since_current_branch = false;
|
||||
must_recalculate_branches_tree = true;
|
||||
}
|
||||
void BRANCHES::HandleBookmarkDeploy(int slot)
|
||||
{
|
||||
|
@ -574,6 +650,101 @@ void BRANCHES::HandleBookmarkDeploy(int slot)
|
|||
changes_since_current_branch = false;
|
||||
must_recalculate_branches_tree = true;
|
||||
}
|
||||
void BRANCHES::HandleHistoryJump(int new_current_branch, bool new_changes_since_current_branch)
|
||||
{
|
||||
RecalculateParents();
|
||||
current_branch = new_current_branch;
|
||||
changes_since_current_branch = new_changes_since_current_branch;
|
||||
if (new_changes_since_current_branch)
|
||||
SetCurrentPosTime();
|
||||
must_recalculate_branches_tree = true;
|
||||
}
|
||||
|
||||
void BRANCHES::InvalidateBranchSlot(int slot)
|
||||
{
|
||||
for (int i = TOTAL_BOOKMARKS-1; i >= 0; i--)
|
||||
{
|
||||
cached_timelines[i] = ITEM_UNDER_MOUSE_CLOUD;
|
||||
cached_first_difference[i][slot] = FIRST_DIFFERENCE_UNKNOWN;
|
||||
cached_first_difference[slot][i] = FIRST_DIFFERENCE_UNKNOWN;
|
||||
parents[i] = ITEM_UNDER_MOUSE_CLOUD;
|
||||
}
|
||||
}
|
||||
// returns the frame of first difference between snapshots of two Branches
|
||||
int BRANCHES::GetFirstDifference(int first_branch, int second_branch)
|
||||
{
|
||||
if (first_branch == second_branch)
|
||||
return bookmarks.bookmarks_array[first_branch].snapshot.size;
|
||||
|
||||
if (cached_first_difference[first_branch][second_branch] == FIRST_DIFFERENCE_UNKNOWN)
|
||||
{
|
||||
if (bookmarks.bookmarks_array[first_branch].not_empty && bookmarks.bookmarks_array[second_branch].not_empty)
|
||||
{
|
||||
int frame = bookmarks.bookmarks_array[first_branch].snapshot.findFirstChange(bookmarks.bookmarks_array[second_branch].snapshot);
|
||||
if (frame < 0)
|
||||
frame = bookmarks.bookmarks_array[first_branch].snapshot.size;
|
||||
cached_first_difference[first_branch][second_branch] = frame;
|
||||
cached_first_difference[second_branch][first_branch] = frame;
|
||||
return frame;
|
||||
} else return 0;
|
||||
} else
|
||||
return cached_first_difference[first_branch][second_branch];
|
||||
}
|
||||
|
||||
int BRANCHES::FindFullTimelineForBranch(int branch_num)
|
||||
{
|
||||
if (cached_timelines[branch_num] == ITEM_UNDER_MOUSE_CLOUD)
|
||||
{
|
||||
cached_timelines[branch_num] = branch_num; // by default
|
||||
std::vector<int> candidates;
|
||||
int temp_jump_frame, temp_parent, max_jump_frame, max_first_difference;
|
||||
// 1 - find max_first_difference among Branches that are in the same timeline
|
||||
max_first_difference = -1;
|
||||
int first_diff;
|
||||
for (int i = TOTAL_BOOKMARKS-1; i >= 0; i--)
|
||||
{
|
||||
if (i != branch_num && bookmarks.bookmarks_array[i].not_empty)
|
||||
{
|
||||
first_diff = GetFirstDifference(branch_num, i);
|
||||
if (first_diff >= bookmarks.bookmarks_array[i].snapshot.jump_frame)
|
||||
if (max_first_difference < first_diff)
|
||||
max_first_difference = first_diff;
|
||||
}
|
||||
}
|
||||
// 2 - find max_jump_frame among those Branches whose first_diff >= max_first_difference
|
||||
max_jump_frame = -1;
|
||||
for (int i = TOTAL_BOOKMARKS-1; i >= 0; i--)
|
||||
{
|
||||
if (bookmarks.bookmarks_array[i].not_empty)
|
||||
{
|
||||
if (i != branch_num && GetFirstDifference(branch_num, i) >= max_first_difference && GetFirstDifference(branch_num, i) >= bookmarks.bookmarks_array[i].snapshot.jump_frame)
|
||||
{
|
||||
// ensure that this candidate belongs to children/grandchildren of current_branch
|
||||
temp_parent = parents[i];
|
||||
while (temp_parent != ITEM_UNDER_MOUSE_CLOUD && temp_parent != branch_num)
|
||||
temp_parent = parents[temp_parent];
|
||||
if (temp_parent == branch_num)
|
||||
{
|
||||
candidates.push_back(i);
|
||||
temp_jump_frame = bookmarks.bookmarks_array[i].snapshot.jump_frame;
|
||||
if (max_jump_frame < temp_jump_frame)
|
||||
max_jump_frame = temp_jump_frame;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
// 3 - remove those candidates who have jump_frame < max_jump_frame
|
||||
for (int i = candidates.size()-1; i >= 0; i--)
|
||||
{
|
||||
if (bookmarks.bookmarks_array[candidates[i]].snapshot.jump_frame < max_jump_frame)
|
||||
candidates.erase(candidates.begin() + i);
|
||||
}
|
||||
// 4 - get first of candidates (if there are many then it will be the Branch with highest id number)
|
||||
if (candidates.size())
|
||||
cached_timelines[branch_num] = candidates[0];
|
||||
}
|
||||
return cached_timelines[branch_num];
|
||||
}
|
||||
|
||||
void BRANCHES::ChangesMadeSinceBranch()
|
||||
{
|
||||
|
@ -592,7 +763,7 @@ void BRANCHES::FindItemUnderMouse(int mouse_x, int mouse_y)
|
|||
int prev_item_under_mouse = bookmarks.item_under_mouse;
|
||||
bookmarks.item_under_mouse = ITEM_UNDER_MOUSE_NONE;
|
||||
for (int i = 0; i < TOTAL_BOOKMARKS; ++i)
|
||||
if (bookmarks.item_under_mouse == ITEM_UNDER_MOUSE_NONE && mouse_x >= BranchCurrX[i] - DIGIT_RECT_HALFWIDTH_COLLISION && mouse_x < BranchCurrX[i] - DIGIT_RECT_HALFWIDTH_COLLISION + DIGIT_RECT_WIDTH_COLLISION && mouse_y >= BranchCurrY[i] - DIGIT_RECT_HALFHEIGHT_COLLISION && mouse_y < BranchCurrY[i] - DIGIT_RECT_HALFHEIGHT_COLLISION + DIGIT_RECT_HEIGHT_COLLISION)
|
||||
if (bookmarks.item_under_mouse == ITEM_UNDER_MOUSE_NONE && bookmarks.bookmarks_array[i].not_empty && mouse_x >= BranchCurrX[i] - DIGIT_RECT_HALFWIDTH_COLLISION && mouse_x < BranchCurrX[i] - DIGIT_RECT_HALFWIDTH_COLLISION + DIGIT_RECT_WIDTH_COLLISION && mouse_y >= BranchCurrY[i] - DIGIT_RECT_HALFHEIGHT_COLLISION && mouse_y < BranchCurrY[i] - DIGIT_RECT_HALFHEIGHT_COLLISION + DIGIT_RECT_HEIGHT_COLLISION)
|
||||
bookmarks.item_under_mouse = i;
|
||||
if (bookmarks.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)
|
||||
bookmarks.item_under_mouse = ITEM_UNDER_MOUSE_CLOUD;
|
||||
|
@ -610,6 +781,62 @@ void BRANCHES::SetCurrentPosTime()
|
|||
strftime(current_pos_time, TIME_DESC_LENGTH, "%H:%M:%S", timeinfo);
|
||||
}
|
||||
|
||||
void BRANCHES::RecalculateParents()
|
||||
{
|
||||
// find best parent for every Branch
|
||||
std::vector<int> candidates;
|
||||
int temp_jump_frame, temp_parent, max_jump_frame, max_first_difference;
|
||||
for (int i = TOTAL_BOOKMARKS-1; i >= 0; i--)
|
||||
{
|
||||
if (bookmarks.bookmarks_array[i].not_empty)
|
||||
{
|
||||
int jump_frame = bookmarks.bookmarks_array[i].snapshot.jump_frame;
|
||||
// 1 - find all candidates and max_jump_frame among them
|
||||
candidates.resize(0);
|
||||
max_jump_frame = -1;
|
||||
for (int t = TOTAL_BOOKMARKS-1; t >= 0; t--)
|
||||
{
|
||||
temp_jump_frame = bookmarks.bookmarks_array[t].snapshot.jump_frame;
|
||||
if (t != i && bookmarks.bookmarks_array[t].not_empty && temp_jump_frame <= jump_frame && GetFirstDifference(t, i) >= temp_jump_frame)
|
||||
{
|
||||
// ensure that this candidate doesn't belong to children/grandchildren of this Branch
|
||||
temp_parent = parents[t];
|
||||
while (temp_parent != ITEM_UNDER_MOUSE_CLOUD && temp_parent != i)
|
||||
temp_parent = parents[temp_parent];
|
||||
if (temp_parent == ITEM_UNDER_MOUSE_CLOUD)
|
||||
{
|
||||
// all ok, this is a good candidate for being the parent of the Branch
|
||||
candidates.push_back(t);
|
||||
if (max_jump_frame < temp_jump_frame)
|
||||
max_jump_frame = temp_jump_frame;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (candidates.size())
|
||||
{
|
||||
// 2 - remove those candidates who have jump_frame < max_jump_frame
|
||||
// and for those who have jump_frame == max_jump_frame, find max_first_difference
|
||||
max_first_difference = -1;
|
||||
for (int t = candidates.size()-1; t >= 0; t--)
|
||||
{
|
||||
if (bookmarks.bookmarks_array[candidates[t]].snapshot.jump_frame < max_jump_frame)
|
||||
candidates.erase(candidates.begin() + t);
|
||||
else if (max_first_difference < GetFirstDifference(candidates[t], i))
|
||||
max_first_difference = GetFirstDifference(candidates[t], i);
|
||||
}
|
||||
// 3 - remove those candidates who have FirstDifference < max_first_difference
|
||||
for (int t = candidates.size()-1; t >= 0; t--)
|
||||
{
|
||||
if (GetFirstDifference(candidates[t], i) < max_first_difference)
|
||||
candidates.erase(candidates.begin() + t);
|
||||
}
|
||||
// 4 - get first of candidates (if there are many then it will be the Branch with highest id number)
|
||||
if (candidates.size())
|
||||
parents[i] = candidates[0];
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
void BRANCHES::RecalculateBranchesTree()
|
||||
{
|
||||
// save previous values
|
||||
|
@ -619,8 +846,6 @@ void BRANCHES::RecalculateBranchesTree()
|
|||
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
|
||||
|
@ -853,9 +1078,6 @@ void BRANCHES::RecalculateBranchesTree()
|
|||
if (bookmarks.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;
|
||||
|
@ -887,6 +1109,7 @@ void BRANCHES::RecursiveSetYPos(int parent, int parentY)
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------------------------
|
||||
LRESULT APIENTRY BranchesBitmapWndProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam)
|
||||
{
|
||||
|
|
|
@ -2,6 +2,9 @@
|
|||
|
||||
#define BRANCHES_ANIMATION_TICK 50 // animate at 20FPS
|
||||
#define BRANCHES_TRANSITION_MAX 8
|
||||
#define CURSOR_MIN_DISTANCE 1.0
|
||||
#define CURSOR_MAX_DISTANCE 256.0
|
||||
#define CURSOR_MIN_SPEED 1.0
|
||||
|
||||
// branches bitmap
|
||||
#define BRANCHES_BITMAP_WIDTH 170
|
||||
|
@ -70,7 +73,15 @@
|
|||
#define BRANCHES_CORNER3_SPRITESHEET_Y 7
|
||||
#define BRANCHES_CORNER4_SPRITESHEET_X 213
|
||||
#define BRANCHES_CORNER4_SPRITESHEET_Y 7
|
||||
#define BRANCHES_CORNER_BASE_SHIFT 6
|
||||
#define BRANCHES_CORNER_BASE_SHIFT 5
|
||||
#define BRANCHES_MINIARROW_SPRITESHEET_X 180
|
||||
#define BRANCHES_MINIARROW_SPRITESHEET_Y 15
|
||||
#define BRANCHES_MINIARROW_WIDTH 3
|
||||
#define BRANCHES_MINIARROW_HALFWIDTH BRANCHES_MINIARROW_WIDTH/2
|
||||
#define BRANCHES_MINIARROW_HEIGHT 5
|
||||
#define BRANCHES_MINIARROW_HALFHEIGHT BRANCHES_MINIARROW_HEIGHT/2
|
||||
|
||||
#define FIRST_DIFFERENCE_UNKNOWN -2
|
||||
|
||||
class BRANCHES
|
||||
{
|
||||
|
@ -86,20 +97,28 @@ public:
|
|||
bool load(EMUFILE *is);
|
||||
|
||||
int GetCurrentBranch();
|
||||
bool GetChangesSinceCurrentBranch();
|
||||
|
||||
void RedrawBranchesTree();
|
||||
void PaintBranchesBitmap(HDC hdc);
|
||||
|
||||
void HandleBookmarkSet(int slot, char* slot_time);
|
||||
void HandleBookmarkSet(int slot);
|
||||
void HandleBookmarkDeploy(int slot);
|
||||
void HandleHistoryJump(int new_current_branch, bool new_changes_since_current_branch);
|
||||
|
||||
void InvalidateBranchSlot(int slot);
|
||||
int GetFirstDifference(int first_branch, int second_branch);
|
||||
int FindFullTimelineForBranch(int branch_num);
|
||||
void ChangesMadeSinceBranch();
|
||||
|
||||
void FindItemUnderMouse(int mouse_x, int mouse_y);
|
||||
|
||||
void RecalculateParents();
|
||||
void RecalculateBranchesTree();
|
||||
void RecursiveAddHeight(int branch_num, int amount);
|
||||
void RecursiveSetYPos(int parent, int parentY);
|
||||
|
||||
|
||||
// saved vars
|
||||
std::vector<int> parents;
|
||||
|
||||
|
@ -115,10 +134,14 @@ private:
|
|||
bool changes_since_current_branch;
|
||||
char cloud_time[TIME_DESC_LENGTH];
|
||||
char current_pos_time[TIME_DESC_LENGTH];
|
||||
std::vector<std::vector<int>> cached_first_difference;
|
||||
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
|
||||
int animation_frame;
|
||||
int next_animation_time;
|
||||
int playback_x, playback_y;
|
||||
double cursor_x, cursor_y;
|
||||
std::vector<int> BranchX; // in pixels
|
||||
std::vector<int> BranchY;
|
||||
std::vector<int> BranchPrevX;
|
||||
|
@ -126,14 +149,13 @@ private:
|
|||
std::vector<int> BranchCurrX;
|
||||
std::vector<int> BranchCurrY;
|
||||
int CloudX, CloudPrevX, cloud_x;
|
||||
int CursorX, CursorPrevX, CursorY, CursorPrevY;
|
||||
int transition_phase;
|
||||
int fireball_size;
|
||||
|
||||
// GDI stuff
|
||||
HBRUSH normal_brush;
|
||||
RECT temp_rect;
|
||||
HPEN normal_pen, select_pen;
|
||||
HPEN normal_pen, timeline_pen, select_pen;
|
||||
HBITMAP branches_hbitmap, hOldBitmap, buffer_hbitmap, hOldBitmap1, branchesSpritesheet, hOldBitmap2;
|
||||
HDC hBitmapDC, hBufferDC, hSpritesheetDC;
|
||||
|
||||
|
|
|
@ -64,7 +64,7 @@ void GREENZONE::reset()
|
|||
void GREENZONE::update()
|
||||
{
|
||||
// keep memorizing savestates, this function should be called at the end of every frame
|
||||
if (greenZoneCount <= currFrameCounter || (int)savestates.size() <= currFrameCounter || savestates[currFrameCounter].empty())
|
||||
if (greenZoneCount <= currFrameCounter || (int)savestates.size() <= currFrameCounter || savestates[currFrameCounter].empty() || (int)lag_history.size() <= currFrameCounter)
|
||||
CollectCurrentState();
|
||||
|
||||
// run cleaning from time to time
|
||||
|
@ -250,9 +250,15 @@ void GREENZONE::save(EMUFILE *os, bool really_save)
|
|||
}
|
||||
}
|
||||
// returns true if couldn't load
|
||||
bool GREENZONE::load(EMUFILE *is)
|
||||
bool GREENZONE::load(EMUFILE *is, bool really_load)
|
||||
{
|
||||
free();
|
||||
if (!really_load)
|
||||
{
|
||||
reset();
|
||||
playback.StartFromZero(); // reset playback to frame 0
|
||||
return false;
|
||||
}
|
||||
int frame = 0, prev_frame = -1, size = 0;
|
||||
int last_tick = 0;
|
||||
// read "GREENZONE" string
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
|
||||
#define GREENZONE_ID_LEN 10
|
||||
|
||||
#define TIME_BETWEEN_CLEANINGS 15000 // in milliseconds
|
||||
#define TIME_BETWEEN_CLEANINGS 10000 // in milliseconds
|
||||
// greenzone cleaning masks
|
||||
#define EVERY16TH 0xFFFFFFF0
|
||||
#define EVERY8TH 0xFFFFFFF8
|
||||
|
@ -21,7 +21,7 @@ public:
|
|||
void update();
|
||||
|
||||
void save(EMUFILE *os, bool really_save = true);
|
||||
bool load(EMUFILE *is);
|
||||
bool load(EMUFILE *is, bool really_load = true);
|
||||
|
||||
void CollectCurrentState();
|
||||
|
||||
|
@ -38,12 +38,15 @@ public:
|
|||
|
||||
bool GetLagHistoryAtFrame(int frame);
|
||||
|
||||
// data
|
||||
// saved data
|
||||
int greenZoneCount;
|
||||
std::vector<std::vector<uint8>> savestates;
|
||||
std::vector<uint8> lag_history;
|
||||
|
||||
private:
|
||||
// saved data
|
||||
std::vector<uint8> lag_history;
|
||||
|
||||
// not saved data
|
||||
int next_cleaning_time;
|
||||
|
||||
};
|
||||
|
|
|
@ -10,7 +10,7 @@ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLI
|
|||
History - History of movie modifications
|
||||
[Singleton]
|
||||
|
||||
* stores array of snapshots and pointer to current (last) snapshot
|
||||
* stores array of History items (snapshots, backup_bookmarks, backup_current_branch) and pointer to current snapshot
|
||||
* saves and loads the data from a project file. On error: clears the array and starts new history by making snapshot of current movie data
|
||||
* on demand: checks the difference between the last snapshot and current movie, and makes a decision to create new point of rollback. In special cases it can create a point of rollback without checking the difference, assuming that caller already checked it
|
||||
* implements all restoring operations: undo, redo, revert to any snapshot from the array
|
||||
|
@ -35,6 +35,7 @@ extern SELECTION selection;
|
|||
extern GREENZONE greenzone;
|
||||
extern TASEDITOR_PROJECT project;
|
||||
extern PIANO_ROLL piano_roll;
|
||||
extern POPUP_DISPLAY popup_display;
|
||||
extern TASEDITOR_LUA taseditor_lua;
|
||||
|
||||
extern int joysticks_per_frame[NUM_SUPPORTED_INPUT_TYPES];
|
||||
|
@ -44,53 +45,63 @@ extern Window_items_struct window_items[];
|
|||
|
||||
char history_save_id[HISTORY_ID_LEN] = "HISTORY";
|
||||
char history_skipsave_id[HISTORY_ID_LEN] = "HISTORX";
|
||||
char modCaptions[MODTYPES_TOTAL][20] = {" Init Project",
|
||||
" Undefined",
|
||||
" Set",
|
||||
" Unset",
|
||||
" Pattern",
|
||||
" Insert",
|
||||
" Insert#",
|
||||
" Delete",
|
||||
" Truncate",
|
||||
" Clear",
|
||||
" Cut",
|
||||
" Paste",
|
||||
" PasteInsert",
|
||||
" Clone",
|
||||
" Record",
|
||||
" Import",
|
||||
" Branch0 to ",
|
||||
" Branch1 to ",
|
||||
" Branch2 to ",
|
||||
" Branch3 to ",
|
||||
" Branch4 to ",
|
||||
" Branch5 to ",
|
||||
" Branch6 to ",
|
||||
" Branch7 to ",
|
||||
" Branch8 to ",
|
||||
" Branch9 to ",
|
||||
" Marker Branch0 to ",
|
||||
" Marker Branch1 to ",
|
||||
" Marker Branch2 to ",
|
||||
" Marker Branch3 to ",
|
||||
" Marker Branch4 to ",
|
||||
" Marker Branch5 to ",
|
||||
" Marker Branch6 to ",
|
||||
" Marker Branch7 to ",
|
||||
" Marker Branch8 to ",
|
||||
" Marker Branch9 to ",
|
||||
" Marker Set",
|
||||
" Marker Remove",
|
||||
" Marker Pattern",
|
||||
" Marker Rename",
|
||||
" Marker Drag",
|
||||
" Marker Swap",
|
||||
" Marker Shift",
|
||||
" LUA Marker Set",
|
||||
" LUA Marker Remove",
|
||||
" LUA Marker Rename",
|
||||
" LUA Change" };
|
||||
char modCaptions[MODTYPES_TOTAL][20] = {" Initialization",
|
||||
" Undefined",
|
||||
" Set",
|
||||
" Unset",
|
||||
" Pattern",
|
||||
" Insert",
|
||||
" Insert#",
|
||||
" Delete",
|
||||
" Truncate",
|
||||
" Clear",
|
||||
" Cut",
|
||||
" Paste",
|
||||
" PasteInsert",
|
||||
" Clone",
|
||||
" Record",
|
||||
" Import",
|
||||
" Bookmark0",
|
||||
" Bookmark1",
|
||||
" Bookmark2",
|
||||
" Bookmark3",
|
||||
" Bookmark4",
|
||||
" Bookmark5",
|
||||
" Bookmark6",
|
||||
" Bookmark7",
|
||||
" Bookmark8",
|
||||
" Bookmark9",
|
||||
" Branch0 to ",
|
||||
" Branch1 to ",
|
||||
" Branch2 to ",
|
||||
" Branch3 to ",
|
||||
" Branch4 to ",
|
||||
" Branch5 to ",
|
||||
" Branch6 to ",
|
||||
" Branch7 to ",
|
||||
" Branch8 to ",
|
||||
" Branch9 to ",
|
||||
" Marker Branch0 to ",
|
||||
" Marker Branch1 to ",
|
||||
" Marker Branch2 to ",
|
||||
" Marker Branch3 to ",
|
||||
" Marker Branch4 to ",
|
||||
" Marker Branch5 to ",
|
||||
" Marker Branch6 to ",
|
||||
" Marker Branch7 to ",
|
||||
" Marker Branch8 to ",
|
||||
" Marker Branch9 to ",
|
||||
" Marker Set",
|
||||
" Marker Remove",
|
||||
" Marker Pattern",
|
||||
" Marker Rename",
|
||||
" Marker Drag",
|
||||
" Marker Swap",
|
||||
" Marker Shift",
|
||||
" LUA Marker Set",
|
||||
" LUA Marker Remove",
|
||||
" LUA Marker Rename",
|
||||
" LUA Change" };
|
||||
char LuaCaptionPrefix[6] = " LUA ";
|
||||
char joypadCaptions[4][5] = {"(1P)", "(2P)", "(3P)", "(4P)"};
|
||||
|
||||
|
@ -114,6 +125,8 @@ void HISTORY::init()
|
|||
void HISTORY::free()
|
||||
{
|
||||
snapshots.resize(0);
|
||||
backup_bookmarks.resize(0);
|
||||
backup_current_branch.resize(0);
|
||||
history_total_items = 0;
|
||||
}
|
||||
void HISTORY::reset()
|
||||
|
@ -124,6 +137,8 @@ void HISTORY::reset()
|
|||
undo_hint_pos = old_undo_hint_pos = undo_hint_time = -1;
|
||||
old_show_undo_hint = show_undo_hint = false;
|
||||
snapshots.resize(history_size);
|
||||
backup_bookmarks.resize(history_size);
|
||||
backup_current_branch.resize(history_size);
|
||||
history_start_pos = 0;
|
||||
history_cursor_pos = -1;
|
||||
// create initial snapshot
|
||||
|
@ -133,7 +148,7 @@ void HISTORY::reset()
|
|||
inp.jump_frame = -1;
|
||||
inp.start_frame = 0;
|
||||
inp.end_frame = inp.size - 1;
|
||||
AddSnapshotToHistory(inp);
|
||||
AddItemToHistory(inp);
|
||||
UpdateHistoryList();
|
||||
RedrawHistoryList();
|
||||
}
|
||||
|
@ -160,26 +175,36 @@ void HISTORY::HistorySizeChanged()
|
|||
{
|
||||
int new_history_size = taseditor_config.undo_levels + 1;
|
||||
std::vector<SNAPSHOT> new_snapshots(new_history_size);
|
||||
std::vector<BOOKMARK> new_backup_bookmarks(new_history_size);
|
||||
std::vector<int8> new_backup_current_branch(new_history_size);
|
||||
int pos = history_cursor_pos, source_pos = history_cursor_pos;
|
||||
if (pos >= new_history_size)
|
||||
pos = new_history_size - 1;
|
||||
int new_history_cursor_pos = pos;
|
||||
// copy old "undo" snapshots
|
||||
// copy old "undo" items
|
||||
while (pos >= 0)
|
||||
{
|
||||
new_snapshots[pos] = snapshots[(history_start_pos + source_pos) % history_size];
|
||||
new_backup_bookmarks[pos] = backup_bookmarks[(history_start_pos + source_pos) % history_size];
|
||||
new_backup_current_branch[pos] = backup_current_branch[(history_start_pos + source_pos) % history_size];
|
||||
pos--;
|
||||
source_pos--;
|
||||
}
|
||||
// copy old "redo" snapshots
|
||||
int num_redo_snapshots = history_total_items - (history_cursor_pos + 1);
|
||||
// copy old "redo" items
|
||||
int num_redo_items = history_total_items - (history_cursor_pos + 1);
|
||||
int space_available = new_history_size - (new_history_cursor_pos + 1);
|
||||
int i = (num_redo_snapshots <= space_available) ? num_redo_snapshots : space_available;
|
||||
int i = (num_redo_items <= space_available) ? num_redo_items : space_available;
|
||||
int new_history_total_items = new_history_cursor_pos + i + 1;
|
||||
for (; i > 0; i--)
|
||||
{
|
||||
new_snapshots[new_history_cursor_pos + i] = snapshots[(history_start_pos + history_cursor_pos + i) % history_size];
|
||||
new_backup_bookmarks[new_history_cursor_pos + i] = backup_bookmarks[(history_start_pos + history_cursor_pos + i) % history_size];
|
||||
new_backup_current_branch[new_history_cursor_pos + i] = backup_current_branch[(history_start_pos + history_cursor_pos + i) % history_size];
|
||||
}
|
||||
// finish
|
||||
snapshots = new_snapshots;
|
||||
backup_bookmarks = new_backup_bookmarks;
|
||||
backup_current_branch = new_backup_current_branch;
|
||||
history_size = new_history_size;
|
||||
history_start_pos = 0;
|
||||
history_cursor_pos = new_history_cursor_pos;
|
||||
|
@ -198,18 +223,119 @@ int HISTORY::jump(int new_pos)
|
|||
// make jump
|
||||
int old_pos = history_cursor_pos;
|
||||
history_cursor_pos = new_pos;
|
||||
int real_pos = (history_start_pos + history_cursor_pos) % history_size;
|
||||
RedrawHistoryList();
|
||||
|
||||
int real_pos, mod_type, slot, current_branch = branches.GetCurrentBranch();
|
||||
bool bookmarks_changed = false, changes_since_current_branch = false;
|
||||
bool old_changes_since_current_branch = branches.GetChangesSinceCurrentBranch();
|
||||
// restore Bookmarks/Branches
|
||||
std::vector<uint8> bookmarks_to_redraw;
|
||||
std::vector<int> frames_to_redraw;
|
||||
if (new_pos > old_pos)
|
||||
{
|
||||
// redo
|
||||
for (int i = old_pos + 1; i <= new_pos; ++i)
|
||||
{
|
||||
real_pos = (history_start_pos + i) % history_size;
|
||||
mod_type = snapshots[real_pos].mod_type;
|
||||
if (mod_type >= MODTYPE_BOOKMARK_0 && mod_type <= MODTYPE_BRANCH_MARKERS_9)
|
||||
{
|
||||
current_branch = (mod_type - MODTYPE_BOOKMARK_0) % TOTAL_BOOKMARKS;
|
||||
changes_since_current_branch = false;
|
||||
} else
|
||||
{
|
||||
changes_since_current_branch = true;
|
||||
}
|
||||
if (mod_type >= MODTYPE_BOOKMARK_0 && mod_type <= MODTYPE_BOOKMARK_9)
|
||||
{
|
||||
// swap Bookmark and its backup version
|
||||
slot = (mod_type - MODTYPE_BOOKMARK_0) % TOTAL_BOOKMARKS;
|
||||
BOOKMARK temp_bookmark(bookmarks.bookmarks_array[slot]);
|
||||
frames_to_redraw.push_back(bookmarks.bookmarks_array[slot].snapshot.jump_frame);
|
||||
bookmarks.bookmarks_array[slot] = backup_bookmarks[real_pos];
|
||||
frames_to_redraw.push_back(bookmarks.bookmarks_array[slot].snapshot.jump_frame);
|
||||
bookmarks_to_redraw.push_back(slot);
|
||||
backup_bookmarks[real_pos] = temp_bookmark;
|
||||
branches.InvalidateBranchSlot(slot);
|
||||
bookmarks_changed = true;
|
||||
}
|
||||
}
|
||||
} else
|
||||
{
|
||||
// undo
|
||||
for (int i = old_pos; i > new_pos; i--)
|
||||
{
|
||||
real_pos = (history_start_pos + i) % history_size;
|
||||
mod_type = snapshots[real_pos].mod_type;
|
||||
if (mod_type >= MODTYPE_BOOKMARK_0 && mod_type <= MODTYPE_BRANCH_MARKERS_9)
|
||||
current_branch = backup_current_branch[real_pos];
|
||||
if (mod_type >= MODTYPE_BOOKMARK_0 && mod_type <= MODTYPE_BOOKMARK_9)
|
||||
{
|
||||
// swap Bookmark and its backup version
|
||||
slot = (mod_type - MODTYPE_BOOKMARK_0) % TOTAL_BOOKMARKS;
|
||||
BOOKMARK temp_bookmark(bookmarks.bookmarks_array[slot]);
|
||||
frames_to_redraw.push_back(bookmarks.bookmarks_array[slot].snapshot.jump_frame);
|
||||
bookmarks.bookmarks_array[slot] = backup_bookmarks[real_pos];
|
||||
frames_to_redraw.push_back(bookmarks.bookmarks_array[slot].snapshot.jump_frame);
|
||||
bookmarks_to_redraw.push_back(slot);
|
||||
backup_bookmarks[real_pos] = temp_bookmark;
|
||||
branches.InvalidateBranchSlot(slot);
|
||||
bookmarks_changed = true;
|
||||
}
|
||||
}
|
||||
real_pos = (history_start_pos + new_pos) % history_size;
|
||||
mod_type = snapshots[real_pos].mod_type;
|
||||
if (mod_type >= MODTYPE_BOOKMARK_0 && mod_type <= MODTYPE_BRANCH_MARKERS_9)
|
||||
{
|
||||
current_branch = (mod_type - MODTYPE_BOOKMARK_0) % TOTAL_BOOKMARKS;
|
||||
changes_since_current_branch = false;
|
||||
} else if (GetCategoryOfOperation(mod_type) != CATEGORY_OTHER)
|
||||
{
|
||||
changes_since_current_branch = true;
|
||||
}
|
||||
}
|
||||
int old_current_branch = branches.GetCurrentBranch();
|
||||
if (bookmarks_changed || current_branch != old_current_branch || changes_since_current_branch != old_changes_since_current_branch)
|
||||
{
|
||||
branches.HandleHistoryJump(current_branch, changes_since_current_branch);
|
||||
if (current_branch != old_current_branch)
|
||||
{
|
||||
// current_branch was switched, redraw Bookmarks List to change the color of digits
|
||||
if (old_current_branch != ITEM_UNDER_MOUSE_CLOUD)
|
||||
{
|
||||
frames_to_redraw.push_back(bookmarks.bookmarks_array[old_current_branch].snapshot.jump_frame);
|
||||
bookmarks_to_redraw.push_back(old_current_branch);
|
||||
}
|
||||
if (current_branch != ITEM_UNDER_MOUSE_CLOUD)
|
||||
{
|
||||
frames_to_redraw.push_back(bookmarks.bookmarks_array[current_branch].snapshot.jump_frame);
|
||||
bookmarks_to_redraw.push_back(current_branch);
|
||||
}
|
||||
}
|
||||
bookmarks.must_check_item_under_mouse = true;
|
||||
project.SetProjectChanged();
|
||||
}
|
||||
// redraw Piano Roll rows and Bookmarks List rows
|
||||
for (int i = frames_to_redraw.size() - 1; i >= 0; i--)
|
||||
piano_roll.RedrawRow(frames_to_redraw[i]);
|
||||
for (int i = bookmarks_to_redraw.size() - 1; i >= 0; i--)
|
||||
{
|
||||
bookmarks.RedrawBookmark(bookmarks_to_redraw[i]);
|
||||
// if screenshot of the slot is currently shown - reinit and redraw the picture
|
||||
if (popup_display.screenshot_currently_shown == bookmarks_to_redraw[i])
|
||||
popup_display.screenshot_currently_shown = ITEM_UNDER_MOUSE_NONE;
|
||||
}
|
||||
|
||||
// create undo_hint
|
||||
if (new_pos > old_pos)
|
||||
undo_hint_pos = GetCurrentSnapshot().jump_frame;
|
||||
undo_hint_pos = GetCurrentSnapshot().jump_frame; // redo
|
||||
else
|
||||
undo_hint_pos = GetNextToCurrentSnapshot().jump_frame;
|
||||
undo_hint_pos = GetNextToCurrentSnapshot().jump_frame; // undo
|
||||
undo_hint_time = clock() + UNDO_HINT_TIME;
|
||||
show_undo_hint = true;
|
||||
|
||||
// update markers
|
||||
real_pos = (history_start_pos + history_cursor_pos) % history_size;
|
||||
// update Markers
|
||||
bool markers_changed = false;
|
||||
if (taseditor_config.bind_markers)
|
||||
{
|
||||
|
@ -221,27 +347,26 @@ int HISTORY::jump(int new_pos)
|
|||
}
|
||||
}
|
||||
|
||||
// update current movie
|
||||
// update current movie data
|
||||
int first_change = snapshots[real_pos].findFirstChange(currMovieData);
|
||||
if (first_change >= 0)
|
||||
{
|
||||
snapshots[real_pos].toMovie(currMovieData, first_change);
|
||||
selection.must_find_current_marker = playback.must_find_current_marker = true;
|
||||
branches.ChangesMadeSinceBranch();
|
||||
// and Piano Roll will be redrawn by greenzone invalidation
|
||||
// Piano Roll Redraw and ProjectChanged will be called by greenzone invalidation
|
||||
} else if (markers_changed)
|
||||
{
|
||||
markers_manager.update();
|
||||
selection.must_find_current_marker = playback.must_find_current_marker = true;
|
||||
branches.ChangesMadeSinceBranch();
|
||||
piano_roll.RedrawList();
|
||||
piano_roll.FollowUndo();
|
||||
project.SetProjectChanged();
|
||||
} else if (taseditor_config.enable_hot_changes)
|
||||
{
|
||||
// when using Hot Changes, Piano Roll should be always redrawn, because old changes become less hot
|
||||
piano_roll.RedrawList();
|
||||
}
|
||||
|
||||
piano_roll.UpdateItemCount();
|
||||
piano_roll.FollowUndo();
|
||||
return first_change;
|
||||
}
|
||||
|
||||
|
@ -249,28 +374,20 @@ void HISTORY::undo()
|
|||
{
|
||||
int result = jump(history_cursor_pos - 1);
|
||||
if (result >= 0)
|
||||
{
|
||||
piano_roll.UpdateItemCount();
|
||||
piano_roll.FollowUndo();
|
||||
greenzone.InvalidateAndCheck(result);
|
||||
}
|
||||
return;
|
||||
}
|
||||
void HISTORY::redo()
|
||||
{
|
||||
int result = jump(history_cursor_pos + 1);
|
||||
if (result >= 0)
|
||||
{
|
||||
piano_roll.UpdateItemCount();
|
||||
piano_roll.FollowUndo();
|
||||
greenzone.InvalidateAndCheck(result);
|
||||
}
|
||||
return;
|
||||
}
|
||||
// ----------------------------
|
||||
void HISTORY::AddSnapshotToHistory(SNAPSHOT &inp)
|
||||
void HISTORY::AddItemToHistory(SNAPSHOT &inp, int cur_branch)
|
||||
{
|
||||
// history uses conveyor of snapshots (vector with fixed size) to aviod resizing which is awfully expensive with such large objects as SNAPSHOT
|
||||
// history uses conveyor of items (vector with fixed size) to aviod frequent resizing, which would be awfully expensive with such large objects as SNAPSHOT and BOOKMARK
|
||||
if (history_total_items >= history_size)
|
||||
{
|
||||
// reached the end of available history_size - move history_start_pos (thus deleting oldest snapshot)
|
||||
|
@ -283,9 +400,33 @@ void HISTORY::AddSnapshotToHistory(SNAPSHOT &inp)
|
|||
history_total_items = history_cursor_pos+1;
|
||||
UpdateHistoryList();
|
||||
}
|
||||
// write snapshot
|
||||
// write data
|
||||
int real_pos = (history_start_pos + history_cursor_pos) % history_size;
|
||||
snapshots[real_pos] = inp;
|
||||
backup_bookmarks[real_pos].free();
|
||||
backup_current_branch[real_pos] = cur_branch;
|
||||
RedrawHistoryList();
|
||||
}
|
||||
void HISTORY::AddItemToHistory(SNAPSHOT &inp, int cur_branch, BOOKMARK &bookm)
|
||||
{
|
||||
// history uses conveyor of items (vector with fixed size) to aviod frequent resizing, which would be awfully expensive with such large objects as SNAPSHOT and BOOKMARK
|
||||
if (history_total_items >= history_size)
|
||||
{
|
||||
// reached the end of available history_size - move history_start_pos (thus deleting oldest snapshot)
|
||||
history_cursor_pos = history_size-1;
|
||||
history_start_pos = (history_start_pos + 1) % history_size;
|
||||
} else
|
||||
{
|
||||
// didn't reach the end of history yet
|
||||
history_cursor_pos++;
|
||||
history_total_items = history_cursor_pos+1;
|
||||
UpdateHistoryList();
|
||||
}
|
||||
// write data
|
||||
int real_pos = (history_start_pos + history_cursor_pos) % history_size;
|
||||
snapshots[real_pos] = inp;
|
||||
backup_bookmarks[real_pos] = bookm;
|
||||
backup_current_branch[real_pos] = cur_branch;
|
||||
RedrawHistoryList();
|
||||
}
|
||||
|
||||
|
@ -414,7 +555,7 @@ int HISTORY::RegisterChanges(int mod_type, int start, int end, const char* comme
|
|||
break;
|
||||
}
|
||||
}
|
||||
AddSnapshotToHistory(inp);
|
||||
AddItemToHistory(inp);
|
||||
}
|
||||
branches.ChangesMadeSinceBranch();
|
||||
}
|
||||
|
@ -448,7 +589,7 @@ int HISTORY::RegisterInsertNum(int start, int frames)
|
|||
// set hotchanges
|
||||
if (taseditor_config.enable_hot_changes)
|
||||
inp.inheritHotChanges_InsertNum(&snapshots[real_pos], start, frames);
|
||||
AddSnapshotToHistory(inp);
|
||||
AddItemToHistory(inp);
|
||||
branches.ChangesMadeSinceBranch();
|
||||
}
|
||||
return first_changes;
|
||||
|
@ -479,7 +620,7 @@ int HISTORY::RegisterPasteInsert(int start, SelectionFrames& inserted_set)
|
|||
// set hotchanges
|
||||
if (taseditor_config.enable_hot_changes)
|
||||
inp.inheritHotChanges_PasteInsert(&snapshots[real_pos], inserted_set);
|
||||
AddSnapshotToHistory(inp);
|
||||
AddItemToHistory(inp);
|
||||
branches.ChangesMadeSinceBranch();
|
||||
}
|
||||
return first_changes;
|
||||
|
@ -520,18 +661,35 @@ void HISTORY::RegisterMarkersChange(int mod_type, int start, int end, const char
|
|||
// input hotchanges aren't changed
|
||||
if (taseditor_config.enable_hot_changes)
|
||||
inp.copyHotChanges(&GetCurrentSnapshot());
|
||||
AddSnapshotToHistory(inp);
|
||||
AddItemToHistory(inp);
|
||||
branches.ChangesMadeSinceBranch();
|
||||
project.SetProjectChanged();
|
||||
}
|
||||
void HISTORY::RegisterBranching(int mod_type, int first_change, int slot)
|
||||
void HISTORY::RegisterBookmarkSet(int slot, BOOKMARK& backup_copy, int old_current_branch)
|
||||
{
|
||||
// create new snapshot
|
||||
SNAPSHOT inp;
|
||||
inp.init(currMovieData, taseditor_config.enable_hot_changes);
|
||||
// fill description: modification type + jump_frame of the Bookmark
|
||||
inp.mod_type = MODTYPE_BOOKMARK_0 + slot;
|
||||
strcat(inp.description, modCaptions[inp.mod_type]);
|
||||
inp.start_frame = inp.end_frame = inp.jump_frame = bookmarks.bookmarks_array[slot].snapshot.jump_frame;
|
||||
char framenum[11];
|
||||
strcat(inp.description, " ");
|
||||
_itoa(inp.jump_frame, framenum, 10);
|
||||
strcat(inp.description, framenum);
|
||||
if (taseditor_config.enable_hot_changes)
|
||||
inp.copyHotChanges(&GetCurrentSnapshot());
|
||||
AddItemToHistory(inp, old_current_branch, backup_copy);
|
||||
}
|
||||
void HISTORY::RegisterBranching(int mod_type, int first_change, int slot, int old_current_branch)
|
||||
{
|
||||
// create new snapshot
|
||||
SNAPSHOT inp;
|
||||
inp.init(currMovieData, taseditor_config.enable_hot_changes);
|
||||
// fill description: modification type + time of the Branch
|
||||
inp.mod_type = mod_type;
|
||||
strcat(inp.description, modCaptions[mod_type]);
|
||||
strcat(inp.description, modCaptions[inp.mod_type]);
|
||||
strcat(inp.description, bookmarks.bookmarks_array[slot].snapshot.description);
|
||||
inp.jump_frame = first_change;
|
||||
inp.start_frame = first_change;
|
||||
|
@ -556,7 +714,7 @@ void HISTORY::RegisterBranching(int mod_type, int first_change, int slot)
|
|||
inp.copyHotChanges(&GetCurrentSnapshot());
|
||||
}
|
||||
}
|
||||
AddSnapshotToHistory(inp);
|
||||
AddItemToHistory(inp, old_current_branch);
|
||||
}
|
||||
void HISTORY::RegisterRecording(int frame_of_change)
|
||||
{
|
||||
|
@ -629,7 +787,7 @@ void HISTORY::RegisterRecording(int frame_of_change)
|
|||
inp.inheritHotChanges(&snapshots[real_pos]);
|
||||
inp.fillHotChanges(snapshots[real_pos], frame_of_change, frame_of_change);
|
||||
}
|
||||
AddSnapshotToHistory(inp);
|
||||
AddItemToHistory(inp);
|
||||
}
|
||||
branches.ChangesMadeSinceBranch();
|
||||
}
|
||||
|
@ -658,7 +816,7 @@ void HISTORY::RegisterImport(MovieData& md, char* filename)
|
|||
// do not inherit old hotchanges, because imported input (most likely) doesn't have direct connection with recent edits, so old hotchanges are irrelevant and should not be copied
|
||||
inp.fillHotChanges(snapshots[real_pos], first_changes);
|
||||
}
|
||||
AddSnapshotToHistory(inp);
|
||||
AddItemToHistory(inp);
|
||||
inp.toMovie(currMovieData);
|
||||
piano_roll.UpdateItemCount();
|
||||
branches.ChangesMadeSinceBranch();
|
||||
|
@ -730,7 +888,7 @@ int HISTORY::RegisterLuaChanges(const char* name, int start, bool InsertionDelet
|
|||
inp.fillHotChanges(snapshots[real_pos], first_changes);
|
||||
}
|
||||
}
|
||||
AddSnapshotToHistory(inp);
|
||||
AddItemToHistory(inp);
|
||||
branches.ChangesMadeSinceBranch();
|
||||
}
|
||||
return first_changes;
|
||||
|
@ -746,11 +904,13 @@ void HISTORY::save(EMUFILE *os, bool really_save)
|
|||
// write vars
|
||||
write32le(history_cursor_pos, os);
|
||||
write32le(history_total_items, os);
|
||||
// write snapshots starting from history_start_pos
|
||||
// write items starting from history_start_pos
|
||||
for (int i = 0; i < history_total_items; ++i)
|
||||
{
|
||||
real_pos = (history_start_pos + i) % history_size;
|
||||
snapshots[real_pos].save(os);
|
||||
backup_bookmarks[real_pos].save(os);
|
||||
os->fwrite(&backup_current_branch[real_pos], 1);
|
||||
playback.SetProgressbar(i, history_total_items);
|
||||
}
|
||||
} else
|
||||
|
@ -760,12 +920,16 @@ void HISTORY::save(EMUFILE *os, bool really_save)
|
|||
}
|
||||
}
|
||||
// returns true if couldn't load
|
||||
bool HISTORY::load(EMUFILE *is)
|
||||
bool HISTORY::load(EMUFILE *is, bool really_load)
|
||||
{
|
||||
if (!really_load)
|
||||
{
|
||||
reset();
|
||||
return false;
|
||||
}
|
||||
int i = -1;
|
||||
SNAPSHOT inp;
|
||||
// delete old snapshots
|
||||
snapshots.resize(history_size);
|
||||
BOOKMARK bookm;
|
||||
// read "HISTORY" string
|
||||
char save_id[HISTORY_ID_LEN];
|
||||
if ((int)is->fread(save_id, HISTORY_ID_LEN) < HISTORY_ID_LEN) goto error;
|
||||
|
@ -777,47 +941,60 @@ bool HISTORY::load(EMUFILE *is)
|
|||
return false;
|
||||
}
|
||||
if (strcmp(history_save_id, save_id)) goto error; // string is not valid
|
||||
// delete old items
|
||||
snapshots.resize(history_size);
|
||||
backup_bookmarks.resize(history_size);
|
||||
backup_current_branch.resize(history_size);
|
||||
// read vars
|
||||
if (!read32le(&history_cursor_pos, is)) goto error;
|
||||
if (!read32le(&history_total_items, is)) goto error;
|
||||
if (history_cursor_pos > history_total_items) goto error;
|
||||
history_start_pos = 0;
|
||||
// read snapshots
|
||||
// read items
|
||||
int total = history_total_items;
|
||||
if (history_total_items > history_size)
|
||||
{
|
||||
// user can't afford that much undo levels, skip some snapshots
|
||||
int num_snapshots_to_skip = history_total_items - history_size;
|
||||
// first try to skip snapshots over history_cursor_pos (future snapshots), because "redo" is less important than "undo"
|
||||
int num_redo_snapshots = history_total_items-1 - history_cursor_pos;
|
||||
if (num_snapshots_to_skip >= num_redo_snapshots)
|
||||
// user can't afford that much undo levels, skip some items
|
||||
int num_items_to_skip = history_total_items - history_size;
|
||||
// first try to skip items over history_cursor_pos (future items), because "redo" is less important than "undo"
|
||||
int num_redo_items = history_total_items-1 - history_cursor_pos;
|
||||
if (num_items_to_skip >= num_redo_items)
|
||||
{
|
||||
// skip all redo snapshots
|
||||
// skip all redo items
|
||||
history_total_items = history_cursor_pos+1;
|
||||
num_snapshots_to_skip -= num_redo_snapshots;
|
||||
// and still need to skip some undo snapshots
|
||||
for (i = 0; i < num_snapshots_to_skip; ++i)
|
||||
num_items_to_skip -= num_redo_items;
|
||||
// and still need to skip some undo items
|
||||
for (i = 0; i < num_items_to_skip; ++i)
|
||||
{
|
||||
if (inp.skipLoad(is)) goto error;
|
||||
total -= num_snapshots_to_skip;
|
||||
history_cursor_pos -= num_snapshots_to_skip;
|
||||
if (bookm.skipLoad(is)) goto error;
|
||||
if (is->fseek(1, SEEK_CUR)) goto error; // backup_current_branch
|
||||
}
|
||||
total -= num_items_to_skip;
|
||||
history_cursor_pos -= num_items_to_skip;
|
||||
}
|
||||
history_total_items -= num_snapshots_to_skip;
|
||||
history_total_items -= num_items_to_skip;
|
||||
}
|
||||
// load snapshots
|
||||
// load items
|
||||
for (i = 0; i < history_total_items; ++i)
|
||||
{
|
||||
if (snapshots[i].load(is)) goto error;
|
||||
if (backup_bookmarks[i].load(is)) goto error;
|
||||
if (is->fread(&backup_current_branch[i], 1) != 1) goto error;
|
||||
playback.SetProgressbar(i, history_total_items);
|
||||
}
|
||||
// skip redo snapshots if needed
|
||||
// skip redo items if needed
|
||||
for (; i < total; ++i)
|
||||
{
|
||||
if (inp.skipLoad(is)) goto error;
|
||||
if (bookm.skipLoad(is)) goto error;
|
||||
if (is->fseek(1, SEEK_CUR)) goto error; // backup_current_branch
|
||||
}
|
||||
|
||||
// everything went well
|
||||
// init vars
|
||||
undo_hint_pos = old_undo_hint_pos = undo_hint_time = -1;
|
||||
old_show_undo_hint = show_undo_hint = false;
|
||||
|
||||
// everything went well
|
||||
UpdateHistoryList();
|
||||
RedrawHistoryList();
|
||||
return false;
|
||||
|
@ -855,14 +1032,8 @@ void HISTORY::Click(int row_index)
|
|||
{
|
||||
int result = jump(row_index);
|
||||
if (result >= 0)
|
||||
{
|
||||
piano_roll.UpdateItemCount();
|
||||
piano_roll.FollowUndo();
|
||||
greenzone.InvalidateAndCheck(result);
|
||||
return;
|
||||
}
|
||||
}
|
||||
RedrawHistoryList();
|
||||
}
|
||||
|
||||
void HISTORY::UpdateHistoryList()
|
||||
|
@ -880,6 +1051,82 @@ void HISTORY::RedrawHistoryList()
|
|||
InvalidateRect(hwndHistoryList, 0, FALSE);
|
||||
}
|
||||
// ----------------------------
|
||||
int HISTORY::GetCategoryOfOperation(int mod_type)
|
||||
{
|
||||
switch (mod_type)
|
||||
{
|
||||
case MODTYPE_INIT:
|
||||
case MODTYPE_UNDEFINED:
|
||||
return CATEGORY_OTHER;
|
||||
case MODTYPE_SET:
|
||||
case MODTYPE_UNSET:
|
||||
case MODTYPE_PATTERN:
|
||||
return CATEGORY_INPUT_CHANGE;
|
||||
case MODTYPE_INSERT:
|
||||
case MODTYPE_INSERTNUM:
|
||||
case MODTYPE_DELETE:
|
||||
case MODTYPE_TRUNCATE:
|
||||
return CATEGORY_INPUT_MARKERS_CHANGE;
|
||||
case MODTYPE_CLEAR:
|
||||
case MODTYPE_CUT:
|
||||
case MODTYPE_PASTE:
|
||||
return CATEGORY_INPUT_CHANGE;
|
||||
case MODTYPE_PASTEINSERT:
|
||||
case MODTYPE_CLONE:
|
||||
return CATEGORY_INPUT_MARKERS_CHANGE;
|
||||
case MODTYPE_RECORD:
|
||||
case MODTYPE_IMPORT:
|
||||
return CATEGORY_INPUT_CHANGE;
|
||||
case MODTYPE_BOOKMARK_0:
|
||||
case MODTYPE_BOOKMARK_1:
|
||||
case MODTYPE_BOOKMARK_2:
|
||||
case MODTYPE_BOOKMARK_3:
|
||||
case MODTYPE_BOOKMARK_4:
|
||||
case MODTYPE_BOOKMARK_5:
|
||||
case MODTYPE_BOOKMARK_6:
|
||||
case MODTYPE_BOOKMARK_7:
|
||||
case MODTYPE_BOOKMARK_8:
|
||||
case MODTYPE_BOOKMARK_9:
|
||||
return CATEGORY_OTHER;
|
||||
case MODTYPE_BRANCH_0:
|
||||
case MODTYPE_BRANCH_1:
|
||||
case MODTYPE_BRANCH_2:
|
||||
case MODTYPE_BRANCH_3:
|
||||
case MODTYPE_BRANCH_4:
|
||||
case MODTYPE_BRANCH_5:
|
||||
case MODTYPE_BRANCH_6:
|
||||
case MODTYPE_BRANCH_7:
|
||||
case MODTYPE_BRANCH_8:
|
||||
case MODTYPE_BRANCH_9:
|
||||
return CATEGORY_INPUT_MARKERS_CHANGE;
|
||||
case MODTYPE_BRANCH_MARKERS_0:
|
||||
case MODTYPE_BRANCH_MARKERS_1:
|
||||
case MODTYPE_BRANCH_MARKERS_2:
|
||||
case MODTYPE_BRANCH_MARKERS_3:
|
||||
case MODTYPE_BRANCH_MARKERS_4:
|
||||
case MODTYPE_BRANCH_MARKERS_5:
|
||||
case MODTYPE_BRANCH_MARKERS_6:
|
||||
case MODTYPE_BRANCH_MARKERS_7:
|
||||
case MODTYPE_BRANCH_MARKERS_8:
|
||||
case MODTYPE_BRANCH_MARKERS_9:
|
||||
case MODTYPE_MARKER_SET:
|
||||
case MODTYPE_MARKER_REMOVE:
|
||||
case MODTYPE_MARKER_PATTERN:
|
||||
case MODTYPE_MARKER_RENAME:
|
||||
case MODTYPE_MARKER_DRAG:
|
||||
case MODTYPE_MARKER_SWAP:
|
||||
case MODTYPE_MARKER_SHIFT:
|
||||
case MODTYPE_LUA_MARKER_SET:
|
||||
case MODTYPE_LUA_MARKER_REMOVE:
|
||||
case MODTYPE_LUA_MARKER_RENAME:
|
||||
return CATEGORY_MARKERS_CHANGE;
|
||||
case MODTYPE_LUA_CHANGE:
|
||||
return CATEGORY_INPUT_MARKERS_CHANGE;
|
||||
}
|
||||
// if undefined
|
||||
return CATEGORY_OTHER;
|
||||
}
|
||||
|
||||
SNAPSHOT& HISTORY::GetCurrentSnapshot()
|
||||
{
|
||||
return snapshots[(history_start_pos + history_cursor_pos) % history_size];
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
|
||||
#define UNDO_HINT_TIME 200
|
||||
|
||||
enum
|
||||
enum MOD_TYPES
|
||||
{
|
||||
MODTYPE_INIT,
|
||||
MODTYPE_UNDEFINED,
|
||||
|
@ -20,6 +20,16 @@ enum
|
|||
MODTYPE_CLONE,
|
||||
MODTYPE_RECORD,
|
||||
MODTYPE_IMPORT,
|
||||
MODTYPE_BOOKMARK_0,
|
||||
MODTYPE_BOOKMARK_1,
|
||||
MODTYPE_BOOKMARK_2,
|
||||
MODTYPE_BOOKMARK_3,
|
||||
MODTYPE_BOOKMARK_4,
|
||||
MODTYPE_BOOKMARK_5,
|
||||
MODTYPE_BOOKMARK_6,
|
||||
MODTYPE_BOOKMARK_7,
|
||||
MODTYPE_BOOKMARK_8,
|
||||
MODTYPE_BOOKMARK_9,
|
||||
MODTYPE_BRANCH_0,
|
||||
MODTYPE_BRANCH_1,
|
||||
MODTYPE_BRANCH_2,
|
||||
|
@ -54,6 +64,17 @@ enum
|
|||
|
||||
MODTYPES_TOTAL
|
||||
};
|
||||
|
||||
enum CATEGORIES_OF_OPERATIONS
|
||||
{
|
||||
CATEGORY_OTHER,
|
||||
CATEGORY_INPUT_CHANGE,
|
||||
CATEGORY_MARKERS_CHANGE,
|
||||
CATEGORY_INPUT_MARKERS_CHANGE,
|
||||
|
||||
CATEGORIES_OF_OPERATIONS_TOTAL
|
||||
};
|
||||
|
||||
#define HISTORY_NORMAL_COLOR 0x000000
|
||||
|
||||
#define WM_MOUSEWHEEL_RESENT WM_APP+123
|
||||
|
@ -72,7 +93,7 @@ public:
|
|||
void HistorySizeChanged();
|
||||
|
||||
void save(EMUFILE *os, bool really_save = true);
|
||||
bool load(EMUFILE *is);
|
||||
bool load(EMUFILE *is, bool really_load = true);
|
||||
|
||||
int jump(int new_pos);
|
||||
|
||||
|
@ -83,11 +104,14 @@ public:
|
|||
int RegisterInsertNum(int start, int frames);
|
||||
int RegisterPasteInsert(int start, SelectionFrames& inserted_set);
|
||||
void RegisterMarkersChange(int mod_type, int start = 0, int end =-1, const char* comment = 0);
|
||||
void RegisterBranching(int mod_type, int first_change, int slot);
|
||||
void RegisterBookmarkSet(int slot, BOOKMARK& backup_copy, int old_current_branch);
|
||||
void RegisterBranching(int mod_type, int first_change, int slot, int old_current_branch);
|
||||
void RegisterRecording(int frame_of_change);
|
||||
void RegisterImport(MovieData& md, char* filename);
|
||||
int RegisterLuaChanges(const char* name, int start, bool InsertionDeletion_was_made);
|
||||
|
||||
int GetCategoryOfOperation(int mod_type);
|
||||
|
||||
SNAPSHOT& GetCurrentSnapshot();
|
||||
SNAPSHOT& GetNextToCurrentSnapshot();
|
||||
char* GetItemDesc(int pos);
|
||||
|
@ -105,9 +129,12 @@ public:
|
|||
HWND hwndHistoryList;
|
||||
|
||||
private:
|
||||
void AddSnapshotToHistory(SNAPSHOT &inp);
|
||||
void AddItemToHistory(SNAPSHOT &inp, int cur_branch = 0);
|
||||
void AddItemToHistory(SNAPSHOT &inp, int cur_branch, BOOKMARK &bookm);
|
||||
|
||||
std::vector<SNAPSHOT> snapshots;
|
||||
std::vector<BOOKMARK> backup_bookmarks;
|
||||
std::vector<int8> backup_current_branch;
|
||||
|
||||
int history_cursor_pos;
|
||||
int history_start_pos;
|
||||
|
|
|
@ -80,8 +80,13 @@ void MARKERS_MANAGER::save(EMUFILE *os, bool really_save)
|
|||
}
|
||||
}
|
||||
// returns true if couldn't load
|
||||
bool MARKERS_MANAGER::load(EMUFILE *is)
|
||||
bool MARKERS_MANAGER::load(EMUFILE *is, bool really_load)
|
||||
{
|
||||
if (!really_load)
|
||||
{
|
||||
reset();
|
||||
return false;
|
||||
}
|
||||
// read "MARKERS" string
|
||||
char save_id[MARKERS_ID_LEN];
|
||||
if ((int)is->fread(save_id, MARKERS_ID_LEN) < MARKERS_ID_LEN) goto error;
|
||||
|
|
|
@ -32,7 +32,7 @@ public:
|
|||
void update();
|
||||
|
||||
void save(EMUFILE *os, bool really_save = true);
|
||||
bool load(EMUFILE *is);
|
||||
bool load(EMUFILE *is, bool really_load = true);
|
||||
|
||||
int GetMarkersSize();
|
||||
bool SetMarkersSize(int new_size);
|
||||
|
|
|
@ -717,10 +717,16 @@ void PIANO_ROLL::save(EMUFILE *os, bool really_save)
|
|||
}
|
||||
}
|
||||
// returns true if couldn't load
|
||||
bool PIANO_ROLL::load(EMUFILE *is)
|
||||
bool PIANO_ROLL::load(EMUFILE *is, bool really_load)
|
||||
{
|
||||
reset();
|
||||
update();
|
||||
if (!really_load)
|
||||
{
|
||||
// scroll to the beginning
|
||||
ListView_EnsureVisible(hwndList, 0, FALSE);
|
||||
return false;
|
||||
}
|
||||
// read "PIANO_ROLL" string
|
||||
char save_id[PIANO_ROLL_ID_LEN];
|
||||
if ((int)is->fread(save_id, PIANO_ROLL_ID_LEN) < PIANO_ROLL_ID_LEN) goto error;
|
||||
|
@ -746,9 +752,9 @@ error:
|
|||
return true;
|
||||
}
|
||||
// ----------------------------------------------------------------------
|
||||
void PIANO_ROLL::RedrawList()
|
||||
void PIANO_ROLL::RedrawList(bool erase_bg)
|
||||
{
|
||||
InvalidateRect(hwndList, 0, FALSE);
|
||||
InvalidateRect(hwndList, 0, erase_bg);
|
||||
must_check_item_under_mouse = true;
|
||||
}
|
||||
void PIANO_ROLL::RedrawRow(int index)
|
||||
|
@ -1072,16 +1078,13 @@ void PIANO_ROLL::GetDispInfo(NMLVDISPINFO* nmlvDispInfo)
|
|||
{
|
||||
case COLUMN_ICONS:
|
||||
{
|
||||
if(item.iImage == I_IMAGECALLBACK)
|
||||
item.iImage = bookmarks.FindBookmarkAtFrame(item.iItem);
|
||||
if (item.iImage < 0)
|
||||
{
|
||||
item.iImage = bookmarks.FindBookmarkAtFrame(item.iItem);
|
||||
if (item.iImage < 0)
|
||||
{
|
||||
if (item.iItem == currFrameCounter)
|
||||
item.iImage = ARROW_IMAGE_ID;
|
||||
else if (item.iItem == playback.lost_position_frame-1)
|
||||
item.iImage = GREEN_ARROW_IMAGE_ID;
|
||||
}
|
||||
if (item.iItem == currFrameCounter)
|
||||
item.iImage = ARROW_IMAGE_ID;
|
||||
else if (item.iItem == playback.lost_position_frame-1)
|
||||
item.iImage = GREEN_ARROW_IMAGE_ID;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
@ -1181,7 +1184,7 @@ LONG PIANO_ROLL::CustomDraw(NMLVCUSTOMDRAW* msg)
|
|||
{
|
||||
if (!greenzone.savestates[cell_y].empty())
|
||||
{
|
||||
if (taseditor_config.show_lag_frames && greenzone.lag_history[cell_y])
|
||||
if (taseditor_config.show_lag_frames && greenzone.GetLagHistoryAtFrame(cell_y))
|
||||
msg->clrTextBk = LAG_FRAMENUM_COLOR;
|
||||
else
|
||||
msg->clrTextBk = GREENZONE_FRAMENUM_COLOR;
|
||||
|
@ -1190,7 +1193,7 @@ LONG PIANO_ROLL::CustomDraw(NMLVCUSTOMDRAW* msg)
|
|||
|| (!greenzone.savestates[cell_y & EVERY4TH].empty() && (int)greenzone.savestates.size() > (cell_y | 0x3) + 1 && !greenzone.savestates[(cell_y | 0x3) + 1].empty())
|
||||
|| (!greenzone.savestates[cell_y & EVERY2ND].empty() && !greenzone.savestates[(cell_y | 0x1) + 1].empty()))
|
||||
{
|
||||
if (taseditor_config.show_lag_frames && greenzone.lag_history[cell_y])
|
||||
if (taseditor_config.show_lag_frames && greenzone.GetLagHistoryAtFrame(cell_y))
|
||||
msg->clrTextBk = PALE_LAG_FRAMENUM_COLOR;
|
||||
else
|
||||
msg->clrTextBk = PALE_GREENZONE_FRAMENUM_COLOR;
|
||||
|
@ -1221,7 +1224,7 @@ LONG PIANO_ROLL::CustomDraw(NMLVCUSTOMDRAW* msg)
|
|||
{
|
||||
if (!greenzone.savestates[cell_y].empty())
|
||||
{
|
||||
if (taseditor_config.show_lag_frames && greenzone.lag_history[cell_y])
|
||||
if (taseditor_config.show_lag_frames && greenzone.GetLagHistoryAtFrame(cell_y))
|
||||
msg->clrTextBk = LAG_INPUT_COLOR1;
|
||||
else
|
||||
msg->clrTextBk = GREENZONE_INPUT_COLOR1;
|
||||
|
@ -1230,7 +1233,7 @@ LONG PIANO_ROLL::CustomDraw(NMLVCUSTOMDRAW* msg)
|
|||
|| (!greenzone.savestates[cell_y & EVERY4TH].empty() && (int)greenzone.savestates.size() > (cell_y | 0x3) + 1 && !greenzone.savestates[(cell_y | 0x3) + 1].empty())
|
||||
|| (!greenzone.savestates[cell_y & EVERY2ND].empty() && !greenzone.savestates[(cell_y | 0x1) + 1].empty()))
|
||||
{
|
||||
if (taseditor_config.show_lag_frames && greenzone.lag_history[cell_y])
|
||||
if (taseditor_config.show_lag_frames && greenzone.GetLagHistoryAtFrame(cell_y))
|
||||
msg->clrTextBk = PALE_LAG_INPUT_COLOR1;
|
||||
else
|
||||
msg->clrTextBk = PALE_GREENZONE_INPUT_COLOR1;
|
||||
|
@ -1260,7 +1263,7 @@ LONG PIANO_ROLL::CustomDraw(NMLVCUSTOMDRAW* msg)
|
|||
{
|
||||
if (!greenzone.savestates[cell_y].empty())
|
||||
{
|
||||
if (taseditor_config.show_lag_frames && greenzone.lag_history[cell_y])
|
||||
if (taseditor_config.show_lag_frames && greenzone.GetLagHistoryAtFrame(cell_y))
|
||||
msg->clrTextBk = LAG_INPUT_COLOR2;
|
||||
else
|
||||
msg->clrTextBk = GREENZONE_INPUT_COLOR2;
|
||||
|
@ -1269,7 +1272,7 @@ LONG PIANO_ROLL::CustomDraw(NMLVCUSTOMDRAW* msg)
|
|||
|| (!greenzone.savestates[cell_y & EVERY4TH].empty() && (int)greenzone.savestates.size() > (cell_y | 0x3) + 1 && !greenzone.savestates[(cell_y | 0x3) + 1].empty())
|
||||
|| (!greenzone.savestates[cell_y & EVERY2ND].empty() && !greenzone.savestates[(cell_y | 0x1) + 1].empty()))
|
||||
{
|
||||
if (taseditor_config.show_lag_frames && greenzone.lag_history[cell_y])
|
||||
if (taseditor_config.show_lag_frames && greenzone.GetLagHistoryAtFrame(cell_y))
|
||||
msg->clrTextBk = PALE_LAG_INPUT_COLOR2;
|
||||
else
|
||||
msg->clrTextBk = PALE_GREENZONE_INPUT_COLOR2;
|
||||
|
|
|
@ -144,9 +144,9 @@ public:
|
|||
void update();
|
||||
|
||||
void save(EMUFILE *os, bool really_save = true);
|
||||
bool load(EMUFILE *is);
|
||||
bool load(EMUFILE *is, bool really_load = true);
|
||||
|
||||
void RedrawList();
|
||||
void RedrawList(bool erase_bg = true);
|
||||
void RedrawRow(int index);
|
||||
void RedrawHeader();
|
||||
|
||||
|
|
|
@ -133,7 +133,7 @@ void POPUP_DISPLAY::update()
|
|||
if (clock() > next_update_time)
|
||||
{
|
||||
next_update_time = clock() + DISPLAY_UPDATE_TICK;
|
||||
if (bookmarks.item_under_mouse >= 0 && bookmarks.item_under_mouse < TOTAL_BOOKMARKS)
|
||||
if (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)
|
||||
{
|
||||
|
|
|
@ -260,8 +260,13 @@ void SELECTION::save(EMUFILE *os, bool really_save)
|
|||
}
|
||||
}
|
||||
// returns true if couldn't load
|
||||
bool SELECTION::load(EMUFILE *is)
|
||||
bool SELECTION::load(EMUFILE *is, bool really_load)
|
||||
{
|
||||
if (!really_load)
|
||||
{
|
||||
reset();
|
||||
return false;
|
||||
}
|
||||
// read "SELECTION" string
|
||||
char save_id[SELECTION_ID_LEN];
|
||||
if ((int)is->fread(save_id, SELECTION_ID_LEN) < SELECTION_ID_LEN) goto error;
|
||||
|
@ -526,33 +531,25 @@ void SELECTION::SelectBetweenMarkers()
|
|||
return;
|
||||
}
|
||||
|
||||
// selecting circle:
|
||||
// selecting circle: 1-2-3-4-1-2-3-4...
|
||||
if (upper_border > upper_marker+1 || lower_border < lower_marker-1 || lower_border > lower_marker)
|
||||
{
|
||||
// default: select all between markers
|
||||
for (int i = upper_marker+1; i < lower_marker; ++i)
|
||||
{
|
||||
ListView_SetItemState(piano_roll.hwndList, i, LVIS_SELECTED, LVIS_SELECTED);
|
||||
}
|
||||
} else if (upper_border == upper_marker+1 && lower_border == lower_marker-1)
|
||||
{
|
||||
// already selected all between markers - now select both markers or at least select the marker that is not outside movie range
|
||||
// 1 - default: select all between markers, not including lower marker
|
||||
if (upper_marker < 0) upper_marker = 0;
|
||||
if (lower_marker >= movie_size) lower_marker = movie_size - 1;
|
||||
for (int i = upper_marker; i <= lower_marker; ++i)
|
||||
{
|
||||
ListView_SetItemState(piano_roll.hwndList, i, LVIS_SELECTED, LVIS_SELECTED);
|
||||
}
|
||||
} else if (upper_border <= upper_marker && lower_border >= lower_marker)
|
||||
{
|
||||
// selected all between markers and both markers selected too - now deselect lower marker
|
||||
for (int i = upper_marker; i < lower_marker; ++i)
|
||||
{
|
||||
ListView_SetItemState(piano_roll.hwndList, i, LVIS_SELECTED, LVIS_SELECTED);
|
||||
}
|
||||
} else if (upper_border == upper_marker && lower_border == lower_marker-1)
|
||||
{
|
||||
// selected all between markers and upper marker selected too - now deselect upper marker and (if lower marker < movie_size) reselect lower marker
|
||||
// 2 - selected all between markers and upper marker selected too: select all between markers, not including markers
|
||||
for (int i = upper_marker+1; i < lower_marker; ++i)
|
||||
{
|
||||
ListView_SetItemState(piano_roll.hwndList, i, LVIS_SELECTED, LVIS_SELECTED);
|
||||
}
|
||||
} else if (upper_border == upper_marker+1 && lower_border == lower_marker-1)
|
||||
{
|
||||
// 3 - selected all between markers, nut including markers: select all between markers, not including upper marker
|
||||
if (lower_marker >= movie_size) lower_marker = movie_size - 1;
|
||||
for (int i = upper_marker+1; i <= lower_marker; ++i)
|
||||
{
|
||||
|
@ -560,8 +557,18 @@ void SELECTION::SelectBetweenMarkers()
|
|||
}
|
||||
} else if (upper_border == upper_marker+1 && lower_border == lower_marker)
|
||||
{
|
||||
// selected all between markers and lower marker selected too - now deselect lower marker (return to "selected all between markers")
|
||||
for (int i = upper_marker + 1; i < lower_marker; ++i)
|
||||
// 4 - selected all between markers and lower marker selected too: select all bertween markers, including markers
|
||||
if (upper_marker < 0) upper_marker = 0;
|
||||
if (lower_marker >= movie_size) lower_marker = movie_size - 1;
|
||||
for (int i = upper_marker; i <= lower_marker; ++i)
|
||||
{
|
||||
ListView_SetItemState(piano_roll.hwndList, i, LVIS_SELECTED, LVIS_SELECTED);
|
||||
}
|
||||
} else
|
||||
{
|
||||
// return to 1
|
||||
if (upper_marker < 0) upper_marker = 0;
|
||||
for (int i = upper_marker; i < lower_marker; ++i)
|
||||
{
|
||||
ListView_SetItemState(piano_roll.hwndList, i, LVIS_SELECTED, LVIS_SELECTED);
|
||||
}
|
||||
|
|
|
@ -20,7 +20,7 @@ public:
|
|||
void RedrawMarker();
|
||||
|
||||
void save(EMUFILE *os, bool really_save = true);
|
||||
bool load(EMUFILE *is);
|
||||
bool load(EMUFILE *is, bool really_load = true);
|
||||
void saveSelection(SelectionFrames& selection, EMUFILE *os);
|
||||
bool loadSelection(SelectionFrames& selection, EMUFILE *is);
|
||||
bool skiploadSelection(EMUFILE *is);
|
||||
|
|
|
@ -432,7 +432,7 @@ int SNAPSHOT::findFirstChange(SNAPSHOT& inp, int start, int end)
|
|||
break;
|
||||
}
|
||||
}
|
||||
// if current size is less then previous, return size-1 as the frame of difference
|
||||
// if current size is less then previous, return last frame (=size-1) as the frame of difference
|
||||
if (size < inp_end) return size-1;
|
||||
// no changes were found
|
||||
return -1;
|
||||
|
|
|
@ -92,12 +92,12 @@ bool TASEDITOR_PROJECT::save(const char* different_name, bool save_binary, bool
|
|||
if(count1 && count2)
|
||||
{
|
||||
// ask user if he wants to fix the checksum before saving
|
||||
char message[2048];
|
||||
char message[2048] = {0};
|
||||
strcpy(message, "Movie ROM:\n");
|
||||
strncat(message, currMovieData.romFilename.c_str(), 2047 - strlen(message));
|
||||
strncat(message, "\nMD5: ", 2047 - strlen(message));
|
||||
strncat(message, md5_movie, 2047 - strlen(message));
|
||||
strncat(message, "\n\nCurrent ROM: \n", 2047 - strlen(message));
|
||||
strncat(message, "\n\nCurrent ROM:\n", 2047 - strlen(message));
|
||||
strncat(message, GameInfo->filename, 2047 - strlen(message));
|
||||
strncat(message, "\nMD5: ", 2047 - strlen(message));
|
||||
strncat(message, md5_rom, 2047 - strlen(message));
|
||||
|
@ -128,7 +128,8 @@ bool TASEDITOR_PROJECT::save(const char* different_name, bool save_binary, bool
|
|||
currMovieData.loadFrameCount = currMovieData.records.size();
|
||||
currMovieData.emuVersion = FCEU_VERSION_NUMERIC;
|
||||
currMovieData.dump(ofs, save_binary);
|
||||
// save specified modules
|
||||
// save header: fm3 version + saved_stuff
|
||||
write32le(PROJECT_FILE_CURRENT_VERSION, ofs);
|
||||
unsigned int saved_stuff = 0;
|
||||
if (save_markers) saved_stuff |= MARKERS_SAVED;
|
||||
if (save_bookmarks) saved_stuff |= BOOKMARKS_SAVED;
|
||||
|
@ -137,6 +138,7 @@ bool TASEDITOR_PROJECT::save(const char* different_name, bool save_binary, bool
|
|||
if (save_piano_roll) saved_stuff |= PIANO_ROLL_SAVED;
|
||||
if (save_selection) saved_stuff |= SELECTION_SAVED;
|
||||
write32le(saved_stuff, ofs);
|
||||
// save specified modules
|
||||
markers_manager.save(ofs, save_markers);
|
||||
bookmarks.save(ofs, save_bookmarks);
|
||||
greenzone.save(ofs, save_greenzone);
|
||||
|
@ -158,6 +160,7 @@ bool TASEDITOR_PROJECT::save(const char* different_name, bool save_binary, bool
|
|||
}
|
||||
bool TASEDITOR_PROJECT::load(char* fullname)
|
||||
{
|
||||
bool load_all = true;
|
||||
EMUFILE_FILE ifs(fullname, "rb");
|
||||
|
||||
if(ifs.fail())
|
||||
|
@ -186,46 +189,79 @@ bool TASEDITOR_PROJECT::load(char* fullname)
|
|||
if(count1 && count2)
|
||||
{
|
||||
// ask user if he really wants to load the project
|
||||
char message[2048];
|
||||
char message[2048] = {0};
|
||||
strcpy(message, "This project was made using different ROM!\n\n");
|
||||
strcat(message, "Original ROM:\n");
|
||||
strncat(message, tempMovieData.romFilename.c_str(), 2047 - strlen(message));
|
||||
strncat(message, "\nMD5: ", 2047 - strlen(message));
|
||||
strncat(message, md5_original, 2047 - strlen(message));
|
||||
strncat(message, "\n\nCurrent ROM: \n", 2047 - strlen(message));
|
||||
strncat(message, "\n\nCurrent ROM:\n", 2047 - strlen(message));
|
||||
strncat(message, GameInfo->filename, 2047 - strlen(message));
|
||||
strncat(message, "\nMD5: ", 2047 - strlen(message));
|
||||
strncat(message, md5_current, 2047 - strlen(message));
|
||||
strncat(message, "\n\nLoad the project anyway? ", 2047 - strlen(message));
|
||||
strncat(message, "\n\nLoad the project anyway?", 2047 - strlen(message));
|
||||
int answer = MessageBox(taseditor_window.hwndTasEditor, message, "ROM Checksum Mismatch", MB_YESNO);
|
||||
if(answer == IDNO)
|
||||
if (answer == IDNO)
|
||||
return false;
|
||||
}
|
||||
}
|
||||
FCEU_printf("\nLoading TAS Editor project %s...\n", fullname);
|
||||
// load fm3 version from header and check it
|
||||
unsigned int file_version;
|
||||
if (read32le(&file_version, &ifs))
|
||||
{
|
||||
if (file_version != PROJECT_FILE_CURRENT_VERSION)
|
||||
{
|
||||
char message[2048] = {0};
|
||||
strcpy(message, "This project was saved using different version of TAS Editor!\n\n");
|
||||
strcat(message, "Original version: ");
|
||||
char version_num[11];
|
||||
_itoa(file_version, version_num, 10);
|
||||
strncat(message, version_num, 2047 - strlen(message));
|
||||
strncat(message, "\nCurrent version: ", 2047 - strlen(message));
|
||||
_itoa(PROJECT_FILE_CURRENT_VERSION, version_num, 10);
|
||||
strncat(message, version_num, 2047 - strlen(message));
|
||||
strncat(message, "\n\nClick Yes to try loading all data from the file (may crash).\n", 2047 - strlen(message));
|
||||
strncat(message, "Click No to only load movie data.\n", 2047 - strlen(message));
|
||||
strncat(message, "Click Cancel to abort loading.", 2047 - strlen(message));
|
||||
int answer = MessageBox(taseditor_window.hwndTasEditor, message, "FM3 Version Mismatch", MB_YESNOCANCEL);
|
||||
if (answer == IDCANCEL)
|
||||
return false;
|
||||
else if (answer == IDNO)
|
||||
load_all = false;
|
||||
}
|
||||
} else
|
||||
{
|
||||
// couldn't even load header, this seems like an FM2
|
||||
load_all = false;
|
||||
char message[2048];
|
||||
strcpy(message, "This file doesn't seem to be an FM3 project.\nIt only contains FM2 movie data. Load it anyway?");
|
||||
int answer = MessageBox(taseditor_window.hwndTasEditor, message, "Opening FM2 file", MB_YESNO);
|
||||
if (answer == IDNO)
|
||||
return false;
|
||||
}
|
||||
// save data to currMovieData and continue loading
|
||||
FCEU_printf("\nLoading TAS Editor project %s...\n", fullname);
|
||||
currMovieData = tempMovieData;
|
||||
LoadSubtitles(currMovieData);
|
||||
// ensure that movie has correct set of ports/fourscore
|
||||
SetInputType(currMovieData, GetInputType(currMovieData));
|
||||
} else
|
||||
{
|
||||
FCEU_PrintError("Error loading movie data from %s!", fullname);
|
||||
// do not load the project
|
||||
// do not alter the project
|
||||
return false;
|
||||
}
|
||||
|
||||
// ensure that movie has correct set of ports/fourscore
|
||||
SetInputType(currMovieData, GetInputType(currMovieData));
|
||||
|
||||
// load modules
|
||||
unsigned int saved_stuff;
|
||||
read32le(&saved_stuff, &ifs);
|
||||
markers_manager.load(&ifs);
|
||||
bookmarks.load(&ifs);
|
||||
greenzone.load(&ifs);
|
||||
history.load(&ifs);
|
||||
piano_roll.load(&ifs);
|
||||
selection.load(&ifs);
|
||||
|
||||
if (load_all)
|
||||
read32le(&saved_stuff, &ifs);
|
||||
// load modules
|
||||
markers_manager.load(&ifs, load_all);
|
||||
bookmarks.load(&ifs, load_all);
|
||||
greenzone.load(&ifs, load_all);
|
||||
history.load(&ifs, load_all);
|
||||
piano_roll.load(&ifs, load_all);
|
||||
selection.load(&ifs, load_all);
|
||||
// reset other modules
|
||||
playback.reset();
|
||||
recorder.reset();
|
||||
|
@ -233,7 +269,7 @@ bool TASEDITOR_PROJECT::load(char* fullname)
|
|||
popup_display.reset();
|
||||
reset();
|
||||
RenameProject(fullname);
|
||||
// restore cursor
|
||||
// restore mouse cursor shape
|
||||
piano_roll.must_check_item_under_mouse = true;
|
||||
return true;
|
||||
}
|
||||
|
|
|
@ -8,12 +8,12 @@
|
|||
#include "selection.h"
|
||||
#include "markers_manager.h"
|
||||
#include "snapshot.h"
|
||||
#include "bookmarks.h"
|
||||
#include "branches.h"
|
||||
#include "history.h"
|
||||
#include "playback.h"
|
||||
#include "recorder.h"
|
||||
#include "greenzone.h"
|
||||
#include "bookmarks.h"
|
||||
#include "branches.h"
|
||||
#include "piano_roll.h"
|
||||
#include "taseditor_lua.h"
|
||||
#include "splicer.h"
|
||||
|
@ -29,6 +29,8 @@
|
|||
#define PIANO_ROLL_SAVED 16
|
||||
#define SELECTION_SAVED 32
|
||||
|
||||
#define PROJECT_FILE_CURRENT_VERSION 1
|
||||
|
||||
class TASEDITOR_PROJECT
|
||||
{
|
||||
public:
|
||||
|
|
|
@ -90,7 +90,7 @@ Window_items_struct window_items[TASEDITOR_WINDOW_TOTAL_ITEMS] = {
|
|||
TASEDITOR_FORWARD_FULL, -1, 0, 0, 0, "Send Playback to next Marker (mouse: Shift+Wheel down) (hotkey: Shift+PageDown)", "", false, 0, 0,
|
||||
IDC_PROGRESS1, -1, 0, 0, 0, "", "", false, 0, 0,
|
||||
CHECK_FOLLOW_CURSOR, -1, 0, 0, 0, "The Piano Roll will follow Playback cursor movements", "", false, 0, 0,
|
||||
CHECK_AUTORESTORE_PLAYBACK, -1, 0, 0, 0, "If you change input above Playback, cursor will run where it was before change", "", false, 0, 0,
|
||||
CHECK_AUTORESTORE_PLAYBACK, -1, 0, 0, 0, "If you change input above Playback, cursor will run to where it was before change", "", false, 0, 0,
|
||||
IDC_BOOKMARKSLIST, -1, 0, 0, 0, "Right click = set Bookmark, Left click = jump to Bookmark or load Branch", "", false, 0, 0,
|
||||
IDC_HISTORYLIST, -1, 0, 0, -1, "Click to revert the movie back to that time", "", false, 0, 0,
|
||||
IDC_RADIO_ALL, -1, 0, 0, 0, "", "", false, 0, 0,
|
||||
|
|
|
@ -3,7 +3,7 @@
|
|||
#define TASEDITOR_WINDOW_TOTAL_ITEMS 43
|
||||
#define PIANOROLL_IN_WINDOWITEMS 2
|
||||
|
||||
#define TOOLTIP_TEXT_MAX_LEN 80
|
||||
#define TOOLTIP_TEXT_MAX_LEN 82
|
||||
#define TOOLTIPS_AUTOPOP_TIMEOUT 30000
|
||||
|
||||
#define PATTERNS_MENU_POS 5
|
||||
|
|
|
@ -126,8 +126,6 @@ int GetCheckedAutoFirePattern();
|
|||
int GetCheckedAutoFireOffset();
|
||||
|
||||
//Internal variables-------------------------------------
|
||||
bool AVIenableHUDrecording = false;
|
||||
bool AVIdisableMovieMessages = false;
|
||||
char *md5_asciistr(uint8 digest[16]);
|
||||
static int winwidth, winheight;
|
||||
static volatile int nofocus = 0;
|
||||
|
@ -402,8 +400,8 @@ void UpdateCheckedMenuItems()
|
|||
//File Menu
|
||||
CheckMenuItem(fceumenu, ID_FILE_MOVIE_TOGGLEREAD, movie_readonly ? MF_CHECKED : MF_UNCHECKED);
|
||||
CheckMenuItem(fceumenu, ID_FILE_OPENLUAWINDOW, LuaConsoleHWnd ? MF_CHECKED : MF_UNCHECKED);
|
||||
CheckMenuItem(fceumenu, ID_AVI_ENABLEHUDRECORDING, AVIenableHUDrecording ? MF_CHECKED : MF_UNCHECKED);
|
||||
CheckMenuItem(fceumenu, ID_AVI_DISMOVIEMESSAGE, AVIdisableMovieMessages ? MF_CHECKED : MF_UNCHECKED);
|
||||
CheckMenuItem(fceumenu, ID_AVI_ENABLEHUDRECORDING, FCEUI_AviEnableHUDrecording() ? MF_CHECKED : MF_UNCHECKED);
|
||||
CheckMenuItem(fceumenu, ID_AVI_DISMOVIEMESSAGE, FCEUI_AviDisableMovieMessages() ? MF_CHECKED : MF_UNCHECKED);
|
||||
|
||||
//NES Menu
|
||||
CheckMenuItem(fceumenu, ID_NES_PAUSE, EmulationPaused ? MF_CHECKED : MF_UNCHECKED);
|
||||
|
@ -1635,14 +1633,19 @@ LRESULT FAR PASCAL AppWndProc(HWND hWnd,UINT msg,WPARAM wParam,LPARAM lParam)
|
|||
loggingSound = false;
|
||||
break;
|
||||
case ID_AVI_ENABLEHUDRECORDING:
|
||||
{
|
||||
bool AVIenableHUDrecording = FCEUI_AviEnableHUDrecording();
|
||||
AVIenableHUDrecording ^= 1;
|
||||
FCEUI_SetAviEnableHUDrecording(AVIenableHUDrecording);
|
||||
break;
|
||||
}
|
||||
case ID_AVI_DISMOVIEMESSAGE:
|
||||
{
|
||||
bool AVIdisableMovieMessages = FCEUI_AviDisableMovieMessages();
|
||||
AVIdisableMovieMessages ^= 1;
|
||||
FCEUI_SetAviDisableMovieMessages(AVIdisableMovieMessages);
|
||||
break;
|
||||
|
||||
}
|
||||
case FCEUX_CONTEXT_SCREENSHOT:
|
||||
case ID_FILE_SCREENSHOT:
|
||||
FCEUI_SaveSnapshot();
|
||||
|
@ -1834,7 +1837,7 @@ LRESULT FAR PASCAL AppWndProc(HWND hWnd,UINT msg,WPARAM wParam,LPARAM lParam)
|
|||
UpdateCheckedMenuItems();
|
||||
PushCurrentVideoSettings();
|
||||
break;
|
||||
case MENU_DIRECTORIES:
|
||||
case MENU_DIRECTORIES:
|
||||
ConfigDirectories();
|
||||
break;
|
||||
case MENU_GUI_OPTIONS:
|
||||
|
@ -2257,9 +2260,14 @@ adelikat: Outsourced this to a remappable hotkey
|
|||
EnableMenuItem(fceumenu,ID_FILE_CLOSELUAWINDOWS,MF_BYCOMMAND | (LuaConsoleHWnd?MF_ENABLED:MF_GRAYED));
|
||||
if (FCEUMOV_Mode(MOVIEMODE_TASEDITOR))
|
||||
{
|
||||
EnableMenuItem(fceumenu, MENU_PAL, false);
|
||||
EnableMenuItem(fceumenu, ID_NEWPPU, false);
|
||||
EnableMenuItem(fceumenu, ID_OLDPPU, false);
|
||||
EnableMenuItem(fceumenu, MENU_PAL, MF_GRAYED);
|
||||
EnableMenuItem(fceumenu, ID_NEWPPU, MF_GRAYED);
|
||||
EnableMenuItem(fceumenu, ID_OLDPPU, MF_GRAYED);
|
||||
} else
|
||||
{
|
||||
EnableMenuItem(fceumenu, MENU_PAL, MF_ENABLED);
|
||||
EnableMenuItem(fceumenu, ID_NEWPPU, MF_ENABLED);
|
||||
EnableMenuItem(fceumenu, ID_OLDPPU, MF_ENABLED);
|
||||
}
|
||||
CheckMenuRadioItem(fceumenu, ID_NEWPPU, ID_OLDPPU, newppu ? ID_NEWPPU : ID_OLDPPU, MF_BYCOMMAND);
|
||||
|
||||
|
|
|
@ -422,7 +422,7 @@ bool FCEUSS_SaveMS(EMUFILE* outstream, int compressionLevel)
|
|||
int error = Z_OK;
|
||||
uint8* cbuf = (uint8*)memory_savestate.buf();
|
||||
uLongf comprlen = -1;
|
||||
if(compressionLevel != Z_NO_COMPRESSION && compressSavestates)
|
||||
if(compressionLevel != Z_NO_COMPRESSION && (compressSavestates || FCEUMOV_Mode(MOVIEMODE_TASEDITOR)))
|
||||
{
|
||||
// worst case compression: zlib says "0.1% larger than sourceLen plus 12 bytes"
|
||||
comprlen = (len>>9)+12 + len;
|
||||
|
|
Loading…
Reference in New Issue