From 665ea521e81b1ff2fa6e92ba5e86d6c3bc885cd7 Mon Sep 17 00:00:00 2001 From: Heather Anderson Date: Tue, 31 Aug 2021 18:09:08 -0700 Subject: [PATCH] shifting classes around and adding static initializers to resolve dependencies on scripting-engine (and drop dependencies from scripting-engine) --- assignment-client/src/Agent.cpp | 2 +- interface/src/Application.cpp | 2 +- interface/src/avatar/MyAvatar.cpp | 4 +- libraries/animation/CMakeLists.txt | 2 - libraries/animation/src/AnimationObject.cpp | 5 + libraries/animation/src/Rig.cpp | 37 +- libraries/audio/src/AudioEffectOptions.cpp | 8 + .../src/AudioScriptingInterface.cpp | 16 +- .../src/AudioScriptingInterface.h | 6 +- .../src/ScriptAudioInjector.cpp | 16 +- .../src/ScriptAudioInjector.h | 4 +- libraries/avatars/src/AvatarData.cpp | 11 +- libraries/avatars/src/ScriptAvatarData.cpp | 19 + .../src/controllers/ScriptingInterface.cpp | 21 ++ .../src/ModelScriptingInterface.cpp | 20 +- .../src/ModelScriptingInterface.h | 2 +- .../src/RenderablePolyVoxEntityItem.cpp | 2 +- libraries/entities/CMakeLists.txt | 1 - .../entities/src/EntityScriptingInterface.cpp | 170 +++++++++ .../entities/src/EntityScriptingInterface.h | 8 +- .../GraphicsScriptingInterface.cpp | 2 +- libraries/physics/src/ObjectDynamic.h | 2 +- libraries/recording/CMakeLists.txt | 2 +- .../RecordingScriptingInterface.cpp | 18 +- .../recording}/RecordingScriptingInterface.h | 6 +- libraries/script-engine/CMakeLists.txt | 17 +- .../src/EntitiesScriptEngineProvider.h | 2 +- .../src/EntityItemID.cpp | 8 +- .../src/EntityItemID.h | 2 +- .../src/EntityScriptUtils.h | 2 +- libraries/script-engine/src/ScriptCache.cpp | 1 + libraries/script-engine/src/ScriptCache.h | 2 +- libraries/script-engine/src/ScriptEngine.h | 4 +- libraries/script-engine/src/ScriptManager.cpp | 329 +++--------------- libraries/script-engine/src/ScriptManager.h | 57 +-- .../script-engine/src/ScriptValueUtils.cpp | 3 +- .../src/qtscript/ScriptContextQtAgent.cpp | 2 +- .../src/qtscript/ScriptContextQtAgent.h | 2 +- .../src/qtscript/ScriptContextQtWrapper.cpp | 2 +- .../src/qtscript/ScriptContextQtWrapper.h | 2 +- .../src/qtscript/ScriptEngineQtScript.cpp | 8 +- .../src/qtscript/ScriptEngineQtScript.h | 2 +- .../src/qtscript/ScriptProgramQtWrapper.cpp | 2 +- .../src/qtscript/ScriptProgramQtWrapper.h | 2 +- .../qtscript/ScriptValueIteratorQtWrapper.cpp | 2 +- .../qtscript/ScriptValueIteratorQtWrapper.h | 2 +- .../src/qtscript/ScriptValueQtWrapper.cpp | 2 +- .../src/qtscript/ScriptValueQtWrapper.h | 2 +- libraries/ui/CMakeLists.txt | 2 - libraries/ui/src/ui/QmlWrapper.h | 2 +- .../ui/src/ui/ToolbarScriptingInterface.cpp | 4 +- plugins/JSAPIExample/CMakeLists.txt | 2 - plugins/JSAPIExample/src/JSAPIExample.cpp | 4 +- 53 files changed, 455 insertions(+), 402 deletions(-) rename libraries/{script-engine => audio}/src/AudioScriptingInterface.cpp (91%) rename libraries/{script-engine => audio}/src/AudioScriptingInterface.h (99%) rename libraries/{script-engine => audio}/src/ScriptAudioInjector.cpp (79%) rename libraries/{script-engine => audio}/src/ScriptAudioInjector.h (98%) rename libraries/{script-engine => entities-renderer}/src/ModelScriptingInterface.cpp (96%) rename libraries/{script-engine => entities-renderer}/src/ModelScriptingInterface.h (99%) rename libraries/{script-engine/src => recording/src/recording}/RecordingScriptingInterface.cpp (97%) rename libraries/{script-engine/src => recording/src/recording}/RecordingScriptingInterface.h (99%) rename libraries/{entities => script-engine}/src/EntitiesScriptEngineProvider.h (96%) rename libraries/{entities => script-engine}/src/EntityItemID.cpp (94%) rename libraries/{entities => script-engine}/src/EntityItemID.h (98%) rename libraries/{networking => script-engine}/src/EntityScriptUtils.h (96%) diff --git a/assignment-client/src/Agent.cpp b/assignment-client/src/Agent.cpp index ac808e55f8..27685fbcda 100644 --- a/assignment-client/src/Agent.cpp +++ b/assignment-client/src/Agent.cpp @@ -59,7 +59,7 @@ #include "entities/AssignmentParentFinder.h" #include "AssignmentDynamicFactory.h" -#include "RecordingScriptingInterface.h" +#include #include "AbstractAudioInterface.h" #include "AgentScriptingInterface.h" diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index d964cec9c1..e250e0ce17 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -131,7 +131,7 @@ #include #include #include -#include +#include #include #include #include diff --git a/interface/src/avatar/MyAvatar.cpp b/interface/src/avatar/MyAvatar.cpp index c5dcf723fb..69e246ff28 100644 --- a/interface/src/avatar/MyAvatar.cpp +++ b/interface/src/avatar/MyAvatar.cpp @@ -51,7 +51,7 @@ #include #include #include -#include +#include #include #include #include @@ -440,7 +440,7 @@ void MyAvatar::enableHandTouchForID(const QUuid& entityID) { } void MyAvatar::registerMetaTypes(ScriptEnginePointer engine) { - ScriptValuePointer value = engine->newQObject(this, ScriptEngine::QtOwnership, ScriptEngine::ExcludeDeleteLater | ScriptEngine::ExcludeChildObjects); + ScriptValuePointer value = engine->newQObject(this, ScriptEngine::QtOwnership); engine->globalObject()->setProperty("MyAvatar", value); ScriptValuePointer driveKeys = engine->newObject(); diff --git a/libraries/animation/CMakeLists.txt b/libraries/animation/CMakeLists.txt index 9d843caaac..a18f6c2482 100644 --- a/libraries/animation/CMakeLists.txt +++ b/libraries/animation/CMakeLists.txt @@ -1,8 +1,6 @@ set(TARGET_NAME animation) setup_hifi_library(Network) link_hifi_libraries(shared graphics model-serializers script-engine) -include_hifi_library_headers(animation) -include_hifi_library_headers(entities) include_hifi_library_headers(gpu) include_hifi_library_headers(hfm) include_hifi_library_headers(image) diff --git a/libraries/animation/src/AnimationObject.cpp b/libraries/animation/src/AnimationObject.cpp index 20ecead184..09ac8114b9 100644 --- a/libraries/animation/src/AnimationObject.cpp +++ b/libraries/animation/src/AnimationObject.cpp @@ -13,10 +13,15 @@ #include #include +#include #include #include "AnimationCache.h" +STATIC_SCRIPT_INITIALIZER(+[](ScriptManager* manager) { + registerAnimationTypes(manager->engine().data()); +}); + QStringList AnimationObject::getJointNames() const { return scriptvalue_cast(thisObject())->getJointNames(); } diff --git a/libraries/animation/src/Rig.cpp b/libraries/animation/src/Rig.cpp index 485def7cc3..6edda21992 100644 --- a/libraries/animation/src/Rig.cpp +++ b/libraries/animation/src/Rig.cpp @@ -1652,14 +1652,35 @@ void Rig::updateAnimationStateHandlers() { // called on avatar update thread (wh rig->animationStateHandlerResult(identifier, result); } }; - // invokeMethod makes a copy of the args, and copies of AnimVariantMap do copy the underlying map, so this will correctly capture - // the state of _animVars and allow continued changes to _animVars in this thread without conflict. - QMetaObject::invokeMethod(function->engine()->manager(), "callAnimationStateHandler", Qt::QueuedConnection, - Q_ARG(ScriptValuePointer, function), - Q_ARG(AnimVariantMap, _animVars), - Q_ARG(QStringList, value.propertyNames), - Q_ARG(bool, value.useNames), - Q_ARG(AnimVariantResultHandler, handleResult)); + + { + // make references to the parameters for the lambda here, but let the lambda be the one to take the copies + // Copies of AnimVariantMap do copy the underlying map, so this will correctly capture + // the state of _animVars and allow continued changes to _animVars in this thread without conflict. + const AnimVariantMap& animVars = _animVars; + ScriptEnginePointer engine = function->engine(); + const QStringList& names = value.propertyNames; + bool useNames = value.useNames; + + QMetaObject::invokeMethod( + engine->manager(), + [function, animVars, names, useNames, handleResult, engine] { + ScriptValuePointer javascriptParameters = animVars.animVariantMapToScriptValue(engine.get(), names, useNames); + ScriptValueList callingArguments; + callingArguments << javascriptParameters; + ScriptValuePointer result = function->call(ScriptValuePointer(), callingArguments); + + // validate result from callback function. + if (result->isValid() && result->isObject()) { + handleResult(result); + } else { + qCWarning(animation) << "Rig::updateAnimationStateHandlers invalid return argument from " + "callback, expected an object"; + } + }, + Qt::QueuedConnection); + } + // It turns out that, for thread-safety reasons, ScriptEngine::callAnimationStateHandler will invoke itself if called from other // than the script thread. Thus the above _could_ be replaced with an ordinary call, which will then trigger the same // invokeMethod as is done explicitly above. However, the script-engine library depends on this animation library, not vice versa. diff --git a/libraries/audio/src/AudioEffectOptions.cpp b/libraries/audio/src/AudioEffectOptions.cpp index 94533a230e..dc7dd38b23 100644 --- a/libraries/audio/src/AudioEffectOptions.cpp +++ b/libraries/audio/src/AudioEffectOptions.cpp @@ -12,8 +12,16 @@ #include #include +#include #include +STATIC_SCRIPT_INITIALIZER(+[](ScriptManager* manager) { + auto scriptEngine = manager->engine().data(); + + ScriptValuePointer audioEffectOptionsConstructorValue = scriptEngine->newFunction(AudioEffectOptions::constructor); + scriptEngine->globalObject()->setProperty("AudioEffectOptions", audioEffectOptionsConstructorValue); +}); + static const QString BANDWIDTH_HANDLE = "bandwidth"; static const QString PRE_DELAY_HANDLE = "preDelay"; static const QString LATE_DELAY_HANDLE = "lateDelay"; diff --git a/libraries/script-engine/src/AudioScriptingInterface.cpp b/libraries/audio/src/AudioScriptingInterface.cpp similarity index 91% rename from libraries/script-engine/src/AudioScriptingInterface.cpp rename to libraries/audio/src/AudioScriptingInterface.cpp index 797a5b525d..f84efada04 100644 --- a/libraries/script-engine/src/AudioScriptingInterface.cpp +++ b/libraries/audio/src/AudioScriptingInterface.cpp @@ -16,9 +16,19 @@ #include #include "ScriptAudioInjector.h" -#include "ScriptEngine.h" -#include "ScriptEngineCast.h" -#include "ScriptEngineLogging.h" +#include +#include +#include +#include + + +STATIC_SCRIPT_INITIALIZER(+[](ScriptManager* manager){ + auto scriptEngine = manager->engine().data(); + + registerAudioMetaTypes(scriptEngine); + scriptEngine->registerGlobalObject("Audio", DependencyManager::get().data()); +}); + void registerAudioMetaTypes(ScriptEngine* engine) { scriptRegisterMetaType(engine, injectorOptionsToScriptValue, injectorOptionsFromScriptValue); diff --git a/libraries/script-engine/src/AudioScriptingInterface.h b/libraries/audio/src/AudioScriptingInterface.h similarity index 99% rename from libraries/script-engine/src/AudioScriptingInterface.h rename to libraries/audio/src/AudioScriptingInterface.h index 263d768e24..41239cec1c 100644 --- a/libraries/script-engine/src/AudioScriptingInterface.h +++ b/libraries/audio/src/AudioScriptingInterface.h @@ -15,10 +15,10 @@ #ifndef hifi_AudioScriptingInterface_h #define hifi_AudioScriptingInterface_h -#include -#include +#include "AbstractAudioInterface.h" +#include "AudioInjector.h" #include -#include +#include "Sound.h" class ScriptAudioInjector; class ScriptEngine; diff --git a/libraries/script-engine/src/ScriptAudioInjector.cpp b/libraries/audio/src/ScriptAudioInjector.cpp similarity index 79% rename from libraries/script-engine/src/ScriptAudioInjector.cpp rename to libraries/audio/src/ScriptAudioInjector.cpp index 324a463ef2..67a761c149 100644 --- a/libraries/script-engine/src/ScriptAudioInjector.cpp +++ b/libraries/audio/src/ScriptAudioInjector.cpp @@ -1,6 +1,6 @@ // // ScriptAudioInjector.cpp -// libraries/script-engine/src +// libraries/audio/src // // Created by Stephen Birarda on 2015-02-11. // Copyright 2015 High Fidelity, Inc. @@ -11,9 +11,17 @@ #include "ScriptAudioInjector.h" -#include "ScriptEngine.h" -#include "ScriptEngineLogging.h" -#include "ScriptValue.h" +#include +#include +#include +#include +#include + +STATIC_SCRIPT_INITIALIZER(+[](ScriptManager* manager) { + auto scriptEngine = manager->engine().data(); + + scriptRegisterMetaType(scriptEngine, injectorToScriptValue, injectorFromScriptValue); +}); ScriptValuePointer injectorToScriptValue(ScriptEngine* engine, ScriptAudioInjector* const& in) { // The AudioScriptingInterface::playSound method can return null, so we need to account for that. diff --git a/libraries/script-engine/src/ScriptAudioInjector.h b/libraries/audio/src/ScriptAudioInjector.h similarity index 98% rename from libraries/script-engine/src/ScriptAudioInjector.h rename to libraries/audio/src/ScriptAudioInjector.h index 80f382db88..5ff594643d 100644 --- a/libraries/script-engine/src/ScriptAudioInjector.h +++ b/libraries/audio/src/ScriptAudioInjector.h @@ -1,6 +1,6 @@ // // ScriptAudioInjector.h -// libraries/script-engine/src +// libraries/audio/src // // Created by Stephen Birarda on 2015-02-11. // Copyright 2015 High Fidelity, Inc. @@ -18,7 +18,7 @@ #include #include -#include +#include "AudioInjectorManager.h" class ScriptEngine; class ScriptValue; diff --git a/libraries/avatars/src/AvatarData.cpp b/libraries/avatars/src/AvatarData.cpp index 373b3bf0b3..106eb53f15 100644 --- a/libraries/avatars/src/AvatarData.cpp +++ b/libraries/avatars/src/AvatarData.cpp @@ -37,13 +37,14 @@ #include #include #include +#include #include +#include #include #include #include #include #include -#include #include "AvatarLogging.h" #include "AvatarTraits.h" @@ -67,6 +68,14 @@ static const float DEFAULT_AVATAR_DENSITY = 1000.0f; // density of water #define ASSERT(COND) do { if (!(COND)) { abort(); } } while(0) +STATIC_SCRIPT_INITIALIZER(+[](ScriptManager* manager) { + auto scriptEngine = manager->engine().data(); + + registerAvatarTypes(scriptEngine); + scriptRegisterMetaType(scriptEngine, RayToAvatarIntersectionResultToScriptValue, RayToAvatarIntersectionResultFromScriptValue); + scriptRegisterMetaType(scriptEngine, AvatarEntityMapToScriptValue, AvatarEntityMapFromScriptValue); +}); + size_t AvatarDataPacket::maxFaceTrackerInfoSize(size_t numBlendshapeCoefficients) { return FACE_TRACKER_INFO_SIZE + numBlendshapeCoefficients * sizeof(float); } diff --git a/libraries/avatars/src/ScriptAvatarData.cpp b/libraries/avatars/src/ScriptAvatarData.cpp index a67af18c40..6f322190c0 100644 --- a/libraries/avatars/src/ScriptAvatarData.cpp +++ b/libraries/avatars/src/ScriptAvatarData.cpp @@ -11,6 +11,25 @@ #include "ScriptAvatarData.h" +#include +#include + +ScriptValuePointer avatarDataToScriptValue(ScriptEngine* engine, ScriptAvatarData* const& in) { + return engine->newQObject(in, ScriptEngine::ScriptOwnership); +} + +void avatarDataFromScriptValue(const ScriptValuePointer& object, ScriptAvatarData*& out) { + // This is not implemented because there are no slots/properties that take an AvatarSharedPointer from a script + assert(false); + out = nullptr; +} + +STATIC_SCRIPT_INITIALIZER(+[](ScriptManager* manager) { + auto scriptEngine = manager->engine().data(); + + scriptRegisterMetaType(scriptEngine, avatarDataToScriptValue, avatarDataFromScriptValue); +}); + ScriptAvatarData::ScriptAvatarData(AvatarSharedPointer avatarData) : _avatarData(avatarData) { diff --git a/libraries/controllers/src/controllers/ScriptingInterface.cpp b/libraries/controllers/src/controllers/ScriptingInterface.cpp index e9a831859d..396e7cb5d4 100644 --- a/libraries/controllers/src/controllers/ScriptingInterface.cpp +++ b/libraries/controllers/src/controllers/ScriptingInterface.cpp @@ -25,6 +25,27 @@ #include "InputDevice.h" #include "InputRecorder.h" +#include +#include +#include +#include + +Q_DECLARE_METATYPE(controller::InputController*) +//static int inputControllerPointerId = qRegisterMetaType(); + +ScriptValuePointer inputControllerToScriptValue(ScriptEngine* engine, controller::InputController* const& in) { + return engine->newQObject(in, ScriptEngine::QtOwnership); +} + +void inputControllerFromScriptValue(const ScriptValuePointer& object, controller::InputController*& out) { + out = qobject_cast(object->toQObject()); +} + +STATIC_SCRIPT_INITIALIZER(+[](ScriptManager* manager) { + auto scriptEngine = manager->engine().data(); + + scriptRegisterMetaType(scriptEngine, inputControllerToScriptValue, inputControllerFromScriptValue); +}); static QRegularExpression SANITIZE_NAME_EXPRESSION{ "[\\(\\)\\.\\s]" }; diff --git a/libraries/script-engine/src/ModelScriptingInterface.cpp b/libraries/entities-renderer/src/ModelScriptingInterface.cpp similarity index 96% rename from libraries/script-engine/src/ModelScriptingInterface.cpp rename to libraries/entities-renderer/src/ModelScriptingInterface.cpp index 01ea580ca4..8fef3f0534 100644 --- a/libraries/script-engine/src/ModelScriptingInterface.cpp +++ b/libraries/entities-renderer/src/ModelScriptingInterface.cpp @@ -1,6 +1,6 @@ // // ModelScriptingInterface.cpp -// libraries/script-engine/src +// libraries/entities-renderer/src // // Created by Seth Alves on 2017-1-27. // Copyright 2017 High Fidelity, Inc. @@ -11,12 +11,18 @@ #include "ModelScriptingInterface.h" #include -#include "ScriptEngine.h" -#include "ScriptEngineCast.h" -#include "ScriptEngineLogging.h" -#include "ScriptManager.h" -#include "ScriptValueUtils.h" -#include "OBJWriter.h" +#include +#include +#include +#include +#include +#include + +STATIC_SCRIPT_INITIALIZER(+[](ScriptManager* manager) { + auto scriptEngine = manager->engine().data(); + + scriptEngine->registerGlobalObject("Model", new ModelScriptingInterface(manager)); +}); ModelScriptingInterface::ModelScriptingInterface(QObject* parent) : QObject(parent) { _modelScriptEngine = qobject_cast(parent)->engine(); diff --git a/libraries/script-engine/src/ModelScriptingInterface.h b/libraries/entities-renderer/src/ModelScriptingInterface.h similarity index 99% rename from libraries/script-engine/src/ModelScriptingInterface.h rename to libraries/entities-renderer/src/ModelScriptingInterface.h index 28d1fabd6a..25806716ec 100644 --- a/libraries/script-engine/src/ModelScriptingInterface.h +++ b/libraries/entities-renderer/src/ModelScriptingInterface.h @@ -1,6 +1,6 @@ // // ModelScriptingInterface.h -// libraries/script-engine/src +// libraries/entities-renderer/src // // Created by Seth Alves on 2017-1-27. // Copyright 2017 High Fidelity, Inc. diff --git a/libraries/entities-renderer/src/RenderablePolyVoxEntityItem.cpp b/libraries/entities-renderer/src/RenderablePolyVoxEntityItem.cpp index e5f6cafb82..172656f546 100644 --- a/libraries/entities-renderer/src/RenderablePolyVoxEntityItem.cpp +++ b/libraries/entities-renderer/src/RenderablePolyVoxEntityItem.cpp @@ -22,7 +22,7 @@ #include #include -#include +#include "ModelScriptingInterface.h" #include #include #include diff --git a/libraries/entities/CMakeLists.txt b/libraries/entities/CMakeLists.txt index dcd5a665b9..bf612b156e 100644 --- a/libraries/entities/CMakeLists.txt +++ b/libraries/entities/CMakeLists.txt @@ -1,7 +1,6 @@ set(TARGET_NAME entities) setup_hifi_library(Network) target_include_directories(${TARGET_NAME} PRIVATE "${OPENSSL_INCLUDE_DIR}") -include_hifi_library_headers(animation) include_hifi_library_headers(hfm) include_hifi_library_headers(model-serializers) include_hifi_library_headers(gpu) diff --git a/libraries/entities/src/EntityScriptingInterface.cpp b/libraries/entities/src/EntityScriptingInterface.cpp index 6b4ba52f20..ba338e6084 100644 --- a/libraries/entities/src/EntityScriptingInterface.cpp +++ b/libraries/entities/src/EntityScriptingInterface.cpp @@ -48,6 +48,36 @@ const QString GRABBABLE_USER_DATA = "{\"grabbableKey\":{\"grabbable\":true}}"; const QString NOT_GRABBABLE_USER_DATA = "{\"grabbableKey\":{\"grabbable\":false}}"; +static void staticScriptInitializer(ScriptManager* manager) { + auto scriptEngine = manager->engine().data(); + + auto entityScriptingInterface = DependencyManager::get(); + entityScriptingInterface->init(); + auto ifacePtr = entityScriptingInterface.data(); // using this when we don't want to leak a reference + + registerMetaTypes(scriptEngine); + + scriptRegisterMetaType(scriptEngine, EntityPropertyFlagsToScriptValue, EntityPropertyFlagsFromScriptValue); + scriptRegisterMetaType(scriptEngine, EntityItemPropertiesToScriptValue, EntityItemPropertiesFromScriptValueHonorReadOnly); + scriptRegisterMetaType(scriptEngine, EntityPropertyInfoToScriptValue, EntityPropertyInfoFromScriptValue); + scriptRegisterMetaType(scriptEngine, EntityItemIDtoScriptValue, EntityItemIDfromScriptValue); + scriptRegisterMetaType(scriptEngine, RayToEntityIntersectionResultToScriptValue, RayToEntityIntersectionResultFromScriptValue); + + scriptEngine->registerGlobalObject("Entities", entityScriptingInterface.data()); + scriptEngine->registerFunction("Entities", "getMultipleEntityProperties", EntityScriptingInterface::getMultipleEntityProperties); + + // "The return value of QObject::sender() is not valid when the slot is called via a Qt::DirectConnection from a thread + // different from this object's thread. Do not use this function in this type of scenario." + // so... yay lambdas everywhere to get the sender + manager->connect( + manager, &ScriptManager::attachDefaultEventHandlers, entityScriptingInterface.data(), + [ifacePtr, manager] { ifacePtr->attachDefaultEventHandlers(manager); }, + Qt::DirectConnection); + manager->connect(manager, &ScriptManager::releaseEntityPacketSenderMessages, entityScriptingInterface.data(), + &EntityScriptingInterface::releaseEntityPacketSenderMessages, Qt::DirectConnection); +} +STATIC_SCRIPT_INITIALIZER(staticScriptInitializer); + EntityScriptingInterface::EntityScriptingInterface(bool bidOnSimulationOwnership) : _entityTree(nullptr), _bidOnSimulationOwnership(bidOnSimulationOwnership) @@ -67,6 +97,146 @@ EntityScriptingInterface::EntityScriptingInterface(bool bidOnSimulationOwnership PacketReceiver::makeSourcedListenerReference(this, &EntityScriptingInterface::handleEntityScriptCallMethodPacket)); } +void EntityScriptingInterface::releaseEntityPacketSenderMessages(bool wait) { + EntityEditPacketSender* entityPacketSender = getEntityPacketSender(); + if (entityPacketSender->serversExist()) { + // release the queue of edit entity messages. + entityPacketSender->releaseQueuedMessages(); + + // since we're in non-threaded mode, call process so that the packets are sent + if (!entityPacketSender->isThreaded()) { + if (!wait) { + entityPacketSender->process(); + } else { + // wait here till the edit packet sender is completely done sending + while (entityPacketSender->hasPacketsToSend()) { + entityPacketSender->process(); + QCoreApplication::processEvents(); + } + } + } else { + // FIXME - do we need to have a similar "wait here" loop for non-threaded packet senders? + } + } +} + + +void EntityScriptingInterface::attachDefaultEventHandlers(ScriptManager* manager) { + // Connect up ALL the handlers to the global entities object's signals. + // (We could go signal by signal, or even handler by handler, but I don't think the efficiency is worth the complexity.) + + // Bug? These handlers are deleted when entityID is deleted, which is nice. + // But if they are created by an entity script on a different entity, should they also be deleted when the entity script unloads? + // E.g., suppose a bow has an entity script that causes arrows to be created with a potential lifetime greater than the bow, + // and that the entity script adds (e.g., collision) handlers to the arrows. Should those handlers fire if the bow is unloaded? + // Also, what about when the entity script is REloaded? + // For now, we are leaving them around. Changing that would require some non-trivial digging around to find the + // handlers that were added while a given currentEntityIdentifier was in place. I don't think this is dangerous. Just perhaps unexpected. -HRS + connect(this, &EntityScriptingInterface::deletingEntity, manager, + [manager](const EntityItemID& entityID) { manager->removeAllEventHandlers(entityID); }); + + // Two common cases of event handler, differing only in argument signature. + + /*@jsdoc + * Called when an entity event occurs on an entity as registered with {@link Script.addEventHandler}. + * @callback Script~entityEventCallback + * @param {Uuid} entityID - The ID of the entity the event has occured on. + */ + using SingleEntityHandler = std::function; + auto makeSingleEntityHandler = [manager](QString eventName) -> SingleEntityHandler { + return [manager, eventName](const EntityItemID& entityItemID) { + manager->forwardHandlerCall(entityItemID, eventName, { entityItemID.toScriptValue(manager->engine().data()) }); + }; + }; + + /*@jsdoc + * Called when a pointer event occurs on an entity as registered with {@link Script.addEventHandler}. + * @callback Script~pointerEventCallback + * @param {Uuid} entityID - The ID of the entity the event has occurred on. + * @param {PointerEvent} pointerEvent - Details of the event. + */ + using PointerHandler = std::function; + auto makePointerHandler = [manager](QString eventName) -> PointerHandler { + return [manager, eventName](const EntityItemID& entityItemID, const PointerEvent& event) { + if (!EntityTree::areEntityClicksCaptured()) { + ScriptEngine* engine = manager->engine().data(); + manager->forwardHandlerCall(entityItemID, eventName, + { entityItemID.toScriptValue(engine), event.toScriptValue(engine) }); + } + }; + }; + + /*@jsdoc + * Called when a collision event occurs on an entity as registered with {@link Script.addEventHandler}. + * @callback Script~collisionEventCallback + * @param {Uuid} entityA - The ID of one entity in the collision. + * @param {Uuid} entityB - The ID of the other entity in the collision. + * @param {Collision} collisionEvent - Details of the collision. + */ + using CollisionHandler = std::function; + auto makeCollisionHandler = [manager](QString eventName) -> CollisionHandler { + return [manager, eventName](const EntityItemID& idA, const EntityItemID& idB, const Collision& collision) { + ScriptEngine* engine = manager->engine().data(); + manager->forwardHandlerCall(idA, eventName, + { idA.toScriptValue(engine), idB.toScriptValue(engine), + collisionToScriptValue(engine, collision) }); + }; + }; + + /*@jsdoc + *

The name of an entity event. When the entity event occurs, any function that has been registered for that event + * via {@link Script.addEventHandler} is called with parameters per the entity event.

+ * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + *
Event NameCallback TypeEntity Event
"enterEntity"{@link Script~entityEventCallback|entityEventCallback}{@link Entities.enterEntity}
"leaveEntity"{@link Script~entityEventCallback|entityEventCallback}{@link Entities.leaveEntity}
"mousePressOnEntity"{@link Script~pointerEventCallback|pointerEventCallback}{@link Entities.mousePressOnEntity}
"mouseMoveOnEntity"{@link Script~pointerEventCallback|pointerEventCallback}{@link Entities.mouseMoveOnEntity}
"mouseReleaseOnEntity"{@link Script~pointerEventCallback|pointerEventCallback}{@link Entities.mouseReleaseOnEntity}
"clickDownOnEntity"{@link Script~pointerEventCallback|pointerEventCallback}{@link Entities.clickDownOnEntity}
"holdingClickOnEntity"{@link Script~pointerEventCallback|pointerEventCallback}{@link Entities.holdingClickOnEntity}
"clickReleaseOnEntity"{@link Script~pointerEventCallback|pointerEventCallback}{@link Entities.clickReleaseOnEntity}
"hoverEnterEntity"{@link Script~pointerEventCallback|pointerEventCallback}{@link Entities.hoverEnterEntity}
"hoverOverEntity"{@link Script~pointerEventCallback|pointerEventCallback}{@link Entities.hoverOverEntity}
"hoverLeaveEntity"{@link Script~pointerEventCallback|pointerEventCallback}{@link Entities.hoverLeaveEntity}
"collisionWithEntity"{@link Script~collisionEventCallback|collisionEventCallback}{@link Entities.collisionWithEntity}
+ * @typedef {string} Script.EntityEvent + */ + connect(this, &EntityScriptingInterface::enterEntity, manager, makeSingleEntityHandler("enterEntity")); + connect(this, &EntityScriptingInterface::leaveEntity, manager, makeSingleEntityHandler("leaveEntity")); + + connect(this, &EntityScriptingInterface::mousePressOnEntity, manager, makePointerHandler("mousePressOnEntity")); + connect(this, &EntityScriptingInterface::mouseMoveOnEntity, manager, makePointerHandler("mouseMoveOnEntity")); + connect(this, &EntityScriptingInterface::mouseReleaseOnEntity, manager, makePointerHandler("mouseReleaseOnEntity")); + + connect(this, &EntityScriptingInterface::clickDownOnEntity, manager, makePointerHandler("clickDownOnEntity")); + connect(this, &EntityScriptingInterface::holdingClickOnEntity, manager, makePointerHandler("holdingClickOnEntity")); + connect(this, &EntityScriptingInterface::clickReleaseOnEntity, manager, makePointerHandler("clickReleaseOnEntity")); + + connect(this, &EntityScriptingInterface::hoverEnterEntity, manager, makePointerHandler("hoverEnterEntity")); + connect(this, &EntityScriptingInterface::hoverOverEntity, manager, makePointerHandler("hoverOverEntity")); + connect(this, &EntityScriptingInterface::hoverLeaveEntity, manager, makePointerHandler("hoverLeaveEntity")); + + connect(this, &EntityScriptingInterface::collisionWithEntity, manager, makeCollisionHandler("collisionWithEntity")); +} + void EntityScriptingInterface::queueEntityMessage(PacketType packetType, EntityItemID entityID, const EntityItemProperties& properties) { getEntityPacketSender()->queueEditEntityMessage(packetType, _entityTree, entityID, properties); diff --git a/libraries/entities/src/EntityScriptingInterface.h b/libraries/entities/src/EntityScriptingInterface.h index 27eedee6f2..f18a3212a1 100644 --- a/libraries/entities/src/EntityScriptingInterface.h +++ b/libraries/entities/src/EntityScriptingInterface.h @@ -28,7 +28,7 @@ #include #include "PointerEvent.h" #include -#include "ScriptManager.h" +#include #include "PolyVoxEntityItem.h" #include "LineEntityItem.h" @@ -2541,7 +2541,13 @@ protected: } }; +private: + void attachDefaultEventHandlers(ScriptManager* manager); // called on first call to Script.addEventHandler + friend void staticScriptInitializer(ScriptManager* manager); + private slots: + void releaseEntityPacketSenderMessages(bool wait); + void handleEntityScriptCallMethodPacket(QSharedPointer receivedMessage, SharedNodePointer senderNode); void onAddingEntity(EntityItem* entity); void onDeletingEntity(EntityItem* entity); diff --git a/libraries/graphics-scripting/src/graphics-scripting/GraphicsScriptingInterface.cpp b/libraries/graphics-scripting/src/graphics-scripting/GraphicsScriptingInterface.cpp index 4ea94f1fd2..8314057225 100644 --- a/libraries/graphics-scripting/src/graphics-scripting/GraphicsScriptingInterface.cpp +++ b/libraries/graphics-scripting/src/graphics-scripting/GraphicsScriptingInterface.cpp @@ -323,7 +323,7 @@ namespace scriptable { if (!object) { return engine->nullValue(); } - return engine->newQObject(object, ScriptEngine::QtOwnership, ScriptEngine::ExcludeDeleteLater | ScriptEngine::AutoCreateDynamicProperties); + return engine->newQObject(object, ScriptEngine::QtOwnership, ScriptEngine::AutoCreateDynamicProperties); }, [](const ScriptValuePointer& value, QPointer& out) { auto obj = value->toQObject(); diff --git a/libraries/physics/src/ObjectDynamic.h b/libraries/physics/src/ObjectDynamic.h index 49fa615b88..96c2f225bb 100644 --- a/libraries/physics/src/ObjectDynamic.h +++ b/libraries/physics/src/ObjectDynamic.h @@ -23,7 +23,7 @@ #include "ObjectMotionState.h" #include "BulletUtil.h" -#include "EntityDynamicInterface.h" +#include class ObjectDynamic : public EntityDynamicInterface, public ReadWriteLockable { diff --git a/libraries/recording/CMakeLists.txt b/libraries/recording/CMakeLists.txt index 5821688eb0..ef357fdd5d 100644 --- a/libraries/recording/CMakeLists.txt +++ b/libraries/recording/CMakeLists.txt @@ -4,6 +4,6 @@ set(TARGET_NAME recording) setup_hifi_library() # use setup_hifi_library macro to setup our project and link appropriate Qt modules -link_hifi_libraries(shared networking) +link_hifi_libraries(shared networking script-engine) GroupSources("src/recording") diff --git a/libraries/script-engine/src/RecordingScriptingInterface.cpp b/libraries/recording/src/recording/RecordingScriptingInterface.cpp similarity index 97% rename from libraries/script-engine/src/RecordingScriptingInterface.cpp rename to libraries/recording/src/recording/RecordingScriptingInterface.cpp index e6cab50b24..f712a4c813 100644 --- a/libraries/script-engine/src/RecordingScriptingInterface.cpp +++ b/libraries/recording/src/recording/RecordingScriptingInterface.cpp @@ -20,16 +20,16 @@ #include #include #include -#include -#include -#include -#include -#include +#include "Deck.h" +#include "Recorder.h" +#include "Clip.h" +#include "Frame.h" +#include "ClipCache.h" -#include "ScriptEngine.h" -#include "ScriptEngineLogging.h" -#include "ScriptManager.h" -#include "ScriptValue.h" +#include +#include +#include +#include using namespace recording; diff --git a/libraries/script-engine/src/RecordingScriptingInterface.h b/libraries/recording/src/recording/RecordingScriptingInterface.h similarity index 99% rename from libraries/script-engine/src/RecordingScriptingInterface.h rename to libraries/recording/src/recording/RecordingScriptingInterface.h index 6026c49b3b..bad1561695 100644 --- a/libraries/script-engine/src/RecordingScriptingInterface.h +++ b/libraries/recording/src/recording/RecordingScriptingInterface.h @@ -19,9 +19,9 @@ #include #include -#include -#include -#include +#include "ClipCache.h" +#include "Forward.h" +#include "Frame.h" class ScriptValue; using ScriptValuePointer = QSharedPointer; diff --git a/libraries/script-engine/CMakeLists.txt b/libraries/script-engine/CMakeLists.txt index ae4d16db52..83ba2c63cc 100644 --- a/libraries/script-engine/CMakeLists.txt +++ b/libraries/script-engine/CMakeLists.txt @@ -1,6 +1,6 @@ set(TARGET_NAME script-engine) # FIXME Move undo scripting interface to application and remove Widgets -setup_hifi_library(Gui Network Script ScriptTools WebSockets) +setup_hifi_library(Network Script WebSockets) target_zlib() if (NOT ANDROID) @@ -8,21 +8,6 @@ if (NOT ANDROID) endif () link_hifi_libraries(shaders) -include_hifi_library_headers(animation) -include_hifi_library_headers(audio) -include_hifi_library_headers(avatars) -include_hifi_library_headers(controllers) -include_hifi_library_headers(entities) -include_hifi_library_headers(gpu) -include_hifi_library_headers(hfm) -include_hifi_library_headers(image) -include_hifi_library_headers(ktx) -include_hifi_library_headers(graphics) -include_hifi_library_headers(material-networking) -include_hifi_library_headers(model-networking) -include_hifi_library_headers(model-serializers) include_hifi_library_headers(networking) include_hifi_library_headers(octree) -include_hifi_library_headers(procedural) -include_hifi_library_headers(recording) include_hifi_library_headers(shared) diff --git a/libraries/entities/src/EntitiesScriptEngineProvider.h b/libraries/script-engine/src/EntitiesScriptEngineProvider.h similarity index 96% rename from libraries/entities/src/EntitiesScriptEngineProvider.h rename to libraries/script-engine/src/EntitiesScriptEngineProvider.h index 100c17df5f..fffdbe4c76 100644 --- a/libraries/entities/src/EntitiesScriptEngineProvider.h +++ b/libraries/script-engine/src/EntitiesScriptEngineProvider.h @@ -1,6 +1,6 @@ // // EntitiesScriptEngineProvider.h -// libraries/entities/src +// libraries/script-engine/src // // Created by Brad Hefta-Gaub on Sept. 18, 2015 // Copyright 2015 High Fidelity, Inc. diff --git a/libraries/entities/src/EntityItemID.cpp b/libraries/script-engine/src/EntityItemID.cpp similarity index 94% rename from libraries/entities/src/EntityItemID.cpp rename to libraries/script-engine/src/EntityItemID.cpp index 874a0fcd53..275637dfa8 100644 --- a/libraries/entities/src/EntityItemID.cpp +++ b/libraries/script-engine/src/EntityItemID.cpp @@ -1,6 +1,6 @@ // // EntityItemID.cpp -// libraries/entities/src +// libraries/script-engine/src // // Created by Brad Hefta-Gaub on 12/4/13. // Copyright 2013 High Fidelity, Inc. @@ -17,9 +17,9 @@ #include #include -#include "RegisteredMetaTypes.h" -#include -#include +#include +#include "ScriptValue.h" +#include "ScriptValueUtils.h" int entityItemIDTypeID = qRegisterMetaType(); diff --git a/libraries/entities/src/EntityItemID.h b/libraries/script-engine/src/EntityItemID.h similarity index 98% rename from libraries/entities/src/EntityItemID.h rename to libraries/script-engine/src/EntityItemID.h index 499493fa10..72a1bc90c7 100644 --- a/libraries/entities/src/EntityItemID.h +++ b/libraries/script-engine/src/EntityItemID.h @@ -1,6 +1,6 @@ // // EntityItemID.h -// libraries/entities/src +// libraries/script-engine/src // // Created by Brad Hefta-Gaub on 12/4/13. // Copyright 2013 High Fidelity, Inc. diff --git a/libraries/networking/src/EntityScriptUtils.h b/libraries/script-engine/src/EntityScriptUtils.h similarity index 96% rename from libraries/networking/src/EntityScriptUtils.h rename to libraries/script-engine/src/EntityScriptUtils.h index 15b056f0d2..4dad88f892 100644 --- a/libraries/networking/src/EntityScriptUtils.h +++ b/libraries/script-engine/src/EntityScriptUtils.h @@ -1,6 +1,6 @@ // // EntityScriptUtils.h -// libraries/networking/src +// libraries/script-engine/src // // Created by Ryan Huffman on 2017/01/13 // Copyright 2017 High Fidelity, Inc. diff --git a/libraries/script-engine/src/ScriptCache.cpp b/libraries/script-engine/src/ScriptCache.cpp index 0b63803a33..bd2e5dfa78 100644 --- a/libraries/script-engine/src/ScriptCache.cpp +++ b/libraries/script-engine/src/ScriptCache.cpp @@ -22,6 +22,7 @@ #include #include +#include #include #include "ScriptEngines.h" diff --git a/libraries/script-engine/src/ScriptCache.h b/libraries/script-engine/src/ScriptCache.h index 03d815e4ad..019cdac6f9 100644 --- a/libraries/script-engine/src/ScriptCache.h +++ b/libraries/script-engine/src/ScriptCache.h @@ -16,7 +16,7 @@ #define hifi_ScriptCache_h #include -#include +#include using contentAvailableCallback = std::function; diff --git a/libraries/script-engine/src/ScriptEngine.h b/libraries/script-engine/src/ScriptEngine.h index e9efded5cd..8488873680 100644 --- a/libraries/script-engine/src/ScriptEngine.h +++ b/libraries/script-engine/src/ScriptEngine.h @@ -50,11 +50,11 @@ public: }; enum QObjectWrapOption { - ExcludeChildObjects = 0x0001, // The script object will not expose child objects as properties. + //ExcludeChildObjects = 0x0001, // The script object will not expose child objects as properties. ExcludeSuperClassMethods = 0x0002, // The script object will not expose signals and slots inherited from the superclass. ExcludeSuperClassProperties = 0x0004, // The script object will not expose properties inherited from the superclass. ExcludeSuperClassContents = 0x0006, // Shorthand form for ExcludeSuperClassMethods | ExcludeSuperClassProperties - ExcludeDeleteLater = 0x0010, // The script object will not expose the QObject::deleteLater() slot. + //ExcludeDeleteLater = 0x0010, // The script object will not expose the QObject::deleteLater() slot. ExcludeSlots = 0x0020, // The script object will not expose the QObject's slots. AutoCreateDynamicProperties = 0x0100, // Properties that don't already exist in the QObject will be created as dynamic properties of that object, rather than as properties of the script object. PreferExistingWrapperObject = 0x0200, // If a wrapper object with the requested configuration already exists, return that object. diff --git a/libraries/script-engine/src/ScriptManager.cpp b/libraries/script-engine/src/ScriptManager.cpp index 1cb80d98ca..e2bebd5202 100644 --- a/libraries/script-engine/src/ScriptManager.cpp +++ b/libraries/script-engine/src/ScriptManager.cpp @@ -24,55 +24,36 @@ #include #include -#include -#include -#include -#include - -#include -#include - #include -#include #include -#include -#include -#include #include -#include #include -#include +#include #include +#include +#include +#include #include #include #include -#include -#include -#include -#include -#include - -#include "AudioScriptingInterface.h" #include "AssetScriptingInterface.h" #include "BatchLoader.h" #include "EventTypes.h" #include "FileScriptingInterface.h" // unzip project #include "MenuItemProperties.h" -#include "ScriptAudioInjector.h" -#include "ScriptAvatarData.h" #include "ScriptCache.h" #include "ScriptContext.h" -#include "ScriptEngineCast.h" -#include "ScriptEngineLogging.h" #include "XMLHttpRequestClass.h" #include "WebSocketClass.h" -#include "RecordingScriptingInterface.h" +#include "ScriptEngine.h" +#include "ScriptEngineCast.h" +#include "ScriptEngineLogging.h" #include "ScriptEngines.h" #include "StackTestScriptingInterface.h" -#include "ModelScriptingInterface.h" #include "ScriptValue.h" #include "ScriptValueIterator.h" +#include "ScriptValueUtils.h" #include @@ -94,8 +75,6 @@ const QString ScriptManager::SCRIPT_BACKTRACE_SEP{ "\n " }; static const int MAX_MODULE_ID_LENGTH { 4096 }; static const int MAX_DEBUG_VALUE_LENGTH { 80 }; -static const ScriptEngine::QObjectWrapOptions DEFAULT_QOBJECT_WRAP_OPTIONS = - ScriptEngine::ExcludeDeleteLater | ScriptEngine::ExcludeChildObjects; static const ScriptValue::PropertyFlags READONLY_PROP_FLAGS{ ScriptValue::ReadOnly | ScriptValue::Undeletable }; static const ScriptValue::PropertyFlags READONLY_HIDDEN_PROP_FLAGS{ READONLY_PROP_FLAGS | ScriptValue::SkipInEnumeration }; @@ -108,6 +87,26 @@ int scriptManagerPointerMetaID = qRegisterMetaType(); Q_DECLARE_METATYPE(ExternalResource::Bucket); +// --- Static script initialization registry + +static ScriptManager::StaticInitializerNode* rootInitializer = nullptr; + +void ScriptManager::registerNewStaticInitializer(StaticInitializerNode* dest) { + // this function is assumed to be called on LoadLibrary, where we are explicitly operating in single-threaded mode + // Therefore there is no mutex or threadsafety here and the structure is assumed not to change after loading + dest->prev = rootInitializer; + rootInitializer = dest; +} +static void runStaticInitializers(ScriptManager* manager) { + ScriptManager::StaticInitializerNode* here = rootInitializer; + while (here != nullptr) { + (*here->init)(manager); + here = here->prev; + } +} + +// --- + static ScriptValuePointer debugPrint(ScriptContext* context, ScriptEngine* engine) { // assemble the message by concatenating our arguments QString message = ""; @@ -172,17 +171,6 @@ static ScriptValuePointer debugPrint(ScriptContext* context, ScriptEngine* engin return ScriptValuePointer(); } -Q_DECLARE_METATYPE(controller::InputController*) -//static int inputControllerPointerId = qRegisterMetaType(); - -ScriptValuePointer inputControllerToScriptValue(ScriptEngine* engine, controller::InputController* const& in) { - return engine->newQObject(in, ScriptEngine::QtOwnership, DEFAULT_QOBJECT_WRAP_OPTIONS); -} - -void inputControllerFromScriptValue(const ScriptValuePointer& object, controller::InputController*& out) { - out = qobject_cast(object->toQObject()); -} - // FIXME Come up with a way to properly encode entity IDs in filename // The purpose of the following two function is to embed entity ids into entity script filenames // so that they show up in stacktraces @@ -522,28 +510,6 @@ void ScriptManager::clearDebugLogWindow() { emit clearDebugWindow(); } -// Even though we never pass AnimVariantMap directly to and from javascript, the queued invokeMethod of -// callAnimationStateHandler requires that the type be registered. -// These two are meaningful, if we ever do want to use them... -static ScriptValuePointer animVarMapToScriptValue(ScriptEngine* engine, const AnimVariantMap& parameters) { - QStringList unused; - return parameters.animVariantMapToScriptValue(engine, unused, false); -} -static void animVarMapFromScriptValue(const ScriptValuePointer& value, AnimVariantMap& parameters) { - parameters.animVariantMapFromScriptValue(value); -} -// ... while these two are not. But none of the four are ever used. -static ScriptValuePointer resultHandlerToScriptValue(ScriptEngine* engine, - const AnimVariantResultHandler& resultHandler) { - qCCritical(scriptengine) << "Attempt to marshall result handler to javascript"; - assert(false); - return ScriptValuePointer(); -} -static void resultHandlerFromScriptValue(const ScriptValuePointer& value, AnimVariantResultHandler& resultHandler) { - qCCritical(scriptengine) << "Attempt to marshall result handler from javascript"; - assert(false); -} - // Templated qScriptRegisterMetaType fails to compile with raw pointers using ScriptableResourceRawPtr = ScriptableResource*; @@ -562,13 +528,10 @@ static ScriptValuePointer scriptableResourceToScriptValue(ScriptEngine* engine, auto manager = engine->manager(); if (data && manager && !resource->isInScript()) { resource->setInScript(true); - QObject::connect(data.data(), SIGNAL(updateSize(qint64)), manager, SLOT(updateMemoryCost(qint64))); + QObject::connect(data.data(), &Resource::updateSize, manager, &ScriptManager::updateMemoryCost); } - auto object = engine->newQObject( - const_cast(resource), - ScriptEngine::ScriptOwnership, - DEFAULT_QOBJECT_WRAP_OPTIONS); + auto object = engine->newQObject(const_cast(resource), ScriptEngine::ScriptOwnership); return object; } @@ -602,22 +565,12 @@ static ScriptValuePointer createScriptableResourcePrototype(ScriptManagerPointer } auto prototypeState = engine->newQObject(state, ScriptEngine::QtOwnership, - ScriptEngine::ExcludeDeleteLater | ScriptEngine::ExcludeSlots | ScriptEngine::ExcludeSuperClassMethods); + ScriptEngine::ExcludeSlots | ScriptEngine::ExcludeSuperClassMethods); prototype->setProperty("State", prototypeState); return prototype; } -ScriptValuePointer avatarDataToScriptValue(ScriptEngine* engine, ScriptAvatarData* const& in) { - return engine->newQObject(in, ScriptEngine::ScriptOwnership, DEFAULT_QOBJECT_WRAP_OPTIONS); -} - -void avatarDataFromScriptValue(const ScriptValuePointer& object, ScriptAvatarData*& out) { - // This is not implemented because there are no slots/properties that take an AvatarSharedPointer from a script - assert(false); - out = nullptr; -} - ScriptValuePointer externalResourceBucketToScriptValue(ScriptEngine* engine, ExternalResource::Bucket const& in) { return engine->newValue((int)in); } @@ -666,27 +619,15 @@ void ScriptManager::init() { } _isInitialized = true; + runStaticInitializers(this); + auto scriptEngine = _engine.data(); - auto entityScriptingInterface = DependencyManager::get(); - entityScriptingInterface->init(); - // register various meta-types - registerMetaTypes(scriptEngine); registerMIDIMetaTypes(scriptEngine); registerEventTypes(scriptEngine); registerMenuItemProperties(scriptEngine); - registerAnimationTypes(scriptEngine); - registerAvatarTypes(scriptEngine); - registerAudioMetaTypes(scriptEngine); - scriptRegisterMetaType(scriptEngine, EntityPropertyFlagsToScriptValue, EntityPropertyFlagsFromScriptValue); - scriptRegisterMetaType(scriptEngine, EntityItemPropertiesToScriptValue, EntityItemPropertiesFromScriptValueHonorReadOnly); - scriptRegisterMetaType(scriptEngine, EntityPropertyInfoToScriptValue, EntityPropertyInfoFromScriptValue); - scriptRegisterMetaType(scriptEngine, EntityItemIDtoScriptValue, EntityItemIDfromScriptValue); - scriptRegisterMetaType(scriptEngine, RayToEntityIntersectionResultToScriptValue, RayToEntityIntersectionResultFromScriptValue); - scriptRegisterMetaType(scriptEngine, RayToAvatarIntersectionResultToScriptValue, RayToAvatarIntersectionResultFromScriptValue); - scriptRegisterMetaType(scriptEngine, AvatarEntityMapToScriptValue, AvatarEntityMapFromScriptValue); scriptRegisterSequenceMetaType>(scriptEngine); scriptRegisterSequenceMetaType>(scriptEngine); @@ -709,12 +650,6 @@ void ScriptManager::init() { */ scriptEngine->globalObject()->setProperty("print", scriptEngine->newFunction(debugPrint)); - ScriptValuePointer audioEffectOptionsConstructorValue = scriptEngine->newFunction(AudioEffectOptions::constructor); - scriptEngine->globalObject()->setProperty("AudioEffectOptions", audioEffectOptionsConstructorValue); - - scriptRegisterMetaType(scriptEngine, injectorToScriptValue, injectorFromScriptValue); - scriptRegisterMetaType(scriptEngine, inputControllerToScriptValue, inputControllerFromScriptValue); - scriptRegisterMetaType(scriptEngine, avatarDataToScriptValue, avatarDataFromScriptValue); scriptRegisterMetaType(scriptEngine, animationDetailsToScriptValue, animationDetailsFromScriptValue); scriptRegisterMetaType(scriptEngine, webSocketToScriptValue, webSocketFromScriptValue); scriptRegisterMetaType(scriptEngine, qWSCloseCodeToScriptValue, qWSCloseCodeFromScriptValue); @@ -737,13 +672,8 @@ void ScriptManager::init() { scriptRegisterMetaType(scriptEngine, externalResourceBucketToScriptValue, externalResourceBucketFromScriptValue); scriptEngine->registerEnum("Script.ExternalPaths", QMetaEnum::fromType()); - scriptEngine->registerGlobalObject("Audio", DependencyManager::get().data()); - scriptEngine->registerGlobalObject("Midi", DependencyManager::get().data()); - scriptEngine->registerGlobalObject("Entities", entityScriptingInterface.data()); - scriptEngine->registerFunction("Entities", "getMultipleEntityProperties", - EntityScriptingInterface::getMultipleEntityProperties); scriptEngine->registerGlobalObject("Quat", &_quatLibrary); scriptEngine->registerGlobalObject("Vec3", &_vec3Library); scriptEngine->registerGlobalObject("Mat4", &_mat4Library); @@ -762,9 +692,6 @@ void ScriptManager::init() { scriptEngine->registerFunction("console", "groupCollapsed", ConsoleScriptingInterface::groupCollapsed, 1); scriptEngine->registerFunction("console", "groupEnd", ConsoleScriptingInterface::groupEnd, 0); - scriptRegisterMetaType(scriptEngine, animVarMapToScriptValue, animVarMapFromScriptValue); - scriptRegisterMetaType(scriptEngine, resultHandlerToScriptValue, resultHandlerFromScriptValue); - // Scriptable cache access auto resourcePrototype = createScriptableResourcePrototype(qSharedPointerCast(sharedFromThis())); scriptEngine->globalObject()->setProperty("Resource", resourcePrototype); @@ -779,7 +706,6 @@ void ScriptManager::init() { scriptEngine->registerGlobalObject("DebugDraw", &DebugDraw::getInstance()); - scriptEngine->registerGlobalObject("Model", new ModelScriptingInterface(this)); scriptRegisterMetaType(scriptEngine, meshToScriptValue, meshFromScriptValue); scriptRegisterMetaType(scriptEngine, meshesToScriptValue, meshesFromScriptValue); @@ -825,6 +751,22 @@ void ScriptManager::removeEventHandler(const EntityItemID& entityID, const QStri } } } + +// Unregister all event handlers for the specified entityID (i.e. the entity is being removed) +void ScriptManager::removeAllEventHandlers(const EntityItemID& entityID) { + if (QThread::currentThread() != thread()) { +#ifdef THREAD_DEBUGGING + qCDebug(scriptengine) << "*** WARNING *** ScriptManager::removeAllEventHandlers() called on wrong thread [" << QThread::currentThread() << ", correct thread is " << thread() << " ], ignoring " + "entityID:" << entityID; +#endif + return; + } + + if (_registeredHandlers.contains(entityID)) { + _registeredHandlers.remove(entityID); + } +} + // Register the handler. void ScriptManager::addEventHandler(const EntityItemID& entityID, const QString& eventName, ScriptValuePointer handler) { if (QThread::currentThread() != thread()) { @@ -843,117 +785,9 @@ void ScriptManager::addEventHandler(const EntityItemID& entityID, const QString& qCDebug(scriptengine) << "ScriptManager::addEventHandler() called on thread [" << QThread::currentThread() << "] entityID:" << entityID << " eventName : " << eventName; #endif - if (_registeredHandlers.count() == 0) { // First time any per-entity handler has been added in this script... - // Connect up ALL the handlers to the global entities object's signals. - // (We could go signal by signal, or even handler by handler, but I don't think the efficiency is worth the complexity.) - auto entities = DependencyManager::get(); - // Bug? These handlers are deleted when entityID is deleted, which is nice. - // But if they are created by an entity script on a different entity, should they also be deleted when the entity script unloads? - // E.g., suppose a bow has an entity script that causes arrows to be created with a potential lifetime greater than the bow, - // and that the entity script adds (e.g., collision) handlers to the arrows. Should those handlers fire if the bow is unloaded? - // Also, what about when the entity script is REloaded? - // For now, we are leaving them around. Changing that would require some non-trivial digging around to find the - // handlers that were added while a given currentEntityIdentifier was in place. I don't think this is dangerous. Just perhaps unexpected. -HRS - connect(entities.data(), &EntityScriptingInterface::deletingEntity, this, [this](const EntityItemID& entityID) { - _registeredHandlers.remove(entityID); - }); - - // Two common cases of event handler, differing only in argument signature. - - /*@jsdoc - * Called when an entity event occurs on an entity as registered with {@link Script.addEventHandler}. - * @callback Script~entityEventCallback - * @param {Uuid} entityID - The ID of the entity the event has occured on. - */ - using SingleEntityHandler = std::function; - auto makeSingleEntityHandler = [this](QString eventName) -> SingleEntityHandler { - return [this, eventName](const EntityItemID& entityItemID) { - forwardHandlerCall(entityItemID, eventName, { entityItemID.toScriptValue(_engine.data()) }); - }; - }; - - /*@jsdoc - * Called when a pointer event occurs on an entity as registered with {@link Script.addEventHandler}. - * @callback Script~pointerEventCallback - * @param {Uuid} entityID - The ID of the entity the event has occurred on. - * @param {PointerEvent} pointerEvent - Details of the event. - */ - using PointerHandler = std::function; - auto makePointerHandler = [this](QString eventName) -> PointerHandler { - return [this, eventName](const EntityItemID& entityItemID, const PointerEvent& event) { - if (!EntityTree::areEntityClicksCaptured()) { - forwardHandlerCall(entityItemID, eventName, { entityItemID.toScriptValue(_engine.data()), event.toScriptValue(_engine.data()) }); - } - }; - }; - - /*@jsdoc - * Called when a collision event occurs on an entity as registered with {@link Script.addEventHandler}. - * @callback Script~collisionEventCallback - * @param {Uuid} entityA - The ID of one entity in the collision. - * @param {Uuid} entityB - The ID of the other entity in the collision. - * @param {Collision} collisionEvent - Details of the collision. - */ - using CollisionHandler = std::function; - auto makeCollisionHandler = [this](QString eventName) -> CollisionHandler { - return [this, eventName](const EntityItemID& idA, const EntityItemID& idB, const Collision& collision) { - forwardHandlerCall(idA, eventName, { idA.toScriptValue(_engine.data()), idB.toScriptValue(_engine.data()), - collisionToScriptValue(_engine.data(), collision) }); - }; - }; - - /*@jsdoc - *

The name of an entity event. When the entity event occurs, any function that has been registered for that event - * via {@link Script.addEventHandler} is called with parameters per the entity event.

- * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - *
Event NameCallback TypeEntity Event
"enterEntity"{@link Script~entityEventCallback|entityEventCallback}{@link Entities.enterEntity}
"leaveEntity"{@link Script~entityEventCallback|entityEventCallback}{@link Entities.leaveEntity}
"mousePressOnEntity"{@link Script~pointerEventCallback|pointerEventCallback}{@link Entities.mousePressOnEntity}
"mouseMoveOnEntity"{@link Script~pointerEventCallback|pointerEventCallback}{@link Entities.mouseMoveOnEntity}
"mouseReleaseOnEntity"{@link Script~pointerEventCallback|pointerEventCallback}{@link Entities.mouseReleaseOnEntity}
"clickDownOnEntity"{@link Script~pointerEventCallback|pointerEventCallback}{@link Entities.clickDownOnEntity}
"holdingClickOnEntity"{@link Script~pointerEventCallback|pointerEventCallback}{@link Entities.holdingClickOnEntity}
"clickReleaseOnEntity"{@link Script~pointerEventCallback|pointerEventCallback}{@link Entities.clickReleaseOnEntity}
"hoverEnterEntity"{@link Script~pointerEventCallback|pointerEventCallback}{@link Entities.hoverEnterEntity}
"hoverOverEntity"{@link Script~pointerEventCallback|pointerEventCallback}{@link Entities.hoverOverEntity}
"hoverLeaveEntity"{@link Script~pointerEventCallback|pointerEventCallback}{@link Entities.hoverLeaveEntity}
"collisionWithEntity"{@link Script~collisionEventCallback|collisionEventCallback}{@link Entities.collisionWithEntity}
- * @typedef {string} Script.EntityEvent - */ - connect(entities.data(), &EntityScriptingInterface::enterEntity, this, makeSingleEntityHandler("enterEntity")); - connect(entities.data(), &EntityScriptingInterface::leaveEntity, this, makeSingleEntityHandler("leaveEntity")); - - connect(entities.data(), &EntityScriptingInterface::mousePressOnEntity, this, makePointerHandler("mousePressOnEntity")); - connect(entities.data(), &EntityScriptingInterface::mouseMoveOnEntity, this, makePointerHandler("mouseMoveOnEntity")); - connect(entities.data(), &EntityScriptingInterface::mouseReleaseOnEntity, this, makePointerHandler("mouseReleaseOnEntity")); - - connect(entities.data(), &EntityScriptingInterface::clickDownOnEntity, this, makePointerHandler("clickDownOnEntity")); - connect(entities.data(), &EntityScriptingInterface::holdingClickOnEntity, this, makePointerHandler("holdingClickOnEntity")); - connect(entities.data(), &EntityScriptingInterface::clickReleaseOnEntity, this, makePointerHandler("clickReleaseOnEntity")); - - connect(entities.data(), &EntityScriptingInterface::hoverEnterEntity, this, makePointerHandler("hoverEnterEntity")); - connect(entities.data(), &EntityScriptingInterface::hoverOverEntity, this, makePointerHandler("hoverOverEntity")); - connect(entities.data(), &EntityScriptingInterface::hoverLeaveEntity, this, makePointerHandler("hoverLeaveEntity")); - - connect(entities.data(), &EntityScriptingInterface::collisionWithEntity, this, makeCollisionHandler("collisionWithEntity")); + if (_registeredHandlers.count() == 0) { + // First time any per-entity handler has been added in this script... + emit attachDefaultEventHandlers(); } if (!_registeredHandlers.contains(entityID)) { _registeredHandlers[entityID] = RegisteredEventHandlers(); @@ -1008,9 +842,6 @@ void ScriptManager::run() { clock::time_point startTime = clock::now(); int thisFrame = 0; - auto nodeList = DependencyManager::get(); - auto entityScriptingInterface = DependencyManager::get(); - _lastUpdate = usecTimestampNow(); std::chrono::microseconds totalUpdates(0); @@ -1050,7 +881,7 @@ void ScriptManager::run() { QEventLoop loop; QTimer timer; timer.setSingleShot(true); - connect(&timer, SIGNAL(timeout()), &loop, SLOT(quit())); + connect(&timer, &QTimer::timeout, &loop, &QEventLoop::quit); timer.start(sleepFor.count()); loop.exec(); } else { @@ -1092,14 +923,8 @@ void ScriptManager::run() { break; } - if (!_isFinished && entityScriptingInterface->getEntityPacketSender()->serversExist()) { - // release the queue of edit entity messages. - entityScriptingInterface->getEntityPacketSender()->releaseQueuedMessages(); - - // since we're in non-threaded mode, call process so that the packets are sent - if (!entityScriptingInterface->getEntityPacketSender()->isThreaded()) { - entityScriptingInterface->getEntityPacketSender()->process(); - } + if (!_isFinished) { + emit releaseEntityPacketSenderMessages(false); } qint64 now = usecTimestampNow(); @@ -1133,21 +958,7 @@ void ScriptManager::run() { stopAllTimers(); // make sure all our timers are stopped if the script is ending emit scriptEnding(); - if (entityScriptingInterface->getEntityPacketSender()->serversExist()) { - // release the queue of edit entity messages. - entityScriptingInterface->getEntityPacketSender()->releaseQueuedMessages(); - - // since we're in non-threaded mode, call process so that the packets are sent - if (!entityScriptingInterface->getEntityPacketSender()->isThreaded()) { - // wait here till the edit packet sender is completely done sending - while (entityScriptingInterface->getEntityPacketSender()->hasPacketsToSend()) { - entityScriptingInterface->getEntityPacketSender()->process(); - QCoreApplication::processEvents(); - } - } else { - // FIXME - do we need to have a similar "wait here" loop for non-threaded packet senders? - } - } + emit releaseEntityPacketSenderMessages(true); emit finished(_fileNameString, qSharedPointerCast(sharedFromThis())); @@ -1203,34 +1014,6 @@ void ScriptManager::stop(bool marshal) { } } -// Other threads can invoke this through invokeMethod, which causes the callback to be asynchronously executed in this script's thread. -void ScriptManager::callAnimationStateHandler(ScriptValuePointer callback, AnimVariantMap parameters, QStringList names, bool useNames, AnimVariantResultHandler resultHandler) { - if (QThread::currentThread() != thread()) { -#ifdef THREAD_DEBUGGING - qCDebug(scriptengine) << "*** WARNING *** ScriptManager::callAnimationStateHandler() called on wrong thread [" << QThread::currentThread() << "], invoking on correct thread [" << thread() << "] name:" << name; -#endif - QMetaObject::invokeMethod(this, "callAnimationStateHandler", - Q_ARG(ScriptValuePointer, callback), - Q_ARG(AnimVariantMap, parameters), - Q_ARG(QStringList, names), - Q_ARG(bool, useNames), - Q_ARG(AnimVariantResultHandler, resultHandler)); - return; - } - ScriptValuePointer javascriptParameters = parameters.animVariantMapToScriptValue(_engine.get(), names, useNames); - ScriptValueList callingArguments; - callingArguments << javascriptParameters; - assert(currentEntityIdentifier.isInvalidID()); // No animation state handlers from entity scripts. - ScriptValuePointer result = callback->call(ScriptValuePointer(), callingArguments); - - // validate result from callback function. - if (result->isValid() && result->isObject()) { - resultHandler(result); - } else { - qCWarning(scriptengine) << "ScriptManager::callAnimationStateHandler invalid return argument from callback, expected an object"; - } -} - void ScriptManager::updateMemoryCost(const qint64& deltaSize) { _engine->updateMemoryCost(deltaSize); } diff --git a/libraries/script-engine/src/ScriptManager.h b/libraries/script-engine/src/ScriptManager.h index aec48bc9b7..b180d69753 100644 --- a/libraries/script-engine/src/ScriptManager.h +++ b/libraries/script-engine/src/ScriptManager.h @@ -16,6 +16,7 @@ #include #include #include +#include #include #include @@ -29,10 +30,9 @@ #include #include -#include #include "EntityItemID.h" #include "EntitiesScriptEngineProvider.h" -#include +#include "EntityScriptUtils.h" #include #include @@ -44,8 +44,6 @@ #include "ScriptUUID.h" #include "Vec3.h" -class QScriptEngineDebugger; - static const QString NO_SCRIPT(""); static const int SCRIPT_FPS = 60; @@ -104,6 +102,10 @@ public: QUrl definingSandboxURL { QUrl("about:EntityScript") }; }; +// declare a static script initializer +#define STATIC_SCRIPT_INITIALIZER(init) \ + static ScriptManager::StaticInitializerNode static_script_initializer_(init); + /**jsdoc * The Script API provides facilities for working with scripts. * @@ -159,19 +161,27 @@ public: AGENT, AVATAR }; - Q_ENUM(Type) + Q_ENUM(Type); static int processLevelMaxRetries; ScriptManager(Context context, const QString& scriptContents = NO_SCRIPT, const QString& fileNameString = QString("about:ScriptEngine")); ~ScriptManager(); + // static initialization support + typedef void (*ScriptManagerInitializer)(ScriptManager*); + class StaticInitializerNode { + public: + ScriptManagerInitializer init; + StaticInitializerNode* prev; + inline StaticInitializerNode(ScriptManagerInitializer&& pInit) : init(std::move(pInit)),prev(nullptr) { registerNewStaticInitializer(this); } + }; + static void registerNewStaticInitializer(StaticInitializerNode* dest); + /// run the script in a dedicated thread. This will have the side effect of evalulating /// the current script contents and calling run(). Callers will likely want to register the script with external /// services before calling this. void runInThread(); - void runDebuggable(); - /// run the script in the callers thread, exit when stop() is called. void run(); @@ -376,7 +386,7 @@ public: /**jsdoc * Provides access to methods or objects provided in an external JavaScript or JSON file. - * See {@link https://docs.vircadia.dev/script/js-tips.html} for further details. + * See {@link https://docs.overte.org/script/js-tips.html} for further details. * @function Script.require * @param {string} module - The module to use. May be a JavaScript file, a JSON file, or the name of a system module such * as "appUi" (i.e., the "appUi.js" system module JavaScript file). @@ -595,8 +605,6 @@ public: // this is used by code in ScriptEngines.cpp during the "reload all" operation bool isStopping() const { return _isStopping; } - bool isDebuggable() const { return _debuggable; } - void disconnectNonEssentialSignals(); //////////////////////////////////////////////////////////////////////////////////////////////////////////////////// @@ -621,6 +629,13 @@ public: void setScriptEngines(QSharedPointer& scriptEngines) { _scriptEngines = scriptEngines; } + // call all the registered event handlers on an entity for the specified name. + void forwardHandlerCall(const EntityItemID& entityID, const QString& eventName, ScriptValueList eventHanderArgs); + + // remove all event handlers for the specified entityID (i.e. the entity is being removed) + void removeAllEventHandlers(const EntityItemID& entityID); + + /**jsdoc * Gets the URL for an asset in an external resource bucket. (The location where the bucket is hosted may change over time * but this method will return the asset's current URL.) @@ -640,17 +655,6 @@ public: public slots: - /**jsdoc - * @function Script.callAnimationStateHandler - * @param {function} callback - Callback function. - * @param {object} parameters - Parameters. - * @param {string[]} names - Names. - * @param {boolean} useNames - Use names. - * @param {function} resultHandler - Result handler. - * @deprecated This function is deprecated and will be removed. - */ - void callAnimationStateHandler(ScriptValuePointer callback, AnimVariantMap parameters, QStringList names, bool useNames, AnimVariantResultHandler resultHandler); - /**jsdoc * @function Script.updateMemoryCost * @param {number} deltaSize - Delta size. @@ -851,6 +855,14 @@ signals: */ void unhandledException(const ScriptValuePointer& exception); + // Triggered once before the first call to Script.addEventHandler happens on this ScriptManager + // connections assumed to use Qt::DirectConnection; not for use by scripts + void attachDefaultEventHandlers(); + + // Triggered repeatedly in the scripting loop to ensure entity edit messages get processed properly + // connections assumed to use Qt::DirectConnection; not for use by scripts + void releaseEntityPacketSenderMessages(bool wait); + protected: void init(); @@ -886,7 +898,6 @@ protected: void stopTimer(QTimer* timer); QHash _registeredHandlers; - void forwardHandlerCall(const EntityItemID& entityID, const QString& eventName, ScriptValueList eventHanderArgs); /**jsdoc * @function Script.entityScriptContentAvailable @@ -921,8 +932,6 @@ protected: EntityScriptContentAvailableMap _contentAvailableQueue; bool _isThreaded { false }; - QScriptEngineDebugger* _debugger { nullptr }; - bool _debuggable { false }; qint64 _lastUpdate; QString _fileNameString; diff --git a/libraries/script-engine/src/ScriptValueUtils.cpp b/libraries/script-engine/src/ScriptValueUtils.cpp index 777e3296f7..ba047da230 100644 --- a/libraries/script-engine/src/ScriptValueUtils.cpp +++ b/libraries/script-engine/src/ScriptValueUtils.cpp @@ -806,8 +806,7 @@ void animationDetailsFromScriptValue(const ScriptValuePointer& object, Animation } ScriptValuePointer meshToScriptValue(ScriptEngine* engine, MeshProxy* const& in) { - return engine->newQObject(in, ScriptEngine::QtOwnership, - ScriptEngine::ExcludeDeleteLater | ScriptEngine::ExcludeChildObjects); + return engine->newQObject(in, ScriptEngine::QtOwnership); } void meshFromScriptValue(const ScriptValuePointer& value, MeshProxy*& out) { diff --git a/libraries/script-engine/src/qtscript/ScriptContextQtAgent.cpp b/libraries/script-engine/src/qtscript/ScriptContextQtAgent.cpp index 142d2dbb2a..db888c3e99 100644 --- a/libraries/script-engine/src/qtscript/ScriptContextQtAgent.cpp +++ b/libraries/script-engine/src/qtscript/ScriptContextQtAgent.cpp @@ -1,6 +1,6 @@ // // ScriptContextQtAgent.cpp -// libraries/script-engine/src +// libraries/script-engine/src/qtscript // // Created by Heather Anderson on 5/22/21. // Copyright 2021 Vircadia contributors. diff --git a/libraries/script-engine/src/qtscript/ScriptContextQtAgent.h b/libraries/script-engine/src/qtscript/ScriptContextQtAgent.h index 15e02e9934..05f4254bf0 100644 --- a/libraries/script-engine/src/qtscript/ScriptContextQtAgent.h +++ b/libraries/script-engine/src/qtscript/ScriptContextQtAgent.h @@ -1,6 +1,6 @@ // // ScriptContextQtAgent.h -// libraries/script-engine/src +// libraries/script-engine/src/qtscript // // Created by Heather Anderson on 5/22/21. // Copyright 2021 Vircadia contributors. diff --git a/libraries/script-engine/src/qtscript/ScriptContextQtWrapper.cpp b/libraries/script-engine/src/qtscript/ScriptContextQtWrapper.cpp index 0e37545840..41cd945ca2 100644 --- a/libraries/script-engine/src/qtscript/ScriptContextQtWrapper.cpp +++ b/libraries/script-engine/src/qtscript/ScriptContextQtWrapper.cpp @@ -1,6 +1,6 @@ // // ScriptContextQtWrapper.cpp -// libraries/script-engine/src +// libraries/script-engine/src/qtscript // // Created by Heather Anderson on 5/22/21. // Copyright 2021 Vircadia contributors. diff --git a/libraries/script-engine/src/qtscript/ScriptContextQtWrapper.h b/libraries/script-engine/src/qtscript/ScriptContextQtWrapper.h index 229a5b7102..b2f7726d85 100644 --- a/libraries/script-engine/src/qtscript/ScriptContextQtWrapper.h +++ b/libraries/script-engine/src/qtscript/ScriptContextQtWrapper.h @@ -1,6 +1,6 @@ // // ScriptContextQtWrapper.h -// libraries/script-engine/src +// libraries/script-engine/src/qtscript // // Created by Heather Anderson on 5/22/21. // Copyright 2021 Vircadia contributors. diff --git a/libraries/script-engine/src/qtscript/ScriptEngineQtScript.cpp b/libraries/script-engine/src/qtscript/ScriptEngineQtScript.cpp index 258a792165..2552856727 100644 --- a/libraries/script-engine/src/qtscript/ScriptEngineQtScript.cpp +++ b/libraries/script-engine/src/qtscript/ScriptEngineQtScript.cpp @@ -1,6 +1,6 @@ // // ScriptEngineQtScript.cpp -// libraries/script-engine-qtscript/src +// libraries/script-engine/src/qtscript // // Created by Brad Hefta-Gaub on 12/14/13. // Copyright 2013 High Fidelity, Inc. @@ -869,11 +869,11 @@ ScriptProgramPointer ScriptEngineQtScript::newProgram(const QString& sourceCode, return ScriptProgramPointer(new ScriptProgramQtWrapper(this, result)); } -ScriptValuePointer ScriptEngineQtScript::newQObject(QObject* obj, +ScriptValuePointer ScriptEngineQtScript::newQObject(QObject* object, ScriptEngine::ValueOwnership ownership, const ScriptEngine::QObjectWrapOptions& options) { - QScriptValue result = QScriptEngine::newQObject(obj, static_cast(ownership), - (QScriptEngine::QObjectWrapOptions)(int)options); + QScriptValue result = QScriptEngine::newQObject(object, static_cast(ownership), + (QScriptEngine::QObjectWrapOptions)((int)options | DEFAULT_QOBJECT_WRAP_OPTIONS)); return ScriptValuePointer(new ScriptValueQtWrapper(this, std::move(result))); } diff --git a/libraries/script-engine/src/qtscript/ScriptEngineQtScript.h b/libraries/script-engine/src/qtscript/ScriptEngineQtScript.h index 367525e7fb..ff704c5ad8 100644 --- a/libraries/script-engine/src/qtscript/ScriptEngineQtScript.h +++ b/libraries/script-engine/src/qtscript/ScriptEngineQtScript.h @@ -1,6 +1,6 @@ // // ScriptEngineQtScript.h -// libraries/script-engine-qtscript/src +// libraries/script-engine/src/qtscript // // Created by Brad Hefta-Gaub on 12/14/13. // Copyright 2013 High Fidelity, Inc. diff --git a/libraries/script-engine/src/qtscript/ScriptProgramQtWrapper.cpp b/libraries/script-engine/src/qtscript/ScriptProgramQtWrapper.cpp index be5f4df111..11dba1417e 100644 --- a/libraries/script-engine/src/qtscript/ScriptProgramQtWrapper.cpp +++ b/libraries/script-engine/src/qtscript/ScriptProgramQtWrapper.cpp @@ -1,6 +1,6 @@ // // ScriptProgramQtWrapper.cpp -// libraries/script-engine/src +// libraries/script-engine/src/qtscript // // Created by Heather Anderson on 8/24/21. // Copyright 2021 Vircadia contributors. diff --git a/libraries/script-engine/src/qtscript/ScriptProgramQtWrapper.h b/libraries/script-engine/src/qtscript/ScriptProgramQtWrapper.h index dca9c9d83a..ddd477b90b 100644 --- a/libraries/script-engine/src/qtscript/ScriptProgramQtWrapper.h +++ b/libraries/script-engine/src/qtscript/ScriptProgramQtWrapper.h @@ -1,6 +1,6 @@ // // ScriptProgramQtWrapper.h -// libraries/script-engine/src +// libraries/script-engine/src/qtscript // // Created by Heather Anderson on 5/21/21. // Copyright 2021 Vircadia contributors. diff --git a/libraries/script-engine/src/qtscript/ScriptValueIteratorQtWrapper.cpp b/libraries/script-engine/src/qtscript/ScriptValueIteratorQtWrapper.cpp index 755d2556db..c56f021f88 100644 --- a/libraries/script-engine/src/qtscript/ScriptValueIteratorQtWrapper.cpp +++ b/libraries/script-engine/src/qtscript/ScriptValueIteratorQtWrapper.cpp @@ -1,6 +1,6 @@ // // ScriptValueIteratorQtWrapper.cpp -// libraries/script-engine/src +// libraries/script-engine/src/qtscript // // Created by Heather Anderson on 8/29/21. // Copyright 2021 Vircadia contributors. diff --git a/libraries/script-engine/src/qtscript/ScriptValueIteratorQtWrapper.h b/libraries/script-engine/src/qtscript/ScriptValueIteratorQtWrapper.h index ee5d20ef1e..7835e7cfae 100644 --- a/libraries/script-engine/src/qtscript/ScriptValueIteratorQtWrapper.h +++ b/libraries/script-engine/src/qtscript/ScriptValueIteratorQtWrapper.h @@ -1,6 +1,6 @@ // // ScriptValueIteratorQtWrapper.h -// libraries/script-engine/src +// libraries/script-engine/src/qtscript // // Created by Heather Anderson on 8/29/21. // Copyright 2021 Vircadia contributors. diff --git a/libraries/script-engine/src/qtscript/ScriptValueQtWrapper.cpp b/libraries/script-engine/src/qtscript/ScriptValueQtWrapper.cpp index 0bdb824549..f0d1e4d22b 100644 --- a/libraries/script-engine/src/qtscript/ScriptValueQtWrapper.cpp +++ b/libraries/script-engine/src/qtscript/ScriptValueQtWrapper.cpp @@ -1,6 +1,6 @@ // // ScriptValueQtWrapper.cpp -// libraries/script-engine/src +// libraries/script-engine/src/qtscript // // Created by Heather Anderson on 5/16/21. // Copyright 2021 Vircadia contributors. diff --git a/libraries/script-engine/src/qtscript/ScriptValueQtWrapper.h b/libraries/script-engine/src/qtscript/ScriptValueQtWrapper.h index 5ac1dea943..d7fa124a5a 100644 --- a/libraries/script-engine/src/qtscript/ScriptValueQtWrapper.h +++ b/libraries/script-engine/src/qtscript/ScriptValueQtWrapper.h @@ -1,6 +1,6 @@ // // ScriptValueQtWrapper.h -// libraries/script-engine/src +// libraries/script-engine/src/qtscript // // Created by Heather Anderson on 5/16/21. // Copyright 2021 Vircadia contributors. diff --git a/libraries/ui/CMakeLists.txt b/libraries/ui/CMakeLists.txt index a2d84cb478..fce94173f6 100644 --- a/libraries/ui/CMakeLists.txt +++ b/libraries/ui/CMakeLists.txt @@ -1,8 +1,6 @@ set(TARGET_NAME ui) setup_hifi_library(OpenGL Multimedia Network Qml Quick WebChannel WebSockets XmlPatterns ${PLATFORM_QT_COMPONENTS}) link_hifi_libraries(shared networking qml gl audio audio-client plugins pointers script-engine) -include_hifi_library_headers(animation) -include_hifi_library_headers(entities) include_hifi_library_headers(controllers) # Required for some low level GL interaction in the OffscreenQMLSurface diff --git a/libraries/ui/src/ui/QmlWrapper.h b/libraries/ui/src/ui/QmlWrapper.h index b768f3c262..b5150f440c 100644 --- a/libraries/ui/src/ui/QmlWrapper.h +++ b/libraries/ui/src/ui/QmlWrapper.h @@ -36,7 +36,7 @@ ScriptValuePointer wrapperToScriptValue(ScriptEngine* engine, T* const &in) { if (!in) { return engine->undefinedValue(); } - return engine->newQObject(in, ScriptEngine::QtOwnership, ScriptEngine::ExcludeDeleteLater | ScriptEngine::ExcludeChildObjects); + return engine->newQObject(in, ScriptEngine::QtOwnership); } template diff --git a/libraries/ui/src/ui/ToolbarScriptingInterface.cpp b/libraries/ui/src/ui/ToolbarScriptingInterface.cpp index 05b1804f87..e23023e137 100644 --- a/libraries/ui/src/ui/ToolbarScriptingInterface.cpp +++ b/libraries/ui/src/ui/ToolbarScriptingInterface.cpp @@ -20,7 +20,7 @@ ScriptValuePointer toolbarToScriptValue(ScriptEngine* engine, ToolbarProxy* cons if (!in) { return engine->undefinedValue(); } - return engine->newQObject(in, ScriptEngine::QtOwnership, ScriptEngine::ExcludeDeleteLater | ScriptEngine::ExcludeChildObjects); + return engine->newQObject(in, ScriptEngine::QtOwnership); } void toolbarFromScriptValue(const ScriptValuePointer& value, ToolbarProxy* &out) { @@ -31,7 +31,7 @@ ScriptValuePointer toolbarButtonToScriptValue(ScriptEngine* engine, ToolbarButto if (!in) { return engine->undefinedValue(); } - return engine->newQObject(in, ScriptEngine::QtOwnership, ScriptEngine::ExcludeDeleteLater | ScriptEngine::ExcludeChildObjects); + return engine->newQObject(in, ScriptEngine::QtOwnership); } void toolbarButtonFromScriptValue(const ScriptValuePointer& value, ToolbarButtonProxy* &out) { diff --git a/plugins/JSAPIExample/CMakeLists.txt b/plugins/JSAPIExample/CMakeLists.txt index 02301654c8..c8858ad2cb 100644 --- a/plugins/JSAPIExample/CMakeLists.txt +++ b/plugins/JSAPIExample/CMakeLists.txt @@ -1,6 +1,4 @@ set(TARGET_NAME JSAPIExample) setup_hifi_client_server_plugin(scripting) link_hifi_libraries(shared plugins script-engine) -include_hifi_library_headers(animation) -include_hifi_library_headers(entities) include_hifi_library_headers(networking) diff --git a/plugins/JSAPIExample/src/JSAPIExample.cpp b/plugins/JSAPIExample/src/JSAPIExample.cpp index 3993689c4a..205bd83f98 100644 --- a/plugins/JSAPIExample/src/JSAPIExample.cpp +++ b/plugins/JSAPIExample/src/JSAPIExample.cpp @@ -64,7 +64,7 @@ namespace REPLACE_ME_WITH_UNIQUE_NAME { } qCWarning(logger) << "registering w/ScriptInitializerMixin..." << scriptInit.data(); scriptInit->registerScriptInitializer([this](ScriptEngine* engine) { - auto value = engine->newQObject(this, ScriptEngine::QtOwnership, ScriptEngine::ExcludeDeleteLater); + auto value = engine->newQObject(this, ScriptEngine::QtOwnership); engine->globalObject()->setProperty(objectName(), value); // qCDebug(logger) << "setGlobalInstance" << objectName() << engine->property("fileName"); }); @@ -175,7 +175,7 @@ namespace REPLACE_ME_WITH_UNIQUE_NAME { raiseScriptingError(context(), "error creating scoped settings instance: " + error); return engine->nullValue(); } - return engine->newQObject(cppValue, ScriptEngine::ScriptOwnership, ScriptEngine::ExcludeDeleteLater); + return engine->newQObject(cppValue, ScriptEngine::ScriptOwnership); } private: