History

shifting classes around and adding static initializers to resolve dependencies on scripting-engine (and drop dependencies from scripting-engine)

Heather Anderson committed 5 years ago

Commit 665ea521 parent 1f4f45853 files · +457 −404Browse files

Showing the changes to libraries/script-engine/src/ScriptManager.cpp (1 of 53 files). Show all

Unified · Split

libraries/script-engine/src/ScriptManager.cpp+57−274
@@ -24,55 +24,36 @@ · 23 unmodified lines
24#include <QtCore/QFuture>24#include <QtCore/QFuture>
25#include <QtConcurrent/QtConcurrentRun>25#include <QtConcurrent/QtConcurrentRun>
26 26
27#include <QtWidgets/QMainWindow>
28#include <QtWidgets/QApplication>
29#include <QtWidgets/QMenuBar>
30#include <QtWidgets/QMenu>
31
32#include <QtNetwork/QNetworkRequest>
33#include <QtNetwork/QNetworkReply>
34
35#include <shared/LocalFileAccessGate.h>27#include <shared/LocalFileAccessGate.h>
36#include <shared/QtHelpers.h>
37#include <shared/AbstractLoggerInterface.h>28#include <shared/AbstractLoggerInterface.h>
38#include <AudioConstants.h>
39#include <AudioEffectOptions.h>
40#include <AvatarData.h>
41#include <DebugDraw.h>29#include <DebugDraw.h>
42#include <EntityScriptingInterface.h>
43#include <MessagesClient.h>30#include <MessagesClient.h>
44#include <NetworkAccessManager.h>31#include <OctreeConstants.h>
45#include <PathUtils.h>32#include <PathUtils.h>
33#include <PortableHighResolutionClock.h>
34#include <ResourceCache.h>
35#include <ResourceManager.h>
46#include <ResourceScriptingInterface.h>36#include <ResourceScriptingInterface.h>
47#include <UserActivityLoggerScriptingInterface.h>37#include <UserActivityLoggerScriptingInterface.h>
48#include <NodeList.h>38#include <NodeList.h>
49#include <ScriptAvatarData.h>
50#include <udt/PacketHeaders.h>
51#include <UUID.h>
52
53#include <controllers/ScriptingInterface.h>
54#include <AnimationObject.h>
55 39
56#include "AudioScriptingInterface.h"
57#include "AssetScriptingInterface.h"40#include "AssetScriptingInterface.h"
58#include "BatchLoader.h"41#include "BatchLoader.h"
59#include "EventTypes.h"42#include "EventTypes.h"
60#include "FileScriptingInterface.h" // unzip project43#include "FileScriptingInterface.h" // unzip project
61#include "MenuItemProperties.h"44#include "MenuItemProperties.h"
62#include "ScriptAudioInjector.h"
63#include "ScriptAvatarData.h"
64#include "ScriptCache.h"45#include "ScriptCache.h"
65#include "ScriptContext.h"46#include "ScriptContext.h"
66#include "ScriptEngineCast.h"
67#include "ScriptEngineLogging.h"
68#include "XMLHttpRequestClass.h"47#include "XMLHttpRequestClass.h"
69#include "WebSocketClass.h"48#include "WebSocketClass.h"
70#include "RecordingScriptingInterface.h"49#include "ScriptEngine.h"
50#include "ScriptEngineCast.h"
51#include "ScriptEngineLogging.h"
71#include "ScriptEngines.h"52#include "ScriptEngines.h"
72#include "StackTestScriptingInterface.h"53#include "StackTestScriptingInterface.h"
73#include "ModelScriptingInterface.h"
74#include "ScriptValue.h"54#include "ScriptValue.h"
75#include "ScriptValueIterator.h"55#include "ScriptValueIterator.h"
56#include "ScriptValueUtils.h"
76 57
77#include <Profile.h>58#include <Profile.h>
78 59
@@ -94,8 +75,6 @@ const QString ScriptManager::SCRIPT_BACKTRACE_SEP{ "\n " }; · 15 unmodified lines
94static const int MAX_MODULE_ID_LENGTH { 4096 };75static const int MAX_MODULE_ID_LENGTH { 4096 };
95static const int MAX_DEBUG_VALUE_LENGTH { 80 };76static const int MAX_DEBUG_VALUE_LENGTH { 80 };
96 77
97static const ScriptEngine::QObjectWrapOptions DEFAULT_QOBJECT_WRAP_OPTIONS =
98 ScriptEngine::ExcludeDeleteLater | ScriptEngine::ExcludeChildObjects;
99static const ScriptValue::PropertyFlags READONLY_PROP_FLAGS{ ScriptValue::ReadOnly | ScriptValue::Undeletable };78static const ScriptValue::PropertyFlags READONLY_PROP_FLAGS{ ScriptValue::ReadOnly | ScriptValue::Undeletable };
100static const ScriptValue::PropertyFlags READONLY_HIDDEN_PROP_FLAGS{ READONLY_PROP_FLAGS | ScriptValue::SkipInEnumeration };79static const ScriptValue::PropertyFlags READONLY_HIDDEN_PROP_FLAGS{ READONLY_PROP_FLAGS | ScriptValue::SkipInEnumeration };
101 80
@@ -108,6 +87,26 @@ int scriptManagerPointerMetaID = qRegisterMetaType<ScriptManagerPointer>(); · 6 unmodified lines
108 87
109Q_DECLARE_METATYPE(ExternalResource::Bucket);88Q_DECLARE_METATYPE(ExternalResource::Bucket);
110 89
90// --- Static script initialization registry
91
92static ScriptManager::StaticInitializerNode* rootInitializer = nullptr;
93
94void ScriptManager::registerNewStaticInitializer(StaticInitializerNode* dest) {
95 // this function is assumed to be called on LoadLibrary, where we are explicitly operating in single-threaded mode
96 // Therefore there is no mutex or threadsafety here and the structure is assumed not to change after loading
97 dest->prev = rootInitializer;
98 rootInitializer = dest;
99}
100static void runStaticInitializers(ScriptManager* manager) {
101 ScriptManager::StaticInitializerNode* here = rootInitializer;
102 while (here != nullptr) {
103 (*here->init)(manager);
104 here = here->prev;
105 }
106}
107
108// ---
109
111static ScriptValuePointer debugPrint(ScriptContext* context, ScriptEngine* engine) {110static ScriptValuePointer debugPrint(ScriptContext* context, ScriptEngine* engine) {
112 // assemble the message by concatenating our arguments111 // assemble the message by concatenating our arguments
113 QString message = "";112 QString message = "";
@@ -172,17 +171,6 @@ static ScriptValuePointer debugPrint(ScriptContext* context, ScriptEngine* engin · 58 unmodified lines
172 return ScriptValuePointer();171 return ScriptValuePointer();
173}172}
174 173
175Q_DECLARE_METATYPE(controller::InputController*)
176//static int inputControllerPointerId = qRegisterMetaType<controller::InputController*>();
177
178ScriptValuePointer inputControllerToScriptValue(ScriptEngine* engine, controller::InputController* const& in) {
179 return engine->newQObject(in, ScriptEngine::QtOwnership, DEFAULT_QOBJECT_WRAP_OPTIONS);
180}
181
182void inputControllerFromScriptValue(const ScriptValuePointer& object, controller::InputController*& out) {
183 out = qobject_cast<controller::InputController*>(object->toQObject());
184}
185
186// FIXME Come up with a way to properly encode entity IDs in filename174// FIXME Come up with a way to properly encode entity IDs in filename
187// The purpose of the following two function is to embed entity ids into entity script filenames175// The purpose of the following two function is to embed entity ids into entity script filenames
188// so that they show up in stacktraces176// so that they show up in stacktraces
@@ -522,28 +510,6 @@ void ScriptManager::clearDebugLogWindow() { · 333 unmodified lines
522 emit clearDebugWindow();510 emit clearDebugWindow();
523}511}
524 512
525// Even though we never pass AnimVariantMap directly to and from javascript, the queued invokeMethod of
526// callAnimationStateHandler requires that the type be registered.
527// These two are meaningful, if we ever do want to use them...
528static ScriptValuePointer animVarMapToScriptValue(ScriptEngine* engine, const AnimVariantMap& parameters) {
529 QStringList unused;
530 return parameters.animVariantMapToScriptValue(engine, unused, false);
531}
532static void animVarMapFromScriptValue(const ScriptValuePointer& value, AnimVariantMap& parameters) {
533 parameters.animVariantMapFromScriptValue(value);
534}
535// ... while these two are not. But none of the four are ever used.
536static ScriptValuePointer resultHandlerToScriptValue(ScriptEngine* engine,
537 const AnimVariantResultHandler& resultHandler) {
538 qCCritical(scriptengine) << "Attempt to marshall result handler to javascript";
539 assert(false);
540 return ScriptValuePointer();
541}
542static void resultHandlerFromScriptValue(const ScriptValuePointer& value, AnimVariantResultHandler& resultHandler) {
543 qCCritical(scriptengine) << "Attempt to marshall result handler from javascript";
544 assert(false);
545}
546
547// Templated qScriptRegisterMetaType fails to compile with raw pointers513// Templated qScriptRegisterMetaType fails to compile with raw pointers
548using ScriptableResourceRawPtr = ScriptableResource*;514using ScriptableResourceRawPtr = ScriptableResource*;
549 515
@@ -562,13 +528,10 @@ static ScriptValuePointer scriptableResourceToScriptValue(ScriptEngine* engine, · 12 unmodified lines
562 auto manager = engine->manager();528 auto manager = engine->manager();
563 if (data && manager && !resource->isInScript()) {529 if (data && manager && !resource->isInScript()) {
564 resource->setInScript(true);530 resource->setInScript(true);
565 QObject::connect(data.data(), SIGNAL(updateSize(qint64)), manager, SLOT(updateMemoryCost(qint64)));531 QObject::connect(data.data(), &Resource::updateSize, manager, &ScriptManager::updateMemoryCost);
566 }532 }
567 533
568 auto object = engine->newQObject(534 auto object = engine->newQObject(const_cast<ScriptableResourceRawPtr>(resource), ScriptEngine::ScriptOwnership);
569 const_cast<ScriptableResourceRawPtr>(resource),
570 ScriptEngine::ScriptOwnership,
571 DEFAULT_QOBJECT_WRAP_OPTIONS);
572 return object;535 return object;
573}536}
574 537
@@ -602,22 +565,12 @@ static ScriptValuePointer createScriptableResourcePrototype(ScriptManagerPointer · 27 unmodified lines
602 }565 }
603 566
604 auto prototypeState = engine->newQObject(state, ScriptEngine::QtOwnership,567 auto prototypeState = engine->newQObject(state, ScriptEngine::QtOwnership,
605 ScriptEngine::ExcludeDeleteLater | ScriptEngine::ExcludeSlots | ScriptEngine::ExcludeSuperClassMethods);568 ScriptEngine::ExcludeSlots | ScriptEngine::ExcludeSuperClassMethods);
606 prototype->setProperty("State", prototypeState);569 prototype->setProperty("State", prototypeState);
607 570
608 return prototype;571 return prototype;
609}572}
610 573
611ScriptValuePointer avatarDataToScriptValue(ScriptEngine* engine, ScriptAvatarData* const& in) {
612 return engine->newQObject(in, ScriptEngine::ScriptOwnership, DEFAULT_QOBJECT_WRAP_OPTIONS);
613}
614
615void avatarDataFromScriptValue(const ScriptValuePointer& object, ScriptAvatarData*& out) {
616 // This is not implemented because there are no slots/properties that take an AvatarSharedPointer from a script
617 assert(false);
618 out = nullptr;
619}
620
621ScriptValuePointer externalResourceBucketToScriptValue(ScriptEngine* engine, ExternalResource::Bucket const& in) {574ScriptValuePointer externalResourceBucketToScriptValue(ScriptEngine* engine, ExternalResource::Bucket const& in) {
622 return engine->newValue((int)in);575 return engine->newValue((int)in);
623}576}
@@ -666,27 +619,15 @@ void ScriptManager::init() { · 42 unmodified lines
666 }619 }
667 620
668 _isInitialized = true;621 _isInitialized = true;
669 auto scriptEngine = _engine.data();622 runStaticInitializers(this);
670 623
671 auto entityScriptingInterface = DependencyManager::get<EntityScriptingInterface>();624 auto scriptEngine = _engine.data();
672 entityScriptingInterface->init();
673 625
674 // register various meta-types626 // register various meta-types
675 registerMetaTypes(scriptEngine);
676 registerMIDIMetaTypes(scriptEngine);627 registerMIDIMetaTypes(scriptEngine);
677 registerEventTypes(scriptEngine);628 registerEventTypes(scriptEngine);
678 registerMenuItemProperties(scriptEngine);629 registerMenuItemProperties(scriptEngine);
679 registerAnimationTypes(scriptEngine);630
680 registerAvatarTypes(scriptEngine);
681 registerAudioMetaTypes(scriptEngine);
682
683 scriptRegisterMetaType(scriptEngine, EntityPropertyFlagsToScriptValue, EntityPropertyFlagsFromScriptValue);
684 scriptRegisterMetaType(scriptEngine, EntityItemPropertiesToScriptValue, EntityItemPropertiesFromScriptValueHonorReadOnly);
685 scriptRegisterMetaType(scriptEngine, EntityPropertyInfoToScriptValue, EntityPropertyInfoFromScriptValue);
686 scriptRegisterMetaType(scriptEngine, EntityItemIDtoScriptValue, EntityItemIDfromScriptValue);
687 scriptRegisterMetaType(scriptEngine, RayToEntityIntersectionResultToScriptValue, RayToEntityIntersectionResultFromScriptValue);
688 scriptRegisterMetaType(scriptEngine, RayToAvatarIntersectionResultToScriptValue, RayToAvatarIntersectionResultFromScriptValue);
689 scriptRegisterMetaType(scriptEngine, AvatarEntityMapToScriptValue, AvatarEntityMapFromScriptValue);
690 scriptRegisterSequenceMetaType<QVector<QUuid>>(scriptEngine);631 scriptRegisterSequenceMetaType<QVector<QUuid>>(scriptEngine);
691 scriptRegisterSequenceMetaType<QVector<EntityItemID>>(scriptEngine);632 scriptRegisterSequenceMetaType<QVector<EntityItemID>>(scriptEngine);
692 633
@@ -709,12 +650,6 @@ void ScriptManager::init() { · 16 unmodified lines
709 */650 */
710 scriptEngine->globalObject()->setProperty("print", scriptEngine->newFunction(debugPrint));651 scriptEngine->globalObject()->setProperty("print", scriptEngine->newFunction(debugPrint));
711 652
712 ScriptValuePointer audioEffectOptionsConstructorValue = scriptEngine->newFunction(AudioEffectOptions::constructor);
713 scriptEngine->globalObject()->setProperty("AudioEffectOptions", audioEffectOptionsConstructorValue);
714
715 scriptRegisterMetaType(scriptEngine, injectorToScriptValue, injectorFromScriptValue);
716 scriptRegisterMetaType(scriptEngine, inputControllerToScriptValue, inputControllerFromScriptValue);
717 scriptRegisterMetaType(scriptEngine, avatarDataToScriptValue, avatarDataFromScriptValue);
718 scriptRegisterMetaType(scriptEngine, animationDetailsToScriptValue, animationDetailsFromScriptValue);653 scriptRegisterMetaType(scriptEngine, animationDetailsToScriptValue, animationDetailsFromScriptValue);
719 scriptRegisterMetaType(scriptEngine, webSocketToScriptValue, webSocketFromScriptValue);654 scriptRegisterMetaType(scriptEngine, webSocketToScriptValue, webSocketFromScriptValue);
720 scriptRegisterMetaType(scriptEngine, qWSCloseCodeToScriptValue, qWSCloseCodeFromScriptValue);655 scriptRegisterMetaType(scriptEngine, qWSCloseCodeToScriptValue, qWSCloseCodeFromScriptValue);
@@ -737,13 +672,8 @@ void ScriptManager::init() { · 16 unmodified lines
737 scriptRegisterMetaType(scriptEngine, externalResourceBucketToScriptValue, externalResourceBucketFromScriptValue);672 scriptRegisterMetaType(scriptEngine, externalResourceBucketToScriptValue, externalResourceBucketFromScriptValue);
738 scriptEngine->registerEnum("Script.ExternalPaths", QMetaEnum::fromType<ExternalResource::Bucket>());673 scriptEngine->registerEnum("Script.ExternalPaths", QMetaEnum::fromType<ExternalResource::Bucket>());
739 674
740 scriptEngine->registerGlobalObject("Audio", DependencyManager::get<AudioScriptingInterface>().data());
741
742 scriptEngine->registerGlobalObject("Midi", DependencyManager::get<Midi>().data());675 scriptEngine->registerGlobalObject("Midi", DependencyManager::get<Midi>().data());
743 676
744 scriptEngine->registerGlobalObject("Entities", entityScriptingInterface.data());
745 scriptEngine->registerFunction("Entities", "getMultipleEntityProperties",
746 EntityScriptingInterface::getMultipleEntityProperties);
747 scriptEngine->registerGlobalObject("Quat", &_quatLibrary);677 scriptEngine->registerGlobalObject("Quat", &_quatLibrary);
748 scriptEngine->registerGlobalObject("Vec3", &_vec3Library);678 scriptEngine->registerGlobalObject("Vec3", &_vec3Library);
749 scriptEngine->registerGlobalObject("Mat4", &_mat4Library);679 scriptEngine->registerGlobalObject("Mat4", &_mat4Library);
@@ -762,9 +692,6 @@ void ScriptManager::init() { · 12 unmodified lines
762 scriptEngine->registerFunction("console", "groupCollapsed", ConsoleScriptingInterface::groupCollapsed, 1);692 scriptEngine->registerFunction("console", "groupCollapsed", ConsoleScriptingInterface::groupCollapsed, 1);
763 scriptEngine->registerFunction("console", "groupEnd", ConsoleScriptingInterface::groupEnd, 0);693 scriptEngine->registerFunction("console", "groupEnd", ConsoleScriptingInterface::groupEnd, 0);
764 694
765 scriptRegisterMetaType(scriptEngine, animVarMapToScriptValue, animVarMapFromScriptValue);
766 scriptRegisterMetaType(scriptEngine, resultHandlerToScriptValue, resultHandlerFromScriptValue);
767
768 // Scriptable cache access695 // Scriptable cache access
769 auto resourcePrototype = createScriptableResourcePrototype(qSharedPointerCast<ScriptManager>(sharedFromThis()));696 auto resourcePrototype = createScriptableResourcePrototype(qSharedPointerCast<ScriptManager>(sharedFromThis()));
770 scriptEngine->globalObject()->setProperty("Resource", resourcePrototype);697 scriptEngine->globalObject()->setProperty("Resource", resourcePrototype);
@@ -779,7 +706,6 @@ void ScriptManager::init() { · 8 unmodified lines
779 706
780 scriptEngine->registerGlobalObject("DebugDraw", &DebugDraw::getInstance());707 scriptEngine->registerGlobalObject("DebugDraw", &DebugDraw::getInstance());
781 708
782 scriptEngine->registerGlobalObject("Model", new ModelScriptingInterface(this));
783 scriptRegisterMetaType(scriptEngine, meshToScriptValue, meshFromScriptValue);709 scriptRegisterMetaType(scriptEngine, meshToScriptValue, meshFromScriptValue);
784 scriptRegisterMetaType(scriptEngine, meshesToScriptValue, meshesFromScriptValue);710 scriptRegisterMetaType(scriptEngine, meshesToScriptValue, meshesFromScriptValue);
785 711
@@ -825,6 +751,22 @@ void ScriptManager::removeEventHandler(const EntityItemID& entityID, const QStri · 39 unmodified lines
825 }751 }
826 }752 }
827}753}
754
755// Unregister all event handlers for the specified entityID (i.e. the entity is being removed)
756void ScriptManager::removeAllEventHandlers(const EntityItemID& entityID) {
757 if (QThread::currentThread() != thread()) {
758#ifdef THREAD_DEBUGGING
759 qCDebug(scriptengine) << "*** WARNING *** ScriptManager::removeAllEventHandlers() called on wrong thread [" << QThread::currentThread() << ", correct thread is " << thread() << " ], ignoring "
760 "entityID:" << entityID;
761#endif
762 return;
763 }
764
765 if (_registeredHandlers.contains(entityID)) {
766 _registeredHandlers.remove(entityID);
767 }
768}
769
828// Register the handler.770// Register the handler.
829void ScriptManager::addEventHandler(const EntityItemID& entityID, const QString& eventName, ScriptValuePointer handler) {771void ScriptManager::addEventHandler(const EntityItemID& entityID, const QString& eventName, ScriptValuePointer handler) {
830 if (QThread::currentThread() != thread()) {772 if (QThread::currentThread() != thread()) {
@@ -843,117 +785,9 @@ void ScriptManager::addEventHandler(const EntityItemID& entityID, const QString& · 12 unmodified lines
843 qCDebug(scriptengine) << "ScriptManager::addEventHandler() called on thread [" << QThread::currentThread() << "] entityID:" << entityID << " eventName : " << eventName;785 qCDebug(scriptengine) << "ScriptManager::addEventHandler() called on thread [" << QThread::currentThread() << "] entityID:" << entityID << " eventName : " << eventName;
844#endif786#endif
845 787
846 if (_registeredHandlers.count() == 0) { // First time any per-entity handler has been added in this script...788 if (_registeredHandlers.count() == 0) {
847 // Connect up ALL the handlers to the global entities object's signals.789 // First time any per-entity handler has been added in this script...
848 // (We could go signal by signal, or even handler by handler, but I don't think the efficiency is worth the complexity.)790 emit attachDefaultEventHandlers();
849 auto entities = DependencyManager::get<EntityScriptingInterface>();
850 // Bug? These handlers are deleted when entityID is deleted, which is nice.
851 // But if they are created by an entity script on a different entity, should they also be deleted when the entity script unloads?
852 // E.g., suppose a bow has an entity script that causes arrows to be created with a potential lifetime greater than the bow,
853 // and that the entity script adds (e.g., collision) handlers to the arrows. Should those handlers fire if the bow is unloaded?
854 // Also, what about when the entity script is REloaded?
855 // For now, we are leaving them around. Changing that would require some non-trivial digging around to find the
856 // handlers that were added while a given currentEntityIdentifier was in place. I don't think this is dangerous. Just perhaps unexpected. -HRS
857 connect(entities.data(), &EntityScriptingInterface::deletingEntity, this, [this](const EntityItemID& entityID) {
858 _registeredHandlers.remove(entityID);
859 });
860
861 // Two common cases of event handler, differing only in argument signature.
862
863 /*@jsdoc
864 * Called when an entity event occurs on an entity as registered with {@link Script.addEventHandler}.
865 * @callback Script~entityEventCallback
866 * @param {Uuid} entityID - The ID of the entity the event has occured on.
867 */
868 using SingleEntityHandler = std::function<void(const EntityItemID&)>;
869 auto makeSingleEntityHandler = [this](QString eventName) -> SingleEntityHandler {
870 return [this, eventName](const EntityItemID& entityItemID) {
871 forwardHandlerCall(entityItemID, eventName, { entityItemID.toScriptValue(_engine.data()) });
872 };
873 };
874
875 /*@jsdoc
876 * Called when a pointer event occurs on an entity as registered with {@link Script.addEventHandler}.
877 * @callback Script~pointerEventCallback
878 * @param {Uuid} entityID - The ID of the entity the event has occurred on.
879 * @param {PointerEvent} pointerEvent - Details of the event.
880 */
881 using PointerHandler = std::function<void(const EntityItemID&, const PointerEvent&)>;
882 auto makePointerHandler = [this](QString eventName) -> PointerHandler {
883 return [this, eventName](const EntityItemID& entityItemID, const PointerEvent& event) {
884 if (!EntityTree::areEntityClicksCaptured()) {
885 forwardHandlerCall(entityItemID, eventName, { entityItemID.toScriptValue(_engine.data()), event.toScriptValue(_engine.data()) });
886 }
887 };
888 };
889
890 /*@jsdoc
891 * Called when a collision event occurs on an entity as registered with {@link Script.addEventHandler}.
892 * @callback Script~collisionEventCallback
893 * @param {Uuid} entityA - The ID of one entity in the collision.
894 * @param {Uuid} entityB - The ID of the other entity in the collision.
895 * @param {Collision} collisionEvent - Details of the collision.
896 */
897 using CollisionHandler = std::function<void(const EntityItemID&, const EntityItemID&, const Collision&)>;
898 auto makeCollisionHandler = [this](QString eventName) -> CollisionHandler {
899 return [this, eventName](const EntityItemID& idA, const EntityItemID& idB, const Collision& collision) {
900 forwardHandlerCall(idA, eventName, { idA.toScriptValue(_engine.data()), idB.toScriptValue(_engine.data()),
901 collisionToScriptValue(_engine.data(), collision) });
902 };
903 };
904
905 /*@jsdoc
906 * <p>The name of an entity event. When the entity event occurs, any function that has been registered for that event
907 * via {@link Script.addEventHandler} is called with parameters per the entity event.</p>
908 * <table>
909 * <thead>
910 * <tr><th>Event Name</th><th>Callback Type</th><th>Entity Event</th></tr>
911 * </thead>
912 * <tbody>
913 * <tr><td><code>"enterEntity"</code></td><td>{@link Script~entityEventCallback|entityEventCallback}</td>
914 * <td>{@link Entities.enterEntity}</td></tr>
915 * <tr><td><code>"leaveEntity"</code></td><td>{@link Script~entityEventCallback|entityEventCallback}</td>
916 * <td>{@link Entities.leaveEntity}</td></tr>
917 * <tr><td><code>"mousePressOnEntity"</code></td><td>{@link Script~pointerEventCallback|pointerEventCallback}</td>
918 * <td>{@link Entities.mousePressOnEntity}</td></tr>
919 * <tr><td><code>"mouseMoveOnEntity"</code></td><td>{@link Script~pointerEventCallback|pointerEventCallback}</td>
920 * <td>{@link Entities.mouseMoveOnEntity}</td></tr>
921 * <tr><td><code>"mouseReleaseOnEntity"</code></td><td>{@link Script~pointerEventCallback|pointerEventCallback}</td>
922 * <td>{@link Entities.mouseReleaseOnEntity}</td></tr>
923 * <tr><td><code>"clickDownOnEntity"</code></td><td>{@link Script~pointerEventCallback|pointerEventCallback}</td>
924 * <td>{@link Entities.clickDownOnEntity}</td></tr>
925 * <tr><td><code>"holdingClickOnEntity"</code></td><td>{@link Script~pointerEventCallback|pointerEventCallback}</td>
926 * <td>{@link Entities.holdingClickOnEntity}</td></tr>
927 * <tr><td><code>"clickReleaseOnEntity"</code></td><td>{@link Script~pointerEventCallback|pointerEventCallback}</td>
928 * <td>{@link Entities.clickReleaseOnEntity}</td></tr>
929 * <tr><td><code>"hoverEnterEntity"</code></td><td>{@link Script~pointerEventCallback|pointerEventCallback}</td>
930 * <td>{@link Entities.hoverEnterEntity}</td></tr>
931 * <tr><td><code>"hoverOverEntity"</code></td><td>{@link Script~pointerEventCallback|pointerEventCallback}</td>
932 * <td>{@link Entities.hoverOverEntity}</td></tr>
933 * <tr><td><code>"hoverLeaveEntity"</code></td><td>{@link Script~pointerEventCallback|pointerEventCallback}</td>
934 * <td>{@link Entities.hoverLeaveEntity}</td></tr>
935 * <tr><td><code>"collisionWithEntity"</code><td>{@link Script~collisionEventCallback|collisionEventCallback}</td>
936 * </td><td>{@link Entities.collisionWithEntity}</td></tr>
937 * </tbody>
938 * </table>
939 * @typedef {string} Script.EntityEvent
940 */
941 connect(entities.data(), &EntityScriptingInterface::enterEntity, this, makeSingleEntityHandler("enterEntity"));
942 connect(entities.data(), &EntityScriptingInterface::leaveEntity, this, makeSingleEntityHandler("leaveEntity"));
943
944 connect(entities.data(), &EntityScriptingInterface::mousePressOnEntity, this, makePointerHandler("mousePressOnEntity"));
945 connect(entities.data(), &EntityScriptingInterface::mouseMoveOnEntity, this, makePointerHandler("mouseMoveOnEntity"));
946 connect(entities.data(), &EntityScriptingInterface::mouseReleaseOnEntity, this, makePointerHandler("mouseReleaseOnEntity"));
947
948 connect(entities.data(), &EntityScriptingInterface::clickDownOnEntity, this, makePointerHandler("clickDownOnEntity"));
949 connect(entities.data(), &EntityScriptingInterface::holdingClickOnEntity, this, makePointerHandler("holdingClickOnEntity"));
950 connect(entities.data(), &EntityScriptingInterface::clickReleaseOnEntity, this, makePointerHandler("clickReleaseOnEntity"));
951
952 connect(entities.data(), &EntityScriptingInterface::hoverEnterEntity, this, makePointerHandler("hoverEnterEntity"));
953 connect(entities.data(), &EntityScriptingInterface::hoverOverEntity, this, makePointerHandler("hoverOverEntity"));
954 connect(entities.data(), &EntityScriptingInterface::hoverLeaveEntity, this, makePointerHandler("hoverLeaveEntity"));
955
956 connect(entities.data(), &EntityScriptingInterface::collisionWithEntity, this, makeCollisionHandler("collisionWithEntity"));
957 }791 }
958 if (!_registeredHandlers.contains(entityID)) {792 if (!_registeredHandlers.contains(entityID)) {
959 _registeredHandlers[entityID] = RegisteredEventHandlers();793 _registeredHandlers[entityID] = RegisteredEventHandlers();
@@ -1008,9 +842,6 @@ void ScriptManager::run() { · 48 unmodified lines
1008 clock::time_point startTime = clock::now();842 clock::time_point startTime = clock::now();
1009 int thisFrame = 0;843 int thisFrame = 0;
1010 844
1011 auto nodeList = DependencyManager::get<NodeList>();
1012 auto entityScriptingInterface = DependencyManager::get<EntityScriptingInterface>();
1013
1014 _lastUpdate = usecTimestampNow();845 _lastUpdate = usecTimestampNow();
1015 846
1016 std::chrono::microseconds totalUpdates(0);847 std::chrono::microseconds totalUpdates(0);
@@ -1050,7 +881,7 @@ void ScriptManager::run() { · 33 unmodified lines
1050 QEventLoop loop;881 QEventLoop loop;
1051 QTimer timer;882 QTimer timer;
1052 timer.setSingleShot(true);883 timer.setSingleShot(true);
1053 connect(&timer, SIGNAL(timeout()), &loop, SLOT(quit()));884 connect(&timer, &QTimer::timeout, &loop, &QEventLoop::quit);
1054 timer.start(sleepFor.count());885 timer.start(sleepFor.count());
1055 loop.exec();886 loop.exec();
1056 } else {887 } else {
@@ -1092,14 +923,8 @@ void ScriptManager::run() { · 35 unmodified lines
1092 break;923 break;
1093 }924 }
1094 925
1095 if (!_isFinished && entityScriptingInterface->getEntityPacketSender()->serversExist()) {926 if (!_isFinished) {
1096 // release the queue of edit entity messages.927 emit releaseEntityPacketSenderMessages(false);
1097 entityScriptingInterface->getEntityPacketSender()->releaseQueuedMessages();
1098
1099 // since we're in non-threaded mode, call process so that the packets are sent
1100 if (!entityScriptingInterface->getEntityPacketSender()->isThreaded()) {
1101 entityScriptingInterface->getEntityPacketSender()->process();
1102 }
1103 }928 }
1104 929
1105 qint64 now = usecTimestampNow();930 qint64 now = usecTimestampNow();
@@ -1133,21 +958,7 @@ void ScriptManager::run() { · 27 unmodified lines
1133 stopAllTimers(); // make sure all our timers are stopped if the script is ending958 stopAllTimers(); // make sure all our timers are stopped if the script is ending
1134 emit scriptEnding();959 emit scriptEnding();
1135 960
1136 if (entityScriptingInterface->getEntityPacketSender()->serversExist()) {961 emit releaseEntityPacketSenderMessages(true);
1137 // release the queue of edit entity messages.
1138 entityScriptingInterface->getEntityPacketSender()->releaseQueuedMessages();
1139
1140 // since we're in non-threaded mode, call process so that the packets are sent
1141 if (!entityScriptingInterface->getEntityPacketSender()->isThreaded()) {
1142 // wait here till the edit packet sender is completely done sending
1143 while (entityScriptingInterface->getEntityPacketSender()->hasPacketsToSend()) {
1144 entityScriptingInterface->getEntityPacketSender()->process();
1145 QCoreApplication::processEvents();
1146 }
1147 } else {
1148 // FIXME - do we need to have a similar "wait here" loop for non-threaded packet senders?
1149 }
1150 }
1151 962
1152 emit finished(_fileNameString, qSharedPointerCast<ScriptManager>(sharedFromThis()));963 emit finished(_fileNameString, qSharedPointerCast<ScriptManager>(sharedFromThis()));
1153 964
@@ -1203,34 +1014,6 @@ void ScriptManager::stop(bool marshal) { · 49 unmodified lines
1203 }1014 }
1204}1015}
1205 1016
1206// Other threads can invoke this through invokeMethod, which causes the callback to be asynchronously executed in this script's thread.
1207void ScriptManager::callAnimationStateHandler(ScriptValuePointer callback, AnimVariantMap parameters, QStringList names, bool useNames, AnimVariantResultHandler resultHandler) {
1208 if (QThread::currentThread() != thread()) {
1209#ifdef THREAD_DEBUGGING
1210 qCDebug(scriptengine) << "*** WARNING *** ScriptManager::callAnimationStateHandler() called on wrong thread [" << QThread::currentThread() << "], invoking on correct thread [" << thread() << "] name:" << name;
1211#endif
1212 QMetaObject::invokeMethod(this, "callAnimationStateHandler",
1213 Q_ARG(ScriptValuePointer, callback),
1214 Q_ARG(AnimVariantMap, parameters),
1215 Q_ARG(QStringList, names),
1216 Q_ARG(bool, useNames),
1217 Q_ARG(AnimVariantResultHandler, resultHandler));
1218 return;
1219 }
1220 ScriptValuePointer javascriptParameters = parameters.animVariantMapToScriptValue(_engine.get(), names, useNames);
1221 ScriptValueList callingArguments;
1222 callingArguments << javascriptParameters;
1223 assert(currentEntityIdentifier.isInvalidID()); // No animation state handlers from entity scripts.
1224 ScriptValuePointer result = callback->call(ScriptValuePointer(), callingArguments);
1225
1226 // validate result from callback function.
1227 if (result->isValid() && result->isObject()) {
1228 resultHandler(result);
1229 } else {
1230 qCWarning(scriptengine) << "ScriptManager::callAnimationStateHandler invalid return argument from callback, expected an object";
1231 }
1232}
1233
1234void ScriptManager::updateMemoryCost(const qint64& deltaSize) {1017void ScriptManager::updateMemoryCost(const qint64& deltaSize) {
1235 _engine->updateMemoryCost(deltaSize);1018 _engine->updateMemoryCost(deltaSize);
1236}1019}