Merge pull request #4602 from ctrlaltdavid/20447

CR for Worklist #20447 - Prepare Interface to include DDE face tracking
This commit is contained in:
Leonardo Murillo 2015-04-15 08:49:31 -06:00
commit 3f0d9b7532
6 changed files with 103 additions and 22 deletions

View file

@ -612,6 +612,10 @@ void Application::cleanupBeforeQuit() {
// destroy the AudioClient so it and its thread have a chance to go down safely
DependencyManager::destroy<AudioClient>();
#ifdef HAVE_DDE
DependencyManager::destroy<DdeFaceTracker>();
#endif
}
Application::~Application() {
@ -1743,8 +1747,10 @@ FaceTracker* Application::getActiveFaceTracker() {
void Application::setActiveFaceTracker() {
#ifdef HAVE_FACESHIFT
DependencyManager::get<Faceshift>()->setTCPEnabled(Menu::getInstance()->isOptionChecked(MenuOption::Faceshift));
#endif
#endif
#ifdef HAVE_DDE
DependencyManager::get<DdeFaceTracker>()->setEnabled(Menu::getInstance()->isOptionChecked(MenuOption::DDEFaceRegression));
#endif
#ifdef HAVE_VISAGE
DependencyManager::get<Visage>()->updateEnabled();
#endif

View file

@ -210,6 +210,8 @@ public:
bool getLastMouseMoveWasSimulated() const { return _lastMouseMoveWasSimulated; }
FaceTracker* getActiveFaceTracker();
void setActiveFaceTracker();
QSystemTrayIcon* getTrayIcon() { return _trayIcon; }
ApplicationOverlay& getApplicationOverlay() { return _applicationOverlay; }
Overlays& getOverlays() { return _overlays; }
@ -390,8 +392,6 @@ public slots:
void notifyPacketVersionMismatch();
void setActiveFaceTracker();
void domainConnectionDenied(const QString& reason);
private slots:

View file

@ -362,28 +362,36 @@ Menu::Menu() {
QAction* noFaceTracker = addCheckableActionToQMenuAndActionHash(faceTrackingMenu, MenuOption::NoFaceTracking,
0, true,
qApp, SLOT(setActiveFaceTracker()));
this, SLOT(setActiveFaceTracker()));
faceTrackerGroup->addAction(noFaceTracker);
#ifdef HAVE_FACESHIFT
QAction* faceshiftFaceTracker = addCheckableActionToQMenuAndActionHash(faceTrackingMenu, MenuOption::Faceshift,
0, false,
qApp, SLOT(setActiveFaceTracker()));
this, SLOT(setActiveFaceTracker()));
faceTrackerGroup->addAction(faceshiftFaceTracker);
#endif
#ifdef HAVE_DDE
QAction* ddeFaceTracker = addCheckableActionToQMenuAndActionHash(faceTrackingMenu, MenuOption::DDEFaceRegression,
0, false,
qApp, SLOT(setActiveFaceTracker()));
this, SLOT(setActiveFaceTracker()));
faceTrackerGroup->addAction(ddeFaceTracker);
#endif
#ifdef HAVE_VISAGE
QAction* visageFaceTracker = addCheckableActionToQMenuAndActionHash(faceTrackingMenu, MenuOption::Visage,
0, false,
qApp, SLOT(setActiveFaceTracker()));
this, SLOT(setActiveFaceTracker()));
faceTrackerGroup->addAction(visageFaceTracker);
#endif
}
#ifdef HAVE_DDE
faceTrackingMenu->addSeparator();
QAction* ddeFaceTrackerReset = addActionToQMenuAndActionHash(faceTrackingMenu, MenuOption::ResetDDETracking,
Qt::CTRL | Qt::Key_Apostrophe,
DependencyManager::get<DdeFaceTracker>().data(), SLOT(resetTracking()));
ddeFaceTrackerReset->setVisible(false);
faceTrackingMenu->addAction(ddeFaceTrackerReset);
#endif
addCheckableActionToQMenuAndActionHash(avatarDebugMenu, MenuOption::RenderSkeletonCollisionShapes);
addCheckableActionToQMenuAndActionHash(avatarDebugMenu, MenuOption::RenderHeadCollisionShapes);
@ -1003,3 +1011,11 @@ void Menu::visibilityChanged(Discoverability::Mode discoverabilityMode) {
qCDebug(interfaceapp) << "ERROR Menu::visibilityChanged() called with unrecognized value.";
}
}
void Menu::setActiveFaceTracker() {
#ifdef HAVE_DDE
bool isUsingDDE = Menu::getInstance()->isOptionChecked(MenuOption::DDEFaceRegression);
Menu::getInstance()->getActionForOption(MenuOption::ResetDDETracking)->setVisible(isUsingDDE);
#endif
qApp->setActiveFaceTracker();
}

View file

@ -68,6 +68,7 @@ public slots:
private slots:
void setVisibility();
void setActiveFaceTracker();
private:
static Menu* _instance;
@ -230,6 +231,7 @@ namespace MenuOption {
const QString RenderAmbientLight8 = "CAMPUS_SUNSET";
const QString RenderAmbientLight9 = "FUNSTON_BEACH_SUNSET";
const QString ResetAvatarSize = "Reset Avatar Size";
const QString ResetDDETracking = "Reset DDE Tracking";
const QString ResetSensors = "Reset Sensors";
const QString RunningScripts = "Running Scripts";
const QString RunTimingTests = "Run Timing Tests";

View file

@ -11,6 +11,7 @@
#include <SharedUtil.h>
#include <QCoreApplication>
#include <QJsonDocument>
#include <QJsonArray>
#include <QJsonObject>
@ -19,10 +20,21 @@
#include "DdeFaceTracker.h"
#include "FaceshiftConstants.h"
#include "InterfaceLogging.h"
#include "Menu.h"
static const QHostAddress DDE_FEATURE_POINT_SERVER_ADDR("127.0.0.1");
static const quint16 DDE_FEATURE_POINT_SERVER_PORT = 5555;
static const QHostAddress DDE_SERVER_ADDR("127.0.0.1");
static const quint16 DDE_SERVER_PORT = 64204;
static const quint16 DDE_CONTROL_PORT = 64205;
#if defined(Q_OS_WIN)
static const QString DDE_PROGRAM_PATH = QCoreApplication::applicationDirPath() + "/dde/dde.exe";
#elif defined(Q_OS_MAC)
static const QString DDE_PROGRAM_PATH = QCoreApplication::applicationDirPath() + "/dde.app/Contents/MacOS/dde";
#endif
static const QStringList DDE_ARGUMENTS = QStringList()
<< "--udp=" + DDE_SERVER_ADDR.toString() + ":" + QString::number(DDE_SERVER_PORT)
<< "--receiver=" + QString::number(DDE_CONTROL_PORT)
<< "--headless";
static const int NUM_EXPRESSIONS = 46;
static const int MIN_PACKET_SIZE = (8 + NUM_EXPRESSIONS) * sizeof(float) + sizeof(int);
@ -121,14 +133,16 @@ struct Packet {
};
DdeFaceTracker::DdeFaceTracker() :
DdeFaceTracker(QHostAddress::Any, DDE_FEATURE_POINT_SERVER_PORT)
DdeFaceTracker(QHostAddress::Any, DDE_SERVER_PORT, DDE_CONTROL_PORT)
{
}
DdeFaceTracker::DdeFaceTracker(const QHostAddress& host, quint16 port) :
DdeFaceTracker::DdeFaceTracker(const QHostAddress& host, quint16 serverPort, quint16 controlPort) :
_ddeProcess(NULL),
_host(host),
_port(port),
_serverPort(serverPort),
_controlPort(controlPort),
_lastReceiveTimestamp(0),
_reset(false),
_leftBlinkIndex(0), // see http://support.faceshift.com/support/articles/35129-export-of-blendshapes
@ -157,17 +171,50 @@ DdeFaceTracker::DdeFaceTracker(const QHostAddress& host, quint16 port) :
}
DdeFaceTracker::~DdeFaceTracker() {
if (_udpSocket.isOpen()) {
_udpSocket.close();
}
setEnabled(false);
}
void DdeFaceTracker::setEnabled(bool enabled) {
#ifdef HAVE_DDE
// isOpen() does not work as one might expect on QUdpSocket; don't test isOpen() before closing socket.
_udpSocket.close();
if (enabled) {
_udpSocket.bind(_host, _port);
_udpSocket.bind(_host, _serverPort);
}
if (enabled && !_ddeProcess) {
// Terminate any existing DDE process, perhaps left running after an Interface crash
const char* DDE_EXIT_COMMAND = "exit";
_udpSocket.writeDatagram(DDE_EXIT_COMMAND, DDE_SERVER_ADDR, _controlPort);
qDebug() << "[Info] DDE Face Tracker Starting";
_ddeProcess = new QProcess(qApp);
connect(_ddeProcess, SIGNAL(finished(int, QProcess::ExitStatus)), SLOT(processFinished(int, QProcess::ExitStatus)));
_ddeProcess->start(QCoreApplication::applicationDirPath() + DDE_PROGRAM_PATH, DDE_ARGUMENTS);
}
if (!enabled && _ddeProcess) {
_ddeProcess->kill(); // More robust than trying to send an "exit" command to DDE
_ddeProcess = NULL;
qDebug() << "[Info] DDE Face Tracker Stopped";
}
#endif
}
void DdeFaceTracker::processFinished(int exitCode, QProcess::ExitStatus exitStatus) {
if (_ddeProcess) {
// DDE crashed or was manually terminated
qDebug() << "[Info] DDE Face Tracker Stopped Unexpectedly";
_udpSocket.close();
_ddeProcess = NULL;
Menu::getInstance()->setIsOptionChecked(MenuOption::NoFaceTracking, true);
}
}
void DdeFaceTracker::resetTracking() {
qDebug() << "[Info] Reset DDE Tracking";
const char* DDE_RESET_COMMAND = "reset";
_udpSocket.writeDatagram(DDE_RESET_COMMAND, DDE_SERVER_ADDR, _controlPort);
}
bool DdeFaceTracker::isActive() const {
@ -239,7 +286,7 @@ void DdeFaceTracker::decodePacket(const QByteArray& buffer) {
}
// Compute relative translation
float LEAN_DAMPING_FACTOR = 200.0f;
float LEAN_DAMPING_FACTOR = 75.0f;
translation -= _referenceTranslation;
translation /= LEAN_DAMPING_FACTOR;
translation.x *= -1;

View file

@ -12,6 +12,11 @@
#ifndef hifi_DdeFaceTracker_h
#define hifi_DdeFaceTracker_h
#if defined(Q_OS_WIN) || defined(Q_OS_OSX)
#define HAVE_DDE
#endif
#include <QProcess>
#include <QUdpSocket>
#include <DependencyManager.h>
@ -45,9 +50,11 @@ public:
public slots:
void setEnabled(bool enabled);
void resetTracking();
private slots:
void processFinished(int exitCode, QProcess::ExitStatus exitStatus);
//sockets
void socketErrorOccurred(QAbstractSocket::SocketError socketError);
void readPendingDatagrams();
@ -55,11 +62,14 @@ private slots:
private:
DdeFaceTracker();
DdeFaceTracker(const QHostAddress& host, quint16 port);
DdeFaceTracker(const QHostAddress& host, quint16 serverPort, quint16 controlPort);
~DdeFaceTracker();
QProcess* _ddeProcess;
QHostAddress _host;
quint16 _port;
quint16 _serverPort;
quint16 _controlPort;
float getBlendshapeCoefficient(int index) const;
void decodePacket(const QByteArray& buffer);