Qt JS engine in work.
This commit is contained in:
parent
3436e221de
commit
ecda95ed70
|
@ -15,13 +15,13 @@ endif()
|
|||
|
||||
if (NOT DEFINED QT)
|
||||
message( STATUS "Attempting to determine Qt Version...")
|
||||
find_package( Qt6 COMPONENTS Core)
|
||||
find_package( Qt6 COMPONENTS Core QUIET)
|
||||
|
||||
if (${Qt6Core_FOUND})
|
||||
message( STATUS "Found Qt Version: ${Qt6Core_VERSION}")
|
||||
set( QT 6 )
|
||||
else()
|
||||
find_package( Qt5 COMPONENTS Core)
|
||||
find_package( Qt5 COMPONENTS Core QUIET)
|
||||
|
||||
if (${Qt5Core_FOUND})
|
||||
message( STATUS "Found Qt Version: ${Qt5Core_VERSION}")
|
||||
|
@ -41,8 +41,9 @@ if ( ${QT} EQUAL 6 )
|
|||
find_package( Qt6 REQUIRED COMPONENTS Widgets OpenGL OpenGLWidgets)
|
||||
find_package( Qt6 COMPONENTS Help QUIET)
|
||||
find_package( Qt6 COMPONENTS Qml)
|
||||
add_definitions( ${Qt6Widgets_DEFINITIONS} ${Qt6Qml_DEFINITIONS} ${Qt6Help_DEFINITIONS} ${Qt6OpenGLWidgets_DEFINITIONS} )
|
||||
include_directories( ${Qt6Widgets_INCLUDE_DIRS} ${Qt6Qml_INCLUDE_DIRS} ${Qt6Help_INCLUDE_DIRS} ${Qt6OpenGLWidgets_INCLUDE_DIRS} )
|
||||
find_package( Qt6 COMPONENTS UiTools)
|
||||
add_definitions( ${Qt6Widgets_DEFINITIONS} ${Qt6Qml_DEFINITIONS} ${Qt6UiTools_DEFINITIONS} ${Qt6Help_DEFINITIONS} ${Qt6OpenGLWidgets_DEFINITIONS} )
|
||||
include_directories( ${Qt6Widgets_INCLUDE_DIRS} ${Qt6Qml_INCLUDE_DIRS} ${Qt6UiTools_INCLUDE_DIRS} ${Qt6Help_INCLUDE_DIRS} ${Qt6OpenGLWidgets_INCLUDE_DIRS} )
|
||||
|
||||
if (${Qt6Help_FOUND})
|
||||
message( STATUS "Qt6 Help Module Found")
|
||||
|
@ -55,18 +56,26 @@ if ( ${QT} EQUAL 6 )
|
|||
|
||||
if (${Qt6Qml_FOUND})
|
||||
message( STATUS "Qt6 Qml Module Found")
|
||||
#add_definitions( -D__FCEU_QSCRIPT_ENABLE__ )
|
||||
add_definitions( -D__FCEU_QSCRIPT_ENABLE__ )
|
||||
else()
|
||||
message( STATUS "Qt6 Qml Module Not Found")
|
||||
endif()
|
||||
|
||||
if (${Qt6UiTools_FOUND})
|
||||
message( STATUS "Qt6 UiTools Module Found")
|
||||
add_definitions( -D__QT_UI_TOOLS__ )
|
||||
else()
|
||||
message( STATUS "Qt6 UiTools Module Not Found")
|
||||
endif()
|
||||
else()
|
||||
message( STATUS "GUI Frontend: Qt5")
|
||||
set( Qt Qt5 )
|
||||
find_package( Qt5 REQUIRED COMPONENTS Widgets OpenGL)
|
||||
find_package( Qt5 COMPONENTS Help QUIET)
|
||||
find_package( Qt5 COMPONENTS Qml)
|
||||
add_definitions( ${Qt5Widgets_DEFINITIONS} ${Qt5Qml_DEFINITIONS} ${Qt5Help_DEFINITIONS} )
|
||||
include_directories( ${Qt5Widgets_INCLUDE_DIRS} ${Qt5Qml_INCLUDE_DIRS} ${Qt5Help_INCLUDE_DIRS} )
|
||||
find_package( Qt5 COMPONENTS UiTools)
|
||||
add_definitions( ${Qt5Widgets_DEFINITIONS} ${Qt5Qml_DEFINITIONS} ${Qt5UiTools_DEFINITIONS} ${Qt5Help_DEFINITIONS} )
|
||||
include_directories( ${Qt5Widgets_INCLUDE_DIRS} ${Qt5Qml_INCLUDE_DIRS} ${Qt5UiTools_INCLUDE_DIRS} ${Qt5Help_INCLUDE_DIRS} )
|
||||
|
||||
if (${Qt5Help_FOUND})
|
||||
message( STATUS "Qt5 Help Module Found")
|
||||
|
@ -83,6 +92,13 @@ else()
|
|||
else()
|
||||
message( STATUS "Qt5 Qml Module Not Found")
|
||||
endif()
|
||||
|
||||
if (${Qt5UiTools_FOUND})
|
||||
message( STATUS "Qt5 UiTools Module Found")
|
||||
add_definitions( -D__QT_UI_TOOLS__ )
|
||||
else()
|
||||
message( STATUS "Qt5 UiTools Module Not Found")
|
||||
endif()
|
||||
endif()
|
||||
|
||||
if(WIN32)
|
||||
|
@ -714,6 +730,7 @@ target_link_libraries( ${APP_NAME}
|
|||
${${Qt}Widgets_LIBRARIES}
|
||||
${${Qt}Help_LIBRARIES}
|
||||
${${Qt}Qml_LIBRARIES}
|
||||
${${Qt}UiTools_LIBRARIES}
|
||||
${${Qt}OpenGL_LIBRARIES}
|
||||
${${Qt}OpenGLWidgets_LIBRARIES}
|
||||
${OPENGL_LDFLAGS}
|
||||
|
|
|
@ -34,6 +34,10 @@
|
|||
#include <QSettings>
|
||||
#include <QJSValueIterator>
|
||||
|
||||
#ifdef __QT_UI_TOOLS__
|
||||
#include <QUiLoader>
|
||||
#endif
|
||||
|
||||
#include "../../fceu.h"
|
||||
#include "../../movie.h"
|
||||
|
||||
|
@ -54,6 +58,7 @@
|
|||
EmuScriptObject::EmuScriptObject(QObject* parent)
|
||||
: QObject(parent)
|
||||
{
|
||||
script = qobject_cast<QtScriptInstance*>(parent);
|
||||
}
|
||||
//----------------------------------------------------
|
||||
EmuScriptObject::~EmuScriptObject()
|
||||
|
@ -68,7 +73,12 @@ void EmuScriptObject::print(const QString& msg)
|
|||
}
|
||||
}
|
||||
//----------------------------------------------------
|
||||
void EmuScriptObject::softreset()
|
||||
void EmuScriptObject::powerOn()
|
||||
{
|
||||
fceuWrapperHardReset();
|
||||
}
|
||||
//----------------------------------------------------
|
||||
void EmuScriptObject::softReset()
|
||||
{
|
||||
fceuWrapperSoftReset();
|
||||
}
|
||||
|
@ -83,6 +93,92 @@ void EmuScriptObject::unpause()
|
|||
FCEUI_SetEmulationPaused(0);
|
||||
}
|
||||
//----------------------------------------------------
|
||||
bool EmuScriptObject::paused()
|
||||
{
|
||||
return FCEUI_EmulationPaused() != 0;
|
||||
}
|
||||
//----------------------------------------------------
|
||||
int EmuScriptObject::framecount()
|
||||
{
|
||||
return FCEUMOV_GetFrame();
|
||||
}
|
||||
//----------------------------------------------------
|
||||
int EmuScriptObject::lagcount()
|
||||
{
|
||||
return FCEUI_GetLagCount();
|
||||
}
|
||||
//----------------------------------------------------
|
||||
bool EmuScriptObject::lagged()
|
||||
{
|
||||
return FCEUI_GetLagged();
|
||||
}
|
||||
//----------------------------------------------------
|
||||
void EmuScriptObject::setlagflag(bool flag)
|
||||
{
|
||||
FCEUI_SetLagFlag(flag);
|
||||
}
|
||||
//----------------------------------------------------
|
||||
bool EmuScriptObject::emulating()
|
||||
{
|
||||
return (GameInfo != nullptr);
|
||||
}
|
||||
//----------------------------------------------------
|
||||
void EmuScriptObject::message(const QString& msg)
|
||||
{
|
||||
FCEU_DispMessage("%s",0, msg.toStdString().c_str());
|
||||
}
|
||||
//----------------------------------------------------
|
||||
void EmuScriptObject::speedMode(const QString& mode)
|
||||
{
|
||||
int speed = EMUSPEED_NORMAL;
|
||||
bool useTurbo = false;
|
||||
|
||||
if (mode.contains("normal", Qt::CaseInsensitive))
|
||||
{
|
||||
speed = EMUSPEED_NORMAL;
|
||||
}
|
||||
else if (mode.contains("nothrottle", Qt::CaseInsensitive))
|
||||
{
|
||||
useTurbo = true;
|
||||
}
|
||||
else if (mode.contains("turbo", Qt::CaseInsensitive))
|
||||
{
|
||||
useTurbo = true;
|
||||
}
|
||||
else if (mode.contains("maximum", Qt::CaseInsensitive))
|
||||
{
|
||||
speed = EMUSPEED_FASTEST;
|
||||
}
|
||||
else
|
||||
{
|
||||
QString msg = "Invalid mode argument \"" + mode + "\" to emu.speedmode\n";
|
||||
script->throwError(QJSValue::TypeError, msg);
|
||||
return;
|
||||
}
|
||||
|
||||
if (useTurbo)
|
||||
{
|
||||
FCEUD_TurboOn();
|
||||
}
|
||||
else
|
||||
{
|
||||
FCEUD_TurboOff();
|
||||
}
|
||||
FCEUD_SetEmulationSpeed(speed);
|
||||
}
|
||||
//----------------------------------------------------
|
||||
bool EmuScriptObject::loadRom(const QString& romPath)
|
||||
{
|
||||
int ret = LoadGame(romPath.toLocal8Bit().constData());
|
||||
|
||||
return ret != 0;
|
||||
}
|
||||
//----------------------------------------------------
|
||||
QString EmuScriptObject::getDir()
|
||||
{
|
||||
return QString(fceuExecutablePath());
|
||||
}
|
||||
//----------------------------------------------------
|
||||
//---- Qt Script Instance
|
||||
//----------------------------------------------------
|
||||
QtScriptInstance::QtScriptInstance(QObject* parent)
|
||||
|
@ -99,6 +195,8 @@ QtScriptInstance::QtScriptInstance(QObject* parent)
|
|||
}
|
||||
engine = new QJSEngine(this);
|
||||
|
||||
emu->setEngine(engine);
|
||||
|
||||
configEngine();
|
||||
|
||||
QtScriptManager::getInstance()->addScriptInstance(this);
|
||||
|
@ -118,6 +216,8 @@ QtScriptInstance::~QtScriptInstance()
|
|||
//----------------------------------------------------
|
||||
void QtScriptInstance::resetEngine()
|
||||
{
|
||||
running = false;
|
||||
|
||||
if (engine != nullptr)
|
||||
{
|
||||
engine->deleteLater();
|
||||
|
@ -136,7 +236,12 @@ int QtScriptInstance::configEngine()
|
|||
|
||||
engine->globalObject().setProperty("emu", emuObject);
|
||||
|
||||
QJSValue guiObject = engine->newQObject(this);
|
||||
|
||||
engine->globalObject().setProperty("gui", guiObject);
|
||||
|
||||
onFrameFinishCallback = QJSValue();
|
||||
onScriptStopCallback = QJSValue();
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -145,6 +250,8 @@ int QtScriptInstance::loadScriptFile( QString filepath )
|
|||
{
|
||||
QFile scriptFile(filepath);
|
||||
|
||||
running = false;
|
||||
|
||||
if (!scriptFile.open(QIODevice::ReadOnly))
|
||||
{
|
||||
return -1;
|
||||
|
@ -164,13 +271,60 @@ int QtScriptInstance::loadScriptFile( QString filepath )
|
|||
}
|
||||
else
|
||||
{
|
||||
running = true;
|
||||
//printf("Script Evaluation Success!\n");
|
||||
}
|
||||
onFrameFinishCallback = engine->globalObject().property("onFrameFinish");
|
||||
onScriptStopCallback = engine->globalObject().property("onScriptStop");
|
||||
|
||||
return 0;
|
||||
}
|
||||
//----------------------------------------------------
|
||||
void QtScriptInstance::loadObjectChildren(QJSValue& jsObject, QObject* obj)
|
||||
{
|
||||
const QObjectList& childList = obj->children();
|
||||
|
||||
for (auto& child : childList)
|
||||
{
|
||||
QString name = child->objectName();
|
||||
|
||||
if (!name.isEmpty())
|
||||
{
|
||||
printf("Object: %s.%s\n", obj->objectName().toStdString().c_str(), child->objectName().toStdString().c_str());
|
||||
|
||||
QJSValue newJsObj = engine->newQObject(child);
|
||||
|
||||
jsObject.setProperty(child->objectName(), newJsObj);
|
||||
|
||||
loadObjectChildren( newJsObj, child);
|
||||
}
|
||||
}
|
||||
}
|
||||
//----------------------------------------------------
|
||||
void QtScriptInstance::loadUI(const QString& uiFilePath)
|
||||
{
|
||||
#ifdef __QT_UI_TOOLS__
|
||||
QFile uiFile(uiFilePath);
|
||||
QUiLoader uiLoader;
|
||||
|
||||
QWidget* rootWidget = uiLoader.load(&uiFile, dialog);
|
||||
|
||||
if (rootWidget == nullptr)
|
||||
{
|
||||
return;
|
||||
}
|
||||
QJSValue uiObject = engine->newQObject(rootWidget);
|
||||
|
||||
engine->globalObject().setProperty("ui", uiObject);
|
||||
|
||||
loadObjectChildren( uiObject, rootWidget);
|
||||
|
||||
rootWidget->show();
|
||||
#else
|
||||
throwError(QJSValue::GenericError, "Error: Application was not linked against Qt UI Tools");
|
||||
#endif
|
||||
}
|
||||
//----------------------------------------------------
|
||||
void QtScriptInstance::print(const QString& msg)
|
||||
{
|
||||
if (dialog)
|
||||
|
@ -179,6 +333,14 @@ void QtScriptInstance::print(const QString& msg)
|
|||
}
|
||||
}
|
||||
//----------------------------------------------------
|
||||
int QtScriptInstance::throwError(QJSValue::ErrorType errorType, const QString &message)
|
||||
{
|
||||
running = false;
|
||||
print(message);
|
||||
engine->setInterrupted(true);
|
||||
return 0;
|
||||
}
|
||||
//----------------------------------------------------
|
||||
void QtScriptInstance::printSymbols(QJSValue& val, int iter)
|
||||
{
|
||||
int i=0;
|
||||
|
@ -236,17 +398,74 @@ int QtScriptInstance::call(const QString& funcName, const QJSValueList& args)
|
|||
return 0;
|
||||
}
|
||||
//----------------------------------------------------
|
||||
void QtScriptInstance::stopRunning()
|
||||
{
|
||||
if (running)
|
||||
{
|
||||
if (onScriptStopCallback.isCallable())
|
||||
{
|
||||
onScriptStopCallback.call();
|
||||
}
|
||||
running = false;
|
||||
}
|
||||
}
|
||||
//----------------------------------------------------
|
||||
void QtScriptInstance::onFrameFinish()
|
||||
{
|
||||
if (onFrameFinishCallback.isCallable())
|
||||
if (running && onFrameFinishCallback.isCallable())
|
||||
{
|
||||
onFrameFinishCallback.call();
|
||||
}
|
||||
}
|
||||
//----------------------------------------------------
|
||||
bool QtScriptInstance::isRunning()
|
||||
QString QtScriptInstance::openFileBrowser(const QString& initialPath)
|
||||
{
|
||||
return false;
|
||||
QString selectedFile;
|
||||
QFileDialog dialog(this->dialog, tr("Open File") );
|
||||
QList<QUrl> urls;
|
||||
bool useNativeFileDialogVal = false;
|
||||
|
||||
g_config->getOption("SDL.UseNativeFileDialog", &useNativeFileDialogVal);
|
||||
|
||||
const QStringList filters({
|
||||
"Any files (*)"
|
||||
});
|
||||
|
||||
urls << QUrl::fromLocalFile( QDir::rootPath() );
|
||||
urls << QUrl::fromLocalFile(QStandardPaths::standardLocations(QStandardPaths::HomeLocation).first());
|
||||
urls << QUrl::fromLocalFile(QStandardPaths::standardLocations(QStandardPaths::DesktopLocation).first());
|
||||
urls << QUrl::fromLocalFile(QStandardPaths::standardLocations(QStandardPaths::DownloadLocation).first());
|
||||
urls << QUrl::fromLocalFile( QDir( FCEUI_GetBaseDirectory() ).absolutePath() );
|
||||
|
||||
dialog.setFileMode(QFileDialog::ExistingFile);
|
||||
|
||||
dialog.setNameFilters( filters );
|
||||
|
||||
dialog.setViewMode(QFileDialog::List);
|
||||
dialog.setFilter( QDir::AllEntries | QDir::AllDirs | QDir::Hidden );
|
||||
dialog.setLabelText( QFileDialog::Accept, tr("Open") );
|
||||
|
||||
if (!initialPath.isEmpty() )
|
||||
{
|
||||
dialog.setDirectory( initialPath );
|
||||
}
|
||||
|
||||
dialog.setOption(QFileDialog::DontUseNativeDialog, !useNativeFileDialogVal);
|
||||
dialog.setSidebarUrls(urls);
|
||||
|
||||
int ret = dialog.exec();
|
||||
|
||||
if ( ret )
|
||||
{
|
||||
QStringList fileList;
|
||||
fileList = dialog.selectedFiles();
|
||||
|
||||
if ( fileList.size() > 0 )
|
||||
{
|
||||
selectedFile = fileList[0];
|
||||
}
|
||||
}
|
||||
return selectedFile;
|
||||
}
|
||||
//----------------------------------------------------
|
||||
//---- Qt Script Manager
|
||||
|
@ -401,31 +620,24 @@ QScriptDialog_t::QScriptDialog_t(QWidget *parent)
|
|||
|
||||
restoreGeometry(settings.value("QScriptWindow/geometry").toByteArray());
|
||||
}
|
||||
|
||||
//----------------------------------------------------
|
||||
QScriptDialog_t::~QScriptDialog_t(void)
|
||||
{
|
||||
QSettings settings;
|
||||
std::list<QScriptDialog_t *>::iterator it;
|
||||
|
||||
//printf("Destroy JS Control Window\n");
|
||||
|
||||
periodicTimer->stop();
|
||||
|
||||
//for (it = winList.begin(); it != winList.end(); it++)
|
||||
//{
|
||||
// if ((*it) == this)
|
||||
// {
|
||||
// winList.erase(it);
|
||||
// //printf("Removing JS Window\n");
|
||||
// break;
|
||||
// }
|
||||
//}
|
||||
scriptInstance->stopRunning();
|
||||
|
||||
settings.setValue("QScriptWindow/geometry", saveGeometry());
|
||||
}
|
||||
//----------------------------------------------------
|
||||
void QScriptDialog_t::closeEvent(QCloseEvent *event)
|
||||
{
|
||||
scriptInstance->stopRunning();
|
||||
|
||||
//printf("JS Control Close Window Event\n");
|
||||
done(0);
|
||||
deleteLater();
|
||||
|
@ -434,6 +646,8 @@ void QScriptDialog_t::closeEvent(QCloseEvent *event)
|
|||
//----------------------------------------------------
|
||||
void QScriptDialog_t::closeWindow(void)
|
||||
{
|
||||
scriptInstance->stopRunning();
|
||||
|
||||
//printf("JS Control Close Window\n");
|
||||
done(0);
|
||||
deleteLater();
|
||||
|
@ -625,10 +839,14 @@ void QScriptDialog_t::startScript(void)
|
|||
QJSValueList argList = { argArray };
|
||||
|
||||
scriptInstance->call("main", argList);
|
||||
|
||||
refreshState();
|
||||
}
|
||||
//----------------------------------------------------
|
||||
void QScriptDialog_t::stopScript(void)
|
||||
{
|
||||
scriptInstance->stopRunning();
|
||||
refreshState();
|
||||
}
|
||||
//----------------------------------------------------
|
||||
void QScriptDialog_t::refreshState(void)
|
||||
|
|
|
@ -26,6 +26,7 @@
|
|||
#include "utils/timeStamp.h"
|
||||
|
||||
class QScriptDialog_t;
|
||||
class QtScriptInstance;
|
||||
|
||||
class EmuScriptObject: public QObject
|
||||
{
|
||||
|
@ -34,16 +35,30 @@ public:
|
|||
EmuScriptObject(QObject* parent = nullptr);
|
||||
~EmuScriptObject();
|
||||
|
||||
void setEngine(QJSEngine* _engine){ engine = _engine; }
|
||||
void setDialog(QScriptDialog_t* _dialog){ dialog = _dialog; }
|
||||
|
||||
private:
|
||||
QJSEngine* engine = nullptr;
|
||||
QScriptDialog_t* dialog = nullptr;
|
||||
QtScriptInstance* script = nullptr;
|
||||
|
||||
public slots:
|
||||
Q_INVOKABLE void print(const QString& msg);
|
||||
Q_INVOKABLE void softreset();
|
||||
Q_INVOKABLE void powerOn();
|
||||
Q_INVOKABLE void softReset();
|
||||
Q_INVOKABLE void pause();
|
||||
Q_INVOKABLE void unpause();
|
||||
Q_INVOKABLE bool paused();
|
||||
Q_INVOKABLE int framecount();
|
||||
Q_INVOKABLE int lagcount();
|
||||
Q_INVOKABLE bool lagged();
|
||||
Q_INVOKABLE void setlagflag(bool flag);
|
||||
Q_INVOKABLE bool emulating();
|
||||
Q_INVOKABLE void message(const QString& msg);
|
||||
Q_INVOKABLE void speedMode(const QString& mode);
|
||||
Q_INVOKABLE bool loadRom(const QString& romPath);
|
||||
Q_INVOKABLE QString getDir();
|
||||
|
||||
};
|
||||
|
||||
|
@ -57,24 +72,32 @@ public:
|
|||
void resetEngine();
|
||||
int loadScriptFile(QString filepath);
|
||||
|
||||
bool isRunning();
|
||||
bool isRunning(){ return running; };
|
||||
void stopRunning();
|
||||
|
||||
int call(const QString& funcName, const QJSValueList& args = QJSValueList());
|
||||
void onFrameFinish();
|
||||
|
||||
int throwError(QJSValue::ErrorType errorType, const QString &message = QString());
|
||||
|
||||
QJSEngine* getEngine(){ return engine; };
|
||||
private:
|
||||
|
||||
int configEngine();
|
||||
void printSymbols(QJSValue& val, int iter = 0);
|
||||
void loadObjectChildren(QJSValue& jsObject, QObject* obj);
|
||||
|
||||
QJSEngine* engine = nullptr;
|
||||
QScriptDialog_t* dialog = nullptr;
|
||||
EmuScriptObject* emu = nullptr;
|
||||
QJSValue onFrameFinishCallback;
|
||||
QJSValue onScriptStopCallback;
|
||||
bool running = false;
|
||||
|
||||
public slots:
|
||||
Q_INVOKABLE void print(const QString& msg);
|
||||
Q_INVOKABLE void loadUI(const QString& uiFilePath);
|
||||
Q_INVOKABLE QString openFileBrowser(const QString& initialPath = QString());
|
||||
};
|
||||
|
||||
class QtScriptManager : public QObject
|
||||
|
|
Loading…
Reference in New Issue