This commit is contained in:
Stephen Birarda 2015-02-24 12:27:21 -08:00
commit 5750d4bad0
62 changed files with 3140 additions and 2600 deletions

View file

@ -194,7 +194,7 @@ void Agent::run() {
// setup an Avatar for the script to use // setup an Avatar for the script to use
ScriptableAvatar scriptedAvatar(&_scriptEngine); ScriptableAvatar scriptedAvatar(&_scriptEngine);
scriptedAvatar.setForceFaceshiftConnected(true); scriptedAvatar.setForceFaceTrackerConnected(true);
// call model URL setters with empty URLs so our avatar, if user, will have the default models // call model URL setters with empty URLs so our avatar, if user, will have the default models
scriptedAvatar.setFaceModelURL(QUrl()); scriptedAvatar.setFaceModelURL(QUrl());

View file

@ -18,10 +18,10 @@
#include <AccountManager.h> #include <AccountManager.h>
#include <AddressManager.h> #include <AddressManager.h>
#include <Assignment.h> #include <Assignment.h>
#include <AvatarHashMap.h>
#include <HifiConfigVariantMap.h> #include <HifiConfigVariantMap.h>
#include <LogHandler.h> #include <LogHandler.h>
#include <LogUtils.h> #include <LogUtils.h>
#include <LimitedNodeList.h>
#include <NodeList.h> #include <NodeList.h>
#include <PacketHeaders.h> #include <PacketHeaders.h>
#include <SharedUtil.h> #include <SharedUtil.h>
@ -43,7 +43,8 @@ int hifiSockAddrMeta = qRegisterMetaType<HifiSockAddr>("HifiSockAddr");
AssignmentClient::AssignmentClient(int &argc, char **argv) : AssignmentClient::AssignmentClient(int &argc, char **argv) :
QCoreApplication(argc, argv), QCoreApplication(argc, argv),
_assignmentServerHostname(DEFAULT_ASSIGNMENT_SERVER_HOSTNAME), _assignmentServerHostname(DEFAULT_ASSIGNMENT_SERVER_HOSTNAME),
_localASPortSharedMem(NULL) _localASPortSharedMem(NULL),
_localACMPortSharedMem(NULL)
{ {
LogUtils::init(); LogUtils::init();
@ -56,7 +57,11 @@ AssignmentClient::AssignmentClient(int &argc, char **argv) :
DependencyManager::registerInheritance<LimitedNodeList, NodeList>(); DependencyManager::registerInheritance<LimitedNodeList, NodeList>();
auto addressManager = DependencyManager::set<AddressManager>(); auto addressManager = DependencyManager::set<AddressManager>();
auto nodeList = DependencyManager::set<NodeList>(NodeType::Unassigned); auto nodeList = DependencyManager::set<NodeList>(NodeType::Unassigned);
auto avatarHashMap = DependencyManager::set<AvatarHashMap>();
// make up a uuid for this child so the parent can tell us apart. This id will be changed
// when the domain server hands over an assignment.
QUuid nodeUUID = QUuid::createUuid();
nodeList->setSessionUUID(nodeUUID);
// setup a shutdown event listener to handle SIGTERM or WM_CLOSE for us // setup a shutdown event listener to handle SIGTERM or WM_CLOSE for us
#ifdef _WIN32 #ifdef _WIN32
@ -123,9 +128,8 @@ AssignmentClient::AssignmentClient(int &argc, char **argv) :
// call a timer function every ASSIGNMENT_REQUEST_INTERVAL_MSECS to ask for assignment, if required // call a timer function every ASSIGNMENT_REQUEST_INTERVAL_MSECS to ask for assignment, if required
qDebug() << "Waiting for assignment -" << _requestAssignment; qDebug() << "Waiting for assignment -" << _requestAssignment;
QTimer* timer = new QTimer(this); connect(&_requestTimer, SIGNAL(timeout()), SLOT(sendAssignmentRequest()));
connect(timer, SIGNAL(timeout()), SLOT(sendAssignmentRequest())); _requestTimer.start(ASSIGNMENT_REQUEST_INTERVAL_MSECS);
timer->start(ASSIGNMENT_REQUEST_INTERVAL_MSECS);
// connect our readPendingDatagrams method to the readyRead() signal of the socket // connect our readPendingDatagrams method to the readyRead() signal of the socket
connect(&nodeList->getNodeSocket(), &QUdpSocket::readyRead, this, &AssignmentClient::readPendingDatagrams); connect(&nodeList->getNodeSocket(), &QUdpSocket::readyRead, this, &AssignmentClient::readPendingDatagrams);
@ -136,6 +140,45 @@ AssignmentClient::AssignmentClient(int &argc, char **argv) :
// Create Singleton objects on main thread // Create Singleton objects on main thread
NetworkAccessManager::getInstance(); NetworkAccessManager::getInstance();
// Hook up a timer to send this child's status to the Monitor once per second
setUpStatsToMonitor();
}
void AssignmentClient::stopAssignmentClient() {
qDebug() << "Exiting.";
_requestTimer.stop();
_statsTimerACM.stop();
quit();
}
void AssignmentClient::setUpStatsToMonitor() {
// Figure out the address to send out stats to
quint16 localMonitorServerPort = DEFAULT_ASSIGNMENT_CLIENT_MONITOR_PORT;
auto nodeList = DependencyManager::get<NodeList>();
nodeList->getLocalServerPortFromSharedMemory(ASSIGNMENT_CLIENT_MONITOR_LOCAL_PORT_SMEM_KEY,
_localACMPortSharedMem, localMonitorServerPort);
_assignmentClientMonitorSocket = HifiSockAddr(DEFAULT_ASSIGNMENT_CLIENT_MONITOR_HOSTNAME, localMonitorServerPort, true);
// send a stats packet every 1 seconds
connect(&_statsTimerACM, &QTimer::timeout, this, &AssignmentClient::sendStatsPacketToACM);
_statsTimerACM.start(1000);
}
void AssignmentClient::sendStatsPacketToACM() {
// tell the assignment client monitor what this assignment client is doing (if anything)
QJsonObject statsObject;
auto nodeList = DependencyManager::get<NodeList>();
if (_currentAssignment) {
statsObject["assignment_type"] = _currentAssignment->getTypeName();
} else {
statsObject["assignment_type"] = "none";
}
nodeList->sendStats(statsObject, _assignmentClientMonitorSocket);
} }
void AssignmentClient::sendAssignmentRequest() { void AssignmentClient::sendAssignmentRequest() {
@ -145,23 +188,9 @@ void AssignmentClient::sendAssignmentRequest() {
if (_assignmentServerHostname == "localhost") { if (_assignmentServerHostname == "localhost") {
// we want to check again for the local domain-server port in case the DS has restarted // we want to check again for the local domain-server port in case the DS has restarted
if (!_localASPortSharedMem) {
_localASPortSharedMem = new QSharedMemory(DOMAIN_SERVER_LOCAL_PORT_SMEM_KEY, this);
if (!_localASPortSharedMem->attach(QSharedMemory::ReadOnly)) {
qWarning() << "Could not attach to shared memory at key" << DOMAIN_SERVER_LOCAL_PORT_SMEM_KEY
<< "- will attempt to connect to domain-server on" << _assignmentServerSocket.getPort();
}
}
if (_localASPortSharedMem->isAttached()) {
_localASPortSharedMem->lock();
quint16 localAssignmentServerPort; quint16 localAssignmentServerPort;
memcpy(&localAssignmentServerPort, _localASPortSharedMem->data(), sizeof(localAssignmentServerPort)); if (nodeList->getLocalServerPortFromSharedMemory(DOMAIN_SERVER_LOCAL_PORT_SMEM_KEY, _localASPortSharedMem,
localAssignmentServerPort)) {
_localASPortSharedMem->unlock();
if (localAssignmentServerPort != _assignmentServerSocket.getPort()) { if (localAssignmentServerPort != _assignmentServerSocket.getPort()) {
qDebug() << "Port for local assignment server read from shared memory is" qDebug() << "Port for local assignment server read from shared memory is"
<< localAssignmentServerPort; << localAssignmentServerPort;
@ -170,7 +199,9 @@ void AssignmentClient::sendAssignmentRequest() {
nodeList->setAssignmentServerSocket(_assignmentServerSocket); nodeList->setAssignmentServerSocket(_assignmentServerSocket);
} }
} }
else {
qDebug () << "- will attempt to connect to domain-server on" << _assignmentServerSocket.getPort();
}
} }
nodeList->sendAssignment(_requestAssignment); nodeList->sendAssignment(_requestAssignment);
@ -227,6 +258,14 @@ void AssignmentClient::readPendingDatagrams() {
} else { } else {
qDebug() << "Received an assignment that could not be unpacked. Re-requesting."; qDebug() << "Received an assignment that could not be unpacked. Re-requesting.";
} }
} else if (packetTypeForPacket(receivedPacket) == PacketTypeStopNode) {
if (senderSockAddr.getAddress() == QHostAddress::LocalHost ||
senderSockAddr.getAddress() == QHostAddress::LocalHostIPv6) {
qDebug() << "Network told me to exit.";
emit stopAssignmentClient();
} else {
qDebug() << "Got a stop packet from other than localhost.";
}
} else { } else {
// have the NodeList attempt to handle it // have the NodeList attempt to handle it
nodeList->processNodeData(senderSockAddr, receivedPacket); nodeList->processNodeData(senderSockAddr, receivedPacket);

View file

@ -29,13 +29,22 @@ private slots:
void readPendingDatagrams(); void readPendingDatagrams();
void assignmentCompleted(); void assignmentCompleted();
void handleAuthenticationRequest(); void handleAuthenticationRequest();
void sendStatsPacketToACM();
void stopAssignmentClient();
private: private:
void setUpStatsToMonitor();
Assignment _requestAssignment; Assignment _requestAssignment;
static SharedAssignmentPointer _currentAssignment; static SharedAssignmentPointer _currentAssignment;
QString _assignmentServerHostname; QString _assignmentServerHostname;
HifiSockAddr _assignmentServerSocket; HifiSockAddr _assignmentServerSocket;
QSharedMemory* _localASPortSharedMem; QSharedMemory* _localASPortSharedMem; // memory shared with domain server
QSharedMemory* _localACMPortSharedMem; // memory shared with assignment client monitor
QTimer _requestTimer; // timer for requesting and assignment
QTimer _statsTimerACM; // timer for sending stats to assignment client monitor
protected:
HifiSockAddr _assignmentClientMonitorSocket;
}; };
#endif // hifi_AssignmentClient_h #endif // hifi_AssignmentClient_h

View file

@ -0,0 +1,66 @@
//
// AssignmentClientapp.cpp
// assignment-client/src
//
// Created by Seth Alves on 2/19/15.
// Copyright 2015 High Fidelity, Inc.
//
// Distributed under the Apache License, Version 2.0.
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
//
#include <QCommandLineParser>
#include <LogHandler.h>
#include <SharedUtil.h>
#include "Assignment.h"
#include "AssignmentClient.h"
#include "AssignmentClientMonitor.h"
#include "AssignmentClientApp.h"
AssignmentClientApp::AssignmentClientApp(int argc, char* argv[]) :
QCoreApplication(argc, argv)
{
# ifndef WIN32
setvbuf(stdout, NULL, _IOLBF, 0);
# endif
// use the verbose message handler in Logging
qInstallMessageHandler(LogHandler::verboseMessageHandler);
// parse command-line
QCommandLineParser parser;
parser.setApplicationDescription("High Fidelity Assignment Client");
parser.addHelpOption();
const QCommandLineOption helpOption = parser.addHelpOption();
const QCommandLineOption numChildsOption("n", "number of children to fork", "child-count");
parser.addOption(numChildsOption);
if (!parser.parse(QCoreApplication::arguments())) {
qCritical() << parser.errorText() << endl;
parser.showHelp();
Q_UNREACHABLE();
}
if (parser.isSet(helpOption)) {
parser.showHelp();
Q_UNREACHABLE();
}
unsigned int numForks = 0;
if (parser.isSet(numChildsOption)) {
numForks = parser.value(numChildsOption).toInt();
}
if (numForks) {
AssignmentClientMonitor monitor(argc, argv, numForks);
monitor.exec();
} else {
AssignmentClient client(argc, argv);
client.exec();
}
}

View file

@ -0,0 +1,18 @@
//
// AssignmentClientapp.h
// assignment-client/src
//
// Created by Seth Alves on 2/19/15.
// Copyright 2015 High Fidelity, Inc.
//
// Distributed under the Apache License, Version 2.0.
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
//
#include <QApplication>
class AssignmentClientApp : public QCoreApplication {
Q_OBJECT
public:
AssignmentClientApp(int argc, char* argv[]);
};

View file

@ -0,0 +1,8 @@
#include "AssignmentClientChildData.h"
AssignmentClientChildData::AssignmentClientChildData(QString childType) :
_childType(childType)
{
}

View file

@ -0,0 +1,32 @@
//
// AssignmentClientChildData.h
// assignment-client/src
//
// Created by Seth Alves on 2/23/2015.
// Copyright 2015 High Fidelity, Inc.
//
// Distributed under the Apache License, Version 2.0.
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
//
#ifndef hifi_AssignmentClientChildData_h
#define hifi_AssignmentClientChildData_h
#include <Assignment.h>
class AssignmentClientChildData : public NodeData {
public:
AssignmentClientChildData(QString childType);
QString getChildType() { return _childType; }
void setChildType(QString childType) { _childType = childType; }
// implement parseData to return 0 so we can be a subclass of NodeData
int parseData(const QByteArray& packet) { return 0; }
private:
QString _childType;
};
#endif // hifi_AssignmentClientChildData_h

View file

@ -13,14 +13,18 @@
#include <LogHandler.h> #include <LogHandler.h>
#include <ShutdownEventListener.h> #include <ShutdownEventListener.h>
#include <AddressManager.h>
#include "AssignmentClientMonitor.h" #include "AssignmentClientMonitor.h"
#include "AssignmentClientChildData.h"
#include "PacketHeaders.h"
#include "SharedUtil.h"
const char* NUM_FORKS_PARAMETER = "-n"; const char* NUM_FORKS_PARAMETER = "-n";
const QString ASSIGNMENT_CLIENT_MONITOR_TARGET_NAME = "assignment-client-monitor"; const QString ASSIGNMENT_CLIENT_MONITOR_TARGET_NAME = "assignment-client-monitor";
AssignmentClientMonitor::AssignmentClientMonitor(int &argc, char **argv, int numAssignmentClientForks) : AssignmentClientMonitor::AssignmentClientMonitor(int &argc, char **argv, const unsigned int numAssignmentClientForks) :
QCoreApplication(argc, argv) QCoreApplication(argc, argv)
{ {
// start the Logging class with the parent's target name // start the Logging class with the parent's target name
@ -42,10 +46,24 @@ AssignmentClientMonitor::AssignmentClientMonitor(int &argc, char **argv, int num
_childArguments.removeAt(forksParameterIndex); _childArguments.removeAt(forksParameterIndex);
_childArguments.removeAt(forksParameterIndex); _childArguments.removeAt(forksParameterIndex);
// create a NodeList so we can receive stats from children
DependencyManager::registerInheritance<LimitedNodeList, NodeList>();
auto addressManager = DependencyManager::set<AddressManager>();
auto nodeList = DependencyManager::set<LimitedNodeList>(DEFAULT_ASSIGNMENT_CLIENT_MONITOR_PORT,
DEFAULT_ASSIGNMENT_CLIENT_MONITOR_DTLS_PORT);
connect(&nodeList->getNodeSocket(), &QUdpSocket::readyRead, this, &AssignmentClientMonitor::readPendingDatagrams);
nodeList->putLocalPortIntoSharedMemory(ASSIGNMENT_CLIENT_MONITOR_LOCAL_PORT_SMEM_KEY, this);
// use QProcess to fork off a process for each of the child assignment clients // use QProcess to fork off a process for each of the child assignment clients
for (int i = 0; i < numAssignmentClientForks; i++) { for (unsigned int i = 0; i < numAssignmentClientForks; i++) {
spawnChildClient(); spawnChildClient();
} }
connect(&_checkSparesTimer, SIGNAL(timeout()), SLOT(checkSpares()));
_checkSparesTimer.start(NODE_SILENCE_THRESHOLD_MSECS * 3);
} }
AssignmentClientMonitor::~AssignmentClientMonitor() { AssignmentClientMonitor::~AssignmentClientMonitor() {
@ -53,46 +71,122 @@ AssignmentClientMonitor::~AssignmentClientMonitor() {
} }
void AssignmentClientMonitor::stopChildProcesses() { void AssignmentClientMonitor::stopChildProcesses() {
auto nodeList = DependencyManager::get<NodeList>();
QList<QPointer<QProcess> >::Iterator it = _childProcesses.begin(); nodeList->eachNode([&](const SharedNodePointer& node) {
while (it != _childProcesses.end()) { qDebug() << "asking child" << node->getUUID() << "to exit.";
if (!it->isNull()) { node->activateLocalSocket();
qDebug() << "Monitor is terminating child process" << it->data(); QByteArray diePacket = byteArrayWithPopulatedHeader(PacketTypeStopNode);
nodeList->writeUnverifiedDatagram(diePacket, *node->getActiveSocket());
// don't re-spawn this child when it goes down });
disconnect(it->data(), 0, this, 0);
it->data()->terminate();
it->data()->waitForFinished();
}
it = _childProcesses.erase(it);
}
} }
void AssignmentClientMonitor::spawnChildClient() { void AssignmentClientMonitor::spawnChildClient() {
QProcess *assignmentClient = new QProcess(this); QProcess *assignmentClient = new QProcess(this);
_childProcesses.append(QPointer<QProcess>(assignmentClient));
// make sure that the output from the child process appears in our output // make sure that the output from the child process appears in our output
assignmentClient->setProcessChannelMode(QProcess::ForwardedChannels); assignmentClient->setProcessChannelMode(QProcess::ForwardedChannels);
assignmentClient->start(applicationFilePath(), _childArguments); assignmentClient->start(applicationFilePath(), _childArguments);
// link the child processes' finished slot to our childProcessFinished slot
connect(assignmentClient, SIGNAL(finished(int, QProcess::ExitStatus)), this,
SLOT(childProcessFinished(int, QProcess::ExitStatus)));
qDebug() << "Spawned a child client with PID" << assignmentClient->pid(); qDebug() << "Spawned a child client with PID" << assignmentClient->pid();
} }
void AssignmentClientMonitor::childProcessFinished(int exitCode, QProcess::ExitStatus exitStatus) {
qDebug("Replacing dead child assignment client with a new one");
// remove the old process from our list of child processes
qDebug() << "need to remove" << QPointer<QProcess>(qobject_cast<QProcess*>(sender()));
_childProcesses.removeOne(QPointer<QProcess>(qobject_cast<QProcess*>(sender())));
void AssignmentClientMonitor::checkSpares() {
auto nodeList = DependencyManager::get<NodeList>();
QUuid aSpareId = "";
unsigned int spareCount = 0;
nodeList->removeSilentNodes();
nodeList->eachNode([&](const SharedNodePointer& node) {
AssignmentClientChildData *childData = static_cast<AssignmentClientChildData*>(node->getLinkedData());
if (childData->getChildType() == "none") {
spareCount ++;
aSpareId = node->getUUID();
}
});
if (spareCount != 1) {
qDebug() << "spare count is" << spareCount;
}
if (spareCount < 1) {
spawnChildClient(); spawnChildClient();
}
if (spareCount > 1) {
// kill aSpareId
qDebug() << "asking child" << aSpareId << "to exit.";
SharedNodePointer childNode = nodeList->nodeWithUUID(aSpareId);
childNode->activateLocalSocket();
QByteArray diePacket = byteArrayWithPopulatedHeader(PacketTypeStopNode);
nodeList->writeUnverifiedDatagram(diePacket, childNode);
}
} }
void AssignmentClientMonitor::readPendingDatagrams() {
auto nodeList = DependencyManager::get<NodeList>();
QByteArray receivedPacket;
HifiSockAddr senderSockAddr;
while (nodeList->getNodeSocket().hasPendingDatagrams()) {
receivedPacket.resize(nodeList->getNodeSocket().pendingDatagramSize());
nodeList->getNodeSocket().readDatagram(receivedPacket.data(), receivedPacket.size(),
senderSockAddr.getAddressPointer(), senderSockAddr.getPortPointer());
if (nodeList->packetVersionAndHashMatch(receivedPacket)) {
if (packetTypeForPacket(receivedPacket) == PacketTypeNodeJsonStats) {
QUuid packetUUID = uuidFromPacketHeader(receivedPacket);
SharedNodePointer matchingNode = nodeList->sendingNodeForPacket(receivedPacket);
if (!matchingNode) {
// The parent only expects to be talking with prorams running on this same machine.
if (senderSockAddr.getAddress() == QHostAddress::LocalHost ||
senderSockAddr.getAddress() == QHostAddress::LocalHostIPv6) {
if (!packetUUID.isNull()) {
matchingNode = DependencyManager::get<LimitedNodeList>()->addOrUpdateNode
(packetUUID, NodeType::Unassigned, senderSockAddr, senderSockAddr, false);
AssignmentClientChildData *childData = new AssignmentClientChildData("unknown");
matchingNode->setLinkedData(childData);
} else {
// tell unknown assignment-client child to exit.
qDebug() << "asking unknown child to exit.";
QByteArray diePacket = byteArrayWithPopulatedHeader(PacketTypeStopNode);
nodeList->writeUnverifiedDatagram(diePacket, senderSockAddr);
}
}
}
if (matchingNode) {
// update our records about how to reach this child
matchingNode->setLocalSocket(senderSockAddr);
// push past the packet header
QDataStream packetStream(receivedPacket);
packetStream.skipRawData(numBytesForPacketHeader(receivedPacket));
// decode json
QVariantMap unpackedVariantMap;
packetStream >> unpackedVariantMap;
QJsonObject unpackedStatsJSON = QJsonObject::fromVariantMap(unpackedVariantMap);
// get child's assignment type out of the decoded json
QString childType = unpackedStatsJSON["assignment_type"].toString();
AssignmentClientChildData *childData =
static_cast<AssignmentClientChildData*>(matchingNode->getLinkedData());
childData->setChildType(childType);
// note when this child talked
matchingNode->setLastHeardMicrostamp(usecTimestampNow());
}
} else {
// have the NodeList attempt to handle it
nodeList->processNodeData(senderSockAddr, receivedPacket);
}
}
}
}

View file

@ -15,25 +15,30 @@
#include <QtCore/QCoreApplication> #include <QtCore/QCoreApplication>
#include <QtCore/qpointer.h> #include <QtCore/qpointer.h>
#include <QtCore/QProcess> #include <QtCore/QProcess>
#include <QtCore/QDateTime>
#include <Assignment.h> #include <Assignment.h>
#include "AssignmentClientChildData.h"
extern const char* NUM_FORKS_PARAMETER; extern const char* NUM_FORKS_PARAMETER;
class AssignmentClientMonitor : public QCoreApplication { class AssignmentClientMonitor : public QCoreApplication {
Q_OBJECT Q_OBJECT
public: public:
AssignmentClientMonitor(int &argc, char **argv, int numAssignmentClientForks); AssignmentClientMonitor(int &argc, char **argv, const unsigned int numAssignmentClientForks);
~AssignmentClientMonitor(); ~AssignmentClientMonitor();
void stopChildProcesses(); void stopChildProcesses();
private slots: private slots:
void childProcessFinished(int exitCode, QProcess::ExitStatus exitStatus); void readPendingDatagrams();
void checkSpares();
private: private:
void spawnChildClient(); void spawnChildClient();
QList<QPointer<QProcess> > _childProcesses;
QStringList _childArguments; QStringList _childArguments;
QTimer _checkSparesTimer; // every few seconds see if it need fewer or more spare children
}; };
#endif // hifi_AssignmentClientMonitor_h #endif // hifi_AssignmentClientMonitor_h

View file

@ -9,34 +9,10 @@
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
// //
#include <LogHandler.h>
#include <SharedUtil.h>
#include "Assignment.h" #include "AssignmentClientApp.h"
#include "AssignmentClient.h"
#include "AssignmentClientMonitor.h"
int main(int argc, char* argv[]) { int main(int argc, char* argv[]) {
#ifndef WIN32 AssignmentClientApp app(argc, argv);
setvbuf(stdout, NULL, _IOLBF, 0); return 0;
#endif
// use the verbose message handler in Logging
qInstallMessageHandler(LogHandler::verboseMessageHandler);
const char* numForksString = getCmdOption(argc, (const char**)argv, NUM_FORKS_PARAMETER);
int numForks = 0;
if (numForksString) {
numForks = atoi(numForksString);
}
if (numForks) {
AssignmentClientMonitor monitor(argc, argv, numForks);
return monitor.exec();
} else {
AssignmentClient client(argc, argv);
return client.exec();
}
} }

View file

@ -246,19 +246,7 @@ void DomainServer::setupNodeListAndAssignments(const QUuid& sessionUUID) {
auto nodeList = DependencyManager::set<LimitedNodeList>(domainServerPort, domainServerDTLSPort); auto nodeList = DependencyManager::set<LimitedNodeList>(domainServerPort, domainServerDTLSPort);
// no matter the local port, save it to shared mem so that local assignment clients can ask what it is // no matter the local port, save it to shared mem so that local assignment clients can ask what it is
QSharedMemory* sharedPortMem = new QSharedMemory(DOMAIN_SERVER_LOCAL_PORT_SMEM_KEY, this); nodeList->putLocalPortIntoSharedMemory(DOMAIN_SERVER_LOCAL_PORT_SMEM_KEY, this);
quint16 localPort = nodeList->getNodeSocket().localPort();
// attempt to create the shared memory segment
if (sharedPortMem->create(sizeof(localPort)) || sharedPortMem->attach()) {
sharedPortMem->lock();
memcpy(sharedPortMem->data(), &localPort, sizeof(localPort));
sharedPortMem->unlock();
qDebug() << "Wrote local listening port" << localPort << "to shared memory at key" << DOMAIN_SERVER_LOCAL_PORT_SMEM_KEY;
} else {
qWarning() << "Failed to create and attach to shared memory to share local port with assignment-client children.";
}
// set our LimitedNodeList UUID to match the UUID from our config // set our LimitedNodeList UUID to match the UUID from our config
// nodes will currently use this to add resources to data-web that relate to our domain // nodes will currently use this to add resources to data-web that relate to our domain

View file

@ -29,15 +29,21 @@ var RIGHT_BUTTON_FWD = 11;
var RIGHT_BUTTON_3 = 9; var RIGHT_BUTTON_3 = 9;
var BALL_RADIUS = 0.08; var BALL_RADIUS = 0.08;
var GRAVITY_STRENGTH = 1.0; var GRAVITY_STRENGTH = 3.0;
var HELD_COLOR = { red: 240, green: 0, blue: 0 }; var HELD_COLOR = { red: 240, green: 0, blue: 0 };
var THROWN_COLOR = { red: 128, green: 0, blue: 0 }; var THROWN_COLOR = { red: 128, green: 0, blue: 0 };
var averageLinearVelocity = [ { x: 0, y: 0, z : 0 }, { x: 0, y: 0, z : 0 } ];
var LIFETIME_SECONDS = 600;
var BALL_MODEL_URL = "https://hifi-public.s3.amazonaws.com/ryan/baseball4.fbx";
var leftBallAlreadyInHand = false; var leftBallAlreadyInHand = false;
var rightBallAlreadyInHand = false; var rightBallAlreadyInHand = false;
var leftHandEntity; var leftHandEntity = false;
var rightHandEntity; var rightHandEntity = false;
var newSound = SoundCache.getSound("https://dl.dropboxusercontent.com/u/1864924/hifi-sounds/throw.raw"); var newSound = SoundCache.getSound("https://dl.dropboxusercontent.com/u/1864924/hifi-sounds/throw.raw");
var catchSound = SoundCache.getSound("https://dl.dropboxusercontent.com/u/1864924/hifi-sounds/catch.raw"); var catchSound = SoundCache.getSound("https://dl.dropboxusercontent.com/u/1864924/hifi-sounds/catch.raw");
@ -67,28 +73,51 @@ function checkControllerSide(whichSide) {
var BUTTON_3; var BUTTON_3;
var TRIGGER; var TRIGGER;
var palmPosition; var palmPosition;
var palmRotation;
var ballAlreadyInHand; var ballAlreadyInHand;
var handMessage; var handMessage;
var linearVelocity;
var angularVelocity;
var AVERAGE_FACTOR = 0.33;
if (whichSide == LEFT_PALM) { if (whichSide == LEFT_PALM) {
BUTTON_FWD = LEFT_BUTTON_FWD; BUTTON_FWD = LEFT_BUTTON_FWD;
BUTTON_3 = LEFT_BUTTON_3; BUTTON_3 = LEFT_BUTTON_3;
TRIGGER = 0; TRIGGER = 0;
palmPosition = Controller.getSpatialControlPosition(LEFT_PALM); palmPosition = Controller.getSpatialControlPosition(LEFT_PALM);
palmRotation = Quat.multiply(MyAvatar.orientation, Controller.getSpatialControlRawRotation(LEFT_PALM));
ballAlreadyInHand = leftBallAlreadyInHand; ballAlreadyInHand = leftBallAlreadyInHand;
handMessage = "LEFT"; handMessage = "LEFT";
averageLinearVelocity[0] = Vec3.sum(Vec3.multiply(AVERAGE_FACTOR, Controller.getSpatialControlVelocity(LEFT_TIP)),
Vec3.multiply(1.0 - AVERAGE_FACTOR, averageLinearVelocity[0]));
linearVelocity = averageLinearVelocity[0];
angularVelocity = Vec3.multiplyQbyV(MyAvatar.orientation, Controller.getSpatialControlRawAngularVelocity(LEFT_TIP));
angularVelocity = Vec3.multiply(180.0 / Math.PI, angularVelocity);
} else { } else {
BUTTON_FWD = RIGHT_BUTTON_FWD; BUTTON_FWD = RIGHT_BUTTON_FWD;
BUTTON_3 = RIGHT_BUTTON_3; BUTTON_3 = RIGHT_BUTTON_3;
TRIGGER = 1; TRIGGER = 1;
palmPosition = Controller.getSpatialControlPosition(RIGHT_PALM); palmPosition = Controller.getSpatialControlPosition(RIGHT_PALM);
palmRotation = Quat.multiply(MyAvatar.orientation, Controller.getSpatialControlRawRotation(RIGHT_PALM));
ballAlreadyInHand = rightBallAlreadyInHand; ballAlreadyInHand = rightBallAlreadyInHand;
averageLinearVelocity[1] = Vec3.sum(Vec3.multiply(AVERAGE_FACTOR, Controller.getSpatialControlVelocity(RIGHT_TIP)),
Vec3.multiply(1.0 - AVERAGE_FACTOR, averageLinearVelocity[1]));
linearVelocity = averageLinearVelocity[1];
angularVelocity = Vec3.multiplyQbyV(MyAvatar.orientation, Controller.getSpatialControlRawAngularVelocity(RIGHT_TIP));
angularVelocity = Vec3.multiply(180.0 / Math.PI, angularVelocity);
handMessage = "RIGHT"; handMessage = "RIGHT";
} }
var grabButtonPressed = (Controller.isButtonPressed(BUTTON_FWD) || Controller.isButtonPressed(BUTTON_3) || (Controller.getTriggerValue(TRIGGER) > 0.5)); var grabButtonPressed = (Controller.isButtonPressed(BUTTON_FWD) || Controller.isButtonPressed(BUTTON_3) || (Controller.getTriggerValue(TRIGGER) > 0.5));
// If I don't currently have a ball in my hand, then try to catch closest one // If I don't currently have a ball in my hand, then try to catch closest one
if (leftHandEntity && !leftHandEntity.isKnownID) {
leftHandEntity = Entities.identifyEntity(leftHandEntity);
}
if (rightHandEntity && !rightHandEntity.isKnownID) {
rightHandEntity = Entities.identifyEntity(rightHandEntity);
}
if (!ballAlreadyInHand && grabButtonPressed) { if (!ballAlreadyInHand && grabButtonPressed) {
var closestEntity = Entities.findClosestEntity(palmPosition, targetRadius); var closestEntity = Entities.findClosestEntity(palmPosition, targetRadius);
@ -107,10 +136,11 @@ function checkControllerSide(whichSide) {
var properties = { position: { x: ballPosition.x, var properties = { position: { x: ballPosition.x,
y: ballPosition.y, y: ballPosition.y,
z: ballPosition.z }, z: ballPosition.z },
rotation: palmRotation,
color: HELD_COLOR, color: HELD_COLOR,
velocity : { x: 0, y: 0, z: 0}, velocity : { x: 0, y: 0, z: 0},
lifetime : 600, gravity: { x: 0, y: 0, z: 0}
inHand: true }; };
Entities.editEntity(closestEntity, properties); Entities.editEntity(closestEntity, properties);
Audio.playSound(catchSound, { position: ballPosition }); Audio.playSound(catchSound, { position: ballPosition });
@ -129,18 +159,20 @@ function checkControllerSide(whichSide) {
if (grabButtonPressed && !ballAlreadyInHand) { if (grabButtonPressed && !ballAlreadyInHand) {
var ballPosition = getBallHoldPosition(whichSide); var ballPosition = getBallHoldPosition(whichSide);
var properties = { var properties = {
type: "Sphere", type: "Model",
modelURL: BALL_MODEL_URL,
position: { x: ballPosition.x, position: { x: ballPosition.x,
y: ballPosition.y, y: ballPosition.y,
z: ballPosition.z }, z: ballPosition.z },
rotation: palmRotation,
velocity: { x: 0, y: 0, z: 0}, velocity: { x: 0, y: 0, z: 0},
gravity: { x: 0, y: 0, z: 0}, gravity: { x: 0, y: 0, z: 0},
inHand: true,
dimensions: { x: BALL_RADIUS * 2, y: BALL_RADIUS * 2, z: BALL_RADIUS * 2 }, dimensions: { x: BALL_RADIUS * 2, y: BALL_RADIUS * 2, z: BALL_RADIUS * 2 },
damping: 0.00001, damping: 0.00001,
shapeType: "sphere",
collisionsWillMove: false,
color: HELD_COLOR, color: HELD_COLOR,
lifetime: LIFETIME_SECONDS
lifetime: 600 // 10 seconds - same as default, not needed but here as an example
}; };
newEntity = Entities.addEntity(properties); newEntity = Entities.addEntity(properties);
@ -174,21 +206,20 @@ function checkControllerSide(whichSide) {
var properties = { position: { x: ballPosition.x, var properties = { position: { x: ballPosition.x,
y: ballPosition.y, y: ballPosition.y,
z: ballPosition.z }, z: ballPosition.z },
rotation: palmRotation,
velocity: { x: 0, y: 0, z: 0},
gravity: { x: 0, y: 0, z: 0},
}; };
Entities.editEntity(handEntity, properties); Entities.editEntity(handEntity, properties);
} else { } else {
debugPrint(">>>>> " + handMessage + "-BALL IN HAND, not grabbing, THROW!!!"); debugPrint(">>>>> " + handMessage + "-BALL IN HAND, not grabbing, THROW!!!");
// If toy ball just released, add velocity to it! // If toy ball just released, add velocity to it!
var tipVelocity = Controller.getSpatialControlVelocity(whichTip);
var THROWN_VELOCITY_SCALING = 1.5;
var properties = { var properties = {
velocity: { x: tipVelocity.x * THROWN_VELOCITY_SCALING, velocity: linearVelocity,
y: tipVelocity.y * THROWN_VELOCITY_SCALING, rotation: palmRotation,
z: tipVelocity.z * THROWN_VELOCITY_SCALING } , angularVelocity: angularVelocity,
collisionsWillMove: true, collisionsWillMove: true,
inHand: false,
color: THROWN_COLOR, color: THROWN_COLOR,
lifetime: 10,
gravity: { x: 0, y: -GRAVITY_STRENGTH, z: 0}, gravity: { x: 0, y: -GRAVITY_STRENGTH, z: 0},
}; };
@ -216,7 +247,7 @@ function checkController(deltaTime) {
// this is expected for hydras // this is expected for hydras
if (!(numberOfButtons==12 && numberOfTriggers == 2 && controllersPerTrigger == 2)) { if (!(numberOfButtons==12 && numberOfTriggers == 2 && controllersPerTrigger == 2)) {
debugPrint("no hydra connected?"); debugPrint("total buttons = " + numberOfButtons + ", Triggers = " + numberOfTriggers + ", controllers/trigger = " + controllersPerTrigger);
return; // bail if no hydra return; // bail if no hydra
} }

View file

@ -53,8 +53,10 @@ function shootDice(position, velocity) {
position: position, position: position,
velocity: velocity, velocity: velocity,
rotation: Quat.fromPitchYawRollDegrees(Math.random() * 360, Math.random() * 360, Math.random() * 360), rotation: Quat.fromPitchYawRollDegrees(Math.random() * 360, Math.random() * 360, Math.random() * 360),
angularVelocity: { x: Math.random() * 100, y: Math.random() * 100, z: Math.random() * 100 },
lifetime: LIFETIME, lifetime: LIFETIME,
gravity: { x: 0, y: GRAVITY, z: 0 }, gravity: { x: 0, y: GRAVITY, z: 0 },
shapeType: "box",
collisionsWillMove: true collisionsWillMove: true
})); }));
position = Vec3.sum(position, Vec3.multiply(DIE_SIZE, Vec3.normalize(Quat.getRight(Camera.getOrientation())))); position = Vec3.sum(position, Vec3.multiply(DIE_SIZE, Vec3.normalize(Quat.getRight(Camera.getOrientation()))));

View file

@ -105,37 +105,27 @@ function makeTable(pos) {
} }
function makeBalls(pos) { function makeBalls(pos) {
var colors = [{ red: 255, green: 255, blue: 0}, // Yellow
{ red: 0, green: 0, blue: 255}, // Blue
{ red: 255, green: 0, blue: 0}, // Red
{ red: 128, green: 0, blue: 128}, // Purple
{ red: 255, green: 165, blue: 0}, // Orange
{ red: 0, green: 255, blue: 0}, // Green
{ red: 128, green: 0, blue: 0}, // Maroon
{ red: 0, green: 0, blue: 0}, // Black
{ red: 255, green: 255, blue: 224}, // Light Yellow
{ red: 173, green: 216, blue: 230}, // Light Blue
{ red: 205, green: 92, blue: 92}, // Indian Red
{ red: 218, green: 112, blue: 214}, // Orchid
{ red: 218, green: 165, blue: 32}, // GoldenRod
{ red: 255, green: 99, blue: 71}, // Tomato
{ red: 128, green: 128, blue: 128}]; // Gray
// Object balls // Object balls
var whichBall = [ 1, 14, 15, 4, 8, 7, 12, 9, 3, 13, 10, 5, 6, 11, 2 ];
var ballNumber = 0;
var ballPosition = { x: pos.x + (LENGTH / 4.0) * SCALE, y: pos.y + HEIGHT / 2.0 + DROP_HEIGHT, z: pos.z }; var ballPosition = { x: pos.x + (LENGTH / 4.0) * SCALE, y: pos.y + HEIGHT / 2.0 + DROP_HEIGHT, z: pos.z };
for (var row = 1; row <= 5; row++) { for (var row = 1; row <= 5; row++) {
ballPosition.z = pos.z - ((row - 1.0) / 2.0 * (BALL_SIZE + BALL_GAP) * SCALE); ballPosition.z = pos.z - ((row - 1.0) / 2.0 * (BALL_SIZE + BALL_GAP) * SCALE);
for (var spot = 0; spot < row; spot++) { for (var spot = 0; spot < row; spot++) {
balls.push(Entities.addEntity( balls.push(Entities.addEntity(
{ type: "Sphere", { type: "Model",
modelURL: "https://s3.amazonaws.com/hifi-public/models/props/Pool/ball_" + whichBall[ballNumber].toString() + ".fbx",
position: ballPosition, position: ballPosition,
dimensions: { x: BALL_SIZE * SCALE, y: BALL_SIZE * SCALE, z: BALL_SIZE * SCALE }, dimensions: { x: BALL_SIZE * SCALE, y: BALL_SIZE * SCALE, z: BALL_SIZE * SCALE },
color: colors[balls.length], rotation: Quat.fromPitchYawRollDegrees((Math.random() - 0.5) * 20, (Math.random() - 0.5) * 20, (Math.random() - 0.5) * 20),
color: { red: 255, green: 255, blue: 255 },
gravity: { x: 0, y: GRAVITY, z: 0 }, gravity: { x: 0, y: GRAVITY, z: 0 },
ignoreCollisions: false, ignoreCollisions: false,
damping: 0.50, damping: 0.50,
shapeType: "sphere",
collisionsWillMove: true })); collisionsWillMove: true }));
ballPosition.z += (BALL_SIZE + BALL_GAP) * SCALE; ballPosition.z += (BALL_SIZE + BALL_GAP) * SCALE;
ballNumber++;
} }
ballPosition.x += (BALL_GAP + Math.sqrt(3.0) / 2.0 * BALL_SIZE) * SCALE; ballPosition.x += (BALL_GAP + Math.sqrt(3.0) / 2.0 * BALL_SIZE) * SCALE;
} }
@ -143,7 +133,8 @@ function makeBalls(pos) {
// Cue Ball // Cue Ball
cuePosition = { x: pos.x - (LENGTH / 4.0) * SCALE, y: pos.y + HEIGHT / 2.0 + DROP_HEIGHT, z: pos.z }; cuePosition = { x: pos.x - (LENGTH / 4.0) * SCALE, y: pos.y + HEIGHT / 2.0 + DROP_HEIGHT, z: pos.z };
cueBall = Entities.addEntity( cueBall = Entities.addEntity(
{ type: "Sphere", { type: "Model",
modelURL: "https://s3.amazonaws.com/hifi-public/models/props/Pool/cue_ball.fbx",
position: cuePosition, position: cuePosition,
dimensions: { x: BALL_SIZE * SCALE, y: BALL_SIZE * SCALE, z: BALL_SIZE * SCALE }, dimensions: { x: BALL_SIZE * SCALE, y: BALL_SIZE * SCALE, z: BALL_SIZE * SCALE },
color: { red: 255, green: 255, blue: 255 }, color: { red: 255, green: 255, blue: 255 },
@ -152,6 +143,7 @@ function makeBalls(pos) {
velocity: {x: 0, y: 0, z: 0 }, velocity: {x: 0, y: 0, z: 0 },
ignoreCollisions: false, ignoreCollisions: false,
damping: 0.50, damping: 0.50,
shapeType: "sphere",
collisionsWillMove: true }); collisionsWillMove: true });
} }

View file

@ -406,7 +406,7 @@
elModelAnimationFrame.addEventListener('change', createEmitNumberPropertyUpdateFunction('animationFrameIndex')); elModelAnimationFrame.addEventListener('change', createEmitNumberPropertyUpdateFunction('animationFrameIndex'));
elModelAnimationSettings.addEventListener('change', createEmitTextPropertyUpdateFunction('animationSettings')); elModelAnimationSettings.addEventListener('change', createEmitTextPropertyUpdateFunction('animationSettings'));
elModelTextures.addEventListener('change', createEmitTextPropertyUpdateFunction('textures')); elModelTextures.addEventListener('change', createEmitTextPropertyUpdateFunction('textures'));
elModelShapeType.addEventListener('change', createEmitNumberPropertyUpdateFunction('shapeType')); elModelShapeType.addEventListener('change', createEmitTextPropertyUpdateFunction('shapeType'));
elTextText.addEventListener('change', createEmitTextPropertyUpdateFunction('text')); elTextText.addEventListener('change', createEmitTextPropertyUpdateFunction('text'));
elTextLineHeight.addEventListener('change', createEmitNumberPropertyUpdateFunction('lineHeight')); elTextLineHeight.addEventListener('change', createEmitNumberPropertyUpdateFunction('lineHeight'));
@ -671,9 +671,9 @@
<div class="label">Shape Type</div> <div class="label">Shape Type</div>
<div class="value"> <div class="value">
<select name="SelectShapeType" id="property-model-shape" name="SelectShapeType"> <select name="SelectShapeType" id="property-model-shape" name="SelectShapeType">
<option value=0>None</option> <option value='none'>none</option>
<option value=1>Box</option> <option value='box'>box</option>
<option value=2>Sphere</option> <option value='sphere'>sphere</option>
</select> </select>
</div> </div>
</div> </div>

View file

@ -477,7 +477,7 @@ CameraManager = function() {
// Last mode that was first or third person // Last mode that was first or third person
var lastAvatarCameraMode = "first person"; var lastAvatarCameraMode = "first person";
Camera.modeUpdated.connect(function(newMode) { Camera.modeUpdated.connect(function(newMode) {
if (newMode == "first person" || newMode == "third person") { if (newMode != "independent") {
lastAvatarCameraMode = newMode; lastAvatarCameraMode = newMode;
that.disable(true); that.disable(true);
} else { } else {

View file

@ -84,7 +84,7 @@ var users = [];
var ctrlIsPressed = false; var ctrlIsPressed = false;
var ready = true; var ready = true;
var randomSounds = new SoundArray({}, true); var randomSounds = new SoundArray({ localOnly: true }, true);
var numberOfSounds = 2; var numberOfSounds = 2;
for (var i = 1; i <= numberOfSounds; i++) { for (var i = 1; i <= numberOfSounds; i++) {
randomSounds.addSound(HIFI_PUBLIC_BUCKET + "sounds/UI/notification-general" + i + ".raw"); randomSounds.addSound(HIFI_PUBLIC_BUCKET + "sounds/UI/notification-general" + i + ".raw");

View file

@ -13,9 +13,14 @@ You may optionally choose to place this folder in a location outside the reposit
If so our CMake find module expects you to set the ENV variable 'HIFI_LIB_DIR' to a directory containing a subfolder faceshift that contains the lib and include folders. If so our CMake find module expects you to set the ENV variable 'HIFI_LIB_DIR' to a directory containing a subfolder faceshift that contains the lib and include folders.
1. Build a Faceshift static library from the fsbinarystream.cpp file. If you build a release version call it libfaceshift.a. The debug version should be called libfaceshiftd.a. Place this in the lib folder in your Faceshift folder. 1. Build a Faceshift static library from the fsbinarystream.cpp file.
Windows: Win32 console application; no precompiled header or SDL checks; no ATL or MFC headers; Project Properties, Configuration Type = Static Library (.lib).
2. Copy the fsbinarystream.h header file from the Faceshift SDK into the include folder in your Faceshift folder. 2. Copy the library files to the lib folder in your Faceshift folder.
OSX: If you build a release version call it libfaceshift.a. The debug version should be called libfaceshiftd.a.
Windows: The release and debug versions should be called faceshift.lib and faceshiftd.lib, respectively. Copy them into a Win32 folder in your lib folder.
3. Clear your build directory, run cmake and build, and you should be all set. 3. Copy the fsbinarystream.h header file from the Faceshift SDK into the include folder in your Faceshift folder.
4. Clear your build directory, run cmake and build, and you should be all set.

View file

@ -1624,6 +1624,16 @@ FaceTracker* Application::getActiveFaceTracker() {
(visage->isActive() ? static_cast<FaceTracker*>(visage.data()) : NULL))); (visage->isActive() ? static_cast<FaceTracker*>(visage.data()) : NULL)));
} }
void Application::setActiveFaceTracker() {
#ifdef HAVE_FACESHIFT
DependencyManager::get<Faceshift>()->setTCPEnabled(Menu::getInstance()->isOptionChecked(MenuOption::Faceshift));
#endif
DependencyManager::get<DdeFaceTracker>()->setEnabled(Menu::getInstance()->isOptionChecked(MenuOption::DDEFaceRegression));
#ifdef HAVE_VISAGE
DependencyManager::get<Visage>()->updateEnabled();
#endif
}
bool Application::exportEntities(const QString& filename, float x, float y, float z, float scale) { bool Application::exportEntities(const QString& filename, float x, float y, float z, float scale) {
QVector<EntityItem*> entities; QVector<EntityItem*> entities;
_entities.getTree()->findEntities(AACube(glm::vec3(x / (float)TREE_SCALE, _entities.getTree()->findEntities(AACube(glm::vec3(x / (float)TREE_SCALE,
@ -1741,6 +1751,7 @@ void Application::init() {
// initialize our face trackers after loading the menu settings // initialize our face trackers after loading the menu settings
DependencyManager::get<Faceshift>()->init(); DependencyManager::get<Faceshift>()->init();
DependencyManager::get<DdeFaceTracker>()->init();
DependencyManager::get<Visage>()->init(); DependencyManager::get<Visage>()->init();
Leapmotion::init(); Leapmotion::init();

View file

@ -366,6 +366,8 @@ public slots:
void notifyPacketVersionMismatch(); void notifyPacketVersionMismatch();
void setActiveFaceTracker();
private slots: private slots:
void clearDomainOctreeDetails(); void clearDomainOctreeDetails();
void checkFPS(); void checkFPS();

View file

@ -27,6 +27,7 @@
#include "audio/AudioIOStatsRenderer.h" #include "audio/AudioIOStatsRenderer.h"
#include "audio/AudioScope.h" #include "audio/AudioScope.h"
#include "avatar/AvatarManager.h" #include "avatar/AvatarManager.h"
#include "devices/DdeFaceTracker.h"
#include "devices/Faceshift.h" #include "devices/Faceshift.h"
#include "devices/RealSense.h" #include "devices/RealSense.h"
#include "devices/SixenseManager.h" #include "devices/SixenseManager.h"
@ -357,18 +358,35 @@ Menu::Menu() {
dialogsManager.data(), SLOT(lodTools())); dialogsManager.data(), SLOT(lodTools()));
QMenu* avatarDebugMenu = developerMenu->addMenu("Avatar"); QMenu* avatarDebugMenu = developerMenu->addMenu("Avatar");
QMenu* faceTrackingMenu = avatarDebugMenu->addMenu("Face Tracking");
{
QActionGroup* faceTrackerGroup = new QActionGroup(avatarDebugMenu);
QAction* noFaceTracker = addCheckableActionToQMenuAndActionHash(faceTrackingMenu, MenuOption::NoFaceTracking,
0, true,
qApp, SLOT(setActiveFaceTracker()));
faceTrackerGroup->addAction(noFaceTracker);
#ifdef HAVE_FACESHIFT #ifdef HAVE_FACESHIFT
addCheckableActionToQMenuAndActionHash(avatarDebugMenu, QAction* faceshiftFaceTracker = addCheckableActionToQMenuAndActionHash(faceTrackingMenu, MenuOption::Faceshift,
MenuOption::Faceshift, 0, false,
0, qApp, SLOT(setActiveFaceTracker()));
true, faceTrackerGroup->addAction(faceshiftFaceTracker);
DependencyManager::get<Faceshift>().data(),
SLOT(setTCPEnabled(bool)));
#endif #endif
QAction* ddeFaceTracker = addCheckableActionToQMenuAndActionHash(faceTrackingMenu, MenuOption::DDEFaceRegression,
0, false,
qApp, SLOT(setActiveFaceTracker()));
faceTrackerGroup->addAction(ddeFaceTracker);
#ifdef HAVE_VISAGE #ifdef HAVE_VISAGE
addCheckableActionToQMenuAndActionHash(avatarDebugMenu, MenuOption::Visage, 0, false, QAction* visageFaceTracker = addCheckableActionToQMenuAndActionHash(faceTrackingMenu, MenuOption::Visage,
DependencyManager::get<Visage>().data(), SLOT(updateEnabled())); 0, false,
qApp, SLOT(setActiveFaceTracker()));
faceTrackerGroup->addAction(visageFaceTracker);
#endif #endif
}
addCheckableActionToQMenuAndActionHash(avatarDebugMenu, MenuOption::RenderSkeletonCollisionShapes); addCheckableActionToQMenuAndActionHash(avatarDebugMenu, MenuOption::RenderSkeletonCollisionShapes);
addCheckableActionToQMenuAndActionHash(avatarDebugMenu, MenuOption::RenderHeadCollisionShapes); addCheckableActionToQMenuAndActionHash(avatarDebugMenu, MenuOption::RenderHeadCollisionShapes);

View file

@ -133,13 +133,12 @@ namespace MenuOption {
const QString CollideWithEnvironment = "Collide With World Boundaries"; const QString CollideWithEnvironment = "Collide With World Boundaries";
const QString Collisions = "Collisions"; const QString Collisions = "Collisions";
const QString Console = "Console..."; const QString Console = "Console...";
const QString ControlWithSpeech = "Control With Speech";
const QString CopyAddress = "Copy Address to Clipboard"; const QString CopyAddress = "Copy Address to Clipboard";
const QString CopyPath = "Copy Path to Clipboard"; const QString CopyPath = "Copy Path to Clipboard";
const QString ControlWithSpeech = "Control With Speech"; const QString DDEFaceRegression = "DDE Face Regression";
const QString DeleteBookmark = "Delete Bookmark...";
const QString DontRenderEntitiesAsScene = "Don't Render Entities as Scene";
const QString DontDoPrecisionPicking = "Don't Do Precision Picking";
const QString DecreaseAvatarSize = "Decrease Avatar Size"; const QString DecreaseAvatarSize = "Decrease Avatar Size";
const QString DeleteBookmark = "Delete Bookmark...";
const QString DisableActivityLogger = "Disable Activity Logger"; const QString DisableActivityLogger = "Disable Activity Logger";
const QString DisableAutoAdjustLOD = "Disable Automatically Adjusting LOD"; const QString DisableAutoAdjustLOD = "Disable Automatically Adjusting LOD";
const QString DisableLightEntities = "Disable Light Entities"; const QString DisableLightEntities = "Disable Light Entities";
@ -152,7 +151,9 @@ namespace MenuOption {
const QString DisplayModelElementChildProxies = "Display Model Element Children"; const QString DisplayModelElementChildProxies = "Display Model Element Children";
const QString DisplayModelElementProxy = "Display Model Element Bounds"; const QString DisplayModelElementProxy = "Display Model Element Bounds";
const QString DisplayTimingDetails = "Display Timing Details"; const QString DisplayTimingDetails = "Display Timing Details";
const QString DontDoPrecisionPicking = "Don't Do Precision Picking";
const QString DontFadeOnOctreeServerChanges = "Don't Fade In/Out on Octree Server Changes"; const QString DontFadeOnOctreeServerChanges = "Don't Fade In/Out on Octree Server Changes";
const QString DontRenderEntitiesAsScene = "Don't Render Entities as Scene";
const QString EchoLocalAudio = "Echo Local Audio"; const QString EchoLocalAudio = "Echo Local Audio";
const QString EchoServerAudio = "Echo Server Audio"; const QString EchoServerAudio = "Echo Server Audio";
const QString EditEntitiesHelp = "Edit Entities Help..."; const QString EditEntitiesHelp = "Edit Entities Help...";
@ -192,6 +193,7 @@ namespace MenuOption {
const QString MuteEnvironment = "Mute Environment"; const QString MuteEnvironment = "Mute Environment";
const QString NetworkSimulator = "Network Simulator..."; const QString NetworkSimulator = "Network Simulator...";
const QString NewVoxelCullingMode = "New Voxel Culling Mode"; const QString NewVoxelCullingMode = "New Voxel Culling Mode";
const QString NoFaceTracking = "None";
const QString ObeyEnvironmentalGravity = "Obey Environmental Gravity"; const QString ObeyEnvironmentalGravity = "Obey Environmental Gravity";
const QString OctreeStats = "Voxel and Entity Statistics"; const QString OctreeStats = "Voxel and Entity Statistics";
const QString OffAxisProjection = "Off-Axis Projection"; const QString OffAxisProjection = "Off-Axis Projection";

View file

@ -12,6 +12,9 @@
#include <QStyle> #include <QStyle>
#include <QStyleOptionTitleBar> #include <QStyleOptionTitleBar>
#include "DependencyManager.h"
#include "GLCanvas.h"
#include "UIUtil.h" #include "UIUtil.h"
int UIUtil::getWindowTitleBarHeight(const QWidget* window) { int UIUtil::getWindowTitleBarHeight(const QWidget* window) {
@ -27,3 +30,49 @@ int UIUtil::getWindowTitleBarHeight(const QWidget* window) {
return titleBarHeight; return titleBarHeight;
} }
// When setting the font size of a widget in points, the rendered text will be larger
// on Windows and Linux than on Mac OSX. This is because Windows and Linux use a DPI
// of 96, while OSX uses 72. In order to get consistent results across platforms, the
// font sizes need to be scaled based on the system DPI.
// This function will scale the font size of widget and all
// of its children recursively.
//
// When creating widgets, if a font size isn't explicitly set Qt will choose a
// reasonable, but often different font size across platforms. This means
// YOU SHOUD EXPLICITLY SET ALL FONT SIZES and call this function OR not use
// this function at all. If you mix both you will end up with inconsistent results
// across platforms.
void UIUtil::scaleWidgetFontSizes(QWidget* widget) {
auto glCanvas = DependencyManager::get<GLCanvas>();
// This is the base dpi that we are targetting. This is based on Mac OSXs default DPI,
// and is the basis for all font sizes.
const float BASE_DPI = 72.0f;
#ifdef Q_OS_MAC
const float NATIVE_DPI = 72.0f;
#else
const float NATIVE_DPI = 96.0f;
#endif
// Scale fonts based on the native dpi. On Windows, where the native DPI is 96,
// the scale will be: 72.0 / 96.0 = 0.75
float fontScale = BASE_DPI / NATIVE_DPI;
internalScaleWidgetFontSizes(widget, fontScale);
}
// Depth-first traversal through widget hierarchy. It is important to do a depth-first
// traversal because modifying the font size of a parent node can affect children.
void UIUtil::internalScaleWidgetFontSizes(QWidget* widget, float scale) {
for (auto child : widget->findChildren<QWidget*>()) {
if (child->parent() == widget) {
internalScaleWidgetFontSizes(child, scale);
}
}
QFont font = widget->font();
font.setPointSizeF(font.pointSizeF() * scale);
widget->setFont(font);
}

View file

@ -18,7 +18,10 @@
class UIUtil { class UIUtil {
public: public:
static int getWindowTitleBarHeight(const QWidget* window); static int getWindowTitleBarHeight(const QWidget* window);
static void scaleWidgetFontSizes(QWidget* widget);
private:
static void internalScaleWidgetFontSizes(QWidget* widget, float scale);
}; };
#endif // hifi_UIUtil_h #endif // hifi_UIUtil_h

View file

@ -537,18 +537,13 @@ void Avatar::renderBillboard() {
return; return;
} }
if (!_billboardTexture) { if (!_billboardTexture) {
QImage image = QImage::fromData(_billboard); // Using a unique URL ensures we don't get another avatar's texture from TextureCache
if (image.format() != QImage::Format_ARGB32) { QUrl uniqueUrl = QUrl(QUuid::createUuid().toString());
image = image.convertToFormat(QImage::Format_ARGB32); _billboardTexture = DependencyManager::get<TextureCache>()->getTexture(
uniqueUrl, DEFAULT_TEXTURE, false, _billboard);
} }
_billboardTexture.reset(new Texture()); if (!_billboardTexture->isLoaded()) {
glBindTexture(GL_TEXTURE_2D, _billboardTexture->getID()); return;
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, image.width(), image.height(), 0,
GL_BGRA, GL_UNSIGNED_BYTE, image.constBits());
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
} else {
glBindTexture(GL_TEXTURE_2D, _billboardTexture->getID());
} }
glEnable(GL_ALPHA_TEST); glEnable(GL_ALPHA_TEST);
@ -557,6 +552,8 @@ void Avatar::renderBillboard() {
glEnable(GL_TEXTURE_2D); glEnable(GL_TEXTURE_2D);
glDisable(GL_LIGHTING); glDisable(GL_LIGHTING);
glBindTexture(GL_TEXTURE_2D, _billboardTexture->getID());
glPushMatrix(); glPushMatrix();
glTranslatef(_position.x, _position.y, _position.z); glTranslatef(_position.x, _position.y, _position.z);

View file

@ -234,7 +234,7 @@ protected:
private: private:
bool _initialized; bool _initialized;
QScopedPointer<Texture> _billboardTexture; NetworkTexturePointer _billboardTexture;
bool _shouldRenderBillboard; bool _shouldRenderBillboard;
bool _isLookAtTarget; bool _isLookAtTarget;

View file

@ -80,13 +80,8 @@ void Head::simulate(float deltaTime, bool isMine, bool billboard) {
// Only use face trackers when not playing back a recording. // Only use face trackers when not playing back a recording.
if (!myAvatar->isPlaying()) { if (!myAvatar->isPlaying()) {
FaceTracker* faceTracker = Application::getInstance()->getActiveFaceTracker(); FaceTracker* faceTracker = Application::getInstance()->getActiveFaceTracker();
auto dde = DependencyManager::get<DdeFaceTracker>(); _isFaceTrackerConnected = faceTracker != NULL;
auto faceshift = DependencyManager::get<Faceshift>(); if (_isFaceTrackerConnected) {
if ((_isFaceshiftConnected = (faceshift == faceTracker))) {
_blendshapeCoefficients = faceTracker->getBlendshapeCoefficients();
} else if (dde->isActive()) {
faceTracker = dde.data();
_blendshapeCoefficients = faceTracker->getBlendshapeCoefficients(); _blendshapeCoefficients = faceTracker->getBlendshapeCoefficients();
} }
} }
@ -109,7 +104,7 @@ void Head::simulate(float deltaTime, bool isMine, bool billboard) {
_longTermAverageLoudness = glm::mix(_longTermAverageLoudness, _averageLoudness, glm::min(deltaTime / AUDIO_LONG_TERM_AVERAGING_SECS, 1.0f)); _longTermAverageLoudness = glm::mix(_longTermAverageLoudness, _averageLoudness, glm::min(deltaTime / AUDIO_LONG_TERM_AVERAGING_SECS, 1.0f));
} }
if (!(_isFaceshiftConnected || billboard)) { if (!(_isFaceTrackerConnected || billboard)) {
// Update eye saccades // Update eye saccades
const float AVERAGE_MICROSACCADE_INTERVAL = 0.50f; const float AVERAGE_MICROSACCADE_INTERVAL = 0.50f;
const float AVERAGE_SACCADE_INTERVAL = 4.0f; const float AVERAGE_SACCADE_INTERVAL = 4.0f;

View file

@ -44,58 +44,40 @@ struct Packet{
}; };
DdeFaceTracker::DdeFaceTracker() : DdeFaceTracker::DdeFaceTracker() :
_lastReceiveTimestamp(0), DdeFaceTracker(QHostAddress::Any, DDE_FEATURE_POINT_SERVER_PORT)
_reset(false), {
_leftBlinkIndex(0), // see http://support.faceshift.com/support/articles/35129-export-of-blendshapes
_rightBlinkIndex(1), }
_leftEyeOpenIndex(8),
_rightEyeOpenIndex(9), DdeFaceTracker::DdeFaceTracker(const QHostAddress& host, quint16 port) :
_browDownLeftIndex(14), _lastReceiveTimestamp(0),
_browDownRightIndex(15), _reset(false),
_browUpCenterIndex(16), _leftBlinkIndex(0), // see http://support.faceshift.com/support/articles/35129-export-of-blendshapes
_browUpLeftIndex(17), _rightBlinkIndex(1),
_browUpRightIndex(18), _leftEyeOpenIndex(8),
_mouthSmileLeftIndex(28), _rightEyeOpenIndex(9),
_mouthSmileRightIndex(29), _browDownLeftIndex(14),
_jawOpenIndex(21) _browDownRightIndex(15),
_browUpCenterIndex(16),
_browUpLeftIndex(17),
_browUpRightIndex(18),
_mouthSmileLeftIndex(28),
_mouthSmileRightIndex(29),
_jawOpenIndex(21),
_host(host),
_port(port)
{ {
_blendshapeCoefficients.resize(NUM_EXPRESSION); _blendshapeCoefficients.resize(NUM_EXPRESSION);
connect(&_udpSocket, SIGNAL(readyRead()), SLOT(readPendingDatagrams())); connect(&_udpSocket, SIGNAL(readyRead()), SLOT(readPendingDatagrams()));
connect(&_udpSocket, SIGNAL(error(QAbstractSocket::SocketError)), SLOT(socketErrorOccurred(QAbstractSocket::SocketError))); connect(&_udpSocket, SIGNAL(error(QAbstractSocket::SocketError)), SLOT(socketErrorOccurred(QAbstractSocket::SocketError)));
connect(&_udpSocket, SIGNAL(stateChanged(QAbstractSocket::SocketState)), SLOT(socketStateChanged(QAbstractSocket::SocketState))); connect(&_udpSocket, SIGNAL(stateChanged(QAbstractSocket::SocketState)), SLOT(socketStateChanged(QAbstractSocket::SocketState)));
bindTo(DDE_FEATURE_POINT_SERVER_PORT);
}
DdeFaceTracker::DdeFaceTracker(const QHostAddress& host, quint16 port) :
_lastReceiveTimestamp(0),
_reset(false),
_leftBlinkIndex(0), // see http://support.faceshift.com/support/articles/35129-export-of-blendshapes
_rightBlinkIndex(1),
_leftEyeOpenIndex(8),
_rightEyeOpenIndex(9),
_browDownLeftIndex(14),
_browDownRightIndex(15),
_browUpCenterIndex(16),
_browUpLeftIndex(17),
_browUpRightIndex(18),
_mouthSmileLeftIndex(28),
_mouthSmileRightIndex(29),
_jawOpenIndex(21)
{
_blendshapeCoefficients.resize(NUM_EXPRESSION);
connect(&_udpSocket, SIGNAL(readyRead()), SLOT(readPendingDatagrams()));
connect(&_udpSocket, SIGNAL(error(QAbstractSocket::SocketError)), SLOT(socketErrorOccurred(QAbstractSocket::SocketError)));
connect(&_udpSocket, SIGNAL(stateChanged(QAbstractSocket::SocketState)), SIGNAL(socketStateChanged(QAbstractSocket::SocketState)));
bindTo(host, port);
} }
DdeFaceTracker::~DdeFaceTracker() { DdeFaceTracker::~DdeFaceTracker() {
if(_udpSocket.isOpen()) if (_udpSocket.isOpen()) {
_udpSocket.close(); _udpSocket.close();
}
} }
void DdeFaceTracker::init() { void DdeFaceTracker::init() {
@ -110,15 +92,12 @@ void DdeFaceTracker::update() {
} }
void DdeFaceTracker::bindTo(quint16 port) { void DdeFaceTracker::setEnabled(bool enabled) {
bindTo(QHostAddress::Any, port); // isOpen() does not work as one might expect on QUdpSocket; don't test isOpen() before closing socket.
}
void DdeFaceTracker::bindTo(const QHostAddress& host, quint16 port) {
if(_udpSocket.isOpen()) {
_udpSocket.close(); _udpSocket.close();
if (enabled) {
_udpSocket.bind(_host, _port);
} }
_udpSocket.bind(host, port);
} }
bool DdeFaceTracker::isActive() const { bool DdeFaceTracker::isActive() const {
@ -135,7 +114,7 @@ void DdeFaceTracker::socketStateChanged(QAbstractSocket::SocketState socketState
QString state; QString state;
switch(socketState) { switch(socketState) {
case QAbstractSocket::BoundState: case QAbstractSocket::BoundState:
state = "Bounded"; state = "Bound";
break; break;
case QAbstractSocket::ClosingState: case QAbstractSocket::ClosingState:
state = "Closing"; state = "Closing";
@ -156,7 +135,7 @@ void DdeFaceTracker::socketStateChanged(QAbstractSocket::SocketState socketState
state = "Unconnected"; state = "Unconnected";
break; break;
} }
qDebug() << "[Info] DDE Face Tracker Socket: " << socketState; qDebug() << "[Info] DDE Face Tracker Socket: " << state;
} }
void DdeFaceTracker::readPendingDatagrams() { void DdeFaceTracker::readPendingDatagrams() {

View file

@ -28,9 +28,6 @@ public:
void reset(); void reset();
void update(); void update();
//sockets
void bindTo(quint16 port);
void bindTo(const QHostAddress& host, quint16 port);
bool isActive() const; bool isActive() const;
float getLeftBlink() const { return getBlendshapeCoefficient(_leftBlinkIndex); } float getLeftBlink() const { return getBlendshapeCoefficient(_leftBlinkIndex); }
@ -48,6 +45,9 @@ public:
float getMouthSmileLeft() const { return getBlendshapeCoefficient(_mouthSmileLeftIndex); } float getMouthSmileLeft() const { return getBlendshapeCoefficient(_mouthSmileLeftIndex); }
float getMouthSmileRight() const { return getBlendshapeCoefficient(_mouthSmileRightIndex); } float getMouthSmileRight() const { return getBlendshapeCoefficient(_mouthSmileRightIndex); }
public slots:
void setEnabled(bool enabled);
private slots: private slots:
//sockets //sockets
@ -60,6 +60,9 @@ private:
DdeFaceTracker(const QHostAddress& host, quint16 port); DdeFaceTracker(const QHostAddress& host, quint16 port);
~DdeFaceTracker(); ~DdeFaceTracker();
QHostAddress _host;
quint16 _port;
float getBlendshapeCoefficient(int index) const; float getBlendshapeCoefficient(int index) const;
void decodePacket(const QByteArray& buffer); void decodePacket(const QByteArray& buffer);

View file

@ -260,6 +260,18 @@ void SixenseManager::update(float deltaTime) {
float sign = (i == 0) ? -1.0f : 1.0f; float sign = (i == 0) ? -1.0f : 1.0f;
rotation *= glm::angleAxis(sign * PI/4.0f, glm::vec3(0.0f, 0.0f, 1.0f)); rotation *= glm::angleAxis(sign * PI/4.0f, glm::vec3(0.0f, 0.0f, 1.0f));
// Angular Velocity of Palm
glm::quat deltaRotation = rotation * glm::inverse(palm->getRawRotation());
glm::vec3 angularVelocity(0.0f);
float rotationAngle = glm::angle(deltaRotation);
if ((rotationAngle > EPSILON) && (deltaTime > 0.0f)) {
angularVelocity = glm::normalize(glm::axis(deltaRotation));
angularVelocity *= (rotationAngle / deltaTime);
palm->setRawAngularVelocity(angularVelocity);
} else {
palm->setRawAngularVelocity(glm::vec3(0.0f));
}
if (_lowVelocityFilter) { if (_lowVelocityFilter) {
// Use a velocity sensitive filter to damp small motions and preserve large ones with // Use a velocity sensitive filter to damp small motions and preserve large ones with
// no latency. // no latency.

View file

@ -174,7 +174,8 @@ void Visage::reset() {
void Visage::updateEnabled() { void Visage::updateEnabled() {
setEnabled(Menu::getInstance()->isOptionChecked(MenuOption::Visage) && setEnabled(Menu::getInstance()->isOptionChecked(MenuOption::Visage) &&
!(Menu::getInstance()->isOptionChecked(MenuOption::Faceshift) && !(Menu::getInstance()->isOptionChecked(MenuOption::Faceshift) &&
DependencyManager::get<Faceshift>()->isConnectedOrConnecting())); DependencyManager::get<Faceshift>()->isConnectedOrConnecting()) &&
!Menu::getInstance()->isOptionChecked(MenuOption::DDEFaceRegression));
} }
void Visage::setEnabled(bool enabled) { void Visage::setEnabled(bool enabled) {

View file

@ -209,6 +209,21 @@ glm::quat ControllerScriptingInterface::getSpatialControlRawRotation(int control
return glm::quat(); // bad index return glm::quat(); // bad index
} }
glm::vec3 ControllerScriptingInterface::getSpatialControlRawAngularVelocity(int controlIndex) const {
int palmIndex = controlIndex / NUMBER_OF_SPATIALCONTROLS_PER_PALM;
int controlOfPalm = controlIndex % NUMBER_OF_SPATIALCONTROLS_PER_PALM;
const PalmData* palmData = getActivePalm(palmIndex);
if (palmData) {
switch (controlOfPalm) {
case PALM_SPATIALCONTROL:
return palmData->getRawAngularVelocity();
case TIP_SPATIALCONTROL:
return palmData->getRawAngularVelocity(); // Tip = palm angular velocity
}
}
return glm::vec3(0); // bad index
}
glm::vec3 ControllerScriptingInterface::getSpatialControlNormal(int controlIndex) const { glm::vec3 ControllerScriptingInterface::getSpatialControlNormal(int controlIndex) const {
int palmIndex = controlIndex / NUMBER_OF_SPATIALCONTROLS_PER_PALM; int palmIndex = controlIndex / NUMBER_OF_SPATIALCONTROLS_PER_PALM;
int controlOfPalm = controlIndex % NUMBER_OF_SPATIALCONTROLS_PER_PALM; int controlOfPalm = controlIndex % NUMBER_OF_SPATIALCONTROLS_PER_PALM;

View file

@ -96,6 +96,7 @@ public slots:
virtual glm::vec3 getSpatialControlVelocity(int controlIndex) const; virtual glm::vec3 getSpatialControlVelocity(int controlIndex) const;
virtual glm::vec3 getSpatialControlNormal(int controlIndex) const; virtual glm::vec3 getSpatialControlNormal(int controlIndex) const;
virtual glm::quat getSpatialControlRawRotation(int controlIndex) const; virtual glm::quat getSpatialControlRawRotation(int controlIndex) const;
virtual glm::vec3 getSpatialControlRawAngularVelocity(int controlIndex) const;
virtual void captureKeyEvents(const KeyEvent& event); virtual void captureKeyEvents(const KeyEvent& event);
virtual void releaseKeyEvents(const KeyEvent& event); virtual void releaseKeyEvents(const KeyEvent& event);

View file

@ -48,7 +48,6 @@ QScriptValue HMDScriptingInterface::getHUDLookAtPosition2D(QScriptContext* conte
QScriptValue HMDScriptingInterface::getHUDLookAtPosition3D(QScriptContext* context, QScriptEngine* engine) { QScriptValue HMDScriptingInterface::getHUDLookAtPosition3D(QScriptContext* context, QScriptEngine* engine) {
glm::vec3 result; glm::vec3 result;
HMDScriptingInterface* hmdInterface = &HMDScriptingInterface::getInstance();
if ((&HMDScriptingInterface::getInstance())->getHUDLookAtPosition3D(result)) { if ((&HMDScriptingInterface::getInstance())->getHUDLookAtPosition3D(result)) {
return qScriptValueFromValue<glm::vec3>(engine, result); return qScriptValueFromValue<glm::vec3>(engine, result);
} }

View file

@ -136,10 +136,10 @@ ApplicationOverlay::ApplicationOverlay() :
_textureFov(glm::radians(DEFAULT_OCULUS_UI_ANGULAR_SIZE)), _textureFov(glm::radians(DEFAULT_OCULUS_UI_ANGULAR_SIZE)),
_textureAspectRatio(1.0f), _textureAspectRatio(1.0f),
_lastMouseMove(0), _lastMouseMove(0),
_magnifier(true),
_alpha(1.0f), _alpha(1.0f),
_oculusUIRadius(1.0f), _oculusUIRadius(1.0f),
_crosshairTexture(0), _crosshairTexture(0),
_magnifier(true),
_previousBorderWidth(-1), _previousBorderWidth(-1),
_previousBorderHeight(-1), _previousBorderHeight(-1),
_previousMagnifierBottomLeft(), _previousMagnifierBottomLeft(),

View file

@ -21,6 +21,7 @@
#include "AccountManager.h" #include "AccountManager.h"
#include "ui_loginDialog.h" #include "ui_loginDialog.h"
#include "LoginDialog.h" #include "LoginDialog.h"
#include "UIUtil.h"
const QString FORGOT_PASSWORD_URL = "https://metaverse.highfidelity.io/users/password/new"; const QString FORGOT_PASSWORD_URL = "https://metaverse.highfidelity.io/users/password/new";
@ -42,6 +43,8 @@ LoginDialog::LoginDialog(QWidget* parent) :
connect(_ui->closeButton, &QPushButton::clicked, connect(_ui->closeButton, &QPushButton::clicked,
this, &LoginDialog::close); this, &LoginDialog::close);
UIUtil::scaleWidgetFontSizes(this);
// Initialize toggle connection // Initialize toggle connection
toggleQAction(); toggleQAction();
}; };

View file

@ -10,6 +10,7 @@
// //
#include <QFileDialog> #include <QFileDialog>
#include <QFont>
#include <AudioClient.h> #include <AudioClient.h>
#include <avatar/AvatarManager.h> #include <avatar/AvatarManager.h>
@ -23,6 +24,7 @@
#include "PreferencesDialog.h" #include "PreferencesDialog.h"
#include "Snapshot.h" #include "Snapshot.h"
#include "UserActivityLogger.h" #include "UserActivityLogger.h"
#include "UIUtil.h"
const int PREFERENCES_HEIGHT_PADDING = 20; const int PREFERENCES_HEIGHT_PADDING = 20;
@ -46,6 +48,8 @@ PreferencesDialog::PreferencesDialog(QWidget* parent) :
// move dialog to left side // move dialog to left side
move(parentWidget()->geometry().topLeft()); move(parentWidget()->geometry().topLeft());
setFixedHeight(parentWidget()->size().height() - PREFERENCES_HEIGHT_PADDING); setFixedHeight(parentWidget()->size().height() - PREFERENCES_HEIGHT_PADDING);
UIUtil::scaleWidgetFontSizes(this);
} }
void PreferencesDialog::accept() { void PreferencesDialog::accept() {

View file

@ -64,6 +64,8 @@ RunningScriptsWidget::RunningScriptsWidget(QWidget* parent) :
connect(ui->loadScriptFromURLButton, &QPushButton::clicked, connect(ui->loadScriptFromURLButton, &QPushButton::clicked,
Application::getInstance(), &Application::loadScriptURLDialog); Application::getInstance(), &Application::loadScriptURLDialog);
connect(&_signalMapper, SIGNAL(mapped(QString)), Application::getInstance(), SLOT(stopScript(const QString&))); connect(&_signalMapper, SIGNAL(mapped(QString)), Application::getInstance(), SLOT(stopScript(const QString&)));
UIUtil::scaleWidgetFontSizes(this);
} }
RunningScriptsWidget::~RunningScriptsWidget() { RunningScriptsWidget::~RunningScriptsWidget() {
@ -103,6 +105,7 @@ void RunningScriptsWidget::setRunningScripts(const QStringList& list) {
hash.insert(list.at(i), 1); hash.insert(list.at(i), 1);
} }
QWidget* row = new QWidget(ui->scriptListWidget); QWidget* row = new QWidget(ui->scriptListWidget);
row->setFont(ui->scriptListWidget->font());
row->setLayout(new QHBoxLayout(row)); row->setLayout(new QHBoxLayout(row));
QUrl url = QUrl(list.at(i)); QUrl url = QUrl(list.at(i));

View file

@ -28,15 +28,26 @@
<height>16777215</height> <height>16777215</height>
</size> </size>
</property> </property>
<widget class="QScrollArea" name="scrollArea"> <property name="font">
<property name="geometry"> <font>
<rect> <pointsize>13</pointsize>
<x>0</x> </font>
<y>0</y>
<width>500</width>
<height>491</height>
</rect>
</property> </property>
<layout class="QVBoxLayout" name="verticalLayout">
<property name="leftMargin">
<number>0</number>
</property>
<property name="topMargin">
<number>0</number>
</property>
<property name="rightMargin">
<number>0</number>
</property>
<property name="bottomMargin">
<number>0</number>
</property>
<item>
<widget class="QScrollArea" name="scrollArea">
<property name="sizePolicy"> <property name="sizePolicy">
<sizepolicy hsizetype="Expanding" vsizetype="Expanding"> <sizepolicy hsizetype="Expanding" vsizetype="Expanding">
<horstretch>0</horstretch> <horstretch>0</horstretch>
@ -59,9 +70,9 @@
<property name="geometry"> <property name="geometry">
<rect> <rect>
<x>0</x> <x>0</x>
<y>-825</y> <y>-107</y>
<width>485</width> <width>485</width>
<height>1611</height> <height>1550</height>
</rect> </rect>
</property> </property>
<layout class="QVBoxLayout" name="verticalLayout_2"> <layout class="QVBoxLayout" name="verticalLayout_2">
@ -80,20 +91,24 @@
<property name="bottomMargin"> <property name="bottomMargin">
<number>30</number> <number>30</number>
</property> </property>
<item>
<spacer name="verticalSpacer_3">
<property name="orientation">
<enum>Qt::Vertical</enum>
</property>
<property name="sizeType">
<enum>QSizePolicy::Fixed</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>20</width>
<height>20</height>
</size>
</property>
</spacer>
</item>
<item> <item>
<widget class="QLabel" name="label_11"> <widget class="QLabel" name="label_11">
<property name="minimumSize">
<size>
<width>0</width>
<height>40</height>
</size>
</property>
<property name="baseSize">
<size>
<width>0</width>
<height>40</height>
</size>
</property>
<property name="font"> <property name="font">
<font> <font>
<family>Arial</family> <family>Arial</family>
@ -103,7 +118,7 @@
</font> </font>
</property> </property>
<property name="styleSheet"> <property name="styleSheet">
<string notr="true">color:#29967e</string> <string notr="true">color:#29967e;</string>
</property> </property>
<property name="text"> <property name="text">
<string>Avatar basics</string> <string>Avatar basics</string>
@ -111,29 +126,24 @@
<property name="alignment"> <property name="alignment">
<set>Qt::AlignBottom|Qt::AlignLeading|Qt::AlignLeft</set> <set>Qt::AlignBottom|Qt::AlignLeading|Qt::AlignLeft</set>
</property> </property>
<property name="margin">
<number>0</number>
</property>
</widget> </widget>
</item> </item>
<item>
<layout class="QVBoxLayout" name="verticalLayout_5">
<property name="spacing">
<number>0</number>
</property>
<property name="topMargin">
<number>7</number>
</property>
<property name="bottomMargin">
<number>7</number>
</property>
<item> <item>
<widget class="QLabel" name="avatarDisplayLabel"> <widget class="QLabel" name="avatarDisplayLabel">
<property name="sizePolicy">
<sizepolicy hsizetype="Fixed" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="minimumSize">
<size>
<width>0</width>
<height>28</height>
</size>
</property>
<property name="font"> <property name="font">
<font> <font>
<family>Arial</family> <family>Arial</family>
<pointsize>14</pointsize>
</font> </font>
</property> </property>
<property name="text"> <property name="text">
@ -147,20 +157,19 @@
</property> </property>
</widget> </widget>
</item> </item>
<item>
<layout class="QHBoxLayout" name="horizontalLayout_17">
<property name="topMargin">
<number>4</number>
</property>
<property name="rightMargin">
<number>140</number>
</property>
<property name="bottomMargin">
<number>4</number>
</property>
<item> <item>
<widget class="QLineEdit" name="displayNameEdit"> <widget class="QLineEdit" name="displayNameEdit">
<property name="sizePolicy">
<sizepolicy hsizetype="Fixed" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="minimumSize">
<size>
<width>280</width>
<height>0</height>
</size>
</property>
<property name="font"> <property name="font">
<font> <font>
<family>Arial</family> <family>Arial</family>
@ -169,32 +178,31 @@
<property name="layoutDirection"> <property name="layoutDirection">
<enum>Qt::LeftToRight</enum> <enum>Qt::LeftToRight</enum>
</property> </property>
<property name="styleSheet">
<string notr="true"/>
</property>
<property name="placeholderText"> <property name="placeholderText">
<string>Not showing a name</string> <string>Not showing a name</string>
</property> </property>
</widget> </widget>
</item> </item>
</layout>
</item>
</layout>
</item>
<item>
<layout class="QVBoxLayout" name="verticalLayout_4">
<property name="spacing">
<number>0</number>
</property>
<property name="topMargin">
<number>7</number>
</property>
<property name="bottomMargin">
<number>7</number>
</property>
<item> <item>
<widget class="QLabel" name="headLabel"> <widget class="QLabel" name="headLabel">
<property name="sizePolicy">
<sizepolicy hsizetype="Fixed" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="minimumSize">
<size>
<width>0</width>
<height>28</height>
</size>
</property>
<property name="font"> <property name="font">
<font> <font>
<family>Arial</family> <family>Arial</family>
<pointsize>14</pointsize>
</font> </font>
</property> </property>
<property name="text"> <property name="text">
@ -203,9 +211,6 @@
<property name="alignment"> <property name="alignment">
<set>Qt::AlignBottom|Qt::AlignLeading|Qt::AlignLeft</set> <set>Qt::AlignBottom|Qt::AlignLeading|Qt::AlignLeft</set>
</property> </property>
<property name="margin">
<number>0</number>
</property>
<property name="buddy"> <property name="buddy">
<cstring>snapshotLocationEdit</cstring> <cstring>snapshotLocationEdit</cstring>
</property> </property>
@ -213,15 +218,11 @@
</item> </item>
<item> <item>
<layout class="QHBoxLayout" name="horizontalLayout"> <layout class="QHBoxLayout" name="horizontalLayout">
<item> <property name="spacing">
<widget class="QLineEdit" name="faceURLEdit"> <number>0</number>
<property name="sizePolicy">
<sizepolicy hsizetype="Expanding" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property> </property>
</widget> <item>
<widget class="QLineEdit" name="faceURLEdit"/>
</item> </item>
<item> <item>
<spacer name="horizontalSpacer"> <spacer name="horizontalSpacer">
@ -259,24 +260,24 @@
</item> </item>
</layout> </layout>
</item> </item>
</layout>
</item>
<item>
<layout class="QVBoxLayout" name="verticalLayout_3">
<property name="spacing">
<number>0</number>
</property>
<property name="topMargin">
<number>7</number>
</property>
<property name="bottomMargin">
<number>7</number>
</property>
<item> <item>
<widget class="QLabel" name="headLabel_2"> <widget class="QLabel" name="headLabel_2">
<property name="sizePolicy">
<sizepolicy hsizetype="Fixed" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="minimumSize">
<size>
<width>0</width>
<height>28</height>
</size>
</property>
<property name="font"> <property name="font">
<font> <font>
<family>Arial</family> <family>Arial</family>
<pointsize>14</pointsize>
</font> </font>
</property> </property>
<property name="text"> <property name="text">
@ -292,6 +293,9 @@
</item> </item>
<item> <item>
<layout class="QHBoxLayout" name="horizontalLayout_7"> <layout class="QHBoxLayout" name="horizontalLayout_7">
<property name="spacing">
<number>0</number>
</property>
<item> <item>
<widget class="QLineEdit" name="skeletonURLEdit"> <widget class="QLineEdit" name="skeletonURLEdit">
<property name="minimumSize"> <property name="minimumSize">
@ -338,20 +342,26 @@
</item> </item>
</layout> </layout>
</item> </item>
</layout>
</item>
<item> <item>
<widget class="QLabel" name="avatarTitleLabel_2"> <spacer name="verticalSpacer_2">
<property name="sizePolicy"> <property name="orientation">
<sizepolicy hsizetype="Fixed" vsizetype="Fixed"> <enum>Qt::Vertical</enum>
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property> </property>
<property name="minimumSize"> <property name="sizeType">
<enum>QSizePolicy::Fixed</enum>
</property>
<property name="sizeHint" stdset="0">
<size> <size>
<width>0</width> <width>20</width>
<height>40</height> <height>20</height>
</size> </size>
</property> </property>
</spacer>
</item>
<item>
<widget class="QLabel" name="avatarTitleLabel_2">
<property name="font"> <property name="font">
<font> <font>
<family>Arial</family> <family>Arial</family>
@ -371,24 +381,22 @@
</property> </property>
</widget> </widget>
</item> </item>
<item>
<layout class="QVBoxLayout" name="verticalLayout_6">
<property name="spacing">
<number>0</number>
</property>
<property name="topMargin">
<number>7</number>
</property>
<property name="bottomMargin">
<number>0</number>
</property>
<item> <item>
<widget class="QLabel" name="headLabel_3"> <widget class="QLabel" name="headLabel_3">
<property name="sizePolicy">
<sizepolicy hsizetype="Fixed" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="minimumSize">
<size>
<width>0</width>
<height>22</height>
</size>
</property>
<property name="font"> <property name="font">
<font> <font>
<family>Arial</family> <family>Arial</family>
<pointsize>13</pointsize>
</font> </font>
</property> </property>
<property name="text"> <property name="text">
@ -407,14 +415,11 @@
</item> </item>
<item> <item>
<layout class="QHBoxLayout" name="horizontalLayout_1"> <layout class="QHBoxLayout" name="horizontalLayout_1">
<property name="spacing">
<number>0</number>
</property>
<item> <item>
<widget class="QLineEdit" name="snapshotLocationEdit"> <widget class="QLineEdit" name="snapshotLocationEdit">
<property name="sizePolicy">
<sizepolicy hsizetype="Expanding" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="font"> <property name="font">
<font> <font>
<family>Arial</family> <family>Arial</family>
@ -458,20 +463,26 @@
</item> </item>
</layout> </layout>
</item> </item>
</layout>
</item>
<item> <item>
<widget class="QLabel" name="avatarTitleLabel_3"> <spacer name="verticalSpacer_4">
<property name="sizePolicy"> <property name="orientation">
<sizepolicy hsizetype="Fixed" vsizetype="Fixed"> <enum>Qt::Vertical</enum>
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property> </property>
<property name="minimumSize"> <property name="sizeType">
<enum>QSizePolicy::Fixed</enum>
</property>
<property name="sizeHint" stdset="0">
<size> <size>
<width>0</width> <width>20</width>
<height>40</height> <height>20</height>
</size> </size>
</property> </property>
</spacer>
</item>
<item>
<widget class="QLabel" name="avatarTitleLabel_3">
<property name="font"> <property name="font">
<font> <font>
<family>Arial</family> <family>Arial</family>
@ -491,24 +502,22 @@
</property> </property>
</widget> </widget>
</item> </item>
<item>
<layout class="QVBoxLayout" name="verticalLayout_7">
<property name="spacing">
<number>0</number>
</property>
<property name="topMargin">
<number>7</number>
</property>
<property name="bottomMargin">
<number>0</number>
</property>
<item> <item>
<widget class="QLabel" name="headLabel_4"> <widget class="QLabel" name="headLabel_4">
<property name="sizePolicy">
<sizepolicy hsizetype="Fixed" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="minimumSize">
<size>
<width>0</width>
<height>22</height>
</size>
</property>
<property name="font"> <property name="font">
<font> <font>
<family>Arial</family> <family>Arial</family>
<pointsize>13</pointsize>
</font> </font>
</property> </property>
<property name="text"> <property name="text">
@ -527,6 +536,9 @@
</item> </item>
<item> <item>
<layout class="QHBoxLayout" name="horizontalLayout_11"> <layout class="QHBoxLayout" name="horizontalLayout_11">
<property name="spacing">
<number>0</number>
</property>
<item> <item>
<widget class="QLineEdit" name="scriptsLocationEdit"> <widget class="QLineEdit" name="scriptsLocationEdit">
<property name="sizePolicy"> <property name="sizePolicy">
@ -578,6 +590,8 @@
</item> </item>
</layout> </layout>
</item> </item>
</layout>
</item>
<item> <item>
<widget class="QPushButton" name="buttonReloadDefaultScripts"> <widget class="QPushButton" name="buttonReloadDefaultScripts">
<property name="sizePolicy"> <property name="sizePolicy">
@ -609,19 +623,23 @@
</widget> </widget>
</item> </item>
<item> <item>
<widget class="QLabel" name="privacyLabel"> <spacer name="verticalSpacer_5">
<property name="sizePolicy"> <property name="orientation">
<sizepolicy hsizetype="Fixed" vsizetype="Fixed"> <enum>Qt::Vertical</enum>
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property> </property>
<property name="minimumSize"> <property name="sizeType">
<enum>QSizePolicy::Fixed</enum>
</property>
<property name="sizeHint" stdset="0">
<size> <size>
<width>0</width> <width>20</width>
<height>40</height> <height>20</height>
</size> </size>
</property> </property>
</spacer>
</item>
<item>
<widget class="QLabel" name="privacyLabel">
<property name="font"> <property name="font">
<font> <font>
<family>Arial</family> <family>Arial</family>
@ -684,19 +702,23 @@
</widget> </widget>
</item> </item>
<item> <item>
<widget class="QLabel" name="avatarTitleLabel"> <spacer name="verticalSpacer_8">
<property name="sizePolicy"> <property name="orientation">
<sizepolicy hsizetype="Fixed" vsizetype="Fixed"> <enum>Qt::Vertical</enum>
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property> </property>
<property name="minimumSize"> <property name="sizeType">
<enum>QSizePolicy::Fixed</enum>
</property>
<property name="sizeHint" stdset="0">
<size> <size>
<width>0</width> <width>20</width>
<height>40</height> <height>20</height>
</size> </size>
</property> </property>
</spacer>
</item>
<item>
<widget class="QLabel" name="avatarTitleLabel">
<property name="font"> <property name="font">
<font> <font>
<family>Arial</family> <family>Arial</family>
@ -1273,19 +1295,23 @@
</layout> </layout>
</item> </item>
<item> <item>
<widget class="QLabel" name="octreeTitleLabel_2"> <spacer name="verticalSpacer_9">
<property name="sizePolicy"> <property name="orientation">
<sizepolicy hsizetype="Preferred" vsizetype="Minimum"> <enum>Qt::Vertical</enum>
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property> </property>
<property name="minimumSize"> <property name="sizeType">
<enum>QSizePolicy::Fixed</enum>
</property>
<property name="sizeHint" stdset="0">
<size> <size>
<width>0</width> <width>20</width>
<height>40</height> <height>20</height>
</size> </size>
</property> </property>
</spacer>
</item>
<item>
<widget class="QLabel" name="octreeTitleLabel_2">
<property name="font"> <property name="font">
<font> <font>
<family>Arial</family> <family>Arial</family>
@ -1305,20 +1331,16 @@
</property> </property>
</widget> </widget>
</item> </item>
<item>
<layout class="QHBoxLayout" name="horizontalLayout_14">
<property name="topMargin">
<number>7</number>
</property>
<property name="bottomMargin">
<number>7</number>
</property>
<item> <item>
<widget class="QCheckBox" name="dynamicJitterBuffersCheckBox"> <widget class="QCheckBox" name="dynamicJitterBuffersCheckBox">
<property name="sizePolicy">
<sizepolicy hsizetype="Fixed" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="minimumSize">
<size>
<width>0</width>
<height>40</height>
</size>
</property>
<property name="baseSize"> <property name="baseSize">
<size> <size>
<width>0</width> <width>0</width>
@ -1335,6 +1357,8 @@
</property> </property>
</widget> </widget>
</item> </item>
</layout>
</item>
<item> <item>
<layout class="QHBoxLayout" name="horizontalLayout_8"> <layout class="QHBoxLayout" name="horizontalLayout_8">
<property name="spacing"> <property name="spacing">
@ -1493,20 +1517,16 @@
</item> </item>
</layout> </layout>
</item> </item>
<item>
<layout class="QHBoxLayout" name="horizontalLayout_18">
<property name="topMargin">
<number>7</number>
</property>
<property name="bottomMargin">
<number>7</number>
</property>
<item> <item>
<widget class="QCheckBox" name="useStdevForJitterCalcCheckBox"> <widget class="QCheckBox" name="useStdevForJitterCalcCheckBox">
<property name="sizePolicy">
<sizepolicy hsizetype="Minimum" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="minimumSize">
<size>
<width>0</width>
<height>40</height>
</size>
</property>
<property name="baseSize"> <property name="baseSize">
<size> <size>
<width>0</width> <width>0</width>
@ -1529,6 +1549,8 @@
</property> </property>
</widget> </widget>
</item> </item>
</layout>
</item>
<item> <item>
<layout class="QHBoxLayout" name="horizontalLayout_20"> <layout class="QHBoxLayout" name="horizontalLayout_20">
<property name="spacing"> <property name="spacing">
@ -1793,20 +1815,16 @@
</item> </item>
</layout> </layout>
</item> </item>
<item>
<layout class="QHBoxLayout" name="horizontalLayout_19">
<property name="topMargin">
<number>7</number>
</property>
<property name="bottomMargin">
<number>7</number>
</property>
<item> <item>
<widget class="QCheckBox" name="repetitionWithFadeCheckBox"> <widget class="QCheckBox" name="repetitionWithFadeCheckBox">
<property name="sizePolicy">
<sizepolicy hsizetype="Minimum" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="minimumSize">
<size>
<width>32</width>
<height>40</height>
</size>
</property>
<property name="baseSize"> <property name="baseSize">
<size> <size>
<width>0</width> <width>0</width>
@ -1829,6 +1847,8 @@
</property> </property>
</widget> </widget>
</item> </item>
</layout>
</item>
<item> <item>
<layout class="QHBoxLayout" name="horizontalLayout_23"> <layout class="QHBoxLayout" name="horizontalLayout_23">
<property name="spacing"> <property name="spacing">
@ -1917,20 +1937,16 @@
</item> </item>
</layout> </layout>
</item> </item>
<item>
<layout class="QHBoxLayout" name="horizontalLayout_24">
<property name="topMargin">
<number>7</number>
</property>
<property name="bottomMargin">
<number>7</number>
</property>
<item> <item>
<widget class="QCheckBox" name="outputStarveDetectionCheckBox"> <widget class="QCheckBox" name="outputStarveDetectionCheckBox">
<property name="sizePolicy">
<sizepolicy hsizetype="Minimum" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="minimumSize">
<size>
<width>32</width>
<height>40</height>
</size>
</property>
<property name="baseSize"> <property name="baseSize">
<size> <size>
<width>0</width> <width>0</width>
@ -1953,6 +1969,8 @@
</property> </property>
</widget> </widget>
</item> </item>
</layout>
</item>
<item> <item>
<layout class="QHBoxLayout" name="horizontalLayout_27"> <layout class="QHBoxLayout" name="horizontalLayout_27">
<property name="spacing"> <property name="spacing">
@ -2130,19 +2148,23 @@
</layout> </layout>
</item> </item>
<item> <item>
<widget class="QLabel" name="octreeTitleLabel"> <spacer name="verticalSpacer_7">
<property name="sizePolicy"> <property name="orientation">
<sizepolicy hsizetype="Preferred" vsizetype="Minimum"> <enum>Qt::Vertical</enum>
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property> </property>
<property name="minimumSize"> <property name="sizeType">
<enum>QSizePolicy::Fixed</enum>
</property>
<property name="sizeHint" stdset="0">
<size> <size>
<width>0</width> <width>20</width>
<height>40</height> <height>20</height>
</size> </size>
</property> </property>
</spacer>
</item>
<item>
<widget class="QLabel" name="octreeTitleLabel">
<property name="font"> <property name="font">
<font> <font>
<family>Arial</family> <family>Arial</family>
@ -2239,19 +2261,23 @@
</layout> </layout>
</item> </item>
<item> <item>
<widget class="QLabel" name="oculusRiftTitleLabel"> <spacer name="verticalSpacer">
<property name="sizePolicy"> <property name="orientation">
<sizepolicy hsizetype="Preferred" vsizetype="Minimum"> <enum>Qt::Vertical</enum>
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property> </property>
<property name="minimumSize"> <property name="sizeType">
<enum>QSizePolicy::Fixed</enum>
</property>
<property name="sizeHint" stdset="0">
<size> <size>
<width>0</width> <width>20</width>
<height>40</height> <height>20</height>
</size> </size>
</property> </property>
</spacer>
</item>
<item>
<widget class="QLabel" name="oculusRiftTitleLabel">
<property name="font"> <property name="font">
<font> <font>
<family>Arial</family> <family>Arial</family>
@ -2348,19 +2374,23 @@
</layout> </layout>
</item> </item>
<item> <item>
<widget class="QLabel" name="sixenseControllersTitleLabel"> <spacer name="verticalSpacer_6">
<property name="sizePolicy"> <property name="orientation">
<sizepolicy hsizetype="Preferred" vsizetype="Minimum"> <enum>Qt::Vertical</enum>
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property> </property>
<property name="minimumSize"> <property name="sizeType">
<enum>QSizePolicy::Fixed</enum>
</property>
<property name="sizeHint" stdset="0">
<size> <size>
<width>0</width> <width>20</width>
<height>40</height> <height>20</height>
</size> </size>
</property> </property>
</spacer>
</item>
<item>
<widget class="QLabel" name="sixenseControllersTitleLabel">
<property name="font"> <property name="font">
<font> <font>
<family>Arial</family> <family>Arial</family>
@ -2381,13 +2411,15 @@
</widget> </widget>
</item> </item>
<item> <item>
<widget class="QCheckBox" name="invertSixenseButtonsCheckBox"> <layout class="QHBoxLayout" name="horizontalLayout_26">
<property name="minimumSize"> <property name="topMargin">
<size> <number>7</number>
<width>0</width>
<height>35</height>
</size>
</property> </property>
<property name="bottomMargin">
<number>7</number>
</property>
<item>
<widget class="QCheckBox" name="invertSixenseButtonsCheckBox">
<property name="baseSize"> <property name="baseSize">
<size> <size>
<width>0</width> <width>0</width>
@ -2410,6 +2442,8 @@
</property> </property>
</widget> </widget>
</item> </item>
</layout>
</item>
<item> <item>
<layout class="QHBoxLayout" name="horizontalLayout_16"> <layout class="QHBoxLayout" name="horizontalLayout_16">
<property name="spacing"> <property name="spacing">
@ -2486,30 +2520,17 @@
</layout> </layout>
</widget> </widget>
</widget> </widget>
</item>
<item>
<widget class="QFrame" name="buttonsPanel"> <widget class="QFrame" name="buttonsPanel">
<property name="geometry">
<rect>
<x>0</x>
<y>490</y>
<width>501</width>
<height>50</height>
</rect>
</property>
<property name="frameShape"> <property name="frameShape">
<enum>QFrame::NoFrame</enum> <enum>QFrame::NoFrame</enum>
</property> </property>
<property name="frameShadow"> <property name="frameShadow">
<enum>QFrame::Raised</enum> <enum>QFrame::Raised</enum>
</property> </property>
<widget class="QWidget" name="horizontalLayoutWidget"> <layout class="QHBoxLayout" name="horizontalLayout_12">
<property name="geometry"> <item>
<rect>
<x>0</x>
<y>0</y>
<width>491</width>
<height>41</height>
</rect>
</property>
<layout class="QHBoxLayout" name="buttonsHBox_2"> <layout class="QHBoxLayout" name="buttonsHBox_2">
<item> <item>
<spacer name="horizontalSpacer_14"> <spacer name="horizontalSpacer_14">
@ -2558,8 +2579,11 @@
</widget> </widget>
</item> </item>
</layout> </layout>
</item>
</layout>
</widget> </widget>
</widget> </item>
</layout>
</widget> </widget>
<resources/> <resources/>
<connections> <connections>

View file

@ -10,6 +10,12 @@
<height>728</height> <height>728</height>
</rect> </rect>
</property> </property>
<property name="font">
<font>
<family>Helvetica,Arial,sans-serif</family>
<pointsize>13</pointsize>
</font>
</property>
<property name="windowTitle"> <property name="windowTitle">
<string>Running Scripts</string> <string>Running Scripts</string>
</property> </property>
@ -31,6 +37,12 @@
<height>141</height> <height>141</height>
</size> </size>
</property> </property>
<property name="font">
<font>
<family>Helvetica,Arial,sans-serif</family>
<pointsize>13</pointsize>
</font>
</property>
<layout class="QVBoxLayout" name="verticalLayout_4"> <layout class="QVBoxLayout" name="verticalLayout_4">
<property name="spacing"> <property name="spacing">
<number>0</number> <number>0</number>
@ -113,6 +125,12 @@ font: bold 16pt;
<verstretch>0</verstretch> <verstretch>0</verstretch>
</sizepolicy> </sizepolicy>
</property> </property>
<property name="font">
<font>
<family>Helvetica,Arial,sans-serif</family>
<pointsize>13</pointsize>
</font>
</property>
<property name="styleSheet"> <property name="styleSheet">
<string notr="true">reloadStopButtonArea { padding: 0 }</string> <string notr="true">reloadStopButtonArea { padding: 0 }</string>
</property> </property>
@ -131,6 +149,12 @@ font: bold 16pt;
</property> </property>
<item> <item>
<widget class="QPushButton" name="reloadAllButton"> <widget class="QPushButton" name="reloadAllButton">
<property name="font">
<font>
<family>Helvetica,Arial,sans-serif</family>
<pointsize>13</pointsize>
</font>
</property>
<property name="text"> <property name="text">
<string>Reload all</string> <string>Reload all</string>
</property> </property>
@ -138,6 +162,12 @@ font: bold 16pt;
</item> </item>
<item> <item>
<widget class="QPushButton" name="stopAllButton"> <widget class="QPushButton" name="stopAllButton">
<property name="font">
<font>
<family>Helvetica,Arial,sans-serif</family>
<pointsize>13</pointsize>
</font>
</property>
<property name="text"> <property name="text">
<string>Stop all</string> <string>Stop all</string>
</property> </property>
@ -167,6 +197,12 @@ font: bold 16pt;
<verstretch>0</verstretch> <verstretch>0</verstretch>
</sizepolicy> </sizepolicy>
</property> </property>
<property name="font">
<font>
<family>Helvetica,Arial,sans-serif</family>
<pointsize>13</pointsize>
</font>
</property>
<layout class="QVBoxLayout" name="verticalLayout_8"> <layout class="QVBoxLayout" name="verticalLayout_8">
<property name="spacing"> <property name="spacing">
<number>0</number> <number>0</number>
@ -191,8 +227,14 @@ font: bold 16pt;
<verstretch>0</verstretch> <verstretch>0</verstretch>
</sizepolicy> </sizepolicy>
</property> </property>
<property name="font">
<font>
<family>Helvetica,Arial,sans-serif</family>
<pointsize>14</pointsize>
</font>
</property>
<property name="styleSheet"> <property name="styleSheet">
<string notr="true">font: 14pt; color: #5f5f5f; margin: 2px;</string> <string notr="true">color: #5f5f5f; margin: 2px;</string>
</property> </property>
<property name="text"> <property name="text">
<string>There are no scripts running.</string> <string>There are no scripts running.</string>
@ -255,12 +297,15 @@ font: bold 16pt;
<verstretch>0</verstretch> <verstretch>0</verstretch>
</sizepolicy> </sizepolicy>
</property> </property>
<property name="font">
<font>
<family>Helvetica,Arial,sans-serif</family>
<pointsize>14</pointsize>
</font>
</property>
<property name="layoutDirection"> <property name="layoutDirection">
<enum>Qt::LeftToRight</enum> <enum>Qt::LeftToRight</enum>
</property> </property>
<property name="styleSheet">
<string notr="true">font-size: 14pt;</string>
</property>
<layout class="QVBoxLayout" name="verticalLayout_3"> <layout class="QVBoxLayout" name="verticalLayout_3">
<property name="spacing"> <property name="spacing">
<number>0</number> <number>0</number>
@ -279,6 +324,12 @@ font: bold 16pt;
</property> </property>
<item> <item>
<widget class="QWidget" name="scriptListWidget" native="true"> <widget class="QWidget" name="scriptListWidget" native="true">
<property name="font">
<font>
<family>Helvetica,Arial,sans-serif</family>
<pointsize>14</pointsize>
</font>
</property>
<layout class="QVBoxLayout" name="verticalLayout_5"> <layout class="QVBoxLayout" name="verticalLayout_5">
<property name="spacing"> <property name="spacing">
<number>0</number> <number>0</number>
@ -300,8 +351,14 @@ font: bold 16pt;
</item> </item>
<item> <item>
<widget class="QLabel" name="tipLabel"> <widget class="QLabel" name="tipLabel">
<property name="font">
<font>
<family>Helvetica,Arial,sans-serif</family>
<pointsize>14</pointsize>
</font>
</property>
<property name="styleSheet"> <property name="styleSheet">
<string notr="true">font: 14pt; color: #5f5f5f; margin: 2px;</string> <string notr="true">color: #5f5f5f; margin: 2px;</string>
</property> </property>
<property name="text"> <property name="text">
<string>Tip</string> <string>Tip</string>

View file

@ -85,16 +85,9 @@ AudioClient::AudioClient() :
_isStereoInput(false), _isStereoInput(false),
_outputStarveDetectionStartTimeMsec(0), _outputStarveDetectionStartTimeMsec(0),
_outputStarveDetectionCount(0), _outputStarveDetectionCount(0),
_outputBufferSizeFrames("audioOutputBufferSize", _outputBufferSizeFrames("audioOutputBufferSize", DEFAULT_AUDIO_OUTPUT_BUFFER_SIZE_FRAMES),
DEFAULT_MAX_FRAMES_OVER_DESIRED),
#ifdef Q_OS_ANDROID
_outputStarveDetectionEnabled("audioOutputStarveDetectionEnabled",
false),
#else
_outputStarveDetectionEnabled("audioOutputStarveDetectionEnabled", _outputStarveDetectionEnabled("audioOutputStarveDetectionEnabled",
DEFAULT_AUDIO_OUTPUT_STARVE_DETECTION_ENABLED), DEFAULT_AUDIO_OUTPUT_STARVE_DETECTION_ENABLED),
#endif
_outputStarveDetectionPeriodMsec("audioOutputStarveDetectionPeriod", _outputStarveDetectionPeriodMsec("audioOutputStarveDetectionPeriod",
DEFAULT_AUDIO_OUTPUT_STARVE_DETECTION_PERIOD), DEFAULT_AUDIO_OUTPUT_STARVE_DETECTION_PERIOD),
_outputStarveDetectionThreshold("audioOutputStarveDetectionThreshold", _outputStarveDetectionThreshold("audioOutputStarveDetectionThreshold",
@ -1090,19 +1083,23 @@ void AudioClient::outputNotify() {
if (recentUnfulfilled > 0) { if (recentUnfulfilled > 0) {
if (_outputStarveDetectionEnabled.get()) { if (_outputStarveDetectionEnabled.get()) {
quint64 now = usecTimestampNow() / 1000; quint64 now = usecTimestampNow() / 1000;
quint64 dt = now - _outputStarveDetectionStartTimeMsec; int dt = (int)(now - _outputStarveDetectionStartTimeMsec);
if (dt > _outputStarveDetectionPeriodMsec.get()) { if (dt > _outputStarveDetectionPeriodMsec.get()) {
_outputStarveDetectionStartTimeMsec = now; _outputStarveDetectionStartTimeMsec = now;
_outputStarveDetectionCount = 0; _outputStarveDetectionCount = 0;
} else { } else {
_outputStarveDetectionCount += recentUnfulfilled; _outputStarveDetectionCount += recentUnfulfilled;
if (_outputStarveDetectionCount > _outputStarveDetectionThreshold.get()) { if (_outputStarveDetectionCount > _outputStarveDetectionThreshold.get()) {
int newOutputBufferSizeFrames = _outputBufferSizeFrames.get() + 1;
qDebug() << "Starve detection threshold met, increasing buffer size to " << newOutputBufferSizeFrames;
setOutputBufferSize(newOutputBufferSizeFrames);
_outputStarveDetectionStartTimeMsec = now; _outputStarveDetectionStartTimeMsec = now;
_outputStarveDetectionCount = 0; _outputStarveDetectionCount = 0;
int oldOutputBufferSizeFrames = _outputBufferSizeFrames.get();
int newOutputBufferSizeFrames = oldOutputBufferSizeFrames + 1;
setOutputBufferSize(newOutputBufferSizeFrames);
newOutputBufferSizeFrames = _outputBufferSizeFrames.get();
if (newOutputBufferSizeFrames > oldOutputBufferSizeFrames) {
qDebug() << "Starve detection threshold met, increasing buffer size to " << newOutputBufferSizeFrames;
}
} }
} }
} }

View file

@ -57,7 +57,11 @@ static const int NUM_AUDIO_CHANNELS = 2;
static const int DEFAULT_AUDIO_OUTPUT_BUFFER_SIZE_FRAMES = 3; static const int DEFAULT_AUDIO_OUTPUT_BUFFER_SIZE_FRAMES = 3;
static const int MIN_AUDIO_OUTPUT_BUFFER_SIZE_FRAMES = 1; static const int MIN_AUDIO_OUTPUT_BUFFER_SIZE_FRAMES = 1;
static const int MAX_AUDIO_OUTPUT_BUFFER_SIZE_FRAMES = 20; static const int MAX_AUDIO_OUTPUT_BUFFER_SIZE_FRAMES = 20;
static const int DEFAULT_AUDIO_OUTPUT_STARVE_DETECTION_ENABLED = true; #if defined(Q_OS_ANDROID) || defined(Q_OS_WIN)
static const int DEFAULT_AUDIO_OUTPUT_STARVE_DETECTION_ENABLED = false;
#else
static const int DEFAULT_AUDIO_OUTPUT_STARVE_DETECTION_ENABLED = true;
#endif
static const int DEFAULT_AUDIO_OUTPUT_STARVE_DETECTION_THRESHOLD = 3; static const int DEFAULT_AUDIO_OUTPUT_STARVE_DETECTION_THRESHOLD = 3;
static const quint64 DEFAULT_AUDIO_OUTPUT_STARVE_DETECTION_PERIOD = 10 * 1000; // 10 Seconds static const quint64 DEFAULT_AUDIO_OUTPUT_STARVE_DETECTION_PERIOD = 10 * 1000; // 10 Seconds

View file

@ -44,7 +44,7 @@ AvatarData::AvatarData() :
_handState(0), _handState(0),
_keyState(NO_KEY_DOWN), _keyState(NO_KEY_DOWN),
_isChatCirclingEnabled(false), _isChatCirclingEnabled(false),
_forceFaceshiftConnected(false), _forceFaceTrackerConnected(false),
_hasNewJointRotations(true), _hasNewJointRotations(true),
_headData(NULL), _headData(NULL),
_handData(NULL), _handData(NULL),
@ -136,8 +136,8 @@ QByteArray AvatarData::toByteArray() {
if (!_headData) { if (!_headData) {
_headData = new HeadData(this); _headData = new HeadData(this);
} }
if (_forceFaceshiftConnected) { if (_forceFaceTrackerConnected) {
_headData->_isFaceshiftConnected = true; _headData->_isFaceTrackerConnected = true;
} }
QByteArray avatarDataByteArray; QByteArray avatarDataByteArray;
@ -191,7 +191,7 @@ QByteArray AvatarData::toByteArray() {
setAtBit(bitItems, HAND_STATE_FINGER_POINTING_BIT); setAtBit(bitItems, HAND_STATE_FINGER_POINTING_BIT);
} }
// faceshift state // faceshift state
if (_headData->_isFaceshiftConnected) { if (_headData->_isFaceTrackerConnected) {
setAtBit(bitItems, IS_FACESHIFT_CONNECTED); setAtBit(bitItems, IS_FACESHIFT_CONNECTED);
} }
if (_isChatCirclingEnabled) { if (_isChatCirclingEnabled) {
@ -208,7 +208,7 @@ QByteArray AvatarData::toByteArray() {
} }
// If it is connected, pack up the data // If it is connected, pack up the data
if (_headData->_isFaceshiftConnected) { if (_headData->_isFaceTrackerConnected) {
memcpy(destinationBuffer, &_headData->_leftEyeBlink, sizeof(float)); memcpy(destinationBuffer, &_headData->_leftEyeBlink, sizeof(float));
destinationBuffer += sizeof(float); destinationBuffer += sizeof(float);
@ -417,7 +417,7 @@ int AvatarData::parseDataAtOffset(const QByteArray& packet, int offset) {
_handState = getSemiNibbleAt(bitItems, HAND_STATE_START_BIT) _handState = getSemiNibbleAt(bitItems, HAND_STATE_START_BIT)
+ (oneAtBit(bitItems, HAND_STATE_FINGER_POINTING_BIT) ? IS_FINGER_POINTING_FLAG : 0); + (oneAtBit(bitItems, HAND_STATE_FINGER_POINTING_BIT) ? IS_FINGER_POINTING_FLAG : 0);
_headData->_isFaceshiftConnected = oneAtBit(bitItems, IS_FACESHIFT_CONNECTED); _headData->_isFaceTrackerConnected = oneAtBit(bitItems, IS_FACESHIFT_CONNECTED);
_isChatCirclingEnabled = oneAtBit(bitItems, IS_CHAT_CIRCLING_ENABLED); _isChatCirclingEnabled = oneAtBit(bitItems, IS_CHAT_CIRCLING_ENABLED);
bool hasReferential = oneAtBit(bitItems, HAS_REFERENTIAL); bool hasReferential = oneAtBit(bitItems, HAS_REFERENTIAL);
@ -436,7 +436,7 @@ int AvatarData::parseDataAtOffset(const QByteArray& packet, int offset) {
} }
if (_headData->_isFaceshiftConnected) { if (_headData->_isFaceTrackerConnected) {
float leftEyeBlink, rightEyeBlink, averageLoudness, browAudioLift; float leftEyeBlink, rightEyeBlink, averageLoudness, browAudioLift;
minPossibleSize += sizeof(leftEyeBlink) + sizeof(rightEyeBlink) + sizeof(averageLoudness) + sizeof(browAudioLift); minPossibleSize += sizeof(leftEyeBlink) + sizeof(rightEyeBlink) + sizeof(averageLoudness) + sizeof(browAudioLift);
minPossibleSize++; // one byte for blendDataSize minPossibleSize++; // one byte for blendDataSize

View file

@ -241,7 +241,7 @@ public:
Q_INVOKABLE void setBlendshape(QString name, float val) { _headData->setBlendshape(name, val); } Q_INVOKABLE void setBlendshape(QString name, float val) { _headData->setBlendshape(name, val); }
void setForceFaceshiftConnected(bool connected) { _forceFaceshiftConnected = connected; } void setForceFaceTrackerConnected(bool connected) { _forceFaceTrackerConnected = connected; }
// key state // key state
void setKeyState(KeyState s) { _keyState = s; } void setKeyState(KeyState s) { _keyState = s; }
@ -357,7 +357,7 @@ protected:
KeyState _keyState; KeyState _keyState;
bool _isChatCirclingEnabled; bool _isChatCirclingEnabled;
bool _forceFaceshiftConnected; bool _forceFaceTrackerConnected;
bool _hasNewJointRotations; // set in AvatarData, cleared in Avatar bool _hasNewJointRotations; // set in AvatarData, cleared in Avatar
HeadData* _headData; HeadData* _headData;

View file

@ -67,7 +67,7 @@ PalmData::PalmData(HandData* owningHandData) :
_rawRotation(0.0f, 0.0f, 0.0f, 1.0f), _rawRotation(0.0f, 0.0f, 0.0f, 1.0f),
_rawPosition(0.0f), _rawPosition(0.0f),
_rawVelocity(0.0f), _rawVelocity(0.0f),
_rotationalVelocity(0.0f), _rawAngularVelocity(0.0f),
_totalPenetration(0.0f), _totalPenetration(0.0f),
_controllerButtons(0), _controllerButtons(0),
_isActive(false), _isActive(false),

View file

@ -98,6 +98,8 @@ public:
void setRawPosition(const glm::vec3& pos) { _rawPosition = pos; } void setRawPosition(const glm::vec3& pos) { _rawPosition = pos; }
void setRawVelocity(const glm::vec3& velocity) { _rawVelocity = velocity; } void setRawVelocity(const glm::vec3& velocity) { _rawVelocity = velocity; }
const glm::vec3& getRawVelocity() const { return _rawVelocity; } const glm::vec3& getRawVelocity() const { return _rawVelocity; }
void setRawAngularVelocity(const glm::vec3& angularVelocity) { _rawAngularVelocity = angularVelocity; }
const glm::vec3& getRawAngularVelocity() const { return _rawAngularVelocity; }
void addToPosition(const glm::vec3& delta); void addToPosition(const glm::vec3& delta);
void addToPenetration(const glm::vec3& penetration) { _totalPenetration += penetration; } void addToPenetration(const glm::vec3& penetration) { _totalPenetration += penetration; }
@ -148,7 +150,7 @@ private:
glm::quat _rawRotation; glm::quat _rawRotation;
glm::vec3 _rawPosition; glm::vec3 _rawPosition;
glm::vec3 _rawVelocity; glm::vec3 _rawVelocity;
glm::vec3 _rotationalVelocity; glm::vec3 _rawAngularVelocity;
glm::quat _lastRotation; glm::quat _lastRotation;
glm::vec3 _tipPosition; glm::vec3 _tipPosition;

View file

@ -31,7 +31,7 @@ HeadData::HeadData(AvatarData* owningAvatar) :
_torsoTwist(0.0f), _torsoTwist(0.0f),
_lookAtPosition(0.0f, 0.0f, 0.0f), _lookAtPosition(0.0f, 0.0f, 0.0f),
_audioLoudness(0.0f), _audioLoudness(0.0f),
_isFaceshiftConnected(false), _isFaceTrackerConnected(false),
_leftEyeBlink(0.0f), _leftEyeBlink(0.0f),
_rightEyeBlink(0.0f), _rightEyeBlink(0.0f),
_averageLoudness(0.0f), _averageLoudness(0.0f),

View file

@ -92,7 +92,7 @@ protected:
glm::vec3 _lookAtPosition; glm::vec3 _lookAtPosition;
float _audioLoudness; float _audioLoudness;
bool _isFaceshiftConnected; bool _isFaceTrackerConnected;
float _leftEyeBlink; float _leftEyeBlink;
float _rightEyeBlink; float _rightEyeBlink;
float _averageLoudness; float _averageLoudness;

View file

@ -110,7 +110,7 @@ void Player::startPlaying() {
} }
// Fake faceshift connection // Fake faceshift connection
_avatar->setForceFaceshiftConnected(true); _avatar->setForceFaceTrackerConnected(true);
qDebug() << "Recorder::startPlaying()"; qDebug() << "Recorder::startPlaying()";
setupAudioThread(); setupAudioThread();
@ -136,8 +136,8 @@ void Player::stopPlaying() {
cleanupAudioThread(); cleanupAudioThread();
_avatar->clearJointsData(); _avatar->clearJointsData();
// Turn off fake faceshift connection // Turn off fake face tracker connection
_avatar->setForceFaceshiftConnected(false); _avatar->setForceFaceTrackerConnected(false);
if (_useAttachments) { if (_useAttachments) {
_avatar->setAttachmentData(_currentContext.attachments); _avatar->setAttachmentData(_currentContext.attachments);
@ -255,8 +255,8 @@ void Player::play() {
HeadData* head = const_cast<HeadData*>(_avatar->getHeadData()); HeadData* head = const_cast<HeadData*>(_avatar->getHeadData());
if (head) { if (head) {
// Make sure fake faceshift connection doesn't get turned off // Make sure fake face tracker connection doesn't get turned off
_avatar->setForceFaceshiftConnected(true); _avatar->setForceFaceTrackerConnected(true);
QVector<float> blendCoef(currentFrame.getBlendshapeCoefficients().size()); QVector<float> blendCoef(currentFrame.getBlendshapeCoefficients().size());
for (int i = 0; i < currentFrame.getBlendshapeCoefficients().size(); ++i) { for (int i = 0; i < currentFrame.getBlendshapeCoefficients().size(); ++i) {

View file

@ -10,6 +10,7 @@
// //
#include <QDebug> #include <QDebug>
#include <QHash>
#include <QObject> #include <QObject>
#include <QtCore/QJsonDocument> #include <QtCore/QJsonDocument>
@ -170,6 +171,31 @@ void EntityItemProperties::setLastEdited(quint64 usecTime) {
_lastEdited = usecTime > _created ? usecTime : _created; _lastEdited = usecTime > _created ? usecTime : _created;
} }
const char* shapeTypeNames[] = {"none", "box", "sphere"};
QHash<QString, ShapeType> stringToShapeTypeLookup;
void buildStringToShapeTypeLookup() {
stringToShapeTypeLookup["none"] = SHAPE_TYPE_NONE;
stringToShapeTypeLookup["box"] = SHAPE_TYPE_BOX;
stringToShapeTypeLookup["sphere"] = SHAPE_TYPE_SPHERE;
}
QString EntityItemProperties::getShapeTypeAsString() const {
return QString(shapeTypeNames[_shapeType]);
}
void EntityItemProperties::setShapeTypeFromString(const QString& shapeName) {
if (stringToShapeTypeLookup.empty()) {
buildStringToShapeTypeLookup();
}
auto shapeTypeItr = stringToShapeTypeLookup.find(shapeName.toLower());
if (shapeTypeItr != stringToShapeTypeLookup.end()) {
_shapeType = shapeTypeItr.value();
_shapeTypeChanged = true;
}
}
EntityPropertyFlags EntityItemProperties::getChangedProperties() const { EntityPropertyFlags EntityItemProperties::getChangedProperties() const {
EntityPropertyFlags changedProperties; EntityPropertyFlags changedProperties;
@ -270,7 +296,7 @@ QScriptValue EntityItemProperties::copyToScriptValue(QScriptEngine* engine) cons
COPY_PROPERTY_TO_QSCRIPTVALUE(lineHeight); COPY_PROPERTY_TO_QSCRIPTVALUE(lineHeight);
COPY_PROPERTY_TO_QSCRIPTVALUE_COLOR_GETTER(textColor, getTextColor()); COPY_PROPERTY_TO_QSCRIPTVALUE_COLOR_GETTER(textColor, getTextColor());
COPY_PROPERTY_TO_QSCRIPTVALUE_COLOR_GETTER(backgroundColor, getBackgroundColor()); COPY_PROPERTY_TO_QSCRIPTVALUE_COLOR_GETTER(backgroundColor, getBackgroundColor());
COPY_PROPERTY_TO_QSCRIPTVALUE(shapeType); COPY_PROPERTY_TO_QSCRIPTVALUE_GETTER(shapeType, getShapeTypeAsString());
// Sitting properties support // Sitting properties support
QScriptValue sittingPoints = engine->newObject(); QScriptValue sittingPoints = engine->newObject();
@ -303,8 +329,6 @@ QScriptValue EntityItemProperties::copyToScriptValue(QScriptEngine* engine) cons
} }
void EntityItemProperties::copyFromScriptValue(const QScriptValue& object) { void EntityItemProperties::copyFromScriptValue(const QScriptValue& object) {
QScriptValue typeScriptValue = object.property("type"); QScriptValue typeScriptValue = object.property("type");
if (typeScriptValue.isValid()) { if (typeScriptValue.isValid()) {
setType(typeScriptValue.toVariant().toString()); setType(typeScriptValue.toVariant().toString());
@ -350,7 +374,7 @@ void EntityItemProperties::copyFromScriptValue(const QScriptValue& object) {
COPY_PROPERTY_FROM_QSCRIPTVALUE_FLOAT(lineHeight, setLineHeight); COPY_PROPERTY_FROM_QSCRIPTVALUE_FLOAT(lineHeight, setLineHeight);
COPY_PROPERTY_FROM_QSCRIPTVALUE_COLOR(textColor, setTextColor); COPY_PROPERTY_FROM_QSCRIPTVALUE_COLOR(textColor, setTextColor);
COPY_PROPERTY_FROM_QSCRIPTVALUE_COLOR(backgroundColor, setBackgroundColor); COPY_PROPERTY_FROM_QSCRIPTVALUE_COLOR(backgroundColor, setBackgroundColor);
COPY_PROPERTY_FROM_QSCRIPTVALUE_ENUM(shapeType, setShapeType, ShapeType); COPY_PROPERTY_FROM_QSCRITPTVALUE_ENUM(shapeType, ShapeType);
_lastEdited = usecTimestampNow(); _lastEdited = usecTimestampNow();
} }

View file

@ -181,7 +181,7 @@ public:
DEFINE_PROPERTY(PROP_LINE_HEIGHT, LineHeight, lineHeight, float); DEFINE_PROPERTY(PROP_LINE_HEIGHT, LineHeight, lineHeight, float);
DEFINE_PROPERTY_REF(PROP_TEXT_COLOR, TextColor, textColor, xColor); DEFINE_PROPERTY_REF(PROP_TEXT_COLOR, TextColor, textColor, xColor);
DEFINE_PROPERTY_REF(PROP_BACKGROUND_COLOR, BackgroundColor, backgroundColor, xColor); DEFINE_PROPERTY_REF(PROP_BACKGROUND_COLOR, BackgroundColor, backgroundColor, xColor);
DEFINE_PROPERTY_REF(PROP_SHAPE_TYPE, ShapeType, shapeType, ShapeType); DEFINE_PROPERTY_REF_ENUM(PROP_SHAPE_TYPE, ShapeType, shapeType, ShapeType);
public: public:
float getMaxDimension() const { return glm::max(_dimensions.x, _dimensions.y, _dimensions.z); } float getMaxDimension() const { return glm::max(_dimensions.x, _dimensions.y, _dimensions.z); }

View file

@ -180,15 +180,6 @@
#define COPY_PROPERTY_TO_QSCRIPTVALUE(P) \ #define COPY_PROPERTY_TO_QSCRIPTVALUE(P) \
properties.setProperty(#P, _##P); properties.setProperty(#P, _##P);
#define COPY_PROPERTY_FROM_QSCRIPTVALUE_ENUM(P, S, E) \
QScriptValue P = object.property(#P); \
if (P.isValid()) { \
E newValue = (E)(P.toVariant().toInt()); \
if (_defaultSettings || newValue != _##P) { \
S(newValue); \
} \
}
#define COPY_PROPERTY_FROM_QSCRIPTVALUE_FLOAT(P, S) \ #define COPY_PROPERTY_FROM_QSCRIPTVALUE_FLOAT(P, S) \
QScriptValue P = object.property(#P); \ QScriptValue P = object.property(#P); \
if (P.isValid()) { \ if (P.isValid()) { \
@ -281,6 +272,15 @@
} \ } \
} }
#define COPY_PROPERTY_FROM_QSCRITPTVALUE_ENUM(P, S) \
QScriptValue P = object.property(#P); \
if (P.isValid()) { \
QString newValue = P.toVariant().toString(); \
if (_defaultSettings || newValue != get##S##AsString()) { \
set##S##FromString(newValue); \
} \
}
#define CONSTRUCT_PROPERTY(n, V) \ #define CONSTRUCT_PROPERTY(n, V) \
_##n(V), \ _##n(V), \
_##n##Changed(false) _##n##Changed(false)
@ -321,6 +321,17 @@
T _##n; \ T _##n; \
bool _##n##Changed; bool _##n##Changed;
#define DEFINE_PROPERTY_REF_ENUM(P, N, n, T) \
public: \
const T& get##N() const { return _##n; } \
void set##N(const T& value) { _##n = value; _##n##Changed = true; } \
bool n##Changed() const { return _##n##Changed; } \
QString get##N##AsString() const; \
void set##N##FromString(const QString& name); \
private: \
T _##n; \
bool _##n##Changed;
#define DEBUG_PROPERTY_IF_CHANGED(D, P, N, n, x) \ #define DEBUG_PROPERTY_IF_CHANGED(D, P, N, n, x) \
if (P.n##Changed()) { \ if (P.n##Changed()) { \
D << " " << #n << ":" << P.get##N() << x << "\n"; \ D << " " << #n << ":" << P.get##N() << x << "\n"; \

View file

@ -76,7 +76,6 @@ void Light::setSpotAngle(float angle) {
if (angle <= 0.f) { if (angle <= 0.f) {
angle = 0.0f; angle = 0.0f;
} }
float cosAngle = cos(angle);
editSchema()._spot.x = cos(angle); editSchema()._spot.x = cos(angle);
editSchema()._spot.y = sin(angle); editSchema()._spot.y = sin(angle);
editSchema()._spot.z = angle; editSchema()._spot.z = angle;

View file

@ -76,7 +76,7 @@ const QString AddressManager::currentPath(bool withOrientation) const {
pathString += "/" + orientationString; pathString += "/" + orientationString;
} else { } else {
qDebug() << "Cannot add orientation to path without a getter for position." qDebug() << "Cannot add orientation to path without a getter for position."
<< "Call AdressManager::setOrientationGetter to pass a function that will return a glm::quat"; << "Call AddressManager::setOrientationGetter to pass a function that will return a glm::quat";
} }
} }
@ -84,7 +84,7 @@ const QString AddressManager::currentPath(bool withOrientation) const {
return pathString; return pathString;
} else { } else {
qDebug() << "Cannot create address path without a getter for position." qDebug() << "Cannot create address path without a getter for position."
<< "Call AdressManager::setPositionGetter to pass a function that will return a const glm::vec3&"; << "Call AddressManager::setPositionGetter to pass a function that will return a const glm::vec3&";
return QString(); return QString();
} }
} }

View file

@ -669,3 +669,41 @@ void LimitedNodeList::sendHeartbeatToIceServer(const HifiSockAddr& iceServerSock
writeUnverifiedDatagram(iceRequestByteArray, iceServerSockAddr); writeUnverifiedDatagram(iceRequestByteArray, iceServerSockAddr);
} }
void LimitedNodeList::putLocalPortIntoSharedMemory(const QString key, QObject* parent) {
// save our local port to shared memory so that assignment client children know how to talk to this parent
QSharedMemory* sharedPortMem = new QSharedMemory(key, parent);
quint16 localPort = getNodeSocket().localPort();
// attempt to create the shared memory segment
if (sharedPortMem->create(sizeof(localPort)) || sharedPortMem->attach()) {
sharedPortMem->lock();
memcpy(sharedPortMem->data(), &localPort, sizeof(localPort));
sharedPortMem->unlock();
qDebug() << "Wrote local listening port" << localPort << "to shared memory at key" << key;
} else {
qWarning() << "Failed to create and attach to shared memory to share local port with assignment-client children.";
}
}
bool LimitedNodeList::getLocalServerPortFromSharedMemory(const QString key, QSharedMemory*& sharedMem,
quint16& localPort) {
if (!sharedMem) {
sharedMem = new QSharedMemory(key, this);
if (!sharedMem->attach(QSharedMemory::ReadOnly)) {
qWarning() << "Could not attach to shared memory at key" << key;
}
}
if (sharedMem->isAttached()) {
sharedMem->lock();
memcpy(&localPort, sharedMem->data(), sizeof(localPort));
sharedMem->unlock();
return true;
}
return false;
}

View file

@ -26,6 +26,7 @@
#include <qsharedpointer.h> #include <qsharedpointer.h>
#include <QtNetwork/qudpsocket.h> #include <QtNetwork/qudpsocket.h>
#include <QtNetwork/qhostaddress.h> #include <QtNetwork/qhostaddress.h>
#include <QSharedMemory>
#include <tbb/concurrent_unordered_map.h> #include <tbb/concurrent_unordered_map.h>
@ -49,6 +50,11 @@ const char STUN_SERVER_HOSTNAME[] = "stun.highfidelity.io";
const unsigned short STUN_SERVER_PORT = 3478; const unsigned short STUN_SERVER_PORT = 3478;
const QString DOMAIN_SERVER_LOCAL_PORT_SMEM_KEY = "domain-server.local-port"; const QString DOMAIN_SERVER_LOCAL_PORT_SMEM_KEY = "domain-server.local-port";
const QString ASSIGNMENT_CLIENT_MONITOR_LOCAL_PORT_SMEM_KEY = "assignment-client-monitor.local-port";
const char DEFAULT_ASSIGNMENT_CLIENT_MONITOR_HOSTNAME[] = "localhost";
const unsigned short DEFAULT_ASSIGNMENT_CLIENT_MONITOR_PORT = 40104;
const unsigned short DEFAULT_ASSIGNMENT_CLIENT_MONITOR_DTLS_PORT = 40105;
class HifiSockAddr; class HifiSockAddr;
@ -169,6 +175,9 @@ public:
return SharedNodePointer(); return SharedNodePointer();
} }
void putLocalPortIntoSharedMemory(const QString key, QObject* parent);
bool getLocalServerPortFromSharedMemory(const QString key, QSharedMemory*& sharedMem, quint16& localPort);
public slots: public slots:
void reset(); void reset();
void eraseAllNodes(); void eraseAllNodes();

View file

@ -149,7 +149,12 @@ QDataStream& operator>>(QDataStream& in, Node& node) {
} }
QDebug operator<<(QDebug debug, const Node &node) { QDebug operator<<(QDebug debug, const Node &node) {
debug.nospace() << NodeType::getNodeTypeName(node.getType()) << " (" << node.getType() << ")"; debug.nospace() << NodeType::getNodeTypeName(node.getType());
if (node.getType() == NodeType::Unassigned) {
debug.nospace() << " (1)";
} else {
debug.nospace() << " (" << node.getType() << ")";
}
debug << " " << node.getUUID().toString().toLocal8Bit().constData() << " "; debug << " " << node.getUUID().toString().toLocal8Bit().constData() << " ";
debug.nospace() << node.getPublicSocket() << "/" << node.getLocalSocket(); debug.nospace() << node.getPublicSocket() << "/" << node.getLocalSocket();
return debug.nospace(); return debug.nospace();

View file

@ -62,13 +62,17 @@ NodeList::NodeList(char newOwnerType, unsigned short socketListenPort, unsigned
connect(&AccountManager::getInstance(), &AccountManager::logoutComplete , this, &NodeList::reset); connect(&AccountManager::getInstance(), &AccountManager::logoutComplete , this, &NodeList::reset);
} }
qint64 NodeList::sendStatsToDomainServer(const QJsonObject& statsObject) { qint64 NodeList::sendStats(const QJsonObject& statsObject, HifiSockAddr destination) {
QByteArray statsPacket = byteArrayWithPopulatedHeader(PacketTypeNodeJsonStats); QByteArray statsPacket = byteArrayWithPopulatedHeader(PacketTypeNodeJsonStats);
QDataStream statsPacketStream(&statsPacket, QIODevice::Append); QDataStream statsPacketStream(&statsPacket, QIODevice::Append);
statsPacketStream << statsObject.toVariantMap(); statsPacketStream << statsObject.toVariantMap();
return writeUnverifiedDatagram(statsPacket, _domainHandler.getSockAddr()); return writeUnverifiedDatagram(statsPacket, destination);
}
qint64 NodeList::sendStatsToDomainServer(const QJsonObject& statsObject) {
return sendStats(statsObject, _domainHandler.getSockAddr());
} }
void NodeList::timePingReply(const QByteArray& packet, const SharedNodePointer& sendingNode) { void NodeList::timePingReply(const QByteArray& packet, const SharedNodePointer& sendingNode) {

View file

@ -47,6 +47,7 @@ public:
NodeType_t getOwnerType() const { return _ownerType; } NodeType_t getOwnerType() const { return _ownerType; }
void setOwnerType(NodeType_t ownerType) { _ownerType = ownerType; } void setOwnerType(NodeType_t ownerType) { _ownerType = ownerType; }
qint64 sendStats(const QJsonObject& statsObject, HifiSockAddr destination);
qint64 sendStatsToDomainServer(const QJsonObject& statsObject); qint64 sendStatsToDomainServer(const QJsonObject& statsObject);
int getNumNoReplyDomainCheckIns() const { return _numNoReplyDomainCheckIns; } int getNumNoReplyDomainCheckIns() const { return _numNoReplyDomainCheckIns; }

View file

@ -70,6 +70,8 @@ PacketVersion versionForPacketType(PacketType type) {
return 2; return 2;
case PacketTypeOctreeStats: case PacketTypeOctreeStats:
return 1; return 1;
case PacketTypeStopNode:
return 1;
case PacketTypeEntityAddOrEdit: case PacketTypeEntityAddOrEdit:
case PacketTypeEntityData: case PacketTypeEntityData:
return VERSION_MODEL_ENTITIES_SUPPORT_SHAPE_TYPE; return VERSION_MODEL_ENTITIES_SUPPORT_SHAPE_TYPE;
@ -124,6 +126,7 @@ QString nameForPacketType(PacketType type) {
PACKET_TYPE_NAME_LOOKUP(PacketTypeEntityErase); PACKET_TYPE_NAME_LOOKUP(PacketTypeEntityErase);
PACKET_TYPE_NAME_LOOKUP(PacketTypeEntityAddResponse); PACKET_TYPE_NAME_LOOKUP(PacketTypeEntityAddResponse);
PACKET_TYPE_NAME_LOOKUP(PacketTypeOctreeDataNack); PACKET_TYPE_NAME_LOOKUP(PacketTypeOctreeDataNack);
PACKET_TYPE_NAME_LOOKUP(PacketTypeStopNode);
PACKET_TYPE_NAME_LOOKUP(PacketTypeAudioEnvironment); PACKET_TYPE_NAME_LOOKUP(PacketTypeAudioEnvironment);
PACKET_TYPE_NAME_LOOKUP(PacketTypeEntityEditNack); PACKET_TYPE_NAME_LOOKUP(PacketTypeEntityEditNack);
PACKET_TYPE_NAME_LOOKUP(PacketTypeSignedTransactionPayment); PACKET_TYPE_NAME_LOOKUP(PacketTypeSignedTransactionPayment);

View file

@ -67,7 +67,7 @@ enum PacketType {
PacketTypeEntityErase, PacketTypeEntityErase,
PacketTypeEntityAddResponse, PacketTypeEntityAddResponse,
PacketTypeOctreeDataNack, // 45 PacketTypeOctreeDataNack, // 45
UNUSED_10, PacketTypeStopNode,
PacketTypeAudioEnvironment, PacketTypeAudioEnvironment,
PacketTypeEntityEditNack, PacketTypeEntityEditNack,
PacketTypeSignedTransactionPayment, PacketTypeSignedTransactionPayment,
@ -86,7 +86,7 @@ const QSet<PacketType> NON_VERIFIED_PACKETS = QSet<PacketType>()
<< PacketTypeNodeJsonStats << PacketTypeEntityQuery << PacketTypeNodeJsonStats << PacketTypeEntityQuery
<< PacketTypeOctreeDataNack << PacketTypeEntityEditNack << PacketTypeOctreeDataNack << PacketTypeEntityEditNack
<< PacketTypeIceServerHeartbeat << PacketTypeIceServerHeartbeatResponse << PacketTypeIceServerHeartbeat << PacketTypeIceServerHeartbeatResponse
<< PacketTypeUnverifiedPing << PacketTypeUnverifiedPingReply; << PacketTypeUnverifiedPing << PacketTypeUnverifiedPingReply << PacketTypeStopNode;
const int NUM_BYTES_MD5_HASH = 16; const int NUM_BYTES_MD5_HASH = 16;
const int NUM_STATIC_HEADER_BYTES = sizeof(PacketVersion) + NUM_BYTES_RFC4122_UUID; const int NUM_STATIC_HEADER_BYTES = sizeof(PacketVersion) + NUM_BYTES_RFC4122_UUID;