From c0bf822cfbc547da037dbfccbf4205e867c9e124 Mon Sep 17 00:00:00 2001 From: mjbudd77 Date: Thu, 28 Oct 2021 21:59:14 -0400 Subject: [PATCH] TAS editor project load/save mechanisms inwork for Qt GUI. --- src/drivers/Qt/ConsoleWindow.cpp | 2 + src/drivers/Qt/TasEditor/TasEditorWindow.cpp | 383 +++++++++++++++++-- src/drivers/Qt/TasEditor/TasEditorWindow.h | 18 +- 3 files changed, 376 insertions(+), 27 deletions(-) diff --git a/src/drivers/Qt/ConsoleWindow.cpp b/src/drivers/Qt/ConsoleWindow.cpp index 0b727581..2c070936 100644 --- a/src/drivers/Qt/ConsoleWindow.cpp +++ b/src/drivers/Qt/ConsoleWindow.cpp @@ -2834,6 +2834,8 @@ void consoleWin_t::openTasEditor(void) win = new TasEditorWindow(this); win->show(); + + connect(emulatorThread, SIGNAL(frameFinished(void)), win, SLOT(frameUpdate(void)) ); } fceuWrapperUnLock(); } diff --git a/src/drivers/Qt/TasEditor/TasEditorWindow.cpp b/src/drivers/Qt/TasEditor/TasEditorWindow.cpp index 04d2455c..ff399aee 100644 --- a/src/drivers/Qt/TasEditor/TasEditorWindow.cpp +++ b/src/drivers/Qt/TasEditor/TasEditorWindow.cpp @@ -24,16 +24,21 @@ #include #include +#include #include #include #include +#include +#include #include "fceu.h" #include "movie.h" #include "driver.h" #include "Qt/config.h" +#include "Qt/throttle.h" #include "Qt/fceuWrapper.h" +#include "Qt/ConsoleUtilities.h" #include "Qt/TasEditor/TasEditorWindow.h" TasEditorWindow *tasWin = NULL; @@ -70,15 +75,45 @@ void tasWindowSetFocus(bool val) // this getter contains formula to decide whether to record or replay movie bool isTaseditorRecording(void) { - //if (movie_readonly || playback.getPauseFrame() >= 0 || (taseditorConfig.oldControlSchemeForBranching && !recorder.stateWasLoadedInReadWriteMode)) - // return false; // replay + if ( tasWin == NULL ) + { + return false; + } + if (movie_readonly || playback->getPauseFrame() >= 0 || (taseditorConfig->oldControlSchemeForBranching && !recorder->stateWasLoadedInReadWriteMode)) + { + return false; // replay + } return true; // record } -bool recordInputByTaseditor(void) +void recordInputByTaseditor(void) { - //recorder.recordInput(); - return 0; + if ( recorder ) + { + recorder->recordInput(); + } + return; +} + +void applyMovieInputConfig(void) +{ + // update FCEUX input config + FCEUD_SetInput(currMovieData.fourscore, currMovieData.microphone, (ESI)currMovieData.ports[0], (ESI)currMovieData.ports[1], (ESIFC)currMovieData.ports[2]); + // update PAL flag + pal_emulation = currMovieData.palFlag; + if (pal_emulation) + { + dendy = 0; + } + FCEUI_SetVidSystem(pal_emulation); + RefreshThrottleFPS(); + //PushCurrentVideoSettings(); + // update PPU type + newppu = currMovieData.PPUflag; + //SetMainWindowText(); + // return focus to TAS Editor window + //SetFocus(taseditorWindow.hwndTASEditor); + RAMInitOption = currMovieData.RAMInitOption; } //---------------------------------------------------------------------------- TasEditorWindow::TasEditorWindow(QWidget *parent) @@ -128,20 +163,56 @@ TasEditorWindow::~TasEditorWindow(void) { printf("Destroy Tas Editor Window\n"); - if ( tasWin == this ) - { - tasWin = NULL; - } + fceuWrapperLock(); + //if (!askToSaveProject()) return false; + + // destroy window + //taseditorWindow.exit(); + //disableGeneralKeyboardInput(); + // release memory + //editor.free(); + //pianoRoll.free(); + markersManager.free(); + greenzone.free(); + bookmarks.free(); + branches.free(); + //popupDisplay.free(); + history.free(); + playback.stopSeeking(); + selection.free(); // switch off TAS Editor mode movieMode = MOVIEMODE_INACTIVE; FCEU_DispMessage("TAS Editor disengaged", 0); FCEUMOV_CreateCleanMovie(); + + if ( tasWin == this ) + { + tasWin = NULL; + } + + ::project = NULL; + ::taseditorConfig = NULL; + ::taseditor_lua = NULL; + ::markersManager = NULL; + ::selection = NULL; + ::greenzone = NULL; + ::bookmarks = NULL; + ::playback = NULL; + ::recorder = NULL; + ::history = NULL; + ::branches = NULL; + ::splicer = NULL; + + fceuWrapperUnLock(); } //---------------------------------------------------------------------------- void TasEditorWindow::closeEvent(QCloseEvent *event) { printf("Tas Editor Close Window Event\n"); + + if (!askToSaveProject()) return; + done(0); deleteLater(); event->accept(); @@ -149,6 +220,7 @@ void TasEditorWindow::closeEvent(QCloseEvent *event) //---------------------------------------------------------------------------- void TasEditorWindow::closeWindow(void) { + if (!askToSaveProject()) return; //printf("Close Window\n"); done(0); deleteLater(); @@ -179,7 +251,7 @@ QMenuBar *TasEditorWindow::buildMenuBar(void) act->setShortcut(QKeySequence(tr("Ctrl+N"))); act->setStatusTip(tr("Open New Project")); //act->setIcon( style()->standardIcon( QStyle::SP_FileDialogStart ) ); - //connect(act, SIGNAL(triggered()), this, SLOT(openAviFileDialog(void)) ); + connect(act, SIGNAL(triggered()), this, SLOT(createNewProject(void)) ); fileMenu->addAction(act); @@ -434,18 +506,18 @@ int TasEditorWindow::initModules(void) // init modules //editor.init(); //pianoRoll.init(); - //selection.init(); - //splicer.init(); - //playback.init(); - //greenzone.init(); - //recorder.init(); - //markersManager.init(); - //project.init(); - //bookmarks.init(); - //branches.init(); + selection.init(); + splicer.init(); + playback.init(); + greenzone.init(); + recorder.init(); + markersManager.init(); + project.init(); + bookmarks.init(); + branches.init(); //popupDisplay.init(); - //history.init(); - //taseditor_lua.init(); + history.init(); + taseditor_lua.init(); // either start new movie or use current movie if (!FCEUMOV_Mode(MOVIEMODE_RECORD|MOVIEMODE_PLAY) || currMovieData.savestate.size() != 0) { @@ -470,24 +542,283 @@ int TasEditorWindow::initModules(void) currMovieData.insertEmpty(-1, currFrameCounter - ((int)currMovieData.records.size() - 1)); } // ensure that movie has correct set of ports/fourscore - //setInputType(currMovieData, getInputType(currMovieData)); + setInputType(currMovieData, getInputType(currMovieData)); // force the input configuration stored in the movie to apply to FCEUX config - //applyMovieInputConfig(); + applyMovieInputConfig(); // reset some modules that need MovieData info //pianoRoll.reset(); - //recorder.reset(); + recorder.reset(); // create initial snapshot in history - //history.reset(); + history.reset(); // reset Taseditor variables //mustCallManualLuaFunction = false; //SetFocus(history.hwndHistoryList); // set focus only once, to show blue selection cursor //SetFocus(pianoRoll.hwndList); FCEU_DispMessage("TAS Editor engaged", 0); - //taseditorWindow.redraw(); + update(); return 0; } //---------------------------------------------------------------------------- +void TasEditorWindow::frameUpdate(void) +{ + fceuWrapperLock(); + //printf("TAS Frame Update\n"); + + //taseditorWindow.update(); + greenzone.update(); + recorder.update(); + //pianoRoll.update(); + markersManager.update(); + playback.update(); + bookmarks.update(); + branches.update(); + //popupDisplay.update(); + selection.update(); + splicer.update(); + history.update(); + project.update(); + // run Lua functions if needed + if (taseditorConfig.enableLuaAutoFunction) + { + //TaseditorAutoFunction(); + } + //if (mustCallManualLuaFunction) + //{ + // TaseditorManualFunction(); + // mustCallManualLuaFunction = false; + //} + fceuWrapperUnLock(); +} +//---------------------------------------------------------------------------- +bool TasEditorWindow::loadProject(const char* fullname) +{ + bool success = false; + + fceuWrapperLock(); + + // try to load project + if (project.load(fullname)) + { + // loaded successfully + applyMovieInputConfig(); + // add new file to Recent menu + //taseditorWindow.updateRecentProjectsArray(fullname); + //taseditorWindow.updateCaption(); + update(); + success = true; + } else + { + // failed to load + //taseditorWindow.updateCaption(); + update(); + } + fceuWrapperUnLock(); + + return success; +} +bool TasEditorWindow::saveProject(bool save_compact) +{ + bool ret = true; + + fceuWrapperLock(); + + if (project.getProjectFile().empty()) + { + ret = saveProjectAs(save_compact); + } else + { + if (save_compact) + { + project.save(0, taseditorConfig.saveCompact_SaveInBinary, taseditorConfig.saveCompact_SaveMarkers, taseditorConfig.saveCompact_SaveBookmarks, taseditorConfig.saveCompact_GreenzoneSavingMode, taseditorConfig.saveCompact_SaveHistory, taseditorConfig.saveCompact_SavePianoRoll, taseditorConfig.saveCompact_SaveSelection); + } + else + { + project.save(0, taseditorConfig.projectSavingOptions_SaveInBinary, taseditorConfig.projectSavingOptions_SaveMarkers, taseditorConfig.projectSavingOptions_SaveBookmarks, taseditorConfig.projectSavingOptions_GreenzoneSavingMode, taseditorConfig.projectSavingOptions_SaveHistory, taseditorConfig.projectSavingOptions_SavePianoRoll, taseditorConfig.projectSavingOptions_SaveSelection); + } + //taseditorWindow.updateCaption(); + } + + fceuWrapperUnLock(); + + return ret; +} + +bool TasEditorWindow::saveProjectAs(bool save_compact) +{ + std::string last; + int ret, useNativeFileDialogVal; + QString filename; + std::string lastPath; + //char dir[512]; + const char *base, *rom; + QFileDialog dialog(this, tr("Save TAS Editor Project As") ); + QList urls; + QDir d; + + dialog.setFileMode(QFileDialog::AnyFile); + + dialog.setNameFilter(tr("TAS Project Files (*.fm3) ;; All files (*)")); + + dialog.setViewMode(QFileDialog::List); + dialog.setFilter( QDir::AllEntries | QDir::AllDirs | QDir::Hidden ); + dialog.setLabelText( QFileDialog::Accept, tr("Save") ); + + base = FCEUI_GetBaseDirectory(); + + urls << QUrl::fromLocalFile( QDir::rootPath() ); + urls << QUrl::fromLocalFile(QStandardPaths::standardLocations(QStandardPaths::HomeLocation).first()); + urls << QUrl::fromLocalFile(QStandardPaths::standardLocations(QStandardPaths::DownloadLocation).first()); + + if ( base ) + { + urls << QUrl::fromLocalFile( QDir( base ).absolutePath() ); + + d.setPath( QString(base) + "/movies"); + + if ( d.exists() ) + { + urls << QUrl::fromLocalFile( d.absolutePath() ); + } + + dialog.setDirectory( d.absolutePath() ); + } + dialog.setDefaultSuffix( tr(".fm3") ); + + g_config->getOption ("SDL.TasProjectFilePath", &lastPath); + if ( lastPath.size() > 0 ) + { + dialog.setDirectory( QString::fromStdString(lastPath) ); + } + + rom = getRomFile(); + + if ( rom ) + { + char baseName[512]; + getFileBaseName( rom, baseName ); + + if ( baseName[0] != 0 ) + { + dialog.selectFile(baseName); + } + } + + // Check config option to use native file dialog or not + g_config->getOption ("SDL.UseNativeFileDialog", &useNativeFileDialogVal); + + dialog.setOption(QFileDialog::DontUseNativeDialog, !useNativeFileDialogVal); + dialog.setSidebarUrls(urls); + + ret = dialog.exec(); + + if ( ret ) + { + QStringList fileList; + fileList = dialog.selectedFiles(); + + if ( fileList.size() > 0 ) + { + filename = fileList[0]; + } + } + + if ( filename.isNull() ) + { + return false; + } + //qDebug() << "selected file path : " << filename.toUtf8(); + + project.renameProject( filename.toStdString().c_str(), true); + if (save_compact) + { + project.save( filename.toStdString().c_str(), taseditorConfig.saveCompact_SaveInBinary, taseditorConfig.saveCompact_SaveMarkers, taseditorConfig.saveCompact_SaveBookmarks, taseditorConfig.saveCompact_GreenzoneSavingMode, taseditorConfig.saveCompact_SaveHistory, taseditorConfig.saveCompact_SavePianoRoll, taseditorConfig.saveCompact_SaveSelection); + } + else + { + project.save( filename.toStdString().c_str(), taseditorConfig.projectSavingOptions_SaveInBinary, taseditorConfig.projectSavingOptions_SaveMarkers, taseditorConfig.projectSavingOptions_SaveBookmarks, taseditorConfig.projectSavingOptions_GreenzoneSavingMode, taseditorConfig.projectSavingOptions_SaveHistory, taseditorConfig.projectSavingOptions_SavePianoRoll, taseditorConfig.projectSavingOptions_SaveSelection); + } + //taseditorWindow.updateRecentProjectsArray(nameo); + // saved successfully - remove * mark from caption + //taseditorWindow.updateCaption(); + return true; +} + +// returns false if user doesn't want to exit +bool TasEditorWindow::askToSaveProject(void) +{ + bool changesFound = false; + if (project.getProjectChanged()) + { + changesFound = true; + } + + // ask saving project + if (changesFound) + { + int ans = QMessageBox::question( this, tr("TAS Editor"), tr("Save project changes?"), + QMessageBox::Yes | QMessageBox::No, QMessageBox::Yes ); + + //int answer = MessageBox(taseditorWindow.hwndTASEditor, "Save Project changes?", "TAS Editor", MB_YESNOCANCEL); + if (ans == QMessageBox::Yes) + { + return saveProject(); + } + return (ans != QMessageBox::No); + } + return true; +} +//---------------------------------------------------------------------------- +void TasEditorWindow::createNewProject(void) +{ + //if (!askToSaveProject()) return; + + fceuWrapperLock(); + + static struct NewProjectParameters params; + //if (DialogBoxParam(fceu_hInstance, MAKEINTRESOURCE(IDD_TASEDITOR_NEWPROJECT), taseditorWindow.hwndTASEditor, newProjectProc, (LPARAM)¶ms) > 0) + //{ + FCEUMOV_CreateCleanMovie(); + // apply selected options + setInputType(currMovieData, params.inputType); + applyMovieInputConfig(); + if (params.copyCurrentInput) + { + // copy Input from current snapshot (from history) + history.getCurrentSnapshot().inputlog.toMovie(currMovieData); + } + if (!params.copyCurrentMarkers) + { + markersManager.reset(); + } + if (params.authorName != L"") currMovieData.comments.push_back(L"author " + params.authorName); + + // reset Taseditor + project.init(); // new project has blank name + greenzone.reset(); + if (params.copyCurrentInput) + { + // copy LagLog from current snapshot (from history) + greenzone.lagLog = history.getCurrentSnapshot().laglog; + } + playback.reset(); + playback.restartPlaybackFromZeroGround(); + bookmarks.reset(); + branches.reset(); + history.reset(); + //pianoRoll.reset(); + selection.reset(); + //editor.reset(); + splicer.reset(); + recorder.reset(); + //popupDisplay.reset(); + //taseditorWindow.redraw(); + //taseditorWindow.updateCaption(); + update(); + //} + fceuWrapperUnLock(); +} +//---------------------------------------------------------------------------- //---- TAS Piano Roll Widget //---------------------------------------------------------------------------- QPianoRoll::QPianoRoll(QWidget *parent) diff --git a/src/drivers/Qt/TasEditor/TasEditorWindow.h b/src/drivers/Qt/TasEditor/TasEditorWindow.h index 52599531..257089ff 100644 --- a/src/drivers/Qt/TasEditor/TasEditorWindow.h +++ b/src/drivers/Qt/TasEditor/TasEditorWindow.h @@ -49,6 +49,14 @@ class TasEditorWindow; +struct NewProjectParameters +{ + int inputType; + bool copyCurrentInput; + bool copyCurrentMarkers; + std::wstring authorName; +}; + class QPianoRoll : public QWidget { Q_OBJECT @@ -104,6 +112,8 @@ class TasEditorWindow : public QDialog RECORDER recorder; HISTORY history; BRANCHES branches; + + protected: void closeEvent(QCloseEvent *event); @@ -165,10 +175,16 @@ class TasEditorWindow : public QDialog private: int initModules(void); + bool loadProject(const char* fullname); + bool saveProject(bool save_compact = false); + bool saveProjectAs(bool save_compact = false); + bool askToSaveProject(void); public slots: void closeWindow(void); + void frameUpdate(void); private slots: + void createNewProject(void); }; extern TASEDITOR_PROJECT *project; @@ -189,6 +205,6 @@ bool tasWindowIsOpen(void); void tasWindowSetFocus(bool val); bool isTaseditorRecording(void); -bool recordInputByTaseditor(void); +void recordInputByTaseditor(void); extern TasEditorWindow *tasWin;