Example #1
0
void Agent::executeScript() {
    _scriptEngine = std::unique_ptr<ScriptEngine>(new ScriptEngine(_scriptContents, _payload));
    _scriptEngine->setParent(this); // be the parent of the script engine so it gets moved when we do

    // setup an Avatar for the script to use
    auto scriptedAvatar = DependencyManager::get<ScriptableAvatar>();
    connect(_scriptEngine.get(), SIGNAL(update(float)), scriptedAvatar.data(), SLOT(update(float)), Qt::ConnectionType::QueuedConnection);
    scriptedAvatar->setForceFaceTrackerConnected(true);

    // call model URL setters with empty URLs so our avatar, if user, will have the default models
    scriptedAvatar->setSkeletonModelURL(QUrl());

    // give this AvatarData object to the script engine
    _scriptEngine->registerGlobalObject("Avatar", scriptedAvatar.data());


    using namespace recording;
    static const FrameType AVATAR_FRAME_TYPE = Frame::registerFrameType(AvatarData::FRAME_NAME);
    // FIXME how to deal with driving multiple avatars locally?
    Frame::registerFrameHandler(AVATAR_FRAME_TYPE, [this, scriptedAvatar](Frame::ConstPointer frame) {
        AvatarData::fromFrame(frame->data, *scriptedAvatar);
    });

    using namespace recording;
    static const FrameType AUDIO_FRAME_TYPE = Frame::registerFrameType(AudioConstants::getAudioFrameName());
    Frame::registerFrameHandler(AUDIO_FRAME_TYPE, [this, &scriptedAvatar](Frame::ConstPointer frame) {
        const QByteArray& audio = frame->data;
        static quint16 audioSequenceNumber{ 0 };
        Transform audioTransform;
        audioTransform.setTranslation(scriptedAvatar->getPosition());
        audioTransform.setRotation(scriptedAvatar->getOrientation());
        AbstractAudioInterface::emitAudioPacket(audio.data(), audio.size(), audioSequenceNumber, audioTransform, PacketType::MicrophoneAudioNoEcho);
    });

    auto avatarHashMap = DependencyManager::set<AvatarHashMap>();
    _scriptEngine->registerGlobalObject("AvatarList", avatarHashMap.data());

    auto& packetReceiver = DependencyManager::get<NodeList>()->getPacketReceiver();
    packetReceiver.registerListener(PacketType::BulkAvatarData, avatarHashMap.data(), "processAvatarDataPacket");
    packetReceiver.registerListener(PacketType::KillAvatar, avatarHashMap.data(), "processKillAvatar");
    packetReceiver.registerListener(PacketType::AvatarIdentity, avatarHashMap.data(), "processAvatarIdentityPacket");
    packetReceiver.registerListener(PacketType::AvatarBillboard, avatarHashMap.data(), "processAvatarBillboardPacket");

    // register ourselves to the script engine
    _scriptEngine->registerGlobalObject("Agent", this);

    // FIXME -we shouldn't be calling this directly, it's normally called by run(), not sure why
    // viewers would need this called.
    //_scriptEngine->init(); // must be done before we set up the viewers

    _scriptEngine->registerGlobalObject("SoundCache", DependencyManager::get<SoundCache>().data());

    QScriptValue webSocketServerConstructorValue = _scriptEngine->newFunction(WebSocketServerClass::constructor);
    _scriptEngine->globalObject().setProperty("WebSocketServer", webSocketServerConstructorValue);

    auto entityScriptingInterface = DependencyManager::get<EntityScriptingInterface>();

    _scriptEngine->registerGlobalObject("EntityViewer", &_entityViewer);

    // we need to make sure that init has been called for our EntityScriptingInterface
    // so that it actually has a jurisdiction listener when we ask it for it next
    entityScriptingInterface->init();
    _entityViewer.setJurisdictionListener(entityScriptingInterface->getJurisdictionListener());

    _entityViewer.init();

    entityScriptingInterface->setEntityTree(_entityViewer.getTree());

    DependencyManager::set<AssignmentParentFinder>(_entityViewer.getTree());

    // wire up our additional agent related processing to the update signal
    QObject::connect(_scriptEngine.get(), &ScriptEngine::update, this, &Agent::processAgentAvatarAndAudio);

    _scriptEngine->run();

    Frame::clearFrameHandler(AUDIO_FRAME_TYPE);
    Frame::clearFrameHandler(AVATAR_FRAME_TYPE);

    setFinished(true);
}