Interim JSDoc for Script

This commit is contained in:
David Rowe 2018-04-22 15:26:39 +12:00
parent 01870af624
commit 62930eb576

View file

@ -87,6 +87,10 @@ public:
QUrl definingSandboxURL { QUrl("about:EntityScript") };
};
/**jsdoc
* @namespace Script
* @property {string} context
*/
class ScriptEngine : public BaseScriptEngine, public EntitiesScriptEngineProvider {
Q_OBJECT
Q_PROPERTY(QString context READ getContext)
@ -115,6 +119,11 @@ public:
QString getFilename() const;
/**jsdoc
* Stop the current script.
* @function Script.stop
* @param {boolean} [marshal=false]
*/
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// NOTE - this is intended to be a public interface for Agent scripts, and local scripts, but not for EntityScripts
Q_INVOKABLE void stop(bool marshal = false);
@ -126,26 +135,69 @@ public:
// NOTE - these are NOT intended to be public interfaces available to scripts, the are only Q_INVOKABLE so we can
// properly ensure they are only called on the correct thread
/**jsdoc
* @function Script.registerGlobalObject
* @param {string} name
* @param {object} object
*/
/// registers a global object by name
Q_INVOKABLE void registerGlobalObject(const QString& name, QObject* object);
/**jsdoc
* @function Script.registerGetterSetter
* @param {string} name
* @param {object} getter
* @param {object} setter
* @param {string} [parent=""]
*/
/// registers a global getter/setter
Q_INVOKABLE void registerGetterSetter(const QString& name, QScriptEngine::FunctionSignature getter,
QScriptEngine::FunctionSignature setter, const QString& parent = QString(""));
/**jsdoc
* @function Script.registerFunction
* @param {string} name
* @param {object} function
* @param {number} [numArguments=-1]
*/
/// register a global function
Q_INVOKABLE void registerFunction(const QString& name, QScriptEngine::FunctionSignature fun, int numArguments = -1);
/**jsdoc
* @function Script.registerFunction
* @param {string} parent
* @param {string} name
* @param {object} function
* @param {number} [numArguments=-1]
*/
/// register a function as a method on a previously registered global object
Q_INVOKABLE void registerFunction(const QString& parent, const QString& name, QScriptEngine::FunctionSignature fun,
int numArguments = -1);
/**jsdoc
* @function Script.registerValue
* @param {string} name
* @param {object} value
*/
/// registers a global object by name
Q_INVOKABLE void registerValue(const QString& valueName, QScriptValue value);
/**jsdoc
* @function Script.evaluate
* @param {string} program
* @param {string} filename
* @param {number} [lineNumber=-1]
* @returns {object}
*/
/// evaluate some code in the context of the ScriptEngine and return the result
Q_INVOKABLE QScriptValue evaluate(const QString& program, const QString& fileName, int lineNumber = 1); // this is also used by the script tool widget
/**jsdoc
* @function Script.evaluateInClosure
* @param {object} locals
* @param {object} program
* @returns {object}
*/
Q_INVOKABLE QScriptValue evaluateInClosure(const QScriptValue& locals, const QScriptProgram& program);
/// if the script engine is not already running, this will download the URL and start the process of seting it up
@ -154,24 +206,122 @@ public:
void loadURL(const QUrl& scriptURL, bool reload);
bool hasValidScriptSuffix(const QString& scriptFileName);
/**jsdoc
* @function Script.getContext
* @returns {string}
*/
Q_INVOKABLE QString getContext() const;
/**jsdoc
* @function Script.isClientScript
* @returns {boolean}
*/
Q_INVOKABLE bool isClientScript() const { return _context == CLIENT_SCRIPT; }
/**jsdoc
* @function Script.isEntityClientScript
* @returns {boolean}
*/
Q_INVOKABLE bool isEntityClientScript() const { return _context == ENTITY_CLIENT_SCRIPT; }
/**jsdoc
* @function Script.isEntityServerScript
* @returns {boolean}
*/
Q_INVOKABLE bool isEntityServerScript() const { return _context == ENTITY_SERVER_SCRIPT; }
/**jsdoc
* @function Script.isAgentScript
* @returns {boolean}
*/
Q_INVOKABLE bool isAgentScript() const { return _context == AGENT_SCRIPT; }
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// NOTE - these are intended to be public interfaces available to scripts
/**jsdoc
* @function Script.addEventHandler
* @param {Uuid} entityID
* @param {string} eventName
* @param {function} handler
*/
Q_INVOKABLE void addEventHandler(const EntityItemID& entityID, const QString& eventName, QScriptValue handler);
/**jsdoc
* @function Script.removeEventHandler
* @param {Uuid} entityID
* @param {string} eventName
* @param {function} handler
*/
Q_INVOKABLE void removeEventHandler(const EntityItemID& entityID, const QString& eventName, QScriptValue handler);
/**jsdoc
* Start a new Interface or entity script.
* @function Script.load
* @param {string} filename - The URL of the script to load. Can be relative to the current script.
* @example <caption>Load a script from another script.</caption>
* // First file: scriptA.js
* print("This is script A");
*
* // Second file: scriptB.js
* print("This is script B");
* Script.load("scriptA.js");
*
* // If you run scriptB.js you should see both scripts in the running scripts list.
* // And you should see the following output:
* // This is script B
* // This is script A
*/
Q_INVOKABLE void load(const QString& loadfile);
/**jsdoc
* Include JavaScript from other files in the current script. If a callback is specified the files are loaded and included
* asynchronously, otherwise they are included synchronously (i.e., script execution blocks while the files are included).
* @function Script.include
* @param {string[]} filenames - The URLs of the scripts to include. Each can be relative to the current script.
* @param {function} [callback=null] - The function to call back when the scripts have been included. Can be an in-line
* function or the name of a function.
*/
Q_INVOKABLE void include(const QStringList& includeFiles, QScriptValue callback = QScriptValue());
/**jsdoc
* Include JavaScript from another file in the current script. If a callback is specified the file is loaded and included
* asynchronously, otherwise it is included synchronously (i.e., script execution blocks while the file is included).
* @function Script.include
* @param {string} filename - The URL of the script to include. Can be relative to the current script.
* @param {function} [callback=null] - The function to call back when the script has been included. Can be an in-line
* function or the name of a function.
* @example <caption>Include a script file asynchronously.</caption>
* // First file: scriptA.js
* print("This is script A");
*
* // Second file: scriptB.js
* print("This is script B");
* Script.include("scriptA.js", function () {
* print("Script A has been included");
* });
*
* // If you run scriptB.js you should see only scriptB.js in the running scripts list.
* // And you should see the following output:
* // This is script B
* // This is script A
* // Script A has been included
*/
Q_INVOKABLE void include(const QString& includeFile, QScriptValue callback = QScriptValue());
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// MODULE related methods
/**jsdoc
* @function Script.require
* @param {string} module
*/
Q_INVOKABLE QScriptValue require(const QString& moduleId);
/**jsdoc
* @function Script.resetModuleCache
* @param {boolean} [deleteScriptCache=false]
*/
Q_INVOKABLE void resetModuleCache(bool deleteScriptCache = false);
QScriptValue currentModule();
bool registerModuleWithParent(const QScriptValue& module, const QScriptValue& parent);
@ -179,34 +329,168 @@ public:
QVariantMap fetchModuleSource(const QString& modulePath, const bool forceDownload = false);
QScriptValue instantiateModule(const QScriptValue& module, const QString& sourceCode);
/**jsdoc
* Call a function at a set interval.
* @function Script.setInterval
* @param {function} function - The function to call. Can be an in-line function or the name of a function.
* @param {number} interval - The interval at which to call the function, in ms.
* @returns {object} A handle to the interval timer. Can be used by {@link Script.clearInterval}.
* @example <caption>Print a message every second.</caption>
* Script.setInterval(function () {
* print("Timer fired");
* }, 1000);
*/
Q_INVOKABLE QObject* setInterval(const QScriptValue& function, int intervalMS);
/**jsdoc
* Call a function after a delay.
* @function Script.setTimeout
* @param {function} function - The function to call. Can be an in-line function or the name of a function.
* @param {number} timeout - The delay after which to call the function, in ms.
* @returns {object} A handle to the timeout timer. Can be used by {@link Script.clearTimeout}.
* @example <caption>Print a message after a second.</caption>
* Script.setTimeout(function () {
* print("Timer fired");
* }, 1000);
*/
Q_INVOKABLE QObject* setTimeout(const QScriptValue& function, int timeoutMS);
/**jsdoc
* Stop an interval timer set by {@link Script.setInterval|setInterval}.
* @function Script.clearInterval
* @param {object} timer - The interval timer to clear.
* @example <caption>Stop an interval timer.</caption>
* // Print a message every second.
* var timer = Script.setInterval(function () {
* print("Timer fired");
* }, 1000);
*
* // Stop the timer after 10 seconds.
* Script.setTimeout(function () {
* print("Stop timer");
* Script.clearInterval(timer);
* }, 10000);
*/
Q_INVOKABLE void clearInterval(QObject* timer) { stopTimer(reinterpret_cast<QTimer*>(timer)); }
/**jsdoc
* Clear a timeout timer set by {@link Script.setTimeout|setTimeout}.
* @function Script.clearTimeout
* @param {object} timer - The timeout timer to clear.
* @example <caption>Stop a timeout timer.</caption>
* // Print a message after two seconds.
* var timer = Script.setTimeout(function () {
* print("Timer fired");
* }, 2000);
*
* // Uncomment the following line to stop the timer from firing.
* //Script.clearTimeout(timer);
*/
Q_INVOKABLE void clearTimeout(QObject* timer) { stopTimer(reinterpret_cast<QTimer*>(timer)); }
/**jsdoc
* @function Script.print
* @param {string} message
*/
Q_INVOKABLE void print(const QString& message);
/**jsdoc
* Resolve a relative path to an absolute path.
* @function Script.resolvePath
* @param {string} path - The relative path to resolve.
* @returns {string} The absolute path.
*/
Q_INVOKABLE QUrl resolvePath(const QString& path) const;
/**jsdoc
* @function Script.resourcesPath
* @returns {string}
*/
Q_INVOKABLE QUrl resourcesPath() const;
/**jsdoc
* @function Script.beginProfileRange
* @param {string} label
*/
Q_INVOKABLE void beginProfileRange(const QString& label) const;
/**jsdoc
* @function Script.endProfileRange
* @param {string} label
*/
Q_INVOKABLE void endProfileRange(const QString& label) const;
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// Entity Script Related methods
/**jsdoc
* @function Script.isEntityScriptRunning
* @param {Uuid} entityID
* @returns {boolean}
*/
Q_INVOKABLE bool isEntityScriptRunning(const EntityItemID& entityID) {
return _entityScripts.contains(entityID) && _entityScripts[entityID].status == EntityScriptStatus::RUNNING;
}
QVariant cloneEntityScriptDetails(const EntityItemID& entityID);
QFuture<QVariant> getLocalEntityScriptDetails(const EntityItemID& entityID) override;
/**jsdoc
* @function Script.loadEntityScript
* @param {Uuid} entityID
* @param {string} script
* @param {boolean} forceRedownload
*/
Q_INVOKABLE void loadEntityScript(const EntityItemID& entityID, const QString& entityScript, bool forceRedownload);
/**jsdoc
* @function Script.unloadEntityScript
* @param {Uuid} entityID
* @param {boolean} [shouldRemoveFromMap=false]
*/
Q_INVOKABLE void unloadEntityScript(const EntityItemID& entityID, bool shouldRemoveFromMap = false); // will call unload method
/**jsdoc
* @function Script.unloadAllEntityScripts
*/
Q_INVOKABLE void unloadAllEntityScripts();
/**jsdoc
* @function Script.callEntityScriptMethod
* @param {Uuid} entityID
* @param {string} methodName
* @param {string[]} parameters
* @param {Uuid} [remoteCallerID=Uuid.NULL]
*/
Q_INVOKABLE void callEntityScriptMethod(const EntityItemID& entityID, const QString& methodName,
const QStringList& params = QStringList(),
const QUuid& remoteCallerID = QUuid()) override;
/**jsdoc
* @function Script.callEntityScriptMethod
* @param {Uuid} entityID
* @param {string} methodName
* @param {PointerEvent} event
*/
Q_INVOKABLE void callEntityScriptMethod(const EntityItemID& entityID, const QString& methodName, const PointerEvent& event);
/**jsdoc
* @function Script.callEntityScriptMethod
* @param {Uuid} entityID
* @param {string} methodName
* @param {Uuid} otherID
* @param {Collision} collision
*/
Q_INVOKABLE void callEntityScriptMethod(const EntityItemID& entityID, const QString& methodName, const EntityItemID& otherID, const Collision& collision);
/**jsdoc
* @function Script.requestGarbageCollection
*/
Q_INVOKABLE void requestGarbageCollection() { collectGarbage(); }
/**jsdoc
* @function Script.generateUUID
* @returns {Uuid}
*/
Q_INVOKABLE QUuid generateUUID() { return QUuid::createUuid(); }
bool isFinished() const { return _isFinished; } // used by Application and ScriptWidget
@ -239,33 +523,170 @@ public:
bool getEntityScriptDetails(const EntityItemID& entityID, EntityScriptDetails &details) const;
public slots:
/**jsdoc
* @function Script.callAnimationStateHandler
* @param {function} callback
* @param {object} parameters
* @param {string[]} names
* @param {boolean} useNames
* @param {object} resultHandler
*/
void callAnimationStateHandler(QScriptValue callback, AnimVariantMap parameters, QStringList names, bool useNames, AnimVariantResultHandler resultHandler);
/**jsdoc
* @function Script.updateMemoryCost
* @param {number} deltaSize
*/
void updateMemoryCost(const qint64&);
signals:
/**jsdoc
* @function Script.scriptLoaded
* @param {string} filename
* @returns {Signal}
*/
void scriptLoaded(const QString& scriptFilename);
/**jsdoc
* @function Script.errorLoadingScript
* @param {string} filename
* @returns {Signal}
*/
void errorLoadingScript(const QString& scriptFilename);
/**jsdoc
* Triggered regularly at a system-determined frequency.
* @function Script.update
* @param {number} deltaTime - The time since the last update, in s.
* @returns {Signal}
*/
void update(float deltaTime);
/**jsdoc
* Triggered when the script is ending.
* @function Script.scriptEnding
* @returns {Signal}
* @example <caption>Connect to the <code>scriptEnding</code> signal.</caption>
* print("Script started");
*
* Script.scriptEnding.connect(function () {
* print("Script ending");
* });
*
* Script.setTimeout(function () {
* print("Stopping script");
* Script.stop();
* }, 1000);
*/
void scriptEnding();
/**jsdoc
* @function Script.finished
* @param {string} filename
* @param {object} engine
* @returns {Signal}
*/
void finished(const QString& fileNameString, ScriptEnginePointer);
/**jsdoc
* @function Script.cleanupMenuItem
* @param {string} menuItem
* @returns {Signal}
*/
void cleanupMenuItem(const QString& menuItemString);
/**jsdoc
* @function Script.printedMessage
* @param {string} message
* @param {string} scriptName
* @returns {Signal}
*/
void printedMessage(const QString& message, const QString& scriptName);
/**jsdoc
* @function Script.errorMessage
* @param {string} message
* @param {string} scriptName
* @returns {Signal}
*/
void errorMessage(const QString& message, const QString& scriptName);
/**jsdoc
* @function Script.warningMessage
* @param {string} message
* @param {string} scriptName
* @returns {Signal}
*/
void warningMessage(const QString& message, const QString& scriptName);
/**jsdoc
* @function Script.infoMessage
* @param {string} message
* @param {string} scriptName
* @returns {Signal}
*/
void infoMessage(const QString& message, const QString& scriptName);
/**jsdoc
* @function Script.runningStateChanged
* @returns {Signal}
*/
void runningStateChanged();
/**jsdoc
* @function Script.clearDebugWindow
* @returns {Signal}
*/
void clearDebugWindow();
/**jsdoc
* @function Script.loadScript
* @param {string} scriptName
* @param {boolean} isUserLoaded
* @returns {Signal}
*/
void loadScript(const QString& scriptName, bool isUserLoaded);
/**jsdoc
* @function Script.reloadScript
* @param {string} scriptName
* @param {boolean} isUserLoaded
* @returns {Signal}
*/
void reloadScript(const QString& scriptName, bool isUserLoaded);
/**jsdoc
* @function Script.doneRunning
* @returns {Signal}
*/
void doneRunning();
/**jsdoc
* @function Script.entityScriptDetailsUpdated
* @returns {Signal}
*/
// Emitted when an entity script is added or removed, or when the status of an entity
// script is updated (goes from RUNNING to ERROR_RUNNING_SCRIPT, for example)
void entityScriptDetailsUpdated();
protected:
void init();
/**jsdoc
* @function Script.executeOnScriptThread
* @param {object} function
* @param {ConnectionType} [type=2]
*/
Q_INVOKABLE void executeOnScriptThread(std::function<void()> function, const Qt::ConnectionType& type = Qt::QueuedConnection );
/**jsdoc
* @function Script._requireResolve
* @param {string} module
* @param {string} [relativeTo=""]
* @returns {string}
*/
// note: this is not meant to be called directly, but just to have QMetaObject take care of wiring it up in general;
// then inside of init() we just have to do "Script.require.resolve = Script._requireResolve;"
Q_INVOKABLE QString _requireResolve(const QString& moduleId, const QString& relativeTo = QString());
@ -285,6 +706,16 @@ protected:
QHash<EntityItemID, RegisteredEventHandlers> _registeredHandlers;
void forwardHandlerCall(const EntityItemID& entityID, const QString& eventName, QScriptValueList eventHanderArgs);
/**jsdoc
* @function Script.entityScriptContentAvailable
* @param {Uuid} entityID
* @param {string} scriptOrURL
* @param {string} contents
* @param {boolean} isURL
* @param {boolean} success
* @param {string} status
*/
Q_INVOKABLE void entityScriptContentAvailable(const EntityItemID& entityID, const QString& scriptOrURL, const QString& contents, bool isURL, bool success, const QString& status);
EntityItemID currentEntityIdentifier {}; // Contains the defining entity script entity id during execution, if any. Empty for interface script execution.