fixes for scripted avatars, closes #2033

This commit is contained in:
Stephen Birarda 2014-02-19 16:55:24 -08:00
parent 3f572765ed
commit 4ee416ba96
9 changed files with 50 additions and 22 deletions

View file

@ -113,6 +113,10 @@ void Agent::run() {
// setup an Avatar for the script to use // setup an Avatar for the script to use
AvatarData scriptedAvatar; AvatarData scriptedAvatar;
// call model URL setters with empty URLs so our avatar, if user, will have the default models
scriptedAvatar.setFaceModelURL(QUrl());
scriptedAvatar.setSkeletonModelURL(QUrl());
// give this AvatarData object to the script engine // give this AvatarData object to the script engine
_scriptEngine.setAvatarData(&scriptedAvatar, "Avatar"); _scriptEngine.setAvatarData(&scriptedAvatar, "Avatar");

View file

@ -29,7 +29,7 @@ class Agent : public ThreadedAssignment {
public: public:
Agent(const QByteArray& packet); Agent(const QByteArray& packet);
void setIsAvatar(bool isAvatar) { _scriptEngine.setIsAvatar(isAvatar); } void setIsAvatar(bool isAvatar) { QMetaObject::invokeMethod(&_scriptEngine, "setIsAvatar", Q_ARG(bool, isAvatar)); }
bool isAvatar() const { return _scriptEngine.isAvatar(); } bool isAvatar() const { return _scriptEngine.isAvatar(); }
public slots: public slots:

View file

@ -252,7 +252,7 @@ Application::Application(int& argc, char** argv, timeval &startup_time) :
// send the identity packet for our avatar each second to our avatar mixer // send the identity packet for our avatar each second to our avatar mixer
QTimer* identityPacketTimer = new QTimer(); QTimer* identityPacketTimer = new QTimer();
connect(identityPacketTimer, &QTimer::timeout, _myAvatar, &MyAvatar::sendIdentityPacket); connect(identityPacketTimer, &QTimer::timeout, _myAvatar, &MyAvatar::sendIdentityPacket);
identityPacketTimer->start(1000); identityPacketTimer->start(AVATAR_IDENTITY_PACKET_SEND_INTERVAL_MSECS);
QString cachePath = QStandardPaths::writableLocation(QStandardPaths::DataLocation); QString cachePath = QStandardPaths::writableLocation(QStandardPaths::DataLocation);

View file

@ -648,13 +648,6 @@ void MyAvatar::sendKillAvatar() {
NodeList::getInstance()->broadcastToNodes(killPacket, NodeSet() << NodeType::AvatarMixer); NodeList::getInstance()->broadcastToNodes(killPacket, NodeSet() << NodeType::AvatarMixer);
} }
void MyAvatar::sendIdentityPacket() {
QByteArray identityPacket = byteArrayWithPopluatedHeader(PacketTypeAvatarIdentity);
identityPacket.append(AvatarData::identityByteArray());
NodeList::getInstance()->broadcastToNodes(identityPacket, NodeSet() << NodeType::AvatarMixer);
}
void MyAvatar::orbit(const glm::vec3& position, int deltaX, int deltaY) { void MyAvatar::orbit(const glm::vec3& position, int deltaX, int deltaY) {
// first orbit horizontally // first orbit horizontally
glm::quat orientation = getOrientation(); glm::quat orientation = getOrientation();

View file

@ -89,7 +89,6 @@ public slots:
void increaseSize(); void increaseSize();
void decreaseSize(); void decreaseSize();
void resetSize(); void resetSize();
void sendIdentityPacket();
// Set/Get update the thrust that will move the avatar around // Set/Get update the thrust that will move the avatar around
void addThrust(glm::vec3 newThrust) { _thrust += newThrust; }; void addThrust(glm::vec3 newThrust) { _thrust += newThrust; };

View file

@ -338,3 +338,10 @@ void AvatarData::setOrientation(const glm::quat& orientation) {
_bodyYaw = eulerAngles.y; _bodyYaw = eulerAngles.y;
_bodyRoll = eulerAngles.z; _bodyRoll = eulerAngles.z;
} }
void AvatarData::sendIdentityPacket() {
QByteArray identityPacket = byteArrayWithPopluatedHeader(PacketTypeAvatarIdentity);
identityPacket.append(identityByteArray());
NodeList::getInstance()->broadcastToNodes(identityPacket, NodeSet() << NodeType::AvatarMixer);
}

View file

@ -52,6 +52,8 @@ static const float MIN_AVATAR_SCALE = .005f;
const float MAX_AUDIO_LOUDNESS = 1000.0; // close enough for mouth animation const float MAX_AUDIO_LOUDNESS = 1000.0; // close enough for mouth animation
const int AVATAR_IDENTITY_PACKET_SEND_INTERVAL_MSECS = 1000;
const QUrl DEFAULT_HEAD_MODEL_URL = QUrl("http://public.highfidelity.io/meshes/defaultAvatar_head.fst"); const QUrl DEFAULT_HEAD_MODEL_URL = QUrl("http://public.highfidelity.io/meshes/defaultAvatar_head.fst");
const QUrl DEFAULT_BODY_MODEL_URL = QUrl("http://public.highfidelity.io/meshes/defaultAvatar_body.fst"); const QUrl DEFAULT_BODY_MODEL_URL = QUrl("http://public.highfidelity.io/meshes/defaultAvatar_body.fst");
@ -157,6 +159,9 @@ public:
virtual float getBoundingRadius() const { return 1.f; } virtual float getBoundingRadius() const { return 1.f; }
public slots:
void sendIdentityPacket();
protected: protected:
glm::vec3 _position; glm::vec3 _position;
glm::vec3 _handPosition; glm::vec3 _handPosition;

View file

@ -44,6 +44,7 @@ ScriptEngine::ScriptEngine(const QString& scriptContents, bool wantMenuItems, co
AbstractMenuInterface* menu, AbstractMenuInterface* menu,
AbstractControllerScriptingInterface* controllerScriptingInterface) : AbstractControllerScriptingInterface* controllerScriptingInterface) :
_isAvatar(false), _isAvatar(false),
_avatarIdentityTimer(NULL),
_avatarData(NULL) _avatarData(NULL)
{ {
_scriptContents = scriptContents; _scriptContents = scriptContents;
@ -74,6 +75,21 @@ ScriptEngine::~ScriptEngine() {
//printf("ScriptEngine::~ScriptEngine()...\n"); //printf("ScriptEngine::~ScriptEngine()...\n");
} }
void ScriptEngine::setIsAvatar(bool isAvatar) {
_isAvatar = isAvatar;
if (_isAvatar && !_avatarIdentityTimer) {
// set up the avatar identity timer
_avatarIdentityTimer = new QTimer(this);
// connect our slot
connect(_avatarIdentityTimer, &QTimer::timeout, this, &ScriptEngine::sendAvatarIdentityPacket);
// start the timer
_avatarIdentityTimer->start(AVATAR_IDENTITY_PACKET_SEND_INTERVAL_MSECS);
}
}
void ScriptEngine::setAvatarData(AvatarData* avatarData, const QString& objectName) { void ScriptEngine::setAvatarData(AvatarData* avatarData, const QString& objectName) {
_avatarData = avatarData; _avatarData = avatarData;
@ -84,6 +100,7 @@ void ScriptEngine::setAvatarData(AvatarData* avatarData, const QString& objectNa
registerGlobalObject(objectName, _avatarData); registerGlobalObject(objectName, _avatarData);
} }
void ScriptEngine::setupMenuItems() { void ScriptEngine::setupMenuItems() {
if (_menu && _wantMenuItems) { if (_menu && _wantMenuItems) {
_menu->addActionToQMenuAndActionHash(_menu->getActiveScriptsMenu(), _scriptMenuName, 0, this, SLOT(stop())); _menu->addActionToQMenuAndActionHash(_menu->getActiveScriptsMenu(), _scriptMenuName, 0, this, SLOT(stop()));
@ -173,6 +190,12 @@ void ScriptEngine::evaluate() {
} }
} }
void ScriptEngine::sendAvatarIdentityPacket() {
if (_isAvatar && _avatarData) {
_avatarData->sendIdentityPacket();
}
}
void ScriptEngine::run() { void ScriptEngine::run() {
if (!_isInitialized) { if (!_isInitialized) {
init(); init();
@ -229,16 +252,7 @@ void ScriptEngine::run() {
} }
if (_isAvatar && _avatarData) { if (_isAvatar && _avatarData) {
static QByteArray avatarPacket; QByteArray avatarPacket = byteArrayWithPopluatedHeader(PacketTypeAvatarData);
int numAvatarHeaderBytes = 0;
if (avatarPacket.size() == 0) {
// pack the avatar header bytes the first time
// unlike the _avatar.getBroadcastData these won't change
numAvatarHeaderBytes = populatePacketHeader(avatarPacket, PacketTypeAvatarData);
}
avatarPacket.resize(numAvatarHeaderBytes);
avatarPacket.append(_avatarData->toByteArray()); avatarPacket.append(_avatarData->toByteArray());
nodeList->broadcastToNodes(avatarPacket, NodeSet() << NodeType::AvatarMixer); nodeList->broadcastToNodes(avatarPacket, NodeSet() << NodeType::AvatarMixer);
@ -253,6 +267,9 @@ void ScriptEngine::run() {
} }
emit scriptEnding(); emit scriptEnding();
// kill the avatar identity timer
delete _avatarIdentityTimer;
if (_voxelsScriptingInterface.getVoxelPacketSender()->serversExist()) { if (_voxelsScriptingInterface.getVoxelPacketSender()->serversExist()) {
// release the queue of edit voxel messages. // release the queue of edit voxel messages.
_voxelsScriptingInterface.getVoxelPacketSender()->releaseQueuedMessages(); _voxelsScriptingInterface.getVoxelPacketSender()->releaseQueuedMessages();

View file

@ -11,9 +11,9 @@
#include <vector> #include <vector>
#include <QtScript/QScriptEngine>
#include <QtCore/QObject> #include <QtCore/QObject>
#include <QtCore/QUrl> #include <QtCore/QUrl>
#include <QtScript/QScriptEngine>
#include <AbstractMenuInterface.h> #include <AbstractMenuInterface.h>
#include <AudioScriptingInterface.h> #include <AudioScriptingInterface.h>
@ -52,7 +52,7 @@ public:
void registerGlobalObject(const QString& name, QObject* object); /// registers a global object by name void registerGlobalObject(const QString& name, QObject* object); /// registers a global object by name
void setIsAvatar(bool isAvatar) { _isAvatar = isAvatar; } Q_INVOKABLE void setIsAvatar(bool isAvatar);
bool isAvatar() const { return _isAvatar; } bool isAvatar() const { return _isAvatar; }
void setAvatarData(AvatarData* avatarData, const QString& objectName); void setAvatarData(AvatarData* avatarData, const QString& objectName);
@ -84,9 +84,12 @@ protected:
bool _isInitialized; bool _isInitialized;
QScriptEngine _engine; QScriptEngine _engine;
bool _isAvatar; bool _isAvatar;
QTimer* _avatarIdentityTimer;
QHash<QTimer*, QScriptValue> _timerFunctionMap; QHash<QTimer*, QScriptValue> _timerFunctionMap;
private: private:
void sendAvatarIdentityPacket();
QObject* setupTimerWithInterval(const QScriptValue& function, int intervalMS, bool isSingleShot); QObject* setupTimerWithInterval(const QScriptValue& function, int intervalMS, bool isSingleShot);
void stopTimer(QTimer* timer); void stopTimer(QTimer* timer);