Qt TAS editor mouse tracking in work.

This commit is contained in:
mjbudd77 2021-11-02 21:52:59 -04:00
parent ffe8aacdc1
commit 7dce4b650b
3 changed files with 833 additions and 0 deletions

View File

@ -22,6 +22,7 @@
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <math.h>
#include <string>
#include <QDir>
@ -32,6 +33,7 @@
#include <QFontMetrics>
#include <QFileDialog>
#include <QStandardPaths>
#include <QApplication>
#include "fceu.h"
#include "movie.h"
@ -58,6 +60,58 @@ HISTORY *history = NULL;
SPLICER *splicer = NULL;
// Piano Roll Definitions
enum PIANO_ROLL_COLUMNS
{
COLUMN_ICONS,
COLUMN_FRAMENUM,
COLUMN_JOYPAD1_A,
COLUMN_JOYPAD1_B,
COLUMN_JOYPAD1_S,
COLUMN_JOYPAD1_T,
COLUMN_JOYPAD1_U,
COLUMN_JOYPAD1_D,
COLUMN_JOYPAD1_L,
COLUMN_JOYPAD1_R,
COLUMN_JOYPAD2_A,
COLUMN_JOYPAD2_B,
COLUMN_JOYPAD2_S,
COLUMN_JOYPAD2_T,
COLUMN_JOYPAD2_U,
COLUMN_JOYPAD2_D,
COLUMN_JOYPAD2_L,
COLUMN_JOYPAD2_R,
COLUMN_JOYPAD3_A,
COLUMN_JOYPAD3_B,
COLUMN_JOYPAD3_S,
COLUMN_JOYPAD3_T,
COLUMN_JOYPAD3_U,
COLUMN_JOYPAD3_D,
COLUMN_JOYPAD3_L,
COLUMN_JOYPAD3_R,
COLUMN_JOYPAD4_A,
COLUMN_JOYPAD4_B,
COLUMN_JOYPAD4_S,
COLUMN_JOYPAD4_T,
COLUMN_JOYPAD4_U,
COLUMN_JOYPAD4_D,
COLUMN_JOYPAD4_L,
COLUMN_JOYPAD4_R,
COLUMN_FRAMENUM2,
TOTAL_COLUMNS
};
enum DRAG_MODES
{
DRAG_MODE_NONE,
DRAG_MODE_OBSERVE,
DRAG_MODE_PLAYBACK,
DRAG_MODE_MARKER,
DRAG_MODE_SET,
DRAG_MODE_UNSET,
DRAG_MODE_SELECTION,
DRAG_MODE_DESELECTION,
};
#define BOOKMARKS_WITH_BLUE_ARROW 20
#define BOOKMARKS_WITH_GREEN_ARROW 40
#define BLUE_ARROW_IMAGE_ID 60
@ -150,6 +204,7 @@ SPLICER *splicer = NULL;
#define PLAYBACK_MARKER_COLOR 0xC9AF00
#define MARKER_DRAG_COUNTDOWN_MAX 14
//----------------------------------------------------------------------------
//---- Main TAS Editor Window
@ -495,6 +550,12 @@ void TasEditorWindow::buildSideControlPanel(void)
QHBoxLayout *hbox;
QGridLayout *grid;
patternsNames.resize(4);
patternsNames[0] = "Alternating (1010...)";
patternsNames[1] = "Alternating at 30FPS (11001100...)";
patternsNames[2] = "One Quarter (10001000...)";
patternsNames[3] = "Tap'n'Hold (101111111...)";
ctlPanelMainVbox = new QVBoxLayout();
playbackGBox = new QGroupBox( tr("Playback") );
@ -1152,6 +1213,75 @@ void TasEditorWindow::playbackFrameForwardFull(void)
pianoRoll->update();
fceuWrapperUnLock();
}
// ----------------------------------------------------------------------------------------------
// following functions use function parameters to determine range of frames
void TasEditorWindow::toggleInput(int start, int end, int joy, int button, int consecutivenessTag)
{
if (joy < 0 || joy >= joysticksPerFrame[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.invalidateAndUpdatePlayback(history.registerChanges(MODTYPE_UNSET, start, end, 0, NULL, consecutivenessTag));
} else
{
// set range
for (int i = start; i <= end; ++i)
currMovieData.records[i].setBit(joy, button);
greenzone.invalidateAndUpdatePlayback(history.registerChanges(MODTYPE_SET, start, end, 0, NULL, consecutivenessTag));
}
}
void TasEditorWindow::setInputUsingPattern(int start, int end, int joy, int button, int consecutivenessTag)
{
if (joy < 0 || joy >= joysticksPerFrame[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 = taseditorConfig.currentPattern;
bool changes_made = false;
bool value;
for (int i = start; i <= end; ++i)
{
// skip lag frames
if (taseditorConfig.autofirePatternSkipsLag && greenzone.lagLog.getLagInfoAtFrame(i) == LAGGED_YES)
continue;
value = (patterns[current_pattern][pattern_offset] != 0);
if (currMovieData.records[i].checkBit(joy, button) != value)
{
changes_made = true;
currMovieData.records[i].setBitValue(joy, button, value);
}
pattern_offset++;
if (pattern_offset >= (int)patterns[current_pattern].size())
pattern_offset -= patterns[current_pattern].size();
}
if (changes_made)
greenzone.invalidateAndUpdatePlayback(history.registerChanges(MODTYPE_PATTERN, start, end, 0, patternsNames[current_pattern].c_str(), consecutivenessTag));
}
//----------------------------------------------------------------------------
//----------------------------------------------------------------------------
//---- TAS Piano Roll Widget
@ -1219,6 +1349,14 @@ QPianoRoll::QPianoRoll(QWidget *parent)
lineOffset = 0;
maxLineOffset = 0;
dragMode = DRAG_MODE_NONE;
dragSelectionStartingFrame = 0;
dragSelectionEndingFrame = 0;
realRowUnderMouse = -1;
markerDragFrameNumber = 0;
markerDragCountdown = 0;
drawingStartTimestamp = 0;
mouse_x = mouse_y = -1;
}
//----------------------------------------------------------------------------
QPianoRoll::~QPianoRoll(void)
@ -1292,6 +1430,65 @@ void QPianoRoll::calcFontData(void)
pxLineWidth = pxFrameCtlX[ numCtlr-1 ] + pxWidthCtlCol;
}
//----------------------------------------------------------------------------
QPoint QPianoRoll::convPixToCursor( QPoint p )
{
QPoint c(0,0);
if ( p.x() < 0 )
{
c.setX(0);
}
else
{
float x = (float)(p.x() + pxLineXScroll) / pxCharWidth;
c.setX( (int)x );
}
if ( p.y() < 0 )
{
c.setY( -1 );
}
else
{
float py = ( (float)p.y() ) / (float)pxLineSpacing;
c.setY( (int)py - 1 );
}
return c;
}
//----------------------------------------------------------------------------
int QPianoRoll::calcColumn( int px )
{
int col = -1;
px = px + pxLineXScroll;
if ( px < pxFrameColX )
{
col = COLUMN_ICONS;
}
else if ( px < pxFrameCtlX[0] )
{
col = COLUMN_FRAMENUM;
}
else
{
int i=0;
while ( px < pxFrameCtlX[i] )
{
if ( i >= 3 )
{
break;
}
i++;
}
col = COLUMN_JOYPAD1_A + (i*8) + ( (px - pxFrameCtlX[i]) / pxWidthBtnCol);
}
return col;
}
//----------------------------------------------------------------------------
void QPianoRoll::drawArrow( QPainter *painter, int xl, int yl, int value )
{
int x, y, w, h, b, b2;
@ -1355,6 +1552,612 @@ void QPianoRoll::resizeEvent(QResizeEvent *event)
vbar->setPageStep( (3*viewLines)/4 );
}
//----------------------------------------------------------------------------
void QPianoRoll::mousePressEvent(QMouseEvent * event)
{
int col, line, row_index, column_index, kbModifiers, alt_pressed;
QPoint c = convPixToCursor( event->pos() );
mouse_x = event->pos().x();
mouse_y = event->pos().y();
line = lineOffset + c.y();
col = calcColumn( event->pos().x() );
row_index = line;
rowUnderMouse = realRowUnderMouse = line;
columnUnderMouse = column_index = col;
kbModifiers = QApplication::keyboardModifiers();
alt_pressed = (kbModifiers & Qt::AltModifier) ? 1 : 0;
printf("Mouse Button Pressed: 0x%x (%i,%i)\n", event->button(), c.x(), c.y() );
if ( event->button() == Qt::LeftButton )
{
if (col == COLUMN_ICONS)
{
// clicked on the "icons" column
startDraggingPlaybackCursor();
}
else if ( (col == COLUMN_FRAMENUM) || (col == COLUMN_FRAMENUM2) )
{
// clicked on the "Frame#" column
if (row_index >= 0)
{
if (kbModifiers & Qt::ShiftModifier)
{
// select region from selection_beginning to row_index
int selection_beginning = selection->getCurrentRowsSelectionBeginning();
if (selection_beginning >= 0)
{
if (selection_beginning < row_index)
{
selection->setRegionOfRowsSelection(selection_beginning, row_index + 1);
}
else
{
selection->setRegionOfRowsSelection(row_index, selection_beginning + 1);
}
}
startSelectingDrag(row_index);
}
else if (kbModifiers & Qt::AltModifier)
{
// make Selection by Pattern
int selection_beginning = selection->getCurrentRowsSelectionBeginning();
if (selection_beginning >= 0)
{
selection->clearAllRowsSelection();
if (selection_beginning < row_index)
{
selection->setRegionOfRowsSelectionUsingPattern(selection_beginning, row_index);
}
else
{
selection->setRegionOfRowsSelectionUsingPattern(row_index, selection_beginning);
}
}
if (selection->isRowSelected(row_index))
{
startDeselectingDrag(row_index);
}
else
{
startSelectingDrag(row_index);
}
}
else if (kbModifiers & Qt::ControlModifier)
{
// clone current selection, so that user will be able to revert
if (selection->getCurrentRowsSelectionSize() > 0)
{
selection->addCurrentSelectionToHistory();
}
if (selection->isRowSelected(row_index))
{
selection->clearSingleRowSelection(row_index);
startDeselectingDrag(row_index);
}
else
{
selection->setRowSelection(row_index);
startSelectingDrag(row_index);
}
}
else // just click
{
selection->clearAllRowsSelection();
selection->setRowSelection(row_index);
startSelectingDrag(row_index);
}
}
}
else if (column_index >= COLUMN_JOYPAD1_A && column_index <= COLUMN_JOYPAD4_R)
{
// clicked on Input
if (row_index >= 0)
{
if (!alt_pressed && !(kbModifiers & Qt::ShiftModifier))
{
// clicked without Shift/Alt - bring Selection cursor to this row
selection->clearAllRowsSelection();
selection->setRowSelection(row_index);
}
// toggle Input
drawingStartTimestamp = clock();
int joy = (column_index - COLUMN_JOYPAD1_A) / NUM_JOYPAD_BUTTONS;
int button = (column_index - COLUMN_JOYPAD1_A) % NUM_JOYPAD_BUTTONS;
int selection_beginning = selection->getCurrentRowsSelectionBeginning();
if (alt_pressed && selection_beginning >= 0)
{
tasWin->setInputUsingPattern(selection_beginning, row_index, joy, button, drawingStartTimestamp);
}
else if ((kbModifiers & Qt::ShiftModifier) && selection_beginning >= 0)
{
tasWin->toggleInput(selection_beginning, row_index, joy, button, drawingStartTimestamp);
}
else
{
tasWin->toggleInput(row_index, row_index, joy, button, drawingStartTimestamp);
}
// and start dragging/drawing
if (dragMode == DRAG_MODE_NONE)
{
if (taseditorConfig->drawInputByDragging)
{
// if clicked this click created buttonpress, then start painting, else start erasing
if (currMovieData.records[row_index].checkBit(joy, button))
{
dragMode = DRAG_MODE_SET;
}
else
{
dragMode = DRAG_MODE_UNSET;
}
//pianoRoll.drawingLastX = GET_X_LPARAM(lParam) + GetScrollPos(pianoRoll.hwndList, SB_HORZ);
//pianoRoll.drawingLastY = GET_Y_LPARAM(lParam) + GetScrollPos(pianoRoll.hwndList, SB_VERT) * pianoRoll.listRowHeight;
}
else
{
dragMode = DRAG_MODE_OBSERVE;
}
}
}
}
//updateDrag();
}
}
//----------------------------------------------------------------------------
void QPianoRoll::mouseReleaseEvent(QMouseEvent * event)
{
int col, line;
QPoint c = convPixToCursor( event->pos() );
mouse_x = event->pos().x();
mouse_y = event->pos().y();
line = lineOffset + c.y();
col = calcColumn( event->pos().x() );
rowUnderMouse = realRowUnderMouse = line;
columnUnderMouse = col;
printf("Mouse Button Released: 0x%x (%i,%i)\n", event->button(), c.x(), c.y() );
if ( event->button() == Qt::LeftButton )
{
if (dragMode != DRAG_MODE_NONE)
{
// check if user released left button
finishDrag();
}
}
}
//----------------------------------------------------------------------------
void QPianoRoll::mouseMoveEvent(QMouseEvent * event)
{
int col, line;
QPoint c = convPixToCursor( event->pos() );
mouse_x = event->pos().x();
mouse_y = event->pos().y();
line = lineOffset + c.y();
col = calcColumn( event->pos().x() );
rowUnderMouse = realRowUnderMouse = line;
columnUnderMouse = col;
printf("Mouse Move Event: 0x%x (%i,%i) Col:%i\n", event->button(), c.x(), c.y(), col );
if ( event->button() == Qt::LeftButton )
{
}
updateDrag();
}
//----------------------------------------------------------------------------
void QPianoRoll::updateDrag(void)
{
int kbModifiers, altHeld;
if ( dragMode == DRAG_MODE_NONE )
{
return;
}
kbModifiers = QApplication::keyboardModifiers();
altHeld = (kbModifiers & Qt::AltModifier) ? 1 : 0;
// perform drag
switch (dragMode)
{
case DRAG_MODE_PLAYBACK:
{
handlePlaybackCursorDragging();
break;
}
case DRAG_MODE_MARKER:
{
// if suddenly source frame lost its Marker, abort drag
if (!markersManager->getMarkerAtFrame(markerDragFrameNumber))
{
//if (hwndMarkerDragBox)
//{
// DestroyWindow(hwndMarkerDragBox);
// hwndMarkerDragBox = 0;
//}
dragMode = DRAG_MODE_NONE;
break;
}
// when dragging, always show semi-transparent yellow rectangle under mouse
//POINT p = {0, 0};
//GetCursorPos(&p);
//markerDragBoxX = p.x - markerDragBoxDX;
//markerDragBoxY = p.y - markerDragBoxDY;
//if (!hwndMarkerDragBox)
//{
// hwndMarkerDragBox = CreateWindowEx(WS_EX_LAYERED | WS_EX_TRANSPARENT, markerDragBoxClassName, markerDragBoxClassName, WS_POPUP, markerDragBoxX, markerDragBoxY, COLUMN_FRAMENUM_WIDTH, listRowHeight, taseditorWindow.hwndTASEditor, NULL, fceu_hInstance, NULL);
// ShowWindow(hwndMarkerDragBox, SW_SHOWNA);
//} else
//{
// SetWindowPos(hwndMarkerDragBox, 0, markerDragBoxX, markerDragBoxY, 0, 0, SWP_NOSIZE|SWP_NOZORDER|SWP_NOACTIVATE);
//}
//SetLayeredWindowAttributes(hwndMarkerDragBox, 0, MARKER_DRAG_BOX_ALPHA, LWA_ALPHA);
//UpdateLayeredWindow(hwndMarkerDragBox, 0, 0, 0, 0, 0, 0, &blend, ULW_ALPHA);
break;
}
case DRAG_MODE_SET:
case DRAG_MODE_UNSET:
{
//ScreenToClient(hwndList, &p);
//int drawing_current_x = p.x + GetScrollPos(hwndList, SB_HORZ);
//int drawing_current_y = p.y + GetScrollPos(hwndList, SB_VERT) * listRowHeight;
//// draw (or erase) line from [drawing_current_x, drawing_current_y] to (drawing_last_x, drawing_last_y)
//int total_dx = drawingLastX - drawing_current_x, total_dy = drawingLastY - drawing_current_y;
//if (!shiftHeld)
//{
// // when user is not holding Shift, draw only vertical lines
// total_dx = 0;
// drawing_current_x = drawingLastX;
// p.x = drawing_current_x - GetScrollPos(hwndList, SB_HORZ);
//}
//LVHITTESTINFO info;
int row_index, column_index, joy, bit;
int min_row_index = currMovieData.getNumRecords(), max_row_index = -1;
bool changes_made = false;
if (altHeld)
{
// special mode: draw pattern
int selection_beginning = selection->getCurrentRowsSelectionBeginning();
if (selection_beginning >= 0)
{
// perform hit test
//info.pt.x = p.x;
//info.pt.y = p.y;
//ListView_SubItemHitTest(hwndList, &info);
row_index = rowUnderMouse;
//if (row_index < 0)
//{
// row_index = ListView_GetTopIndex(hwndList) + (info.pt.y - listTopMargin) / listRowHeight;
//}
// pad movie size if user tries to draw pattern below Piano Roll limit
if (row_index >= currMovieData.getNumRecords())
{
currMovieData.insertEmpty(-1, row_index + 1 - currMovieData.getNumRecords());
}
column_index = columnUnderMouse;
if (row_index >= 0 && column_index >= COLUMN_JOYPAD1_A && column_index <= COLUMN_JOYPAD4_R)
{
joy = (column_index - COLUMN_JOYPAD1_A) / NUM_JOYPAD_BUTTONS;
bit = (column_index - COLUMN_JOYPAD1_A) % NUM_JOYPAD_BUTTONS;
tasWin->setInputUsingPattern(selection_beginning, row_index, joy, bit, drawingStartTimestamp);
}
}
}
else
{
//double total_len = sqrt((double)(total_dx * total_dx + total_dy * total_dy));
//int drawing_min_line_len = listRowHeight; // = min(list_row_width, list_row_height) in pixels
//for (double len = 0; len < total_len; len += drawing_min_line_len)
//{
// perform hit test
//info.pt.x = p.x + (len / total_len) * total_dx;
//info.pt.y = p.y + (len / total_len) * total_dy;
//ListView_SubItemHitTest(hwndList, &info);
//row_index = info.iItem;
row_index = rowUnderMouse;
//if (row_index < 0)
// row_index = ListView_GetTopIndex(hwndList) + (info.pt.y - listTopMargin) / listRowHeight;
// pad movie size if user tries to draw below Piano Roll limit
if (row_index >= currMovieData.getNumRecords())
{
currMovieData.insertEmpty(-1, row_index + 1 - currMovieData.getNumRecords());
}
column_index = columnUnderMouse;
if (row_index >= 0 && column_index >= COLUMN_JOYPAD1_A && column_index <= COLUMN_JOYPAD4_R)
{
joy = (column_index - COLUMN_JOYPAD1_A) / NUM_JOYPAD_BUTTONS;
bit = (column_index - COLUMN_JOYPAD1_A) % NUM_JOYPAD_BUTTONS;
if (dragMode == DRAG_MODE_SET && !currMovieData.records[row_index].checkBit(joy, bit))
{
currMovieData.records[row_index].setBit(joy, bit);
changes_made = true;
if (min_row_index > row_index) min_row_index = row_index;
if (max_row_index < row_index) max_row_index = row_index;
}
else if (dragMode == DRAG_MODE_UNSET && currMovieData.records[row_index].checkBit(joy, bit))
{
currMovieData.records[row_index].clearBit(joy, bit);
changes_made = true;
if (min_row_index > row_index) min_row_index = row_index;
if (max_row_index < row_index) max_row_index = row_index;
}
}
//}
if (changes_made)
{
if (dragMode == DRAG_MODE_SET)
{
greenzone->invalidateAndUpdatePlayback(history->registerChanges(MODTYPE_SET, min_row_index, max_row_index, 0, NULL, drawingStartTimestamp));
}
else
{
greenzone->invalidateAndUpdatePlayback(history->registerChanges(MODTYPE_UNSET, min_row_index, max_row_index, 0, NULL, drawingStartTimestamp));
}
}
}
//drawingLastX = drawing_current_x;
//drawingLastY = drawing_current_y;
break;
}
case DRAG_MODE_SELECTION:
{
int new_drag_selection_ending_frame = realRowUnderMouse;
// if trying to select above Piano Roll, select from frame 0
if (new_drag_selection_ending_frame < 0)
new_drag_selection_ending_frame = 0;
else if (new_drag_selection_ending_frame >= currMovieData.getNumRecords())
new_drag_selection_ending_frame = currMovieData.getNumRecords() - 1;
if (new_drag_selection_ending_frame >= 0 && new_drag_selection_ending_frame != dragSelectionEndingFrame)
{
// change Selection shape
if (new_drag_selection_ending_frame >= dragSelectionStartingFrame)
{
// selecting from upper to lower
if (dragSelectionEndingFrame < dragSelectionStartingFrame)
{
selection->clearRegionOfRowsSelection(dragSelectionEndingFrame, dragSelectionStartingFrame);
selection->setRegionOfRowsSelection(dragSelectionStartingFrame, new_drag_selection_ending_frame + 1);
} else // both ending_frame and new_ending_frame are >= starting_frame
{
if (dragSelectionEndingFrame > new_drag_selection_ending_frame)
selection->clearRegionOfRowsSelection(new_drag_selection_ending_frame + 1, dragSelectionEndingFrame + 1);
else
selection->setRegionOfRowsSelection(dragSelectionEndingFrame + 1, new_drag_selection_ending_frame + 1);
}
} else
{
// selecting from lower to upper
if (dragSelectionEndingFrame > dragSelectionStartingFrame)
{
selection->clearRegionOfRowsSelection(dragSelectionStartingFrame + 1, dragSelectionEndingFrame + 1);
selection->setRegionOfRowsSelection(new_drag_selection_ending_frame, dragSelectionStartingFrame);
} else // both ending_frame and new_ending_frame are <= starting_frame
{
if (dragSelectionEndingFrame < new_drag_selection_ending_frame)
selection->clearRegionOfRowsSelection(dragSelectionEndingFrame, new_drag_selection_ending_frame);
else
selection->setRegionOfRowsSelection(new_drag_selection_ending_frame, dragSelectionEndingFrame);
}
}
dragSelectionEndingFrame = new_drag_selection_ending_frame;
}
break;
}
case DRAG_MODE_DESELECTION:
{
int new_drag_selection_ending_frame = realRowUnderMouse;
// if trying to deselect above Piano Roll, deselect from frame 0
if (new_drag_selection_ending_frame < 0)
new_drag_selection_ending_frame = 0;
else if (new_drag_selection_ending_frame >= currMovieData.getNumRecords())
new_drag_selection_ending_frame = currMovieData.getNumRecords() - 1;
if (new_drag_selection_ending_frame >= 0 && new_drag_selection_ending_frame != dragSelectionEndingFrame)
{
// change Deselection shape
if (new_drag_selection_ending_frame >= dragSelectionStartingFrame)
// deselecting from upper to lower
selection->clearRegionOfRowsSelection(dragSelectionStartingFrame, new_drag_selection_ending_frame + 1);
else
// deselecting from lower to upper
selection->clearRegionOfRowsSelection(new_drag_selection_ending_frame, dragSelectionStartingFrame + 1);
dragSelectionEndingFrame = new_drag_selection_ending_frame;
}
break;
}
}
}
//----------------------------------------------------------------------------
void QPianoRoll::startDraggingPlaybackCursor(void)
{
if (dragMode == DRAG_MODE_NONE)
{
dragMode = DRAG_MODE_PLAYBACK;
// call it once
handlePlaybackCursorDragging();
}
}
void QPianoRoll::startDraggingMarker(int mouseX, int mouseY, int rowIndex, int columnIndex)
{
if (dragMode == DRAG_MODE_NONE)
{
// start dragging the Marker
dragMode = DRAG_MODE_MARKER;
markerDragFrameNumber = rowIndex;
markerDragCountdown = MARKER_DRAG_COUNTDOWN_MAX;
//RECT temp_rect;
//if (ListView_GetSubItemRect(hwndList, rowIndex, columnIndex, LVIR_BOUNDS, &temp_rect))
//{
// markerDragBoxDX = mouseX - temp_rect.left;
// markerDragBoxDY = mouseY - temp_rect.top;
//} else
//{
// markerDragBoxDX = 0;
// markerDragBoxDY = 0;
//}
//// redraw the row to show that Marker was lifted
//redrawRow(rowIndex);
update();
}
}
void QPianoRoll::startSelectingDrag(int start_frame)
{
if (dragMode == DRAG_MODE_NONE)
{
dragMode = DRAG_MODE_SELECTION;
dragSelectionStartingFrame = start_frame;
dragSelectionEndingFrame = dragSelectionStartingFrame; // assuming that start_frame is already selected
}
}
void QPianoRoll::startDeselectingDrag(int start_frame)
{
if (dragMode == DRAG_MODE_NONE)
{
dragMode = DRAG_MODE_DESELECTION;
dragSelectionStartingFrame = start_frame;
dragSelectionEndingFrame = dragSelectionStartingFrame; // assuming that start_frame is already deselected
}
}
void QPianoRoll::handlePlaybackCursorDragging(void)
{
int target_frame = realRowUnderMouse;
if (target_frame < 0)
{
target_frame = 0;
}
if (currFrameCounter != target_frame)
{
playback->jump(target_frame);
}
}
void QPianoRoll::finishDrag(void)
{
switch (dragMode)
{
case DRAG_MODE_MARKER:
{
// place Marker here
if (markersManager->getMarkerAtFrame(markerDragFrameNumber))
{
//POINT p = {0, 0};
//GetCursorPos(&p);
//int mouse_x = p.x, mouse_y = p.y;
//ScreenToClient(hwndList, &p);
//RECT wrect;
//GetClientRect(hwndList, &wrect);
if (mouse_x < 0 || mouse_x > viewWidth || mouse_y < 0 || mouse_y > viewHeight)
{
// user threw the Marker away
markersManager->removeMarkerFromFrame(markerDragFrameNumber);
//redrawRow(markerDragFrameNumber);
history->registerMarkersChange(MODTYPE_MARKER_REMOVE, markerDragFrameNumber);
selection->mustFindCurrentMarker = playback->mustFindCurrentMarker = true;
// calculate vector of movement
//POINT p = {0, 0};
//GetCursorPos(&p);
//markerDragBoxDX = (mouse_x - markerDragBoxDX) - markerDragBoxX;
//markerDragBoxDY = (mouse_y - markerDragBoxDY) - markerDragBoxY;
//if (markerDragBoxDX || markerDragBoxDY)
//{
// // limit max speed
// double marker_drag_box_speed = sqrt((double)(markerDragBoxDX * markerDragBoxDX + markerDragBoxDY * markerDragBoxDY));
// if (marker_drag_box_speed > MARKER_DRAG_MAX_SPEED)
// {
// markerDragBoxDX *= MARKER_DRAG_MAX_SPEED / marker_drag_box_speed;
// markerDragBoxDY *= MARKER_DRAG_MAX_SPEED / marker_drag_box_speed;
// }
//}
//markerDragCountdown = MARKER_DRAG_COUNTDOWN_MAX;
}
else
{
if (rowUnderMouse >= 0 && (columnUnderMouse <= COLUMN_FRAMENUM || columnUnderMouse >= COLUMN_FRAMENUM2))
{
if (rowUnderMouse == markerDragFrameNumber)
{
// it was just double-click and release
// if Selection points at dragged Marker, set focus to lower Note edit field
int dragged_marker_id = markersManager->getMarkerAtFrame(markerDragFrameNumber);
int selection_marker_id = markersManager->getMarkerAboveFrame(selection->getCurrentRowsSelectionBeginning());
if (dragged_marker_id == selection_marker_id)
{
//SetFocus(selection.hwndSelectionMarkerEditField);
// select all text in case user wants to overwrite it
//SendMessage(selection.hwndSelectionMarkerEditField, EM_SETSEL, 0, -1);
}
}
else if (markersManager->getMarkerAtFrame(rowUnderMouse))
{
int dragged_marker_id = markersManager->getMarkerAtFrame(markerDragFrameNumber);
int destination_marker_id = markersManager->getMarkerAtFrame(rowUnderMouse);
// swap Notes of these Markers
char dragged_marker_note[MAX_NOTE_LEN];
strcpy(dragged_marker_note, markersManager->getNoteCopy(dragged_marker_id).c_str());
if (strcmp(markersManager->getNoteCopy(destination_marker_id).c_str(), dragged_marker_note))
{
// notes are different, swap them
markersManager->setNote(dragged_marker_id, markersManager->getNoteCopy(destination_marker_id).c_str());
markersManager->setNote(destination_marker_id, dragged_marker_note);
history->registerMarkersChange(MODTYPE_MARKER_SWAP, markerDragFrameNumber, rowUnderMouse);
selection->mustFindCurrentMarker = playback->mustFindCurrentMarker = true;
//setLightInHeaderColumn(COLUMN_FRAMENUM, HEADER_LIGHT_MAX);
}
}
else
{
// move Marker
int new_marker_id = markersManager->setMarkerAtFrame(rowUnderMouse);
if (new_marker_id)
{
markersManager->setNote(new_marker_id, markersManager->getNoteCopy(markersManager->getMarkerAtFrame(markerDragFrameNumber)).c_str());
// and delete it from old frame
markersManager->removeMarkerFromFrame(markerDragFrameNumber);
history->registerMarkersChange(MODTYPE_MARKER_DRAG, markerDragFrameNumber, rowUnderMouse, markersManager->getNoteCopy(markersManager->getMarkerAtFrame(rowUnderMouse)).c_str());
selection->mustFindCurrentMarker = playback->mustFindCurrentMarker = true;
//setLightInHeaderColumn(COLUMN_FRAMENUM, HEADER_LIGHT_MAX);
//redrawRow(rowUnderMouse);
}
}
}
//redrawRow(markerDragFrameNumber);
//if (hwndMarkerDragBox)
//{
// DestroyWindow(hwndMarkerDragBox);
// hwndMarkerDragBox = 0;
//}
}
} else
{
// abort drag
//if (hwndMarkerDragBox)
//{
// DestroyWindow(hwndMarkerDragBox);
// hwndMarkerDragBox = 0;
//}
}
break;
}
}
dragMode = DRAG_MODE_NONE;
//mustCheckItemUnderMouse = true;
}
//----------------------------------------------------------------------------
void QPianoRoll::paintEvent(QPaintEvent *event)
{
int x, y, row, nrow, lineNum;

View File

@ -75,9 +75,23 @@ class QPianoRoll : public QWidget
void calcFontData(void);
void resizeEvent(QResizeEvent *event);
void paintEvent(QPaintEvent *event);
void mousePressEvent(QMouseEvent * event);
void mouseReleaseEvent(QMouseEvent * event);
void mouseMoveEvent(QMouseEvent * event);
void startDraggingPlaybackCursor(void);
void startDraggingMarker(int mouseX, int mouseY, int rowIndex, int columnIndex);
void startSelectingDrag(int start_frame);
void startDeselectingDrag(int start_frame);
void handlePlaybackCursorDragging(void);
void finishDrag(void);
void updateDrag(void);
void drawArrow( QPainter *painter, int xl, int yl, int value );
int calcColumn( int px );
QPoint convPixToCursor( QPoint p );
private:
TasEditorWindow *parent;
QFont font;
@ -106,6 +120,17 @@ class QPianoRoll : public QWidget
int lineOffset;
int maxLineOffset;
int numInputDevs;
int dragMode;
int dragSelectionStartingFrame;
int dragSelectionEndingFrame;
int realRowUnderMouse;
int rowUnderMouse;
int columnUnderMouse;
int markerDragFrameNumber;
int markerDragCountdown;
int drawingStartTimestamp;
int mouse_x;
int mouse_y;
bool useDarkTheme;
@ -139,6 +164,8 @@ class TasEditorWindow : public QDialog
HISTORY history;
BRANCHES branches;
void toggleInput(int start, int end, int joy, int button, int consecutivenessTag);
void setInputUsingPattern(int start, int end, int joy, int button, int consecutivenessTag);
protected:
void closeEvent(QCloseEvent *event);
@ -199,6 +226,8 @@ class TasEditorWindow : public QDialog
QPushButton *similarBtn;
QPushButton *moreBtn;
std::vector<std::string> patternsNames;
std::vector<std::vector<uint8_t>> patterns;
private:
int initModules(void);

View File

@ -90,3 +90,4 @@ private:
bool alreadyCompressed; // to compress only once
};
extern int joysticksPerFrame[INPUT_TYPES_TOTAL];