GUI: new pattern cursor logic, part 1 - READ

this new pattern cursor logic will finally allow you to click on any
cell of the previous/next pattern and take you there
on top of that you'll be able to make selections that go beyond the
boundaries of a pattern

operations are not supported yet, so don't try it out!
it won't work properly until I adapt the code.
This commit is contained in:
tildearrow 2025-06-27 20:37:23 -05:00
parent eac8c03158
commit b9604c5729
5 changed files with 97 additions and 46 deletions

View file

@ -21,22 +21,24 @@
#include "../ta-log.h"
#include "actionUtil.h"
void FurnaceGUI::startSelection(int xCoarse, int xFine, int y, bool fullRow) {
void FurnaceGUI::startSelection(int xCoarse, int xFine, int y, int ord, bool fullRow) {
DETERMINE_FIRST_LAST;
if (xCoarse!=selStart.xCoarse || xFine!=selStart.xFine || y!=selStart.y) {
if (xCoarse!=selStart.xCoarse || xFine!=selStart.xFine || y!=selStart.y || ord!=selStart.order) {
curNibble=false;
}
if (ImGui::IsMouseDoubleClicked(ImGuiMouseButton_Left) && !fullRow && settings.doubleClickColumn) {
if (cursor.xCoarse==xCoarse && cursor.xFine==xFine && cursor.y==y) {
if (cursor.xCoarse==xCoarse && cursor.xFine==xFine && cursor.y==y && cursor.order==ord) {
// select entire channel
selStart.xCoarse=xCoarse;
selStart.xFine=0;
selStart.y=0;
selStart.order=ord;
selEnd.xCoarse=xCoarse;
selEnd.xFine=2+e->curPat[selEnd.xCoarse].effectCols*2;
selEnd.y=e->curSubSong->patLen-1;
selEnd.order=ord;
finishSelection();
return;
@ -44,17 +46,19 @@ void FurnaceGUI::startSelection(int xCoarse, int xFine, int y, bool fullRow) {
}
if (((settings.dragMovesSelection==1 || settings.dragMovesSelection==3 || settings.dragMovesSelection==5) || ((settings.dragMovesSelection==2 || settings.dragMovesSelection==4) && (ImGui::IsKeyDown(ImGuiKey_LeftCtrl) || ImGui::IsKeyDown(ImGuiKey_RightCtrl)))) && !fullRow) {
if (xCoarse>=selStart.xCoarse && (xFine>=selStart.xFine || xCoarse>selStart.xCoarse) && y>=selStart.y &&
xCoarse<=selEnd.xCoarse && (xFine<=selEnd.xFine || xCoarse<selEnd.xCoarse) && y<=selEnd.y) {
if (xCoarse>=selStart.xCoarse && (xFine>=selStart.xFine || xCoarse>selStart.xCoarse) && (ord>selStart.order || y>=selStart.y) &&
xCoarse<=selEnd.xCoarse && (xFine<=selEnd.xFine || xCoarse<selEnd.xCoarse) && (ord<selEnd.order || y<=selEnd.y)) {
dragging=true;
selecting=true;
selectingFull=false;
dragSourceX=xCoarse;
dragSourceXFine=xFine;
dragSourceY=y;
dragSourceOrder=ord;
dragDestinationX=xCoarse;
dragDestinationXFine=xFine;
dragDestinationY=y;
dragDestinationOrder=ord;
dragStart=selStart;
dragEnd=selEnd;
return;
@ -68,34 +72,41 @@ void FurnaceGUI::startSelection(int xCoarse, int xFine, int y, bool fullRow) {
selEnd.xFine=2+e->curPat[selEnd.xCoarse].effectCols*2;
selStart.y=y;
selEnd.y=y;
selStart.order=ord;
selEnd.order=ord;
} else {
if (xCoarse!=cursor.xCoarse || y!=cursor.y) {
if (xCoarse!=cursor.xCoarse || y!=cursor.y || ord!=cursor.order) {
makeCursorUndo();
}
cursor.xCoarse=xCoarse;
cursor.xFine=xFine;
cursor.y=y;
cursor.order=ord;
selStart.xCoarse=xCoarse;
selStart.xFine=xFine;
selStart.y=y;
selStart.order=ord;
selEnd.xCoarse=xCoarse;
selEnd.xFine=xFine;
selEnd.y=y;
selEnd.order=ord;
}
selecting=true;
selectingFull=fullRow;
e->setMidiBaseChan(cursor.xCoarse);
}
void FurnaceGUI::updateSelection(int xCoarse, int xFine, int y, bool fullRow) {
void FurnaceGUI::updateSelection(int xCoarse, int xFine, int y, int ord, bool fullRow) {
if (!selecting) return;
if (dragging) {
dragDestinationX=xCoarse;
if (dragStart.xFine>=3 && dragStart.xCoarse==dragEnd.xCoarse) dragDestinationXFine=(dragSourceXFine&1)?((xFine-1)|1):((xFine+1)&(~1));
dragDestinationY=y;
dragDestinationOrder=ord;
cursorDrag.xCoarse=xCoarse;
cursorDrag.xFine=xFine;
cursorDrag.y=y;
cursorDrag.order=ord;
int len=dragEnd.xCoarse-dragStart.xCoarse+1;
if (len<0) len=0;
@ -119,6 +130,7 @@ void FurnaceGUI::updateSelection(int xCoarse, int xFine, int y, bool fullRow) {
}
}
// TODO: new cursor logic
if (dragStart.y+(dragDestinationY-dragSourceY)<0) {
dragDestinationY=dragSourceY-dragStart.y;
}
@ -139,17 +151,26 @@ void FurnaceGUI::updateSelection(int xCoarse, int xFine, int y, bool fullRow) {
selEnd.xCoarse=lastChannel-1;
selEnd.xFine=2+e->curPat[selEnd.xCoarse].effectCols*2;
selEnd.y=y;
selEnd.order=ord;
} else {
selEnd.xCoarse=xCoarse;
selEnd.xFine=xFine;
selEnd.y=y;
selEnd.order=ord;
}
}
}
void FurnaceGUI::finishSelection() {
// swap points if needed
if (selEnd.y<selStart.y) {
if (selEnd.order<selStart.order) {
selEnd.order^=selStart.order;
selStart.order^=selEnd.order;
selEnd.order^=selStart.order;
selEnd.y^=selStart.y;
selStart.y^=selEnd.y;
selEnd.y^=selStart.y;
} else if (selEnd.order==selStart.order && selEnd.y<selStart.y) {
selEnd.y^=selStart.y;
selStart.y^=selEnd.y;
selEnd.y^=selStart.y;
@ -172,7 +193,7 @@ void FurnaceGUI::finishSelection() {
mobilePatSel=false;
if (dragging) {
if (dragSourceX==dragDestinationX && dragSourceY==dragDestinationY && dragSourceXFine==dragDestinationXFine) {
if (dragSourceX==dragDestinationX && dragSourceY==dragDestinationY && dragSourceXFine==dragDestinationXFine && dragSourceOrder==dragDestinationOrder) {
cursor=cursorDrag;
selStart=cursorDrag;
selEnd=cursorDrag;
@ -190,14 +211,20 @@ void FurnaceGUI::finishSelection() {
if (selStart.xCoarse>=chanCount) selStart.xCoarse=chanCount-1;
if (selStart.y<0) selStart.y=0;
if (selStart.y>=e->curSubSong->patLen) selStart.y=e->curSubSong->patLen-1;
if (selStart.order<0) selStart.order=0;
if (selStart.order>=e->curSubSong->ordersLen) selStart.order=e->curSubSong->ordersLen-1;
if (selEnd.xCoarse<0) selEnd.xCoarse=0;
if (selEnd.xCoarse>=chanCount) selEnd.xCoarse=chanCount-1;
if (selEnd.y<0) selEnd.y=0;
if (selEnd.y>=e->curSubSong->patLen) selEnd.y=e->curSubSong->patLen-1;
if (selEnd.order<0) selEnd.order=0;
if (selEnd.order>=e->curSubSong->ordersLen) selEnd.order=e->curSubSong->ordersLen-1;
if (cursor.xCoarse<0) cursor.xCoarse=0;
if (cursor.xCoarse>=chanCount) cursor.xCoarse=chanCount-1;
if (cursor.y<0) cursor.y=0;
if (cursor.y>=e->curSubSong->patLen) cursor.y=e->curSubSong->patLen-1;
if (cursor.order<0) cursor.order=0;
if (cursor.order>=e->curSubSong->ordersLen) cursor.order=e->curSubSong->ordersLen-1;
if (e->curSubSong->chanCollapse[selStart.xCoarse]==3) {
selStart.xFine=0;
@ -218,7 +245,13 @@ void FurnaceGUI::finishSelection() {
selEnd.xFine=2+e->curPat[selEnd.xCoarse].effectCols*2;
}
logV(_("finish selection: %d.%d,%d - %d.%d,%d"),selStart.xCoarse,selStart.xFine,selStart.y,selEnd.xCoarse,selEnd.xFine,selEnd.y);
// change order if necessary
if (curOrder!=cursor.order) {
setOrder(cursor.order);
updateScroll(cursor.y);
}
logV(_("finish selection: %d.%d,%d.%d - %d.%d,%d.%d"),selStart.xCoarse,selStart.xFine,selStart.order,selStart.y,selEnd.xCoarse,selEnd.xFine,selEnd.order,selEnd.y);
e->setMidiBaseChan(cursor.xCoarse);
}