Skip to content

Commit

Permalink
Qt JS script engine interface in work.
Browse files Browse the repository at this point in the history
  • Loading branch information
thor2016 committed Jan 15, 2024
1 parent 8e7e5e8 commit 198cdaf
Show file tree
Hide file tree
Showing 4 changed files with 137 additions and 61 deletions.
10 changes: 7 additions & 3 deletions src/drivers/Qt/ConsoleWindow.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -186,6 +186,10 @@ consoleWin_t::consoleWin_t(QWidget *parent)
gameTimer->setTimerType( Qt::PreciseTimer );
gameTimer->start( 8 ); // 120hz

#ifdef __FCEU_QSCRIPT_ENABLE__
QtScriptManager::create(nullptr);
#endif

emulatorThread->start();

g_config->getOption( "SDL.SetSchedParam", &opt );
Expand Down Expand Up @@ -272,9 +276,6 @@ consoleWin_t::consoleWin_t(QWidget *parent)
// Create AVI Recording Disk Thread
aviDiskThread = new AviRecordDiskThread_t(this);

#ifdef __FCEU_QSCRIPT_ENABLE__
QtScriptManager::create(this);
#endif
scrHandlerConnected = false;
}

Expand Down Expand Up @@ -316,6 +317,9 @@ consoleWin_t::~consoleWin_t(void)

closeGamePadConfWindow();

#ifdef __FCEU_QSCRIPT_ENABLE__
QtScriptManager::destroy();
#endif
// The closeApp function call stops all threads.
// Calling quit on threads should not happen here.
//printf("Thread Finished: %i \n", emulatorThread->isFinished() );
Expand Down
152 changes: 100 additions & 52 deletions src/drivers/Qt/QtScriptManager.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -167,10 +167,29 @@ void EmuScriptObject::speedMode(const QString& mode)
FCEUD_SetEmulationSpeed(speed);
}
//----------------------------------------------------
void EmuScriptObject::registerBefore(const QJSValue& func)
{
script->registerBefore(func);
}
//----------------------------------------------------
void EmuScriptObject::registerAfter(const QJSValue& func)
{
script->registerAfter(func);
}
//----------------------------------------------------
void EmuScriptObject::registerStop(const QJSValue& func)
{
script->registerStop(func);
}
//----------------------------------------------------
bool EmuScriptObject::loadRom(const QString& romPath)
{
int ret = LoadGame(romPath.toLocal8Bit().constData());
int ret = 0;

if (!romPath.isEmpty())
{
ret = LoadGame(romPath.toLocal8Bit().constData());
}
return ret != 0;
}
//----------------------------------------------------
Expand All @@ -193,7 +212,7 @@ QtScriptInstance::QtScriptInstance(QObject* parent)
dialog = win;
emu->setDialog(dialog);
}
engine = new QJSEngine(this);
engine = new QJSEngine(nullptr);

emu->setEngine(engine);

Expand Down Expand Up @@ -223,7 +242,14 @@ void QtScriptInstance::resetEngine()
engine->deleteLater();
engine = nullptr;
}
engine = new QJSEngine(this);
engine = new QJSEngine(nullptr);

if (ui_rootWidget != nullptr)
{
ui_rootWidget->hide();
ui_rootWidget->deleteLater();
ui_rootWidget = nullptr;
}

configEngine();
}
Expand All @@ -240,8 +266,7 @@ int QtScriptInstance::configEngine()

engine->globalObject().setProperty("gui", guiObject);

QtScriptManager::getInstance()->removeFrameFinishedConnection(this);

onFrameBeginCallback = QJSValue();
onFrameFinishCallback = QJSValue();
onScriptStopCallback = QJSValue();

Expand Down Expand Up @@ -276,13 +301,10 @@ int QtScriptInstance::loadScriptFile( QString filepath )
running = true;
//printf("Script Evaluation Success!\n");
}
onFrameFinishCallback = engine->globalObject().property("onFrameFinish");
onScriptStopCallback = engine->globalObject().property("onScriptStop");
//onFrameBeginCallback = engine->globalObject().property("onFrameBegin");
//onFrameFinishCallback = engine->globalObject().property("onFrameFinish");
//onScriptStopCallback = engine->globalObject().property("onScriptStop");

if (onFrameFinishCallback.isCallable())
{
QtScriptManager::getInstance()->addFrameFinishedConnection(this);
}
return 0;
}
//----------------------------------------------------
Expand Down Expand Up @@ -313,24 +335,40 @@ void QtScriptInstance::loadUI(const QString& uiFilePath)
QFile uiFile(uiFilePath);
QUiLoader uiLoader;

QWidget* rootWidget = uiLoader.load(&uiFile, dialog);
ui_rootWidget = uiLoader.load(&uiFile, dialog);

if (rootWidget == nullptr)
if (ui_rootWidget == nullptr)
{
return;
}
QJSValue uiObject = engine->newQObject(rootWidget);

QJSValue uiObject = engine->newQObject(ui_rootWidget);

engine->globalObject().setProperty("ui", uiObject);

loadObjectChildren( uiObject, rootWidget);
loadObjectChildren( uiObject, ui_rootWidget);

rootWidget->show();
ui_rootWidget->show();
#else
throwError(QJSValue::GenericError, "Error: Application was not linked against Qt UI Tools");
#endif
}
//----------------------------------------------------
void QtScriptInstance::registerBefore(const QJSValue& func)
{
onFrameBeginCallback = func;
}
//----------------------------------------------------
void QtScriptInstance::registerAfter(const QJSValue& func)
{
onFrameFinishCallback = func;
}
//----------------------------------------------------
void QtScriptInstance::registerStop(const QJSValue& func)
{
onScriptStopCallback = func;
}
//----------------------------------------------------
void QtScriptInstance::print(const QString& msg)
{
if (dialog)
Expand Down Expand Up @@ -416,6 +454,14 @@ void QtScriptInstance::stopRunning()
}
}
//----------------------------------------------------
void QtScriptInstance::onFrameBegin()
{
if (running && onFrameBeginCallback.isCallable())
{
onFrameBeginCallback.call();
}
}
//----------------------------------------------------
void QtScriptInstance::onFrameFinish()
{
if (running && onFrameFinishCallback.isCallable())
Expand Down Expand Up @@ -499,6 +545,14 @@ QtScriptManager* QtScriptManager::create(QObject* parent)
return mgr;
}
//----------------------------------------------------
void QtScriptManager::destroy(void)
{
if (_instance != nullptr)
{
delete _instance;
}
}
//----------------------------------------------------
void QtScriptManager::addScriptInstance(QtScriptInstance* script)
{
scriptList.push_back(script);
Expand All @@ -519,45 +573,22 @@ void QtScriptManager::removeScriptInstance(QtScriptInstance* script)
it++;
}
}

removeFrameFinishedConnection(script);
}
//----------------------------------------------------
void QtScriptManager::addFrameFinishedConnection(QtScriptInstance* script)
void QtScriptManager::frameBeginUpdate()
{
if (frameFinishConnectList.size() == 0)
{
connect(consoleWindow->emulatorThread, SIGNAL(frameFinished(void)), this, SLOT(frameFinishedUpdate(void)), Qt::BlockingQueuedConnection);
}
frameFinishConnectList.push_back(script);
}
//----------------------------------------------------
void QtScriptManager::removeFrameFinishedConnection(QtScriptInstance* script)
{
auto it = frameFinishConnectList.begin();

while (it != frameFinishConnectList.end())
{
if (*it == script)
{
it = frameFinishConnectList.erase(it);
}
else
{
it++;
}
}

if (frameFinishConnectList.size() == 0)
FCEU_WRAPPER_LOCK();
for (auto script : scriptList)
{
consoleWindow->emulatorThread->disconnect( SIGNAL(frameFinished(void)), this, SLOT(frameFinishedUpdate(void)));
script->onFrameBegin();
}
FCEU_WRAPPER_UNLOCK();
}
//----------------------------------------------------
void QtScriptManager::frameFinishedUpdate()
{
FCEU_WRAPPER_LOCK();
for (auto script : frameFinishConnectList)
for (auto script : scriptList)
{
script->onFrameFinish();
}
Expand Down Expand Up @@ -649,6 +680,8 @@ QScriptDialog_t::QScriptDialog_t(QWidget *parent)

setLayout(mainLayout);

emuThreadText.reserve(4096);

//winList.push_back(this);

periodicTimer = new QTimer(this);
Expand Down Expand Up @@ -694,13 +727,15 @@ void QScriptDialog_t::closeWindow(void)
//----------------------------------------------------
void QScriptDialog_t::updatePeriodic(void)
{
// TODO
//printf("Update JS\n");
//if (updateJSDisplay)
//{
// updateJSWindows();
// updateJSDisplay = false;
//}
FCEU_WRAPPER_LOCK();
if (!emuThreadText.isEmpty())
{
jsOutput->insertPlainText(emuThreadText);
emuThreadText.clear();
}
refreshState();
FCEU_WRAPPER_UNLOCK();
}
//----------------------------------------------------
void QScriptDialog_t::openJSKillMessageBox(void)
Expand Down Expand Up @@ -863,10 +898,12 @@ void QScriptDialog_t::openScriptFile(void)
//----------------------------------------------------
void QScriptDialog_t::startScript(void)
{
FCEU_WRAPPER_LOCK();
scriptInstance->resetEngine();
if (scriptInstance->loadScriptFile(scriptPath->text()))
{
// Script parsing error
FCEU_WRAPPER_UNLOCK();
return;
}
// TODO add option to pass options to script main.
Expand All @@ -880,12 +917,16 @@ void QScriptDialog_t::startScript(void)
scriptInstance->call("main", argList);

refreshState();

FCEU_WRAPPER_UNLOCK();
}
//----------------------------------------------------
void QScriptDialog_t::stopScript(void)
{
FCEU_WRAPPER_LOCK();
scriptInstance->stopRunning();
refreshState();
FCEU_WRAPPER_UNLOCK();
}
//----------------------------------------------------
void QScriptDialog_t::refreshState(void)
Expand All @@ -904,7 +945,14 @@ void QScriptDialog_t::refreshState(void)
//----------------------------------------------------
void QScriptDialog_t::logOutput(const QString& text)
{
jsOutput->insertPlainText(text);
if (QThread::currentThread() == consoleWindow->emulatorThread)
{
emuThreadText.append(text);
}
else
{
jsOutput->insertPlainText(text);
}
}
//----------------------------------------------------
#endif // __FCEU_QSCRIPT_ENABLE__
18 changes: 13 additions & 5 deletions src/drivers/Qt/QtScriptManager.h
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,9 @@ public slots:
Q_INVOKABLE bool lagged();
Q_INVOKABLE void setlagflag(bool flag);
Q_INVOKABLE bool emulating();
Q_INVOKABLE void registerBefore(const QJSValue& func);
Q_INVOKABLE void registerAfter(const QJSValue& func);
Q_INVOKABLE void registerStop(const QJSValue& func);
Q_INVOKABLE void message(const QString& msg);
Q_INVOKABLE void speedMode(const QString& mode);
Q_INVOKABLE bool loadRom(const QString& romPath);
Expand All @@ -76,6 +79,7 @@ class QtScriptInstance : public QObject
void stopRunning();

int call(const QString& funcName, const QJSValueList& args = QJSValueList());
void onFrameBegin();
void onFrameFinish();

int throwError(QJSValue::ErrorType errorType, const QString &message = QString());
Expand All @@ -90,6 +94,8 @@ class QtScriptInstance : public QObject
QJSEngine* engine = nullptr;
QScriptDialog_t* dialog = nullptr;
EmuScriptObject* emu = nullptr;
QWidget* ui_rootWidget = nullptr;
QJSValue onFrameBeginCallback;
QJSValue onFrameFinishCallback;
QJSValue onScriptStopCallback;
bool running = false;
Expand All @@ -98,6 +104,9 @@ public slots:
Q_INVOKABLE void print(const QString& msg);
Q_INVOKABLE void loadUI(const QString& uiFilePath);
Q_INVOKABLE QString openFileBrowser(const QString& initialPath = QString());
Q_INVOKABLE void registerBefore(const QJSValue& func);
Q_INVOKABLE void registerAfter(const QJSValue& func);
Q_INVOKABLE void registerStop(const QJSValue& func);
};

class QtScriptManager : public QObject
Expand All @@ -110,21 +119,19 @@ class QtScriptManager : public QObject

static QtScriptManager* getInstance(){ return _instance; }
static QtScriptManager* create(QObject* parent = nullptr);
static void destroy();

int numScriptsLoaded(void){ return scriptList.size(); }
void addScriptInstance(QtScriptInstance* script);
void removeScriptInstance(QtScriptInstance* script);
void addFrameFinishedConnection(QtScriptInstance* script);
void removeFrameFinishedConnection(QtScriptInstance* script);
private:
static QtScriptManager* _instance;

QList<QtScriptInstance*> scriptList;
QList<QtScriptInstance*> frameFinishConnectList;
FCEU::timeStampRecord lastFrameUpdate;

int frameFinishedConnectCount = 0;

public slots:
void frameBeginUpdate();
void frameFinishedUpdate();
};

Expand All @@ -151,6 +158,7 @@ class QScriptDialog_t : public QDialog
QPushButton *startButton;
QTextEdit *jsOutput;
QtScriptInstance *scriptInstance;
QString emuThreadText;

private:
public slots:
Expand Down
Loading

0 comments on commit 198cdaf

Please sign in to comment.