* Taseditor: set/pick Markers by doubleclick, throw Markers away

* Taseditor: clicks on Input don't change Selection
* Taseditor: selection by dragging from Frame#
* Taseditor: better way to check doubletap for Shift and Ctrl keys
* Taseditor: no more "allow keys in Piano Roll"; new accelerators: Ctrl + arrows, Shift + arrows, Home/End/Page Up/Page Down, Ctrl + Home/End, Shift + Home/End
* Taseditor: showing row_last_clicked when Shift or Alt is held
This commit is contained in:
ansstuff 2012-03-17 15:59:35 +00:00
parent b68dcc072d
commit 125173107b
27 changed files with 1166 additions and 777 deletions

View File

@ -321,7 +321,6 @@ static CFGSTRUCT fceuconfig[] = {
AC(taseditor_config.combine_consecutive_rec),
AC(taseditor_config.use_1p_rec),
AC(taseditor_config.columnset_by_keys),
AC(taseditor_config.keyboard_for_piano_roll),
AC(taseditor_config.superimpose_affects_paste),
AC(taseditor_config.branch_full_movie),
AC(taseditor_config.branch_only_when_rec),
@ -348,7 +347,6 @@ static CFGSTRUCT fceuconfig[] = {
AC(taseditor_config.findnote_matchcase),
AC(taseditor_config.findnote_search_up),
AC(taseditor_config.deselect_on_doubleclick),
AC(taseditor_config.doubleclick_affects_playback),
AC(taseditor_config.draw_input),
AC(taseditor_config.silent_autosave),
AC(taseditor_config.tooltips),

View File

@ -71,10 +71,8 @@
#include "utils/xstring.h"
#include <string.h>
#include "taseditor/taseditor_window.h"
#include "taseditor/piano_roll.h"
extern TASEDITOR_WINDOW taseditor_window;
extern PIANO_ROLL piano_roll;
//---------------------------
//mbg merge 6/29/06 - new aboutbox
@ -342,11 +340,7 @@ int BlockingCheck()
if(!handled && taseditor_window.hwndTasEditor)
{
if(IsChild(taseditor_window.hwndTasEditor, msg.hwnd))
{
handled = TranslateAccelerator(taseditor_window.hwndTasEditor, fceu_hAccel, &msg);
if (handled)
piano_roll.AcceleratorDispatched();
}
}
if(!handled && taseditor_window.hwndFindNote)
{

View File

@ -284,15 +284,13 @@ BEGIN
MENUITEM "Bind Markers to Input", ID_CONFIG_BINDMARKERSTOINPUT,MFT_STRING,MFS_ENABLED
MENUITEM "Empty new Marker Notes", ID_CONFIG_EMPTYNEWMARKERNOTES,MFT_STRING,MFS_ENABLED
MENUITEM MFT_SEPARATOR
MENUITEM "Combine consecutive Recordings", ID_CONFIG_COMBINECONSECUTIVERECORDINGS,MFT_STRING,MFS_ENABLED
MENUITEM "Combine consecutive Recordings/Draws", ID_CONFIG_COMBINECONSECUTIVERECORDINGS,MFT_STRING,MFS_ENABLED
MENUITEM "Use 1P keys for all single Recordings", ID_CONFIG_USE1PFORRECORDING,MFT_STRING,MFS_ENABLED
MENUITEM "Use Input keys for Column Set", ID_CONFIG_USEINPUTKEYSFORCOLUMNSET,MFT_STRING,MFS_ENABLED
MENUITEM "Allow keyboard controls in Piano Roll", ID_CONFIG_KEYBOARDCONTROLSINPIANOROLL,MFT_STRING,MFS_ENABLED
MENUITEM "Superimpose affects copy/paste", ID_CONFIG_SUPERIMPOSE_AFFECTS_PASTE,MFT_STRING,MFS_ENABLED
MENUITEM MFT_SEPARATOR
MENUITEM "Autofire Pattern skips Lag", ID_CONFIG_COLUMNSETPATTERNSKIPSLAG,MFT_STRING,MFS_ENABLED
MENUITEM "Deselect on doubleclick", ID_CONFIG_DESELECTONDOUBLECLICK,MFT_STRING,MFS_ENABLED
MENUITEM "Doubleclick on Frame# affects Playback", ID_CONFIG_DOUBLECLICKONFRAME,MFT_STRING,MFS_ENABLED
MENUITEM "Draw Input by dragging", ID_CONFIG_DRAWINPUTBYDRAGGING,MFT_STRING,MFS_ENABLED
MENUITEM MFT_SEPARATOR
MENUITEM "Silent Autosave", ID_CONFIG_SILENTAUTOSAVE,MFT_STRING,MFS_ENABLED
@ -383,17 +381,10 @@ END
TASEDITORCONTEXTMENUS MENU
BEGIN
POPUP "Stray"
BEGIN
MENUITEM "Unpause emulator", ID_STRAY_UNPAUSE
MENUITEM SEPARATOR
MENUITEM "Insert # of Frames", MENU_CONTEXT_STRAY_INSERTFRAMES
MENUITEM "Truncate movie", ID_STRAY_TRUNCATE
END
POPUP "Selected"
BEGIN
MENUITEM "Set Marker", ID_SELECTED_SETMARKER
MENUITEM "Remove Marker", ID_SELECTED_REMOVEMARKER
MENUITEM "Set Markers", ID_SELECTED_SETMARKER
MENUITEM "Remove Markers", ID_SELECTED_REMOVEMARKER
MENUITEM SEPARATOR
MENUITEM "Deselect", ID_SELECTED_DESELECT
MENUITEM "Select between Markers", ID_SELECTED_SELECTMIDMARKERS
@ -2193,29 +2184,45 @@ END
// Accelerator
//
IDR_ACCELERATOR1 ACCELERATORS
IDR_TASEDITOR_ACCELERATORS ACCELERATORS
BEGIN
"A", ACCEL_CTRL_A, VIRTKEY, CONTROL, NOINVERT
"B", ACCEL_CTRL_B, VIRTKEY, CONTROL, NOINVERT
"C", ACCEL_CTRL_C, VIRTKEY, CONTROL, NOINVERT
VK_DELETE, ACCEL_CTRL_DELETE, VIRTKEY, CONTROL, NOINVERT
VK_DOWN, ACCEL_CTRL_DOWN, VIRTKEY, CONTROL, NOINVERT
"F", ACCEL_CTRL_F, VIRTKEY, CONTROL, NOINVERT
VK_INSERT, ACCEL_CTRL_INSERT, VIRTKEY, CONTROL, NOINVERT
VK_LEFT, ACCEL_CTRL_LEFT, VIRTKEY, CONTROL, NOINVERT
VK_NEXT, ACCEL_CTRL_PGDN, VIRTKEY, CONTROL, NOINVERT
VK_PRIOR, ACCEL_CTRL_PGUP, VIRTKEY, CONTROL, NOINVERT
"Q", ACCEL_CTRL_Q, VIRTKEY, CONTROL, NOINVERT
VK_RIGHT, ACCEL_CTRL_RIGHT, VIRTKEY, CONTROL, NOINVERT
"S", ACCEL_CTRL_S, VIRTKEY, CONTROL, NOINVERT
VK_UP, ACCEL_CTRL_UP, VIRTKEY, CONTROL, NOINVERT
"V", ACCEL_CTRL_V, VIRTKEY, CONTROL, NOINVERT
"W", ACCEL_CTRL_W, VIRTKEY, CONTROL, NOINVERT
"X", ACCEL_CTRL_X, VIRTKEY, CONTROL, NOINVERT
"Y", ACCEL_CTRL_Y, VIRTKEY, CONTROL, NOINVERT
"Z", ACCEL_CTRL_Z, VIRTKEY, CONTROL, NOINVERT
VK_DELETE, ACCEL_DEL, VIRTKEY, NOINVERT
VK_END, ACCEL_END, VIRTKEY, NOINVERT
VK_HOME, ACCEL_HOME, VIRTKEY, NOINVERT
VK_INSERT, ACCEL_INS, VIRTKEY, NOINVERT
VK_NEXT, ACCEL_PGDN, VIRTKEY, NOINVERT
VK_PRIOR, ACCEL_PGUP, VIRTKEY, NOINVERT
VK_INSERT, ACCEL_SHIFT_INS, VIRTKEY, SHIFT, NOINVERT
VK_NEXT, ACCEL_SHIFT_PGDN, VIRTKEY, SHIFT, NOINVERT
VK_PRIOR, ACCEL_SHIFT_PGUP, VIRTKEY, SHIFT, NOINVERT
"V", ACCEL_SHIFT_V, VIRTKEY, SHIFT, NOINVERT
VK_HOME, ACCEL_CTRL_HOME, VIRTKEY, CONTROL, NOINVERT
VK_END, ACCEL_CTRL_END, VIRTKEY, CONTROL, NOINVERT
VK_HOME, ACCEL_SHIFT_HOME, VIRTKEY, SHIFT, NOINVERT
VK_END, ACCEL_SHIFT_END, VIRTKEY, SHIFT, NOINVERT
VK_UP, ACCEL_SHIFT_UP, VIRTKEY, SHIFT, NOINVERT
VK_DOWN, ACCEL_SHIFT_DOWN, VIRTKEY, SHIFT, NOINVERT
VK_LEFT, ACCEL_SHIFT_LEFT, VIRTKEY, SHIFT, NOINVERT
VK_RIGHT, ACCEL_SHIFT_RIGHT, VIRTKEY, SHIFT, NOINVERT
END
IDR_RWACCELERATOR ACCELERATORS

View File

@ -98,6 +98,7 @@
#define BTN_CDLOGGER_SAVE_STRIPPED 108
#define IDC_CHEAT_VAL_NE_BY 108
#define IDC_DEBUGGER_SEEK_PC 108
#define IDR_TASEDITOR_ACCELERATORS 108
#define IDC_CHEAT_VAL_GT_BY 109
#define IDC_DEBUGGER_SEEK_TO 109
#define IDC_ROMPATCHER_PATCH_DATA 109
@ -997,6 +998,23 @@
#define ID_CONFIG_DESELECTONDOUBLECLICK 40538
#define ID_CONFIG_DRAWINPUTBYDRAGGING 40539
#define ID_CONFIG_DOUBLECLICKONFRAME 40540
#define ACCEL_CTRL_UP 40541
#define ACCEL_CTRL_DOWN 40542
#define ACCEL_CTRL_LEFT 40543
#define ACCEL_CTRL_RIGHT 40544
#define ACCEL_HOME 40545
#define ACCEL_END 40546
#define ACCEL_PGUP 40547
#define ACCEL_PGDN 40548
#define ACCEL_CTRL_HOME 40550
#define ACCEL_CTRL_END 40551
#define ACCEL_SHIFT_HOME 40552
#define ACCEL_SHIFT_END 40553
#define ACCEL_SHIFT_UP 40554
#define ACCEL_SHIFT_DOWN 40555
#define ACCEL_SHIFT_LEFT 40556
#define ID_ACCELERATOR40557 40557
#define ACCEL_SHIFT_RIGHT 40557
#define IDC_DEBUGGER_ICONTRAY 55535
#define MW_ValueLabel2 65423
#define MW_ValueLabel1 65426
@ -1006,7 +1024,7 @@
#ifdef APSTUDIO_INVOKED
#ifndef APSTUDIO_READONLY_SYMBOLS
#define _APS_NEXT_RESOURCE_VALUE 206
#define _APS_NEXT_COMMAND_VALUE 40541
#define _APS_NEXT_COMMAND_VALUE 40559
#define _APS_NEXT_CONTROL_VALUE 1281
#define _APS_NEXT_SYMED_VALUE 101
#endif

View File

@ -14,8 +14,6 @@ Main - Logical center of the program
* the point of quitting from TAS Editor
* regularly (at the end of every frame) updates all modules that need regular update
* implements operations of the "File" menu: creating New project, opening a file, saving, compact saving, import, export
* stores Autofire Patterns data and their loading/generating code
* stores resources: patterns filename, id of buttonpresses in patterns
------------------------------------------------------------------------------------ */
#include <fstream>
@ -30,8 +28,6 @@ using namespace std;
bool emulator_must_run_taseditor = false;
bool Taseditor_rewind_now = false;
bool must_call_manual_lua_function = false;
std::vector<std::string> autofire_patterns_names;
std::vector<std::vector<uint8>> autofire_patterns;
// all Taseditor functional modules
TASEDITOR_CONFIG taseditor_config;
@ -48,6 +44,7 @@ PIANO_ROLL piano_roll;
TASEDITOR_LUA taseditor_lua;
SELECTION selection;
SPLICER splicer;
EDITOR editor;
extern int joysticks_per_frame[NUM_SUPPORTED_INPUT_TYPES];
extern bool turbo;
@ -62,87 +59,12 @@ extern void UpdateCheckedMenuItems();
extern void TaseditorAutoFunction();
extern void TaseditorManualFunction();
// resources
char patternsFilename[] = "\\taseditor_patterns.txt";
char autofire_patterns_flagpress = 49; // "1"
bool EnterTasEditor()
{
if(!FCEU_IsValidUI(FCEUI_TASEDITOR)) return false;
if(!taseditor_window.hwndTasEditor)
{
// start TAS Editor
// init/load autofire_patterns
int total_patterns = 0;
autofire_patterns.resize(total_patterns);
autofire_patterns_names.resize(total_patterns);
char nameo[2048];
strncpy(nameo, FCEU_GetPath(FCEUMKF_TASEDITOR).c_str(), 2047);
strncat(nameo, patternsFilename, 2047 - strlen(nameo));
EMUFILE_FILE ifs(nameo, "rb");
if(!ifs.fail())
{
std::string tempstr1, tempstr2;
while (ReadString(&ifs, tempstr1))
{
if (ReadString(&ifs, tempstr2))
{
total_patterns++;
// save the name
autofire_patterns_names.push_back(tempstr1);
// parse 2nd string to sequence of 1s and 0s
autofire_patterns.resize(total_patterns);
autofire_patterns[total_patterns - 1].resize(tempstr2.size());
for (int i = tempstr2.size() - 1; i >= 0; i--)
{
if (tempstr2[i] == autofire_patterns_flagpress)
autofire_patterns[total_patterns - 1][i] = 1;
else
autofire_patterns[total_patterns - 1][i] = 0;
}
}
}
} else
{
FCEU_printf("Could not load tools\\taseditor_patterns.txt!\n");
}
if (autofire_patterns.size() == 0)
{
FCEU_printf("Will be using default set of patterns...\n");
autofire_patterns.resize(4);
autofire_patterns_names.resize(4);
// Default Pattern 0: Alternating (1010...)
autofire_patterns_names[0] = "Alternating (1010...)";
autofire_patterns[0].resize(2);
autofire_patterns[0][0] = 1;
autofire_patterns[0][1] = 0;
// Default Pattern 1: Alternating at 30FPS (11001100...)
autofire_patterns_names[1] = "Alternating at 30FPS (11001100...)";
autofire_patterns[1].resize(4);
autofire_patterns[1][0] = 1;
autofire_patterns[1][1] = 1;
autofire_patterns[1][2] = 0;
autofire_patterns[1][3] = 0;
// Default Pattern 2: One Quarter (10001000...)
autofire_patterns_names[2] = "One Quarter (10001000...)";
autofire_patterns[2].resize(4);
autofire_patterns[2][0] = 1;
autofire_patterns[2][1] = 0;
autofire_patterns[2][2] = 0;
autofire_patterns[2][3] = 0;
// Default Pattern 3: Tap'n'Hold (1011111111111111111111111111111111111...)
autofire_patterns_names[3] = "Tap'n'Hold (101111111...)";
autofire_patterns[3].resize(1000);
autofire_patterns[3][0] = 1;
autofire_patterns[3][1] = 0;
for (int i = 2; i < 1000; ++i)
autofire_patterns[3][i] = 1;
}
// reset current_pattern if it's outside the range
if (taseditor_config.current_pattern < 0 || taseditor_config.current_pattern >= (int)autofire_patterns.size())
taseditor_config.current_pattern = 0;
// create window
taseditor_window.init();
if(taseditor_window.hwndTasEditor)
@ -162,6 +84,7 @@ bool EnterTasEditor()
UpdateCheckedMenuItems();
// init modules
editor.init();
piano_roll.init();
selection.init();
splicer.init();
@ -214,40 +137,15 @@ bool EnterTasEditor()
} else return false;
} else return true;
}
// returns false if couldn't real a string containing at least one char
bool ReadString(EMUFILE *is, std::string& dest)
{
dest.resize(0);
int c;
while (true)
{
c = is->fgetc();
if (c < 0) break;
if (c == 10 || c == 13) // end of line
{
if (dest.size())
break; // already collected at least one char
else
continue; // skip the char and continue searching
} else
{
dest.push_back(c);
}
}
return dest.size() != 0;
}
bool ExitTasEditor()
{
if (!AskSaveProject()) return false;
// free autofire_patterns
autofire_patterns.resize(0);
autofire_patterns_names.resize(0);
// destroy window
taseditor_window.exit();
// release memory
editor.free();
piano_roll.free();
markers_manager.free();
greenzone.free();
@ -422,6 +320,7 @@ void NewProject()
history.reset();
piano_roll.reset();
selection.reset();
editor.reset();
splicer.reset();
recorder.reset();
popup_display.reset();
@ -851,4 +750,5 @@ bool TaseditorIsRecording()
if (movie_readonly || playback.pause_frame > currFrameCounter)
return false; // replay
return true; // record
}
}

View File

@ -9,7 +9,6 @@ struct NewProjectParameters
};
bool EnterTasEditor();
bool ReadString(EMUFILE *is, std::string& dest);
bool ExitTasEditor();
void UpdateTasEditor();

View File

@ -516,7 +516,7 @@ void BOOKMARKS::deploy(int slot)
{
// restore entire movie
bookmarks_array[slot].snapshot.toMovie(currMovieData, first_change);
piano_roll.update();
piano_roll.UpdateItemCount();
selection.must_find_current_marker = playback.must_find_current_marker = true;
history.RegisterBranching(MODTYPE_BRANCH_0 + slot, first_change, slot);
greenzone.Invalidate(first_change);
@ -551,7 +551,7 @@ void BOOKMARKS::deploy(int slot)
// restore movie up to and not including bookmarked frame (imitating old TASing method)
if (currMovieData.getNumRecords() <= jump_frame) currMovieData.records.resize(jump_frame+1); // but if old movie is shorter, include last frame as blank frame
bookmarks_array[slot].snapshot.toMovie(currMovieData, first_change, jump_frame-1);
piano_roll.update();
piano_roll.UpdateItemCount();
selection.must_find_current_marker = playback.must_find_current_marker = true;
history.RegisterBranching(MODTYPE_BRANCH_0 + slot, first_change, slot);
greenzone.Invalidate(first_change);

View File

@ -0,0 +1,386 @@
/* ---------------------------------------------------------------------------------
Implementation file of EDITOR class
Copyright (c) 2011-2012 AnS
(The MIT License)
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
------------------------------------------------------------------------------------
Editor - Interface for editing Input and Markers
[Singleton]
* implements operations of changing Input:
* implements operations of changing Markers:
* stores Autofire Patterns data and their loading/generating code
* stores resources: patterns filename, id of buttonpresses in patterns
------------------------------------------------------------------------------------ */
#include "taseditor_project.h"
extern TASEDITOR_WINDOW taseditor_window;
extern TASEDITOR_CONFIG taseditor_config;
extern HISTORY history;
extern MARKERS_MANAGER markers_manager;
extern PLAYBACK playback;
extern GREENZONE greenzone;
extern PIANO_ROLL piano_roll;
extern SELECTION selection;
extern int joysticks_per_frame[NUM_SUPPORTED_INPUT_TYPES];
extern int GetInputType(MovieData& md);
// resources
char patternsFilename[] = "\\taseditor_patterns.txt";
char autofire_patterns_flagpress = 49; // "1"
EDITOR::EDITOR()
{
}
void EDITOR::init()
{
free();
// load autofire_patterns
int total_patterns = 0;
char nameo[2048];
strncpy(nameo, FCEU_GetPath(FCEUMKF_TASEDITOR).c_str(), 2047);
strncat(nameo, patternsFilename, 2047 - strlen(nameo));
EMUFILE_FILE ifs(nameo, "rb");
if(!ifs.fail())
{
std::string tempstr1, tempstr2;
while (ReadString(&ifs, tempstr1))
{
if (ReadString(&ifs, tempstr2))
{
total_patterns++;
// save the name
autofire_patterns_names.push_back(tempstr1);
// parse 2nd string to sequence of 1s and 0s
autofire_patterns.resize(total_patterns);
autofire_patterns[total_patterns - 1].resize(tempstr2.size());
for (int i = tempstr2.size() - 1; i >= 0; i--)
{
if (tempstr2[i] == autofire_patterns_flagpress)
autofire_patterns[total_patterns - 1][i] = 1;
else
autofire_patterns[total_patterns - 1][i] = 0;
}
}
}
} else
{
FCEU_printf("Could not load tools\\taseditor_patterns.txt!\n");
}
if (autofire_patterns.size() == 0)
{
FCEU_printf("Will be using default set of patterns...\n");
autofire_patterns.resize(4);
autofire_patterns_names.resize(4);
// Default Pattern 0: Alternating (1010...)
autofire_patterns_names[0] = "Alternating (1010...)";
autofire_patterns[0].resize(2);
autofire_patterns[0][0] = 1;
autofire_patterns[0][1] = 0;
// Default Pattern 1: Alternating at 30FPS (11001100...)
autofire_patterns_names[1] = "Alternating at 30FPS (11001100...)";
autofire_patterns[1].resize(4);
autofire_patterns[1][0] = 1;
autofire_patterns[1][1] = 1;
autofire_patterns[1][2] = 0;
autofire_patterns[1][3] = 0;
// Default Pattern 2: One Quarter (10001000...)
autofire_patterns_names[2] = "One Quarter (10001000...)";
autofire_patterns[2].resize(4);
autofire_patterns[2][0] = 1;
autofire_patterns[2][1] = 0;
autofire_patterns[2][2] = 0;
autofire_patterns[2][3] = 0;
// Default Pattern 3: Tap'n'Hold (1011111111111111111111111111111111111...)
autofire_patterns_names[3] = "Tap'n'Hold (101111111...)";
autofire_patterns[3].resize(1000);
autofire_patterns[3][0] = 1;
autofire_patterns[3][1] = 0;
for (int i = 2; i < 1000; ++i)
autofire_patterns[3][i] = 1;
}
// reset current_pattern if it's outside the range
if (taseditor_config.current_pattern < 0 || taseditor_config.current_pattern >= (int)autofire_patterns.size())
taseditor_config.current_pattern = 0;
taseditor_window.UpdatePatternsMenu();
reset();
}
void EDITOR::free()
{
autofire_patterns.resize(0);
autofire_patterns_names.resize(0);
}
void EDITOR::reset()
{
}
void EDITOR::update()
{
}
// ----------------------------------------------------------------------------------------------
// returns false if couldn't real a string containing at least one char
bool EDITOR::ReadString(EMUFILE *is, std::string& dest)
{
dest.resize(0);
int charr;
while (true)
{
charr = is->fgetc();
if (charr < 0) break;
if (charr == 10 || charr == 13) // end of line
{
if (dest.size())
break; // already collected at least one char
else
continue; // skip the char and continue searching
} else
{
dest.push_back(charr);
}
}
return dest.size() != 0;
}
// ----------------------------------------------------------------------------------------------
// following functions use function parameters to determine range of frames
void EDITOR::InputToggle(int start, int end, int joy, int button)
{
if (joy < 0 || joy >= joysticks_per_frame[GetInputType(currMovieData)]) return;
int check_frame = end;
if (start > end)
{
// swap
int temp_start = start;
start = end;
end = temp_start;
}
if (start < 0) start = end;
if (end >= currMovieData.getNumRecords())
return;
if (currMovieData.records[check_frame].checkBit(joy, button))
{
// clear range
for (int i = start; i <= end; ++i)
currMovieData.records[i].clearBit(joy, button);
greenzone.InvalidateAndCheck(history.RegisterChanges(MODTYPE_UNSET, start, end));
} else
{
// set range
for (int i = start; i <= end; ++i)
currMovieData.records[i].setBit(joy, button);
greenzone.InvalidateAndCheck(history.RegisterChanges(MODTYPE_SET, start, end));
}
}
void EDITOR::InputSetPattern(int start, int end, int joy, int button)
{
if (joy < 0 || joy >= joysticks_per_frame[GetInputType(currMovieData)]) return;
if (start > end)
{
// swap
int temp_start = start;
start = end;
end = temp_start;
}
if (start < 0) start = end;
if (end >= currMovieData.getNumRecords())
return;
int pattern_offset = 0, current_pattern = taseditor_config.current_pattern;
for (int i = start; i <= end; ++i)
{
// skip lag frames
if (taseditor_config.pattern_skips_lag && greenzone.GetLagHistoryAtFrame(i))
continue;
currMovieData.records[i].setBitValue(joy, button, autofire_patterns[current_pattern][pattern_offset] != 0);
pattern_offset++;
if (pattern_offset >= (int)autofire_patterns[current_pattern].size())
pattern_offset -= autofire_patterns[current_pattern].size();
}
greenzone.InvalidateAndCheck(history.RegisterChanges(MODTYPE_PATTERN, start, end, autofire_patterns_names[current_pattern].c_str()));
}
// following functions use current Selection to determine range of frames
bool EDITOR::FrameColumnSet()
{
SelectionFrames* current_selection = selection.MakeStrobe();
if (current_selection->size() == 0) return false;
SelectionFrames::iterator current_selection_begin(current_selection->begin());
SelectionFrames::iterator current_selection_end(current_selection->end());
// inspect the selected frames, if they are all set, then unset all, else set all
bool unset_found = false, changes_made = false;
for(SelectionFrames::iterator it(current_selection_begin); it != current_selection_end; it++)
{
if(!markers_manager.GetMarker(*it))
{
unset_found = true;
break;
}
}
if (unset_found)
{
// set all
for(SelectionFrames::iterator it(current_selection_begin); it != current_selection_end; it++)
{
if(!markers_manager.GetMarker(*it))
{
if (markers_manager.SetMarker(*it))
{
changes_made = true;
piano_roll.RedrawRow(*it);
}
}
}
if (changes_made)
history.RegisterMarkersChange(MODTYPE_MARKER_SET, *current_selection_begin, *current_selection->rbegin());
} else
{
// unset all
for(SelectionFrames::iterator it(current_selection_begin); it != current_selection_end; it++)
{
if(markers_manager.GetMarker(*it))
{
markers_manager.ClearMarker(*it);
changes_made = true;
piano_roll.RedrawRow(*it);
}
}
if (changes_made)
history.RegisterMarkersChange(MODTYPE_MARKER_REMOVE, *current_selection_begin, *current_selection->rbegin());
}
if (changes_made)
selection.must_find_current_marker = playback.must_find_current_marker = true;
return changes_made;
}
bool EDITOR::FrameColumnSetPattern()
{
SelectionFrames* current_selection = selection.MakeStrobe();
if (current_selection->size() == 0) return false;
SelectionFrames::iterator current_selection_begin(current_selection->begin());
SelectionFrames::iterator current_selection_end(current_selection->end());
int pattern_offset = 0, current_pattern = taseditor_config.current_pattern;
bool changes_made = false;
for(SelectionFrames::iterator it(current_selection_begin); it != current_selection_end; it++)
{
// skip lag frames
if (taseditor_config.pattern_skips_lag && greenzone.GetLagHistoryAtFrame(*it))
continue;
if (autofire_patterns[current_pattern][pattern_offset])
{
if(!markers_manager.GetMarker(*it))
{
if (markers_manager.SetMarker(*it))
{
changes_made = true;
piano_roll.RedrawRow(*it);
}
}
} else
{
if(markers_manager.GetMarker(*it))
{
markers_manager.ClearMarker(*it);
changes_made = true;
piano_roll.RedrawRow(*it);
}
}
pattern_offset++;
if (pattern_offset >= (int)autofire_patterns[current_pattern].size())
pattern_offset -= autofire_patterns[current_pattern].size();
}
if (changes_made)
{
history.RegisterMarkersChange(MODTYPE_MARKER_PATTERN, *current_selection_begin, *current_selection->rbegin(), autofire_patterns_names[current_pattern].c_str());
selection.must_find_current_marker = playback.must_find_current_marker = true;
return true;
} else
return false;
}
bool EDITOR::InputColumnSet(int joy, int button)
{
if (joy < 0 || joy >= joysticks_per_frame[GetInputType(currMovieData)]) return false;
SelectionFrames* current_selection = selection.MakeStrobe();
if (current_selection->size() == 0) return false;
SelectionFrames::iterator current_selection_begin(current_selection->begin());
SelectionFrames::iterator current_selection_end(current_selection->end());
//inspect the selected frames, if they are all set, then unset all, else set all
bool newValue = false;
for(SelectionFrames::iterator it(current_selection_begin); it != current_selection_end; it++)
{
if(!(currMovieData.records[*it].checkBit(joy,button)))
{
newValue = true;
break;
}
}
// apply newValue
for(SelectionFrames::iterator it(current_selection_begin); it != current_selection_end; it++)
currMovieData.records[*it].setBitValue(joy,button,newValue);
int first_changes;
if (newValue)
{
first_changes = history.RegisterChanges(MODTYPE_SET, *current_selection_begin, *current_selection->rbegin());
} else
{
first_changes = history.RegisterChanges(MODTYPE_UNSET, *current_selection_begin, *current_selection->rbegin());
}
if (first_changes >= 0)
{
greenzone.InvalidateAndCheck(first_changes);
return true;
} else
return false;
}
bool EDITOR::InputColumnSetPattern(int joy, int button)
{
if (joy < 0 || joy >= joysticks_per_frame[GetInputType(currMovieData)]) return false;
SelectionFrames* current_selection = selection.MakeStrobe();
if (current_selection->size() == 0) return false;
SelectionFrames::iterator current_selection_begin(current_selection->begin());
SelectionFrames::iterator current_selection_end(current_selection->end());
int pattern_offset = 0, current_pattern = taseditor_config.current_pattern;
for(SelectionFrames::iterator it(current_selection_begin); it != current_selection_end; it++)
{
// skip lag frames
if (taseditor_config.pattern_skips_lag && greenzone.GetLagHistoryAtFrame(*it))
continue;
currMovieData.records[*it].setBitValue(joy, button, autofire_patterns[current_pattern][pattern_offset] != 0);
pattern_offset++;
if (pattern_offset >= (int)autofire_patterns[current_pattern].size())
pattern_offset -= autofire_patterns[current_pattern].size();
}
int first_changes = history.RegisterChanges(MODTYPE_PATTERN, *current_selection_begin, *current_selection->rbegin(), autofire_patterns_names[current_pattern].c_str());
if (first_changes >= 0)
{
greenzone.InvalidateAndCheck(first_changes);
return true;
} else
return false;
}
// ----------------------------------------------------------------------------------------------

View File

@ -0,0 +1,29 @@
// Specification file for EDITOR class
class EDITOR
{
public:
EDITOR();
void init();
void free();
void reset();
void update();
void InputToggle(int start, int end, int joy, int button);
void InputSetPattern(int start, int end, int joy, int button);
bool FrameColumnSet();
bool FrameColumnSetPattern();
bool InputColumnSet(int joy, int button);
bool InputColumnSetPattern(int joy, int button);
std::vector<std::string> autofire_patterns_names;
std::vector<std::vector<uint8>> autofire_patterns;
private:
bool ReadString(EMUFILE *is, std::string& dest);
};

View File

@ -80,14 +80,14 @@ char modCaptions[MODTYPES_TOTAL][20] = {" Init Project",
" Marker Branch8 to ",
" Marker Branch9 to ",
" Marker Set",
" Marker Unset",
" Marker Remove",
" Marker Pattern",
" Marker Rename",
" Marker Drag",
" Marker Swap",
" Marker Shift",
" LUA Marker Set",
" LUA Marker Unset",
" LUA Marker Remove",
" LUA Marker Rename",
" LUA Change" };
char LuaCaptionPrefix[6] = " LUA ";
@ -247,7 +247,7 @@ void HISTORY::undo()
int result = jump(history_cursor_pos - 1);
if (result >= 0)
{
piano_roll.update();
piano_roll.UpdateItemCount();
piano_roll.FollowUndo();
greenzone.InvalidateAndCheck(result);
}
@ -258,7 +258,7 @@ void HISTORY::redo()
int result = jump(history_cursor_pos + 1);
if (result >= 0)
{
piano_roll.update();
piano_roll.UpdateItemCount();
piano_roll.FollowUndo();
greenzone.InvalidateAndCheck(result);
}
@ -600,7 +600,7 @@ void HISTORY::RegisterImport(MovieData& md, char* filename)
}
AddSnapshotToHistory(inp);
inp.toMovie(currMovieData);
piano_roll.update();
piano_roll.UpdateItemCount();
bookmarks.ChangesMadeSinceBranch();
project.SetProjectChanged();
greenzone.InvalidateAndCheck(first_changes);
@ -794,7 +794,7 @@ void HISTORY::Click(int row_index)
int result = jump(row_index);
if (result >= 0)
{
piano_roll.update();
piano_roll.UpdateItemCount();
piano_roll.FollowUndo();
greenzone.InvalidateAndCheck(result);
return;

View File

@ -41,14 +41,14 @@ enum
MODTYPE_BRANCH_MARKERS_8,
MODTYPE_BRANCH_MARKERS_9,
MODTYPE_MARKER_SET,
MODTYPE_MARKER_UNSET,
MODTYPE_MARKER_REMOVE,
MODTYPE_MARKER_PATTERN,
MODTYPE_MARKER_RENAME,
MODTYPE_MARKER_DRAG,
MODTYPE_MARKER_SWAP,
MODTYPE_MARKER_SHIFT,
MODTYPE_LUA_MARKER_SET,
MODTYPE_LUA_MARKER_UNSET,
MODTYPE_LUA_MARKER_REMOVE,
MODTYPE_LUA_MARKER_RENAME,
MODTYPE_LUA_CHANGE,

File diff suppressed because it is too large Load Diff

View File

@ -21,10 +21,17 @@
#define BOOST_WHEN_BOTH_RIGHTBUTTON_AND_ALT_PRESSED 4
#define MARKER_DRAG_BOX_ALPHA 175
#define MARKER_DRAG_COUNTDOWN_MAX 14
#define MARKER_DRAG_ALPHA_PER_TICK 13
#define MARKER_DRAG_MAX_SPEED 70
#define MARKER_DRAG_GRAVITY 2
#define DRAWING_MIN_LINE_LEN 14 // = min(list_row_width, list_row_height) in pixels
#define SCROLLING_BORDER_SIZE 8 // in pixels
#define DRAG_SCROLLING_BORDER_SIZE 10 // in pixels
#define DOUBLETAP_COUNT 3 // 1:quick press, 2 - quick release, 3 - quick press
#define ROW_LAST_CLICKED_BLINKING_PERIOD 200
enum
{
@ -75,6 +82,7 @@ enum DRAG_MODES
DRAG_MODE_MARKER,
DRAG_MODE_SET,
DRAG_MODE_UNSET,
DRAG_MODE_SELECTION,
};
// when there's too many button columns, there's need for 2nd Frame# column at the end
@ -145,6 +153,7 @@ public:
void RedrawRow(int index);
void RedrawHeader();
void UpdateItemCount();
bool CheckItemVisible(int frame);
void FollowPlayback();
@ -154,43 +163,46 @@ public:
void FollowPauseframe();
void FollowMarker(int marker_id);
void ColumnSet(int column, bool alt_pressed);
void SetHeaderColumnLight(int column, int level);
void StartDraggingPlaybackCursor();
void AcceleratorDispatched();
void StartDraggingMarker(int mouse_x, int mouse_y, int row_index, int column_index);
void StartSelectingDrag(int start_frame);
void GetDispInfo(NMLVDISPINFO* nmlvDispInfo);
LONG CustomDraw(NMLVCUSTOMDRAW* msg);
LONG HeaderCustomDraw(NMLVCUSTOMDRAW* msg);
void RightClick(LVHITTESTINFO& info);
void StrayClickMenu(LVHITTESTINFO& info);
void RightClickMenu(LVHITTESTINFO& info);
void ToggleJoypadBit(int column_index, int row_index, UINT KeyFlags);
void ColumnSet(int column, bool alt_pressed);
bool FrameColumnSetPattern();
bool FrameColumnSet();
bool InputColumnSetPattern(int joy, int button);
bool InputColumnSet(int joy, int button);
int header_item_under_mouse;
HWND hwndList, hwndHeader;
TRACKMOUSEEVENT tme;
int list_row_top, list_row_height, list_header_height;
bool must_check_item_under_mouse;
int row_under_mouse, real_row_under_mouse, column_under_mouse;
unsigned int drag_mode;
bool rbutton_drag_mode;
bool can_drag_when_seeking;
int marker_drag_box_dx, marker_drag_box_dy;
int marker_drag_box_x, marker_drag_box_y;
int marker_drag_countdown;
int marker_drag_framenum;
int drawing_last_x, drawing_last_y;
int drag_selection_starting_frame;
int drag_selection_ending_frame;
bool must_check_item_under_mouse;
int row_last_clicked;
int row_last_clicked_blinking_phase_shift;
int vk_shift_release_time;
int vk_control_release_time;
bool shift_held, ctrl_held, alt_held;
int shift_timer, ctrl_timer;
int shift_count, ctrl_count;
HWND hwndMarkerDragBox, hwndMarkerDragBoxText;
// GDI stuff

View File

@ -23,7 +23,6 @@ extern int joysticks_per_frame[NUM_SUPPORTED_INPUT_TYPES];
extern uint32 GetGamepadPressedImmediate();
extern int GetInputType(MovieData& md);
extern std::vector<std::vector<uint8>> autofire_patterns;
extern char lagFlag;
extern TASEDITOR_CONFIG taseditor_config;
@ -32,6 +31,7 @@ extern BOOKMARKS bookmarks;
extern HISTORY history;
extern GREENZONE greenzone;
extern PIANO_ROLL piano_roll;
extern EDITOR editor;
// resources
const char recordingCheckbox[10] = "Recording";
@ -132,8 +132,8 @@ void RECORDER::update()
if (!taseditor_config.pattern_skips_lag || lagFlag == 0)
{
pattern_offset++;
if (pattern_offset >= (int)autofire_patterns[old_current_pattern].size())
pattern_offset -= autofire_patterns[old_current_pattern].size();
if (pattern_offset >= (int)editor.autofire_patterns[old_current_pattern].size())
pattern_offset -= editor.autofire_patterns[old_current_pattern].size();
}
}
// update "Recording" checkbox text if something changed in pattern
@ -141,7 +141,7 @@ void RECORDER::update()
{
old_current_pattern = taseditor_config.current_pattern;
old_pattern_offset = pattern_offset;
if (!taseditor_config.pattern_recording || autofire_patterns[old_current_pattern][pattern_offset])
if (!taseditor_config.pattern_recording || editor.autofire_patterns[old_current_pattern][pattern_offset])
// either not using Patterns or current pattern has 1 in current offset
SetWindowText(hwndRecCheckbox, recordingCheckbox);
else
@ -238,7 +238,7 @@ void RECORDER::InputChanged()
for (int i = 0; i < num_joys; ++i)
{
old_joy[i] = history.GetCurrentSnapshot().GetJoystickInfo(currFrameCounter, i);
if (!taseditor_config.pattern_recording || autofire_patterns[old_current_pattern][pattern_offset])
if (!taseditor_config.pattern_recording || editor.autofire_patterns[old_current_pattern][pattern_offset])
new_joy[i] = currMovieData.records[currFrameCounter].joysticks[i];
else
new_joy[i] = 0; // blank

View File

@ -29,6 +29,8 @@ extern TASEDITOR_WINDOW taseditor_window;
extern MARKERS_MANAGER markers_manager;
extern PIANO_ROLL piano_roll;
extern SPLICER splicer;
extern EDITOR editor;
extern GREENZONE greenzone;
extern int joysticks_per_frame[NUM_SUPPORTED_INPUT_TYPES];
@ -441,39 +443,59 @@ void SELECTION::redo()
jump(history_cursor_pos + 1);
}
// ----------------------------------------------------------
bool SELECTION::GetRowSelection(int index)
{
return ListView_GetItemState(piano_roll.hwndList, index, LVIS_SELECTED) != 0;
}
void SELECTION::ClearSelection()
{
ListView_SetItemState(piano_roll.hwndList, -1, 0, LVIS_FOCUSED|LVIS_SELECTED);
ListView_SetItemState(piano_roll.hwndList, -1, 0, LVIS_SELECTED);
}
void SELECTION::ClearRowSelection(int index)
{
ListView_SetItemState(piano_roll.hwndList, index, 0, LVIS_FOCUSED|LVIS_SELECTED);
ListView_SetItemState(piano_roll.hwndList, index, 0, LVIS_SELECTED);
}
void SELECTION::ClearRegionSelection(int start, int end)
{
for (int i = start; i < end; ++i)
ListView_SetItemState(piano_roll.hwndList, i, 0, LVIS_SELECTED);
}
void SELECTION::EnforceSelectionToList()
{
track_selection_changes = false;
ClearSelection();
for(SelectionFrames::reverse_iterator it(CurrentSelection().rbegin()); it != CurrentSelection().rend(); it++)
{
ListView_SetItemState(piano_roll.hwndList, *it, LVIS_SELECTED, LVIS_SELECTED);
}
track_selection_changes = true;
}
void SELECTION::SelectAll()
{
// select all, but remove "focused" from all
ListView_SetItemState(piano_roll.hwndList, -1, LVIS_FOCUSED|LVIS_SELECTED, LVIS_SELECTED);
ListView_SetItemState(piano_roll.hwndList, -1, LVIS_SELECTED, LVIS_SELECTED);
}
void SELECTION::SetRowSelection(int index)
{
ListView_SetItemState(piano_roll.hwndList, index, LVIS_FOCUSED|LVIS_SELECTED, LVIS_FOCUSED|LVIS_SELECTED);
ListView_SetItemState(piano_roll.hwndList, index, LVIS_SELECTED, LVIS_SELECTED);
}
void SELECTION::SetRegionSelection(int start, int end)
{
for (int i = start; i < end; ++i)
ListView_SetItemState(piano_roll.hwndList, i, LVIS_FOCUSED|LVIS_SELECTED, LVIS_FOCUSED|LVIS_SELECTED);
ListView_SetItemState(piano_roll.hwndList, i, LVIS_SELECTED, LVIS_SELECTED);
}
void SELECTION::SetRegionSelectionPattern(int start, int end)
{
int pattern_offset = 0, current_pattern = taseditor_config.current_pattern;
for (int i = start; i <= end; ++i)
{
// skip lag frames
if (taseditor_config.pattern_skips_lag && greenzone.GetLagHistoryAtFrame(i))
continue;
if (editor.autofire_patterns[current_pattern][pattern_offset])
{
ListView_SetItemState(piano_roll.hwndList, i, LVIS_SELECTED, LVIS_SELECTED);
} else
{
ListView_SetItemState(piano_roll.hwndList, i, 0, LVIS_SELECTED);
}
pattern_offset++;
if (pattern_offset >= (int)editor.autofire_patterns[current_pattern].size())
pattern_offset -= editor.autofire_patterns[current_pattern].size();
}
}
void SELECTION::SelectBetweenMarkers()
{
@ -511,7 +533,7 @@ void SELECTION::SelectBetweenMarkers()
// default: select all between markers
for (int i = upper_marker+1; i < lower_marker; ++i)
{
ListView_SetItemState(piano_roll.hwndList, i, LVIS_FOCUSED|LVIS_SELECTED, LVIS_FOCUSED|LVIS_SELECTED);
ListView_SetItemState(piano_roll.hwndList, i, LVIS_SELECTED, LVIS_SELECTED);
}
} else if (upper_border == upper_marker+1 && lower_border == lower_marker-1)
{
@ -520,14 +542,14 @@ void SELECTION::SelectBetweenMarkers()
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_FOCUSED|LVIS_SELECTED, LVIS_FOCUSED|LVIS_SELECTED);
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_FOCUSED|LVIS_SELECTED, LVIS_FOCUSED|LVIS_SELECTED);
ListView_SetItemState(piano_roll.hwndList, i, LVIS_SELECTED, LVIS_SELECTED);
}
} else if (upper_border == upper_marker && lower_border == lower_marker-1)
{
@ -535,14 +557,14 @@ void SELECTION::SelectBetweenMarkers()
if (lower_marker >= movie_size) lower_marker = movie_size - 1;
for (int i = upper_marker+1; i <= lower_marker; ++i)
{
ListView_SetItemState(piano_roll.hwndList, i, LVIS_FOCUSED|LVIS_SELECTED, LVIS_FOCUSED|LVIS_SELECTED);
ListView_SetItemState(piano_roll.hwndList, i, LVIS_SELECTED, LVIS_SELECTED);
}
} 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)
{
ListView_SetItemState(piano_roll.hwndList, i, LVIS_FOCUSED|LVIS_SELECTED, LVIS_FOCUSED|LVIS_SELECTED);
ListView_SetItemState(piano_roll.hwndList, i, LVIS_SELECTED, LVIS_SELECTED);
}
}
}
@ -558,6 +580,48 @@ void SELECTION::ReselectClipboard()
update();
}
void SELECTION::Transpose(int shift)
{
if (!shift) return;
SelectionFrames* current_selection = MakeStrobe();
if (current_selection->size())
{
ClearSelection();
int pos;
if (shift > 0)
{
int movie_size = currMovieData.getNumRecords();
SelectionFrames::reverse_iterator current_selection_rend(current_selection->rend());
for(SelectionFrames::reverse_iterator it(current_selection->rbegin()); it != current_selection_rend; it++)
{
pos = (*it) + shift;
if (pos < movie_size)
ListView_SetItemState(piano_roll.hwndList, pos, LVIS_SELECTED, LVIS_SELECTED);
}
} else
{
SelectionFrames::iterator current_selection_end(current_selection->end());
for(SelectionFrames::iterator it(current_selection->begin()); it != current_selection_end; it++)
{
pos = (*it) + shift;
if (pos >= 0)
ListView_SetItemState(piano_roll.hwndList, pos, LVIS_SELECTED, LVIS_SELECTED);
}
}
}
}
void SELECTION::EnforceSelectionToList()
{
track_selection_changes = false;
ClearSelection();
for(SelectionFrames::reverse_iterator it(CurrentSelection().rbegin()); it != CurrentSelection().rend(); it++)
{
ListView_SetItemState(piano_roll.hwndList, *it, LVIS_SELECTED, LVIS_SELECTED);
}
track_selection_changes = true;
}
// getters
int SELECTION::GetCurrentSelectionSize()
{
@ -570,6 +634,13 @@ int SELECTION::GetCurrentSelectionBeginning()
else
return -1;
}
int SELECTION::GetCurrentSelectionEnd()
{
if (selections_history[(history_start_pos + history_cursor_pos) % history_size].size())
return *selections_history[(history_start_pos + history_cursor_pos) % history_size].rbegin();
else
return -1;
}
bool SELECTION::CheckFrameSelected(int frame)
{
if(CurrentSelection().find(frame) == CurrentSelection().end())

View File

@ -33,17 +33,24 @@ public:
void undo();
void redo();
bool GetRowSelection(int index);
void ClearSelection();
void ClearRowSelection(int index);
void EnforceSelectionToList();
void ClearRegionSelection(int start, int end);
void SelectAll();
void SetRowSelection(int index);
void SetRegionSelection(int start, int end);
void SetRegionSelectionPattern(int start, int end);
void SelectBetweenMarkers();
void ReselectClipboard();
void Transpose(int shift);
void EnforceSelectionToList();
void JumpPrevMarker(int speed = 1);
void JumpNextMarker(int speed = 1);
void JumpToFrame(int frame);
@ -51,6 +58,7 @@ public:
// getters
int GetCurrentSelectionSize();
int GetCurrentSelectionBeginning();
int GetCurrentSelectionEnd();
bool CheckFrameSelected(int frame);
SelectionFrames* MakeStrobe();
SelectionFrames& GetStrobedSelection();

View File

@ -226,7 +226,7 @@ void SPLICER::InsertNumFrames()
if (current_selection->size())
{
// shift selection down, so that same frames are selected
piano_roll.update();
piano_roll.UpdateItemCount();
selection.ClearSelection();
SelectionFrames::iterator current_selection_end = current_selection->end();
for(SelectionFrames::iterator it(current_selection->begin()); it != current_selection_end; it++)
@ -273,7 +273,7 @@ void SPLICER::DeleteFrames()
if (!currMovieData.getNumRecords())
playback.StartFromZero();
// reduce Piano Roll
piano_roll.update();
piano_roll.UpdateItemCount();
// check and register changes
int result = history.RegisterChanges(MODTYPE_DELETE, start_index);
if (result >= 0)
@ -331,7 +331,7 @@ void SPLICER::Truncate()
selection.must_find_current_marker = playback.must_find_current_marker = true;
}
}
piano_roll.update();
piano_roll.UpdateItemCount();
int result = history.RegisterChanges(MODTYPE_TRUNCATE, frame+1);
if (result >= 0)
{
@ -344,7 +344,7 @@ void SPLICER::Truncate()
else
piano_roll.RedrawList();
if (markers_changed)
history.RegisterMarkersChange(MODTYPE_MARKER_UNSET, frame+1, last_frame_was);
history.RegisterMarkersChange(MODTYPE_MARKER_REMOVE, frame+1, last_frame_was);
}
}
}

View File

@ -47,7 +47,6 @@ TASEDITOR_CONFIG::TASEDITOR_CONFIG()
combine_consecutive_rec = true;
use_1p_rec = true;
columnset_by_keys = false;
keyboard_for_piano_roll = true;
superimpose = 0; // SUPERIMPOSE_UNCHECKED
superimpose_affects_paste = true;
branch_full_movie = true;
@ -71,7 +70,6 @@ TASEDITOR_CONFIG::TASEDITOR_CONFIG()
findnote_search_up = false;
enable_auto_function = true;
deselect_on_doubleclick = true;
doubleclick_affects_playback = false;
draw_input = true;
silent_autosave = true;
tooltips = true;

View File

@ -45,7 +45,6 @@ public:
bool combine_consecutive_rec;
bool use_1p_rec;
bool columnset_by_keys;
bool keyboard_for_piano_roll;
int superimpose;
bool superimpose_affects_paste;
bool branch_full_movie;
@ -69,7 +68,6 @@ public:
bool findnote_search_up;
bool enable_auto_function;
bool deselect_on_doubleclick;
bool doubleclick_affects_playback;
bool draw_input;
bool silent_autosave;
bool tooltips;

View File

@ -142,8 +142,8 @@ int TASEDITOR_LUA::setmarker(int frame)
return -1;
}
// taseditor.clearmarker(int frame)
void TASEDITOR_LUA::clearmarker(int frame)
// taseditor.removemarker(int frame)
void TASEDITOR_LUA::removemarker(int frame)
{
if (FCEUMOV_Mode(MOVIEMODE_TASEDITOR))
{
@ -151,7 +151,7 @@ void TASEDITOR_LUA::clearmarker(int frame)
{
markers_manager.ClearMarker(frame);
// marker was deleted - register changes in TAS Editor
history.RegisterMarkersChange(MODTYPE_LUA_MARKER_UNSET, frame);
history.RegisterMarkersChange(MODTYPE_LUA_MARKER_REMOVE, frame);
selection.must_find_current_marker = playback.must_find_current_marker = true;
piano_roll.RedrawRow(frame);
piano_roll.SetHeaderColumnLight(COLUMN_FRAMENUM, HEADER_LIGHT_MAX);
@ -429,7 +429,7 @@ int TASEDITOR_LUA::applyinputchanges(const char* name)
if (!currMovieData.getNumRecords())
playback.StartFromZero();
// reduce Piano Roll
piano_roll.update();
piano_roll.UpdateItemCount();
// check actual changes
int result = history.RegisterLuaChanges(name, start_index, InsertionDeletion_was_made);
if (result >= 0)

View File

@ -44,7 +44,7 @@ public:
bool markedframe(int frame);
int getmarker(int frame);
int setmarker(int frame);
void clearmarker(int frame);
void removemarker(int frame);
const char* getnote(int index);
void setnote(int index, const char* newtext);
int getcurrentbranch();

View File

@ -16,6 +16,7 @@
#include "piano_roll.h"
#include "taseditor_lua.h"
#include "splicer.h"
#include "editor.h"
#include "popup_display.h"
#define AUTOSAVE_PERIOD_SCALE 60000 // = 1 minute in milliseconds

View File

@ -12,7 +12,6 @@ Window - User Interface
* implements all operations with TAS Editor window: creating, redrawing, resizing, moving, tooltips, clicks
* processes OS messages and sends signals from user to TAS Editor modules (also implements some minor commands on-site, like Greenzone capacity dialog and such)
* regularly checks if Shift or Ctrl key is held and sets keyboard focus to Piano Roll
* switches off/on emulator's keyboard input when the window loses/gains focus
* on demand: updates the window caption
* updates all checkboxes and menu items when some settings change
@ -36,6 +35,7 @@ extern RECORDER recorder;
extern TASEDITOR_PROJECT project;
extern PIANO_ROLL piano_roll;
extern SELECTION selection;
extern EDITOR editor;
extern SPLICER splicer;
extern MARKERS_MANAGER markers_manager;
extern BOOKMARKS bookmarks;
@ -45,8 +45,6 @@ extern POPUP_DISPLAY popup_display;
extern bool turbo;
extern bool muteTurbo;
extern bool must_call_manual_lua_function;
extern std::vector<std::string> autofire_patterns_names;
extern std::vector<std::vector<uint8>> autofire_patterns;
extern char* GetKeyComboName(int c);
@ -141,8 +139,8 @@ void TASEDITOR_WINDOW::init()
ShowWindow(hwndTasEditor, SW_SHOWMAXIMIZED);
// menus and checked items
hmenu = GetMenu(hwndTasEditor);
patterns_menu = GetSubMenu(hmenu, PATTERNS_MENU_POS);
UpdateCheckedItems();
patterns_menu = GetSubMenu(hmenu, PATTERNS_MENU_POS);
// tooltips
int x = 0;
for (int i = 0; i < TASEDITOR_WINDOW_TOTAL_ITEMS; ++i)
@ -204,8 +202,6 @@ void TASEDITOR_WINDOW::init()
// create "Recent" submenu
recent_projects_menu = CreateMenu();
UpdateRecentProjectsMenu();
// create "Patterns" menu
UpdatePatternsMenu();
SetTaseditorInput();
reset();
@ -244,14 +240,6 @@ void TASEDITOR_WINDOW::reset()
}
void TASEDITOR_WINDOW::update()
{
if (markers_manager.marker_note_edit == MARKER_NOTE_EDIT_NONE)
{
HWND cur_focus = GetFocus();
if (cur_focus != piano_roll.hwndList && cur_focus != hwndFindNote)
// set focus to Piano Roll when Shift or Ctrl are held
if ((GetAsyncKeyState(VK_CONTROL) < 0) || (GetAsyncKeyState(VK_SHIFT) < 0))
SetFocus(piano_roll.hwndList);
}
}
// --------------------------------------------------------------------------------
void TASEDITOR_WINDOW::CalculateItems()
@ -446,11 +434,9 @@ void TASEDITOR_WINDOW::UpdateCheckedItems()
CheckMenuItem(hmenu, ID_CONFIG_COMBINECONSECUTIVERECORDINGS, taseditor_config.combine_consecutive_rec?MF_CHECKED : MF_UNCHECKED);
CheckMenuItem(hmenu, ID_CONFIG_USE1PFORRECORDING, taseditor_config.use_1p_rec?MF_CHECKED : MF_UNCHECKED);
CheckMenuItem(hmenu, ID_CONFIG_USEINPUTKEYSFORCOLUMNSET, taseditor_config.columnset_by_keys?MF_CHECKED : MF_UNCHECKED);
CheckMenuItem(hmenu, ID_CONFIG_KEYBOARDCONTROLSINPIANOROLL, taseditor_config.keyboard_for_piano_roll?MF_CHECKED : MF_UNCHECKED);
CheckMenuItem(hmenu, ID_CONFIG_SUPERIMPOSE_AFFECTS_PASTE, taseditor_config.superimpose_affects_paste?MF_CHECKED : MF_UNCHECKED);
CheckMenuItem(hmenu, ID_CONFIG_COLUMNSETPATTERNSKIPSLAG, taseditor_config.pattern_skips_lag?MF_CHECKED : MF_UNCHECKED);
CheckMenuItem(hmenu, ID_CONFIG_DESELECTONDOUBLECLICK, taseditor_config.deselect_on_doubleclick?MF_CHECKED : MF_UNCHECKED);
CheckMenuItem(hmenu, ID_CONFIG_DOUBLECLICKONFRAME, taseditor_config.doubleclick_affects_playback?MF_CHECKED : MF_UNCHECKED);
CheckMenuItem(hmenu, ID_CONFIG_DRAWINPUTBYDRAGGING, taseditor_config.draw_input?MF_CHECKED : MF_UNCHECKED);
CheckMenuItem(hmenu, ID_CONFIG_SILENTAUTOSAVE, taseditor_config.silent_autosave?MF_CHECKED : MF_UNCHECKED);
CheckMenuItem(hmenu, ID_CONFIG_MUTETURBO, muteTurbo?MF_CHECKED : MF_UNCHECKED);
@ -593,12 +579,12 @@ void TASEDITOR_WINDOW::UpdatePatternsMenu()
for(x = GetMenuItemCount(patterns_menu); x > 0 ; x--)
RemoveMenu(patterns_menu, 0, MF_BYPOSITION);
// Fill the menu
for(x = autofire_patterns.size() - 1; x >= 0; x--)
for(x = editor.autofire_patterns.size() - 1; x >= 0; x--)
{
moo.fMask = MIIM_DATA | MIIM_ID | MIIM_TYPE;
moo.fType = 0;
moo.wID = MENU_FIRST_PATTERN + x;
std::string tmp = autofire_patterns_names[x];
std::string tmp = editor.autofire_patterns_names[x];
// clamp this string to 50 chars
if(tmp.size() > PATTERNS_MAX_VISIBLE_NAME)
tmp = tmp.substr(0, PATTERNS_MAX_VISIBLE_NAME);
@ -621,7 +607,7 @@ void TASEDITOR_WINDOW::RecheckPatternsMenu()
int x;
x = GetMenuItemInfo(hmenu, PATTERNS_MENU_POS, true, &moo);
std::string tmp = patterns_menu_prefix;
tmp += autofire_patterns_names[taseditor_config.current_pattern];
tmp += editor.autofire_patterns_names[taseditor_config.current_pattern];
// clamp this string
if(tmp.size() > PATTERNMENU_MAX_VISIBLE_NAME)
tmp = tmp.substr(0, PATTERNMENU_MAX_VISIBLE_NAME);
@ -774,7 +760,7 @@ BOOL CALLBACK WndprocTasEditor(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lPara
break;
}
// then check clicking Patterns menu item
if (loword_wparam >= MENU_FIRST_PATTERN && loword_wparam < MENU_FIRST_PATTERN + autofire_patterns.size())
if (loword_wparam >= MENU_FIRST_PATTERN && loword_wparam < MENU_FIRST_PATTERN + editor.autofire_patterns.size())
{
taseditor_config.current_pattern = loword_wparam - MENU_FIRST_PATTERN;
recorder.pattern_offset = 0;
@ -811,14 +797,15 @@ BOOL CALLBACK WndprocTasEditor(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lPara
break;
case ID_EDIT_DESELECT:
case ID_SELECTED_DESELECT:
selection.ClearSelection();
if (piano_roll.drag_mode != DRAG_MODE_SELECTION)
selection.ClearSelection();
break;
case ID_EDIT_SELECTALL:
if (markers_manager.marker_note_edit == MARKER_NOTE_EDIT_UPPER)
SendMessage(playback.hwndPlaybackMarkerEdit, EM_SETSEL, 0, -1);
else if (markers_manager.marker_note_edit == MARKER_NOTE_EDIT_LOWER)
SendMessage(selection.hwndSelectionMarkerEdit, EM_SETSEL, 0, -1);
else
else if (piano_roll.drag_mode != DRAG_MODE_SELECTION)
selection.SelectAll();
break;
case ACCEL_CTRL_X:
@ -1054,10 +1041,6 @@ BOOL CALLBACK WndprocTasEditor(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lPara
taseditor_config.columnset_by_keys ^= 1;
taseditor_window.UpdateCheckedItems();
break;
case ID_CONFIG_KEYBOARDCONTROLSINPIANOROLL:
taseditor_config.keyboard_for_piano_roll ^= 1;
taseditor_window.UpdateCheckedItems();
break;
case ID_CONFIG_SUPERIMPOSE_AFFECTS_PASTE:
taseditor_config.superimpose_affects_paste ^= 1;
taseditor_window.UpdateCheckedItems();
@ -1070,10 +1053,6 @@ BOOL CALLBACK WndprocTasEditor(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lPara
taseditor_config.deselect_on_doubleclick ^= 1;
taseditor_window.UpdateCheckedItems();
break;
case ID_CONFIG_DOUBLECLICKONFRAME:
taseditor_config.doubleclick_affects_playback ^= 1;
taseditor_window.UpdateCheckedItems();
break;
case ID_CONFIG_DRAWINPUTBYDRAGGING:
taseditor_config.draw_input ^= 1;
taseditor_window.UpdateCheckedItems();
@ -1132,12 +1111,13 @@ BOOL CALLBACK WndprocTasEditor(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lPara
SendMessage(playback.hwndPlaybackMarkerEdit, EM_SETSEL, 0, -1);
else if (markers_manager.marker_note_edit == MARKER_NOTE_EDIT_LOWER)
SendMessage(selection.hwndSelectionMarkerEdit, EM_SETSEL, 0, -1);
else
else if (piano_roll.drag_mode != DRAG_MODE_SELECTION)
selection.SelectBetweenMarkers();
break;
case ID_EDIT_SELECTMIDMARKERS:
case ID_SELECTED_SELECTMIDMARKERS:
selection.SelectBetweenMarkers();
if (piano_roll.drag_mode != DRAG_MODE_SELECTION)
selection.SelectBetweenMarkers();
break;
case ACCEL_CTRL_INSERT:
case ID_EDIT_CLONEFRAMES:
@ -1168,22 +1148,31 @@ BOOL CALLBACK WndprocTasEditor(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lPara
case ID_EDIT_SELECTIONUNDO:
case ACCEL_CTRL_Q:
{
selection.undo();
piano_roll.FollowSelection();
if (piano_roll.drag_mode != DRAG_MODE_SELECTION)
{
selection.undo();
piano_roll.FollowSelection();
}
break;
}
case ID_EDIT_SELECTIONREDO:
case ACCEL_CTRL_W:
{
selection.redo();
piano_roll.FollowSelection();
if (piano_roll.drag_mode != DRAG_MODE_SELECTION)
{
selection.redo();
piano_roll.FollowSelection();
}
break;
}
case ID_EDIT_RESELECTCLIPBOARD:
case ACCEL_CTRL_B:
{
selection.ReselectClipboard();
piano_roll.FollowSelection();
if (piano_roll.drag_mode != DRAG_MODE_SELECTION)
{
selection.ReselectClipboard();
piano_roll.FollowSelection();
}
break;
}
case IDC_JUMP_PLAYBACK_BUTTON:
@ -1193,7 +1182,8 @@ BOOL CALLBACK WndprocTasEditor(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lPara
}
case IDC_JUMP_SELECTION_BUTTON:
{
piano_roll.FollowSelection();
if (piano_roll.drag_mode != DRAG_MODE_SELECTION)
piano_roll.FollowSelection();
break;
}
case ID_SELECTED_SETMARKER:
@ -1243,23 +1233,11 @@ BOOL CALLBACK WndprocTasEditor(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lPara
if (changes_made)
{
selection.must_find_current_marker = playback.must_find_current_marker = true;
history.RegisterMarkersChange(MODTYPE_MARKER_UNSET, *current_selection_begin, *current_selection->rbegin());
history.RegisterMarkersChange(MODTYPE_MARKER_REMOVE, *current_selection_begin, *current_selection->rbegin());
}
}
break;
}
case ACCEL_SHIFT_PGUP:
playback.RewindFull();
break;
case ACCEL_SHIFT_PGDN:
playback.ForwardFull();
break;
case ACCEL_CTRL_PGUP:
selection.JumpPrevMarker();
break;
case ACCEL_CTRL_PGDN:
selection.JumpNextMarker();
break;
case ACCEL_CTRL_F:
case ID_VIEW_FINDNOTE:
{
@ -1298,10 +1276,106 @@ BOOL CALLBACK WndprocTasEditor(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lPara
case ID_HELP_ABOUT:
DialogBox(fceu_hInstance, MAKEINTRESOURCE(IDD_TASEDITOR_ABOUT), taseditor_window.hwndTasEditor, AboutProc);
break;
case ID_STRAY_UNPAUSE:
playback.UnpauseEmulation();
case ACCEL_HOME:
// scroll Piano Roll to the beginning
ListView_Scroll(piano_roll.hwndList, 0, -piano_roll.list_row_height * ListView_GetTopIndex(piano_roll.hwndList));
break;
case ACCEL_END:
// scroll Piano Roll to the end
ListView_Scroll(piano_roll.hwndList, 0, piano_roll.list_row_height * currMovieData.getNumRecords());
break;
case ACCEL_PGUP:
// scroll Piano Roll 1 page up
ListView_Scroll(piano_roll.hwndList, 0, -piano_roll.list_row_height * ListView_GetCountPerPage(piano_roll.hwndList));
break;
case ACCEL_PGDN:
// scroll Piano Roll 1 page up
ListView_Scroll(piano_roll.hwndList, 0, piano_roll.list_row_height * ListView_GetCountPerPage(piano_roll.hwndList));
break;
case ACCEL_CTRL_HOME:
{
// transpose Selection to the beginning and scroll to it
if (piano_roll.drag_mode != DRAG_MODE_SELECTION)
{
int selection_beginning = selection.GetCurrentSelectionBeginning();
if (selection_beginning >= 0)
{
selection.Transpose(-selection_beginning);
piano_roll.FollowSelection();
}
}
break;
}
case ACCEL_CTRL_END:
{
// transpose Selection to the end and scroll to it
if (piano_roll.drag_mode != DRAG_MODE_SELECTION)
{
int selection_end = selection.GetCurrentSelectionEnd();
if (selection_end >= 0)
{
selection.Transpose(currMovieData.getNumRecords() - 1 - selection_end);
piano_roll.FollowSelection();
}
}
break;
}
case ACCEL_CTRL_PGUP:
if (piano_roll.drag_mode != DRAG_MODE_SELECTION)
selection.JumpPrevMarker();
break;
case ACCEL_CTRL_PGDN:
if (piano_roll.drag_mode != DRAG_MODE_SELECTION)
selection.JumpNextMarker();
break;
case ACCEL_CTRL_UP:
// transpose Selection 1 frame up and scroll to it
if (piano_roll.drag_mode != DRAG_MODE_SELECTION)
{
selection.Transpose(-1);
piano_roll.FollowSelection();
}
break;
case ACCEL_CTRL_DOWN:
// transpose Selection 1 frame down and scroll to it
if (piano_roll.drag_mode != DRAG_MODE_SELECTION)
{
selection.Transpose(1);
piano_roll.FollowSelection();
}
break;
case ACCEL_CTRL_LEFT:
case ACCEL_SHIFT_LEFT:
// scroll Piano Roll horizontally to the left
ListView_Scroll(piano_roll.hwndList, -COLUMN_BUTTON_WIDTH, 0);
break;
case ACCEL_CTRL_RIGHT:
case ACCEL_SHIFT_RIGHT:
// scroll Piano Roll horizontally to the right
ListView_Scroll(piano_roll.hwndList, COLUMN_BUTTON_WIDTH, 0);
break;
case ACCEL_SHIFT_HOME:
// send Playback to the beginning
playback.jump(0);
break;
case ACCEL_SHIFT_END:
// send Playback to the end
playback.jump(currMovieData.getNumRecords() - 1);
break;
case ACCEL_SHIFT_PGUP:
playback.RewindFull();
break;
case ACCEL_SHIFT_PGDN:
playback.ForwardFull();
break;
case ACCEL_SHIFT_UP:
// rewind 1 frame
playback.RewindFrame();
break;
case ACCEL_SHIFT_DOWN:
// step forward 1 frame
playback.ForwardFrame();
break;
}
break;

View File

@ -24,12 +24,6 @@ struct Window_items_struct
HWND tooltip_hwnd;
};
enum ECONTEXTMENU
{
CONTEXTMENU_STRAY = 0,
CONTEXTMENU_SELECTED = 1,
};
class TASEDITOR_WINDOW
{
public:

View File

@ -4398,11 +4398,11 @@ static int taseditor_setmarker(lua_State *L)
return 1;
}
// taseditor.clearmarker(int frame)
static int taseditor_clearmarker(lua_State *L)
// taseditor.removemarker(int frame)
static int taseditor_removemarker(lua_State *L)
{
#ifdef WIN32
taseditor_lua.clearmarker(luaL_checkinteger(L, 1));
taseditor_lua.removemarker(luaL_checkinteger(L, 1));
#endif
return 0;
}
@ -5387,7 +5387,7 @@ static const struct luaL_reg taseditorlib[] = {
{"markedframe", taseditor_markedframe},
{"getmarker", taseditor_getmarker},
{"setmarker", taseditor_setmarker},
{"clearmarker", taseditor_clearmarker},
{"removemarker", taseditor_removemarker},
{"getnote", taseditor_getnote},
{"setnote", taseditor_setnote},
{"getcurrentbranch", taseditor_getcurrentbranch},

View File

@ -422,6 +422,7 @@
<ClCompile Include="..\src\drivers\win\taseditor.cpp" />
<ClCompile Include="..\src\drivers\win\taseditor\bookmark.cpp" />
<ClCompile Include="..\src\drivers\win\taseditor\bookmarks.cpp" />
<ClCompile Include="..\src\drivers\win\taseditor\editor.cpp" />
<ClCompile Include="..\src\drivers\win\taseditor\greenzone.cpp" />
<ClCompile Include="..\src\drivers\win\taseditor\history.cpp" />
<ClCompile Include="..\src\drivers\win\taseditor\markers.cpp" />
@ -748,6 +749,7 @@
<ClInclude Include="..\src\drivers\win\taseditor.h" />
<ClInclude Include="..\src\drivers\win\taseditor\bookmark.h" />
<ClInclude Include="..\src\drivers\win\taseditor\bookmarks.h" />
<ClInclude Include="..\src\drivers\win\taseditor\editor.h" />
<ClInclude Include="..\src\drivers\win\taseditor\greenzone.h" />
<ClInclude Include="..\src\drivers\win\taseditor\history.h" />
<ClInclude Include="..\src\drivers\win\taseditor\markers.h" />

View File

@ -955,6 +955,9 @@
<ClCompile Include="..\src\drivers\win\taseditor\selection.cpp">
<Filter>drivers\win\taseditor</Filter>
</ClCompile>
<ClCompile Include="..\src\drivers\win\taseditor\editor.cpp">
<Filter>drivers\win\taseditor</Filter>
</ClCompile>
</ItemGroup>
<ItemGroup>
<ClInclude Include="..\src\cart.h">
@ -1444,6 +1447,9 @@
<ClInclude Include="..\src\drivers\win\taseditor\selection.h">
<Filter>drivers\win\taseditor</Filter>
</ClInclude>
<ClInclude Include="..\src\drivers\win\taseditor\editor.h">
<Filter>drivers\win\taseditor</Filter>
</ClInclude>
</ItemGroup>
<ItemGroup>
<ResourceCompile Include="..\src\drivers\win\res.rc">