GUI: undo, part 1
This commit is contained in:
parent
8d587f72f2
commit
ca62347917
203
src/gui/gui.cpp
203
src/gui/gui.cpp
|
@ -406,6 +406,7 @@ void FurnaceGUI::drawOrders() {
|
||||||
snprintf(selID,16,"%.2x##O_%.2x_%.2x",e->song.orders.ord[j][i],j,i);
|
snprintf(selID,16,"%.2x##O_%.2x_%.2x",e->song.orders.ord[j][i],j,i);
|
||||||
if (ImGui::Selectable(selID)) {
|
if (ImGui::Selectable(selID)) {
|
||||||
if (e->getOrder()==i) {
|
if (e->getOrder()==i) {
|
||||||
|
prepareUndo(GUI_ACTION_CHANGE_ORDER);
|
||||||
if (changeAllOrders) {
|
if (changeAllOrders) {
|
||||||
for (int k=0; k<e->getChannelCount(e->song.system); k++) {
|
for (int k=0; k<e->getChannelCount(e->song.system); k++) {
|
||||||
if (e->song.orders.ord[k][i]<0x7f) e->song.orders.ord[k][i]++;
|
if (e->song.orders.ord[k][i]<0x7f) e->song.orders.ord[k][i]++;
|
||||||
|
@ -413,12 +414,14 @@ void FurnaceGUI::drawOrders() {
|
||||||
} else {
|
} else {
|
||||||
if (e->song.orders.ord[j][i]<0x7f) e->song.orders.ord[j][i]++;
|
if (e->song.orders.ord[j][i]<0x7f) e->song.orders.ord[j][i]++;
|
||||||
}
|
}
|
||||||
|
makeUndo(GUI_ACTION_CHANGE_ORDER);
|
||||||
} else {
|
} else {
|
||||||
e->setOrder(i);
|
e->setOrder(i);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (ImGui::IsItemClicked(ImGuiMouseButton_Right)) {
|
if (ImGui::IsItemClicked(ImGuiMouseButton_Right)) {
|
||||||
if (e->getOrder()==i) {
|
if (e->getOrder()==i) {
|
||||||
|
prepareUndo(GUI_ACTION_CHANGE_ORDER);
|
||||||
if (changeAllOrders) {
|
if (changeAllOrders) {
|
||||||
for (int k=0; k<e->getChannelCount(e->song.system); k++) {
|
for (int k=0; k<e->getChannelCount(e->song.system); k++) {
|
||||||
if (e->song.orders.ord[k][i]>0) e->song.orders.ord[k][i]--;
|
if (e->song.orders.ord[k][i]>0) e->song.orders.ord[k][i]--;
|
||||||
|
@ -426,6 +429,7 @@ void FurnaceGUI::drawOrders() {
|
||||||
} else {
|
} else {
|
||||||
if (e->song.orders.ord[j][i]>0) e->song.orders.ord[j][i]--;
|
if (e->song.orders.ord[j][i]>0) e->song.orders.ord[j][i]--;
|
||||||
}
|
}
|
||||||
|
makeUndo(GUI_ACTION_CHANGE_ORDER);
|
||||||
} else {
|
} else {
|
||||||
e->setOrder(i);
|
e->setOrder(i);
|
||||||
}
|
}
|
||||||
|
@ -439,27 +443,39 @@ void FurnaceGUI::drawOrders() {
|
||||||
ImGui::NextColumn();
|
ImGui::NextColumn();
|
||||||
if (ImGui::Button(ICON_FA_PLUS)) {
|
if (ImGui::Button(ICON_FA_PLUS)) {
|
||||||
// add order row (new)
|
// add order row (new)
|
||||||
|
prepareUndo(GUI_ACTION_CHANGE_ORDER);
|
||||||
e->addOrder(false,false);
|
e->addOrder(false,false);
|
||||||
|
makeUndo(GUI_ACTION_CHANGE_ORDER);
|
||||||
}
|
}
|
||||||
if (ImGui::Button(ICON_FA_MINUS)) {
|
if (ImGui::Button(ICON_FA_MINUS)) {
|
||||||
// remove this order row
|
// remove this order row
|
||||||
|
prepareUndo(GUI_ACTION_CHANGE_ORDER);
|
||||||
e->deleteOrder();
|
e->deleteOrder();
|
||||||
|
makeUndo(GUI_ACTION_CHANGE_ORDER);
|
||||||
}
|
}
|
||||||
if (ImGui::Button(ICON_FA_FILES_O)) {
|
if (ImGui::Button(ICON_FA_FILES_O)) {
|
||||||
// duplicate order row
|
// duplicate order row
|
||||||
|
prepareUndo(GUI_ACTION_CHANGE_ORDER);
|
||||||
e->addOrder(true,false);
|
e->addOrder(true,false);
|
||||||
|
makeUndo(GUI_ACTION_CHANGE_ORDER);
|
||||||
}
|
}
|
||||||
if (ImGui::Button(ICON_FA_ANGLE_UP)) {
|
if (ImGui::Button(ICON_FA_ANGLE_UP)) {
|
||||||
// move order row up
|
// move order row up
|
||||||
|
prepareUndo(GUI_ACTION_CHANGE_ORDER);
|
||||||
e->moveOrderUp();
|
e->moveOrderUp();
|
||||||
|
makeUndo(GUI_ACTION_CHANGE_ORDER);
|
||||||
}
|
}
|
||||||
if (ImGui::Button(ICON_FA_ANGLE_DOWN)) {
|
if (ImGui::Button(ICON_FA_ANGLE_DOWN)) {
|
||||||
// move order row down
|
// move order row down
|
||||||
|
prepareUndo(GUI_ACTION_CHANGE_ORDER);
|
||||||
e->moveOrderDown();
|
e->moveOrderDown();
|
||||||
|
makeUndo(GUI_ACTION_CHANGE_ORDER);
|
||||||
}
|
}
|
||||||
if (ImGui::Button(ICON_FA_ANGLE_DOUBLE_DOWN)) {
|
if (ImGui::Button(ICON_FA_ANGLE_DOUBLE_DOWN)) {
|
||||||
// duplicate order row at end
|
// duplicate order row at end
|
||||||
|
prepareUndo(GUI_ACTION_CHANGE_ORDER);
|
||||||
e->addOrder(true,true);
|
e->addOrder(true,true);
|
||||||
|
makeUndo(GUI_ACTION_CHANGE_ORDER);
|
||||||
}
|
}
|
||||||
if (ImGui::Button(changeAllOrders?ICON_FA_LINK"##ChangeAll":ICON_FA_CHAIN_BROKEN"##ChangeAll")) {
|
if (ImGui::Button(changeAllOrders?ICON_FA_LINK"##ChangeAll":ICON_FA_CHAIN_BROKEN"##ChangeAll")) {
|
||||||
// whether to change one or all orders in a row
|
// whether to change one or all orders in a row
|
||||||
|
@ -1611,8 +1627,95 @@ void FurnaceGUI::editAdvance() {
|
||||||
updateScroll(cursor.y);
|
updateScroll(cursor.y);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void FurnaceGUI::prepareUndo(ActionType action) {
|
||||||
|
int order=e->getOrder();
|
||||||
|
switch (action) {
|
||||||
|
case GUI_ACTION_CHANGE_SYSTEM:
|
||||||
|
oldSystem=e->song.system;
|
||||||
|
break;
|
||||||
|
case GUI_ACTION_CHANGE_ORDER:
|
||||||
|
oldOrders=e->song.orders;
|
||||||
|
oldOrdersLen=e->song.ordersLen;
|
||||||
|
break;
|
||||||
|
case GUI_ACTION_PATTERN_EDIT:
|
||||||
|
case GUI_ACTION_PATTERN_DELETE:
|
||||||
|
case GUI_ACTION_PATTERN_PULL:
|
||||||
|
case GUI_ACTION_PATTERN_PUSH:
|
||||||
|
case GUI_ACTION_PATTERN_CUT:
|
||||||
|
case GUI_ACTION_PATTERN_PASTE:
|
||||||
|
for (int i=0; i<17; i++) {
|
||||||
|
memcpy(oldPat[i],e->song.pat[i].getPattern(e->song.orders.ord[i][order],false),sizeof(DivPattern));
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void FurnaceGUI::makeUndo(ActionType action) {
|
||||||
|
bool doPush=false;
|
||||||
|
UndoStep s;
|
||||||
|
s.type=action;
|
||||||
|
s.cursor=cursor;
|
||||||
|
s.selStart=selStart;
|
||||||
|
s.selEnd=selEnd;
|
||||||
|
int order=e->getOrder();
|
||||||
|
s.order=order;
|
||||||
|
s.nibble=curNibble;
|
||||||
|
switch (action) {
|
||||||
|
case GUI_ACTION_CHANGE_SYSTEM:
|
||||||
|
if (oldSystem!=e->song.system) {
|
||||||
|
s.oldSystem=oldSystem;
|
||||||
|
s.newSystem=e->song.system;
|
||||||
|
doPush=true;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case GUI_ACTION_CHANGE_ORDER:
|
||||||
|
for (int i=0; i<32; i++) {
|
||||||
|
for (int j=0; j<128; j++) {
|
||||||
|
if (oldOrders.ord[i][j]!=e->song.orders.ord[i][j]) {
|
||||||
|
s.ord.push_back(UndoOrderData(i,j,oldOrders.ord[i][j],e->song.orders.ord[i][j]));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
s.oldOrdersLen=oldOrdersLen;
|
||||||
|
s.newOrdersLen=e->song.ordersLen;
|
||||||
|
if (oldOrdersLen!=e->song.ordersLen) {
|
||||||
|
doPush=true;
|
||||||
|
}
|
||||||
|
if (!s.ord.empty()) {
|
||||||
|
doPush=true;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case GUI_ACTION_PATTERN_EDIT:
|
||||||
|
case GUI_ACTION_PATTERN_DELETE:
|
||||||
|
case GUI_ACTION_PATTERN_PULL:
|
||||||
|
case GUI_ACTION_PATTERN_PUSH:
|
||||||
|
case GUI_ACTION_PATTERN_CUT:
|
||||||
|
case GUI_ACTION_PATTERN_PASTE:
|
||||||
|
for (int i=0; i<17; i++) {
|
||||||
|
DivPattern* p=e->song.pat[i].getPattern(e->song.orders.ord[i][order],false);
|
||||||
|
for (int j=0; j<e->song.patLen; j++) {
|
||||||
|
for (int k=0; k<16; k++) {
|
||||||
|
if (p->data[j][k]!=oldPat[i]->data[j][k]) {
|
||||||
|
s.pat.push_back(UndoPatternData(i,e->song.orders.ord[i][order],j,k,p->data[j][k],oldPat[i]->data[j][k]));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (!s.pat.empty()) {
|
||||||
|
doPush=true;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if (doPush) {
|
||||||
|
undoHist.push_back(s);
|
||||||
|
redoHist.clear();
|
||||||
|
if (undoHist.size()>maxUndoSteps) undoHist.pop_front();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void FurnaceGUI::doDelete() {
|
void FurnaceGUI::doDelete() {
|
||||||
finishSelection();
|
finishSelection();
|
||||||
|
prepareUndo(GUI_ACTION_PATTERN_DELETE);
|
||||||
curNibble=false;
|
curNibble=false;
|
||||||
|
|
||||||
int iCoarse=selStart.xCoarse;
|
int iCoarse=selStart.xCoarse;
|
||||||
|
@ -1630,10 +1733,13 @@ void FurnaceGUI::doDelete() {
|
||||||
}
|
}
|
||||||
iFine=0;
|
iFine=0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
makeUndo(GUI_ACTION_PATTERN_DELETE);
|
||||||
}
|
}
|
||||||
|
|
||||||
void FurnaceGUI::doPullDelete() {
|
void FurnaceGUI::doPullDelete() {
|
||||||
finishSelection();
|
finishSelection();
|
||||||
|
prepareUndo(GUI_ACTION_PATTERN_PULL);
|
||||||
curNibble=false;
|
curNibble=false;
|
||||||
|
|
||||||
int iCoarse=selStart.xCoarse;
|
int iCoarse=selStart.xCoarse;
|
||||||
|
@ -1658,10 +1764,13 @@ void FurnaceGUI::doPullDelete() {
|
||||||
}
|
}
|
||||||
iFine=0;
|
iFine=0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
makeUndo(GUI_ACTION_PATTERN_PULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
void FurnaceGUI::doInsert() {
|
void FurnaceGUI::doInsert() {
|
||||||
finishSelection();
|
finishSelection();
|
||||||
|
prepareUndo(GUI_ACTION_PATTERN_PUSH);
|
||||||
curNibble=false;
|
curNibble=false;
|
||||||
|
|
||||||
int iCoarse=selStart.xCoarse;
|
int iCoarse=selStart.xCoarse;
|
||||||
|
@ -1686,11 +1795,16 @@ void FurnaceGUI::doInsert() {
|
||||||
}
|
}
|
||||||
iFine=0;
|
iFine=0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
makeUndo(GUI_ACTION_PATTERN_PUSH);
|
||||||
}
|
}
|
||||||
|
|
||||||
void FurnaceGUI::doCopy(bool cut) {
|
void FurnaceGUI::doCopy(bool cut) {
|
||||||
finishSelection();
|
finishSelection();
|
||||||
if (cut) curNibble=false;
|
if (cut) {
|
||||||
|
curNibble=false;
|
||||||
|
prepareUndo(GUI_ACTION_PATTERN_CUT);
|
||||||
|
}
|
||||||
clipboard=fmt::sprintf("org.tildearrow.furnace - Pattern Data (%d)\n%d",DIV_ENGINE_VERSION,selStart.xFine);
|
clipboard=fmt::sprintf("org.tildearrow.furnace - Pattern Data (%d)\n%d",DIV_ENGINE_VERSION,selStart.xFine);
|
||||||
|
|
||||||
for (int j=selStart.y; j<=selEnd.y; j++) {
|
for (int j=selStart.y; j<=selEnd.y; j++) {
|
||||||
|
@ -1723,10 +1837,15 @@ void FurnaceGUI::doCopy(bool cut) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
SDL_SetClipboardText(clipboard.c_str());
|
SDL_SetClipboardText(clipboard.c_str());
|
||||||
|
|
||||||
|
if (cut) {
|
||||||
|
makeUndo(GUI_ACTION_PATTERN_CUT);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void FurnaceGUI::doPaste() {
|
void FurnaceGUI::doPaste() {
|
||||||
finishSelection();
|
finishSelection();
|
||||||
|
prepareUndo(GUI_ACTION_PATTERN_PASTE);
|
||||||
char* clipText=SDL_GetClipboardText();
|
char* clipText=SDL_GetClipboardText();
|
||||||
if (clipText!=NULL) {
|
if (clipText!=NULL) {
|
||||||
if (clipText[0]) {
|
if (clipText[0]) {
|
||||||
|
@ -1828,6 +1947,53 @@ void FurnaceGUI::doPaste() {
|
||||||
}
|
}
|
||||||
j++;
|
j++;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
makeUndo(GUI_ACTION_PATTERN_PASTE);
|
||||||
|
}
|
||||||
|
|
||||||
|
void FurnaceGUI::doUndo() {
|
||||||
|
if (undoHist.empty()) return;
|
||||||
|
UndoStep& us=undoHist.back();
|
||||||
|
redoHist.push_back(us);
|
||||||
|
|
||||||
|
switch (us.type) {
|
||||||
|
case GUI_ACTION_CHANGE_SYSTEM:
|
||||||
|
e->changeSystem(us.oldSystem);
|
||||||
|
updateWindowTitle();
|
||||||
|
break;
|
||||||
|
case GUI_ACTION_CHANGE_ORDER:
|
||||||
|
e->song.ordersLen=us.oldOrdersLen;
|
||||||
|
for (UndoOrderData& i: us.ord) {
|
||||||
|
e->song.orders.ord[i.chan][i.ord]=i.oldVal;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case GUI_ACTION_PATTERN_EDIT:
|
||||||
|
case GUI_ACTION_PATTERN_DELETE:
|
||||||
|
case GUI_ACTION_PATTERN_PULL:
|
||||||
|
case GUI_ACTION_PATTERN_PUSH:
|
||||||
|
case GUI_ACTION_PATTERN_CUT:
|
||||||
|
case GUI_ACTION_PATTERN_PASTE:
|
||||||
|
for (UndoPatternData& i: us.pat) {
|
||||||
|
DivPattern* p=e->song.pat[i.chan].getPattern(i.pat,true);
|
||||||
|
p->data[i.row][i.col]=i.oldVal;
|
||||||
|
}
|
||||||
|
if (!e->isPlaying()) {
|
||||||
|
cursor=us.cursor;
|
||||||
|
selStart=us.selStart;
|
||||||
|
selEnd=us.selEnd;
|
||||||
|
curNibble=us.nibble;
|
||||||
|
updateScroll(cursor.y);
|
||||||
|
e->setOrder(us.order);
|
||||||
|
}
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
undoHist.pop_back();
|
||||||
|
}
|
||||||
|
|
||||||
|
void FurnaceGUI::doRedo() {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void FurnaceGUI::keyDown(SDL_Event& ev) {
|
void FurnaceGUI::keyDown(SDL_Event& ev) {
|
||||||
|
@ -1858,6 +2024,13 @@ void FurnaceGUI::keyDown(SDL_Event& ev) {
|
||||||
case GUI_WINDOW_PATTERN: {
|
case GUI_WINDOW_PATTERN: {
|
||||||
if (ev.key.keysym.mod&KMOD_CTRL) {
|
if (ev.key.keysym.mod&KMOD_CTRL) {
|
||||||
switch (ev.key.keysym.sym) {
|
switch (ev.key.keysym.sym) {
|
||||||
|
case SDLK_z:
|
||||||
|
if (ev.key.keysym.mod&KMOD_SHIFT) {
|
||||||
|
doRedo();
|
||||||
|
} else {
|
||||||
|
doUndo();
|
||||||
|
}
|
||||||
|
break;
|
||||||
case SDLK_x:
|
case SDLK_x:
|
||||||
doCopy(true);
|
doCopy(true);
|
||||||
break;
|
break;
|
||||||
|
@ -1904,6 +2077,8 @@ void FurnaceGUI::keyDown(SDL_Event& ev) {
|
||||||
int key=noteKeys.at(ev.key.keysym.sym);
|
int key=noteKeys.at(ev.key.keysym.sym);
|
||||||
int num=12*curOctave+key;
|
int num=12*curOctave+key;
|
||||||
DivPattern* pat=e->song.pat[cursor.xCoarse].getPattern(e->song.orders.ord[cursor.xCoarse][e->getOrder()],true);
|
DivPattern* pat=e->song.pat[cursor.xCoarse].getPattern(e->song.orders.ord[cursor.xCoarse][e->getOrder()],true);
|
||||||
|
|
||||||
|
prepareUndo(GUI_ACTION_PATTERN_EDIT);
|
||||||
|
|
||||||
if (key==100) { // note off
|
if (key==100) { // note off
|
||||||
pat->data[cursor.y][0]=100;
|
pat->data[cursor.y][0]=100;
|
||||||
|
@ -1919,12 +2094,14 @@ void FurnaceGUI::keyDown(SDL_Event& ev) {
|
||||||
}
|
}
|
||||||
editAdvance();
|
editAdvance();
|
||||||
curNibble=false;
|
curNibble=false;
|
||||||
|
makeUndo(GUI_ACTION_PATTERN_EDIT);
|
||||||
} catch (std::out_of_range& e) {
|
} catch (std::out_of_range& e) {
|
||||||
}
|
}
|
||||||
} else { // value
|
} else { // value
|
||||||
try {
|
try {
|
||||||
int num=valueKeys.at(ev.key.keysym.sym);
|
int num=valueKeys.at(ev.key.keysym.sym);
|
||||||
DivPattern* pat=e->song.pat[cursor.xCoarse].getPattern(e->song.orders.ord[cursor.xCoarse][e->getOrder()],true);
|
DivPattern* pat=e->song.pat[cursor.xCoarse].getPattern(e->song.orders.ord[cursor.xCoarse][e->getOrder()],true);
|
||||||
|
prepareUndo(GUI_ACTION_PATTERN_EDIT);
|
||||||
if (pat->data[cursor.y][cursor.xFine+1]==-1) pat->data[cursor.y][cursor.xFine+1]=0;
|
if (pat->data[cursor.y][cursor.xFine+1]==-1) pat->data[cursor.y][cursor.xFine+1]=0;
|
||||||
pat->data[cursor.y][cursor.xFine+1]=((pat->data[cursor.y][cursor.xFine+1]<<4)|num)&0xff;
|
pat->data[cursor.y][cursor.xFine+1]=((pat->data[cursor.y][cursor.xFine+1]<<4)|num)&0xff;
|
||||||
if (cursor.xFine==1) { // instrument
|
if (cursor.xFine==1) { // instrument
|
||||||
|
@ -1951,6 +2128,7 @@ void FurnaceGUI::keyDown(SDL_Event& ev) {
|
||||||
curNibble=!curNibble;
|
curNibble=!curNibble;
|
||||||
if (!curNibble) editAdvance();
|
if (!curNibble) editAdvance();
|
||||||
}
|
}
|
||||||
|
makeUndo(GUI_ACTION_PATTERN_EDIT);
|
||||||
} catch (std::out_of_range& e) {
|
} catch (std::out_of_range& e) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -2123,6 +2301,8 @@ int FurnaceGUI::load(String path) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
lastError="everything OK";
|
lastError="everything OK";
|
||||||
|
undoHist.clear();
|
||||||
|
redoHist.clear();
|
||||||
updateWindowTitle();
|
updateWindowTitle();
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
@ -2167,8 +2347,10 @@ void FurnaceGUI::processDrags(int dragX, int dragY) {
|
||||||
|
|
||||||
#define sysChangeOption(x) \
|
#define sysChangeOption(x) \
|
||||||
if (ImGui::MenuItem(e->getSystemName(x),NULL,e->song.system==x)) { \
|
if (ImGui::MenuItem(e->getSystemName(x),NULL,e->song.system==x)) { \
|
||||||
|
prepareUndo(GUI_ACTION_CHANGE_SYSTEM); \
|
||||||
e->changeSystem(x); \
|
e->changeSystem(x); \
|
||||||
updateWindowTitle(); \
|
updateWindowTitle(); \
|
||||||
|
makeUndo(GUI_ACTION_CHANGE_SYSTEM); \
|
||||||
}
|
}
|
||||||
|
|
||||||
bool FurnaceGUI::loop() {
|
bool FurnaceGUI::loop() {
|
||||||
|
@ -2239,6 +2421,8 @@ bool FurnaceGUI::loop() {
|
||||||
if (ImGui::BeginMenu("file")) {
|
if (ImGui::BeginMenu("file")) {
|
||||||
if (ImGui::MenuItem("new")) {
|
if (ImGui::MenuItem("new")) {
|
||||||
e->createNew();
|
e->createNew();
|
||||||
|
undoHist.clear();
|
||||||
|
redoHist.clear();
|
||||||
}
|
}
|
||||||
if (ImGui::MenuItem("open...")) {
|
if (ImGui::MenuItem("open...")) {
|
||||||
openFileDialog(GUI_FILE_OPEN);
|
openFileDialog(GUI_FILE_OPEN);
|
||||||
|
@ -2270,8 +2454,8 @@ bool FurnaceGUI::loop() {
|
||||||
ImGui::EndMenu();
|
ImGui::EndMenu();
|
||||||
}
|
}
|
||||||
if (ImGui::BeginMenu("edit")) {
|
if (ImGui::BeginMenu("edit")) {
|
||||||
ImGui::MenuItem("undo");
|
if (ImGui::MenuItem("undo")) doUndo();
|
||||||
ImGui::MenuItem("redo");
|
if (ImGui::MenuItem("redo")) doRedo();
|
||||||
ImGui::Separator();
|
ImGui::Separator();
|
||||||
if (ImGui::MenuItem("cut")) doCopy(true);
|
if (ImGui::MenuItem("cut")) doCopy(true);
|
||||||
if (ImGui::MenuItem("copy")) doCopy(false);
|
if (ImGui::MenuItem("copy")) doCopy(false);
|
||||||
|
@ -2489,6 +2673,10 @@ bool FurnaceGUI::init() {
|
||||||
ImGuiFileDialog::Instance()->SetFileStyle(IGFD_FileStyleByExtension,".wav",ImVec4(1.0f,1.0f,0.5f,1.0f),ICON_FA_FILE_AUDIO_O);
|
ImGuiFileDialog::Instance()->SetFileStyle(IGFD_FileStyleByExtension,".wav",ImVec4(1.0f,1.0f,0.5f,1.0f),ICON_FA_FILE_AUDIO_O);
|
||||||
|
|
||||||
updateWindowTitle();
|
updateWindowTitle();
|
||||||
|
|
||||||
|
for (int i=0; i<17; i++) {
|
||||||
|
oldPat[i]=new DivPattern;
|
||||||
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2499,6 +2687,10 @@ bool FurnaceGUI::finish() {
|
||||||
ImGui::DestroyContext();
|
ImGui::DestroyContext();
|
||||||
SDL_DestroyRenderer(sdlRend);
|
SDL_DestroyRenderer(sdlRend);
|
||||||
SDL_DestroyWindow(sdlWin);
|
SDL_DestroyWindow(sdlWin);
|
||||||
|
|
||||||
|
for (int i=0; i<17; i++) {
|
||||||
|
delete oldPat[i];
|
||||||
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2515,6 +2707,7 @@ FurnaceGUI::FurnaceGUI():
|
||||||
aboutHue(0.0f),
|
aboutHue(0.0f),
|
||||||
mainFontSize(18),
|
mainFontSize(18),
|
||||||
patFontSize(18),
|
patFontSize(18),
|
||||||
|
maxUndoSteps(100),
|
||||||
curIns(0),
|
curIns(0),
|
||||||
curWave(0),
|
curWave(0),
|
||||||
curSample(0),
|
curSample(0),
|
||||||
|
@ -2551,7 +2744,9 @@ FurnaceGUI::FurnaceGUI():
|
||||||
macroDragMax(0),
|
macroDragMax(0),
|
||||||
macroDragActive(false),
|
macroDragActive(false),
|
||||||
nextScroll(-1.0f),
|
nextScroll(-1.0f),
|
||||||
nextAddScroll(0.0f) {
|
nextAddScroll(0.0f),
|
||||||
|
oldSystem(DIV_SYSTEM_NULL),
|
||||||
|
oldOrdersLen(0) {
|
||||||
uiColors[GUI_COLOR_BACKGROUND]=ImVec4(0.1f,0.1f,0.1f,1.0f);
|
uiColors[GUI_COLOR_BACKGROUND]=ImVec4(0.1f,0.1f,0.1f,1.0f);
|
||||||
uiColors[GUI_COLOR_FRAME_BACKGROUND]=ImVec4(0.0f,0.0f,0.0f,0.85f);
|
uiColors[GUI_COLOR_FRAME_BACKGROUND]=ImVec4(0.0f,0.0f,0.0f,0.85f);
|
||||||
uiColors[GUI_COLOR_CHANNEL_FM]=ImVec4(0.2f,0.8f,1.0f,1.0f);
|
uiColors[GUI_COLOR_CHANNEL_FM]=ImVec4(0.2f,0.8f,1.0f,1.0f);
|
||||||
|
|
|
@ -79,6 +79,7 @@ struct SelectionPoint {
|
||||||
|
|
||||||
enum ActionType {
|
enum ActionType {
|
||||||
GUI_ACTION_CHANGE_SYSTEM,
|
GUI_ACTION_CHANGE_SYSTEM,
|
||||||
|
GUI_ACTION_CHANGE_ORDER,
|
||||||
GUI_ACTION_PATTERN_EDIT,
|
GUI_ACTION_PATTERN_EDIT,
|
||||||
GUI_ACTION_PATTERN_DELETE,
|
GUI_ACTION_PATTERN_DELETE,
|
||||||
GUI_ACTION_PATTERN_PULL,
|
GUI_ACTION_PATTERN_PULL,
|
||||||
|
@ -87,13 +88,38 @@ enum ActionType {
|
||||||
GUI_ACTION_PATTERN_PASTE
|
GUI_ACTION_PATTERN_PASTE
|
||||||
};
|
};
|
||||||
|
|
||||||
struct UndoData {
|
struct UndoPatternData {
|
||||||
int data;
|
int chan, pat, row, col;
|
||||||
|
short oldVal, newVal;
|
||||||
|
UndoPatternData(int c, int p, int r, int co, short v1, short v2):
|
||||||
|
chan(c),
|
||||||
|
pat(p),
|
||||||
|
row(r),
|
||||||
|
col(c),
|
||||||
|
oldVal(v1),
|
||||||
|
newVal(v2) {}
|
||||||
|
};
|
||||||
|
|
||||||
|
struct UndoOrderData {
|
||||||
|
int chan, ord;
|
||||||
|
unsigned char oldVal, newVal;
|
||||||
|
UndoOrderData(int c, int o, unsigned char v1, unsigned char v2):
|
||||||
|
chan(c),
|
||||||
|
ord(o),
|
||||||
|
oldVal(v1),
|
||||||
|
newVal(v2) {}
|
||||||
};
|
};
|
||||||
|
|
||||||
struct UndoStep {
|
struct UndoStep {
|
||||||
ActionType type;
|
ActionType type;
|
||||||
std::vector<UndoData> data;
|
SelectionPoint cursor, selStart, selEnd;
|
||||||
|
int order;
|
||||||
|
bool nibble;
|
||||||
|
DivSystem oldSystem, newSystem;
|
||||||
|
int oldOrdersLen, newOrdersLen;
|
||||||
|
int oldPatLen, newPatLen;
|
||||||
|
std::vector<UndoOrderData> ord;
|
||||||
|
std::vector<UndoPatternData> pat;
|
||||||
};
|
};
|
||||||
|
|
||||||
class FurnaceGUI {
|
class FurnaceGUI {
|
||||||
|
@ -123,6 +149,7 @@ class FurnaceGUI {
|
||||||
ImVec4 volColors[128];
|
ImVec4 volColors[128];
|
||||||
|
|
||||||
int mainFontSize, patFontSize;
|
int mainFontSize, patFontSize;
|
||||||
|
size_t maxUndoSteps;
|
||||||
|
|
||||||
char finalLayoutPath[4096];
|
char finalLayoutPath[4096];
|
||||||
|
|
||||||
|
@ -162,6 +189,10 @@ class FurnaceGUI {
|
||||||
|
|
||||||
ImVec2 patWindowPos, patWindowSize;
|
ImVec2 patWindowPos, patWindowSize;
|
||||||
|
|
||||||
|
DivSystem oldSystem;
|
||||||
|
int oldOrdersLen;
|
||||||
|
DivOrders oldOrders;
|
||||||
|
DivPattern* oldPat[17];
|
||||||
std::deque<UndoStep> undoHist;
|
std::deque<UndoStep> undoHist;
|
||||||
std::deque<UndoStep> redoHist;
|
std::deque<UndoStep> redoHist;
|
||||||
|
|
||||||
|
@ -190,11 +221,15 @@ class FurnaceGUI {
|
||||||
|
|
||||||
void moveCursor(int x, int y);
|
void moveCursor(int x, int y);
|
||||||
void editAdvance();
|
void editAdvance();
|
||||||
|
void prepareUndo(ActionType action);
|
||||||
|
void makeUndo(ActionType action);
|
||||||
void doDelete();
|
void doDelete();
|
||||||
void doPullDelete();
|
void doPullDelete();
|
||||||
void doInsert();
|
void doInsert();
|
||||||
void doCopy(bool cut);
|
void doCopy(bool cut);
|
||||||
void doPaste();
|
void doPaste();
|
||||||
|
void doUndo();
|
||||||
|
void doRedo();
|
||||||
|
|
||||||
void keyDown(SDL_Event& ev);
|
void keyDown(SDL_Event& ev);
|
||||||
void keyUp(SDL_Event& ev);
|
void keyUp(SDL_Event& ev);
|
||||||
|
|
Loading…
Reference in New Issue