Merge pull request #1029 from birarda/nameserver

initial revision of storing user data in data-server
This commit is contained in:
Philip Rosedale 2013-10-09 11:36:36 -07:00
commit 3a92856386
21 changed files with 519 additions and 78 deletions

View file

@ -12,6 +12,7 @@
#include <AvatarData.h>
#include <NodeList.h>
#include <UUID.h>
#include <VoxelConstants.h>
#include "Agent.h"
@ -50,7 +51,7 @@ void Agent::run() {
// figure out the URL for the script for this agent assignment
QString scriptURLString("http://%1:8080/assignment/%2");
scriptURLString = scriptURLString.arg(NodeList::getInstance()->getDomainIP().toString(),
this->getUUIDStringWithoutCurlyBraces());
uuidStringWithoutCurlyBraces(_uuid));
// setup curl for script download
CURLcode curlResult;

View file

@ -12,6 +12,7 @@
#include <PacketHeaders.h>
#include <SharedUtil.h>
#include <UUID.h>
#include "DomainServer.h"
@ -62,7 +63,7 @@ void DomainServer::civetwebUploadHandler(struct mg_connection *connection, const
QString newPath(ASSIGNMENT_SCRIPT_HOST_LOCATION);
newPath += "/";
// append the UUID for this script as the new filename, remove the curly braces
newPath += scriptAssignment->getUUIDStringWithoutCurlyBraces();
newPath += uuidStringWithoutCurlyBraces(scriptAssignment->getUUID());
// rename the saved script to the GUID of the assignment and move it to the script host locaiton
rename(path, newPath.toLocal8Bit().constData());

View file

@ -58,6 +58,7 @@
#include <VoxelSceneStats.h>
#include "Application.h"
#include "DataServerClient.h"
#include "LogDisplay.h"
#include "Menu.h"
#include "Swatch.h"
@ -1260,13 +1261,14 @@ void Application::processAvatarURLsMessage(unsigned char* packetData, size_t dat
return;
}
QDataStream in(QByteArray((char*)packetData, dataBytes));
QUrl voxelURL, faceURL;
QUrl voxelURL;
in >> voxelURL;
in >> faceURL;
// invoke the set URL functions on the simulate/render thread
QMetaObject::invokeMethod(avatar->getVoxels(), "setVoxelURL", Q_ARG(QUrl, voxelURL));
QMetaObject::invokeMethod(&avatar->getHead().getBlendFace(), "setModelURL", Q_ARG(QUrl, faceURL));
// use this timing to as the data-server for an updated mesh for this avatar (if we have UUID)
DataServerClient::getValueForKeyAndUUID(DataServerKey::FaceMeshURL, avatar->getUUID());
}
void Application::processAvatarFaceVideoMessage(unsigned char* packetData, size_t dataBytes) {
@ -1593,6 +1595,11 @@ void Application::init() {
_audio.setJitterBufferSamples(Menu::getInstance()->getAudioJitterBufferSamples());
}
qDebug("Loaded settings.\n");
if (!_profile.getUsername().isEmpty()) {
// we have a username for this avatar, ask the data-server for the mesh URL for this avatar
DataServerClient::getClientValueForKey(DataServerKey::FaceMeshURL);
}
// Set up VoxelSystem after loading preferences so we can get the desired max voxel count
_voxels.setMaxVoxels(Menu::getInstance()->getMaxVoxels());
@ -1602,7 +1609,7 @@ void Application::init() {
_voxels.init();
Avatar::sendAvatarURLsMessage(_myAvatar.getVoxels()->getVoxelURL(), _myAvatar.getHead().getBlendFace().getModelURL());
Avatar::sendAvatarURLsMessage(_myAvatar.getVoxels()->getVoxelURL());
_palette.init(_glWidget->width(), _glWidget->height());
_palette.addAction(Menu::getInstance()->getActionForOption(MenuOption::VoxelAddMode), 0, 0);
@ -2177,8 +2184,7 @@ void Application::updateAvatar(float deltaTime) {
// once in a while, send my urls
const float AVATAR_URLS_SEND_INTERVAL = 1.0f; // seconds
if (shouldDo(AVATAR_URLS_SEND_INTERVAL, deltaTime)) {
Avatar::sendAvatarURLsMessage(_myAvatar.getVoxels()->getVoxelURL(),
_myAvatar.getHead().getBlendFace().getModelURL());
Avatar::sendAvatarURLsMessage(_myAvatar.getVoxels()->getVoxelURL());
}
}
}
@ -3616,6 +3622,12 @@ void* Application::networkReceive(void* args) {
case PACKET_TYPE_AVATAR_FACE_VIDEO:
processAvatarFaceVideoMessage(app->_incomingPacket, bytesReceived);
break;
case PACKET_TYPE_DATA_SERVER_GET:
case PACKET_TYPE_DATA_SERVER_PUT:
case PACKET_TYPE_DATA_SERVER_SEND:
case PACKET_TYPE_DATA_SERVER_CONFIRM:
DataServerClient::processMessageFromDataServer(app->_incomingPacket, bytesReceived);
break;
default:
NodeList::getInstance()->processNodeData(&senderAddress, app->_incomingPacket, bytesReceived);
break;

View file

@ -44,6 +44,7 @@
#include "VoxelImporter.h"
#include "avatar/Avatar.h"
#include "avatar/MyAvatar.h"
#include "avatar/Profile.h"
#include "avatar/HandControl.h"
#include "devices/Faceshift.h"
#include "devices/SerialInterface.h"
@ -110,6 +111,7 @@ public:
QGLWidget* getGLWidget() { return _glWidget; }
MyAvatar* getAvatar() { return &_myAvatar; }
Profile* getProfile() { return &_profile; }
Audio* getAudio() { return &_audio; }
Camera* getCamera() { return &_myCamera; }
ViewFrustum* getViewFrustum() { return &_viewFrustum; }
@ -275,6 +277,7 @@ private:
Oscilloscope _audioScope;
MyAvatar _myAvatar; // The rendered avatar of oneself
Profile _profile; // The data-server linked profile for this user
Transmitter _myTransmitter; // Gets UDP data from transmitter app used to animate the avatar

View file

@ -0,0 +1,197 @@
//
// DataServerClient.cpp
// hifi
//
// Created by Stephen Birarda on 10/7/13.
// Copyright (c) 2013 HighFidelity, Inc. All rights reserved.
//
#include <QtCore/QUrl>
#include <NodeList.h>
#include <PacketHeaders.h>
#include <UDPSocket.h>
#include <UUID.h>
#include "Application.h"
#include "avatar/Profile.h"
#include "DataServerClient.h"
std::map<unsigned char*, int> DataServerClient::_unmatchedPackets;
const char DATA_SERVER_HOSTNAME[] = "data.highfidelity.io";
const unsigned short DATA_SERVER_PORT = 3282;
const sockaddr_in DATA_SERVER_SOCKET = socketForHostnameAndHostOrderPort(DATA_SERVER_HOSTNAME, DATA_SERVER_PORT);
void DataServerClient::putValueForKey(const char* key, const char* value) {
Profile* userProfile = Application::getInstance()->getProfile();
QString clientString = userProfile->getUUID().isNull()
? userProfile->getUsername()
: uuidStringWithoutCurlyBraces(userProfile->getUUID().toString());
if (!clientString.isEmpty()) {
unsigned char* putPacket = new unsigned char[MAX_PACKET_SIZE];
// setup the header for this packet
int numPacketBytes = populateTypeAndVersion(putPacket, PACKET_TYPE_DATA_SERVER_PUT);
// pack the client UUID, null terminated
memcpy(putPacket + numPacketBytes, clientString.toLocal8Bit().constData(), clientString.toLocal8Bit().size());
numPacketBytes += clientString.toLocal8Bit().size();
putPacket[numPacketBytes++] = '\0';
// pack the key, null terminated
strcpy((char*) putPacket + numPacketBytes, key);
numPacketBytes += strlen(key);
putPacket[numPacketBytes++] = '\0';
// pack the value, null terminated
strcpy((char*) putPacket + numPacketBytes, value);
numPacketBytes += strlen(value);
putPacket[numPacketBytes++] = '\0';
// add the putPacket to our vector of unconfirmed packets, will be deleted once put is confirmed
_unmatchedPackets.insert(std::pair<unsigned char*, int>(putPacket, numPacketBytes));
// send this put request to the data server
NodeList::getInstance()->getNodeSocket()->send((sockaddr*) &DATA_SERVER_SOCKET, putPacket, numPacketBytes);
}
}
void DataServerClient::getValueForKeyAndUUID(const char* key, const QUuid &uuid) {
if (!uuid.isNull()) {
getValueForKeyAndUserString(key, uuidStringWithoutCurlyBraces(uuid));
}
}
void DataServerClient::getValueForKeyAndUserString(const char* key, const QString& userString) {
unsigned char* getPacket = new unsigned char[MAX_PACKET_SIZE];
// setup the header for this packet
int numPacketBytes = populateTypeAndVersion(getPacket, PACKET_TYPE_DATA_SERVER_GET);
// pack the user string (could be username or UUID string), null-terminate
memcpy(getPacket + numPacketBytes, userString.toLocal8Bit().constData(), userString.toLocal8Bit().size());
numPacketBytes += userString.toLocal8Bit().size();
getPacket[numPacketBytes++] = '\0';
// pack the key, null terminated
strcpy((char*) getPacket + numPacketBytes, key);
int numKeyBytes = strlen(key);
if (numKeyBytes > 0) {
numPacketBytes += numKeyBytes;
getPacket[numPacketBytes++] = '\0';
}
// add the getPacket to our vector of uncofirmed packets, will be deleted once we get a response from the nameserver
_unmatchedPackets.insert(std::pair<unsigned char*, int>(getPacket, numPacketBytes));
// send the get to the data server
NodeList::getInstance()->getNodeSocket()->send((sockaddr*) &DATA_SERVER_SOCKET, getPacket, numPacketBytes);
}
void DataServerClient::getClientValueForKey(const char* key) {
getValueForKeyAndUserString(key, Application::getInstance()->getProfile()->getUsername());
}
void DataServerClient::processConfirmFromDataServer(unsigned char* packetData, int numPacketBytes) {
removeMatchedPacketFromMap(packetData, numPacketBytes);
}
void DataServerClient::processSendFromDataServer(unsigned char* packetData, int numPacketBytes) {
// pull the user string from the packet so we know who to associate this with
int numHeaderBytes = numBytesForPacketHeader(packetData);
char* userStringPosition = (char*) packetData + numHeaderBytes;
QString userString(QByteArray(userStringPosition, strlen(userStringPosition)));
QUuid userUUID(userString);
char* dataKeyPosition = (char*) packetData + numHeaderBytes + strlen(userStringPosition) + sizeof('\0');
char* dataValuePosition = dataKeyPosition + strlen(dataKeyPosition) + sizeof(char);
QString dataValueString(QByteArray(dataValuePosition,
numPacketBytes - ((unsigned char*) dataValuePosition - packetData)));
if (userUUID.isNull()) {
// the user string was a username
// for now assume this means that it is for our avatar
if (strcmp(dataKeyPosition, DataServerKey::FaceMeshURL) == 0) {
// pull the user's face mesh and set it on the Avatar instance
qDebug("Changing user's face model URL to %s\n", dataValueString.toLocal8Bit().constData());
Application::getInstance()->getProfile()->setFaceModelURL(QUrl(dataValueString));
} else if (strcmp(dataKeyPosition, DataServerKey::UUID) == 0) {
// this is the user's UUID - set it on the profile
Application::getInstance()->getProfile()->setUUID(dataValueString);
}
} else {
// user string was UUID, find matching avatar and associate data
if (strcmp(dataKeyPosition, DataServerKey::FaceMeshURL) == 0) {
NodeList* nodeList = NodeList::getInstance();
for (NodeList::iterator node = nodeList->begin(); node != nodeList->end(); node++) {
if (node->getLinkedData() != NULL && node->getType() == NODE_TYPE_AGENT) {
Avatar* avatar = (Avatar *) node->getLinkedData();
if (avatar->getUUID() == userUUID) {
QMetaObject::invokeMethod(&avatar->getHead().getBlendFace(),
"setModelURL",
Q_ARG(QUrl, QUrl(dataValueString)));
}
}
}
}
}
// remove the matched packet from our map so it isn't re-sent to the data-server
removeMatchedPacketFromMap(packetData, numPacketBytes);
}
void DataServerClient::processMessageFromDataServer(unsigned char* packetData, int numPacketBytes) {
switch (packetData[0]) {
case PACKET_TYPE_DATA_SERVER_SEND:
processSendFromDataServer(packetData, numPacketBytes);
break;
case PACKET_TYPE_DATA_SERVER_CONFIRM:
processConfirmFromDataServer(packetData, numPacketBytes);
break;
default:
break;
}
}
void DataServerClient::removeMatchedPacketFromMap(unsigned char* packetData, int numPacketBytes) {
for (std::map<unsigned char*, int>::iterator mapIterator = _unmatchedPackets.begin();
mapIterator != _unmatchedPackets.end();
++mapIterator) {
if (memcmp(mapIterator->first + sizeof(PACKET_TYPE),
packetData + sizeof(PACKET_TYPE),
numPacketBytes - sizeof(PACKET_TYPE)) == 0) {
// this is a match - remove the confirmed packet from the vector and delete associated member
// so it isn't sent back out
delete[] mapIterator->first;
_unmatchedPackets.erase(mapIterator);
// we've matched the packet - bail out
break;
}
}
}
void DataServerClient::resendUnmatchedPackets() {
for (std::map<unsigned char*, int>::iterator mapIterator = _unmatchedPackets.begin();
mapIterator != _unmatchedPackets.end();
++mapIterator) {
// send the unmatched packet to the data server
NodeList::getInstance()->getNodeSocket()->send((sockaddr*) &DATA_SERVER_SOCKET,
mapIterator->first,
mapIterator->second);
}
}

View file

@ -0,0 +1,38 @@
//
// DataServerClient.h
// hifi
//
// Created by Stephen Birarda on 10/7/13.
// Copyright (c) 2013 HighFidelity, Inc. All rights reserved.
//
#ifndef __hifi__DataServerClient__
#define __hifi__DataServerClient__
#include <map>
#include <QtCore/QUuid>
#include "Application.h"
class DataServerClient {
public:
static void putValueForKey(const char* key, const char* value);
static void getValueForKeyAndUUID(const char* key, const QUuid& uuid);
static void getValueForKeyAndUserString(const char* key, const QString& userString);
static void getClientValueForKey(const char* key);
static void processConfirmFromDataServer(unsigned char* packetData, int numPacketBytes);
static void processSendFromDataServer(unsigned char* packetData, int numPacketBytes);
static void processMessageFromDataServer(unsigned char* packetData, int numPacketBytes);
static void removeMatchedPacketFromMap(unsigned char* packetData, int numPacketBytes);
static void resendUnmatchedPackets();
private:
static std::map<unsigned char*, int> _unmatchedPackets;
};
namespace DataServerKey {
const char FaceMeshURL[] = "mesh";
const char UUID[] = "uuid";
}
#endif /* defined(__hifi__DataServerClient__) */

View file

@ -19,8 +19,12 @@
#include <QMainWindow>
#include <QSlider>
#include <QStandardPaths>
#include <QUuid>
#include <UUID.h>
#include "Application.h"
#include "DataServerClient.h"
#include "PairingHandler.h"
#include "Menu.h"
#include "Util.h"
@ -500,6 +504,7 @@ void Menu::loadSettings(QSettings* settings) {
settings->endGroup();
scanMenuBar(&loadAction, settings);
Application::getInstance()->getProfile()->loadData(settings);
Application::getInstance()->getAvatar()->loadData(settings);
Application::getInstance()->getSwatch()->loadData(settings);
}
@ -522,6 +527,7 @@ void Menu::saveSettings(QSettings* settings) {
scanMenuBar(&saveAction, settings);
Application::getInstance()->getAvatar()->saveData(settings);
Application::getInstance()->getProfile()->saveData(settings);
Application::getInstance()->getSwatch()->saveData(settings);
// ask the NodeList to save its data
@ -742,6 +748,7 @@ QLineEdit* lineEditForDomainHostname() {
void Menu::editPreferences() {
Application* applicationInstance = Application::getInstance();
QDialog dialog(applicationInstance->getGLWidget());
dialog.setWindowTitle("Interface Preferences");
QBoxLayout* layout = new QBoxLayout(QBoxLayout::TopToBottom);
@ -750,13 +757,19 @@ void Menu::editPreferences() {
QFormLayout* form = new QFormLayout();
layout->addLayout(form, 1);
QString avatarUsername = applicationInstance->getProfile()->getUsername();
QLineEdit* avatarUsernameEdit = new QLineEdit(avatarUsername);
avatarUsernameEdit->setMinimumWidth(QLINE_MINIMUM_WIDTH);
form->addRow("Username:", avatarUsernameEdit);
QLineEdit* avatarURL = new QLineEdit(applicationInstance->getAvatar()->getVoxels()->getVoxelURL().toString());
avatarURL->setMinimumWidth(QLINE_MINIMUM_WIDTH);
form->addRow("Avatar URL:", avatarURL);
QLineEdit* faceURL = new QLineEdit(applicationInstance->getAvatar()->getHead().getBlendFace().getModelURL().toString());
faceURL->setMinimumWidth(QLINE_MINIMUM_WIDTH);
form->addRow("Face URL:", faceURL);
QString faceURLString = applicationInstance->getProfile()->getFaceModelURL().toString();
QLineEdit* faceURLEdit = new QLineEdit(faceURLString);
faceURLEdit->setMinimumWidth(QLINE_MINIMUM_WIDTH);
form->addRow("Face URL:", faceURLEdit);
QSlider* pupilDilation = new QSlider(Qt::Horizontal);
pupilDilation->setValue(applicationInstance->getAvatar()->getHead().getPupilDilation() * pupilDilation->maximum());
@ -799,13 +812,32 @@ void Menu::editPreferences() {
return;
}
QUrl faceModelURL(faceURLEdit->text());
if (avatarUsernameEdit->text() != avatarUsername) {
// there has been a username change - set the new UUID on the avatar instance
applicationInstance->getProfile()->setUsername(avatarUsernameEdit->text());
if (faceModelURL.toString() == faceURLString && !avatarUsernameEdit->text().isEmpty()) {
// if there was no change to the face model URL then ask the data-server for what it is
DataServerClient::getClientValueForKey(DataServerKey::FaceMeshURL);
}
}
if (faceModelURL.toString() != faceURLString) {
// change the faceModelURL in the profile, it will also update this user's BlendFace
applicationInstance->getProfile()->setFaceModelURL(faceModelURL);
// send the new face mesh URL to the data-server (if we have a client UUID)
DataServerClient::putValueForKey(DataServerKey::FaceMeshURL,
faceModelURL.toString().toLocal8Bit().constData());
}
QUrl avatarVoxelURL(avatarURL->text());
applicationInstance->getAvatar()->getVoxels()->setVoxelURL(avatarVoxelURL);
QUrl faceModelURL(faceURL->text());
applicationInstance->getAvatar()->getHead().getBlendFace().setModelURL(faceModelURL);
Avatar::sendAvatarURLsMessage(avatarVoxelURL, faceModelURL);
Avatar::sendAvatarURLsMessage(avatarVoxelURL);
applicationInstance->getAvatar()->getHead().setPupilDilation(pupilDilation->value() / (float)pupilDilation->maximum());

View file

@ -18,6 +18,7 @@
#include "Application.h"
#include "Avatar.h"
#include "DataServerClient.h"
#include "Hand.h"
#include "Head.h"
#include "Physics.h"
@ -59,7 +60,7 @@ const int NUM_BODY_CONE_SIDES = 9;
const float chatMessageScale = 0.0015;
const float chatMessageHeight = 0.20;
void Avatar::sendAvatarURLsMessage(const QUrl& voxelURL, const QUrl& faceURL) {
void Avatar::sendAvatarURLsMessage(const QUrl& voxelURL) {
uint16_t ownerID = NodeList::getInstance()->getOwnerID();
if (ownerID == UNKNOWN_NODE_ID) {
@ -76,7 +77,6 @@ void Avatar::sendAvatarURLsMessage(const QUrl& voxelURL, const QUrl& faceURL) {
QDataStream out(&message, QIODevice::WriteOnly | QIODevice::Append);
out << voxelURL;
out << faceURL;
Application::controlledBroadcastToNodes((unsigned char*)message.data(), message.size(), &NODE_TYPE_AVATAR_MIXER, 1);
}
@ -751,31 +751,6 @@ void Avatar::renderBody(bool lookingInMirror, bool renderAvatarBalls) {
_hand.render(lookingInMirror);
}
void Avatar::loadData(QSettings* settings) {
settings->beginGroup("Avatar");
// in case settings is corrupt or missing loadSetting() will check for NaN
_bodyYaw = loadSetting(settings, "bodyYaw", 0.0f);
_bodyPitch = loadSetting(settings, "bodyPitch", 0.0f);
_bodyRoll = loadSetting(settings, "bodyRoll", 0.0f);
_position.x = loadSetting(settings, "position_x", 0.0f);
_position.y = loadSetting(settings, "position_y", 0.0f);
_position.z = loadSetting(settings, "position_z", 0.0f);
_voxels.setVoxelURL(settings->value("voxelURL").toUrl());
_head.getBlendFace().setModelURL(settings->value("faceModelURL").toUrl());
_head.setPupilDilation(settings->value("pupilDilation", 0.0f).toFloat());
_leanScale = loadSetting(settings, "leanScale", 0.05f);
_newScale = loadSetting(settings, "scale", 1.0f);
setScale(_scale);
Application::getInstance()->getCamera()->setScale(_scale);
settings->endGroup();
}
void Avatar::getBodyBallTransform(AvatarJointID jointID, glm::vec3& position, glm::quat& rotation) const {
position = _bodyBall[jointID].position;
rotation = _bodyBall[jointID].rotation;
@ -805,27 +780,6 @@ int Avatar::parseData(unsigned char* sourceBuffer, int numBytes) {
return bytesRead;
}
void Avatar::saveData(QSettings* set) {
set->beginGroup("Avatar");
set->setValue("bodyYaw", _bodyYaw);
set->setValue("bodyPitch", _bodyPitch);
set->setValue("bodyRoll", _bodyRoll);
set->setValue("position_x", _position.x);
set->setValue("position_y", _position.y);
set->setValue("position_z", _position.z);
set->setValue("voxelURL", _voxels.getVoxelURL());
set->setValue("faceModelURL", _head.getBlendFace().getModelURL());
set->setValue("pupilDilation", _head.getPupilDilation());
set->setValue("leanScale", _leanScale);
set->setValue("scale", _newScale);
set->endGroup();
}
// render a makeshift cone section that serves as a body part connecting joint spheres
void Avatar::renderJointConnectingCone(glm::vec3 position1, glm::vec3 position2, float radius1, float radius2) {

View file

@ -11,7 +11,7 @@
#include <glm/glm.hpp>
#include <glm/gtc/quaternion.hpp>
#include <QSettings>
#include <QtCore/QUuid>
#include <AvatarData.h>
@ -129,7 +129,7 @@ class Avatar : public AvatarData {
Q_OBJECT
public:
static void sendAvatarURLsMessage(const QUrl& voxelURL, const QUrl& faceURL);
static void sendAvatarURLsMessage(const QUrl& voxelURL);
Avatar(Node* owningNode = NULL);
~Avatar();
@ -155,10 +155,6 @@ public:
glm::quat getOrientation() const;
glm::quat getWorldAlignedOrientation() const;
AvatarVoxelSystem* getVoxels() { return &_voxels; }
// get/set avatar data
void saveData(QSettings* set);
void loadData(QSettings* set);
// Get the position/rotation of a single body ball
void getBodyBallTransform(AvatarJointID jointID, glm::vec3& position, glm::quat& rotation) const;
@ -247,6 +243,7 @@ private:
float _maxArmLength;
float _pelvisStandingHeight;
// private methods...
glm::vec3 calculateAverageEyePosition() { return _head.calculateAverageEyePosition(); } // get the position smack-dab between the eyes (for lookat)
float getBallRenderAlpha(int ball, bool lookingInMirror) const;

View file

@ -16,6 +16,7 @@
#include <SharedUtil.h>
#include "Application.h"
#include "DataServerClient.h"
#include "MyAvatar.h"
#include "Physics.h"
#include "devices/OculusManager.h"
@ -524,6 +525,50 @@ void MyAvatar::renderScreenTint(ScreenTintLayer layer, Camera& whichCamera) {
}
}
void MyAvatar::saveData(QSettings* settings) {
settings->beginGroup("Avatar");
settings->setValue("bodyYaw", _bodyYaw);
settings->setValue("bodyPitch", _bodyPitch);
settings->setValue("bodyRoll", _bodyRoll);
settings->setValue("position_x", _position.x);
settings->setValue("position_y", _position.y);
settings->setValue("position_z", _position.z);
settings->setValue("voxelURL", _voxels.getVoxelURL());
settings->setValue("pupilDilation", _head.getPupilDilation());
settings->setValue("leanScale", _leanScale);
settings->setValue("scale", _newScale);
settings->endGroup();
}
void MyAvatar::loadData(QSettings* settings) {
settings->beginGroup("Avatar");
// in case settings is corrupt or missing loadSetting() will check for NaN
_bodyYaw = loadSetting(settings, "bodyYaw", 0.0f);
_bodyPitch = loadSetting(settings, "bodyPitch", 0.0f);
_bodyRoll = loadSetting(settings, "bodyRoll", 0.0f);
_position.x = loadSetting(settings, "position_x", 0.0f);
_position.y = loadSetting(settings, "position_y", 0.0f);
_position.z = loadSetting(settings, "position_z", 0.0f);
_voxels.setVoxelURL(settings->value("voxelURL").toUrl());
_head.setPupilDilation(settings->value("pupilDilation", 0.0f).toFloat());
_leanScale = loadSetting(settings, "leanScale", 0.05f);
_newScale = loadSetting(settings, "scale", 1.0f);
setScale(_scale);
Application::getInstance()->getCamera()->setScale(_scale);
settings->endGroup();
}
float MyAvatar::getAbsoluteHeadYaw() const {
return glm::yaw(_head.getOrientation());
}

View file

@ -9,6 +9,8 @@
#ifndef __interface__myavatar__
#define __interface__myavatar__
#include <QSettings>
#include "Avatar.h"
class MyAvatar : public Avatar {
@ -47,6 +49,10 @@ public:
glm::vec3 getGravity() const { return _gravity; }
glm::vec3 getUprightHeadPosition() const;
glm::vec3 getUprightEyeLevelPosition() const;
// get/set avatar data
void saveData(QSettings* settings);
void loadData(QSettings* settings);
// Set what driving keys are being pressed to control thrust levels
void setDriveKeys(int key, bool val) { _driveKeys[key] = val; };
@ -57,7 +63,7 @@ public:
void addThrust(glm::vec3 newThrust) { _thrust += newThrust; };
glm::vec3 getThrust() { return _thrust; };
private:
private:
bool _mousePressed;
float _bodyPitchDelta;
float _bodyRollDelta;

View file

@ -0,0 +1,71 @@
//
// Profile.cpp
// hifi
//
// Created by Stephen Birarda on 10/8/13.
// Copyright (c) 2013 HighFidelity, Inc. All rights reserved.
//
#include <QtCore/QSettings>
#include "Profile.h"
#include "DataServerClient.h"
Profile::Profile() :
_username(),
_uuid(),
_faceModelURL()
{
}
void Profile::clear() {
_username.clear();
_uuid = QUuid();
_faceModelURL.clear();
}
void Profile::setUsername(const QString &username) {
this->clear();
_username = username;
if (!_username.isEmpty()) {
// we've been given a new username, ask the data-server for our UUID
DataServerClient::getClientValueForKey(DataServerKey::UUID);
}
}
void Profile::setUUID(const QUuid& uuid) {
_uuid = uuid;
// when the UUID is changed we need set it appropriately on our avatar instance
Application::getInstance()->getAvatar()->setUUID(_uuid);
}
void Profile::setFaceModelURL(const QUrl& faceModelURL) {
_faceModelURL = faceModelURL;
QMetaObject::invokeMethod(&Application::getInstance()->getAvatar()->getHead().getBlendFace(),
"setModelURL",
Q_ARG(QUrl, _faceModelURL));
}
void Profile::saveData(QSettings* settings) {
settings->beginGroup("Profile");
settings->setValue("username", _username);
settings->setValue("UUID", _uuid);
settings->setValue("faceModelURL", _faceModelURL);
settings->endGroup();
}
void Profile::loadData(QSettings* settings) {
settings->beginGroup("Profile");
_username = settings->value("username").toString();
this->setUUID(settings->value("UUID").toUuid());
_faceModelURL = settings->value("faceModelURL").toUrl();
settings->endGroup();
}

View file

@ -0,0 +1,39 @@
//
// Profile.h
// hifi
//
// Created by Stephen Birarda on 10/8/13.
// Copyright (c) 2013 HighFidelity, Inc. All rights reserved.
//
#ifndef __hifi__Profile__
#define __hifi__Profile__
#include <QtCore/QString>
#include <QtCore/QUrl>
#include <QtCore/QUuid>
class Profile {
public:
Profile();
void setUsername(const QString& username);
QString& getUsername() { return _username; }
void setUUID(const QUuid& uuid);
QUuid& getUUID() { return _uuid; }
void setFaceModelURL(const QUrl& faceModelURL);
QUrl& getFaceModelURL() { return _faceModelURL; }
void clear();
void saveData(QSettings* settings);
void loadData(QSettings* settings);
private:
QString _username;
QUuid _uuid;
QUrl _faceModelURL;
};
#endif /* defined(__hifi__Profile__) */

View file

@ -23,6 +23,7 @@ static const float fingerVectorRadix = 4; // bits of precision when converting f
AvatarData::AvatarData(Node* owningNode) :
NodeData(owningNode),
_uuid(),
_handPosition(0,0,0),
_bodyYaw(-90.0),
_bodyPitch(0.0),
@ -116,6 +117,11 @@ int AvatarData::getBroadcastData(unsigned char* destinationBuffer) {
_handData = new HandData(this);
}
// UUID
QByteArray uuidByteArray = _uuid.toRfc4122();
memcpy(destinationBuffer, uuidByteArray.constData(), uuidByteArray.size());
destinationBuffer += uuidByteArray.size();
// Body world position
memcpy(destinationBuffer, &_position, sizeof(float) * 3);
destinationBuffer += sizeof(float) * 3;
@ -249,6 +255,11 @@ int AvatarData::parseData(unsigned char* sourceBuffer, int numBytes) {
// push past the node ID
sourceBuffer += sizeof(uint16_t);
// UUID
const int NUM_BYTES_RFC4122_UUID = 16;
_uuid = QUuid::fromRfc4122(QByteArray((char*) sourceBuffer, NUM_BYTES_RFC4122_UUID));
sourceBuffer += NUM_BYTES_RFC4122_UUID;
// Body world position
memcpy(&_position, sourceBuffer, sizeof(float) * 3);
sourceBuffer += sizeof(float) * 3;
@ -259,7 +270,7 @@ int AvatarData::parseData(unsigned char* sourceBuffer, int numBytes) {
sourceBuffer += unpackFloatAngleFromTwoByte((uint16_t*) sourceBuffer, &_bodyRoll);
// Body scale
sourceBuffer += unpackFloatRatioFromTwoByte( sourceBuffer, _newScale);
sourceBuffer += unpackFloatRatioFromTwoByte(sourceBuffer, _newScale);
// Follow mode info
memcpy(&_leaderID, sourceBuffer, sizeof(uint16_t));

View file

@ -17,6 +17,7 @@
#include <glm/gtc/quaternion.hpp>
#include <QtCore/QObject>
#include <QtCore/QUuid>
#include <QtCore/QVariantMap>
#include <NodeData.h>
@ -72,6 +73,9 @@ public:
int getBroadcastData(unsigned char* destinationBuffer);
int parseData(unsigned char* sourceBuffer, int numBytes);
QUuid& getUUID() { return _uuid; }
void setUUID(const QUuid& uuid) { _uuid = uuid; }
// Body Rotation
float getBodyYaw() const { return _bodyYaw; }
void setBodyYaw(float bodyYaw) { _bodyYaw = bodyYaw; }
@ -79,7 +83,6 @@ public:
void setBodyPitch(float bodyPitch) { _bodyPitch = bodyPitch; }
float getBodyRoll() const { return _bodyRoll; }
void setBodyRoll(float bodyRoll) { _bodyRoll = bodyRoll; }
// Hand State
void setHandState(char s) { _handState = s; }
@ -133,6 +136,8 @@ public slots:
void setWantOcclusionCulling(bool wantOcclusionCulling) { _wantOcclusionCulling = wantOcclusionCulling; }
protected:
QUuid _uuid;
glm::vec3 _position;
glm::vec3 _handPosition;

View file

@ -139,10 +139,6 @@ void Assignment::setPayload(const uchar* payload, int numBytes) {
memcpy(_payload, payload, _numPayloadBytes);
}
QString Assignment::getUUIDStringWithoutCurlyBraces() const {
return _uuid.toString().mid(1, _uuid.toString().length() - 2);
}
int Assignment::packToBuffer(unsigned char* buffer) {
int numPackedBytes = 0;

View file

@ -60,7 +60,6 @@ public:
void setUUID(const QUuid& uuid) { _uuid = uuid; }
const QUuid& getUUID() const { return _uuid; }
QString getUUIDStringWithoutCurlyBraces() const;
void resetUUID() { _uuid = QUuid::createUuid(); }
Assignment::Command getCommand() const { return _command; }

View file

@ -20,7 +20,7 @@ PACKET_VERSION versionForPacketType(PACKET_TYPE type) {
return 1;
case PACKET_TYPE_HEAD_DATA:
return 8;
return 9;
case PACKET_TYPE_AVATAR_URLS:
return 1;

View file

@ -41,6 +41,10 @@ const PACKET_TYPE PACKET_TYPE_DEPLOY_ASSIGNMENT = 'd';
const PACKET_TYPE PACKET_TYPE_VOXEL_STATS = '#';
const PACKET_TYPE PACKET_TYPE_VOXEL_JURISDICTION = 'J';
const PACKET_TYPE PACKET_TYPE_VOXEL_JURISDICTION_REQUEST = 'j';
const PACKET_TYPE PACKET_TYPE_DATA_SERVER_PUT = 'p';
const PACKET_TYPE PACKET_TYPE_DATA_SERVER_GET = 'g';
const PACKET_TYPE PACKET_TYPE_DATA_SERVER_SEND = 'u';
const PACKET_TYPE PACKET_TYPE_DATA_SERVER_CONFIRM = 'c';
typedef char PACKET_VERSION;

View file

@ -0,0 +1,14 @@
//
// UUID.cpp
// hifi
//
// Created by Stephen Birarda on 10/7/13.
// Copyright (c) 2013 HighFidelity, Inc. All rights reserved.
//
#include "UUID.h"
QString uuidStringWithoutCurlyBraces(const QUuid& uuid) {
QString uuidStringNoBraces = uuid.toString().mid(1, uuid.toString().length() - 2);
return uuidStringNoBraces;
}

View file

@ -0,0 +1,16 @@
//
// UUID.h
// hifi
//
// Created by Stephen Birarda on 10/7/13.
// Copyright (c) 2013 HighFidelity, Inc. All rights reserved.
//
#ifndef __hifi__UUID__
#define __hifi__UUID__
#include <QtCore/QUuid>
QString uuidStringWithoutCurlyBraces(const QUuid& uuid);
#endif /* defined(__hifi__UUID__) */