diff --git a/assignment-client/src/Agent.cpp b/assignment-client/src/Agent.cpp index ca89d3998f..d27845f337 100644 --- a/assignment-client/src/Agent.cpp +++ b/assignment-client/src/Agent.cpp @@ -56,7 +56,7 @@ void Agent::run() { // other node types, but for them to get access to those node types, we have to add them here. It seems like // NodeList should support adding types of interest const NODE_TYPE AGENT_NODE_TYPES_OF_INTEREST[] = { NODE_TYPE_VOXEL_SERVER, NODE_TYPE_PARTICLE_SERVER, - NODE_TYPE_AUDIO_MIXER }; + NODE_TYPE_AUDIO_MIXER, NODE_TYPE_AVATAR_MIXER }; nodeList->setNodeTypesOfInterest(AGENT_NODE_TYPES_OF_INTEREST, sizeof(AGENT_NODE_TYPES_OF_INTEREST)); @@ -93,6 +93,15 @@ void Agent::run() { QTimer* pingNodesTimer = new QTimer(this); connect(pingNodesTimer, SIGNAL(timeout()), nodeList, SLOT(pingInactiveNodes())); pingNodesTimer->start(PING_INACTIVE_NODE_INTERVAL_USECS / 1000); + + // setup an Avatar for the script to use + AvatarData scriptedAvatar; + + // match the scripted avatar's UUID to the DataServerScriptingInterface UUID + scriptedAvatar.setUUID(_scriptEngine.getDataServerScriptingInterface().getUUID()); + + // give this AvatarData object to the script engine + _scriptEngine.setAvatarData(&scriptedAvatar); _scriptEngine.setScriptContents(scriptContents); _scriptEngine.run(); diff --git a/libraries/script-engine/src/DataServerScriptingInterface.h b/libraries/script-engine/src/DataServerScriptingInterface.h index 4a50bc087a..8bd3eea565 100644 --- a/libraries/script-engine/src/DataServerScriptingInterface.h +++ b/libraries/script-engine/src/DataServerScriptingInterface.h @@ -19,6 +19,8 @@ public: DataServerScriptingInterface(); void refreshUUID() { _uuid = QUuid::createUuid(); } + const QUuid& getUUID() const { return _uuid; } + public slots: void setValueForKey(const QString& key, const QString& value); private: diff --git a/libraries/script-engine/src/ScriptEngine.cpp b/libraries/script-engine/src/ScriptEngine.cpp index 2c08bd9b08..1b2f121b5b 100644 --- a/libraries/script-engine/src/ScriptEngine.cpp +++ b/libraries/script-engine/src/ScriptEngine.cpp @@ -40,7 +40,9 @@ static QScriptValue soundConstructor(QScriptContext* context, QScriptEngine* eng ScriptEngine::ScriptEngine(const QString& scriptContents, bool wantMenuItems, const char* scriptMenuName, AbstractMenuInterface* menu, - AbstractControllerScriptingInterface* controllerScriptingInterface) { + AbstractControllerScriptingInterface* controllerScriptingInterface) : + _avatarData(NULL) +{ _scriptContents = scriptContents; _isFinished = false; _isRunning = false; @@ -65,6 +67,15 @@ ScriptEngine::~ScriptEngine() { //printf("ScriptEngine::~ScriptEngine()...\n"); } +void ScriptEngine::setAvatarData(AvatarData* avatarData) { + _avatarData = avatarData; + + // remove the old Avatar property, if it exists + _engine.globalObject().setProperty("Avatar", QScriptValue()); + + // give the script engine the new Avatar script property + registerGlobalObject("Avatar", _avatarData); +} void ScriptEngine::setupMenuItems() { if (_menu && _wantMenuItems) { @@ -178,6 +189,8 @@ void ScriptEngine::run() { gettimeofday(&startTime, NULL); int thisFrame = 0; + + NodeList* nodeList = NodeList::getInstance(); while (!_isFinished) { int usecToSleep = usecTimestamp(&startTime) + (thisFrame++ * VISUAL_DATA_CALLBACK_USECS) - usecTimestampNow(); @@ -221,6 +234,26 @@ void ScriptEngine::run() { _particlesScriptingInterface.getParticlePacketSender()->process(); } } + + if (_isAvatar && _avatarData) { + static unsigned char avatarPacket[MAX_PACKET_SIZE]; + static int numAvatarHeaderBytes = 0; + + if (numAvatarHeaderBytes == 0) { + // pack the avatar header bytes the first time + // unlike the _avatar.getBroadcastData these won't change + numAvatarHeaderBytes = populateTypeAndVersion(avatarPacket, PACKET_TYPE_HEAD_DATA); + + // pack the owner UUID for this script + QByteArray ownerUUID = nodeList->getOwnerUUID().toRfc4122(); + memcpy(avatarPacket, ownerUUID.constData(), ownerUUID.size()); + numAvatarHeaderBytes += ownerUUID.size(); + } + + int numAvatarPacketBytes = _avatarData->getBroadcastData(avatarPacket + numAvatarHeaderBytes) + numAvatarHeaderBytes; + + nodeList->broadcastToNodes(avatarPacket, numAvatarPacketBytes, &NODE_TYPE_AVATAR_MIXER, 1); + } if (willSendVisualDataCallBack) { emit willSendVisualDataCallback(); diff --git a/libraries/script-engine/src/ScriptEngine.h b/libraries/script-engine/src/ScriptEngine.h index ab38b48bbf..9f1fbeacae 100644 --- a/libraries/script-engine/src/ScriptEngine.h +++ b/libraries/script-engine/src/ScriptEngine.h @@ -19,6 +19,8 @@ #include #include +#include + class ParticlesScriptingInterface; #include "AbstractControllerScriptingInterface.h" @@ -28,6 +30,8 @@ const QString NO_SCRIPT(""); class ScriptEngine : public QObject { Q_OBJECT + + Q_PROPERTY(bool isAvatar READ isAvatar WRITE setIsAvatar) public: ScriptEngine(const QString& scriptContents = NO_SCRIPT, bool wantMenuItems = false, const char* scriptMenuName = NULL, AbstractMenuInterface* menu = NULL, @@ -40,6 +44,9 @@ public: /// Access the ParticlesScriptingInterface in order to initialize it with a custom packet sender and jurisdiction listener ParticlesScriptingInterface* getParticlesScriptingInterface() { return &_particlesScriptingInterface; } + + /// Access the DataServerScriptingInterface for access to its underlying UUID + const DataServerScriptingInterface& getDataServerScriptingInterface() { return _dataServerScriptingInterface; } /// sets the script contents, will return false if failed, will fail if script is already running bool setScriptContents(const QString& scriptContents); @@ -48,6 +55,11 @@ public: void cleanMenuItems(); void registerGlobalObject(const QString& name, QObject* object); /// registers a global object by name + + void setIsAvatar(bool isAvatar) { _isAvatar = isAvatar; } + bool isAvatar() const { return _isAvatar; } + + void setAvatarData(AvatarData* avatarData); public slots: void init(); @@ -69,6 +81,7 @@ protected: bool _isRunning; bool _isInitialized; QScriptEngine _engine; + bool _isAvatar; private: static VoxelsScriptingInterface _voxelsScriptingInterface; @@ -76,6 +89,7 @@ private: AbstractControllerScriptingInterface* _controllerScriptingInterface; AudioScriptingInterface _audioScriptingInterface; DataServerScriptingInterface _dataServerScriptingInterface; + AvatarData* _avatarData; bool _wantMenuItems; QString _scriptMenuName; AbstractMenuInterface* _menu;