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
2424 #include <QtCore/QFuture>
2525 #include <QtConcurrent/QtConcurrentRun>
2626
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−
3527 #include <shared/LocalFileAccessGate.h>
36−#include <shared/QtHelpers.h>
3728 #include <shared/AbstractLoggerInterface.h>
38−#include <AudioConstants.h>
39−#include <AudioEffectOptions.h>
40−#include <AvatarData.h>
4129 #include <DebugDraw.h>
42−#include <EntityScriptingInterface.h>
4330 #include <MessagesClient.h>
44−#include <NetworkAccessManager.h>
31+#include <OctreeConstants.h>
4532 #include <PathUtils.h>
33+#include <PortableHighResolutionClock.h>
34+#include <ResourceCache.h>
35+#include <ResourceManager.h>
4636 #include <ResourceScriptingInterface.h>
4737 #include <UserActivityLoggerScriptingInterface.h>
4838 #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>
5539
56−#include "AudioScriptingInterface.h"
5740 #include "AssetScriptingInterface.h"
5841 #include "BatchLoader.h"
5942 #include "EventTypes.h"
6043 #include "FileScriptingInterface.h" // unzip project
6144 #include "MenuItemProperties.h"
62−#include "ScriptAudioInjector.h"
63−#include "ScriptAvatarData.h"
6445 #include "ScriptCache.h"
6546 #include "ScriptContext.h"
66−#include "ScriptEngineCast.h"
67−#include "ScriptEngineLogging.h"
6847 #include "XMLHttpRequestClass.h"
6948 #include "WebSocketClass.h"
70−#include "RecordingScriptingInterface.h"
49+#include "ScriptEngine.h"
50+#include "ScriptEngineCast.h"
51+#include "ScriptEngineLogging.h"
7152 #include "ScriptEngines.h"
7253 #include "StackTestScriptingInterface.h"
73−#include "ModelScriptingInterface.h"
7454 #include "ScriptValue.h"
7555 #include "ScriptValueIterator.h"
56+#include "ScriptValueUtils.h"
7657
7758 #include <Profile.h>
7859
@@ -94,8 +75,6 @@ const QString ScriptManager::SCRIPT_BACKTRACE_SEP{ "\n " }; · 15 unmodified lines
9475 static const int MAX_MODULE_ID_LENGTH { 4096 };
9576 static const int MAX_DEBUG_VALUE_LENGTH { 80 };
9677
97−static const ScriptEngine::QObjectWrapOptions DEFAULT_QOBJECT_WRAP_OPTIONS =
98− ScriptEngine::ExcludeDeleteLater | ScriptEngine::ExcludeChildObjects;
9978 static const ScriptValue::PropertyFlags READONLY_PROP_FLAGS{ ScriptValue::ReadOnly | ScriptValue::Undeletable };
10079 static const ScriptValue::PropertyFlags READONLY_HIDDEN_PROP_FLAGS{ READONLY_PROP_FLAGS | ScriptValue::SkipInEnumeration };
10180
@@ -108,6 +87,26 @@ int scriptManagerPointerMetaID = qRegisterMetaType<ScriptManagerPointer>(); · 6 unmodified lines
10887
10988 Q_DECLARE_METATYPE(ExternalResource::Bucket);
11089
90+// --- Static script initialization registry
91+
92+static ScriptManager::StaticInitializerNode* rootInitializer = nullptr;
93+
94+void 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+}
100+static 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+
111110 static ScriptValuePointer debugPrint(ScriptContext* context, ScriptEngine* engine) {
112111 // assemble the message by concatenating our arguments
113112 QString message = "";
@@ -172,17 +171,6 @@ static ScriptValuePointer debugPrint(ScriptContext* context, ScriptEngine* engin · 58 unmodified lines
172171 return ScriptValuePointer();
173172 }
174173
175−Q_DECLARE_METATYPE(controller::InputController*)
176−//static int inputControllerPointerId = qRegisterMetaType<controller::InputController*>();
177−
178−ScriptValuePointer inputControllerToScriptValue(ScriptEngine* engine, controller::InputController* const& in) {
179− return engine->newQObject(in, ScriptEngine::QtOwnership, DEFAULT_QOBJECT_WRAP_OPTIONS);
180−}
181−
182−void inputControllerFromScriptValue(const ScriptValuePointer& object, controller::InputController*& out) {
183− out = qobject_cast<controller::InputController*>(object->toQObject());
184−}
185−
186174 // FIXME Come up with a way to properly encode entity IDs in filename
187175 // The purpose of the following two function is to embed entity ids into entity script filenames
188176 // so that they show up in stacktraces
@@ -522,28 +510,6 @@ void ScriptManager::clearDebugLogWindow() { · 333 unmodified lines
522510 emit clearDebugWindow();
523511 }
524512
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...
528−static ScriptValuePointer animVarMapToScriptValue(ScriptEngine* engine, const AnimVariantMap& parameters) {
529− QStringList unused;
530− return parameters.animVariantMapToScriptValue(engine, unused, false);
531−}
532−static 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.
536−static 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−}
542−static void resultHandlerFromScriptValue(const ScriptValuePointer& value, AnimVariantResultHandler& resultHandler) {
543− qCCritical(scriptengine) << "Attempt to marshall result handler from javascript";
544− assert(false);
545−}
546−
547513 // Templated qScriptRegisterMetaType fails to compile with raw pointers
548514 using ScriptableResourceRawPtr = ScriptableResource*;
549515
@@ -562,13 +528,10 @@ static ScriptValuePointer scriptableResourceToScriptValue(ScriptEngine* engine, · 12 unmodified lines
562528 auto manager = engine->manager();
563529 if (data && manager && !resource->isInScript()) {
564530 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);
566532 }
567533
568− auto object = engine->newQObject(
569− const_cast<ScriptableResourceRawPtr>(resource),
570− ScriptEngine::ScriptOwnership,
571− DEFAULT_QOBJECT_WRAP_OPTIONS);
534+ auto object = engine->newQObject(const_cast<ScriptableResourceRawPtr>(resource), ScriptEngine::ScriptOwnership);
572535 return object;
573536 }
574537
@@ -602,22 +565,12 @@ static ScriptValuePointer createScriptableResourcePrototype(ScriptManagerPointer · 27 unmodified lines
602565 }
603566
604567 auto prototypeState = engine->newQObject(state, ScriptEngine::QtOwnership,
605− ScriptEngine::ExcludeDeleteLater | ScriptEngine::ExcludeSlots | ScriptEngine::ExcludeSuperClassMethods);
568+ ScriptEngine::ExcludeSlots | ScriptEngine::ExcludeSuperClassMethods);
606569 prototype->setProperty("State", prototypeState);
607570
608571 return prototype;
609572 }
610573
611−ScriptValuePointer avatarDataToScriptValue(ScriptEngine* engine, ScriptAvatarData* const& in) {
612− return engine->newQObject(in, ScriptEngine::ScriptOwnership, DEFAULT_QOBJECT_WRAP_OPTIONS);
613−}
614−
615−void 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−
621574 ScriptValuePointer externalResourceBucketToScriptValue(ScriptEngine* engine, ExternalResource::Bucket const& in) {
622575 return engine->newValue((int)in);
623576 }
@@ -666,27 +619,15 @@ void ScriptManager::init() { · 42 unmodified lines
666619 }
667620
668621 _isInitialized = true;
669− auto scriptEngine = _engine.data();
622+ runStaticInitializers(this);
670623
671− auto entityScriptingInterface = DependencyManager::get<EntityScriptingInterface>();
672− entityScriptingInterface->init();
624+ auto scriptEngine = _engine.data();
673625
674626 // register various meta-types
675− registerMetaTypes(scriptEngine);
676627 registerMIDIMetaTypes(scriptEngine);
677628 registerEventTypes(scriptEngine);
678629 registerMenuItemProperties(scriptEngine);
679− registerAnimationTypes(scriptEngine);
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);
630+
690631 scriptRegisterSequenceMetaType<QVector<QUuid>>(scriptEngine);
691632 scriptRegisterSequenceMetaType<QVector<EntityItemID>>(scriptEngine);
692633
@@ -709,12 +650,6 @@ void ScriptManager::init() { · 16 unmodified lines
709650 */
710651 scriptEngine->globalObject()->setProperty("print", scriptEngine->newFunction(debugPrint));
711652
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);
718653 scriptRegisterMetaType(scriptEngine, animationDetailsToScriptValue, animationDetailsFromScriptValue);
719654 scriptRegisterMetaType(scriptEngine, webSocketToScriptValue, webSocketFromScriptValue);
720655 scriptRegisterMetaType(scriptEngine, qWSCloseCodeToScriptValue, qWSCloseCodeFromScriptValue);
@@ -737,13 +672,8 @@ void ScriptManager::init() { · 16 unmodified lines
737672 scriptRegisterMetaType(scriptEngine, externalResourceBucketToScriptValue, externalResourceBucketFromScriptValue);
738673 scriptEngine->registerEnum("Script.ExternalPaths", QMetaEnum::fromType<ExternalResource::Bucket>());
739674
740− scriptEngine->registerGlobalObject("Audio", DependencyManager::get<AudioScriptingInterface>().data());
741−
742675 scriptEngine->registerGlobalObject("Midi", DependencyManager::get<Midi>().data());
743676
744− scriptEngine->registerGlobalObject("Entities", entityScriptingInterface.data());
745− scriptEngine->registerFunction("Entities", "getMultipleEntityProperties",
746− EntityScriptingInterface::getMultipleEntityProperties);
747677 scriptEngine->registerGlobalObject("Quat", &_quatLibrary);
748678 scriptEngine->registerGlobalObject("Vec3", &_vec3Library);
749679 scriptEngine->registerGlobalObject("Mat4", &_mat4Library);
@@ -762,9 +692,6 @@ void ScriptManager::init() { · 12 unmodified lines
762692 scriptEngine->registerFunction("console", "groupCollapsed", ConsoleScriptingInterface::groupCollapsed, 1);
763693 scriptEngine->registerFunction("console", "groupEnd", ConsoleScriptingInterface::groupEnd, 0);
764694
765− scriptRegisterMetaType(scriptEngine, animVarMapToScriptValue, animVarMapFromScriptValue);
766− scriptRegisterMetaType(scriptEngine, resultHandlerToScriptValue, resultHandlerFromScriptValue);
767−
768695 // Scriptable cache access
769696 auto resourcePrototype = createScriptableResourcePrototype(qSharedPointerCast<ScriptManager>(sharedFromThis()));
770697 scriptEngine->globalObject()->setProperty("Resource", resourcePrototype);
@@ -779,7 +706,6 @@ void ScriptManager::init() { · 8 unmodified lines
779706
780707 scriptEngine->registerGlobalObject("DebugDraw", &DebugDraw::getInstance());
781708
782− scriptEngine->registerGlobalObject("Model", new ModelScriptingInterface(this));
783709 scriptRegisterMetaType(scriptEngine, meshToScriptValue, meshFromScriptValue);
784710 scriptRegisterMetaType(scriptEngine, meshesToScriptValue, meshesFromScriptValue);
785711
@@ -825,6 +751,22 @@ void ScriptManager::removeEventHandler(const EntityItemID& entityID, const QStri · 39 unmodified lines
825751 }
826752 }
827753 }
754+
755+// Unregister all event handlers for the specified entityID (i.e. the entity is being removed)
756+void 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+
828770 // Register the handler.
829771 void ScriptManager::addEventHandler(const EntityItemID& entityID, const QString& eventName, ScriptValuePointer handler) {
830772 if (QThread::currentThread() != thread()) {
@@ -843,117 +785,9 @@ void ScriptManager::addEventHandler(const EntityItemID& entityID, const QString& · 12 unmodified lines
843785 qCDebug(scriptengine) << "ScriptManager::addEventHandler() called on thread [" << QThread::currentThread() << "] entityID:" << entityID << " eventName : " << eventName;
844786 #endif
845787
846− if (_registeredHandlers.count() == 0) { // First time any per-entity handler has been added in this script...
847− // Connect up ALL the handlers to the global entities object's signals.
848− // (We could go signal by signal, or even handler by handler, but I don't think the efficiency is worth the complexity.)
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"));
788+ if (_registeredHandlers.count() == 0) {
789+ // First time any per-entity handler has been added in this script...
790+ emit attachDefaultEventHandlers();
957791 }
958792 if (!_registeredHandlers.contains(entityID)) {
959793 _registeredHandlers[entityID] = RegisteredEventHandlers();
@@ -1008,9 +842,6 @@ void ScriptManager::run() { · 48 unmodified lines
1008842 clock::time_point startTime = clock::now();
1009843 int thisFrame = 0;
1010844
1011− auto nodeList = DependencyManager::get<NodeList>();
1012− auto entityScriptingInterface = DependencyManager::get<EntityScriptingInterface>();
1013−
1014845 _lastUpdate = usecTimestampNow();
1015846
1016847 std::chrono::microseconds totalUpdates(0);
@@ -1050,7 +881,7 @@ void ScriptManager::run() { · 33 unmodified lines
1050881 QEventLoop loop;
1051882 QTimer timer;
1052883 timer.setSingleShot(true);
1053− connect(&timer, SIGNAL(timeout()), &loop, SLOT(quit()));
884+ connect(&timer, &QTimer::timeout, &loop, &QEventLoop::quit);
1054885 timer.start(sleepFor.count());
1055886 loop.exec();
1056887 } else {
@@ -1092,14 +923,8 @@ void ScriptManager::run() { · 35 unmodified lines
1092923 break;
1093924 }
1094925
1095− if (!_isFinished && entityScriptingInterface->getEntityPacketSender()->serversExist()) {
1096− // release the queue of edit entity messages.
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− }
926+ if (!_isFinished) {
927+ emit releaseEntityPacketSenderMessages(false);
1103928 }
1104929
1105930 qint64 now = usecTimestampNow();
@@ -1133,21 +958,7 @@ void ScriptManager::run() { · 27 unmodified lines
1133958 stopAllTimers(); // make sure all our timers are stopped if the script is ending
1134959 emit scriptEnding();
1135960
1136− if (entityScriptingInterface->getEntityPacketSender()->serversExist()) {
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− }
961+ emit releaseEntityPacketSenderMessages(true);
1151962
1152963 emit finished(_fileNameString, qSharedPointerCast<ScriptManager>(sharedFromThis()));
1153964
@@ -1203,34 +1014,6 @@ void ScriptManager::stop(bool marshal) { · 49 unmodified lines
12031014 }
12041015 }
12051016
1206−// Other threads can invoke this through invokeMethod, which causes the callback to be asynchronously executed in this script's thread.
1207−void 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−
12341017 void ScriptManager::updateMemoryCost(const qint64& deltaSize) {
12351018 _engine->updateMemoryCost(deltaSize);
12361019 }